import type { CodexInstallationProblem } from '../../shared/codex-cli-installation' import { sayAgentSessionFailureEnglish } from '../../shared/agent-session-failure-copy' import { readCodexCliInstallation } from '../preflight/codex-cli-installation' import { AgentSessionPreSpawnError } from '../native-chat/agent-session-wire/structured-agent-session-adapter' import type { StructuredAgentLaunchResolver } from '../runtime/structured-agent-launch-composition' import { resolveProviderChildEnv, type ProviderProcessLaunch } from '../provider-process/provider-process-launch' import { findInErrorChain } from '../provider-process/provider-error-chain' export class CodexCliInstallationError extends AgentSessionPreSpawnError { readonly codexInstallation: CodexInstallationProblem constructor(problem: CodexInstallationProblem) { super( sayAgentSessionFailureEnglish( problem.installedVersion === null ? 'cliMissing' : 'codexCliTooOld', { agent: 'Codex', installedVersion: problem.installedVersion ?? '', minimumVersion: problem.minimumVersion } ) ) this.codexInstallation = problem } } export function codexInstallationProblemOf(error: unknown): CodexInstallationProblem | undefined { return findInErrorChain(error, (inner) => inner instanceof CodexCliInstallationError ? inner.codexInstallation : undefined ) } export async function requireSupportedCodexCli( input: Parameters[0], readInstallation: typeof readCodexCliInstallation = readCodexCliInstallation ): Promise { const result = await readInstallation(input) if (result.status === 'unsupported') { throw new CodexCliInstallationError({ installedVersion: result.version, minimumVersion: result.minimumVersion }) } if (result.status === 'unknown') { console.warn(`[codex-cli-version] Could not verify ${input.program}; allowing structured chat`) } } /** Check every acquired child against the same sealed launch the app-server will use. */ export function withSupportedCodexCli( resolveLaunch: StructuredAgentLaunchResolver, readInstallation: typeof readCodexCliInstallation = readCodexCliInstallation ): StructuredAgentLaunchResolver { return async (request) => { const launch = await resolveLaunch(request) await requireSupportedCodexCli( { program: launch.command, cwd: launch.cwd, env: resolveProviderChildEnv(launch, process.env) }, readInstallation ) return launch } }