@assistant-ui/react-ag-ui 0.0.32 → 0.0.34

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.
@@ -1 +1 @@
1
- {"version":3,"file":"AgUiThreadRuntimeCore.d.ts","names":[],"sources":["../../src/runtime/AgUiThreadRuntimeCore.ts"],"mappings":";;;;;;;KAoCK,SAAA,GAAY,WAAW,CAAC,aAAA;AAAA,KACxB,eAAA;EACH,QAAA;EACA,QAAA;EACA,SAAA,EAAW,SAAS;EACpB,MAAA;AAAA;AAAA,KAGG,WAAA;EACH,KAAA,EAAO,SAAA;EACP,MAAA,EAAQ,MAAA;EACR,YAAA;EACA,OAAA,IAAW,KAAA,EAAO,KAAA;EAClB,QAAA;EACA,OAAA,GAAU,oBAAA;EACV,YAAA;AAAA;AAAA,cAKW,qBAAA;EAAA,QACH,KAAA;EAAA,QACA,MAAA;EAAA,QACA,YAAA;EAAA,QACA,OAAA;EAAA,QACA,QAAA;EAAA,iBACS,YAAA;EAAA,QAET,OAAA;EAAA,QACA,QAAA;EAAA,QACA,aAAA;EAAA,QACA,eAAA;EAAA,QACA,aAAA;EAAA,QACA,YAAA;EAAA,QACA,OAAA;EAAA,QACA,aAAA;EAAA,iBACS,uBAAA;EAAA,iBACA,kBAAA;EAAA,QACT,UAAA;EAAA,QACA,YAAA;cAEI,OAAA,EAAS,WAAA;EAWrB,aAAA,CAAc,OAAA,EAAS,IAAA,CAAK,WAAA;EAU5B,aAAA,CAAc,OAAA,EAAS,gBAAA;EAIvB,aAAA,CAAA;EAIA,WAAA,CAAA,YAAwB,aAAA;EAIxB,QAAA,CAAA,GAAY,iBAAA;EAIZ,SAAA,CAAA;EAAA,IAII,SAAA,CAAA;EAIJ,eAAA,CAAA,GAAmB,OAAA;EAkCb,MAAA,CAAO,OAAA,EAAS,aAAA,GAAgB,OAAA;EAmBhC,IAAA,CAAK,OAAA,EAAS,aAAA,GAAgB,OAAA;EAI9B,MAAA,CACJ,QAAA,iBACA,MAAA;IAAU,SAAA,GAAY,SAAA;EAAA,IACrB,OAAA;EAOG,MAAA,CAAA,GAAU,OAAA;EAKV,MAAA,CAAO,MAAA,EAAQ,eAAA,GAAkB,OAAA;EAAA,QAa/B,yBAAA;EAOR,oBAAA,CAAA;IACE,SAAA;IACA,UAAA,WAAqB,aAAA;EAAA;EAqBjB,wBAAA,CACJ,SAAA,WAAoB,eAAA,KACnB,OAAA;EAAA,QAyEK,sBAAA;EAgCR,wBAAA,CAAyB,UAAA;EAiBzB,aAAA,CAAc,OAAA,EAAS,oBAAA;EAgEvB,qBAAA,CAAsB,QAAA,WAAmB,aAAA;EAUzC,iBAAA,CAAkB,KAAA,EAAO,iBAAA;EAAA,QAKX,QAAA;EAAA,QAsGN,aAAA;EAAA,QA2BA,iBAAA;EAAA,QAqBA,UAAA;EAAA,QAKA,SAAA;EAAA,QAOA,0BAAA;EAAA,QAqBA,mBAAA;EAAA,QAiCA,sBAAA;EAAA,QAyCA,sBAAA;EAAA,QA4BA,WAAA;EAAA,QAoBA,sBAAA;EAAA,QA0BA,eAAA;EAAA,QAQA,SAAA;EAAA,QAYA,gBAAA;EAAA,QAIA,mBAAA;EAAA,QAKA,kBAAA;EAAA,QAIA,2BAAA;EAAA,QAQA,uBAAA;EAAA,QAWA,iBAAA;AAAA"}
1
+ {"version":3,"file":"AgUiThreadRuntimeCore.d.ts","names":[],"sources":["../../src/runtime/AgUiThreadRuntimeCore.ts"],"mappings":";;;;;;;KAmCK,SAAA,GAAY,WAAW,CAAC,aAAA;AAAA,KACxB,eAAA;EACH,QAAA;EACA,QAAA;EACA,SAAA,EAAW,SAAS;EACpB,MAAA;AAAA;AAAA,KAGG,WAAA;EACH,KAAA,EAAO,SAAA;EACP,MAAA,EAAQ,MAAA;EACR,YAAA;EACA,OAAA,IAAW,KAAA,EAAO,KAAA;EAClB,QAAA;EACA,OAAA,GAAU,oBAAA;EACV,YAAA;AAAA;AAAA,cAKW,qBAAA;EAAA,QACH,KAAA;EAAA,QACA,MAAA;EAAA,QACA,YAAA;EAAA,QACA,OAAA;EAAA,QACA,QAAA;EAAA,iBACS,YAAA;EAAA,QAET,OAAA;EAAA,QACA,QAAA;EAAA,QACA,aAAA;EAAA,QACA,eAAA;EAAA,QACA,aAAA;EAAA,QACA,YAAA;EAAA,QACA,OAAA;EAAA,QACA,aAAA;EAAA,iBACS,uBAAA;EAAA,iBACA,kBAAA;EAAA,QACT,UAAA;EAAA,QACA,YAAA;cAEI,OAAA,EAAS,WAAA;EAWrB,aAAA,CAAc,OAAA,EAAS,IAAA,CAAK,WAAA;EAU5B,aAAA,CAAc,OAAA,EAAS,gBAAA;EAIvB,aAAA;EAIA,WAAA,aAAwB,aAAA;EAIxB,QAAA,IAAY,iBAAA;EAIZ,SAAA;EAAA,IAII,SAAA;EAIJ,eAAA,IAAmB,OAAA;EAkCb,MAAA,CAAO,OAAA,EAAS,aAAA,GAAgB,OAAA;EAmBhC,IAAA,CAAK,OAAA,EAAS,aAAA,GAAgB,OAAA;EAI9B,MAAA,CACJ,QAAA,iBACA,MAAA;IAAU,SAAA,GAAY,SAAA;EAAA,IACrB,OAAA;EAOG,MAAA,IAAU,OAAA;EAKV,MAAA,CAAO,MAAA,EAAQ,eAAA,GAAkB,OAAA;EAAA,QAa/B,yBAAA;EAOR,oBAAA;IACE,SAAA;IACA,UAAA,WAAqB,aAAA;EAAA;EAqBjB,wBAAA,CACJ,SAAA,WAAoB,eAAA,KACnB,OAAA;EAAA,QAyEK,sBAAA;EAgCR,wBAAA,CAAyB,UAAA;EAiBzB,aAAA,CAAc,OAAA,EAAS,oBAAA;EAgEvB,qBAAA,CAAsB,QAAA,WAAmB,aAAA;EAUzC,iBAAA,CAAkB,KAAA,EAAO,iBAAA;EAAA,QAKX,QAAA;EAAA,QAsGN,aAAA;EAAA,QA2BA,iBAAA;EAAA,QAqBA,UAAA;EAAA,QAKA,SAAA;EAAA,QAOA,0BAAA;EAAA,QAqBA,mBAAA;EAAA,QAiCA,sBAAA;EAAA,QAyCA,sBAAA;EAAA,QA4BA,WAAA;EAAA,QAoBA,sBAAA;EAAA,QA0BA,eAAA;EAAA,QAQA,SAAA;EAAA,QAYA,gBAAA;EAAA,QAIA,mBAAA;EAAA,QAKA,kBAAA;EAAA,QAIA,2BAAA;EAAA,QAQA,uBAAA;EAAA,QAWA,iBAAA;AAAA"}
@@ -2,8 +2,11 @@
2
2
  import { AG_UI_METADATA_NAMESPACE, RunAggregator } from "./adapter/run-aggregator.js";
3
3
  import { fromAgUiMessages, toAgUiMessages, toAgUiTools } from "./adapter/conversions.js";
4
4
  import { createAgUiSubscriber } from "./adapter/subscriber.js";
5
- import { fromThreadMessageLike, generateId, generateOptimisticId, isOptimisticId } from "@assistant-ui/core/internal";
5
+ import { fromThreadMessageLike, generateId } from "@assistant-ui/core/internal";
6
6
  //#region src/runtime/AgUiThreadRuntimeCore.ts
7
+ const optimisticPrefix = "__optimistic__";
8
+ const generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
9
+ const isOptimisticId = (id) => id.startsWith(optimisticPrefix);
7
10
  const symbolResumeShim = Symbol("agui-resume-shim");
8
11
  const FALLBACK_USER_STATUS = {
9
12
  type: "complete",
@@ -1 +1 @@
1
- {"version":3,"file":"AgUiThreadRuntimeCore.js","names":[],"sources":["../../src/runtime/AgUiThreadRuntimeCore.ts"],"sourcesContent":["\"use client\";\n\nimport {\n generateId,\n generateOptimisticId,\n isOptimisticId,\n fromThreadMessageLike,\n} from \"@assistant-ui/core/internal\";\nimport type {\n AddToolResultOptions,\n AppendMessage,\n AssistantRuntime,\n ChatModelRunResult,\n MessageStatus,\n ThreadAssistantMessage,\n ThreadHistoryAdapter,\n ThreadMessage,\n} from \"@assistant-ui/core\";\nimport type { HttpAgent } from \"@ag-ui/client\";\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} from \"./adapter/run-aggregator\";\nimport {\n fromAgUiMessages,\n toAgUiMessages,\n toAgUiTools,\n} from \"./adapter/conversions\";\nimport { createAgUiSubscriber } from \"./adapter/subscriber\";\n\nconst symbolResumeShim = Symbol(\"agui-resume-shim\");\n\ntype RunConfig = NonNullable<AppendMessage[\"runConfig\"]>;\ntype ResumeRunConfig = {\n parentId: string | null;\n sourceId: string | null;\n runConfig: RunConfig;\n stream?: unknown;\n};\n\ntype CoreOptions = {\n agent: HttpAgent;\n logger: Logger;\n showThinking: boolean;\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: HttpAgent;\n private logger: Logger;\n private showThinking: boolean;\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 messages: ThreadMessage[] = [];\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\n constructor(options: CoreOptions) {\n this.agent = options.agent;\n this.logger = options.logger;\n this.showThinking = options.showThinking;\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.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.messages;\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 const messages = repo.messages.map((item) => item.message);\n this.applyExternalMessages(messages);\n\n if (repo.unstable_resume) {\n const parentId = repo.headId ?? messages.at(-1)?.id ?? null;\n await this.startRun(parentId, this.lastRunConfig);\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) this.assertNoPendingInterrupts();\n if (message.sourceId) {\n this.messages = this.messages.filter(\n (entry) => entry.id !== message.sourceId,\n );\n }\n this.resetHead(message.parentId);\n\n const threadMessage = this.toThreadMessage(message);\n this.messages = [...this.messages, threadMessage];\n this.notifyUpdate();\n this.recordHistoryEntry(message.parentId ?? null, threadMessage);\n\n if (!startRun) return;\n await this.startRun(threadMessage.id, message.runConfig);\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.resetHead(parentId);\n this.notifyUpdate();\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 if (config.stream) {\n this.logger.debug?.(\n \"[agui] resume stream is not supported, falling back to regular run\",\n );\n }\n await this.startRun(\n config.parentId,\n config.runConfig ?? this.lastRunConfig,\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 getPendingInterrupts(): {\n messageId: string;\n interrupts: readonly AgUiInterrupt[];\n } | null {\n const assistant = this.messages.findLast((m) => m.role === \"assistant\") as\n | ThreadAssistantMessage\n | undefined;\n if (\n !assistant ||\n assistant.status?.type !== \"requires-action\" ||\n assistant.status.reason !== \"interrupt\"\n ) {\n return null;\n }\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 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(\n (id) => 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 private clearPendingInterrupts(messageId: string): void {\n let touched = false;\n this.messages = this.messages.map((message) => {\n if (message.id !== messageId || message.role !== \"assistant\")\n 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 touched = true;\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) this.notifyUpdate();\n }\n\n findMessageIdForToolCall(toolCallId: string): string | undefined {\n let fallbackMessageId: string | undefined;\n for (let index = this.messages.length - 1; index >= 0; index--) {\n const message = this.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 (!(\"result\" in part) || part.result === undefined) {\n return message.id;\n }\n fallbackMessageId ??= message.id;\n }\n }\n return fallbackMessageId;\n }\n\n addToolResult(options: AddToolResultOptions): void {\n let updated = false;\n let shouldResume = false;\n this.messages = this.messages.map((message) => {\n if (message.id !== options.messageId || message.role !== \"assistant\")\n 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 updated = true;\n\n if (\n assistant.status?.type === \"requires-action\" &&\n assistant.status.reason === \"tool-calls\" &&\n content.every(\n (part) =>\n part.type !== \"tool-call\" ||\n (\"result\" in part && part.result !== undefined),\n )\n ) {\n shouldResume = true;\n return {\n ...assistant,\n content,\n status: { type: \"complete\" as const, reason: \"unknown\" as const },\n };\n }\n\n return {\n ...assistant,\n content,\n };\n });\n\n if (updated) {\n this.notifyUpdate();\n\n if (shouldResume) {\n this.persistAssistantHistory(options.messageId);\n\n if (!this.isRunningFlag) {\n void this.startRun(options.messageId, this.lastRunConfig).catch(\n (error) => {\n this.onError?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n },\n );\n }\n }\n }\n }\n\n applyExternalMessages(messages: readonly ThreadMessage[]): void {\n this.assistantHistoryParents.clear();\n this.messages = [...messages];\n this.recordedHistoryIds.clear();\n for (const message of this.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 private async startRun(\n parentId: string | null,\n runConfig?: RunConfig,\n resume?: AgUiResumeEntry[],\n ): Promise<void> {\n const normalizedRunConfig = runConfig ?? {};\n this.lastRunConfig = normalizedRunConfig;\n this.resetHead(parentId);\n const historicalMessages = [...this.messages];\n\n const runId = generateId();\n this.pendingError = null;\n const input = this.buildRunInput(\n runId,\n normalizedRunConfig,\n historicalMessages,\n resume,\n );\n const assistantParentId = parentId ?? this.messages.at(-1)?.id ?? null;\n let assistantMessageId: string | undefined;\n const ensureAssistant = () => {\n if (assistantMessageId) return assistantMessageId;\n const created = this.insertAssistantPlaceholder();\n assistantMessageId = created;\n this.markPendingAssistantHistory(created, assistantParentId ?? null);\n return created;\n };\n\n const aggregator = new RunAggregator({\n showThinking: this.showThinking,\n logger: this.logger,\n emit: (update) => {\n const resolved = this.updateAssistantMessage(ensureAssistant(), update);\n if (resolved !== assistantMessageId) {\n assistantMessageId = resolved;\n }\n },\n onServerMessageId: (serverId) => {\n const placeholder = ensureAssistant();\n if (placeholder === serverId) return;\n this.reassignAssistantId(placeholder, serverId);\n assistantMessageId = serverId;\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 abortSignal.addEventListener(\n \"abort\",\n () => {\n dispatch({ type: \"RUN_CANCELLED\" });\n this.finishRun(abortController);\n this.onCancel?.();\n },\n { once: true },\n );\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\n aggregator.handle({ type: \"RUN_STARTED\", runId });\n this.setRunning(true);\n\n try {\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 } 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 throw err;\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(historyMessages ?? this.messages);\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(): 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 custom: {},\n },\n };\n this.messages = [...this.messages, assistant];\n this.notifyUpdate();\n return id;\n }\n\n private reassignAssistantId(oldId: string, newId: string): void {\n if (oldId === newId) return;\n\n const collidesWithExisting = this.messages.some((m) => m.id === newId);\n\n if (collidesWithExisting) {\n this.logger.debug?.(\n \"[agui] reassignAssistantId: server id already present in messages, dropping placeholder\",\n { oldId, newId },\n );\n this.messages = this.messages.filter((m) => m.id !== oldId);\n } else {\n this.messages = this.messages.map((m) =>\n m.id === oldId ? { ...m, id: newId } : m,\n );\n }\n\n const pendingParent = this.assistantHistoryParents.get(oldId);\n if (pendingParent !== undefined) {\n this.assistantHistoryParents.delete(oldId);\n if (!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 this.recordedHistoryIds.add(newId);\n }\n\n this.notifyUpdate();\n }\n\n private updateAssistantMessage(\n messageId: string,\n update: ChatModelRunResult,\n ): string {\n let touched = false;\n let latestStatus: MessageStatus | undefined;\n this.messages = this.messages.map((message) => {\n if (message.id !== messageId || message.role !== \"assistant\")\n return message;\n touched = true;\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 return {\n ...assistant,\n content: (update.content ??\n assistant.content) as ThreadAssistantMessage[\"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 return resolvedMessageId;\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 ...(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 this.logger.debug?.(\"[agui] state delta event ignored\", event.delta);\n return;\n }\n case \"MESSAGES_SNAPSHOT\": {\n this.importMessagesSnapshot(event.messages);\n return;\n }\n default:\n aggregator.handle(event);\n }\n }\n\n private importMessagesSnapshot(rawMessages: readonly unknown[]) {\n try {\n const normalized = fromAgUiMessages(rawMessages);\n const converted: ThreadMessage[] = [];\n for (const message of normalized) {\n try {\n converted.push(\n fromThreadMessageLike(\n message as any,\n generateId(),\n FALLBACK_USER_STATUS,\n ),\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 resetHead(parentId: string | null | undefined) {\n if (!parentId) {\n if (this.messages.length) {\n this.messages = [];\n }\n return;\n }\n const idx = this.messages.findIndex((message) => message.id === parentId);\n if (idx === -1) return;\n this.messages = this.messages.slice(0, idx + 1);\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.messages.find((m) => m.id === messageId);\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 { generateId, fromThreadMessageLike } from \"@assistant-ui/core/internal\";\nimport type {\n AddToolResultOptions,\n AppendMessage,\n AssistantRuntime,\n ChatModelRunResult,\n MessageStatus,\n ThreadAssistantMessage,\n ThreadHistoryAdapter,\n ThreadMessage,\n} from \"@assistant-ui/core\";\nimport type { HttpAgent } from \"@ag-ui/client\";\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} 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 symbolResumeShim = Symbol(\"agui-resume-shim\");\n\ntype RunConfig = NonNullable<AppendMessage[\"runConfig\"]>;\ntype ResumeRunConfig = {\n parentId: string | null;\n sourceId: string | null;\n runConfig: RunConfig;\n stream?: unknown;\n};\n\ntype CoreOptions = {\n agent: HttpAgent;\n logger: Logger;\n showThinking: boolean;\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: HttpAgent;\n private logger: Logger;\n private showThinking: boolean;\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 messages: ThreadMessage[] = [];\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\n constructor(options: CoreOptions) {\n this.agent = options.agent;\n this.logger = options.logger;\n this.showThinking = options.showThinking;\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.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.messages;\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 const messages = repo.messages.map((item) => item.message);\n this.applyExternalMessages(messages);\n\n if (repo.unstable_resume) {\n const parentId = repo.headId ?? messages.at(-1)?.id ?? null;\n await this.startRun(parentId, this.lastRunConfig);\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) this.assertNoPendingInterrupts();\n if (message.sourceId) {\n this.messages = this.messages.filter(\n (entry) => entry.id !== message.sourceId,\n );\n }\n this.resetHead(message.parentId);\n\n const threadMessage = this.toThreadMessage(message);\n this.messages = [...this.messages, threadMessage];\n this.notifyUpdate();\n this.recordHistoryEntry(message.parentId ?? null, threadMessage);\n\n if (!startRun) return;\n await this.startRun(threadMessage.id, message.runConfig);\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.resetHead(parentId);\n this.notifyUpdate();\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 if (config.stream) {\n this.logger.debug?.(\n \"[agui] resume stream is not supported, falling back to regular run\",\n );\n }\n await this.startRun(\n config.parentId,\n config.runConfig ?? this.lastRunConfig,\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 getPendingInterrupts(): {\n messageId: string;\n interrupts: readonly AgUiInterrupt[];\n } | null {\n const assistant = this.messages.findLast((m) => m.role === \"assistant\") as\n | ThreadAssistantMessage\n | undefined;\n if (\n !assistant ||\n assistant.status?.type !== \"requires-action\" ||\n assistant.status.reason !== \"interrupt\"\n ) {\n return null;\n }\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 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(\n (id) => 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 private clearPendingInterrupts(messageId: string): void {\n let touched = false;\n this.messages = this.messages.map((message) => {\n if (message.id !== messageId || message.role !== \"assistant\")\n 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 touched = true;\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) this.notifyUpdate();\n }\n\n findMessageIdForToolCall(toolCallId: string): string | undefined {\n let fallbackMessageId: string | undefined;\n for (let index = this.messages.length - 1; index >= 0; index--) {\n const message = this.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 (!(\"result\" in part) || part.result === undefined) {\n return message.id;\n }\n fallbackMessageId ??= message.id;\n }\n }\n return fallbackMessageId;\n }\n\n addToolResult(options: AddToolResultOptions): void {\n let updated = false;\n let shouldResume = false;\n this.messages = this.messages.map((message) => {\n if (message.id !== options.messageId || message.role !== \"assistant\")\n 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 updated = true;\n\n if (\n assistant.status?.type === \"requires-action\" &&\n assistant.status.reason === \"tool-calls\" &&\n content.every(\n (part) =>\n part.type !== \"tool-call\" ||\n (\"result\" in part && part.result !== undefined),\n )\n ) {\n shouldResume = true;\n return {\n ...assistant,\n content,\n status: { type: \"complete\" as const, reason: \"unknown\" as const },\n };\n }\n\n return {\n ...assistant,\n content,\n };\n });\n\n if (updated) {\n this.notifyUpdate();\n\n if (shouldResume) {\n this.persistAssistantHistory(options.messageId);\n\n if (!this.isRunningFlag) {\n void this.startRun(options.messageId, this.lastRunConfig).catch(\n (error) => {\n this.onError?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n },\n );\n }\n }\n }\n }\n\n applyExternalMessages(messages: readonly ThreadMessage[]): void {\n this.assistantHistoryParents.clear();\n this.messages = [...messages];\n this.recordedHistoryIds.clear();\n for (const message of this.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 private async startRun(\n parentId: string | null,\n runConfig?: RunConfig,\n resume?: AgUiResumeEntry[],\n ): Promise<void> {\n const normalizedRunConfig = runConfig ?? {};\n this.lastRunConfig = normalizedRunConfig;\n this.resetHead(parentId);\n const historicalMessages = [...this.messages];\n\n const runId = generateId();\n this.pendingError = null;\n const input = this.buildRunInput(\n runId,\n normalizedRunConfig,\n historicalMessages,\n resume,\n );\n const assistantParentId = parentId ?? this.messages.at(-1)?.id ?? null;\n let assistantMessageId: string | undefined;\n const ensureAssistant = () => {\n if (assistantMessageId) return assistantMessageId;\n const created = this.insertAssistantPlaceholder();\n assistantMessageId = created;\n this.markPendingAssistantHistory(created, assistantParentId ?? null);\n return created;\n };\n\n const aggregator = new RunAggregator({\n showThinking: this.showThinking,\n logger: this.logger,\n emit: (update) => {\n const resolved = this.updateAssistantMessage(ensureAssistant(), update);\n if (resolved !== assistantMessageId) {\n assistantMessageId = resolved;\n }\n },\n onServerMessageId: (serverId) => {\n const placeholder = ensureAssistant();\n if (placeholder === serverId) return;\n this.reassignAssistantId(placeholder, serverId);\n assistantMessageId = serverId;\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 abortSignal.addEventListener(\n \"abort\",\n () => {\n dispatch({ type: \"RUN_CANCELLED\" });\n this.finishRun(abortController);\n this.onCancel?.();\n },\n { once: true },\n );\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\n aggregator.handle({ type: \"RUN_STARTED\", runId });\n this.setRunning(true);\n\n try {\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 } 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 throw err;\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(historyMessages ?? this.messages);\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(): 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 custom: {},\n },\n };\n this.messages = [...this.messages, assistant];\n this.notifyUpdate();\n return id;\n }\n\n private reassignAssistantId(oldId: string, newId: string): void {\n if (oldId === newId) return;\n\n const collidesWithExisting = this.messages.some((m) => m.id === newId);\n\n if (collidesWithExisting) {\n this.logger.debug?.(\n \"[agui] reassignAssistantId: server id already present in messages, dropping placeholder\",\n { oldId, newId },\n );\n this.messages = this.messages.filter((m) => m.id !== oldId);\n } else {\n this.messages = this.messages.map((m) =>\n m.id === oldId ? { ...m, id: newId } : m,\n );\n }\n\n const pendingParent = this.assistantHistoryParents.get(oldId);\n if (pendingParent !== undefined) {\n this.assistantHistoryParents.delete(oldId);\n if (!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 this.recordedHistoryIds.add(newId);\n }\n\n this.notifyUpdate();\n }\n\n private updateAssistantMessage(\n messageId: string,\n update: ChatModelRunResult,\n ): string {\n let touched = false;\n let latestStatus: MessageStatus | undefined;\n this.messages = this.messages.map((message) => {\n if (message.id !== messageId || message.role !== \"assistant\")\n return message;\n touched = true;\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 return {\n ...assistant,\n content: (update.content ??\n assistant.content) as ThreadAssistantMessage[\"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 return resolvedMessageId;\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 ...(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 this.logger.debug?.(\"[agui] state delta event ignored\", event.delta);\n return;\n }\n case \"MESSAGES_SNAPSHOT\": {\n this.importMessagesSnapshot(event.messages);\n return;\n }\n default:\n aggregator.handle(event);\n }\n }\n\n private importMessagesSnapshot(rawMessages: readonly unknown[]) {\n try {\n const normalized = fromAgUiMessages(rawMessages);\n const converted: ThreadMessage[] = [];\n for (const message of normalized) {\n try {\n converted.push(\n fromThreadMessageLike(\n message as any,\n generateId(),\n FALLBACK_USER_STATUS,\n ),\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 resetHead(parentId: string | null | undefined) {\n if (!parentId) {\n if (this.messages.length) {\n this.messages = [];\n }\n return;\n }\n const idx = this.messages.findIndex((message) => message.id === parentId);\n if (idx === -1) return;\n this.messages = this.messages.slice(0, idx + 1);\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.messages.find((m) => m.id === messageId);\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,5 +1,5 @@
1
1
  import { Logger } from "./logger.js";
2
- import { AttachmentAdapter, DictationAdapter, FeedbackAdapter, SpeechSynthesisAdapter, ThreadHistoryAdapter, ThreadMessage } from "@assistant-ui/core";
2
+ import { AttachmentAdapter, DictationAdapter, ExternalStoreSharedOptions, FeedbackAdapter, RealtimeVoiceAdapter, SpeechSynthesisAdapter, ThreadHistoryAdapter, ThreadMessage } from "@assistant-ui/core";
3
3
  import { HttpAgent } from "@ag-ui/client";
4
4
  import { ReadonlyJSONValue } from "assistant-stream/utils";
5
5
 
@@ -22,6 +22,7 @@ type UseAgUiRuntimeAdapters = {
22
22
  attachments?: AttachmentAdapter;
23
23
  speech?: SpeechSynthesisAdapter;
24
24
  dictation?: DictationAdapter;
25
+ voice?: RealtimeVoiceAdapter;
25
26
  feedback?: FeedbackAdapter;
26
27
  history?: ThreadHistoryAdapter;
27
28
  /**
@@ -29,7 +30,7 @@ type UseAgUiRuntimeAdapters = {
29
30
  */
30
31
  threadList?: UseAgUiThreadListAdapter;
31
32
  };
32
- type UseAgUiRuntimeOptions = {
33
+ type UseAgUiRuntimeOptions = ExternalStoreSharedOptions & {
33
34
  agent: HttpAgent;
34
35
  logger?: Partial<Logger>;
35
36
  showThinking?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/runtime/types.ts"],"mappings":";;;;;;;;AAeA;KAAY,wBAAA;EACV,QAAA;EACA,mBAAA,UAA6B,OAAA;EAC7B,gBAAA,KACM,QAAA,aACE,OAAA;IACE,QAAA,WAAmB,aAAA;IACnB,KAAA,GAAQ,iBAAA;EAAA;IAER,QAAA,WAAmB,aAAA;IAAiB,KAAA,GAAQ,iBAAA;EAAA;AAAA;AAAA,KAI5C,sBAAA;EACV,WAAA,GAAc,iBAAA;EACd,MAAA,GAAS,sBAAA;EACT,SAAA,GAAY,gBAAA;EACZ,QAAA,GAAW,eAAA;EACX,OAAA,GAAU,oBAAA;EAZmB;;;EAgB7B,UAAA,GAAa,wBAAA;AAAA;AAAA,KAGH,qBAAA;EACV,KAAA,EAAO,SAAA;EACP,MAAA,GAAS,OAAA,CAAQ,MAAA;EACjB,YAAA;EACA,OAAA,IAAW,CAAA,EAAG,KAAA;EACd,QAAA;EACA,QAAA,GAAW,sBAAA;AAAA;AAAA,KAGD,mBAAA;AAAA,KAMA,aAAA;EACV,EAAA;EACA,MAAA,EAAQ,mBAAA;EACR,OAAA;EACA,UAAA;EACA,cAAA,GAAiB,MAAA;EACjB,SAAA;EACA,QAAA,GAAW,MAAA;AAAA;AAAA,KAGD,eAAA;EACV,WAAA;EACA,MAAA;EACA,OAAA;AAAA;AAAA,KAGU,sBAAA;EACN,IAAA;AAAA;EACA,IAAA;EAAmB,UAAA,EAAY,aAAa;AAAA;AAAA,KAEtC,SAAA;EACN,IAAA;EAAqB,KAAA;AAAA;EAErB,IAAA;EACA,KAAA;EACA,OAAA,GAAU,sBAAsB;AAAA;EAEhC,IAAA;EAAuB,KAAA;AAAA;EACvB,IAAA;EAAmB,OAAA;EAAkB,IAAA;AAAA;EACrC,IAAA;EAA4B,SAAA;AAAA;EAC5B,IAAA;EAA8B,SAAA;EAAoB,KAAA;AAAA;EAClD,IAAA;EAA0B,SAAA;AAAA;EAC1B,IAAA;EAA4B,KAAA;AAAA;EAC5B,IAAA;EAAwB,KAAA;AAAA;EACxB,IAAA;AAAA;EACA,IAAA;EAAuC,KAAA;AAAA;EACvC,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;EAAyB,SAAA;AAAA;EACzB,IAAA;EAAiC,SAAA;AAAA;EACjC,IAAA;EAAmC,SAAA;EAAoB,KAAA;AAAA;EACvD,IAAA;EAA+B,SAAA;AAAA;EAC/B,IAAA;EAAuB,SAAA;AAAA;EAEvB,IAAA;EACA,UAAA;EACA,YAAA;EACA,eAAA;AAAA;EAEA,IAAA;EAAwB,UAAA;EAAoB,KAAA;AAAA;EAC5C,IAAA;EAAuB,UAAA;AAAA;EAEvB,IAAA;EACA,UAAA;EACA,YAAA;EACA,eAAA;EACA,KAAA;AAAA;EAGA,IAAA;EACA,SAAA;EACA,UAAA;EACA,OAAA;EACA,IAAA;AAAA;EAEA,IAAA;EAAa,KAAA;EAAY,MAAA;AAAA;EACzB,IAAA;EAAgB,IAAA;EAAc,KAAA;AAAA;EAC9B,IAAA;EAAwB,QAAA;AAAA;EACxB,IAAA;EAAqB,KAAA;AAAA;EACrB,IAAA;EAA2B,QAAA;AAAA"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/runtime/types.ts"],"mappings":";;;;;;;;AAiBA;KAAY,wBAAA;EACV,QAAA;EACA,mBAAA,UAA6B,OAAA;EAC7B,gBAAA,KACM,QAAA,aACE,OAAA;IACE,QAAA,WAAmB,aAAA;IACnB,KAAA,GAAQ,iBAAA;EAAA;IAER,QAAA,WAAmB,aAAA;IAAiB,KAAA,GAAQ,iBAAA;EAAA;AAAA;AAAA,KAI5C,sBAAA;EACV,WAAA,GAAc,iBAAA;EACd,MAAA,GAAS,sBAAA;EACT,SAAA,GAAY,gBAAA;EACZ,KAAA,GAAQ,oBAAA;EACR,QAAA,GAAW,eAAA;EACX,OAAA,GAAU,oBAAA;EAZA;;;EAgBV,UAAA,GAAa,wBAAA;AAAA;AAAA,KAGH,qBAAA,GAAwB,0BAAA;EAClC,KAAA,EAAO,SAAA;EACP,MAAA,GAAS,OAAA,CAAQ,MAAA;EACjB,YAAA;EACA,OAAA,IAAW,CAAA,EAAG,KAAA;EACd,QAAA;EACA,QAAA,GAAW,sBAAA;AAAA;AAAA,KAGD,mBAAA;AAAA,KAMA,aAAA;EACV,EAAA;EACA,MAAA,EAAQ,mBAAA;EACR,OAAA;EACA,UAAA;EACA,cAAA,GAAiB,MAAA;EACjB,SAAA;EACA,QAAA,GAAW,MAAA;AAAA;AAAA,KAGD,eAAA;EACV,WAAA;EACA,MAAA;EACA,OAAA;AAAA;AAAA,KAGU,sBAAA;EACN,IAAA;AAAA;EACA,IAAA;EAAmB,UAAA,EAAY,aAAa;AAAA;AAAA,KAEtC,SAAA;EACN,IAAA;EAAqB,KAAA;AAAA;EAErB,IAAA;EACA,KAAA;EACA,OAAA,GAAU,sBAAsB;AAAA;EAEhC,IAAA;EAAuB,KAAA;AAAA;EACvB,IAAA;EAAmB,OAAA;EAAkB,IAAA;AAAA;EACrC,IAAA;EAA4B,SAAA;AAAA;EAC5B,IAAA;EAA8B,SAAA;EAAoB,KAAA;AAAA;EAClD,IAAA;EAA0B,SAAA;AAAA;EAC1B,IAAA;EAA4B,KAAA;AAAA;EAC5B,IAAA;EAAwB,KAAA;AAAA;EACxB,IAAA;AAAA;EACA,IAAA;EAAuC,KAAA;AAAA;EACvC,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;EAAyB,SAAA;AAAA;EACzB,IAAA;EAAiC,SAAA;AAAA;EACjC,IAAA;EAAmC,SAAA;EAAoB,KAAA;AAAA;EACvD,IAAA;EAA+B,SAAA;AAAA;EAC/B,IAAA;EAAuB,SAAA;AAAA;EAEvB,IAAA;EACA,UAAA;EACA,YAAA;EACA,eAAA;AAAA;EAEA,IAAA;EAAwB,UAAA;EAAoB,KAAA;AAAA;EAC5C,IAAA;EAAuB,UAAA;AAAA;EAEvB,IAAA;EACA,UAAA;EACA,YAAA;EACA,eAAA;EACA,KAAA;AAAA;EAGA,IAAA;EACA,SAAA;EACA,UAAA;EACA,OAAA;EACA,IAAA;AAAA;EAEA,IAAA;EAAa,KAAA;EAAY,MAAA;AAAA;EACzB,IAAA;EAAgB,IAAA;EAAc,KAAA;AAAA;EAC9B,IAAA;EAAwB,QAAA;AAAA;EACxB,IAAA;EAAqB,KAAA;AAAA;EACrB,IAAA;EAA2B,QAAA;AAAA"}
@@ -2,7 +2,7 @@
2
2
  import { makeLogger } from "./runtime/logger.js";
3
3
  import { AgUiThreadRuntimeCore } from "./runtime/AgUiThreadRuntimeCore.js";
4
4
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
5
- import { useExternalStoreRuntime, useRuntimeAdapters, useToolInvocations } from "@assistant-ui/core/react";
5
+ import { useExternalStoreRuntime, useExternalStoreSharedOptions, useRuntimeAdapters } from "@assistant-ui/core/react";
6
6
  //#region src/useAgUiRuntime.ts
7
7
  function useAgUiRuntime(options) {
8
8
  const logger = useMemo(() => makeLogger(options.logger), [options.logger]);
@@ -32,26 +32,16 @@ function useAgUiRuntime(options) {
32
32
  });
33
33
  const [toolStatuses, setToolStatuses] = useState({});
34
34
  const hasExecutingTools = Object.values(toolStatuses).some((s) => s?.type === "executing");
35
- const [runtimeRef] = useState(() => ({ get current() {
36
- return runtime;
37
- } }));
38
- const toolInvocationsRef = useRef({
39
- reset: () => {},
40
- abort: () => Promise.resolve(),
41
- resume: (_toolCallId, _payload) => {}
42
- });
43
35
  const threadList = useMemo(() => {
44
36
  if (!threadListAdapter) return void 0;
45
37
  const { onSwitchToNewThread, onSwitchToThread } = threadListAdapter;
46
38
  return {
47
39
  threadId: threadListAdapter.threadId,
48
40
  onSwitchToNewThread: onSwitchToNewThread ? async () => {
49
- toolInvocationsRef.current.reset();
50
41
  await onSwitchToNewThread();
51
42
  core.applyExternalMessages([]);
52
43
  } : void 0,
53
44
  onSwitchToThread: onSwitchToThread ? async (threadId) => {
54
- toolInvocationsRef.current.reset();
55
45
  const result = await onSwitchToThread(threadId);
56
46
  core.applyExternalMessages(result.messages);
57
47
  if (result.state) core.loadExternalState(result.state);
@@ -63,6 +53,7 @@ function useAgUiRuntime(options) {
63
53
  attachments: adapters?.attachments ?? runtimeAdapters?.attachments,
64
54
  speech: adapters?.speech,
65
55
  dictation: adapters?.dictation,
56
+ voice: adapters?.voice,
66
57
  feedback: adapters?.feedback,
67
58
  threadList
68
59
  }), [
@@ -70,43 +61,24 @@ function useAgUiRuntime(options) {
70
61
  runtimeAdapters,
71
62
  threadList
72
63
  ]);
73
- toolInvocationsRef.current = useToolInvocations({
74
- state: {
75
- messages: core.getMessages(),
76
- isRunning: core.isRunning() || hasExecutingTools
77
- },
78
- getTools: () => runtimeRef.current.thread.getModelContext().tools,
79
- onResult: (command) => {
80
- if (command.type === "add-tool-result") {
81
- const messageId = core.findMessageIdForToolCall(command.toolCallId);
82
- if (messageId) core.addToolResult({
83
- messageId,
84
- toolCallId: command.toolCallId,
85
- toolName: command.toolName,
86
- result: command.result,
87
- isError: command.isError,
88
- ...command.artifact && { artifact: command.artifact }
89
- });
90
- }
91
- },
92
- setToolStatuses
93
- });
64
+ const shared = useExternalStoreSharedOptions(options);
94
65
  const baseRuntime = useExternalStoreRuntime(useMemo(() => {
95
66
  return {
67
+ ...shared,
96
68
  isLoading: core.isLoading,
97
69
  messages: core.getMessages(),
98
70
  state: core.getState(),
99
71
  isRunning: core.isRunning() || hasExecutingTools,
72
+ unstable_enableToolInvocations: true,
73
+ setToolStatuses,
100
74
  onNew: (message) => core.append(message),
101
75
  onEdit: (message) => core.edit(message),
102
76
  onReload: (parentId, config) => core.reload(parentId, config),
103
77
  onCancel: async () => {
104
78
  core.cancel();
105
- await toolInvocationsRef.current.abort();
106
79
  },
107
80
  onAddToolResult: (options) => core.addToolResult(options),
108
81
  onResume: (config) => core.resume(config),
109
- onResumeToolCall: (options) => toolInvocationsRef.current.resume(options.toolCallId, options.payload),
110
82
  setMessages: (messages) => core.applyExternalMessages(messages),
111
83
  onImport: (messages) => core.applyExternalMessages(messages),
112
84
  onLoadExternalState: (state) => core.loadExternalState(state),
@@ -116,7 +88,8 @@ function useAgUiRuntime(options) {
116
88
  adapterAdapters,
117
89
  core,
118
90
  _version,
119
- hasExecutingTools
91
+ hasExecutingTools,
92
+ shared
120
93
  ]));
121
94
  const runtime = useMemo(() => {
122
95
  const wrapper = Object.create(baseRuntime);
@@ -1 +1 @@
1
- {"version":3,"file":"useAgUiRuntime.js","names":[],"sources":["../src/useAgUiRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n useExternalStoreRuntime,\n useRuntimeAdapters,\n useToolInvocations,\n} from \"@assistant-ui/core/react\";\nimport type { ToolExecutionStatus } from \"@assistant-ui/core/react\";\nimport type {\n AssistantRuntime,\n AppendMessage,\n ExternalStoreAdapter,\n ThreadMessage,\n} from \"@assistant-ui/core\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport { makeLogger } from \"./runtime/logger\";\nimport type {\n AgUiInterrupt,\n AgUiResumeEntry,\n UseAgUiRuntimeOptions,\n} from \"./runtime/types\";\nimport { AgUiThreadRuntimeCore } from \"./runtime/AgUiThreadRuntimeCore\";\n\nexport type AgUiAssistantRuntime = AssistantRuntime & {\n unstable_getPendingInterrupts: () => readonly AgUiInterrupt[];\n unstable_submitInterruptResponses: (\n responses: readonly AgUiResumeEntry[],\n ) => Promise<void>;\n};\n\nexport function useAgUiRuntime(\n options: UseAgUiRuntimeOptions,\n): AgUiAssistantRuntime {\n const logger = useMemo(() => makeLogger(options.logger), [options.logger]);\n const [_version, setVersion] = useState(0);\n const notifyUpdate = useCallback(() => setVersion((v) => v + 1), []);\n const coreRef = useRef<AgUiThreadRuntimeCore | null>(null);\n const runtimeAdapters = useRuntimeAdapters();\n\n const historyAdapter = options.adapters?.history ?? runtimeAdapters?.history;\n const threadListAdapter = options.adapters?.threadList;\n\n if (!coreRef.current) {\n coreRef.current = new AgUiThreadRuntimeCore({\n agent: options.agent,\n logger,\n showThinking: options.showThinking ?? true,\n ...(options.onError && { onError: options.onError }),\n ...(options.onCancel && { onCancel: options.onCancel }),\n ...(historyAdapter && { history: historyAdapter }),\n notifyUpdate,\n });\n }\n\n const core = coreRef.current;\n core.updateOptions({\n agent: options.agent,\n logger,\n showThinking: options.showThinking ?? true,\n ...(options.onError && { onError: options.onError }),\n ...(options.onCancel && { onCancel: options.onCancel }),\n ...(historyAdapter && { history: historyAdapter }),\n });\n\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n\n const hasExecutingTools = Object.values(toolStatuses).some(\n (s) => s?.type === \"executing\",\n );\n\n const [runtimeRef] = useState(() => ({\n get current(): AssistantRuntime {\n return runtime;\n },\n }));\n\n const toolInvocationsRef = useRef({\n reset: () => {},\n abort: (): Promise<void> => Promise.resolve(),\n resume: (_toolCallId: string, _payload: unknown) => {},\n });\n\n const threadList = useMemo(() => {\n if (!threadListAdapter) return undefined;\n\n const { onSwitchToNewThread, onSwitchToThread } = threadListAdapter;\n\n return {\n threadId: threadListAdapter.threadId,\n onSwitchToNewThread: onSwitchToNewThread\n ? async () => {\n toolInvocationsRef.current.reset();\n await onSwitchToNewThread();\n core.applyExternalMessages([]);\n }\n : undefined,\n onSwitchToThread: onSwitchToThread\n ? async (threadId: string) => {\n toolInvocationsRef.current.reset();\n const result = await onSwitchToThread(threadId);\n core.applyExternalMessages(result.messages);\n if (result.state) {\n core.loadExternalState(result.state);\n }\n }\n : undefined,\n };\n }, [threadListAdapter, core]);\n\n const adapters = options.adapters;\n const adapterAdapters = useMemo(\n () => ({\n attachments: adapters?.attachments ?? runtimeAdapters?.attachments,\n speech: adapters?.speech,\n dictation: adapters?.dictation,\n feedback: adapters?.feedback,\n threadList,\n }),\n [adapters, runtimeAdapters, threadList],\n );\n\n const toolInvocations = useToolInvocations({\n state: {\n messages: core.getMessages(),\n isRunning: core.isRunning() || hasExecutingTools,\n },\n getTools: () => runtimeRef.current.thread.getModelContext().tools,\n onResult: (command) => {\n if (command.type === \"add-tool-result\") {\n const messageId = core.findMessageIdForToolCall(command.toolCallId);\n if (messageId) {\n core.addToolResult({\n messageId,\n toolCallId: command.toolCallId,\n toolName: command.toolName,\n result: command.result,\n isError: command.isError,\n ...(command.artifact && { artifact: command.artifact }),\n });\n }\n }\n },\n setToolStatuses,\n });\n toolInvocationsRef.current = toolInvocations;\n\n const store = useMemo(\n () => {\n void _version; // rerender on version change\n\n return {\n isLoading: core.isLoading,\n messages: core.getMessages(),\n state: core.getState(),\n isRunning: core.isRunning() || hasExecutingTools,\n onNew: (message: AppendMessage) => core.append(message),\n onEdit: (message: AppendMessage) => core.edit(message),\n onReload: (parentId: string | null, config: { runConfig?: any }) =>\n core.reload(parentId, config),\n onCancel: async () => {\n core.cancel();\n await toolInvocationsRef.current.abort();\n },\n onAddToolResult: (options) => core.addToolResult(options),\n onResume: (config) => core.resume(config),\n onResumeToolCall: (options) =>\n toolInvocationsRef.current.resume(\n options.toolCallId,\n options.payload,\n ),\n setMessages: (messages: readonly ThreadMessage[]) =>\n core.applyExternalMessages(messages),\n onImport: (messages: readonly ThreadMessage[]) =>\n core.applyExternalMessages(messages),\n onLoadExternalState: (state: ReadonlyJSONValue) =>\n core.loadExternalState(state),\n adapters: adapterAdapters,\n } satisfies ExternalStoreAdapter<ThreadMessage>;\n },\n // _version is intentionally included to trigger re-computation when core state changes via notifyUpdate\n // toolInvocations intentionally excluded: abort/resume use refs internally and work with stale captures\n [adapterAdapters, core, _version, hasExecutingTools],\n );\n\n const baseRuntime = useExternalStoreRuntime(store);\n\n const runtime = useMemo<AgUiAssistantRuntime>(() => {\n const wrapper = Object.create(baseRuntime) as AgUiAssistantRuntime;\n wrapper.unstable_getPendingInterrupts = () =>\n core.getPendingInterrupts()?.interrupts ?? [];\n wrapper.unstable_submitInterruptResponses = (responses) =>\n core.submitInterruptResponses(responses);\n return wrapper;\n }, [baseRuntime, core]);\n\n useEffect(() => {\n core.attachRuntime(runtime);\n return () => {\n core.detachRuntime();\n };\n }, [core, runtime]);\n\n useEffect(() => {\n core.__internal_load();\n }, [core]);\n\n return runtime;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useAgUiRuntime.js","names":[],"sources":["../src/useAgUiRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n useExternalStoreRuntime,\n useExternalStoreSharedOptions,\n useRuntimeAdapters,\n} from \"@assistant-ui/core/react\";\nimport type { ToolExecutionStatus } from \"@assistant-ui/core\";\nimport type {\n AssistantRuntime,\n AppendMessage,\n ExternalStoreAdapter,\n ThreadMessage,\n} from \"@assistant-ui/core\";\nimport type { ReadonlyJSONValue } from \"assistant-stream/utils\";\nimport { makeLogger } from \"./runtime/logger\";\nimport type {\n AgUiInterrupt,\n AgUiResumeEntry,\n UseAgUiRuntimeOptions,\n} from \"./runtime/types\";\nimport { AgUiThreadRuntimeCore } from \"./runtime/AgUiThreadRuntimeCore\";\n\nexport type AgUiAssistantRuntime = AssistantRuntime & {\n unstable_getPendingInterrupts: () => readonly AgUiInterrupt[];\n unstable_submitInterruptResponses: (\n responses: readonly AgUiResumeEntry[],\n ) => Promise<void>;\n};\n\nexport function useAgUiRuntime(\n options: UseAgUiRuntimeOptions,\n): AgUiAssistantRuntime {\n const logger = useMemo(() => makeLogger(options.logger), [options.logger]);\n const [_version, setVersion] = useState(0);\n const notifyUpdate = useCallback(() => setVersion((v) => v + 1), []);\n const coreRef = useRef<AgUiThreadRuntimeCore | null>(null);\n const runtimeAdapters = useRuntimeAdapters();\n\n const historyAdapter = options.adapters?.history ?? runtimeAdapters?.history;\n const threadListAdapter = options.adapters?.threadList;\n\n if (!coreRef.current) {\n coreRef.current = new AgUiThreadRuntimeCore({\n agent: options.agent,\n logger,\n showThinking: options.showThinking ?? true,\n ...(options.onError && { onError: options.onError }),\n ...(options.onCancel && { onCancel: options.onCancel }),\n ...(historyAdapter && { history: historyAdapter }),\n notifyUpdate,\n });\n }\n\n const core = coreRef.current;\n core.updateOptions({\n agent: options.agent,\n logger,\n showThinking: options.showThinking ?? true,\n ...(options.onError && { onError: options.onError }),\n ...(options.onCancel && { onCancel: options.onCancel }),\n ...(historyAdapter && { history: historyAdapter }),\n });\n\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n\n const hasExecutingTools = Object.values(toolStatuses).some(\n (s) => s?.type === \"executing\",\n );\n\n const threadList = useMemo(() => {\n if (!threadListAdapter) return undefined;\n\n const { onSwitchToNewThread, onSwitchToThread } = threadListAdapter;\n\n return {\n threadId: threadListAdapter.threadId,\n onSwitchToNewThread: onSwitchToNewThread\n ? async () => {\n await onSwitchToNewThread();\n core.applyExternalMessages([]);\n }\n : undefined,\n onSwitchToThread: onSwitchToThread\n ? async (threadId: string) => {\n const result = await onSwitchToThread(threadId);\n core.applyExternalMessages(result.messages);\n if (result.state) {\n core.loadExternalState(result.state);\n }\n }\n : undefined,\n };\n }, [threadListAdapter, core]);\n\n const adapters = options.adapters;\n const adapterAdapters = useMemo(\n () => ({\n attachments: adapters?.attachments ?? runtimeAdapters?.attachments,\n speech: adapters?.speech,\n dictation: adapters?.dictation,\n voice: adapters?.voice,\n feedback: adapters?.feedback,\n threadList,\n }),\n [adapters, runtimeAdapters, threadList],\n );\n\n const shared = useExternalStoreSharedOptions(options);\n const store = useMemo(\n () => {\n void _version; // rerender on version change\n\n return {\n ...shared,\n isLoading: core.isLoading,\n messages: core.getMessages(),\n state: core.getState(),\n isRunning: core.isRunning() || hasExecutingTools,\n unstable_enableToolInvocations: true,\n setToolStatuses,\n onNew: (message: AppendMessage) => core.append(message),\n onEdit: (message: AppendMessage) => core.edit(message),\n onReload: (parentId: string | null, config: { runConfig?: any }) =>\n core.reload(parentId, config),\n onCancel: async () => {\n core.cancel();\n },\n onAddToolResult: (options) => core.addToolResult(options),\n onResume: (config) => core.resume(config),\n setMessages: (messages: readonly ThreadMessage[]) =>\n core.applyExternalMessages(messages),\n onImport: (messages: readonly ThreadMessage[]) =>\n core.applyExternalMessages(messages),\n onLoadExternalState: (state: ReadonlyJSONValue) =>\n core.loadExternalState(state),\n adapters: adapterAdapters,\n } satisfies ExternalStoreAdapter<ThreadMessage>;\n },\n // _version is intentionally included to trigger re-computation when core state changes via notifyUpdate\n // toolInvocations intentionally excluded: abort/resume use refs internally and work with stale captures\n [adapterAdapters, core, _version, hasExecutingTools, shared],\n );\n\n const baseRuntime = useExternalStoreRuntime(store);\n\n const runtime = useMemo<AgUiAssistantRuntime>(() => {\n const wrapper = Object.create(baseRuntime) as AgUiAssistantRuntime;\n wrapper.unstable_getPendingInterrupts = () =>\n core.getPendingInterrupts()?.interrupts ?? [];\n wrapper.unstable_submitInterruptResponses = (responses) =>\n core.submitInterruptResponses(responses);\n return wrapper;\n }, [baseRuntime, core]);\n\n useEffect(() => {\n core.attachRuntime(runtime);\n return () => {\n core.detachRuntime();\n };\n }, [core, runtime]);\n\n useEffect(() => {\n core.__internal_load();\n }, [core]);\n\n return runtime;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react-ag-ui",
3
- "version": "0.0.32",
3
+ "version": "0.0.34",
4
4
  "description": "AG-UI protocol adapter for assistant-ui",
5
5
  "keywords": [
6
6
  "ag-ui",
@@ -29,9 +29,9 @@
29
29
  ],
30
30
  "sideEffects": false,
31
31
  "dependencies": {
32
- "@ag-ui/client": "^0.0.53",
33
- "@assistant-ui/core": "^0.2.5",
34
- "assistant-stream": "^0.3.16"
32
+ "@ag-ui/client": "^0.0.54",
33
+ "@assistant-ui/core": "^0.2.8",
34
+ "assistant-stream": "^0.3.18"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@types/react": "*",
@@ -47,7 +47,7 @@
47
47
  "react": "^19.2.6",
48
48
  "vitest": "^4.1.7",
49
49
  "zod": "^4.4.3",
50
- "@assistant-ui/x-buildutils": "0.0.9"
50
+ "@assistant-ui/x-buildutils": "0.0.10"
51
51
  },
52
52
  "publishConfig": {
53
53
  "access": "public",
@@ -1,11 +1,6 @@
1
1
  "use client";
2
2
 
3
- import {
4
- generateId,
5
- generateOptimisticId,
6
- isOptimisticId,
7
- fromThreadMessageLike,
8
- } from "@assistant-ui/core/internal";
3
+ import { generateId, fromThreadMessageLike } from "@assistant-ui/core/internal";
9
4
  import type {
10
5
  AddToolResultOptions,
11
6
  AppendMessage,
@@ -32,6 +27,10 @@ import {
32
27
  } from "./adapter/conversions";
33
28
  import { createAgUiSubscriber } from "./adapter/subscriber";
34
29
 
30
+ const optimisticPrefix = "__optimistic__";
31
+ const generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
32
+ const isOptimisticId = (id: string) => id.startsWith(optimisticPrefix);
33
+
35
34
  const symbolResumeShim = Symbol("agui-resume-shim");
36
35
 
37
36
  type RunConfig = NonNullable<AppendMessage["runConfig"]>;
@@ -1,7 +1,9 @@
1
1
  import type {
2
2
  AttachmentAdapter,
3
3
  DictationAdapter,
4
+ ExternalStoreSharedOptions,
4
5
  FeedbackAdapter,
6
+ RealtimeVoiceAdapter,
5
7
  SpeechSynthesisAdapter,
6
8
  ThreadHistoryAdapter,
7
9
  ThreadMessage,
@@ -30,6 +32,7 @@ export type UseAgUiRuntimeAdapters = {
30
32
  attachments?: AttachmentAdapter;
31
33
  speech?: SpeechSynthesisAdapter;
32
34
  dictation?: DictationAdapter;
35
+ voice?: RealtimeVoiceAdapter;
33
36
  feedback?: FeedbackAdapter;
34
37
  history?: ThreadHistoryAdapter;
35
38
  /**
@@ -38,7 +41,7 @@ export type UseAgUiRuntimeAdapters = {
38
41
  threadList?: UseAgUiThreadListAdapter;
39
42
  };
40
43
 
41
- export type UseAgUiRuntimeOptions = {
44
+ export type UseAgUiRuntimeOptions = ExternalStoreSharedOptions & {
42
45
  agent: HttpAgent;
43
46
  logger?: Partial<Logger>;
44
47
  showThinking?: boolean;
@@ -3,10 +3,10 @@
3
3
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
4
  import {
5
5
  useExternalStoreRuntime,
6
+ useExternalStoreSharedOptions,
6
7
  useRuntimeAdapters,
7
- useToolInvocations,
8
8
  } from "@assistant-ui/core/react";
9
- import type { ToolExecutionStatus } from "@assistant-ui/core/react";
9
+ import type { ToolExecutionStatus } from "@assistant-ui/core";
10
10
  import type {
11
11
  AssistantRuntime,
12
12
  AppendMessage,
@@ -71,18 +71,6 @@ export function useAgUiRuntime(
71
71
  (s) => s?.type === "executing",
72
72
  );
73
73
 
74
- const [runtimeRef] = useState(() => ({
75
- get current(): AssistantRuntime {
76
- return runtime;
77
- },
78
- }));
79
-
80
- const toolInvocationsRef = useRef({
81
- reset: () => {},
82
- abort: (): Promise<void> => Promise.resolve(),
83
- resume: (_toolCallId: string, _payload: unknown) => {},
84
- });
85
-
86
74
  const threadList = useMemo(() => {
87
75
  if (!threadListAdapter) return undefined;
88
76
 
@@ -92,14 +80,12 @@ export function useAgUiRuntime(
92
80
  threadId: threadListAdapter.threadId,
93
81
  onSwitchToNewThread: onSwitchToNewThread
94
82
  ? async () => {
95
- toolInvocationsRef.current.reset();
96
83
  await onSwitchToNewThread();
97
84
  core.applyExternalMessages([]);
98
85
  }
99
86
  : undefined,
100
87
  onSwitchToThread: onSwitchToThread
101
88
  ? async (threadId: string) => {
102
- toolInvocationsRef.current.reset();
103
89
  const result = await onSwitchToThread(threadId);
104
90
  core.applyExternalMessages(result.messages);
105
91
  if (result.state) {
@@ -116,61 +102,35 @@ export function useAgUiRuntime(
116
102
  attachments: adapters?.attachments ?? runtimeAdapters?.attachments,
117
103
  speech: adapters?.speech,
118
104
  dictation: adapters?.dictation,
105
+ voice: adapters?.voice,
119
106
  feedback: adapters?.feedback,
120
107
  threadList,
121
108
  }),
122
109
  [adapters, runtimeAdapters, threadList],
123
110
  );
124
111
 
125
- const toolInvocations = useToolInvocations({
126
- state: {
127
- messages: core.getMessages(),
128
- isRunning: core.isRunning() || hasExecutingTools,
129
- },
130
- getTools: () => runtimeRef.current.thread.getModelContext().tools,
131
- onResult: (command) => {
132
- if (command.type === "add-tool-result") {
133
- const messageId = core.findMessageIdForToolCall(command.toolCallId);
134
- if (messageId) {
135
- core.addToolResult({
136
- messageId,
137
- toolCallId: command.toolCallId,
138
- toolName: command.toolName,
139
- result: command.result,
140
- isError: command.isError,
141
- ...(command.artifact && { artifact: command.artifact }),
142
- });
143
- }
144
- }
145
- },
146
- setToolStatuses,
147
- });
148
- toolInvocationsRef.current = toolInvocations;
149
-
112
+ const shared = useExternalStoreSharedOptions(options);
150
113
  const store = useMemo(
151
114
  () => {
152
115
  void _version; // rerender on version change
153
116
 
154
117
  return {
118
+ ...shared,
155
119
  isLoading: core.isLoading,
156
120
  messages: core.getMessages(),
157
121
  state: core.getState(),
158
122
  isRunning: core.isRunning() || hasExecutingTools,
123
+ unstable_enableToolInvocations: true,
124
+ setToolStatuses,
159
125
  onNew: (message: AppendMessage) => core.append(message),
160
126
  onEdit: (message: AppendMessage) => core.edit(message),
161
127
  onReload: (parentId: string | null, config: { runConfig?: any }) =>
162
128
  core.reload(parentId, config),
163
129
  onCancel: async () => {
164
130
  core.cancel();
165
- await toolInvocationsRef.current.abort();
166
131
  },
167
132
  onAddToolResult: (options) => core.addToolResult(options),
168
133
  onResume: (config) => core.resume(config),
169
- onResumeToolCall: (options) =>
170
- toolInvocationsRef.current.resume(
171
- options.toolCallId,
172
- options.payload,
173
- ),
174
134
  setMessages: (messages: readonly ThreadMessage[]) =>
175
135
  core.applyExternalMessages(messages),
176
136
  onImport: (messages: readonly ThreadMessage[]) =>
@@ -182,7 +142,7 @@ export function useAgUiRuntime(
182
142
  },
183
143
  // _version is intentionally included to trigger re-computation when core state changes via notifyUpdate
184
144
  // toolInvocations intentionally excluded: abort/resume use refs internally and work with stale captures
185
- [adapterAdapters, core, _version, hasExecutingTools],
145
+ [adapterAdapters, core, _version, hasExecutingTools, shared],
186
146
  );
187
147
 
188
148
  const baseRuntime = useExternalStoreRuntime(store);