@assistant-ui/react-ag-ui 0.0.45 → 0.0.46
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 -0
- package/dist/runtime/AgUiThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtime/AgUiThreadRuntimeCore.js +83 -25
- package/dist/runtime/AgUiThreadRuntimeCore.js.map +1 -1
- package/dist/runtime/adapter/conversions.d.ts.map +1 -1
- package/dist/runtime/adapter/conversions.js +12 -13
- package/dist/runtime/adapter/conversions.js.map +1 -1
- package/dist/runtime/adapter/run-aggregator.d.ts +3 -1
- package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
- package/dist/runtime/adapter/run-aggregator.js +13 -5
- package/dist/runtime/adapter/run-aggregator.js.map +1 -1
- package/dist/runtime/event-parser.d.ts.map +1 -1
- package/dist/runtime/event-parser.js +5 -2
- package/dist/runtime/event-parser.js.map +1 -1
- package/dist/runtime/mcp-tool-result.d.ts +11 -0
- package/dist/runtime/mcp-tool-result.d.ts.map +1 -0
- package/dist/runtime/mcp-tool-result.js +20 -0
- package/dist/runtime/mcp-tool-result.js.map +1 -0
- package/dist/runtime/types.d.ts +2 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/runtime/AgUiThreadRuntimeCore.ts +157 -39
- package/src/runtime/adapter/conversions.ts +18 -16
- package/src/runtime/adapter/run-aggregator.ts +17 -4
- package/src/runtime/event-parser.ts +4 -1
- package/src/runtime/mcp-tool-result.ts +26 -0
- package/src/runtime/types.ts +2 -0
|
@@ -87,6 +87,7 @@ declare class AgUiThreadRuntimeCore {
|
|
|
87
87
|
submitInterruptResponses(responses: readonly AgUiResumeEntry[]): Promise<void>;
|
|
88
88
|
steerAway(message: CreateAppendMessage, responses?: readonly AgUiResumeEntry[]): Promise<void>;
|
|
89
89
|
private resolveSteerAwayResume;
|
|
90
|
+
private collectInterruptResponses;
|
|
90
91
|
private toAppendMessage;
|
|
91
92
|
private clearPendingInterrupts;
|
|
92
93
|
findMessageIdForToolCall(toolCallId: string): string | undefined;
|
|
@@ -113,6 +114,7 @@ declare class AgUiThreadRuntimeCore {
|
|
|
113
114
|
private mergeAssistantMetadata;
|
|
114
115
|
private handleEvent;
|
|
115
116
|
private applyCrossRunToolResult;
|
|
117
|
+
private applyCrossRunActivitySnapshot;
|
|
116
118
|
private importMessagesSnapshot;
|
|
117
119
|
private toThreadMessage;
|
|
118
120
|
private isTerminalStatus;
|
|
@@ -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":";;;;;;KAqDK,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;;cAKW;UACH;UACA;UACA;UACA;UACA;UACA;mBACS;UAET;mBACS;UACT;UACA;UACA;UACA;UACA;UACA;UACA;mBACS;mBACA;UACT;UACA;UACA;EAEI,YAAA,SAAS;EAYrB,cAAc,SAAS,KAAK;EAW5B,cAAc,SAAS;EAIvB;EAIA,wBAAwB;EAIxB,wBAAwB;UAmBhB;UAQA;UAUA;UAIA;UAQA;UAQA;UAMA;UAKA;UAKA;UAKA;EAYR,YAAY;EAIZ;MAII;EAIJ,mBAAmB;EA2Cb,OAAO,SAAS,gBAAgB;UAW9B;UAQA;EAiBF,KAAK,SAAS,gBAAgB;EAI9B,OACJ,yBACA;IAAU,YAAY;MACrB;EAMG,UAAU;EAKV,OAAO,QAAQ,kBAAkB;EAUjC,kBAAkB,mBAAmB,kBAAkB;UAwBrD;UAOA;EAgBR;IACE;IACA,qBAAqB;;EAavB;IACE;IACA;;EAcI,yBACJ,oBAAoB,oBACnB;EAoDG,UACJ,SAAS,qBACT,qBAAqB,oBACpB;UAyCK;UAkBA;UAiCA;UA0BA;EA+BR,yBAAyB;UAkBjB;EAiBR,cAAc,SAAS;UA4Bf;UAYA;UA6BA;EAMR,sBAAsB,mBAAmB;UAgDjC;EAgER,kBAAkB,OAAO;EAKzB,SACE,MACI,sBACE,MAAM,kCAAkC;EAOhD;UAKc;UAkJA;UAyDN;UA6BA;UAqBA;UAKA;UAOA;UAuBA;UA2CA;UAiDA;UA4BA;UA6BA;UA4DA;UAuEA;UA8DA;UAwBA;UAQA;UAIA;UAKA;UAIA;UAQA;UAWA"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { AG_UI_METADATA_NAMESPACE, RunAggregator, tryParseJSON } from "./adapter/run-aggregator.js";
|
|
2
|
+
import { AG_UI_METADATA_NAMESPACE, RunAggregator, isPlainObject, tryParseJSON } from "./adapter/run-aggregator.js";
|
|
3
3
|
import { fromAgUiMessages, toAgUiMessages, toAgUiTools } from "./adapter/conversions.js";
|
|
4
4
|
import { createAgUiSubscriber } from "./adapter/subscriber.js";
|
|
5
5
|
import { MessageRepository } from "@assistant-ui/core/internal";
|
|
6
|
-
import { fromThreadMessageLike, generateId } from "@assistant-ui/core";
|
|
6
|
+
import { fromThreadMessageLike, generateId, isMcpAppUri } from "@assistant-ui/core";
|
|
7
7
|
import jsonpatch from "fast-json-patch";
|
|
8
8
|
//#region src/runtime/AgUiThreadRuntimeCore.ts
|
|
9
9
|
const optimisticPrefix = "__optimistic__";
|
|
@@ -259,19 +259,10 @@ var AgUiThreadRuntimeCore = class {
|
|
|
259
259
|
async submitInterruptResponses(responses) {
|
|
260
260
|
const pending = this.getPendingInterrupts();
|
|
261
261
|
if (!pending) throw new Error("[agui] submitInterruptResponses: no pending interrupts on this thread");
|
|
262
|
-
const responsesById =
|
|
263
|
-
for (const entry of responses) {
|
|
264
|
-
if (!entry || typeof entry.interruptId !== "string") throw new Error("[agui] submitInterruptResponses: every entry must have an interruptId");
|
|
265
|
-
if (entry.status !== "resolved" && entry.status !== "cancelled") throw new Error(`[agui] submitInterruptResponses: invalid status "${entry.status}" for interrupt ${entry.interruptId}`);
|
|
266
|
-
if (responsesById.has(entry.interruptId)) throw new Error(`[agui] submitInterruptResponses: duplicate response for interrupt ${entry.interruptId}`);
|
|
267
|
-
responsesById.set(entry.interruptId, entry);
|
|
268
|
-
}
|
|
262
|
+
const responsesById = this.collectInterruptResponses("submitInterruptResponses", pending.interrupts, responses);
|
|
269
263
|
const openIds = pending.interrupts.map((i) => i.id);
|
|
270
264
|
const missing = openIds.filter((id) => !responsesById.has(id));
|
|
271
265
|
if (missing.length > 0) throw new Error(`[agui] submitInterruptResponses: missing responses for open interrupts: ${missing.join(", ")}`);
|
|
272
|
-
const known = new Set(openIds);
|
|
273
|
-
const unknownIds = [...responsesById.keys()].filter((id) => !known.has(id));
|
|
274
|
-
if (unknownIds.length > 0) throw new Error(`[agui] submitInterruptResponses: unknown interrupt ids: ${unknownIds.join(", ")}`);
|
|
275
266
|
const now = Date.now();
|
|
276
267
|
for (const interrupt of pending.interrupts) {
|
|
277
268
|
if (!interrupt.expiresAt) continue;
|
|
@@ -310,20 +301,23 @@ var AgUiThreadRuntimeCore = class {
|
|
|
310
301
|
await this.startRun(threadMessageId, normalized.runConfig, resume);
|
|
311
302
|
}
|
|
312
303
|
resolveSteerAwayResume(interrupts, responses) {
|
|
313
|
-
const
|
|
314
|
-
|
|
304
|
+
const responsesById = this.collectInterruptResponses("steerAway", interrupts, responses ?? []);
|
|
305
|
+
return interrupts.map((interrupt) => responsesById.get(interrupt.id) ?? {
|
|
306
|
+
interruptId: interrupt.id,
|
|
307
|
+
status: "cancelled"
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
collectInterruptResponses(method, interrupts, responses) {
|
|
311
|
+
const known = new Set(interrupts.map((interrupt) => interrupt.id));
|
|
315
312
|
const responsesById = /* @__PURE__ */ new Map();
|
|
316
|
-
for (const entry of responses
|
|
317
|
-
if (!entry || typeof entry.interruptId !== "string") throw new Error(
|
|
318
|
-
if (entry.status !== "resolved" && entry.status !== "cancelled") throw new Error(`[agui]
|
|
319
|
-
if (!known.has(entry.interruptId)) throw new Error(`[agui]
|
|
320
|
-
if (responsesById.has(entry.interruptId)) throw new Error(`[agui]
|
|
313
|
+
for (const entry of responses) {
|
|
314
|
+
if (!entry || typeof entry.interruptId !== "string") throw new Error(`[agui] ${method}: every entry must have an interruptId`);
|
|
315
|
+
if (entry.status !== "resolved" && entry.status !== "cancelled") throw new Error(`[agui] ${method}: invalid status "${entry.status}" for interrupt ${entry.interruptId}`);
|
|
316
|
+
if (!known.has(entry.interruptId)) throw new Error(`[agui] ${method}: unknown interrupt id ${entry.interruptId}`);
|
|
317
|
+
if (responsesById.has(entry.interruptId)) throw new Error(`[agui] ${method}: duplicate response for interrupt ${entry.interruptId}`);
|
|
321
318
|
responsesById.set(entry.interruptId, entry);
|
|
322
319
|
}
|
|
323
|
-
return
|
|
324
|
-
interruptId: id,
|
|
325
|
-
status: "cancelled"
|
|
326
|
-
});
|
|
320
|
+
return responsesById;
|
|
327
321
|
}
|
|
328
322
|
toAppendMessage(message) {
|
|
329
323
|
if (typeof message === "string") return {
|
|
@@ -898,6 +892,18 @@ var AgUiThreadRuntimeCore = class {
|
|
|
898
892
|
}
|
|
899
893
|
aggregator.handle(event);
|
|
900
894
|
return;
|
|
895
|
+
case "ACTIVITY_SNAPSHOT": {
|
|
896
|
+
const toolCallId = event.content["toolCallId"];
|
|
897
|
+
if (event.activityType === "mcp-apps" && typeof toolCallId === "string" && !aggregator.hasToolCall(toolCallId)) {
|
|
898
|
+
const messageId = this.findMessageIdForToolCall(toolCallId);
|
|
899
|
+
if (messageId !== void 0) {
|
|
900
|
+
this.applyCrossRunActivitySnapshot(messageId, toolCallId, event);
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
aggregator.handle(event);
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
901
907
|
default: aggregator.handle(event);
|
|
902
908
|
}
|
|
903
909
|
}
|
|
@@ -909,10 +915,23 @@ var AgUiThreadRuntimeCore = class {
|
|
|
909
915
|
const content = assistant.content.map((part) => {
|
|
910
916
|
if (part.type !== "tool-call" || part.toolCallId !== event.toolCallId) return part;
|
|
911
917
|
matchedToolCall = true;
|
|
918
|
+
if (part.mcp?.app !== void 0 && isPlainObject(part.result) && Array.isArray(part.result["content"])) return {
|
|
919
|
+
...part,
|
|
920
|
+
...part.modelContent === void 0 && event.content ? { modelContent: [{
|
|
921
|
+
type: "text",
|
|
922
|
+
text: event.content
|
|
923
|
+
}] } : {},
|
|
924
|
+
...part.isError === void 0 ? typeof event.mcpResult?.isError === "boolean" ? { isError: event.mcpResult.isError } : event.role === "tool" ? { isError: false } : {} : {},
|
|
925
|
+
...event.messageId ? { unstable_toolMessageId: event.messageId } : {}
|
|
926
|
+
};
|
|
912
927
|
return {
|
|
913
928
|
...part,
|
|
914
|
-
result: tryParseJSON(event.content ?? ""),
|
|
915
|
-
...event.
|
|
929
|
+
result: event.mcpResult ?? tryParseJSON(event.content ?? ""),
|
|
930
|
+
...event.mcpResult !== void 0 ? { modelContent: [{
|
|
931
|
+
type: "text",
|
|
932
|
+
text: event.content
|
|
933
|
+
}] } : {},
|
|
934
|
+
...typeof event.mcpResult?.isError === "boolean" ? { isError: event.mcpResult.isError } : event.role === "tool" ? { isError: false } : {},
|
|
916
935
|
...event.messageId ? { unstable_toolMessageId: event.messageId } : {}
|
|
917
936
|
};
|
|
918
937
|
});
|
|
@@ -925,6 +944,45 @@ var AgUiThreadRuntimeCore = class {
|
|
|
925
944
|
this.notifyUpdate();
|
|
926
945
|
this.maybeCompleteAfterToolResults(messageId);
|
|
927
946
|
}
|
|
947
|
+
applyCrossRunActivitySnapshot(messageId, toolCallId, event) {
|
|
948
|
+
const resourceUri = event.content["resourceUri"];
|
|
949
|
+
if (typeof resourceUri !== "string" || !isMcpAppUri(resourceUri)) return;
|
|
950
|
+
const serverId = event.content["serverId"];
|
|
951
|
+
const serverHash = event.content["serverHash"];
|
|
952
|
+
const appServerId = typeof serverId === "string" && serverId.length > 0 ? serverId : typeof serverHash === "string" && serverHash.length > 0 ? serverHash : void 0;
|
|
953
|
+
const result = event.content["result"];
|
|
954
|
+
if (!this.updateMessage(messageId, (message) => {
|
|
955
|
+
if (message.role !== "assistant") return message;
|
|
956
|
+
const assistant = message;
|
|
957
|
+
let matchedToolCall = false;
|
|
958
|
+
const content = assistant.content.map((part) => {
|
|
959
|
+
if (part.type !== "tool-call" || part.toolCallId !== toolCallId) return part;
|
|
960
|
+
matchedToolCall = true;
|
|
961
|
+
return {
|
|
962
|
+
...part,
|
|
963
|
+
mcp: { app: {
|
|
964
|
+
resourceUri,
|
|
965
|
+
...appServerId ? { serverId: appServerId } : {}
|
|
966
|
+
} },
|
|
967
|
+
...isPlainObject(result) ? {
|
|
968
|
+
...part.result !== void 0 && part.modelContent === void 0 ? { modelContent: [{
|
|
969
|
+
type: "text",
|
|
970
|
+
text: typeof part.result === "string" ? part.result : JSON.stringify(part.result)
|
|
971
|
+
}] } : {},
|
|
972
|
+
result,
|
|
973
|
+
isError: result["isError"] === true
|
|
974
|
+
} : {}
|
|
975
|
+
};
|
|
976
|
+
});
|
|
977
|
+
if (!matchedToolCall) return message;
|
|
978
|
+
return {
|
|
979
|
+
...assistant,
|
|
980
|
+
content
|
|
981
|
+
};
|
|
982
|
+
})) return;
|
|
983
|
+
this.notifyUpdate();
|
|
984
|
+
this.maybeCompleteAfterToolResults(messageId);
|
|
985
|
+
}
|
|
928
986
|
importMessagesSnapshot(rawMessages) {
|
|
929
987
|
try {
|
|
930
988
|
const normalized = fromAgUiMessages(rawMessages, { showThinking: this.showThinking });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgUiThreadRuntimeCore.js","names":[],"sources":["../../src/runtime/AgUiThreadRuntimeCore.ts"],"sourcesContent":["\"use client\";\n\nimport { generateId, fromThreadMessageLike } from \"@assistant-ui/core\";\nimport type {\n AddToolResultOptions,\n AppendMessage,\n CreateAppendMessage,\n AssistantRuntime,\n ChatModelRunOptions,\n ChatModelRunResult,\n ExportedMessageRepository,\n MessageStatus,\n ThreadAssistantMessage,\n ThreadHistoryAdapter,\n ThreadMessage,\n ToolCallMessagePart,\n} from \"@assistant-ui/core\";\nimport { MessageRepository } from \"@assistant-ui/core/internal\";\nimport type { AbstractAgent } from \"@ag-ui/client\";\nimport jsonpatch, { type Operation } from \"fast-json-patch\";\nimport type { Logger } from \"./logger\";\nimport type { AgUiEvent, AgUiInterrupt, AgUiResumeEntry } from \"./types\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport {\n AG_UI_METADATA_NAMESPACE,\n type AgUiCustomMetadata,\n RunAggregator,\n tryParseJSON,\n} from \"./adapter/run-aggregator\";\nimport {\n fromAgUiMessages,\n toAgUiMessages,\n toAgUiTools,\n} from \"./adapter/conversions\";\nimport { createAgUiSubscriber } from \"./adapter/subscriber\";\n\nconst optimisticPrefix = \"__optimistic__\";\nconst generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;\nconst isOptimisticId = (id: string) => id.startsWith(optimisticPrefix);\n\nconst isResolvedToolCall = (\n part: ThreadAssistantMessage[\"content\"][number],\n): boolean =>\n part.type === \"tool-call\" && \"result\" in part && part.result !== undefined;\n\nconst symbolResumeShim = Symbol(\"agui-resume-shim\");\n\ntype RunConfig = NonNullable<AppendMessage[\"runConfig\"]>;\ntype ResumeStream = (\n options: ChatModelRunOptions,\n) => AsyncGenerator<ChatModelRunResult, void, unknown>;\ntype ResumeRunConfig = {\n parentId: string | null;\n sourceId: string | null;\n runConfig: RunConfig;\n stream?: ResumeStream;\n};\n\ntype CoreOptions = {\n agent: AbstractAgent;\n logger: Logger;\n showThinking: boolean;\n autoCancelPendingToolCalls?: boolean | undefined;\n onError?: (error: Error) => void;\n onCancel?: () => void;\n history?: ThreadHistoryAdapter;\n notifyUpdate: () => void;\n};\n\nconst FALLBACK_USER_STATUS = { type: \"complete\", reason: \"unknown\" } as const;\n\nexport class AgUiThreadRuntimeCore {\n private agent: AbstractAgent;\n private logger: Logger;\n private showThinking: boolean;\n private autoCancelPendingToolCalls: boolean | undefined;\n private onError: ((error: Error) => void) | undefined;\n private onCancel: (() => void) | undefined;\n private readonly notifyUpdate: () => void;\n\n private runtime: AssistantRuntime | undefined;\n private readonly repository = new MessageRepository();\n private exportedRepository: ExportedMessageRepository | undefined;\n private isRunningFlag = false;\n private abortController: AbortController | null = null;\n private stateSnapshot: ReadonlyJSONValue | undefined;\n private pendingError: Error | null = null;\n private history: ThreadHistoryAdapter | undefined;\n private lastRunConfig: RunConfig | undefined;\n private readonly assistantHistoryParents = new Map<string, string | null>();\n private readonly recordedHistoryIds = new Set<string>();\n private _isLoading = false;\n private _loadPromise: Promise<void> | undefined;\n private pendingResumeMessageId: string | null = null;\n\n constructor(options: CoreOptions) {\n this.agent = options.agent;\n this.logger = options.logger;\n this.showThinking = options.showThinking;\n this.autoCancelPendingToolCalls = options.autoCancelPendingToolCalls;\n this.onError = options.onError;\n this.onCancel = options.onCancel;\n this.history = options.history;\n this.notifyUpdate = options.notifyUpdate;\n this.installResumeShim();\n }\n\n updateOptions(options: Omit<CoreOptions, \"notifyUpdate\">) {\n this.agent = options.agent;\n this.logger = options.logger;\n this.showThinking = options.showThinking;\n this.autoCancelPendingToolCalls = options.autoCancelPendingToolCalls;\n this.onError = options.onError;\n this.onCancel = options.onCancel;\n this.history = options.history;\n this.installResumeShim();\n }\n\n attachRuntime(runtime: AssistantRuntime) {\n this.runtime = runtime;\n }\n\n detachRuntime() {\n this.runtime = undefined;\n }\n\n getMessages(): readonly ThreadMessage[] {\n return this.repository.getMessages();\n }\n\n getMessageRepository(): ExportedMessageRepository {\n if (this.exportedRepository) return this.exportedRepository;\n\n const exportedRepository = this.repository.export();\n let parentId: string | null = null;\n for (const message of this.repository.getMessages()) {\n if (message.metadata.isOptimistic) {\n exportedRepository.messages.push({ parentId, message });\n }\n parentId = message.id;\n }\n\n this.exportedRepository = {\n ...exportedRepository,\n headId: this.repository.headId,\n };\n return this.exportedRepository;\n }\n\n private tryGetMessage(messageId: string) {\n try {\n return this.repository.getMessage(messageId);\n } catch {\n return undefined;\n }\n }\n\n private tryGetMessages(\n messageId: string,\n ): readonly ThreadMessage[] | undefined {\n try {\n return this.repository.getMessages(messageId);\n } catch {\n return undefined;\n }\n }\n\n private hasMessage(messageId: string): boolean {\n return this.tryGetMessage(messageId) !== undefined;\n }\n\n private addOrUpdateMessage(\n parentId: string | null,\n message: ThreadMessage,\n ): void {\n this.repository.addOrUpdateMessage(parentId, message);\n this.exportedRepository = undefined;\n }\n\n private deleteMessage(\n messageId: string,\n replacementId?: string | null,\n ): void {\n this.repository.deleteMessage(messageId, replacementId);\n this.exportedRepository = undefined;\n }\n\n private tryDeleteMessage(messageId: string): boolean {\n if (!this.hasMessage(messageId)) return false;\n this.deleteMessage(messageId);\n return true;\n }\n\n private switchToBranch(messageId: string): void {\n this.repository.switchToBranch(messageId);\n this.exportedRepository = undefined;\n }\n\n private resetRepositoryHead(messageId: string | null): void {\n this.repository.resetHead(messageId);\n this.exportedRepository = undefined;\n }\n\n private clearRepository(): void {\n this.repository.clear();\n this.exportedRepository = undefined;\n }\n\n private updateMessage(\n messageId: string,\n updater: (message: ThreadMessage) => ThreadMessage,\n ): boolean {\n const item = this.tryGetMessage(messageId);\n if (!item) return false;\n const message = updater(item.message);\n if (message === item.message) return false;\n this.addOrUpdateMessage(item.parentId, message);\n return true;\n }\n\n getState(): ReadonlyJSONValue | undefined {\n return this.stateSnapshot;\n }\n\n isRunning(): boolean {\n return this.isRunningFlag;\n }\n\n get isLoading(): boolean {\n return this._isLoading;\n }\n\n __internal_load(): Promise<void> {\n if (this._loadPromise) return this._loadPromise;\n\n const promise = this.history?.load() ?? Promise.resolve(null);\n\n this._isLoading = true;\n\n this._loadPromise = promise\n .then(async (repo) => {\n if (!repo) return;\n\n this.applyExternalMessageRepository(repo);\n\n if (repo.state !== undefined) {\n this.loadExternalState(repo.state);\n }\n\n if (repo.unstable_resume) {\n const parentId = repo.headId ?? this.repository.headId;\n const resumeStream = this.history?.resume?.bind(this.history);\n await this.startRun(\n parentId,\n this.lastRunConfig,\n undefined,\n resumeStream,\n );\n }\n })\n .catch((error) => {\n this.logger.error?.(\"[agui] failed to load history\", error);\n this.onError?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n })\n .finally(() => {\n this._isLoading = false;\n this.notifyUpdate();\n });\n\n this.notifyUpdate();\n return this._loadPromise;\n }\n\n async append(message: AppendMessage): Promise<void> {\n const startRun = message.startRun ?? message.role === \"user\";\n if (startRun) {\n this.assertNoPendingInterrupts();\n this.maybeAutoCancelPendingToolCalls();\n }\n const threadMessageId = this.appendEntry(message);\n if (!startRun) return;\n await this.startRun(threadMessageId, message.runConfig);\n }\n\n private maybeAutoCancelPendingToolCalls(): void {\n if (this.autoCancelPendingToolCalls === false) return;\n const pending = this.getPendingToolCalls();\n if (!pending) return;\n this.cancelUnresolvedToolCalls(pending.messageId);\n this.maybeCompleteAfterToolResults(pending.messageId);\n }\n\n private appendEntry(message: AppendMessage): string {\n if (message.sourceId) this.tryDeleteMessage(message.sourceId);\n\n const threadMessage = this.toThreadMessage(message);\n const parentId =\n message.parentId === null\n ? null\n : message.parentId && this.hasMessage(message.parentId)\n ? message.parentId\n : this.repository.headId;\n this.addOrUpdateMessage(parentId, threadMessage);\n this.switchToBranch(threadMessage.id);\n this.notifyUpdate();\n this.recordHistoryEntry(parentId, threadMessage);\n return threadMessage.id;\n }\n\n async edit(message: AppendMessage): Promise<void> {\n await this.append(message);\n }\n\n async reload(\n parentId: string | null,\n config: { runConfig?: RunConfig } = {},\n ): Promise<void> {\n this.assertNoPendingInterrupts();\n this.maybeAutoCancelPendingToolCalls();\n await this.startRun(parentId, config.runConfig);\n }\n\n async cancel(): Promise<void> {\n if (!this.abortController) return;\n this.abortController.abort();\n }\n\n async resume(config: ResumeRunConfig): Promise<void> {\n this.assertNoPendingInterrupts();\n await this.startRun(\n config.parentId,\n config.runConfig ?? this.lastRunConfig,\n undefined,\n config.stream,\n );\n }\n\n async resumeInFlightRun(messages: readonly ThreadMessage[]): Promise<void> {\n // Without a resume stream startRun would re-run the agent from scratch.\n const resumeStream = this.history?.resume?.bind(this.history);\n if (!resumeStream) {\n const error = new Error(\n \"[agui] unstable_resume requires a ThreadHistoryAdapter with a resume() method; skipping resume after thread switch\",\n );\n this.logger.error?.(error.message);\n this.onError?.(error);\n return;\n }\n const parentId = messages.at(-1)?.id ?? null;\n try {\n await this.startRun(\n parentId,\n this.lastRunConfig,\n undefined,\n resumeStream,\n );\n } catch {\n // startRun already reported via onError; don't reject the switch.\n }\n }\n\n private assertNoPendingInterrupts(): void {\n if (!this.getPendingInterrupts()) return;\n throw new Error(\n \"[agui] cannot start a new run while interrupts are pending; resolve them with submitInterruptResponses()\",\n );\n }\n\n private findRequiresActionAssistant(\n reason: \"interrupt\" | \"tool-calls\",\n ): ThreadAssistantMessage | null {\n const assistant = this.getMessages().findLast(\n (message) => message.role === \"assistant\",\n ) as ThreadAssistantMessage | undefined;\n if (\n !assistant ||\n assistant.status?.type !== \"requires-action\" ||\n assistant.status.reason !== reason\n ) {\n return null;\n }\n return assistant;\n }\n\n getPendingInterrupts(): {\n messageId: string;\n interrupts: readonly AgUiInterrupt[];\n } | null {\n const assistant = this.findRequiresActionAssistant(\"interrupt\");\n if (!assistant) return null;\n const stored = (\n assistant.metadata.custom[AG_UI_METADATA_NAMESPACE] as\n | AgUiCustomMetadata\n | undefined\n )?.interrupts;\n if (!stored?.length) return null;\n return { messageId: assistant.id, interrupts: stored };\n }\n\n getPendingToolCalls(): {\n messageId: string;\n toolCallIds: string[];\n } | null {\n const assistant = this.findRequiresActionAssistant(\"tool-calls\");\n if (!assistant) return null;\n const toolCallIds: string[] = [];\n for (const part of assistant.content) {\n if (part.type !== \"tool-call\") continue;\n if (isResolvedToolCall(part)) continue;\n toolCallIds.push(part.toolCallId);\n }\n if (toolCallIds.length === 0) return null;\n return { messageId: assistant.id, toolCallIds };\n }\n\n async submitInterruptResponses(\n responses: readonly AgUiResumeEntry[],\n ): Promise<void> {\n const pending = this.getPendingInterrupts();\n if (!pending) {\n throw new Error(\n \"[agui] submitInterruptResponses: no pending interrupts on this thread\",\n );\n }\n\n const responsesById = new Map<string, AgUiResumeEntry>();\n for (const entry of responses) {\n if (!entry || typeof entry.interruptId !== \"string\") {\n throw new Error(\n \"[agui] submitInterruptResponses: every entry must have an interruptId\",\n );\n }\n if (entry.status !== \"resolved\" && entry.status !== \"cancelled\") {\n throw new Error(\n `[agui] submitInterruptResponses: invalid status \"${entry.status}\" for interrupt ${entry.interruptId}`,\n );\n }\n if (responsesById.has(entry.interruptId)) {\n throw new Error(\n `[agui] submitInterruptResponses: duplicate response for interrupt ${entry.interruptId}`,\n );\n }\n responsesById.set(entry.interruptId, entry);\n }\n\n const openIds = pending.interrupts.map((i) => i.id);\n const missing = openIds.filter((id) => !responsesById.has(id));\n if (missing.length > 0) {\n throw new Error(\n `[agui] submitInterruptResponses: missing responses for open interrupts: ${missing.join(\", \")}`,\n );\n }\n const known = new Set(openIds);\n const unknownIds = [...responsesById.keys()].filter((id) => !known.has(id));\n if (unknownIds.length > 0) {\n throw new Error(\n `[agui] submitInterruptResponses: unknown interrupt ids: ${unknownIds.join(\", \")}`,\n );\n }\n\n const now = Date.now();\n for (const interrupt of pending.interrupts) {\n if (!interrupt.expiresAt) continue;\n const expiry = new Date(interrupt.expiresAt).getTime();\n if (Number.isNaN(expiry)) {\n throw new Error(\n `[agui] submitInterruptResponses: interrupt ${interrupt.id} has malformed expiresAt \"${interrupt.expiresAt}\"`,\n );\n }\n if (expiry <= now) {\n throw new Error(\n `[agui] submitInterruptResponses: interrupt ${interrupt.id} expired at ${interrupt.expiresAt}`,\n );\n }\n }\n\n const resume: AgUiResumeEntry[] = openIds.map((id) =>\n responsesById.get(id)!,\n );\n\n if (this.isRunningFlag) {\n throw new Error(\n \"[agui] submitInterruptResponses: a run is already in progress\",\n );\n }\n\n this.clearPendingInterrupts(pending.messageId);\n await this.startRun(pending.messageId, this.lastRunConfig, resume);\n }\n\n async steerAway(\n message: CreateAppendMessage,\n responses?: readonly AgUiResumeEntry[],\n ): Promise<void> {\n const pending = this.getPendingInterrupts();\n if (!pending) {\n const pendingTools = this.getPendingToolCalls();\n if (pendingTools) {\n if (responses?.length) {\n throw new Error(\n \"[agui] steerAway: responses are only valid for pending interrupts\",\n );\n }\n if (this.isRunningFlag) {\n throw new Error(\"[agui] steerAway: a run is already in progress\");\n }\n this.cancelUnresolvedToolCalls(pendingTools.messageId);\n this.maybeCompleteAfterToolResults(pendingTools.messageId);\n const normalized = this.toAppendMessage(message);\n const threadMessageId = this.appendEntry(normalized);\n await this.startRun(threadMessageId, normalized.runConfig);\n return;\n }\n if (responses?.length) {\n throw new Error(\n \"[agui] steerAway: no pending interrupts on this thread\",\n );\n }\n await this.append(this.toAppendMessage(message));\n return;\n }\n\n const resume = this.resolveSteerAwayResume(pending.interrupts, responses);\n\n if (this.isRunningFlag) {\n throw new Error(\"[agui] steerAway: a run is already in progress\");\n }\n\n const normalized = this.toAppendMessage(message);\n this.clearPendingInterrupts(pending.messageId);\n const threadMessageId = this.appendEntry(normalized);\n await this.startRun(threadMessageId, normalized.runConfig, resume);\n }\n\n private resolveSteerAwayResume(\n interrupts: readonly AgUiInterrupt[],\n responses: readonly AgUiResumeEntry[] | undefined,\n ): AgUiResumeEntry[] {\n const openIds = interrupts.map((interrupt) => interrupt.id);\n const known = new Set(openIds);\n const responsesById = new Map<string, AgUiResumeEntry>();\n for (const entry of responses ?? []) {\n if (!entry || typeof entry.interruptId !== \"string\") {\n throw new Error(\n \"[agui] steerAway: every response must have an interruptId\",\n );\n }\n if (entry.status !== \"resolved\" && entry.status !== \"cancelled\") {\n throw new Error(\n `[agui] steerAway: invalid status \"${entry.status}\" for interrupt ${entry.interruptId}`,\n );\n }\n if (!known.has(entry.interruptId)) {\n throw new Error(\n `[agui] steerAway: unknown interrupt id ${entry.interruptId}`,\n );\n }\n if (responsesById.has(entry.interruptId)) {\n throw new Error(\n `[agui] steerAway: duplicate response for interrupt ${entry.interruptId}`,\n );\n }\n responsesById.set(entry.interruptId, entry);\n }\n return openIds.map(\n (id) => responsesById.get(id) ?? { interruptId: id, status: \"cancelled\" },\n );\n }\n\n private toAppendMessage(message: CreateAppendMessage): AppendMessage {\n if (typeof message === \"string\") {\n return {\n createdAt: new Date(),\n parentId: this.repository.headId,\n sourceId: null,\n runConfig: {},\n role: \"user\",\n content: [{ type: \"text\", text: message }],\n attachments: [],\n metadata: { custom: {} },\n };\n }\n return {\n createdAt: message.createdAt ?? new Date(),\n parentId: message.parentId ?? this.repository.headId,\n sourceId: message.sourceId ?? null,\n role: message.role ?? \"user\",\n content: message.content,\n attachments: message.attachments ?? [],\n metadata: message.metadata ?? { custom: {} },\n runConfig: message.runConfig ?? {},\n startRun: message.startRun,\n } as AppendMessage;\n }\n\n private clearPendingInterrupts(messageId: string): void {\n const touched = this.updateMessage(messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n const assistant = message as ThreadAssistantMessage;\n if (\n assistant.status?.type !== \"requires-action\" ||\n assistant.status.reason !== \"interrupt\"\n ) {\n return assistant;\n }\n const aguiMeta = assistant.metadata.custom[AG_UI_METADATA_NAMESPACE] as\n | AgUiCustomMetadata\n | undefined;\n const { interrupts: _drop, ...restAgui } = aguiMeta ?? {};\n const newCustom = { ...assistant.metadata.custom };\n if (Object.keys(restAgui).length > 0) {\n newCustom[AG_UI_METADATA_NAMESPACE] = restAgui;\n } else {\n delete newCustom[AG_UI_METADATA_NAMESPACE];\n }\n return {\n ...assistant,\n status: { type: \"complete\" as const, reason: \"unknown\" as const },\n metadata: { ...assistant.metadata, custom: newCustom },\n };\n });\n if (touched) {\n this.notifyUpdate();\n }\n }\n\n findMessageIdForToolCall(toolCallId: string): string | undefined {\n let fallbackMessageId: string | undefined;\n const messages = this.getMessages();\n for (let index = messages.length - 1; index >= 0; index--) {\n const message = messages[index];\n if (!message || message.role !== \"assistant\") continue;\n for (const part of message.content) {\n if (part.type !== \"tool-call\" || part.toolCallId !== toolCallId)\n continue;\n if (!isResolvedToolCall(part)) {\n return message.id;\n }\n fallbackMessageId ??= message.id;\n }\n }\n return fallbackMessageId;\n }\n\n private cancelUnresolvedToolCalls(messageId: string): void {\n const updated = this.updateMessage(messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n const assistant = message as ThreadAssistantMessage;\n const content = assistant.content.map((part) => {\n if (part.type !== \"tool-call\" || isResolvedToolCall(part)) return part;\n return {\n ...part,\n result: { error: \"Tool call cancelled by user\" },\n isError: true,\n };\n });\n return { ...assistant, content };\n });\n if (updated) this.notifyUpdate();\n }\n\n addToolResult(options: AddToolResultOptions): void {\n const updated = this.updateMessage(options.messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n const assistant = message as ThreadAssistantMessage;\n let matchedToolCall = false;\n const content = assistant.content.map((part) => {\n if (part.type !== \"tool-call\" || part.toolCallId !== options.toolCallId)\n return part;\n matchedToolCall = true;\n return {\n ...part,\n result: options.result,\n artifact: options.artifact,\n isError: options.isError,\n };\n });\n if (!matchedToolCall) return message;\n return { ...assistant, content };\n });\n\n if (!updated) return;\n this.notifyUpdate();\n this.maybeResumeAfterToolResults(options.messageId);\n }\n\n // The continuation fires whether the frontend result lands before\n // RUN_FINISHED (the status flips to requires-action only later, while the\n // run is still draining) or after it.\n private maybeResumeAfterToolResults(messageId: string): void {\n if (!this.maybeCompleteAfterToolResults(messageId)) return;\n\n if (this.isRunningFlag) {\n // A run is still draining (RUN_FINISHED arrived but the stream has not\n // closed). Defer until startRun's tail so we never start two runs.\n this.pendingResumeMessageId = messageId;\n return;\n }\n this.startResumeRun(messageId);\n }\n\n private maybeCompleteAfterToolResults(messageId: string): boolean {\n const message = this.tryGetMessage(messageId)?.message;\n if (!message || message.role !== \"assistant\") return false;\n const assistant = message as ThreadAssistantMessage;\n if (\n assistant.status?.type !== \"requires-action\" ||\n assistant.status.reason !== \"tool-calls\"\n ) {\n return false;\n }\n const allResolved = assistant.content.every(\n (part) => part.type !== \"tool-call\" || isResolvedToolCall(part),\n );\n if (!allResolved) return false;\n\n const updated = this.updateMessage(messageId, (current) =>\n current.role === \"assistant\"\n ? {\n ...(current as ThreadAssistantMessage),\n status: { type: \"complete\" as const, reason: \"unknown\" as const },\n }\n : current,\n );\n if (!updated) return false;\n this.notifyUpdate();\n this.persistAssistantHistory(messageId);\n return true;\n }\n\n private startResumeRun(messageId: string): void {\n void this.startRun(messageId, this.lastRunConfig).catch((error) => {\n this.onError?.(error instanceof Error ? error : new Error(String(error)));\n });\n }\n\n applyExternalMessages(messages: readonly ThreadMessage[]): void {\n this.assistantHistoryParents.clear();\n\n if (messages.length === 0) {\n this.clearRepository();\n } else {\n let expectedParentId: string | null = null;\n let lastAppliedId: string | null = null;\n let hardReplace = false;\n const seen = new Set<string>();\n\n for (const message of messages) {\n if (seen.has(message.id)) continue;\n seen.add(message.id);\n const existing = this.tryGetMessage(message.id);\n if (existing && existing.parentId !== expectedParentId) {\n hardReplace = true;\n break;\n }\n this.addOrUpdateMessage(expectedParentId, message);\n expectedParentId = message.id;\n lastAppliedId = message.id;\n }\n\n if (hardReplace) {\n this.clearRepository();\n expectedParentId = null;\n lastAppliedId = null;\n seen.clear();\n for (const message of messages) {\n if (seen.has(message.id)) continue;\n seen.add(message.id);\n this.addOrUpdateMessage(expectedParentId, message);\n expectedParentId = message.id;\n lastAppliedId = message.id;\n }\n }\n\n this.resetRepositoryHead(lastAppliedId);\n }\n\n this.recordedHistoryIds.clear();\n for (const { message } of this.getMessageRepository().messages) {\n this.recordedHistoryIds.add(message.id);\n }\n this.notifyUpdate();\n }\n\n private applyExternalMessageRepository(\n loaded: ExportedMessageRepository,\n ): void {\n const headId = loaded.headId ?? loaded.messages.at(-1)?.message.id ?? null;\n const ids = new Set<string>();\n let degenerate = false;\n for (const { message } of loaded.messages) {\n if (ids.has(message.id)) {\n degenerate = true;\n break;\n }\n ids.add(message.id);\n }\n if (headId !== null && !ids.has(headId)) degenerate = true;\n\n if (!degenerate) {\n this.clearRepository();\n let pending = [...loaded.messages];\n const importedIds = new Set<string>();\n\n while (pending.length > 0) {\n const unresolved: typeof pending = [];\n let progressed = false;\n for (const item of pending) {\n if (item.parentId !== null && !importedIds.has(item.parentId)) {\n unresolved.push(item);\n continue;\n }\n this.addOrUpdateMessage(item.parentId, item.message);\n importedIds.add(item.message.id);\n progressed = true;\n }\n if (!progressed) {\n degenerate = true;\n break;\n }\n pending = unresolved;\n }\n }\n\n if (degenerate) {\n this.clearRepository();\n let previousId: string | null = null;\n for (const { message } of loaded.messages) {\n const existing = this.tryGetMessage(message.id);\n this.addOrUpdateMessage(\n existing ? existing.parentId : previousId,\n message,\n );\n previousId = message.id;\n }\n this.resetRepositoryHead(previousId);\n } else {\n this.resetRepositoryHead(headId);\n }\n\n this.assistantHistoryParents.clear();\n this.recordedHistoryIds.clear();\n for (const { message } of loaded.messages) {\n this.recordedHistoryIds.add(message.id);\n }\n this.notifyUpdate();\n }\n\n loadExternalState(state: ReadonlyJSONValue): void {\n this.stateSnapshot = state;\n this.notifyUpdate();\n }\n\n setState(\n next:\n | ReadonlyJSONValue\n | ((prev: ReadonlyJSONValue | undefined) => ReadonlyJSONValue),\n ): void {\n this.stateSnapshot =\n typeof next === \"function\" ? next(this.stateSnapshot) : next;\n this.notifyUpdate();\n }\n\n resetState(): void {\n this.stateSnapshot = undefined;\n this.notifyUpdate();\n }\n\n private async startRun(\n parentId: string | null,\n runConfig?: RunConfig,\n resume?: AgUiResumeEntry[],\n resumeStream?: ResumeStream,\n ): Promise<void> {\n const normalizedRunConfig = runConfig ?? {};\n this.lastRunConfig = normalizedRunConfig;\n const parent = parentId === null ? undefined : this.tryGetMessage(parentId);\n const shouldEagerlyInsertAssistant =\n parentId !== null &&\n parent !== undefined &&\n parentId !== this.repository.headId;\n const historicalMessages = [\n ...(shouldEagerlyInsertAssistant\n ? (this.tryGetMessages(parentId) ?? this.repository.getMessages())\n : this.repository.getMessages()),\n ];\n\n this.pendingError = null;\n const assistantParentId = parent ? parentId : this.repository.headId;\n let assistantMessageId: string | undefined;\n const ensureAssistant = () => {\n if (assistantMessageId) return assistantMessageId;\n const created = this.insertAssistantPlaceholder(\n assistantParentId ?? null,\n );\n assistantMessageId = created;\n this.markPendingAssistantHistory(created, assistantParentId ?? null);\n return created;\n };\n\n if (shouldEagerlyInsertAssistant) ensureAssistant();\n\n const applyUpdate = (update: ChatModelRunResult) => {\n const resolved = this.updateAssistantMessage(ensureAssistant(), update);\n if (resolved !== assistantMessageId) {\n assistantMessageId = resolved;\n }\n };\n\n const aggregator = new RunAggregator({\n showThinking: this.showThinking,\n logger: this.logger,\n emit: applyUpdate,\n onServerMessageId: (serverId) => {\n const placeholder = ensureAssistant();\n if (placeholder === serverId) return;\n if (this.reassignAssistantId(placeholder, serverId)) {\n assistantMessageId = serverId;\n }\n },\n });\n const dispatch = (event: AgUiEvent) => this.handleEvent(aggregator, event);\n\n const abortController = new AbortController();\n const abortSignal = abortController.signal;\n this.abortController = abortController;\n\n let cancelRun = () => dispatch({ type: \"RUN_CANCELLED\" });\n abortSignal.addEventListener(\n \"abort\",\n () => {\n cancelRun();\n this.finishRun(abortController);\n this.onCancel?.();\n },\n { once: true },\n );\n\n this.setRunning(true);\n\n try {\n if (resumeStream) {\n // Cancel flips only the status; an aggregator RUN_CANCELLED would emit an empty snapshot and wipe the replayed content.\n cancelRun = () =>\n applyUpdate({ status: { type: \"incomplete\", reason: \"cancelled\" } });\n await this.consumeResumeStream(resumeStream, {\n runConfig: normalizedRunConfig,\n threadId: this.agent.threadId || \"main\",\n parentId: assistantParentId,\n historicalMessages,\n abortSignal,\n ensureAssistant,\n applyUpdate,\n getAssistantMessageId: () => assistantMessageId,\n });\n } else {\n const runId = generateId();\n aggregator.handle({ type: \"RUN_STARTED\", runId });\n const input = this.buildRunInput(\n runId,\n normalizedRunConfig,\n historicalMessages,\n resume,\n );\n const subscriber = createAgUiSubscriber({\n dispatch,\n runId,\n logger: this.logger,\n onRunFailed: (error) => {\n this.pendingError = error;\n this.onError?.(error);\n },\n });\n try {\n (this.agent as any).messages = input.messages;\n (this.agent as any).threadId = input.threadId;\n (this.agent as any).state = input.state ?? null;\n } catch {\n // ignore\n }\n await (this.agent as any).runAgent(input, subscriber, {\n signal: abortSignal,\n });\n }\n } catch (error) {\n if (!abortSignal.aborted) {\n const err = error instanceof Error ? error : new Error(String(error));\n dispatch({ type: \"RUN_ERROR\", message: err.message });\n this.onError?.(err);\n this.pendingError = this.pendingError ?? err;\n }\n } finally {\n this.finishRun(abortController);\n }\n\n if (this.pendingError) {\n const err = this.pendingError;\n this.pendingError = null;\n this.pendingResumeMessageId = null;\n throw err;\n }\n\n // A tool result that landed before the run settled deferred its\n // continuation here so a second run never overlaps the first.\n if (this.pendingResumeMessageId !== null) {\n const resumeMessageId = this.pendingResumeMessageId;\n this.pendingResumeMessageId = null;\n if (!abortSignal.aborted) {\n this.startResumeRun(resumeMessageId);\n }\n }\n }\n\n // Replays a persisted run's snapshots into the existing assistant message, bypassing agent.runAgent so it is not re-invoked.\n private async consumeResumeStream(\n stream: ResumeStream,\n ctx: {\n runConfig: RunConfig;\n threadId: string;\n parentId: string | null;\n historicalMessages: readonly ThreadMessage[];\n abortSignal: AbortSignal;\n ensureAssistant: () => string;\n applyUpdate: (update: ChatModelRunResult) => void;\n getAssistantMessageId: () => string | undefined;\n },\n ): Promise<void> {\n const assistantId = ctx.ensureAssistant();\n const currentId = () => ctx.getAssistantMessageId() ?? assistantId;\n const options: ChatModelRunOptions = {\n messages: ctx.historicalMessages,\n runConfig: ctx.runConfig,\n abortSignal: ctx.abortSignal,\n context: this.runtime?.thread.getModelContext() ?? {},\n unstable_assistantMessageId: assistantId,\n unstable_threadId: ctx.threadId,\n unstable_parentId: ctx.parentId,\n unstable_getMessage: () => {\n const message = this.tryGetMessage(currentId())?.message;\n if (!message) {\n throw new Error(\n \"[agui] resume stream requested the assistant message before it existed\",\n );\n }\n return message;\n },\n };\n\n try {\n for await (const result of stream(options)) {\n if (ctx.abortSignal.aborted) return;\n ctx.applyUpdate(result);\n }\n } catch (error) {\n if (ctx.abortSignal.aborted) return;\n const err = error instanceof Error ? error : new Error(String(error));\n ctx.applyUpdate({\n status: { type: \"incomplete\", reason: \"error\", error: err.message },\n });\n this.onError?.(err);\n this.pendingError = this.pendingError ?? err;\n return;\n }\n\n if (ctx.abortSignal.aborted) return;\n const current = this.tryGetMessage(currentId())?.message;\n if (!current || current.status?.type === \"running\") {\n ctx.applyUpdate({ status: { type: \"complete\", reason: \"unknown\" } });\n }\n }\n\n private buildRunInput(\n runId: string,\n runConfig: RunConfig | undefined,\n historyMessages: readonly ThreadMessage[] | undefined,\n resume?: AgUiResumeEntry[],\n ) {\n const threadId = this.agent.threadId || \"main\";\n const messages = toAgUiMessages(\n historyMessages ?? this.repository.getMessages(),\n );\n const context = this.runtime?.thread.getModelContext();\n return {\n threadId,\n runId,\n state: this.stateSnapshot ?? null,\n messages,\n tools: toAgUiTools(context?.tools),\n context: context?.system\n ? [{ description: \"system\", value: context.system }]\n : [],\n forwardedProps: {\n ...(context?.callSettings ?? {}),\n ...(context?.config ?? {}),\n ...(runConfig?.custom ? { runConfig: runConfig.custom } : {}),\n },\n ...(resume !== undefined ? { resume } : {}),\n };\n }\n\n private installResumeShim(): void {\n const agent = this.agent as any;\n if (agent[symbolResumeShim]) return;\n agent[symbolResumeShim] = true;\n const onInstance = Object.hasOwn(agent, \"prepareRunAgentInput\");\n const original = onInstance\n ? agent.prepareRunAgentInput\n : Object.getPrototypeOf(agent)?.prepareRunAgentInput;\n if (typeof original !== \"function\") return;\n agent.prepareRunAgentInput = function (\n this: unknown,\n params: { resume?: unknown } | undefined,\n ) {\n const input = original.call(this, params);\n if (params?.resume !== undefined && input && typeof input === \"object\") {\n return { ...(input as object), resume: params.resume };\n }\n return input;\n };\n }\n\n private setRunning(running: boolean) {\n this.isRunningFlag = running;\n this.notifyUpdate();\n }\n\n private finishRun(controller: AbortController | null) {\n if (this.abortController === controller) {\n this.abortController = null;\n }\n this.setRunning(false);\n }\n\n private insertAssistantPlaceholder(parentId: string | null): string {\n const id = generateOptimisticId();\n const assistant: ThreadAssistantMessage = {\n id,\n role: \"assistant\",\n createdAt: new Date(),\n status: { type: \"running\" },\n content: [],\n metadata: {\n unstable_state: this.stateSnapshot ?? null,\n unstable_annotations: [],\n unstable_data: [],\n steps: [],\n isOptimistic: true,\n custom: {},\n },\n };\n this.addOrUpdateMessage(parentId ?? this.repository.headId, assistant);\n this.switchToBranch(id);\n this.notifyUpdate();\n return id;\n }\n\n private reassignAssistantId(oldId: string, newId: string): boolean {\n if (oldId === newId) return true;\n const oldItem = this.tryGetMessage(oldId);\n if (!oldItem) return false;\n\n const collidesWithExisting = this.hasMessage(newId);\n\n if (collidesWithExisting) {\n this.logger.debug?.(\n \"[agui] reassignAssistantId: server id already present in messages or repository, dropping placeholder\",\n { oldId, newId },\n );\n this.deleteMessage(oldId, oldItem.parentId ?? null);\n } else {\n const { isOptimistic: _, ...metadata } = oldItem.message.metadata;\n this.addOrUpdateMessage(oldItem.parentId, {\n ...oldItem.message,\n id: newId,\n metadata,\n } as ThreadMessage);\n this.switchToBranch(newId);\n this.tryDeleteMessage(oldId);\n }\n\n const pendingParent = this.assistantHistoryParents.get(oldId);\n if (pendingParent !== undefined) {\n this.assistantHistoryParents.delete(oldId);\n if (!collidesWithExisting && !this.assistantHistoryParents.has(newId)) {\n this.assistantHistoryParents.set(newId, pendingParent);\n }\n }\n\n if (this.recordedHistoryIds.has(oldId)) {\n this.recordedHistoryIds.delete(oldId);\n if (!collidesWithExisting) {\n this.recordedHistoryIds.add(newId);\n }\n }\n\n this.notifyUpdate();\n return !collidesWithExisting;\n }\n\n private updateAssistantMessage(\n messageId: string,\n update: ChatModelRunResult,\n ): string {\n let latestStatus: MessageStatus | undefined;\n const touched = this.updateMessage(messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n const assistant = message as ThreadAssistantMessage;\n const metadata = update.metadata\n ? this.mergeAssistantMetadata(assistant.metadata, update.metadata)\n : assistant.metadata;\n latestStatus = update.status ?? assistant.status;\n const content =\n update.content !== undefined\n ? this.preserveToolResults(\n assistant.content,\n update.content as ThreadAssistantMessage[\"content\"],\n )\n : assistant.content;\n return {\n ...assistant,\n content,\n status: latestStatus,\n metadata,\n };\n });\n if (!touched) return messageId;\n\n let resolvedMessageId = messageId;\n const isSettled =\n latestStatus !== undefined && latestStatus.type !== \"running\";\n if (isSettled && isOptimisticId(messageId)) {\n const stableId = generateId();\n this.reassignAssistantId(messageId, stableId);\n resolvedMessageId = stableId;\n } else {\n this.notifyUpdate();\n }\n if (this.isPersistableStatus(latestStatus)) {\n this.persistAssistantHistory(resolvedMessageId);\n }\n this.maybeResumeAfterToolResults(resolvedMessageId);\n return resolvedMessageId;\n }\n\n // The RunAggregator rebuilds the assistant content from stream events only,\n // so a fresh snapshot omits results injected via addToolResult (frontend tool\n // execution). Carry those results forward so the aggregator never clobbers\n // them. Results are only ever added in this flow, so preserving is safe.\n private preserveToolResults(\n previous: ThreadAssistantMessage[\"content\"],\n next: ThreadAssistantMessage[\"content\"],\n ): ThreadAssistantMessage[\"content\"] {\n const resolved = new Map<string, ToolCallMessagePart>();\n for (const part of previous) {\n if (part.type === \"tool-call\" && isResolvedToolCall(part)) {\n resolved.set(part.toolCallId, part);\n }\n }\n if (resolved.size === 0) return next;\n\n let changed = false;\n const merged = next.map((part) => {\n if (part.type !== \"tool-call\" || isResolvedToolCall(part)) return part;\n const prior = resolved.get(part.toolCallId);\n if (!prior) return part;\n changed = true;\n return {\n ...part,\n result: prior.result,\n ...(prior.artifact !== undefined ? { artifact: prior.artifact } : {}),\n ...(prior.isError !== undefined ? { isError: prior.isError } : {}),\n };\n });\n return changed ? (merged as ThreadAssistantMessage[\"content\"]) : next;\n }\n\n private mergeAssistantMetadata(\n current: ThreadAssistantMessage[\"metadata\"],\n incoming: NonNullable<ChatModelRunResult[\"metadata\"]>,\n ): ThreadAssistantMessage[\"metadata\"] {\n const annotations = incoming.unstable_annotations\n ? [...current.unstable_annotations, ...incoming.unstable_annotations]\n : current.unstable_annotations;\n const data = incoming.unstable_data\n ? [...current.unstable_data, ...incoming.unstable_data]\n : current.unstable_data;\n const steps = incoming.steps\n ? [...current.steps, ...incoming.steps]\n : current.steps;\n return {\n unstable_state:\n incoming.unstable_state !== undefined\n ? incoming.unstable_state\n : current.unstable_state,\n unstable_annotations: annotations,\n unstable_data: data,\n steps,\n ...(current.isOptimistic ? { isOptimistic: true } : {}),\n ...(incoming.timing ? { timing: incoming.timing } : {}),\n custom: incoming.custom\n ? { ...current.custom, ...incoming.custom }\n : current.custom,\n };\n }\n\n private handleEvent(aggregator: RunAggregator, event: AgUiEvent) {\n switch (event.type) {\n case \"STATE_SNAPSHOT\": {\n this.stateSnapshot = event.snapshot as ReadonlyJSONValue;\n this.notifyUpdate();\n return;\n }\n case \"STATE_DELTA\": {\n if (event.delta.length === 0) return;\n try {\n const state = this.stateSnapshot ?? {};\n const result = jsonpatch.applyPatch(\n state,\n event.delta as Operation[],\n /* validateOperation */ true,\n /* mutateDocument */ false,\n );\n this.stateSnapshot = result.newDocument as ReadonlyJSONValue;\n this.notifyUpdate();\n } catch (error) {\n this.logger.error?.(\"[agui] failed to apply state delta\", error);\n }\n return;\n }\n case \"MESSAGES_SNAPSHOT\": {\n this.importMessagesSnapshot(event.messages);\n return;\n }\n case \"TOOL_CALL_RESULT\": {\n if (!aggregator.hasToolCall(event.toolCallId)) {\n const messageId = this.findMessageIdForToolCall(event.toolCallId);\n if (messageId !== undefined) {\n this.applyCrossRunToolResult(messageId, event);\n return;\n }\n }\n aggregator.handle(event);\n return;\n }\n default:\n aggregator.handle(event);\n }\n }\n\n private applyCrossRunToolResult(\n messageId: string,\n event: Extract<AgUiEvent, { type: \"TOOL_CALL_RESULT\" }>,\n ): void {\n const updated = this.updateMessage(messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n const assistant = message as ThreadAssistantMessage;\n let matchedToolCall = false;\n const content = assistant.content.map((part) => {\n if (part.type !== \"tool-call\" || part.toolCallId !== event.toolCallId)\n return part;\n matchedToolCall = true;\n return {\n ...part,\n result: tryParseJSON(event.content ?? \"\") as ReadonlyJSONValue,\n ...(event.role === \"tool\" ? { isError: false } : {}),\n ...(event.messageId\n ? { unstable_toolMessageId: event.messageId }\n : {}),\n };\n });\n if (!matchedToolCall) return message;\n return { ...assistant, content };\n });\n\n if (!updated) return;\n this.notifyUpdate();\n // Not maybeResumeAfterToolResults: the delivering run is already in\n // flight, and a resume from the owner would reset the head past it.\n this.maybeCompleteAfterToolResults(messageId);\n }\n\n private importMessagesSnapshot(rawMessages: readonly unknown[]) {\n try {\n const normalized = fromAgUiMessages(rawMessages, {\n showThinking: this.showThinking,\n });\n const converted: ThreadMessage[] = [];\n for (const message of normalized) {\n try {\n converted.push(\n fromThreadMessageLike(message, generateId(), FALLBACK_USER_STATUS),\n );\n } catch (error) {\n this.logger.error?.(\n \"[agui] failed to import message from snapshot\",\n error,\n );\n }\n }\n this.applyExternalMessages(converted);\n } catch (error) {\n this.logger.error?.(\"[agui] failed to import messages snapshot\", error);\n }\n }\n\n private toThreadMessage(message: AppendMessage): ThreadMessage {\n return fromThreadMessageLike(\n message as any,\n generateId(),\n FALLBACK_USER_STATUS,\n );\n }\n\n private isTerminalStatus(status?: MessageStatus): boolean {\n return status?.type === \"complete\" || status?.type === \"incomplete\";\n }\n\n private isPersistableStatus(status?: MessageStatus): boolean {\n if (this.isTerminalStatus(status)) return true;\n return status?.type === \"requires-action\" && status.reason === \"interrupt\";\n }\n\n private recordHistoryEntry(parentId: string | null, message: ThreadMessage) {\n this.appendHistoryItem(parentId, message);\n }\n\n private markPendingAssistantHistory(\n messageId: string,\n parentId: string | null,\n ) {\n if (!this.history) return;\n this.assistantHistoryParents.set(messageId, parentId);\n }\n\n private persistAssistantHistory(messageId: string) {\n if (!this.history) return;\n const parentId = this.assistantHistoryParents.get(messageId);\n if (parentId === undefined) return;\n const message = this.tryGetMessage(messageId)?.message;\n if (!message || message.role !== \"assistant\") return;\n if (!this.isPersistableStatus(message.status)) return;\n this.assistantHistoryParents.delete(messageId);\n this.appendHistoryItem(parentId, message);\n }\n\n private appendHistoryItem(parentId: string | null, message: ThreadMessage) {\n if (!this.history || this.recordedHistoryIds.has(message.id)) return;\n this.recordedHistoryIds.add(message.id);\n void this.history.append({ parentId, message }).catch((error) => {\n this.recordedHistoryIds.delete(message.id);\n this.logger.error?.(\"[agui] failed to append history entry\", error);\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AgUiThreadRuntimeCore.js","names":[],"sources":["../../src/runtime/AgUiThreadRuntimeCore.ts"],"sourcesContent":["\"use client\";\n\nimport {\n generateId,\n fromThreadMessageLike,\n isMcpAppUri,\n} from \"@assistant-ui/core\";\nimport type {\n AddToolResultOptions,\n AppendMessage,\n CreateAppendMessage,\n AssistantRuntime,\n ChatModelRunOptions,\n ChatModelRunResult,\n ExportedMessageRepository,\n MessageStatus,\n ThreadAssistantMessage,\n ThreadHistoryAdapter,\n ThreadMessage,\n ToolCallMessagePart,\n} from \"@assistant-ui/core\";\nimport { MessageRepository } from \"@assistant-ui/core/internal\";\nimport type { AbstractAgent } from \"@ag-ui/client\";\nimport jsonpatch, { type Operation } from \"fast-json-patch\";\nimport type { Logger } from \"./logger\";\nimport type { AgUiEvent, AgUiInterrupt, AgUiResumeEntry } from \"./types\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport {\n AG_UI_METADATA_NAMESPACE,\n type AgUiCustomMetadata,\n isPlainObject,\n MCP_APPS_ACTIVITY_TYPE,\n RunAggregator,\n tryParseJSON,\n} from \"./adapter/run-aggregator\";\nimport {\n fromAgUiMessages,\n toAgUiMessages,\n toAgUiTools,\n} from \"./adapter/conversions\";\nimport { createAgUiSubscriber } from \"./adapter/subscriber\";\n\nconst optimisticPrefix = \"__optimistic__\";\nconst generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;\nconst isOptimisticId = (id: string) => id.startsWith(optimisticPrefix);\n\nconst isResolvedToolCall = (\n part: ThreadAssistantMessage[\"content\"][number],\n): boolean =>\n part.type === \"tool-call\" && \"result\" in part && part.result !== undefined;\n\nconst symbolResumeShim = Symbol(\"agui-resume-shim\");\n\ntype RunConfig = NonNullable<AppendMessage[\"runConfig\"]>;\ntype ResumeStream = (\n options: ChatModelRunOptions,\n) => AsyncGenerator<ChatModelRunResult, void, unknown>;\ntype ResumeRunConfig = {\n parentId: string | null;\n sourceId: string | null;\n runConfig: RunConfig;\n stream?: ResumeStream;\n};\n\ntype CoreOptions = {\n agent: AbstractAgent;\n logger: Logger;\n showThinking: boolean;\n autoCancelPendingToolCalls?: boolean | undefined;\n onError?: (error: Error) => void;\n onCancel?: () => void;\n history?: ThreadHistoryAdapter;\n notifyUpdate: () => void;\n};\n\nconst FALLBACK_USER_STATUS = { type: \"complete\", reason: \"unknown\" } as const;\n\nexport class AgUiThreadRuntimeCore {\n private agent: AbstractAgent;\n private logger: Logger;\n private showThinking: boolean;\n private autoCancelPendingToolCalls: boolean | undefined;\n private onError: ((error: Error) => void) | undefined;\n private onCancel: (() => void) | undefined;\n private readonly notifyUpdate: () => void;\n\n private runtime: AssistantRuntime | undefined;\n private readonly repository = new MessageRepository();\n private exportedRepository: ExportedMessageRepository | undefined;\n private isRunningFlag = false;\n private abortController: AbortController | null = null;\n private stateSnapshot: ReadonlyJSONValue | undefined;\n private pendingError: Error | null = null;\n private history: ThreadHistoryAdapter | undefined;\n private lastRunConfig: RunConfig | undefined;\n private readonly assistantHistoryParents = new Map<string, string | null>();\n private readonly recordedHistoryIds = new Set<string>();\n private _isLoading = false;\n private _loadPromise: Promise<void> | undefined;\n private pendingResumeMessageId: string | null = null;\n\n constructor(options: CoreOptions) {\n this.agent = options.agent;\n this.logger = options.logger;\n this.showThinking = options.showThinking;\n this.autoCancelPendingToolCalls = options.autoCancelPendingToolCalls;\n this.onError = options.onError;\n this.onCancel = options.onCancel;\n this.history = options.history;\n this.notifyUpdate = options.notifyUpdate;\n this.installResumeShim();\n }\n\n updateOptions(options: Omit<CoreOptions, \"notifyUpdate\">) {\n this.agent = options.agent;\n this.logger = options.logger;\n this.showThinking = options.showThinking;\n this.autoCancelPendingToolCalls = options.autoCancelPendingToolCalls;\n this.onError = options.onError;\n this.onCancel = options.onCancel;\n this.history = options.history;\n this.installResumeShim();\n }\n\n attachRuntime(runtime: AssistantRuntime) {\n this.runtime = runtime;\n }\n\n detachRuntime() {\n this.runtime = undefined;\n }\n\n getMessages(): readonly ThreadMessage[] {\n return this.repository.getMessages();\n }\n\n getMessageRepository(): ExportedMessageRepository {\n if (this.exportedRepository) return this.exportedRepository;\n\n const exportedRepository = this.repository.export();\n let parentId: string | null = null;\n for (const message of this.repository.getMessages()) {\n if (message.metadata.isOptimistic) {\n exportedRepository.messages.push({ parentId, message });\n }\n parentId = message.id;\n }\n\n this.exportedRepository = {\n ...exportedRepository,\n headId: this.repository.headId,\n };\n return this.exportedRepository;\n }\n\n private tryGetMessage(messageId: string) {\n try {\n return this.repository.getMessage(messageId);\n } catch {\n return undefined;\n }\n }\n\n private tryGetMessages(\n messageId: string,\n ): readonly ThreadMessage[] | undefined {\n try {\n return this.repository.getMessages(messageId);\n } catch {\n return undefined;\n }\n }\n\n private hasMessage(messageId: string): boolean {\n return this.tryGetMessage(messageId) !== undefined;\n }\n\n private addOrUpdateMessage(\n parentId: string | null,\n message: ThreadMessage,\n ): void {\n this.repository.addOrUpdateMessage(parentId, message);\n this.exportedRepository = undefined;\n }\n\n private deleteMessage(\n messageId: string,\n replacementId?: string | null,\n ): void {\n this.repository.deleteMessage(messageId, replacementId);\n this.exportedRepository = undefined;\n }\n\n private tryDeleteMessage(messageId: string): boolean {\n if (!this.hasMessage(messageId)) return false;\n this.deleteMessage(messageId);\n return true;\n }\n\n private switchToBranch(messageId: string): void {\n this.repository.switchToBranch(messageId);\n this.exportedRepository = undefined;\n }\n\n private resetRepositoryHead(messageId: string | null): void {\n this.repository.resetHead(messageId);\n this.exportedRepository = undefined;\n }\n\n private clearRepository(): void {\n this.repository.clear();\n this.exportedRepository = undefined;\n }\n\n private updateMessage(\n messageId: string,\n updater: (message: ThreadMessage) => ThreadMessage,\n ): boolean {\n const item = this.tryGetMessage(messageId);\n if (!item) return false;\n const message = updater(item.message);\n if (message === item.message) return false;\n this.addOrUpdateMessage(item.parentId, message);\n return true;\n }\n\n getState(): ReadonlyJSONValue | undefined {\n return this.stateSnapshot;\n }\n\n isRunning(): boolean {\n return this.isRunningFlag;\n }\n\n get isLoading(): boolean {\n return this._isLoading;\n }\n\n __internal_load(): Promise<void> {\n if (this._loadPromise) return this._loadPromise;\n\n const promise = this.history?.load() ?? Promise.resolve(null);\n\n this._isLoading = true;\n\n this._loadPromise = promise\n .then(async (repo) => {\n if (!repo) return;\n\n this.applyExternalMessageRepository(repo);\n\n if (repo.state !== undefined) {\n this.loadExternalState(repo.state);\n }\n\n if (repo.unstable_resume) {\n const parentId = repo.headId ?? this.repository.headId;\n const resumeStream = this.history?.resume?.bind(this.history);\n await this.startRun(\n parentId,\n this.lastRunConfig,\n undefined,\n resumeStream,\n );\n }\n })\n .catch((error) => {\n this.logger.error?.(\"[agui] failed to load history\", error);\n this.onError?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n })\n .finally(() => {\n this._isLoading = false;\n this.notifyUpdate();\n });\n\n this.notifyUpdate();\n return this._loadPromise;\n }\n\n async append(message: AppendMessage): Promise<void> {\n const startRun = message.startRun ?? message.role === \"user\";\n if (startRun) {\n this.assertNoPendingInterrupts();\n this.maybeAutoCancelPendingToolCalls();\n }\n const threadMessageId = this.appendEntry(message);\n if (!startRun) return;\n await this.startRun(threadMessageId, message.runConfig);\n }\n\n private maybeAutoCancelPendingToolCalls(): void {\n if (this.autoCancelPendingToolCalls === false) return;\n const pending = this.getPendingToolCalls();\n if (!pending) return;\n this.cancelUnresolvedToolCalls(pending.messageId);\n this.maybeCompleteAfterToolResults(pending.messageId);\n }\n\n private appendEntry(message: AppendMessage): string {\n if (message.sourceId) this.tryDeleteMessage(message.sourceId);\n\n const threadMessage = this.toThreadMessage(message);\n const parentId =\n message.parentId === null\n ? null\n : message.parentId && this.hasMessage(message.parentId)\n ? message.parentId\n : this.repository.headId;\n this.addOrUpdateMessage(parentId, threadMessage);\n this.switchToBranch(threadMessage.id);\n this.notifyUpdate();\n this.recordHistoryEntry(parentId, threadMessage);\n return threadMessage.id;\n }\n\n async edit(message: AppendMessage): Promise<void> {\n await this.append(message);\n }\n\n async reload(\n parentId: string | null,\n config: { runConfig?: RunConfig } = {},\n ): Promise<void> {\n this.assertNoPendingInterrupts();\n this.maybeAutoCancelPendingToolCalls();\n await this.startRun(parentId, config.runConfig);\n }\n\n async cancel(): Promise<void> {\n if (!this.abortController) return;\n this.abortController.abort();\n }\n\n async resume(config: ResumeRunConfig): Promise<void> {\n this.assertNoPendingInterrupts();\n await this.startRun(\n config.parentId,\n config.runConfig ?? this.lastRunConfig,\n undefined,\n config.stream,\n );\n }\n\n async resumeInFlightRun(messages: readonly ThreadMessage[]): Promise<void> {\n // Without a resume stream startRun would re-run the agent from scratch.\n const resumeStream = this.history?.resume?.bind(this.history);\n if (!resumeStream) {\n const error = new Error(\n \"[agui] unstable_resume requires a ThreadHistoryAdapter with a resume() method; skipping resume after thread switch\",\n );\n this.logger.error?.(error.message);\n this.onError?.(error);\n return;\n }\n const parentId = messages.at(-1)?.id ?? null;\n try {\n await this.startRun(\n parentId,\n this.lastRunConfig,\n undefined,\n resumeStream,\n );\n } catch {\n // startRun already reported via onError; don't reject the switch.\n }\n }\n\n private assertNoPendingInterrupts(): void {\n if (!this.getPendingInterrupts()) return;\n throw new Error(\n \"[agui] cannot start a new run while interrupts are pending; resolve them with submitInterruptResponses()\",\n );\n }\n\n private findRequiresActionAssistant(\n reason: \"interrupt\" | \"tool-calls\",\n ): ThreadAssistantMessage | null {\n const assistant = this.getMessages().findLast(\n (message) => message.role === \"assistant\",\n ) as ThreadAssistantMessage | undefined;\n if (\n !assistant ||\n assistant.status?.type !== \"requires-action\" ||\n assistant.status.reason !== reason\n ) {\n return null;\n }\n return assistant;\n }\n\n getPendingInterrupts(): {\n messageId: string;\n interrupts: readonly AgUiInterrupt[];\n } | null {\n const assistant = this.findRequiresActionAssistant(\"interrupt\");\n if (!assistant) return null;\n const stored = (\n assistant.metadata.custom[AG_UI_METADATA_NAMESPACE] as\n | AgUiCustomMetadata\n | undefined\n )?.interrupts;\n if (!stored?.length) return null;\n return { messageId: assistant.id, interrupts: stored };\n }\n\n getPendingToolCalls(): {\n messageId: string;\n toolCallIds: string[];\n } | null {\n const assistant = this.findRequiresActionAssistant(\"tool-calls\");\n if (!assistant) return null;\n const toolCallIds: string[] = [];\n for (const part of assistant.content) {\n if (part.type !== \"tool-call\") continue;\n if (isResolvedToolCall(part)) continue;\n toolCallIds.push(part.toolCallId);\n }\n if (toolCallIds.length === 0) return null;\n return { messageId: assistant.id, toolCallIds };\n }\n\n async submitInterruptResponses(\n responses: readonly AgUiResumeEntry[],\n ): Promise<void> {\n const pending = this.getPendingInterrupts();\n if (!pending) {\n throw new Error(\n \"[agui] submitInterruptResponses: no pending interrupts on this thread\",\n );\n }\n\n const responsesById = this.collectInterruptResponses(\n \"submitInterruptResponses\",\n pending.interrupts,\n responses,\n );\n\n const openIds = pending.interrupts.map((i) => i.id);\n const missing = openIds.filter((id) => !responsesById.has(id));\n if (missing.length > 0) {\n throw new Error(\n `[agui] submitInterruptResponses: missing responses for open interrupts: ${missing.join(\", \")}`,\n );\n }\n\n const now = Date.now();\n for (const interrupt of pending.interrupts) {\n if (!interrupt.expiresAt) continue;\n const expiry = new Date(interrupt.expiresAt).getTime();\n if (Number.isNaN(expiry)) {\n throw new Error(\n `[agui] submitInterruptResponses: interrupt ${interrupt.id} has malformed expiresAt \"${interrupt.expiresAt}\"`,\n );\n }\n if (expiry <= now) {\n throw new Error(\n `[agui] submitInterruptResponses: interrupt ${interrupt.id} expired at ${interrupt.expiresAt}`,\n );\n }\n }\n\n const resume: AgUiResumeEntry[] = openIds.map((id) =>\n responsesById.get(id)!,\n );\n\n if (this.isRunningFlag) {\n throw new Error(\n \"[agui] submitInterruptResponses: a run is already in progress\",\n );\n }\n\n this.clearPendingInterrupts(pending.messageId);\n await this.startRun(pending.messageId, this.lastRunConfig, resume);\n }\n\n async steerAway(\n message: CreateAppendMessage,\n responses?: readonly AgUiResumeEntry[],\n ): Promise<void> {\n const pending = this.getPendingInterrupts();\n if (!pending) {\n const pendingTools = this.getPendingToolCalls();\n if (pendingTools) {\n if (responses?.length) {\n throw new Error(\n \"[agui] steerAway: responses are only valid for pending interrupts\",\n );\n }\n if (this.isRunningFlag) {\n throw new Error(\"[agui] steerAway: a run is already in progress\");\n }\n this.cancelUnresolvedToolCalls(pendingTools.messageId);\n this.maybeCompleteAfterToolResults(pendingTools.messageId);\n const normalized = this.toAppendMessage(message);\n const threadMessageId = this.appendEntry(normalized);\n await this.startRun(threadMessageId, normalized.runConfig);\n return;\n }\n if (responses?.length) {\n throw new Error(\n \"[agui] steerAway: no pending interrupts on this thread\",\n );\n }\n await this.append(this.toAppendMessage(message));\n return;\n }\n\n const resume = this.resolveSteerAwayResume(pending.interrupts, responses);\n\n if (this.isRunningFlag) {\n throw new Error(\"[agui] steerAway: a run is already in progress\");\n }\n\n const normalized = this.toAppendMessage(message);\n this.clearPendingInterrupts(pending.messageId);\n const threadMessageId = this.appendEntry(normalized);\n await this.startRun(threadMessageId, normalized.runConfig, resume);\n }\n\n private resolveSteerAwayResume(\n interrupts: readonly AgUiInterrupt[],\n responses: readonly AgUiResumeEntry[] | undefined,\n ): AgUiResumeEntry[] {\n const responsesById = this.collectInterruptResponses(\n \"steerAway\",\n interrupts,\n responses ?? [],\n );\n return interrupts.map(\n (interrupt) =>\n responsesById.get(interrupt.id) ?? {\n interruptId: interrupt.id,\n status: \"cancelled\",\n },\n );\n }\n\n private collectInterruptResponses(\n method: \"submitInterruptResponses\" | \"steerAway\",\n interrupts: readonly AgUiInterrupt[],\n responses: readonly AgUiResumeEntry[],\n ): Map<string, AgUiResumeEntry> {\n const known = new Set(interrupts.map((interrupt) => interrupt.id));\n const responsesById = new Map<string, AgUiResumeEntry>();\n for (const entry of responses) {\n if (!entry || typeof entry.interruptId !== \"string\") {\n throw new Error(\n `[agui] ${method}: every entry must have an interruptId`,\n );\n }\n if (entry.status !== \"resolved\" && entry.status !== \"cancelled\") {\n throw new Error(\n `[agui] ${method}: invalid status \"${entry.status}\" for interrupt ${entry.interruptId}`,\n );\n }\n if (!known.has(entry.interruptId)) {\n throw new Error(\n `[agui] ${method}: unknown interrupt id ${entry.interruptId}`,\n );\n }\n if (responsesById.has(entry.interruptId)) {\n throw new Error(\n `[agui] ${method}: duplicate response for interrupt ${entry.interruptId}`,\n );\n }\n responsesById.set(entry.interruptId, entry);\n }\n return responsesById;\n }\n\n private toAppendMessage(message: CreateAppendMessage): AppendMessage {\n if (typeof message === \"string\") {\n return {\n createdAt: new Date(),\n parentId: this.repository.headId,\n sourceId: null,\n runConfig: {},\n role: \"user\",\n content: [{ type: \"text\", text: message }],\n attachments: [],\n metadata: { custom: {} },\n };\n }\n return {\n createdAt: message.createdAt ?? new Date(),\n parentId: message.parentId ?? this.repository.headId,\n sourceId: message.sourceId ?? null,\n role: message.role ?? \"user\",\n content: message.content,\n attachments: message.attachments ?? [],\n metadata: message.metadata ?? { custom: {} },\n runConfig: message.runConfig ?? {},\n startRun: message.startRun,\n } as AppendMessage;\n }\n\n private clearPendingInterrupts(messageId: string): void {\n const touched = this.updateMessage(messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n const assistant = message as ThreadAssistantMessage;\n if (\n assistant.status?.type !== \"requires-action\" ||\n assistant.status.reason !== \"interrupt\"\n ) {\n return assistant;\n }\n const aguiMeta = assistant.metadata.custom[AG_UI_METADATA_NAMESPACE] as\n | AgUiCustomMetadata\n | undefined;\n const { interrupts: _drop, ...restAgui } = aguiMeta ?? {};\n const newCustom = { ...assistant.metadata.custom };\n if (Object.keys(restAgui).length > 0) {\n newCustom[AG_UI_METADATA_NAMESPACE] = restAgui;\n } else {\n delete newCustom[AG_UI_METADATA_NAMESPACE];\n }\n return {\n ...assistant,\n status: { type: \"complete\" as const, reason: \"unknown\" as const },\n metadata: { ...assistant.metadata, custom: newCustom },\n };\n });\n if (touched) {\n this.notifyUpdate();\n }\n }\n\n findMessageIdForToolCall(toolCallId: string): string | undefined {\n let fallbackMessageId: string | undefined;\n const messages = this.getMessages();\n for (let index = messages.length - 1; index >= 0; index--) {\n const message = messages[index];\n if (!message || message.role !== \"assistant\") continue;\n for (const part of message.content) {\n if (part.type !== \"tool-call\" || part.toolCallId !== toolCallId)\n continue;\n if (!isResolvedToolCall(part)) {\n return message.id;\n }\n fallbackMessageId ??= message.id;\n }\n }\n return fallbackMessageId;\n }\n\n private cancelUnresolvedToolCalls(messageId: string): void {\n const updated = this.updateMessage(messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n const assistant = message as ThreadAssistantMessage;\n const content = assistant.content.map((part) => {\n if (part.type !== \"tool-call\" || isResolvedToolCall(part)) return part;\n return {\n ...part,\n result: { error: \"Tool call cancelled by user\" },\n isError: true,\n };\n });\n return { ...assistant, content };\n });\n if (updated) this.notifyUpdate();\n }\n\n addToolResult(options: AddToolResultOptions): void {\n const updated = this.updateMessage(options.messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n const assistant = message as ThreadAssistantMessage;\n let matchedToolCall = false;\n const content = assistant.content.map((part) => {\n if (part.type !== \"tool-call\" || part.toolCallId !== options.toolCallId)\n return part;\n matchedToolCall = true;\n return {\n ...part,\n result: options.result,\n artifact: options.artifact,\n isError: options.isError,\n };\n });\n if (!matchedToolCall) return message;\n return { ...assistant, content };\n });\n\n if (!updated) return;\n this.notifyUpdate();\n this.maybeResumeAfterToolResults(options.messageId);\n }\n\n // The continuation fires whether the frontend result lands before\n // RUN_FINISHED (the status flips to requires-action only later, while the\n // run is still draining) or after it.\n private maybeResumeAfterToolResults(messageId: string): void {\n if (!this.maybeCompleteAfterToolResults(messageId)) return;\n\n if (this.isRunningFlag) {\n // A run is still draining (RUN_FINISHED arrived but the stream has not\n // closed). Defer until startRun's tail so we never start two runs.\n this.pendingResumeMessageId = messageId;\n return;\n }\n this.startResumeRun(messageId);\n }\n\n private maybeCompleteAfterToolResults(messageId: string): boolean {\n const message = this.tryGetMessage(messageId)?.message;\n if (!message || message.role !== \"assistant\") return false;\n const assistant = message as ThreadAssistantMessage;\n if (\n assistant.status?.type !== \"requires-action\" ||\n assistant.status.reason !== \"tool-calls\"\n ) {\n return false;\n }\n const allResolved = assistant.content.every(\n (part) => part.type !== \"tool-call\" || isResolvedToolCall(part),\n );\n if (!allResolved) return false;\n\n const updated = this.updateMessage(messageId, (current) =>\n current.role === \"assistant\"\n ? {\n ...(current as ThreadAssistantMessage),\n status: { type: \"complete\" as const, reason: \"unknown\" as const },\n }\n : current,\n );\n if (!updated) return false;\n this.notifyUpdate();\n this.persistAssistantHistory(messageId);\n return true;\n }\n\n private startResumeRun(messageId: string): void {\n void this.startRun(messageId, this.lastRunConfig).catch((error) => {\n this.onError?.(error instanceof Error ? error : new Error(String(error)));\n });\n }\n\n applyExternalMessages(messages: readonly ThreadMessage[]): void {\n this.assistantHistoryParents.clear();\n\n if (messages.length === 0) {\n this.clearRepository();\n } else {\n let expectedParentId: string | null = null;\n let lastAppliedId: string | null = null;\n let hardReplace = false;\n const seen = new Set<string>();\n\n for (const message of messages) {\n if (seen.has(message.id)) continue;\n seen.add(message.id);\n const existing = this.tryGetMessage(message.id);\n if (existing && existing.parentId !== expectedParentId) {\n hardReplace = true;\n break;\n }\n this.addOrUpdateMessage(expectedParentId, message);\n expectedParentId = message.id;\n lastAppliedId = message.id;\n }\n\n if (hardReplace) {\n this.clearRepository();\n expectedParentId = null;\n lastAppliedId = null;\n seen.clear();\n for (const message of messages) {\n if (seen.has(message.id)) continue;\n seen.add(message.id);\n this.addOrUpdateMessage(expectedParentId, message);\n expectedParentId = message.id;\n lastAppliedId = message.id;\n }\n }\n\n this.resetRepositoryHead(lastAppliedId);\n }\n\n this.recordedHistoryIds.clear();\n for (const { message } of this.getMessageRepository().messages) {\n this.recordedHistoryIds.add(message.id);\n }\n this.notifyUpdate();\n }\n\n private applyExternalMessageRepository(\n loaded: ExportedMessageRepository,\n ): void {\n const headId = loaded.headId ?? loaded.messages.at(-1)?.message.id ?? null;\n const ids = new Set<string>();\n let degenerate = false;\n for (const { message } of loaded.messages) {\n if (ids.has(message.id)) {\n degenerate = true;\n break;\n }\n ids.add(message.id);\n }\n if (headId !== null && !ids.has(headId)) degenerate = true;\n\n if (!degenerate) {\n this.clearRepository();\n let pending = [...loaded.messages];\n const importedIds = new Set<string>();\n\n while (pending.length > 0) {\n const unresolved: typeof pending = [];\n let progressed = false;\n for (const item of pending) {\n if (item.parentId !== null && !importedIds.has(item.parentId)) {\n unresolved.push(item);\n continue;\n }\n this.addOrUpdateMessage(item.parentId, item.message);\n importedIds.add(item.message.id);\n progressed = true;\n }\n if (!progressed) {\n degenerate = true;\n break;\n }\n pending = unresolved;\n }\n }\n\n if (degenerate) {\n this.clearRepository();\n let previousId: string | null = null;\n for (const { message } of loaded.messages) {\n const existing = this.tryGetMessage(message.id);\n this.addOrUpdateMessage(\n existing ? existing.parentId : previousId,\n message,\n );\n previousId = message.id;\n }\n this.resetRepositoryHead(previousId);\n } else {\n this.resetRepositoryHead(headId);\n }\n\n this.assistantHistoryParents.clear();\n this.recordedHistoryIds.clear();\n for (const { message } of loaded.messages) {\n this.recordedHistoryIds.add(message.id);\n }\n this.notifyUpdate();\n }\n\n loadExternalState(state: ReadonlyJSONValue): void {\n this.stateSnapshot = state;\n this.notifyUpdate();\n }\n\n setState(\n next:\n | ReadonlyJSONValue\n | ((prev: ReadonlyJSONValue | undefined) => ReadonlyJSONValue),\n ): void {\n this.stateSnapshot =\n typeof next === \"function\" ? next(this.stateSnapshot) : next;\n this.notifyUpdate();\n }\n\n resetState(): void {\n this.stateSnapshot = undefined;\n this.notifyUpdate();\n }\n\n private async startRun(\n parentId: string | null,\n runConfig?: RunConfig,\n resume?: AgUiResumeEntry[],\n resumeStream?: ResumeStream,\n ): Promise<void> {\n const normalizedRunConfig = runConfig ?? {};\n this.lastRunConfig = normalizedRunConfig;\n const parent = parentId === null ? undefined : this.tryGetMessage(parentId);\n const shouldEagerlyInsertAssistant =\n parentId !== null &&\n parent !== undefined &&\n parentId !== this.repository.headId;\n const historicalMessages = [\n ...(shouldEagerlyInsertAssistant\n ? (this.tryGetMessages(parentId) ?? this.repository.getMessages())\n : this.repository.getMessages()),\n ];\n\n this.pendingError = null;\n const assistantParentId = parent ? parentId : this.repository.headId;\n let assistantMessageId: string | undefined;\n const ensureAssistant = () => {\n if (assistantMessageId) return assistantMessageId;\n const created = this.insertAssistantPlaceholder(\n assistantParentId ?? null,\n );\n assistantMessageId = created;\n this.markPendingAssistantHistory(created, assistantParentId ?? null);\n return created;\n };\n\n if (shouldEagerlyInsertAssistant) ensureAssistant();\n\n const applyUpdate = (update: ChatModelRunResult) => {\n const resolved = this.updateAssistantMessage(ensureAssistant(), update);\n if (resolved !== assistantMessageId) {\n assistantMessageId = resolved;\n }\n };\n\n const aggregator = new RunAggregator({\n showThinking: this.showThinking,\n logger: this.logger,\n emit: applyUpdate,\n onServerMessageId: (serverId) => {\n const placeholder = ensureAssistant();\n if (placeholder === serverId) return;\n if (this.reassignAssistantId(placeholder, serverId)) {\n assistantMessageId = serverId;\n }\n },\n });\n const dispatch = (event: AgUiEvent) => this.handleEvent(aggregator, event);\n\n const abortController = new AbortController();\n const abortSignal = abortController.signal;\n this.abortController = abortController;\n\n let cancelRun = () => dispatch({ type: \"RUN_CANCELLED\" });\n abortSignal.addEventListener(\n \"abort\",\n () => {\n cancelRun();\n this.finishRun(abortController);\n this.onCancel?.();\n },\n { once: true },\n );\n\n this.setRunning(true);\n\n try {\n if (resumeStream) {\n // Cancel flips only the status; an aggregator RUN_CANCELLED would emit an empty snapshot and wipe the replayed content.\n cancelRun = () =>\n applyUpdate({ status: { type: \"incomplete\", reason: \"cancelled\" } });\n await this.consumeResumeStream(resumeStream, {\n runConfig: normalizedRunConfig,\n threadId: this.agent.threadId || \"main\",\n parentId: assistantParentId,\n historicalMessages,\n abortSignal,\n ensureAssistant,\n applyUpdate,\n getAssistantMessageId: () => assistantMessageId,\n });\n } else {\n const runId = generateId();\n aggregator.handle({ type: \"RUN_STARTED\", runId });\n const input = this.buildRunInput(\n runId,\n normalizedRunConfig,\n historicalMessages,\n resume,\n );\n const subscriber = createAgUiSubscriber({\n dispatch,\n runId,\n logger: this.logger,\n onRunFailed: (error) => {\n this.pendingError = error;\n this.onError?.(error);\n },\n });\n try {\n (this.agent as any).messages = input.messages;\n (this.agent as any).threadId = input.threadId;\n (this.agent as any).state = input.state ?? null;\n } catch {\n // ignore\n }\n await (this.agent as any).runAgent(input, subscriber, {\n signal: abortSignal,\n });\n }\n } catch (error) {\n if (!abortSignal.aborted) {\n const err = error instanceof Error ? error : new Error(String(error));\n dispatch({ type: \"RUN_ERROR\", message: err.message });\n this.onError?.(err);\n this.pendingError = this.pendingError ?? err;\n }\n } finally {\n this.finishRun(abortController);\n }\n\n if (this.pendingError) {\n const err = this.pendingError;\n this.pendingError = null;\n this.pendingResumeMessageId = null;\n throw err;\n }\n\n // A tool result that landed before the run settled deferred its\n // continuation here so a second run never overlaps the first.\n if (this.pendingResumeMessageId !== null) {\n const resumeMessageId = this.pendingResumeMessageId;\n this.pendingResumeMessageId = null;\n if (!abortSignal.aborted) {\n this.startResumeRun(resumeMessageId);\n }\n }\n }\n\n // Replays a persisted run's snapshots into the existing assistant message, bypassing agent.runAgent so it is not re-invoked.\n private async consumeResumeStream(\n stream: ResumeStream,\n ctx: {\n runConfig: RunConfig;\n threadId: string;\n parentId: string | null;\n historicalMessages: readonly ThreadMessage[];\n abortSignal: AbortSignal;\n ensureAssistant: () => string;\n applyUpdate: (update: ChatModelRunResult) => void;\n getAssistantMessageId: () => string | undefined;\n },\n ): Promise<void> {\n const assistantId = ctx.ensureAssistant();\n const currentId = () => ctx.getAssistantMessageId() ?? assistantId;\n const options: ChatModelRunOptions = {\n messages: ctx.historicalMessages,\n runConfig: ctx.runConfig,\n abortSignal: ctx.abortSignal,\n context: this.runtime?.thread.getModelContext() ?? {},\n unstable_assistantMessageId: assistantId,\n unstable_threadId: ctx.threadId,\n unstable_parentId: ctx.parentId,\n unstable_getMessage: () => {\n const message = this.tryGetMessage(currentId())?.message;\n if (!message) {\n throw new Error(\n \"[agui] resume stream requested the assistant message before it existed\",\n );\n }\n return message;\n },\n };\n\n try {\n for await (const result of stream(options)) {\n if (ctx.abortSignal.aborted) return;\n ctx.applyUpdate(result);\n }\n } catch (error) {\n if (ctx.abortSignal.aborted) return;\n const err = error instanceof Error ? error : new Error(String(error));\n ctx.applyUpdate({\n status: { type: \"incomplete\", reason: \"error\", error: err.message },\n });\n this.onError?.(err);\n this.pendingError = this.pendingError ?? err;\n return;\n }\n\n if (ctx.abortSignal.aborted) return;\n const current = this.tryGetMessage(currentId())?.message;\n if (!current || current.status?.type === \"running\") {\n ctx.applyUpdate({ status: { type: \"complete\", reason: \"unknown\" } });\n }\n }\n\n private buildRunInput(\n runId: string,\n runConfig: RunConfig | undefined,\n historyMessages: readonly ThreadMessage[] | undefined,\n resume?: AgUiResumeEntry[],\n ) {\n const threadId = this.agent.threadId || \"main\";\n const messages = toAgUiMessages(\n historyMessages ?? this.repository.getMessages(),\n );\n const context = this.runtime?.thread.getModelContext();\n return {\n threadId,\n runId,\n state: this.stateSnapshot ?? null,\n messages,\n tools: toAgUiTools(context?.tools),\n context: context?.system\n ? [{ description: \"system\", value: context.system }]\n : [],\n forwardedProps: {\n ...(context?.callSettings ?? {}),\n ...(context?.config ?? {}),\n ...(runConfig?.custom ? { runConfig: runConfig.custom } : {}),\n },\n ...(resume !== undefined ? { resume } : {}),\n };\n }\n\n private installResumeShim(): void {\n const agent = this.agent as any;\n if (agent[symbolResumeShim]) return;\n agent[symbolResumeShim] = true;\n const onInstance = Object.hasOwn(agent, \"prepareRunAgentInput\");\n const original = onInstance\n ? agent.prepareRunAgentInput\n : Object.getPrototypeOf(agent)?.prepareRunAgentInput;\n if (typeof original !== \"function\") return;\n agent.prepareRunAgentInput = function (\n this: unknown,\n params: { resume?: unknown } | undefined,\n ) {\n const input = original.call(this, params);\n if (params?.resume !== undefined && input && typeof input === \"object\") {\n return { ...(input as object), resume: params.resume };\n }\n return input;\n };\n }\n\n private setRunning(running: boolean) {\n this.isRunningFlag = running;\n this.notifyUpdate();\n }\n\n private finishRun(controller: AbortController | null) {\n if (this.abortController === controller) {\n this.abortController = null;\n }\n this.setRunning(false);\n }\n\n private insertAssistantPlaceholder(parentId: string | null): string {\n const id = generateOptimisticId();\n const assistant: ThreadAssistantMessage = {\n id,\n role: \"assistant\",\n createdAt: new Date(),\n status: { type: \"running\" },\n content: [],\n metadata: {\n unstable_state: this.stateSnapshot ?? null,\n unstable_annotations: [],\n unstable_data: [],\n steps: [],\n isOptimistic: true,\n custom: {},\n },\n };\n this.addOrUpdateMessage(parentId ?? this.repository.headId, assistant);\n this.switchToBranch(id);\n this.notifyUpdate();\n return id;\n }\n\n private reassignAssistantId(oldId: string, newId: string): boolean {\n if (oldId === newId) return true;\n const oldItem = this.tryGetMessage(oldId);\n if (!oldItem) return false;\n\n const collidesWithExisting = this.hasMessage(newId);\n\n if (collidesWithExisting) {\n this.logger.debug?.(\n \"[agui] reassignAssistantId: server id already present in messages or repository, dropping placeholder\",\n { oldId, newId },\n );\n this.deleteMessage(oldId, oldItem.parentId ?? null);\n } else {\n const { isOptimistic: _, ...metadata } = oldItem.message.metadata;\n this.addOrUpdateMessage(oldItem.parentId, {\n ...oldItem.message,\n id: newId,\n metadata,\n } as ThreadMessage);\n this.switchToBranch(newId);\n this.tryDeleteMessage(oldId);\n }\n\n const pendingParent = this.assistantHistoryParents.get(oldId);\n if (pendingParent !== undefined) {\n this.assistantHistoryParents.delete(oldId);\n if (!collidesWithExisting && !this.assistantHistoryParents.has(newId)) {\n this.assistantHistoryParents.set(newId, pendingParent);\n }\n }\n\n if (this.recordedHistoryIds.has(oldId)) {\n this.recordedHistoryIds.delete(oldId);\n if (!collidesWithExisting) {\n this.recordedHistoryIds.add(newId);\n }\n }\n\n this.notifyUpdate();\n return !collidesWithExisting;\n }\n\n private updateAssistantMessage(\n messageId: string,\n update: ChatModelRunResult,\n ): string {\n let latestStatus: MessageStatus | undefined;\n const touched = this.updateMessage(messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n const assistant = message as ThreadAssistantMessage;\n const metadata = update.metadata\n ? this.mergeAssistantMetadata(assistant.metadata, update.metadata)\n : assistant.metadata;\n latestStatus = update.status ?? assistant.status;\n const content =\n update.content !== undefined\n ? this.preserveToolResults(\n assistant.content,\n update.content as ThreadAssistantMessage[\"content\"],\n )\n : assistant.content;\n return {\n ...assistant,\n content,\n status: latestStatus,\n metadata,\n };\n });\n if (!touched) return messageId;\n\n let resolvedMessageId = messageId;\n const isSettled =\n latestStatus !== undefined && latestStatus.type !== \"running\";\n if (isSettled && isOptimisticId(messageId)) {\n const stableId = generateId();\n this.reassignAssistantId(messageId, stableId);\n resolvedMessageId = stableId;\n } else {\n this.notifyUpdate();\n }\n if (this.isPersistableStatus(latestStatus)) {\n this.persistAssistantHistory(resolvedMessageId);\n }\n this.maybeResumeAfterToolResults(resolvedMessageId);\n return resolvedMessageId;\n }\n\n // The RunAggregator rebuilds the assistant content from stream events only,\n // so a fresh snapshot omits results injected via addToolResult (frontend tool\n // execution). Carry those results forward so the aggregator never clobbers\n // them. Results are only ever added in this flow, so preserving is safe.\n private preserveToolResults(\n previous: ThreadAssistantMessage[\"content\"],\n next: ThreadAssistantMessage[\"content\"],\n ): ThreadAssistantMessage[\"content\"] {\n const resolved = new Map<string, ToolCallMessagePart>();\n for (const part of previous) {\n if (part.type === \"tool-call\" && isResolvedToolCall(part)) {\n resolved.set(part.toolCallId, part);\n }\n }\n if (resolved.size === 0) return next;\n\n let changed = false;\n const merged = next.map((part) => {\n if (part.type !== \"tool-call\" || isResolvedToolCall(part)) return part;\n const prior = resolved.get(part.toolCallId);\n if (!prior) return part;\n changed = true;\n return {\n ...part,\n result: prior.result,\n ...(prior.artifact !== undefined ? { artifact: prior.artifact } : {}),\n ...(prior.isError !== undefined ? { isError: prior.isError } : {}),\n };\n });\n return changed ? (merged as ThreadAssistantMessage[\"content\"]) : next;\n }\n\n private mergeAssistantMetadata(\n current: ThreadAssistantMessage[\"metadata\"],\n incoming: NonNullable<ChatModelRunResult[\"metadata\"]>,\n ): ThreadAssistantMessage[\"metadata\"] {\n const annotations = incoming.unstable_annotations\n ? [...current.unstable_annotations, ...incoming.unstable_annotations]\n : current.unstable_annotations;\n const data = incoming.unstable_data\n ? [...current.unstable_data, ...incoming.unstable_data]\n : current.unstable_data;\n const steps = incoming.steps\n ? [...current.steps, ...incoming.steps]\n : current.steps;\n return {\n unstable_state:\n incoming.unstable_state !== undefined\n ? incoming.unstable_state\n : current.unstable_state,\n unstable_annotations: annotations,\n unstable_data: data,\n steps,\n ...(current.isOptimistic ? { isOptimistic: true } : {}),\n ...(incoming.timing ? { timing: incoming.timing } : {}),\n custom: incoming.custom\n ? { ...current.custom, ...incoming.custom }\n : current.custom,\n };\n }\n\n private handleEvent(aggregator: RunAggregator, event: AgUiEvent) {\n switch (event.type) {\n case \"STATE_SNAPSHOT\": {\n this.stateSnapshot = event.snapshot as ReadonlyJSONValue;\n this.notifyUpdate();\n return;\n }\n case \"STATE_DELTA\": {\n if (event.delta.length === 0) return;\n try {\n const state = this.stateSnapshot ?? {};\n const result = jsonpatch.applyPatch(\n state,\n event.delta as Operation[],\n /* validateOperation */ true,\n /* mutateDocument */ false,\n );\n this.stateSnapshot = result.newDocument as ReadonlyJSONValue;\n this.notifyUpdate();\n } catch (error) {\n this.logger.error?.(\"[agui] failed to apply state delta\", error);\n }\n return;\n }\n case \"MESSAGES_SNAPSHOT\": {\n this.importMessagesSnapshot(event.messages);\n return;\n }\n case \"TOOL_CALL_RESULT\": {\n if (!aggregator.hasToolCall(event.toolCallId)) {\n const messageId = this.findMessageIdForToolCall(event.toolCallId);\n if (messageId !== undefined) {\n this.applyCrossRunToolResult(messageId, event);\n return;\n }\n }\n aggregator.handle(event);\n return;\n }\n case \"ACTIVITY_SNAPSHOT\": {\n const toolCallId = event.content[\"toolCallId\"];\n if (\n event.activityType === MCP_APPS_ACTIVITY_TYPE &&\n typeof toolCallId === \"string\" &&\n !aggregator.hasToolCall(toolCallId)\n ) {\n const messageId = this.findMessageIdForToolCall(toolCallId);\n if (messageId !== undefined) {\n this.applyCrossRunActivitySnapshot(messageId, toolCallId, event);\n return;\n }\n }\n aggregator.handle(event);\n return;\n }\n default:\n aggregator.handle(event);\n }\n }\n\n private applyCrossRunToolResult(\n messageId: string,\n event: Extract<AgUiEvent, { type: \"TOOL_CALL_RESULT\" }>,\n ): void {\n const updated = this.updateMessage(messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n const assistant = message as ThreadAssistantMessage;\n let matchedToolCall = false;\n const content = assistant.content.map((part) => {\n if (part.type !== \"tool-call\" || part.toolCallId !== event.toolCallId)\n return part;\n matchedToolCall = true;\n // An applied activity snapshot owns part.result; a later result only\n // fills what is missing, mirroring the aggregator's finishToolCall.\n // The aggregator's flag is set only when the snapshot carried a\n // result, so app presence alone is not enough: the current result\n // must be CallToolResult-shaped (a required content array).\n const snapshotResultApplied =\n part.mcp?.app !== undefined &&\n isPlainObject(part.result) &&\n Array.isArray((part.result as Record<string, unknown>)[\"content\"]);\n if (snapshotResultApplied) {\n return {\n ...part,\n ...(part.modelContent === undefined && event.content\n ? {\n modelContent: [\n { type: \"text\" as const, text: event.content },\n ],\n }\n : {}),\n ...(part.isError === undefined\n ? typeof event.mcpResult?.isError === \"boolean\"\n ? { isError: event.mcpResult.isError }\n : event.role === \"tool\"\n ? { isError: false }\n : {}\n : {}),\n ...(event.messageId\n ? { unstable_toolMessageId: event.messageId }\n : {}),\n };\n }\n return {\n ...part,\n result: (event.mcpResult ??\n tryParseJSON(event.content ?? \"\")) as ReadonlyJSONValue,\n ...(event.mcpResult !== undefined\n ? { modelContent: [{ type: \"text\" as const, text: event.content }] }\n : {}),\n ...(typeof event.mcpResult?.isError === \"boolean\"\n ? { isError: event.mcpResult.isError }\n : event.role === \"tool\"\n ? { isError: false }\n : {}),\n ...(event.messageId\n ? { unstable_toolMessageId: event.messageId }\n : {}),\n };\n });\n if (!matchedToolCall) return message;\n return { ...assistant, content };\n });\n\n if (!updated) return;\n this.notifyUpdate();\n // Not maybeResumeAfterToolResults: the delivering run is already in\n // flight, and a resume from the owner would reset the head past it.\n this.maybeCompleteAfterToolResults(messageId);\n }\n\n private applyCrossRunActivitySnapshot(\n messageId: string,\n toolCallId: string,\n event: Extract<AgUiEvent, { type: \"ACTIVITY_SNAPSHOT\" }>,\n ): void {\n const resourceUri = event.content[\"resourceUri\"];\n if (typeof resourceUri !== \"string\" || !isMcpAppUri(resourceUri)) return;\n const serverId = event.content[\"serverId\"];\n const serverHash = event.content[\"serverHash\"];\n const appServerId =\n typeof serverId === \"string\" && serverId.length > 0\n ? serverId\n : typeof serverHash === \"string\" && serverHash.length > 0\n ? serverHash\n : undefined;\n const result = event.content[\"result\"];\n const updated = this.updateMessage(messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n const assistant = message as ThreadAssistantMessage;\n let matchedToolCall = false;\n const content = assistant.content.map((part) => {\n if (part.type !== \"tool-call\" || part.toolCallId !== toolCallId)\n return part;\n matchedToolCall = true;\n return {\n ...part,\n mcp: {\n app: {\n resourceUri,\n ...(appServerId ? { serverId: appServerId } : {}),\n },\n },\n ...(isPlainObject(result)\n ? {\n ...(part.result !== undefined && part.modelContent === undefined\n ? {\n modelContent: [\n {\n type: \"text\" as const,\n text:\n typeof part.result === \"string\"\n ? part.result\n : JSON.stringify(part.result),\n },\n ],\n }\n : {}),\n result: result as ReadonlyJSONValue,\n isError: result[\"isError\"] === true,\n }\n : {}),\n };\n });\n if (!matchedToolCall) return message;\n return { ...assistant, content };\n });\n\n if (!updated) return;\n this.notifyUpdate();\n this.maybeCompleteAfterToolResults(messageId);\n }\n\n private importMessagesSnapshot(rawMessages: readonly unknown[]) {\n try {\n const normalized = fromAgUiMessages(rawMessages, {\n showThinking: this.showThinking,\n });\n const converted: ThreadMessage[] = [];\n for (const message of normalized) {\n try {\n converted.push(\n fromThreadMessageLike(message, generateId(), FALLBACK_USER_STATUS),\n );\n } catch (error) {\n this.logger.error?.(\n \"[agui] failed to import message from snapshot\",\n error,\n );\n }\n }\n this.applyExternalMessages(converted);\n } catch (error) {\n this.logger.error?.(\"[agui] failed to import messages snapshot\", error);\n }\n }\n\n private toThreadMessage(message: AppendMessage): ThreadMessage {\n return fromThreadMessageLike(\n message as any,\n generateId(),\n FALLBACK_USER_STATUS,\n );\n }\n\n private isTerminalStatus(status?: MessageStatus): boolean {\n return status?.type === \"complete\" || status?.type === \"incomplete\";\n }\n\n private isPersistableStatus(status?: MessageStatus): boolean {\n if (this.isTerminalStatus(status)) return true;\n return status?.type === \"requires-action\" && status.reason === \"interrupt\";\n }\n\n private recordHistoryEntry(parentId: string | null, message: ThreadMessage) {\n this.appendHistoryItem(parentId, message);\n }\n\n private markPendingAssistantHistory(\n messageId: string,\n parentId: string | null,\n ) {\n if (!this.history) return;\n this.assistantHistoryParents.set(messageId, parentId);\n }\n\n private persistAssistantHistory(messageId: string) {\n if (!this.history) return;\n const parentId = this.assistantHistoryParents.get(messageId);\n if (parentId === undefined) return;\n const message = this.tryGetMessage(messageId)?.message;\n if (!message || message.role !== \"assistant\") return;\n if (!this.isPersistableStatus(message.status)) return;\n this.assistantHistoryParents.delete(messageId);\n this.appendHistoryItem(parentId, message);\n }\n\n private appendHistoryItem(parentId: string | null, message: ThreadMessage) {\n if (!this.history || this.recordedHistoryIds.has(message.id)) return;\n this.recordedHistoryIds.add(message.id);\n void this.history.append({ parentId, message }).catch((error) => {\n this.recordedHistoryIds.delete(message.id);\n this.logger.error?.(\"[agui] failed to append history entry\", error);\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversions.d.ts","names":[],"sources":["../../../src/runtime/adapter/conversions.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"conversions.d.ts","names":[],"sources":["../../../src/runtime/adapter/conversions.ts"],"mappings":";;;;KAuBK;EACH;EACA;EACA;;KAGG;EACH;EACA;EACA;EACA;EACA;EACA;EACA,uBAAuB;;KAGpB;EACH;EACA;EACA;IAAY;IAAc;;;KAGhB;EAEN;EACA;EACA,kBAAkB;EAClB;EACA,YAAY;;EAGZ;EACA;EACA;EACA;EACA;;KAwcM;;;;;EAKV;;iBAGc,iBACd,8BACA,UAAU,0BACT;iBA8Oa,eACd,mBAAmB,wBAClB;KA+BE;EACH;EACA;EACA;;iBAGc,YACd,OAAO,eAAe,oBACrB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { AG_UI_METADATA_NAMESPACE } from "./run-aggregator.js";
|
|
3
|
-
import {
|
|
3
|
+
import { parseMcpToolCallResult } from "../mcp-tool-result.js";
|
|
4
|
+
import { getAutoStatus, httpUrlPattern, parseDataUrl } from "@assistant-ui/core/internal";
|
|
4
5
|
import { toToolsJSONSchema } from "assistant-stream";
|
|
5
6
|
//#region src/runtime/adapter/conversions.ts
|
|
6
7
|
const isObject = (value) => typeof value === "object" && value !== null;
|
|
@@ -40,15 +41,6 @@ function extractText(content) {
|
|
|
40
41
|
if (!Array.isArray(content)) return "";
|
|
41
42
|
return content.filter((part) => part?.type === "text" && typeof part?.text === "string").map((part) => part.text).join("\n");
|
|
42
43
|
}
|
|
43
|
-
function parseDataUrl(value) {
|
|
44
|
-
const match = value.match(/^data:([^;,]+)(?:;[^;,]+)*;base64,(.+)$/);
|
|
45
|
-
if (!match) return null;
|
|
46
|
-
return {
|
|
47
|
-
mimeType: match[1],
|
|
48
|
-
data: match[2]
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
const httpUrlPattern = /^https?:\/\//i;
|
|
52
44
|
function mediaTypeForMime(mimeType) {
|
|
53
45
|
if (mimeType?.startsWith("image/")) return "image";
|
|
54
46
|
if (mimeType?.startsWith("audio/")) return "audio";
|
|
@@ -335,7 +327,13 @@ function fromAgUiMessages(messages, options) {
|
|
|
335
327
|
if (role === "tool") {
|
|
336
328
|
const toolCallId = getToolCallId(rawMessage) ?? `tool-${generateId()}`;
|
|
337
329
|
const toolMessageId = getString(rawMessage, "id");
|
|
338
|
-
const
|
|
330
|
+
const modelContent = extractText(rawMessage.content);
|
|
331
|
+
const mcpResult = parseMcpToolCallResult(rawMessage, modelContent);
|
|
332
|
+
const mcpModelContent = mcpResult ? [{
|
|
333
|
+
type: "text",
|
|
334
|
+
text: modelContent
|
|
335
|
+
}] : void 0;
|
|
336
|
+
const result = mcpResult ?? (rawMessage.result !== void 0 ? rawMessage.result : typeof rawMessage.content === "string" ? parseJSONText(rawMessage.content) : rawMessage.content);
|
|
339
337
|
const isError = typeof rawMessage.error === "string" || rawMessage.isError === true || rawMessage.status === "error" ? true : rawMessage.isError === false ? false : void 0;
|
|
340
338
|
let updated = false;
|
|
341
339
|
for (let messageIndex = converted.length - 1; messageIndex >= 0 && !updated; messageIndex--) {
|
|
@@ -348,6 +346,7 @@ function fromAgUiMessages(messages, options) {
|
|
|
348
346
|
const updatedPart = {
|
|
349
347
|
...part,
|
|
350
348
|
result,
|
|
349
|
+
...mcpModelContent ? { modelContent: mcpModelContent } : {},
|
|
351
350
|
...isError !== void 0 ? { isError } : {},
|
|
352
351
|
...toolMessageId !== void 0 ? { unstable_toolMessageId: toolMessageId } : {}
|
|
353
352
|
};
|
|
@@ -373,6 +372,7 @@ function fromAgUiMessages(messages, options) {
|
|
|
373
372
|
args: {},
|
|
374
373
|
argsText: "{}",
|
|
375
374
|
result,
|
|
375
|
+
...mcpModelContent ? { modelContent: mcpModelContent } : {},
|
|
376
376
|
...isError !== void 0 ? { isError } : {},
|
|
377
377
|
...toolMessageId !== void 0 ? { unstable_toolMessageId: toolMessageId } : {}
|
|
378
378
|
}]
|
|
@@ -428,8 +428,7 @@ function convertAssistantMessage(message, converted) {
|
|
|
428
428
|
converted.push(assistantMessage);
|
|
429
429
|
for (const { id: toolCallId, part } of toolCalls) {
|
|
430
430
|
if (part.result === void 0) continue;
|
|
431
|
-
const
|
|
432
|
-
const resultContent = modelText.length > 0 ? modelText : typeof part.result === "string" ? part.result : JSON.stringify(part.result);
|
|
431
|
+
const resultContent = part.modelContent !== void 0 ? extractText(part.modelContent) : typeof part.result === "string" ? part.result : JSON.stringify(part.result);
|
|
433
432
|
const toolMessage = {
|
|
434
433
|
id: part.unstable_toolMessageId ?? `${toolCallId}:tool`,
|
|
435
434
|
role: "tool",
|