import { ref } from 'vue' import { useAppStore } from '@/stores/app' import { adminAPI } from '@/api/admin' export interface OpenAITokenInfo { access_token?: string refresh_token?: string id_token?: string token_type?: string expires_in?: number expires_at?: number scope?: string email?: string name?: string // OpenAI specific IDs (extracted from ID Token) chatgpt_account_id?: string chatgpt_user_id?: string organization_id?: string [key: string]: unknown } export function useOpenAIOAuth() { const appStore = useAppStore() // State const authUrl = ref('') const sessionId = ref('') const loading = ref(false) const error = ref('') // Reset state const resetState = () => { authUrl.value = '' sessionId.value = '' loading.value = false error.value = '' } // Generate auth URL for OpenAI OAuth const generateAuthUrl = async ( proxyId?: number | null, redirectUri?: string ): Promise => { loading.value = true authUrl.value = '' sessionId.value = '' error.value = '' try { const payload: Record = {} if (proxyId) { payload.proxy_id = proxyId } if (redirectUri) { payload.redirect_uri = redirectUri } const response = await adminAPI.accounts.generateAuthUrl( '/admin/openai/generate-auth-url', payload ) authUrl.value = response.auth_url sessionId.value = response.session_id return true } catch (err: any) { error.value = err.response?.data?.detail || 'Failed to generate OpenAI auth URL' appStore.showError(error.value) return false } finally { loading.value = false } } // Exchange auth code for tokens const exchangeAuthCode = async ( code: string, currentSessionId: string, proxyId?: number | null ): Promise => { if (!code.trim() || !currentSessionId) { error.value = 'Missing auth code or session ID' return null } loading.value = true error.value = '' try { const payload: { session_id: string; code: string; proxy_id?: number } = { session_id: currentSessionId, code: code.trim() } if (proxyId) { payload.proxy_id = proxyId } const tokenInfo = await adminAPI.accounts.exchangeCode('/admin/openai/exchange-code', payload) return tokenInfo as OpenAITokenInfo } catch (err: any) { error.value = err.response?.data?.detail || 'Failed to exchange OpenAI auth code' appStore.showError(error.value) return null } finally { loading.value = false } } // Build credentials for OpenAI OAuth account const buildCredentials = (tokenInfo: OpenAITokenInfo): Record => { const creds: Record = { access_token: tokenInfo.access_token, refresh_token: tokenInfo.refresh_token, token_type: tokenInfo.token_type, expires_in: tokenInfo.expires_in, expires_at: tokenInfo.expires_at, scope: tokenInfo.scope } // Include OpenAI specific IDs (required for forwarding) if (tokenInfo.chatgpt_account_id) { creds.chatgpt_account_id = tokenInfo.chatgpt_account_id } if (tokenInfo.chatgpt_user_id) { creds.chatgpt_user_id = tokenInfo.chatgpt_user_id } if (tokenInfo.organization_id) { creds.organization_id = tokenInfo.organization_id } return creds } // Build extra info from token response const buildExtraInfo = (tokenInfo: OpenAITokenInfo): Record | undefined => { const extra: Record = {} if (tokenInfo.email) { extra.email = tokenInfo.email } if (tokenInfo.name) { extra.name = tokenInfo.name } return Object.keys(extra).length > 0 ? extra : undefined } return { // State authUrl, sessionId, loading, error, // Methods resetState, generateAuthUrl, exchangeAuthCode, buildCredentials, buildExtraInfo } }