@assistant-ui/react-ag-ui 0.1.2 → 0.1.4
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/AgUiThreadController.d.ts +3 -0
- package/dist/runtime/AgUiThreadController.d.ts.map +1 -1
- package/dist/runtime/AgUiThreadController.js +124 -14
- package/dist/runtime/AgUiThreadController.js.map +1 -1
- package/dist/runtime/adapter/run-aggregator.d.ts +1 -0
- package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
- package/dist/runtime/adapter/run-aggregator.js +8 -0
- package/dist/runtime/adapter/run-aggregator.js.map +1 -1
- package/package.json +5 -4
- package/src/runtime/AgUiThreadController.snapshot-head-history.test.ts +226 -0
- package/src/runtime/AgUiThreadController.snapshot-head-move.test.ts +180 -1
- package/src/runtime/AgUiThreadController.snapshot-nested-settle.test.ts +210 -0
- package/src/runtime/AgUiThreadController.test.ts +133 -1
- package/src/runtime/AgUiThreadController.ts +207 -22
- package/src/runtime/adapter/run-aggregator.ts +11 -0
- package/src/useAgUiRuntime.cloud-run-leases.test.tsx +384 -0
- package/src/useAgUiRuntime.state.test.tsx +87 -0
|
@@ -42,11 +42,13 @@ export declare class AgUiThreadController {
|
|
|
42
42
|
private state;
|
|
43
43
|
private abortController;
|
|
44
44
|
private activeRunAgent;
|
|
45
|
+
private runCount;
|
|
45
46
|
private history;
|
|
46
47
|
private readonly assistantHistoryParents;
|
|
47
48
|
private readonly subagentParentToolCallIds;
|
|
48
49
|
private readonly snapshotHistoryIds;
|
|
49
50
|
private readonly persistedHistoryIds;
|
|
51
|
+
private readonly unappendedHistoryIds;
|
|
50
52
|
private readonly historyWrites;
|
|
51
53
|
private _historyImportPromise;
|
|
52
54
|
private _loadPromise;
|
|
@@ -179,6 +181,7 @@ export declare class AgUiThreadController {
|
|
|
179
181
|
private markPendingAssistantHistory;
|
|
180
182
|
private persistSettledAssistant;
|
|
181
183
|
private persistAssistantHistory;
|
|
184
|
+
private appendOnce;
|
|
182
185
|
private appendHistoryItem;
|
|
183
186
|
}
|
|
184
187
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgUiThreadController.d.ts","sourceRoot":"","sources":["../../src/runtime/AgUiThreadController.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,yBAAyB,EAEzB,4BAA4B,EAC5B,SAAS,EAET,oBAAoB,EACpB,aAAa,EAEb,wBAAwB,EACzB,MAAM,oBAAoB,CAAC;AAS5B,OAAO,KAAK,EACV,aAAa,EAKd,MAAM,eAAe,CAAC;AAQvB,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAiB;AAEvC,OAAO,KAAK,EAGV,aAAa,EACb,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACtB,mBAAgB;AAEjB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"AgUiThreadController.d.ts","sourceRoot":"","sources":["../../src/runtime/AgUiThreadController.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,yBAAyB,EAEzB,4BAA4B,EAC5B,SAAS,EAET,oBAAoB,EACpB,aAAa,EAEb,wBAAwB,EACzB,MAAM,oBAAoB,CAAC;AAS5B,OAAO,KAAK,EACV,aAAa,EAKd,MAAM,eAAe,CAAC;AAQvB,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAiB;AAEvC,OAAO,KAAK,EAGV,aAAa,EACb,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACtB,mBAAgB;AAEjB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AA+JhE,KAAK,YAAY,GAAG,CAClB,OAAO,EAAE,mBAAmB,KACzB,cAAc,CAAC,kBAAkB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACvD,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,CAAC;AAYF,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,qBAAqB,CAAC,cAAc,CAAC,CAAC;IACrD,aAAa,CAAC,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAC;IACvD,gBAAgB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACpD,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC;CACnC,CAAC;AAmHF,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,aAAa,CAAyC;IAC9D,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,0BAA0B,CAAsB;IACxD,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IACnD,OAAO,CAAC,QAAQ,CAOF;IACd,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA8B;IAChE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IAExD,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAerB;IACH,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,eAAe,CAAgC;IAGvD,OAAO,CAAC,cAAc,CAA8B;IAEpD,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAoC;IAC5E,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAGtC;IACJ,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IAGzD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAqB;IAC1D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAC3D,OAAO,CAAC,qBAAqB,CAA4B;IACzD,OAAO,CAAC,YAAY,CAA4B;gBAEpC,OAAO,EAAE,WAAW;IAqBhC,SAAS,GAAI,UAAU,MAAM,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC,CAG9C;IAEF,WAAW;mBA1EM,OAAO;mBACP,OAAO;2BACC,yBAAyB;eACrC,iBAAiB,GAAG,SAAS;MA6ErC;IAEL,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,aAAa;IAKrB,aAAa,CAAC,OAAO,EAAE,WAAW;IAkClC,aAAa,CAAC,OAAO,EAAE,gBAAgB;IAIvC,aAAa;IAOb,WAAW,IAAI,SAAS,aAAa,EAAE;IAIvC,oBAAoB,IAAI,yBAAyB;IAIjD,QAAQ,IAAI,iBAAiB,GAAG,SAAS;IAIzC,SAAS,IAAI,OAAO;IAIpB,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAgEhC,OAAO,CAAC,oBAAoB;IAW5B,OAAO,CAAC,yBAAyB;IAoB3B,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BnD,qBAAqB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAQnD,OAAO,CAAC,+BAA+B;IAQvC,OAAO,CAAC,WAAW;IAeb,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,MAAM,CACV,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,GAAE;QAAE,SAAS,CAAC,EAAE,SAAS,CAAA;KAAO,GACrC,OAAO,CAAC,IAAI,CAAC;IAQV,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAc7B,OAAO,CAAC,cAAc;IAiBtB,OAAO,CAAC,kBAAkB;IAapB,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAa9C,iBAAiB,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B1E,OAAO,CAAC,yBAAyB;IAOjC,OAAO,CAAC,2BAA2B;IAYnC,OAAO,CAAC,wBAAwB;IAWhC,OAAO,CAAC,0BAA0B;IAQlC,oBAAoB,IAAI;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;KACtC,GAAG,IAAI;IAYR,mBAAmB,IAAI;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,GAAG,IAAI;IAkBF,wBAAwB,CAC5B,SAAS,EAAE,SAAS,eAAe,EAAE,GACpC,OAAO,CAAC,IAAI,CAAC;IAoChB;;;;;OAKG;YACW,mBAAmB;IAYjC;;;;;;OAMG;IACH,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAYjC,OAAO,CAAC,0BAA0B;IA4B5B,qBAAqB,CACzB,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,IAAI,CAAC;IAwEV,SAAS,CACb,OAAO,EAAE,mBAAmB,EAC5B,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,GACrC,OAAO,CAAC,IAAI,CAAC;IAgDhB,OAAO,CAAC,sBAAsB;IAkB9B,OAAO,CAAC,yBAAyB;IAiCjC,OAAO,CAAC,eAAe;IA2BvB,OAAO,CAAC,sBAAsB;IAoC9B,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAiBhE,OAAO,CAAC,yBAAyB;IAiBjC,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAmE5C,qBAAqB,CAAC,OAAO,EAAE;QACnC,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,wBAAwB,CAAC;KACvC,GAAG,OAAO,CAAC,IAAI,CAAC;IA2DjB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAqCrD,OAAO,CAAC,2BAA2B;IAqCnC,OAAO,CAAC,6BAA6B;IAwCrC,OAAO,CAAC,cAAc;IAMtB,qBAAqB,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI;IAkH/D,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAQjD,QAAQ,CACN,IAAI,EACA,iBAAiB,GACjB,CAAC,CAAC,IAAI,EAAE,iBAAiB,GAAG,SAAS,KAAK,iBAAiB,CAAC,GAC/D,IAAI;IAUP,UAAU,IAAI,IAAI;IAKlB,gBAAgB,IAAI,IAAI;YA0BV,QAAQ;YAs+BR,mBAAmB;IA4DjC,OAAO,CAAC,aAAa;IAoDrB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,0BAA0B;IAWlC,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,0BAA0B;IAyBlC,OAAO,CAAC,mBAAmB;IAiE3B,OAAO,CAAC,sBAAsB;IAmJ9B,OAAO,CAAC,mBAAmB;IAoC3B,OAAO,CAAC,wBAAwB;IA4BhC,OAAO,CAAC,6BAA6B;IA2ErC,OAAO,CAAC,8BAA8B;IAsEtC;;;;;;;OAOG;IACH,OAAO,CAAC,sBAAsB;IA+D9B,OAAO,CAAC,sBAAsB;IA6B9B,OAAO,CAAC,WAAW;IAiJnB,OAAO,CAAC,0BAA0B;IAyBlC,OAAO,CAAC,uBAAuB;IAgG/B,OAAO,CAAC,6BAA6B;IA8DrC,OAAO,CAAC,sBAAsB;IAkO9B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,2BAA2B;IAQnC,OAAO,CAAC,uBAAuB;IAa/B,OAAO,CAAC,uBAAuB;YA0DjB,UAAU;IASxB,OAAO,CAAC,iBAAiB;CAqB1B"}
|
|
@@ -11,6 +11,14 @@ import { fromThreadMessageLike, generateId, isMcpAppUri } from "@assistant-ui/co
|
|
|
11
11
|
import { appendToolInteraction, createHistoryWriteChain, createMessageRepositorySession, invokeUserCallback, iterateToolCallParts, mapToolCallPartsDeep } from "@assistant-ui/core/internal";
|
|
12
12
|
import jsonpatch from "fast-json-patch";
|
|
13
13
|
// src/runtime/AgUiThreadController.ts
|
|
14
|
+
const agentInitialStates = /* @__PURE__ */ new WeakMap();
|
|
15
|
+
const getAgentInitialState = (agent) => {
|
|
16
|
+
if (!agentInitialStates.has(agent)) {
|
|
17
|
+
const state = agent.state;
|
|
18
|
+
agentInitialStates.set(agent, state === void 0 || isPlainObject(state) && Object.keys(state).length === 0 ? void 0 : structuredClone(state));
|
|
19
|
+
}
|
|
20
|
+
return agentInitialStates.get(agent);
|
|
21
|
+
};
|
|
14
22
|
const optimisticPrefix = "__optimistic__";
|
|
15
23
|
const generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
|
|
16
24
|
const isOptimisticId = (id) => id.startsWith(optimisticPrefix);
|
|
@@ -86,13 +94,29 @@ const replaceTextParts = (content, source) => {
|
|
|
86
94
|
}
|
|
87
95
|
return result;
|
|
88
96
|
};
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Settles nested sub-agent messages with `status`. Without `runSubagentIds`,
|
|
99
|
+
* only running messages settle. With it, only that run's sub-agent messages
|
|
100
|
+
* settle, and an incomplete `status` also settles one still waiting on its own
|
|
101
|
+
* tool call: the run that could answer it has ended.
|
|
102
|
+
*/
|
|
103
|
+
const settleNestedContent = (content, status, runSubagentIds) => mapToolCallPartsDeep(content, (part) => {
|
|
104
|
+
if (!part.messages) return part;
|
|
105
|
+
let changed = false;
|
|
106
|
+
const messages = part.messages.map((message) => {
|
|
107
|
+
if (message.role !== "assistant") return message;
|
|
108
|
+
if (!(!runSubagentIds ? message.status?.type === "running" : runSubagentIds.has(message.id) && (message.status?.type === "running" || status.type === "incomplete" && message.status?.type === "requires-action" && message.status.reason === "tool-calls"))) return message;
|
|
109
|
+
changed = true;
|
|
110
|
+
return {
|
|
111
|
+
...message,
|
|
112
|
+
status
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
return changed ? {
|
|
116
|
+
...part,
|
|
117
|
+
messages
|
|
118
|
+
} : part;
|
|
119
|
+
}).content;
|
|
96
120
|
const invokeRuntimeCallback = (name, callback, ...args) => {
|
|
97
121
|
invokeUserCallback("react-ag-ui", name, callback, ...args);
|
|
98
122
|
};
|
|
@@ -141,16 +165,23 @@ var AgUiThreadController = class {
|
|
|
141
165
|
state = createAgUiThreadState();
|
|
142
166
|
abortController = null;
|
|
143
167
|
activeRunAgent = null;
|
|
168
|
+
runCount = 0;
|
|
144
169
|
history;
|
|
145
170
|
assistantHistoryParents = /* @__PURE__ */ new Map();
|
|
146
171
|
subagentParentToolCallIds = /* @__PURE__ */ new Map();
|
|
147
172
|
snapshotHistoryIds = /* @__PURE__ */ new Set();
|
|
148
173
|
persistedHistoryIds = /* @__PURE__ */ new Set();
|
|
174
|
+
unappendedHistoryIds = /* @__PURE__ */ new Set();
|
|
149
175
|
historyWrites = createHistoryWriteChain();
|
|
150
176
|
_historyImportPromise;
|
|
151
177
|
_loadPromise;
|
|
152
178
|
constructor(options) {
|
|
153
179
|
this.agent = options.agent;
|
|
180
|
+
const initialState = getAgentInitialState(this.agent);
|
|
181
|
+
if (initialState !== void 0) this.dispatch({
|
|
182
|
+
type: "stateSnapshot",
|
|
183
|
+
snapshot: initialState
|
|
184
|
+
});
|
|
154
185
|
this.logger = options.logger;
|
|
155
186
|
this.showThinking = options.showThinking;
|
|
156
187
|
this.joinStrategy = options.joinStrategy;
|
|
@@ -180,7 +211,18 @@ var AgUiThreadController = class {
|
|
|
180
211
|
for (const listener of this.listeners) listener();
|
|
181
212
|
}
|
|
182
213
|
updateOptions(options) {
|
|
214
|
+
const agentChanged = this.agent !== options.agent;
|
|
183
215
|
this.agent = options.agent;
|
|
216
|
+
if (agentChanged) {
|
|
217
|
+
const initialState = getAgentInitialState(this.agent);
|
|
218
|
+
if (this.state.stateSnapshot === void 0 && initialState !== void 0) {
|
|
219
|
+
this.dispatch({
|
|
220
|
+
type: "stateSnapshot",
|
|
221
|
+
snapshot: initialState
|
|
222
|
+
});
|
|
223
|
+
this.publishUpdate();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
184
226
|
this.logger = options.logger;
|
|
185
227
|
this.showThinking = options.showThinking;
|
|
186
228
|
this.joinStrategy = options.joinStrategy;
|
|
@@ -228,6 +270,7 @@ var AgUiThreadController = class {
|
|
|
228
270
|
this.subagentParentToolCallIds.clear();
|
|
229
271
|
this.snapshotHistoryIds.clear();
|
|
230
272
|
this.persistedHistoryIds.clear();
|
|
273
|
+
this.unappendedHistoryIds.clear();
|
|
231
274
|
for (const { message } of repo.messages) this.persistedHistoryIds.add(message.id);
|
|
232
275
|
this.publishUpdate();
|
|
233
276
|
if (repo.state !== void 0) this.loadExternalState(repo.state);
|
|
@@ -951,6 +994,8 @@ var AgUiThreadController = class {
|
|
|
951
994
|
const assistantParentId = parent ? parentId : this.session.headId;
|
|
952
995
|
let assistantMessageId;
|
|
953
996
|
let snapshotAssistantId;
|
|
997
|
+
const importedRunAssistants = /* @__PURE__ */ new Set();
|
|
998
|
+
const runSubagentIds = /* @__PURE__ */ new Set();
|
|
954
999
|
let replayInterruptMessageId;
|
|
955
1000
|
let assistantCollided = false;
|
|
956
1001
|
const heldMessages = /* @__PURE__ */ new Map();
|
|
@@ -1225,9 +1270,29 @@ var AgUiThreadController = class {
|
|
|
1225
1270
|
adoptServerMessageId(serverId, true, frameOpenIds);
|
|
1226
1271
|
}
|
|
1227
1272
|
});
|
|
1273
|
+
const settleRunSubagents = (status) => {
|
|
1274
|
+
if (runSubagentIds.size === 0) return;
|
|
1275
|
+
for (const message of this.session.getMessages()) {
|
|
1276
|
+
if (message.role !== "assistant") continue;
|
|
1277
|
+
const content = settleNestedContent(message.content, status, runSubagentIds);
|
|
1278
|
+
if (content === message.content) continue;
|
|
1279
|
+
this.updateAssistantMessage(message.id, { content });
|
|
1280
|
+
this.persistSettledAssistant(message.id);
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
const persistRunAssistants = (aboveAnswer) => {
|
|
1284
|
+
for (const message of this.session.getMessages()) {
|
|
1285
|
+
if (message.id === assistantMessageId) {
|
|
1286
|
+
if (aboveAnswer) return;
|
|
1287
|
+
continue;
|
|
1288
|
+
}
|
|
1289
|
+
if (message.role === "assistant" && !runStartMessageIds.has(message.id)) this.persistAssistantHistory(message.id);
|
|
1290
|
+
}
|
|
1291
|
+
};
|
|
1228
1292
|
let runFinished = false;
|
|
1229
1293
|
const dispatch = (event) => {
|
|
1230
1294
|
if (this.abortController !== abortController) return;
|
|
1295
|
+
if (event.type === "SUBAGENT_STARTED") runSubagentIds.add(event.subagentRunId);
|
|
1231
1296
|
if (event.type === "RUN_FINISHED") {
|
|
1232
1297
|
runFinished = true;
|
|
1233
1298
|
if (event.outcome?.type === "interrupt") replayInterruptMessageId = assistantMessageId ?? replayTail;
|
|
@@ -1239,10 +1304,21 @@ var AgUiThreadController = class {
|
|
|
1239
1304
|
for (const openToolCallIds of heldMessages.values()) openToolCallIds.delete(event.toolCallId);
|
|
1240
1305
|
}
|
|
1241
1306
|
settlingRun = event.type === "RUN_FINISHED" || event.type === "RUN_ERROR" || event.type === "RUN_CANCELLED";
|
|
1307
|
+
if (settlingRun) persistRunAssistants(true);
|
|
1242
1308
|
const beforeSnapshot = event.type === "MESSAGES_SNAPSHOT" ? this.session.getMessages() : [];
|
|
1243
1309
|
try {
|
|
1244
1310
|
const nextAssistantMessageId = this.handleEvent(aggregator, event, assistantMessageId, joinStrategy, runStartMessageIds, hasRunUserBoundary, candidateContexts.size ? reconcileReplaySnapshot : void 0);
|
|
1245
1311
|
if (event.type === "MESSAGES_SNAPSHOT") {
|
|
1312
|
+
const previousIds = new Set(beforeSnapshot.map(({ id }) => id));
|
|
1313
|
+
for (const message of this.session.getMessages()) {
|
|
1314
|
+
if (message.role !== "assistant" || runStartMessageIds.has(message.id)) continue;
|
|
1315
|
+
if (!previousIds.has(message.id)) importedRunAssistants.add(message.id);
|
|
1316
|
+
if (!this.persistedHistoryIds.has(message.id) && this.historyWrites.pending(message.id) === void 0) this.snapshotHistoryIds.delete(message.id);
|
|
1317
|
+
}
|
|
1318
|
+
for (const messageId of importedRunAssistants) {
|
|
1319
|
+
const item = this.session.tryGetMessage(messageId);
|
|
1320
|
+
if (item) this.markPendingAssistantHistory(messageId, item.parentId);
|
|
1321
|
+
}
|
|
1246
1322
|
for (const message of beforeSnapshot) {
|
|
1247
1323
|
const context = replayContexts.get(message.id);
|
|
1248
1324
|
const current = this.session.tryGetMessage(message.id)?.message;
|
|
@@ -1261,6 +1337,16 @@ var AgUiThreadController = class {
|
|
|
1261
1337
|
snapshotAssistantId = tail?.role === "assistant" ? tail.id : void 0;
|
|
1262
1338
|
}
|
|
1263
1339
|
}
|
|
1340
|
+
if (event.type === "RUN_ERROR") settleRunSubagents({
|
|
1341
|
+
type: "incomplete",
|
|
1342
|
+
reason: "error",
|
|
1343
|
+
...event.message !== void 0 ? { error: event.message } : {}
|
|
1344
|
+
});
|
|
1345
|
+
else if (event.type === "RUN_CANCELLED") settleRunSubagents({
|
|
1346
|
+
type: "incomplete",
|
|
1347
|
+
reason: "cancelled"
|
|
1348
|
+
});
|
|
1349
|
+
if (settlingRun) persistRunAssistants(false);
|
|
1264
1350
|
} finally {
|
|
1265
1351
|
settlingRun = false;
|
|
1266
1352
|
}
|
|
@@ -1268,6 +1354,7 @@ var AgUiThreadController = class {
|
|
|
1268
1354
|
this.abortController = abortController;
|
|
1269
1355
|
const runAgentInstance = this.agent;
|
|
1270
1356
|
this.activeRunAgent = runAgentInstance;
|
|
1357
|
+
const runNumber = ++this.runCount;
|
|
1271
1358
|
let cancelRun = () => dispatch({ type: "RUN_CANCELLED" });
|
|
1272
1359
|
abortSignal.addEventListener("abort", () => {
|
|
1273
1360
|
cancelRun();
|
|
@@ -1330,6 +1417,7 @@ var AgUiThreadController = class {
|
|
|
1330
1417
|
} finally {
|
|
1331
1418
|
const current = assistantMessageId ? this.session.tryGetMessage(assistantMessageId)?.message : void 0;
|
|
1332
1419
|
if (this.abortController === abortController && current?.role === "assistant" && current.status?.type === "running") {
|
|
1420
|
+
persistRunAssistants(true);
|
|
1333
1421
|
const status = {
|
|
1334
1422
|
type: "incomplete",
|
|
1335
1423
|
reason: "error",
|
|
@@ -1341,6 +1429,15 @@ var AgUiThreadController = class {
|
|
|
1341
1429
|
content: settleNestedContent(current.content, status)
|
|
1342
1430
|
});
|
|
1343
1431
|
}
|
|
1432
|
+
if (this.abortController === abortController && !runFinished) {
|
|
1433
|
+
const settled = assistantMessageId ? this.session.tryGetMessage(assistantMessageId)?.message : void 0;
|
|
1434
|
+
settleRunSubagents(settled?.status?.type === "incomplete" ? settled.status : {
|
|
1435
|
+
type: "incomplete",
|
|
1436
|
+
reason: "error",
|
|
1437
|
+
error: "The connection ended before the answer finished."
|
|
1438
|
+
});
|
|
1439
|
+
}
|
|
1440
|
+
if (this.runCount === runNumber) persistRunAssistants(false);
|
|
1344
1441
|
this.finishRun(abortController);
|
|
1345
1442
|
}
|
|
1346
1443
|
if (pendingError) {
|
|
@@ -1558,9 +1655,11 @@ var AgUiThreadController = class {
|
|
|
1558
1655
|
if (!collidesWithExisting) ids.add(newId);
|
|
1559
1656
|
}
|
|
1560
1657
|
const pendingWrite = this.historyWrites.move(oldId, collidesWithExisting ? void 0 : newId);
|
|
1658
|
+
if (this.unappendedHistoryIds.delete(oldId) && !collidesWithExisting) this.unappendedHistoryIds.add(newId);
|
|
1561
1659
|
if (pendingWrite && !collidesWithExisting) pendingWrite.then(() => {
|
|
1562
1660
|
this.persistedHistoryIds.delete(oldId);
|
|
1563
1661
|
this.persistedHistoryIds.add(newId);
|
|
1662
|
+
this.unappendedHistoryIds.delete(newId);
|
|
1564
1663
|
}, () => {});
|
|
1565
1664
|
this.publishUpdate();
|
|
1566
1665
|
return !collidesWithExisting;
|
|
@@ -1573,13 +1672,13 @@ var AgUiThreadController = class {
|
|
|
1573
1672
|
const mergedMetadata = update.metadata ? this.mergeAssistantMetadata(assistant.metadata, update.metadata) : assistant.metadata;
|
|
1574
1673
|
latestStatus = update.status ?? assistant.status;
|
|
1575
1674
|
let content = update.content !== void 0 ? replay ? replay.merge(assistant.content, update.content) : this.preserveToolResults(assistant.content, update.content) : assistant.content;
|
|
1576
|
-
const calls =
|
|
1675
|
+
const calls = Array.from(iterateToolCallParts(content));
|
|
1577
1676
|
const pending = pendingToolCallIds ?? (replay ? /* @__PURE__ */ new Set([...replay.admittedToolCallIds, ...Array.from(iterateToolCallParts(update.content ?? [])).filter((part) => !isResolvedToolCall(part)).map((part) => part.toolCallId)]) : void 0);
|
|
1578
1677
|
if (replay && latestStatus?.type !== "running" && pending) replay.admittedToolCallIds = pending;
|
|
1579
|
-
if (replay) {
|
|
1678
|
+
if (replay || latestStatus?.type === "requires-action" && latestStatus.reason === "interrupt") {
|
|
1580
1679
|
const interrupts = latestStatus?.type === "requires-action" && latestStatus.reason === "interrupt" ? mergedMetadata.custom["agui"]?.interrupts : void 0;
|
|
1581
1680
|
const approvals = projectAgUiToolApprovals(interrupts, new Set(calls.map((part) => part.toolCallId)));
|
|
1582
|
-
const originalCalls = new Map(Array.from(iterateToolCallParts(replay.
|
|
1681
|
+
const originalCalls = new Map(Array.from(iterateToolCallParts(replay?.originalContent ?? assistant.content), (part) => [part.toolCallId, part]));
|
|
1583
1682
|
content = mapToolCallPartsDeep(content, (part) => {
|
|
1584
1683
|
const approval = approvals.get(part.toolCallId);
|
|
1585
1684
|
if (approval) return {
|
|
@@ -1821,6 +1920,7 @@ var AgUiThreadController = class {
|
|
|
1821
1920
|
});
|
|
1822
1921
|
}
|
|
1823
1922
|
activeAssistantId = nextActiveAssistantId;
|
|
1923
|
+
if (activeAssistantId && joinStrategy !== "concat-content") aggregator.rebaseMessage(activeAssistantId);
|
|
1824
1924
|
if (hasNewPendingToolCallAnswer && head) this.updateAssistantMessage(head.id, { status: { type: "running" } });
|
|
1825
1925
|
}
|
|
1826
1926
|
this.updateActiveAssistantState(activeAssistantId);
|
|
@@ -1975,9 +2075,11 @@ var AgUiThreadController = class {
|
|
|
1975
2075
|
const previous = existing?.role === "assistant" ? existing : void 0;
|
|
1976
2076
|
const snapshot = reconcileSnapshot?.(convertedMessage, previous) ?? convertedMessage;
|
|
1977
2077
|
const preservesRunningStatus = convertedMessage.id === activeAssistantId && previous?.status?.type === "running" && snapshot.status?.type === "requires-action" && snapshot.status.reason === "tool-calls";
|
|
2078
|
+
const previousToolCallIds = new Set(Array.from(iterateToolCallParts(previous?.content ?? []), (call) => call.toolCallId));
|
|
2079
|
+
const preservesSettledStatus = convertedMessage.id !== activeAssistantId && this.isTerminalStatus(previous?.status) && snapshot.status?.type === "requires-action" && snapshot.status.reason === "tool-calls" && Array.from(iterateToolCallParts(snapshot.content)).every((call) => isResolvedToolCall(call) || previousToolCallIds.has(call.toolCallId));
|
|
1978
2080
|
converted[index] = previous ? {
|
|
1979
2081
|
...snapshot,
|
|
1980
|
-
...preservesRunningStatus ? { status: previous.status } : {},
|
|
2082
|
+
...preservesRunningStatus || preservesSettledStatus ? { status: previous.status } : {},
|
|
1981
2083
|
content: this.mergeSnapshotAssistantContent(previous.content, snapshot.content, snapshotHasReasoning, snapshotHasActivity, /* @__PURE__ */ new Set(), true)
|
|
1982
2084
|
} : snapshot;
|
|
1983
2085
|
}
|
|
@@ -2082,7 +2184,10 @@ var AgUiThreadController = class {
|
|
|
2082
2184
|
const wasPersisted = this.persistedHistoryIds.has(messageId);
|
|
2083
2185
|
const update = history.update;
|
|
2084
2186
|
if (update !== void 0 && (wasPersisted || this.snapshotHistoryIds.has(messageId) || this.historyWrites.pending(messageId) !== void 0)) {
|
|
2085
|
-
const write = this.historyWrites.chain(messageId, () =>
|
|
2187
|
+
const write = this.historyWrites.chain(messageId, () => this.unappendedHistoryIds.has(messageId) ? this.appendOnce(history, messageId, {
|
|
2188
|
+
parentId,
|
|
2189
|
+
message
|
|
2190
|
+
}) : update.call(history, {
|
|
2086
2191
|
parentId,
|
|
2087
2192
|
message
|
|
2088
2193
|
}));
|
|
@@ -2109,12 +2214,17 @@ var AgUiThreadController = class {
|
|
|
2109
2214
|
this.logger.error?.("[agui] failed to append history entry", error);
|
|
2110
2215
|
});
|
|
2111
2216
|
}
|
|
2217
|
+
async appendOnce(history, messageId, item) {
|
|
2218
|
+
await history.append(item);
|
|
2219
|
+
this.unappendedHistoryIds.delete(messageId);
|
|
2220
|
+
}
|
|
2112
2221
|
appendHistoryItem(parentId, message) {
|
|
2113
2222
|
if (!this.history || this.persistedHistoryIds.has(message.id)) return;
|
|
2114
2223
|
const pending = this.historyWrites.pending(message.id);
|
|
2115
2224
|
if (pending) return pending;
|
|
2116
|
-
const
|
|
2117
|
-
|
|
2225
|
+
const history = this.history;
|
|
2226
|
+
this.unappendedHistoryIds.add(message.id);
|
|
2227
|
+
const write = this.historyWrites.chain(message.id, () => this.appendOnce(history, message.id, {
|
|
2118
2228
|
parentId,
|
|
2119
2229
|
message
|
|
2120
2230
|
}));
|