ai 6.0.259 → 6.0.260

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,13 @@
1
1
  # ai
2
2
 
3
+ ## 6.0.260
4
+
5
+ ### Patch Changes
6
+
7
+ - 98c656f: fix: reject `streamObject` result promises and report failed completion when the provider stream errors
8
+ - b253d52: Filter preliminary tool outputs when `ignoreIncompleteToolCalls` is enabled.
9
+ - 9e15cb4: Prevent automatic tool execution when a model call ends with an unsafe finish reason.
10
+
3
11
  ## 6.0.259
4
12
 
5
13
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1304,7 +1304,7 @@ function detectMediaType({
1304
1304
  var import_provider_utils3 = require("@ai-sdk/provider-utils");
1305
1305
 
1306
1306
  // src/version.ts
1307
- var VERSION = true ? "6.0.259" : "0.0.0-test";
1307
+ var VERSION = true ? "6.0.260" : "0.0.0-test";
1308
1308
 
1309
1309
  // src/util/download/download.ts
1310
1310
  var download = async ({
@@ -3216,6 +3216,11 @@ async function isApprovalNeeded({
3216
3216
  });
3217
3217
  }
3218
3218
 
3219
+ // src/generate-text/is-tool-execution-allowed-finish-reason.ts
3220
+ function isToolExecutionAllowedFinishReason(finishReason) {
3221
+ return finishReason === "stop" || finishReason === "tool-calls";
3222
+ }
3223
+
3219
3224
  // src/generate-text/tool-approval-signature.ts
3220
3225
  var import_provider_utils11 = require("@ai-sdk/provider-utils");
3221
3226
  var encoder = new TextEncoder();
@@ -4979,7 +4984,9 @@ async function generateText({
4979
4984
  clientToolCalls = stepToolCalls.filter(
4980
4985
  (toolCall) => !toolCall.providerExecuted
4981
4986
  );
4982
- if (stepToolSet != null) {
4987
+ if (stepToolSet != null && isToolExecutionAllowedFinishReason(
4988
+ currentModelResponse.finishReason.unified
4989
+ )) {
4983
4990
  clientToolOutputs.push(
4984
4991
  ...await executeTools({
4985
4992
  toolCalls: clientToolCalls.filter(
@@ -6639,32 +6646,33 @@ function createResolvablePromise() {
6639
6646
 
6640
6647
  // src/util/create-stitchable-stream.ts
6641
6648
  function createStitchableStream() {
6642
- let innerStreamReaders = [];
6649
+ let innerStreams = [];
6643
6650
  let controller = null;
6644
6651
  let isClosed = false;
6645
6652
  let waitForNewStream = createResolvablePromise();
6646
6653
  const terminate = () => {
6647
6654
  isClosed = true;
6648
6655
  waitForNewStream.resolve();
6649
- innerStreamReaders.forEach((reader) => reader.cancel());
6650
- innerStreamReaders = [];
6656
+ innerStreams.forEach(({ reader }) => reader.cancel());
6657
+ innerStreams = [];
6651
6658
  controller == null ? void 0 : controller.close();
6652
6659
  };
6653
6660
  const processPull = async () => {
6654
- if (isClosed && innerStreamReaders.length === 0) {
6661
+ var _a22, _b;
6662
+ if (isClosed && innerStreams.length === 0) {
6655
6663
  controller == null ? void 0 : controller.close();
6656
6664
  return;
6657
6665
  }
6658
- if (innerStreamReaders.length === 0) {
6666
+ if (innerStreams.length === 0) {
6659
6667
  waitForNewStream = createResolvablePromise();
6660
6668
  await waitForNewStream.promise;
6661
6669
  return processPull();
6662
6670
  }
6663
6671
  try {
6664
- const { value, done } = await innerStreamReaders[0].read();
6672
+ const { value, done } = await innerStreams[0].reader.read();
6665
6673
  if (done) {
6666
- innerStreamReaders.shift();
6667
- if (innerStreamReaders.length === 0 && isClosed) {
6674
+ innerStreams.shift();
6675
+ if (innerStreams.length === 0 && isClosed) {
6668
6676
  controller == null ? void 0 : controller.close();
6669
6677
  } else {
6670
6678
  await processPull();
@@ -6673,8 +6681,9 @@ function createStitchableStream() {
6673
6681
  controller == null ? void 0 : controller.enqueue(value);
6674
6682
  }
6675
6683
  } catch (error) {
6684
+ (_b = (_a22 = innerStreams[0]).onError) == null ? void 0 : _b.call(_a22, error);
6676
6685
  controller == null ? void 0 : controller.error(error);
6677
- innerStreamReaders.shift();
6686
+ innerStreams.shift();
6678
6687
  terminate();
6679
6688
  }
6680
6689
  };
@@ -6685,18 +6694,21 @@ function createStitchableStream() {
6685
6694
  },
6686
6695
  pull: processPull,
6687
6696
  async cancel() {
6688
- for (const reader of innerStreamReaders) {
6697
+ for (const { reader } of innerStreams) {
6689
6698
  await reader.cancel();
6690
6699
  }
6691
- innerStreamReaders = [];
6700
+ innerStreams = [];
6692
6701
  isClosed = true;
6693
6702
  }
6694
6703
  }),
6695
- addStream: (innerStream) => {
6704
+ addStream: (innerStream, callbacks) => {
6696
6705
  if (isClosed) {
6697
6706
  throw new Error("Cannot add inner stream: outer stream is closed");
6698
6707
  }
6699
- innerStreamReaders.push(innerStream.getReader());
6708
+ innerStreams.push({
6709
+ reader: innerStream.getReader(),
6710
+ ...callbacks
6711
+ });
6700
6712
  waitForNewStream.resolve();
6701
6713
  },
6702
6714
  /**
@@ -6706,7 +6718,7 @@ function createStitchableStream() {
6706
6718
  close: () => {
6707
6719
  isClosed = true;
6708
6720
  waitForNewStream.resolve();
6709
- if (innerStreamReaders.length === 0) {
6721
+ if (innerStreams.length === 0) {
6710
6722
  controller == null ? void 0 : controller.close();
6711
6723
  }
6712
6724
  },
@@ -6768,6 +6780,7 @@ function runToolsTransformation({
6768
6780
  }
6769
6781
  }
6770
6782
  const outstandingToolResults = /* @__PURE__ */ new Set();
6783
+ const toolCallsToExecute = [];
6771
6784
  const toolCallsByToolCallId = /* @__PURE__ */ new Map();
6772
6785
  let canClose = false;
6773
6786
  let finishChunk = void 0;
@@ -6779,6 +6792,36 @@ function runToolsTransformation({
6779
6792
  closeToolResultsStream();
6780
6793
  }
6781
6794
  }
6795
+ function executeToolCallAfterFinish(toolCall) {
6796
+ const toolExecutionId = generateId2();
6797
+ outstandingToolResults.add(toolExecutionId);
6798
+ executeToolCall({
6799
+ toolCall,
6800
+ tools,
6801
+ tracer,
6802
+ telemetry,
6803
+ messages,
6804
+ abortSignal,
6805
+ experimental_context,
6806
+ stepNumber,
6807
+ model,
6808
+ onToolCallStart,
6809
+ onToolCallFinish,
6810
+ onPreliminaryToolResult: (result) => {
6811
+ enqueueToolResult(result);
6812
+ }
6813
+ }).then((result) => {
6814
+ enqueueToolResult(result);
6815
+ }).catch((error) => {
6816
+ enqueueToolResult({
6817
+ type: "error",
6818
+ error
6819
+ });
6820
+ }).finally(() => {
6821
+ outstandingToolResults.delete(toolExecutionId);
6822
+ attemptClose();
6823
+ });
6824
+ }
6782
6825
  const forwardStream = new TransformStream({
6783
6826
  async transform(chunk, controller) {
6784
6827
  const chunkType = chunk.type;
@@ -6819,6 +6862,13 @@ function runToolsTransformation({
6819
6862
  usage: asLanguageModelUsage(chunk.usage),
6820
6863
  providerMetadata: chunk.providerMetadata
6821
6864
  };
6865
+ if (isToolExecutionAllowedFinishReason(chunk.finishReason.unified)) {
6866
+ for (const toolCall of toolCallsToExecute.splice(0)) {
6867
+ executeToolCallAfterFinish(toolCall);
6868
+ }
6869
+ } else {
6870
+ toolCallsToExecute.length = 0;
6871
+ }
6822
6872
  break;
6823
6873
  }
6824
6874
  case "tool-approval-request": {
@@ -6850,7 +6900,7 @@ function runToolsTransformation({
6850
6900
  messages
6851
6901
  });
6852
6902
  toolCallsByToolCallId.set(toolCall.toolCallId, toolCall);
6853
- controller.enqueue(toolCall);
6903
+ controller.enqueue({ ...toolCall });
6854
6904
  if (toolCall.invalid) {
6855
6905
  if (!toolCall.providerExecuted) {
6856
6906
  enqueueToolResult({
@@ -6902,34 +6952,7 @@ function runToolsTransformation({
6902
6952
  break;
6903
6953
  }
6904
6954
  if (tool2.execute != null && toolCall.providerExecuted !== true) {
6905
- const toolExecutionId = generateId2();
6906
- outstandingToolResults.add(toolExecutionId);
6907
- executeToolCall({
6908
- toolCall,
6909
- tools,
6910
- tracer,
6911
- telemetry,
6912
- messages,
6913
- abortSignal,
6914
- experimental_context,
6915
- stepNumber,
6916
- model,
6917
- onToolCallStart,
6918
- onToolCallFinish,
6919
- onPreliminaryToolResult: (result) => {
6920
- enqueueToolResult(result);
6921
- }
6922
- }).then((result) => {
6923
- enqueueToolResult(result);
6924
- }).catch((error) => {
6925
- enqueueToolResult({
6926
- type: "error",
6927
- error
6928
- });
6929
- }).finally(() => {
6930
- outstandingToolResults.delete(toolExecutionId);
6931
- attemptClose();
6932
- });
6955
+ toolCallsToExecute.push(toolCall);
6933
6956
  }
6934
6957
  } catch (error) {
6935
6958
  enqueueToolResult({ type: "error", error });
@@ -9106,7 +9129,7 @@ async function convertToModelMessages(messages, options) {
9106
9129
  messages = messages.map((message) => ({
9107
9130
  ...message,
9108
9131
  parts: message.parts.filter(
9109
- (part) => !isToolUIPart(part) || part.state === "approval-responded" || part.state === "output-available" || part.state === "output-error" || part.state === "output-denied"
9132
+ (part) => !isToolUIPart(part) || part.state === "approval-responded" || part.state === "output-available" && part.preliminary !== true || part.state === "output-error" || part.state === "output-denied"
9110
9133
  )
9111
9134
  }));
9112
9135
  }
@@ -11281,6 +11304,12 @@ function simulateReadableStream({
11281
11304
 
11282
11305
  // src/generate-object/stream-object.ts
11283
11306
  var originalGenerateId4 = (0, import_provider_utils32.createIdGenerator)({ prefix: "aiobj", size: 24 });
11307
+ async function markPromiseAsHandled(promise) {
11308
+ try {
11309
+ await promise;
11310
+ } catch (e) {
11311
+ }
11312
+ }
11284
11313
  function streamObject(options) {
11285
11314
  const {
11286
11315
  model,
@@ -11515,6 +11544,7 @@ var DefaultStreamObjectResult = class {
11515
11544
  let providerMetadata;
11516
11545
  let object2;
11517
11546
  let error;
11547
+ let terminalError;
11518
11548
  let accumulatedText = "";
11519
11549
  let textDelta = "";
11520
11550
  let fullResponse = {
@@ -11585,16 +11615,27 @@ var DefaultStreamObjectResult = class {
11585
11615
  };
11586
11616
  break;
11587
11617
  }
11618
+ case "error": {
11619
+ if (terminalError === void 0) {
11620
+ const wrappedError = wrapGatewayError(chunk.error);
11621
+ terminalError = { error: wrappedError };
11622
+ error = wrappedError;
11623
+ finishReason = "error";
11624
+ self.rejectResultPromises(wrappedError);
11625
+ }
11626
+ controller.enqueue(chunk);
11627
+ break;
11628
+ }
11588
11629
  case "finish": {
11589
11630
  if (textDelta !== "") {
11590
11631
  controller.enqueue({ type: "text-delta", textDelta });
11591
11632
  }
11592
- finishReason = chunk.finishReason.unified;
11633
+ finishReason = terminalError === void 0 ? chunk.finishReason.unified : "error";
11593
11634
  usage = asLanguageModelUsage(chunk.usage);
11594
11635
  providerMetadata = chunk.providerMetadata;
11595
11636
  controller.enqueue({
11596
11637
  ...chunk,
11597
- finishReason: chunk.finishReason.unified,
11638
+ finishReason,
11598
11639
  usage,
11599
11640
  response: fullResponse
11600
11641
  });
@@ -11603,6 +11644,9 @@ var DefaultStreamObjectResult = class {
11603
11644
  provider: model.provider,
11604
11645
  model: model.modelId
11605
11646
  });
11647
+ if (terminalError !== void 0) {
11648
+ break;
11649
+ }
11606
11650
  self._usage.resolve(usage);
11607
11651
  self._providerMetadata.resolve(providerMetadata);
11608
11652
  self._warnings.resolve(warnings);
@@ -11705,9 +11749,16 @@ var DefaultStreamObjectResult = class {
11705
11749
  }
11706
11750
  })
11707
11751
  );
11708
- stitchableStream.addStream(transformedStream);
11752
+ stitchableStream.addStream(transformedStream, {
11753
+ onError(error2) {
11754
+ const wrappedError = wrapGatewayError(error2);
11755
+ self.rejectResultPromises(wrappedError);
11756
+ void onError({ error: wrappedError });
11757
+ }
11758
+ });
11709
11759
  }
11710
11760
  }).catch((error) => {
11761
+ self.rejectResultPromises(error);
11711
11762
  stitchableStream.addStream(
11712
11763
  new ReadableStream({
11713
11764
  start(controller) {
@@ -11721,6 +11772,24 @@ var DefaultStreamObjectResult = class {
11721
11772
  });
11722
11773
  this.outputStrategy = outputStrategy;
11723
11774
  }
11775
+ rejectResultPromises(error) {
11776
+ this.rejectResultPromise({ delayedPromise: this._object, error });
11777
+ this.rejectResultPromise({ delayedPromise: this._usage, error });
11778
+ this.rejectResultPromise({ delayedPromise: this._providerMetadata, error });
11779
+ this.rejectResultPromise({ delayedPromise: this._warnings, error });
11780
+ this.rejectResultPromise({ delayedPromise: this._request, error });
11781
+ this.rejectResultPromise({ delayedPromise: this._response, error });
11782
+ this.rejectResultPromise({ delayedPromise: this._finishReason, error });
11783
+ }
11784
+ rejectResultPromise({
11785
+ delayedPromise,
11786
+ error
11787
+ }) {
11788
+ if (delayedPromise.isPending()) {
11789
+ delayedPromise.reject(error);
11790
+ markPromiseAsHandled(delayedPromise.promise);
11791
+ }
11792
+ }
11724
11793
  get object() {
11725
11794
  return this._object.promise;
11726
11795
  }