@ai-sdk/harness 1.0.39 → 1.0.40

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,15 @@
1
1
  # @ai-sdk/harness
2
2
 
3
+ ## 1.0.40
4
+
5
+ ### Patch Changes
6
+
7
+ - 59a2306: fix(harness): execute host tools through telemetry context wrappers
8
+ - 5f65e61: feat(harness): add support for `stopWhen` control to `HarnessAgent` (e.g. `isStepCount(1)`)
9
+ - Updated dependencies [7f6650b]
10
+ - Updated dependencies [106ea59]
11
+ - ai@7.0.35
12
+
3
13
  ## 1.0.39
4
14
 
5
15
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
2
- import { Experimental_SandboxSession, UserModelMessage, ToolSet, FlexibleSchema, Tool, ToolApprovalResponse, ModelMessage, Context } from '@ai-sdk/provider-utils';
3
- import { ToolApprovalStatus, TelemetryOptions, ActiveTools, StreamTextResult, Agent, AgentCallParameters, GenerateTextResult, AgentStreamParameters, Telemetry } from 'ai';
2
+ import { Experimental_SandboxSession, UserModelMessage, ToolSet, FlexibleSchema, Tool, Context, Arrayable, ToolApprovalResponse, ModelMessage } from '@ai-sdk/provider-utils';
3
+ import { StopCondition, ToolApprovalStatus, TelemetryOptions, ActiveTools, StreamTextResult, Agent, AgentCallParameters, GenerateTextResult, AgentStreamParameters, Telemetry } from 'ai';
4
4
  import { z } from 'zod/v4';
5
5
  import { JSONValue, LanguageModelV4ToolCall, LanguageModelV4ToolApprovalRequest, LanguageModelV4ToolResult, LanguageModelV4FinishReason, LanguageModelV4Usage, JSONSchema7, AISDKError } from '@ai-sdk/provider';
6
6
 
@@ -1143,7 +1143,7 @@ type HarnessAgentToolFilteringSettings<TOOLS extends ToolSet> = {
1143
1143
  */
1144
1144
  readonly inactiveTools?: HarnessTools<TOOLS>;
1145
1145
  };
1146
- type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAgentAdapter, TUserTools extends ToolSet = {}> = {
1146
+ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAgentAdapter, TUserTools extends ToolSet = {}, RUNTIME_CONTEXT extends Context = Context> = {
1147
1147
  /**
1148
1148
  * The harness adapter driving the underlying agent runtime. Its
1149
1149
  * `builtinTools` are merged with the user-defined `tools` and exposed to
@@ -1177,6 +1177,16 @@ type HarnessAgentSettings<THarness extends HarnessAgentAdapter<any> = HarnessAge
1177
1177
  * later turns or when resuming a previously ended session.
1178
1178
  */
1179
1179
  readonly instructions?: string;
1180
+ /**
1181
+ * Conditions that stop the current result after a completed harness tool
1182
+ * step that can continue into another model step. The underlying turn remains
1183
+ * unfinished and can be suspended and continued.
1184
+ *
1185
+ * A terminal text-only step finishes naturally and is not stopped early.
1186
+ *
1187
+ * When omitted, the harness runs until the turn naturally finishes or pauses.
1188
+ */
1189
+ readonly stopWhen?: Arrayable<StopCondition<NoInfer<HarnessAllTools<THarness, TUserTools>>, RUNTIME_CONTEXT>>;
1180
1190
  /**
1181
1191
  * Built-in tool permission mode. Defaults to `'allow-all'`, preserving the
1182
1192
  * existing bypass-permissions behavior unless users opt in.
@@ -1303,6 +1313,7 @@ declare class HarnessAgentSession {
1303
1313
  private turnState;
1304
1314
  private turnSequence;
1305
1315
  private activeTurnSequence;
1316
+ private suspendedTurnState;
1306
1317
  /**
1307
1318
  * Whether this session was created from `resumeFrom` or `continueFrom`.
1308
1319
  * Captured at construction so it survives lifecycle cleanup.
@@ -1332,6 +1343,7 @@ declare class HarnessAgentSession {
1332
1343
  runtimeContext: RUNTIME_CONTEXT;
1333
1344
  abortSignal: AbortSignal | undefined;
1334
1345
  telemetry: TelemetryOptions | undefined;
1346
+ stopConditions: ReadonlyArray<StopCondition<TOOLS, RUNTIME_CONTEXT>>;
1335
1347
  }): HarnessAgentTurnResult<TOOLS, RUNTIME_CONTEXT>;
1336
1348
  continueTurn<TOOLS extends ToolSet, RUNTIME_CONTEXT extends Context>(options: {
1337
1349
  instructions: string | undefined;
@@ -1342,6 +1354,7 @@ declare class HarnessAgentSession {
1342
1354
  runtimeContext: RUNTIME_CONTEXT;
1343
1355
  abortSignal: AbortSignal | undefined;
1344
1356
  telemetry: TelemetryOptions | undefined;
1357
+ stopConditions: ReadonlyArray<StopCondition<TOOLS, RUNTIME_CONTEXT>>;
1345
1358
  toolApprovalContinuations?: readonly HarnessAgentToolApprovalContinuation[] | undefined;
1346
1359
  toolResultContinuations?: readonly HarnessAgentToolResultContinuation[] | undefined;
1347
1360
  }): HarnessAgentTurnResult<TOOLS, RUNTIME_CONTEXT>;
@@ -1392,6 +1405,7 @@ declare class HarnessAgentSession {
1392
1405
  private getPendingToolResults;
1393
1406
  private addPendingToolState;
1394
1407
  private suspendCurrentTurn;
1408
+ private captureStopConditionBoundary;
1395
1409
  private toResumeStateWithContinuation;
1396
1410
  private requirePromptableTurn;
1397
1411
  private requireContinuableTurn;
@@ -1461,11 +1475,12 @@ declare class HarnessAgent<THarness extends HarnessAgentAdapter<any> = HarnessAg
1461
1475
  */
1462
1476
  readonly tools: HarnessAllTools<THarness, TUserTools>;
1463
1477
  private readonly settings;
1478
+ private readonly stopConditions;
1464
1479
  private readonly sandboxConfig;
1465
1480
  private readonly activeUserTools;
1466
1481
  private readonly builtinToolFiltering;
1467
1482
  private readonly permissionMode;
1468
- constructor(settings: HarnessAgentSettings<THarness, TUserTools>);
1483
+ constructor(settings: HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT>);
1469
1484
  /** Identifier of the harness backing this agent. */
1470
1485
  get harnessId(): string;
1471
1486
  /**
@@ -40,6 +40,7 @@ var HarnessCapabilityUnsupportedError = class extends (_b2 = HarnessError, _a2 =
40
40
 
41
41
  // src/agent/harness-agent.ts
42
42
  import {
43
+ asArray as asArray2,
43
44
  asSchema,
44
45
  generateId as generateId5
45
46
  } from "@ai-sdk/provider-utils";
@@ -181,7 +182,7 @@ import {
181
182
  executeTool,
182
183
  generateId as generateId4,
183
184
  isExecutableTool,
184
- safeParseJSON
185
+ safeParseJSON as safeParseJSON2
185
186
  } from "@ai-sdk/provider-utils";
186
187
  import {
187
188
  getErrorMessage
@@ -924,7 +925,10 @@ var NOOP = {
924
925
  },
925
926
  stepFinish() {
926
927
  },
927
- toolStart() {
928
+ async toolStart() {
929
+ },
930
+ async executeTool({ execute }) {
931
+ return await execute();
928
932
  },
929
933
  toolEnd() {
930
934
  },
@@ -1083,11 +1087,12 @@ function createTurnTelemetry(opts) {
1083
1087
  stepOpen = false;
1084
1088
  stepNumber += 1;
1085
1089
  },
1086
- toolStart(call) {
1090
+ async toolStart(call) {
1087
1091
  var _a4;
1088
1092
  ensureStepOpen();
1093
+ if (openTools.has(call.toolCallId)) return;
1089
1094
  openTools.set(call.toolCallId, call);
1090
- (_a4 = dispatcher.onToolExecutionStart) == null ? void 0 : _a4.call(
1095
+ await ((_a4 = dispatcher.onToolExecutionStart) == null ? void 0 : _a4.call(
1091
1096
  dispatcher,
1092
1097
  cast({
1093
1098
  callId,
@@ -1101,7 +1106,11 @@ function createTurnTelemetry(opts) {
1101
1106
  },
1102
1107
  toolContext: void 0
1103
1108
  })
1104
- );
1109
+ ));
1110
+ },
1111
+ async executeTool({ toolCallId, execute }) {
1112
+ if (dispatcher.executeTool == null) return await execute();
1113
+ return await dispatcher.executeTool({ callId, toolCallId, execute });
1105
1114
  },
1106
1115
  toolEnd(toolCallId, output) {
1107
1116
  var _a4;
@@ -1263,6 +1272,20 @@ function logBridgeError({
1263
1272
  }
1264
1273
  }
1265
1274
 
1275
+ // src/utils/sandbox-channel.ts
1276
+ import {
1277
+ safeParseJSON,
1278
+ safeValidateTypes as safeValidateTypes2
1279
+ } from "@ai-sdk/provider-utils";
1280
+ var sandboxChannelEventCheckpointSymbol = /* @__PURE__ */ Symbol.for(
1281
+ "vercel.ai.harness.sandboxChannelEventCheckpoint"
1282
+ );
1283
+ function pinSandboxChannelEventCheckpoint(event) {
1284
+ var _a3;
1285
+ if (event == null || typeof event !== "object") return void 0;
1286
+ return (_a3 = event[sandboxChannelEventCheckpointSymbol]) == null ? void 0 : _a3.pin();
1287
+ }
1288
+
1266
1289
  // src/agent/internal/run-prompt.ts
1267
1290
  function runPrompt(input) {
1268
1291
  var _a3, _b3, _c, _d, _e, _f, _g;
@@ -1306,7 +1329,7 @@ function runPrompt(input) {
1306
1329
  result.fail(err);
1307
1330
  };
1308
1331
  const done = (async () => {
1309
- var _a4, _b4, _c2, _d2, _e2, _f2, _g2, _h, _i, _j;
1332
+ var _a4, _b4, _c2, _d2, _e2, _f2, _g2, _h, _i, _j, _k;
1310
1333
  let bridge;
1311
1334
  try {
1312
1335
  bridge = await toHarnessStream({
@@ -1370,7 +1393,14 @@ function runPrompt(input) {
1370
1393
  );
1371
1394
  const settledHostToolCallIds = /* @__PURE__ */ new Set();
1372
1395
  let closingResumedStep = false;
1396
+ let pendingStopBoundary;
1373
1397
  let finalFinish;
1398
+ const completedSteps = [];
1399
+ const releasePendingStopBoundary = () => {
1400
+ var _a5;
1401
+ (_a5 = pendingStopBoundary == null ? void 0 : pendingStopBoundary.releaseCheckpoint) == null ? void 0 : _a5.call(pendingStopBoundary);
1402
+ pendingStopBoundary = void 0;
1403
+ };
1374
1404
  let stepText = "";
1375
1405
  let stepReasoning = "";
1376
1406
  let stepToolCalls = [];
@@ -1411,12 +1441,14 @@ function runPrompt(input) {
1411
1441
  content: buildStepContent()
1412
1442
  });
1413
1443
  resetStepContent();
1414
- return result.finishStep({
1444
+ const step = result.finishStep({
1415
1445
  finishReason: input2.finishReason,
1416
1446
  usage: input2.usage,
1417
1447
  providerMetadata: input2.providerMetadata,
1418
1448
  warnings: []
1419
1449
  });
1450
+ completedSteps.push(step);
1451
+ return step;
1420
1452
  };
1421
1453
  const finishForHostInputPause = async (options) => {
1422
1454
  if (options.completeCurrentStep) {
@@ -1517,9 +1549,16 @@ function runPrompt(input) {
1517
1549
  toolName: approval.toolName,
1518
1550
  input: approval.input
1519
1551
  };
1552
+ telemetry.start(input.session.modelId);
1553
+ await telemetry.toolStart({
1554
+ toolCallId: rawToolCall.toolCallId,
1555
+ toolName: rawToolCall.toolName,
1556
+ input: rawToolCall.input
1557
+ });
1520
1558
  const execution = await maybeExecuteHostTool({
1521
1559
  event: rawToolCall,
1522
1560
  tools: activeTools,
1561
+ wrappedExecuteTool: telemetry.executeTool,
1523
1562
  sandboxSession: input.sandboxSession,
1524
1563
  abortSignal: input.abortSignal,
1525
1564
  control,
@@ -1577,10 +1616,31 @@ function runPrompt(input) {
1577
1616
  }
1578
1617
  while (true) {
1579
1618
  const { value, done: done2 } = await reader.read();
1580
- if (done2) break;
1619
+ if (done2) {
1620
+ releasePendingStopBoundary();
1621
+ break;
1622
+ }
1581
1623
  if (value == null) continue;
1624
+ if (pendingStopBoundary != null) {
1625
+ if (value.type === "finish") {
1626
+ releasePendingStopBoundary();
1627
+ } else if ((await Promise.all(
1628
+ input.stopConditions.map(
1629
+ (condition) => condition({ steps: completedSteps })
1630
+ )
1631
+ )).some(Boolean)) {
1632
+ await ((_c2 = input.onStopConditionMet) == null ? void 0 : _c2.call(input));
1633
+ const { finishReason, usage } = pendingStopBoundary;
1634
+ releasePendingStopBoundary();
1635
+ telemetry.end({ finishReason, usage });
1636
+ await result.finish();
1637
+ return;
1638
+ } else {
1639
+ releasePendingStopBoundary();
1640
+ }
1641
+ }
1582
1642
  if (value.type === "stream-start") {
1583
- telemetry.start((_c2 = value.modelId) != null ? _c2 : input.session.modelId);
1643
+ telemetry.start((_d2 = value.modelId) != null ? _d2 : input.session.modelId);
1584
1644
  }
1585
1645
  if (value.type !== "stream-start" && value.type !== "finish-step" && value.type !== "finish" && value.type !== "error") {
1586
1646
  telemetry.ensureStepOpen();
@@ -1606,7 +1666,7 @@ function runPrompt(input) {
1606
1666
  const rawToolCall = rawToolCallsByToolCallId.get(
1607
1667
  displayValue.toolCallId
1608
1668
  );
1609
- const toolName = (_d2 = rawToolCall == null ? void 0 : rawToolCall.toolName) != null ? _d2 : toolCall.toolName;
1669
+ const toolName = (_e2 = rawToolCall == null ? void 0 : rawToolCall.toolName) != null ? _e2 : toolCall.toolName;
1610
1670
  if (!isHarnessV1BuiltinToolIncluded({
1611
1671
  toolName,
1612
1672
  toolFiltering: input.builtinToolFiltering
@@ -1662,7 +1722,7 @@ function runPrompt(input) {
1662
1722
  toolName: value.toolName,
1663
1723
  input: value.input
1664
1724
  });
1665
- telemetry.toolStart({
1725
+ await telemetry.toolStart({
1666
1726
  toolCallId: value.toolCallId,
1667
1727
  toolName: value.toolName,
1668
1728
  input: value.input
@@ -1682,13 +1742,13 @@ function runPrompt(input) {
1682
1742
  );
1683
1743
  }
1684
1744
  const rawToolCall = rawToolCallsByToolCallId.get(value.toolCallId);
1685
- const pendingApproval = (_g2 = pendingApprovalsByApprovalId.get(value.approvalId)) != null ? _g2 : {
1745
+ const pendingApproval = (_h = pendingApprovalsByApprovalId.get(value.approvalId)) != null ? _h : {
1686
1746
  approvalId: value.approvalId,
1687
1747
  toolCallId: value.toolCallId,
1688
1748
  toolName: toolCall.toolName,
1689
- input: (_e2 = rawToolCall == null ? void 0 : rawToolCall.input) != null ? _e2 : JSON.stringify(toolCall.input),
1749
+ input: (_f2 = rawToolCall == null ? void 0 : rawToolCall.input) != null ? _f2 : JSON.stringify(toolCall.input),
1690
1750
  kind: "builtin",
1691
- providerExecuted: (_f2 = rawToolCall == null ? void 0 : rawToolCall.providerExecuted) != null ? _f2 : true,
1751
+ providerExecuted: (_g2 = rawToolCall == null ? void 0 : rawToolCall.providerExecuted) != null ? _g2 : true,
1692
1752
  ...(rawToolCall == null ? void 0 : rawToolCall.nativeName) !== void 0 ? { nativeName: rawToolCall.nativeName } : {}
1693
1753
  };
1694
1754
  pendingApprovalsByApprovalId.set(
@@ -1725,6 +1785,13 @@ function runPrompt(input) {
1725
1785
  usage: value.usage,
1726
1786
  providerMetadata: value.harnessMetadata
1727
1787
  });
1788
+ if (input.stopConditions != null && input.stopConditions.length > 0) {
1789
+ pendingStopBoundary = {
1790
+ finishReason: value.finishReason,
1791
+ usage: value.usage,
1792
+ releaseCheckpoint: pinSandboxChannelEventCheckpoint(value)
1793
+ };
1794
+ }
1728
1795
  }
1729
1796
  if (value.type === "finish") {
1730
1797
  finalFinish = value;
@@ -1784,7 +1851,7 @@ function runPrompt(input) {
1784
1851
  telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
1785
1852
  continue;
1786
1853
  }
1787
- const pendingApproval = (_h = pendingApprovalsByToolCallId.get(toolCall.toolCallId)) != null ? _h : customToolApprovalDecision.type === "request" ? {
1854
+ const pendingApproval = (_i = pendingApprovalsByToolCallId.get(toolCall.toolCallId)) != null ? _i : customToolApprovalDecision.type === "request" ? {
1788
1855
  approvalId: generateId4(),
1789
1856
  toolCallId: toolCall.toolCallId,
1790
1857
  toolName: toolCall.toolName,
@@ -1833,6 +1900,7 @@ function runPrompt(input) {
1833
1900
  const execution = await maybeExecuteHostTool({
1834
1901
  event: toolCall,
1835
1902
  tools: activeTools,
1903
+ wrappedExecuteTool: telemetry.executeTool,
1836
1904
  sandboxSession: input.sandboxSession,
1837
1905
  abortSignal: input.abortSignal,
1838
1906
  control,
@@ -1865,9 +1933,9 @@ function runPrompt(input) {
1865
1933
  }
1866
1934
  }
1867
1935
  if (finalFinish != null) {
1868
- (_i = input.onTurnFinished) == null ? void 0 : _i.call(input);
1936
+ (_j = input.onTurnFinished) == null ? void 0 : _j.call(input);
1869
1937
  } else {
1870
- (_j = input.onTurnFailed) == null ? void 0 : _j.call(input);
1938
+ (_k = input.onTurnFailed) == null ? void 0 : _k.call(input);
1871
1939
  }
1872
1940
  await result.finish(
1873
1941
  finalFinish ? {
@@ -1886,6 +1954,7 @@ function runPrompt(input) {
1886
1954
  });
1887
1955
  settleFailure(err);
1888
1956
  } finally {
1957
+ releasePendingStopBoundary();
1889
1958
  reader.releaseLock();
1890
1959
  }
1891
1960
  })();
@@ -1907,28 +1976,34 @@ function hasTool(input) {
1907
1976
  async function maybeExecuteHostTool(input) {
1908
1977
  const tool = input.tools[input.event.toolName];
1909
1978
  if (!isExecutableTool(tool)) return { executed: false };
1910
- const parsed = await safeParseJSON({ text: input.event.input });
1979
+ const parsed = await safeParseJSON2({ text: input.event.input });
1911
1980
  const args = parsed.success ? parsed.value : input.event.input;
1912
1981
  try {
1913
- let output;
1914
- const stream = executeTool({
1915
- tool,
1916
- input: args,
1917
- options: {
1918
- toolCallId: input.event.toolCallId,
1919
- messages: [],
1920
- abortSignal: input.abortSignal,
1921
- context: void 0,
1922
- experimental_sandbox: input.sandboxSession
1982
+ const output = await input.wrappedExecuteTool({
1983
+ toolCallId: input.event.toolCallId,
1984
+ execute: async () => {
1985
+ let output2;
1986
+ const stream = executeTool({
1987
+ tool,
1988
+ input: args,
1989
+ options: {
1990
+ toolCallId: input.event.toolCallId,
1991
+ messages: [],
1992
+ abortSignal: input.abortSignal,
1993
+ context: void 0,
1994
+ experimental_sandbox: input.sandboxSession
1995
+ }
1996
+ });
1997
+ for await (const part of stream) {
1998
+ if (part.type === "preliminary") {
1999
+ input.onPreliminaryResult(part.output);
2000
+ } else {
2001
+ output2 = part.output;
2002
+ }
2003
+ }
2004
+ return output2;
1923
2005
  }
1924
2006
  });
1925
- for await (const part of stream) {
1926
- if (part.type === "preliminary") {
1927
- input.onPreliminaryResult(part.output);
1928
- } else {
1929
- output = part.output;
1930
- }
1931
- }
1932
2007
  await input.control.submitToolResult({
1933
2008
  toolCallId: input.event.toolCallId,
1934
2009
  output
@@ -2046,6 +2121,7 @@ var HarnessAgentSession = class {
2046
2121
  runtimeContext: options.runtimeContext,
2047
2122
  abortSignal: options.abortSignal,
2048
2123
  telemetry: options.telemetry,
2124
+ stopConditions: options.stopConditions,
2049
2125
  toolApproval: this.toolApproval,
2050
2126
  pendingToolApprovals: this.getPendingToolApprovals(),
2051
2127
  pendingToolResults: this.getPendingToolResults(),
@@ -2068,7 +2144,8 @@ var HarnessAgentSession = class {
2068
2144
  },
2069
2145
  onTurnFailed: () => {
2070
2146
  this.finishTrackedTurn({ turnId });
2071
- }
2147
+ },
2148
+ onStopConditionMet: () => this.captureStopConditionBoundary({ session, turnId })
2072
2149
  });
2073
2150
  return turn;
2074
2151
  } catch (error) {
@@ -2096,6 +2173,7 @@ var HarnessAgentSession = class {
2096
2173
  runtimeContext: options.runtimeContext,
2097
2174
  abortSignal: options.abortSignal,
2098
2175
  telemetry: options.telemetry,
2176
+ stopConditions: options.stopConditions,
2099
2177
  toolApproval: this.toolApproval,
2100
2178
  pendingToolApprovals: this.getPendingToolApprovals(),
2101
2179
  pendingToolResults: this.getPendingToolResults(),
@@ -2120,7 +2198,8 @@ var HarnessAgentSession = class {
2120
2198
  },
2121
2199
  onTurnFailed: () => {
2122
2200
  this.finishTrackedTurn({ turnId });
2123
- }
2201
+ },
2202
+ onStopConditionMet: () => this.captureStopConditionBoundary({ session, turnId })
2124
2203
  });
2125
2204
  return turn;
2126
2205
  } catch (error) {
@@ -2286,14 +2365,25 @@ var HarnessAgentSession = class {
2286
2365
  };
2287
2366
  }
2288
2367
  async suspendCurrentTurn(options) {
2289
- const raw = await options.session.doSuspendTurn();
2290
- const validated = await validateLifecycleStateData({
2291
- harness: this.harness,
2292
- state: raw,
2293
- expectedType: "continue-turn"
2294
- });
2368
+ var _a3;
2369
+ (_a3 = this.suspendedTurnState) != null ? _a3 : this.suspendedTurnState = (async () => {
2370
+ const raw = await options.session.doSuspendTurn();
2371
+ const validated = await validateLifecycleStateData({
2372
+ harness: this.harness,
2373
+ state: raw,
2374
+ expectedType: "continue-turn"
2375
+ });
2376
+ return this.addPendingToolState(validated);
2377
+ })();
2378
+ const state = await this.suspendedTurnState;
2295
2379
  this.turnState = "suspended";
2296
- return this.addPendingToolState(validated);
2380
+ return state;
2381
+ }
2382
+ async captureStopConditionBoundary(options) {
2383
+ if (this.sessionState !== "active" || this.activeTurnSequence !== options.turnId) {
2384
+ return;
2385
+ }
2386
+ await this.suspendCurrentTurn({ session: options.session });
2297
2387
  }
2298
2388
  toResumeStateWithContinuation(options) {
2299
2389
  const { continueFrom } = options;
@@ -2342,6 +2432,7 @@ var HarnessAgentSession = class {
2342
2432
  startTrackedTurn() {
2343
2433
  const turnId = ++this.turnSequence;
2344
2434
  this.activeTurnSequence = turnId;
2435
+ this.suspendedTurnState = void 0;
2345
2436
  this.turnState = "running";
2346
2437
  return turnId;
2347
2438
  }
@@ -2350,6 +2441,7 @@ var HarnessAgentSession = class {
2350
2441
  if (this.activeTurnSequence !== options.turnId) return;
2351
2442
  this.pendingToolApprovals.clear();
2352
2443
  this.pendingToolResults.clear();
2444
+ this.suspendedTurnState = void 0;
2353
2445
  this.turnState = "idle";
2354
2446
  }
2355
2447
  endLocalHandle(options) {
@@ -2870,6 +2962,7 @@ var HarnessAgent = class {
2870
2962
  const sandboxConfig = resolveSandboxConfig(settings);
2871
2963
  validateSandboxBootstrapSettings(sandboxConfig);
2872
2964
  this.settings = settings;
2965
+ this.stopConditions = settings.stopWhen == null ? [] : asArray2(settings.stopWhen);
2873
2966
  this.sandboxConfig = sandboxConfig;
2874
2967
  this.id = settings.id;
2875
2968
  const userTools = (_a3 = settings.tools) != null ? _a3 : {};
@@ -3117,6 +3210,7 @@ var HarnessAgent = class {
3117
3210
  runtimeContext: input.runtimeContext,
3118
3211
  abortSignal: input.abortSignal,
3119
3212
  telemetry: this.settings.telemetry,
3213
+ stopConditions: this.stopConditions,
3120
3214
  toolApprovalContinuations: input.turnInput.toolApprovalContinuations,
3121
3215
  toolResultContinuations: input.turnInput.toolResultContinuations
3122
3216
  });
@@ -3130,7 +3224,8 @@ var HarnessAgent = class {
3130
3224
  builtinToolFiltering: this.builtinToolFiltering,
3131
3225
  runtimeContext: input.runtimeContext,
3132
3226
  abortSignal: input.abortSignal,
3133
- telemetry: this.settings.telemetry
3227
+ telemetry: this.settings.telemetry,
3228
+ stopConditions: this.stopConditions
3134
3229
  });
3135
3230
  }
3136
3231
  async _acquireSandbox(input) {