ai 7.0.136 → 7.0.138

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 +29 -0
  2. package/dist/index.d.ts +31 -6
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +116 -77
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +73 -4
  7. package/dist/internal/index.d.ts.map +1 -1
  8. package/dist/internal/index.js +44 -17
  9. package/dist/internal/index.js.map +1 -1
  10. package/docs/03-ai-sdk-core/05-generating-text.mdx +70 -2
  11. package/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +14 -1
  12. package/docs/04-ai-sdk-ui/03-chatbot-resume-streams.mdx +23 -1
  13. package/docs/04-ai-sdk-ui/03-chatbot-tool-usage.mdx +6 -0
  14. package/docs/04-ai-sdk-ui/21-error-handling.mdx +34 -0
  15. package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +4 -2
  16. package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +11 -1
  17. package/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx +8 -1
  18. package/docs/07-reference/04-ai-sdk-workflow/02-workflow-chat-transport.mdx +2 -2
  19. package/package.json +12 -12
  20. package/src/decide/validate-decision.ts +2 -1
  21. package/src/generate-text/content-part.ts +7 -1
  22. package/src/generate-text/is-output-chunk.ts +59 -0
  23. package/src/generate-text/stream-text-result.ts +2 -0
  24. package/src/generate-text/stream-text.ts +7 -57
  25. package/src/global.ts +23 -4
  26. package/src/middleware/simulate-streaming-middleware.ts +8 -2
  27. package/src/prompt/convert-to-language-model-prompt.ts +0 -42
  28. package/src/types/citation.ts +31 -0
  29. package/src/types/index.ts +1 -0
  30. package/src/ui/chat.ts +63 -13
  31. package/src/ui/default-chat-transport.ts +14 -1
  32. package/src/ui/process-ui-message-stream.ts +23 -11
  33. package/src/ui/ui-messages.ts +4 -0
  34. package/src/ui/validate-ui-messages.ts +2 -0
  35. package/src/ui-message-stream/read-ui-message-stream.ts +1 -0
  36. package/src/ui-message-stream/to-ui-message-chunk.ts +1 -0
  37. package/src/ui-message-stream/ui-message-chunks.ts +3 -0
package/dist/index.js CHANGED
@@ -1174,7 +1174,7 @@ function cloneValue(value) {
1174
1174
  }
1175
1175
  //#endregion
1176
1176
  //#region src/version.ts
1177
- const VERSION = "7.0.136";
1177
+ const VERSION = "7.0.138";
1178
1178
  //#endregion
1179
1179
  //#region src/util/download/download.ts
1180
1180
  /**
@@ -1396,17 +1396,6 @@ function convertToLanguageModelV4FilePart(content) {
1396
1396
  //#region src/prompt/convert-to-language-model-prompt.ts
1397
1397
  async function convertToLanguageModelPrompt({ prompt, supportedUrls, download, abortSignal, provider }) {
1398
1398
  const downloadedAssets = await downloadAssets(prompt.messages, download ?? createDefaultDownloadFunction(void 0, abortSignal), supportedUrls);
1399
- const approvalIdToToolCallId = /* @__PURE__ */ new Map();
1400
- for (const message of prompt.messages) if (message.role === "assistant" && Array.isArray(message.content)) {
1401
- for (const part of message.content) if (part.type === "tool-approval-request" && "approvalId" in part && "toolCallId" in part) approvalIdToToolCallId.set(part.approvalId, part.toolCallId);
1402
- }
1403
- const approvedToolCallIds = /* @__PURE__ */ new Set();
1404
- for (const message of prompt.messages) if (message.role === "tool") {
1405
- for (const part of message.content) if (part.type === "tool-approval-response") {
1406
- const toolCallId = approvalIdToToolCallId.get(part.approvalId);
1407
- if (toolCallId) approvedToolCallIds.add(toolCallId);
1408
- }
1409
- }
1410
1399
  const messages = [...prompt.instructions != null ? typeof prompt.instructions === "string" ? [{
1411
1400
  role: "system",
1412
1401
  content: prompt.instructions
@@ -1442,11 +1431,8 @@ async function convertToLanguageModelPrompt({ prompt, supportedUrls, download, a
1442
1431
  for (const content of message.content) if (content.type === "tool-result") toolCallIds.delete(content.toolCallId);
1443
1432
  break;
1444
1433
  case "user":
1445
- case "system":
1446
- for (const id of approvedToolCallIds) toolCallIds.delete(id);
1447
- if (toolCallIds.size > 0) throw new MissingToolResultsError({ toolCallIds: Array.from(toolCallIds) });
1434
+ case "system": if (toolCallIds.size > 0) throw new MissingToolResultsError({ toolCallIds: Array.from(toolCallIds) });
1448
1435
  }
1449
- for (const id of approvedToolCallIds) toolCallIds.delete(id);
1450
1436
  if (toolCallIds.size > 0) throw new MissingToolResultsError({ toolCallIds: Array.from(toolCallIds) });
1451
1437
  return combinedMessages.filter((message) => message.role !== "tool" || message.content.length > 0);
1452
1438
  }
@@ -6276,6 +6262,29 @@ function getResponseUIMessageId({ originalMessages, responseMessageId }) {
6276
6262
  return lastMessage?.role === "assistant" ? lastMessage.id : typeof responseMessageId === "function" ? responseMessageId() : responseMessageId;
6277
6263
  }
6278
6264
  //#endregion
6265
+ //#region src/types/citation.ts
6266
+ const citationSchema = z.object({
6267
+ source: z.discriminatedUnion("sourceType", [z.object({
6268
+ type: z.literal("source"),
6269
+ sourceType: z.literal("url"),
6270
+ id: z.string(),
6271
+ url: z.string(),
6272
+ title: z.string().optional(),
6273
+ providerMetadata: providerMetadataSchema.optional()
6274
+ }), z.object({
6275
+ type: z.literal("source"),
6276
+ sourceType: z.literal("document"),
6277
+ id: z.string(),
6278
+ mediaType: z.string(),
6279
+ title: z.string(),
6280
+ filename: z.string().optional(),
6281
+ providerMetadata: providerMetadataSchema.optional()
6282
+ })]),
6283
+ startIndex: z.number().int().nonnegative().optional(),
6284
+ endIndex: z.number().int().nonnegative().optional(),
6285
+ citedText: z.string().optional()
6286
+ });
6287
+ //#endregion
6279
6288
  //#region src/ui-message-stream/ui-message-chunks.ts
6280
6289
  const toolMetadataSchema$1 = z.record(z.string(), jsonValueSchema.optional());
6281
6290
  const uiMessageChunkSchema = lazySchema(() => zodSchema$1(z.union([
@@ -6293,6 +6302,7 @@ const uiMessageChunkSchema = lazySchema(() => zodSchema$1(z.union([
6293
6302
  z.looseObject({
6294
6303
  type: z.literal("text-end"),
6295
6304
  id: z.string(),
6305
+ citations: z.array(citationSchema).optional(),
6296
6306
  providerMetadata: providerMetadataSchema.optional()
6297
6307
  }),
6298
6308
  z.looseObject({
@@ -6604,6 +6614,7 @@ function createStreamingUIMessageState({ lastMessage, messageId }) {
6604
6614
  };
6605
6615
  }
6606
6616
  function processUIMessageStream({ stream, messageMetadataSchema, dataPartSchemas, runUpdateMessageJob, onError, onToolCall, onData, resetStateOnMessageIdChange = false, resetStateOnFirstMessageStart = false }) {
6617
+ let isFirstMessageStart = true;
6607
6618
  return stream.pipeThrough(new TransformStream({ async transform(chunk, controller) {
6608
6619
  await runUpdateMessageJob(async ({ state, write }) => {
6609
6620
  function getCurrentStepParts() {
@@ -6765,6 +6776,7 @@ function processUIMessageStream({ stream, messageMetadataSchema, dataPartSchemas
6765
6776
  message: `Received text-end for missing text part with ID "${chunk.id}". Ensure a "text-start" chunk is sent before any "text-end" chunks.`
6766
6777
  });
6767
6778
  textPart.state = "done";
6779
+ if (chunk.citations != null) textPart.citations = chunk.citations;
6768
6780
  textPart.providerMetadata = chunk.providerMetadata ?? textPart.providerMetadata;
6769
6781
  delete state.activeTextParts[chunk.id];
6770
6782
  write();
@@ -7068,15 +7080,18 @@ function processUIMessageStream({ stream, messageMetadataSchema, dataPartSchemas
7068
7080
  }
7069
7081
  break;
7070
7082
  }
7071
- case "start":
7072
- if (chunk.messageId != null && (resetStateOnFirstMessageStart || resetStateOnMessageIdChange && chunk.messageId !== state.message.id)) Object.assign(state, createStreamingUIMessageState({
7083
+ case "start": {
7084
+ const shouldReset = resetStateOnFirstMessageStart && isFirstMessageStart || resetStateOnMessageIdChange && chunk.messageId != null && chunk.messageId !== state.message.id;
7085
+ isFirstMessageStart = false;
7086
+ if (shouldReset) Object.assign(state, createStreamingUIMessageState({
7073
7087
  lastMessage: void 0,
7074
- messageId: chunk.messageId
7088
+ messageId: chunk.messageId ?? state.message.id
7075
7089
  }), { finishReason: void 0 });
7076
7090
  if (chunk.messageId != null) state.message.id = chunk.messageId;
7077
7091
  await updateMessageMetadata(chunk.messageMetadata);
7078
- if (chunk.messageId != null || chunk.messageMetadata != null) write({ updateStatus: false });
7092
+ if (shouldReset || chunk.messageId != null || chunk.messageMetadata != null) write({ updateStatus: false });
7079
7093
  break;
7094
+ }
7080
7095
  case "finish":
7081
7096
  if (chunk.finishReason != null) state.finishReason = chunk.finishReason;
7082
7097
  await updateMessageMetadata(chunk.messageMetadata);
@@ -7248,6 +7263,7 @@ function toUIMessageChunk(part, { tools, sendReasoning = true, sendSources = fal
7248
7263
  case "text-end": return {
7249
7264
  type: "text-end",
7250
7265
  id: part.id,
7266
+ ...part.citations != null ? { citations: part.citations } : {},
7251
7267
  ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
7252
7268
  };
7253
7269
  case "reasoning-start":
@@ -7917,6 +7933,47 @@ function executeToolsFromStream({ stream, tools, callId, messages, abortSignal,
7917
7933
  } }));
7918
7934
  }
7919
7935
  //#endregion
7936
+ //#region src/generate-text/is-output-chunk.ts
7937
+ const isOutputChunkType = {
7938
+ file: true,
7939
+ custom: false,
7940
+ source: false,
7941
+ "text-start": false,
7942
+ "text-end": false,
7943
+ "text-delta": true,
7944
+ "reasoning-start": false,
7945
+ "reasoning-end": false,
7946
+ "reasoning-delta": true,
7947
+ "reasoning-file": true,
7948
+ "tool-input-start": false,
7949
+ "tool-input-end": false,
7950
+ "tool-input-delta": true,
7951
+ "tool-approval-request": false,
7952
+ "tool-approval-response": false,
7953
+ "tool-call": true,
7954
+ "tool-result": false,
7955
+ "tool-error": false,
7956
+ "tool-output-denied": false,
7957
+ "tool-execution-end": false,
7958
+ "model-call-start": false,
7959
+ "model-call-response-metadata": false,
7960
+ "model-call-end": false,
7961
+ error: false,
7962
+ raw: false
7963
+ };
7964
+ function isOutputChunk$1(chunk) {
7965
+ if (!isOutputChunkType[chunk.type]) return false;
7966
+ switch (chunk.type) {
7967
+ case "text-delta":
7968
+ case "reasoning-delta": return chunk.text.length > 0;
7969
+ case "tool-input-delta": return chunk.delta.length > 0;
7970
+ case "file":
7971
+ case "reasoning-file":
7972
+ case "tool-call": return true;
7973
+ default: return false;
7974
+ }
7975
+ }
7976
+ //#endregion
7920
7977
  //#region src/generate-text/invoke-tool-callbacks-from-stream.ts
7921
7978
  function invokeToolCallbacksFromStream({ stream, tools, stepInputMessages, abortSignal, toolsContext }) {
7922
7979
  if (tools == null) return stream;
@@ -8216,7 +8273,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({ too
8216
8273
  let previousOutputChunkTimestampMs;
8217
8274
  const timeBetweenOutputChunksMs = [];
8218
8275
  return new TransformStream({ async transform(chunk, controller) {
8219
- if (isOutputChunk$1(chunk)) {
8276
+ if (isOutputChunk(chunk)) {
8220
8277
  const outputChunkTimestampMs = now();
8221
8278
  if (timeToFirstOutputMs == null) timeToFirstOutputMs = outputChunkTimestampMs - callStartTimestampMs;
8222
8279
  else if (previousOutputChunkTimestampMs != null) timeBetweenOutputChunksMs.push(outputChunkTimestampMs - previousOutputChunkTimestampMs);
@@ -8528,7 +8585,7 @@ function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({ too
8528
8585
  * Used to measure time-to-first-output for text, reasoning, generated files,
8529
8586
  * and tool calls.
8530
8587
  */
8531
- function isOutputChunk$1(chunk) {
8588
+ function isOutputChunk(chunk) {
8532
8589
  return chunk.type === "text-delta" && chunk.delta.length > 0 || chunk.type === "reasoning-delta" && chunk.delta.length > 0 || chunk.type === "tool-input-delta" && chunk.delta.length > 0 || chunk.type === "file" || chunk.type === "reasoning-file" || chunk.type === "tool-call";
8533
8590
  }
8534
8591
  function calculateOutputChunkTimingStats(timingsMs) {
@@ -8589,45 +8646,6 @@ const originalGenerateCallId$7 = createIdGenerator$1({
8589
8646
  prefix: "call",
8590
8647
  size: 24
8591
8648
  });
8592
- const isOutputChunkType = {
8593
- file: true,
8594
- custom: false,
8595
- source: false,
8596
- "text-start": false,
8597
- "text-end": false,
8598
- "text-delta": true,
8599
- "reasoning-start": false,
8600
- "reasoning-end": false,
8601
- "reasoning-delta": true,
8602
- "reasoning-file": true,
8603
- "tool-input-start": false,
8604
- "tool-input-end": false,
8605
- "tool-input-delta": true,
8606
- "tool-approval-request": false,
8607
- "tool-approval-response": false,
8608
- "tool-call": true,
8609
- "tool-result": false,
8610
- "tool-error": false,
8611
- "tool-output-denied": false,
8612
- "tool-execution-end": false,
8613
- "model-call-start": false,
8614
- "model-call-response-metadata": false,
8615
- "model-call-end": false,
8616
- error: false,
8617
- raw: false
8618
- };
8619
- function isOutputChunk(chunk) {
8620
- if (!isOutputChunkType[chunk.type]) return false;
8621
- switch (chunk.type) {
8622
- case "text-delta":
8623
- case "reasoning-delta": return chunk.text.length > 0;
8624
- case "tool-input-delta": return chunk.delta.length > 0;
8625
- case "file":
8626
- case "reasoning-file":
8627
- case "tool-call": return true;
8628
- default: return false;
8629
- }
8630
- }
8631
8649
  /**
8632
8650
  * Generate a text and call tools for a given prompt using a language model.
8633
8651
  *
@@ -9070,6 +9088,7 @@ var DefaultStreamTextResult = class {
9070
9088
  return;
9071
9089
  }
9072
9090
  activeText.providerMetadata = part.providerMetadata ?? activeText.providerMetadata;
9091
+ if (part.citations != null) activeText.citations = part.citations;
9073
9092
  delete activeTextContent[part.id];
9074
9093
  }
9075
9094
  if (part.type === "reasoning-start") {
@@ -9731,7 +9750,7 @@ var DefaultStreamTextResult = class {
9731
9750
  enqueueAttemptPart(value);
9732
9751
  return;
9733
9752
  }
9734
- if (isOutputChunk(value)) {
9753
+ if (isOutputChunk$1(value)) {
9735
9754
  clearFirstChunkTimeout();
9736
9755
  resetChunkTimeout();
9737
9756
  }
@@ -9889,7 +9908,7 @@ var DefaultStreamTextResult = class {
9889
9908
  });
9890
9909
  }
9891
9910
  const chunkType = chunk.type;
9892
- if (isOutputChunk(chunk)) hasReceivedOutputChunk = true;
9911
+ if (isOutputChunk$1(chunk)) hasReceivedOutputChunk = true;
9893
9912
  switch (chunkType) {
9894
9913
  case "file":
9895
9914
  case "custom":
@@ -10654,6 +10673,7 @@ function readUIMessageStream({ message, stream, onError, terminateOnError = fals
10654
10673
  consumeStream({
10655
10674
  stream: processUIMessageStream({
10656
10675
  stream,
10676
+ resetStateOnMessageIdChange: true,
10657
10677
  runUpdateMessageJob(job) {
10658
10678
  return job({
10659
10679
  state,
@@ -10980,6 +11000,7 @@ const uiMessagesSchema = lazySchema(() => {
10980
11000
  z.object({
10981
11001
  type: z.literal("text"),
10982
11002
  text: z.string(),
11003
+ citations: z.array(citationSchema).optional(),
10983
11004
  state: z.enum(["streaming", "done"]).optional(),
10984
11005
  providerMetadata: providerMetadataSchema.optional()
10985
11006
  }),
@@ -12878,7 +12899,7 @@ function validateDecisionAnswers({ questions, answers, rounding }) {
12878
12899
  if (answer.probabilities !== void 0) {
12879
12900
  validateDistribution(answer.probabilities, Object.keys(question.criteria), answers, id, probabilityError);
12880
12901
  const selected = answer.probabilities[answer.choice];
12881
- if (Object.values(answer.probabilities).some((probability) => probability > selected + tolerance)) invalidAnswer(answers, `Question "${id}" did not select a highest-probability option.`);
12902
+ if (Object.values(answer.probabilities).some((probability) => probability > selected + tolerance + 2 * probabilityError)) invalidAnswer(answers, `Question "${id}" did not select a highest-probability option.`);
12882
12903
  }
12883
12904
  break;
12884
12905
  case "score":
@@ -15677,7 +15698,7 @@ function simulateStreamingMiddleware() {
15677
15698
  });
15678
15699
  for (const part of result.content) switch (part.type) {
15679
15700
  case "text":
15680
- if (part.text.length > 0) {
15701
+ if (part.text.length > 0 || (part.citations?.length ?? 0) > 0) {
15681
15702
  controller.enqueue({
15682
15703
  type: "text-start",
15683
15704
  id: String(id),
@@ -15690,7 +15711,8 @@ function simulateStreamingMiddleware() {
15690
15711
  });
15691
15712
  controller.enqueue({
15692
15713
  type: "text-end",
15693
- id: String(id)
15714
+ id: String(id),
15715
+ ...part.citations != null ? { citations: part.citations } : {}
15694
15716
  });
15695
15717
  id++;
15696
15718
  }
@@ -19719,8 +19741,9 @@ var HttpChatTransport = class {
19719
19741
  //#endregion
19720
19742
  //#region src/ui/default-chat-transport.ts
19721
19743
  var DefaultChatTransport = class extends HttpChatTransport {
19722
- constructor(options = {}) {
19744
+ constructor({ resumeStreamIsReplay = true, ...options } = {}) {
19723
19745
  super(options);
19746
+ this.resumeStreamIsReplay = resumeStreamIsReplay;
19724
19747
  }
19725
19748
  processResponseStream(stream) {
19726
19749
  return parseJsonEventStream$1({
@@ -19831,6 +19854,14 @@ var AbstractChat = class {
19831
19854
  ...options
19832
19855
  });
19833
19856
  };
19857
+ this["~resumeStreamIfDisconnected"] = async ({ shouldResume = () => true } = {}) => {
19858
+ const activeResponse = this.activeResponse;
19859
+ if (this.resumableStreamState == null && activeResponse != null) {
19860
+ await activeResponse.completionPromise;
19861
+ if (this.resumableStreamState !== activeResponse.state) return;
19862
+ }
19863
+ if (this.resumableStreamState != null && shouldResume()) await this.resumeStream();
19864
+ };
19834
19865
  this.clearError = () => {
19835
19866
  if (this.status === "error") {
19836
19867
  this.state.error = void 0;
@@ -19873,7 +19904,6 @@ var AbstractChat = class {
19873
19904
  });
19874
19905
  this.addToolOutput = async ({ state, toolCallId, output, errorText, options }) => this.jobExecutor.run(async () => {
19875
19906
  const messages = this.state.messages;
19876
- const lastMessage = messages[messages.length - 1];
19877
19907
  const updatePart = (part) => {
19878
19908
  if (!isToolUIPart(part) || part.toolCallId !== toolCallId) return part;
19879
19909
  const { approval: existingApproval, ...toolPart } = part;
@@ -19897,16 +19927,20 @@ var AbstractChat = class {
19897
19927
  errorText: void 0
19898
19928
  };
19899
19929
  };
19900
- this.state.replaceMessage(messages.length - 1, {
19901
- ...lastMessage,
19902
- parts: lastMessage.parts.map(updatePart)
19903
- });
19930
+ const messageIndex = messages.findIndex((message) => message.parts.some((part) => isToolUIPart(part) && part.toolCallId === toolCallId));
19931
+ if (messageIndex !== -1) {
19932
+ const message = messages[messageIndex];
19933
+ this.state.replaceMessage(messageIndex, {
19934
+ ...message,
19935
+ parts: message.parts.map(updatePart)
19936
+ });
19937
+ }
19904
19938
  if (this.activeResponse) this.activeResponse.state.message.parts = this.activeResponse.state.message.parts.map(updatePart);
19905
- if (this.status !== "streaming" && this.status !== "submitted" && this.sendAutomaticallyWhen) {
19939
+ if (messageIndex !== -1 && this.status !== "streaming" && this.status !== "submitted" && this.sendAutomaticallyWhen) {
19906
19940
  const shouldSend = await this.shouldSendAutomatically();
19907
19941
  if (shouldSend) this.runAutomaticRequest(() => this.makeRequest({
19908
19942
  trigger: "submit-message",
19909
- messageId: this.lastMessage?.id,
19943
+ messageId: messages[messageIndex].id,
19910
19944
  ...options
19911
19945
  }), shouldSend);
19912
19946
  }
@@ -20073,6 +20107,7 @@ var AbstractChat = class {
20073
20107
  const lastMessage = this.lastMessage;
20074
20108
  const responseMessageIndex = trigger === "submit-message" && messageId != null ? this.state.messages.findIndex((message) => message.id === messageId) : this.state.messages.length - 1;
20075
20109
  const responseMessage = responseMessageIndex === -1 ? lastMessage : this.state.messages[responseMessageIndex];
20110
+ const originalResponseMessageId = responseMessage?.id;
20076
20111
  const resumableResponseMessage = trigger === "resume-stream" && responseMessage?.role === "assistant" && responseMessage.parts.some((part) => isToolUIPart(part) && (part.state === "input-streaming" || part.state === "input-available" && part.providerExecuted || part.state === "approval-responded")) ? this.state.snapshot(responseMessage) : void 0;
20077
20112
  const usesEarlierAssistantMessage = responseMessageIndex !== -1 && responseMessageIndex < this.state.messages.length - 1 && responseMessage?.role === "assistant";
20078
20113
  let isAbort = false;
@@ -20112,9 +20147,13 @@ var AbstractChat = class {
20112
20147
  write: ({ updateStatus = true } = {}) => {
20113
20148
  if (response.abortController.signal.aborted) return;
20114
20149
  if (updateStatus) this.setStatus({ status: "streaming" });
20115
- if (usesEarlierAssistantMessage) this.state.replaceMessage(responseMessageIndex, response.state.message);
20116
- else if (response.state.message.id === this.lastMessage?.id) this.state.replaceMessage(this.state.messages.length - 1, response.state.message);
20117
- else this.state.pushMessage(response.state.message);
20150
+ const existingMessageIndex = this.state.messages.findLastIndex((message) => message.id === response.state.message.id);
20151
+ if (existingMessageIndex !== -1) this.state.replaceMessage(existingMessageIndex, response.state.message);
20152
+ else if (usesEarlierAssistantMessage) {
20153
+ const originalMessageIndex = this.state.messages.findLastIndex((message) => message.id === originalResponseMessageId);
20154
+ if (originalMessageIndex !== -1) this.state.replaceMessage(originalMessageIndex, response.state.message);
20155
+ else this.state.pushMessage(response.state.message);
20156
+ } else this.state.pushMessage(response.state.message);
20118
20157
  }
20119
20158
  });
20120
20159
  });