@ai-sdk/harness-codex 1.0.122 → 1.0.124
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/codex-bootstrap.ts +7 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @ai-sdk/harness-codex
|
|
2
2
|
|
|
3
|
+
## 1.0.124
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @ai-sdk/harness@1.0.122
|
|
8
|
+
- @ai-sdk/provider-utils@5.0.46
|
|
9
|
+
|
|
10
|
+
## 1.0.123
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 3ea56bc: fix(harness): make bridge asset resolution compatible with Turbopack (and thus Next.js 16)
|
|
15
|
+
- Updated dependencies [3ea56bc]
|
|
16
|
+
- @ai-sdk/harness@1.0.121
|
|
17
|
+
|
|
3
18
|
## 1.0.122
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,9 @@ import { z as z2 } from "zod/v4";
|
|
|
32
32
|
// src/codex-bootstrap.ts
|
|
33
33
|
import { createReadBridgeAsset } from "@ai-sdk/harness/utils";
|
|
34
34
|
var readBridgeAsset = createReadBridgeAsset({
|
|
35
|
-
|
|
35
|
+
"package.json": new URL("./bridge/package.json", import.meta.url),
|
|
36
|
+
"pnpm-lock.yaml": new URL("./bridge/pnpm-lock.yaml", import.meta.url),
|
|
37
|
+
"index.mjs": new URL("./bridge/index.mjs", import.meta.url)
|
|
36
38
|
});
|
|
37
39
|
var CODEX_BOOTSTRAP_DIR = ".harness-bootstrap/codex";
|
|
38
40
|
var cachedBootstrap;
|
|
@@ -531,7 +533,7 @@ var inboundMessageSchema = z.discriminatedUnion("type", [
|
|
|
531
533
|
var CLI_SHIM_FILENAME = "harness-tool.mjs";
|
|
532
534
|
|
|
533
535
|
// src/version.ts
|
|
534
|
-
var VERSION = true ? "1.0.
|
|
536
|
+
var VERSION = true ? "1.0.124" : "0.0.0-test";
|
|
535
537
|
|
|
536
538
|
// src/codex-harness.ts
|
|
537
539
|
var DEFAULT_CODEX_MODEL = "gpt-5.5";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/codex-harness.ts","../src/codex-bootstrap.ts","../src/codex-auth.ts","../src/codex-subscription.ts","../src/codex-bridge-protocol.ts","../src/bridge/cli-relay.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport path from 'node:path';\nimport {\n commonTool,\n HarnessCapabilityUnsupportedError,\n harnessV1DiagnosticFromBridgeFrame,\n type HarnessV1,\n type HarnessV1DebugConfig,\n type HarnessV1BuiltinTool,\n type HarnessV1ContinueTurnState,\n type HarnessV1CredentialForwarding,\n type HarnessV1MintBridgeTokenCallback,\n type HarnessV1Prompt,\n type HarnessV1PromptControl,\n type HarnessV1PortEndpoint,\n type HarnessV1ResumeSessionState,\n type HarnessV1NetworkSandboxSession,\n type HarnessV1PermissionMode,\n type HarnessV1Session,\n type HarnessV1Skill,\n type HarnessV1StreamPart,\n} from '@ai-sdk/harness';\nimport {\n applyCredentialForwarding,\n classifyDiskLog,\n createBridgeToken,\n createSandboxCredentialEnvironment,\n createBridgeErrorHandler,\n createBridgeStartupError,\n drainBridgeProcessStream,\n forwardBridgeProcessStream,\n getRestrictedSandboxSession,\n markBridgeStarting,\n resolveSandboxDefaultWorkingDirectory,\n resolveSandboxHomeDir,\n SandboxChannel,\n shellQuote,\n warnCredentialBrokeringUnavailable,\n waitForBridgeReady,\n withBridgeToken,\n writeSkills,\n type SandboxChannelReconnectOptions,\n} from '@ai-sdk/harness/utils';\nimport {\n type Experimental_SandboxProcess,\n type Experimental_SandboxSession as SandboxSession,\n} from '@ai-sdk/provider-utils';\nimport { WebSocket } from 'ws';\nimport { z } from 'zod/v4';\nimport {\n CODEX_BOOTSTRAP_DIR as BOOTSTRAP_DIR,\n getCodexBootstrap,\n} from './codex-bootstrap';\nimport {\n CODEX_CREDENTIAL_ENVIRONMENT_VARIABLES,\n DEFAULT_OPENAI_BASE_URL,\n resolveCodexAuthenticationMode,\n type CodexAuthenticationMode,\n} from './codex-auth';\nimport {\n createCodexSubscriptionRequestTransformations,\n resolveCodexAuthentication,\n} from './codex-subscription';\nimport {\n outboundMessageSchema,\n type InboundMessage,\n type OutboundMessage,\n} from './codex-bridge-protocol';\nimport { CLI_SHIM_FILENAME } from './bridge/cli-relay';\nimport { VERSION } from './version';\n\ntype CodexChannel = SandboxChannel<OutboundMessage, InboundMessage>;\ntype CodexRespawnStrategy = 'replay' | 'rerun';\n\n/*\n * This intentionally is not the latest Codex model. Newer GPT-5.6 models use\n * Responses Lite, which does not expose their code-mode tools as callable\n * through the custom model provider used by the harness. Keep GPT-5.5 as the\n * default until the upstream bug is resolved:\n * https://github.com/openai/codex/issues/31894\n *\n * Passing the model explicitly keeps the runtime behavior deterministic and\n * the telemetry (`gen_ai.request.model`) accurate.\n */\nconst DEFAULT_CODEX_MODEL = 'gpt-5.5';\n\n/**\n * Value to use in User-Agent and `x-client-app` headers.\n */\nconst CODEX_CLIENT_APP = `ai-sdk/harness-codex/${VERSION}`;\n\nexport type CodexHarnessSettings = {\n readonly auth?: CodexAuthenticationMode;\n /**\n * Customizes each credential value before it is forwarded into a sandbox\n * process. This does not restrict which credentials the harness adapter can\n * discover, read, or otherwise access in the host process.\n */\n readonly credentialForwarding?: HarnessV1CredentialForwarding;\n /**\n * Additional configuration passed through to Codex as-is. Codex config keys\n * typically use snake_case and must be provided in that form. Values managed\n * by this adapter take precedence over conflicting entries.\n */\n readonly codexConfig?: Record<string, unknown>;\n /**\n * MCP server definitions keyed by server name. Each definition uses the\n * underlying runtime's native MCP server configuration format.\n */\n readonly mcpServers?: Record<string, unknown>;\n /**\n * Reasoning effort for reasoning-capable models. Leaving this unset\n * defers to the CLI's default.\n */\n readonly reasoningEffort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max';\n /**\n * When `true`, allow the underlying runtime to use live web search.\n */\n readonly webSearch?: boolean;\n /**\n * Override the port the bridge binds inside the sandbox. By default the\n * adapter uses the first port the sandbox declares via `sandbox.ports`.\n * Only set this if the sandbox declares multiple ports and the first one\n * is reserved for something else.\n */\n readonly port?: number;\n /**\n * Override the host endpoint used to connect to the sandbox bridge. Required\n * together with `port` when using a basic sandbox session.\n */\n readonly portEndpoint?: HarnessV1PortEndpoint;\n /** Maximum milliseconds to wait for the bridge to advertise its port. Defaults to 120000. */\n readonly startupTimeoutMs?: number;\n /**\n * Configures reconnection attempts after an established bridge connection\n * drops. The reconnect window includes connection establishment and\n * backoff delays. Defaults to 30 seconds with exponential backoff from 50\n * milliseconds up to 2 seconds.\n */\n readonly reconnect?: SandboxChannelReconnectOptions;\n /**\n * Creates the authentication token used by the sandbox bridge. Defaults to\n * a random 32-byte hexadecimal token.\n */\n readonly mintBridgeToken?: HarnessV1MintBridgeTokenCallback;\n};\n\n/*\n * Every native tool the Codex CLI can invoke as a model-callable tool,\n * declared as a `ToolSet` keyed by what the bridge emits as `toolName` on\n * the wire (`commonName ?? nativeName`). Schemas reflect the `ThreadItem`\n * union in `@openai/codex-sdk`'s `dist/index.d.ts`.\n *\n * Codex's other native operations (`apply_patch`, todo planning) surface\n * only as side-effect events (`file_change`, `todo_list`) and are not\n * model-callable tools — they don't appear here.\n */\nconst CODEX_BUILTIN_TOOLS = {\n bash: commonTool('bash', {\n nativeName: 'shell',\n toolUseKind: 'bash',\n description: 'Execute a shell command',\n inputSchema: z.object({ command: z.string() }),\n }),\n webSearch: commonTool('webSearch', {\n nativeName: 'web_search',\n toolUseKind: 'readonly',\n description: 'Search the web',\n inputSchema: z.object({ query: z.string() }),\n }),\n} as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;\n\n/**\n * Live bridge coordinates returned by `doDetach()` and `doSuspendTurn()`. A\n * future process uses them to reopen a socket to the still-running bridge\n * (`attach`) instead of re-spawning it. Absent on a `doStop()` payload.\n */\nconst codexBridgeCoordsSchema = z.object({\n port: z.number(),\n token: z.string(),\n lastSeenEventId: z.number(),\n sandboxId: z.string().optional(),\n});\n\n/**\n * Schema for the adapter-specific lifecycle `data` payload Codex produces.\n * `threadId` is what `codex.resumeThread(...)` requires for the replay/rerun\n * rungs; the sandbox lookup is handled separately via\n * `provider.resumeSession({ sessionId })`. `bridge` carries live coordinates\n * for cross-process `attach` (present on `doDetach()` and `doSuspendTurn()`\n * payloads).\n */\nconst codexResumeStateSchema = z.object({\n threadId: z.string().optional(),\n turnConfigurationFingerprint: z.string().optional(),\n bridge: codexBridgeCoordsSchema.optional(),\n sandboxCredentialEnvironment: z.record(z.string(), z.string()).optional(),\n});\n\ntype CodexBridgeCoords = z.infer<typeof codexBridgeCoordsSchema>;\n\nexport function createCodex(\n settings: CodexHarnessSettings = {},\n): HarnessV1<typeof CODEX_BUILTIN_TOOLS> {\n return {\n specificationVersion: 'harness-v1',\n harnessId: 'codex',\n builtinTools: CODEX_BUILTIN_TOOLS,\n supportsBuiltinToolApprovals: false,\n lifecycleStateSchema: codexResumeStateSchema,\n getBootstrap: getCodexBootstrap,\n doStart: async startOpts => {\n const model = DEFAULT_CODEX_MODEL;\n if (startOpts.builtinToolFiltering != null) {\n throw new HarnessCapabilityUnsupportedError({\n message:\n \"Harness 'codex' does not support built-in tool filtering controls.\",\n harnessId: 'codex',\n });\n }\n if (\n startOpts.permissionMode != null &&\n startOpts.permissionMode !== 'allow-all'\n ) {\n throw new HarnessCapabilityUnsupportedError({\n message:\n \"Harness 'codex' does not support built-in tool approval requests; use permissionMode: 'allow-all'.\",\n harnessId: 'codex',\n });\n }\n const sandboxSession = startOpts.sandboxSession;\n const toolSafeSandboxSession =\n getRestrictedSandboxSession(sandboxSession);\n const sandboxId = 'id' in sandboxSession ? sandboxSession.id : undefined;\n validateBasicSandboxSettings({\n sandboxSession,\n port: settings.port,\n portEndpoint: settings.portEndpoint,\n });\n if (settings.mintBridgeToken != null && sandboxId == null) {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'codex',\n message:\n 'The codex harness cannot use `mintBridgeToken` with a sandbox session that does not expose an id.',\n });\n }\n const defaultWorkingDirectory =\n await resolveSandboxDefaultWorkingDirectory({\n sandboxSession,\n abortSignal: startOpts.abortSignal,\n });\n const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;\n const isResume = lifecycleState != null;\n const isContinue = startOpts.continueFrom != null;\n const resumeData =\n isResume && typeof lifecycleState?.data === 'object'\n ? (lifecycleState.data as {\n threadId?: unknown;\n turnConfigurationFingerprint?: unknown;\n bridge?: CodexBridgeCoords;\n sandboxCredentialEnvironment?: Record<string, string>;\n })\n : undefined;\n const resumeThreadId = resumeData?.threadId;\n const resumeThreadIdString =\n typeof resumeThreadId === 'string' && resumeThreadId.length > 0\n ? resumeThreadId\n : undefined;\n const turnConfigurationFingerprint =\n typeof resumeData?.turnConfigurationFingerprint === 'string'\n ? resumeData.turnConfigurationFingerprint\n : undefined;\n const coords = resumeData?.bridge;\n const authenticationMode = resolveCodexAuthenticationMode(settings.auth);\n const resolvedAuthentication = await resolveCodexAuthentication({\n auth: settings.auth,\n authCredentialsStoreMode:\n settings.codexConfig?.cli_auth_credentials_store,\n });\n const resolvedAuthEnvironment = resolvedAuthentication.environment;\n let sandboxAuthEnvironment = resolvedAuthEnvironment;\n let sandboxCredentialEnvironment: Record<string, string> | undefined;\n let credentialsBrokered = false;\n if (\n 'addRequestTransformations' in sandboxSession &&\n sandboxSession.addRequestTransformations != null\n ) {\n sandboxCredentialEnvironment =\n resumeData?.sandboxCredentialEnvironment ??\n (await createSandboxCredentialEnvironment({\n environment: resolvedAuthEnvironment,\n credentialEnvironmentVariables:\n CODEX_CREDENTIAL_ENVIRONMENT_VARIABLES,\n credentialForwarding: settings.credentialForwarding,\n }));\n sandboxAuthEnvironment = {\n ...resolvedAuthEnvironment,\n ...sandboxCredentialEnvironment,\n };\n const requestTransformations =\n createCodexSubscriptionRequestTransformations({\n env: resolvedAuthEnvironment,\n sandboxEnv: sandboxAuthEnvironment,\n auth: authenticationMode,\n requestHeaders: resolvedAuthentication.requestHeaders,\n });\n if (requestTransformations.length > 0) {\n await sandboxSession.addRequestTransformations(\n requestTransformations,\n );\n }\n credentialsBrokered = true;\n if (\n requestTransformations.length > 0 &&\n authenticationMode === 'direct' &&\n resolvedAuthEnvironment.OPENAI_BASE_URL == null\n ) {\n /*\n * Vercel Sandbox request transformations apply only to HTTP traffic.\n * Materializing Codex's standard OpenAI URL makes the bridge select\n * its custom provider, where WebSockets are disabled, while keeping\n * the non-brokered path on Codex's built-in OpenAI provider.\n */\n sandboxAuthEnvironment.OPENAI_BASE_URL = DEFAULT_OPENAI_BASE_URL;\n }\n }\n const bootstrapDir = path.posix.resolve(\n defaultWorkingDirectory,\n BOOTSTRAP_DIR,\n );\n\n const workDir = startOpts.sessionWorkDir;\n const sandboxHomeDir = await resolveSandboxHomeDir({\n sandbox: toolSafeSandboxSession,\n abortSignal: startOpts.abortSignal,\n });\n const sessionDataDir = `${defaultWorkingDirectory}/.agent-runs/${startOpts.sessionId}`;\n const bridgeStateDir = `${sessionDataDir}/bridge`;\n const cliShimDir = `${sessionDataDir}/codex`;\n const cliShimPath = `${cliShimDir}/${CLI_SHIM_FILENAME}`;\n const timeoutMs = settings.startupTimeoutMs ?? 120_000;\n\n // Normalize each forwarded bridge diagnostics frame into the general\n // `HarnessV1Diagnostic` and report it. The adapter does no telemetry work\n // beyond this transport→emission mapping.\n const report = startOpts.observability?.report;\n const onDiagnostic = report\n ? (frame: Parameters<typeof harnessV1DiagnosticFromBridgeFrame>[0]) =>\n report(\n harnessV1DiagnosticFromBridgeFrame(frame, {\n sessionId: startOpts.sessionId,\n timestamp: Date.now(),\n }),\n )\n : undefined;\n const onBridgeError = createBridgeErrorHandler({\n harnessId: 'codex',\n sessionId: startOpts.sessionId,\n });\n\n /*\n * Rung 1 — ATTACH. With live coordinates, reopen a socket to the\n * still-running bridge. Parked between-turn sessions just attach and wait\n * for the next `start`; suspended in-flight turns request replay of\n * everything past the persisted cursor. No spawn, no fresh token. If the\n * bridge is gone the open throws and we fall through to a spawn-based\n * recovery.\n */\n if (coords) {\n try {\n const endpoint = await resolveBridgeEndpoint({\n sandboxSession,\n override: settings.portEndpoint,\n port: coords.port,\n });\n const attachEndpoint = withBridgeToken({\n endpoint,\n token: coords.token,\n });\n const attachChannel: CodexChannel = new SandboxChannel({\n connect: ({ abortSignal }) =>\n openWebSocket({ ...attachEndpoint, abortSignal }),\n outboundSchema: outboundMessageSchema,\n initialLastSeenEventId: coords.lastSeenEventId,\n onDiagnostic,\n onBridgeError,\n reconnect: settings.reconnect,\n });\n await attachChannel.open(isContinue ? { resume: true } : undefined);\n return createSession({\n sessionId: startOpts.sessionId,\n channel: attachChannel,\n cliShimPath,\n // The live bridge was spawned by another process; no process handle.\n proc: undefined,\n model,\n reasoningEffort: settings.reasoningEffort,\n webSearch: settings.webSearch,\n codexConfig: settings.codexConfig,\n mcpServers: settings.mcpServers,\n headers: startOpts.headers,\n resumeThreadId: resumeThreadIdString,\n isResume: true,\n seedResumeThreadOnFirstPrompt: false,\n rerunContinue: false,\n bridgePort: coords.port,\n bridgeToken: coords.token,\n sandboxId,\n sandboxCredentialEnvironment,\n debug: startOpts.observability?.debug,\n permissionMode: startOpts.permissionMode,\n sandbox: toolSafeSandboxSession,\n sandboxHomeDir,\n turnConfigurationFingerprint,\n });\n } catch {\n // Bridge no longer reachable — recover by respawning below.\n }\n }\n\n /*\n * Rungs 2/3 — REPLAY vs RERUN. Respawn the bridge. `replay` is only sound\n * for `continueFrom`: those coordinates include the cursor the on-disk\n * log is replayed *from*. `resumeFrom` is a between-turn resume; even when\n * it carries bridge coordinates, replaying the previous turn would\n * re-deliver stale events into the next turn. Those resumes always `rerun`\n * via `codex.resumeThread(threadId)` when attach is unavailable.\n */\n let respawnStrategy: CodexRespawnStrategy | undefined = isResume\n ? 'rerun'\n : undefined;\n if (coords && isContinue) {\n const logRaw = await Promise.resolve(\n toolSafeSandboxSession.readTextFile({\n path: `${bridgeStateDir}/event-log.ndjson`,\n abortSignal: startOpts.abortSignal,\n }),\n ).catch(() => null);\n if ((await classifyDiskLog(logRaw)) === 'replay') {\n respawnStrategy = 'replay';\n }\n }\n\n const port = resolveBridgePort({\n sandboxSession,\n override: settings.port,\n });\n const token =\n settings.mintBridgeToken == null\n ? createBridgeToken()\n : settings.mintBridgeToken(sandboxId!);\n const forwardedAuthEnvironment = credentialsBrokered\n ? sandboxAuthEnvironment\n : await applyCredentialForwarding({\n environment: sandboxAuthEnvironment,\n credentialEnvironmentVariables:\n CODEX_CREDENTIAL_ENVIRONMENT_VARIABLES,\n credentialForwarding: settings.credentialForwarding,\n });\n if (!credentialsBrokered) {\n warnCredentialBrokeringUnavailable({\n environment: resolvedAuthEnvironment,\n forwardedEnvironment: forwardedAuthEnvironment,\n credentialEnvironmentVariables:\n CODEX_CREDENTIAL_ENVIRONMENT_VARIABLES,\n });\n }\n const env = {\n ...forwardedAuthEnvironment,\n AI_SDK_HARNESS_CLIENT_APP: CODEX_CLIENT_APP,\n BRIDGE_CHANNEL_TOKEN: token,\n BRIDGE_WS_PORT: String(port),\n ...(respawnStrategy === 'replay'\n ? { BRIDGE_REPLAY_FROM_DISK: '1' }\n : {}),\n };\n\n if (respawnStrategy === undefined) {\n await toolSafeSandboxSession.run({\n command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,\n abortSignal: startOpts.abortSignal,\n });\n }\n\n await markBridgeStarting({\n sandbox: toolSafeSandboxSession,\n bridgeStateDir,\n bridgeType: 'codex',\n abortSignal: startOpts.abortSignal,\n });\n\n const proc = await toolSafeSandboxSession.spawn({\n command: `node ${shellQuote(`${bootstrapDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)} --cli-shim-dir ${shellQuote(cliShimDir)}`,\n env,\n abortSignal: startOpts.abortSignal,\n });\n const stderrTail: string[] = [];\n const bridgeStderrDone = forwardBridgeProcessStream({\n stream: proc.stderr,\n streamName: 'stderr',\n source: 'codex',\n collectTail: stderrTail,\n });\n\n const { port: boundPort } = await waitForBridgeReady({\n proc,\n sandbox: toolSafeSandboxSession,\n bridgeStateDir,\n bridgeType: 'codex',\n timeoutMs,\n abortSignal: startOpts.abortSignal,\n createTimeoutError: ({ proc, stdoutTail }) =>\n createBridgeStartupError({\n message: 'codex bridge did not become ready in time.',\n proc,\n stdoutTail,\n stderrTail,\n stderrDone: bridgeStderrDone,\n }),\n createExitError: ({ proc, stdoutTail }) =>\n createBridgeStartupError({\n message: 'codex bridge exited before becoming ready.',\n proc,\n stdoutTail,\n stderrTail,\n stderrDone: bridgeStderrDone,\n }),\n });\n void drainBridgeProcessStream(proc.stdout);\n\n const endpoint = await resolveBridgeEndpoint({\n sandboxSession,\n override: settings.portEndpoint,\n port: boundPort,\n });\n const bridgeEndpoint = withBridgeToken({ endpoint, token });\n\n const channel: CodexChannel = new SandboxChannel({\n connect: ({ abortSignal }) =>\n openWebSocket({ ...bridgeEndpoint, abortSignal }),\n outboundSchema: outboundMessageSchema,\n onDiagnostic,\n onBridgeError,\n reconnect: settings.reconnect,\n // In replay mode the respawned bridge reloaded the finished turn from\n // disk; seed the cursor and resume so it streams the tail (incl.\n // `finish`).\n ...(respawnStrategy === 'replay'\n ? { initialLastSeenEventId: coords?.lastSeenEventId ?? 0 }\n : {}),\n });\n await channel.open(\n respawnStrategy === 'replay' ? { resume: true } : undefined,\n );\n\n return createSession({\n sessionId: startOpts.sessionId,\n channel,\n cliShimPath,\n proc,\n model,\n reasoningEffort: settings.reasoningEffort,\n webSearch: settings.webSearch,\n codexConfig: settings.codexConfig,\n mcpServers: settings.mcpServers,\n headers: startOpts.headers,\n resumeThreadId: resumeThreadIdString,\n isResume: respawnStrategy !== undefined,\n seedResumeThreadOnFirstPrompt: respawnStrategy !== undefined,\n rerunContinue: respawnStrategy === 'rerun',\n bridgePort: boundPort,\n bridgeToken: token,\n sandboxId,\n sandboxCredentialEnvironment,\n debug: startOpts.observability?.debug,\n permissionMode: startOpts.permissionMode,\n sandbox: toolSafeSandboxSession,\n sandboxHomeDir,\n turnConfigurationFingerprint,\n });\n },\n };\n}\n\nfunction resolveBridgePort({\n sandboxSession,\n override,\n}: {\n sandboxSession: HarnessV1NetworkSandboxSession | SandboxSession;\n override: number | undefined;\n}): number {\n if (override !== undefined) return override;\n if ('ports' in sandboxSession && sandboxSession.ports.length > 0) {\n return sandboxSession.ports[0];\n }\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'codex',\n message:\n 'The codex harness needs a TCP port exposed by the sandbox. ' +\n 'Create the sandbox with `ports: [<port>]` or pass `createCodex({ port })`.',\n });\n}\n\nfunction validateBasicSandboxSettings({\n sandboxSession,\n port,\n portEndpoint,\n}: {\n sandboxSession: HarnessV1NetworkSandboxSession | SandboxSession;\n port: number | undefined;\n portEndpoint: HarnessV1PortEndpoint | undefined;\n}): void {\n if ('getPortEndpoint' in sandboxSession) return;\n if (port == null) {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'codex',\n message:\n 'The codex harness requires an explicit `port` when using a basic sandbox session.',\n });\n }\n if (portEndpoint == null) {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'codex',\n message:\n 'The codex harness requires an explicit `portEndpoint` when using a basic sandbox session.',\n });\n }\n}\n\nasync function resolveBridgeEndpoint({\n sandboxSession,\n override,\n port,\n}: {\n sandboxSession: HarnessV1NetworkSandboxSession | SandboxSession;\n override: HarnessV1PortEndpoint | undefined;\n port: number;\n}): Promise<HarnessV1PortEndpoint> {\n if (override != null) return override;\n if ('getPortEndpoint' in sandboxSession) {\n return sandboxSession.getPortEndpoint({ port, protocol: 'ws' });\n }\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'codex',\n message:\n 'The codex harness requires an explicit `portEndpoint` when using a basic sandbox session.',\n });\n}\n\nfunction openWebSocket({\n url,\n headers,\n abortSignal,\n}: HarnessV1PortEndpoint & { abortSignal: AbortSignal }): Promise<WebSocket> {\n return new Promise((resolve, reject) => {\n if (abortSignal.aborted) {\n reject(abortSignal.reason ?? new Error('WebSocket connection aborted'));\n return;\n }\n\n const ws = new WebSocket(url, {\n headers: headers == null ? undefined : { ...headers },\n });\n\n let settled = false;\n const cleanup = () => {\n abortSignal.removeEventListener('abort', onAbort);\n ws.off('open', onOpen);\n ws.off('error', onError);\n };\n const rejectWithCleanup = (error: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n ws.once('error', () => {});\n try {\n ws.terminate();\n } catch {\n try {\n ws.close();\n } catch {\n // best-effort\n }\n }\n reject(error);\n };\n const onOpen = () => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(ws);\n };\n const onError = (err: Error) => {\n rejectWithCleanup(err);\n };\n const onAbort = () =>\n rejectWithCleanup(\n abortSignal.reason ?? new Error('WebSocket connection aborted'),\n );\n\n ws.once('open', onOpen);\n ws.once('error', onError);\n abortSignal.addEventListener('abort', onAbort, { once: true });\n });\n}\n\nfunction createSession({\n sessionId,\n channel,\n cliShimPath,\n proc,\n model,\n reasoningEffort,\n webSearch,\n codexConfig,\n mcpServers,\n headers,\n resumeThreadId,\n isResume,\n seedResumeThreadOnFirstPrompt,\n rerunContinue,\n bridgePort,\n bridgeToken,\n sandboxId,\n sandboxCredentialEnvironment,\n debug,\n permissionMode,\n sandbox,\n sandboxHomeDir,\n turnConfigurationFingerprint,\n}: {\n sessionId: string;\n channel: CodexChannel;\n cliShimPath: string;\n /** Undefined on `attach` — the live bridge was spawned by another process. */\n proc: Experimental_SandboxProcess | undefined;\n model: string | undefined;\n reasoningEffort: 'low' | 'medium' | 'high' | 'xhigh' | 'max' | undefined;\n webSearch: boolean | undefined;\n codexConfig: Record<string, unknown> | undefined;\n mcpServers: Record<string, unknown> | undefined;\n headers: Readonly<Record<string, string>> | undefined;\n resumeThreadId: string | undefined;\n isResume: boolean;\n seedResumeThreadOnFirstPrompt: boolean;\n rerunContinue: boolean;\n bridgePort: number;\n bridgeToken: string;\n sandboxId: string | undefined;\n sandboxCredentialEnvironment: Record<string, string> | undefined;\n debug: HarnessV1DebugConfig | undefined;\n permissionMode: HarnessV1PermissionMode | undefined;\n sandbox: SandboxSession;\n sandboxHomeDir: string;\n turnConfigurationFingerprint: string | undefined;\n}): HarnessV1Session {\n let stopped = false;\n let stopPromise: Promise<void> | undefined;\n /*\n * Send the persisted threadId on the first prompt only when the bridge was\n * respawned (rerun/replay) so it takes the `codex.resumeThread(...)` branch.\n * An `attach`ed bridge already holds its threadState in memory and continues\n * on its own, so it needs no seed.\n */\n let pendingResumeThreadId = seedResumeThreadOnFirstPrompt\n ? resumeThreadId\n : undefined;\n /*\n * Host-tool relay guidance is prepended to the first user message of a fresh\n * session only. A resumed session (attach/replay/rerun) already carried it in\n * its original first message (preserved in the persisted thread), so it\n * starts \"applied\".\n */\n let initialPromptGuidanceApplied = isResume;\n\n /*\n * Latest codex thread id, cached from the bridge's `bridge-thread`\n * announcements. Seeded from lifecycle state so `doDetach()` and `doStop()`\n * can include a thread id even before this process has run a turn.\n */\n let latestThreadId = resumeThreadId;\n let latestTurnConfigurationFingerprint = turnConfigurationFingerprint;\n channel.on('bridge-thread', msg => {\n latestThreadId = msg.threadId;\n });\n\n const synchronizeTurnConfiguration = async ({\n skills,\n instructions,\n tools,\n abortSignal,\n }: {\n skills: ReadonlyArray<HarnessV1Skill>;\n instructions: string | undefined;\n tools: ReadonlyArray<{\n name: string;\n description?: string;\n inputSchema: unknown;\n }>;\n abortSignal?: AbortSignal;\n }): Promise<{ restartThread: boolean }> => {\n const skillsResult = await writeSkills({\n sandbox,\n homePath: sandboxHomeDir,\n skillsDir: '.agents/skills',\n skills,\n abortSignal,\n invalidSkillNameMessage: ({ name }) =>\n `Invalid Codex skill name: ${name}`,\n invalidSkillFilePathMessage: ({ skillName, filePath }) =>\n `Invalid Codex skill file path for ${skillName}: ${filePath}`,\n });\n const nextFingerprint = fingerprintCodexTurnConfiguration({\n instructions,\n tools,\n });\n const restartThread =\n latestThreadId != null &&\n (skillsResult.changed ||\n (latestTurnConfigurationFingerprint != null &&\n latestTurnConfigurationFingerprint !== nextFingerprint));\n latestTurnConfigurationFingerprint = nextFingerprint;\n if (restartThread) {\n /*\n * `codex exec resume` retains the native thread's original developer\n * instructions and skill catalog. A fresh native thread is therefore\n * required for replacement semantics. Host-tool guidance is framed\n * again because that guidance also belongs to the new native thread.\n */\n initialPromptGuidanceApplied = false;\n pendingResumeThreadId = undefined;\n }\n return { restartThread };\n };\n\n /*\n * Wire the channel into one turn's worth of events and return the control\n * surface. Shared by `doPromptTurn` (which sends a `start` afterwards) and\n * `doContinueTurn` (which attaches to an already-running/replayed turn, or sends\n * a rerun `start`). The only difference between the two entry points is the\n * `start` message, not the listener/abort/settle plumbing.\n */\n const wireTurn = (turnOpts: {\n emit: (event: HarnessV1StreamPart) => void;\n abortSignal?: AbortSignal;\n }): {\n control: HarnessV1PromptControl;\n sendStart: (send: () => void) => void;\n } => {\n let pendingResolve: (() => void) | undefined;\n let pendingReject: ((err: unknown) => void) | undefined;\n const done = new Promise<void>((resolve, reject) => {\n pendingResolve = resolve;\n pendingReject = reject;\n });\n\n const unsubs: Array<() => void> = [];\n const forward = (event: HarnessV1StreamPart) => {\n try {\n turnOpts.emit(event);\n } catch {}\n };\n\n const eventTypes = [\n 'stream-start',\n 'text-start',\n 'text-delta',\n 'text-end',\n 'reasoning-start',\n 'reasoning-delta',\n 'reasoning-end',\n 'tool-call',\n 'tool-approval-request',\n 'tool-result',\n 'file-change',\n 'finish-step',\n 'raw',\n ] as const;\n let isSettled = false;\n const settleSuccess = () => {\n if (isSettled) return;\n isSettled = true;\n for (const u of unsubs) u();\n pendingResolve!();\n };\n const settleError = (err: unknown) => {\n if (isSettled) return;\n isSettled = true;\n for (const u of unsubs) u();\n pendingReject!(err);\n };\n\n for (const type of eventTypes) {\n unsubs.push(\n channel.on(type, msg => {\n forward(msg);\n }),\n );\n }\n unsubs.push(\n channel.on('finish', msg => {\n forward(msg);\n settleSuccess();\n }),\n );\n unsubs.push(\n channel.on('error', msg => {\n forward(msg);\n settleError(msg.error);\n }),\n );\n\n /*\n * A `'suspended'` close is a graceful slice-boundary freeze the host\n * initiated (`doSuspendTurn`): the turn keeps running in the bridge and its\n * tail is replayed to the next process, so wind this turn down cleanly\n * rather than failing it. Any other close mid-turn is an unexpected drop.\n */\n const onClose = (_code?: number, reason?: string) => {\n if (isSettled) return;\n if (reason === 'suspended') {\n settleSuccess();\n return;\n }\n settleError(new Error('codex bridge closed before the turn finished.'));\n };\n channel.onClose(onClose);\n\n const onAbort = () => {\n if (isSettled) return;\n try {\n channel.send({ type: 'abort' });\n } catch {}\n settleError(\n turnOpts.abortSignal?.reason ??\n new DOMException('Aborted', 'AbortError'),\n );\n };\n if (turnOpts.abortSignal) {\n if (turnOpts.abortSignal.aborted) {\n onAbort();\n } else {\n turnOpts.abortSignal.addEventListener('abort', onAbort, {\n once: true,\n });\n }\n }\n\n const control: HarnessV1PromptControl = {\n submitToolResult: async input => {\n channel.send({\n type: 'tool-result',\n toolCallId: input.toolCallId,\n output: input.output,\n isError: input.isError,\n });\n },\n submitToolApproval: async input => {\n channel.send({\n type: 'tool-approval-response',\n approvalId: input.approvalId,\n approved: input.approved,\n reason: input.reason,\n });\n },\n done,\n };\n\n return {\n control,\n sendStart: send => {\n /*\n * Codex can complete short turns without using tools. Deferring the\n * start frame gives the harness runner one event-loop turn to finish\n * wiring the prompt control and stream output before Codex can settle.\n */\n const timer = setTimeout(() => {\n if (isSettled) return;\n try {\n send();\n } catch (err) {\n settleError(err);\n }\n }, 0);\n timer.unref?.();\n },\n };\n };\n\n return {\n sessionId,\n isResume,\n doPromptTurn: async promptOpts => {\n if (\n promptOpts.responseFormat?.type === 'json' &&\n promptOpts.responseFormat.schema == null\n ) {\n throw new HarnessCapabilityUnsupportedError({\n message:\n \"Harness 'codex' requires a JSON schema for structured output.\",\n harnessId: 'codex',\n });\n }\n const tools = (promptOpts.tools ?? []).map(t => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n }));\n const { restartThread } = await synchronizeTurnConfiguration({\n skills: promptOpts.skills,\n instructions: promptOpts.instructions,\n tools,\n abortSignal: promptOpts.abortSignal,\n });\n const turn = wireTurn({\n emit: promptOpts.emit,\n abortSignal: promptOpts.abortSignal,\n });\n\n let promptText = extractUserText(promptOpts.prompt);\n if (!initialPromptGuidanceApplied) {\n promptText = frameInitialPromptGuidance({\n toolUsageBlock:\n tools.length > 0\n ? composeToolUsageInstructions({\n tools,\n cliShimPath,\n })\n : undefined,\n userText: promptText,\n });\n }\n initialPromptGuidanceApplied = true;\n\n const startMessage = {\n type: 'start' as const,\n prompt: promptText,\n tools,\n ...(promptOpts.responseFormat == null\n ? {}\n : { responseFormat: promptOpts.responseFormat }),\n ...(promptOpts.instructions\n ? { instructions: promptOpts.instructions }\n : {}),\n model: promptOpts.model ?? model,\n reasoningEffort,\n webSearch,\n ...(codexConfig == null ? {} : { codexConfig }),\n ...(mcpServers == null ? {} : { mcpServers }),\n ...(headers == null ? {} : { headers }),\n ...(permissionMode ? { permissionMode } : {}),\n ...(pendingResumeThreadId\n ? { resumeThreadId: pendingResumeThreadId }\n : {}),\n ...(restartThread ? { restartThread: true } : {}),\n ...(debug ? { debug } : {}),\n };\n pendingResumeThreadId = undefined;\n turn.sendStart(() => channel.send(startMessage));\n\n return turn.control;\n },\n doContinueTurn: async continueOpts => {\n if (\n continueOpts.responseFormat?.type === 'json' &&\n continueOpts.responseFormat.schema == null\n ) {\n throw new HarnessCapabilityUnsupportedError({\n message:\n \"Harness 'codex' requires a JSON schema for structured output.\",\n harnessId: 'codex',\n });\n }\n const tools = (continueOpts.tools ?? []).map(t => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n }));\n const { restartThread } = await synchronizeTurnConfiguration({\n skills: continueOpts.skills,\n instructions: continueOpts.instructions,\n tools,\n abortSignal: continueOpts.abortSignal,\n });\n const turn = wireTurn({\n emit: continueOpts.emit,\n abortSignal: continueOpts.abortSignal,\n });\n\n /*\n * attach / replay: the still-running (or disk-replayed) turn streams into\n * the wired listeners — `doStart` opened the channel with `{ resume: true }`\n * so the bridge replays everything past the persisted cursor (including a\n * `finish` if the turn ended during the gap). No `start` is sent: issuing\n * one would clear the bridge's replay log and begin a new turn. Lossless.\n *\n * rerun: the bridge was respawned with no in-flight turn to attach to, so\n * re-drive codex's own thread via `resumeThreadId`. Lossy — work in flight\n * at the suspension is recomputed. This is the rare bridge-died\n * fallback; the common slice path is `attach`.\n */\n if (rerunContinue) {\n const threadId = pendingResumeThreadId ?? latestThreadId;\n pendingResumeThreadId = undefined;\n turn.sendStart(() =>\n channel.send({\n type: 'start' as const,\n /*\n * A continuation nudge rather than an empty prompt: `resumeThreadId`\n * rehydrates the prior thread, and this is the new user turn that\n * drives it forward. Keeping it non-empty avoids handing the runtime\n * an empty user message (and mirrors the claude-code adapter, where an\n * empty text block trips the Anthropic API's `cache_control` rule).\n */\n prompt: 'Continue.',\n tools,\n ...(continueOpts.responseFormat == null\n ? {}\n : { responseFormat: continueOpts.responseFormat }),\n ...(continueOpts.instructions\n ? { instructions: continueOpts.instructions }\n : {}),\n model: continueOpts.model ?? model,\n reasoningEffort,\n webSearch,\n ...(codexConfig == null ? {} : { codexConfig }),\n ...(mcpServers == null ? {} : { mcpServers }),\n ...(headers == null ? {} : { headers }),\n ...(permissionMode ? { permissionMode } : {}),\n ...(threadId ? { resumeThreadId: threadId } : {}),\n ...(restartThread ? { restartThread: true } : {}),\n ...(debug ? { debug } : {}),\n }),\n );\n }\n\n return turn.control;\n },\n doCompact: async () => {\n /*\n * Codex compacts its context automatically inside the core turn loop\n * (~90% of the model context window), but the `codex exec` transport this\n * adapter drives exposes no manual compaction trigger and emits no\n * compaction event. Manual `compact()` is therefore unsupported; Codex's\n * own auto-compaction continues to run regardless.\n */\n throw new HarnessCapabilityUnsupportedError({\n message:\n \"Harness 'codex' does not support manual compaction; Codex auto-compacts its context internally.\",\n harnessId: 'codex',\n });\n },\n doDetach: async () => {\n if (stopped) {\n throw new Error(\n `codex session ${sessionId} is already stopped; cannot detach.`,\n );\n }\n stopped = true;\n const lastSeenEventId = await channel.suspend();\n const payload: HarnessV1ResumeSessionState = {\n type: 'resume-session',\n harnessId: 'codex',\n specificationVersion: 'harness-v1',\n data: {\n ...(latestThreadId ? { threadId: latestThreadId } : {}),\n ...(latestTurnConfigurationFingerprint\n ? {\n turnConfigurationFingerprint:\n latestTurnConfigurationFingerprint,\n }\n : {}),\n ...(sandboxCredentialEnvironment == null\n ? {}\n : { sandboxCredentialEnvironment }),\n bridge: {\n port: bridgePort,\n token: bridgeToken,\n lastSeenEventId,\n ...(sandboxId == null ? {} : { sandboxId }),\n },\n },\n };\n return payload;\n },\n doDestroy: async () => {\n if (stopped) return stopPromise;\n stopped = true;\n stopPromise = (async () => {\n // Tell the channel we are tearing down so the bridge's post-shutdown\n // socket close finalises instead of triggering a reconnect.\n channel.beginClose();\n try {\n if (!channel.isClosed()) {\n channel.send({ type: 'destroy' });\n }\n } catch {}\n let stopTimer: ReturnType<typeof setTimeout> | undefined;\n try {\n if (proc) {\n await Promise.race([\n proc.wait(),\n new Promise<void>(resolve => {\n stopTimer = setTimeout(resolve, 5000);\n stopTimer.unref?.();\n }),\n ]);\n }\n } finally {\n if (stopTimer) clearTimeout(stopTimer);\n try {\n await proc?.kill();\n } catch {}\n channel.close();\n }\n })();\n return stopPromise;\n },\n doStop: async () => {\n if (stopped) {\n throw new Error(\n `codex session ${sessionId} is already stopped; cannot stop.`,\n );\n }\n stopped = true;\n /*\n * If the bridge's channel already closed (e.g. mid-turn WS drop)\n * there is no one to acknowledge a `stop` message. Synthesize an empty\n * payload — the workdir is still captured by the sandbox snapshot\n * during the subsequent `sandboxSession.stop()`, so the next turn can\n * resume the filesystem state. The trade-off: we lose\n * `threadId`, so the codex CLI starts a fresh thread on the\n * preserved workdir rather than resuming the prior conversation\n * inside Codex's runtime. Ability to continue beats throwing.\n */\n // Tell the channel we are tearing down so the bridge's post-stop\n // socket close finalises instead of triggering a reconnect.\n channel.beginClose();\n const data: unknown = channel.isClosed()\n ? {}\n : await new Promise<unknown>((resolve, reject) => {\n const timer = setTimeout(() => {\n unsub();\n reject(\n new Error(\n `codex session ${sessionId} did not reply to stop within 5s.`,\n ),\n );\n }, 5000);\n timer.unref?.();\n const unsub = channel.on('bridge-stop', msg => {\n clearTimeout(timer);\n unsub();\n resolve(msg.data);\n });\n try {\n channel.send({ type: 'stop' });\n } catch (err) {\n clearTimeout(timer);\n unsub();\n reject(err);\n }\n });\n\n let stopTimer: ReturnType<typeof setTimeout> | undefined;\n try {\n if (proc) {\n await Promise.race([\n proc.wait(),\n new Promise<void>(resolve => {\n stopTimer = setTimeout(resolve, 5000);\n stopTimer.unref?.();\n }),\n ]);\n }\n } finally {\n if (stopTimer) clearTimeout(stopTimer);\n try {\n await proc?.kill();\n } catch {}\n channel.close();\n }\n\n const lifecycleData =\n data != null && typeof data === 'object' && !Array.isArray(data)\n ? { ...(data as Record<string, unknown>) }\n : {};\n const payload: HarnessV1ResumeSessionState = {\n type: 'resume-session',\n harnessId: 'codex',\n specificationVersion: 'harness-v1',\n data: {\n ...lifecycleData,\n ...(latestTurnConfigurationFingerprint\n ? {\n turnConfigurationFingerprint:\n latestTurnConfigurationFingerprint,\n }\n : {}),\n ...(sandboxCredentialEnvironment == null\n ? {}\n : { sandboxCredentialEnvironment }),\n } as HarnessV1ResumeSessionState['data'],\n };\n return payload;\n },\n doSuspendTurn: async () => {\n if (stopped) {\n throw new Error(\n `codex session ${sessionId} is stopped; cannot suspend.`,\n );\n }\n stopped = true;\n /*\n * Freeze the host at a precise cursor without stopping the active model\n * turn. `channel.suspend` stops processing inbound frames, drains what\n * was already dispatched, then closes the host socket with reason\n * `'suspended'`. The bridge keeps the turn running and accumulates events\n * past the cursor for the next slice to replay. The sandbox process is\n * deliberately left alive.\n */\n const lastSeenEventId = await channel.suspend();\n const payload: HarnessV1ContinueTurnState = {\n type: 'continue-turn',\n harnessId: 'codex',\n specificationVersion: 'harness-v1',\n data: {\n ...(latestThreadId ? { threadId: latestThreadId } : {}),\n ...(latestTurnConfigurationFingerprint\n ? {\n turnConfigurationFingerprint:\n latestTurnConfigurationFingerprint,\n }\n : {}),\n ...(sandboxCredentialEnvironment == null\n ? {}\n : { sandboxCredentialEnvironment }),\n bridge: {\n port: bridgePort,\n token: bridgeToken,\n lastSeenEventId,\n ...(sandboxId == null ? {} : { sandboxId }),\n },\n },\n };\n return payload;\n },\n };\n}\n\nfunction fingerprintCodexTurnConfiguration({\n instructions,\n tools,\n}: {\n instructions: string | undefined;\n tools: ReadonlyArray<{\n name: string;\n description?: string;\n inputSchema: unknown;\n }>;\n}): string {\n return createHash('sha256')\n .update(JSON.stringify({ instructions: instructions ?? null, tools }))\n .digest('hex');\n}\n\n/*\n * Frame host-tool relay guidance and the user's text so Codex treats the\n * prepended block as operating guidance rather than user prose. Applied only\n * to the first user message of a fresh session.\n */\nfunction frameInitialPromptGuidance({\n toolUsageBlock,\n userText,\n}: {\n toolUsageBlock: string | undefined;\n userText: string;\n}): string {\n const blocks: string[] = [];\n if (toolUsageBlock) blocks.push(toolUsageBlock);\n if (blocks.length === 0) return userText;\n return `${blocks.join('\\n\\n')}\\n\\n<user-message>\\n${userText}\\n</user-message>`;\n}\n\nfunction composeToolUsageInstructions({\n tools,\n cliShimPath,\n}: {\n tools: ReadonlyArray<{\n name: string;\n description?: string;\n inputSchema?: unknown;\n }>;\n cliShimPath: string;\n}): string {\n const lines: string[] = [\n '<host-tool-instructions>',\n 'You have access to the following host-provided tools. To use one, run the following command via your built-in `bash` tool:',\n '',\n ` node ${cliShimPath} <toolName> '<jsonInput>'`,\n '',\n 'The script prints the JSON result to stdout. Do not invent another way to call these tools — only this CLI invocation will work. Pass the JSON input as a single-quoted argument.',\n 'For every user request that depends on a host-provided tool, run a separate CLI invocation for each needed tool call in the current turn before answering. Do not reuse previous tool results, and do not say you used a host tool unless the command has completed in the current turn.',\n '',\n ];\n for (const toolSpec of tools) {\n lines.push(\n `- **${toolSpec.name}**${toolSpec.description ? ': ' + toolSpec.description : ''}`,\n );\n lines.push(\n ` - Input schema: \\`${JSON.stringify(toolSpec.inputSchema ?? {})}\\``,\n );\n }\n lines.push('</host-tool-instructions>');\n return lines.join('\\n');\n}\n\n/*\n * Reduce a `HarnessV1Prompt` to the plain user text the bridge forwards\n * to the Codex SDK. File and image parts on the message are not yet\n * supported by the underlying runtime — throw rather than silently drop\n * them so callers learn about the gap instead of seeing mysteriously\n * truncated prompts.\n */\nfunction extractUserText(prompt: HarnessV1Prompt): string {\n if (typeof prompt === 'string') return prompt;\n const { content } = prompt;\n if (typeof content === 'string') return content;\n const parts: string[] = [];\n for (const part of content) {\n if (part.type !== 'text') {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'codex',\n message: `The codex harness does not yet support user message parts of type '${part.type}'. Pass a string or a user message whose content contains only text parts.`,\n });\n }\n parts.push(part.text);\n }\n return parts.join('\\n\\n');\n}\n","import type { HarnessV1Bootstrap } from '@ai-sdk/harness';\nimport { createReadBridgeAsset } from '@ai-sdk/harness/utils';\n\nconst readBridgeAsset = createReadBridgeAsset({\n resolveAssetUrl: name => new URL(`./bridge/${name}`, import.meta.url),\n});\n\n/*\n * Bootstrap is derived state stored under the sandbox's default working\n * directory so snapshot-capable providers can preserve the installed CLI,\n * bridge, and recipe marker without requiring root filesystem access.\n *\n * The session work dir (`startOpts.sessionWorkDir`) lives under the sandbox's\n * default working directory — the provider's persistent mount — so any files\n * the agent edits survive both detach -> attach and stop -> snapshot -> resume\n * cycles. Harness infra derived from `sandboxSession.defaultWorkingDirectory`\n * lives under `.agent-runs`, outside the agent workdir.\n */\nexport const CODEX_BOOTSTRAP_DIR = '.harness-bootstrap/codex';\n\nlet cachedBootstrap: HarnessV1Bootstrap | undefined;\n\nexport async function getCodexBootstrap(): Promise<HarnessV1Bootstrap> {\n if (cachedBootstrap != null) return cachedBootstrap;\n const [pkg, lock, bridge] = await Promise.all([\n readBridgeAsset('package.json'),\n readBridgeAsset('pnpm-lock.yaml'),\n readBridgeAsset('index.mjs'),\n ]);\n cachedBootstrap = {\n harnessId: 'codex',\n bootstrapDir: CODEX_BOOTSTRAP_DIR,\n files: [\n { path: `${CODEX_BOOTSTRAP_DIR}/package.json`, content: pkg },\n { path: `${CODEX_BOOTSTRAP_DIR}/pnpm-lock.yaml`, content: lock },\n { path: `${CODEX_BOOTSTRAP_DIR}/bridge.mjs`, content: bridge },\n ],\n commands: [\n {\n command: 'pnpm install --frozen-lockfile --store-dir .pnpm-store',\n },\n ],\n };\n return cachedBootstrap;\n}\n","import type {\n HarnessV1Authentication,\n HarnessV1RequestTransformation,\n HarnessV1RequestTransformationSources,\n} from '@ai-sdk/harness';\nimport {\n createCredentialRequestTransformation,\n getAiGatewayAuthFromEnv,\n isHarnessAuthenticationEnvironment,\n} from '@ai-sdk/harness/utils';\n\nconst DEFAULT_AI_GATEWAY_BASE_URL = 'https://ai-gateway.vercel.sh/v1';\nexport const DEFAULT_OPENAI_BASE_URL = 'https://api.openai.com/v1';\n\nexport const CODEX_CREDENTIAL_ENVIRONMENT_VARIABLES = [\n 'AI_GATEWAY_API_KEY',\n 'CODEX_API_KEY',\n] as const;\n\nexport function createCodexRequestTransformations({\n env: environment,\n sandboxEnv: sandboxEnvironment,\n auth: authenticationMode,\n}: HarnessV1RequestTransformationSources<CodexResolvedAuthenticationMode>): HarnessV1RequestTransformation[] {\n if (!environment.CODEX_API_KEY || !sandboxEnvironment.CODEX_API_KEY) {\n return [];\n }\n return [\n createCredentialRequestTransformation({\n matchUrl:\n environment.OPENAI_BASE_URL ??\n (authenticationMode === 'ai-gateway'\n ? DEFAULT_AI_GATEWAY_BASE_URL\n : DEFAULT_OPENAI_BASE_URL),\n matchHeaders: {\n Authorization: `Bearer ${sandboxEnvironment.CODEX_API_KEY}`,\n },\n transformHeaders: {\n Authorization: `Bearer ${environment.CODEX_API_KEY}`,\n },\n }),\n ];\n}\n\nexport type CodexResolvedAuthenticationMode = 'direct' | 'ai-gateway';\n\nexport type CodexAuthenticationMode = HarnessV1Authentication;\n\n/**\n * Resolve the environment-variable blob the codex bridge needs. Precedence:\n *\n * 1. An explicit authentication mode pins the selected route.\n * 2. Auto-detect from the host process env: gateway first\n * (`AI_GATEWAY_API_KEY` / `VERCEL_OIDC_TOKEN`), then `CODEX_API_KEY` /\n * `OPENAI_API_KEY`.\n */\nexport function resolveCodexEnv(\n auth: CodexAuthenticationMode | undefined,\n processEnv: Record<string, string | undefined> = process.env,\n): Record<string, string> {\n const suppliedEnvironment = isHarnessAuthenticationEnvironment(auth);\n const authenticationEnvironment = suppliedEnvironment ? auth : processEnv;\n if (auth === 'direct') {\n return pickOpenAI({ processEnv: authenticationEnvironment });\n }\n\n const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({\n env: authenticationEnvironment,\n });\n if (auth === 'ai-gateway' || gatewayAuthFromEnv.apiKey) {\n return pickGateway({ gatewayAuthFromEnv });\n }\n return pickOpenAI({ processEnv: authenticationEnvironment });\n}\n\nexport function resolveCodexAuthenticationMode(\n auth: CodexAuthenticationMode | undefined,\n processEnv: Record<string, string | undefined> = process.env,\n): CodexResolvedAuthenticationMode {\n if (isHarnessAuthenticationEnvironment(auth)) {\n return getAiGatewayAuthFromEnv({ env: auth }).apiKey\n ? 'ai-gateway'\n : 'direct';\n }\n if (auth === 'direct') {\n return 'direct';\n }\n if (auth === 'ai-gateway') {\n return 'ai-gateway';\n }\n return getAiGatewayAuthFromEnv({ env: processEnv }).apiKey\n ? 'ai-gateway'\n : 'direct';\n}\n\nfunction pickOpenAI({\n processEnv,\n}: {\n processEnv: Record<string, string | undefined>;\n}): Record<string, string> {\n const env: Record<string, string> = {};\n const apiKey = processEnv.OPENAI_API_KEY ?? processEnv.CODEX_API_KEY;\n if (apiKey) env.CODEX_API_KEY = apiKey;\n const baseUrl = processEnv.OPENAI_BASE_URL;\n if (baseUrl) env.OPENAI_BASE_URL = baseUrl;\n const organization = processEnv.OPENAI_ORGANIZATION;\n if (organization) env.OPENAI_ORGANIZATION = organization;\n const project = processEnv.OPENAI_PROJECT;\n if (project) env.OPENAI_PROJECT = project;\n return env;\n}\n\nfunction pickGateway({\n gatewayAuthFromEnv,\n}: {\n gatewayAuthFromEnv: ReturnType<typeof getAiGatewayAuthFromEnv>;\n}): Record<string, string> {\n const apiKey = gatewayAuthFromEnv.apiKey;\n const baseUrl = toCodexGatewayBaseUrl(gatewayAuthFromEnv.baseUrl);\n const env: Record<string, string> = {};\n if (apiKey) {\n env.AI_GATEWAY_API_KEY = apiKey;\n env.CODEX_API_KEY = apiKey;\n }\n env.AI_GATEWAY_BASE_URL = baseUrl;\n env.OPENAI_BASE_URL = baseUrl;\n return env;\n}\n\nfunction toCodexGatewayBaseUrl(baseUrl: string): string {\n const trimmed = baseUrl.replace(/\\/+$/, '');\n return trimmed.endsWith('/v1') ? trimmed : `${trimmed}/v1`;\n}\n","import { spawn } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport {\n chmod,\n mkdir,\n readFile,\n realpath,\n rename,\n writeFile,\n} from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, join, resolve } from 'node:path';\nimport type {\n HarnessV1RequestTransformation,\n HarnessV1RequestTransformationSources,\n} from '@ai-sdk/harness';\nimport {\n getJwtExpiresAt,\n isAccessTokenExpiringSoon,\n isHarnessAuthenticationEnvironment,\n isLinux,\n isMacOS,\n isWindows,\n readLinuxSecretServicePassword,\n readMacOSKeychainPassword,\n readWindowsCredentialManagerPassword,\n refreshOAuthAccessToken,\n shouldResolveNativeSubscription,\n} from '@ai-sdk/harness/utils';\nimport { isRecord, safeParseJSON } from '@ai-sdk/provider-utils';\nimport {\n createCodexRequestTransformations,\n resolveCodexEnv,\n type CodexAuthenticationMode,\n type CodexResolvedAuthenticationMode,\n} from './codex-auth';\n\nconst CHATGPT_CODEX_BASE_URL = 'https://chatgpt.com/backend-api/codex';\nconst OPENAI_TOKEN_URL = 'https://auth.openai.com/oauth/token';\nconst OPENAI_CLIENT_ID = 'app_EMoamEEZ73f0CkXaXp7hrann';\n\nexport type CodexResolvedAuthentication = {\n readonly environment: Record<string, string>;\n readonly requestHeaders?: Readonly<Record<string, string>>;\n};\n\nexport function createCodexSubscriptionRequestTransformations({\n requestHeaders,\n ...sources\n}: HarnessV1RequestTransformationSources<CodexResolvedAuthenticationMode> & {\n requestHeaders?: Readonly<Record<string, string>>;\n}): HarnessV1RequestTransformation[] {\n const transformations = createCodexRequestTransformations(sources);\n if (requestHeaders == null) return transformations;\n\n return transformations.map(transformation => ({\n ...transformation,\n transform: {\n ...transformation.transform,\n headers: {\n ...transformation.transform.headers,\n ...requestHeaders,\n },\n },\n }));\n}\n\ntype CodexAuthCredentialsStoreMode = 'file' | 'keyring' | 'auto' | 'ephemeral';\n\ntype CodexKeyring = {\n read(options: {\n service: string;\n account: string;\n }): Promise<string | undefined>;\n write(options: {\n service: string;\n account: string;\n value: string;\n }): Promise<void>;\n};\n\ntype CodexAuthFile = {\n readonly auth_mode?: unknown;\n readonly tokens?: {\n readonly access_token?: unknown;\n readonly refresh_token?: unknown;\n readonly account_id?: unknown;\n };\n readonly [key: string]: unknown;\n};\n\nexport async function resolveCodexAuthentication({\n auth,\n processEnv = process.env,\n authCredentialsStoreMode,\n readSubscription = readCodexSubscription,\n}: {\n auth: CodexAuthenticationMode | undefined;\n processEnv?: Record<string, string | undefined>;\n authCredentialsStoreMode?: unknown;\n readSubscription?: (options?: {\n authCredentialsStoreMode?: unknown;\n }) => Promise<CodexResolvedAuthentication | undefined>;\n}): Promise<CodexResolvedAuthentication> {\n const environment = resolveCodexEnv(auth, processEnv);\n if (isHarnessAuthenticationEnvironment(auth)) {\n return { environment };\n }\n if (\n !shouldResolveNativeSubscription({\n auth,\n env: environment,\n hasDirectCredential: environment.CODEX_API_KEY != null,\n })\n ) {\n return { environment };\n }\n\n return (\n (await readSubscription({ authCredentialsStoreMode })) ?? { environment }\n );\n}\n\nexport async function readCodexSubscription({\n env = process.env,\n homeDirectory = homedir(),\n authCredentialsStoreMode,\n platform = process.platform,\n keyring,\n fetch,\n}: {\n env?: Record<string, string | undefined>;\n homeDirectory?: string;\n authCredentialsStoreMode?: unknown;\n platform?: NodeJS.Platform;\n keyring?: CodexKeyring;\n fetch?: typeof globalThis.fetch;\n} = {}): Promise<CodexResolvedAuthentication | undefined> {\n const codexHome = resolve(env.CODEX_HOME ?? join(homeDirectory, '.codex'));\n const authPath = join(codexHome, 'auth.json');\n const storageMode =\n toCodexAuthCredentialsStoreMode(authCredentialsStoreMode) ??\n (await readCodexAuthCredentialsStoreMode({ codexHome })) ??\n 'file';\n const stored = await readCodexAuthStore({\n codexHome,\n authPath,\n storageMode,\n keyring: keyring ?? createCodexKeyring({ platform }),\n });\n if (stored == null) return undefined;\n\n const credential = await toCodexCredential(stored.value);\n if (credential == null) return undefined;\n\n let accessToken = credential.accessToken;\n if (isAccessTokenExpiringSoon({ expiresAt: credential.expiresAt })) {\n const refreshed = await refreshOAuthAccessToken({\n tokenUrl: OPENAI_TOKEN_URL,\n clientId: OPENAI_CLIENT_ID,\n refreshToken: credential.refreshToken,\n requestFormat: 'json',\n ...(fetch == null ? {} : { fetch }),\n });\n accessToken = refreshed.accessToken;\n await stored.write({\n ...stored.value,\n last_refresh: new Date().toISOString(),\n tokens: {\n ...stored.value.tokens,\n access_token: refreshed.accessToken,\n refresh_token: refreshed.refreshToken ?? credential.refreshToken,\n },\n });\n }\n\n return {\n environment: {\n CODEX_API_KEY: accessToken,\n OPENAI_BASE_URL: CHATGPT_CODEX_BASE_URL,\n },\n ...(credential.accountId == null\n ? {}\n : {\n requestHeaders: {\n 'ChatGPT-Account-ID': credential.accountId,\n },\n }),\n };\n}\n\nasync function readCodexAuthStore({\n codexHome,\n authPath,\n storageMode,\n keyring,\n}: {\n codexHome: string;\n authPath: string;\n storageMode: CodexAuthCredentialsStoreMode;\n keyring: CodexKeyring | undefined;\n}): Promise<\n | {\n value: CodexAuthFile;\n write(value: CodexAuthFile): Promise<void>;\n }\n | undefined\n> {\n if (storageMode === 'ephemeral') return undefined;\n\n const readFileStore = async () => {\n const value = await readCodexAuthFile(authPath);\n return value == null\n ? undefined\n : {\n value,\n write: (updated: CodexAuthFile) =>\n writeCodexAuthFile({ authPath, value: updated }),\n };\n };\n const readKeyringStore = async () => {\n if (keyring == null) return undefined;\n const canonicalHome = await realpath(codexHome).catch(() => codexHome);\n const account = `cli|${createHash('sha256')\n .update(canonicalHome)\n .digest('hex')\n .slice(0, 16)}`;\n const text = await keyring.read({ service: 'Codex Auth', account });\n if (text == null) return undefined;\n const value = await parseCodexAuthFile(text);\n return value == null\n ? undefined\n : {\n value,\n write: (updated: CodexAuthFile) =>\n keyring.write({\n service: 'Codex Auth',\n account,\n value: JSON.stringify(updated),\n }),\n };\n };\n\n if (storageMode === 'file') return readFileStore();\n if (storageMode === 'keyring') return readKeyringStore();\n return (await readKeyringStore()) ?? readFileStore();\n}\n\nasync function readCodexAuthCredentialsStoreMode({\n codexHome,\n}: {\n codexHome: string;\n}): Promise<CodexAuthCredentialsStoreMode | undefined> {\n const text = await readFile(join(codexHome, 'config.toml'), 'utf8').catch(\n () => undefined,\n );\n if (text == null) return undefined;\n for (const line of text.split(/\\r?\\n/)) {\n if (line.trimStart().startsWith('[')) return undefined;\n const match =\n /^\\s*cli_auth_credentials_store\\s*=\\s*[\"'](file|keyring|auto|ephemeral)[\"']\\s*(?:#.*)?$/.exec(\n line,\n );\n if (match != null) {\n return toCodexAuthCredentialsStoreMode(match[1]);\n }\n }\n return undefined;\n}\n\nfunction toCodexAuthCredentialsStoreMode(\n value: unknown,\n): CodexAuthCredentialsStoreMode | undefined {\n return value === 'file' ||\n value === 'keyring' ||\n value === 'auto' ||\n value === 'ephemeral'\n ? value\n : undefined;\n}\n\nasync function readCodexAuthFile(\n authPath: string,\n): Promise<CodexAuthFile | undefined> {\n const text = await readFile(authPath, 'utf8').catch(() => undefined);\n return text == null ? undefined : parseCodexAuthFile(text);\n}\n\nasync function parseCodexAuthFile(\n text: string,\n): Promise<CodexAuthFile | undefined> {\n const parsed = await safeParseJSON({ text });\n return parsed.success && isRecord(parsed.value)\n ? (parsed.value as CodexAuthFile)\n : undefined;\n}\n\nasync function toCodexCredential(value: CodexAuthFile): Promise<\n | {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n accountId?: string;\n }\n | undefined\n> {\n if (value.auth_mode !== 'chatgpt' || !isRecord(value.tokens)) {\n return undefined;\n }\n const accessToken = value.tokens.access_token;\n const refreshToken = value.tokens.refresh_token;\n if (typeof accessToken !== 'string' || typeof refreshToken !== 'string') {\n return undefined;\n }\n const expiresAt = await getJwtExpiresAt({ token: accessToken });\n if (expiresAt == null) return undefined;\n const accountId = value.tokens.account_id;\n return {\n accessToken,\n refreshToken,\n expiresAt,\n ...(typeof accountId === 'string' ? { accountId } : {}),\n };\n}\n\nasync function writeCodexAuthFile({\n authPath,\n value,\n}: {\n authPath: string;\n value: CodexAuthFile;\n}): Promise<void> {\n await mkdir(dirname(authPath), { recursive: true });\n const temporaryPath = `${authPath}.${process.pid}.tmp`;\n await writeFile(temporaryPath, `${JSON.stringify(value, null, 2)}\\n`, {\n mode: 0o600,\n });\n await chmod(temporaryPath, 0o600);\n await rename(temporaryPath, authPath);\n}\n\nfunction createCodexKeyring({\n platform,\n}: {\n platform: NodeJS.Platform;\n}): CodexKeyring | undefined {\n if (isMacOS(platform)) {\n return {\n async read({ service, account }) {\n return readMacOSKeychainPassword({ service, account });\n },\n async write({ service, account, value }) {\n const command = `add-generic-password -U -s ${shellQuoteForSecurity(service)} -a ${shellQuoteForSecurity(account)} -X ${Buffer.from(value, 'utf8').toString('hex')}\\n`;\n await runCommandWithInput({\n command: '/usr/bin/security',\n args: ['-i'],\n input: command,\n });\n },\n };\n }\n if (isLinux(platform)) {\n return {\n async read({ service, account }) {\n return readLinuxSecretServicePassword({\n attributes: {\n service,\n username: account,\n target: 'default',\n },\n });\n },\n async write({ service, account, value }) {\n await runCommandWithInput({\n command: 'secret-tool',\n args: [\n 'store',\n '--label',\n `${account}@${service}:default`,\n 'service',\n service,\n 'username',\n account,\n 'target',\n 'default',\n 'application',\n 'rust-keyring',\n ],\n input: value,\n });\n },\n };\n }\n if (isWindows(platform)) {\n return createWindowsCodexKeyring();\n }\n return undefined;\n}\n\nfunction shellQuoteForSecurity(value: string): string {\n return `\"${value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n}\n\nasync function runCommandWithInput({\n command,\n args,\n input,\n env,\n}: {\n command: string;\n args: string[];\n input: string;\n env?: NodeJS.ProcessEnv;\n}): Promise<void> {\n await new Promise<void>((resolvePromise, reject) => {\n const child = spawn(command, args, {\n stdio: ['pipe', 'ignore', 'pipe'],\n ...(env == null ? {} : { env }),\n });\n let stderr = '';\n child.stderr.setEncoding('utf8');\n child.stderr.on('data', chunk => {\n stderr += chunk;\n });\n child.once('error', reject);\n child.once('close', code => {\n if (code === 0) resolvePromise();\n else reject(new Error(stderr || `${command} exited with code ${code}.`));\n });\n child.stdin.end(input);\n });\n}\n\nfunction createWindowsCodexKeyring(): CodexKeyring {\n const source = `\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Text;\npublic static class CodexCredentialManager {\n [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]\n public struct Credential {\n public UInt32 Flags; public UInt32 Type; public string TargetName;\n public string Comment; public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;\n public UInt32 CredentialBlobSize; public IntPtr CredentialBlob;\n public UInt32 Persist; public UInt32 AttributeCount; public IntPtr Attributes;\n public string TargetAlias; public string UserName;\n }\n [DllImport(\"advapi32.dll\", EntryPoint = \"CredWriteW\", CharSet = CharSet.Unicode, SetLastError = true)]\n static extern bool CredWrite(ref Credential credential, UInt32 flags);\n public static void Write(string target, string userName, string value) {\n byte[] bytes = Encoding.Unicode.GetBytes(value);\n IntPtr blob = Marshal.AllocHGlobal(bytes.Length);\n try {\n Marshal.Copy(bytes, 0, blob, bytes.Length);\n Credential credential = new Credential {\n Type = 1, TargetName = target, CredentialBlobSize = (UInt32)bytes.Length,\n CredentialBlob = blob, Persist = 3, UserName = userName\n };\n if (!CredWrite(ref credential, 0)) throw new System.ComponentModel.Win32Exception();\n } finally { Marshal.FreeHGlobal(blob); }\n }\n}`;\n return {\n async read({ service, account }) {\n return readWindowsCredentialManagerPassword({\n targetName: `${account}.${service}`,\n });\n },\n async write({ service, account, value }) {\n const script = `Add-Type -TypeDefinition $env:AI_SDK_CODEX_CREDENTIAL_SOURCE; $value = [Console]::In.ReadToEnd(); [CodexCredentialManager]::Write($env:AI_SDK_CODEX_CREDENTIAL_TARGET, $env:AI_SDK_CODEX_CREDENTIAL_USER, $value)`;\n await runCommandWithInput({\n command: 'powershell.exe',\n args: ['-NoProfile', '-NonInteractive', '-Command', script],\n input: value,\n env: {\n ...process.env,\n AI_SDK_CODEX_CREDENTIAL_SOURCE: source,\n AI_SDK_CODEX_CREDENTIAL_TARGET: `${account}.${service}`,\n AI_SDK_CODEX_CREDENTIAL_USER: account,\n },\n });\n },\n };\n}\n","import {\n harnessV1BridgeInboundCommandSchemas,\n harnessV1BridgeOutboundMessageSchema,\n harnessV1BridgeReadySchema,\n harnessV1BridgeStartBaseSchema,\n} from '@ai-sdk/harness';\nimport { z } from 'zod/v4';\n\n/*\n * Codex's bridge wire protocol. The outbound events (including `file-change`\n * and the `bridge-thread` resume coordinate), transport frames, shared inbound\n * commands, and `bridge-ready` line all come from the shared `@ai-sdk/harness`\n * protocol — the only Codex-specific piece is the `start` payload.\n */\n\nexport const outboundMessageSchema = harnessV1BridgeOutboundMessageSchema;\nexport type OutboundMessage = z.infer<typeof outboundMessageSchema>;\n\nexport const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({\n instructions: z.string().optional(),\n reasoningEffort: z.enum(['low', 'medium', 'high', 'xhigh', 'max']).optional(),\n webSearch: z.boolean().optional(),\n codexConfig: z.record(z.string(), z.unknown()).optional(),\n mcpServers: z.record(z.string(), z.unknown()).optional(),\n headers: z.record(z.string(), z.string()).optional(),\n // Resume signal. When supplied, the bridge calls\n // `codex.resumeThread(resumeThreadId, …)` instead of starting a fresh thread.\n // The host sources the id from lifecycle state `data` cached from a prior\n // `agent.detach`.\n resumeThreadId: z.string().optional(),\n restartThread: z.boolean().optional(),\n});\n\nexport type StartMessage = z.infer<typeof startMessageSchema>;\n\nexport const inboundMessageSchema = z.discriminatedUnion('type', [\n startMessageSchema,\n ...harnessV1BridgeInboundCommandSchemas,\n]);\nexport type InboundMessage = z.infer<typeof inboundMessageSchema>;\n\nexport const bridgeReadySchema = harnessV1BridgeReadySchema;\nexport type BridgeReady = z.infer<typeof bridgeReadySchema>;\n","/*\n * Temporary workaround for upstream codex CLI bug\n * https://github.com/openai/codex/issues/19425 — MCP tools registered via\n * `mcp_servers.*` are not exposed to the model in `codex exec --experimental-json`\n * mode (which is what `@openai/codex-sdk` uses). The MCP handshake completes\n * and `tools/list` succeeds, but codex never registers the tools as\n * model-callable functions.\n *\n * Until that's fixed upstream, this file implements a CLI-based relay:\n *\n * 1. A small Node script is written into harness-owned session state at turn\n * start (`buildCliShimScript`). It accepts `<toolName> <jsonInput>` as\n * argv, POSTs to the same HTTP relay the MCP shim uses, and prints the\n * result to stdout.\n *\n * 2. Tool descriptions and invocation instructions are injected into the\n * initial user prompt by the host adapter, telling the model to call host\n * tools by running `node <shim-path> <toolName> '<jsonInput>'` via its\n * built-in `bash` tool.\n *\n * 3. The bridge's event loop suppresses the matching `command_execution`\n * events (`isToolRelayCommand`) so callers receive clean `tool-call` /\n * `tool-result` events from the HTTP relay rather than seeing the\n * relay invocations as raw bash commands.\n *\n * Once #19425 is fixed and MCP tools are properly exposed in exec mode, the\n * three hookpoints in `bridge/index.ts` can be removed along with this file.\n */\nexport const CLI_SHIM_FILENAME = 'harness-tool.mjs';\n\nexport function buildCliShimScript({\n relayPort,\n}: {\n relayPort: number;\n}): string {\n return `#!/usr/bin/env node\nconst [toolName, inputJson = '{}'] = process.argv.slice(2);\nif (!toolName) {\n console.error('Usage: harness-tool <tool_name> <json_input>');\n process.exit(64);\n}\nlet input;\ntry {\n input = JSON.parse(inputJson);\n} catch (error) {\n console.error('Invalid JSON input: ' + (error instanceof Error ? error.message : String(error)));\n process.exit(64);\n}\nconst requestId = 'cli-' + Date.now() + '-' + Math.random().toString(16).slice(2);\nconst response = await fetch('http://127.0.0.1:${relayPort}', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ requestId, toolName, input }),\n});\nconst text = await response.text();\nlet payload;\ntry {\n payload = text ? JSON.parse(text) : {};\n} catch {\n payload = { error: text };\n}\nif (!response.ok || payload.error) {\n console.error(String(payload.error ?? ('tool relay failed with HTTP ' + response.status)));\n process.exit(1);\n}\nconsole.log(JSON.stringify(payload.result ?? payload, null, 2));\n`;\n}\n\nexport function isToolRelayCommand({\n command,\n cliShimPath,\n}: {\n command: string;\n cliShimPath: string;\n}): boolean {\n return parseToolRelayCommands({ command, cliShimPath }) !== undefined;\n}\n\nexport function parseToolRelayCommand({\n command,\n cliShimPath,\n}: {\n command: string;\n cliShimPath: string;\n}): { toolName: string; input: unknown } | undefined {\n const calls = parseToolRelayCommands({ command, cliShimPath });\n return calls?.length === 1 ? calls[0] : undefined;\n}\n\nexport function parseToolRelayCommands({\n command,\n cliShimPath,\n}: {\n command: string;\n cliShimPath: string;\n}): Array<{ toolName: string; input: unknown }> | undefined {\n return parseToolRelayCommandsInternal({ command, cliShimPath, depth: 0 });\n}\n\nfunction parseToolRelayCommandsInternal({\n command,\n cliShimPath,\n depth,\n}: {\n command: string;\n cliShimPath: string;\n depth: number;\n}): Array<{ toolName: string; input: unknown }> | undefined {\n const commands = splitShellAndCommands(command);\n if (!commands) return undefined;\n if (commands.length > 1) {\n const relayCalls: Array<{ toolName: string; input: unknown }> = [];\n for (const nestedCommand of commands) {\n const nestedCalls = parseToolRelayCommandsInternal({\n command: nestedCommand,\n cliShimPath,\n depth,\n });\n if (!nestedCalls) return undefined;\n relayCalls.push(...nestedCalls);\n }\n return relayCalls;\n }\n\n const argv = parseShellWords(command);\n if (!argv) return undefined;\n\n const relayCall = parseDirectToolRelayArgv({ argv, cliShimPath });\n if (relayCall) return [relayCall];\n\n const innerCommand = extractShellEvalCommand(argv);\n if (!innerCommand || depth >= 2) return undefined;\n return parseToolRelayCommandsInternal({\n command: innerCommand,\n cliShimPath,\n depth: depth + 1,\n });\n}\n\nfunction parseDirectToolRelayArgv({\n argv,\n cliShimPath,\n}: {\n argv: string[];\n cliShimPath: string;\n}): { toolName: string; input: unknown } | undefined {\n if (argv.length < 3 || argv.length > 4) return undefined;\n if (argv[0] !== 'node' || argv[1] !== cliShimPath) return undefined;\n const toolName = argv[2];\n if (!toolName) return undefined;\n try {\n return { toolName, input: JSON.parse(argv[3] ?? '{}') };\n } catch {\n return undefined;\n }\n}\n\nfunction extractShellEvalCommand(argv: string[]): string | undefined {\n if (argv.length !== 3) return undefined;\n const shellName = argv[0].split('/').at(-1);\n if (shellName !== 'bash' && shellName !== 'sh' && shellName !== 'zsh') {\n return undefined;\n }\n if (argv[1] !== '-c' && argv[1] !== '-lc') return undefined;\n return argv[2];\n}\n\nfunction splitShellAndCommands(command: string): string[] | undefined {\n const commands: string[] = [];\n let start = 0;\n let quote: '\"' | \"'\" | undefined;\n\n for (let i = 0; i < command.length; i++) {\n const char = command[i];\n if (quote === \"'\") {\n if (char === \"'\") quote = undefined;\n continue;\n }\n if (quote === '\"') {\n if (char === '\"') {\n quote = undefined;\n } else if (char === '\\\\') {\n i++;\n }\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n continue;\n }\n if (char === '\\\\') {\n i++;\n continue;\n }\n if (char === '&' && command[i + 1] === '&') {\n const nestedCommand = command.slice(start, i).trim();\n if (!nestedCommand) return undefined;\n commands.push(nestedCommand);\n start = i + 2;\n i++;\n }\n }\n\n if (quote) return undefined;\n const nestedCommand = command.slice(start).trim();\n if (!nestedCommand) return undefined;\n commands.push(nestedCommand);\n return commands;\n}\n\nfunction parseShellWords(command: string): string[] | undefined {\n const words: string[] = [];\n let current = '';\n let quote: '\"' | \"'\" | undefined;\n let hasCurrent = false;\n\n const pushCurrent = () => {\n if (!hasCurrent) return;\n words.push(current);\n current = '';\n hasCurrent = false;\n };\n\n for (let i = 0; i < command.length; i++) {\n const char = command[i];\n if (quote === \"'\") {\n if (char === \"'\") {\n quote = undefined;\n } else {\n current += char;\n }\n hasCurrent = true;\n continue;\n }\n if (quote === '\"') {\n if (char === '\"') {\n quote = undefined;\n } else if (char === '\\\\' && i + 1 < command.length) {\n current += command[++i];\n } else {\n current += char;\n }\n hasCurrent = true;\n continue;\n }\n if (/\\s/.test(char)) {\n pushCurrent();\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n hasCurrent = true;\n continue;\n }\n if (char === '\\\\' && i + 1 < command.length) {\n current += command[++i];\n hasCurrent = true;\n continue;\n }\n if (/[;&|<>()`$]/.test(char)) return undefined;\n current += char;\n hasCurrent = true;\n }\n if (quote) return undefined;\n pushCurrent();\n return words;\n}\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n","import { createCodex } from './codex-harness';\n\n/**\n * Default `codex` harness instance with no overrides — suitable for the\n * common case where the underlying `codex` CLI's defaults are fine.\n * Equivalent to `createCodex()`.\n */\nexport const codex = createCodex();\n\nexport { createCodex } from './codex-harness';\nexport { VERSION } from './version';\nexport type { CodexHarnessSettings } from './codex-harness';\nexport type { CodexAuthenticationMode } from './codex-auth';\n"],"mappings":"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","names":["createHash","z","isHarnessAuthenticationEnvironment","isHarnessAuthenticationEnvironment","z","endpoint","proc","resolve","createHash"]}
|
|
1
|
+
{"version":3,"sources":["../src/codex-harness.ts","../src/codex-bootstrap.ts","../src/codex-auth.ts","../src/codex-subscription.ts","../src/codex-bridge-protocol.ts","../src/bridge/cli-relay.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport path from 'node:path';\nimport {\n commonTool,\n HarnessCapabilityUnsupportedError,\n harnessV1DiagnosticFromBridgeFrame,\n type HarnessV1,\n type HarnessV1DebugConfig,\n type HarnessV1BuiltinTool,\n type HarnessV1ContinueTurnState,\n type HarnessV1CredentialForwarding,\n type HarnessV1MintBridgeTokenCallback,\n type HarnessV1Prompt,\n type HarnessV1PromptControl,\n type HarnessV1PortEndpoint,\n type HarnessV1ResumeSessionState,\n type HarnessV1NetworkSandboxSession,\n type HarnessV1PermissionMode,\n type HarnessV1Session,\n type HarnessV1Skill,\n type HarnessV1StreamPart,\n} from '@ai-sdk/harness';\nimport {\n applyCredentialForwarding,\n classifyDiskLog,\n createBridgeToken,\n createSandboxCredentialEnvironment,\n createBridgeErrorHandler,\n createBridgeStartupError,\n drainBridgeProcessStream,\n forwardBridgeProcessStream,\n getRestrictedSandboxSession,\n markBridgeStarting,\n resolveSandboxDefaultWorkingDirectory,\n resolveSandboxHomeDir,\n SandboxChannel,\n shellQuote,\n warnCredentialBrokeringUnavailable,\n waitForBridgeReady,\n withBridgeToken,\n writeSkills,\n type SandboxChannelReconnectOptions,\n} from '@ai-sdk/harness/utils';\nimport {\n type Experimental_SandboxProcess,\n type Experimental_SandboxSession as SandboxSession,\n} from '@ai-sdk/provider-utils';\nimport { WebSocket } from 'ws';\nimport { z } from 'zod/v4';\nimport {\n CODEX_BOOTSTRAP_DIR as BOOTSTRAP_DIR,\n getCodexBootstrap,\n} from './codex-bootstrap';\nimport {\n CODEX_CREDENTIAL_ENVIRONMENT_VARIABLES,\n DEFAULT_OPENAI_BASE_URL,\n resolveCodexAuthenticationMode,\n type CodexAuthenticationMode,\n} from './codex-auth';\nimport {\n createCodexSubscriptionRequestTransformations,\n resolveCodexAuthentication,\n} from './codex-subscription';\nimport {\n outboundMessageSchema,\n type InboundMessage,\n type OutboundMessage,\n} from './codex-bridge-protocol';\nimport { CLI_SHIM_FILENAME } from './bridge/cli-relay';\nimport { VERSION } from './version';\n\ntype CodexChannel = SandboxChannel<OutboundMessage, InboundMessage>;\ntype CodexRespawnStrategy = 'replay' | 'rerun';\n\n/*\n * This intentionally is not the latest Codex model. Newer GPT-5.6 models use\n * Responses Lite, which does not expose their code-mode tools as callable\n * through the custom model provider used by the harness. Keep GPT-5.5 as the\n * default until the upstream bug is resolved:\n * https://github.com/openai/codex/issues/31894\n *\n * Passing the model explicitly keeps the runtime behavior deterministic and\n * the telemetry (`gen_ai.request.model`) accurate.\n */\nconst DEFAULT_CODEX_MODEL = 'gpt-5.5';\n\n/**\n * Value to use in User-Agent and `x-client-app` headers.\n */\nconst CODEX_CLIENT_APP = `ai-sdk/harness-codex/${VERSION}`;\n\nexport type CodexHarnessSettings = {\n readonly auth?: CodexAuthenticationMode;\n /**\n * Customizes each credential value before it is forwarded into a sandbox\n * process. This does not restrict which credentials the harness adapter can\n * discover, read, or otherwise access in the host process.\n */\n readonly credentialForwarding?: HarnessV1CredentialForwarding;\n /**\n * Additional configuration passed through to Codex as-is. Codex config keys\n * typically use snake_case and must be provided in that form. Values managed\n * by this adapter take precedence over conflicting entries.\n */\n readonly codexConfig?: Record<string, unknown>;\n /**\n * MCP server definitions keyed by server name. Each definition uses the\n * underlying runtime's native MCP server configuration format.\n */\n readonly mcpServers?: Record<string, unknown>;\n /**\n * Reasoning effort for reasoning-capable models. Leaving this unset\n * defers to the CLI's default.\n */\n readonly reasoningEffort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max';\n /**\n * When `true`, allow the underlying runtime to use live web search.\n */\n readonly webSearch?: boolean;\n /**\n * Override the port the bridge binds inside the sandbox. By default the\n * adapter uses the first port the sandbox declares via `sandbox.ports`.\n * Only set this if the sandbox declares multiple ports and the first one\n * is reserved for something else.\n */\n readonly port?: number;\n /**\n * Override the host endpoint used to connect to the sandbox bridge. Required\n * together with `port` when using a basic sandbox session.\n */\n readonly portEndpoint?: HarnessV1PortEndpoint;\n /** Maximum milliseconds to wait for the bridge to advertise its port. Defaults to 120000. */\n readonly startupTimeoutMs?: number;\n /**\n * Configures reconnection attempts after an established bridge connection\n * drops. The reconnect window includes connection establishment and\n * backoff delays. Defaults to 30 seconds with exponential backoff from 50\n * milliseconds up to 2 seconds.\n */\n readonly reconnect?: SandboxChannelReconnectOptions;\n /**\n * Creates the authentication token used by the sandbox bridge. Defaults to\n * a random 32-byte hexadecimal token.\n */\n readonly mintBridgeToken?: HarnessV1MintBridgeTokenCallback;\n};\n\n/*\n * Every native tool the Codex CLI can invoke as a model-callable tool,\n * declared as a `ToolSet` keyed by what the bridge emits as `toolName` on\n * the wire (`commonName ?? nativeName`). Schemas reflect the `ThreadItem`\n * union in `@openai/codex-sdk`'s `dist/index.d.ts`.\n *\n * Codex's other native operations (`apply_patch`, todo planning) surface\n * only as side-effect events (`file_change`, `todo_list`) and are not\n * model-callable tools — they don't appear here.\n */\nconst CODEX_BUILTIN_TOOLS = {\n bash: commonTool('bash', {\n nativeName: 'shell',\n toolUseKind: 'bash',\n description: 'Execute a shell command',\n inputSchema: z.object({ command: z.string() }),\n }),\n webSearch: commonTool('webSearch', {\n nativeName: 'web_search',\n toolUseKind: 'readonly',\n description: 'Search the web',\n inputSchema: z.object({ query: z.string() }),\n }),\n} as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;\n\n/**\n * Live bridge coordinates returned by `doDetach()` and `doSuspendTurn()`. A\n * future process uses them to reopen a socket to the still-running bridge\n * (`attach`) instead of re-spawning it. Absent on a `doStop()` payload.\n */\nconst codexBridgeCoordsSchema = z.object({\n port: z.number(),\n token: z.string(),\n lastSeenEventId: z.number(),\n sandboxId: z.string().optional(),\n});\n\n/**\n * Schema for the adapter-specific lifecycle `data` payload Codex produces.\n * `threadId` is what `codex.resumeThread(...)` requires for the replay/rerun\n * rungs; the sandbox lookup is handled separately via\n * `provider.resumeSession({ sessionId })`. `bridge` carries live coordinates\n * for cross-process `attach` (present on `doDetach()` and `doSuspendTurn()`\n * payloads).\n */\nconst codexResumeStateSchema = z.object({\n threadId: z.string().optional(),\n turnConfigurationFingerprint: z.string().optional(),\n bridge: codexBridgeCoordsSchema.optional(),\n sandboxCredentialEnvironment: z.record(z.string(), z.string()).optional(),\n});\n\ntype CodexBridgeCoords = z.infer<typeof codexBridgeCoordsSchema>;\n\nexport function createCodex(\n settings: CodexHarnessSettings = {},\n): HarnessV1<typeof CODEX_BUILTIN_TOOLS> {\n return {\n specificationVersion: 'harness-v1',\n harnessId: 'codex',\n builtinTools: CODEX_BUILTIN_TOOLS,\n supportsBuiltinToolApprovals: false,\n lifecycleStateSchema: codexResumeStateSchema,\n getBootstrap: getCodexBootstrap,\n doStart: async startOpts => {\n const model = DEFAULT_CODEX_MODEL;\n if (startOpts.builtinToolFiltering != null) {\n throw new HarnessCapabilityUnsupportedError({\n message:\n \"Harness 'codex' does not support built-in tool filtering controls.\",\n harnessId: 'codex',\n });\n }\n if (\n startOpts.permissionMode != null &&\n startOpts.permissionMode !== 'allow-all'\n ) {\n throw new HarnessCapabilityUnsupportedError({\n message:\n \"Harness 'codex' does not support built-in tool approval requests; use permissionMode: 'allow-all'.\",\n harnessId: 'codex',\n });\n }\n const sandboxSession = startOpts.sandboxSession;\n const toolSafeSandboxSession =\n getRestrictedSandboxSession(sandboxSession);\n const sandboxId = 'id' in sandboxSession ? sandboxSession.id : undefined;\n validateBasicSandboxSettings({\n sandboxSession,\n port: settings.port,\n portEndpoint: settings.portEndpoint,\n });\n if (settings.mintBridgeToken != null && sandboxId == null) {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'codex',\n message:\n 'The codex harness cannot use `mintBridgeToken` with a sandbox session that does not expose an id.',\n });\n }\n const defaultWorkingDirectory =\n await resolveSandboxDefaultWorkingDirectory({\n sandboxSession,\n abortSignal: startOpts.abortSignal,\n });\n const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;\n const isResume = lifecycleState != null;\n const isContinue = startOpts.continueFrom != null;\n const resumeData =\n isResume && typeof lifecycleState?.data === 'object'\n ? (lifecycleState.data as {\n threadId?: unknown;\n turnConfigurationFingerprint?: unknown;\n bridge?: CodexBridgeCoords;\n sandboxCredentialEnvironment?: Record<string, string>;\n })\n : undefined;\n const resumeThreadId = resumeData?.threadId;\n const resumeThreadIdString =\n typeof resumeThreadId === 'string' && resumeThreadId.length > 0\n ? resumeThreadId\n : undefined;\n const turnConfigurationFingerprint =\n typeof resumeData?.turnConfigurationFingerprint === 'string'\n ? resumeData.turnConfigurationFingerprint\n : undefined;\n const coords = resumeData?.bridge;\n const authenticationMode = resolveCodexAuthenticationMode(settings.auth);\n const resolvedAuthentication = await resolveCodexAuthentication({\n auth: settings.auth,\n authCredentialsStoreMode:\n settings.codexConfig?.cli_auth_credentials_store,\n });\n const resolvedAuthEnvironment = resolvedAuthentication.environment;\n let sandboxAuthEnvironment = resolvedAuthEnvironment;\n let sandboxCredentialEnvironment: Record<string, string> | undefined;\n let credentialsBrokered = false;\n if (\n 'addRequestTransformations' in sandboxSession &&\n sandboxSession.addRequestTransformations != null\n ) {\n sandboxCredentialEnvironment =\n resumeData?.sandboxCredentialEnvironment ??\n (await createSandboxCredentialEnvironment({\n environment: resolvedAuthEnvironment,\n credentialEnvironmentVariables:\n CODEX_CREDENTIAL_ENVIRONMENT_VARIABLES,\n credentialForwarding: settings.credentialForwarding,\n }));\n sandboxAuthEnvironment = {\n ...resolvedAuthEnvironment,\n ...sandboxCredentialEnvironment,\n };\n const requestTransformations =\n createCodexSubscriptionRequestTransformations({\n env: resolvedAuthEnvironment,\n sandboxEnv: sandboxAuthEnvironment,\n auth: authenticationMode,\n requestHeaders: resolvedAuthentication.requestHeaders,\n });\n if (requestTransformations.length > 0) {\n await sandboxSession.addRequestTransformations(\n requestTransformations,\n );\n }\n credentialsBrokered = true;\n if (\n requestTransformations.length > 0 &&\n authenticationMode === 'direct' &&\n resolvedAuthEnvironment.OPENAI_BASE_URL == null\n ) {\n /*\n * Vercel Sandbox request transformations apply only to HTTP traffic.\n * Materializing Codex's standard OpenAI URL makes the bridge select\n * its custom provider, where WebSockets are disabled, while keeping\n * the non-brokered path on Codex's built-in OpenAI provider.\n */\n sandboxAuthEnvironment.OPENAI_BASE_URL = DEFAULT_OPENAI_BASE_URL;\n }\n }\n const bootstrapDir = path.posix.resolve(\n defaultWorkingDirectory,\n BOOTSTRAP_DIR,\n );\n\n const workDir = startOpts.sessionWorkDir;\n const sandboxHomeDir = await resolveSandboxHomeDir({\n sandbox: toolSafeSandboxSession,\n abortSignal: startOpts.abortSignal,\n });\n const sessionDataDir = `${defaultWorkingDirectory}/.agent-runs/${startOpts.sessionId}`;\n const bridgeStateDir = `${sessionDataDir}/bridge`;\n const cliShimDir = `${sessionDataDir}/codex`;\n const cliShimPath = `${cliShimDir}/${CLI_SHIM_FILENAME}`;\n const timeoutMs = settings.startupTimeoutMs ?? 120_000;\n\n // Normalize each forwarded bridge diagnostics frame into the general\n // `HarnessV1Diagnostic` and report it. The adapter does no telemetry work\n // beyond this transport→emission mapping.\n const report = startOpts.observability?.report;\n const onDiagnostic = report\n ? (frame: Parameters<typeof harnessV1DiagnosticFromBridgeFrame>[0]) =>\n report(\n harnessV1DiagnosticFromBridgeFrame(frame, {\n sessionId: startOpts.sessionId,\n timestamp: Date.now(),\n }),\n )\n : undefined;\n const onBridgeError = createBridgeErrorHandler({\n harnessId: 'codex',\n sessionId: startOpts.sessionId,\n });\n\n /*\n * Rung 1 — ATTACH. With live coordinates, reopen a socket to the\n * still-running bridge. Parked between-turn sessions just attach and wait\n * for the next `start`; suspended in-flight turns request replay of\n * everything past the persisted cursor. No spawn, no fresh token. If the\n * bridge is gone the open throws and we fall through to a spawn-based\n * recovery.\n */\n if (coords) {\n try {\n const endpoint = await resolveBridgeEndpoint({\n sandboxSession,\n override: settings.portEndpoint,\n port: coords.port,\n });\n const attachEndpoint = withBridgeToken({\n endpoint,\n token: coords.token,\n });\n const attachChannel: CodexChannel = new SandboxChannel({\n connect: ({ abortSignal }) =>\n openWebSocket({ ...attachEndpoint, abortSignal }),\n outboundSchema: outboundMessageSchema,\n initialLastSeenEventId: coords.lastSeenEventId,\n onDiagnostic,\n onBridgeError,\n reconnect: settings.reconnect,\n });\n await attachChannel.open(isContinue ? { resume: true } : undefined);\n return createSession({\n sessionId: startOpts.sessionId,\n channel: attachChannel,\n cliShimPath,\n // The live bridge was spawned by another process; no process handle.\n proc: undefined,\n model,\n reasoningEffort: settings.reasoningEffort,\n webSearch: settings.webSearch,\n codexConfig: settings.codexConfig,\n mcpServers: settings.mcpServers,\n headers: startOpts.headers,\n resumeThreadId: resumeThreadIdString,\n isResume: true,\n seedResumeThreadOnFirstPrompt: false,\n rerunContinue: false,\n bridgePort: coords.port,\n bridgeToken: coords.token,\n sandboxId,\n sandboxCredentialEnvironment,\n debug: startOpts.observability?.debug,\n permissionMode: startOpts.permissionMode,\n sandbox: toolSafeSandboxSession,\n sandboxHomeDir,\n turnConfigurationFingerprint,\n });\n } catch {\n // Bridge no longer reachable — recover by respawning below.\n }\n }\n\n /*\n * Rungs 2/3 — REPLAY vs RERUN. Respawn the bridge. `replay` is only sound\n * for `continueFrom`: those coordinates include the cursor the on-disk\n * log is replayed *from*. `resumeFrom` is a between-turn resume; even when\n * it carries bridge coordinates, replaying the previous turn would\n * re-deliver stale events into the next turn. Those resumes always `rerun`\n * via `codex.resumeThread(threadId)` when attach is unavailable.\n */\n let respawnStrategy: CodexRespawnStrategy | undefined = isResume\n ? 'rerun'\n : undefined;\n if (coords && isContinue) {\n const logRaw = await Promise.resolve(\n toolSafeSandboxSession.readTextFile({\n path: `${bridgeStateDir}/event-log.ndjson`,\n abortSignal: startOpts.abortSignal,\n }),\n ).catch(() => null);\n if ((await classifyDiskLog(logRaw)) === 'replay') {\n respawnStrategy = 'replay';\n }\n }\n\n const port = resolveBridgePort({\n sandboxSession,\n override: settings.port,\n });\n const token =\n settings.mintBridgeToken == null\n ? createBridgeToken()\n : settings.mintBridgeToken(sandboxId!);\n const forwardedAuthEnvironment = credentialsBrokered\n ? sandboxAuthEnvironment\n : await applyCredentialForwarding({\n environment: sandboxAuthEnvironment,\n credentialEnvironmentVariables:\n CODEX_CREDENTIAL_ENVIRONMENT_VARIABLES,\n credentialForwarding: settings.credentialForwarding,\n });\n if (!credentialsBrokered) {\n warnCredentialBrokeringUnavailable({\n environment: resolvedAuthEnvironment,\n forwardedEnvironment: forwardedAuthEnvironment,\n credentialEnvironmentVariables:\n CODEX_CREDENTIAL_ENVIRONMENT_VARIABLES,\n });\n }\n const env = {\n ...forwardedAuthEnvironment,\n AI_SDK_HARNESS_CLIENT_APP: CODEX_CLIENT_APP,\n BRIDGE_CHANNEL_TOKEN: token,\n BRIDGE_WS_PORT: String(port),\n ...(respawnStrategy === 'replay'\n ? { BRIDGE_REPLAY_FROM_DISK: '1' }\n : {}),\n };\n\n if (respawnStrategy === undefined) {\n await toolSafeSandboxSession.run({\n command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,\n abortSignal: startOpts.abortSignal,\n });\n }\n\n await markBridgeStarting({\n sandbox: toolSafeSandboxSession,\n bridgeStateDir,\n bridgeType: 'codex',\n abortSignal: startOpts.abortSignal,\n });\n\n const proc = await toolSafeSandboxSession.spawn({\n command: `node ${shellQuote(`${bootstrapDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)} --cli-shim-dir ${shellQuote(cliShimDir)}`,\n env,\n abortSignal: startOpts.abortSignal,\n });\n const stderrTail: string[] = [];\n const bridgeStderrDone = forwardBridgeProcessStream({\n stream: proc.stderr,\n streamName: 'stderr',\n source: 'codex',\n collectTail: stderrTail,\n });\n\n const { port: boundPort } = await waitForBridgeReady({\n proc,\n sandbox: toolSafeSandboxSession,\n bridgeStateDir,\n bridgeType: 'codex',\n timeoutMs,\n abortSignal: startOpts.abortSignal,\n createTimeoutError: ({ proc, stdoutTail }) =>\n createBridgeStartupError({\n message: 'codex bridge did not become ready in time.',\n proc,\n stdoutTail,\n stderrTail,\n stderrDone: bridgeStderrDone,\n }),\n createExitError: ({ proc, stdoutTail }) =>\n createBridgeStartupError({\n message: 'codex bridge exited before becoming ready.',\n proc,\n stdoutTail,\n stderrTail,\n stderrDone: bridgeStderrDone,\n }),\n });\n void drainBridgeProcessStream(proc.stdout);\n\n const endpoint = await resolveBridgeEndpoint({\n sandboxSession,\n override: settings.portEndpoint,\n port: boundPort,\n });\n const bridgeEndpoint = withBridgeToken({ endpoint, token });\n\n const channel: CodexChannel = new SandboxChannel({\n connect: ({ abortSignal }) =>\n openWebSocket({ ...bridgeEndpoint, abortSignal }),\n outboundSchema: outboundMessageSchema,\n onDiagnostic,\n onBridgeError,\n reconnect: settings.reconnect,\n // In replay mode the respawned bridge reloaded the finished turn from\n // disk; seed the cursor and resume so it streams the tail (incl.\n // `finish`).\n ...(respawnStrategy === 'replay'\n ? { initialLastSeenEventId: coords?.lastSeenEventId ?? 0 }\n : {}),\n });\n await channel.open(\n respawnStrategy === 'replay' ? { resume: true } : undefined,\n );\n\n return createSession({\n sessionId: startOpts.sessionId,\n channel,\n cliShimPath,\n proc,\n model,\n reasoningEffort: settings.reasoningEffort,\n webSearch: settings.webSearch,\n codexConfig: settings.codexConfig,\n mcpServers: settings.mcpServers,\n headers: startOpts.headers,\n resumeThreadId: resumeThreadIdString,\n isResume: respawnStrategy !== undefined,\n seedResumeThreadOnFirstPrompt: respawnStrategy !== undefined,\n rerunContinue: respawnStrategy === 'rerun',\n bridgePort: boundPort,\n bridgeToken: token,\n sandboxId,\n sandboxCredentialEnvironment,\n debug: startOpts.observability?.debug,\n permissionMode: startOpts.permissionMode,\n sandbox: toolSafeSandboxSession,\n sandboxHomeDir,\n turnConfigurationFingerprint,\n });\n },\n };\n}\n\nfunction resolveBridgePort({\n sandboxSession,\n override,\n}: {\n sandboxSession: HarnessV1NetworkSandboxSession | SandboxSession;\n override: number | undefined;\n}): number {\n if (override !== undefined) return override;\n if ('ports' in sandboxSession && sandboxSession.ports.length > 0) {\n return sandboxSession.ports[0];\n }\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'codex',\n message:\n 'The codex harness needs a TCP port exposed by the sandbox. ' +\n 'Create the sandbox with `ports: [<port>]` or pass `createCodex({ port })`.',\n });\n}\n\nfunction validateBasicSandboxSettings({\n sandboxSession,\n port,\n portEndpoint,\n}: {\n sandboxSession: HarnessV1NetworkSandboxSession | SandboxSession;\n port: number | undefined;\n portEndpoint: HarnessV1PortEndpoint | undefined;\n}): void {\n if ('getPortEndpoint' in sandboxSession) return;\n if (port == null) {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'codex',\n message:\n 'The codex harness requires an explicit `port` when using a basic sandbox session.',\n });\n }\n if (portEndpoint == null) {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'codex',\n message:\n 'The codex harness requires an explicit `portEndpoint` when using a basic sandbox session.',\n });\n }\n}\n\nasync function resolveBridgeEndpoint({\n sandboxSession,\n override,\n port,\n}: {\n sandboxSession: HarnessV1NetworkSandboxSession | SandboxSession;\n override: HarnessV1PortEndpoint | undefined;\n port: number;\n}): Promise<HarnessV1PortEndpoint> {\n if (override != null) return override;\n if ('getPortEndpoint' in sandboxSession) {\n return sandboxSession.getPortEndpoint({ port, protocol: 'ws' });\n }\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'codex',\n message:\n 'The codex harness requires an explicit `portEndpoint` when using a basic sandbox session.',\n });\n}\n\nfunction openWebSocket({\n url,\n headers,\n abortSignal,\n}: HarnessV1PortEndpoint & { abortSignal: AbortSignal }): Promise<WebSocket> {\n return new Promise((resolve, reject) => {\n if (abortSignal.aborted) {\n reject(abortSignal.reason ?? new Error('WebSocket connection aborted'));\n return;\n }\n\n const ws = new WebSocket(url, {\n headers: headers == null ? undefined : { ...headers },\n });\n\n let settled = false;\n const cleanup = () => {\n abortSignal.removeEventListener('abort', onAbort);\n ws.off('open', onOpen);\n ws.off('error', onError);\n };\n const rejectWithCleanup = (error: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n ws.once('error', () => {});\n try {\n ws.terminate();\n } catch {\n try {\n ws.close();\n } catch {\n // best-effort\n }\n }\n reject(error);\n };\n const onOpen = () => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(ws);\n };\n const onError = (err: Error) => {\n rejectWithCleanup(err);\n };\n const onAbort = () =>\n rejectWithCleanup(\n abortSignal.reason ?? new Error('WebSocket connection aborted'),\n );\n\n ws.once('open', onOpen);\n ws.once('error', onError);\n abortSignal.addEventListener('abort', onAbort, { once: true });\n });\n}\n\nfunction createSession({\n sessionId,\n channel,\n cliShimPath,\n proc,\n model,\n reasoningEffort,\n webSearch,\n codexConfig,\n mcpServers,\n headers,\n resumeThreadId,\n isResume,\n seedResumeThreadOnFirstPrompt,\n rerunContinue,\n bridgePort,\n bridgeToken,\n sandboxId,\n sandboxCredentialEnvironment,\n debug,\n permissionMode,\n sandbox,\n sandboxHomeDir,\n turnConfigurationFingerprint,\n}: {\n sessionId: string;\n channel: CodexChannel;\n cliShimPath: string;\n /** Undefined on `attach` — the live bridge was spawned by another process. */\n proc: Experimental_SandboxProcess | undefined;\n model: string | undefined;\n reasoningEffort: 'low' | 'medium' | 'high' | 'xhigh' | 'max' | undefined;\n webSearch: boolean | undefined;\n codexConfig: Record<string, unknown> | undefined;\n mcpServers: Record<string, unknown> | undefined;\n headers: Readonly<Record<string, string>> | undefined;\n resumeThreadId: string | undefined;\n isResume: boolean;\n seedResumeThreadOnFirstPrompt: boolean;\n rerunContinue: boolean;\n bridgePort: number;\n bridgeToken: string;\n sandboxId: string | undefined;\n sandboxCredentialEnvironment: Record<string, string> | undefined;\n debug: HarnessV1DebugConfig | undefined;\n permissionMode: HarnessV1PermissionMode | undefined;\n sandbox: SandboxSession;\n sandboxHomeDir: string;\n turnConfigurationFingerprint: string | undefined;\n}): HarnessV1Session {\n let stopped = false;\n let stopPromise: Promise<void> | undefined;\n /*\n * Send the persisted threadId on the first prompt only when the bridge was\n * respawned (rerun/replay) so it takes the `codex.resumeThread(...)` branch.\n * An `attach`ed bridge already holds its threadState in memory and continues\n * on its own, so it needs no seed.\n */\n let pendingResumeThreadId = seedResumeThreadOnFirstPrompt\n ? resumeThreadId\n : undefined;\n /*\n * Host-tool relay guidance is prepended to the first user message of a fresh\n * session only. A resumed session (attach/replay/rerun) already carried it in\n * its original first message (preserved in the persisted thread), so it\n * starts \"applied\".\n */\n let initialPromptGuidanceApplied = isResume;\n\n /*\n * Latest codex thread id, cached from the bridge's `bridge-thread`\n * announcements. Seeded from lifecycle state so `doDetach()` and `doStop()`\n * can include a thread id even before this process has run a turn.\n */\n let latestThreadId = resumeThreadId;\n let latestTurnConfigurationFingerprint = turnConfigurationFingerprint;\n channel.on('bridge-thread', msg => {\n latestThreadId = msg.threadId;\n });\n\n const synchronizeTurnConfiguration = async ({\n skills,\n instructions,\n tools,\n abortSignal,\n }: {\n skills: ReadonlyArray<HarnessV1Skill>;\n instructions: string | undefined;\n tools: ReadonlyArray<{\n name: string;\n description?: string;\n inputSchema: unknown;\n }>;\n abortSignal?: AbortSignal;\n }): Promise<{ restartThread: boolean }> => {\n const skillsResult = await writeSkills({\n sandbox,\n homePath: sandboxHomeDir,\n skillsDir: '.agents/skills',\n skills,\n abortSignal,\n invalidSkillNameMessage: ({ name }) =>\n `Invalid Codex skill name: ${name}`,\n invalidSkillFilePathMessage: ({ skillName, filePath }) =>\n `Invalid Codex skill file path for ${skillName}: ${filePath}`,\n });\n const nextFingerprint = fingerprintCodexTurnConfiguration({\n instructions,\n tools,\n });\n const restartThread =\n latestThreadId != null &&\n (skillsResult.changed ||\n (latestTurnConfigurationFingerprint != null &&\n latestTurnConfigurationFingerprint !== nextFingerprint));\n latestTurnConfigurationFingerprint = nextFingerprint;\n if (restartThread) {\n /*\n * `codex exec resume` retains the native thread's original developer\n * instructions and skill catalog. A fresh native thread is therefore\n * required for replacement semantics. Host-tool guidance is framed\n * again because that guidance also belongs to the new native thread.\n */\n initialPromptGuidanceApplied = false;\n pendingResumeThreadId = undefined;\n }\n return { restartThread };\n };\n\n /*\n * Wire the channel into one turn's worth of events and return the control\n * surface. Shared by `doPromptTurn` (which sends a `start` afterwards) and\n * `doContinueTurn` (which attaches to an already-running/replayed turn, or sends\n * a rerun `start`). The only difference between the two entry points is the\n * `start` message, not the listener/abort/settle plumbing.\n */\n const wireTurn = (turnOpts: {\n emit: (event: HarnessV1StreamPart) => void;\n abortSignal?: AbortSignal;\n }): {\n control: HarnessV1PromptControl;\n sendStart: (send: () => void) => void;\n } => {\n let pendingResolve: (() => void) | undefined;\n let pendingReject: ((err: unknown) => void) | undefined;\n const done = new Promise<void>((resolve, reject) => {\n pendingResolve = resolve;\n pendingReject = reject;\n });\n\n const unsubs: Array<() => void> = [];\n const forward = (event: HarnessV1StreamPart) => {\n try {\n turnOpts.emit(event);\n } catch {}\n };\n\n const eventTypes = [\n 'stream-start',\n 'text-start',\n 'text-delta',\n 'text-end',\n 'reasoning-start',\n 'reasoning-delta',\n 'reasoning-end',\n 'tool-call',\n 'tool-approval-request',\n 'tool-result',\n 'file-change',\n 'finish-step',\n 'raw',\n ] as const;\n let isSettled = false;\n const settleSuccess = () => {\n if (isSettled) return;\n isSettled = true;\n for (const u of unsubs) u();\n pendingResolve!();\n };\n const settleError = (err: unknown) => {\n if (isSettled) return;\n isSettled = true;\n for (const u of unsubs) u();\n pendingReject!(err);\n };\n\n for (const type of eventTypes) {\n unsubs.push(\n channel.on(type, msg => {\n forward(msg);\n }),\n );\n }\n unsubs.push(\n channel.on('finish', msg => {\n forward(msg);\n settleSuccess();\n }),\n );\n unsubs.push(\n channel.on('error', msg => {\n forward(msg);\n settleError(msg.error);\n }),\n );\n\n /*\n * A `'suspended'` close is a graceful slice-boundary freeze the host\n * initiated (`doSuspendTurn`): the turn keeps running in the bridge and its\n * tail is replayed to the next process, so wind this turn down cleanly\n * rather than failing it. Any other close mid-turn is an unexpected drop.\n */\n const onClose = (_code?: number, reason?: string) => {\n if (isSettled) return;\n if (reason === 'suspended') {\n settleSuccess();\n return;\n }\n settleError(new Error('codex bridge closed before the turn finished.'));\n };\n channel.onClose(onClose);\n\n const onAbort = () => {\n if (isSettled) return;\n try {\n channel.send({ type: 'abort' });\n } catch {}\n settleError(\n turnOpts.abortSignal?.reason ??\n new DOMException('Aborted', 'AbortError'),\n );\n };\n if (turnOpts.abortSignal) {\n if (turnOpts.abortSignal.aborted) {\n onAbort();\n } else {\n turnOpts.abortSignal.addEventListener('abort', onAbort, {\n once: true,\n });\n }\n }\n\n const control: HarnessV1PromptControl = {\n submitToolResult: async input => {\n channel.send({\n type: 'tool-result',\n toolCallId: input.toolCallId,\n output: input.output,\n isError: input.isError,\n });\n },\n submitToolApproval: async input => {\n channel.send({\n type: 'tool-approval-response',\n approvalId: input.approvalId,\n approved: input.approved,\n reason: input.reason,\n });\n },\n done,\n };\n\n return {\n control,\n sendStart: send => {\n /*\n * Codex can complete short turns without using tools. Deferring the\n * start frame gives the harness runner one event-loop turn to finish\n * wiring the prompt control and stream output before Codex can settle.\n */\n const timer = setTimeout(() => {\n if (isSettled) return;\n try {\n send();\n } catch (err) {\n settleError(err);\n }\n }, 0);\n timer.unref?.();\n },\n };\n };\n\n return {\n sessionId,\n isResume,\n doPromptTurn: async promptOpts => {\n if (\n promptOpts.responseFormat?.type === 'json' &&\n promptOpts.responseFormat.schema == null\n ) {\n throw new HarnessCapabilityUnsupportedError({\n message:\n \"Harness 'codex' requires a JSON schema for structured output.\",\n harnessId: 'codex',\n });\n }\n const tools = (promptOpts.tools ?? []).map(t => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n }));\n const { restartThread } = await synchronizeTurnConfiguration({\n skills: promptOpts.skills,\n instructions: promptOpts.instructions,\n tools,\n abortSignal: promptOpts.abortSignal,\n });\n const turn = wireTurn({\n emit: promptOpts.emit,\n abortSignal: promptOpts.abortSignal,\n });\n\n let promptText = extractUserText(promptOpts.prompt);\n if (!initialPromptGuidanceApplied) {\n promptText = frameInitialPromptGuidance({\n toolUsageBlock:\n tools.length > 0\n ? composeToolUsageInstructions({\n tools,\n cliShimPath,\n })\n : undefined,\n userText: promptText,\n });\n }\n initialPromptGuidanceApplied = true;\n\n const startMessage = {\n type: 'start' as const,\n prompt: promptText,\n tools,\n ...(promptOpts.responseFormat == null\n ? {}\n : { responseFormat: promptOpts.responseFormat }),\n ...(promptOpts.instructions\n ? { instructions: promptOpts.instructions }\n : {}),\n model: promptOpts.model ?? model,\n reasoningEffort,\n webSearch,\n ...(codexConfig == null ? {} : { codexConfig }),\n ...(mcpServers == null ? {} : { mcpServers }),\n ...(headers == null ? {} : { headers }),\n ...(permissionMode ? { permissionMode } : {}),\n ...(pendingResumeThreadId\n ? { resumeThreadId: pendingResumeThreadId }\n : {}),\n ...(restartThread ? { restartThread: true } : {}),\n ...(debug ? { debug } : {}),\n };\n pendingResumeThreadId = undefined;\n turn.sendStart(() => channel.send(startMessage));\n\n return turn.control;\n },\n doContinueTurn: async continueOpts => {\n if (\n continueOpts.responseFormat?.type === 'json' &&\n continueOpts.responseFormat.schema == null\n ) {\n throw new HarnessCapabilityUnsupportedError({\n message:\n \"Harness 'codex' requires a JSON schema for structured output.\",\n harnessId: 'codex',\n });\n }\n const tools = (continueOpts.tools ?? []).map(t => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n }));\n const { restartThread } = await synchronizeTurnConfiguration({\n skills: continueOpts.skills,\n instructions: continueOpts.instructions,\n tools,\n abortSignal: continueOpts.abortSignal,\n });\n const turn = wireTurn({\n emit: continueOpts.emit,\n abortSignal: continueOpts.abortSignal,\n });\n\n /*\n * attach / replay: the still-running (or disk-replayed) turn streams into\n * the wired listeners — `doStart` opened the channel with `{ resume: true }`\n * so the bridge replays everything past the persisted cursor (including a\n * `finish` if the turn ended during the gap). No `start` is sent: issuing\n * one would clear the bridge's replay log and begin a new turn. Lossless.\n *\n * rerun: the bridge was respawned with no in-flight turn to attach to, so\n * re-drive codex's own thread via `resumeThreadId`. Lossy — work in flight\n * at the suspension is recomputed. This is the rare bridge-died\n * fallback; the common slice path is `attach`.\n */\n if (rerunContinue) {\n const threadId = pendingResumeThreadId ?? latestThreadId;\n pendingResumeThreadId = undefined;\n turn.sendStart(() =>\n channel.send({\n type: 'start' as const,\n /*\n * A continuation nudge rather than an empty prompt: `resumeThreadId`\n * rehydrates the prior thread, and this is the new user turn that\n * drives it forward. Keeping it non-empty avoids handing the runtime\n * an empty user message (and mirrors the claude-code adapter, where an\n * empty text block trips the Anthropic API's `cache_control` rule).\n */\n prompt: 'Continue.',\n tools,\n ...(continueOpts.responseFormat == null\n ? {}\n : { responseFormat: continueOpts.responseFormat }),\n ...(continueOpts.instructions\n ? { instructions: continueOpts.instructions }\n : {}),\n model: continueOpts.model ?? model,\n reasoningEffort,\n webSearch,\n ...(codexConfig == null ? {} : { codexConfig }),\n ...(mcpServers == null ? {} : { mcpServers }),\n ...(headers == null ? {} : { headers }),\n ...(permissionMode ? { permissionMode } : {}),\n ...(threadId ? { resumeThreadId: threadId } : {}),\n ...(restartThread ? { restartThread: true } : {}),\n ...(debug ? { debug } : {}),\n }),\n );\n }\n\n return turn.control;\n },\n doCompact: async () => {\n /*\n * Codex compacts its context automatically inside the core turn loop\n * (~90% of the model context window), but the `codex exec` transport this\n * adapter drives exposes no manual compaction trigger and emits no\n * compaction event. Manual `compact()` is therefore unsupported; Codex's\n * own auto-compaction continues to run regardless.\n */\n throw new HarnessCapabilityUnsupportedError({\n message:\n \"Harness 'codex' does not support manual compaction; Codex auto-compacts its context internally.\",\n harnessId: 'codex',\n });\n },\n doDetach: async () => {\n if (stopped) {\n throw new Error(\n `codex session ${sessionId} is already stopped; cannot detach.`,\n );\n }\n stopped = true;\n const lastSeenEventId = await channel.suspend();\n const payload: HarnessV1ResumeSessionState = {\n type: 'resume-session',\n harnessId: 'codex',\n specificationVersion: 'harness-v1',\n data: {\n ...(latestThreadId ? { threadId: latestThreadId } : {}),\n ...(latestTurnConfigurationFingerprint\n ? {\n turnConfigurationFingerprint:\n latestTurnConfigurationFingerprint,\n }\n : {}),\n ...(sandboxCredentialEnvironment == null\n ? {}\n : { sandboxCredentialEnvironment }),\n bridge: {\n port: bridgePort,\n token: bridgeToken,\n lastSeenEventId,\n ...(sandboxId == null ? {} : { sandboxId }),\n },\n },\n };\n return payload;\n },\n doDestroy: async () => {\n if (stopped) return stopPromise;\n stopped = true;\n stopPromise = (async () => {\n // Tell the channel we are tearing down so the bridge's post-shutdown\n // socket close finalises instead of triggering a reconnect.\n channel.beginClose();\n try {\n if (!channel.isClosed()) {\n channel.send({ type: 'destroy' });\n }\n } catch {}\n let stopTimer: ReturnType<typeof setTimeout> | undefined;\n try {\n if (proc) {\n await Promise.race([\n proc.wait(),\n new Promise<void>(resolve => {\n stopTimer = setTimeout(resolve, 5000);\n stopTimer.unref?.();\n }),\n ]);\n }\n } finally {\n if (stopTimer) clearTimeout(stopTimer);\n try {\n await proc?.kill();\n } catch {}\n channel.close();\n }\n })();\n return stopPromise;\n },\n doStop: async () => {\n if (stopped) {\n throw new Error(\n `codex session ${sessionId} is already stopped; cannot stop.`,\n );\n }\n stopped = true;\n /*\n * If the bridge's channel already closed (e.g. mid-turn WS drop)\n * there is no one to acknowledge a `stop` message. Synthesize an empty\n * payload — the workdir is still captured by the sandbox snapshot\n * during the subsequent `sandboxSession.stop()`, so the next turn can\n * resume the filesystem state. The trade-off: we lose\n * `threadId`, so the codex CLI starts a fresh thread on the\n * preserved workdir rather than resuming the prior conversation\n * inside Codex's runtime. Ability to continue beats throwing.\n */\n // Tell the channel we are tearing down so the bridge's post-stop\n // socket close finalises instead of triggering a reconnect.\n channel.beginClose();\n const data: unknown = channel.isClosed()\n ? {}\n : await new Promise<unknown>((resolve, reject) => {\n const timer = setTimeout(() => {\n unsub();\n reject(\n new Error(\n `codex session ${sessionId} did not reply to stop within 5s.`,\n ),\n );\n }, 5000);\n timer.unref?.();\n const unsub = channel.on('bridge-stop', msg => {\n clearTimeout(timer);\n unsub();\n resolve(msg.data);\n });\n try {\n channel.send({ type: 'stop' });\n } catch (err) {\n clearTimeout(timer);\n unsub();\n reject(err);\n }\n });\n\n let stopTimer: ReturnType<typeof setTimeout> | undefined;\n try {\n if (proc) {\n await Promise.race([\n proc.wait(),\n new Promise<void>(resolve => {\n stopTimer = setTimeout(resolve, 5000);\n stopTimer.unref?.();\n }),\n ]);\n }\n } finally {\n if (stopTimer) clearTimeout(stopTimer);\n try {\n await proc?.kill();\n } catch {}\n channel.close();\n }\n\n const lifecycleData =\n data != null && typeof data === 'object' && !Array.isArray(data)\n ? { ...(data as Record<string, unknown>) }\n : {};\n const payload: HarnessV1ResumeSessionState = {\n type: 'resume-session',\n harnessId: 'codex',\n specificationVersion: 'harness-v1',\n data: {\n ...lifecycleData,\n ...(latestTurnConfigurationFingerprint\n ? {\n turnConfigurationFingerprint:\n latestTurnConfigurationFingerprint,\n }\n : {}),\n ...(sandboxCredentialEnvironment == null\n ? {}\n : { sandboxCredentialEnvironment }),\n } as HarnessV1ResumeSessionState['data'],\n };\n return payload;\n },\n doSuspendTurn: async () => {\n if (stopped) {\n throw new Error(\n `codex session ${sessionId} is stopped; cannot suspend.`,\n );\n }\n stopped = true;\n /*\n * Freeze the host at a precise cursor without stopping the active model\n * turn. `channel.suspend` stops processing inbound frames, drains what\n * was already dispatched, then closes the host socket with reason\n * `'suspended'`. The bridge keeps the turn running and accumulates events\n * past the cursor for the next slice to replay. The sandbox process is\n * deliberately left alive.\n */\n const lastSeenEventId = await channel.suspend();\n const payload: HarnessV1ContinueTurnState = {\n type: 'continue-turn',\n harnessId: 'codex',\n specificationVersion: 'harness-v1',\n data: {\n ...(latestThreadId ? { threadId: latestThreadId } : {}),\n ...(latestTurnConfigurationFingerprint\n ? {\n turnConfigurationFingerprint:\n latestTurnConfigurationFingerprint,\n }\n : {}),\n ...(sandboxCredentialEnvironment == null\n ? {}\n : { sandboxCredentialEnvironment }),\n bridge: {\n port: bridgePort,\n token: bridgeToken,\n lastSeenEventId,\n ...(sandboxId == null ? {} : { sandboxId }),\n },\n },\n };\n return payload;\n },\n };\n}\n\nfunction fingerprintCodexTurnConfiguration({\n instructions,\n tools,\n}: {\n instructions: string | undefined;\n tools: ReadonlyArray<{\n name: string;\n description?: string;\n inputSchema: unknown;\n }>;\n}): string {\n return createHash('sha256')\n .update(JSON.stringify({ instructions: instructions ?? null, tools }))\n .digest('hex');\n}\n\n/*\n * Frame host-tool relay guidance and the user's text so Codex treats the\n * prepended block as operating guidance rather than user prose. Applied only\n * to the first user message of a fresh session.\n */\nfunction frameInitialPromptGuidance({\n toolUsageBlock,\n userText,\n}: {\n toolUsageBlock: string | undefined;\n userText: string;\n}): string {\n const blocks: string[] = [];\n if (toolUsageBlock) blocks.push(toolUsageBlock);\n if (blocks.length === 0) return userText;\n return `${blocks.join('\\n\\n')}\\n\\n<user-message>\\n${userText}\\n</user-message>`;\n}\n\nfunction composeToolUsageInstructions({\n tools,\n cliShimPath,\n}: {\n tools: ReadonlyArray<{\n name: string;\n description?: string;\n inputSchema?: unknown;\n }>;\n cliShimPath: string;\n}): string {\n const lines: string[] = [\n '<host-tool-instructions>',\n 'You have access to the following host-provided tools. To use one, run the following command via your built-in `bash` tool:',\n '',\n ` node ${cliShimPath} <toolName> '<jsonInput>'`,\n '',\n 'The script prints the JSON result to stdout. Do not invent another way to call these tools — only this CLI invocation will work. Pass the JSON input as a single-quoted argument.',\n 'For every user request that depends on a host-provided tool, run a separate CLI invocation for each needed tool call in the current turn before answering. Do not reuse previous tool results, and do not say you used a host tool unless the command has completed in the current turn.',\n '',\n ];\n for (const toolSpec of tools) {\n lines.push(\n `- **${toolSpec.name}**${toolSpec.description ? ': ' + toolSpec.description : ''}`,\n );\n lines.push(\n ` - Input schema: \\`${JSON.stringify(toolSpec.inputSchema ?? {})}\\``,\n );\n }\n lines.push('</host-tool-instructions>');\n return lines.join('\\n');\n}\n\n/*\n * Reduce a `HarnessV1Prompt` to the plain user text the bridge forwards\n * to the Codex SDK. File and image parts on the message are not yet\n * supported by the underlying runtime — throw rather than silently drop\n * them so callers learn about the gap instead of seeing mysteriously\n * truncated prompts.\n */\nfunction extractUserText(prompt: HarnessV1Prompt): string {\n if (typeof prompt === 'string') return prompt;\n const { content } = prompt;\n if (typeof content === 'string') return content;\n const parts: string[] = [];\n for (const part of content) {\n if (part.type !== 'text') {\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'codex',\n message: `The codex harness does not yet support user message parts of type '${part.type}'. Pass a string or a user message whose content contains only text parts.`,\n });\n }\n parts.push(part.text);\n }\n return parts.join('\\n\\n');\n}\n","import type { HarnessV1Bootstrap } from '@ai-sdk/harness';\nimport { createReadBridgeAsset } from '@ai-sdk/harness/utils';\n\n/*\n * Keep every asset URL literal so bundlers can emit each file separately.\n * Dynamic new URL() paths can collapse multiple assets into one resolution.\n */\nconst readBridgeAsset = createReadBridgeAsset({\n 'package.json': new URL('./bridge/package.json', import.meta.url),\n 'pnpm-lock.yaml': new URL('./bridge/pnpm-lock.yaml', import.meta.url),\n 'index.mjs': new URL('./bridge/index.mjs', import.meta.url),\n});\n\n/*\n * Bootstrap is derived state stored under the sandbox's default working\n * directory so snapshot-capable providers can preserve the installed CLI,\n * bridge, and recipe marker without requiring root filesystem access.\n *\n * The session work dir (`startOpts.sessionWorkDir`) lives under the sandbox's\n * default working directory — the provider's persistent mount — so any files\n * the agent edits survive both detach -> attach and stop -> snapshot -> resume\n * cycles. Harness infra derived from `sandboxSession.defaultWorkingDirectory`\n * lives under `.agent-runs`, outside the agent workdir.\n */\nexport const CODEX_BOOTSTRAP_DIR = '.harness-bootstrap/codex';\n\nlet cachedBootstrap: HarnessV1Bootstrap | undefined;\n\nexport async function getCodexBootstrap(): Promise<HarnessV1Bootstrap> {\n if (cachedBootstrap != null) return cachedBootstrap;\n const [pkg, lock, bridge] = await Promise.all([\n readBridgeAsset('package.json'),\n readBridgeAsset('pnpm-lock.yaml'),\n readBridgeAsset('index.mjs'),\n ]);\n cachedBootstrap = {\n harnessId: 'codex',\n bootstrapDir: CODEX_BOOTSTRAP_DIR,\n files: [\n { path: `${CODEX_BOOTSTRAP_DIR}/package.json`, content: pkg },\n { path: `${CODEX_BOOTSTRAP_DIR}/pnpm-lock.yaml`, content: lock },\n { path: `${CODEX_BOOTSTRAP_DIR}/bridge.mjs`, content: bridge },\n ],\n commands: [\n {\n command: 'pnpm install --frozen-lockfile --store-dir .pnpm-store',\n },\n ],\n };\n return cachedBootstrap;\n}\n","import type {\n HarnessV1Authentication,\n HarnessV1RequestTransformation,\n HarnessV1RequestTransformationSources,\n} from '@ai-sdk/harness';\nimport {\n createCredentialRequestTransformation,\n getAiGatewayAuthFromEnv,\n isHarnessAuthenticationEnvironment,\n} from '@ai-sdk/harness/utils';\n\nconst DEFAULT_AI_GATEWAY_BASE_URL = 'https://ai-gateway.vercel.sh/v1';\nexport const DEFAULT_OPENAI_BASE_URL = 'https://api.openai.com/v1';\n\nexport const CODEX_CREDENTIAL_ENVIRONMENT_VARIABLES = [\n 'AI_GATEWAY_API_KEY',\n 'CODEX_API_KEY',\n] as const;\n\nexport function createCodexRequestTransformations({\n env: environment,\n sandboxEnv: sandboxEnvironment,\n auth: authenticationMode,\n}: HarnessV1RequestTransformationSources<CodexResolvedAuthenticationMode>): HarnessV1RequestTransformation[] {\n if (!environment.CODEX_API_KEY || !sandboxEnvironment.CODEX_API_KEY) {\n return [];\n }\n return [\n createCredentialRequestTransformation({\n matchUrl:\n environment.OPENAI_BASE_URL ??\n (authenticationMode === 'ai-gateway'\n ? DEFAULT_AI_GATEWAY_BASE_URL\n : DEFAULT_OPENAI_BASE_URL),\n matchHeaders: {\n Authorization: `Bearer ${sandboxEnvironment.CODEX_API_KEY}`,\n },\n transformHeaders: {\n Authorization: `Bearer ${environment.CODEX_API_KEY}`,\n },\n }),\n ];\n}\n\nexport type CodexResolvedAuthenticationMode = 'direct' | 'ai-gateway';\n\nexport type CodexAuthenticationMode = HarnessV1Authentication;\n\n/**\n * Resolve the environment-variable blob the codex bridge needs. Precedence:\n *\n * 1. An explicit authentication mode pins the selected route.\n * 2. Auto-detect from the host process env: gateway first\n * (`AI_GATEWAY_API_KEY` / `VERCEL_OIDC_TOKEN`), then `CODEX_API_KEY` /\n * `OPENAI_API_KEY`.\n */\nexport function resolveCodexEnv(\n auth: CodexAuthenticationMode | undefined,\n processEnv: Record<string, string | undefined> = process.env,\n): Record<string, string> {\n const suppliedEnvironment = isHarnessAuthenticationEnvironment(auth);\n const authenticationEnvironment = suppliedEnvironment ? auth : processEnv;\n if (auth === 'direct') {\n return pickOpenAI({ processEnv: authenticationEnvironment });\n }\n\n const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({\n env: authenticationEnvironment,\n });\n if (auth === 'ai-gateway' || gatewayAuthFromEnv.apiKey) {\n return pickGateway({ gatewayAuthFromEnv });\n }\n return pickOpenAI({ processEnv: authenticationEnvironment });\n}\n\nexport function resolveCodexAuthenticationMode(\n auth: CodexAuthenticationMode | undefined,\n processEnv: Record<string, string | undefined> = process.env,\n): CodexResolvedAuthenticationMode {\n if (isHarnessAuthenticationEnvironment(auth)) {\n return getAiGatewayAuthFromEnv({ env: auth }).apiKey\n ? 'ai-gateway'\n : 'direct';\n }\n if (auth === 'direct') {\n return 'direct';\n }\n if (auth === 'ai-gateway') {\n return 'ai-gateway';\n }\n return getAiGatewayAuthFromEnv({ env: processEnv }).apiKey\n ? 'ai-gateway'\n : 'direct';\n}\n\nfunction pickOpenAI({\n processEnv,\n}: {\n processEnv: Record<string, string | undefined>;\n}): Record<string, string> {\n const env: Record<string, string> = {};\n const apiKey = processEnv.OPENAI_API_KEY ?? processEnv.CODEX_API_KEY;\n if (apiKey) env.CODEX_API_KEY = apiKey;\n const baseUrl = processEnv.OPENAI_BASE_URL;\n if (baseUrl) env.OPENAI_BASE_URL = baseUrl;\n const organization = processEnv.OPENAI_ORGANIZATION;\n if (organization) env.OPENAI_ORGANIZATION = organization;\n const project = processEnv.OPENAI_PROJECT;\n if (project) env.OPENAI_PROJECT = project;\n return env;\n}\n\nfunction pickGateway({\n gatewayAuthFromEnv,\n}: {\n gatewayAuthFromEnv: ReturnType<typeof getAiGatewayAuthFromEnv>;\n}): Record<string, string> {\n const apiKey = gatewayAuthFromEnv.apiKey;\n const baseUrl = toCodexGatewayBaseUrl(gatewayAuthFromEnv.baseUrl);\n const env: Record<string, string> = {};\n if (apiKey) {\n env.AI_GATEWAY_API_KEY = apiKey;\n env.CODEX_API_KEY = apiKey;\n }\n env.AI_GATEWAY_BASE_URL = baseUrl;\n env.OPENAI_BASE_URL = baseUrl;\n return env;\n}\n\nfunction toCodexGatewayBaseUrl(baseUrl: string): string {\n const trimmed = baseUrl.replace(/\\/+$/, '');\n return trimmed.endsWith('/v1') ? trimmed : `${trimmed}/v1`;\n}\n","import { spawn } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport {\n chmod,\n mkdir,\n readFile,\n realpath,\n rename,\n writeFile,\n} from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, join, resolve } from 'node:path';\nimport type {\n HarnessV1RequestTransformation,\n HarnessV1RequestTransformationSources,\n} from '@ai-sdk/harness';\nimport {\n getJwtExpiresAt,\n isAccessTokenExpiringSoon,\n isHarnessAuthenticationEnvironment,\n isLinux,\n isMacOS,\n isWindows,\n readLinuxSecretServicePassword,\n readMacOSKeychainPassword,\n readWindowsCredentialManagerPassword,\n refreshOAuthAccessToken,\n shouldResolveNativeSubscription,\n} from '@ai-sdk/harness/utils';\nimport { isRecord, safeParseJSON } from '@ai-sdk/provider-utils';\nimport {\n createCodexRequestTransformations,\n resolveCodexEnv,\n type CodexAuthenticationMode,\n type CodexResolvedAuthenticationMode,\n} from './codex-auth';\n\nconst CHATGPT_CODEX_BASE_URL = 'https://chatgpt.com/backend-api/codex';\nconst OPENAI_TOKEN_URL = 'https://auth.openai.com/oauth/token';\nconst OPENAI_CLIENT_ID = 'app_EMoamEEZ73f0CkXaXp7hrann';\n\nexport type CodexResolvedAuthentication = {\n readonly environment: Record<string, string>;\n readonly requestHeaders?: Readonly<Record<string, string>>;\n};\n\nexport function createCodexSubscriptionRequestTransformations({\n requestHeaders,\n ...sources\n}: HarnessV1RequestTransformationSources<CodexResolvedAuthenticationMode> & {\n requestHeaders?: Readonly<Record<string, string>>;\n}): HarnessV1RequestTransformation[] {\n const transformations = createCodexRequestTransformations(sources);\n if (requestHeaders == null) return transformations;\n\n return transformations.map(transformation => ({\n ...transformation,\n transform: {\n ...transformation.transform,\n headers: {\n ...transformation.transform.headers,\n ...requestHeaders,\n },\n },\n }));\n}\n\ntype CodexAuthCredentialsStoreMode = 'file' | 'keyring' | 'auto' | 'ephemeral';\n\ntype CodexKeyring = {\n read(options: {\n service: string;\n account: string;\n }): Promise<string | undefined>;\n write(options: {\n service: string;\n account: string;\n value: string;\n }): Promise<void>;\n};\n\ntype CodexAuthFile = {\n readonly auth_mode?: unknown;\n readonly tokens?: {\n readonly access_token?: unknown;\n readonly refresh_token?: unknown;\n readonly account_id?: unknown;\n };\n readonly [key: string]: unknown;\n};\n\nexport async function resolveCodexAuthentication({\n auth,\n processEnv = process.env,\n authCredentialsStoreMode,\n readSubscription = readCodexSubscription,\n}: {\n auth: CodexAuthenticationMode | undefined;\n processEnv?: Record<string, string | undefined>;\n authCredentialsStoreMode?: unknown;\n readSubscription?: (options?: {\n authCredentialsStoreMode?: unknown;\n }) => Promise<CodexResolvedAuthentication | undefined>;\n}): Promise<CodexResolvedAuthentication> {\n const environment = resolveCodexEnv(auth, processEnv);\n if (isHarnessAuthenticationEnvironment(auth)) {\n return { environment };\n }\n if (\n !shouldResolveNativeSubscription({\n auth,\n env: environment,\n hasDirectCredential: environment.CODEX_API_KEY != null,\n })\n ) {\n return { environment };\n }\n\n return (\n (await readSubscription({ authCredentialsStoreMode })) ?? { environment }\n );\n}\n\nexport async function readCodexSubscription({\n env = process.env,\n homeDirectory = homedir(),\n authCredentialsStoreMode,\n platform = process.platform,\n keyring,\n fetch,\n}: {\n env?: Record<string, string | undefined>;\n homeDirectory?: string;\n authCredentialsStoreMode?: unknown;\n platform?: NodeJS.Platform;\n keyring?: CodexKeyring;\n fetch?: typeof globalThis.fetch;\n} = {}): Promise<CodexResolvedAuthentication | undefined> {\n const codexHome = resolve(env.CODEX_HOME ?? join(homeDirectory, '.codex'));\n const authPath = join(codexHome, 'auth.json');\n const storageMode =\n toCodexAuthCredentialsStoreMode(authCredentialsStoreMode) ??\n (await readCodexAuthCredentialsStoreMode({ codexHome })) ??\n 'file';\n const stored = await readCodexAuthStore({\n codexHome,\n authPath,\n storageMode,\n keyring: keyring ?? createCodexKeyring({ platform }),\n });\n if (stored == null) return undefined;\n\n const credential = await toCodexCredential(stored.value);\n if (credential == null) return undefined;\n\n let accessToken = credential.accessToken;\n if (isAccessTokenExpiringSoon({ expiresAt: credential.expiresAt })) {\n const refreshed = await refreshOAuthAccessToken({\n tokenUrl: OPENAI_TOKEN_URL,\n clientId: OPENAI_CLIENT_ID,\n refreshToken: credential.refreshToken,\n requestFormat: 'json',\n ...(fetch == null ? {} : { fetch }),\n });\n accessToken = refreshed.accessToken;\n await stored.write({\n ...stored.value,\n last_refresh: new Date().toISOString(),\n tokens: {\n ...stored.value.tokens,\n access_token: refreshed.accessToken,\n refresh_token: refreshed.refreshToken ?? credential.refreshToken,\n },\n });\n }\n\n return {\n environment: {\n CODEX_API_KEY: accessToken,\n OPENAI_BASE_URL: CHATGPT_CODEX_BASE_URL,\n },\n ...(credential.accountId == null\n ? {}\n : {\n requestHeaders: {\n 'ChatGPT-Account-ID': credential.accountId,\n },\n }),\n };\n}\n\nasync function readCodexAuthStore({\n codexHome,\n authPath,\n storageMode,\n keyring,\n}: {\n codexHome: string;\n authPath: string;\n storageMode: CodexAuthCredentialsStoreMode;\n keyring: CodexKeyring | undefined;\n}): Promise<\n | {\n value: CodexAuthFile;\n write(value: CodexAuthFile): Promise<void>;\n }\n | undefined\n> {\n if (storageMode === 'ephemeral') return undefined;\n\n const readFileStore = async () => {\n const value = await readCodexAuthFile(authPath);\n return value == null\n ? undefined\n : {\n value,\n write: (updated: CodexAuthFile) =>\n writeCodexAuthFile({ authPath, value: updated }),\n };\n };\n const readKeyringStore = async () => {\n if (keyring == null) return undefined;\n const canonicalHome = await realpath(codexHome).catch(() => codexHome);\n const account = `cli|${createHash('sha256')\n .update(canonicalHome)\n .digest('hex')\n .slice(0, 16)}`;\n const text = await keyring.read({ service: 'Codex Auth', account });\n if (text == null) return undefined;\n const value = await parseCodexAuthFile(text);\n return value == null\n ? undefined\n : {\n value,\n write: (updated: CodexAuthFile) =>\n keyring.write({\n service: 'Codex Auth',\n account,\n value: JSON.stringify(updated),\n }),\n };\n };\n\n if (storageMode === 'file') return readFileStore();\n if (storageMode === 'keyring') return readKeyringStore();\n return (await readKeyringStore()) ?? readFileStore();\n}\n\nasync function readCodexAuthCredentialsStoreMode({\n codexHome,\n}: {\n codexHome: string;\n}): Promise<CodexAuthCredentialsStoreMode | undefined> {\n const text = await readFile(join(codexHome, 'config.toml'), 'utf8').catch(\n () => undefined,\n );\n if (text == null) return undefined;\n for (const line of text.split(/\\r?\\n/)) {\n if (line.trimStart().startsWith('[')) return undefined;\n const match =\n /^\\s*cli_auth_credentials_store\\s*=\\s*[\"'](file|keyring|auto|ephemeral)[\"']\\s*(?:#.*)?$/.exec(\n line,\n );\n if (match != null) {\n return toCodexAuthCredentialsStoreMode(match[1]);\n }\n }\n return undefined;\n}\n\nfunction toCodexAuthCredentialsStoreMode(\n value: unknown,\n): CodexAuthCredentialsStoreMode | undefined {\n return value === 'file' ||\n value === 'keyring' ||\n value === 'auto' ||\n value === 'ephemeral'\n ? value\n : undefined;\n}\n\nasync function readCodexAuthFile(\n authPath: string,\n): Promise<CodexAuthFile | undefined> {\n const text = await readFile(authPath, 'utf8').catch(() => undefined);\n return text == null ? undefined : parseCodexAuthFile(text);\n}\n\nasync function parseCodexAuthFile(\n text: string,\n): Promise<CodexAuthFile | undefined> {\n const parsed = await safeParseJSON({ text });\n return parsed.success && isRecord(parsed.value)\n ? (parsed.value as CodexAuthFile)\n : undefined;\n}\n\nasync function toCodexCredential(value: CodexAuthFile): Promise<\n | {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n accountId?: string;\n }\n | undefined\n> {\n if (value.auth_mode !== 'chatgpt' || !isRecord(value.tokens)) {\n return undefined;\n }\n const accessToken = value.tokens.access_token;\n const refreshToken = value.tokens.refresh_token;\n if (typeof accessToken !== 'string' || typeof refreshToken !== 'string') {\n return undefined;\n }\n const expiresAt = await getJwtExpiresAt({ token: accessToken });\n if (expiresAt == null) return undefined;\n const accountId = value.tokens.account_id;\n return {\n accessToken,\n refreshToken,\n expiresAt,\n ...(typeof accountId === 'string' ? { accountId } : {}),\n };\n}\n\nasync function writeCodexAuthFile({\n authPath,\n value,\n}: {\n authPath: string;\n value: CodexAuthFile;\n}): Promise<void> {\n await mkdir(dirname(authPath), { recursive: true });\n const temporaryPath = `${authPath}.${process.pid}.tmp`;\n await writeFile(temporaryPath, `${JSON.stringify(value, null, 2)}\\n`, {\n mode: 0o600,\n });\n await chmod(temporaryPath, 0o600);\n await rename(temporaryPath, authPath);\n}\n\nfunction createCodexKeyring({\n platform,\n}: {\n platform: NodeJS.Platform;\n}): CodexKeyring | undefined {\n if (isMacOS(platform)) {\n return {\n async read({ service, account }) {\n return readMacOSKeychainPassword({ service, account });\n },\n async write({ service, account, value }) {\n const command = `add-generic-password -U -s ${shellQuoteForSecurity(service)} -a ${shellQuoteForSecurity(account)} -X ${Buffer.from(value, 'utf8').toString('hex')}\\n`;\n await runCommandWithInput({\n command: '/usr/bin/security',\n args: ['-i'],\n input: command,\n });\n },\n };\n }\n if (isLinux(platform)) {\n return {\n async read({ service, account }) {\n return readLinuxSecretServicePassword({\n attributes: {\n service,\n username: account,\n target: 'default',\n },\n });\n },\n async write({ service, account, value }) {\n await runCommandWithInput({\n command: 'secret-tool',\n args: [\n 'store',\n '--label',\n `${account}@${service}:default`,\n 'service',\n service,\n 'username',\n account,\n 'target',\n 'default',\n 'application',\n 'rust-keyring',\n ],\n input: value,\n });\n },\n };\n }\n if (isWindows(platform)) {\n return createWindowsCodexKeyring();\n }\n return undefined;\n}\n\nfunction shellQuoteForSecurity(value: string): string {\n return `\"${value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n}\n\nasync function runCommandWithInput({\n command,\n args,\n input,\n env,\n}: {\n command: string;\n args: string[];\n input: string;\n env?: NodeJS.ProcessEnv;\n}): Promise<void> {\n await new Promise<void>((resolvePromise, reject) => {\n const child = spawn(command, args, {\n stdio: ['pipe', 'ignore', 'pipe'],\n ...(env == null ? {} : { env }),\n });\n let stderr = '';\n child.stderr.setEncoding('utf8');\n child.stderr.on('data', chunk => {\n stderr += chunk;\n });\n child.once('error', reject);\n child.once('close', code => {\n if (code === 0) resolvePromise();\n else reject(new Error(stderr || `${command} exited with code ${code}.`));\n });\n child.stdin.end(input);\n });\n}\n\nfunction createWindowsCodexKeyring(): CodexKeyring {\n const source = `\nusing System;\nusing System.Runtime.InteropServices;\nusing System.Text;\npublic static class CodexCredentialManager {\n [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]\n public struct Credential {\n public UInt32 Flags; public UInt32 Type; public string TargetName;\n public string Comment; public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;\n public UInt32 CredentialBlobSize; public IntPtr CredentialBlob;\n public UInt32 Persist; public UInt32 AttributeCount; public IntPtr Attributes;\n public string TargetAlias; public string UserName;\n }\n [DllImport(\"advapi32.dll\", EntryPoint = \"CredWriteW\", CharSet = CharSet.Unicode, SetLastError = true)]\n static extern bool CredWrite(ref Credential credential, UInt32 flags);\n public static void Write(string target, string userName, string value) {\n byte[] bytes = Encoding.Unicode.GetBytes(value);\n IntPtr blob = Marshal.AllocHGlobal(bytes.Length);\n try {\n Marshal.Copy(bytes, 0, blob, bytes.Length);\n Credential credential = new Credential {\n Type = 1, TargetName = target, CredentialBlobSize = (UInt32)bytes.Length,\n CredentialBlob = blob, Persist = 3, UserName = userName\n };\n if (!CredWrite(ref credential, 0)) throw new System.ComponentModel.Win32Exception();\n } finally { Marshal.FreeHGlobal(blob); }\n }\n}`;\n return {\n async read({ service, account }) {\n return readWindowsCredentialManagerPassword({\n targetName: `${account}.${service}`,\n });\n },\n async write({ service, account, value }) {\n const script = `Add-Type -TypeDefinition $env:AI_SDK_CODEX_CREDENTIAL_SOURCE; $value = [Console]::In.ReadToEnd(); [CodexCredentialManager]::Write($env:AI_SDK_CODEX_CREDENTIAL_TARGET, $env:AI_SDK_CODEX_CREDENTIAL_USER, $value)`;\n await runCommandWithInput({\n command: 'powershell.exe',\n args: ['-NoProfile', '-NonInteractive', '-Command', script],\n input: value,\n env: {\n ...process.env,\n AI_SDK_CODEX_CREDENTIAL_SOURCE: source,\n AI_SDK_CODEX_CREDENTIAL_TARGET: `${account}.${service}`,\n AI_SDK_CODEX_CREDENTIAL_USER: account,\n },\n });\n },\n };\n}\n","import {\n harnessV1BridgeInboundCommandSchemas,\n harnessV1BridgeOutboundMessageSchema,\n harnessV1BridgeReadySchema,\n harnessV1BridgeStartBaseSchema,\n} from '@ai-sdk/harness';\nimport { z } from 'zod/v4';\n\n/*\n * Codex's bridge wire protocol. The outbound events (including `file-change`\n * and the `bridge-thread` resume coordinate), transport frames, shared inbound\n * commands, and `bridge-ready` line all come from the shared `@ai-sdk/harness`\n * protocol — the only Codex-specific piece is the `start` payload.\n */\n\nexport const outboundMessageSchema = harnessV1BridgeOutboundMessageSchema;\nexport type OutboundMessage = z.infer<typeof outboundMessageSchema>;\n\nexport const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({\n instructions: z.string().optional(),\n reasoningEffort: z.enum(['low', 'medium', 'high', 'xhigh', 'max']).optional(),\n webSearch: z.boolean().optional(),\n codexConfig: z.record(z.string(), z.unknown()).optional(),\n mcpServers: z.record(z.string(), z.unknown()).optional(),\n headers: z.record(z.string(), z.string()).optional(),\n // Resume signal. When supplied, the bridge calls\n // `codex.resumeThread(resumeThreadId, …)` instead of starting a fresh thread.\n // The host sources the id from lifecycle state `data` cached from a prior\n // `agent.detach`.\n resumeThreadId: z.string().optional(),\n restartThread: z.boolean().optional(),\n});\n\nexport type StartMessage = z.infer<typeof startMessageSchema>;\n\nexport const inboundMessageSchema = z.discriminatedUnion('type', [\n startMessageSchema,\n ...harnessV1BridgeInboundCommandSchemas,\n]);\nexport type InboundMessage = z.infer<typeof inboundMessageSchema>;\n\nexport const bridgeReadySchema = harnessV1BridgeReadySchema;\nexport type BridgeReady = z.infer<typeof bridgeReadySchema>;\n","/*\n * Temporary workaround for upstream codex CLI bug\n * https://github.com/openai/codex/issues/19425 — MCP tools registered via\n * `mcp_servers.*` are not exposed to the model in `codex exec --experimental-json`\n * mode (which is what `@openai/codex-sdk` uses). The MCP handshake completes\n * and `tools/list` succeeds, but codex never registers the tools as\n * model-callable functions.\n *\n * Until that's fixed upstream, this file implements a CLI-based relay:\n *\n * 1. A small Node script is written into harness-owned session state at turn\n * start (`buildCliShimScript`). It accepts `<toolName> <jsonInput>` as\n * argv, POSTs to the same HTTP relay the MCP shim uses, and prints the\n * result to stdout.\n *\n * 2. Tool descriptions and invocation instructions are injected into the\n * initial user prompt by the host adapter, telling the model to call host\n * tools by running `node <shim-path> <toolName> '<jsonInput>'` via its\n * built-in `bash` tool.\n *\n * 3. The bridge's event loop suppresses the matching `command_execution`\n * events (`isToolRelayCommand`) so callers receive clean `tool-call` /\n * `tool-result` events from the HTTP relay rather than seeing the\n * relay invocations as raw bash commands.\n *\n * Once #19425 is fixed and MCP tools are properly exposed in exec mode, the\n * three hookpoints in `bridge/index.ts` can be removed along with this file.\n */\nexport const CLI_SHIM_FILENAME = 'harness-tool.mjs';\n\nexport function buildCliShimScript({\n relayPort,\n}: {\n relayPort: number;\n}): string {\n return `#!/usr/bin/env node\nconst [toolName, inputJson = '{}'] = process.argv.slice(2);\nif (!toolName) {\n console.error('Usage: harness-tool <tool_name> <json_input>');\n process.exit(64);\n}\nlet input;\ntry {\n input = JSON.parse(inputJson);\n} catch (error) {\n console.error('Invalid JSON input: ' + (error instanceof Error ? error.message : String(error)));\n process.exit(64);\n}\nconst requestId = 'cli-' + Date.now() + '-' + Math.random().toString(16).slice(2);\nconst response = await fetch('http://127.0.0.1:${relayPort}', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ requestId, toolName, input }),\n});\nconst text = await response.text();\nlet payload;\ntry {\n payload = text ? JSON.parse(text) : {};\n} catch {\n payload = { error: text };\n}\nif (!response.ok || payload.error) {\n console.error(String(payload.error ?? ('tool relay failed with HTTP ' + response.status)));\n process.exit(1);\n}\nconsole.log(JSON.stringify(payload.result ?? payload, null, 2));\n`;\n}\n\nexport function isToolRelayCommand({\n command,\n cliShimPath,\n}: {\n command: string;\n cliShimPath: string;\n}): boolean {\n return parseToolRelayCommands({ command, cliShimPath }) !== undefined;\n}\n\nexport function parseToolRelayCommand({\n command,\n cliShimPath,\n}: {\n command: string;\n cliShimPath: string;\n}): { toolName: string; input: unknown } | undefined {\n const calls = parseToolRelayCommands({ command, cliShimPath });\n return calls?.length === 1 ? calls[0] : undefined;\n}\n\nexport function parseToolRelayCommands({\n command,\n cliShimPath,\n}: {\n command: string;\n cliShimPath: string;\n}): Array<{ toolName: string; input: unknown }> | undefined {\n return parseToolRelayCommandsInternal({ command, cliShimPath, depth: 0 });\n}\n\nfunction parseToolRelayCommandsInternal({\n command,\n cliShimPath,\n depth,\n}: {\n command: string;\n cliShimPath: string;\n depth: number;\n}): Array<{ toolName: string; input: unknown }> | undefined {\n const commands = splitShellAndCommands(command);\n if (!commands) return undefined;\n if (commands.length > 1) {\n const relayCalls: Array<{ toolName: string; input: unknown }> = [];\n for (const nestedCommand of commands) {\n const nestedCalls = parseToolRelayCommandsInternal({\n command: nestedCommand,\n cliShimPath,\n depth,\n });\n if (!nestedCalls) return undefined;\n relayCalls.push(...nestedCalls);\n }\n return relayCalls;\n }\n\n const argv = parseShellWords(command);\n if (!argv) return undefined;\n\n const relayCall = parseDirectToolRelayArgv({ argv, cliShimPath });\n if (relayCall) return [relayCall];\n\n const innerCommand = extractShellEvalCommand(argv);\n if (!innerCommand || depth >= 2) return undefined;\n return parseToolRelayCommandsInternal({\n command: innerCommand,\n cliShimPath,\n depth: depth + 1,\n });\n}\n\nfunction parseDirectToolRelayArgv({\n argv,\n cliShimPath,\n}: {\n argv: string[];\n cliShimPath: string;\n}): { toolName: string; input: unknown } | undefined {\n if (argv.length < 3 || argv.length > 4) return undefined;\n if (argv[0] !== 'node' || argv[1] !== cliShimPath) return undefined;\n const toolName = argv[2];\n if (!toolName) return undefined;\n try {\n return { toolName, input: JSON.parse(argv[3] ?? '{}') };\n } catch {\n return undefined;\n }\n}\n\nfunction extractShellEvalCommand(argv: string[]): string | undefined {\n if (argv.length !== 3) return undefined;\n const shellName = argv[0].split('/').at(-1);\n if (shellName !== 'bash' && shellName !== 'sh' && shellName !== 'zsh') {\n return undefined;\n }\n if (argv[1] !== '-c' && argv[1] !== '-lc') return undefined;\n return argv[2];\n}\n\nfunction splitShellAndCommands(command: string): string[] | undefined {\n const commands: string[] = [];\n let start = 0;\n let quote: '\"' | \"'\" | undefined;\n\n for (let i = 0; i < command.length; i++) {\n const char = command[i];\n if (quote === \"'\") {\n if (char === \"'\") quote = undefined;\n continue;\n }\n if (quote === '\"') {\n if (char === '\"') {\n quote = undefined;\n } else if (char === '\\\\') {\n i++;\n }\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n continue;\n }\n if (char === '\\\\') {\n i++;\n continue;\n }\n if (char === '&' && command[i + 1] === '&') {\n const nestedCommand = command.slice(start, i).trim();\n if (!nestedCommand) return undefined;\n commands.push(nestedCommand);\n start = i + 2;\n i++;\n }\n }\n\n if (quote) return undefined;\n const nestedCommand = command.slice(start).trim();\n if (!nestedCommand) return undefined;\n commands.push(nestedCommand);\n return commands;\n}\n\nfunction parseShellWords(command: string): string[] | undefined {\n const words: string[] = [];\n let current = '';\n let quote: '\"' | \"'\" | undefined;\n let hasCurrent = false;\n\n const pushCurrent = () => {\n if (!hasCurrent) return;\n words.push(current);\n current = '';\n hasCurrent = false;\n };\n\n for (let i = 0; i < command.length; i++) {\n const char = command[i];\n if (quote === \"'\") {\n if (char === \"'\") {\n quote = undefined;\n } else {\n current += char;\n }\n hasCurrent = true;\n continue;\n }\n if (quote === '\"') {\n if (char === '\"') {\n quote = undefined;\n } else if (char === '\\\\' && i + 1 < command.length) {\n current += command[++i];\n } else {\n current += char;\n }\n hasCurrent = true;\n continue;\n }\n if (/\\s/.test(char)) {\n pushCurrent();\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n hasCurrent = true;\n continue;\n }\n if (char === '\\\\' && i + 1 < command.length) {\n current += command[++i];\n hasCurrent = true;\n continue;\n }\n if (/[;&|<>()`$]/.test(char)) return undefined;\n current += char;\n hasCurrent = true;\n }\n if (quote) return undefined;\n pushCurrent();\n return words;\n}\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n","import { createCodex } from './codex-harness';\n\n/**\n * Default `codex` harness instance with no overrides — suitable for the\n * common case where the underlying `codex` CLI's defaults are fine.\n * Equivalent to `createCodex()`.\n */\nexport const codex = createCodex();\n\nexport { createCodex } from './codex-harness';\nexport { VERSION } from './version';\nexport type { CodexHarnessSettings } from './codex-harness';\nexport type { CodexAuthenticationMode } from './codex-auth';\n"],"mappings":"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","names":["createHash","z","isHarnessAuthenticationEnvironment","isHarnessAuthenticationEnvironment","z","endpoint","proc","resolve","createHash"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/harness-codex",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.124",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@ai-sdk/harness": "1.0.
|
|
30
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
29
|
+
"@ai-sdk/harness": "1.0.122",
|
|
30
|
+
"@ai-sdk/provider-utils": "5.0.46",
|
|
31
31
|
"ws": "^8.21.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
package/src/codex-bootstrap.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import type { HarnessV1Bootstrap } from '@ai-sdk/harness';
|
|
2
2
|
import { createReadBridgeAsset } from '@ai-sdk/harness/utils';
|
|
3
3
|
|
|
4
|
+
/*
|
|
5
|
+
* Keep every asset URL literal so bundlers can emit each file separately.
|
|
6
|
+
* Dynamic new URL() paths can collapse multiple assets into one resolution.
|
|
7
|
+
*/
|
|
4
8
|
const readBridgeAsset = createReadBridgeAsset({
|
|
5
|
-
|
|
9
|
+
'package.json': new URL('./bridge/package.json', import.meta.url),
|
|
10
|
+
'pnpm-lock.yaml': new URL('./bridge/pnpm-lock.yaml', import.meta.url),
|
|
11
|
+
'index.mjs': new URL('./bridge/index.mjs', import.meta.url),
|
|
6
12
|
});
|
|
7
13
|
|
|
8
14
|
/*
|