@assistant-ui/react-ag-ui 0.0.57 → 0.0.59
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 +16 -0
- package/dist/index.d.ts +2 -2
- package/dist/runtime/AgUiThreadRuntimeCore.d.ts +19 -8
- package/dist/runtime/AgUiThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtime/AgUiThreadRuntimeCore.js +118 -86
- package/dist/runtime/AgUiThreadRuntimeCore.js.map +1 -1
- package/dist/runtime/adapter/conversions.d.ts.map +1 -1
- package/dist/runtime/adapter/conversions.js +34 -11
- package/dist/runtime/adapter/conversions.js.map +1 -1
- package/dist/runtime/adapter/run-aggregator.d.ts +13 -3
- package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
- package/dist/runtime/adapter/run-aggregator.js +385 -119
- package/dist/runtime/adapter/run-aggregator.js.map +1 -1
- package/dist/runtime/adapter/subscriber.d.ts +9 -0
- package/dist/runtime/adapter/subscriber.d.ts.map +1 -1
- package/dist/runtime/adapter/subscriber.js +4 -1
- package/dist/runtime/adapter/subscriber.js.map +1 -1
- package/dist/runtime/adapter/tool-approval.d.ts +3 -1
- package/dist/runtime/adapter/tool-approval.d.ts.map +1 -1
- package/dist/runtime/adapter/tool-approval.js +11 -12
- package/dist/runtime/adapter/tool-approval.js.map +1 -1
- package/dist/runtime/event-parser.d.ts.map +1 -1
- package/dist/runtime/event-parser.js +176 -45
- package/dist/runtime/event-parser.js.map +1 -1
- package/dist/runtime/types.d.ts +67 -1
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/useAgUiRuntime.d.ts.map +1 -1
- package/dist/useAgUiRuntime.js +15 -5
- package/dist/useAgUiRuntime.js.map +1 -1
- package/package.json +9 -9
- package/src/index.ts +1 -0
- package/src/runtime/AgUiThreadRuntimeCore.test.ts +18 -0
- package/src/runtime/AgUiThreadRuntimeCore.ts +204 -120
- package/src/runtime/adapter/conversions.ts +87 -17
- package/src/runtime/adapter/run-aggregator.approval.test.ts +128 -0
- package/src/runtime/adapter/run-aggregator.ts +595 -139
- package/src/runtime/adapter/subscriber.ts +10 -1
- package/src/runtime/adapter/tool-approval.test.ts +75 -0
- package/src/runtime/adapter/tool-approval.ts +17 -12
- package/src/runtime/event-parser.ts +216 -36
- package/src/runtime/types.ts +96 -12
- package/src/useAgUiRuntime.approval.test.tsx +34 -24
- package/src/useAgUiRuntime.queue.test.tsx +54 -0
- package/src/useAgUiRuntime.thread-switch.test.tsx +199 -0
- package/src/useAgUiRuntime.toolDeferral.test.tsx +186 -0
- package/src/useAgUiRuntime.ts +15 -3
|
@@ -5,6 +5,62 @@ import { isMcpAppUri } from "@assistant-ui/core";
|
|
|
5
5
|
import { applyA2uiOperations, convertSurfaceToUISpec } from "@assistant-ui/react-generative-ui/a2ui";
|
|
6
6
|
//#region src/runtime/adapter/run-aggregator.ts
|
|
7
7
|
const AG_UI_METADATA_NAMESPACE = "agui";
|
|
8
|
+
const ROOT_SCOPE = "";
|
|
9
|
+
const MAX_SUBAGENT_DEPTH = 16;
|
|
10
|
+
const createJSONContainerScanner = () => ({
|
|
11
|
+
state: "pending",
|
|
12
|
+
stack: [],
|
|
13
|
+
inString: false,
|
|
14
|
+
escaped: false
|
|
15
|
+
});
|
|
16
|
+
const isJSONWhitespace = (char) => char === " " || char === " " || char === "\n" || char === "\r";
|
|
17
|
+
const scanJSONContainerDelta = (scanner, delta) => {
|
|
18
|
+
let completed = false;
|
|
19
|
+
for (const char of delta) {
|
|
20
|
+
if (scanner.state === "invalid") continue;
|
|
21
|
+
if (scanner.state === "complete") {
|
|
22
|
+
if (isJSONWhitespace(char)) continue;
|
|
23
|
+
scanner.state = "invalid";
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (scanner.state === "pending") {
|
|
27
|
+
if (isJSONWhitespace(char)) continue;
|
|
28
|
+
if (char !== "{" && char !== "[") {
|
|
29
|
+
scanner.state = "invalid";
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
scanner.state = "open";
|
|
33
|
+
scanner.stack.push(char);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (scanner.inString) {
|
|
37
|
+
if (scanner.escaped) scanner.escaped = false;
|
|
38
|
+
else if (char === "\\") scanner.escaped = true;
|
|
39
|
+
else if (char === "\"") scanner.inString = false;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (char === "\"") {
|
|
43
|
+
scanner.inString = true;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (char === "{" || char === "[") {
|
|
47
|
+
scanner.stack.push(char);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (char === "}" || char === "]") {
|
|
51
|
+
const expected = char === "}" ? "{" : "[";
|
|
52
|
+
if (scanner.stack.pop() !== expected) {
|
|
53
|
+
scanner.state = "invalid";
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (scanner.stack.length === 0) {
|
|
57
|
+
scanner.state = "complete";
|
|
58
|
+
completed = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return completed && scanner.state === "complete";
|
|
63
|
+
};
|
|
8
64
|
const MCP_APPS_ACTIVITY_TYPE = "mcp-apps";
|
|
9
65
|
const A2UI_SURFACE_ACTIVITY_TYPE = "a2ui-surface";
|
|
10
66
|
const isPlainObject = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -27,7 +83,7 @@ var RunAggregator = class {
|
|
|
27
83
|
status;
|
|
28
84
|
interrupts;
|
|
29
85
|
textParts = /* @__PURE__ */ new Map();
|
|
30
|
-
|
|
86
|
+
activeTextMessageIdByScope = /* @__PURE__ */ new Map();
|
|
31
87
|
reasoningParts = /* @__PURE__ */ new Map();
|
|
32
88
|
reasoningSignatures = /* @__PURE__ */ new Map();
|
|
33
89
|
reasoningSignatureIds = /* @__PURE__ */ new Map();
|
|
@@ -41,12 +97,14 @@ var RunAggregator = class {
|
|
|
41
97
|
loggedDroppedOpaqueIds = /* @__PURE__ */ new Set();
|
|
42
98
|
reasoningMessageIds = /* @__PURE__ */ new Map();
|
|
43
99
|
anonymousReasoningKeys = /* @__PURE__ */ new Set();
|
|
44
|
-
|
|
100
|
+
activeReasoningKeyByScope = /* @__PURE__ */ new Map();
|
|
101
|
+
subagentRuns = /* @__PURE__ */ new Map();
|
|
102
|
+
nestingMemo;
|
|
45
103
|
reasoningPartCounter = 0;
|
|
46
104
|
toolCalls = /* @__PURE__ */ new Map();
|
|
47
105
|
a2uiBuckets = /* @__PURE__ */ new Map();
|
|
48
106
|
a2uiToolCallIds = /* @__PURE__ */ new Set();
|
|
49
|
-
|
|
107
|
+
lastResolvedToolCallIdByScope = /* @__PURE__ */ new Map();
|
|
50
108
|
partOrder = [];
|
|
51
109
|
textPartCounter = 0;
|
|
52
110
|
serverMessageIdReported = false;
|
|
@@ -91,13 +149,14 @@ var RunAggregator = class {
|
|
|
91
149
|
}
|
|
92
150
|
this.interrupts = void 0;
|
|
93
151
|
const hasUnresolvedToolCalls = Array.from(this.toolCalls.values()).some((tc) => tc.result === void 0);
|
|
94
|
-
this.status =
|
|
95
|
-
type: "complete",
|
|
96
|
-
reason: "unknown"
|
|
97
|
-
} : {
|
|
152
|
+
this.status = hasUnresolvedToolCalls ? {
|
|
98
153
|
type: "requires-action",
|
|
99
154
|
reason: "tool-calls"
|
|
155
|
+
} : {
|
|
156
|
+
type: "complete",
|
|
157
|
+
reason: "unknown"
|
|
100
158
|
};
|
|
159
|
+
this.closeOpenSubagentRuns(this.status);
|
|
101
160
|
this.emit();
|
|
102
161
|
break;
|
|
103
162
|
}
|
|
@@ -107,6 +166,7 @@ var RunAggregator = class {
|
|
|
107
166
|
reason: "error",
|
|
108
167
|
...event.message !== void 0 ? { error: event.message } : {}
|
|
109
168
|
};
|
|
169
|
+
this.closeOpenSubagentRuns(this.status);
|
|
110
170
|
this.emit();
|
|
111
171
|
break;
|
|
112
172
|
case "RUN_CANCELLED":
|
|
@@ -114,36 +174,46 @@ var RunAggregator = class {
|
|
|
114
174
|
type: "incomplete",
|
|
115
175
|
reason: "cancelled"
|
|
116
176
|
};
|
|
177
|
+
this.closeOpenSubagentRuns(this.status);
|
|
117
178
|
this.emit();
|
|
118
179
|
break;
|
|
119
|
-
case "TEXT_MESSAGE_START":
|
|
120
|
-
this.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
180
|
+
case "TEXT_MESSAGE_START": {
|
|
181
|
+
const scope = this.scopeOf(event);
|
|
182
|
+
if (scope === ROOT_SCOPE) {
|
|
183
|
+
this.beginDistinctTextMessage(event.messageId);
|
|
184
|
+
this.reportServerMessageId(event.messageId);
|
|
185
|
+
if (event.messageId) this.lastTextMessageId = event.messageId;
|
|
186
|
+
}
|
|
187
|
+
this.startTextMessage(scope, event.messageId);
|
|
124
188
|
this.emit();
|
|
125
189
|
break;
|
|
190
|
+
}
|
|
126
191
|
case "TEXT_MESSAGE_CONTENT":
|
|
127
192
|
case "TEXT_MESSAGE_CHUNK": {
|
|
128
193
|
const incomingId = "messageId" in event ? event.messageId : void 0;
|
|
129
|
-
this.
|
|
130
|
-
|
|
131
|
-
|
|
194
|
+
const scope = this.scopeOf(event);
|
|
195
|
+
if (scope === ROOT_SCOPE) {
|
|
196
|
+
this.beginDistinctTextMessage(incomingId);
|
|
197
|
+
this.reportServerMessageId(incomingId);
|
|
198
|
+
if (incomingId) this.lastTextMessageId = incomingId;
|
|
199
|
+
}
|
|
132
200
|
if (!event.delta) break;
|
|
133
201
|
this.recordFirstToken();
|
|
134
|
-
const id = this.resolveTextMessageId(incomingId);
|
|
202
|
+
const id = this.resolveTextMessageId(scope, incomingId);
|
|
135
203
|
this.appendText(id, event.delta);
|
|
136
204
|
this.totalChunks++;
|
|
137
205
|
this.emit();
|
|
138
206
|
break;
|
|
139
207
|
}
|
|
140
|
-
case "TEXT_MESSAGE_END":
|
|
141
|
-
this.
|
|
142
|
-
if (
|
|
208
|
+
case "TEXT_MESSAGE_END": {
|
|
209
|
+
const scope = this.scopeOf(event);
|
|
210
|
+
if (scope === ROOT_SCOPE) this.reportServerMessageId(event.messageId);
|
|
211
|
+
if (event.messageId && this.activeTextMessageIdByScope.get(scope) === this.partKey(scope, event.messageId)) this.activeTextMessageIdByScope.delete(scope);
|
|
143
212
|
this.emit();
|
|
144
213
|
break;
|
|
214
|
+
}
|
|
145
215
|
case "CUSTOM":
|
|
146
|
-
this.
|
|
216
|
+
this.activeTextMessageIdByScope.delete(ROOT_SCOPE);
|
|
147
217
|
this.partOrder.push({
|
|
148
218
|
kind: "data",
|
|
149
219
|
name: event.name,
|
|
@@ -155,17 +225,19 @@ var RunAggregator = class {
|
|
|
155
225
|
case "THINKING_TEXT_MESSAGE_START":
|
|
156
226
|
case "REASONING_START":
|
|
157
227
|
case "REASONING_MESSAGE_START":
|
|
158
|
-
this.handleReasoningStart("messageId" in event ? event.messageId : void 0, event.type === "REASONING_MESSAGE_START");
|
|
228
|
+
this.handleReasoningStart(this.scopeOf("subagentRunId" in event ? event : {}), "messageId" in event ? event.messageId : void 0, event.type === "REASONING_MESSAGE_START");
|
|
159
229
|
break;
|
|
160
230
|
case "REASONING_ENCRYPTED_VALUE":
|
|
161
231
|
if (event.subtype === "message") {
|
|
162
|
-
const
|
|
163
|
-
const
|
|
232
|
+
const scope = this.scopeOf(event);
|
|
233
|
+
const active = this.activeReasoningKeyByScope.get(scope);
|
|
234
|
+
const entityKey = this.partKey(scope, event.entityId);
|
|
235
|
+
const key = this.showThinking ? this.reasoningParts.has(entityKey) ? entityKey : active !== void 0 && this.anonymousReasoningKeys.has(active) ? active : void 0 : void 0;
|
|
164
236
|
if (key !== void 0) {
|
|
165
237
|
this.reasoningSignatures.set(key, event.encryptedValue);
|
|
166
238
|
this.reasoningSignatureIds.set(key, event.entityId);
|
|
167
239
|
this.emit();
|
|
168
|
-
} else if (!this.showThinking && event.entityId.trim().length > 0 && event.encryptedValue.trim().length > 0 && (this.hiddenReasoningIds.has(event.entityId) || this.hiddenActiveReasoning === "anonymous")) {
|
|
240
|
+
} else if (!this.showThinking && scope === ROOT_SCOPE && event.entityId.trim().length > 0 && event.encryptedValue.trim().length > 0 && (this.hiddenReasoningIds.has(event.entityId) || this.hiddenActiveReasoning === "anonymous")) {
|
|
169
241
|
this.hiddenSignatures.set(event.entityId, event.encryptedValue);
|
|
170
242
|
this.hiddenSignatureAnchors.set(event.entityId, this.hiddenBlockAnchors.get(event.entityId) ?? this.hiddenAnonymousAnchor ?? this.partOrder.length);
|
|
171
243
|
this.emit();
|
|
@@ -173,29 +245,33 @@ var RunAggregator = class {
|
|
|
173
245
|
}
|
|
174
246
|
break;
|
|
175
247
|
case "THINKING_TEXT_MESSAGE_CONTENT":
|
|
176
|
-
this.handleReasoningContent(event.delta);
|
|
248
|
+
this.handleReasoningContent(ROOT_SCOPE, event.delta);
|
|
177
249
|
this.totalChunks++;
|
|
178
250
|
this.recordFirstToken();
|
|
179
251
|
break;
|
|
180
252
|
case "REASONING_MESSAGE_CONTENT":
|
|
181
|
-
this.handleReasoningContent(event.delta, "messageId" in event ? event.messageId : void 0, true);
|
|
253
|
+
this.handleReasoningContent(this.scopeOf(event), event.delta, "messageId" in event ? event.messageId : void 0, true);
|
|
182
254
|
this.totalChunks++;
|
|
183
255
|
this.recordFirstToken();
|
|
184
256
|
break;
|
|
185
257
|
case "THINKING_TEXT_MESSAGE_END":
|
|
186
258
|
case "THINKING_END":
|
|
259
|
+
this.handleReasoningEnd(ROOT_SCOPE);
|
|
260
|
+
break;
|
|
187
261
|
case "REASONING_MESSAGE_END":
|
|
188
262
|
case "REASONING_END":
|
|
189
|
-
this.handleReasoningEnd();
|
|
263
|
+
this.handleReasoningEnd(this.scopeOf(event));
|
|
190
264
|
break;
|
|
191
|
-
case "TOOL_CALL_START":
|
|
192
|
-
this.
|
|
193
|
-
this.
|
|
265
|
+
case "TOOL_CALL_START": {
|
|
266
|
+
const scope = this.scopeOf(event);
|
|
267
|
+
if (scope === ROOT_SCOPE) this.reportServerMessageId(event.parentMessageId);
|
|
268
|
+
this.startToolCall(scope, event.toolCallId, event.toolCallName, event.parentMessageId);
|
|
194
269
|
this.emit();
|
|
195
270
|
break;
|
|
271
|
+
}
|
|
196
272
|
case "TOOL_CALL_ARGS":
|
|
197
273
|
case "TOOL_CALL_CHUNK":
|
|
198
|
-
if (event.type === "TOOL_CALL_CHUNK") this.reportServerMessageId(event.parentMessageId);
|
|
274
|
+
if (event.type === "TOOL_CALL_CHUNK" && this.scopeOf(event) === ROOT_SCOPE) this.reportServerMessageId(event.parentMessageId);
|
|
199
275
|
if (!event.delta) break;
|
|
200
276
|
this.appendToolArgs(event.toolCallId, event.delta);
|
|
201
277
|
this.emit();
|
|
@@ -204,7 +280,7 @@ var RunAggregator = class {
|
|
|
204
280
|
this.emit();
|
|
205
281
|
break;
|
|
206
282
|
case "TOOL_CALL_RESULT":
|
|
207
|
-
this.finishToolCall(event.toolCallId, event.content ?? "", typeof event.mcpResult?.isError === "boolean" ? event.mcpResult.isError : event.role === "tool" ? false : void 0, event.messageId, event.mcpResult);
|
|
283
|
+
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);
|
|
208
284
|
this.emit();
|
|
209
285
|
break;
|
|
210
286
|
case "ACTIVITY_SNAPSHOT": {
|
|
@@ -213,8 +289,10 @@ var RunAggregator = class {
|
|
|
213
289
|
break;
|
|
214
290
|
}
|
|
215
291
|
if (event.activityType !== "mcp-apps") break;
|
|
292
|
+
const activityScope = this.scopeOf(event);
|
|
216
293
|
const toolCallId = event.content.toolCallId;
|
|
217
|
-
const
|
|
294
|
+
const fallbackId = this.lastResolvedToolCallIdByScope.get(activityScope);
|
|
295
|
+
const entry = typeof toolCallId === "string" ? this.toolCalls.get(toolCallId) : fallbackId ? this.toolCalls.get(fallbackId) : void 0;
|
|
218
296
|
const resourceUri = event.content.resourceUri;
|
|
219
297
|
if (entry && typeof resourceUri === "string" && isMcpAppUri(resourceUri)) {
|
|
220
298
|
entry.mcpAppResourceUri = resourceUri;
|
|
@@ -236,6 +314,58 @@ var RunAggregator = class {
|
|
|
236
314
|
}
|
|
237
315
|
break;
|
|
238
316
|
}
|
|
317
|
+
case "SUBAGENT_STARTED": {
|
|
318
|
+
const existing = this.subagentRuns.get(event.subagentRunId);
|
|
319
|
+
if (existing) {
|
|
320
|
+
existing.name = event.name;
|
|
321
|
+
if (event.description !== void 0) existing.description = event.description;
|
|
322
|
+
existing.status = { type: "running" };
|
|
323
|
+
this.emit();
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
this.nestingMemo = void 0;
|
|
327
|
+
this.subagentRuns.set(event.subagentRunId, {
|
|
328
|
+
subagentRunId: event.subagentRunId,
|
|
329
|
+
name: event.name,
|
|
330
|
+
...event.description !== void 0 ? { description: event.description } : {},
|
|
331
|
+
...event.parentSubagentRunId !== void 0 ? { parentSubagentRunId: event.parentSubagentRunId } : {},
|
|
332
|
+
...event.parentToolCallId !== void 0 ? { parentToolCallId: event.parentToolCallId } : {},
|
|
333
|
+
...event.parentMessageId !== void 0 ? { parentMessageId: event.parentMessageId } : {},
|
|
334
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
335
|
+
status: { type: "running" }
|
|
336
|
+
});
|
|
337
|
+
this.emit();
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
case "SUBAGENT_FINISHED": {
|
|
341
|
+
const run = this.subagentRuns.get(event.subagentRunId);
|
|
342
|
+
if (run) {
|
|
343
|
+
run.status = event.outcome?.type === "suspended" ? {
|
|
344
|
+
type: "requires-action",
|
|
345
|
+
reason: "interrupt"
|
|
346
|
+
} : {
|
|
347
|
+
type: "complete",
|
|
348
|
+
reason: "unknown"
|
|
349
|
+
};
|
|
350
|
+
if (event.result !== void 0) run.result = event.result;
|
|
351
|
+
if (event.outcome?.type === "suspended" && event.outcome.interruptIds) run.interruptIds = event.outcome.interruptIds;
|
|
352
|
+
}
|
|
353
|
+
this.emit();
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
case "SUBAGENT_ERROR": {
|
|
357
|
+
const run = this.subagentRuns.get(event.subagentRunId);
|
|
358
|
+
if (run) {
|
|
359
|
+
run.status = {
|
|
360
|
+
type: "incomplete",
|
|
361
|
+
reason: "error",
|
|
362
|
+
...event.message !== void 0 ? { error: event.message } : {}
|
|
363
|
+
};
|
|
364
|
+
if (event.code !== void 0) run.errorCode = event.code;
|
|
365
|
+
}
|
|
366
|
+
this.emit();
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
239
369
|
default: this.logger.debug?.("[agui] aggregator ignored event", event);
|
|
240
370
|
}
|
|
241
371
|
}
|
|
@@ -274,11 +404,13 @@ var RunAggregator = class {
|
|
|
274
404
|
kind: "tool-call",
|
|
275
405
|
toolCallId
|
|
276
406
|
});
|
|
407
|
+
this.nestingMemo = void 0;
|
|
277
408
|
this.toolCalls.set(toolCallId, entry);
|
|
278
409
|
this.a2uiToolCallIds.add(toolCallId);
|
|
279
410
|
}
|
|
280
411
|
for (const toolCallId of this.a2uiToolCallIds) {
|
|
281
412
|
if (activeToolCallIds.has(toolCallId)) continue;
|
|
413
|
+
this.nestingMemo = void 0;
|
|
282
414
|
this.toolCalls.delete(toolCallId);
|
|
283
415
|
const partIndex = this.partOrder.findIndex((part) => part.kind === "tool-call" && part.toolCallId === toolCallId);
|
|
284
416
|
if (partIndex !== -1) this.partOrder.splice(partIndex, 1);
|
|
@@ -310,17 +442,28 @@ var RunAggregator = class {
|
|
|
310
442
|
this.hiddenActiveReasoning = "none";
|
|
311
443
|
this.loggedDroppedOpaqueIds.clear();
|
|
312
444
|
this.anonymousReasoningKeys.clear();
|
|
313
|
-
this.
|
|
445
|
+
this.activeReasoningKeyByScope.clear();
|
|
446
|
+
this.nestingMemo = void 0;
|
|
447
|
+
this.subagentRuns.clear();
|
|
314
448
|
this.reasoningPartCounter = 0;
|
|
315
449
|
this.toolCalls.clear();
|
|
316
450
|
this.a2uiBuckets.clear();
|
|
317
451
|
this.a2uiToolCallIds.clear();
|
|
318
|
-
this.
|
|
452
|
+
this.lastResolvedToolCallIdByScope.clear();
|
|
319
453
|
this.partOrder.length = 0;
|
|
320
454
|
this.textPartCounter = 0;
|
|
321
|
-
this.
|
|
455
|
+
this.activeTextMessageIdByScope.clear();
|
|
322
456
|
this.reportedServerMessageId = void 0;
|
|
323
457
|
}
|
|
458
|
+
closeOpenSubagentRuns(status) {
|
|
459
|
+
for (const run of this.subagentRuns.values()) if (run.status.type === "running") run.status = status;
|
|
460
|
+
}
|
|
461
|
+
scopeOf(event) {
|
|
462
|
+
return event.subagentRunId ?? ROOT_SCOPE;
|
|
463
|
+
}
|
|
464
|
+
partKey(scope, id) {
|
|
465
|
+
return scope === ROOT_SCOPE ? id : `${scope}\u0000${id}`;
|
|
466
|
+
}
|
|
324
467
|
beginDistinctTextMessage(messageId) {
|
|
325
468
|
if (!messageId || this.lastTextMessageId === void 0 || this.lastTextMessageId === messageId || !this.onTextMessageStart) return;
|
|
326
469
|
this.resetMessageParts();
|
|
@@ -330,43 +473,48 @@ var RunAggregator = class {
|
|
|
330
473
|
this.textPartCounter += 1;
|
|
331
474
|
return `text-${this.textPartCounter}`;
|
|
332
475
|
}
|
|
333
|
-
startTextMessage(messageId) {
|
|
476
|
+
startTextMessage(scope, messageId) {
|
|
334
477
|
const id = messageId ?? this.generateTextKey();
|
|
335
|
-
this.ensureTextPart(id);
|
|
336
|
-
this.
|
|
337
|
-
return
|
|
478
|
+
const key = this.ensureTextPart(scope, id);
|
|
479
|
+
this.activeTextMessageIdByScope.set(scope, key);
|
|
480
|
+
return key;
|
|
338
481
|
}
|
|
339
|
-
resolveTextMessageId(messageId) {
|
|
482
|
+
resolveTextMessageId(scope, messageId) {
|
|
340
483
|
if (messageId) {
|
|
341
|
-
this.ensureTextPart(messageId);
|
|
342
|
-
this.
|
|
343
|
-
return
|
|
484
|
+
const key = this.ensureTextPart(scope, messageId);
|
|
485
|
+
this.activeTextMessageIdByScope.set(scope, key);
|
|
486
|
+
return key;
|
|
344
487
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
this.ensureTextPart(
|
|
348
|
-
this.
|
|
349
|
-
return
|
|
350
|
-
}
|
|
351
|
-
ensureTextPart(id) {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
488
|
+
const active = this.activeTextMessageIdByScope.get(scope);
|
|
489
|
+
if (active) return active;
|
|
490
|
+
const key = this.ensureTextPart(scope, this.generateTextKey());
|
|
491
|
+
this.activeTextMessageIdByScope.set(scope, key);
|
|
492
|
+
return key;
|
|
493
|
+
}
|
|
494
|
+
ensureTextPart(scope, id) {
|
|
495
|
+
const key = this.partKey(scope, id);
|
|
496
|
+
if (!this.textParts.has(key)) {
|
|
497
|
+
this.textParts.set(key, { buffer: "" });
|
|
498
|
+
if (!this.partOrder.some((part) => part.kind === "text" && part.key === key)) this.partOrder.push(scope === ROOT_SCOPE ? {
|
|
499
|
+
kind: "text",
|
|
500
|
+
key
|
|
501
|
+
} : {
|
|
355
502
|
kind: "text",
|
|
356
|
-
key
|
|
503
|
+
key,
|
|
504
|
+
subagentRunId: scope
|
|
357
505
|
});
|
|
358
506
|
}
|
|
507
|
+
return key;
|
|
359
508
|
}
|
|
360
509
|
appendText(id, delta) {
|
|
361
|
-
this.ensureTextPart(id);
|
|
362
510
|
const entry = this.textParts.get(id);
|
|
363
511
|
if (!entry) return;
|
|
364
512
|
entry.buffer += delta;
|
|
365
513
|
}
|
|
366
|
-
startToolCall(id, name, parentMessageId) {
|
|
514
|
+
startToolCall(scope, id, name, parentMessageId) {
|
|
367
515
|
if (!id) return;
|
|
368
|
-
this.
|
|
369
|
-
if (!this.partOrder.some((part) => part.kind === "tool-call" && part.toolCallId === id)) this.insertToolPart(id, parentMessageId);
|
|
516
|
+
this.activeTextMessageIdByScope.delete(scope);
|
|
517
|
+
if (!this.partOrder.some((part) => part.kind === "tool-call" && part.toolCallId === id)) this.insertToolPart(scope, id, parentMessageId);
|
|
370
518
|
const state = {
|
|
371
519
|
toolCallId: id,
|
|
372
520
|
toolCallName: name ?? "tool",
|
|
@@ -377,15 +525,18 @@ var RunAggregator = class {
|
|
|
377
525
|
snapshotResultApplied: false
|
|
378
526
|
};
|
|
379
527
|
if (parentMessageId) state.parentMessageId = parentMessageId;
|
|
528
|
+
if (scope !== ROOT_SCOPE) state.subagentRunId = scope;
|
|
529
|
+
this.nestingMemo = void 0;
|
|
380
530
|
this.toolCalls.set(id, state);
|
|
381
531
|
}
|
|
382
|
-
insertToolPart(id, parentMessageId) {
|
|
532
|
+
insertToolPart(scope, id, parentMessageId) {
|
|
383
533
|
const entry = {
|
|
384
534
|
kind: "tool-call",
|
|
385
535
|
toolCallId: id
|
|
386
536
|
};
|
|
387
537
|
if (parentMessageId) {
|
|
388
|
-
const
|
|
538
|
+
const parentKey = this.partKey(scope, parentMessageId);
|
|
539
|
+
const parentIndex = this.partOrder.findIndex((part) => part.kind === "text" && part.key === parentKey);
|
|
389
540
|
if (parentIndex !== -1) {
|
|
390
541
|
let insertAt = parentIndex + 1;
|
|
391
542
|
while (insertAt < this.partOrder.length) {
|
|
@@ -405,7 +556,12 @@ var RunAggregator = class {
|
|
|
405
556
|
appendToolArgs(id, delta) {
|
|
406
557
|
const entry = id ? this.toolCalls.get(id) : void 0;
|
|
407
558
|
if (!entry) return;
|
|
559
|
+
if (!entry.argsTextScanner) entry.argsTextScanner = createJSONContainerScanner();
|
|
408
560
|
entry.argsText += delta;
|
|
561
|
+
if (!scanJSONContainerDelta(entry.argsTextScanner, delta)) {
|
|
562
|
+
if (entry.argsTextScanner.state === "invalid") entry.parsedArgs = void 0;
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
409
565
|
try {
|
|
410
566
|
const parsed = JSON.parse(entry.argsText);
|
|
411
567
|
if (parsed && typeof parsed === "object") entry.parsedArgs = parsed;
|
|
@@ -414,7 +570,7 @@ var RunAggregator = class {
|
|
|
414
570
|
entry.parsedArgs = void 0;
|
|
415
571
|
}
|
|
416
572
|
}
|
|
417
|
-
finishToolCall(id, content, isError, toolMessageId, mcpResult) {
|
|
573
|
+
finishToolCall(scope, id, content, isError, toolMessageId, mcpResult) {
|
|
418
574
|
if (!id) return;
|
|
419
575
|
let entry = this.toolCalls.get(id);
|
|
420
576
|
if (!entry) {
|
|
@@ -425,8 +581,10 @@ var RunAggregator = class {
|
|
|
425
581
|
parsedArgs: void 0,
|
|
426
582
|
result: void 0,
|
|
427
583
|
isError: void 0,
|
|
428
|
-
snapshotResultApplied: false
|
|
584
|
+
snapshotResultApplied: false,
|
|
585
|
+
...scope !== ROOT_SCOPE ? { subagentRunId: scope } : {}
|
|
429
586
|
};
|
|
587
|
+
this.nestingMemo = void 0;
|
|
430
588
|
this.toolCalls.set(id, entry);
|
|
431
589
|
}
|
|
432
590
|
if (!this.partOrder.some((part) => part.kind === "tool-call" && part.toolCallId === id)) this.partOrder.push({
|
|
@@ -456,43 +614,126 @@ var RunAggregator = class {
|
|
|
456
614
|
entry.isError = isError;
|
|
457
615
|
}
|
|
458
616
|
if (toolMessageId) entry.toolMessageId = toolMessageId;
|
|
459
|
-
this.
|
|
617
|
+
this.lastResolvedToolCallIdByScope.set(scope, id);
|
|
460
618
|
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
619
|
+
nesting() {
|
|
620
|
+
if (!this.nestingMemo) {
|
|
621
|
+
const subagentsByParentToolCallId = this.subagentsByParentToolCallId();
|
|
622
|
+
this.nestingMemo = {
|
|
623
|
+
subagentsByParentToolCallId,
|
|
624
|
+
reachable: this.reachableSubagentRunIds(subagentsByParentToolCallId)
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
return this.nestingMemo;
|
|
628
|
+
}
|
|
629
|
+
subagentsByParentToolCallId() {
|
|
630
|
+
const map = /* @__PURE__ */ new Map();
|
|
631
|
+
for (const run of this.subagentRuns.values()) {
|
|
632
|
+
if (!run.parentToolCallId) continue;
|
|
633
|
+
const list = map.get(run.parentToolCallId) ?? [];
|
|
634
|
+
list.push(run.subagentRunId);
|
|
635
|
+
map.set(run.parentToolCallId, list);
|
|
636
|
+
}
|
|
637
|
+
return map;
|
|
638
|
+
}
|
|
639
|
+
reachableSubagentRunIds(subagentsByParentToolCallId) {
|
|
640
|
+
const reachable = /* @__PURE__ */ new Set();
|
|
641
|
+
const walk = (scope, depth) => {
|
|
642
|
+
if (depth > MAX_SUBAGENT_DEPTH) return;
|
|
643
|
+
for (const entry of this.toolCalls.values()) {
|
|
644
|
+
if ((entry.subagentRunId ?? ROOT_SCOPE) !== scope) continue;
|
|
645
|
+
for (const id of subagentsByParentToolCallId.get(entry.toolCallId) ?? []) {
|
|
646
|
+
if (reachable.has(id)) continue;
|
|
647
|
+
reachable.add(id);
|
|
648
|
+
walk(id, depth + 1);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
474
651
|
};
|
|
475
|
-
|
|
476
|
-
|
|
652
|
+
walk(ROOT_SCOPE, 0);
|
|
653
|
+
return reachable;
|
|
654
|
+
}
|
|
655
|
+
materializeSubagentMessage(subagentRunId, depth, ctx) {
|
|
656
|
+
const run = this.subagentRuns.get(subagentRunId);
|
|
657
|
+
if (!run || depth > MAX_SUBAGENT_DEPTH) return void 0;
|
|
658
|
+
const content = this.buildParts(subagentRunId, depth + 1, ctx);
|
|
659
|
+
return {
|
|
660
|
+
id: run.subagentRunId,
|
|
661
|
+
role: "assistant",
|
|
662
|
+
createdAt: run.createdAt,
|
|
663
|
+
status: run.status,
|
|
664
|
+
content,
|
|
665
|
+
metadata: {
|
|
666
|
+
unstable_state: null,
|
|
667
|
+
unstable_annotations: [],
|
|
668
|
+
unstable_data: [],
|
|
669
|
+
steps: [],
|
|
670
|
+
custom: { [AG_UI_METADATA_NAMESPACE]: {
|
|
671
|
+
name: run.name,
|
|
672
|
+
...run.description !== void 0 ? { description: run.description } : {},
|
|
673
|
+
...run.parentSubagentRunId !== void 0 ? { parentSubagentRunId: run.parentSubagentRunId } : {},
|
|
674
|
+
...run.result !== void 0 ? { result: run.result } : {},
|
|
675
|
+
...run.interruptIds !== void 0 ? { interruptIds: run.interruptIds } : {},
|
|
676
|
+
...run.errorCode !== void 0 ? { errorCode: run.errorCode } : {}
|
|
677
|
+
} }
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
buildParts(scope, depth, ctx) {
|
|
682
|
+
const snapshot = [];
|
|
683
|
+
const isRoot = scope === ROOT_SCOPE;
|
|
684
|
+
for (const { index, part } of ctx.partsByScope.get(scope) ?? []) {
|
|
685
|
+
const materialized = () => {
|
|
686
|
+
if (isRoot && ctx.root) ctx.root.lastMaterializedIndex = index;
|
|
687
|
+
};
|
|
688
|
+
if (part.kind === "tool-call") {
|
|
689
|
+
const entry = this.toolCalls.get(part.toolCallId);
|
|
690
|
+
if (!entry) continue;
|
|
691
|
+
const approval = ctx.approvals.get(entry.toolCallId);
|
|
692
|
+
const nestedMessages = (ctx.subagentsByParentToolCallId.get(entry.toolCallId) ?? []).filter((id) => ctx.reachable.has(id)).map((id) => this.materializeSubagentMessage(id, depth, ctx)).filter((m) => m !== void 0);
|
|
693
|
+
const toolPart = {
|
|
694
|
+
type: "tool-call",
|
|
695
|
+
toolCallId: entry.toolCallId,
|
|
696
|
+
toolName: entry.toolCallName,
|
|
697
|
+
args: entry.parsedArgs ?? {},
|
|
698
|
+
argsText: entry.argsText,
|
|
699
|
+
...approval ? { approval } : {},
|
|
700
|
+
...entry.result !== void 0 ? { result: entry.result } : {},
|
|
701
|
+
...entry.modelContent !== void 0 ? { modelContent: entry.modelContent } : {},
|
|
702
|
+
...entry.isError !== void 0 ? { isError: entry.isError } : {},
|
|
703
|
+
...entry.mcpAppResourceUri ? { mcp: { app: {
|
|
704
|
+
resourceUri: entry.mcpAppResourceUri,
|
|
705
|
+
...entry.mcpAppServerId ? { serverId: entry.mcpAppServerId } : {}
|
|
706
|
+
} } } : {},
|
|
707
|
+
...entry.parentMessageId ? { parentId: entry.parentMessageId } : {},
|
|
708
|
+
...entry.toolMessageId ? { unstable_toolMessageId: entry.toolMessageId } : {},
|
|
709
|
+
...nestedMessages.length > 0 ? { messages: nestedMessages } : {}
|
|
710
|
+
};
|
|
711
|
+
snapshot.push(toolPart);
|
|
712
|
+
materialized();
|
|
713
|
+
continue;
|
|
714
|
+
}
|
|
715
|
+
const rawScope = "subagentRunId" in part ? part.subagentRunId ?? ROOT_SCOPE : ROOT_SCOPE;
|
|
477
716
|
if (part.kind === "reasoning") {
|
|
478
717
|
if (this.showThinking) {
|
|
479
718
|
const buffer = this.reasoningParts.get(part.key) ?? "";
|
|
480
|
-
|
|
719
|
+
const isActive = this.activeReasoningKeyByScope.get(rawScope) === part.key;
|
|
720
|
+
if (buffer.length > 0 || isActive) {
|
|
481
721
|
const encryptedValue = this.reasoningSignatures.get(part.key);
|
|
482
722
|
const reasoningId = this.reasoningMessageIds.get(part.key);
|
|
483
723
|
const meta = {
|
|
484
724
|
...reasoningId !== void 0 ? { reasoningId } : {},
|
|
485
725
|
...encryptedValue !== void 0 ? { encryptedValue } : {}
|
|
486
726
|
};
|
|
487
|
-
|
|
727
|
+
snapshot.push({
|
|
488
728
|
type: "reasoning",
|
|
489
729
|
text: buffer,
|
|
490
730
|
...Object.keys(meta).length > 0 ? { providerMetadata: { [AG_UI_METADATA_NAMESPACE]: meta } } : {}
|
|
491
731
|
});
|
|
492
|
-
|
|
732
|
+
materialized();
|
|
733
|
+
} else if (isRoot && ctx.root) {
|
|
493
734
|
const encryptedValue = this.reasoningSignatures.get(part.key);
|
|
494
735
|
const id = this.reasoningSignatureIds.get(part.key);
|
|
495
|
-
if (id?.trim() && encryptedValue?.trim()) opaqueCandidates.push({
|
|
736
|
+
if (id?.trim() && encryptedValue?.trim()) ctx.root.opaqueCandidates.push({
|
|
496
737
|
id,
|
|
497
738
|
encryptedValue,
|
|
498
739
|
anchor: index + 1
|
|
@@ -503,41 +744,60 @@ var RunAggregator = class {
|
|
|
503
744
|
}
|
|
504
745
|
if (part.kind === "text") {
|
|
505
746
|
const entry = this.textParts.get(part.key);
|
|
506
|
-
if (entry && entry.buffer.trim().length > 0)
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
747
|
+
if (entry && entry.buffer.trim().length > 0) {
|
|
748
|
+
snapshot.push({
|
|
749
|
+
type: "text",
|
|
750
|
+
text: entry.buffer
|
|
751
|
+
});
|
|
752
|
+
materialized();
|
|
753
|
+
}
|
|
510
754
|
continue;
|
|
511
755
|
}
|
|
512
756
|
if (part.kind === "data") {
|
|
513
|
-
|
|
757
|
+
snapshot.push({
|
|
514
758
|
type: "data",
|
|
515
759
|
name: part.name,
|
|
516
760
|
data: part.value
|
|
517
761
|
});
|
|
762
|
+
materialized();
|
|
518
763
|
continue;
|
|
519
764
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
765
|
+
}
|
|
766
|
+
return snapshot;
|
|
767
|
+
}
|
|
768
|
+
emit() {
|
|
769
|
+
const { subagentsByParentToolCallId, reachable } = this.nesting();
|
|
770
|
+
const root = {
|
|
771
|
+
opaqueCandidates: Array.from(this.hiddenSignatures, ([id, encryptedValue]) => ({
|
|
772
|
+
id,
|
|
773
|
+
encryptedValue,
|
|
774
|
+
anchor: this.hiddenSignatureAnchors.get(id)
|
|
775
|
+
})),
|
|
776
|
+
lastMaterializedIndex: -1
|
|
777
|
+
};
|
|
778
|
+
const partsByScope = /* @__PURE__ */ new Map();
|
|
779
|
+
for (const [index, part] of this.partOrder.entries()) {
|
|
780
|
+
const rawScope = part.kind === "tool-call" ? this.toolCalls.get(part.toolCallId)?.subagentRunId ?? ROOT_SCOPE : "subagentRunId" in part ? part.subagentRunId ?? ROOT_SCOPE : ROOT_SCOPE;
|
|
781
|
+
const bucketScope = rawScope === ROOT_SCOPE || reachable.has(rawScope) ? rawScope : ROOT_SCOPE;
|
|
782
|
+
const bucket = partsByScope.get(bucketScope);
|
|
783
|
+
if (bucket) bucket.push({
|
|
784
|
+
index,
|
|
785
|
+
part
|
|
539
786
|
});
|
|
787
|
+
else partsByScope.set(bucketScope, [{
|
|
788
|
+
index,
|
|
789
|
+
part
|
|
790
|
+
}]);
|
|
540
791
|
}
|
|
792
|
+
const ctx = {
|
|
793
|
+
subagentsByParentToolCallId,
|
|
794
|
+
reachable,
|
|
795
|
+
partsByScope,
|
|
796
|
+
approvals: projectAgUiToolApprovals(this.status?.type === "requires-action" ? this.interrupts : void 0, new Set(Array.from(this.toolCalls.values()).map((entry) => entry.toolCallId))),
|
|
797
|
+
root
|
|
798
|
+
};
|
|
799
|
+
const snapshot = this.buildParts(ROOT_SCOPE, 0, ctx);
|
|
800
|
+
const { opaqueCandidates, lastMaterializedIndex } = root;
|
|
541
801
|
const toolMessageIds = /* @__PURE__ */ new Set();
|
|
542
802
|
for (const call of this.toolCalls.values()) if (call.toolMessageId) toolMessageIds.add(call.toolMessageId);
|
|
543
803
|
opaqueCandidates.sort((a, b) => a.anchor - b.anchor);
|
|
@@ -587,8 +847,9 @@ var RunAggregator = class {
|
|
|
587
847
|
toolCallCount: this.toolCalls.size
|
|
588
848
|
};
|
|
589
849
|
}
|
|
590
|
-
handleReasoningStart(messageId, isMessageId = false) {
|
|
850
|
+
handleReasoningStart(scope, messageId, isMessageId = false) {
|
|
591
851
|
if (!this.showThinking) {
|
|
852
|
+
if (scope !== ROOT_SCOPE) return;
|
|
592
853
|
const anchor = this.partOrder.length;
|
|
593
854
|
if (messageId === void 0) {
|
|
594
855
|
this.hiddenActiveReasoning = "anonymous";
|
|
@@ -600,38 +861,43 @@ var RunAggregator = class {
|
|
|
600
861
|
}
|
|
601
862
|
return;
|
|
602
863
|
}
|
|
603
|
-
this.
|
|
604
|
-
const key = messageId ?? `__auto-reasoning-${++this.reasoningPartCounter}
|
|
864
|
+
this.activeTextMessageIdByScope.delete(scope);
|
|
865
|
+
const key = this.partKey(scope, messageId ?? `__auto-reasoning-${++this.reasoningPartCounter}`);
|
|
605
866
|
if (messageId === void 0) this.anonymousReasoningKeys.add(key);
|
|
606
867
|
else if (isMessageId) this.reasoningMessageIds.set(key, messageId);
|
|
607
868
|
if (!this.reasoningParts.has(key)) {
|
|
608
869
|
this.reasoningParts.set(key, "");
|
|
609
|
-
this.partOrder.push({
|
|
870
|
+
this.partOrder.push(scope === ROOT_SCOPE ? {
|
|
610
871
|
kind: "reasoning",
|
|
611
872
|
key
|
|
873
|
+
} : {
|
|
874
|
+
kind: "reasoning",
|
|
875
|
+
key,
|
|
876
|
+
subagentRunId: scope
|
|
612
877
|
});
|
|
613
878
|
}
|
|
614
|
-
this.
|
|
879
|
+
this.activeReasoningKeyByScope.set(scope, key);
|
|
615
880
|
this.emit();
|
|
616
881
|
}
|
|
617
|
-
handleReasoningContent(delta, messageId, isMessageId = false) {
|
|
882
|
+
handleReasoningContent(scope, delta, messageId, isMessageId = false) {
|
|
618
883
|
if (!delta) return;
|
|
619
884
|
if (!this.showThinking) {
|
|
620
|
-
if (
|
|
885
|
+
if (scope !== ROOT_SCOPE) return;
|
|
886
|
+
if (this.hiddenActiveReasoning === "none") this.handleReasoningStart(scope, messageId, isMessageId);
|
|
621
887
|
return;
|
|
622
888
|
}
|
|
623
|
-
if (!this.
|
|
624
|
-
const key = this.
|
|
889
|
+
if (!this.activeReasoningKeyByScope.has(scope)) this.handleReasoningStart(scope, messageId, isMessageId);
|
|
890
|
+
const key = this.activeReasoningKeyByScope.get(scope);
|
|
625
891
|
if (!key) return;
|
|
626
892
|
this.reasoningParts.set(key, (this.reasoningParts.get(key) ?? "") + delta);
|
|
627
893
|
this.emit();
|
|
628
894
|
}
|
|
629
|
-
handleReasoningEnd() {
|
|
895
|
+
handleReasoningEnd(scope) {
|
|
630
896
|
if (!this.showThinking) {
|
|
631
|
-
this.hiddenActiveReasoning = "none";
|
|
897
|
+
if (scope === ROOT_SCOPE) this.hiddenActiveReasoning = "none";
|
|
632
898
|
return;
|
|
633
899
|
}
|
|
634
|
-
this.
|
|
900
|
+
this.activeReasoningKeyByScope.delete(scope);
|
|
635
901
|
this.emit();
|
|
636
902
|
}
|
|
637
903
|
};
|