@assistant-ui/ai-sdk 0.0.10 → 0.0.12
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 +8 -6
- package/dist/converters/convertMessage.d.ts.map +1 -1
- package/dist/converters/convertMessage.js +106 -28
- package/dist/converters/convertMessage.js.map +1 -1
- package/dist/converters/toolApprovalAnswers.d.ts +3 -0
- package/dist/converters/toolApprovalAnswers.d.ts.map +1 -0
- package/dist/converters/toolApprovalAnswers.js +17 -0
- package/dist/converters/toolApprovalAnswers.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.native.d.ts +1 -1
- package/dist/index.native.d.ts.map +1 -1
- package/dist/index.native.js +1 -1
- package/dist/model-context/injectInteractableContext.d.ts +3 -0
- package/dist/model-context/injectInteractableContext.d.ts.map +1 -1
- package/dist/model-context/injectInteractableContext.js +3 -0
- package/dist/model-context/injectInteractableContext.js.map +1 -1
- package/dist/model-context/injectQuoteContext.d.ts +1 -0
- package/dist/model-context/injectQuoteContext.d.ts.map +1 -1
- package/dist/model-context/injectQuoteContext.js +1 -0
- package/dist/model-context/injectQuoteContext.js.map +1 -1
- package/dist/runtime/AISDKChat.js +1 -1
- package/dist/runtime/AISDKThreads.d.ts +5 -0
- package/dist/runtime/AISDKThreads.d.ts.map +1 -1
- package/dist/runtime/AISDKThreads.js +37 -4
- package/dist/runtime/AISDKThreads.js.map +1 -1
- package/dist/runtime/DynamicChatTransport.d.ts +49 -0
- package/dist/runtime/DynamicChatTransport.d.ts.map +1 -0
- package/dist/runtime/DynamicChatTransport.js +147 -0
- package/dist/runtime/DynamicChatTransport.js.map +1 -0
- package/dist/runtime/getResumableAdapter.d.ts +5 -0
- package/dist/runtime/getResumableAdapter.d.ts.map +1 -0
- package/dist/runtime/getResumableAdapter.js +12 -0
- package/dist/runtime/getResumableAdapter.js.map +1 -0
- package/dist/runtime/sdkIdentity.js +1 -1
- package/dist/runtime/toolHistoryCodec.d.ts +20 -0
- package/dist/runtime/toolHistoryCodec.d.ts.map +1 -0
- package/dist/runtime/toolHistoryCodec.js +107 -0
- package/dist/runtime/toolHistoryCodec.js.map +1 -0
- package/dist/runtime/useAISDKRuntime.d.ts +4 -1
- package/dist/runtime/useAISDKRuntime.d.ts.map +1 -1
- package/dist/runtime/useAISDKRuntime.js +154 -155
- package/dist/runtime/useAISDKRuntime.js.map +1 -1
- package/dist/runtime/useChatRuntime.d.ts +14 -2
- package/dist/runtime/useChatRuntime.d.ts.map +1 -1
- package/dist/runtime/useChatRuntime.js +12 -3
- package/dist/runtime/useChatRuntime.js.map +1 -1
- package/dist/runtime/useChatThread.d.ts +3 -2
- package/dist/runtime/useChatThread.d.ts.map +1 -1
- package/dist/runtime/useChatThread.js +56 -36
- package/dist/runtime/useChatThread.js.map +1 -1
- package/dist/runtime/useDynamicChatTransport.d.ts +4 -0
- package/dist/runtime/useDynamicChatTransport.d.ts.map +1 -0
- package/dist/runtime/useDynamicChatTransport.js +64 -0
- package/dist/runtime/useDynamicChatTransport.js.map +1 -0
- package/dist/runtime/useExternalHistory.d.ts.map +1 -1
- package/dist/runtime/useExternalHistory.js +11 -105
- package/dist/runtime/useExternalHistory.js.map +1 -1
- package/dist/runtime/useResourceCleanup.js +1 -1
- package/dist/runtime/useStreamingTiming.js +2 -2
- package/dist/runtime/useStreamingTiming.js.map +1 -1
- package/dist/tools/generativeTools.d.ts +2 -1
- package/dist/tools/generativeTools.d.ts.map +1 -1
- package/dist/tools/generativeTools.js +17 -6
- package/dist/tools/generativeTools.js.map +1 -1
- package/dist/usage.js +1 -1
- package/dist/utils/sliceMessagesUntil.d.ts.map +1 -1
- package/dist/utils/sliceMessagesUntil.js +1 -2
- package/dist/utils/sliceMessagesUntil.js.map +1 -1
- package/package.json +12 -10
- package/src/converters/convertMessage.test.ts +350 -2
- package/src/converters/convertMessage.tool-args-status.test.tsx +185 -0
- package/src/converters/convertMessage.ts +154 -23
- package/src/converters/toCreateMessage.test.ts +27 -0
- package/src/converters/toolApprovalAnswers.ts +27 -0
- package/src/index.native.ts +1 -1
- package/src/index.ts +1 -1
- package/src/model-context/injectInteractableContext.ts +3 -0
- package/src/model-context/injectQuoteContext.ts +1 -0
- package/src/runtime/AISDKChat.integration.test.tsx +57 -2
- package/src/runtime/AISDKThreads.cloud.test.ts +3 -0
- package/src/runtime/AISDKThreads.test.ts +181 -0
- package/src/runtime/AISDKThreads.ts +31 -4
- package/src/runtime/DynamicChatTransport.test.ts +203 -0
- package/src/runtime/DynamicChatTransport.ts +273 -0
- package/src/runtime/__tests__/controlled-transport.ts +3 -0
- package/src/runtime/getResumableAdapter.ts +16 -0
- package/src/runtime/toolHistoryCodec.test.ts +161 -0
- package/src/runtime/toolHistoryCodec.ts +207 -0
- package/src/runtime/useAISDKRuntime.approval.test.tsx +12 -0
- package/src/runtime/useAISDKRuntime.reload.test.tsx +219 -0
- package/src/runtime/useAISDKRuntime.test.ts +538 -5
- package/src/runtime/useAISDKRuntime.ts +161 -51
- package/src/runtime/useChatRuntime.integration.test.tsx +319 -4
- package/src/runtime/useChatRuntime.local-storage.test.tsx +123 -0
- package/src/runtime/useChatRuntime.test.ts +107 -1
- package/src/runtime/useChatRuntime.ts +26 -4
- package/src/runtime/useChatThread.binding.test.tsx +143 -0
- package/src/runtime/useChatThread.ts +98 -81
- package/src/runtime/useDynamicChatTransport.ts +26 -0
- package/src/runtime/useExternalHistory.test.ts +205 -0
- package/src/runtime/useExternalHistory.ts +14 -206
- package/src/runtime/useStreamingTiming.ts +2 -2
- package/src/tools/generativeTools.test.ts +190 -2
- package/src/tools/generativeTools.ts +28 -8
- package/src/utils/sliceMessagesUntil.test.ts +2 -6
- package/src/utils/sliceMessagesUntil.ts +1 -5
- package/dist/converters/modelContentEnvelope.d.ts +0 -14
- package/dist/converters/modelContentEnvelope.d.ts.map +0 -1
- package/dist/converters/modelContentEnvelope.js +0 -22
- package/dist/converters/modelContentEnvelope.js.map +0 -1
- package/dist/converters/toolOutputConversion.d.ts +0 -26
- package/dist/converters/toolOutputConversion.d.ts.map +0 -1
- package/dist/converters/toolOutputConversion.js +0 -31
- package/dist/converters/toolOutputConversion.js.map +0 -1
- package/dist/tools/frontendTools.d.ts +0 -30
- package/dist/tools/frontendTools.d.ts.map +0 -1
- package/dist/tools/frontendTools.js +0 -33
- package/dist/tools/frontendTools.js.map +0 -1
- package/src/converters/modelContentEnvelope.ts +0 -41
- package/src/converters/toolOutputConversion.ts +0 -26
- package/src/tools/frontendTools.test.ts +0 -205
- package/src/tools/frontendTools.ts +0 -83
|
@@ -15,6 +15,8 @@ import { unstable_formatInteractableSnapshot, unstable_getInteractableSnapshots
|
|
|
15
15
|
* `format` must also handle entries with `partial: true`, whose `state` carries
|
|
16
16
|
* only the fields that changed since the model's last known state.
|
|
17
17
|
*
|
|
18
|
+
* @deprecated Experimental since 2026-06-23. Not scheduled for removal; the API may change in any release.
|
|
19
|
+
*
|
|
18
20
|
* @example
|
|
19
21
|
* ```ts
|
|
20
22
|
* import { convertToModelMessages, streamText } from "ai";
|
|
@@ -23,6 +25,7 @@ import { unstable_formatInteractableSnapshot, unstable_getInteractableSnapshots
|
|
|
23
25
|
* export async function POST(req: Request) {
|
|
24
26
|
* const { messages } = await req.json();
|
|
25
27
|
* const result = streamText({
|
|
28
|
+
* abortSignal: req.signal,
|
|
26
29
|
* model: myModel,
|
|
27
30
|
* messages: await convertToModelMessages(unstable_injectInteractableContext(messages)),
|
|
28
31
|
* });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injectInteractableContext.js","names":["UIMessage","unstable_formatInteractableSnapshot","unstable_getInteractableSnapshots","Unstable_InteractableSnapshotEntry","unstable_injectInteractableContext","messages","format","item","map","msg","role","items","length","text","join","alreadyInjected","parts","type","const"],"sources":["../../src/model-context/injectInteractableContext.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\nimport {\n unstable_formatInteractableSnapshot,\n unstable_getInteractableSnapshots,\n type Unstable_InteractableSnapshotEntry,\n} from \"@assistant-ui/core\";\n\n/**\n * Injects interactable state snapshots into messages as model-visible text.\n *\n * Mirrors {@link injectQuoteContext}: reads the frozen snapshot stamped on a user\n * message's `metadata.custom.interactables` (by the interactables scope at send\n * time) and prepends a text part. Run this in your route handler before\n * `convertToModelMessages`, which otherwise ignores `metadata.custom`.\n *\n * Wording is consumer-owned — pass `format` to control how each snapshot reads.\n * A snapshot may originate from a user edit or an agent `update_*` call, so the\n * default phrasing is neutral. Keep the instance id visible in custom wording:\n * the model needs it to address the `update_*` tool's `id` parameter. A custom\n * `format` must also handle entries with `partial: true`, whose `state` carries\n * only the fields that changed since the model's last known state.\n *\n * @example\n * ```ts\n * import { convertToModelMessages, streamText } from \"ai\";\n * import { unstable_injectInteractableContext } from \"@assistant-ui/ai-sdk\";\n *\n * export async function POST(req: Request) {\n * const { messages } = await req.json();\n * const result = streamText({\n * model: myModel,\n * messages: await convertToModelMessages(unstable_injectInteractableContext(messages)),\n * });\n * return result.toUIMessageStreamResponse();\n * }\n * ```\n */\nexport function unstable_injectInteractableContext(\n messages: UIMessage[],\n format: (\n item: Unstable_InteractableSnapshotEntry,\n ) => string = unstable_formatInteractableSnapshot,\n): UIMessage[] {\n return messages.map((msg) => {\n if (msg.role !== \"user\") return msg;\n\n const items = unstable_getInteractableSnapshots(msg);\n if (!items?.length) return msg;\n\n const text = `${items.map(format).join(\"\\n\")}\\n\\n`;\n\n const alreadyInjected =\n msg.parts?.[0]?.type === \"text\" && msg.parts[0].text === text;\n if (alreadyInjected) return msg;\n\n return {\n ...msg,\n parts: [{ type: \"text\" as const, text }, ...(msg.parts ?? [])],\n };\n });\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"injectInteractableContext.js","names":["UIMessage","unstable_formatInteractableSnapshot","unstable_getInteractableSnapshots","Unstable_InteractableSnapshotEntry","unstable_injectInteractableContext","messages","format","item","map","msg","role","items","length","text","join","alreadyInjected","parts","type","const"],"sources":["../../src/model-context/injectInteractableContext.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\nimport {\n unstable_formatInteractableSnapshot,\n unstable_getInteractableSnapshots,\n type Unstable_InteractableSnapshotEntry,\n} from \"@assistant-ui/core\";\n\n/**\n * Injects interactable state snapshots into messages as model-visible text.\n *\n * Mirrors {@link injectQuoteContext}: reads the frozen snapshot stamped on a user\n * message's `metadata.custom.interactables` (by the interactables scope at send\n * time) and prepends a text part. Run this in your route handler before\n * `convertToModelMessages`, which otherwise ignores `metadata.custom`.\n *\n * Wording is consumer-owned — pass `format` to control how each snapshot reads.\n * A snapshot may originate from a user edit or an agent `update_*` call, so the\n * default phrasing is neutral. Keep the instance id visible in custom wording:\n * the model needs it to address the `update_*` tool's `id` parameter. A custom\n * `format` must also handle entries with `partial: true`, whose `state` carries\n * only the fields that changed since the model's last known state.\n *\n * @deprecated Experimental since 2026-06-23. Not scheduled for removal; the API may change in any release.\n *\n * @example\n * ```ts\n * import { convertToModelMessages, streamText } from \"ai\";\n * import { unstable_injectInteractableContext } from \"@assistant-ui/ai-sdk\";\n *\n * export async function POST(req: Request) {\n * const { messages } = await req.json();\n * const result = streamText({\n * abortSignal: req.signal,\n * model: myModel,\n * messages: await convertToModelMessages(unstable_injectInteractableContext(messages)),\n * });\n * return result.toUIMessageStreamResponse();\n * }\n * ```\n */\nexport function unstable_injectInteractableContext(\n messages: UIMessage[],\n format: (\n item: Unstable_InteractableSnapshotEntry,\n ) => string = unstable_formatInteractableSnapshot,\n): UIMessage[] {\n return messages.map((msg) => {\n if (msg.role !== \"user\") return msg;\n\n const items = unstable_getInteractableSnapshots(msg);\n if (!items?.length) return msg;\n\n const text = `${items.map(format).join(\"\\n\")}\\n\\n`;\n\n const alreadyInjected =\n msg.parts?.[0]?.type === \"text\" && msg.parts[0].text === text;\n if (alreadyInjected) return msg;\n\n return {\n ...msg,\n parts: [{ type: \"text\" as const, text }, ...(msg.parts ?? [])],\n };\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgBI,mCACdC,UACAC,SAEcL,qCACD;CACb,OAAOI,SAASG,KAAKC,QAAQ;EAC3B,IAAIA,IAAIC,SAAS,QAAQ,OAAOD;EAEhC,MAAME,QAAQT,kCAAkCO,GAAG;EACnD,IAAI,CAACE,OAAOC,QAAQ,OAAOH;EAE3B,MAAMI,OAAO,GAAGF,MAAMH,IAAIF,MAAM,CAAC,CAACQ,KAAK,IAAI,EAAC;EAI5C,IADEL,IAAIO,QAAQ,EAAE,EAAEC,SAAS,UAAUR,IAAIO,MAAM,EAAE,CAACH,SAASA,MACtC,OAAOJ;EAE5B,OAAO;GACL,GAAGA;GACHO,OAAO,CAAC;IAAEC,MAAM;IAAiBJ;GAAK,GAAG,GAAIJ,IAAIO,SAAS,CAAA,CAAG;EAC/D;CACF,CAAC;AACH"}
|
|
@@ -13,6 +13,7 @@ import type { UIMessage } from "ai";
|
|
|
13
13
|
* export async function POST(req: Request) {
|
|
14
14
|
* const { messages } = await req.json();
|
|
15
15
|
* const result = streamText({
|
|
16
|
+
* abortSignal: req.signal,
|
|
16
17
|
* model: myModel,
|
|
17
18
|
* messages: await convertToModelMessages(injectQuoteContext(messages)),
|
|
18
19
|
* });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injectQuoteContext.d.ts","sourceRoot":"","sources":["../../src/model-context/injectQuoteContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAepC
|
|
1
|
+
{"version":3,"file":"injectQuoteContext.d.ts","sourceRoot":"","sources":["../../src/model-context/injectQuoteContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAepC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAyBrE"}
|
|
@@ -22,6 +22,7 @@ const getQuoteText = (metadata) => {
|
|
|
22
22
|
* export async function POST(req: Request) {
|
|
23
23
|
* const { messages } = await req.json();
|
|
24
24
|
* const result = streamText({
|
|
25
|
+
* abortSignal: req.signal,
|
|
25
26
|
* model: myModel,
|
|
26
27
|
* messages: await convertToModelMessages(injectQuoteContext(messages)),
|
|
27
28
|
* });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injectQuoteContext.js","names":["UIMessage","getQuoteText","metadata","undefined","custom","Record","quote","text","injectQuoteContext","messages","map","msg","role","blockquote","split","line","join","alreadyInjected","parts","type","const"],"sources":["../../src/model-context/injectQuoteContext.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\n\nconst getQuoteText = (metadata: unknown): string | undefined => {\n if (!metadata || typeof metadata !== \"object\") return undefined;\n\n const custom = (metadata as Record<string, unknown>).custom;\n if (!custom || typeof custom !== \"object\") return undefined;\n\n const quote = (custom as Record<string, unknown>).quote;\n if (!quote || typeof quote !== \"object\") return undefined;\n\n const text = (quote as Record<string, unknown>).text;\n return typeof text === \"string\" ? text : undefined;\n};\n\n/**\n * Injects quote context into messages as markdown blockquotes.\n *\n * Use this in your route handler before `convertToModelMessages` so the LLM\n * sees the quoted text that the user is referring to.\n *\n * @example\n * ```ts\n * import { convertToModelMessages, streamText } from \"ai\";\n * import { injectQuoteContext } from \"@assistant-ui/ai-sdk\";\n *\n * export async function POST(req: Request) {\n * const { messages } = await req.json();\n * const result = streamText({\n * model: myModel,\n * messages: await convertToModelMessages(injectQuoteContext(messages)),\n * });\n * return result.toUIMessageStreamResponse();\n * }\n * ```\n */\nexport function injectQuoteContext(messages: UIMessage[]): UIMessage[] {\n return messages.map((msg) => {\n if (msg.role !== \"user\") return msg;\n\n const text = getQuoteText(msg.metadata);\n if (!text) return msg;\n\n const blockquote = text\n .split(/\\r?\\n/)\n .map((line) => `> ${line}`)\n .join(\"\\n\");\n\n const alreadyInjected =\n msg.parts?.[0]?.type === \"text\" &&\n msg.parts[0].text === `${blockquote}\\n\\n`;\n if (alreadyInjected) return msg;\n\n return {\n ...msg,\n parts: [\n { type: \"text\" as const, text: `${blockquote}\\n\\n` },\n ...(msg.parts ?? []),\n ],\n };\n });\n}\n"],"mappings":";AAEA,MAAMC,gBAAgBC,aAA0C;CAC9D,IAAI,CAACA,YAAY,OAAOA,aAAa,UAAU,OAAOC,KAAAA;CAEtD,MAAMC,SAAUF,SAAqCE;CACrD,IAAI,CAACA,UAAU,OAAOA,WAAW,UAAU,OAAOD,KAAAA;CAElD,MAAMG,QAASF,OAAmCE;CAClD,IAAI,CAACA,SAAS,OAAOA,UAAU,UAAU,OAAOH,KAAAA;CAEhD,MAAMI,OAAQD,MAAkCC;CAChD,OAAO,OAAOA,SAAS,WAAWA,OAAOJ,KAAAA;AAC3C
|
|
1
|
+
{"version":3,"file":"injectQuoteContext.js","names":["UIMessage","getQuoteText","metadata","undefined","custom","Record","quote","text","injectQuoteContext","messages","map","msg","role","blockquote","split","line","join","alreadyInjected","parts","type","const"],"sources":["../../src/model-context/injectQuoteContext.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\n\nconst getQuoteText = (metadata: unknown): string | undefined => {\n if (!metadata || typeof metadata !== \"object\") return undefined;\n\n const custom = (metadata as Record<string, unknown>).custom;\n if (!custom || typeof custom !== \"object\") return undefined;\n\n const quote = (custom as Record<string, unknown>).quote;\n if (!quote || typeof quote !== \"object\") return undefined;\n\n const text = (quote as Record<string, unknown>).text;\n return typeof text === \"string\" ? text : undefined;\n};\n\n/**\n * Injects quote context into messages as markdown blockquotes.\n *\n * Use this in your route handler before `convertToModelMessages` so the LLM\n * sees the quoted text that the user is referring to.\n *\n * @example\n * ```ts\n * import { convertToModelMessages, streamText } from \"ai\";\n * import { injectQuoteContext } from \"@assistant-ui/ai-sdk\";\n *\n * export async function POST(req: Request) {\n * const { messages } = await req.json();\n * const result = streamText({\n * abortSignal: req.signal,\n * model: myModel,\n * messages: await convertToModelMessages(injectQuoteContext(messages)),\n * });\n * return result.toUIMessageStreamResponse();\n * }\n * ```\n */\nexport function injectQuoteContext(messages: UIMessage[]): UIMessage[] {\n return messages.map((msg) => {\n if (msg.role !== \"user\") return msg;\n\n const text = getQuoteText(msg.metadata);\n if (!text) return msg;\n\n const blockquote = text\n .split(/\\r?\\n/)\n .map((line) => `> ${line}`)\n .join(\"\\n\");\n\n const alreadyInjected =\n msg.parts?.[0]?.type === \"text\" &&\n msg.parts[0].text === `${blockquote}\\n\\n`;\n if (alreadyInjected) return msg;\n\n return {\n ...msg,\n parts: [\n { type: \"text\" as const, text: `${blockquote}\\n\\n` },\n ...(msg.parts ?? []),\n ],\n };\n });\n}\n"],"mappings":";AAEA,MAAMC,gBAAgBC,aAA0C;CAC9D,IAAI,CAACA,YAAY,OAAOA,aAAa,UAAU,OAAOC,KAAAA;CAEtD,MAAMC,SAAUF,SAAqCE;CACrD,IAAI,CAACA,UAAU,OAAOA,WAAW,UAAU,OAAOD,KAAAA;CAElD,MAAMG,QAASF,OAAmCE;CAClD,IAAI,CAACA,SAAS,OAAOA,UAAU,UAAU,OAAOH,KAAAA;CAEhD,MAAMI,OAAQD,MAAkCC;CAChD,OAAO,OAAOA,SAAS,WAAWA,OAAOJ,KAAAA;AAC3C;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgBK,mBAAmBC,UAAoC;CACrE,OAAOA,SAASC,KAAKC,QAAQ;EAC3B,IAAIA,IAAIC,SAAS,QAAQ,OAAOD;EAEhC,MAAMJ,OAAON,aAAaU,IAAIT,QAAQ;EACtC,IAAI,CAACK,MAAM,OAAOI;EAElB,MAAME,aAAaN,KAChBO,MAAM,OAAO,CAAC,CACdJ,KAAKK,SAAS,KAAKA,MAAM,CAAC,CAC1BC,KAAK,IAAI;EAKZ,IAFEL,IAAIO,QAAQ,EAAE,EAAEC,SAAS,UACzBR,IAAIO,MAAM,EAAE,CAACX,SAAS,GAAGM,WAAU,OAChB,OAAOF;EAE5B,OAAO;GACL,GAAGA;GACHO,OAAO,CACL;IAAEC,MAAM;IAAiBZ,MAAM,GAAGM,WAAU;GAAO,GACnD,GAAIF,IAAIO,SAAS,CAAA,CAAG;EAExB;CACF,CAAC;AACH"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useChatThread } from "./useChatThread.js";
|
|
3
3
|
import { generateId } from "ai";
|
|
4
|
-
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
5
4
|
import { useState } from "@assistant-ui/tap/react-shim";
|
|
5
|
+
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
6
6
|
import { resource, useResource } from "@assistant-ui/tap";
|
|
7
7
|
import { RuntimeAdapter, runtimeAdapterTransformScopes } from "@assistant-ui/core/store";
|
|
8
8
|
import { attachTransformScopes } from "@assistant-ui/store/client";
|
|
@@ -18,6 +18,11 @@ export type AISDKThreadsOptions<UI_MESSAGE extends UIMessage = UIMessage> = Omit
|
|
|
18
18
|
* switch and stops on delete; per-thread history loads once per thread.
|
|
19
19
|
*/
|
|
20
20
|
cloud?: AssistantCloud | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Stable identity for the account or workspace owning Cloud runtime state.
|
|
23
|
+
* Provide it from the first render and change it when that scope changes.
|
|
24
|
+
*/
|
|
25
|
+
scopeId?: string | undefined;
|
|
21
26
|
/**
|
|
22
27
|
* Controlled thread id for the cloud list. Ignored without `cloud`.
|
|
23
28
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AISDKThreads.d.ts","sourceRoot":"","sources":["../../src/runtime/AISDKThreads.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAQ,SAAS,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAetD,OAAO,EAIL,KAAK,iBAAiB,EACvB,2BAAwB;AAKzB,MAAM,MAAM,mBAAmB,CAAC,UAAU,SAAS,SAAS,GAAG,SAAS,IACtE,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,UAAU,CAAC,GAAG;IACrE;;;;;;OAMG;IACH,SAAS,CAAC,EACN,aAAa,CAAC,UAAU,CAAC,GACzB,CAAC,MAAM,aAAa,CAAC,UAAU,CAAC,CAAC,GACjC,SAAS,CAAC;IACd;;;;;OAKG;IACH,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACnC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACzE,CAAC;
|
|
1
|
+
{"version":3,"file":"AISDKThreads.d.ts","sourceRoot":"","sources":["../../src/runtime/AISDKThreads.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAQ,SAAS,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAetD,OAAO,EAIL,KAAK,iBAAiB,EACvB,2BAAwB;AAKzB,MAAM,MAAM,mBAAmB,CAAC,UAAU,SAAS,SAAS,GAAG,SAAS,IACtE,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,UAAU,CAAC,GAAG;IACrE;;;;;;OAMG;IACH,SAAS,CAAC,EACN,aAAa,CAAC,UAAU,CAAC,GACzB,CAAC,MAAM,aAAa,CAAC,UAAU,CAAC,CAAC,GACjC,SAAS,CAAC;IACd;;;;;OAKG;IACH,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACzE,CAAC;AAoMJ;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,GAvFA,UAAU,SAAS,SAAS,mOAuFA,CAAC"}
|
|
@@ -5,9 +5,9 @@ import { createChat, splitChatThreadOptions, useChatThread } from "./useChatThre
|
|
|
5
5
|
import { AI_SDK_SDK } from "./sdkIdentity.js";
|
|
6
6
|
import { MessageRepository } from "@assistant-ui/core/internal";
|
|
7
7
|
import { useCloudThreadListAdapter } from "@assistant-ui/core/react";
|
|
8
|
-
import {
|
|
9
|
-
import { useEffect, useState } from "@assistant-ui/tap/react-shim";
|
|
8
|
+
import { useEffect, useRef, useState } from "@assistant-ui/tap/react-shim";
|
|
10
9
|
import { useAui } from "@assistant-ui/store";
|
|
10
|
+
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
11
11
|
import { resource, useResource, withKey } from "@assistant-ui/tap";
|
|
12
12
|
import { InMemoryThreadList, RemoteThreadList, inMemoryThreadListTransformScopes } from "@assistant-ui/core/store";
|
|
13
13
|
import { attachTransformScopes, useAssistantClientRef, useAssistantScopeEffect } from "@assistant-ui/store/client";
|
|
@@ -158,8 +158,8 @@ const useAISDKChatThread = (t0) => {
|
|
|
158
158
|
};
|
|
159
159
|
const AISDKChatThread = resource(useAISDKChatThread);
|
|
160
160
|
const useAISDKThreads = (options) => {
|
|
161
|
-
const $ = c(
|
|
162
|
-
const { cloud, threadId, onThreadIdChange, ...threadOptions } = options ?? {};
|
|
161
|
+
const $ = c(7);
|
|
162
|
+
const { cloud, scopeId, threadId, onThreadIdChange, ...threadOptions } = options ?? {};
|
|
163
163
|
const [chats] = useState(_temp2);
|
|
164
164
|
const bindCloud = cloud !== void 0;
|
|
165
165
|
useEffect(() => {
|
|
@@ -176,8 +176,41 @@ const useAISDKThreads = (options) => {
|
|
|
176
176
|
useResourceCleanup(true, t0);
|
|
177
177
|
const cloudAdapter = useCloudThreadListAdapter({
|
|
178
178
|
cloud,
|
|
179
|
+
scopeId,
|
|
179
180
|
sdk: AI_SDK_SDK
|
|
180
181
|
});
|
|
182
|
+
const clientRef = useAssistantClientRef();
|
|
183
|
+
const previousCloudAdapter = useRef(bindCloud ? cloudAdapter : void 0);
|
|
184
|
+
let t1;
|
|
185
|
+
let t2;
|
|
186
|
+
if ($[2] !== bindCloud || $[3] !== clientRef || $[4] !== cloudAdapter) {
|
|
187
|
+
t1 = () => {
|
|
188
|
+
const previous = previousCloudAdapter.current;
|
|
189
|
+
previousCloudAdapter.current = bindCloud ? cloudAdapter : void 0;
|
|
190
|
+
if (!bindCloud || previous === void 0 || previous === cloudAdapter) return;
|
|
191
|
+
let cancelled = false;
|
|
192
|
+
queueMicrotask(() => {
|
|
193
|
+
if (!cancelled) clientRef.current.threads.reload();
|
|
194
|
+
});
|
|
195
|
+
return () => {
|
|
196
|
+
cancelled = true;
|
|
197
|
+
};
|
|
198
|
+
};
|
|
199
|
+
t2 = [
|
|
200
|
+
bindCloud,
|
|
201
|
+
clientRef,
|
|
202
|
+
cloudAdapter
|
|
203
|
+
];
|
|
204
|
+
$[2] = bindCloud;
|
|
205
|
+
$[3] = clientRef;
|
|
206
|
+
$[4] = cloudAdapter;
|
|
207
|
+
$[5] = t1;
|
|
208
|
+
$[6] = t2;
|
|
209
|
+
} else {
|
|
210
|
+
t1 = $[5];
|
|
211
|
+
t2 = $[6];
|
|
212
|
+
}
|
|
213
|
+
useEffect(t1, t2);
|
|
181
214
|
const thread = (id) => {
|
|
182
215
|
const element = AISDKChatThread({
|
|
183
216
|
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","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
|
+
{"version":3,"file":"AISDKThreads.js","names":["c","_c","resource","useResource","withKey","useEffect","useMemo","useRef","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","scopeId","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","previousCloudAdapter","previous","cancelled","queueMicrotask","threads","reload","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, useRef, 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 * Stable identity for the account or workspace owning Cloud runtime state.\n * Provide it from the first render and change it when that scope changes.\n */\n scopeId?: string | 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\" | \"scopeId\" | \"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, scopeId, threadId, onThreadIdChange, ...threadOptions } =\n 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({\n cloud,\n scopeId,\n sdk: AI_SDK_SDK,\n });\n const clientRef = useAssistantClientRef();\n const previousCloudAdapter = useRef(bindCloud ? cloudAdapter : undefined);\n useEffect(() => {\n const previous = previousCloudAdapter.current;\n previousCloudAdapter.current = bindCloud ? cloudAdapter : undefined;\n if (!bindCloud || previous === undefined || previous === cloudAdapter)\n return;\n // Wait until RemoteThreadList commits the replacement adapter before\n // requesting its explicit reload.\n let cancelled = false;\n queueMicrotask(() => {\n if (!cancelled) void clientRef.current!.threads.reload();\n });\n return () => {\n cancelled = true;\n };\n }, [bindCloud, clientRef, cloudAdapter]);\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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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { AssistantRuntime } from "@assistant-ui/core";
|
|
2
|
+
import type { UIMessage } from "@ai-sdk/react";
|
|
3
|
+
import type { ChatTransport } from "ai";
|
|
4
|
+
import { type InitializableThreadListItem } from "../transport/AssistantChatTransport.js";
|
|
5
|
+
import type { ResumableClientStorage } from "../transport/resumable.js";
|
|
6
|
+
export declare const getResumedStreamIds: (storage: ResumableClientStorage | undefined) => Set<string>;
|
|
7
|
+
declare class DynamicResumableStorage implements ResumableClientStorage {
|
|
8
|
+
private readonly subscriptions;
|
|
9
|
+
private storage;
|
|
10
|
+
private resumedStreamIds;
|
|
11
|
+
private hasPendingNotification;
|
|
12
|
+
constructor(storage: ResumableClientStorage | undefined);
|
|
13
|
+
setStorage(storage: ResumableClientStorage | undefined): void;
|
|
14
|
+
flushChange(): void;
|
|
15
|
+
getResumedStreamIds(): Set<string>;
|
|
16
|
+
getStreamId(threadId?: string): string | null;
|
|
17
|
+
setStreamId(id: string, threadId?: string): void;
|
|
18
|
+
clear(threadId?: string): void;
|
|
19
|
+
subscribe(listener: () => void, threadId?: string): () => void;
|
|
20
|
+
}
|
|
21
|
+
type ThreadTransportBinding = {
|
|
22
|
+
runtime: AssistantRuntime;
|
|
23
|
+
getThreadListItem: () => InitializableThreadListItem | undefined;
|
|
24
|
+
};
|
|
25
|
+
export declare class DynamicChatTransport<UI_MESSAGE extends UIMessage> implements ChatTransport<UI_MESSAGE> {
|
|
26
|
+
private readonly threadContexts;
|
|
27
|
+
private transport;
|
|
28
|
+
private readonly resumableStorage;
|
|
29
|
+
constructor(transport: ChatTransport<UI_MESSAGE>);
|
|
30
|
+
readonly sendMessages: ChatTransport<UI_MESSAGE>["sendMessages"];
|
|
31
|
+
readonly reconnectToStream: ChatTransport<UI_MESSAGE>["reconnectToStream"];
|
|
32
|
+
readonly getCurrentTransport: (chatId: string) => ChatTransport<UI_MESSAGE>;
|
|
33
|
+
readonly getCurrentResumableStorage: () => DynamicResumableStorage;
|
|
34
|
+
readonly getResumedStreamIds: () => Set<string>;
|
|
35
|
+
createThreadProxy(owner: object, getBinding: () => ThreadTransportBinding): ChatTransport<UI_MESSAGE>;
|
|
36
|
+
setTransport(transport: ChatTransport<UI_MESSAGE>): void;
|
|
37
|
+
flushTransportChange(): void;
|
|
38
|
+
registerThread(chatId: string, owner: object): void;
|
|
39
|
+
setThreadContext(chatId: string, owner: object, runtime: AssistantRuntime, getThreadListItem: () => InitializableThreadListItem | undefined): void;
|
|
40
|
+
unregisterThread(chatId: string, owner: object): void;
|
|
41
|
+
private getTransport;
|
|
42
|
+
private getBoundTransport;
|
|
43
|
+
private getOrCreateBoundTransport;
|
|
44
|
+
private getThreadTransport;
|
|
45
|
+
private createThreadTransport;
|
|
46
|
+
private wireTransport;
|
|
47
|
+
}
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=DynamicChatTransport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DynamicChatTransport.d.ts","sourceRoot":"","sources":["../../src/runtime/DynamicChatTransport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAEL,KAAK,2BAA2B,EACjC,+CAA4C;AAC7C,OAAO,KAAK,EAAE,sBAAsB,EAAE,kCAA+B;AAQrE,eAAO,MAAM,mBAAmB,GAC9B,SAAS,sBAAsB,GAAG,SAAS,gBAS5C,CAAC;AAQF,cAAM,uBAAwB,YAAW,sBAAsB;IAC7D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA2C;IACzE,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,gBAAgB,CAAc;IACtC,OAAO,CAAC,sBAAsB,CAAS;gBAE3B,OAAO,EAAE,sBAAsB,GAAG,SAAS;IAKhD,UAAU,CAAC,OAAO,EAAE,sBAAsB,GAAG,SAAS;IAWtD,WAAW;IAaX,mBAAmB;IAInB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM;IAI7B,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAIzC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM;IAIvB,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM;CAYzD;AAYD,KAAK,sBAAsB,GAAG;IAC5B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,iBAAiB,EAAE,MAAM,2BAA2B,GAAG,SAAS,CAAC;CAClE,CAAC;AAEF,qBAAa,oBAAoB,CAC/B,UAAU,SAAS,SAAS,CAC5B,YAAW,aAAa,CAAC,UAAU,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAG3B;IACJ,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;gBAE/C,SAAS,EAAE,aAAa,CAAC,UAAU,CAAC;IAOhD,SAAgB,YAAY,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC,cAAc,CAAC,CAEV;IAE7D,SAAgB,iBAAiB,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC,mBAAmB,CAAC,CACL;IAE5E,SAAgB,mBAAmB,GAAI,QAAQ,MAAM,+BACwB;IAE7E,SAAgB,0BAA0B,gCAA+B;IAEzE,SAAgB,mBAAmB,oBACW;IAEvC,iBAAiB,CACtB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,sBAAsB,GACvC,aAAa,CAAC,UAAU,CAAC;IAiBrB,YAAY,CAAC,SAAS,EAAE,aAAa,CAAC,UAAU,CAAC;IAMjD,oBAAoB;IAIpB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAQ5C,gBAAgB,CACrB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,gBAAgB,EACzB,iBAAiB,EAAE,MAAM,2BAA2B,GAAG,SAAS;IAkB3D,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAMrD,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,yBAAyB;IAWjC,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,qBAAqB;IAM7B,OAAO,CAAC,aAAa;CAUtB"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { AssistantChatTransport } from "../transport/AssistantChatTransport.js";
|
|
2
|
+
import { getResumableAdapter } from "./getResumableAdapter.js";
|
|
3
|
+
//#region src/runtime/DynamicChatTransport.ts
|
|
4
|
+
const resumedStreamIdsByStorage = /* @__PURE__ */ new WeakMap();
|
|
5
|
+
const getResumedStreamIds = (storage) => {
|
|
6
|
+
if (!storage) return /* @__PURE__ */ new Set();
|
|
7
|
+
let resumedStreamIds = resumedStreamIdsByStorage.get(storage);
|
|
8
|
+
if (!resumedStreamIds) {
|
|
9
|
+
resumedStreamIds = /* @__PURE__ */ new Set();
|
|
10
|
+
resumedStreamIdsByStorage.set(storage, resumedStreamIds);
|
|
11
|
+
}
|
|
12
|
+
return resumedStreamIds;
|
|
13
|
+
};
|
|
14
|
+
var DynamicResumableStorage = class {
|
|
15
|
+
subscriptions = /* @__PURE__ */ new Set();
|
|
16
|
+
storage;
|
|
17
|
+
resumedStreamIds;
|
|
18
|
+
hasPendingNotification = false;
|
|
19
|
+
constructor(storage) {
|
|
20
|
+
this.storage = storage;
|
|
21
|
+
this.resumedStreamIds = getResumedStreamIds(storage);
|
|
22
|
+
}
|
|
23
|
+
setStorage(storage) {
|
|
24
|
+
if (this.storage === storage) return;
|
|
25
|
+
this.storage = storage;
|
|
26
|
+
const nextResumedStreamIds = getResumedStreamIds(storage);
|
|
27
|
+
for (const streamId of this.resumedStreamIds) nextResumedStreamIds.add(streamId);
|
|
28
|
+
this.resumedStreamIds = nextResumedStreamIds;
|
|
29
|
+
this.hasPendingNotification = true;
|
|
30
|
+
}
|
|
31
|
+
flushChange() {
|
|
32
|
+
if (!this.hasPendingNotification) return;
|
|
33
|
+
this.hasPendingNotification = false;
|
|
34
|
+
for (const subscription of this.subscriptions) {
|
|
35
|
+
subscription.unsubscribe?.();
|
|
36
|
+
subscription.unsubscribe = this.storage?.subscribe?.(subscription.listener, subscription.threadId);
|
|
37
|
+
subscription.listener();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
getResumedStreamIds() {
|
|
41
|
+
return this.resumedStreamIds;
|
|
42
|
+
}
|
|
43
|
+
getStreamId(threadId) {
|
|
44
|
+
return this.storage?.getStreamId(threadId) ?? null;
|
|
45
|
+
}
|
|
46
|
+
setStreamId(id, threadId) {
|
|
47
|
+
this.storage?.setStreamId(id, threadId);
|
|
48
|
+
}
|
|
49
|
+
clear(threadId) {
|
|
50
|
+
this.storage?.clear(threadId);
|
|
51
|
+
}
|
|
52
|
+
subscribe(listener, threadId) {
|
|
53
|
+
const subscription = {
|
|
54
|
+
listener,
|
|
55
|
+
threadId,
|
|
56
|
+
unsubscribe: this.storage?.subscribe?.(listener, threadId)
|
|
57
|
+
};
|
|
58
|
+
this.subscriptions.add(subscription);
|
|
59
|
+
return () => {
|
|
60
|
+
this.subscriptions.delete(subscription);
|
|
61
|
+
subscription.unsubscribe?.();
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var DynamicChatTransport = class {
|
|
66
|
+
threadContexts = /* @__PURE__ */ new Map();
|
|
67
|
+
transport;
|
|
68
|
+
resumableStorage;
|
|
69
|
+
constructor(transport) {
|
|
70
|
+
this.transport = transport;
|
|
71
|
+
this.resumableStorage = new DynamicResumableStorage(getResumableAdapter(transport)?.storage);
|
|
72
|
+
}
|
|
73
|
+
sendMessages = (options) => this.getTransport(options.chatId).sendMessages(options);
|
|
74
|
+
reconnectToStream = (options) => this.getTransport(options.chatId).reconnectToStream(options);
|
|
75
|
+
getCurrentTransport = (chatId) => this.getThreadTransport(this.threadContexts.get(chatId)) ?? this.transport;
|
|
76
|
+
getCurrentResumableStorage = () => this.resumableStorage;
|
|
77
|
+
getResumedStreamIds = () => this.resumableStorage.getResumedStreamIds();
|
|
78
|
+
createThreadProxy(owner, getBinding) {
|
|
79
|
+
return {
|
|
80
|
+
sendMessages: (options) => this.getOrCreateBoundTransport(options.chatId, owner, getBinding).sendMessages(options),
|
|
81
|
+
reconnectToStream: (options) => this.getOrCreateBoundTransport(options.chatId, owner, getBinding).reconnectToStream(options)
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
setTransport(transport) {
|
|
85
|
+
if (this.transport === transport) return;
|
|
86
|
+
this.transport = transport;
|
|
87
|
+
this.resumableStorage.setStorage(getResumableAdapter(transport)?.storage);
|
|
88
|
+
}
|
|
89
|
+
flushTransportChange() {
|
|
90
|
+
this.resumableStorage.flushChange();
|
|
91
|
+
}
|
|
92
|
+
registerThread(chatId, owner) {
|
|
93
|
+
if (this.threadContexts.get(chatId)?.owner === owner) return;
|
|
94
|
+
this.threadContexts.set(chatId, { owner });
|
|
95
|
+
}
|
|
96
|
+
setThreadContext(chatId, owner, runtime, getThreadListItem) {
|
|
97
|
+
this.registerThread(chatId, owner);
|
|
98
|
+
const context = this.threadContexts.get(chatId);
|
|
99
|
+
context.runtime = runtime;
|
|
100
|
+
context.getThreadListItem = getThreadListItem;
|
|
101
|
+
if (context.transport === void 0) {
|
|
102
|
+
this.getThreadTransport(context);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (context.sourceTransport === this.transport && context.transport !== void 0) this.wireTransport(context, context.transport);
|
|
106
|
+
}
|
|
107
|
+
unregisterThread(chatId, owner) {
|
|
108
|
+
if (this.threadContexts.get(chatId)?.owner === owner) this.threadContexts.delete(chatId);
|
|
109
|
+
}
|
|
110
|
+
getTransport(chatId) {
|
|
111
|
+
const context = this.threadContexts.get(chatId);
|
|
112
|
+
if (!context) throw new Error(`DynamicChatTransport has no registered context for chat "${chatId}"`);
|
|
113
|
+
return this.getThreadTransport(context);
|
|
114
|
+
}
|
|
115
|
+
getBoundTransport(chatId, owner, binding) {
|
|
116
|
+
this.registerThread(chatId, owner);
|
|
117
|
+
const context = this.threadContexts.get(chatId);
|
|
118
|
+
context.runtime = binding.runtime;
|
|
119
|
+
context.getThreadListItem = binding.getThreadListItem;
|
|
120
|
+
return this.getThreadTransport(context);
|
|
121
|
+
}
|
|
122
|
+
getOrCreateBoundTransport(chatId, owner, getBinding) {
|
|
123
|
+
const context = this.threadContexts.get(chatId);
|
|
124
|
+
return context?.owner === owner ? this.getThreadTransport(context) : this.getBoundTransport(chatId, owner, getBinding());
|
|
125
|
+
}
|
|
126
|
+
getThreadTransport(context) {
|
|
127
|
+
if (!context) return void 0;
|
|
128
|
+
if (context.sourceTransport !== this.transport) {
|
|
129
|
+
context.transport = this.createThreadTransport(this.transport);
|
|
130
|
+
context.sourceTransport = this.transport;
|
|
131
|
+
}
|
|
132
|
+
this.wireTransport(context, context.transport);
|
|
133
|
+
return context.transport;
|
|
134
|
+
}
|
|
135
|
+
createThreadTransport(transport) {
|
|
136
|
+
return transport instanceof AssistantChatTransport ? transport.__internal_clone() : transport;
|
|
137
|
+
}
|
|
138
|
+
wireTransport(context, transport) {
|
|
139
|
+
if (!(transport instanceof AssistantChatTransport)) return;
|
|
140
|
+
if (context.runtime) transport.setRuntime(context.runtime);
|
|
141
|
+
if (context.getThreadListItem) transport.__internal_setGetThreadListItem(context.getThreadListItem);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
//#endregion
|
|
145
|
+
export { DynamicChatTransport, getResumedStreamIds };
|
|
146
|
+
|
|
147
|
+
//# sourceMappingURL=DynamicChatTransport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DynamicChatTransport.js","names":["AssistantRuntime","UIMessage","ChatTransport","AssistantChatTransport","InitializableThreadListItem","ResumableClientStorage","getResumableAdapter","resumedStreamIdsByStorage","WeakMap","Set","getResumedStreamIds","storage","resumedStreamIds","get","set","ResumableStorageSubscription","listener","threadId","unsubscribe","DynamicResumableStorage","subscriptions","hasPendingNotification","constructor","setStorage","nextResumedStreamIds","streamId","add","flushChange","subscription","subscribe","getStreamId","setStreamId","id","clear","delete","ThreadTransportContext","owner","sourceTransport","UI_MESSAGE","transport","runtime","getThreadListItem","ThreadTransportBinding","DynamicChatTransport","threadContexts","Map","resumableStorage","sendMessages","options","getTransport","chatId","reconnectToStream","getCurrentTransport","getThreadTransport","getCurrentResumableStorage","createThreadProxy","getBinding","getOrCreateBoundTransport","setTransport","flushTransportChange","registerThread","existing","setThreadContext","context","undefined","wireTransport","unregisterThread","Error","getBoundTransport","binding","createThreadTransport","__internal_clone","setRuntime","__internal_setGetThreadListItem"],"sources":["../../src/runtime/DynamicChatTransport.ts"],"sourcesContent":["import type { AssistantRuntime } from \"@assistant-ui/core\";\nimport type { UIMessage } from \"@ai-sdk/react\";\nimport type { ChatTransport } from \"ai\";\nimport {\n AssistantChatTransport,\n type InitializableThreadListItem,\n} from \"../transport/AssistantChatTransport\";\nimport type { ResumableClientStorage } from \"../transport/resumable\";\nimport { getResumableAdapter } from \"./getResumableAdapter\";\n\nconst resumedStreamIdsByStorage = new WeakMap<\n ResumableClientStorage,\n Set<string>\n>();\n\nexport const getResumedStreamIds = (\n storage: ResumableClientStorage | undefined,\n) => {\n if (!storage) return new Set<string>();\n let resumedStreamIds = resumedStreamIdsByStorage.get(storage);\n if (!resumedStreamIds) {\n resumedStreamIds = new Set();\n resumedStreamIdsByStorage.set(storage, resumedStreamIds);\n }\n return resumedStreamIds;\n};\n\ntype ResumableStorageSubscription = {\n listener: () => void;\n threadId: string | undefined;\n unsubscribe: (() => void) | undefined;\n};\n\nclass DynamicResumableStorage implements ResumableClientStorage {\n private readonly subscriptions = new Set<ResumableStorageSubscription>();\n private storage: ResumableClientStorage | undefined;\n private resumedStreamIds: Set<string>;\n private hasPendingNotification = false;\n\n constructor(storage: ResumableClientStorage | undefined) {\n this.storage = storage;\n this.resumedStreamIds = getResumedStreamIds(storage);\n }\n\n public setStorage(storage: ResumableClientStorage | undefined) {\n if (this.storage === storage) return;\n this.storage = storage;\n const nextResumedStreamIds = getResumedStreamIds(storage);\n for (const streamId of this.resumedStreamIds) {\n nextResumedStreamIds.add(streamId);\n }\n this.resumedStreamIds = nextResumedStreamIds;\n this.hasPendingNotification = true;\n }\n\n public flushChange() {\n if (!this.hasPendingNotification) return;\n this.hasPendingNotification = false;\n for (const subscription of this.subscriptions) {\n subscription.unsubscribe?.();\n subscription.unsubscribe = this.storage?.subscribe?.(\n subscription.listener,\n subscription.threadId,\n );\n subscription.listener();\n }\n }\n\n public getResumedStreamIds() {\n return this.resumedStreamIds;\n }\n\n public getStreamId(threadId?: string) {\n return this.storage?.getStreamId(threadId) ?? null;\n }\n\n public setStreamId(id: string, threadId?: string) {\n this.storage?.setStreamId(id, threadId);\n }\n\n public clear(threadId?: string) {\n this.storage?.clear(threadId);\n }\n\n public subscribe(listener: () => void, threadId?: string) {\n const subscription: ResumableStorageSubscription = {\n listener,\n threadId,\n unsubscribe: this.storage?.subscribe?.(listener, threadId),\n };\n this.subscriptions.add(subscription);\n return () => {\n this.subscriptions.delete(subscription);\n subscription.unsubscribe?.();\n };\n }\n}\n\ntype ThreadTransportContext<UI_MESSAGE extends UIMessage> = {\n owner: object;\n sourceTransport?: ChatTransport<UI_MESSAGE> | undefined;\n transport?: ChatTransport<UI_MESSAGE> | undefined;\n runtime?: AssistantRuntime | undefined;\n getThreadListItem?:\n | (() => InitializableThreadListItem | undefined)\n | undefined;\n};\n\ntype ThreadTransportBinding = {\n runtime: AssistantRuntime;\n getThreadListItem: () => InitializableThreadListItem | undefined;\n};\n\nexport class DynamicChatTransport<\n UI_MESSAGE extends UIMessage,\n> implements ChatTransport<UI_MESSAGE> {\n private readonly threadContexts = new Map<\n string,\n ThreadTransportContext<UI_MESSAGE>\n >();\n private transport: ChatTransport<UI_MESSAGE>;\n private readonly resumableStorage: DynamicResumableStorage;\n\n constructor(transport: ChatTransport<UI_MESSAGE>) {\n this.transport = transport;\n this.resumableStorage = new DynamicResumableStorage(\n getResumableAdapter(transport)?.storage,\n );\n }\n\n public readonly sendMessages: ChatTransport<UI_MESSAGE>[\"sendMessages\"] = (\n options,\n ) => this.getTransport(options.chatId).sendMessages(options);\n\n public readonly reconnectToStream: ChatTransport<UI_MESSAGE>[\"reconnectToStream\"] =\n (options) => this.getTransport(options.chatId).reconnectToStream(options);\n\n public readonly getCurrentTransport = (chatId: string) =>\n this.getThreadTransport(this.threadContexts.get(chatId)) ?? this.transport;\n\n public readonly getCurrentResumableStorage = () => this.resumableStorage;\n\n public readonly getResumedStreamIds = () =>\n this.resumableStorage.getResumedStreamIds();\n\n public createThreadProxy(\n owner: object,\n getBinding: () => ThreadTransportBinding,\n ): ChatTransport<UI_MESSAGE> {\n return {\n sendMessages: (options) =>\n this.getOrCreateBoundTransport(\n options.chatId,\n owner,\n getBinding,\n ).sendMessages(options),\n reconnectToStream: (options) =>\n this.getOrCreateBoundTransport(\n options.chatId,\n owner,\n getBinding,\n ).reconnectToStream(options),\n };\n }\n\n public setTransport(transport: ChatTransport<UI_MESSAGE>) {\n if (this.transport === transport) return;\n this.transport = transport;\n this.resumableStorage.setStorage(getResumableAdapter(transport)?.storage);\n }\n\n public flushTransportChange() {\n this.resumableStorage.flushChange();\n }\n\n public registerThread(chatId: string, owner: object) {\n const existing = this.threadContexts.get(chatId);\n if (existing?.owner === owner) return;\n this.threadContexts.set(chatId, {\n owner,\n });\n }\n\n public setThreadContext(\n chatId: string,\n owner: object,\n runtime: AssistantRuntime,\n getThreadListItem: () => InitializableThreadListItem | undefined,\n ) {\n this.registerThread(chatId, owner);\n const context = this.threadContexts.get(chatId)!;\n context.runtime = runtime;\n context.getThreadListItem = getThreadListItem;\n if (context.transport === undefined) {\n this.getThreadTransport(context);\n return;\n }\n if (\n context.sourceTransport === this.transport &&\n context.transport !== undefined\n ) {\n this.wireTransport(context, context.transport);\n }\n }\n\n public unregisterThread(chatId: string, owner: object) {\n if (this.threadContexts.get(chatId)?.owner === owner) {\n this.threadContexts.delete(chatId);\n }\n }\n\n private getTransport(chatId: string) {\n const context = this.threadContexts.get(chatId);\n if (!context) {\n throw new Error(\n `DynamicChatTransport has no registered context for chat \"${chatId}\"`,\n );\n }\n return this.getThreadTransport(context)!;\n }\n\n private getBoundTransport(\n chatId: string,\n owner: object,\n binding: ThreadTransportBinding,\n ) {\n this.registerThread(chatId, owner);\n const context = this.threadContexts.get(chatId)!;\n context.runtime = binding.runtime;\n context.getThreadListItem = binding.getThreadListItem;\n return this.getThreadTransport(context)!;\n }\n\n private getOrCreateBoundTransport(\n chatId: string,\n owner: object,\n getBinding: () => ThreadTransportBinding,\n ) {\n const context = this.threadContexts.get(chatId);\n return context?.owner === owner\n ? this.getThreadTransport(context)!\n : this.getBoundTransport(chatId, owner, getBinding());\n }\n\n private getThreadTransport(\n context: ThreadTransportContext<UI_MESSAGE> | undefined,\n ) {\n if (!context) return undefined;\n if (context.sourceTransport !== this.transport) {\n context.transport = this.createThreadTransport(this.transport);\n context.sourceTransport = this.transport;\n }\n this.wireTransport(context, context.transport!);\n return context.transport!;\n }\n\n private createThreadTransport(transport: ChatTransport<UI_MESSAGE>) {\n return transport instanceof AssistantChatTransport\n ? transport.__internal_clone()\n : transport;\n }\n\n private wireTransport(\n context: ThreadTransportContext<UI_MESSAGE>,\n transport: ChatTransport<UI_MESSAGE>,\n ) {\n if (!(transport instanceof AssistantChatTransport)) return;\n if (context.runtime) transport.setRuntime(context.runtime);\n if (context.getThreadListItem) {\n transport.__internal_setGetThreadListItem(context.getThreadListItem);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { UIMessage } from "@ai-sdk/react";
|
|
2
|
+
import type { ChatTransport } from "ai";
|
|
3
|
+
import type { AssistantChatResumableOptions } from "../transport/resumable.js";
|
|
4
|
+
export declare const getResumableAdapter: <UI_MESSAGE extends UIMessage>(transport: ChatTransport<UI_MESSAGE>) => AssistantChatResumableOptions | undefined;
|
|
5
|
+
//# sourceMappingURL=getResumableAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getResumableAdapter.d.ts","sourceRoot":"","sources":["../../src/runtime/getResumableAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAExC,OAAO,KAAK,EAAE,6BAA6B,EAAE,kCAA+B;AAE5E,eAAO,MAAM,mBAAmB,GAAI,UAAU,SAAS,SAAS,EAC9D,WAAW,aAAa,CAAC,UAAU,CAAC,KACnC,6BAA6B,GAAG,SAQlC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AssistantChatTransport } from "../transport/AssistantChatTransport.js";
|
|
2
|
+
//#region src/runtime/getResumableAdapter.ts
|
|
3
|
+
const getResumableAdapter = (transport) => {
|
|
4
|
+
if (transport instanceof AssistantChatTransport) return transport.getResumableAdapter();
|
|
5
|
+
const candidate = transport.getResumableAdapter;
|
|
6
|
+
if (typeof candidate !== "function") return void 0;
|
|
7
|
+
return candidate.call(transport);
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { getResumableAdapter };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=getResumableAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getResumableAdapter.js","names":["UIMessage","ChatTransport","AssistantChatTransport","AssistantChatResumableOptions","getResumableAdapter","transport","UI_MESSAGE","candidate","undefined","call"],"sources":["../../src/runtime/getResumableAdapter.ts"],"sourcesContent":["import type { UIMessage } from \"@ai-sdk/react\";\nimport type { ChatTransport } from \"ai\";\nimport { AssistantChatTransport } from \"../transport/AssistantChatTransport\";\nimport type { AssistantChatResumableOptions } from \"../transport/resumable\";\n\nexport const getResumableAdapter = <UI_MESSAGE extends UIMessage>(\n transport: ChatTransport<UI_MESSAGE>,\n): AssistantChatResumableOptions | undefined => {\n if (transport instanceof AssistantChatTransport) {\n return transport.getResumableAdapter();\n }\n const candidate = (transport as { getResumableAdapter?: () => unknown })\n .getResumableAdapter;\n if (typeof candidate !== \"function\") return undefined;\n return candidate.call(transport) as AssistantChatResumableOptions | undefined;\n};\n"],"mappings":";;AAKA,MAAaI,uBACXC,cAC8C;CAC9C,IAAIA,qBAAqBH,wBACvB,OAAOG,UAAUD,oBAAoB;CAEvC,MAAMG,YAAaF,UAChBD;CACH,IAAI,OAAOG,cAAc,YAAY,OAAOC,KAAAA;CAC5C,OAAOD,UAAUE,KAAKJ,SAAS;AACjC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { RespondToToolApprovalOptions, ThreadMessage, Unstable_ToolInteractionLog } from "@assistant-ui/core";
|
|
2
|
+
export type StoredToolApprovalResponse = Omit<RespondToToolApprovalOptions, "approvalId">;
|
|
3
|
+
export declare const collectToolArtifacts: (message: ThreadMessage, toolArtifacts: ReadonlyMap<string, unknown> | undefined) => {
|
|
4
|
+
[k: string]: {} | null;
|
|
5
|
+
} | undefined;
|
|
6
|
+
export declare const collectToolInteractions: (message: ThreadMessage, toolInteractions: ReadonlyMap<string, Unstable_ToolInteractionLog> | undefined) => {
|
|
7
|
+
[k: string]: Unstable_ToolInteractionLog;
|
|
8
|
+
} | undefined;
|
|
9
|
+
export declare const collectToolApprovalResponses: (message: ThreadMessage, toolApprovalResponses: ReadonlyMap<string, RespondToToolApprovalOptions> | undefined) => {
|
|
10
|
+
[k: string]: {
|
|
11
|
+
readonly reason?: string;
|
|
12
|
+
readonly answers?: Readonly<Record<string, import("@assistant-ui/core").ToolApprovalAnswer>>;
|
|
13
|
+
readonly text?: string;
|
|
14
|
+
readonly optionId?: string;
|
|
15
|
+
readonly approved: boolean;
|
|
16
|
+
};
|
|
17
|
+
} | undefined;
|
|
18
|
+
export declare const addToolData: <TMessage>(message: TMessage, toolArtifacts: Record<string, unknown> | undefined, toolInteractions: Record<string, Unstable_ToolInteractionLog> | undefined, toolApprovalResponses: Record<string, StoredToolApprovalResponse> | undefined) => TMessage;
|
|
19
|
+
export declare const restoreToolData: <TMessage>(message: TMessage, toolArtifacts: Map<string, unknown> | undefined, toolInteractions: Map<string, Unstable_ToolInteractionLog> | undefined, toolApprovalResponses: Map<string, RespondToToolApprovalOptions> | undefined) => TMessage;
|
|
20
|
+
//# sourceMappingURL=toolHistoryCodec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolHistoryCodec.d.ts","sourceRoot":"","sources":["../../src/runtime/toolHistoryCodec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,4BAA4B,EAC5B,aAAa,EACb,2BAA2B,EAC5B,MAAM,oBAAoB,CAAC;AAQ5B,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAC3C,4BAA4B,EAC5B,YAAY,CACb,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,SAAS,aAAa,EACtB,eAAe,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;;aASxD,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAClC,SAAS,aAAa,EACtB,kBACI,WAAW,CAAC,MAAM,EAAE,2BAA2B,CAAC,GAChD,SAAS;;aAWd,CAAC;AAEF,eAAO,MAAM,4BAA4B,GACvC,SAAS,aAAa,EACtB,uBACI,WAAW,CAAC,MAAM,EAAE,4BAA4B,CAAC,GACjD,SAAS;;;;;;;;aAqBd,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,QAAQ,EAClC,SAAS,QAAQ,EACjB,eAAe,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAClD,kBAAkB,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,GAAG,SAAS,EACzE,uBAAuB,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,GAAG,SAAS,KAC5E,QAgEF,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,QAAQ,EACtC,SAAS,QAAQ,EACjB,eAAe,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC/C,kBAAkB,GAAG,CAAC,MAAM,EAAE,2BAA2B,CAAC,GAAG,SAAS,EACtE,uBAAuB,GAAG,CAAC,MAAM,EAAE,4BAA4B,CAAC,GAAG,SAAS,KAC3E,QAwDF,CAAC"}
|