diff --git a/src/components/providers/utils.ts b/src/components/providers/utils.ts index f45f41e..5221472 100644 --- a/src/components/providers/utils.ts +++ b/src/components/providers/utils.ts @@ -63,6 +63,21 @@ export const buildOpenAIChatCompletionsEndpoint = (baseUrl: string): string => { return `${trimmed}/chat/completions`; }; +export const buildCodexResponsesEndpoint = (baseUrl: string): string => { + const trimmed = normalizeUpstreamBaseUrl(baseUrl); + if (!trimmed) return ''; + if (/\/v1\/responses$/i.test(trimmed)) { + return trimmed; + } + if (/\/v1\/models$/i.test(trimmed)) { + return trimmed.replace(/\/models$/i, '/responses'); + } + if (/\/v1$/i.test(trimmed)) { + return `${trimmed}/responses`; + } + return `${trimmed}/v1/responses`; +}; + export const buildClaudeMessagesEndpoint = (baseUrl: string): string => { const trimmed = normalizeUpstreamBaseUrl(baseUrl, 'https://api.anthropic.com'); if (!trimmed) return ''; diff --git a/src/features/providers/descriptors.ts b/src/features/providers/descriptors.ts index 29cfab5..505e6bb 100644 --- a/src/features/providers/descriptors.ts +++ b/src/features/providers/descriptors.ts @@ -54,7 +54,7 @@ export const PROVIDER_DESCRIPTORS: Record = { supportsHeaders: true, supportsExcludedModels: true, supportsPriority: true, - supportsTestModel: false, + supportsTestModel: true, supportsWebsockets: true, supportsCloak: false, supportsApiKeyEntries: false, diff --git a/src/features/providers/sheets/forms/BaseProviderForm.tsx b/src/features/providers/sheets/forms/BaseProviderForm.tsx index 5b3cecc..a5979a3 100644 --- a/src/features/providers/sheets/forms/BaseProviderForm.tsx +++ b/src/features/providers/sheets/forms/BaseProviderForm.tsx @@ -86,7 +86,10 @@ function buildInitialForm( : undefined, experimentalCchSigning: brand === 'claude' ? false : undefined, testModel: - brand === 'openaiCompatibility' || brand === 'claude' || brand === 'gemini' + brand === 'openaiCompatibility' || + brand === 'codex' || + brand === 'claude' || + brand === 'gemini' ? '' : undefined, apiKeyEntries: brand === 'openaiCompatibility' ? [emptyApiKeyEntry()] : undefined, @@ -173,7 +176,7 @@ function buildInitialForm( brand === 'claude' ? (cfg as ProviderKeyConfig).experimentalCchSigning === true : undefined, - testModel: brand === 'claude' || brand === 'gemini' ? '' : undefined, + testModel: brand === 'codex' || brand === 'claude' || brand === 'gemini' ? '' : undefined, }; } @@ -448,7 +451,9 @@ export function BaseProviderForm({ brand === 'openaiCompatibility'; const supportsOpenAIModelOptions = brand === 'openaiCompatibility'; const singleConnectivity = - brand === 'gemini' + brand === 'codex' + ? { status: connectivity.codexStatus, run: connectivity.runCodex } + : brand === 'gemini' ? { status: connectivity.geminiStatus, run: connectivity.runGemini } : brand === 'claude' ? { status: connectivity.claudeStatus, run: connectivity.runClaude } @@ -630,7 +635,7 @@ export function BaseProviderForm({