reeval 0.0.1

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.
Files changed (213) hide show
  1. package/LICENSE +202 -0
  2. package/THIRD_PARTY_NOTICES.md +2160 -0
  3. package/assets/package.json +9 -0
  4. package/assets/pnpm-lock.yaml +1336 -0
  5. package/dist/agent-DVHkx8aT.js +532 -0
  6. package/dist/agent-DVHkx8aT.js.map +1 -0
  7. package/dist/analysis-CxSCt1YY.js +16 -0
  8. package/dist/analysis-CxSCt1YY.js.map +1 -0
  9. package/dist/assemble-B-nmz8oH.js +695 -0
  10. package/dist/assemble-B-nmz8oH.js.map +1 -0
  11. package/dist/assemble-CmRVDZ2Q.js +2 -0
  12. package/dist/attempt-BdRQ9jKX.js +176 -0
  13. package/dist/attempt-BdRQ9jKX.js.map +1 -0
  14. package/dist/bridge/index.mjs +1911 -0
  15. package/dist/bridge/package.json +13 -0
  16. package/dist/bridge/pnpm-lock.yaml +1041 -0
  17. package/dist/bridge/pnpm-workspace.yaml +2 -0
  18. package/dist/budget-DBUrH4jX.js +8 -0
  19. package/dist/budget-DBUrH4jX.js.map +1 -0
  20. package/dist/cli--CQ3Iy9q.js +1865 -0
  21. package/dist/cli--CQ3Iy9q.js.map +1 -0
  22. package/dist/cli-spec-DKAu09Gi.js +478 -0
  23. package/dist/cli-spec-DKAu09Gi.js.map +1 -0
  24. package/dist/cli.d.ts +1 -0
  25. package/dist/cli.js +8 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/colors-QV9dFVhN.js +34 -0
  28. package/dist/colors-QV9dFVhN.js.map +1 -0
  29. package/dist/command-BSJzHMtP.js +280 -0
  30. package/dist/command-BSJzHMtP.js.map +1 -0
  31. package/dist/command-CEm8PZ1N.js +1043 -0
  32. package/dist/command-CEm8PZ1N.js.map +1 -0
  33. package/dist/command-D-jnQWVG.js +673 -0
  34. package/dist/command-D-jnQWVG.js.map +1 -0
  35. package/dist/command-DQAvbG7d.js +432 -0
  36. package/dist/command-DQAvbG7d.js.map +1 -0
  37. package/dist/commands-A4udfyKZ.js +2 -0
  38. package/dist/commands-CF8mOfiu.js +207 -0
  39. package/dist/commands-CF8mOfiu.js.map +1 -0
  40. package/dist/config-Cuj0kVYj.js +415 -0
  41. package/dist/config-Cuj0kVYj.js.map +1 -0
  42. package/dist/context-loi9OCZv.js +106 -0
  43. package/dist/context-loi9OCZv.js.map +1 -0
  44. package/dist/core-tLN-z1Be.js +96 -0
  45. package/dist/core-tLN-z1Be.js.map +1 -0
  46. package/dist/db-Cjj2ZsfQ.js +2 -0
  47. package/dist/db-DxDzMhtB.js +827 -0
  48. package/dist/db-DxDzMhtB.js.map +1 -0
  49. package/dist/debug-D24NOQH1.js +89 -0
  50. package/dist/debug-D24NOQH1.js.map +1 -0
  51. package/dist/debug-SEmW4w8f.js +2 -0
  52. package/dist/dist-BZXYHN2X.js +1673 -0
  53. package/dist/dist-BZXYHN2X.js.map +1 -0
  54. package/dist/docker-DQDZWXF9.js +20 -0
  55. package/dist/docker-DQDZWXF9.js.map +1 -0
  56. package/dist/docker-DnWAVdEm.js +2 -0
  57. package/dist/docker-oSbCExHL.js +153 -0
  58. package/dist/docker-oSbCExHL.js.map +1 -0
  59. package/dist/doctor-CxlH1pDM.js +525 -0
  60. package/dist/doctor-CxlH1pDM.js.map +1 -0
  61. package/dist/egress-73SQfKdx.js +619 -0
  62. package/dist/egress-73SQfKdx.js.map +1 -0
  63. package/dist/env-BQqj93gu.js +21 -0
  64. package/dist/env-BQqj93gu.js.map +1 -0
  65. package/dist/environment-Mz7wvrtD.js +552 -0
  66. package/dist/environment-Mz7wvrtD.js.map +1 -0
  67. package/dist/errors-C9w_ud7g.js +160 -0
  68. package/dist/errors-C9w_ud7g.js.map +1 -0
  69. package/dist/errors-CSxfJ4qu.js +11 -0
  70. package/dist/errors-CSxfJ4qu.js.map +1 -0
  71. package/dist/files--6CEUXm7.js +2 -0
  72. package/dist/files-BLlrhU4-.js +62 -0
  73. package/dist/files-BLlrhU4-.js.map +1 -0
  74. package/dist/files-Bd25OAQH.js +2 -0
  75. package/dist/files-BvHCFWgD.js +2 -0
  76. package/dist/files-D2-qn_Dl.js +275 -0
  77. package/dist/files-D2-qn_Dl.js.map +1 -0
  78. package/dist/files-bF2fPuT9.js +99 -0
  79. package/dist/files-bF2fPuT9.js.map +1 -0
  80. package/dist/git-D6hMeieS.js +44 -0
  81. package/dist/git-D6hMeieS.js.map +1 -0
  82. package/dist/harness-ls5aX1UO.js +131 -0
  83. package/dist/harness-ls5aX1UO.js.map +1 -0
  84. package/dist/harness.d.ts +74 -0
  85. package/dist/harness.js +2 -0
  86. package/dist/header-DzFDoMCI.js +78 -0
  87. package/dist/header-DzFDoMCI.js.map +1 -0
  88. package/dist/ids-Bp6ut7ZD.js +49 -0
  89. package/dist/ids-Bp6ut7ZD.js.map +1 -0
  90. package/dist/images-Cc1-coFc.js +286 -0
  91. package/dist/images-Cc1-coFc.js.map +1 -0
  92. package/dist/index.d.ts +97 -0
  93. package/dist/index.js +1959 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/init-CFljS8BJ.js +344 -0
  96. package/dist/init-CFljS8BJ.js.map +1 -0
  97. package/dist/init-z2ZPn9Tj.js +2 -0
  98. package/dist/invocations-rXktgSAn.js +157 -0
  99. package/dist/invocations-rXktgSAn.js.map +1 -0
  100. package/dist/jiti-BOLXpKyG.js +46 -0
  101. package/dist/jiti-BOLXpKyG.js.map +1 -0
  102. package/dist/judge-D8Uf4dA9.js +146 -0
  103. package/dist/judge-D8Uf4dA9.js.map +1 -0
  104. package/dist/judge.d.ts +21 -0
  105. package/dist/judge.js +19 -0
  106. package/dist/judge.js.map +1 -0
  107. package/dist/live-Bs3LReMV.js +98 -0
  108. package/dist/live-Bs3LReMV.js.map +1 -0
  109. package/dist/matchers-DyLvm7EG.js +374 -0
  110. package/dist/matchers-DyLvm7EG.js.map +1 -0
  111. package/dist/model-BdO79gWz.js +44 -0
  112. package/dist/model-BdO79gWz.js.map +1 -0
  113. package/dist/model-CDL98xue.js +725 -0
  114. package/dist/model-CDL98xue.js.map +1 -0
  115. package/dist/model-v-0_Ik7S.js +2 -0
  116. package/dist/node-kG64XxdE.js +506 -0
  117. package/dist/node-kG64XxdE.js.map +1 -0
  118. package/dist/opencode-providers-DZuD_oYt.js +3149 -0
  119. package/dist/opencode-providers-DZuD_oYt.js.map +1 -0
  120. package/dist/options-CAQhu--C.js +452 -0
  121. package/dist/options-CAQhu--C.js.map +1 -0
  122. package/dist/patch-BkKje4cp.js +69 -0
  123. package/dist/patch-BkKje4cp.js.map +1 -0
  124. package/dist/paths-CBvm6pap.js +72 -0
  125. package/dist/paths-CBvm6pap.js.map +1 -0
  126. package/dist/plan-gwk6dJ8c.js +237 -0
  127. package/dist/plan-gwk6dJ8c.js.map +1 -0
  128. package/dist/preflight-BtubXKQ8.js +2 -0
  129. package/dist/preflight-BypZMNBG.js +185 -0
  130. package/dist/preflight-BypZMNBG.js.map +1 -0
  131. package/dist/prepare-Cwv0bHs_.js +3 -0
  132. package/dist/prepare-D6Uzcubb.js +213 -0
  133. package/dist/prepare-D6Uzcubb.js.map +1 -0
  134. package/dist/provenance-Dfb8YY5Y.js +129 -0
  135. package/dist/provenance-Dfb8YY5Y.js.map +1 -0
  136. package/dist/provider-BDbNOQhQ.js +2 -0
  137. package/dist/provider-CmAYTQQs.js +14 -0
  138. package/dist/provider-CmAYTQQs.js.map +1 -0
  139. package/dist/providers-2p3ylMHI.js +107 -0
  140. package/dist/providers-2p3ylMHI.js.map +1 -0
  141. package/dist/providers-BUOxitcT.js +2 -0
  142. package/dist/query-CFATHZmV.js +91 -0
  143. package/dist/query-CFATHZmV.js.map +1 -0
  144. package/dist/query-DR4m6CXf.js +2 -0
  145. package/dist/record-DQ8wzyco.js +99 -0
  146. package/dist/record-DQ8wzyco.js.map +1 -0
  147. package/dist/redact-C4fL_bZP.js +167 -0
  148. package/dist/redact-C4fL_bZP.js.map +1 -0
  149. package/dist/results-CeXb8Wde.js +37 -0
  150. package/dist/results-CeXb8Wde.js.map +1 -0
  151. package/dist/root-CFDjpWuc.js +110 -0
  152. package/dist/root-CFDjpWuc.js.map +1 -0
  153. package/dist/sandbox-By2gkdkC.js +133 -0
  154. package/dist/sandbox-By2gkdkC.js.map +1 -0
  155. package/dist/sandbox.d.ts +41 -0
  156. package/dist/sandbox.js +2 -0
  157. package/dist/server-Bi61uiY0.js +350 -0
  158. package/dist/server-Bi61uiY0.js.map +1 -0
  159. package/dist/server-CsSBL8NC.js +2 -0
  160. package/dist/source-BXzrmof5.js +2 -0
  161. package/dist/source-Bsfa3LZH.js +40 -0
  162. package/dist/source-Bsfa3LZH.js.map +1 -0
  163. package/dist/src-55j1zNHH.js +3 -0
  164. package/dist/src-AEwxd1UP.js +602 -0
  165. package/dist/src-AEwxd1UP.js.map +1 -0
  166. package/dist/src-BDwSuyIo.js +3 -0
  167. package/dist/src-BQyMiWri.js +490 -0
  168. package/dist/src-BQyMiWri.js.map +1 -0
  169. package/dist/src-C-LHyTSV.js +3 -0
  170. package/dist/src-Cmp-7YrD.js +1136 -0
  171. package/dist/src-Cmp-7YrD.js.map +1 -0
  172. package/dist/src-D0RdqpNb.js +252 -0
  173. package/dist/src-D0RdqpNb.js.map +1 -0
  174. package/dist/src-D8KYzxBX.js +793 -0
  175. package/dist/src-D8KYzxBX.js.map +1 -0
  176. package/dist/src-DEgff9Z7.js +4 -0
  177. package/dist/src-DXx_29pq.js +567 -0
  178. package/dist/src-DXx_29pq.js.map +1 -0
  179. package/dist/src-DwwiVLqv.js +2937 -0
  180. package/dist/src-DwwiVLqv.js.map +1 -0
  181. package/dist/src-N7E_mfcZ.js +2 -0
  182. package/dist/src-W9g-y5X5.js +3 -0
  183. package/dist/src-daS0wKH2.js +3 -0
  184. package/dist/state-Cyw3QTsN.js +2 -0
  185. package/dist/state-DZ7eqb1F.js +167 -0
  186. package/dist/state-DZ7eqb1F.js.map +1 -0
  187. package/dist/stats-BNAHlNMD.js +114 -0
  188. package/dist/stats-BNAHlNMD.js.map +1 -0
  189. package/dist/studio-app/assets/index-D6XyfFSH.js +58 -0
  190. package/dist/studio-app/assets/index-xwzWdcE_.css +2 -0
  191. package/dist/studio-app/favicon.svg +1 -0
  192. package/dist/studio-app/index.html +15 -0
  193. package/dist/summary-D7Ttky0z.js +166 -0
  194. package/dist/summary-D7Ttky0z.js.map +1 -0
  195. package/dist/text-gEcKjAyp.js +29 -0
  196. package/dist/text-gEcKjAyp.js.map +1 -0
  197. package/dist/types-C5vI3g1C.js +9 -0
  198. package/dist/types-C5vI3g1C.js.map +1 -0
  199. package/dist/types-DLec-6Cx.d.ts +1535 -0
  200. package/dist/usage-DsYUqIUM.js +24 -0
  201. package/dist/usage-DsYUqIUM.js.map +1 -0
  202. package/dist/view/index.d.ts +645 -0
  203. package/dist/view/index.js +8 -0
  204. package/dist/views-BrHOv6wg.js +220 -0
  205. package/dist/views-BrHOv6wg.js.map +1 -0
  206. package/dist/views-CwCWLWqo.js +3 -0
  207. package/dist/worker-entry-DnYkANPG.js +506 -0
  208. package/dist/worker-entry-DnYkANPG.js.map +1 -0
  209. package/dist/workspace-C2S0Z6gl.js +327 -0
  210. package/dist/workspace-C2S0Z6gl.js.map +1 -0
  211. package/dist/workspace-CyoXG6CY.js +2 -0
  212. package/docker/Dockerfile +19 -0
  213. package/package.json +79 -0
@@ -0,0 +1,1673 @@
1
+ import { l as ownFileURL } from "./root-CFDjpWuc.js";
2
+ import { dirname, join, posix, resolve } from "path";
3
+ import { HARNESS_V1_BUILTIN_TOOLS, HarnessCapabilityUnsupportedError, commonTool, harnessSessionDataDirectoryPath, harnessStateDirectoryPath, harnessV1BridgeInboundCommandSchemas, harnessV1BridgeOutboundMessageSchema, harnessV1BridgeStartBaseSchema, harnessV1DiagnosticFromBridgeFrame } from "@ai-sdk/harness";
4
+ import { SandboxChannel, applyCredentialForwarding, classifyDiskLog, createBridgeErrorHandler, createBridgeStartupError, createBridgeToken, createCredentialRequestTransformation, createReadBridgeAsset, createSandboxCredentialEnvironment, drainBridgeProcessStream, experimental_createBridgeUserMessageSubmitter, forwardBridgeProcessStream, getAiGatewayAuthFromEnv, getRestrictedSandboxSession, isAccessTokenExpiringSoon, isHarnessAuthenticationEnvironment, isMacOS, markBridgeStarting, readMacOSKeychainPassword, refreshOAuthAccessToken, resolveSandboxHomeDir, shellQuote, shouldResolveNativeSubscription, sleep, waitForBridgeReady, warnCredentialBrokeringUnavailable, withBridgeToken, writeSkills } from "@ai-sdk/harness/utils";
5
+ import { isRecord, safeParseJSON, tool } from "@ai-sdk/provider-utils";
6
+ import { WebSocket } from "ws";
7
+ import { z } from "zod/v4";
8
+ import { execFileSync } from "child_process";
9
+ import { readFileSync } from "fs";
10
+ import { homedir } from "os";
11
+ import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
12
+ //#region ../../node_modules/.pnpm/@ai-sdk+harness-claude-code@1.0.128_patch_hash=5d1c985cccfd5adf255e05536c0c2bf570cb49aa_cafe426571bfb8cfcbbfa8ad488f9b8a/node_modules/@ai-sdk/harness-claude-code/dist/index.js
13
+ var readBridgeAsset = createReadBridgeAsset({
14
+ "package.json": ownFileURL("dist/bridge/package.json"),
15
+ "pnpm-lock.yaml": ownFileURL("dist/bridge/pnpm-lock.yaml"),
16
+ "pnpm-workspace.yaml": ownFileURL("dist/bridge/pnpm-workspace.yaml"),
17
+ "index.mjs": ownFileURL("dist/bridge/index.mjs")
18
+ });
19
+ var CLAUDE_CODE_BOOTSTRAP_DIR = ".harness-bootstrap/claude-code";
20
+ var cachedBootstrap;
21
+ async function getClaudeCodeBootstrap() {
22
+ if (cachedBootstrap != null) return cachedBootstrap;
23
+ const [pkg, lock, workspace, bridge] = await Promise.all([
24
+ readBridgeAsset("package.json"),
25
+ readBridgeAsset("pnpm-lock.yaml"),
26
+ readBridgeAsset("pnpm-workspace.yaml"),
27
+ readBridgeAsset("index.mjs")
28
+ ]);
29
+ cachedBootstrap = {
30
+ harnessId: "claude-code",
31
+ bootstrapDir: CLAUDE_CODE_BOOTSTRAP_DIR,
32
+ files: [
33
+ {
34
+ path: `${CLAUDE_CODE_BOOTSTRAP_DIR}/package.json`,
35
+ content: pkg
36
+ },
37
+ {
38
+ path: `${CLAUDE_CODE_BOOTSTRAP_DIR}/pnpm-lock.yaml`,
39
+ content: lock
40
+ },
41
+ {
42
+ path: `${CLAUDE_CODE_BOOTSTRAP_DIR}/pnpm-workspace.yaml`,
43
+ content: workspace
44
+ },
45
+ {
46
+ path: `${CLAUDE_CODE_BOOTSTRAP_DIR}/bridge.mjs`,
47
+ content: bridge
48
+ }
49
+ ],
50
+ commands: [{ command: "pnpm install --frozen-lockfile --store-dir .pnpm-store" }, { command: "./node_modules/.bin/claude --version" }]
51
+ };
52
+ return cachedBootstrap;
53
+ }
54
+ var CLAUDE_CODE_CREDENTIAL_ENVIRONMENT_VARIABLES = [
55
+ "AI_GATEWAY_API_KEY",
56
+ "ANTHROPIC_API_KEY",
57
+ "ANTHROPIC_AUTH_TOKEN",
58
+ "CLAUDE_CODE_OAUTH_TOKEN"
59
+ ];
60
+ function createClaudeCodeRequestTransformations({ env: environment, sandboxEnv: sandboxEnvironment, auth: authenticationMode }) {
61
+ const matchUrl = authenticationMode === "ai-gateway" ? environment.ANTHROPIC_BASE_URL : environment.ANTHROPIC_BASE_URL ?? "https://api.anthropic.com";
62
+ const transformations = [];
63
+ if (environment.ANTHROPIC_API_KEY != null && sandboxEnvironment.ANTHROPIC_API_KEY != null) transformations.push(createCredentialRequestTransformation({
64
+ matchUrl,
65
+ matchHeaders: { "x-api-key": sandboxEnvironment.ANTHROPIC_API_KEY },
66
+ transformHeaders: { "x-api-key": environment.ANTHROPIC_API_KEY }
67
+ }));
68
+ if (environment.ANTHROPIC_AUTH_TOKEN != null && sandboxEnvironment.ANTHROPIC_AUTH_TOKEN != null) transformations.push(createCredentialRequestTransformation({
69
+ matchUrl,
70
+ matchHeaders: { Authorization: `Bearer ${sandboxEnvironment.ANTHROPIC_AUTH_TOKEN}` },
71
+ transformHeaders: { Authorization: `Bearer ${environment.ANTHROPIC_AUTH_TOKEN}` }
72
+ }));
73
+ return transformations;
74
+ }
75
+ function resolveClaudeCodeEnv(auth, processEnv = process.env, options = {}) {
76
+ const suppliedEnvironment = isHarnessAuthenticationEnvironment(auth);
77
+ const authenticationEnvironment = suppliedEnvironment ? auth : processEnv;
78
+ const readApiKey = suppliedEnvironment || auth === "direct" ? () => void 0 : options.readApiKeyHelper ?? readApiKeyHelper;
79
+ if (auth === "direct") return pickAnthropic({
80
+ processEnv: authenticationEnvironment,
81
+ readApiKey
82
+ });
83
+ const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({ env: authenticationEnvironment });
84
+ if (auth === "ai-gateway" || gatewayAuthFromEnv.apiKey) return pickGateway({ gatewayAuthFromEnv });
85
+ return pickAnthropic({
86
+ processEnv: authenticationEnvironment,
87
+ readApiKey
88
+ });
89
+ }
90
+ function resolveClaudeCodeAuthenticationMode(auth, processEnv = process.env) {
91
+ if (isHarnessAuthenticationEnvironment(auth)) return getAiGatewayAuthFromEnv({ env: auth }).apiKey ? "ai-gateway" : "direct";
92
+ if (auth === "direct") return "direct";
93
+ if (auth === "ai-gateway") return "ai-gateway";
94
+ return getAiGatewayAuthFromEnv({ env: processEnv }).apiKey ? "ai-gateway" : "direct";
95
+ }
96
+ function pickAnthropic({ processEnv, readApiKey }) {
97
+ const env = {};
98
+ const helperKey = readApiKey();
99
+ const apiKey = processEnv.ANTHROPIC_API_KEY ?? helperKey;
100
+ const authToken = processEnv.ANTHROPIC_AUTH_TOKEN ?? helperKey;
101
+ const oauthToken = processEnv.CLAUDE_CODE_OAUTH_TOKEN;
102
+ if (apiKey) env.ANTHROPIC_API_KEY = apiKey;
103
+ if (authToken) env.ANTHROPIC_AUTH_TOKEN = authToken;
104
+ if (oauthToken) env.CLAUDE_CODE_OAUTH_TOKEN = oauthToken;
105
+ const baseUrl = processEnv.ANTHROPIC_BASE_URL;
106
+ if (baseUrl) env.ANTHROPIC_BASE_URL = baseUrl;
107
+ return env;
108
+ }
109
+ function readApiKeyHelper() {
110
+ const home = homedir();
111
+ if (!home) return void 0;
112
+ let raw;
113
+ try {
114
+ raw = readFileSync(join(home, ".claude", "settings.json"), "utf8");
115
+ } catch {
116
+ return;
117
+ }
118
+ let settings;
119
+ try {
120
+ settings = JSON.parse(raw);
121
+ } catch {
122
+ return;
123
+ }
124
+ const command = settings.apiKeyHelper;
125
+ if (typeof command !== "string" || command.length === 0) return void 0;
126
+ try {
127
+ const trimmed = execFileSync("sh", ["-c", command], {
128
+ encoding: "utf8",
129
+ stdio: [
130
+ "ignore",
131
+ "pipe",
132
+ "ignore"
133
+ ]
134
+ }).trim();
135
+ return trimmed.length > 0 ? trimmed : void 0;
136
+ } catch {
137
+ return;
138
+ }
139
+ }
140
+ function pickGateway({ gatewayAuthFromEnv }) {
141
+ const apiKey = gatewayAuthFromEnv.apiKey;
142
+ const baseUrl = gatewayAuthFromEnv.baseUrl;
143
+ const env = {};
144
+ if (apiKey) {
145
+ env.AI_GATEWAY_API_KEY = apiKey;
146
+ env.ANTHROPIC_API_KEY = apiKey;
147
+ }
148
+ env.AI_GATEWAY_BASE_URL = baseUrl;
149
+ env.ANTHROPIC_BASE_URL = baseUrl;
150
+ return env;
151
+ }
152
+ var CLAUDE_TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
153
+ var CLAUDE_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
154
+ function createClaudeCodeSubscriptionRequestTransformations({ env: environment, sandboxEnv: sandboxEnvironment, auth: authenticationMode }) {
155
+ if (environment.CLAUDE_CODE_OAUTH_TOKEN == null || sandboxEnvironment.CLAUDE_CODE_OAUTH_TOKEN == null) return [];
156
+ return [createCredentialRequestTransformation({
157
+ matchUrl: authenticationMode === "ai-gateway" ? environment.ANTHROPIC_BASE_URL : environment.ANTHROPIC_BASE_URL ?? "https://api.anthropic.com",
158
+ matchHeaders: { Authorization: `Bearer ${sandboxEnvironment.CLAUDE_CODE_OAUTH_TOKEN}` },
159
+ transformHeaders: { Authorization: `Bearer ${environment.CLAUDE_CODE_OAUTH_TOKEN}` }
160
+ })];
161
+ }
162
+ async function resolveClaudeCodeAuthentication({ auth, processEnv = process.env, options = {}, readSubscription = readClaudeCodeSubscription }) {
163
+ const environmentWithoutHelper = resolveClaudeCodeEnv(auth, processEnv, { readApiKeyHelper: () => void 0 });
164
+ if (isHarnessAuthenticationEnvironment(auth)) return environmentWithoutHelper;
165
+ if (!shouldResolveNativeSubscription({
166
+ auth,
167
+ env: environmentWithoutHelper,
168
+ hasDirectCredential: environmentWithoutHelper.ANTHROPIC_API_KEY != null || environmentWithoutHelper.ANTHROPIC_AUTH_TOKEN != null || environmentWithoutHelper.CLAUDE_CODE_OAUTH_TOKEN != null
169
+ })) return environmentWithoutHelper;
170
+ return await readSubscription() ?? resolveClaudeCodeEnv(auth, processEnv, options);
171
+ }
172
+ async function readClaudeCodeSubscription({ env = process.env, homeDirectory = homedir(), platform = process.platform, fetch } = {}) {
173
+ const configDirectory = resolve(env.CLAUDE_CONFIG_DIR ?? join(homeDirectory, ".claude"));
174
+ const stored = await readClaudeCredentialStore({
175
+ credentialPath: join(configDirectory, ".credentials.json"),
176
+ homeDirectory,
177
+ configDirectory,
178
+ platform
179
+ });
180
+ if (stored == null) return void 0;
181
+ const oauth = getClaudeOAuthCredential({ value: stored.value });
182
+ if (oauth == null) return void 0;
183
+ const { accessToken, refreshToken, expiresAt } = oauth;
184
+ let resolvedAccessToken = accessToken;
185
+ if (isAccessTokenExpiringSoon({ expiresAt })) {
186
+ const refreshed = await refreshOAuthAccessToken({
187
+ tokenUrl: CLAUDE_TOKEN_URL,
188
+ clientId: CLAUDE_CLIENT_ID,
189
+ refreshToken,
190
+ requestFormat: "json",
191
+ ...fetch == null ? {} : { fetch }
192
+ });
193
+ resolvedAccessToken = refreshed.accessToken;
194
+ await stored.write({
195
+ ...stored.value,
196
+ claudeAiOauth: {
197
+ ...oauth,
198
+ accessToken: refreshed.accessToken,
199
+ refreshToken: refreshed.refreshToken ?? refreshToken,
200
+ expiresAt: refreshed.expiresAt
201
+ }
202
+ });
203
+ }
204
+ return {
205
+ CLAUDE_CODE_OAUTH_TOKEN: resolvedAccessToken,
206
+ ANTHROPIC_BASE_URL: "https://api.anthropic.com"
207
+ };
208
+ }
209
+ async function readClaudeCredentialStore({ credentialPath, homeDirectory, configDirectory, platform }) {
210
+ const text = await readFile(credentialPath, "utf8").catch(() => void 0);
211
+ if (text != null) {
212
+ const value2 = await parseClaudeCredentialFile(text);
213
+ if (value2 != null && getClaudeOAuthCredential({ value: value2 }) != null) return {
214
+ value: value2,
215
+ write: (updated) => writeClaudeCredentialFile({
216
+ credentialPath,
217
+ value: updated
218
+ })
219
+ };
220
+ }
221
+ if (!isMacOS(platform)) return void 0;
222
+ if (configDirectory !== resolve(join(homeDirectory, ".claude"))) return;
223
+ const service = "Claude Code-credentials";
224
+ const keychainText = await readMacOSKeychainPassword({
225
+ service,
226
+ account: process.env.USER ?? ""
227
+ });
228
+ if (keychainText == null) return void 0;
229
+ const value = await parseClaudeCredentialFile(keychainText);
230
+ if (value == null) return void 0;
231
+ return {
232
+ value,
233
+ write: async (updated) => {
234
+ execFileSync("/usr/bin/security", [
235
+ "add-generic-password",
236
+ "-U",
237
+ "-s",
238
+ service,
239
+ "-a",
240
+ process.env.USER ?? "",
241
+ "-w",
242
+ JSON.stringify(updated)
243
+ ], { stdio: "ignore" });
244
+ }
245
+ };
246
+ }
247
+ function getClaudeOAuthCredential({ value }) {
248
+ const oauth = value.claudeAiOauth;
249
+ if (!isRecord(oauth) || typeof oauth.accessToken !== "string" || typeof oauth.refreshToken !== "string" || typeof oauth.expiresAt !== "number") return;
250
+ return oauth;
251
+ }
252
+ async function parseClaudeCredentialFile(text) {
253
+ const parsed = await safeParseJSON({ text });
254
+ return parsed.success && isRecord(parsed.value) ? parsed.value : void 0;
255
+ }
256
+ async function writeClaudeCredentialFile({ credentialPath, value }) {
257
+ await mkdir(dirname(credentialPath), { recursive: true });
258
+ const temporaryPath = `${credentialPath}.${process.pid}.tmp`;
259
+ await writeFile(temporaryPath, `${JSON.stringify(value, null, 2)}
260
+ `, { mode: 384 });
261
+ await chmod(temporaryPath, 384);
262
+ await rename(temporaryPath, credentialPath);
263
+ }
264
+ var outboundMessageSchema = harnessV1BridgeOutboundMessageSchema;
265
+ var thinkingDisplaySchema = z.enum(["summarized", "omitted"]).optional();
266
+ var thinkingSchema = z.discriminatedUnion("type", [
267
+ z.object({
268
+ type: z.literal("adaptive"),
269
+ display: thinkingDisplaySchema
270
+ }),
271
+ z.object({
272
+ type: z.literal("enabled"),
273
+ display: thinkingDisplaySchema
274
+ }),
275
+ z.object({ type: z.literal("disabled") })
276
+ ]);
277
+ var startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
278
+ instructions: z.string().optional(),
279
+ thinking: thinkingSchema,
280
+ effort: z.enum([
281
+ "low",
282
+ "medium",
283
+ "high",
284
+ "xhigh",
285
+ "max"
286
+ ]).optional(),
287
+ maxTurns: z.number().optional(),
288
+ env: z.record(z.string(), z.string()).optional(),
289
+ skills: z.array(z.string()).optional(),
290
+ mcpServers: z.record(z.string(), z.unknown()).optional(),
291
+ continue: z.boolean().optional(),
292
+ resumeSessionId: z.string().optional()
293
+ });
294
+ z.discriminatedUnion("type", [startMessageSchema, ...harnessV1BridgeInboundCommandSchemas]);
295
+ var CLAUDE_CODE_CLIENT_APP = `ai-sdk/harness-claude-code/1.0.128`;
296
+ var listMcpResourcesInputSchema = z.object({ server: z.string().optional() });
297
+ var readMcpResourceInputSchema = z.object({
298
+ server: z.string(),
299
+ uri: z.string()
300
+ });
301
+ var structuredTeamMessageSchema = z.discriminatedUnion("type", [
302
+ z.object({
303
+ type: z.literal("shutdown_request"),
304
+ reason: z.string().optional()
305
+ }),
306
+ z.object({
307
+ type: z.literal("shutdown_response"),
308
+ request_id: z.string(),
309
+ approve: z.boolean(),
310
+ reason: z.string().optional()
311
+ }),
312
+ z.object({
313
+ type: z.literal("plan_approval_response"),
314
+ request_id: z.string(),
315
+ approve: z.boolean(),
316
+ feedback: z.string().optional()
317
+ })
318
+ ]);
319
+ var CLAUDE_CODE_BUILTIN_TOOLS = {
320
+ read: commonTool("read", {
321
+ nativeName: "Read",
322
+ toolUseKind: "readonly",
323
+ description: "Read file contents (text, image, PDF, notebook)",
324
+ inputSchema: z.object({
325
+ file_path: z.string(),
326
+ offset: z.number().optional(),
327
+ limit: z.number().optional(),
328
+ pages: z.string().optional()
329
+ })
330
+ }),
331
+ write: commonTool("write", {
332
+ nativeName: "Write",
333
+ toolUseKind: "edit",
334
+ description: "Overwrite or create a file at an absolute path",
335
+ inputSchema: z.object({
336
+ file_path: z.string(),
337
+ content: z.string()
338
+ })
339
+ }),
340
+ edit: commonTool("edit", {
341
+ nativeName: "Edit",
342
+ toolUseKind: "edit",
343
+ description: "Edit a file by exact string replacement",
344
+ inputSchema: z.object({
345
+ file_path: z.string(),
346
+ old_string: z.string(),
347
+ new_string: z.string(),
348
+ replace_all: z.boolean().optional()
349
+ })
350
+ }),
351
+ bash: commonTool("bash", {
352
+ nativeName: "Bash",
353
+ toolUseKind: "bash",
354
+ description: "Execute a shell command, optionally in background",
355
+ inputSchema: z.object({
356
+ command: z.string(),
357
+ timeout: z.number().optional(),
358
+ description: z.string().optional(),
359
+ run_in_background: z.boolean().optional(),
360
+ dangerouslyDisableSandbox: z.boolean().optional()
361
+ })
362
+ }),
363
+ glob: commonTool("glob", {
364
+ nativeName: "Glob",
365
+ toolUseKind: "readonly",
366
+ description: "Fast file-pattern search using glob syntax",
367
+ inputSchema: z.object({
368
+ pattern: z.string(),
369
+ path: z.string().optional()
370
+ })
371
+ }),
372
+ grep: commonTool("grep", {
373
+ nativeName: "Grep",
374
+ toolUseKind: "readonly",
375
+ description: "Regex search over file contents via ripgrep",
376
+ inputSchema: z.object({
377
+ pattern: z.string(),
378
+ path: z.string().optional(),
379
+ glob: z.string().optional(),
380
+ output_mode: z.enum([
381
+ "content",
382
+ "files_with_matches",
383
+ "count"
384
+ ]).optional(),
385
+ "-B": z.number().optional(),
386
+ "-A": z.number().optional(),
387
+ "-C": z.number().optional(),
388
+ context: z.number().optional(),
389
+ "-n": z.boolean().optional(),
390
+ "-i": z.boolean().optional(),
391
+ "-o": z.boolean().optional(),
392
+ type: z.string().optional(),
393
+ head_limit: z.number().optional(),
394
+ offset: z.number().optional(),
395
+ multiline: z.boolean().optional()
396
+ })
397
+ }),
398
+ webSearch: commonTool("webSearch", {
399
+ nativeName: "WebSearch",
400
+ toolUseKind: "readonly",
401
+ description: "Issue web search queries with optional domain filters",
402
+ inputSchema: z.object({
403
+ query: z.string(),
404
+ allowed_domains: z.array(z.string()).optional(),
405
+ blocked_domains: z.array(z.string()).optional()
406
+ })
407
+ }),
408
+ WebFetch: tool({
409
+ description: "Fetch a URL and run a prompt against its content",
410
+ inputSchema: z.object({
411
+ url: z.string(),
412
+ prompt: z.string()
413
+ })
414
+ }),
415
+ NotebookEdit: tool({
416
+ description: "Edit, insert, or delete a Jupyter notebook cell",
417
+ inputSchema: z.object({
418
+ notebook_path: z.string(),
419
+ new_source: z.string(),
420
+ cell_id: z.string().optional(),
421
+ cell_type: z.enum(["code", "markdown"]).optional(),
422
+ edit_mode: z.enum([
423
+ "replace",
424
+ "insert",
425
+ "delete"
426
+ ]).optional()
427
+ })
428
+ }),
429
+ TodoWrite: tool({
430
+ description: "Replace the session todo list",
431
+ inputSchema: z.object({ todos: z.array(z.object({
432
+ content: z.string(),
433
+ status: z.enum([
434
+ "pending",
435
+ "in_progress",
436
+ "completed"
437
+ ]),
438
+ activeForm: z.string()
439
+ })) })
440
+ }),
441
+ Agent: tool({
442
+ description: "Spawn a subagent with a task",
443
+ inputSchema: z.object({
444
+ description: z.string(),
445
+ prompt: z.string(),
446
+ subagent_type: z.string().optional(),
447
+ model: z.enum([
448
+ "sonnet",
449
+ "opus",
450
+ "haiku"
451
+ ]).optional(),
452
+ run_in_background: z.boolean().optional(),
453
+ name: z.string().optional(),
454
+ team_name: z.string().optional(),
455
+ mode: z.enum([
456
+ "acceptEdits",
457
+ "auto",
458
+ "bypassPermissions",
459
+ "default",
460
+ "dontAsk",
461
+ "plan"
462
+ ]).optional(),
463
+ isolation: z.literal("worktree").optional()
464
+ })
465
+ }),
466
+ TaskCreate: tool({
467
+ description: "Create a task in the session-local task list",
468
+ inputSchema: z.object({
469
+ subject: z.string(),
470
+ description: z.string(),
471
+ activeForm: z.string().optional(),
472
+ metadata: z.record(z.string(), z.unknown()).optional()
473
+ })
474
+ }),
475
+ TaskGet: tool({
476
+ description: "Retrieve a task by id",
477
+ inputSchema: z.object({ taskId: z.string() })
478
+ }),
479
+ TaskUpdate: tool({
480
+ description: "Update fields of an existing task",
481
+ inputSchema: z.object({
482
+ taskId: z.string(),
483
+ subject: z.string().optional(),
484
+ description: z.string().optional(),
485
+ activeForm: z.string().optional(),
486
+ status: z.union([z.enum([
487
+ "pending",
488
+ "in_progress",
489
+ "completed"
490
+ ]), z.literal("deleted")]).optional(),
491
+ addBlocks: z.array(z.string()).optional(),
492
+ addBlockedBy: z.array(z.string()).optional(),
493
+ owner: z.string().optional(),
494
+ metadata: z.record(z.string(), z.unknown()).optional()
495
+ })
496
+ }),
497
+ TaskList: tool({
498
+ description: "Return all tasks in the session-local task list",
499
+ inputSchema: z.object({})
500
+ }),
501
+ TaskStop: tool({
502
+ description: "Stop a running background task by id",
503
+ inputSchema: z.object({
504
+ task_id: z.string().optional(),
505
+ shell_id: z.string().optional()
506
+ })
507
+ }),
508
+ TaskOutput: tool({
509
+ description: "Poll for output from a background task",
510
+ inputSchema: z.object({
511
+ task_id: z.string(),
512
+ block: z.boolean(),
513
+ timeout: z.number()
514
+ })
515
+ }),
516
+ Monitor: {
517
+ ...tool({
518
+ description: "Run and monitor a shell command or WebSocket",
519
+ inputSchema: z.object({
520
+ description: z.string().optional(),
521
+ timeout_ms: z.number().optional(),
522
+ persistent: z.boolean().optional(),
523
+ command: z.string().optional(),
524
+ ws: z.object({
525
+ url: z.string(),
526
+ protocols: z.array(z.string()).optional()
527
+ }).optional()
528
+ })
529
+ }),
530
+ toolUseKind: "bash"
531
+ },
532
+ ListMcpResources: {
533
+ ...tool({
534
+ description: "List resources available from MCP servers",
535
+ inputSchema: listMcpResourcesInputSchema
536
+ }),
537
+ toolUseKind: "readonly"
538
+ },
539
+ ListMcpResourcesTool: {
540
+ ...tool({
541
+ description: "List resources available from MCP servers",
542
+ inputSchema: listMcpResourcesInputSchema
543
+ }),
544
+ toolUseKind: "readonly"
545
+ },
546
+ ReadMcpResource: {
547
+ ...tool({
548
+ description: "Read a specific MCP resource by URI",
549
+ inputSchema: readMcpResourceInputSchema
550
+ }),
551
+ toolUseKind: "readonly"
552
+ },
553
+ ReadMcpResourceTool: {
554
+ ...tool({
555
+ description: "Read a specific MCP resource by URI",
556
+ inputSchema: readMcpResourceInputSchema
557
+ }),
558
+ toolUseKind: "readonly"
559
+ },
560
+ ReadMcpResourceDirTool: {
561
+ ...tool({
562
+ description: "List direct children of an MCP directory resource",
563
+ inputSchema: readMcpResourceInputSchema
564
+ }),
565
+ toolUseKind: "readonly"
566
+ },
567
+ RefreshMcpTools: {
568
+ ...tool({
569
+ description: "Refresh tools from one or all connected MCP servers",
570
+ inputSchema: z.object({ server: z.string().optional() })
571
+ }),
572
+ toolUseKind: "readonly"
573
+ },
574
+ ExitPlanMode: tool({
575
+ description: "Exit plan mode with optional permission approvals",
576
+ inputSchema: z.looseObject({ allowedPrompts: z.array(z.object({
577
+ tool: z.literal("Bash"),
578
+ prompt: z.string()
579
+ })).optional() })
580
+ }),
581
+ EnterPlanMode: {
582
+ ...tool({
583
+ description: "Enter plan mode",
584
+ inputSchema: z.object({})
585
+ }),
586
+ toolUseKind: "readonly"
587
+ },
588
+ EnterWorktree: tool({
589
+ description: "Create or enter an isolated git worktree",
590
+ inputSchema: z.object({
591
+ name: z.string().optional(),
592
+ path: z.string().optional()
593
+ })
594
+ }),
595
+ ExitWorktree: tool({
596
+ description: "Exit the current worktree session",
597
+ inputSchema: z.object({
598
+ action: z.enum(["keep", "remove"]),
599
+ discard_changes: z.boolean().optional()
600
+ })
601
+ }),
602
+ askUserQuestions: {
603
+ ...HARNESS_V1_BUILTIN_TOOLS.askUserQuestions,
604
+ nativeName: "AskUserQuestion",
605
+ toolUseKind: "readonly"
606
+ },
607
+ Skill: {
608
+ ...tool({
609
+ description: "Activate a skill by name",
610
+ inputSchema: z.object({
611
+ skill: z.string(),
612
+ args: z.string().optional()
613
+ })
614
+ }),
615
+ toolUseKind: "readonly"
616
+ },
617
+ ToolSearch: tool({
618
+ description: "Search deferred MCP / catalog tools so the model can load them on demand",
619
+ inputSchema: z.object({
620
+ query: z.string(),
621
+ max_results: z.number().optional()
622
+ })
623
+ }),
624
+ Artifact: {
625
+ ...tool({
626
+ description: "Publish or list claude.ai artifacts",
627
+ inputSchema: z.object({
628
+ action: z.enum(["publish", "list"]).optional(),
629
+ file_path: z.string().optional(),
630
+ favicon: z.string().optional(),
631
+ limit: z.number().optional(),
632
+ scope: z.enum([
633
+ "mine",
634
+ "shared",
635
+ "all"
636
+ ]).optional(),
637
+ title: z.string().optional(),
638
+ description: z.string().optional(),
639
+ label: z.string().optional(),
640
+ url: z.string().optional(),
641
+ force: z.boolean().optional()
642
+ })
643
+ }),
644
+ toolUseKind: "edit"
645
+ },
646
+ CronCreate: {
647
+ ...tool({
648
+ description: "Schedule a recurring or one-shot prompt",
649
+ inputSchema: z.object({
650
+ cron: z.string(),
651
+ prompt: z.string(),
652
+ recurring: z.boolean().optional(),
653
+ durable: z.boolean().optional()
654
+ })
655
+ }),
656
+ toolUseKind: "edit"
657
+ },
658
+ CronDelete: {
659
+ ...tool({
660
+ description: "Delete a scheduled prompt by id",
661
+ inputSchema: z.object({ id: z.string() })
662
+ }),
663
+ toolUseKind: "edit"
664
+ },
665
+ CronList: {
666
+ ...tool({
667
+ description: "List scheduled prompts for the current session",
668
+ inputSchema: z.object({})
669
+ }),
670
+ toolUseKind: "readonly"
671
+ },
672
+ DesignSync: {
673
+ ...tool({
674
+ description: "Read or update claude.ai Design projects",
675
+ inputSchema: z.object({
676
+ method: z.enum([
677
+ "list_projects",
678
+ "get_project",
679
+ "list_files",
680
+ "get_file",
681
+ "finalize_plan",
682
+ "write_files",
683
+ "delete_files",
684
+ "register_assets",
685
+ "unregister_assets",
686
+ "create_project",
687
+ "report_validate"
688
+ ]),
689
+ projectId: z.string().optional(),
690
+ path: z.string().optional(),
691
+ writes: z.array(z.string()).max(256).optional(),
692
+ deletes: z.array(z.string()).max(256).optional(),
693
+ planId: z.string().optional(),
694
+ files: z.array(z.object({
695
+ path: z.string(),
696
+ localPath: z.string().optional(),
697
+ data: z.string().optional(),
698
+ encoding: z.literal("base64").optional(),
699
+ mimeType: z.string().optional()
700
+ })).max(256).optional(),
701
+ paths: z.array(z.string()).max(256).optional(),
702
+ name: z.string().optional(),
703
+ assets: z.array(z.object({
704
+ name: z.string(),
705
+ path: z.string(),
706
+ subtitle: z.string().optional(),
707
+ viewport: z.object({
708
+ width: z.number(),
709
+ height: z.number().optional()
710
+ }).optional(),
711
+ group: z.string().optional()
712
+ })).max(256).optional(),
713
+ localDir: z.string().optional(),
714
+ counts: z.object({
715
+ total: z.number(),
716
+ bad: z.number(),
717
+ thin: z.number(),
718
+ variantsIdentical: z.number(),
719
+ iterations: z.number()
720
+ }).optional()
721
+ })
722
+ }),
723
+ toolUseKind: "edit"
724
+ },
725
+ LSP: {
726
+ ...tool({
727
+ description: "Query a language server for code intelligence",
728
+ inputSchema: z.object({
729
+ operation: z.enum([
730
+ "goToDefinition",
731
+ "findReferences",
732
+ "hover",
733
+ "documentSymbol",
734
+ "workspaceSymbol",
735
+ "goToImplementation",
736
+ "prepareCallHierarchy",
737
+ "incomingCalls",
738
+ "outgoingCalls"
739
+ ]),
740
+ filePath: z.string(),
741
+ line: z.number().int().positive(),
742
+ character: z.number().int().positive(),
743
+ query: z.string().optional()
744
+ })
745
+ }),
746
+ toolUseKind: "readonly"
747
+ },
748
+ PowerShell: {
749
+ ...tool({
750
+ description: "Execute a PowerShell command, optionally in background",
751
+ inputSchema: z.object({
752
+ command: z.string(),
753
+ timeout: z.number().optional(),
754
+ description: z.string().optional(),
755
+ run_in_background: z.boolean().optional(),
756
+ dangerouslyDisableSandbox: z.boolean().optional()
757
+ })
758
+ }),
759
+ toolUseKind: "bash"
760
+ },
761
+ PushNotification: {
762
+ ...tool({
763
+ description: "Send a notification for proactive or scheduled work",
764
+ inputSchema: z.object({
765
+ message: z.string(),
766
+ status: z.literal("proactive")
767
+ })
768
+ }),
769
+ toolUseKind: "edit"
770
+ },
771
+ RemoteTrigger: {
772
+ ...tool({
773
+ description: "List, manage, or run a claude.ai Routine trigger",
774
+ inputSchema: z.object({
775
+ action: z.enum([
776
+ "list",
777
+ "get",
778
+ "create",
779
+ "update",
780
+ "run"
781
+ ]),
782
+ trigger_id: z.string().optional(),
783
+ body: z.record(z.string(), z.unknown()).optional()
784
+ })
785
+ }),
786
+ toolUseKind: "edit"
787
+ },
788
+ ReportFindings: {
789
+ ...tool({
790
+ description: "Return verified code-review findings",
791
+ inputSchema: z.object({
792
+ level: z.enum([
793
+ "low",
794
+ "medium",
795
+ "high",
796
+ "xhigh",
797
+ "max"
798
+ ]).optional(),
799
+ findings: z.array(z.object({
800
+ file: z.string(),
801
+ line: z.number().optional(),
802
+ summary: z.string(),
803
+ short_summary: z.string().optional(),
804
+ failure_scenario: z.string(),
805
+ category: z.string().optional(),
806
+ verdict: z.enum(["CONFIRMED", "PLAUSIBLE"]).optional(),
807
+ outcome: z.enum([
808
+ "fixed",
809
+ "skipped",
810
+ "no_change_needed"
811
+ ]).optional()
812
+ })).max(32)
813
+ })
814
+ }),
815
+ toolUseKind: "readonly"
816
+ },
817
+ ScheduleWakeup: {
818
+ ...tool({
819
+ description: "Schedule or stop the next iteration of a dynamic loop",
820
+ inputSchema: z.object({
821
+ delaySeconds: z.number().optional(),
822
+ reason: z.string().optional(),
823
+ prompt: z.string().optional(),
824
+ stop: z.boolean().optional()
825
+ })
826
+ }),
827
+ toolUseKind: "edit"
828
+ },
829
+ SendMessage: {
830
+ ...tool({
831
+ description: "Send a plain-text or protocol message to another agent",
832
+ inputSchema: z.object({
833
+ to: z.string(),
834
+ summary: z.string().max(200).optional(),
835
+ message: z.union([z.string(), structuredTeamMessageSchema])
836
+ })
837
+ }),
838
+ toolUseKind: "edit"
839
+ },
840
+ SendUserFile: {
841
+ ...tool({
842
+ description: "Send one or more files to the user",
843
+ inputSchema: z.object({
844
+ files: z.union([z.string(), z.array(z.string()).min(1)]),
845
+ caption: z.string().optional(),
846
+ status: z.enum(["normal", "proactive"]),
847
+ display: z.enum(["render", "attach"]).optional()
848
+ })
849
+ }),
850
+ toolUseKind: "readonly"
851
+ },
852
+ ShareOnboardingGuide: {
853
+ ...tool({
854
+ description: "Create, update, inspect, or delete an onboarding guide",
855
+ inputSchema: z.object({
856
+ mode: z.enum([
857
+ "check",
858
+ "update",
859
+ "create",
860
+ "delete"
861
+ ]).optional(),
862
+ short_code: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/).optional()
863
+ })
864
+ }),
865
+ toolUseKind: "edit"
866
+ },
867
+ WaitForMcpServers: {
868
+ ...tool({
869
+ description: "Wait for MCP servers that are still connecting",
870
+ inputSchema: z.object({ servers: z.array(z.string()).optional() })
871
+ }),
872
+ toolUseKind: "readonly"
873
+ },
874
+ Workflow: {
875
+ ...tool({
876
+ description: "Run or resume a dynamic multi-agent workflow",
877
+ inputSchema: z.object({
878
+ script: z.string().optional(),
879
+ name: z.string().optional(),
880
+ description: z.string().optional(),
881
+ title: z.string().optional(),
882
+ args: z.record(z.string(), z.unknown()).optional(),
883
+ scriptPath: z.string().optional(),
884
+ resumeFromRunId: z.string().optional()
885
+ })
886
+ }),
887
+ toolUseKind: "edit"
888
+ }
889
+ };
890
+ var claudeCodeBridgeCoordsSchema = z.object({
891
+ port: z.number(),
892
+ token: z.string(),
893
+ lastSeenEventId: z.number(),
894
+ sandboxId: z.string().optional()
895
+ });
896
+ var claudeCodeResumeStateSchema = z.looseObject({
897
+ bridge: claudeCodeBridgeCoordsSchema.optional(),
898
+ sandboxCredentialEnvironment: z.record(z.string(), z.string()).optional(),
899
+ /**
900
+ * The exact Claude conversation to rehydrate on resume. Written by the
901
+ * adapter on `doStop()`/`doDetach()`/`doSuspendTurn()` from the session id
902
+ * the bridge observed, so a resume names the conversation instead of
903
+ * relying on the SDK's `continue` flag — "most recent thread in this
904
+ * workdir" — which silently picks the wrong one once a second thread
905
+ * exists there. Hosts that captured the id themselves (it is surfaced as
906
+ * `harnessMetadata['claude-code'].sessionId` on `finish` parts) may also
907
+ * set it explicitly.
908
+ */
909
+ claudeSessionId: z.string().optional()
910
+ });
911
+ function createClaudeCode(settings = {}) {
912
+ if (settings.mcpServers != null && Object.prototype.hasOwnProperty.call(settings.mcpServers, "harness-tools")) throw new Error("Claude Code MCP server name \"harness-tools\" is reserved for HarnessAgent tools.");
913
+ const thinking = settings.thinking ?? {
914
+ type: "adaptive",
915
+ display: "summarized"
916
+ };
917
+ return {
918
+ specificationVersion: "harness-v1",
919
+ harnessId: "claude-code",
920
+ builtinTools: CLAUDE_CODE_BUILTIN_TOOLS,
921
+ supportsBuiltinToolApprovals: true,
922
+ supportsBuiltinToolFiltering: true,
923
+ lifecycleStateSchema: claudeCodeResumeStateSchema,
924
+ getBootstrap: getClaudeCodeBootstrap,
925
+ doStart: async (startOpts) => {
926
+ const sandboxSession = startOpts.sandboxSession;
927
+ const toolSafeSandboxSession = getRestrictedSandboxSession(sandboxSession);
928
+ const sandboxId = "id" in sandboxSession ? sandboxSession.id : void 0;
929
+ validateBasicSandboxSettings({
930
+ sandboxSession,
931
+ port: settings.port,
932
+ portEndpoint: settings.portEndpoint
933
+ });
934
+ if (settings.mintBridgeToken != null && sandboxId == null) throw new HarnessCapabilityUnsupportedError({
935
+ harnessId: "claude-code",
936
+ message: "The Claude Code harness cannot use `mintBridgeToken` with a sandbox session that does not expose an id."
937
+ });
938
+ const lifecycleState = startOpts.continueFrom ?? startOpts.resumeFrom;
939
+ const isResume = lifecycleState != null;
940
+ const isContinue = startOpts.continueFrom != null;
941
+ const resumeData = isResume ? lifecycleState?.data : void 0;
942
+ const coords = resumeData?.bridge;
943
+ const authenticationMode = resolveClaudeCodeAuthenticationMode(settings.auth);
944
+ const resolvedAuthEnvironment = await resolveClaudeCodeAuthentication({ auth: settings.auth });
945
+ const claudeEnvironment = {
946
+ ...resolvedAuthEnvironment,
947
+ ...resolvedAuthEnvironment.AI_GATEWAY_BASE_URL ? { CLAUDE_AGENT_SDK_CLIENT_APP: CLAUDE_CODE_CLIENT_APP } : {},
948
+ ...settings.env,
949
+ ...startOpts.headers != null ? { ANTHROPIC_CUSTOM_HEADERS: Object.entries(startOpts.headers).map(([name, value]) => `${name}: ${value}`).join("\n") } : {}
950
+ };
951
+ let sandboxClaudeEnvironment = claudeEnvironment;
952
+ let sandboxCredentialEnvironment;
953
+ if ("addRequestTransformations" in sandboxSession && sandboxSession.addRequestTransformations != null) {
954
+ sandboxCredentialEnvironment = resumeData?.sandboxCredentialEnvironment ?? await createSandboxCredentialEnvironment({
955
+ environment: claudeEnvironment,
956
+ credentialEnvironmentVariables: CLAUDE_CODE_CREDENTIAL_ENVIRONMENT_VARIABLES,
957
+ credentialForwarding: settings.credentialForwarding
958
+ });
959
+ sandboxClaudeEnvironment = {
960
+ ...claudeEnvironment,
961
+ ...sandboxCredentialEnvironment
962
+ };
963
+ const transformationSources = {
964
+ env: claudeEnvironment,
965
+ sandboxEnv: sandboxClaudeEnvironment,
966
+ auth: authenticationMode
967
+ };
968
+ const requestTransformations = [...createClaudeCodeRequestTransformations(transformationSources), ...createClaudeCodeSubscriptionRequestTransformations(transformationSources)];
969
+ if (requestTransformations.length > 0) await sandboxSession.addRequestTransformations(requestTransformations);
970
+ } else {
971
+ sandboxClaudeEnvironment = await applyCredentialForwarding({
972
+ environment: sandboxClaudeEnvironment,
973
+ credentialEnvironmentVariables: CLAUDE_CODE_CREDENTIAL_ENVIRONMENT_VARIABLES,
974
+ credentialForwarding: settings.credentialForwarding
975
+ });
976
+ warnCredentialBrokeringUnavailable({
977
+ environment: claudeEnvironment,
978
+ forwardedEnvironment: sandboxClaudeEnvironment,
979
+ credentialEnvironmentVariables: CLAUDE_CODE_CREDENTIAL_ENVIRONMENT_VARIABLES
980
+ });
981
+ }
982
+ const sandboxHomeDir = await resolveSandboxHomeDir({
983
+ sandbox: toolSafeSandboxSession,
984
+ abortSignal: startOpts.abortSignal
985
+ });
986
+ const stateDir = harnessStateDirectoryPath({ sandboxHomeDir });
987
+ const bootstrapDir = posix.resolve(stateDir, CLAUDE_CODE_BOOTSTRAP_DIR);
988
+ const resumeSessionId = resumeData?.claudeSessionId;
989
+ const workDir = startOpts.sessionWorkDir;
990
+ const bridgeStateDir = `${harnessSessionDataDirectoryPath({
991
+ stateDirectory: stateDir,
992
+ sessionId: startOpts.sessionId
993
+ })}/bridge`;
994
+ const timeoutMs = settings.startupTimeoutMs ?? 12e4;
995
+ const report = startOpts.observability?.report;
996
+ const onDiagnostic = report ? (frame) => report(harnessV1DiagnosticFromBridgeFrame(frame, {
997
+ sessionId: startOpts.sessionId,
998
+ timestamp: Date.now()
999
+ })) : void 0;
1000
+ const onBridgeError = createBridgeErrorHandler({
1001
+ harnessId: "claude-code",
1002
+ sessionId: startOpts.sessionId
1003
+ });
1004
+ let supportsUserMessageResponses = false;
1005
+ const buildConnect = (endpoint2) => async ({ abortSignal }) => {
1006
+ return openBridgeWebSocket({
1007
+ endpoint: endpoint2,
1008
+ timeoutMs,
1009
+ abortSignal,
1010
+ onHello: (supportsResponses) => {
1011
+ supportsUserMessageResponses = supportsResponses;
1012
+ }
1013
+ });
1014
+ };
1015
+ if (coords) try {
1016
+ const endpoint2 = await resolveBridgeEndpoint({
1017
+ sandboxSession,
1018
+ override: settings.portEndpoint,
1019
+ port: coords.port
1020
+ });
1021
+ const attachEndpoint = withBridgeToken({
1022
+ endpoint: endpoint2,
1023
+ token: coords.token
1024
+ });
1025
+ const attachChannel = new SandboxChannel({
1026
+ connect: buildConnect(attachEndpoint),
1027
+ outboundSchema: outboundMessageSchema,
1028
+ initialLastSeenEventId: coords.lastSeenEventId,
1029
+ onDiagnostic,
1030
+ onBridgeError,
1031
+ reconnect: settings.reconnect
1032
+ });
1033
+ const finishListenerAttachment2 = isContinue ? attachChannel.beginListenerAttachment() : void 0;
1034
+ try {
1035
+ await attachChannel.open(isContinue ? { resume: true } : void 0);
1036
+ } catch (error) {
1037
+ finishListenerAttachment2?.();
1038
+ throw error;
1039
+ }
1040
+ return createSession({
1041
+ sessionId: startOpts.sessionId,
1042
+ channel: attachChannel,
1043
+ finishListenerAttachment: finishListenerAttachment2,
1044
+ ...resumeSessionId ? { resumeSessionId } : {},
1045
+ proc: void 0,
1046
+ maxTurns: settings.maxTurns,
1047
+ env: sandboxClaudeEnvironment,
1048
+ thinking,
1049
+ effort: settings.effort,
1050
+ isResume: true,
1051
+ continueOnFirstPrompt: false,
1052
+ rerunContinue: false,
1053
+ bridgePort: coords.port,
1054
+ bridgeToken: coords.token,
1055
+ sandboxId,
1056
+ sandboxCredentialEnvironment,
1057
+ debug: startOpts.observability?.debug,
1058
+ permissionMode: startOpts.permissionMode,
1059
+ builtinToolFiltering: startOpts.builtinToolFiltering,
1060
+ sandbox: toolSafeSandboxSession,
1061
+ sandboxHomeDir,
1062
+ mcpServers: settings.mcpServers,
1063
+ supportsUserMessageResponses: () => supportsUserMessageResponses
1064
+ });
1065
+ } catch {}
1066
+ let respawnStrategy = isResume ? "rerun" : void 0;
1067
+ if (coords && isContinue) {
1068
+ const logRaw = await Promise.resolve(toolSafeSandboxSession.readTextFile({
1069
+ path: `${bridgeStateDir}/event-log.ndjson`,
1070
+ abortSignal: startOpts.abortSignal
1071
+ })).catch(() => null);
1072
+ if (await classifyDiskLog(logRaw) === "replay") respawnStrategy = "replay";
1073
+ }
1074
+ const port = resolveBridgePort({
1075
+ sandboxSession,
1076
+ override: settings.port
1077
+ });
1078
+ const token = settings.mintBridgeToken == null ? createBridgeToken() : settings.mintBridgeToken(sandboxId);
1079
+ const env = {
1080
+ BRIDGE_CHANNEL_TOKEN: token,
1081
+ BRIDGE_WS_PORT: String(port),
1082
+ ...respawnStrategy === "replay" ? { BRIDGE_REPLAY_FROM_DISK: "1" } : {}
1083
+ };
1084
+ if (respawnStrategy === void 0) await toolSafeSandboxSession.run({
1085
+ command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,
1086
+ abortSignal: startOpts.abortSignal
1087
+ });
1088
+ await markBridgeStarting({
1089
+ sandbox: toolSafeSandboxSession,
1090
+ bridgeStateDir,
1091
+ bridgeType: "claude-code",
1092
+ abortSignal: startOpts.abortSignal
1093
+ });
1094
+ const proc = await toolSafeSandboxSession.spawn({
1095
+ command: `node ${shellQuote(`${bootstrapDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)}`,
1096
+ env,
1097
+ abortSignal: startOpts.abortSignal
1098
+ });
1099
+ const bridgeStartupStderr = [];
1100
+ const bridgeStartupStderrDone = forwardBridgeProcessStream({
1101
+ stream: proc.stderr,
1102
+ streamName: "stderr",
1103
+ source: "claude-code",
1104
+ collectTail: bridgeStartupStderr
1105
+ });
1106
+ const { port: boundPort } = await waitForBridgeReady({
1107
+ proc,
1108
+ sandbox: toolSafeSandboxSession,
1109
+ bridgeStateDir,
1110
+ bridgeType: "claude-code",
1111
+ timeoutMs,
1112
+ abortSignal: startOpts.abortSignal,
1113
+ createTimeoutError: ({ proc: proc2, stdoutTail }) => createBridgeStartupError({
1114
+ message: "claude-code bridge did not become ready in time.",
1115
+ proc: proc2,
1116
+ stdoutTail,
1117
+ stderrTail: bridgeStartupStderr,
1118
+ stderrDone: bridgeStartupStderrDone
1119
+ }),
1120
+ createExitError: ({ proc: proc2, stdoutTail }) => createBridgeStartupError({
1121
+ message: "claude-code bridge exited before becoming ready.",
1122
+ proc: proc2,
1123
+ stdoutTail,
1124
+ stderrTail: bridgeStartupStderr,
1125
+ stderrDone: bridgeStartupStderrDone
1126
+ })
1127
+ });
1128
+ drainBridgeProcessStream(proc.stdout);
1129
+ const endpoint = await resolveBridgeEndpoint({
1130
+ sandboxSession,
1131
+ override: settings.portEndpoint,
1132
+ port: boundPort
1133
+ });
1134
+ const bridgeEndpoint = withBridgeToken({
1135
+ endpoint,
1136
+ token
1137
+ });
1138
+ const channel = new SandboxChannel({
1139
+ connect: buildConnect(bridgeEndpoint),
1140
+ outboundSchema: outboundMessageSchema,
1141
+ onDiagnostic,
1142
+ onBridgeError,
1143
+ reconnect: settings.reconnect,
1144
+ ...respawnStrategy === "replay" ? { initialLastSeenEventId: coords?.lastSeenEventId ?? 0 } : {}
1145
+ });
1146
+ const finishListenerAttachment = respawnStrategy === "replay" ? channel.beginListenerAttachment() : void 0;
1147
+ try {
1148
+ await channel.open(respawnStrategy === "replay" ? { resume: true } : void 0);
1149
+ } catch (error) {
1150
+ finishListenerAttachment?.();
1151
+ throw error;
1152
+ }
1153
+ return createSession({
1154
+ sessionId: startOpts.sessionId,
1155
+ channel,
1156
+ finishListenerAttachment,
1157
+ proc,
1158
+ maxTurns: settings.maxTurns,
1159
+ env: sandboxClaudeEnvironment,
1160
+ thinking,
1161
+ effort: settings.effort,
1162
+ isResume: respawnStrategy !== void 0,
1163
+ continueOnFirstPrompt: respawnStrategy !== void 0,
1164
+ ...resumeSessionId ? { resumeSessionId } : {},
1165
+ rerunContinue: respawnStrategy === "rerun",
1166
+ bridgePort: boundPort,
1167
+ bridgeToken: token,
1168
+ sandboxId,
1169
+ sandboxCredentialEnvironment,
1170
+ debug: startOpts.observability?.debug,
1171
+ permissionMode: startOpts.permissionMode,
1172
+ builtinToolFiltering: startOpts.builtinToolFiltering,
1173
+ sandbox: toolSafeSandboxSession,
1174
+ sandboxHomeDir,
1175
+ mcpServers: settings.mcpServers,
1176
+ supportsUserMessageResponses: () => supportsUserMessageResponses
1177
+ });
1178
+ }
1179
+ };
1180
+ }
1181
+ function resolveBridgePort({ sandboxSession, override }) {
1182
+ if (override !== void 0) return override;
1183
+ if ("ports" in sandboxSession && sandboxSession.ports.length > 0) return sandboxSession.ports[0];
1184
+ throw new HarnessCapabilityUnsupportedError({
1185
+ harnessId: "claude-code",
1186
+ message: "The claude-code harness needs a TCP port exposed by the sandbox. Create the sandbox with `ports: [<port>]` or pass `createClaudeCode({ port })`."
1187
+ });
1188
+ }
1189
+ function validateBasicSandboxSettings({ sandboxSession, port, portEndpoint }) {
1190
+ if ("getPortEndpoint" in sandboxSession) return;
1191
+ if (port == null) throw new HarnessCapabilityUnsupportedError({
1192
+ harnessId: "claude-code",
1193
+ message: "The Claude Code harness requires an explicit `port` when using a basic sandbox session."
1194
+ });
1195
+ if (portEndpoint == null) throw new HarnessCapabilityUnsupportedError({
1196
+ harnessId: "claude-code",
1197
+ message: "The Claude Code harness requires an explicit `portEndpoint` when using a basic sandbox session."
1198
+ });
1199
+ }
1200
+ async function resolveBridgeEndpoint({ sandboxSession, override, port }) {
1201
+ if (override != null) return override;
1202
+ if ("getPortEndpoint" in sandboxSession) return sandboxSession.getPortEndpoint({
1203
+ port,
1204
+ protocol: "ws"
1205
+ });
1206
+ throw new HarnessCapabilityUnsupportedError({
1207
+ harnessId: "claude-code",
1208
+ message: "The Claude Code harness requires an explicit `portEndpoint` when using a basic sandbox session."
1209
+ });
1210
+ }
1211
+ function openWebSocketAndWaitForBridgeHello({ endpoint, openTimeoutMs, getHelloTimeoutMs, abortSignal, onHello }) {
1212
+ return new Promise((resolve2, reject) => {
1213
+ const abortReason = () => abortSignal.reason ?? /* @__PURE__ */ new Error("WebSocket connection aborted");
1214
+ if (abortSignal.aborted) {
1215
+ reject(abortReason());
1216
+ return;
1217
+ }
1218
+ const ws = new WebSocket(endpoint.url, { headers: endpoint.headers == null ? void 0 : { ...endpoint.headers } });
1219
+ let opened = false;
1220
+ let sawBridgeHello = false;
1221
+ let settled = false;
1222
+ let openTimer;
1223
+ let helloTimer;
1224
+ let onAbort;
1225
+ const cleanup = ({ keepTerminationListeners = false } = {}) => {
1226
+ if (openTimer) clearTimeout(openTimer);
1227
+ if (helloTimer) clearTimeout(helloTimer);
1228
+ ws.off("open", onOpen);
1229
+ ws.off("message", onMessage);
1230
+ if (onAbort != null) abortSignal.removeEventListener("abort", onAbort);
1231
+ if (!keepTerminationListeners) {
1232
+ ws.off("close", onClose);
1233
+ ws.off("error", onError);
1234
+ }
1235
+ };
1236
+ const settle = (err) => {
1237
+ if (settled) return;
1238
+ settled = true;
1239
+ if (err) {
1240
+ cleanup({ keepTerminationListeners: true });
1241
+ try {
1242
+ ws.terminate();
1243
+ } catch {
1244
+ cleanup();
1245
+ }
1246
+ reject(err);
1247
+ } else {
1248
+ cleanup();
1249
+ resolve2(ws);
1250
+ }
1251
+ };
1252
+ const tryResolve = () => {
1253
+ if (opened && sawBridgeHello) settle();
1254
+ };
1255
+ const startHelloTimer = () => {
1256
+ if (helloTimer) return;
1257
+ const helloTimeoutMs = getHelloTimeoutMs();
1258
+ helloTimer = setTimeout(() => settle(/* @__PURE__ */ new Error(`claude-code bridge did not send bridge-hello within ${helloTimeoutMs}ms`)), helloTimeoutMs);
1259
+ helloTimer.unref?.();
1260
+ };
1261
+ const onOpen = () => {
1262
+ opened = true;
1263
+ if (openTimer) {
1264
+ clearTimeout(openTimer);
1265
+ openTimer = void 0;
1266
+ }
1267
+ startHelloTimer();
1268
+ tryResolve();
1269
+ };
1270
+ const onMessage = (raw) => {
1271
+ (async () => {
1272
+ const parsed = await safeParseJSON({ text: webSocketMessageToString(raw) });
1273
+ if (!parsed.success || settled) return;
1274
+ const value = parsed.value;
1275
+ if (typeof value === "object" && value !== null && !Array.isArray(value) && value.type === "bridge-hello") {
1276
+ const capabilities = value.capabilities;
1277
+ onHello(capabilities?.experimental_userMessageResponses === true);
1278
+ sawBridgeHello = true;
1279
+ tryResolve();
1280
+ }
1281
+ })();
1282
+ };
1283
+ const onClose = () => {
1284
+ settle(/* @__PURE__ */ new Error("claude-code bridge closed before sending bridge-hello"));
1285
+ cleanup();
1286
+ };
1287
+ const onError = (err) => settle(err);
1288
+ onAbort = () => settle(abortReason());
1289
+ openTimer = setTimeout(() => settle(/* @__PURE__ */ new Error(`WebSocket open timed out after ${openTimeoutMs}ms`)), openTimeoutMs);
1290
+ openTimer.unref?.();
1291
+ ws.on("open", onOpen);
1292
+ ws.on("message", onMessage);
1293
+ ws.on("close", onClose);
1294
+ ws.on("error", onError);
1295
+ abortSignal.addEventListener("abort", onAbort, { once: true });
1296
+ });
1297
+ }
1298
+ async function openBridgeWebSocket({ endpoint, timeoutMs, abortSignal, onHello }) {
1299
+ const deadline = Date.now() + timeoutMs;
1300
+ let attempt = 0;
1301
+ let lastError;
1302
+ while (!abortSignal.aborted && Date.now() < deadline) {
1303
+ attempt++;
1304
+ try {
1305
+ const remaining = Math.max(1, deadline - Date.now());
1306
+ return await openWebSocketAndWaitForBridgeHello({
1307
+ endpoint,
1308
+ openTimeoutMs: Math.min(1e4, remaining),
1309
+ getHelloTimeoutMs: () => Math.min(5e3, Math.max(1, deadline - Date.now())),
1310
+ abortSignal,
1311
+ onHello
1312
+ });
1313
+ } catch (err) {
1314
+ if (abortSignal.aborted) throw abortSignal.reason ?? /* @__PURE__ */ new Error("WebSocket connection aborted");
1315
+ lastError = err;
1316
+ const remaining = deadline - Date.now();
1317
+ if (remaining <= 0) break;
1318
+ await sleep({
1319
+ ms: Math.min(250 * attempt, 1e3, remaining),
1320
+ abortSignal
1321
+ });
1322
+ }
1323
+ }
1324
+ if (abortSignal.aborted) throw abortSignal.reason ?? /* @__PURE__ */ new Error("WebSocket connection aborted");
1325
+ throw new Error(`claude-code bridge did not complete WebSocket handshake within ${timeoutMs}ms after ${attempt} attempt(s). Last error: ${formatUnknownError(lastError)}`);
1326
+ }
1327
+ function webSocketMessageToString(raw) {
1328
+ if (typeof raw === "string") return raw;
1329
+ if (Buffer.isBuffer(raw)) return raw.toString("utf8");
1330
+ if (Array.isArray(raw)) return Buffer.concat(raw).toString("utf8");
1331
+ if (raw instanceof ArrayBuffer) return Buffer.from(raw).toString("utf8");
1332
+ if (ArrayBuffer.isView(raw)) return Buffer.from(raw.buffer, raw.byteOffset, raw.byteLength).toString("utf8");
1333
+ return String(raw);
1334
+ }
1335
+ function formatUnknownError(error) {
1336
+ if (error instanceof Error) return error.message;
1337
+ return String(error);
1338
+ }
1339
+ function createSession({ sessionId, channel, finishListenerAttachment, proc, maxTurns, env, thinking, effort, isResume, continueOnFirstPrompt, resumeSessionId, rerunContinue, bridgePort, bridgeToken, sandboxId, sandboxCredentialEnvironment, debug, permissionMode, builtinToolFiltering, sandbox, sandboxHomeDir, mcpServers, supportsUserMessageResponses }) {
1340
+ let stopped = false;
1341
+ let stopPromise;
1342
+ let pendingResumeFlag = continueOnFirstPrompt;
1343
+ let lastClaudeSessionId = resumeSessionId;
1344
+ const wireTurn = (turnOpts) => {
1345
+ let pendingResolve;
1346
+ let pendingReject;
1347
+ const done = new Promise((resolve2, reject) => {
1348
+ pendingResolve = resolve2;
1349
+ pendingReject = reject;
1350
+ });
1351
+ const userMessageSubmitter = supportsUserMessageResponses() ? experimental_createBridgeUserMessageSubmitter({
1352
+ send: (message) => channel.send(message),
1353
+ onResponse: (listener) => channel.on("user-message-response", listener),
1354
+ onReconnect: (listener) => channel.onReconnect(listener)
1355
+ }) : void 0;
1356
+ const unsubs = [];
1357
+ const forward = (event) => {
1358
+ try {
1359
+ turnOpts.emit(event);
1360
+ } catch {}
1361
+ };
1362
+ let isSettled = false;
1363
+ const settleSuccess = () => {
1364
+ if (isSettled) return;
1365
+ isSettled = true;
1366
+ userMessageSubmitter?.close();
1367
+ for (const u of unsubs) u();
1368
+ pendingResolve();
1369
+ };
1370
+ const settleError = (err) => {
1371
+ if (isSettled) return;
1372
+ isSettled = true;
1373
+ userMessageSubmitter?.close(err);
1374
+ for (const u of unsubs) u();
1375
+ pendingReject(err);
1376
+ };
1377
+ for (const type of [
1378
+ "stream-start",
1379
+ "text-start",
1380
+ "text-delta",
1381
+ "text-end",
1382
+ "reasoning-start",
1383
+ "reasoning-delta",
1384
+ "reasoning-end",
1385
+ "tool-input-start",
1386
+ "tool-input-delta",
1387
+ "tool-input-end",
1388
+ "tool-call",
1389
+ "tool-approval-request",
1390
+ "tool-result",
1391
+ "finish-step",
1392
+ "compaction",
1393
+ "raw"
1394
+ ]) unsubs.push(channel.on(type, (msg) => {
1395
+ forward(msg);
1396
+ }));
1397
+ unsubs.push(channel.on("finish", (msg) => {
1398
+ const metadata = msg.harnessMetadata?.["claude-code"]?.sessionId;
1399
+ if (typeof metadata === "string" && metadata.length > 0) lastClaudeSessionId = metadata;
1400
+ forward(msg);
1401
+ settleSuccess();
1402
+ }));
1403
+ unsubs.push(channel.on("error", (msg) => {
1404
+ forward(msg);
1405
+ settleError(msg.error);
1406
+ }));
1407
+ finishListenerAttachment?.();
1408
+ finishListenerAttachment = void 0;
1409
+ const onClose = (_code, reason) => {
1410
+ if (isSettled) return;
1411
+ if (reason === "suspended") {
1412
+ settleSuccess();
1413
+ return;
1414
+ }
1415
+ settleError(/* @__PURE__ */ new Error("claude-code bridge closed before the turn finished."));
1416
+ };
1417
+ channel.onClose(onClose);
1418
+ const onAbort = () => {
1419
+ if (isSettled) return;
1420
+ try {
1421
+ channel.send({ type: "abort" });
1422
+ } catch {}
1423
+ settleError(turnOpts.abortSignal?.reason ?? new DOMException("Aborted", "AbortError"));
1424
+ };
1425
+ if (turnOpts.abortSignal) {
1426
+ if (turnOpts.abortSignal.aborted) onAbort();
1427
+ else turnOpts.abortSignal.addEventListener("abort", onAbort, { once: true });
1428
+ }
1429
+ return {
1430
+ submitToolResult: async (input) => {
1431
+ channel.send({
1432
+ type: "tool-result",
1433
+ toolCallId: input.toolCallId,
1434
+ output: input.output,
1435
+ isError: input.isError,
1436
+ ...input.toolResult !== void 0 ? { toolResult: input.toolResult } : {}
1437
+ });
1438
+ },
1439
+ submitToolApproval: async (input) => {
1440
+ channel.send({
1441
+ type: "tool-approval-response",
1442
+ approvalId: input.approvalId,
1443
+ approved: input.approved,
1444
+ reason: input.reason
1445
+ });
1446
+ },
1447
+ ...userMessageSubmitter == null ? {} : { submitUserMessage: async (text) => {
1448
+ await userMessageSubmitter.submit(text);
1449
+ } },
1450
+ done
1451
+ };
1452
+ };
1453
+ const prepareTurn = async (turnOpts) => {
1454
+ if (turnOpts.responseFormat?.type === "json" && turnOpts.responseFormat.schema == null) throw new HarnessCapabilityUnsupportedError({
1455
+ message: "Harness 'claude-code' requires a JSON schema for structured output.",
1456
+ harnessId: "claude-code"
1457
+ });
1458
+ await writeSkills({
1459
+ sandbox,
1460
+ homePath: sandboxHomeDir,
1461
+ skillsDir: ".claude/skills",
1462
+ skills: turnOpts.skills,
1463
+ abortSignal: turnOpts.abortSignal,
1464
+ invalidSkillNameMessage: ({ name }) => `Invalid Claude Code skill name: ${name}`,
1465
+ invalidSkillFilePathMessage: ({ skillName, filePath }) => `Invalid Claude Code skill file path for ${skillName}: ${filePath}`,
1466
+ trailingNewline: true
1467
+ });
1468
+ return wireTurn({
1469
+ emit: turnOpts.emit,
1470
+ abortSignal: turnOpts.abortSignal
1471
+ });
1472
+ };
1473
+ return {
1474
+ sessionId,
1475
+ isResume,
1476
+ doPromptTurn: async (promptOpts) => {
1477
+ const control = await prepareTurn(promptOpts);
1478
+ if (promptOpts.abortSignal?.aborted) return control;
1479
+ const startMessage = {
1480
+ type: "start",
1481
+ prompt: extractUserText(promptOpts.prompt),
1482
+ tools: (promptOpts.tools ?? []).map((t) => ({
1483
+ name: t.name,
1484
+ description: t.description,
1485
+ inputSchema: t.inputSchema
1486
+ })),
1487
+ ...promptOpts.responseFormat == null ? {} : { responseFormat: promptOpts.responseFormat },
1488
+ ...promptOpts.instructions ? { instructions: promptOpts.instructions } : {},
1489
+ model: promptOpts.model,
1490
+ maxTurns,
1491
+ ...env !== void 0 ? { env } : {},
1492
+ thinking,
1493
+ ...effort !== void 0 ? { effort } : {},
1494
+ ...promptOpts.skills.length > 0 ? { skills: promptOpts.skills.map((skill) => skill.name) } : {},
1495
+ ...mcpServers == null ? {} : { mcpServers },
1496
+ ...permissionMode ? { permissionMode } : {},
1497
+ ...builtinToolFiltering ? { builtinToolFiltering } : {},
1498
+ ...debug ? { debug } : {},
1499
+ ...lastClaudeSessionId ? { resumeSessionId: lastClaudeSessionId } : pendingResumeFlag ? { continue: true } : {}
1500
+ };
1501
+ pendingResumeFlag = false;
1502
+ channel.send(startMessage);
1503
+ return control;
1504
+ },
1505
+ doContinueTurn: async (continueOpts) => {
1506
+ const control = await prepareTurn(continueOpts);
1507
+ if (rerunContinue && !continueOpts.abortSignal?.aborted) {
1508
+ pendingResumeFlag = false;
1509
+ channel.send({
1510
+ type: "start",
1511
+ prompt: "Continue.",
1512
+ tools: (continueOpts.tools ?? []).map((t) => ({
1513
+ name: t.name,
1514
+ description: t.description,
1515
+ inputSchema: t.inputSchema
1516
+ })),
1517
+ ...continueOpts.responseFormat == null ? {} : { responseFormat: continueOpts.responseFormat },
1518
+ ...continueOpts.instructions ? { instructions: continueOpts.instructions } : {},
1519
+ model: continueOpts.model,
1520
+ maxTurns,
1521
+ ...env !== void 0 ? { env } : {},
1522
+ thinking,
1523
+ ...effort !== void 0 ? { effort } : {},
1524
+ ...continueOpts.skills.length > 0 ? { skills: continueOpts.skills.map((skill) => skill.name) } : {},
1525
+ ...mcpServers == null ? {} : { mcpServers },
1526
+ ...permissionMode ? { permissionMode } : {},
1527
+ ...builtinToolFiltering ? { builtinToolFiltering } : {},
1528
+ ...debug ? { debug } : {},
1529
+ ...lastClaudeSessionId ? { resumeSessionId: lastClaudeSessionId } : { continue: true }
1530
+ });
1531
+ }
1532
+ return control;
1533
+ },
1534
+ doCompact: async (customInstructions) => {
1535
+ const text = customInstructions && customInstructions.trim() ? `/compact ${customInstructions.trim()}` : "/compact";
1536
+ channel.send({
1537
+ type: "user-message",
1538
+ text
1539
+ });
1540
+ },
1541
+ doDetach: async () => {
1542
+ if (stopped) throw new Error(`claude-code session ${sessionId} is already stopped; cannot detach.`);
1543
+ stopped = true;
1544
+ const lastSeenEventId = await channel.suspend();
1545
+ return {
1546
+ type: "resume-session",
1547
+ harnessId: "claude-code",
1548
+ specificationVersion: "harness-v1",
1549
+ data: {
1550
+ ...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment },
1551
+ bridge: {
1552
+ port: bridgePort,
1553
+ token: bridgeToken,
1554
+ lastSeenEventId,
1555
+ ...sandboxId == null ? {} : { sandboxId }
1556
+ },
1557
+ ...lastClaudeSessionId ? { claudeSessionId: lastClaudeSessionId } : {}
1558
+ }
1559
+ };
1560
+ },
1561
+ doDestroy: async () => {
1562
+ if (stopped) return stopPromise;
1563
+ stopped = true;
1564
+ stopPromise = (async () => {
1565
+ channel.beginClose();
1566
+ try {
1567
+ if (!channel.isClosed()) channel.send({ type: "destroy" });
1568
+ } catch {}
1569
+ let stopTimer;
1570
+ try {
1571
+ if (proc) await Promise.race([proc.wait(), new Promise((resolve2) => {
1572
+ stopTimer = setTimeout(resolve2, 5e3);
1573
+ stopTimer.unref?.();
1574
+ })]);
1575
+ } finally {
1576
+ if (stopTimer) clearTimeout(stopTimer);
1577
+ try {
1578
+ await proc?.kill();
1579
+ } catch {}
1580
+ channel.close();
1581
+ }
1582
+ })();
1583
+ return stopPromise;
1584
+ },
1585
+ doStop: async () => {
1586
+ if (stopped) throw new Error(`claude-code session ${sessionId} is already stopped; cannot stop.`);
1587
+ stopped = true;
1588
+ channel.beginClose();
1589
+ const data = channel.isClosed() ? {} : await new Promise((resolve2, reject) => {
1590
+ const timer = setTimeout(() => {
1591
+ unsub();
1592
+ reject(/* @__PURE__ */ new Error(`claude-code session ${sessionId} did not reply to stop within 5s.`));
1593
+ }, 5e3);
1594
+ timer.unref?.();
1595
+ const unsub = channel.on("bridge-stop", (msg) => {
1596
+ clearTimeout(timer);
1597
+ unsub();
1598
+ resolve2(msg.data);
1599
+ });
1600
+ try {
1601
+ channel.send({ type: "stop" });
1602
+ } catch (err) {
1603
+ clearTimeout(timer);
1604
+ unsub();
1605
+ reject(err);
1606
+ }
1607
+ });
1608
+ let stopTimer;
1609
+ try {
1610
+ if (proc) await Promise.race([proc.wait(), new Promise((resolve2) => {
1611
+ stopTimer = setTimeout(resolve2, 5e3);
1612
+ stopTimer.unref?.();
1613
+ })]);
1614
+ } finally {
1615
+ if (stopTimer) clearTimeout(stopTimer);
1616
+ try {
1617
+ await proc?.kill();
1618
+ } catch {}
1619
+ channel.close();
1620
+ }
1621
+ const lifecycleData = data != null && typeof data === "object" && !Array.isArray(data) ? { ...data } : {};
1622
+ return {
1623
+ type: "resume-session",
1624
+ harnessId: "claude-code",
1625
+ specificationVersion: "harness-v1",
1626
+ data: {
1627
+ ...lastClaudeSessionId ? { claudeSessionId: lastClaudeSessionId } : {},
1628
+ ...lifecycleData,
1629
+ ...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment }
1630
+ }
1631
+ };
1632
+ },
1633
+ doSuspendTurn: async () => {
1634
+ if (stopped) throw new Error(`claude-code session ${sessionId} is stopped; cannot suspend.`);
1635
+ stopped = true;
1636
+ const lastSeenEventId = await channel.suspend();
1637
+ return {
1638
+ type: "continue-turn",
1639
+ harnessId: "claude-code",
1640
+ specificationVersion: "harness-v1",
1641
+ data: {
1642
+ ...sandboxCredentialEnvironment == null ? {} : { sandboxCredentialEnvironment },
1643
+ bridge: {
1644
+ port: bridgePort,
1645
+ token: bridgeToken,
1646
+ lastSeenEventId,
1647
+ ...sandboxId == null ? {} : { sandboxId }
1648
+ },
1649
+ ...lastClaudeSessionId ? { claudeSessionId: lastClaudeSessionId } : {}
1650
+ }
1651
+ };
1652
+ }
1653
+ };
1654
+ }
1655
+ function extractUserText(prompt) {
1656
+ if (typeof prompt === "string") return prompt;
1657
+ const { content } = prompt;
1658
+ if (typeof content === "string") return content;
1659
+ const parts = [];
1660
+ for (const part of content) {
1661
+ if (part.type !== "text") throw new HarnessCapabilityUnsupportedError({
1662
+ harnessId: "claude-code",
1663
+ 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.`
1664
+ });
1665
+ parts.push(part.text);
1666
+ }
1667
+ return parts.join("\n\n");
1668
+ }
1669
+ createClaudeCode();
1670
+ //#endregion
1671
+ export { createClaudeCode };
1672
+
1673
+ //# sourceMappingURL=dist-BZXYHN2X.js.map