@ai-sdk/harness 1.0.117 → 1.0.119

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,27 @@
1
1
  # @ai-sdk/harness
2
2
 
3
+ ## 1.0.119
4
+
5
+ ### Patch Changes
6
+
7
+ - 125f493: fix(harness): forward validated `toolsContext` to host-executed tools in alignment with `ToolLoopAgent`
8
+ - Updated dependencies [0343bb1]
9
+ - Updated dependencies [2b105fa]
10
+ - Updated dependencies [125f493]
11
+ - ai@7.0.109
12
+
13
+ ## 1.0.118
14
+
15
+ ### Patch Changes
16
+
17
+ - d975097: feat(harness): add `AbortSignal` to `SandboxChannel.connect`, plus a `sleep()` helper function
18
+ - b2baeba: fix(harness): preserve work directory text inside longer path segments
19
+ - Updated dependencies [3f6852a]
20
+ - Updated dependencies [6317504]
21
+ - Updated dependencies [3cb2dcd]
22
+ - Updated dependencies [ccf98e7]
23
+ - ai@7.0.108
24
+
3
25
  ## 1.0.117
4
26
 
5
27
  ### Patch Changes
@@ -1,5 +1,6 @@
1
1
  import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
2
- import { Experimental_SandboxSession, UserModelMessage, ToolResultPart, ProviderOptions, ToolSet, FlexibleSchema, Tool, Context, SystemModelMessage, MaybePromiseLike, Arrayable, ToolApprovalResponse, ModelMessage } from '@ai-sdk/provider-utils';
2
+ import { Experimental_SandboxSession, UserModelMessage, ToolResultPart, ProviderOptions, ToolSet, FlexibleSchema, Tool, Context, InferToolSetContext, SystemModelMessage, MaybePromiseLike, Arrayable, ToolApprovalResponse, ModelMessage } from '@ai-sdk/provider-utils';
3
+ import { ToolsContextSettings } from 'ai/internal';
3
4
  import { OutputInterface, AgentCallParameters, Prompt, StopCondition, GenerateTextOnStartCallback, GenerateTextOnStepStartCallback, OnLanguageModelCallStartCallback, OnLanguageModelCallEndCallback, OnToolExecutionStartCallback, OnToolExecutionEndCallback, GenerateTextOnStepEndCallback, GenerateTextOnEndCallback, ToolApprovalStatus, TelemetryOptions, ActiveTools, StreamTextResult, Agent, GenerateTextResult, AgentStreamParameters, Telemetry } from 'ai';
4
5
  import { z } from 'zod/v4';
5
6
  import { JSONSchema7, JSONValue, LanguageModelV4StreamPart, LanguageModelV4ToolCall, LanguageModelV4ToolApprovalRequest, LanguageModelV4ToolResult, LanguageModelV4FinishReason, LanguageModelV4Usage, AISDKError } from '@ai-sdk/provider';
@@ -1344,6 +1345,12 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
1344
1345
  * declare a tool with the same name as a builtin to override.
1345
1346
  */
1346
1347
  readonly tools?: TUserTools;
1348
+ /**
1349
+ * Per-tool context passed to host-executed tools. Each entry is validated
1350
+ * against the matching tool's `contextSchema` before execution.
1351
+ * `prepareCall` can replace it for each new turn.
1352
+ */
1353
+ readonly toolsContext?: InferToolSetContext<TUserTools>;
1347
1354
  /**
1348
1355
  * Skills made available to the underlying runtime. Each adapter decides how
1349
1356
  * to surface skills. `prepareCall` can replace them between completed turns.
@@ -1383,7 +1390,11 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
1383
1390
  * })
1384
1391
  * ```
1385
1392
  */
1386
- readonly prepareCall?: (options: Omit<AgentCallParameters<CALL_OPTIONS, HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT>, 'abortSignal' | 'timeout' | 'onStart' | 'experimental_onStart' | 'onStepStart' | 'experimental_onStepStart' | 'onToolExecutionStart' | 'experimental_onToolCallStart' | 'onToolExecutionEnd' | 'experimental_onToolCallFinish' | 'onStepEnd' | 'onStepFinish' | 'onEnd' | 'onFinish' | 'experimental_sandbox'> & Pick<HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, NoInfer<OUTPUT>, CALL_OPTIONS>, 'model' | 'skills' | 'instructions' | 'tools'>) => MaybePromiseLike<Pick<HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, NoInfer<OUTPUT>, CALL_OPTIONS>, 'model' | 'skills' | 'instructions' | 'tools'> & Omit<Prompt, 'system' | 'instructions' | 'allowSystemInMessages'>>;
1393
+ readonly prepareCall?: (options: Omit<AgentCallParameters<CALL_OPTIONS, HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT>, 'abortSignal' | 'timeout' | 'onStart' | 'experimental_onStart' | 'onStepStart' | 'experimental_onStepStart' | 'onToolExecutionStart' | 'experimental_onToolCallStart' | 'onToolExecutionEnd' | 'experimental_onToolCallFinish' | 'onStepEnd' | 'onStepFinish' | 'onEnd' | 'onFinish' | 'experimental_sandbox'> & Pick<HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, NoInfer<OUTPUT>, CALL_OPTIONS>, 'model' | 'skills' | 'instructions' | 'tools'> & {
1394
+ toolsContext: InferToolSetContext<TUserTools>;
1395
+ }) => MaybePromiseLike<Pick<HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT, NoInfer<OUTPUT>, CALL_OPTIONS>, 'model' | 'skills' | 'instructions' | 'tools'> & {
1396
+ toolsContext: InferToolSetContext<TUserTools>;
1397
+ } & Omit<Prompt, 'system' | 'instructions' | 'allowSystemInMessages'>>;
1387
1398
  /**
1388
1399
  * Optional specification for generating typed output. The same output
1389
1400
  * requirement is active for every turn run by this agent.
@@ -1478,7 +1489,7 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
1478
1489
  * stderr default — wire this to capture diagnostics in code.
1479
1490
  */
1480
1491
  readonly onLog?: (event: HarnessDiagnostic) => void;
1481
- } & HarnessAgentToolFilteringSettings<HarnessAllTools<THarness, TUserTools>>;
1492
+ } & ToolsContextSettings<TUserTools> & HarnessAgentToolFilteringSettings<HarnessAllTools<THarness, TUserTools>>;
1482
1493
 
1483
1494
  type HarnessAgentLifecycleCallbacks<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Context, OUTPUT extends OutputInterface> = {
1484
1495
  onStart?: GenerateTextOnStartCallback<TOOLS, RUNTIME_CONTEXT, OUTPUT>;
@@ -1533,6 +1544,7 @@ declare class HarnessAgentSession {
1533
1544
  private suspendedTurnState;
1534
1545
  private activeTurnSettings;
1535
1546
  private persistedTurnSettings;
1547
+ private readonly resumedToolsContext;
1536
1548
  /**
1537
1549
  * Whether this session was created from `resumeFrom` or `continueFrom`.
1538
1550
  * Captured at construction so it survives lifecycle cleanup.
@@ -1549,6 +1561,7 @@ declare class HarnessAgentSession {
1549
1561
  pendingToolApprovals?: readonly HarnessAgentPendingToolApproval[];
1550
1562
  pendingToolResults?: readonly HarnessAgentPendingToolResult[];
1551
1563
  turnSettings?: HarnessV1TurnSettings;
1564
+ resumedToolsContext?: Record<string, Context | undefined>;
1552
1565
  turnState?: HarnessAgentTurnState;
1553
1566
  });
1554
1567
  hasUnfinishedTurn(): boolean;
@@ -1558,6 +1571,7 @@ declare class HarnessAgentSession {
1558
1571
  skills: ReadonlyArray<HarnessV1Skill>;
1559
1572
  instructions: string | undefined;
1560
1573
  tools: TOOLS;
1574
+ toolsContext: InferToolSetContext<TOOLS>;
1561
1575
  activeTools: ToolSet;
1562
1576
  toolSpecs: HarnessAgentToolSpec[];
1563
1577
  builtinToolFiltering: HarnessV1BuiltinToolFiltering | undefined;
@@ -1574,6 +1588,7 @@ declare class HarnessAgentSession {
1574
1588
  skills: ReadonlyArray<HarnessV1Skill>;
1575
1589
  instructions: string | undefined;
1576
1590
  tools: TOOLS;
1591
+ toolsContext: InferToolSetContext<TOOLS>;
1577
1592
  activeTools: ToolSet;
1578
1593
  toolSpecs: HarnessAgentToolSpec[];
1579
1594
  builtinToolFiltering: HarnessV1BuiltinToolFiltering | undefined;
@@ -1756,6 +1771,13 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
1756
1771
  * handing it to the adapter.
1757
1772
  */
1758
1773
  continueFrom?: HarnessAgentContinueTurnState;
1774
+ /**
1775
+ * Rebinds host-only tool context for an unfinished turn resumed with
1776
+ * `continueFrom` (directly or through `resumeFrom`). Tool context is not
1777
+ * serialized into lifecycle state because it may contain credentials or
1778
+ * non-serializable host objects.
1779
+ */
1780
+ toolsContext?: ToolsContextSettings<TUserTools>['toolsContext'];
1759
1781
  /**
1760
1782
  * Existing sandbox session to run the harness in. When provided, the
1761
1783
  * caller retains ownership of the sandbox lifecycle.
@@ -164,7 +164,11 @@ import {
164
164
  import {
165
165
  getErrorMessage
166
166
  } from "@ai-sdk/provider";
167
- import { asLanguageModelUsage as asLanguageModelUsage2, parseToolCall } from "ai/internal";
167
+ import {
168
+ asLanguageModelUsage as asLanguageModelUsage2,
169
+ parseToolCall,
170
+ validateToolContext
171
+ } from "ai/internal";
168
172
 
169
173
  // src/agent/internal/harness-stream-text-result.ts
170
174
  import {
@@ -851,6 +855,11 @@ function notSupportedYet(feature) {
851
855
  );
852
856
  }
853
857
 
858
+ // src/agent/internal/get-own.ts
859
+ function getOwn(obj, key) {
860
+ return obj != null && Object.prototype.hasOwnProperty.call(obj, key) ? obj[key] : void 0;
861
+ }
862
+
854
863
  // src/agent/internal/translate-stream-part.ts
855
864
  import { generateId } from "@ai-sdk/provider-utils";
856
865
  function translateStreamPart(event, options = {}) {
@@ -1014,30 +1023,44 @@ function translateStreamPart(event, options = {}) {
1014
1023
  function createToolInputWorkDirStripper({
1015
1024
  sessionWorkDir
1016
1025
  }) {
1017
- const pendingByToolCallId = /* @__PURE__ */ new Map();
1026
+ const stateByToolCallId = /* @__PURE__ */ new Map();
1018
1027
  return (part) => {
1019
1028
  var _a4;
1020
1029
  if (sessionWorkDir.length === 0) return [part];
1021
1030
  if (part.type === "tool-input-start") {
1022
- pendingByToolCallId.set(part.id, "");
1031
+ stateByToolCallId.set(part.id, {
1032
+ pending: "",
1033
+ precedingCharacter: void 0
1034
+ });
1023
1035
  return [part];
1024
1036
  }
1025
1037
  if (part.type === "tool-input-delta") {
1038
+ const state2 = (_a4 = stateByToolCallId.get(part.id)) != null ? _a4 : {
1039
+ pending: "",
1040
+ precedingCharacter: void 0
1041
+ };
1042
+ const value = state2.pending + part.delta;
1026
1043
  const stripped2 = stripStreamingString({
1027
- value: ((_a4 = pendingByToolCallId.get(part.id)) != null ? _a4 : "") + part.delta,
1044
+ value,
1028
1045
  workDir: sessionWorkDir,
1029
- final: false
1046
+ final: false,
1047
+ precedingCharacter: state2.precedingCharacter
1048
+ });
1049
+ const pendingStart = value.length - stripped2.pending.length;
1050
+ stateByToolCallId.set(part.id, {
1051
+ pending: stripped2.pending,
1052
+ precedingCharacter: stripped2.pending.length > 0 ? pendingStart > 0 ? value[pendingStart - 1] : state2.precedingCharacter : value.length > 0 ? value[value.length - 1] : state2.precedingCharacter
1030
1053
  });
1031
- pendingByToolCallId.set(part.id, stripped2.pending);
1032
1054
  return stripped2.output.length === 0 ? [] : [{ ...part, delta: stripped2.output }];
1033
1055
  }
1034
- const pending = pendingByToolCallId.get(part.id);
1035
- pendingByToolCallId.delete(part.id);
1036
- if (pending == null || pending.length === 0) return [part];
1056
+ const state = stateByToolCallId.get(part.id);
1057
+ stateByToolCallId.delete(part.id);
1058
+ if (state == null || state.pending.length === 0) return [part];
1037
1059
  const stripped = stripStreamingString({
1038
- value: pending,
1060
+ value: state.pending,
1039
1061
  workDir: sessionWorkDir,
1040
- final: true
1062
+ final: true,
1063
+ precedingCharacter: state.precedingCharacter
1041
1064
  });
1042
1065
  return stripped.output.length === 0 ? [part] : [
1043
1066
  { type: "tool-input-delta", id: part.id, delta: stripped.output },
@@ -1064,34 +1087,59 @@ function stripWorkDir(part, sessionWorkDir) {
1064
1087
  }
1065
1088
  }
1066
1089
  function stripString(value, workDir) {
1067
- return value.split(`${workDir}/`).join("").split(workDir).join(".");
1090
+ return stripStreamingString({
1091
+ value,
1092
+ workDir,
1093
+ final: true,
1094
+ precedingCharacter: void 0
1095
+ }).output;
1068
1096
  }
1069
1097
  function stripStreamingString({
1070
1098
  value,
1071
1099
  workDir,
1072
- final
1100
+ final,
1101
+ precedingCharacter
1073
1102
  }) {
1074
1103
  let remaining = value;
1075
1104
  let output = "";
1105
+ let characterBeforeRemaining = precedingCharacter;
1076
1106
  while (remaining.length > 0) {
1077
1107
  const matchIndex = remaining.indexOf(workDir);
1078
1108
  if (matchIndex >= 0) {
1079
- output += remaining.slice(0, matchIndex);
1080
1109
  const followingIndex = matchIndex + workDir.length;
1081
- if (followingIndex === remaining.length && !final) {
1082
- return { output, pending: remaining.slice(matchIndex) };
1110
+ const hasPathBoundary = isPathBoundary(
1111
+ remaining,
1112
+ matchIndex,
1113
+ characterBeforeRemaining
1114
+ );
1115
+ if (hasPathBoundary && followingIndex === remaining.length && !final) {
1116
+ return {
1117
+ output: output + remaining.slice(0, matchIndex),
1118
+ pending: remaining.slice(matchIndex)
1119
+ };
1083
1120
  }
1084
- if (remaining[followingIndex] === "/") {
1121
+ const isPath = hasPathBoundary && (followingIndex === remaining.length || remaining[followingIndex] === "/" || isPathTerminator(remaining[followingIndex]));
1122
+ if (!isPath) {
1123
+ output += remaining.slice(0, followingIndex);
1124
+ characterBeforeRemaining = remaining[followingIndex - 1];
1125
+ remaining = remaining.slice(followingIndex);
1126
+ } else if (remaining[followingIndex] === "/") {
1127
+ output += remaining.slice(0, matchIndex);
1128
+ characterBeforeRemaining = remaining[followingIndex];
1085
1129
  remaining = remaining.slice(followingIndex + 1);
1086
1130
  } else {
1087
- output += ".";
1131
+ output += remaining.slice(0, matchIndex) + ".";
1088
1132
  remaining = remaining.slice(followingIndex);
1089
1133
  }
1090
1134
  continue;
1091
1135
  }
1092
1136
  if (final) return { output: output + remaining, pending: "" };
1093
1137
  let pendingLength = Math.min(remaining.length, workDir.length - 1);
1094
- while (pendingLength > 0 && !workDir.startsWith(remaining.slice(-pendingLength))) {
1138
+ while (pendingLength > 0 && (!workDir.startsWith(remaining.slice(-pendingLength)) || !isPathBoundary(
1139
+ remaining,
1140
+ remaining.length - pendingLength,
1141
+ characterBeforeRemaining
1142
+ ))) {
1095
1143
  pendingLength -= 1;
1096
1144
  }
1097
1145
  const outputLength = remaining.length - pendingLength;
@@ -1102,6 +1150,13 @@ function stripStreamingString({
1102
1150
  }
1103
1151
  return { output, pending: "" };
1104
1152
  }
1153
+ function isPathBoundary(value, index, precedingCharacter) {
1154
+ const character = index === 0 ? precedingCharacter : value[index - 1];
1155
+ return character === void 0 || /[\s"'`=]/.test(character);
1156
+ }
1157
+ function isPathTerminator(character) {
1158
+ return character === void 0 || /[\s"'`;|&<>()]/.test(character);
1159
+ }
1105
1160
  function stripDeep(value, workDir) {
1106
1161
  if (typeof value === "string") return stripString(value, workDir);
1107
1162
  if (Array.isArray(value)) return value.map((item) => stripDeep(item, workDir));
@@ -1479,29 +1534,29 @@ function unwrapToolResultOutput(toolResult) {
1479
1534
  }
1480
1535
  }
1481
1536
  function runPrompt(input) {
1482
- var _a4, _b4, _c, _d, _e, _f, _g, _h, _i;
1537
+ var _a4, _b4, _c, _d, _e, _f, _g, _h, _i, _j;
1483
1538
  const callId = generateId2();
1484
- const toolsContext = {};
1539
+ const toolsContext = (_a4 = input.toolsContext) != null ? _a4 : {};
1485
1540
  const result = new HarnessStreamTextResult({
1486
1541
  tools: input.tools,
1487
1542
  runtimeContext: input.runtimeContext,
1488
1543
  toolsContext,
1489
1544
  harnessId: input.harness.harnessId,
1490
1545
  callId,
1491
- modelId: (_a4 = input.model) != null ? _a4 : "",
1546
+ modelId: (_b4 = input.model) != null ? _b4 : "",
1492
1547
  output: input.output
1493
1548
  });
1494
- const pendingToolApprovals = (_b4 = input.pendingToolApprovals) != null ? _b4 : [];
1495
- const pendingToolResults = (_c = input.pendingToolResults) != null ? _c : [];
1496
- const onPendingToolApproval = (_d = input.onPendingToolApproval) != null ? _d : (() => {
1549
+ const pendingToolApprovals = (_c = input.pendingToolApprovals) != null ? _c : [];
1550
+ const pendingToolResults = (_d = input.pendingToolResults) != null ? _d : [];
1551
+ const onPendingToolApproval = (_e = input.onPendingToolApproval) != null ? _e : (() => {
1497
1552
  });
1498
- const onToolApprovalSettled = (_e = input.onToolApprovalSettled) != null ? _e : (() => {
1553
+ const onToolApprovalSettled = (_f = input.onToolApprovalSettled) != null ? _f : (() => {
1499
1554
  });
1500
- const onPendingToolResult = (_f = input.onPendingToolResult) != null ? _f : (() => {
1555
+ const onPendingToolResult = (_g = input.onPendingToolResult) != null ? _g : (() => {
1501
1556
  });
1502
- const onToolResultSettled = (_g = input.onToolResultSettled) != null ? _g : (() => {
1557
+ const onToolResultSettled = (_h = input.onToolResultSettled) != null ? _h : (() => {
1503
1558
  });
1504
- const activeTools = (_h = input.activeTools) != null ? _h : input.tools;
1559
+ const activeTools = (_i = input.activeTools) != null ? _i : input.tools;
1505
1560
  const activeToolNames = Object.keys(input.tools).filter(
1506
1561
  (toolName) => Object.prototype.hasOwnProperty.call(activeTools, toolName) || Object.prototype.hasOwnProperty.call(
1507
1562
  input.harness.builtinTools,
@@ -1514,7 +1569,7 @@ function runPrompt(input) {
1514
1569
  const lifecycle = createTurnLifecycle({
1515
1570
  callId,
1516
1571
  telemetry: input.telemetry,
1517
- callbacks: (_i = input.callbacks) != null ? _i : {},
1572
+ callbacks: (_j = input.callbacks) != null ? _j : {},
1518
1573
  harnessId: input.harness.harnessId,
1519
1574
  modelId: input.model,
1520
1575
  instructions: input.instructions,
@@ -1541,7 +1596,7 @@ function runPrompt(input) {
1541
1596
  result.fail(err);
1542
1597
  };
1543
1598
  const done = (async () => {
1544
- var _a5, _b5, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j, _k, _l, _m, _n, _o;
1599
+ var _a5, _b5, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k, _l, _m, _n, _o;
1545
1600
  let bridge;
1546
1601
  try {
1547
1602
  bridge = await toHarnessStream({
@@ -1926,6 +1981,7 @@ function runPrompt(input) {
1926
1981
  const execution = await maybeExecuteHostTool({
1927
1982
  event: rawToolCall,
1928
1983
  tools: activeTools,
1984
+ toolsContext,
1929
1985
  wrappedExecuteTool: lifecycle.executeTool,
1930
1986
  sandboxSession: input.sandboxSession,
1931
1987
  abortSignal: input.abortSignal,
@@ -2177,7 +2233,7 @@ function runPrompt(input) {
2177
2233
  toolName: toolCall.toolName,
2178
2234
  input: (_i2 = rawToolCall == null ? void 0 : rawToolCall.input) != null ? _i2 : JSON.stringify(toolCall.input),
2179
2235
  kind: "builtin",
2180
- providerExecuted: (_j = rawToolCall == null ? void 0 : rawToolCall.providerExecuted) != null ? _j : true,
2236
+ providerExecuted: (_j2 = rawToolCall == null ? void 0 : rawToolCall.providerExecuted) != null ? _j2 : true,
2181
2237
  ...(rawToolCall == null ? void 0 : rawToolCall.nativeName) !== void 0 ? { nativeName: rawToolCall.nativeName } : {}
2182
2238
  };
2183
2239
  pendingApprovalsByApprovalId.set(
@@ -2372,6 +2428,7 @@ function runPrompt(input) {
2372
2428
  const execution = await maybeExecuteHostTool({
2373
2429
  event: toolCall,
2374
2430
  tools: activeTools,
2431
+ toolsContext,
2375
2432
  wrappedExecuteTool: lifecycle.executeTool,
2376
2433
  sandboxSession: input.sandboxSession,
2377
2434
  abortSignal: input.abortSignal,
@@ -2483,6 +2540,21 @@ async function maybeExecuteHostTool(input) {
2483
2540
  if (!isExecutableTool(tool)) return { executed: false };
2484
2541
  const parsed = await safeParseJSON2({ text: input.event.input });
2485
2542
  const args = parsed.success ? parsed.value : input.event.input;
2543
+ let context;
2544
+ try {
2545
+ context = await validateToolContext({
2546
+ toolName: input.event.toolName,
2547
+ context: getOwn(input.toolsContext, input.event.toolName),
2548
+ contextSchema: tool.contextSchema
2549
+ });
2550
+ } catch (err) {
2551
+ await input.submitToolResult({
2552
+ toolCallId: input.event.toolCallId,
2553
+ output: { error: "Tool context validation failed." },
2554
+ isError: true
2555
+ });
2556
+ return { executed: true, outcome: { ok: false, error: err } };
2557
+ }
2486
2558
  try {
2487
2559
  const output = await input.wrappedExecuteTool({
2488
2560
  toolCallId: input.event.toolCallId,
@@ -2495,7 +2567,7 @@ async function maybeExecuteHostTool(input) {
2495
2567
  toolCallId: input.event.toolCallId,
2496
2568
  messages: [],
2497
2569
  abortSignal: input.abortSignal,
2498
- context: void 0,
2570
+ context,
2499
2571
  experimental_sandbox: input.sandboxSession
2500
2572
  }
2501
2573
  });
@@ -2584,6 +2656,7 @@ var HarnessAgentSession = class {
2584
2656
  this.pendingToolResults.set(pendingResult.toolCallId, pendingResult);
2585
2657
  }
2586
2658
  this.persistedTurnSettings = options.turnSettings;
2659
+ this.resumedToolsContext = options.resumedToolsContext;
2587
2660
  this.turnState = (_d = options.turnState) != null ? _d : this.pendingToolApprovals.size > 0 ? "awaiting-approval" : this.pendingToolResults.size > 0 ? "awaiting-tool-result" : "idle";
2588
2661
  this.isResume = options.underlyingSession.isResume;
2589
2662
  }
@@ -2624,6 +2697,7 @@ var HarnessAgentSession = class {
2624
2697
  this.activeTurnSettings = {
2625
2698
  persisted: this.persistedTurnSettings,
2626
2699
  tools: options.tools,
2700
+ toolsContext: options.toolsContext,
2627
2701
  activeTools: options.activeTools,
2628
2702
  builtinToolFiltering: options.builtinToolFiltering
2629
2703
  };
@@ -2638,6 +2712,7 @@ var HarnessAgentSession = class {
2638
2712
  skills: options.skills,
2639
2713
  instructions: options.instructions,
2640
2714
  tools: options.tools,
2715
+ toolsContext: options.toolsContext,
2641
2716
  activeTools: options.activeTools,
2642
2717
  toolSpecs: options.toolSpecs,
2643
2718
  builtinToolFiltering: options.builtinToolFiltering,
@@ -2697,6 +2772,7 @@ var HarnessAgentSession = class {
2697
2772
  skills: options.skills,
2698
2773
  instructions: options.instructions,
2699
2774
  tools: options.tools,
2775
+ toolsContext: options.toolsContext,
2700
2776
  activeTools: options.activeTools,
2701
2777
  toolSpecs: options.toolSpecs,
2702
2778
  builtinToolFiltering: options.builtinToolFiltering
@@ -2712,6 +2788,7 @@ var HarnessAgentSession = class {
2712
2788
  skills: turnSettings.persisted.skills,
2713
2789
  instructions: turnSettings.persisted.instructions,
2714
2790
  tools: turnSettings.tools,
2791
+ toolsContext: turnSettings.toolsContext,
2715
2792
  activeTools: turnSettings.activeTools,
2716
2793
  toolSpecs: [...turnSettings.persisted.tools],
2717
2794
  builtinToolFiltering: turnSettings.builtinToolFiltering,
@@ -3076,7 +3153,7 @@ var HarnessAgentSession = class {
3076
3153
  this.turnState = "idle";
3077
3154
  }
3078
3155
  resolveActiveTurnSettings(options) {
3079
- var _a4;
3156
+ var _a4, _b4;
3080
3157
  if (this.activeTurnSettings != null) {
3081
3158
  return this.activeTurnSettings;
3082
3159
  }
@@ -3100,6 +3177,7 @@ var HarnessAgentSession = class {
3100
3177
  this.activeTurnSettings = {
3101
3178
  persisted,
3102
3179
  tools: options.tools,
3180
+ toolsContext: (_b4 = this.resumedToolsContext) != null ? _b4 : options.toolsContext,
3103
3181
  activeTools,
3104
3182
  builtinToolFiltering: options.builtinToolFiltering
3105
3183
  };
@@ -3722,6 +3800,11 @@ var HarnessAgent = class {
3722
3800
  });
3723
3801
  }
3724
3802
  const effectiveContinueFrom = validatedContinueFrom != null ? validatedContinueFrom : validatedResumeFrom == null ? void 0 : validatedResumeFrom.continueFrom;
3803
+ if ((options == null ? void 0 : options.toolsContext) != null && effectiveContinueFrom == null) {
3804
+ throw new Error(
3805
+ "HarnessAgent.createSession: `toolsContext` can only rebind an unfinished turn from `continueFrom` or `resumeFrom`."
3806
+ );
3807
+ }
3725
3808
  const isResumedSession = validatedResumeFrom != null || effectiveContinueFrom != null;
3726
3809
  let sandboxSession;
3727
3810
  let sessionWorkDir;
@@ -3884,6 +3967,7 @@ var HarnessAgent = class {
3884
3967
  pendingToolApprovals: effectiveContinueFrom == null ? void 0 : effectiveContinueFrom.pendingToolApprovals,
3885
3968
  pendingToolResults: effectiveContinueFrom == null ? void 0 : effectiveContinueFrom.pendingToolResults,
3886
3969
  turnSettings: effectiveContinueFrom == null ? void 0 : effectiveContinueFrom.turnSettings,
3970
+ resumedToolsContext: options == null ? void 0 : options.toolsContext,
3887
3971
  turnState: effectiveContinueFrom == null ? "idle" : effectiveContinueFrom.pendingToolApprovals != null && effectiveContinueFrom.pendingToolApprovals.length > 0 ? "awaiting-approval" : effectiveContinueFrom.pendingToolResults != null && effectiveContinueFrom.pendingToolResults.length > 0 ? "awaiting-tool-result" : "suspended"
3888
3972
  });
3889
3973
  } catch (error) {
@@ -4007,6 +4091,7 @@ var HarnessAgent = class {
4007
4091
  skills: input.turnSettings.skills,
4008
4092
  instructions: input.turnSettings.instructions,
4009
4093
  tools: input.turnSettings.tools,
4094
+ toolsContext: input.turnSettings.toolsContext,
4010
4095
  activeTools: input.turnSettings.activeTools,
4011
4096
  toolSpecs: input.turnSettings.toolSpecs,
4012
4097
  builtinToolFiltering: input.turnSettings.builtinToolFiltering,
@@ -4089,7 +4174,7 @@ var HarnessAgent = class {
4089
4174
  throw new Error("HarnessAgent: either `prompt` or `messages` is required.");
4090
4175
  }
4091
4176
  async _preparePromptTurnInput(options) {
4092
- var _a4, _b4, _c;
4177
+ var _a4, _b4, _c, _d;
4093
4178
  let callOptions = options;
4094
4179
  if (this.settings.callOptionsSchema != null && options.options !== void 0) {
4095
4180
  const validatedOptions = await validateTypes({
@@ -4126,12 +4211,13 @@ var HarnessAgent = class {
4126
4211
  skills: this.settings.skills,
4127
4212
  instructions: this.settings.instructions,
4128
4213
  tools: this.settings.tools,
4214
+ toolsContext: (_a4 = this.settings.toolsContext) != null ? _a4 : {},
4129
4215
  ...promptOptions
4130
4216
  };
4131
- const preparedCallArgs = (_c = await ((_b4 = (_a4 = this.settings).prepareCall) == null ? void 0 : _b4.call(
4132
- _a4,
4217
+ const preparedCallArgs = (_d = await ((_c = (_b4 = this.settings).prepareCall) == null ? void 0 : _c.call(
4218
+ _b4,
4133
4219
  baseCallArgs
4134
- ))) != null ? _c : baseCallArgs;
4220
+ ))) != null ? _d : baseCallArgs;
4135
4221
  if (this._resolveContinueTurnInput(preparedCallArgs) != null) {
4136
4222
  throw new Error(
4137
4223
  "HarnessAgent.prepareCall must return a fresh user prompt, not a tool continuation."
@@ -4143,7 +4229,8 @@ var HarnessAgent = class {
4143
4229
  model: preparedCallArgs.model,
4144
4230
  skills: preparedCallArgs.skills,
4145
4231
  instructions: preparedCallArgs.instructions,
4146
- tools: preparedCallArgs.tools
4232
+ tools: preparedCallArgs.tools,
4233
+ toolsContext: preparedCallArgs.toolsContext
4147
4234
  })
4148
4235
  };
4149
4236
  }
@@ -4154,14 +4241,15 @@ var HarnessAgent = class {
4154
4241
  model: this.settings.model,
4155
4242
  skills: this.settings.skills,
4156
4243
  instructions: this.settings.instructions,
4157
- tools: this.settings.tools
4244
+ tools: this.settings.tools,
4245
+ toolsContext: this.settings.toolsContext
4158
4246
  }),
4159
4247
  toolApprovalContinuations: (_a4 = options.toolApprovalContinuations) != null ? _a4 : [],
4160
4248
  toolResultContinuations: (_b4 = options.toolResultContinuations) != null ? _b4 : []
4161
4249
  };
4162
4250
  }
4163
4251
  _prepareTurnSettings(options) {
4164
- var _a4, _b4, _c;
4252
+ var _a4, _b4, _c, _d;
4165
4253
  const userTools = (_a4 = options.tools) != null ? _a4 : {};
4166
4254
  assertNoReservedQuestionTool({
4167
4255
  harness: this.settings.harness,
@@ -4183,6 +4271,7 @@ var HarnessAgent = class {
4183
4271
  skills: (_b4 = options.skills) != null ? _b4 : [],
4184
4272
  instructions: typeof options.instructions === "string" ? options.instructions : (_c = options.instructions) == null ? void 0 : _c.content,
4185
4273
  tools,
4274
+ toolsContext: (_d = options.toolsContext) != null ? _d : {},
4186
4275
  activeTools: toolFiltering.activeUserTools,
4187
4276
  toolSpecs: this._toToolSpecs(toolFiltering.activeUserTools),
4188
4277
  builtinToolFiltering: toolFiltering.builtinToolFiltering