@assistant-ui/ai-sdk 0.0.1
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/LICENSE +21 -0
- package/README.md +32 -0
- package/dist/adapters/aiSDKFormatAdapter.d.ts +8 -0
- package/dist/adapters/aiSDKFormatAdapter.d.ts.map +1 -0
- package/dist/adapters/aiSDKFormatAdapter.js +26 -0
- package/dist/adapters/aiSDKFormatAdapter.js.map +1 -0
- package/dist/adapters/vercelAttachmentAdapter.d.ts +6 -0
- package/dist/adapters/vercelAttachmentAdapter.d.ts.map +1 -0
- package/dist/adapters/vercelAttachmentAdapter.js +37 -0
- package/dist/adapters/vercelAttachmentAdapter.js.map +1 -0
- package/dist/aiSDKExtras.d.ts +11 -0
- package/dist/aiSDKExtras.d.ts.map +1 -0
- package/dist/aiSDKExtras.js +7 -0
- package/dist/aiSDKExtras.js.map +1 -0
- package/dist/converters/convertMessage.d.ts +28 -0
- package/dist/converters/convertMessage.d.ts.map +1 -0
- package/dist/converters/convertMessage.js +249 -0
- package/dist/converters/convertMessage.js.map +1 -0
- package/dist/converters/modelContentEnvelope.d.ts +16 -0
- package/dist/converters/modelContentEnvelope.d.ts.map +1 -0
- package/dist/converters/modelContentEnvelope.js +22 -0
- package/dist/converters/modelContentEnvelope.js.map +1 -0
- package/dist/converters/toCreateMessage.d.ts +7 -0
- package/dist/converters/toCreateMessage.d.ts.map +1 -0
- package/dist/converters/toCreateMessage.js +58 -0
- package/dist/converters/toCreateMessage.js.map +1 -0
- package/dist/converters/toolOutputConversion.d.ts +29 -0
- package/dist/converters/toolOutputConversion.d.ts.map +1 -0
- package/dist/converters/toolOutputConversion.js +31 -0
- package/dist/converters/toolOutputConversion.js.map +1 -0
- package/dist/hooks.d.ts +19 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +20 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +13 -0
- package/dist/index.native.d.ts +12 -0
- package/dist/index.native.js +11 -0
- package/dist/model-context/injectInteractableContext.d.ts +37 -0
- package/dist/model-context/injectInteractableContext.d.ts.map +1 -0
- package/dist/model-context/injectInteractableContext.js +52 -0
- package/dist/model-context/injectInteractableContext.js.map +1 -0
- package/dist/model-context/injectQuoteContext.d.ts +27 -0
- package/dist/model-context/injectQuoteContext.d.ts.map +1 -0
- package/dist/model-context/injectQuoteContext.js +51 -0
- package/dist/model-context/injectQuoteContext.js.map +1 -0
- package/dist/runtime/AISDKChat.d.ts +16 -0
- package/dist/runtime/AISDKChat.d.ts.map +1 -0
- package/dist/runtime/AISDKChat.js +69 -0
- package/dist/runtime/AISDKChat.js.map +1 -0
- package/dist/runtime/AISDKThreads.d.ts +45 -0
- package/dist/runtime/AISDKThreads.d.ts.map +1 -0
- package/dist/runtime/AISDKThreads.js +203 -0
- package/dist/runtime/AISDKThreads.js.map +1 -0
- package/dist/runtime/useAISDKRuntime.d.ts +49 -0
- package/dist/runtime/useAISDKRuntime.d.ts.map +1 -0
- package/dist/runtime/useAISDKRuntime.js +266 -0
- package/dist/runtime/useAISDKRuntime.js.map +1 -0
- package/dist/runtime/useChatRuntime.d.ts +13 -0
- package/dist/runtime/useChatRuntime.d.ts.map +1 -0
- package/dist/runtime/useChatRuntime.js +52 -0
- package/dist/runtime/useChatRuntime.js.map +1 -0
- package/dist/runtime/useChatThread.d.ts +77 -0
- package/dist/runtime/useChatThread.d.ts.map +1 -0
- package/dist/runtime/useChatThread.js +134 -0
- package/dist/runtime/useChatThread.js.map +1 -0
- package/dist/runtime/useExternalHistory.d.ts +11 -0
- package/dist/runtime/useExternalHistory.d.ts.map +1 -0
- package/dist/runtime/useExternalHistory.js +278 -0
- package/dist/runtime/useExternalHistory.js.map +1 -0
- package/dist/runtime/useResourceCleanup.d.ts +5 -0
- package/dist/runtime/useResourceCleanup.d.ts.map +1 -0
- package/dist/runtime/useResourceCleanup.js +47 -0
- package/dist/runtime/useResourceCleanup.js.map +1 -0
- package/dist/runtime/useStreamingTiming.d.ts +15 -0
- package/dist/runtime/useStreamingTiming.d.ts.map +1 -0
- package/dist/runtime/useStreamingTiming.js +38 -0
- package/dist/runtime/useStreamingTiming.js.map +1 -0
- package/dist/tools/frontendTools.d.ts +33 -0
- package/dist/tools/frontendTools.d.ts.map +1 -0
- package/dist/tools/frontendTools.js +33 -0
- package/dist/tools/frontendTools.js.map +1 -0
- package/dist/tools/generativeTools.d.ts +73 -0
- package/dist/tools/generativeTools.d.ts.map +1 -0
- package/dist/tools/generativeTools.js +245 -0
- package/dist/tools/generativeTools.js.map +1 -0
- package/dist/tools/mcp-stdio.node.d.ts +2 -0
- package/dist/tools/mcp-stdio.node.js +2 -0
- package/dist/tools/mcp-stdio.unsupported.d.ts +6 -0
- package/dist/tools/mcp-stdio.unsupported.d.ts.map +1 -0
- package/dist/tools/mcp-stdio.unsupported.js +11 -0
- package/dist/tools/mcp-stdio.unsupported.js.map +1 -0
- package/dist/transport/AssistantChatTransport.d.ts +23 -0
- package/dist/transport/AssistantChatTransport.d.ts.map +1 -0
- package/dist/transport/AssistantChatTransport.js +134 -0
- package/dist/transport/AssistantChatTransport.js.map +1 -0
- package/dist/transport/resumable.d.ts +38 -0
- package/dist/transport/resumable.d.ts.map +1 -0
- package/dist/transport/resumable.js +113 -0
- package/dist/transport/resumable.js.map +1 -0
- package/dist/usage.d.ts +19 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +127 -0
- package/dist/usage.js.map +1 -0
- package/dist/utils/getVercelAIMessages.d.ts +7 -0
- package/dist/utils/getVercelAIMessages.d.ts.map +1 -0
- package/dist/utils/getVercelAIMessages.js +9 -0
- package/dist/utils/getVercelAIMessages.js.map +1 -0
- package/dist/utils/sliceMessagesUntil.d.ts +6 -0
- package/dist/utils/sliceMessagesUntil.d.ts.map +1 -0
- package/dist/utils/sliceMessagesUntil.js +12 -0
- package/dist/utils/sliceMessagesUntil.js.map +1 -0
- package/package.json +100 -0
- package/src/__tests__/standalone.e2e.ts +59 -0
- package/src/adapters/aiSDKFormatAdapter.ts +41 -0
- package/src/adapters/vercelAttachmentAdapter.test.ts +29 -0
- package/src/adapters/vercelAttachmentAdapter.ts +36 -0
- package/src/aiSDKExtras.ts +11 -0
- package/src/converters/convertMessage.test.ts +1130 -0
- package/src/converters/convertMessage.ts +457 -0
- package/src/converters/modelContentEnvelope.ts +41 -0
- package/src/converters/toCreateMessage.test.ts +596 -0
- package/src/converters/toCreateMessage.ts +99 -0
- package/src/converters/toolOutputConversion.ts +26 -0
- package/src/hooks.ts +23 -0
- package/src/index.native.ts +21 -0
- package/src/index.ts +29 -0
- package/src/model-context/injectInteractableContext.test.ts +167 -0
- package/src/model-context/injectInteractableContext.ts +61 -0
- package/src/model-context/injectQuoteContext.test.ts +33 -0
- package/src/model-context/injectQuoteContext.ts +62 -0
- package/src/runtime/AISDKChat.integration.test.tsx +47 -0
- package/src/runtime/AISDKChat.react-compiler.test.ts +49 -0
- package/src/runtime/AISDKChat.test.ts +193 -0
- package/src/runtime/AISDKChat.ts +47 -0
- package/src/runtime/AISDKThreads.cloud.test.ts +136 -0
- package/src/runtime/AISDKThreads.test.ts +548 -0
- package/src/runtime/AISDKThreads.ts +223 -0
- package/src/runtime/__tests__/controlled-transport.ts +43 -0
- package/src/runtime/useAISDKRuntime.approval.test.tsx +69 -0
- package/src/runtime/useAISDKRuntime.test.ts +1021 -0
- package/src/runtime/useAISDKRuntime.tool-output.test.tsx +113 -0
- package/src/runtime/useAISDKRuntime.ts +524 -0
- package/src/runtime/useChatOnTap.test.ts +58 -0
- package/src/runtime/useChatRuntime.integration.test.tsx +67 -0
- package/src/runtime/useChatRuntime.test.ts +522 -0
- package/src/runtime/useChatRuntime.ts +49 -0
- package/src/runtime/useChatThread.ts +286 -0
- package/src/runtime/useExternalHistory.test.ts +1289 -0
- package/src/runtime/useExternalHistory.ts +435 -0
- package/src/runtime/useResourceCleanup.ts +32 -0
- package/src/runtime/useStreamingTiming.ts +68 -0
- package/src/tools/frontendTools.test.ts +205 -0
- package/src/tools/frontendTools.ts +83 -0
- package/src/tools/generativeTools.test.ts +785 -0
- package/src/tools/generativeTools.ts +470 -0
- package/src/tools/mcp-stdio.node.ts +1 -0
- package/src/tools/mcp-stdio.unsupported.ts +12 -0
- package/src/transport/AssistantChatTransport.test.ts +300 -0
- package/src/transport/AssistantChatTransport.ts +204 -0
- package/src/transport/resumable.test.ts +262 -0
- package/src/transport/resumable.ts +161 -0
- package/src/usage.test.ts +186 -0
- package/src/usage.ts +174 -0
- package/src/utils/getVercelAIMessages.ts +11 -0
- package/src/utils/sliceMessagesUntil.test.ts +55 -0
- package/src/utils/sliceMessagesUntil.ts +20 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { httpUrlPattern, parseDataUrl, resolveFileMediaType, resolveImageMediaType, toMediaWireUrl } from "@assistant-ui/core/internal";
|
|
2
|
+
//#region src/converters/toCreateMessage.ts
|
|
3
|
+
const toCreateMessage = (message) => {
|
|
4
|
+
const parts = [...message.content, ...message.attachments?.flatMap((a) => a.content.map((c) => ({
|
|
5
|
+
...c,
|
|
6
|
+
filename: a.name,
|
|
7
|
+
contentType: a.contentType
|
|
8
|
+
}))) ?? []].map((part) => {
|
|
9
|
+
switch (part.type) {
|
|
10
|
+
case "text": return {
|
|
11
|
+
type: "text",
|
|
12
|
+
text: part.text
|
|
13
|
+
};
|
|
14
|
+
case "image": {
|
|
15
|
+
const mediaType = resolveImageMediaType(part.image, part.contentType);
|
|
16
|
+
return {
|
|
17
|
+
type: "file",
|
|
18
|
+
url: toMediaWireUrl(part.image, mediaType),
|
|
19
|
+
...part.filename && { filename: part.filename },
|
|
20
|
+
mediaType
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
case "file": {
|
|
24
|
+
const mediaType = resolveFileMediaType(part.data, part.mimeType);
|
|
25
|
+
return {
|
|
26
|
+
type: "file",
|
|
27
|
+
url: part.sourceType === "id" ? part.data : toMediaWireUrl(part.data, mediaType),
|
|
28
|
+
mediaType,
|
|
29
|
+
...part.filename && { filename: part.filename }
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
case "audio": {
|
|
33
|
+
const mediaType = `audio/${part.audio.format}`;
|
|
34
|
+
const data = part.audio.data;
|
|
35
|
+
return {
|
|
36
|
+
type: "file",
|
|
37
|
+
url: httpUrlPattern.test(data) ? data : `data:${mediaType};base64,${parseDataUrl(data)?.data ?? data}`,
|
|
38
|
+
mediaType,
|
|
39
|
+
...part.filename && { filename: part.filename }
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
case "data": return {
|
|
43
|
+
type: `data-${part.name}`,
|
|
44
|
+
data: part.data
|
|
45
|
+
};
|
|
46
|
+
default: throw new Error(`Unsupported part type: ${part.type}`);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
role: message.role,
|
|
51
|
+
parts,
|
|
52
|
+
metadata: message.metadata
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
//#endregion
|
|
56
|
+
export { toCreateMessage };
|
|
57
|
+
|
|
58
|
+
//# sourceMappingURL=toCreateMessage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toCreateMessage.js","names":["AppendMessage","httpUrlPattern","parseDataUrl","resolveFileMediaType","resolveImageMediaType","toMediaWireUrl","CreateUIMessage","UIDataTypes","UIMessage","UIMessagePart","UITools","InputPart","contentType","filename","toCreateMessage","message","UI_MESSAGE","inputParts","content","attachments","flatMap","a","map","c","name","parts","part","type","text","mediaType","image","url","data","mimeType","sourceType","audio","format","test","Error","role","metadata"],"sources":["../../src/converters/toCreateMessage.ts"],"sourcesContent":["import type { AppendMessage } from \"@assistant-ui/core\";\nimport {\n httpUrlPattern,\n parseDataUrl,\n resolveFileMediaType,\n resolveImageMediaType,\n toMediaWireUrl,\n} from \"@assistant-ui/core/internal\";\nimport type {\n CreateUIMessage,\n UIDataTypes,\n UIMessage,\n UIMessagePart,\n UITools,\n} from \"ai\";\n\ntype InputPart = AppendMessage[\"content\"][number] & {\n readonly contentType?: string | undefined;\n readonly filename?: string | undefined;\n};\n\nexport const toCreateMessage = <UI_MESSAGE extends UIMessage = UIMessage>(\n message: AppendMessage,\n): CreateUIMessage<UI_MESSAGE> => {\n const inputParts: InputPart[] = [\n ...message.content,\n ...(message.attachments?.flatMap((a) =>\n a.content.map((c) => ({\n ...c,\n filename: a.name,\n contentType: a.contentType,\n })),\n ) ?? []),\n ];\n\n const parts = inputParts.map((part): UIMessagePart<UIDataTypes, UITools> => {\n switch (part.type) {\n case \"text\":\n return {\n type: \"text\",\n text: part.text,\n };\n case \"image\": {\n const mediaType = resolveImageMediaType(part.image, part.contentType);\n return {\n type: \"file\",\n url: toMediaWireUrl(part.image, mediaType),\n ...(part.filename && { filename: part.filename }),\n mediaType,\n };\n }\n case \"file\": {\n // `mimeType` is a plain string, and an adapter reading `file.type` on a\n // file the OS cannot type yields \"\". Same ladder as images: declared,\n // then the envelope, then the floor.\n const mediaType = resolveFileMediaType(part.data, part.mimeType);\n return {\n type: \"file\",\n // An `id` reference is an opaque provider handle, not base64, and\n // this adapter has no way to send one. Left unwrapped so it fails\n // loudly upstream rather than shipping a corrupt payload.\n url:\n part.sourceType === \"id\"\n ? part.data\n : toMediaWireUrl(part.data, mediaType),\n mediaType,\n ...(part.filename && { filename: part.filename }),\n };\n }\n case \"audio\": {\n // A data URL's own media type wins over `mediaType` downstream, so the\n // envelope is rebuilt from the typed format rather than forwarded.\n const mediaType = `audio/${part.audio.format}`;\n const data = part.audio.data;\n return {\n type: \"file\",\n url: httpUrlPattern.test(data)\n ? data\n : `data:${mediaType};base64,${parseDataUrl(data)?.data ?? data}`,\n mediaType,\n ...(part.filename && { filename: part.filename }),\n };\n }\n case \"data\":\n return {\n type: `data-${part.name}`,\n data: part.data,\n };\n default:\n throw new Error(`Unsupported part type: ${part.type}`);\n }\n });\n\n return {\n role: message.role,\n parts,\n metadata: message.metadata,\n } satisfies CreateUIMessage<UIMessage> as CreateUIMessage<UI_MESSAGE>;\n};\n"],"mappings":";;AAqBA,MAAac,mBACXC,YACgC;CAYhC,MAAMU,QAAQR,CAVZ,GAAGF,QAAQG,SACX,GAAIH,QAAQI,aAAaC,SAASC,MAChCA,EAAEH,QAAQI,KAAKC,OAAO;EACpB,GAAGA;EACHV,UAAUQ,EAAEG;EACZZ,aAAaS,EAAET;CACjB,EAAE,CACJ,KAAK,CAAA,CAGOK,CAAU,CAACK,KAAKI,SAA8C;EAC1E,QAAQA,KAAKC,MAAb;GACE,KAAK,QACH,OAAO;IACLA,MAAM;IACNC,MAAMF,KAAKE;GACb;GACF,KAAK,SAAS;IACZ,MAAMC,YAAYzB,sBAAsBsB,KAAKI,OAAOJ,KAAKd,WAAW;IACpE,OAAO;KACLe,MAAM;KACNI,KAAK1B,eAAeqB,KAAKI,OAAOD,SAAS;KACzC,GAAIH,KAAKb,YAAY,EAAEA,UAAUa,KAAKb,SAAS;KAC/CgB;IACF;GACF;GACA,KAAK,QAAQ;IAIX,MAAMA,YAAY1B,qBAAqBuB,KAAKM,MAAMN,KAAKO,QAAQ;IAC/D,OAAO;KACLN,MAAM;KAINI,KACEL,KAAKQ,eAAe,OAChBR,KAAKM,OACL3B,eAAeqB,KAAKM,MAAMH,SAAS;KACzCA;KACA,GAAIH,KAAKb,YAAY,EAAEA,UAAUa,KAAKb,SAAS;IACjD;GACF;GACA,KAAK,SAAS;IAGZ,MAAMgB,YAAY,SAASH,KAAKS,MAAMC;IACtC,MAAMJ,OAAON,KAAKS,MAAMH;IACxB,OAAO;KACLL,MAAM;KACNI,KAAK9B,eAAeoC,KAAKL,IAAI,IACzBA,OACA,QAAQH,UAAS,UAAW3B,aAAa8B,IAAI,CAAC,EAAEA,QAAQA;KAC5DH;KACA,GAAIH,KAAKb,YAAY,EAAEA,UAAUa,KAAKb,SAAS;IACjD;GACF;GACA,KAAK,QACH,OAAO;IACLc,MAAM,QAAQD,KAAKF;IACnBQ,MAAMN,KAAKM;GACb;GACF,SACE,MAAM,IAAIM,MAAM,0BAA0BZ,KAAKC,MAAM;EACzD;CACF,CAAC;CAED,OAAO;EACLY,MAAMxB,QAAQwB;EACdd;EACAe,UAAUzB,QAAQyB;CACpB;AACF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { JSONValue } from "ai";
|
|
2
|
+
import { ToolModelContentPart } from "assistant-stream";
|
|
3
|
+
//#region src/converters/toolOutputConversion.d.ts
|
|
4
|
+
declare const toAISDKContent: (parts: readonly ToolModelContentPart[]) => {
|
|
5
|
+
type: "content";
|
|
6
|
+
value: ({
|
|
7
|
+
type: "text";
|
|
8
|
+
text: string;
|
|
9
|
+
} | {
|
|
10
|
+
filename?: string;
|
|
11
|
+
type: "file";
|
|
12
|
+
data: {
|
|
13
|
+
type: "data";
|
|
14
|
+
data: string;
|
|
15
|
+
};
|
|
16
|
+
mediaType: string;
|
|
17
|
+
text?: never;
|
|
18
|
+
})[];
|
|
19
|
+
};
|
|
20
|
+
declare const toAISDKDefaultOutput: (output: unknown) => {
|
|
21
|
+
type: "text";
|
|
22
|
+
value: string;
|
|
23
|
+
} | {
|
|
24
|
+
type: "json";
|
|
25
|
+
value: JSONValue;
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
28
|
+
export { toAISDKContent, toAISDKDefaultOutput };
|
|
29
|
+
//# sourceMappingURL=toolOutputConversion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolOutputConversion.d.ts","names":[],"sources":["../../src/converters/toolOutputConversion.ts"],"mappings":";;;cAGa,iBAAkB,gBAAgB;;;;;;;;;;;;;;;;cAmBlC,uBAAwB;;;;;EAGqB,OAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/converters/toolOutputConversion.ts
|
|
2
|
+
const toAISDKContent = (parts) => ({
|
|
3
|
+
type: "content",
|
|
4
|
+
value: parts.map((part) => {
|
|
5
|
+
if (part.type === "text") return {
|
|
6
|
+
type: "text",
|
|
7
|
+
text: part.text
|
|
8
|
+
};
|
|
9
|
+
const mediaType = typeof part.mediaType === "string" ? part.mediaType : "application/octet-stream";
|
|
10
|
+
return {
|
|
11
|
+
type: "file",
|
|
12
|
+
data: {
|
|
13
|
+
type: "data",
|
|
14
|
+
data: part.data
|
|
15
|
+
},
|
|
16
|
+
mediaType,
|
|
17
|
+
...part.filename !== void 0 && { filename: part.filename }
|
|
18
|
+
};
|
|
19
|
+
})
|
|
20
|
+
});
|
|
21
|
+
const toAISDKDefaultOutput = (output) => typeof output === "string" ? {
|
|
22
|
+
type: "text",
|
|
23
|
+
value: output
|
|
24
|
+
} : {
|
|
25
|
+
type: "json",
|
|
26
|
+
value: output ?? null
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
export { toAISDKContent, toAISDKDefaultOutput };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=toolOutputConversion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolOutputConversion.js","names":["JSONValue","ToolModelContentPart","toAISDKContent","parts","type","const","value","map","part","text","mediaType","data","filename","undefined","toAISDKDefaultOutput","output"],"sources":["../../src/converters/toolOutputConversion.ts"],"sourcesContent":["import type { JSONValue } from \"ai\";\nimport type { ToolModelContentPart } from \"assistant-stream\";\n\nexport const toAISDKContent = (parts: readonly ToolModelContentPart[]) => ({\n type: \"content\" as const,\n value: parts.map((part) => {\n if (part.type === \"text\") {\n return { type: \"text\" as const, text: part.text };\n }\n const mediaType =\n typeof part.mediaType === \"string\"\n ? part.mediaType\n : \"application/octet-stream\";\n return {\n type: \"file\" as const,\n data: { type: \"data\" as const, data: part.data },\n mediaType,\n ...(part.filename !== undefined && { filename: part.filename }),\n };\n }),\n});\n\nexport const toAISDKDefaultOutput = (output: unknown) =>\n typeof output === \"string\"\n ? { type: \"text\" as const, value: output }\n : { type: \"json\" as const, value: (output ?? null) as JSONValue };\n"],"mappings":";AAGA,MAAaE,kBAAkBC,WAA4C;CACzEC,MAAM;CACNE,OAAOH,MAAMI,KAAKC,SAAS;EACzB,IAAIA,KAAKJ,SAAS,QAChB,OAAO;GAAEA,MAAM;GAAiBK,MAAMD,KAAKC;EAAK;EAElD,MAAMC,YACJ,OAAOF,KAAKE,cAAc,WACtBF,KAAKE,YACL;EACN,OAAO;GACLN,MAAM;GACNO,MAAM;IAAEP,MAAM;IAAiBO,MAAMH,KAAKG;GAAK;GAC/CD;GACA,GAAIF,KAAKI,aAAaC,KAAAA,KAAa,EAAED,UAAUJ,KAAKI,SAAS;EAC/D;CACF,CAAC;AACH;AAEA,MAAaE,wBAAwBC,WACnC,OAAOA,WAAW,WACd;CAAEX,MAAM;CAAiBE,OAAOS;AAAO,IACvC;CAAEX,MAAM;CAAiBE,OAAQS,UAAU;AAAmB"}
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { UIMessage } from "ai";
|
|
2
|
+
import { UseChatHelpers } from "@ai-sdk/react";
|
|
3
|
+
//#region src/hooks.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Read the last AI SDK chat error object from the runtime extras.
|
|
6
|
+
* `undefined` when there is no error or the current thread is not backed by
|
|
7
|
+
* the AI SDK runtime.
|
|
8
|
+
*/
|
|
9
|
+
declare const useAISDKError: () => Error | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* The underlying `useChat` helpers object, for advanced views — reach
|
|
12
|
+
* `resumeStream`, `clearError`, or the raw `sendMessage` without forking the
|
|
13
|
+
* runtime hook. `undefined` when the current thread is not backed by the AI
|
|
14
|
+
* SDK runtime.
|
|
15
|
+
*/
|
|
16
|
+
declare const useAISDKChat: <UI_MESSAGE extends UIMessage = UIMessage>() => UseChatHelpers<UI_MESSAGE> | undefined;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { useAISDKChat, useAISDKError };
|
|
19
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;;;;;;cAWa,qBAAa;;;;;;;cAQb,eAAgB,mBAAmB,YAAY,gBAEtD,eAAe"}
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { aiSDKExtras } from "./aiSDKExtras.js";
|
|
3
|
+
//#region src/hooks.ts
|
|
4
|
+
/**
|
|
5
|
+
* Read the last AI SDK chat error object from the runtime extras.
|
|
6
|
+
* `undefined` when there is no error or the current thread is not backed by
|
|
7
|
+
* the AI SDK runtime.
|
|
8
|
+
*/
|
|
9
|
+
const useAISDKError = () => aiSDKExtras.use((e) => e.error, void 0);
|
|
10
|
+
/**
|
|
11
|
+
* The underlying `useChat` helpers object, for advanced views — reach
|
|
12
|
+
* `resumeStream`, `clearError`, or the raw `sendMessage` without forking the
|
|
13
|
+
* runtime hook. `undefined` when the current thread is not backed by the AI
|
|
14
|
+
* SDK runtime.
|
|
15
|
+
*/
|
|
16
|
+
const useAISDKChat = () => aiSDKExtras.use((e) => e.chat, void 0);
|
|
17
|
+
//#endregion
|
|
18
|
+
export { useAISDKChat, useAISDKError };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","names":["UseChatHelpers","UIMessage","aiSDKExtras","useAISDKError","use","e","error","undefined","useAISDKChat","chat","UI_MESSAGE"],"sources":["../src/hooks.ts"],"sourcesContent":["\"use client\";\n\nimport type { UseChatHelpers } from \"@ai-sdk/react\";\nimport type { UIMessage } from \"ai\";\nimport { aiSDKExtras } from \"./aiSDKExtras\";\n\n/**\n * Read the last AI SDK chat error object from the runtime extras.\n * `undefined` when there is no error or the current thread is not backed by\n * the AI SDK runtime.\n */\nexport const useAISDKError = () => aiSDKExtras.use((e) => e.error, undefined);\n\n/**\n * The underlying `useChat` helpers object, for advanced views — reach\n * `resumeStream`, `clearError`, or the raw `sendMessage` without forking the\n * runtime hook. `undefined` when the current thread is not backed by the AI\n * SDK runtime.\n */\nexport const useAISDKChat = <UI_MESSAGE extends UIMessage = UIMessage>() =>\n aiSDKExtras.use((e) => e.chat, undefined) as\n | UseChatHelpers<UI_MESSAGE>\n | undefined;\n"],"mappings":";;;;;;;;AAWA,MAAaG,sBAAsBD,YAAYE,KAAKC,MAAMA,EAAEC,OAAOC,KAAAA,CAAS;;;;;;;AAQ5E,MAAaC,qBACXN,YAAYE,KAAKC,MAAMA,EAAEI,MAAMF,KAAAA,CAAS"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="@assistant-ui/core/react" />
|
|
2
|
+
import { useAISDKChat, useAISDKError } from "./hooks.js";
|
|
3
|
+
import { useAISDKRuntime } from "./runtime/useAISDKRuntime.js";
|
|
4
|
+
import { AssistantChatResumableOptions, RESUMABLE_STREAM_ID_HEADER, ResumableClientStorage, createResumableSessionStorage } from "./transport/resumable.js";
|
|
5
|
+
import { AssistantChatTransport } from "./transport/AssistantChatTransport.js";
|
|
6
|
+
import { UseChatRuntimeOptions, useChatRuntime } from "./runtime/useChatRuntime.js";
|
|
7
|
+
import { FrontendTools, frontendTools } from "./tools/frontendTools.js";
|
|
8
|
+
import { injectQuoteContext } from "./model-context/injectQuoteContext.js";
|
|
9
|
+
import { unstable_injectInteractableContext } from "./model-context/injectInteractableContext.js";
|
|
10
|
+
import { ThreadTokenUsage, TokenUsageExtractableMessage, getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
11
|
+
import { AISDKToolkit, AISDKToolkitOptions, AISDKToolkitToolsOptions, GenerativeToolsOptions, generativeTools } from "./tools/generativeTools.js";
|
|
12
|
+
import { AISDKChat, AISDKChatOptions } from "./runtime/AISDKChat.js";
|
|
13
|
+
import { AISDKThreads, AISDKThreadsOptions } from "./runtime/AISDKThreads.js";
|
|
14
|
+
export { AISDKChat, type AISDKChatOptions, AISDKThreads, type AISDKThreadsOptions, AISDKToolkit, type AISDKToolkitOptions, type AISDKToolkitToolsOptions, type AssistantChatResumableOptions, AssistantChatTransport, type FrontendTools, type GenerativeToolsOptions, RESUMABLE_STREAM_ID_HEADER, type ResumableClientStorage, type ThreadTokenUsage, type TokenUsageExtractableMessage, type UseChatRuntimeOptions, createResumableSessionStorage, frontendTools, generativeTools, getThreadMessageTokenUsage, injectQuoteContext, unstable_injectInteractableContext, useAISDKChat, useAISDKError, useAISDKRuntime, useChatRuntime, useThreadTokenUsage };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useAISDKChat, useAISDKError } from "./hooks.js";
|
|
2
|
+
import { useAISDKRuntime } from "./runtime/useAISDKRuntime.js";
|
|
3
|
+
import { RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage } from "./transport/resumable.js";
|
|
4
|
+
import { AssistantChatTransport } from "./transport/AssistantChatTransport.js";
|
|
5
|
+
import { useChatRuntime } from "./runtime/useChatRuntime.js";
|
|
6
|
+
import { frontendTools } from "./tools/frontendTools.js";
|
|
7
|
+
import { injectQuoteContext } from "./model-context/injectQuoteContext.js";
|
|
8
|
+
import { unstable_injectInteractableContext } from "./model-context/injectInteractableContext.js";
|
|
9
|
+
import { getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
10
|
+
import { AISDKChat } from "./runtime/AISDKChat.js";
|
|
11
|
+
import { AISDKToolkit, generativeTools } from "./tools/generativeTools.js";
|
|
12
|
+
import { AISDKThreads } from "./runtime/AISDKThreads.js";
|
|
13
|
+
export { AISDKChat, AISDKThreads, AISDKToolkit, AssistantChatTransport, RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage, frontendTools, generativeTools, getThreadMessageTokenUsage, injectQuoteContext, unstable_injectInteractableContext, useAISDKChat, useAISDKError, useAISDKRuntime, useChatRuntime, useThreadTokenUsage };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/// <reference types="@assistant-ui/core/react" />
|
|
2
|
+
import { useAISDKChat, useAISDKError } from "./hooks.js";
|
|
3
|
+
import { useAISDKRuntime } from "./runtime/useAISDKRuntime.js";
|
|
4
|
+
import { AssistantChatResumableOptions, RESUMABLE_STREAM_ID_HEADER, ResumableClientStorage, createResumableSessionStorage } from "./transport/resumable.js";
|
|
5
|
+
import { AssistantChatTransport } from "./transport/AssistantChatTransport.js";
|
|
6
|
+
import { UseChatRuntimeOptions, useChatRuntime } from "./runtime/useChatRuntime.js";
|
|
7
|
+
import { FrontendTools, frontendTools } from "./tools/frontendTools.js";
|
|
8
|
+
import { injectQuoteContext } from "./model-context/injectQuoteContext.js";
|
|
9
|
+
import { unstable_injectInteractableContext } from "./model-context/injectInteractableContext.js";
|
|
10
|
+
import { ThreadTokenUsage, TokenUsageExtractableMessage, getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
11
|
+
import { AISDKChat, AISDKChatOptions } from "./runtime/AISDKChat.js";
|
|
12
|
+
export { AISDKChat, type AISDKChatOptions, type AssistantChatResumableOptions, AssistantChatTransport, type FrontendTools, RESUMABLE_STREAM_ID_HEADER, type ResumableClientStorage, type ThreadTokenUsage, type TokenUsageExtractableMessage, type UseChatRuntimeOptions, createResumableSessionStorage, frontendTools, getThreadMessageTokenUsage, injectQuoteContext, unstable_injectInteractableContext, useAISDKChat, useAISDKError, useAISDKRuntime, useChatRuntime, useThreadTokenUsage };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useAISDKChat, useAISDKError } from "./hooks.js";
|
|
2
|
+
import { useAISDKRuntime } from "./runtime/useAISDKRuntime.js";
|
|
3
|
+
import { RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage } from "./transport/resumable.js";
|
|
4
|
+
import { AssistantChatTransport } from "./transport/AssistantChatTransport.js";
|
|
5
|
+
import { useChatRuntime } from "./runtime/useChatRuntime.js";
|
|
6
|
+
import { frontendTools } from "./tools/frontendTools.js";
|
|
7
|
+
import { injectQuoteContext } from "./model-context/injectQuoteContext.js";
|
|
8
|
+
import { unstable_injectInteractableContext } from "./model-context/injectInteractableContext.js";
|
|
9
|
+
import { getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
10
|
+
import { AISDKChat } from "./runtime/AISDKChat.js";
|
|
11
|
+
export { AISDKChat, AssistantChatTransport, RESUMABLE_STREAM_ID_HEADER, createResumableSessionStorage, frontendTools, getThreadMessageTokenUsage, injectQuoteContext, unstable_injectInteractableContext, useAISDKChat, useAISDKError, useAISDKRuntime, useChatRuntime, useThreadTokenUsage };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { UIMessage } from "ai";
|
|
2
|
+
import { Unstable_InteractableSnapshotEntry } from "@assistant-ui/core";
|
|
3
|
+
//#region src/model-context/injectInteractableContext.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Injects interactable state snapshots into messages as model-visible text.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors {@link injectQuoteContext}: reads the frozen snapshot stamped on a user
|
|
8
|
+
* message's `metadata.custom.interactables` (by the interactables scope at send
|
|
9
|
+
* time) and prepends a text part. Run this in your route handler before
|
|
10
|
+
* `convertToModelMessages`, which otherwise ignores `metadata.custom`.
|
|
11
|
+
*
|
|
12
|
+
* Wording is consumer-owned — pass `format` to control how each snapshot reads.
|
|
13
|
+
* A snapshot may originate from a user edit or an agent `update_*` call, so the
|
|
14
|
+
* default phrasing is neutral. Keep the instance id visible in custom wording:
|
|
15
|
+
* the model needs it to address the `update_*` tool's `id` parameter. A custom
|
|
16
|
+
* `format` must also handle entries with `partial: true`, whose `state` carries
|
|
17
|
+
* only the fields that changed since the model's last known state.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { convertToModelMessages, streamText } from "ai";
|
|
22
|
+
* import { unstable_injectInteractableContext } from "@assistant-ui/react-ai-sdk";
|
|
23
|
+
*
|
|
24
|
+
* export async function POST(req: Request) {
|
|
25
|
+
* const { messages } = await req.json();
|
|
26
|
+
* const result = streamText({
|
|
27
|
+
* model: myModel,
|
|
28
|
+
* messages: await convertToModelMessages(unstable_injectInteractableContext(messages)),
|
|
29
|
+
* });
|
|
30
|
+
* return result.toUIMessageStreamResponse();
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
declare function unstable_injectInteractableContext(messages: UIMessage[], format?: (item: Unstable_InteractableSnapshotEntry) => string): UIMessage[];
|
|
35
|
+
//#endregion
|
|
36
|
+
export { unstable_injectInteractableContext };
|
|
37
|
+
//# sourceMappingURL=injectInteractableContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"injectInteractableContext.d.ts","names":[],"sources":["../../src/model-context/injectInteractableContext.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAqCgB,mCACd,UAAU,aACV,UACE,MAAM,gDAEP"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { unstable_formatInteractableSnapshot, unstable_getInteractableSnapshots } from "@assistant-ui/core";
|
|
2
|
+
//#region src/model-context/injectInteractableContext.ts
|
|
3
|
+
/**
|
|
4
|
+
* Injects interactable state snapshots into messages as model-visible text.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors {@link injectQuoteContext}: reads the frozen snapshot stamped on a user
|
|
7
|
+
* message's `metadata.custom.interactables` (by the interactables scope at send
|
|
8
|
+
* time) and prepends a text part. Run this in your route handler before
|
|
9
|
+
* `convertToModelMessages`, which otherwise ignores `metadata.custom`.
|
|
10
|
+
*
|
|
11
|
+
* Wording is consumer-owned — pass `format` to control how each snapshot reads.
|
|
12
|
+
* A snapshot may originate from a user edit or an agent `update_*` call, so the
|
|
13
|
+
* default phrasing is neutral. Keep the instance id visible in custom wording:
|
|
14
|
+
* the model needs it to address the `update_*` tool's `id` parameter. A custom
|
|
15
|
+
* `format` must also handle entries with `partial: true`, whose `state` carries
|
|
16
|
+
* only the fields that changed since the model's last known state.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { convertToModelMessages, streamText } from "ai";
|
|
21
|
+
* import { unstable_injectInteractableContext } from "@assistant-ui/react-ai-sdk";
|
|
22
|
+
*
|
|
23
|
+
* export async function POST(req: Request) {
|
|
24
|
+
* const { messages } = await req.json();
|
|
25
|
+
* const result = streamText({
|
|
26
|
+
* model: myModel,
|
|
27
|
+
* messages: await convertToModelMessages(unstable_injectInteractableContext(messages)),
|
|
28
|
+
* });
|
|
29
|
+
* return result.toUIMessageStreamResponse();
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
function unstable_injectInteractableContext(messages, format = unstable_formatInteractableSnapshot) {
|
|
34
|
+
return messages.map((msg) => {
|
|
35
|
+
if (msg.role !== "user") return msg;
|
|
36
|
+
const items = unstable_getInteractableSnapshots(msg);
|
|
37
|
+
if (!items?.length) return msg;
|
|
38
|
+
const text = `${items.map(format).join("\n")}\n\n`;
|
|
39
|
+
if (msg.parts?.[0]?.type === "text" && msg.parts[0].text === text) return msg;
|
|
40
|
+
return {
|
|
41
|
+
...msg,
|
|
42
|
+
parts: [{
|
|
43
|
+
type: "text",
|
|
44
|
+
text
|
|
45
|
+
}, ...msg.parts ?? []]
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { unstable_injectInteractableContext };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=injectInteractableContext.js.map
|
|
@@ -0,0 +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/react-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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { UIMessage } from "ai";
|
|
2
|
+
//#region src/model-context/injectQuoteContext.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Injects quote context into messages as markdown blockquotes.
|
|
5
|
+
*
|
|
6
|
+
* Use this in your route handler before `convertToModelMessages` so the LLM
|
|
7
|
+
* sees the quoted text that the user is referring to.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { convertToModelMessages, streamText } from "ai";
|
|
12
|
+
* import { injectQuoteContext } from "@assistant-ui/react-ai-sdk";
|
|
13
|
+
*
|
|
14
|
+
* export async function POST(req: Request) {
|
|
15
|
+
* const { messages } = await req.json();
|
|
16
|
+
* const result = streamText({
|
|
17
|
+
* model: myModel,
|
|
18
|
+
* messages: await convertToModelMessages(injectQuoteContext(messages)),
|
|
19
|
+
* });
|
|
20
|
+
* return result.toUIMessageStreamResponse();
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
declare function injectQuoteContext(messages: UIMessage[]): UIMessage[];
|
|
25
|
+
//#endregion
|
|
26
|
+
export { injectQuoteContext };
|
|
27
|
+
//# sourceMappingURL=injectQuoteContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"injectQuoteContext.d.ts","names":[],"sources":["../../src/model-context/injectQuoteContext.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;iBAoCgB,mBAAmB,UAAU,cAAc"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//#region src/model-context/injectQuoteContext.ts
|
|
2
|
+
const getQuoteText = (metadata) => {
|
|
3
|
+
if (!metadata || typeof metadata !== "object") return void 0;
|
|
4
|
+
const custom = metadata.custom;
|
|
5
|
+
if (!custom || typeof custom !== "object") return void 0;
|
|
6
|
+
const quote = custom.quote;
|
|
7
|
+
if (!quote || typeof quote !== "object") return void 0;
|
|
8
|
+
const text = quote.text;
|
|
9
|
+
return typeof text === "string" ? text : void 0;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Injects quote context into messages as markdown blockquotes.
|
|
13
|
+
*
|
|
14
|
+
* Use this in your route handler before `convertToModelMessages` so the LLM
|
|
15
|
+
* sees the quoted text that the user is referring to.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { convertToModelMessages, streamText } from "ai";
|
|
20
|
+
* import { injectQuoteContext } from "@assistant-ui/react-ai-sdk";
|
|
21
|
+
*
|
|
22
|
+
* export async function POST(req: Request) {
|
|
23
|
+
* const { messages } = await req.json();
|
|
24
|
+
* const result = streamText({
|
|
25
|
+
* model: myModel,
|
|
26
|
+
* messages: await convertToModelMessages(injectQuoteContext(messages)),
|
|
27
|
+
* });
|
|
28
|
+
* return result.toUIMessageStreamResponse();
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
function injectQuoteContext(messages) {
|
|
33
|
+
return messages.map((msg) => {
|
|
34
|
+
if (msg.role !== "user") return msg;
|
|
35
|
+
const text = getQuoteText(msg.metadata);
|
|
36
|
+
if (!text) return msg;
|
|
37
|
+
const blockquote = text.split(/\r?\n/).map((line) => `> ${line}`).join("\n");
|
|
38
|
+
if (msg.parts?.[0]?.type === "text" && msg.parts[0].text === `${blockquote}\n\n`) return msg;
|
|
39
|
+
return {
|
|
40
|
+
...msg,
|
|
41
|
+
parts: [{
|
|
42
|
+
type: "text",
|
|
43
|
+
text: `${blockquote}\n\n`
|
|
44
|
+
}, ...msg.parts ?? []]
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { injectQuoteContext };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=injectQuoteContext.js.map
|
|
@@ -0,0 +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/react-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;;;;;;;;;;;;;;;;;;;;;;AAuBA,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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ChatThreadOptions } from "./useChatThread.js";
|
|
2
|
+
import { UIMessage } from "@ai-sdk/react";
|
|
3
|
+
//#region src/runtime/AISDKChat.d.ts
|
|
4
|
+
type AISDKChatOptions<UI_MESSAGE extends UIMessage = UIMessage> = ChatThreadOptions<UI_MESSAGE>;
|
|
5
|
+
/**
|
|
6
|
+
* `AuiConfig` entry that runs the AI SDK chat as the `threads` scope. Hosts the
|
|
7
|
+
* same orchestration as `useChatRuntime` inside the client's own resource tree,
|
|
8
|
+
* so it works with any `AssistantClient` host, React or not. Single thread; the
|
|
9
|
+
* multi-thread and assistant-cloud surface is {@link AISDKThreads}. The chat
|
|
10
|
+
* id is captured when the entry mounts, so a later `id` change in the options
|
|
11
|
+
* has no effect.
|
|
12
|
+
*/
|
|
13
|
+
declare const AISDKChat: <UI_MESSAGE extends UIMessage = UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>>(options?: AISDKChatOptions<UI_MESSAGE> | undefined) => import("@assistant-ui/tap").ResourceElement<import("@assistant-ui/store").ClientOutput<"threads">>;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { AISDKChat, AISDKChatOptions };
|
|
16
|
+
//# sourceMappingURL=AISDKChat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AISDKChat.d.ts","names":[],"sources":["../../src/runtime/AISDKChat.ts"],"mappings":";;;KAaY,iBAAiB,mBAAmB,YAAY,aAC1D,kBAAkB;;;;;;;;;cA8BP,YA5BS,mBAAmB,YAAS,gCAAA,0BAAA,UAAA,UAAA,iBAAA,wDAAA,8CAAA"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useChatThread } from "./useChatThread.js";
|
|
3
|
+
import { useState } from "@assistant-ui/tap/react-shim";
|
|
4
|
+
import { generateId } from "ai";
|
|
5
|
+
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
6
|
+
import { resource, useResource } from "@assistant-ui/tap";
|
|
7
|
+
import { RuntimeAdapter, runtimeAdapterTransformScopes } from "@assistant-ui/core/store";
|
|
8
|
+
import { attachTransformScopes } from "@assistant-ui/store/client";
|
|
9
|
+
//#region src/runtime/AISDKChat.ts
|
|
10
|
+
const useAISDKChat = (options) => {
|
|
11
|
+
const $ = c(11);
|
|
12
|
+
let t0;
|
|
13
|
+
if ($[0] !== options?.id) {
|
|
14
|
+
t0 = () => options?.id ?? generateId();
|
|
15
|
+
$[0] = options?.id;
|
|
16
|
+
$[1] = t0;
|
|
17
|
+
} else t0 = $[1];
|
|
18
|
+
const [id] = useState(t0);
|
|
19
|
+
let t1;
|
|
20
|
+
if ($[2] !== id) {
|
|
21
|
+
t1 = () => ({ initialize: async () => ({
|
|
22
|
+
remoteId: id,
|
|
23
|
+
externalId: void 0
|
|
24
|
+
}) });
|
|
25
|
+
$[2] = id;
|
|
26
|
+
$[3] = t1;
|
|
27
|
+
} else t1 = $[3];
|
|
28
|
+
const [threadListItem] = useState(t1);
|
|
29
|
+
let t2;
|
|
30
|
+
if ($[4] !== threadListItem) {
|
|
31
|
+
t2 = () => threadListItem;
|
|
32
|
+
$[4] = threadListItem;
|
|
33
|
+
$[5] = t2;
|
|
34
|
+
} else t2 = $[5];
|
|
35
|
+
let t3;
|
|
36
|
+
if ($[6] !== id || $[7] !== t2) {
|
|
37
|
+
t3 = {
|
|
38
|
+
id,
|
|
39
|
+
isMainThread: true,
|
|
40
|
+
getThreadListItem: t2,
|
|
41
|
+
stopOnClientDestroy: true
|
|
42
|
+
};
|
|
43
|
+
$[6] = id;
|
|
44
|
+
$[7] = t2;
|
|
45
|
+
$[8] = t3;
|
|
46
|
+
} else t3 = $[8];
|
|
47
|
+
const runtime = useChatThread(options, t3);
|
|
48
|
+
let t4;
|
|
49
|
+
if ($[9] !== runtime) {
|
|
50
|
+
t4 = RuntimeAdapter(runtime);
|
|
51
|
+
$[9] = runtime;
|
|
52
|
+
$[10] = t4;
|
|
53
|
+
} else t4 = $[10];
|
|
54
|
+
return useResource(t4);
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* `AuiConfig` entry that runs the AI SDK chat as the `threads` scope. Hosts the
|
|
58
|
+
* same orchestration as `useChatRuntime` inside the client's own resource tree,
|
|
59
|
+
* so it works with any `AssistantClient` host, React or not. Single thread; the
|
|
60
|
+
* multi-thread and assistant-cloud surface is {@link AISDKThreads}. The chat
|
|
61
|
+
* id is captured when the entry mounts, so a later `id` change in the options
|
|
62
|
+
* has no effect.
|
|
63
|
+
*/
|
|
64
|
+
const AISDKChat = resource(useAISDKChat);
|
|
65
|
+
attachTransformScopes(useAISDKChat, runtimeAdapterTransformScopes);
|
|
66
|
+
//#endregion
|
|
67
|
+
export { AISDKChat };
|
|
68
|
+
|
|
69
|
+
//# sourceMappingURL=AISDKChat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AISDKChat.js","names":["c","_c","resource","useResource","useState","generateId","UIMessage","RuntimeAdapter","runtimeAdapterTransformScopes","attachTransformScopes","useChatThread","ChatThreadOptions","AISDKChatOptions","UI_MESSAGE","useAISDKChat","options","$","t0","id","t1","initialize","remoteId","externalId","undefined","threadListItem","t2","t3","isMainThread","getThreadListItem","stopOnClientDestroy","runtime","t4","AISDKChat"],"sources":["../../src/runtime/AISDKChat.ts"],"sourcesContent":["\"use client\";\n\nimport { resource, useResource } from \"@assistant-ui/tap\";\nimport { useState } from \"react\";\nimport { generateId } from \"ai\";\nimport type { UIMessage } from \"@ai-sdk/react\";\nimport {\n RuntimeAdapter,\n runtimeAdapterTransformScopes,\n} from \"@assistant-ui/core/store\";\nimport { attachTransformScopes } from \"@assistant-ui/store/client\";\nimport { useChatThread, type ChatThreadOptions } from \"./useChatThread\";\n\nexport type AISDKChatOptions<UI_MESSAGE extends UIMessage = UIMessage> =\n ChatThreadOptions<UI_MESSAGE>;\n\nconst useAISDKChat = <UI_MESSAGE extends UIMessage = UIMessage>(\n options?: AISDKChatOptions<UI_MESSAGE>,\n) => {\n const [id] = useState(() => options?.id ?? generateId());\n // The transport resolves the request id from the thread list item, falling\n // back to the runtime's main item, whose id here is the external store's\n // placeholder constant. The single thread of this entry is the chat itself,\n // so the handed-over item initializes to the chat id.\n const [threadListItem] = useState(() => ({\n initialize: async () => ({ remoteId: id, externalId: undefined }),\n }));\n const runtime = useChatThread(options, {\n id,\n isMainThread: true,\n getThreadListItem: () => threadListItem,\n stopOnClientDestroy: true,\n });\n return useResource(RuntimeAdapter(runtime));\n};\n\n/**\n * `AuiConfig` entry that runs the AI SDK chat as the `threads` scope. Hosts the\n * same orchestration as `useChatRuntime` inside the client's own resource tree,\n * so it works with any `AssistantClient` host, React or not. Single thread; the\n * multi-thread and assistant-cloud surface is {@link AISDKThreads}. The chat\n * id is captured when the entry mounts, so a later `id` change in the options\n * has no effect.\n */\nexport const AISDKChat = resource(useAISDKChat);\n\nattachTransformScopes(useAISDKChat, runtimeAdapterTransformScopes);\n"],"mappings":";;;;;;;;;AAgBA,MAAMc,gBAAeC,YAAA;CAAA,MAAAC,IAAAf,EAAA,EAAA;CAAA,IAAAgB;CAAA,IAAAD,EAAA,OAAAD,SAAAG,IAAA;EAGGD,WAAMF,SAAOG,MAAQb,WAAW;EAACW,EAAA,KAAAD,SAAAG;EAAAF,EAAA,KAAAC;CAAA,OAAAA,KAAAD,EAAA;CAAvD,MAAA,CAAAE,MAAad,SAASa,EAAiC;CAAE,IAAAE;CAAA,IAAAH,EAAA,OAAAE,IAAA;EAKvBC,YAAO,EAAAC,YAC3B,aAAa;GAAAC,UAAYH;GAAEI,YAAcC,KAAAA;EAAU,GACjE;EAAEP,EAAA,KAAAE;EAAAF,EAAA,KAAAG;CAAA,OAAAA,KAAAH,EAAA;CAFF,MAAA,CAAAQ,kBAAyBpB,SAASe,EAEhC;CAAE,IAAAM;CAAA,IAAAT,EAAA,OAAAQ,gBAAA;EAIiBC,WAAMD;EAAcR,EAAA,KAAAQ;EAAAR,EAAA,KAAAS;CAAA,OAAAA,KAAAT,EAAA;CAAA,IAAAU;CAAA,IAAAV,EAAA,OAAAE,MAAAF,EAAA,OAAAS,IAAA;EAHFC,KAAA;GAAAR;GAAAS,cAEvB;GAAIC,mBACCH;GAAoBI,qBAClB;EACvB;EAACb,EAAA,KAAAE;EAAAF,EAAA,KAAAS;EAAAT,EAAA,KAAAU;CAAA,OAAAA,KAAAV,EAAA;CALD,MAAAc,UAAgBpB,cAAcK,SAASW,EAKtC;CAAE,IAAAK;CAAA,IAAAf,EAAA,OAAAc,SAAA;EACgBC,KAAAxB,eAAeuB,OAAO;EAACd,EAAA,KAAAc;EAAAd,EAAA,MAAAe;CAAA,OAAAA,KAAAf,EAAA;CAAA,OAAnCb,YAAY4B,EAAuB;AAAC;;;;;;;;;AAW7C,MAAaC,YAAY9B,SAASY,YAAY;AAE9CL,sBAAsBK,cAAcN,6BAA6B"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ChatThreadOptions } from "./useChatThread.js";
|
|
2
|
+
import { ChatTransport } from "ai";
|
|
3
|
+
import { UIMessage as UIMessage$1 } from "@ai-sdk/react";
|
|
4
|
+
import { AssistantCloud } from "assistant-cloud";
|
|
5
|
+
//#region src/runtime/AISDKThreads.d.ts
|
|
6
|
+
type AISDKThreadsOptions<UI_MESSAGE extends UIMessage$1 = UIMessage$1> = Omit<ChatThreadOptions<UI_MESSAGE>, "id" | "transport" | "messages"> & {
|
|
7
|
+
/**
|
|
8
|
+
* The transport threads send through. A factory is invoked once per
|
|
9
|
+
* thread so each thread owns its instance. A plain
|
|
10
|
+
* `AssistantChatTransport` instance is cloned per thread (its
|
|
11
|
+
* assistant-ui wiring is per thread); any other transport instance is
|
|
12
|
+
* shared as-is. Defaults to one `AssistantChatTransport` per thread.
|
|
13
|
+
*/
|
|
14
|
+
transport?: ChatTransport<UI_MESSAGE> | (() => ChatTransport<UI_MESSAGE>) | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* When set, the thread list is a `RemoteThreadList` backed by this
|
|
17
|
+
* assistant-cloud. Omit it to keep the in-memory list. The thread
|
|
18
|
+
* factory is keyed so cloud history reloads on a switch, and an
|
|
19
|
+
* in-flight run does not continue in the background.
|
|
20
|
+
*/
|
|
21
|
+
cloud?: AssistantCloud | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Controlled thread id for the cloud list. Ignored without `cloud`.
|
|
24
|
+
*/
|
|
25
|
+
threadId?: string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Called with the settled remote id when the cloud list changes thread.
|
|
28
|
+
*/
|
|
29
|
+
onThreadIdChange?: ((threadId: string | undefined) => void) | undefined;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* `AuiConfig` entry that runs one AI SDK chat per thread. Hosts the same
|
|
33
|
+
* per-thread orchestration as {@link AISDKChat} inside the client's own
|
|
34
|
+
* resource tree, so it works with any `AssistantClient` host, React or not.
|
|
35
|
+
* Without `cloud`, threads live in memory for the client's lifetime and keep
|
|
36
|
+
* their history across switches; each thread's chat id is its thread id.
|
|
37
|
+
* With `cloud`, the list is a `RemoteThreadList` and the factory is keyed so
|
|
38
|
+
* cloud history reloads on a switch. The store entry mounts only the visible
|
|
39
|
+
* thread, so a switch cancels an in-flight run. Model context is
|
|
40
|
+
* registered on the visible thread only.
|
|
41
|
+
*/
|
|
42
|
+
declare const AISDKThreads: <UI_MESSAGE extends UIMessage$1 = UIMessage$1<unknown, import("ai").UIDataTypes, import("ai").UITools>>(options?: AISDKThreadsOptions<UI_MESSAGE> | undefined) => import("@assistant-ui/tap").ResourceElement<import("@assistant-ui/store").ClientOutput<"threads">>;
|
|
43
|
+
//#endregion
|
|
44
|
+
export { AISDKThreads, AISDKThreadsOptions };
|
|
45
|
+
//# sourceMappingURL=AISDKThreads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AISDKThreads.d.ts","names":[],"sources":["../../src/runtime/AISDKThreads.ts"],"mappings":";;;;;KA4BY,oBAAoB,mBAAmB,cAAY,eAC7D,KAAK,kBAAkB;;;;;;;;EAQrB,YACI,cAAc,qBACP,cAAc;;;;;;;EAQzB,QAAQ;;;;EAIR;;;;EAIA,qBAAqB;;;;;;;;;;;;;cAqKZ,eAxDY,mBAAmB,cAAS,kCAAA,0BAAA,UAAA,UAAA,oBAAA,wDAAA,8CAAA"}
|