@assistant-ui/react-ag-ui 0.0.36 → 0.0.39

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":"conversions.js","names":[],"sources":["../../../src/runtime/adapter/conversions.ts"],"sourcesContent":["\"use client\";\n\nimport type { InputContent } from \"@ag-ui/client\";\nimport type { ThreadMessageLike as CoreThreadMessageLike } from \"@assistant-ui/core\";\nimport { type Tool, toToolsJSONSchema } from \"assistant-stream\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\n\nexport type { InputContent };\n\ntype AttachmentLike = {\n name?: string | undefined;\n contentType?: string | undefined;\n content?: readonly unknown[] | undefined;\n};\n\ntype ThreadMessageLike = {\n id: string;\n role: string;\n content: unknown;\n name?: string;\n toolCallId?: string;\n error?: string;\n attachments?: readonly AttachmentLike[];\n};\n\ntype AgUiToolCall = {\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n};\n\nexport type AgUiMessage =\n | {\n id: string;\n role: string;\n content: string | InputContent[];\n name?: string;\n toolCalls?: AgUiToolCall[];\n }\n | {\n id: string;\n role: \"tool\";\n content: string;\n toolCallId: string;\n error?: string;\n };\n\ntype ToolCallPart = {\n type: \"tool-call\";\n toolCallId?: string;\n toolName: string;\n argsText?: string;\n args?: ReadonlyJSONObject;\n result?: unknown;\n isError?: boolean;\n unstable_toolMessageId?: string;\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nconst getString = (record: Record<string, unknown>, key: string) => {\n const value = record[key];\n return typeof value === \"string\" ? value : undefined;\n};\n\nconst getToolCallId = (record: Record<string, unknown>) =>\n getString(record, \"toolCallId\") ?? getString(record, \"tool_call_id\");\n\nfunction parseJSONText(value: string): unknown {\n if (!value) return value;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n\nfunction generateId(): string {\n return (\n (globalThis.crypto as { randomUUID?: () => string })?.randomUUID?.() ??\n Math.random().toString(36).slice(2)\n );\n}\n\nfunction normalizeToolCall(part: ToolCallPart): {\n id: string;\n call: AgUiToolCall;\n} {\n const id = part.toolCallId ?? generateId();\n const argsText =\n typeof part.argsText === \"string\"\n ? part.argsText\n : JSON.stringify(part.args ?? {});\n\n return {\n id,\n call: {\n id,\n type: \"function\",\n function: {\n name: part.toolName ?? \"tool\",\n arguments: argsText,\n },\n },\n };\n}\n\nfunction extractText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n\n return content\n .filter(\n (part): part is { type: \"text\"; text: string } =>\n part?.type === \"text\" && typeof part?.text === \"string\",\n )\n .map((part) => part.text)\n .join(\"\\n\");\n}\n\nfunction parseDataUrl(\n value: string,\n): { mimeType: string; data: string } | null {\n const match = value.match(/^data:([^;,]+)(?:;[^;,]+)*;base64,(.+)$/);\n if (!match) return null;\n return { mimeType: match[1]!, data: match[2]! };\n}\n\nconst httpUrlPattern = /^https?:\\/\\//i;\n\ntype InputContentSource =\n | { type: \"data\"; value: string; mimeType: string }\n | { type: \"url\"; value: string; mimeType?: string };\n\ntype MediaInputType = \"image\" | \"audio\" | \"video\" | \"document\";\n\nfunction mediaTypeForMime(mimeType: string | undefined): MediaInputType {\n if (mimeType?.startsWith(\"image/\")) return \"image\";\n if (mimeType?.startsWith(\"audio/\")) return \"audio\";\n if (mimeType?.startsWith(\"video/\")) return \"video\";\n return \"document\";\n}\n\n// Build an AG-UI multimodal source from a data URL, raw base64 payload, or an\n// http(s) URL. A `url` source may omit the mime type; a `data` source always\n// resolves one (falling back to application/octet-stream).\nfunction buildInputSource(\n value: string,\n declaredMimeType: string | undefined,\n): InputContentSource {\n if (httpUrlPattern.test(value)) {\n return declaredMimeType !== undefined\n ? { type: \"url\", value, mimeType: declaredMimeType }\n : { type: \"url\", value };\n }\n const parsed = parseDataUrl(value);\n return {\n type: \"data\",\n value: parsed?.data ?? value,\n mimeType:\n parsed?.mimeType ?? declaredMimeType ?? \"application/octet-stream\",\n };\n}\n\nfunction toInputContent(\n part: unknown,\n fallbackMimeType: string | undefined,\n): InputContent | null {\n if (!isObject(part)) return null;\n const type = getString(part, \"type\");\n\n if (type === \"text\") {\n const text = getString(part, \"text\");\n if (text === undefined) return null;\n return { type: \"text\", text };\n }\n\n if (type === \"image\") {\n const image = getString(part, \"image\");\n if (image === undefined) return null;\n return { type: \"image\", source: buildInputSource(image, fallbackMimeType) };\n }\n\n if (type === \"file\") {\n const data = getString(part, \"data\");\n if (data === undefined) return null;\n const declaredMimeType = getString(part, \"mimeType\") || fallbackMimeType;\n const filename = getString(part, \"filename\");\n const source = buildInputSource(data, declaredMimeType);\n const metadata = filename !== undefined ? { filename } : undefined;\n switch (mediaTypeForMime(source.mimeType)) {\n case \"image\":\n return { type: \"image\", source, ...(metadata && { metadata }) };\n case \"audio\":\n return { type: \"audio\", source, ...(metadata && { metadata }) };\n case \"video\":\n return { type: \"video\", source, ...(metadata && { metadata }) };\n default:\n return { type: \"document\", source, ...(metadata && { metadata }) };\n }\n }\n\n return null;\n}\n\nfunction buildUserContent(message: ThreadMessageLike): string | InputContent[] {\n // File parts in message.content are intentionally skipped: the canonical\n // binary payload for files always flows through message.attachments.\n const contentParts = Array.isArray(message.content)\n ? message.content.filter(\n (part) => !(isObject(part) && part.type === \"file\"),\n )\n : [];\n\n const attachments = message.attachments ?? [];\n\n const converted: InputContent[] = [];\n\n // Promote string-form content to a leading text part so it survives when\n // non-text attachments are present (fromAgUiMessages emits string content).\n if (typeof message.content === \"string\" && message.content.length > 0) {\n converted.push({ type: \"text\", text: message.content });\n }\n\n for (const part of contentParts) {\n const input = toInputContent(part, undefined);\n if (input) converted.push(input);\n }\n for (const attachment of attachments) {\n if (!isObject(attachment)) continue;\n const attachmentContent = attachment.content;\n if (!Array.isArray(attachmentContent)) continue;\n const fallbackMime = getString(attachment, \"contentType\");\n for (const part of attachmentContent) {\n const input = toInputContent(part, fallbackMime);\n if (input) converted.push(input);\n }\n }\n\n const hasNonText = converted.some((part) => part.type !== \"text\");\n if (hasNonText) return converted;\n\n // All-text path: collapse to plain string. Join text parts collected from\n // both content and attachments so attachment-sourced text is not dropped.\n if (converted.length === 0) return extractText(message.content);\n return converted\n .filter(\n (part): part is { type: \"text\"; text: string } => part.type === \"text\",\n )\n .map((part) => part.text)\n .join(\"\\n\");\n}\n\nfunction toToolCallPart(value: unknown): ToolCallPart | null {\n if (!isObject(value)) return null;\n const rawFunction = isObject(value.function) ? value.function : null;\n const toolCallId = getString(value, \"toolCallId\") ?? getString(value, \"id\");\n const toolName =\n getString(value, \"toolName\") ??\n getString(value, \"name\") ??\n (rawFunction ? getString(rawFunction, \"name\") : undefined) ??\n \"tool\";\n const argsText =\n getString(value, \"argsText\") ??\n getString(value, \"arguments\") ??\n (rawFunction ? getString(rawFunction, \"arguments\") : undefined);\n\n const parsedArgs =\n typeof argsText === \"string\" ? parseJSONText(argsText) : undefined;\n const args =\n isObject(parsedArgs) && !Array.isArray(parsedArgs)\n ? (parsedArgs as ReadonlyJSONObject)\n : isObject(value.args) && !Array.isArray(value.args)\n ? (value.args as ReadonlyJSONObject)\n : undefined;\n\n const part: ToolCallPart = {\n type: \"tool-call\",\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n toolName,\n argsText: argsText ?? JSON.stringify(args ?? {}),\n ...(args !== undefined ? { args } : {}),\n };\n\n if (value.type === \"tool-call\") {\n const result = value.result;\n const isError = value.isError;\n if (result !== undefined) part.result = result;\n if (typeof isError === \"boolean\") part.isError = isError;\n }\n\n return part;\n}\n\nfunction extractAssistantToolCalls(\n message: Record<string, unknown>,\n): ToolCallPart[] {\n const parts: ToolCallPart[] = [];\n const seenToolCallIds = new Set<string>();\n const pushPart = (part: ToolCallPart | null) => {\n if (!part) return;\n const id = part.toolCallId ?? generateId();\n if (seenToolCallIds.has(id)) return;\n seenToolCallIds.add(id);\n parts.push({\n ...part,\n toolCallId: id,\n });\n };\n\n const content = message.content;\n if (Array.isArray(content)) {\n for (const part of content) {\n if (isObject(part) && part.type === \"tool-call\") {\n pushPart(toToolCallPart(part));\n }\n }\n }\n\n const toolCalls = Array.isArray(message.toolCalls)\n ? message.toolCalls\n : Array.isArray(message.tool_calls)\n ? message.tool_calls\n : [];\n for (const call of toolCalls) {\n pushPart(toToolCallPart(call));\n }\n\n return parts;\n}\n\nfunction toAssistantSnapshotMessage(\n rawMessage: Record<string, unknown>,\n): CoreThreadMessageLike {\n const text = extractText(rawMessage.content);\n const toolCallParts = extractAssistantToolCalls(rawMessage);\n const assistantContent = [\n ...(text.length > 0 ? [{ type: \"text\" as const, text }] : []),\n ...toolCallParts,\n ];\n const messageName = getString(rawMessage, \"name\");\n return {\n id: getString(rawMessage, \"id\") ?? generateId(),\n role: \"assistant\",\n content: assistantContent.length > 0 ? assistantContent : \"\",\n ...(messageName !== undefined ? { name: messageName } : {}),\n };\n}\n\nfunction toUserOrSystemSnapshotMessage(\n role: \"user\" | \"system\",\n rawMessage: Record<string, unknown>,\n): CoreThreadMessageLike {\n const messageName = getString(rawMessage, \"name\");\n return {\n id: getString(rawMessage, \"id\") ?? generateId(),\n role,\n content: extractText(rawMessage.content),\n ...(messageName !== undefined ? { name: messageName } : {}),\n };\n}\n\nexport type FromAgUiMessagesOptions = {\n /**\n * Whether to convert `reasoning` messages into visible reasoning parts.\n * Matches the `showThinking` option of `useAgUiRuntime`. Defaults to `true`.\n */\n showThinking?: boolean;\n};\n\nexport function fromAgUiMessages(\n messages: readonly unknown[],\n options?: FromAgUiMessagesOptions,\n): CoreThreadMessageLike[] {\n const showThinking = options?.showThinking ?? true;\n const converted: CoreThreadMessageLike[] = [];\n\n for (const rawMessage of messages) {\n if (!isObject(rawMessage)) continue;\n const role = getString(rawMessage, \"role\");\n if (!role) continue;\n\n if (role === \"tool\") {\n const toolCallId = getToolCallId(rawMessage) ?? `tool-${generateId()}`;\n const toolMessageId = getString(rawMessage, \"id\");\n const result =\n rawMessage.result !== undefined\n ? rawMessage.result\n : typeof rawMessage.content === \"string\"\n ? parseJSONText(rawMessage.content)\n : rawMessage.content;\n const isError =\n typeof rawMessage.error === \"string\" ||\n rawMessage.isError === true ||\n rawMessage.status === \"error\"\n ? true\n : rawMessage.isError === false\n ? false\n : undefined;\n\n let updated = false;\n for (\n let messageIndex = converted.length - 1;\n messageIndex >= 0 && !updated;\n messageIndex--\n ) {\n const message = converted[messageIndex];\n if (\n !message ||\n message.role !== \"assistant\" ||\n !Array.isArray(message.content)\n )\n continue;\n\n for (\n let partIndex = message.content.length - 1;\n partIndex >= 0;\n partIndex--\n ) {\n const part = message.content[partIndex];\n if (!isObject(part) || part.type !== \"tool-call\") continue;\n if (getString(part, \"toolCallId\") !== toolCallId) continue;\n\n const updatedPart: ToolCallPart = {\n ...(part as ToolCallPart),\n result,\n ...(isError !== undefined ? { isError } : {}),\n ...(toolMessageId !== undefined\n ? { unstable_toolMessageId: toolMessageId }\n : {}),\n };\n const updatedContent = message.content.map((contentPart, index) =>\n index === partIndex ? updatedPart : contentPart,\n );\n converted[messageIndex] = { ...message, content: updatedContent };\n updated = true;\n break;\n }\n }\n\n if (updated) {\n continue;\n }\n\n const id = toolMessageId ?? toolCallId;\n const toolName =\n getString(rawMessage, \"name\") ??\n getString(rawMessage, \"toolName\") ??\n \"tool\";\n converted.push({\n id: `${id}:assistant`,\n role: \"assistant\",\n content: [\n {\n type: \"tool-call\",\n toolCallId,\n toolName,\n args: {},\n argsText: \"{}\",\n result,\n ...(isError !== undefined ? { isError } : {}),\n ...(toolMessageId !== undefined\n ? { unstable_toolMessageId: toolMessageId }\n : {}),\n },\n ],\n });\n continue;\n }\n\n if (role === \"assistant\") {\n converted.push(toAssistantSnapshotMessage(rawMessage));\n continue;\n }\n\n if (role === \"reasoning\") {\n // Gate on showThinking so a cold reload matches the live run: the\n // aggregator never stores reasoning parts when showThinking is false.\n if (!showThinking) continue;\n const text = extractText(rawMessage.content);\n if (text.trim().length === 0) continue;\n converted.push({\n id: getString(rawMessage, \"id\") ?? generateId(),\n role: \"assistant\",\n content: [{ type: \"reasoning\", text }],\n });\n continue;\n }\n\n if (role === \"user\" || role === \"system\") {\n converted.push(toUserOrSystemSnapshotMessage(role, rawMessage));\n }\n }\n\n return converted;\n}\n\nfunction convertAssistantMessage(\n message: ThreadMessageLike,\n converted: AgUiMessage[],\n): void {\n const content = extractText(message.content);\n const contentArray = Array.isArray(message.content) ? message.content : [];\n\n const toolCallParts = contentArray.filter(\n (part): part is ToolCallPart => part?.type === \"tool-call\",\n );\n\n const toolCalls = toolCallParts.map((part) => ({\n ...normalizeToolCall(part),\n part,\n }));\n\n // Drop assistant messages with no text or tool calls (e.g. an imported\n // reasoning-only entry) so they are not re-sent as a blank assistant turn.\n if (content.length === 0 && toolCalls.length === 0) {\n return;\n }\n\n const assistantMessage: AgUiMessage = {\n id: message.id,\n role: \"assistant\",\n content,\n };\n if (message.name) {\n assistantMessage.name = message.name;\n }\n if (toolCalls.length > 0) {\n assistantMessage.toolCalls = toolCalls.map((entry) => entry.call);\n }\n converted.push(assistantMessage);\n\n for (const { id: toolCallId, part } of toolCalls) {\n if (part.result === undefined) continue;\n\n const resultContent =\n typeof part.result === \"string\"\n ? part.result\n : JSON.stringify(part.result);\n\n const toolMessage: AgUiMessage = {\n id: part.unstable_toolMessageId ?? `${toolCallId}:tool`,\n role: \"tool\",\n content: resultContent,\n toolCallId,\n };\n if (part.isError) {\n toolMessage.error = resultContent;\n }\n converted.push(toolMessage);\n }\n}\n\nfunction convertToolMessage(\n message: ThreadMessageLike,\n converted: AgUiMessage[],\n): void {\n const content = extractText(message.content);\n const toolCallId = message.toolCallId ?? generateId();\n\n const toolMessage: AgUiMessage = {\n id: message.id,\n role: \"tool\",\n content,\n toolCallId,\n };\n if (typeof message.error === \"string\") {\n toolMessage.error = message.error;\n }\n converted.push(toolMessage);\n}\n\nexport function toAgUiMessages(\n messages: readonly ThreadMessageLike[],\n): AgUiMessage[] {\n const converted: AgUiMessage[] = [];\n\n for (const message of messages) {\n if (message.role === \"assistant\") {\n convertAssistantMessage(message, converted);\n continue;\n }\n\n if (message.role === \"tool\") {\n convertToolMessage(message, converted);\n continue;\n }\n\n const genericMessage: AgUiMessage = {\n id: message.id,\n role: message.role,\n content:\n message.role === \"user\"\n ? buildUserContent(message)\n : extractText(message.content),\n };\n if (message.name) {\n genericMessage.name = message.name;\n }\n converted.push(genericMessage);\n }\n\n return converted;\n}\n\ntype AgUiTool = {\n name: string;\n description: string | undefined;\n parameters: unknown;\n};\n\nexport function toAgUiTools(\n tools: Record<string, Tool> | undefined,\n): AgUiTool[] {\n if (!tools) return [];\n\n const toolsSchema = toToolsJSONSchema(tools);\n return Object.entries(toolsSchema).map(([name, tool]) => ({\n name,\n description: tool.description,\n parameters: tool.parameters,\n }));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"conversions.js","names":[],"sources":["../../../src/runtime/adapter/conversions.ts"],"sourcesContent":["\"use client\";\n\nimport type { InputContent } from \"@ag-ui/client\";\nimport type { ThreadMessageLike as CoreThreadMessageLike } from \"@assistant-ui/core\";\nimport { type Tool, toToolsJSONSchema } from \"assistant-stream\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\n\nexport type { InputContent };\n\ntype AttachmentLike = {\n name?: string | undefined;\n contentType?: string | undefined;\n content?: readonly unknown[] | undefined;\n};\n\ntype ThreadMessageLike = {\n id: string;\n role: string;\n content: unknown;\n name?: string;\n toolCallId?: string;\n error?: string;\n attachments?: readonly AttachmentLike[];\n};\n\ntype AgUiToolCall = {\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n};\n\nexport type AgUiMessage =\n | {\n id: string;\n role: string;\n content: string | InputContent[];\n name?: string;\n toolCalls?: AgUiToolCall[];\n }\n | {\n id: string;\n role: \"tool\";\n content: string;\n toolCallId: string;\n error?: string;\n };\n\ntype ToolCallPart = {\n type: \"tool-call\";\n toolCallId?: string;\n toolName: string;\n argsText?: string;\n args?: ReadonlyJSONObject;\n result?: unknown;\n isError?: boolean;\n unstable_toolMessageId?: string;\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nconst getString = (record: Record<string, unknown>, key: string) => {\n const value = record[key];\n return typeof value === \"string\" ? value : undefined;\n};\n\nconst getToolCallId = (record: Record<string, unknown>) =>\n getString(record, \"toolCallId\") ?? getString(record, \"tool_call_id\");\n\nfunction parseJSONText(value: string): unknown {\n if (!value) return value;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n\nfunction generateId(): string {\n return (\n (globalThis.crypto as { randomUUID?: () => string })?.randomUUID?.() ??\n Math.random().toString(36).slice(2)\n );\n}\n\nfunction normalizeToolCall(part: ToolCallPart): {\n id: string;\n call: AgUiToolCall;\n} {\n const id = part.toolCallId ?? generateId();\n const argsText =\n typeof part.argsText === \"string\"\n ? part.argsText\n : JSON.stringify(part.args ?? {});\n\n return {\n id,\n call: {\n id,\n type: \"function\",\n function: {\n name: part.toolName ?? \"tool\",\n arguments: argsText,\n },\n },\n };\n}\n\nfunction extractText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n\n return content\n .filter(\n (part): part is { type: \"text\"; text: string } =>\n part?.type === \"text\" && typeof part?.text === \"string\",\n )\n .map((part) => part.text)\n .join(\"\\n\");\n}\n\nfunction parseDataUrl(\n value: string,\n): { mimeType: string; data: string } | null {\n const match = value.match(/^data:([^;,]+)(?:;[^;,]+)*;base64,(.+)$/);\n if (!match) return null;\n return { mimeType: match[1]!, data: match[2]! };\n}\n\nconst httpUrlPattern = /^https?:\\/\\//i;\n\ntype InputContentSource =\n | { type: \"data\"; value: string; mimeType: string }\n | { type: \"url\"; value: string; mimeType?: string };\n\ntype MediaInputType = \"image\" | \"audio\" | \"video\" | \"document\";\n\nfunction mediaTypeForMime(mimeType: string | undefined): MediaInputType {\n if (mimeType?.startsWith(\"image/\")) return \"image\";\n if (mimeType?.startsWith(\"audio/\")) return \"audio\";\n if (mimeType?.startsWith(\"video/\")) return \"video\";\n return \"document\";\n}\n\n// Build an AG-UI multimodal source from a data URL, raw base64 payload, or an\n// http(s) URL. A `url` source may omit the mime type; a `data` source always\n// resolves one (falling back to application/octet-stream).\nfunction buildInputSource(\n value: string,\n declaredMimeType: string | undefined,\n): InputContentSource {\n if (httpUrlPattern.test(value)) {\n return declaredMimeType !== undefined\n ? { type: \"url\", value, mimeType: declaredMimeType }\n : { type: \"url\", value };\n }\n const parsed = parseDataUrl(value);\n return {\n type: \"data\",\n value: parsed?.data ?? value,\n mimeType:\n parsed?.mimeType ?? declaredMimeType ?? \"application/octet-stream\",\n };\n}\n\nfunction toInputContent(\n part: unknown,\n fallbackMimeType: string | undefined,\n): InputContent | null {\n if (!isObject(part)) return null;\n const type = getString(part, \"type\");\n\n if (type === \"text\") {\n const text = getString(part, \"text\");\n if (text === undefined) return null;\n return { type: \"text\", text };\n }\n\n if (type === \"image\") {\n const image = getString(part, \"image\");\n if (image === undefined) return null;\n return { type: \"image\", source: buildInputSource(image, fallbackMimeType) };\n }\n\n if (type === \"file\") {\n const data = getString(part, \"data\");\n if (data === undefined) return null;\n const declaredMimeType = getString(part, \"mimeType\") || fallbackMimeType;\n const filename = getString(part, \"filename\");\n const source = buildInputSource(data, declaredMimeType);\n const metadata = filename !== undefined ? { filename } : undefined;\n switch (mediaTypeForMime(source.mimeType)) {\n case \"image\":\n return { type: \"image\", source, ...(metadata && { metadata }) };\n case \"audio\":\n return { type: \"audio\", source, ...(metadata && { metadata }) };\n case \"video\":\n return { type: \"video\", source, ...(metadata && { metadata }) };\n default:\n return { type: \"document\", source, ...(metadata && { metadata }) };\n }\n }\n\n return null;\n}\n\ntype SnapshotAttachment = NonNullable<\n CoreThreadMessageLike[\"attachments\"]\n>[number];\n\nconst mediaInputTypes = new Set([\"image\", \"audio\", \"video\", \"document\"]);\n\n// Inverse of buildInputSource.\nfunction inputSourceToString(\n value: unknown,\n): { value: string; mimeType?: string } | null {\n if (!isObject(value)) return null;\n const sourceValue = getString(value, \"value\");\n if (sourceValue === undefined) return null;\n const mimeType = getString(value, \"mimeType\");\n const type = getString(value, \"type\");\n if (type === \"url\") {\n return { value: sourceValue, ...(mimeType !== undefined && { mimeType }) };\n }\n if (type === \"data\") {\n const resolvedMimeType = mimeType ?? \"application/octet-stream\";\n return {\n value: `data:${resolvedMimeType};base64,${sourceValue}`,\n mimeType: resolvedMimeType,\n };\n }\n return null;\n}\n\n// Mirrors @ag-ui/client's BackwardCompatibility_0_0_47 middleware.\nfunction upgradeBinaryInputPart(\n part: Record<string, unknown>,\n): Record<string, unknown> | null {\n const mimeType = getString(part, \"mimeType\");\n if (mimeType === undefined) return null;\n const data = getString(part, \"data\");\n const url = getString(part, \"url\");\n const source = data\n ? { type: \"data\", value: data, mimeType }\n : url\n ? { type: \"url\", value: url, mimeType }\n : null;\n if (!source) return null;\n const filename = getString(part, \"filename\");\n return {\n type: mediaTypeForMime(mimeType),\n source,\n ...(filename && { metadata: { filename } }),\n };\n}\n\nfunction toSnapshotAttachments(content: unknown): SnapshotAttachment[] {\n if (!Array.isArray(content)) return [];\n\n const attachments: SnapshotAttachment[] = [];\n for (const rawPart of content) {\n if (!isObject(rawPart)) continue;\n const part =\n getString(rawPart, \"type\") === \"binary\"\n ? upgradeBinaryInputPart(rawPart)\n : rawPart;\n if (!part) continue;\n const type = getString(part, \"type\");\n if (type === undefined || !mediaInputTypes.has(type)) continue;\n const source = inputSourceToString(part.source);\n if (!source) continue;\n\n const filename = isObject(part.metadata)\n ? getString(part.metadata, \"filename\")\n : undefined;\n const id = attachments.length.toString();\n\n if (type === \"image\") {\n attachments.push({\n id,\n type: \"image\",\n name: filename ?? \"image\",\n ...(source.mimeType !== undefined && { contentType: source.mimeType }),\n status: { type: \"complete\" },\n content: [\n {\n type: \"image\",\n image: source.value,\n ...(filename !== undefined && { filename }),\n },\n ],\n });\n continue;\n }\n\n const mimeType = source.mimeType ?? \"application/octet-stream\";\n attachments.push({\n id,\n type: type === \"document\" ? \"document\" : \"file\",\n name: filename ?? \"file\",\n contentType: mimeType,\n status: { type: \"complete\" },\n content: [\n {\n type: \"file\",\n data: source.value,\n mimeType,\n ...(filename !== undefined && { filename }),\n },\n ],\n });\n }\n return attachments;\n}\n\nfunction buildUserContent(message: ThreadMessageLike): string | InputContent[] {\n // File parts in message.content are intentionally skipped: the canonical\n // binary payload for files always flows through message.attachments.\n const contentParts = Array.isArray(message.content)\n ? message.content.filter(\n (part) => !(isObject(part) && part.type === \"file\"),\n )\n : [];\n\n const attachments = message.attachments ?? [];\n\n const converted: InputContent[] = [];\n\n // Promote string-form content to a leading text part so it survives when\n // non-text attachments are present (fromAgUiMessages emits string content).\n if (typeof message.content === \"string\" && message.content.length > 0) {\n converted.push({ type: \"text\", text: message.content });\n }\n\n for (const part of contentParts) {\n const input = toInputContent(part, undefined);\n if (input) converted.push(input);\n }\n for (const attachment of attachments) {\n if (!isObject(attachment)) continue;\n const attachmentContent = attachment.content;\n if (!Array.isArray(attachmentContent)) continue;\n const fallbackMime = getString(attachment, \"contentType\");\n for (const part of attachmentContent) {\n const input = toInputContent(part, fallbackMime);\n if (input) converted.push(input);\n }\n }\n\n const hasNonText = converted.some((part) => part.type !== \"text\");\n if (hasNonText) return converted;\n\n // All-text path: collapse to plain string. Join text parts collected from\n // both content and attachments so attachment-sourced text is not dropped.\n if (converted.length === 0) return extractText(message.content);\n return converted\n .filter(\n (part): part is { type: \"text\"; text: string } => part.type === \"text\",\n )\n .map((part) => part.text)\n .join(\"\\n\");\n}\n\nfunction toToolCallPart(value: unknown): ToolCallPart | null {\n if (!isObject(value)) return null;\n const rawFunction = isObject(value.function) ? value.function : null;\n const toolCallId = getString(value, \"toolCallId\") ?? getString(value, \"id\");\n const toolName =\n getString(value, \"toolName\") ??\n getString(value, \"name\") ??\n (rawFunction ? getString(rawFunction, \"name\") : undefined) ??\n \"tool\";\n const argsText =\n getString(value, \"argsText\") ??\n getString(value, \"arguments\") ??\n (rawFunction ? getString(rawFunction, \"arguments\") : undefined);\n\n const parsedArgs =\n typeof argsText === \"string\" ? parseJSONText(argsText) : undefined;\n const args =\n isObject(parsedArgs) && !Array.isArray(parsedArgs)\n ? (parsedArgs as ReadonlyJSONObject)\n : isObject(value.args) && !Array.isArray(value.args)\n ? (value.args as ReadonlyJSONObject)\n : undefined;\n\n const part: ToolCallPart = {\n type: \"tool-call\",\n ...(toolCallId !== undefined ? { toolCallId } : {}),\n toolName,\n argsText: argsText ?? JSON.stringify(args ?? {}),\n ...(args !== undefined ? { args } : {}),\n };\n\n if (value.type === \"tool-call\") {\n const result = value.result;\n const isError = value.isError;\n if (result !== undefined) part.result = result;\n if (typeof isError === \"boolean\") part.isError = isError;\n }\n\n return part;\n}\n\nfunction extractAssistantToolCalls(\n message: Record<string, unknown>,\n): ToolCallPart[] {\n const parts: ToolCallPart[] = [];\n const seenToolCallIds = new Set<string>();\n const pushPart = (part: ToolCallPart | null) => {\n if (!part) return;\n const id = part.toolCallId ?? generateId();\n if (seenToolCallIds.has(id)) return;\n seenToolCallIds.add(id);\n parts.push({\n ...part,\n toolCallId: id,\n });\n };\n\n const content = message.content;\n if (Array.isArray(content)) {\n for (const part of content) {\n if (isObject(part) && part.type === \"tool-call\") {\n pushPart(toToolCallPart(part));\n }\n }\n }\n\n const toolCalls = Array.isArray(message.toolCalls)\n ? message.toolCalls\n : Array.isArray(message.tool_calls)\n ? message.tool_calls\n : [];\n for (const call of toolCalls) {\n pushPart(toToolCallPart(call));\n }\n\n return parts;\n}\n\nfunction toAssistantSnapshotMessage(\n rawMessage: Record<string, unknown>,\n): CoreThreadMessageLike {\n const text = extractText(rawMessage.content);\n const toolCallParts = extractAssistantToolCalls(rawMessage);\n const assistantContent = [\n ...(text.length > 0 ? [{ type: \"text\" as const, text }] : []),\n ...toolCallParts,\n ];\n const messageName = getString(rawMessage, \"name\");\n return {\n id: getString(rawMessage, \"id\") ?? generateId(),\n role: \"assistant\",\n content: assistantContent.length > 0 ? assistantContent : \"\",\n ...(messageName !== undefined ? { name: messageName } : {}),\n };\n}\n\nfunction toUserOrSystemSnapshotMessage(\n role: \"user\" | \"system\",\n rawMessage: Record<string, unknown>,\n): CoreThreadMessageLike {\n const messageName = getString(rawMessage, \"name\");\n const attachments =\n role === \"user\" ? toSnapshotAttachments(rawMessage.content) : [];\n return {\n id: getString(rawMessage, \"id\") ?? generateId(),\n role,\n content: extractText(rawMessage.content),\n ...(messageName !== undefined ? { name: messageName } : {}),\n ...(attachments.length > 0 ? { attachments } : {}),\n };\n}\n\nexport type FromAgUiMessagesOptions = {\n /**\n * Whether to convert `reasoning` messages into visible reasoning parts.\n * Matches the `showThinking` option of `useAgUiRuntime`. Defaults to `true`.\n */\n showThinking?: boolean;\n};\n\nexport function fromAgUiMessages(\n messages: readonly unknown[],\n options?: FromAgUiMessagesOptions,\n): CoreThreadMessageLike[] {\n const showThinking = options?.showThinking ?? true;\n const converted: CoreThreadMessageLike[] = [];\n\n for (const rawMessage of messages) {\n if (!isObject(rawMessage)) continue;\n const role = getString(rawMessage, \"role\");\n if (!role) continue;\n\n if (role === \"tool\") {\n const toolCallId = getToolCallId(rawMessage) ?? `tool-${generateId()}`;\n const toolMessageId = getString(rawMessage, \"id\");\n const result =\n rawMessage.result !== undefined\n ? rawMessage.result\n : typeof rawMessage.content === \"string\"\n ? parseJSONText(rawMessage.content)\n : rawMessage.content;\n const isError =\n typeof rawMessage.error === \"string\" ||\n rawMessage.isError === true ||\n rawMessage.status === \"error\"\n ? true\n : rawMessage.isError === false\n ? false\n : undefined;\n\n let updated = false;\n for (\n let messageIndex = converted.length - 1;\n messageIndex >= 0 && !updated;\n messageIndex--\n ) {\n const message = converted[messageIndex];\n if (\n !message ||\n message.role !== \"assistant\" ||\n !Array.isArray(message.content)\n )\n continue;\n\n for (\n let partIndex = message.content.length - 1;\n partIndex >= 0;\n partIndex--\n ) {\n const part = message.content[partIndex];\n if (!isObject(part) || part.type !== \"tool-call\") continue;\n if (getString(part, \"toolCallId\") !== toolCallId) continue;\n\n const updatedPart: ToolCallPart = {\n ...(part as ToolCallPart),\n result,\n ...(isError !== undefined ? { isError } : {}),\n ...(toolMessageId !== undefined\n ? { unstable_toolMessageId: toolMessageId }\n : {}),\n };\n const updatedContent = message.content.map((contentPart, index) =>\n index === partIndex ? updatedPart : contentPart,\n );\n converted[messageIndex] = { ...message, content: updatedContent };\n updated = true;\n break;\n }\n }\n\n if (updated) {\n continue;\n }\n\n const id = toolMessageId ?? toolCallId;\n const toolName =\n getString(rawMessage, \"name\") ??\n getString(rawMessage, \"toolName\") ??\n \"tool\";\n converted.push({\n id: `${id}:assistant`,\n role: \"assistant\",\n content: [\n {\n type: \"tool-call\",\n toolCallId,\n toolName,\n args: {},\n argsText: \"{}\",\n result,\n ...(isError !== undefined ? { isError } : {}),\n ...(toolMessageId !== undefined\n ? { unstable_toolMessageId: toolMessageId }\n : {}),\n },\n ],\n });\n continue;\n }\n\n if (role === \"assistant\") {\n converted.push(toAssistantSnapshotMessage(rawMessage));\n continue;\n }\n\n if (role === \"reasoning\") {\n // Gate on showThinking so a cold reload matches the live run: the\n // aggregator never stores reasoning parts when showThinking is false.\n if (!showThinking) continue;\n const text = extractText(rawMessage.content);\n if (text.trim().length === 0) continue;\n converted.push({\n id: getString(rawMessage, \"id\") ?? generateId(),\n role: \"assistant\",\n content: [{ type: \"reasoning\", text }],\n });\n continue;\n }\n\n if (role === \"user\" || role === \"system\") {\n converted.push(toUserOrSystemSnapshotMessage(role, rawMessage));\n }\n }\n\n return converted;\n}\n\nfunction convertAssistantMessage(\n message: ThreadMessageLike,\n converted: AgUiMessage[],\n): void {\n const content = extractText(message.content);\n const contentArray = Array.isArray(message.content) ? message.content : [];\n\n const toolCallParts = contentArray.filter(\n (part): part is ToolCallPart => part?.type === \"tool-call\",\n );\n\n const toolCalls = toolCallParts.map((part) => ({\n ...normalizeToolCall(part),\n part,\n }));\n\n // Drop assistant messages with no text or tool calls (e.g. an imported\n // reasoning-only entry) so they are not re-sent as a blank assistant turn.\n if (content.length === 0 && toolCalls.length === 0) {\n return;\n }\n\n const assistantMessage: AgUiMessage = {\n id: message.id,\n role: \"assistant\",\n content,\n };\n if (message.name) {\n assistantMessage.name = message.name;\n }\n if (toolCalls.length > 0) {\n assistantMessage.toolCalls = toolCalls.map((entry) => entry.call);\n }\n converted.push(assistantMessage);\n\n for (const { id: toolCallId, part } of toolCalls) {\n if (part.result === undefined) continue;\n\n const resultContent =\n typeof part.result === \"string\"\n ? part.result\n : JSON.stringify(part.result);\n\n const toolMessage: AgUiMessage = {\n id: part.unstable_toolMessageId ?? `${toolCallId}:tool`,\n role: \"tool\",\n content: resultContent,\n toolCallId,\n };\n if (part.isError) {\n toolMessage.error = resultContent;\n }\n converted.push(toolMessage);\n }\n}\n\nfunction convertToolMessage(\n message: ThreadMessageLike,\n converted: AgUiMessage[],\n): void {\n const content = extractText(message.content);\n const toolCallId = message.toolCallId ?? generateId();\n\n const toolMessage: AgUiMessage = {\n id: message.id,\n role: \"tool\",\n content,\n toolCallId,\n };\n if (typeof message.error === \"string\") {\n toolMessage.error = message.error;\n }\n converted.push(toolMessage);\n}\n\nexport function toAgUiMessages(\n messages: readonly ThreadMessageLike[],\n): AgUiMessage[] {\n const converted: AgUiMessage[] = [];\n\n for (const message of messages) {\n if (message.role === \"assistant\") {\n convertAssistantMessage(message, converted);\n continue;\n }\n\n if (message.role === \"tool\") {\n convertToolMessage(message, converted);\n continue;\n }\n\n const genericMessage: AgUiMessage = {\n id: message.id,\n role: message.role,\n content:\n message.role === \"user\"\n ? buildUserContent(message)\n : extractText(message.content),\n };\n if (message.name) {\n genericMessage.name = message.name;\n }\n converted.push(genericMessage);\n }\n\n return converted;\n}\n\ntype AgUiTool = {\n name: string;\n description: string | undefined;\n parameters: unknown;\n};\n\nexport function toAgUiTools(\n tools: Record<string, Tool> | undefined,\n): AgUiTool[] {\n if (!tools) return [];\n\n const toolsSchema = toToolsJSONSchema(tools);\n return Object.entries(toolsSchema).map(([name, tool]) => ({\n name,\n description: tool.description,\n parameters: tool.parameters,\n }));\n}\n"],"mappings":"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"}
@@ -41,6 +41,7 @@ declare class RunAggregator {
41
41
  private firstTokenTime;
42
42
  private totalChunks;
43
43
  constructor(options: RunAggregatorOptions);
44
+ hasToolCall(toolCallId: string): boolean;
44
45
  handle(event: AgUiEvent): void;
45
46
  private reportServerMessageId;
46
47
  private clearTextParts;
@@ -53,7 +54,6 @@ declare class RunAggregator {
53
54
  private startToolCall;
54
55
  private appendToolArgs;
55
56
  private finishToolCall;
56
- private tryParseJSON;
57
57
  private emit;
58
58
  private recordFirstToken;
59
59
  private getTiming;
@@ -61,6 +61,7 @@ declare class RunAggregator {
61
61
  private handleReasoningContent;
62
62
  private handleReasoningEnd;
63
63
  }
64
+ declare function tryParseJSON(value: string): unknown;
64
65
  //#endregion
65
- export { AG_UI_METADATA_NAMESPACE, AgUiCustomMetadata, RunAggregator, RunAggregatorOptions };
66
+ export { AG_UI_METADATA_NAMESPACE, AgUiCustomMetadata, RunAggregator, RunAggregatorOptions, tryParseJSON };
66
67
  //# sourceMappingURL=run-aggregator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-aggregator.d.ts","names":[],"sources":["../../../src/runtime/adapter/run-aggregator.ts"],"mappings":";;;;;cAYa,wBAAA;AAAA,KAED,kBAAA;EACV,UAAA,GAAa,aAAa;AAAA;AAAA,KAGvB,IAAA,IAAQ,MAA0B,EAAlB,kBAAkB;AAAA,KAgB3B,oBAAA;EACV,YAAA;EACA,MAAA,EAAQ,MAAA;EACR,IAAA,EAAM,IAAI;EACV,iBAAA,IAAqB,SAAA;AAAA;AAvBK;AAC1B;;;;AAEqC;AAHX,cAgCf,aAAA;EAAA,iBACM,UAAA;EAAA,iBACA,YAAA;EAAA,iBACA,MAAA;EAAA,iBACA,iBAAA;EAAA,QAET,MAAA;EAAA,QACA,UAAA;EAAA,iBACS,SAAA;EAAA,QAIT,mBAAA;EAAA,iBACS,cAAA;EAAA,QACT,kBAAA;EAAA,QACA,oBAAA;EAAA,iBACS,SAAA;EAAA,QACT,sBAAA;EAAA,iBACS,SAAA;EAAA,QAKT,eAAA;EAAA,QACA,uBAAA;EAAA,QAEA,eAAA;EAAA,QACA,cAAA;EAAA,QACA,WAAA;cAEI,OAAA,EAAS,oBAAA;EAOrB,MAAA,CAAO,KAAA,EAAO,SAAS;EAAA,QA0Kf,qBAAA;EAAA,QAMA,cAAA;EAAA,QAIA,eAAA;EAAA,QAKA,gBAAA;EAAA,QAOA,oBAAA;EAAA,QAiBA,cAAA;EAAA,QAWA,mBAAA;EAAA,QAMA,UAAA;EAAA,QAQA,aAAA;EAAA,QA8BA,cAAA;EAAA,QAgBA,cAAA;EAAA,QAkCA,YAAA;EAAA,QASA,IAAA;EAAA,QAgEA,gBAAA;EAAA,QASA,SAAA;EAAA,QAgCA,oBAAA;EAAA,QAcA,sBAAA;EAAA,QAYA,kBAAA;AAAA"}
1
+ {"version":3,"file":"run-aggregator.d.ts","names":[],"sources":["../../../src/runtime/adapter/run-aggregator.ts"],"mappings":";;;;;cAYa,wBAAA;AAAA,KAED,kBAAA;EACV,UAAA,GAAa,aAAa;AAAA;AAAA,KAGvB,IAAA,IAAQ,MAA0B,EAAlB,kBAAkB;AAAA,KAgB3B,oBAAA;EACV,YAAA;EACA,MAAA,EAAQ,MAAA;EACR,IAAA,EAAM,IAAI;EACV,iBAAA,IAAqB,SAAA;AAAA;AAvBK;AAC1B;;;;AAEqC;AAHX,cAgCf,aAAA;EAAA,iBACM,UAAA;EAAA,iBACA,YAAA;EAAA,iBACA,MAAA;EAAA,iBACA,iBAAA;EAAA,QAET,MAAA;EAAA,QACA,UAAA;EAAA,iBACS,SAAA;EAAA,QAIT,mBAAA;EAAA,iBACS,cAAA;EAAA,QACT,kBAAA;EAAA,QACA,oBAAA;EAAA,iBACS,SAAA;EAAA,QACT,sBAAA;EAAA,iBACS,SAAA;EAAA,QAKT,eAAA;EAAA,QACA,uBAAA;EAAA,QAEA,eAAA;EAAA,QACA,cAAA;EAAA,QACA,WAAA;cAEI,OAAA,EAAS,oBAAA;EAOrB,WAAA,CAAY,UAAA;EAIZ,MAAA,CAAO,KAAA,EAAO,SAAS;EAAA,QA0Kf,qBAAA;EAAA,QAMA,cAAA;EAAA,QAIA,eAAA;EAAA,QAKA,gBAAA;EAAA,QAOA,oBAAA;EAAA,QAiBA,cAAA;EAAA,QAWA,mBAAA;EAAA,QAMA,UAAA;EAAA,QAQA,aAAA;EAAA,QA8BA,cAAA;EAAA,QAgBA,cAAA;EAAA,QAkCA,IAAA;EAAA,QAgEA,gBAAA;EAAA,QASA,SAAA;EAAA,QAgCA,oBAAA;EAAA,QAcA,sBAAA;EAAA,QAYA,kBAAA;AAAA;AAAA,iBAOM,YAAA,CAAa,KAAa"}
@@ -35,6 +35,9 @@ var RunAggregator = class {
35
35
  this.logger = options.logger;
36
36
  this.onServerMessageId = options.onServerMessageId;
37
37
  }
38
+ hasToolCall(toolCallId) {
39
+ return this.toolCalls.has(toolCallId);
40
+ }
38
41
  handle(event) {
39
42
  switch (event.type) {
40
43
  case "RUN_STARTED":
@@ -273,19 +276,11 @@ var RunAggregator = class {
273
276
  kind: "tool-call",
274
277
  toolCallId: id
275
278
  });
276
- entry.result = this.tryParseJSON(content);
279
+ entry.result = tryParseJSON(content);
277
280
  entry.isError = isError;
278
281
  if (toolMessageId) entry.toolMessageId = toolMessageId;
279
282
  this.lastResolvedToolCallId = id;
280
283
  }
281
- tryParseJSON(value) {
282
- if (!value) return value;
283
- try {
284
- return JSON.parse(value);
285
- } catch {
286
- return value;
287
- }
288
- }
289
284
  emit() {
290
285
  const snapshot = [];
291
286
  for (const part of this.partOrder) {
@@ -381,7 +376,15 @@ var RunAggregator = class {
381
376
  this.emit();
382
377
  }
383
378
  };
379
+ function tryParseJSON(value) {
380
+ if (!value) return value;
381
+ try {
382
+ return JSON.parse(value);
383
+ } catch {
384
+ return value;
385
+ }
386
+ }
384
387
  //#endregion
385
- export { AG_UI_METADATA_NAMESPACE, RunAggregator };
388
+ export { AG_UI_METADATA_NAMESPACE, RunAggregator, tryParseJSON };
386
389
 
387
390
  //# sourceMappingURL=run-aggregator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-aggregator.js","names":[],"sources":["../../../src/runtime/adapter/run-aggregator.ts"],"sourcesContent":["\"use client\";\n\nimport {\n isMcpAppUri,\n type ChatModelRunResult,\n type MessageTiming,\n type ThreadAssistantMessagePart,\n type ToolCallMessagePart,\n} from \"@assistant-ui/core\";\nimport type { AgUiEvent, AgUiInterrupt } from \"../types\";\nimport type { Logger } from \"../logger\";\n\nexport const AG_UI_METADATA_NAMESPACE = \"agui\";\n\nexport type AgUiCustomMetadata = {\n interrupts?: AgUiInterrupt[];\n};\n\ntype Emit = (update: ChatModelRunResult) => void;\n\ntype ToolCallState = {\n toolCallId: string;\n toolCallName: string;\n argsText: string;\n parsedArgs: Record<string, unknown> | undefined;\n result: unknown;\n isError: boolean | undefined;\n parentMessageId?: string;\n toolMessageId?: string;\n mcpAppResourceUri?: string;\n};\n\nconst MCP_APPS_ACTIVITY_TYPE = \"mcp-apps\";\n\nexport type RunAggregatorOptions = {\n showThinking: boolean;\n logger: Logger;\n emit: Emit;\n onServerMessageId?: (messageId: string) => void;\n};\n\n/**\n * Collects AG-UI events into assistant-ui run snapshots that can be yielded from a ChatModelAdapter.\n *\n * The aggregator keeps a single assistant message worth of parts. Each incoming event updates the parts and\n * emits a fresh snapshot through the provided `emit` callback.\n */\nexport class RunAggregator {\n private readonly emitUpdate: Emit;\n private readonly showThinking: boolean;\n private readonly logger: Logger;\n private readonly onServerMessageId: ((messageId: string) => void) | undefined;\n\n private status: ChatModelRunResult[\"status\"] | undefined;\n private interrupts: AgUiInterrupt[] | undefined;\n private readonly textParts = new Map<\n string,\n { buffer: string; touched: boolean }\n >();\n private activeTextMessageId: string | undefined;\n private readonly reasoningParts = new Map<string, string>(); // key → buffer\n private activeReasoningKey: string | undefined;\n private reasoningPartCounter = 0;\n private readonly toolCalls = new Map<string, ToolCallState>();\n private lastResolvedToolCallId: string | undefined;\n private readonly partOrder: (\n | { kind: \"text\"; key: string }\n | { kind: \"reasoning\"; key: string }\n | { kind: \"tool-call\"; toolCallId: string }\n )[] = [];\n private textPartCounter = 0;\n private serverMessageIdReported = false;\n\n private streamStartTime: number | undefined;\n private firstTokenTime: number | undefined;\n private totalChunks = 0;\n\n constructor(options: RunAggregatorOptions) {\n this.emitUpdate = options.emit;\n this.showThinking = options.showThinking;\n this.logger = options.logger;\n this.onServerMessageId = options.onServerMessageId;\n }\n\n handle(event: AgUiEvent): void {\n switch (event.type) {\n case \"RUN_STARTED\": {\n this.clearTextParts();\n this.reasoningParts.clear();\n this.activeReasoningKey = undefined;\n this.reasoningPartCounter = 0;\n this.toolCalls.clear();\n this.lastResolvedToolCallId = undefined;\n this.partOrder.length = 0;\n this.textPartCounter = 0;\n this.activeTextMessageId = undefined;\n this.interrupts = undefined;\n this.serverMessageIdReported = false;\n this.streamStartTime = Date.now();\n this.firstTokenTime = undefined;\n this.totalChunks = 0;\n this.status = { type: \"running\" };\n this.emit();\n break;\n }\n case \"RUN_FINISHED\": {\n if (event.outcome?.type === \"interrupt\") {\n this.interrupts = event.outcome.interrupts;\n this.status = { type: \"requires-action\", reason: \"interrupt\" };\n this.emit();\n break;\n }\n\n this.interrupts = undefined;\n const hasUnresolvedToolCalls = Array.from(this.toolCalls.values()).some(\n (tc) => tc.result === undefined,\n );\n\n this.status =\n event.outcome?.type === \"success\" || !hasUnresolvedToolCalls\n ? { type: \"complete\", reason: \"unknown\" }\n : { type: \"requires-action\", reason: \"tool-calls\" };\n this.emit();\n break;\n }\n case \"RUN_ERROR\": {\n this.status = {\n type: \"incomplete\",\n reason: \"error\",\n ...(event.message !== undefined ? { error: event.message } : {}),\n };\n this.emit();\n break;\n }\n case \"RUN_CANCELLED\": {\n this.status = { type: \"incomplete\", reason: \"cancelled\" };\n this.emit();\n break;\n }\n\n case \"TEXT_MESSAGE_START\": {\n this.reportServerMessageId(event.messageId);\n const id = this.startTextMessage(event.messageId);\n if (id) {\n this.markTextPartTouched(id);\n }\n this.emit();\n break;\n }\n case \"TEXT_MESSAGE_CONTENT\":\n case \"TEXT_MESSAGE_CHUNK\": {\n const incomingId = \"messageId\" in event ? event.messageId : undefined;\n this.reportServerMessageId(incomingId);\n if (!event.delta) break;\n this.recordFirstToken();\n const id = this.resolveTextMessageId(incomingId);\n this.appendText(id, event.delta);\n this.totalChunks++;\n this.emit();\n break;\n }\n case \"TEXT_MESSAGE_END\": {\n this.reportServerMessageId(event.messageId);\n if (event.messageId && this.activeTextMessageId === event.messageId) {\n this.activeTextMessageId = undefined;\n }\n this.emit();\n break;\n }\n\n case \"THINKING_START\":\n case \"THINKING_TEXT_MESSAGE_START\":\n case \"REASONING_START\":\n case \"REASONING_MESSAGE_START\":\n this.handleReasoningStart(\n \"messageId\" in event ? event.messageId : undefined,\n );\n break;\n case \"THINKING_TEXT_MESSAGE_CONTENT\":\n this.handleReasoningContent(event.delta);\n this.totalChunks++;\n this.recordFirstToken();\n break;\n case \"REASONING_MESSAGE_CONTENT\":\n this.handleReasoningContent(\n event.delta,\n \"messageId\" in event ? event.messageId : undefined,\n );\n this.totalChunks++;\n this.recordFirstToken();\n break;\n case \"THINKING_TEXT_MESSAGE_END\":\n case \"THINKING_END\":\n case \"REASONING_MESSAGE_END\":\n case \"REASONING_END\":\n this.handleReasoningEnd();\n break;\n\n case \"TOOL_CALL_START\": {\n this.reportServerMessageId(event.parentMessageId);\n this.startToolCall(\n event.toolCallId,\n event.toolCallName,\n event.parentMessageId,\n );\n this.emit();\n break;\n }\n case \"TOOL_CALL_ARGS\":\n case \"TOOL_CALL_CHUNK\": {\n if (event.type === \"TOOL_CALL_CHUNK\") {\n this.reportServerMessageId(event.parentMessageId);\n }\n if (!event.delta) break;\n this.appendToolArgs(event.toolCallId, event.delta);\n this.emit();\n break;\n }\n case \"TOOL_CALL_END\": {\n this.emit();\n break;\n }\n case \"TOOL_CALL_RESULT\": {\n this.finishToolCall(\n event.toolCallId,\n event.content ?? \"\",\n event.role === \"tool\" ? false : undefined,\n event.messageId,\n );\n this.emit();\n break;\n }\n case \"ACTIVITY_SNAPSHOT\": {\n if (event.activityType !== MCP_APPS_ACTIVITY_TYPE) break;\n const id = this.lastResolvedToolCallId;\n const entry = id ? this.toolCalls.get(id) : undefined;\n const resourceUri = event.content.resourceUri;\n if (\n entry &&\n typeof resourceUri === \"string\" &&\n isMcpAppUri(resourceUri)\n ) {\n entry.mcpAppResourceUri = resourceUri;\n this.emit();\n }\n break;\n }\n\n default: {\n this.logger.debug?.(\"[agui] aggregator ignored event\", event);\n }\n }\n }\n\n private reportServerMessageId(messageId: string | undefined): void {\n if (this.serverMessageIdReported || !messageId) return;\n this.serverMessageIdReported = true;\n this.onServerMessageId?.(messageId);\n }\n\n private clearTextParts(): void {\n this.textParts.clear();\n }\n\n private generateTextKey(): string {\n this.textPartCounter += 1;\n return `text-${this.textPartCounter}`;\n }\n\n private startTextMessage(messageId?: string): string {\n const id = messageId ?? this.generateTextKey();\n this.ensureTextPart(id);\n this.activeTextMessageId = id;\n return id;\n }\n\n private resolveTextMessageId(messageId?: string): string {\n if (messageId) {\n this.ensureTextPart(messageId);\n this.activeTextMessageId = messageId;\n return messageId;\n }\n\n if (this.activeTextMessageId) {\n return this.activeTextMessageId;\n }\n\n const generated = this.generateTextKey();\n this.ensureTextPart(generated);\n this.activeTextMessageId = generated;\n return generated;\n }\n\n private ensureTextPart(id: string): void {\n if (!this.textParts.has(id)) {\n this.textParts.set(id, { buffer: \"\", touched: false });\n if (\n !this.partOrder.some((part) => part.kind === \"text\" && part.key === id)\n ) {\n this.partOrder.push({ kind: \"text\", key: id });\n }\n }\n }\n\n private markTextPartTouched(id: string): void {\n const entry = this.textParts.get(id);\n if (!entry) return;\n entry.touched = true;\n }\n\n private appendText(id: string, delta: string): void {\n this.ensureTextPart(id);\n const entry = this.textParts.get(id);\n if (!entry) return;\n entry.buffer += delta;\n entry.touched = true;\n }\n\n private startToolCall(\n id: string | undefined,\n name?: string,\n parentMessageId?: string,\n ) {\n if (!id) return;\n // A new tool call acts as a boundary: any anonymous text that arrives\n // after it should be a new part, not appended to the pre-tool text.\n this.activeTextMessageId = undefined;\n if (\n !this.partOrder.some(\n (part) => part.kind === \"tool-call\" && part.toolCallId === id,\n )\n ) {\n this.partOrder.push({ kind: \"tool-call\", toolCallId: id });\n }\n const state: ToolCallState = {\n toolCallId: id,\n toolCallName: name ?? \"tool\",\n argsText: \"\",\n parsedArgs: undefined,\n result: undefined,\n isError: undefined,\n };\n if (parentMessageId) {\n state.parentMessageId = parentMessageId;\n }\n this.toolCalls.set(id, state);\n }\n\n private appendToolArgs(id: string | undefined, delta: string) {\n const entry = id ? this.toolCalls.get(id) : undefined;\n if (!entry) return;\n entry.argsText += delta;\n try {\n const parsed = JSON.parse(entry.argsText);\n if (parsed && typeof parsed === \"object\") {\n entry.parsedArgs = parsed as Record<string, unknown>;\n } else {\n entry.parsedArgs = undefined;\n }\n } catch {\n entry.parsedArgs = undefined;\n }\n }\n\n private finishToolCall(\n id: string,\n content: string,\n isError?: boolean,\n toolMessageId?: string,\n ) {\n if (!id) return;\n let entry = this.toolCalls.get(id);\n if (!entry) {\n entry = {\n toolCallId: id,\n toolCallName: \"tool\",\n argsText: \"\",\n parsedArgs: undefined,\n result: undefined,\n isError: undefined,\n };\n this.toolCalls.set(id, entry);\n }\n if (\n !this.partOrder.some(\n (part) => part.kind === \"tool-call\" && part.toolCallId === id,\n )\n ) {\n this.partOrder.push({ kind: \"tool-call\", toolCallId: id });\n }\n entry.result = this.tryParseJSON(content);\n entry.isError = isError;\n if (toolMessageId) {\n entry.toolMessageId = toolMessageId;\n }\n this.lastResolvedToolCallId = id;\n }\n\n private tryParseJSON(value: string): unknown {\n if (!value) return value;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n }\n\n private emit(): void {\n const snapshot: ThreadAssistantMessagePart[] = [];\n\n for (const part of this.partOrder) {\n if (part.kind === \"reasoning\") {\n if (this.showThinking) {\n const buffer = this.reasoningParts.get(part.key) ?? \"\";\n if (buffer.length > 0 || this.activeReasoningKey === part.key) {\n snapshot.push({ type: \"reasoning\", text: buffer } as const);\n }\n }\n continue;\n }\n\n if (part.kind === \"text\") {\n const entry = this.textParts.get(part.key);\n if (entry?.touched) {\n snapshot.push({ type: \"text\", text: entry.buffer } as const);\n }\n continue;\n }\n\n const entry = this.toolCalls.get(part.toolCallId);\n if (!entry) continue;\n const toolPart: ToolCallMessagePart = {\n type: \"tool-call\",\n toolCallId: entry.toolCallId,\n toolName: entry.toolCallName,\n args: (entry.parsedArgs ?? {}) as any,\n argsText: entry.argsText,\n ...(entry.result !== undefined ? { result: entry.result } : {}),\n ...(entry.isError !== undefined ? { isError: entry.isError } : {}),\n ...(entry.mcpAppResourceUri\n ? { mcp: { app: { resourceUri: entry.mcpAppResourceUri } } }\n : {}),\n ...(entry.parentMessageId ? { parentId: entry.parentMessageId } : {}),\n ...(entry.toolMessageId\n ? { unstable_toolMessageId: entry.toolMessageId }\n : {}),\n } as ToolCallMessagePart & { unstable_toolMessageId?: string };\n snapshot.push(toolPart);\n }\n\n const timing = this.getTiming();\n const metadata = {\n ...(timing ? { timing } : {}),\n ...(this.interrupts\n ? {\n custom: {\n [AG_UI_METADATA_NAMESPACE]: {\n interrupts: this.interrupts,\n } satisfies AgUiCustomMetadata,\n },\n }\n : {}),\n };\n const result: ChatModelRunResult = {\n content: snapshot,\n ...(this.status ? { status: this.status } : undefined),\n ...(Object.keys(metadata).length > 0 ? { metadata } : undefined),\n };\n this.emitUpdate(result);\n }\n\n private recordFirstToken(): void {\n if (\n this.firstTokenTime === undefined &&\n this.streamStartTime !== undefined\n ) {\n this.firstTokenTime = Date.now() - this.streamStartTime;\n }\n }\n\n private getTiming(): MessageTiming | undefined {\n if (this.streamStartTime === undefined) return undefined;\n\n const now = Date.now();\n const totalStreamTime = now - this.streamStartTime;\n const tokenCount =\n this.totalChunks > 0\n ? Math.ceil(\n Array.from(this.textParts.values()).reduce(\n (sum, p) => sum + p.buffer.length,\n 0,\n ) / 4,\n )\n : undefined;\n const tokensPerSecond =\n tokenCount && totalStreamTime > 0\n ? (tokenCount / totalStreamTime) * 1000\n : undefined;\n\n return {\n streamStartTime: this.streamStartTime,\n ...(this.firstTokenTime !== undefined\n ? { firstTokenTime: this.firstTokenTime }\n : {}),\n totalStreamTime,\n ...(tokenCount !== undefined ? { tokenCount } : {}),\n ...(tokensPerSecond !== undefined ? { tokensPerSecond } : {}),\n totalChunks: this.totalChunks,\n toolCallCount: this.toolCalls.size,\n };\n }\n\n private handleReasoningStart(messageId?: string): void {\n if (!this.showThinking) return;\n // A reasoning block acts as a boundary: anonymous text arriving after it\n // should be a new part, not appended to any pre-reasoning text.\n this.activeTextMessageId = undefined;\n const key = messageId ?? `__auto-reasoning-${++this.reasoningPartCounter}`;\n if (!this.reasoningParts.has(key)) {\n this.reasoningParts.set(key, \"\");\n this.partOrder.push({ kind: \"reasoning\", key });\n }\n this.activeReasoningKey = key;\n this.emit();\n }\n\n private handleReasoningContent(delta: string, messageId?: string): void {\n if (!this.showThinking || !delta) return;\n if (!this.activeReasoningKey) {\n // Content arrived without a preceding START — create the slot lazily.\n this.handleReasoningStart(messageId);\n }\n const key = this.activeReasoningKey;\n if (!key) return;\n this.reasoningParts.set(key, (this.reasoningParts.get(key) ?? \"\") + delta);\n this.emit();\n }\n\n private handleReasoningEnd(): void {\n if (!this.showThinking) return;\n this.activeReasoningKey = undefined;\n this.emit();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"run-aggregator.js","names":[],"sources":["../../../src/runtime/adapter/run-aggregator.ts"],"sourcesContent":["\"use client\";\n\nimport {\n isMcpAppUri,\n type ChatModelRunResult,\n type MessageTiming,\n type ThreadAssistantMessagePart,\n type ToolCallMessagePart,\n} from \"@assistant-ui/core\";\nimport type { AgUiEvent, AgUiInterrupt } from \"../types\";\nimport type { Logger } from \"../logger\";\n\nexport const AG_UI_METADATA_NAMESPACE = \"agui\";\n\nexport type AgUiCustomMetadata = {\n interrupts?: AgUiInterrupt[];\n};\n\ntype Emit = (update: ChatModelRunResult) => void;\n\ntype ToolCallState = {\n toolCallId: string;\n toolCallName: string;\n argsText: string;\n parsedArgs: Record<string, unknown> | undefined;\n result: unknown;\n isError: boolean | undefined;\n parentMessageId?: string;\n toolMessageId?: string;\n mcpAppResourceUri?: string;\n};\n\nconst MCP_APPS_ACTIVITY_TYPE = \"mcp-apps\";\n\nexport type RunAggregatorOptions = {\n showThinking: boolean;\n logger: Logger;\n emit: Emit;\n onServerMessageId?: (messageId: string) => void;\n};\n\n/**\n * Collects AG-UI events into assistant-ui run snapshots that can be yielded from a ChatModelAdapter.\n *\n * The aggregator keeps a single assistant message worth of parts. Each incoming event updates the parts and\n * emits a fresh snapshot through the provided `emit` callback.\n */\nexport class RunAggregator {\n private readonly emitUpdate: Emit;\n private readonly showThinking: boolean;\n private readonly logger: Logger;\n private readonly onServerMessageId: ((messageId: string) => void) | undefined;\n\n private status: ChatModelRunResult[\"status\"] | undefined;\n private interrupts: AgUiInterrupt[] | undefined;\n private readonly textParts = new Map<\n string,\n { buffer: string; touched: boolean }\n >();\n private activeTextMessageId: string | undefined;\n private readonly reasoningParts = new Map<string, string>(); // key → buffer\n private activeReasoningKey: string | undefined;\n private reasoningPartCounter = 0;\n private readonly toolCalls = new Map<string, ToolCallState>();\n private lastResolvedToolCallId: string | undefined;\n private readonly partOrder: (\n | { kind: \"text\"; key: string }\n | { kind: \"reasoning\"; key: string }\n | { kind: \"tool-call\"; toolCallId: string }\n )[] = [];\n private textPartCounter = 0;\n private serverMessageIdReported = false;\n\n private streamStartTime: number | undefined;\n private firstTokenTime: number | undefined;\n private totalChunks = 0;\n\n constructor(options: RunAggregatorOptions) {\n this.emitUpdate = options.emit;\n this.showThinking = options.showThinking;\n this.logger = options.logger;\n this.onServerMessageId = options.onServerMessageId;\n }\n\n hasToolCall(toolCallId: string): boolean {\n return this.toolCalls.has(toolCallId);\n }\n\n handle(event: AgUiEvent): void {\n switch (event.type) {\n case \"RUN_STARTED\": {\n this.clearTextParts();\n this.reasoningParts.clear();\n this.activeReasoningKey = undefined;\n this.reasoningPartCounter = 0;\n this.toolCalls.clear();\n this.lastResolvedToolCallId = undefined;\n this.partOrder.length = 0;\n this.textPartCounter = 0;\n this.activeTextMessageId = undefined;\n this.interrupts = undefined;\n this.serverMessageIdReported = false;\n this.streamStartTime = Date.now();\n this.firstTokenTime = undefined;\n this.totalChunks = 0;\n this.status = { type: \"running\" };\n this.emit();\n break;\n }\n case \"RUN_FINISHED\": {\n if (event.outcome?.type === \"interrupt\") {\n this.interrupts = event.outcome.interrupts;\n this.status = { type: \"requires-action\", reason: \"interrupt\" };\n this.emit();\n break;\n }\n\n this.interrupts = undefined;\n const hasUnresolvedToolCalls = Array.from(this.toolCalls.values()).some(\n (tc) => tc.result === undefined,\n );\n\n this.status =\n event.outcome?.type === \"success\" || !hasUnresolvedToolCalls\n ? { type: \"complete\", reason: \"unknown\" }\n : { type: \"requires-action\", reason: \"tool-calls\" };\n this.emit();\n break;\n }\n case \"RUN_ERROR\": {\n this.status = {\n type: \"incomplete\",\n reason: \"error\",\n ...(event.message !== undefined ? { error: event.message } : {}),\n };\n this.emit();\n break;\n }\n case \"RUN_CANCELLED\": {\n this.status = { type: \"incomplete\", reason: \"cancelled\" };\n this.emit();\n break;\n }\n\n case \"TEXT_MESSAGE_START\": {\n this.reportServerMessageId(event.messageId);\n const id = this.startTextMessage(event.messageId);\n if (id) {\n this.markTextPartTouched(id);\n }\n this.emit();\n break;\n }\n case \"TEXT_MESSAGE_CONTENT\":\n case \"TEXT_MESSAGE_CHUNK\": {\n const incomingId = \"messageId\" in event ? event.messageId : undefined;\n this.reportServerMessageId(incomingId);\n if (!event.delta) break;\n this.recordFirstToken();\n const id = this.resolveTextMessageId(incomingId);\n this.appendText(id, event.delta);\n this.totalChunks++;\n this.emit();\n break;\n }\n case \"TEXT_MESSAGE_END\": {\n this.reportServerMessageId(event.messageId);\n if (event.messageId && this.activeTextMessageId === event.messageId) {\n this.activeTextMessageId = undefined;\n }\n this.emit();\n break;\n }\n\n case \"THINKING_START\":\n case \"THINKING_TEXT_MESSAGE_START\":\n case \"REASONING_START\":\n case \"REASONING_MESSAGE_START\":\n this.handleReasoningStart(\n \"messageId\" in event ? event.messageId : undefined,\n );\n break;\n case \"THINKING_TEXT_MESSAGE_CONTENT\":\n this.handleReasoningContent(event.delta);\n this.totalChunks++;\n this.recordFirstToken();\n break;\n case \"REASONING_MESSAGE_CONTENT\":\n this.handleReasoningContent(\n event.delta,\n \"messageId\" in event ? event.messageId : undefined,\n );\n this.totalChunks++;\n this.recordFirstToken();\n break;\n case \"THINKING_TEXT_MESSAGE_END\":\n case \"THINKING_END\":\n case \"REASONING_MESSAGE_END\":\n case \"REASONING_END\":\n this.handleReasoningEnd();\n break;\n\n case \"TOOL_CALL_START\": {\n this.reportServerMessageId(event.parentMessageId);\n this.startToolCall(\n event.toolCallId,\n event.toolCallName,\n event.parentMessageId,\n );\n this.emit();\n break;\n }\n case \"TOOL_CALL_ARGS\":\n case \"TOOL_CALL_CHUNK\": {\n if (event.type === \"TOOL_CALL_CHUNK\") {\n this.reportServerMessageId(event.parentMessageId);\n }\n if (!event.delta) break;\n this.appendToolArgs(event.toolCallId, event.delta);\n this.emit();\n break;\n }\n case \"TOOL_CALL_END\": {\n this.emit();\n break;\n }\n case \"TOOL_CALL_RESULT\": {\n this.finishToolCall(\n event.toolCallId,\n event.content ?? \"\",\n event.role === \"tool\" ? false : undefined,\n event.messageId,\n );\n this.emit();\n break;\n }\n case \"ACTIVITY_SNAPSHOT\": {\n if (event.activityType !== MCP_APPS_ACTIVITY_TYPE) break;\n const id = this.lastResolvedToolCallId;\n const entry = id ? this.toolCalls.get(id) : undefined;\n const resourceUri = event.content.resourceUri;\n if (\n entry &&\n typeof resourceUri === \"string\" &&\n isMcpAppUri(resourceUri)\n ) {\n entry.mcpAppResourceUri = resourceUri;\n this.emit();\n }\n break;\n }\n\n default: {\n this.logger.debug?.(\"[agui] aggregator ignored event\", event);\n }\n }\n }\n\n private reportServerMessageId(messageId: string | undefined): void {\n if (this.serverMessageIdReported || !messageId) return;\n this.serverMessageIdReported = true;\n this.onServerMessageId?.(messageId);\n }\n\n private clearTextParts(): void {\n this.textParts.clear();\n }\n\n private generateTextKey(): string {\n this.textPartCounter += 1;\n return `text-${this.textPartCounter}`;\n }\n\n private startTextMessage(messageId?: string): string {\n const id = messageId ?? this.generateTextKey();\n this.ensureTextPart(id);\n this.activeTextMessageId = id;\n return id;\n }\n\n private resolveTextMessageId(messageId?: string): string {\n if (messageId) {\n this.ensureTextPart(messageId);\n this.activeTextMessageId = messageId;\n return messageId;\n }\n\n if (this.activeTextMessageId) {\n return this.activeTextMessageId;\n }\n\n const generated = this.generateTextKey();\n this.ensureTextPart(generated);\n this.activeTextMessageId = generated;\n return generated;\n }\n\n private ensureTextPart(id: string): void {\n if (!this.textParts.has(id)) {\n this.textParts.set(id, { buffer: \"\", touched: false });\n if (\n !this.partOrder.some((part) => part.kind === \"text\" && part.key === id)\n ) {\n this.partOrder.push({ kind: \"text\", key: id });\n }\n }\n }\n\n private markTextPartTouched(id: string): void {\n const entry = this.textParts.get(id);\n if (!entry) return;\n entry.touched = true;\n }\n\n private appendText(id: string, delta: string): void {\n this.ensureTextPart(id);\n const entry = this.textParts.get(id);\n if (!entry) return;\n entry.buffer += delta;\n entry.touched = true;\n }\n\n private startToolCall(\n id: string | undefined,\n name?: string,\n parentMessageId?: string,\n ) {\n if (!id) return;\n // A new tool call acts as a boundary: any anonymous text that arrives\n // after it should be a new part, not appended to the pre-tool text.\n this.activeTextMessageId = undefined;\n if (\n !this.partOrder.some(\n (part) => part.kind === \"tool-call\" && part.toolCallId === id,\n )\n ) {\n this.partOrder.push({ kind: \"tool-call\", toolCallId: id });\n }\n const state: ToolCallState = {\n toolCallId: id,\n toolCallName: name ?? \"tool\",\n argsText: \"\",\n parsedArgs: undefined,\n result: undefined,\n isError: undefined,\n };\n if (parentMessageId) {\n state.parentMessageId = parentMessageId;\n }\n this.toolCalls.set(id, state);\n }\n\n private appendToolArgs(id: string | undefined, delta: string) {\n const entry = id ? this.toolCalls.get(id) : undefined;\n if (!entry) return;\n entry.argsText += delta;\n try {\n const parsed = JSON.parse(entry.argsText);\n if (parsed && typeof parsed === \"object\") {\n entry.parsedArgs = parsed as Record<string, unknown>;\n } else {\n entry.parsedArgs = undefined;\n }\n } catch {\n entry.parsedArgs = undefined;\n }\n }\n\n private finishToolCall(\n id: string,\n content: string,\n isError?: boolean,\n toolMessageId?: string,\n ) {\n if (!id) return;\n let entry = this.toolCalls.get(id);\n if (!entry) {\n entry = {\n toolCallId: id,\n toolCallName: \"tool\",\n argsText: \"\",\n parsedArgs: undefined,\n result: undefined,\n isError: undefined,\n };\n this.toolCalls.set(id, entry);\n }\n if (\n !this.partOrder.some(\n (part) => part.kind === \"tool-call\" && part.toolCallId === id,\n )\n ) {\n this.partOrder.push({ kind: \"tool-call\", toolCallId: id });\n }\n entry.result = tryParseJSON(content);\n entry.isError = isError;\n if (toolMessageId) {\n entry.toolMessageId = toolMessageId;\n }\n this.lastResolvedToolCallId = id;\n }\n\n private emit(): void {\n const snapshot: ThreadAssistantMessagePart[] = [];\n\n for (const part of this.partOrder) {\n if (part.kind === \"reasoning\") {\n if (this.showThinking) {\n const buffer = this.reasoningParts.get(part.key) ?? \"\";\n if (buffer.length > 0 || this.activeReasoningKey === part.key) {\n snapshot.push({ type: \"reasoning\", text: buffer } as const);\n }\n }\n continue;\n }\n\n if (part.kind === \"text\") {\n const entry = this.textParts.get(part.key);\n if (entry?.touched) {\n snapshot.push({ type: \"text\", text: entry.buffer } as const);\n }\n continue;\n }\n\n const entry = this.toolCalls.get(part.toolCallId);\n if (!entry) continue;\n const toolPart: ToolCallMessagePart = {\n type: \"tool-call\",\n toolCallId: entry.toolCallId,\n toolName: entry.toolCallName,\n args: (entry.parsedArgs ?? {}) as any,\n argsText: entry.argsText,\n ...(entry.result !== undefined ? { result: entry.result } : {}),\n ...(entry.isError !== undefined ? { isError: entry.isError } : {}),\n ...(entry.mcpAppResourceUri\n ? { mcp: { app: { resourceUri: entry.mcpAppResourceUri } } }\n : {}),\n ...(entry.parentMessageId ? { parentId: entry.parentMessageId } : {}),\n ...(entry.toolMessageId\n ? { unstable_toolMessageId: entry.toolMessageId }\n : {}),\n } as ToolCallMessagePart & { unstable_toolMessageId?: string };\n snapshot.push(toolPart);\n }\n\n const timing = this.getTiming();\n const metadata = {\n ...(timing ? { timing } : {}),\n ...(this.interrupts\n ? {\n custom: {\n [AG_UI_METADATA_NAMESPACE]: {\n interrupts: this.interrupts,\n } satisfies AgUiCustomMetadata,\n },\n }\n : {}),\n };\n const result: ChatModelRunResult = {\n content: snapshot,\n ...(this.status ? { status: this.status } : undefined),\n ...(Object.keys(metadata).length > 0 ? { metadata } : undefined),\n };\n this.emitUpdate(result);\n }\n\n private recordFirstToken(): void {\n if (\n this.firstTokenTime === undefined &&\n this.streamStartTime !== undefined\n ) {\n this.firstTokenTime = Date.now() - this.streamStartTime;\n }\n }\n\n private getTiming(): MessageTiming | undefined {\n if (this.streamStartTime === undefined) return undefined;\n\n const now = Date.now();\n const totalStreamTime = now - this.streamStartTime;\n const tokenCount =\n this.totalChunks > 0\n ? Math.ceil(\n Array.from(this.textParts.values()).reduce(\n (sum, p) => sum + p.buffer.length,\n 0,\n ) / 4,\n )\n : undefined;\n const tokensPerSecond =\n tokenCount && totalStreamTime > 0\n ? (tokenCount / totalStreamTime) * 1000\n : undefined;\n\n return {\n streamStartTime: this.streamStartTime,\n ...(this.firstTokenTime !== undefined\n ? { firstTokenTime: this.firstTokenTime }\n : {}),\n totalStreamTime,\n ...(tokenCount !== undefined ? { tokenCount } : {}),\n ...(tokensPerSecond !== undefined ? { tokensPerSecond } : {}),\n totalChunks: this.totalChunks,\n toolCallCount: this.toolCalls.size,\n };\n }\n\n private handleReasoningStart(messageId?: string): void {\n if (!this.showThinking) return;\n // A reasoning block acts as a boundary: anonymous text arriving after it\n // should be a new part, not appended to any pre-reasoning text.\n this.activeTextMessageId = undefined;\n const key = messageId ?? `__auto-reasoning-${++this.reasoningPartCounter}`;\n if (!this.reasoningParts.has(key)) {\n this.reasoningParts.set(key, \"\");\n this.partOrder.push({ kind: \"reasoning\", key });\n }\n this.activeReasoningKey = key;\n this.emit();\n }\n\n private handleReasoningContent(delta: string, messageId?: string): void {\n if (!this.showThinking || !delta) return;\n if (!this.activeReasoningKey) {\n // Content arrived without a preceding START — create the slot lazily.\n this.handleReasoningStart(messageId);\n }\n const key = this.activeReasoningKey;\n if (!key) return;\n this.reasoningParts.set(key, (this.reasoningParts.get(key) ?? \"\") + delta);\n this.emit();\n }\n\n private handleReasoningEnd(): void {\n if (!this.showThinking) return;\n this.activeReasoningKey = undefined;\n this.emit();\n }\n}\n\nexport function tryParseJSON(value: string): unknown {\n if (!value) return value;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"subscriber.d.ts","names":[],"sources":["../../../src/runtime/adapter/subscriber.ts"],"mappings":";;;;KAMK,QAAA,IAAY,KAAgB,EAAT,SAAS;AAAA,KAE5B,UAAA;EACH,OAAA,IAAW,OAAA;IAAW,KAAA;EAAA;EACtB,uBAAA,IAA2B,OAAA;IAAW,KAAA;EAAA;EACtC,yBAAA,IAA6B,OAAA;IAAW,KAAA;EAAA;EACxC,qBAAA,IAAyB,OAAA;IAAW,KAAA;EAAA;EACpC,uBAAA,IAA2B,OAAA;IAAW,KAAA;EAAA;EACtC,oBAAA,IAAwB,OAAA;IAAW,KAAA;EAAA;EACnC,kBAAA,IAAsB,OAAA;IAAW,KAAA;EAAA;EACjC,+BAAA,IAAmC,OAAA;IAAW,KAAA;EAAA;EAC9C,iCAAA,IAAqC,OAAA;IAAW,KAAA;EAAA;EAChD,6BAAA,IAAiC,OAAA;IAAW,KAAA;EAAA;EAC5C,qBAAA,IAAyB,OAAA;IAAW,KAAA;EAAA;EACpC,mBAAA,IAAuB,OAAA;IAAW,KAAA;EAAA;EAClC,4BAAA,IAAgC,OAAA;IAAW,KAAA;EAAA;EAC3C,8BAAA,IAAkC,OAAA;IAAW,KAAA;EAAA;EAC7C,0BAAA,IAA8B,OAAA;IAAW,KAAA;EAAA;EACzC,oBAAA,IAAwB,OAAA;IAAW,KAAA;EAAA;EACnC,mBAAA,IAAuB,OAAA;IAAW,KAAA;EAAA;EAClC,kBAAA,IAAsB,OAAA;IAAW,KAAA;EAAA;EACjC,oBAAA,IAAwB,OAAA;IAAW,KAAA;EAAA;EACnC,qBAAA,IAAyB,OAAA;IAAW,KAAA;EAAA;EACpC,uBAAA,IAA2B,OAAA;IAAW,KAAA;EAAA;EACtC,oBAAA,IAAwB,OAAA;IAAW,KAAA;EAAA;EACnC,iBAAA,IAAqB,OAAA;IAAW,KAAA;EAAA;EAChC,uBAAA,IAA2B,OAAA;IAAW,KAAA;EAAA;EACtC,aAAA,IAAiB,OAAA;IAAW,KAAA;EAAA;EAC5B,UAAA,IAAc,OAAA;IAAW,KAAA;EAAA;EACzB,kBAAA,IAAsB,OAAA;IAAW,KAAA;EAAA;EACjC,cAAA;EACA,WAAA,IAAe,OAAA;IAAW,KAAA,EAAO,KAAK;EAAA;AAAA;AAAA,KAuBnC,iBAAA;EACH,QAAA,EAAU,QAAA;EACV,KAAA;EACA,MAAA,GAAS,MAAA;EACT,WAAA,IAAe,KAAA,EAAO,KAAA;AAAA;AAAA,cAGX,oBAAA,GACX,OAAA,EAAS,iBAAA,KACR,UA0FF;AAAA,KAEW,cAAA,GAAiB,UAAU,QAAQ,oBAAA"}
1
+ {"version":3,"file":"subscriber.d.ts","names":[],"sources":["../../../src/runtime/adapter/subscriber.ts"],"mappings":";;;;KAMK,QAAA,IAAY,KAAgB,EAAT,SAAS;AAAA,KAE5B,UAAA;EACH,OAAA,IAAW,OAAA;IAAW,KAAA;EAAA;EACtB,uBAAA,IAA2B,OAAA;IAAW,KAAA;EAAA;EACtC,yBAAA,IAA6B,OAAA;IAAW,KAAA;EAAA;EACxC,qBAAA,IAAyB,OAAA;IAAW,KAAA;EAAA;EACpC,uBAAA,IAA2B,OAAA;IAAW,KAAA;EAAA;EACtC,oBAAA,IAAwB,OAAA;IAAW,KAAA;EAAA;EACnC,kBAAA,IAAsB,OAAA;IAAW,KAAA;EAAA;EACjC,+BAAA,IAAmC,OAAA;IAAW,KAAA;EAAA;EAC9C,iCAAA,IAAqC,OAAA;IAAW,KAAA;EAAA;EAChD,6BAAA,IAAiC,OAAA;IAAW,KAAA;EAAA;EAC5C,qBAAA,IAAyB,OAAA;IAAW,KAAA;EAAA;EACpC,mBAAA,IAAuB,OAAA;IAAW,KAAA;EAAA;EAClC,4BAAA,IAAgC,OAAA;IAAW,KAAA;EAAA;EAC3C,8BAAA,IAAkC,OAAA;IAAW,KAAA;EAAA;EAC7C,0BAAA,IAA8B,OAAA;IAAW,KAAA;EAAA;EACzC,oBAAA,IAAwB,OAAA;IAAW,KAAA;EAAA;EACnC,mBAAA,IAAuB,OAAA;IAAW,KAAA;EAAA;EAClC,kBAAA,IAAsB,OAAA;IAAW,KAAA;EAAA;EACjC,oBAAA,IAAwB,OAAA;IAAW,KAAA;EAAA;EACnC,qBAAA,IAAyB,OAAA;IAAW,KAAA;EAAA;EACpC,uBAAA,IAA2B,OAAA;IAAW,KAAA;EAAA;EACtC,oBAAA,IAAwB,OAAA;IAAW,KAAA;EAAA;EACnC,iBAAA,IAAqB,OAAA;IAAW,KAAA;EAAA;EAChC,uBAAA,IAA2B,OAAA;IAAW,KAAA;EAAA;EACtC,aAAA,IAAiB,OAAA;IAAW,KAAA;EAAA;EAC5B,UAAA,IAAc,OAAA;IAAW,KAAA;EAAA;EACzB,kBAAA,IAAsB,OAAA;IAAW,KAAA;EAAA;EACjC,cAAA;EACA,WAAA,IAAe,OAAA;IAAW,KAAA,EAAO,KAAK;EAAA;AAAA;AAAA,KAiCnC,iBAAA;EACH,QAAA,EAAU,QAAA;EACV,KAAA;EACA,MAAA,GAAS,MAAA;EACT,WAAA,IAAe,KAAA,EAAO,KAAA;AAAA;AAAA,cAGX,oBAAA,GACX,OAAA,EAAS,iBAAA,KACR,UA+FF;AAAA,KAEW,cAAA,GAAiB,UAAU,QAAQ,oBAAA"}
@@ -1,6 +1,11 @@
1
1
  "use client";
2
2
  import { parseAgUiEvent } from "../event-parser.js";
3
3
  //#region src/runtime/adapter/subscriber.ts
4
+ const isAbortError = (error) => {
5
+ if (error.name === "AbortError") return true;
6
+ const message = typeof error.message === "string" ? error.message : "";
7
+ return message === "Fetch is aborted" || message === "signal is aborted without reason" || message === "component unmounted";
8
+ };
4
9
  const ensureEvent = (raw, type, logger) => {
5
10
  const parseOptions = logger ? { logger } : void 0;
6
11
  let parsed;
@@ -67,7 +72,12 @@ const createAgUiSubscriber = (options) => {
67
72
  });
68
73
  },
69
74
  onRunFailed: ({ error }) => {
75
+ runFinishedDispatched = true;
70
76
  onRunFailed?.(error);
77
+ if (isAbortError(error)) {
78
+ dispatch({ type: "RUN_CANCELLED" });
79
+ return;
80
+ }
71
81
  const message = typeof error.message === "string" ? error.message : "Run failed";
72
82
  const code = typeof error?.code === "string" ? error.code : void 0;
73
83
  dispatch({
@@ -1 +1 @@
1
- {"version":3,"file":"subscriber.js","names":[],"sources":["../../../src/runtime/adapter/subscriber.ts"],"sourcesContent":["\"use client\";\n\nimport type { AgUiEvent } from \"../types\";\nimport { parseAgUiEvent } from \"../event-parser\";\nimport type { Logger } from \"../logger\";\n\ntype Dispatch = (event: AgUiEvent) => void;\n\ntype Subscriber = {\n onEvent?: (payload: { event: unknown }) => void;\n onTextMessageStartEvent?: (payload: { event: unknown }) => void;\n onTextMessageContentEvent?: (payload: { event: unknown }) => void;\n onTextMessageEndEvent?: (payload: { event: unknown }) => void;\n onTextMessageChunkEvent?: (payload: { event: unknown }) => void;\n onThinkingStartEvent?: (payload: { event: unknown }) => void;\n onThinkingEndEvent?: (payload: { event: unknown }) => void;\n onThinkingTextMessageStartEvent?: (payload: { event: unknown }) => void;\n onThinkingTextMessageContentEvent?: (payload: { event: unknown }) => void;\n onThinkingTextMessageEndEvent?: (payload: { event: unknown }) => void;\n onReasoningStartEvent?: (payload: { event: unknown }) => void;\n onReasoningEndEvent?: (payload: { event: unknown }) => void;\n onReasoningMessageStartEvent?: (payload: { event: unknown }) => void;\n onReasoningMessageContentEvent?: (payload: { event: unknown }) => void;\n onReasoningMessageEndEvent?: (payload: { event: unknown }) => void;\n onToolCallStartEvent?: (payload: { event: unknown }) => void;\n onToolCallArgsEvent?: (payload: { event: unknown }) => void;\n onToolCallEndEvent?: (payload: { event: unknown }) => void;\n onToolCallChunkEvent?: (payload: { event: unknown }) => void;\n onToolCallResultEvent?: (payload: { event: unknown }) => void;\n onActivitySnapshotEvent?: (payload: { event: unknown }) => void;\n onStateSnapshotEvent?: (payload: { event: unknown }) => void;\n onStateDeltaEvent?: (payload: { event: unknown }) => void;\n onMessagesSnapshotEvent?: (payload: { event: unknown }) => void;\n onCustomEvent?: (payload: { event: unknown }) => void;\n onRawEvent?: (payload: { event: unknown }) => void;\n onRunFinishedEvent?: (payload: { event: unknown }) => void;\n onRunFinalized?: () => void;\n onRunFailed?: (payload: { error: Error }) => void;\n};\n\nconst ensureEvent = (\n raw: unknown,\n type: AgUiEvent[\"type\"],\n logger?: Logger,\n): AgUiEvent | null => {\n const parseOptions = logger ? { logger } : undefined;\n let parsed: AgUiEvent | null;\n if (raw && typeof raw === \"object\") {\n const payload = raw as Record<string, unknown>;\n if (typeof payload.type === \"string\") {\n parsed = parseAgUiEvent(payload, parseOptions);\n } else {\n parsed = parseAgUiEvent({ type, ...payload }, parseOptions);\n }\n } else {\n parsed = parseAgUiEvent({ type }, parseOptions);\n }\n return parsed && parsed.type === type ? parsed : null;\n};\n\ntype SubscriberOptions = {\n dispatch: Dispatch;\n runId: string;\n logger?: Logger;\n onRunFailed?: (error: Error) => void;\n};\n\nexport const createAgUiSubscriber = (\n options: SubscriberOptions,\n): Subscriber => {\n const { dispatch, runId, logger, onRunFailed } = options;\n let runFinishedDispatched = false;\n const dispatchIfValid = (raw: unknown, type: AgUiEvent[\"type\"]) => {\n const event = ensureEvent(raw, type, logger);\n if (!event) return;\n dispatch(event);\n };\n return {\n onEvent: ({ event }) => {\n const typeCandidate =\n event && typeof event === \"object\"\n ? (event as Record<string, unknown>).type\n : undefined;\n if (typeof typeCandidate === \"string\") {\n // Typed handlers will receive this via the discriminated callbacks; avoid duplicates.\n return;\n }\n const parsed = parseAgUiEvent(event);\n if (parsed) dispatch(parsed);\n },\n onTextMessageStartEvent: ({ event }) =>\n dispatchIfValid(event, \"TEXT_MESSAGE_START\"),\n onTextMessageContentEvent: ({ event }) =>\n dispatchIfValid(event, \"TEXT_MESSAGE_CONTENT\"),\n onTextMessageEndEvent: ({ event }) =>\n dispatchIfValid(event, \"TEXT_MESSAGE_END\"),\n onTextMessageChunkEvent: ({ event }) =>\n dispatchIfValid(event, \"TEXT_MESSAGE_CHUNK\"),\n onThinkingStartEvent: ({ event }) =>\n dispatchIfValid(event, \"THINKING_START\"),\n onThinkingEndEvent: ({ event }) => dispatchIfValid(event, \"THINKING_END\"),\n onThinkingTextMessageStartEvent: ({ event }) =>\n dispatchIfValid(event, \"THINKING_TEXT_MESSAGE_START\"),\n onThinkingTextMessageContentEvent: ({ event }) =>\n dispatchIfValid(event, \"THINKING_TEXT_MESSAGE_CONTENT\"),\n onThinkingTextMessageEndEvent: ({ event }) =>\n dispatchIfValid(event, \"THINKING_TEXT_MESSAGE_END\"),\n onReasoningStartEvent: ({ event }) =>\n dispatchIfValid(event, \"REASONING_START\"),\n onReasoningEndEvent: ({ event }) => dispatchIfValid(event, \"REASONING_END\"),\n onReasoningMessageStartEvent: ({ event }) =>\n dispatchIfValid(event, \"REASONING_MESSAGE_START\"),\n onReasoningMessageContentEvent: ({ event }) =>\n dispatchIfValid(event, \"REASONING_MESSAGE_CONTENT\"),\n onReasoningMessageEndEvent: ({ event }) =>\n dispatchIfValid(event, \"REASONING_MESSAGE_END\"),\n onToolCallStartEvent: ({ event }) =>\n dispatchIfValid(event, \"TOOL_CALL_START\"),\n onToolCallArgsEvent: ({ event }) =>\n dispatchIfValid(event, \"TOOL_CALL_ARGS\"),\n onToolCallEndEvent: ({ event }) => dispatchIfValid(event, \"TOOL_CALL_END\"),\n onToolCallChunkEvent: ({ event }) =>\n dispatchIfValid(event, \"TOOL_CALL_CHUNK\"),\n onToolCallResultEvent: ({ event }) =>\n dispatchIfValid(event, \"TOOL_CALL_RESULT\"),\n onActivitySnapshotEvent: ({ event }) =>\n dispatchIfValid(event, \"ACTIVITY_SNAPSHOT\"),\n onStateSnapshotEvent: ({ event }) =>\n dispatchIfValid(event, \"STATE_SNAPSHOT\"),\n onStateDeltaEvent: ({ event }) => dispatchIfValid(event, \"STATE_DELTA\"),\n onMessagesSnapshotEvent: ({ event }) =>\n dispatchIfValid(event, \"MESSAGES_SNAPSHOT\"),\n onCustomEvent: ({ event }) => dispatchIfValid(event, \"CUSTOM\"),\n onRawEvent: ({ event }) => dispatchIfValid(event, \"RAW\"),\n onRunFinishedEvent: ({ event }) => {\n const parsed = ensureEvent(event, \"RUN_FINISHED\", logger);\n if (!parsed) return;\n runFinishedDispatched = true;\n dispatch(parsed);\n },\n onRunFinalized: () => {\n if (runFinishedDispatched) return;\n dispatch({ type: \"RUN_FINISHED\", runId });\n },\n onRunFailed: ({ error }) => {\n onRunFailed?.(error);\n const message =\n typeof error.message === \"string\" ? error.message : \"Run failed\";\n const code =\n typeof (error as any)?.code === \"string\"\n ? (error as any).code\n : undefined;\n dispatch({\n type: \"RUN_ERROR\" as const,\n ...(message !== undefined ? { message } : {}),\n ...(code !== undefined ? { code } : {}),\n } satisfies AgUiEvent);\n },\n };\n};\n\nexport type AgUiSubscriber = ReturnType<typeof createAgUiSubscriber>;\n"],"mappings":";;;AAwCA,MAAM,eACJ,KACA,MACA,WACqB;CACrB,MAAM,eAAe,SAAS,EAAE,OAAO,IAAI,KAAA;CAC3C,IAAI;CACJ,IAAI,OAAO,OAAO,QAAQ,UAAU;EAClC,MAAM,UAAU;EAChB,IAAI,OAAO,QAAQ,SAAS,UAC1B,SAAS,eAAe,SAAS,YAAY;OAE7C,SAAS,eAAe;GAAE;GAAM,GAAG;EAAQ,GAAG,YAAY;CAE9D,OACE,SAAS,eAAe,EAAE,KAAK,GAAG,YAAY;CAEhD,OAAO,UAAU,OAAO,SAAS,OAAO,SAAS;AACnD;AASA,MAAa,wBACX,YACe;CACf,MAAM,EAAE,UAAU,OAAO,QAAQ,gBAAgB;CACjD,IAAI,wBAAwB;CAC5B,MAAM,mBAAmB,KAAc,SAA4B;EACjE,MAAM,QAAQ,YAAY,KAAK,MAAM,MAAM;EAC3C,IAAI,CAAC,OAAO;EACZ,SAAS,KAAK;CAChB;CACA,OAAO;EACL,UAAU,EAAE,YAAY;GAKtB,IAAI,QAHF,SAAS,OAAO,UAAU,WACrB,MAAkC,OACnC,KAAA,OACuB,UAE3B;GAEF,MAAM,SAAS,eAAe,KAAK;GACnC,IAAI,QAAQ,SAAS,MAAM;EAC7B;EACA,0BAA0B,EAAE,YAC1B,gBAAgB,OAAO,oBAAoB;EAC7C,4BAA4B,EAAE,YAC5B,gBAAgB,OAAO,sBAAsB;EAC/C,wBAAwB,EAAE,YACxB,gBAAgB,OAAO,kBAAkB;EAC3C,0BAA0B,EAAE,YAC1B,gBAAgB,OAAO,oBAAoB;EAC7C,uBAAuB,EAAE,YACvB,gBAAgB,OAAO,gBAAgB;EACzC,qBAAqB,EAAE,YAAY,gBAAgB,OAAO,cAAc;EACxE,kCAAkC,EAAE,YAClC,gBAAgB,OAAO,6BAA6B;EACtD,oCAAoC,EAAE,YACpC,gBAAgB,OAAO,+BAA+B;EACxD,gCAAgC,EAAE,YAChC,gBAAgB,OAAO,2BAA2B;EACpD,wBAAwB,EAAE,YACxB,gBAAgB,OAAO,iBAAiB;EAC1C,sBAAsB,EAAE,YAAY,gBAAgB,OAAO,eAAe;EAC1E,+BAA+B,EAAE,YAC/B,gBAAgB,OAAO,yBAAyB;EAClD,iCAAiC,EAAE,YACjC,gBAAgB,OAAO,2BAA2B;EACpD,6BAA6B,EAAE,YAC7B,gBAAgB,OAAO,uBAAuB;EAChD,uBAAuB,EAAE,YACvB,gBAAgB,OAAO,iBAAiB;EAC1C,sBAAsB,EAAE,YACtB,gBAAgB,OAAO,gBAAgB;EACzC,qBAAqB,EAAE,YAAY,gBAAgB,OAAO,eAAe;EACzE,uBAAuB,EAAE,YACvB,gBAAgB,OAAO,iBAAiB;EAC1C,wBAAwB,EAAE,YACxB,gBAAgB,OAAO,kBAAkB;EAC3C,0BAA0B,EAAE,YAC1B,gBAAgB,OAAO,mBAAmB;EAC5C,uBAAuB,EAAE,YACvB,gBAAgB,OAAO,gBAAgB;EACzC,oBAAoB,EAAE,YAAY,gBAAgB,OAAO,aAAa;EACtE,0BAA0B,EAAE,YAC1B,gBAAgB,OAAO,mBAAmB;EAC5C,gBAAgB,EAAE,YAAY,gBAAgB,OAAO,QAAQ;EAC7D,aAAa,EAAE,YAAY,gBAAgB,OAAO,KAAK;EACvD,qBAAqB,EAAE,YAAY;GACjC,MAAM,SAAS,YAAY,OAAO,gBAAgB,MAAM;GACxD,IAAI,CAAC,QAAQ;GACb,wBAAwB;GACxB,SAAS,MAAM;EACjB;EACA,sBAAsB;GACpB,IAAI,uBAAuB;GAC3B,SAAS;IAAE,MAAM;IAAgB;GAAM,CAAC;EAC1C;EACA,cAAc,EAAE,YAAY;GAC1B,cAAc,KAAK;GACnB,MAAM,UACJ,OAAO,MAAM,YAAY,WAAW,MAAM,UAAU;GACtD,MAAM,OACJ,OAAQ,OAAe,SAAS,WAC3B,MAAc,OACf,KAAA;GACN,SAAS;IACP,MAAM;IACN,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;IAC3C,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;GACvC,CAAqB;EACvB;CACF;AACF"}
1
+ {"version":3,"file":"subscriber.js","names":[],"sources":["../../../src/runtime/adapter/subscriber.ts"],"sourcesContent":["\"use client\";\n\nimport type { AgUiEvent } from \"../types\";\nimport { parseAgUiEvent } from \"../event-parser\";\nimport type { Logger } from \"../logger\";\n\ntype Dispatch = (event: AgUiEvent) => void;\n\ntype Subscriber = {\n onEvent?: (payload: { event: unknown }) => void;\n onTextMessageStartEvent?: (payload: { event: unknown }) => void;\n onTextMessageContentEvent?: (payload: { event: unknown }) => void;\n onTextMessageEndEvent?: (payload: { event: unknown }) => void;\n onTextMessageChunkEvent?: (payload: { event: unknown }) => void;\n onThinkingStartEvent?: (payload: { event: unknown }) => void;\n onThinkingEndEvent?: (payload: { event: unknown }) => void;\n onThinkingTextMessageStartEvent?: (payload: { event: unknown }) => void;\n onThinkingTextMessageContentEvent?: (payload: { event: unknown }) => void;\n onThinkingTextMessageEndEvent?: (payload: { event: unknown }) => void;\n onReasoningStartEvent?: (payload: { event: unknown }) => void;\n onReasoningEndEvent?: (payload: { event: unknown }) => void;\n onReasoningMessageStartEvent?: (payload: { event: unknown }) => void;\n onReasoningMessageContentEvent?: (payload: { event: unknown }) => void;\n onReasoningMessageEndEvent?: (payload: { event: unknown }) => void;\n onToolCallStartEvent?: (payload: { event: unknown }) => void;\n onToolCallArgsEvent?: (payload: { event: unknown }) => void;\n onToolCallEndEvent?: (payload: { event: unknown }) => void;\n onToolCallChunkEvent?: (payload: { event: unknown }) => void;\n onToolCallResultEvent?: (payload: { event: unknown }) => void;\n onActivitySnapshotEvent?: (payload: { event: unknown }) => void;\n onStateSnapshotEvent?: (payload: { event: unknown }) => void;\n onStateDeltaEvent?: (payload: { event: unknown }) => void;\n onMessagesSnapshotEvent?: (payload: { event: unknown }) => void;\n onCustomEvent?: (payload: { event: unknown }) => void;\n onRawEvent?: (payload: { event: unknown }) => void;\n onRunFinishedEvent?: (payload: { event: unknown }) => void;\n onRunFinalized?: () => void;\n onRunFailed?: (payload: { error: Error }) => void;\n};\n\nconst isAbortError = (error: Error): boolean => {\n if (error.name === \"AbortError\") return true;\n const message = typeof error.message === \"string\" ? error.message : \"\";\n return (\n message === \"Fetch is aborted\" ||\n message === \"signal is aborted without reason\" ||\n message === \"component unmounted\"\n );\n};\n\nconst ensureEvent = (\n raw: unknown,\n type: AgUiEvent[\"type\"],\n logger?: Logger,\n): AgUiEvent | null => {\n const parseOptions = logger ? { logger } : undefined;\n let parsed: AgUiEvent | null;\n if (raw && typeof raw === \"object\") {\n const payload = raw as Record<string, unknown>;\n if (typeof payload.type === \"string\") {\n parsed = parseAgUiEvent(payload, parseOptions);\n } else {\n parsed = parseAgUiEvent({ type, ...payload }, parseOptions);\n }\n } else {\n parsed = parseAgUiEvent({ type }, parseOptions);\n }\n return parsed && parsed.type === type ? parsed : null;\n};\n\ntype SubscriberOptions = {\n dispatch: Dispatch;\n runId: string;\n logger?: Logger;\n onRunFailed?: (error: Error) => void;\n};\n\nexport const createAgUiSubscriber = (\n options: SubscriberOptions,\n): Subscriber => {\n const { dispatch, runId, logger, onRunFailed } = options;\n let runFinishedDispatched = false;\n const dispatchIfValid = (raw: unknown, type: AgUiEvent[\"type\"]) => {\n const event = ensureEvent(raw, type, logger);\n if (!event) return;\n dispatch(event);\n };\n return {\n onEvent: ({ event }) => {\n const typeCandidate =\n event && typeof event === \"object\"\n ? (event as Record<string, unknown>).type\n : undefined;\n if (typeof typeCandidate === \"string\") {\n // Typed handlers will receive this via the discriminated callbacks; avoid duplicates.\n return;\n }\n const parsed = parseAgUiEvent(event);\n if (parsed) dispatch(parsed);\n },\n onTextMessageStartEvent: ({ event }) =>\n dispatchIfValid(event, \"TEXT_MESSAGE_START\"),\n onTextMessageContentEvent: ({ event }) =>\n dispatchIfValid(event, \"TEXT_MESSAGE_CONTENT\"),\n onTextMessageEndEvent: ({ event }) =>\n dispatchIfValid(event, \"TEXT_MESSAGE_END\"),\n onTextMessageChunkEvent: ({ event }) =>\n dispatchIfValid(event, \"TEXT_MESSAGE_CHUNK\"),\n onThinkingStartEvent: ({ event }) =>\n dispatchIfValid(event, \"THINKING_START\"),\n onThinkingEndEvent: ({ event }) => dispatchIfValid(event, \"THINKING_END\"),\n onThinkingTextMessageStartEvent: ({ event }) =>\n dispatchIfValid(event, \"THINKING_TEXT_MESSAGE_START\"),\n onThinkingTextMessageContentEvent: ({ event }) =>\n dispatchIfValid(event, \"THINKING_TEXT_MESSAGE_CONTENT\"),\n onThinkingTextMessageEndEvent: ({ event }) =>\n dispatchIfValid(event, \"THINKING_TEXT_MESSAGE_END\"),\n onReasoningStartEvent: ({ event }) =>\n dispatchIfValid(event, \"REASONING_START\"),\n onReasoningEndEvent: ({ event }) => dispatchIfValid(event, \"REASONING_END\"),\n onReasoningMessageStartEvent: ({ event }) =>\n dispatchIfValid(event, \"REASONING_MESSAGE_START\"),\n onReasoningMessageContentEvent: ({ event }) =>\n dispatchIfValid(event, \"REASONING_MESSAGE_CONTENT\"),\n onReasoningMessageEndEvent: ({ event }) =>\n dispatchIfValid(event, \"REASONING_MESSAGE_END\"),\n onToolCallStartEvent: ({ event }) =>\n dispatchIfValid(event, \"TOOL_CALL_START\"),\n onToolCallArgsEvent: ({ event }) =>\n dispatchIfValid(event, \"TOOL_CALL_ARGS\"),\n onToolCallEndEvent: ({ event }) => dispatchIfValid(event, \"TOOL_CALL_END\"),\n onToolCallChunkEvent: ({ event }) =>\n dispatchIfValid(event, \"TOOL_CALL_CHUNK\"),\n onToolCallResultEvent: ({ event }) =>\n dispatchIfValid(event, \"TOOL_CALL_RESULT\"),\n onActivitySnapshotEvent: ({ event }) =>\n dispatchIfValid(event, \"ACTIVITY_SNAPSHOT\"),\n onStateSnapshotEvent: ({ event }) =>\n dispatchIfValid(event, \"STATE_SNAPSHOT\"),\n onStateDeltaEvent: ({ event }) => dispatchIfValid(event, \"STATE_DELTA\"),\n onMessagesSnapshotEvent: ({ event }) =>\n dispatchIfValid(event, \"MESSAGES_SNAPSHOT\"),\n onCustomEvent: ({ event }) => dispatchIfValid(event, \"CUSTOM\"),\n onRawEvent: ({ event }) => dispatchIfValid(event, \"RAW\"),\n onRunFinishedEvent: ({ event }) => {\n const parsed = ensureEvent(event, \"RUN_FINISHED\", logger);\n if (!parsed) return;\n runFinishedDispatched = true;\n dispatch(parsed);\n },\n onRunFinalized: () => {\n if (runFinishedDispatched) return;\n dispatch({ type: \"RUN_FINISHED\", runId });\n },\n onRunFailed: ({ error }) => {\n runFinishedDispatched = true;\n onRunFailed?.(error);\n if (isAbortError(error)) {\n dispatch({ type: \"RUN_CANCELLED\" } satisfies AgUiEvent);\n return;\n }\n const message =\n typeof error.message === \"string\" ? error.message : \"Run failed\";\n const code =\n typeof (error as any)?.code === \"string\"\n ? (error as any).code\n : undefined;\n dispatch({\n type: \"RUN_ERROR\" as const,\n ...(message !== undefined ? { message } : {}),\n ...(code !== undefined ? { code } : {}),\n } satisfies AgUiEvent);\n },\n };\n};\n\nexport type AgUiSubscriber = ReturnType<typeof createAgUiSubscriber>;\n"],"mappings":"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"}
@@ -1,22 +1,27 @@
1
1
  import { Logger } from "./logger.js";
2
- import { AttachmentAdapter, DictationAdapter, ExternalStoreSharedOptions, FeedbackAdapter, RealtimeVoiceAdapter, SpeechSynthesisAdapter, ThreadHistoryAdapter, ThreadMessage } from "@assistant-ui/core";
3
- import { HttpAgent } from "@ag-ui/client";
2
+ import { AttachmentAdapter, DictationAdapter, ExternalStoreSharedOptions, ExternalStoreThreadListAdapter, FeedbackAdapter, RealtimeVoiceAdapter, SpeechSynthesisAdapter, ThreadHistoryAdapter, ThreadMessage } from "@assistant-ui/core";
3
+ import { AbstractAgent } from "@ag-ui/client";
4
4
  import { ReadonlyJSONValue } from "assistant-stream/utils";
5
5
 
6
6
  //#region src/runtime/types.d.ts
7
7
  /**
8
8
  * @experimental This API is still under active development and might change without notice.
9
+ *
10
+ * Same as ExternalStoreThreadListAdapter, except `onSwitchToThread` returns
11
+ * the messages (and optional state) to hydrate the thread with.
9
12
  */
10
- type UseAgUiThreadListAdapter = {
11
- threadId?: string | undefined;
12
- onSwitchToNewThread?: (() => Promise<void> | void) | undefined;
13
- onSwitchToThread?: ((threadId: string) => Promise<{
14
- messages: readonly ThreadMessage[];
15
- state?: ReadonlyJSONValue;
16
- }> | {
17
- messages: readonly ThreadMessage[];
18
- state?: ReadonlyJSONValue;
19
- }) | undefined;
13
+ type SwitchToThreadResult = {
14
+ messages: readonly ThreadMessage[];
15
+ state?: ReadonlyJSONValue;
16
+ /**
17
+ * Set when the thread has a run in flight. The runtime resumes the run
18
+ * after hydrating, the same way `ThreadHistoryAdapter.load()` does when it
19
+ * returns `unstable_resume: true`.
20
+ */
21
+ unstable_resume?: boolean;
22
+ };
23
+ type UseAgUiThreadListAdapter = Omit<ExternalStoreThreadListAdapter, "onSwitchToThread"> & {
24
+ onSwitchToThread?: ((threadId: string) => Promise<SwitchToThreadResult> | SwitchToThreadResult) | undefined;
20
25
  };
21
26
  type UseAgUiRuntimeAdapters = {
22
27
  attachments?: AttachmentAdapter;
@@ -31,7 +36,7 @@ type UseAgUiRuntimeAdapters = {
31
36
  threadList?: UseAgUiThreadListAdapter;
32
37
  };
33
38
  type UseAgUiRuntimeOptions = ExternalStoreSharedOptions & {
34
- agent: HttpAgent;
39
+ agent: AbstractAgent;
35
40
  logger?: Partial<Logger>;
36
41
  showThinking?: boolean;
37
42
  onError?: (e: Error) => void;
@@ -1 +1 @@
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,sBAAA;AAAA;EAEV,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;EAGA,IAAA;EACA,YAAA;EACA,OAAA,EAAS,MAAM;AAAA;EAEf,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":";;;;;;;;AAagE;;;;KAQ3D,oBAAA;EACH,QAAA,WAAmB,aAAA;EACnB,KAAA,GAAQ,iBAAiB;EAAjB;;;AAMO;AAGjB;EAHE,eAAA;AAAA;AAAA,KAGU,wBAAA,GAA2B,IAAA,CACrC,8BAAA;EAGA,gBAAA,KAEM,QAAA,aACG,OAAA,CAAQ,oBAAA,IAAwB,oBAAA;AAAA;AAAA,KAI/B,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;EAXJ;;;EAeN,UAAA,GAAa,wBAAA;AAAA;AAAA,KAGH,qBAAA,GAAwB,0BAAA;EAClC,KAAA,EAAO,aAAA;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,sBAAA;AAAA;EAEV,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;EAGA,IAAA;EACA,YAAA;EACA,OAAA,EAAS,MAAM;AAAA;EAEf,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"}
@@ -34,17 +34,19 @@ function useAgUiRuntime(options) {
34
34
  const hasExecutingTools = Object.values(toolStatuses).some((s) => s?.type === "executing");
35
35
  const threadList = useMemo(() => {
36
36
  if (!threadListAdapter) return void 0;
37
- const { onSwitchToNewThread, onSwitchToThread } = threadListAdapter;
37
+ const { onSwitchToNewThread, onSwitchToThread, ...rest } = threadListAdapter;
38
38
  return {
39
- threadId: threadListAdapter.threadId,
39
+ ...rest,
40
40
  onSwitchToNewThread: onSwitchToNewThread ? async () => {
41
41
  await onSwitchToNewThread();
42
42
  core.applyExternalMessages([]);
43
43
  } : void 0,
44
44
  onSwitchToThread: onSwitchToThread ? async (threadId) => {
45
+ core.applyExternalMessages([]);
45
46
  const result = await onSwitchToThread(threadId);
46
47
  core.applyExternalMessages(result.messages);
47
48
  if (result.state) core.loadExternalState(result.state);
49
+ if (result.unstable_resume) core.resumeInFlightRun(result.messages);
48
50
  } : void 0
49
51
  };
50
52
  }, [threadListAdapter, core]);
@@ -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 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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"}
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, ...rest } =\n threadListAdapter;\n\n return {\n ...rest,\n onSwitchToNewThread: onSwitchToNewThread\n ? async () => {\n await onSwitchToNewThread();\n core.applyExternalMessages([]);\n }\n : undefined,\n onSwitchToThread: onSwitchToThread\n ? async (threadId: string) => {\n // Clear before the thread id flips, or the old messages leak\n // into the new thread as a sibling branch.\n core.applyExternalMessages([]);\n const result = await onSwitchToThread(threadId);\n core.applyExternalMessages(result.messages);\n if (result.state) {\n core.loadExternalState(result.state);\n }\n if (result.unstable_resume) {\n void core.resumeInFlightRun(result.messages);\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.36",
3
+ "version": "0.0.39",
4
4
  "description": "AG-UI protocol adapter for assistant-ui",
5
5
  "keywords": [
6
6
  "ag-ui",
@@ -30,8 +30,8 @@
30
30
  "sideEffects": false,
31
31
  "dependencies": {
32
32
  "@ag-ui/client": "^0.0.55",
33
- "@assistant-ui/core": "^0.2.11",
34
- "assistant-stream": "^0.3.21",
33
+ "@assistant-ui/core": "^0.2.15",
34
+ "assistant-stream": "^0.3.22",
35
35
  "fast-json-patch": "^3.1.1"
36
36
  },
37
37
  "peerDependencies": {
@@ -48,7 +48,7 @@
48
48
  "react": "^19.2.7",
49
49
  "vitest": "^4.1.8",
50
50
  "zod": "^4.4.3",
51
- "@assistant-ui/x-buildutils": "0.0.12"
51
+ "@assistant-ui/x-buildutils": "0.0.13"
52
52
  },
53
53
  "publishConfig": {
54
54
  "access": "public",