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