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