import { useEffect, useMemo, useRef, useState } from 'react'; import { formatCodexCreditsValue, formatCodexRemainingPercent, formatCodexResetWindowLabel, formatCodexUsagePercent, formatCodexUsageWindowLabel, formatCodexWindowDurationLong, mergeCodexProviderStatusWithSnapshot, normalizeCodexResetTimestamp, useCodexAccountSnapshot, } from '@features/codex-account/renderer'; import { CODEX_FAST_CREDIT_COST_MULTIPLIER, CODEX_FAST_MODEL_ID, CODEX_FAST_SPEED_MULTIPLIER, resolveCodexFastMode, resolveCodexRuntimeSelection, } from '@features/codex-runtime-profile/renderer'; import { useAppTranslation } from '@features/localization/renderer'; import { RuntimeProviderManagementPanel } from '@features/runtime-provider-management/renderer'; import { api } from '@renderer/api'; import { ProviderBrandLogo } from '@renderer/components/common/ProviderBrandLogo'; import { CodexLoginLinkCopyButton, CodexLoginUserCodeBadge, } from '@renderer/components/runtime/CodexLoginLinkCopyButton'; import { Button } from '@renderer/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from '@renderer/components/ui/dialog'; import { Input } from '@renderer/components/ui/input'; import { Label } from '@renderer/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@renderer/components/ui/select'; import { Tabs, TabsList, TabsTrigger } from '@renderer/components/ui/tabs'; import { useStore } from '@renderer/store'; import { AlertTriangle, Download, Key, Link2, Loader2, Save, Trash2 } from 'lucide-react'; import { isCodexProviderRuntimeMissing, shouldOfferCodexRuntimeInstall, } from './codexRuntimeInstallAction'; import { formatProviderAuthMethodLabelForProvider, formatProviderAuthModeLabelForProvider, formatProviderStatusText, getProviderConnectLabel, getProviderCurrentRuntimeSummary, isConnectionManagedRuntimeProvider, } from './providerConnectionUi'; import { getProviderRuntimeBackendSummary, getVisibleProviderRuntimeBackendOptions, ProviderRuntimeBackendSelector, } from './ProviderRuntimeBackendSelector'; import type { CodexRuntimeStatus } from '@features/codex-runtime-installer/contracts'; import type { CliProviderAuthMode, CliProviderId, CliProviderStatus } from '@shared/types'; import type { ApiKeyEntry } from '@shared/types/extensions'; type ApiKeyProviderId = 'anthropic' | 'codex' | 'gemini'; type PendingConnectionAction = 'auto' | 'oauth' | 'chatgpt' | 'api_key' | 'compatible' | null; interface ConnectionMethodCardOption { readonly authMode: CliProviderAuthMode; readonly title: string; readonly description: string; } interface Props { readonly open: boolean; readonly onOpenChange: (open: boolean) => void; readonly providers: CliProviderStatus[]; readonly initialProviderId: CliProviderId; readonly initialRuntimeProviderId?: string | null; readonly initialRuntimeProviderAction?: 'connect' | 'select' | null; readonly projectPath?: string | null; readonly providerStatusLoading?: Partial>; readonly disabled?: boolean; readonly codexRuntimeStatus?: CodexRuntimeStatus | null; readonly codexRuntimeStatusLoading?: boolean; readonly onInstallCodexRuntime?: () => Promise | void; readonly onSelectBackend: (providerId: CliProviderId, backendId: string) => Promise | void; readonly onRefreshProvider?: (providerId: CliProviderId) => Promise | void; readonly onRequestLogin?: (providerId: CliProviderId) => void; } const API_KEY_PROVIDER_CONFIG: Record< ApiKeyProviderId, { envVarName: 'ANTHROPIC_API_KEY' | 'OPENAI_API_KEY' | 'GEMINI_API_KEY'; name: string; title: string; description: string; placeholder: string; } > = { anthropic: { envVarName: 'ANTHROPIC_API_KEY', name: 'Anthropic API Key', title: 'API key', description: 'Use a direct Anthropic API key for API-billed access. Your Anthropic subscription session stays available when you switch back.', placeholder: 'sk-ant-...', }, codex: { envVarName: 'OPENAI_API_KEY', name: 'Codex API Key', title: 'API key', description: 'Use an OpenAI API key as a secondary Codex auth path. If you switch Codex to API key mode, the app will mirror OPENAI_API_KEY into CODEX_API_KEY for native launches.', placeholder: 'sk-proj-...', }, gemini: { envVarName: 'GEMINI_API_KEY', name: 'Gemini API Key', title: 'API access', description: 'Use `GEMINI_API_KEY` for the Gemini API backend. CLI SDK and ADC do not require it.', placeholder: 'AIza...', }, }; const API_KEY_PROVIDER_TRANSLATION_KEYS = { anthropic: { name: 'providerRuntime.apiKey.providers.anthropic.name', title: 'providerRuntime.apiKey.providers.anthropic.title', description: 'providerRuntime.apiKey.providers.anthropic.description', placeholder: 'providerRuntime.apiKey.providers.anthropic.placeholder', }, codex: { name: 'providerRuntime.apiKey.providers.codex.name', title: 'providerRuntime.apiKey.providers.codex.title', description: 'providerRuntime.apiKey.providers.codex.description', placeholder: 'providerRuntime.apiKey.providers.codex.placeholder', }, gemini: { name: 'providerRuntime.apiKey.providers.gemini.name', title: 'providerRuntime.apiKey.providers.gemini.title', description: 'providerRuntime.apiKey.providers.gemini.description', placeholder: 'providerRuntime.apiKey.providers.gemini.placeholder', }, } as const satisfies Record< ApiKeyProviderId, { name: string; title: string; description: string; placeholder: string; } >; const ANTHROPIC_COMPATIBLE_AUTH_TOKEN_ENV_VAR = 'ANTHROPIC_AUTH_TOKEN'; const ANTHROPIC_COMPATIBLE_AUTH_TOKEN_NAME = 'Anthropic-compatible Auth Token'; const FIRST_PARTY_ANTHROPIC_HOSTS = new Set(['api.anthropic.com', 'api-staging.anthropic.com']); function isApiKeyProviderId(providerId: CliProviderId): providerId is ApiKeyProviderId { return providerId === 'anthropic' || providerId === 'codex' || providerId === 'gemini'; } function isCodexRuntimeInstalling( status: CodexRuntimeStatus | null | undefined, loading: boolean ): boolean { return ( loading || status?.state === 'checking' || status?.state === 'downloading' || status?.state === 'installing' ); } function getCodexRuntimeInstallLabel( status: CodexRuntimeStatus | null | undefined, t: ReturnType['t'] ): string { switch (status?.state) { case 'checking': return t('providerRuntime.codex.install.checking'); case 'downloading': return t('providerRuntime.codex.install.downloading'); case 'installing': return t('providerRuntime.codex.install.installing'); case 'failed': return t('providerRuntime.codex.install.retryInstall'); default: return t('providerRuntime.codex.install.installCli'); } } function findPreferredApiKeyEntry(apiKeys: ApiKeyEntry[], envVarName: string): ApiKeyEntry | null { const matches = apiKeys.filter((entry) => entry.envVarName === envVarName); return matches.find((entry) => entry.scope === 'user') ?? null; } function validateAnthropicCompatibleBaseUrl( value: string, t: ReturnType['t'] ): string | null { const trimmed = value.trim(); if (!trimmed) { return t('providerRuntime.compatibleEndpoint.validation.baseUrlRequired'); } try { const url = new URL(trimmed); if (url.protocol !== 'http:' && url.protocol !== 'https:') { return t('providerRuntime.compatibleEndpoint.validation.httpRequired'); } if (url.username || url.password) { return t('providerRuntime.compatibleEndpoint.validation.noCredentials'); } if (FIRST_PARTY_ANTHROPIC_HOSTS.has(url.hostname)) { return t('providerRuntime.compatibleEndpoint.validation.firstPartyAnthropic'); } } catch { return t('providerRuntime.compatibleEndpoint.validation.invalidUrl'); } return null; } function getConnectionDescription( provider: CliProviderStatus, t: ReturnType['t'] ): string { switch (provider.providerId) { case 'anthropic': return t('providerRuntime.connection.descriptions.anthropic'); case 'codex': return t('providerRuntime.connection.descriptions.codex'); case 'gemini': return t('providerRuntime.connection.descriptions.gemini'); case 'opencode': return t('providerRuntime.connection.descriptions.opencode'); } } function getRuntimeDescription( provider: CliProviderStatus, t: ReturnType['t'] ): string { switch (provider.providerId) { case 'anthropic': return t('providerRuntime.runtime.descriptions.anthropic'); case 'codex': return t('providerRuntime.runtime.descriptions.codex'); case 'gemini': return t('providerRuntime.runtime.descriptions.gemini'); case 'opencode': return t('providerRuntime.runtime.descriptions.opencode'); } } function getAuthModeDescription( providerId: CliProviderId, authMode: CliProviderAuthMode, t: ReturnType['t'] ): string { if (providerId === 'anthropic') { switch (authMode) { case 'auto': return t('providerRuntime.authModeDescriptions.anthropic.auto'); case 'oauth': return t('providerRuntime.authModeDescriptions.anthropic.oauth'); case 'api_key': return t('providerRuntime.authModeDescriptions.anthropic.apiKey'); } } if (providerId === 'codex') { switch (authMode) { case 'auto': return t('providerRuntime.authModeDescriptions.codex.auto'); case 'chatgpt': return t('providerRuntime.authModeDescriptions.codex.chatgpt'); case 'api_key': return t('providerRuntime.authModeDescriptions.codex.apiKey'); default: return ''; } } return ''; } function getConnectionAlert( provider: CliProviderStatus, t: ReturnType['t'] ): string | null { const authMode = provider.connection?.configuredAuthMode; const hasAnthropicSubscriptionSession = provider.authMethod === 'oauth_token' || provider.authMethod === 'claude.ai'; if (provider.providerId === 'anthropic' && provider.connection?.compatibleEndpoint?.enabled) { return provider.connection.compatibleEndpoint.tokenConfigured ? null : t('providerRuntime.alerts.authTokenMissing'); } if ( provider.providerId === 'anthropic' && authMode === 'api_key' && !provider.connection?.apiKeyConfigured ) { return t('providerRuntime.alerts.anthropicApiKeyMissing'); } if ( provider.providerId === 'anthropic' && authMode === 'oauth' && !hasAnthropicSubscriptionSession ) { return t('providerRuntime.alerts.anthropicSubscriptionMissing'); } if ( provider.providerId === 'anthropic' && authMode === 'auto' && provider.connection?.apiKeySource === 'stored' ) { return t('providerRuntime.alerts.anthropicStoredKeyAvailable'); } if (provider.providerId === 'codex') { const codex = provider.connection?.codex; if (codex?.login.status === 'starting') { return t('providerRuntime.alerts.chatgptLoginStarting'); } if (codex?.login.status === 'pending') { return t('providerRuntime.alerts.chatgptLoginPending'); } if (codex?.login.status === 'failed' && codex.login.error) { return codex.login.error; } if (provider.connection?.configuredAuthMode === 'api_key') { if (!provider.connection?.apiKeyConfigured) { return t('providerRuntime.alerts.codexApiKeyMissing'); } return null; } if (provider.connection?.configuredAuthMode === 'chatgpt' && !codex?.managedAccount) { const missingChatgptMessage = codex?.localActiveChatgptAccountPresent ? t('providerRuntime.alerts.codexNeedsReconnect') : codex?.localAccountArtifactsPresent ? t('providerRuntime.alerts.codexLocalArtifactsNoSession') : t('providerRuntime.alerts.codexNoChatgptAccount'); return provider.connection.apiKeyConfigured ? t('providerRuntime.alerts.withApiKeyFallback', { message: missingChatgptMessage }) : missingChatgptMessage; } if (!codex?.launchAllowed && codex?.launchIssueMessage) { return codex.launchIssueMessage; } if (codex?.appServerState === 'degraded' && codex.appServerStatusMessage) { return codex.appServerStatusMessage; } if (!provider.connection?.apiKeyConfigured && !codex?.managedAccount) { return t('providerRuntime.alerts.codexNoCredential'); } return null; } if ( provider.providerId === 'gemini' && provider.availableBackends?.some((option) => option.id === 'api' && !option.available) ) { return t('providerRuntime.alerts.geminiApiUnavailable'); } return null; } function getProviderUsageLabel( provider: CliProviderStatus, t: ReturnType['t'] ): string { if (provider.providerId === 'anthropic' && provider.connection?.compatibleEndpoint?.enabled) { return t('providerRuntime.usage.compatibleEndpoint'); } if ( provider.providerId === 'anthropic' && provider.connection?.configuredAuthMode === 'api_key' ) { return provider.connection.apiKeyConfigured ? t('providerRuntime.usage.apiKey') : t('providerRuntime.usage.apiKeyRequired'); } return provider.authenticated ? t('providerRuntime.usage.usingMethod', { method: formatProviderAuthMethodLabelForProvider( provider.providerId, provider.authMethod, t ), }) : formatProviderStatusText(provider, t); } function getCompactOpenCodeProviderDetailMessage(detailMessage?: string | null): string | null { const trimmed = detailMessage?.trim(); if (!trimmed) { return null; } const firstInternalDetailIndex = [' - auth ', ' - behavior ', ' - managed '] .map((marker) => trimmed.indexOf(marker)) .filter((index) => index >= 0) .sort((left, right) => left - right)[0]; const compact = typeof firstInternalDetailIndex === 'number' ? trimmed.slice(0, firstInternalDetailIndex).trim() : trimmed; return compact || null; } function getCodexAccountPanelHint( provider: CliProviderStatus | null, configuredAuthMode: CliProviderAuthMode | undefined, t: ReturnType['t'] ): string | null { if (provider?.providerId !== 'codex') { return null; } const codex = provider.connection?.codex; if (!codex || codex.login.status === 'starting' || codex.login.status === 'pending') { return null; } const hasActiveChatgptSession = codex.effectiveAuthMode === 'chatgpt' && codex.launchAllowed === true; if (hasActiveChatgptSession) { if (!codex.rateLimits) { return t('providerRuntime.codex.account.hints.usageLimitsAfterReport'); } return null; } const usageSentence = codex.localActiveChatgptAccountPresent ? t('providerRuntime.codex.account.hints.reconnectBeforeUsage') : codex.localAccountArtifactsPresent ? t('providerRuntime.codex.account.hints.localArtifactsNoSession') : t('providerRuntime.codex.account.hints.noActiveAccount'); if (configuredAuthMode === 'chatgpt' && provider.connection?.apiKeyConfigured) { return t('providerRuntime.codex.account.hints.detectedApiKeyNeedsApiMode', { message: usageSentence, }); } if (configuredAuthMode === 'auto' && provider.connection?.apiKeyConfigured) { return t('providerRuntime.codex.account.hints.autoUsesApiKeyUntilChatgpt', { message: usageSentence, }); } return usageSentence; } function getCheckingStatusColor(): string { return 'var(--color-text-secondary)'; } function getProviderStatusColor(statusText: string | null, authenticated: boolean): string { if (statusText === 'Checking...') { return getCheckingStatusColor(); } return authenticated ? '#4ade80' : 'var(--color-text-muted)'; } function formatCodexResetDateTime( timestampSeconds: number | null | undefined, t: ReturnType['t'] ): string { const normalized = normalizeCodexResetTimestamp(timestampSeconds); return normalized ? new Date(normalized).toLocaleString() : t('providerRuntime.status.unknown'); } function formatLocalizedCodexUsageWindowLabel( title: 'Primary used' | 'Secondary used' | 'Weekly used', windowDurationMins: number | null | undefined, t: ReturnType['t'] ): string { const titleByKey = { 'Primary used': t('providerRuntime.codex.rateLimits.primaryUsed'), 'Secondary used': t('providerRuntime.codex.rateLimits.secondaryUsed'), 'Weekly used': t('providerRuntime.codex.rateLimits.weeklyUsed'), }; return formatCodexUsageWindowLabel(title, windowDurationMins).replace(title, titleByKey[title]); } function formatLocalizedCodexResetWindowLabel( title: 'Primary reset' | 'Secondary reset' | 'Weekly reset', windowDurationMins: number | null | undefined, t: ReturnType['t'] ): string { const titleByKey = { 'Primary reset': t('providerRuntime.codex.rateLimits.primaryReset'), 'Secondary reset': t('providerRuntime.codex.rateLimits.secondaryReset'), 'Weekly reset': t('providerRuntime.codex.rateLimits.weeklyReset'), }; return formatCodexResetWindowLabel(title, windowDurationMins).replace(title, titleByKey[title]); } function formatLocalizedCodexUsageExplanation( usedPercent: number | null | undefined, windowDurationMins: number | null | undefined, t: ReturnType['t'] ): string { const windowLabel = formatCodexWindowDurationLong(windowDurationMins); const remaining = formatCodexRemainingPercent(usedPercent); if (windowLabel && remaining) { return t('providerRuntime.codex.rateLimits.usageExplanationWithRemaining', { used: formatCodexUsagePercent(usedPercent), remaining, window: windowLabel, }); } if (windowLabel) { return t('providerRuntime.codex.rateLimits.usageExplanationWindowOnly', { window: windowLabel, }); } return t('providerRuntime.codex.rateLimits.usageExplanationGeneric'); } const CodexRateLimitWindowCard = ({ title, usedLabel, usedValue, remainingValue, resetLabel, resetValue, accent, }: Readonly<{ title: string; usedLabel: string; usedValue: string; remainingValue: string; resetLabel: string; resetValue: string; accent: 'primary' | 'secondary'; }>): React.JSX.Element => { const { t } = useAppTranslation('settings'); const accentStyles = accent === 'primary' ? { borderColor: 'rgba(74, 222, 128, 0.24)', backgroundColor: 'rgba(74, 222, 128, 0.05)', badgeColor: '#86efac', badgeBackground: 'rgba(74, 222, 128, 0.14)', } : { borderColor: 'rgba(125, 211, 252, 0.22)', backgroundColor: 'rgba(125, 211, 252, 0.04)', badgeColor: '#bae6fd', badgeBackground: 'rgba(125, 211, 252, 0.14)', }; return (
{title}
{remainingValue}
{usedLabel}
{usedValue}
{t('providerRuntime.codex.rateLimits.remainingLeft', { value: remainingValue })}
{resetLabel}
{resetValue}
); }; function getConnectionMethodCardOptions( provider: CliProviderStatus, t: ReturnType['t'] ): ConnectionMethodCardOption[] | null { switch (provider.providerId) { case 'anthropic': return [ { authMode: 'auto', title: t('providerRuntime.connectionCards.auto.title'), description: t('providerRuntime.connectionCards.anthropic.autoDescription'), }, { authMode: 'oauth', title: t('providerRuntime.connectionCards.anthropic.subscriptionTitle'), description: t('providerRuntime.connectionCards.anthropic.subscriptionDescription'), }, { authMode: 'api_key', title: t('providerRuntime.connectionCards.apiKey.title'), description: t('providerRuntime.connectionCards.anthropic.apiKeyDescription'), }, ]; case 'codex': return [ { authMode: 'auto', title: t('providerRuntime.connectionCards.auto.title'), description: t('providerRuntime.connectionCards.codex.autoDescription'), }, { authMode: 'chatgpt', title: t('providerRuntime.connectionCards.codex.chatgptTitle'), description: t('providerRuntime.connectionCards.codex.chatgptDescription'), }, { authMode: 'api_key', title: t('providerRuntime.connectionCards.apiKey.title'), description: t('providerRuntime.connectionCards.codex.apiKeyDescription'), }, ]; default: return null; } } function getConnectionMethodCardsHint( provider: CliProviderStatus, t: ReturnType['t'] ): string | null { if (provider.providerId === 'codex') { return t('providerRuntime.connectionCards.codex.hint'); } if (provider.providerId === 'anthropic') { return t('providerRuntime.connectionCards.anthropic.hint'); } return null; } const ConnectionMethodCards = ({ options, selectedAuthMode, disabled, connectionSaving, pendingConnectionAction, onSelect, }: Readonly<{ options: ConnectionMethodCardOption[]; selectedAuthMode: CliProviderAuthMode; disabled: boolean; connectionSaving: boolean; pendingConnectionAction: PendingConnectionAction; onSelect: (authMode: CliProviderAuthMode) => void; }>): React.JSX.Element => { const { t } = useAppTranslation('settings'); const gridClassName = options.length === 3 ? 'grid gap-2 md:grid-cols-3' : 'grid gap-2 sm:grid-cols-2'; return (
{options.map((option) => { const selected = selectedAuthMode === option.authMode; return ( ); })}
); }; export const ProviderRuntimeSettingsDialog = ({ open, onOpenChange, providers, initialProviderId, initialRuntimeProviderId = null, initialRuntimeProviderAction = null, projectPath = null, providerStatusLoading = {}, disabled = false, codexRuntimeStatus = null, codexRuntimeStatusLoading = false, onInstallCodexRuntime, onSelectBackend, onRefreshProvider, onRequestLogin, }: Props): React.JSX.Element => { const { t } = useAppTranslation('settings'); const [selectedProviderId, setSelectedProviderId] = useState(initialProviderId); const [activeApiKeyFormProviderId, setActiveApiKeyFormProviderId] = useState(null); const [apiKeyValue, setApiKeyValue] = useState(''); const [apiKeyScope, setApiKeyScope] = useState<'user' | 'project'>('user'); const [apiKeyError, setApiKeyError] = useState(null); const [connectionError, setConnectionError] = useState(null); const [runtimeError, setRuntimeError] = useState(null); const [connectionSaving, setConnectionSaving] = useState(false); const [runtimeSaving, setRuntimeSaving] = useState(false); const [pendingConnectionAction, setPendingConnectionAction] = useState(null); const [compatibleBaseUrl, setCompatibleBaseUrl] = useState(''); const [compatibleTokenValue, setCompatibleTokenValue] = useState(''); const [compatibleEndpointError, setCompatibleEndpointError] = useState(null); const [compatibleEndpointStatus, setCompatibleEndpointStatus] = useState(null); const apiKeyInputRef = useRef(null); const apiKeys = useStore((s) => s.apiKeys); const apiKeysLoading = useStore((s) => s.apiKeysLoading); const apiKeysError = useStore((s) => s.apiKeysError); const apiKeySaving = useStore((s) => s.apiKeySaving); const apiKeyStorageStatus = useStore((s) => s.apiKeyStorageStatus); const fetchApiKeys = useStore((s) => s.fetchApiKeys); const fetchApiKeyStorageStatus = useStore((s) => s.fetchApiKeyStorageStatus); const saveApiKey = useStore((s) => s.saveApiKey); const deleteApiKey = useStore((s) => s.deleteApiKey); const updateConfig = useStore((s) => s.updateConfig); const appConfig = useStore((s) => s.appConfig); const codexAccount = useCodexAccountSnapshot({ enabled: open && selectedProviderId === 'codex', includeRateLimits: true, }); useEffect(() => { if (!open) { return; } setSelectedProviderId(initialProviderId); void fetchApiKeys(); void fetchApiKeyStorageStatus(); }, [fetchApiKeyStorageStatus, fetchApiKeys, initialProviderId, open]); useEffect(() => { if (open) { return; } setActiveApiKeyFormProviderId(null); setApiKeyValue(''); setApiKeyScope('user'); setApiKeyError(null); setConnectionError(null); setRuntimeError(null); setConnectionSaving(false); setRuntimeSaving(false); setPendingConnectionAction(null); setCompatibleBaseUrl(''); setCompatibleTokenValue(''); setCompatibleEndpointError(null); setCompatibleEndpointStatus(null); }, [open]); useEffect(() => { setConnectionError(null); setRuntimeError(null); setCompatibleEndpointError(null); setCompatibleEndpointStatus(null); }, [selectedProviderId]); useEffect(() => { if (selectedProviderId === 'codex' && codexAccount.error) { setConnectionError(codexAccount.error); } }, [codexAccount.error, selectedProviderId]); const statusSelectedProvider = useMemo(() => { return ( providers.find((provider) => provider.providerId === selectedProviderId) ?? providers.find( (provider) => provider.availableBackends && provider.availableBackends.length > 0 ) ?? providers[0] ?? null ); }, [providers, selectedProviderId]); const statusApiKeyConfig = statusSelectedProvider && isApiKeyProviderId(statusSelectedProvider.providerId) ? API_KEY_PROVIDER_CONFIG[statusSelectedProvider.providerId] : null; const selectedApiKey = statusApiKeyConfig ? findPreferredApiKeyEntry(apiKeys, statusApiKeyConfig.envVarName) : null; const anthropicCompatibleConfig = appConfig?.providerConnections?.anthropic .compatibleEndpoint ?? { enabled: false, baseUrl: '', }; const selectedCompatibleToken = findPreferredApiKeyEntry( apiKeys, ANTHROPIC_COMPATIBLE_AUTH_TOKEN_ENV_VAR ); const selectedProvider = useMemo(() => { const mergedStatusProvider = statusSelectedProvider?.providerId === 'codex' ? mergeCodexProviderStatusWithSnapshot(statusSelectedProvider, codexAccount.snapshot) : statusSelectedProvider; if (!mergedStatusProvider?.connection) { return mergedStatusProvider; } const nextConnection = { ...mergedStatusProvider.connection, }; if (mergedStatusProvider.providerId === 'anthropic') { nextConnection.configuredAuthMode = appConfig?.providerConnections?.anthropic.authMode ?? mergedStatusProvider.connection.configuredAuthMode; nextConnection.compatibleEndpoint = { ...(mergedStatusProvider.connection.compatibleEndpoint ?? { enabled: false, baseUrl: '', tokenConfigured: false, tokenSource: null, tokenSourceLabel: null, }), enabled: anthropicCompatibleConfig.enabled, baseUrl: anthropicCompatibleConfig.baseUrl, }; if (selectedCompatibleToken) { nextConnection.compatibleEndpoint.tokenConfigured = true; nextConnection.compatibleEndpoint.tokenSource = 'stored'; nextConnection.compatibleEndpoint.tokenSourceLabel = t( 'providerRuntime.apiKey.storedInApp' ); } } if (mergedStatusProvider.providerId === 'codex') { nextConnection.configuredAuthMode = appConfig?.providerConnections?.codex.preferredAuthMode ?? mergedStatusProvider.connection.configuredAuthMode; } if (statusApiKeyConfig) { if (nextConnection.apiKeySource === 'stored') { nextConnection.apiKeyConfigured = Boolean(selectedApiKey); nextConnection.apiKeySource = selectedApiKey ? 'stored' : null; nextConnection.apiKeySourceLabel = selectedApiKey ? t('providerRuntime.apiKey.storedInApp') : null; } else if (!nextConnection.apiKeyConfigured && selectedApiKey) { nextConnection.apiKeyConfigured = true; nextConnection.apiKeySource = 'stored'; nextConnection.apiKeySourceLabel = t('providerRuntime.apiKey.storedInApp'); } } return { ...mergedStatusProvider, connection: nextConnection, }; }, [ anthropicCompatibleConfig.baseUrl, anthropicCompatibleConfig.enabled, appConfig?.providerConnections?.anthropic.authMode, appConfig?.providerConnections?.codex.preferredAuthMode, codexAccount.snapshot, selectedCompatibleToken, selectedApiKey, statusApiKeyConfig, statusSelectedProvider, t, ]); useEffect(() => { if (!open || selectedProviderId !== 'anthropic') { return; } setCompatibleBaseUrl(anthropicCompatibleConfig.baseUrl); setCompatibleTokenValue(''); setCompatibleEndpointError(null); setCompatibleEndpointStatus(null); }, [anthropicCompatibleConfig.baseUrl, open, selectedProviderId]); const selectedProviderLoading = selectedProvider ? providerStatusLoading[selectedProvider.providerId] === true : false; const runtimeSummary = selectedProvider ? getProviderRuntimeBackendSummary(selectedProvider) : null; const codexConnection = selectedProvider?.providerId === 'codex' ? (selectedProvider.connection?.codex ?? null) : null; const codexHasActiveChatgptSession = codexConnection?.effectiveAuthMode === 'chatgpt' && codexConnection.launchAllowed === true; const codexNeedsReconnect = Boolean(codexConnection?.localActiveChatgptAccountPresent) && !codexHasActiveChatgptSession; const codexLoginPending = codexConnection?.login.status === 'starting' || codexConnection?.login.status === 'pending'; const codexLoginAuthUrl = codexConnection?.login.authUrl ?? null; const codexLoginUserCode = codexConnection?.login.userCode ?? null; const configurableAuthModes = selectedProvider?.connection?.configurableAuthModes ?? []; const configuredAuthMode: CliProviderAuthMode | undefined = selectedProvider?.connection?.configuredAuthMode ?? configurableAuthModes[0] ?? undefined; const connectionMethodCardOptions = selectedProvider ? getConnectionMethodCardOptions(selectedProvider, t) : null; const showConnectionMethodCards = connectionMethodCardOptions !== null && typeof configuredAuthMode !== 'undefined'; const managedRuntimeSummary = selectedProvider ? getProviderCurrentRuntimeSummary(selectedProvider, t) : null; const connectionManagedRuntime = selectedProvider ? isConnectionManagedRuntimeProvider(selectedProvider) : false; const showRuntimeProviderManagement = selectedProvider?.providerId === 'opencode'; const hideConnectionMethodMeta = showConnectionMethodCards; const canConfigureRuntime = !showRuntimeProviderManagement && !connectionManagedRuntime && (selectedProvider ? getVisibleProviderRuntimeBackendOptions(selectedProvider).length > 1 : false); const apiKeyProviderId = selectedProvider && isApiKeyProviderId(selectedProvider.providerId) ? selectedProvider.providerId : null; const apiKeyConfig = apiKeyProviderId ? API_KEY_PROVIDER_CONFIG[apiKeyProviderId] : null; const apiKeyTranslationKeys = apiKeyProviderId ? API_KEY_PROVIDER_TRANSLATION_KEYS[apiKeyProviderId] : null; const apiKeyDisplayConfig = apiKeyTranslationKeys ? { title: t(apiKeyTranslationKeys.title), description: t(apiKeyTranslationKeys.description), name: t(apiKeyTranslationKeys.name), placeholder: t(apiKeyTranslationKeys.placeholder), } : null; const showApiKeyForm = selectedProvider && isApiKeyProviderId(selectedProvider.providerId) && activeApiKeyFormProviderId === selectedProvider.providerId; const showApiKeySection = Boolean( apiKeyConfig && (selectedProvider?.providerId !== 'codex' || !selectedProvider.connection?.supportsOAuth) ); const connectionAlert = selectedProvider ? getConnectionAlert(selectedProvider, t) : null; const connectionLoading = selectedProviderLoading || connectionSaving || Boolean(selectedProvider?.providerId === 'codex' && codexAccount.loading && !codexConnection); const connectionBusy = disabled || connectionLoading; const codexActionBusy = disabled || selectedProviderLoading || connectionSaving || codexAccount.loading; const codexRuntimeInstallBusy = isCodexRuntimeInstalling( codexRuntimeStatus, codexRuntimeStatusLoading ); const showCodexRuntimeInstallAction = selectedProvider?.providerId === 'codex' && typeof onInstallCodexRuntime === 'function' && isCodexProviderRuntimeMissing(selectedProvider) && shouldOfferCodexRuntimeInstall(codexRuntimeStatus); const runtimeBusy = disabled || selectedProviderLoading || runtimeSaving; const anthropicFastModeCapability = selectedProvider?.providerId === 'anthropic' ? (selectedProvider.runtimeCapabilities?.fastMode ?? null) : null; const anthropicFastModeEnabled = appConfig?.providerConnections?.anthropic.fastModeDefault === true; const anthropicFastModeSupported = anthropicFastModeCapability?.supported === true; const anthropicFastModeAvailable = anthropicFastModeCapability?.available === true; const anthropicFastModeDisabledReason = anthropicFastModeCapability?.reason ?? (anthropicFastModeSupported ? t('providerRuntime.fastMode.unavailableForRuntime') : t('providerRuntime.fastMode.notExposed')); const connectionMethodCardsHint = selectedProvider ? getConnectionMethodCardsHint(selectedProvider, t) : null; const codexAccountPanelHint = getCodexAccountPanelHint( selectedProvider ?? null, configuredAuthMode, t ); const codexFastCapability = useMemo(() => { if (selectedProvider?.providerId !== 'codex') { return null; } const fastProbeModel = selectedProvider.modelCatalog?.models.find((model) => model.supportsFastMode === true) ?.launchModel ?? CODEX_FAST_MODEL_ID; const selection = resolveCodexRuntimeSelection({ source: { providerStatus: selectedProvider, accountSnapshot: codexAccount.snapshot, }, selectedModel: fastProbeModel, }); return resolveCodexFastMode({ selection, selectedFastMode: 'on', }); }, [codexAccount.snapshot, selectedProvider]); const codexFastCapabilityHint = selectedProvider?.providerId === 'codex' && codexFastCapability ? codexFastCapability.selectable ? `Fast mode can be enabled per team or schedule for Fast-capable Codex models with your ChatGPT account. It is about ${CODEX_FAST_SPEED_MULTIPLIER}x faster and costs ${CODEX_FAST_CREDIT_COST_MULTIPLIER}x credits.` : (codexFastCapability.disabledReason ?? 'Codex Fast mode is currently unavailable for this account or runtime.') : null; const hasSubscriptionSession = selectedProvider?.providerId === 'anthropic' ? selectedProvider.authMethod === 'oauth_token' || selectedProvider.authMethod === 'claude.ai' : false; const canRequestSubscriptionLogin = selectedProvider?.providerId === 'anthropic' && Boolean(selectedProvider.connection?.supportsOAuth && onRequestLogin) && selectedProvider.connection?.compatibleEndpoint?.enabled !== true && configuredAuthMode !== 'api_key' && selectedProvider.statusMessage !== 'Checking...' && (!selectedProvider?.authenticated || hasSubscriptionSession || configuredAuthMode === 'oauth'); const anthropicCompatibleEndpoint = selectedProvider?.providerId === 'anthropic' ? (selectedProvider.connection?.compatibleEndpoint ?? null) : null; const anthropicCompatibleEndpointEnabled = anthropicCompatibleEndpoint?.enabled === true; const anthropicCompatibleTokenConfigured = Boolean( selectedCompatibleToken || anthropicCompatibleEndpoint?.tokenConfigured ); const anthropicCompatibleTokenStatus = selectedCompatibleToken?.maskedValue ?? anthropicCompatibleEndpoint?.tokenSourceLabel ?? (anthropicCompatibleTokenConfigured ? t('providerRuntime.status.configured') : null); const anthropicCompatibleMissingToken = anthropicCompatibleEndpointEnabled && !anthropicCompatibleTokenConfigured; useEffect(() => { if (!showApiKeyForm) { return; } const frame = window.requestAnimationFrame(() => { apiKeyInputRef.current?.focus({ preventScroll: true }); }); return () => window.cancelAnimationFrame(frame); }, [selectedProvider?.providerId, showApiKeyForm]); let connectionStatusLabel: string | null = null; if (selectedProvider) { if (!hideConnectionMethodMeta) { connectionStatusLabel = getProviderUsageLabel(selectedProvider, t); } } const showSelectedProviderSummary = Boolean(selectedProvider) && !connectionManagedRuntime; const selectedProviderDetailMessage = selectedProvider?.providerId === 'opencode' ? getCompactOpenCodeProviderDetailMessage(selectedProvider.detailMessage) : (selectedProvider?.detailMessage ?? null); const selectedProviderDiagnostics = selectedProvider?.providerId === 'opencode' ? [] : (selectedProvider?.externalRuntimeDiagnostics ?? []); const connectionProgressMessage = useMemo(() => { if (!connectionLoading || !selectedProvider) { return null; } if (connectionSaving) { if (selectedProvider.providerId === 'anthropic') { switch (pendingConnectionAction) { case 'api_key': return t('providerRuntime.progress.switchingApiKey'); case 'oauth': return t('providerRuntime.progress.switchingAnthropicSubscription'); case 'auto': return t('providerRuntime.progress.switchingAuto'); case 'compatible': return t('providerRuntime.progress.savingCompatibleEndpoint'); default: return t('providerRuntime.progress.applyingConnectionChanges'); } } if (selectedProvider.providerId === 'codex') { switch (pendingConnectionAction) { case 'chatgpt': return t('providerRuntime.progress.switchingChatgpt'); case 'api_key': return t('providerRuntime.progress.switchingApiKeyMode'); case 'auto': return t('providerRuntime.progress.switchingAuto'); default: return t('providerRuntime.progress.applyingConnectionChanges'); } } return t('providerRuntime.progress.applyingConnectionChanges'); } return t('providerRuntime.progress.refreshingProviderStatus'); }, [connectionLoading, connectionSaving, pendingConnectionAction, selectedProvider, t]); const handleStartApiKeyEdit = (): void => { if (!selectedProvider || !isApiKeyProviderId(selectedProvider.providerId) || !apiKeyConfig) { return; } setConnectionError(null); setActiveApiKeyFormProviderId(selectedProvider.providerId); setApiKeyScope(selectedApiKey?.scope ?? 'user'); setApiKeyValue(''); setApiKeyError(null); }; const handleCancelApiKeyEdit = (): void => { setActiveApiKeyFormProviderId(null); setApiKeyValue(''); setApiKeyError(null); }; const handleSaveApiKey = async (): Promise => { if (!selectedProvider || !isApiKeyProviderId(selectedProvider.providerId) || !apiKeyConfig) { return; } if (!apiKeyValue.trim()) { setApiKeyError(t('providerRuntime.errors.apiKeyRequired')); return; } setApiKeyError(null); setConnectionError(null); try { await saveApiKey({ id: selectedApiKey?.id, name: apiKeyConfig.name, envVarName: apiKeyConfig.envVarName, value: apiKeyValue.trim(), scope: apiKeyScope, }); } catch (error) { setApiKeyError( error instanceof Error ? error.message : t('providerRuntime.errors.saveApiKey') ); return; } setActiveApiKeyFormProviderId(null); setApiKeyValue(''); try { await onRefreshProvider?.(selectedProvider.providerId); } catch { setConnectionError(t('providerRuntime.errors.apiKeySavedRefreshFailed')); } }; const handleDeleteApiKey = async (): Promise => { if (!selectedProvider || !selectedApiKey) { return; } setApiKeyError(null); setConnectionError(null); try { await deleteApiKey(selectedApiKey.id); } catch (error) { setApiKeyError( error instanceof Error ? error.message : t('providerRuntime.errors.deleteApiKey') ); return; } setActiveApiKeyFormProviderId(null); setApiKeyValue(''); try { await onRefreshProvider?.(selectedProvider.providerId); } catch { setConnectionError(t('providerRuntime.errors.apiKeyDeletedRefreshFailed')); } }; const handleAuthModeChange = async (authMode: string): Promise => { if (selectedProvider?.providerId !== 'anthropic' && selectedProvider?.providerId !== 'codex') { return; } const nextAuthMode = authMode as CliProviderAuthMode; if (nextAuthMode === configuredAuthMode) { return; } setConnectionSaving(true); setPendingConnectionAction(nextAuthMode); setConnectionError(null); let updateSucceeded = false; try { if (selectedProvider.providerId === 'anthropic') { await updateConfig('providerConnections', { anthropic: { authMode: nextAuthMode, }, }); } else if (nextAuthMode !== 'oauth') { await updateConfig('providerConnections', { codex: { preferredAuthMode: nextAuthMode, }, }); await codexAccount.refresh({ includeRateLimits: true, forceRefreshToken: true }); } updateSucceeded = true; } catch (error) { setConnectionError( error instanceof Error ? error.message : t('providerRuntime.errors.updateConnection') ); } finally { if (updateSucceeded) { try { await onRefreshProvider?.(selectedProvider.providerId); } catch { setConnectionError(t('providerRuntime.errors.connectionUpdatedRefreshFailed')); } } setConnectionSaving(false); setPendingConnectionAction(null); } }; const handleSaveAnthropicCompatibleEndpoint = async (): Promise => { if (selectedProvider?.providerId !== 'anthropic') { return; } const baseUrl = compatibleBaseUrl.trim(); const validationError = validateAnthropicCompatibleBaseUrl(baseUrl, t); if (validationError) { setCompatibleEndpointError(validationError); setCompatibleEndpointStatus(null); return; } setConnectionSaving(true); setPendingConnectionAction('compatible'); setConnectionError(null); setCompatibleEndpointError(null); setCompatibleEndpointStatus(null); let updateSucceeded = false; try { if (compatibleTokenValue.trim()) { await saveApiKey({ id: selectedCompatibleToken?.id, name: ANTHROPIC_COMPATIBLE_AUTH_TOKEN_NAME, envVarName: ANTHROPIC_COMPATIBLE_AUTH_TOKEN_ENV_VAR, value: compatibleTokenValue.trim(), scope: 'user', }); } await updateConfig('providerConnections', { anthropic: { compatibleEndpoint: { enabled: true, baseUrl, }, }, }); updateSucceeded = true; setCompatibleTokenValue(''); setCompatibleEndpointStatus( compatibleTokenValue.trim() || anthropicCompatibleTokenConfigured ? t('providerRuntime.compatibleEndpoint.status.endpointSaved') : t('providerRuntime.compatibleEndpoint.status.endpointSavedTokenMissing') ); } catch (error) { setCompatibleEndpointError( error instanceof Error ? error.message : t('providerRuntime.errors.saveEndpoint') ); } finally { if (updateSucceeded) { try { await onRefreshProvider?.('anthropic'); } catch { setConnectionError(t('providerRuntime.errors.endpointSavedRefreshFailed')); } } setConnectionSaving(false); setPendingConnectionAction(null); } }; const handleDisableAnthropicCompatibleEndpoint = async (): Promise => { if (selectedProvider?.providerId !== 'anthropic') { return; } setConnectionSaving(true); setPendingConnectionAction('compatible'); setConnectionError(null); setCompatibleEndpointError(null); setCompatibleEndpointStatus(null); let updateSucceeded = false; try { await updateConfig('providerConnections', { anthropic: { compatibleEndpoint: { enabled: false, baseUrl: compatibleBaseUrl.trim(), }, }, }); updateSucceeded = true; setCompatibleTokenValue(''); setCompatibleEndpointStatus( t('providerRuntime.compatibleEndpoint.status.endpointDisabledTokenKept') ); } catch (error) { setCompatibleEndpointError( error instanceof Error ? error.message : t('providerRuntime.errors.disableEndpoint') ); } finally { if (updateSucceeded) { try { await onRefreshProvider?.('anthropic'); } catch { setConnectionError(t('providerRuntime.errors.endpointDisabledRefreshFailed')); } } setConnectionSaving(false); setPendingConnectionAction(null); } }; const handleCodexAccountRefresh = async (): Promise => { setConnectionError(null); try { await codexAccount.refresh({ includeRateLimits: true, forceRefreshToken: true }); await onRefreshProvider?.('codex'); } catch (error) { setConnectionError( error instanceof Error ? error.message : t('providerRuntime.errors.refreshCodexAccount') ); } }; const handleCodexStartLogin = async ( mode: 'browser' | 'device_code' = 'browser' ): Promise => { setConnectionError(null); const success = await codexAccount.startChatgptLogin(mode); if (!success && codexAccount.error) { setConnectionError(codexAccount.error); } }; const handleCodexCancelLogin = async (): Promise => { setConnectionError(null); const success = await codexAccount.cancelChatgptLogin(); if (success) { await onRefreshProvider?.('codex'); } else if (codexAccount.error) { setConnectionError(codexAccount.error); } }; const handleCodexLogout = async (): Promise => { setConnectionError(null); const success = await codexAccount.logout(); if (success) { await onRefreshProvider?.('codex'); } else if (codexAccount.error) { setConnectionError(codexAccount.error); } }; const handleRuntimeBackendSelect = async ( providerId: CliProviderId, backendId: string ): Promise => { setRuntimeSaving(true); setRuntimeError(null); try { await onSelectBackend(providerId, backendId); } catch (error) { setRuntimeError( error instanceof Error ? error.message : t('providerRuntime.errors.updateRuntimeBackend') ); } finally { setRuntimeSaving(false); } }; const handleAnthropicFastModeDefaultChange = async (enabled: boolean): Promise => { if (selectedProvider?.providerId !== 'anthropic' || anthropicFastModeEnabled === enabled) { return; } setConnectionSaving(true); setConnectionError(null); try { await updateConfig('providerConnections', { anthropic: { fastModeDefault: enabled, }, }); await onRefreshProvider?.('anthropic'); } catch (error) { setConnectionError( error instanceof Error ? error.message : t('providerRuntime.errors.updateAnthropicFastMode') ); } finally { setConnectionSaving(false); } }; return ( {t('providerRuntime.title')} {t('providerRuntime.description')}
{t('providerRuntime.provider')}
setSelectedProviderId(value as CliProviderId)} >
{providers.map((provider) => ( {provider.displayName} ))}
{showSelectedProviderSummary && selectedProvider ? (
{selectedProvider.displayName} {getProviderUsageLabel(selectedProvider, t)} {managedRuntimeSummary && !hideConnectionMethodMeta ? ( {managedRuntimeSummary} ) : runtimeSummary ? ( {t('providerRuntime.runtimeSummary', { runtime: runtimeSummary })} ) : null}
{selectedProviderDetailMessage ? (
{selectedProviderDetailMessage}
) : null} {selectedProviderDiagnostics.length > 0 ? (
{selectedProviderDiagnostics.slice(0, 3).map((diagnostic) => (
{diagnostic.label}:{' '} {diagnostic.statusMessage ?? (diagnostic.detected ? 'detected' : 'missing')} {diagnostic.detailMessage ? ` - ${diagnostic.detailMessage}` : ''}
))}
) : null}
) : null} {selectedProvider ? ( showRuntimeProviderManagement ? ( onRefreshProvider?.('opencode')} /> ) : (
{t('providerRuntime.connection.title')}
{getConnectionDescription(selectedProvider, t)}
{connectionProgressMessage ? (
{connectionProgressMessage}
) : null}
{canRequestSubscriptionLogin ? ( ) : null}
{showConnectionMethodCards ? (
void handleAuthModeChange(authMode)} /> {connectionMethodCardsHint ? (
{connectionMethodCardsHint}
) : null}
) : configurableAuthModes.length > 0 && configuredAuthMode ? (
{getAuthModeDescription(selectedProvider.providerId, configuredAuthMode, t)}
) : null} {selectedProvider.providerId === 'anthropic' ? (
{t('providerRuntime.compatibleEndpoint.title')}
{t('providerRuntime.compatibleEndpoint.description')}
{anthropicCompatibleEndpointEnabled ? t('providerRuntime.status.enabled') : t('providerRuntime.status.off')}
{ setCompatibleBaseUrl(event.currentTarget.value); setCompatibleEndpointError(null); setCompatibleEndpointStatus(null); }} placeholder={t('runtimeProvider.compatibleEndpoint.baseUrlPlaceholder')} className="h-9 text-sm" disabled={connectionBusy} />
{ setCompatibleTokenValue(event.currentTarget.value); setCompatibleEndpointError(null); setCompatibleEndpointStatus(null); }} placeholder={ anthropicCompatibleTokenConfigured ? t('providerRuntime.compatibleEndpoint.keepSavedToken') : 'lmstudio' } className="h-9 text-sm" disabled={connectionBusy || apiKeySaving} />
{t('providerRuntime.compatibleEndpoint.tokenStatus', { status: anthropicCompatibleTokenConfigured ? t('providerRuntime.status.configured') : t('providerRuntime.status.notSet'), })} {anthropicCompatibleTokenStatus ? ( {anthropicCompatibleTokenStatus} ) : null} {anthropicCompatibleEndpointEnabled && anthropicCompatibleEndpoint?.baseUrl ? ( {anthropicCompatibleEndpoint.baseUrl} ) : null}
{compatibleEndpointError ? (
{compatibleEndpointError}
) : compatibleEndpointStatus ? (
{compatibleEndpointStatus}
) : anthropicCompatibleMissingToken ? (
{t('providerRuntime.compatibleEndpoint.authTokenMissing')}
) : null}
{anthropicCompatibleEndpointEnabled ? ( ) : null}
) : null}
{configuredAuthMode && !hideConnectionMethodMeta ? ( {t('providerRuntime.connection.mode', { mode: formatProviderAuthModeLabelForProvider( selectedProvider.providerId, configuredAuthMode, t ), })} ) : null} {connectionStatusLabel ? ( {connectionStatusLabel} ) : null} {selectedProvider.connection?.apiKeyConfigured && !showApiKeySection ? ( {selectedProvider.connection.apiKeySourceLabel} ) : null}
{selectedProvider.providerId === 'anthropic' ? (
{t('providerRuntime.fastMode.title')}
{t('providerRuntime.fastMode.description')}
{anthropicFastModeSupported ? (
{[ { enabled: false, label: t('providerRuntime.fastMode.defaultOff') }, { enabled: true, label: t('providerRuntime.fastMode.preferFast') }, ].map((option) => ( ))}
) : null}
{anthropicFastModeSupported && anthropicFastModeAvailable ? anthropicFastModeEnabled ? t('providerRuntime.fastMode.enabledHint') : t('providerRuntime.fastMode.disabledHint') : anthropicFastModeDisabledReason}
) : null} {selectedProvider.providerId === 'codex' ? (
{t('providerRuntime.codex.account.title')}
{t('providerRuntime.codex.account.description')}
{showCodexRuntimeInstallAction ? ( ) : null} {codexLoginPending ? ( <> {codexLoginAuthUrl ? ( ) : null} ) : codexHasActiveChatgptSession ? ( ) : ( <> )}
{codexHasActiveChatgptSession ? t('providerRuntime.codex.account.connected') : codexNeedsReconnect ? t('providerRuntime.codex.account.reconnectRequired') : codexLoginPending ? t('providerRuntime.codex.account.loginInProgress') : t('providerRuntime.usage.notConnected')} {codexConnection ? ( {t('providerRuntime.codex.account.appServer', { state: codexConnection.appServerState, })} ) : null} {codexConnection?.managedAccount?.planType ? ( {t('providerRuntime.codex.account.plan', { plan: codexConnection.managedAccount.planType, })} ) : null} {codexConnection?.managedAccount?.email ? ( {codexConnection.managedAccount.email} ) : null}
{codexAccountPanelHint ? (
{codexAccountPanelHint}
) : null} {codexFastCapabilityHint ? (
{codexFastCapabilityHint}
) : null} {codexConnection?.rateLimits ? (
{t('providerRuntime.codex.rateLimits.usedQuotaNote')}{' '} {formatLocalizedCodexUsageExplanation( codexConnection.rateLimits.primary?.usedPercent, codexConnection.rateLimits.primary?.windowDurationMins, t )} {codexConnection.rateLimits.secondary ? t('providerRuntime.codex.rateLimits.secondaryWindowNote', { window: formatCodexWindowDurationLong( codexConnection.rateLimits.secondary.windowDurationMins ) ?? t('providerRuntime.codex.rateLimits.secondaryFallback'), }) : ''}
{codexConnection.rateLimits.secondary ? ( ) : (
{t('providerRuntime.codex.rateLimits.weeklyWindow')}
{t('providerRuntime.codex.rateLimits.weeklyUsedOneWeek')}
{t('providerRuntime.codex.rateLimits.notReported')}
{t('providerRuntime.codex.rateLimits.noSecondaryWindow')}
)}
{t('providerRuntime.codex.rateLimits.credits')}
{formatCodexCreditsValue(codexConnection.rateLimits.credits)}
{t('providerRuntime.codex.rateLimits.creditsDescription')}
) : null}
) : null} {showApiKeySection && apiKeyConfig ? (
{apiKeyDisplayConfig?.title ?? apiKeyConfig.title}
{apiKeyDisplayConfig?.description ?? apiKeyConfig.description}
{!showApiKeyForm ? ( ) : null}
{selectedProvider.connection?.apiKeyConfigured || selectedApiKey ? t('providerRuntime.status.configured') : t('providerRuntime.status.notConfigured')} {selectedApiKey ? ( {selectedApiKey.maskedValue} ยท {selectedApiKey.scope} ) : selectedProvider.connection?.apiKeySource === 'environment' ? ( {selectedProvider.connection.apiKeySourceLabel} ) : null} {apiKeyStorageStatus && selectedApiKey ? ( {t('providerRuntime.apiKey.storedIn', { backend: apiKeyStorageStatus.backend, })} ) : null}
{showApiKeyForm ? (
setApiKeyValue(e.target.value)} placeholder={ apiKeyDisplayConfig?.placeholder ?? apiKeyConfig.placeholder } className="h-9 text-sm" autoFocus />
{(apiKeyError || apiKeysError) && (
{apiKeyError ?? apiKeysError}
)}
{selectedApiKey ? ( ) : ( )}
) : null}
) : null} {connectionError ? (
{connectionError}
) : null} {connectionAlert ? (
{connectionAlert}
) : null} {apiKeysLoading && !selectedApiKey ? (
{t('providerRuntime.apiKey.loadingStoredCredentials')}
) : null}
) ) : null} {selectedProvider && canConfigureRuntime ? (
{t('providerRuntime.runtime.title')}
{getRuntimeDescription(selectedProvider, t)}
void handleRuntimeBackendSelect(providerId, backendId) } /> {runtimeSaving ? (
{t('providerRuntime.runtime.updating')}
) : null} {runtimeError ? (
{runtimeError}
) : null}
) : null}
); };