@mastra/react 0.4.3 → 0.5.0-alpha.0

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 (49) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/dist/agent/extractRunIdFromMessages.d.ts +9 -2
  3. package/dist/agent/extractRunIdFromMessages.d.ts.map +1 -1
  4. package/dist/agent/hooks.d.ts +9 -11
  5. package/dist/agent/hooks.d.ts.map +1 -1
  6. package/dist/agent/types.d.ts +5 -1
  7. package/dist/agent/types.d.ts.map +1 -1
  8. package/dist/index.cjs +1342 -1476
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.ts +2 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +1342 -1476
  13. package/dist/index.js.map +1 -1
  14. package/dist/lib/mastra-db/accumulator.d.ts +48 -0
  15. package/dist/lib/mastra-db/accumulator.d.ts.map +1 -0
  16. package/dist/lib/mastra-db/formatCompletionFeedback.d.ts.map +1 -0
  17. package/dist/lib/mastra-db/fromCoreUserMessage.d.ts +11 -0
  18. package/dist/lib/mastra-db/fromCoreUserMessage.d.ts.map +1 -0
  19. package/dist/lib/mastra-db/index.d.ts +5 -0
  20. package/dist/lib/mastra-db/index.d.ts.map +1 -0
  21. package/dist/lib/mastra-db/types.d.ts +156 -0
  22. package/dist/lib/mastra-db/types.d.ts.map +1 -0
  23. package/dist/ui/MessageFactory/MessageFactory.d.ts +22 -0
  24. package/dist/ui/MessageFactory/MessageFactory.d.ts.map +1 -0
  25. package/dist/ui/MessageFactory/index.d.ts +3 -0
  26. package/dist/ui/MessageFactory/index.d.ts.map +1 -0
  27. package/dist/ui/MessageFactory/types.d.ts +164 -0
  28. package/dist/ui/MessageFactory/types.d.ts.map +1 -0
  29. package/dist/ui/index.d.ts +1 -0
  30. package/dist/ui/index.d.ts.map +1 -1
  31. package/package.json +5 -9
  32. package/dist/lib/ai-sdk/index.d.ts +0 -5
  33. package/dist/lib/ai-sdk/index.d.ts.map +0 -1
  34. package/dist/lib/ai-sdk/memory/resolveInitialMessages.d.ts +0 -13
  35. package/dist/lib/ai-sdk/memory/resolveInitialMessages.d.ts.map +0 -1
  36. package/dist/lib/ai-sdk/transformers/AISdkNetworkTransformer.d.ts +0 -11
  37. package/dist/lib/ai-sdk/transformers/AISdkNetworkTransformer.d.ts.map +0 -1
  38. package/dist/lib/ai-sdk/transformers/types.d.ts +0 -11
  39. package/dist/lib/ai-sdk/transformers/types.d.ts.map +0 -1
  40. package/dist/lib/ai-sdk/types.d.ts +0 -145
  41. package/dist/lib/ai-sdk/types.d.ts.map +0 -1
  42. package/dist/lib/ai-sdk/utils/formatCompletionFeedback.d.ts.map +0 -1
  43. package/dist/lib/ai-sdk/utils/fromCoreUserMessageToUIMessage.d.ts +0 -11
  44. package/dist/lib/ai-sdk/utils/fromCoreUserMessageToUIMessage.d.ts.map +0 -1
  45. package/dist/lib/ai-sdk/utils/toAssistantUIMessage.d.ts +0 -15
  46. package/dist/lib/ai-sdk/utils/toAssistantUIMessage.d.ts.map +0 -1
  47. package/dist/lib/ai-sdk/utils/toUIMessage.d.ts +0 -20
  48. package/dist/lib/ai-sdk/utils/toUIMessage.d.ts.map +0 -1
  49. /package/dist/lib/{ai-sdk/utils → mastra-db}/formatCompletionFeedback.d.ts +0 -0
package/dist/index.cjs CHANGED
@@ -4,6 +4,7 @@ var clientJs = require('@mastra/client-js');
4
4
  var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var uuid = require('@lukeed/uuid');
7
+ var messageList = require('@mastra/core/agent/message-list');
7
8
  var lucideReact = require('lucide-react');
8
9
  var tailwindMerge = require('tailwind-merge');
9
10
  var reactTooltip = require('@radix-ui/react-tooltip');
@@ -69,7 +70,7 @@ var MastraReactProvider = ({
69
70
  );
70
71
  };
71
72
 
72
- // src/lib/ai-sdk/utils/formatCompletionFeedback.ts
73
+ // src/lib/mastra-db/formatCompletionFeedback.ts
73
74
  var formatBaseCompletionFeedback = (result, maxIterationReached, formatScorerHeading, incompleteMessage) => {
74
75
  const lines = [];
75
76
  lines.push("#### Completion Check Results");
@@ -114,29 +115,106 @@ var formatStreamCompletionFeedback = (result, maxIterationReached) => {
114
115
  );
115
116
  };
116
117
 
117
- // src/lib/ai-sdk/utils/toUIMessage.ts
118
- var markStreamingPartsDone = (message) => ({
118
+ // src/lib/mastra-db/accumulator.ts
119
+ var cloneMetadata = (metadata) => metadata ? { ...metadata } : {};
120
+ var withParts = (message, parts) => ({
119
121
  ...message,
120
- parts: message.parts.map((part) => {
121
- if (typeof part === "object" && part !== null && "type" in part && "state" in part && part.state === "streaming" && (part.type === "text" || part.type === "reasoning")) {
122
- return { ...part, state: "done" };
123
- }
124
- return part;
125
- })
122
+ content: {
123
+ ...message.content,
124
+ parts
125
+ }
126
+ });
127
+ var withMetadata = (message, metadata) => ({
128
+ ...message,
129
+ content: {
130
+ ...message.content,
131
+ metadata
132
+ }
126
133
  });
134
+ var replaceLast = (conversation, message) => [
135
+ ...conversation.slice(0, -1),
136
+ message
137
+ ];
138
+ var replaceAt = (conversation, index, message) => [
139
+ ...conversation.slice(0, index),
140
+ message,
141
+ ...conversation.slice(index + 1)
142
+ ];
143
+ var newAssistantMessage = (id, parts, metadata) => ({
144
+ id,
145
+ role: "assistant",
146
+ createdAt: /* @__PURE__ */ new Date(),
147
+ content: {
148
+ format: 2,
149
+ parts,
150
+ metadata: cloneMetadata(metadata)
151
+ }
152
+ });
153
+ var appendAssistantMessage = (conversation, id, parts, metadata) => [...conversation, newAssistantMessage(id, parts, metadata)];
154
+ var isToolPart = (part) => part.type === "tool-invocation";
155
+ var partTextId = (part) => part.type === "text" ? part.textId : void 0;
156
+ var partState = (part) => part.state;
127
157
  var finishStreamingAssistantMessage = (conversation) => {
128
158
  const lastMessage = conversation[conversation.length - 1];
129
159
  if (!lastMessage || lastMessage.role !== "assistant") return conversation;
130
- return [...conversation.slice(0, -1), markStreamingPartsDone(lastMessage)];
160
+ const nextParts = lastMessage.content.parts.map((part) => {
161
+ if ((part.type === "text" || part.type === "reasoning") && partState(part) === "streaming") {
162
+ return {
163
+ ...part,
164
+ state: "done"
165
+ };
166
+ }
167
+ return part;
168
+ });
169
+ return replaceLast(conversation, withParts(lastMessage, nextParts));
131
170
  };
132
- var appendAssistantMessage = (conversation, message, metadata) => [
133
- ...conversation,
134
- {
135
- ...message,
136
- role: "assistant",
137
- metadata
171
+ var locateToolPart = (messages, toolCallId, allowMetadataOnlyMatch) => {
172
+ const findIndex = (parts) => parts.findIndex((part) => isToolPart(part) && part.toolInvocation.toolCallId === toolCallId);
173
+ const lastMessage = messages[messages.length - 1];
174
+ if (lastMessage && lastMessage.role === "assistant") {
175
+ const idx = findIndex(lastMessage.content.parts);
176
+ if (idx !== -1) return { messageIndex: messages.length - 1, toolPartIndex: idx };
138
177
  }
139
- ];
178
+ let count = 0;
179
+ const maxMessagesBack = 10;
180
+ for (let i = messages.length - 1; i >= 0; i--) {
181
+ if (count > maxMessagesBack) break;
182
+ const message = messages[i];
183
+ if (message.role !== "assistant") continue;
184
+ const idx = findIndex(message.content.parts);
185
+ if (idx !== -1) return { messageIndex: i, toolPartIndex: idx };
186
+ count++;
187
+ }
188
+ if (!allowMetadataOnlyMatch) return null;
189
+ for (let i = messages.length - 1; i >= 0; i--) {
190
+ if (messages[i].role === "assistant") return { messageIndex: i, toolPartIndex: -1 };
191
+ }
192
+ return null;
193
+ };
194
+ var mergeBgTaskMetadata = (existing, mode, args, otherMetadata) => {
195
+ const base = cloneMetadata(existing);
196
+ const existingBgTasks = base.backgroundTasks ?? {};
197
+ const nextBgTasks = { ...existingBgTasks };
198
+ if (args.perTaskEntry) {
199
+ const { toolCallId, startedAt, completedAt, taskId, suspendedAt } = args.perTaskEntry;
200
+ const prev = existingBgTasks[toolCallId] ?? { taskId };
201
+ nextBgTasks[toolCallId] = {
202
+ ...prev,
203
+ taskId,
204
+ ...startedAt !== void 0 ? { startedAt } : {},
205
+ ...completedAt !== void 0 ? { completedAt } : {},
206
+ ...suspendedAt !== void 0 ? { suspendedAt } : {}
207
+ };
208
+ }
209
+ const merged = {
210
+ ...base,
211
+ ...otherMetadata ?? {},
212
+ mode,
213
+ backgroundTasks: nextBgTasks
214
+ };
215
+ if (args.resetRunningCount) merged.runningBackgroundTasksCount = void 0;
216
+ return merged;
217
+ };
140
218
  var mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
141
219
  if (chunk.type === "workflow-start") {
142
220
  return {
@@ -146,10 +224,7 @@ var mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
146
224
  };
147
225
  }
148
226
  if (chunk.type === "workflow-canceled") {
149
- return {
150
- ...prev,
151
- status: "canceled"
152
- };
227
+ return { ...prev, status: "canceled" };
153
228
  }
154
229
  if (chunk.type === "workflow-finish") {
155
230
  const finalStatus = chunk.payload.workflowStatus;
@@ -161,7 +236,7 @@ var mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
161
236
  ...finalStatus === "success" && lastStep?.status === "success" ? { result: lastStep?.output } : finalStatus === "failed" && lastStep?.status === "failed" ? { error: lastStep?.error } : finalStatus === "tripwire" && chunk.payload.tripwire ? { tripwire: chunk.payload.tripwire } : {}
162
237
  };
163
238
  }
164
- const { stepCallId, stepName, ...newPayload } = chunk.payload ?? {};
239
+ const { stepCallId: _stepCallId, stepName: _stepName, ...newPayload } = chunk.payload ?? {};
165
240
  const newSteps = {
166
241
  ...prev?.steps,
167
242
  [chunk.payload.id]: {
@@ -169,12 +244,7 @@ var mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
169
244
  ...newPayload
170
245
  }
171
246
  };
172
- if (chunk.type === "workflow-step-start") {
173
- return {
174
- ...prev,
175
- steps: newSteps
176
- };
177
- }
247
+ if (chunk.type === "workflow-step-start") return { ...prev, steps: newSteps };
178
248
  if (chunk.type === "workflow-step-suspended") {
179
249
  const suspendedStepIds = Object.entries(newSteps).flatMap(
180
250
  ([stepId, stepResult]) => {
@@ -193,76 +263,40 @@ var mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
193
263
  suspended: suspendedStepIds
194
264
  };
195
265
  }
196
- if (chunk.type === "workflow-step-waiting") {
266
+ if (chunk.type === "workflow-step-waiting") return { ...prev, status: "waiting", steps: newSteps };
267
+ if (chunk.type === "workflow-step-progress") {
197
268
  return {
198
269
  ...prev,
199
- status: "waiting",
200
- steps: newSteps
201
- };
202
- }
203
- if (chunk.type === "workflow-step-progress") {
204
- const progressSteps = {
205
- ...prev?.steps,
206
- [chunk.payload.id]: {
207
- ...prev?.steps?.[chunk.payload.id],
208
- foreachProgress: {
209
- completedCount: chunk.payload.completedCount,
210
- totalCount: chunk.payload.totalCount,
211
- currentIndex: chunk.payload.currentIndex,
212
- iterationStatus: chunk.payload.iterationStatus,
213
- iterationOutput: chunk.payload.iterationOutput
270
+ steps: {
271
+ ...prev?.steps,
272
+ [chunk.payload.id]: {
273
+ ...prev?.steps?.[chunk.payload.id],
274
+ foreachProgress: {
275
+ completedCount: chunk.payload.completedCount,
276
+ totalCount: chunk.payload.totalCount,
277
+ currentIndex: chunk.payload.currentIndex,
278
+ iterationStatus: chunk.payload.iterationStatus,
279
+ iterationOutput: chunk.payload.iterationOutput
280
+ }
214
281
  }
215
282
  }
216
283
  };
217
- return {
218
- ...prev,
219
- steps: progressSteps
220
- };
221
- }
222
- if (chunk.type === "workflow-step-result") {
223
- return {
224
- ...prev,
225
- steps: newSteps
226
- };
227
284
  }
285
+ if (chunk.type === "workflow-step-result") return { ...prev, steps: newSteps };
228
286
  return prev;
229
287
  };
230
- function signalContentsToUserMessages(contents, metadata) {
231
- if (typeof contents === "string") {
232
- return [
233
- {
234
- id: `signal-${Date.now()}`,
235
- role: "user",
236
- parts: [{ type: "text", text: contents }],
237
- metadata
238
- }
239
- ];
240
- }
241
- if (Array.isArray(contents)) {
242
- return contents.flatMap((content2) => signalContentsToUserMessages(content2, metadata));
243
- }
244
- if (!contents || typeof contents !== "object") {
245
- return [];
246
- }
247
- const message = contents;
248
- if (message.role && message.role !== "user") {
249
- return [];
250
- }
251
- const content = message.content;
252
- if (typeof content === "string") {
253
- return [
254
- {
255
- id: `signal-${Date.now()}`,
256
- role: "user",
257
- parts: [{ type: "text", text: content }],
258
- metadata
259
- }
260
- ];
261
- }
262
- if (!Array.isArray(content)) {
263
- return [];
264
- }
265
- const parts = content.flatMap((part) => {
288
+ var signalContentsToUserMessages = (contents, metadata) => {
289
+ const makeUserMessage = (parts2) => ({
290
+ id: `signal-${Date.now()}`,
291
+ role: "user",
292
+ createdAt: /* @__PURE__ */ new Date(),
293
+ content: {
294
+ format: 2,
295
+ parts: parts2,
296
+ metadata: cloneMetadata(metadata)
297
+ }
298
+ });
299
+ const toMessagePart = (part) => {
266
300
  if (!part || typeof part !== "object") return [];
267
301
  const typedPart = part;
268
302
  if (typedPart.type === "text" && typeof typedPart.text === "string") {
@@ -290,19 +324,37 @@ function signalContentsToUserMessages(contents, metadata) {
290
324
  ];
291
325
  }
292
326
  return [];
293
- });
294
- return parts.length ? [
295
- {
296
- id: `signal-${Date.now()}`,
297
- role: "user",
298
- parts,
299
- metadata
300
- }
301
- ] : [];
302
- }
303
- var toUIMessage = ({ chunk, conversation, metadata }) => {
327
+ };
328
+ if (typeof contents === "string") {
329
+ return [makeUserMessage([{ type: "text", text: contents }])];
330
+ }
331
+ if (Array.isArray(contents)) {
332
+ const parts2 = contents.flatMap(toMessagePart);
333
+ return parts2.length ? [makeUserMessage(parts2)] : contents.flatMap((content2) => signalContentsToUserMessages(content2, metadata));
334
+ }
335
+ if (!contents || typeof contents !== "object") return [];
336
+ const message = contents;
337
+ if (message.role && message.role !== "user") return [];
338
+ const content = message.content;
339
+ if (typeof content === "string") {
340
+ return [makeUserMessage([{ type: "text", text: content }])];
341
+ }
342
+ if (!Array.isArray(content)) return [];
343
+ const parts = content.flatMap(toMessagePart);
344
+ return parts.length ? [makeUserMessage(parts)] : [];
345
+ };
346
+ var makeToolInvocationPart = (invocation) => ({
347
+ type: "tool-invocation",
348
+ toolInvocation: invocation
349
+ });
350
+ var isTemplateLiteralPassthrough = (chunk) => chunk.type.startsWith("agent-execution-event-") || chunk.type.startsWith("workflow-execution-event-");
351
+ var isDataChunk = (chunk) => chunk.type.startsWith("data-");
352
+ var accumulateChunk = ({ chunk, conversation, metadata }) => {
304
353
  const result = [...conversation];
305
- if (chunk.type.startsWith("data-")) {
354
+ if (isTemplateLiteralPassthrough(chunk)) {
355
+ return result;
356
+ }
357
+ if (isDataChunk(chunk)) {
306
358
  if (chunk.type === "data-user-message" && "data" in chunk && (chunk.data?.type === "user-message" || chunk.data?.type === "user")) {
307
359
  const signalId = chunk.data.id;
308
360
  if (typeof signalId === "string" && result.some((message) => message.id === signalId)) {
@@ -327,58 +379,37 @@ var toUIMessage = ({ chunk, conversation, metadata }) => {
327
379
  };
328
380
  const lastMessage = result[result.length - 1];
329
381
  if (!lastMessage || lastMessage.role !== "assistant") {
330
- const newMessage = {
331
- id: `data-${chunk.runId}-${Date.now()}`,
332
- role: "assistant",
333
- parts: [dataPart],
334
- metadata
335
- };
336
- return [...result, newMessage];
382
+ return appendAssistantMessage(result, `data-${chunk.runId}-${Date.now()}`, [dataPart], metadata);
337
383
  }
338
- const updatedMessage = {
339
- ...lastMessage,
340
- parts: [...lastMessage.parts, dataPart]
341
- };
342
- return [...result.slice(0, -1), updatedMessage];
384
+ return replaceLast(result, withParts(lastMessage, [...lastMessage.content.parts, dataPart]));
343
385
  }
344
386
  switch (chunk.type) {
345
387
  case "tripwire": {
346
- const newMessage = {
347
- id: `tripwire-${chunk.runId + Date.now()}`,
348
- role: "assistant",
349
- parts: [
350
- {
351
- type: "text",
352
- text: chunk.payload.reason
353
- }
354
- ],
355
- metadata: {
388
+ const newMessage = newAssistantMessage(
389
+ `tripwire-${chunk.runId + Date.now()}`,
390
+ [{ type: "text", text: chunk.payload.reason }],
391
+ {
356
392
  ...metadata,
357
393
  status: "tripwire",
358
394
  tripwire: {
395
+ reason: chunk.payload.reason,
359
396
  retry: chunk.payload.retry,
360
- tripwirePayload: chunk.payload.metadata,
397
+ metadata: chunk.payload.metadata,
361
398
  processorId: chunk.payload.processorId
362
399
  }
363
400
  }
364
- };
401
+ );
365
402
  return [...result, newMessage];
366
403
  }
367
404
  case "start": {
368
405
  const messageId = typeof chunk.payload.messageId === "string" ? chunk.payload.messageId : void 0;
369
406
  if (messageId && result.some((message) => message.id === messageId)) return result;
370
- const newMessage = {
371
- id: messageId ?? `start-${chunk.runId + Date.now()}`,
372
- role: "assistant",
373
- parts: [],
374
- metadata
375
- };
376
- return [...result, newMessage];
407
+ return [...result, newAssistantMessage(messageId ?? `start-${chunk.runId + Date.now()}`, [], metadata)];
377
408
  }
378
409
  case "text-start": {
379
410
  const lastMessage = result[result.length - 1];
380
411
  const textId = chunk.payload.id || `text-${Date.now()}`;
381
- if (chunk.payload.id && lastMessage?.role === "assistant" && lastMessage.parts.some((part) => part.type === "text" && part.textId === textId)) {
412
+ if (chunk.payload.id && lastMessage?.role === "assistant" && lastMessage.content.parts.some((part) => part.type === "text" && partTextId(part) === textId)) {
382
413
  return result;
383
414
  }
384
415
  const newTextPart = {
@@ -391,41 +422,35 @@ var toUIMessage = ({ chunk, conversation, metadata }) => {
391
422
  if (!lastMessage || lastMessage.role !== "assistant") {
392
423
  return appendAssistantMessage(
393
424
  result,
394
- { id: `start-${chunk.runId}-${Date.now()}`, parts: [newTextPart] },
425
+ `start-${chunk.runId}-${Date.now()}`,
426
+ [newTextPart],
395
427
  metadata
396
428
  );
397
429
  }
398
- if (lastMessage.metadata?.completionResult) {
430
+ if (lastMessage.content.metadata?.completionResult) {
399
431
  return appendAssistantMessage(
400
432
  result,
401
- { id: `start-${chunk.runId}-${Date.now()}`, parts: [newTextPart] },
433
+ `start-${chunk.runId}-${Date.now()}`,
434
+ [newTextPart],
402
435
  metadata
403
436
  );
404
437
  }
405
- const parts = [...lastMessage.parts];
406
- parts.push(newTextPart);
407
- return [
408
- ...result.slice(0, -1),
409
- {
410
- ...lastMessage,
411
- parts
412
- }
413
- ];
438
+ return replaceLast(
439
+ result,
440
+ withParts(lastMessage, [...lastMessage.content.parts, newTextPart])
441
+ );
414
442
  }
415
443
  case "background-task-progress": {
416
444
  const lastMessage = result[result.length - 1];
417
445
  if (!lastMessage || lastMessage.role !== "assistant") return result;
418
- return [
419
- ...result.slice(0, -1),
420
- {
421
- ...lastMessage,
422
- metadata: {
423
- mode: metadata.mode,
424
- ...lastMessage.metadata,
425
- runningBackgroundTasksCount: chunk.payload.runningCount
426
- }
427
- }
428
- ];
446
+ return replaceLast(
447
+ result,
448
+ withMetadata(lastMessage, {
449
+ mode: metadata.mode,
450
+ ...lastMessage.content.metadata,
451
+ runningBackgroundTasksCount: chunk.payload.runningCount
452
+ })
453
+ );
429
454
  }
430
455
  case "text-delta": {
431
456
  const lastMessage = result[result.length - 1];
@@ -440,16 +465,15 @@ var toUIMessage = ({ chunk, conversation, metadata }) => {
440
465
  };
441
466
  return appendAssistantMessage(
442
467
  result,
443
- { id: `text-${chunk.runId}-${Date.now()}`, parts: [newTextPart] },
468
+ `text-${chunk.runId}-${Date.now()}`,
469
+ [newTextPart],
444
470
  metadata
445
471
  );
446
472
  }
447
- const parts = [...lastMessage.parts];
448
- let textPartIndex = textId ? parts.findLastIndex((part) => part.type === "text" && part.textId === textId) : -1;
473
+ const parts = [...lastMessage.content.parts];
474
+ let textPartIndex = textId ? parts.findLastIndex((part) => part.type === "text" && partTextId(part) === textId) : -1;
449
475
  if (textPartIndex === -1) {
450
- textPartIndex = parts.findLastIndex(
451
- (part) => part.type === "text" && part.state === "streaming"
452
- );
476
+ textPartIndex = parts.findLastIndex((part) => part.type === "text" && partState(part) === "streaming");
453
477
  }
454
478
  if (textPartIndex === -1) {
455
479
  const newTextPart = {
@@ -462,232 +486,370 @@ var toUIMessage = ({ chunk, conversation, metadata }) => {
462
486
  parts.push(newTextPart);
463
487
  } else {
464
488
  const textPart = parts[textPartIndex];
465
- if (textPart.type === "text") {
466
- const extendedTextPart = textPart;
467
- const updatedTextPart = {
468
- ...extendedTextPart,
469
- text: extendedTextPart.text + chunk.payload.text,
470
- state: "streaming"
471
- };
472
- parts[textPartIndex] = updatedTextPart;
473
- }
489
+ parts[textPartIndex] = {
490
+ ...textPart,
491
+ text: textPart.text + chunk.payload.text,
492
+ state: "streaming"
493
+ };
474
494
  }
475
- return [
476
- ...result.slice(0, -1),
477
- {
478
- ...lastMessage,
479
- parts
480
- }
481
- ];
495
+ return replaceLast(result, withParts(lastMessage, parts));
496
+ }
497
+ case "text-end": {
498
+ return result;
482
499
  }
483
500
  case "reasoning-start": {
484
501
  const lastMessage = result[result.length - 1];
485
- if (!lastMessage || lastMessage.role !== "assistant") {
486
- const newMessage = {
487
- id: `reasoning-${chunk.runId + Date.now()}`,
488
- role: "assistant",
489
- parts: [
490
- {
491
- type: "reasoning",
492
- text: "",
493
- state: "streaming",
494
- providerMetadata: chunk.payload.providerMetadata
495
- }
496
- ],
497
- metadata
498
- };
499
- return [...result, newMessage];
500
- }
501
- const parts = [...lastMessage.parts];
502
- parts.push({
502
+ const newReasoningPart = {
503
503
  type: "reasoning",
504
- text: "",
504
+ reasoning: "",
505
505
  state: "streaming",
506
506
  providerMetadata: chunk.payload.providerMetadata
507
- });
508
- return [
509
- ...result.slice(0, -1),
510
- {
511
- ...lastMessage,
512
- parts
513
- }
514
- ];
507
+ };
508
+ if (!lastMessage || lastMessage.role !== "assistant") {
509
+ return appendAssistantMessage(
510
+ result,
511
+ `reasoning-${chunk.runId + Date.now()}`,
512
+ [newReasoningPart],
513
+ metadata
514
+ );
515
+ }
516
+ return replaceLast(
517
+ result,
518
+ withParts(lastMessage, [...lastMessage.content.parts, newReasoningPart])
519
+ );
515
520
  }
516
521
  case "reasoning-delta": {
517
522
  const lastMessage = result[result.length - 1];
518
523
  if (!lastMessage || lastMessage.role !== "assistant") {
519
- const newMessage = {
520
- id: `reasoning-${chunk.runId + Date.now()}`,
521
- role: "assistant",
522
- parts: [
523
- {
524
- type: "reasoning",
525
- text: chunk.payload.text,
526
- state: "streaming",
527
- providerMetadata: chunk.payload.providerMetadata
528
- }
529
- ],
530
- metadata
524
+ const newReasoningPart = {
525
+ type: "reasoning",
526
+ reasoning: chunk.payload.text,
527
+ state: "streaming",
528
+ providerMetadata: chunk.payload.providerMetadata
531
529
  };
532
- return [...result, newMessage];
530
+ return appendAssistantMessage(
531
+ result,
532
+ `reasoning-${chunk.runId + Date.now()}`,
533
+ [newReasoningPart],
534
+ metadata
535
+ );
533
536
  }
534
- const parts = [...lastMessage.parts];
535
- const lastPartIndex = parts.length - 1;
536
- const lastPart = parts[lastPartIndex];
537
+ const parts = [...lastMessage.content.parts];
538
+ const lastIndex = parts.length - 1;
539
+ const lastPart = parts[lastIndex];
537
540
  if (lastPart?.type === "reasoning") {
538
- parts[lastPartIndex] = {
539
- ...lastPart,
540
- text: lastPart.text + chunk.payload.text,
541
+ const reasoningPart = lastPart;
542
+ parts[lastIndex] = {
543
+ ...reasoningPart,
544
+ reasoning: reasoningPart.reasoning + chunk.payload.text,
541
545
  state: "streaming"
542
546
  };
543
547
  } else {
544
- parts.push({
548
+ const newReasoningPart = {
545
549
  type: "reasoning",
546
- text: chunk.payload.text,
550
+ reasoning: chunk.payload.text,
547
551
  state: "streaming",
548
552
  providerMetadata: chunk.payload.providerMetadata
549
- });
553
+ };
554
+ parts.push(newReasoningPart);
550
555
  }
551
- return [
552
- ...result.slice(0, -1),
553
- {
554
- ...lastMessage,
555
- parts
556
- }
557
- ];
556
+ return replaceLast(result, withParts(lastMessage, parts));
558
557
  }
559
558
  case "reasoning-end": {
560
559
  const lastMessage = result[result.length - 1];
561
560
  if (!lastMessage || lastMessage.role !== "assistant") return result;
562
- const parts = [...lastMessage.parts];
563
- const reasoningPartIndex = parts.findLastIndex(
564
- (part) => part.type === "reasoning" && part.state === "streaming"
565
- );
566
- if (reasoningPartIndex === -1) return result;
567
- const reasoningPart = parts[reasoningPartIndex];
568
- if (reasoningPart.type !== "reasoning") return result;
569
- const existingMetadata = reasoningPart.providerMetadata;
570
- const endMetadata = chunk.payload.providerMetadata;
571
- parts[reasoningPartIndex] = {
561
+ const parts = [...lastMessage.content.parts];
562
+ const reasoningIndex = parts.findLastIndex((part) => part.type === "reasoning" && partState(part) === "streaming");
563
+ if (reasoningIndex === -1) return result;
564
+ const reasoningPart = parts[reasoningIndex];
565
+ const existingMeta = reasoningPart.providerMetadata;
566
+ const endMeta = chunk.payload.providerMetadata;
567
+ parts[reasoningIndex] = {
572
568
  ...reasoningPart,
573
569
  state: "done",
574
- ...existingMetadata || endMetadata ? {
575
- providerMetadata: {
576
- ...existingMetadata ?? {},
577
- ...endMetadata ?? {}
578
- }
579
- } : {}
570
+ ...existingMeta || endMeta ? { providerMetadata: { ...existingMeta ?? {}, ...endMeta ?? {} } } : {}
580
571
  };
581
- return [
582
- ...result.slice(0, -1),
583
- {
584
- ...lastMessage,
585
- parts
586
- }
587
- ];
572
+ return replaceLast(result, withParts(lastMessage, parts));
588
573
  }
589
- case "tool-call": {
574
+ case "reasoning-signature": {
575
+ const lastMessage = result[result.length - 1];
576
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
577
+ const parts = [...lastMessage.content.parts];
578
+ const reasoningIndex = parts.findLastIndex((part) => part.type === "reasoning");
579
+ if (reasoningIndex === -1) return result;
580
+ const reasoningPart = parts[reasoningIndex];
581
+ const existingMeta = reasoningPart.providerMetadata;
582
+ const sigMeta = chunk.payload.providerMetadata;
583
+ parts[reasoningIndex] = {
584
+ ...reasoningPart,
585
+ ...existingMeta || sigMeta ? { providerMetadata: { ...existingMeta ?? {}, ...sigMeta ?? {} } } : {}
586
+ };
587
+ return replaceLast(result, withParts(lastMessage, parts));
588
+ }
589
+ case "redacted-reasoning": {
590
590
  const lastMessage = result[result.length - 1];
591
+ const redactedData = chunk.payload.data;
592
+ const redactedPart = {
593
+ type: "reasoning",
594
+ reasoning: typeof redactedData === "string" ? redactedData : "",
595
+ state: "done",
596
+ redacted: true,
597
+ providerMetadata: chunk.payload.providerMetadata
598
+ };
591
599
  if (!lastMessage || lastMessage.role !== "assistant") {
592
- const newMessage = {
593
- id: `tool-call-${chunk.runId + Date.now()}`,
594
- role: "assistant",
595
- parts: [
596
- {
597
- type: "dynamic-tool",
598
- toolName: chunk.payload.toolName,
599
- toolCallId: chunk.payload.toolCallId,
600
- state: "input-available",
601
- input: chunk.payload.args,
602
- callProviderMetadata: chunk.payload.providerMetadata
603
- }
604
- ],
600
+ return appendAssistantMessage(
601
+ result,
602
+ `redacted-reasoning-${chunk.runId + Date.now()}`,
603
+ [redactedPart],
605
604
  metadata
606
- };
607
- return [...result, newMessage];
605
+ );
608
606
  }
609
- const parts = [...lastMessage.parts];
610
- parts.push({
611
- type: "dynamic-tool",
612
- toolName: chunk.payload.toolName,
607
+ return replaceLast(
608
+ result,
609
+ withParts(lastMessage, [...lastMessage.content.parts, redactedPart])
610
+ );
611
+ }
612
+ case "tool-call": {
613
+ const invocation = {
614
+ state: "call",
613
615
  toolCallId: chunk.payload.toolCallId,
614
- state: "input-available",
615
- input: chunk.payload.args,
616
- callProviderMetadata: chunk.payload.providerMetadata
617
- });
618
- return [
619
- ...result.slice(0, -1),
620
- {
621
- ...lastMessage,
622
- parts
616
+ toolName: chunk.payload.toolName,
617
+ args: chunk.payload.args
618
+ };
619
+ const newPart = {
620
+ ...makeToolInvocationPart(invocation),
621
+ providerMetadata: chunk.payload.providerMetadata
622
+ };
623
+ const existing = locateToolPart(result, chunk.payload.toolCallId, false);
624
+ if (existing && existing.toolPartIndex >= 0) {
625
+ const { messageIndex, toolPartIndex } = existing;
626
+ const targetMessage = result[messageIndex];
627
+ if (targetMessage && targetMessage.role === "assistant") {
628
+ const parts = [...targetMessage.content.parts];
629
+ const prev = parts[toolPartIndex];
630
+ if (isToolPart(prev)) {
631
+ const { argsText: _argsText, ...rest } = prev;
632
+ parts[toolPartIndex] = {
633
+ ...rest,
634
+ toolInvocation: {
635
+ ...prev.toolInvocation,
636
+ state: "call",
637
+ toolName: chunk.payload.toolName,
638
+ toolCallId: chunk.payload.toolCallId,
639
+ args: chunk.payload.args
640
+ },
641
+ providerMetadata: chunk.payload.providerMetadata ?? prev.providerMetadata
642
+ };
643
+ return replaceAt(result, messageIndex, withParts(targetMessage, parts));
644
+ }
623
645
  }
624
- ];
646
+ }
647
+ const lastMessage = result[result.length - 1];
648
+ if (!lastMessage || lastMessage.role !== "assistant") {
649
+ return appendAssistantMessage(result, `tool-call-${chunk.runId + Date.now()}`, [newPart], metadata);
650
+ }
651
+ return replaceLast(result, withParts(lastMessage, [...lastMessage.content.parts, newPart]));
625
652
  }
626
- case "tool-error":
627
- case "tool-result":
628
- case "background-task-completed":
629
- case "background-task-failed": {
630
- const isBgTaskEvent = chunk.type === "background-task-completed" || chunk.type === "background-task-failed";
631
- const location = locateToolPart(result, chunk.payload.toolCallId, isBgTaskEvent);
632
- if (!location) return result;
653
+ case "tool-call-input-streaming-start": {
654
+ const lastMessage = result[result.length - 1];
655
+ const invocation = {
656
+ state: "partial-call",
657
+ toolCallId: chunk.payload.toolCallId,
658
+ toolName: chunk.payload.toolName,
659
+ args: {}
660
+ };
661
+ const newPart = {
662
+ ...makeToolInvocationPart(invocation),
663
+ argsText: ""
664
+ };
665
+ if (!lastMessage || lastMessage.role !== "assistant") {
666
+ return appendAssistantMessage(
667
+ result,
668
+ `tool-call-streaming-${chunk.runId + Date.now()}`,
669
+ [newPart],
670
+ metadata
671
+ );
672
+ }
673
+ return replaceLast(result, withParts(lastMessage, [...lastMessage.content.parts, newPart]));
674
+ }
675
+ case "tool-call-delta": {
676
+ const location = locateToolPart(result, chunk.payload.toolCallId, false);
677
+ if (!location || location.toolPartIndex < 0) return result;
633
678
  const { messageIndex, toolPartIndex } = location;
634
679
  const targetMessage = result[messageIndex];
635
680
  if (!targetMessage || targetMessage.role !== "assistant") return result;
636
- const parts = [...targetMessage.parts];
637
- const toolPart = toolPartIndex >= 0 ? parts[toolPartIndex] : void 0;
638
- if (toolPart && (toolPart.type === "dynamic-tool" || typeof toolPart.type === "string" && toolPart.type.startsWith("tool-"))) {
639
- const toolName = "toolName" in toolPart && typeof toolPart.toolName === "string" ? toolPart.toolName : typeof toolPart.type === "string" && toolPart.type.startsWith("tool-") ? toolPart.type.substring(5) : "";
640
- const toolCallId = toolPart.toolCallId;
641
- if ((chunk.type === "tool-result" || chunk.type === "background-task-completed") && chunk.payload.isError || chunk.type === "tool-error" || chunk.type === "background-task-failed") {
642
- const error = chunk.type === "tool-error" || chunk.type === "background-task-failed" ? chunk.payload.error : chunk.payload.result;
643
- parts[toolPartIndex] = {
644
- type: "dynamic-tool",
645
- toolName,
646
- toolCallId,
647
- state: "output-error",
648
- input: toolPart.input,
649
- errorText: typeof error === "string" ? error : error instanceof Error ? error.message : error?.message ?? String(error),
650
- callProviderMetadata: chunk.payload.providerMetadata
681
+ const parts = [...targetMessage.content.parts];
682
+ const toolPart = parts[toolPartIndex];
683
+ if (!isToolPart(toolPart)) return result;
684
+ const nextArgsText = (toolPart.argsText ?? "") + (chunk.payload.argsTextDelta ?? "");
685
+ parts[toolPartIndex] = {
686
+ ...toolPart,
687
+ argsText: nextArgsText,
688
+ toolInvocation: {
689
+ ...toolPart.toolInvocation,
690
+ state: "partial-call"
691
+ }
692
+ };
693
+ return replaceAt(result, messageIndex, withParts(targetMessage, parts));
694
+ }
695
+ case "tool-call-input-streaming-end": {
696
+ const location = locateToolPart(result, chunk.payload.toolCallId, false);
697
+ if (!location || location.toolPartIndex < 0) return result;
698
+ const { messageIndex, toolPartIndex } = location;
699
+ const targetMessage = result[messageIndex];
700
+ if (!targetMessage || targetMessage.role !== "assistant") return result;
701
+ const parts = [...targetMessage.content.parts];
702
+ const toolPart = parts[toolPartIndex];
703
+ if (!isToolPart(toolPart)) return result;
704
+ let parsedArgs = {};
705
+ const argsText = toolPart.argsText;
706
+ if (typeof argsText === "string" && argsText.length > 0) {
707
+ try {
708
+ const maybe = JSON.parse(argsText);
709
+ if (maybe && typeof maybe === "object" && !Array.isArray(maybe)) {
710
+ parsedArgs = maybe;
711
+ }
712
+ } catch {
713
+ parsedArgs = {};
714
+ }
715
+ }
716
+ parts[toolPartIndex] = {
717
+ ...toolPart,
718
+ toolInvocation: {
719
+ ...toolPart.toolInvocation,
720
+ state: "call",
721
+ args: parsedArgs
722
+ }
723
+ };
724
+ return replaceAt(result, messageIndex, withParts(targetMessage, parts));
725
+ }
726
+ case "tool-error":
727
+ case "tool-result":
728
+ case "background-task-completed":
729
+ case "background-task-failed": {
730
+ const isBgTaskEvent = chunk.type === "background-task-completed" || chunk.type === "background-task-failed";
731
+ const location = locateToolPart(result, chunk.payload.toolCallId, isBgTaskEvent);
732
+ if (!location) return result;
733
+ const { messageIndex, toolPartIndex } = location;
734
+ const targetMessage = result[messageIndex];
735
+ if (!targetMessage || targetMessage.role !== "assistant") return result;
736
+ const parts = [...targetMessage.content.parts];
737
+ const toolPart = toolPartIndex >= 0 ? parts[toolPartIndex] : void 0;
738
+ let payloadResult;
739
+ let payloadError;
740
+ let payloadIsError = false;
741
+ let payloadProviderMetadata;
742
+ let payloadCompletedAt;
743
+ let payloadTaskId;
744
+ switch (chunk.type) {
745
+ case "tool-result":
746
+ payloadResult = chunk.payload.result;
747
+ payloadIsError = Boolean(chunk.payload.isError);
748
+ payloadProviderMetadata = chunk.payload.providerMetadata;
749
+ break;
750
+ case "tool-error":
751
+ payloadError = chunk.payload.error;
752
+ payloadProviderMetadata = chunk.payload.providerMetadata;
753
+ break;
754
+ case "background-task-completed":
755
+ payloadResult = chunk.payload.result;
756
+ payloadCompletedAt = chunk.payload.completedAt;
757
+ payloadTaskId = chunk.payload.taskId;
758
+ break;
759
+ case "background-task-failed":
760
+ payloadError = chunk.payload.error;
761
+ payloadCompletedAt = chunk.payload.completedAt;
762
+ payloadTaskId = chunk.payload.taskId;
763
+ break;
764
+ }
765
+ if (toolPart && isToolPart(toolPart)) {
766
+ const { toolName, toolCallId, args } = toolPart.toolInvocation;
767
+ const providerMeta = payloadProviderMetadata ?? toolPart.providerMetadata;
768
+ const isError = chunk.type === "tool-error" || chunk.type === "background-task-failed" || payloadIsError;
769
+ if (isError) {
770
+ const error = chunk.type === "tool-error" || chunk.type === "background-task-failed" ? payloadError : payloadResult;
771
+ const errorText = typeof error === "string" ? error : error instanceof Error ? error.message : error?.message ?? String(error);
772
+ parts[toolPartIndex] = {
773
+ ...toolPart,
774
+ providerMetadata: providerMeta,
775
+ toolInvocation: {
776
+ state: "output-error",
777
+ toolCallId,
778
+ toolName,
779
+ args,
780
+ errorText
781
+ }
651
782
  };
652
783
  } else {
653
- const isWorkflow = Boolean(chunk.payload.result?.result?.steps);
654
- const isAgent = chunk?.from === "AGENT";
784
+ const resultObj = payloadResult;
785
+ const existingResult = toolPart.toolInvocation.state === "partial-call" || toolPart.toolInvocation.state === "result" ? toolPart.toolInvocation.result : void 0;
786
+ const existingLooksLikeWorkflow = Boolean(
787
+ existingResult && typeof existingResult === "object" && "steps" in existingResult
788
+ );
789
+ const isWorkflow = Boolean(resultObj?.result?.steps) || toolName?.startsWith("workflow-") || existingLooksLikeWorkflow;
790
+ const isAgent = chunk.from === "AGENT";
655
791
  let output;
656
792
  if (isWorkflow) {
657
- output = chunk.payload.result?.result;
793
+ const accumulated = existingLooksLikeWorkflow && existingResult && typeof existingResult === "object" ? existingResult : void 0;
794
+ const payloadWorkflow = resultObj?.result && typeof resultObj.result === "object" ? resultObj.result : void 0;
795
+ if (accumulated || payloadWorkflow) {
796
+ output = {
797
+ ...accumulated ?? {},
798
+ ...payloadWorkflow ?? {},
799
+ // Preserve `steps` from accumulated state when the terminal
800
+ // payload doesn't carry them.
801
+ steps: payloadWorkflow?.steps ?? accumulated?.steps ?? [],
802
+ status: payloadWorkflow?.status ?? accumulated?.status ?? "success",
803
+ // Surface the terminal scalar output without losing history.
804
+ output: payloadResult
805
+ };
806
+ } else {
807
+ output = payloadResult;
808
+ }
658
809
  } else if (isAgent) {
659
- const existingOutput = parts[toolPartIndex].output;
810
+ const existingOutput = toolPart.toolInvocation.state === "result" ? toolPart.toolInvocation.result : void 0;
811
+ const existingChild = existingOutput?.childMessages;
660
812
  output = existingOutput ? {
661
- ...chunk.payload.result,
662
- childMessages: existingOutput.childMessages?.length ? existingOutput.childMessages : chunk.payload.result?.childMessages
663
- } : chunk.payload.result;
813
+ ...payloadResult,
814
+ childMessages: existingChild?.length ? existingChild : resultObj?.childMessages
815
+ } : payloadResult;
664
816
  } else {
665
- output = chunk.payload.result;
817
+ output = payloadResult;
666
818
  }
667
819
  parts[toolPartIndex] = {
668
- type: "dynamic-tool",
669
- toolName,
670
- toolCallId,
671
- state: "output-available",
672
- input: toolPart.input,
673
- output,
674
- callProviderMetadata: chunk.payload.providerMetadata
820
+ ...toolPart,
821
+ providerMetadata: providerMeta,
822
+ toolInvocation: {
823
+ state: "result",
824
+ toolCallId,
825
+ toolName,
826
+ args,
827
+ result: output
828
+ }
675
829
  };
676
830
  }
677
831
  }
678
- const nextMessage = {
679
- ...targetMessage,
680
- parts,
681
- metadata: mergeBgTaskMetadata(targetMessage.metadata, metadata.mode, {
832
+ const nextMetadata = mergeBgTaskMetadata(
833
+ targetMessage.content.metadata,
834
+ metadata.mode,
835
+ {
682
836
  resetRunningCount: isBgTaskEvent,
683
- perTaskEntry: isBgTaskEvent ? {
837
+ perTaskEntry: isBgTaskEvent && payloadTaskId ? {
684
838
  toolCallId: chunk.payload.toolCallId,
685
- completedAt: chunk.payload.completedAt,
686
- taskId: chunk.payload.taskId
839
+ completedAt: payloadCompletedAt,
840
+ taskId: payloadTaskId
687
841
  } : void 0
688
- })
842
+ }
843
+ );
844
+ const nextMessage = {
845
+ ...targetMessage,
846
+ content: {
847
+ ...targetMessage.content,
848
+ parts,
849
+ metadata: nextMetadata
850
+ }
689
851
  };
690
- return [...result.slice(0, messageIndex), nextMessage, ...result.slice(messageIndex + 1)];
852
+ return replaceAt(result, messageIndex, nextMessage);
691
853
  }
692
854
  case "background-task-running": {
693
855
  const location = locateToolPart(result, chunk.payload.toolCallId, true);
@@ -695,20 +857,18 @@ var toUIMessage = ({ chunk, conversation, metadata }) => {
695
857
  const { messageIndex } = location;
696
858
  const targetMessage = result[messageIndex];
697
859
  if (!targetMessage || targetMessage.role !== "assistant") return result;
698
- return [
699
- ...result.slice(0, messageIndex),
860
+ const nextMetadata = mergeBgTaskMetadata(
861
+ targetMessage.content.metadata,
862
+ metadata.mode,
700
863
  {
701
- ...targetMessage,
702
- metadata: mergeBgTaskMetadata(targetMessage.metadata, metadata.mode, {
703
- perTaskEntry: {
704
- toolCallId: chunk.payload.toolCallId,
705
- startedAt: chunk.payload.startedAt,
706
- taskId: chunk.payload.taskId
707
- }
708
- })
709
- },
710
- ...result.slice(messageIndex + 1)
711
- ];
864
+ perTaskEntry: {
865
+ toolCallId: chunk.payload.toolCallId,
866
+ startedAt: chunk.payload.startedAt,
867
+ taskId: chunk.payload.taskId
868
+ }
869
+ }
870
+ );
871
+ return replaceAt(result, messageIndex, withMetadata(targetMessage, nextMetadata));
712
872
  }
713
873
  case "tool-output":
714
874
  case "background-task-output": {
@@ -718,47 +878,41 @@ var toUIMessage = ({ chunk, conversation, metadata }) => {
718
878
  const { messageIndex, toolPartIndex } = location;
719
879
  const targetMessage = result[messageIndex];
720
880
  if (!targetMessage || targetMessage.role !== "assistant") return result;
721
- const parts = [...targetMessage.parts];
881
+ const parts = [...targetMessage.content.parts];
722
882
  const toolPart = parts[toolPartIndex];
723
- if (toolPart.type === "dynamic-tool" || typeof toolPart.type === "string" && toolPart.type.startsWith("tool-")) {
724
- const toolName = "toolName" in toolPart && typeof toolPart.toolName === "string" ? toolPart.toolName : typeof toolPart.type === "string" && toolPart.type.startsWith("tool-") ? toolPart.type.substring(5) : "";
725
- const toolCallId = toolPart.toolCallId;
726
- const input = toolPart.input;
727
- const payloadOutput = chunk.type === "background-task-output" ? chunk.payload.payload.payload.output : chunk.payload.output;
728
- if (payloadOutput?.type?.startsWith("workflow-")) {
729
- const existingWorkflowState = toolPart.output || {};
730
- const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, payloadOutput);
731
- parts[toolPartIndex] = {
732
- type: "dynamic-tool",
733
- toolName,
883
+ if (!isToolPart(toolPart)) return result;
884
+ const { toolName, toolCallId, args } = toolPart.toolInvocation;
885
+ const payloadOutput = chunk.type === "background-task-output" ? chunk.payload.payload.payload.output : chunk.payload.output;
886
+ if (payloadOutput?.type?.startsWith("workflow-")) {
887
+ const existingWorkflowState = toolPart.toolInvocation.result || {};
888
+ const updated = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, payloadOutput);
889
+ parts[toolPartIndex] = {
890
+ ...toolPart,
891
+ toolInvocation: {
892
+ state: "partial-call",
734
893
  toolCallId,
735
- state: "input-streaming",
736
- input,
737
- output: updatedWorkflowState
738
- };
739
- } else if (payloadOutput?.from === "AGENT" || payloadOutput?.from === "USER" && payloadOutput?.payload?.output?.type?.startsWith("workflow-")) {
740
- return toUIMessageFromAgent(payloadOutput, conversation, metadata, toolCallId, toolName);
741
- } else {
742
- const currentOutput = toolPart.output || [];
743
- const existingOutput = Array.isArray(currentOutput) ? currentOutput : [];
744
- parts[toolPartIndex] = {
745
- type: "dynamic-tool",
746
894
  toolName,
895
+ args,
896
+ result: updated
897
+ }
898
+ };
899
+ } else if (payloadOutput?.from === "AGENT" || payloadOutput?.from === "USER" && payloadOutput?.payload?.output?.type?.startsWith("workflow-")) {
900
+ return accumulateAgentChunk(payloadOutput, result, metadata, toolCallId, toolName);
901
+ } else {
902
+ const currentResult = toolPart.toolInvocation.result;
903
+ const existing = Array.isArray(currentResult) ? currentResult : [];
904
+ parts[toolPartIndex] = {
905
+ ...toolPart,
906
+ toolInvocation: {
907
+ state: "partial-call",
747
908
  toolCallId,
748
- state: "input-streaming",
749
- input,
750
- output: [...existingOutput, payloadOutput]
751
- };
752
- }
909
+ toolName,
910
+ args,
911
+ result: [...existing, payloadOutput]
912
+ }
913
+ };
753
914
  }
754
- return [
755
- ...result.slice(0, messageIndex),
756
- {
757
- ...targetMessage,
758
- parts
759
- },
760
- ...result.slice(messageIndex + 1)
761
- ];
915
+ return replaceAt(result, messageIndex, withParts(targetMessage, parts));
762
916
  }
763
917
  case "is-task-complete": {
764
918
  if (chunk.payload.suppressFeedback) return result;
@@ -770,36 +924,29 @@ var toUIMessage = ({ chunk, conversation, metadata }) => {
770
924
  timedOut: chunk.payload.timedOut},
771
925
  chunk.payload.maxIterationReached
772
926
  );
773
- const newMessage = {
774
- id: `is-task-complete-${chunk.runId + Date.now()}`,
775
- role: "assistant",
776
- parts: [
777
- {
778
- type: "text",
779
- text: feedback
780
- }
781
- ],
782
- metadata: {
927
+ const newMessage = newAssistantMessage(
928
+ `is-task-complete-${chunk.runId + Date.now()}`,
929
+ [{ type: "text", text: feedback }],
930
+ {
783
931
  ...metadata,
784
- completionResult: {
785
- passed: chunk.payload.passed
786
- }
932
+ completionResult: { passed: chunk.payload.passed }
787
933
  }
788
- };
934
+ );
789
935
  return [...result, newMessage];
790
936
  }
791
937
  case "source": {
792
938
  const lastMessage = result[result.length - 1];
793
939
  if (!lastMessage || lastMessage.role !== "assistant") return result;
794
- const parts = [...lastMessage.parts];
940
+ const parts = [...lastMessage.content.parts];
795
941
  if (chunk.payload.sourceType === "url") {
796
- parts.push({
942
+ const sourceUrlPart = {
797
943
  type: "source-url",
798
944
  sourceId: chunk.payload.id,
799
945
  url: chunk.payload.url || "",
800
946
  title: chunk.payload.title,
801
947
  providerMetadata: chunk.payload.providerMetadata
802
- });
948
+ };
949
+ parts.push(sourceUrlPart);
803
950
  } else if (chunk.payload.sourceType === "document") {
804
951
  parts.push({
805
952
  type: "source-document",
@@ -810,18 +957,12 @@ var toUIMessage = ({ chunk, conversation, metadata }) => {
810
957
  providerMetadata: chunk.payload.providerMetadata
811
958
  });
812
959
  }
813
- return [
814
- ...result.slice(0, -1),
815
- {
816
- ...lastMessage,
817
- parts
818
- }
819
- ];
960
+ return replaceLast(result, withParts(lastMessage, parts));
820
961
  }
821
962
  case "file": {
822
963
  const lastMessage = result[result.length - 1];
823
964
  if (!lastMessage || lastMessage.role !== "assistant") return result;
824
- const parts = [...lastMessage.parts];
965
+ const parts = [...lastMessage.content.parts];
825
966
  let url;
826
967
  if (typeof chunk.payload.data === "string") {
827
968
  url = chunk.payload.base64 ? `data:${chunk.payload.mimeType};base64,${chunk.payload.data}` : `data:${chunk.payload.mimeType},${encodeURIComponent(chunk.payload.data)}`;
@@ -835,27 +976,22 @@ var toUIMessage = ({ chunk, conversation, metadata }) => {
835
976
  url,
836
977
  providerMetadata: chunk.payload.providerMetadata
837
978
  });
838
- return [
839
- ...result.slice(0, -1),
840
- {
841
- ...lastMessage,
842
- parts
843
- }
844
- ];
979
+ return replaceLast(result, withParts(lastMessage, parts));
845
980
  }
846
981
  case "tool-call-approval": {
847
982
  const lastMessage = result[result.length - 1];
848
983
  if (!lastMessage || lastMessage.role !== "assistant") return result;
849
- const lastRequireApprovalMetadata = lastMessage.metadata?.mode === "stream" ? lastMessage.metadata?.requireApprovalMetadata : {};
850
- return [
851
- ...result.slice(0, -1),
852
- {
853
- ...lastMessage,
984
+ const existingMeta = lastMessage.content.metadata ?? {};
985
+ const lastRequireApproval = existingMeta.mode === "stream" ? existingMeta.requireApprovalMetadata ?? {} : {};
986
+ return replaceLast(result, {
987
+ ...lastMessage,
988
+ content: {
989
+ ...lastMessage.content,
854
990
  metadata: {
855
- ...lastMessage.metadata,
991
+ ...existingMeta,
856
992
  mode: "stream",
857
993
  requireApprovalMetadata: {
858
- ...lastRequireApprovalMetadata,
994
+ ...lastRequireApproval,
859
995
  [chunk.payload.toolName]: {
860
996
  toolCallId: chunk.payload.toolCallId,
861
997
  toolName: chunk.payload.toolName,
@@ -864,1099 +1000,644 @@ var toUIMessage = ({ chunk, conversation, metadata }) => {
864
1000
  }
865
1001
  }
866
1002
  }
867
- ];
1003
+ });
868
1004
  }
869
1005
  case "tool-call-suspended":
870
1006
  case "background-task-suspended": {
871
1007
  const isBgTaskEvent = chunk.type === "background-task-suspended";
872
- const location = isBgTaskEvent ? locateToolPart(result, chunk.payload.toolCallId, isBgTaskEvent) : { messageIndex: result.length - 1 };
1008
+ let suspToolCallId;
1009
+ let suspToolName;
1010
+ let suspArgs;
1011
+ let suspPayload;
1012
+ let suspSuspendedAt;
1013
+ let suspTaskId;
1014
+ if (chunk.type === "background-task-suspended") {
1015
+ suspToolCallId = chunk.payload.toolCallId;
1016
+ suspToolName = chunk.payload.toolName;
1017
+ suspArgs = chunk.payload.args;
1018
+ suspPayload = chunk.payload.suspendPayload;
1019
+ suspSuspendedAt = chunk.payload.suspendedAt;
1020
+ suspTaskId = chunk.payload.taskId;
1021
+ } else {
1022
+ suspToolCallId = chunk.payload.toolCallId;
1023
+ suspToolName = chunk.payload.toolName;
1024
+ suspArgs = chunk.payload.args;
1025
+ suspPayload = chunk.payload.suspendPayload;
1026
+ }
1027
+ const location = isBgTaskEvent ? locateToolPart(result, suspToolCallId, true) : { messageIndex: result.length - 1 };
873
1028
  if (!location) return result;
874
1029
  const { messageIndex } = location;
875
1030
  const targetMessage = result[messageIndex];
876
1031
  if (!targetMessage || targetMessage.role !== "assistant") return result;
877
- const lastSuspendedTools = targetMessage.metadata?.mode === "stream" ? targetMessage.metadata?.suspendedTools : {};
878
- const nextMessage = {
879
- ...targetMessage,
880
- metadata: mergeBgTaskMetadata(
881
- targetMessage.metadata,
882
- "stream",
883
- {
884
- resetRunningCount: isBgTaskEvent,
885
- perTaskEntry: isBgTaskEvent ? {
886
- toolCallId: chunk.payload.toolCallId,
887
- suspendedAt: chunk.payload.suspendedAt,
888
- taskId: chunk.payload.taskId
889
- } : void 0
890
- },
891
- {
892
- suspendedTools: {
893
- ...lastSuspendedTools,
894
- [chunk.payload.toolName]: {
895
- toolCallId: chunk.payload.toolCallId,
896
- toolName: chunk.payload.toolName,
897
- args: chunk.payload.args,
898
- suspendPayload: chunk.payload.suspendPayload,
899
- runId: chunk.runId
900
- }
1032
+ const existingMeta = targetMessage.content.metadata ?? {};
1033
+ const lastSuspendedTools = existingMeta.mode === "stream" ? existingMeta.suspendedTools ?? {} : {};
1034
+ const nextMetadata = mergeBgTaskMetadata(
1035
+ existingMeta,
1036
+ "stream",
1037
+ {
1038
+ resetRunningCount: isBgTaskEvent,
1039
+ perTaskEntry: isBgTaskEvent && suspTaskId ? {
1040
+ toolCallId: suspToolCallId,
1041
+ suspendedAt: suspSuspendedAt,
1042
+ taskId: suspTaskId
1043
+ } : void 0
1044
+ },
1045
+ {
1046
+ suspendedTools: {
1047
+ ...lastSuspendedTools,
1048
+ [suspToolName]: {
1049
+ toolCallId: suspToolCallId,
1050
+ toolName: suspToolName,
1051
+ args: suspArgs,
1052
+ suspendPayload: suspPayload,
1053
+ runId: chunk.runId
901
1054
  }
902
1055
  }
903
- )
904
- };
905
- return [...result.slice(0, messageIndex), nextMessage, ...result.slice(messageIndex + 1)];
1056
+ }
1057
+ );
1058
+ return replaceAt(result, messageIndex, withMetadata(targetMessage, nextMetadata));
906
1059
  }
907
1060
  case "finish":
908
1061
  case "abort": {
909
1062
  return finishStreamingAssistantMessage(result);
910
1063
  }
911
1064
  case "error": {
912
- const newMessage = {
913
- id: `error-${chunk.runId + Date.now()}`,
914
- role: "assistant",
915
- parts: [
1065
+ const newMessage = newAssistantMessage(
1066
+ `error-${chunk.runId + Date.now()}`,
1067
+ [
916
1068
  {
917
1069
  type: "text",
918
1070
  text: typeof chunk.payload.error === "string" ? chunk.payload.error : JSON.stringify(chunk.payload.error)
919
1071
  }
920
1072
  ],
921
- metadata: {
1073
+ {
922
1074
  ...metadata,
923
1075
  status: "error"
924
1076
  }
925
- };
1077
+ );
926
1078
  return [...result, newMessage];
927
1079
  }
928
- // For all other chunk types, return conversation unchanged
929
- default:
1080
+ // ----- Lifecycle / step / framing chunks (not surfaced on DB messages) -----
1081
+ case "step-start":
1082
+ case "step-finish":
1083
+ case "step-output":
1084
+ case "raw":
1085
+ case "watch":
1086
+ case "response-metadata":
1087
+ return result;
1088
+ // ----- Object chunks (object/object-result are not stored on DB messages) -----
1089
+ case "object":
1090
+ case "object-result":
930
1091
  return result;
1092
+ // ----- Background-task lifecycle markers not folded into messages -----
1093
+ case "background-task-started":
1094
+ case "background-task-cancelled":
1095
+ case "background-task-resumed":
1096
+ return result;
1097
+ // ----- Workflow lifecycle passthroughs (handled by mapWorkflowStreamChunkToWatchResult inside tool-output) -----
1098
+ case "workflow-start":
1099
+ case "workflow-finish":
1100
+ case "workflow-canceled":
1101
+ case "workflow-paused":
1102
+ case "workflow-step-start":
1103
+ case "workflow-step-finish":
1104
+ case "workflow-step-suspended":
1105
+ case "workflow-step-waiting":
1106
+ case "workflow-step-output":
1107
+ case "workflow-step-progress":
1108
+ case "workflow-step-result":
1109
+ return result;
1110
+ // ----- Nested-execution / routing / network passthroughs -----
1111
+ case "agent-execution-start":
1112
+ case "agent-execution-approval":
1113
+ case "agent-execution-suspended":
1114
+ case "agent-execution-end":
1115
+ case "agent-execution-abort":
1116
+ case "tool-execution-start":
1117
+ case "tool-execution-end":
1118
+ case "tool-execution-approval":
1119
+ case "tool-execution-suspended":
1120
+ case "tool-execution-abort":
1121
+ case "routing-agent-start":
1122
+ case "routing-agent-text-delta":
1123
+ case "routing-agent-text-start":
1124
+ case "routing-agent-end":
1125
+ case "routing-agent-abort":
1126
+ case "workflow-execution-start":
1127
+ case "workflow-execution-end":
1128
+ case "workflow-execution-suspended":
1129
+ case "workflow-execution-abort":
1130
+ case "network-execution-event-step-finish":
1131
+ case "network-execution-event-finish":
1132
+ case "network-validation-start":
1133
+ case "network-validation-end":
1134
+ case "network-object":
1135
+ case "network-object-result":
1136
+ return result;
1137
+ default:
1138
+ return assertExhaustive(chunk, result);
931
1139
  }
932
1140
  };
933
- var toUIMessageFromAgent = (chunk, conversation, metadata, parentToolCallId, parentToolName) => {
1141
+ var assertExhaustive = (_chunk, fallback) => fallback;
1142
+ var accumulateAgentChunk = (chunk, conversation, _metadata, parentToolCallId, parentToolName) => {
934
1143
  const lastMessage = conversation[conversation.length - 1];
935
1144
  if (!lastMessage || lastMessage.role !== "assistant") return conversation;
936
- const parts = [...lastMessage.parts];
1145
+ const parts = [...lastMessage.content.parts];
1146
+ const findToolPartIndex = () => parts.findIndex(
1147
+ (part) => isToolPart(part) && (parentToolCallId && part.toolInvocation.toolCallId === parentToolCallId || parentToolName && part.toolInvocation.toolName === parentToolName)
1148
+ );
937
1149
  if (chunk.type === "text-delta") {
938
1150
  const agentChunk = chunk.payload;
939
- const toolPartIndex = parts.findIndex(
940
- (part) => part.type === "dynamic-tool" && (parentToolCallId && part.toolCallId === parentToolCallId || parentToolName && part.toolName === parentToolName)
941
- );
1151
+ const toolPartIndex = findToolPartIndex();
942
1152
  if (toolPartIndex === -1) return conversation;
943
1153
  const toolPart = parts[toolPartIndex];
944
- const childMessages = toolPart?.output?.childMessages || [];
1154
+ const existingResult = toolPart.toolInvocation.result || {};
1155
+ const childMessages = existingResult.childMessages || [];
945
1156
  const lastChildMessage = childMessages[childMessages.length - 1];
946
1157
  const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.text };
947
- const nextMessages = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
1158
+ const nextChildren = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
948
1159
  parts[toolPartIndex] = {
949
1160
  ...toolPart,
950
- output: {
951
- childMessages: nextMessages
1161
+ toolInvocation: {
1162
+ ...toolPart.toolInvocation,
1163
+ result: { ...existingResult, childMessages: nextChildren }
952
1164
  }
953
1165
  };
954
1166
  } else if (chunk.type === "tool-call") {
955
1167
  const agentChunk = chunk.payload;
956
- const toolPartIndex = parts.findIndex(
957
- (part) => part.type === "dynamic-tool" && (parentToolCallId && part.toolCallId === parentToolCallId || parentToolName && part.toolName === parentToolName)
958
- );
1168
+ const toolPartIndex = findToolPartIndex();
959
1169
  if (toolPartIndex === -1) return conversation;
960
1170
  const toolPart = parts[toolPartIndex];
961
- const childMessages = toolPart?.output?.childMessages || [];
1171
+ const existingResult = toolPart.toolInvocation.result || {};
1172
+ const childMessages = existingResult.childMessages || [];
962
1173
  parts[toolPartIndex] = {
963
1174
  ...toolPart,
964
- output: {
965
- ...toolPart?.output,
966
- childMessages: [
967
- ...childMessages,
968
- {
969
- type: "tool",
970
- toolCallId: agentChunk.toolCallId,
971
- toolName: agentChunk.toolName,
972
- args: agentChunk.args
973
- }
974
- ]
1175
+ toolInvocation: {
1176
+ ...toolPart.toolInvocation,
1177
+ result: {
1178
+ ...existingResult,
1179
+ childMessages: [
1180
+ ...childMessages,
1181
+ {
1182
+ type: "tool",
1183
+ toolCallId: agentChunk.toolCallId,
1184
+ toolName: agentChunk.toolName,
1185
+ args: agentChunk.args
1186
+ }
1187
+ ]
1188
+ }
975
1189
  }
976
1190
  };
977
1191
  } else if (chunk.type === "tool-output") {
978
1192
  const agentChunk = chunk.payload;
979
- const toolPartIndex = parts.findIndex(
980
- (part) => part.type === "dynamic-tool" && (parentToolCallId && part.toolCallId === parentToolCallId || parentToolName && part.toolName === parentToolName)
981
- );
1193
+ const toolPartIndex = findToolPartIndex();
982
1194
  if (toolPartIndex === -1) return conversation;
983
1195
  const toolPart = parts[toolPartIndex];
984
1196
  if (agentChunk?.output?.type?.startsWith("workflow-")) {
985
- const childMessages = toolPart?.output?.childMessages || [];
986
- const lastToolIndex = childMessages.length - 1;
987
- const currentMessage = childMessages[lastToolIndex];
1197
+ const existingResult = toolPart.toolInvocation.result || {};
1198
+ const childMessages = existingResult.childMessages || [];
1199
+ const lastIndex = childMessages.length - 1;
1200
+ const currentMessage = childMessages[lastIndex];
988
1201
  const actualExistingWorkflowState = currentMessage?.toolOutput || {};
989
- const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(actualExistingWorkflowState, agentChunk.output);
990
- if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
1202
+ const updated = mapWorkflowStreamChunkToWatchResult(actualExistingWorkflowState, agentChunk.output);
1203
+ if (lastIndex >= 0 && childMessages[lastIndex]?.type === "tool") {
991
1204
  parts[toolPartIndex] = {
992
1205
  ...toolPart,
993
- output: {
994
- ...toolPart?.output,
995
- childMessages: [
996
- ...childMessages.slice(0, -1),
997
- {
998
- ...currentMessage,
999
- toolOutput: { ...updatedWorkflowState, runId: agentChunk.output.runId }
1000
- }
1001
- ]
1206
+ toolInvocation: {
1207
+ ...toolPart.toolInvocation,
1208
+ result: {
1209
+ ...existingResult,
1210
+ childMessages: [
1211
+ ...childMessages.slice(0, -1),
1212
+ {
1213
+ ...currentMessage,
1214
+ toolOutput: { ...updated, runId: agentChunk.output.runId }
1215
+ }
1216
+ ]
1217
+ }
1002
1218
  }
1003
1219
  };
1004
1220
  }
1005
1221
  }
1006
1222
  } else if (chunk.type === "tool-result") {
1007
1223
  const agentChunk = chunk.payload;
1008
- const toolPartIndex = parts.findIndex(
1009
- (part) => part.type === "dynamic-tool" && (parentToolCallId && part.toolCallId === parentToolCallId || parentToolName && part.toolName === parentToolName)
1010
- );
1224
+ const toolPartIndex = findToolPartIndex();
1011
1225
  if (toolPartIndex === -1) return conversation;
1012
1226
  const toolPart = parts[toolPartIndex];
1013
- const childMessages = toolPart?.output?.childMessages || [];
1014
- const lastToolIndex = childMessages.length - 1;
1227
+ const existingResult = toolPart.toolInvocation.result || {};
1228
+ const childMessages = existingResult.childMessages || [];
1229
+ const lastIndex = childMessages.length - 1;
1015
1230
  const isWorkflow = agentChunk?.toolName?.startsWith("workflow-");
1016
- if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
1231
+ if (lastIndex >= 0 && childMessages[lastIndex]?.type === "tool") {
1017
1232
  parts[toolPartIndex] = {
1018
1233
  ...toolPart,
1019
- output: {
1020
- ...toolPart?.output,
1021
- childMessages: [
1022
- ...childMessages.slice(0, -1),
1023
- {
1024
- ...childMessages[lastToolIndex],
1025
- toolOutput: isWorkflow ? { ...agentChunk.result?.result, runId: agentChunk.result?.runId } : agentChunk.result
1026
- }
1027
- ]
1234
+ toolInvocation: {
1235
+ ...toolPart.toolInvocation,
1236
+ result: {
1237
+ ...existingResult,
1238
+ childMessages: [
1239
+ ...childMessages.slice(0, -1),
1240
+ {
1241
+ ...childMessages[lastIndex],
1242
+ toolOutput: isWorkflow ? { ...agentChunk.result?.result, runId: agentChunk.result?.runId } : agentChunk.result
1243
+ }
1244
+ ]
1245
+ }
1028
1246
  }
1029
1247
  };
1030
1248
  }
1031
1249
  }
1032
- return [
1033
- ...conversation.slice(0, -1),
1034
- {
1035
- ...lastMessage,
1036
- parts
1037
- }
1038
- ];
1250
+ return replaceLast(conversation, withParts(lastMessage, parts));
1039
1251
  };
1040
- var findMessageIndexByToolCallId = (messages, toolCallId) => {
1041
- let count = 0;
1042
- for (let i = messages.length - 1; i >= 0; i--) {
1043
- const maxMessagesBack = 10;
1044
- if (count > maxMessagesBack) {
1045
- return -1;
1046
- }
1047
- const message = messages[i];
1048
- if (message.role !== "assistant") {
1049
- continue;
1050
- }
1051
- for (const part of message.parts) {
1052
- if (part.type === "dynamic-tool" && part.toolCallId === toolCallId) {
1053
- return i;
1054
- }
1055
- }
1056
- count++;
1057
- }
1058
- return -1;
1252
+ var networkMode = (metadata) => ({ ...metadata, mode: "network" });
1253
+ var findPartIndex = (parts, predicate) => parts.findIndex(predicate);
1254
+ var isDynamicToolPart = (part) => part.type === "dynamic-tool";
1255
+ var lastAssistant = (conversation) => {
1256
+ const last = conversation[conversation.length - 1];
1257
+ return last && last.role === "assistant" ? last : void 0;
1059
1258
  };
1060
- var locateToolPart = (messages, toolCallId, allowMetadataOnlyMatch) => {
1061
- const lastMessage = messages[messages.length - 1];
1062
- if (lastMessage && lastMessage.role === "assistant") {
1063
- const toolPartIndex2 = lastMessage.parts.findIndex(
1064
- (part) => (part.type === "dynamic-tool" || typeof part.type === "string" && part.type.startsWith("tool-")) && "toolCallId" in part && part.toolCallId === toolCallId
1065
- );
1066
- if (toolPartIndex2 !== -1) {
1067
- return { messageIndex: messages.length - 1, toolPartIndex: toolPartIndex2 };
1259
+ var tryParseRoutingDecision = (buffered) => {
1260
+ const trimmed = buffered.trim();
1261
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return null;
1262
+ try {
1263
+ const parsed = JSON.parse(trimmed);
1264
+ if (parsed && typeof parsed === "object") {
1265
+ return parsed;
1068
1266
  }
1267
+ return null;
1268
+ } catch {
1269
+ return null;
1069
1270
  }
1070
- const messageIndex = findMessageIndexByToolCallId(messages, toolCallId);
1071
- if (messageIndex === -1) return null;
1072
- const message = messages[messageIndex];
1073
- if (!message || message.role !== "assistant") return null;
1074
- const toolPartIndex = message.parts.findIndex(
1075
- (part) => (part.type === "dynamic-tool" || typeof part.type === "string" && part.type.startsWith("tool-")) && "toolCallId" in part && part.toolCallId === toolCallId
1076
- );
1077
- if (toolPartIndex === -1) {
1078
- return allowMetadataOnlyMatch ? { messageIndex, toolPartIndex: -1 } : null;
1079
- }
1080
- return { messageIndex, toolPartIndex };
1081
- };
1082
- var mergeBgTaskMetadata = (existing, mode, args, otherMetadata) => {
1083
- const existingAny = existing ?? {};
1084
- const existingBgTasks = existingAny.backgroundTasks ?? {};
1085
- const nextBgTasks = { ...existingBgTasks };
1086
- if (args.perTaskEntry) {
1087
- const { toolCallId, startedAt, completedAt, taskId, suspendedAt } = args.perTaskEntry;
1088
- const prev = existingBgTasks[toolCallId] ?? { taskId };
1089
- nextBgTasks[toolCallId] = {
1090
- ...prev,
1091
- taskId,
1092
- ...startedAt !== void 0 ? { startedAt } : {},
1093
- ...completedAt !== void 0 ? { completedAt } : {},
1094
- ...suspendedAt !== void 0 ? { suspendedAt } : {}
1095
- };
1096
- }
1097
- return {
1098
- ...existingAny,
1099
- ...otherMetadata ?? {},
1100
- mode,
1101
- ...args.resetRunningCount ? { runningBackgroundTasksCount: void 0 } : {},
1102
- backgroundTasks: nextBgTasks
1103
- };
1104
1271
  };
1105
-
1106
- // src/lib/ai-sdk/utils/toAssistantUIMessage.ts
1107
- var toAssistantUIMessage = (message) => {
1108
- const extendedMessage = message;
1109
- const content = message.parts.map((part) => {
1110
- if (part.type === "text") {
1111
- return {
1112
- type: "text",
1113
- text: part.text,
1114
- metadata: message.metadata
1115
- };
1116
- }
1117
- if (part.type === "reasoning") {
1118
- return {
1119
- type: "reasoning",
1120
- text: part.text,
1121
- metadata: message.metadata
1122
- };
1123
- }
1124
- if (part.type === "source-url") {
1125
- return {
1126
- type: "source",
1127
- sourceType: "url",
1128
- id: part.sourceId,
1129
- url: part.url,
1130
- title: part.title,
1131
- metadata: message.metadata
1132
- };
1133
- }
1134
- if (part.type === "source-document") {
1135
- return {
1136
- type: "file",
1137
- filename: part.filename,
1138
- mimeType: part.mediaType,
1139
- data: "",
1140
- // Source documents don't have inline data
1141
- metadata: message.metadata
1142
- };
1143
- }
1144
- if (part.type === "file") {
1145
- const type = part.mediaType.includes("image/") ? "image" : "file";
1146
- if (type === "file") {
1147
- return {
1148
- type,
1149
- mimeType: part.mediaType,
1150
- data: part.url,
1151
- // Use URL as data source
1152
- metadata: message.metadata
1153
- };
1154
- }
1155
- if (type === "image") {
1156
- return {
1157
- type,
1158
- image: part.url,
1159
- metadata: message.metadata
1160
- };
1161
- }
1162
- }
1163
- if (part.type === "dynamic-tool") {
1164
- const baseToolCall = {
1165
- type: "tool-call",
1166
- toolCallId: part.toolCallId,
1167
- toolName: part.toolName,
1168
- argsText: JSON.stringify(part.input),
1169
- args: part.input,
1170
- metadata: message.metadata
1171
- };
1172
- if (part.state === "output-error" && "errorText" in part) {
1173
- return { ...baseToolCall, result: part.errorText, isError: true };
1174
- }
1175
- if ("output" in part) {
1176
- return { ...baseToolCall, result: part.output };
1177
- }
1178
- return baseToolCall;
1179
- }
1180
- if (part.type.startsWith("tool-") && part.state !== "input-available") {
1181
- const toolName2 = "toolName" in part && typeof part.toolName === "string" ? part.toolName : part.type.substring(5);
1182
- const { suspendedToolRunId, ...cleanInput } = "input" in part ? part.input : {};
1183
- const baseToolCall = {
1184
- type: "tool-call",
1185
- toolCallId: "toolCallId" in part && typeof part.toolCallId === "string" ? part.toolCallId : "",
1186
- toolName: toolName2,
1187
- argsText: JSON.stringify(cleanInput ?? {}),
1188
- args: cleanInput ?? {},
1189
- metadata: message.metadata
1190
- };
1191
- if ("output" in part) {
1192
- return { ...baseToolCall, result: part.output };
1193
- } else if ("error" in part) {
1194
- return { ...baseToolCall, result: part.error, isError: true };
1195
- }
1196
- return baseToolCall;
1197
- }
1198
- const toolName = "toolName" in part && typeof part.toolName === "string" ? part.toolName : part.type.startsWith("tool-") ? part.type.substring(5) : "";
1199
- const requireApprovalMetadata = extendedMessage.metadata?.requireApprovalMetadata;
1200
- const suspendedTools = extendedMessage.metadata?.suspendedTools;
1201
- const partToolCallId = "toolCallId" in part && typeof part.toolCallId === "string" ? part.toolCallId : void 0;
1202
- const suspensionData = toolName ? requireApprovalMetadata?.[toolName] ?? suspendedTools?.[toolName] : void 0;
1203
- if (suspensionData) {
1204
- const { suspendedToolRunId, ...cleanInput } = "input" in part ? part.input : {};
1205
- return {
1206
- type: "tool-call",
1207
- toolCallId: partToolCallId,
1208
- toolName,
1209
- argsText: JSON.stringify(cleanInput ?? {}),
1210
- args: cleanInput,
1211
- metadata: extendedMessage.metadata
1212
- };
1213
- }
1214
- if (part.type.startsWith("data-")) {
1215
- return {
1216
- type: "data",
1217
- name: part.type.substring(5),
1218
- // Extract name from 'data-{name}'
1219
- data: part.data,
1220
- metadata: message.metadata
1221
- };
1222
- }
1223
- return {
1224
- type: "text",
1225
- text: "",
1226
- metadata: message.metadata
1227
- };
1228
- });
1229
- let status;
1230
- if (message.role === "assistant" && content.length > 0) {
1231
- const hasStreamingParts = message.parts.some(
1232
- (part) => part.type === "text" && "state" in part && part.state === "streaming" || part.type === "reasoning" && "state" in part && part.state === "streaming"
1233
- );
1234
- const hasToolCalls = message.parts.some((part) => part.type === "dynamic-tool" || part.type.startsWith("tool-"));
1235
- const hasInputAvailableTools = message.parts.some(
1236
- (part) => part.type === "dynamic-tool" && part.state === "input-available"
1237
- );
1238
- const hasErrorTools = message.parts.some(
1239
- (part) => part.type === "dynamic-tool" && part.state === "output-error" || part.type.startsWith("tool-") && "error" in part
1240
- );
1241
- if (hasStreamingParts) {
1242
- status = { type: "running" };
1243
- } else if (hasInputAvailableTools && hasToolCalls) {
1244
- status = { type: "requires-action", reason: "tool-calls" };
1245
- } else if (hasErrorTools) {
1246
- status = { type: "incomplete", reason: "error" };
1272
+ var handleRoutingAgentDelta = (chunk, conversation, metadata) => {
1273
+ const delta = chunk.payload?.text ?? "";
1274
+ if (!delta) return conversation;
1275
+ const lastMessage = lastAssistant(conversation);
1276
+ const mergeRoutingMetadata = (existing) => {
1277
+ const buffered = (existing.routingDecisionBuffer ?? "") + delta;
1278
+ const next = { ...cloneMetadata(existing), mode: "network" };
1279
+ const parsed = tryParseRoutingDecision(buffered);
1280
+ if (parsed) {
1281
+ next.routingDecision = parsed;
1282
+ delete next.routingDecisionBuffer;
1283
+ delete next.routingDecisionText;
1247
1284
  } else {
1248
- status = { type: "complete", reason: "stop" };
1285
+ next.routingDecisionBuffer = buffered;
1286
+ next.routingDecisionText = buffered;
1249
1287
  }
1250
- }
1251
- const threadMessage = {
1252
- role: message.role,
1253
- content,
1254
- id: message.id,
1255
- createdAt: extendedMessage.createdAt,
1256
- status,
1257
- attachments: extendedMessage.experimental_attachments
1288
+ return next;
1258
1289
  };
1259
- return threadMessage;
1260
- };
1261
-
1262
- // src/lib/ai-sdk/memory/resolveInitialMessages.ts
1263
- var resolveInitialMessages = (messages) => {
1264
- const messagesLength = messages.length;
1265
- return messages.map((message, index) => {
1266
- const networkPart = message.parts.find(
1267
- (part) => typeof part === "object" && part !== null && "type" in part && part.type === "text" && "text" in part && typeof part.text === "string" && part.text.includes('"isNetwork":true')
1290
+ if (!lastMessage) {
1291
+ const seed = mergeRoutingMetadata({});
1292
+ return appendAssistantMessage(
1293
+ conversation,
1294
+ `routing-agent-${chunk.payload?.runId ?? "unknown"}-${Date.now()}`,
1295
+ [],
1296
+ { ...networkMode(metadata), ...seed }
1268
1297
  );
1269
- if (networkPart && networkPart.type === "text") {
1270
- try {
1271
- const json = JSON.parse(networkPart.text);
1272
- if (json.isNetwork === true) {
1273
- const selectionReason = json.selectionReason || "";
1274
- const primitiveType = json.primitiveType || "";
1275
- const primitiveId = json.primitiveId || "";
1276
- const finalResult = json.finalResult;
1277
- const messages2 = finalResult?.messages || [];
1278
- const childMessages = [];
1279
- const toolResultMap = /* @__PURE__ */ new Map();
1280
- for (const msg of messages2) {
1281
- if (Array.isArray(msg.content)) {
1282
- for (const part of msg.content) {
1283
- if (typeof part === "object" && part.type === "tool-result") {
1284
- toolResultMap.set(part.toolCallId, part);
1285
- }
1286
- }
1287
- }
1288
- }
1289
- for (const msg of messages2) {
1290
- if (msg.type === "tool-call" && Array.isArray(msg.content)) {
1291
- for (const part of msg.content) {
1292
- if (typeof part === "object" && part.type === "tool-call") {
1293
- const toolCallContent = part;
1294
- const toolResult = toolResultMap.get(toolCallContent.toolCallId);
1295
- const isWorkflow = Boolean(toolResult?.result?.result?.steps);
1296
- childMessages.push({
1297
- type: "tool",
1298
- toolCallId: toolCallContent.toolCallId,
1299
- toolName: toolCallContent.toolName,
1300
- args: toolCallContent.args,
1301
- toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
1302
- });
1303
- }
1304
- }
1305
- }
1306
- }
1307
- if (finalResult && finalResult.text) {
1308
- childMessages.push({
1309
- type: "text",
1310
- content: finalResult.text
1311
- });
1312
- }
1313
- const result = primitiveType === "tool" ? finalResult?.result : {
1314
- childMessages,
1315
- result: finalResult?.text || ""
1316
- };
1317
- const nextMessage = {
1318
- role: "assistant",
1319
- parts: [
1320
- {
1321
- type: "dynamic-tool",
1322
- toolCallId: primitiveId,
1323
- toolName: primitiveId,
1324
- state: "output-available",
1325
- input: json.input,
1326
- output: result
1327
- }
1328
- ],
1329
- id: message.id,
1330
- metadata: {
1331
- ...message.metadata,
1332
- mode: "network",
1333
- selectionReason,
1334
- agentInput: json.input,
1335
- hasMoreMessages: index < messagesLength - 1,
1336
- from: primitiveType === "agent" ? "AGENT" : primitiveType === "tool" ? "TOOL" : "WORKFLOW"
1337
- }
1338
- };
1339
- return nextMessage;
1340
- }
1341
- } catch {
1342
- return message;
1343
- }
1344
- }
1345
- const extendedMessage = message;
1346
- const pendingToolApprovals = extendedMessage.metadata?.pendingToolApprovals;
1347
- if (pendingToolApprovals && typeof pendingToolApprovals === "object") {
1348
- const stillPending = Object.fromEntries(
1349
- Object.entries(pendingToolApprovals).filter(([_, approval]) => {
1350
- if (!approval || typeof approval !== "object" || !("toolCallId" in approval)) {
1351
- return false;
1352
- }
1353
- const toolCallId = approval.toolCallId;
1354
- return !message.parts.some(
1355
- (part) => part.toolCallId === toolCallId && (part.state === "output-available" || part.output != null)
1356
- );
1357
- })
1358
- );
1359
- return {
1360
- ...message,
1361
- metadata: {
1362
- ...message.metadata,
1363
- mode: "stream",
1364
- ...Object.keys(stillPending).length > 0 ? { requireApprovalMetadata: stillPending } : {}
1365
- }
1366
- };
1367
- }
1368
- const suspendedTools = extendedMessage.metadata?.suspendedTools;
1369
- if (suspendedTools && typeof suspendedTools === "object") {
1370
- return {
1371
- ...message,
1372
- metadata: {
1373
- ...message.metadata,
1374
- mode: "stream",
1375
- suspendedTools
1376
- }
1377
- };
1378
- }
1379
- return message;
1380
- })?.filter((message) => {
1381
- const completionModes = ["generate", "stream", "network"];
1382
- if (message.role === "assistant" && completionModes.includes(message?.metadata?.mode)) {
1383
- const meta = message.metadata;
1384
- if (meta?.isTaskCompleteResult?.suppressFeedback || meta?.completionResult?.suppressFeedback) {
1385
- return false;
1386
- }
1387
- return true;
1388
- }
1389
- return true;
1390
- });
1391
- };
1392
- var resolveToChildMessages = (messages) => {
1393
- const assistantMessage = messages.find((message) => message.role === "assistant");
1394
- if (!assistantMessage) return [];
1395
- const parts = assistantMessage.parts;
1396
- let childMessages = [];
1397
- for (const part of parts) {
1398
- const toolPart = part;
1399
- if (part.type.startsWith("tool-")) {
1400
- const toolName = part.type.substring("tool-".length);
1401
- const isWorkflow = toolName.startsWith("workflow-");
1402
- childMessages.push({
1403
- type: "tool",
1404
- toolCallId: toolPart.toolCallId,
1405
- toolName,
1406
- args: toolPart.input,
1407
- toolOutput: isWorkflow ? { ...toolPart.output?.result, runId: toolPart.output?.runId } : toolPart.output
1408
- });
1409
- }
1410
- if (part.type === "text") {
1411
- childMessages.push({
1412
- type: "text",
1413
- content: toolPart.text
1414
- });
1415
- }
1416
1298
  }
1417
- return childMessages;
1299
+ return replaceLast(conversation, withMetadata(lastMessage, mergeRoutingMetadata(lastMessage.content.metadata ?? {})));
1418
1300
  };
1419
-
1420
- // src/lib/ai-sdk/transformers/AISdkNetworkTransformer.ts
1421
- var AISdkNetworkTransformer = class {
1422
- transform({ chunk, conversation, metadata }) {
1423
- const newConversation = [...conversation];
1424
- if (chunk.type === "routing-agent-text-delta") {
1425
- return this.handleRoutingAgentConversation(chunk, newConversation);
1426
- }
1427
- if (chunk.type.startsWith("agent-execution-")) {
1428
- return this.handleAgentConversation(chunk, newConversation, metadata);
1429
- }
1430
- if (chunk.type.startsWith("workflow-execution-")) {
1431
- return this.handleWorkflowConversation(chunk, newConversation, metadata);
1432
- }
1433
- if (chunk.type.startsWith("tool-execution-")) {
1434
- return this.handleToolConversation(chunk, newConversation, metadata);
1435
- }
1436
- if (chunk.type === "network-validation-end") {
1437
- if (chunk.payload.suppressFeedback) return newConversation;
1438
- const feedback = formatCompletionFeedback(
1439
- {
1440
- complete: chunk.payload.passed,
1441
- scorers: chunk.payload.results,
1442
- totalDuration: chunk.payload.duration,
1443
- timedOut: chunk.payload.timedOut},
1444
- chunk.payload.maxIterationReached
1445
- );
1446
- const newMessage = {
1447
- id: `network-validation-end-${chunk.payload.runId}-${Date.now()}`,
1448
- role: "assistant",
1449
- parts: [
1450
- {
1451
- type: "text",
1452
- text: feedback
1453
- }
1454
- ],
1455
- metadata: {
1456
- ...metadata,
1457
- mode: "network",
1458
- completionResult: {
1459
- passed: chunk.payload.passed
1460
- }
1461
- }
1301
+ var handleAgentNetworkChunk = (chunk, conversation, metadata) => {
1302
+ if (chunk.type === "agent-execution-start") {
1303
+ const primitiveId = chunk.payload?.args?.primitiveId;
1304
+ const runId = chunk.payload.runId;
1305
+ if (!primitiveId || !runId) return conversation;
1306
+ const toolPart = {
1307
+ type: "dynamic-tool",
1308
+ toolName: primitiveId,
1309
+ toolCallId: runId,
1310
+ state: "input-available",
1311
+ input: chunk.payload.args
1312
+ };
1313
+ return appendAssistantMessage(conversation, `agent-execution-start-${runId}-${Date.now()}`, [toolPart], {
1314
+ ...networkMode(metadata),
1315
+ selectionReason: chunk.payload?.args?.selectionReason || "",
1316
+ agentInput: chunk.payload?.args?.task,
1317
+ from: "AGENT"
1318
+ });
1319
+ }
1320
+ if (chunk.type === "agent-execution-end") {
1321
+ const lastMessage = lastAssistant(conversation);
1322
+ if (!lastMessage) return conversation;
1323
+ const parts = [...lastMessage.content.parts];
1324
+ const toolPartIndex = findPartIndex(parts, (part) => isDynamicToolPart(part));
1325
+ if (toolPartIndex !== -1) {
1326
+ const toolPart = parts[toolPartIndex];
1327
+ const currentOutput = toolPart.output;
1328
+ parts[toolPartIndex] = {
1329
+ type: "dynamic-tool",
1330
+ toolName: toolPart.toolName,
1331
+ toolCallId: toolPart.toolCallId,
1332
+ state: "output-available",
1333
+ input: toolPart.input,
1334
+ output: { ...currentOutput, result: currentOutput?.result || chunk.payload?.result || "" }
1462
1335
  };
1463
- return [...newConversation, newMessage];
1464
- }
1465
- if (chunk.type === "network-execution-event-step-finish") {
1466
- const lastMessage = newConversation[newConversation.length - 1];
1467
- if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
1468
- const agentChunk = chunk.payload;
1469
- const parts = [...lastMessage.parts];
1470
- const textPartIndex = parts.findIndex((part) => part.type === "text");
1471
- if (textPartIndex === -1) {
1472
- parts.push({
1473
- type: "text",
1474
- text: agentChunk.result,
1475
- state: "done"
1476
- });
1477
- return [
1478
- ...newConversation.slice(0, -1),
1479
- {
1480
- ...lastMessage,
1481
- parts
1482
- }
1483
- ];
1484
- }
1485
- const textPart = parts[textPartIndex];
1486
- if (textPart.type === "text") {
1487
- parts[textPartIndex] = {
1488
- ...textPart,
1489
- state: "done"
1490
- };
1491
- return [
1492
- ...newConversation.slice(0, -1),
1493
- {
1494
- ...lastMessage,
1495
- parts
1496
- }
1497
- ];
1498
- }
1499
- return newConversation;
1500
1336
  }
1501
- return newConversation;
1337
+ return replaceLast(conversation, withParts(lastMessage, parts));
1502
1338
  }
1503
- handleRoutingAgentConversation = (chunk, newConversation) => {
1504
- const lastMessage = newConversation[newConversation.length - 1];
1505
- if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
1339
+ if (chunk.type.startsWith("agent-execution-event-")) {
1340
+ const lastMessage = lastAssistant(conversation);
1341
+ if (!lastMessage) return conversation;
1506
1342
  const agentChunk = chunk.payload;
1507
- const parts = [...lastMessage.parts];
1508
- const textPartIndex = parts.findIndex((part) => part.type === "text");
1509
- if (textPartIndex === -1) {
1510
- parts.push({
1511
- type: "text",
1512
- text: agentChunk.text,
1513
- state: "streaming"
1514
- });
1515
- return [
1516
- ...newConversation.slice(0, -1),
1517
- {
1518
- ...lastMessage,
1519
- parts
1520
- }
1521
- ];
1522
- }
1523
- const textPart = parts[textPartIndex];
1524
- if (textPart.type === "text") {
1525
- parts[textPartIndex] = {
1526
- ...textPart,
1527
- text: textPart.text + agentChunk.text,
1528
- state: "streaming"
1529
- };
1530
- return [
1531
- ...newConversation.slice(0, -1),
1532
- {
1533
- ...lastMessage,
1534
- parts
1535
- }
1536
- ];
1537
- }
1538
- return newConversation;
1539
- };
1540
- handleAgentConversation = (chunk, newConversation, metadata) => {
1541
- if (chunk.type === "agent-execution-start") {
1542
- const primitiveId = chunk.payload?.args?.primitiveId;
1543
- const runId = chunk.payload.runId;
1544
- if (!primitiveId || !runId) return newConversation;
1545
- const newMessage = {
1546
- id: `agent-execution-start-${runId}-${Date.now()}`,
1547
- role: "assistant",
1548
- parts: [
1549
- {
1550
- type: "dynamic-tool",
1551
- toolName: primitiveId,
1552
- toolCallId: runId,
1553
- state: "input-available",
1554
- input: chunk.payload.args
1555
- }
1556
- ],
1557
- metadata: {
1558
- ...metadata,
1559
- selectionReason: chunk.payload?.args?.selectionReason || "",
1560
- agentInput: chunk.payload?.args?.task,
1561
- mode: "network",
1562
- from: "AGENT"
1563
- }
1343
+ const parts = [...lastMessage.content.parts];
1344
+ const toolPartIndex = findPartIndex(parts, (part) => isDynamicToolPart(part));
1345
+ if (toolPartIndex === -1) return conversation;
1346
+ const toolPart = parts[toolPartIndex];
1347
+ if (agentChunk.type === "text-delta") {
1348
+ const childMessages = toolPart?.output?.childMessages || [];
1349
+ const lastChildMessage = childMessages[childMessages.length - 1];
1350
+ const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.payload.text };
1351
+ const nextMessages = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
1352
+ parts[toolPartIndex] = {
1353
+ ...toolPart,
1354
+ output: { childMessages: nextMessages }
1564
1355
  };
1565
- return [...newConversation, newMessage];
1566
- }
1567
- if (chunk.type === "agent-execution-approval") {
1568
- const lastMessage = newConversation[newConversation.length - 1];
1569
- if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
1570
- const lastRequireApprovalMetadata = lastMessage.metadata?.mode === "network" ? lastMessage.metadata?.requireApprovalMetadata : {};
1571
- return [
1572
- ...newConversation.slice(0, -1),
1573
- {
1574
- ...lastMessage,
1575
- metadata: {
1576
- ...lastMessage.metadata,
1577
- mode: "network",
1578
- requireApprovalMetadata: {
1579
- ...lastRequireApprovalMetadata,
1580
- [chunk.payload.toolName]: {
1581
- toolCallId: chunk.payload.toolCallId,
1582
- toolName: chunk.payload.toolName,
1583
- args: chunk.payload.args,
1584
- runId: chunk.payload.runId
1585
- }
1586
- }
1587
- }
1588
- }
1589
- ];
1590
- }
1591
- if (chunk.type === "agent-execution-suspended") {
1592
- const lastMessage = newConversation[newConversation.length - 1];
1593
- if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
1594
- const lastSuspendedTools = lastMessage.metadata?.mode === "network" ? lastMessage.metadata?.suspendedTools : {};
1595
- return [
1596
- ...newConversation.slice(0, -1),
1597
- {
1598
- ...lastMessage,
1599
- metadata: {
1600
- ...lastMessage.metadata,
1601
- mode: "network",
1602
- suspendedTools: {
1603
- ...lastSuspendedTools,
1604
- [chunk.payload.toolName]: {
1605
- toolCallId: chunk.payload.toolCallId,
1606
- toolName: chunk.payload.toolName,
1607
- args: chunk.payload.args,
1608
- suspendPayload: chunk.payload.suspendPayload,
1609
- runId: chunk.payload.runId
1610
- }
1356
+ } else if (agentChunk.type === "tool-call") {
1357
+ const childMessages = toolPart?.output?.childMessages || [];
1358
+ parts[toolPartIndex] = {
1359
+ ...toolPart,
1360
+ output: {
1361
+ ...toolPart?.output,
1362
+ childMessages: [
1363
+ ...childMessages,
1364
+ {
1365
+ type: "tool",
1366
+ toolCallId: agentChunk.payload.toolCallId,
1367
+ toolName: agentChunk.payload.toolName,
1368
+ args: agentChunk.payload.args
1611
1369
  }
1612
- }
1370
+ ]
1613
1371
  }
1614
- ];
1615
- }
1616
- if (chunk.type === "agent-execution-end") {
1617
- const lastMessage = newConversation[newConversation.length - 1];
1618
- if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
1619
- const parts = [...lastMessage.parts];
1620
- const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
1621
- if (toolPartIndex !== -1) {
1622
- const toolPart = parts[toolPartIndex];
1623
- if (toolPart.type === "dynamic-tool") {
1624
- const currentOutput = toolPart.output;
1372
+ };
1373
+ } else if (agentChunk.type === "tool-output") {
1374
+ if (agentChunk.payload?.output?.type?.startsWith("workflow-")) {
1375
+ const childMessages = toolPart?.output?.childMessages || [];
1376
+ const lastToolIndex = childMessages.length - 1;
1377
+ const currentMessage = childMessages[lastToolIndex];
1378
+ const actualExistingWorkflowState = currentMessage?.toolOutput || {};
1379
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(
1380
+ actualExistingWorkflowState,
1381
+ agentChunk.payload.output
1382
+ );
1383
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
1625
1384
  parts[toolPartIndex] = {
1626
- type: "dynamic-tool",
1627
- toolName: toolPart.toolName,
1628
- toolCallId: toolPart.toolCallId,
1629
- state: "output-available",
1630
- input: toolPart.input,
1385
+ ...toolPart,
1631
1386
  output: {
1632
- ...currentOutput,
1633
- result: currentOutput?.result || chunk.payload?.result || ""
1387
+ ...toolPart?.output,
1388
+ childMessages: [...childMessages.slice(0, -1), { ...currentMessage, toolOutput: updatedWorkflowState }]
1634
1389
  }
1635
1390
  };
1636
1391
  }
1637
1392
  }
1638
- return [
1639
- ...newConversation.slice(0, -1),
1640
- {
1641
- ...lastMessage,
1642
- parts
1643
- }
1644
- ];
1645
- }
1646
- if (chunk.type.startsWith("agent-execution-event-")) {
1647
- const lastMessage = newConversation[newConversation.length - 1];
1648
- if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
1649
- const agentChunk = chunk.payload;
1650
- const parts = [...lastMessage.parts];
1651
- const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
1652
- if (toolPartIndex === -1) return newConversation;
1653
- const toolPart = parts[toolPartIndex];
1654
- if (agentChunk.type === "text-delta") {
1655
- const childMessages = toolPart?.output?.childMessages || [];
1656
- const lastChildMessage = childMessages[childMessages.length - 1];
1657
- const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.payload.text };
1658
- const nextMessages = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
1659
- parts[toolPartIndex] = {
1660
- ...toolPart,
1661
- output: {
1662
- childMessages: nextMessages
1663
- }
1664
- };
1665
- } else if (agentChunk.type === "tool-call") {
1666
- const childMessages = toolPart?.output?.childMessages || [];
1393
+ } else if (agentChunk.type === "tool-result") {
1394
+ const childMessages = toolPart?.output?.childMessages || [];
1395
+ const lastToolIndex = childMessages.length - 1;
1396
+ const isWorkflow = Boolean(agentChunk.payload?.result?.result?.steps);
1397
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
1667
1398
  parts[toolPartIndex] = {
1668
1399
  ...toolPart,
1669
1400
  output: {
1670
1401
  ...toolPart?.output,
1671
1402
  childMessages: [
1672
- ...childMessages,
1403
+ ...childMessages.slice(0, -1),
1673
1404
  {
1674
- type: "tool",
1675
- toolCallId: agentChunk.payload.toolCallId,
1676
- toolName: agentChunk.payload.toolName,
1677
- args: agentChunk.payload.args
1405
+ ...childMessages[lastToolIndex],
1406
+ toolOutput: isWorkflow ? agentChunk.payload.result.result : agentChunk.payload.result
1678
1407
  }
1679
1408
  ]
1680
1409
  }
1681
1410
  };
1682
- } else if (agentChunk.type === "tool-output") {
1683
- if (agentChunk.payload?.output?.type?.startsWith("workflow-")) {
1684
- const childMessages = toolPart?.output?.childMessages || [];
1685
- const lastToolIndex = childMessages.length - 1;
1686
- const currentMessage = childMessages[lastToolIndex];
1687
- const actualExistingWorkflowState = currentMessage?.toolOutput || {};
1688
- const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(
1689
- actualExistingWorkflowState,
1690
- agentChunk.payload.output
1691
- );
1692
- if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
1693
- parts[toolPartIndex] = {
1694
- ...toolPart,
1695
- output: {
1696
- ...toolPart?.output,
1697
- childMessages: [
1698
- ...childMessages.slice(0, -1),
1699
- {
1700
- ...currentMessage,
1701
- toolOutput: updatedWorkflowState
1702
- }
1703
- ]
1704
- }
1705
- };
1411
+ }
1412
+ }
1413
+ return replaceLast(conversation, withParts(lastMessage, parts));
1414
+ }
1415
+ return conversation;
1416
+ };
1417
+ var handleWorkflowNetworkChunk = (chunk, conversation, metadata) => {
1418
+ if (chunk.type === "workflow-execution-start") {
1419
+ const primitiveId = chunk.payload?.args?.primitiveId;
1420
+ const runId = chunk.payload.runId;
1421
+ if (!primitiveId || !runId) return conversation;
1422
+ let agentInput;
1423
+ try {
1424
+ agentInput = JSON.parse(chunk.payload?.args?.prompt);
1425
+ } catch {
1426
+ agentInput = chunk.payload?.args?.prompt;
1427
+ }
1428
+ const toolPart = {
1429
+ type: "dynamic-tool",
1430
+ toolName: primitiveId,
1431
+ toolCallId: runId,
1432
+ state: "input-available",
1433
+ input: chunk.payload.args
1434
+ };
1435
+ return appendAssistantMessage(conversation, `workflow-start-${runId}-${Date.now()}`, [toolPart], {
1436
+ ...networkMode(metadata),
1437
+ selectionReason: chunk.payload?.args?.selectionReason || "",
1438
+ from: "WORKFLOW",
1439
+ agentInput
1440
+ });
1441
+ }
1442
+ if (chunk.type === "workflow-execution-suspended") {
1443
+ const lastMessage = lastAssistant(conversation);
1444
+ if (!lastMessage) return conversation;
1445
+ const existing = lastMessage.content.metadata?.suspendedTools ?? {};
1446
+ return replaceLast(
1447
+ conversation,
1448
+ withMetadata(lastMessage, {
1449
+ ...cloneMetadata(lastMessage.content.metadata),
1450
+ mode: "network",
1451
+ suspendedTools: {
1452
+ ...existing,
1453
+ [chunk.payload.toolName]: {
1454
+ toolCallId: chunk.payload.toolCallId,
1455
+ toolName: chunk.payload.toolName,
1456
+ args: chunk.payload.args,
1457
+ suspendPayload: chunk.payload.suspendPayload,
1458
+ runId: chunk.payload.runId
1706
1459
  }
1707
1460
  }
1708
- } else if (agentChunk.type === "tool-result") {
1709
- const childMessages = toolPart?.output?.childMessages || [];
1710
- const lastToolIndex = childMessages.length - 1;
1711
- const isWorkflow = Boolean(agentChunk.payload?.result?.result?.steps);
1712
- if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
1713
- parts[toolPartIndex] = {
1714
- ...toolPart,
1715
- output: {
1716
- ...toolPart?.output,
1717
- childMessages: [
1718
- ...childMessages.slice(0, -1),
1719
- {
1720
- ...childMessages[lastToolIndex],
1721
- toolOutput: isWorkflow ? agentChunk.payload.result.result : agentChunk.payload.result
1722
- }
1723
- ]
1724
- }
1725
- };
1726
- }
1727
- }
1728
- return [
1729
- ...newConversation.slice(0, -1),
1461
+ })
1462
+ );
1463
+ }
1464
+ if (chunk.type.startsWith("workflow-execution-event-")) {
1465
+ const lastMessage = lastAssistant(conversation);
1466
+ if (!lastMessage) return conversation;
1467
+ const parts = [...lastMessage.content.parts];
1468
+ const toolPartIndex = findPartIndex(parts, (part) => isDynamicToolPart(part));
1469
+ if (toolPartIndex === -1) return conversation;
1470
+ const toolPart = parts[toolPartIndex];
1471
+ const existingWorkflowState = toolPart.output || {};
1472
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, chunk.payload);
1473
+ parts[toolPartIndex] = { ...toolPart, output: updatedWorkflowState };
1474
+ return replaceLast(conversation, withParts(lastMessage, parts));
1475
+ }
1476
+ return conversation;
1477
+ };
1478
+ var handleToolNetworkChunk = (chunk, conversation, metadata) => {
1479
+ if (chunk.type === "tool-execution-start") {
1480
+ const argsData = chunk.payload.args;
1481
+ const nestedArgs = argsData.args || {};
1482
+ const lastMessage = lastAssistant(conversation);
1483
+ const toolPart = {
1484
+ type: "dynamic-tool",
1485
+ toolName: argsData.toolName || "unknown",
1486
+ toolCallId: argsData.toolCallId || "unknown",
1487
+ state: "input-available",
1488
+ input: nestedArgs
1489
+ };
1490
+ if (!lastMessage) {
1491
+ return appendAssistantMessage(
1492
+ conversation,
1493
+ `tool-start-${chunk.payload.runId}-${Date.now()}`,
1494
+ [toolPart],
1730
1495
  {
1731
- ...lastMessage,
1732
- parts
1496
+ ...networkMode(metadata),
1497
+ selectionReason: metadata.mode === "network" ? metadata.selectionReason || argsData.selectionReason : "",
1498
+ agentInput: nestedArgs
1733
1499
  }
1734
- ];
1500
+ );
1735
1501
  }
1736
- return newConversation;
1737
- };
1738
- handleWorkflowConversation = (chunk, newConversation, metadata) => {
1739
- if (chunk.type === "workflow-execution-start") {
1740
- const primitiveId = chunk.payload?.args?.primitiveId;
1741
- const runId = chunk.payload.runId;
1742
- if (!primitiveId || !runId) return newConversation;
1743
- let agentInput;
1744
- try {
1745
- agentInput = JSON.parse(chunk?.payload?.args?.prompt);
1746
- } catch {
1747
- agentInput = chunk?.payload?.args?.prompt;
1748
- }
1749
- const newMessage = {
1750
- id: `workflow-start-${runId}-${Date.now()}`,
1751
- role: "assistant",
1752
- parts: [
1753
- {
1754
- type: "dynamic-tool",
1755
- toolName: primitiveId,
1756
- toolCallId: runId,
1757
- state: "input-available",
1758
- input: chunk.payload.args
1502
+ const parts = [...lastMessage.content.parts, toolPart];
1503
+ return replaceLast(conversation, withParts(lastMessage, parts));
1504
+ }
1505
+ if (chunk.type === "tool-execution-approval") {
1506
+ const lastMessage = lastAssistant(conversation);
1507
+ if (!lastMessage) return conversation;
1508
+ const existing = lastMessage.content.metadata?.requireApprovalMetadata ?? {};
1509
+ return replaceLast(
1510
+ conversation,
1511
+ withMetadata(lastMessage, {
1512
+ ...cloneMetadata(lastMessage.content.metadata),
1513
+ mode: "network",
1514
+ requireApprovalMetadata: {
1515
+ ...existing,
1516
+ [chunk.payload.toolName]: {
1517
+ toolCallId: chunk.payload.toolCallId,
1518
+ toolName: chunk.payload.toolName,
1519
+ args: chunk.payload.args,
1520
+ runId: chunk.payload.runId
1759
1521
  }
1760
- ],
1761
- metadata: {
1762
- ...metadata,
1763
- selectionReason: chunk.payload?.args?.selectionReason || "",
1764
- from: "WORKFLOW",
1765
- mode: "network",
1766
- agentInput
1767
1522
  }
1768
- };
1769
- return [...newConversation, newMessage];
1770
- }
1771
- if (chunk.type === "workflow-execution-suspended") {
1772
- const lastMessage = newConversation[newConversation.length - 1];
1773
- if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
1774
- const lastSuspendedTools = lastMessage.metadata?.mode === "network" ? lastMessage.metadata?.suspendedTools : {};
1775
- return [
1776
- ...newConversation.slice(0, -1),
1777
- {
1778
- ...lastMessage,
1779
- metadata: {
1780
- ...lastMessage.metadata,
1781
- mode: "network",
1782
- suspendedTools: {
1783
- ...lastSuspendedTools,
1784
- [chunk.payload.toolName]: {
1785
- toolCallId: chunk.payload.toolCallId,
1786
- toolName: chunk.payload.toolName,
1787
- args: chunk.payload.args,
1788
- suspendPayload: chunk.payload.suspendPayload,
1789
- runId: chunk.payload.runId
1790
- }
1791
- }
1523
+ })
1524
+ );
1525
+ }
1526
+ if (chunk.type === "tool-execution-suspended") {
1527
+ const lastMessage = lastAssistant(conversation);
1528
+ if (!lastMessage) return conversation;
1529
+ const existing = lastMessage.content.metadata?.suspendedTools ?? {};
1530
+ return replaceLast(
1531
+ conversation,
1532
+ withMetadata(lastMessage, {
1533
+ ...cloneMetadata(lastMessage.content.metadata),
1534
+ mode: "network",
1535
+ suspendedTools: {
1536
+ ...existing,
1537
+ [chunk.payload.toolName]: {
1538
+ toolCallId: chunk.payload.toolCallId,
1539
+ toolName: chunk.payload.toolName,
1540
+ args: chunk.payload.args,
1541
+ suspendPayload: chunk.payload.suspendPayload,
1542
+ runId: chunk.payload.runId
1792
1543
  }
1793
1544
  }
1794
- ];
1795
- }
1796
- if (chunk.type.startsWith("workflow-execution-event-")) {
1797
- const lastMessage = newConversation[newConversation.length - 1];
1798
- if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
1799
- const parts = [...lastMessage.parts];
1800
- const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
1801
- if (toolPartIndex === -1) return newConversation;
1545
+ })
1546
+ );
1547
+ }
1548
+ if (chunk.type === "tool-execution-end") {
1549
+ const lastMessage = lastAssistant(conversation);
1550
+ if (!lastMessage) return conversation;
1551
+ const parts = [...lastMessage.content.parts];
1552
+ const toolPartIndex = findPartIndex(
1553
+ parts,
1554
+ (part) => isDynamicToolPart(part) && part.toolCallId === chunk.payload.toolCallId
1555
+ );
1556
+ if (toolPartIndex !== -1) {
1802
1557
  const toolPart = parts[toolPartIndex];
1803
- if (toolPart.type !== "dynamic-tool") return newConversation;
1804
- const existingWorkflowState = toolPart.output || {};
1805
- const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, chunk.payload);
1558
+ const currentOutput = toolPart.output;
1806
1559
  parts[toolPartIndex] = {
1807
- ...toolPart,
1808
- output: updatedWorkflowState
1560
+ type: "dynamic-tool",
1561
+ toolName: toolPart.toolName,
1562
+ toolCallId: toolPart.toolCallId,
1563
+ state: "output-available",
1564
+ input: toolPart.input,
1565
+ output: currentOutput?.result || chunk.payload?.result || ""
1809
1566
  };
1810
- return [
1811
- ...newConversation.slice(0, -1),
1812
- {
1813
- ...lastMessage,
1814
- parts
1815
- }
1816
- ];
1817
1567
  }
1818
- return newConversation;
1819
- };
1820
- handleToolConversation = (chunk, newConversation, metadata) => {
1821
- if (chunk.type === "tool-execution-start") {
1822
- const { args: argsData } = chunk.payload;
1823
- const lastMessage = newConversation[newConversation.length - 1];
1824
- const nestedArgs = argsData.args || {};
1825
- if (!lastMessage || lastMessage.role !== "assistant") {
1826
- const newMessage = {
1827
- id: `tool-start-${chunk.runId}-${Date.now()}`,
1828
- role: "assistant",
1829
- parts: [
1830
- {
1831
- type: "dynamic-tool",
1832
- toolName: argsData.toolName || "unknown",
1833
- toolCallId: argsData.toolCallId || "unknown",
1834
- state: "input-available",
1835
- input: nestedArgs
1836
- }
1837
- ],
1838
- metadata: {
1839
- ...metadata,
1840
- selectionReason: metadata?.mode === "network" ? metadata.selectionReason || argsData.selectionReason : "",
1841
- mode: "network",
1842
- agentInput: nestedArgs
1843
- }
1844
- };
1845
- return [...newConversation, newMessage];
1568
+ return replaceLast(conversation, withParts(lastMessage, parts));
1569
+ }
1570
+ return conversation;
1571
+ };
1572
+ var accumulateNetworkChunk = ({
1573
+ chunk,
1574
+ conversation,
1575
+ metadata
1576
+ }) => {
1577
+ const newConversation = [...conversation];
1578
+ if (chunk.type === "routing-agent-text-delta") {
1579
+ return handleRoutingAgentDelta(chunk, newConversation, metadata);
1580
+ }
1581
+ if (chunk.type.startsWith("agent-execution-")) {
1582
+ return handleAgentNetworkChunk(chunk, newConversation, metadata);
1583
+ }
1584
+ if (chunk.type.startsWith("workflow-execution-")) {
1585
+ return handleWorkflowNetworkChunk(chunk, newConversation, metadata);
1586
+ }
1587
+ if (chunk.type.startsWith("tool-execution-")) {
1588
+ return handleToolNetworkChunk(chunk, newConversation, metadata);
1589
+ }
1590
+ if (chunk.type === "network-validation-end") {
1591
+ if (chunk.payload.suppressFeedback) return newConversation;
1592
+ const feedback = formatCompletionFeedback(
1593
+ {
1594
+ complete: chunk.payload.passed,
1595
+ scorers: chunk.payload.results,
1596
+ totalDuration: chunk.payload.duration,
1597
+ timedOut: chunk.payload.timedOut},
1598
+ chunk.payload.maxIterationReached
1599
+ );
1600
+ const textPart = { type: "text", text: feedback };
1601
+ return appendAssistantMessage(
1602
+ newConversation,
1603
+ `network-validation-end-${chunk.payload.runId}-${Date.now()}`,
1604
+ [textPart],
1605
+ {
1606
+ ...networkMode(metadata),
1607
+ completionResult: { passed: chunk.payload.passed }
1846
1608
  }
1847
- const parts = [...lastMessage.parts];
1848
- parts.push({
1849
- type: "dynamic-tool",
1850
- toolName: argsData.toolName || "unknown",
1851
- toolCallId: argsData.toolCallId || "unknown",
1852
- state: "input-available",
1853
- input: nestedArgs
1854
- });
1855
- return [
1856
- ...newConversation.slice(0, -1),
1857
- {
1858
- ...lastMessage,
1859
- parts
1860
- }
1861
- ];
1862
- }
1863
- if (chunk.type === "tool-execution-approval") {
1864
- const lastMessage = newConversation[newConversation.length - 1];
1865
- if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
1866
- const lastRequireApprovalMetadata = lastMessage.metadata?.mode === "network" ? lastMessage.metadata?.requireApprovalMetadata : {};
1867
- return [
1868
- ...newConversation.slice(0, -1),
1869
- {
1870
- ...lastMessage,
1871
- metadata: {
1872
- ...lastMessage.metadata,
1873
- mode: "network",
1874
- requireApprovalMetadata: {
1875
- ...lastRequireApprovalMetadata,
1876
- [chunk.payload.toolName]: {
1877
- toolCallId: chunk.payload.toolCallId,
1878
- toolName: chunk.payload.toolName,
1879
- args: chunk.payload.args,
1880
- runId: chunk.payload.runId
1881
- }
1882
- }
1883
- }
1884
- }
1885
- ];
1886
- }
1887
- if (chunk.type === "tool-execution-suspended") {
1888
- const lastMessage = newConversation[newConversation.length - 1];
1889
- if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
1890
- const lastSuspendedTools = lastMessage.metadata?.mode === "network" ? lastMessage.metadata?.suspendedTools : {};
1891
- return [
1892
- ...newConversation.slice(0, -1),
1893
- {
1894
- ...lastMessage,
1895
- metadata: {
1896
- ...lastMessage.metadata,
1897
- mode: "network",
1898
- suspendedTools: {
1899
- ...lastSuspendedTools,
1900
- [chunk.payload.toolName]: {
1901
- toolCallId: chunk.payload.toolCallId,
1902
- toolName: chunk.payload.toolName,
1903
- args: chunk.payload.args,
1904
- suspendPayload: chunk.payload.suspendPayload,
1905
- runId: chunk.payload.runId
1906
- }
1907
- }
1908
- }
1909
- }
1910
- ];
1609
+ );
1610
+ }
1611
+ if (chunk.type === "network-execution-event-step-finish") {
1612
+ const lastMessage = lastAssistant(newConversation);
1613
+ if (!lastMessage) return newConversation;
1614
+ const agentChunk = chunk.payload;
1615
+ const parts = [...lastMessage.content.parts];
1616
+ const textPartIndex = findPartIndex(parts, (part) => part.type === "text");
1617
+ if (textPartIndex === -1) {
1618
+ parts.push({ type: "text", text: agentChunk.result, state: "done" });
1619
+ return replaceLast(newConversation, withParts(lastMessage, parts));
1911
1620
  }
1912
- if (chunk.type === "tool-execution-end") {
1913
- const lastMessage = newConversation[newConversation.length - 1];
1914
- if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
1915
- const parts = [...lastMessage.parts];
1916
- const toolPartIndex = parts.findIndex(
1917
- (part) => part.type === "dynamic-tool" && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
1918
- );
1919
- if (toolPartIndex !== -1) {
1920
- const toolPart = parts[toolPartIndex];
1921
- if (toolPart.type === "dynamic-tool") {
1922
- const currentOutput = toolPart.output;
1923
- parts[toolPartIndex] = {
1924
- type: "dynamic-tool",
1925
- toolName: toolPart.toolName,
1926
- toolCallId: toolPart.toolCallId,
1927
- state: "output-available",
1928
- input: toolPart.input,
1929
- output: currentOutput?.result || chunk.payload?.result || ""
1930
- };
1931
- }
1932
- }
1933
- return [
1934
- ...newConversation.slice(0, -1),
1935
- {
1936
- ...lastMessage,
1937
- parts
1938
- }
1939
- ];
1621
+ const textPart = parts[textPartIndex];
1622
+ if (textPart.type === "text") {
1623
+ parts[textPartIndex] = {
1624
+ ...textPart,
1625
+ state: "done"
1626
+ };
1627
+ return replaceLast(newConversation, withParts(lastMessage, parts));
1940
1628
  }
1941
1629
  return newConversation;
1942
- };
1630
+ }
1631
+ return newConversation;
1943
1632
  };
1944
1633
 
1945
- // src/lib/ai-sdk/utils/fromCoreUserMessageToUIMessage.tsx
1946
- var fromCoreUserMessageToUIMessage = (coreUserMessage) => {
1634
+ // src/lib/mastra-db/fromCoreUserMessage.ts
1635
+ var fromCoreUserMessageToMastraDBMessage = (coreUserMessage) => {
1947
1636
  const id = `user-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
1948
- const parts = typeof coreUserMessage.content === "string" ? [
1949
- {
1950
- type: "text",
1951
- text: coreUserMessage.content
1952
- }
1953
- ] : coreUserMessage.content.map((part) => {
1637
+ const parts = typeof coreUserMessage.content === "string" ? [{ type: "text", text: coreUserMessage.content }] : coreUserMessage.content.map((part) => {
1954
1638
  switch (part.type) {
1955
1639
  case "text": {
1956
- return {
1957
- type: "text",
1958
- text: part.text
1959
- };
1640
+ return { type: "text", text: part.text };
1960
1641
  }
1961
1642
  case "image": {
1962
1643
  const url = typeof part.image === "string" ? part.image : part.image instanceof URL ? part.image.toString() : "";
@@ -1984,23 +1665,35 @@ var fromCoreUserMessageToUIMessage = (coreUserMessage) => {
1984
1665
  return {
1985
1666
  id,
1986
1667
  role: "user",
1987
- parts
1668
+ createdAt: /* @__PURE__ */ new Date(),
1669
+ content: {
1670
+ format: 2,
1671
+ parts
1672
+ }
1988
1673
  };
1989
1674
  };
1990
1675
 
1991
1676
  // src/agent/extractRunIdFromMessages.ts
1677
+ var isRecord = (value) => value !== null && typeof value === "object";
1678
+ var runIdMetadataKeys = ["pendingToolApprovals", "requireApprovalMetadata", "suspendedTools"];
1679
+ var isRunIdMetadataSource = (value) => isRecord(value) && Object.values(value).every((entry) => isRecord(entry));
1680
+ var getRunIdMetadataSources = (metadata) => {
1681
+ if (!isRecord(metadata)) return [];
1682
+ const sources = [];
1683
+ for (const key of runIdMetadataKeys) {
1684
+ const source = metadata[key];
1685
+ if (isRunIdMetadataSource(source)) {
1686
+ sources.push(source);
1687
+ }
1688
+ }
1689
+ return sources;
1690
+ };
1992
1691
  var extractRunIdFromMessages = (messages) => {
1993
1692
  for (const message of messages) {
1994
- const metadataSources = [
1995
- message.metadata?.pendingToolApprovals,
1996
- message.metadata?.requireApprovalMetadata,
1997
- message.metadata?.suspendedTools
1998
- ];
1999
- for (const source of metadataSources) {
2000
- if (!source || typeof source !== "object") continue;
2001
- for (const suspensionData of Object.values(source)) {
2002
- if (suspensionData && typeof suspensionData === "object" && typeof suspensionData.runId === "string" && suspensionData.runId.length > 0) {
2003
- return suspensionData.runId;
1693
+ for (const source of getRunIdMetadataSources(message.content?.metadata)) {
1694
+ for (const entry of Object.values(source)) {
1695
+ if (isRecord(entry) && typeof entry.runId === "string" && entry.runId.length > 0) {
1696
+ return entry.runId;
2004
1697
  }
2005
1698
  }
2006
1699
  }
@@ -2025,11 +1718,12 @@ function convertSignalDataToBase64String(content) {
2025
1718
  var extractPendingToolApprovalIdsFromMessages = (messages) => {
2026
1719
  const pendingToolApprovalIds = /* @__PURE__ */ new Set();
2027
1720
  for (const message of messages) {
2028
- const metadata = message.metadata;
1721
+ const metadata = message.content?.metadata;
1722
+ if (!metadata) continue;
2029
1723
  const metadataSources = [
2030
- metadata?.pendingToolApprovals,
2031
- metadata?.requireApprovalMetadata,
2032
- metadata?.suspendedTools
1724
+ metadata.pendingToolApprovals,
1725
+ metadata.requireApprovalMetadata,
1726
+ metadata.suspendedTools
2033
1727
  ];
2034
1728
  for (const source of metadataSources) {
2035
1729
  if (!source || typeof source !== "object") continue;
@@ -2043,14 +1737,68 @@ var extractPendingToolApprovalIdsFromMessages = (messages) => {
2043
1737
  }
2044
1738
  return pendingToolApprovalIds;
2045
1739
  };
1740
+ var toolCallHasOutput = (parts, toolCallId) => parts.some((part) => {
1741
+ if (part.type !== "tool-invocation") return false;
1742
+ const invocation = part.toolInvocation;
1743
+ if (invocation.toolCallId !== toolCallId) return false;
1744
+ return invocation.state === "result" || invocation.result != null;
1745
+ });
1746
+ var resolveInitialMessages = (messages) => messages.filter((message) => {
1747
+ const metadata = message.content?.metadata;
1748
+ if (metadata?.completionResult?.suppressFeedback || metadata?.isTaskCompleteResult?.suppressFeedback) {
1749
+ return false;
1750
+ }
1751
+ return true;
1752
+ }).map((message) => {
1753
+ const metadata = message.content?.metadata;
1754
+ const pendingToolApprovals = metadata?.pendingToolApprovals;
1755
+ if (!pendingToolApprovals || typeof pendingToolApprovals !== "object") {
1756
+ return message;
1757
+ }
1758
+ const stillPending = Object.fromEntries(
1759
+ Object.entries(pendingToolApprovals).filter(
1760
+ ([, approval]) => approval && typeof approval === "object" && typeof approval.toolCallId === "string" && !toolCallHasOutput(message.content.parts, approval.toolCallId)
1761
+ )
1762
+ );
1763
+ const { pendingToolApprovals: _omit, ...restMetadata } = metadata;
1764
+ const hasStillPending = Object.keys(stillPending).length > 0;
1765
+ return {
1766
+ ...message,
1767
+ content: {
1768
+ ...message.content,
1769
+ metadata: {
1770
+ ...restMetadata,
1771
+ mode: "stream",
1772
+ ...hasStillPending ? { pendingToolApprovals: stillPending, requireApprovalMetadata: stillPending } : {}
1773
+ }
1774
+ }
1775
+ };
1776
+ });
1777
+ var isObject = (value) => typeof value === "object" && value !== null;
1778
+ var getErrorName = (error) => isObject(error) && typeof error.name === "string" ? error.name : void 0;
1779
+ var isAbortError = (error) => getErrorName(error) === "AbortError";
2046
1780
  var isThreadSignalUnsupportedError = (error) => {
2047
- const candidate = error;
2048
- const status = candidate?.status;
1781
+ if (!isObject(error)) return false;
1782
+ const status = error.status;
2049
1783
  if (status === 404 || status === 405 || status === 501) {
2050
1784
  return true;
2051
1785
  }
2052
- return status === 400 && candidate?.message?.includes("No active agent run found for signal target");
1786
+ return status === 400 && typeof error.message === "string" && error.message.includes("No active agent run found for signal target");
2053
1787
  };
1788
+ var isDataChunk2 = (chunk) => typeof chunk.type === "string" && chunk.type.startsWith("data-");
1789
+ var dbFromServerUiMessages = (uiMessages, metadata) => uiMessages.map((uiMsg) => {
1790
+ const dbMsg = messageList.AIV5Adapter.fromUIMessage(uiMsg);
1791
+ return {
1792
+ ...dbMsg,
1793
+ content: {
1794
+ ...dbMsg.content,
1795
+ metadata: {
1796
+ ...dbMsg.content.metadata ?? {},
1797
+ ...metadata
1798
+ }
1799
+ }
1800
+ };
1801
+ });
2054
1802
  var useChat = ({
2055
1803
  agentId,
2056
1804
  resourceId,
@@ -2085,7 +1833,7 @@ var useChat = ({
2085
1833
  const baseClient = useMastraClient();
2086
1834
  const [isRunning, setIsRunning] = react.useState(false);
2087
1835
  react.useEffect(() => {
2088
- const formattedMessages = resolveInitialMessages(initialMessages || []);
1836
+ const formattedMessages = resolveInitialMessages(initialMessages ?? []);
2089
1837
  setMessages(formattedMessages);
2090
1838
  pendingToolApprovalIdsRef.current = extractPendingToolApprovalIdsFromMessages(formattedMessages);
2091
1839
  setIsAwaitingToolApproval(pendingToolApprovalIdsRef.current.size > 0);
@@ -2157,8 +1905,8 @@ var useChat = ({
2157
1905
  }, []);
2158
1906
  const processStreamChunk = react.useCallback(
2159
1907
  async (chunk, onChunk) => {
2160
- setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
2161
- if (chunk.type === "data-user-message" && "data" in chunk && typeof chunk.data?.id === "string") {
1908
+ setMessages((prev) => accumulateChunk({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1909
+ if (chunk.type === "data-user-message" && isDataChunk2(chunk) && (chunk.data?.type === "user-message" || chunk.data?.type === "user") && typeof chunk.data?.id === "string") {
2162
1910
  onSignalEcho?.(chunk.data.id);
2163
1911
  }
2164
1912
  if (chunk.type === "start") {
@@ -2203,18 +1951,14 @@ var useChat = ({
2203
1951
  _threadSubscriptionPromiseRef.current = subscriptionAgent.subscribeToThread({ resourceId: resourceId2, threadId: threadId2 }).then((response) => {
2204
1952
  const subscription = response;
2205
1953
  if (_threadSubscriptionAbortRef.current !== subscriptionAbort) {
2206
- if (subscription.unsubscribe) {
2207
- subscription.unsubscribe();
2208
- } else {
2209
- subscriptionAbort.abort();
2210
- }
1954
+ subscription.unsubscribe();
2211
1955
  return;
2212
1956
  }
2213
1957
  _threadSubscriptionRef.current = subscription;
2214
1958
  void subscription.processDataStream({
2215
1959
  onChunk: (chunk) => processStreamChunk(chunk)
2216
1960
  }).catch((error) => {
2217
- if (error.name !== "AbortError") {
1961
+ if (!isAbortError(error)) {
2218
1962
  console.error("[useChat] Thread subscription failed", error);
2219
1963
  setIsRunning(false);
2220
1964
  }
@@ -2239,7 +1983,7 @@ var useChat = ({
2239
1983
  }
2240
1984
  return;
2241
1985
  }
2242
- if (error.name !== "AbortError") {
1986
+ if (!isAbortError(error)) {
2243
1987
  console.error("[useChat] Thread subscription failed", error);
2244
1988
  setIsRunning(false);
2245
1989
  }
@@ -2259,7 +2003,7 @@ var useChat = ({
2259
2003
  return;
2260
2004
  }
2261
2005
  void ensureThreadSubscription({ threadId, resourceId: resourceId || agentId }).catch((error) => {
2262
- if (error.name !== "AbortError") {
2006
+ if (!isAbortError(error)) {
2263
2007
  console.error("[useChat] Thread subscription failed", error);
2264
2008
  }
2265
2009
  });
@@ -2321,34 +2065,22 @@ var useChat = ({
2321
2065
  if (response.finishReason === "suspended" && response.suspendPayload) {
2322
2066
  const { toolCallId, toolName, args } = response.suspendPayload;
2323
2067
  if (response.response?.uiMessages) {
2324
- const mastraUIMessages = (response.response.uiMessages || []).map((message) => ({
2325
- ...message,
2326
- metadata: {
2327
- mode: "generate",
2328
- requireApprovalMetadata: {
2329
- [toolName]: {
2330
- toolCallId,
2331
- toolName,
2332
- args
2333
- }
2334
- }
2068
+ const dbMessages = dbFromServerUiMessages(response.response.uiMessages, {
2069
+ mode: "generate",
2070
+ requireApprovalMetadata: {
2071
+ [toolName]: { toolCallId, toolName, args }
2335
2072
  }
2336
- }));
2337
- setMessages((prev) => [...prev, ...mastraUIMessages]);
2073
+ });
2074
+ setMessages((prev) => [...prev, ...dbMessages]);
2338
2075
  }
2339
2076
  setIsRunning(false);
2340
2077
  return;
2341
2078
  }
2342
2079
  setIsRunning(false);
2343
2080
  if (response && "uiMessages" in response.response && response.response.uiMessages) {
2344
- void onFinish?.(response.response.uiMessages);
2345
- const mastraUIMessages = (response.response.uiMessages || []).map((message) => ({
2346
- ...message,
2347
- metadata: {
2348
- mode: "generate"
2349
- }
2350
- }));
2351
- setMessages((prev) => [...prev, ...mastraUIMessages]);
2081
+ const dbMessages = dbFromServerUiMessages(response.response.uiMessages, { mode: "generate" });
2082
+ void onFinish?.(dbMessages);
2083
+ setMessages((prev) => [...prev, ...dbMessages]);
2352
2084
  }
2353
2085
  };
2354
2086
  const stream = async ({
@@ -2450,14 +2182,27 @@ var useChat = ({
2450
2182
  return;
2451
2183
  }
2452
2184
  const resolvedSignalId = signalId ?? uuid.v4();
2453
- onSignalSent?.(resolvedSignalId, getSignalPreview(coreUserMessages));
2185
+ const messageContents = getSignalContents(coreUserMessages);
2186
+ const streamOptions = {
2187
+ maxSteps,
2188
+ modelSettings: {
2189
+ frequencyPenalty,
2190
+ presencePenalty,
2191
+ maxRetries,
2192
+ maxOutputTokens: maxTokens,
2193
+ temperature,
2194
+ topK,
2195
+ topP
2196
+ },
2197
+ instructions,
2198
+ requestContext: resolvedRequestContext,
2199
+ providerOptions,
2200
+ requireToolApproval,
2201
+ tracingOptions
2202
+ };
2454
2203
  try {
2455
- await agent.sendSignal({
2456
- signal: {
2457
- id: resolvedSignalId,
2458
- type: "user-message",
2459
- contents: getSignalContents(coreUserMessages)
2460
- },
2204
+ const result = await agent.sendMessage({
2205
+ message: messageContents,
2461
2206
  resourceId: resourceId || agentId,
2462
2207
  threadId: threadId2,
2463
2208
  ifIdle: {
@@ -2468,16 +2213,36 @@ var useChat = ({
2468
2213
  }
2469
2214
  }
2470
2215
  });
2216
+ const echoedSignalId = result.signal && typeof result.signal === "object" && "id" in result.signal && typeof result.signal.id === "string" ? result.signal.id : resolvedSignalId;
2217
+ onSignalSent?.(echoedSignalId, getSignalPreview(coreUserMessages));
2471
2218
  if (pendingToolApprovalIdsRef.current.size > 0) {
2472
2219
  setIsRunning(false);
2473
2220
  }
2474
2221
  } catch (error) {
2475
- onSignalEcho?.(resolvedSignalId);
2476
2222
  if (isThreadSignalUnsupportedError(error)) {
2477
- markThreadSignalsUnsupported();
2478
- setMessages((prev) => [...prev, ...coreUserMessages.map(fromCoreUserMessageToUIMessage)]);
2479
- await streamWithLegacyRoute();
2480
- return;
2223
+ onSignalSent?.(resolvedSignalId, getSignalPreview(coreUserMessages));
2224
+ try {
2225
+ await agent.sendSignal({
2226
+ signal: {
2227
+ id: resolvedSignalId,
2228
+ type: "user-message",
2229
+ contents: messageContents
2230
+ },
2231
+ resourceId: resourceId || agentId,
2232
+ threadId: threadId2,
2233
+ ifIdle: { streamOptions }
2234
+ });
2235
+ return;
2236
+ } catch (signalError) {
2237
+ onSignalEcho?.(resolvedSignalId);
2238
+ if (isThreadSignalUnsupportedError(signalError)) {
2239
+ markThreadSignalsUnsupported();
2240
+ setMessages((prev) => [...prev, ...coreUserMessages.map(fromCoreUserMessageToMastraDBMessage)]);
2241
+ await streamWithLegacyRoute();
2242
+ return;
2243
+ }
2244
+ throw signalError;
2245
+ }
2481
2246
  }
2482
2247
  throw error;
2483
2248
  }
@@ -2522,13 +2287,13 @@ var useChat = ({
2522
2287
  });
2523
2288
  _onNetworkChunk.current = onNetworkChunk;
2524
2289
  _networkRunId.current = runId;
2525
- const transformer = new AISdkNetworkTransformer();
2526
2290
  await response.processDataStream({
2527
2291
  onChunk: async (chunk) => {
2528
- setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
2292
+ setMessages((prev) => accumulateNetworkChunk({ chunk, conversation: prev, metadata: { mode: "network" } }));
2529
2293
  void onNetworkChunk?.(chunk);
2530
2294
  }
2531
2295
  });
2296
+ setMessages((prev) => finishStreamingAssistantMessage(prev));
2532
2297
  setIsRunning(false);
2533
2298
  };
2534
2299
  const handleCancelRun = () => {
@@ -2650,13 +2415,8 @@ var useChat = ({
2650
2415
  requestContext: _requestContext.current
2651
2416
  });
2652
2417
  if (response && "uiMessages" in response.response && response.response.uiMessages) {
2653
- const mastraUIMessages = (response.response.uiMessages || []).map((message) => ({
2654
- ...message,
2655
- metadata: {
2656
- mode: "generate"
2657
- }
2658
- }));
2659
- setMessages((prev) => [...prev, ...mastraUIMessages]);
2418
+ const dbMessages = dbFromServerUiMessages(response.response.uiMessages, { mode: "generate" });
2419
+ setMessages((prev) => [...prev, ...dbMessages]);
2660
2420
  }
2661
2421
  setIsRunning(false);
2662
2422
  };
@@ -2675,13 +2435,8 @@ var useChat = ({
2675
2435
  requestContext: _requestContext.current
2676
2436
  });
2677
2437
  if (response && "uiMessages" in response.response && response.response.uiMessages) {
2678
- const mastraUIMessages = (response.response.uiMessages || []).map((message) => ({
2679
- ...message,
2680
- metadata: {
2681
- mode: "generate"
2682
- }
2683
- }));
2684
- setMessages((prev) => [...prev, ...mastraUIMessages]);
2438
+ const dbMessages = dbFromServerUiMessages(response.response.uiMessages, { mode: "generate" });
2439
+ setMessages((prev) => [...prev, ...dbMessages]);
2685
2440
  }
2686
2441
  setIsRunning(false);
2687
2442
  };
@@ -2702,13 +2457,13 @@ var useChat = ({
2702
2457
  runId: networkRunId,
2703
2458
  requestContext: _requestContext.current
2704
2459
  });
2705
- const transformer = new AISdkNetworkTransformer();
2706
2460
  await response.processDataStream({
2707
2461
  onChunk: async (chunk) => {
2708
- setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
2462
+ setMessages((prev) => accumulateNetworkChunk({ chunk, conversation: prev, metadata: { mode: "network" } }));
2709
2463
  void onNetworkChunk?.(chunk);
2710
2464
  }
2711
2465
  });
2466
+ setMessages((prev) => finishStreamingAssistantMessage(prev));
2712
2467
  setIsRunning(false);
2713
2468
  };
2714
2469
  const declineNetworkToolCall = async (toolName, runId) => {
@@ -2728,13 +2483,13 @@ var useChat = ({
2728
2483
  runId: networkRunId,
2729
2484
  requestContext: _requestContext.current
2730
2485
  });
2731
- const transformer = new AISdkNetworkTransformer();
2732
2486
  await response.processDataStream({
2733
2487
  onChunk: async (chunk) => {
2734
- setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
2488
+ setMessages((prev) => accumulateNetworkChunk({ chunk, conversation: prev, metadata: { mode: "network" } }));
2735
2489
  void onNetworkChunk?.(chunk);
2736
2490
  }
2737
2491
  });
2492
+ setMessages((prev) => finishStreamingAssistantMessage(prev));
2738
2493
  setIsRunning(false);
2739
2494
  };
2740
2495
  const sendMessage = async ({ mode = "stream", ...args }) => {
@@ -2743,10 +2498,10 @@ var useChat = ({
2743
2498
  if (args.coreUserMessages) {
2744
2499
  coreUserMessages.push(...args.coreUserMessages);
2745
2500
  }
2746
- const uiMessages = coreUserMessages.map(fromCoreUserMessageToUIMessage);
2747
- const signalId = mode === "stream" && args.threadId && !_threadSignalsUnsupportedRef.current && !threadSignalsDisabled ? uiMessages[0]?.id : void 0;
2501
+ const dbUserMessages = coreUserMessages.map(fromCoreUserMessageToMastraDBMessage);
2502
+ const signalId = mode === "stream" && args.threadId && !_threadSignalsUnsupportedRef.current && !threadSignalsDisabled ? dbUserMessages[0]?.id : void 0;
2748
2503
  if (!signalId) {
2749
- setMessages((s) => [...s, ...uiMessages]);
2504
+ setMessages((s) => [...s, ...dbUserMessages]);
2750
2505
  }
2751
2506
  if (mode === "generate") {
2752
2507
  await generate({ ...args, coreUserMessages });
@@ -3075,6 +2830,117 @@ var MessageStreamingClass = "mastra:inline-block mastra:w-[2px] mastra:h-[1em] m
3075
2830
  var MessageStreaming = ({ className, ...props }) => {
3076
2831
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: className || MessageStreamingClass, ...props });
3077
2832
  };
2833
+ var isDynamicToolPart2 = (part) => (
2834
+ // `tool-invocation` is the v4 typed discriminant and must NOT be treated as a
2835
+ // v5 `tool-${string}` streaming part, even though it shares the `tool-` prefix.
2836
+ part.type === "dynamic-tool" || part.type.startsWith("tool-") && part.type !== "tool-invocation"
2837
+ );
2838
+ var isDataPart = (part) => part.type.startsWith("data-");
2839
+ var sourceToSourceUrl = (part) => ({
2840
+ type: "source-url",
2841
+ sourceId: part.source.id,
2842
+ url: part.source.url,
2843
+ title: part.source.title,
2844
+ providerMetadata: part.providerMetadata
2845
+ });
2846
+ var getPartKey = (part, index) => {
2847
+ if (isDynamicToolPart2(part)) {
2848
+ return part.toolCallId ?? `${part.type}-${index}`;
2849
+ }
2850
+ switch (part.type) {
2851
+ case "text":
2852
+ return part.textId ?? `text-${index}`;
2853
+ case "reasoning":
2854
+ return part.reasoningId ?? `reasoning-${index}`;
2855
+ case "tool-invocation":
2856
+ return part.toolInvocation.toolCallId ?? `tool-invocation-${index}`;
2857
+ case "source-url":
2858
+ return part.sourceId || `source-url-${index}`;
2859
+ case "source":
2860
+ return part.source.id ?? `source-${index}`;
2861
+ }
2862
+ const id = part.id;
2863
+ return id ?? `${part.type}-${index}`;
2864
+ };
2865
+ var renderPart = (part, renderers, fallback) => {
2866
+ if (isDynamicToolPart2(part)) {
2867
+ return renderers.DynamicTool?.(part) ?? fallback?.(part) ?? null;
2868
+ }
2869
+ if (isDataPart(part)) {
2870
+ return renderers.Data?.(part) ?? fallback?.(part) ?? null;
2871
+ }
2872
+ switch (part.type) {
2873
+ case "text":
2874
+ return renderers.Text?.(part) ?? fallback?.(part) ?? null;
2875
+ case "reasoning":
2876
+ return renderers.Reasoning?.(part) ?? fallback?.(part) ?? null;
2877
+ case "file":
2878
+ return renderers.File?.(part) ?? fallback?.(part) ?? null;
2879
+ case "step-start":
2880
+ return renderers.StepStart?.(part) ?? fallback?.(part) ?? null;
2881
+ case "tool-invocation":
2882
+ return renderers.ToolInvocation?.(part) ?? fallback?.(part) ?? null;
2883
+ case "source":
2884
+ return renderers.SourceUrl?.(sourceToSourceUrl(part)) ?? fallback?.(part) ?? null;
2885
+ case "source-url":
2886
+ return renderers.SourceUrl?.(part) ?? fallback?.(part) ?? null;
2887
+ case "source-document":
2888
+ return renderers.SourceDocument?.(part) ?? fallback?.(part) ?? null;
2889
+ default: {
2890
+ return fallback?.(part) ?? null;
2891
+ }
2892
+ }
2893
+ };
2894
+ var PartRenderer = react.memo(({ part, renderers, fallback }) => /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderPart(part, renderers, fallback) }));
2895
+ PartRenderer.displayName = "PartRenderer";
2896
+ var joinText = (parts) => parts.filter((part) => part.type === "text").map((part) => part.text).join("");
2897
+ var resolveTaskVerdict = (metadata) => {
2898
+ const verdict = metadata?.completionResult ?? metadata?.isTaskCompleteResult;
2899
+ if (!verdict) return void 0;
2900
+ return { passed: !!verdict.passed, suppressFeedback: verdict.suppressFeedback };
2901
+ };
2902
+ var roleRendererFor = (role, roles) => {
2903
+ switch (role) {
2904
+ case "user":
2905
+ return roles?.User;
2906
+ case "assistant":
2907
+ return roles?.Assistant;
2908
+ case "system":
2909
+ return roles?.System;
2910
+ case "signal":
2911
+ return roles?.Signal;
2912
+ default:
2913
+ return void 0;
2914
+ }
2915
+ };
2916
+ var MessageFactoryComponent = ({ message, roles, status, fallback, ...renderers }) => {
2917
+ const parts = message.content.parts ?? [];
2918
+ const metadata = message.content.metadata;
2919
+ let content;
2920
+ if (metadata?.status === "tripwire" && status?.Tripwire) {
2921
+ content = status.Tripwire({ text: joinText(parts), tripwire: metadata.tripwire, message });
2922
+ } else if (metadata?.status === "warning" && status?.Warning) {
2923
+ content = status.Warning({ text: joinText(parts), message });
2924
+ } else if (metadata?.status === "error" && status?.Error) {
2925
+ content = status.Error({ text: joinText(parts), message });
2926
+ } else {
2927
+ content = /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: parts.map((part, index) => /* @__PURE__ */ jsxRuntime.jsx(PartRenderer, { part, renderers, fallback }, getPartKey(part, index))) });
2928
+ const verdict = resolveTaskVerdict(metadata);
2929
+ if (verdict && status?.Task) {
2930
+ content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2931
+ content,
2932
+ status.Task({ ...verdict, text: joinText(parts), message })
2933
+ ] });
2934
+ }
2935
+ }
2936
+ const RoleWrapper = roleRendererFor(message.role, roles);
2937
+ if (RoleWrapper) {
2938
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: RoleWrapper({ message, children: content }) });
2939
+ }
2940
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: content });
2941
+ };
2942
+ var MessageFactory = react.memo(MessageFactoryComponent);
2943
+ MessageFactory.displayName = "MessageFactory";
3078
2944
  function useMutation(mutationFn) {
3079
2945
  const [isPending, setIsPending] = react.useState(false);
3080
2946
  const [isSuccess, setIsSuccess] = react.useState(false);
@@ -3511,6 +3377,7 @@ exports.MessageActionsClass = MessageActionsClass;
3511
3377
  exports.MessageClass = MessageClass;
3512
3378
  exports.MessageContent = MessageContent;
3513
3379
  exports.MessageContentClass = MessageContentClass;
3380
+ exports.MessageFactory = MessageFactory;
3514
3381
  exports.MessageList = MessageList;
3515
3382
  exports.MessageListClass = MessageListClass;
3516
3383
  exports.MessageStreaming = MessageStreaming;
@@ -3539,12 +3406,11 @@ exports.TooltipContent = TooltipContent;
3539
3406
  exports.TooltipContentClass = TooltipContentClass;
3540
3407
  exports.TooltipTrigger = TooltipTrigger;
3541
3408
  exports.WorkflowIcon = WorkflowIcon;
3409
+ exports.accumulateChunk = accumulateChunk;
3410
+ exports.accumulateNetworkChunk = accumulateNetworkChunk;
3542
3411
  exports.finishStreamingAssistantMessage = finishStreamingAssistantMessage;
3412
+ exports.fromCoreUserMessageToMastraDBMessage = fromCoreUserMessageToMastraDBMessage;
3543
3413
  exports.mapWorkflowStreamChunkToWatchResult = mapWorkflowStreamChunkToWatchResult;
3544
- exports.markStreamingPartsDone = markStreamingPartsDone;
3545
- exports.resolveToChildMessages = resolveToChildMessages;
3546
- exports.toAssistantUIMessage = toAssistantUIMessage;
3547
- exports.toUIMessage = toUIMessage;
3548
3414
  exports.useCancelWorkflowRun = useCancelWorkflowRun;
3549
3415
  exports.useChat = useChat;
3550
3416
  exports.useCreateWorkflowRun = useCreateWorkflowRun;