{"version":3,"file":"ai-model/service-caller/codex-app-server.mjs","sources":["../../../../src/ai-model/service-caller/codex-app-server.ts"],"sourcesContent":["import type {\n  AIUsageInfo,\n  CodeGenerationChunk,\n  StreamingCallback,\n} from '@/types';\nimport type {\n  IModelConfig,\n  TModelReasoningEnabled,\n} from '@midscene/shared/env';\nimport { getDebug } from '@midscene/shared/logger';\nimport { ifInBrowser } from '@midscene/shared/utils';\nimport type { ChatCompletionMessageParam } from 'openai/resources/index';\n\nconst CODEX_PROVIDER_SCHEME = 'codex://';\nconst CODEX_DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;\nconst CODEX_DEFAULT_PROCESS_START_TIMEOUT_MS = 15 * 1000;\nconst CODEX_DEFAULT_CLEANUP_TIMEOUT_MS = 8 * 1000;\nconst CODEX_TEXT_INPUT_MAX_LENGTH = 256 * 1024;\n\nconst debugCodex = getDebug('ai:call:codex');\nconst warnCodex = getDebug('ai:call:codex', { console: true });\n\ntype CodexReasoningEffort =\n  | 'none'\n  | 'minimal'\n  | 'low'\n  | 'medium'\n  | 'high'\n  | 'xhigh';\n\ntype JsonRpcRequest = {\n  id: string | number;\n  method: string;\n  params?: unknown;\n};\n\ntype JsonRpcResponse = {\n  id: string | number;\n  result?: unknown;\n  error?: {\n    code?: number;\n    message?: string;\n    data?: unknown;\n  };\n};\n\ntype JsonRpcNotification = {\n  method: string;\n  params?: Record<string, any>;\n};\n\ntype JsonRpcMessage = JsonRpcRequest | JsonRpcResponse | JsonRpcNotification;\n\ntype CodexTextInput = {\n  type: 'text';\n  text: string;\n  text_elements: any[];\n};\n\ntype CodexImageInput = {\n  type: 'image';\n  url: string;\n};\n\ntype CodexLocalImageInput = {\n  type: 'localImage';\n  path: string;\n};\n\ntype CodexTurnInput = CodexTextInput | CodexImageInput | CodexLocalImageInput;\n\ntype CodexTurnResult = {\n  content: string;\n  reasoning_content?: string;\n  usage?: AIUsageInfo;\n  isStreamed: boolean;\n};\n\ntype CodexTurnStartResponse = {\n  turn?: {\n    id?: string;\n  };\n};\n\ntype CodexThreadStartResponse = {\n  thread?: {\n    id?: string;\n  };\n};\n\ntype CodexUsageNotification = {\n  threadId?: string;\n  turnId?: string;\n  tokenUsage?: {\n    total?: {\n      totalTokens?: number;\n      inputTokens?: number;\n      cachedInputTokens?: number;\n      outputTokens?: number;\n      reasoningOutputTokens?: number;\n    };\n    last?: {\n      totalTokens?: number;\n      inputTokens?: number;\n      cachedInputTokens?: number;\n      outputTokens?: number;\n      reasoningOutputTokens?: number;\n    };\n  };\n};\n\nclass SerializedRunner {\n  private tail: Promise<void> = Promise.resolve();\n\n  async run<T>(work: () => Promise<T>): Promise<T> {\n    const previous = this.tail;\n    let release!: () => void;\n    this.tail = new Promise<void>((resolve) => {\n      release = resolve;\n    });\n\n    await previous;\n    try {\n      return await work();\n    } finally {\n      release();\n    }\n  }\n}\n\nexport const isCodexAppServerProvider = (baseURL?: string): boolean => {\n  if (!baseURL) return false;\n  return baseURL.trim().toLowerCase().startsWith(CODEX_PROVIDER_SCHEME);\n};\n\nconst isAbortError = (error: unknown): boolean => {\n  if (!error) return false;\n  if (error instanceof Error && error.name === 'AbortError') return true;\n  const message =\n    error instanceof Error ? error.message : String(error ?? 'unknown error');\n  return /aborted|abort/i.test(message);\n};\n\nconst toNonEmptyString = (value: unknown): string | undefined => {\n  if (typeof value !== 'string') return undefined;\n  const trimmed = value.trim();\n  return trimmed || undefined;\n};\n\nexport const normalizeCodexLocalImagePath = (\n  imageUrl: string,\n  platform: NodeJS.Platform = process.platform,\n): string => {\n  if (!imageUrl.startsWith('file://')) {\n    return imageUrl;\n  }\n\n  try {\n    const parsed = new URL(imageUrl);\n    const pathname = decodeURIComponent(parsed.pathname);\n    const host = parsed.hostname.toLowerCase();\n\n    if (platform === 'win32') {\n      const windowsPath = pathname\n        .replace(/\\//g, '\\\\')\n        .replace(/^\\\\([A-Za-z]:)/, '$1');\n\n      if (host && host !== 'localhost') {\n        return `\\\\\\\\${parsed.hostname}${windowsPath}`;\n      }\n\n      return windowsPath;\n    }\n\n    if (host && host !== 'localhost') {\n      return `//${parsed.hostname}${pathname}`;\n    }\n\n    return pathname;\n  } catch {\n    return decodeURIComponent(imageUrl.slice('file://'.length));\n  }\n};\n\nconst extractTextFromMessage = (\n  message: ChatCompletionMessageParam,\n): string => {\n  const content = (message as any).content;\n  if (typeof content === 'string') {\n    return content;\n  }\n\n  if (Array.isArray(content)) {\n    return content\n      .map((part) => {\n        if (!part || typeof part !== 'object') return '';\n\n        if (part.type === 'text' && typeof part.text === 'string') {\n          return part.text;\n        }\n\n        if (part.type === 'input_text' && typeof part.text === 'string') {\n          return part.text;\n        }\n\n        return '';\n      })\n      .filter(Boolean)\n      .join('\\n');\n  }\n\n  return '';\n};\n\nconst extractImageInputs = (\n  message: ChatCompletionMessageParam,\n): Array<CodexImageInput | CodexLocalImageInput> => {\n  const content = (message as any).content;\n  if (!Array.isArray(content)) return [];\n\n  const inputs: Array<CodexImageInput | CodexLocalImageInput> = [];\n  for (const part of content) {\n    if (!part || typeof part !== 'object') continue;\n\n    const partType = String(part.type || '');\n    const imageUrl =\n      partType === 'image_url'\n        ? toNonEmptyString(part.image_url?.url)\n        : partType === 'input_image'\n          ? toNonEmptyString(part.image_url || part.url)\n          : undefined;\n\n    if (!imageUrl) continue;\n\n    if (\n      imageUrl.startsWith('/') ||\n      imageUrl.startsWith('./') ||\n      imageUrl.startsWith('../') ||\n      imageUrl.startsWith('file://')\n    ) {\n      const path = imageUrl.startsWith('file://')\n        ? normalizeCodexLocalImagePath(imageUrl)\n        : imageUrl;\n\n      inputs.push({\n        type: 'localImage',\n        path,\n      });\n      continue;\n    }\n\n    inputs.push({\n      type: 'image',\n      url: imageUrl,\n    });\n  }\n\n  return inputs;\n};\n\nexport const resolveCodexReasoningEffort = ({\n  reasoningEnabled,\n  modelConfig,\n}: {\n  reasoningEnabled?: TModelReasoningEnabled;\n  modelConfig: IModelConfig;\n}): CodexReasoningEffort | undefined => {\n  if (reasoningEnabled === true) return 'high';\n  if (reasoningEnabled === false) return 'none';\n  if (reasoningEnabled === 'default') return undefined;\n\n  const normalized = modelConfig.reasoningEffort?.trim().toLowerCase();\n  if (\n    normalized === 'none' ||\n    normalized === 'minimal' ||\n    normalized === 'low' ||\n    normalized === 'medium' ||\n    normalized === 'high' ||\n    normalized === 'xhigh'\n  ) {\n    return normalized;\n  }\n\n  return 'none';\n};\n\nexport const buildCodexTurnPayloadFromMessages = (\n  messages: ChatCompletionMessageParam[],\n): {\n  developerInstructions?: string;\n  input: CodexTurnInput[];\n} => {\n  const developerInstructionParts: string[] = [];\n  const transcriptParts: string[] = [];\n  const imageInputs: Array<CodexImageInput | CodexLocalImageInput> = [];\n\n  for (const message of messages) {\n    const role = String((message as any).role || 'user');\n    const text = extractTextFromMessage(message);\n\n    if (role === 'system') {\n      if (text.trim()) developerInstructionParts.push(text.trim());\n      continue;\n    }\n\n    const roleTag = role.toUpperCase();\n    if (text.trim()) {\n      transcriptParts.push(`[${roleTag}]\\n${text.trim()}`);\n    } else {\n      transcriptParts.push(`[${roleTag}]\\n(no text content)`);\n    }\n\n    if (role === 'user') {\n      imageInputs.push(...extractImageInputs(message));\n    }\n  }\n\n  const fullTranscript = transcriptParts.join('\\n\\n');\n  const transcriptText =\n    (fullTranscript.length > CODEX_TEXT_INPUT_MAX_LENGTH\n      ? fullTranscript.slice(-CODEX_TEXT_INPUT_MAX_LENGTH)\n      : fullTranscript) || 'Please answer the latest user request.';\n\n  const input: CodexTurnInput[] = [\n    {\n      type: 'text',\n      text: transcriptText,\n      text_elements: [],\n    },\n    ...imageInputs,\n  ];\n\n  const developerInstructions = developerInstructionParts.length\n    ? developerInstructionParts.join('\\n\\n')\n    : undefined;\n\n  return {\n    developerInstructions,\n    input,\n  };\n};\n\nclass CodexAppServerConnection {\n  private child: any;\n  private lineReader: any;\n  private pendingMessages: JsonRpcMessage[] = [];\n  private lineBuffer: string[] = [];\n  private nextRequestId = 1;\n  private closed = false;\n  private lastExitCode: number | null = null;\n  private processErrorMessage: string | null = null;\n  private stderrBuffer = '';\n\n  private constructor(child: any, lineReader: any) {\n    this.child = child;\n    this.lineReader = lineReader;\n  }\n\n  static async create(): Promise<CodexAppServerConnection> {\n    if (ifInBrowser) {\n      throw new Error(\n        'codex app-server provider is not supported in browser runtime',\n      );\n    }\n\n    const childProcessModuleName = 'node:child_process';\n    const readlineModuleName = 'node:readline';\n    const { spawn } = await import(childProcessModuleName);\n    const readline = await import(readlineModuleName);\n\n    const child = spawn('codex', ['app-server'], {\n      stdio: ['pipe', 'pipe', 'pipe'],\n    });\n\n    if (!child.stdin || !child.stdout || !child.stderr) {\n      throw new Error('failed to start codex app-server: stdio unavailable');\n    }\n\n    const lineReader = readline.createInterface({\n      input: child.stdout,\n      crlfDelay: Number.POSITIVE_INFINITY,\n    });\n    const connection = new CodexAppServerConnection(child, lineReader);\n    connection.detachFromEventLoop();\n    connection.attachProcessListeners();\n    await connection.initializeHandshake();\n\n    return connection;\n  }\n\n  isClosed(): boolean {\n    return this.closed;\n  }\n\n  async runTurn({\n    messages,\n    modelConfig,\n    stream,\n    onChunk,\n    reasoningEnabled,\n    abortSignal,\n  }: {\n    messages: ChatCompletionMessageParam[];\n    modelConfig: IModelConfig;\n    stream?: boolean;\n    onChunk?: StreamingCallback;\n    reasoningEnabled?: TModelReasoningEnabled;\n    abortSignal?: AbortSignal;\n  }): Promise<CodexTurnResult> {\n    const startTime = Date.now();\n    const timeoutMs = modelConfig.timeout || CODEX_DEFAULT_TIMEOUT_MS;\n    const deadlineAt = Date.now() + timeoutMs;\n    const isStreaming = !!(stream && onChunk);\n\n    const { developerInstructions, input } =\n      buildCodexTurnPayloadFromMessages(messages);\n    const effort = resolveCodexReasoningEffort({\n      reasoningEnabled,\n      modelConfig,\n    });\n\n    let threadId: string | undefined;\n    let turnId: string | undefined;\n    let latestErrorMessage: string | undefined;\n    let accumulatedText = '';\n    let accumulatedReasoning = '';\n    let latestUsage: AIUsageInfo | undefined;\n\n    const emitChunk = ({\n      content,\n      reasoning,\n      isComplete,\n      usage,\n    }: {\n      content: string;\n      reasoning: string;\n      isComplete: boolean;\n      usage?: AIUsageInfo;\n    }) => {\n      if (!isStreaming || !onChunk) return;\n      const chunk: CodeGenerationChunk = {\n        content,\n        reasoning_content: reasoning,\n        accumulated: accumulatedText,\n        isComplete,\n        usage,\n      };\n      onChunk(chunk);\n    };\n\n    try {\n      const threadStartResponse = await this.request<CodexThreadStartResponse>({\n        method: 'thread/start',\n        params: {\n          model: modelConfig.modelName,\n          cwd: process.cwd(),\n          approvalPolicy: 'never',\n          sandbox: 'read-only',\n          ephemeral: true,\n          experimentalRawEvents: false,\n          persistExtendedHistory: false,\n          developerInstructions: developerInstructions || null,\n        },\n        deadlineAt,\n        abortSignal,\n      });\n\n      threadId = threadStartResponse?.thread?.id;\n      if (!threadId) {\n        throw new Error('thread/start did not return a thread id');\n      }\n\n      const turnStartResponse = await this.request<CodexTurnStartResponse>({\n        method: 'turn/start',\n        params: {\n          threadId,\n          input,\n          effort,\n        },\n        deadlineAt,\n        abortSignal,\n      });\n\n      turnId = turnStartResponse?.turn?.id;\n      if (!turnId) {\n        throw new Error('turn/start did not return a turn id');\n      }\n\n      let turnStatus: string | undefined;\n      while (!turnStatus) {\n        const message = await this.nextMessage({ deadlineAt, abortSignal });\n\n        if (this.isResponseMessage(message)) {\n          // No concurrent requests in adapter runtime.\n          continue;\n        }\n\n        if (this.isRequestMessage(message)) {\n          await this.respondToServerRequest(message);\n          continue;\n        }\n\n        const notification = message as JsonRpcNotification;\n        const method = notification.method;\n        const params = notification.params || {};\n\n        if (method === 'error') {\n          const messageText =\n            params.error?.message ||\n            params.message ||\n            'codex app-server reported turn error';\n          latestErrorMessage = String(messageText);\n          continue;\n        }\n\n        if (\n          method === 'item/agentMessage/delta' &&\n          params.threadId === threadId &&\n          params.turnId === turnId\n        ) {\n          const delta = String(params.delta || '');\n          if (delta) {\n            accumulatedText += delta;\n            emitChunk({\n              content: delta,\n              reasoning: '',\n              isComplete: false,\n            });\n          }\n          continue;\n        }\n\n        if (\n          (method === 'item/reasoning/summaryTextDelta' ||\n            method === 'item/reasoning/textDelta') &&\n          params.threadId === threadId &&\n          params.turnId === turnId\n        ) {\n          const delta = String(params.delta || '');\n          if (delta) {\n            accumulatedReasoning += delta;\n            emitChunk({\n              content: '',\n              reasoning: delta,\n              isComplete: false,\n            });\n          }\n          continue;\n        }\n\n        if (\n          method === 'item/completed' &&\n          params.threadId === threadId &&\n          params.turnId === turnId &&\n          params.item?.type === 'agentMessage' &&\n          typeof params.item?.text === 'string' &&\n          !accumulatedText\n        ) {\n          accumulatedText = params.item.text;\n          continue;\n        }\n\n        if (\n          method === 'thread/tokenUsage/updated' &&\n          params.threadId === threadId &&\n          params.turnId === turnId\n        ) {\n          latestUsage = this.mapUsage({\n            usage: params as CodexUsageNotification,\n            modelConfig,\n            turnId,\n            startTime,\n          });\n          continue;\n        }\n\n        if (\n          method === 'turn/completed' &&\n          params.threadId === threadId &&\n          params.turn?.id === turnId\n        ) {\n          turnStatus = String(params.turn.status || '');\n          latestErrorMessage =\n            params.turn?.error?.message || latestErrorMessage || undefined;\n          break;\n        }\n      }\n\n      if (turnStatus !== 'completed') {\n        throw new Error(\n          latestErrorMessage ||\n            `codex turn finished with status \"${turnStatus || 'unknown'}\"`,\n        );\n      }\n\n      if (isStreaming) {\n        emitChunk({\n          content: '',\n          reasoning: '',\n          isComplete: true,\n          usage: latestUsage,\n        });\n      }\n\n      return {\n        content: accumulatedText,\n        reasoning_content: accumulatedReasoning || undefined,\n        usage: latestUsage,\n        isStreamed: isStreaming,\n      };\n    } catch (error) {\n      if (isAbortError(error) && threadId && turnId) {\n        await this.request({\n          method: 'turn/interrupt',\n          params: {\n            threadId,\n            turnId,\n          },\n          deadlineAt: Date.now() + 5_000,\n        }).catch(() => {});\n      }\n      throw error;\n    } finally {\n      if (threadId) {\n        await this.request({\n          method: 'thread/unsubscribe',\n          params: { threadId },\n          deadlineAt: Date.now() + CODEX_DEFAULT_CLEANUP_TIMEOUT_MS,\n        }).catch((error) => {\n          warnCodex(\n            `failed to unsubscribe codex thread ${threadId}: ${String(error)}`,\n          );\n        });\n      }\n    }\n  }\n\n  async dispose(): Promise<void> {\n    if (this.closed) return;\n    this.closed = true;\n\n    try {\n      this.lineReader?.close?.();\n    } catch {}\n\n    try {\n      this.child?.stdin?.end?.();\n    } catch {}\n\n    try {\n      this.child?.kill?.();\n    } catch {}\n  }\n\n  private attachProcessListeners() {\n    this.lineReader.on('line', (line: string) => {\n      this.lineBuffer.push(line);\n    });\n\n    this.child.stderr.on('data', (chunk: Buffer | string) => {\n      const text = Buffer.isBuffer(chunk)\n        ? chunk.toString('utf8')\n        : String(chunk);\n      this.stderrBuffer += text;\n      if (this.stderrBuffer.length > 8192) {\n        this.stderrBuffer = this.stderrBuffer.slice(-8192);\n      }\n    });\n\n    this.child.on('exit', (code: number | null) => {\n      this.closed = true;\n      this.lastExitCode = code;\n    });\n\n    this.child.on('error', (error: Error) => {\n      this.closed = true;\n      this.processErrorMessage = error.message;\n    });\n  }\n\n  /**\n   * Keep codex process reusable but let short-lived callers exit naturally.\n   * Without unref, one-shot scripts/tests that call AI once can hang.\n   */\n  private detachFromEventLoop() {\n    this.child.unref?.();\n    this.child.stdin?.unref?.();\n    this.child.stdout?.unref?.();\n    this.child.stderr?.unref?.();\n  }\n\n  private async initializeHandshake() {\n    const deadlineAt = Date.now() + CODEX_DEFAULT_PROCESS_START_TIMEOUT_MS;\n    await this.request({\n      method: 'initialize',\n      params: {\n        clientInfo: {\n          name: 'midscene_codex_provider',\n          title: 'Midscene Codex Provider',\n          version: '1.0.0',\n        },\n        capabilities: {\n          experimentalApi: false,\n        },\n      },\n      deadlineAt,\n    });\n    await this.sendMessage({\n      method: 'initialized',\n    });\n  }\n\n  private mapUsage({\n    usage,\n    modelConfig,\n    turnId,\n    startTime,\n  }: {\n    usage: CodexUsageNotification;\n    modelConfig: IModelConfig;\n    turnId: string;\n    startTime: number;\n  }): AIUsageInfo | undefined {\n    const tokenUsage = usage.tokenUsage;\n    const picked = tokenUsage?.last || tokenUsage?.total;\n    if (!picked) return undefined;\n\n    return {\n      ...picked,\n      prompt_tokens: picked.inputTokens ?? 0,\n      completion_tokens: picked.outputTokens ?? 0,\n      total_tokens: picked.totalTokens ?? 0,\n      cached_input: picked.cachedInputTokens ?? 0,\n      time_cost: Date.now() - startTime,\n      model_name: modelConfig.modelName,\n      model_description: modelConfig.modelDescription,\n      response_model_name: undefined,\n      slot: modelConfig.slot,\n      intent: undefined,\n      request_id: turnId,\n    } satisfies AIUsageInfo;\n  }\n\n  private isRequestMessage(message: JsonRpcMessage): message is JsonRpcRequest {\n    return (\n      typeof (message as any)?.method === 'string' &&\n      (message as any)?.id !== undefined\n    );\n  }\n\n  private isResponseMessage(\n    message: JsonRpcMessage,\n  ): message is JsonRpcResponse {\n    return (\n      (message as any)?.id !== undefined &&\n      ((message as any)?.result !== undefined ||\n        (message as any)?.error !== undefined) &&\n      typeof (message as any)?.method !== 'string'\n    );\n  }\n\n  private async request<T = unknown>({\n    method,\n    params,\n    deadlineAt,\n    abortSignal,\n  }: {\n    method: string;\n    params: unknown;\n    deadlineAt?: number;\n    abortSignal?: AbortSignal;\n  }): Promise<T> {\n    const requestId = this.nextRequestId++;\n\n    await this.sendMessage({\n      id: requestId,\n      method,\n      params,\n    });\n\n    while (true) {\n      const message = await this.nextMessage({\n        deadlineAt,\n        abortSignal,\n        includePending: false,\n      });\n\n      if (this.isResponseMessage(message) && message.id === requestId) {\n        if (message.error) {\n          throw new Error(\n            `codex app-server ${method} failed: ${\n              message.error.message || 'unknown error'\n            }`,\n          );\n        }\n        return (message.result || {}) as T;\n      }\n\n      if (this.isRequestMessage(message)) {\n        await this.respondToServerRequest(message);\n        continue;\n      }\n\n      // Keep unmatched notifications/other responses for later stream handling.\n      this.pendingMessages.push(message);\n    }\n  }\n\n  private async respondToServerRequest(request: JsonRpcRequest): Promise<void> {\n    const requestId = request.id;\n    const method = request.method;\n\n    let result: unknown = {};\n    if (method === 'item/commandExecution/requestApproval') {\n      result = { decision: 'decline' };\n    } else if (method === 'item/fileChange/requestApproval') {\n      result = { decision: 'decline' };\n    } else if (method === 'mcpServer/elicitation/request') {\n      result = { action: 'cancel', content: null };\n    } else if (method === 'item/tool/requestUserInput') {\n      result = { answers: [] };\n    } else {\n      await this.sendMessage({\n        id: requestId,\n        error: {\n          code: -32601,\n          message: `unsupported server request: ${method}`,\n        },\n      });\n      return;\n    }\n\n    await this.sendMessage({\n      id: requestId,\n      result,\n    });\n  }\n\n  private async nextMessage({\n    deadlineAt,\n    abortSignal,\n    includePending = true,\n  }: {\n    deadlineAt?: number;\n    abortSignal?: AbortSignal;\n    includePending?: boolean;\n  }): Promise<JsonRpcMessage> {\n    if (includePending && this.pendingMessages.length) {\n      return this.pendingMessages.shift() as JsonRpcMessage;\n    }\n\n    while (true) {\n      if (abortSignal?.aborted) {\n        throw new Error('codex app-server request aborted');\n      }\n\n      if (deadlineAt && Date.now() > deadlineAt) {\n        throw new Error('codex app-server request timed out');\n      }\n\n      if (this.lineBuffer.length) {\n        const line = this.lineBuffer.shift()!;\n        const trimmed = line.trim();\n        if (!trimmed) continue;\n\n        let parsed: JsonRpcMessage;\n        try {\n          parsed = JSON.parse(trimmed);\n        } catch (error) {\n          warnCodex(\n            `ignored non-JSON message from codex app-server: ${trimmed}`,\n          );\n          continue;\n        }\n\n        return parsed;\n      }\n\n      if (this.closed) {\n        throw this.createClosedConnectionError();\n      }\n\n      await new Promise((resolve) => setTimeout(resolve, 20));\n    }\n  }\n\n  private async sendMessage(payload: Record<string, unknown>): Promise<void> {\n    if (this.closed) {\n      throw this.createClosedConnectionError();\n    }\n\n    const line = JSON.stringify(payload);\n    await new Promise<void>((resolve, reject) => {\n      this.child.stdin.write(`${line}\\n`, (error: Error | null | undefined) => {\n        if (error) {\n          reject(\n            new Error(\n              `failed writing to codex app-server stdin: ${error.message}`,\n            ),\n          );\n          return;\n        }\n        resolve();\n      });\n    });\n  }\n\n  private createClosedConnectionError(): Error {\n    const stderr = this.stderrBuffer.trim();\n    if (this.processErrorMessage) {\n      return new Error(\n        stderr\n          ? `codex app-server process error: ${this.processErrorMessage}. stderr=${stderr}`\n          : `codex app-server process error: ${this.processErrorMessage}`,\n      );\n    }\n\n    return new Error(\n      stderr\n        ? `codex app-server connection closed (exitCode=${this.lastExitCode}). stderr=${stderr}`\n        : `codex app-server connection closed (exitCode=${this.lastExitCode})`,\n    );\n  }\n}\n\nclass CodexAppServerConnectionManager {\n  private connection: CodexAppServerConnection | null = null;\n  private runner = new SerializedRunner();\n\n  async runTurn({\n    messages,\n    modelConfig,\n    stream,\n    onChunk,\n    reasoningEnabled,\n    abortSignal,\n  }: {\n    messages: ChatCompletionMessageParam[];\n    modelConfig: IModelConfig;\n    stream?: boolean;\n    onChunk?: StreamingCallback;\n    reasoningEnabled?: TModelReasoningEnabled;\n    abortSignal?: AbortSignal;\n  }): Promise<CodexTurnResult> {\n    return this.runner.run(async () => {\n      const connection = await this.getConnection();\n      try {\n        return await connection.runTurn({\n          messages,\n          modelConfig,\n          stream,\n          onChunk,\n          reasoningEnabled,\n          abortSignal,\n        });\n      } catch (error) {\n        if (connection.isClosed() || !isAbortError(error)) {\n          await this.resetConnection();\n        }\n        throw error;\n      }\n    });\n  }\n\n  async shutdownForTests(): Promise<void> {\n    await this.resetConnection();\n  }\n\n  private async getConnection(): Promise<CodexAppServerConnection> {\n    if (!this.connection || this.connection.isClosed()) {\n      this.connection = await CodexAppServerConnection.create();\n      debugCodex('started long-lived codex app-server connection');\n    }\n    return this.connection;\n  }\n\n  private async resetConnection(): Promise<void> {\n    if (!this.connection) return;\n    const staleConnection = this.connection;\n    this.connection = null;\n    await staleConnection.dispose();\n    debugCodex('reset codex app-server connection');\n  }\n}\n\nconst codexConnectionManager = new CodexAppServerConnectionManager();\n\nexport async function callAIWithCodexAppServer(\n  messages: ChatCompletionMessageParam[],\n  modelConfig: IModelConfig,\n  options?: {\n    stream?: boolean;\n    onChunk?: StreamingCallback;\n    reasoningEnabled?: TModelReasoningEnabled;\n    abortSignal?: AbortSignal;\n  },\n): Promise<CodexTurnResult> {\n  if (ifInBrowser) {\n    throw new Error(\n      'codex app-server provider is not supported in browser runtime',\n    );\n  }\n\n  return codexConnectionManager.runTurn({\n    messages,\n    modelConfig,\n    stream: options?.stream,\n    onChunk: options?.onChunk,\n    reasoningEnabled: options?.reasoningEnabled,\n    abortSignal: options?.abortSignal,\n  });\n}\n\nexport async function __shutdownCodexAppServerForTests() {\n  await codexConnectionManager.shutdownForTests();\n}\n"],"names":["CODEX_PROVIDER_SCHEME","CODEX_DEFAULT_TIMEOUT_MS","CODEX_DEFAULT_PROCESS_START_TIMEOUT_MS","CODEX_DEFAULT_CLEANUP_TIMEOUT_MS","CODEX_TEXT_INPUT_MAX_LENGTH","debugCodex","getDebug","warnCodex","SerializedRunner","work","previous","release","Promise","resolve","isCodexAppServerProvider","baseURL","isAbortError","error","Error","message","String","toNonEmptyString","value","trimmed","undefined","normalizeCodexLocalImagePath","imageUrl","platform","process","parsed","URL","pathname","decodeURIComponent","host","windowsPath","extractTextFromMessage","content","Array","part","Boolean","extractImageInputs","inputs","partType","path","resolveCodexReasoningEffort","reasoningEnabled","modelConfig","normalized","buildCodexTurnPayloadFromMessages","messages","developerInstructionParts","transcriptParts","imageInputs","role","text","roleTag","fullTranscript","transcriptText","input","developerInstructions","CodexAppServerConnection","ifInBrowser","childProcessModuleName","readlineModuleName","spawn","readline","child","lineReader","Number","connection","stream","onChunk","abortSignal","startTime","Date","timeoutMs","deadlineAt","isStreaming","effort","threadId","turnId","latestErrorMessage","accumulatedText","accumulatedReasoning","latestUsage","emitChunk","reasoning","isComplete","usage","chunk","threadStartResponse","turnStartResponse","turnStatus","notification","method","params","messageText","delta","line","Buffer","code","tokenUsage","picked","requestId","request","result","includePending","JSON","setTimeout","payload","reject","stderr","CodexAppServerConnectionManager","staleConnection","codexConnectionManager","callAIWithCodexAppServer","options","__shutdownCodexAppServerForTests"],"mappings":"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"}