@tanstack/ai 0.57.0 → 0.59.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/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 +345 -19
- 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 +94 -18
- 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 +50 -3
- package/dist/esm/activities/chat/middleware/types.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +46 -0
- package/dist/esm/activities/chat/stream/processor.js +280 -7
- 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 -7
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/generateAudio/index.js +1 -1
- package/dist/esm/activities/generateImage/index.js +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/generateVoice/index.js +1 -1
- package/dist/esm/activities/generateWorld/index.js +1 -1
- package/dist/esm/activities/index.d.ts +3 -0
- package/dist/esm/activities/index.js +5 -3
- package/dist/esm/activities/summarize/index.js +1 -1
- package/dist/esm/client.d.ts +5 -36
- package/dist/esm/client.js +4 -37
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +7 -4
- package/dist/esm/middlewares/content-guard.js.map +1 -1
- package/dist/esm/stream-to-response.js +12 -6
- package/dist/esm/stream-to-response.js.map +1 -1
- package/dist/esm/strip-to-spec-middleware.js +2 -1
- package/dist/esm/strip-to-spec-middleware.js.map +1 -1
- package/dist/esm/types.d.ts +128 -89
- 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 +56 -0
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/durability-batch.d.ts +8 -0
- package/dist/esm/utilities/durability-batch.js +45 -0
- package/dist/esm/utilities/durability-batch.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/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/package.json +4 -4
- package/skills/ai-core/adapter-configuration/references/grok-adapter.md +1 -1
- package/skills/ai-core/media-generation/SKILL.md +2 -2
- package/skills/ai-core/middleware/SKILL.md +7 -4
- 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 +540 -16
- package/src/activities/chat/messages.ts +125 -15
- package/src/activities/chat/middleware/run-store.ts +56 -7
- package/src/activities/chat/middleware/types.ts +55 -2
- package/src/activities/chat/stream/processor.ts +428 -8
- package/src/activities/chat/tools/tool-calls.ts +92 -16
- package/src/activities/index.ts +15 -0
- package/src/client.ts +22 -35
- package/src/index.ts +23 -0
- package/src/middlewares/content-guard.ts +7 -5
- package/src/stream-to-response.ts +16 -6
- package/src/strip-to-spec-middleware.ts +2 -1
- package/src/types.ts +177 -95
- 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 +74 -0
- package/src/utilities/durability-batch.ts +48 -0
- package/src/utilities/normalize-stream-chunk.ts +10 -2
- package/src/utilities/spec-event-keys.ts +34 -7
- package/src/utilities/subagent-wire.ts +184 -0
|
@@ -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
5
|
import { normalizeToolResult } from "../../../utilities/tool-result.js";
|
|
6
|
+
import { splitSubagentWire } from "../../../utilities/subagent-wire.js";
|
|
5
7
|
import { isProviderExecutedToolCall } from "../../../utilities/provider-executed.js";
|
|
6
|
-
import { aguiSnapshotMessageToUIMessage, coerceCreatedAt, generateMessageId, uiMessageToModelMessages } from "../messages.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
|
*
|
|
@@ -901,13 +1155,13 @@ var StreamProcessor = class StreamProcessor {
|
|
|
901
1155
|
const isOutputError = chunk.state === "output-error" || tanstackMetadata(chunk)?.state === "output-error";
|
|
902
1156
|
let output;
|
|
903
1157
|
try {
|
|
904
|
-
output = JSON.parse(chunk.content);
|
|
1158
|
+
output = typeof chunk.content === "string" ? JSON.parse(chunk.content) : chunk.content;
|
|
905
1159
|
} catch {
|
|
906
1160
|
output = chunk.content;
|
|
907
1161
|
}
|
|
908
1162
|
this.messages = updateToolCallWithOutput(this.messages, chunk.toolCallId, output, isOutputError ? "error" : void 0);
|
|
909
1163
|
const resultState = isOutputError ? "error" : "complete";
|
|
910
|
-
this.messages = updateToolResultPart(this.messages, messageId, chunk.toolCallId, chunk.content, resultState, resultState === "error" ? this.extractToolResultError(output) : void 0);
|
|
1164
|
+
this.messages = updateToolResultPart(this.messages, messageId, chunk.toolCallId, aguiContentToContentParts(chunk.content), resultState, resultState === "error" ? this.extractToolResultError(output) : void 0);
|
|
911
1165
|
this.emitMessagesChange();
|
|
912
1166
|
}
|
|
913
1167
|
/**
|
|
@@ -941,21 +1195,38 @@ var StreamProcessor = class StreamProcessor {
|
|
|
941
1195
|
this.finalizeStream();
|
|
942
1196
|
}
|
|
943
1197
|
}
|
|
944
|
-
|
|
1198
|
+
/**
|
|
1199
|
+
* Apply interrupt state to tool-call parts, then fire the client events.
|
|
1200
|
+
* A child's interrupt updates the child's card. `emit` is false there, so
|
|
1201
|
+
* the events fire once, from the top processor.
|
|
1202
|
+
*/
|
|
1203
|
+
handleInterrupts(interrupts, emit = true) {
|
|
945
1204
|
const hasGeneric = interruptBatchHasGeneric(interrupts);
|
|
946
1205
|
for (const interrupt of interrupts) {
|
|
947
1206
|
const metadata = interrupt.metadata && typeof interrupt.metadata === "object" ? interrupt.metadata : {};
|
|
948
1207
|
const kind = typeof metadata.kind === "string" ? metadata.kind : void 0;
|
|
949
1208
|
const toolCallId = interrupt.toolCallId;
|
|
950
1209
|
if (!toolCallId) continue;
|
|
1210
|
+
const owner = interrupt.subagentRunId !== void 0 ? this.childOwning(interrupt.subagentRunId) : this.childOwningToolCall((part) => part.id === toolCallId);
|
|
1211
|
+
if (owner !== void 0) this.updateChild(owner, (child) => child.handleInterrupts([interrupt], false));
|
|
951
1212
|
const toolName = typeof metadata.toolName === "string" ? metadata.toolName : this.findToolCallName(toolCallId);
|
|
952
1213
|
const input = Object.hasOwn(metadata, "input") ? metadata.input : {};
|
|
953
1214
|
if (kind === "approval" || interrupt.reason === "approval_required") {
|
|
1215
|
+
if (owner !== void 0) {
|
|
1216
|
+
if (emit) this.events.onApprovalRequest?.({
|
|
1217
|
+
toolCallId,
|
|
1218
|
+
toolName,
|
|
1219
|
+
input,
|
|
1220
|
+
approvalId: interrupt.id
|
|
1221
|
+
});
|
|
1222
|
+
continue;
|
|
1223
|
+
}
|
|
954
1224
|
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
1225
|
if (resolvedMessageId) {
|
|
956
1226
|
this.messages = updateToolCallApproval(this.messages, resolvedMessageId, toolCallId, interrupt.id);
|
|
957
1227
|
this.emitMessagesChange();
|
|
958
1228
|
}
|
|
1229
|
+
if (!emit) continue;
|
|
959
1230
|
this.events.onApprovalRequest?.({
|
|
960
1231
|
toolCallId,
|
|
961
1232
|
toolName,
|
|
@@ -965,7 +1236,7 @@ var StreamProcessor = class StreamProcessor {
|
|
|
965
1236
|
continue;
|
|
966
1237
|
}
|
|
967
1238
|
if (kind === "client_tool" || interrupt.reason === "client_tool_input") {
|
|
968
|
-
if (hasGeneric) continue;
|
|
1239
|
+
if (hasGeneric || !emit) continue;
|
|
969
1240
|
this.events.onToolCall?.({
|
|
970
1241
|
toolCallId,
|
|
971
1242
|
toolName,
|
|
@@ -1473,6 +1744,8 @@ var StreamProcessor = class StreamProcessor {
|
|
|
1473
1744
|
reset() {
|
|
1474
1745
|
this.resetStreamState();
|
|
1475
1746
|
this.messages = [];
|
|
1747
|
+
this.childProcessors.clear();
|
|
1748
|
+
this.childToolCalls.clear();
|
|
1476
1749
|
}
|
|
1477
1750
|
/**
|
|
1478
1751
|
* Check if a message contains only whitespace text and no other meaningful parts
|