@assistant-ui/react-ag-ui 0.0.65 → 0.0.67
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/runtime/AgUiThreadRuntimeCore.d.ts +19 -3
- package/dist/runtime/AgUiThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtime/AgUiThreadRuntimeCore.js +193 -39
- package/dist/runtime/AgUiThreadRuntimeCore.js.map +1 -1
- package/dist/runtime/adapter/conversions.d.ts.map +1 -1
- package/dist/runtime/adapter/conversions.js +11 -12
- package/dist/runtime/adapter/conversions.js.map +1 -1
- package/dist/runtime/adapter/run-aggregator.d.ts +4 -16
- package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
- package/dist/runtime/adapter/run-aggregator.js +80 -15
- package/dist/runtime/adapter/run-aggregator.js.map +1 -1
- package/dist/runtime/types.d.ts +22 -5
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js +8 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/useAgUiRuntime.d.ts.map +1 -1
- package/dist/useAgUiRuntime.js +76 -33
- package/dist/useAgUiRuntime.js.map +1 -1
- package/package.json +6 -6
- package/src/runtime/AgUiThreadRuntimeCore.test.ts +380 -6
- package/src/runtime/AgUiThreadRuntimeCore.ts +314 -70
- package/src/runtime/adapter/conversions.content.test.ts +41 -0
- package/src/runtime/adapter/conversions.ts +16 -19
- package/src/runtime/adapter/run-aggregator.reasoning.test.ts +143 -0
- package/src/runtime/adapter/run-aggregator.ts +128 -33
- package/src/runtime/types.ts +25 -5
- package/src/useAgUiRuntime.external-store.test.tsx +51 -0
- package/src/useAgUiRuntime.thread-switch.test.tsx +587 -3
- package/src/useAgUiRuntime.ts +98 -44
|
@@ -20,7 +20,7 @@ type CoreOptions = {
|
|
|
20
20
|
onError?: (error: Error) => void;
|
|
21
21
|
onCancel?: () => void;
|
|
22
22
|
history?: ThreadHistoryAdapter;
|
|
23
|
-
|
|
23
|
+
isThreadSwitching?: () => boolean;
|
|
24
24
|
};
|
|
25
25
|
export declare class AgUiThreadRuntimeCore {
|
|
26
26
|
private agent;
|
|
@@ -30,7 +30,9 @@ export declare class AgUiThreadRuntimeCore {
|
|
|
30
30
|
private autoCancelPendingToolCalls;
|
|
31
31
|
private onError;
|
|
32
32
|
private onCancel;
|
|
33
|
-
private readonly
|
|
33
|
+
private readonly listeners;
|
|
34
|
+
private snapshot;
|
|
35
|
+
private readonly isThreadSwitching;
|
|
34
36
|
private readonly reportedErrors;
|
|
35
37
|
private runtime;
|
|
36
38
|
private readonly session;
|
|
@@ -45,13 +47,23 @@ export declare class AgUiThreadRuntimeCore {
|
|
|
45
47
|
private readonly persistedHistoryIds;
|
|
46
48
|
private readonly historyWrites;
|
|
47
49
|
private _isLoading;
|
|
50
|
+
private _historyImportPromise;
|
|
51
|
+
private historyMutationGeneration;
|
|
48
52
|
private _loadPromise;
|
|
49
53
|
private _loadRequested;
|
|
50
54
|
private pendingResume;
|
|
51
55
|
private pendingA2uiResumeOwner;
|
|
52
56
|
private pendingA2uiAction;
|
|
53
57
|
constructor(options: CoreOptions);
|
|
54
|
-
|
|
58
|
+
subscribe: (listener: () => void) => (() => void);
|
|
59
|
+
getSnapshot: () => {
|
|
60
|
+
isLoading: boolean;
|
|
61
|
+
isRunning: boolean;
|
|
62
|
+
messageRepository: ExportedMessageRepository;
|
|
63
|
+
state: ReadonlyJSONValue | undefined;
|
|
64
|
+
};
|
|
65
|
+
private publishUpdate;
|
|
66
|
+
updateOptions(options: CoreOptions): void;
|
|
55
67
|
attachRuntime(runtime: AssistantRuntime): void;
|
|
56
68
|
detachRuntime(): void;
|
|
57
69
|
getMessages(): readonly ThreadMessage[];
|
|
@@ -60,6 +72,8 @@ export declare class AgUiThreadRuntimeCore {
|
|
|
60
72
|
isRunning(): boolean;
|
|
61
73
|
get isLoading(): boolean;
|
|
62
74
|
__internal_load(): Promise<void>;
|
|
75
|
+
private waitForHistoryImport;
|
|
76
|
+
private deferUntilHistoryImported;
|
|
63
77
|
append(message: AppendMessage): Promise<void>;
|
|
64
78
|
appendVoiceTranscript(message: ThreadMessage): void;
|
|
65
79
|
private maybeAutoCancelPendingToolCalls;
|
|
@@ -142,6 +156,8 @@ export declare class AgUiThreadRuntimeCore {
|
|
|
142
156
|
private updateAssistantMessage;
|
|
143
157
|
private preserveToolResults;
|
|
144
158
|
private preserveToolInteractions;
|
|
159
|
+
private mergeSnapshotAssistantContent;
|
|
160
|
+
private reconcileSnapshotNestedContent;
|
|
145
161
|
private mergeAssistantMetadata;
|
|
146
162
|
private handleEvent;
|
|
147
163
|
private updateActiveAssistantState;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgUiThreadRuntimeCore.d.ts","sourceRoot":"","sources":["../../src/runtime/AgUiThreadRuntimeCore.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,yBAAyB,EAEzB,4BAA4B,EAE5B,oBAAoB,EACpB,aAAa,EAEb,wBAAwB,EACzB,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,KAAK,EACV,aAAa,EAId,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAiB;AAEvC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"AgUiThreadRuntimeCore.d.ts","sourceRoot":"","sources":["../../src/runtime/AgUiThreadRuntimeCore.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { readMcpAppResourceUri } from "./mcp-tool-result.js";
|
|
3
|
+
import { AG_UI_METADATA_NAMESPACE } from "./types.js";
|
|
3
4
|
import { buildToolApprovalResume, projectAgUiToolApprovals, withSettledToolApprovals, withToolApprovalDecision } from "./adapter/tool-approval.js";
|
|
4
|
-
import {
|
|
5
|
+
import { RunAggregator, isPlainObject, tryParseJSON } from "./adapter/run-aggregator.js";
|
|
5
6
|
import { fromAgUiMessages, toAgUiMessages, toAgUiTools } from "./adapter/conversions.js";
|
|
6
7
|
import { createAgUiSubscriber } from "./adapter/subscriber.js";
|
|
7
8
|
import { fromThreadMessageLike, generateId, isMcpAppUri } from "@assistant-ui/core";
|
|
@@ -12,6 +13,7 @@ const optimisticPrefix = "__optimistic__";
|
|
|
12
13
|
const generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
|
|
13
14
|
const isOptimisticId = (id) => id.startsWith(optimisticPrefix);
|
|
14
15
|
const isResolvedToolCall = (part) => part.type === "tool-call" && "result" in part && part.result !== void 0;
|
|
16
|
+
const isActivityPart = (part) => part.type === "data" && part.name.startsWith("agui-activity/");
|
|
15
17
|
const FALLBACK_USER_STATUS = {
|
|
16
18
|
type: "complete",
|
|
17
19
|
reason: "unknown"
|
|
@@ -40,7 +42,9 @@ var AgUiThreadRuntimeCore = class {
|
|
|
40
42
|
autoCancelPendingToolCalls;
|
|
41
43
|
onError;
|
|
42
44
|
onCancel;
|
|
43
|
-
|
|
45
|
+
listeners = /* @__PURE__ */ new Set();
|
|
46
|
+
snapshot;
|
|
47
|
+
isThreadSwitching;
|
|
44
48
|
reportedErrors = /* @__PURE__ */ new WeakSet();
|
|
45
49
|
runtime;
|
|
46
50
|
session = createMessageRepositorySession({ decorateExport: (exported, repository) => {
|
|
@@ -68,6 +72,8 @@ var AgUiThreadRuntimeCore = class {
|
|
|
68
72
|
persistedHistoryIds = /* @__PURE__ */ new Set();
|
|
69
73
|
historyWrites = /* @__PURE__ */ new Map();
|
|
70
74
|
_isLoading = false;
|
|
75
|
+
_historyImportPromise;
|
|
76
|
+
historyMutationGeneration = 0;
|
|
71
77
|
_loadPromise;
|
|
72
78
|
_loadRequested = false;
|
|
73
79
|
pendingResume = null;
|
|
@@ -82,7 +88,21 @@ var AgUiThreadRuntimeCore = class {
|
|
|
82
88
|
this.onError = options.onError;
|
|
83
89
|
this.onCancel = options.onCancel;
|
|
84
90
|
this.history = options.history;
|
|
85
|
-
this.
|
|
91
|
+
this.isThreadSwitching = options.isThreadSwitching;
|
|
92
|
+
}
|
|
93
|
+
subscribe = (listener) => {
|
|
94
|
+
this.listeners.add(listener);
|
|
95
|
+
return () => this.listeners.delete(listener);
|
|
96
|
+
};
|
|
97
|
+
getSnapshot = () => this.snapshot ??= {
|
|
98
|
+
isLoading: this._isLoading,
|
|
99
|
+
isRunning: this.isRunningFlag,
|
|
100
|
+
messageRepository: this.session.export(),
|
|
101
|
+
state: this.stateSnapshot
|
|
102
|
+
};
|
|
103
|
+
publishUpdate() {
|
|
104
|
+
this.snapshot = void 0;
|
|
105
|
+
for (const listener of this.listeners) listener();
|
|
86
106
|
}
|
|
87
107
|
updateOptions(options) {
|
|
88
108
|
this.agent = options.agent;
|
|
@@ -124,18 +144,25 @@ var AgUiThreadRuntimeCore = class {
|
|
|
124
144
|
this._loadRequested = true;
|
|
125
145
|
if (this._loadPromise) return this._loadPromise;
|
|
126
146
|
if (!this.history) return Promise.resolve();
|
|
127
|
-
const promise = this.history.load()
|
|
128
|
-
this._isLoading = true;
|
|
129
|
-
this._loadPromise = promise.then(async (repo) => {
|
|
147
|
+
const promise = this.history.load().then((repo) => {
|
|
130
148
|
if (!repo) return;
|
|
131
149
|
this.session.applyExternalMessageRepository(repo);
|
|
132
150
|
this.assistantHistoryParents.clear();
|
|
133
151
|
this.snapshotHistoryIds.clear();
|
|
134
152
|
this.persistedHistoryIds.clear();
|
|
135
153
|
for (const { message } of repo.messages) this.persistedHistoryIds.add(message.id);
|
|
136
|
-
this.
|
|
154
|
+
this.publishUpdate();
|
|
137
155
|
if (repo.state !== void 0) this.loadExternalState(repo.state);
|
|
138
|
-
|
|
156
|
+
return repo;
|
|
157
|
+
});
|
|
158
|
+
this._isLoading = true;
|
|
159
|
+
this._historyImportPromise = promise.then(() => {
|
|
160
|
+
this._historyImportPromise = void 0;
|
|
161
|
+
}, () => {
|
|
162
|
+
this._historyImportPromise = void 0;
|
|
163
|
+
});
|
|
164
|
+
this._loadPromise = promise.then(async (repo) => {
|
|
165
|
+
if (repo?.unstable_resume) {
|
|
139
166
|
const parentId = repo.headId ?? this.session.headId;
|
|
140
167
|
const resumeStream = this.history?.resume?.bind(this.history);
|
|
141
168
|
await this.startRun(parentId, this.lastRunConfig, void 0, resumeStream);
|
|
@@ -145,12 +172,43 @@ var AgUiThreadRuntimeCore = class {
|
|
|
145
172
|
this.reportError(error);
|
|
146
173
|
}).finally(() => {
|
|
147
174
|
this._isLoading = false;
|
|
148
|
-
this.
|
|
175
|
+
this.publishUpdate();
|
|
149
176
|
});
|
|
150
|
-
this.
|
|
177
|
+
this.publishUpdate();
|
|
151
178
|
return this._loadPromise;
|
|
152
179
|
}
|
|
180
|
+
waitForHistoryImport() {
|
|
181
|
+
const historyImport = this._historyImportPromise;
|
|
182
|
+
if (!historyImport) return void 0;
|
|
183
|
+
const generation = this.historyMutationGeneration;
|
|
184
|
+
return historyImport.then(() => generation === this.historyMutationGeneration && !this.isThreadSwitching?.());
|
|
185
|
+
}
|
|
186
|
+
deferUntilHistoryImported(callback) {
|
|
187
|
+
const historyImport = this._historyImportPromise;
|
|
188
|
+
if (!historyImport) return false;
|
|
189
|
+
const generation = this.historyMutationGeneration;
|
|
190
|
+
historyImport.then(() => {
|
|
191
|
+
if (generation !== this.historyMutationGeneration || this.isThreadSwitching?.()) return;
|
|
192
|
+
try {
|
|
193
|
+
callback();
|
|
194
|
+
} catch (error) {
|
|
195
|
+
this.reportError(error);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
153
200
|
async append(message) {
|
|
201
|
+
const historyImport = this._historyImportPromise;
|
|
202
|
+
if (historyImport) {
|
|
203
|
+
const wasAtTail = message.parentId === this.session.headId;
|
|
204
|
+
const generation = this.historyMutationGeneration;
|
|
205
|
+
await historyImport;
|
|
206
|
+
if (generation !== this.historyMutationGeneration || this.isThreadSwitching?.()) return;
|
|
207
|
+
if (wasAtTail) message = {
|
|
208
|
+
...message,
|
|
209
|
+
parentId: this.session.headId
|
|
210
|
+
};
|
|
211
|
+
}
|
|
154
212
|
const startRun = message.startRun ?? message.role === "user";
|
|
155
213
|
let ownsThread = true;
|
|
156
214
|
if (startRun) {
|
|
@@ -166,7 +224,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
166
224
|
const parentId = this.session.headId;
|
|
167
225
|
this.session.addOrUpdateMessage(parentId, message);
|
|
168
226
|
this.session.switchToBranch(message.id);
|
|
169
|
-
this.
|
|
227
|
+
this.publishUpdate();
|
|
170
228
|
this.recordHistoryEntry(parentId, message);
|
|
171
229
|
}
|
|
172
230
|
maybeAutoCancelPendingToolCalls() {
|
|
@@ -181,7 +239,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
181
239
|
const parentId = message.parentId === null ? null : message.parentId && this.session.hasMessage(message.parentId) ? message.parentId : this.session.headId;
|
|
182
240
|
this.session.addOrUpdateMessage(parentId, threadMessage);
|
|
183
241
|
this.session.switchToBranch(threadMessage.id);
|
|
184
|
-
this.
|
|
242
|
+
this.publishUpdate();
|
|
185
243
|
this.recordHistoryEntry(parentId, threadMessage);
|
|
186
244
|
return threadMessage.id;
|
|
187
245
|
}
|
|
@@ -189,11 +247,14 @@ var AgUiThreadRuntimeCore = class {
|
|
|
189
247
|
await this.append(message);
|
|
190
248
|
}
|
|
191
249
|
async reload(parentId, config = {}) {
|
|
250
|
+
const historyImport = this.waitForHistoryImport();
|
|
251
|
+
if (historyImport && !await historyImport) return;
|
|
192
252
|
this.assertNoPendingInterrupts();
|
|
193
253
|
this.maybeAutoCancelPendingToolCalls();
|
|
194
254
|
await this.startRun(parentId, config.runConfig);
|
|
195
255
|
}
|
|
196
256
|
async cancel() {
|
|
257
|
+
this.historyMutationGeneration++;
|
|
197
258
|
this.abortActiveRun();
|
|
198
259
|
}
|
|
199
260
|
abortActiveRun() {
|
|
@@ -216,10 +277,14 @@ var AgUiThreadRuntimeCore = class {
|
|
|
216
277
|
return false;
|
|
217
278
|
}
|
|
218
279
|
async resume(config) {
|
|
280
|
+
const historyImport = this.waitForHistoryImport();
|
|
281
|
+
if (historyImport && !await historyImport) return;
|
|
219
282
|
this.assertNoPendingInterrupts();
|
|
220
283
|
await this.startRun(config.parentId, config.runConfig ?? this.lastRunConfig, void 0, config.stream);
|
|
221
284
|
}
|
|
222
285
|
async resumeInFlightRun(messages) {
|
|
286
|
+
const historyImport = this.waitForHistoryImport();
|
|
287
|
+
if (historyImport && !await historyImport) return;
|
|
223
288
|
const resumeStream = this.history?.resume?.bind(this.history);
|
|
224
289
|
if (!resumeStream) {
|
|
225
290
|
const error = /* @__PURE__ */ new Error("[agui] unstable_resume requires a ThreadHistoryAdapter with a resume() method; skipping resume after thread switch");
|
|
@@ -266,6 +331,8 @@ var AgUiThreadRuntimeCore = class {
|
|
|
266
331
|
};
|
|
267
332
|
}
|
|
268
333
|
async submitInterruptResponses(responses) {
|
|
334
|
+
const historyImport = this.waitForHistoryImport();
|
|
335
|
+
if (historyImport && !await historyImport) return;
|
|
269
336
|
const pending = this.getPendingInterrupts();
|
|
270
337
|
if (!pending) throw new Error("[agui] submitInterruptResponses: no pending interrupts on this thread");
|
|
271
338
|
const responsesById = this.collectInterruptResponses("submitInterruptResponses", pending.interrupts, responses);
|
|
@@ -313,6 +380,8 @@ var AgUiThreadRuntimeCore = class {
|
|
|
313
380
|
if (this.isRunningFlag) throw new Error(`[agui] ${method}: a run is already in progress`);
|
|
314
381
|
}
|
|
315
382
|
async respondToToolApproval(options) {
|
|
383
|
+
const historyImport = this.waitForHistoryImport();
|
|
384
|
+
if (historyImport && !await historyImport) return;
|
|
316
385
|
const pending = this.getPendingInterrupts();
|
|
317
386
|
if (!pending) throw new Error("[agui] respondToToolApproval: no pending interrupts on this thread");
|
|
318
387
|
const gatedMessage = this.session.tryGetMessage(pending.messageId)?.message;
|
|
@@ -328,7 +397,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
328
397
|
content
|
|
329
398
|
};
|
|
330
399
|
})) throw new Error(`[agui] respondToToolApproval: approval "${options.approvalId}" is already decided`);
|
|
331
|
-
this.
|
|
400
|
+
this.publishUpdate();
|
|
332
401
|
const assistant = this.session.tryGetMessage(pending.messageId)?.message;
|
|
333
402
|
if (!assistant) return;
|
|
334
403
|
const resume = buildToolApprovalResume(assistant.content, pending.interrupts);
|
|
@@ -336,6 +405,8 @@ var AgUiThreadRuntimeCore = class {
|
|
|
336
405
|
await this.resumeWithResponses(pending.messageId, resume);
|
|
337
406
|
}
|
|
338
407
|
async steerAway(message, responses) {
|
|
408
|
+
const historyImport = this.waitForHistoryImport();
|
|
409
|
+
if (historyImport && !await historyImport) return;
|
|
339
410
|
const pending = this.getPendingInterrupts();
|
|
340
411
|
if (!pending) {
|
|
341
412
|
const pendingTools = this.getPendingToolCalls();
|
|
@@ -429,7 +500,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
429
500
|
custom: newCustom
|
|
430
501
|
}
|
|
431
502
|
};
|
|
432
|
-
})) this.
|
|
503
|
+
})) this.publishUpdate();
|
|
433
504
|
}
|
|
434
505
|
findMessageIdForToolCall(toolCallId) {
|
|
435
506
|
let fallbackMessageId;
|
|
@@ -461,9 +532,10 @@ var AgUiThreadRuntimeCore = class {
|
|
|
461
532
|
...assistant,
|
|
462
533
|
content
|
|
463
534
|
};
|
|
464
|
-
})) this.
|
|
535
|
+
})) this.publishUpdate();
|
|
465
536
|
}
|
|
466
537
|
addToolResult(options) {
|
|
538
|
+
if (this.deferUntilHistoryImported(() => this.addToolResult(options))) return;
|
|
467
539
|
const sessionMessageId = this.session.tryGetMessage(options.messageId) ? options.messageId : this.findMessageIdForToolCall(options.toolCallId);
|
|
468
540
|
if (sessionMessageId === void 0) return;
|
|
469
541
|
if (!this.session.updateMessage(sessionMessageId, (message) => {
|
|
@@ -487,10 +559,12 @@ var AgUiThreadRuntimeCore = class {
|
|
|
487
559
|
content
|
|
488
560
|
};
|
|
489
561
|
})) return;
|
|
490
|
-
this.
|
|
562
|
+
this.publishUpdate();
|
|
491
563
|
this.maybeResumeAfterToolResults(sessionMessageId);
|
|
492
564
|
}
|
|
493
565
|
async recordToolInteraction(options) {
|
|
566
|
+
const historyImport = this.waitForHistoryImport();
|
|
567
|
+
if (historyImport && !await historyImport) return;
|
|
494
568
|
const sessionMessageId = this.session.tryGetMessage(options.messageId) ? options.messageId : this.findMessageIdForToolCall(options.toolCallId);
|
|
495
569
|
if (sessionMessageId === void 0) throw new Error(`[agui] recordToolInteraction: message "${options.messageId}" was not found`);
|
|
496
570
|
const item = this.session.tryGetMessage(sessionMessageId);
|
|
@@ -513,7 +587,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
513
587
|
} : assistant;
|
|
514
588
|
});
|
|
515
589
|
if (!recorded || !updated) throw new Error(`[agui] recordToolInteraction: tool call "${options.toolCallId}" was not found on message "${options.messageId}"`);
|
|
516
|
-
this.
|
|
590
|
+
this.publishUpdate();
|
|
517
591
|
const message = this.session.tryGetMessage(sessionMessageId)?.message;
|
|
518
592
|
const history = this.history;
|
|
519
593
|
if (!message || !history?.update || !this.isPersistableStatus(message.status)) return;
|
|
@@ -523,6 +597,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
523
597
|
}));
|
|
524
598
|
}
|
|
525
599
|
sendA2uiAction(action) {
|
|
600
|
+
if (this.deferUntilHistoryImported(() => this.sendA2uiAction(action))) return;
|
|
526
601
|
this.assertNoPendingInterrupts();
|
|
527
602
|
this.maybeAutoCancelPendingToolCalls();
|
|
528
603
|
const parentId = this.session.headId;
|
|
@@ -571,7 +646,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
571
646
|
reason: "unknown"
|
|
572
647
|
}
|
|
573
648
|
} : current)) return false;
|
|
574
|
-
this.
|
|
649
|
+
this.publishUpdate();
|
|
575
650
|
this.persistAssistantHistory(messageId);
|
|
576
651
|
return true;
|
|
577
652
|
}
|
|
@@ -633,21 +708,22 @@ var AgUiThreadRuntimeCore = class {
|
|
|
633
708
|
for (const { message } of this.getMessageRepository().messages) this.snapshotHistoryIds.add(message.id);
|
|
634
709
|
const resumeTarget = this.pendingResume?.messageId;
|
|
635
710
|
if (resumeTarget !== void 0 && !this.session.getMessages().some((message) => message.id === resumeTarget)) this.pendingResume = null;
|
|
636
|
-
this.
|
|
711
|
+
this.publishUpdate();
|
|
637
712
|
}
|
|
638
713
|
loadExternalState(state) {
|
|
639
714
|
this.stateSnapshot = state;
|
|
640
|
-
this.
|
|
715
|
+
this.publishUpdate();
|
|
641
716
|
}
|
|
642
717
|
setState(next) {
|
|
643
718
|
this.stateSnapshot = typeof next === "function" ? next(this.stateSnapshot) : next;
|
|
644
|
-
this.
|
|
719
|
+
this.publishUpdate();
|
|
645
720
|
}
|
|
646
721
|
resetState() {
|
|
647
722
|
this.stateSnapshot = void 0;
|
|
648
|
-
this.
|
|
723
|
+
this.publishUpdate();
|
|
649
724
|
}
|
|
650
725
|
resetThreadState() {
|
|
726
|
+
this.historyMutationGeneration++;
|
|
651
727
|
const controller = this.abortController;
|
|
652
728
|
const activeRunAgent = this.activeRunAgent;
|
|
653
729
|
this.stateSnapshot = void 0;
|
|
@@ -665,9 +741,10 @@ var AgUiThreadRuntimeCore = class {
|
|
|
665
741
|
} finally {
|
|
666
742
|
controller.abort();
|
|
667
743
|
}
|
|
668
|
-
} else this.
|
|
744
|
+
} else this.publishUpdate();
|
|
669
745
|
}
|
|
670
746
|
async startRun(parentId, runConfig, resume, resumeStream) {
|
|
747
|
+
if (this.isThreadSwitching?.()) return;
|
|
671
748
|
if (!this.supersedeActiveRun()) return;
|
|
672
749
|
const normalizedRunConfig = runConfig ?? {};
|
|
673
750
|
this.lastRunConfig = normalizedRunConfig;
|
|
@@ -924,7 +1001,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
924
1001
|
}
|
|
925
1002
|
setRunning(running) {
|
|
926
1003
|
this.isRunningFlag = running;
|
|
927
|
-
this.
|
|
1004
|
+
this.publishUpdate();
|
|
928
1005
|
}
|
|
929
1006
|
finishRun(controller) {
|
|
930
1007
|
if (this.abortController !== controller) return;
|
|
@@ -950,7 +1027,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
950
1027
|
};
|
|
951
1028
|
this.session.addOrUpdateMessage(parentId ?? this.session.headId, assistant);
|
|
952
1029
|
this.session.switchToBranch(id);
|
|
953
|
-
this.
|
|
1030
|
+
this.publishUpdate();
|
|
954
1031
|
return id;
|
|
955
1032
|
}
|
|
956
1033
|
reassignAssistantId(oldId, newId) {
|
|
@@ -998,7 +1075,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
998
1075
|
}, settle);
|
|
999
1076
|
}
|
|
1000
1077
|
}
|
|
1001
|
-
this.
|
|
1078
|
+
this.publishUpdate();
|
|
1002
1079
|
return !collidesWithExisting;
|
|
1003
1080
|
}
|
|
1004
1081
|
updateAssistantMessage(messageId, update) {
|
|
@@ -1021,7 +1098,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
1021
1098
|
const stableId = generateId();
|
|
1022
1099
|
this.reassignAssistantId(messageId, stableId);
|
|
1023
1100
|
resolvedMessageId = stableId;
|
|
1024
|
-
} else this.
|
|
1101
|
+
} else this.publishUpdate();
|
|
1025
1102
|
if (this.isPersistableStatus(latestStatus)) this.persistAssistantHistory(resolvedMessageId);
|
|
1026
1103
|
this.maybeResumeAfterToolResults(resolvedMessageId);
|
|
1027
1104
|
return resolvedMessageId;
|
|
@@ -1058,6 +1135,77 @@ var AgUiThreadRuntimeCore = class {
|
|
|
1058
1135
|
});
|
|
1059
1136
|
return changed ? content : next;
|
|
1060
1137
|
}
|
|
1138
|
+
mergeSnapshotAssistantContent(previous, next, snapshotHasReasoning, snapshotHasActivity) {
|
|
1139
|
+
const shouldKeep = (part) => part.type === "reasoning" ? this.showThinking && !snapshotHasReasoning : isActivityPart(part) && !snapshotHasActivity;
|
|
1140
|
+
const kept = previous.filter(shouldKeep);
|
|
1141
|
+
const merged = this.reconcileSnapshotNestedContent(previous, this.preserveToolInteractions(previous, next));
|
|
1142
|
+
if (kept.length === 0) return merged;
|
|
1143
|
+
const mergedByType = /* @__PURE__ */ new Map();
|
|
1144
|
+
const mergedTools = /* @__PURE__ */ new Map();
|
|
1145
|
+
for (const [index, part] of merged.entries()) if (part.type === "tool-call") mergedTools.set(part.toolCallId, index);
|
|
1146
|
+
else {
|
|
1147
|
+
const indexes = mergedByType.get(part.type) ?? [];
|
|
1148
|
+
indexes.push(index);
|
|
1149
|
+
mergedByType.set(part.type, indexes);
|
|
1150
|
+
}
|
|
1151
|
+
const previousOrdinals = /* @__PURE__ */ new Map();
|
|
1152
|
+
const insertions = Array.from({ length: merged.length + 1 }, () => []);
|
|
1153
|
+
let predecessorIndex = -1;
|
|
1154
|
+
for (const part of previous) {
|
|
1155
|
+
if (shouldKeep(part)) {
|
|
1156
|
+
insertions[predecessorIndex + 1].push(part);
|
|
1157
|
+
continue;
|
|
1158
|
+
}
|
|
1159
|
+
let matchedIndex;
|
|
1160
|
+
if (part.type === "tool-call") matchedIndex = mergedTools.get(part.toolCallId);
|
|
1161
|
+
else {
|
|
1162
|
+
const ordinal = previousOrdinals.get(part.type) ?? 0;
|
|
1163
|
+
matchedIndex = mergedByType.get(part.type)?.[ordinal];
|
|
1164
|
+
previousOrdinals.set(part.type, ordinal + 1);
|
|
1165
|
+
}
|
|
1166
|
+
if (matchedIndex !== void 0) predecessorIndex = matchedIndex;
|
|
1167
|
+
}
|
|
1168
|
+
const result = [];
|
|
1169
|
+
for (const [index, part] of merged.entries()) result.push(...insertions[index], part);
|
|
1170
|
+
result.push(...insertions[merged.length]);
|
|
1171
|
+
return result;
|
|
1172
|
+
}
|
|
1173
|
+
reconcileSnapshotNestedContent(previous, next) {
|
|
1174
|
+
const nestedIds = /* @__PURE__ */ new Set();
|
|
1175
|
+
for (const part of previous) {
|
|
1176
|
+
if (part.type !== "tool-call" || !part.messages) continue;
|
|
1177
|
+
for (const nested of part.messages) {
|
|
1178
|
+
if (nested.role !== "assistant") continue;
|
|
1179
|
+
for (const call of iterateToolCallParts(nested.content)) nestedIds.add(call.toolCallId);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
const flattened = /* @__PURE__ */ new Map();
|
|
1183
|
+
for (const part of next) if (part.type === "tool-call" && nestedIds.has(part.toolCallId)) flattened.set(part.toolCallId, part);
|
|
1184
|
+
const carried = flattened.size === 0 ? previous : mapToolCallPartsDeep(previous, (part) => {
|
|
1185
|
+
const snapshot = flattened.get(part.toolCallId);
|
|
1186
|
+
if (!snapshot) return part;
|
|
1187
|
+
return {
|
|
1188
|
+
...part,
|
|
1189
|
+
...snapshot.result !== void 0 ? { result: snapshot.result } : {},
|
|
1190
|
+
...snapshot.isError !== void 0 ? { isError: snapshot.isError } : {},
|
|
1191
|
+
...snapshot.artifact !== void 0 ? { artifact: snapshot.artifact } : {}
|
|
1192
|
+
};
|
|
1193
|
+
}).content;
|
|
1194
|
+
const previousCalls = /* @__PURE__ */ new Map();
|
|
1195
|
+
for (const part of carried) {
|
|
1196
|
+
if (part.type !== "tool-call") continue;
|
|
1197
|
+
previousCalls.set(part.toolCallId, part);
|
|
1198
|
+
}
|
|
1199
|
+
return next.flatMap((part) => {
|
|
1200
|
+
if (part.type === "tool-call" && flattened.has(part.toolCallId)) return [];
|
|
1201
|
+
if (part.type !== "tool-call") return [part];
|
|
1202
|
+
const prior = previousCalls.get(part.toolCallId);
|
|
1203
|
+
return prior?.messages === void 0 ? [part] : [{
|
|
1204
|
+
...part,
|
|
1205
|
+
messages: prior.messages
|
|
1206
|
+
}];
|
|
1207
|
+
});
|
|
1208
|
+
}
|
|
1061
1209
|
mergeAssistantMetadata(current, incoming) {
|
|
1062
1210
|
const annotations = incoming.unstable_annotations ? [...current.unstable_annotations, ...incoming.unstable_annotations] : current.unstable_annotations;
|
|
1063
1211
|
const data = incoming.unstable_data ? [...current.unstable_data, ...incoming.unstable_data] : current.unstable_data;
|
|
@@ -1138,7 +1286,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
1138
1286
|
}
|
|
1139
1287
|
};
|
|
1140
1288
|
});
|
|
1141
|
-
this.
|
|
1289
|
+
this.publishUpdate();
|
|
1142
1290
|
}
|
|
1143
1291
|
applyCrossRunToolResult(messageId, event) {
|
|
1144
1292
|
if (!this.session.updateMessage(messageId, (message) => {
|
|
@@ -1176,7 +1324,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
1176
1324
|
content
|
|
1177
1325
|
};
|
|
1178
1326
|
})) return;
|
|
1179
|
-
this.
|
|
1327
|
+
this.publishUpdate();
|
|
1180
1328
|
this.maybeCompleteAfterToolResults(messageId);
|
|
1181
1329
|
}
|
|
1182
1330
|
applyCrossRunActivitySnapshot(messageId, toolCallId, event) {
|
|
@@ -1215,28 +1363,34 @@ var AgUiThreadRuntimeCore = class {
|
|
|
1215
1363
|
content
|
|
1216
1364
|
};
|
|
1217
1365
|
})) return;
|
|
1218
|
-
this.
|
|
1366
|
+
this.publishUpdate();
|
|
1219
1367
|
this.maybeCompleteAfterToolResults(messageId);
|
|
1220
1368
|
}
|
|
1221
1369
|
importMessagesSnapshot(rawMessages, activeAssistantId) {
|
|
1222
1370
|
try {
|
|
1223
|
-
const
|
|
1371
|
+
const activeAssistantItem = activeAssistantId ? this.session.tryGetMessage(activeAssistantId) : void 0;
|
|
1372
|
+
const activeMessage = activeAssistantItem?.message;
|
|
1373
|
+
const activeAssistantParentId = activeAssistantItem?.parentId;
|
|
1224
1374
|
const activeAssistant = activeMessage?.role === "assistant" ? activeMessage : void 0;
|
|
1225
1375
|
const normalized = fromAgUiMessages(rawMessages, { showThinking: this.showThinking });
|
|
1226
1376
|
const converted = [];
|
|
1227
1377
|
for (const message of normalized) try {
|
|
1228
|
-
|
|
1229
|
-
const existing = this.session.tryGetMessage(convertedMessage.id)?.message;
|
|
1230
|
-
if (convertedMessage.role === "assistant" && existing?.role === "assistant") converted.push({
|
|
1231
|
-
...convertedMessage,
|
|
1232
|
-
content: this.preserveToolInteractions(existing.content, convertedMessage.content)
|
|
1233
|
-
});
|
|
1234
|
-
else converted.push(convertedMessage);
|
|
1378
|
+
converted.push(fromThreadMessageLike(message, generateId(), FALLBACK_USER_STATUS));
|
|
1235
1379
|
} catch (error) {
|
|
1236
1380
|
this.logger.error?.("[agui] failed to import message from snapshot", error);
|
|
1237
1381
|
}
|
|
1382
|
+
const snapshotHasReasoning = converted.some((message) => message.role === "assistant" && message.content.some((part) => part.type === "reasoning"));
|
|
1383
|
+
const snapshotHasActivity = converted.some((message) => message.role === "assistant" && message.content.some(isActivityPart));
|
|
1384
|
+
for (let index = 0; index < converted.length; index++) {
|
|
1385
|
+
const convertedMessage = converted[index];
|
|
1386
|
+
const existing = this.session.tryGetMessage(convertedMessage.id)?.message;
|
|
1387
|
+
if (convertedMessage.role === "assistant" && existing?.role === "assistant") converted[index] = {
|
|
1388
|
+
...convertedMessage,
|
|
1389
|
+
content: this.mergeSnapshotAssistantContent(existing.content, convertedMessage.content, snapshotHasReasoning, snapshotHasActivity)
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1238
1392
|
const snapshotContainsActiveAssistant = converted.some((message) => message.id === activeAssistant?.id);
|
|
1239
|
-
const preservesActiveAssistant = activeAssistant !== void 0 && !snapshotContainsActiveAssistant && (activeAssistant.metadata.isOptimistic !== true || converted.at(-1)?.role !== "assistant");
|
|
1393
|
+
const preservesActiveAssistant = activeAssistant !== void 0 && !snapshotContainsActiveAssistant && (activeAssistant.metadata.isOptimistic !== true || converted.at(-1)?.role !== "assistant" || activeAssistantParentId !== void 0 && converted.at(-1)?.id === activeAssistantParentId);
|
|
1240
1394
|
if (preservesActiveAssistant) converted.push(activeAssistant);
|
|
1241
1395
|
this.applyExternalMessages(converted);
|
|
1242
1396
|
if (activeAssistant !== void 0) {
|