import React from "react"; import { ExternalLink, LogIn, LogOut, RefreshCw, RotateCcw, X } from "lucide-react"; import { useI18n } from "../../../../application/i18n/I18nProvider"; import { Button } from "../../../ui/button"; import { Switch } from "../../../ui/switch"; import { cn } from "../../../../lib/utils"; import type { AgentPathInfo, CodexAppServerStatus, CodexIntegrationStatus, CodexLoginSession } from "./types"; export const CodexConnectionCard: React.FC<{ pathInfo: AgentPathInfo | null; isResolvingPath: boolean; customPath: string; onCustomPathChange: (path: string) => void; onRecheckPath: () => void; onResetPath: () => void; integration: CodexIntegrationStatus | null; loginSession: CodexLoginSession | null; isLoading: boolean; hasPendingCustomPath?: boolean; error: string | null; onRefresh: () => void; onConnect: () => void; onCancel: () => void; onOpenUrl: () => void; onLogout: () => void; appServerRuntime: 'sdk' | 'app-server'; appServerStatus: CodexAppServerStatus | null; onAppServerRuntimeChange: (runtime: 'sdk' | 'app-server') => void; }> = ({ pathInfo, isResolvingPath, customPath, onCustomPathChange, onRecheckPath, onResetPath, integration, loginSession, isLoading, hasPendingCustomPath = false, error, onRefresh, onConnect, onCancel, onOpenUrl, onLogout, appServerRuntime, appServerStatus, onAppServerRuntimeChange, }) => { const { t } = useI18n(); const found = pathInfo?.available; const customConfigIncomplete = Boolean( integration?.state === "connected_custom_config" && integration.customConfig && integration.customConfig.envKey && !integration.customConfig.envKeyPresent && !integration.customConfig.hasHardcodedApiKey, ); const status = isResolvingPath ? t('ai.codex.detecting') : !found ? t('ai.codex.notFound') : loginSession?.state === "running" ? t('ai.codex.awaitingLogin') : integration?.state === "connected_chatgpt" ? t('ai.codex.connectedChatGPT') : integration?.state === "connected_api_key" ? t('ai.codex.connectedApiKey') : integration?.state === "connected_custom_config" ? customConfigIncomplete ? t('ai.codex.customConfigIncomplete') : t('ai.codex.connectedCustomConfig') : integration?.state === "not_logged_in" ? t('ai.codex.notConnected') : t('ai.codex.statusUnknown'); const statusClassName = isResolvingPath ? "text-muted-foreground" : !found ? "text-amber-500" : loginSession?.state === "running" ? "text-amber-500" : customConfigIncomplete ? "text-amber-500" : integration?.isConnected ? "text-emerald-500" : "text-muted-foreground"; const outputText = loginSession?.error ? loginSession.error : loginSession?.output?.trim() ? loginSession.output.trim() : integration?.rawOutput?.trim() ? integration.rawOutput.trim() : ""; return (

{t('ai.codex.description')}

{status}
{found && (
{t('ai.codex.path')} {pathInfo.path} {pathInfo.version && ( <> | {pathInfo.version} )}
)} {!isResolvingPath && (
{!found && (

{t('ai.codex.notFoundHint')}

)}
onCustomPathChange(e.target.value)} placeholder={t('ai.codex.customPathPlaceholder')} className="flex-1 h-8 rounded-md border border-input bg-background px-3 text-sm font-mono placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" />
)} {found && (
{t('ai.codex.appServer.title')} {t('ai.codex.appServer.experimental')}

{t('ai.codex.appServer.description')}

{appServerStatus?.checking ? (

{t('ai.codex.appServer.checking')}

) : appServerStatus?.available ? (

{t('ai.codex.appServer.available')}

) : appServerStatus?.error ? (

{appServerStatus.error}

) : null}
onAppServerRuntimeChange(checked ? 'app-server' : 'sdk')} />
)} {/* Connection & login UI -- only when codex is detected */} {found && ( <>
{loginSession?.state === "running" ? ( <> ) : integration?.state === "connected_custom_config" ? ( // Nothing to log out of; config.toml is user-owned state. null ) : integration?.isConnected ? ( ) : ( )}
{integration?.state === "connected_custom_config" && integration.customConfig && ( <>

{t('ai.codex.customConfigHint').replace( '{provider}', integration.customConfig.displayName || integration.customConfig.providerName, )}

{integration.customConfig.envKey && !integration.customConfig.envKeyPresent && !integration.customConfig.hasHardcodedApiKey && (

{t('ai.codex.customConfigMissingEnvKey').replace( '{envKey}', integration.customConfig.envKey, )}

)} )} )} {error && (

{error}

)} {found && outputText && (
          {outputText}
        
)}
); };