ai 6.0.296 → 6.0.298

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/index.d.mts +36 -5
  3. package/dist/index.d.ts +36 -5
  4. package/dist/index.js +187 -32
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +187 -32
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/internal/index.js +1 -1
  9. package/dist/internal/index.mjs +1 -1
  10. package/docs/04-ai-sdk-ui/02-chatbot.mdx +10 -1
  11. package/docs/04-ai-sdk-ui/03-chatbot-message-persistence.mdx +8 -0
  12. package/docs/04-ai-sdk-ui/03-chatbot-resume-streams.mdx +10 -3
  13. package/docs/04-ai-sdk-ui/03-chatbot-tool-usage.mdx +10 -1
  14. package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +1 -1
  15. package/docs/07-reference/02-ai-sdk-ui/41-create-ui-message-stream-response.mdx +7 -0
  16. package/docs/07-reference/02-ai-sdk-ui/42-pipe-ui-message-stream-to-response.mdx +7 -0
  17. package/package.json +4 -4
  18. package/src/agent/create-agent-ui-stream-response.ts +3 -0
  19. package/src/agent/pipe-agent-ui-stream-to-response.ts +3 -0
  20. package/src/embed/embed-many.ts +5 -3
  21. package/src/generate-image/generate-image.ts +7 -2
  22. package/src/generate-text/stream-text-result.ts +5 -0
  23. package/src/generate-text/stream-text.ts +4 -1
  24. package/src/generate-video/generate-video.ts +6 -4
  25. package/src/registry/provider-registry.ts +1 -1
  26. package/src/ui/chat.ts +13 -4
  27. package/src/ui/http-chat-transport.ts +27 -1
  28. package/src/ui/last-assistant-message-is-complete-with-tool-calls.ts +15 -3
  29. package/src/ui/process-ui-message-stream.ts +51 -14
  30. package/src/ui/ui-messages.ts +14 -0
  31. package/src/ui/validate-ui-messages.ts +2 -0
  32. package/src/ui-message-stream/create-sse-stream-with-keep-alive.ts +89 -0
  33. package/src/ui-message-stream/create-ui-message-stream-response.ts +7 -1
  34. package/src/ui-message-stream/pipe-ui-message-stream-to-response.ts +7 -1
  35. package/src/ui-message-stream/ui-message-stream-response-init.ts +7 -0
  36. package/src/util/get-own.ts +18 -0
  37. package/src/util/set-own.ts +16 -0
package/dist/index.js CHANGED
@@ -1334,7 +1334,7 @@ function detectMediaType({
1334
1334
  var import_provider_utils3 = require("@ai-sdk/provider-utils");
1335
1335
 
1336
1336
  // src/version.ts
1337
- var VERSION = true ? "6.0.296" : "0.0.0-test";
1337
+ var VERSION = true ? "6.0.298" : "0.0.0-test";
1338
1338
 
1339
1339
  // src/util/download/download.ts
1340
1340
  var download = async ({
@@ -5712,6 +5712,75 @@ function pipeTextStreamToResponse({
5712
5712
  });
5713
5713
  }
5714
5714
 
5715
+ // src/ui-message-stream/create-sse-stream-with-keep-alive.ts
5716
+ var STREAM_OPEN_COMMENT = ": stream-open\n\n";
5717
+ var KEEP_ALIVE_COMMENT = ": keep-alive\n\n";
5718
+ function createSseStreamWithKeepAlive({
5719
+ stream,
5720
+ keepAliveMs
5721
+ }) {
5722
+ if (keepAliveMs == null) {
5723
+ return stream;
5724
+ }
5725
+ if (!Number.isFinite(keepAliveMs) || keepAliveMs <= 0 || keepAliveMs > 2147483647) {
5726
+ throw new Error(
5727
+ "keepAliveMs must be a positive finite timer duration no greater than 2147483647"
5728
+ );
5729
+ }
5730
+ const reader = stream.getReader();
5731
+ let keepAliveTimeout;
5732
+ let isCancelled = false;
5733
+ const clearKeepAliveTimeout = () => {
5734
+ clearTimeout(keepAliveTimeout);
5735
+ keepAliveTimeout = void 0;
5736
+ };
5737
+ const scheduleKeepAlive = (controller) => {
5738
+ clearKeepAliveTimeout();
5739
+ keepAliveTimeout = setTimeout(() => {
5740
+ if (isCancelled) {
5741
+ return;
5742
+ }
5743
+ if (controller.desiredSize != null && controller.desiredSize > 0) {
5744
+ controller.enqueue(KEEP_ALIVE_COMMENT);
5745
+ }
5746
+ scheduleKeepAlive(controller);
5747
+ }, keepAliveMs);
5748
+ };
5749
+ return new ReadableStream({
5750
+ start(controller) {
5751
+ controller.enqueue(STREAM_OPEN_COMMENT);
5752
+ scheduleKeepAlive(controller);
5753
+ },
5754
+ pull(controller) {
5755
+ return reader.read().then(
5756
+ (result) => {
5757
+ clearKeepAliveTimeout();
5758
+ if (isCancelled) {
5759
+ return;
5760
+ }
5761
+ if (result.done) {
5762
+ controller.close();
5763
+ } else {
5764
+ controller.enqueue(result.value);
5765
+ scheduleKeepAlive(controller);
5766
+ }
5767
+ },
5768
+ (error) => {
5769
+ clearKeepAliveTimeout();
5770
+ if (!isCancelled) {
5771
+ throw error;
5772
+ }
5773
+ }
5774
+ );
5775
+ },
5776
+ async cancel(reason) {
5777
+ isCancelled = true;
5778
+ clearKeepAliveTimeout();
5779
+ await reader.cancel(reason);
5780
+ }
5781
+ });
5782
+ }
5783
+
5715
5784
  // src/ui-message-stream/json-to-sse-transform-stream.ts
5716
5785
  var JsonToSseTransformStream = class extends TransformStream {
5717
5786
  constructor() {
@@ -5744,9 +5813,13 @@ function createUIMessageStreamResponse({
5744
5813
  statusText,
5745
5814
  headers,
5746
5815
  stream,
5816
+ keepAliveMs,
5747
5817
  consumeSseStream
5748
5818
  }) {
5749
- let sseStream = stream.pipeThrough(new JsonToSseTransformStream());
5819
+ let sseStream = createSseStreamWithKeepAlive({
5820
+ stream: stream.pipeThrough(new JsonToSseTransformStream()),
5821
+ keepAliveMs
5822
+ });
5750
5823
  if (consumeSseStream) {
5751
5824
  const [stream1, stream2] = sseStream.tee();
5752
5825
  sseStream = stream1;
@@ -5998,16 +6071,43 @@ function createStreamingUIMessageState({
5998
6071
  lastMessage,
5999
6072
  messageId
6000
6073
  }) {
6074
+ var _a23;
6075
+ const message = (lastMessage == null ? void 0 : lastMessage.role) === "assistant" ? lastMessage : {
6076
+ id: messageId,
6077
+ metadata: void 0,
6078
+ role: "assistant",
6079
+ parts: []
6080
+ };
6081
+ const partialToolCalls = createIdMap();
6082
+ const lastStepStartIndex = message.parts.findLastIndex(
6083
+ (part) => part.type === "step-start"
6084
+ );
6085
+ let staticToolIndex = 0;
6086
+ for (const part of message.parts.slice(lastStepStartIndex + 1)) {
6087
+ if (!isToolUIPart(part)) {
6088
+ continue;
6089
+ }
6090
+ const index = staticToolIndex;
6091
+ if (isStaticToolUIPart(part)) {
6092
+ staticToolIndex++;
6093
+ }
6094
+ if (part.state !== "input-streaming") {
6095
+ continue;
6096
+ }
6097
+ partialToolCalls[part.toolCallId] = {
6098
+ text: (_a23 = part.rawInput) != null ? _a23 : "",
6099
+ index,
6100
+ toolName: part.type === "dynamic-tool" ? part.toolName : getStaticToolName(part),
6101
+ dynamic: part.type === "dynamic-tool",
6102
+ title: part.title,
6103
+ toolMetadata: part.toolMetadata
6104
+ };
6105
+ }
6001
6106
  return {
6002
- message: (lastMessage == null ? void 0 : lastMessage.role) === "assistant" ? lastMessage : {
6003
- id: messageId,
6004
- metadata: void 0,
6005
- role: "assistant",
6006
- parts: []
6007
- },
6107
+ message,
6008
6108
  activeTextParts: createIdMap(),
6009
6109
  activeReasoningParts: createIdMap(),
6010
- partialToolCalls: createIdMap()
6110
+ partialToolCalls
6011
6111
  };
6012
6112
  }
6013
6113
  function processUIMessageStream({
@@ -6108,7 +6208,7 @@ function processUIMessageStream({
6108
6208
  }
6109
6209
  }
6110
6210
  function updateDynamicToolPart(options, existingPart) {
6111
- var _a24, _b2;
6211
+ var _a24;
6112
6212
  const part = existingPart != null ? existingPart : getCurrentStepParts().find(
6113
6213
  (part2) => part2.type === "dynamic-tool" && part2.toolCallId === options.toolCallId
6114
6214
  );
@@ -6120,7 +6220,7 @@ function processUIMessageStream({
6120
6220
  anyPart.input = anyOptions.input;
6121
6221
  anyPart.output = anyOptions.output;
6122
6222
  anyPart.errorText = anyOptions.errorText;
6123
- anyPart.rawInput = (_a24 = anyOptions.rawInput) != null ? _a24 : anyPart.rawInput;
6223
+ anyPart.rawInput = anyOptions.rawInput;
6124
6224
  anyPart.preliminary = anyOptions.preliminary;
6125
6225
  if (options.title !== void 0) {
6126
6226
  anyPart.title = options.title;
@@ -6128,7 +6228,7 @@ function processUIMessageStream({
6128
6228
  if (options.toolMetadata !== void 0) {
6129
6229
  anyPart.toolMetadata = options.toolMetadata;
6130
6230
  }
6131
- anyPart.providerExecuted = (_b2 = anyOptions.providerExecuted) != null ? _b2 : part.providerExecuted;
6231
+ anyPart.providerExecuted = (_a24 = anyOptions.providerExecuted) != null ? _a24 : part.providerExecuted;
6132
6232
  const providerMetadata = anyOptions.providerMetadata;
6133
6233
  if (providerMetadata != null) {
6134
6234
  if (options.state === "output-available" || options.state === "output-error") {
@@ -6344,6 +6444,7 @@ function processUIMessageStream({
6344
6444
  toolName: partialToolCall.toolName,
6345
6445
  state: "input-streaming",
6346
6446
  input: partialArgs,
6447
+ rawInput: partialToolCall.text,
6347
6448
  title: partialToolCall.title,
6348
6449
  toolMetadata: partialToolCall.toolMetadata
6349
6450
  });
@@ -6353,6 +6454,7 @@ function processUIMessageStream({
6353
6454
  toolName: partialToolCall.toolName,
6354
6455
  state: "input-streaming",
6355
6456
  input: partialArgs,
6457
+ rawInput: partialToolCall.text,
6356
6458
  title: partialToolCall.title,
6357
6459
  toolMetadata: partialToolCall.toolMetadata
6358
6460
  });
@@ -6741,9 +6843,13 @@ function pipeUIMessageStreamToResponse({
6741
6843
  statusText,
6742
6844
  headers,
6743
6845
  stream,
6846
+ keepAliveMs,
6744
6847
  consumeSseStream
6745
6848
  }) {
6746
- let sseStream = stream.pipeThrough(new JsonToSseTransformStream());
6849
+ let sseStream = createSseStreamWithKeepAlive({
6850
+ stream: stream.pipeThrough(new JsonToSseTransformStream()),
6851
+ keepAliveMs
6852
+ });
6747
6853
  if (consumeSseStream) {
6748
6854
  const [stream1, stream2] = sseStream.tee();
6749
6855
  sseStream = stream1;
@@ -8905,7 +9011,7 @@ var DefaultStreamTextResult = class {
8905
9011
  sendStart = true,
8906
9012
  sendFinish = true,
8907
9013
  onError = () => "An error occurred."
8908
- // prevent leaking server error details to the client by default
9014
+ // masks errors except provider-executed tool execution errors
8909
9015
  } = {}) {
8910
9016
  let outcome = { status: "unknown" };
8911
9017
  let hasFatalFailure = false;
@@ -9943,6 +10049,7 @@ var uiMessagesSchema = (0, import_provider_utils24.lazySchema)(() => {
9943
10049
  toolMetadata: toolMetadataSchema2.optional(),
9944
10050
  state: import_v48.z.literal("input-streaming"),
9945
10051
  input: import_v48.z.unknown().optional(),
10052
+ rawInput: import_v48.z.string().optional(),
9946
10053
  providerExecuted: import_v48.z.boolean().optional(),
9947
10054
  callProviderMetadata: providerMetadataSchema.optional(),
9948
10055
  output: import_v48.z.never().optional(),
@@ -10039,6 +10146,7 @@ var uiMessagesSchema = (0, import_provider_utils24.lazySchema)(() => {
10039
10146
  providerExecuted: import_v48.z.boolean().optional(),
10040
10147
  callProviderMetadata: providerMetadataSchema.optional(),
10041
10148
  input: import_v48.z.unknown().optional(),
10149
+ rawInput: import_v48.z.string().optional(),
10042
10150
  output: import_v48.z.never().optional(),
10043
10151
  errorText: import_v48.z.never().optional(),
10044
10152
  approval: import_v48.z.never().optional()
@@ -10360,6 +10468,7 @@ async function createAgentUIStreamResponse({
10360
10468
  headers,
10361
10469
  status,
10362
10470
  statusText,
10471
+ keepAliveMs,
10363
10472
  consumeSseStream,
10364
10473
  ...options
10365
10474
  }) {
@@ -10367,6 +10476,7 @@ async function createAgentUIStreamResponse({
10367
10476
  headers,
10368
10477
  status,
10369
10478
  statusText,
10479
+ keepAliveMs,
10370
10480
  consumeSseStream,
10371
10481
  stream: await createAgentUIStream(options)
10372
10482
  });
@@ -10378,6 +10488,7 @@ async function pipeAgentUIStreamToResponse({
10378
10488
  headers,
10379
10489
  status,
10380
10490
  statusText,
10491
+ keepAliveMs,
10381
10492
  consumeSseStream,
10382
10493
  ...options
10383
10494
  }) {
@@ -10386,6 +10497,7 @@ async function pipeAgentUIStreamToResponse({
10386
10497
  headers,
10387
10498
  status,
10388
10499
  statusText,
10500
+ keepAliveMs,
10389
10501
  consumeSseStream,
10390
10502
  stream: await createAgentUIStream(options)
10391
10503
  });
@@ -10520,6 +10632,21 @@ var DefaultEmbedResult = class {
10520
10632
  }
10521
10633
  };
10522
10634
 
10635
+ // src/util/get-own.ts
10636
+ function getOwn(obj, key) {
10637
+ return obj != null && Object.hasOwn(obj, key) ? obj[key] : void 0;
10638
+ }
10639
+
10640
+ // src/util/set-own.ts
10641
+ function setOwn(object2, key, value) {
10642
+ Object.defineProperty(object2, key, {
10643
+ value,
10644
+ enumerable: true,
10645
+ configurable: true,
10646
+ writable: true
10647
+ });
10648
+ }
10649
+
10523
10650
  // src/embed/embed-many.ts
10524
10651
  var import_provider_utils28 = require("@ai-sdk/provider-utils");
10525
10652
 
@@ -10769,10 +10896,10 @@ async function embedMany({
10769
10896
  for (const [providerName, metadata] of Object.entries(
10770
10897
  result.providerMetadata
10771
10898
  )) {
10772
- providerMetadata[providerName] = {
10773
- ...providerMetadata[providerName],
10899
+ setOwn(providerMetadata, providerName, {
10900
+ ...getOwn(providerMetadata, providerName),
10774
10901
  ...metadata
10775
- };
10902
+ });
10776
10903
  }
10777
10904
  }
10778
10905
  }
@@ -10968,10 +11095,13 @@ async function generateImage({
10968
11095
  delete providerMetadata[providerName].images;
10969
11096
  }
10970
11097
  } else {
10971
- (_b = providerMetadata[providerName]) != null ? _b : providerMetadata[providerName] = { images: [] };
10972
- providerMetadata[providerName].images.push(
11098
+ const currentEntry = (_b = getOwn(providerMetadata, providerName)) != null ? _b : {
11099
+ images: []
11100
+ };
11101
+ currentEntry.images.push(
10973
11102
  ...result.providerMetadata[providerName].images
10974
11103
  );
11104
+ setOwn(providerMetadata, providerName, currentEntry);
10975
11105
  }
10976
11106
  }
10977
11107
  }
@@ -12915,12 +13045,12 @@ async function experimental_generateVideo({
12915
13045
  for (const [providerName, metadata] of Object.entries(
12916
13046
  result.providerMetadata
12917
13047
  )) {
12918
- const existingMetadata = providerMetadata[providerName];
13048
+ const existingMetadata = getOwn(providerMetadata, providerName);
12919
13049
  if (existingMetadata != null && typeof existingMetadata === "object") {
12920
- providerMetadata[providerName] = {
13050
+ setOwn(providerMetadata, providerName, {
12921
13051
  ...existingMetadata,
12922
13052
  ...metadata
12923
- };
13053
+ });
12924
13054
  if ("videos" in existingMetadata && Array.isArray(existingMetadata.videos) && "videos" in metadata && Array.isArray(metadata.videos)) {
12925
13055
  providerMetadata[providerName].videos = [
12926
13056
  ...existingMetadata.videos,
@@ -12928,7 +13058,7 @@ async function experimental_generateVideo({
12928
13058
  ];
12929
13059
  }
12930
13060
  } else {
12931
- providerMetadata[providerName] = metadata;
13061
+ setOwn(providerMetadata, providerName, metadata);
12932
13062
  }
12933
13063
  }
12934
13064
  }
@@ -13799,7 +13929,7 @@ var DefaultProviderRegistry = class {
13799
13929
  languageModelMiddleware,
13800
13930
  imageModelMiddleware
13801
13931
  }) {
13802
- this.providers = {};
13932
+ this.providers = /* @__PURE__ */ Object.create(null);
13803
13933
  this.separator = separator;
13804
13934
  this.languageModelMiddleware = languageModelMiddleware;
13805
13935
  this.imageModelMiddleware = imageModelMiddleware;
@@ -14308,6 +14438,10 @@ var import_provider_utils42 = require("@ai-sdk/provider-utils");
14308
14438
 
14309
14439
  // src/ui/http-chat-transport.ts
14310
14440
  var import_provider_utils41 = require("@ai-sdk/provider-utils");
14441
+ function appendPathToUrl(url, path) {
14442
+ const queryOrFragmentStart = url.search(/[?#]/);
14443
+ return queryOrFragmentStart === -1 ? `${url}${path}` : `${url.slice(0, queryOrFragmentStart)}${path}${url.slice(queryOrFragmentStart)}`;
14444
+ }
14311
14445
  var HttpChatTransport = class {
14312
14446
  constructor({
14313
14447
  api = "/api/chat",
@@ -14382,7 +14516,7 @@ var HttpChatTransport = class {
14382
14516
  return this.processResponseStream(response.body);
14383
14517
  }
14384
14518
  async reconnectToStream(options) {
14385
- var _a23, _b, _c, _d, _e;
14519
+ var _a23, _b, _c, _d;
14386
14520
  const resolvedBody = await (0, import_provider_utils41.resolve)(this.body);
14387
14521
  const resolvedHeaders = await (0, import_provider_utils41.resolve)(this.headers);
14388
14522
  const resolvedCredentials = await (0, import_provider_utils41.resolve)(this.credentials);
@@ -14398,10 +14532,23 @@ var HttpChatTransport = class {
14398
14532
  credentials: resolvedCredentials,
14399
14533
  requestMetadata: options.metadata
14400
14534
  }));
14401
- const api = (_b = preparedRequest == null ? void 0 : preparedRequest.api) != null ? _b : `${this.api}/${options.chatId}/stream`;
14535
+ let api = preparedRequest == null ? void 0 : preparedRequest.api;
14536
+ if (api == null) {
14537
+ if (options.chatId === "." || options.chatId === "..") {
14538
+ throw new InvalidArgumentError({
14539
+ parameter: "chatId",
14540
+ value: options.chatId,
14541
+ message: 'Chat IDs must not be "." or ".." when using the default reconnect URL.'
14542
+ });
14543
+ }
14544
+ api = appendPathToUrl(
14545
+ this.api,
14546
+ `/${encodeURIComponent(options.chatId)}/stream`
14547
+ );
14548
+ }
14402
14549
  const headers = (preparedRequest == null ? void 0 : preparedRequest.headers) !== void 0 ? (0, import_provider_utils41.normalizeHeaders)(preparedRequest.headers) : baseHeaders;
14403
- const credentials = (_c = preparedRequest == null ? void 0 : preparedRequest.credentials) != null ? _c : resolvedCredentials;
14404
- const fetch2 = (_d = this.fetch) != null ? _d : globalThis.fetch;
14550
+ const credentials = (_b = preparedRequest == null ? void 0 : preparedRequest.credentials) != null ? _b : resolvedCredentials;
14551
+ const fetch2 = (_c = this.fetch) != null ? _c : globalThis.fetch;
14405
14552
  const response = await fetch2(api, {
14406
14553
  method: "GET",
14407
14554
  headers,
@@ -14413,7 +14560,7 @@ var HttpChatTransport = class {
14413
14560
  }
14414
14561
  if (!response.ok) {
14415
14562
  throw new Error(
14416
- (_e = await response.text()) != null ? _e : "Failed to fetch the chat response."
14563
+ (_d = await response.text()) != null ? _d : "Failed to fetch the chat response."
14417
14564
  );
14418
14565
  }
14419
14566
  if (!response.body) {
@@ -14808,6 +14955,9 @@ var AbstractChat = class {
14808
14955
  const lastMessage = this.lastMessage;
14809
14956
  const responseMessageIndex = trigger === "submit-message" && messageId != null ? this.state.messages.findIndex((message) => message.id === messageId) : this.state.messages.length - 1;
14810
14957
  const responseMessage = responseMessageIndex === -1 ? lastMessage : this.state.messages[responseMessageIndex];
14958
+ const resumableResponseMessage = trigger === "resume-stream" && (responseMessage == null ? void 0 : responseMessage.role) === "assistant" && responseMessage.parts.some(
14959
+ (part) => isToolUIPart(part) && part.state === "input-streaming"
14960
+ ) ? this.state.snapshot(responseMessage) : void 0;
14811
14961
  const usesEarlierAssistantMessage = responseMessageIndex !== -1 && responseMessageIndex < this.state.messages.length - 1 && (responseMessage == null ? void 0 : responseMessage.role) === "assistant";
14812
14962
  let isAbort = false;
14813
14963
  let isDisconnect = false;
@@ -14816,7 +14966,7 @@ var AbstractChat = class {
14816
14966
  try {
14817
14967
  const response = {
14818
14968
  state: trigger === "resume-stream" && this.resumableStreamState != null ? this.resumableStreamState : createStreamingUIMessageState({
14819
- lastMessage: trigger === "resume-stream" || trigger === "regenerate-message" ? void 0 : this.state.snapshot(responseMessage),
14969
+ lastMessage: trigger === "resume-stream" ? resumableResponseMessage : trigger === "regenerate-message" ? void 0 : this.state.snapshot(responseMessage),
14820
14970
  messageId: this.generateId()
14821
14971
  }),
14822
14972
  abortController
@@ -15042,8 +15192,13 @@ function lastAssistantMessageIsCompleteWithToolCalls({
15042
15192
  const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => {
15043
15193
  return part.type === "step-start" ? index : lastIndex;
15044
15194
  }, -1);
15045
- const lastStepToolInvocations = message.parts.slice(lastStepStartIndex + 1).filter(isToolUIPart).filter((part) => !part.providerExecuted);
15046
- return lastStepToolInvocations.length > 0 && lastStepToolInvocations.every(
15195
+ const lastStepParts = message.parts.slice(lastStepStartIndex + 1);
15196
+ const lastStepToolInvocations = lastStepParts.filter(isToolUIPart).filter((part) => !part.providerExecuted);
15197
+ const lastToolInvocationIndex = lastStepParts.reduce(
15198
+ (lastIndex, part, index) => isToolUIPart(part) && !part.providerExecuted ? index : lastIndex,
15199
+ -1
15200
+ );
15201
+ return lastStepToolInvocations.length > 0 && !lastStepParts.slice(lastToolInvocationIndex + 1).some((part) => part.type === "text" && part.state !== "done") && lastStepToolInvocations.every(
15047
15202
  (part) => part.state === "output-available" && part.preliminary !== true || part.state === "output-error"
15048
15203
  );
15049
15204
  }