@assistant-ui/react-ag-ui 0.1.0 → 0.1.2
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/README.md +2 -0
- package/dist/agUiExtras.js +1 -2
- package/dist/hooks.js +1 -2
- package/dist/runtime/AgUiThreadController.d.ts +11 -0
- package/dist/runtime/AgUiThreadController.d.ts.map +1 -1
- package/dist/runtime/AgUiThreadController.js +565 -89
- package/dist/runtime/AgUiThreadController.js.map +1 -1
- package/dist/runtime/adapter/conversions.d.ts +9 -1
- package/dist/runtime/adapter/conversions.d.ts.map +1 -1
- package/dist/runtime/adapter/conversions.js +194 -12
- package/dist/runtime/adapter/conversions.js.map +1 -1
- package/dist/runtime/adapter/replay-content.d.ts +9 -0
- package/dist/runtime/adapter/replay-content.d.ts.map +1 -0
- package/dist/runtime/adapter/replay-content.js +185 -0
- package/dist/runtime/adapter/replay-content.js.map +1 -0
- package/dist/runtime/adapter/run-aggregator.d.ts +1 -0
- package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
- package/dist/runtime/adapter/run-aggregator.js +35 -14
- package/dist/runtime/adapter/run-aggregator.js.map +1 -1
- package/dist/runtime/adapter/subscriber.d.ts +0 -1
- package/dist/runtime/adapter/subscriber.d.ts.map +1 -1
- package/dist/runtime/adapter/subscriber.js +2 -10
- package/dist/runtime/adapter/subscriber.js.map +1 -1
- package/dist/runtime/adapter/tool-approval.d.ts +2 -0
- package/dist/runtime/adapter/tool-approval.d.ts.map +1 -1
- package/dist/runtime/adapter/tool-approval.js +23 -6
- package/dist/runtime/adapter/tool-approval.js.map +1 -1
- package/dist/runtime/agUiThreadState.d.ts +1 -1
- package/dist/runtime/agUiThreadState.d.ts.map +1 -1
- package/dist/runtime/agUiThreadState.js +3 -4
- package/dist/runtime/agUiThreadState.js.map +1 -1
- package/dist/runtime/event-parser.d.ts.map +1 -1
- package/dist/runtime/event-parser.js +2 -2
- package/dist/runtime/event-parser.js.map +1 -1
- package/dist/runtime/interrupt-internals.js +1 -2
- package/dist/runtime/logger.js +1 -2
- package/dist/runtime/mcp-tool-result.js +1 -2
- package/dist/runtime/types.d.ts +2 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js +3 -3
- package/dist/runtime/types.js.map +1 -1
- package/dist/useAgUiRuntime.js +1 -2
- package/package.json +6 -6
- package/src/runtime/AgUiThreadController.deferred-results.test.ts +548 -0
- package/src/runtime/AgUiThreadController.disconnect.test.ts +914 -0
- package/src/runtime/AgUiThreadController.interrupt-history.test.ts +392 -0
- package/src/runtime/AgUiThreadController.replay.test.ts +3939 -0
- package/src/runtime/AgUiThreadController.snapshot-head-move.test.ts +167 -0
- package/src/runtime/AgUiThreadController.subagent-snapshot.test.ts +854 -0
- package/src/runtime/AgUiThreadController.test.ts +119 -0
- package/src/runtime/AgUiThreadController.ts +1184 -136
- package/src/runtime/adapter/conversions.content.test.ts +242 -1
- package/src/runtime/adapter/conversions.subagent-messages.test.ts +550 -0
- package/src/runtime/adapter/conversions.ts +349 -28
- package/src/runtime/adapter/replay-content.test.ts +235 -0
- package/src/runtime/adapter/replay-content.ts +306 -0
- package/src/runtime/adapter/run-aggregator.metadata.test.ts +151 -0
- package/src/runtime/adapter/run-aggregator.ts +52 -9
- package/src/runtime/adapter/subscriber.test.ts +1 -1
- package/src/runtime/adapter/subscriber.ts +1 -6
- package/src/runtime/adapter/tool-approval.ts +41 -3
- package/src/runtime/agUiThreadState.test.ts +21 -2
- package/src/runtime/agUiThreadState.ts +12 -3
- package/src/runtime/event-parser.ts +3 -0
- package/src/runtime/types.ts +5 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { preserveToolApprovalDecision } from "./tool-approval.js";
|
|
2
|
+
import { iterateToolCallParts, mapToolCallPartsDeep } from "@assistant-ui/core/internal";
|
|
3
|
+
// src/runtime/adapter/replay-content.ts
|
|
4
|
+
function indexReplayToolOwners(owners) {
|
|
5
|
+
const ownerByToolCallId = /* @__PURE__ */ new Map();
|
|
6
|
+
for (const owner of owners) for (const part of iterateToolCallParts(owner.content)) if (!ownerByToolCallId.has(part.toolCallId)) ownerByToolCallId.set(part.toolCallId, owner.id);
|
|
7
|
+
return ownerByToolCallId;
|
|
8
|
+
}
|
|
9
|
+
function groupReplayToolContent(owners, content, fallbackMessageId) {
|
|
10
|
+
const ownerByToolCallId = indexReplayToolOwners(owners);
|
|
11
|
+
const grouped = /* @__PURE__ */ new Map([[fallbackMessageId, []]]);
|
|
12
|
+
for (const part of content) {
|
|
13
|
+
const ownerId = part.type === "tool-call" ? ownerByToolCallId.get(part.toolCallId) ?? fallbackMessageId : fallbackMessageId;
|
|
14
|
+
const parts = grouped.get(ownerId) ?? [];
|
|
15
|
+
parts.push(part);
|
|
16
|
+
grouped.set(ownerId, parts);
|
|
17
|
+
}
|
|
18
|
+
return grouped;
|
|
19
|
+
}
|
|
20
|
+
function preserveToolResult(previous, next) {
|
|
21
|
+
if (previous.result === void 0 || next.result !== void 0) return next;
|
|
22
|
+
return {
|
|
23
|
+
...next,
|
|
24
|
+
result: previous.result,
|
|
25
|
+
...previous.artifact !== void 0 ? { artifact: previous.artifact } : {},
|
|
26
|
+
...previous.isError !== void 0 ? { isError: previous.isError } : {},
|
|
27
|
+
...previous.modelContent !== void 0 ? { modelContent: previous.modelContent } : {}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function mergeOrdered(previous, next, merge) {
|
|
31
|
+
const old = new Map(previous.map(([value, key]) => [key, value]));
|
|
32
|
+
const indexes = new Map(next.map(([, key], index) => [key, index]));
|
|
33
|
+
const insertions = Array.from({ length: next.length + 1 }, () => []);
|
|
34
|
+
let predecessor = -1;
|
|
35
|
+
for (const [value, key] of previous) {
|
|
36
|
+
const index = indexes.get(key);
|
|
37
|
+
if (index === void 0) insertions[predecessor + 1].push(value);
|
|
38
|
+
else predecessor = index;
|
|
39
|
+
}
|
|
40
|
+
const result = [];
|
|
41
|
+
for (const [index, [value, key]] of next.entries()) {
|
|
42
|
+
const prior = old.get(key);
|
|
43
|
+
result.push(...insertions[index], prior === void 0 ? value : merge(prior, value));
|
|
44
|
+
}
|
|
45
|
+
result.push(...insertions[next.length]);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
function mergeMessages(previous, next) {
|
|
49
|
+
return mergeOrdered(previous.map((message) => [message, message.id]), next.map((message) => [message, message.id]), (old, fresh) => old.role === "assistant" && fresh.role === "assistant" ? {
|
|
50
|
+
...fresh,
|
|
51
|
+
content: mergeReplayContent(old.content, fresh.content)
|
|
52
|
+
} : fresh);
|
|
53
|
+
}
|
|
54
|
+
function mergeTool(previous, next) {
|
|
55
|
+
const result = preserveToolResult(previous, next);
|
|
56
|
+
const approval = preserveToolApprovalDecision(previous, next);
|
|
57
|
+
return {
|
|
58
|
+
...result,
|
|
59
|
+
...approval ? { approval } : {},
|
|
60
|
+
...result.unstable_interactions === void 0 && previous.unstable_interactions !== void 0 ? { unstable_interactions: previous.unstable_interactions } : {},
|
|
61
|
+
...previous.messages !== void 0 || next.messages !== void 0 ? { messages: mergeMessages(previous.messages ?? [], next.messages ?? []) } : {}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function partKey(part) {
|
|
65
|
+
if (part.type === "tool-call") return `tool:${part.toolCallId}`;
|
|
66
|
+
if (part.type === "text" || part.type === "reasoning") return part.type;
|
|
67
|
+
if ("id" in part && typeof part.id === "string" && part.id) return `${part.type}:${part.id}`;
|
|
68
|
+
if (part.type === "data") return `data:${part.name}`;
|
|
69
|
+
return part.type;
|
|
70
|
+
}
|
|
71
|
+
function keyed(content) {
|
|
72
|
+
const ordinals = /* @__PURE__ */ new Map();
|
|
73
|
+
return content.map((part) => {
|
|
74
|
+
const base = partKey(part);
|
|
75
|
+
const ordinal = ordinals.get(base) ?? 0;
|
|
76
|
+
ordinals.set(base, ordinal + 1);
|
|
77
|
+
return [part, `${base}:${ordinal}`];
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function identity(part, key, scope) {
|
|
81
|
+
return JSON.stringify(part.type === "tool-call" ? ["tool", part.toolCallId] : [...scope, key]);
|
|
82
|
+
}
|
|
83
|
+
function visitMessages(messages, scope, visit) {
|
|
84
|
+
for (const message of messages) {
|
|
85
|
+
const path = [
|
|
86
|
+
...scope,
|
|
87
|
+
"message",
|
|
88
|
+
message.id
|
|
89
|
+
];
|
|
90
|
+
visit(JSON.stringify(path));
|
|
91
|
+
if (message.role === "assistant") visitContent(message.content, path, visit);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function visitContent(content, scope, visit) {
|
|
95
|
+
for (const [part, key] of keyed(content)) {
|
|
96
|
+
visit(identity(part, key, scope));
|
|
97
|
+
if (part.type === "tool-call" && part.messages) visitMessages(part.messages, ["tool", part.toolCallId], visit);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function pruneMessages(messages, scope, present, owned) {
|
|
101
|
+
let hasCurrent = false;
|
|
102
|
+
return {
|
|
103
|
+
messages: messages.flatMap((message) => {
|
|
104
|
+
const path = [
|
|
105
|
+
...scope,
|
|
106
|
+
"message",
|
|
107
|
+
message.id
|
|
108
|
+
];
|
|
109
|
+
const key = JSON.stringify(path);
|
|
110
|
+
const nested = message.role === "assistant" ? pruneContent(message.content, path, present, owned) : void 0;
|
|
111
|
+
const current = present.has(key) || (nested?.hasCurrent ?? false);
|
|
112
|
+
if (owned.has(key) && !current) return [];
|
|
113
|
+
hasCurrent ||= current;
|
|
114
|
+
return [nested && message.role === "assistant" ? {
|
|
115
|
+
...message,
|
|
116
|
+
content: nested.content
|
|
117
|
+
} : message];
|
|
118
|
+
}),
|
|
119
|
+
hasCurrent
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function pruneContent(content, scope, present, owned) {
|
|
123
|
+
let hasCurrent = false;
|
|
124
|
+
return {
|
|
125
|
+
content: keyed(content).flatMap(([part, localKey]) => {
|
|
126
|
+
const key = identity(part, localKey, scope);
|
|
127
|
+
const nested = part.type === "tool-call" && part.messages ? pruneMessages(part.messages, ["tool", part.toolCallId], present, owned) : void 0;
|
|
128
|
+
const current = present.has(key) || (nested?.hasCurrent ?? false);
|
|
129
|
+
if (owned.has(key) && !current) return [];
|
|
130
|
+
hasCurrent ||= current;
|
|
131
|
+
return [nested ? {
|
|
132
|
+
...part,
|
|
133
|
+
messages: nested.messages
|
|
134
|
+
} : part];
|
|
135
|
+
}),
|
|
136
|
+
hasCurrent
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function createReplayContentMerger() {
|
|
140
|
+
const owned = /* @__PURE__ */ new Set();
|
|
141
|
+
return (previous, next) => {
|
|
142
|
+
const present = /* @__PURE__ */ new Set();
|
|
143
|
+
visitContent(next, [], (key) => present.add(key));
|
|
144
|
+
for (const key of present) owned.add(key);
|
|
145
|
+
return pruneContent(mergeReplayContent(previous, next), [], present, owned).content;
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function nestedToolIds(content) {
|
|
149
|
+
const nestedIds = /* @__PURE__ */ new Set();
|
|
150
|
+
for (const part of content) {
|
|
151
|
+
if (part.type !== "tool-call") continue;
|
|
152
|
+
for (const message of part.messages ?? []) {
|
|
153
|
+
if (message.role !== "assistant") continue;
|
|
154
|
+
for (const child of iterateToolCallParts(message.content)) nestedIds.add(child.toolCallId);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return nestedIds;
|
|
158
|
+
}
|
|
159
|
+
function mergeReplayContent(previous, next) {
|
|
160
|
+
const nestedIds = nestedToolIds(previous);
|
|
161
|
+
const incomingNestedIds = nestedToolIds(next);
|
|
162
|
+
const movingRoots = new Map(previous.flatMap((part) => part.type === "tool-call" && incomingNestedIds.has(part.toolCallId) ? [[part.toolCallId, part]] : []));
|
|
163
|
+
const flattened = /* @__PURE__ */ new Map();
|
|
164
|
+
for (const part of next) if (part.type === "tool-call" && nestedIds.has(part.toolCallId)) flattened.set(part.toolCallId, part);
|
|
165
|
+
const prior = (flattened.size ? mapToolCallPartsDeep(previous, (part) => {
|
|
166
|
+
const fresh = flattened.get(part.toolCallId);
|
|
167
|
+
return fresh ? mergeTool(part, fresh) : part;
|
|
168
|
+
}).content : previous).filter((part) => part.type !== "tool-call" || !movingRoots.has(part.toolCallId));
|
|
169
|
+
let incoming = next.filter((part) => part.type !== "tool-call" || !flattened.has(part.toolCallId));
|
|
170
|
+
if (movingRoots.size) incoming = [...mapToolCallPartsDeep(incoming, (part) => {
|
|
171
|
+
const prior = movingRoots.get(part.toolCallId);
|
|
172
|
+
return prior ? mergeTool(prior, part) : part;
|
|
173
|
+
}).content];
|
|
174
|
+
return mergeOrdered(keyed(prior), keyed(incoming), (old, fresh) => {
|
|
175
|
+
if (old.type === "tool-call" && fresh.type === "tool-call") return mergeTool(old, fresh);
|
|
176
|
+
if ((old.type === "text" || old.type === "reasoning") && (fresh.type === "text" || fresh.type === "reasoning") && old.text.startsWith(fresh.text) && old.text.length > fresh.text.length) return {
|
|
177
|
+
...fresh,
|
|
178
|
+
text: old.text
|
|
179
|
+
};
|
|
180
|
+
return fresh;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
export { createReplayContentMerger, groupReplayToolContent, indexReplayToolOwners, preserveToolResult };
|
|
184
|
+
|
|
185
|
+
//# sourceMappingURL=replay-content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay-content.js","names":[],"sources":["../../../src/runtime/adapter/replay-content.ts"],"sourcesContent":["import type {\n ThreadAssistantMessage,\n ThreadMessage,\n ToolCallMessagePart,\n} from \"@assistant-ui/core\";\nimport {\n iterateToolCallParts,\n mapToolCallPartsDeep,\n} from \"@assistant-ui/core/internal\";\n\nimport { preserveToolApprovalDecision } from \"./tool-approval\";\n\ntype Content = ThreadAssistantMessage[\"content\"];\ntype Part = Content[number];\n\nexport function indexReplayToolOwners(\n owners: readonly ThreadAssistantMessage[],\n): ReadonlyMap<string, string> {\n const ownerByToolCallId = new Map<string, string>();\n for (const owner of owners) {\n for (const part of iterateToolCallParts(owner.content)) {\n if (!ownerByToolCallId.has(part.toolCallId))\n ownerByToolCallId.set(part.toolCallId, owner.id);\n }\n }\n return ownerByToolCallId;\n}\n\nexport function groupReplayToolContent(\n owners: readonly ThreadAssistantMessage[],\n content: Content,\n fallbackMessageId: string,\n): Map<string, Part[]> {\n const ownerByToolCallId = indexReplayToolOwners(owners);\n const grouped = new Map<string, Part[]>([[fallbackMessageId, []]]);\n for (const part of content) {\n const ownerId =\n part.type === \"tool-call\"\n ? (ownerByToolCallId.get(part.toolCallId) ?? fallbackMessageId)\n : fallbackMessageId;\n const parts = grouped.get(ownerId) ?? [];\n parts.push(part);\n grouped.set(ownerId, parts);\n }\n return grouped;\n}\n\nexport function preserveToolResult(\n previous: ToolCallMessagePart,\n next: ToolCallMessagePart,\n): ToolCallMessagePart {\n if (previous.result === undefined || next.result !== undefined) return next;\n return {\n ...next,\n result: previous.result,\n ...(previous.artifact !== undefined ? { artifact: previous.artifact } : {}),\n ...(previous.isError !== undefined ? { isError: previous.isError } : {}),\n ...(previous.modelContent !== undefined\n ? { modelContent: previous.modelContent }\n : {}),\n };\n}\n\nfunction mergeOrdered<T>(\n previous: readonly (readonly [T, string])[],\n next: readonly (readonly [T, string])[],\n merge: (old: T, fresh: T) => T,\n): T[] {\n const old = new Map(previous.map(([value, key]) => [key, value] as const));\n const indexes = new Map(next.map(([, key], index) => [key, index] as const));\n const insertions: T[][] = Array.from({ length: next.length + 1 }, () => []);\n let predecessor = -1;\n for (const [value, key] of previous) {\n const index = indexes.get(key);\n if (index === undefined) insertions[predecessor + 1]!.push(value);\n else predecessor = index;\n }\n const result: T[] = [];\n for (const [index, [value, key]] of next.entries()) {\n const prior = old.get(key);\n result.push(\n ...insertions[index]!,\n prior === undefined ? value : merge(prior, value),\n );\n }\n result.push(...insertions[next.length]!);\n return result;\n}\n\nfunction mergeMessages(\n previous: readonly ThreadMessage[],\n next: readonly ThreadMessage[],\n): readonly ThreadMessage[] {\n return mergeOrdered(\n previous.map((message) => [message, message.id] as const),\n next.map((message) => [message, message.id] as const),\n (old, fresh) =>\n old.role === \"assistant\" && fresh.role === \"assistant\"\n ? { ...fresh, content: mergeReplayContent(old.content, fresh.content) }\n : fresh,\n );\n}\n\nfunction mergeTool(\n previous: ToolCallMessagePart,\n next: ToolCallMessagePart,\n): ToolCallMessagePart {\n const result = preserveToolResult(previous, next);\n const approval = preserveToolApprovalDecision(previous, next);\n return {\n ...result,\n ...(approval ? { approval } : {}),\n ...(result.unstable_interactions === undefined &&\n previous.unstable_interactions !== undefined\n ? { unstable_interactions: previous.unstable_interactions }\n : {}),\n ...(previous.messages !== undefined || next.messages !== undefined\n ? {\n messages: mergeMessages(previous.messages ?? [], next.messages ?? []),\n }\n : {}),\n };\n}\n\nfunction partKey(part: Part): string {\n if (part.type === \"tool-call\") return `tool:${part.toolCallId}`;\n if (part.type === \"text\" || part.type === \"reasoning\") return part.type;\n if (\"id\" in part && typeof part.id === \"string\" && part.id)\n return `${part.type}:${part.id}`;\n if (part.type === \"data\") return `data:${part.name}`;\n return part.type;\n}\n\nfunction keyed(content: Content): [Part, string][] {\n const ordinals = new Map<string, number>();\n return content.map((part) => {\n const base = partKey(part);\n const ordinal = ordinals.get(base) ?? 0;\n ordinals.set(base, ordinal + 1);\n return [part, `${base}:${ordinal}`] as [Part, string];\n });\n}\n\nfunction identity(part: Part, key: string, scope: readonly string[]): string {\n return JSON.stringify(\n part.type === \"tool-call\" ? [\"tool\", part.toolCallId] : [...scope, key],\n );\n}\n\nfunction visitMessages(\n messages: readonly ThreadMessage[],\n scope: readonly string[],\n visit: (key: string) => void,\n): void {\n for (const message of messages) {\n const path = [...scope, \"message\", message.id];\n visit(JSON.stringify(path));\n if (message.role === \"assistant\")\n visitContent(message.content, path, visit);\n }\n}\n\nfunction visitContent(\n content: Content,\n scope: readonly string[],\n visit: (key: string) => void,\n): void {\n for (const [part, key] of keyed(content)) {\n visit(identity(part, key, scope));\n if (part.type === \"tool-call\" && part.messages)\n visitMessages(part.messages, [\"tool\", part.toolCallId], visit);\n }\n}\n\nfunction pruneMessages(\n messages: readonly ThreadMessage[],\n scope: readonly string[],\n present: ReadonlySet<string>,\n owned: ReadonlySet<string>,\n): { messages: readonly ThreadMessage[]; hasCurrent: boolean } {\n let hasCurrent = false;\n const kept = messages.flatMap((message) => {\n const path = [...scope, \"message\", message.id];\n const key = JSON.stringify(path);\n const nested =\n message.role === \"assistant\"\n ? pruneContent(message.content, path, present, owned)\n : undefined;\n const current = present.has(key) || (nested?.hasCurrent ?? false);\n if (owned.has(key) && !current) return [];\n hasCurrent ||= current;\n return [\n nested && message.role === \"assistant\"\n ? { ...message, content: nested.content }\n : message,\n ];\n });\n return { messages: kept, hasCurrent };\n}\n\nfunction pruneContent(\n content: Content,\n scope: readonly string[],\n present: ReadonlySet<string>,\n owned: ReadonlySet<string>,\n): { content: Content; hasCurrent: boolean } {\n let hasCurrent = false;\n const kept = keyed(content).flatMap(([part, localKey]) => {\n const key = identity(part, localKey, scope);\n const nested =\n part.type === \"tool-call\" && part.messages\n ? pruneMessages(\n part.messages,\n [\"tool\", part.toolCallId],\n present,\n owned,\n )\n : undefined;\n const current = present.has(key) || (nested?.hasCurrent ?? false);\n if (owned.has(key) && !current) return [];\n hasCurrent ||= current;\n return [nested ? { ...part, messages: nested.messages } : part];\n });\n return { content: kept, hasCurrent };\n}\n\nexport function createReplayContentMerger(): (\n previous: Content,\n next: Content,\n) => Content {\n // Remember stream-owned identities, never a second copy of tool payloads.\n const owned = new Set<string>();\n return (previous, next) => {\n const present = new Set<string>();\n visitContent(next, [], (key) => present.add(key));\n for (const key of present) owned.add(key);\n return pruneContent(mergeReplayContent(previous, next), [], present, owned)\n .content;\n };\n}\n\nfunction nestedToolIds(content: Content): Set<string> {\n const nestedIds = new Set<string>();\n for (const part of content) {\n if (part.type !== \"tool-call\") continue;\n for (const message of part.messages ?? []) {\n if (message.role !== \"assistant\") continue;\n for (const child of iterateToolCallParts(message.content)) {\n nestedIds.add(child.toolCallId);\n }\n }\n }\n return nestedIds;\n}\n\nfunction mergeReplayContent(previous: Content, next: Content): Content {\n const nestedIds = nestedToolIds(previous);\n const incomingNestedIds = nestedToolIds(next);\n const movingRoots = new Map(\n previous.flatMap((part) =>\n part.type === \"tool-call\" && incomingNestedIds.has(part.toolCallId)\n ? [[part.toolCallId, part] as const]\n : [],\n ),\n );\n const flattened = new Map<string, ToolCallMessagePart>();\n for (const part of next) {\n if (part.type === \"tool-call\" && nestedIds.has(part.toolCallId)) {\n flattened.set(part.toolCallId, part);\n }\n }\n const prior = (\n flattened.size\n ? mapToolCallPartsDeep(previous, (part) => {\n const fresh = flattened.get(part.toolCallId);\n return fresh ? mergeTool(part, fresh) : part;\n }).content\n : previous\n ).filter(\n (part) => part.type !== \"tool-call\" || !movingRoots.has(part.toolCallId),\n );\n let incoming = next.filter(\n (part) => part.type !== \"tool-call\" || !flattened.has(part.toolCallId),\n );\n if (movingRoots.size) {\n incoming = [\n ...mapToolCallPartsDeep(incoming, (part) => {\n const prior = movingRoots.get(part.toolCallId);\n return prior ? mergeTool(prior, part) : part;\n }).content,\n ];\n }\n return mergeOrdered(keyed(prior), keyed(incoming), (old, fresh) => {\n if (old.type === \"tool-call\" && fresh.type === \"tool-call\")\n return mergeTool(old, fresh);\n if (\n (old.type === \"text\" || old.type === \"reasoning\") &&\n (fresh.type === \"text\" || fresh.type === \"reasoning\") &&\n old.text.startsWith(fresh.text) &&\n old.text.length > fresh.text.length\n ) {\n return { ...fresh, text: old.text };\n }\n return fresh;\n });\n}\n"],"mappings":";;;AAeA,SAAgB,sBACd,QAC6B;CAC7B,MAAM,oCAAoB,IAAI,IAAoB;CAClD,KAAK,MAAM,SAAS,QAClB,KAAK,MAAM,QAAQ,qBAAqB,MAAM,OAAO,GACnD,IAAI,CAAC,kBAAkB,IAAI,KAAK,UAAU,GACxC,kBAAkB,IAAI,KAAK,YAAY,MAAM,EAAE;CAGrD,OAAO;AACT;AAEA,SAAgB,uBACd,QACA,SACA,mBACqB;CACrB,MAAM,oBAAoB,sBAAsB,MAAM;CACtD,MAAM,0BAAU,IAAI,IAAoB,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;CACjE,KAAK,MAAM,QAAQ,SAAS;EAC1B,MAAM,UACJ,KAAK,SAAS,cACT,kBAAkB,IAAI,KAAK,UAAU,KAAK,oBAC3C;EACN,MAAM,QAAQ,QAAQ,IAAI,OAAO,KAAK,CAAC;EACvC,MAAM,KAAK,IAAI;EACf,QAAQ,IAAI,SAAS,KAAK;CAC5B;CACA,OAAO;AACT;AAEA,SAAgB,mBACd,UACA,MACqB;CACrB,IAAI,SAAS,WAAW,KAAA,KAAa,KAAK,WAAW,KAAA,GAAW,OAAO;CACvE,OAAO;EACL,GAAG;EACH,QAAQ,SAAS;EACjB,GAAI,SAAS,aAAa,KAAA,IAAY,EAAE,UAAU,SAAS,SAAS,IAAI,CAAC;EACzE,GAAI,SAAS,YAAY,KAAA,IAAY,EAAE,SAAS,SAAS,QAAQ,IAAI,CAAC;EACtE,GAAI,SAAS,iBAAiB,KAAA,IAC1B,EAAE,cAAc,SAAS,aAAa,IACtC,CAAC;CACP;AACF;AAEA,SAAS,aACP,UACA,MACA,OACK;CACL,MAAM,MAAM,IAAI,IAAI,SAAS,KAAK,CAAC,OAAO,SAAS,CAAC,KAAK,KAAK,CAAU,CAAC;CACzE,MAAM,UAAU,IAAI,IAAI,KAAK,KAAK,GAAG,MAAM,UAAU,CAAC,KAAK,KAAK,CAAU,CAAC;CAC3E,MAAM,aAAoB,MAAM,KAAK,EAAE,QAAQ,KAAK,SAAS,EAAE,SAAS,CAAC,CAAC;CAC1E,IAAI,cAAc;CAClB,KAAK,MAAM,CAAC,OAAO,QAAQ,UAAU;EACnC,MAAM,QAAQ,QAAQ,IAAI,GAAG;EAC7B,IAAI,UAAU,KAAA,GAAW,WAAW,cAAc,EAAE,CAAE,KAAK,KAAK;OAC3D,cAAc;CACrB;CACA,MAAM,SAAc,CAAC;CACrB,KAAK,MAAM,CAAC,OAAO,CAAC,OAAO,SAAS,KAAK,QAAQ,GAAG;EAClD,MAAM,QAAQ,IAAI,IAAI,GAAG;EACzB,OAAO,KACL,GAAG,WAAW,QACd,UAAU,KAAA,IAAY,QAAQ,MAAM,OAAO,KAAK,CAClD;CACF;CACA,OAAO,KAAK,GAAG,WAAW,KAAK,OAAQ;CACvC,OAAO;AACT;AAEA,SAAS,cACP,UACA,MAC0B;CAC1B,OAAO,aACL,SAAS,KAAK,YAAY,CAAC,SAAS,QAAQ,EAAE,CAAU,GACxD,KAAK,KAAK,YAAY,CAAC,SAAS,QAAQ,EAAE,CAAU,IACnD,KAAK,UACJ,IAAI,SAAS,eAAe,MAAM,SAAS,cACvC;EAAE,GAAG;EAAO,SAAS,mBAAmB,IAAI,SAAS,MAAM,OAAO;CAAE,IACpE,KACR;AACF;AAEA,SAAS,UACP,UACA,MACqB;CACrB,MAAM,SAAS,mBAAmB,UAAU,IAAI;CAChD,MAAM,WAAW,6BAA6B,UAAU,IAAI;CAC5D,OAAO;EACL,GAAG;EACH,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;EAC/B,GAAI,OAAO,0BAA0B,KAAA,KACrC,SAAS,0BAA0B,KAAA,IAC/B,EAAE,uBAAuB,SAAS,sBAAsB,IACxD,CAAC;EACL,GAAI,SAAS,aAAa,KAAA,KAAa,KAAK,aAAa,KAAA,IACrD,EACE,UAAU,cAAc,SAAS,YAAY,CAAC,GAAG,KAAK,YAAY,CAAC,CAAC,EACtE,IACA,CAAC;CACP;AACF;AAEA,SAAS,QAAQ,MAAoB;CACnC,IAAI,KAAK,SAAS,aAAa,OAAO,QAAQ,KAAK;CACnD,IAAI,KAAK,SAAS,UAAU,KAAK,SAAS,aAAa,OAAO,KAAK;CACnE,IAAI,QAAQ,QAAQ,OAAO,KAAK,OAAO,YAAY,KAAK,IACtD,OAAO,GAAG,KAAK,KAAK,GAAG,KAAK;CAC9B,IAAI,KAAK,SAAS,QAAQ,OAAO,QAAQ,KAAK;CAC9C,OAAO,KAAK;AACd;AAEA,SAAS,MAAM,SAAoC;CACjD,MAAM,2BAAW,IAAI,IAAoB;CACzC,OAAO,QAAQ,KAAK,SAAS;EAC3B,MAAM,OAAO,QAAQ,IAAI;EACzB,MAAM,UAAU,SAAS,IAAI,IAAI,KAAK;EACtC,SAAS,IAAI,MAAM,UAAU,CAAC;EAC9B,OAAO,CAAC,MAAM,GAAG,KAAK,GAAG,SAAS;CACpC,CAAC;AACH;AAEA,SAAS,SAAS,MAAY,KAAa,OAAkC;CAC3E,OAAO,KAAK,UACV,KAAK,SAAS,cAAc,CAAC,QAAQ,KAAK,UAAU,IAAI,CAAC,GAAG,OAAO,GAAG,CACxE;AACF;AAEA,SAAS,cACP,UACA,OACA,OACM;CACN,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,OAAO;GAAC,GAAG;GAAO;GAAW,QAAQ;EAAE;EAC7C,MAAM,KAAK,UAAU,IAAI,CAAC;EAC1B,IAAI,QAAQ,SAAS,aACnB,aAAa,QAAQ,SAAS,MAAM,KAAK;CAC7C;AACF;AAEA,SAAS,aACP,SACA,OACA,OACM;CACN,KAAK,MAAM,CAAC,MAAM,QAAQ,MAAM,OAAO,GAAG;EACxC,MAAM,SAAS,MAAM,KAAK,KAAK,CAAC;EAChC,IAAI,KAAK,SAAS,eAAe,KAAK,UACpC,cAAc,KAAK,UAAU,CAAC,QAAQ,KAAK,UAAU,GAAG,KAAK;CACjE;AACF;AAEA,SAAS,cACP,UACA,OACA,SACA,OAC6D;CAC7D,IAAI,aAAa;CAiBjB,OAAO;EAAE,UAhBI,SAAS,SAAS,YAAY;GACzC,MAAM,OAAO;IAAC,GAAG;IAAO;IAAW,QAAQ;GAAE;GAC7C,MAAM,MAAM,KAAK,UAAU,IAAI;GAC/B,MAAM,SACJ,QAAQ,SAAS,cACb,aAAa,QAAQ,SAAS,MAAM,SAAS,KAAK,IAClD,KAAA;GACN,MAAM,UAAU,QAAQ,IAAI,GAAG,MAAM,QAAQ,cAAc;GAC3D,IAAI,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,OAAO,CAAC;GACxC,eAAe;GACf,OAAO,CACL,UAAU,QAAQ,SAAS,cACvB;IAAE,GAAG;IAAS,SAAS,OAAO;GAAQ,IACtC,OACN;EACF,CACsB;EAAG;CAAW;AACtC;AAEA,SAAS,aACP,SACA,OACA,SACA,OAC2C;CAC3C,IAAI,aAAa;CAiBjB,OAAO;EAAE,SAhBI,MAAM,OAAO,CAAC,CAAC,SAAS,CAAC,MAAM,cAAc;GACxD,MAAM,MAAM,SAAS,MAAM,UAAU,KAAK;GAC1C,MAAM,SACJ,KAAK,SAAS,eAAe,KAAK,WAC9B,cACE,KAAK,UACL,CAAC,QAAQ,KAAK,UAAU,GACxB,SACA,KACF,IACA,KAAA;GACN,MAAM,UAAU,QAAQ,IAAI,GAAG,MAAM,QAAQ,cAAc;GAC3D,IAAI,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,OAAO,CAAC;GACxC,eAAe;GACf,OAAO,CAAC,SAAS;IAAE,GAAG;IAAM,UAAU,OAAO;GAAS,IAAI,IAAI;EAChE,CACqB;EAAG;CAAW;AACrC;AAEA,SAAgB,4BAGH;CAEX,MAAM,wBAAQ,IAAI,IAAY;CAC9B,QAAQ,UAAU,SAAS;EACzB,MAAM,0BAAU,IAAI,IAAY;EAChC,aAAa,MAAM,CAAC,IAAI,QAAQ,QAAQ,IAAI,GAAG,CAAC;EAChD,KAAK,MAAM,OAAO,SAAS,MAAM,IAAI,GAAG;EACxC,OAAO,aAAa,mBAAmB,UAAU,IAAI,GAAG,CAAC,GAAG,SAAS,KAAK,CAAC,CACxE;CACL;AACF;AAEA,SAAS,cAAc,SAA+B;CACpD,MAAM,4BAAY,IAAI,IAAY;CAClC,KAAK,MAAM,QAAQ,SAAS;EAC1B,IAAI,KAAK,SAAS,aAAa;EAC/B,KAAK,MAAM,WAAW,KAAK,YAAY,CAAC,GAAG;GACzC,IAAI,QAAQ,SAAS,aAAa;GAClC,KAAK,MAAM,SAAS,qBAAqB,QAAQ,OAAO,GACtD,UAAU,IAAI,MAAM,UAAU;EAElC;CACF;CACA,OAAO;AACT;AAEA,SAAS,mBAAmB,UAAmB,MAAwB;CACrE,MAAM,YAAY,cAAc,QAAQ;CACxC,MAAM,oBAAoB,cAAc,IAAI;CAC5C,MAAM,cAAc,IAAI,IACtB,SAAS,SAAS,SAChB,KAAK,SAAS,eAAe,kBAAkB,IAAI,KAAK,UAAU,IAC9D,CAAC,CAAC,KAAK,YAAY,IAAI,CAAU,IACjC,CAAC,CACP,CACF;CACA,MAAM,4BAAY,IAAI,IAAiC;CACvD,KAAK,MAAM,QAAQ,MACjB,IAAI,KAAK,SAAS,eAAe,UAAU,IAAI,KAAK,UAAU,GAC5D,UAAU,IAAI,KAAK,YAAY,IAAI;CAGvC,MAAM,SACJ,UAAU,OACN,qBAAqB,WAAW,SAAS;EACvC,MAAM,QAAQ,UAAU,IAAI,KAAK,UAAU;EAC3C,OAAO,QAAQ,UAAU,MAAM,KAAK,IAAI;CAC1C,CAAC,CAAC,CAAC,UACH,SAAA,CACJ,QACC,SAAS,KAAK,SAAS,eAAe,CAAC,YAAY,IAAI,KAAK,UAAU,CACzE;CACA,IAAI,WAAW,KAAK,QACjB,SAAS,KAAK,SAAS,eAAe,CAAC,UAAU,IAAI,KAAK,UAAU,CACvE;CACA,IAAI,YAAY,MACd,WAAW,CACT,GAAG,qBAAqB,WAAW,SAAS;EAC1C,MAAM,QAAQ,YAAY,IAAI,KAAK,UAAU;EAC7C,OAAO,QAAQ,UAAU,OAAO,IAAI,IAAI;CAC1C,CAAC,CAAC,CAAC,OACL;CAEF,OAAO,aAAa,MAAM,KAAK,GAAG,MAAM,QAAQ,IAAI,KAAK,UAAU;EACjE,IAAI,IAAI,SAAS,eAAe,MAAM,SAAS,aAC7C,OAAO,UAAU,KAAK,KAAK;EAC7B,KACG,IAAI,SAAS,UAAU,IAAI,SAAS,iBACpC,MAAM,SAAS,UAAU,MAAM,SAAS,gBACzC,IAAI,KAAK,WAAW,MAAM,IAAI,KAC9B,IAAI,KAAK,SAAS,MAAM,KAAK,QAE7B,OAAO;GAAE,GAAG;GAAO,MAAM,IAAI;EAAK;EAEpC,OAAO;CACT,CAAC;AACH"}
|
|
@@ -33,6 +33,7 @@ export declare class RunAggregator {
|
|
|
33
33
|
private interrupts;
|
|
34
34
|
private pendingToolCallIds;
|
|
35
35
|
private readonly textParts;
|
|
36
|
+
private readonly pendingSnapshotText;
|
|
36
37
|
private readonly activeTextMessageIdByScope;
|
|
37
38
|
private readonly reasoningParts;
|
|
38
39
|
private readonly reasoningSignatures;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-aggregator.d.ts","sourceRoot":"","sources":["../../../src/runtime/adapter/run-aggregator.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,kBAAkB,EAQxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"run-aggregator.d.ts","sourceRoot":"","sources":["../../../src/runtime/adapter/run-aggregator.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import { readMcpAppResourceUri, toolContentText } from "../mcp-tool-result.js";
|
|
3
3
|
import { AG_UI_METADATA_NAMESPACE } from "../types.js";
|
|
4
4
|
import { projectAgUiToolApprovals } from "./tool-approval.js";
|
|
5
|
+
import { withAgUiPartMessageMetadata } from "./conversions.js";
|
|
5
6
|
import { isMcpAppUri } from "@assistant-ui/core";
|
|
6
7
|
import jsonpatch from "fast-json-patch";
|
|
7
8
|
import { applyA2uiOperations, surfaceToPresentToolCall } from "@assistant-ui/generative-ui/a2ui";
|
|
8
|
-
|
|
9
|
+
// src/runtime/adapter/run-aggregator.ts
|
|
9
10
|
const ROOT_SCOPE = "";
|
|
10
|
-
const MAX_SUBAGENT_DEPTH = 16;
|
|
11
11
|
const createJSONContainerScanner = () => ({
|
|
12
12
|
state: "pending",
|
|
13
13
|
stack: [],
|
|
@@ -84,6 +84,7 @@ var RunAggregator = class {
|
|
|
84
84
|
interrupts;
|
|
85
85
|
pendingToolCallIds;
|
|
86
86
|
textParts = /* @__PURE__ */ new Map();
|
|
87
|
+
pendingSnapshotText = /* @__PURE__ */ new Map();
|
|
87
88
|
activeTextMessageIdByScope = /* @__PURE__ */ new Map();
|
|
88
89
|
reasoningParts = /* @__PURE__ */ new Map();
|
|
89
90
|
reasoningSignatures = /* @__PURE__ */ new Map();
|
|
@@ -138,6 +139,15 @@ var RunAggregator = class {
|
|
|
138
139
|
this.status = { type: "running" };
|
|
139
140
|
this.emit();
|
|
140
141
|
break;
|
|
142
|
+
case "MESSAGES_SNAPSHOT":
|
|
143
|
+
this.pendingSnapshotText.clear();
|
|
144
|
+
for (const message of event.messages) {
|
|
145
|
+
if (message.role !== "assistant" || typeof message.content !== "string") continue;
|
|
146
|
+
const part = this.textParts.get(message.id);
|
|
147
|
+
if (part) part.buffer = message.content;
|
|
148
|
+
else this.pendingSnapshotText.set(message.id, message.content);
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
141
151
|
case "RUN_FINISHED": {
|
|
142
152
|
if (event.outcome?.type === "cancelled") {
|
|
143
153
|
this.interrupts = void 0;
|
|
@@ -209,7 +219,7 @@ var RunAggregator = class {
|
|
|
209
219
|
const incomingId = event.messageId;
|
|
210
220
|
const scope = this.scopeOf(event);
|
|
211
221
|
if (scope === ROOT_SCOPE) {
|
|
212
|
-
this.beginDistinctTextMessage(incomingId);
|
|
222
|
+
this.beginDistinctTextMessage(incomingId, true);
|
|
213
223
|
this.reportServerMessageId(incomingId);
|
|
214
224
|
if (incomingId) this.lastTextMessageId = incomingId;
|
|
215
225
|
}
|
|
@@ -282,7 +292,7 @@ var RunAggregator = class {
|
|
|
282
292
|
this.emit();
|
|
283
293
|
break;
|
|
284
294
|
case "TOOL_CALL_RESULT":
|
|
285
|
-
this.finishToolCall(this.scopeOf(event), event.toolCallId, event.content ?? "", typeof event.mcpResult?.isError === "boolean" ? event.mcpResult.isError : event.role === "tool" ? false : void 0, event.messageId, event.mcpResult);
|
|
295
|
+
this.finishToolCall(this.scopeOf(event), event.toolCallId, event.content ?? "", typeof event.mcpResult?.isError === "boolean" ? event.mcpResult.isError : event.role === "tool" ? false : void 0, event.messageId, event.mcpResult, event.metadata);
|
|
286
296
|
this.emit();
|
|
287
297
|
break;
|
|
288
298
|
case "ACTIVITY_SNAPSHOT": {
|
|
@@ -485,6 +495,7 @@ var RunAggregator = class {
|
|
|
485
495
|
}
|
|
486
496
|
resetMessageParts() {
|
|
487
497
|
this.clearTextParts();
|
|
498
|
+
this.pendingSnapshotText.clear();
|
|
488
499
|
this.reasoningParts.clear();
|
|
489
500
|
this.reasoningSignatures.clear();
|
|
490
501
|
this.reasoningSignatureIds.clear();
|
|
@@ -518,12 +529,14 @@ var RunAggregator = class {
|
|
|
518
529
|
partKey(scope, id) {
|
|
519
530
|
return scope === ROOT_SCOPE ? id : `${scope}\u0000${id}`;
|
|
520
531
|
}
|
|
521
|
-
beginDistinctTextMessage(messageId) {
|
|
532
|
+
beginDistinctTextMessage(messageId, preserveSnapshotText = false) {
|
|
522
533
|
if (this.joinStrategy === "concat-content" || !messageId || this.lastTextMessageId === void 0 || this.lastTextMessageId === messageId || !this.onTextMessageStart) return;
|
|
523
534
|
const carried = this.takeTrailingReasoning();
|
|
524
535
|
if (carried.parts.length > 0 || carried.hiddenSignatures.length > 0) this.emit();
|
|
525
536
|
const openToolCallIds = Array.from(this.toolCalls.values()).filter((call) => call.result === void 0).map((call) => call.toolCallId);
|
|
537
|
+
const snapshotText = preserveSnapshotText ? this.pendingSnapshotText.get(messageId) : void 0;
|
|
526
538
|
this.resetMessageParts();
|
|
539
|
+
if (snapshotText !== void 0) this.pendingSnapshotText.set(messageId, snapshotText);
|
|
527
540
|
this.onTextMessageStart(messageId, openToolCallIds);
|
|
528
541
|
this.restoreReasoning(carried);
|
|
529
542
|
}
|
|
@@ -586,15 +599,19 @@ var RunAggregator = class {
|
|
|
586
599
|
startTextMessage(scope, messageId) {
|
|
587
600
|
const id = messageId ?? this.generateTextKey();
|
|
588
601
|
const key = this.ensureTextPart(scope, id);
|
|
602
|
+
if (scope === ROOT_SCOPE && messageId) {
|
|
603
|
+
const snapshotText = this.pendingSnapshotText.get(messageId);
|
|
604
|
+
const part = this.textParts.get(key);
|
|
605
|
+
if (snapshotText !== void 0 && part) {
|
|
606
|
+
part.buffer = snapshotText;
|
|
607
|
+
this.pendingSnapshotText.delete(messageId);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
589
610
|
this.activeTextMessageIdByScope.set(scope, key);
|
|
590
611
|
return key;
|
|
591
612
|
}
|
|
592
613
|
resolveTextMessageId(scope, messageId) {
|
|
593
|
-
if (messageId)
|
|
594
|
-
const key = this.ensureTextPart(scope, messageId);
|
|
595
|
-
this.activeTextMessageIdByScope.set(scope, key);
|
|
596
|
-
return key;
|
|
597
|
-
}
|
|
614
|
+
if (messageId) return this.startTextMessage(scope, messageId);
|
|
598
615
|
const active = this.activeTextMessageIdByScope.get(scope);
|
|
599
616
|
if (active) return active;
|
|
600
617
|
const key = this.ensureTextPart(scope, this.generateTextKey());
|
|
@@ -683,7 +700,7 @@ var RunAggregator = class {
|
|
|
683
700
|
entry.parsedArgs = void 0;
|
|
684
701
|
}
|
|
685
702
|
}
|
|
686
|
-
finishToolCall(scope, id, content, isError, toolMessageId, mcpResult) {
|
|
703
|
+
finishToolCall(scope, id, content, isError, toolMessageId, mcpResult, metadata) {
|
|
687
704
|
if (!id) return;
|
|
688
705
|
const modelText = toolContentText(content);
|
|
689
706
|
let entry = this.toolCalls.get(id);
|
|
@@ -729,6 +746,10 @@ var RunAggregator = class {
|
|
|
729
746
|
entry.isError = isError;
|
|
730
747
|
}
|
|
731
748
|
if (toolMessageId) entry.toolMessageId = toolMessageId;
|
|
749
|
+
if (metadata !== void 0) entry.resultMetadata = {
|
|
750
|
+
...entry.resultMetadata,
|
|
751
|
+
...metadata
|
|
752
|
+
};
|
|
732
753
|
this.lastResolvedToolCallIdByScope.set(scope, id);
|
|
733
754
|
}
|
|
734
755
|
nesting() {
|
|
@@ -754,7 +775,7 @@ var RunAggregator = class {
|
|
|
754
775
|
reachableSubagentRunIds(subagentsByParentToolCallId) {
|
|
755
776
|
const reachable = /* @__PURE__ */ new Set();
|
|
756
777
|
const walk = (scope, depth) => {
|
|
757
|
-
if (depth >
|
|
778
|
+
if (depth > 16) return;
|
|
758
779
|
for (const entry of this.toolCalls.values()) {
|
|
759
780
|
if ((entry.subagentRunId ?? ROOT_SCOPE) !== scope) continue;
|
|
760
781
|
for (const id of subagentsByParentToolCallId.get(entry.toolCallId) ?? []) {
|
|
@@ -769,7 +790,7 @@ var RunAggregator = class {
|
|
|
769
790
|
}
|
|
770
791
|
materializeSubagentMessage(subagentRunId, depth, ctx) {
|
|
771
792
|
const run = this.subagentRuns.get(subagentRunId);
|
|
772
|
-
if (!run || depth >
|
|
793
|
+
if (!run || depth > 16) return void 0;
|
|
773
794
|
const content = this.buildParts(subagentRunId, depth + 1, ctx);
|
|
774
795
|
return {
|
|
775
796
|
id: run.subagentRunId,
|
|
@@ -822,6 +843,7 @@ var RunAggregator = class {
|
|
|
822
843
|
} } } : {},
|
|
823
844
|
...entry.parentMessageId ? { parentId: entry.parentMessageId } : {},
|
|
824
845
|
...entry.toolMessageId ? { unstable_toolMessageId: entry.toolMessageId } : {},
|
|
846
|
+
...entry.resultMetadata !== void 0 ? { providerMetadata: withAgUiPartMessageMetadata(void 0, entry.resultMetadata) } : {},
|
|
825
847
|
...nestedMessages.length > 0 ? { messages: nestedMessages } : {}
|
|
826
848
|
};
|
|
827
849
|
snapshot.push(toolPart);
|
|
@@ -1032,7 +1054,6 @@ function tryParseJSON(value) {
|
|
|
1032
1054
|
return value;
|
|
1033
1055
|
}
|
|
1034
1056
|
}
|
|
1035
|
-
//#endregion
|
|
1036
1057
|
export { RunAggregator, isPlainObject, tryParseJSON };
|
|
1037
1058
|
|
|
1038
1059
|
//# sourceMappingURL=run-aggregator.js.map
|