@ai-sdk/harness 1.0.123 → 1.0.126

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.
@@ -521,7 +521,7 @@ var HarnessStreamTextResult = class {
521
521
  ]) {
522
522
  try {
523
523
  dp.reject(error);
524
- } catch (e) {
524
+ } catch {
525
525
  }
526
526
  }
527
527
  }
@@ -644,11 +644,10 @@ var HarnessStreamTextResult = class {
644
644
  );
645
645
  }
646
646
  get elementStream() {
647
- var _a4, _b4, _c;
648
- const transform = (_a4 = this.outputSpecification) == null ? void 0 : _a4.createElementStreamTransform();
647
+ const transform = this.outputSpecification?.createElementStreamTransform();
649
648
  if (transform == null) {
650
649
  throw notSupportedYet(
651
- `element streams in ${(_c = (_b4 = this.outputSpecification) == null ? void 0 : _b4.name) != null ? _c : "text"} mode`
650
+ `element streams in ${this.outputSpecification?.name ?? "text"} mode`
652
651
  );
653
652
  }
654
653
  return createAsyncIterableStream(
@@ -807,7 +806,6 @@ function createOutputTransformStream(output) {
807
806
  };
808
807
  return new TransformStream({
809
808
  async transform(chunk, controller) {
810
- var _a4;
811
809
  if (chunk.type === "finish-step" && textChunk.length > 0) {
812
810
  publishTextChunk({ controller });
813
811
  }
@@ -834,7 +832,7 @@ function createOutputTransformStream(output) {
834
832
  }
835
833
  text += chunk.text;
836
834
  textChunk += chunk.text;
837
- textProviderMetadata = (_a4 = chunk.providerMetadata) != null ? _a4 : textProviderMetadata;
835
+ textProviderMetadata = chunk.providerMetadata ?? textProviderMetadata;
838
836
  if (chunk.text.length === 0 && chunk.providerMetadata != null) {
839
837
  controller.enqueue({ part: chunk, partialOutput: void 0 });
840
838
  return;
@@ -880,7 +878,6 @@ function getOwn(obj, key) {
880
878
  // src/agent/internal/translate-stream-part.ts
881
879
  import { generateId } from "@ai-sdk/provider-utils";
882
880
  function translateStreamPart(event, options = {}) {
883
- var _a4, _b4;
884
881
  switch (event.type) {
885
882
  case "stream-start":
886
883
  return [];
@@ -943,7 +940,7 @@ function translateStreamPart(event, options = {}) {
943
940
  case "tool-approval-request":
944
941
  return [];
945
942
  case "tool-result":
946
- if (event.isError === true && ((_b4 = (_a4 = options.isProviderExecuted) == null ? void 0 : _a4.call(options, event.toolCallId)) != null ? _b4 : true)) {
943
+ if (event.isError === true && (options.isProviderExecuted?.(event.toolCallId) ?? true)) {
947
944
  return [
948
945
  {
949
946
  type: "tool-error",
@@ -1042,7 +1039,6 @@ function createToolInputWorkDirStripper({
1042
1039
  }) {
1043
1040
  const stateByToolCallId = /* @__PURE__ */ new Map();
1044
1041
  return (part) => {
1045
- var _a4;
1046
1042
  if (sessionWorkDir.length === 0) return [part];
1047
1043
  if (part.type === "tool-input-start") {
1048
1044
  stateByToolCallId.set(part.id, {
@@ -1052,7 +1048,7 @@ function createToolInputWorkDirStripper({
1052
1048
  return [part];
1053
1049
  }
1054
1050
  if (part.type === "tool-input-delta") {
1055
- const state2 = (_a4 = stateByToolCallId.get(part.id)) != null ? _a4 : {
1051
+ const state2 = stateByToolCallId.get(part.id) ?? {
1056
1052
  pending: "",
1057
1053
  precedingCharacter: void 0
1058
1054
  };
@@ -1103,6 +1099,45 @@ function stripWorkDir(part, sessionWorkDir) {
1103
1099
  return part;
1104
1100
  }
1105
1101
  }
1102
+ function stripParsedToolInputWorkDir({
1103
+ value,
1104
+ sessionWorkDir
1105
+ }) {
1106
+ if (sessionWorkDir.length === 0) return value;
1107
+ const projected = /* @__PURE__ */ new WeakMap();
1108
+ const pending = [];
1109
+ const project = (item) => {
1110
+ if (typeof item === "string") return stripString(item, sessionWorkDir);
1111
+ if (item === null || typeof item !== "object") return item;
1112
+ if (!Array.isArray(item) && Object.getPrototypeOf(item) !== Object.prototype && Object.getPrototypeOf(item) !== null) {
1113
+ return item;
1114
+ }
1115
+ if (projected.has(item)) return projected.get(item);
1116
+ const target = Array.isArray(item) ? new Array(item.length) : {};
1117
+ projected.set(item, target);
1118
+ pending.push({ source: item, target });
1119
+ return target;
1120
+ };
1121
+ const result = project(value);
1122
+ while (pending.length > 0) {
1123
+ const { source, target } = pending.pop();
1124
+ if (Array.isArray(source) && Array.isArray(target)) {
1125
+ for (let index = 0; index < source.length; index++) {
1126
+ if (index in source) target[index] = project(source[index]);
1127
+ }
1128
+ } else {
1129
+ for (const [key, item] of Object.entries(source)) {
1130
+ Object.defineProperty(target, key, {
1131
+ value: project(item),
1132
+ enumerable: true,
1133
+ writable: true,
1134
+ configurable: true
1135
+ });
1136
+ }
1137
+ }
1138
+ }
1139
+ return result;
1140
+ }
1106
1141
  function stripString(value, workDir) {
1107
1142
  return stripStreamingString({
1108
1143
  value,
@@ -1192,15 +1227,14 @@ import { createTelemetryDispatcher } from "ai/internal";
1192
1227
  async function notify(event, ...callbacks) {
1193
1228
  await Promise.allSettled(
1194
1229
  callbacks.map(async (callback) => {
1195
- await (callback == null ? void 0 : callback(event));
1230
+ await callback?.(event);
1196
1231
  })
1197
1232
  );
1198
1233
  }
1199
1234
  function createTurnLifecycle(options) {
1200
- var _a4;
1201
1235
  const telemetry = options.telemetry == null ? {} : createTelemetryDispatcher({ telemetry: options.telemetry });
1202
1236
  const provider = `harness:${options.harnessId}`;
1203
- let modelId = (_a4 = options.modelId) != null ? _a4 : "";
1237
+ let modelId = options.modelId ?? "";
1204
1238
  let started = false;
1205
1239
  let stepOpen = false;
1206
1240
  let stepNumber = 0;
@@ -1342,7 +1376,6 @@ function createTurnLifecycle(options) {
1342
1376
  );
1343
1377
  },
1344
1378
  async stepEnd(step) {
1345
- var _a5, _b4, _c;
1346
1379
  if (!stepOpen) return;
1347
1380
  completedSteps.push(step);
1348
1381
  const telemetryStepEndEvent = Object.assign(/* @__PURE__ */ Object.create(null), {
@@ -1373,8 +1406,8 @@ function createTurnLifecycle(options) {
1373
1406
  dynamicToolResults: step.dynamicToolResults
1374
1407
  });
1375
1408
  await Promise.allSettled([
1376
- (_b4 = (_a5 = options.callbacks).onStepEnd) == null ? void 0 : _b4.call(_a5, step),
1377
- (_c = telemetry.onStepEnd) == null ? void 0 : _c.call(telemetry, telemetryStepEndEvent)
1409
+ options.callbacks.onStepEnd?.(step),
1410
+ telemetry.onStepEnd?.(telemetryStepEndEvent)
1378
1411
  ]);
1379
1412
  stepOpen = false;
1380
1413
  stepNumber += 1;
@@ -1406,10 +1439,7 @@ function createTurnLifecycle(options) {
1406
1439
  rawFinishReason: finalStep.rawFinishReason,
1407
1440
  usage,
1408
1441
  totalUsage: usage,
1409
- warnings: steps.flatMap((step) => {
1410
- var _a5;
1411
- return (_a5 = step.warnings) != null ? _a5 : [];
1412
- }),
1442
+ warnings: steps.flatMap((step) => step.warnings ?? []),
1413
1443
  request: finalStep.request,
1414
1444
  response: finalStep.response,
1415
1445
  providerMetadata: finalStep.providerMetadata,
@@ -1432,11 +1462,10 @@ function createTurnLifecycle(options) {
1432
1462
  });
1433
1463
  },
1434
1464
  async error(error) {
1435
- var _a5;
1436
1465
  if (ended) return;
1437
1466
  if (!started) await start();
1438
1467
  ended = true;
1439
- await ((_a5 = telemetry.onError) == null ? void 0 : _a5.call(telemetry, error));
1468
+ await telemetry.onError?.(error);
1440
1469
  }
1441
1470
  };
1442
1471
  }
@@ -1444,16 +1473,14 @@ function createTurnLifecycle(options) {
1444
1473
  // src/agent/internal/permission-mode.ts
1445
1474
  var DEFAULT_PERMISSION_MODE = "allow-all";
1446
1475
  function resolvePermissionMode(input) {
1447
- var _a4;
1448
- return (_a4 = input.permissionMode) != null ? _a4 : DEFAULT_PERMISSION_MODE;
1476
+ return input.permissionMode ?? DEFAULT_PERMISSION_MODE;
1449
1477
  }
1450
1478
  function permissionModeNeedsBuiltinSupport(input) {
1451
1479
  return input.permissionMode !== "allow-all";
1452
1480
  }
1453
1481
  function resolveCustomToolApproval(input) {
1454
- var _a4;
1455
1482
  const status = normalizeToolApprovalStatus({
1456
- status: (_a4 = input.toolApproval) == null ? void 0 : _a4[input.toolName]
1483
+ status: input.toolApproval?.[input.toolName]
1457
1484
  });
1458
1485
  switch (status.type) {
1459
1486
  case "not-applicable":
@@ -1479,24 +1506,23 @@ function stringifyUnknown(value) {
1479
1506
  if (typeof value === "string") return value;
1480
1507
  try {
1481
1508
  return JSON.stringify(value);
1482
- } catch (e) {
1509
+ } catch {
1483
1510
  return String(value);
1484
1511
  }
1485
1512
  }
1486
1513
  function formatBridgeError(error) {
1487
- var _a4, _b4;
1488
1514
  if (error instanceof Error) {
1489
- return (_a4 = error.stack) != null ? _a4 : `${error.name}: ${error.message}`;
1515
+ return error.stack ?? `${error.name}: ${error.message}`;
1490
1516
  }
1491
1517
  if (isSerializedError(error)) {
1492
- return (_b4 = error.stack) != null ? _b4 : `${error.name ? `${error.name}: ` : ""}${error.message}`;
1518
+ return error.stack ?? `${error.name ? `${error.name}: ` : ""}${error.message}`;
1493
1519
  }
1494
1520
  return stringifyUnknown(error);
1495
1521
  }
1496
1522
  function writeToStderr(line) {
1497
1523
  try {
1498
1524
  process.stderr.write(line);
1499
- } catch (e) {
1525
+ } catch {
1500
1526
  }
1501
1527
  }
1502
1528
  function logBridgeError({
@@ -1525,12 +1551,12 @@ var sandboxChannelEventCheckpointSymbol = /* @__PURE__ */ Symbol.for(
1525
1551
  "vercel.ai.harness.sandboxChannelEventCheckpoint"
1526
1552
  );
1527
1553
  function pinSandboxChannelEventCheckpoint(event) {
1528
- var _a4;
1529
1554
  if (event == null || typeof event !== "object") return void 0;
1530
- return (_a4 = event[sandboxChannelEventCheckpointSymbol]) == null ? void 0 : _a4.pin();
1555
+ return event[sandboxChannelEventCheckpointSymbol]?.pin();
1531
1556
  }
1532
1557
 
1533
1558
  // src/agent/internal/run-prompt.ts
1559
+ var invalidToolInputMessage = "Tool input validation failed.";
1534
1560
  function unwrapToolResultOutput(toolResult) {
1535
1561
  switch (toolResult.output.type) {
1536
1562
  case "text":
@@ -1551,29 +1577,28 @@ function unwrapToolResultOutput(toolResult) {
1551
1577
  }
1552
1578
  }
1553
1579
  function runPrompt(input) {
1554
- var _a4, _b4, _c, _d, _e, _f, _g, _h, _i, _j;
1555
1580
  const callId = generateId2();
1556
- const toolsContext = (_a4 = input.toolsContext) != null ? _a4 : {};
1581
+ const toolsContext = input.toolsContext ?? {};
1557
1582
  const result = new HarnessStreamTextResult({
1558
1583
  tools: input.tools,
1559
1584
  runtimeContext: input.runtimeContext,
1560
1585
  toolsContext,
1561
1586
  harnessId: input.harness.harnessId,
1562
1587
  callId,
1563
- modelId: (_b4 = input.model) != null ? _b4 : "",
1588
+ modelId: input.model ?? "",
1564
1589
  output: input.output
1565
1590
  });
1566
- const pendingToolApprovals = (_c = input.pendingToolApprovals) != null ? _c : [];
1567
- const pendingToolResults = (_d = input.pendingToolResults) != null ? _d : [];
1568
- const onPendingToolApproval = (_e = input.onPendingToolApproval) != null ? _e : (() => {
1591
+ const pendingToolApprovals = input.pendingToolApprovals ?? [];
1592
+ const pendingToolResults = input.pendingToolResults ?? [];
1593
+ const onPendingToolApproval = input.onPendingToolApproval ?? (() => {
1569
1594
  });
1570
- const onToolApprovalSettled = (_f = input.onToolApprovalSettled) != null ? _f : (() => {
1595
+ const onToolApprovalSettled = input.onToolApprovalSettled ?? (() => {
1571
1596
  });
1572
- const onPendingToolResult = (_g = input.onPendingToolResult) != null ? _g : (() => {
1597
+ const onPendingToolResult = input.onPendingToolResult ?? (() => {
1573
1598
  });
1574
- const onToolResultSettled = (_h = input.onToolResultSettled) != null ? _h : (() => {
1599
+ const onToolResultSettled = input.onToolResultSettled ?? (() => {
1575
1600
  });
1576
- const activeTools = (_i = input.activeTools) != null ? _i : input.tools;
1601
+ const activeTools = input.activeTools ?? input.tools;
1577
1602
  const activeToolNames = Object.keys(input.tools).filter(
1578
1603
  (toolName) => Object.prototype.hasOwnProperty.call(activeTools, toolName) || Object.prototype.hasOwnProperty.call(
1579
1604
  input.harness.builtinTools,
@@ -1586,7 +1611,7 @@ function runPrompt(input) {
1586
1611
  const lifecycle = createTurnLifecycle({
1587
1612
  callId,
1588
1613
  telemetry: input.telemetry,
1589
- callbacks: (_j = input.callbacks) != null ? _j : {},
1614
+ callbacks: input.callbacks ?? {},
1590
1615
  harnessId: input.harness.harnessId,
1591
1616
  modelId: input.model,
1592
1617
  instructions: input.instructions,
@@ -1599,11 +1624,10 @@ function runPrompt(input) {
1599
1624
  output: input.output
1600
1625
  });
1601
1626
  const settleFailure = (err) => {
1602
- var _a5, _b5, _c2;
1603
- if (!((_a5 = input.isTurnSuspending) == null ? void 0 : _a5.call(input))) {
1604
- (_b5 = input.onTurnFailed) == null ? void 0 : _b5.call(input);
1627
+ if (!input.isTurnSuspending?.()) {
1628
+ input.onTurnFailed?.();
1605
1629
  }
1606
- if ((_c2 = input.abortSignal) == null ? void 0 : _c2.aborted) {
1630
+ if (input.abortSignal?.aborted) {
1607
1631
  result.abort({
1608
1632
  error: err,
1609
1633
  ...input.abortSignal.reason !== void 0 ? { reason: getErrorMessage(input.abortSignal.reason) } : {}
@@ -1613,23 +1637,18 @@ function runPrompt(input) {
1613
1637
  result.fail(err);
1614
1638
  };
1615
1639
  const done = (async () => {
1616
- var _a5, _b5, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k, _l, _m, _n, _o;
1617
1640
  let bridge;
1618
1641
  try {
1619
1642
  bridge = await toHarnessStream({
1620
- invoke: input.mode === "continue" ? (emit) => {
1621
- var _a6;
1622
- return input.session.doContinueTurn({
1623
- model: input.model,
1624
- skills: (_a6 = input.skills) != null ? _a6 : [],
1625
- responseFormat: input.responseFormat,
1626
- tools: input.toolSpecs,
1627
- instructions: input.instructions,
1628
- abortSignal: input.abortSignal,
1629
- emit
1630
- });
1631
- } : (emit) => {
1632
- var _a6;
1643
+ invoke: input.mode === "continue" ? (emit) => input.session.doContinueTurn({
1644
+ model: input.model,
1645
+ skills: input.skills ?? [],
1646
+ responseFormat: input.responseFormat,
1647
+ tools: input.toolSpecs,
1648
+ instructions: input.instructions,
1649
+ abortSignal: input.abortSignal,
1650
+ emit
1651
+ }) : (emit) => {
1633
1652
  if (input.prompt == null) {
1634
1653
  throw new Error(
1635
1654
  'runPrompt: `prompt` is required for mode "prompt".'
@@ -1638,7 +1657,7 @@ function runPrompt(input) {
1638
1657
  return input.session.doPromptTurn({
1639
1658
  prompt: input.prompt,
1640
1659
  model: input.model,
1641
- skills: (_a6 = input.skills) != null ? _a6 : [],
1660
+ skills: input.skills ?? [],
1642
1661
  responseFormat: input.responseFormat,
1643
1662
  tools: input.toolSpecs,
1644
1663
  instructions: input.instructions,
@@ -1659,7 +1678,7 @@ function runPrompt(input) {
1659
1678
  return;
1660
1679
  }
1661
1680
  const { stream, control } = bridge;
1662
- (_a5 = input.onPromptControlAvailable) == null ? void 0 : _a5.call(input, control);
1681
+ input.onPromptControlAvailable?.(control);
1663
1682
  const reader = stream.getReader();
1664
1683
  const stripToolInputWorkDir = createToolInputWorkDirStripper({
1665
1684
  sessionWorkDir: input.sessionWorkDir
@@ -1679,7 +1698,7 @@ function runPrompt(input) {
1679
1698
  pendingToolApprovals.map((approval) => [approval.toolCallId, approval])
1680
1699
  );
1681
1700
  const continuationsByApprovalId = new Map(
1682
- ((_b5 = input.toolApprovalContinuations) != null ? _b5 : []).map((continuation) => [
1701
+ (input.toolApprovalContinuations ?? []).map((continuation) => [
1683
1702
  continuation.approvalId,
1684
1703
  continuation
1685
1704
  ])
@@ -1691,7 +1710,7 @@ function runPrompt(input) {
1691
1710
  ])
1692
1711
  );
1693
1712
  const continuationsByToolCallId = new Map(
1694
- ((_c2 = input.toolResultContinuations) != null ? _c2 : []).map((continuation) => [
1713
+ (input.toolResultContinuations ?? []).map((continuation) => [
1695
1714
  continuation.toolCallId,
1696
1715
  continuation
1697
1716
  ])
@@ -1720,8 +1739,7 @@ function runPrompt(input) {
1720
1739
  }
1721
1740
  };
1722
1741
  const releasePendingStopBoundary = () => {
1723
- var _a6;
1724
- (_a6 = pendingStopBoundary == null ? void 0 : pendingStopBoundary.releaseCheckpoint) == null ? void 0 : _a6.call(pendingStopBoundary);
1742
+ pendingStopBoundary?.releaseCheckpoint?.();
1725
1743
  pendingStopBoundary = void 0;
1726
1744
  };
1727
1745
  let stepText = "";
@@ -1732,7 +1750,6 @@ function runPrompt(input) {
1732
1750
  let bufferedToolOutcomes = [];
1733
1751
  const toolExecutions = /* @__PURE__ */ new Map();
1734
1752
  const publishToolExecutions = async () => {
1735
- var _a6;
1736
1753
  for (const execution of toolExecutions.values()) {
1737
1754
  if (execution.toolOutput == null) continue;
1738
1755
  await lifecycle.toolExecutionStart({
@@ -1741,7 +1758,7 @@ function runPrompt(input) {
1741
1758
  await lifecycle.toolExecutionEnd({
1742
1759
  toolCall: execution.toolCall,
1743
1760
  toolOutput: execution.toolOutput,
1744
- toolExecutionMs: (_a6 = execution.toolExecutionMs) != null ? _a6 : 0
1761
+ toolExecutionMs: execution.toolExecutionMs ?? 0
1745
1762
  });
1746
1763
  }
1747
1764
  for (const publish of bufferedToolOutcomes) publish();
@@ -1856,8 +1873,7 @@ function runPrompt(input) {
1856
1873
  });
1857
1874
  };
1858
1875
  const recordPendingToolResult = (options) => {
1859
- var _a6;
1860
- const pendingResult = (_a6 = pendingResultsByToolCallId.get(options.toolCall.toolCallId)) != null ? _a6 : {
1876
+ const pendingResult = pendingResultsByToolCallId.get(options.toolCall.toolCallId) ?? {
1861
1877
  toolCallId: options.toolCall.toolCallId,
1862
1878
  toolName: options.toolCall.toolName,
1863
1879
  input: options.toolCall.input,
@@ -1896,11 +1912,10 @@ function runPrompt(input) {
1896
1912
  });
1897
1913
  };
1898
1914
  const submitToolResult = async (submission) => {
1899
- var _a6, _b6, _c3;
1900
- if (!((_a6 = input.isTurnSuspending) == null ? void 0 : _a6.call(input))) {
1915
+ if (!input.isTurnSuspending?.()) {
1901
1916
  return control.submitToolResult(submission);
1902
1917
  }
1903
- const toolCall = (_c3 = (_b6 = rawToolCallsByToolCallId.get(submission.toolCallId)) != null ? _b6 : pendingResultsByToolCallId.get(submission.toolCallId)) != null ? _c3 : pendingToolApprovals.find(
1918
+ const toolCall = rawToolCallsByToolCallId.get(submission.toolCallId) ?? pendingResultsByToolCallId.get(submission.toolCallId) ?? pendingToolApprovals.find(
1904
1919
  (approval) => approval.toolCallId === submission.toolCallId
1905
1920
  );
1906
1921
  if (toolCall == null) {
@@ -1944,8 +1959,7 @@ function runPrompt(input) {
1944
1959
  pendingResultsByToolCallId.delete(pendingResult.toolCallId);
1945
1960
  };
1946
1961
  const processPendingApprovalContinuation = async (approval, continuation) => {
1947
- var _a6;
1948
- const rawToolCall = (_a6 = rawToolCallsByToolCallId.get(approval.toolCallId)) != null ? _a6 : {
1962
+ const rawToolCall = (approval.kind === "builtin" ? rawToolCallsByToolCallId.get(approval.toolCallId) : void 0) ?? {
1949
1963
  type: "tool-call",
1950
1964
  toolCallId: approval.toolCallId,
1951
1965
  toolName: approval.toolName,
@@ -1953,14 +1967,29 @@ function runPrompt(input) {
1953
1967
  providerExecuted: approval.providerExecuted,
1954
1968
  nativeName: approval.nativeName
1955
1969
  };
1956
- const parsedInput = await safeParseJSON2({ text: rawToolCall.input });
1957
- const toolCall = {
1958
- type: "tool-call",
1959
- toolCallId: rawToolCall.toolCallId,
1960
- toolName: rawToolCall.toolName,
1961
- input: parsedInput.success ? parsedInput.value : rawToolCall.input,
1962
- ...rawToolCall.providerExecuted !== void 0 ? { providerExecuted: rawToolCall.providerExecuted } : {}
1963
- };
1970
+ let validatedToolCall;
1971
+ let toolCall;
1972
+ if (approval.kind === "custom" && continuation.approved) {
1973
+ validatedToolCall = asToolCallTextStreamPart({
1974
+ part: await validateToolCall({
1975
+ event: rawToolCall,
1976
+ tools: input.tools
1977
+ })
1978
+ });
1979
+ toolCall = displayHostToolCall({
1980
+ toolCall: validatedToolCall,
1981
+ sessionWorkDir: input.sessionWorkDir
1982
+ });
1983
+ } else {
1984
+ const parsedInput = await safeParseJSON2({ text: rawToolCall.input });
1985
+ toolCall = {
1986
+ type: "tool-call",
1987
+ toolCallId: rawToolCall.toolCallId,
1988
+ toolName: rawToolCall.toolName,
1989
+ input: parsedInput.success ? parsedInput.value : rawToolCall.input,
1990
+ ...rawToolCall.providerExecuted !== void 0 ? { providerExecuted: rawToolCall.providerExecuted } : {}
1991
+ };
1992
+ }
1964
1993
  enqueueApprovalResponse(approval, continuation, toolCall);
1965
1994
  onToolApprovalSettled(approval.approvalId);
1966
1995
  pendingApprovalsByApprovalId.delete(approval.approvalId);
@@ -1990,6 +2019,27 @@ function runPrompt(input) {
1990
2019
  });
1991
2020
  return "continued";
1992
2021
  }
2022
+ if (validatedToolCall == null) {
2023
+ throw new Error(
2024
+ `Harness '${input.harness.harnessId}' could not validate approved host tool '${approval.toolName}'.`
2025
+ );
2026
+ }
2027
+ if (validatedToolCall.invalid) {
2028
+ const error = new Error(invalidToolInputMessage);
2029
+ await submitToolResult({
2030
+ toolCallId: approval.toolCallId,
2031
+ output: { error: invalidToolInputMessage },
2032
+ isError: true
2033
+ });
2034
+ bufferedToolOutcomes.push(() => {
2035
+ enqueueHostToolOutcome({
2036
+ toolCall,
2037
+ outcome: { ok: false, error }
2038
+ });
2039
+ });
2040
+ await publishToolExecutions();
2041
+ return "continued";
2042
+ }
1993
2043
  await lifecycle.start(input.model);
1994
2044
  toolExecutions.set(rawToolCall.toolCallId, {
1995
2045
  toolCall
@@ -1997,6 +2047,7 @@ function runPrompt(input) {
1997
2047
  const executionStartedAt = Date.now();
1998
2048
  const execution = await maybeExecuteHostTool({
1999
2049
  event: rawToolCall,
2050
+ parsedToolCall: validatedToolCall,
2000
2051
  tools: activeTools,
2001
2052
  toolsContext,
2002
2053
  wrappedExecuteTool: lifecycle.executeTool,
@@ -2088,7 +2139,7 @@ function runPrompt(input) {
2088
2139
  (condition) => condition({ steps: completedSteps })
2089
2140
  )
2090
2141
  )).some(Boolean)) {
2091
- await ((_d2 = input.onStopConditionMet) == null ? void 0 : _d2.call(input));
2142
+ await input.onStopConditionMet?.();
2092
2143
  const { usage } = pendingStopBoundary;
2093
2144
  releasePendingStopBoundary();
2094
2145
  await lifecycle.end({
@@ -2102,7 +2153,7 @@ function runPrompt(input) {
2102
2153
  }
2103
2154
  }
2104
2155
  if (value.type === "stream-start") {
2105
- const modelId = (_e2 = value.modelId) != null ? _e2 : input.model;
2156
+ const modelId = value.modelId ?? input.model;
2106
2157
  if (modelId != null) result.setModelId(modelId);
2107
2158
  await lifecycle.start(modelId);
2108
2159
  }
@@ -2146,7 +2197,7 @@ function runPrompt(input) {
2146
2197
  const rawToolCall = rawToolCallsByToolCallId.get(
2147
2198
  displayValue.toolCallId
2148
2199
  );
2149
- const toolName = (_f2 = rawToolCall == null ? void 0 : rawToolCall.toolName) != null ? _f2 : toolCall.toolName;
2200
+ const toolName = rawToolCall?.toolName ?? toolCall.toolName;
2150
2201
  if (!isHarnessV1BuiltinToolIncluded({
2151
2202
  toolName,
2152
2203
  toolFiltering: input.builtinToolFiltering
@@ -2169,7 +2220,7 @@ function runPrompt(input) {
2169
2220
  if (value.type === "error" && displayValue.type === "error") {
2170
2221
  await waitForOutstandingHostToolExecutions();
2171
2222
  await lifecycle.error(value.error);
2172
- if (!((_g2 = input.abortSignal) == null ? void 0 : _g2.aborted)) {
2223
+ if (!input.abortSignal?.aborted) {
2173
2224
  logBridgeError({
2174
2225
  harnessId: input.harness.harnessId,
2175
2226
  sessionId: input.session.sessionId,
@@ -2191,15 +2242,25 @@ function runPrompt(input) {
2191
2242
  } else {
2192
2243
  for (const part of translatedParts) result.enqueue(part);
2193
2244
  }
2245
+ let validatedHostToolCall;
2194
2246
  if (displayValue.type === "tool-call") {
2247
+ const isHostTool = value.type === "tool-call" && !value.providerExecuted && hasTool({ tools: activeTools, toolName: value.toolName }) && !(value.toolName === "askUserQuestions" && hasTool({
2248
+ tools: input.harness.builtinTools,
2249
+ toolName: value.toolName
2250
+ }));
2195
2251
  const parsed = await validateToolCall({
2196
- event: displayValue,
2252
+ event: isHostTool ? value : displayValue,
2197
2253
  tools: input.tools
2198
2254
  });
2199
2255
  const parsedToolCall = asToolCallTextStreamPart({ part: parsed });
2256
+ validatedHostToolCall = isHostTool ? parsedToolCall : void 0;
2257
+ const displayToolCall = isHostTool ? displayHostToolCall({
2258
+ toolCall: parsedToolCall,
2259
+ sessionWorkDir: input.sessionWorkDir
2260
+ }) : parsedToolCall;
2200
2261
  rawToolCallsByToolCallId.set(displayValue.toolCallId, displayValue);
2201
- toolCallsByToolCallId.set(displayValue.toolCallId, parsedToolCall);
2202
- result.enqueue(parsed);
2262
+ toolCallsByToolCallId.set(displayValue.toolCallId, displayToolCall);
2263
+ result.enqueue(displayToolCall);
2203
2264
  }
2204
2265
  if (value.type === "text-delta") {
2205
2266
  stepText += value.delta;
@@ -2208,7 +2269,7 @@ function runPrompt(input) {
2208
2269
  }
2209
2270
  if (value.type === "tool-call") {
2210
2271
  observedStepToolCallCount += 1;
2211
- expectedStepToolCallCount != null ? expectedStepToolCallCount : expectedStepToolCallCount = value.stepToolCallCount;
2272
+ expectedStepToolCallCount ??= value.stepToolCallCount;
2212
2273
  const toolCall = toolCallsByToolCallId.get(value.toolCallId);
2213
2274
  if (toolCall != null) {
2214
2275
  stepToolCalls.push(toolCall);
@@ -2230,7 +2291,7 @@ function runPrompt(input) {
2230
2291
  output: value.result
2231
2292
  };
2232
2293
  }
2233
- if (((_h2 = rawToolCallsByToolCallId.get(value.toolCallId)) == null ? void 0 : _h2.providerExecuted) === true && (execution == null ? void 0 : execution.toolOutput) != null) {
2294
+ if (rawToolCallsByToolCallId.get(value.toolCallId)?.providerExecuted === true && execution?.toolOutput != null) {
2234
2295
  stepProviderToolResults.push(
2235
2296
  execution.toolOutput
2236
2297
  );
@@ -2244,14 +2305,14 @@ function runPrompt(input) {
2244
2305
  );
2245
2306
  }
2246
2307
  const rawToolCall = rawToolCallsByToolCallId.get(value.toolCallId);
2247
- const pendingApproval = (_k = pendingApprovalsByApprovalId.get(value.approvalId)) != null ? _k : {
2308
+ const pendingApproval = pendingApprovalsByApprovalId.get(value.approvalId) ?? {
2248
2309
  approvalId: value.approvalId,
2249
2310
  toolCallId: value.toolCallId,
2250
2311
  toolName: toolCall.toolName,
2251
- input: (_i2 = rawToolCall == null ? void 0 : rawToolCall.input) != null ? _i2 : JSON.stringify(toolCall.input),
2312
+ input: rawToolCall?.input ?? JSON.stringify(toolCall.input),
2252
2313
  kind: "builtin",
2253
- providerExecuted: (_j2 = rawToolCall == null ? void 0 : rawToolCall.providerExecuted) != null ? _j2 : true,
2254
- ...(rawToolCall == null ? void 0 : rawToolCall.nativeName) !== void 0 ? { nativeName: rawToolCall.nativeName } : {}
2314
+ providerExecuted: rawToolCall?.providerExecuted ?? true,
2315
+ ...rawToolCall?.nativeName !== void 0 ? { nativeName: rawToolCall.nativeName } : {}
2255
2316
  };
2256
2317
  pendingApprovalsByApprovalId.set(
2257
2318
  pendingApproval.approvalId,
@@ -2345,6 +2406,31 @@ function runPrompt(input) {
2345
2406
  await finishForHostInputPause({ completeCurrentStep: true });
2346
2407
  return;
2347
2408
  }
2409
+ if (validatedHostToolCall == null) {
2410
+ throw new Error(
2411
+ `Harness '${input.harness.harnessId}' could not validate host tool '${toolCall.toolName}'.`
2412
+ );
2413
+ }
2414
+ if (validatedHostToolCall.invalid) {
2415
+ settledHostToolCallIds.add(toolCall.toolCallId);
2416
+ toolExecutions.delete(toolCall.toolCallId);
2417
+ bufferedToolOutcomes.push(() => {
2418
+ result.enqueue({
2419
+ type: "tool-error",
2420
+ toolCallId: toolCall.toolCallId,
2421
+ toolName: toolCall.toolName,
2422
+ input: parsedToolCall.input,
2423
+ error: new Error(invalidToolInputMessage),
2424
+ dynamic: true
2425
+ });
2426
+ });
2427
+ await submitToolResult({
2428
+ toolCallId: toolCall.toolCallId,
2429
+ output: { error: invalidToolInputMessage },
2430
+ isError: true
2431
+ });
2432
+ continue;
2433
+ }
2348
2434
  const customToolApprovalDecision = resolveCustomToolApproval({
2349
2435
  toolName: toolCall.toolName,
2350
2436
  toolApproval: input.toolApproval
@@ -2380,7 +2466,7 @@ function runPrompt(input) {
2380
2466
  }
2381
2467
  continue;
2382
2468
  }
2383
- const pendingApproval = (_l = pendingApprovalsByToolCallId.get(toolCall.toolCallId)) != null ? _l : customToolApprovalDecision.type === "request" ? {
2469
+ const pendingApproval = pendingApprovalsByToolCallId.get(toolCall.toolCallId) ?? (customToolApprovalDecision.type === "request" ? {
2384
2470
  approvalId: generateId2(),
2385
2471
  toolCallId: toolCall.toolCallId,
2386
2472
  toolName: toolCall.toolName,
@@ -2388,7 +2474,7 @@ function runPrompt(input) {
2388
2474
  kind: "custom",
2389
2475
  providerExecuted: false,
2390
2476
  ...toolCall.nativeName !== void 0 ? { nativeName: toolCall.nativeName } : {}
2391
- } : void 0;
2477
+ } : void 0);
2392
2478
  if (pendingApproval != null) {
2393
2479
  pendingApprovalsByApprovalId.set(
2394
2480
  pendingApproval.approvalId,
@@ -2444,6 +2530,7 @@ function runPrompt(input) {
2444
2530
  const executionStartedAt = Date.now();
2445
2531
  const execution = await maybeExecuteHostTool({
2446
2532
  event: toolCall,
2533
+ parsedToolCall: validatedHostToolCall,
2447
2534
  tools: activeTools,
2448
2535
  toolsContext,
2449
2536
  wrappedExecuteTool: lifecycle.executeTool,
@@ -2490,16 +2577,16 @@ function runPrompt(input) {
2490
2577
  }
2491
2578
  }
2492
2579
  await waitForOutstandingHostToolExecutions();
2493
- const isTurnSuspending = ((_m = input.isTurnSuspending) == null ? void 0 : _m.call(input)) === true;
2580
+ const isTurnSuspending = input.isTurnSuspending?.() === true;
2494
2581
  if (isTurnSuspending) {
2495
2582
  await publishToolExecutions();
2496
2583
  if (finalFinish == null) {
2497
2584
  result.discardCurrentStepContent();
2498
2585
  }
2499
2586
  } else if (finalFinish != null) {
2500
- (_n = input.onTurnFinished) == null ? void 0 : _n.call(input);
2587
+ input.onTurnFinished?.();
2501
2588
  } else {
2502
- (_o = input.onTurnFailed) == null ? void 0 : _o.call(input);
2589
+ input.onTurnFailed?.();
2503
2590
  }
2504
2591
  await result.finish(
2505
2592
  finalFinish ? {
@@ -2511,7 +2598,7 @@ function runPrompt(input) {
2511
2598
  } catch (err) {
2512
2599
  try {
2513
2600
  await waitForOutstandingHostToolExecutions();
2514
- } catch (e) {
2601
+ } catch {
2515
2602
  }
2516
2603
  await lifecycle.error(err);
2517
2604
  logBridgeError({
@@ -2549,14 +2636,31 @@ function asToolCallTextStreamPart(input) {
2549
2636
  }
2550
2637
  return input.part;
2551
2638
  }
2639
+ function displayHostToolCall(input) {
2640
+ return {
2641
+ ...input.toolCall,
2642
+ input: stripParsedToolInputWorkDir({
2643
+ value: input.toolCall.input,
2644
+ sessionWorkDir: input.sessionWorkDir
2645
+ }),
2646
+ ...input.toolCall.invalid ? { error: new Error(invalidToolInputMessage) } : {}
2647
+ };
2648
+ }
2552
2649
  function hasTool(input) {
2553
2650
  return Object.prototype.hasOwnProperty.call(input.tools, input.toolName);
2554
2651
  }
2555
2652
  async function maybeExecuteHostTool(input) {
2556
2653
  const tool = input.tools[input.event.toolName];
2557
2654
  if (!isExecutableTool(tool)) return { executed: false };
2558
- const parsed = await safeParseJSON2({ text: input.event.input });
2559
- const args = parsed.success ? parsed.value : input.event.input;
2655
+ if (input.parsedToolCall.invalid) {
2656
+ const error = new Error(invalidToolInputMessage);
2657
+ await input.submitToolResult({
2658
+ toolCallId: input.event.toolCallId,
2659
+ output: { error: invalidToolInputMessage },
2660
+ isError: true
2661
+ });
2662
+ return { executed: true, outcome: { ok: false, error } };
2663
+ }
2560
2664
  let context;
2561
2665
  try {
2562
2666
  context = await validateToolContext({
@@ -2579,7 +2683,7 @@ async function maybeExecuteHostTool(input) {
2579
2683
  let output2;
2580
2684
  const stream = executeTool({
2581
2685
  tool,
2582
- input: args,
2686
+ input: input.parsedToolCall.input,
2583
2687
  options: {
2584
2688
  toolCallId: input.event.toolCallId,
2585
2689
  messages: [],
@@ -2658,23 +2762,22 @@ var HarnessAgentSession = class {
2658
2762
  this.sessionState = "active";
2659
2763
  this.turnSequence = 0;
2660
2764
  this.activeTurnSequence = 0;
2661
- var _a4, _b4, _c, _d;
2662
2765
  this.sessionId = options.sessionId;
2663
2766
  this.harness = options.harness;
2664
2767
  this.underlyingSession = options.underlyingSession;
2665
2768
  this.sandboxSession = options.sandboxSession;
2666
- this.ownsSandboxLifecycle = (_a4 = options.ownsSandboxLifecycle) != null ? _a4 : true;
2769
+ this.ownsSandboxLifecycle = options.ownsSandboxLifecycle ?? true;
2667
2770
  this.sessionWorkDir = options.sessionWorkDir;
2668
2771
  this.toolApproval = options.toolApproval;
2669
- for (const approval of (_b4 = options.pendingToolApprovals) != null ? _b4 : []) {
2772
+ for (const approval of options.pendingToolApprovals ?? []) {
2670
2773
  this.pendingToolApprovals.set(approval.approvalId, approval);
2671
2774
  }
2672
- for (const pendingResult of (_c = options.pendingToolResults) != null ? _c : []) {
2775
+ for (const pendingResult of options.pendingToolResults ?? []) {
2673
2776
  this.pendingToolResults.set(pendingResult.toolCallId, pendingResult);
2674
2777
  }
2675
2778
  this.persistedTurnSettings = options.turnSettings;
2676
2779
  this.resumedToolsContext = options.resumedToolsContext;
2677
- this.turnState = (_d = options.turnState) != null ? _d : this.pendingToolApprovals.size > 0 ? "awaiting-approval" : this.pendingToolResults.size > 0 ? "awaiting-tool-result" : "idle";
2780
+ this.turnState = options.turnState ?? (this.pendingToolApprovals.size > 0 ? "awaiting-approval" : this.pendingToolResults.size > 0 ? "awaiting-tool-result" : "idle");
2678
2781
  this.isResume = options.underlyingSession.isResume;
2679
2782
  }
2680
2783
  /**
@@ -3041,9 +3144,8 @@ var HarnessAgentSession = class {
3041
3144
  };
3042
3145
  }
3043
3146
  async suspendCurrentTurn(options) {
3044
- var _a4;
3045
3147
  this.clearActivePromptControl();
3046
- (_a4 = this.suspendedTurnState) != null ? _a4 : this.suspendedTurnState = (async () => {
3148
+ this.suspendedTurnState ??= (async () => {
3047
3149
  const raw = await options.session.doSuspendTurn();
3048
3150
  const validated = await validateLifecycleStateData({
3049
3151
  harness: this.harness,
@@ -3135,14 +3237,14 @@ var HarnessAgentSession = class {
3135
3237
  }
3136
3238
  setPromptControl(options) {
3137
3239
  const activePromptControl = this.activePromptControl;
3138
- if (this.sessionState !== "active" || this.turnState !== "running" || this.activeTurnSequence !== options.turnId || (activePromptControl == null ? void 0 : activePromptControl.turnId) !== options.turnId) {
3240
+ if (this.sessionState !== "active" || this.turnState !== "running" || this.activeTurnSequence !== options.turnId || activePromptControl?.turnId !== options.turnId) {
3139
3241
  return;
3140
3242
  }
3141
3243
  this.settleActivePromptControl(options.control);
3142
3244
  }
3143
3245
  async waitForPromptControl(options) {
3144
3246
  const activePromptControl = this.activePromptControl;
3145
- if ((activePromptControl == null ? void 0 : activePromptControl.turnId) !== options.turnId) return;
3247
+ if (activePromptControl?.turnId !== options.turnId) return;
3146
3248
  await activePromptControl.promise;
3147
3249
  }
3148
3250
  settleActivePromptControl(control) {
@@ -3170,11 +3272,10 @@ var HarnessAgentSession = class {
3170
3272
  this.turnState = "idle";
3171
3273
  }
3172
3274
  resolveActiveTurnSettings(options) {
3173
- var _a4, _b4;
3174
3275
  if (this.activeTurnSettings != null) {
3175
3276
  return this.activeTurnSettings;
3176
3277
  }
3177
- const persisted = (_a4 = this.persistedTurnSettings) != null ? _a4 : {
3278
+ const persisted = this.persistedTurnSettings ?? {
3178
3279
  ...options.model == null ? {} : { model: options.model },
3179
3280
  skills: options.skills,
3180
3281
  ...options.instructions == null ? {} : { instructions: options.instructions },
@@ -3194,7 +3295,7 @@ var HarnessAgentSession = class {
3194
3295
  this.activeTurnSettings = {
3195
3296
  persisted,
3196
3297
  tools: options.tools,
3197
- toolsContext: (_b4 = this.resumedToolsContext) != null ? _b4 : options.toolsContext,
3298
+ toolsContext: this.resumedToolsContext ?? options.toolsContext,
3198
3299
  activeTools,
3199
3300
  builtinToolFiltering: options.builtinToolFiltering
3200
3301
  };
@@ -3219,7 +3320,7 @@ var HarnessAgentSession = class {
3219
3320
  // src/agent/harness-agent-tool-approval-continuation.ts
3220
3321
  function collectHarnessAgentToolApprovalContinuations(input) {
3221
3322
  const lastMessage = input.messages.at(-1);
3222
- if ((lastMessage == null ? void 0 : lastMessage.role) !== "tool") return [];
3323
+ if (lastMessage?.role !== "tool") return [];
3223
3324
  const toolCallIds = /* @__PURE__ */ new Set();
3224
3325
  const approvalRequestsByApprovalId = /* @__PURE__ */ new Map();
3225
3326
  for (const message of input.messages) {
@@ -3263,7 +3364,7 @@ function collectHarnessAgentToolApprovalContinuations(input) {
3263
3364
  // src/agent/harness-agent-tool-result-continuation.ts
3264
3365
  function collectHarnessAgentToolResultContinuations(input) {
3265
3366
  const lastMessage = input.messages.at(-1);
3266
- if ((lastMessage == null ? void 0 : lastMessage.role) !== "tool") return [];
3367
+ if (lastMessage?.role !== "tool") return [];
3267
3368
  return lastMessage.content.filter((part) => part.type === "tool-result");
3268
3369
  }
3269
3370
 
@@ -3388,7 +3489,7 @@ function resolveBootstrapPath({
3388
3489
  }
3389
3490
 
3390
3491
  // src/agent/internal/sandbox-bootstrap.ts
3391
- import { posix as posix5 } from "path";
3492
+ import { posix as posix6 } from "path";
3392
3493
 
3393
3494
  // src/utils/resolve-sandbox-default-working-directory.ts
3394
3495
  import { posix as posix4 } from "path";
@@ -3436,6 +3537,59 @@ async function resolveSandboxHomeDir({
3436
3537
  return homeDir;
3437
3538
  }
3438
3539
 
3540
+ // src/agent/internal/on-bootstrap-marker.ts
3541
+ import { posix as posix5 } from "path";
3542
+ async function onBootstrapMarkerPath({
3543
+ session,
3544
+ bootstrapHash,
3545
+ abortSignal
3546
+ }) {
3547
+ const digest = new Uint8Array(
3548
+ await crypto.subtle.digest(
3549
+ "SHA-256",
3550
+ new TextEncoder().encode(bootstrapHash)
3551
+ )
3552
+ );
3553
+ const filename = Array.from(
3554
+ digest,
3555
+ (byte) => byte.toString(16).padStart(2, "0")
3556
+ ).join("");
3557
+ return posix5.join(
3558
+ harnessStateDirectoryPath({
3559
+ sandboxHomeDir: await resolveSandboxHomeDir({
3560
+ sandbox: session,
3561
+ abortSignal
3562
+ })
3563
+ }),
3564
+ ".on-bootstrap",
3565
+ `${filename}.ok`
3566
+ );
3567
+ }
3568
+ async function hasOnBootstrapMarker(options) {
3569
+ return await options.session.readTextFile({
3570
+ path: await onBootstrapMarkerPath(options),
3571
+ abortSignal: options.abortSignal
3572
+ }) !== null;
3573
+ }
3574
+ async function writeOnBootstrapMarker(options) {
3575
+ const path2 = await onBootstrapMarkerPath(options);
3576
+ const result = await options.session.run({
3577
+ command: 'mkdir -p "$MARKER_DIR"',
3578
+ env: { MARKER_DIR: posix5.dirname(path2) },
3579
+ abortSignal: options.abortSignal
3580
+ });
3581
+ if (result.exitCode !== 0) {
3582
+ throw new Error(
3583
+ `Failed to create onBootstrap marker directory: ${result.stderr || result.stdout}`
3584
+ );
3585
+ }
3586
+ await options.session.writeTextFile({
3587
+ path: path2,
3588
+ content: "",
3589
+ abortSignal: options.abortSignal
3590
+ });
3591
+ }
3592
+
3439
3593
  // src/agent/internal/sandbox-bootstrap.ts
3440
3594
  var SANDBOX_BOOTSTRAP_IDENTITY_VERSION = 1;
3441
3595
  function validateSandboxBootstrapSettings(settings) {
@@ -3462,10 +3616,10 @@ function normalizeSandboxWorkDir(workDir) {
3462
3616
  "HarnessAgent: `sandboxConfig.workDir` must use POSIX path separators."
3463
3617
  );
3464
3618
  }
3465
- if (posix5.isAbsolute(workDir)) {
3619
+ if (posix6.isAbsolute(workDir)) {
3466
3620
  throw new Error("HarnessAgent: `sandboxConfig.workDir` must be relative.");
3467
3621
  }
3468
- const normalized = posix5.normalize(workDir);
3622
+ const normalized = posix6.normalize(workDir);
3469
3623
  if (normalized === "." || normalized === ".." || normalized.startsWith("../")) {
3470
3624
  throw new Error(
3471
3625
  "HarnessAgent: `sandboxConfig.workDir` must stay inside the sandbox default working directory."
@@ -3481,7 +3635,7 @@ function resolveSessionWorkDir({
3481
3635
  }) {
3482
3636
  return joinSandboxPath({
3483
3637
  base: defaultWorkingDirectory,
3484
- path: workDir != null ? workDir : `${encodeHarnessPathSegment(harnessId)}-${encodeHarnessPathSegment(sessionId)}`
3638
+ path: workDir ?? `${encodeHarnessPathSegment(harnessId)}-${encodeHarnessPathSegment(sessionId)}`
3485
3639
  });
3486
3640
  }
3487
3641
  async function createSandboxBootstrapPlan({
@@ -3509,6 +3663,7 @@ async function createSandboxBootstrapPlan({
3509
3663
  recipeIdentity,
3510
3664
  workDir,
3511
3665
  onBootstrap: settings.onBootstrap,
3666
+ bootstrapHash: settings.bootstrapHash,
3512
3667
  abortSignal: opts.abortSignal
3513
3668
  })
3514
3669
  } : {}
@@ -3520,6 +3675,8 @@ async function runSandboxBootstrap({
3520
3675
  recipeIdentity,
3521
3676
  workDir,
3522
3677
  onBootstrap,
3678
+ bootstrapHash,
3679
+ skipOnBootstrapIfMarked = false,
3523
3680
  defaultWorkingDirectory,
3524
3681
  abortSignal
3525
3682
  }) {
@@ -3544,7 +3701,9 @@ async function runSandboxBootstrap({
3544
3701
  });
3545
3702
  }
3546
3703
  if (onBootstrap == null) return;
3547
- const resolvedDefaultWorkingDirectory = defaultWorkingDirectory != null ? defaultWorkingDirectory : await resolveSandboxDefaultWorkingDirectory({
3704
+ if (skipOnBootstrapIfMarked && bootstrapHash != null && await hasOnBootstrapMarker({ session, bootstrapHash, abortSignal }))
3705
+ return;
3706
+ const resolvedDefaultWorkingDirectory = defaultWorkingDirectory ?? await resolveSandboxDefaultWorkingDirectory({
3548
3707
  sandboxSession: session,
3549
3708
  abortSignal
3550
3709
  });
@@ -3558,6 +3717,9 @@ async function runSandboxBootstrap({
3558
3717
  abortSignal
3559
3718
  });
3560
3719
  await onBootstrap({ session, workDir: bootstrapWorkDir, abortSignal });
3720
+ if (bootstrapHash != null) {
3721
+ await writeOnBootstrapMarker({ session, bootstrapHash, abortSignal });
3722
+ }
3561
3723
  }
3562
3724
  async function ensureSandboxDirectory({
3563
3725
  session,
@@ -3587,9 +3749,9 @@ async function hashSandboxBootstrapIdentity({
3587
3749
  chunks.push(encoder.encode("\0"));
3588
3750
  };
3589
3751
  pushString(String(SANDBOX_BOOTSTRAP_IDENTITY_VERSION));
3590
- pushString(recipeIdentity != null ? recipeIdentity : "");
3591
- pushString(bootstrapHash != null ? bootstrapHash : "");
3592
- pushString(workDir != null ? workDir : "");
3752
+ pushString(recipeIdentity ?? "");
3753
+ pushString(bootstrapHash ?? "");
3754
+ pushString(workDir ?? "");
3593
3755
  const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
3594
3756
  const buffer = new Uint8Array(totalLength);
3595
3757
  let offset = 0;
@@ -3609,7 +3771,7 @@ function joinSandboxPath({
3609
3771
  base,
3610
3772
  path: path2
3611
3773
  }) {
3612
- return posix5.join(base, path2);
3774
+ return posix6.join(base, path2);
3613
3775
  }
3614
3776
 
3615
3777
  // src/agent/internal/resolve-observability.ts
@@ -3621,10 +3783,9 @@ function parseList(value) {
3621
3783
  return items.length > 0 ? items : void 0;
3622
3784
  }
3623
3785
  function resolveDebugConfig(debug, env = process.env) {
3624
- var _a4, _b4, _c, _d;
3625
- const enabled = (_b4 = debug == null ? void 0 : debug.enabled) != null ? _b4 : ENV_TRUTHY.has(((_a4 = env.HARNESS_DEBUG) != null ? _a4 : "").toLowerCase());
3626
- const level = (_d = (_c = debug == null ? void 0 : debug.level) != null ? _c : env.HARNESS_DEBUG_LEVEL) != null ? _d : "debug";
3627
- const subsystems = (debug == null ? void 0 : debug.subsystems) ? [...debug.subsystems] : parseList(env.HARNESS_DEBUG_SUBSYSTEMS);
3786
+ const enabled = debug?.enabled ?? ENV_TRUTHY.has((env.HARNESS_DEBUG ?? "").toLowerCase());
3787
+ const level = debug?.level ?? env.HARNESS_DEBUG_LEVEL ?? "debug";
3788
+ const subsystems = debug?.subsystems ? [...debug.subsystems] : parseList(env.HARNESS_DEBUG_SUBSYSTEMS);
3628
3789
  return { enabled, level, subsystems };
3629
3790
  }
3630
3791
  function toHarnessDiagnostic(d) {
@@ -3642,36 +3803,33 @@ function toHarnessDiagnostic(d) {
3642
3803
  };
3643
3804
  }
3644
3805
  function formatForStderr(d) {
3645
- var _a4;
3646
3806
  const parts = [`[harness:${d.level}]`, d.subsystem, d.message].filter(
3647
3807
  Boolean
3648
3808
  );
3649
3809
  let line = parts.join(" ");
3650
3810
  if (d.error) {
3651
- line += ` (${(_a4 = d.error.name) != null ? _a4 : "Error"}: ${d.error.message})`;
3811
+ line += ` (${d.error.name ?? "Error"}: ${d.error.message})`;
3652
3812
  }
3653
3813
  return `${line}
3654
3814
  `;
3655
3815
  }
3656
3816
  function buildObservability(options) {
3657
- var _a4;
3658
3817
  const resolved = resolveDebugConfig(options.settings.debug);
3659
3818
  if (!resolved.enabled) return void 0;
3660
3819
  const onLog = options.settings.onLog;
3661
- const integrations = ((_a4 = options.settings.telemetry) == null ? void 0 : _a4.integrations) ? asArray(options.settings.telemetry.integrations) : [];
3820
+ const integrations = options.settings.telemetry?.integrations ? asArray(options.settings.telemetry.integrations) : [];
3662
3821
  const diagnosticConsumers = integrations.filter(
3663
3822
  (integration) => typeof integration.ingestDiagnostic === "function"
3664
3823
  );
3665
3824
  const report = (emitted) => {
3666
- var _a5;
3667
3825
  const diagnostic = toHarnessDiagnostic(emitted);
3668
3826
  try {
3669
3827
  process.stderr.write(formatForStderr(diagnostic));
3670
- } catch (e) {
3828
+ } catch {
3671
3829
  }
3672
- onLog == null ? void 0 : onLog(diagnostic);
3830
+ onLog?.(diagnostic);
3673
3831
  for (const consumer of diagnosticConsumers) {
3674
- (_a5 = consumer.ingestDiagnostic) == null ? void 0 : _a5.call(consumer, diagnostic);
3832
+ consumer.ingestDiagnostic?.(diagnostic);
3675
3833
  }
3676
3834
  };
3677
3835
  return {
@@ -3696,7 +3854,7 @@ function resolveHarnessAgentToolFiltering(input) {
3696
3854
  const activeTools = dedupeToolNames({ toolNames: input.activeTools });
3697
3855
  const inactiveTools = dedupeToolNames({ toolNames: input.inactiveTools });
3698
3856
  validateToolNames({
3699
- requestedToolNames: activeTools != null ? activeTools : inactiveTools,
3857
+ requestedToolNames: activeTools ?? inactiveTools,
3700
3858
  availableToolNames: allToolNames
3701
3859
  });
3702
3860
  const userToolNames = Object.keys(input.userTools);
@@ -3744,11 +3902,115 @@ function filterToolSet(input) {
3744
3902
  );
3745
3903
  }
3746
3904
 
3905
+ // src/agent/internal/prepared-sandbox-identity.ts
3906
+ var PREPARED_SANDBOX_IDENTITY_VERSION = 1;
3907
+ async function resolvePreparedSandboxIdentity({
3908
+ recipeIdentities,
3909
+ bootstrapHash,
3910
+ workDir
3911
+ }) {
3912
+ const entries = Object.entries(recipeIdentities).sort(
3913
+ ([a], [b]) => a.localeCompare(b)
3914
+ );
3915
+ if (entries.length === 0 && bootstrapHash == null) return void 0;
3916
+ const encoder = new TextEncoder();
3917
+ const chunks = [];
3918
+ const pushString = (value) => {
3919
+ chunks.push(encoder.encode(value));
3920
+ chunks.push(encoder.encode("\0"));
3921
+ };
3922
+ pushString(String(PREPARED_SANDBOX_IDENTITY_VERSION));
3923
+ pushString(workDir ?? "");
3924
+ pushString(bootstrapHash ?? "");
3925
+ for (const [harnessId, identity] of entries) {
3926
+ pushString(harnessId);
3927
+ pushString(identity);
3928
+ }
3929
+ const buffer = new Uint8Array(
3930
+ chunks.reduce((sum, chunk) => sum + chunk.length, 0)
3931
+ );
3932
+ let offset = 0;
3933
+ for (const chunk of chunks) {
3934
+ buffer.set(chunk, offset);
3935
+ offset += chunk.length;
3936
+ }
3937
+ const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", buffer));
3938
+ return Array.from(
3939
+ digest.slice(0, 8),
3940
+ (byte) => byte.toString(16).padStart(2, "0")
3941
+ ).join("");
3942
+ }
3943
+
3944
+ // src/agent/create-harness-sandbox-template.ts
3945
+ async function createHarnessSandboxTemplate(options) {
3946
+ if (options.harnesses.length === 0) {
3947
+ throw new Error(
3948
+ "createHarnessSandboxTemplate: at least one harness must be provided."
3949
+ );
3950
+ }
3951
+ const settings = options.sandboxConfig ?? {};
3952
+ validateSandboxBootstrapSettings(settings);
3953
+ const workDir = settings.workDir == null ? void 0 : normalizeSandboxWorkDir(settings.workDir);
3954
+ const harnesses = [
3955
+ ...new Map(
3956
+ options.harnesses.map((harness) => [harness.harnessId, harness])
3957
+ ).values()
3958
+ ].sort((a, b) => a.harnessId.localeCompare(b.harnessId));
3959
+ const recipes = await Promise.all(
3960
+ harnesses.map(async (harness) => {
3961
+ const recipe = await harness.getBootstrap?.({});
3962
+ return recipe == null ? void 0 : {
3963
+ recipe,
3964
+ identity: await hashHarnessBootstrap(recipe)
3965
+ };
3966
+ })
3967
+ );
3968
+ const recipeIdentities = {};
3969
+ for (let index = 0; index < harnesses.length; index++) {
3970
+ const entry = recipes[index];
3971
+ if (entry != null)
3972
+ recipeIdentities[harnesses[index].harnessId] = entry.identity;
3973
+ }
3974
+ const identity = await resolvePreparedSandboxIdentity({
3975
+ recipeIdentities,
3976
+ bootstrapHash: settings.bootstrapHash,
3977
+ workDir
3978
+ });
3979
+ if (identity == null) return void 0;
3980
+ return {
3981
+ identity,
3982
+ prepare: async ({ session, abortSignal }) => {
3983
+ for (const entry of recipes) {
3984
+ if (entry != null) {
3985
+ await runSandboxBootstrap({
3986
+ session,
3987
+ recipe: entry.recipe,
3988
+ recipeIdentity: entry.identity,
3989
+ abortSignal
3990
+ });
3991
+ }
3992
+ }
3993
+ await runSandboxBootstrap({
3994
+ session,
3995
+ workDir,
3996
+ onBootstrap: settings.onBootstrap,
3997
+ bootstrapHash: settings.bootstrapHash,
3998
+ skipOnBootstrapIfMarked: true,
3999
+ abortSignal
4000
+ });
4001
+ }
4002
+ };
4003
+ }
4004
+
3747
4005
  // src/agent/harness-agent.ts
3748
4006
  var HarnessAgent = class {
3749
4007
  constructor(settings) {
3750
4008
  this.version = "agent-v1";
3751
- var _a4, _b4;
4009
+ if (settings.sandbox != null) {
4010
+ console.warn(
4011
+ "HarnessAgent: `sandbox` is deprecated. Supply `sandboxSession` to createSession() instead."
4012
+ );
4013
+ }
3752
4014
  const sandboxConfig = resolveSandboxConfig(settings);
3753
4015
  validateSandboxBootstrapSettings(sandboxConfig);
3754
4016
  this.settings = settings;
@@ -3760,7 +4022,7 @@ var HarnessAgent = class {
3760
4022
  "user-agent",
3761
4023
  "x-client-app"
3762
4024
  ]);
3763
- const forbiddenHeader = Object.keys((_a4 = settings.headers) != null ? _a4 : {}).map((name4) => name4.toLowerCase()).find((name4) => forbiddenHeaders.has(name4));
4025
+ const forbiddenHeader = Object.keys(settings.headers ?? {}).map((name4) => name4.toLowerCase()).find((name4) => forbiddenHeaders.has(name4));
3764
4026
  if (forbiddenHeader != null) {
3765
4027
  throw new Error(
3766
4028
  `HarnessAgent: \`headers\` must not include the managed header \`${forbiddenHeader}\`.`
@@ -3769,7 +4031,7 @@ var HarnessAgent = class {
3769
4031
  const headers = normalizeHeaders(settings.headers);
3770
4032
  this.headers = Object.keys(headers).length === 0 ? void 0 : headers;
3771
4033
  this.id = settings.id;
3772
- const userTools = (_b4 = settings.tools) != null ? _b4 : {};
4034
+ const userTools = settings.tools ?? {};
3773
4035
  assertNoReservedQuestionTool({
3774
4036
  harness: settings.harness,
3775
4037
  userTools
@@ -3807,6 +4069,12 @@ var HarnessAgent = class {
3807
4069
  get hasOutput() {
3808
4070
  return this.settings.output != null;
3809
4071
  }
4072
+ getSandboxTemplate() {
4073
+ return createHarnessSandboxTemplate({
4074
+ harnesses: [this.settings.harness],
4075
+ sandboxConfig: this.sandboxConfig
4076
+ });
4077
+ }
3810
4078
  /**
3811
4079
  * Start a fresh session, or resume from state previously returned by
3812
4080
  * `session.detach()` or `session.stop()`. The returned
@@ -3815,12 +4083,11 @@ var HarnessAgent = class {
3815
4083
  * `session.destroy()`.
3816
4084
  */
3817
4085
  async createSession(options) {
3818
- var _a4, _b4, _c;
3819
- const sessionId = (_a4 = options == null ? void 0 : options.sessionId) != null ? _a4 : generateId3();
3820
- const resumeFrom = options == null ? void 0 : options.resumeFrom;
3821
- const continueFrom = options == null ? void 0 : options.continueFrom;
3822
- const providedSandboxSession = options == null ? void 0 : options.sandboxSession;
3823
- const abortSignal = options == null ? void 0 : options.abortSignal;
4086
+ const sessionId = options?.sessionId ?? generateId3();
4087
+ const resumeFrom = options?.resumeFrom;
4088
+ const continueFrom = options?.continueFrom;
4089
+ const providedSandboxSession = options?.sandboxSession;
4090
+ const abortSignal = options?.abortSignal;
3824
4091
  const harness = this.settings.harness;
3825
4092
  const sandboxProvider = this.settings.sandbox;
3826
4093
  const ownsSandboxLifecycle = providedSandboxSession == null;
@@ -3845,8 +4112,8 @@ var HarnessAgent = class {
3845
4112
  expectedType: "continue-turn"
3846
4113
  });
3847
4114
  }
3848
- const effectiveContinueFrom = validatedContinueFrom != null ? validatedContinueFrom : validatedResumeFrom == null ? void 0 : validatedResumeFrom.continueFrom;
3849
- if ((options == null ? void 0 : options.toolsContext) != null && effectiveContinueFrom == null) {
4115
+ const effectiveContinueFrom = validatedContinueFrom ?? validatedResumeFrom?.continueFrom;
4116
+ if (options?.toolsContext != null && effectiveContinueFrom == null) {
3850
4117
  throw new Error(
3851
4118
  "HarnessAgent.createSession: `toolsContext` can only rebind an unfinished turn from `continueFrom` or `resumeFrom`."
3852
4119
  );
@@ -3867,7 +4134,7 @@ var HarnessAgent = class {
3867
4134
  sessionId,
3868
4135
  workDir: this.sandboxConfig.workDir
3869
4136
  });
3870
- const recipe = await ((_b4 = harness.getBootstrap) == null ? void 0 : _b4.call(harness, { abortSignal }));
4137
+ const recipe = await harness.getBootstrap?.({ abortSignal });
3871
4138
  if (recipe != null) {
3872
4139
  const recipeIdentity = await hashHarnessBootstrap(recipe);
3873
4140
  try {
@@ -3899,7 +4166,7 @@ var HarnessAgent = class {
3899
4166
  "HarnessAgent.createSession: configure `sandbox` on HarnessAgent or pass `sandboxSession` to createSession()."
3900
4167
  );
3901
4168
  }
3902
- const recipe = await ((_c = harness.getBootstrap) == null ? void 0 : _c.call(harness, { abortSignal }));
4169
+ const recipe = await harness.getBootstrap?.({ abortSignal });
3903
4170
  if (isResumedSession) {
3904
4171
  if (sandboxProvider.resumeSession == null) {
3905
4172
  throw new HarnessCapabilityUnsupportedError({
@@ -3988,6 +4255,14 @@ var HarnessAgent = class {
3988
4255
  }
3989
4256
  }
3990
4257
  try {
4258
+ await runSandboxBootstrap({
4259
+ session: getRestrictedSandboxSession(sandboxSession),
4260
+ workDir: this.sandboxConfig.workDir,
4261
+ onBootstrap: this.sandboxConfig.onBootstrap,
4262
+ bootstrapHash: this.sandboxConfig.bootstrapHash,
4263
+ skipOnBootstrapIfMarked: true,
4264
+ abortSignal
4265
+ });
3991
4266
  await ensureSandboxDirectory({
3992
4267
  session: sandboxSession,
3993
4268
  workDir: sessionWorkDir,
@@ -4031,10 +4306,10 @@ var HarnessAgent = class {
4031
4306
  ownsSandboxLifecycle,
4032
4307
  sessionWorkDir,
4033
4308
  toolApproval: this.settings.toolApproval,
4034
- pendingToolApprovals: effectiveContinueFrom == null ? void 0 : effectiveContinueFrom.pendingToolApprovals,
4035
- pendingToolResults: effectiveContinueFrom == null ? void 0 : effectiveContinueFrom.pendingToolResults,
4036
- turnSettings: effectiveContinueFrom == null ? void 0 : effectiveContinueFrom.turnSettings,
4037
- resumedToolsContext: options == null ? void 0 : options.toolsContext,
4309
+ pendingToolApprovals: effectiveContinueFrom?.pendingToolApprovals,
4310
+ pendingToolResults: effectiveContinueFrom?.pendingToolResults,
4311
+ turnSettings: effectiveContinueFrom?.turnSettings,
4312
+ resumedToolsContext: options?.toolsContext,
4038
4313
  turnState: effectiveContinueFrom == null ? "idle" : effectiveContinueFrom.pendingToolApprovals != null && effectiveContinueFrom.pendingToolApprovals.length > 0 ? "awaiting-approval" : effectiveContinueFrom.pendingToolResults != null && effectiveContinueFrom.pendingToolResults.length > 0 ? "awaiting-tool-result" : "suspended"
4039
4314
  });
4040
4315
  } catch (error) {
@@ -4075,13 +4350,12 @@ var HarnessAgent = class {
4075
4350
  * consuming a turn that crossed a process boundary.
4076
4351
  */
4077
4352
  async continueGenerate(options) {
4078
- var _a4, _b4;
4079
4353
  const runtimeContext = {};
4080
4354
  const { result, done } = await this._startContinueTurn({
4081
4355
  session: options.session,
4082
4356
  turnInput: {
4083
- toolApprovalContinuations: (_a4 = options.toolApprovalContinuations) != null ? _a4 : [],
4084
- toolResultContinuations: (_b4 = options.toolResultContinuations) != null ? _b4 : []
4357
+ toolApprovalContinuations: options.toolApprovalContinuations ?? [],
4358
+ toolResultContinuations: options.toolResultContinuations ?? []
4085
4359
  },
4086
4360
  runtimeContext,
4087
4361
  abortSignal: options.abortSignal
@@ -4098,13 +4372,12 @@ var HarnessAgent = class {
4098
4372
  * follows from how the adapter resumed the session.
4099
4373
  */
4100
4374
  async continueStream(options) {
4101
- var _a4, _b4;
4102
4375
  const runtimeContext = {};
4103
4376
  const { result, ready } = await this._startContinueTurn({
4104
4377
  session: options.session,
4105
4378
  turnInput: {
4106
- toolApprovalContinuations: (_a4 = options.toolApprovalContinuations) != null ? _a4 : [],
4107
- toolResultContinuations: (_b4 = options.toolResultContinuations) != null ? _b4 : []
4379
+ toolApprovalContinuations: options.toolApprovalContinuations ?? [],
4380
+ toolResultContinuations: options.toolResultContinuations ?? []
4108
4381
  },
4109
4382
  runtimeContext,
4110
4383
  abortSignal: options.abortSignal
@@ -4172,31 +4445,30 @@ var HarnessAgent = class {
4172
4445
  };
4173
4446
  }
4174
4447
  _resolveLifecycleCallbacks(call) {
4175
- var _a4, _b4, _c, _d, _e, _f;
4176
4448
  return {
4177
4449
  onStart: mergeCallbacks(
4178
4450
  this.settings.onStart,
4179
- (_a4 = call == null ? void 0 : call.onStart) != null ? _a4 : call == null ? void 0 : call.experimental_onStart
4451
+ call?.onStart ?? call?.experimental_onStart
4180
4452
  ),
4181
4453
  onStepStart: mergeCallbacks(
4182
4454
  this.settings.onStepStart,
4183
- (_b4 = call == null ? void 0 : call.onStepStart) != null ? _b4 : call == null ? void 0 : call.experimental_onStepStart
4455
+ call?.onStepStart ?? call?.experimental_onStepStart
4184
4456
  ),
4185
4457
  onLanguageModelCallStart: this.settings.onLanguageModelCallStart,
4186
4458
  onLanguageModelCallEnd: this.settings.onLanguageModelCallEnd,
4187
4459
  onToolExecutionStart: mergeCallbacks(
4188
4460
  this.settings.onToolExecutionStart,
4189
- (_c = call == null ? void 0 : call.onToolExecutionStart) != null ? _c : call == null ? void 0 : call.experimental_onToolCallStart
4461
+ call?.onToolExecutionStart ?? call?.experimental_onToolCallStart
4190
4462
  ),
4191
4463
  onToolExecutionEnd: mergeCallbacks(
4192
4464
  this.settings.onToolExecutionEnd,
4193
- (_d = call == null ? void 0 : call.onToolExecutionEnd) != null ? _d : call == null ? void 0 : call.experimental_onToolCallFinish
4465
+ call?.onToolExecutionEnd ?? call?.experimental_onToolCallFinish
4194
4466
  ),
4195
4467
  onStepEnd: mergeCallbacks(
4196
4468
  this.settings.onStepEnd,
4197
- (_e = call == null ? void 0 : call.onStepEnd) != null ? _e : call == null ? void 0 : call.onStepFinish
4469
+ call?.onStepEnd ?? call?.onStepFinish
4198
4470
  ),
4199
- onEnd: mergeCallbacks(this.settings.onEnd, (_f = call == null ? void 0 : call.onEnd) != null ? _f : call == null ? void 0 : call.onFinish)
4471
+ onEnd: mergeCallbacks(this.settings.onEnd, call?.onEnd ?? call?.onFinish)
4200
4472
  };
4201
4473
  }
4202
4474
  _resolveContinueTurnInput(options) {
@@ -4231,7 +4503,7 @@ var HarnessAgent = class {
4231
4503
  if (Array.isArray(messages)) {
4232
4504
  for (let i = messages.length - 1; i >= 0; i--) {
4233
4505
  const message = messages[i];
4234
- if ((message == null ? void 0 : message.role) === "user") return message;
4506
+ if (message?.role === "user") return message;
4235
4507
  }
4236
4508
  throw new Error(
4237
4509
  'HarnessAgent: messages must contain at least one `role: "user"` entry.'
@@ -4240,7 +4512,6 @@ var HarnessAgent = class {
4240
4512
  throw new Error("HarnessAgent: either `prompt` or `messages` is required.");
4241
4513
  }
4242
4514
  async _preparePromptTurnInput(options) {
4243
- var _a4, _b4, _c, _d;
4244
4515
  let callOptions = options;
4245
4516
  if (this.settings.callOptionsSchema != null && options.options !== void 0) {
4246
4517
  const validatedOptions = await validateTypes({
@@ -4277,13 +4548,12 @@ var HarnessAgent = class {
4277
4548
  skills: this.settings.skills,
4278
4549
  instructions: this.settings.instructions,
4279
4550
  tools: this.settings.tools,
4280
- toolsContext: (_a4 = this.settings.toolsContext) != null ? _a4 : {},
4551
+ toolsContext: this.settings.toolsContext ?? {},
4281
4552
  ...promptOptions
4282
4553
  };
4283
- const preparedCallArgs = (_d = await ((_c = (_b4 = this.settings).prepareCall) == null ? void 0 : _c.call(
4284
- _b4,
4554
+ const preparedCallArgs = await this.settings.prepareCall?.(
4285
4555
  baseCallArgs
4286
- ))) != null ? _d : baseCallArgs;
4556
+ ) ?? baseCallArgs;
4287
4557
  if (this._resolveContinueTurnInput(preparedCallArgs) != null) {
4288
4558
  throw new Error(
4289
4559
  "HarnessAgent.prepareCall must return a fresh user prompt, not a tool continuation."
@@ -4301,7 +4571,6 @@ var HarnessAgent = class {
4301
4571
  };
4302
4572
  }
4303
4573
  _prepareContinueTurnInput(options) {
4304
- var _a4, _b4;
4305
4574
  return {
4306
4575
  ...this._prepareTurnSettings({
4307
4576
  model: this.settings.model,
@@ -4310,13 +4579,12 @@ var HarnessAgent = class {
4310
4579
  tools: this.settings.tools,
4311
4580
  toolsContext: this.settings.toolsContext
4312
4581
  }),
4313
- toolApprovalContinuations: (_a4 = options.toolApprovalContinuations) != null ? _a4 : [],
4314
- toolResultContinuations: (_b4 = options.toolResultContinuations) != null ? _b4 : []
4582
+ toolApprovalContinuations: options.toolApprovalContinuations ?? [],
4583
+ toolResultContinuations: options.toolResultContinuations ?? []
4315
4584
  };
4316
4585
  }
4317
4586
  _prepareTurnSettings(options) {
4318
- var _a4, _b4, _c, _d;
4319
- const userTools = (_a4 = options.tools) != null ? _a4 : {};
4587
+ const userTools = options.tools ?? {};
4320
4588
  assertNoReservedQuestionTool({
4321
4589
  harness: this.settings.harness,
4322
4590
  userTools
@@ -4334,10 +4602,10 @@ var HarnessAgent = class {
4334
4602
  });
4335
4603
  return {
4336
4604
  model: options.model,
4337
- skills: (_b4 = options.skills) != null ? _b4 : [],
4338
- instructions: typeof options.instructions === "string" ? options.instructions : (_c = options.instructions) == null ? void 0 : _c.content,
4605
+ skills: options.skills ?? [],
4606
+ instructions: typeof options.instructions === "string" ? options.instructions : options.instructions?.content,
4339
4607
  tools,
4340
- toolsContext: (_d = options.toolsContext) != null ? _d : {},
4608
+ toolsContext: options.toolsContext ?? {},
4341
4609
  activeTools: toolFiltering.activeUserTools,
4342
4610
  toolSpecs: this._toToolSpecs(toolFiltering.activeUserTools),
4343
4611
  builtinToolFiltering: toolFiltering.builtinToolFiltering
@@ -4360,7 +4628,7 @@ var HarnessAgent = class {
4360
4628
  inputSchema = asSchema(
4361
4629
  t.inputSchema
4362
4630
  ).jsonSchema;
4363
- } catch (e) {
4631
+ } catch {
4364
4632
  }
4365
4633
  }
4366
4634
  specs.push({ name: name4, description: t.description, inputSchema });
@@ -4377,8 +4645,7 @@ var HarnessAgent = class {
4377
4645
  return new HarnessGenerateTextResult({ steps, usage, responseMessages, output });
4378
4646
  }
4379
4647
  async _resolveResponseFormat() {
4380
- var _a4;
4381
- const responseFormat = await ((_a4 = this.settings.output) == null ? void 0 : _a4.responseFormat);
4648
+ const responseFormat = await this.settings.output?.responseFormat;
4382
4649
  if (responseFormat == null || responseFormat.type === "text") {
4383
4650
  return responseFormat == null ? void 0 : { type: "text" };
4384
4651
  }
@@ -4447,10 +4714,7 @@ var HarnessGenerateTextResult = class {
4447
4714
  return this.finalStep.rawFinishReason;
4448
4715
  }
4449
4716
  get warnings() {
4450
- return this.steps.flatMap((step) => {
4451
- var _a4;
4452
- return (_a4 = step.warnings) != null ? _a4 : [];
4453
- });
4717
+ return this.steps.flatMap((step) => step.warnings ?? []);
4454
4718
  }
4455
4719
  get reasoning() {
4456
4720
  return this.finalStep.content.filter(
@@ -4474,7 +4738,6 @@ var HarnessGenerateTextResult = class {
4474
4738
  }
4475
4739
  };
4476
4740
  function resolveSandboxConfig(settings) {
4477
- var _a4;
4478
4741
  if (settings.onSandboxSession != null) {
4479
4742
  console.warn(
4480
4743
  "HarnessAgent: `onSandboxSession` is deprecated. Use `sandboxConfig.onSession` instead."
@@ -4482,7 +4745,7 @@ function resolveSandboxConfig(settings) {
4482
4745
  }
4483
4746
  return {
4484
4747
  ...settings.sandboxConfig,
4485
- ...((_a4 = settings.sandboxConfig) == null ? void 0 : _a4.onSession) == null && settings.onSandboxSession != null ? { onSession: settings.onSandboxSession } : {}
4748
+ ...settings.sandboxConfig?.onSession == null && settings.onSandboxSession != null ? { onSession: settings.onSandboxSession } : {}
4486
4749
  };
4487
4750
  }
4488
4751
  async function cleanupAfterStartFailure(input) {
@@ -4495,8 +4758,10 @@ async function cleanupAfterStartFailure(input) {
4495
4758
 
4496
4759
  // src/agent/prepare-harness-sandbox-template.ts
4497
4760
  async function prepareHarnessSandboxTemplate(options) {
4498
- var _a4;
4499
- const sandboxConfig = (_a4 = options.sandboxConfig) != null ? _a4 : {};
4761
+ console.warn(
4762
+ "prepareHarnessSandboxTemplate (prewarmHarness) is deprecated. Use createHarnessSandboxTemplate and a sandbox session creator instead."
4763
+ );
4764
+ const sandboxConfig = options.sandboxConfig ?? {};
4500
4765
  validateSandboxBootstrapSettings(sandboxConfig);
4501
4766
  const { harness, sandboxProvider, abortSignal } = options;
4502
4767
  let recipe;
@@ -4541,10 +4806,11 @@ async function prepareHarnessSandboxTemplate(options) {
4541
4806
  var prewarmHarness = prepareHarnessSandboxTemplate;
4542
4807
 
4543
4808
  // src/agent/prepare-sandbox-for-harness.ts
4544
- var PREPARED_SANDBOX_IDENTITY_VERSION = 1;
4545
4809
  async function prepareSandboxForHarness(options) {
4546
- var _a4, _b4;
4547
- const sandboxConfig = (_a4 = options.sandboxConfig) != null ? _a4 : {};
4810
+ console.warn(
4811
+ "prepareSandboxForHarness is deprecated. Use createHarnessSandboxTemplate and template.prepare instead."
4812
+ );
4813
+ const sandboxConfig = options.sandboxConfig ?? {};
4548
4814
  validateSandboxBootstrapSettings(sandboxConfig);
4549
4815
  if (options.harnesses.length === 0) {
4550
4816
  throw new Error(
@@ -4561,16 +4827,16 @@ async function prepareSandboxForHarness(options) {
4561
4827
  const skippedHarnessIds = [];
4562
4828
  let stateDirectory;
4563
4829
  for (const harness of harnesses) {
4564
- const recipe = await ((_b4 = harness.getBootstrap) == null ? void 0 : _b4.call(harness, {
4830
+ const recipe = await harness.getBootstrap?.({
4565
4831
  abortSignal: options.abortSignal
4566
- }));
4832
+ });
4567
4833
  if (recipe == null) {
4568
4834
  skippedHarnessIds.push(harness.harnessId);
4569
4835
  continue;
4570
4836
  }
4571
4837
  const recipeIdentity = await hashHarnessBootstrap(recipe);
4572
4838
  recipeIdentities[harness.harnessId] = recipeIdentity;
4573
- stateDirectory != null ? stateDirectory : stateDirectory = harnessStateDirectoryPath({
4839
+ stateDirectory ??= harnessStateDirectoryPath({
4574
4840
  sandboxHomeDir: await resolveSandboxHomeDir({
4575
4841
  sandbox: options.session,
4576
4842
  abortSignal: options.abortSignal
@@ -4592,6 +4858,7 @@ async function prepareSandboxForHarness(options) {
4592
4858
  session: options.session,
4593
4859
  workDir,
4594
4860
  onBootstrap: sandboxConfig.onBootstrap,
4861
+ bootstrapHash: sandboxConfig.bootstrapHash,
4595
4862
  defaultWorkingDirectory,
4596
4863
  abortSignal: options.abortSignal
4597
4864
  });
@@ -4607,45 +4874,6 @@ async function prepareSandboxForHarness(options) {
4607
4874
  skippedHarnessIds
4608
4875
  };
4609
4876
  }
4610
- async function resolvePreparedSandboxIdentity({
4611
- recipeIdentities,
4612
- bootstrapHash,
4613
- workDir
4614
- }) {
4615
- const entries = Object.entries(recipeIdentities).sort(
4616
- ([a], [b]) => a.localeCompare(b)
4617
- );
4618
- if (entries.length === 0 && bootstrapHash == null) {
4619
- return void 0;
4620
- }
4621
- const encoder = new TextEncoder();
4622
- const chunks = [];
4623
- const pushString = (value) => {
4624
- chunks.push(encoder.encode(value));
4625
- chunks.push(encoder.encode("\0"));
4626
- };
4627
- pushString(String(PREPARED_SANDBOX_IDENTITY_VERSION));
4628
- pushString(workDir != null ? workDir : "");
4629
- pushString(bootstrapHash != null ? bootstrapHash : "");
4630
- for (const [harnessId, identity] of entries) {
4631
- pushString(harnessId);
4632
- pushString(identity);
4633
- }
4634
- const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
4635
- const buffer = new Uint8Array(totalLength);
4636
- let offset = 0;
4637
- for (const chunk of chunks) {
4638
- buffer.set(chunk, offset);
4639
- offset += chunk.length;
4640
- }
4641
- const digest = await crypto.subtle.digest("SHA-256", buffer);
4642
- const bytes = new Uint8Array(digest);
4643
- let hex = "";
4644
- for (let i = 0; i < 8; i++) {
4645
- hex += bytes[i].toString(16).padStart(2, "0");
4646
- }
4647
- return hex;
4648
- }
4649
4877
 
4650
4878
  // src/errors/harness-sandbox-authentication-error.ts
4651
4879
  import { AISDKError as AISDKError3 } from "@ai-sdk/provider";
@@ -4681,10 +4909,9 @@ function getHarnessErrorMessage(error) {
4681
4909
  // src/agent/observability/file-reporter.ts
4682
4910
  import { appendFileSync, mkdirSync } from "fs";
4683
4911
  function createFileReporter(options) {
4684
- var _a4, _b4;
4685
- const fileName = (_a4 = options.fileName) != null ? _a4 : "events.jsonl";
4912
+ const fileName = options.fileName ?? "events.jsonl";
4686
4913
  const path2 = `${options.dir}/${fileName}`;
4687
- const failOnly = (_b4 = options.failOnly) != null ? _b4 : false;
4914
+ const failOnly = options.failOnly ?? false;
4688
4915
  const turns = /* @__PURE__ */ new Map();
4689
4916
  let lastOpenCallId;
4690
4917
  let dirReady = false;
@@ -4697,7 +4924,7 @@ function createFileReporter(options) {
4697
4924
  return bucket;
4698
4925
  };
4699
4926
  const record = (callId, rec) => {
4700
- const id = callId != null ? callId : lastOpenCallId;
4927
+ const id = callId ?? lastOpenCallId;
4701
4928
  if (id == null) {
4702
4929
  flushLines([rec]);
4703
4930
  return;
@@ -4712,7 +4939,7 @@ function createFileReporter(options) {
4712
4939
  dirReady = true;
4713
4940
  }
4714
4941
  appendFileSync(path2, lines.map((l) => JSON.stringify(l)).join("\n") + "\n");
4715
- } catch (e) {
4942
+ } catch {
4716
4943
  }
4717
4944
  };
4718
4945
  const finishTurn = (callId) => {
@@ -4783,14 +5010,13 @@ function createFileReporter(options) {
4783
5010
  });
4784
5011
  },
4785
5012
  onEnd(event) {
4786
- var _a5;
4787
5013
  const e = event;
4788
5014
  record(e.callId, {
4789
5015
  ts: Date.now(),
4790
5016
  kind: "turn-finish",
4791
5017
  callId: e.callId,
4792
5018
  finishReason: e.finishReason,
4793
- usage: (_a5 = e.totalUsage) != null ? _a5 : e.usage
5019
+ usage: e.totalUsage ?? e.usage
4794
5020
  });
4795
5021
  finishTurn(e.callId);
4796
5022
  },
@@ -4817,8 +5043,7 @@ function createFileReporter(options) {
4817
5043
 
4818
5044
  // src/agent/observability/trace-tree-reporter.ts
4819
5045
  function createTraceTreeReporter(options = {}) {
4820
- var _a4;
4821
- const write = (_a4 = options.write) != null ? _a4 : ((chunk) => void process.stderr.write(chunk));
5046
+ const write = options.write ?? ((chunk) => void process.stderr.write(chunk));
4822
5047
  const turns = /* @__PURE__ */ new Map();
4823
5048
  const render = (node, depth) => {
4824
5049
  const indent = " ".repeat(depth);
@@ -4830,11 +5055,10 @@ function createTraceTreeReporter(options = {}) {
4830
5055
  };
4831
5056
  return {
4832
5057
  onStart(event) {
4833
- var _a5;
4834
5058
  const e = event;
4835
5059
  turns.set(e.callId, {
4836
5060
  root: {
4837
- label: `${(_a5 = e.operationId) != null ? _a5 : "turn"}${e.modelId ? ` ${e.modelId}` : ""}`,
5061
+ label: `${e.operationId ?? "turn"}${e.modelId ? ` ${e.modelId}` : ""}`,
4838
5062
  startMs: Date.now(),
4839
5063
  children: []
4840
5064
  },
@@ -4842,12 +5066,11 @@ function createTraceTreeReporter(options = {}) {
4842
5066
  });
4843
5067
  },
4844
5068
  onStepStart(event) {
4845
- var _a5;
4846
5069
  const e = event;
4847
5070
  const turn = turns.get(e.callId);
4848
5071
  if (!turn) return;
4849
5072
  const step = {
4850
- label: `step ${((_a5 = e.stepNumber) != null ? _a5 : turn.root.children.length) + 1}`,
5073
+ label: `step ${(e.stepNumber ?? turn.root.children.length) + 1}`,
4851
5074
  startMs: Date.now(),
4852
5075
  children: []
4853
5076
  };
@@ -4855,10 +5078,9 @@ function createTraceTreeReporter(options = {}) {
4855
5078
  turn.root.children.push(step);
4856
5079
  },
4857
5080
  onToolExecutionStart(event) {
4858
- var _a5;
4859
5081
  const e = event;
4860
5082
  const turn = turns.get(e.callId);
4861
- const parent = (_a5 = turn == null ? void 0 : turn.step) != null ? _a5 : turn == null ? void 0 : turn.root;
5083
+ const parent = turn?.step ?? turn?.root;
4862
5084
  if (!turn || !parent) return;
4863
5085
  const node = {
4864
5086
  label: `tool ${e.toolCall.toolName}`,
@@ -4869,9 +5091,8 @@ function createTraceTreeReporter(options = {}) {
4869
5091
  parent.children.push(node);
4870
5092
  },
4871
5093
  onToolExecutionEnd(event) {
4872
- var _a5;
4873
5094
  const e = event;
4874
- const node = (_a5 = turns.get(e.callId)) == null ? void 0 : _a5.tools.get(e.toolCall.toolCallId);
5095
+ const node = turns.get(e.callId)?.tools.get(e.toolCall.toolCallId);
4875
5096
  if (!node) return;
4876
5097
  node.endMs = Date.now();
4877
5098
  if (e.toolOutput.type === "error") node.label += " [error]";
@@ -4879,7 +5100,7 @@ function createTraceTreeReporter(options = {}) {
4879
5100
  onStepFinish(event) {
4880
5101
  const e = event;
4881
5102
  const turn = turns.get(e.callId);
4882
- if (turn == null ? void 0 : turn.step) {
5103
+ if (turn?.step) {
4883
5104
  turn.step.endMs = Date.now();
4884
5105
  turn.step = void 0;
4885
5106
  }
@@ -4893,7 +5114,7 @@ function createTraceTreeReporter(options = {}) {
4893
5114
  try {
4894
5115
  write(`
4895
5116
  ${render(turn.root, 0)}`);
4896
- } catch (e2) {
5117
+ } catch {
4897
5118
  }
4898
5119
  }
4899
5120
  };
@@ -4907,6 +5128,7 @@ export {
4907
5128
  collectHarnessAgentToolApprovalContinuations,
4908
5129
  collectHarnessAgentToolResultContinuations,
4909
5130
  createFileReporter,
5131
+ createHarnessSandboxTemplate,
4910
5132
  createTraceTreeReporter,
4911
5133
  getHarnessErrorMessage,
4912
5134
  prepareHarnessSandboxTemplate,