@assistant-ui/react-ag-ui 0.1.4 → 0.1.6
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 +2 -0
- package/dist/runtime/AgUiThreadController.d.ts.map +1 -1
- package/dist/runtime/AgUiThreadController.js +93 -13
- package/dist/runtime/AgUiThreadController.js.map +1 -1
- package/dist/runtime/adapter/run-aggregator.d.ts +37 -31
- package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
- package/dist/runtime/adapter/run-aggregator.js +363 -218
- package/dist/runtime/adapter/run-aggregator.js.map +1 -1
- package/dist/useAgUiRuntime.d.ts.map +1 -1
- package/dist/useAgUiRuntime.js +1 -0
- package/dist/useAgUiRuntime.js.map +1 -1
- package/package.json +2 -2
- package/src/runtime/AgUiThreadController.disconnect.test.ts +198 -3
- package/src/runtime/AgUiThreadController.replay.test.ts +57 -0
- package/src/runtime/AgUiThreadController.snapshot-head-history.test.ts +34 -2
- package/src/runtime/AgUiThreadController.snapshot-head-move.test.ts +510 -0
- package/src/runtime/AgUiThreadController.ts +190 -28
- package/src/runtime/adapter/run-aggregator.routing.test.ts +359 -0
- package/src/runtime/adapter/run-aggregator.ts +539 -258
- package/src/useAgUiRuntime.cloud-run-leases.test.tsx +85 -7
- package/src/useAgUiRuntime.ts +1 -0
|
@@ -81,6 +81,8 @@ export declare class AgUiThreadController {
|
|
|
81
81
|
reload(parentId: string | null, config?: {
|
|
82
82
|
runConfig?: RunConfig;
|
|
83
83
|
}): Promise<void>;
|
|
84
|
+
/** Deletes a message that has no replies under it, and its stored history entry. */
|
|
85
|
+
deleteMessage(messageId: string): Promise<void>;
|
|
84
86
|
cancel(): Promise<void>;
|
|
85
87
|
private abortActiveRun;
|
|
86
88
|
private supersedeActiveRun;
|
|
@@ -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":"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"}
|
|
@@ -65,6 +65,10 @@ const FALLBACK_USER_STATUS = {
|
|
|
65
65
|
type: "complete",
|
|
66
66
|
reason: "unknown"
|
|
67
67
|
};
|
|
68
|
+
const snapshotRecordToolCallIds = (record) => {
|
|
69
|
+
const toolCalls = record?.toolCalls;
|
|
70
|
+
return new Set(Array.isArray(toolCalls) ? toolCalls.map((call) => call?.id).filter((id) => typeof id === "string") : []);
|
|
71
|
+
};
|
|
68
72
|
const textOf = (content) => content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
69
73
|
/**
|
|
70
74
|
* Swaps `content`'s text parts, in order, for `source`'s. A text part `source`
|
|
@@ -374,6 +378,19 @@ var AgUiThreadController = class {
|
|
|
374
378
|
this.maybeAutoCancelPendingToolCalls();
|
|
375
379
|
await this.startRun(parentId, config.runConfig);
|
|
376
380
|
}
|
|
381
|
+
/** Deletes a message that has no replies under it, and its stored history entry. */
|
|
382
|
+
async deleteMessage(messageId) {
|
|
383
|
+
const item = this.session.tryGetMessage(messageId);
|
|
384
|
+
if (!item) return;
|
|
385
|
+
const parentId = item.parentId ?? null;
|
|
386
|
+
this.session.deleteMessage(messageId, parentId);
|
|
387
|
+
this.snapshotHistoryIds.delete(messageId);
|
|
388
|
+
this.publishUpdate();
|
|
389
|
+
await this.history?.delete?.([{
|
|
390
|
+
parentId,
|
|
391
|
+
message: item.message
|
|
392
|
+
}]);
|
|
393
|
+
}
|
|
377
394
|
async cancel() {
|
|
378
395
|
this.dispatch({ type: "historyMutationAdvanced" });
|
|
379
396
|
this.abortActiveRun();
|
|
@@ -1004,6 +1021,9 @@ var AgUiThreadController = class {
|
|
|
1004
1021
|
let settlingRun = false;
|
|
1005
1022
|
let latestSnapshot;
|
|
1006
1023
|
let snapshotToolCallIds = /* @__PURE__ */ new Set();
|
|
1024
|
+
const snapshotResultIds = /* @__PURE__ */ new Set();
|
|
1025
|
+
let announcingMove = false;
|
|
1026
|
+
const retainedSnapshots = /* @__PURE__ */ new Map();
|
|
1007
1027
|
const ensureAssistant = (allowRecreate = false) => {
|
|
1008
1028
|
const cached = assistantMessageId;
|
|
1009
1029
|
if (cached !== void 0 && this.session.tryGetMessage(cached)) return cached;
|
|
@@ -1027,6 +1047,7 @@ var AgUiThreadController = class {
|
|
|
1027
1047
|
}
|
|
1028
1048
|
for (const [messageId, openToolCallIds] of heldMessages) {
|
|
1029
1049
|
const existing = this.session.tryGetMessage(messageId);
|
|
1050
|
+
if (!canWaitForTools && this.isTerminalStatus(existing?.message.status)) continue;
|
|
1030
1051
|
if (existing) this.markPendingAssistantHistory(messageId, existing.parentId);
|
|
1031
1052
|
let requiresToolResult = false;
|
|
1032
1053
|
if (this.session.updateMessage(messageId, (message) => {
|
|
@@ -1203,6 +1224,39 @@ var AgUiThreadController = class {
|
|
|
1203
1224
|
}
|
|
1204
1225
|
} else assistantCollided = true;
|
|
1205
1226
|
};
|
|
1227
|
+
const applyRetainedUpdate = (update, { messageId, streaming, openToolCallIds }) => {
|
|
1228
|
+
const item = this.session.tryGetMessage(messageId);
|
|
1229
|
+
if (item?.message.role !== "assistant") return;
|
|
1230
|
+
this.markPendingAssistantHistory(messageId, item.parentId);
|
|
1231
|
+
let snapshot = retainedSnapshots.get(messageId);
|
|
1232
|
+
if (!snapshot) {
|
|
1233
|
+
snapshot = {
|
|
1234
|
+
message: item.message,
|
|
1235
|
+
toolCallIds: new Set(Array.from(iterateToolCallParts(item.message.content), (part) => part.toolCallId))
|
|
1236
|
+
};
|
|
1237
|
+
retainedSnapshots.set(messageId, snapshot);
|
|
1238
|
+
}
|
|
1239
|
+
const content = update.content !== void 0 ? this.mergeSnapshotAssistantContent(snapshot.message.content, update.content, update.content.some((part) => part.type === "reasoning"), update.content.some(isActivityPart), snapshot.toolCallIds) : update.content;
|
|
1240
|
+
const unresolved = [.../* @__PURE__ */ new Set([...openToolCallIds, ...Array.from(iterateToolCallParts(content ?? item.message.content)).filter((part) => snapshot.toolCallIds.has(part.toolCallId) && !isResolvedToolCall(part)).map((part) => part.toolCallId)])].filter((id) => !snapshotResultIds.has(id));
|
|
1241
|
+
const held = streaming || unresolved.length > 0 || settlingRun && heldMessages.has(messageId);
|
|
1242
|
+
if (held) heldMessages.set(messageId, new Set(unresolved));
|
|
1243
|
+
else heldMessages.delete(messageId);
|
|
1244
|
+
this.updateAssistantMessage(messageId, {
|
|
1245
|
+
...update,
|
|
1246
|
+
...content !== void 0 ? { content } : {},
|
|
1247
|
+
status: held ? { type: "running" } : {
|
|
1248
|
+
type: "complete",
|
|
1249
|
+
reason: "unknown"
|
|
1250
|
+
}
|
|
1251
|
+
});
|
|
1252
|
+
const current = this.session.tryGetMessage(messageId)?.message;
|
|
1253
|
+
if (current?.role === "assistant") retainedSnapshots.set(messageId, {
|
|
1254
|
+
...snapshot,
|
|
1255
|
+
message: current
|
|
1256
|
+
});
|
|
1257
|
+
const head = assistantMessageId === void 0 ? void 0 : this.session.tryGetMessage(assistantMessageId)?.message;
|
|
1258
|
+
if (!settlingRun && !announcingMove && head?.role === "assistant" && head.status?.type !== "running" && !runStartMessageIds.has(head.id) && !aggregator.isRetained(head.id)) this.updateAssistantMessage(head.id, { status: { type: "running" } });
|
|
1259
|
+
};
|
|
1206
1260
|
const abortController = new AbortController();
|
|
1207
1261
|
const abortSignal = abortController.signal;
|
|
1208
1262
|
const aggregator = new RunAggregator({
|
|
@@ -1248,10 +1302,13 @@ var AgUiThreadController = class {
|
|
|
1248
1302
|
const current = assistantMessageId ? this.session.tryGetMessage(assistantMessageId)?.message : void 0;
|
|
1249
1303
|
latestSnapshot = !settlingRun && current?.role === "assistant" && current.id === latestSnapshot?.id ? current : void 0;
|
|
1250
1304
|
},
|
|
1305
|
+
onRetainedMessage: applyRetainedUpdate,
|
|
1306
|
+
canRetainMessage: (messageId) => messageId !== assistantMessageId && messageId !== this.session.headId && !runStartMessageIds.has(messageId) && this.session.tryGetMessage(messageId)?.message.role === "assistant",
|
|
1251
1307
|
onServerMessageId: (serverId) => {
|
|
1252
1308
|
adoptServerMessageId(serverId, false);
|
|
1253
1309
|
},
|
|
1254
1310
|
onTextMessageStart: (serverId, openToolCallIds) => {
|
|
1311
|
+
const outgoingId = assistantMessageId !== void 0 && !assistantCollided && !runStartMessageIds.has(assistantMessageId) && !replayContexts.has(assistantMessageId) && this.session.hasMessage(assistantMessageId) ? assistantMessageId : void 0;
|
|
1255
1312
|
const owners = this.getTrailingAssistantTurn().filter((message) => replayContexts.has(message.id));
|
|
1256
1313
|
const toolOwners = indexReplayToolOwners(owners);
|
|
1257
1314
|
const frameOpenIds = openToolCallIds.filter((id) => {
|
|
@@ -1268,6 +1325,7 @@ var AgUiThreadController = class {
|
|
|
1268
1325
|
}
|
|
1269
1326
|
frameOwnerIds.clear();
|
|
1270
1327
|
adoptServerMessageId(serverId, true, frameOpenIds);
|
|
1328
|
+
return outgoingId;
|
|
1271
1329
|
}
|
|
1272
1330
|
});
|
|
1273
1331
|
const settleRunSubagents = (status) => {
|
|
@@ -1303,11 +1361,16 @@ var AgUiThreadController = class {
|
|
|
1303
1361
|
if (!assistantCollided && candidateContexts.size) accountedResultIds.add(event.toolCallId);
|
|
1304
1362
|
for (const openToolCallIds of heldMessages.values()) openToolCallIds.delete(event.toolCallId);
|
|
1305
1363
|
}
|
|
1364
|
+
if (event.type === "MESSAGES_SNAPSHOT") for (const record of event.messages) {
|
|
1365
|
+
if (record?.role !== "tool" || typeof record.toolCallId !== "string") continue;
|
|
1366
|
+
snapshotResultIds.add(record.toolCallId);
|
|
1367
|
+
for (const openToolCallIds of heldMessages.values()) openToolCallIds.delete(record.toolCallId);
|
|
1368
|
+
}
|
|
1306
1369
|
settlingRun = event.type === "RUN_FINISHED" || event.type === "RUN_ERROR" || event.type === "RUN_CANCELLED";
|
|
1307
1370
|
if (settlingRun) persistRunAssistants(true);
|
|
1308
1371
|
const beforeSnapshot = event.type === "MESSAGES_SNAPSHOT" ? this.session.getMessages() : [];
|
|
1309
1372
|
try {
|
|
1310
|
-
const nextAssistantMessageId = this.handleEvent(aggregator, event, assistantMessageId, joinStrategy, runStartMessageIds, hasRunUserBoundary, candidateContexts.size ? reconcileReplaySnapshot : void 0);
|
|
1373
|
+
const nextAssistantMessageId = this.handleEvent(aggregator, event, assistantMessageId, joinStrategy, runStartMessageIds, hasRunUserBoundary, heldMessages, candidateContexts.size ? reconcileReplaySnapshot : void 0);
|
|
1311
1374
|
if (event.type === "MESSAGES_SNAPSHOT") {
|
|
1312
1375
|
const previousIds = new Set(beforeSnapshot.map(({ id }) => id));
|
|
1313
1376
|
for (const message of this.session.getMessages()) {
|
|
@@ -1331,11 +1394,26 @@ var AgUiThreadController = class {
|
|
|
1331
1394
|
const imported = assistantMessageId ? this.session.tryGetMessage(assistantMessageId)?.message : void 0;
|
|
1332
1395
|
const source = event.messages.find((message) => message?.role === "assistant" && message.id === imported?.id);
|
|
1333
1396
|
latestSnapshot = imported?.role === "assistant" && source ? imported : void 0;
|
|
1334
|
-
snapshotToolCallIds =
|
|
1397
|
+
snapshotToolCallIds = snapshotRecordToolCallIds(source);
|
|
1335
1398
|
if (!replayEnded && assistantMessageId === void 0) {
|
|
1336
1399
|
const tail = this.session.getMessages().at(-1);
|
|
1337
1400
|
snapshotAssistantId = tail?.role === "assistant" ? tail.id : void 0;
|
|
1338
1401
|
}
|
|
1402
|
+
for (const record of event.messages) {
|
|
1403
|
+
if (record?.role !== "assistant" || !aggregator.isRetained(record.id)) continue;
|
|
1404
|
+
const message = this.session.tryGetMessage(record.id)?.message;
|
|
1405
|
+
if (message?.role !== "assistant") continue;
|
|
1406
|
+
retainedSnapshots.set(record.id, {
|
|
1407
|
+
message,
|
|
1408
|
+
toolCallIds: snapshotRecordToolCallIds(record)
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
announcingMove = true;
|
|
1412
|
+
try {
|
|
1413
|
+
aggregator.announceRetained();
|
|
1414
|
+
} finally {
|
|
1415
|
+
announcingMove = false;
|
|
1416
|
+
}
|
|
1339
1417
|
}
|
|
1340
1418
|
if (event.type === "RUN_ERROR") settleRunSubagents({
|
|
1341
1419
|
type: "incomplete",
|
|
@@ -1416,7 +1494,8 @@ var AgUiThreadController = class {
|
|
|
1416
1494
|
}
|
|
1417
1495
|
} finally {
|
|
1418
1496
|
const current = assistantMessageId ? this.session.tryGetMessage(assistantMessageId)?.message : void 0;
|
|
1419
|
-
|
|
1497
|
+
const currentRunning = current?.role === "assistant" && current.status?.type === "running";
|
|
1498
|
+
if (this.abortController === abortController && (currentRunning || heldMessages.size > 0)) {
|
|
1420
1499
|
persistRunAssistants(true);
|
|
1421
1500
|
const status = {
|
|
1422
1501
|
type: "incomplete",
|
|
@@ -1424,7 +1503,7 @@ var AgUiThreadController = class {
|
|
|
1424
1503
|
error: "The connection ended before the answer finished."
|
|
1425
1504
|
};
|
|
1426
1505
|
settleHeldMessages(status);
|
|
1427
|
-
applyUpdate({
|
|
1506
|
+
if (currentRunning) applyUpdate({
|
|
1428
1507
|
status,
|
|
1429
1508
|
content: settleNestedContent(current.content, status)
|
|
1430
1509
|
});
|
|
@@ -1878,7 +1957,7 @@ var AgUiThreadController = class {
|
|
|
1878
1957
|
custom: incoming.custom ? mergeAgUiNamespace(current.custom, incoming.custom) : current.custom
|
|
1879
1958
|
};
|
|
1880
1959
|
}
|
|
1881
|
-
handleEvent(aggregator, event, activeAssistantId, joinStrategy, runStartMessageIds, hasRunUserBoundary, reconcileSnapshot) {
|
|
1960
|
+
handleEvent(aggregator, event, activeAssistantId, joinStrategy, runStartMessageIds, hasRunUserBoundary, heldMessages, reconcileSnapshot) {
|
|
1882
1961
|
if (event.type === "SUBAGENT_STARTED" && !this.subagentParentToolCallIds.has(event.subagentRunId)) this.subagentParentToolCallIds.set(event.subagentRunId, event.parentToolCallId);
|
|
1883
1962
|
switch (event.type) {
|
|
1884
1963
|
case "STATE_SNAPSHOT":
|
|
@@ -1906,23 +1985,24 @@ var AgUiThreadController = class {
|
|
|
1906
1985
|
const previousHeadId = this.session.headId;
|
|
1907
1986
|
const activeAssistant = activeAssistantId === void 0 ? void 0 : this.session.tryGetMessage(activeAssistantId)?.message;
|
|
1908
1987
|
const hasActiveText = activeAssistant?.role === "assistant" && activeAssistant.content.some((part) => part.type === "text");
|
|
1909
|
-
this.importMessagesSnapshot(event.messages, activeAssistantId, joinStrategy, runStartMessageIds, hasRunUserBoundary, reconcileSnapshot);
|
|
1988
|
+
this.importMessagesSnapshot(event.messages, activeAssistantId, joinStrategy, runStartMessageIds, hasRunUserBoundary, heldMessages, reconcileSnapshot);
|
|
1910
1989
|
const headId = this.session.headId;
|
|
1911
1990
|
const head = headId === null ? void 0 : this.session.tryGetMessage(headId)?.message;
|
|
1912
1991
|
const hasNewPendingToolCallAnswer = head?.role === "assistant" && !runStartMessageIds.has(head.id) && head.status?.type === "requires-action" && head.status.reason === "tool-calls";
|
|
1913
1992
|
if (headId !== previousHeadId && (hasActiveText || hasNewPendingToolCallAnswer)) {
|
|
1914
1993
|
const nextActiveAssistantId = head?.role === "assistant" ? headId ?? void 0 : void 0;
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1994
|
+
const previousActiveId = activeAssistantId !== nextActiveAssistantId ? activeAssistantId : void 0;
|
|
1995
|
+
const retained = nextActiveAssistantId !== void 0 && joinStrategy !== "concat-content" && aggregator.rebaseMessage(nextActiveAssistantId, previousActiveId);
|
|
1996
|
+
if (previousActiveId && !retained) {
|
|
1997
|
+
const previous = this.session.tryGetMessage(previousActiveId)?.message;
|
|
1998
|
+
if (previous?.role === "assistant" && previous.status?.type === "running") this.updateAssistantMessage(previousActiveId, {
|
|
1918
1999
|
status: FALLBACK_USER_STATUS,
|
|
1919
2000
|
content: settleNestedContent(previous.content, FALLBACK_USER_STATUS)
|
|
1920
2001
|
});
|
|
1921
2002
|
}
|
|
1922
2003
|
activeAssistantId = nextActiveAssistantId;
|
|
1923
|
-
if (activeAssistantId && joinStrategy !== "concat-content") aggregator.rebaseMessage(activeAssistantId);
|
|
1924
|
-
if (hasNewPendingToolCallAnswer && head) this.updateAssistantMessage(head.id, { status: { type: "running" } });
|
|
1925
2004
|
}
|
|
2005
|
+
if (hasNewPendingToolCallAnswer && head && head.id === activeAssistantId) this.updateAssistantMessage(head.id, { status: { type: "running" } });
|
|
1926
2006
|
this.updateActiveAssistantState(activeAssistantId);
|
|
1927
2007
|
break;
|
|
1928
2008
|
}
|
|
@@ -2051,7 +2131,7 @@ var AgUiThreadController = class {
|
|
|
2051
2131
|
if (this.maybeCompleteAfterToolResults(messageId)) return;
|
|
2052
2132
|
this.persistSettledAssistant(messageId);
|
|
2053
2133
|
}
|
|
2054
|
-
importMessagesSnapshot(rawMessages, activeAssistantId, joinStrategy, runStartMessageIds, hasRunUserBoundary, reconcileSnapshot) {
|
|
2134
|
+
importMessagesSnapshot(rawMessages, activeAssistantId, joinStrategy, runStartMessageIds, hasRunUserBoundary, heldMessages, reconcileSnapshot) {
|
|
2055
2135
|
try {
|
|
2056
2136
|
const activeAssistantItem = activeAssistantId ? this.session.tryGetMessage(activeAssistantId) : void 0;
|
|
2057
2137
|
const activeMessage = activeAssistantItem?.message;
|
|
@@ -2074,7 +2154,7 @@ var AgUiThreadController = class {
|
|
|
2074
2154
|
if (convertedMessage.role === "assistant") {
|
|
2075
2155
|
const previous = existing?.role === "assistant" ? existing : void 0;
|
|
2076
2156
|
const snapshot = reconcileSnapshot?.(convertedMessage, previous) ?? convertedMessage;
|
|
2077
|
-
const preservesRunningStatus = convertedMessage.id === activeAssistantId && previous?.status?.type === "running" && snapshot.status?.type === "requires-action" && snapshot.status.reason === "tool-calls";
|
|
2157
|
+
const preservesRunningStatus = (convertedMessage.id === activeAssistantId || heldMessages.has(convertedMessage.id)) && previous?.status?.type === "running" && snapshot.status?.type === "requires-action" && snapshot.status.reason === "tool-calls";
|
|
2078
2158
|
const previousToolCallIds = new Set(Array.from(iterateToolCallParts(previous?.content ?? []), (call) => call.toolCallId));
|
|
2079
2159
|
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));
|
|
2080
2160
|
converted[index] = previous ? {
|