@ai-sdk/harness 1.0.38 → 1.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @ai-sdk/harness
2
2
 
3
+ ## 1.0.39
4
+
5
+ ### Patch Changes
6
+
7
+ - 86a84c9: fix(harness): settle a turn aborted by the caller's abortSignal with an `abort` stream part instead of an AbortError `error` part, matching `streamText`'s abort contract
8
+ - ai@7.0.34
9
+
3
10
  ## 1.0.38
4
11
 
5
12
  ### Patch Changes
@@ -183,6 +183,9 @@ import {
183
183
  isExecutableTool,
184
184
  safeParseJSON
185
185
  } from "@ai-sdk/provider-utils";
186
+ import {
187
+ getErrorMessage
188
+ } from "@ai-sdk/provider";
186
189
  import { parseToolCall } from "ai/internal";
187
190
 
188
191
  // src/agent/internal/harness-stream-text-result.ts
@@ -457,6 +460,24 @@ var HarnessStreamTextResult = class {
457
460
  });
458
461
  this.fullStreamController.close();
459
462
  }
463
+ /**
464
+ * Settle the turn as user-aborted: emit a final `abort` part — matching
465
+ * `streamText`'s abort contract — and close the stream, instead of
466
+ * surfacing an `error` part. `toUIMessageStream` consumers then observe
467
+ * an `abort` chunk (and `isAborted: true`) rather than a spurious
468
+ * `onError`. The delayed promise accessors still reject with the
469
+ * underlying abort error so awaiting consumers do not hang. Idempotent.
470
+ */
471
+ abort(input) {
472
+ if (this.settled) return;
473
+ this.settled = true;
474
+ this.fullStreamController.enqueue({
475
+ type: "abort",
476
+ ...input.reason !== void 0 ? { reason: input.reason } : {}
477
+ });
478
+ this.fullStreamController.close();
479
+ this.rejectDelayedPromises(input.error);
480
+ }
460
481
  /**
461
482
  * Surface a fatal error as a stream `error` part + reject every delayed
462
483
  * promise so awaiting consumers stop hanging. Idempotent.
@@ -469,6 +490,9 @@ var HarnessStreamTextResult = class {
469
490
  error
470
491
  });
471
492
  this.fullStreamController.close();
493
+ this.rejectDelayedPromises(error);
494
+ }
495
+ rejectDelayedPromises(error) {
472
496
  for (const dp of [
473
497
  this._content,
474
498
  this._text,
@@ -596,6 +620,7 @@ var HarnessStreamTextResult = class {
596
620
  toUIMessageStream({
597
621
  originalMessages,
598
622
  generateMessageId,
623
+ onEnd,
599
624
  onFinish,
600
625
  messageMetadata,
601
626
  sendReasoning,
@@ -610,6 +635,7 @@ var HarnessStreamTextResult = class {
610
635
  tools: this.tools,
611
636
  originalMessages,
612
637
  generateMessageId,
638
+ onEnd,
613
639
  onFinish,
614
640
  messageMetadata,
615
641
  sendReasoning,
@@ -629,6 +655,7 @@ var HarnessStreamTextResult = class {
629
655
  toUIMessageStreamResponse({
630
656
  originalMessages,
631
657
  generateMessageId,
658
+ onEnd,
632
659
  onFinish,
633
660
  messageMetadata,
634
661
  sendReasoning,
@@ -642,6 +669,7 @@ var HarnessStreamTextResult = class {
642
669
  stream: this.toUIMessageStream({
643
670
  originalMessages,
644
671
  generateMessageId,
672
+ onEnd,
645
673
  onFinish,
646
674
  messageMetadata,
647
675
  sendReasoning,
@@ -1265,8 +1293,20 @@ function runPrompt(input) {
1265
1293
  promptText: input.prompt != null ? promptToText(input.prompt) : "",
1266
1294
  runtimeContext: input.runtimeContext
1267
1295
  });
1296
+ const settleFailure = (err) => {
1297
+ var _a4, _b4;
1298
+ (_a4 = input.onTurnFailed) == null ? void 0 : _a4.call(input);
1299
+ if ((_b4 = input.abortSignal) == null ? void 0 : _b4.aborted) {
1300
+ result.abort({
1301
+ error: err,
1302
+ ...input.abortSignal.reason !== void 0 ? { reason: getErrorMessage(input.abortSignal.reason) } : {}
1303
+ });
1304
+ return;
1305
+ }
1306
+ result.fail(err);
1307
+ };
1268
1308
  const done = (async () => {
1269
- var _a4, _b4, _c2, _d2, _e2, _f2, _g2, _h, _i, _j, _k, _l, _m;
1309
+ var _a4, _b4, _c2, _d2, _e2, _f2, _g2, _h, _i, _j;
1270
1310
  let bridge;
1271
1311
  try {
1272
1312
  bridge = await toHarnessStream({
@@ -1297,8 +1337,7 @@ function runPrompt(input) {
1297
1337
  context: "failed to start harness turn",
1298
1338
  error: err
1299
1339
  });
1300
- (_a4 = input.onTurnFailed) == null ? void 0 : _a4.call(input);
1301
- result.fail(err);
1340
+ settleFailure(err);
1302
1341
  return;
1303
1342
  }
1304
1343
  const { stream, control } = bridge;
@@ -1312,7 +1351,7 @@ function runPrompt(input) {
1312
1351
  pendingToolApprovals.map((approval) => [approval.toolCallId, approval])
1313
1352
  );
1314
1353
  const continuationsByApprovalId = new Map(
1315
- ((_b4 = input.toolApprovalContinuations) != null ? _b4 : []).map((continuation) => [
1354
+ ((_a4 = input.toolApprovalContinuations) != null ? _a4 : []).map((continuation) => [
1316
1355
  continuation.approvalResponse.approvalId,
1317
1356
  continuation
1318
1357
  ])
@@ -1324,7 +1363,7 @@ function runPrompt(input) {
1324
1363
  ])
1325
1364
  );
1326
1365
  const continuationsByToolCallId = new Map(
1327
- ((_c2 = input.toolResultContinuations) != null ? _c2 : []).map((continuation) => [
1366
+ ((_b4 = input.toolResultContinuations) != null ? _b4 : []).map((continuation) => [
1328
1367
  continuation.toolCallId,
1329
1368
  continuation
1330
1369
  ])
@@ -1541,7 +1580,7 @@ function runPrompt(input) {
1541
1580
  if (done2) break;
1542
1581
  if (value == null) continue;
1543
1582
  if (value.type === "stream-start") {
1544
- telemetry.start((_d2 = value.modelId) != null ? _d2 : input.session.modelId);
1583
+ telemetry.start((_c2 = value.modelId) != null ? _c2 : input.session.modelId);
1545
1584
  }
1546
1585
  if (value.type !== "stream-start" && value.type !== "finish-step" && value.type !== "finish" && value.type !== "error") {
1547
1586
  telemetry.ensureStepOpen();
@@ -1567,7 +1606,7 @@ function runPrompt(input) {
1567
1606
  const rawToolCall = rawToolCallsByToolCallId.get(
1568
1607
  displayValue.toolCallId
1569
1608
  );
1570
- const toolName = (_e2 = rawToolCall == null ? void 0 : rawToolCall.toolName) != null ? _e2 : toolCall.toolName;
1609
+ const toolName = (_d2 = rawToolCall == null ? void 0 : rawToolCall.toolName) != null ? _d2 : toolCall.toolName;
1571
1610
  if (!isHarnessV1BuiltinToolIncluded({
1572
1611
  toolName,
1573
1612
  toolFiltering: input.builtinToolFiltering
@@ -1587,6 +1626,17 @@ function runPrompt(input) {
1587
1626
  continue;
1588
1627
  }
1589
1628
  }
1629
+ if (value.type === "error" && displayValue.type === "error") {
1630
+ telemetry.error(value.error);
1631
+ logBridgeError({
1632
+ harnessId: input.harness.harnessId,
1633
+ sessionId: input.session.sessionId,
1634
+ context: "harness stream error",
1635
+ error: value.error
1636
+ });
1637
+ settleFailure(displayValue.error);
1638
+ return;
1639
+ }
1590
1640
  for (const part of translateStreamPart(displayValue)) {
1591
1641
  result.enqueue(part);
1592
1642
  }
@@ -1632,13 +1682,13 @@ function runPrompt(input) {
1632
1682
  );
1633
1683
  }
1634
1684
  const rawToolCall = rawToolCallsByToolCallId.get(value.toolCallId);
1635
- const pendingApproval = (_h = pendingApprovalsByApprovalId.get(value.approvalId)) != null ? _h : {
1685
+ const pendingApproval = (_g2 = pendingApprovalsByApprovalId.get(value.approvalId)) != null ? _g2 : {
1636
1686
  approvalId: value.approvalId,
1637
1687
  toolCallId: value.toolCallId,
1638
1688
  toolName: toolCall.toolName,
1639
- input: (_f2 = rawToolCall == null ? void 0 : rawToolCall.input) != null ? _f2 : JSON.stringify(toolCall.input),
1689
+ input: (_e2 = rawToolCall == null ? void 0 : rawToolCall.input) != null ? _e2 : JSON.stringify(toolCall.input),
1640
1690
  kind: "builtin",
1641
- providerExecuted: (_g2 = rawToolCall == null ? void 0 : rawToolCall.providerExecuted) != null ? _g2 : true,
1691
+ providerExecuted: (_f2 = rawToolCall == null ? void 0 : rawToolCall.providerExecuted) != null ? _f2 : true,
1642
1692
  ...(rawToolCall == null ? void 0 : rawToolCall.nativeName) !== void 0 ? { nativeName: rawToolCall.nativeName } : {}
1643
1693
  };
1644
1694
  pendingApprovalsByApprovalId.set(
@@ -1734,7 +1784,7 @@ function runPrompt(input) {
1734
1784
  telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
1735
1785
  continue;
1736
1786
  }
1737
- const pendingApproval = (_i = pendingApprovalsByToolCallId.get(toolCall.toolCallId)) != null ? _i : customToolApprovalDecision.type === "request" ? {
1787
+ const pendingApproval = (_h = pendingApprovalsByToolCallId.get(toolCall.toolCallId)) != null ? _h : customToolApprovalDecision.type === "request" ? {
1738
1788
  approvalId: generateId4(),
1739
1789
  toolCallId: toolCall.toolCallId,
1740
1790
  toolName: toolCall.toolName,
@@ -1813,23 +1863,11 @@ function runPrompt(input) {
1813
1863
  }
1814
1864
  telemetry.toolEnd(toolCall.toolCallId, execution.outcome);
1815
1865
  }
1816
- if (value.type === "error") {
1817
- telemetry.error(value.error);
1818
- logBridgeError({
1819
- harnessId: input.harness.harnessId,
1820
- sessionId: input.session.sessionId,
1821
- context: "harness stream error",
1822
- error: value.error
1823
- });
1824
- (_j = input.onTurnFailed) == null ? void 0 : _j.call(input);
1825
- result.fail(value.error);
1826
- return;
1827
- }
1828
1866
  }
1829
1867
  if (finalFinish != null) {
1830
- (_k = input.onTurnFinished) == null ? void 0 : _k.call(input);
1868
+ (_i = input.onTurnFinished) == null ? void 0 : _i.call(input);
1831
1869
  } else {
1832
- (_l = input.onTurnFailed) == null ? void 0 : _l.call(input);
1870
+ (_j = input.onTurnFailed) == null ? void 0 : _j.call(input);
1833
1871
  }
1834
1872
  await result.finish(
1835
1873
  finalFinish ? {
@@ -1846,8 +1884,7 @@ function runPrompt(input) {
1846
1884
  context: "harness turn failed",
1847
1885
  error: err
1848
1886
  });
1849
- (_m = input.onTurnFailed) == null ? void 0 : _m.call(input);
1850
- result.fail(err);
1887
+ settleFailure(err);
1851
1888
  } finally {
1852
1889
  reader.releaseLock();
1853
1890
  }