@ai-sdk/harness 1.0.39 → 1.0.41

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.
@@ -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
@@ -918,19 +919,22 @@ function stripDeep(value, workDir) {
918
919
  import { generateId as generateId3 } from "@ai-sdk/provider-utils";
919
920
  import { createTelemetryDispatcher } from "ai/internal";
920
921
  var NOOP = {
921
- start() {
922
+ async start() {
922
923
  },
923
- ensureStepOpen() {
924
+ async ensureStepOpen() {
924
925
  },
925
- stepFinish() {
926
+ async stepFinish() {
926
927
  },
927
- toolStart() {
928
+ async toolStart() {
928
929
  },
929
- toolEnd() {
930
+ async executeTool({ execute }) {
931
+ return await execute();
930
932
  },
931
- end() {
933
+ async toolEnd() {
932
934
  },
933
- error() {
935
+ async end() {
936
+ },
937
+ async error() {
934
938
  }
935
939
  };
936
940
  function createTurnTelemetry(opts) {
@@ -950,11 +954,11 @@ function createTurnTelemetry(opts) {
950
954
  let ended = false;
951
955
  const openTools = /* @__PURE__ */ new Map();
952
956
  const cast = (event) => event;
953
- const fireStart = () => {
957
+ const fireStart = async () => {
954
958
  var _a4;
955
959
  if (started) return;
956
960
  started = true;
957
- (_a4 = dispatcher.onStart) == null ? void 0 : _a4.call(
961
+ await ((_a4 = dispatcher.onStart) == null ? void 0 : _a4.call(
958
962
  dispatcher,
959
963
  cast({
960
964
  callId,
@@ -974,19 +978,19 @@ function createTurnTelemetry(opts) {
974
978
  instructions: opts.instructions,
975
979
  messages: inputMessages
976
980
  })
977
- );
981
+ ));
978
982
  };
979
- const start = (overrideModelId) => {
983
+ const start = async (overrideModelId) => {
980
984
  if (started) return;
981
985
  if (overrideModelId) modelId = overrideModelId;
982
- fireStart();
986
+ await fireStart();
983
987
  };
984
- const ensureStepOpen = () => {
988
+ const ensureStepOpen = async () => {
985
989
  var _a4, _b3;
986
- if (!started) fireStart();
990
+ if (!started) await fireStart();
987
991
  if (stepOpen || ended) return;
988
992
  stepOpen = true;
989
- (_a4 = dispatcher.onStepStart) == null ? void 0 : _a4.call(
993
+ await ((_a4 = dispatcher.onStepStart) == null ? void 0 : _a4.call(
990
994
  dispatcher,
991
995
  cast({
992
996
  callId,
@@ -1002,8 +1006,8 @@ function createTurnTelemetry(opts) {
1002
1006
  runtimeContext,
1003
1007
  messages: inputMessages
1004
1008
  })
1005
- );
1006
- (_b3 = dispatcher.onLanguageModelCallStart) == null ? void 0 : _b3.call(
1009
+ ));
1010
+ await ((_b3 = dispatcher.onLanguageModelCallStart) == null ? void 0 : _b3.call(
1007
1011
  dispatcher,
1008
1012
  cast({
1009
1013
  callId,
@@ -1012,11 +1016,11 @@ function createTurnTelemetry(opts) {
1012
1016
  messages: inputMessages,
1013
1017
  tools: void 0
1014
1018
  })
1015
- );
1019
+ ));
1016
1020
  };
1017
- const inferenceEnd = (info) => {
1021
+ const inferenceEnd = async (info) => {
1018
1022
  var _a4;
1019
- (_a4 = dispatcher.onLanguageModelCallEnd) == null ? void 0 : _a4.call(
1023
+ await ((_a4 = dispatcher.onLanguageModelCallEnd) == null ? void 0 : _a4.call(
1020
1024
  dispatcher,
1021
1025
  cast({
1022
1026
  callId,
@@ -1025,12 +1029,12 @@ function createTurnTelemetry(opts) {
1025
1029
  usage: info.usage,
1026
1030
  content: info.content
1027
1031
  })
1028
- );
1032
+ ));
1029
1033
  };
1030
- const closeOpenTools = () => {
1034
+ const closeOpenTools = async () => {
1031
1035
  var _a4;
1032
1036
  for (const call of openTools.values()) {
1033
- (_a4 = dispatcher.onToolExecutionEnd) == null ? void 0 : _a4.call(
1037
+ await ((_a4 = dispatcher.onToolExecutionEnd) == null ? void 0 : _a4.call(
1034
1038
  dispatcher,
1035
1039
  cast({
1036
1040
  callId,
@@ -1046,24 +1050,24 @@ function createTurnTelemetry(opts) {
1046
1050
  toolContext: void 0,
1047
1051
  toolOutput: { type: "error", error: new Error("tool span unclosed") }
1048
1052
  })
1049
- );
1053
+ ));
1050
1054
  }
1051
1055
  openTools.clear();
1052
1056
  };
1053
1057
  return {
1054
1058
  start,
1055
1059
  ensureStepOpen,
1056
- stepFinish(info) {
1060
+ async stepFinish(info) {
1057
1061
  var _a4, _b3;
1058
1062
  if (!stepOpen) return;
1059
1063
  const content = (_a4 = info.content) != null ? _a4 : [];
1060
- closeOpenTools();
1061
- inferenceEnd({
1064
+ await closeOpenTools();
1065
+ await inferenceEnd({
1062
1066
  finishReason: info.finishReason,
1063
1067
  usage: info.usage,
1064
1068
  content
1065
1069
  });
1066
- (_b3 = dispatcher.onStepEnd) == null ? void 0 : _b3.call(
1070
+ await ((_b3 = dispatcher.onStepEnd) == null ? void 0 : _b3.call(
1067
1071
  dispatcher,
1068
1072
  cast({
1069
1073
  callId,
@@ -1079,15 +1083,16 @@ function createTurnTelemetry(opts) {
1079
1083
  messages: []
1080
1084
  }
1081
1085
  })
1082
- );
1086
+ ));
1083
1087
  stepOpen = false;
1084
1088
  stepNumber += 1;
1085
1089
  },
1086
- toolStart(call) {
1090
+ async toolStart(call) {
1087
1091
  var _a4;
1088
- ensureStepOpen();
1092
+ await 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,14 +1106,18 @@ 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
- toolEnd(toolCallId, output) {
1115
+ async toolEnd(toolCallId, output) {
1107
1116
  var _a4;
1108
1117
  const call = openTools.get(toolCallId);
1109
1118
  if (call == null) return;
1110
1119
  openTools.delete(toolCallId);
1111
- (_a4 = dispatcher.onToolExecutionEnd) == null ? void 0 : _a4.call(
1120
+ await ((_a4 = dispatcher.onToolExecutionEnd) == null ? void 0 : _a4.call(
1112
1121
  dispatcher,
1113
1122
  cast({
1114
1123
  callId,
@@ -1124,20 +1133,20 @@ function createTurnTelemetry(opts) {
1124
1133
  toolContext: void 0,
1125
1134
  toolOutput: output.ok ? { type: "tool-result", output: output.output } : { type: "error", error: output.error }
1126
1135
  })
1127
- );
1136
+ ));
1128
1137
  },
1129
- end(info) {
1138
+ async end(info) {
1130
1139
  var _a4, _b3;
1131
1140
  if (ended) return;
1132
- if (!started) fireStart();
1141
+ if (!started) await fireStart();
1133
1142
  if (stepOpen) {
1134
- closeOpenTools();
1135
- inferenceEnd({
1143
+ await closeOpenTools();
1144
+ await inferenceEnd({
1136
1145
  finishReason: info.finishReason,
1137
1146
  usage: info.usage,
1138
1147
  content: []
1139
1148
  });
1140
- (_a4 = dispatcher.onStepEnd) == null ? void 0 : _a4.call(
1149
+ await ((_a4 = dispatcher.onStepEnd) == null ? void 0 : _a4.call(
1141
1150
  dispatcher,
1142
1151
  cast({
1143
1152
  callId,
@@ -1153,11 +1162,11 @@ function createTurnTelemetry(opts) {
1153
1162
  messages: []
1154
1163
  }
1155
1164
  })
1156
- );
1165
+ ));
1157
1166
  stepOpen = false;
1158
1167
  }
1159
1168
  ended = true;
1160
- (_b3 = dispatcher.onEnd) == null ? void 0 : _b3.call(
1169
+ await ((_b3 = dispatcher.onEnd) == null ? void 0 : _b3.call(
1161
1170
  dispatcher,
1162
1171
  cast({
1163
1172
  callId,
@@ -1175,15 +1184,15 @@ function createTurnTelemetry(opts) {
1175
1184
  },
1176
1185
  runtimeContext
1177
1186
  })
1178
- );
1187
+ ));
1179
1188
  },
1180
- error(err) {
1189
+ async error(err) {
1181
1190
  var _a4;
1182
1191
  if (ended) return;
1183
- if (!started) fireStart();
1184
- closeOpenTools();
1192
+ if (!started) await fireStart();
1193
+ await closeOpenTools();
1185
1194
  ended = true;
1186
- (_a4 = dispatcher.onError) == null ? void 0 : _a4.call(dispatcher, err);
1195
+ await ((_a4 = dispatcher.onError) == null ? void 0 : _a4.call(dispatcher, err));
1187
1196
  }
1188
1197
  };
1189
1198
  }
@@ -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({
@@ -1330,7 +1353,7 @@ function runPrompt(input) {
1330
1353
  }
1331
1354
  });
1332
1355
  } catch (err) {
1333
- telemetry.error(err);
1356
+ await telemetry.error(err);
1334
1357
  logBridgeError({
1335
1358
  harnessId: input.harness.harnessId,
1336
1359
  sessionId: input.session.sessionId,
@@ -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 = [];
@@ -1403,30 +1433,32 @@ function runPrompt(input) {
1403
1433
  unified: "tool-calls",
1404
1434
  raw: void 0
1405
1435
  };
1406
- const completeStep = (input2) => {
1407
- telemetry.stepFinish({
1436
+ const completeStep = async (input2) => {
1437
+ await telemetry.stepFinish({
1408
1438
  finishReason: input2.finishReason,
1409
1439
  usage: input2.usage,
1410
1440
  providerMetadata: input2.providerMetadata,
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) {
1423
- completeStep({
1455
+ await completeStep({
1424
1456
  finishReason: toolCallsFinishReason,
1425
1457
  usage: zeroUsage,
1426
1458
  providerMetadata: void 0
1427
1459
  });
1428
1460
  }
1429
- telemetry.end({
1461
+ await telemetry.end({
1430
1462
  finishReason: toolCallsFinishReason,
1431
1463
  usage: zeroUsage
1432
1464
  });
@@ -1517,9 +1549,16 @@ function runPrompt(input) {
1517
1549
  toolName: approval.toolName,
1518
1550
  input: approval.input
1519
1551
  };
1552
+ await 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,
@@ -1548,7 +1587,7 @@ function runPrompt(input) {
1548
1587
  await finishForHostInputPause({ completeCurrentStep: false });
1549
1588
  return "awaiting-tool-result";
1550
1589
  }
1551
- telemetry.toolEnd(rawToolCall.toolCallId, execution.outcome);
1590
+ await telemetry.toolEnd(rawToolCall.toolCallId, execution.outcome);
1552
1591
  return "continued";
1553
1592
  };
1554
1593
  try {
@@ -1577,13 +1616,34 @@ 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
+ await 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
+ await 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
- telemetry.ensureStepOpen();
1646
+ await telemetry.ensureStepOpen();
1587
1647
  }
1588
1648
  const displayValue = stripWorkDir(value, input.sessionWorkDir);
1589
1649
  const settledHostInputReplay = (displayValue.type === "tool-call" || displayValue.type === "tool-result" || displayValue.type === "tool-approval-request") && settledHostToolCallIds.has(displayValue.toolCallId);
@@ -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
@@ -1627,7 +1687,7 @@ function runPrompt(input) {
1627
1687
  }
1628
1688
  }
1629
1689
  if (value.type === "error" && displayValue.type === "error") {
1630
- telemetry.error(value.error);
1690
+ await telemetry.error(value.error);
1631
1691
  logBridgeError({
1632
1692
  harnessId: input.harness.harnessId,
1633
1693
  sessionId: input.session.sessionId,
@@ -1662,14 +1722,14 @@ 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
1669
1729
  });
1670
1730
  }
1671
1731
  if (value.type === "tool-result") {
1672
- telemetry.toolEnd(
1732
+ await telemetry.toolEnd(
1673
1733
  value.toolCallId,
1674
1734
  value.isError ? { ok: false, error: value.result } : { ok: true, output: value.result }
1675
1735
  );
@@ -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(
@@ -1720,15 +1780,22 @@ function runPrompt(input) {
1720
1780
  return;
1721
1781
  }
1722
1782
  if (value.type === "finish-step") {
1723
- completeStep({
1783
+ await completeStep({
1724
1784
  finishReason: value.finishReason,
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;
1731
- telemetry.end({
1798
+ await telemetry.end({
1732
1799
  finishReason: value.finishReason,
1733
1800
  usage: value.totalUsage
1734
1801
  });
@@ -1752,7 +1819,7 @@ function runPrompt(input) {
1752
1819
  toolCallId: toolCall.toolCallId,
1753
1820
  output
1754
1821
  });
1755
- telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
1822
+ await telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
1756
1823
  continue;
1757
1824
  }
1758
1825
  const customToolApprovalDecision = resolveCustomToolApproval({
@@ -1781,10 +1848,10 @@ function runPrompt(input) {
1781
1848
  toolCallId: toolCall.toolCallId,
1782
1849
  output
1783
1850
  });
1784
- telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
1851
+ await 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,
@@ -1861,13 +1929,13 @@ function runPrompt(input) {
1861
1929
  await finishForHostInputPause({ completeCurrentStep: true });
1862
1930
  return;
1863
1931
  }
1864
- telemetry.toolEnd(toolCall.toolCallId, execution.outcome);
1932
+ await telemetry.toolEnd(toolCall.toolCallId, execution.outcome);
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 ? {
@@ -1877,7 +1945,7 @@ function runPrompt(input) {
1877
1945
  } : void 0
1878
1946
  );
1879
1947
  } catch (err) {
1880
- telemetry.error(err);
1948
+ await telemetry.error(err);
1881
1949
  logBridgeError({
1882
1950
  harnessId: input.harness.harnessId,
1883
1951
  sessionId: input.session.sessionId,
@@ -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
@@ -1951,6 +2026,7 @@ async function validateToolCall(args) {
1951
2026
  toolName: event.toolName,
1952
2027
  input: event.input,
1953
2028
  ...event.providerExecuted !== void 0 ? { providerExecuted: event.providerExecuted } : {},
2029
+ ...event.dynamic !== void 0 ? { dynamic: event.dynamic } : {},
1954
2030
  ...event.providerMetadata !== void 0 ? { providerMetadata: event.providerMetadata } : {}
1955
2031
  };
1956
2032
  const parsed = await parseToolCall({
@@ -2046,6 +2122,7 @@ var HarnessAgentSession = class {
2046
2122
  runtimeContext: options.runtimeContext,
2047
2123
  abortSignal: options.abortSignal,
2048
2124
  telemetry: options.telemetry,
2125
+ stopConditions: options.stopConditions,
2049
2126
  toolApproval: this.toolApproval,
2050
2127
  pendingToolApprovals: this.getPendingToolApprovals(),
2051
2128
  pendingToolResults: this.getPendingToolResults(),
@@ -2068,7 +2145,8 @@ var HarnessAgentSession = class {
2068
2145
  },
2069
2146
  onTurnFailed: () => {
2070
2147
  this.finishTrackedTurn({ turnId });
2071
- }
2148
+ },
2149
+ onStopConditionMet: () => this.captureStopConditionBoundary({ session, turnId })
2072
2150
  });
2073
2151
  return turn;
2074
2152
  } catch (error) {
@@ -2096,6 +2174,7 @@ var HarnessAgentSession = class {
2096
2174
  runtimeContext: options.runtimeContext,
2097
2175
  abortSignal: options.abortSignal,
2098
2176
  telemetry: options.telemetry,
2177
+ stopConditions: options.stopConditions,
2099
2178
  toolApproval: this.toolApproval,
2100
2179
  pendingToolApprovals: this.getPendingToolApprovals(),
2101
2180
  pendingToolResults: this.getPendingToolResults(),
@@ -2120,7 +2199,8 @@ var HarnessAgentSession = class {
2120
2199
  },
2121
2200
  onTurnFailed: () => {
2122
2201
  this.finishTrackedTurn({ turnId });
2123
- }
2202
+ },
2203
+ onStopConditionMet: () => this.captureStopConditionBoundary({ session, turnId })
2124
2204
  });
2125
2205
  return turn;
2126
2206
  } catch (error) {
@@ -2286,14 +2366,25 @@ var HarnessAgentSession = class {
2286
2366
  };
2287
2367
  }
2288
2368
  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
- });
2369
+ var _a3;
2370
+ (_a3 = this.suspendedTurnState) != null ? _a3 : this.suspendedTurnState = (async () => {
2371
+ const raw = await options.session.doSuspendTurn();
2372
+ const validated = await validateLifecycleStateData({
2373
+ harness: this.harness,
2374
+ state: raw,
2375
+ expectedType: "continue-turn"
2376
+ });
2377
+ return this.addPendingToolState(validated);
2378
+ })();
2379
+ const state = await this.suspendedTurnState;
2295
2380
  this.turnState = "suspended";
2296
- return this.addPendingToolState(validated);
2381
+ return state;
2382
+ }
2383
+ async captureStopConditionBoundary(options) {
2384
+ if (this.sessionState !== "active" || this.activeTurnSequence !== options.turnId) {
2385
+ return;
2386
+ }
2387
+ await this.suspendCurrentTurn({ session: options.session });
2297
2388
  }
2298
2389
  toResumeStateWithContinuation(options) {
2299
2390
  const { continueFrom } = options;
@@ -2342,6 +2433,7 @@ var HarnessAgentSession = class {
2342
2433
  startTrackedTurn() {
2343
2434
  const turnId = ++this.turnSequence;
2344
2435
  this.activeTurnSequence = turnId;
2436
+ this.suspendedTurnState = void 0;
2345
2437
  this.turnState = "running";
2346
2438
  return turnId;
2347
2439
  }
@@ -2350,6 +2442,7 @@ var HarnessAgentSession = class {
2350
2442
  if (this.activeTurnSequence !== options.turnId) return;
2351
2443
  this.pendingToolApprovals.clear();
2352
2444
  this.pendingToolResults.clear();
2445
+ this.suspendedTurnState = void 0;
2353
2446
  this.turnState = "idle";
2354
2447
  }
2355
2448
  endLocalHandle(options) {
@@ -2870,6 +2963,7 @@ var HarnessAgent = class {
2870
2963
  const sandboxConfig = resolveSandboxConfig(settings);
2871
2964
  validateSandboxBootstrapSettings(sandboxConfig);
2872
2965
  this.settings = settings;
2966
+ this.stopConditions = settings.stopWhen == null ? [] : asArray2(settings.stopWhen);
2873
2967
  this.sandboxConfig = sandboxConfig;
2874
2968
  this.id = settings.id;
2875
2969
  const userTools = (_a3 = settings.tools) != null ? _a3 : {};
@@ -3117,6 +3211,7 @@ var HarnessAgent = class {
3117
3211
  runtimeContext: input.runtimeContext,
3118
3212
  abortSignal: input.abortSignal,
3119
3213
  telemetry: this.settings.telemetry,
3214
+ stopConditions: this.stopConditions,
3120
3215
  toolApprovalContinuations: input.turnInput.toolApprovalContinuations,
3121
3216
  toolResultContinuations: input.turnInput.toolResultContinuations
3122
3217
  });
@@ -3130,7 +3225,8 @@ var HarnessAgent = class {
3130
3225
  builtinToolFiltering: this.builtinToolFiltering,
3131
3226
  runtimeContext: input.runtimeContext,
3132
3227
  abortSignal: input.abortSignal,
3133
- telemetry: this.settings.telemetry
3228
+ telemetry: this.settings.telemetry,
3229
+ stopConditions: this.stopConditions
3134
3230
  });
3135
3231
  }
3136
3232
  async _acquireSandbox(input) {