@ai-sdk/harness-claude-code 1.0.65 → 1.0.67

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,24 @@
1
1
  # @ai-sdk/harness-claude-code
2
2
 
3
+ ## 1.0.67
4
+
5
+ ### Patch Changes
6
+
7
+ - a03ff6c: feat(harness): add support for per-harness MCP servers
8
+ - fc3baaf: feat(harness): add optional `mintBridgeToken(sandboxId)` to harness settings to control the bridge token value
9
+ - cfc587b: fix(harness-claude-code): add missing Claude Code built-in tools
10
+ - Updated dependencies [401a4ba]
11
+ - Updated dependencies [a03ff6c]
12
+ - @ai-sdk/provider-utils@5.0.26
13
+ - @ai-sdk/harness@1.0.65
14
+
15
+ ## 1.0.66
16
+
17
+ ### Patch Changes
18
+
19
+ - 8c95b3f: fix(harness-claude-code): fix built-in tool filtering by using actual denylist when passing `inactiveTools`
20
+ - a65bbb2: feat(harness-claude-code): add optional `env` property to `createClaudeCode()` for custom env vars
21
+
3
22
  ## 1.0.65
4
23
 
5
24
  ### Patch Changes
package/README.md CHANGED
@@ -62,3 +62,16 @@ try {
62
62
  ```
63
63
 
64
64
  The adapter requires a `HarnessV1SandboxProvider` whose handles expose at least one port — `@ai-sdk/sandbox-vercel` is the supported choice today. The agent calls `provider.createSession()` when a session starts. Use `session.detach()` to park the bridge and sandbox, `session.stop()` to save state and stop the sandbox, or `session.destroy()` to clean up without keeping resume state.
65
+
66
+ ## Runtime configuration
67
+
68
+ Use `env` to add environment variables to the Claude Code process. Configured
69
+ values override variables inherited from the sandbox bridge process.
70
+
71
+ ```ts
72
+ const harness = createClaudeCode({
73
+ env: {
74
+ DEPLOYMENT_ENV: 'staging',
75
+ },
76
+ });
77
+ ```
@@ -491,7 +491,7 @@ function createCompactionLatch(emit) {
491
491
 
492
492
  // src/bridge/index.ts
493
493
  import { randomUUID as randomUUID2 } from "crypto";
494
- import { argv, stdout as stdout2 } from "process";
494
+ import { argv, env as procEnv2, stdout as stdout2 } from "process";
495
495
  import * as claudeAgentSdk from "@anthropic-ai/claude-agent-sdk";
496
496
  import * as mcpServerModule from "@modelcontextprotocol/sdk/server/mcp.js";
497
497
 
@@ -512,6 +512,7 @@ function createClaudeStreamEventState() {
512
512
  pendingStepUsage: void 0,
513
513
  stepOpen: false,
514
514
  mcpToolUseIds: /* @__PURE__ */ new Set(),
515
+ externalMcpToolUseIds: /* @__PURE__ */ new Set(),
515
516
  observedTerminalError: void 0
516
517
  };
517
518
  }
@@ -586,6 +587,8 @@ function createEmitStreamEvent({
586
587
  continue;
587
588
  }
588
589
  state.nativeToolCallNames.set(block.id, block.name);
590
+ const dynamic = block.name.startsWith("mcp__");
591
+ if (dynamic) state.externalMcpToolUseIds.add(block.id);
589
592
  if (state.approvalRequestedToolUseIds.has(block.id)) {
590
593
  continue;
591
594
  }
@@ -597,7 +600,8 @@ function createEmitStreamEvent({
597
600
  toolName: toCommonName2(block.name),
598
601
  nativeName: block.name,
599
602
  input: JSON.stringify(block.input ?? {}),
600
- providerExecuted: true
603
+ providerExecuted: true,
604
+ ...dynamic ? { dynamic: true } : {}
601
605
  });
602
606
  }
603
607
  }
@@ -619,15 +623,17 @@ function createEmitStreamEvent({
619
623
  const nativeName = state.nativeToolCallNames.get(block.tool_use_id) ?? "unknown";
620
624
  state.nativeToolCallNames.delete(block.tool_use_id);
621
625
  const toolName = toCommonName2(nativeName);
626
+ const dynamic = state.externalMcpToolUseIds.delete(block.tool_use_id);
622
627
  const isError = !!block.is_error;
623
628
  const content = stringifyContent(block.content);
624
- const result = toolName === "bash" ? { exitCode: isError ? 1 : 0, stdout: content } : content;
629
+ const result = toolName === "bash" ? { exitCode: isError ? 1 : 0, stdout: content } : dynamic ? parseMcpToolResult(content) : content;
625
630
  emit({
626
631
  type: "tool-result",
627
632
  toolCallId: block.tool_use_id,
628
633
  toolName,
629
634
  result,
630
- isError
635
+ isError,
636
+ ...dynamic ? { dynamic: true } : {}
631
637
  });
632
638
  state.pendingStepToolUseIds.delete(block.tool_use_id);
633
639
  }
@@ -734,6 +740,13 @@ function stringifyContent(content) {
734
740
  }
735
741
  return JSON.stringify(content);
736
742
  }
743
+ function parseMcpToolResult(content) {
744
+ try {
745
+ return JSON.parse(content);
746
+ } catch {
747
+ return content;
748
+ }
749
+ }
737
750
  function mapUsage(usage) {
738
751
  if (!usage || typeof usage !== "object") return void 0;
739
752
  const u = usage;
@@ -848,16 +861,7 @@ function isJsonLiteral(value) {
848
861
  return value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value);
849
862
  }
850
863
 
851
- // src/bridge/index.ts
852
- var NATIVE_TO_COMMON = {
853
- Read: "read",
854
- Write: "write",
855
- Edit: "edit",
856
- Bash: "bash",
857
- Glob: "glob",
858
- Grep: "grep",
859
- WebSearch: "webSearch"
860
- };
864
+ // src/bridge/tool-filtering.ts
861
865
  var PUBLIC_TO_NATIVE = {
862
866
  read: "Read",
863
867
  write: "Write",
@@ -887,6 +891,31 @@ var PUBLIC_TO_NATIVE = {
887
891
  ToolSearch: "ToolSearch"
888
892
  };
889
893
  var PUBLIC_TOOL_NAMES = Object.keys(PUBLIC_TO_NATIVE);
894
+ function toNativeName(toolName) {
895
+ return PUBLIC_TO_NATIVE[toolName] ?? toolName;
896
+ }
897
+ function resolveNativeTools(toolFiltering) {
898
+ if (toolFiltering == null || toolFiltering.mode === "deny") return void 0;
899
+ return toolFiltering.toolNames.map((name) => toNativeName(name));
900
+ }
901
+ function resolveInactiveNativeTools(toolFiltering) {
902
+ if (toolFiltering == null) return [];
903
+ const inactiveToolNames = toolFiltering.mode === "allow" ? PUBLIC_TOOL_NAMES.filter(
904
+ (name) => !toolFiltering.toolNames.includes(name)
905
+ ) : toolFiltering.toolNames;
906
+ return inactiveToolNames.map((name) => toNativeName(name));
907
+ }
908
+
909
+ // src/bridge/index.ts
910
+ var NATIVE_TO_COMMON = {
911
+ Read: "read",
912
+ Write: "write",
913
+ Edit: "edit",
914
+ Bash: "bash",
915
+ Glob: "glob",
916
+ Grep: "grep",
917
+ WebSearch: "webSearch"
918
+ };
890
919
  var NATIVE_TOOL_KINDS = {
891
920
  Read: "readonly",
892
921
  Glob: "readonly",
@@ -917,25 +946,6 @@ var NATIVE_TOOL_KINDS = {
917
946
  function toCommonName(nativeName) {
918
947
  return NATIVE_TO_COMMON[nativeName] ?? nativeName;
919
948
  }
920
- function toNativeName(toolName) {
921
- return PUBLIC_TO_NATIVE[toolName] ?? toolName;
922
- }
923
- function resolveNativeTools(start) {
924
- const toolFiltering = start.builtinToolFiltering;
925
- if (toolFiltering == null) return void 0;
926
- const activeToolNames = toolFiltering.mode === "allow" ? toolFiltering.toolNames : PUBLIC_TOOL_NAMES.filter(
927
- (name) => !toolFiltering.toolNames.includes(name)
928
- );
929
- return activeToolNames.map((name) => toNativeName(name));
930
- }
931
- function resolveInactiveNativeTools(start) {
932
- const toolFiltering = start.builtinToolFiltering;
933
- if (toolFiltering == null) return [];
934
- const inactiveToolNames = toolFiltering.mode === "allow" ? PUBLIC_TOOL_NAMES.filter(
935
- (name) => !toolFiltering.toolNames.includes(name)
936
- ) : toolFiltering.toolNames;
937
- return inactiveToolNames.map((name) => toNativeName(name));
938
- }
939
949
  var args = parseArgs(argv.slice(2));
940
950
  var workdir = args.workdir;
941
951
  var bridgeStateDir = args.bridgeStateDir;
@@ -1038,7 +1048,7 @@ async function runTurn(start, turn) {
1038
1048
  });
1039
1049
  }
1040
1050
  const streamEventState = createClaudeStreamEventState();
1041
- const mcpServers = {};
1051
+ const mcpServers = { ...start.mcpServers ?? {} };
1042
1052
  if (start.tools && start.tools.length > 0) {
1043
1053
  const server = new mcpModule.McpServer({
1044
1054
  name: "harness-tools",
@@ -1087,8 +1097,10 @@ async function runTurn(start, turn) {
1087
1097
  abortSignal: abortCtl.signal
1088
1098
  });
1089
1099
  const skillsOption = toClaudeSkillsOption(start.skills);
1090
- const nativeTools = resolveNativeTools(start);
1091
- const inactiveNativeTools = resolveInactiveNativeTools(start);
1100
+ const nativeTools = resolveNativeTools(start.builtinToolFiltering);
1101
+ const inactiveNativeTools = resolveInactiveNativeTools(
1102
+ start.builtinToolFiltering
1103
+ );
1092
1104
  const permissionOptions = createPermissionOptions({
1093
1105
  start,
1094
1106
  inactiveNativeTools,
@@ -1105,6 +1117,7 @@ async function runTurn(start, turn) {
1105
1117
  options: {
1106
1118
  ...start.model ? { model: start.model } : {},
1107
1119
  ...start.maxTurns !== void 0 ? { maxTurns: start.maxTurns } : {},
1120
+ ...start.env !== void 0 ? { env: { ...procEnv2, ...start.env } } : {},
1108
1121
  ...skillsOption ? { skills: skillsOption } : {},
1109
1122
  ...nativeTools !== void 0 ? { tools: nativeTools } : {},
1110
1123
  ...inactiveNativeTools.length > 0 ? { disallowedTools: inactiveNativeTools } : {},