ai 5.0.273 → 5.0.274

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/dist/index.mjs CHANGED
@@ -727,7 +727,7 @@ import {
727
727
  } from "@ai-sdk/provider-utils";
728
728
 
729
729
  // src/version.ts
730
- var VERSION = true ? "5.0.273" : "0.0.0-test";
730
+ var VERSION = true ? "5.0.274" : "0.0.0-test";
731
731
 
732
732
  // src/util/download/download.ts
733
733
  var download = async ({
@@ -3748,7 +3748,8 @@ function processUIMessageStream({
3748
3748
  runUpdateMessageJob,
3749
3749
  onError,
3750
3750
  onToolCall,
3751
- onData
3751
+ onData,
3752
+ resetStateOnMessageIdChange = false
3752
3753
  }) {
3753
3754
  return stream.pipeThrough(
3754
3755
  new TransformStream({
@@ -4165,6 +4166,16 @@ function processUIMessageStream({
4165
4166
  break;
4166
4167
  }
4167
4168
  case "start": {
4169
+ if (resetStateOnMessageIdChange && chunk.messageId != null && chunk.messageId !== state.message.id) {
4170
+ Object.assign(
4171
+ state,
4172
+ createStreamingUIMessageState({
4173
+ lastMessage: void 0,
4174
+ messageId: chunk.messageId
4175
+ }),
4176
+ { finishReason: void 0 }
4177
+ );
4178
+ }
4168
4179
  if (chunk.messageId != null) {
4169
4180
  state.message.id = chunk.messageId;
4170
4181
  }
@@ -7990,17 +8001,24 @@ var SerialJobExecutor = class {
7990
8001
  constructor() {
7991
8002
  this.queue = [];
7992
8003
  this.isProcessing = false;
8004
+ this.idleWaiters = [];
7993
8005
  }
7994
8006
  async processQueue() {
7995
8007
  if (this.isProcessing) {
7996
8008
  return;
7997
8009
  }
7998
8010
  this.isProcessing = true;
7999
- while (this.queue.length > 0) {
8000
- await this.queue[0]();
8001
- this.queue.shift();
8011
+ try {
8012
+ while (this.queue.length > 0) {
8013
+ await this.queue[0]();
8014
+ this.queue.shift();
8015
+ }
8016
+ } finally {
8017
+ this.isProcessing = false;
8018
+ for (const resolve2 of this.idleWaiters.splice(0)) {
8019
+ resolve2();
8020
+ }
8002
8021
  }
8003
- this.isProcessing = false;
8004
8022
  }
8005
8023
  async run(job) {
8006
8024
  return new Promise((resolve2, reject) => {
@@ -8015,6 +8033,14 @@ var SerialJobExecutor = class {
8015
8033
  void this.processQueue();
8016
8034
  });
8017
8035
  }
8036
+ async waitForIdle() {
8037
+ if (!this.isProcessing && this.queue.length === 0) {
8038
+ return;
8039
+ }
8040
+ await new Promise((resolve2) => {
8041
+ this.idleWaiters.push(resolve2);
8042
+ });
8043
+ }
8018
8044
  };
8019
8045
 
8020
8046
  // src/util/simulate-readable-stream.ts
@@ -9955,6 +9981,8 @@ var AbstractChat = class {
9955
9981
  this.activeResumeRequest = void 0;
9956
9982
  this.resumableStreamState = void 0;
9957
9983
  this.jobExecutor = new SerialJobExecutor();
9984
+ this.activeStopCount = 0;
9985
+ this.stopGeneration = 0;
9958
9986
  /**
9959
9987
  * Appends or replaces a user message to the chat list. This triggers the API call to fetch
9960
9988
  * the assistant's response.
@@ -10045,6 +10073,27 @@ var AbstractChat = class {
10045
10073
  this.resumeStream = async (options = {}) => {
10046
10074
  await this.makeRequest({ trigger: "resume-stream", ...options });
10047
10075
  };
10076
+ /**
10077
+ * Resume the stream if the latest response ended with a resumable network
10078
+ * disconnect. If a response is still active, wait for it to settle first so
10079
+ * disconnects reported shortly after the caller's trigger are handled.
10080
+ *
10081
+ * @internal
10082
+ */
10083
+ this["~resumeStreamIfDisconnected"] = async ({
10084
+ shouldResume = () => true
10085
+ } = {}) => {
10086
+ const activeResponse = this.activeResponse;
10087
+ if (this.resumableStreamState == null && activeResponse != null) {
10088
+ await activeResponse.completionPromise;
10089
+ if (this.resumableStreamState !== activeResponse.state) {
10090
+ return;
10091
+ }
10092
+ }
10093
+ if (this.resumableStreamState != null && shouldResume()) {
10094
+ await this.resumeStream();
10095
+ }
10096
+ };
10048
10097
  /**
10049
10098
  * Clear the error state and set the status to ready if the chat is in an error state.
10050
10099
  */
@@ -10061,15 +10110,21 @@ var AbstractChat = class {
10061
10110
  output,
10062
10111
  errorText
10063
10112
  }) => this.jobExecutor.run(async () => {
10064
- var _a16, _b;
10065
10113
  const messages = this.state.messages;
10066
- const lastMessage = messages[messages.length - 1];
10067
- this.state.replaceMessage(messages.length - 1, {
10068
- ...lastMessage,
10069
- parts: lastMessage.parts.map(
10070
- (part) => isToolOrDynamicToolUIPart(part) && part.toolCallId === toolCallId ? { ...part, state, output, errorText } : part
10114
+ const messageIndex = messages.findIndex(
10115
+ (message) => message.parts.some(
10116
+ (part) => isToolOrDynamicToolUIPart(part) && part.toolCallId === toolCallId
10071
10117
  )
10072
- });
10118
+ );
10119
+ if (messageIndex !== -1) {
10120
+ const message = messages[messageIndex];
10121
+ this.state.replaceMessage(messageIndex, {
10122
+ ...message,
10123
+ parts: message.parts.map(
10124
+ (part) => isToolOrDynamicToolUIPart(part) && part.toolCallId === toolCallId ? { ...part, state, output, errorText } : part
10125
+ )
10126
+ });
10127
+ }
10073
10128
  if (this.activeResponse) {
10074
10129
  this.activeResponse.state.message.parts = this.activeResponse.state.message.parts.map(
10075
10130
  (part) => isToolOrDynamicToolUIPart(part) && part.toolCallId === toolCallId ? {
@@ -10080,22 +10135,41 @@ var AbstractChat = class {
10080
10135
  } : part
10081
10136
  );
10082
10137
  }
10083
- if (this.status !== "streaming" && this.status !== "submitted" && ((_a16 = this.sendAutomaticallyWhen) == null ? void 0 : _a16.call(this, { messages: this.state.messages }))) {
10084
- this.makeRequest({
10085
- trigger: "submit-message",
10086
- messageId: (_b = this.lastMessage) == null ? void 0 : _b.id
10087
- });
10138
+ if (messageIndex !== -1 && this.status !== "streaming" && this.status !== "submitted" && this.sendAutomaticallyWhen) {
10139
+ const shouldSend = await this.shouldSendAutomatically();
10140
+ if (shouldSend) {
10141
+ void this.runAutomaticRequest(
10142
+ () => this.makeRequest({
10143
+ trigger: "submit-message",
10144
+ messageId: messages[messageIndex].id
10145
+ }),
10146
+ shouldSend
10147
+ );
10148
+ }
10088
10149
  }
10089
10150
  });
10090
10151
  /** @deprecated Use addToolOutput */
10091
10152
  this.addToolResult = this.addToolOutput;
10092
10153
  /**
10093
- * Abort the current request immediately, keep the generated tokens if any.
10154
+ * Abort the current request, keep the generated tokens if any, and wait for
10155
+ * the request pipeline to finish.
10094
10156
  */
10095
10157
  this.stop = async () => {
10096
- var _a16, _b;
10097
- (_a16 = this.activeResumeRequest) == null ? void 0 : _a16.abortController.abort();
10098
- (_b = this.activeResponse) == null ? void 0 : _b.abortController.abort();
10158
+ this.activeStopCount++;
10159
+ this.stopGeneration++;
10160
+ try {
10161
+ const activeResumeRequest = this.activeResumeRequest;
10162
+ const activeResponse = this.activeResponse;
10163
+ activeResumeRequest == null ? void 0 : activeResumeRequest.abortController.abort();
10164
+ activeResponse == null ? void 0 : activeResponse.abortController.abort();
10165
+ await Promise.all([
10166
+ activeResumeRequest == null ? void 0 : activeResumeRequest.completionPromise,
10167
+ activeResponse == null ? void 0 : activeResponse.completionPromise
10168
+ ]);
10169
+ await this.jobExecutor.waitForIdle();
10170
+ } finally {
10171
+ this.activeStopCount--;
10172
+ }
10099
10173
  };
10100
10174
  this.id = id;
10101
10175
  this.transport = transport;
@@ -10141,19 +10215,53 @@ var AbstractChat = class {
10141
10215
  set messages(messages) {
10142
10216
  this.state.messages = messages;
10143
10217
  }
10144
- async makeRequest({
10218
+ async shouldSendAutomatically() {
10219
+ if (!this.sendAutomaticallyWhen)
10220
+ return false;
10221
+ const result = this.sendAutomaticallyWhen({
10222
+ messages: this.state.messages
10223
+ });
10224
+ if (result && typeof result === "object" && "then" in result) {
10225
+ return await result;
10226
+ }
10227
+ return result;
10228
+ }
10229
+ async runAutomaticRequest(request, shouldSend) {
10230
+ const stopGeneration = this.stopGeneration;
10231
+ const startedWhileStopping = this.activeStopCount > 0;
10232
+ if (!(shouldSend != null ? shouldSend : await this.shouldSendAutomatically())) {
10233
+ return;
10234
+ }
10235
+ if (startedWhileStopping || stopGeneration !== this.stopGeneration || this.activeStopCount > 0) {
10236
+ return;
10237
+ }
10238
+ await request();
10239
+ }
10240
+ async makeRequest(options) {
10241
+ const completion = createResolvablePromise();
10242
+ try {
10243
+ await this.makeRequestImpl({
10244
+ ...options,
10245
+ completionPromise: completion.promise
10246
+ });
10247
+ } finally {
10248
+ completion.resolve();
10249
+ }
10250
+ }
10251
+ async makeRequestImpl({
10145
10252
  trigger,
10146
10253
  metadata,
10147
10254
  headers,
10148
10255
  body,
10149
- messageId
10256
+ messageId,
10257
+ completionPromise
10150
10258
  }) {
10151
- var _a16, _b, _c, _d;
10259
+ var _a16, _b;
10152
10260
  if (trigger !== "resume-stream") {
10153
10261
  this.resumableStreamState = void 0;
10154
10262
  }
10155
10263
  const abortController = new AbortController();
10156
- const activeResumeRequest = trigger === "resume-stream" ? { abortController } : void 0;
10264
+ const activeResumeRequest = trigger === "resume-stream" ? { abortController, completionPromise } : void 0;
10157
10265
  if (activeResumeRequest) {
10158
10266
  (_a16 = this.activeResumeRequest) == null ? void 0 : _a16.abortController.abort();
10159
10267
  this.activeResumeRequest = activeResumeRequest;
@@ -10166,9 +10274,13 @@ var AbstractChat = class {
10166
10274
  };
10167
10275
  this.setStatus({ status: "submitted", error: void 0 });
10168
10276
  const lastMessage = this.lastMessage;
10277
+ const responseMessageIndex = trigger === "submit-message" && messageId != null ? this.state.messages.findIndex((message) => message.id === messageId) : this.state.messages.length - 1;
10278
+ const responseMessage = responseMessageIndex === -1 ? lastMessage : this.state.messages[responseMessageIndex];
10279
+ const originalResponseMessageId = responseMessage == null ? void 0 : responseMessage.id;
10169
10280
  const resumableResponseMessage = trigger === "resume-stream" && (lastMessage == null ? void 0 : lastMessage.role) === "assistant" && lastMessage.parts.some(
10170
10281
  (part) => isToolOrDynamicToolUIPart(part) && part.state === "input-streaming"
10171
10282
  ) ? this.state.snapshot(lastMessage) : void 0;
10283
+ const usesEarlierAssistantMessage = responseMessageIndex !== -1 && responseMessageIndex < this.state.messages.length - 1 && (responseMessage == null ? void 0 : responseMessage.role) === "assistant";
10172
10284
  let isAbort = false;
10173
10285
  let isDisconnect = false;
10174
10286
  let isError = false;
@@ -10176,10 +10288,11 @@ var AbstractChat = class {
10176
10288
  try {
10177
10289
  const response = {
10178
10290
  state: trigger === "resume-stream" && this.resumableStreamState != null ? this.resumableStreamState : createStreamingUIMessageState({
10179
- lastMessage: trigger === "resume-stream" ? resumableResponseMessage : this.state.snapshot(lastMessage),
10291
+ lastMessage: trigger === "resume-stream" ? resumableResponseMessage : this.state.snapshot(responseMessage),
10180
10292
  messageId: this.generateId()
10181
10293
  }),
10182
- abortController
10294
+ abortController,
10295
+ completionPromise
10183
10296
  };
10184
10297
  activeResponse = response;
10185
10298
  response.abortController.signal.addEventListener("abort", () => {
@@ -10233,19 +10346,32 @@ var AbstractChat = class {
10233
10346
  return job({
10234
10347
  state: response.state,
10235
10348
  write: ({ updateStatus = true } = {}) => {
10236
- var _a17;
10237
10349
  if (response.abortController.signal.aborted) {
10238
10350
  return;
10239
10351
  }
10240
10352
  if (updateStatus) {
10241
10353
  this.setStatus({ status: "streaming" });
10242
10354
  }
10243
- const replaceLastMessage = response.state.message.id === ((_a17 = this.lastMessage) == null ? void 0 : _a17.id);
10244
- if (replaceLastMessage) {
10355
+ const existingMessageIndex = this.state.messages.findLastIndex(
10356
+ (message) => message.id === response.state.message.id
10357
+ );
10358
+ if (existingMessageIndex !== -1) {
10245
10359
  this.state.replaceMessage(
10246
- this.state.messages.length - 1,
10360
+ existingMessageIndex,
10247
10361
  response.state.message
10248
10362
  );
10363
+ } else if (usesEarlierAssistantMessage) {
10364
+ const originalMessageIndex = this.state.messages.findLastIndex(
10365
+ (message) => message.id === originalResponseMessageId
10366
+ );
10367
+ if (originalMessageIndex !== -1) {
10368
+ this.state.replaceMessage(
10369
+ originalMessageIndex,
10370
+ response.state.message
10371
+ );
10372
+ } else {
10373
+ this.state.pushMessage(response.state.message);
10374
+ }
10249
10375
  } else {
10250
10376
  this.state.pushMessage(response.state.message);
10251
10377
  }
@@ -10331,14 +10457,19 @@ var AbstractChat = class {
10331
10457
  clearActiveResumeRequest();
10332
10458
  }
10333
10459
  }
10334
- if (((_c = this.sendAutomaticallyWhen) == null ? void 0 : _c.call(this, { messages: this.state.messages })) && !isError) {
10335
- await this.makeRequest({
10336
- trigger: "submit-message",
10337
- messageId: (_d = this.lastMessage) == null ? void 0 : _d.id,
10338
- metadata,
10339
- headers,
10340
- body
10341
- });
10460
+ if (!isAbort && !isError) {
10461
+ await this.runAutomaticRequest(
10462
+ () => {
10463
+ var _a17;
10464
+ return this.makeRequest({
10465
+ trigger: "submit-message",
10466
+ messageId: (_a17 = this.lastMessage) == null ? void 0 : _a17.id,
10467
+ metadata,
10468
+ headers,
10469
+ body
10470
+ });
10471
+ }
10472
+ );
10342
10473
  }
10343
10474
  }
10344
10475
  };
@@ -10971,6 +11102,7 @@ function readUIMessageStream({
10971
11102
  consumeStream({
10972
11103
  stream: processUIMessageStream({
10973
11104
  stream,
11105
+ resetStateOnMessageIdChange: true,
10974
11106
  runUpdateMessageJob(job) {
10975
11107
  return job({
10976
11108
  state,