@tanstack/ai 0.58.0 → 0.61.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/dist/esm/activities/chat/adapter.d.ts +9 -0
- package/dist/esm/activities/chat/adapter.js +1 -0
- package/dist/esm/activities/chat/adapter.js.map +1 -1
- package/dist/esm/activities/chat/agents/define-agent.d.ts +81 -0
- package/dist/esm/activities/chat/agents/define-agent.js +34 -0
- package/dist/esm/activities/chat/agents/define-agent.js.map +1 -0
- package/dist/esm/activities/chat/agents/route.d.ts +53 -0
- package/dist/esm/activities/chat/agents/route.js +59 -0
- package/dist/esm/activities/chat/agents/route.js.map +1 -0
- package/dist/esm/activities/chat/agents/spawn.d.ts +124 -0
- package/dist/esm/activities/chat/agents/spawn.js +490 -0
- package/dist/esm/activities/chat/agents/spawn.js.map +1 -0
- package/dist/esm/activities/chat/agents/turn.d.ts +36 -0
- package/dist/esm/activities/chat/agents/turn.js +78 -0
- package/dist/esm/activities/chat/agents/turn.js.map +1 -0
- package/dist/esm/activities/chat/index.d.ts +13 -3
- package/dist/esm/activities/chat/index.js +462 -26
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.d.ts +7 -1
- package/dist/esm/activities/chat/messages.js +99 -19
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/middleware/run-store.d.ts +43 -7
- package/dist/esm/activities/chat/middleware/run-store.js +8 -1
- package/dist/esm/activities/chat/middleware/run-store.js.map +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +47 -1
- package/dist/esm/activities/chat/middleware/types.js.map +1 -1
- package/dist/esm/activities/chat/stream/message-updaters.js +9 -2
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +46 -1
- package/dist/esm/activities/chat/stream/processor.js +294 -18
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +17 -3
- package/dist/esm/activities/chat/tools/tool-calls.js +56 -5
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/embed/adapter.d.ts +7 -0
- package/dist/esm/activities/embed/adapter.js +1 -0
- package/dist/esm/activities/embed/adapter.js.map +1 -1
- package/dist/esm/activities/embed/index.js +2 -0
- package/dist/esm/activities/embed/index.js.map +1 -1
- package/dist/esm/activities/files/adapter.d.ts +97 -0
- package/dist/esm/activities/files/adapter.js +45 -0
- package/dist/esm/activities/files/adapter.js.map +1 -0
- package/dist/esm/activities/files/index.d.ts +66 -0
- package/dist/esm/activities/files/index.js +78 -0
- package/dist/esm/activities/files/index.js.map +1 -0
- package/dist/esm/activities/generateAudio/index.js +1 -1
- package/dist/esm/activities/generateImage/adapter.d.ts +8 -0
- package/dist/esm/activities/generateImage/adapter.js +1 -0
- package/dist/esm/activities/generateImage/adapter.js.map +1 -1
- package/dist/esm/activities/generateImage/index.js +3 -1
- package/dist/esm/activities/generateImage/index.js.map +1 -1
- package/dist/esm/activities/generateLiveVideo/index.js +1 -1
- package/dist/esm/activities/generateSpeech/index.js +1 -1
- package/dist/esm/activities/generateTranscription/index.js +1 -1
- package/dist/esm/activities/generateVideo/adapter.d.ts +8 -0
- package/dist/esm/activities/generateVideo/adapter.js +1 -0
- package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.js +3 -0
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/generateVoice/index.js +1 -1
- package/dist/esm/activities/generateWorld/adapter.d.ts +4 -2
- package/dist/esm/activities/generateWorld/adapter.js.map +1 -1
- package/dist/esm/activities/generateWorld/index.d.ts +4 -3
- package/dist/esm/activities/generateWorld/index.js +6 -5
- package/dist/esm/activities/generateWorld/index.js.map +1 -1
- package/dist/esm/activities/index.d.ts +9 -3
- package/dist/esm/activities/index.js +17 -13
- package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +2 -0
- package/dist/esm/activities/summarize/chat-stream-summarize.js +8 -8
- package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
- package/dist/esm/activities/summarize/index.js +1 -1
- package/dist/esm/client.d.ts +7 -36
- package/dist/esm/client.js +5 -37
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +8 -2
- package/dist/esm/index.js +9 -4
- package/dist/esm/middlewares/content-guard.js.map +1 -1
- package/dist/esm/types.d.ts +179 -98
- package/dist/esm/utilities/adapter-yield-chunk.d.ts +5 -1
- package/dist/esm/utilities/ag-ui-usage.d.ts +9 -9
- package/dist/esm/utilities/ag-ui-usage.js +66 -3
- package/dist/esm/utilities/ag-ui-usage.js.map +1 -1
- package/dist/esm/utilities/ag-ui-wire.js +90 -13
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/content-source.d.ts +60 -0
- package/dist/esm/utilities/content-source.js +85 -0
- package/dist/esm/utilities/content-source.js.map +1 -0
- package/dist/esm/utilities/normalize-stream-chunk.js +7 -2
- package/dist/esm/utilities/normalize-stream-chunk.js.map +1 -1
- package/dist/esm/utilities/provider-executed.d.ts +7 -0
- package/dist/esm/utilities/provider-executed.js +10 -1
- package/dist/esm/utilities/provider-executed.js.map +1 -1
- package/dist/esm/utilities/spec-event-keys.js +13 -8
- package/dist/esm/utilities/spec-event-keys.js.map +1 -1
- package/dist/esm/utilities/subagent-wire.d.ts +36 -0
- package/dist/esm/utilities/subagent-wire.js +131 -0
- package/dist/esm/utilities/subagent-wire.js.map +1 -0
- package/dist/esm/utilities/tool-result.d.ts +12 -2
- package/dist/esm/utilities/tool-result.js +23 -3
- package/dist/esm/utilities/tool-result.js.map +1 -1
- package/package.json +3 -3
- package/skills/ai-core/adapter-configuration/SKILL.md +62 -0
- package/skills/ai-core/adapter-configuration/references/grok-adapter.md +1 -1
- package/skills/ai-core/chat-experience/SKILL.md +14 -0
- package/skills/ai-core/media-generation/SKILL.md +10 -2
- package/skills/ai-core/middleware/SKILL.md +7 -4
- package/src/activities/chat/adapter.ts +10 -0
- package/src/activities/chat/agents/define-agent.ts +121 -0
- package/src/activities/chat/agents/route.ts +115 -0
- package/src/activities/chat/agents/spawn.ts +806 -0
- package/src/activities/chat/agents/turn.ts +151 -0
- package/src/activities/chat/index.ts +734 -30
- package/src/activities/chat/messages.ts +137 -16
- package/src/activities/chat/middleware/run-store.ts +56 -7
- package/src/activities/chat/middleware/types.ts +47 -0
- package/src/activities/chat/stream/message-updaters.ts +24 -2
- package/src/activities/chat/stream/processor.ts +452 -30
- package/src/activities/chat/tools/tool-calls.ts +83 -11
- package/src/activities/embed/adapter.ts +7 -0
- package/src/activities/embed/index.ts +5 -0
- package/src/activities/files/adapter.ts +120 -0
- package/src/activities/files/index.ts +113 -0
- package/src/activities/generateImage/adapter.ts +8 -0
- package/src/activities/generateImage/index.ts +4 -0
- package/src/activities/generateVideo/adapter.ts +8 -0
- package/src/activities/generateVideo/index.ts +7 -0
- package/src/activities/generateWorld/adapter.ts +4 -2
- package/src/activities/generateWorld/index.ts +7 -6
- package/src/activities/index.ts +40 -1
- package/src/activities/summarize/chat-stream-summarize.ts +22 -12
- package/src/client.ts +29 -35
- package/src/index.ts +39 -0
- package/src/middlewares/content-guard.ts +7 -5
- package/src/types.ts +226 -103
- package/src/utilities/adapter-yield-chunk.ts +10 -2
- package/src/utilities/ag-ui-usage.test.ts +38 -0
- package/src/utilities/ag-ui-usage.ts +98 -11
- package/src/utilities/ag-ui-wire.ts +134 -16
- package/src/utilities/content-source.ts +138 -0
- package/src/utilities/normalize-stream-chunk.ts +10 -2
- package/src/utilities/provider-executed.ts +13 -0
- package/src/utilities/spec-event-keys.ts +34 -7
- package/src/utilities/subagent-wire.ts +184 -0
- package/src/utilities/tool-result.ts +38 -2
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { EventType } from "../../../types.js";
|
|
1
2
|
import { mergeMetadata, tanstackMetadata } from "../../../utilities/merge-metadata.js";
|
|
2
3
|
import { runErrorEventToError } from "../../../utilities/errors.js";
|
|
3
4
|
import { INTERRUPT_BINDING_METADATA_KEY } from "../../../interrupt-resume.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { isAssistantSegmentOf, isProviderExecutedToolCall } from "../../../utilities/provider-executed.js";
|
|
6
|
+
import { normalizeToolResult, toolResultErrorText } from "../../../utilities/tool-result.js";
|
|
7
|
+
import { splitSubagentWire } from "../../../utilities/subagent-wire.js";
|
|
8
|
+
import { aguiContentToContentParts, aguiSnapshotMessageToUIMessage, coerceCreatedAt, generateMessageId, uiMessageToModelMessages } from "../messages.js";
|
|
7
9
|
import { getChunkRunId } from "../../../utilities/chunk-ids.js";
|
|
8
10
|
import { defaultJSONParser } from "./json-parser.js";
|
|
9
11
|
import { appendStructuredOutputDelta, completeStructuredOutputPart, errorStructuredOutputPart, updateTextPart, updateThinkingPart, updateToolCallApproval, updateToolCallApprovalResponse, updateToolCallPart, updateToolCallWithOutput, updateToolResultPart } from "./message-updaters.js";
|
|
@@ -67,13 +69,17 @@ var StreamProcessor = class StreamProcessor {
|
|
|
67
69
|
structuredMessageIds = /* @__PURE__ */ new Set();
|
|
68
70
|
structuredOutputUpdateBatches = /* @__PURE__ */ new Map();
|
|
69
71
|
activeRuns = /* @__PURE__ */ new Set();
|
|
72
|
+
childProcessors = /* @__PURE__ */ new Map();
|
|
73
|
+
childToolCalls = /* @__PURE__ */ new Map();
|
|
70
74
|
finishReason = null;
|
|
71
75
|
hasError = false;
|
|
72
76
|
isDone = false;
|
|
73
77
|
streamEndEmitted = false;
|
|
74
78
|
recording = null;
|
|
75
79
|
recordingStartTime = 0;
|
|
80
|
+
subagentRunId;
|
|
76
81
|
constructor(options = {}) {
|
|
82
|
+
this.subagentRunId = options.subagentRunId;
|
|
77
83
|
this.chunkStrategy = options.chunkStrategy || new ImmediateStrategy();
|
|
78
84
|
this.events = options.events || {};
|
|
79
85
|
this.jsonParser = options.jsonParser || defaultJSONParser;
|
|
@@ -192,6 +198,11 @@ var StreamProcessor = class StreamProcessor {
|
|
|
192
198
|
addToolResult(toolCallId, output, error) {
|
|
193
199
|
const messageWithToolCall = this.messages.find((msg) => msg.parts.some((p) => p.type === "tool-call" && p.id === toolCallId));
|
|
194
200
|
if (!messageWithToolCall) {
|
|
201
|
+
const owner = this.childOwningToolCall((part) => part.id === toolCallId);
|
|
202
|
+
if (owner !== void 0) {
|
|
203
|
+
this.updateChild(owner, (child) => child.addToolResult(toolCallId, output, error));
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
195
206
|
console.warn(`[StreamProcessor] Could not find message with tool call ${toolCallId}`);
|
|
196
207
|
return;
|
|
197
208
|
}
|
|
@@ -206,6 +217,11 @@ var StreamProcessor = class StreamProcessor {
|
|
|
206
217
|
* Add an approval response (called by client after handling onApprovalRequest)
|
|
207
218
|
*/
|
|
208
219
|
addToolApprovalResponse(approvalId, approved) {
|
|
220
|
+
const owner = this.childOwningToolCall((part) => part.approval?.id === approvalId);
|
|
221
|
+
if (owner !== void 0) {
|
|
222
|
+
this.updateChild(owner, (child) => child.addToolApprovalResponse(approvalId, approved));
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
209
225
|
this.messages = updateToolCallApprovalResponse(this.messages, approvalId, approved);
|
|
210
226
|
this.emitMessagesChange();
|
|
211
227
|
}
|
|
@@ -259,6 +275,8 @@ var StreamProcessor = class StreamProcessor {
|
|
|
259
275
|
this.structuredMessageIds.clear();
|
|
260
276
|
this.structuredOutputUpdateBatches.clear();
|
|
261
277
|
this.pendingManualMessageId = null;
|
|
278
|
+
this.childProcessors.clear();
|
|
279
|
+
this.childToolCalls.clear();
|
|
262
280
|
this.emitMessagesChange();
|
|
263
281
|
}
|
|
264
282
|
/**
|
|
@@ -287,7 +305,17 @@ var StreamProcessor = class StreamProcessor {
|
|
|
287
305
|
timestamp: Date.now(),
|
|
288
306
|
index: this.recording.chunks.length
|
|
289
307
|
});
|
|
308
|
+
if (this.routeToChild(chunk)) return;
|
|
290
309
|
switch (chunk.type) {
|
|
310
|
+
case "SUBAGENT_STARTED":
|
|
311
|
+
this.handleSubagentStartedEvent(chunk);
|
|
312
|
+
break;
|
|
313
|
+
case "SUBAGENT_FINISHED":
|
|
314
|
+
this.handleSubagentFinishedEvent(chunk);
|
|
315
|
+
break;
|
|
316
|
+
case "SUBAGENT_ERROR":
|
|
317
|
+
this.handleSubagentErrorEvent(chunk);
|
|
318
|
+
break;
|
|
291
319
|
case "TEXT_MESSAGE_START":
|
|
292
320
|
this.handleTextMessageStartEvent(chunk);
|
|
293
321
|
break;
|
|
@@ -497,6 +525,164 @@ var StreamProcessor = class StreamProcessor {
|
|
|
497
525
|
} : msg);
|
|
498
526
|
this.emitMessagesChange();
|
|
499
527
|
}
|
|
528
|
+
findSubagentPart(subagentRunId) {
|
|
529
|
+
for (const message of this.messages) for (const part of message.parts) if (part.type === "subagent" && part.subagent.id === subagentRunId) return {
|
|
530
|
+
message,
|
|
531
|
+
part
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* The direct child whose card holds `id`: the child itself, or a nested
|
|
536
|
+
* child inside its messages.
|
|
537
|
+
*/
|
|
538
|
+
childOwning(id) {
|
|
539
|
+
const holds = (messages) => messages.some((message) => message.parts.some((part) => part.type === "subagent" && (part.subagent.id === id || holds(part.subagent.messages))));
|
|
540
|
+
for (const message of this.messages) for (const part of message.parts) {
|
|
541
|
+
if (part.type !== "subagent") continue;
|
|
542
|
+
if (part.subagent.id === id || holds(part.subagent.messages)) return part.subagent.id;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
/** The direct child whose messages hold this tool call. */
|
|
546
|
+
childOwningToolCall(matches) {
|
|
547
|
+
const holds = (messages) => messages.some((message) => message.parts.some((part) => part.type === "tool-call" && matches(part) || part.type === "subagent" && holds(part.subagent.messages)));
|
|
548
|
+
for (const message of this.messages) for (const part of message.parts) if (part.type === "subagent" && holds(part.subagent.messages)) return part.subagent.id;
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* The processor for a direct child. The card's messages are the source of
|
|
552
|
+
* truth. The processor re-reads them when something else replaced them.
|
|
553
|
+
*/
|
|
554
|
+
childProcessor(subagentRunId) {
|
|
555
|
+
const found = this.findSubagentPart(subagentRunId);
|
|
556
|
+
if (!found) return void 0;
|
|
557
|
+
const messages = found.part.subagent.messages;
|
|
558
|
+
const existing = this.childProcessors.get(subagentRunId);
|
|
559
|
+
if (existing) {
|
|
560
|
+
if (existing.getMessages() !== messages) existing.messages = messages;
|
|
561
|
+
return existing;
|
|
562
|
+
}
|
|
563
|
+
const child = new StreamProcessor({
|
|
564
|
+
subagentRunId,
|
|
565
|
+
initialMessages: messages,
|
|
566
|
+
events: {
|
|
567
|
+
onToolCall: (args) => this.events.onToolCall?.(args),
|
|
568
|
+
onApprovalRequest: (args) => this.events.onApprovalRequest?.(args),
|
|
569
|
+
onCustomEvent: (name, value, context) => this.events.onCustomEvent?.(name, value, context)
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
this.childProcessors.set(subagentRunId, child);
|
|
573
|
+
return child;
|
|
574
|
+
}
|
|
575
|
+
/** Run `update` on a direct child, then copy its messages onto the card. */
|
|
576
|
+
updateChild(subagentRunId, update) {
|
|
577
|
+
const child = this.childProcessor(subagentRunId);
|
|
578
|
+
if (!child) return;
|
|
579
|
+
update(child);
|
|
580
|
+
const messages = child.getMessages();
|
|
581
|
+
this.patchSubagent(subagentRunId, (subagent) => {
|
|
582
|
+
subagent.messages = messages;
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
handleSubagentStartedEvent(chunk) {
|
|
586
|
+
if (chunk.type !== "SUBAGENT_STARTED") return;
|
|
587
|
+
if (this.findSubagentPart(chunk.subagentRunId)) {
|
|
588
|
+
this.childProcessors.delete(chunk.subagentRunId);
|
|
589
|
+
this.patchSubagent(chunk.subagentRunId, (subagent) => {
|
|
590
|
+
subagent.status = "running";
|
|
591
|
+
delete subagent.interruptIds;
|
|
592
|
+
delete subagent.error;
|
|
593
|
+
if (chunk.metadata !== void 0) subagent.metadata = chunk.metadata;
|
|
594
|
+
});
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
const { messageId } = this.ensureAssistantMessage();
|
|
598
|
+
const part = {
|
|
599
|
+
type: "subagent",
|
|
600
|
+
subagent: {
|
|
601
|
+
id: chunk.subagentRunId,
|
|
602
|
+
name: chunk.name,
|
|
603
|
+
...chunk.description !== void 0 && { description: chunk.description },
|
|
604
|
+
status: "running",
|
|
605
|
+
...chunk.parentSubagentRunId !== void 0 && { parentSubagentRunId: chunk.parentSubagentRunId },
|
|
606
|
+
...chunk.parentToolCallId !== void 0 && { parentToolCallId: chunk.parentToolCallId },
|
|
607
|
+
...chunk.metadata !== void 0 && { metadata: chunk.metadata },
|
|
608
|
+
messages: []
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
this.messages = this.messages.map((message) => message.id === messageId ? {
|
|
612
|
+
...message,
|
|
613
|
+
parts: [...message.parts, part]
|
|
614
|
+
} : message);
|
|
615
|
+
this.emitMessagesChange();
|
|
616
|
+
}
|
|
617
|
+
handleSubagentFinishedEvent(chunk) {
|
|
618
|
+
if (chunk.type !== "SUBAGENT_FINISHED") return;
|
|
619
|
+
this.updateChild(chunk.subagentRunId, (child) => child.finalizeStream());
|
|
620
|
+
this.patchSubagent(chunk.subagentRunId, (subagent) => {
|
|
621
|
+
if (subagent.status === "error") return;
|
|
622
|
+
if (chunk.outcome?.type === "suspended") {
|
|
623
|
+
subagent.status = "suspended";
|
|
624
|
+
subagent.interruptIds = chunk.outcome.interruptIds ?? [];
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
subagent.status = "finished";
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
handleSubagentErrorEvent(chunk) {
|
|
631
|
+
if (chunk.type !== "SUBAGENT_ERROR") return;
|
|
632
|
+
this.updateChild(chunk.subagentRunId, (child) => child.finalizeStream());
|
|
633
|
+
this.patchSubagent(chunk.subagentRunId, (subagent) => {
|
|
634
|
+
subagent.status = "error";
|
|
635
|
+
subagent.error = {
|
|
636
|
+
message: chunk.message,
|
|
637
|
+
...chunk.code !== void 0 && { code: chunk.code }
|
|
638
|
+
};
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
patchSubagent(subagentRunId, patch) {
|
|
642
|
+
this.messages = this.messages.map((message) => {
|
|
643
|
+
const index = message.parts.findIndex((part) => part.type === "subagent" && part.subagent.id === subagentRunId);
|
|
644
|
+
if (index === -1) return message;
|
|
645
|
+
const part = message.parts[index];
|
|
646
|
+
if (!part || part.type !== "subagent") return message;
|
|
647
|
+
const next = {
|
|
648
|
+
type: "subagent",
|
|
649
|
+
subagent: { ...part.subagent }
|
|
650
|
+
};
|
|
651
|
+
patch(next.subagent);
|
|
652
|
+
const parts = [...message.parts];
|
|
653
|
+
parts[index] = next;
|
|
654
|
+
return {
|
|
655
|
+
...message,
|
|
656
|
+
parts
|
|
657
|
+
};
|
|
658
|
+
});
|
|
659
|
+
this.emitMessagesChange();
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Send a child's chunk to that child's processor, so the card keeps text,
|
|
663
|
+
* reasoning, tool calls, results, and nested children. A tool event without
|
|
664
|
+
* `subagentRunId` follows its `TOOL_CALL_START`.
|
|
665
|
+
*/
|
|
666
|
+
routeToChild(chunk) {
|
|
667
|
+
let id;
|
|
668
|
+
if (chunk.type === "SUBAGENT_STARTED") id = chunk.parentSubagentRunId;
|
|
669
|
+
else if (chunk.type === "SUBAGENT_FINISHED" || chunk.type === "SUBAGENT_ERROR") {
|
|
670
|
+
if (this.findSubagentPart(chunk.subagentRunId)) return false;
|
|
671
|
+
id = chunk.subagentRunId;
|
|
672
|
+
} else if ("subagentRunId" in chunk && chunk.subagentRunId) id = chunk.subagentRunId;
|
|
673
|
+
else if ("toolCallId" in chunk && typeof chunk.toolCallId === "string") id = this.childToolCalls.get(chunk.toolCallId);
|
|
674
|
+
if (id === void 0) return false;
|
|
675
|
+
const owner = this.childOwning(id);
|
|
676
|
+
if (owner === void 0) {
|
|
677
|
+
if (id === this.subagentRunId) return false;
|
|
678
|
+
console.warn(`[StreamProcessor] Dropped a chunk for unknown subagent ${id}`);
|
|
679
|
+
return true;
|
|
680
|
+
}
|
|
681
|
+
if (this.findSubagentPart(owner)?.part.subagent.status === "error") return true;
|
|
682
|
+
if (chunk.type === "TOOL_CALL_START") this.childToolCalls.set(chunk.toolCallId, owner);
|
|
683
|
+
this.updateChild(owner, (child) => child.processChunk(chunk));
|
|
684
|
+
return true;
|
|
685
|
+
}
|
|
500
686
|
/**
|
|
501
687
|
* Handle TEXT_MESSAGE_START event
|
|
502
688
|
*/
|
|
@@ -579,8 +765,9 @@ var StreamProcessor = class StreamProcessor {
|
|
|
579
765
|
this.resetStreamState();
|
|
580
766
|
const prevMessages = this.messages;
|
|
581
767
|
const prevById = new Map(prevMessages.map((msg) => [msg.id, msg]));
|
|
582
|
-
const
|
|
583
|
-
|
|
768
|
+
const { top, groups } = splitSubagentWire(chunk.messages);
|
|
769
|
+
const normalized = this.mergeReasoningFanOut(top.map(aguiSnapshotMessageToUIMessage));
|
|
770
|
+
const reconciled = this.reconcileSnapshotToolCalls(normalized, prevMessages).map((msg) => {
|
|
584
771
|
if (msg.metadata != null) return msg;
|
|
585
772
|
const prev = prevById.get(msg.id);
|
|
586
773
|
if (prev?.metadata == null) return msg;
|
|
@@ -589,9 +776,76 @@ var StreamProcessor = class StreamProcessor {
|
|
|
589
776
|
metadata: prev.metadata
|
|
590
777
|
};
|
|
591
778
|
});
|
|
779
|
+
this.messages = this.attachSnapshotSubagents(reconciled, top, groups, prevMessages);
|
|
592
780
|
this.emitMessagesChange();
|
|
593
781
|
}
|
|
594
782
|
/**
|
|
783
|
+
* Put subagent cards back on a snapshot. Child wire messages (tagged with
|
|
784
|
+
* `subagentRunId`) become a card on the nearest assistant message before
|
|
785
|
+
* them, or a new assistant message when there is none. A card that the
|
|
786
|
+
* snapshot does not carry stays on its message, because a server snapshot
|
|
787
|
+
* can hold the parent history only.
|
|
788
|
+
*/
|
|
789
|
+
attachSnapshotSubagents(messages, top, groups, prevMessages) {
|
|
790
|
+
const cards = [];
|
|
791
|
+
const children = /* @__PURE__ */ new Map();
|
|
792
|
+
for (const group of groups) {
|
|
793
|
+
const child = new StreamProcessor({ subagentRunId: group.id });
|
|
794
|
+
child.processChunk({
|
|
795
|
+
type: EventType.MESSAGES_SNAPSHOT,
|
|
796
|
+
messages: group.messages,
|
|
797
|
+
timestamp: Date.now()
|
|
798
|
+
});
|
|
799
|
+
children.set(group.id, child);
|
|
800
|
+
const { placeholder: _placeholder, ...info } = group.info;
|
|
801
|
+
cards.push({
|
|
802
|
+
hostId: top.slice(0, group.hostIndex + 1).findLast((message) => message.role === "assistant")?.id,
|
|
803
|
+
part: {
|
|
804
|
+
type: "subagent",
|
|
805
|
+
subagent: {
|
|
806
|
+
...info,
|
|
807
|
+
id: group.id,
|
|
808
|
+
messages: child.getMessages()
|
|
809
|
+
}
|
|
810
|
+
},
|
|
811
|
+
carried: false
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
const inSnapshot = new Set(groups.map((group) => group.id));
|
|
815
|
+
for (const message of prevMessages) for (const part of message.parts) {
|
|
816
|
+
if (part.type !== "subagent" || inSnapshot.has(part.subagent.id)) continue;
|
|
817
|
+
cards.push({
|
|
818
|
+
hostId: message.id,
|
|
819
|
+
...part.subagent.parentToolCallId !== void 0 && { toolCallId: part.subagent.parentToolCallId },
|
|
820
|
+
part,
|
|
821
|
+
carried: true
|
|
822
|
+
});
|
|
823
|
+
const kept = this.childProcessors.get(part.subagent.id);
|
|
824
|
+
if (kept) children.set(part.subagent.id, kept);
|
|
825
|
+
}
|
|
826
|
+
this.childProcessors.clear();
|
|
827
|
+
for (const [id, child] of children) this.childProcessors.set(id, child);
|
|
828
|
+
let out = messages;
|
|
829
|
+
for (const card of cards) {
|
|
830
|
+
let index = out.findIndex((message) => message.id === card.hostId);
|
|
831
|
+
if (index === -1 && card.toolCallId !== void 0) index = out.findIndex((message) => message.parts.some((part) => part.type === "tool-call" && part.id === card.toolCallId));
|
|
832
|
+
if (index === -1 && !card.carried) index = out.findLastIndex((message) => message.role === "assistant");
|
|
833
|
+
if (index === -1) {
|
|
834
|
+
if (!card.carried) out = [...out, {
|
|
835
|
+
id: generateMessageId(),
|
|
836
|
+
role: "assistant",
|
|
837
|
+
parts: [card.part]
|
|
838
|
+
}];
|
|
839
|
+
continue;
|
|
840
|
+
}
|
|
841
|
+
out = out.map((message, position) => position !== index || message.parts.some((part) => part.type === "subagent" && part.subagent.id === card.part.subagent.id) ? message : {
|
|
842
|
+
...message,
|
|
843
|
+
parts: [...message.parts, card.part]
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
return out;
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
595
849
|
* Reconcile a freshly normalized snapshot with the pre-snapshot message
|
|
596
850
|
* state so unreconstructable tool-call metadata is preserved.
|
|
597
851
|
*
|
|
@@ -636,16 +890,23 @@ var StreamProcessor = class StreamProcessor {
|
|
|
636
890
|
pending.push(msg);
|
|
637
891
|
continue;
|
|
638
892
|
}
|
|
893
|
+
let next = msg;
|
|
639
894
|
if (msg.role === "assistant" && pending.length > 0 && !isToolResultOnly(msg)) {
|
|
640
|
-
|
|
895
|
+
next = {
|
|
641
896
|
...msg,
|
|
642
897
|
parts: [...pending.flatMap(thinkingParts), ...msg.parts]
|
|
643
|
-
}
|
|
898
|
+
};
|
|
644
899
|
pending = [];
|
|
900
|
+
} else flushPending();
|
|
901
|
+
const prev = out.at(-1);
|
|
902
|
+
if (prev?.role === "assistant" && next.role === "assistant" && isAssistantSegmentOf(next.id, prev.id)) {
|
|
903
|
+
out[out.length - 1] = {
|
|
904
|
+
...prev,
|
|
905
|
+
parts: [...prev.parts, ...next.parts]
|
|
906
|
+
};
|
|
645
907
|
continue;
|
|
646
908
|
}
|
|
647
|
-
|
|
648
|
-
out.push(msg);
|
|
909
|
+
out.push(next);
|
|
649
910
|
}
|
|
650
911
|
flushPending();
|
|
651
912
|
return out;
|
|
@@ -711,7 +972,7 @@ var StreamProcessor = class StreamProcessor {
|
|
|
711
972
|
} catch {
|
|
712
973
|
output = result.content;
|
|
713
974
|
}
|
|
714
|
-
const errorText = result.state === "error" ?
|
|
975
|
+
const errorText = result.state === "error" ? toolResultErrorText(output) : void 0;
|
|
715
976
|
next = {
|
|
716
977
|
...next,
|
|
717
978
|
output: errorText ? { error: errorText } : output,
|
|
@@ -884,10 +1145,6 @@ var StreamProcessor = class StreamProcessor {
|
|
|
884
1145
|
}
|
|
885
1146
|
}
|
|
886
1147
|
}
|
|
887
|
-
extractToolResultError(output) {
|
|
888
|
-
if (output && typeof output === "object" && "error" in output && typeof output.error === "string") return output.error;
|
|
889
|
-
return typeof output === "string" ? output : "Tool execution failed";
|
|
890
|
-
}
|
|
891
1148
|
/**
|
|
892
1149
|
* Handle TOOL_CALL_RESULT event (AG-UI spec).
|
|
893
1150
|
*
|
|
@@ -901,13 +1158,13 @@ var StreamProcessor = class StreamProcessor {
|
|
|
901
1158
|
const isOutputError = chunk.state === "output-error" || tanstackMetadata(chunk)?.state === "output-error";
|
|
902
1159
|
let output;
|
|
903
1160
|
try {
|
|
904
|
-
output = JSON.parse(chunk.content);
|
|
1161
|
+
output = typeof chunk.content === "string" ? JSON.parse(chunk.content) : chunk.content;
|
|
905
1162
|
} catch {
|
|
906
1163
|
output = chunk.content;
|
|
907
1164
|
}
|
|
908
1165
|
this.messages = updateToolCallWithOutput(this.messages, chunk.toolCallId, output, isOutputError ? "error" : void 0);
|
|
909
1166
|
const resultState = isOutputError ? "error" : "complete";
|
|
910
|
-
this.messages = updateToolResultPart(this.messages, messageId, chunk.toolCallId, chunk.content, resultState, resultState === "error" ?
|
|
1167
|
+
this.messages = updateToolResultPart(this.messages, messageId, chunk.toolCallId, aguiContentToContentParts(chunk.content), resultState, resultState === "error" ? toolResultErrorText(output) : void 0);
|
|
911
1168
|
this.emitMessagesChange();
|
|
912
1169
|
}
|
|
913
1170
|
/**
|
|
@@ -941,21 +1198,38 @@ var StreamProcessor = class StreamProcessor {
|
|
|
941
1198
|
this.finalizeStream();
|
|
942
1199
|
}
|
|
943
1200
|
}
|
|
944
|
-
|
|
1201
|
+
/**
|
|
1202
|
+
* Apply interrupt state to tool-call parts, then fire the client events.
|
|
1203
|
+
* A child's interrupt updates the child's card. `emit` is false there, so
|
|
1204
|
+
* the events fire once, from the top processor.
|
|
1205
|
+
*/
|
|
1206
|
+
handleInterrupts(interrupts, emit = true) {
|
|
945
1207
|
const hasGeneric = interruptBatchHasGeneric(interrupts);
|
|
946
1208
|
for (const interrupt of interrupts) {
|
|
947
1209
|
const metadata = interrupt.metadata && typeof interrupt.metadata === "object" ? interrupt.metadata : {};
|
|
948
1210
|
const kind = typeof metadata.kind === "string" ? metadata.kind : void 0;
|
|
949
1211
|
const toolCallId = interrupt.toolCallId;
|
|
950
1212
|
if (!toolCallId) continue;
|
|
1213
|
+
const owner = interrupt.subagentRunId !== void 0 ? this.childOwning(interrupt.subagentRunId) : this.childOwningToolCall((part) => part.id === toolCallId);
|
|
1214
|
+
if (owner !== void 0) this.updateChild(owner, (child) => child.handleInterrupts([interrupt], false));
|
|
951
1215
|
const toolName = typeof metadata.toolName === "string" ? metadata.toolName : this.findToolCallName(toolCallId);
|
|
952
1216
|
const input = Object.hasOwn(metadata, "input") ? metadata.input : {};
|
|
953
1217
|
if (kind === "approval" || interrupt.reason === "approval_required") {
|
|
1218
|
+
if (owner !== void 0) {
|
|
1219
|
+
if (emit) this.events.onApprovalRequest?.({
|
|
1220
|
+
toolCallId,
|
|
1221
|
+
toolName,
|
|
1222
|
+
input,
|
|
1223
|
+
approvalId: interrupt.id
|
|
1224
|
+
});
|
|
1225
|
+
continue;
|
|
1226
|
+
}
|
|
954
1227
|
const resolvedMessageId = this.getActiveAssistantMessageId() ?? this.toolCallToMessage.get(toolCallId) ?? this.messages.find((m) => m.role === "assistant" && m.parts.some((p) => p.type === "tool-call" && p.id === toolCallId))?.id;
|
|
955
1228
|
if (resolvedMessageId) {
|
|
956
1229
|
this.messages = updateToolCallApproval(this.messages, resolvedMessageId, toolCallId, interrupt.id);
|
|
957
1230
|
this.emitMessagesChange();
|
|
958
1231
|
}
|
|
1232
|
+
if (!emit) continue;
|
|
959
1233
|
this.events.onApprovalRequest?.({
|
|
960
1234
|
toolCallId,
|
|
961
1235
|
toolName,
|
|
@@ -965,7 +1239,7 @@ var StreamProcessor = class StreamProcessor {
|
|
|
965
1239
|
continue;
|
|
966
1240
|
}
|
|
967
1241
|
if (kind === "client_tool" || interrupt.reason === "client_tool_input") {
|
|
968
|
-
if (hasGeneric) continue;
|
|
1242
|
+
if (hasGeneric || !emit) continue;
|
|
969
1243
|
this.events.onToolCall?.({
|
|
970
1244
|
toolCallId,
|
|
971
1245
|
toolName,
|
|
@@ -1473,6 +1747,8 @@ var StreamProcessor = class StreamProcessor {
|
|
|
1473
1747
|
reset() {
|
|
1474
1748
|
this.resetStreamState();
|
|
1475
1749
|
this.messages = [];
|
|
1750
|
+
this.childProcessors.clear();
|
|
1751
|
+
this.childToolCalls.clear();
|
|
1476
1752
|
}
|
|
1477
1753
|
/**
|
|
1478
1754
|
* Check if a message contains only whitespace text and no other meaningful parts
|