ai 5.0.0-canary.22 → 5.0.0-canary.24

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
@@ -467,102 +467,84 @@ import {
467
467
 
468
468
  // src/ui-message-stream/ui-message-stream-parts.ts
469
469
  import { z } from "zod";
470
- var toolCallSchema = z.object({
471
- toolCallId: z.string(),
472
- toolName: z.string(),
473
- args: z.unknown()
474
- });
475
- var toolResultValueSchema = z.object({
476
- toolCallId: z.string(),
477
- result: z.unknown(),
478
- providerMetadata: z.any().optional()
479
- });
480
- var sourceSchema = z.object({
481
- type: z.literal("source"),
482
- sourceType: z.literal("url"),
483
- id: z.string(),
484
- url: z.string(),
485
- title: z.string().optional(),
486
- providerMetadata: z.any().optional()
487
- // Use z.any() for generic metadata
488
- });
489
- var uiMessageStreamPartSchema = z.discriminatedUnion("type", [
470
+ var uiMessageStreamPartSchema = z.union([
490
471
  z.object({
491
472
  type: z.literal("text"),
492
- value: z.string()
473
+ text: z.string()
493
474
  }),
494
475
  z.object({
495
476
  type: z.literal("error"),
496
- value: z.string()
477
+ errorText: z.string()
497
478
  }),
498
479
  z.object({
499
- type: z.literal("tool-call"),
500
- value: toolCallSchema
480
+ type: z.literal("tool-call-streaming-start"),
481
+ toolCallId: z.string(),
482
+ toolName: z.string()
501
483
  }),
502
484
  z.object({
503
- type: z.literal("tool-result"),
504
- value: toolResultValueSchema
485
+ type: z.literal("tool-call-delta"),
486
+ toolCallId: z.string(),
487
+ argsTextDelta: z.string()
505
488
  }),
506
489
  z.object({
507
- type: z.literal("tool-call-streaming-start"),
508
- value: z.object({ toolCallId: z.string(), toolName: z.string() })
490
+ type: z.literal("tool-call"),
491
+ toolCallId: z.string(),
492
+ toolName: z.string(),
493
+ args: z.unknown()
509
494
  }),
510
495
  z.object({
511
- type: z.literal("tool-call-delta"),
512
- value: z.object({ toolCallId: z.string(), argsTextDelta: z.string() })
496
+ type: z.literal("tool-result"),
497
+ toolCallId: z.string(),
498
+ result: z.unknown(),
499
+ providerMetadata: z.any().optional()
513
500
  }),
514
501
  z.object({
515
502
  type: z.literal("reasoning"),
516
- value: z.object({
517
- text: z.string(),
518
- providerMetadata: z.record(z.any()).optional()
519
- })
503
+ text: z.string(),
504
+ providerMetadata: z.record(z.any()).optional()
520
505
  }),
521
506
  z.object({
522
507
  type: z.literal("source"),
523
- value: sourceSchema
508
+ sourceType: z.literal("url"),
509
+ id: z.string(),
510
+ url: z.string(),
511
+ title: z.string().optional(),
512
+ providerMetadata: z.any().optional()
513
+ // Use z.any() for generic metadata
524
514
  }),
525
515
  z.object({
526
516
  type: z.literal("file"),
527
- value: z.object({
528
- url: z.string(),
529
- mediaType: z.string()
530
- })
517
+ url: z.string(),
518
+ mediaType: z.string()
519
+ }),
520
+ z.object({
521
+ type: z.string().startsWith("data-"),
522
+ id: z.string().optional(),
523
+ data: z.unknown()
531
524
  }),
532
525
  z.object({
533
526
  type: z.literal("metadata"),
534
- value: z.object({
535
- metadata: z.unknown()
536
- })
527
+ value: z.object({ metadata: z.unknown() })
537
528
  }),
538
529
  z.object({
539
530
  type: z.literal("start-step"),
540
- value: z.object({
541
- metadata: z.unknown()
542
- })
531
+ metadata: z.unknown().optional()
543
532
  }),
544
533
  z.object({
545
534
  type: z.literal("finish-step"),
546
- value: z.object({
547
- metadata: z.unknown()
548
- })
535
+ metadata: z.unknown().optional()
549
536
  }),
550
537
  z.object({
551
538
  type: z.literal("start"),
552
- value: z.object({
553
- messageId: z.string().optional(),
554
- metadata: z.unknown()
555
- })
539
+ messageId: z.string().optional(),
540
+ metadata: z.unknown().optional()
556
541
  }),
557
542
  z.object({
558
543
  type: z.literal("finish"),
559
- value: z.object({
560
- metadata: z.unknown()
561
- })
544
+ metadata: z.unknown().optional()
562
545
  }),
563
546
  z.object({
564
- type: z.literal("reasoning-part-finish"),
565
- value: z.null()
547
+ type: z.literal("reasoning-part-finish")
566
548
  })
567
549
  ]);
568
550
 
@@ -974,303 +956,305 @@ function getToolInvocations(message) {
974
956
  }
975
957
 
976
958
  // src/ui/process-ui-message-stream.ts
977
- function processUIMessageStream({
978
- stream,
979
- onUpdate,
980
- onToolCall,
981
- onFinish,
959
+ function createStreamingUIMessageState({
982
960
  lastMessage,
983
- newMessageId,
984
- messageMetadataSchema
985
- }) {
961
+ newMessageId = "no-id"
962
+ } = {}) {
986
963
  var _a17;
987
964
  const isContinuation = (lastMessage == null ? void 0 : lastMessage.role) === "assistant";
988
- let step = isContinuation ? 1 + ((_a17 = extractMaxToolInvocationStep(getToolInvocations(lastMessage))) != null ? _a17 : 0) : 0;
965
+ const step = isContinuation ? 1 + ((_a17 = extractMaxToolInvocationStep(getToolInvocations(lastMessage))) != null ? _a17 : 0) : 0;
989
966
  const message = isContinuation ? structuredClone(lastMessage) : {
990
967
  id: newMessageId,
991
968
  metadata: {},
992
969
  role: "assistant",
993
970
  parts: []
994
971
  };
995
- let currentTextPart = void 0;
996
- let currentReasoningPart = void 0;
997
- function updateToolInvocationPart(toolCallId, invocation) {
998
- const part = message.parts.find(
999
- (part2) => part2.type === "tool-invocation" && part2.toolInvocation.toolCallId === toolCallId
1000
- );
1001
- if (part != null) {
1002
- part.toolInvocation = invocation;
1003
- } else {
1004
- message.parts.push({
1005
- type: "tool-invocation",
1006
- toolInvocation: invocation
1007
- });
1008
- }
1009
- }
1010
- const partialToolCalls = {};
1011
- async function updateMessageMetadata(metadata) {
1012
- if (metadata != null) {
1013
- const mergedMetadata = message.metadata != null ? mergeObjects(message.metadata, metadata) : metadata;
1014
- if (messageMetadataSchema != null) {
1015
- await validateTypes({
1016
- value: mergedMetadata,
1017
- schema: messageMetadataSchema
1018
- });
1019
- }
1020
- message.metadata = mergedMetadata;
1021
- }
1022
- }
972
+ return {
973
+ message,
974
+ activeTextPart: void 0,
975
+ activeReasoningPart: void 0,
976
+ partialToolCalls: {},
977
+ step
978
+ };
979
+ }
980
+ function processUIMessageStream({
981
+ stream,
982
+ onToolCall,
983
+ messageMetadataSchema,
984
+ runUpdateMessageJob
985
+ }) {
1023
986
  return stream.pipeThrough(
1024
987
  new TransformStream({
1025
- async transform(chunk, controller) {
1026
- const { type, value } = chunk;
1027
- switch (type) {
1028
- case "text": {
1029
- if (currentTextPart == null) {
1030
- currentTextPart = {
1031
- type: "text",
1032
- text: value
1033
- };
1034
- message.parts.push(currentTextPart);
988
+ async transform(part, controller) {
989
+ await runUpdateMessageJob(async ({ state, write }) => {
990
+ function updateToolInvocationPart(toolCallId, invocation) {
991
+ const part2 = state.message.parts.find(
992
+ (part3) => part3.type === "tool-invocation" && part3.toolInvocation.toolCallId === toolCallId
993
+ );
994
+ if (part2 != null) {
995
+ part2.toolInvocation = invocation;
1035
996
  } else {
1036
- currentTextPart.text += value;
997
+ state.message.parts.push({
998
+ type: "tool-invocation",
999
+ toolInvocation: invocation
1000
+ });
1037
1001
  }
1038
- onUpdate == null ? void 0 : onUpdate({ message });
1039
- break;
1040
1002
  }
1041
- case "reasoning": {
1042
- if (currentReasoningPart == null) {
1043
- currentReasoningPart = {
1044
- type: "reasoning",
1045
- text: value.text,
1046
- providerMetadata: value.providerMetadata
1047
- };
1048
- message.parts.push(currentReasoningPart);
1049
- } else {
1050
- currentReasoningPart.text += value.text;
1051
- currentReasoningPart.providerMetadata = value.providerMetadata;
1003
+ async function updateMessageMetadata(metadata) {
1004
+ if (metadata != null) {
1005
+ const mergedMetadata = state.message.metadata != null ? mergeObjects(state.message.metadata, metadata) : metadata;
1006
+ if (messageMetadataSchema != null) {
1007
+ await validateTypes({
1008
+ value: mergedMetadata,
1009
+ schema: messageMetadataSchema
1010
+ });
1011
+ }
1012
+ state.message.metadata = mergedMetadata;
1052
1013
  }
1053
- onUpdate == null ? void 0 : onUpdate({ message });
1054
- break;
1055
1014
  }
1056
- case "reasoning-part-finish": {
1057
- if (currentReasoningPart != null) {
1058
- currentReasoningPart = void 0;
1015
+ switch (part.type) {
1016
+ case "text": {
1017
+ if (state.activeTextPart == null) {
1018
+ state.activeTextPart = {
1019
+ type: "text",
1020
+ text: part.text
1021
+ };
1022
+ state.message.parts.push(state.activeTextPart);
1023
+ } else {
1024
+ state.activeTextPart.text += part.text;
1025
+ }
1026
+ write();
1027
+ break;
1059
1028
  }
1060
- break;
1061
- }
1062
- case "file": {
1063
- message.parts.push({
1064
- type: "file",
1065
- mediaType: value.mediaType,
1066
- url: value.url
1067
- });
1068
- onUpdate == null ? void 0 : onUpdate({ message });
1069
- break;
1070
- }
1071
- case "source": {
1072
- message.parts.push({
1073
- type: "source",
1074
- source: value
1075
- });
1076
- onUpdate == null ? void 0 : onUpdate({ message });
1077
- break;
1078
- }
1079
- case "tool-call-streaming-start": {
1080
- const toolInvocations = getToolInvocations(message);
1081
- partialToolCalls[value.toolCallId] = {
1082
- text: "",
1083
- step,
1084
- toolName: value.toolName,
1085
- index: toolInvocations.length
1086
- };
1087
- updateToolInvocationPart(value.toolCallId, {
1088
- state: "partial-call",
1089
- step,
1090
- toolCallId: value.toolCallId,
1091
- toolName: value.toolName,
1092
- args: void 0
1093
- });
1094
- onUpdate == null ? void 0 : onUpdate({ message });
1095
- break;
1096
- }
1097
- case "tool-call-delta": {
1098
- const partialToolCall = partialToolCalls[value.toolCallId];
1099
- partialToolCall.text += value.argsTextDelta;
1100
- const { value: partialArgs } = await parsePartialJson(
1101
- partialToolCall.text
1102
- );
1103
- updateToolInvocationPart(value.toolCallId, {
1104
- state: "partial-call",
1105
- step: partialToolCall.step,
1106
- toolCallId: value.toolCallId,
1107
- toolName: partialToolCall.toolName,
1108
- args: partialArgs
1109
- });
1110
- onUpdate == null ? void 0 : onUpdate({ message });
1111
- break;
1112
- }
1113
- case "tool-call": {
1114
- const call = { args: value.args, ...value };
1115
- updateToolInvocationPart(value.toolCallId, {
1116
- state: "call",
1117
- step,
1118
- ...call
1119
- });
1120
- onUpdate == null ? void 0 : onUpdate({ message });
1121
- if (onToolCall) {
1122
- const result = await onToolCall({
1123
- toolCall: call
1029
+ case "reasoning": {
1030
+ if (state.activeReasoningPart == null) {
1031
+ state.activeReasoningPart = {
1032
+ type: "reasoning",
1033
+ text: part.text,
1034
+ providerMetadata: part.providerMetadata
1035
+ };
1036
+ state.message.parts.push(state.activeReasoningPart);
1037
+ } else {
1038
+ state.activeReasoningPart.text += part.text;
1039
+ state.activeReasoningPart.providerMetadata = part.providerMetadata;
1040
+ }
1041
+ write();
1042
+ break;
1043
+ }
1044
+ case "reasoning-part-finish": {
1045
+ if (state.activeReasoningPart != null) {
1046
+ state.activeReasoningPart = void 0;
1047
+ }
1048
+ break;
1049
+ }
1050
+ case "file": {
1051
+ state.message.parts.push({
1052
+ type: "file",
1053
+ mediaType: part.mediaType,
1054
+ url: part.url
1055
+ });
1056
+ write();
1057
+ break;
1058
+ }
1059
+ case "source": {
1060
+ state.message.parts.push({
1061
+ type: "source",
1062
+ source: {
1063
+ sourceType: "url",
1064
+ id: part.id,
1065
+ url: part.url,
1066
+ title: part.title,
1067
+ providerMetadata: part.providerMetadata
1068
+ }
1124
1069
  });
1125
- if (result != null) {
1126
- updateToolInvocationPart(value.toolCallId, {
1127
- state: "result",
1128
- step,
1129
- ...call,
1130
- result
1070
+ write();
1071
+ break;
1072
+ }
1073
+ case "tool-call-streaming-start": {
1074
+ const toolInvocations = getToolInvocations(state.message);
1075
+ state.partialToolCalls[part.toolCallId] = {
1076
+ text: "",
1077
+ step: state.step,
1078
+ toolName: part.toolName,
1079
+ index: toolInvocations.length
1080
+ };
1081
+ updateToolInvocationPart(part.toolCallId, {
1082
+ state: "partial-call",
1083
+ step: state.step,
1084
+ toolCallId: part.toolCallId,
1085
+ toolName: part.toolName,
1086
+ args: void 0
1087
+ });
1088
+ write();
1089
+ break;
1090
+ }
1091
+ case "tool-call-delta": {
1092
+ const partialToolCall = state.partialToolCalls[part.toolCallId];
1093
+ partialToolCall.text += part.argsTextDelta;
1094
+ const { value: partialArgs } = await parsePartialJson(
1095
+ partialToolCall.text
1096
+ );
1097
+ updateToolInvocationPart(part.toolCallId, {
1098
+ state: "partial-call",
1099
+ step: partialToolCall.step,
1100
+ toolCallId: part.toolCallId,
1101
+ toolName: partialToolCall.toolName,
1102
+ args: partialArgs
1103
+ });
1104
+ write();
1105
+ break;
1106
+ }
1107
+ case "tool-call": {
1108
+ updateToolInvocationPart(part.toolCallId, {
1109
+ state: "call",
1110
+ step: state.step,
1111
+ toolCallId: part.toolCallId,
1112
+ toolName: part.toolName,
1113
+ args: part.args
1114
+ });
1115
+ write();
1116
+ if (onToolCall) {
1117
+ const result = await onToolCall({
1118
+ toolCall: part
1131
1119
  });
1132
- onUpdate == null ? void 0 : onUpdate({ message });
1120
+ if (result != null) {
1121
+ updateToolInvocationPart(part.toolCallId, {
1122
+ state: "result",
1123
+ step: state.step,
1124
+ toolCallId: part.toolCallId,
1125
+ toolName: part.toolName,
1126
+ args: part.args,
1127
+ result
1128
+ });
1129
+ write();
1130
+ }
1133
1131
  }
1132
+ break;
1134
1133
  }
1135
- break;
1136
- }
1137
- case "tool-result": {
1138
- const toolInvocations = getToolInvocations(message);
1139
- if (toolInvocations == null) {
1140
- throw new Error("tool_result must be preceded by a tool_call");
1141
- }
1142
- const toolInvocationIndex = toolInvocations.findIndex(
1143
- (invocation) => invocation.toolCallId === value.toolCallId
1144
- );
1145
- if (toolInvocationIndex === -1) {
1146
- throw new Error(
1147
- "tool_result must be preceded by a tool_call with the same toolCallId"
1134
+ case "tool-result": {
1135
+ const toolInvocations = getToolInvocations(state.message);
1136
+ if (toolInvocations == null) {
1137
+ throw new Error("tool_result must be preceded by a tool_call");
1138
+ }
1139
+ const toolInvocationIndex = toolInvocations.findIndex(
1140
+ (invocation) => invocation.toolCallId === part.toolCallId
1148
1141
  );
1142
+ if (toolInvocationIndex === -1) {
1143
+ throw new Error(
1144
+ "tool_result must be preceded by a tool_call with the same toolCallId"
1145
+ );
1146
+ }
1147
+ updateToolInvocationPart(part.toolCallId, {
1148
+ ...toolInvocations[toolInvocationIndex],
1149
+ state: "result",
1150
+ result: part.result
1151
+ });
1152
+ write();
1153
+ break;
1149
1154
  }
1150
- const result = { result: value.result, ...value };
1151
- updateToolInvocationPart(value.toolCallId, {
1152
- ...toolInvocations[toolInvocationIndex],
1153
- state: "result",
1154
- ...result
1155
- });
1156
- onUpdate == null ? void 0 : onUpdate({ message });
1157
- break;
1158
- }
1159
- case "start-step": {
1160
- message.parts.push({ type: "step-start" });
1161
- await updateMessageMetadata(value.metadata);
1162
- onUpdate == null ? void 0 : onUpdate({ message });
1163
- break;
1164
- }
1165
- case "finish-step": {
1166
- step += 1;
1167
- currentTextPart = void 0;
1168
- currentReasoningPart = void 0;
1169
- await updateMessageMetadata(value.metadata);
1170
- if (value.metadata != null) {
1171
- onUpdate == null ? void 0 : onUpdate({ message });
1155
+ case "start-step": {
1156
+ state.message.parts.push({ type: "step-start" });
1157
+ await updateMessageMetadata(part.metadata);
1158
+ write();
1159
+ break;
1172
1160
  }
1173
- break;
1174
- }
1175
- case "start": {
1176
- if (value.messageId != null) {
1177
- message.id = value.messageId;
1161
+ case "finish-step": {
1162
+ state.step += 1;
1163
+ state.activeTextPart = void 0;
1164
+ state.activeReasoningPart = void 0;
1165
+ await updateMessageMetadata(part.metadata);
1166
+ if (part.metadata != null) {
1167
+ write();
1168
+ }
1169
+ break;
1170
+ }
1171
+ case "start": {
1172
+ if (part.messageId != null) {
1173
+ state.message.id = part.messageId;
1174
+ }
1175
+ await updateMessageMetadata(part.metadata);
1176
+ if (part.messageId != null || part.metadata != null) {
1177
+ write();
1178
+ }
1179
+ break;
1178
1180
  }
1179
- await updateMessageMetadata(value.metadata);
1180
- if (value.messageId != null || value.metadata != null) {
1181
- onUpdate == null ? void 0 : onUpdate({ message });
1181
+ case "finish": {
1182
+ await updateMessageMetadata(part.metadata);
1183
+ if (part.metadata != null) {
1184
+ write();
1185
+ }
1186
+ break;
1182
1187
  }
1183
- break;
1184
- }
1185
- case "finish": {
1186
- await updateMessageMetadata(value.metadata);
1187
- if (value.metadata != null) {
1188
- onUpdate == null ? void 0 : onUpdate({ message });
1188
+ case "metadata": {
1189
+ await updateMessageMetadata(part.metadata);
1190
+ if (part.metadata != null) {
1191
+ write();
1192
+ }
1193
+ break;
1189
1194
  }
1190
- break;
1191
- }
1192
- case "metadata": {
1193
- await updateMessageMetadata(value.metadata);
1194
- if (value.metadata != null) {
1195
- onUpdate == null ? void 0 : onUpdate({ message });
1195
+ case "error": {
1196
+ throw new Error(part.errorText);
1197
+ }
1198
+ default: {
1199
+ if (part.type.startsWith("data-")) {
1200
+ const existingPart = part.id != null ? state.message.parts.find(
1201
+ (partArg) => part.type === partArg.type && part.id === partArg.id
1202
+ ) : void 0;
1203
+ if (existingPart != null) {
1204
+ existingPart.value = mergeObjects(
1205
+ existingPart.data,
1206
+ part.data
1207
+ );
1208
+ } else {
1209
+ state.message.parts.push({
1210
+ type: part.type,
1211
+ id: part.id,
1212
+ value: part.data
1213
+ });
1214
+ }
1215
+ write();
1216
+ }
1196
1217
  }
1197
- break;
1198
- }
1199
- case "error": {
1200
- throw new Error(value);
1201
- }
1202
- default: {
1203
- const _exhaustiveCheck = type;
1204
- throw new Error(`Unhandled stream part: ${_exhaustiveCheck}`);
1205
1218
  }
1206
- }
1207
- controller.enqueue(chunk);
1208
- },
1209
- flush() {
1210
- onFinish == null ? void 0 : onFinish({ message });
1219
+ controller.enqueue(part);
1220
+ });
1211
1221
  }
1212
1222
  })
1213
1223
  );
1214
1224
  }
1215
1225
 
1216
- // src/ui/process-chat-text-response.ts
1217
- import { generateId as generateIdFunction } from "@ai-sdk/provider-utils";
1218
-
1219
- // src/ui/process-text-stream.ts
1220
- async function processTextStream({
1221
- stream,
1222
- onTextPart
1223
- }) {
1224
- const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
1225
- while (true) {
1226
- const { done, value } = await reader.read();
1227
- if (done) {
1228
- break;
1229
- }
1230
- await onTextPart(value);
1231
- }
1232
- }
1233
-
1234
- // src/ui/process-chat-text-response.ts
1235
- async function processChatTextResponse({
1236
- stream,
1237
- update,
1238
- onFinish,
1239
- generateId: generateId3 = generateIdFunction
1226
+ // src/ui/transform-text-to-ui-message-stream.ts
1227
+ function transformTextToUiMessageStream({
1228
+ stream
1240
1229
  }) {
1241
- const textPart = { type: "text", text: "" };
1242
- const resultMessage = {
1243
- id: generateId3(),
1244
- role: "assistant",
1245
- parts: [textPart]
1246
- };
1247
- await processTextStream({
1248
- stream,
1249
- onTextPart: (chunk) => {
1250
- textPart.text += chunk;
1251
- update({ message: { ...resultMessage } });
1252
- }
1253
- });
1254
- onFinish == null ? void 0 : onFinish({ message: resultMessage });
1230
+ return stream.pipeThrough(
1231
+ new TransformStream({
1232
+ start(controller) {
1233
+ controller.enqueue({ type: "start" });
1234
+ controller.enqueue({ type: "start-step" });
1235
+ },
1236
+ async transform(part, controller) {
1237
+ controller.enqueue({ type: "text", text: part });
1238
+ },
1239
+ async flush(controller) {
1240
+ controller.enqueue({ type: "finish-step" });
1241
+ controller.enqueue({ type: "finish" });
1242
+ }
1243
+ })
1244
+ );
1255
1245
  }
1256
1246
 
1257
1247
  // src/ui/call-chat-api.ts
1258
1248
  var getOriginalFetch = () => fetch;
1259
- async function callChatApi({
1249
+ async function fetchUIMessageStream({
1260
1250
  api,
1261
1251
  body,
1262
1252
  streamProtocol = "ui-message",
1263
1253
  credentials,
1264
1254
  headers,
1265
1255
  abortController,
1266
- onUpdate,
1267
- onFinish,
1268
- onToolCall,
1269
- generateId: generateId3,
1270
1256
  fetch: fetch2 = getOriginalFetch(),
1271
- lastMessage,
1272
- requestType = "generate",
1273
- messageMetadataSchema
1257
+ requestType = "generate"
1274
1258
  }) {
1275
1259
  var _a17, _b, _c;
1276
1260
  const response = requestType === "resume" ? await fetch2(`${api}?chatId=${body.id}`, {
@@ -1299,177 +1283,674 @@ async function callChatApi({
1299
1283
  if (!response.body) {
1300
1284
  throw new Error("The response body is empty.");
1301
1285
  }
1302
- switch (streamProtocol) {
1303
- case "text": {
1304
- await processChatTextResponse({
1305
- stream: response.body,
1306
- update: onUpdate,
1307
- onFinish,
1308
- generateId: generateId3
1309
- });
1310
- return;
1286
+ return streamProtocol === "text" ? transformTextToUiMessageStream({
1287
+ stream: response.body.pipeThrough(new TextDecoderStream())
1288
+ }) : parseJsonEventStream({
1289
+ stream: response.body,
1290
+ schema: uiMessageStreamPartSchema
1291
+ }).pipeThrough(
1292
+ new TransformStream({
1293
+ async transform(part, controller) {
1294
+ if (!part.success) {
1295
+ throw part.error;
1296
+ }
1297
+ controller.enqueue(part.value);
1298
+ }
1299
+ })
1300
+ );
1301
+ }
1302
+ async function consumeUIMessageStream({
1303
+ stream,
1304
+ onUpdate,
1305
+ onFinish,
1306
+ onToolCall,
1307
+ generateId: generateId3,
1308
+ lastMessage,
1309
+ messageMetadataSchema
1310
+ }) {
1311
+ const state = createStreamingUIMessageState({
1312
+ lastMessage,
1313
+ newMessageId: generateId3()
1314
+ });
1315
+ const runUpdateMessageJob = async (job) => {
1316
+ await job({
1317
+ state,
1318
+ write: () => {
1319
+ onUpdate({ message: state.message });
1320
+ }
1321
+ });
1322
+ };
1323
+ await consumeStream({
1324
+ stream: processUIMessageStream({
1325
+ stream,
1326
+ onToolCall,
1327
+ messageMetadataSchema,
1328
+ runUpdateMessageJob
1329
+ }),
1330
+ onError: (error) => {
1331
+ throw error;
1311
1332
  }
1312
- case "ui-message": {
1333
+ });
1334
+ onFinish == null ? void 0 : onFinish({ message: state.message });
1335
+ }
1336
+ async function callChatApi({
1337
+ api,
1338
+ body,
1339
+ streamProtocol = "ui-message",
1340
+ credentials,
1341
+ headers,
1342
+ abortController,
1343
+ onUpdate,
1344
+ onFinish,
1345
+ onToolCall,
1346
+ generateId: generateId3,
1347
+ fetch: fetch2 = getOriginalFetch(),
1348
+ lastMessage,
1349
+ requestType = "generate",
1350
+ messageMetadataSchema
1351
+ }) {
1352
+ const stream = await fetchUIMessageStream({
1353
+ api,
1354
+ body,
1355
+ streamProtocol,
1356
+ credentials,
1357
+ headers,
1358
+ abortController,
1359
+ fetch: fetch2,
1360
+ requestType
1361
+ });
1362
+ await consumeUIMessageStream({
1363
+ stream,
1364
+ onUpdate,
1365
+ onFinish,
1366
+ onToolCall,
1367
+ generateId: generateId3,
1368
+ lastMessage,
1369
+ messageMetadataSchema
1370
+ });
1371
+ }
1372
+
1373
+ // src/ui/call-completion-api.ts
1374
+ import { parseJsonEventStream as parseJsonEventStream2 } from "@ai-sdk/provider-utils";
1375
+
1376
+ // src/ui/process-text-stream.ts
1377
+ async function processTextStream({
1378
+ stream,
1379
+ onTextPart
1380
+ }) {
1381
+ const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
1382
+ while (true) {
1383
+ const { done, value } = await reader.read();
1384
+ if (done) {
1385
+ break;
1386
+ }
1387
+ await onTextPart(value);
1388
+ }
1389
+ }
1390
+
1391
+ // src/ui/call-completion-api.ts
1392
+ var getOriginalFetch2 = () => fetch;
1393
+ async function callCompletionApi({
1394
+ api,
1395
+ prompt,
1396
+ credentials,
1397
+ headers,
1398
+ body,
1399
+ streamProtocol = "data",
1400
+ setCompletion,
1401
+ setLoading,
1402
+ setError,
1403
+ setAbortController,
1404
+ onFinish,
1405
+ onError,
1406
+ fetch: fetch2 = getOriginalFetch2()
1407
+ }) {
1408
+ var _a17;
1409
+ try {
1410
+ setLoading(true);
1411
+ setError(void 0);
1412
+ const abortController = new AbortController();
1413
+ setAbortController(abortController);
1414
+ setCompletion("");
1415
+ const response = await fetch2(api, {
1416
+ method: "POST",
1417
+ body: JSON.stringify({
1418
+ prompt,
1419
+ ...body
1420
+ }),
1421
+ credentials,
1422
+ headers: {
1423
+ "Content-Type": "application/json",
1424
+ ...headers
1425
+ },
1426
+ signal: abortController.signal
1427
+ }).catch((err) => {
1428
+ throw err;
1429
+ });
1430
+ if (!response.ok) {
1431
+ throw new Error(
1432
+ (_a17 = await response.text()) != null ? _a17 : "Failed to fetch the chat response."
1433
+ );
1434
+ }
1435
+ if (!response.body) {
1436
+ throw new Error("The response body is empty.");
1437
+ }
1438
+ let result = "";
1439
+ switch (streamProtocol) {
1440
+ case "text": {
1441
+ await processTextStream({
1442
+ stream: response.body,
1443
+ onTextPart: (chunk) => {
1444
+ result += chunk;
1445
+ setCompletion(result);
1446
+ }
1447
+ });
1448
+ break;
1449
+ }
1450
+ case "data": {
1451
+ await consumeStream({
1452
+ stream: parseJsonEventStream2({
1453
+ stream: response.body,
1454
+ schema: uiMessageStreamPartSchema
1455
+ }).pipeThrough(
1456
+ new TransformStream({
1457
+ async transform(part) {
1458
+ if (!part.success) {
1459
+ throw part.error;
1460
+ }
1461
+ const streamPart = part.value;
1462
+ if (streamPart.type === "text") {
1463
+ result += streamPart.text;
1464
+ setCompletion(result);
1465
+ } else if (streamPart.type === "error") {
1466
+ throw new Error(streamPart.errorText);
1467
+ }
1468
+ }
1469
+ })
1470
+ ),
1471
+ onError: (error) => {
1472
+ throw error;
1473
+ }
1474
+ });
1475
+ break;
1476
+ }
1477
+ default: {
1478
+ const exhaustiveCheck = streamProtocol;
1479
+ throw new Error(`Unknown stream protocol: ${exhaustiveCheck}`);
1480
+ }
1481
+ }
1482
+ if (onFinish) {
1483
+ onFinish(prompt, result);
1484
+ }
1485
+ setAbortController(null);
1486
+ return result;
1487
+ } catch (err) {
1488
+ if (err.name === "AbortError") {
1489
+ setAbortController(null);
1490
+ return null;
1491
+ }
1492
+ if (err instanceof Error) {
1493
+ if (onError) {
1494
+ onError(err);
1495
+ }
1496
+ }
1497
+ setError(err);
1498
+ } finally {
1499
+ setLoading(false);
1500
+ }
1501
+ }
1502
+
1503
+ // src/ui/chat-store.ts
1504
+ import {
1505
+ generateId as generateIdFunc
1506
+ } from "@ai-sdk/provider-utils";
1507
+
1508
+ // src/util/serial-job-executor.ts
1509
+ var SerialJobExecutor = class {
1510
+ constructor() {
1511
+ this.queue = [];
1512
+ this.isProcessing = false;
1513
+ }
1514
+ async processQueue() {
1515
+ if (this.isProcessing) {
1516
+ return;
1517
+ }
1518
+ this.isProcessing = true;
1519
+ while (this.queue.length > 0) {
1520
+ await this.queue[0]();
1521
+ this.queue.shift();
1522
+ }
1523
+ this.isProcessing = false;
1524
+ }
1525
+ async run(job) {
1526
+ return new Promise((resolve, reject) => {
1527
+ this.queue.push(async () => {
1528
+ try {
1529
+ await job();
1530
+ resolve();
1531
+ } catch (error) {
1532
+ reject(error);
1533
+ }
1534
+ });
1535
+ void this.processQueue();
1536
+ });
1537
+ }
1538
+ };
1539
+
1540
+ // src/ui/should-resubmit-messages.ts
1541
+ function shouldResubmitMessages({
1542
+ originalMaxToolInvocationStep,
1543
+ originalMessageCount,
1544
+ maxSteps: maxSteps2,
1545
+ messages
1546
+ }) {
1547
+ var _a17;
1548
+ const lastMessage = messages[messages.length - 1];
1549
+ return (
1550
+ // check if the feature is enabled:
1551
+ maxSteps2 > 1 && // ensure there is a last message:
1552
+ lastMessage != null && // ensure we actually have new steps (to prevent infinite loops in case of errors):
1553
+ (messages.length > originalMessageCount || extractMaxToolInvocationStep(getToolInvocations(lastMessage)) !== originalMaxToolInvocationStep) && // check that next step is possible:
1554
+ isAssistantMessageWithCompletedToolCalls(lastMessage) && // limit the number of automatic steps:
1555
+ ((_a17 = extractMaxToolInvocationStep(getToolInvocations(lastMessage))) != null ? _a17 : 0) < maxSteps2
1556
+ );
1557
+ }
1558
+ function isAssistantMessageWithCompletedToolCalls(message) {
1559
+ if (message.role !== "assistant") {
1560
+ return false;
1561
+ }
1562
+ const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => {
1563
+ return part.type === "step-start" ? index : lastIndex;
1564
+ }, -1);
1565
+ const lastStepToolInvocations = message.parts.slice(lastStepStartIndex + 1).filter((part) => part.type === "tool-invocation");
1566
+ return lastStepToolInvocations.length > 0 && lastStepToolInvocations.every((part) => "result" in part.toolInvocation);
1567
+ }
1568
+
1569
+ // src/ui/update-tool-call-result.ts
1570
+ function updateToolCallResult({
1571
+ messages,
1572
+ toolCallId,
1573
+ toolResult: result
1574
+ }) {
1575
+ const lastMessage = messages[messages.length - 1];
1576
+ const invocationPart = lastMessage.parts.find(
1577
+ (part) => part.type === "tool-invocation" && part.toolInvocation.toolCallId === toolCallId
1578
+ );
1579
+ if (invocationPart == null) {
1580
+ return;
1581
+ }
1582
+ invocationPart.toolInvocation = {
1583
+ ...invocationPart.toolInvocation,
1584
+ state: "result",
1585
+ result
1586
+ };
1587
+ }
1588
+
1589
+ // src/ui/chat-store.ts
1590
+ var ChatStore = class {
1591
+ constructor({
1592
+ chats = {},
1593
+ generateId: generateId3,
1594
+ messageMetadataSchema,
1595
+ transport,
1596
+ maxSteps: maxSteps2 = 1
1597
+ }) {
1598
+ this.chats = new Map(
1599
+ Object.entries(chats).map(([id, state]) => [
1600
+ id,
1601
+ {
1602
+ messages: [...state.messages],
1603
+ status: "ready",
1604
+ activeResponse: void 0,
1605
+ error: void 0,
1606
+ jobExecutor: new SerialJobExecutor()
1607
+ }
1608
+ ])
1609
+ );
1610
+ this.maxSteps = maxSteps2;
1611
+ this.transport = transport;
1612
+ this.subscribers = /* @__PURE__ */ new Set();
1613
+ this.generateId = generateId3 != null ? generateId3 : generateIdFunc;
1614
+ this.messageMetadataSchema = messageMetadataSchema;
1615
+ }
1616
+ hasChat(id) {
1617
+ return this.chats.has(id);
1618
+ }
1619
+ addChat(id, messages) {
1620
+ this.chats.set(id, {
1621
+ messages,
1622
+ status: "ready",
1623
+ jobExecutor: new SerialJobExecutor()
1624
+ });
1625
+ }
1626
+ getChats() {
1627
+ return Array.from(this.chats.entries());
1628
+ }
1629
+ get chatCount() {
1630
+ return this.chats.size;
1631
+ }
1632
+ getStatus(id) {
1633
+ return this.getChat(id).status;
1634
+ }
1635
+ setStatus({
1636
+ id,
1637
+ status,
1638
+ error
1639
+ }) {
1640
+ const chat = this.getChat(id);
1641
+ if (chat.status === status)
1642
+ return;
1643
+ chat.status = status;
1644
+ chat.error = error;
1645
+ this.emit({ type: "chat-status-changed", chatId: id, error });
1646
+ }
1647
+ getError(id) {
1648
+ return this.getChat(id).error;
1649
+ }
1650
+ getMessages(id) {
1651
+ return this.getChat(id).messages;
1652
+ }
1653
+ getLastMessage(id) {
1654
+ const chat = this.getChat(id);
1655
+ return chat.messages[chat.messages.length - 1];
1656
+ }
1657
+ subscribe(subscriber) {
1658
+ this.subscribers.add(subscriber);
1659
+ return () => this.subscribers.delete(subscriber);
1660
+ }
1661
+ setMessages({
1662
+ id,
1663
+ messages
1664
+ }) {
1665
+ this.getChat(id).messages = [...messages];
1666
+ this.emit({ type: "chat-messages-changed", chatId: id });
1667
+ }
1668
+ removeAssistantResponse(id) {
1669
+ const chat = this.getChat(id);
1670
+ const lastMessage = chat.messages[chat.messages.length - 1];
1671
+ if (lastMessage == null) {
1672
+ throw new Error("Cannot remove assistant response from empty chat");
1673
+ }
1674
+ if (lastMessage.role !== "assistant") {
1675
+ throw new Error("Last message is not an assistant message");
1676
+ }
1677
+ this.setMessages({ id, messages: chat.messages.slice(0, -1) });
1678
+ }
1679
+ async submitMessage({
1680
+ chatId,
1681
+ message,
1682
+ headers,
1683
+ body,
1684
+ onError,
1685
+ onToolCall,
1686
+ onFinish
1687
+ }) {
1688
+ var _a17;
1689
+ const chat = this.getChat(chatId);
1690
+ const currentMessages = chat.messages;
1691
+ await this.triggerRequest({
1692
+ chatId,
1693
+ messages: currentMessages.concat({
1694
+ ...message,
1695
+ id: (_a17 = message.id) != null ? _a17 : this.generateId()
1696
+ }),
1697
+ headers,
1698
+ body,
1699
+ requestType: "generate",
1700
+ onError,
1701
+ onToolCall,
1702
+ onFinish
1703
+ });
1704
+ }
1705
+ async resubmitLastUserMessage({
1706
+ chatId,
1707
+ headers,
1708
+ body,
1709
+ onError,
1710
+ onToolCall,
1711
+ onFinish
1712
+ }) {
1713
+ const messages = this.getChat(chatId).messages;
1714
+ const messagesToSubmit = messages[messages.length - 1].role === "assistant" ? messages.slice(0, -1) : messages;
1715
+ if (messagesToSubmit.length === 0) {
1716
+ return;
1717
+ }
1718
+ return this.triggerRequest({
1719
+ chatId,
1720
+ requestType: "generate",
1721
+ messages: messagesToSubmit,
1722
+ headers,
1723
+ body,
1724
+ onError,
1725
+ onToolCall,
1726
+ onFinish
1727
+ });
1728
+ }
1729
+ async resumeStream({
1730
+ chatId,
1731
+ headers,
1732
+ body,
1733
+ onError,
1734
+ onToolCall,
1735
+ onFinish
1736
+ }) {
1737
+ const chat = this.getChat(chatId);
1738
+ const currentMessages = chat.messages;
1739
+ return this.triggerRequest({
1740
+ chatId,
1741
+ messages: currentMessages,
1742
+ requestType: "resume",
1743
+ headers,
1744
+ body,
1745
+ onError,
1746
+ onToolCall,
1747
+ onFinish
1748
+ });
1749
+ }
1750
+ async addToolResult({
1751
+ chatId,
1752
+ toolCallId,
1753
+ result
1754
+ }) {
1755
+ const chat = this.getChat(chatId);
1756
+ chat.jobExecutor.run(async () => {
1757
+ const currentMessages = chat.messages;
1758
+ updateToolCallResult({
1759
+ messages: currentMessages,
1760
+ toolCallId,
1761
+ toolResult: result
1762
+ });
1763
+ this.setMessages({ id: chatId, messages: currentMessages });
1764
+ if (chat.status === "submitted" || chat.status === "streaming") {
1765
+ return;
1766
+ }
1767
+ const lastMessage = currentMessages[currentMessages.length - 1];
1768
+ if (isAssistantMessageWithCompletedToolCalls(lastMessage)) {
1769
+ await this.triggerRequest({
1770
+ messages: currentMessages,
1771
+ requestType: "generate",
1772
+ chatId
1773
+ });
1774
+ }
1775
+ });
1776
+ }
1777
+ async stopStream({ chatId }) {
1778
+ var _a17;
1779
+ const chat = this.getChat(chatId);
1780
+ if (chat.status !== "streaming" && chat.status !== "submitted")
1781
+ return;
1782
+ if ((_a17 = chat.activeResponse) == null ? void 0 : _a17.abortController) {
1783
+ chat.activeResponse.abortController.abort();
1784
+ chat.activeResponse.abortController = void 0;
1785
+ }
1786
+ }
1787
+ emit(event) {
1788
+ for (const subscriber of this.subscribers) {
1789
+ subscriber.onChatChanged(event);
1790
+ }
1791
+ }
1792
+ getChat(id) {
1793
+ if (!this.hasChat(id)) {
1794
+ throw new Error(`chat '${id}' not found`);
1795
+ }
1796
+ return this.chats.get(id);
1797
+ }
1798
+ async triggerRequest({
1799
+ chatId,
1800
+ messages: chatMessages,
1801
+ requestType,
1802
+ headers,
1803
+ body,
1804
+ onError,
1805
+ onToolCall,
1806
+ onFinish
1807
+ }) {
1808
+ const self = this;
1809
+ const chat = this.getChat(chatId);
1810
+ this.setMessages({ id: chatId, messages: chatMessages });
1811
+ this.setStatus({ id: chatId, status: "submitted", error: void 0 });
1812
+ const messageCount = chatMessages.length;
1813
+ const maxStep = extractMaxToolInvocationStep(
1814
+ getToolInvocations(chatMessages[chatMessages.length - 1])
1815
+ );
1816
+ try {
1817
+ const activeResponse = {
1818
+ state: createStreamingUIMessageState({
1819
+ lastMessage: chatMessages[chatMessages.length - 1],
1820
+ newMessageId: self.generateId()
1821
+ }),
1822
+ abortController: new AbortController()
1823
+ };
1824
+ chat.activeResponse = activeResponse;
1825
+ const stream = await self.transport.submitMessages({
1826
+ chatId,
1827
+ messages: chatMessages,
1828
+ body,
1829
+ headers,
1830
+ abortController: activeResponse.abortController,
1831
+ requestType
1832
+ });
1833
+ const runUpdateMessageJob = (job) => (
1834
+ // serialize the job execution to avoid race conditions:
1835
+ chat.jobExecutor.run(
1836
+ () => job({
1837
+ state: activeResponse.state,
1838
+ write: () => {
1839
+ self.setStatus({ id: chatId, status: "streaming" });
1840
+ const replaceLastMessage = activeResponse.state.message.id === chatMessages[chatMessages.length - 1].id;
1841
+ const newMessages = [
1842
+ ...replaceLastMessage ? chatMessages.slice(0, chatMessages.length - 1) : chatMessages,
1843
+ activeResponse.state.message
1844
+ ];
1845
+ self.setMessages({
1846
+ id: chatId,
1847
+ messages: newMessages
1848
+ });
1849
+ }
1850
+ })
1851
+ )
1852
+ );
1313
1853
  await consumeStream({
1314
1854
  stream: processUIMessageStream({
1315
- stream: parseJsonEventStream({
1316
- stream: response.body,
1317
- schema: uiMessageStreamPartSchema
1318
- }).pipeThrough(
1319
- new TransformStream({
1320
- async transform(part, controller) {
1321
- if (!part.success) {
1322
- throw part.error;
1323
- }
1324
- controller.enqueue(part.value);
1325
- }
1326
- })
1327
- ),
1328
- onUpdate({ message }) {
1329
- const copiedMessage = {
1330
- // deep copy the message to ensure that deep changes (msg attachments) are updated
1331
- // with SolidJS. SolidJS uses referential integration of sub-objects to detect changes.
1332
- ...structuredClone(message),
1333
- // add a revision id to ensure that the message is updated with SWR. SWR uses a
1334
- // hashing approach by default to detect changes, but it only works for shallow
1335
- // changes. This is why we need to add a revision id to ensure that the message
1336
- // is updated with SWR (without it, the changes get stuck in SWR and are not
1337
- // forwarded to rendering):
1338
- revisionId: generateId3()
1339
- };
1340
- onUpdate({ message: copiedMessage });
1341
- },
1342
- lastMessage,
1855
+ stream,
1343
1856
  onToolCall,
1344
- onFinish,
1345
- newMessageId: generateId3(),
1346
- messageMetadataSchema
1857
+ messageMetadataSchema: self.messageMetadataSchema,
1858
+ runUpdateMessageJob
1347
1859
  }),
1348
1860
  onError: (error) => {
1349
1861
  throw error;
1350
1862
  }
1351
1863
  });
1352
- return;
1353
- }
1354
- default: {
1355
- const exhaustiveCheck = streamProtocol;
1356
- throw new Error(`Unknown stream protocol: ${exhaustiveCheck}`);
1864
+ onFinish == null ? void 0 : onFinish({ message: activeResponse.state.message });
1865
+ this.setStatus({ id: chatId, status: "ready" });
1866
+ } catch (err) {
1867
+ if (err.name === "AbortError") {
1868
+ this.setStatus({ id: chatId, status: "ready" });
1869
+ return null;
1870
+ }
1871
+ if (onError && err instanceof Error) {
1872
+ onError(err);
1873
+ }
1874
+ this.setStatus({ id: chatId, status: "error", error: err });
1875
+ } finally {
1876
+ chat.activeResponse = void 0;
1877
+ }
1878
+ const currentMessages = self.getMessages(chatId);
1879
+ if (shouldResubmitMessages({
1880
+ originalMaxToolInvocationStep: maxStep,
1881
+ originalMessageCount: messageCount,
1882
+ maxSteps: self.maxSteps,
1883
+ messages: currentMessages
1884
+ })) {
1885
+ await self.triggerRequest({
1886
+ chatId,
1887
+ requestType,
1888
+ onError,
1889
+ onToolCall,
1890
+ onFinish,
1891
+ headers,
1892
+ body,
1893
+ messages: currentMessages
1894
+ });
1357
1895
  }
1358
1896
  }
1359
- }
1897
+ };
1360
1898
 
1361
- // src/ui/call-completion-api.ts
1362
- import { parseJsonEventStream as parseJsonEventStream2 } from "@ai-sdk/provider-utils";
1363
- var getOriginalFetch2 = () => fetch;
1364
- async function callCompletionApi({
1365
- api,
1366
- prompt,
1367
- credentials,
1368
- headers,
1369
- body,
1370
- streamProtocol = "data",
1371
- setCompletion,
1372
- setLoading,
1373
- setError,
1374
- setAbortController,
1375
- onFinish,
1376
- onError,
1377
- fetch: fetch2 = getOriginalFetch2()
1378
- }) {
1379
- var _a17;
1380
- try {
1381
- setLoading(true);
1382
- setError(void 0);
1383
- const abortController = new AbortController();
1384
- setAbortController(abortController);
1385
- setCompletion("");
1386
- const response = await fetch2(api, {
1387
- method: "POST",
1388
- body: JSON.stringify({
1389
- prompt,
1390
- ...body
1391
- }),
1392
- credentials,
1899
+ // src/ui/chat-transport.ts
1900
+ var DefaultChatTransport = class {
1901
+ constructor({
1902
+ api,
1903
+ credentials,
1904
+ headers,
1905
+ body,
1906
+ streamProtocol,
1907
+ fetch: fetch2,
1908
+ prepareRequestBody
1909
+ }) {
1910
+ this.api = api;
1911
+ this.credentials = credentials;
1912
+ this.headers = headers;
1913
+ this.body = body;
1914
+ this.streamProtocol = streamProtocol;
1915
+ this.fetch = fetch2;
1916
+ this.prepareRequestBody = prepareRequestBody;
1917
+ }
1918
+ submitMessages({
1919
+ chatId,
1920
+ messages,
1921
+ abortController,
1922
+ body,
1923
+ headers,
1924
+ requestType
1925
+ }) {
1926
+ var _a17, _b;
1927
+ return fetchUIMessageStream({
1928
+ api: this.api,
1393
1929
  headers: {
1394
- "Content-Type": "application/json",
1930
+ ...this.headers,
1395
1931
  ...headers
1396
1932
  },
1397
- signal: abortController.signal
1398
- }).catch((err) => {
1399
- throw err;
1933
+ body: (_b = (_a17 = this.prepareRequestBody) == null ? void 0 : _a17.call(this, {
1934
+ id: chatId,
1935
+ // TODO change to chatId
1936
+ messages,
1937
+ ...this.body,
1938
+ ...body
1939
+ })) != null ? _b : {
1940
+ id: chatId,
1941
+ // TODO change to chatId
1942
+ messages,
1943
+ ...this.body,
1944
+ ...body
1945
+ },
1946
+ streamProtocol: this.streamProtocol,
1947
+ credentials: this.credentials,
1948
+ abortController: () => abortController,
1949
+ fetch: this.fetch,
1950
+ requestType
1400
1951
  });
1401
- if (!response.ok) {
1402
- throw new Error(
1403
- (_a17 = await response.text()) != null ? _a17 : "Failed to fetch the chat response."
1404
- );
1405
- }
1406
- if (!response.body) {
1407
- throw new Error("The response body is empty.");
1408
- }
1409
- let result = "";
1410
- switch (streamProtocol) {
1411
- case "text": {
1412
- await processTextStream({
1413
- stream: response.body,
1414
- onTextPart: (chunk) => {
1415
- result += chunk;
1416
- setCompletion(result);
1417
- }
1418
- });
1419
- break;
1420
- }
1421
- case "data": {
1422
- await consumeStream({
1423
- stream: parseJsonEventStream2({
1424
- stream: response.body,
1425
- schema: uiMessageStreamPartSchema
1426
- }).pipeThrough(
1427
- new TransformStream({
1428
- async transform(part) {
1429
- if (!part.success) {
1430
- throw part.error;
1431
- }
1432
- const { type, value } = part.value;
1433
- if (type === "text") {
1434
- result += value;
1435
- setCompletion(result);
1436
- } else if (type === "error") {
1437
- throw new Error(value);
1438
- }
1439
- }
1440
- })
1441
- ),
1442
- onError: (error) => {
1443
- throw error;
1444
- }
1445
- });
1446
- break;
1447
- }
1448
- default: {
1449
- const exhaustiveCheck = streamProtocol;
1450
- throw new Error(`Unknown stream protocol: ${exhaustiveCheck}`);
1451
- }
1452
- }
1453
- if (onFinish) {
1454
- onFinish(prompt, result);
1455
- }
1456
- setAbortController(null);
1457
- return result;
1458
- } catch (err) {
1459
- if (err.name === "AbortError") {
1460
- setAbortController(null);
1461
- return null;
1462
- }
1463
- if (err instanceof Error) {
1464
- if (onError) {
1465
- onError(err);
1466
- }
1467
- }
1468
- setError(err);
1469
- } finally {
1470
- setLoading(false);
1471
1952
  }
1472
- }
1953
+ };
1473
1954
 
1474
1955
  // src/ui/convert-file-list-to-file-ui-parts.ts
1475
1956
  async function convertFileListToFileUIParts(files) {
@@ -1657,53 +2138,38 @@ function convertToModelMessages(messages, options) {
1657
2138
  }
1658
2139
  var convertToCoreMessages = convertToModelMessages;
1659
2140
 
1660
- // src/ui/should-resubmit-messages.ts
1661
- function shouldResubmitMessages({
1662
- originalMaxToolInvocationStep,
1663
- originalMessageCount,
1664
- maxSteps,
1665
- messages
1666
- }) {
1667
- var _a17;
1668
- const lastMessage = messages[messages.length - 1];
1669
- return (
1670
- // check if the feature is enabled:
1671
- maxSteps > 1 && // ensure there is a last message:
1672
- lastMessage != null && // ensure we actually have new steps (to prevent infinite loops in case of errors):
1673
- (messages.length > originalMessageCount || extractMaxToolInvocationStep(getToolInvocations(lastMessage)) !== originalMaxToolInvocationStep) && // check that next step is possible:
1674
- isAssistantMessageWithCompletedToolCalls(lastMessage) && // limit the number of automatic steps:
1675
- ((_a17 = extractMaxToolInvocationStep(getToolInvocations(lastMessage))) != null ? _a17 : 0) < maxSteps
1676
- );
1677
- }
1678
- function isAssistantMessageWithCompletedToolCalls(message) {
1679
- if (message.role !== "assistant") {
1680
- return false;
1681
- }
1682
- const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => {
1683
- return part.type === "step-start" ? index : lastIndex;
1684
- }, -1);
1685
- const lastStepToolInvocations = message.parts.slice(lastStepStartIndex + 1).filter((part) => part.type === "tool-invocation");
1686
- return lastStepToolInvocations.length > 0 && lastStepToolInvocations.every((part) => "result" in part.toolInvocation);
1687
- }
1688
-
1689
- // src/ui/update-tool-call-result.ts
1690
- function updateToolCallResult({
1691
- messages,
1692
- toolCallId,
1693
- toolResult: result
2141
+ // src/ui/default-chat-store.ts
2142
+ import {
2143
+ generateId as generateIdFunc2
2144
+ } from "@ai-sdk/provider-utils";
2145
+ function defaultChatStore({
2146
+ api,
2147
+ fetch: fetch2,
2148
+ streamProtocol = "ui-message",
2149
+ credentials,
2150
+ headers,
2151
+ body,
2152
+ prepareRequestBody,
2153
+ generateId: generateId3 = generateIdFunc2,
2154
+ messageMetadataSchema,
2155
+ maxSteps: maxSteps2 = 1,
2156
+ chats
1694
2157
  }) {
1695
- const lastMessage = messages[messages.length - 1];
1696
- const invocationPart = lastMessage.parts.find(
1697
- (part) => part.type === "tool-invocation" && part.toolInvocation.toolCallId === toolCallId
1698
- );
1699
- if (invocationPart == null) {
1700
- return;
1701
- }
1702
- invocationPart.toolInvocation = {
1703
- ...invocationPart.toolInvocation,
1704
- state: "result",
1705
- result
1706
- };
2158
+ return new ChatStore({
2159
+ transport: new DefaultChatTransport({
2160
+ api,
2161
+ fetch: fetch2,
2162
+ streamProtocol,
2163
+ credentials,
2164
+ headers,
2165
+ body,
2166
+ prepareRequestBody
2167
+ }),
2168
+ generateId: generateId3,
2169
+ messageMetadataSchema,
2170
+ maxSteps: maxSteps2,
2171
+ chats
2172
+ });
1707
2173
  }
1708
2174
 
1709
2175
  // src/ui-message-stream/create-ui-message-stream.ts
@@ -1741,7 +2207,7 @@ function createUIMessageStream({
1741
2207
  safeEnqueue(value);
1742
2208
  }
1743
2209
  })().catch((error) => {
1744
- safeEnqueue({ type: "error", value: onError(error) });
2210
+ safeEnqueue({ type: "error", errorText: onError(error) });
1745
2211
  })
1746
2212
  );
1747
2213
  },
@@ -1750,12 +2216,12 @@ function createUIMessageStream({
1750
2216
  if (result) {
1751
2217
  ongoingStreamPromises.push(
1752
2218
  result.catch((error) => {
1753
- safeEnqueue({ type: "error", value: onError(error) });
2219
+ safeEnqueue({ type: "error", errorText: onError(error) });
1754
2220
  })
1755
2221
  );
1756
2222
  }
1757
2223
  } catch (error) {
1758
- safeEnqueue({ type: "error", value: onError(error) });
2224
+ safeEnqueue({ type: "error", errorText: onError(error) });
1759
2225
  }
1760
2226
  const waitForStreams = new Promise(async (resolve) => {
1761
2227
  while (ongoingStreamPromises.length > 0) {
@@ -3411,7 +3877,7 @@ async function standardizePrompt(prompt) {
3411
3877
  if (!validationResult.success) {
3412
3878
  throw new InvalidPromptError2({
3413
3879
  prompt,
3414
- message: "messages must be an array of ModelMessage",
3880
+ message: "The messages must be a ModelMessage[]. If you have passed a UIMessage[], you can use convertToModelMessages to convert them.",
3415
3881
  cause: validationResult.error
3416
3882
  });
3417
3883
  }
@@ -5056,6 +5522,19 @@ var DefaultStepResult = class {
5056
5522
  }
5057
5523
  };
5058
5524
 
5525
+ // core/generate-text/stop-condition.ts
5526
+ function maxSteps(maxSteps2) {
5527
+ return ({ steps }) => steps.length >= maxSteps2;
5528
+ }
5529
+ function hasToolCall(toolName) {
5530
+ return ({ steps }) => {
5531
+ var _a17, _b, _c;
5532
+ return (_c = (_b = (_a17 = steps[steps.length - 1]) == null ? void 0 : _a17.toolCalls) == null ? void 0 : _b.some(
5533
+ (toolCall) => toolCall.toolName === toolName
5534
+ )) != null ? _c : false;
5535
+ };
5536
+ }
5537
+
5059
5538
  // core/generate-text/to-response-messages.ts
5060
5539
  function toResponseMessages({
5061
5540
  content: inputContent,
@@ -5129,7 +5608,7 @@ async function generateText({
5129
5608
  maxRetries: maxRetriesArg,
5130
5609
  abortSignal,
5131
5610
  headers,
5132
- maxSteps = 1,
5611
+ continueUntil = maxSteps(1),
5133
5612
  experimental_output: output,
5134
5613
  experimental_telemetry: telemetry,
5135
5614
  providerOptions,
@@ -5143,13 +5622,6 @@ async function generateText({
5143
5622
  onStepFinish,
5144
5623
  ...settings
5145
5624
  }) {
5146
- if (maxSteps < 1) {
5147
- throw new InvalidArgumentError({
5148
- parameter: "maxSteps",
5149
- value: maxSteps,
5150
- message: "maxSteps must be at least 1"
5151
- });
5152
- }
5153
5625
  const { maxRetries, retry } = prepareRetries({ maxRetries: maxRetriesArg });
5154
5626
  const callSettings = prepareCallSettings(settings);
5155
5627
  const baseTelemetryAttributes = getBaseTelemetryAttributes({
@@ -5180,8 +5652,7 @@ async function generateText({
5180
5652
  // specific settings that only make sense on the outer level:
5181
5653
  "ai.prompt": {
5182
5654
  input: () => JSON.stringify({ system, prompt, messages })
5183
- },
5184
- "ai.settings.maxSteps": maxSteps
5655
+ }
5185
5656
  }
5186
5657
  }),
5187
5658
  tracer,
@@ -5191,7 +5662,6 @@ async function generateText({
5191
5662
  let currentModelResponse;
5192
5663
  let currentToolCalls = [];
5193
5664
  let currentToolResults = [];
5194
- let stepCount = 0;
5195
5665
  const responseMessages = [];
5196
5666
  const steps = [];
5197
5667
  do {
@@ -5202,8 +5672,7 @@ async function generateText({
5202
5672
  const prepareStepResult = await (prepareStep == null ? void 0 : prepareStep({
5203
5673
  model,
5204
5674
  steps,
5205
- maxSteps,
5206
- stepNumber: stepCount
5675
+ stepNumber: steps.length
5207
5676
  }));
5208
5677
  const promptMessages = await convertToLanguageModelPrompt({
5209
5678
  prompt: {
@@ -5358,9 +5827,12 @@ async function generateText({
5358
5827
  });
5359
5828
  steps.push(currentStepResult);
5360
5829
  await (onStepFinish == null ? void 0 : onStepFinish(currentStepResult));
5361
- } while (++stepCount < maxSteps && // there are tool calls:
5362
- currentToolCalls.length > 0 && // all current tool calls have results:
5363
- currentToolResults.length === currentToolCalls.length);
5830
+ } while (
5831
+ // there are tool calls:
5832
+ currentToolCalls.length > 0 && // all current tool calls have results:
5833
+ currentToolResults.length === currentToolCalls.length && // continue until the stop condition is met:
5834
+ !await continueUntil({ steps })
5835
+ );
5364
5836
  span.setAttributes(
5365
5837
  selectTelemetryAttributes({
5366
5838
  telemetry,
@@ -5924,7 +6396,7 @@ function streamText({
5924
6396
  maxRetries,
5925
6397
  abortSignal,
5926
6398
  headers,
5927
- maxSteps = 1,
6399
+ maxSteps: maxSteps2 = 1,
5928
6400
  experimental_output: output,
5929
6401
  experimental_telemetry: telemetry,
5930
6402
  providerOptions,
@@ -5960,7 +6432,7 @@ function streamText({
5960
6432
  transforms: asArray(transform),
5961
6433
  activeTools,
5962
6434
  repairToolCall,
5963
- maxSteps,
6435
+ maxSteps: maxSteps2,
5964
6436
  output,
5965
6437
  providerOptions,
5966
6438
  onChunk,
@@ -6037,7 +6509,7 @@ var DefaultStreamTextResult = class {
6037
6509
  transforms,
6038
6510
  activeTools,
6039
6511
  repairToolCall,
6040
- maxSteps,
6512
+ maxSteps: maxSteps2,
6041
6513
  output,
6042
6514
  providerOptions,
6043
6515
  now: now2,
@@ -6051,10 +6523,10 @@ var DefaultStreamTextResult = class {
6051
6523
  this.totalUsagePromise = new DelayedPromise();
6052
6524
  this.finishReasonPromise = new DelayedPromise();
6053
6525
  this.stepsPromise = new DelayedPromise();
6054
- if (maxSteps < 1) {
6526
+ if (maxSteps2 < 1) {
6055
6527
  throw new InvalidArgumentError({
6056
6528
  parameter: "maxSteps",
6057
- value: maxSteps,
6529
+ value: maxSteps2,
6058
6530
  message: "maxSteps must be at least 1"
6059
6531
  });
6060
6532
  }
@@ -6211,6 +6683,13 @@ var DefaultStreamTextResult = class {
6211
6683
  this.addStream = stitchableStream.addStream;
6212
6684
  this.closeStream = stitchableStream.close;
6213
6685
  let stream = stitchableStream.stream;
6686
+ stream = stream.pipeThrough(
6687
+ new TransformStream({
6688
+ start(controller) {
6689
+ controller.enqueue({ type: "start" });
6690
+ }
6691
+ })
6692
+ );
6214
6693
  for (const transform of transforms) {
6215
6694
  stream = stream.pipeThrough(
6216
6695
  transform({
@@ -6245,7 +6724,7 @@ var DefaultStreamTextResult = class {
6245
6724
  "ai.prompt": {
6246
6725
  input: () => JSON.stringify({ system, prompt, messages })
6247
6726
  },
6248
- "ai.settings.maxSteps": maxSteps
6727
+ "ai.settings.maxSteps": maxSteps2
6249
6728
  }
6250
6729
  }),
6251
6730
  tracer,
@@ -6383,7 +6862,6 @@ var DefaultStreamTextResult = class {
6383
6862
  var _a17, _b, _c, _d;
6384
6863
  if (chunk.type === "stream-start") {
6385
6864
  warnings = chunk.warnings;
6386
- controller.enqueue({ type: "start" });
6387
6865
  return;
6388
6866
  }
6389
6867
  if (stepFirstChunk) {
@@ -6533,7 +7011,7 @@ var DefaultStreamTextResult = class {
6533
7011
  }
6534
7012
  });
6535
7013
  const combinedUsage = addLanguageModelUsage(usage, stepUsage);
6536
- if (currentStep + 1 < maxSteps && // there are tool calls:
7014
+ if (currentStep + 1 < maxSteps2 && // there are tool calls:
6537
7015
  stepToolCalls.length > 0 && // all current tool calls have results:
6538
7016
  stepToolResults.length === stepToolCalls.length) {
6539
7017
  responseMessages.push(
@@ -6718,125 +7196,122 @@ var DefaultStreamTextResult = class {
6718
7196
  const partType = part.type;
6719
7197
  switch (partType) {
6720
7198
  case "text": {
6721
- controller.enqueue({ type: "text", value: part.text });
7199
+ controller.enqueue({
7200
+ type: "text",
7201
+ text: part.text
7202
+ });
6722
7203
  break;
6723
7204
  }
6724
7205
  case "reasoning": {
6725
7206
  if (sendReasoning) {
6726
- controller.enqueue({ type: "reasoning", value: part });
7207
+ controller.enqueue({
7208
+ type: "reasoning",
7209
+ text: part.text,
7210
+ providerMetadata: part.providerMetadata
7211
+ });
6727
7212
  }
6728
7213
  break;
6729
7214
  }
6730
7215
  case "reasoning-part-finish": {
6731
7216
  if (sendReasoning) {
6732
- controller.enqueue({
6733
- type: "reasoning-part-finish",
6734
- value: null
6735
- });
7217
+ controller.enqueue({ type: "reasoning-part-finish" });
6736
7218
  }
6737
7219
  break;
6738
7220
  }
6739
7221
  case "file": {
6740
7222
  controller.enqueue({
6741
7223
  type: "file",
6742
- value: {
6743
- mediaType: part.file.mediaType,
6744
- url: `data:${part.file.mediaType};base64,${part.file.base64}`
6745
- }
7224
+ mediaType: part.file.mediaType,
7225
+ url: `data:${part.file.mediaType};base64,${part.file.base64}`
6746
7226
  });
6747
7227
  break;
6748
7228
  }
6749
7229
  case "source": {
6750
7230
  if (sendSources) {
6751
- controller.enqueue({ type: "source", value: part });
7231
+ controller.enqueue({
7232
+ type: "source",
7233
+ sourceType: part.sourceType,
7234
+ id: part.id,
7235
+ url: part.url,
7236
+ title: part.title,
7237
+ providerMetadata: part.providerMetadata
7238
+ });
6752
7239
  }
6753
7240
  break;
6754
7241
  }
6755
7242
  case "tool-call-streaming-start": {
6756
7243
  controller.enqueue({
6757
7244
  type: "tool-call-streaming-start",
6758
- value: {
6759
- toolCallId: part.toolCallId,
6760
- toolName: part.toolName
6761
- }
7245
+ toolCallId: part.toolCallId,
7246
+ toolName: part.toolName
6762
7247
  });
6763
7248
  break;
6764
7249
  }
6765
7250
  case "tool-call-delta": {
6766
7251
  controller.enqueue({
6767
7252
  type: "tool-call-delta",
6768
- value: {
6769
- toolCallId: part.toolCallId,
6770
- argsTextDelta: part.argsTextDelta
6771
- }
7253
+ toolCallId: part.toolCallId,
7254
+ argsTextDelta: part.argsTextDelta
6772
7255
  });
6773
7256
  break;
6774
7257
  }
6775
7258
  case "tool-call": {
6776
7259
  controller.enqueue({
6777
7260
  type: "tool-call",
6778
- value: {
6779
- toolCallId: part.toolCallId,
6780
- toolName: part.toolName,
6781
- args: part.args
6782
- }
7261
+ toolCallId: part.toolCallId,
7262
+ toolName: part.toolName,
7263
+ args: part.args
6783
7264
  });
6784
7265
  break;
6785
7266
  }
6786
7267
  case "tool-result": {
6787
7268
  controller.enqueue({
6788
7269
  type: "tool-result",
6789
- value: {
6790
- toolCallId: part.toolCallId,
6791
- result: part.result
6792
- }
7270
+ toolCallId: part.toolCallId,
7271
+ result: part.result
6793
7272
  });
6794
7273
  break;
6795
7274
  }
6796
7275
  case "error": {
6797
7276
  controller.enqueue({
6798
7277
  type: "error",
6799
- value: onError(part.error)
7278
+ errorText: onError(part.error)
6800
7279
  });
6801
7280
  break;
6802
7281
  }
6803
7282
  case "start-step": {
7283
+ const metadata = messageMetadata == null ? void 0 : messageMetadata({ part });
6804
7284
  controller.enqueue({
6805
7285
  type: "start-step",
6806
- value: {
6807
- metadata: messageMetadata == null ? void 0 : messageMetadata({ part })
6808
- }
7286
+ metadata
6809
7287
  });
6810
7288
  break;
6811
7289
  }
6812
7290
  case "finish-step": {
7291
+ const metadata = messageMetadata == null ? void 0 : messageMetadata({ part });
6813
7292
  controller.enqueue({
6814
7293
  type: "finish-step",
6815
- value: {
6816
- metadata: messageMetadata == null ? void 0 : messageMetadata({ part })
6817
- }
7294
+ metadata
6818
7295
  });
6819
7296
  break;
6820
7297
  }
6821
7298
  case "start": {
6822
7299
  if (experimental_sendStart) {
7300
+ const metadata = messageMetadata == null ? void 0 : messageMetadata({ part });
6823
7301
  controller.enqueue({
6824
7302
  type: "start",
6825
- value: {
6826
- messageId,
6827
- metadata: messageMetadata == null ? void 0 : messageMetadata({ part })
6828
- }
7303
+ messageId,
7304
+ metadata
6829
7305
  });
6830
7306
  }
6831
7307
  break;
6832
7308
  }
6833
7309
  case "finish": {
6834
7310
  if (experimental_sendFinish) {
7311
+ const metadata = messageMetadata == null ? void 0 : messageMetadata({ part });
6835
7312
  controller.enqueue({
6836
7313
  type: "finish",
6837
- value: {
6838
- metadata: messageMetadata == null ? void 0 : messageMetadata({ part })
6839
- }
7314
+ metadata
6840
7315
  });
6841
7316
  }
6842
7317
  break;
@@ -6849,22 +7324,38 @@ var DefaultStreamTextResult = class {
6849
7324
  }
6850
7325
  })
6851
7326
  );
6852
- return onFinish == null ? baseStream : processUIMessageStream({
6853
- stream: baseStream,
7327
+ if (onFinish == null) {
7328
+ return baseStream;
7329
+ }
7330
+ const state = createStreamingUIMessageState({
6854
7331
  lastMessage,
6855
- newMessageId: messageId != null ? messageId : this.generateId(),
6856
- onFinish: ({ message }) => {
6857
- const isContinuation2 = message.id === (lastMessage == null ? void 0 : lastMessage.id);
6858
- onFinish({
6859
- isContinuation: isContinuation2,
6860
- responseMessage: message,
6861
- messages: [
6862
- ...isContinuation2 ? originalMessages.slice(0, -1) : originalMessages,
6863
- message
6864
- ]
6865
- });
6866
- }
7332
+ newMessageId: messageId != null ? messageId : this.generateId()
6867
7333
  });
7334
+ const runUpdateMessageJob = async (job) => {
7335
+ await job({ state, write: () => {
7336
+ } });
7337
+ };
7338
+ return processUIMessageStream({
7339
+ stream: baseStream,
7340
+ runUpdateMessageJob
7341
+ }).pipeThrough(
7342
+ new TransformStream({
7343
+ transform(chunk, controller) {
7344
+ controller.enqueue(chunk);
7345
+ },
7346
+ flush() {
7347
+ const isContinuation2 = state.message.id === (lastMessage == null ? void 0 : lastMessage.id);
7348
+ onFinish({
7349
+ isContinuation: isContinuation2,
7350
+ responseMessage: state.message,
7351
+ messages: [
7352
+ ...isContinuation2 ? originalMessages.slice(0, -1) : originalMessages,
7353
+ state.message
7354
+ ]
7355
+ });
7356
+ }
7357
+ })
7358
+ );
6868
7359
  }
6869
7360
  pipeUIMessageStreamToResponse(response, {
6870
7361
  newMessageId,
@@ -7944,6 +8435,8 @@ var DefaultTranscriptionResult = class {
7944
8435
  export {
7945
8436
  AISDKError16 as AISDKError,
7946
8437
  APICallError,
8438
+ ChatStore,
8439
+ DefaultChatTransport,
7947
8440
  DownloadError,
7948
8441
  EmptyResponseBodyError,
7949
8442
  InvalidArgumentError,
@@ -7991,6 +8484,7 @@ export {
7991
8484
  createUIMessageStream,
7992
8485
  createUIMessageStreamResponse,
7993
8486
  customProvider,
8487
+ defaultChatStore,
7994
8488
  defaultSettingsMiddleware,
7995
8489
  embed,
7996
8490
  embedMany,
@@ -8007,14 +8501,15 @@ export {
8007
8501
  generateText,
8008
8502
  getTextFromDataUrl,
8009
8503
  getToolInvocations,
8504
+ hasToolCall,
8010
8505
  isAssistantMessageWithCompletedToolCalls,
8011
8506
  isDeepEqualData,
8012
8507
  jsonSchema2 as jsonSchema,
8508
+ maxSteps,
8013
8509
  modelMessageSchema,
8014
8510
  parsePartialJson,
8015
8511
  pipeTextStreamToResponse,
8016
8512
  pipeUIMessageStreamToResponse,
8017
- processTextStream,
8018
8513
  shouldResubmitMessages,
8019
8514
  simulateReadableStream,
8020
8515
  simulateStreamingMiddleware,