@assistant-ui/react-ag-ui 0.0.56 → 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/runtime/AgUiThreadRuntimeCore.d.ts +2 -13
- package/dist/runtime/AgUiThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtime/AgUiThreadRuntimeCore.js +106 -193
- package/dist/runtime/AgUiThreadRuntimeCore.js.map +1 -1
- package/dist/runtime/adapter/conversions.d.ts.map +1 -1
- package/dist/runtime/adapter/conversions.js +20 -14
- package/dist/runtime/adapter/conversions.js.map +1 -1
- package/dist/runtime/adapter/run-aggregator.d.ts +18 -1
- package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
- package/dist/runtime/adapter/run-aggregator.js +130 -41
- package/dist/runtime/adapter/run-aggregator.js.map +1 -1
- package/dist/useAgUiRuntime.js +11 -9
- package/dist/useAgUiRuntime.js.map +1 -1
- package/package.json +8 -8
- package/src/runtime/AgUiThreadRuntimeCore.test.ts +105 -0
- package/src/runtime/AgUiThreadRuntimeCore.ts +152 -261
- package/src/runtime/adapter/conversions.ts +41 -19
- package/src/runtime/adapter/run-aggregator.ts +198 -47
- package/src/useAgUiRuntime.history.test.tsx +76 -0
- package/src/useAgUiRuntime.ts +11 -9
|
@@ -32,8 +32,7 @@ declare class AgUiThreadRuntimeCore {
|
|
|
32
32
|
private readonly notifyUpdate;
|
|
33
33
|
private readonly reportedErrors;
|
|
34
34
|
private runtime;
|
|
35
|
-
private readonly
|
|
36
|
-
private exportedRepository;
|
|
35
|
+
private readonly session;
|
|
37
36
|
private isRunningFlag;
|
|
38
37
|
private abortController;
|
|
39
38
|
private activeRunAgent;
|
|
@@ -47,6 +46,7 @@ declare class AgUiThreadRuntimeCore {
|
|
|
47
46
|
private readonly historyWrites;
|
|
48
47
|
private _isLoading;
|
|
49
48
|
private _loadPromise;
|
|
49
|
+
private _loadRequested;
|
|
50
50
|
private pendingResumeMessageId;
|
|
51
51
|
private pendingA2uiResume;
|
|
52
52
|
private pendingA2uiAction;
|
|
@@ -56,16 +56,6 @@ declare class AgUiThreadRuntimeCore {
|
|
|
56
56
|
detachRuntime(): void;
|
|
57
57
|
getMessages(): readonly ThreadMessage[];
|
|
58
58
|
getMessageRepository(): ExportedMessageRepository;
|
|
59
|
-
private tryGetMessage;
|
|
60
|
-
private tryGetMessages;
|
|
61
|
-
private hasMessage;
|
|
62
|
-
private addOrUpdateMessage;
|
|
63
|
-
private deleteMessage;
|
|
64
|
-
private tryDeleteMessage;
|
|
65
|
-
private switchToBranch;
|
|
66
|
-
private resetRepositoryHead;
|
|
67
|
-
private clearRepository;
|
|
68
|
-
private updateMessage;
|
|
69
59
|
getState(): ReadonlyJSONValue | undefined;
|
|
70
60
|
isRunning(): boolean;
|
|
71
61
|
get isLoading(): boolean;
|
|
@@ -121,7 +111,6 @@ declare class AgUiThreadRuntimeCore {
|
|
|
121
111
|
private maybeCompleteAfterToolResults;
|
|
122
112
|
private startResumeRun;
|
|
123
113
|
applyExternalMessages(messages: readonly ThreadMessage[]): void;
|
|
124
|
-
private applyExternalMessageRepository;
|
|
125
114
|
loadExternalState(state: ReadonlyJSONValue): void;
|
|
126
115
|
setState(next: ReadonlyJSONValue | ((prev: ReadonlyJSONValue | undefined) => ReadonlyJSONValue)): void;
|
|
127
116
|
resetState(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgUiThreadRuntimeCore.d.ts","names":[],"sources":["../../src/runtime/AgUiThreadRuntimeCore.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"AgUiThreadRuntimeCore.d.ts","names":[],"sources":["../../src/runtime/AgUiThreadRuntimeCore.ts"],"mappings":";;;;;;KA8EK,YAAY,YAAY;KACxB,gBACH,SAAS,wBACN,eAAe;KACf;EACH;EACA;EACA,WAAW;EACX,SAAS;;KAGN;EACH,OAAO;EACP,QAAQ;EACR;EACA;EACA,WAAW,OAAO;EAClB;EACA,UAAU;EACV;;cAoCW;UACH;UACA;UACA;UACA;UACA;UACA;mBACS;mBACA;UAET;mBACS;UAgBT;UACA;UAGA;UACA;UACA;UACA;UACA;mBACS;mBACA;mBACA;mBACA;UACT;UACA;UACA;UACA;UACA;UACA;EAEI,YAAA,SAAS;EAYrB,cAAc,SAAS,KAAK;EAsB5B,cAAc,SAAS;EAIvB;EAOA,wBAAwB;EAIxB,wBAAwB;EAIxB,YAAY;EAIZ;MAII;EAIJ,mBAAmB;EAsDb,OAAO,SAAS,gBAAgB;UAW9B;UAQA;EAiBF,KAAK,SAAS,gBAAgB;EAI9B,OACJ,yBACA;IAAU,YAAY;MACrB;EAMG,UAAU;EAcV,OAAO,QAAQ,kBAAkB;EAUjC,kBAAkB,mBAAmB,kBAAkB;UAwBrD;UAOA;EAgBR;IACE;IACA,qBAAqB;;EAavB;IACE;IACA;;EAcI,yBACJ,oBAAoB,oBACnB;;;;;;;UAuCW;;;;;;;;EAed,YAAY;UAYJ;EAwBF,sBACJ,SAAS,+BACR;EAsEG,UACJ,SAAS,qBACT,qBAAqB,oBACpB;UAyCK;UAkBA;UAiCA;UA0BA;EAmCR,yBAAyB;UAkBjB;EAiBR,cAAc,SAAS;EAyBvB,eAAe,QAAQ;UA4Bf;UAYA;UA6BA;EAUR,sBAAsB,mBAAmB;EAkDzC,kBAAkB,OAAO;EAKzB,SACE,MACI,sBACE,MAAM,kCAAkC;EAOhD;UAKc;UAyPA;UA2DN;UAkCA;UAqBA;UAKA;UAQA;UAyBA;UAkEA;UAiDA;UA4BA;UA6BA;UAgEA;UA2EA;UA8DA;UAuDA;UAQA;UAIA;UAKA;UAMA;UAQA;UAsDA;UAqBA"}
|
|
@@ -5,7 +5,7 @@ import { AG_UI_METADATA_NAMESPACE, RunAggregator, isPlainObject, tryParseJSON }
|
|
|
5
5
|
import { fromAgUiMessages, toAgUiMessages, toAgUiTools } from "./adapter/conversions.js";
|
|
6
6
|
import { createAgUiSubscriber } from "./adapter/subscriber.js";
|
|
7
7
|
import { fromThreadMessageLike, generateId, isMcpAppUri } from "@assistant-ui/core";
|
|
8
|
-
import {
|
|
8
|
+
import { createMessageRepositorySession, invokeUserCallback } from "@assistant-ui/core/internal";
|
|
9
9
|
import jsonpatch from "fast-json-patch";
|
|
10
10
|
//#region src/runtime/AgUiThreadRuntimeCore.ts
|
|
11
11
|
const optimisticPrefix = "__optimistic__";
|
|
@@ -17,19 +17,8 @@ const FALLBACK_USER_STATUS = {
|
|
|
17
17
|
type: "complete",
|
|
18
18
|
reason: "unknown"
|
|
19
19
|
};
|
|
20
|
-
const reportCallbackError = (name, error) => {
|
|
21
|
-
console.error(`[react-ag-ui] ${name} callback threw an error`, error);
|
|
22
|
-
};
|
|
23
20
|
const invokeRuntimeCallback = (name, callback, ...args) => {
|
|
24
|
-
|
|
25
|
-
try {
|
|
26
|
-
const result = callback(...args);
|
|
27
|
-
if (result !== null && (typeof result === "object" || typeof result === "function") && "then" in result && typeof result.then === "function") Promise.resolve(result).catch((error) => {
|
|
28
|
-
reportCallbackError(name, error);
|
|
29
|
-
});
|
|
30
|
-
} catch (error) {
|
|
31
|
-
reportCallbackError(name, error);
|
|
32
|
-
}
|
|
21
|
+
invokeUserCallback("react-ag-ui", name, callback, ...args);
|
|
33
22
|
};
|
|
34
23
|
const mergeAgUiNamespace = (current, incoming) => {
|
|
35
24
|
const merged = {
|
|
@@ -54,8 +43,20 @@ var AgUiThreadRuntimeCore = class {
|
|
|
54
43
|
notifyUpdate;
|
|
55
44
|
reportedErrors = /* @__PURE__ */ new WeakSet();
|
|
56
45
|
runtime;
|
|
57
|
-
|
|
58
|
-
|
|
46
|
+
session = createMessageRepositorySession({ decorateExport: (exported, repository) => {
|
|
47
|
+
let parentId = null;
|
|
48
|
+
for (const message of repository.getMessages()) {
|
|
49
|
+
if (message.metadata.isOptimistic) exported.messages.push({
|
|
50
|
+
parentId,
|
|
51
|
+
message
|
|
52
|
+
});
|
|
53
|
+
parentId = message.id;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
...exported,
|
|
57
|
+
headId: repository.headId
|
|
58
|
+
};
|
|
59
|
+
} });
|
|
59
60
|
isRunningFlag = false;
|
|
60
61
|
abortController = null;
|
|
61
62
|
activeRunAgent = null;
|
|
@@ -69,6 +70,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
69
70
|
historyWrites = /* @__PURE__ */ new Map();
|
|
70
71
|
_isLoading = false;
|
|
71
72
|
_loadPromise;
|
|
73
|
+
_loadRequested = false;
|
|
72
74
|
pendingResumeMessageId = null;
|
|
73
75
|
pendingA2uiResume = false;
|
|
74
76
|
pendingA2uiAction;
|
|
@@ -90,8 +92,10 @@ var AgUiThreadRuntimeCore = class {
|
|
|
90
92
|
this.autoCancelPendingToolCalls = options.autoCancelPendingToolCalls;
|
|
91
93
|
this.onError = options.onError;
|
|
92
94
|
this.onCancel = options.onCancel;
|
|
95
|
+
const previousHistory = this.history;
|
|
93
96
|
this.history = options.history;
|
|
94
97
|
this.installResumeShim();
|
|
98
|
+
if (this._loadRequested && !this._loadPromise && !previousHistory && options.history && this.session.getMessages().length === 0) this.__internal_load();
|
|
95
99
|
}
|
|
96
100
|
attachRuntime(runtime) {
|
|
97
101
|
this.runtime = runtime;
|
|
@@ -103,74 +107,10 @@ var AgUiThreadRuntimeCore = class {
|
|
|
103
107
|
});
|
|
104
108
|
}
|
|
105
109
|
getMessages() {
|
|
106
|
-
return this.
|
|
110
|
+
return this.session.getMessages();
|
|
107
111
|
}
|
|
108
112
|
getMessageRepository() {
|
|
109
|
-
|
|
110
|
-
const exportedRepository = this.repository.export();
|
|
111
|
-
let parentId = null;
|
|
112
|
-
for (const message of this.repository.getMessages()) {
|
|
113
|
-
if (message.metadata.isOptimistic) exportedRepository.messages.push({
|
|
114
|
-
parentId,
|
|
115
|
-
message
|
|
116
|
-
});
|
|
117
|
-
parentId = message.id;
|
|
118
|
-
}
|
|
119
|
-
this.exportedRepository = {
|
|
120
|
-
...exportedRepository,
|
|
121
|
-
headId: this.repository.headId
|
|
122
|
-
};
|
|
123
|
-
return this.exportedRepository;
|
|
124
|
-
}
|
|
125
|
-
tryGetMessage(messageId) {
|
|
126
|
-
try {
|
|
127
|
-
return this.repository.getMessage(messageId);
|
|
128
|
-
} catch {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
tryGetMessages(messageId) {
|
|
133
|
-
try {
|
|
134
|
-
return this.repository.getMessages(messageId);
|
|
135
|
-
} catch {
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
hasMessage(messageId) {
|
|
140
|
-
return this.tryGetMessage(messageId) !== void 0;
|
|
141
|
-
}
|
|
142
|
-
addOrUpdateMessage(parentId, message) {
|
|
143
|
-
this.repository.addOrUpdateMessage(parentId, message);
|
|
144
|
-
this.exportedRepository = void 0;
|
|
145
|
-
}
|
|
146
|
-
deleteMessage(messageId, replacementId) {
|
|
147
|
-
this.repository.deleteMessage(messageId, replacementId);
|
|
148
|
-
this.exportedRepository = void 0;
|
|
149
|
-
}
|
|
150
|
-
tryDeleteMessage(messageId) {
|
|
151
|
-
if (!this.hasMessage(messageId)) return false;
|
|
152
|
-
this.deleteMessage(messageId);
|
|
153
|
-
return true;
|
|
154
|
-
}
|
|
155
|
-
switchToBranch(messageId) {
|
|
156
|
-
this.repository.switchToBranch(messageId);
|
|
157
|
-
this.exportedRepository = void 0;
|
|
158
|
-
}
|
|
159
|
-
resetRepositoryHead(messageId) {
|
|
160
|
-
this.repository.resetHead(messageId);
|
|
161
|
-
this.exportedRepository = void 0;
|
|
162
|
-
}
|
|
163
|
-
clearRepository() {
|
|
164
|
-
this.repository.clear();
|
|
165
|
-
this.exportedRepository = void 0;
|
|
166
|
-
}
|
|
167
|
-
updateMessage(messageId, updater) {
|
|
168
|
-
const item = this.tryGetMessage(messageId);
|
|
169
|
-
if (!item) return false;
|
|
170
|
-
const message = updater(item.message);
|
|
171
|
-
if (message === item.message) return false;
|
|
172
|
-
this.addOrUpdateMessage(item.parentId, message);
|
|
173
|
-
return true;
|
|
113
|
+
return this.session.export();
|
|
174
114
|
}
|
|
175
115
|
getState() {
|
|
176
116
|
return this.stateSnapshot;
|
|
@@ -182,15 +122,22 @@ var AgUiThreadRuntimeCore = class {
|
|
|
182
122
|
return this._isLoading;
|
|
183
123
|
}
|
|
184
124
|
__internal_load() {
|
|
125
|
+
this._loadRequested = true;
|
|
185
126
|
if (this._loadPromise) return this._loadPromise;
|
|
186
|
-
|
|
127
|
+
if (!this.history) return Promise.resolve();
|
|
128
|
+
const promise = this.history.load();
|
|
187
129
|
this._isLoading = true;
|
|
188
130
|
this._loadPromise = promise.then(async (repo) => {
|
|
189
131
|
if (!repo) return;
|
|
190
|
-
this.applyExternalMessageRepository(repo);
|
|
132
|
+
this.session.applyExternalMessageRepository(repo);
|
|
133
|
+
this.assistantHistoryParents.clear();
|
|
134
|
+
this.snapshotHistoryIds.clear();
|
|
135
|
+
this.persistedHistoryIds.clear();
|
|
136
|
+
for (const { message } of repo.messages) this.persistedHistoryIds.add(message.id);
|
|
137
|
+
this.notifyUpdate();
|
|
191
138
|
if (repo.state !== void 0) this.loadExternalState(repo.state);
|
|
192
139
|
if (repo.unstable_resume) {
|
|
193
|
-
const parentId = repo.headId ?? this.
|
|
140
|
+
const parentId = repo.headId ?? this.session.headId;
|
|
194
141
|
const resumeStream = this.history?.resume?.bind(this.history);
|
|
195
142
|
await this.startRun(parentId, this.lastRunConfig, void 0, resumeStream);
|
|
196
143
|
}
|
|
@@ -222,11 +169,11 @@ var AgUiThreadRuntimeCore = class {
|
|
|
222
169
|
this.maybeCompleteAfterToolResults(pending.messageId);
|
|
223
170
|
}
|
|
224
171
|
appendEntry(message) {
|
|
225
|
-
if (message.sourceId) this.tryDeleteMessage(message.sourceId);
|
|
172
|
+
if (message.sourceId) this.session.tryDeleteMessage(message.sourceId);
|
|
226
173
|
const threadMessage = this.toThreadMessage(message);
|
|
227
|
-
const parentId = message.parentId === null ? null : message.parentId && this.hasMessage(message.parentId) ? message.parentId : this.
|
|
228
|
-
this.addOrUpdateMessage(parentId, threadMessage);
|
|
229
|
-
this.switchToBranch(threadMessage.id);
|
|
174
|
+
const parentId = message.parentId === null ? null : message.parentId && this.session.hasMessage(message.parentId) ? message.parentId : this.session.headId;
|
|
175
|
+
this.session.addOrUpdateMessage(parentId, threadMessage);
|
|
176
|
+
this.session.switchToBranch(threadMessage.id);
|
|
230
177
|
this.notifyUpdate();
|
|
231
178
|
this.recordHistoryEntry(parentId, threadMessage);
|
|
232
179
|
return threadMessage.id;
|
|
@@ -345,10 +292,10 @@ var AgUiThreadRuntimeCore = class {
|
|
|
345
292
|
async respondToToolApproval(options) {
|
|
346
293
|
const pending = this.getPendingInterrupts();
|
|
347
294
|
if (!pending) throw new Error("[agui] respondToToolApproval: no pending interrupts on this thread");
|
|
348
|
-
const gatedMessage = this.tryGetMessage(pending.messageId)?.message;
|
|
295
|
+
const gatedMessage = this.session.tryGetMessage(pending.messageId)?.message;
|
|
349
296
|
if (![...projectAgUiToolApprovals(pending.interrupts, new Set((gatedMessage?.content ?? []).filter((part) => part.type === "tool-call").map((part) => part.toolCallId))).values()].some((approval) => approval.id === options.approvalId)) throw new Error(`[agui] respondToToolApproval: no pending tool-call interrupt for approval id "${options.approvalId}"`);
|
|
350
297
|
this.assertInterruptsAnswerable("respondToToolApproval", pending.interrupts);
|
|
351
|
-
if (!this.updateMessage(pending.messageId, (message) => {
|
|
298
|
+
if (!this.session.updateMessage(pending.messageId, (message) => {
|
|
352
299
|
if (message.role !== "assistant") return message;
|
|
353
300
|
const assistant = message;
|
|
354
301
|
const content = withToolApprovalDecision(assistant.content, options);
|
|
@@ -359,7 +306,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
359
306
|
};
|
|
360
307
|
})) throw new Error(`[agui] respondToToolApproval: approval "${options.approvalId}" is already decided`);
|
|
361
308
|
this.notifyUpdate();
|
|
362
|
-
const assistant = this.tryGetMessage(pending.messageId)?.message;
|
|
309
|
+
const assistant = this.session.tryGetMessage(pending.messageId)?.message;
|
|
363
310
|
if (!assistant) return;
|
|
364
311
|
const resume = buildToolApprovalResume(assistant.content, pending.interrupts);
|
|
365
312
|
if (!resume) return;
|
|
@@ -412,7 +359,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
412
359
|
toAppendMessage(message) {
|
|
413
360
|
if (typeof message === "string") return {
|
|
414
361
|
createdAt: /* @__PURE__ */ new Date(),
|
|
415
|
-
parentId: this.
|
|
362
|
+
parentId: this.session.headId,
|
|
416
363
|
sourceId: null,
|
|
417
364
|
runConfig: {},
|
|
418
365
|
role: "user",
|
|
@@ -425,7 +372,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
425
372
|
};
|
|
426
373
|
return {
|
|
427
374
|
createdAt: message.createdAt ?? /* @__PURE__ */ new Date(),
|
|
428
|
-
parentId: message.parentId ?? this.
|
|
375
|
+
parentId: message.parentId ?? this.session.headId,
|
|
429
376
|
sourceId: message.sourceId ?? null,
|
|
430
377
|
role: message.role ?? "user",
|
|
431
378
|
content: message.content,
|
|
@@ -436,7 +383,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
436
383
|
};
|
|
437
384
|
}
|
|
438
385
|
clearPendingInterrupts(messageId, resume) {
|
|
439
|
-
if (this.updateMessage(messageId, (message) => {
|
|
386
|
+
if (this.session.updateMessage(messageId, (message) => {
|
|
440
387
|
if (message.role !== "assistant") return message;
|
|
441
388
|
const assistant = message;
|
|
442
389
|
if (assistant.status?.type !== "requires-action" || assistant.status.reason !== "interrupt") return assistant;
|
|
@@ -473,7 +420,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
473
420
|
return fallbackMessageId;
|
|
474
421
|
}
|
|
475
422
|
cancelUnresolvedToolCalls(messageId) {
|
|
476
|
-
if (this.updateMessage(messageId, (message) => {
|
|
423
|
+
if (this.session.updateMessage(messageId, (message) => {
|
|
477
424
|
if (message.role !== "assistant") return message;
|
|
478
425
|
const assistant = message;
|
|
479
426
|
const content = assistant.content.map((part) => {
|
|
@@ -491,7 +438,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
491
438
|
})) this.notifyUpdate();
|
|
492
439
|
}
|
|
493
440
|
addToolResult(options) {
|
|
494
|
-
if (!this.updateMessage(options.messageId, (message) => {
|
|
441
|
+
if (!this.session.updateMessage(options.messageId, (message) => {
|
|
495
442
|
if (message.role !== "assistant") return message;
|
|
496
443
|
const assistant = message;
|
|
497
444
|
let matchedToolCall = false;
|
|
@@ -517,7 +464,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
517
464
|
sendA2uiAction(action) {
|
|
518
465
|
this.assertNoPendingInterrupts();
|
|
519
466
|
this.maybeAutoCancelPendingToolCalls();
|
|
520
|
-
const parentId = this.
|
|
467
|
+
const parentId = this.session.headId;
|
|
521
468
|
if (parentId === null) {
|
|
522
469
|
this.logger.debug("[agui] sendA2uiAction: no messages to resume, dropping action");
|
|
523
470
|
return;
|
|
@@ -541,12 +488,12 @@ var AgUiThreadRuntimeCore = class {
|
|
|
541
488
|
this.startResumeRun(messageId);
|
|
542
489
|
}
|
|
543
490
|
maybeCompleteAfterToolResults(messageId) {
|
|
544
|
-
const message = this.tryGetMessage(messageId)?.message;
|
|
491
|
+
const message = this.session.tryGetMessage(messageId)?.message;
|
|
545
492
|
if (!message || message.role !== "assistant") return false;
|
|
546
493
|
const assistant = message;
|
|
547
494
|
if (assistant.status?.type !== "requires-action" || assistant.status.reason !== "tool-calls") return false;
|
|
548
495
|
if (!assistant.content.every((part) => part.type !== "tool-call" || isResolvedToolCall(part))) return false;
|
|
549
|
-
if (!this.updateMessage(messageId, (current) => current.role === "assistant" ? {
|
|
496
|
+
if (!this.session.updateMessage(messageId, (current) => current.role === "assistant" ? {
|
|
550
497
|
...current,
|
|
551
498
|
status: {
|
|
552
499
|
type: "complete",
|
|
@@ -566,7 +513,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
566
513
|
this.pendingA2uiResume = false;
|
|
567
514
|
this.pendingA2uiAction = void 0;
|
|
568
515
|
this.assistantHistoryParents.clear();
|
|
569
|
-
if (messages.length === 0) this.
|
|
516
|
+
if (messages.length === 0) this.session.clear();
|
|
570
517
|
else {
|
|
571
518
|
let expectedParentId = null;
|
|
572
519
|
let lastAppliedId = null;
|
|
@@ -575,85 +522,34 @@ var AgUiThreadRuntimeCore = class {
|
|
|
575
522
|
for (const message of messages) {
|
|
576
523
|
if (seen.has(message.id)) continue;
|
|
577
524
|
seen.add(message.id);
|
|
578
|
-
const existing = this.tryGetMessage(message.id);
|
|
525
|
+
const existing = this.session.tryGetMessage(message.id);
|
|
579
526
|
if (existing && existing.parentId !== expectedParentId) {
|
|
580
527
|
hardReplace = true;
|
|
581
528
|
break;
|
|
582
529
|
}
|
|
583
|
-
this.addOrUpdateMessage(expectedParentId, message);
|
|
530
|
+
this.session.addOrUpdateMessage(expectedParentId, message);
|
|
584
531
|
expectedParentId = message.id;
|
|
585
532
|
lastAppliedId = message.id;
|
|
586
533
|
}
|
|
587
534
|
if (hardReplace) {
|
|
588
|
-
this.
|
|
535
|
+
this.session.clear();
|
|
589
536
|
expectedParentId = null;
|
|
590
537
|
lastAppliedId = null;
|
|
591
538
|
seen.clear();
|
|
592
539
|
for (const message of messages) {
|
|
593
540
|
if (seen.has(message.id)) continue;
|
|
594
541
|
seen.add(message.id);
|
|
595
|
-
this.addOrUpdateMessage(expectedParentId, message);
|
|
542
|
+
this.session.addOrUpdateMessage(expectedParentId, message);
|
|
596
543
|
expectedParentId = message.id;
|
|
597
544
|
lastAppliedId = message.id;
|
|
598
545
|
}
|
|
599
546
|
}
|
|
600
|
-
this.
|
|
547
|
+
this.session.resetHead(lastAppliedId);
|
|
601
548
|
}
|
|
602
549
|
this.snapshotHistoryIds.clear();
|
|
603
550
|
for (const { message } of this.getMessageRepository().messages) this.snapshotHistoryIds.add(message.id);
|
|
604
551
|
this.notifyUpdate();
|
|
605
552
|
}
|
|
606
|
-
applyExternalMessageRepository(loaded) {
|
|
607
|
-
const headId = loaded.headId ?? loaded.messages.at(-1)?.message.id ?? null;
|
|
608
|
-
const ids = /* @__PURE__ */ new Set();
|
|
609
|
-
let degenerate = false;
|
|
610
|
-
for (const { message } of loaded.messages) {
|
|
611
|
-
if (ids.has(message.id)) {
|
|
612
|
-
degenerate = true;
|
|
613
|
-
break;
|
|
614
|
-
}
|
|
615
|
-
ids.add(message.id);
|
|
616
|
-
}
|
|
617
|
-
if (headId !== null && !ids.has(headId)) degenerate = true;
|
|
618
|
-
if (!degenerate) {
|
|
619
|
-
this.clearRepository();
|
|
620
|
-
let pending = [...loaded.messages];
|
|
621
|
-
const importedIds = /* @__PURE__ */ new Set();
|
|
622
|
-
while (pending.length > 0) {
|
|
623
|
-
const unresolved = [];
|
|
624
|
-
let progressed = false;
|
|
625
|
-
for (const item of pending) {
|
|
626
|
-
if (item.parentId !== null && !importedIds.has(item.parentId)) {
|
|
627
|
-
unresolved.push(item);
|
|
628
|
-
continue;
|
|
629
|
-
}
|
|
630
|
-
this.addOrUpdateMessage(item.parentId, item.message);
|
|
631
|
-
importedIds.add(item.message.id);
|
|
632
|
-
progressed = true;
|
|
633
|
-
}
|
|
634
|
-
if (!progressed) {
|
|
635
|
-
degenerate = true;
|
|
636
|
-
break;
|
|
637
|
-
}
|
|
638
|
-
pending = unresolved;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
if (degenerate) {
|
|
642
|
-
this.clearRepository();
|
|
643
|
-
let previousId = null;
|
|
644
|
-
for (const { message } of loaded.messages) {
|
|
645
|
-
const existing = this.tryGetMessage(message.id);
|
|
646
|
-
this.addOrUpdateMessage(existing ? existing.parentId : previousId, message);
|
|
647
|
-
previousId = message.id;
|
|
648
|
-
}
|
|
649
|
-
this.resetRepositoryHead(previousId);
|
|
650
|
-
} else this.resetRepositoryHead(headId);
|
|
651
|
-
this.assistantHistoryParents.clear();
|
|
652
|
-
this.snapshotHistoryIds.clear();
|
|
653
|
-
this.persistedHistoryIds.clear();
|
|
654
|
-
for (const { message } of loaded.messages) this.persistedHistoryIds.add(message.id);
|
|
655
|
-
this.notifyUpdate();
|
|
656
|
-
}
|
|
657
553
|
loadExternalState(state) {
|
|
658
554
|
this.stateSnapshot = state;
|
|
659
555
|
this.notifyUpdate();
|
|
@@ -669,20 +565,20 @@ var AgUiThreadRuntimeCore = class {
|
|
|
669
565
|
async startRun(parentId, runConfig, resume, resumeStream) {
|
|
670
566
|
const normalizedRunConfig = runConfig ?? {};
|
|
671
567
|
this.lastRunConfig = normalizedRunConfig;
|
|
672
|
-
const parent = parentId === null ? void 0 : this.tryGetMessage(parentId);
|
|
673
|
-
const shouldEagerlyInsertAssistant = parentId !== null && parent !== void 0 && parentId !== this.
|
|
674
|
-
const historicalMessages = [...shouldEagerlyInsertAssistant ? this.tryGetMessages(parentId) ?? this.
|
|
568
|
+
const parent = parentId === null ? void 0 : this.session.tryGetMessage(parentId);
|
|
569
|
+
const shouldEagerlyInsertAssistant = parentId !== null && parent !== void 0 && parentId !== this.session.headId;
|
|
570
|
+
const historicalMessages = [...shouldEagerlyInsertAssistant ? this.session.tryGetMessages(parentId) ?? this.session.getMessages() : this.session.getMessages()];
|
|
675
571
|
const runStartMessageIds = new Set(this.getMessageRepository().messages.map(({ message }) => message.id));
|
|
676
572
|
this.pendingError = null;
|
|
677
|
-
const assistantParentId = parent ? parentId : this.
|
|
573
|
+
const assistantParentId = parent ? parentId : this.session.headId;
|
|
678
574
|
let assistantMessageId;
|
|
679
575
|
let assistantCollided = false;
|
|
680
576
|
const ensureAssistant = (allowRecreate = false) => {
|
|
681
577
|
const cached = assistantMessageId;
|
|
682
|
-
if (cached !== void 0 && this.tryGetMessage(cached)) return cached;
|
|
578
|
+
if (cached !== void 0 && this.session.tryGetMessage(cached)) return cached;
|
|
683
579
|
if (cached !== void 0 && (assistantCollided || !allowRecreate)) return cached;
|
|
684
|
-
const repositoryHeadId = this.
|
|
685
|
-
const parentId = (cached === void 0 || shouldEagerlyInsertAssistant && (repositoryHeadId === null || runStartMessageIds.has(repositoryHeadId))) && assistantParentId && this.hasMessage(assistantParentId) ? assistantParentId : repositoryHeadId;
|
|
580
|
+
const repositoryHeadId = this.session.headId;
|
|
581
|
+
const parentId = (cached === void 0 || shouldEagerlyInsertAssistant && (repositoryHeadId === null || runStartMessageIds.has(repositoryHeadId))) && assistantParentId && this.session.hasMessage(assistantParentId) ? assistantParentId : repositoryHeadId;
|
|
686
582
|
const created = this.insertAssistantPlaceholder(parentId, cached);
|
|
687
583
|
assistantMessageId = created;
|
|
688
584
|
this.markPendingAssistantHistory(created, parentId);
|
|
@@ -694,23 +590,40 @@ var AgUiThreadRuntimeCore = class {
|
|
|
694
590
|
const resolved = this.updateAssistantMessage(ensureAssistant(hasStreamContent), update);
|
|
695
591
|
if (resolved !== assistantMessageId) assistantMessageId = resolved;
|
|
696
592
|
};
|
|
593
|
+
const adoptServerMessageId = (serverId, startNewMessage) => {
|
|
594
|
+
if (startNewMessage && assistantMessageId !== void 0) {
|
|
595
|
+
applyUpdate({ status: {
|
|
596
|
+
type: "complete",
|
|
597
|
+
reason: "unknown"
|
|
598
|
+
} });
|
|
599
|
+
const previousId = assistantMessageId;
|
|
600
|
+
assistantMessageId = void 0;
|
|
601
|
+
if (this.session.tryGetMessage(previousId)) {
|
|
602
|
+
const created = this.insertAssistantPlaceholder(previousId);
|
|
603
|
+
assistantMessageId = created;
|
|
604
|
+
this.markPendingAssistantHistory(created, previousId);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
const placeholder = ensureAssistant(true);
|
|
608
|
+
if (placeholder === serverId) return;
|
|
609
|
+
const reassigned = this.reassignAssistantId(placeholder, serverId);
|
|
610
|
+
const adoptsVisibleCollision = !reassigned && !runStartMessageIds.has(serverId) && this.session.headId === serverId;
|
|
611
|
+
if (reassigned || adoptsVisibleCollision) {
|
|
612
|
+
assistantMessageId = serverId;
|
|
613
|
+
if (adoptsVisibleCollision) {
|
|
614
|
+
const parentId = this.session.tryGetMessage(serverId)?.parentId ?? null;
|
|
615
|
+
this.markPendingAssistantHistory(serverId, parentId);
|
|
616
|
+
}
|
|
617
|
+
} else assistantCollided = true;
|
|
618
|
+
};
|
|
697
619
|
const aggregator = new RunAggregator({
|
|
698
620
|
showThinking: this.showThinking,
|
|
699
621
|
logger: this.logger,
|
|
700
622
|
emit: applyUpdate,
|
|
701
623
|
onServerMessageId: (serverId) => {
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
const adoptsVisibleCollision = !reassigned && !runStartMessageIds.has(serverId) && this.repository.headId === serverId;
|
|
706
|
-
if (reassigned || adoptsVisibleCollision) {
|
|
707
|
-
assistantMessageId = serverId;
|
|
708
|
-
if (adoptsVisibleCollision) {
|
|
709
|
-
const parentId = this.tryGetMessage(serverId)?.parentId ?? null;
|
|
710
|
-
this.markPendingAssistantHistory(serverId, parentId);
|
|
711
|
-
}
|
|
712
|
-
} else assistantCollided = true;
|
|
713
|
-
}
|
|
624
|
+
adoptServerMessageId(serverId, false);
|
|
625
|
+
},
|
|
626
|
+
onTextMessageStart: (serverId) => adoptServerMessageId(serverId, true)
|
|
714
627
|
});
|
|
715
628
|
const dispatch = (event) => this.handleEvent(aggregator, event, assistantMessageId);
|
|
716
629
|
const abortController = new AbortController();
|
|
@@ -802,7 +715,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
802
715
|
return;
|
|
803
716
|
}
|
|
804
717
|
this.maybeAutoCancelPendingToolCalls();
|
|
805
|
-
const parentId = this.
|
|
718
|
+
const parentId = this.session.headId;
|
|
806
719
|
if (parentId !== null) this.startResumeRun(parentId);
|
|
807
720
|
else {
|
|
808
721
|
this.pendingA2uiAction = void 0;
|
|
@@ -825,7 +738,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
825
738
|
unstable_threadId: ctx.threadId,
|
|
826
739
|
unstable_parentId: ctx.parentId,
|
|
827
740
|
unstable_getMessage: () => {
|
|
828
|
-
const message = this.tryGetMessage(currentId())?.message;
|
|
741
|
+
const message = this.session.tryGetMessage(currentId())?.message;
|
|
829
742
|
if (!message) throw new Error("[agui] resume stream requested the assistant message before it existed");
|
|
830
743
|
return message;
|
|
831
744
|
}
|
|
@@ -848,7 +761,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
848
761
|
return;
|
|
849
762
|
}
|
|
850
763
|
if (ctx.abortSignal.aborted) return;
|
|
851
|
-
const current = this.tryGetMessage(currentId())?.message;
|
|
764
|
+
const current = this.session.tryGetMessage(currentId())?.message;
|
|
852
765
|
if (!current || current.status?.type === "running") ctx.applyUpdate({ status: {
|
|
853
766
|
type: "complete",
|
|
854
767
|
reason: "unknown"
|
|
@@ -856,7 +769,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
856
769
|
}
|
|
857
770
|
buildRunInput(runId, runConfig, historyMessages, resume) {
|
|
858
771
|
const threadId = this.agent.threadId || "main";
|
|
859
|
-
const messages = toAgUiMessages(historyMessages ?? this.
|
|
772
|
+
const messages = toAgUiMessages(historyMessages ?? this.session.getMessages());
|
|
860
773
|
const context = this.runtime?.thread.getModelContext();
|
|
861
774
|
const input = {
|
|
862
775
|
threadId,
|
|
@@ -921,31 +834,31 @@ var AgUiThreadRuntimeCore = class {
|
|
|
921
834
|
custom: {}
|
|
922
835
|
}
|
|
923
836
|
};
|
|
924
|
-
this.addOrUpdateMessage(parentId ?? this.
|
|
925
|
-
this.switchToBranch(id);
|
|
837
|
+
this.session.addOrUpdateMessage(parentId ?? this.session.headId, assistant);
|
|
838
|
+
this.session.switchToBranch(id);
|
|
926
839
|
this.notifyUpdate();
|
|
927
840
|
return id;
|
|
928
841
|
}
|
|
929
842
|
reassignAssistantId(oldId, newId) {
|
|
930
843
|
if (oldId === newId) return true;
|
|
931
|
-
const oldItem = this.tryGetMessage(oldId);
|
|
844
|
+
const oldItem = this.session.tryGetMessage(oldId);
|
|
932
845
|
if (!oldItem) return false;
|
|
933
|
-
const collidesWithExisting = this.hasMessage(newId);
|
|
846
|
+
const collidesWithExisting = this.session.hasMessage(newId);
|
|
934
847
|
if (collidesWithExisting) {
|
|
935
848
|
this.logger.debug?.("[agui] reassignAssistantId: server id already present in messages or repository, dropping placeholder", {
|
|
936
849
|
oldId,
|
|
937
850
|
newId
|
|
938
851
|
});
|
|
939
|
-
this.deleteMessage(oldId, oldItem.parentId ?? null);
|
|
852
|
+
this.session.deleteMessage(oldId, oldItem.parentId ?? null);
|
|
940
853
|
} else {
|
|
941
854
|
const { isOptimistic: _, ...metadata } = oldItem.message.metadata;
|
|
942
|
-
this.addOrUpdateMessage(oldItem.parentId, {
|
|
855
|
+
this.session.addOrUpdateMessage(oldItem.parentId, {
|
|
943
856
|
...oldItem.message,
|
|
944
857
|
id: newId,
|
|
945
858
|
metadata
|
|
946
859
|
});
|
|
947
|
-
this.switchToBranch(newId);
|
|
948
|
-
this.tryDeleteMessage(oldId);
|
|
860
|
+
this.session.switchToBranch(newId);
|
|
861
|
+
this.session.tryDeleteMessage(oldId);
|
|
949
862
|
}
|
|
950
863
|
const pendingParent = this.assistantHistoryParents.get(oldId);
|
|
951
864
|
if (pendingParent !== void 0) {
|
|
@@ -976,7 +889,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
976
889
|
}
|
|
977
890
|
updateAssistantMessage(messageId, update) {
|
|
978
891
|
let latestStatus;
|
|
979
|
-
if (!this.updateMessage(messageId, (message) => {
|
|
892
|
+
if (!this.session.updateMessage(messageId, (message) => {
|
|
980
893
|
if (message.role !== "assistant") return message;
|
|
981
894
|
const assistant = message;
|
|
982
895
|
const metadata = update.metadata ? this.mergeAssistantMetadata(assistant.metadata, update.metadata) : assistant.metadata;
|
|
@@ -1078,7 +991,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
1078
991
|
}
|
|
1079
992
|
}
|
|
1080
993
|
applyCrossRunToolResult(messageId, event) {
|
|
1081
|
-
if (!this.updateMessage(messageId, (message) => {
|
|
994
|
+
if (!this.session.updateMessage(messageId, (message) => {
|
|
1082
995
|
if (message.role !== "assistant") return message;
|
|
1083
996
|
const assistant = message;
|
|
1084
997
|
const mcpAppUri = readMcpAppResourceUri(event.mcpResult?._meta);
|
|
@@ -1123,7 +1036,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
1123
1036
|
const serverHash = event.content["serverHash"];
|
|
1124
1037
|
const appServerId = typeof serverId === "string" && serverId.length > 0 ? serverId : typeof serverHash === "string" && serverHash.length > 0 ? serverHash : void 0;
|
|
1125
1038
|
const result = event.content["result"];
|
|
1126
|
-
if (!this.updateMessage(messageId, (message) => {
|
|
1039
|
+
if (!this.session.updateMessage(messageId, (message) => {
|
|
1127
1040
|
if (message.role !== "assistant") return message;
|
|
1128
1041
|
const assistant = message;
|
|
1129
1042
|
let matchedToolCall = false;
|
|
@@ -1157,7 +1070,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
1157
1070
|
}
|
|
1158
1071
|
importMessagesSnapshot(rawMessages, activeAssistantId) {
|
|
1159
1072
|
try {
|
|
1160
|
-
const activeMessage = activeAssistantId ? this.tryGetMessage(activeAssistantId)?.message : void 0;
|
|
1073
|
+
const activeMessage = activeAssistantId ? this.session.tryGetMessage(activeAssistantId)?.message : void 0;
|
|
1161
1074
|
const activeAssistant = activeMessage?.role === "assistant" ? activeMessage : void 0;
|
|
1162
1075
|
const normalized = fromAgUiMessages(rawMessages, { showThinking: this.showThinking });
|
|
1163
1076
|
const converted = [];
|
|
@@ -1171,7 +1084,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
1171
1084
|
if (preservesActiveAssistant) converted.push(activeAssistant);
|
|
1172
1085
|
this.applyExternalMessages(converted);
|
|
1173
1086
|
if (activeAssistant !== void 0) {
|
|
1174
|
-
const activeItem = this.tryGetMessage(activeAssistant.id);
|
|
1087
|
+
const activeItem = this.session.tryGetMessage(activeAssistant.id);
|
|
1175
1088
|
if (activeItem) {
|
|
1176
1089
|
if (preservesActiveAssistant) this.snapshotHistoryIds.delete(activeAssistant.id);
|
|
1177
1090
|
this.markPendingAssistantHistory(activeAssistant.id, activeItem.parentId);
|
|
@@ -1205,7 +1118,7 @@ var AgUiThreadRuntimeCore = class {
|
|
|
1205
1118
|
if (!history) return;
|
|
1206
1119
|
const parentId = this.assistantHistoryParents.get(messageId);
|
|
1207
1120
|
if (parentId === void 0) return;
|
|
1208
|
-
const message = this.tryGetMessage(messageId)?.message;
|
|
1121
|
+
const message = this.session.tryGetMessage(messageId)?.message;
|
|
1209
1122
|
if (!message || message.role !== "assistant") return;
|
|
1210
1123
|
if (!this.isPersistableStatus(message.status)) return;
|
|
1211
1124
|
const wasPersisted = this.persistedHistoryIds.has(messageId);
|