@assistant-ui/ai-sdk 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/converters/convertMessage.d.ts.map +1 -1
- package/dist/converters/convertMessage.js +1 -0
- package/dist/converters/convertMessage.js.map +1 -1
- package/dist/converters/toCreateMessage.d.ts.map +1 -1
- package/dist/converters/toCreateMessage.js +2 -1
- package/dist/converters/toCreateMessage.js.map +1 -1
- package/dist/runtime/AISDKChat.js.map +1 -1
- package/dist/runtime/AISDKThreads.js.map +1 -1
- package/dist/runtime/sdkIdentity.js +1 -1
- package/dist/runtime/useAISDKRuntime.js.map +1 -1
- package/dist/runtime/useChatRuntime.js.map +1 -1
- package/dist/runtime/useResourceCleanup.js.map +1 -1
- package/dist/runtime/useStreamingTiming.js.map +1 -1
- package/dist/transport/resumable.js.map +1 -1
- package/dist/usage.js.map +1 -1
- package/package.json +11 -11
- package/src/converters/convertMessage.test.ts +36 -0
- package/src/converters/convertMessage.ts +3 -0
- package/src/converters/toCreateMessage.test.ts +13 -0
- package/src/converters/toCreateMessage.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertMessage.d.ts","sourceRoot":"","sources":["../../src/converters/convertMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,IAAI,CAAC;AACZ,OAAO,EAEL,KAAK,2BAA2B,EACjC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAYL,KAAK,cAAc,EAEnB,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EACjC,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,wBAAwB,CAAC;AA6BhC,MAAM,MAAM,6BAA6B,GACvC,2BAA2B,CAAC,QAAQ,GAAG;IACrC,qBAAqB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC3D;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACrE,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACrD,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAClD,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,gBAAgB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IACpE,iCAAiC,CAAC,EAAE,OAAO,CAAC;IAC5C,qBAAqB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAC;IAC1E,wBAAwB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/C,yBAAyB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChD,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C,CAAC;
|
|
1
|
+
{"version":3,"file":"convertMessage.d.ts","sourceRoot":"","sources":["../../src/converters/convertMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,IAAI,CAAC;AACZ,OAAO,EAEL,KAAK,2BAA2B,EACjC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAYL,KAAK,cAAc,EAEnB,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EACjC,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,wBAAwB,CAAC;AA6BhC,MAAM,MAAM,6BAA6B,GACvC,2BAA2B,CAAC,QAAQ,GAAG;IACrC,qBAAqB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAC3D;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACrE,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACrD,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAClD,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,gBAAgB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IACpE,iCAAiC,CAAC,EAAE,OAAO,CAAC;IAC5C,qBAAqB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAC;IAC1E,wBAAwB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/C,yBAAyB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChD,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C,CAAC;AAgiBJ,eAAO,MAAM,qBAAqB;;;;;;;;+HAplBX,qDACD;8HAE+B,qDAE7C;;;CA0pBP,CAAC"}
|
|
@@ -267,6 +267,7 @@ function convertParts(message, metadata) {
|
|
|
267
267
|
};
|
|
268
268
|
if (part.type.startsWith("data-")) return {
|
|
269
269
|
type: "data",
|
|
270
|
+
..."id" in part && typeof part.id === "string" ? { id: part.id } : void 0,
|
|
270
271
|
name: part.type.substring(5),
|
|
271
272
|
data: part.data
|
|
272
273
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertMessage.js","names":["isToolUIPart","isReasoningFileUIPart","isCustomContentUIPart","getToolName","UIMessage","createMessageConverter","unstable_createMessageConverter","useExternalMessageConverter","isMcpAppUri","ReasoningMessagePart","ToolApprovalOption","ToolCallMessagePart","TextMessagePart","DataMessagePart","PartProviderMetadata","SourceMessagePart","SourceProviderMetadata","FileMessagePart","ThreadMessageLike","McpAppMetadata","MessagePartStreamStatus","RespondToToolApprovalOptions","Unstable_ToolInteractionLog","stableStringifyToolArgs","parsePartialJsonObject","ReadonlyJSONObject","unwrapModelContentEnvelope","MessageMetadata","THREAD_METADATA_KEYS","Set","toThreadMetadata","metadata","undefined","result","Record","extra","Object","create","key","value","entries","has","keys","length","custom","AISDKMessageConverterMetadata","Metadata","toolArgsKeyOrderCache","Map","toolArgsTextCache","WeakMap","toolLastInputCache","mcpAppMetadataCache","toolArtifacts","ReadonlyMap","toolInteractions","supportsRichToolApprovalResponses","toolApprovalResponses","cancelledToolApprovalIds","ReadonlySet","cancelledStatusMessageIds","optimisticMessageId","stripClosingDelimiters","json","end","includes","slice","MCP_APP_METADATA_CACHE_MAX","extractMcpAppMetadata","part","cache","meta","callProviderMetadata","mcp","app","a","output","outMeta","_meta","ui","uiMeta","resourceUri","Array","isArray","visibility","flat","cacheKey","cached","get","delete","set","out","K","mimeType","filter","v","serverId","size","oldest","next","normalizeToolApprovalOptions","options","flatMap","option","id","kind","confirm","confirmDetails","label","description","grants","grant","title","APPROVAL_DESCRIPTOR_FIELDS","const","readApprovalDescriptor","descriptor","fields","hasOwn","getToolApprovalAndInterrupt","approval","toolStatus","type","payload","NonNullable","interrupt","rawApproval","approved","resolution","response","prompt","reason","isAutomatic","display","allowFreeform","dismissible","optionId","text","additionalApprovalFields","normalizedOptions","requestReason","MessageContent","Exclude","uiPartStateToStatus","state","convertParts","message","parts","converted","p","role","map","status","providerMetadata","toolName","toolCallId","argsKeyOrderCacheKey","rawInput","input","args","modelContent","isError","unwrapped","error","errorText","argsText","frozen","frozenText","toolStatuses","mcpApp","artifact","interactions","unstable_interactions","preliminary","isPreliminary","sourceType","sourceId","url","data","mediaType","filename","startsWith","name","substring","console","warn","Boolean","seenToolCallIds","add","AISDKMessageConverter","createdAt","Date","content","attachments","idx","isImage","toString","image","contentType","timing","messageTiming","isOptimistic"],"sources":["../../src/converters/convertMessage.ts"],"sourcesContent":["import {\n isToolUIPart,\n isReasoningFileUIPart,\n isCustomContentUIPart,\n getToolName,\n type UIMessage,\n} from \"ai\";\nimport {\n createMessageConverter as unstable_createMessageConverter,\n type useExternalMessageConverter,\n} from \"@assistant-ui/core/react\";\nimport {\n isMcpAppUri,\n type ReasoningMessagePart,\n type ToolApprovalOption,\n type ToolCallMessagePart,\n type TextMessagePart,\n type DataMessagePart,\n type PartProviderMetadata,\n type SourceMessagePart,\n type SourceProviderMetadata,\n type FileMessagePart,\n type ThreadMessageLike,\n type McpAppMetadata,\n type MessagePartStreamStatus,\n type RespondToToolApprovalOptions,\n type Unstable_ToolInteractionLog,\n} from \"@assistant-ui/core\";\nimport { stableStringifyToolArgs } from \"@assistant-ui/core/internal\";\nimport {\n parsePartialJsonObject,\n type ReadonlyJSONObject,\n} from \"assistant-stream/utils\";\nimport { unwrapModelContentEnvelope } from \"./modelContentEnvelope\";\n\ntype MessageMetadata = ThreadMessageLike[\"metadata\"];\n\nconst THREAD_METADATA_KEYS = new Set([\n \"unstable_state\",\n \"unstable_annotations\",\n \"unstable_data\",\n \"steps\",\n \"timing\",\n \"submittedFeedback\",\n \"isOptimistic\",\n \"modality\",\n \"custom\",\n]);\n\nconst toThreadMetadata = (metadata: unknown): MessageMetadata => {\n if (!metadata || typeof metadata !== \"object\") return undefined;\n const result: Record<string, unknown> = {};\n const extra = Object.create(null) as Record<string, unknown>;\n for (const [key, value] of Object.entries(metadata)) {\n (THREAD_METADATA_KEYS.has(key) ? result : extra)[key] = value;\n }\n if (Object.keys(extra).length > 0) {\n result.custom = { ...extra, ...(result.custom as object | undefined) };\n }\n return result as MessageMetadata;\n};\nexport type AISDKMessageConverterMetadata =\n useExternalMessageConverter.Metadata & {\n toolArgsKeyOrderCache?: Map<string, Map<string, string[]>>;\n /**\n * Frozen `argsText` keyed weakly by a settled tool call's input object, then\n * by call, since the text carries the call's streamed key order. A known\n * call/input pair skips serialization; the entries become collectible once\n * the input is unreachable. A fresh input object re-serializes in its own\n * deterministic key order.\n */\n toolArgsTextCache?: WeakMap<ReadonlyJSONObject, Map<string, string>>;\n toolLastInputCache?: Map<string, ReadonlyJSONObject>;\n mcpAppMetadataCache?: Map<string, McpAppMetadata>;\n toolArtifacts?: ReadonlyMap<string, unknown>;\n toolInteractions?: ReadonlyMap<string, Unstable_ToolInteractionLog>;\n supportsRichToolApprovalResponses?: boolean;\n toolApprovalResponses?: ReadonlyMap<string, RespondToToolApprovalOptions>;\n cancelledToolApprovalIds?: ReadonlySet<string>;\n cancelledStatusMessageIds?: ReadonlySet<string>;\n /** Id of the currently-streaming message, flagged optimistic (#4037). */\n optimisticMessageId?: string | undefined;\n };\n\nfunction stripClosingDelimiters(json: string): string {\n let end = json.length;\n while (end > 0 && '}]\"'.includes(json[end - 1]!)) end--;\n return json.slice(0, end);\n}\n\nconst MCP_APP_METADATA_CACHE_MAX = 100;\n\nfunction extractMcpAppMetadata(\n part: unknown,\n cache: Map<string, McpAppMetadata> | undefined,\n): McpAppMetadata | undefined {\n if (!part || typeof part !== \"object\") return undefined;\n const meta = (part as { callProviderMetadata?: unknown })\n .callProviderMetadata;\n const mcp =\n meta && typeof meta === \"object\"\n ? (meta as { mcp?: unknown }).mcp\n : undefined;\n const app =\n mcp && typeof mcp === \"object\" ? (mcp as { app?: unknown }).app : undefined;\n let a: Record<string, unknown>;\n if (app && typeof app === \"object\") {\n a = app as Record<string, unknown>;\n } else {\n // MCP-UI tools surface the pointer on result._meta: canonical nested\n // `ui.resourceUri`, or the deprecated flat `\"ui/resourceUri\"` key.\n const output = (part as { output?: unknown }).output;\n const outMeta =\n output && typeof output === \"object\"\n ? (output as { _meta?: unknown })._meta\n : undefined;\n const ui =\n outMeta && typeof outMeta === \"object\"\n ? (outMeta as Record<string, unknown>)[\"ui\"]\n : undefined;\n if (\n ui &&\n typeof ui === \"object\" &&\n typeof (ui as Record<string, unknown>)[\"resourceUri\"] === \"string\" &&\n isMcpAppUri((ui as Record<string, unknown>)[\"resourceUri\"] as string)\n ) {\n // Only the spec'd ui fields cross from the result body; serverId is a\n // routing key and stays transport-derived via callProviderMetadata.\n const uiMeta = ui as Record<string, unknown>;\n a = {\n resourceUri: uiMeta[\"resourceUri\"],\n ...(Array.isArray(uiMeta[\"visibility\"])\n ? { visibility: uiMeta[\"visibility\"] }\n : {}),\n };\n } else {\n const flat =\n outMeta && typeof outMeta === \"object\"\n ? (outMeta as Record<string, unknown>)[\"ui/resourceUri\"]\n : undefined;\n if (typeof flat !== \"string\" || !isMcpAppUri(flat)) return undefined;\n a = { resourceUri: flat };\n }\n }\n if (typeof a[\"resourceUri\"] !== \"string\") return undefined;\n if (!isMcpAppUri(a[\"resourceUri\"])) return undefined;\n const cacheKey = `${typeof a[\"serverId\"] === \"string\" ? a[\"serverId\"] : \"\"} ${a[\"resourceUri\"]}`;\n const cached = cache?.get(cacheKey);\n if (cached) {\n cache!.delete(cacheKey);\n cache!.set(cacheKey, cached);\n return cached;\n }\n const out: { -readonly [K in keyof McpAppMetadata]: McpAppMetadata[K] } = {\n resourceUri: a[\"resourceUri\"],\n };\n if (typeof a[\"mimeType\"] === \"string\") out.mimeType = a[\"mimeType\"];\n if (Array.isArray(a[\"visibility\"])) {\n out.visibility = a[\"visibility\"].filter(\n (v): v is \"model\" | \"app\" => v === \"model\" || v === \"app\",\n );\n }\n if (typeof a[\"serverId\"] === \"string\" && a[\"serverId\"].length > 0)\n out.serverId = a[\"serverId\"];\n if (cache) {\n if (cache.size >= MCP_APP_METADATA_CACHE_MAX) {\n const oldest = cache.keys().next().value;\n if (oldest !== undefined) cache.delete(oldest);\n }\n cache.set(cacheKey, out);\n }\n return out;\n}\n\nconst normalizeToolApprovalOptions = (\n options: unknown,\n): readonly ToolApprovalOption[] | undefined => {\n if (!Array.isArray(options)) return undefined;\n\n return options.flatMap<ToolApprovalOption>((value) => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return [];\n const option = value as Record<string, unknown>;\n if (typeof option.id !== \"string\" || typeof option.kind !== \"string\")\n return [];\n\n const confirm = option.confirm;\n const confirmDetails =\n confirm && typeof confirm === \"object\" && !Array.isArray(confirm)\n ? (confirm as Record<string, unknown>)\n : undefined;\n\n return [\n {\n id: option.id,\n kind: option.kind,\n ...(typeof option.label === \"string\" && { label: option.label }),\n ...(typeof option.description === \"string\" && {\n description: option.description,\n }),\n ...(Array.isArray(option.grants) && {\n grants: option.grants.filter(\n (grant): grant is string => typeof grant === \"string\",\n ),\n }),\n ...(typeof confirm === \"boolean\"\n ? { confirm }\n : confirmDetails\n ? {\n confirm: {\n ...(typeof confirmDetails.title === \"string\" && {\n title: confirmDetails.title,\n }),\n ...(typeof confirmDetails.description === \"string\" && {\n description: confirmDetails.description,\n }),\n },\n }\n : {}),\n },\n ];\n });\n};\n\nconst APPROVAL_DESCRIPTOR_FIELDS = [\n \"prompt\",\n \"display\",\n \"allowFreeform\",\n \"dismissible\",\n \"options\",\n \"optionId\",\n \"text\",\n \"resolution\",\n] as const;\n\n// The AI SDK's approval object declares none of the core request and answer\n// fields and `validateUIMessages` strips unknown ones, so a host streams or\n// persists them inside the opaque `approvalDescriptor`. Only those fields are\n// read from it: a descriptor cannot approve its own request.\nconst readApprovalDescriptor = (\n descriptor: unknown,\n): Record<string, unknown> => {\n if (\n !descriptor ||\n typeof descriptor !== \"object\" ||\n Array.isArray(descriptor)\n )\n return {};\n const fields: Record<string, unknown> = {};\n for (const key of APPROVAL_DESCRIPTOR_FIELDS) {\n if (Object.hasOwn(descriptor, key))\n fields[key] = (descriptor as Record<string, unknown>)[key];\n }\n return fields;\n};\n\nfunction getToolApprovalAndInterrupt(\n part: {\n approval?: Record<string, unknown> | undefined;\n },\n toolStatus: { type: string; payload?: unknown } | undefined,\n supportsRichToolApprovalResponses: boolean,\n toolApprovalResponses:\n | ReadonlyMap<string, RespondToToolApprovalOptions>\n | undefined,\n cancelledToolApprovalIds: ReadonlySet<string> | undefined,\n): {\n approval?: NonNullable<ToolCallMessagePart[\"approval\"]>;\n interrupt?: NonNullable<ToolCallMessagePart[\"interrupt\"]>;\n} {\n if (part.approval) {\n const rawApproval = {\n ...readApprovalDescriptor(part.approval.descriptor),\n ...part.approval,\n };\n const approval =\n typeof rawApproval.id === \"string\" &&\n rawApproval.approved === undefined &&\n rawApproval.resolution === undefined &&\n cancelledToolApprovalIds?.has(rawApproval.id)\n ? { ...rawApproval, resolution: \"cancelled\" as const }\n : rawApproval;\n const response =\n typeof approval.id === \"string\" &&\n approval.approved === undefined &&\n approval.resolution !== \"cancelled\" &&\n approval.resolution !== \"expired\"\n ? toolApprovalResponses?.get(approval.id)\n : undefined;\n // The built-in AI SDK channel sends only id, approved and reason back to\n // the server, so a request shape promising any other answer would render\n // controls whose response cannot travel.\n const {\n id,\n prompt,\n approved,\n reason,\n isAutomatic,\n resolution,\n display,\n allowFreeform,\n dismissible,\n options,\n optionId,\n text,\n ...additionalApprovalFields\n } = response\n ? {\n ...approval,\n approved: response.approved,\n ...(response.reason != null && { reason: response.reason }),\n ...(response.optionId != null && { optionId: response.optionId }),\n ...(response.text != null && { text: response.text }),\n }\n : approval;\n const normalizedOptions = supportsRichToolApprovalResponses\n ? normalizeToolApprovalOptions(options)\n : undefined;\n const requestReason = additionalApprovalFields.requestReason;\n if (typeof id === \"string\")\n return {\n approval: {\n ...additionalApprovalFields,\n id,\n ...(typeof prompt === \"string\"\n ? { prompt }\n : typeof requestReason === \"string\"\n ? { prompt: requestReason }\n : {}),\n ...(typeof approved === \"boolean\" && { approved }),\n ...(typeof reason === \"string\" && { reason }),\n ...(isAutomatic === true && { isAutomatic: true }),\n ...(supportsRichToolApprovalResponses && {\n ...((display === \"decision\" ||\n display === \"select\" ||\n display === \"text\") && { display }),\n ...(typeof allowFreeform === \"boolean\" && { allowFreeform }),\n ...(typeof dismissible === \"boolean\" && { dismissible }),\n ...(normalizedOptions && { options: normalizedOptions }),\n ...(typeof optionId === \"string\" && { optionId }),\n ...(typeof text === \"string\" && { text }),\n }),\n ...((resolution === \"cancelled\" || resolution === \"expired\") && {\n resolution,\n }),\n } as NonNullable<ToolCallMessagePart[\"approval\"]>,\n };\n }\n\n if (toolStatus?.type === \"interrupt\") {\n return {\n interrupt: toolStatus.payload as NonNullable<\n ToolCallMessagePart[\"interrupt\"]\n >,\n };\n }\n\n return {};\n}\n\ntype MessageContent = Exclude<ThreadMessageLike[\"content\"], string>;\n\nconst uiPartStateToStatus = (\n state: \"streaming\" | \"done\" | undefined,\n): MessagePartStreamStatus | undefined => {\n if (state === \"streaming\") return { type: \"running\" };\n if (state === \"done\") return { type: \"complete\" };\n return undefined;\n};\n\nfunction convertParts(\n message: UIMessage,\n metadata: AISDKMessageConverterMetadata,\n): MessageContent {\n if (!message.parts || message.parts.length === 0) {\n return [];\n }\n\n const converted = message.parts\n .filter(\n (p) =>\n p.type !== \"step-start\" &&\n (message.role !== \"user\" || p.type !== \"file\"),\n )\n .map((part) => {\n if (part.type === \"text\") {\n const status = uiPartStateToStatus(part.state);\n return {\n type: \"text\",\n text: part.text,\n ...(status != null ? { status } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata: part.providerMetadata as PartProviderMetadata,\n }\n : undefined),\n } satisfies TextMessagePart;\n }\n\n if (part.type === \"reasoning\") {\n const status = uiPartStateToStatus(part.state);\n return {\n type: \"reasoning\",\n text: part.text,\n ...(status != null ? { status } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata: part.providerMetadata as PartProviderMetadata,\n }\n : undefined),\n } satisfies ReasoningMessagePart;\n }\n\n if (isToolUIPart(part)) {\n const toolName = getToolName(part);\n const toolCallId = part.toolCallId;\n const argsKeyOrderCacheKey = `${message.id}:${toolCallId}`;\n\n // A tool call that streamed complete arguments then failed schema\n // validation keeps them in `rawInput`, not `input`; reading `input`\n // alone would convert the error snapshot to `{}` and hide the input.\n const rawInput = (part.input ??\n (\"rawInput\" in part ? part.rawInput : undefined)) as\n | ReadonlyJSONObject\n | null\n | undefined;\n let args: ReadonlyJSONObject;\n if (\n rawInput != null &&\n typeof rawInput === \"object\" &&\n !Array.isArray(rawInput)\n ) {\n args = rawInput;\n metadata.toolLastInputCache?.set(argsKeyOrderCacheKey, args);\n } else {\n args = metadata.toolLastInputCache?.get(argsKeyOrderCacheKey) ?? {};\n }\n\n let result: unknown;\n let modelContent: ToolCallMessagePart[\"modelContent\"];\n let isError = false;\n\n if (part.state === \"output-available\") {\n const unwrapped = unwrapModelContentEnvelope(part.output);\n result = unwrapped.result;\n modelContent = unwrapped.modelContent;\n } else if (part.state === \"output-error\") {\n isError = true;\n result = { error: part.errorText };\n } else if (part.state === \"output-denied\") {\n isError = true;\n result = {\n error:\n (part as { approval?: { reason?: string } }).approval?.reason ||\n \"Tool approval denied\",\n };\n }\n\n let argsText: string;\n if (part.state === \"input-streaming\") {\n argsText = stableStringifyToolArgs(\n metadata.toolArgsKeyOrderCache,\n argsKeyOrderCacheKey,\n args,\n );\n // strip closing delimiters added by the AI SDK's fix-json\n argsText = stripClosingDelimiters(argsText);\n // Re-parse so args carries the partial-JSON meta that marks which\n // field is still mid-arrival, like every argsText-based runtime.\n // The key-order cache appends new keys last, so the trailing field\n // of the stripped text is the streaming frontier.\n args = parsePartialJsonObject(argsText) ?? args;\n } else {\n // A settled part is re-converted whenever its message or the converter\n // metadata changes; the text frozen on its input object skips\n // re-serializing large args while the call keeps that input. Arrival\n // order only matters while args stream, so the key-order entry is\n // released.\n const frozen =\n metadata.toolArgsTextCache?.get(args) ?? new Map<string, string>();\n const frozenText = frozen.get(argsKeyOrderCacheKey);\n if (frozenText !== undefined) {\n argsText = frozenText;\n } else {\n argsText = stableStringifyToolArgs(\n metadata.toolArgsKeyOrderCache,\n argsKeyOrderCacheKey,\n args,\n );\n metadata.toolArgsTextCache?.set(\n args,\n frozen.set(argsKeyOrderCacheKey, argsText),\n );\n }\n metadata.toolArgsKeyOrderCache?.delete(argsKeyOrderCacheKey);\n if (\n part.state === \"output-available\" ||\n part.state === \"output-error\" ||\n part.state === \"output-denied\"\n ) {\n metadata.toolLastInputCache?.delete(argsKeyOrderCacheKey);\n }\n }\n\n const toolStatus = metadata.toolStatuses?.[toolCallId];\n const mcpApp = extractMcpAppMetadata(\n part,\n metadata.mcpAppMetadataCache,\n );\n const artifact = metadata.toolArtifacts?.get(toolCallId);\n const interactions = metadata.toolInteractions?.get(toolCallId);\n return {\n type: \"tool-call\",\n toolName,\n toolCallId,\n argsText,\n args,\n result,\n isError,\n ...(artifact !== undefined && { artifact }),\n ...(interactions !== undefined && {\n unstable_interactions: interactions,\n }),\n ...(part.state === \"output-available\" &&\n part.preliminary === true && { isPreliminary: true }),\n ...(modelContent !== undefined && { modelContent }),\n ...(mcpApp && { mcp: { app: mcpApp } }),\n ...(part.callProviderMetadata != null\n ? {\n providerMetadata:\n part.callProviderMetadata as PartProviderMetadata,\n }\n : undefined),\n ...getToolApprovalAndInterrupt(\n part,\n toolStatus,\n metadata.supportsRichToolApprovalResponses === true,\n metadata.toolApprovalResponses,\n metadata.cancelledToolApprovalIds,\n ),\n } satisfies ToolCallMessagePart;\n }\n\n if (part.type === \"source-url\") {\n return {\n type: \"source\",\n sourceType: \"url\",\n id: part.sourceId,\n url: part.url,\n ...(part.title != null ? { title: part.title } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata:\n part.providerMetadata as SourceProviderMetadata,\n }\n : undefined),\n } satisfies SourceMessagePart;\n }\n\n if (part.type === \"file\") {\n return {\n type: \"file\",\n data: part.url,\n mimeType: part.mediaType,\n ...(part.filename != null && { filename: part.filename }),\n } satisfies FileMessagePart;\n }\n\n if (part.type === \"source-document\") {\n return {\n type: \"source\",\n sourceType: \"document\",\n id: part.sourceId,\n title: part.title,\n mediaType: part.mediaType,\n ...(part.filename != null ? { filename: part.filename } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata:\n part.providerMetadata as SourceProviderMetadata,\n }\n : undefined),\n } satisfies SourceMessagePart;\n }\n\n if (part.type.startsWith(\"data-\")) {\n return {\n type: \"data\",\n name: part.type.substring(5),\n data: (part as any).data,\n } satisfies DataMessagePart;\n }\n\n if (isReasoningFileUIPart(part)) {\n return {\n type: \"file\",\n data: part.url,\n mimeType: part.mediaType,\n } satisfies FileMessagePart;\n }\n\n if (isCustomContentUIPart(part)) {\n return {\n type: \"data\",\n name: part.kind,\n data: part.providerMetadata ?? null,\n } satisfies DataMessagePart;\n }\n\n console.warn(`Unsupported message part type: ${part.type}`);\n return null;\n })\n .filter(Boolean) as MessageContent[number][];\n\n const seenToolCallIds = new Set<string>();\n return converted.filter((part) => {\n if (part.type === \"tool-call\" && part.toolCallId != null) {\n if (seenToolCallIds.has(part.toolCallId)) return false;\n seenToolCallIds.add(part.toolCallId);\n }\n return true;\n });\n}\n\nexport const AISDKMessageConverter = unstable_createMessageConverter(\n (message: UIMessage, metadata: AISDKMessageConverterMetadata) => {\n const createdAt = new Date();\n const content = convertParts(message, metadata);\n\n switch (message.role) {\n case \"user\":\n return {\n role: \"user\",\n id: message.id,\n createdAt,\n content,\n attachments: message.parts\n ?.filter((p) => p.type === \"file\")\n .map((part, idx) => {\n const mediaType = part.mediaType ?? \"unknown/unknown\";\n const isImage = mediaType.startsWith(\"image/\");\n return {\n id: idx.toString(),\n type: isImage ? \"image\" : \"file\",\n name: part.filename ?? \"file\",\n content: [\n isImage\n ? {\n type: \"image\",\n image: part.url,\n filename: part.filename!,\n }\n : {\n type: \"file\",\n filename: part.filename!,\n data: part.url,\n mimeType: mediaType,\n },\n ],\n contentType: mediaType,\n status: { type: \"complete\" as const },\n };\n }),\n metadata: toThreadMetadata(message.metadata),\n };\n\n case \"system\":\n case \"assistant\": {\n const timing = metadata.messageTiming?.[message.id];\n const isOptimistic =\n message.role === \"assistant\" &&\n message.id === metadata.optimisticMessageId;\n return {\n role: message.role,\n id: message.id,\n createdAt,\n content,\n ...(message.role === \"assistant\" &&\n metadata.cancelledStatusMessageIds?.has(message.id)\n ? {\n status: {\n type: \"incomplete\" as const,\n reason: \"cancelled\" as const,\n },\n }\n : undefined),\n metadata: {\n ...toThreadMetadata(message.metadata),\n ...(timing && { timing }),\n ...(isOptimistic && { isOptimistic: true }),\n },\n };\n }\n\n default:\n console.warn(`Unsupported message role: ${message.role}`);\n return [];\n }\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"convertMessage.js","names":["isToolUIPart","isReasoningFileUIPart","isCustomContentUIPart","getToolName","UIMessage","createMessageConverter","unstable_createMessageConverter","useExternalMessageConverter","isMcpAppUri","ReasoningMessagePart","ToolApprovalOption","ToolCallMessagePart","TextMessagePart","DataMessagePart","PartProviderMetadata","SourceMessagePart","SourceProviderMetadata","FileMessagePart","ThreadMessageLike","McpAppMetadata","MessagePartStreamStatus","RespondToToolApprovalOptions","Unstable_ToolInteractionLog","stableStringifyToolArgs","parsePartialJsonObject","ReadonlyJSONObject","unwrapModelContentEnvelope","MessageMetadata","THREAD_METADATA_KEYS","Set","toThreadMetadata","metadata","undefined","result","Record","extra","Object","create","key","value","entries","has","keys","length","custom","AISDKMessageConverterMetadata","Metadata","toolArgsKeyOrderCache","Map","toolArgsTextCache","WeakMap","toolLastInputCache","mcpAppMetadataCache","toolArtifacts","ReadonlyMap","toolInteractions","supportsRichToolApprovalResponses","toolApprovalResponses","cancelledToolApprovalIds","ReadonlySet","cancelledStatusMessageIds","optimisticMessageId","stripClosingDelimiters","json","end","includes","slice","MCP_APP_METADATA_CACHE_MAX","extractMcpAppMetadata","part","cache","meta","callProviderMetadata","mcp","app","a","output","outMeta","_meta","ui","uiMeta","resourceUri","Array","isArray","visibility","flat","cacheKey","cached","get","delete","set","out","K","mimeType","filter","v","serverId","size","oldest","next","normalizeToolApprovalOptions","options","flatMap","option","id","kind","confirm","confirmDetails","label","description","grants","grant","title","APPROVAL_DESCRIPTOR_FIELDS","const","readApprovalDescriptor","descriptor","fields","hasOwn","getToolApprovalAndInterrupt","approval","toolStatus","type","payload","NonNullable","interrupt","rawApproval","approved","resolution","response","prompt","reason","isAutomatic","display","allowFreeform","dismissible","optionId","text","additionalApprovalFields","normalizedOptions","requestReason","MessageContent","Exclude","uiPartStateToStatus","state","convertParts","message","parts","converted","p","role","map","status","providerMetadata","toolName","toolCallId","argsKeyOrderCacheKey","rawInput","input","args","modelContent","isError","unwrapped","error","errorText","argsText","frozen","frozenText","toolStatuses","mcpApp","artifact","interactions","unstable_interactions","preliminary","isPreliminary","sourceType","sourceId","url","data","mediaType","filename","startsWith","name","substring","console","warn","Boolean","seenToolCallIds","add","AISDKMessageConverter","createdAt","Date","content","attachments","idx","isImage","toString","image","contentType","timing","messageTiming","isOptimistic","unstable_createMessageConverter"],"sources":["../../src/converters/convertMessage.ts"],"sourcesContent":["import {\n isToolUIPart,\n isReasoningFileUIPart,\n isCustomContentUIPart,\n getToolName,\n type UIMessage,\n} from \"ai\";\nimport {\n createMessageConverter as unstable_createMessageConverter,\n type useExternalMessageConverter,\n} from \"@assistant-ui/core/react\";\nimport {\n isMcpAppUri,\n type ReasoningMessagePart,\n type ToolApprovalOption,\n type ToolCallMessagePart,\n type TextMessagePart,\n type DataMessagePart,\n type PartProviderMetadata,\n type SourceMessagePart,\n type SourceProviderMetadata,\n type FileMessagePart,\n type ThreadMessageLike,\n type McpAppMetadata,\n type MessagePartStreamStatus,\n type RespondToToolApprovalOptions,\n type Unstable_ToolInteractionLog,\n} from \"@assistant-ui/core\";\nimport { stableStringifyToolArgs } from \"@assistant-ui/core/internal\";\nimport {\n parsePartialJsonObject,\n type ReadonlyJSONObject,\n} from \"assistant-stream/utils\";\nimport { unwrapModelContentEnvelope } from \"./modelContentEnvelope\";\n\ntype MessageMetadata = ThreadMessageLike[\"metadata\"];\n\nconst THREAD_METADATA_KEYS = new Set([\n \"unstable_state\",\n \"unstable_annotations\",\n \"unstable_data\",\n \"steps\",\n \"timing\",\n \"submittedFeedback\",\n \"isOptimistic\",\n \"modality\",\n \"custom\",\n]);\n\nconst toThreadMetadata = (metadata: unknown): MessageMetadata => {\n if (!metadata || typeof metadata !== \"object\") return undefined;\n const result: Record<string, unknown> = {};\n const extra = Object.create(null) as Record<string, unknown>;\n for (const [key, value] of Object.entries(metadata)) {\n (THREAD_METADATA_KEYS.has(key) ? result : extra)[key] = value;\n }\n if (Object.keys(extra).length > 0) {\n result.custom = { ...extra, ...(result.custom as object | undefined) };\n }\n return result as MessageMetadata;\n};\nexport type AISDKMessageConverterMetadata =\n useExternalMessageConverter.Metadata & {\n toolArgsKeyOrderCache?: Map<string, Map<string, string[]>>;\n /**\n * Frozen `argsText` keyed weakly by a settled tool call's input object, then\n * by call, since the text carries the call's streamed key order. A known\n * call/input pair skips serialization; the entries become collectible once\n * the input is unreachable. A fresh input object re-serializes in its own\n * deterministic key order.\n */\n toolArgsTextCache?: WeakMap<ReadonlyJSONObject, Map<string, string>>;\n toolLastInputCache?: Map<string, ReadonlyJSONObject>;\n mcpAppMetadataCache?: Map<string, McpAppMetadata>;\n toolArtifacts?: ReadonlyMap<string, unknown>;\n toolInteractions?: ReadonlyMap<string, Unstable_ToolInteractionLog>;\n supportsRichToolApprovalResponses?: boolean;\n toolApprovalResponses?: ReadonlyMap<string, RespondToToolApprovalOptions>;\n cancelledToolApprovalIds?: ReadonlySet<string>;\n cancelledStatusMessageIds?: ReadonlySet<string>;\n /** Id of the currently-streaming message, flagged optimistic (#4037). */\n optimisticMessageId?: string | undefined;\n };\n\nfunction stripClosingDelimiters(json: string): string {\n let end = json.length;\n while (end > 0 && '}]\"'.includes(json[end - 1]!)) end--;\n return json.slice(0, end);\n}\n\nconst MCP_APP_METADATA_CACHE_MAX = 100;\n\nfunction extractMcpAppMetadata(\n part: unknown,\n cache: Map<string, McpAppMetadata> | undefined,\n): McpAppMetadata | undefined {\n if (!part || typeof part !== \"object\") return undefined;\n const meta = (part as { callProviderMetadata?: unknown })\n .callProviderMetadata;\n const mcp =\n meta && typeof meta === \"object\"\n ? (meta as { mcp?: unknown }).mcp\n : undefined;\n const app =\n mcp && typeof mcp === \"object\" ? (mcp as { app?: unknown }).app : undefined;\n let a: Record<string, unknown>;\n if (app && typeof app === \"object\") {\n a = app as Record<string, unknown>;\n } else {\n // MCP-UI tools surface the pointer on result._meta: canonical nested\n // `ui.resourceUri`, or the deprecated flat `\"ui/resourceUri\"` key.\n const output = (part as { output?: unknown }).output;\n const outMeta =\n output && typeof output === \"object\"\n ? (output as { _meta?: unknown })._meta\n : undefined;\n const ui =\n outMeta && typeof outMeta === \"object\"\n ? (outMeta as Record<string, unknown>)[\"ui\"]\n : undefined;\n if (\n ui &&\n typeof ui === \"object\" &&\n typeof (ui as Record<string, unknown>)[\"resourceUri\"] === \"string\" &&\n isMcpAppUri((ui as Record<string, unknown>)[\"resourceUri\"] as string)\n ) {\n // Only the spec'd ui fields cross from the result body; serverId is a\n // routing key and stays transport-derived via callProviderMetadata.\n const uiMeta = ui as Record<string, unknown>;\n a = {\n resourceUri: uiMeta[\"resourceUri\"],\n ...(Array.isArray(uiMeta[\"visibility\"])\n ? { visibility: uiMeta[\"visibility\"] }\n : {}),\n };\n } else {\n const flat =\n outMeta && typeof outMeta === \"object\"\n ? (outMeta as Record<string, unknown>)[\"ui/resourceUri\"]\n : undefined;\n if (typeof flat !== \"string\" || !isMcpAppUri(flat)) return undefined;\n a = { resourceUri: flat };\n }\n }\n if (typeof a[\"resourceUri\"] !== \"string\") return undefined;\n if (!isMcpAppUri(a[\"resourceUri\"])) return undefined;\n const cacheKey = `${typeof a[\"serverId\"] === \"string\" ? a[\"serverId\"] : \"\"} ${a[\"resourceUri\"]}`;\n const cached = cache?.get(cacheKey);\n if (cached) {\n cache!.delete(cacheKey);\n cache!.set(cacheKey, cached);\n return cached;\n }\n const out: { -readonly [K in keyof McpAppMetadata]: McpAppMetadata[K] } = {\n resourceUri: a[\"resourceUri\"],\n };\n if (typeof a[\"mimeType\"] === \"string\") out.mimeType = a[\"mimeType\"];\n if (Array.isArray(a[\"visibility\"])) {\n out.visibility = a[\"visibility\"].filter(\n (v): v is \"model\" | \"app\" => v === \"model\" || v === \"app\",\n );\n }\n if (typeof a[\"serverId\"] === \"string\" && a[\"serverId\"].length > 0)\n out.serverId = a[\"serverId\"];\n if (cache) {\n if (cache.size >= MCP_APP_METADATA_CACHE_MAX) {\n const oldest = cache.keys().next().value;\n if (oldest !== undefined) cache.delete(oldest);\n }\n cache.set(cacheKey, out);\n }\n return out;\n}\n\nconst normalizeToolApprovalOptions = (\n options: unknown,\n): readonly ToolApprovalOption[] | undefined => {\n if (!Array.isArray(options)) return undefined;\n\n return options.flatMap<ToolApprovalOption>((value) => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return [];\n const option = value as Record<string, unknown>;\n if (typeof option.id !== \"string\" || typeof option.kind !== \"string\")\n return [];\n\n const confirm = option.confirm;\n const confirmDetails =\n confirm && typeof confirm === \"object\" && !Array.isArray(confirm)\n ? (confirm as Record<string, unknown>)\n : undefined;\n\n return [\n {\n id: option.id,\n kind: option.kind,\n ...(typeof option.label === \"string\" && { label: option.label }),\n ...(typeof option.description === \"string\" && {\n description: option.description,\n }),\n ...(Array.isArray(option.grants) && {\n grants: option.grants.filter(\n (grant): grant is string => typeof grant === \"string\",\n ),\n }),\n ...(typeof confirm === \"boolean\"\n ? { confirm }\n : confirmDetails\n ? {\n confirm: {\n ...(typeof confirmDetails.title === \"string\" && {\n title: confirmDetails.title,\n }),\n ...(typeof confirmDetails.description === \"string\" && {\n description: confirmDetails.description,\n }),\n },\n }\n : {}),\n },\n ];\n });\n};\n\nconst APPROVAL_DESCRIPTOR_FIELDS = [\n \"prompt\",\n \"display\",\n \"allowFreeform\",\n \"dismissible\",\n \"options\",\n \"optionId\",\n \"text\",\n \"resolution\",\n] as const;\n\n// The AI SDK's approval object declares none of the core request and answer\n// fields and `validateUIMessages` strips unknown ones, so a host streams or\n// persists them inside the opaque `approvalDescriptor`. Only those fields are\n// read from it: a descriptor cannot approve its own request.\nconst readApprovalDescriptor = (\n descriptor: unknown,\n): Record<string, unknown> => {\n if (\n !descriptor ||\n typeof descriptor !== \"object\" ||\n Array.isArray(descriptor)\n )\n return {};\n const fields: Record<string, unknown> = {};\n for (const key of APPROVAL_DESCRIPTOR_FIELDS) {\n if (Object.hasOwn(descriptor, key))\n fields[key] = (descriptor as Record<string, unknown>)[key];\n }\n return fields;\n};\n\nfunction getToolApprovalAndInterrupt(\n part: {\n approval?: Record<string, unknown> | undefined;\n },\n toolStatus: { type: string; payload?: unknown } | undefined,\n supportsRichToolApprovalResponses: boolean,\n toolApprovalResponses:\n | ReadonlyMap<string, RespondToToolApprovalOptions>\n | undefined,\n cancelledToolApprovalIds: ReadonlySet<string> | undefined,\n): {\n approval?: NonNullable<ToolCallMessagePart[\"approval\"]>;\n interrupt?: NonNullable<ToolCallMessagePart[\"interrupt\"]>;\n} {\n if (part.approval) {\n const rawApproval = {\n ...readApprovalDescriptor(part.approval.descriptor),\n ...part.approval,\n };\n const approval =\n typeof rawApproval.id === \"string\" &&\n rawApproval.approved === undefined &&\n rawApproval.resolution === undefined &&\n cancelledToolApprovalIds?.has(rawApproval.id)\n ? { ...rawApproval, resolution: \"cancelled\" as const }\n : rawApproval;\n const response =\n typeof approval.id === \"string\" &&\n approval.approved === undefined &&\n approval.resolution !== \"cancelled\" &&\n approval.resolution !== \"expired\"\n ? toolApprovalResponses?.get(approval.id)\n : undefined;\n // The built-in AI SDK channel sends only id, approved and reason back to\n // the server, so a request shape promising any other answer would render\n // controls whose response cannot travel.\n const {\n id,\n prompt,\n approved,\n reason,\n isAutomatic,\n resolution,\n display,\n allowFreeform,\n dismissible,\n options,\n optionId,\n text,\n ...additionalApprovalFields\n } = response\n ? {\n ...approval,\n approved: response.approved,\n ...(response.reason != null && { reason: response.reason }),\n ...(response.optionId != null && { optionId: response.optionId }),\n ...(response.text != null && { text: response.text }),\n }\n : approval;\n const normalizedOptions = supportsRichToolApprovalResponses\n ? normalizeToolApprovalOptions(options)\n : undefined;\n const requestReason = additionalApprovalFields.requestReason;\n if (typeof id === \"string\")\n return {\n approval: {\n ...additionalApprovalFields,\n id,\n ...(typeof prompt === \"string\"\n ? { prompt }\n : typeof requestReason === \"string\"\n ? { prompt: requestReason }\n : {}),\n ...(typeof approved === \"boolean\" && { approved }),\n ...(typeof reason === \"string\" && { reason }),\n ...(isAutomatic === true && { isAutomatic: true }),\n ...(supportsRichToolApprovalResponses && {\n ...((display === \"decision\" ||\n display === \"select\" ||\n display === \"text\") && { display }),\n ...(typeof allowFreeform === \"boolean\" && { allowFreeform }),\n ...(typeof dismissible === \"boolean\" && { dismissible }),\n ...(normalizedOptions && { options: normalizedOptions }),\n ...(typeof optionId === \"string\" && { optionId }),\n ...(typeof text === \"string\" && { text }),\n }),\n ...((resolution === \"cancelled\" || resolution === \"expired\") && {\n resolution,\n }),\n } as NonNullable<ToolCallMessagePart[\"approval\"]>,\n };\n }\n\n if (toolStatus?.type === \"interrupt\") {\n return {\n interrupt: toolStatus.payload as NonNullable<\n ToolCallMessagePart[\"interrupt\"]\n >,\n };\n }\n\n return {};\n}\n\ntype MessageContent = Exclude<ThreadMessageLike[\"content\"], string>;\n\nconst uiPartStateToStatus = (\n state: \"streaming\" | \"done\" | undefined,\n): MessagePartStreamStatus | undefined => {\n if (state === \"streaming\") return { type: \"running\" };\n if (state === \"done\") return { type: \"complete\" };\n return undefined;\n};\n\nfunction convertParts(\n message: UIMessage,\n metadata: AISDKMessageConverterMetadata,\n): MessageContent {\n if (!message.parts || message.parts.length === 0) {\n return [];\n }\n\n const converted = message.parts\n .filter(\n (p) =>\n p.type !== \"step-start\" &&\n (message.role !== \"user\" || p.type !== \"file\"),\n )\n .map((part) => {\n if (part.type === \"text\") {\n const status = uiPartStateToStatus(part.state);\n return {\n type: \"text\",\n text: part.text,\n ...(status != null ? { status } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata: part.providerMetadata as PartProviderMetadata,\n }\n : undefined),\n } satisfies TextMessagePart;\n }\n\n if (part.type === \"reasoning\") {\n const status = uiPartStateToStatus(part.state);\n return {\n type: \"reasoning\",\n text: part.text,\n ...(status != null ? { status } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata: part.providerMetadata as PartProviderMetadata,\n }\n : undefined),\n } satisfies ReasoningMessagePart;\n }\n\n if (isToolUIPart(part)) {\n const toolName = getToolName(part);\n const toolCallId = part.toolCallId;\n const argsKeyOrderCacheKey = `${message.id}:${toolCallId}`;\n\n // A tool call that streamed complete arguments then failed schema\n // validation keeps them in `rawInput`, not `input`; reading `input`\n // alone would convert the error snapshot to `{}` and hide the input.\n const rawInput = (part.input ??\n (\"rawInput\" in part ? part.rawInput : undefined)) as\n | ReadonlyJSONObject\n | null\n | undefined;\n let args: ReadonlyJSONObject;\n if (\n rawInput != null &&\n typeof rawInput === \"object\" &&\n !Array.isArray(rawInput)\n ) {\n args = rawInput;\n metadata.toolLastInputCache?.set(argsKeyOrderCacheKey, args);\n } else {\n args = metadata.toolLastInputCache?.get(argsKeyOrderCacheKey) ?? {};\n }\n\n let result: unknown;\n let modelContent: ToolCallMessagePart[\"modelContent\"];\n let isError = false;\n\n if (part.state === \"output-available\") {\n const unwrapped = unwrapModelContentEnvelope(part.output);\n result = unwrapped.result;\n modelContent = unwrapped.modelContent;\n } else if (part.state === \"output-error\") {\n isError = true;\n result = { error: part.errorText };\n } else if (part.state === \"output-denied\") {\n isError = true;\n result = {\n error:\n (part as { approval?: { reason?: string } }).approval?.reason ||\n \"Tool approval denied\",\n };\n }\n\n let argsText: string;\n if (part.state === \"input-streaming\") {\n argsText = stableStringifyToolArgs(\n metadata.toolArgsKeyOrderCache,\n argsKeyOrderCacheKey,\n args,\n );\n // strip closing delimiters added by the AI SDK's fix-json\n argsText = stripClosingDelimiters(argsText);\n // Re-parse so args carries the partial-JSON meta that marks which\n // field is still mid-arrival, like every argsText-based runtime.\n // The key-order cache appends new keys last, so the trailing field\n // of the stripped text is the streaming frontier.\n args = parsePartialJsonObject(argsText) ?? args;\n } else {\n // A settled part is re-converted whenever its message or the converter\n // metadata changes; the text frozen on its input object skips\n // re-serializing large args while the call keeps that input. Arrival\n // order only matters while args stream, so the key-order entry is\n // released.\n const frozen =\n metadata.toolArgsTextCache?.get(args) ?? new Map<string, string>();\n const frozenText = frozen.get(argsKeyOrderCacheKey);\n if (frozenText !== undefined) {\n argsText = frozenText;\n } else {\n argsText = stableStringifyToolArgs(\n metadata.toolArgsKeyOrderCache,\n argsKeyOrderCacheKey,\n args,\n );\n metadata.toolArgsTextCache?.set(\n args,\n frozen.set(argsKeyOrderCacheKey, argsText),\n );\n }\n metadata.toolArgsKeyOrderCache?.delete(argsKeyOrderCacheKey);\n if (\n part.state === \"output-available\" ||\n part.state === \"output-error\" ||\n part.state === \"output-denied\"\n ) {\n metadata.toolLastInputCache?.delete(argsKeyOrderCacheKey);\n }\n }\n\n const toolStatus = metadata.toolStatuses?.[toolCallId];\n const mcpApp = extractMcpAppMetadata(\n part,\n metadata.mcpAppMetadataCache,\n );\n const artifact = metadata.toolArtifacts?.get(toolCallId);\n const interactions = metadata.toolInteractions?.get(toolCallId);\n return {\n type: \"tool-call\",\n toolName,\n toolCallId,\n argsText,\n args,\n result,\n isError,\n ...(artifact !== undefined && { artifact }),\n ...(interactions !== undefined && {\n unstable_interactions: interactions,\n }),\n ...(part.state === \"output-available\" &&\n part.preliminary === true && { isPreliminary: true }),\n ...(modelContent !== undefined && { modelContent }),\n ...(mcpApp && { mcp: { app: mcpApp } }),\n ...(part.callProviderMetadata != null\n ? {\n providerMetadata:\n part.callProviderMetadata as PartProviderMetadata,\n }\n : undefined),\n ...getToolApprovalAndInterrupt(\n part,\n toolStatus,\n metadata.supportsRichToolApprovalResponses === true,\n metadata.toolApprovalResponses,\n metadata.cancelledToolApprovalIds,\n ),\n } satisfies ToolCallMessagePart;\n }\n\n if (part.type === \"source-url\") {\n return {\n type: \"source\",\n sourceType: \"url\",\n id: part.sourceId,\n url: part.url,\n ...(part.title != null ? { title: part.title } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata:\n part.providerMetadata as SourceProviderMetadata,\n }\n : undefined),\n } satisfies SourceMessagePart;\n }\n\n if (part.type === \"file\") {\n return {\n type: \"file\",\n data: part.url,\n mimeType: part.mediaType,\n ...(part.filename != null && { filename: part.filename }),\n } satisfies FileMessagePart;\n }\n\n if (part.type === \"source-document\") {\n return {\n type: \"source\",\n sourceType: \"document\",\n id: part.sourceId,\n title: part.title,\n mediaType: part.mediaType,\n ...(part.filename != null ? { filename: part.filename } : undefined),\n ...(part.providerMetadata != null\n ? {\n providerMetadata:\n part.providerMetadata as SourceProviderMetadata,\n }\n : undefined),\n } satisfies SourceMessagePart;\n }\n\n if (part.type.startsWith(\"data-\")) {\n return {\n type: \"data\",\n ...(\"id\" in part && typeof part.id === \"string\"\n ? { id: part.id }\n : undefined),\n name: part.type.substring(5),\n data: (part as any).data,\n } satisfies DataMessagePart;\n }\n\n if (isReasoningFileUIPart(part)) {\n return {\n type: \"file\",\n data: part.url,\n mimeType: part.mediaType,\n } satisfies FileMessagePart;\n }\n\n if (isCustomContentUIPart(part)) {\n return {\n type: \"data\",\n name: part.kind,\n data: part.providerMetadata ?? null,\n } satisfies DataMessagePart;\n }\n\n console.warn(`Unsupported message part type: ${part.type}`);\n return null;\n })\n .filter(Boolean) as MessageContent[number][];\n\n const seenToolCallIds = new Set<string>();\n return converted.filter((part) => {\n if (part.type === \"tool-call\" && part.toolCallId != null) {\n if (seenToolCallIds.has(part.toolCallId)) return false;\n seenToolCallIds.add(part.toolCallId);\n }\n return true;\n });\n}\n\nexport const AISDKMessageConverter = unstable_createMessageConverter(\n (message: UIMessage, metadata: AISDKMessageConverterMetadata) => {\n const createdAt = new Date();\n const content = convertParts(message, metadata);\n\n switch (message.role) {\n case \"user\":\n return {\n role: \"user\",\n id: message.id,\n createdAt,\n content,\n attachments: message.parts\n ?.filter((p) => p.type === \"file\")\n .map((part, idx) => {\n const mediaType = part.mediaType ?? \"unknown/unknown\";\n const isImage = mediaType.startsWith(\"image/\");\n return {\n id: idx.toString(),\n type: isImage ? \"image\" : \"file\",\n name: part.filename ?? \"file\",\n content: [\n isImage\n ? {\n type: \"image\",\n image: part.url,\n filename: part.filename!,\n }\n : {\n type: \"file\",\n filename: part.filename!,\n data: part.url,\n mimeType: mediaType,\n },\n ],\n contentType: mediaType,\n status: { type: \"complete\" as const },\n };\n }),\n metadata: toThreadMetadata(message.metadata),\n };\n\n case \"system\":\n case \"assistant\": {\n const timing = metadata.messageTiming?.[message.id];\n const isOptimistic =\n message.role === \"assistant\" &&\n message.id === metadata.optimisticMessageId;\n return {\n role: message.role,\n id: message.id,\n createdAt,\n content,\n ...(message.role === \"assistant\" &&\n metadata.cancelledStatusMessageIds?.has(message.id)\n ? {\n status: {\n type: \"incomplete\" as const,\n reason: \"cancelled\" as const,\n },\n }\n : undefined),\n metadata: {\n ...toThreadMetadata(message.metadata),\n ...(timing && { timing }),\n ...(isOptimistic && { isOptimistic: true }),\n },\n };\n }\n\n default:\n console.warn(`Unsupported message role: ${message.role}`);\n return [];\n }\n },\n);\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toCreateMessage.d.ts","sourceRoot":"","sources":["../../src/converters/toCreateMessage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAOxD,OAAO,KAAK,EACV,eAAe,EAEf,SAAS,EAGV,MAAM,IAAI,CAAC;AAOZ,eAAO,MAAM,eAAe,GAAI,UAAU,SAAS,SAAS,GAAG,SAAS,EACtE,SAAS,aAAa,KACrB,eAAe,CAAC,UAAU,
|
|
1
|
+
{"version":3,"file":"toCreateMessage.d.ts","sourceRoot":"","sources":["../../src/converters/toCreateMessage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAOxD,OAAO,KAAK,EACV,eAAe,EAEf,SAAS,EAGV,MAAM,IAAI,CAAC;AAOZ,eAAO,MAAM,eAAe,GAAI,UAAU,SAAS,SAAS,GAAG,SAAS,EACtE,SAAS,aAAa,KACrB,eAAe,CAAC,UAAU,CA8E5B,CAAC"}
|
|
@@ -45,7 +45,8 @@ const toCreateMessage = (message) => {
|
|
|
45
45
|
}
|
|
46
46
|
case "data": return {
|
|
47
47
|
type: `data-${part.name}`,
|
|
48
|
-
data: part.data
|
|
48
|
+
data: part.data,
|
|
49
|
+
...part.id !== void 0 && { id: part.id }
|
|
49
50
|
};
|
|
50
51
|
default: throw new Error(`Unsupported part type: ${part.type}`);
|
|
51
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toCreateMessage.js","names":["AppendMessage","resolveFileMediaType","resolveFilePartSource","resolveImageMediaType","toMediaWireUrl","CreateUIMessage","UIDataTypes","UIMessage","UIMessagePart","UITools","InputPart","contentType","filename","toCreateMessage","message","UI_MESSAGE","inputParts","content","attachments","flatMap","a","map","c","name","parts","part","type","text","mediaType","image","url","data","mimeType","sourceType","audio","format","source","kind","Error","role","metadata"],"sources":["../../src/converters/toCreateMessage.ts"],"sourcesContent":["import type { AppendMessage } from \"@assistant-ui/core\";\nimport {\n resolveFileMediaType,\n resolveFilePartSource,\n resolveImageMediaType,\n toMediaWireUrl,\n} from \"@assistant-ui/core/internal\";\nimport type {\n CreateUIMessage,\n UIDataTypes,\n UIMessage,\n UIMessagePart,\n UITools,\n} from \"ai\";\n\ntype InputPart = AppendMessage[\"content\"][number] & {\n readonly contentType?: string | undefined;\n readonly filename?: string | undefined;\n};\n\nexport const toCreateMessage = <UI_MESSAGE extends UIMessage = UIMessage>(\n message: AppendMessage,\n): CreateUIMessage<UI_MESSAGE> => {\n const inputParts: InputPart[] = [\n ...message.content,\n ...(message.attachments?.flatMap((a) =>\n a.content.map((c) => ({\n ...c,\n filename: a.name,\n contentType: a.contentType,\n })),\n ) ?? []),\n ];\n\n const parts = inputParts.map((part): UIMessagePart<UIDataTypes, UITools> => {\n switch (part.type) {\n case \"text\":\n return {\n type: \"text\",\n text: part.text,\n };\n case \"image\": {\n const mediaType = resolveImageMediaType(part.image, part.contentType);\n return {\n type: \"file\",\n url: toMediaWireUrl(part.image, mediaType),\n ...(part.filename && { filename: part.filename }),\n mediaType,\n };\n }\n case \"file\": {\n // `mimeType` is a plain string, and an adapter reading `file.type` on a\n // file the OS cannot type yields \"\". Same ladder as images: declared,\n // then the envelope, then the floor.\n const mediaType = resolveFileMediaType(part.data, part.mimeType);\n return {\n type: \"file\",\n // An `id` reference is an opaque provider handle, not base64, and\n // this adapter has no way to send one. Left unwrapped so it fails\n // loudly upstream rather than shipping a corrupt payload.\n url:\n part.sourceType === \"id\"\n ? part.data\n : toMediaWireUrl(part.data, mediaType),\n mediaType,\n ...(part.filename && { filename: part.filename }),\n };\n }\n case \"audio\": {\n // A data URL's own media type wins over `mediaType` downstream, so the\n // envelope is rebuilt from the typed format rather than forwarded.\n const mediaType = `audio/${part.audio.format}`;\n const data = part.audio.data;\n const source = resolveFilePartSource({ data, mimeType: mediaType });\n return {\n type: \"file\",\n url:\n source.kind === \"url\"\n ? source.url\n : `data:${mediaType};base64,${source.data}`,\n mediaType,\n ...(part.filename && { filename: part.filename }),\n };\n }\n case \"data\":\n return {\n type: `data-${part.name}`,\n data: part.data,\n };\n default:\n throw new Error(`Unsupported part type: ${part.type}`);\n }\n });\n\n return {\n role: message.role,\n parts,\n metadata: message.metadata,\n } satisfies CreateUIMessage<UIMessage> as CreateUIMessage<UI_MESSAGE>;\n};\n"],"mappings":";;AAoBA,MAAaa,mBACXC,YACgC;CAYhC,MAAMU,QAAQR,CAVZ,GAAGF,QAAQG,SACX,GAAIH,QAAQI,aAAaC,SAASC,MAChCA,EAAEH,QAAQI,KAAKC,OAAO;EACpB,GAAGA;EACHV,UAAUQ,EAAEG;EACZZ,aAAaS,EAAET;CACjB,EAAE,CACJ,KAAK,CAAA,CAGOK,CAAU,CAACK,KAAKI,SAA8C;EAC1E,QAAQA,KAAKC,MAAb;GACE,KAAK,QACH,OAAO;IACLA,MAAM;IACNC,MAAMF,KAAKE;GACb;GACF,KAAK,SAAS;IACZ,MAAMC,YAAYzB,sBAAsBsB,KAAKI,OAAOJ,KAAKd,WAAW;IACpE,OAAO;KACLe,MAAM;KACNI,KAAK1B,eAAeqB,KAAKI,OAAOD,SAAS;KACzC,GAAIH,KAAKb,YAAY,EAAEA,UAAUa,KAAKb,SAAS;KAC/CgB;IACF;GACF;GACA,KAAK,QAAQ;IAIX,MAAMA,YAAY3B,qBAAqBwB,KAAKM,MAAMN,KAAKO,QAAQ;IAC/D,OAAO;KACLN,MAAM;KAINI,KACEL,KAAKQ,eAAe,OAChBR,KAAKM,OACL3B,eAAeqB,KAAKM,MAAMH,SAAS;KACzCA;KACA,GAAIH,KAAKb,YAAY,EAAEA,UAAUa,KAAKb,SAAS;IACjD;GACF;GACA,KAAK,SAAS;IAGZ,MAAMgB,YAAY,SAASH,KAAKS,MAAMC;IACtC,MAAMJ,OAAON,KAAKS,MAAMH;IACxB,MAAMK,SAASlC,sBAAsB;KAAE6B;KAAMC,UAAUJ;IAAU,CAAC;IAClE,OAAO;KACLF,MAAM;KACNI,KACEM,OAAOC,SAAS,QACZD,OAAON,MACP,QAAQF,UAAS,UAAWQ,OAAOL;KACzCH;KACA,GAAIH,KAAKb,YAAY,EAAEA,UAAUa,KAAKb,SAAS;IACjD;GACF;GACA,KAAK,QACH,OAAO;IACLc,MAAM,QAAQD,KAAKF;IACnBQ,MAAMN,KAAKM;
|
|
1
|
+
{"version":3,"file":"toCreateMessage.js","names":["AppendMessage","resolveFileMediaType","resolveFilePartSource","resolveImageMediaType","toMediaWireUrl","CreateUIMessage","UIDataTypes","UIMessage","UIMessagePart","UITools","InputPart","contentType","filename","toCreateMessage","message","UI_MESSAGE","inputParts","content","attachments","flatMap","a","map","c","name","parts","part","type","text","mediaType","image","url","data","mimeType","sourceType","audio","format","source","kind","id","undefined","Error","role","metadata"],"sources":["../../src/converters/toCreateMessage.ts"],"sourcesContent":["import type { AppendMessage } from \"@assistant-ui/core\";\nimport {\n resolveFileMediaType,\n resolveFilePartSource,\n resolveImageMediaType,\n toMediaWireUrl,\n} from \"@assistant-ui/core/internal\";\nimport type {\n CreateUIMessage,\n UIDataTypes,\n UIMessage,\n UIMessagePart,\n UITools,\n} from \"ai\";\n\ntype InputPart = AppendMessage[\"content\"][number] & {\n readonly contentType?: string | undefined;\n readonly filename?: string | undefined;\n};\n\nexport const toCreateMessage = <UI_MESSAGE extends UIMessage = UIMessage>(\n message: AppendMessage,\n): CreateUIMessage<UI_MESSAGE> => {\n const inputParts: InputPart[] = [\n ...message.content,\n ...(message.attachments?.flatMap((a) =>\n a.content.map((c) => ({\n ...c,\n filename: a.name,\n contentType: a.contentType,\n })),\n ) ?? []),\n ];\n\n const parts = inputParts.map((part): UIMessagePart<UIDataTypes, UITools> => {\n switch (part.type) {\n case \"text\":\n return {\n type: \"text\",\n text: part.text,\n };\n case \"image\": {\n const mediaType = resolveImageMediaType(part.image, part.contentType);\n return {\n type: \"file\",\n url: toMediaWireUrl(part.image, mediaType),\n ...(part.filename && { filename: part.filename }),\n mediaType,\n };\n }\n case \"file\": {\n // `mimeType` is a plain string, and an adapter reading `file.type` on a\n // file the OS cannot type yields \"\". Same ladder as images: declared,\n // then the envelope, then the floor.\n const mediaType = resolveFileMediaType(part.data, part.mimeType);\n return {\n type: \"file\",\n // An `id` reference is an opaque provider handle, not base64, and\n // this adapter has no way to send one. Left unwrapped so it fails\n // loudly upstream rather than shipping a corrupt payload.\n url:\n part.sourceType === \"id\"\n ? part.data\n : toMediaWireUrl(part.data, mediaType),\n mediaType,\n ...(part.filename && { filename: part.filename }),\n };\n }\n case \"audio\": {\n // A data URL's own media type wins over `mediaType` downstream, so the\n // envelope is rebuilt from the typed format rather than forwarded.\n const mediaType = `audio/${part.audio.format}`;\n const data = part.audio.data;\n const source = resolveFilePartSource({ data, mimeType: mediaType });\n return {\n type: \"file\",\n url:\n source.kind === \"url\"\n ? source.url\n : `data:${mediaType};base64,${source.data}`,\n mediaType,\n ...(part.filename && { filename: part.filename }),\n };\n }\n case \"data\":\n return {\n type: `data-${part.name}`,\n data: part.data,\n ...(part.id !== undefined && { id: part.id }),\n };\n default:\n throw new Error(`Unsupported part type: ${part.type}`);\n }\n });\n\n return {\n role: message.role,\n parts,\n metadata: message.metadata,\n } satisfies CreateUIMessage<UIMessage> as CreateUIMessage<UI_MESSAGE>;\n};\n"],"mappings":";;AAoBA,MAAaa,mBACXC,YACgC;CAYhC,MAAMU,QAAQR,CAVZ,GAAGF,QAAQG,SACX,GAAIH,QAAQI,aAAaC,SAASC,MAChCA,EAAEH,QAAQI,KAAKC,OAAO;EACpB,GAAGA;EACHV,UAAUQ,EAAEG;EACZZ,aAAaS,EAAET;CACjB,EAAE,CACJ,KAAK,CAAA,CAGOK,CAAU,CAACK,KAAKI,SAA8C;EAC1E,QAAQA,KAAKC,MAAb;GACE,KAAK,QACH,OAAO;IACLA,MAAM;IACNC,MAAMF,KAAKE;GACb;GACF,KAAK,SAAS;IACZ,MAAMC,YAAYzB,sBAAsBsB,KAAKI,OAAOJ,KAAKd,WAAW;IACpE,OAAO;KACLe,MAAM;KACNI,KAAK1B,eAAeqB,KAAKI,OAAOD,SAAS;KACzC,GAAIH,KAAKb,YAAY,EAAEA,UAAUa,KAAKb,SAAS;KAC/CgB;IACF;GACF;GACA,KAAK,QAAQ;IAIX,MAAMA,YAAY3B,qBAAqBwB,KAAKM,MAAMN,KAAKO,QAAQ;IAC/D,OAAO;KACLN,MAAM;KAINI,KACEL,KAAKQ,eAAe,OAChBR,KAAKM,OACL3B,eAAeqB,KAAKM,MAAMH,SAAS;KACzCA;KACA,GAAIH,KAAKb,YAAY,EAAEA,UAAUa,KAAKb,SAAS;IACjD;GACF;GACA,KAAK,SAAS;IAGZ,MAAMgB,YAAY,SAASH,KAAKS,MAAMC;IACtC,MAAMJ,OAAON,KAAKS,MAAMH;IACxB,MAAMK,SAASlC,sBAAsB;KAAE6B;KAAMC,UAAUJ;IAAU,CAAC;IAClE,OAAO;KACLF,MAAM;KACNI,KACEM,OAAOC,SAAS,QACZD,OAAON,MACP,QAAQF,UAAS,UAAWQ,OAAOL;KACzCH;KACA,GAAIH,KAAKb,YAAY,EAAEA,UAAUa,KAAKb,SAAS;IACjD;GACF;GACA,KAAK,QACH,OAAO;IACLc,MAAM,QAAQD,KAAKF;IACnBQ,MAAMN,KAAKM;IACX,GAAIN,KAAKa,OAAOC,KAAAA,KAAa,EAAED,IAAIb,KAAKa,GAAG;GAC7C;GACF,SACE,MAAM,IAAIE,MAAM,0BAA0Bf,KAAKC,MAAM;EACzD;CACF,CAAC;CAED,OAAO;EACLe,MAAM3B,QAAQ2B;EACdjB;EACAkB,UAAU5B,QAAQ4B;CACpB;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AISDKChat.js","names":["c","_c","resource","useResource","useState","generateId","UIMessage","RuntimeAdapter","runtimeAdapterTransformScopes","attachTransformScopes","useChatThread","ChatThreadOptions","AISDKChatOptions","UI_MESSAGE","useAISDKChat","options","$","t0","id","t1","initialize","remoteId","externalId","undefined","threadListItem","t2","t3","isMainThread","getThreadListItem","stopOnClientDestroy","runtime","t4","AISDKChat"],"sources":["../../src/runtime/AISDKChat.ts"],"sourcesContent":["\"use client\";\n\nimport { resource, useResource } from \"@assistant-ui/tap\";\nimport { useState } from \"react\";\nimport { generateId } from \"ai\";\nimport type { UIMessage } from \"@ai-sdk/react\";\nimport {\n RuntimeAdapter,\n runtimeAdapterTransformScopes,\n} from \"@assistant-ui/core/store\";\nimport { attachTransformScopes } from \"@assistant-ui/store/client\";\nimport { useChatThread, type ChatThreadOptions } from \"./useChatThread\";\n\nexport type AISDKChatOptions<UI_MESSAGE extends UIMessage = UIMessage> =\n ChatThreadOptions<UI_MESSAGE>;\n\nconst useAISDKChat = <UI_MESSAGE extends UIMessage = UIMessage>(\n options?: AISDKChatOptions<UI_MESSAGE>,\n) => {\n const [id] = useState(() => options?.id ?? generateId());\n const [threadListItem] = useState(() => ({\n initialize: async () => ({ remoteId: id, externalId: undefined }),\n }));\n const runtime = useChatThread(options, {\n id,\n isMainThread: true,\n getThreadListItem: () => threadListItem,\n stopOnClientDestroy: true,\n });\n return useResource(RuntimeAdapter(runtime));\n};\n\n/**\n * `AuiConfig` entry that runs the AI SDK chat as the `threads` scope. Hosts the\n * same orchestration as `useChatRuntime` inside the client's own resource tree,\n * so it works with any `AssistantClient` host, React or not. Single thread; the\n * multi-thread and assistant-cloud surface is {@link AISDKThreads}. The chat\n * id is captured when the entry mounts, so a later `id` change in the options\n * has no effect.\n */\nexport const AISDKChat = resource(useAISDKChat);\n\nattachTransformScopes(useAISDKChat, runtimeAdapterTransformScopes);\n"],"mappings":";;;;;;;;;AAgBA,MAAMc,gBAAeC,YAAA;CAAA,MAAAC,IAAAf,EAAA,EAAA;CAAA,IAAAgB;CAAA,IAAAD,EAAA,OAAAD,SAAAG,IAAA;EAGGD,WAAMF,SAAOG,MAAQb,WAAW;EAACW,EAAA,KAAAD,SAAAG;EAAAF,EAAA,KAAAC;CAAA,OAAAA,KAAAD,EAAA;CAAvD,MAAA,CAAAE,MAAad,SAASa,EAAiC;CAAE,IAAAE;CAAA,IAAAH,EAAA,OAAAE,IAAA;EACvBC,YAAO,EAAAC,YAC3B,aAAa;GAAAC,UAAYH;GAAEI,YAAcC,KAAAA;EAAU,GACjE;EAAEP,EAAA,KAAAE;EAAAF,EAAA,KAAAG;CAAA,OAAAA,KAAAH,EAAA;CAFF,MAAA,CAAAQ,kBAAyBpB,SAASe,EAEhC;CAAE,IAAAM;CAAA,IAAAT,EAAA,OAAAQ,gBAAA;EAIiBC,WAAMD;EAAcR,EAAA,KAAAQ;EAAAR,EAAA,KAAAS;CAAA,OAAAA,KAAAT,EAAA;CAAA,IAAAU;CAAA,IAAAV,EAAA,OAAAE,MAAAF,EAAA,OAAAS,IAAA;EAHFC,KAAA;GAAAR;GAAAS,cAEvB;GAAIC,mBACCH;GAAoBI,qBAClB;EACvB;EAACb,EAAA,KAAAE;EAAAF,EAAA,KAAAS;EAAAT,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CALD,MAAAc,UAAgBpB,cAAcK,SAASW,EAKtC;CAAE,IAAAK;CAAA,IAAAf,EAAA,OAAAc,SAAA;EACgBC,KAAAxB,eAAeuB,OAAO;EAACd,EAAA,KAAAc;EAAAd,EAAA,MAAAe;CAAA,OAAAA,KAAAf,EAAA;CAAA,OAAnCb,YAAY4B,EAAuB;AAAC;;;;;;;;;AAW7C,MAAaC,YAAY9B,SAASY,YAAY;AAE9CL,sBAAsBK,cAAcN,6BAA6B"}
|
|
1
|
+
{"version":3,"file":"AISDKChat.js","names":["c","_c","resource","useResource","useState","generateId","UIMessage","RuntimeAdapter","runtimeAdapterTransformScopes","attachTransformScopes","useChatThread","ChatThreadOptions","AISDKChatOptions","UI_MESSAGE","useAISDKChat","options","$","t0","id","t1","initialize","remoteId","externalId","undefined","threadListItem","t2","t3","isMainThread","getThreadListItem","stopOnClientDestroy","runtime","t4","AISDKChat","_c"],"sources":["../../src/runtime/AISDKChat.ts"],"sourcesContent":["\"use client\";\n\nimport { resource, useResource } from \"@assistant-ui/tap\";\nimport { useState } from \"react\";\nimport { generateId } from \"ai\";\nimport type { UIMessage } from \"@ai-sdk/react\";\nimport {\n RuntimeAdapter,\n runtimeAdapterTransformScopes,\n} from \"@assistant-ui/core/store\";\nimport { attachTransformScopes } from \"@assistant-ui/store/client\";\nimport { useChatThread, type ChatThreadOptions } from \"./useChatThread\";\n\nexport type AISDKChatOptions<UI_MESSAGE extends UIMessage = UIMessage> =\n ChatThreadOptions<UI_MESSAGE>;\n\nconst useAISDKChat = <UI_MESSAGE extends UIMessage = UIMessage>(\n options?: AISDKChatOptions<UI_MESSAGE>,\n) => {\n const [id] = useState(() => options?.id ?? generateId());\n const [threadListItem] = useState(() => ({\n initialize: async () => ({ remoteId: id, externalId: undefined }),\n }));\n const runtime = useChatThread(options, {\n id,\n isMainThread: true,\n getThreadListItem: () => threadListItem,\n stopOnClientDestroy: true,\n });\n return useResource(RuntimeAdapter(runtime));\n};\n\n/**\n * `AuiConfig` entry that runs the AI SDK chat as the `threads` scope. Hosts the\n * same orchestration as `useChatRuntime` inside the client's own resource tree,\n * so it works with any `AssistantClient` host, React or not. Single thread; the\n * multi-thread and assistant-cloud surface is {@link AISDKThreads}. The chat\n * id is captured when the entry mounts, so a later `id` change in the options\n * has no effect.\n */\nexport const AISDKChat = resource(useAISDKChat);\n\nattachTransformScopes(useAISDKChat, runtimeAdapterTransformScopes);\n"],"mappings":";;;;;;;;;AAgBA,MAAMc,gBAAeC,YAAA;CAAA,MAAAC,IAAAf,EAAA,EAAA;CAAA,IAAAgB;CAAA,IAAAD,EAAA,OAAAD,SAAAG,IAAA;EAGGD,WAAMF,SAAOG,MAAQb,WAAW;EAACW,EAAA,KAAAD,SAAAG;EAAAF,EAAA,KAAAC;CAAA,OAAAA,KAAAD,EAAA;CAAvD,MAAA,CAAAE,MAAad,SAASa,EAAiC;CAAE,IAAAE;CAAA,IAAAH,EAAA,OAAAE,IAAA;EACvBC,YAAO,EAAAC,YAC3B,aAAa;GAAAC,UAAYH;GAAEI,YAAcC,KAAAA;EAAU,GACjE;EAAEP,EAAA,KAAAE;EAAAF,EAAA,KAAAG;CAAA,OAAAA,KAAAH,EAAA;CAFF,MAAA,CAAAQ,kBAAyBpB,SAASe,EAEhC;CAAE,IAAAM;CAAA,IAAAT,EAAA,OAAAQ,gBAAA;EAIiBC,WAAMD;EAAcR,EAAA,KAAAQ;EAAAR,EAAA,KAAAS;CAAA,OAAAA,KAAAT,EAAA;CAAA,IAAAU;CAAA,IAAAV,EAAA,OAAAE,MAAAF,EAAA,OAAAS,IAAA;EAHFC,KAAA;GAAAR;GAAAS,cAEvB;GAAIC,mBACCH;GAAoBI,qBAClB;EACvB;EAACb,EAAA,KAAAE;EAAAF,EAAA,KAAAS;EAAAT,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CALD,MAAAc,UAAgBpB,cAAcK,SAASW,EAKtC;CAAE,IAAAK;CAAA,IAAAf,EAAA,OAAAc,SAAA;EACgBC,KAAAxB,eAAeuB,OAAO;EAACd,EAAA,KAAAc;EAAAd,EAAA,MAAAe;CAAA,OAAAA,KAAAf,EAAA;CAAA,OAAnCb,YAAY4B,EAAuB;AAAC;;;;;;;;;AAW7C,MAAaC,YAAY9B,SAASY,YAAY;AAE9CL,sBAAsBK,cAAcN,6BAA6B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AISDKThreads.js","names":["c","_c","resource","useResource","withKey","useEffect","useMemo","useState","Chat","UIMessage","ChatTransport","AssistantCloud","InMemoryThreadList","RemoteThreadList","inMemoryThreadListTransformScopes","ThreadClient","useCloudThreadListAdapter","attachTransformScopes","useAssistantClientRef","useAssistantScopeEffect","useAui","AssistantChatTransport","createChat","splitChatThreadOptions","useChatThread","ChatThreadOptions","MessageRepository","useResourceCleanup","AI_SDK_SDK","AISDKThreadsOptions","Omit","UI_MESSAGE","transport","cloud","threadId","onThreadIdChange","AISDKThreadChatOptions","ChatOptionsRef","current","ChatEntry","chat","repository","optionsRef","createChatEntry","options","chatInit","undefined","__internal_clone","id","getOrCreateChatEntry","chats","Map","existing","get","created","set","useAISDKChatThread","t0","$","t1","owned","t2","t3","t4","t5","stop","catch","_temp","aui","t6","initialize","remoteId","externalId","fallbackItem","t7","t8","threadListItem","source","t9","isMainThread","getThreadListItem","messageRepositoryInstance","stopOnClientDestroy","runtime","clientRef","t10","registerModelContextProvider","modelContext","t11","t12","thread","AISDKChatThread","useAISDKThreads","threadOptions","_temp2","bindCloud","values","_temp3","cloudAdapter","sdk","element","adapter","backgroundThreads","onDelete","id_0","_temp4","delete","AISDKThreads"],"sources":["../../src/runtime/AISDKThreads.ts"],"sourcesContent":["\"use client\";\n\nimport { resource, useResource, withKey } from \"@assistant-ui/tap\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { Chat, UIMessage } from \"@ai-sdk/react\";\nimport type { ChatTransport } from \"ai\";\nimport type { AssistantCloud } from \"assistant-cloud\";\nimport {\n InMemoryThreadList,\n RemoteThreadList,\n inMemoryThreadListTransformScopes,\n} from \"@assistant-ui/core/store\";\nimport { ThreadClient } from \"@assistant-ui/core/store/internal\";\nimport { useCloudThreadListAdapter } from \"@assistant-ui/core/react\";\nimport {\n attachTransformScopes,\n useAssistantClientRef,\n useAssistantScopeEffect,\n} from \"@assistant-ui/store/client\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { AssistantChatTransport } from \"../transport/AssistantChatTransport\";\nimport {\n createChat,\n splitChatThreadOptions,\n useChatThread,\n type ChatThreadOptions,\n} from \"./useChatThread\";\nimport { MessageRepository } from \"@assistant-ui/core/internal\";\nimport { useResourceCleanup } from \"./useResourceCleanup\";\nimport { AI_SDK_SDK } from \"./sdkIdentity\";\n\nexport type AISDKThreadsOptions<UI_MESSAGE extends UIMessage = UIMessage> =\n Omit<ChatThreadOptions<UI_MESSAGE>, \"id\" | \"transport\" | \"messages\"> & {\n /**\n * The transport threads send through. A factory is invoked once per\n * thread so each thread owns its instance. A plain\n * `AssistantChatTransport` instance is cloned per thread (its\n * assistant-ui wiring is per thread); any other transport instance is\n * shared as-is. Defaults to one `AssistantChatTransport` per thread.\n */\n transport?:\n | ChatTransport<UI_MESSAGE>\n | (() => ChatTransport<UI_MESSAGE>)\n | undefined;\n /**\n * When set, the thread list is a `RemoteThreadList` backed by this\n * assistant-cloud. Omit it to keep the in-memory list. Every visited\n * cloud thread stays mounted, so an in-flight run continues after a\n * switch and stops on delete; per-thread history loads once per thread.\n */\n cloud?: AssistantCloud | undefined;\n /**\n * Controlled thread id for the cloud list. Ignored without `cloud`.\n */\n threadId?: string | undefined;\n /**\n * Called with the settled remote id when the cloud list changes thread.\n */\n onThreadIdChange?: ((threadId: string | undefined) => void) | undefined;\n };\n\ntype AISDKThreadChatOptions<UI_MESSAGE extends UIMessage = UIMessage> = Omit<\n AISDKThreadsOptions<UI_MESSAGE>,\n \"cloud\" | \"threadId\" | \"onThreadIdChange\"\n>;\n\ntype ChatOptionsRef<UI_MESSAGE extends UIMessage> = {\n current: AISDKThreadChatOptions<UI_MESSAGE> | undefined;\n};\n\ntype ChatEntry<UI_MESSAGE extends UIMessage> = {\n chat: Chat<UI_MESSAGE>;\n transport: ChatTransport<UI_MESSAGE>;\n repository: MessageRepository;\n optionsRef: ChatOptionsRef<UI_MESSAGE>;\n};\n\nconst createChatEntry = <UI_MESSAGE extends UIMessage>(\n threadId: string,\n options: AISDKThreadChatOptions<UI_MESSAGE> | undefined,\n): ChatEntry<UI_MESSAGE> => {\n const optionsRef: ChatOptionsRef<UI_MESSAGE> = { current: options };\n const { chatInit } = splitChatThreadOptions(\n options as ChatThreadOptions<UI_MESSAGE> | undefined,\n );\n const transport =\n typeof options?.transport === \"function\"\n ? options.transport()\n : options?.transport === undefined\n ? new AssistantChatTransport()\n : options.transport instanceof AssistantChatTransport\n ? options.transport.__internal_clone()\n : options.transport;\n return {\n chat: createChat({ ...chatInit, id: threadId, transport }, optionsRef),\n transport,\n repository: new MessageRepository(),\n optionsRef,\n };\n};\n\nconst getOrCreateChatEntry = <UI_MESSAGE extends UIMessage>(\n threadId: string,\n options: AISDKThreadChatOptions<UI_MESSAGE> | undefined,\n chats: Map<string, ChatEntry<UI_MESSAGE>>,\n): ChatEntry<UI_MESSAGE> => {\n const existing = chats.get(threadId);\n if (existing) return existing;\n const created = createChatEntry(threadId, options);\n chats.set(threadId, created);\n return created;\n};\n\nconst useAISDKChatThread = <UI_MESSAGE extends UIMessage = UIMessage>({\n threadId,\n options,\n chats,\n cloud,\n}: {\n threadId: string;\n options: AISDKThreadChatOptions<UI_MESSAGE> | undefined;\n chats: Map<string, ChatEntry<UI_MESSAGE>>;\n cloud: boolean;\n}) => {\n const [owned] = useState(() =>\n cloud ? createChatEntry(threadId, options) : undefined,\n );\n const { chat, transport, repository, optionsRef } =\n owned ?? getOrCreateChatEntry(threadId, options, chats);\n\n useEffect(() => {\n if (cloud) optionsRef.current = options;\n });\n\n useEffect(() => {\n if (!cloud) return undefined;\n return () => {\n void chat.stop().catch(() => {});\n };\n }, [chat, cloud]);\n\n const aui = useAui();\n const fallbackItem = useMemo(\n () => ({\n initialize: async () => ({\n remoteId: threadId,\n externalId: undefined,\n }),\n }),\n [threadId],\n );\n const runtime = useChatThread(\n { ...options, transport } as ChatThreadOptions<UI_MESSAGE>,\n {\n id: threadId,\n isMainThread: true,\n getThreadListItem: () =>\n cloud\n ? aui.threadListItem.source\n ? aui.threadListItem\n : undefined\n : fallbackItem,\n chat,\n messageRepositoryInstance: repository,\n stopOnClientDestroy: false,\n },\n );\n\n const clientRef = useAssistantClientRef();\n useAssistantScopeEffect(\n \"modelContext\",\n () =>\n runtime.registerModelContextProvider(clientRef.current!.modelContext()),\n [runtime],\n );\n\n return useResource(ThreadClient({ runtime: runtime.thread }));\n};\n\nconst AISDKChatThread = resource(useAISDKChatThread);\n\nconst useAISDKThreads = <UI_MESSAGE extends UIMessage = UIMessage>(\n options?: AISDKThreadsOptions<UI_MESSAGE>,\n) => {\n const { cloud, threadId, onThreadIdChange, ...threadOptions } = options ?? {};\n const [chats] = useState(() => new Map<string, ChatEntry<UI_MESSAGE>>());\n const bindCloud = cloud !== undefined;\n\n useEffect(() => {\n for (const { optionsRef } of chats.values()) {\n optionsRef.current = threadOptions;\n }\n });\n\n useResourceCleanup(true, () => {\n for (const { chat } of chats.values()) {\n void chat.stop().catch(() => {});\n }\n });\n\n const cloudAdapter = useCloudThreadListAdapter({ cloud, sdk: AI_SDK_SDK });\n const thread = (id: string) => {\n const element = AISDKChatThread({\n threadId: id,\n options: threadOptions,\n chats,\n cloud: bindCloud,\n });\n return bindCloud ? withKey(id, element) : element;\n };\n\n return useResource(\n bindCloud\n ? RemoteThreadList({\n adapter: cloudAdapter,\n backgroundThreads: true,\n thread,\n threadId,\n onThreadIdChange,\n })\n : InMemoryThreadList({\n thread,\n onDelete: (id) => {\n void chats\n .get(id)\n ?.chat.stop()\n .catch(() => {});\n chats.delete(id);\n },\n }),\n );\n};\n\n/**\n * `AuiConfig` entry that runs one AI SDK chat per thread. Hosts the same\n * per-thread orchestration as {@link AISDKChat} inside the client's own\n * resource tree, so it works with any `AssistantClient` host, React or not.\n * Without `cloud`, threads live in memory for the client's lifetime and keep\n * their history across switches; only the visible thread is mounted, and a\n * switched-away chat keeps streaming into its stored state until it settles\n * or the thread is deleted. With `cloud`, the list is a\n * `RemoteThreadList` with `backgroundThreads`: every visited thread stays\n * mounted with its own history, a run continues after a switch and stops on\n * delete, and a freshly created thread titles itself. Model context is\n * registered on every mounted thread.\n */\nexport const AISDKThreads = resource(useAISDKThreads);\n\nattachTransformScopes(useAISDKThreads, inMemoryThreadListTransformScopes);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AISDKThreads.js","names":["c","_c","resource","useResource","withKey","useEffect","useMemo","useState","Chat","UIMessage","ChatTransport","AssistantCloud","InMemoryThreadList","RemoteThreadList","inMemoryThreadListTransformScopes","ThreadClient","useCloudThreadListAdapter","attachTransformScopes","useAssistantClientRef","useAssistantScopeEffect","useAui","AssistantChatTransport","createChat","splitChatThreadOptions","useChatThread","ChatThreadOptions","MessageRepository","useResourceCleanup","AI_SDK_SDK","AISDKThreadsOptions","Omit","UI_MESSAGE","transport","cloud","threadId","onThreadIdChange","AISDKThreadChatOptions","ChatOptionsRef","current","ChatEntry","chat","repository","optionsRef","createChatEntry","options","chatInit","undefined","__internal_clone","id","getOrCreateChatEntry","chats","Map","existing","get","created","set","useAISDKChatThread","t0","$","t1","owned","t2","t3","t4","t5","stop","catch","_temp","aui","t6","initialize","remoteId","externalId","fallbackItem","t7","t8","threadListItem","source","t9","isMainThread","getThreadListItem","messageRepositoryInstance","stopOnClientDestroy","runtime","clientRef","t10","registerModelContextProvider","modelContext","t11","t12","thread","AISDKChatThread","useAISDKThreads","threadOptions","_temp2","bindCloud","values","_temp3","cloudAdapter","sdk","element","adapter","backgroundThreads","onDelete","id_0","_temp4","delete","AISDKThreads","_c"],"sources":["../../src/runtime/AISDKThreads.ts"],"sourcesContent":["\"use client\";\n\nimport { resource, useResource, withKey } from \"@assistant-ui/tap\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { Chat, UIMessage } from \"@ai-sdk/react\";\nimport type { ChatTransport } from \"ai\";\nimport type { AssistantCloud } from \"assistant-cloud\";\nimport {\n InMemoryThreadList,\n RemoteThreadList,\n inMemoryThreadListTransformScopes,\n} from \"@assistant-ui/core/store\";\nimport { ThreadClient } from \"@assistant-ui/core/store/internal\";\nimport { useCloudThreadListAdapter } from \"@assistant-ui/core/react\";\nimport {\n attachTransformScopes,\n useAssistantClientRef,\n useAssistantScopeEffect,\n} from \"@assistant-ui/store/client\";\nimport { useAui } from \"@assistant-ui/store\";\nimport { AssistantChatTransport } from \"../transport/AssistantChatTransport\";\nimport {\n createChat,\n splitChatThreadOptions,\n useChatThread,\n type ChatThreadOptions,\n} from \"./useChatThread\";\nimport { MessageRepository } from \"@assistant-ui/core/internal\";\nimport { useResourceCleanup } from \"./useResourceCleanup\";\nimport { AI_SDK_SDK } from \"./sdkIdentity\";\n\nexport type AISDKThreadsOptions<UI_MESSAGE extends UIMessage = UIMessage> =\n Omit<ChatThreadOptions<UI_MESSAGE>, \"id\" | \"transport\" | \"messages\"> & {\n /**\n * The transport threads send through. A factory is invoked once per\n * thread so each thread owns its instance. A plain\n * `AssistantChatTransport` instance is cloned per thread (its\n * assistant-ui wiring is per thread); any other transport instance is\n * shared as-is. Defaults to one `AssistantChatTransport` per thread.\n */\n transport?:\n | ChatTransport<UI_MESSAGE>\n | (() => ChatTransport<UI_MESSAGE>)\n | undefined;\n /**\n * When set, the thread list is a `RemoteThreadList` backed by this\n * assistant-cloud. Omit it to keep the in-memory list. Every visited\n * cloud thread stays mounted, so an in-flight run continues after a\n * switch and stops on delete; per-thread history loads once per thread.\n */\n cloud?: AssistantCloud | undefined;\n /**\n * Controlled thread id for the cloud list. Ignored without `cloud`.\n */\n threadId?: string | undefined;\n /**\n * Called with the settled remote id when the cloud list changes thread.\n */\n onThreadIdChange?: ((threadId: string | undefined) => void) | undefined;\n };\n\ntype AISDKThreadChatOptions<UI_MESSAGE extends UIMessage = UIMessage> = Omit<\n AISDKThreadsOptions<UI_MESSAGE>,\n \"cloud\" | \"threadId\" | \"onThreadIdChange\"\n>;\n\ntype ChatOptionsRef<UI_MESSAGE extends UIMessage> = {\n current: AISDKThreadChatOptions<UI_MESSAGE> | undefined;\n};\n\ntype ChatEntry<UI_MESSAGE extends UIMessage> = {\n chat: Chat<UI_MESSAGE>;\n transport: ChatTransport<UI_MESSAGE>;\n repository: MessageRepository;\n optionsRef: ChatOptionsRef<UI_MESSAGE>;\n};\n\nconst createChatEntry = <UI_MESSAGE extends UIMessage>(\n threadId: string,\n options: AISDKThreadChatOptions<UI_MESSAGE> | undefined,\n): ChatEntry<UI_MESSAGE> => {\n const optionsRef: ChatOptionsRef<UI_MESSAGE> = { current: options };\n const { chatInit } = splitChatThreadOptions(\n options as ChatThreadOptions<UI_MESSAGE> | undefined,\n );\n const transport =\n typeof options?.transport === \"function\"\n ? options.transport()\n : options?.transport === undefined\n ? new AssistantChatTransport()\n : options.transport instanceof AssistantChatTransport\n ? options.transport.__internal_clone()\n : options.transport;\n return {\n chat: createChat({ ...chatInit, id: threadId, transport }, optionsRef),\n transport,\n repository: new MessageRepository(),\n optionsRef,\n };\n};\n\nconst getOrCreateChatEntry = <UI_MESSAGE extends UIMessage>(\n threadId: string,\n options: AISDKThreadChatOptions<UI_MESSAGE> | undefined,\n chats: Map<string, ChatEntry<UI_MESSAGE>>,\n): ChatEntry<UI_MESSAGE> => {\n const existing = chats.get(threadId);\n if (existing) return existing;\n const created = createChatEntry(threadId, options);\n chats.set(threadId, created);\n return created;\n};\n\nconst useAISDKChatThread = <UI_MESSAGE extends UIMessage = UIMessage>({\n threadId,\n options,\n chats,\n cloud,\n}: {\n threadId: string;\n options: AISDKThreadChatOptions<UI_MESSAGE> | undefined;\n chats: Map<string, ChatEntry<UI_MESSAGE>>;\n cloud: boolean;\n}) => {\n const [owned] = useState(() =>\n cloud ? createChatEntry(threadId, options) : undefined,\n );\n const { chat, transport, repository, optionsRef } =\n owned ?? getOrCreateChatEntry(threadId, options, chats);\n\n useEffect(() => {\n if (cloud) optionsRef.current = options;\n });\n\n useEffect(() => {\n if (!cloud) return undefined;\n return () => {\n void chat.stop().catch(() => {});\n };\n }, [chat, cloud]);\n\n const aui = useAui();\n const fallbackItem = useMemo(\n () => ({\n initialize: async () => ({\n remoteId: threadId,\n externalId: undefined,\n }),\n }),\n [threadId],\n );\n const runtime = useChatThread(\n { ...options, transport } as ChatThreadOptions<UI_MESSAGE>,\n {\n id: threadId,\n isMainThread: true,\n getThreadListItem: () =>\n cloud\n ? aui.threadListItem.source\n ? aui.threadListItem\n : undefined\n : fallbackItem,\n chat,\n messageRepositoryInstance: repository,\n stopOnClientDestroy: false,\n },\n );\n\n const clientRef = useAssistantClientRef();\n useAssistantScopeEffect(\n \"modelContext\",\n () =>\n runtime.registerModelContextProvider(clientRef.current!.modelContext()),\n [runtime],\n );\n\n return useResource(ThreadClient({ runtime: runtime.thread }));\n};\n\nconst AISDKChatThread = resource(useAISDKChatThread);\n\nconst useAISDKThreads = <UI_MESSAGE extends UIMessage = UIMessage>(\n options?: AISDKThreadsOptions<UI_MESSAGE>,\n) => {\n const { cloud, threadId, onThreadIdChange, ...threadOptions } = options ?? {};\n const [chats] = useState(() => new Map<string, ChatEntry<UI_MESSAGE>>());\n const bindCloud = cloud !== undefined;\n\n useEffect(() => {\n for (const { optionsRef } of chats.values()) {\n optionsRef.current = threadOptions;\n }\n });\n\n useResourceCleanup(true, () => {\n for (const { chat } of chats.values()) {\n void chat.stop().catch(() => {});\n }\n });\n\n const cloudAdapter = useCloudThreadListAdapter({ cloud, sdk: AI_SDK_SDK });\n const thread = (id: string) => {\n const element = AISDKChatThread({\n threadId: id,\n options: threadOptions,\n chats,\n cloud: bindCloud,\n });\n return bindCloud ? withKey(id, element) : element;\n };\n\n return useResource(\n bindCloud\n ? RemoteThreadList({\n adapter: cloudAdapter,\n backgroundThreads: true,\n thread,\n threadId,\n onThreadIdChange,\n })\n : InMemoryThreadList({\n thread,\n onDelete: (id) => {\n void chats\n .get(id)\n ?.chat.stop()\n .catch(() => {});\n chats.delete(id);\n },\n }),\n );\n};\n\n/**\n * `AuiConfig` entry that runs one AI SDK chat per thread. Hosts the same\n * per-thread orchestration as {@link AISDKChat} inside the client's own\n * resource tree, so it works with any `AssistantClient` host, React or not.\n * Without `cloud`, threads live in memory for the client's lifetime and keep\n * their history across switches; only the visible thread is mounted, and a\n * switched-away chat keeps streaming into its stored state until it settles\n * or the thread is deleted. With `cloud`, the list is a\n * `RemoteThreadList` with `backgroundThreads`: every visited thread stays\n * mounted with its own history, a run continues after a switch and stops on\n * delete, and a freshly created thread titles itself. Model context is\n * registered on every mounted thread.\n */\nexport const AISDKThreads = resource(useAISDKThreads);\n\nattachTransformScopes(useAISDKThreads, inMemoryThreadListTransformScopes);\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAISDKRuntime.js","names":["c","_c","useCallback","useEffect","useInsertionEffect","useMemo","useRef","useState","UIMessage","useChat","CreateUIMessage","UseChatHelpers","isToolUIPart","generateId","getToolName","useExternalStoreRuntime","useRuntimeAdapters","JoinStrategy","useReplaySafeEffect","SuggestionAdapter","ThreadSuggestion","ToolExecutionStatus","ExternalStoreAdapter","ExternalStoreSharedOptions","ThreadHistoryAdapter","AssistantRuntime","ThreadMessage","MessageFormatAdapter","MessageFormatItem","MessageFormatRepository","AppendMessage","RunConfig","McpAppMetadata","RespondToToolApprovalOptions","Unstable_ToolInteractionLog","getExternalStoreMessages","pickExternalStoreSharedOptions","appendToolInteraction","consumeSuggestionResult","MessageRepository","ReadonlyJSONObject","AssistantError","sliceMessagesUntil","toCreateMessage","vercelAttachmentAdapter","getVercelAIMessages","AISDKMessageConverter","AISDKMessageConverterMetadata","wrapModelContentEnvelope","AISDKStorageFormat","aiSDKV6FormatAdapter","useExternalHistory","toExportedMessageRepository","useStreamingTiming","aiSDKExtras","CustomToCreateMessageFunction","message","UI_MESSAGE","toUIMessage","createMessage","fallbackRole","id","role","toVoiceTranscriptUIMessage","parts","content","filter","part","type","map","text","metadata","modality","Object","keys","custom","length","AISDKRuntimeAdapter","adapters","NonNullable","history","suggestion","unstable_messageRepositoryInstance","unstable_hostApprovalOwner","cancelPendingToolCallsOnSend","onResume","onResumeToolCall","onRespondToToolApproval","response","context","toolCallId","toolName","respondViaAISDK","Promise","joinStrategy","messageRepository","unstable_onBranchChange","EMPTY_SUGGESTIONS","useGeneratedSuggestions","suggestionAdapter","messages","isRunning","$","suggestions","setSuggestions","controllerRef","wasRunningRef","messagesRef","t0","t1","current","adapterRef","t2","t3","hasAdapter","t4","clearSuggestions","abort","_temp","adapter","currentMessages","last","at","status","controller","AbortController","signal","promiseOrGenerator","generate","onUpdate","t5","t6","t7","Symbol","for","NO_CANCELLED_MESSAGE_IDS","ReadonlySet","Set","NO_SUPERSEDED_APPROVAL_PROJECTION","freeze","approvalIds","statusMessageIds","NO_TOOL_APPROVAL_RESPONSES","ReadonlyMap","Map","OwnedApproval","hostToolApprovalsByChat","WeakMap","toApprovalResponses","owned","size","entry","hostApprovalListenersByChat","subscribeToHostApprovals","owner","listener","listeners","get","set","add","delete","notifyHostApprovals","getSupersededApprovalProjection","hostApprovalIds","lastIndex","lastAssistant","hasSupersededApproval","previousWasVoice","flush","hasOpenToolPart","some","state","approval","resolution","descriptor","undefined","index","isVoice","approvalId","has","findRawToolMessageIndex","messageId","containsToolCall","messageIndex","findIndex","start","end","toChatError","error","Error","code","name","useAISDKRuntime","chatHelpers","ReturnType","customToCreateMessage","customOnRespondToToolApproval","contextAdapters","toolStatuses","setToolStatuses","Record","cancelledMessages","setCancelledMessages","chatId","ids","approvalOwner","ownedApprovals","created","toolApprovalResponses","setToolApprovalResponses","toolArtifactEpoch","setToolArtifactEpoch","toolInteractionEpoch","setToolInteractionEpoch","toolApprovalResponsesRef","ownedApprovalIdsRef","hostApprovalIdsRef","sync","prev","next","unchanged","every","unsubscribe","lastApprovalOwnerRef","toolArgsKeyOrderCacheRef","toolLastInputCacheRef","toolArgsTextCacheRef","mcpAppMetadataCacheRef","toolArtifactsRef","toolInteractionsRef","lastRunConfigRef","markToolArtifactsChanged","epoch","markToolInteractionsChanged","hasExecutingTools","values","s","providerIsRunning","wasProviderRunningRef","messageTiming","lastMessage","optimisticMessageId","cancelledMessageIds","supportsRichToolApprovalResponses","supersededApprovalProjectionRef","supersededApprovalProjection","projection","previous","toThreadMessages","sourceMessages","toolArtifacts","toolInteractions","retractCancellation","resumedMessageId","wasProviderRunning","useThreadMessages","toolArgsKeyOrderCache","toolArgsTextCache","toolLastInputCache","mcpAppMetadataCache","cancelledToolApprovalIds","cancelledStatusMessageIds","exportedMessageRepository","converted","generatedSuggestions","runtimeRef","runtime","isLoading","deleteMessage","deleteHistoryMessage","persistToolInteractions","persistToolApprovalResponses","setMessages","chatMessages","chatStatus","extras","provide","chat","completePendingToolCalls","hasChanges","messageChanged","_approval","rest","const","errorText","approved","reason","resolve","addToolApprovalResponse","options","respondViaHost","onRespond","requested","flatMap","find","startedWith","startedOwner","startedResponses","isApplied","applyResponse","applied","remainsApplied","hasSeededRepositoryRef","shouldFeedRepository","unstable_persistsHistory","unstable_enableToolInvocations","Boolean","flat","onImport","onVoiceTranscript","onExportExternalState","exported","thread","export","expandedMessages","lastInnerIdMap","item","innerMessages","parentId","innerMessage","push","getId","result","headId","onLoadExternalState","repo","exportedRepo","import","onCancel","cancelledId","liveIds","m","kept","stop","onNew","startRun","runConfig","sendMessage","onEdit","onDelete","threadMessages","getState","removedToolArtifact","removedToolInteractions","removedToolApprovalResponse","removedHostApprovalId","deleteIds","onReload","config","newMessages","regenerate","onAddToolResult","isError","artifact","modelContent","targetIndex","JSON","stringify","output","target","targetPart","preliminary","targetMessageId","_preliminary","finalPart","addToolOutput","tool","reject","unstable_onRecordToolInteraction","interaction","attachments","setMessagesRef","tempRepo","getMessages"],"sources":["../../src/runtime/useAISDKRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useInsertionEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type {\n UIMessage,\n useChat,\n CreateUIMessage,\n UseChatHelpers,\n} from \"@ai-sdk/react\";\nimport { isToolUIPart, generateId, getToolName } from \"ai\";\nimport {\n useExternalStoreRuntime,\n useRuntimeAdapters,\n type JoinStrategy,\n} from \"@assistant-ui/core/react\";\nimport { useReplaySafeEffect } from \"@assistant-ui/store/internal\";\nimport type {\n SuggestionAdapter,\n ThreadSuggestion,\n ToolExecutionStatus,\n} from \"@assistant-ui/core\";\nimport type {\n ExternalStoreAdapter,\n ExternalStoreSharedOptions,\n ThreadHistoryAdapter,\n AssistantRuntime,\n ThreadMessage,\n MessageFormatAdapter,\n MessageFormatItem,\n MessageFormatRepository,\n AppendMessage,\n RunConfig,\n McpAppMetadata,\n RespondToToolApprovalOptions,\n Unstable_ToolInteractionLog,\n} from \"@assistant-ui/core\";\nimport {\n getExternalStoreMessages,\n pickExternalStoreSharedOptions,\n} from \"@assistant-ui/core\";\nimport {\n appendToolInteraction,\n consumeSuggestionResult,\n MessageRepository,\n} from \"@assistant-ui/core/internal\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\nimport type { AssistantError } from \"@assistant-ui/core\";\nimport { sliceMessagesUntil } from \"../utils/sliceMessagesUntil\";\nimport { toCreateMessage } from \"../converters/toCreateMessage\";\nimport { vercelAttachmentAdapter } from \"../adapters/vercelAttachmentAdapter\";\nimport { getVercelAIMessages } from \"../utils/getVercelAIMessages\";\nimport {\n AISDKMessageConverter,\n type AISDKMessageConverterMetadata,\n} from \"../converters/convertMessage\";\nimport { wrapModelContentEnvelope } from \"../converters/modelContentEnvelope\";\nimport {\n type AISDKStorageFormat,\n aiSDKV6FormatAdapter,\n} from \"../adapters/aiSDKFormatAdapter\";\nimport {\n useExternalHistory,\n toExportedMessageRepository,\n} from \"./useExternalHistory\";\nimport { useStreamingTiming } from \"./useStreamingTiming\";\nimport { aiSDKExtras } from \"../aiSDKExtras\";\n\nexport type CustomToCreateMessageFunction = <\n UI_MESSAGE extends UIMessage = UIMessage,\n>(\n message: AppendMessage,\n) => CreateUIMessage<UI_MESSAGE>;\n\nconst toUIMessage = <UI_MESSAGE extends UIMessage>(\n createMessage: CreateUIMessage<UI_MESSAGE>,\n fallbackRole: UI_MESSAGE[\"role\"],\n): UI_MESSAGE =>\n ({\n ...createMessage,\n id: createMessage.id ?? generateId(),\n role: createMessage.role ?? fallbackRole,\n }) as UI_MESSAGE;\n\nconst toVoiceTranscriptUIMessage = <UI_MESSAGE extends UIMessage>(\n message: ThreadMessage,\n): UI_MESSAGE =>\n ({\n id: message.id,\n role: message.role,\n parts: message.content\n .filter((part) => part.type === \"text\")\n .map((part) => ({ type: \"text\", text: part.text })),\n metadata: {\n ...(message.metadata.modality && { modality: message.metadata.modality }),\n ...(Object.keys(message.metadata.custom).length > 0 && {\n custom: message.metadata.custom,\n }),\n },\n }) as UI_MESSAGE;\n\nexport type AISDKRuntimeAdapter<UI_MESSAGE extends UIMessage = UIMessage> =\n ExternalStoreSharedOptions & {\n adapters?:\n | (NonNullable<ExternalStoreAdapter[\"adapters\"]> & {\n history?: ThreadHistoryAdapter | undefined;\n suggestion?: SuggestionAdapter | undefined;\n })\n | undefined;\n toCreateMessage?: CustomToCreateMessageFunction;\n unstable_messageRepositoryInstance?: MessageRepository | undefined;\n /**\n * The object a host answer belongs to, normally the `Chat` the runtime\n * renders. A host answer never reaches the `useChat` messages, so without\n * an owner it lives only as long as this runtime. With an owner, it\n * survives runtime remounts over the same chat.\n */\n unstable_hostApprovalOwner?: object | undefined;\n /**\n * Whether to automatically cancel pending interactive tool calls when the user sends a new message.\n *\n * When enabled (default), the pending tool calls will be marked as failed with an error message\n * indicating the user cancelled the tool call by sending a new message.\n *\n * @default true\n */\n cancelPendingToolCallsOnSend?: boolean | undefined;\n /**\n * Called when `runtime.thread.resumeRun(config)` is invoked.\n *\n * When omitted, `resumeRun` throws `\"Runtime does not support resuming runs.\"`.\n * Provide this to bridge resume invocations into a custom replay channel\n * (for example, an SSE reconnect endpoint keyed by turn id).\n */\n onResume?: ExternalStoreAdapter[\"onResume\"];\n /**\n * Called when `runtime.thread.resumeToolCall(options)` is invoked for a tool call the in-process tracker does not own.\n *\n * When omitted, `resumeToolCall` throws `\"Tool call ${toolCallId} is not waiting for resume.\"`.\n * Provide this to bridge resume-tool-call invocations into a custom handler.\n */\n onResumeToolCall?: ExternalStoreAdapter[\"onResumeToolCall\"];\n /**\n * Answers tool approval requests through a host-owned channel instead of the AI SDK's `addToolApprovalResponse`.\n *\n * Called for every approval request in the thread with the complete response, including option and free-form answers. Hand requests the host does not own to `respondViaAISDK`, which is what runs when this option is omitted. The answer applies to the approval when the handler starts and is removed if it throws. It is never written into the `useChat` messages, so `sendAutomaticallyWhen` cannot forward it. With a history adapter, the answer is stored with its message once the handler resolves and returns on reload. With `unstable_hostApprovalOwner`, in-memory answers survive runtime remounts over the same chat; without an owner or history adapter, they last only as long as the runtime. Bring the resumed run back into the chat, for example with `resumeStream`, and have the endpoint refuse a second resume.\n *\n * While a handler is set, an approval's `display`, `allowFreeform`, `dismissible` and `options` reach the renderer, because the handler can receive answers the AI SDK cannot carry. A stream declares them through the `approvalDescriptor` of its `tool-approval-request` chunk, the one approval field the AI SDK keeps opaque; the converter reads the request and answer fields from that descriptor when the approval itself lacks them.\n */\n onRespondToToolApproval?:\n | ((\n response: RespondToToolApprovalOptions,\n context: {\n toolCallId: string;\n toolName: string;\n /** Sends this response through the AI SDK's `addToolApprovalResponse`, which carries only `approved` and `reason`. */\n respondViaAISDK: () => Promise<void>;\n },\n ) => Promise<void> | void)\n | undefined;\n /**\n * How consecutive assistant messages are rendered.\n *\n * `\"concat-content\"` (the default) merges them into a single thread message.\n * `\"none\"` keeps each assistant message as its own thread message, which is\n * useful when a backend persists proactive or consecutive assistant messages\n * as separate entries.\n */\n joinStrategy?: JoinStrategy | undefined;\n /**\n * A branch-aware AI SDK message tree seeded once when `useChat` is empty.\n * After that seed, live updates come only from `useChat`. A later empty\n * chat or a new object identity does not reload the tree.\n */\n messageRepository?: MessageFormatRepository<UI_MESSAGE>;\n /**\n * Called after an explicit `switchToBranch` (for example a BranchPicker\n * click). Complements `setMessages` and does not enable switching by itself.\n *\n * @deprecated This API is still under active development and might change without notice.\n */\n unstable_onBranchChange?: ExternalStoreAdapter[\"unstable_onBranchChange\"];\n };\n\nconst EMPTY_SUGGESTIONS: readonly ThreadSuggestion[] = [];\n\nconst useGeneratedSuggestions = (\n suggestionAdapter: SuggestionAdapter | undefined,\n messages: readonly ThreadMessage[],\n isRunning: boolean,\n): readonly ThreadSuggestion[] => {\n const [suggestions, setSuggestions] =\n useState<readonly ThreadSuggestion[]>(EMPTY_SUGGESTIONS);\n const controllerRef = useRef<AbortController | null>(null);\n const wasRunningRef = useRef(false);\n const messagesRef = useRef(messages);\n useInsertionEffect(() => {\n messagesRef.current = messages;\n }, [messages]);\n const adapterRef = useRef(suggestionAdapter);\n useInsertionEffect(() => {\n adapterRef.current = suggestionAdapter;\n }, [suggestionAdapter]);\n const hasAdapter = suggestionAdapter != null;\n\n useEffect(() => {\n const clearSuggestions = () => {\n controllerRef.current?.abort();\n controllerRef.current = null;\n setSuggestions((prev) => (prev.length === 0 ? prev : EMPTY_SUGGESTIONS));\n };\n\n const adapter = adapterRef.current;\n if (!adapter) {\n clearSuggestions();\n wasRunningRef.current = isRunning;\n return;\n }\n\n if (isRunning) {\n if (!wasRunningRef.current) {\n clearSuggestions();\n }\n wasRunningRef.current = true;\n return;\n }\n\n if (!wasRunningRef.current) return;\n wasRunningRef.current = false;\n\n const currentMessages = messagesRef.current;\n const last = currentMessages.at(-1);\n if (last?.role !== \"assistant\") return;\n if (last.status?.type === \"requires-action\") return;\n\n const controller = new AbortController();\n controllerRef.current = controller;\n const { signal } = controller;\n\n void (async () => {\n try {\n const promiseOrGenerator = adapter.generate({\n messages: currentMessages,\n signal,\n });\n\n await consumeSuggestionResult(promiseOrGenerator, {\n signal,\n onUpdate: setSuggestions,\n });\n } catch {}\n })();\n }, [hasAdapter, isRunning]);\n\n useReplaySafeEffect(() => {\n return () => {\n controllerRef.current?.abort();\n };\n }, []);\n\n return suggestions;\n};\n\nconst NO_CANCELLED_MESSAGE_IDS: ReadonlySet<string> = new Set();\n\nconst NO_SUPERSEDED_APPROVAL_PROJECTION = Object.freeze({\n approvalIds: Object.freeze(new Set<string>()),\n statusMessageIds: Object.freeze(new Set<string>()),\n});\n\nconst NO_TOOL_APPROVAL_RESPONSES: ReadonlyMap<\n string,\n RespondToToolApprovalOptions\n> = new Map();\n\n/**\n * A host answer is deliberately kept out of the `useChat` messages, so nothing\n * in the chat records it. Held in runtime state it would die with the runtime,\n * and a runtime mounted again over the same chat would show the request open\n * and take a second answer. Keyed on the chat instead, the answer lives as\n * long as the chat it belongs to, and is collected with it.\n */\ntype OwnedApproval = {\n response: RespondToToolApprovalOptions;\n};\n\nconst hostToolApprovalsByChat = new WeakMap<\n object,\n Map<string, OwnedApproval>\n>();\n\nconst toApprovalResponses = (\n owned: ReadonlyMap<string, OwnedApproval> | undefined,\n): ReadonlyMap<string, RespondToToolApprovalOptions> =>\n owned && owned.size > 0\n ? new Map([...owned].map(([id, entry]) => [id, entry.response]))\n : NO_TOOL_APPROVAL_RESPONSES;\n\n/**\n * The answers live on the owner, but each mounted runtime renders them from\n * its own state, so a write has to be announced: the runtime that performed it\n * may already be unmounted (a rollback resolving after a remount), and another\n * runtime may be mounted over the same owner.\n */\nconst hostApprovalListenersByChat = new WeakMap<object, Set<() => void>>();\n\nconst subscribeToHostApprovals = (owner: object, listener: () => void) => {\n const listeners = hostApprovalListenersByChat.get(owner) ?? new Set();\n hostApprovalListenersByChat.set(owner, listeners);\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\n\nconst notifyHostApprovals = (owner: object) => {\n for (const listener of [...(hostApprovalListenersByChat.get(owner) ?? [])]) {\n listener();\n }\n};\n\nconst getSupersededApprovalProjection = <UI_MESSAGE extends UIMessage>(\n messages: readonly UI_MESSAGE[],\n hostApprovalIds: ReadonlySet<string>,\n joinStrategy: JoinStrategy | undefined,\n isRunning: boolean,\n) => {\n const approvalIds = new Set<string>();\n const statusMessageIds = new Set<string>();\n const lastIndex = messages.length - 1;\n let lastAssistant: UI_MESSAGE | undefined;\n let hasSupersededApproval = false;\n let previousWasVoice = false;\n\n const flush = () => {\n const hasOpenToolPart =\n lastAssistant === messages[lastIndex] &&\n lastAssistant?.parts?.some((part) => {\n if (\n !isToolUIPart(part) ||\n part.state === \"output-available\" ||\n part.state === \"output-error\" ||\n part.state === \"output-denied\"\n )\n return false;\n\n const approval = (\n part as {\n approval?: {\n resolution?: unknown;\n descriptor?: unknown;\n };\n }\n ).approval;\n const resolution =\n approval?.resolution ??\n (approval?.descriptor as { resolution?: unknown } | undefined)\n ?.resolution;\n return resolution !== \"cancelled\" && resolution !== \"expired\";\n });\n if (\n lastAssistant &&\n hasSupersededApproval &&\n !hasOpenToolPart &&\n !(isRunning && lastAssistant === messages[lastIndex])\n ) {\n statusMessageIds.add(lastAssistant.id);\n }\n lastAssistant = undefined;\n hasSupersededApproval = false;\n previousWasVoice = false;\n };\n\n for (let index = 0; index < messages.length; index++) {\n const message = messages[index]!;\n if (message.role !== \"assistant\") {\n flush();\n } else {\n const isVoice =\n (message.metadata as { modality?: unknown } | undefined)?.modality ===\n \"voice\";\n if (isVoice || previousWasVoice || joinStrategy === \"none\") flush();\n lastAssistant = message;\n previousWasVoice = isVoice;\n }\n\n for (const part of message.parts ?? []) {\n if (!isToolUIPart(part) || part.state !== \"approval-requested\") continue;\n\n const approval = part.approval;\n if (!approval) continue;\n\n const approvalId = approval.id;\n if (hostApprovalIds.has(approvalId)) continue;\n\n const resolution =\n (approval as { resolution?: unknown }).resolution ??\n (approval.descriptor as { resolution?: unknown } | null | undefined)\n ?.resolution;\n if (resolution === \"cancelled\" || resolution === \"expired\") continue;\n\n if (index !== lastIndex) {\n approvalIds.add(approvalId);\n if (message.role === \"assistant\") hasSupersededApproval = true;\n }\n }\n }\n flush();\n\n if (approvalIds.size === 0 && statusMessageIds.size === 0)\n return NO_SUPERSEDED_APPROVAL_PROJECTION;\n\n return { approvalIds, statusMessageIds };\n};\n\nconst findRawToolMessageIndex = <UI_MESSAGE extends UIMessage>(\n messages: readonly UI_MESSAGE[],\n messageId: string,\n toolCallId: string,\n joinStrategy: JoinStrategy | undefined,\n) => {\n const containsToolCall = (message: UI_MESSAGE) =>\n message.parts?.some(\n (part) => isToolUIPart(part) && part.toolCallId === toolCallId,\n ) === true;\n\n const messageIndex = messages.findIndex(\n (message) => message.id === messageId,\n );\n if (messageIndex === -1) return -1;\n if (containsToolCall(messages[messageIndex]!)) return messageIndex;\n if (joinStrategy === \"none\" || messages[messageIndex]?.role !== \"assistant\")\n return -1;\n\n let start = messageIndex;\n while (start > 0 && messages[start - 1]?.role === \"assistant\") start--;\n\n let end = messageIndex;\n while (end + 1 < messages.length && messages[end + 1]?.role === \"assistant\")\n end++;\n\n for (let index = start; index <= end; index++) {\n if (containsToolCall(messages[index]!)) return index;\n }\n return -1;\n};\n\nconst toChatError = (error: Error): AssistantError => {\n const code = (error as { code?: unknown }).code;\n return {\n code:\n typeof code === \"string\"\n ? code\n : error.name !== \"Error\"\n ? error.name\n : \"unknown\",\n message: error.message,\n };\n};\n\nexport const useAISDKRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(\n chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>,\n adapter: AISDKRuntimeAdapter<UI_MESSAGE> = {},\n) => {\n const {\n adapters,\n toCreateMessage: customToCreateMessage,\n cancelPendingToolCallsOnSend = true,\n onResume,\n onResumeToolCall,\n onRespondToToolApproval: customOnRespondToToolApproval,\n joinStrategy,\n messageRepository,\n unstable_onBranchChange,\n } = adapter;\n const suggestionAdapter = adapters?.suggestion;\n const contextAdapters = useRuntimeAdapters();\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n const [cancelledMessages, setCancelledMessages] = useState<{\n chatId: string;\n ids: ReadonlySet<string>;\n } | null>(null);\n // Set by hosts that own the chat across runtime lifetimes, so a host answer\n // outlives a remount over that same chat.\n const approvalOwner = adapter.unstable_hostApprovalOwner;\n const ownedApprovals = approvalOwner\n ? (hostToolApprovalsByChat.get(approvalOwner) ??\n (() => {\n const created = new Map<string, OwnedApproval>();\n hostToolApprovalsByChat.set(approvalOwner, created);\n return created;\n })())\n : undefined;\n const [toolApprovalResponses, setToolApprovalResponses] = useState<\n ReadonlyMap<string, RespondToToolApprovalOptions>\n >(() => toApprovalResponses(ownedApprovals));\n const [toolArtifactEpoch, setToolArtifactEpoch] = useState(0);\n const [toolInteractionEpoch, setToolInteractionEpoch] = useState(0);\n const toolApprovalResponsesRef = useRef(\n new Map(toApprovalResponses(ownedApprovals)),\n );\n const ownedApprovalIdsRef = useRef(new Set(ownedApprovals?.keys()));\n const hostApprovalIdsRef = useRef(new Set<string>(ownedApprovals?.keys()));\n\n // The owner's record is shared, so this runtime re-reads it whenever it is\n // written rather than only at mount: the write may come from a runtime that\n // has since unmounted, or from another runtime mounted over the same owner.\n useEffect(() => {\n if (!approvalOwner || !ownedApprovals) return undefined;\n const sync = () => {\n for (const id of ownedApprovalIdsRef.current)\n toolApprovalResponsesRef.current.delete(id);\n for (const [id, entry] of ownedApprovals)\n toolApprovalResponsesRef.current.set(id, entry.response);\n ownedApprovalIdsRef.current = new Set(ownedApprovals.keys());\n hostApprovalIdsRef.current = new Set(\n toolApprovalResponsesRef.current.keys(),\n );\n setToolApprovalResponses((prev) => {\n const next = new Map(toolApprovalResponsesRef.current);\n const unchanged =\n prev.size === next.size &&\n [...next].every(([id, response]) => prev.get(id) === response);\n return unchanged ? prev : next;\n });\n };\n const unsubscribe = subscribeToHostApprovals(approvalOwner, sync);\n // The state was seeded during render, so a write landing between then and\n // this subscription would otherwise never be seen.\n sync();\n return unsubscribe;\n }, [approvalOwner, ownedApprovals]);\n\n // A runtime kept mounted across a change of owner must not carry the\n // previous chat's answers: a reused approval id would render as already\n // answered and reject a genuine response.\n const lastApprovalOwnerRef = useRef(approvalOwner);\n if (lastApprovalOwnerRef.current !== approvalOwner) {\n lastApprovalOwnerRef.current = approvalOwner;\n hostApprovalIdsRef.current = new Set<string>(ownedApprovals?.keys());\n toolApprovalResponsesRef.current = new Map(\n toApprovalResponses(ownedApprovals),\n );\n ownedApprovalIdsRef.current = new Set(ownedApprovals?.keys());\n setToolApprovalResponses(new Map(toolApprovalResponsesRef.current));\n }\n const toolArgsKeyOrderCacheRef = useRef<Map<string, Map<string, string[]>>>(\n new Map(),\n );\n const toolLastInputCacheRef = useRef<Map<string, ReadonlyJSONObject>>(\n new Map(),\n );\n const toolArgsTextCacheRef = useRef<\n WeakMap<ReadonlyJSONObject, Map<string, string>>\n >(new WeakMap());\n const mcpAppMetadataCacheRef = useRef<Map<string, McpAppMetadata>>(new Map());\n const toolArtifactsRef = useRef<Map<string, unknown>>(new Map());\n const toolInteractionsRef = useRef<Map<string, Unstable_ToolInteractionLog>>(\n new Map(),\n );\n const lastRunConfigRef = useRef<RunConfig | undefined>(undefined);\n const markToolArtifactsChanged = useCallback(() => {\n setToolArtifactEpoch((epoch) => epoch + 1);\n }, []);\n const markToolInteractionsChanged = useCallback(() => {\n setToolInteractionEpoch((epoch) => epoch + 1);\n }, []);\n\n const hasExecutingTools = Object.values(toolStatuses).some(\n (s) => s?.type === \"executing\",\n );\n const providerIsRunning =\n chatHelpers.status === \"submitted\" || chatHelpers.status === \"streaming\";\n const isRunning = providerIsRunning || hasExecutingTools;\n const wasProviderRunningRef = useRef(providerIsRunning);\n\n const messageTiming = useStreamingTiming(chatHelpers.messages, isRunning);\n\n // Flag the streaming message optimistic: its id can be swapped for a server\n // id mid-run, and the repository then drops the orphaned pre-swap id (#4037).\n const lastMessage = chatHelpers.messages.at(-1);\n const optimisticMessageId =\n isRunning && lastMessage?.role === \"assistant\" ? lastMessage.id : undefined;\n\n const cancelledMessageIds =\n cancelledMessages?.chatId === chatHelpers.id\n ? cancelledMessages.ids\n : NO_CANCELLED_MESSAGE_IDS;\n const supportsRichToolApprovalResponses =\n customOnRespondToToolApproval != null;\n const supersededApprovalProjectionRef = useRef(\n NO_SUPERSEDED_APPROVAL_PROJECTION,\n );\n const supersededApprovalProjection = useMemo(\n () => {\n const projection = getSupersededApprovalProjection(\n chatHelpers.messages,\n hostApprovalIdsRef.current,\n joinStrategy,\n isRunning,\n );\n const previous = supersededApprovalProjectionRef.current;\n if (\n projection.approvalIds.size === previous.approvalIds.size &&\n projection.statusMessageIds.size === previous.statusMessageIds.size &&\n [...projection.approvalIds].every((id) =>\n previous.approvalIds.has(id),\n ) &&\n [...projection.statusMessageIds].every((id) =>\n previous.statusMessageIds.has(id),\n )\n )\n return previous;\n\n supersededApprovalProjectionRef.current = projection;\n return projection;\n },\n // oxlint-disable-next-line react/exhaustive-deps -- hostApprovalIdsRef changes alongside toolApprovalResponses, which invalidates the projection\n [chatHelpers.messages, joinStrategy, isRunning, toolApprovalResponses],\n );\n\n const toThreadMessages = useCallback(\n (sourceMessages: UI_MESSAGE[]) => {\n const metadata: AISDKMessageConverterMetadata = {\n supportsRichToolApprovalResponses,\n toolArtifacts: toolArtifactsRef.current,\n toolInteractions: toolInteractionsRef.current,\n toolApprovalResponses: toolApprovalResponsesRef.current,\n };\n return AISDKMessageConverter.toThreadMessages(\n sourceMessages,\n false,\n metadata,\n );\n },\n [supportsRichToolApprovalResponses],\n );\n\n const retractCancellation = useCallback(\n (chatId: string, messageId: string) => {\n setCancelledMessages((prev) => {\n if (prev?.chatId !== chatId || !prev.ids.has(messageId)) return prev;\n const ids = new Set(prev.ids);\n ids.delete(messageId);\n return { chatId, ids };\n });\n },\n [],\n );\n\n // A provider run that resumes the stopped response retracts its cancellation;\n // a run that starts a new response leaves the stopped one marked.\n const resumedMessageId =\n providerIsRunning && lastMessage?.role === \"assistant\"\n ? lastMessage.id\n : undefined;\n\n useEffect(() => {\n const wasProviderRunning = wasProviderRunningRef.current;\n wasProviderRunningRef.current = providerIsRunning;\n if (wasProviderRunning || !resumedMessageId) return;\n retractCancellation(chatHelpers.id, resumedMessageId);\n }, [\n providerIsRunning,\n resumedMessageId,\n chatHelpers.id,\n retractCancellation,\n ]);\n\n const messages = AISDKMessageConverter.useThreadMessages({\n isRunning,\n messages: chatHelpers.messages,\n joinStrategy,\n metadata: useMemo<AISDKMessageConverterMetadata>(\n () => ({\n toolStatuses,\n messageTiming,\n toolArgsKeyOrderCache: toolArgsKeyOrderCacheRef.current,\n toolArgsTextCache: toolArgsTextCacheRef.current,\n toolLastInputCache: toolLastInputCacheRef.current,\n mcpAppMetadataCache: mcpAppMetadataCacheRef.current,\n toolArtifacts: toolArtifactsRef.current,\n toolInteractions: toolInteractionsRef.current,\n supportsRichToolApprovalResponses,\n cancelledToolApprovalIds: supersededApprovalProjection.approvalIds,\n cancelledStatusMessageIds:\n supersededApprovalProjection.statusMessageIds,\n ...(optimisticMessageId && { optimisticMessageId }),\n ...(chatHelpers.error && {\n error: toChatError(chatHelpers.error),\n }),\n ...(cancelledMessageIds.size > 0 && { cancelledMessageIds }),\n ...(toolApprovalResponses.size > 0 && { toolApprovalResponses }),\n }),\n [\n toolStatuses,\n messageTiming,\n optimisticMessageId,\n chatHelpers.error,\n cancelledMessageIds,\n toolApprovalResponses,\n supportsRichToolApprovalResponses,\n supersededApprovalProjection,\n toolArtifactEpoch,\n toolInteractionEpoch,\n ],\n ),\n });\n\n const exportedMessageRepository = useMemo(() => {\n if (!messageRepository) return undefined;\n const converted = toExportedMessageRepository(\n toThreadMessages,\n messageRepository,\n );\n return converted.messages.length > 0 ? converted : undefined;\n }, [messageRepository, toThreadMessages]);\n\n const generatedSuggestions = useGeneratedSuggestions(\n suggestionAdapter,\n messages,\n isRunning,\n );\n\n const [runtimeRef] = useState(() => ({\n get current(): AssistantRuntime {\n return runtime;\n },\n }));\n\n const {\n isLoading,\n deleteMessage: deleteHistoryMessage,\n persistToolInteractions,\n persistToolApprovalResponses,\n } = useExternalHistory(\n runtimeRef,\n adapters?.history ?? contextAdapters?.history,\n toThreadMessages,\n aiSDKV6FormatAdapter as MessageFormatAdapter<\n UI_MESSAGE,\n AISDKStorageFormat\n >,\n (messages) => {\n chatHelpers.setMessages(messages);\n },\n toolArtifactsRef.current,\n markToolArtifactsChanged,\n toolInteractionsRef.current,\n markToolInteractionsChanged,\n toolApprovalResponsesRef.current,\n () => {\n for (const [id, entry] of ownedApprovals ?? []) {\n toolApprovalResponsesRef.current.set(id, entry.response);\n }\n hostApprovalIdsRef.current = new Set(\n toolApprovalResponsesRef.current.keys(),\n );\n setToolApprovalResponses(new Map(toolApprovalResponsesRef.current));\n },\n );\n\n const {\n id: chatId,\n messages: chatMessages,\n status: chatStatus,\n error,\n } = chatHelpers;\n const extras = useMemo(\n () =>\n aiSDKExtras.provide({\n chat: chatHelpers as unknown as UseChatHelpers<UIMessage>,\n error,\n }),\n // oxlint-disable-next-line react/exhaustive-deps -- keyed on the chat's identity and reactive snapshots; useChat re-mints the helpers object every render while its remaining fields are instance-bound methods, and a render-stable extras identity is what lets the external-store core dedupe adapter updates\n [chatId, chatMessages, chatStatus, error],\n );\n\n const completePendingToolCalls = async () => {\n if (!cancelPendingToolCallsOnSend) return;\n\n // The runtime auto-aborts in-flight tool invocations when a new run\n // is dispatched (append() / startRun()), so this only has to mark the\n // abandoned tools cancelled in the UI message list. Every non-terminal\n // tool call qualifies wherever it sits: the run that produced it is over,\n // and a staged `startRun: false` message can sit between it and the tail.\n // Uses setMessages to avoid triggering sendAutomaticallyWhen.\n chatHelpers.setMessages((messages) => {\n let hasChanges = false;\n\n const next = messages.map((message) => {\n if (message.role !== \"assistant\") return message;\n\n let messageChanged = false;\n const parts = message.parts?.map((part) => {\n if (!isToolUIPart(part)) return part;\n if (\n part.state === \"output-available\" ||\n part.state === \"output-error\" ||\n part.state === \"output-denied\"\n )\n return part;\n\n messageChanged = true;\n const { approval: _approval, ...rest } = part;\n return {\n ...rest,\n state: \"output-error\" as const,\n errorText: \"User cancelled tool call by sending a new message.\",\n };\n });\n\n if (!messageChanged) return message;\n hasChanges = true;\n return { ...message, parts };\n });\n\n if (!hasChanges) return messages;\n return next;\n });\n };\n\n const respondViaAISDK = ({\n approvalId,\n approved,\n reason,\n }: RespondToToolApprovalOptions) =>\n Promise.resolve(\n chatHelpers.addToolApprovalResponse({\n id: approvalId,\n approved,\n ...(reason != null && { reason }),\n options: { metadata: lastRunConfigRef.current },\n }),\n );\n\n const respondViaHost = async (\n onRespond: NonNullable<AISDKRuntimeAdapter[\"onRespondToToolApproval\"]>,\n response: RespondToToolApprovalOptions,\n ) => {\n const { approvalId } = response;\n const requested = chatHelpers.messages\n .flatMap((message) =>\n message.parts.flatMap((part) =>\n isToolUIPart(part) ? [{ messageId: message.id, part }] : [],\n ),\n )\n .find(\n ({ part }) =>\n part.state === \"approval-requested\" &&\n part.approval?.id === approvalId,\n );\n if (!requested || hostApprovalIdsRef.current.has(approvalId))\n throw new Error(\n `Tool approval ${approvalId} is not waiting for a response.`,\n );\n\n // A host answer stays out of the useChat messages, where sendAutomaticallyWhen would forward it to the chat route.\n // The owner can change while a response is in flight, and the id set is a\n // ref that is reseeded when it does. Both writes are therefore scoped to\n // the record this response started under, so a rollback never reaches a\n // different chat's state.\n const startedWith = ownedApprovals;\n const startedOwner = approvalOwner;\n const startedResponses = toolApprovalResponsesRef.current;\n // Whether this response is currently applied, tracked here rather than\n // read back from the id ref: that ref follows the chat on screen and is\n // reseeded when the owner changes, so it cannot answer for this response.\n let isApplied = false;\n const applyResponse = (applied: boolean) => {\n isApplied = applied;\n // The captured record is always corrected, so a rollback reaches the\n // chat the response belongs to even after the owner moved on.\n if (applied)\n startedWith?.set(approvalId, {\n response,\n });\n else startedWith?.delete(approvalId);\n\n if (startedOwner) {\n // Every runtime mounted over that owner re-reads the record, including\n // one mounted after this response started.\n notifyHostApprovals(startedOwner);\n return;\n }\n\n if (lastApprovalOwnerRef.current !== startedOwner) return;\n if (applied) hostApprovalIdsRef.current.add(approvalId);\n else hostApprovalIdsRef.current.delete(approvalId);\n if (applied) toolApprovalResponsesRef.current.set(approvalId, response);\n else toolApprovalResponsesRef.current.delete(approvalId);\n setToolApprovalResponses(new Map(toolApprovalResponsesRef.current));\n };\n\n applyResponse(true);\n try {\n await onRespond(response, {\n toolCallId: requested.part.toolCallId,\n toolName: getToolName(requested.part),\n respondViaAISDK: async () => {\n try {\n await respondViaAISDK(response);\n } finally {\n applyResponse(false);\n }\n },\n });\n } catch (error) {\n if (isApplied) applyResponse(false);\n throw error;\n }\n const remainsApplied =\n startedWith?.has(approvalId) ?? startedResponses.has(approvalId);\n if (isApplied && remainsApplied) {\n await persistToolApprovalResponses(requested.messageId);\n }\n };\n\n const hasSeededRepositoryRef = useRef(false);\n const shouldFeedRepository =\n exportedMessageRepository != null &&\n !hasSeededRepositoryRef.current &&\n messages.length === 0;\n\n const runtime = useExternalStoreRuntime({\n unstable_persistsHistory: true,\n isRunning: providerIsRunning,\n ...(shouldFeedRepository\n ? { messageRepository: exportedMessageRepository }\n : { messages }),\n unstable_enableToolInvocations: true,\n setToolStatuses,\n setMessages: (messages) =>\n chatHelpers.setMessages(\n messages\n .map(getVercelAIMessages<UI_MESSAGE>)\n .filter(Boolean)\n .flat(),\n ),\n onImport: (messages) =>\n chatHelpers.setMessages(\n messages\n .map(getVercelAIMessages<UI_MESSAGE>)\n .filter(Boolean)\n .flat(),\n ),\n onVoiceTranscript: (message: ThreadMessage) =>\n chatHelpers.setMessages((current) => [\n ...current,\n toVoiceTranscriptUIMessage<UI_MESSAGE>(message),\n ]),\n onExportExternalState: (): MessageFormatRepository<UI_MESSAGE> => {\n const exported = runtimeRef.current.thread.export();\n\n const expandedMessages: MessageFormatItem<UI_MESSAGE>[] = [];\n const lastInnerIdMap = new Map<string, string>();\n\n for (const item of exported.messages) {\n const innerMessages = getExternalStoreMessages<UI_MESSAGE>(\n item.message,\n );\n let parentId =\n item.parentId != null\n ? (lastInnerIdMap.get(item.parentId) ?? item.parentId)\n : null;\n for (const innerMessage of innerMessages) {\n expandedMessages.push({ parentId, message: innerMessage });\n parentId = aiSDKV6FormatAdapter.getId(innerMessage as UIMessage);\n }\n if (innerMessages.length > 0) {\n lastInnerIdMap.set(\n item.message.id,\n aiSDKV6FormatAdapter.getId(\n innerMessages[innerMessages.length - 1]! as UIMessage,\n ),\n );\n }\n }\n\n const result: MessageFormatRepository<UI_MESSAGE> = {\n messages: expandedMessages,\n };\n\n if (exported.headId != null) {\n result.headId = lastInnerIdMap.get(exported.headId) ?? exported.headId;\n }\n\n return result;\n },\n onLoadExternalState: (repo: MessageFormatRepository<UI_MESSAGE>) => {\n // Convert MessageFormatRepository to ExportedMessageRepository\n const exportedRepo = toExportedMessageRepository(toThreadMessages, repo);\n\n // Import into the thread's MessageRepository\n runtimeRef.current.thread.import(exportedRepo);\n },\n onCancel: async () => {\n const message = chatHelpers.messages.at(-1);\n const cancelledId =\n isRunning && message?.role === \"assistant\" ? message.id : undefined;\n if (cancelledId) {\n const liveIds = new Set(chatHelpers.messages.map((m) => m.id));\n setCancelledMessages((prev) => {\n const kept =\n prev?.chatId === chatHelpers.id\n ? [...prev.ids].filter((id) => liveIds.has(id))\n : [];\n return {\n chatId: chatHelpers.id,\n ids: new Set([...kept, cancelledId]),\n };\n });\n }\n try {\n await chatHelpers.stop();\n } catch (error) {\n if (!(error instanceof Error && error.name === \"AbortError\")) {\n if (cancelledId) retractCancellation(chatHelpers.id, cancelledId);\n throw error;\n }\n }\n },\n onNew: async (message) => {\n const createMessage = (\n customToCreateMessage ?? toCreateMessage\n )<UI_MESSAGE>(message);\n\n if (!(message.startRun ?? message.role === \"user\")) {\n chatHelpers.setMessages((current) => [\n ...current,\n toUIMessage<UI_MESSAGE>(createMessage, message.role),\n ]);\n return;\n }\n\n lastRunConfigRef.current = message.runConfig;\n await completePendingToolCalls();\n await chatHelpers.sendMessage(createMessage, {\n metadata: message.runConfig,\n });\n },\n onEdit: async (message) => {\n const createMessage = (\n customToCreateMessage ?? toCreateMessage\n )<UI_MESSAGE>(message);\n\n if (!(message.startRun ?? message.role === \"user\")) {\n chatHelpers.setMessages((current) => [\n ...sliceMessagesUntil(current, message.parentId),\n toUIMessage<UI_MESSAGE>(createMessage, message.role),\n ]);\n return;\n }\n\n lastRunConfigRef.current = message.runConfig;\n chatHelpers.setMessages((current) =>\n sliceMessagesUntil(current, message.parentId),\n );\n await chatHelpers.sendMessage(createMessage, {\n metadata: message.runConfig,\n });\n },\n onDelete: async (messageId) => {\n const threadMessages = runtimeRef.current.thread.getState().messages;\n const messageIndex = threadMessages.findIndex(\n (message) => message.id === messageId,\n );\n if (messageIndex === -1) return;\n\n await deleteHistoryMessage(messageId);\n\n let removedToolArtifact = false;\n let removedToolInteractions = false;\n let removedToolApprovalResponse = false;\n let removedHostApprovalId = false;\n for (const part of threadMessages[messageIndex]!.content) {\n if (part.type === \"tool-call\") {\n removedToolArtifact =\n toolArtifactsRef.current.delete(part.toolCallId) ||\n removedToolArtifact;\n removedToolInteractions =\n toolInteractionsRef.current.delete(part.toolCallId) ||\n removedToolInteractions;\n if (part.approval) {\n ownedApprovals?.delete(part.approval.id);\n removedToolApprovalResponse =\n toolApprovalResponsesRef.current.delete(part.approval.id) ||\n removedToolApprovalResponse;\n removedHostApprovalId =\n hostApprovalIdsRef.current.delete(part.approval.id) ||\n removedHostApprovalId;\n }\n }\n }\n if (removedToolArtifact) markToolArtifactsChanged();\n if (removedToolInteractions) markToolInteractionsChanged();\n if (removedToolApprovalResponse || removedHostApprovalId) {\n if (approvalOwner) notifyHostApprovals(approvalOwner);\n setToolApprovalResponses(new Map(toolApprovalResponsesRef.current));\n }\n\n const deleteIds = new Set(\n getExternalStoreMessages<UI_MESSAGE>(threadMessages[messageIndex]!).map(\n (message) => message.id,\n ),\n );\n chatHelpers.setMessages((current) =>\n current.filter((message) => !deleteIds.has(message.id)),\n );\n },\n onReload: async (parentId: string | null, config) => {\n lastRunConfigRef.current = config.runConfig;\n const newMessages = sliceMessagesUntil(chatHelpers.messages, parentId);\n chatHelpers.setMessages(newMessages);\n\n await chatHelpers.regenerate({ metadata: config.runConfig });\n },\n onAddToolResult: ({\n messageId,\n toolCallId,\n toolName,\n result,\n isError,\n artifact,\n modelContent,\n }) => {\n if (artifact !== undefined) {\n toolArtifactsRef.current.set(toolCallId, artifact);\n markToolArtifactsChanged();\n }\n\n const targetIndex = findRawToolMessageIndex(\n chatHelpers.messages,\n messageId,\n toolCallId,\n joinStrategy,\n );\n\n const errorText =\n typeof result === \"string\" ? result : JSON.stringify(result);\n const output =\n !isError && modelContent !== undefined\n ? wrapModelContentEnvelope(result, modelContent)\n : result;\n\n if (targetIndex >= 0 && targetIndex !== chatHelpers.messages.length - 1) {\n const target = chatHelpers.messages[targetIndex]!;\n const targetPart = target.parts.find(\n (part) => isToolUIPart(part) && part.toolCallId === toolCallId,\n ) as { state?: string; preliminary?: boolean } | undefined;\n // An earlier message's settled output may already have reached the model, as the error a cancelling send writes does.\n if (\n targetPart?.state === \"output-error\" ||\n targetPart?.state === \"output-denied\" ||\n (targetPart?.state === \"output-available\" && !targetPart.preliminary)\n )\n return Promise.resolve();\n\n const targetMessageId = target.id;\n chatHelpers.setMessages((current) =>\n current.map((message) => {\n if (message.id !== targetMessageId) return message;\n\n return {\n ...message,\n parts: message.parts.map((part) => {\n if (!isToolUIPart(part) || part.toolCallId !== toolCallId)\n return part;\n\n const { preliminary: _preliminary, ...finalPart } =\n part as typeof part & { preliminary?: boolean };\n return {\n ...finalPart,\n state: isError\n ? (\"output-error\" as const)\n : (\"output-available\" as const),\n output: isError ? undefined : output,\n errorText: isError ? errorText : undefined,\n } as typeof part;\n }),\n };\n }),\n );\n return Promise.resolve();\n }\n\n const options = { metadata: lastRunConfigRef.current };\n if (isError) {\n return Promise.resolve(\n chatHelpers.addToolOutput({\n state: \"output-error\",\n tool: toolName ?? toolCallId,\n toolCallId,\n errorText,\n options,\n }),\n );\n }\n\n return Promise.resolve(\n chatHelpers.addToolOutput({\n tool: toolName,\n toolCallId,\n output,\n options,\n }),\n );\n },\n onRespondToToolApproval: (response) => {\n if (supersededApprovalProjection.approvalIds.has(response.approvalId))\n return Promise.reject(\n new Error(\n `Tool approval ${response.approvalId} is not waiting for a response.`,\n ),\n );\n return customOnRespondToToolApproval\n ? respondViaHost(customOnRespondToToolApproval, response)\n : respondViaAISDK(response);\n },\n unstable_onRecordToolInteraction: ({\n messageId,\n toolCallId,\n interaction,\n }) => {\n toolInteractionsRef.current.set(\n toolCallId,\n appendToolInteraction(\n toolInteractionsRef.current.get(toolCallId),\n interaction,\n ),\n );\n markToolInteractionsChanged();\n return persistToolInteractions(messageId);\n },\n ...pickExternalStoreSharedOptions(adapter),\n ...(adapter.unstable_messageRepositoryInstance && {\n unstable_messageRepositoryInstance:\n adapter.unstable_messageRepositoryInstance,\n }),\n ...(suggestionAdapter ? { suggestions: generatedSuggestions } : {}),\n ...(onResume && { onResume }),\n ...(onResumeToolCall && { onResumeToolCall }),\n ...(unstable_onBranchChange && { unstable_onBranchChange }),\n adapters: {\n attachments: vercelAttachmentAdapter,\n ...contextAdapters,\n ...adapters,\n },\n extras,\n isLoading,\n });\n\n const setMessagesRef = useRef(chatHelpers.setMessages);\n useInsertionEffect(() => {\n setMessagesRef.current = chatHelpers.setMessages;\n }, [chatHelpers.setMessages]);\n\n useEffect(() => {\n if (hasSeededRepositoryRef.current) return;\n if (!exportedMessageRepository) return;\n if (chatHelpers.messages.length > 0) {\n hasSeededRepositoryRef.current = true;\n return;\n }\n const tempRepo = new MessageRepository();\n tempRepo.import(exportedMessageRepository);\n setMessagesRef.current(\n tempRepo.getMessages().flatMap(getExternalStoreMessages<UI_MESSAGE>),\n );\n hasSeededRepositoryRef.current = true;\n }, [exportedMessageRepository, chatHelpers.messages.length]);\n return runtime;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useAISDKRuntime.js","names":["c","_c","useCallback","useEffect","useInsertionEffect","useMemo","useRef","useState","UIMessage","useChat","CreateUIMessage","UseChatHelpers","isToolUIPart","generateId","getToolName","useExternalStoreRuntime","useRuntimeAdapters","JoinStrategy","useReplaySafeEffect","SuggestionAdapter","ThreadSuggestion","ToolExecutionStatus","ExternalStoreAdapter","ExternalStoreSharedOptions","ThreadHistoryAdapter","AssistantRuntime","ThreadMessage","MessageFormatAdapter","MessageFormatItem","MessageFormatRepository","AppendMessage","RunConfig","McpAppMetadata","RespondToToolApprovalOptions","Unstable_ToolInteractionLog","getExternalStoreMessages","pickExternalStoreSharedOptions","appendToolInteraction","consumeSuggestionResult","MessageRepository","ReadonlyJSONObject","AssistantError","sliceMessagesUntil","toCreateMessage","vercelAttachmentAdapter","getVercelAIMessages","AISDKMessageConverter","AISDKMessageConverterMetadata","wrapModelContentEnvelope","AISDKStorageFormat","aiSDKV6FormatAdapter","useExternalHistory","toExportedMessageRepository","useStreamingTiming","aiSDKExtras","CustomToCreateMessageFunction","message","UI_MESSAGE","toUIMessage","createMessage","fallbackRole","id","role","toVoiceTranscriptUIMessage","parts","content","filter","part","type","map","text","metadata","modality","Object","keys","custom","length","AISDKRuntimeAdapter","adapters","NonNullable","history","suggestion","unstable_messageRepositoryInstance","unstable_hostApprovalOwner","cancelPendingToolCallsOnSend","onResume","onResumeToolCall","onRespondToToolApproval","response","context","toolCallId","toolName","respondViaAISDK","Promise","joinStrategy","messageRepository","unstable_onBranchChange","EMPTY_SUGGESTIONS","useGeneratedSuggestions","suggestionAdapter","messages","isRunning","$","suggestions","setSuggestions","controllerRef","wasRunningRef","messagesRef","t0","t1","current","adapterRef","t2","t3","hasAdapter","t4","clearSuggestions","abort","_temp","adapter","currentMessages","last","at","status","controller","AbortController","signal","promiseOrGenerator","generate","onUpdate","t5","t6","t7","Symbol","for","NO_CANCELLED_MESSAGE_IDS","ReadonlySet","Set","NO_SUPERSEDED_APPROVAL_PROJECTION","freeze","approvalIds","statusMessageIds","NO_TOOL_APPROVAL_RESPONSES","ReadonlyMap","Map","OwnedApproval","hostToolApprovalsByChat","WeakMap","toApprovalResponses","owned","size","entry","hostApprovalListenersByChat","subscribeToHostApprovals","owner","listener","listeners","get","set","add","delete","notifyHostApprovals","getSupersededApprovalProjection","hostApprovalIds","lastIndex","lastAssistant","hasSupersededApproval","previousWasVoice","flush","hasOpenToolPart","some","state","approval","resolution","descriptor","undefined","index","isVoice","approvalId","has","findRawToolMessageIndex","messageId","containsToolCall","messageIndex","findIndex","start","end","toChatError","error","Error","code","name","useAISDKRuntime","chatHelpers","ReturnType","customToCreateMessage","customOnRespondToToolApproval","contextAdapters","toolStatuses","setToolStatuses","Record","cancelledMessages","setCancelledMessages","chatId","ids","approvalOwner","ownedApprovals","created","toolApprovalResponses","setToolApprovalResponses","toolArtifactEpoch","setToolArtifactEpoch","toolInteractionEpoch","setToolInteractionEpoch","toolApprovalResponsesRef","ownedApprovalIdsRef","hostApprovalIdsRef","sync","prev","next","unchanged","every","unsubscribe","lastApprovalOwnerRef","toolArgsKeyOrderCacheRef","toolLastInputCacheRef","toolArgsTextCacheRef","mcpAppMetadataCacheRef","toolArtifactsRef","toolInteractionsRef","lastRunConfigRef","markToolArtifactsChanged","epoch","markToolInteractionsChanged","hasExecutingTools","values","s","providerIsRunning","wasProviderRunningRef","messageTiming","lastMessage","optimisticMessageId","cancelledMessageIds","supportsRichToolApprovalResponses","supersededApprovalProjectionRef","supersededApprovalProjection","projection","previous","toThreadMessages","sourceMessages","toolArtifacts","toolInteractions","retractCancellation","resumedMessageId","wasProviderRunning","useThreadMessages","toolArgsKeyOrderCache","toolArgsTextCache","toolLastInputCache","mcpAppMetadataCache","cancelledToolApprovalIds","cancelledStatusMessageIds","exportedMessageRepository","converted","generatedSuggestions","runtimeRef","runtime","isLoading","deleteMessage","deleteHistoryMessage","persistToolInteractions","persistToolApprovalResponses","setMessages","chatMessages","chatStatus","extras","provide","chat","completePendingToolCalls","hasChanges","messageChanged","_approval","rest","const","errorText","approved","reason","resolve","addToolApprovalResponse","options","respondViaHost","onRespond","requested","flatMap","find","startedWith","startedOwner","startedResponses","isApplied","applyResponse","applied","remainsApplied","hasSeededRepositoryRef","shouldFeedRepository","unstable_persistsHistory","unstable_enableToolInvocations","Boolean","flat","onImport","onVoiceTranscript","onExportExternalState","exported","thread","export","expandedMessages","lastInnerIdMap","item","innerMessages","parentId","innerMessage","push","getId","result","headId","onLoadExternalState","repo","exportedRepo","import","onCancel","cancelledId","liveIds","m","kept","stop","onNew","startRun","runConfig","sendMessage","onEdit","onDelete","threadMessages","getState","removedToolArtifact","removedToolInteractions","removedToolApprovalResponse","removedHostApprovalId","deleteIds","onReload","config","newMessages","regenerate","onAddToolResult","isError","artifact","modelContent","targetIndex","JSON","stringify","output","target","targetPart","preliminary","targetMessageId","_preliminary","finalPart","addToolOutput","tool","reject","unstable_onRecordToolInteraction","interaction","attachments","setMessagesRef","tempRepo","getMessages","_c","useStreamingTiming"],"sources":["../../src/runtime/useAISDKRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useInsertionEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type {\n UIMessage,\n useChat,\n CreateUIMessage,\n UseChatHelpers,\n} from \"@ai-sdk/react\";\nimport { isToolUIPart, generateId, getToolName } from \"ai\";\nimport {\n useExternalStoreRuntime,\n useRuntimeAdapters,\n type JoinStrategy,\n} from \"@assistant-ui/core/react\";\nimport { useReplaySafeEffect } from \"@assistant-ui/store/internal\";\nimport type {\n SuggestionAdapter,\n ThreadSuggestion,\n ToolExecutionStatus,\n} from \"@assistant-ui/core\";\nimport type {\n ExternalStoreAdapter,\n ExternalStoreSharedOptions,\n ThreadHistoryAdapter,\n AssistantRuntime,\n ThreadMessage,\n MessageFormatAdapter,\n MessageFormatItem,\n MessageFormatRepository,\n AppendMessage,\n RunConfig,\n McpAppMetadata,\n RespondToToolApprovalOptions,\n Unstable_ToolInteractionLog,\n} from \"@assistant-ui/core\";\nimport {\n getExternalStoreMessages,\n pickExternalStoreSharedOptions,\n} from \"@assistant-ui/core\";\nimport {\n appendToolInteraction,\n consumeSuggestionResult,\n MessageRepository,\n} from \"@assistant-ui/core/internal\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\nimport type { AssistantError } from \"@assistant-ui/core\";\nimport { sliceMessagesUntil } from \"../utils/sliceMessagesUntil\";\nimport { toCreateMessage } from \"../converters/toCreateMessage\";\nimport { vercelAttachmentAdapter } from \"../adapters/vercelAttachmentAdapter\";\nimport { getVercelAIMessages } from \"../utils/getVercelAIMessages\";\nimport {\n AISDKMessageConverter,\n type AISDKMessageConverterMetadata,\n} from \"../converters/convertMessage\";\nimport { wrapModelContentEnvelope } from \"../converters/modelContentEnvelope\";\nimport {\n type AISDKStorageFormat,\n aiSDKV6FormatAdapter,\n} from \"../adapters/aiSDKFormatAdapter\";\nimport {\n useExternalHistory,\n toExportedMessageRepository,\n} from \"./useExternalHistory\";\nimport { useStreamingTiming } from \"./useStreamingTiming\";\nimport { aiSDKExtras } from \"../aiSDKExtras\";\n\nexport type CustomToCreateMessageFunction = <\n UI_MESSAGE extends UIMessage = UIMessage,\n>(\n message: AppendMessage,\n) => CreateUIMessage<UI_MESSAGE>;\n\nconst toUIMessage = <UI_MESSAGE extends UIMessage>(\n createMessage: CreateUIMessage<UI_MESSAGE>,\n fallbackRole: UI_MESSAGE[\"role\"],\n): UI_MESSAGE =>\n ({\n ...createMessage,\n id: createMessage.id ?? generateId(),\n role: createMessage.role ?? fallbackRole,\n }) as UI_MESSAGE;\n\nconst toVoiceTranscriptUIMessage = <UI_MESSAGE extends UIMessage>(\n message: ThreadMessage,\n): UI_MESSAGE =>\n ({\n id: message.id,\n role: message.role,\n parts: message.content\n .filter((part) => part.type === \"text\")\n .map((part) => ({ type: \"text\", text: part.text })),\n metadata: {\n ...(message.metadata.modality && { modality: message.metadata.modality }),\n ...(Object.keys(message.metadata.custom).length > 0 && {\n custom: message.metadata.custom,\n }),\n },\n }) as UI_MESSAGE;\n\nexport type AISDKRuntimeAdapter<UI_MESSAGE extends UIMessage = UIMessage> =\n ExternalStoreSharedOptions & {\n adapters?:\n | (NonNullable<ExternalStoreAdapter[\"adapters\"]> & {\n history?: ThreadHistoryAdapter | undefined;\n suggestion?: SuggestionAdapter | undefined;\n })\n | undefined;\n toCreateMessage?: CustomToCreateMessageFunction;\n unstable_messageRepositoryInstance?: MessageRepository | undefined;\n /**\n * The object a host answer belongs to, normally the `Chat` the runtime\n * renders. A host answer never reaches the `useChat` messages, so without\n * an owner it lives only as long as this runtime. With an owner, it\n * survives runtime remounts over the same chat.\n */\n unstable_hostApprovalOwner?: object | undefined;\n /**\n * Whether to automatically cancel pending interactive tool calls when the user sends a new message.\n *\n * When enabled (default), the pending tool calls will be marked as failed with an error message\n * indicating the user cancelled the tool call by sending a new message.\n *\n * @default true\n */\n cancelPendingToolCallsOnSend?: boolean | undefined;\n /**\n * Called when `runtime.thread.resumeRun(config)` is invoked.\n *\n * When omitted, `resumeRun` throws `\"Runtime does not support resuming runs.\"`.\n * Provide this to bridge resume invocations into a custom replay channel\n * (for example, an SSE reconnect endpoint keyed by turn id).\n */\n onResume?: ExternalStoreAdapter[\"onResume\"];\n /**\n * Called when `runtime.thread.resumeToolCall(options)` is invoked for a tool call the in-process tracker does not own.\n *\n * When omitted, `resumeToolCall` throws `\"Tool call ${toolCallId} is not waiting for resume.\"`.\n * Provide this to bridge resume-tool-call invocations into a custom handler.\n */\n onResumeToolCall?: ExternalStoreAdapter[\"onResumeToolCall\"];\n /**\n * Answers tool approval requests through a host-owned channel instead of the AI SDK's `addToolApprovalResponse`.\n *\n * Called for every approval request in the thread with the complete response, including option and free-form answers. Hand requests the host does not own to `respondViaAISDK`, which is what runs when this option is omitted. The answer applies to the approval when the handler starts and is removed if it throws. It is never written into the `useChat` messages, so `sendAutomaticallyWhen` cannot forward it. With a history adapter, the answer is stored with its message once the handler resolves and returns on reload. With `unstable_hostApprovalOwner`, in-memory answers survive runtime remounts over the same chat; without an owner or history adapter, they last only as long as the runtime. Bring the resumed run back into the chat, for example with `resumeStream`, and have the endpoint refuse a second resume.\n *\n * While a handler is set, an approval's `display`, `allowFreeform`, `dismissible` and `options` reach the renderer, because the handler can receive answers the AI SDK cannot carry. A stream declares them through the `approvalDescriptor` of its `tool-approval-request` chunk, the one approval field the AI SDK keeps opaque; the converter reads the request and answer fields from that descriptor when the approval itself lacks them.\n */\n onRespondToToolApproval?:\n | ((\n response: RespondToToolApprovalOptions,\n context: {\n toolCallId: string;\n toolName: string;\n /** Sends this response through the AI SDK's `addToolApprovalResponse`, which carries only `approved` and `reason`. */\n respondViaAISDK: () => Promise<void>;\n },\n ) => Promise<void> | void)\n | undefined;\n /**\n * How consecutive assistant messages are rendered.\n *\n * `\"concat-content\"` (the default) merges them into a single thread message.\n * `\"none\"` keeps each assistant message as its own thread message, which is\n * useful when a backend persists proactive or consecutive assistant messages\n * as separate entries.\n */\n joinStrategy?: JoinStrategy | undefined;\n /**\n * A branch-aware AI SDK message tree seeded once when `useChat` is empty.\n * After that seed, live updates come only from `useChat`. A later empty\n * chat or a new object identity does not reload the tree.\n */\n messageRepository?: MessageFormatRepository<UI_MESSAGE>;\n /**\n * Called after an explicit `switchToBranch` (for example a BranchPicker\n * click). Complements `setMessages` and does not enable switching by itself.\n *\n * @deprecated This API is still under active development and might change without notice.\n */\n unstable_onBranchChange?: ExternalStoreAdapter[\"unstable_onBranchChange\"];\n };\n\nconst EMPTY_SUGGESTIONS: readonly ThreadSuggestion[] = [];\n\nconst useGeneratedSuggestions = (\n suggestionAdapter: SuggestionAdapter | undefined,\n messages: readonly ThreadMessage[],\n isRunning: boolean,\n): readonly ThreadSuggestion[] => {\n const [suggestions, setSuggestions] =\n useState<readonly ThreadSuggestion[]>(EMPTY_SUGGESTIONS);\n const controllerRef = useRef<AbortController | null>(null);\n const wasRunningRef = useRef(false);\n const messagesRef = useRef(messages);\n useInsertionEffect(() => {\n messagesRef.current = messages;\n }, [messages]);\n const adapterRef = useRef(suggestionAdapter);\n useInsertionEffect(() => {\n adapterRef.current = suggestionAdapter;\n }, [suggestionAdapter]);\n const hasAdapter = suggestionAdapter != null;\n\n useEffect(() => {\n const clearSuggestions = () => {\n controllerRef.current?.abort();\n controllerRef.current = null;\n setSuggestions((prev) => (prev.length === 0 ? prev : EMPTY_SUGGESTIONS));\n };\n\n const adapter = adapterRef.current;\n if (!adapter) {\n clearSuggestions();\n wasRunningRef.current = isRunning;\n return;\n }\n\n if (isRunning) {\n if (!wasRunningRef.current) {\n clearSuggestions();\n }\n wasRunningRef.current = true;\n return;\n }\n\n if (!wasRunningRef.current) return;\n wasRunningRef.current = false;\n\n const currentMessages = messagesRef.current;\n const last = currentMessages.at(-1);\n if (last?.role !== \"assistant\") return;\n if (last.status?.type === \"requires-action\") return;\n\n const controller = new AbortController();\n controllerRef.current = controller;\n const { signal } = controller;\n\n void (async () => {\n try {\n const promiseOrGenerator = adapter.generate({\n messages: currentMessages,\n signal,\n });\n\n await consumeSuggestionResult(promiseOrGenerator, {\n signal,\n onUpdate: setSuggestions,\n });\n } catch {}\n })();\n }, [hasAdapter, isRunning]);\n\n useReplaySafeEffect(() => {\n return () => {\n controllerRef.current?.abort();\n };\n }, []);\n\n return suggestions;\n};\n\nconst NO_CANCELLED_MESSAGE_IDS: ReadonlySet<string> = new Set();\n\nconst NO_SUPERSEDED_APPROVAL_PROJECTION = Object.freeze({\n approvalIds: Object.freeze(new Set<string>()),\n statusMessageIds: Object.freeze(new Set<string>()),\n});\n\nconst NO_TOOL_APPROVAL_RESPONSES: ReadonlyMap<\n string,\n RespondToToolApprovalOptions\n> = new Map();\n\n/**\n * A host answer is deliberately kept out of the `useChat` messages, so nothing\n * in the chat records it. Held in runtime state it would die with the runtime,\n * and a runtime mounted again over the same chat would show the request open\n * and take a second answer. Keyed on the chat instead, the answer lives as\n * long as the chat it belongs to, and is collected with it.\n */\ntype OwnedApproval = {\n response: RespondToToolApprovalOptions;\n};\n\nconst hostToolApprovalsByChat = new WeakMap<\n object,\n Map<string, OwnedApproval>\n>();\n\nconst toApprovalResponses = (\n owned: ReadonlyMap<string, OwnedApproval> | undefined,\n): ReadonlyMap<string, RespondToToolApprovalOptions> =>\n owned && owned.size > 0\n ? new Map([...owned].map(([id, entry]) => [id, entry.response]))\n : NO_TOOL_APPROVAL_RESPONSES;\n\n/**\n * The answers live on the owner, but each mounted runtime renders them from\n * its own state, so a write has to be announced: the runtime that performed it\n * may already be unmounted (a rollback resolving after a remount), and another\n * runtime may be mounted over the same owner.\n */\nconst hostApprovalListenersByChat = new WeakMap<object, Set<() => void>>();\n\nconst subscribeToHostApprovals = (owner: object, listener: () => void) => {\n const listeners = hostApprovalListenersByChat.get(owner) ?? new Set();\n hostApprovalListenersByChat.set(owner, listeners);\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\n\nconst notifyHostApprovals = (owner: object) => {\n for (const listener of [...(hostApprovalListenersByChat.get(owner) ?? [])]) {\n listener();\n }\n};\n\nconst getSupersededApprovalProjection = <UI_MESSAGE extends UIMessage>(\n messages: readonly UI_MESSAGE[],\n hostApprovalIds: ReadonlySet<string>,\n joinStrategy: JoinStrategy | undefined,\n isRunning: boolean,\n) => {\n const approvalIds = new Set<string>();\n const statusMessageIds = new Set<string>();\n const lastIndex = messages.length - 1;\n let lastAssistant: UI_MESSAGE | undefined;\n let hasSupersededApproval = false;\n let previousWasVoice = false;\n\n const flush = () => {\n const hasOpenToolPart =\n lastAssistant === messages[lastIndex] &&\n lastAssistant?.parts?.some((part) => {\n if (\n !isToolUIPart(part) ||\n part.state === \"output-available\" ||\n part.state === \"output-error\" ||\n part.state === \"output-denied\"\n )\n return false;\n\n const approval = (\n part as {\n approval?: {\n resolution?: unknown;\n descriptor?: unknown;\n };\n }\n ).approval;\n const resolution =\n approval?.resolution ??\n (approval?.descriptor as { resolution?: unknown } | undefined)\n ?.resolution;\n return resolution !== \"cancelled\" && resolution !== \"expired\";\n });\n if (\n lastAssistant &&\n hasSupersededApproval &&\n !hasOpenToolPart &&\n !(isRunning && lastAssistant === messages[lastIndex])\n ) {\n statusMessageIds.add(lastAssistant.id);\n }\n lastAssistant = undefined;\n hasSupersededApproval = false;\n previousWasVoice = false;\n };\n\n for (let index = 0; index < messages.length; index++) {\n const message = messages[index]!;\n if (message.role !== \"assistant\") {\n flush();\n } else {\n const isVoice =\n (message.metadata as { modality?: unknown } | undefined)?.modality ===\n \"voice\";\n if (isVoice || previousWasVoice || joinStrategy === \"none\") flush();\n lastAssistant = message;\n previousWasVoice = isVoice;\n }\n\n for (const part of message.parts ?? []) {\n if (!isToolUIPart(part) || part.state !== \"approval-requested\") continue;\n\n const approval = part.approval;\n if (!approval) continue;\n\n const approvalId = approval.id;\n if (hostApprovalIds.has(approvalId)) continue;\n\n const resolution =\n (approval as { resolution?: unknown }).resolution ??\n (approval.descriptor as { resolution?: unknown } | null | undefined)\n ?.resolution;\n if (resolution === \"cancelled\" || resolution === \"expired\") continue;\n\n if (index !== lastIndex) {\n approvalIds.add(approvalId);\n if (message.role === \"assistant\") hasSupersededApproval = true;\n }\n }\n }\n flush();\n\n if (approvalIds.size === 0 && statusMessageIds.size === 0)\n return NO_SUPERSEDED_APPROVAL_PROJECTION;\n\n return { approvalIds, statusMessageIds };\n};\n\nconst findRawToolMessageIndex = <UI_MESSAGE extends UIMessage>(\n messages: readonly UI_MESSAGE[],\n messageId: string,\n toolCallId: string,\n joinStrategy: JoinStrategy | undefined,\n) => {\n const containsToolCall = (message: UI_MESSAGE) =>\n message.parts?.some(\n (part) => isToolUIPart(part) && part.toolCallId === toolCallId,\n ) === true;\n\n const messageIndex = messages.findIndex(\n (message) => message.id === messageId,\n );\n if (messageIndex === -1) return -1;\n if (containsToolCall(messages[messageIndex]!)) return messageIndex;\n if (joinStrategy === \"none\" || messages[messageIndex]?.role !== \"assistant\")\n return -1;\n\n let start = messageIndex;\n while (start > 0 && messages[start - 1]?.role === \"assistant\") start--;\n\n let end = messageIndex;\n while (end + 1 < messages.length && messages[end + 1]?.role === \"assistant\")\n end++;\n\n for (let index = start; index <= end; index++) {\n if (containsToolCall(messages[index]!)) return index;\n }\n return -1;\n};\n\nconst toChatError = (error: Error): AssistantError => {\n const code = (error as { code?: unknown }).code;\n return {\n code:\n typeof code === \"string\"\n ? code\n : error.name !== \"Error\"\n ? error.name\n : \"unknown\",\n message: error.message,\n };\n};\n\nexport const useAISDKRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(\n chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>,\n adapter: AISDKRuntimeAdapter<UI_MESSAGE> = {},\n) => {\n const {\n adapters,\n toCreateMessage: customToCreateMessage,\n cancelPendingToolCallsOnSend = true,\n onResume,\n onResumeToolCall,\n onRespondToToolApproval: customOnRespondToToolApproval,\n joinStrategy,\n messageRepository,\n unstable_onBranchChange,\n } = adapter;\n const suggestionAdapter = adapters?.suggestion;\n const contextAdapters = useRuntimeAdapters();\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n const [cancelledMessages, setCancelledMessages] = useState<{\n chatId: string;\n ids: ReadonlySet<string>;\n } | null>(null);\n // Set by hosts that own the chat across runtime lifetimes, so a host answer\n // outlives a remount over that same chat.\n const approvalOwner = adapter.unstable_hostApprovalOwner;\n const ownedApprovals = approvalOwner\n ? (hostToolApprovalsByChat.get(approvalOwner) ??\n (() => {\n const created = new Map<string, OwnedApproval>();\n hostToolApprovalsByChat.set(approvalOwner, created);\n return created;\n })())\n : undefined;\n const [toolApprovalResponses, setToolApprovalResponses] = useState<\n ReadonlyMap<string, RespondToToolApprovalOptions>\n >(() => toApprovalResponses(ownedApprovals));\n const [toolArtifactEpoch, setToolArtifactEpoch] = useState(0);\n const [toolInteractionEpoch, setToolInteractionEpoch] = useState(0);\n const toolApprovalResponsesRef = useRef(\n new Map(toApprovalResponses(ownedApprovals)),\n );\n const ownedApprovalIdsRef = useRef(new Set(ownedApprovals?.keys()));\n const hostApprovalIdsRef = useRef(new Set<string>(ownedApprovals?.keys()));\n\n // The owner's record is shared, so this runtime re-reads it whenever it is\n // written rather than only at mount: the write may come from a runtime that\n // has since unmounted, or from another runtime mounted over the same owner.\n useEffect(() => {\n if (!approvalOwner || !ownedApprovals) return undefined;\n const sync = () => {\n for (const id of ownedApprovalIdsRef.current)\n toolApprovalResponsesRef.current.delete(id);\n for (const [id, entry] of ownedApprovals)\n toolApprovalResponsesRef.current.set(id, entry.response);\n ownedApprovalIdsRef.current = new Set(ownedApprovals.keys());\n hostApprovalIdsRef.current = new Set(\n toolApprovalResponsesRef.current.keys(),\n );\n setToolApprovalResponses((prev) => {\n const next = new Map(toolApprovalResponsesRef.current);\n const unchanged =\n prev.size === next.size &&\n [...next].every(([id, response]) => prev.get(id) === response);\n return unchanged ? prev : next;\n });\n };\n const unsubscribe = subscribeToHostApprovals(approvalOwner, sync);\n // The state was seeded during render, so a write landing between then and\n // this subscription would otherwise never be seen.\n sync();\n return unsubscribe;\n }, [approvalOwner, ownedApprovals]);\n\n // A runtime kept mounted across a change of owner must not carry the\n // previous chat's answers: a reused approval id would render as already\n // answered and reject a genuine response.\n const lastApprovalOwnerRef = useRef(approvalOwner);\n if (lastApprovalOwnerRef.current !== approvalOwner) {\n lastApprovalOwnerRef.current = approvalOwner;\n hostApprovalIdsRef.current = new Set<string>(ownedApprovals?.keys());\n toolApprovalResponsesRef.current = new Map(\n toApprovalResponses(ownedApprovals),\n );\n ownedApprovalIdsRef.current = new Set(ownedApprovals?.keys());\n setToolApprovalResponses(new Map(toolApprovalResponsesRef.current));\n }\n const toolArgsKeyOrderCacheRef = useRef<Map<string, Map<string, string[]>>>(\n new Map(),\n );\n const toolLastInputCacheRef = useRef<Map<string, ReadonlyJSONObject>>(\n new Map(),\n );\n const toolArgsTextCacheRef = useRef<\n WeakMap<ReadonlyJSONObject, Map<string, string>>\n >(new WeakMap());\n const mcpAppMetadataCacheRef = useRef<Map<string, McpAppMetadata>>(new Map());\n const toolArtifactsRef = useRef<Map<string, unknown>>(new Map());\n const toolInteractionsRef = useRef<Map<string, Unstable_ToolInteractionLog>>(\n new Map(),\n );\n const lastRunConfigRef = useRef<RunConfig | undefined>(undefined);\n const markToolArtifactsChanged = useCallback(() => {\n setToolArtifactEpoch((epoch) => epoch + 1);\n }, []);\n const markToolInteractionsChanged = useCallback(() => {\n setToolInteractionEpoch((epoch) => epoch + 1);\n }, []);\n\n const hasExecutingTools = Object.values(toolStatuses).some(\n (s) => s?.type === \"executing\",\n );\n const providerIsRunning =\n chatHelpers.status === \"submitted\" || chatHelpers.status === \"streaming\";\n const isRunning = providerIsRunning || hasExecutingTools;\n const wasProviderRunningRef = useRef(providerIsRunning);\n\n const messageTiming = useStreamingTiming(chatHelpers.messages, isRunning);\n\n // Flag the streaming message optimistic: its id can be swapped for a server\n // id mid-run, and the repository then drops the orphaned pre-swap id (#4037).\n const lastMessage = chatHelpers.messages.at(-1);\n const optimisticMessageId =\n isRunning && lastMessage?.role === \"assistant\" ? lastMessage.id : undefined;\n\n const cancelledMessageIds =\n cancelledMessages?.chatId === chatHelpers.id\n ? cancelledMessages.ids\n : NO_CANCELLED_MESSAGE_IDS;\n const supportsRichToolApprovalResponses =\n customOnRespondToToolApproval != null;\n const supersededApprovalProjectionRef = useRef(\n NO_SUPERSEDED_APPROVAL_PROJECTION,\n );\n const supersededApprovalProjection = useMemo(\n () => {\n const projection = getSupersededApprovalProjection(\n chatHelpers.messages,\n hostApprovalIdsRef.current,\n joinStrategy,\n isRunning,\n );\n const previous = supersededApprovalProjectionRef.current;\n if (\n projection.approvalIds.size === previous.approvalIds.size &&\n projection.statusMessageIds.size === previous.statusMessageIds.size &&\n [...projection.approvalIds].every((id) =>\n previous.approvalIds.has(id),\n ) &&\n [...projection.statusMessageIds].every((id) =>\n previous.statusMessageIds.has(id),\n )\n )\n return previous;\n\n supersededApprovalProjectionRef.current = projection;\n return projection;\n },\n // oxlint-disable-next-line react/exhaustive-deps -- hostApprovalIdsRef changes alongside toolApprovalResponses, which invalidates the projection\n [chatHelpers.messages, joinStrategy, isRunning, toolApprovalResponses],\n );\n\n const toThreadMessages = useCallback(\n (sourceMessages: UI_MESSAGE[]) => {\n const metadata: AISDKMessageConverterMetadata = {\n supportsRichToolApprovalResponses,\n toolArtifacts: toolArtifactsRef.current,\n toolInteractions: toolInteractionsRef.current,\n toolApprovalResponses: toolApprovalResponsesRef.current,\n };\n return AISDKMessageConverter.toThreadMessages(\n sourceMessages,\n false,\n metadata,\n );\n },\n [supportsRichToolApprovalResponses],\n );\n\n const retractCancellation = useCallback(\n (chatId: string, messageId: string) => {\n setCancelledMessages((prev) => {\n if (prev?.chatId !== chatId || !prev.ids.has(messageId)) return prev;\n const ids = new Set(prev.ids);\n ids.delete(messageId);\n return { chatId, ids };\n });\n },\n [],\n );\n\n // A provider run that resumes the stopped response retracts its cancellation;\n // a run that starts a new response leaves the stopped one marked.\n const resumedMessageId =\n providerIsRunning && lastMessage?.role === \"assistant\"\n ? lastMessage.id\n : undefined;\n\n useEffect(() => {\n const wasProviderRunning = wasProviderRunningRef.current;\n wasProviderRunningRef.current = providerIsRunning;\n if (wasProviderRunning || !resumedMessageId) return;\n retractCancellation(chatHelpers.id, resumedMessageId);\n }, [\n providerIsRunning,\n resumedMessageId,\n chatHelpers.id,\n retractCancellation,\n ]);\n\n const messages = AISDKMessageConverter.useThreadMessages({\n isRunning,\n messages: chatHelpers.messages,\n joinStrategy,\n metadata: useMemo<AISDKMessageConverterMetadata>(\n () => ({\n toolStatuses,\n messageTiming,\n toolArgsKeyOrderCache: toolArgsKeyOrderCacheRef.current,\n toolArgsTextCache: toolArgsTextCacheRef.current,\n toolLastInputCache: toolLastInputCacheRef.current,\n mcpAppMetadataCache: mcpAppMetadataCacheRef.current,\n toolArtifacts: toolArtifactsRef.current,\n toolInteractions: toolInteractionsRef.current,\n supportsRichToolApprovalResponses,\n cancelledToolApprovalIds: supersededApprovalProjection.approvalIds,\n cancelledStatusMessageIds:\n supersededApprovalProjection.statusMessageIds,\n ...(optimisticMessageId && { optimisticMessageId }),\n ...(chatHelpers.error && {\n error: toChatError(chatHelpers.error),\n }),\n ...(cancelledMessageIds.size > 0 && { cancelledMessageIds }),\n ...(toolApprovalResponses.size > 0 && { toolApprovalResponses }),\n }),\n [\n toolStatuses,\n messageTiming,\n optimisticMessageId,\n chatHelpers.error,\n cancelledMessageIds,\n toolApprovalResponses,\n supportsRichToolApprovalResponses,\n supersededApprovalProjection,\n toolArtifactEpoch,\n toolInteractionEpoch,\n ],\n ),\n });\n\n const exportedMessageRepository = useMemo(() => {\n if (!messageRepository) return undefined;\n const converted = toExportedMessageRepository(\n toThreadMessages,\n messageRepository,\n );\n return converted.messages.length > 0 ? converted : undefined;\n }, [messageRepository, toThreadMessages]);\n\n const generatedSuggestions = useGeneratedSuggestions(\n suggestionAdapter,\n messages,\n isRunning,\n );\n\n const [runtimeRef] = useState(() => ({\n get current(): AssistantRuntime {\n return runtime;\n },\n }));\n\n const {\n isLoading,\n deleteMessage: deleteHistoryMessage,\n persistToolInteractions,\n persistToolApprovalResponses,\n } = useExternalHistory(\n runtimeRef,\n adapters?.history ?? contextAdapters?.history,\n toThreadMessages,\n aiSDKV6FormatAdapter as MessageFormatAdapter<\n UI_MESSAGE,\n AISDKStorageFormat\n >,\n (messages) => {\n chatHelpers.setMessages(messages);\n },\n toolArtifactsRef.current,\n markToolArtifactsChanged,\n toolInteractionsRef.current,\n markToolInteractionsChanged,\n toolApprovalResponsesRef.current,\n () => {\n for (const [id, entry] of ownedApprovals ?? []) {\n toolApprovalResponsesRef.current.set(id, entry.response);\n }\n hostApprovalIdsRef.current = new Set(\n toolApprovalResponsesRef.current.keys(),\n );\n setToolApprovalResponses(new Map(toolApprovalResponsesRef.current));\n },\n );\n\n const {\n id: chatId,\n messages: chatMessages,\n status: chatStatus,\n error,\n } = chatHelpers;\n const extras = useMemo(\n () =>\n aiSDKExtras.provide({\n chat: chatHelpers as unknown as UseChatHelpers<UIMessage>,\n error,\n }),\n // oxlint-disable-next-line react/exhaustive-deps -- keyed on the chat's identity and reactive snapshots; useChat re-mints the helpers object every render while its remaining fields are instance-bound methods, and a render-stable extras identity is what lets the external-store core dedupe adapter updates\n [chatId, chatMessages, chatStatus, error],\n );\n\n const completePendingToolCalls = async () => {\n if (!cancelPendingToolCallsOnSend) return;\n\n // The runtime auto-aborts in-flight tool invocations when a new run\n // is dispatched (append() / startRun()), so this only has to mark the\n // abandoned tools cancelled in the UI message list. Every non-terminal\n // tool call qualifies wherever it sits: the run that produced it is over,\n // and a staged `startRun: false` message can sit between it and the tail.\n // Uses setMessages to avoid triggering sendAutomaticallyWhen.\n chatHelpers.setMessages((messages) => {\n let hasChanges = false;\n\n const next = messages.map((message) => {\n if (message.role !== \"assistant\") return message;\n\n let messageChanged = false;\n const parts = message.parts?.map((part) => {\n if (!isToolUIPart(part)) return part;\n if (\n part.state === \"output-available\" ||\n part.state === \"output-error\" ||\n part.state === \"output-denied\"\n )\n return part;\n\n messageChanged = true;\n const { approval: _approval, ...rest } = part;\n return {\n ...rest,\n state: \"output-error\" as const,\n errorText: \"User cancelled tool call by sending a new message.\",\n };\n });\n\n if (!messageChanged) return message;\n hasChanges = true;\n return { ...message, parts };\n });\n\n if (!hasChanges) return messages;\n return next;\n });\n };\n\n const respondViaAISDK = ({\n approvalId,\n approved,\n reason,\n }: RespondToToolApprovalOptions) =>\n Promise.resolve(\n chatHelpers.addToolApprovalResponse({\n id: approvalId,\n approved,\n ...(reason != null && { reason }),\n options: { metadata: lastRunConfigRef.current },\n }),\n );\n\n const respondViaHost = async (\n onRespond: NonNullable<AISDKRuntimeAdapter[\"onRespondToToolApproval\"]>,\n response: RespondToToolApprovalOptions,\n ) => {\n const { approvalId } = response;\n const requested = chatHelpers.messages\n .flatMap((message) =>\n message.parts.flatMap((part) =>\n isToolUIPart(part) ? [{ messageId: message.id, part }] : [],\n ),\n )\n .find(\n ({ part }) =>\n part.state === \"approval-requested\" &&\n part.approval?.id === approvalId,\n );\n if (!requested || hostApprovalIdsRef.current.has(approvalId))\n throw new Error(\n `Tool approval ${approvalId} is not waiting for a response.`,\n );\n\n // A host answer stays out of the useChat messages, where sendAutomaticallyWhen would forward it to the chat route.\n // The owner can change while a response is in flight, and the id set is a\n // ref that is reseeded when it does. Both writes are therefore scoped to\n // the record this response started under, so a rollback never reaches a\n // different chat's state.\n const startedWith = ownedApprovals;\n const startedOwner = approvalOwner;\n const startedResponses = toolApprovalResponsesRef.current;\n // Whether this response is currently applied, tracked here rather than\n // read back from the id ref: that ref follows the chat on screen and is\n // reseeded when the owner changes, so it cannot answer for this response.\n let isApplied = false;\n const applyResponse = (applied: boolean) => {\n isApplied = applied;\n // The captured record is always corrected, so a rollback reaches the\n // chat the response belongs to even after the owner moved on.\n if (applied)\n startedWith?.set(approvalId, {\n response,\n });\n else startedWith?.delete(approvalId);\n\n if (startedOwner) {\n // Every runtime mounted over that owner re-reads the record, including\n // one mounted after this response started.\n notifyHostApprovals(startedOwner);\n return;\n }\n\n if (lastApprovalOwnerRef.current !== startedOwner) return;\n if (applied) hostApprovalIdsRef.current.add(approvalId);\n else hostApprovalIdsRef.current.delete(approvalId);\n if (applied) toolApprovalResponsesRef.current.set(approvalId, response);\n else toolApprovalResponsesRef.current.delete(approvalId);\n setToolApprovalResponses(new Map(toolApprovalResponsesRef.current));\n };\n\n applyResponse(true);\n try {\n await onRespond(response, {\n toolCallId: requested.part.toolCallId,\n toolName: getToolName(requested.part),\n respondViaAISDK: async () => {\n try {\n await respondViaAISDK(response);\n } finally {\n applyResponse(false);\n }\n },\n });\n } catch (error) {\n if (isApplied) applyResponse(false);\n throw error;\n }\n const remainsApplied =\n startedWith?.has(approvalId) ?? startedResponses.has(approvalId);\n if (isApplied && remainsApplied) {\n await persistToolApprovalResponses(requested.messageId);\n }\n };\n\n const hasSeededRepositoryRef = useRef(false);\n const shouldFeedRepository =\n exportedMessageRepository != null &&\n !hasSeededRepositoryRef.current &&\n messages.length === 0;\n\n const runtime = useExternalStoreRuntime({\n unstable_persistsHistory: true,\n isRunning: providerIsRunning,\n ...(shouldFeedRepository\n ? { messageRepository: exportedMessageRepository }\n : { messages }),\n unstable_enableToolInvocations: true,\n setToolStatuses,\n setMessages: (messages) =>\n chatHelpers.setMessages(\n messages\n .map(getVercelAIMessages<UI_MESSAGE>)\n .filter(Boolean)\n .flat(),\n ),\n onImport: (messages) =>\n chatHelpers.setMessages(\n messages\n .map(getVercelAIMessages<UI_MESSAGE>)\n .filter(Boolean)\n .flat(),\n ),\n onVoiceTranscript: (message: ThreadMessage) =>\n chatHelpers.setMessages((current) => [\n ...current,\n toVoiceTranscriptUIMessage<UI_MESSAGE>(message),\n ]),\n onExportExternalState: (): MessageFormatRepository<UI_MESSAGE> => {\n const exported = runtimeRef.current.thread.export();\n\n const expandedMessages: MessageFormatItem<UI_MESSAGE>[] = [];\n const lastInnerIdMap = new Map<string, string>();\n\n for (const item of exported.messages) {\n const innerMessages = getExternalStoreMessages<UI_MESSAGE>(\n item.message,\n );\n let parentId =\n item.parentId != null\n ? (lastInnerIdMap.get(item.parentId) ?? item.parentId)\n : null;\n for (const innerMessage of innerMessages) {\n expandedMessages.push({ parentId, message: innerMessage });\n parentId = aiSDKV6FormatAdapter.getId(innerMessage as UIMessage);\n }\n if (innerMessages.length > 0) {\n lastInnerIdMap.set(\n item.message.id,\n aiSDKV6FormatAdapter.getId(\n innerMessages[innerMessages.length - 1]! as UIMessage,\n ),\n );\n }\n }\n\n const result: MessageFormatRepository<UI_MESSAGE> = {\n messages: expandedMessages,\n };\n\n if (exported.headId != null) {\n result.headId = lastInnerIdMap.get(exported.headId) ?? exported.headId;\n }\n\n return result;\n },\n onLoadExternalState: (repo: MessageFormatRepository<UI_MESSAGE>) => {\n // Convert MessageFormatRepository to ExportedMessageRepository\n const exportedRepo = toExportedMessageRepository(toThreadMessages, repo);\n\n // Import into the thread's MessageRepository\n runtimeRef.current.thread.import(exportedRepo);\n },\n onCancel: async () => {\n const message = chatHelpers.messages.at(-1);\n const cancelledId =\n isRunning && message?.role === \"assistant\" ? message.id : undefined;\n if (cancelledId) {\n const liveIds = new Set(chatHelpers.messages.map((m) => m.id));\n setCancelledMessages((prev) => {\n const kept =\n prev?.chatId === chatHelpers.id\n ? [...prev.ids].filter((id) => liveIds.has(id))\n : [];\n return {\n chatId: chatHelpers.id,\n ids: new Set([...kept, cancelledId]),\n };\n });\n }\n try {\n await chatHelpers.stop();\n } catch (error) {\n if (!(error instanceof Error && error.name === \"AbortError\")) {\n if (cancelledId) retractCancellation(chatHelpers.id, cancelledId);\n throw error;\n }\n }\n },\n onNew: async (message) => {\n const createMessage = (\n customToCreateMessage ?? toCreateMessage\n )<UI_MESSAGE>(message);\n\n if (!(message.startRun ?? message.role === \"user\")) {\n chatHelpers.setMessages((current) => [\n ...current,\n toUIMessage<UI_MESSAGE>(createMessage, message.role),\n ]);\n return;\n }\n\n lastRunConfigRef.current = message.runConfig;\n await completePendingToolCalls();\n await chatHelpers.sendMessage(createMessage, {\n metadata: message.runConfig,\n });\n },\n onEdit: async (message) => {\n const createMessage = (\n customToCreateMessage ?? toCreateMessage\n )<UI_MESSAGE>(message);\n\n if (!(message.startRun ?? message.role === \"user\")) {\n chatHelpers.setMessages((current) => [\n ...sliceMessagesUntil(current, message.parentId),\n toUIMessage<UI_MESSAGE>(createMessage, message.role),\n ]);\n return;\n }\n\n lastRunConfigRef.current = message.runConfig;\n chatHelpers.setMessages((current) =>\n sliceMessagesUntil(current, message.parentId),\n );\n await chatHelpers.sendMessage(createMessage, {\n metadata: message.runConfig,\n });\n },\n onDelete: async (messageId) => {\n const threadMessages = runtimeRef.current.thread.getState().messages;\n const messageIndex = threadMessages.findIndex(\n (message) => message.id === messageId,\n );\n if (messageIndex === -1) return;\n\n await deleteHistoryMessage(messageId);\n\n let removedToolArtifact = false;\n let removedToolInteractions = false;\n let removedToolApprovalResponse = false;\n let removedHostApprovalId = false;\n for (const part of threadMessages[messageIndex]!.content) {\n if (part.type === \"tool-call\") {\n removedToolArtifact =\n toolArtifactsRef.current.delete(part.toolCallId) ||\n removedToolArtifact;\n removedToolInteractions =\n toolInteractionsRef.current.delete(part.toolCallId) ||\n removedToolInteractions;\n if (part.approval) {\n ownedApprovals?.delete(part.approval.id);\n removedToolApprovalResponse =\n toolApprovalResponsesRef.current.delete(part.approval.id) ||\n removedToolApprovalResponse;\n removedHostApprovalId =\n hostApprovalIdsRef.current.delete(part.approval.id) ||\n removedHostApprovalId;\n }\n }\n }\n if (removedToolArtifact) markToolArtifactsChanged();\n if (removedToolInteractions) markToolInteractionsChanged();\n if (removedToolApprovalResponse || removedHostApprovalId) {\n if (approvalOwner) notifyHostApprovals(approvalOwner);\n setToolApprovalResponses(new Map(toolApprovalResponsesRef.current));\n }\n\n const deleteIds = new Set(\n getExternalStoreMessages<UI_MESSAGE>(threadMessages[messageIndex]!).map(\n (message) => message.id,\n ),\n );\n chatHelpers.setMessages((current) =>\n current.filter((message) => !deleteIds.has(message.id)),\n );\n },\n onReload: async (parentId: string | null, config) => {\n lastRunConfigRef.current = config.runConfig;\n const newMessages = sliceMessagesUntil(chatHelpers.messages, parentId);\n chatHelpers.setMessages(newMessages);\n\n await chatHelpers.regenerate({ metadata: config.runConfig });\n },\n onAddToolResult: ({\n messageId,\n toolCallId,\n toolName,\n result,\n isError,\n artifact,\n modelContent,\n }) => {\n if (artifact !== undefined) {\n toolArtifactsRef.current.set(toolCallId, artifact);\n markToolArtifactsChanged();\n }\n\n const targetIndex = findRawToolMessageIndex(\n chatHelpers.messages,\n messageId,\n toolCallId,\n joinStrategy,\n );\n\n const errorText =\n typeof result === \"string\" ? result : JSON.stringify(result);\n const output =\n !isError && modelContent !== undefined\n ? wrapModelContentEnvelope(result, modelContent)\n : result;\n\n if (targetIndex >= 0 && targetIndex !== chatHelpers.messages.length - 1) {\n const target = chatHelpers.messages[targetIndex]!;\n const targetPart = target.parts.find(\n (part) => isToolUIPart(part) && part.toolCallId === toolCallId,\n ) as { state?: string; preliminary?: boolean } | undefined;\n // An earlier message's settled output may already have reached the model, as the error a cancelling send writes does.\n if (\n targetPart?.state === \"output-error\" ||\n targetPart?.state === \"output-denied\" ||\n (targetPart?.state === \"output-available\" && !targetPart.preliminary)\n )\n return Promise.resolve();\n\n const targetMessageId = target.id;\n chatHelpers.setMessages((current) =>\n current.map((message) => {\n if (message.id !== targetMessageId) return message;\n\n return {\n ...message,\n parts: message.parts.map((part) => {\n if (!isToolUIPart(part) || part.toolCallId !== toolCallId)\n return part;\n\n const { preliminary: _preliminary, ...finalPart } =\n part as typeof part & { preliminary?: boolean };\n return {\n ...finalPart,\n state: isError\n ? (\"output-error\" as const)\n : (\"output-available\" as const),\n output: isError ? undefined : output,\n errorText: isError ? errorText : undefined,\n } as typeof part;\n }),\n };\n }),\n );\n return Promise.resolve();\n }\n\n const options = { metadata: lastRunConfigRef.current };\n if (isError) {\n return Promise.resolve(\n chatHelpers.addToolOutput({\n state: \"output-error\",\n tool: toolName ?? toolCallId,\n toolCallId,\n errorText,\n options,\n }),\n );\n }\n\n return Promise.resolve(\n chatHelpers.addToolOutput({\n tool: toolName,\n toolCallId,\n output,\n options,\n }),\n );\n },\n onRespondToToolApproval: (response) => {\n if (supersededApprovalProjection.approvalIds.has(response.approvalId))\n return Promise.reject(\n new Error(\n `Tool approval ${response.approvalId} is not waiting for a response.`,\n ),\n );\n return customOnRespondToToolApproval\n ? respondViaHost(customOnRespondToToolApproval, response)\n : respondViaAISDK(response);\n },\n unstable_onRecordToolInteraction: ({\n messageId,\n toolCallId,\n interaction,\n }) => {\n toolInteractionsRef.current.set(\n toolCallId,\n appendToolInteraction(\n toolInteractionsRef.current.get(toolCallId),\n interaction,\n ),\n );\n markToolInteractionsChanged();\n return persistToolInteractions(messageId);\n },\n ...pickExternalStoreSharedOptions(adapter),\n ...(adapter.unstable_messageRepositoryInstance && {\n unstable_messageRepositoryInstance:\n adapter.unstable_messageRepositoryInstance,\n }),\n ...(suggestionAdapter ? { suggestions: generatedSuggestions } : {}),\n ...(onResume && { onResume }),\n ...(onResumeToolCall && { onResumeToolCall }),\n ...(unstable_onBranchChange && { unstable_onBranchChange }),\n adapters: {\n attachments: vercelAttachmentAdapter,\n ...contextAdapters,\n ...adapters,\n },\n extras,\n isLoading,\n });\n\n const setMessagesRef = useRef(chatHelpers.setMessages);\n useInsertionEffect(() => {\n setMessagesRef.current = chatHelpers.setMessages;\n }, [chatHelpers.setMessages]);\n\n useEffect(() => {\n if (hasSeededRepositoryRef.current) return;\n if (!exportedMessageRepository) return;\n if (chatHelpers.messages.length > 0) {\n hasSeededRepositoryRef.current = true;\n return;\n }\n const tempRepo = new MessageRepository();\n tempRepo.import(exportedMessageRepository);\n setMessagesRef.current(\n tempRepo.getMessages().flatMap(getExternalStoreMessages<UI_MESSAGE>),\n );\n hasSeededRepositoryRef.current = true;\n }, [exportedMessageRepository, chatHelpers.messages.length]);\n return runtime;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAgFA,MAAM0D,eACJC,eACAC,kBAEC;CACC,GAAGD;CACHE,IAAIF,cAAcE,MAAMhD,WAAW;CACnCiD,MAAMH,cAAcG,QAAQF;AAC9B;AAEF,MAAMG,8BACJP,aAEC;CACCK,IAAIL,QAAQK;CACZC,MAAMN,QAAQM;CACdE,OAAOR,QAAQS,QACZC,QAAQC,SAASA,KAAKC,SAAS,MAAM,CAAC,CACtCC,KAAKF,UAAU;EAAEC,MAAM;EAAQE,MAAMH,KAAKG;CAAK,EAAE;CACpDC,UAAU;EACR,GAAIf,QAAQe,SAASC,YAAY,EAAEA,UAAUhB,QAAQe,SAASC,SAAS;EACvE,GAAIC,OAAOC,KAAKlB,QAAQe,SAASI,MAAM,CAAC,CAACC,SAAS,KAAK,EACrDD,QAAQnB,QAAQe,SAASI,OAC3B;CACF;AACF;AAqFF,MAAMsB,oBAAiD,CAAA;AAEvD,MAAMC,2BAA0BC,mBAAAC,UAAAC,cAAA;CAAA,MAAAC,IAAArG,EAAA,EAAA;CAK9B,MAAA,CAAAsG,aAAAC,kBACEjG,SAAsC0F,iBAAiB;CACzD,MAAAQ,gBAAsBnG,OAA+B,IAAI;CACzD,MAAAoG,gBAAsBpG,OAAO,KAAK;CAClC,MAAAqG,cAAoBrG,OAAO8F,QAAQ;CAAE,IAAAQ;CAAA,IAAAC;CAAA,IAAAP,EAAA,OAAAF,UAAA;EAClBQ,WAAA;GACjBD,YAAWG,UAAWV;EAAH;EAClBS,KAAA,CAACT,QAAQ;EAACE,EAAA,KAAAF;EAAAE,EAAA,KAAAM;EAAAN,EAAA,KAAAO;CAAA,OAAA;EAAAD,KAAAN,EAAA;EAAAO,KAAAP,EAAA;CAAA;CAFblG,mBAAmBwG,IAEhBC,EAAU;CACb,MAAAE,aAAmBzG,OAAO6F,iBAAiB;CAAE,IAAAa;CAAA,IAAAC;CAAA,IAAAX,EAAA,OAAAH,mBAAA;EAC1Ba,WAAA;GACjBD,WAAUD,UAAWX;EAAH;EACjBc,KAAA,CAACd,iBAAiB;EAACG,EAAA,KAAAH;EAAAG,EAAA,KAAAU;EAAAV,EAAA,KAAAW;CAAA,OAAA;EAAAD,KAAAV,EAAA;EAAAW,KAAAX,EAAA;CAAA;CAFtBlG,mBAAmB4G,IAEhBC,EAAmB;CACtB,MAAAC,aAAmBf,qBAAqB;CAAK,IAAAgB;CAAA,IAAAb,EAAA,OAAAD,WAAA;EAEnCc,WAAA;GACR,MAAAC,yBAAyB;IACvBX,cAAaK,SAAeO,MAAC;IAC7BZ,cAAaK,UAAW;IACxBN,eAAec,KAAwD;GAAC;GAG1E,MAAAC,UAAgBR,WAAUD;GAC1B,IAAI,CAACS,SAAO;IACVH,iBAAiB;IACjBV,cAAaI,UAAWT;IAAH;GAAA;GAIvB,IAAIA,WAAS;IACX,IAAI,CAACK,cAAaI,SAChBM,iBAAiB;IAEnBV,cAAaI,UAAW;IAAH;GAAA;GAIvB,IAAI,CAACJ,cAAaI,SAAQ;GAC1BJ,cAAaI,UAAW;GAExB,MAAAU,kBAAwBb,YAAWG;GACnC,MAAAW,OAAaD,gBAAeE,GAAI,EAAE;GAClC,IAAID,MAAI3D,SAAW,aAAW;GAC9B,IAAI2D,KAAIE,QAAavD,SAAK,mBAAiB;GAE3C,MAAAwD,aAAmB,IAAIC,gBAAgB;GACvCpB,cAAaK,UAAWc;GACxB,MAAA,EAAAE,WAAmBF;GAEd,CAAC,YAAA;IACJ,IAAA;KACE,MAAAG,qBAA2BR,QAAOS,SAAU;MAAA5B,UAChCoB;MAAeM;KAE3B,CAAC;KAED,MAAMxF,wBAAwByF,oBAAoB;MAAAD;MAAAG,UAEtCzB;KACZ,CAAC;IAAC,QAAA,CAAA;GACM,EAAA,CACT;EAAC;EACLF,EAAA,KAAAD;EAAAC,EAAA,KAAAa;CAAA,OAAAA,KAAAb,EAAA;CAAA,IAAA4B;CAAA,IAAA5B,EAAA,OAAAY,cAAAZ,EAAA,OAAAD,WAAA;EAAE6B,KAAA,CAAChB,YAAYb,SAAS;EAACC,EAAA,KAAAY;EAAAZ,EAAA,KAAAD;EAAAC,EAAA,MAAA4B;CAAA,OAAAA,KAAA5B,EAAA;CA/C1BnG,UAAUgH,IA+CPe,EAAuB;CAAC,IAAAC;CAAA,IAAAC;CAAA,IAAA9B,EAAA,QAAA+B,OAAAC,IAAA,2BAAA,GAAA;EAEPH,iBACX;GACL1B,cAAaK,SAAeO,MAAC;EAAC;EAE/Be,KAAA,CAAA;EAAE9B,EAAA,MAAA6B;EAAA7B,EAAA,MAAA8B;CAAA,OAAA;EAAAD,KAAA7B,EAAA;EAAA8B,KAAA9B,EAAA;CAAA;CAJLpF,oBAAoBiH,IAIjBC,EAAE;CAAC,OAEC7B;AAAW;AAGpB,MAAMgC,2CAAgD,IAAIE,IAAI;AAE9D,MAAMC,oCAAoCjE,OAAOkE,OAAO;CACtDC,aAAanE,OAAOkE,uBAAO,IAAIF,IAAY,CAAC;CAC5CI,kBAAkBpE,OAAOkE,uBAAO,IAAIF,IAAY,CAAC;AACnD,CAAC;AAED,MAAMK,6CAGF,IAAIE,IAAI;AAaZ,MAAME,0CAA0B,IAAIC,QAGlC;AAEF,MAAMC,uBACJC,UAEAA,SAASA,MAAMC,OAAO,IAClB,IAAIN,IAAI,CAAC,GAAGK,KAAK,CAAC,CAAChF,KAAK,CAACR,IAAI0F,WAAW,CAAC1F,IAAI0F,MAAM/D,QAAQ,CAAC,CAAC,IAC7DsD;;;;;;;AAQN,MAAMU,8CAA8B,IAAIL,QAAiC;AAEzE,MAAMM,4BAA4BC,OAAeC,aAAyB;CACxE,MAAMC,YAAYJ,4BAA4BK,IAAIH,KAAK,qBAAK,IAAIjB,IAAI;CACpEe,4BAA4BM,IAAIJ,OAAOE,SAAS;CAChDA,UAAUG,IAAIJ,QAAQ;CACtB,aAAa;EACXC,UAAUI,OAAOL,QAAQ;CAC3B;AACF;AAEA,MAAMM,uBAAuBP,UAAkB;CAC7C,KAAK,MAAMC,YAAY,CAAC,GAAIH,4BAA4BK,IAAIH,KAAK,KAAK,CAAA,CAAG,GACvEC,SAAS;AAEb;AAEA,MAAMO,mCACJ9D,UACA+D,iBACArE,cACAO,cACG;CACH,MAAMuC,8BAAc,IAAIH,IAAY;CACpC,MAAMI,mCAAmB,IAAIJ,IAAY;CACzC,MAAM2B,YAAYhE,SAASxB,SAAS;CACpC,IAAIyF;CACJ,IAAIC,wBAAwB;CAC5B,IAAIC,mBAAmB;CAEvB,MAAMC,cAAc;EAClB,MAAMC,kBACJJ,kBAAkBjE,SAASgE,cAC3BC,eAAerG,OAAO0G,MAAMvG,SAAS;GACnC,IACE,CAACvD,aAAauD,IAAI,KAClBA,KAAKwG,UAAU,sBACfxG,KAAKwG,UAAU,kBACfxG,KAAKwG,UAAU,iBAEf,OAAO;GAET,MAAMC,WACJzG,KAMAyG;GACF,MAAMC,aACJD,UAAUC,eACTD,UAAUE,WAAAA,EACPD;GACN,OAAOA,eAAe,eAAeA,eAAe;EACtD,CAAC;EACH,IACER,iBACAC,yBACA,CAACG,mBACD,EAAEpE,aAAagE,kBAAkBjE,SAASgE,aAE1CvB,iBAAiBkB,IAAIM,cAAcxG,EAAE;EAEvCwG,gBAAgBU,KAAAA;EAChBT,wBAAwB;EACxBC,mBAAmB;CACrB;CAEA,KAAK,IAAIS,QAAQ,GAAGA,QAAQ5E,SAASxB,QAAQoG,SAAS;EACpD,MAAMxH,UAAU4C,SAAS4E;EACzB,IAAIxH,QAAQM,SAAS,aACnB0G,MAAM;OACD;GACL,MAAMS,UACHzH,QAAQe,UAAiDC,aAC1D;GACF,IAAIyG,WAAWV,oBAAoBzE,iBAAiB,QAAQ0E,MAAM;GAClEH,gBAAgB7G;GAChB+G,mBAAmBU;EACrB;EAEA,KAAK,MAAM9G,QAAQX,QAAQQ,SAAS,CAAA,GAAI;GACtC,IAAI,CAACpD,aAAauD,IAAI,KAAKA,KAAKwG,UAAU,sBAAsB;GAEhE,MAAMC,WAAWzG,KAAKyG;GACtB,IAAI,CAACA,UAAU;GAEf,MAAMM,aAAaN,SAAS/G;GAC5B,IAAIsG,gBAAgBgB,IAAID,UAAU,GAAG;GAErC,MAAML,aACHD,SAAsCC,cACtCD,SAASE,YACND;GACN,IAAIA,eAAe,eAAeA,eAAe,WAAW;GAE5D,IAAIG,UAAUZ,WAAW;IACvBxB,YAAYmB,IAAImB,UAAU;IAC1B,IAAI1H,QAAQM,SAAS,aAAawG,wBAAwB;GAC5D;EACF;CACF;CACAE,MAAM;CAEN,IAAI5B,YAAYU,SAAS,KAAKT,iBAAiBS,SAAS,GACtD,OAAOZ;CAET,OAAO;EAAEE;EAAaC;CAAiB;AACzC;AAEA,MAAMuC,2BACJhF,UACAiF,WACA3F,YACAI,iBACG;CACH,MAAMwF,oBAAoB9H,YACxBA,QAAQQ,OAAO0G,MACZvG,SAASvD,aAAauD,IAAI,KAAKA,KAAKuB,eAAeA,UACtD,MAAM;CAER,MAAM6F,eAAenF,SAASoF,WAC3BhI,YAAYA,QAAQK,OAAOwH,SAC9B;CACA,IAAIE,iBAAiB,IAAI,OAAO;CAChC,IAAID,iBAAiBlF,SAASmF,aAAc,GAAG,OAAOA;CACtD,IAAIzF,iBAAiB,UAAUM,SAASmF,aAAa,EAAEzH,SAAS,aAC9D,OAAO;CAET,IAAI2H,QAAQF;CACZ,OAAOE,QAAQ,KAAKrF,SAASqF,QAAQ,EAAE,EAAE3H,SAAS,aAAa2H;CAE/D,IAAIC,MAAMH;CACV,OAAOG,MAAM,IAAItF,SAASxB,UAAUwB,SAASsF,MAAM,EAAE,EAAE5H,SAAS,aAC9D4H;CAEF,KAAK,IAAIV,QAAQS,OAAOT,SAASU,KAAKV,SACpC,IAAIM,iBAAiBlF,SAAS4E,MAAO,GAAG,OAAOA;CAEjD,OAAO;AACT;AAEA,MAAMW,eAAeC,UAAiC;CACpD,MAAME,OAAQF,MAA6BE;CAC3C,OAAO;EACLA,MACE,OAAOA,SAAS,WACZA,OACAF,MAAMG,SAAS,UACbH,MAAMG,OACN;EACRvI,SAASoI,MAAMpI;CACjB;AACF;AAEA,MAAawI,mBACXC,aACA1E,UAA2C,CAAC,MACzC;CACH,MAAM,EACJzC,UACAnC,iBAAiBwJ,uBACjB/G,+BAA+B,MAC/BC,UACAC,kBACAC,yBAAyB6G,+BACzBtG,cACAC,mBACAC,4BACEuB;CACJ,MAAMpB,oBAAoBrB,UAAUG;CACpC,MAAMoH,kBAAkBrL,mBAAmB;CAC3C,MAAM,CAACsL,cAAcC,mBAAmBhM,SAEtC,CAAC,CAAC;CACJ,MAAM,CAACkM,mBAAmBC,wBAAwBnM,SAGxC,IAAI;CAGd,MAAMsM,gBAAgBtF,QAAQpC;CAC9B,MAAM2H,iBAAiBD,gBAClB3D,wBAAwBW,IAAIgD,aAAa,YACnC;EACL,MAAME,0BAAU,IAAI/D,IAA2B;EAC/CE,wBAAwBY,IAAI+C,eAAeE,OAAO;EAClD,OAAOA;CACT,EAAA,CAAG,IACHhC,KAAAA;CACJ,MAAM,CAACiC,uBAAuBC,4BAA4B1M,eAElD6I,oBAAoB0D,cAAc,CAAC;CAC3C,MAAM,CAACI,mBAAmBC,wBAAwB5M,SAAS,CAAC;CAC5D,MAAM,CAAC6M,sBAAsBC,2BAA2B9M,SAAS,CAAC;CAClE,MAAM+M,2BAA2BhN,OAC/B,IAAI0I,IAAII,oBAAoB0D,cAAc,CAAC,CAC7C;CACA,MAAMS,sBAAsBjN,OAAO,IAAImI,IAAIqE,gBAAgBpI,KAAK,CAAC,CAAC;CAClE,MAAM8I,qBAAqBlN,OAAO,IAAImI,IAAYqE,gBAAgBpI,KAAK,CAAC,CAAC;CAKzEvE,gBAAgB;EACd,IAAI,CAAC0M,iBAAiB,CAACC,gBAAgB,OAAO/B,KAAAA;EAC9C,MAAM0C,aAAa;GACjB,KAAK,MAAM5J,MAAM0J,oBAAoBzG,SACnCwG,yBAAyBxG,QAAQkD,OAAOnG,EAAE;GAC5C,KAAK,MAAM,CAACA,MAAI0F,UAAUuD,gBACxBQ,yBAAyBxG,QAAQgD,IAAIjG,MAAI0F,MAAM/D,QAAQ;GACzD+H,oBAAoBzG,UAAU,IAAI2B,IAAIqE,eAAepI,KAAK,CAAC;GAC3D8I,mBAAmB1G,UAAU,IAAI2B,IAC/B6E,yBAAyBxG,QAAQpC,KAAK,CACxC;GACAuI,0BAA0BS,SAAS;IACjC,MAAMC,OAAO,IAAI3E,IAAIsE,yBAAyBxG,OAAO;IAIrD,OAFE4G,KAAKpE,SAASqE,KAAKrE,QACnB,CAAC,GAAGqE,IAAI,CAAC,CAACE,OAAO,CAAChK,MAAI2B,cAAckI,KAAK7D,IAAIhG,IAAE,MAAM2B,QAAQ,IAC5CkI,OAAOC;GAC5B,CAAC;EACH;EACA,MAAMG,cAAcrE,yBAAyBoD,eAAeY,IAAI;EAGhEA,KAAK;EACL,OAAOK;CACT,GAAG,CAACjB,eAAeC,cAAc,CAAC;CAKlC,MAAMiB,uBAAuBzN,OAAOuM,aAAa;CACjD,IAAIkB,qBAAqBjH,YAAY+F,eAAe;EAClDkB,qBAAqBjH,UAAU+F;EAC/BW,mBAAmB1G,UAAU,IAAI2B,IAAYqE,gBAAgBpI,KAAK,CAAC;EACnE4I,yBAAyBxG,UAAU,IAAIkC,IACrCI,oBAAoB0D,cAAc,CACpC;EACAS,oBAAoBzG,UAAU,IAAI2B,IAAIqE,gBAAgBpI,KAAK,CAAC;EAC5DuI,yBAAyB,IAAIjE,IAAIsE,yBAAyBxG,OAAO,CAAC;CACpE;CACA,MAAMkH,2BAA2B1N,uBAC/B,IAAI0I,IAAI,CACV;CACA,MAAMiF,wBAAwB3N,uBAC5B,IAAI0I,IAAI,CACV;CACA,MAAMkF,uBAAuB5N,uBAE3B,IAAI6I,QAAQ,CAAC;CACf,MAAMgF,yBAAyB7N,uBAAoC,IAAI0I,IAAI,CAAC;CAC5E,MAAMoF,mBAAmB9N,uBAA6B,IAAI0I,IAAI,CAAC;CAC/D,MAAMqF,sBAAsB/N,uBAC1B,IAAI0I,IAAI,CACV;CACA,MAAMsF,mBAAmBhO,OAA8ByK,KAAAA,CAAS;CAChE,MAAMwD,2BAA2BrO,kBAAkB;EACjDiN,sBAAsBqB,UAAUA,QAAQ,CAAC;CAC3C,GAAG,CAAA,CAAE;CACL,MAAMC,8BAA8BvO,kBAAkB;EACpDmN,yBAAyBmB,YAAUA,UAAQ,CAAC;CAC9C,GAAG,CAAA,CAAE;CAEL,MAAME,oBAAoBjK,OAAOkK,OAAOrC,YAAY,CAAC,CAAC5B,MACnDkE,MAAMA,GAAGxK,SAAS,WACrB;CACA,MAAMyK,oBACJ5C,YAAYtE,WAAW,eAAesE,YAAYtE,WAAW;CAC/D,MAAMtB,YAAYwI,qBAAqBH;CACvC,MAAMI,wBAAwBxO,OAAOuO,iBAAiB;CAEtD,MAAME,gBAAgB1L,qBAAmB4I,YAAY7F,UAAUC,SAAS;CAIxE,MAAM2I,cAAc/C,YAAY7F,SAASsB,GAAG,EAAE;CAC9C,MAAMuH,sBACJ5I,aAAa2I,aAAalL,SAAS,cAAckL,YAAYnL,KAAKkH,KAAAA;CAEpE,MAAMmE,sBACJzC,mBAAmBE,WAAWV,YAAYpI,KACtC4I,kBAAkBG,MAClBrE;CACN,MAAM4G,oCACJ/C,iCAAiC;CACnC,MAAMgD,kCAAkC9O,OACtCoI,iCACF;CACA,MAAM2G,+BAA+BhP,cAC7B;EACJ,MAAMiP,aAAapF,gCACjB+B,YAAY7F,UACZoH,mBAAmB1G,SACnBhB,cACAO,SACF;EACA,MAAMkJ,WAAWH,gCAAgCtI;EACjD,IACEwI,WAAW1G,YAAYU,SAASiG,SAAS3G,YAAYU,QACrDgG,WAAWzG,iBAAiBS,SAASiG,SAAS1G,iBAAiBS,QAC/D,CAAC,GAAGgG,WAAW1G,WAAW,CAAC,CAACiF,OAAOhK,SACjC0L,SAAS3G,YAAYuC,IAAItH,IAAE,CAC7B,KACA,CAAC,GAAGyL,WAAWzG,gBAAgB,CAAC,CAACgF,OAAOhK,SACtC0L,SAAS1G,iBAAiBsC,IAAItH,IAAE,CAClC,GAEA,OAAO0L;EAETH,gCAAgCtI,UAAUwI;EAC1C,OAAOA;CACT,GAEA;EAACrD,YAAY7F;EAAUN;EAAcO;EAAW2G;CAAqB,CACvE;CAEA,MAAMwC,mBAAmBtP,aACtBuP,mBAAiC;EAChC,MAAMlL,WAA0C;GAC9C4K;GACAO,eAAetB,iBAAiBtH;GAChC6I,kBAAkBtB,oBAAoBvH;GACtCkG,uBAAuBM,yBAAyBxG;EAClD;EACA,OAAOhE,sBAAsB0M,iBAC3BC,gBACA,OACAlL,QACF;CACF,GACA,CAAC4K,iCAAiC,CACpC;CAEA,MAAMS,sBAAsB1P,aACzByM,QAAgBtB,cAAsB;EACrCqB,sBAAsBgB,WAAS;GAC7B,IAAIA,QAAMf,WAAWA,UAAU,CAACe,OAAKd,IAAIzB,IAAIE,SAAS,GAAG,OAAOqC;GAChE,MAAMd,MAAM,IAAInE,IAAIiF,OAAKd,GAAG;GAC5BA,IAAI5C,OAAOqB,SAAS;GACpB,OAAO;IAAEsB;IAAQC;GAAI;EACvB,CAAC;CACH,GACA,CAAA,CACF;CAIA,MAAMiD,mBACJhB,qBAAqBG,aAAalL,SAAS,cACvCkL,YAAYnL,KACZkH,KAAAA;CAEN5K,gBAAgB;EACd,MAAM2P,qBAAqBhB,sBAAsBhI;EACjDgI,sBAAsBhI,UAAU+H;EAChC,IAAIiB,sBAAsB,CAACD,kBAAkB;EAC7CD,oBAAoB3D,YAAYpI,IAAIgM,gBAAgB;CACtD,GAAG;EACDhB;EACAgB;EACA5D,YAAYpI;EACZ+L;CAAmB,CACpB;CAED,MAAMxJ,WAAWtD,sBAAsBiN,kBAAkB;EACvD1J;EACAD,UAAU6F,YAAY7F;EACtBN;EACAvB,UAAUlE,eACD;GACLiM;GACAyC;GACAiB,uBAAuBhC,yBAAyBlH;GAChDmJ,mBAAmB/B,qBAAqBpH;GACxCoJ,oBAAoBjC,sBAAsBnH;GAC1CqJ,qBAAqBhC,uBAAuBrH;GAC5C4I,eAAetB,iBAAiBtH;GAChC6I,kBAAkBtB,oBAAoBvH;GACtCqI;GACAiB,0BAA0Bf,6BAA6BzG;GACvDyH,2BACEhB,6BAA6BxG;GAC/B,GAAIoG,uBAAuB,EAAEA,oBAAoB;GACjD,GAAIhD,YAAYL,SAAS,EACvBA,OAAOD,YAAYM,YAAYL,KAAK,EACtC;GACA,GAAIsD,oBAAoB5F,OAAO,KAAK,EAAE4F,oBAAoB;GAC1D,GAAIlC,sBAAsB1D,OAAO,KAAK,EAAE0D,sBAAsB;EAChE,IACA;GACEV;GACAyC;GACAE;GACAhD,YAAYL;GACZsD;GACAlC;GACAmC;GACAE;GACAnC;GACAE;EAAoB,CAExB;CACF,CAAC;CAED,MAAMkD,4BAA4BjQ,cAAc;EAC9C,IAAI,CAAC0F,mBAAmB,OAAOgF,KAAAA;EAC/B,MAAMwF,YAAYnN,4BAChBoM,kBACAzJ,iBACF;EACA,OAAOwK,UAAUnK,SAASxB,SAAS,IAAI2L,YAAYxF,KAAAA;CACrD,GAAG,CAAChF,mBAAmByJ,gBAAgB,CAAC;CAExC,MAAMgB,uBAAuBtK,wBAC3BC,mBACAC,UACAC,SACF;CAEA,MAAM,CAACoK,cAAclQ,gBAAgB,EACnC,IAAIuG,UAA4B;EAC9B,OAAO4J;CACT,EACF,EAAE;CAEF,MAAM,EACJC,WACAC,eAAeC,sBACfC,yBACAC,iCACE5N,mBACFsN,YACA3L,UAAUE,WAAWqH,iBAAiBrH,SACtCwK,kBACAtM,uBAICkD,eAAa;EACZ6F,YAAY+E,YAAY5K,UAAQ;CAClC,GACAgI,iBAAiBtH,SACjByH,0BACAF,oBAAoBvH,SACpB2H,6BACAnB,yBAAyBxG,eACnB;EACJ,KAAK,MAAM,CAACjD,MAAI0F,YAAUuD,kBAAkB,CAAA,GAC1CQ,yBAAyBxG,QAAQgD,IAAIjG,MAAI0F,QAAM/D,QAAQ;EAEzDgI,mBAAmB1G,UAAU,IAAI2B,IAC/B6E,yBAAyBxG,QAAQpC,KAAK,CACxC;EACAuI,yBAAyB,IAAIjE,IAAIsE,yBAAyBxG,OAAO,CAAC;CACpE,CACF;CAEA,MAAM,EACJjD,IAAI8I,UACJvG,UAAU6K,cACVtJ,QAAQuJ,YACRtF,UACEK;CACJ,MAAMkF,SAAS9Q,cAEXiD,YAAY8N,QAAQ;EAClBC,MAAMpF;EACNL;CACF,CAAC,GAEH;EAACe;EAAQsE;EAAcC;EAAYtF;CAAK,CAC1C;CAEA,MAAM0F,2BAA2B,YAAY;EAC3C,IAAI,CAAClM,8BAA8B;EAQnC6G,YAAY+E,aAAa5K,eAAa;GACpC,IAAImL,aAAa;GAEjB,MAAM5D,SAAOvH,WAAS/B,KAAKb,YAAY;IACrC,IAAIA,QAAQM,SAAS,aAAa,OAAON;IAEzC,IAAIgO,iBAAiB;IACrB,MAAMxN,QAAQR,QAAQQ,OAAOK,KAAKF,SAAS;KACzC,IAAI,CAACvD,aAAauD,IAAI,GAAG,OAAOA;KAChC,IACEA,KAAKwG,UAAU,sBACfxG,KAAKwG,UAAU,kBACfxG,KAAKwG,UAAU,iBAEf,OAAOxG;KAETqN,iBAAiB;KACjB,MAAM,EAAE5G,UAAU6G,WAAW,GAAGC,SAASvN;KACzC,OAAO;MACL,GAAGuN;MACH/G,OAAO;MACPiH,WAAW;KACb;IACF,CAAC;IAED,IAAI,CAACJ,gBAAgB,OAAOhO;IAC5B+N,aAAa;IACb,OAAO;KAAE,GAAG/N;KAASQ;IAAM;GAC7B,CAAC;GAED,IAAI,CAACuN,YAAY,OAAOnL;GACxB,OAAOuH;EACT,CAAC;CACH;CAEA,MAAM/H,mBAAmB,EACvBsF,YACA2G,UACAC,aAEAjM,QAAQkM,QACN9F,YAAY+F,wBAAwB;EAClCnO,IAAIqH;EACJ2G;EACA,GAAIC,UAAU,QAAQ,EAAEA,OAAO;EAC/BG,SAAS,EAAE1N,UAAU+J,iBAAiBxH,QAAQ;CAChD,CAAC,CACH;CAEF,MAAMoL,iBAAiB,OACrBC,WACA3M,eACG;EACH,MAAM,EAAE0F,YAAAA,iBAAe1F;EACvB,MAAM4M,YAAYnG,YAAY7F,SAC3BiM,SAAS7O,cACRA,UAAQQ,MAAMqO,SAASlO,WACrBvD,aAAauD,MAAI,IAAI,CAAC;GAAEkH,WAAW7H,UAAQK;GAAIM,MAAAA;EAAK,CAAC,IAAI,CAAA,CAC3D,CACF,CAAC,CACAmO,MACE,EAAEnO,MAAAA,aACDA,OAAKwG,UAAU,wBACfxG,OAAKyG,UAAU/G,OAAOqH,YAC1B;EACF,IAAI,CAACkH,aAAa5E,mBAAmB1G,QAAQqE,IAAID,YAAU,GACzD,MAAM,IAAIW,MACR,iBAAiBX,aAAU,gCAC7B;EAOF,MAAMqH,cAAczF;EACpB,MAAM0F,eAAe3F;EACrB,MAAM4F,mBAAmBnF,yBAAyBxG;EAIlD,IAAI4L,YAAY;EAChB,MAAMC,iBAAiBC,YAAqB;GAC1CF,YAAYE;GAGZ,IAAIA,SACFL,aAAazI,IAAIoB,cAAY,EAC3B1F,UAAAA,WACF,CAAC;QACE+M,aAAavI,OAAOkB,YAAU;GAEnC,IAAIsH,cAAc;IAGhBvI,oBAAoBuI,YAAY;IAChC;GACF;GAEA,IAAIzE,qBAAqBjH,YAAY0L,cAAc;GACnD,IAAII,SAASpF,mBAAmB1G,QAAQiD,IAAImB,YAAU;QACjDsC,mBAAmB1G,QAAQkD,OAAOkB,YAAU;GACjD,IAAI0H,SAAStF,yBAAyBxG,QAAQgD,IAAIoB,cAAY1F,UAAQ;QACjE8H,yBAAyBxG,QAAQkD,OAAOkB,YAAU;GACvD+B,yBAAyB,IAAIjE,IAAIsE,yBAAyBxG,OAAO,CAAC;EACpE;EAEA6L,cAAc,IAAI;EAClB,IAAI;GACF,MAAMR,UAAU3M,YAAU;IACxBE,YAAY0M,UAAUjO,KAAKuB;IAC3BC,UAAU7E,YAAYsR,UAAUjO,IAAI;IACpCyB,iBAAiB,YAAY;KAC3B,IAAI;MACF,MAAMA,gBAAgBJ,UAAQ;KAChC,UAAU;MACRmN,cAAc,KAAK;KACrB;IACF;GACF,CAAC;EACH,SAAS/G,SAAO;GACd,IAAI8G,WAAWC,cAAc,KAAK;GAClC,MAAM/G;EACR;EACA,MAAMiH,iBACJN,aAAapH,IAAID,YAAU,KAAKuH,iBAAiBtH,IAAID,YAAU;EACjE,IAAIwH,aAAaG,gBACf,MAAM9B,6BAA6BqB,UAAU/G,SAAS;CAE1D;CAEA,MAAMyH,yBAAyBxS,OAAO,KAAK;CAC3C,MAAMyS,uBACJzC,6BAA6B,QAC7B,CAACwC,uBAAuBhM,WACxBV,SAASxB,WAAW;CAEtB,MAAM8L,UAAU3P,wBAAwB;EACtCiS,0BAA0B;EAC1B3M,WAAWwI;EACX,GAAIkE,uBACA,EAAEhN,mBAAmBuK,0BAA0B,IAC/C,EAAElK,SAAS;EACf6M,gCAAgC;EAChC1G;EACAyE,cAAc5K,eACZ6F,YAAY+E,YACV5K,WACG/B,IAAIxB,mBAA+B,CAAC,CACpCqB,OAAOgP,OAAO,CAAC,CACfC,KAAK,CACV;EACFC,WAAWhN,eACT6F,YAAY+E,YACV5K,WACG/B,IAAIxB,mBAA+B,CAAC,CACpCqB,OAAOgP,OAAO,CAAC,CACfC,KAAK,CACV;EACFE,oBAAoB7P,cAClByI,YAAY+E,aAAalK,YAAY,CACnC,GAAGA,SACH/C,2BAAuCP,SAAO,CAAC,CAChD;EACH8P,6BAAkE;GAChE,MAAMC,WAAW9C,WAAW3J,QAAQ0M,OAAOC,OAAO;GAElD,MAAMC,mBAAoD,CAAA;GAC1D,MAAMC,iCAAiB,IAAI3K,IAAoB;GAE/C,KAAK,MAAM4K,QAAQL,SAASnN,UAAU;IACpC,MAAMyN,gBAAgB1R,yBACpByR,KAAKpQ,OACP;IACA,IAAIsQ,WACFF,KAAKE,YAAY,OACZH,eAAe9J,IAAI+J,KAAKE,QAAQ,KAAKF,KAAKE,WAC3C;IACN,KAAK,MAAMC,gBAAgBF,eAAe;KACxCH,iBAAiBM,KAAK;MAAEF;MAAUtQ,SAASuQ;KAAa,CAAC;KACzDD,WAAW5Q,qBAAqB+Q,MAAMF,YAAyB;IACjE;IACA,IAAIF,cAAcjP,SAAS,GACzB+O,eAAe7J,IACb8J,KAAKpQ,QAAQK,IACbX,qBAAqB+Q,MACnBJ,cAAcA,cAAcjP,SAAS,EACvC,CACF;GAEJ;GAEA,MAAMsP,SAA8C,EAClD9N,UAAUsN,iBACZ;GAEA,IAAIH,SAASY,UAAU,MACrBD,OAAOC,SAASR,eAAe9J,IAAI0J,SAASY,MAAM,KAAKZ,SAASY;GAGlE,OAAOD;EACT;EACAE,sBAAsBC,SAA8C;GAElE,MAAMC,eAAelR,4BAA4BoM,kBAAkB6E,IAAI;GAGvE5D,WAAW3J,QAAQ0M,OAAOe,OAAOD,YAAY;EAC/C;EACAE,UAAU,YAAY;GACpB,MAAMhR,YAAUyI,YAAY7F,SAASsB,GAAG,EAAE;GAC1C,MAAM+M,cACJpO,aAAa7C,WAASM,SAAS,cAAcN,UAAQK,KAAKkH,KAAAA;GAC5D,IAAI0J,aAAa;IACf,MAAMC,UAAU,IAAIjM,IAAIwD,YAAY7F,SAAS/B,KAAKsQ,MAAMA,EAAE9Q,EAAE,CAAC;IAC7D6I,sBAAsBgB,WAAS;KAC7B,MAAMkH,OACJlH,QAAMf,WAAWV,YAAYpI,KACzB,CAAC,GAAG6J,OAAKd,GAAG,CAAC,CAAC1I,QAAQL,SAAO6Q,QAAQvJ,IAAItH,IAAE,CAAC,IAC5C,CAAA;KACN,OAAO;MACL8I,QAAQV,YAAYpI;MACpB+I,qBAAK,IAAInE,IAAI,CAAC,GAAGmM,MAAMH,WAAW,CAAC;KACrC;IACF,CAAC;GACH;GACA,IAAI;IACF,MAAMxI,YAAY4I,KAAK;GACzB,SAASjJ,SAAO;IACd,IAAI,EAAEA,mBAAiBC,SAASD,QAAMG,SAAS,eAAe;KAC5D,IAAI0I,aAAa7E,oBAAoB3D,YAAYpI,IAAI4Q,WAAW;KAChE,MAAM7I;IACR;GACF;EACF;EACAkJ,OAAO,OAAOtR,cAAY;GACxB,MAAMG,iBACJwI,yBAAyBxJ,gBAAAA,CACba,SAAO;GAErB,IAAI,EAAEA,UAAQuR,YAAYvR,UAAQM,SAAS,SAAS;IAClDmI,YAAY+E,aAAalK,cAAY,CACnC,GAAGA,WACHpD,YAAwBC,eAAeH,UAAQM,IAAI,CAAC,CACrD;IACD;GACF;GAEAwK,iBAAiBxH,UAAUtD,UAAQwR;GACnC,MAAM1D,yBAAyB;GAC/B,MAAMrF,YAAYgJ,YAAYtR,eAAe,EAC3CY,UAAUf,UAAQwR,UACpB,CAAC;EACH;EACAE,QAAQ,OAAO1R,cAAY;GACzB,MAAMG,mBACJwI,yBAAyBxJ,gBAAAA,CACba,SAAO;GAErB,IAAI,EAAEA,UAAQuR,YAAYvR,UAAQM,SAAS,SAAS;IAClDmI,YAAY+E,aAAalK,cAAY,CACnC,GAAGpE,mBAAmBoE,WAAStD,UAAQsQ,QAAQ,GAC/CpQ,YAAwBC,iBAAeH,UAAQM,IAAI,CAAC,CACrD;IACD;GACF;GAEAwK,iBAAiBxH,UAAUtD,UAAQwR;GACnC/I,YAAY+E,aAAalK,cACvBpE,mBAAmBoE,WAAStD,UAAQsQ,QAAQ,CAC9C;GACA,MAAM7H,YAAYgJ,YAAYtR,iBAAe,EAC3CY,UAAUf,UAAQwR,UACpB,CAAC;EACH;EACAG,UAAU,OAAO9J,gBAAc;GAC7B,MAAM+J,iBAAiB3E,WAAW3J,QAAQ0M,OAAO6B,SAAS,CAAC,CAACjP;GAC5D,MAAMmF,eAAe6J,eAAe5J,WACjChI,cAAYA,UAAQK,OAAOwH,WAC9B;GACA,IAAIE,iBAAiB,IAAI;GAEzB,MAAMsF,qBAAqBxF,WAAS;GAEpC,IAAIiK,sBAAsB;GAC1B,IAAIC,0BAA0B;GAC9B,IAAIC,8BAA8B;GAClC,IAAIC,wBAAwB;GAC5B,KAAK,MAAMtR,UAAQiR,eAAe7J,aAAa,CAAEtH,SAC/C,IAAIE,OAAKC,SAAS,aAAa;IAC7BkR,sBACElH,iBAAiBtH,QAAQkD,OAAO7F,OAAKuB,UAAU,KAC/C4P;IACFC,0BACElH,oBAAoBvH,QAAQkD,OAAO7F,OAAKuB,UAAU,KAClD6P;IACF,IAAIpR,OAAKyG,UAAU;KACjBkC,gBAAgB9C,OAAO7F,OAAKyG,SAAS/G,EAAE;KACvC2R,8BACElI,yBAAyBxG,QAAQkD,OAAO7F,OAAKyG,SAAS/G,EAAE,KACxD2R;KACFC,wBACEjI,mBAAmB1G,QAAQkD,OAAO7F,OAAKyG,SAAS/G,EAAE,KAClD4R;IACJ;GACF;GAEF,IAAIH,qBAAqB/G,yBAAyB;GAClD,IAAIgH,yBAAyB9G,4BAA4B;GACzD,IAAI+G,+BAA+BC,uBAAuB;IACxD,IAAI5I,eAAe5C,oBAAoB4C,aAAa;IACpDI,yBAAyB,IAAIjE,IAAIsE,yBAAyBxG,OAAO,CAAC;GACpE;GAEA,MAAM4O,YAAY,IAAIjN,IACpBtG,yBAAqCiT,eAAe7J,aAAc,CAAC,CAAClH,KACjEb,cAAYA,UAAQK,EACvB,CACF;GACAoI,YAAY+E,aAAalK,cACvBA,UAAQ5C,QAAQV,cAAY,CAACkS,UAAUvK,IAAI3H,UAAQK,EAAE,CAAC,CACxD;EACF;EACA8R,UAAU,OAAO7B,YAAyB8B,WAAW;GACnDtH,iBAAiBxH,UAAU8O,OAAOZ;GAClC,MAAMa,cAAcnT,mBAAmBuJ,YAAY7F,UAAU0N,UAAQ;GACrE7H,YAAY+E,YAAY6E,WAAW;GAEnC,MAAM5J,YAAY6J,WAAW,EAAEvR,UAAUqR,OAAOZ,UAAU,CAAC;EAC7D;EACAe,kBAAkB,EAChB1K,WAAAA,aACA3F,YACAC,UACAuO,QAAAA,UACA8B,SACAC,UACAC,mBACI;GACJ,IAAID,aAAalL,KAAAA,GAAW;IAC1BqD,iBAAiBtH,QAAQgD,IAAIpE,YAAYuQ,QAAQ;IACjD1H,yBAAyB;GAC3B;GAEA,MAAM4H,cAAc/K,wBAClBa,YAAY7F,UACZiF,aACA3F,YACAI,YACF;GAEA,MAAM8L,YACJ,OAAOsC,aAAW,WAAWA,WAASkC,KAAKC,UAAUnC,QAAM;GAC7D,MAAMoC,SACJ,CAACN,WAAWE,iBAAiBnL,KAAAA,IACzB/H,yBAAyBkR,UAAQgC,YAAY,IAC7ChC;GAEN,IAAIiC,eAAe,KAAKA,gBAAgBlK,YAAY7F,SAASxB,SAAS,GAAG;IACvE,MAAM2R,SAAStK,YAAY7F,SAAS+P;IACpC,MAAMK,aAAaD,OAAOvS,MAAMsO,MAC7BnO,WAASvD,aAAauD,MAAI,KAAKA,OAAKuB,eAAeA,UACtD;IAEA,IACE8Q,YAAY7L,UAAU,kBACtB6L,YAAY7L,UAAU,mBACrB6L,YAAY7L,UAAU,sBAAsB,CAAC6L,WAAWC,aAEzD,OAAO5Q,QAAQkM,QAAQ;IAEzB,MAAM2E,kBAAkBH,OAAO1S;IAC/BoI,YAAY+E,aAAalK,cACvBA,UAAQzC,KAAKb,cAAY;KACvB,IAAIA,UAAQK,OAAO6S,iBAAiB,OAAOlT;KAE3C,OAAO;MACL,GAAGA;MACHQ,OAAOR,UAAQQ,MAAMK,KAAKF,WAAS;OACjC,IAAI,CAACvD,aAAauD,MAAI,KAAKA,OAAKuB,eAAeA,YAC7C,OAAOvB;OAET,MAAM,EAAEsS,aAAaE,cAAc,GAAGC,cACpCzS;OACF,OAAO;QACL,GAAGyS;QACHjM,OAAOqL,UACF,iBACA;QACLM,QAAQN,UAAUjL,KAAAA,IAAYuL;QAC9B1E,WAAWoE,UAAUpE,YAAY7G,KAAAA;OACnC;MACF,CAAC;KACH;IACF,CAAC,CACH;IACA,OAAOlF,QAAQkM,QAAQ;GACzB;GAEA,MAAME,UAAU,EAAE1N,UAAU+J,iBAAiBxH,QAAQ;GACrD,IAAIkP,SACF,OAAOnQ,QAAQkM,QACb9F,YAAY4K,cAAc;IACxBlM,OAAO;IACPmM,MAAMnR,YAAYD;IAClBA;IACAkM;IACAK;GACF,CAAC,CACH;GAGF,OAAOpM,QAAQkM,QACb9F,YAAY4K,cAAc;IACxBC,MAAMnR;IACND;IACA4Q;IACArE;GACF,CAAC,CACH;EACF;EACA1M,0BAA0BC,eAAa;GACrC,IAAI6J,6BAA6BzG,YAAYuC,IAAI3F,WAAS0F,UAAU,GAClE,OAAOrF,QAAQkR,uBACb,IAAIlL,MACF,iBAAiBrG,WAAS0F,WAAU,gCACtC,CACF;GACF,OAAOkB,gCACH8F,eAAe9F,+BAA+B5G,UAAQ,IACtDI,gBAAgBJ,UAAQ;EAC9B;EACAwR,mCAAmC,EACjC3L,WAAAA,aACA3F,YAAAA,cACAuR,kBACI;GACJ5I,oBAAoBvH,QAAQgD,IAC1BpE,cACArD,sBACEgM,oBAAoBvH,QAAQ+C,IAAInE,YAAU,GAC1CuR,WACF,CACF;GACAxI,4BAA4B;GAC5B,OAAOqC,wBAAwBzF,WAAS;EAC1C;EACA,GAAGjJ,+BAA+BmF,OAAO;EACzC,GAAIA,QAAQrC,sCAAsC,EAChDA,oCACEqC,QAAQrC,mCACZ;EACA,GAAIiB,oBAAoB,EAAEI,aAAaiK,qBAAqB,IAAI,CAAC;EACjE,GAAInL,YAAY,EAAEA,SAAS;EAC3B,GAAIC,oBAAoB,EAAEA,iBAAiB;EAC3C,GAAIU,2BAA2B,EAAEA,wBAAwB;EACzDlB,UAAU;GACRoS,aAAatU;GACb,GAAGyJ;GACH,GAAGvH;EACL;EACAqM;EACAR;CACF,CAAC;CAED,MAAMwG,iBAAiB7W,OAAO2L,YAAY+E,WAAW;CACrD5Q,yBAAyB;EACvB+W,eAAerQ,UAAUmF,YAAY+E;CACvC,GAAG,CAAC/E,YAAY+E,WAAW,CAAC;CAE5B7Q,gBAAgB;EACd,IAAI2S,uBAAuBhM,SAAS;EACpC,IAAI,CAACwJ,2BAA2B;EAChC,IAAIrE,YAAY7F,SAASxB,SAAS,GAAG;GACnCkO,uBAAuBhM,UAAU;GACjC;EACF;EACA,MAAMsQ,WAAW,IAAI7U,kBAAkB;EACvC6U,SAAS7C,OAAOjE,yBAAyB;EACzC6G,eAAerQ,QACbsQ,SAASC,YAAY,CAAC,CAAChF,QAAQlQ,wBAAoC,CACrE;EACA2Q,uBAAuBhM,UAAU;CACnC,GAAG,CAACwJ,2BAA2BrE,YAAY7F,SAASxB,MAAM,CAAC;CAC3D,OAAO8L;AACT;AAhkCgC,SAAApJ,MAAAoG,MAAA;CAAA,OAuBAA,KAAI9I,WAAY,IAAhB8I,OAAAzH;AAA4C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChatRuntime.js","names":["c","_c","UIMessage","AssistantCloud","AssistantRuntime","useCloudThreadListAdapter","useRemoteThreadListRuntime","useAui","useAuiState","useHostDestroySignal","useChatThread","ChatThreadOptions","AI_SDK_SDK","UseChatRuntimeOptions","UI_MESSAGE","cloud","onThreadIdChange","threadId","useChatThreadRuntime","options","hostDestroySignal","$","id","_temp","isMainThread","_temp2","aui","t0","threadListItem","source","undefined","t1","getThreadListItem","stopOnClientDestroy","useChatRuntime","cloudAdapter","sdk","runtimeHook","RuntimeHook","adapter","allowNesting","s","s_0","threads","mainThreadId"],"sources":["../../src/runtime/useChatRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport type { UIMessage } from \"@ai-sdk/react\";\nimport type { AssistantCloud } from \"assistant-cloud\";\nimport type { AssistantRuntime } from \"@assistant-ui/core\";\nimport {\n useCloudThreadListAdapter,\n useRemoteThreadListRuntime,\n} from \"@assistant-ui/core/react\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport { useHostDestroySignal } from \"@assistant-ui/store/internal\";\nimport { useChatThread, type ChatThreadOptions } from \"./useChatThread\";\nimport { AI_SDK_SDK } from \"./sdkIdentity\";\n\nexport type UseChatRuntimeOptions<UI_MESSAGE extends UIMessage = UIMessage> =\n ChatThreadOptions<UI_MESSAGE> & {\n cloud?: AssistantCloud | undefined;\n onThreadIdChange?: ((threadId: string | undefined) => void) | undefined;\n };\n\nconst useChatThreadRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(\n options: ChatThreadOptions<UI_MESSAGE> | undefined,\n hostDestroySignal: AbortSignal,\n): AssistantRuntime => {\n const id = useAuiState((s) => s.threadListItem.id);\n const isMainThread = useAuiState(\n (s) => s.threads.mainThreadId === s.threadListItem.id,\n );\n const aui = useAui();\n return useChatThread(options, {\n id,\n isMainThread,\n getThreadListItem: () =>\n aui.threadListItem.source ? aui.threadListItem : undefined,\n stopOnClientDestroy: true,\n hostDestroySignal,\n });\n};\n\nexport const useChatRuntime = <UI_MESSAGE extends UIMessage = UIMessage>({\n cloud,\n onThreadIdChange,\n ...options\n}: UseChatRuntimeOptions<UI_MESSAGE> = {}): AssistantRuntime => {\n const hostDestroySignal = useHostDestroySignal();\n const cloudAdapter = useCloudThreadListAdapter({ cloud, sdk: AI_SDK_SDK });\n return useRemoteThreadListRuntime({\n runtimeHook: function RuntimeHook() {\n return useChatThreadRuntime(options, hostDestroySignal);\n },\n adapter: cloudAdapter,\n allowNesting: true,\n onThreadIdChange,\n });\n};\n"],"mappings":";;;;;;;;AAoBA,MAAMkB,wBAAuBC,SAAAC,sBAAA;CAAA,MAAAC,IAAApB,EAAA,CAAA;CAI3B,MAAAqB,KAAWd,YAAYe,KAA0B;CACjD,MAAAC,eAAqBhB,YACnBiB,MACF;CACA,MAAAC,MAAYnB,OAAO;CAAE,IAAAoB;CAAA,IAAAN,EAAA,OAAAK,KAAA;EAIAC,WACjBD,IAAGE,eAAeC,SAAUH,IAAGE,iBAA/BE,KAAAA;EAA0DT,EAAA,KAAAK;EAAAL,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAAA,IAAAU;CAAA,IAAAV,EAAA,OAAAD,qBAAAC,EAAA,OAAAC,MAAAD,EAAA,OAAAG,gBAAAH,EAAA,OAAAM,IAAA;EAJhCI,KAAA;GAAAT;GAAAE;GAAAQ,mBAGTL;GACyCM,qBACvC;GAAIb;EAE3B;EAACC,EAAA,KAAAD;EAAAC,EAAA,KAAAC;EAAAD,EAAA,KAAAG;EAAAH,EAAA,KAAAM;EAAAN,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CAAA,OAPMX,cAAcS,SAASY,EAO7B;AAAC;AAGJ,MAAaG,kBAA4D,EACvEnB,OACAC,kBACA,GAAGG,YACkC,CAAC,MAAwB;CAC9D,MAAMC,oBAAoBX,qBAAqB;CAC/C,MAAM0B,eAAe9B,0BAA0B;EAAEU;EAAOqB,KAAKxB;CAAW,CAAC;CACzE,OAAON,2BAA2B;EAChC+B,aAAa,SAASC,cAAc;GAClC,OAAOpB,qBAAqBC,SAASC,iBAAiB;EACxD;EACAmB,SAASJ;EACTK,cAAc;EACdxB;CACF,CAAC;AACH;AAlC6B,SAAAO,MAAAkB,GAAA;CAAA,OAIGA,EAACb,eAAeN;AAAG;AAJtB,SAAAG,OAAAiB,KAAA;CAAA,OAMlBD,IAACE,QAAQC,iBAAkBH,IAACb,eAAeN;AAAG"}
|
|
1
|
+
{"version":3,"file":"useChatRuntime.js","names":["c","_c","UIMessage","AssistantCloud","AssistantRuntime","useCloudThreadListAdapter","useRemoteThreadListRuntime","useAui","useAuiState","useHostDestroySignal","useChatThread","ChatThreadOptions","AI_SDK_SDK","UseChatRuntimeOptions","UI_MESSAGE","cloud","onThreadIdChange","threadId","useChatThreadRuntime","options","hostDestroySignal","$","id","_temp","isMainThread","_temp2","aui","t0","threadListItem","source","undefined","t1","getThreadListItem","stopOnClientDestroy","useChatRuntime","cloudAdapter","sdk","runtimeHook","RuntimeHook","adapter","allowNesting","s","s_0","threads","mainThreadId","_c"],"sources":["../../src/runtime/useChatRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport type { UIMessage } from \"@ai-sdk/react\";\nimport type { AssistantCloud } from \"assistant-cloud\";\nimport type { AssistantRuntime } from \"@assistant-ui/core\";\nimport {\n useCloudThreadListAdapter,\n useRemoteThreadListRuntime,\n} from \"@assistant-ui/core/react\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport { useHostDestroySignal } from \"@assistant-ui/store/internal\";\nimport { useChatThread, type ChatThreadOptions } from \"./useChatThread\";\nimport { AI_SDK_SDK } from \"./sdkIdentity\";\n\nexport type UseChatRuntimeOptions<UI_MESSAGE extends UIMessage = UIMessage> =\n ChatThreadOptions<UI_MESSAGE> & {\n cloud?: AssistantCloud | undefined;\n onThreadIdChange?: ((threadId: string | undefined) => void) | undefined;\n };\n\nconst useChatThreadRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(\n options: ChatThreadOptions<UI_MESSAGE> | undefined,\n hostDestroySignal: AbortSignal,\n): AssistantRuntime => {\n const id = useAuiState((s) => s.threadListItem.id);\n const isMainThread = useAuiState(\n (s) => s.threads.mainThreadId === s.threadListItem.id,\n );\n const aui = useAui();\n return useChatThread(options, {\n id,\n isMainThread,\n getThreadListItem: () =>\n aui.threadListItem.source ? aui.threadListItem : undefined,\n stopOnClientDestroy: true,\n hostDestroySignal,\n });\n};\n\nexport const useChatRuntime = <UI_MESSAGE extends UIMessage = UIMessage>({\n cloud,\n onThreadIdChange,\n ...options\n}: UseChatRuntimeOptions<UI_MESSAGE> = {}): AssistantRuntime => {\n const hostDestroySignal = useHostDestroySignal();\n const cloudAdapter = useCloudThreadListAdapter({ cloud, sdk: AI_SDK_SDK });\n return useRemoteThreadListRuntime({\n runtimeHook: function RuntimeHook() {\n return useChatThreadRuntime(options, hostDestroySignal);\n },\n adapter: cloudAdapter,\n allowNesting: true,\n onThreadIdChange,\n });\n};\n"],"mappings":";;;;;;;;AAoBA,MAAMkB,wBAAuBC,SAAAC,sBAAA;CAAA,MAAAC,IAAApB,EAAA,CAAA;CAI3B,MAAAqB,KAAWd,YAAYe,KAA0B;CACjD,MAAAC,eAAqBhB,YACnBiB,MACF;CACA,MAAAC,MAAYnB,OAAO;CAAE,IAAAoB;CAAA,IAAAN,EAAA,OAAAK,KAAA;EAIAC,WACjBD,IAAGE,eAAeC,SAAUH,IAAGE,iBAA/BE,KAAAA;EAA0DT,EAAA,KAAAK;EAAAL,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAAA,IAAAU;CAAA,IAAAV,EAAA,OAAAD,qBAAAC,EAAA,OAAAC,MAAAD,EAAA,OAAAG,gBAAAH,EAAA,OAAAM,IAAA;EAJhCI,KAAA;GAAAT;GAAAE;GAAAQ,mBAGTL;GACyCM,qBACvC;GAAIb;EAE3B;EAACC,EAAA,KAAAD;EAAAC,EAAA,KAAAC;EAAAD,EAAA,KAAAG;EAAAH,EAAA,KAAAM;EAAAN,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CAAA,OAPMX,cAAcS,SAASY,EAO7B;AAAC;AAGJ,MAAaG,kBAA4D,EACvEnB,OACAC,kBACA,GAAGG,YACkC,CAAC,MAAwB;CAC9D,MAAMC,oBAAoBX,qBAAqB;CAC/C,MAAM0B,eAAe9B,0BAA0B;EAAEU;EAAOqB,KAAKxB;CAAW,CAAC;CACzE,OAAON,2BAA2B;EAChC+B,aAAa,SAASC,cAAc;GAClC,OAAOpB,qBAAqBC,SAASC,iBAAiB;EACxD;EACAmB,SAASJ;EACTK,cAAc;EACdxB;CACF,CAAC;AACH;AAlC6B,SAAAO,MAAAkB,GAAA;CAAA,OAIGA,EAACb,eAAeN;AAAG;AAJtB,SAAAG,OAAAiB,KAAA;CAAA,OAMlBD,IAACE,QAAQC,iBAAkBH,IAACb,eAAeN;AAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useResourceCleanup.js","names":["useEffect","useRef","useAssistantClientDestroySignal","useResourceCleanup","enabled","cleanup","hostDestroySignal","$","_c","destroySignal","cleanupRef","enabledRef","registrationRef","t0","current","t1","t2","controller","abort","registration","AbortController","run","signal","aborted","options","once","addEventListener"],"sources":["../../src/runtime/useResourceCleanup.ts"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { useAssistantClientDestroySignal } from \"@assistant-ui/store/internal\";\n\nexport const useResourceCleanup = (\n enabled: boolean,\n cleanup: () => void,\n hostDestroySignal?: AbortSignal,\n) => {\n const destroySignal = useAssistantClientDestroySignal();\n const cleanupRef = useRef(cleanup);\n const enabledRef = useRef(enabled);\n const registrationRef = useRef<{\n destroySignal: AbortSignal | undefined;\n hostDestroySignal: AbortSignal | undefined;\n controller: AbortController;\n } | null>(null);\n\n useEffect(() => {\n cleanupRef.current = cleanup;\n enabledRef.current = enabled;\n });\n\n useEffect(() => {\n if (!enabled || (!destroySignal && !hostDestroySignal)) return undefined;\n const current = registrationRef.current;\n if (\n current !== null &&\n current.destroySignal === destroySignal &&\n current.hostDestroySignal === hostDestroySignal\n ) {\n return undefined;\n }\n current?.controller.abort();\n\n const registration = new AbortController();\n registrationRef.current = {\n destroySignal,\n hostDestroySignal,\n controller: registration,\n };\n const run = () => {\n if (registration.signal.aborted) return;\n registration.abort();\n if (enabledRef.current) cleanupRef.current();\n };\n if (destroySignal?.aborted || hostDestroySignal?.aborted) {\n run();\n return undefined;\n }\n const options = { once: true, signal: registration.signal };\n destroySignal?.addEventListener(\"abort\", run, options);\n hostDestroySignal?.addEventListener(\"abort\", run, options);\n\n // The listeners must survive standalone soft unmounts so a later\n // permanent destroy still cleans up the retained resource state.\n return undefined;\n }, [destroySignal, enabled, hostDestroySignal]);\n};\n"],"mappings":";;;;AAGA,MAAaG,sBAAqBC,SAAAC,SAAAC,sBAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAKhC,MAAAC,gBAAsBP,gCAAgC;CACtD,MAAAQ,aAAmBT,OAAOI,OAAO;CACjC,MAAAM,aAAmBV,OAAOG,OAAO;CACjC,MAAAQ,kBAAwBX,OAId,IAAI;CAAE,IAAAY;CAAA,IAAAN,EAAA,OAAAF,WAAAE,EAAA,OAAAH,SAAA;EAENS,WAAA;GACRH,WAAUI,UAAWT;GACrBM,WAAUG,UAAWV;EAAH;EACnBG,EAAA,KAAAF;EAAAE,EAAA,KAAAH;EAAAG,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAHDP,UAAUa,EAGT;CAAC,IAAAE;CAAA,IAAAC;CAAA,IAAAT,EAAA,OAAAE,iBAAAF,EAAA,OAAAH,WAAAG,EAAA,OAAAD,mBAAA;EAEQS,WAAA;GACR,IAAI,CAACX,WAAY,CAACK,iBAAD,CAAmBH,mBAAkB;GACtD,MAAAQ,UAAgBF,gBAAeE;GAC/B,IACEA,YAAY,QACZA,QAAOL,kBAAmBA,iBAC1BK,QAAOR,sBAAuBA,mBAAiB;GAIjDQ,SAAOG,WAAkBC,MAAC;GAE1B,MAAAC,eAAqB,IAAIC,gBAAgB;GACzCR,gBAAeE,UAAW;IAAAL;IAAAH;IAAAW,YAGZE;GACd;GACA,MAAAE,YAAY;IACV,IAAIF,aAAYG,OAAOC,SAAQ;IAC/BJ,aAAYD,MAAO;IACnB,IAAIP,WAAUG,SAAUJ,WAAUI,QAAS;GAAE;GAE/C,IAAIL,eAAac,WAAajB,mBAAiBiB,SAAS;IACtDF,IAAI;IAAC;GAAA;GAGP,MAAAG,UAAgB;IAAAC,MAAQ;IAAIH,QAAUH,aAAYG;GAAQ;GAC1Db,eAAaiB,iBAAmB,SAASL,KAAKG,OAAO;GACrDlB,mBAAiBoB,iBAAmB,SAASL,KAAKG,OAAO;EAAC;EAKzDR,KAAA;GAACP;GAAeL;GAASE;EAAiB;EAACC,EAAA,KAAAE;EAAAF,EAAA,KAAAH;EAAAG,EAAA,KAAAD;EAAAC,EAAA,KAAAQ;EAAAR,EAAA,KAAAS;CAAA,OAAA;EAAAD,KAAAR,EAAA;EAAAS,KAAAT,EAAA;CAAA;CAlC9CP,UAAUe,IAkCPC,EAA2C;AAAC"}
|
|
1
|
+
{"version":3,"file":"useResourceCleanup.js","names":["useEffect","useRef","useAssistantClientDestroySignal","useResourceCleanup","enabled","cleanup","hostDestroySignal","$","_c","destroySignal","cleanupRef","enabledRef","registrationRef","t0","current","t1","t2","controller","abort","registration","AbortController","run","signal","aborted","options","once","addEventListener","_c"],"sources":["../../src/runtime/useResourceCleanup.ts"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport { useAssistantClientDestroySignal } from \"@assistant-ui/store/internal\";\n\nexport const useResourceCleanup = (\n enabled: boolean,\n cleanup: () => void,\n hostDestroySignal?: AbortSignal,\n) => {\n const destroySignal = useAssistantClientDestroySignal();\n const cleanupRef = useRef(cleanup);\n const enabledRef = useRef(enabled);\n const registrationRef = useRef<{\n destroySignal: AbortSignal | undefined;\n hostDestroySignal: AbortSignal | undefined;\n controller: AbortController;\n } | null>(null);\n\n useEffect(() => {\n cleanupRef.current = cleanup;\n enabledRef.current = enabled;\n });\n\n useEffect(() => {\n if (!enabled || (!destroySignal && !hostDestroySignal)) return undefined;\n const current = registrationRef.current;\n if (\n current !== null &&\n current.destroySignal === destroySignal &&\n current.hostDestroySignal === hostDestroySignal\n ) {\n return undefined;\n }\n current?.controller.abort();\n\n const registration = new AbortController();\n registrationRef.current = {\n destroySignal,\n hostDestroySignal,\n controller: registration,\n };\n const run = () => {\n if (registration.signal.aborted) return;\n registration.abort();\n if (enabledRef.current) cleanupRef.current();\n };\n if (destroySignal?.aborted || hostDestroySignal?.aborted) {\n run();\n return undefined;\n }\n const options = { once: true, signal: registration.signal };\n destroySignal?.addEventListener(\"abort\", run, options);\n hostDestroySignal?.addEventListener(\"abort\", run, options);\n\n // The listeners must survive standalone soft unmounts so a later\n // permanent destroy still cleans up the retained resource state.\n return undefined;\n }, [destroySignal, enabled, hostDestroySignal]);\n};\n"],"mappings":";;;;AAGA,MAAaG,sBAAqBC,SAAAC,SAAAC,sBAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAKhC,MAAAC,gBAAsBP,gCAAgC;CACtD,MAAAQ,aAAmBT,OAAOI,OAAO;CACjC,MAAAM,aAAmBV,OAAOG,OAAO;CACjC,MAAAQ,kBAAwBX,OAId,IAAI;CAAE,IAAAY;CAAA,IAAAN,EAAA,OAAAF,WAAAE,EAAA,OAAAH,SAAA;EAENS,WAAA;GACRH,WAAUI,UAAWT;GACrBM,WAAUG,UAAWV;EAAH;EACnBG,EAAA,KAAAF;EAAAE,EAAA,KAAAH;EAAAG,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAHDP,UAAUa,EAGT;CAAC,IAAAE;CAAA,IAAAC;CAAA,IAAAT,EAAA,OAAAE,iBAAAF,EAAA,OAAAH,WAAAG,EAAA,OAAAD,mBAAA;EAEQS,WAAA;GACR,IAAI,CAACX,WAAY,CAACK,iBAAD,CAAmBH,mBAAkB;GACtD,MAAAQ,UAAgBF,gBAAeE;GAC/B,IACEA,YAAY,QACZA,QAAOL,kBAAmBA,iBAC1BK,QAAOR,sBAAuBA,mBAAiB;GAIjDQ,SAAOG,WAAkBC,MAAC;GAE1B,MAAAC,eAAqB,IAAIC,gBAAgB;GACzCR,gBAAeE,UAAW;IAAAL;IAAAH;IAAAW,YAGZE;GACd;GACA,MAAAE,YAAY;IACV,IAAIF,aAAYG,OAAOC,SAAQ;IAC/BJ,aAAYD,MAAO;IACnB,IAAIP,WAAUG,SAAUJ,WAAUI,QAAS;GAAE;GAE/C,IAAIL,eAAac,WAAajB,mBAAiBiB,SAAS;IACtDF,IAAI;IAAC;GAAA;GAGP,MAAAG,UAAgB;IAAAC,MAAQ;IAAIH,QAAUH,aAAYG;GAAQ;GAC1Db,eAAaiB,iBAAmB,SAASL,KAAKG,OAAO;GACrDlB,mBAAiBoB,iBAAmB,SAASL,KAAKG,OAAO;EAAC;EAKzDR,KAAA;GAACP;GAAeL;GAASE;EAAiB;EAACC,EAAA,KAAAE;EAAAF,EAAA,KAAAH;EAAAG,EAAA,KAAAD;EAAAC,EAAA,KAAAQ;EAAAR,EAAA,KAAAS;CAAA,OAAA;EAAAD,KAAAR,EAAA;EAAAS,KAAAT,EAAA;CAAA;CAlC9CP,UAAUe,IAkCPC,EAA2C;AAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStreamingTiming.js","names":["UIMessage","isToolUIPart","MessageTiming","useStreamingTiming","useStreamingTimingPrimitive","StreamingTimingAccessors","findAssistant","messages","messageId","find","m","role","id","getTextLength","message","parts","len","part","type","text","length","getToolCallCount","count","getAssistantMessageId","findLast","aiSdkStreamingTimingAccessors","isRunning"],"sources":["../../src/runtime/useStreamingTiming.ts"],"sourcesContent":["\"use client\";\n\nimport type { UIMessage } from \"@ai-sdk/react\";\nimport { isToolUIPart } from \"ai\";\nimport type { MessageTiming } from \"@assistant-ui/core\";\nimport {\n useStreamingTiming as useStreamingTimingPrimitive,\n type StreamingTimingAccessors,\n} from \"@assistant-ui/core/react\";\n\nconst findAssistant = (\n messages: readonly UIMessage[],\n messageId: string,\n): UIMessage | undefined =>\n messages.find((m) => m.role === \"assistant\" && m.id === messageId);\n\nconst getTextLength = (\n messages: readonly UIMessage[],\n messageId: string,\n): number => {\n const message = findAssistant(messages, messageId);\n if (!message?.parts) return 0;\n let len = 0;\n for (const part of message.parts) {\n if (part.type === \"text\") len += part.text.length;\n }\n return len;\n};\n\nconst getToolCallCount = (\n messages: readonly UIMessage[],\n messageId: string,\n): number => {\n const message = findAssistant(messages, messageId);\n if (!message?.parts) return 0;\n let count = 0;\n for (const part of message.parts) {\n if (isToolUIPart(part)) count++;\n }\n return count;\n};\n\nconst getAssistantMessageId = (\n messages: readonly UIMessage[],\n): string | undefined => messages.findLast((m) => m.role === \"assistant\")?.id;\n\nexport const aiSdkStreamingTimingAccessors: StreamingTimingAccessors<UIMessage> =\n {\n getAssistantMessageId,\n getTextLength,\n getToolCallCount,\n };\n\n/**\n * Tracks streaming timing for AI SDK messages client-side. Delegates to the\n * shared `useStreamingTiming` primitive in `@assistant-ui/core/react`,\n * adapted to the `UIMessage` shape. Timing is finalized when streaming ends\n * and stored per message id.\n */\nexport const useStreamingTiming = (\n messages: UIMessage[],\n isRunning: boolean,\n): Record<string, MessageTiming> =>\n useStreamingTimingPrimitive(\n messages,\n isRunning,\n aiSdkStreamingTimingAccessors,\n );\n"],"mappings":";;;;AAUA,MAAMM,iBACJC,UACAC,cAEAD,SAASE,MAAMC,MAAMA,EAAEC,SAAS,eAAeD,EAAEE,OAAOJ,SAAS;AAEnE,MAAMK,iBACJN,UACAC,cACW;CACX,MAAMM,UAAUR,cAAcC,UAAUC,SAAS;CACjD,IAAI,CAACM,SAASC,OAAO,OAAO;CAC5B,IAAIC,MAAM;CACV,KAAK,MAAMC,QAAQH,QAAQC,OACzB,IAAIE,KAAKC,SAAS,QAAQF,OAAOC,KAAKE,KAAKC;CAE7C,OAAOJ;AACT;AAEA,MAAMK,oBACJd,UACAC,cACW;CACX,MAAMM,UAAUR,cAAcC,UAAUC,SAAS;CACjD,IAAI,CAACM,SAASC,OAAO,OAAO;CAC5B,IAAIO,QAAQ;CACZ,KAAK,MAAML,QAAQH,QAAQC,OACzB,IAAId,aAAagB,IAAI,GAAGK;CAE1B,OAAOA;AACT;AAEA,MAAMC,yBACJhB,aACuBA,SAASiB,UAAUd,MAAMA,EAAEC,SAAS,WAAW,CAAC,EAAEC;AAE3E,MAAaa,gCACX;CACEF;CACAV;CACAQ;AACF;;;;;;;AAQF,MAAalB,sBAAqBI,UAAAmB,cAAA;CAAA,OAIhCtB,qBACEG,UACAmB,WACAD,6BACF;AAAC"}
|
|
1
|
+
{"version":3,"file":"useStreamingTiming.js","names":["UIMessage","isToolUIPart","MessageTiming","useStreamingTiming","useStreamingTimingPrimitive","StreamingTimingAccessors","findAssistant","messages","messageId","find","m","role","id","getTextLength","message","parts","len","part","type","text","length","getToolCallCount","count","getAssistantMessageId","findLast","aiSdkStreamingTimingAccessors","isRunning","useStreamingTimingPrimitive"],"sources":["../../src/runtime/useStreamingTiming.ts"],"sourcesContent":["\"use client\";\n\nimport type { UIMessage } from \"@ai-sdk/react\";\nimport { isToolUIPart } from \"ai\";\nimport type { MessageTiming } from \"@assistant-ui/core\";\nimport {\n useStreamingTiming as useStreamingTimingPrimitive,\n type StreamingTimingAccessors,\n} from \"@assistant-ui/core/react\";\n\nconst findAssistant = (\n messages: readonly UIMessage[],\n messageId: string,\n): UIMessage | undefined =>\n messages.find((m) => m.role === \"assistant\" && m.id === messageId);\n\nconst getTextLength = (\n messages: readonly UIMessage[],\n messageId: string,\n): number => {\n const message = findAssistant(messages, messageId);\n if (!message?.parts) return 0;\n let len = 0;\n for (const part of message.parts) {\n if (part.type === \"text\") len += part.text.length;\n }\n return len;\n};\n\nconst getToolCallCount = (\n messages: readonly UIMessage[],\n messageId: string,\n): number => {\n const message = findAssistant(messages, messageId);\n if (!message?.parts) return 0;\n let count = 0;\n for (const part of message.parts) {\n if (isToolUIPart(part)) count++;\n }\n return count;\n};\n\nconst getAssistantMessageId = (\n messages: readonly UIMessage[],\n): string | undefined => messages.findLast((m) => m.role === \"assistant\")?.id;\n\nexport const aiSdkStreamingTimingAccessors: StreamingTimingAccessors<UIMessage> =\n {\n getAssistantMessageId,\n getTextLength,\n getToolCallCount,\n };\n\n/**\n * Tracks streaming timing for AI SDK messages client-side. Delegates to the\n * shared `useStreamingTiming` primitive in `@assistant-ui/core/react`,\n * adapted to the `UIMessage` shape. Timing is finalized when streaming ends\n * and stored per message id.\n */\nexport const useStreamingTiming = (\n messages: UIMessage[],\n isRunning: boolean,\n): Record<string, MessageTiming> =>\n useStreamingTimingPrimitive(\n messages,\n isRunning,\n aiSdkStreamingTimingAccessors,\n );\n"],"mappings":";;;;AAUA,MAAMM,iBACJC,UACAC,cAEAD,SAASE,MAAMC,MAAMA,EAAEC,SAAS,eAAeD,EAAEE,OAAOJ,SAAS;AAEnE,MAAMK,iBACJN,UACAC,cACW;CACX,MAAMM,UAAUR,cAAcC,UAAUC,SAAS;CACjD,IAAI,CAACM,SAASC,OAAO,OAAO;CAC5B,IAAIC,MAAM;CACV,KAAK,MAAMC,QAAQH,QAAQC,OACzB,IAAIE,KAAKC,SAAS,QAAQF,OAAOC,KAAKE,KAAKC;CAE7C,OAAOJ;AACT;AAEA,MAAMK,oBACJd,UACAC,cACW;CACX,MAAMM,UAAUR,cAAcC,UAAUC,SAAS;CACjD,IAAI,CAACM,SAASC,OAAO,OAAO;CAC5B,IAAIO,QAAQ;CACZ,KAAK,MAAML,QAAQH,QAAQC,OACzB,IAAId,aAAagB,IAAI,GAAGK;CAE1B,OAAOA;AACT;AAEA,MAAMC,yBACJhB,aACuBA,SAASiB,UAAUd,MAAMA,EAAEC,SAAS,WAAW,CAAC,EAAEC;AAE3E,MAAaa,gCACX;CACEF;CACAV;CACAQ;AACF;;;;;;;AAQF,MAAalB,sBAAqBI,UAAAmB,cAAA;CAAA,OAIhCtB,qBACEG,UACAmB,WACAD,6BACF;AAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resumable.js","names":["RESUMABLE_STREAM_ID_HEADER","RESUMABLE_STREAM_ID_HEADER_VALUE","DEFAULT_STORAGE_KEY","ResumableClientStorage","getStreamId","threadId","setStreamId","id","clear","subscribe","listener","getSessionStorage","Storage","window","sessionStorage","StorageSlot","value","owner","createResumableSessionStorage","options","key","keyOption","resolveKey","undefined","slots","Map","listeners","Set","readSlot","slot","get","storage","getItem","set","notify","subscription","error","console","setItem","Array","from","find","removeItem","add","delete","AssistantChatResumableOptions","resumeApi","streamId","isFinishEvent","chunk","Uint8Array","accumulator"],"sources":["../../src/transport/resumable.ts"],"sourcesContent":["\"use client\";\n\nimport { RESUMABLE_STREAM_ID_HEADER as RESUMABLE_STREAM_ID_HEADER_VALUE } from \"assistant-stream/resumable\";\n\n/** Response header used by the [Resumable Streams](/docs/guides/resumable-streams) server and client wiring. */\nexport const RESUMABLE_STREAM_ID_HEADER = RESUMABLE_STREAM_ID_HEADER_VALUE;\n\nconst DEFAULT_STORAGE_KEY = \"aui-resumable-stream-id\";\n\nexport type ResumableClientStorage = {\n getStreamId(threadId?: string): string | null;\n setStreamId(id: string, threadId?: string): void;\n clear(threadId?: string): void;\n /** Subscribes to stream id changes so automatic resume can react after mount. */\n subscribe?(listener: () => void, threadId?: string): () => void;\n};\n\nconst getSessionStorage = (): Storage | null => {\n if (typeof window === \"undefined\") return null;\n try {\n return window.sessionStorage;\n } catch {\n return null;\n }\n};\n\ntype StorageSlot = {\n value: string | null;\n owner: string | undefined;\n};\n\n/** `sessionStorage`-backed storage for the pending resumable stream id. See the [Resumable Streams](/docs/guides/resumable-streams) guide for end-to-end wiring. */\nexport function createResumableSessionStorage(options?: {\n /**\n * Storage key for the pending stream id. A static string namespaces per route\n * or chat surface. A getter is read lazily on every access, so the key can be\n * derived from the active thread's identity; while the getter returns\n * `undefined`, reads report no pending stream and writes are dropped, so a\n * thread whose identity is not known yet never touches another thread's key.\n *\n * Under a remote thread list with more than one thread, scope the key per\n * thread and create one storage instance per thread runtime rather than a\n * single shared one. A shared key is written and cleared by whichever thread\n * acts last, so one conversation's stream can resume inside another.\n */\n key?: string | (() => string | undefined);\n}): ResumableClientStorage {\n const keyOption = options?.key;\n const resolveKey = (): string | undefined => {\n if (typeof keyOption !== \"function\")\n return keyOption ?? DEFAULT_STORAGE_KEY;\n try {\n return keyOption();\n } catch {\n return undefined;\n }\n };\n const slots = new Map<string, StorageSlot>();\n const listeners = new Set<{\n listener: () => void;\n threadId: string | undefined;\n }>();\n const readSlot = (key: string): StorageSlot => {\n let slot = slots.get(key);\n if (slot) return slot;\n const storage = getSessionStorage();\n let value: string | null = null;\n if (storage) {\n try {\n value = storage.getItem(key);\n } catch {\n value = null;\n }\n }\n slot = { value, owner: undefined };\n slots.set(key, slot);\n return slot;\n };\n const notify = (threadId?: string) => {\n for (const subscription of listeners) {\n if (threadId && subscription.threadId !== threadId) continue;\n try {\n subscription.listener();\n } catch (error) {\n console.error(\n \"[assistant-ui] resumable storage listener failed\",\n error,\n );\n }\n }\n };\n\n return {\n getStreamId(threadId) {\n const key = resolveKey();\n if (!key) return null;\n const slot = readSlot(key);\n if (slot.value === null) return null;\n if (slot.owner && threadId && slot.owner !== threadId) return null;\n return slot.value;\n },\n setStreamId(id, threadId) {\n const key = resolveKey();\n const storage = getSessionStorage();\n if (!key || !storage) return;\n try {\n storage.setItem(key, id);\n } catch {\n // Ignore blocked or unavailable sessionStorage.\n return;\n }\n const slot = readSlot(key);\n slot.value = id;\n if (threadId) {\n slot.owner = threadId;\n } else if (!slot.owner) {\n slot.owner = Array.from(listeners).find(\n (subscription) => subscription.threadId !== undefined,\n )?.threadId;\n }\n notify(slot.owner);\n },\n clear(threadId) {\n const key = resolveKey();\n if (!key) return;\n const slot = readSlot(key);\n if (slot.owner && threadId && slot.owner !== threadId) return;\n const storage = getSessionStorage();\n if (!storage) return;\n try {\n storage.removeItem(key);\n } catch {\n // Ignore blocked or unavailable sessionStorage.\n return;\n }\n slot.value = null;\n slot.owner = undefined;\n notify(threadId);\n },\n subscribe(listener, threadId) {\n const key = resolveKey();\n if (key && threadId) {\n const slot = readSlot(key);\n if (slot.value !== null) slot.owner ??= threadId;\n }\n const subscription = { listener, threadId };\n listeners.add(subscription);\n return () => listeners.delete(subscription);\n },\n };\n}\n\nexport type AssistantChatResumableOptions = {\n storage: ResumableClientStorage;\n resumeApi: string | ((streamId: string) => string);\n /**\n * Defaults to scanning for the AI SDK UIMessageStream `finish` marker.\n * Cancellation never invokes this callback, only natural completion does.\n */\n isFinishEvent?: (chunk: Uint8Array, accumulator: string) => boolean;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"resumable.js","names":["RESUMABLE_STREAM_ID_HEADER","RESUMABLE_STREAM_ID_HEADER_VALUE","DEFAULT_STORAGE_KEY","ResumableClientStorage","getStreamId","threadId","setStreamId","id","clear","subscribe","listener","getSessionStorage","Storage","window","sessionStorage","StorageSlot","value","owner","createResumableSessionStorage","options","key","keyOption","resolveKey","undefined","slots","Map","listeners","Set","readSlot","slot","get","storage","getItem","set","notify","subscription","error","console","setItem","Array","from","find","removeItem","add","delete","AssistantChatResumableOptions","resumeApi","streamId","isFinishEvent","chunk","Uint8Array","accumulator","RESUMABLE_STREAM_ID_HEADER_VALUE"],"sources":["../../src/transport/resumable.ts"],"sourcesContent":["\"use client\";\n\nimport { RESUMABLE_STREAM_ID_HEADER as RESUMABLE_STREAM_ID_HEADER_VALUE } from \"assistant-stream/resumable\";\n\n/** Response header used by the [Resumable Streams](/docs/guides/resumable-streams) server and client wiring. */\nexport const RESUMABLE_STREAM_ID_HEADER = RESUMABLE_STREAM_ID_HEADER_VALUE;\n\nconst DEFAULT_STORAGE_KEY = \"aui-resumable-stream-id\";\n\nexport type ResumableClientStorage = {\n getStreamId(threadId?: string): string | null;\n setStreamId(id: string, threadId?: string): void;\n clear(threadId?: string): void;\n /** Subscribes to stream id changes so automatic resume can react after mount. */\n subscribe?(listener: () => void, threadId?: string): () => void;\n};\n\nconst getSessionStorage = (): Storage | null => {\n if (typeof window === \"undefined\") return null;\n try {\n return window.sessionStorage;\n } catch {\n return null;\n }\n};\n\ntype StorageSlot = {\n value: string | null;\n owner: string | undefined;\n};\n\n/** `sessionStorage`-backed storage for the pending resumable stream id. See the [Resumable Streams](/docs/guides/resumable-streams) guide for end-to-end wiring. */\nexport function createResumableSessionStorage(options?: {\n /**\n * Storage key for the pending stream id. A static string namespaces per route\n * or chat surface. A getter is read lazily on every access, so the key can be\n * derived from the active thread's identity; while the getter returns\n * `undefined`, reads report no pending stream and writes are dropped, so a\n * thread whose identity is not known yet never touches another thread's key.\n *\n * Under a remote thread list with more than one thread, scope the key per\n * thread and create one storage instance per thread runtime rather than a\n * single shared one. A shared key is written and cleared by whichever thread\n * acts last, so one conversation's stream can resume inside another.\n */\n key?: string | (() => string | undefined);\n}): ResumableClientStorage {\n const keyOption = options?.key;\n const resolveKey = (): string | undefined => {\n if (typeof keyOption !== \"function\")\n return keyOption ?? DEFAULT_STORAGE_KEY;\n try {\n return keyOption();\n } catch {\n return undefined;\n }\n };\n const slots = new Map<string, StorageSlot>();\n const listeners = new Set<{\n listener: () => void;\n threadId: string | undefined;\n }>();\n const readSlot = (key: string): StorageSlot => {\n let slot = slots.get(key);\n if (slot) return slot;\n const storage = getSessionStorage();\n let value: string | null = null;\n if (storage) {\n try {\n value = storage.getItem(key);\n } catch {\n value = null;\n }\n }\n slot = { value, owner: undefined };\n slots.set(key, slot);\n return slot;\n };\n const notify = (threadId?: string) => {\n for (const subscription of listeners) {\n if (threadId && subscription.threadId !== threadId) continue;\n try {\n subscription.listener();\n } catch (error) {\n console.error(\n \"[assistant-ui] resumable storage listener failed\",\n error,\n );\n }\n }\n };\n\n return {\n getStreamId(threadId) {\n const key = resolveKey();\n if (!key) return null;\n const slot = readSlot(key);\n if (slot.value === null) return null;\n if (slot.owner && threadId && slot.owner !== threadId) return null;\n return slot.value;\n },\n setStreamId(id, threadId) {\n const key = resolveKey();\n const storage = getSessionStorage();\n if (!key || !storage) return;\n try {\n storage.setItem(key, id);\n } catch {\n // Ignore blocked or unavailable sessionStorage.\n return;\n }\n const slot = readSlot(key);\n slot.value = id;\n if (threadId) {\n slot.owner = threadId;\n } else if (!slot.owner) {\n slot.owner = Array.from(listeners).find(\n (subscription) => subscription.threadId !== undefined,\n )?.threadId;\n }\n notify(slot.owner);\n },\n clear(threadId) {\n const key = resolveKey();\n if (!key) return;\n const slot = readSlot(key);\n if (slot.owner && threadId && slot.owner !== threadId) return;\n const storage = getSessionStorage();\n if (!storage) return;\n try {\n storage.removeItem(key);\n } catch {\n // Ignore blocked or unavailable sessionStorage.\n return;\n }\n slot.value = null;\n slot.owner = undefined;\n notify(threadId);\n },\n subscribe(listener, threadId) {\n const key = resolveKey();\n if (key && threadId) {\n const slot = readSlot(key);\n if (slot.value !== null) slot.owner ??= threadId;\n }\n const subscription = { listener, threadId };\n listeners.add(subscription);\n return () => listeners.delete(subscription);\n },\n };\n}\n\nexport type AssistantChatResumableOptions = {\n storage: ResumableClientStorage;\n resumeApi: string | ((streamId: string) => string);\n /**\n * Defaults to scanning for the AI SDK UIMessageStream `finish` marker.\n * Cancellation never invokes this callback, only natural completion does.\n */\n isFinishEvent?: (chunk: Uint8Array, accumulator: string) => boolean;\n};\n"],"mappings":"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"}
|
package/dist/usage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage.js","names":["useMemo","useAuiState","ThreadTokenUsage","totalTokens","inputTokens","outputTokens","reasoningTokens","cachedInputTokens","TokenUsageExtractableMessage","role","metadata","UsageRecord","Record","USAGE_KEYS","const","asRecord","value","Array","isArray","undefined","asPositiveTokenCount","Number","isFinite","computeTotalTokens","usage","normalizeUsage","record","result","hasFields","key","count","outputTokenDetails","inputTokenDetails","cacheReadTokens","withComputedTotal","usageFromSteps","steps","sums","present","stepsWithUsage","stepsWithComputableTotal","step","stepTotal","getThreadMessageTokenUsage","message","topLevelUsage","customUsage","custom","findLatestMessageWithUsage","messages","idx","length","useThreadTokenUsage","$","_c","msg","_temp","t0","s","thread"],"sources":["../src/usage.ts"],"sourcesContent":["/// <reference types=\"@assistant-ui/core/react\" preserve=\"true\" />\nimport { useMemo } from \"react\";\nimport { useAuiState } from \"@assistant-ui/store\";\n\nexport type ThreadTokenUsage = {\n totalTokens?: number;\n inputTokens?: number;\n outputTokens?: number;\n reasoningTokens?: number;\n cachedInputTokens?: number;\n};\n\nexport interface TokenUsageExtractableMessage {\n role?: string;\n metadata?: unknown;\n}\n\ntype UsageRecord = Record<string, unknown>;\n\nconst USAGE_KEYS = [\n \"inputTokens\",\n \"outputTokens\",\n \"reasoningTokens\",\n \"cachedInputTokens\",\n \"totalTokens\",\n] as const satisfies (keyof ThreadTokenUsage)[];\n\nfunction asRecord(value: unknown): UsageRecord | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value))\n return undefined;\n return value as UsageRecord;\n}\n\nfunction asPositiveTokenCount(value: unknown): number | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n return undefined;\n }\n return value;\n}\n\nfunction computeTotalTokens(usage: ThreadTokenUsage): number | undefined {\n if (usage.totalTokens !== undefined) return usage.totalTokens;\n if (usage.inputTokens !== undefined && usage.outputTokens !== undefined) {\n return usage.inputTokens + usage.outputTokens;\n }\n return undefined;\n}\n\nfunction normalizeUsage(value: unknown): ThreadTokenUsage | undefined {\n const record = asRecord(value);\n if (!record) return undefined;\n\n const result: ThreadTokenUsage = {};\n let hasFields = false;\n for (const key of USAGE_KEYS) {\n const count = asPositiveTokenCount(record[key]);\n if (count !== undefined) {\n result[key] = count;\n hasFields = true;\n }\n }\n // AI SDK v7 moved these under token detail objects; v6 kept them top-level.\n if (result.reasoningTokens === undefined) {\n const count = asPositiveTokenCount(\n asRecord(record.outputTokenDetails)?.reasoningTokens,\n );\n if (count !== undefined) {\n result.reasoningTokens = count;\n hasFields = true;\n }\n }\n if (result.cachedInputTokens === undefined) {\n const count = asPositiveTokenCount(\n asRecord(record.inputTokenDetails)?.cacheReadTokens,\n );\n if (count !== undefined) {\n result.cachedInputTokens = count;\n hasFields = true;\n }\n }\n return hasFields ? result : undefined;\n}\n\nfunction withComputedTotal(\n usage: ThreadTokenUsage,\n): ThreadTokenUsage | undefined {\n const totalTokens = computeTotalTokens(usage);\n return { ...usage, ...(totalTokens !== undefined && { totalTokens }) };\n}\n\nfunction usageFromSteps(value: unknown): ThreadTokenUsage | undefined {\n const steps = Array.isArray(value) ? value : [];\n\n const sums: Record<string, number> = {};\n const present: Record<string, boolean> = {};\n let stepsWithUsage = 0;\n let stepsWithComputableTotal = 0;\n\n for (const step of steps) {\n const usage = normalizeUsage(asRecord(step)?.usage);\n if (!usage) continue;\n stepsWithUsage++;\n\n const stepTotal = computeTotalTokens(usage);\n if (stepTotal !== undefined) {\n sums.totalTokens = (sums.totalTokens ?? 0) + stepTotal;\n stepsWithComputableTotal++;\n }\n\n for (const key of USAGE_KEYS) {\n if (key === \"totalTokens\") continue;\n if (usage[key] !== undefined) {\n sums[key] = (sums[key] ?? 0) + usage[key];\n present[key] = true;\n }\n }\n }\n\n if (stepsWithUsage === 0) return undefined;\n\n const result: ThreadTokenUsage = {};\n if (stepsWithComputableTotal === stepsWithUsage) {\n result.totalTokens = sums.totalTokens!;\n }\n for (const key of USAGE_KEYS) {\n if (key === \"totalTokens\") continue;\n if (present[key]) {\n result[key] = sums[key]!;\n }\n }\n return result;\n}\n\nexport function getThreadMessageTokenUsage(\n message: TokenUsageExtractableMessage | undefined,\n): ThreadTokenUsage | undefined {\n if (!message || message.role !== \"assistant\") return undefined;\n\n const metadata = asRecord(message.metadata);\n if (!metadata) return undefined;\n\n const topLevelUsage = normalizeUsage(metadata.usage);\n if (topLevelUsage) return withComputedTotal(topLevelUsage);\n\n const customUsage = normalizeUsage(asRecord(metadata.custom)?.usage);\n if (customUsage) return withComputedTotal(customUsage);\n\n return usageFromSteps(metadata.steps);\n}\n\nfunction findLatestMessageWithUsage(\n messages: readonly TokenUsageExtractableMessage[] | undefined,\n): TokenUsageExtractableMessage | undefined {\n if (!messages) return undefined;\n\n for (let idx = messages.length - 1; idx >= 0; idx -= 1) {\n const message = messages[idx];\n if (getThreadMessageTokenUsage(message)) {\n return message;\n }\n }\n\n return undefined;\n}\n\n/**\n * Reads token usage from the newest assistant message that reports any.\n *\n * A route attaches usage through the AI SDK's `messageMetadata` option. Because\n * a thread message carries a fixed metadata shape, the converter moves every\n * other key the route returns into `metadata.custom`, which is where this hook\n * looks.\n */\nexport function useThreadTokenUsage(): ThreadTokenUsage | undefined {\n const msg = useAuiState((s) => findLatestMessageWithUsage(s.thread.messages));\n return useMemo(() => getThreadMessageTokenUsage(msg), [msg]);\n}\n"],"mappings":";;;;AAmBA,MAAMa,aAAa;CACjB;CACA;CACA;CACA;CACA;AAAa;AAGf,SAASE,SAASC,OAAyC;CACzD,IAAI,CAACA,SAAS,OAAOA,UAAU,YAAYC,MAAMC,QAAQF,KAAK,GAC5D,OAAOG,KAAAA;CACT,OAAOH;AACT;AAEA,SAASI,qBAAqBJ,OAAoC;CAChE,IAAI,OAAOA,UAAU,YAAY,CAACK,OAAOC,SAASN,KAAK,KAAKA,QAAQ,GAClE;CAEF,OAAOA;AACT;AAEA,SAASO,mBAAmBC,OAA6C;CACvE,IAAIA,MAAMrB,gBAAgBgB,KAAAA,GAAW,OAAOK,MAAMrB;CAClD,IAAIqB,MAAMpB,gBAAgBe,KAAAA,KAAaK,MAAMnB,iBAAiBc,KAAAA,GAC5D,OAAOK,MAAMpB,cAAcoB,MAAMnB;AAGrC;AAEA,SAASoB,eAAeT,OAA8C;CACpE,MAAMU,SAASX,SAASC,KAAK;CAC7B,IAAI,CAACU,QAAQ,OAAOP,KAAAA;CAEpB,MAAMQ,SAA2B,CAAC;CAClC,IAAIC,YAAY;CAChB,KAAK,MAAMC,OAAOhB,YAAY;EAC5B,MAAMiB,QAAQV,qBAAqBM,OAAOG,IAAI;EAC9C,IAAIC,UAAUX,KAAAA,GAAW;GACvBQ,OAAOE,OAAOC;GACdF,YAAY;EACd;CACF;CAEA,IAAID,OAAOrB,oBAAoBa,KAAAA,GAAW;EACxC,MAAMW,QAAQV,qBACZL,SAASW,OAAOK,kBAAkB,CAAC,EAAEzB,eACvC;EACA,IAAIwB,UAAUX,KAAAA,GAAW;GACvBQ,OAAOrB,kBAAkBwB;GACzBF,YAAY;EACd;CACF;CACA,IAAID,OAAOpB,sBAAsBY,KAAAA,GAAW;EAC1C,MAAMW,QAAQV,qBACZL,SAASW,OAAOM,iBAAiB,CAAC,EAAEC,eACtC;EACA,IAAIH,UAAUX,KAAAA,GAAW;GACvBQ,OAAOpB,oBAAoBuB;GAC3BF,YAAY;EACd;CACF;CACA,OAAOA,YAAYD,SAASR,KAAAA;AAC9B;AAEA,SAASe,kBACPV,OAC8B;CAC9B,MAAMrB,cAAcoB,mBAAmBC,KAAK;CAC5C,OAAO;EAAE,GAAGA;EAAO,GAAIrB,gBAAgBgB,KAAAA,KAAa,EAAEhB,YAAY;CAAG;AACvE;AAEA,SAASgC,eAAenB,OAA8C;CACpE,MAAMoB,QAAQnB,MAAMC,QAAQF,KAAK,IAAIA,QAAQ,CAAA;CAE7C,MAAMqB,OAA+B,CAAC;CACtC,MAAMC,UAAmC,CAAC;CAC1C,IAAIC,iBAAiB;CACrB,IAAIC,2BAA2B;CAE/B,KAAK,MAAMC,QAAQL,OAAO;EACxB,MAAMZ,QAAQC,eAAeV,SAAS0B,IAAI,CAAC,EAAEjB,KAAK;EAClD,IAAI,CAACA,OAAO;EACZe;EAEA,MAAMG,YAAYnB,mBAAmBC,KAAK;EAC1C,IAAIkB,cAAcvB,KAAAA,GAAW;GAC3BkB,KAAKlC,eAAekC,KAAKlC,eAAe,KAAKuC;GAC7CF;EACF;EAEA,KAAK,MAAMX,OAAOhB,YAAY;GAC5B,IAAIgB,QAAQ,eAAe;GAC3B,IAAIL,MAAMK,SAASV,KAAAA,GAAW;IAC5BkB,KAAKR,QAAQQ,KAAKR,QAAQ,KAAKL,MAAMK;IACrCS,QAAQT,OAAO;GACjB;EACF;CACF;CAEA,IAAIU,mBAAmB,GAAG,OAAOpB,KAAAA;CAEjC,MAAMQ,SAA2B,CAAC;CAClC,IAAIa,6BAA6BD,gBAC/BZ,OAAOxB,cAAckC,KAAKlC;CAE5B,KAAK,MAAM0B,OAAOhB,YAAY;EAC5B,IAAIgB,QAAQ,eAAe;EAC3B,IAAIS,QAAQT,MACVF,OAAOE,OAAOQ,KAAKR;CAEvB;CACA,OAAOF;AACT;AAEA,SAAgBgB,2BACdC,SAC8B;CAC9B,IAAI,CAACA,WAAWA,QAAQnC,SAAS,aAAa,OAAOU,KAAAA;CAErD,MAAMT,WAAWK,SAAS6B,QAAQlC,QAAQ;CAC1C,IAAI,CAACA,UAAU,OAAOS,KAAAA;CAEtB,MAAM0B,gBAAgBpB,eAAef,SAASc,KAAK;CACnD,IAAIqB,eAAe,OAAOX,kBAAkBW,aAAa;CAEzD,MAAMC,cAAcrB,eAAeV,SAASL,SAASqC,MAAM,CAAC,EAAEvB,KAAK;CACnE,IAAIsB,aAAa,OAAOZ,kBAAkBY,WAAW;CAErD,OAAOX,eAAezB,SAAS0B,KAAK;AACtC;AAEA,SAASY,2BACPC,UAC0C;CAC1C,IAAI,CAACA,UAAU,OAAO9B,KAAAA;CAEtB,KAAK,IAAI+B,MAAMD,SAASE,SAAS,GAAGD,OAAO,GAAGA,OAAO,GAAG;EACtD,MAAMN,UAAUK,SAASC;EACzB,IAAIP,2BAA2BC,OAAO,GACpC,OAAOA;CAEX;AAGF;;;;;;;;;AAUA,SAAOQ,sBAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CACL,MAAAC,MAAYtD,YAAYuD,KAAoD;CAAE,IAAAC;CAAA,IAAAJ,EAAA,OAAAE,KAAA;EACzDE,KAAAd,2BAA2BY,GAAG;EAACF,EAAA,KAAAE;EAAAF,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAAA,OAA/BI;AAA+B;AAF/C,SAAAD,MAAAE,GAAA;CAAA,OAC0BV,2BAA2BU,EAACC,OAAOV,QAAS;AAAC"}
|
|
1
|
+
{"version":3,"file":"usage.js","names":["useMemo","useAuiState","ThreadTokenUsage","totalTokens","inputTokens","outputTokens","reasoningTokens","cachedInputTokens","TokenUsageExtractableMessage","role","metadata","UsageRecord","Record","USAGE_KEYS","const","asRecord","value","Array","isArray","undefined","asPositiveTokenCount","Number","isFinite","computeTotalTokens","usage","normalizeUsage","record","result","hasFields","key","count","outputTokenDetails","inputTokenDetails","cacheReadTokens","withComputedTotal","usageFromSteps","steps","sums","present","stepsWithUsage","stepsWithComputableTotal","step","stepTotal","getThreadMessageTokenUsage","message","topLevelUsage","customUsage","custom","findLatestMessageWithUsage","messages","idx","length","useThreadTokenUsage","$","_c","msg","_temp","t0","s","thread","_c"],"sources":["../src/usage.ts"],"sourcesContent":["/// <reference types=\"@assistant-ui/core/react\" preserve=\"true\" />\nimport { useMemo } from \"react\";\nimport { useAuiState } from \"@assistant-ui/store\";\n\nexport type ThreadTokenUsage = {\n totalTokens?: number;\n inputTokens?: number;\n outputTokens?: number;\n reasoningTokens?: number;\n cachedInputTokens?: number;\n};\n\nexport interface TokenUsageExtractableMessage {\n role?: string;\n metadata?: unknown;\n}\n\ntype UsageRecord = Record<string, unknown>;\n\nconst USAGE_KEYS = [\n \"inputTokens\",\n \"outputTokens\",\n \"reasoningTokens\",\n \"cachedInputTokens\",\n \"totalTokens\",\n] as const satisfies (keyof ThreadTokenUsage)[];\n\nfunction asRecord(value: unknown): UsageRecord | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value))\n return undefined;\n return value as UsageRecord;\n}\n\nfunction asPositiveTokenCount(value: unknown): number | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n return undefined;\n }\n return value;\n}\n\nfunction computeTotalTokens(usage: ThreadTokenUsage): number | undefined {\n if (usage.totalTokens !== undefined) return usage.totalTokens;\n if (usage.inputTokens !== undefined && usage.outputTokens !== undefined) {\n return usage.inputTokens + usage.outputTokens;\n }\n return undefined;\n}\n\nfunction normalizeUsage(value: unknown): ThreadTokenUsage | undefined {\n const record = asRecord(value);\n if (!record) return undefined;\n\n const result: ThreadTokenUsage = {};\n let hasFields = false;\n for (const key of USAGE_KEYS) {\n const count = asPositiveTokenCount(record[key]);\n if (count !== undefined) {\n result[key] = count;\n hasFields = true;\n }\n }\n // AI SDK v7 moved these under token detail objects; v6 kept them top-level.\n if (result.reasoningTokens === undefined) {\n const count = asPositiveTokenCount(\n asRecord(record.outputTokenDetails)?.reasoningTokens,\n );\n if (count !== undefined) {\n result.reasoningTokens = count;\n hasFields = true;\n }\n }\n if (result.cachedInputTokens === undefined) {\n const count = asPositiveTokenCount(\n asRecord(record.inputTokenDetails)?.cacheReadTokens,\n );\n if (count !== undefined) {\n result.cachedInputTokens = count;\n hasFields = true;\n }\n }\n return hasFields ? result : undefined;\n}\n\nfunction withComputedTotal(\n usage: ThreadTokenUsage,\n): ThreadTokenUsage | undefined {\n const totalTokens = computeTotalTokens(usage);\n return { ...usage, ...(totalTokens !== undefined && { totalTokens }) };\n}\n\nfunction usageFromSteps(value: unknown): ThreadTokenUsage | undefined {\n const steps = Array.isArray(value) ? value : [];\n\n const sums: Record<string, number> = {};\n const present: Record<string, boolean> = {};\n let stepsWithUsage = 0;\n let stepsWithComputableTotal = 0;\n\n for (const step of steps) {\n const usage = normalizeUsage(asRecord(step)?.usage);\n if (!usage) continue;\n stepsWithUsage++;\n\n const stepTotal = computeTotalTokens(usage);\n if (stepTotal !== undefined) {\n sums.totalTokens = (sums.totalTokens ?? 0) + stepTotal;\n stepsWithComputableTotal++;\n }\n\n for (const key of USAGE_KEYS) {\n if (key === \"totalTokens\") continue;\n if (usage[key] !== undefined) {\n sums[key] = (sums[key] ?? 0) + usage[key];\n present[key] = true;\n }\n }\n }\n\n if (stepsWithUsage === 0) return undefined;\n\n const result: ThreadTokenUsage = {};\n if (stepsWithComputableTotal === stepsWithUsage) {\n result.totalTokens = sums.totalTokens!;\n }\n for (const key of USAGE_KEYS) {\n if (key === \"totalTokens\") continue;\n if (present[key]) {\n result[key] = sums[key]!;\n }\n }\n return result;\n}\n\nexport function getThreadMessageTokenUsage(\n message: TokenUsageExtractableMessage | undefined,\n): ThreadTokenUsage | undefined {\n if (!message || message.role !== \"assistant\") return undefined;\n\n const metadata = asRecord(message.metadata);\n if (!metadata) return undefined;\n\n const topLevelUsage = normalizeUsage(metadata.usage);\n if (topLevelUsage) return withComputedTotal(topLevelUsage);\n\n const customUsage = normalizeUsage(asRecord(metadata.custom)?.usage);\n if (customUsage) return withComputedTotal(customUsage);\n\n return usageFromSteps(metadata.steps);\n}\n\nfunction findLatestMessageWithUsage(\n messages: readonly TokenUsageExtractableMessage[] | undefined,\n): TokenUsageExtractableMessage | undefined {\n if (!messages) return undefined;\n\n for (let idx = messages.length - 1; idx >= 0; idx -= 1) {\n const message = messages[idx];\n if (getThreadMessageTokenUsage(message)) {\n return message;\n }\n }\n\n return undefined;\n}\n\n/**\n * Reads token usage from the newest assistant message that reports any.\n *\n * A route attaches usage through the AI SDK's `messageMetadata` option. Because\n * a thread message carries a fixed metadata shape, the converter moves every\n * other key the route returns into `metadata.custom`, which is where this hook\n * looks.\n */\nexport function useThreadTokenUsage(): ThreadTokenUsage | undefined {\n const msg = useAuiState((s) => findLatestMessageWithUsage(s.thread.messages));\n return useMemo(() => getThreadMessageTokenUsage(msg), [msg]);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/ai-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "Vercel AI SDK adapter for assistant-ui",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-sdk",
|
|
@@ -46,13 +46,13 @@
|
|
|
46
46
|
],
|
|
47
47
|
"sideEffects": false,
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@ai-sdk/mcp": "^2.0.
|
|
50
|
-
"@ai-sdk/react": "^4.0.
|
|
51
|
-
"@assistant-ui/core": "^0.3.
|
|
52
|
-
"@assistant-ui/store": "^0.3.
|
|
53
|
-
"@assistant-ui/tap": "^0.9.
|
|
54
|
-
"assistant-cloud": "^0.2.
|
|
55
|
-
"assistant-stream": "^0.3.
|
|
49
|
+
"@ai-sdk/mcp": "^2.0.63",
|
|
50
|
+
"@ai-sdk/react": "^4.0.126",
|
|
51
|
+
"@assistant-ui/core": "^0.3.23",
|
|
52
|
+
"@assistant-ui/store": "^0.3.17",
|
|
53
|
+
"@assistant-ui/tap": "^0.9.21",
|
|
54
|
+
"assistant-cloud": "^0.2.5",
|
|
55
|
+
"assistant-stream": "^0.3.47"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"@types/react": "*",
|
|
@@ -68,16 +68,16 @@
|
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
71
|
+
"@assistant-ui/x-buildutils": "0.0.30",
|
|
72
72
|
"@assistant-ui/x-react18": "0.0.0",
|
|
73
73
|
"@testing-library/react": "^16.3.3",
|
|
74
74
|
"@types/json-schema": "^7.0.15",
|
|
75
75
|
"@types/react": "^19.3.0",
|
|
76
76
|
"@types/react-dom": "^19.3.0",
|
|
77
|
-
"ai": "^7.0.
|
|
77
|
+
"ai": "^7.0.123",
|
|
78
78
|
"jsdom": "^30.0.1",
|
|
79
79
|
"react": "^19.3.0",
|
|
80
|
-
"vitest": "^5.0.
|
|
80
|
+
"vitest": "^5.0.3"
|
|
81
81
|
},
|
|
82
82
|
"publishConfig": {
|
|
83
83
|
"access": "public",
|
|
@@ -1483,6 +1483,42 @@ describe("AISDKMessageConverter", () => {
|
|
|
1483
1483
|
expect(converted[0]?.content[2]).not.toHaveProperty("providerMetadata");
|
|
1484
1484
|
});
|
|
1485
1485
|
|
|
1486
|
+
it("keeps a step scoped reasoning block id off the part", () => {
|
|
1487
|
+
const converted = AISDKMessageConverter.toThreadMessages([
|
|
1488
|
+
{
|
|
1489
|
+
id: "a1",
|
|
1490
|
+
role: "assistant",
|
|
1491
|
+
parts: [
|
|
1492
|
+
{ type: "reasoning", id: "reasoning-0", text: "first step" },
|
|
1493
|
+
{ type: "text", text: "answer" },
|
|
1494
|
+
{ type: "reasoning", id: "reasoning-0", text: "second step" },
|
|
1495
|
+
],
|
|
1496
|
+
} as any,
|
|
1497
|
+
]);
|
|
1498
|
+
|
|
1499
|
+
expect(converted[0]?.content[0]).toMatchObject({ type: "reasoning" });
|
|
1500
|
+
expect(converted[0]?.content[0]).not.toHaveProperty("id");
|
|
1501
|
+
expect(converted[0]?.content[1]).not.toHaveProperty("id");
|
|
1502
|
+
expect(converted[0]?.content[2]).not.toHaveProperty("id");
|
|
1503
|
+
});
|
|
1504
|
+
|
|
1505
|
+
it("forwards data part ids", () => {
|
|
1506
|
+
const converted = AISDKMessageConverter.toThreadMessages([
|
|
1507
|
+
{
|
|
1508
|
+
id: "a1",
|
|
1509
|
+
role: "assistant",
|
|
1510
|
+
parts: [{ type: "data-chart", id: "data-1", data: { x: 1 } }],
|
|
1511
|
+
} as any,
|
|
1512
|
+
]);
|
|
1513
|
+
|
|
1514
|
+
expect(converted[0]?.content[0]).toMatchObject({
|
|
1515
|
+
type: "data",
|
|
1516
|
+
id: "data-1",
|
|
1517
|
+
name: "chart",
|
|
1518
|
+
data: { x: 1 },
|
|
1519
|
+
});
|
|
1520
|
+
});
|
|
1521
|
+
|
|
1486
1522
|
it("maps TextUIPart.state onto the per-part status", () => {
|
|
1487
1523
|
const converted = AISDKMessageConverter.toThreadMessages([
|
|
1488
1524
|
{
|
|
@@ -585,6 +585,9 @@ function convertParts(
|
|
|
585
585
|
if (part.type.startsWith("data-")) {
|
|
586
586
|
return {
|
|
587
587
|
type: "data",
|
|
588
|
+
...("id" in part && typeof part.id === "string"
|
|
589
|
+
? { id: part.id }
|
|
590
|
+
: undefined),
|
|
588
591
|
name: part.type.substring(5),
|
|
589
592
|
data: (part as any).data,
|
|
590
593
|
} satisfies DataMessagePart;
|
|
@@ -185,6 +185,19 @@ describe("toCreateMessage", () => {
|
|
|
185
185
|
]);
|
|
186
186
|
});
|
|
187
187
|
|
|
188
|
+
it("forwards a data part id", () => {
|
|
189
|
+
const message = {
|
|
190
|
+
...baseMessage,
|
|
191
|
+
content: [
|
|
192
|
+
{ type: "data", name: "workflow", id: "p1", data: { field: 1 } },
|
|
193
|
+
],
|
|
194
|
+
} as unknown as AppendMessage;
|
|
195
|
+
|
|
196
|
+
expect(toCreateMessage(message).parts).toEqual([
|
|
197
|
+
{ type: "data-workflow", id: "p1", data: { field: 1 } },
|
|
198
|
+
]);
|
|
199
|
+
});
|
|
200
|
+
|
|
188
201
|
it("converts a data part inside an attachment without throwing", () => {
|
|
189
202
|
const message = {
|
|
190
203
|
...baseMessage,
|
|
@@ -86,6 +86,7 @@ export const toCreateMessage = <UI_MESSAGE extends UIMessage = UIMessage>(
|
|
|
86
86
|
return {
|
|
87
87
|
type: `data-${part.name}`,
|
|
88
88
|
data: part.data,
|
|
89
|
+
...(part.id !== undefined && { id: part.id }),
|
|
89
90
|
};
|
|
90
91
|
default:
|
|
91
92
|
throw new Error(`Unsupported part type: ${part.type}`);
|