@mastra/react 0.4.3 → 0.5.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +64 -0
- package/dist/agent/extractRunIdFromMessages.d.ts +9 -2
- package/dist/agent/extractRunIdFromMessages.d.ts.map +1 -1
- package/dist/agent/hooks.d.ts +9 -11
- package/dist/agent/hooks.d.ts.map +1 -1
- package/dist/agent/types.d.ts +5 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/index.cjs +1342 -1476
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1342 -1476
- package/dist/index.js.map +1 -1
- package/dist/lib/mastra-db/accumulator.d.ts +48 -0
- package/dist/lib/mastra-db/accumulator.d.ts.map +1 -0
- package/dist/lib/mastra-db/formatCompletionFeedback.d.ts.map +1 -0
- package/dist/lib/mastra-db/fromCoreUserMessage.d.ts +11 -0
- package/dist/lib/mastra-db/fromCoreUserMessage.d.ts.map +1 -0
- package/dist/lib/mastra-db/index.d.ts +5 -0
- package/dist/lib/mastra-db/index.d.ts.map +1 -0
- package/dist/lib/mastra-db/types.d.ts +156 -0
- package/dist/lib/mastra-db/types.d.ts.map +1 -0
- package/dist/ui/MessageFactory/MessageFactory.d.ts +22 -0
- package/dist/ui/MessageFactory/MessageFactory.d.ts.map +1 -0
- package/dist/ui/MessageFactory/index.d.ts +3 -0
- package/dist/ui/MessageFactory/index.d.ts.map +1 -0
- package/dist/ui/MessageFactory/types.d.ts +164 -0
- package/dist/ui/MessageFactory/types.d.ts.map +1 -0
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.d.ts.map +1 -1
- package/package.json +5 -9
- package/dist/lib/ai-sdk/index.d.ts +0 -5
- package/dist/lib/ai-sdk/index.d.ts.map +0 -1
- package/dist/lib/ai-sdk/memory/resolveInitialMessages.d.ts +0 -13
- package/dist/lib/ai-sdk/memory/resolveInitialMessages.d.ts.map +0 -1
- package/dist/lib/ai-sdk/transformers/AISdkNetworkTransformer.d.ts +0 -11
- package/dist/lib/ai-sdk/transformers/AISdkNetworkTransformer.d.ts.map +0 -1
- package/dist/lib/ai-sdk/transformers/types.d.ts +0 -11
- package/dist/lib/ai-sdk/transformers/types.d.ts.map +0 -1
- package/dist/lib/ai-sdk/types.d.ts +0 -145
- package/dist/lib/ai-sdk/types.d.ts.map +0 -1
- package/dist/lib/ai-sdk/utils/formatCompletionFeedback.d.ts.map +0 -1
- package/dist/lib/ai-sdk/utils/fromCoreUserMessageToUIMessage.d.ts +0 -11
- package/dist/lib/ai-sdk/utils/fromCoreUserMessageToUIMessage.d.ts.map +0 -1
- package/dist/lib/ai-sdk/utils/toAssistantUIMessage.d.ts +0 -15
- package/dist/lib/ai-sdk/utils/toAssistantUIMessage.d.ts.map +0 -1
- package/dist/lib/ai-sdk/utils/toUIMessage.d.ts +0 -20
- package/dist/lib/ai-sdk/utils/toUIMessage.d.ts.map +0 -1
- /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/
|
|
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/
|
|
116
|
-
var
|
|
116
|
+
// src/lib/mastra-db/accumulator.ts
|
|
117
|
+
var cloneMetadata = (metadata) => metadata ? { ...metadata } : {};
|
|
118
|
+
var withParts = (message, parts) => ({
|
|
117
119
|
...message,
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
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
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
239
|
-
|
|
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
|
-
|
|
293
|
-
{
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
346
|
-
|
|
347
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
431
|
+
`start-${chunk.runId}-${Date.now()}`,
|
|
432
|
+
[newTextPart],
|
|
400
433
|
metadata
|
|
401
434
|
);
|
|
402
435
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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
|
-
|
|
418
|
-
{
|
|
419
|
-
|
|
420
|
-
metadata
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
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
|
-
|
|
475
|
-
|
|
476
|
-
|
|
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
|
-
|
|
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
|
-
|
|
502
|
+
reasoning: "",
|
|
503
503
|
state: "streaming",
|
|
504
504
|
providerMetadata: chunk.payload.providerMetadata
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
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
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
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
|
|
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
|
|
534
|
-
const lastPart = parts[
|
|
535
|
+
const parts = [...lastMessage.content.parts];
|
|
536
|
+
const lastIndex = parts.length - 1;
|
|
537
|
+
const lastPart = parts[lastIndex];
|
|
535
538
|
if (lastPart?.type === "reasoning") {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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
|
-
|
|
546
|
+
const newReasoningPart = {
|
|
543
547
|
type: "reasoning",
|
|
544
|
-
|
|
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
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
const
|
|
566
|
-
|
|
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
|
-
...
|
|
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 "
|
|
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
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
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
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
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
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
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-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
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 =
|
|
636
|
-
if (
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
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
|
|
652
|
-
const
|
|
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
|
-
|
|
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 =
|
|
808
|
+
const existingOutput = toolPart.toolInvocation.state === "result" ? toolPart.toolInvocation.result : void 0;
|
|
809
|
+
const existingChild = existingOutput?.childMessages;
|
|
658
810
|
output = existingOutput ? {
|
|
659
|
-
...
|
|
660
|
-
childMessages:
|
|
661
|
-
} :
|
|
811
|
+
...payloadResult,
|
|
812
|
+
childMessages: existingChild?.length ? existingChild : resultObj?.childMessages
|
|
813
|
+
} : payloadResult;
|
|
662
814
|
} else {
|
|
663
|
-
output =
|
|
815
|
+
output = payloadResult;
|
|
664
816
|
}
|
|
665
817
|
parts[toolPartIndex] = {
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
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
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
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:
|
|
684
|
-
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
|
|
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
|
-
|
|
697
|
-
|
|
858
|
+
const nextMetadata = mergeBgTaskMetadata(
|
|
859
|
+
targetMessage.content.metadata,
|
|
860
|
+
metadata.mode,
|
|
698
861
|
{
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
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
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
const
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
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
|
-
|
|
747
|
-
|
|
748
|
-
|
|
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
|
-
|
|
773
|
-
|
|
774
|
-
|
|
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
|
-
|
|
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
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
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
|
-
...
|
|
989
|
+
...existingMeta,
|
|
854
990
|
mode: "stream",
|
|
855
991
|
requireApprovalMetadata: {
|
|
856
|
-
...
|
|
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
|
-
|
|
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
|
|
876
|
-
const
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
{
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
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
|
|
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
|
-
|
|
912
|
-
|
|
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
|
-
|
|
1071
|
+
{
|
|
920
1072
|
...metadata,
|
|
921
1073
|
status: "error"
|
|
922
1074
|
}
|
|
923
|
-
|
|
1075
|
+
);
|
|
924
1076
|
return [...result, newMessage];
|
|
925
1077
|
}
|
|
926
|
-
//
|
|
927
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
1156
|
+
const nextChildren = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
|
|
946
1157
|
parts[toolPartIndex] = {
|
|
947
1158
|
...toolPart,
|
|
948
|
-
|
|
949
|
-
|
|
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 =
|
|
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
|
|
1169
|
+
const existingResult = toolPart.toolInvocation.result || {};
|
|
1170
|
+
const childMessages = existingResult.childMessages || [];
|
|
960
1171
|
parts[toolPartIndex] = {
|
|
961
1172
|
...toolPart,
|
|
962
|
-
|
|
963
|
-
...toolPart
|
|
964
|
-
|
|
965
|
-
...
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
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 =
|
|
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
|
|
984
|
-
const
|
|
985
|
-
const
|
|
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
|
|
988
|
-
if (
|
|
1200
|
+
const updated = mapWorkflowStreamChunkToWatchResult(actualExistingWorkflowState, agentChunk.output);
|
|
1201
|
+
if (lastIndex >= 0 && childMessages[lastIndex]?.type === "tool") {
|
|
989
1202
|
parts[toolPartIndex] = {
|
|
990
1203
|
...toolPart,
|
|
991
|
-
|
|
992
|
-
...toolPart
|
|
993
|
-
|
|
994
|
-
...
|
|
995
|
-
|
|
996
|
-
...
|
|
997
|
-
|
|
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 =
|
|
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
|
|
1012
|
-
const
|
|
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 (
|
|
1229
|
+
if (lastIndex >= 0 && childMessages[lastIndex]?.type === "tool") {
|
|
1015
1230
|
parts[toolPartIndex] = {
|
|
1016
1231
|
...toolPart,
|
|
1017
|
-
|
|
1018
|
-
...toolPart
|
|
1019
|
-
|
|
1020
|
-
...
|
|
1021
|
-
|
|
1022
|
-
...childMessages
|
|
1023
|
-
|
|
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
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
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
|
|
1059
|
-
const
|
|
1060
|
-
if (
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
)
|
|
1064
|
-
|
|
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
|
-
|
|
1105
|
-
|
|
1106
|
-
const
|
|
1107
|
-
const
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1258
|
-
};
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
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
|
|
1297
|
+
return replaceLast(conversation, withMetadata(lastMessage, mergeRoutingMetadata(lastMessage.content.metadata ?? {})));
|
|
1416
1298
|
};
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
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
|
|
1335
|
+
return replaceLast(conversation, withParts(lastMessage, parts));
|
|
1500
1336
|
}
|
|
1501
|
-
|
|
1502
|
-
const lastMessage =
|
|
1503
|
-
if (!lastMessage
|
|
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
|
|
1507
|
-
if (
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
}
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
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
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
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
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
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
|
-
|
|
1625
|
-
toolName: toolPart.toolName,
|
|
1626
|
-
toolCallId: toolPart.toolCallId,
|
|
1627
|
-
state: "output-available",
|
|
1628
|
-
input: toolPart.input,
|
|
1383
|
+
...toolPart,
|
|
1629
1384
|
output: {
|
|
1630
|
-
...
|
|
1631
|
-
|
|
1385
|
+
...toolPart?.output,
|
|
1386
|
+
childMessages: [...childMessages.slice(0, -1), { ...currentMessage, toolOutput: updatedWorkflowState }]
|
|
1632
1387
|
}
|
|
1633
1388
|
};
|
|
1634
1389
|
}
|
|
1635
1390
|
}
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
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
|
-
|
|
1673
|
-
|
|
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
|
-
}
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
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
|
-
}
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
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
|
-
...
|
|
1730
|
-
|
|
1494
|
+
...networkMode(metadata),
|
|
1495
|
+
selectionReason: metadata.mode === "network" ? metadata.selectionReason || argsData.selectionReason : "",
|
|
1496
|
+
agentInput: nestedArgs
|
|
1731
1497
|
}
|
|
1732
|
-
|
|
1498
|
+
);
|
|
1733
1499
|
}
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
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
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
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
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
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
|
-
|
|
1802
|
-
const existingWorkflowState = toolPart.output || {};
|
|
1803
|
-
const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, chunk.payload);
|
|
1556
|
+
const currentOutput = toolPart.output;
|
|
1804
1557
|
parts[toolPartIndex] = {
|
|
1805
|
-
|
|
1806
|
-
|
|
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
|
|
1817
|
-
}
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
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
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
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
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
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/
|
|
1944
|
-
var
|
|
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
|
-
|
|
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
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
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
|
|
2029
|
-
metadata
|
|
2030
|
-
metadata
|
|
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
|
-
|
|
2046
|
-
const 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 &&
|
|
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) =>
|
|
2159
|
-
if (chunk.type === "data-user-message" &&
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
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, ...
|
|
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
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
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
|
-
|
|
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.
|
|
2454
|
-
|
|
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
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
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) =>
|
|
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
|
|
2652
|
-
|
|
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
|
|
2677
|
-
|
|
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) =>
|
|
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) =>
|
|
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
|
|
2745
|
-
const signalId = mode === "stream" && args.threadId && !_threadSignalsUnsupportedRef.current && !threadSignalsDisabled ?
|
|
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, ...
|
|
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,
|
|
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
|