@assistant-ui/react-ag-ui 0.0.29 → 0.0.30
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 +41 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/runtime/AgUiThreadRuntimeCore.d.ts +11 -0
- package/dist/runtime/AgUiThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtime/AgUiThreadRuntimeCore.js +185 -12
- package/dist/runtime/AgUiThreadRuntimeCore.js.map +1 -1
- package/dist/runtime/adapter/run-aggregator.d.ts +10 -1
- package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
- package/dist/runtime/adapter/run-aggregator.js +52 -6
- package/dist/runtime/adapter/run-aggregator.js.map +1 -1
- package/dist/runtime/adapter/subscriber.d.ts +5 -0
- package/dist/runtime/adapter/subscriber.d.ts.map +1 -1
- package/dist/runtime/adapter/subscriber.js +55 -36
- package/dist/runtime/adapter/subscriber.js.map +1 -1
- package/dist/runtime/event-parser.d.ts +5 -1
- package/dist/runtime/event-parser.d.ts.map +1 -1
- package/dist/runtime/event-parser.js +48 -2
- package/dist/runtime/event-parser.js.map +1 -1
- package/dist/runtime/types.d.ts +22 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/useAgUiRuntime.d.ts +6 -2
- package/dist/useAgUiRuntime.d.ts.map +1 -1
- package/dist/useAgUiRuntime.js +7 -1
- package/dist/useAgUiRuntime.js.map +1 -1
- package/package.json +4 -5
- package/src/index.ts +5 -0
- package/src/runtime/AgUiThreadRuntimeCore.ts +250 -11
- package/src/runtime/adapter/run-aggregator.ts +67 -9
- package/src/runtime/adapter/subscriber.ts +53 -43
- package/src/runtime/event-parser.ts +64 -3
- package/src/runtime/types.ts +31 -1
- package/src/useAgUiRuntime.ts +23 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAgUiRuntime.js","sourceRoot":"","sources":["../src/useAgUiRuntime.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC1E,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AASlC,OAAO,EAAE,UAAU,EAAE,4BAAyB;
|
|
1
|
+
{"version":3,"file":"useAgUiRuntime.js","sourceRoot":"","sources":["../src/useAgUiRuntime.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react-ag-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.30",
|
|
4
4
|
"description": "AG-UI protocol adapter for assistant-ui",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ag-ui",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"sideEffects": false,
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@ag-ui/client": "^0.0.53",
|
|
33
|
-
"@assistant-ui/core": "^0.2.
|
|
34
|
-
"assistant-stream": "^0.3.
|
|
33
|
+
"@assistant-ui/core": "^0.2.1",
|
|
34
|
+
"assistant-stream": "^0.3.14"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@types/react": "*",
|
|
@@ -50,8 +50,7 @@
|
|
|
50
50
|
"@assistant-ui/x-buildutils": "0.0.7"
|
|
51
51
|
},
|
|
52
52
|
"publishConfig": {
|
|
53
|
-
"access": "public"
|
|
54
|
-
"provenance": true
|
|
53
|
+
"access": "public"
|
|
55
54
|
},
|
|
56
55
|
"homepage": "https://www.assistant-ui.com/",
|
|
57
56
|
"repository": {
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export { useAgUiRuntime } from "./useAgUiRuntime";
|
|
2
|
+
export type { AgUiAssistantRuntime } from "./useAgUiRuntime";
|
|
2
3
|
export type {
|
|
4
|
+
AgUiInterrupt,
|
|
5
|
+
AgUiInterruptReason,
|
|
6
|
+
AgUiResumeEntry,
|
|
7
|
+
AgUiRunFinishedOutcome,
|
|
3
8
|
UseAgUiRuntimeOptions,
|
|
4
9
|
UseAgUiRuntimeAdapters,
|
|
5
10
|
UseAgUiThreadListAdapter,
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
generateId,
|
|
5
|
+
generateOptimisticId,
|
|
6
|
+
isOptimisticId,
|
|
7
|
+
fromThreadMessageLike,
|
|
8
|
+
} from "@assistant-ui/core/internal";
|
|
4
9
|
import type {
|
|
5
10
|
AddToolResultOptions,
|
|
6
11
|
AppendMessage,
|
|
@@ -13,9 +18,13 @@ import type {
|
|
|
13
18
|
} from "@assistant-ui/core";
|
|
14
19
|
import type { HttpAgent } from "@ag-ui/client";
|
|
15
20
|
import type { Logger } from "./logger";
|
|
16
|
-
import type { AgUiEvent } from "./types";
|
|
21
|
+
import type { AgUiEvent, AgUiInterrupt, AgUiResumeEntry } from "./types";
|
|
17
22
|
import type { ReadonlyJSONValue } from "assistant-stream/utils";
|
|
18
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
AG_UI_METADATA_NAMESPACE,
|
|
25
|
+
type AgUiCustomMetadata,
|
|
26
|
+
RunAggregator,
|
|
27
|
+
} from "./adapter/run-aggregator";
|
|
19
28
|
import {
|
|
20
29
|
fromAgUiMessages,
|
|
21
30
|
toAgUiMessages,
|
|
@@ -23,6 +32,8 @@ import {
|
|
|
23
32
|
} from "./adapter/conversions";
|
|
24
33
|
import { createAgUiSubscriber } from "./adapter/subscriber";
|
|
25
34
|
|
|
35
|
+
const symbolResumeShim = Symbol("agui-resume-shim");
|
|
36
|
+
|
|
26
37
|
type RunConfig = NonNullable<AppendMessage["runConfig"]>;
|
|
27
38
|
type ResumeRunConfig = {
|
|
28
39
|
parentId: string | null;
|
|
@@ -72,6 +83,7 @@ export class AgUiThreadRuntimeCore {
|
|
|
72
83
|
this.onCancel = options.onCancel;
|
|
73
84
|
this.history = options.history;
|
|
74
85
|
this.notifyUpdate = options.notifyUpdate;
|
|
86
|
+
this.installResumeShim();
|
|
75
87
|
}
|
|
76
88
|
|
|
77
89
|
updateOptions(options: Omit<CoreOptions, "notifyUpdate">) {
|
|
@@ -81,6 +93,7 @@ export class AgUiThreadRuntimeCore {
|
|
|
81
93
|
this.onError = options.onError;
|
|
82
94
|
this.onCancel = options.onCancel;
|
|
83
95
|
this.history = options.history;
|
|
96
|
+
this.installResumeShim();
|
|
84
97
|
}
|
|
85
98
|
|
|
86
99
|
attachRuntime(runtime: AssistantRuntime) {
|
|
@@ -143,6 +156,7 @@ export class AgUiThreadRuntimeCore {
|
|
|
143
156
|
|
|
144
157
|
async append(message: AppendMessage): Promise<void> {
|
|
145
158
|
const startRun = message.startRun ?? message.role === "user";
|
|
159
|
+
if (startRun) this.assertNoPendingInterrupts();
|
|
146
160
|
if (message.sourceId) {
|
|
147
161
|
this.messages = this.messages.filter(
|
|
148
162
|
(entry) => entry.id !== message.sourceId,
|
|
@@ -167,6 +181,7 @@ export class AgUiThreadRuntimeCore {
|
|
|
167
181
|
parentId: string | null,
|
|
168
182
|
config: { runConfig?: RunConfig } = {},
|
|
169
183
|
): Promise<void> {
|
|
184
|
+
this.assertNoPendingInterrupts();
|
|
170
185
|
this.resetHead(parentId);
|
|
171
186
|
this.notifyUpdate();
|
|
172
187
|
await this.startRun(parentId, config.runConfig);
|
|
@@ -178,6 +193,7 @@ export class AgUiThreadRuntimeCore {
|
|
|
178
193
|
}
|
|
179
194
|
|
|
180
195
|
async resume(config: ResumeRunConfig): Promise<void> {
|
|
196
|
+
this.assertNoPendingInterrupts();
|
|
181
197
|
if (config.stream) {
|
|
182
198
|
this.logger.debug?.(
|
|
183
199
|
"[agui] resume stream is not supported, falling back to regular run",
|
|
@@ -189,6 +205,143 @@ export class AgUiThreadRuntimeCore {
|
|
|
189
205
|
);
|
|
190
206
|
}
|
|
191
207
|
|
|
208
|
+
private assertNoPendingInterrupts(): void {
|
|
209
|
+
if (!this.getPendingInterrupts()) return;
|
|
210
|
+
throw new Error(
|
|
211
|
+
"[agui] cannot start a new run while interrupts are pending; resolve them with submitInterruptResponses()",
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
getPendingInterrupts(): {
|
|
216
|
+
messageId: string;
|
|
217
|
+
interrupts: readonly AgUiInterrupt[];
|
|
218
|
+
} | null {
|
|
219
|
+
const assistant = this.messages.findLast((m) => m.role === "assistant") as
|
|
220
|
+
| ThreadAssistantMessage
|
|
221
|
+
| undefined;
|
|
222
|
+
if (
|
|
223
|
+
!assistant ||
|
|
224
|
+
assistant.status?.type !== "requires-action" ||
|
|
225
|
+
assistant.status.reason !== "interrupt"
|
|
226
|
+
) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
const stored = (
|
|
230
|
+
assistant.metadata.custom[AG_UI_METADATA_NAMESPACE] as
|
|
231
|
+
| AgUiCustomMetadata
|
|
232
|
+
| undefined
|
|
233
|
+
)?.interrupts;
|
|
234
|
+
if (!stored?.length) return null;
|
|
235
|
+
return { messageId: assistant.id, interrupts: stored };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async submitInterruptResponses(
|
|
239
|
+
responses: readonly AgUiResumeEntry[],
|
|
240
|
+
): Promise<void> {
|
|
241
|
+
const pending = this.getPendingInterrupts();
|
|
242
|
+
if (!pending) {
|
|
243
|
+
throw new Error(
|
|
244
|
+
"[agui] submitInterruptResponses: no pending interrupts on this thread",
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const responsesById = new Map<string, AgUiResumeEntry>();
|
|
249
|
+
for (const entry of responses) {
|
|
250
|
+
if (!entry || typeof entry.interruptId !== "string") {
|
|
251
|
+
throw new Error(
|
|
252
|
+
"[agui] submitInterruptResponses: every entry must have an interruptId",
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
if (entry.status !== "resolved" && entry.status !== "cancelled") {
|
|
256
|
+
throw new Error(
|
|
257
|
+
`[agui] submitInterruptResponses: invalid status "${entry.status}" for interrupt ${entry.interruptId}`,
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
if (responsesById.has(entry.interruptId)) {
|
|
261
|
+
throw new Error(
|
|
262
|
+
`[agui] submitInterruptResponses: duplicate response for interrupt ${entry.interruptId}`,
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
responsesById.set(entry.interruptId, entry);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const openIds = pending.interrupts.map((i) => i.id);
|
|
269
|
+
const missing = openIds.filter((id) => !responsesById.has(id));
|
|
270
|
+
if (missing.length > 0) {
|
|
271
|
+
throw new Error(
|
|
272
|
+
`[agui] submitInterruptResponses: missing responses for open interrupts: ${missing.join(", ")}`,
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
const known = new Set(openIds);
|
|
276
|
+
const unknownIds = [...responsesById.keys()].filter((id) => !known.has(id));
|
|
277
|
+
if (unknownIds.length > 0) {
|
|
278
|
+
throw new Error(
|
|
279
|
+
`[agui] submitInterruptResponses: unknown interrupt ids: ${unknownIds.join(", ")}`,
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const now = Date.now();
|
|
284
|
+
for (const interrupt of pending.interrupts) {
|
|
285
|
+
if (!interrupt.expiresAt) continue;
|
|
286
|
+
const expiry = new Date(interrupt.expiresAt).getTime();
|
|
287
|
+
if (Number.isNaN(expiry)) {
|
|
288
|
+
throw new Error(
|
|
289
|
+
`[agui] submitInterruptResponses: interrupt ${interrupt.id} has malformed expiresAt "${interrupt.expiresAt}"`,
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
if (expiry <= now) {
|
|
293
|
+
throw new Error(
|
|
294
|
+
`[agui] submitInterruptResponses: interrupt ${interrupt.id} expired at ${interrupt.expiresAt}`,
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const resume: AgUiResumeEntry[] = openIds.map(
|
|
300
|
+
(id) => responsesById.get(id)!,
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
if (this.isRunningFlag) {
|
|
304
|
+
throw new Error(
|
|
305
|
+
"[agui] submitInterruptResponses: a run is already in progress",
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
this.clearPendingInterrupts(pending.messageId);
|
|
310
|
+
await this.startRun(pending.messageId, this.lastRunConfig, resume);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
private clearPendingInterrupts(messageId: string): void {
|
|
314
|
+
let touched = false;
|
|
315
|
+
this.messages = this.messages.map((message) => {
|
|
316
|
+
if (message.id !== messageId || message.role !== "assistant")
|
|
317
|
+
return message;
|
|
318
|
+
const assistant = message as ThreadAssistantMessage;
|
|
319
|
+
if (
|
|
320
|
+
assistant.status?.type !== "requires-action" ||
|
|
321
|
+
assistant.status.reason !== "interrupt"
|
|
322
|
+
) {
|
|
323
|
+
return assistant;
|
|
324
|
+
}
|
|
325
|
+
touched = true;
|
|
326
|
+
const aguiMeta = assistant.metadata.custom[AG_UI_METADATA_NAMESPACE] as
|
|
327
|
+
| AgUiCustomMetadata
|
|
328
|
+
| undefined;
|
|
329
|
+
const { interrupts: _drop, ...restAgui } = aguiMeta ?? {};
|
|
330
|
+
const newCustom = { ...assistant.metadata.custom };
|
|
331
|
+
if (Object.keys(restAgui).length > 0) {
|
|
332
|
+
newCustom[AG_UI_METADATA_NAMESPACE] = restAgui;
|
|
333
|
+
} else {
|
|
334
|
+
delete newCustom[AG_UI_METADATA_NAMESPACE];
|
|
335
|
+
}
|
|
336
|
+
return {
|
|
337
|
+
...assistant,
|
|
338
|
+
status: { type: "complete" as const, reason: "unknown" as const },
|
|
339
|
+
metadata: { ...assistant.metadata, custom: newCustom },
|
|
340
|
+
};
|
|
341
|
+
});
|
|
342
|
+
if (touched) this.notifyUpdate();
|
|
343
|
+
}
|
|
344
|
+
|
|
192
345
|
findMessageIdForToolCall(toolCallId: string): string | undefined {
|
|
193
346
|
let fallbackMessageId: string | undefined;
|
|
194
347
|
for (let index = this.messages.length - 1; index >= 0; index--) {
|
|
@@ -288,6 +441,7 @@ export class AgUiThreadRuntimeCore {
|
|
|
288
441
|
private async startRun(
|
|
289
442
|
parentId: string | null,
|
|
290
443
|
runConfig?: RunConfig,
|
|
444
|
+
resume?: AgUiResumeEntry[],
|
|
291
445
|
): Promise<void> {
|
|
292
446
|
const normalizedRunConfig = runConfig ?? {};
|
|
293
447
|
this.lastRunConfig = normalizedRunConfig;
|
|
@@ -300,6 +454,7 @@ export class AgUiThreadRuntimeCore {
|
|
|
300
454
|
runId,
|
|
301
455
|
normalizedRunConfig,
|
|
302
456
|
historicalMessages,
|
|
457
|
+
resume,
|
|
303
458
|
);
|
|
304
459
|
const assistantParentId = parentId ?? this.messages.at(-1)?.id ?? null;
|
|
305
460
|
let assistantMessageId: string | undefined;
|
|
@@ -314,7 +469,18 @@ export class AgUiThreadRuntimeCore {
|
|
|
314
469
|
const aggregator = new RunAggregator({
|
|
315
470
|
showThinking: this.showThinking,
|
|
316
471
|
logger: this.logger,
|
|
317
|
-
emit: (update) =>
|
|
472
|
+
emit: (update) => {
|
|
473
|
+
const resolved = this.updateAssistantMessage(ensureAssistant(), update);
|
|
474
|
+
if (resolved !== assistantMessageId) {
|
|
475
|
+
assistantMessageId = resolved;
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
onServerMessageId: (serverId) => {
|
|
479
|
+
const placeholder = ensureAssistant();
|
|
480
|
+
if (placeholder === serverId) return;
|
|
481
|
+
this.reassignAssistantId(placeholder, serverId);
|
|
482
|
+
assistantMessageId = serverId;
|
|
483
|
+
},
|
|
318
484
|
});
|
|
319
485
|
const dispatch = (event: AgUiEvent) => this.handleEvent(aggregator, event);
|
|
320
486
|
|
|
@@ -335,6 +501,7 @@ export class AgUiThreadRuntimeCore {
|
|
|
335
501
|
const subscriber = createAgUiSubscriber({
|
|
336
502
|
dispatch,
|
|
337
503
|
runId,
|
|
504
|
+
logger: this.logger,
|
|
338
505
|
onRunFailed: (error) => {
|
|
339
506
|
this.pendingError = error;
|
|
340
507
|
this.onError?.(error);
|
|
@@ -348,6 +515,7 @@ export class AgUiThreadRuntimeCore {
|
|
|
348
515
|
try {
|
|
349
516
|
(this.agent as any).messages = input.messages;
|
|
350
517
|
(this.agent as any).threadId = input.threadId;
|
|
518
|
+
(this.agent as any).state = input.state ?? null;
|
|
351
519
|
} catch {
|
|
352
520
|
// ignore
|
|
353
521
|
}
|
|
@@ -376,6 +544,7 @@ export class AgUiThreadRuntimeCore {
|
|
|
376
544
|
runId: string,
|
|
377
545
|
runConfig: RunConfig | undefined,
|
|
378
546
|
historyMessages: readonly ThreadMessage[] | undefined,
|
|
547
|
+
resume?: AgUiResumeEntry[],
|
|
379
548
|
) {
|
|
380
549
|
const threadId = this.agent.threadId || "main";
|
|
381
550
|
const messages = toAgUiMessages(historyMessages ?? this.messages);
|
|
@@ -394,6 +563,28 @@ export class AgUiThreadRuntimeCore {
|
|
|
394
563
|
...(context?.config ?? {}),
|
|
395
564
|
...(runConfig?.custom ? { runConfig: runConfig.custom } : {}),
|
|
396
565
|
},
|
|
566
|
+
...(resume !== undefined ? { resume } : {}),
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
private installResumeShim(): void {
|
|
571
|
+
const agent = this.agent as any;
|
|
572
|
+
if (agent[symbolResumeShim]) return;
|
|
573
|
+
agent[symbolResumeShim] = true;
|
|
574
|
+
const onInstance = Object.hasOwn(agent, "prepareRunAgentInput");
|
|
575
|
+
const original = onInstance
|
|
576
|
+
? agent.prepareRunAgentInput
|
|
577
|
+
: Object.getPrototypeOf(agent)?.prepareRunAgentInput;
|
|
578
|
+
if (typeof original !== "function") return;
|
|
579
|
+
agent.prepareRunAgentInput = function (
|
|
580
|
+
this: unknown,
|
|
581
|
+
params: { resume?: unknown } | undefined,
|
|
582
|
+
) {
|
|
583
|
+
const input = original.call(this, params);
|
|
584
|
+
if (params?.resume !== undefined && input && typeof input === "object") {
|
|
585
|
+
return { ...(input as object), resume: params.resume };
|
|
586
|
+
}
|
|
587
|
+
return input;
|
|
397
588
|
};
|
|
398
589
|
}
|
|
399
590
|
|
|
@@ -410,7 +601,7 @@ export class AgUiThreadRuntimeCore {
|
|
|
410
601
|
}
|
|
411
602
|
|
|
412
603
|
private insertAssistantPlaceholder(): string {
|
|
413
|
-
const id =
|
|
604
|
+
const id = generateOptimisticId();
|
|
414
605
|
const assistant: ThreadAssistantMessage = {
|
|
415
606
|
id,
|
|
416
607
|
role: "assistant",
|
|
@@ -430,10 +621,43 @@ export class AgUiThreadRuntimeCore {
|
|
|
430
621
|
return id;
|
|
431
622
|
}
|
|
432
623
|
|
|
624
|
+
private reassignAssistantId(oldId: string, newId: string): void {
|
|
625
|
+
if (oldId === newId) return;
|
|
626
|
+
|
|
627
|
+
const collidesWithExisting = this.messages.some((m) => m.id === newId);
|
|
628
|
+
|
|
629
|
+
if (collidesWithExisting) {
|
|
630
|
+
this.logger.debug?.(
|
|
631
|
+
"[agui] reassignAssistantId: server id already present in messages, dropping placeholder",
|
|
632
|
+
{ oldId, newId },
|
|
633
|
+
);
|
|
634
|
+
this.messages = this.messages.filter((m) => m.id !== oldId);
|
|
635
|
+
} else {
|
|
636
|
+
this.messages = this.messages.map((m) =>
|
|
637
|
+
m.id === oldId ? { ...m, id: newId } : m,
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
const pendingParent = this.assistantHistoryParents.get(oldId);
|
|
642
|
+
if (pendingParent !== undefined) {
|
|
643
|
+
this.assistantHistoryParents.delete(oldId);
|
|
644
|
+
if (!this.assistantHistoryParents.has(newId)) {
|
|
645
|
+
this.assistantHistoryParents.set(newId, pendingParent);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (this.recordedHistoryIds.has(oldId)) {
|
|
650
|
+
this.recordedHistoryIds.delete(oldId);
|
|
651
|
+
this.recordedHistoryIds.add(newId);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
this.notifyUpdate();
|
|
655
|
+
}
|
|
656
|
+
|
|
433
657
|
private updateAssistantMessage(
|
|
434
658
|
messageId: string,
|
|
435
659
|
update: ChatModelRunResult,
|
|
436
|
-
) {
|
|
660
|
+
): string {
|
|
437
661
|
let touched = false;
|
|
438
662
|
let latestStatus: MessageStatus | undefined;
|
|
439
663
|
this.messages = this.messages.map((message) => {
|
|
@@ -453,12 +677,22 @@ export class AgUiThreadRuntimeCore {
|
|
|
453
677
|
metadata,
|
|
454
678
|
};
|
|
455
679
|
});
|
|
456
|
-
if (touched)
|
|
680
|
+
if (!touched) return messageId;
|
|
681
|
+
|
|
682
|
+
let resolvedMessageId = messageId;
|
|
683
|
+
const isSettled =
|
|
684
|
+
latestStatus !== undefined && latestStatus.type !== "running";
|
|
685
|
+
if (isSettled && isOptimisticId(messageId)) {
|
|
686
|
+
const stableId = generateId();
|
|
687
|
+
this.reassignAssistantId(messageId, stableId);
|
|
688
|
+
resolvedMessageId = stableId;
|
|
689
|
+
} else {
|
|
457
690
|
this.notifyUpdate();
|
|
458
|
-
if (this.isTerminalStatus(latestStatus)) {
|
|
459
|
-
this.persistAssistantHistory(messageId);
|
|
460
|
-
}
|
|
461
691
|
}
|
|
692
|
+
if (this.isPersistableStatus(latestStatus)) {
|
|
693
|
+
this.persistAssistantHistory(resolvedMessageId);
|
|
694
|
+
}
|
|
695
|
+
return resolvedMessageId;
|
|
462
696
|
}
|
|
463
697
|
|
|
464
698
|
private mergeAssistantMetadata(
|
|
@@ -558,6 +792,11 @@ export class AgUiThreadRuntimeCore {
|
|
|
558
792
|
return status?.type === "complete" || status?.type === "incomplete";
|
|
559
793
|
}
|
|
560
794
|
|
|
795
|
+
private isPersistableStatus(status?: MessageStatus): boolean {
|
|
796
|
+
if (this.isTerminalStatus(status)) return true;
|
|
797
|
+
return status?.type === "requires-action" && status.reason === "interrupt";
|
|
798
|
+
}
|
|
799
|
+
|
|
561
800
|
private recordHistoryEntry(parentId: string | null, message: ThreadMessage) {
|
|
562
801
|
this.appendHistoryItem(parentId, message);
|
|
563
802
|
}
|
|
@@ -576,7 +815,7 @@ export class AgUiThreadRuntimeCore {
|
|
|
576
815
|
if (parentId === undefined) return;
|
|
577
816
|
const message = this.messages.find((m) => m.id === messageId);
|
|
578
817
|
if (!message || message.role !== "assistant") return;
|
|
579
|
-
if (!this.
|
|
818
|
+
if (!this.isPersistableStatus(message.status)) return;
|
|
580
819
|
this.assistantHistoryParents.delete(messageId);
|
|
581
820
|
this.appendHistoryItem(parentId, message);
|
|
582
821
|
}
|
|
@@ -5,9 +5,15 @@ import type {
|
|
|
5
5
|
ThreadAssistantMessagePart,
|
|
6
6
|
ToolCallMessagePart,
|
|
7
7
|
} from "@assistant-ui/core";
|
|
8
|
-
import type { AgUiEvent } from "../types";
|
|
8
|
+
import type { AgUiEvent, AgUiInterrupt } from "../types";
|
|
9
9
|
import type { Logger } from "../logger";
|
|
10
10
|
|
|
11
|
+
export const AG_UI_METADATA_NAMESPACE = "agui";
|
|
12
|
+
|
|
13
|
+
export type AgUiCustomMetadata = {
|
|
14
|
+
interrupts?: AgUiInterrupt[];
|
|
15
|
+
};
|
|
16
|
+
|
|
11
17
|
type Emit = (update: ChatModelRunResult) => void;
|
|
12
18
|
|
|
13
19
|
type ToolCallState = {
|
|
@@ -18,12 +24,14 @@ type ToolCallState = {
|
|
|
18
24
|
result: unknown;
|
|
19
25
|
isError: boolean | undefined;
|
|
20
26
|
parentMessageId?: string;
|
|
27
|
+
toolMessageId?: string;
|
|
21
28
|
};
|
|
22
29
|
|
|
23
30
|
export type RunAggregatorOptions = {
|
|
24
31
|
showThinking: boolean;
|
|
25
32
|
logger: Logger;
|
|
26
33
|
emit: Emit;
|
|
34
|
+
onServerMessageId?: (messageId: string) => void;
|
|
27
35
|
};
|
|
28
36
|
|
|
29
37
|
/**
|
|
@@ -36,8 +44,10 @@ export class RunAggregator {
|
|
|
36
44
|
private readonly emitUpdate: Emit;
|
|
37
45
|
private readonly showThinking: boolean;
|
|
38
46
|
private readonly logger: Logger;
|
|
47
|
+
private readonly onServerMessageId: ((messageId: string) => void) | undefined;
|
|
39
48
|
|
|
40
49
|
private status: ChatModelRunResult["status"] | undefined;
|
|
50
|
+
private interrupts: AgUiInterrupt[] | undefined;
|
|
41
51
|
private readonly textParts = new Map<
|
|
42
52
|
string,
|
|
43
53
|
{ buffer: string; touched: boolean }
|
|
@@ -53,11 +63,13 @@ export class RunAggregator {
|
|
|
53
63
|
)[] = [];
|
|
54
64
|
private hasReasoningPart = false;
|
|
55
65
|
private textPartCounter = 0;
|
|
66
|
+
private serverMessageIdReported = false;
|
|
56
67
|
|
|
57
68
|
constructor(options: RunAggregatorOptions) {
|
|
58
69
|
this.emitUpdate = options.emit;
|
|
59
70
|
this.showThinking = options.showThinking;
|
|
60
71
|
this.logger = options.logger;
|
|
72
|
+
this.onServerMessageId = options.onServerMessageId;
|
|
61
73
|
}
|
|
62
74
|
|
|
63
75
|
handle(event: AgUiEvent): void {
|
|
@@ -71,18 +83,29 @@ export class RunAggregator {
|
|
|
71
83
|
this.hasReasoningPart = false;
|
|
72
84
|
this.textPartCounter = 0;
|
|
73
85
|
this.activeTextMessageId = undefined;
|
|
86
|
+
this.interrupts = undefined;
|
|
87
|
+
this.serverMessageIdReported = false;
|
|
74
88
|
this.status = { type: "running" };
|
|
75
89
|
this.emit();
|
|
76
90
|
break;
|
|
77
91
|
}
|
|
78
92
|
case "RUN_FINISHED": {
|
|
93
|
+
if (event.outcome?.type === "interrupt") {
|
|
94
|
+
this.interrupts = event.outcome.interrupts;
|
|
95
|
+
this.status = { type: "requires-action", reason: "interrupt" };
|
|
96
|
+
this.emit();
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this.interrupts = undefined;
|
|
79
101
|
const hasUnresolvedToolCalls = Array.from(this.toolCalls.values()).some(
|
|
80
102
|
(tc) => tc.result === undefined,
|
|
81
103
|
);
|
|
82
104
|
|
|
83
|
-
this.status =
|
|
84
|
-
|
|
85
|
-
|
|
105
|
+
this.status =
|
|
106
|
+
event.outcome?.type === "success" || !hasUnresolvedToolCalls
|
|
107
|
+
? { type: "complete", reason: "unknown" }
|
|
108
|
+
: { type: "requires-action", reason: "tool-calls" };
|
|
86
109
|
this.emit();
|
|
87
110
|
break;
|
|
88
111
|
}
|
|
@@ -102,6 +125,7 @@ export class RunAggregator {
|
|
|
102
125
|
}
|
|
103
126
|
|
|
104
127
|
case "TEXT_MESSAGE_START": {
|
|
128
|
+
this.reportServerMessageId(event.messageId);
|
|
105
129
|
const id = this.startTextMessage(event.messageId);
|
|
106
130
|
if (id) {
|
|
107
131
|
this.markTextPartTouched(id);
|
|
@@ -111,15 +135,16 @@ export class RunAggregator {
|
|
|
111
135
|
}
|
|
112
136
|
case "TEXT_MESSAGE_CONTENT":
|
|
113
137
|
case "TEXT_MESSAGE_CHUNK": {
|
|
138
|
+
const incomingId = "messageId" in event ? event.messageId : undefined;
|
|
139
|
+
this.reportServerMessageId(incomingId);
|
|
114
140
|
if (!event.delta) break;
|
|
115
|
-
const id = this.resolveTextMessageId(
|
|
116
|
-
"messageId" in event ? event.messageId : undefined,
|
|
117
|
-
);
|
|
141
|
+
const id = this.resolveTextMessageId(incomingId);
|
|
118
142
|
this.appendText(id, event.delta);
|
|
119
143
|
this.emit();
|
|
120
144
|
break;
|
|
121
145
|
}
|
|
122
146
|
case "TEXT_MESSAGE_END": {
|
|
147
|
+
this.reportServerMessageId(event.messageId);
|
|
123
148
|
if (event.messageId && this.activeTextMessageId === event.messageId) {
|
|
124
149
|
this.activeTextMessageId = undefined;
|
|
125
150
|
}
|
|
@@ -145,6 +170,7 @@ export class RunAggregator {
|
|
|
145
170
|
break;
|
|
146
171
|
|
|
147
172
|
case "TOOL_CALL_START": {
|
|
173
|
+
this.reportServerMessageId(event.parentMessageId);
|
|
148
174
|
this.startToolCall(
|
|
149
175
|
event.toolCallId,
|
|
150
176
|
event.toolCallName,
|
|
@@ -155,6 +181,9 @@ export class RunAggregator {
|
|
|
155
181
|
}
|
|
156
182
|
case "TOOL_CALL_ARGS":
|
|
157
183
|
case "TOOL_CALL_CHUNK": {
|
|
184
|
+
if (event.type === "TOOL_CALL_CHUNK") {
|
|
185
|
+
this.reportServerMessageId(event.parentMessageId);
|
|
186
|
+
}
|
|
158
187
|
if (!event.delta) break;
|
|
159
188
|
this.appendToolArgs(event.toolCallId, event.delta);
|
|
160
189
|
this.emit();
|
|
@@ -169,6 +198,7 @@ export class RunAggregator {
|
|
|
169
198
|
event.toolCallId,
|
|
170
199
|
event.content ?? "",
|
|
171
200
|
event.role === "tool" ? false : undefined,
|
|
201
|
+
event.messageId,
|
|
172
202
|
);
|
|
173
203
|
this.emit();
|
|
174
204
|
break;
|
|
@@ -180,6 +210,12 @@ export class RunAggregator {
|
|
|
180
210
|
}
|
|
181
211
|
}
|
|
182
212
|
|
|
213
|
+
private reportServerMessageId(messageId: string | undefined): void {
|
|
214
|
+
if (this.serverMessageIdReported || !messageId) return;
|
|
215
|
+
this.serverMessageIdReported = true;
|
|
216
|
+
this.onServerMessageId?.(messageId);
|
|
217
|
+
}
|
|
218
|
+
|
|
183
219
|
private clearTextParts(): void {
|
|
184
220
|
this.textParts.clear();
|
|
185
221
|
}
|
|
@@ -281,7 +317,12 @@ export class RunAggregator {
|
|
|
281
317
|
}
|
|
282
318
|
}
|
|
283
319
|
|
|
284
|
-
private finishToolCall(
|
|
320
|
+
private finishToolCall(
|
|
321
|
+
id: string,
|
|
322
|
+
content: string,
|
|
323
|
+
isError?: boolean,
|
|
324
|
+
toolMessageId?: string,
|
|
325
|
+
) {
|
|
285
326
|
if (!id) return;
|
|
286
327
|
let entry = this.toolCalls.get(id);
|
|
287
328
|
if (!entry) {
|
|
@@ -304,6 +345,9 @@ export class RunAggregator {
|
|
|
304
345
|
}
|
|
305
346
|
entry.result = this.tryParseJSON(content);
|
|
306
347
|
entry.isError = isError;
|
|
348
|
+
if (toolMessageId) {
|
|
349
|
+
entry.toolMessageId = toolMessageId;
|
|
350
|
+
}
|
|
307
351
|
}
|
|
308
352
|
|
|
309
353
|
private tryParseJSON(value: string): unknown {
|
|
@@ -351,13 +395,27 @@ export class RunAggregator {
|
|
|
351
395
|
...(entry.result !== undefined ? { result: entry.result } : {}),
|
|
352
396
|
...(entry.isError !== undefined ? { isError: entry.isError } : {}),
|
|
353
397
|
...(entry.parentMessageId ? { parentId: entry.parentMessageId } : {}),
|
|
354
|
-
|
|
398
|
+
...(entry.toolMessageId
|
|
399
|
+
? { unstable_toolMessageId: entry.toolMessageId }
|
|
400
|
+
: {}),
|
|
401
|
+
} as ToolCallMessagePart & { unstable_toolMessageId?: string };
|
|
355
402
|
snapshot.push(toolPart);
|
|
356
403
|
}
|
|
357
404
|
|
|
358
405
|
const result: ChatModelRunResult = {
|
|
359
406
|
content: snapshot,
|
|
360
407
|
...(this.status ? { status: this.status } : undefined),
|
|
408
|
+
...(this.interrupts
|
|
409
|
+
? {
|
|
410
|
+
metadata: {
|
|
411
|
+
custom: {
|
|
412
|
+
[AG_UI_METADATA_NAMESPACE]: {
|
|
413
|
+
interrupts: this.interrupts,
|
|
414
|
+
} satisfies AgUiCustomMetadata,
|
|
415
|
+
},
|
|
416
|
+
},
|
|
417
|
+
}
|
|
418
|
+
: undefined),
|
|
361
419
|
};
|
|
362
420
|
this.emitUpdate(result);
|
|
363
421
|
}
|