@assistant-ui/react-ag-ui 0.0.54 → 0.0.57
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/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/runtime/AgUiThreadRuntimeCore.d.ts +25 -15
- package/dist/runtime/AgUiThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtime/AgUiThreadRuntimeCore.js +257 -210
- package/dist/runtime/AgUiThreadRuntimeCore.js.map +1 -1
- package/dist/runtime/adapter/conversions.d.ts +13 -3
- package/dist/runtime/adapter/conversions.d.ts.map +1 -1
- package/dist/runtime/adapter/conversions.js +77 -39
- package/dist/runtime/adapter/conversions.js.map +1 -1
- package/dist/runtime/adapter/run-aggregator.d.ts +23 -2
- package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
- package/dist/runtime/adapter/run-aggregator.js +155 -41
- package/dist/runtime/adapter/run-aggregator.js.map +1 -1
- package/dist/runtime/adapter/subscriber.d.ts +3 -0
- package/dist/runtime/adapter/subscriber.d.ts.map +1 -1
- package/dist/runtime/adapter/subscriber.js +9 -0
- package/dist/runtime/adapter/subscriber.js.map +1 -1
- package/dist/runtime/adapter/tool-approval.d.ts +56 -0
- package/dist/runtime/adapter/tool-approval.d.ts.map +1 -0
- package/dist/runtime/adapter/tool-approval.js +244 -0
- package/dist/runtime/adapter/tool-approval.js.map +1 -0
- package/dist/runtime/event-parser.d.ts.map +1 -1
- package/dist/runtime/event-parser.js +2 -1
- package/dist/runtime/event-parser.js.map +1 -1
- package/dist/runtime/interrupt-internals.d.ts +8 -0
- package/dist/runtime/interrupt-internals.d.ts.map +1 -0
- package/dist/runtime/interrupt-internals.js +25 -0
- package/dist/runtime/interrupt-internals.js.map +1 -0
- package/dist/useAgUiRuntime.js +14 -9
- package/dist/useAgUiRuntime.js.map +1 -1
- package/package.json +9 -9
- package/src/index.ts +8 -2
- package/src/runtime/AgUiThreadRuntimeCore.test.ts +105 -0
- package/src/runtime/AgUiThreadRuntimeCore.ts +436 -272
- package/src/runtime/adapter/conversions.content.test.ts +61 -3
- package/src/runtime/adapter/conversions.ts +123 -57
- package/src/runtime/adapter/run-aggregator.approval.test.ts +103 -0
- package/src/runtime/adapter/run-aggregator.ts +234 -47
- package/src/runtime/adapter/subscriber.ts +14 -0
- package/src/runtime/adapter/tool-approval.test.ts +681 -0
- package/src/runtime/adapter/tool-approval.ts +366 -0
- package/src/runtime/event-parser.ts +10 -1
- package/src/runtime/interrupt-internals.ts +35 -0
- package/src/useAgUiRuntime.approval.test.tsx +885 -0
- package/src/useAgUiRuntime.history.test.tsx +76 -0
- package/src/useAgUiRuntime.ts +15 -9
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { readMcpAppResourceUri } from "../mcp-tool-result.js";
|
|
3
|
+
import { projectAgUiToolApprovals } from "./tool-approval.js";
|
|
3
4
|
import { isMcpAppUri } from "@assistant-ui/core";
|
|
4
5
|
import { applyA2uiOperations, convertSurfaceToUISpec } from "@assistant-ui/react-generative-ui/a2ui";
|
|
5
6
|
//#region src/runtime/adapter/run-aggregator.ts
|
|
@@ -11,19 +12,33 @@ const isPlainObject = (value) => !!value && typeof value === "object" && !Array.
|
|
|
11
12
|
* Collects AG-UI events into assistant-ui run snapshots that can be yielded from a ChatModelAdapter.
|
|
12
13
|
*
|
|
13
14
|
* The aggregator keeps a single assistant message worth of parts. Each incoming event updates the parts and
|
|
14
|
-
* emits a fresh snapshot through the provided `emit` callback.
|
|
15
|
+
* emits a fresh snapshot through the provided `emit` callback. `CUSTOM` events
|
|
16
|
+
* become canonical data parts; integration plumbing names such as
|
|
17
|
+
* `on_interrupt`, `PredictState`, `Exit`, `hook_error`, `state_update_error`,
|
|
18
|
+
* `system:*`, and `MultiAgentHandoff` are forwarded the same way, so apps only
|
|
19
|
+
* need data renderers for names they own.
|
|
15
20
|
*/
|
|
16
21
|
var RunAggregator = class {
|
|
17
22
|
emitUpdate;
|
|
18
23
|
showThinking;
|
|
19
24
|
logger;
|
|
20
25
|
onServerMessageId;
|
|
26
|
+
onTextMessageStart;
|
|
21
27
|
status;
|
|
22
28
|
interrupts;
|
|
23
29
|
textParts = /* @__PURE__ */ new Map();
|
|
24
30
|
activeTextMessageId;
|
|
25
31
|
reasoningParts = /* @__PURE__ */ new Map();
|
|
26
32
|
reasoningSignatures = /* @__PURE__ */ new Map();
|
|
33
|
+
reasoningSignatureIds = /* @__PURE__ */ new Map();
|
|
34
|
+
hiddenSignatures = /* @__PURE__ */ new Map();
|
|
35
|
+
hiddenSignatureAnchors = /* @__PURE__ */ new Map();
|
|
36
|
+
hiddenBlockAnchors = /* @__PURE__ */ new Map();
|
|
37
|
+
hiddenAnonymousAnchor;
|
|
38
|
+
hiddenReasoningIds = /* @__PURE__ */ new Set();
|
|
39
|
+
hiddenActiveReasoning = "none";
|
|
40
|
+
hasEmittedOpaqueReasoning = false;
|
|
41
|
+
loggedDroppedOpaqueIds = /* @__PURE__ */ new Set();
|
|
27
42
|
reasoningMessageIds = /* @__PURE__ */ new Map();
|
|
28
43
|
anonymousReasoningKeys = /* @__PURE__ */ new Set();
|
|
29
44
|
activeReasoningKey;
|
|
@@ -35,6 +50,8 @@ var RunAggregator = class {
|
|
|
35
50
|
partOrder = [];
|
|
36
51
|
textPartCounter = 0;
|
|
37
52
|
serverMessageIdReported = false;
|
|
53
|
+
reportedServerMessageId;
|
|
54
|
+
lastTextMessageId;
|
|
38
55
|
streamStartTime;
|
|
39
56
|
firstTokenTime;
|
|
40
57
|
totalChunks = 0;
|
|
@@ -43,6 +60,7 @@ var RunAggregator = class {
|
|
|
43
60
|
this.showThinking = options.showThinking;
|
|
44
61
|
this.logger = options.logger;
|
|
45
62
|
this.onServerMessageId = options.onServerMessageId;
|
|
63
|
+
this.onTextMessageStart = options.onTextMessageStart;
|
|
46
64
|
}
|
|
47
65
|
hasToolCall(toolCallId) {
|
|
48
66
|
return this.toolCalls.has(toolCallId);
|
|
@@ -50,22 +68,11 @@ var RunAggregator = class {
|
|
|
50
68
|
handle(event) {
|
|
51
69
|
switch (event.type) {
|
|
52
70
|
case "RUN_STARTED":
|
|
53
|
-
this.
|
|
54
|
-
this.reasoningParts.clear();
|
|
55
|
-
this.reasoningSignatures.clear();
|
|
56
|
-
this.reasoningMessageIds.clear();
|
|
57
|
-
this.anonymousReasoningKeys.clear();
|
|
58
|
-
this.activeReasoningKey = void 0;
|
|
59
|
-
this.reasoningPartCounter = 0;
|
|
60
|
-
this.toolCalls.clear();
|
|
61
|
-
this.a2uiBuckets.clear();
|
|
62
|
-
this.a2uiToolCallIds.clear();
|
|
63
|
-
this.lastResolvedToolCallId = void 0;
|
|
64
|
-
this.partOrder.length = 0;
|
|
65
|
-
this.textPartCounter = 0;
|
|
66
|
-
this.activeTextMessageId = void 0;
|
|
71
|
+
this.resetMessageParts();
|
|
67
72
|
this.interrupts = void 0;
|
|
68
73
|
this.serverMessageIdReported = false;
|
|
74
|
+
this.lastTextMessageId = void 0;
|
|
75
|
+
this.reportedServerMessageId = void 0;
|
|
69
76
|
this.streamStartTime = Date.now();
|
|
70
77
|
this.firstTokenTime = void 0;
|
|
71
78
|
this.totalChunks = 0;
|
|
@@ -109,17 +116,19 @@ var RunAggregator = class {
|
|
|
109
116
|
};
|
|
110
117
|
this.emit();
|
|
111
118
|
break;
|
|
112
|
-
case "TEXT_MESSAGE_START":
|
|
119
|
+
case "TEXT_MESSAGE_START":
|
|
120
|
+
this.beginDistinctTextMessage(event.messageId);
|
|
113
121
|
this.reportServerMessageId(event.messageId);
|
|
114
|
-
|
|
115
|
-
if (
|
|
122
|
+
this.startTextMessage(event.messageId);
|
|
123
|
+
if (event.messageId) this.lastTextMessageId = event.messageId;
|
|
116
124
|
this.emit();
|
|
117
125
|
break;
|
|
118
|
-
}
|
|
119
126
|
case "TEXT_MESSAGE_CONTENT":
|
|
120
127
|
case "TEXT_MESSAGE_CHUNK": {
|
|
121
128
|
const incomingId = "messageId" in event ? event.messageId : void 0;
|
|
129
|
+
this.beginDistinctTextMessage(incomingId);
|
|
122
130
|
this.reportServerMessageId(incomingId);
|
|
131
|
+
if (incomingId) this.lastTextMessageId = incomingId;
|
|
123
132
|
if (!event.delta) break;
|
|
124
133
|
this.recordFirstToken();
|
|
125
134
|
const id = this.resolveTextMessageId(incomingId);
|
|
@@ -133,6 +142,15 @@ var RunAggregator = class {
|
|
|
133
142
|
if (event.messageId && this.activeTextMessageId === event.messageId) this.activeTextMessageId = void 0;
|
|
134
143
|
this.emit();
|
|
135
144
|
break;
|
|
145
|
+
case "CUSTOM":
|
|
146
|
+
this.activeTextMessageId = void 0;
|
|
147
|
+
this.partOrder.push({
|
|
148
|
+
kind: "data",
|
|
149
|
+
name: event.name,
|
|
150
|
+
value: event.value
|
|
151
|
+
});
|
|
152
|
+
this.emit();
|
|
153
|
+
break;
|
|
136
154
|
case "THINKING_START":
|
|
137
155
|
case "THINKING_TEXT_MESSAGE_START":
|
|
138
156
|
case "REASONING_START":
|
|
@@ -142,9 +160,14 @@ var RunAggregator = class {
|
|
|
142
160
|
case "REASONING_ENCRYPTED_VALUE":
|
|
143
161
|
if (event.subtype === "message") {
|
|
144
162
|
const active = this.activeReasoningKey;
|
|
145
|
-
const key = this.reasoningParts.has(event.entityId) ? event.entityId : active !== void 0 && this.anonymousReasoningKeys.has(active) ? active : void 0;
|
|
163
|
+
const key = this.showThinking ? this.reasoningParts.has(event.entityId) ? event.entityId : active !== void 0 && this.anonymousReasoningKeys.has(active) ? active : void 0 : void 0;
|
|
146
164
|
if (key !== void 0) {
|
|
147
165
|
this.reasoningSignatures.set(key, event.encryptedValue);
|
|
166
|
+
this.reasoningSignatureIds.set(key, event.entityId);
|
|
167
|
+
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")) {
|
|
169
|
+
this.hiddenSignatures.set(event.entityId, event.encryptedValue);
|
|
170
|
+
this.hiddenSignatureAnchors.set(event.entityId, this.hiddenBlockAnchors.get(event.entityId) ?? this.hiddenAnonymousAnchor ?? this.partOrder.length);
|
|
148
171
|
this.emit();
|
|
149
172
|
}
|
|
150
173
|
}
|
|
@@ -263,13 +286,46 @@ var RunAggregator = class {
|
|
|
263
286
|
}
|
|
264
287
|
}
|
|
265
288
|
reportServerMessageId(messageId) {
|
|
266
|
-
if (
|
|
289
|
+
if (!messageId) return;
|
|
290
|
+
if (this.lastTextMessageId === void 0) this.lastTextMessageId = messageId;
|
|
291
|
+
if (this.serverMessageIdReported) return;
|
|
267
292
|
this.serverMessageIdReported = true;
|
|
293
|
+
this.reportedServerMessageId = messageId;
|
|
268
294
|
this.onServerMessageId?.(messageId);
|
|
269
295
|
}
|
|
270
296
|
clearTextParts() {
|
|
271
297
|
this.textParts.clear();
|
|
272
298
|
}
|
|
299
|
+
resetMessageParts() {
|
|
300
|
+
this.clearTextParts();
|
|
301
|
+
this.reasoningParts.clear();
|
|
302
|
+
this.reasoningSignatures.clear();
|
|
303
|
+
this.reasoningSignatureIds.clear();
|
|
304
|
+
this.reasoningMessageIds.clear();
|
|
305
|
+
this.hiddenSignatures.clear();
|
|
306
|
+
this.hiddenSignatureAnchors.clear();
|
|
307
|
+
this.hiddenBlockAnchors.clear();
|
|
308
|
+
this.hiddenAnonymousAnchor = void 0;
|
|
309
|
+
this.hiddenReasoningIds.clear();
|
|
310
|
+
this.hiddenActiveReasoning = "none";
|
|
311
|
+
this.loggedDroppedOpaqueIds.clear();
|
|
312
|
+
this.anonymousReasoningKeys.clear();
|
|
313
|
+
this.activeReasoningKey = void 0;
|
|
314
|
+
this.reasoningPartCounter = 0;
|
|
315
|
+
this.toolCalls.clear();
|
|
316
|
+
this.a2uiBuckets.clear();
|
|
317
|
+
this.a2uiToolCallIds.clear();
|
|
318
|
+
this.lastResolvedToolCallId = void 0;
|
|
319
|
+
this.partOrder.length = 0;
|
|
320
|
+
this.textPartCounter = 0;
|
|
321
|
+
this.activeTextMessageId = void 0;
|
|
322
|
+
this.reportedServerMessageId = void 0;
|
|
323
|
+
}
|
|
324
|
+
beginDistinctTextMessage(messageId) {
|
|
325
|
+
if (!messageId || this.lastTextMessageId === void 0 || this.lastTextMessageId === messageId || !this.onTextMessageStart) return;
|
|
326
|
+
this.resetMessageParts();
|
|
327
|
+
this.onTextMessageStart(messageId);
|
|
328
|
+
}
|
|
273
329
|
generateTextKey() {
|
|
274
330
|
this.textPartCounter += 1;
|
|
275
331
|
return `text-${this.textPartCounter}`;
|
|
@@ -294,27 +350,18 @@ var RunAggregator = class {
|
|
|
294
350
|
}
|
|
295
351
|
ensureTextPart(id) {
|
|
296
352
|
if (!this.textParts.has(id)) {
|
|
297
|
-
this.textParts.set(id, {
|
|
298
|
-
buffer: "",
|
|
299
|
-
touched: false
|
|
300
|
-
});
|
|
353
|
+
this.textParts.set(id, { buffer: "" });
|
|
301
354
|
if (!this.partOrder.some((part) => part.kind === "text" && part.key === id)) this.partOrder.push({
|
|
302
355
|
kind: "text",
|
|
303
356
|
key: id
|
|
304
357
|
});
|
|
305
358
|
}
|
|
306
359
|
}
|
|
307
|
-
markTextPartTouched(id) {
|
|
308
|
-
const entry = this.textParts.get(id);
|
|
309
|
-
if (!entry) return;
|
|
310
|
-
entry.touched = true;
|
|
311
|
-
}
|
|
312
360
|
appendText(id, delta) {
|
|
313
361
|
this.ensureTextPart(id);
|
|
314
362
|
const entry = this.textParts.get(id);
|
|
315
363
|
if (!entry) return;
|
|
316
364
|
entry.buffer += delta;
|
|
317
|
-
entry.touched = true;
|
|
318
365
|
}
|
|
319
366
|
startToolCall(id, name, parentMessageId) {
|
|
320
367
|
if (!id) return;
|
|
@@ -413,7 +460,20 @@ var RunAggregator = class {
|
|
|
413
460
|
}
|
|
414
461
|
emit() {
|
|
415
462
|
const snapshot = [];
|
|
416
|
-
|
|
463
|
+
const approvals = projectAgUiToolApprovals(this.status?.type === "requires-action" ? this.interrupts : void 0, new Set(this.toolCalls.keys()));
|
|
464
|
+
const opaqueCandidates = Array.from(this.hiddenSignatures, ([id, encryptedValue]) => ({
|
|
465
|
+
id,
|
|
466
|
+
encryptedValue,
|
|
467
|
+
anchor: this.hiddenSignatureAnchors.get(id)
|
|
468
|
+
}));
|
|
469
|
+
let currentIndex = -1;
|
|
470
|
+
let lastMaterializedIndex = -1;
|
|
471
|
+
const pushSnapshotPart = (part) => {
|
|
472
|
+
snapshot.push(part);
|
|
473
|
+
lastMaterializedIndex = currentIndex;
|
|
474
|
+
};
|
|
475
|
+
for (const [index, part] of this.partOrder.entries()) {
|
|
476
|
+
currentIndex = index;
|
|
417
477
|
if (part.kind === "reasoning") {
|
|
418
478
|
if (this.showThinking) {
|
|
419
479
|
const buffer = this.reasoningParts.get(part.key) ?? "";
|
|
@@ -424,31 +484,49 @@ var RunAggregator = class {
|
|
|
424
484
|
...reasoningId !== void 0 ? { reasoningId } : {},
|
|
425
485
|
...encryptedValue !== void 0 ? { encryptedValue } : {}
|
|
426
486
|
};
|
|
427
|
-
|
|
487
|
+
pushSnapshotPart({
|
|
428
488
|
type: "reasoning",
|
|
429
489
|
text: buffer,
|
|
430
490
|
...Object.keys(meta).length > 0 ? { providerMetadata: { [AG_UI_METADATA_NAMESPACE]: meta } } : {}
|
|
431
491
|
});
|
|
492
|
+
} else {
|
|
493
|
+
const encryptedValue = this.reasoningSignatures.get(part.key);
|
|
494
|
+
const id = this.reasoningSignatureIds.get(part.key);
|
|
495
|
+
if (id?.trim() && encryptedValue?.trim()) opaqueCandidates.push({
|
|
496
|
+
id,
|
|
497
|
+
encryptedValue,
|
|
498
|
+
anchor: index + 1
|
|
499
|
+
});
|
|
432
500
|
}
|
|
433
501
|
}
|
|
434
502
|
continue;
|
|
435
503
|
}
|
|
436
504
|
if (part.kind === "text") {
|
|
437
505
|
const entry = this.textParts.get(part.key);
|
|
438
|
-
if (entry
|
|
506
|
+
if (entry && entry.buffer.trim().length > 0) pushSnapshotPart({
|
|
439
507
|
type: "text",
|
|
440
508
|
text: entry.buffer
|
|
441
509
|
});
|
|
442
510
|
continue;
|
|
443
511
|
}
|
|
512
|
+
if (part.kind === "data") {
|
|
513
|
+
pushSnapshotPart({
|
|
514
|
+
type: "data",
|
|
515
|
+
name: part.name,
|
|
516
|
+
data: part.value
|
|
517
|
+
});
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
444
520
|
const entry = this.toolCalls.get(part.toolCallId);
|
|
445
521
|
if (!entry) continue;
|
|
446
|
-
const
|
|
522
|
+
const approval = approvals.get(entry.toolCallId);
|
|
523
|
+
pushSnapshotPart({
|
|
447
524
|
type: "tool-call",
|
|
448
525
|
toolCallId: entry.toolCallId,
|
|
449
526
|
toolName: entry.toolCallName,
|
|
450
527
|
args: entry.parsedArgs ?? {},
|
|
451
528
|
argsText: entry.argsText,
|
|
529
|
+
...approval ? { approval } : {},
|
|
452
530
|
...entry.result !== void 0 ? { result: entry.result } : {},
|
|
453
531
|
...entry.modelContent !== void 0 ? { modelContent: entry.modelContent } : {},
|
|
454
532
|
...entry.isError !== void 0 ? { isError: entry.isError } : {},
|
|
@@ -458,13 +536,31 @@ var RunAggregator = class {
|
|
|
458
536
|
} } } : {},
|
|
459
537
|
...entry.parentMessageId ? { parentId: entry.parentMessageId } : {},
|
|
460
538
|
...entry.toolMessageId ? { unstable_toolMessageId: entry.toolMessageId } : {}
|
|
461
|
-
};
|
|
462
|
-
snapshot.push(toolPart);
|
|
539
|
+
});
|
|
463
540
|
}
|
|
541
|
+
const toolMessageIds = /* @__PURE__ */ new Set();
|
|
542
|
+
for (const call of this.toolCalls.values()) if (call.toolMessageId) toolMessageIds.add(call.toolMessageId);
|
|
543
|
+
opaqueCandidates.sort((a, b) => a.anchor - b.anchor);
|
|
544
|
+
const publishableOpaqueReasoning = opaqueCandidates.filter((entry) => {
|
|
545
|
+
const collides = this.textParts.has(entry.id) || entry.id === this.reportedServerMessageId || toolMessageIds.has(entry.id);
|
|
546
|
+
if (collides && !this.loggedDroppedOpaqueIds.has(entry.id)) {
|
|
547
|
+
this.loggedDroppedOpaqueIds.add(entry.id);
|
|
548
|
+
this.logger.debug?.("[agui] aggregator dropped opaque reasoning signature: id collides with a message id", entry.id);
|
|
549
|
+
}
|
|
550
|
+
return !collides;
|
|
551
|
+
}).map(({ anchor, ...entry }) => lastMaterializedIndex < anchor ? {
|
|
552
|
+
...entry,
|
|
553
|
+
after: true
|
|
554
|
+
} : entry);
|
|
555
|
+
if (publishableOpaqueReasoning.length > 0) this.hasEmittedOpaqueReasoning = true;
|
|
556
|
+
const includeOpaque = this.hasEmittedOpaqueReasoning;
|
|
464
557
|
const timing = this.getTiming();
|
|
465
558
|
const metadata = {
|
|
466
559
|
...timing ? { timing } : {},
|
|
467
|
-
...this.interrupts ? { custom: { [AG_UI_METADATA_NAMESPACE]: {
|
|
560
|
+
...this.interrupts || includeOpaque ? { custom: { [AG_UI_METADATA_NAMESPACE]: {
|
|
561
|
+
...this.interrupts ? { interrupts: this.interrupts } : {},
|
|
562
|
+
...includeOpaque ? { opaqueReasoning: publishableOpaqueReasoning } : {}
|
|
563
|
+
} } } : {}
|
|
468
564
|
};
|
|
469
565
|
const result = {
|
|
470
566
|
content: snapshot,
|
|
@@ -492,7 +588,18 @@ var RunAggregator = class {
|
|
|
492
588
|
};
|
|
493
589
|
}
|
|
494
590
|
handleReasoningStart(messageId, isMessageId = false) {
|
|
495
|
-
if (!this.showThinking)
|
|
591
|
+
if (!this.showThinking) {
|
|
592
|
+
const anchor = this.partOrder.length;
|
|
593
|
+
if (messageId === void 0) {
|
|
594
|
+
this.hiddenActiveReasoning = "anonymous";
|
|
595
|
+
this.hiddenAnonymousAnchor = anchor;
|
|
596
|
+
} else {
|
|
597
|
+
this.hiddenReasoningIds.add(messageId);
|
|
598
|
+
this.hiddenBlockAnchors.set(messageId, anchor);
|
|
599
|
+
this.hiddenActiveReasoning = "identified";
|
|
600
|
+
}
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
496
603
|
this.activeTextMessageId = void 0;
|
|
497
604
|
const key = messageId ?? `__auto-reasoning-${++this.reasoningPartCounter}`;
|
|
498
605
|
if (messageId === void 0) this.anonymousReasoningKeys.add(key);
|
|
@@ -508,7 +615,11 @@ var RunAggregator = class {
|
|
|
508
615
|
this.emit();
|
|
509
616
|
}
|
|
510
617
|
handleReasoningContent(delta, messageId, isMessageId = false) {
|
|
511
|
-
if (!
|
|
618
|
+
if (!delta) return;
|
|
619
|
+
if (!this.showThinking) {
|
|
620
|
+
if (this.hiddenActiveReasoning === "none") this.handleReasoningStart(messageId, isMessageId);
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
512
623
|
if (!this.activeReasoningKey) this.handleReasoningStart(messageId, isMessageId);
|
|
513
624
|
const key = this.activeReasoningKey;
|
|
514
625
|
if (!key) return;
|
|
@@ -516,7 +627,10 @@ var RunAggregator = class {
|
|
|
516
627
|
this.emit();
|
|
517
628
|
}
|
|
518
629
|
handleReasoningEnd() {
|
|
519
|
-
if (!this.showThinking)
|
|
630
|
+
if (!this.showThinking) {
|
|
631
|
+
this.hiddenActiveReasoning = "none";
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
520
634
|
this.activeReasoningKey = void 0;
|
|
521
635
|
this.emit();
|
|
522
636
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-aggregator.js","names":[],"sources":["../../../src/runtime/adapter/run-aggregator.ts"],"sourcesContent":["\"use client\";\n\nimport {\n isMcpAppUri,\n type ChatModelRunResult,\n type MessageTiming,\n type ThreadAssistantMessagePart,\n type ToolCallMessagePart,\n type ToolModelContentPart,\n} from \"@assistant-ui/core\";\nimport {\n applyA2uiOperations,\n convertSurfaceToUISpec,\n type A2uiState,\n type A2uiSurfaceState,\n} from \"@assistant-ui/react-generative-ui/a2ui\";\nimport { readMcpAppResourceUri } from \"../mcp-tool-result\";\nimport type { AgUiEvent, AgUiInterrupt } from \"../types\";\nimport type { Logger } from \"../logger\";\n\nexport const AG_UI_METADATA_NAMESPACE = \"agui\";\n\nexport type AgUiOpaqueReasoning = {\n id: string;\n encryptedValue: string;\n after?: boolean;\n};\n\nexport type AgUiCustomMetadata = {\n interrupts?: AgUiInterrupt[];\n opaqueReasoning?: AgUiOpaqueReasoning[];\n};\n\ntype Emit = (update: ChatModelRunResult) => void;\n\ntype ToolCallState = {\n toolCallId: string;\n toolCallName: string;\n argsText: string;\n parsedArgs: Record<string, unknown> | undefined;\n result: unknown;\n isError: boolean | undefined;\n parentMessageId?: string;\n toolMessageId?: string;\n mcpAppResourceUri?: string;\n mcpAppServerId?: string;\n modelContent?: ToolModelContentPart[];\n snapshotResultApplied: boolean;\n};\n\nexport const MCP_APPS_ACTIVITY_TYPE = \"mcp-apps\";\n\nexport const A2UI_SURFACE_ACTIVITY_TYPE = \"a2ui-surface\";\n\nexport const isPlainObject = (\n value: unknown,\n): value is Record<string, unknown> =>\n !!value && typeof value === \"object\" && !Array.isArray(value);\n\nexport type RunAggregatorOptions = {\n showThinking: boolean;\n logger: Logger;\n emit: Emit;\n onServerMessageId?: (messageId: string) => void;\n};\n\n/**\n * Collects AG-UI events into assistant-ui run snapshots that can be yielded from a ChatModelAdapter.\n *\n * The aggregator keeps a single assistant message worth of parts. Each incoming event updates the parts and\n * emits a fresh snapshot through the provided `emit` callback.\n */\nexport class RunAggregator {\n private readonly emitUpdate: Emit;\n private readonly showThinking: boolean;\n private readonly logger: Logger;\n private readonly onServerMessageId: ((messageId: string) => void) | undefined;\n\n private status: ChatModelRunResult[\"status\"] | undefined;\n private interrupts: AgUiInterrupt[] | undefined;\n private readonly textParts = new Map<\n string,\n { buffer: string; touched: boolean }\n >();\n private activeTextMessageId: string | undefined;\n private readonly reasoningParts = new Map<string, string>(); // key → buffer\n private readonly reasoningSignatures = new Map<string, string>();\n private readonly reasoningMessageIds = new Map<string, string>();\n private readonly anonymousReasoningKeys = new Set<string>();\n private activeReasoningKey: string | undefined;\n private reasoningPartCounter = 0;\n private readonly toolCalls = new Map<string, ToolCallState>();\n private readonly a2uiBuckets = new Map<string, A2uiState>();\n private readonly a2uiToolCallIds = new Set<string>();\n private lastResolvedToolCallId: string | undefined;\n private readonly partOrder: (\n | { kind: \"text\"; key: string }\n | { kind: \"reasoning\"; key: string }\n | { kind: \"tool-call\"; toolCallId: string }\n )[] = [];\n private textPartCounter = 0;\n private serverMessageIdReported = false;\n\n private streamStartTime: number | undefined;\n private firstTokenTime: number | undefined;\n private totalChunks = 0;\n\n constructor(options: RunAggregatorOptions) {\n this.emitUpdate = options.emit;\n this.showThinking = options.showThinking;\n this.logger = options.logger;\n this.onServerMessageId = options.onServerMessageId;\n }\n\n hasToolCall(toolCallId: string): boolean {\n return this.toolCalls.has(toolCallId);\n }\n\n handle(event: AgUiEvent): void {\n switch (event.type) {\n case \"RUN_STARTED\": {\n this.clearTextParts();\n this.reasoningParts.clear();\n this.reasoningSignatures.clear();\n this.reasoningMessageIds.clear();\n this.anonymousReasoningKeys.clear();\n this.activeReasoningKey = undefined;\n this.reasoningPartCounter = 0;\n this.toolCalls.clear();\n this.a2uiBuckets.clear();\n this.a2uiToolCallIds.clear();\n this.lastResolvedToolCallId = undefined;\n this.partOrder.length = 0;\n this.textPartCounter = 0;\n this.activeTextMessageId = undefined;\n this.interrupts = undefined;\n this.serverMessageIdReported = false;\n this.streamStartTime = Date.now();\n this.firstTokenTime = undefined;\n this.totalChunks = 0;\n this.status = { type: \"running\" };\n this.emit();\n break;\n }\n case \"RUN_FINISHED\": {\n if (event.outcome?.type === \"interrupt\") {\n this.interrupts = event.outcome.interrupts;\n this.status = { type: \"requires-action\", reason: \"interrupt\" };\n this.emit();\n break;\n }\n\n this.interrupts = undefined;\n const hasUnresolvedToolCalls = Array.from(this.toolCalls.values()).some(\n (tc) => tc.result === undefined,\n );\n\n this.status =\n event.outcome?.type === \"success\" || !hasUnresolvedToolCalls\n ? { type: \"complete\", reason: \"unknown\" }\n : { type: \"requires-action\", reason: \"tool-calls\" };\n this.emit();\n break;\n }\n case \"RUN_ERROR\": {\n this.status = {\n type: \"incomplete\",\n reason: \"error\",\n ...(event.message !== undefined ? { error: event.message } : {}),\n };\n this.emit();\n break;\n }\n case \"RUN_CANCELLED\": {\n this.status = { type: \"incomplete\", reason: \"cancelled\" };\n this.emit();\n break;\n }\n\n case \"TEXT_MESSAGE_START\": {\n this.reportServerMessageId(event.messageId);\n const id = this.startTextMessage(event.messageId);\n if (id) {\n this.markTextPartTouched(id);\n }\n this.emit();\n break;\n }\n case \"TEXT_MESSAGE_CONTENT\":\n case \"TEXT_MESSAGE_CHUNK\": {\n const incomingId = \"messageId\" in event ? event.messageId : undefined;\n this.reportServerMessageId(incomingId);\n if (!event.delta) break;\n this.recordFirstToken();\n const id = this.resolveTextMessageId(incomingId);\n this.appendText(id, event.delta);\n this.totalChunks++;\n this.emit();\n break;\n }\n case \"TEXT_MESSAGE_END\": {\n this.reportServerMessageId(event.messageId);\n if (event.messageId && this.activeTextMessageId === event.messageId) {\n this.activeTextMessageId = undefined;\n }\n this.emit();\n break;\n }\n\n case \"THINKING_START\":\n case \"THINKING_TEXT_MESSAGE_START\":\n case \"REASONING_START\":\n case \"REASONING_MESSAGE_START\":\n this.handleReasoningStart(\n \"messageId\" in event ? event.messageId : undefined,\n event.type === \"REASONING_MESSAGE_START\",\n );\n break;\n case \"REASONING_ENCRYPTED_VALUE\":\n if (event.subtype === \"message\") {\n // entityId names any message, not necessarily a reasoning one, so an\n // unmatched id may only claim a block that has no id to contradict it.\n const active = this.activeReasoningKey;\n const key = this.reasoningParts.has(event.entityId)\n ? event.entityId\n : active !== undefined && this.anonymousReasoningKeys.has(active)\n ? active\n : undefined;\n if (key !== undefined) {\n this.reasoningSignatures.set(key, event.encryptedValue);\n this.emit();\n }\n }\n break;\n case \"THINKING_TEXT_MESSAGE_CONTENT\":\n this.handleReasoningContent(event.delta);\n this.totalChunks++;\n this.recordFirstToken();\n break;\n case \"REASONING_MESSAGE_CONTENT\":\n this.handleReasoningContent(\n event.delta,\n \"messageId\" in event ? event.messageId : undefined,\n true,\n );\n this.totalChunks++;\n this.recordFirstToken();\n break;\n case \"THINKING_TEXT_MESSAGE_END\":\n case \"THINKING_END\":\n case \"REASONING_MESSAGE_END\":\n case \"REASONING_END\":\n this.handleReasoningEnd();\n break;\n\n case \"TOOL_CALL_START\": {\n this.reportServerMessageId(event.parentMessageId);\n this.startToolCall(\n event.toolCallId,\n event.toolCallName,\n event.parentMessageId,\n );\n this.emit();\n break;\n }\n case \"TOOL_CALL_ARGS\":\n case \"TOOL_CALL_CHUNK\": {\n if (event.type === \"TOOL_CALL_CHUNK\") {\n this.reportServerMessageId(event.parentMessageId);\n }\n if (!event.delta) break;\n this.appendToolArgs(event.toolCallId, event.delta);\n this.emit();\n break;\n }\n case \"TOOL_CALL_END\": {\n this.emit();\n break;\n }\n case \"TOOL_CALL_RESULT\": {\n this.finishToolCall(\n event.toolCallId,\n event.content ?? \"\",\n typeof event.mcpResult?.isError === \"boolean\"\n ? event.mcpResult.isError\n : event.role === \"tool\"\n ? false\n : undefined,\n event.messageId,\n event.mcpResult,\n );\n this.emit();\n break;\n }\n case \"ACTIVITY_SNAPSHOT\": {\n if (event.activityType === A2UI_SURFACE_ACTIVITY_TYPE) {\n this.handleA2uiActivitySnapshot(event);\n break;\n }\n if (event.activityType !== MCP_APPS_ACTIVITY_TYPE) break;\n const toolCallId = event.content.toolCallId;\n const entry =\n typeof toolCallId === \"string\"\n ? this.toolCalls.get(toolCallId)\n : this.lastResolvedToolCallId\n ? this.toolCalls.get(this.lastResolvedToolCallId)\n : undefined;\n const resourceUri = event.content.resourceUri;\n if (\n entry &&\n typeof resourceUri === \"string\" &&\n isMcpAppUri(resourceUri)\n ) {\n entry.mcpAppResourceUri = resourceUri;\n const id = event.content.serverId;\n const hash = event.content.serverHash;\n if (typeof id === \"string\" && id.length > 0) {\n entry.mcpAppServerId = id;\n } else if (typeof hash === \"string\" && hash.length > 0) {\n entry.mcpAppServerId = hash;\n }\n const result = event.content.result;\n if (isPlainObject(result)) {\n if (\n entry.result !== undefined &&\n entry.modelContent === undefined\n ) {\n entry.modelContent = [\n {\n type: \"text\",\n text:\n typeof entry.result === \"string\"\n ? entry.result\n : JSON.stringify(entry.result),\n },\n ];\n }\n entry.result = result;\n entry.snapshotResultApplied = true;\n if (typeof result.isError === \"boolean\") {\n entry.isError = result.isError;\n }\n }\n this.emit();\n }\n break;\n }\n\n default: {\n this.logger.debug?.(\"[agui] aggregator ignored event\", event);\n }\n }\n }\n\n private handleA2uiActivitySnapshot(\n event: Extract<AgUiEvent, { type: \"ACTIVITY_SNAPSHOT\" }>,\n ): void {\n const operations = event.content[\"a2ui_operations\"];\n if (!Array.isArray(operations)) return;\n\n const messageId = event.messageId ?? \"a2ui:anonymous\";\n if (event.replace === false && this.a2uiBuckets.has(messageId)) return;\n\n const { state, warnings } = applyA2uiOperations(new Map(), operations);\n for (const warning of warnings) {\n this.logger.debug(\"[agui] a2ui operation warning\", warning);\n }\n this.a2uiBuckets.delete(messageId);\n this.a2uiBuckets.set(messageId, state);\n this.synthesizeA2uiToolCalls();\n this.emit();\n }\n\n private synthesizeA2uiToolCalls(): void {\n const surfaces = new Map<string, A2uiSurfaceState>();\n\n for (const bucket of this.a2uiBuckets.values()) {\n for (const [surfaceId, surface] of bucket) {\n surfaces.set(surfaceId, surface);\n }\n }\n\n const activeToolCallIds = new Set<string>();\n for (const [surfaceId, surface] of surfaces) {\n const toolCallId = `a2ui:${surfaceId}`;\n const { spec, warnings } = convertSurfaceToUISpec(surface);\n for (const warning of warnings) {\n this.logger.debug(\"[agui] a2ui surface conversion warning\", warning);\n }\n if (!spec) continue;\n\n activeToolCallIds.add(toolCallId);\n\n const entry: ToolCallState = {\n toolCallId,\n toolCallName: \"present\",\n argsText: JSON.stringify(spec),\n parsedArgs: spec,\n result: {},\n isError: undefined,\n snapshotResultApplied: false,\n };\n if (!this.toolCalls.has(toolCallId)) {\n this.partOrder.push({ kind: \"tool-call\", toolCallId });\n }\n this.toolCalls.set(toolCallId, entry);\n this.a2uiToolCallIds.add(toolCallId);\n }\n\n for (const toolCallId of this.a2uiToolCallIds) {\n if (activeToolCallIds.has(toolCallId)) continue;\n this.toolCalls.delete(toolCallId);\n const partIndex = this.partOrder.findIndex(\n (part) => part.kind === \"tool-call\" && part.toolCallId === toolCallId,\n );\n if (partIndex !== -1) this.partOrder.splice(partIndex, 1);\n this.a2uiToolCallIds.delete(toolCallId);\n }\n }\n\n private reportServerMessageId(messageId: string | undefined): void {\n if (this.serverMessageIdReported || !messageId) return;\n this.serverMessageIdReported = true;\n this.onServerMessageId?.(messageId);\n }\n\n private clearTextParts(): void {\n this.textParts.clear();\n }\n\n private generateTextKey(): string {\n this.textPartCounter += 1;\n return `text-${this.textPartCounter}`;\n }\n\n private startTextMessage(messageId?: string): string {\n const id = messageId ?? this.generateTextKey();\n this.ensureTextPart(id);\n this.activeTextMessageId = id;\n return id;\n }\n\n private resolveTextMessageId(messageId?: string): string {\n if (messageId) {\n this.ensureTextPart(messageId);\n this.activeTextMessageId = messageId;\n return messageId;\n }\n\n if (this.activeTextMessageId) {\n return this.activeTextMessageId;\n }\n\n const generated = this.generateTextKey();\n this.ensureTextPart(generated);\n this.activeTextMessageId = generated;\n return generated;\n }\n\n private ensureTextPart(id: string): void {\n if (!this.textParts.has(id)) {\n this.textParts.set(id, { buffer: \"\", touched: false });\n if (\n !this.partOrder.some((part) => part.kind === \"text\" && part.key === id)\n ) {\n this.partOrder.push({ kind: \"text\", key: id });\n }\n }\n }\n\n private markTextPartTouched(id: string): void {\n const entry = this.textParts.get(id);\n if (!entry) return;\n entry.touched = true;\n }\n\n private appendText(id: string, delta: string): void {\n this.ensureTextPart(id);\n const entry = this.textParts.get(id);\n if (!entry) return;\n entry.buffer += delta;\n entry.touched = true;\n }\n\n private startToolCall(\n id: string | undefined,\n name?: string,\n parentMessageId?: string,\n ) {\n if (!id) return;\n // A new tool call acts as a boundary: any anonymous text that arrives\n // after it should be a new part, not appended to the pre-tool text.\n this.activeTextMessageId = undefined;\n if (\n !this.partOrder.some(\n (part) => part.kind === \"tool-call\" && part.toolCallId === id,\n )\n ) {\n this.insertToolPart(id, parentMessageId);\n }\n const state: ToolCallState = {\n toolCallId: id,\n toolCallName: name ?? \"tool\",\n argsText: \"\",\n parsedArgs: undefined,\n result: undefined,\n isError: undefined,\n snapshotResultApplied: false,\n };\n if (parentMessageId) {\n state.parentMessageId = parentMessageId;\n }\n this.toolCalls.set(id, state);\n }\n\n // The message and tool-call channels are unordered on the wire, so anchor a\n // tool call under its parentMessageId text part instead of appending it.\n private insertToolPart(id: string, parentMessageId?: string) {\n const entry = { kind: \"tool-call\", toolCallId: id } as const;\n if (parentMessageId) {\n const parentIndex = this.partOrder.findIndex(\n (part) => part.kind === \"text\" && part.key === parentMessageId,\n );\n if (parentIndex !== -1) {\n let insertAt = parentIndex + 1;\n while (insertAt < this.partOrder.length) {\n const part = this.partOrder[insertAt];\n if (\n part?.kind === \"tool-call\" &&\n this.toolCalls.get(part.toolCallId)?.parentMessageId ===\n parentMessageId\n ) {\n insertAt += 1;\n continue;\n }\n break;\n }\n this.partOrder.splice(insertAt, 0, entry);\n return;\n }\n }\n this.partOrder.push(entry);\n }\n\n private appendToolArgs(id: string | undefined, delta: string) {\n const entry = id ? this.toolCalls.get(id) : undefined;\n if (!entry) return;\n entry.argsText += delta;\n try {\n const parsed = JSON.parse(entry.argsText);\n if (parsed && typeof parsed === \"object\") {\n entry.parsedArgs = parsed as Record<string, unknown>;\n } else {\n entry.parsedArgs = undefined;\n }\n } catch {\n entry.parsedArgs = undefined;\n }\n }\n\n private finishToolCall(\n id: string,\n content: string,\n isError?: boolean,\n toolMessageId?: string,\n mcpResult?: Record<string, unknown>,\n ) {\n if (!id) return;\n let entry = this.toolCalls.get(id);\n if (!entry) {\n entry = {\n toolCallId: id,\n toolCallName: \"tool\",\n argsText: \"\",\n parsedArgs: undefined,\n result: undefined,\n isError: undefined,\n snapshotResultApplied: false,\n };\n this.toolCalls.set(id, entry);\n }\n if (\n !this.partOrder.some(\n (part) => part.kind === \"tool-call\" && part.toolCallId === id,\n )\n ) {\n this.partOrder.push({ kind: \"tool-call\", toolCallId: id });\n }\n if (mcpResult !== undefined && !entry.snapshotResultApplied) {\n entry.result = mcpResult;\n entry.modelContent = [{ type: \"text\", text: content }];\n entry.snapshotResultApplied = true;\n entry.isError = isError;\n if (entry.mcpAppResourceUri === undefined) {\n const uri = readMcpAppResourceUri(mcpResult._meta);\n if (uri !== undefined) entry.mcpAppResourceUri = uri;\n }\n } else if (entry.snapshotResultApplied) {\n if (entry.modelContent === undefined) {\n entry.modelContent = [{ type: \"text\", text: content }];\n }\n if (entry.isError === undefined) {\n entry.isError = isError;\n }\n } else {\n entry.result = tryParseJSON(content);\n entry.isError = isError;\n }\n if (toolMessageId) {\n entry.toolMessageId = toolMessageId;\n }\n this.lastResolvedToolCallId = id;\n }\n\n private emit(): void {\n const snapshot: ThreadAssistantMessagePart[] = [];\n\n for (const part of this.partOrder) {\n if (part.kind === \"reasoning\") {\n if (this.showThinking) {\n const buffer = this.reasoningParts.get(part.key) ?? \"\";\n if (buffer.length > 0 || this.activeReasoningKey === part.key) {\n const encryptedValue = this.reasoningSignatures.get(part.key);\n const reasoningId = this.reasoningMessageIds.get(part.key);\n const meta = {\n ...(reasoningId !== undefined ? { reasoningId } : {}),\n ...(encryptedValue !== undefined ? { encryptedValue } : {}),\n };\n snapshot.push({\n type: \"reasoning\",\n text: buffer,\n ...(Object.keys(meta).length > 0\n ? { providerMetadata: { [AG_UI_METADATA_NAMESPACE]: meta } }\n : {}),\n } as const);\n }\n }\n continue;\n }\n\n if (part.kind === \"text\") {\n const entry = this.textParts.get(part.key);\n if (entry?.touched) {\n snapshot.push({ type: \"text\", text: entry.buffer } as const);\n }\n continue;\n }\n\n const entry = this.toolCalls.get(part.toolCallId);\n if (!entry) continue;\n const toolPart: ToolCallMessagePart = {\n type: \"tool-call\",\n toolCallId: entry.toolCallId,\n toolName: entry.toolCallName,\n args: (entry.parsedArgs ?? {}) as any,\n argsText: entry.argsText,\n ...(entry.result !== undefined ? { result: entry.result } : {}),\n ...(entry.modelContent !== undefined\n ? { modelContent: entry.modelContent }\n : {}),\n ...(entry.isError !== undefined ? { isError: entry.isError } : {}),\n ...(entry.mcpAppResourceUri\n ? {\n mcp: {\n app: {\n resourceUri: entry.mcpAppResourceUri,\n ...(entry.mcpAppServerId\n ? { serverId: entry.mcpAppServerId }\n : {}),\n },\n },\n }\n : {}),\n ...(entry.parentMessageId ? { parentId: entry.parentMessageId } : {}),\n ...(entry.toolMessageId\n ? { unstable_toolMessageId: entry.toolMessageId }\n : {}),\n } as ToolCallMessagePart & { unstable_toolMessageId?: string };\n snapshot.push(toolPart);\n }\n\n const timing = this.getTiming();\n const metadata = {\n ...(timing ? { timing } : {}),\n ...(this.interrupts\n ? {\n custom: {\n [AG_UI_METADATA_NAMESPACE]: {\n interrupts: this.interrupts,\n } satisfies AgUiCustomMetadata,\n },\n }\n : {}),\n };\n const result: ChatModelRunResult = {\n content: snapshot,\n ...(this.status ? { status: this.status } : undefined),\n ...(Object.keys(metadata).length > 0 ? { metadata } : undefined),\n };\n this.emitUpdate(result);\n }\n\n private recordFirstToken(): void {\n if (\n this.firstTokenTime === undefined &&\n this.streamStartTime !== undefined\n ) {\n this.firstTokenTime = Date.now() - this.streamStartTime;\n }\n }\n\n private getTiming(): MessageTiming | undefined {\n if (this.streamStartTime === undefined) return undefined;\n\n const now = Date.now();\n const totalStreamTime = now - this.streamStartTime;\n const tokenCount =\n this.totalChunks > 0\n ? Math.ceil(\n Array.from(this.textParts.values()).reduce(\n (sum, p) => sum + p.buffer.length,\n 0,\n ) / 4,\n )\n : undefined;\n const tokensPerSecond =\n tokenCount && totalStreamTime > 0\n ? (tokenCount / totalStreamTime) * 1000\n : undefined;\n\n return {\n streamStartTime: this.streamStartTime,\n ...(this.firstTokenTime !== undefined\n ? { firstTokenTime: this.firstTokenTime }\n : {}),\n totalStreamTime,\n ...(tokenCount !== undefined ? { tokenCount } : {}),\n ...(tokensPerSecond !== undefined ? { tokensPerSecond } : {}),\n totalChunks: this.totalChunks,\n toolCallCount: this.toolCalls.size,\n };\n }\n\n private handleReasoningStart(messageId?: string, isMessageId = false): void {\n if (!this.showThinking) return;\n // A reasoning block acts as a boundary: anonymous text arriving after it\n // should be a new part, not appended to any pre-reasoning text.\n this.activeTextMessageId = undefined;\n const key = messageId ?? `__auto-reasoning-${++this.reasoningPartCounter}`;\n // Two different questions: which id may be replayed as a ReasoningMessage.id\n // (only the message-scoped aliases carry one), and which block an unmatched\n // signature may claim (any block opened without an id at all).\n if (messageId === undefined) {\n this.anonymousReasoningKeys.add(key);\n } else if (isMessageId) {\n this.reasoningMessageIds.set(key, messageId);\n }\n if (!this.reasoningParts.has(key)) {\n this.reasoningParts.set(key, \"\");\n this.partOrder.push({ kind: \"reasoning\", key });\n }\n this.activeReasoningKey = key;\n this.emit();\n }\n\n private handleReasoningContent(\n delta: string,\n messageId?: string,\n isMessageId = false,\n ): void {\n if (!this.showThinking || !delta) return;\n if (!this.activeReasoningKey) {\n // Content arrived without a preceding START — create the slot lazily.\n this.handleReasoningStart(messageId, isMessageId);\n }\n const key = this.activeReasoningKey;\n if (!key) return;\n this.reasoningParts.set(key, (this.reasoningParts.get(key) ?? \"\") + delta);\n this.emit();\n }\n\n private handleReasoningEnd(): void {\n if (!this.showThinking) return;\n this.activeReasoningKey = undefined;\n this.emit();\n }\n}\n\nexport function tryParseJSON(value: string): unknown {\n if (!value) return value;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run-aggregator.js","names":[],"sources":["../../../src/runtime/adapter/run-aggregator.ts"],"sourcesContent":["\"use client\";\n\nimport {\n isMcpAppUri,\n type ChatModelRunResult,\n type MessageTiming,\n type ThreadAssistantMessagePart,\n type ToolCallMessagePart,\n type ToolModelContentPart,\n} from \"@assistant-ui/core\";\nimport {\n applyA2uiOperations,\n convertSurfaceToUISpec,\n type A2uiState,\n type A2uiSurfaceState,\n} from \"@assistant-ui/react-generative-ui/a2ui\";\nimport { readMcpAppResourceUri } from \"../mcp-tool-result\";\nimport { projectAgUiToolApprovals } from \"./tool-approval\";\nimport type { AgUiEvent, AgUiInterrupt } from \"../types\";\nimport type { Logger } from \"../logger\";\n\nexport const AG_UI_METADATA_NAMESPACE = \"agui\";\n\nexport type AgUiOpaqueReasoning = {\n id: string;\n encryptedValue: string;\n after?: boolean;\n};\n\nexport type AgUiCustomMetadata = {\n /** Wire role restored on export for messages the internal model cannot\n * represent (a developer record rides as a system message). */\n role?: \"developer\";\n interrupts?: AgUiInterrupt[];\n opaqueReasoning?: AgUiOpaqueReasoning[];\n};\n\ntype Emit = (update: ChatModelRunResult) => void;\n\ntype ToolCallState = {\n toolCallId: string;\n toolCallName: string;\n argsText: string;\n parsedArgs: Record<string, unknown> | undefined;\n result: unknown;\n isError: boolean | undefined;\n parentMessageId?: string;\n toolMessageId?: string;\n mcpAppResourceUri?: string;\n mcpAppServerId?: string;\n modelContent?: ToolModelContentPart[];\n snapshotResultApplied: boolean;\n};\n\nexport const MCP_APPS_ACTIVITY_TYPE = \"mcp-apps\";\n\nexport const A2UI_SURFACE_ACTIVITY_TYPE = \"a2ui-surface\";\n\nexport const isPlainObject = (\n value: unknown,\n): value is Record<string, unknown> =>\n !!value && typeof value === \"object\" && !Array.isArray(value);\n\nexport type RunAggregatorOptions = {\n showThinking: boolean;\n logger: Logger;\n emit: Emit;\n onServerMessageId?: (messageId: string) => void;\n onTextMessageStart?: (messageId: string) => void;\n};\n\n/**\n * Collects AG-UI events into assistant-ui run snapshots that can be yielded from a ChatModelAdapter.\n *\n * The aggregator keeps a single assistant message worth of parts. Each incoming event updates the parts and\n * emits a fresh snapshot through the provided `emit` callback. `CUSTOM` events\n * become canonical data parts; integration plumbing names such as\n * `on_interrupt`, `PredictState`, `Exit`, `hook_error`, `state_update_error`,\n * `system:*`, and `MultiAgentHandoff` are forwarded the same way, so apps only\n * need data renderers for names they own.\n */\nexport class RunAggregator {\n private readonly emitUpdate: Emit;\n private readonly showThinking: boolean;\n private readonly logger: Logger;\n private readonly onServerMessageId: ((messageId: string) => void) | undefined;\n private readonly onTextMessageStart:\n | ((messageId: string) => void)\n | undefined;\n\n private status: ChatModelRunResult[\"status\"] | undefined;\n private interrupts: AgUiInterrupt[] | undefined;\n private readonly textParts = new Map<string, { buffer: string }>();\n private activeTextMessageId: string | undefined;\n private readonly reasoningParts = new Map<string, string>(); // key → buffer\n private readonly reasoningSignatures = new Map<string, string>();\n private readonly reasoningSignatureIds = new Map<string, string>();\n // Signatures captured while thinking is hidden have no block to live on;\n // they are transport state that must survive to the next run input. The\n // claim rules mirror the visible path: an id-carrying block, or an open\n // anonymous one.\n private readonly hiddenSignatures = new Map<string, string>();\n private readonly hiddenSignatureAnchors = new Map<string, number>();\n private readonly hiddenBlockAnchors = new Map<string, number>();\n private hiddenAnonymousAnchor: number | undefined;\n private readonly hiddenReasoningIds = new Set<string>();\n private hiddenActiveReasoning: \"none\" | \"anonymous\" | \"identified\" = \"none\";\n private hasEmittedOpaqueReasoning = false;\n private readonly loggedDroppedOpaqueIds = new Set<string>();\n private readonly reasoningMessageIds = new Map<string, string>();\n private readonly anonymousReasoningKeys = new Set<string>();\n private activeReasoningKey: string | undefined;\n private reasoningPartCounter = 0;\n private readonly toolCalls = new Map<string, ToolCallState>();\n private readonly a2uiBuckets = new Map<string, A2uiState>();\n private readonly a2uiToolCallIds = new Set<string>();\n private lastResolvedToolCallId: string | undefined;\n private readonly partOrder: (\n | { kind: \"text\"; key: string }\n | { kind: \"reasoning\"; key: string }\n | { kind: \"tool-call\"; toolCallId: string }\n | { kind: \"data\"; name: string; value: unknown }\n )[] = [];\n private textPartCounter = 0;\n private serverMessageIdReported = false;\n private reportedServerMessageId: string | undefined;\n private lastTextMessageId: string | undefined;\n\n private streamStartTime: number | undefined;\n private firstTokenTime: number | undefined;\n private totalChunks = 0;\n\n constructor(options: RunAggregatorOptions) {\n this.emitUpdate = options.emit;\n this.showThinking = options.showThinking;\n this.logger = options.logger;\n this.onServerMessageId = options.onServerMessageId;\n this.onTextMessageStart = options.onTextMessageStart;\n }\n\n hasToolCall(toolCallId: string): boolean {\n return this.toolCalls.has(toolCallId);\n }\n\n handle(event: AgUiEvent): void {\n switch (event.type) {\n case \"RUN_STARTED\": {\n this.resetMessageParts();\n this.interrupts = undefined;\n this.serverMessageIdReported = false;\n this.lastTextMessageId = undefined;\n this.reportedServerMessageId = undefined;\n this.streamStartTime = Date.now();\n this.firstTokenTime = undefined;\n this.totalChunks = 0;\n this.status = { type: \"running\" };\n this.emit();\n break;\n }\n case \"RUN_FINISHED\": {\n if (event.outcome?.type === \"interrupt\") {\n this.interrupts = event.outcome.interrupts;\n this.status = { type: \"requires-action\", reason: \"interrupt\" };\n this.emit();\n break;\n }\n\n this.interrupts = undefined;\n const hasUnresolvedToolCalls = Array.from(this.toolCalls.values()).some(\n (tc) => tc.result === undefined,\n );\n\n this.status =\n event.outcome?.type === \"success\" || !hasUnresolvedToolCalls\n ? { type: \"complete\", reason: \"unknown\" }\n : { type: \"requires-action\", reason: \"tool-calls\" };\n this.emit();\n break;\n }\n case \"RUN_ERROR\": {\n this.status = {\n type: \"incomplete\",\n reason: \"error\",\n ...(event.message !== undefined ? { error: event.message } : {}),\n };\n this.emit();\n break;\n }\n case \"RUN_CANCELLED\": {\n this.status = { type: \"incomplete\", reason: \"cancelled\" };\n this.emit();\n break;\n }\n\n case \"TEXT_MESSAGE_START\": {\n this.beginDistinctTextMessage(event.messageId);\n this.reportServerMessageId(event.messageId);\n this.startTextMessage(event.messageId);\n if (event.messageId) this.lastTextMessageId = event.messageId;\n this.emit();\n break;\n }\n case \"TEXT_MESSAGE_CONTENT\":\n case \"TEXT_MESSAGE_CHUNK\": {\n const incomingId = \"messageId\" in event ? event.messageId : undefined;\n this.beginDistinctTextMessage(incomingId);\n this.reportServerMessageId(incomingId);\n if (incomingId) this.lastTextMessageId = incomingId;\n if (!event.delta) break;\n this.recordFirstToken();\n const id = this.resolveTextMessageId(incomingId);\n this.appendText(id, event.delta);\n this.totalChunks++;\n this.emit();\n break;\n }\n case \"TEXT_MESSAGE_END\": {\n this.reportServerMessageId(event.messageId);\n if (event.messageId && this.activeTextMessageId === event.messageId) {\n this.activeTextMessageId = undefined;\n }\n this.emit();\n break;\n }\n\n case \"CUSTOM\": {\n this.activeTextMessageId = undefined;\n this.partOrder.push({\n kind: \"data\",\n name: event.name,\n value: event.value,\n });\n this.emit();\n break;\n }\n\n case \"THINKING_START\":\n case \"THINKING_TEXT_MESSAGE_START\":\n case \"REASONING_START\":\n case \"REASONING_MESSAGE_START\":\n this.handleReasoningStart(\n \"messageId\" in event ? event.messageId : undefined,\n event.type === \"REASONING_MESSAGE_START\",\n );\n break;\n case \"REASONING_ENCRYPTED_VALUE\":\n if (event.subtype === \"message\") {\n // entityId names any message, not necessarily a reasoning one, so an\n // unmatched id may only claim a block that has no id to contradict it.\n const active = this.activeReasoningKey;\n const key = this.showThinking\n ? this.reasoningParts.has(event.entityId)\n ? event.entityId\n : active !== undefined && this.anonymousReasoningKeys.has(active)\n ? active\n : undefined\n : undefined;\n if (key !== undefined) {\n this.reasoningSignatures.set(key, event.encryptedValue);\n this.reasoningSignatureIds.set(key, event.entityId);\n this.emit();\n } else if (\n !this.showThinking &&\n event.entityId.trim().length > 0 &&\n event.encryptedValue.trim().length > 0 &&\n (this.hiddenReasoningIds.has(event.entityId) ||\n this.hiddenActiveReasoning === \"anonymous\")\n ) {\n this.hiddenSignatures.set(event.entityId, event.encryptedValue);\n this.hiddenSignatureAnchors.set(\n event.entityId,\n this.hiddenBlockAnchors.get(event.entityId) ??\n this.hiddenAnonymousAnchor ??\n this.partOrder.length,\n );\n this.emit();\n }\n }\n break;\n case \"THINKING_TEXT_MESSAGE_CONTENT\":\n this.handleReasoningContent(event.delta);\n this.totalChunks++;\n this.recordFirstToken();\n break;\n case \"REASONING_MESSAGE_CONTENT\":\n this.handleReasoningContent(\n event.delta,\n \"messageId\" in event ? event.messageId : undefined,\n true,\n );\n this.totalChunks++;\n this.recordFirstToken();\n break;\n case \"THINKING_TEXT_MESSAGE_END\":\n case \"THINKING_END\":\n case \"REASONING_MESSAGE_END\":\n case \"REASONING_END\":\n this.handleReasoningEnd();\n break;\n\n case \"TOOL_CALL_START\": {\n this.reportServerMessageId(event.parentMessageId);\n this.startToolCall(\n event.toolCallId,\n event.toolCallName,\n event.parentMessageId,\n );\n this.emit();\n break;\n }\n case \"TOOL_CALL_ARGS\":\n case \"TOOL_CALL_CHUNK\": {\n if (event.type === \"TOOL_CALL_CHUNK\") {\n this.reportServerMessageId(event.parentMessageId);\n }\n if (!event.delta) break;\n this.appendToolArgs(event.toolCallId, event.delta);\n this.emit();\n break;\n }\n case \"TOOL_CALL_END\": {\n this.emit();\n break;\n }\n case \"TOOL_CALL_RESULT\": {\n this.finishToolCall(\n event.toolCallId,\n event.content ?? \"\",\n typeof event.mcpResult?.isError === \"boolean\"\n ? event.mcpResult.isError\n : event.role === \"tool\"\n ? false\n : undefined,\n event.messageId,\n event.mcpResult,\n );\n this.emit();\n break;\n }\n case \"ACTIVITY_SNAPSHOT\": {\n if (event.activityType === A2UI_SURFACE_ACTIVITY_TYPE) {\n this.handleA2uiActivitySnapshot(event);\n break;\n }\n if (event.activityType !== MCP_APPS_ACTIVITY_TYPE) break;\n const toolCallId = event.content.toolCallId;\n const entry =\n typeof toolCallId === \"string\"\n ? this.toolCalls.get(toolCallId)\n : this.lastResolvedToolCallId\n ? this.toolCalls.get(this.lastResolvedToolCallId)\n : undefined;\n const resourceUri = event.content.resourceUri;\n if (\n entry &&\n typeof resourceUri === \"string\" &&\n isMcpAppUri(resourceUri)\n ) {\n entry.mcpAppResourceUri = resourceUri;\n const id = event.content.serverId;\n const hash = event.content.serverHash;\n if (typeof id === \"string\" && id.length > 0) {\n entry.mcpAppServerId = id;\n } else if (typeof hash === \"string\" && hash.length > 0) {\n entry.mcpAppServerId = hash;\n }\n const result = event.content.result;\n if (isPlainObject(result)) {\n if (\n entry.result !== undefined &&\n entry.modelContent === undefined\n ) {\n entry.modelContent = [\n {\n type: \"text\",\n text:\n typeof entry.result === \"string\"\n ? entry.result\n : JSON.stringify(entry.result),\n },\n ];\n }\n entry.result = result;\n entry.snapshotResultApplied = true;\n if (typeof result.isError === \"boolean\") {\n entry.isError = result.isError;\n }\n }\n this.emit();\n }\n break;\n }\n\n default: {\n this.logger.debug?.(\"[agui] aggregator ignored event\", event);\n }\n }\n }\n\n private handleA2uiActivitySnapshot(\n event: Extract<AgUiEvent, { type: \"ACTIVITY_SNAPSHOT\" }>,\n ): void {\n const operations = event.content[\"a2ui_operations\"];\n if (!Array.isArray(operations)) return;\n\n const messageId = event.messageId ?? \"a2ui:anonymous\";\n if (event.replace === false && this.a2uiBuckets.has(messageId)) return;\n\n const { state, warnings } = applyA2uiOperations(new Map(), operations);\n for (const warning of warnings) {\n this.logger.debug(\"[agui] a2ui operation warning\", warning);\n }\n this.a2uiBuckets.delete(messageId);\n this.a2uiBuckets.set(messageId, state);\n this.synthesizeA2uiToolCalls();\n this.emit();\n }\n\n private synthesizeA2uiToolCalls(): void {\n const surfaces = new Map<string, A2uiSurfaceState>();\n\n for (const bucket of this.a2uiBuckets.values()) {\n for (const [surfaceId, surface] of bucket) {\n surfaces.set(surfaceId, surface);\n }\n }\n\n const activeToolCallIds = new Set<string>();\n for (const [surfaceId, surface] of surfaces) {\n const toolCallId = `a2ui:${surfaceId}`;\n const { spec, warnings } = convertSurfaceToUISpec(surface);\n for (const warning of warnings) {\n this.logger.debug(\"[agui] a2ui surface conversion warning\", warning);\n }\n if (!spec) continue;\n\n activeToolCallIds.add(toolCallId);\n\n const entry: ToolCallState = {\n toolCallId,\n toolCallName: \"present\",\n argsText: JSON.stringify(spec),\n parsedArgs: spec,\n result: {},\n isError: undefined,\n snapshotResultApplied: false,\n };\n if (!this.toolCalls.has(toolCallId)) {\n this.partOrder.push({ kind: \"tool-call\", toolCallId });\n }\n this.toolCalls.set(toolCallId, entry);\n this.a2uiToolCallIds.add(toolCallId);\n }\n\n for (const toolCallId of this.a2uiToolCallIds) {\n if (activeToolCallIds.has(toolCallId)) continue;\n this.toolCalls.delete(toolCallId);\n const partIndex = this.partOrder.findIndex(\n (part) => part.kind === \"tool-call\" && part.toolCallId === toolCallId,\n );\n if (partIndex !== -1) this.partOrder.splice(partIndex, 1);\n this.a2uiToolCallIds.delete(toolCallId);\n }\n }\n\n private reportServerMessageId(messageId: string | undefined): void {\n if (!messageId) return;\n if (this.lastTextMessageId === undefined) {\n this.lastTextMessageId = messageId;\n }\n if (this.serverMessageIdReported) return;\n this.serverMessageIdReported = true;\n this.reportedServerMessageId = messageId;\n this.onServerMessageId?.(messageId);\n }\n\n private clearTextParts(): void {\n this.textParts.clear();\n }\n\n private resetMessageParts(): void {\n this.clearTextParts();\n this.reasoningParts.clear();\n this.reasoningSignatures.clear();\n this.reasoningSignatureIds.clear();\n this.reasoningMessageIds.clear();\n this.hiddenSignatures.clear();\n this.hiddenSignatureAnchors.clear();\n this.hiddenBlockAnchors.clear();\n this.hiddenAnonymousAnchor = undefined;\n this.hiddenReasoningIds.clear();\n this.hiddenActiveReasoning = \"none\";\n this.loggedDroppedOpaqueIds.clear();\n this.anonymousReasoningKeys.clear();\n this.activeReasoningKey = undefined;\n this.reasoningPartCounter = 0;\n this.toolCalls.clear();\n this.a2uiBuckets.clear();\n this.a2uiToolCallIds.clear();\n this.lastResolvedToolCallId = undefined;\n this.partOrder.length = 0;\n this.textPartCounter = 0;\n this.activeTextMessageId = undefined;\n this.reportedServerMessageId = undefined;\n }\n\n private beginDistinctTextMessage(messageId: string | undefined): void {\n if (\n !messageId ||\n this.lastTextMessageId === undefined ||\n this.lastTextMessageId === messageId ||\n !this.onTextMessageStart\n ) {\n return;\n }\n this.resetMessageParts();\n this.onTextMessageStart(messageId);\n }\n\n private generateTextKey(): string {\n this.textPartCounter += 1;\n return `text-${this.textPartCounter}`;\n }\n\n private startTextMessage(messageId?: string): string {\n const id = messageId ?? this.generateTextKey();\n this.ensureTextPart(id);\n this.activeTextMessageId = id;\n return id;\n }\n\n private resolveTextMessageId(messageId?: string): string {\n if (messageId) {\n this.ensureTextPart(messageId);\n this.activeTextMessageId = messageId;\n return messageId;\n }\n\n if (this.activeTextMessageId) {\n return this.activeTextMessageId;\n }\n\n const generated = this.generateTextKey();\n this.ensureTextPart(generated);\n this.activeTextMessageId = generated;\n return generated;\n }\n\n private ensureTextPart(id: string): void {\n if (!this.textParts.has(id)) {\n this.textParts.set(id, { buffer: \"\" });\n if (\n !this.partOrder.some((part) => part.kind === \"text\" && part.key === id)\n ) {\n this.partOrder.push({ kind: \"text\", key: id });\n }\n }\n }\n\n private appendText(id: string, delta: string): void {\n this.ensureTextPart(id);\n const entry = this.textParts.get(id);\n if (!entry) return;\n entry.buffer += delta;\n }\n\n private startToolCall(\n id: string | undefined,\n name?: string,\n parentMessageId?: string,\n ) {\n if (!id) return;\n // A new tool call acts as a boundary: any anonymous text that arrives\n // after it should be a new part, not appended to the pre-tool text.\n this.activeTextMessageId = undefined;\n if (\n !this.partOrder.some(\n (part) => part.kind === \"tool-call\" && part.toolCallId === id,\n )\n ) {\n this.insertToolPart(id, parentMessageId);\n }\n const state: ToolCallState = {\n toolCallId: id,\n toolCallName: name ?? \"tool\",\n argsText: \"\",\n parsedArgs: undefined,\n result: undefined,\n isError: undefined,\n snapshotResultApplied: false,\n };\n if (parentMessageId) {\n state.parentMessageId = parentMessageId;\n }\n this.toolCalls.set(id, state);\n }\n\n // The message and tool-call channels are unordered on the wire, so anchor a\n // tool call under its parentMessageId text part instead of appending it.\n private insertToolPart(id: string, parentMessageId?: string) {\n const entry = { kind: \"tool-call\", toolCallId: id } as const;\n if (parentMessageId) {\n const parentIndex = this.partOrder.findIndex(\n (part) => part.kind === \"text\" && part.key === parentMessageId,\n );\n if (parentIndex !== -1) {\n let insertAt = parentIndex + 1;\n while (insertAt < this.partOrder.length) {\n const part = this.partOrder[insertAt];\n if (\n part?.kind === \"tool-call\" &&\n this.toolCalls.get(part.toolCallId)?.parentMessageId ===\n parentMessageId\n ) {\n insertAt += 1;\n continue;\n }\n break;\n }\n this.partOrder.splice(insertAt, 0, entry);\n return;\n }\n }\n this.partOrder.push(entry);\n }\n\n private appendToolArgs(id: string | undefined, delta: string) {\n const entry = id ? this.toolCalls.get(id) : undefined;\n if (!entry) return;\n entry.argsText += delta;\n try {\n const parsed = JSON.parse(entry.argsText);\n if (parsed && typeof parsed === \"object\") {\n entry.parsedArgs = parsed as Record<string, unknown>;\n } else {\n entry.parsedArgs = undefined;\n }\n } catch {\n entry.parsedArgs = undefined;\n }\n }\n\n private finishToolCall(\n id: string,\n content: string,\n isError?: boolean,\n toolMessageId?: string,\n mcpResult?: Record<string, unknown>,\n ) {\n if (!id) return;\n let entry = this.toolCalls.get(id);\n if (!entry) {\n entry = {\n toolCallId: id,\n toolCallName: \"tool\",\n argsText: \"\",\n parsedArgs: undefined,\n result: undefined,\n isError: undefined,\n snapshotResultApplied: false,\n };\n this.toolCalls.set(id, entry);\n }\n if (\n !this.partOrder.some(\n (part) => part.kind === \"tool-call\" && part.toolCallId === id,\n )\n ) {\n this.partOrder.push({ kind: \"tool-call\", toolCallId: id });\n }\n if (mcpResult !== undefined && !entry.snapshotResultApplied) {\n entry.result = mcpResult;\n entry.modelContent = [{ type: \"text\", text: content }];\n entry.snapshotResultApplied = true;\n entry.isError = isError;\n if (entry.mcpAppResourceUri === undefined) {\n const uri = readMcpAppResourceUri(mcpResult._meta);\n if (uri !== undefined) entry.mcpAppResourceUri = uri;\n }\n } else if (entry.snapshotResultApplied) {\n if (entry.modelContent === undefined) {\n entry.modelContent = [{ type: \"text\", text: content }];\n }\n if (entry.isError === undefined) {\n entry.isError = isError;\n }\n } else {\n entry.result = tryParseJSON(content);\n entry.isError = isError;\n }\n if (toolMessageId) {\n entry.toolMessageId = toolMessageId;\n }\n this.lastResolvedToolCallId = id;\n }\n\n private emit(): void {\n const snapshot: ThreadAssistantMessagePart[] = [];\n // A run that ended incomplete can no longer be resumed, so a gate left over\n // from an earlier interrupt outcome is unanswerable and must not stay\n // projected. The interrupts themselves are kept on the message, since the\n // bespoke hooks read that payload.\n const approvals = projectAgUiToolApprovals(\n this.status?.type === \"requires-action\" ? this.interrupts : undefined,\n new Set(this.toolCalls.keys()),\n );\n\n const opaqueCandidates: (AgUiOpaqueReasoning & { anchor: number })[] =\n Array.from(this.hiddenSignatures, ([id, encryptedValue]) => ({\n id,\n encryptedValue,\n anchor: this.hiddenSignatureAnchors.get(id)!,\n }));\n\n let currentIndex = -1;\n let lastMaterializedIndex = -1;\n const pushSnapshotPart = (part: (typeof snapshot)[number]) => {\n snapshot.push(part);\n lastMaterializedIndex = currentIndex;\n };\n\n for (const [index, part] of this.partOrder.entries()) {\n currentIndex = index;\n if (part.kind === \"reasoning\") {\n if (this.showThinking) {\n const buffer = this.reasoningParts.get(part.key) ?? \"\";\n if (buffer.length > 0 || this.activeReasoningKey === part.key) {\n const encryptedValue = this.reasoningSignatures.get(part.key);\n const reasoningId = this.reasoningMessageIds.get(part.key);\n const meta = {\n ...(reasoningId !== undefined ? { reasoningId } : {}),\n ...(encryptedValue !== undefined ? { encryptedValue } : {}),\n };\n pushSnapshotPart({\n type: \"reasoning\",\n text: buffer,\n ...(Object.keys(meta).length > 0\n ? { providerMetadata: { [AG_UI_METADATA_NAMESPACE]: meta } }\n : {}),\n } as const);\n } else {\n // A retracted empty block still carries transport state: without\n // a part to live on, its signature rides the message metadata,\n // matching the shape a snapshot reload produces.\n const encryptedValue = this.reasoningSignatures.get(part.key);\n const id = this.reasoningSignatureIds.get(part.key);\n if (id?.trim() && encryptedValue?.trim()) {\n opaqueCandidates.push({ id, encryptedValue, anchor: index + 1 });\n }\n }\n }\n continue;\n }\n\n if (part.kind === \"text\") {\n const entry = this.textParts.get(part.key);\n if (entry && entry.buffer.trim().length > 0) {\n pushSnapshotPart({ type: \"text\", text: entry.buffer } as const);\n }\n continue;\n }\n\n if (part.kind === \"data\") {\n pushSnapshotPart({\n type: \"data\",\n name: part.name,\n data: part.value,\n });\n continue;\n }\n\n const entry = this.toolCalls.get(part.toolCallId);\n if (!entry) continue;\n const approval = approvals.get(entry.toolCallId);\n const toolPart: ToolCallMessagePart = {\n type: \"tool-call\",\n toolCallId: entry.toolCallId,\n toolName: entry.toolCallName,\n args: (entry.parsedArgs ?? {}) as any,\n argsText: entry.argsText,\n ...(approval ? { approval } : {}),\n ...(entry.result !== undefined ? { result: entry.result } : {}),\n ...(entry.modelContent !== undefined\n ? { modelContent: entry.modelContent }\n : {}),\n ...(entry.isError !== undefined ? { isError: entry.isError } : {}),\n ...(entry.mcpAppResourceUri\n ? {\n mcp: {\n app: {\n resourceUri: entry.mcpAppResourceUri,\n ...(entry.mcpAppServerId\n ? { serverId: entry.mcpAppServerId }\n : {}),\n },\n },\n }\n : {}),\n ...(entry.parentMessageId ? { parentId: entry.parentMessageId } : {}),\n ...(entry.toolMessageId\n ? { unstable_toolMessageId: entry.toolMessageId }\n : {}),\n } as ToolCallMessagePart & { unstable_toolMessageId?: string };\n pushSnapshotPart(toolPart);\n }\n\n // An anonymous claim promotes the signature's entityId to a wire message\n // id; when that id actually names a text message or the adopted assistant\n // message id (which can also arrive via TOOL_CALL_START.parentMessageId),\n // replaying it as its own record would put two wire records under one id,\n // so such entries are dropped instead — the same outcome the visible\n // path's claim guard produces for a signature that is \"not for this\n // block\". Entries with no materialized part after their anchor trail the\n // assistant record, matching the snapshot path's anchor/after\n // bookkeeping.\n const toolMessageIds = new Set<string>();\n for (const call of this.toolCalls.values()) {\n if (call.toolMessageId) toolMessageIds.add(call.toolMessageId);\n }\n opaqueCandidates.sort((a, b) => a.anchor - b.anchor);\n const publishableOpaqueReasoning = opaqueCandidates\n .filter((entry) => {\n const collides =\n this.textParts.has(entry.id) ||\n entry.id === this.reportedServerMessageId ||\n toolMessageIds.has(entry.id);\n if (collides && !this.loggedDroppedOpaqueIds.has(entry.id)) {\n this.loggedDroppedOpaqueIds.add(entry.id);\n this.logger.debug?.(\n \"[agui] aggregator dropped opaque reasoning signature: id collides with a message id\",\n entry.id,\n );\n }\n return !collides;\n })\n .map(({ anchor, ...entry }) =>\n lastMaterializedIndex < anchor ? { ...entry, after: true } : entry,\n );\n if (publishableOpaqueReasoning.length > 0)\n this.hasEmittedOpaqueReasoning = true;\n // Once an opaque entry has been published this run, the key keeps being\n // emitted (empty when withdrawn) so the namespace merge can retract it.\n const includeOpaque = this.hasEmittedOpaqueReasoning;\n const timing = this.getTiming();\n const metadata = {\n ...(timing ? { timing } : {}),\n ...(this.interrupts || includeOpaque\n ? {\n custom: {\n [AG_UI_METADATA_NAMESPACE]: {\n ...(this.interrupts ? { interrupts: this.interrupts } : {}),\n ...(includeOpaque\n ? { opaqueReasoning: publishableOpaqueReasoning }\n : {}),\n } satisfies AgUiCustomMetadata,\n },\n }\n : {}),\n };\n const result: ChatModelRunResult = {\n content: snapshot,\n ...(this.status ? { status: this.status } : undefined),\n ...(Object.keys(metadata).length > 0 ? { metadata } : undefined),\n };\n this.emitUpdate(result);\n }\n\n private recordFirstToken(): void {\n if (\n this.firstTokenTime === undefined &&\n this.streamStartTime !== undefined\n ) {\n this.firstTokenTime = Date.now() - this.streamStartTime;\n }\n }\n\n private getTiming(): MessageTiming | undefined {\n if (this.streamStartTime === undefined) return undefined;\n\n const now = Date.now();\n const totalStreamTime = now - this.streamStartTime;\n const tokenCount =\n this.totalChunks > 0\n ? Math.ceil(\n Array.from(this.textParts.values()).reduce(\n (sum, p) => sum + p.buffer.length,\n 0,\n ) / 4,\n )\n : undefined;\n const tokensPerSecond =\n tokenCount && totalStreamTime > 0\n ? (tokenCount / totalStreamTime) * 1000\n : undefined;\n\n return {\n streamStartTime: this.streamStartTime,\n ...(this.firstTokenTime !== undefined\n ? { firstTokenTime: this.firstTokenTime }\n : {}),\n totalStreamTime,\n ...(tokenCount !== undefined ? { tokenCount } : {}),\n ...(tokensPerSecond !== undefined ? { tokensPerSecond } : {}),\n totalChunks: this.totalChunks,\n toolCallCount: this.toolCalls.size,\n };\n }\n\n private handleReasoningStart(messageId?: string, isMessageId = false): void {\n if (!this.showThinking) {\n const anchor = this.partOrder.length;\n if (messageId === undefined) {\n this.hiddenActiveReasoning = \"anonymous\";\n this.hiddenAnonymousAnchor = anchor;\n } else {\n this.hiddenReasoningIds.add(messageId);\n this.hiddenBlockAnchors.set(messageId, anchor);\n this.hiddenActiveReasoning = \"identified\";\n }\n return;\n }\n // A reasoning block acts as a boundary: anonymous text arriving after it\n // should be a new part, not appended to any pre-reasoning text.\n this.activeTextMessageId = undefined;\n const key = messageId ?? `__auto-reasoning-${++this.reasoningPartCounter}`;\n // Two different questions: which id may be replayed as a ReasoningMessage.id\n // (only the message-scoped aliases carry one), and which block an unmatched\n // signature may claim (any block opened without an id at all).\n if (messageId === undefined) {\n this.anonymousReasoningKeys.add(key);\n } else if (isMessageId) {\n this.reasoningMessageIds.set(key, messageId);\n }\n if (!this.reasoningParts.has(key)) {\n this.reasoningParts.set(key, \"\");\n this.partOrder.push({ kind: \"reasoning\", key });\n }\n this.activeReasoningKey = key;\n this.emit();\n }\n\n private handleReasoningContent(\n delta: string,\n messageId?: string,\n isMessageId = false,\n ): void {\n if (!delta) return;\n if (!this.showThinking) {\n // Content without a preceding START still names the block (the visible\n // path opens it lazily); register it so a signature can claim it.\n if (this.hiddenActiveReasoning === \"none\") {\n this.handleReasoningStart(messageId, isMessageId);\n }\n return;\n }\n if (!this.activeReasoningKey) {\n // Content arrived without a preceding START — create the slot lazily.\n this.handleReasoningStart(messageId, isMessageId);\n }\n const key = this.activeReasoningKey;\n if (!key) return;\n this.reasoningParts.set(key, (this.reasoningParts.get(key) ?? \"\") + delta);\n this.emit();\n }\n\n private handleReasoningEnd(): void {\n if (!this.showThinking) {\n this.hiddenActiveReasoning = \"none\";\n return;\n }\n this.activeReasoningKey = undefined;\n this.emit();\n }\n}\n\nexport function tryParseJSON(value: string): unknown {\n if (!value) return value;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriber.d.ts","names":[],"sources":["../../../src/runtime/adapter/subscriber.ts"],"mappings":";;;KAMK,YAAY,OAAO;KAEnB;EACH,WAAW;IAAW;;EACtB,2BAA2B;IAAW;;EACtC,6BAA6B;IAAW;;EACxC,yBAAyB;IAAW;;EACpC,2BAA2B;IAAW;;EACtC,wBAAwB;IAAW;;EACnC,sBAAsB;IAAW;;EACjC,mCAAmC;IAAW;;EAC9C,qCAAqC;IAAW;;EAChD,iCAAiC;IAAW;;EAC5C,yBAAyB;IAAW;;EACpC,uBAAuB;IAAW;;EAClC,gCAAgC;IAAW;;EAC3C,kCAAkC;IAAW;;EAC7C,8BAA8B;IAAW;;EACzC,kCAAkC;IAAW;;EAC7C,wBAAwB;IAAW;;EACnC,uBAAuB;IAAW;;EAClC,sBAAsB;IAAW;;EACjC,wBAAwB;IAAW;;EACnC,yBAAyB;IAAW;;EACpC,2BAA2B;IAAW;;EACtC,wBAAwB;IAAW;;EACnC,qBAAqB;IAAW;;EAChC,2BAA2B;IAAW;;EACtC,iBAAiB;IAAW;;EAC5B,cAAc;IAAW;;EACzB,sBAAsB;IAAW;;EACjC;EACA,eAAe;IAAW,OAAO;;;KAiC9B;EACH,UAAU;EACV;EACA,SAAS;EACT,eAAe,OAAO;;cAGX,uBACX,SAAS,sBACR;
|
|
1
|
+
{"version":3,"file":"subscriber.d.ts","names":[],"sources":["../../../src/runtime/adapter/subscriber.ts"],"mappings":";;;KAMK,YAAY,OAAO;KAEnB;EACH,WAAW;IAAW;;EACtB,2BAA2B;IAAW;;EACtC,6BAA6B;IAAW;;EACxC,yBAAyB;IAAW;;EACpC,2BAA2B;IAAW;;EACtC,wBAAwB;IAAW;;EACnC,sBAAsB;IAAW;;EACjC,mCAAmC;IAAW;;EAC9C,qCAAqC;IAAW;;EAChD,iCAAiC;IAAW;;EAC5C,yBAAyB;IAAW;;EACpC,uBAAuB;IAAW;;EAClC,gCAAgC;IAAW;;EAC3C,kCAAkC;IAAW;;EAC7C,8BAA8B;IAAW;;EACzC,kCAAkC;IAAW;;EAC7C,wBAAwB;IAAW;;EACnC,uBAAuB;IAAW;;EAClC,sBAAsB;IAAW;;EACjC,wBAAwB;IAAW;;EACnC,yBAAyB;IAAW;;EACpC,2BAA2B;IAAW;;EACtC,wBAAwB;IAAW;;EACnC,qBAAqB;IAAW;;EAChC,2BAA2B;IAAW;;EACtC,iBAAiB;IAAW;;EAC5B,cAAc;IAAW;;EACzB,sBAAsB;IAAW;;EACjC,mBAAmB;IAAW;;EAC9B;EACA,eAAe;IAAW,OAAO;;;KAiC9B;EACH,UAAU;EACV;EACA,SAAS;EACT,eAAe,OAAO;;cAGX,uBACX,SAAS,sBACR;KAgHS,iBAAiB,kBAAkB"}
|
|
@@ -60,11 +60,20 @@ const createAgUiSubscriber = (options) => {
|
|
|
60
60
|
onCustomEvent: ({ event }) => dispatchIfValid(event, "CUSTOM"),
|
|
61
61
|
onRawEvent: ({ event }) => dispatchIfValid(event, "RAW"),
|
|
62
62
|
onRunFinishedEvent: ({ event }) => {
|
|
63
|
+
if (runFinishedDispatched) return;
|
|
63
64
|
const parsed = ensureEvent(event, "RUN_FINISHED", logger);
|
|
64
65
|
if (!parsed) return;
|
|
65
66
|
runFinishedDispatched = true;
|
|
66
67
|
dispatch(parsed);
|
|
67
68
|
},
|
|
69
|
+
onRunErrorEvent: ({ event }) => {
|
|
70
|
+
const parsed = ensureEvent(event, "RUN_ERROR", logger);
|
|
71
|
+
if (!parsed || parsed.type !== "RUN_ERROR") return;
|
|
72
|
+
runFinishedDispatched = true;
|
|
73
|
+
dispatch(parsed);
|
|
74
|
+
const error = Object.assign(new Error(parsed.message ?? "Run failed"), parsed.code === void 0 ? {} : { code: parsed.code });
|
|
75
|
+
onRunFailed?.(error);
|
|
76
|
+
},
|
|
68
77
|
onRunFinalized: () => {
|
|
69
78
|
if (runFinishedDispatched) return;
|
|
70
79
|
dispatch({
|