@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,7 @@
|
|
|
1
|
+
import { UIMessage } from "ai";
|
|
2
|
+
import { ThreadMessage } from "@assistant-ui/core";
|
|
3
|
+
//#region src/utils/getVercelAIMessages.d.ts
|
|
4
|
+
declare const getVercelAIMessages: <UI_MESSAGE extends UIMessage = UIMessage>(message: ThreadMessage) => UI_MESSAGE[];
|
|
5
|
+
//#endregion
|
|
6
|
+
export { getVercelAIMessages };
|
|
7
|
+
//# sourceMappingURL=getVercelAIMessages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getVercelAIMessages.d.ts","names":[],"sources":["../../src/utils/getVercelAIMessages.ts"],"mappings":";;;cAMa,sBAAuB,mBAAmB,YAAY,WACjE,SAAS,kBAEmC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { getExternalStoreMessages } from "@assistant-ui/core";
|
|
2
|
+
//#region src/utils/getVercelAIMessages.ts
|
|
3
|
+
const getVercelAIMessages = (message) => {
|
|
4
|
+
return getExternalStoreMessages(message);
|
|
5
|
+
};
|
|
6
|
+
//#endregion
|
|
7
|
+
export { getVercelAIMessages };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=getVercelAIMessages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getVercelAIMessages.js","names":["getExternalStoreMessages","ThreadMessage","UIMessage","getVercelAIMessages","message","UI_MESSAGE"],"sources":["../../src/utils/getVercelAIMessages.ts"],"sourcesContent":["import {\n getExternalStoreMessages,\n type ThreadMessage,\n} from \"@assistant-ui/core\";\nimport type { UIMessage } from \"ai\";\n\nexport const getVercelAIMessages = <UI_MESSAGE extends UIMessage = UIMessage>(\n message: ThreadMessage,\n) => {\n return getExternalStoreMessages(message) as UI_MESSAGE[];\n};\n"],"mappings":";;AAMA,MAAaG,uBACXC,YACG;CACH,OAAOJ,yBAAyBI,OAAO;AACzC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { UIMessage } from "ai";
|
|
2
|
+
//#region src/utils/sliceMessagesUntil.d.ts
|
|
3
|
+
declare const sliceMessagesUntil: <UI_MESSAGE extends UIMessage = UIMessage>(messages: UI_MESSAGE[], messageId: string | null) => UI_MESSAGE[];
|
|
4
|
+
//#endregion
|
|
5
|
+
export { sliceMessagesUntil };
|
|
6
|
+
//# sourceMappingURL=sliceMessagesUntil.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sliceMessagesUntil.d.ts","names":[],"sources":["../../src/utils/sliceMessagesUntil.ts"],"mappings":";;cAEa,qBAAsB,mBAAmB,YAAY,WAChE,UAAU,cACV,6BAAwB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/utils/sliceMessagesUntil.ts
|
|
2
|
+
const sliceMessagesUntil = (messages, messageId) => {
|
|
3
|
+
if (messageId == null) return [];
|
|
4
|
+
let messageIdx = messages.findIndex((m) => m.id === messageId);
|
|
5
|
+
if (messageIdx === -1) throw new Error(`sliceMessagesUntil: Message "${messageId}" not found in AI SDK messages. This is likely an internal bug in assistant-ui.`);
|
|
6
|
+
while (messages[messageIdx + 1]?.role === "assistant") messageIdx++;
|
|
7
|
+
return messages.slice(0, messageIdx + 1);
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { sliceMessagesUntil };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=sliceMessagesUntil.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sliceMessagesUntil.js","names":["UIMessage","sliceMessagesUntil","messages","UI_MESSAGE","messageId","messageIdx","findIndex","m","id","Error","role","slice"],"sources":["../../src/utils/sliceMessagesUntil.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\n\nexport const sliceMessagesUntil = <UI_MESSAGE extends UIMessage = UIMessage>(\n messages: UI_MESSAGE[],\n messageId: string | null,\n) => {\n if (messageId == null) return [];\n\n let messageIdx = messages.findIndex((m) => m.id === messageId);\n if (messageIdx === -1)\n throw new Error(\n `sliceMessagesUntil: Message \"${messageId}\" not found in AI SDK messages. This is likely an internal bug in assistant-ui.`,\n );\n\n while (messages[messageIdx + 1]?.role === \"assistant\") {\n messageIdx++;\n }\n\n return messages.slice(0, messageIdx + 1);\n};\n"],"mappings":";AAEA,MAAaC,sBACXC,UACAE,cACG;CACH,IAAIA,aAAa,MAAM,OAAO,CAAA;CAE9B,IAAIC,aAAaH,SAASI,WAAWC,MAAMA,EAAEC,OAAOJ,SAAS;CAC7D,IAAIC,eAAe,IACjB,MAAM,IAAII,MACR,gCAAgCL,UAAS,gFAC3C;CAEF,OAAOF,SAASG,aAAa,EAAE,EAAEK,SAAS,aACxCL;CAGF,OAAOH,SAASS,MAAM,GAAGN,aAAa,CAAC;AACzC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@assistant-ui/ai-sdk",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Vercel AI SDK adapter for assistant-ui",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai-sdk",
|
|
7
|
+
"vercel",
|
|
8
|
+
"assistant-ui",
|
|
9
|
+
"react",
|
|
10
|
+
"ai",
|
|
11
|
+
"chat",
|
|
12
|
+
"openai",
|
|
13
|
+
"streaming"
|
|
14
|
+
],
|
|
15
|
+
"author": "AgentbaseAI Inc.",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"type": "module",
|
|
18
|
+
"imports": {
|
|
19
|
+
"#mcp-stdio": {
|
|
20
|
+
"types": "./src/tools/mcp-stdio.node.ts",
|
|
21
|
+
"react-native": "./dist/tools/mcp-stdio.unsupported.js",
|
|
22
|
+
"edge-light": "./dist/tools/mcp-stdio.unsupported.js",
|
|
23
|
+
"workerd": "./dist/tools/mcp-stdio.unsupported.js",
|
|
24
|
+
"browser": "./dist/tools/mcp-stdio.unsupported.js",
|
|
25
|
+
"node": "./dist/tools/mcp-stdio.node.js",
|
|
26
|
+
"default": "./dist/tools/mcp-stdio.unsupported.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"react-native": {
|
|
32
|
+
"types": "./dist/index.native.d.ts",
|
|
33
|
+
"default": "./dist/index.native.js"
|
|
34
|
+
},
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"default": "./dist/index.js"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"main": "./dist/index.js",
|
|
40
|
+
"react-native": "./dist/index.native.js",
|
|
41
|
+
"types": "./dist/index.d.ts",
|
|
42
|
+
"files": [
|
|
43
|
+
"dist",
|
|
44
|
+
"src",
|
|
45
|
+
"README.md"
|
|
46
|
+
],
|
|
47
|
+
"sideEffects": false,
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@ai-sdk/mcp": "^2.0.31",
|
|
50
|
+
"@ai-sdk/react": "^4.0.65",
|
|
51
|
+
"@assistant-ui/core": "^0.3.14",
|
|
52
|
+
"@assistant-ui/store": "^0.3.10",
|
|
53
|
+
"@assistant-ui/tap": "^0.9.13",
|
|
54
|
+
"ai": "^7.0.62",
|
|
55
|
+
"assistant-cloud": "*",
|
|
56
|
+
"assistant-stream": "^0.3.38"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"@types/react": "*",
|
|
60
|
+
"react": "^18 || ^19"
|
|
61
|
+
},
|
|
62
|
+
"peerDependenciesMeta": {
|
|
63
|
+
"@types/react": {
|
|
64
|
+
"optional": true
|
|
65
|
+
},
|
|
66
|
+
"react": {
|
|
67
|
+
"optional": true
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@testing-library/react": "^16.3.2",
|
|
72
|
+
"@types/json-schema": "^7.0.15",
|
|
73
|
+
"@types/react": "^19.2.18",
|
|
74
|
+
"@types/react-dom": "^19.2.4",
|
|
75
|
+
"jsdom": "^30.0.1",
|
|
76
|
+
"react": "^19.2.8",
|
|
77
|
+
"vitest": "^4.1.10",
|
|
78
|
+
"@assistant-ui/x-buildutils": "0.0.23"
|
|
79
|
+
},
|
|
80
|
+
"publishConfig": {
|
|
81
|
+
"access": "public",
|
|
82
|
+
"provenance": true
|
|
83
|
+
},
|
|
84
|
+
"homepage": "https://www.assistant-ui.com/",
|
|
85
|
+
"repository": {
|
|
86
|
+
"type": "git",
|
|
87
|
+
"url": "git+https://github.com/assistant-ui/assistant-ui.git",
|
|
88
|
+
"directory": "packages/ai-sdk"
|
|
89
|
+
},
|
|
90
|
+
"bugs": {
|
|
91
|
+
"url": "https://github.com/assistant-ui/assistant-ui/issues"
|
|
92
|
+
},
|
|
93
|
+
"scripts": {
|
|
94
|
+
"build": "aui-build",
|
|
95
|
+
"test": "vitest run",
|
|
96
|
+
"test:react-compiler": "vitest run --config vitest.react-compiler.config.ts",
|
|
97
|
+
"test:standalone": "vitest run --project standalone",
|
|
98
|
+
"test:watch": "vitest"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { flushTapSync } from "@assistant-ui/tap";
|
|
3
|
+
import { AuiConfig, createAssistantClient } from "@assistant-ui/store/client";
|
|
4
|
+
import * as aiSdk from "../index";
|
|
5
|
+
import { createControlledTransport } from "../runtime/__tests__/controlled-transport";
|
|
6
|
+
|
|
7
|
+
describe("react-less standalone graph", () => {
|
|
8
|
+
it("resolves react to the standalone shim", async () => {
|
|
9
|
+
const react = await import("react");
|
|
10
|
+
expect(() => react.useState(0)).toThrow(/standalone-shim/);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("loads the whole barrel under the standalone shim", () => {
|
|
14
|
+
expect(typeof aiSdk.AISDKChat).toBe("function");
|
|
15
|
+
expect(typeof aiSdk.useChatRuntime).toBe("function");
|
|
16
|
+
expect(typeof aiSdk.useAISDKRuntime).toBe("function");
|
|
17
|
+
expect(typeof aiSdk.frontendTools).toBe("function");
|
|
18
|
+
expect(typeof aiSdk.AssistantChatTransport).toBe("function");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("streams a chat round trip with the shim as the only react", async () => {
|
|
22
|
+
const { transport, emit, close } = createControlledTransport();
|
|
23
|
+
const handle = createAssistantClient(
|
|
24
|
+
AuiConfig({ threads: aiSdk.AISDKChat({ transport }) }),
|
|
25
|
+
);
|
|
26
|
+
try {
|
|
27
|
+
handle.subscribe(() => {});
|
|
28
|
+
const aui = handle.getClient();
|
|
29
|
+
|
|
30
|
+
flushTapSync(() => aui.composer.setText("hi"));
|
|
31
|
+
flushTapSync(() => aui.composer.send());
|
|
32
|
+
|
|
33
|
+
await vi.waitFor(() => {
|
|
34
|
+
expect(aui.thread.getState().isRunning).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
emit(
|
|
38
|
+
{ type: "start" },
|
|
39
|
+
{ type: "text-start", id: "t1" },
|
|
40
|
+
{ type: "text-delta", id: "t1", delta: "hello " },
|
|
41
|
+
{ type: "text-delta", id: "t1", delta: "world" },
|
|
42
|
+
{ type: "text-end", id: "t1" },
|
|
43
|
+
{ type: "finish" },
|
|
44
|
+
);
|
|
45
|
+
close();
|
|
46
|
+
|
|
47
|
+
await vi.waitFor(() => {
|
|
48
|
+
const state = aui.thread.getState();
|
|
49
|
+
expect(state.isRunning).toBe(false);
|
|
50
|
+
expect(state.messages).toHaveLength(2);
|
|
51
|
+
expect(state.messages.at(-1)?.content).toContainEqual(
|
|
52
|
+
expect.objectContaining({ type: "text", text: "hello world" }),
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
} finally {
|
|
56
|
+
handle.destroy();
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { UIMessage } from "ai";
|
|
2
|
+
import type {
|
|
3
|
+
MessageFormatAdapter,
|
|
4
|
+
MessageFormatItem,
|
|
5
|
+
MessageStorageEntry,
|
|
6
|
+
} from "@assistant-ui/core";
|
|
7
|
+
|
|
8
|
+
// Storage format for AI SDK messages - just the UIMessage
|
|
9
|
+
export type AISDKStorageFormat = Omit<UIMessage, "id">;
|
|
10
|
+
|
|
11
|
+
export const aiSDKV6FormatAdapter: MessageFormatAdapter<
|
|
12
|
+
UIMessage,
|
|
13
|
+
AISDKStorageFormat
|
|
14
|
+
> = {
|
|
15
|
+
format: "ai-sdk/v6",
|
|
16
|
+
|
|
17
|
+
encode({
|
|
18
|
+
message: { id, parts, ...message },
|
|
19
|
+
}: MessageFormatItem<UIMessage>): AISDKStorageFormat {
|
|
20
|
+
return {
|
|
21
|
+
...message,
|
|
22
|
+
parts,
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
decode(
|
|
27
|
+
stored: MessageStorageEntry<AISDKStorageFormat>,
|
|
28
|
+
): MessageFormatItem<UIMessage> {
|
|
29
|
+
return {
|
|
30
|
+
parentId: stored.parent_id,
|
|
31
|
+
message: {
|
|
32
|
+
id: stored.id,
|
|
33
|
+
...stored.content,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
getId(message: UIMessage): string {
|
|
39
|
+
return message.id;
|
|
40
|
+
},
|
|
41
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { vercelAttachmentAdapter } from "./vercelAttachmentAdapter";
|
|
3
|
+
|
|
4
|
+
const originalFileReader = globalThis.FileReader;
|
|
5
|
+
|
|
6
|
+
afterEach(() => {
|
|
7
|
+
globalThis.FileReader = originalFileReader;
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
describe("vercelAttachmentAdapter", () => {
|
|
11
|
+
it("sends a file as a data URL via the shared core encoder", async () => {
|
|
12
|
+
globalThis.FileReader = undefined as unknown as typeof FileReader;
|
|
13
|
+
|
|
14
|
+
const file = new File(["hello"], "a.txt", { type: "text/plain" });
|
|
15
|
+
const result = await vercelAttachmentAdapter.send({
|
|
16
|
+
id: "1",
|
|
17
|
+
type: "file",
|
|
18
|
+
name: file.name,
|
|
19
|
+
file,
|
|
20
|
+
contentType: file.type,
|
|
21
|
+
content: [],
|
|
22
|
+
status: { type: "requires-action", reason: "composer-send" },
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const part = result.content[0];
|
|
26
|
+
if (part?.type !== "file") throw new Error("expected file content part");
|
|
27
|
+
expect(part.data).toBe("data:text/plain;base64,aGVsbG8=");
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { AttachmentAdapter } from "@assistant-ui/core";
|
|
2
|
+
import { getFileDataURL } from "@assistant-ui/core/internal";
|
|
3
|
+
import { generateId } from "ai";
|
|
4
|
+
|
|
5
|
+
export const vercelAttachmentAdapter: AttachmentAdapter = {
|
|
6
|
+
accept: "*",
|
|
7
|
+
async add({ file }) {
|
|
8
|
+
return {
|
|
9
|
+
id: generateId(),
|
|
10
|
+
type: file.type.startsWith("image/") ? "image" : "file",
|
|
11
|
+
name: file.name,
|
|
12
|
+
file,
|
|
13
|
+
contentType: file.type,
|
|
14
|
+
content: [],
|
|
15
|
+
status: { type: "requires-action", reason: "composer-send" },
|
|
16
|
+
};
|
|
17
|
+
},
|
|
18
|
+
async send(attachment) {
|
|
19
|
+
// noop
|
|
20
|
+
return {
|
|
21
|
+
...attachment,
|
|
22
|
+
status: { type: "complete" },
|
|
23
|
+
content: [
|
|
24
|
+
{
|
|
25
|
+
type: "file",
|
|
26
|
+
mimeType: attachment.contentType ?? "",
|
|
27
|
+
filename: attachment.name,
|
|
28
|
+
data: await getFileDataURL(attachment.file),
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
async remove() {
|
|
34
|
+
// noop
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createRuntimeExtras } from "@assistant-ui/core/react";
|
|
2
|
+
import type { UseChatHelpers } from "@ai-sdk/react";
|
|
3
|
+
import type { UIMessage } from "ai";
|
|
4
|
+
|
|
5
|
+
export type AISDKRuntimeExtras = {
|
|
6
|
+
chat: UseChatHelpers<UIMessage>;
|
|
7
|
+
error: Error | undefined;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const aiSDKExtras =
|
|
11
|
+
createRuntimeExtras<AISDKRuntimeExtras>("useAISDKRuntime");
|