ai 5.0.269 → 5.0.270

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,18 @@
1
1
  # ai
2
2
 
3
+ ## 5.0.270
4
+
5
+ ### Patch Changes
6
+
7
+ - 1849a5f: fix(ai): preserve hydrated partial static tool input across stream resumptions
8
+ - 5381c08: fix(ai): keep idle UI message streams open with optional SSE heartbeats
9
+ - 06e8d1c: Encode chat IDs in default stream reconnection URLs so slashes, query delimiters, and fragments stay within the ID. Reject standalone `.` and `..` IDs before fetching. Custom URLs returned by `prepareReconnectToStreamRequest` remain unchanged.
10
+ - 58d303f: Preserve prototype-named tools, providers, and provider metadata as own properties without changing lookup object prototypes. Prevent inherited names from resolving as registered providers or causing image metadata aggregation to fail.
11
+ - 430ae0a: Prevent automatic chat resumption when completed tool output is followed by terminal text without a completed stream state, while preserving resumption after completed model text.
12
+ - Updated dependencies [07e394b]
13
+ - Updated dependencies [b6cf409]
14
+ - @ai-sdk/gateway@2.0.161
15
+
3
16
  ## 5.0.269
4
17
 
5
18
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1632,6 +1632,13 @@ type UIToolInvocation<TOOL extends UITool | Tool> = {
1632
1632
  state: 'input-streaming';
1633
1633
  input: DeepPartial<asUITool<TOOL>['input']> | undefined;
1634
1634
  providerExecuted?: boolean;
1635
+ /**
1636
+ * The raw tool input text received so far.
1637
+ *
1638
+ * This is used to continue input streaming when a message is persisted
1639
+ * and later resumed.
1640
+ */
1641
+ rawInput?: string;
1635
1642
  output?: never;
1636
1643
  errorText?: never;
1637
1644
  } | {
@@ -1681,6 +1688,13 @@ type DynamicToolUIPart = {
1681
1688
  } & ({
1682
1689
  state: 'input-streaming';
1683
1690
  input: unknown | undefined;
1691
+ /**
1692
+ * The raw tool input text received so far.
1693
+ *
1694
+ * This is used to continue input streaming when a message is persisted
1695
+ * and later resumed.
1696
+ */
1697
+ rawInput?: string;
1684
1698
  output?: never;
1685
1699
  errorText?: never;
1686
1700
  } | {
@@ -1896,6 +1910,12 @@ type UIMessageStreamOnFinishCallback<UI_MESSAGE extends UIMessage> = (event: {
1896
1910
  }) => PromiseLike<void> | void;
1897
1911
 
1898
1912
  type UIMessageStreamResponseInit = ResponseInit & {
1913
+ /**
1914
+ * Optional interval in milliseconds for sending SSE keep-alive comments.
1915
+ * When set, an opening comment is sent immediately and additional comments
1916
+ * are sent after the stream has been idle for the configured interval.
1917
+ */
1918
+ keepAliveMs?: number;
1899
1919
  consumeSseStream?: (options: {
1900
1920
  stream: ReadableStream<string>;
1901
1921
  }) => PromiseLike<void> | void;
@@ -3926,7 +3946,7 @@ originalMessages, onFinish, generateId, }: {
3926
3946
  generateId?: IdGenerator;
3927
3947
  }): ReadableStream<InferUIMessageChunk<UI_MESSAGE>>;
3928
3948
 
3929
- declare function createUIMessageStreamResponse({ status, statusText, headers, stream, consumeSseStream, }: UIMessageStreamResponseInit & {
3949
+ declare function createUIMessageStreamResponse({ status, statusText, headers, stream, keepAliveMs, consumeSseStream, }: UIMessageStreamResponseInit & {
3930
3950
  stream: ReadableStream<UIMessageChunk>;
3931
3951
  }): Response;
3932
3952
 
@@ -3934,7 +3954,7 @@ declare class JsonToSseTransformStream extends TransformStream<unknown, string>
3934
3954
  constructor();
3935
3955
  }
3936
3956
 
3937
- declare function pipeUIMessageStreamToResponse({ response, status, statusText, headers, stream, consumeSseStream, }: {
3957
+ declare function pipeUIMessageStreamToResponse({ response, status, statusText, headers, stream, keepAliveMs, consumeSseStream, }: {
3938
3958
  response: ServerResponse;
3939
3959
  stream: ReadableStream<UIMessageChunk>;
3940
3960
  } & UIMessageStreamResponseInit): Promise<void>;
@@ -4392,9 +4412,11 @@ declare class DefaultChatTransport<UI_MESSAGE extends UIMessage> extends HttpCha
4392
4412
  }
4393
4413
 
4394
4414
  /**
4395
- Check if the message is an assistant message with completed tool calls.
4396
- The last step of the message must have at least one tool invocation and
4397
- all tool invocations must have a result.
4415
+ * Check if the last message is an assistant message with completed tool calls.
4416
+ * The last step of the message must have at least one tool invocation and
4417
+ * all tool invocations must have a result. Completed model text may follow
4418
+ * the tool invocation because client-side tool results update parts in place,
4419
+ * but trailing text without a completed stream state prevents resubmission.
4398
4420
  */
4399
4421
  declare function lastAssistantMessageIsCompleteWithToolCalls({ messages, }: {
4400
4422
  messages: UIMessage[];
package/dist/index.d.ts CHANGED
@@ -1632,6 +1632,13 @@ type UIToolInvocation<TOOL extends UITool | Tool> = {
1632
1632
  state: 'input-streaming';
1633
1633
  input: DeepPartial<asUITool<TOOL>['input']> | undefined;
1634
1634
  providerExecuted?: boolean;
1635
+ /**
1636
+ * The raw tool input text received so far.
1637
+ *
1638
+ * This is used to continue input streaming when a message is persisted
1639
+ * and later resumed.
1640
+ */
1641
+ rawInput?: string;
1635
1642
  output?: never;
1636
1643
  errorText?: never;
1637
1644
  } | {
@@ -1681,6 +1688,13 @@ type DynamicToolUIPart = {
1681
1688
  } & ({
1682
1689
  state: 'input-streaming';
1683
1690
  input: unknown | undefined;
1691
+ /**
1692
+ * The raw tool input text received so far.
1693
+ *
1694
+ * This is used to continue input streaming when a message is persisted
1695
+ * and later resumed.
1696
+ */
1697
+ rawInput?: string;
1684
1698
  output?: never;
1685
1699
  errorText?: never;
1686
1700
  } | {
@@ -1896,6 +1910,12 @@ type UIMessageStreamOnFinishCallback<UI_MESSAGE extends UIMessage> = (event: {
1896
1910
  }) => PromiseLike<void> | void;
1897
1911
 
1898
1912
  type UIMessageStreamResponseInit = ResponseInit & {
1913
+ /**
1914
+ * Optional interval in milliseconds for sending SSE keep-alive comments.
1915
+ * When set, an opening comment is sent immediately and additional comments
1916
+ * are sent after the stream has been idle for the configured interval.
1917
+ */
1918
+ keepAliveMs?: number;
1899
1919
  consumeSseStream?: (options: {
1900
1920
  stream: ReadableStream<string>;
1901
1921
  }) => PromiseLike<void> | void;
@@ -3926,7 +3946,7 @@ originalMessages, onFinish, generateId, }: {
3926
3946
  generateId?: IdGenerator;
3927
3947
  }): ReadableStream<InferUIMessageChunk<UI_MESSAGE>>;
3928
3948
 
3929
- declare function createUIMessageStreamResponse({ status, statusText, headers, stream, consumeSseStream, }: UIMessageStreamResponseInit & {
3949
+ declare function createUIMessageStreamResponse({ status, statusText, headers, stream, keepAliveMs, consumeSseStream, }: UIMessageStreamResponseInit & {
3930
3950
  stream: ReadableStream<UIMessageChunk>;
3931
3951
  }): Response;
3932
3952
 
@@ -3934,7 +3954,7 @@ declare class JsonToSseTransformStream extends TransformStream<unknown, string>
3934
3954
  constructor();
3935
3955
  }
3936
3956
 
3937
- declare function pipeUIMessageStreamToResponse({ response, status, statusText, headers, stream, consumeSseStream, }: {
3957
+ declare function pipeUIMessageStreamToResponse({ response, status, statusText, headers, stream, keepAliveMs, consumeSseStream, }: {
3938
3958
  response: ServerResponse;
3939
3959
  stream: ReadableStream<UIMessageChunk>;
3940
3960
  } & UIMessageStreamResponseInit): Promise<void>;
@@ -4392,9 +4412,11 @@ declare class DefaultChatTransport<UI_MESSAGE extends UIMessage> extends HttpCha
4392
4412
  }
4393
4413
 
4394
4414
  /**
4395
- Check if the message is an assistant message with completed tool calls.
4396
- The last step of the message must have at least one tool invocation and
4397
- all tool invocations must have a result.
4415
+ * Check if the last message is an assistant message with completed tool calls.
4416
+ * The last step of the message must have at least one tool invocation and
4417
+ * all tool invocations must have a result. Completed model text may follow
4418
+ * the tool invocation because client-side tool results update parts in place,
4419
+ * but trailing text without a completed stream state prevents resubmission.
4398
4420
  */
4399
4421
  declare function lastAssistantMessageIsCompleteWithToolCalls({ messages, }: {
4400
4422
  messages: UIMessage[];
package/dist/index.js CHANGED
@@ -816,7 +816,7 @@ function detectMediaType({
816
816
  var import_provider_utils2 = require("@ai-sdk/provider-utils");
817
817
 
818
818
  // src/version.ts
819
- var VERSION = true ? "5.0.269" : "0.0.0-test";
819
+ var VERSION = true ? "5.0.270" : "0.0.0-test";
820
820
 
821
821
  // src/util/download/download.ts
822
822
  var download = async ({
@@ -3070,6 +3070,75 @@ function pipeTextStreamToResponse({
3070
3070
  });
3071
3071
  }
3072
3072
 
3073
+ // src/ui-message-stream/create-sse-stream-with-keep-alive.ts
3074
+ var STREAM_OPEN_COMMENT = ": stream-open\n\n";
3075
+ var KEEP_ALIVE_COMMENT = ": keep-alive\n\n";
3076
+ function createSseStreamWithKeepAlive({
3077
+ stream,
3078
+ keepAliveMs
3079
+ }) {
3080
+ if (keepAliveMs == null) {
3081
+ return stream;
3082
+ }
3083
+ if (!Number.isFinite(keepAliveMs) || keepAliveMs <= 0 || keepAliveMs > 2147483647) {
3084
+ throw new Error(
3085
+ "keepAliveMs must be a positive finite timer duration no greater than 2147483647"
3086
+ );
3087
+ }
3088
+ const reader = stream.getReader();
3089
+ let keepAliveTimeout;
3090
+ let isCancelled = false;
3091
+ const clearKeepAliveTimeout = () => {
3092
+ clearTimeout(keepAliveTimeout);
3093
+ keepAliveTimeout = void 0;
3094
+ };
3095
+ const scheduleKeepAlive = (controller) => {
3096
+ clearKeepAliveTimeout();
3097
+ keepAliveTimeout = setTimeout(() => {
3098
+ if (isCancelled) {
3099
+ return;
3100
+ }
3101
+ if (controller.desiredSize != null && controller.desiredSize > 0) {
3102
+ controller.enqueue(KEEP_ALIVE_COMMENT);
3103
+ }
3104
+ scheduleKeepAlive(controller);
3105
+ }, keepAliveMs);
3106
+ };
3107
+ return new ReadableStream({
3108
+ start(controller) {
3109
+ controller.enqueue(STREAM_OPEN_COMMENT);
3110
+ scheduleKeepAlive(controller);
3111
+ },
3112
+ pull(controller) {
3113
+ return reader.read().then(
3114
+ (result) => {
3115
+ clearKeepAliveTimeout();
3116
+ if (isCancelled) {
3117
+ return;
3118
+ }
3119
+ if (result.done) {
3120
+ controller.close();
3121
+ } else {
3122
+ controller.enqueue(result.value);
3123
+ scheduleKeepAlive(controller);
3124
+ }
3125
+ },
3126
+ (error) => {
3127
+ clearKeepAliveTimeout();
3128
+ if (!isCancelled) {
3129
+ throw error;
3130
+ }
3131
+ }
3132
+ );
3133
+ },
3134
+ async cancel(reason) {
3135
+ isCancelled = true;
3136
+ clearKeepAliveTimeout();
3137
+ await reader.cancel(reason);
3138
+ }
3139
+ });
3140
+ }
3141
+
3073
3142
  // src/ui-message-stream/json-to-sse-transform-stream.ts
3074
3143
  var JsonToSseTransformStream = class extends TransformStream {
3075
3144
  constructor() {
@@ -3102,9 +3171,13 @@ function createUIMessageStreamResponse({
3102
3171
  statusText,
3103
3172
  headers,
3104
3173
  stream,
3174
+ keepAliveMs,
3105
3175
  consumeSseStream
3106
3176
  }) {
3107
- let sseStream = stream.pipeThrough(new JsonToSseTransformStream());
3177
+ let sseStream = createSseStreamWithKeepAlive({
3178
+ stream: stream.pipeThrough(new JsonToSseTransformStream()),
3179
+ keepAliveMs
3180
+ });
3108
3181
  if (consumeSseStream) {
3109
3182
  const [stream1, stream2] = sseStream.tee();
3110
3183
  sseStream = stream1;
@@ -3700,16 +3773,41 @@ function createStreamingUIMessageState({
3700
3773
  lastMessage,
3701
3774
  messageId
3702
3775
  }) {
3776
+ var _a16;
3777
+ const message = (lastMessage == null ? void 0 : lastMessage.role) === "assistant" ? lastMessage : {
3778
+ id: messageId,
3779
+ metadata: void 0,
3780
+ role: "assistant",
3781
+ parts: []
3782
+ };
3783
+ const partialToolCalls = createIdMap();
3784
+ const lastStepStartIndex = message.parts.findLastIndex(
3785
+ (part) => part.type === "step-start"
3786
+ );
3787
+ let staticToolIndex = 0;
3788
+ for (const part of message.parts.slice(lastStepStartIndex + 1)) {
3789
+ if (!isToolOrDynamicToolUIPart(part)) {
3790
+ continue;
3791
+ }
3792
+ const index = staticToolIndex;
3793
+ if (isToolUIPart(part)) {
3794
+ staticToolIndex++;
3795
+ }
3796
+ if (part.state !== "input-streaming") {
3797
+ continue;
3798
+ }
3799
+ partialToolCalls[part.toolCallId] = {
3800
+ text: (_a16 = part.rawInput) != null ? _a16 : "",
3801
+ index,
3802
+ toolName: isDynamicToolUIPart(part) ? part.toolName : getToolName(part),
3803
+ dynamic: isDynamicToolUIPart(part)
3804
+ };
3805
+ }
3703
3806
  return {
3704
- message: (lastMessage == null ? void 0 : lastMessage.role) === "assistant" ? lastMessage : {
3705
- id: messageId,
3706
- metadata: void 0,
3707
- role: "assistant",
3708
- parts: []
3709
- },
3807
+ message,
3710
3808
  activeTextParts: createIdMap(),
3711
3809
  activeReasoningParts: createIdMap(),
3712
- partialToolCalls: createIdMap()
3810
+ partialToolCalls
3713
3811
  };
3714
3812
  }
3715
3813
  function processUIMessageStream({
@@ -3817,7 +3915,7 @@ function processUIMessageStream({
3817
3915
  }
3818
3916
  }
3819
3917
  function updateDynamicToolPart(options, existingPart) {
3820
- var _a17, _b2;
3918
+ var _a17;
3821
3919
  const part = existingPart != null ? existingPart : getCurrentStepParts().find(
3822
3920
  (part2) => part2.type === "dynamic-tool" && part2.toolCallId === options.toolCallId
3823
3921
  );
@@ -3829,9 +3927,9 @@ function processUIMessageStream({
3829
3927
  anyPart.input = anyOptions.input;
3830
3928
  anyPart.output = anyOptions.output;
3831
3929
  anyPart.errorText = anyOptions.errorText;
3832
- anyPart.rawInput = (_a17 = anyOptions.rawInput) != null ? _a17 : anyPart.rawInput;
3930
+ anyPart.rawInput = anyOptions.rawInput;
3833
3931
  anyPart.preliminary = anyOptions.preliminary;
3834
- anyPart.providerExecuted = (_b2 = anyOptions.providerExecuted) != null ? _b2 : part.providerExecuted;
3932
+ anyPart.providerExecuted = (_a17 = anyOptions.providerExecuted) != null ? _a17 : part.providerExecuted;
3835
3933
  if (anyOptions.providerMetadata != null && part.state === "input-available") {
3836
3934
  part.callProviderMetadata = anyOptions.providerMetadata;
3837
3935
  }
@@ -3989,14 +4087,16 @@ function processUIMessageStream({
3989
4087
  toolCallId: chunk.toolCallId,
3990
4088
  toolName: partialToolCall.toolName,
3991
4089
  state: "input-streaming",
3992
- input: partialArgs
4090
+ input: partialArgs,
4091
+ rawInput: partialToolCall.text
3993
4092
  });
3994
4093
  } else {
3995
4094
  updateToolPart({
3996
4095
  toolCallId: chunk.toolCallId,
3997
4096
  toolName: partialToolCall.toolName,
3998
4097
  state: "input-streaming",
3999
- input: partialArgs
4098
+ input: partialArgs,
4099
+ rawInput: partialToolCall.text
4000
4100
  });
4001
4101
  }
4002
4102
  write();
@@ -4310,9 +4410,13 @@ function pipeUIMessageStreamToResponse({
4310
4410
  statusText,
4311
4411
  headers,
4312
4412
  stream,
4413
+ keepAliveMs,
4313
4414
  consumeSseStream
4314
4415
  }) {
4315
- let sseStream = stream.pipeThrough(new JsonToSseTransformStream());
4416
+ let sseStream = createSseStreamWithKeepAlive({
4417
+ stream: stream.pipeThrough(new JsonToSseTransformStream()),
4418
+ keepAliveMs
4419
+ });
4316
4420
  if (consumeSseStream) {
4317
4421
  const [stream1, stream2] = sseStream.tee();
4318
4422
  sseStream = stream1;
@@ -6636,6 +6740,21 @@ var DefaultEmbedResult = class {
6636
6740
  }
6637
6741
  };
6638
6742
 
6743
+ // src/util/get-own.ts
6744
+ function getOwn(obj, key) {
6745
+ return obj != null && Object.hasOwn(obj, key) ? obj[key] : void 0;
6746
+ }
6747
+
6748
+ // src/util/set-own.ts
6749
+ function setOwn(object2, key, value) {
6750
+ Object.defineProperty(object2, key, {
6751
+ value,
6752
+ enumerable: true,
6753
+ configurable: true,
6754
+ writable: true
6755
+ });
6756
+ }
6757
+
6639
6758
  // src/embed/embed-many.ts
6640
6759
  var import_provider_utils18 = require("@ai-sdk/provider-utils");
6641
6760
 
@@ -6861,10 +6980,10 @@ async function embedMany({
6861
6980
  for (const [providerName, metadata] of Object.entries(
6862
6981
  result.providerMetadata
6863
6982
  )) {
6864
- providerMetadata[providerName] = {
6865
- ...providerMetadata[providerName],
6983
+ setOwn(providerMetadata, providerName, {
6984
+ ...getOwn(providerMetadata, providerName),
6866
6985
  ...metadata
6867
- };
6986
+ });
6868
6987
  }
6869
6988
  }
6870
6989
  }
@@ -7042,10 +7161,13 @@ async function generateImage({
7042
7161
  delete providerMetadata[providerName].images;
7043
7162
  }
7044
7163
  } else {
7045
- (_b = providerMetadata[providerName]) != null ? _b : providerMetadata[providerName] = { images: [] };
7046
- providerMetadata[providerName].images.push(
7164
+ const currentEntry = (_b = getOwn(providerMetadata, providerName)) != null ? _b : {
7165
+ images: []
7166
+ };
7167
+ currentEntry.images.push(
7047
7168
  ...result.providerMetadata[providerName].images
7048
7169
  );
7170
+ setOwn(providerMetadata, providerName, currentEntry);
7049
7171
  }
7050
7172
  }
7051
7173
  }
@@ -9298,7 +9420,7 @@ var DefaultProviderRegistry = class {
9298
9420
  separator,
9299
9421
  languageModelMiddleware
9300
9422
  }) {
9301
- this.providers = {};
9423
+ this.providers = /* @__PURE__ */ Object.create(null);
9302
9424
  this.separator = separator;
9303
9425
  this.languageModelMiddleware = languageModelMiddleware;
9304
9426
  }
@@ -9653,6 +9775,10 @@ var import_provider_utils31 = require("@ai-sdk/provider-utils");
9653
9775
 
9654
9776
  // src/ui/http-chat-transport.ts
9655
9777
  var import_provider_utils30 = require("@ai-sdk/provider-utils");
9778
+ function appendPathToUrl(url, path) {
9779
+ const queryOrFragmentStart = url.search(/[?#]/);
9780
+ return queryOrFragmentStart === -1 ? `${url}${path}` : `${url.slice(0, queryOrFragmentStart)}${path}${url.slice(queryOrFragmentStart)}`;
9781
+ }
9656
9782
  var HttpChatTransport = class {
9657
9783
  constructor({
9658
9784
  api = "/api/chat",
@@ -9727,7 +9853,7 @@ var HttpChatTransport = class {
9727
9853
  return this.processResponseStream(response.body);
9728
9854
  }
9729
9855
  async reconnectToStream(options) {
9730
- var _a16, _b, _c, _d, _e;
9856
+ var _a16, _b, _c, _d;
9731
9857
  const resolvedBody = await (0, import_provider_utils30.resolve)(this.body);
9732
9858
  const resolvedHeaders = await (0, import_provider_utils30.resolve)(this.headers);
9733
9859
  const resolvedCredentials = await (0, import_provider_utils30.resolve)(this.credentials);
@@ -9743,10 +9869,23 @@ var HttpChatTransport = class {
9743
9869
  credentials: resolvedCredentials,
9744
9870
  requestMetadata: options.metadata
9745
9871
  }));
9746
- const api = (_b = preparedRequest == null ? void 0 : preparedRequest.api) != null ? _b : `${this.api}/${options.chatId}/stream`;
9872
+ let api = preparedRequest == null ? void 0 : preparedRequest.api;
9873
+ if (api == null) {
9874
+ if (options.chatId === "." || options.chatId === "..") {
9875
+ throw new InvalidArgumentError({
9876
+ parameter: "chatId",
9877
+ value: options.chatId,
9878
+ message: 'Chat IDs must not be "." or ".." when using the default reconnect URL.'
9879
+ });
9880
+ }
9881
+ api = appendPathToUrl(
9882
+ this.api,
9883
+ `/${encodeURIComponent(options.chatId)}/stream`
9884
+ );
9885
+ }
9747
9886
  const headers = (preparedRequest == null ? void 0 : preparedRequest.headers) !== void 0 ? (0, import_provider_utils30.normalizeHeaders)(preparedRequest.headers) : baseHeaders;
9748
- const credentials = (_c = preparedRequest == null ? void 0 : preparedRequest.credentials) != null ? _c : resolvedCredentials;
9749
- const fetch2 = (_d = this.fetch) != null ? _d : globalThis.fetch;
9887
+ const credentials = (_b = preparedRequest == null ? void 0 : preparedRequest.credentials) != null ? _b : resolvedCredentials;
9888
+ const fetch2 = (_c = this.fetch) != null ? _c : globalThis.fetch;
9750
9889
  const response = await fetch2(api, {
9751
9890
  method: "GET",
9752
9891
  headers,
@@ -9758,7 +9897,7 @@ var HttpChatTransport = class {
9758
9897
  }
9759
9898
  if (!response.ok) {
9760
9899
  throw new Error(
9761
- (_e = await response.text()) != null ? _e : "Failed to fetch the chat response."
9900
+ (_d = await response.text()) != null ? _d : "Failed to fetch the chat response."
9762
9901
  );
9763
9902
  }
9764
9903
  if (!response.body) {
@@ -10020,6 +10159,9 @@ var AbstractChat = class {
10020
10159
  };
10021
10160
  this.setStatus({ status: "submitted", error: void 0 });
10022
10161
  const lastMessage = this.lastMessage;
10162
+ const resumableResponseMessage = trigger === "resume-stream" && (lastMessage == null ? void 0 : lastMessage.role) === "assistant" && lastMessage.parts.some(
10163
+ (part) => isToolOrDynamicToolUIPart(part) && part.state === "input-streaming"
10164
+ ) ? this.state.snapshot(lastMessage) : void 0;
10023
10165
  let isAbort = false;
10024
10166
  let isDisconnect = false;
10025
10167
  let isError = false;
@@ -10027,7 +10169,7 @@ var AbstractChat = class {
10027
10169
  try {
10028
10170
  const response = {
10029
10171
  state: trigger === "resume-stream" && this.resumableStreamState != null ? this.resumableStreamState : createStreamingUIMessageState({
10030
- lastMessage: trigger === "resume-stream" ? void 0 : this.state.snapshot(lastMessage),
10172
+ lastMessage: trigger === "resume-stream" ? resumableResponseMessage : this.state.snapshot(lastMessage),
10031
10173
  messageId: this.generateId()
10032
10174
  }),
10033
10175
  abortController
@@ -10208,8 +10350,13 @@ function lastAssistantMessageIsCompleteWithToolCalls({
10208
10350
  const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => {
10209
10351
  return part.type === "step-start" ? index : lastIndex;
10210
10352
  }, -1);
10211
- const lastStepToolInvocations = message.parts.slice(lastStepStartIndex + 1).filter(isToolOrDynamicToolUIPart).filter((part) => !part.providerExecuted);
10212
- return lastStepToolInvocations.length > 0 && lastStepToolInvocations.every(
10353
+ const lastStepParts = message.parts.slice(lastStepStartIndex + 1);
10354
+ const lastStepToolInvocations = lastStepParts.filter(isToolOrDynamicToolUIPart).filter((part) => !part.providerExecuted);
10355
+ const lastToolInvocationIndex = lastStepParts.reduce(
10356
+ (lastIndex, part, index) => isToolOrDynamicToolUIPart(part) && !part.providerExecuted ? index : lastIndex,
10357
+ -1
10358
+ );
10359
+ return lastStepToolInvocations.length > 0 && !lastStepParts.slice(lastToolInvocationIndex + 1).some((part) => part.type === "text" && part.state !== "done") && lastStepToolInvocations.every(
10213
10360
  (part) => part.state === "output-available" || part.state === "output-error"
10214
10361
  );
10215
10362
  }
@@ -10338,6 +10485,7 @@ var uiMessagesSchema = (0, import_provider_utils33.lazyValidator)(
10338
10485
  toolCallId: import_v48.z.string(),
10339
10486
  state: import_v48.z.literal("input-streaming"),
10340
10487
  input: import_v48.z.unknown().optional(),
10488
+ rawInput: import_v48.z.string().optional(),
10341
10489
  providerExecuted: import_v48.z.boolean().optional(),
10342
10490
  output: import_v48.z.never().optional(),
10343
10491
  errorText: import_v48.z.never().optional()
@@ -10383,6 +10531,7 @@ var uiMessagesSchema = (0, import_provider_utils33.lazyValidator)(
10383
10531
  state: import_v48.z.literal("input-streaming"),
10384
10532
  providerExecuted: import_v48.z.boolean().optional(),
10385
10533
  input: import_v48.z.unknown().optional(),
10534
+ rawInput: import_v48.z.string().optional(),
10386
10535
  output: import_v48.z.never().optional(),
10387
10536
  errorText: import_v48.z.never().optional(),
10388
10537
  approval: import_v48.z.never().optional()