@assistant-ui/ai-sdk 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/adapters/aiSDKFormatAdapter.d.ts +2 -8
  2. package/dist/adapters/aiSDKFormatAdapter.js +1 -25
  3. package/dist/converters/convertMessage.d.ts.map +1 -1
  4. package/dist/converters/convertMessage.js +9 -4
  5. package/dist/converters/convertMessage.js.map +1 -1
  6. package/dist/runtime/AISDKThreads.d.ts.map +1 -1
  7. package/dist/runtime/AISDKThreads.js +90 -65
  8. package/dist/runtime/AISDKThreads.js.map +1 -1
  9. package/dist/runtime/sdkIdentity.d.ts +6 -0
  10. package/dist/runtime/sdkIdentity.d.ts.map +1 -0
  11. package/dist/runtime/sdkIdentity.js +9 -0
  12. package/dist/runtime/sdkIdentity.js.map +1 -0
  13. package/dist/runtime/useAISDKRuntime.d.ts.map +1 -1
  14. package/dist/runtime/useAISDKRuntime.js +8 -1
  15. package/dist/runtime/useAISDKRuntime.js.map +1 -1
  16. package/dist/runtime/useChatRuntime.d.ts.map +1 -1
  17. package/dist/runtime/useChatRuntime.js +7 -2
  18. package/dist/runtime/useChatRuntime.js.map +1 -1
  19. package/dist/runtime/useChatThread.js +1 -1
  20. package/dist/runtime/useChatThread.js.map +1 -1
  21. package/dist/runtime/useExternalHistory.d.ts.map +1 -1
  22. package/dist/runtime/useExternalHistory.js +4 -1
  23. package/dist/runtime/useExternalHistory.js.map +1 -1
  24. package/dist/tools/generativeTools.js +7 -4
  25. package/dist/tools/generativeTools.js.map +1 -1
  26. package/dist/usage.d.ts +8 -0
  27. package/dist/usage.d.ts.map +1 -1
  28. package/dist/usage.js +8 -0
  29. package/dist/usage.js.map +1 -1
  30. package/package.json +12 -12
  31. package/src/adapters/aiSDKFormatAdapter.ts +4 -41
  32. package/src/converters/convertMessage.test.ts +116 -0
  33. package/src/converters/convertMessage.ts +39 -18
  34. package/src/runtime/AISDKChat.integration.test.tsx +48 -27
  35. package/src/runtime/AISDKThreads.cloud.test.ts +12 -3
  36. package/src/runtime/AISDKThreads.test.ts +131 -8
  37. package/src/runtime/AISDKThreads.ts +31 -3
  38. package/src/runtime/__tests__/controlled-transport.ts +21 -0
  39. package/src/runtime/sdkIdentity.ts +9 -0
  40. package/src/runtime/useAISDKRuntime.test.ts +39 -1
  41. package/src/runtime/useAISDKRuntime.ts +17 -1
  42. package/src/runtime/useChatRuntime.integration.test.tsx +137 -4
  43. package/src/runtime/useChatRuntime.test.ts +0 -1
  44. package/src/runtime/useChatRuntime.ts +3 -1
  45. package/src/runtime/useChatThread.test.ts +74 -0
  46. package/src/runtime/useChatThread.ts +1 -1
  47. package/src/runtime/useExternalHistory.test.ts +29 -0
  48. package/src/runtime/useExternalHistory.ts +7 -1
  49. package/src/tools/generativeTools.test.ts +79 -0
  50. package/src/tools/generativeTools.ts +7 -8
  51. package/src/transport/AssistantChatTransport.test.ts +1 -9
  52. package/src/usage.ts +8 -0
  53. package/dist/adapters/aiSDKFormatAdapter.d.ts.map +0 -1
  54. package/dist/adapters/aiSDKFormatAdapter.js.map +0 -1
@@ -1,8 +1,2 @@
1
- import { UIMessage } from "ai";
2
- import { MessageFormatAdapter } from "@assistant-ui/core";
3
- //#region src/adapters/aiSDKFormatAdapter.d.ts
4
- type AISDKStorageFormat = Omit<UIMessage, "id">;
5
- declare const aiSDKV6FormatAdapter: MessageFormatAdapter<UIMessage, AISDKStorageFormat>;
6
- //#endregion
7
- export { AISDKStorageFormat, aiSDKV6FormatAdapter };
8
- //# sourceMappingURL=aiSDKFormatAdapter.d.ts.map
1
+ import { AISDKStorageFormat, aiSDKV6FormatAdapter } from "assistant-cloud/ai-sdk";
2
+ export { type AISDKStorageFormat, aiSDKV6FormatAdapter };
@@ -1,26 +1,2 @@
1
- //#region src/adapters/aiSDKFormatAdapter.ts
2
- const aiSDKV6FormatAdapter = {
3
- format: "ai-sdk/v6",
4
- encode({ message: { id, parts, ...message } }) {
5
- return {
6
- ...message,
7
- parts
8
- };
9
- },
10
- decode(stored) {
11
- return {
12
- parentId: stored.parent_id,
13
- message: {
14
- id: stored.id,
15
- ...stored.content
16
- }
17
- };
18
- },
19
- getId(message) {
20
- return message.id;
21
- }
22
- };
23
- //#endregion
1
+ import { aiSDKV6FormatAdapter } from "assistant-cloud/ai-sdk";
24
2
  export { aiSDKV6FormatAdapter };
25
-
26
- //# sourceMappingURL=aiSDKFormatAdapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"convertMessage.d.ts","names":[],"sources":["../../src/converters/convertMessage.ts"],"mappings":";;;;;KAyDY,gCACV,4BAA4B;EAC1B,wBAAwB,YAAY;EACpC,qBAAqB,YAAY;EACjC,sBAAsB,YAAY;;EAElC;;cA+VS;;;;;;;;EA9XmB,qBAAA,oCAAA,2CAAA,6CAAA;EAK9B,oBAAA,oCAAA,2CAAA,6CAAA"}
1
+ {"version":3,"file":"convertMessage.d.ts","names":[],"sources":["../../src/converters/convertMessage.ts"],"mappings":";;;;;KA0DY,gCACV,4BAA4B;EAC1B,wBAAwB,YAAY;EACpC,qBAAqB,YAAY;EACjC,sBAAsB,YAAY;;EAElC;;cAmXS;;;;;;;;EAnZmB,qBAAA,oCAAA,2CAAA,6CAAA;EAK9B,oBAAA,oCAAA,2CAAA,6CAAA"}
@@ -13,6 +13,7 @@ const THREAD_METADATA_KEYS = /* @__PURE__ */ new Set([
13
13
  "timing",
14
14
  "submittedFeedback",
15
15
  "isOptimistic",
16
+ "modality",
16
17
  "custom"
17
18
  ]);
18
19
  const toThreadMetadata = (metadata) => {
@@ -76,13 +77,17 @@ function extractMcpAppMetadata(part, cache) {
76
77
  return out;
77
78
  }
78
79
  function getToolApprovalAndInterrupt(part, toolStatus) {
79
- if (part.approval && typeof part.approval.id === "string") {
80
- const { id, approved, reason, isAutomatic } = part.approval;
81
- return { approval: {
80
+ if (part.approval) {
81
+ const { id, prompt, approved, reason, isAutomatic, resolution, display, allowFreeform, options, optionId, text, ...additionalApprovalFields } = part.approval;
82
+ const requestReason = additionalApprovalFields.requestReason;
83
+ if (typeof id === "string") return { approval: {
84
+ ...additionalApprovalFields,
82
85
  id,
86
+ ...typeof prompt === "string" ? { prompt } : typeof requestReason === "string" ? { prompt: requestReason } : {},
83
87
  ...typeof approved === "boolean" && { approved },
84
88
  ...typeof reason === "string" && { reason },
85
- ...isAutomatic === true && { isAutomatic: true }
89
+ ...isAutomatic === true && { isAutomatic: true },
90
+ ...(resolution === "cancelled" || resolution === "expired") && { resolution }
86
91
  } };
87
92
  }
88
93
  if (toolStatus?.type === "interrupt") return { interrupt: toolStatus.payload };
@@ -1 +1 @@
1
- {"version":3,"file":"convertMessage.js","names":["isToolUIPart","isReasoningFileUIPart","isCustomContentUIPart","getToolName","UIMessage","createMessageConverter","unstable_createMessageConverter","useExternalMessageConverter","isMcpAppUri","ReasoningMessagePart","ToolCallMessagePart","TextMessagePart","DataMessagePart","PartProviderMetadata","SourceMessagePart","SourceProviderMetadata","FileMessagePart","ThreadMessageLike","McpAppMetadata","MessagePartStreamStatus","stableStringifyToolArgs","parsePartialJsonObject","ReadonlyJSONObject","unwrapModelContentEnvelope","MessageMetadata","THREAD_METADATA_KEYS","Set","toThreadMetadata","metadata","undefined","result","Record","extra","key","value","Object","entries","has","keys","length","custom","AISDKMessageConverterMetadata","Metadata","toolArgsKeyOrderCache","Map","toolLastInputCache","mcpAppMetadataCache","optimisticMessageId","stripClosingDelimiters","json","replace","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","getToolApprovalAndInterrupt","approval","id","approved","reason","isAutomatic","toolStatus","type","payload","NonNullable","interrupt","MessageContent","Exclude","uiPartStateToStatus","state","convertParts","message","parts","converted","p","role","map","status","text","providerMetadata","toolName","toolCallId","argsKeyOrderCacheKey","rawInput","input","args","modelContent","isError","unwrapped","error","errorText","argsText","toolStatuses","mcpApp","sourceType","sourceId","url","title","data","mediaType","filename","startsWith","name","substring","kind","console","warn","Boolean","seenToolCallIds","add","AISDKMessageConverter","createdAt","Date","content","attachments","idx","isImage","toString","image","contentType","const","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 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} 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 \"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: 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 toolLastInputCache?: Map<string, ReadonlyJSONObject>;\n mcpAppMetadataCache?: Map<string, McpAppMetadata>;\n /** Id of the currently-streaming message, flagged optimistic (#4037). */\n optimisticMessageId?: string | undefined;\n };\n\nfunction stripClosingDelimiters(json: string): string {\n return json.replace(/[}\\]\"]+$/, \"\");\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\nfunction getToolApprovalAndInterrupt(\n part: {\n approval?:\n | {\n id: string;\n approved?: boolean;\n reason?: string;\n isAutomatic?: boolean;\n }\n | undefined;\n },\n toolStatus: { type: string; payload?: unknown } | undefined,\n): {\n approval?: NonNullable<ToolCallMessagePart[\"approval\"]>;\n interrupt?: NonNullable<ToolCallMessagePart[\"interrupt\"]>;\n} {\n if (part.approval && typeof part.approval.id === \"string\") {\n const { id, approved, reason, isAutomatic } = part.approval;\n return {\n approval: {\n id,\n ...(typeof approved === \"boolean\" && { approved }),\n ...(typeof reason === \"string\" && { reason }),\n ...(isAutomatic === true && { isAutomatic: true }),\n },\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 const rawInput = part.input as ReadonlyJSONObject | null | 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 = stableStringifyToolArgs(\n metadata.toolArgsKeyOrderCache,\n argsKeyOrderCacheKey,\n args,\n );\n if (part.state === \"input-streaming\") {\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 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 return {\n type: \"tool-call\",\n toolName,\n toolCallId,\n argsText,\n args,\n result,\n isError,\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(part, toolStatus),\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 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","ToolCallMessagePart","TextMessagePart","DataMessagePart","PartProviderMetadata","SourceMessagePart","SourceProviderMetadata","FileMessagePart","ThreadMessageLike","McpAppMetadata","MessagePartStreamStatus","stableStringifyToolArgs","parsePartialJsonObject","ReadonlyJSONObject","unwrapModelContentEnvelope","MessageMetadata","THREAD_METADATA_KEYS","Set","toThreadMetadata","metadata","undefined","result","Record","extra","key","value","Object","entries","has","keys","length","custom","AISDKMessageConverterMetadata","Metadata","toolArgsKeyOrderCache","Map","toolLastInputCache","mcpAppMetadataCache","optimisticMessageId","stripClosingDelimiters","json","replace","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","getToolApprovalAndInterrupt","approval","toolStatus","type","payload","NonNullable","interrupt","id","prompt","approved","reason","isAutomatic","resolution","display","allowFreeform","options","optionId","text","additionalApprovalFields","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","toolStatuses","mcpApp","sourceType","sourceId","url","title","data","mediaType","filename","startsWith","name","substring","kind","console","warn","Boolean","seenToolCallIds","add","AISDKMessageConverter","createdAt","Date","content","attachments","idx","isImage","toString","image","contentType","const","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 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} 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: 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 toolLastInputCache?: Map<string, ReadonlyJSONObject>;\n mcpAppMetadataCache?: Map<string, McpAppMetadata>;\n /** Id of the currently-streaming message, flagged optimistic (#4037). */\n optimisticMessageId?: string | undefined;\n };\n\nfunction stripClosingDelimiters(json: string): string {\n return json.replace(/[}\\]\"]+$/, \"\");\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\nfunction getToolApprovalAndInterrupt(\n part: {\n approval?: Record<string, unknown> | undefined;\n },\n toolStatus: { type: string; payload?: unknown } | undefined,\n): {\n approval?: NonNullable<ToolCallMessagePart[\"approval\"]>;\n interrupt?: NonNullable<ToolCallMessagePart[\"interrupt\"]>;\n} {\n if (part.approval) {\n // The AI SDK sends only id, approved and reason back to the server, so a\n // request shape promising any other answer would render controls whose\n // response cannot travel.\n const {\n id,\n prompt,\n approved,\n reason,\n isAutomatic,\n resolution,\n display,\n allowFreeform,\n options,\n optionId,\n text,\n ...additionalApprovalFields\n } = part.approval;\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 ...((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 const rawInput = part.input as ReadonlyJSONObject | null | 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 = stableStringifyToolArgs(\n metadata.toolArgsKeyOrderCache,\n argsKeyOrderCacheKey,\n args,\n );\n if (part.state === \"input-streaming\") {\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 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 return {\n type: \"tool-call\",\n toolName,\n toolCallId,\n argsText,\n args,\n result,\n isError,\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(part, toolStatus),\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 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":"AISDKThreads.d.ts","names":[],"sources":["../../src/runtime/AISDKThreads.ts"],"mappings":";;;;;KA6BY,oBAAoB,mBAAmB,cAAY,eAC7D,KAAK,kBAAkB;;;;;;;;EAQrB,YACI,cAAc,qBACP,cAAc;;;;;;;EAQzB,QAAQ;;;;EAIR;;;;EAIA,qBAAqB;;;;;;;;;;;;;;;cA2KZ,eA3DY,mBAAmB,cAAS,kCAAA,0BAAA,UAAA,UAAA,oBAAA,wDAAA,8CAAA"}
1
+ {"version":3,"file":"AISDKThreads.d.ts","names":[],"sources":["../../src/runtime/AISDKThreads.ts"],"mappings":";;;;;KA8BY,oBAAoB,mBAAmB,cAAY,eAC7D,KAAK,kBAAkB;;;;;;;;EAQrB,YACI,cAAc,qBACP,cAAc;;;;;;;EAQzB,QAAQ;;;;EAIR;;;;EAIA,qBAAqB;;;;;;;;;;;;;;;cAsMZ,eAjEY,mBAAmB,cAAS,kCAAA,0BAAA,UAAA,UAAA,oBAAA,wDAAA,8CAAA"}
@@ -2,6 +2,7 @@
2
2
  import { AssistantChatTransport } from "../transport/AssistantChatTransport.js";
3
3
  import { useResourceCleanup } from "./useResourceCleanup.js";
4
4
  import { splitChatThreadOptions, useChatThread } from "./useChatThread.js";
5
+ import { AI_SDK_SDK } from "./sdkIdentity.js";
5
6
  import { useCloudThreadListAdapter } from "@assistant-ui/core/react";
6
7
  import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
7
8
  import { useEffect, useState } from "@assistant-ui/tap/react-shim";
@@ -14,16 +15,23 @@ import { attachTransformScopes, useAssistantClientRef, useAssistantScopeEffect }
14
15
  import { ThreadClient } from "@assistant-ui/core/store/internal";
15
16
  //#region src/runtime/AISDKThreads.ts
16
17
  const createChatEntry = (threadId, options) => {
18
+ const optionsRef = { current: options };
17
19
  const { chatInit } = splitChatThreadOptions(options);
18
20
  const transport = typeof options?.transport === "function" ? options.transport() : options?.transport === void 0 ? new AssistantChatTransport() : options.transport instanceof AssistantChatTransport ? options.transport.__internal_clone() : options.transport;
19
21
  return {
20
22
  chat: new Chat({
21
23
  ...chatInit,
22
24
  id: threadId,
23
- transport
25
+ transport,
26
+ onToolCall: (arg) => optionsRef.current?.onToolCall?.(arg),
27
+ onData: (arg) => optionsRef.current?.onData?.(arg),
28
+ onFinish: (arg) => optionsRef.current?.onFinish?.(arg),
29
+ onError: (arg) => optionsRef.current?.onError?.(arg),
30
+ sendAutomaticallyWhen: (arg) => optionsRef.current?.sendAutomaticallyWhen?.(arg) ?? false
24
31
  }),
25
32
  transport,
26
- repository: new MessageRepository()
33
+ repository: new MessageRepository(),
34
+ optionsRef
27
35
  };
28
36
  };
29
37
  const getOrCreateChatEntry = (threadId, options, chats) => {
@@ -34,7 +42,7 @@ const getOrCreateChatEntry = (threadId, options, chats) => {
34
42
  return created;
35
43
  };
36
44
  const useAISDKChatThread = (t0) => {
37
- const $ = c(35);
45
+ const $ = c(39);
38
46
  const { threadId, options, chats, cloud } = t0;
39
47
  let t1;
40
48
  if ($[0] !== cloud || $[1] !== options || $[2] !== threadId) {
@@ -54,95 +62,106 @@ const useAISDKChatThread = (t0) => {
54
62
  $[7] = threadId;
55
63
  $[8] = t2;
56
64
  } else t2 = $[8];
57
- const { chat, transport, repository } = t2;
65
+ const { chat, transport, repository, optionsRef } = t2;
58
66
  let t3;
59
- let t4;
60
- if ($[9] !== chat || $[10] !== cloud) {
67
+ if ($[9] !== cloud || $[10] !== options || $[11] !== optionsRef) {
61
68
  t3 = () => {
69
+ if (cloud) optionsRef.current = options;
70
+ };
71
+ $[9] = cloud;
72
+ $[10] = options;
73
+ $[11] = optionsRef;
74
+ $[12] = t3;
75
+ } else t3 = $[12];
76
+ useEffect(t3);
77
+ let t4;
78
+ let t5;
79
+ if ($[13] !== chat || $[14] !== cloud) {
80
+ t4 = () => {
62
81
  if (!cloud) return;
63
82
  return () => {
64
83
  chat.stop().catch(_temp);
65
84
  };
66
85
  };
67
- t4 = [chat, cloud];
68
- $[9] = chat;
69
- $[10] = cloud;
70
- $[11] = t3;
71
- $[12] = t4;
86
+ t5 = [chat, cloud];
87
+ $[13] = chat;
88
+ $[14] = cloud;
89
+ $[15] = t4;
90
+ $[16] = t5;
72
91
  } else {
73
- t3 = $[11];
74
- t4 = $[12];
92
+ t4 = $[15];
93
+ t5 = $[16];
75
94
  }
76
- useEffect(t3, t4);
95
+ useEffect(t4, t5);
77
96
  const aui = useAui();
78
- let t5;
79
- if ($[13] !== threadId) {
80
- t5 = { initialize: async () => ({
97
+ let t6;
98
+ if ($[17] !== threadId) {
99
+ t6 = { initialize: async () => ({
81
100
  remoteId: threadId,
82
101
  externalId: void 0
83
102
  }) };
84
- $[13] = threadId;
85
- $[14] = t5;
86
- } else t5 = $[14];
87
- const fallbackItem = t5;
88
- let t6;
89
- if ($[15] !== options || $[16] !== transport) {
90
- t6 = {
103
+ $[17] = threadId;
104
+ $[18] = t6;
105
+ } else t6 = $[18];
106
+ const fallbackItem = t6;
107
+ let t7;
108
+ if ($[19] !== options || $[20] !== transport) {
109
+ t7 = {
91
110
  ...options,
92
111
  transport
93
112
  };
94
- $[15] = options;
95
- $[16] = transport;
96
- $[17] = t6;
97
- } else t6 = $[17];
98
- let t7;
99
- if ($[18] !== aui || $[19] !== cloud || $[20] !== fallbackItem) {
100
- t7 = () => cloud ? aui.threadListItem.source ? aui.threadListItem : void 0 : fallbackItem;
101
- $[18] = aui;
102
- $[19] = cloud;
103
- $[20] = fallbackItem;
113
+ $[19] = options;
114
+ $[20] = transport;
104
115
  $[21] = t7;
105
116
  } else t7 = $[21];
106
117
  let t8;
107
- if ($[22] !== chat || $[23] !== cloud || $[24] !== repository || $[25] !== t7 || $[26] !== threadId) {
108
- t8 = {
118
+ if ($[22] !== aui || $[23] !== cloud || $[24] !== fallbackItem) {
119
+ t8 = () => cloud ? aui.threadListItem.source ? aui.threadListItem : void 0 : fallbackItem;
120
+ $[22] = aui;
121
+ $[23] = cloud;
122
+ $[24] = fallbackItem;
123
+ $[25] = t8;
124
+ } else t8 = $[25];
125
+ let t9;
126
+ if ($[26] !== chat || $[27] !== cloud || $[28] !== repository || $[29] !== t8 || $[30] !== threadId) {
127
+ t9 = {
109
128
  id: threadId,
110
129
  isMainThread: true,
111
- getThreadListItem: t7,
130
+ getThreadListItem: t8,
112
131
  chat,
113
132
  messageRepositoryInstance: repository,
114
133
  stopOnClientDestroy: cloud
115
134
  };
116
- $[22] = chat;
117
- $[23] = cloud;
118
- $[24] = repository;
119
- $[25] = t7;
120
- $[26] = threadId;
121
- $[27] = t8;
122
- } else t8 = $[27];
123
- const runtime = useChatThread(t6, t8);
135
+ $[26] = chat;
136
+ $[27] = cloud;
137
+ $[28] = repository;
138
+ $[29] = t8;
139
+ $[30] = threadId;
140
+ $[31] = t9;
141
+ } else t9 = $[31];
142
+ const runtime = useChatThread(t7, t9);
124
143
  const clientRef = useAssistantClientRef();
125
- let t9;
126
- if ($[28] !== clientRef || $[29] !== runtime) {
127
- t9 = () => runtime.registerModelContextProvider(clientRef.current.modelContext());
128
- $[28] = clientRef;
129
- $[29] = runtime;
130
- $[30] = t9;
131
- } else t9 = $[30];
132
144
  let t10;
133
- if ($[31] !== runtime) {
134
- t10 = [runtime];
135
- $[31] = runtime;
136
- $[32] = t10;
137
- } else t10 = $[32];
138
- useAssistantScopeEffect("modelContext", t9, t10);
145
+ if ($[32] !== clientRef || $[33] !== runtime) {
146
+ t10 = () => runtime.registerModelContextProvider(clientRef.current.modelContext());
147
+ $[32] = clientRef;
148
+ $[33] = runtime;
149
+ $[34] = t10;
150
+ } else t10 = $[34];
139
151
  let t11;
140
- if ($[33] !== runtime.thread) {
141
- t11 = ThreadClient({ runtime: runtime.thread });
142
- $[33] = runtime.thread;
143
- $[34] = t11;
144
- } else t11 = $[34];
145
- return useResource(t11);
152
+ if ($[35] !== runtime) {
153
+ t11 = [runtime];
154
+ $[35] = runtime;
155
+ $[36] = t11;
156
+ } else t11 = $[36];
157
+ useAssistantScopeEffect("modelContext", t10, t11);
158
+ let t12;
159
+ if ($[37] !== runtime.thread) {
160
+ t12 = ThreadClient({ runtime: runtime.thread });
161
+ $[37] = runtime.thread;
162
+ $[38] = t12;
163
+ } else t12 = $[38];
164
+ return useResource(t12);
146
165
  };
147
166
  const AISDKChatThread = resource(useAISDKChatThread);
148
167
  const useAISDKThreads = (options) => {
@@ -150,6 +169,9 @@ const useAISDKThreads = (options) => {
150
169
  const { cloud, threadId, onThreadIdChange, ...threadOptions } = options ?? {};
151
170
  const [chats] = useState(_temp2);
152
171
  const bindCloud = cloud !== void 0;
172
+ useEffect(() => {
173
+ for (const { optionsRef } of chats.values()) optionsRef.current = threadOptions;
174
+ });
153
175
  let t0;
154
176
  if ($[0] !== chats) {
155
177
  t0 = () => {
@@ -159,7 +181,10 @@ const useAISDKThreads = (options) => {
159
181
  $[1] = t0;
160
182
  } else t0 = $[1];
161
183
  useResourceCleanup(true, t0);
162
- const cloudAdapter = useCloudThreadListAdapter({ cloud });
184
+ const cloudAdapter = useCloudThreadListAdapter({
185
+ cloud,
186
+ sdk: AI_SDK_SDK
187
+ });
163
188
  const thread = (id) => {
164
189
  const element = AISDKChatThread({
165
190
  threadId: id,
@@ -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","splitChatThreadOptions","useChatThread","ChatThreadOptions","MessageRepository","useResourceCleanup","AISDKThreadsOptions","Omit","UI_MESSAGE","transport","cloud","threadId","onThreadIdChange","AISDKThreadChatOptions","ChatEntry","chat","repository","createChatEntry","options","chatInit","undefined","__internal_clone","id","getOrCreateChatEntry","chats","Map","existing","get","created","set","useAISDKChatThread","t0","$","t1","owned","t2","t3","t4","stop","catch","_temp","aui","t5","initialize","remoteId","externalId","fallbackItem","t6","t7","threadListItem","source","t8","isMainThread","getThreadListItem","messageRepositoryInstance","stopOnClientDestroy","runtime","clientRef","t9","registerModelContextProvider","current","modelContext","t10","t11","thread","AISDKChatThread","useAISDKThreads","threadOptions","_temp2","bindCloud","values","_temp3","cloudAdapter","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 { Chat, type 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 splitChatThreadOptions,\n useChatThread,\n type ChatThreadOptions,\n} from \"./useChatThread\";\nimport { MessageRepository } from \"@assistant-ui/core/internal\";\nimport { useResourceCleanup } from \"./useResourceCleanup\";\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 ChatEntry<UI_MESSAGE extends UIMessage> = {\n chat: Chat<UI_MESSAGE>;\n transport: ChatTransport<UI_MESSAGE>;\n repository: MessageRepository;\n};\n\nconst createChatEntry = <UI_MESSAGE extends UIMessage>(\n threadId: string,\n options: AISDKThreadChatOptions<UI_MESSAGE> | undefined,\n): ChatEntry<UI_MESSAGE> => {\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: new Chat<UI_MESSAGE>({ ...chatInit, id: threadId, transport }),\n transport,\n repository: new MessageRepository(),\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 } =\n owned ?? getOrCreateChatEntry(threadId, options, chats);\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: cloud,\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 useResourceCleanup(true, () => {\n for (const { chat } of chats.values()) {\n void chat.stop().catch(() => {});\n }\n });\n\n const cloudAdapter = useCloudThreadListAdapter({ cloud });\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","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","onToolCall","arg","onData","onFinish","onError","sendAutomaticallyWhen","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 { Chat, type 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 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: new Chat<UI_MESSAGE>({\n ...chatInit,\n id: threadId,\n transport,\n onToolCall: (arg) => optionsRef.current?.onToolCall?.(arg),\n onData: (arg) => optionsRef.current?.onData?.(arg),\n onFinish: (arg) => optionsRef.current?.onFinish?.(arg),\n onError: (arg) => optionsRef.current?.onError?.(arg),\n sendAutomaticallyWhen: (arg) =>\n optionsRef.current?.sendAutomaticallyWhen?.(arg) ?? false,\n }),\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: cloud,\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":";;;;;;;;;;;;;;;;AA4EA,MAAM0C,mBACJT,UACAU,YAC0B;CAC1B,MAAMF,aAAyC,EAAEJ,SAASM,QAAQ;CAClE,MAAM,EAAEC,aAAatB,uBACnBqB,OACF;CACA,MAAMZ,YACJ,OAAOY,SAASZ,cAAc,aAC1BY,QAAQZ,UAAU,IAClBY,SAASZ,cAAcc,KAAAA,IACrB,IAAIxB,uBAAuB,IAC3BsB,QAAQZ,qBAAqBV,yBAC3BsB,QAAQZ,UAAUe,iBAAiB,IACnCH,QAAQZ;CAClB,OAAO;EACLQ,MAAM,IAAI/B,KAAiB;GACzB,GAAGoC;GACHG,IAAId;GACJF;GACAiB,aAAaC,QAAQR,WAAWJ,SAASW,aAAaC,GAAG;GACzDC,SAASD,QAAQR,WAAWJ,SAASa,SAASD,GAAG;GACjDE,WAAWF,QAAQR,WAAWJ,SAASc,WAAWF,GAAG;GACrDG,UAAUH,QAAQR,WAAWJ,SAASe,UAAUH,GAAG;GACnDI,wBAAwBJ,QACtBR,WAAWJ,SAASgB,wBAAwBJ,GAAG,KAAK;EACxD,CAAC;EACDlB;EACAS,YAAY,IAAIf,kBAAkB;EAClCgB;CACF;AACF;AAEA,MAAMa,wBACJrB,UACAU,SACAY,UAC0B;CAC1B,MAAME,WAAWF,MAAMG,IAAIzB,QAAQ;CACnC,IAAIwB,UAAU,OAAOA;CACrB,MAAME,UAAUjB,gBAAgBT,UAAUU,OAAO;CACjDY,MAAMK,IAAI3B,UAAU0B,OAAO;CAC3B,OAAOA;AACT;AAEA,MAAME,sBAAqBC,OAAA;CAAA,MAAAC,IAAA9D,EAAA,EAAA;CAA2C,MAAA,EAAAgC,UAAAU,SAAAY,OAAAvB,UAAA8B;CAUrE,IAAAE;CAAA,IAAAD,EAAA,OAAA/B,SAAA+B,EAAA,OAAApB,WAAAoB,EAAA,OAAA9B,UAAA;EAC0B+B,WACvBhC,QAAQU,gBAAgBT,UAAUU,OAAmB,IAArDE,KAAAA;EAAsDkB,EAAA,KAAA/B;EAAA+B,EAAA,KAAApB;EAAAoB,EAAA,KAAA9B;EAAA8B,EAAA,KAAAC;CAAA,OAAAA,KAAAD,EAAA;CADxD,MAAA,CAAAE,SAAgB1D,SAASyD,EAEzB;CAAE,IAAAE;CAAA,IAAAH,EAAA,OAAAR,SAAAQ,EAAA,OAAApB,WAAAoB,EAAA,OAAAE,SAAAF,EAAA,OAAA9B,UAAA;EAEAiC,KAAAD,SAASX,qBAAqBrB,UAAUU,SAASY,KAAK;EAACQ,EAAA,KAAAR;EAAAQ,EAAA,KAAApB;EAAAoB,EAAA,KAAAE;EAAAF,EAAA,KAAA9B;EAAA8B,EAAA,KAAAG;CAAA,OAAAA,KAAAH,EAAA;CADzD,MAAA,EAAAxB,MAAAR,WAAAS,YAAAC,eACEyB;CAAwD,IAAAC;CAAA,IAAAJ,EAAA,OAAA/B,SAAA+B,EAAA,QAAApB,WAAAoB,EAAA,QAAAtB,YAAA;EAEhD0B,WAAA;GACR,IAAInC,OAAOS,WAAUJ,UAAWM;EAAQ;EACzCoB,EAAA,KAAA/B;EAAA+B,EAAA,MAAApB;EAAAoB,EAAA,MAAAtB;EAAAsB,EAAA,MAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAFD1D,UAAU8D,EAET;CAAC,IAAAC;CAAA,IAAAC;CAAA,IAAAN,EAAA,QAAAxB,QAAAwB,EAAA,QAAA/B,OAAA;EAEQoC,WAAA;GACR,IAAI,CAACpC,OAAK;GAAmB,aACtB;IACAO,KAAI+B,KAAM,CAAC,CAAAC,MAAOC,KAAQ;GAAC;EACjC;EACAH,KAAA,CAAC9B,MAAMP,KAAK;EAAC+B,EAAA,MAAAxB;EAAAwB,EAAA,MAAA/B;EAAA+B,EAAA,MAAAK;EAAAL,EAAA,MAAAM;CAAA,OAAA;EAAAD,KAAAL,EAAA;EAAAM,KAAAN,EAAA;CAAA;CALhB1D,UAAU+D,IAKPC,EAAa;CAEhB,MAAAI,MAAYrD,OAAO;CAAE,IAAAsD;CAAA,IAAAX,EAAA,QAAA9B,UAAA;EAEZyC,KAAA,EAAAC,YACO,aAAa;GAAAC,UACb3C;GAAQ4C,YACNhC,KAAAA;EACd,GACF;EAACkB,EAAA,MAAA9B;EAAA8B,EAAA,MAAAW;CAAA,OAAAA,KAAAX,EAAA;CANH,MAAAe,eACSJ;CAOP,IAAAK;CAAA,IAAAhB,EAAA,QAAApB,WAAAoB,EAAA,QAAAhC,WAAA;EAEAgD,KAAA;GAAA,GAAKpC;GAAOZ;EAAY;EAACgC,EAAA,MAAApB;EAAAoB,EAAA,MAAAhC;EAAAgC,EAAA,MAAAgB;CAAA,OAAAA,KAAAhB,EAAA;CAAA,IAAAiB;CAAA,IAAAjB,EAAA,QAAAU,OAAAV,EAAA,QAAA/B,SAAA+B,EAAA,QAAAe,cAAA;EAIJE,WACjBhD,QACIyC,IAAGQ,eAAeC,SAChBT,IAAGQ,iBADLpC,KAAAA,IADJiC;EAIgBf,EAAA,MAAAU;EAAAV,EAAA,MAAA/B;EAAA+B,EAAA,MAAAe;EAAAf,EAAA,MAAAiB;CAAA,OAAAA,KAAAjB,EAAA;CAAA,IAAAoB;CAAA,IAAApB,EAAA,QAAAxB,QAAAwB,EAAA,QAAA/B,SAAA+B,EAAA,QAAAvB,cAAAuB,EAAA,QAAAiB,MAAAjB,EAAA,QAAA9B,UAAA;EARpBkD,KAAA;GAAApC,IACMd;GAAQmD,cACE;GAAIC,mBACCL;GAKDzC;GAAA+C,2BAES9C;GAAU+C,qBAChBvD;EACvB;EAAC+B,EAAA,MAAAxB;EAAAwB,EAAA,MAAA/B;EAAA+B,EAAA,MAAAvB;EAAAuB,EAAA,MAAAiB;EAAAjB,EAAA,MAAA9B;EAAA8B,EAAA,MAAAoB;CAAA,OAAAA,KAAApB,EAAA;CAdH,MAAAyB,UAAgBjE,cACdwD,IACAI,EAaF;CAEA,MAAAM,YAAkBvE,sBAAsB;CAAE,IAAAwE;CAAA,IAAA3B,EAAA,QAAA0B,aAAA1B,EAAA,QAAAyB,SAAA;EAGxCE,YACEF,QAAOG,6BAA8BF,UAASpD,QAAQuD,aAAe,CAAC;EAAC7B,EAAA,MAAA0B;EAAA1B,EAAA,MAAAyB;EAAAzB,EAAA,MAAA2B;CAAA,OAAAA,MAAA3B,EAAA;CAAA,IAAA8B;CAAA,IAAA9B,EAAA,QAAAyB,SAAA;EACzEK,MAAA,CAACL,OAAO;EAACzB,EAAA,MAAAyB;EAAAzB,EAAA,MAAA8B;CAAA,OAAAA,MAAA9B,EAAA;CAJX5C,wBACE,gBACAuE,KAEAG,GACF;CAAC,IAAAC;CAAA,IAAA/B,EAAA,QAAAyB,QAAAO,QAAA;EAEkBD,MAAA/E,aAAa,EAAAyE,SAAWA,QAAOO,OAAQ,CAAC;EAAChC,EAAA,MAAAyB,QAAAO;EAAAhC,EAAA,MAAA+B;CAAA,OAAAA,MAAA/B,EAAA;CAAA,OAArD5D,YAAY2F,GAAyC;AAAC;AAG/D,MAAME,kBAAkB9F,SAAS2D,kBAAkB;AAEnD,MAAMoC,mBAAkBtD,YAAA;CAAA,MAAAoB,IAAA9D,EAAA,CAAA;CAGtB,MAAA,EAAA+B,OAAAC,UAAAC,kBAAA,GAAAgE,kBAAgEvD,WAAA,CAAY;CAC5E,MAAA,CAAAY,SAAgBhD,SAAS4F,MAA8C;CACvE,MAAAC,YAAkBpE,UAAUa,KAAAA;CAE5BxC,gBAAU;EACR,KAAK,MAAA,EAAAoC,gBAAwBc,MAAK8C,OAAQ,GACxC5D,WAAUJ,UAAW6D;CACtB,CACF;CAAC,IAAApC;CAAA,IAAAC,EAAA,OAAAR,OAAA;EAEuBO,WAAA;GACvB,KAAK,MAAA,EAAAvB,UAAkBgB,MAAK8C,OAAQ,GAC7B9D,KAAI+B,KAAM,CAAC,CAAAC,MAAO+B,MAAQ;EAChC;EACFvC,EAAA,KAAAR;EAAAQ,EAAA,KAAAD;CAAA,OAAAA,KAAAC,EAAA;CAJDrC,mBAAmB,MAAMoC,EAIxB;CAED,MAAAyC,eAAqBvF,0BAA0B;EAAAgB;EAAAwE,KAAc7E;CAAW,CAAC;CACzE,MAAAoE,UAAehD,OAAA;EACb,MAAA0D,UAAgBT,gBAAgB;GAAA/D,UACpBc;GAAEJ,SACHuD;GAAa3C;GAAAvB,OAEfoE;EACT,CAAC;EAAE,OACIA,YAAYhG,QAAQ2C,IAAI0D,OAAiB,IAAzCA;CAA0C;CACjD,OAEKtG,YACLiG,YACIvF,iBAAiB;EAAA6F,SACNH;EAAYI,mBACF;EAAIZ;EAAA9D;EAAAC;CAIzB,CAUC,IATDtB,mBAAmB;EAAAmF;EAAAa,WAEPC,SAAA;GACHtD,MAAKG,IACHX,IACA,CAAC,EAAAR,KAAK+B,KACN,CAAC,CAAAC,MAACuC,MAAQ;GACjBvD,MAAKwD,OAAQhE,IAAE;EAAC;CAEpB,CAAC,CACP;AAAC;;;;;;;;;;;;;;AAgBH,MAAaiE,eAAe9G,SAAS+F,eAAe;AAEpDhF,sBAAsBgF,iBAAiBnF,iCAAiC;AAvI7C,SAAA0D,QAAA,CAAA;AAoEH,SAAA2B,SAAA;CAAA,uBAIS,IAAI3C,IAAmC;AAAC;AAJjD,SAAA8C,SAAA,CAAA;AAAA,SAAAQ,SAAA,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { SdkIdentity } from "assistant-cloud";
2
+ //#region src/runtime/sdkIdentity.d.ts
3
+ declare const AI_SDK_SDK: SdkIdentity;
4
+ //#endregion
5
+ export { AI_SDK_SDK };
6
+ //# sourceMappingURL=sdkIdentity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdkIdentity.d.ts","names":[],"sources":["../../src/runtime/sdkIdentity.ts"],"mappings":";;cAEa,YAAY"}
@@ -0,0 +1,9 @@
1
+ //#region src/runtime/sdkIdentity.ts
2
+ const AI_SDK_SDK = {
3
+ name: "@assistant-ui/ai-sdk",
4
+ version: "0.0.6"
5
+ };
6
+ //#endregion
7
+ export { AI_SDK_SDK };
8
+
9
+ //# sourceMappingURL=sdkIdentity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdkIdentity.js","names":["SdkIdentity","AI_SDK_SDK","name","version","__AUI_PACKAGE_VERSION__"],"sources":["../../src/runtime/sdkIdentity.ts"],"sourcesContent":["import type { SdkIdentity } from \"assistant-cloud\";\n\nexport const AI_SDK_SDK: SdkIdentity = {\n name: \"@assistant-ui/ai-sdk\",\n version:\n typeof __AUI_PACKAGE_VERSION__ === \"string\"\n ? __AUI_PACKAGE_VERSION__\n : \"0.0.0\",\n};\n"],"mappings":";AAEA,MAAaC,aAA0B;CACrCC,MAAM;CACNC,SAAAA;AAIF"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAISDKRuntime.d.ts","names":[],"sources":["../../src/runtime/useAISDKRuntime.ts"],"mappings":";;;;;KAkEY,iCACV,mBAAmB,YAAY,WAE/B,SAAS,kBACN,gBAAgB;KAYT,oBAAoB,mBAAmB,YAAY,aAC7D;EACE,YACK,YAAY;IACX,UAAU;IACV,aAAa;;EAGnB,kBAAkB;EAClB,qCAAqC;;;;;;;;;EASrC;;;;;;;;EAQA,WAAW;;;;;;;EAOX,mBAAmB;;;;;;;;;EASnB,eAAe;;;;;;EAMf,oBAAoB,wBAAwB;;;;;;;EAO5C,0BAA0B;;cAoFjB,kBAAmB,mBAAmB,YAAY,WAC7D,aAAa,kBAAkB,QAAQ,cACvC,UAAS,oBAAoB,gBAAgB"}
1
+ {"version":3,"file":"useAISDKRuntime.d.ts","names":[],"sources":["../../src/runtime/useAISDKRuntime.ts"],"mappings":";;;;;KAmEY,iCACV,mBAAmB,YAAY,WAE/B,SAAS,kBACN,gBAAgB;KAYT,oBAAoB,mBAAmB,YAAY,aAC7D;EACE,YACK,YAAY;IACX,UAAU;IACV,aAAa;;EAGnB,kBAAkB;EAClB,qCAAqC;;;;;;;;;EASrC;;;;;;;;EAQA,WAAW;;;;;;;EAOX,mBAAmB;;;;;;;;;EASnB,eAAe;;;;;;EAMf,oBAAoB,wBAAwB;;;;;;;EAO5C,0BAA0B;;cAiGjB,kBAAmB,mBAAmB,YAAY,WAC7D,aAAa,kBAAkB,QAAQ,cACvC,UAAS,oBAAoB,gBAAgB"}
@@ -129,6 +129,13 @@ const useGeneratedSuggestions = (suggestionAdapter, messages, isRunning) => {
129
129
  return suggestions;
130
130
  };
131
131
  const NO_CANCELLED_MESSAGE_IDS = /* @__PURE__ */ new Set();
132
+ const toChatError = (error) => {
133
+ const code = error.code;
134
+ return {
135
+ code: typeof code === "string" ? code : error.name !== "Error" ? error.name : "unknown",
136
+ message: error.message
137
+ };
138
+ };
132
139
  const useAISDKRuntime = (chatHelpers, adapter = {}) => {
133
140
  const { adapters, toCreateMessage: customToCreateMessage, cancelPendingToolCallsOnSend = true, onResume, onResumeToolCall, joinStrategy, messageRepository, unstable_onBranchChange } = adapter;
134
141
  const suggestionAdapter = adapters?.suggestion;
@@ -181,7 +188,7 @@ const useAISDKRuntime = (chatHelpers, adapter = {}) => {
181
188
  toolLastInputCache: toolLastInputCacheRef.current,
182
189
  mcpAppMetadataCache: mcpAppMetadataCacheRef.current,
183
190
  ...optimisticMessageId && { optimisticMessageId },
184
- ...chatHelpers.error && { error: chatHelpers.error.message },
191
+ ...chatHelpers.error && { error: toChatError(chatHelpers.error) },
185
192
  ...cancelledMessageIds.size > 0 && { cancelledMessageIds }
186
193
  }), [
187
194
  toolStatuses,