@ai-sdk/harness-claude-code 1.0.53 → 1.0.54

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 CHANGED
@@ -1,5 +1,16 @@
1
1
  # @ai-sdk/harness-claude-code
2
2
 
3
+ ## 1.0.54
4
+
5
+ ### Patch Changes
6
+
7
+ - bdde5d9: fix(harness): avoid placing harness bootstrap files in `/tmp` and instead use sandbox working directory
8
+ - Updated dependencies [5fc7da5]
9
+ - Updated dependencies [bdde5d9]
10
+ - Updated dependencies [93b2acd]
11
+ - @ai-sdk/provider-utils@5.0.18
12
+ - @ai-sdk/harness@1.0.53
13
+
3
14
  ## 1.0.53
4
15
 
5
16
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // src/claude-code-harness.ts
2
2
  import { randomBytes } from "crypto";
3
3
  import { readFile } from "fs/promises";
4
+ import { posix } from "path";
4
5
  import { fileURLToPath } from "url";
5
6
  import {
6
7
  commonTool,
@@ -147,7 +148,7 @@ var inboundMessageSchema = z.discriminatedUnion("type", [
147
148
  ]);
148
149
 
149
150
  // src/version.ts
150
- var VERSION = true ? "1.0.53" : "0.0.0-test";
151
+ var VERSION = true ? "1.0.54" : "0.0.0-test";
151
152
 
152
153
  // src/claude-code-harness.ts
153
154
  var CLAUDE_CODE_CLIENT_APP = `ai-sdk/harness-claude-code/${VERSION}`;
@@ -423,7 +424,7 @@ var CLAUDE_CODE_BUILTIN_TOOLS = {
423
424
  })
424
425
  })
425
426
  };
426
- var BOOTSTRAP_DIR = "/tmp/harness/claude-code";
427
+ var BOOTSTRAP_DIR = ".harness-bootstrap/claude-code";
427
428
  var claudeCodeBridgeCoordsSchema = z2.object({
428
429
  port: z2.number(),
429
430
  token: z2.string(),
@@ -462,12 +463,11 @@ function createClaudeCode(settings = {}) {
462
463
  { path: `${BOOTSTRAP_DIR}/bridge.mjs`, content: bridge }
463
464
  ],
464
465
  commands: [
465
- { command: `mkdir -p ${BOOTSTRAP_DIR}` },
466
466
  {
467
- command: `pnpm --dir ${BOOTSTRAP_DIR} install --frozen-lockfile --store-dir ${BOOTSTRAP_DIR}/.pnpm-store`
467
+ command: "pnpm install --frozen-lockfile --store-dir .pnpm-store"
468
468
  },
469
469
  {
470
- command: `cd ${BOOTSTRAP_DIR} && if [ -f node_modules/@anthropic-ai/claude-code/install.cjs ]; then node node_modules/@anthropic-ai/claude-code/install.cjs; fi && ./node_modules/.bin/claude --version`
470
+ command: "if [ -f node_modules/@anthropic-ai/claude-code/install.cjs ]; then node node_modules/@anthropic-ai/claude-code/install.cjs; fi && ./node_modules/.bin/claude --version"
471
471
  }
472
472
  ]
473
473
  };
@@ -477,6 +477,10 @@ function createClaudeCode(settings = {}) {
477
477
  const sandboxSession = startOpts.sandboxSession;
478
478
  const session = sandboxSession.restricted();
479
479
  const sandboxId = sandboxSession.id;
480
+ const bootstrapDir = posix.resolve(
481
+ sandboxSession.defaultWorkingDirectory,
482
+ BOOTSTRAP_DIR
483
+ );
480
484
  const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;
481
485
  const isResume = lifecycleState != null;
482
486
  const isContinue = startOpts.continueFrom != null;
@@ -593,7 +597,7 @@ function createClaudeCode(settings = {}) {
593
597
  abortSignal: startOpts.abortSignal
594
598
  });
595
599
  const proc = await session.spawn({
596
- command: `node ${BOOTSTRAP_DIR}/bridge.mjs --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)}`,
600
+ command: `node ${shellQuote(`${bootstrapDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)}`,
597
601
  env,
598
602
  abortSignal: startOpts.abortSignal
599
603
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/claude-code-harness.ts","../src/claude-code-auth.ts","../src/claude-code-bridge-protocol.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\nimport { fileURLToPath } from 'node:url';\nimport {\n commonTool,\n harnessV1DiagnosticFromBridgeFrame,\n HarnessCapabilityUnsupportedError,\n type HarnessV1,\n type HarnessV1Bootstrap,\n type HarnessV1BuiltinToolFiltering,\n type HarnessV1BuiltinTool,\n type HarnessV1ContinueTurnState,\n type HarnessV1DebugConfig,\n type HarnessV1PermissionMode,\n type HarnessV1Prompt,\n type HarnessV1PromptControl,\n type HarnessV1ResumeSessionState,\n type HarnessV1NetworkSandboxSession,\n type HarnessV1Session,\n type HarnessV1Skill,\n type HarnessV1StreamPart,\n} from '@ai-sdk/harness';\nimport {\n classifyDiskLog,\n createBridgeErrorHandler,\n createBridgeStartupError,\n drainBridgeProcessStream,\n forwardBridgeProcessStream,\n markBridgeStarting,\n resolveSandboxHomeDir,\n SandboxChannel,\n shellQuote,\n waitForBridgeReady,\n writeSkills as writeHarnessSkills,\n} from '@ai-sdk/harness/utils';\nimport {\n tool,\n type Experimental_SandboxSession,\n type Experimental_SandboxProcess,\n} from '@ai-sdk/provider-utils';\nimport { WebSocket } from 'ws';\nimport { z } from 'zod/v4';\nimport {\n resolveClaudeCodeEnv,\n type ClaudeCodeAuthOptions,\n} from './claude-code-auth';\nimport {\n outboundMessageSchema,\n type InboundMessage,\n type OutboundMessage,\n} from './claude-code-bridge-protocol';\nimport type { ClaudeCodeThinkingConfig } from './claude-code-thinking';\nimport { VERSION } from './version';\n\ntype ClaudeCodeChannel = SandboxChannel<OutboundMessage, InboundMessage>;\ntype ClaudeCodeRespawnStrategy = 'replay' | 'rerun';\n\n/**\n * Value to use in User-Agent and `x-client-app` headers.\n */\nconst CLAUDE_CODE_CLIENT_APP = `ai-sdk/harness-claude-code/${VERSION}`;\n\nexport type ClaudeCodeHarnessSettings = {\n readonly auth?: ClaudeCodeAuthOptions;\n /**\n * Anthropic model id the underlying `claude` CLI should use. Leaving this\n * unset defers to the CLI's default.\n */\n readonly model?: string;\n /**\n * Hard cap on how many internal turns the CLI can take before yielding\n * back to the caller. Unset means the CLI's default.\n */\n readonly maxTurns?: number;\n /**\n * Controls extended-thinking behavior and whether reasoning is summarized or\n * omitted. Defaults to `{ type: 'adaptive', display: 'summarized' }`.\n */\n readonly thinking?: ClaudeCodeThinkingConfig;\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 /** Maximum milliseconds to wait for the bridge to advertise its port. Defaults to 120000. */\n readonly startupTimeoutMs?: number;\n};\n\n/*\n * Every native tool the Claude Code CLI can invoke, declared as a `ToolSet`\n * keyed by what the bridge emits as `toolName` on the wire\n * (`commonName ?? nativeName`). Schemas transcribed from\n * `@anthropic-ai/claude-agent-sdk`'s `agentSdkTypes.d.ts`.\n *\n * `MCP` (the generic proxy tool inside the Claude Code SDK) is intentionally\n * omitted — the bridge filters out `mcp__harness-tools__*` tool names before\n * emitting them, and other MCP invocations come through with their own\n * server-tool names rather than the literal `'Mcp'` token.\n */\nconst CLAUDE_CODE_BUILTIN_TOOLS = {\n read: commonTool('read', {\n nativeName: 'Read',\n toolUseKind: 'readonly',\n description: 'Read file contents (text, image, PDF, notebook)',\n inputSchema: z.object({\n file_path: z.string(),\n offset: z.number().optional(),\n limit: z.number().optional(),\n pages: z.string().optional(),\n }),\n }),\n write: commonTool('write', {\n nativeName: 'Write',\n toolUseKind: 'edit',\n description: 'Overwrite or create a file at an absolute path',\n inputSchema: z.object({\n file_path: z.string(),\n content: z.string(),\n }),\n }),\n edit: commonTool('edit', {\n nativeName: 'Edit',\n toolUseKind: 'edit',\n description: 'Edit a file by exact string replacement',\n inputSchema: z.object({\n file_path: z.string(),\n old_string: z.string(),\n new_string: z.string(),\n replace_all: z.boolean().optional(),\n }),\n }),\n bash: commonTool('bash', {\n nativeName: 'Bash',\n toolUseKind: 'bash',\n description: 'Execute a shell command, optionally in background',\n inputSchema: z.object({\n command: z.string(),\n timeout: z.number().optional(),\n description: z.string().optional(),\n run_in_background: z.boolean().optional(),\n dangerouslyDisableSandbox: z.boolean().optional(),\n }),\n }),\n glob: commonTool('glob', {\n nativeName: 'Glob',\n toolUseKind: 'readonly',\n description: 'Fast file-pattern search using glob syntax',\n inputSchema: z.object({\n pattern: z.string(),\n path: z.string().optional(),\n }),\n }),\n grep: commonTool('grep', {\n nativeName: 'Grep',\n toolUseKind: 'readonly',\n description: 'Regex search over file contents via ripgrep',\n inputSchema: z.object({\n pattern: z.string(),\n path: z.string().optional(),\n glob: z.string().optional(),\n output_mode: z\n .enum(['content', 'files_with_matches', 'count'])\n .optional(),\n '-B': z.number().optional(),\n '-A': z.number().optional(),\n '-C': z.number().optional(),\n context: z.number().optional(),\n '-n': z.boolean().optional(),\n '-i': z.boolean().optional(),\n '-o': z.boolean().optional(),\n type: z.string().optional(),\n head_limit: z.number().optional(),\n offset: z.number().optional(),\n multiline: z.boolean().optional(),\n }),\n }),\n webSearch: commonTool('webSearch', {\n nativeName: 'WebSearch',\n toolUseKind: 'readonly',\n description: 'Issue web search queries with optional domain filters',\n inputSchema: z.object({\n query: z.string(),\n allowed_domains: z.array(z.string()).optional(),\n blocked_domains: z.array(z.string()).optional(),\n }),\n }),\n\n WebFetch: tool({\n description: 'Fetch a URL and run a prompt against its content',\n inputSchema: z.object({\n url: z.string(),\n prompt: z.string(),\n }),\n }),\n NotebookEdit: tool({\n description: 'Edit, insert, or delete a Jupyter notebook cell',\n inputSchema: z.object({\n notebook_path: z.string(),\n new_source: z.string(),\n cell_id: z.string().optional(),\n cell_type: z.enum(['code', 'markdown']).optional(),\n edit_mode: z.enum(['replace', 'insert', 'delete']).optional(),\n }),\n }),\n TodoWrite: tool({\n description: 'Replace the session todo list',\n inputSchema: z.object({\n todos: z.array(\n z.object({\n content: z.string(),\n status: z.enum(['pending', 'in_progress', 'completed']),\n activeForm: z.string(),\n }),\n ),\n }),\n }),\n Agent: tool({\n description: 'Spawn a subagent with a task',\n inputSchema: z.object({\n description: z.string(),\n prompt: z.string(),\n subagent_type: z.string().optional(),\n model: z.enum(['sonnet', 'opus', 'haiku']).optional(),\n run_in_background: z.boolean().optional(),\n name: z.string().optional(),\n team_name: z.string().optional(),\n mode: z\n .enum([\n 'acceptEdits',\n 'auto',\n 'bypassPermissions',\n 'default',\n 'dontAsk',\n 'plan',\n ])\n .optional(),\n isolation: z.literal('worktree').optional(),\n }),\n }),\n TaskCreate: tool({\n description: 'Create a task in the session-local task list',\n inputSchema: z.object({\n subject: z.string(),\n description: z.string(),\n activeForm: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n }),\n }),\n TaskGet: tool({\n description: 'Retrieve a task by id',\n inputSchema: z.object({ taskId: z.string() }),\n }),\n TaskUpdate: tool({\n description: 'Update fields of an existing task',\n inputSchema: z.object({\n taskId: z.string(),\n subject: z.string().optional(),\n description: z.string().optional(),\n activeForm: z.string().optional(),\n status: z\n .union([\n z.enum(['pending', 'in_progress', 'completed']),\n z.literal('deleted'),\n ])\n .optional(),\n addBlocks: z.array(z.string()).optional(),\n addBlockedBy: z.array(z.string()).optional(),\n owner: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n }),\n }),\n TaskList: tool({\n description: 'Return all tasks in the session-local task list',\n inputSchema: z.object({}),\n }),\n TaskStop: tool({\n description: 'Stop a running background task by id',\n inputSchema: z.object({\n task_id: z.string().optional(),\n shell_id: z.string().optional(),\n }),\n }),\n TaskOutput: tool({\n description: 'Poll for output from a background task',\n inputSchema: z.object({\n task_id: z.string(),\n block: z.boolean(),\n timeout: z.number(),\n }),\n }),\n Monitor: tool({\n description: 'Run and monitor a shell command',\n inputSchema: z.object({\n command: z.string(),\n description: z.string().optional(),\n timeout_ms: z.number().optional(),\n persistent: z.boolean().optional(),\n }),\n }),\n ListMcpResources: tool({\n description: 'List resources available from MCP servers',\n inputSchema: z.object({ server: z.string().optional() }),\n }),\n ReadMcpResource: tool({\n description: 'Read a specific MCP resource by URI',\n inputSchema: z.object({ server: z.string(), uri: z.string() }),\n }),\n ExitPlanMode: tool({\n description: 'Exit plan mode with optional permission approvals',\n inputSchema: z.looseObject({\n allowedPrompts: z\n .array(\n z.object({\n tool: z.literal('Bash'),\n prompt: z.string(),\n }),\n )\n .optional(),\n }),\n }),\n EnterWorktree: tool({\n description: 'Create or enter an isolated git worktree',\n inputSchema: z.object({\n name: z.string().optional(),\n path: z.string().optional(),\n }),\n }),\n ExitWorktree: tool({\n description: 'Exit the current worktree session',\n inputSchema: z.object({\n action: z.enum(['keep', 'remove']),\n discard_changes: z.boolean().optional(),\n }),\n }),\n AskUserQuestion: tool({\n description: 'Ask the user multiple-choice questions via a structured UI',\n inputSchema: z.object({\n questions: z\n .array(\n z.object({\n question: z.string(),\n header: z.string(),\n options: z.array(\n z.object({\n label: z.string(),\n description: z.string(),\n preview: z.string().optional(),\n }),\n ),\n multiSelect: z.boolean(),\n }),\n )\n .min(1)\n .max(4),\n answers: z.record(z.string(), z.string()).optional(),\n annotations: z\n .record(\n z.string(),\n z.object({\n preview: z.string().optional(),\n notes: z.string().optional(),\n }),\n )\n .optional(),\n metadata: z.object({ source: z.string().optional() }).optional(),\n }),\n }),\n Skill: {\n ...tool({\n description: 'Activate a skill by name',\n inputSchema: z.object({\n skill: z.string(),\n args: z.string().optional(),\n }),\n }),\n toolUseKind: 'readonly',\n },\n ToolSearch: tool({\n description:\n 'Search deferred MCP / catalog tools so the model can load them on demand',\n inputSchema: z.object({\n query: z.string(),\n max_results: z.number().optional(),\n }),\n }),\n} as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;\n\n/*\n * Bootstrap lives in /tmp because it's pure derived state — the harness can\n * reinstall the CLI and bridge files on any fresh sandbox from the recipe.\n * Persistence comes from the sandbox provider's snapshot, not the path.\n *\n * The session work dir (`startOpts.sessionWorkDir`) and the bridge-state dir\n * derived from `sandboxSession.defaultWorkingDirectory` both live under the sandbox's\n * default working directory — the provider's persistent mount — so the\n * workdir's CLI state (Claude's `~/.claude/projects/<dir>/*.jsonl` thread\n * history is keyed by working directory) and the bridge state files survive\n * both detach -> attach/replay and stop -> snapshot -> resume cycles.\n */\nconst BOOTSTRAP_DIR = '/tmp/harness/claude-code';\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 claudeCodeBridgeCoordsSchema = 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 portion of lifecycle state `data`.\n *\n * A `doStop()` payload is structurally empty (`{}`): the framework derives the\n * sandbox via `provider.resumeSession({ sessionId })`, and the Claude SDK's\n * `{ continue: true }` flag rehydrates the thread from the workdir. A\n * `doDetach()` payload additionally carries `bridge` coordinates for\n * cross-process `attach`. A loose object keeps both shapes valid.\n */\nconst claudeCodeResumeStateSchema = z.looseObject({\n bridge: claudeCodeBridgeCoordsSchema.optional(),\n});\n\ntype ClaudeCodeBridgeCoords = z.infer<typeof claudeCodeBridgeCoordsSchema>;\n\nexport function createClaudeCode(\n settings: ClaudeCodeHarnessSettings = {},\n): HarnessV1<typeof CLAUDE_CODE_BUILTIN_TOOLS> {\n let cachedBootstrap: HarnessV1Bootstrap | undefined;\n const thinking = settings.thinking ?? {\n type: 'adaptive',\n display: 'summarized',\n };\n\n return {\n specificationVersion: 'harness-v1',\n harnessId: 'claude-code',\n builtinTools: CLAUDE_CODE_BUILTIN_TOOLS,\n supportsBuiltinToolApprovals: true,\n supportsBuiltinToolFiltering: true,\n lifecycleStateSchema: claudeCodeResumeStateSchema,\n getBootstrap: async () => {\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: 'claude-code',\n bootstrapDir: BOOTSTRAP_DIR,\n files: [\n { path: `${BOOTSTRAP_DIR}/package.json`, content: pkg },\n { path: `${BOOTSTRAP_DIR}/pnpm-lock.yaml`, content: lock },\n { path: `${BOOTSTRAP_DIR}/bridge.mjs`, content: bridge },\n ],\n commands: [\n { command: `mkdir -p ${BOOTSTRAP_DIR}` },\n {\n command: `pnpm --dir ${BOOTSTRAP_DIR} install --frozen-lockfile --store-dir ${BOOTSTRAP_DIR}/.pnpm-store`,\n },\n {\n command: `cd ${BOOTSTRAP_DIR} && if [ -f node_modules/@anthropic-ai/claude-code/install.cjs ]; then node node_modules/@anthropic-ai/claude-code/install.cjs; fi && ./node_modules/.bin/claude --version`,\n },\n ],\n };\n return cachedBootstrap;\n },\n doStart: async startOpts => {\n const sandboxSession = startOpts.sandboxSession;\n const session = sandboxSession.restricted();\n const sandboxId = sandboxSession.id;\n const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;\n const isResume = lifecycleState != null;\n const isContinue = startOpts.continueFrom != null;\n const coords = isResume\n ? (lifecycleState?.data as { bridge?: ClaudeCodeBridgeCoords })?.bridge\n : undefined;\n\n const workDir = startOpts.sessionWorkDir;\n const sessionDataDir = `${sandboxSession.defaultWorkingDirectory}/.agent-runs/${startOpts.sessionId}`;\n const bridgeStateDir = `${sessionDataDir}/bridge`;\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: 'claude-code',\n sessionId: startOpts.sessionId,\n });\n\n // Builds the `connect` thunk a `SandboxChannel` re-invokes on every\n // (re)connect: open the socket, then wait for `bridge-hello` so the\n // end-to-end link is proven live before any frame is sent.\n const buildConnect = (wsUrl: string) => async (): Promise<WebSocket> => {\n return openBridgeWebSocket({ wsUrl, timeoutMs });\n };\n\n /*\n * Rung 1 — ATTACH. When lifecycle state carries live bridge coordinates,\n * try to reopen a socket to the still-running bridge. Parked sessions wait\n * for the next `start`; suspended turns request replay of everything past\n * the persisted cursor. No spawn, no fresh token (the existing bridge\n * still authorises the persisted one). If the bridge is gone the open\n * throws and we fall through to a spawn-based recovery.\n */\n if (coords) {\n try {\n const attachUrl =\n (await sandboxSession.getPortUrl({\n port: coords.port,\n protocol: 'ws',\n })) + `?agent_bridge_token=${encodeURIComponent(coords.token)}`;\n const attachChannel: ClaudeCodeChannel = new SandboxChannel({\n connect: buildConnect(attachUrl),\n outboundSchema: outboundMessageSchema,\n initialLastSeenEventId: coords.lastSeenEventId,\n onDiagnostic,\n onBridgeError,\n });\n await attachChannel.open(isContinue ? { resume: true } : undefined);\n return createSession({\n sessionId: startOpts.sessionId,\n channel: attachChannel,\n // The live bridge was spawned by another process; this one owns no\n // process handle. The session lifecycle method decides whether the\n // sandbox is left running, stopped, or destroyed.\n proc: undefined,\n model: settings.model,\n maxTurns: settings.maxTurns,\n thinking,\n isResume: true,\n continueOnFirstPrompt: false,\n rerunContinue: false,\n bridgePort: coords.port,\n bridgeToken: coords.token,\n sandboxId,\n debug: startOpts.observability?.debug,\n permissionMode: startOpts.permissionMode,\n builtinToolFiltering: startOpts.builtinToolFiltering,\n skills: startOpts.skills ?? [],\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 * when attach is unavailable (the CLI continues its own thread from the\n * workdir snapshot via `continue: true`).\n */\n let respawnStrategy: ClaudeCodeRespawnStrategy | undefined = isResume\n ? 'rerun'\n : undefined;\n if (coords && isContinue) {\n const logRaw = await Promise.resolve(\n session.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 sandboxHomeDir =\n startOpts.skills && startOpts.skills.length > 0\n ? await resolveSandboxHomeDir({\n sandbox: session,\n abortSignal: startOpts.abortSignal,\n })\n : undefined;\n const port = resolveBridgePort(sandboxSession, settings.port);\n const token = randomBytes(32).toString('hex');\n const env = {\n ...resolveClaudeCodeEnv(settings.auth),\n /*\n * The Claude Agent SDK does not expose arbitrary model-request\n * headers. It reads this environment variable and sends the value as\n * `x-client-app`, while also appending `client-app/<value>` to\n * `User-Agent`, so this is the attribution path for AI Gateway.\n */\n CLAUDE_AGENT_SDK_CLIENT_APP: CLAUDE_CODE_CLIENT_APP,\n BRIDGE_CHANNEL_TOKEN: token,\n BRIDGE_WS_PORT: String(port),\n ...(sandboxHomeDir ? { HOME: sandboxHomeDir } : {}),\n ...(respawnStrategy === 'replay'\n ? { BRIDGE_REPLAY_FROM_DISK: '1' }\n : {}),\n };\n\n /*\n * On a fresh start the workdir, skill files, and bridge-state directory\n * must be created. On any resume they already exist in the\n * sandbox snapshot, so skip the rewrite. The env is sent fresh on every\n * spawn — `BRIDGE_CHANNEL_TOKEN` rotates per start.\n */\n if (respawnStrategy === undefined) {\n await session.run({\n command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,\n abortSignal: startOpts.abortSignal,\n });\n\n if (startOpts.skills && startOpts.skills.length > 0) {\n if (!sandboxHomeDir) {\n throw new Error('Unable to resolve sandbox HOME directory.');\n }\n await writeClaudeCodeSkills({\n sandbox: session,\n homeDir: sandboxHomeDir,\n skills: startOpts.skills,\n abortSignal: startOpts.abortSignal,\n });\n }\n }\n\n await markBridgeStarting({\n sandbox: session,\n bridgeStateDir,\n bridgeType: 'claude-code',\n abortSignal: startOpts.abortSignal,\n });\n\n const proc = await session.spawn({\n command: `node ${BOOTSTRAP_DIR}/bridge.mjs --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)}`,\n env,\n abortSignal: startOpts.abortSignal,\n });\n\n const bridgeStartupStderr: string[] = [];\n const bridgeStartupStderrDone = forwardBridgeProcessStream({\n stream: proc.stderr,\n streamName: 'stderr',\n source: 'claude-code',\n collectTail: bridgeStartupStderr,\n });\n void bridgeStartupStderrDone;\n const { port: boundPort } = await waitForBridgeReady({\n proc,\n sandbox: session,\n bridgeStateDir,\n bridgeType: 'claude-code',\n timeoutMs,\n abortSignal: startOpts.abortSignal,\n createTimeoutError: ({ proc, stdoutTail }) =>\n createBridgeStartupError({\n message: 'claude-code bridge did not become ready in time.',\n proc,\n stdoutTail,\n stderrTail: bridgeStartupStderr,\n stderrDone: bridgeStartupStderrDone,\n }),\n createExitError: ({ proc, stdoutTail }) =>\n createBridgeStartupError({\n message: 'claude-code bridge exited before becoming ready.',\n proc,\n stdoutTail,\n stderrTail: bridgeStartupStderr,\n stderrDone: bridgeStartupStderrDone,\n }),\n });\n void drainBridgeProcessStream(proc.stdout);\n\n const wsUrl =\n (await sandboxSession.getPortUrl({\n port: boundPort,\n protocol: 'ws',\n })) + `?agent_bridge_token=${encodeURIComponent(token)}`;\n\n const channel: ClaudeCodeChannel = new SandboxChannel({\n connect: buildConnect(wsUrl),\n outboundSchema: outboundMessageSchema,\n onDiagnostic,\n onBridgeError,\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`) rather than starting empty.\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 proc,\n model: settings.model,\n maxTurns: settings.maxTurns,\n thinking,\n isResume: respawnStrategy !== undefined,\n continueOnFirstPrompt: respawnStrategy !== undefined,\n rerunContinue: respawnStrategy === 'rerun',\n bridgePort: boundPort,\n bridgeToken: token,\n sandboxId,\n debug: startOpts.observability?.debug,\n permissionMode: startOpts.permissionMode,\n builtinToolFiltering: startOpts.builtinToolFiltering,\n skills: startOpts.skills ?? [],\n });\n },\n };\n}\n\nfunction resolveBridgePort(\n sandboxSession: HarnessV1NetworkSandboxSession,\n override: number | undefined,\n): number {\n if (override !== undefined) return override;\n if (sandboxSession.ports.length > 0) return sandboxSession.ports[0];\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'claude-code',\n message:\n 'The claude-code harness needs a TCP port exposed by the sandbox. ' +\n 'Create the sandbox with `ports: [<port>]` or pass `createClaudeCode({ port })`.',\n });\n}\n\n/**\n * Materialise skill files into\n * `$HOME/.claude/skills/<name>/SKILL.md`. The `claude` CLI\n * auto-discovers skills from that directory on startup, so the files have to\n * be in place before the bridge is spawned without mutating the session\n * workdir. Each file uses the YAML-frontmatter shape the CLI expects.\n */\nasync function writeClaudeCodeSkills({\n sandbox,\n homeDir,\n skills,\n abortSignal,\n}: {\n sandbox: Experimental_SandboxSession;\n homeDir: string;\n skills: ReadonlyArray<HarnessV1Skill>;\n abortSignal?: AbortSignal;\n}): Promise<void> {\n await writeHarnessSkills({\n sandbox,\n rootDir: `${homeDir}/.claude/skills`,\n skills,\n abortSignal,\n invalidSkillNameMessage: ({ name }) =>\n `Invalid Claude Code skill name: ${name}`,\n invalidSkillFilePathMessage: ({ skillName, filePath }) =>\n `Invalid Claude Code skill file path for ${skillName}: ${filePath}`,\n trailingNewline: true,\n });\n}\n\nasync function readBridgeAsset(name: string): Promise<string> {\n const candidates = [\n new URL(`./bridge/${name}`, import.meta.url),\n new URL(`../bridge/${name}`, import.meta.url),\n ];\n let lastErr: unknown;\n for (const url of candidates) {\n try {\n return await readFile(fileURLToPath(url), 'utf8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== 'ENOENT') throw err;\n lastErr = err;\n }\n }\n throw lastErr ?? new Error(`bridge asset not found: ${name}`);\n}\n\n/**\n * Wait for the bridge's `bridge-hello` message to arrive on the freshly\n * opened WebSocket before any other host-side code touches it.\n *\n * Some sandbox runtimes (Vercel in particular) complete the WS upgrade\n * with the host long before the connection is actually forwarded to the\n * sandbox-side bridge. Anything sent in that gap is silently dropped —\n * including the `start` message we send next. The bridge emits\n * `bridge-hello` the instant it accepts the connection, so receiving it\n * is the only reliable evidence that the end-to-end link is live.\n */\nasync function waitForBridgeHello({\n ws,\n timeoutMs,\n}: {\n ws: WebSocket;\n timeoutMs: number;\n}): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n let settled = false;\n const cleanup = () => {\n ws.off('message', onMessage);\n ws.off('close', onClose);\n ws.off('error', onError);\n if (timer) clearTimeout(timer);\n };\n const settle = (err?: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n if (err) reject(err);\n else resolve();\n };\n const onMessage = (raw: unknown) => {\n try {\n const text =\n typeof raw === 'string'\n ? raw\n : (raw as Buffer | ArrayBufferLike).toString\n ? (raw as Buffer).toString('utf8')\n : String(raw);\n const parsed = JSON.parse(text) as { type?: unknown };\n if (parsed?.type === 'bridge-hello') settle();\n } catch {\n // Ignore malformed frames while waiting.\n }\n };\n const onClose = () => {\n settle(\n new Error('claude-code bridge closed before sending bridge-hello'),\n );\n };\n const onError = (err: Error) => settle(err);\n const timer = setTimeout(\n () =>\n settle(\n new Error(\n `claude-code bridge did not send bridge-hello within ${timeoutMs}ms`,\n ),\n ),\n timeoutMs,\n );\n timer.unref?.();\n ws.on('message', onMessage);\n ws.on('close', onClose);\n ws.on('error', onError);\n });\n}\n\nasync function openBridgeWebSocket({\n wsUrl,\n timeoutMs,\n}: {\n wsUrl: string;\n timeoutMs: number;\n}): Promise<WebSocket> {\n const deadline = Date.now() + timeoutMs;\n let attempt = 0;\n let lastError: unknown;\n\n while (Date.now() < deadline) {\n attempt++;\n let ws: WebSocket | undefined;\n try {\n const remaining = Math.max(1, deadline - Date.now());\n ws = await openWebSocket({\n url: wsUrl,\n timeoutMs: Math.min(10_000, remaining),\n });\n await waitForBridgeHello({\n ws,\n timeoutMs: Math.min(5_000, Math.max(1, deadline - Date.now())),\n });\n return ws;\n } catch (err) {\n lastError = err;\n try {\n ws?.close();\n } catch {}\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n await sleep(Math.min(250 * attempt, 1_000, remaining));\n }\n }\n\n throw new Error(\n `claude-code bridge did not complete WebSocket handshake within ${timeoutMs}ms after ${attempt} attempt(s). Last error: ${formatUnknownError(lastError)}`,\n );\n}\n\nfunction openWebSocket({\n url,\n timeoutMs,\n}: {\n url: string;\n timeoutMs: number;\n}): Promise<WebSocket> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(url);\n const timer = setTimeout(() => {\n cleanup();\n try {\n ws.terminate();\n } catch {}\n reject(new Error(`WebSocket open timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n timer.unref?.();\n const cleanup = () => {\n clearTimeout(timer);\n ws.off('open', onOpen);\n ws.off('error', onError);\n };\n const onOpen = () => {\n cleanup();\n resolve(ws);\n };\n const onError = (err: Error) => {\n cleanup();\n reject(err);\n };\n ws.once('open', onOpen);\n ws.once('error', onError);\n });\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => {\n const timer = setTimeout(resolve, ms);\n timer.unref?.();\n });\n}\n\nfunction formatUnknownError(error: unknown): string {\n if (error instanceof Error) return error.message;\n return String(error);\n}\n\nfunction createSession({\n sessionId,\n channel,\n proc,\n model,\n maxTurns,\n thinking,\n isResume,\n continueOnFirstPrompt,\n rerunContinue,\n bridgePort,\n bridgeToken,\n sandboxId,\n debug,\n permissionMode,\n builtinToolFiltering,\n skills,\n}: {\n sessionId: string;\n channel: ClaudeCodeChannel;\n /** Undefined on `attach` — the live bridge was spawned by another process. */\n proc: Experimental_SandboxProcess | undefined;\n model: string | undefined;\n maxTurns: number | undefined;\n thinking: ClaudeCodeThinkingConfig;\n isResume: boolean;\n continueOnFirstPrompt: boolean;\n rerunContinue: boolean;\n bridgePort: number;\n bridgeToken: string;\n sandboxId: string;\n debug: HarnessV1DebugConfig | undefined;\n permissionMode: HarnessV1PermissionMode | undefined;\n builtinToolFiltering: HarnessV1BuiltinToolFiltering | undefined;\n skills: ReadonlyArray<HarnessV1Skill>;\n}): HarnessV1Session {\n let stopped = false;\n let stopPromise: Promise<void> | undefined;\n /*\n * Force the Claude SDK's `continue: true` on the first prompt only when the\n * bridge was respawned (rerun/replay): a fresh bridge process treats its\n * first turn as new, so it must be told to rehydrate the workdir thread. An\n * `attach`ed bridge is already past its first turn and continues on its own.\n */\n let pendingResumeFlag = continueOnFirstPrompt;\n /*\n * Instructions are prepended to the first user message of a fresh session\n * only. A resumed session (attach/replay/rerun) already carried them in its\n * original first message (preserved in the workdir snapshot), so it starts\n * \"applied\".\n */\n let instructionsApplied = isResume;\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 }): HarnessV1PromptControl => {\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 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 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 'finish-step',\n 'raw',\n ] as const;\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(\n new Error('claude-code bridge closed before the turn finished.'),\n );\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 return {\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 submitUserMessage: async text => {\n channel.send({ type: 'user-message', text });\n },\n done,\n };\n };\n\n return {\n sessionId,\n isResume,\n modelId: model,\n doPromptTurn: async promptOpts => {\n const control = wireTurn({\n emit: promptOpts.emit,\n abortSignal: promptOpts.abortSignal,\n });\n\n let promptText = extractUserText(promptOpts.prompt);\n if (!instructionsApplied && promptOpts.instructions) {\n promptText = frameInstructions(promptOpts.instructions, promptText);\n }\n instructionsApplied = true;\n\n const startMessage = {\n type: 'start' as const,\n prompt: promptText,\n tools: (promptOpts.tools ?? []).map(t => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n model,\n maxTurns,\n thinking,\n ...(skills.length > 0\n ? { skills: skills.map(skill => skill.name) }\n : {}),\n ...(permissionMode ? { permissionMode } : {}),\n ...(builtinToolFiltering ? { builtinToolFiltering } : {}),\n ...(debug ? { debug } : {}),\n ...(pendingResumeFlag ? { continue: true } : {}),\n };\n pendingResumeFlag = false;\n channel.send(startMessage);\n\n return control;\n },\n doContinueTurn: async continueOpts => {\n const control = 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 the runtime's own thread from the workdir snapshot via\n * `continue: true`. Lossy — work in flight at the suspension is\n * recomputed. This is the rare bridge-died fallback; the common slice path\n * is `attach`.\n */\n if (rerunContinue) {\n pendingResumeFlag = false;\n channel.send({\n type: 'start' as const,\n /*\n * A continuation nudge rather than an empty prompt: `continue: true`\n * rehydrates the prior thread, and this is the new user turn that\n * drives it forward. It must be non-empty — an empty text block is\n * rejected by the Anthropic API once the SDK stamps it with\n * `cache_control`.\n */\n prompt: 'Continue.',\n tools: (continueOpts.tools ?? []).map(t => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n model,\n maxTurns,\n thinking,\n ...(skills.length > 0\n ? { skills: skills.map(skill => skill.name) }\n : {}),\n ...(permissionMode ? { permissionMode } : {}),\n ...(builtinToolFiltering ? { builtinToolFiltering } : {}),\n ...(debug ? { debug } : {}),\n continue: true,\n });\n }\n\n return control;\n },\n doCompact: async (customInstructions?: string) => {\n /*\n * Claude Code has no SDK/control method for compaction — the supported\n * trigger is the `/compact` slash command submitted as user input. Ride\n * the existing user-message rail; the bridge feeds it into the streaming\n * query input and Claude's native compaction handles the rest, emitting a\n * `compact_boundary` + `PostCompact` we observe as a `compaction` event.\n */\n const text =\n customInstructions && customInstructions.trim()\n ? `/compact ${customInstructions.trim()}`\n : '/compact';\n channel.send({ type: 'user-message', text });\n },\n doDetach: async () => {\n if (stopped) {\n throw new Error(\n `claude-code 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: 'claude-code',\n specificationVersion: 'harness-v1',\n data: {\n bridge: {\n port: bridgePort,\n token: bridgeToken,\n lastSeenEventId,\n 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: 'shutdown' });\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 `claude-code 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 ack a `detach` message. Synthesize an empty\n * payload — for Claude Code the resume state structurally is `{}`\n * (the conversation lives in the workdir, captured by the sandbox\n * snapshot during the subsequent `sandboxSession.stop()`), so we\n * lose nothing by skipping the round-trip.\n */\n // Tell the channel we are tearing down so the bridge's post-detach\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 `claude-code session ${sessionId} did not reply to detach within 5s.`,\n ),\n );\n }, 5000);\n timer.unref?.();\n const unsub = channel.on('bridge-detach', msg => {\n clearTimeout(timer);\n unsub();\n resolve(msg.data);\n });\n try {\n channel.send({ type: 'detach' });\n } catch (err) {\n clearTimeout(timer);\n unsub();\n reject(err);\n }\n });\n\n // The bridge exits itself ~50ms after sending bridge-detach. Give\n // it a moment, then ensure the process is reaped and the channel\n // closed.\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 payload: HarnessV1ResumeSessionState = {\n type: 'resume-session',\n harnessId: 'claude-code',\n specificationVersion: 'harness-v1',\n data: (data ?? {}) as HarnessV1ResumeSessionState['data'],\n };\n return payload;\n },\n doSuspendTurn: async () => {\n if (stopped) {\n throw new Error(\n `claude-code 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: 'claude-code',\n specificationVersion: 'harness-v1',\n data: {\n bridge: {\n port: bridgePort,\n token: bridgeToken,\n lastSeenEventId,\n sandboxId,\n },\n },\n };\n return payload;\n },\n };\n}\n\n/*\n * Frame session instructions and the user's text so the runtime treats the\n * instructions as system-provided operating guidance, not something the user\n * wrote. Without the wrapper the agent can echo the prepended text back as if\n * the user had asked for it, which is confusing since the user never typed it.\n * Applied only to the first user message of a fresh session.\n */\nfunction frameInstructions(instructions: string, userText: string): string {\n return (\n '<session-instructions>\\n' +\n 'The block below is operating guidance from the system, not a message from the user — follow it, but do not mention it or attribute it to the user.\\n\\n' +\n `${instructions}\\n` +\n '</session-instructions>\\n\\n' +\n `<user-message>\\n${userText}\\n</user-message>`\n );\n}\n\n/*\n * Reduce a `HarnessV1Prompt` to the plain user text the bridge forwards\n * to the Claude 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: 'claude-code',\n message: `The claude-code 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 { execFileSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { getAiGatewayAuthFromEnv } from '@ai-sdk/harness/utils';\n\nexport type ClaudeCodeAuthOptions = {\n readonly anthropic?: {\n readonly apiKey?: string;\n readonly authToken?: string;\n readonly baseUrl?: string;\n };\n readonly gateway?: {\n readonly apiKey?: string;\n readonly baseUrl?: string;\n };\n};\n\n/**\n * Resolve the environment-variable blob the bridge needs to authenticate\n * with Anthropic (directly or via the Vercel AI Gateway). Precedence:\n *\n * 1. Explicit `auth.anthropic` — pin to direct Anthropic auth.\n * 2. Explicit `auth.gateway` — pin to gateway-routed auth.\n * 3. Auto-detect from the host process env: gateway first\n * (`AI_GATEWAY_API_KEY` / `VERCEL_OIDC_TOKEN`), then direct\n * (`ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN`).\n */\nexport type ResolveClaudeCodeEnvOptions = {\n /**\n * Returns an API key from a custom source (e.g. a password manager).\n * Used as the last-resort fallback in the auto-detect branch when no\n * static env vars or explicit auth are configured. Defaults to running\n * the `apiKeyHelper` command from `~/.claude/settings.json`, matching\n * the `claude` CLI's own behaviour.\n */\n readApiKeyHelper?: () => string | undefined;\n};\n\nexport function resolveClaudeCodeEnv(\n auth: ClaudeCodeAuthOptions | undefined,\n processEnv: Record<string, string | undefined> = process.env,\n options: ResolveClaudeCodeEnvOptions = {},\n): Record<string, string> {\n const readApiKey = options.readApiKeyHelper ?? readApiKeyHelper;\n if (auth?.anthropic) {\n return pickAnthropic({ explicit: auth.anthropic, processEnv, readApiKey });\n }\n\n const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({ env: processEnv });\n if (auth?.gateway) {\n return pickGateway({\n explicit: auth.gateway,\n gatewayAuthFromEnv,\n });\n }\n if (gatewayAuthFromEnv.apiKey) {\n return pickGateway({\n explicit: {},\n gatewayAuthFromEnv,\n });\n }\n\n return pickAnthropic({ processEnv, readApiKey });\n}\n\nfunction pickAnthropic({\n explicit,\n processEnv,\n readApiKey,\n}: {\n explicit?: NonNullable<ClaudeCodeAuthOptions['anthropic']>;\n processEnv: Record<string, string | undefined>;\n readApiKey: () => string | undefined;\n}): Record<string, string> {\n const env: Record<string, string> = {};\n const helperKey = explicit ? undefined : readApiKey();\n const apiKey = explicit?.apiKey ?? processEnv.ANTHROPIC_API_KEY ?? helperKey;\n const authToken =\n explicit?.authToken ?? processEnv.ANTHROPIC_AUTH_TOKEN ?? helperKey;\n if (apiKey) env.ANTHROPIC_API_KEY = apiKey;\n if (authToken) env.ANTHROPIC_AUTH_TOKEN = authToken;\n const baseUrl = explicit?.baseUrl ?? processEnv.ANTHROPIC_BASE_URL;\n if (baseUrl) env.ANTHROPIC_BASE_URL = baseUrl;\n return env;\n}\n\n/**\n * Read the `apiKeyHelper` setting from `~/.claude/settings.json` and run\n * it. The `claude` CLI uses this hook to fetch credentials from password\n * managers and similar tools; mirroring it here lets users with that\n * setup run the harness without having to set `ANTHROPIC_API_KEY`\n * explicitly.\n */\nfunction readApiKeyHelper(): string | undefined {\n const home = homedir();\n if (!home) return undefined;\n let raw: string;\n try {\n raw = readFileSync(join(home, '.claude', 'settings.json'), 'utf8');\n } catch {\n return undefined;\n }\n let settings: { apiKeyHelper?: unknown };\n try {\n settings = JSON.parse(raw);\n } catch {\n return undefined;\n }\n const command = settings.apiKeyHelper;\n if (typeof command !== 'string' || command.length === 0) return undefined;\n try {\n const output = execFileSync('sh', ['-c', command], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n const trimmed = output.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction pickGateway({\n explicit,\n gatewayAuthFromEnv,\n}: {\n explicit: NonNullable<ClaudeCodeAuthOptions['gateway']>;\n gatewayAuthFromEnv: ReturnType<typeof getAiGatewayAuthFromEnv>;\n}): Record<string, string> {\n const apiKey = explicit.apiKey ?? gatewayAuthFromEnv.apiKey;\n const baseUrl = explicit.baseUrl ?? gatewayAuthFromEnv.baseUrl;\n const env: Record<string, string> = {};\n if (apiKey) {\n env.AI_GATEWAY_API_KEY = apiKey;\n env.ANTHROPIC_API_KEY = apiKey;\n }\n env.AI_GATEWAY_BASE_URL = baseUrl;\n env.ANTHROPIC_BASE_URL = baseUrl;\n return env;\n}\n","import {\n harnessV1BridgeInboundCommandSchemas,\n harnessV1BridgeOutboundMessageSchema,\n harnessV1BridgeReadySchema,\n harnessV1BridgeStartBaseSchema,\n} from '@ai-sdk/harness';\nimport { z } from 'zod/v4';\n\n/*\n * Claude Code's bridge wire protocol. The outbound events, transport frames,\n * shared inbound commands, and `bridge-ready` line all come from the shared\n * `@ai-sdk/harness` protocol — the only Claude-specific piece is the `start`\n * payload, which carries Claude SDK configuration.\n */\n\nexport const outboundMessageSchema = harnessV1BridgeOutboundMessageSchema;\nexport type OutboundMessage = z.infer<typeof outboundMessageSchema>;\n\nconst thinkingDisplaySchema = z.enum(['summarized', 'omitted']).optional();\n\nconst thinkingSchema = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('adaptive'),\n display: thinkingDisplaySchema,\n }),\n z.object({\n type: z.literal('enabled'),\n display: thinkingDisplaySchema,\n }),\n z.object({ type: z.literal('disabled') }),\n]);\n\nexport const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({\n thinking: thinkingSchema,\n maxTurns: z.number().optional(),\n skills: z.array(z.string()).optional(),\n // Resume signal. When true, the bridge passes `{ continue: true }` to the\n // Claude SDK so the in-workdir thread state is rehydrated. The host sets this\n // on the first prompt after a cross-process resume.\n continue: 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","// 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 { createClaudeCode } from './claude-code-harness';\n\n/**\n * Default `claude-code` harness instance with no overrides — suitable for the\n * common case where the underlying `claude` CLI's defaults are fine.\n * Equivalent to `createClaudeCode()`.\n */\nexport const claudeCode = createClaudeCode();\n\nexport { createClaudeCode } from './claude-code-harness';\nexport { VERSION } from './version';\nexport type { ClaudeCodeHarnessSettings } from './claude-code-harness';\nexport type { ClaudeCodeAuthOptions } from './claude-code-auth';\nexport type { ClaudeCodeThinkingConfig } from './claude-code-thinking';\n"],"mappings":"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","names":["z","z","wsUrl","proc"]}
1
+ {"version":3,"sources":["../src/claude-code-harness.ts","../src/claude-code-auth.ts","../src/claude-code-bridge-protocol.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { readFile } from 'node:fs/promises';\nimport { posix } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport {\n commonTool,\n harnessV1DiagnosticFromBridgeFrame,\n HarnessCapabilityUnsupportedError,\n type HarnessV1,\n type HarnessV1Bootstrap,\n type HarnessV1BuiltinToolFiltering,\n type HarnessV1BuiltinTool,\n type HarnessV1ContinueTurnState,\n type HarnessV1DebugConfig,\n type HarnessV1PermissionMode,\n type HarnessV1Prompt,\n type HarnessV1PromptControl,\n type HarnessV1ResumeSessionState,\n type HarnessV1NetworkSandboxSession,\n type HarnessV1Session,\n type HarnessV1Skill,\n type HarnessV1StreamPart,\n} from '@ai-sdk/harness';\nimport {\n classifyDiskLog,\n createBridgeErrorHandler,\n createBridgeStartupError,\n drainBridgeProcessStream,\n forwardBridgeProcessStream,\n markBridgeStarting,\n resolveSandboxHomeDir,\n SandboxChannel,\n shellQuote,\n waitForBridgeReady,\n writeSkills as writeHarnessSkills,\n} from '@ai-sdk/harness/utils';\nimport {\n tool,\n type Experimental_SandboxSession,\n type Experimental_SandboxProcess,\n} from '@ai-sdk/provider-utils';\nimport { WebSocket } from 'ws';\nimport { z } from 'zod/v4';\nimport {\n resolveClaudeCodeEnv,\n type ClaudeCodeAuthOptions,\n} from './claude-code-auth';\nimport {\n outboundMessageSchema,\n type InboundMessage,\n type OutboundMessage,\n} from './claude-code-bridge-protocol';\nimport type { ClaudeCodeThinkingConfig } from './claude-code-thinking';\nimport { VERSION } from './version';\n\ntype ClaudeCodeChannel = SandboxChannel<OutboundMessage, InboundMessage>;\ntype ClaudeCodeRespawnStrategy = 'replay' | 'rerun';\n\n/**\n * Value to use in User-Agent and `x-client-app` headers.\n */\nconst CLAUDE_CODE_CLIENT_APP = `ai-sdk/harness-claude-code/${VERSION}`;\n\nexport type ClaudeCodeHarnessSettings = {\n readonly auth?: ClaudeCodeAuthOptions;\n /**\n * Anthropic model id the underlying `claude` CLI should use. Leaving this\n * unset defers to the CLI's default.\n */\n readonly model?: string;\n /**\n * Hard cap on how many internal turns the CLI can take before yielding\n * back to the caller. Unset means the CLI's default.\n */\n readonly maxTurns?: number;\n /**\n * Controls extended-thinking behavior and whether reasoning is summarized or\n * omitted. Defaults to `{ type: 'adaptive', display: 'summarized' }`.\n */\n readonly thinking?: ClaudeCodeThinkingConfig;\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 /** Maximum milliseconds to wait for the bridge to advertise its port. Defaults to 120000. */\n readonly startupTimeoutMs?: number;\n};\n\n/*\n * Every native tool the Claude Code CLI can invoke, declared as a `ToolSet`\n * keyed by what the bridge emits as `toolName` on the wire\n * (`commonName ?? nativeName`). Schemas transcribed from\n * `@anthropic-ai/claude-agent-sdk`'s `agentSdkTypes.d.ts`.\n *\n * `MCP` (the generic proxy tool inside the Claude Code SDK) is intentionally\n * omitted — the bridge filters out `mcp__harness-tools__*` tool names before\n * emitting them, and other MCP invocations come through with their own\n * server-tool names rather than the literal `'Mcp'` token.\n */\nconst CLAUDE_CODE_BUILTIN_TOOLS = {\n read: commonTool('read', {\n nativeName: 'Read',\n toolUseKind: 'readonly',\n description: 'Read file contents (text, image, PDF, notebook)',\n inputSchema: z.object({\n file_path: z.string(),\n offset: z.number().optional(),\n limit: z.number().optional(),\n pages: z.string().optional(),\n }),\n }),\n write: commonTool('write', {\n nativeName: 'Write',\n toolUseKind: 'edit',\n description: 'Overwrite or create a file at an absolute path',\n inputSchema: z.object({\n file_path: z.string(),\n content: z.string(),\n }),\n }),\n edit: commonTool('edit', {\n nativeName: 'Edit',\n toolUseKind: 'edit',\n description: 'Edit a file by exact string replacement',\n inputSchema: z.object({\n file_path: z.string(),\n old_string: z.string(),\n new_string: z.string(),\n replace_all: z.boolean().optional(),\n }),\n }),\n bash: commonTool('bash', {\n nativeName: 'Bash',\n toolUseKind: 'bash',\n description: 'Execute a shell command, optionally in background',\n inputSchema: z.object({\n command: z.string(),\n timeout: z.number().optional(),\n description: z.string().optional(),\n run_in_background: z.boolean().optional(),\n dangerouslyDisableSandbox: z.boolean().optional(),\n }),\n }),\n glob: commonTool('glob', {\n nativeName: 'Glob',\n toolUseKind: 'readonly',\n description: 'Fast file-pattern search using glob syntax',\n inputSchema: z.object({\n pattern: z.string(),\n path: z.string().optional(),\n }),\n }),\n grep: commonTool('grep', {\n nativeName: 'Grep',\n toolUseKind: 'readonly',\n description: 'Regex search over file contents via ripgrep',\n inputSchema: z.object({\n pattern: z.string(),\n path: z.string().optional(),\n glob: z.string().optional(),\n output_mode: z\n .enum(['content', 'files_with_matches', 'count'])\n .optional(),\n '-B': z.number().optional(),\n '-A': z.number().optional(),\n '-C': z.number().optional(),\n context: z.number().optional(),\n '-n': z.boolean().optional(),\n '-i': z.boolean().optional(),\n '-o': z.boolean().optional(),\n type: z.string().optional(),\n head_limit: z.number().optional(),\n offset: z.number().optional(),\n multiline: z.boolean().optional(),\n }),\n }),\n webSearch: commonTool('webSearch', {\n nativeName: 'WebSearch',\n toolUseKind: 'readonly',\n description: 'Issue web search queries with optional domain filters',\n inputSchema: z.object({\n query: z.string(),\n allowed_domains: z.array(z.string()).optional(),\n blocked_domains: z.array(z.string()).optional(),\n }),\n }),\n\n WebFetch: tool({\n description: 'Fetch a URL and run a prompt against its content',\n inputSchema: z.object({\n url: z.string(),\n prompt: z.string(),\n }),\n }),\n NotebookEdit: tool({\n description: 'Edit, insert, or delete a Jupyter notebook cell',\n inputSchema: z.object({\n notebook_path: z.string(),\n new_source: z.string(),\n cell_id: z.string().optional(),\n cell_type: z.enum(['code', 'markdown']).optional(),\n edit_mode: z.enum(['replace', 'insert', 'delete']).optional(),\n }),\n }),\n TodoWrite: tool({\n description: 'Replace the session todo list',\n inputSchema: z.object({\n todos: z.array(\n z.object({\n content: z.string(),\n status: z.enum(['pending', 'in_progress', 'completed']),\n activeForm: z.string(),\n }),\n ),\n }),\n }),\n Agent: tool({\n description: 'Spawn a subagent with a task',\n inputSchema: z.object({\n description: z.string(),\n prompt: z.string(),\n subagent_type: z.string().optional(),\n model: z.enum(['sonnet', 'opus', 'haiku']).optional(),\n run_in_background: z.boolean().optional(),\n name: z.string().optional(),\n team_name: z.string().optional(),\n mode: z\n .enum([\n 'acceptEdits',\n 'auto',\n 'bypassPermissions',\n 'default',\n 'dontAsk',\n 'plan',\n ])\n .optional(),\n isolation: z.literal('worktree').optional(),\n }),\n }),\n TaskCreate: tool({\n description: 'Create a task in the session-local task list',\n inputSchema: z.object({\n subject: z.string(),\n description: z.string(),\n activeForm: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n }),\n }),\n TaskGet: tool({\n description: 'Retrieve a task by id',\n inputSchema: z.object({ taskId: z.string() }),\n }),\n TaskUpdate: tool({\n description: 'Update fields of an existing task',\n inputSchema: z.object({\n taskId: z.string(),\n subject: z.string().optional(),\n description: z.string().optional(),\n activeForm: z.string().optional(),\n status: z\n .union([\n z.enum(['pending', 'in_progress', 'completed']),\n z.literal('deleted'),\n ])\n .optional(),\n addBlocks: z.array(z.string()).optional(),\n addBlockedBy: z.array(z.string()).optional(),\n owner: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n }),\n }),\n TaskList: tool({\n description: 'Return all tasks in the session-local task list',\n inputSchema: z.object({}),\n }),\n TaskStop: tool({\n description: 'Stop a running background task by id',\n inputSchema: z.object({\n task_id: z.string().optional(),\n shell_id: z.string().optional(),\n }),\n }),\n TaskOutput: tool({\n description: 'Poll for output from a background task',\n inputSchema: z.object({\n task_id: z.string(),\n block: z.boolean(),\n timeout: z.number(),\n }),\n }),\n Monitor: tool({\n description: 'Run and monitor a shell command',\n inputSchema: z.object({\n command: z.string(),\n description: z.string().optional(),\n timeout_ms: z.number().optional(),\n persistent: z.boolean().optional(),\n }),\n }),\n ListMcpResources: tool({\n description: 'List resources available from MCP servers',\n inputSchema: z.object({ server: z.string().optional() }),\n }),\n ReadMcpResource: tool({\n description: 'Read a specific MCP resource by URI',\n inputSchema: z.object({ server: z.string(), uri: z.string() }),\n }),\n ExitPlanMode: tool({\n description: 'Exit plan mode with optional permission approvals',\n inputSchema: z.looseObject({\n allowedPrompts: z\n .array(\n z.object({\n tool: z.literal('Bash'),\n prompt: z.string(),\n }),\n )\n .optional(),\n }),\n }),\n EnterWorktree: tool({\n description: 'Create or enter an isolated git worktree',\n inputSchema: z.object({\n name: z.string().optional(),\n path: z.string().optional(),\n }),\n }),\n ExitWorktree: tool({\n description: 'Exit the current worktree session',\n inputSchema: z.object({\n action: z.enum(['keep', 'remove']),\n discard_changes: z.boolean().optional(),\n }),\n }),\n AskUserQuestion: tool({\n description: 'Ask the user multiple-choice questions via a structured UI',\n inputSchema: z.object({\n questions: z\n .array(\n z.object({\n question: z.string(),\n header: z.string(),\n options: z.array(\n z.object({\n label: z.string(),\n description: z.string(),\n preview: z.string().optional(),\n }),\n ),\n multiSelect: z.boolean(),\n }),\n )\n .min(1)\n .max(4),\n answers: z.record(z.string(), z.string()).optional(),\n annotations: z\n .record(\n z.string(),\n z.object({\n preview: z.string().optional(),\n notes: z.string().optional(),\n }),\n )\n .optional(),\n metadata: z.object({ source: z.string().optional() }).optional(),\n }),\n }),\n Skill: {\n ...tool({\n description: 'Activate a skill by name',\n inputSchema: z.object({\n skill: z.string(),\n args: z.string().optional(),\n }),\n }),\n toolUseKind: 'readonly',\n },\n ToolSearch: tool({\n description:\n 'Search deferred MCP / catalog tools so the model can load them on demand',\n inputSchema: z.object({\n query: z.string(),\n max_results: z.number().optional(),\n }),\n }),\n} as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;\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`) and the bridge-state dir\n * derived from `sandboxSession.defaultWorkingDirectory` both live under the sandbox's\n * default working directory — the provider's persistent mount — so the\n * workdir's CLI state (Claude's `~/.claude/projects/<dir>/*.jsonl` thread\n * history is keyed by working directory) and the bridge state files survive\n * both detach -> attach/replay and stop -> snapshot -> resume cycles.\n */\nconst BOOTSTRAP_DIR = '.harness-bootstrap/claude-code';\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 claudeCodeBridgeCoordsSchema = 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 portion of lifecycle state `data`.\n *\n * A `doStop()` payload is structurally empty (`{}`): the framework derives the\n * sandbox via `provider.resumeSession({ sessionId })`, and the Claude SDK's\n * `{ continue: true }` flag rehydrates the thread from the workdir. A\n * `doDetach()` payload additionally carries `bridge` coordinates for\n * cross-process `attach`. A loose object keeps both shapes valid.\n */\nconst claudeCodeResumeStateSchema = z.looseObject({\n bridge: claudeCodeBridgeCoordsSchema.optional(),\n});\n\ntype ClaudeCodeBridgeCoords = z.infer<typeof claudeCodeBridgeCoordsSchema>;\n\nexport function createClaudeCode(\n settings: ClaudeCodeHarnessSettings = {},\n): HarnessV1<typeof CLAUDE_CODE_BUILTIN_TOOLS> {\n let cachedBootstrap: HarnessV1Bootstrap | undefined;\n const thinking = settings.thinking ?? {\n type: 'adaptive',\n display: 'summarized',\n };\n\n return {\n specificationVersion: 'harness-v1',\n harnessId: 'claude-code',\n builtinTools: CLAUDE_CODE_BUILTIN_TOOLS,\n supportsBuiltinToolApprovals: true,\n supportsBuiltinToolFiltering: true,\n lifecycleStateSchema: claudeCodeResumeStateSchema,\n getBootstrap: async () => {\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: 'claude-code',\n bootstrapDir: BOOTSTRAP_DIR,\n files: [\n { path: `${BOOTSTRAP_DIR}/package.json`, content: pkg },\n { path: `${BOOTSTRAP_DIR}/pnpm-lock.yaml`, content: lock },\n { path: `${BOOTSTRAP_DIR}/bridge.mjs`, content: bridge },\n ],\n commands: [\n {\n command: 'pnpm install --frozen-lockfile --store-dir .pnpm-store',\n },\n {\n command:\n 'if [ -f node_modules/@anthropic-ai/claude-code/install.cjs ]; then node node_modules/@anthropic-ai/claude-code/install.cjs; fi && ./node_modules/.bin/claude --version',\n },\n ],\n };\n return cachedBootstrap;\n },\n doStart: async startOpts => {\n const sandboxSession = startOpts.sandboxSession;\n const session = sandboxSession.restricted();\n const sandboxId = sandboxSession.id;\n const bootstrapDir = posix.resolve(\n sandboxSession.defaultWorkingDirectory,\n BOOTSTRAP_DIR,\n );\n const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;\n const isResume = lifecycleState != null;\n const isContinue = startOpts.continueFrom != null;\n const coords = isResume\n ? (lifecycleState?.data as { bridge?: ClaudeCodeBridgeCoords })?.bridge\n : undefined;\n\n const workDir = startOpts.sessionWorkDir;\n const sessionDataDir = `${sandboxSession.defaultWorkingDirectory}/.agent-runs/${startOpts.sessionId}`;\n const bridgeStateDir = `${sessionDataDir}/bridge`;\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: 'claude-code',\n sessionId: startOpts.sessionId,\n });\n\n // Builds the `connect` thunk a `SandboxChannel` re-invokes on every\n // (re)connect: open the socket, then wait for `bridge-hello` so the\n // end-to-end link is proven live before any frame is sent.\n const buildConnect = (wsUrl: string) => async (): Promise<WebSocket> => {\n return openBridgeWebSocket({ wsUrl, timeoutMs });\n };\n\n /*\n * Rung 1 — ATTACH. When lifecycle state carries live bridge coordinates,\n * try to reopen a socket to the still-running bridge. Parked sessions wait\n * for the next `start`; suspended turns request replay of everything past\n * the persisted cursor. No spawn, no fresh token (the existing bridge\n * still authorises the persisted one). If the bridge is gone the open\n * throws and we fall through to a spawn-based recovery.\n */\n if (coords) {\n try {\n const attachUrl =\n (await sandboxSession.getPortUrl({\n port: coords.port,\n protocol: 'ws',\n })) + `?agent_bridge_token=${encodeURIComponent(coords.token)}`;\n const attachChannel: ClaudeCodeChannel = new SandboxChannel({\n connect: buildConnect(attachUrl),\n outboundSchema: outboundMessageSchema,\n initialLastSeenEventId: coords.lastSeenEventId,\n onDiagnostic,\n onBridgeError,\n });\n await attachChannel.open(isContinue ? { resume: true } : undefined);\n return createSession({\n sessionId: startOpts.sessionId,\n channel: attachChannel,\n // The live bridge was spawned by another process; this one owns no\n // process handle. The session lifecycle method decides whether the\n // sandbox is left running, stopped, or destroyed.\n proc: undefined,\n model: settings.model,\n maxTurns: settings.maxTurns,\n thinking,\n isResume: true,\n continueOnFirstPrompt: false,\n rerunContinue: false,\n bridgePort: coords.port,\n bridgeToken: coords.token,\n sandboxId,\n debug: startOpts.observability?.debug,\n permissionMode: startOpts.permissionMode,\n builtinToolFiltering: startOpts.builtinToolFiltering,\n skills: startOpts.skills ?? [],\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 * when attach is unavailable (the CLI continues its own thread from the\n * workdir snapshot via `continue: true`).\n */\n let respawnStrategy: ClaudeCodeRespawnStrategy | undefined = isResume\n ? 'rerun'\n : undefined;\n if (coords && isContinue) {\n const logRaw = await Promise.resolve(\n session.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 sandboxHomeDir =\n startOpts.skills && startOpts.skills.length > 0\n ? await resolveSandboxHomeDir({\n sandbox: session,\n abortSignal: startOpts.abortSignal,\n })\n : undefined;\n const port = resolveBridgePort(sandboxSession, settings.port);\n const token = randomBytes(32).toString('hex');\n const env = {\n ...resolveClaudeCodeEnv(settings.auth),\n /*\n * The Claude Agent SDK does not expose arbitrary model-request\n * headers. It reads this environment variable and sends the value as\n * `x-client-app`, while also appending `client-app/<value>` to\n * `User-Agent`, so this is the attribution path for AI Gateway.\n */\n CLAUDE_AGENT_SDK_CLIENT_APP: CLAUDE_CODE_CLIENT_APP,\n BRIDGE_CHANNEL_TOKEN: token,\n BRIDGE_WS_PORT: String(port),\n ...(sandboxHomeDir ? { HOME: sandboxHomeDir } : {}),\n ...(respawnStrategy === 'replay'\n ? { BRIDGE_REPLAY_FROM_DISK: '1' }\n : {}),\n };\n\n /*\n * On a fresh start the workdir, skill files, and bridge-state directory\n * must be created. On any resume they already exist in the\n * sandbox snapshot, so skip the rewrite. The env is sent fresh on every\n * spawn — `BRIDGE_CHANNEL_TOKEN` rotates per start.\n */\n if (respawnStrategy === undefined) {\n await session.run({\n command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,\n abortSignal: startOpts.abortSignal,\n });\n\n if (startOpts.skills && startOpts.skills.length > 0) {\n if (!sandboxHomeDir) {\n throw new Error('Unable to resolve sandbox HOME directory.');\n }\n await writeClaudeCodeSkills({\n sandbox: session,\n homeDir: sandboxHomeDir,\n skills: startOpts.skills,\n abortSignal: startOpts.abortSignal,\n });\n }\n }\n\n await markBridgeStarting({\n sandbox: session,\n bridgeStateDir,\n bridgeType: 'claude-code',\n abortSignal: startOpts.abortSignal,\n });\n\n const proc = await session.spawn({\n command: `node ${shellQuote(`${bootstrapDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)}`,\n env,\n abortSignal: startOpts.abortSignal,\n });\n\n const bridgeStartupStderr: string[] = [];\n const bridgeStartupStderrDone = forwardBridgeProcessStream({\n stream: proc.stderr,\n streamName: 'stderr',\n source: 'claude-code',\n collectTail: bridgeStartupStderr,\n });\n void bridgeStartupStderrDone;\n const { port: boundPort } = await waitForBridgeReady({\n proc,\n sandbox: session,\n bridgeStateDir,\n bridgeType: 'claude-code',\n timeoutMs,\n abortSignal: startOpts.abortSignal,\n createTimeoutError: ({ proc, stdoutTail }) =>\n createBridgeStartupError({\n message: 'claude-code bridge did not become ready in time.',\n proc,\n stdoutTail,\n stderrTail: bridgeStartupStderr,\n stderrDone: bridgeStartupStderrDone,\n }),\n createExitError: ({ proc, stdoutTail }) =>\n createBridgeStartupError({\n message: 'claude-code bridge exited before becoming ready.',\n proc,\n stdoutTail,\n stderrTail: bridgeStartupStderr,\n stderrDone: bridgeStartupStderrDone,\n }),\n });\n void drainBridgeProcessStream(proc.stdout);\n\n const wsUrl =\n (await sandboxSession.getPortUrl({\n port: boundPort,\n protocol: 'ws',\n })) + `?agent_bridge_token=${encodeURIComponent(token)}`;\n\n const channel: ClaudeCodeChannel = new SandboxChannel({\n connect: buildConnect(wsUrl),\n outboundSchema: outboundMessageSchema,\n onDiagnostic,\n onBridgeError,\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`) rather than starting empty.\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 proc,\n model: settings.model,\n maxTurns: settings.maxTurns,\n thinking,\n isResume: respawnStrategy !== undefined,\n continueOnFirstPrompt: respawnStrategy !== undefined,\n rerunContinue: respawnStrategy === 'rerun',\n bridgePort: boundPort,\n bridgeToken: token,\n sandboxId,\n debug: startOpts.observability?.debug,\n permissionMode: startOpts.permissionMode,\n builtinToolFiltering: startOpts.builtinToolFiltering,\n skills: startOpts.skills ?? [],\n });\n },\n };\n}\n\nfunction resolveBridgePort(\n sandboxSession: HarnessV1NetworkSandboxSession,\n override: number | undefined,\n): number {\n if (override !== undefined) return override;\n if (sandboxSession.ports.length > 0) return sandboxSession.ports[0];\n throw new HarnessCapabilityUnsupportedError({\n harnessId: 'claude-code',\n message:\n 'The claude-code harness needs a TCP port exposed by the sandbox. ' +\n 'Create the sandbox with `ports: [<port>]` or pass `createClaudeCode({ port })`.',\n });\n}\n\n/**\n * Materialise skill files into\n * `$HOME/.claude/skills/<name>/SKILL.md`. The `claude` CLI\n * auto-discovers skills from that directory on startup, so the files have to\n * be in place before the bridge is spawned without mutating the session\n * workdir. Each file uses the YAML-frontmatter shape the CLI expects.\n */\nasync function writeClaudeCodeSkills({\n sandbox,\n homeDir,\n skills,\n abortSignal,\n}: {\n sandbox: Experimental_SandboxSession;\n homeDir: string;\n skills: ReadonlyArray<HarnessV1Skill>;\n abortSignal?: AbortSignal;\n}): Promise<void> {\n await writeHarnessSkills({\n sandbox,\n rootDir: `${homeDir}/.claude/skills`,\n skills,\n abortSignal,\n invalidSkillNameMessage: ({ name }) =>\n `Invalid Claude Code skill name: ${name}`,\n invalidSkillFilePathMessage: ({ skillName, filePath }) =>\n `Invalid Claude Code skill file path for ${skillName}: ${filePath}`,\n trailingNewline: true,\n });\n}\n\nasync function readBridgeAsset(name: string): Promise<string> {\n const candidates = [\n new URL(`./bridge/${name}`, import.meta.url),\n new URL(`../bridge/${name}`, import.meta.url),\n ];\n let lastErr: unknown;\n for (const url of candidates) {\n try {\n return await readFile(fileURLToPath(url), 'utf8');\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== 'ENOENT') throw err;\n lastErr = err;\n }\n }\n throw lastErr ?? new Error(`bridge asset not found: ${name}`);\n}\n\n/**\n * Wait for the bridge's `bridge-hello` message to arrive on the freshly\n * opened WebSocket before any other host-side code touches it.\n *\n * Some sandbox runtimes (Vercel in particular) complete the WS upgrade\n * with the host long before the connection is actually forwarded to the\n * sandbox-side bridge. Anything sent in that gap is silently dropped —\n * including the `start` message we send next. The bridge emits\n * `bridge-hello` the instant it accepts the connection, so receiving it\n * is the only reliable evidence that the end-to-end link is live.\n */\nasync function waitForBridgeHello({\n ws,\n timeoutMs,\n}: {\n ws: WebSocket;\n timeoutMs: number;\n}): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n let settled = false;\n const cleanup = () => {\n ws.off('message', onMessage);\n ws.off('close', onClose);\n ws.off('error', onError);\n if (timer) clearTimeout(timer);\n };\n const settle = (err?: unknown) => {\n if (settled) return;\n settled = true;\n cleanup();\n if (err) reject(err);\n else resolve();\n };\n const onMessage = (raw: unknown) => {\n try {\n const text =\n typeof raw === 'string'\n ? raw\n : (raw as Buffer | ArrayBufferLike).toString\n ? (raw as Buffer).toString('utf8')\n : String(raw);\n const parsed = JSON.parse(text) as { type?: unknown };\n if (parsed?.type === 'bridge-hello') settle();\n } catch {\n // Ignore malformed frames while waiting.\n }\n };\n const onClose = () => {\n settle(\n new Error('claude-code bridge closed before sending bridge-hello'),\n );\n };\n const onError = (err: Error) => settle(err);\n const timer = setTimeout(\n () =>\n settle(\n new Error(\n `claude-code bridge did not send bridge-hello within ${timeoutMs}ms`,\n ),\n ),\n timeoutMs,\n );\n timer.unref?.();\n ws.on('message', onMessage);\n ws.on('close', onClose);\n ws.on('error', onError);\n });\n}\n\nasync function openBridgeWebSocket({\n wsUrl,\n timeoutMs,\n}: {\n wsUrl: string;\n timeoutMs: number;\n}): Promise<WebSocket> {\n const deadline = Date.now() + timeoutMs;\n let attempt = 0;\n let lastError: unknown;\n\n while (Date.now() < deadline) {\n attempt++;\n let ws: WebSocket | undefined;\n try {\n const remaining = Math.max(1, deadline - Date.now());\n ws = await openWebSocket({\n url: wsUrl,\n timeoutMs: Math.min(10_000, remaining),\n });\n await waitForBridgeHello({\n ws,\n timeoutMs: Math.min(5_000, Math.max(1, deadline - Date.now())),\n });\n return ws;\n } catch (err) {\n lastError = err;\n try {\n ws?.close();\n } catch {}\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n await sleep(Math.min(250 * attempt, 1_000, remaining));\n }\n }\n\n throw new Error(\n `claude-code bridge did not complete WebSocket handshake within ${timeoutMs}ms after ${attempt} attempt(s). Last error: ${formatUnknownError(lastError)}`,\n );\n}\n\nfunction openWebSocket({\n url,\n timeoutMs,\n}: {\n url: string;\n timeoutMs: number;\n}): Promise<WebSocket> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(url);\n const timer = setTimeout(() => {\n cleanup();\n try {\n ws.terminate();\n } catch {}\n reject(new Error(`WebSocket open timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n timer.unref?.();\n const cleanup = () => {\n clearTimeout(timer);\n ws.off('open', onOpen);\n ws.off('error', onError);\n };\n const onOpen = () => {\n cleanup();\n resolve(ws);\n };\n const onError = (err: Error) => {\n cleanup();\n reject(err);\n };\n ws.once('open', onOpen);\n ws.once('error', onError);\n });\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => {\n const timer = setTimeout(resolve, ms);\n timer.unref?.();\n });\n}\n\nfunction formatUnknownError(error: unknown): string {\n if (error instanceof Error) return error.message;\n return String(error);\n}\n\nfunction createSession({\n sessionId,\n channel,\n proc,\n model,\n maxTurns,\n thinking,\n isResume,\n continueOnFirstPrompt,\n rerunContinue,\n bridgePort,\n bridgeToken,\n sandboxId,\n debug,\n permissionMode,\n builtinToolFiltering,\n skills,\n}: {\n sessionId: string;\n channel: ClaudeCodeChannel;\n /** Undefined on `attach` — the live bridge was spawned by another process. */\n proc: Experimental_SandboxProcess | undefined;\n model: string | undefined;\n maxTurns: number | undefined;\n thinking: ClaudeCodeThinkingConfig;\n isResume: boolean;\n continueOnFirstPrompt: boolean;\n rerunContinue: boolean;\n bridgePort: number;\n bridgeToken: string;\n sandboxId: string;\n debug: HarnessV1DebugConfig | undefined;\n permissionMode: HarnessV1PermissionMode | undefined;\n builtinToolFiltering: HarnessV1BuiltinToolFiltering | undefined;\n skills: ReadonlyArray<HarnessV1Skill>;\n}): HarnessV1Session {\n let stopped = false;\n let stopPromise: Promise<void> | undefined;\n /*\n * Force the Claude SDK's `continue: true` on the first prompt only when the\n * bridge was respawned (rerun/replay): a fresh bridge process treats its\n * first turn as new, so it must be told to rehydrate the workdir thread. An\n * `attach`ed bridge is already past its first turn and continues on its own.\n */\n let pendingResumeFlag = continueOnFirstPrompt;\n /*\n * Instructions are prepended to the first user message of a fresh session\n * only. A resumed session (attach/replay/rerun) already carried them in its\n * original first message (preserved in the workdir snapshot), so it starts\n * \"applied\".\n */\n let instructionsApplied = isResume;\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 }): HarnessV1PromptControl => {\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 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 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 'finish-step',\n 'raw',\n ] as const;\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(\n new Error('claude-code bridge closed before the turn finished.'),\n );\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 return {\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 submitUserMessage: async text => {\n channel.send({ type: 'user-message', text });\n },\n done,\n };\n };\n\n return {\n sessionId,\n isResume,\n modelId: model,\n doPromptTurn: async promptOpts => {\n const control = wireTurn({\n emit: promptOpts.emit,\n abortSignal: promptOpts.abortSignal,\n });\n\n let promptText = extractUserText(promptOpts.prompt);\n if (!instructionsApplied && promptOpts.instructions) {\n promptText = frameInstructions(promptOpts.instructions, promptText);\n }\n instructionsApplied = true;\n\n const startMessage = {\n type: 'start' as const,\n prompt: promptText,\n tools: (promptOpts.tools ?? []).map(t => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n model,\n maxTurns,\n thinking,\n ...(skills.length > 0\n ? { skills: skills.map(skill => skill.name) }\n : {}),\n ...(permissionMode ? { permissionMode } : {}),\n ...(builtinToolFiltering ? { builtinToolFiltering } : {}),\n ...(debug ? { debug } : {}),\n ...(pendingResumeFlag ? { continue: true } : {}),\n };\n pendingResumeFlag = false;\n channel.send(startMessage);\n\n return control;\n },\n doContinueTurn: async continueOpts => {\n const control = 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 the runtime's own thread from the workdir snapshot via\n * `continue: true`. Lossy — work in flight at the suspension is\n * recomputed. This is the rare bridge-died fallback; the common slice path\n * is `attach`.\n */\n if (rerunContinue) {\n pendingResumeFlag = false;\n channel.send({\n type: 'start' as const,\n /*\n * A continuation nudge rather than an empty prompt: `continue: true`\n * rehydrates the prior thread, and this is the new user turn that\n * drives it forward. It must be non-empty — an empty text block is\n * rejected by the Anthropic API once the SDK stamps it with\n * `cache_control`.\n */\n prompt: 'Continue.',\n tools: (continueOpts.tools ?? []).map(t => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n })),\n model,\n maxTurns,\n thinking,\n ...(skills.length > 0\n ? { skills: skills.map(skill => skill.name) }\n : {}),\n ...(permissionMode ? { permissionMode } : {}),\n ...(builtinToolFiltering ? { builtinToolFiltering } : {}),\n ...(debug ? { debug } : {}),\n continue: true,\n });\n }\n\n return control;\n },\n doCompact: async (customInstructions?: string) => {\n /*\n * Claude Code has no SDK/control method for compaction — the supported\n * trigger is the `/compact` slash command submitted as user input. Ride\n * the existing user-message rail; the bridge feeds it into the streaming\n * query input and Claude's native compaction handles the rest, emitting a\n * `compact_boundary` + `PostCompact` we observe as a `compaction` event.\n */\n const text =\n customInstructions && customInstructions.trim()\n ? `/compact ${customInstructions.trim()}`\n : '/compact';\n channel.send({ type: 'user-message', text });\n },\n doDetach: async () => {\n if (stopped) {\n throw new Error(\n `claude-code 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: 'claude-code',\n specificationVersion: 'harness-v1',\n data: {\n bridge: {\n port: bridgePort,\n token: bridgeToken,\n lastSeenEventId,\n 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: 'shutdown' });\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 `claude-code 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 ack a `detach` message. Synthesize an empty\n * payload — for Claude Code the resume state structurally is `{}`\n * (the conversation lives in the workdir, captured by the sandbox\n * snapshot during the subsequent `sandboxSession.stop()`), so we\n * lose nothing by skipping the round-trip.\n */\n // Tell the channel we are tearing down so the bridge's post-detach\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 `claude-code session ${sessionId} did not reply to detach within 5s.`,\n ),\n );\n }, 5000);\n timer.unref?.();\n const unsub = channel.on('bridge-detach', msg => {\n clearTimeout(timer);\n unsub();\n resolve(msg.data);\n });\n try {\n channel.send({ type: 'detach' });\n } catch (err) {\n clearTimeout(timer);\n unsub();\n reject(err);\n }\n });\n\n // The bridge exits itself ~50ms after sending bridge-detach. Give\n // it a moment, then ensure the process is reaped and the channel\n // closed.\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 payload: HarnessV1ResumeSessionState = {\n type: 'resume-session',\n harnessId: 'claude-code',\n specificationVersion: 'harness-v1',\n data: (data ?? {}) as HarnessV1ResumeSessionState['data'],\n };\n return payload;\n },\n doSuspendTurn: async () => {\n if (stopped) {\n throw new Error(\n `claude-code 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: 'claude-code',\n specificationVersion: 'harness-v1',\n data: {\n bridge: {\n port: bridgePort,\n token: bridgeToken,\n lastSeenEventId,\n sandboxId,\n },\n },\n };\n return payload;\n },\n };\n}\n\n/*\n * Frame session instructions and the user's text so the runtime treats the\n * instructions as system-provided operating guidance, not something the user\n * wrote. Without the wrapper the agent can echo the prepended text back as if\n * the user had asked for it, which is confusing since the user never typed it.\n * Applied only to the first user message of a fresh session.\n */\nfunction frameInstructions(instructions: string, userText: string): string {\n return (\n '<session-instructions>\\n' +\n 'The block below is operating guidance from the system, not a message from the user — follow it, but do not mention it or attribute it to the user.\\n\\n' +\n `${instructions}\\n` +\n '</session-instructions>\\n\\n' +\n `<user-message>\\n${userText}\\n</user-message>`\n );\n}\n\n/*\n * Reduce a `HarnessV1Prompt` to the plain user text the bridge forwards\n * to the Claude 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: 'claude-code',\n message: `The claude-code 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 { execFileSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { getAiGatewayAuthFromEnv } from '@ai-sdk/harness/utils';\n\nexport type ClaudeCodeAuthOptions = {\n readonly anthropic?: {\n readonly apiKey?: string;\n readonly authToken?: string;\n readonly baseUrl?: string;\n };\n readonly gateway?: {\n readonly apiKey?: string;\n readonly baseUrl?: string;\n };\n};\n\n/**\n * Resolve the environment-variable blob the bridge needs to authenticate\n * with Anthropic (directly or via the Vercel AI Gateway). Precedence:\n *\n * 1. Explicit `auth.anthropic` — pin to direct Anthropic auth.\n * 2. Explicit `auth.gateway` — pin to gateway-routed auth.\n * 3. Auto-detect from the host process env: gateway first\n * (`AI_GATEWAY_API_KEY` / `VERCEL_OIDC_TOKEN`), then direct\n * (`ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN`).\n */\nexport type ResolveClaudeCodeEnvOptions = {\n /**\n * Returns an API key from a custom source (e.g. a password manager).\n * Used as the last-resort fallback in the auto-detect branch when no\n * static env vars or explicit auth are configured. Defaults to running\n * the `apiKeyHelper` command from `~/.claude/settings.json`, matching\n * the `claude` CLI's own behaviour.\n */\n readApiKeyHelper?: () => string | undefined;\n};\n\nexport function resolveClaudeCodeEnv(\n auth: ClaudeCodeAuthOptions | undefined,\n processEnv: Record<string, string | undefined> = process.env,\n options: ResolveClaudeCodeEnvOptions = {},\n): Record<string, string> {\n const readApiKey = options.readApiKeyHelper ?? readApiKeyHelper;\n if (auth?.anthropic) {\n return pickAnthropic({ explicit: auth.anthropic, processEnv, readApiKey });\n }\n\n const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({ env: processEnv });\n if (auth?.gateway) {\n return pickGateway({\n explicit: auth.gateway,\n gatewayAuthFromEnv,\n });\n }\n if (gatewayAuthFromEnv.apiKey) {\n return pickGateway({\n explicit: {},\n gatewayAuthFromEnv,\n });\n }\n\n return pickAnthropic({ processEnv, readApiKey });\n}\n\nfunction pickAnthropic({\n explicit,\n processEnv,\n readApiKey,\n}: {\n explicit?: NonNullable<ClaudeCodeAuthOptions['anthropic']>;\n processEnv: Record<string, string | undefined>;\n readApiKey: () => string | undefined;\n}): Record<string, string> {\n const env: Record<string, string> = {};\n const helperKey = explicit ? undefined : readApiKey();\n const apiKey = explicit?.apiKey ?? processEnv.ANTHROPIC_API_KEY ?? helperKey;\n const authToken =\n explicit?.authToken ?? processEnv.ANTHROPIC_AUTH_TOKEN ?? helperKey;\n if (apiKey) env.ANTHROPIC_API_KEY = apiKey;\n if (authToken) env.ANTHROPIC_AUTH_TOKEN = authToken;\n const baseUrl = explicit?.baseUrl ?? processEnv.ANTHROPIC_BASE_URL;\n if (baseUrl) env.ANTHROPIC_BASE_URL = baseUrl;\n return env;\n}\n\n/**\n * Read the `apiKeyHelper` setting from `~/.claude/settings.json` and run\n * it. The `claude` CLI uses this hook to fetch credentials from password\n * managers and similar tools; mirroring it here lets users with that\n * setup run the harness without having to set `ANTHROPIC_API_KEY`\n * explicitly.\n */\nfunction readApiKeyHelper(): string | undefined {\n const home = homedir();\n if (!home) return undefined;\n let raw: string;\n try {\n raw = readFileSync(join(home, '.claude', 'settings.json'), 'utf8');\n } catch {\n return undefined;\n }\n let settings: { apiKeyHelper?: unknown };\n try {\n settings = JSON.parse(raw);\n } catch {\n return undefined;\n }\n const command = settings.apiKeyHelper;\n if (typeof command !== 'string' || command.length === 0) return undefined;\n try {\n const output = execFileSync('sh', ['-c', command], {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n const trimmed = output.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction pickGateway({\n explicit,\n gatewayAuthFromEnv,\n}: {\n explicit: NonNullable<ClaudeCodeAuthOptions['gateway']>;\n gatewayAuthFromEnv: ReturnType<typeof getAiGatewayAuthFromEnv>;\n}): Record<string, string> {\n const apiKey = explicit.apiKey ?? gatewayAuthFromEnv.apiKey;\n const baseUrl = explicit.baseUrl ?? gatewayAuthFromEnv.baseUrl;\n const env: Record<string, string> = {};\n if (apiKey) {\n env.AI_GATEWAY_API_KEY = apiKey;\n env.ANTHROPIC_API_KEY = apiKey;\n }\n env.AI_GATEWAY_BASE_URL = baseUrl;\n env.ANTHROPIC_BASE_URL = baseUrl;\n return env;\n}\n","import {\n harnessV1BridgeInboundCommandSchemas,\n harnessV1BridgeOutboundMessageSchema,\n harnessV1BridgeReadySchema,\n harnessV1BridgeStartBaseSchema,\n} from '@ai-sdk/harness';\nimport { z } from 'zod/v4';\n\n/*\n * Claude Code's bridge wire protocol. The outbound events, transport frames,\n * shared inbound commands, and `bridge-ready` line all come from the shared\n * `@ai-sdk/harness` protocol — the only Claude-specific piece is the `start`\n * payload, which carries Claude SDK configuration.\n */\n\nexport const outboundMessageSchema = harnessV1BridgeOutboundMessageSchema;\nexport type OutboundMessage = z.infer<typeof outboundMessageSchema>;\n\nconst thinkingDisplaySchema = z.enum(['summarized', 'omitted']).optional();\n\nconst thinkingSchema = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('adaptive'),\n display: thinkingDisplaySchema,\n }),\n z.object({\n type: z.literal('enabled'),\n display: thinkingDisplaySchema,\n }),\n z.object({ type: z.literal('disabled') }),\n]);\n\nexport const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({\n thinking: thinkingSchema,\n maxTurns: z.number().optional(),\n skills: z.array(z.string()).optional(),\n // Resume signal. When true, the bridge passes `{ continue: true }` to the\n // Claude SDK so the in-workdir thread state is rehydrated. The host sets this\n // on the first prompt after a cross-process resume.\n continue: 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","// 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 { createClaudeCode } from './claude-code-harness';\n\n/**\n * Default `claude-code` harness instance with no overrides — suitable for the\n * common case where the underlying `claude` CLI's defaults are fine.\n * Equivalent to `createClaudeCode()`.\n */\nexport const claudeCode = createClaudeCode();\n\nexport { createClaudeCode } from './claude-code-harness';\nexport { VERSION } from './version';\nexport type { ClaudeCodeHarnessSettings } from './claude-code-harness';\nexport type { ClaudeCodeAuthOptions } from './claude-code-auth';\nexport type { ClaudeCodeThinkingConfig } from './claude-code-thinking';\n"],"mappings":"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","names":["z","z","wsUrl","proc"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/harness-claude-code",
3
- "version": "1.0.53",
3
+ "version": "1.0.54",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -27,8 +27,8 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "ws": "^8.21.0",
30
- "@ai-sdk/harness": "1.0.52",
31
- "@ai-sdk/provider-utils": "5.0.17"
30
+ "@ai-sdk/harness": "1.0.53",
31
+ "@ai-sdk/provider-utils": "5.0.18"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "zod": "^3.25.76 || ^4.1.8"
@@ -1,5 +1,6 @@
1
1
  import { randomBytes } from 'node:crypto';
2
2
  import { readFile } from 'node:fs/promises';
3
+ import { posix } from 'node:path';
3
4
  import { fileURLToPath } from 'node:url';
4
5
  import {
5
6
  commonTool,
@@ -388,9 +389,9 @@ const CLAUDE_CODE_BUILTIN_TOOLS = {
388
389
  } as const satisfies Record<string, HarnessV1BuiltinTool<any, any>>;
389
390
 
390
391
  /*
391
- * Bootstrap lives in /tmp because it's pure derived state — the harness can
392
- * reinstall the CLI and bridge files on any fresh sandbox from the recipe.
393
- * Persistence comes from the sandbox provider's snapshot, not the path.
392
+ * Bootstrap is derived state stored under the sandbox's default working
393
+ * directory so snapshot-capable providers can preserve the installed CLI,
394
+ * bridge, and recipe marker without requiring root filesystem access.
394
395
  *
395
396
  * The session work dir (`startOpts.sessionWorkDir`) and the bridge-state dir
396
397
  * derived from `sandboxSession.defaultWorkingDirectory` both live under the sandbox's
@@ -399,7 +400,7 @@ const CLAUDE_CODE_BUILTIN_TOOLS = {
399
400
  * history is keyed by working directory) and the bridge state files survive
400
401
  * both detach -> attach/replay and stop -> snapshot -> resume cycles.
401
402
  */
402
- const BOOTSTRAP_DIR = '/tmp/harness/claude-code';
403
+ const BOOTSTRAP_DIR = '.harness-bootstrap/claude-code';
403
404
 
404
405
  /**
405
406
  * Live bridge coordinates returned by `doDetach()` and `doSuspendTurn()`. A
@@ -460,12 +461,12 @@ export function createClaudeCode(
460
461
  { path: `${BOOTSTRAP_DIR}/bridge.mjs`, content: bridge },
461
462
  ],
462
463
  commands: [
463
- { command: `mkdir -p ${BOOTSTRAP_DIR}` },
464
464
  {
465
- command: `pnpm --dir ${BOOTSTRAP_DIR} install --frozen-lockfile --store-dir ${BOOTSTRAP_DIR}/.pnpm-store`,
465
+ command: 'pnpm install --frozen-lockfile --store-dir .pnpm-store',
466
466
  },
467
467
  {
468
- command: `cd ${BOOTSTRAP_DIR} && if [ -f node_modules/@anthropic-ai/claude-code/install.cjs ]; then node node_modules/@anthropic-ai/claude-code/install.cjs; fi && ./node_modules/.bin/claude --version`,
468
+ command:
469
+ 'if [ -f node_modules/@anthropic-ai/claude-code/install.cjs ]; then node node_modules/@anthropic-ai/claude-code/install.cjs; fi && ./node_modules/.bin/claude --version',
469
470
  },
470
471
  ],
471
472
  };
@@ -475,6 +476,10 @@ export function createClaudeCode(
475
476
  const sandboxSession = startOpts.sandboxSession;
476
477
  const session = sandboxSession.restricted();
477
478
  const sandboxId = sandboxSession.id;
479
+ const bootstrapDir = posix.resolve(
480
+ sandboxSession.defaultWorkingDirectory,
481
+ BOOTSTRAP_DIR,
482
+ );
478
483
  const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;
479
484
  const isResume = lifecycleState != null;
480
485
  const isContinue = startOpts.continueFrom != null;
@@ -644,7 +649,7 @@ export function createClaudeCode(
644
649
  });
645
650
 
646
651
  const proc = await session.spawn({
647
- command: `node ${BOOTSTRAP_DIR}/bridge.mjs --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)}`,
652
+ command: `node ${shellQuote(`${bootstrapDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)}`,
648
653
  env,
649
654
  abortSignal: startOpts.abortSignal,
650
655
  });