@assistant-ui/react-ai-sdk 0.11.5 → 1.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/README.md +7 -7
- package/dist/ui/getVercelAIMessages.d.ts +1 -1
- package/dist/ui/getVercelAIMessages.d.ts.map +1 -1
- package/dist/ui/getVercelAIMessages.js.map +1 -1
- package/dist/ui/use-chat/useAISDKRuntime.d.ts +2 -2
- package/dist/ui/use-chat/useAISDKRuntime.d.ts.map +1 -1
- package/dist/ui/use-chat/useAISDKRuntime.js +16 -7
- package/dist/ui/use-chat/useAISDKRuntime.js.map +1 -1
- package/dist/ui/use-chat/useExternalHistory.js +2 -2
- package/dist/ui/use-chat/useExternalHistory.js.map +1 -1
- package/dist/ui/utils/sliceMessagesUntil.d.ts +1 -1
- package/dist/ui/utils/sliceMessagesUntil.d.ts.map +1 -1
- package/dist/ui/utils/sliceMessagesUntil.js.map +1 -1
- package/dist/ui/utils/toCreateMessage.d.ts +1 -1
- package/dist/ui/utils/toCreateMessage.d.ts.map +1 -1
- package/dist/ui/utils/toCreateMessage.js.map +1 -1
- package/package.json +3 -3
- package/src/ui/getVercelAIMessages.tsx +4 -2
- package/src/ui/use-chat/useAISDKRuntime.tsx +31 -14
- package/src/ui/use-chat/useExternalHistory.tsx +2 -2
- package/src/ui/utils/sliceMessagesUntil.tsx +2 -2
- package/src/ui/utils/toCreateMessage.ts +3 -3
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ import { AssistantRuntimeProvider } from '@assistant-ui/react';
|
|
|
19
19
|
function App() {
|
|
20
20
|
// By default, uses AssistantChatTransport which forwards system messages and tools
|
|
21
21
|
const runtime = useChatRuntime();
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
return (
|
|
24
24
|
<AssistantRuntimeProvider runtime={runtime}>
|
|
25
25
|
{/* Your assistant UI components */}
|
|
@@ -33,20 +33,20 @@ function App() {
|
|
|
33
33
|
When you need to customize the transport configuration:
|
|
34
34
|
|
|
35
35
|
```typescript
|
|
36
|
-
import { DefaultChatTransport } from
|
|
37
|
-
import { AssistantChatTransport } from
|
|
38
|
-
import { useChatRuntime } from
|
|
36
|
+
import { DefaultChatTransport } from "ai";
|
|
37
|
+
import { AssistantChatTransport } from "@assistant-ui/react-ai-sdk";
|
|
38
|
+
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
|
|
39
39
|
|
|
40
40
|
// Custom API URL while keeping system/tools forwarding
|
|
41
41
|
const runtime = useChatRuntime({
|
|
42
42
|
transport: new AssistantChatTransport({
|
|
43
|
-
api:
|
|
44
|
-
})
|
|
43
|
+
api: "/my-custom-api/chat",
|
|
44
|
+
}),
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
// Or disable system/tools forwarding entirely
|
|
48
48
|
const runtime = useChatRuntime({
|
|
49
|
-
transport: new DefaultChatTransport()
|
|
49
|
+
transport: new DefaultChatTransport(),
|
|
50
50
|
});
|
|
51
51
|
```
|
|
52
52
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type ThreadMessage } from "@assistant-ui/react";
|
|
2
2
|
import type { UIMessage } from "ai";
|
|
3
|
-
export declare const getVercelAIMessages: (message: ThreadMessage) =>
|
|
3
|
+
export declare const getVercelAIMessages: <UI_MESSAGE extends UIMessage = UIMessage>(message: ThreadMessage) => UI_MESSAGE[];
|
|
4
4
|
//# sourceMappingURL=getVercelAIMessages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getVercelAIMessages.d.ts","sourceRoot":"","sources":["../../src/ui/getVercelAIMessages.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEpC,eAAO,MAAM,mBAAmB,GAAI,SAAS,
|
|
1
|
+
{"version":3,"file":"getVercelAIMessages.d.ts","sourceRoot":"","sources":["../../src/ui/getVercelAIMessages.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEpC,eAAO,MAAM,mBAAmB,GAAI,UAAU,SAAS,SAAS,GAAG,SAAS,EAC1E,SAAS,aAAa,KAEsB,UAAU,EACvD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ui/getVercelAIMessages.tsx"],"sourcesContent":["import {\n getExternalStoreMessages,\n type ThreadMessage,\n} from \"@assistant-ui/react\";\nimport type { UIMessage } from \"ai\";\n\nexport const getVercelAIMessages = (message: ThreadMessage) => {\n return getExternalStoreMessages(message) as
|
|
1
|
+
{"version":3,"sources":["../../src/ui/getVercelAIMessages.tsx"],"sourcesContent":["import {\n getExternalStoreMessages,\n type ThreadMessage,\n} from \"@assistant-ui/react\";\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":";AAAA;AAAA,EACE;AAAA,OAEK;AAGA,IAAM,sBAAsB,CACjC,YACG;AACH,SAAO,yBAAyB,OAAO;AACzC;","names":[]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { useChat } from "@ai-sdk/react";
|
|
1
|
+
import type { UIMessage, useChat } from "@ai-sdk/react";
|
|
2
2
|
import { ExternalStoreAdapter, ThreadHistoryAdapter, AssistantRuntime } from "@assistant-ui/react";
|
|
3
3
|
export type AISDKRuntimeAdapter = {
|
|
4
4
|
adapters?: (NonNullable<ExternalStoreAdapter["adapters"]> & {
|
|
5
5
|
history?: ThreadHistoryAdapter | undefined;
|
|
6
6
|
}) | undefined;
|
|
7
7
|
};
|
|
8
|
-
export declare const useAISDKRuntime: (chatHelpers: ReturnType<typeof useChat
|
|
8
|
+
export declare const useAISDKRuntime: <UI_MESSAGE extends UIMessage = UIMessage>(chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>, adapter?: AISDKRuntimeAdapter) => AssistantRuntime;
|
|
9
9
|
//# sourceMappingURL=useAISDKRuntime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAISDKRuntime.d.ts","sourceRoot":"","sources":["../../../src/ui/use-chat/useAISDKRuntime.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"useAISDKRuntime.d.ts","sourceRoot":"","sources":["../../../src/ui/use-chat/useAISDKRuntime.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAEL,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAGjB,MAAM,qBAAqB,CAAC;AAa7B,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EACL,CAAC,WAAW,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC,GAAG;QAC/C,OAAO,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;KAC5C,CAAC,GACF,SAAS,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,UAAU,SAAS,SAAS,GAAG,SAAS,EACtE,aAAa,UAAU,CAAC,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,EACnD,UAAS,mBAAwB,qBA2ElC,CAAC"}
|
|
@@ -9,19 +9,26 @@ import { toCreateMessage } from "../utils/toCreateMessage.js";
|
|
|
9
9
|
import { vercelAttachmentAdapter } from "../utils/vercelAttachmentAdapter.js";
|
|
10
10
|
import { getVercelAIMessages } from "../getVercelAIMessages.js";
|
|
11
11
|
import { AISDKMessageConverter } from "../utils/convertMessage.js";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
aiSDKV5FormatAdapter
|
|
14
|
+
} from "../adapters/aiSDKFormatAdapter.js";
|
|
13
15
|
import { useExternalHistory } from "./useExternalHistory.js";
|
|
16
|
+
import { useMemo } from "react";
|
|
14
17
|
var useAISDKRuntime = (chatHelpers, adapter = {}) => {
|
|
15
18
|
const messages = AISDKMessageConverter.useThreadMessages({
|
|
16
19
|
isRunning: chatHelpers.status === "submitted" || chatHelpers.status == "streaming",
|
|
17
20
|
messages: chatHelpers.messages
|
|
18
21
|
});
|
|
19
22
|
const isLoading = useExternalHistory(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
useMemo(
|
|
24
|
+
() => ({
|
|
25
|
+
get current() {
|
|
26
|
+
return runtime;
|
|
27
|
+
}
|
|
28
|
+
}),
|
|
29
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
30
|
+
[]
|
|
31
|
+
),
|
|
25
32
|
adapter.adapters?.history,
|
|
26
33
|
AISDKMessageConverter.toThreadMessages,
|
|
27
34
|
aiSDKV5FormatAdapter,
|
|
@@ -32,7 +39,9 @@ var useAISDKRuntime = (chatHelpers, adapter = {}) => {
|
|
|
32
39
|
const runtime = useExternalStoreRuntime({
|
|
33
40
|
isRunning: chatHelpers.status === "submitted" || chatHelpers.status === "streaming",
|
|
34
41
|
messages,
|
|
35
|
-
setMessages: (messages2) => chatHelpers.setMessages(
|
|
42
|
+
setMessages: (messages2) => chatHelpers.setMessages(
|
|
43
|
+
messages2.map(getVercelAIMessages).flat()
|
|
44
|
+
),
|
|
36
45
|
onCancel: async () => chatHelpers.stop(),
|
|
37
46
|
onNew: async (message) => {
|
|
38
47
|
const createMessage = await toCreateMessage(message);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/ui/use-chat/useAISDKRuntime.tsx"],"sourcesContent":["\"use client\";\n\nimport type { useChat } from \"@ai-sdk/react\";\nimport {\n useExternalStoreRuntime,\n ExternalStoreAdapter,\n ThreadHistoryAdapter,\n AssistantRuntime,\n} from \"@assistant-ui/react\";\nimport { sliceMessagesUntil } from \"../utils/sliceMessagesUntil\";\nimport { toCreateMessage } from \"../utils/toCreateMessage\";\nimport { vercelAttachmentAdapter } from \"../utils/vercelAttachmentAdapter\";\nimport { getVercelAIMessages } from \"../getVercelAIMessages\";\nimport { AISDKMessageConverter } from \"../utils/convertMessage\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/use-chat/useAISDKRuntime.tsx"],"sourcesContent":["\"use client\";\n\nimport type { UIMessage, useChat } from \"@ai-sdk/react\";\nimport {\n useExternalStoreRuntime,\n ExternalStoreAdapter,\n ThreadHistoryAdapter,\n AssistantRuntime,\n ThreadMessage,\n MessageFormatAdapter,\n} from \"@assistant-ui/react\";\nimport { sliceMessagesUntil } from \"../utils/sliceMessagesUntil\";\nimport { toCreateMessage } from \"../utils/toCreateMessage\";\nimport { vercelAttachmentAdapter } from \"../utils/vercelAttachmentAdapter\";\nimport { getVercelAIMessages } from \"../getVercelAIMessages\";\nimport { AISDKMessageConverter } from \"../utils/convertMessage\";\nimport {\n AISDKStorageFormat,\n aiSDKV5FormatAdapter,\n} from \"../adapters/aiSDKFormatAdapter\";\nimport { useExternalHistory } from \"./useExternalHistory\";\nimport { useMemo } from \"react\";\n\nexport type AISDKRuntimeAdapter = {\n adapters?:\n | (NonNullable<ExternalStoreAdapter[\"adapters\"]> & {\n history?: ThreadHistoryAdapter | undefined;\n })\n | undefined;\n};\n\nexport const useAISDKRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(\n chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>,\n adapter: AISDKRuntimeAdapter = {},\n) => {\n const messages = AISDKMessageConverter.useThreadMessages({\n isRunning:\n chatHelpers.status === \"submitted\" || chatHelpers.status == \"streaming\",\n messages: chatHelpers.messages,\n });\n\n const isLoading = useExternalHistory(\n useMemo(\n () => ({\n get current(): AssistantRuntime {\n return runtime;\n },\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n ),\n adapter.adapters?.history,\n AISDKMessageConverter.toThreadMessages as (\n messages: UI_MESSAGE[],\n ) => ThreadMessage[],\n aiSDKV5FormatAdapter as MessageFormatAdapter<\n UI_MESSAGE,\n AISDKStorageFormat\n >,\n (messages) => {\n chatHelpers.setMessages(messages);\n },\n );\n\n const runtime = useExternalStoreRuntime({\n isRunning:\n chatHelpers.status === \"submitted\" || chatHelpers.status === \"streaming\",\n messages,\n setMessages: (messages) =>\n chatHelpers.setMessages(\n messages.map(getVercelAIMessages<UI_MESSAGE>).flat(),\n ),\n onCancel: async () => chatHelpers.stop(),\n onNew: async (message) => {\n const createMessage = await toCreateMessage<UI_MESSAGE>(message);\n await chatHelpers.sendMessage(createMessage);\n },\n onEdit: async (message) => {\n const newMessages = sliceMessagesUntil(\n chatHelpers.messages,\n message.parentId,\n );\n chatHelpers.setMessages(newMessages);\n\n const createMessage = await toCreateMessage<UI_MESSAGE>(message);\n await chatHelpers.sendMessage(createMessage);\n },\n onReload: async (parentId: string | null) => {\n const newMessages = sliceMessagesUntil(chatHelpers.messages, parentId);\n chatHelpers.setMessages(newMessages);\n\n await chatHelpers.regenerate();\n },\n onAddToolResult: ({ toolCallId, result }) => {\n chatHelpers.addToolResult({\n tool: toolCallId,\n toolCallId,\n output: result,\n });\n },\n adapters: {\n attachments: vercelAttachmentAdapter,\n ...adapter.adapters,\n },\n isLoading,\n });\n\n return runtime;\n};\n"],"mappings":";;;AAGA;AAAA,EACE;AAAA,OAMK;AACP,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAChC,SAAS,+BAA+B;AACxC,SAAS,2BAA2B;AACpC,SAAS,6BAA6B;AACtC;AAAA,EAEE;AAAA,OACK;AACP,SAAS,0BAA0B;AACnC,SAAS,eAAe;AAUjB,IAAM,kBAAkB,CAC7B,aACA,UAA+B,CAAC,MAC7B;AACH,QAAM,WAAW,sBAAsB,kBAAkB;AAAA,IACvD,WACE,YAAY,WAAW,eAAe,YAAY,UAAU;AAAA,IAC9D,UAAU,YAAY;AAAA,EACxB,CAAC;AAED,QAAM,YAAY;AAAA,IAChB;AAAA,MACE,OAAO;AAAA,QACL,IAAI,UAA4B;AAC9B,iBAAO;AAAA,QACT;AAAA,MACF;AAAA;AAAA,MAEA,CAAC;AAAA,IACH;AAAA,IACA,QAAQ,UAAU;AAAA,IAClB,sBAAsB;AAAA,IAGtB;AAAA,IAIA,CAACA,cAAa;AACZ,kBAAY,YAAYA,SAAQ;AAAA,IAClC;AAAA,EACF;AAEA,QAAM,UAAU,wBAAwB;AAAA,IACtC,WACE,YAAY,WAAW,eAAe,YAAY,WAAW;AAAA,IAC/D;AAAA,IACA,aAAa,CAACA,cACZ,YAAY;AAAA,MACVA,UAAS,IAAI,mBAA+B,EAAE,KAAK;AAAA,IACrD;AAAA,IACF,UAAU,YAAY,YAAY,KAAK;AAAA,IACvC,OAAO,OAAO,YAAY;AACxB,YAAM,gBAAgB,MAAM,gBAA4B,OAAO;AAC/D,YAAM,YAAY,YAAY,aAAa;AAAA,IAC7C;AAAA,IACA,QAAQ,OAAO,YAAY;AACzB,YAAM,cAAc;AAAA,QAClB,YAAY;AAAA,QACZ,QAAQ;AAAA,MACV;AACA,kBAAY,YAAY,WAAW;AAEnC,YAAM,gBAAgB,MAAM,gBAA4B,OAAO;AAC/D,YAAM,YAAY,YAAY,aAAa;AAAA,IAC7C;AAAA,IACA,UAAU,OAAO,aAA4B;AAC3C,YAAM,cAAc,mBAAmB,YAAY,UAAU,QAAQ;AACrE,kBAAY,YAAY,WAAW;AAEnC,YAAM,YAAY,WAAW;AAAA,IAC/B;AAAA,IACA,iBAAiB,CAAC,EAAE,YAAY,OAAO,MAAM;AAC3C,kBAAY,cAAc;AAAA,QACxB,MAAM;AAAA,QACN;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAAA,IACA,UAAU;AAAA,MACR,aAAa;AAAA,MACb,GAAG,QAAQ;AAAA,IACb;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO;AACT;","names":["messages"]}
|
|
@@ -23,7 +23,7 @@ var useExternalHistory = (runtimeRef, historyAdapter, toThreadMessages, storageF
|
|
|
23
23
|
const loadedRef = useRef(false);
|
|
24
24
|
const [isLoading, setIsLoading] = useState(true);
|
|
25
25
|
const historyIds = useRef(/* @__PURE__ */ new Set());
|
|
26
|
-
const onSetMessagesRef = useRef(onSetMessages);
|
|
26
|
+
const onSetMessagesRef = useRef(() => onSetMessages);
|
|
27
27
|
useEffect(() => {
|
|
28
28
|
onSetMessagesRef.current = onSetMessages;
|
|
29
29
|
});
|
|
@@ -74,7 +74,7 @@ var useExternalHistory = (runtimeRef, historyAdapter, toThreadMessages, storageF
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
|
-
}, []);
|
|
77
|
+
}, [historyAdapter, storageFormatAdapter]);
|
|
78
78
|
return isLoading;
|
|
79
79
|
};
|
|
80
80
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/ui/use-chat/useExternalHistory.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n AssistantRuntime,\n ThreadHistoryAdapter,\n ThreadMessage,\n MessageFormatAdapter,\n getExternalStoreMessages,\n MessageFormatRepository,\n ExportedMessageRepository,\n INTERNAL,\n} from \"@assistant-ui/react\";\nimport { useRef, useEffect, useState, RefObject } from \"react\";\n\nconst { MessageRepository } = INTERNAL;\n\nexport const toExportedMessageRepository = <TMessage,>(\n toThreadMessages: (messages: TMessage[]) => ThreadMessage[],\n messages: MessageFormatRepository<TMessage>,\n): ExportedMessageRepository => {\n return {\n headId: messages.headId!,\n messages: messages.messages.map((m) => {\n const message = toThreadMessages([m.message])[0]!;\n return {\n ...m,\n message,\n };\n }),\n };\n};\n\nexport const useExternalHistory = <TMessage,>(\n runtimeRef: RefObject<AssistantRuntime>,\n historyAdapter: ThreadHistoryAdapter | undefined,\n toThreadMessages: (messages: TMessage[]) => ThreadMessage[],\n storageFormatAdapter: MessageFormatAdapter<TMessage, any>,\n onSetMessages: (messages: TMessage[]) => void,\n) => {\n const loadedRef = useRef(false);\n const [isLoading, setIsLoading] = useState(true);\n const historyIds = useRef(new Set<string>());\n\n const onSetMessagesRef = useRef(onSetMessages);\n useEffect(() => {\n onSetMessagesRef.current = onSetMessages;\n });\n\n // Load messages from history adapter on mount\n useEffect(() => {\n if (!historyAdapter || loadedRef.current) return;\n\n const loadHistory = async () => {\n setIsLoading(true);\n try {\n const repo = await historyAdapter\n .withFormat?.(storageFormatAdapter)\n .load();\n if (repo && repo.messages.length > 0) {\n const converted = toExportedMessageRepository(toThreadMessages, repo);\n runtimeRef.current.thread.import(converted);\n\n const tempRepo = new MessageRepository();\n tempRepo.import(converted);\n const messages = tempRepo.getMessages();\n\n onSetMessagesRef.current(\n messages.map(getExternalStoreMessages<TMessage>).flat(),\n );\n\n historyIds.current = new Set(\n converted.messages.map((m) => m.message.id),\n );\n }\n } catch (error) {\n console.error(\"Failed to load message history:\", error);\n } finally {\n setIsLoading(false);\n }\n };\n\n if (!loadedRef.current) {\n loadedRef.current = true;\n loadHistory();\n }\n }, [historyAdapter, storageFormatAdapter, toThreadMessages]);\n\n useEffect(() => {\n return runtimeRef.current.thread.subscribe(async () => {\n const { messages, isRunning } = runtimeRef.current.thread.getState();\n if (isRunning) return;\n\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i]!;\n if (\n message.status === undefined ||\n message.status.type === \"complete\" ||\n message.status.type === \"incomplete\"\n ) {\n if (historyIds.current.has(message.id)) return;\n historyIds.current.add(message.id);\n\n const parentId = i > 0 ? messages[i - 1]!.id : null;\n await historyAdapter?.withFormat?.(storageFormatAdapter).append({\n parentId,\n message: getExternalStoreMessages<TMessage>(message)[0]!,\n });\n }\n }\n });\n }, []);\n\n return isLoading;\n};\n"],"mappings":";;;AAEA;AAAA,EAKE;AAAA,EAGA;AAAA,OACK;AACP,SAAS,QAAQ,WAAW,gBAA2B;AAEvD,IAAM,EAAE,kBAAkB,IAAI;AAEvB,IAAM,8BAA8B,CACzC,kBACA,aAC8B;AAC9B,SAAO;AAAA,IACL,QAAQ,SAAS;AAAA,IACjB,UAAU,SAAS,SAAS,IAAI,CAAC,MAAM;AACrC,YAAM,UAAU,iBAAiB,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC;AAC/C,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEO,IAAM,qBAAqB,CAChC,YACA,gBACA,kBACA,sBACA,kBACG;AACH,QAAM,YAAY,OAAO,KAAK;AAC9B,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,IAAI;AAC/C,QAAM,aAAa,OAAO,oBAAI,IAAY,CAAC;AAE3C,QAAM,mBAAmB,
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/use-chat/useExternalHistory.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n AssistantRuntime,\n ThreadHistoryAdapter,\n ThreadMessage,\n MessageFormatAdapter,\n getExternalStoreMessages,\n MessageFormatRepository,\n ExportedMessageRepository,\n INTERNAL,\n} from \"@assistant-ui/react\";\nimport { useRef, useEffect, useState, RefObject } from \"react\";\n\nconst { MessageRepository } = INTERNAL;\n\nexport const toExportedMessageRepository = <TMessage,>(\n toThreadMessages: (messages: TMessage[]) => ThreadMessage[],\n messages: MessageFormatRepository<TMessage>,\n): ExportedMessageRepository => {\n return {\n headId: messages.headId!,\n messages: messages.messages.map((m) => {\n const message = toThreadMessages([m.message])[0]!;\n return {\n ...m,\n message,\n };\n }),\n };\n};\n\nexport const useExternalHistory = <TMessage,>(\n runtimeRef: RefObject<AssistantRuntime>,\n historyAdapter: ThreadHistoryAdapter | undefined,\n toThreadMessages: (messages: TMessage[]) => ThreadMessage[],\n storageFormatAdapter: MessageFormatAdapter<TMessage, any>,\n onSetMessages: (messages: TMessage[]) => void,\n) => {\n const loadedRef = useRef(false);\n const [isLoading, setIsLoading] = useState(true);\n const historyIds = useRef(new Set<string>());\n\n const onSetMessagesRef = useRef<typeof onSetMessages>(() => onSetMessages);\n useEffect(() => {\n onSetMessagesRef.current = onSetMessages;\n });\n\n // Load messages from history adapter on mount\n useEffect(() => {\n if (!historyAdapter || loadedRef.current) return;\n\n const loadHistory = async () => {\n setIsLoading(true);\n try {\n const repo = await historyAdapter\n .withFormat?.(storageFormatAdapter)\n .load();\n if (repo && repo.messages.length > 0) {\n const converted = toExportedMessageRepository(toThreadMessages, repo);\n runtimeRef.current.thread.import(converted);\n\n const tempRepo = new MessageRepository();\n tempRepo.import(converted);\n const messages = tempRepo.getMessages();\n\n onSetMessagesRef.current(\n messages.map(getExternalStoreMessages<TMessage>).flat(),\n );\n\n historyIds.current = new Set(\n converted.messages.map((m) => m.message.id),\n );\n }\n } catch (error) {\n console.error(\"Failed to load message history:\", error);\n } finally {\n setIsLoading(false);\n }\n };\n\n if (!loadedRef.current) {\n loadedRef.current = true;\n loadHistory();\n }\n }, [historyAdapter, storageFormatAdapter, toThreadMessages]);\n\n useEffect(() => {\n return runtimeRef.current.thread.subscribe(async () => {\n const { messages, isRunning } = runtimeRef.current.thread.getState();\n if (isRunning) return;\n\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i]!;\n if (\n message.status === undefined ||\n message.status.type === \"complete\" ||\n message.status.type === \"incomplete\"\n ) {\n if (historyIds.current.has(message.id)) return;\n historyIds.current.add(message.id);\n\n const parentId = i > 0 ? messages[i - 1]!.id : null;\n await historyAdapter?.withFormat?.(storageFormatAdapter).append({\n parentId,\n message: getExternalStoreMessages<TMessage>(message)[0]!,\n });\n }\n }\n });\n }, [historyAdapter, storageFormatAdapter]);\n\n return isLoading;\n};\n"],"mappings":";;;AAEA;AAAA,EAKE;AAAA,EAGA;AAAA,OACK;AACP,SAAS,QAAQ,WAAW,gBAA2B;AAEvD,IAAM,EAAE,kBAAkB,IAAI;AAEvB,IAAM,8BAA8B,CACzC,kBACA,aAC8B;AAC9B,SAAO;AAAA,IACL,QAAQ,SAAS;AAAA,IACjB,UAAU,SAAS,SAAS,IAAI,CAAC,MAAM;AACrC,YAAM,UAAU,iBAAiB,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC;AAC/C,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEO,IAAM,qBAAqB,CAChC,YACA,gBACA,kBACA,sBACA,kBACG;AACH,QAAM,YAAY,OAAO,KAAK;AAC9B,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,IAAI;AAC/C,QAAM,aAAa,OAAO,oBAAI,IAAY,CAAC;AAE3C,QAAM,mBAAmB,OAA6B,MAAM,aAAa;AACzE,YAAU,MAAM;AACd,qBAAiB,UAAU;AAAA,EAC7B,CAAC;AAGD,YAAU,MAAM;AACd,QAAI,CAAC,kBAAkB,UAAU,QAAS;AAE1C,UAAM,cAAc,YAAY;AAC9B,mBAAa,IAAI;AACjB,UAAI;AACF,cAAM,OAAO,MAAM,eAChB,aAAa,oBAAoB,EACjC,KAAK;AACR,YAAI,QAAQ,KAAK,SAAS,SAAS,GAAG;AACpC,gBAAM,YAAY,4BAA4B,kBAAkB,IAAI;AACpE,qBAAW,QAAQ,OAAO,OAAO,SAAS;AAE1C,gBAAM,WAAW,IAAI,kBAAkB;AACvC,mBAAS,OAAO,SAAS;AACzB,gBAAM,WAAW,SAAS,YAAY;AAEtC,2BAAiB;AAAA,YACf,SAAS,IAAI,wBAAkC,EAAE,KAAK;AAAA,UACxD;AAEA,qBAAW,UAAU,IAAI;AAAA,YACvB,UAAU,SAAS,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE;AAAA,UAC5C;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ,MAAM,mCAAmC,KAAK;AAAA,MACxD,UAAE;AACA,qBAAa,KAAK;AAAA,MACpB;AAAA,IACF;AAEA,QAAI,CAAC,UAAU,SAAS;AACtB,gBAAU,UAAU;AACpB,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,gBAAgB,sBAAsB,gBAAgB,CAAC;AAE3D,YAAU,MAAM;AACd,WAAO,WAAW,QAAQ,OAAO,UAAU,YAAY;AACrD,YAAM,EAAE,UAAU,UAAU,IAAI,WAAW,QAAQ,OAAO,SAAS;AACnE,UAAI,UAAW;AAEf,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,cAAM,UAAU,SAAS,CAAC;AAC1B,YACE,QAAQ,WAAW,UACnB,QAAQ,OAAO,SAAS,cACxB,QAAQ,OAAO,SAAS,cACxB;AACA,cAAI,WAAW,QAAQ,IAAI,QAAQ,EAAE,EAAG;AACxC,qBAAW,QAAQ,IAAI,QAAQ,EAAE;AAEjC,gBAAM,WAAW,IAAI,IAAI,SAAS,IAAI,CAAC,EAAG,KAAK;AAC/C,gBAAM,gBAAgB,aAAa,oBAAoB,EAAE,OAAO;AAAA,YAC9D;AAAA,YACA,SAAS,yBAAmC,OAAO,EAAE,CAAC;AAAA,UACxD,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,gBAAgB,oBAAoB,CAAC;AAEzC,SAAO;AACT;","names":[]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { UIMessage } from "ai";
|
|
2
|
-
export declare const sliceMessagesUntil: (messages:
|
|
2
|
+
export declare const sliceMessagesUntil: <UI_MESSAGE extends UIMessage = UIMessage>(messages: UI_MESSAGE[], messageId: string | null) => UI_MESSAGE[];
|
|
3
3
|
//# sourceMappingURL=sliceMessagesUntil.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sliceMessagesUntil.d.ts","sourceRoot":"","sources":["../../../src/ui/utils/sliceMessagesUntil.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEpC,eAAO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"sliceMessagesUntil.d.ts","sourceRoot":"","sources":["../../../src/ui/utils/sliceMessagesUntil.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEpC,eAAO,MAAM,kBAAkB,GAAI,UAAU,SAAS,SAAS,GAAG,SAAS,EACzE,UAAU,UAAU,EAAE,EACtB,WAAW,MAAM,GAAG,IAAI,iBAezB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/ui/utils/sliceMessagesUntil.tsx"],"sourcesContent":["import type { UIMessage } from \"ai\";\n\nexport const sliceMessagesUntil = (\n messages:
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/utils/sliceMessagesUntil.tsx"],"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 \"useVercelAIThreadState: Message not found. 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":";AAEO,IAAM,qBAAqB,CAChC,UACA,cACG;AACH,MAAI,aAAa,KAAM,QAAO,CAAC;AAE/B,MAAI,aAAa,SAAS,UAAU,CAAC,MAAM,EAAE,OAAO,SAAS;AAC7D,MAAI,eAAe;AACjB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAEF,SAAO,SAAS,aAAa,CAAC,GAAG,SAAS,aAAa;AACrD;AAAA,EACF;AAEA,SAAO,SAAS,MAAM,GAAG,aAAa,CAAC;AACzC;","names":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { AppendMessage } from "@assistant-ui/react";
|
|
2
2
|
import { CreateUIMessage, UIMessage } from "ai";
|
|
3
|
-
export declare const toCreateMessage: (message: AppendMessage) => Promise<CreateUIMessage<
|
|
3
|
+
export declare const toCreateMessage: <UI_MESSAGE extends UIMessage = UIMessage>(message: AppendMessage) => Promise<CreateUIMessage<UI_MESSAGE>>;
|
|
4
4
|
//# sourceMappingURL=toCreateMessage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toCreateMessage.d.ts","sourceRoot":"","sources":["../../../src/ui/utils/toCreateMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,eAAe,EAIf,SAAS,EAGV,MAAM,IAAI,CAAC;AAEZ,eAAO,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"toCreateMessage.d.ts","sourceRoot":"","sources":["../../../src/ui/utils/toCreateMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,eAAe,EAIf,SAAS,EAGV,MAAM,IAAI,CAAC;AAEZ,eAAO,MAAM,eAAe,GAAU,UAAU,SAAS,SAAS,GAAG,SAAS,EAC5E,SAAS,aAAa,KACrB,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,CA+CrC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/ui/utils/toCreateMessage.ts"],"sourcesContent":["import { AppendMessage } from \"@assistant-ui/react\";\nimport {\n CreateUIMessage,\n FileUIPart,\n generateId,\n UIDataTypes,\n UIMessage,\n UIMessagePart,\n UITools,\n} from \"ai\";\n\nexport const toCreateMessage = async (\n message: AppendMessage,\n): Promise<CreateUIMessage<
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/utils/toCreateMessage.ts"],"sourcesContent":["import { AppendMessage } from \"@assistant-ui/react\";\nimport {\n CreateUIMessage,\n FileUIPart,\n generateId,\n UIDataTypes,\n UIMessage,\n UIMessagePart,\n UITools,\n} from \"ai\";\n\nexport const toCreateMessage = async <UI_MESSAGE extends UIMessage = UIMessage>(\n message: AppendMessage,\n): Promise<CreateUIMessage<UI_MESSAGE>> => {\n const textParts = message.content\n .filter((part) => part.type === \"text\")\n .map((t) => t.text)\n .join(\"\\n\\n\");\n\n const parts: UIMessagePart<UIDataTypes, UITools>[] = [\n {\n type: \"text\",\n text: textParts,\n },\n ];\n\n // Add image parts\n const imageParts = message.content\n .filter((part) => part.type === \"image\")\n .map(\n (part) =>\n ({\n type: \"file\",\n mediaType: \"image/png\", // Default to PNG, could be made more dynamic\n url: part.image,\n }) satisfies FileUIPart,\n );\n\n parts.push(...imageParts);\n\n // Add attachment parts\n const attachmentParts = await Promise.all(\n (message.attachments ?? []).map(async (m) => {\n if (m.file == null) throw new Error(\"Attachment did not contain a file\");\n return {\n type: \"file\",\n mediaType: m.file.type,\n filename: m.file.name,\n url: await getFileDataURL(m.file),\n } satisfies FileUIPart;\n }),\n );\n\n parts.push(...attachmentParts);\n\n return {\n id: generateId(),\n role: message.role,\n parts,\n } satisfies CreateUIMessage<UIMessage> as CreateUIMessage<UI_MESSAGE>;\n};\n\nconst getFileDataURL = (file: File) =>\n new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = (error) => reject(error);\n\n reader.readAsDataURL(file);\n });\n"],"mappings":";AACA;AAAA,EAGE;AAAA,OAKK;AAEA,IAAM,kBAAkB,OAC7B,YACyC;AACzC,QAAM,YAAY,QAAQ,QACvB,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM,EACrC,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,MAAM;AAEd,QAAM,QAA+C;AAAA,IACnD;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,aAAa,QAAQ,QACxB,OAAO,CAAC,SAAS,KAAK,SAAS,OAAO,EACtC;AAAA,IACC,CAAC,UACE;AAAA,MACC,MAAM;AAAA,MACN,WAAW;AAAA;AAAA,MACX,KAAK,KAAK;AAAA,IACZ;AAAA,EACJ;AAEF,QAAM,KAAK,GAAG,UAAU;AAGxB,QAAM,kBAAkB,MAAM,QAAQ;AAAA,KACnC,QAAQ,eAAe,CAAC,GAAG,IAAI,OAAO,MAAM;AAC3C,UAAI,EAAE,QAAQ,KAAM,OAAM,IAAI,MAAM,mCAAmC;AACvE,aAAO;AAAA,QACL,MAAM;AAAA,QACN,WAAW,EAAE,KAAK;AAAA,QAClB,UAAU,EAAE,KAAK;AAAA,QACjB,KAAK,MAAM,eAAe,EAAE,IAAI;AAAA,MAClC;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,KAAK,GAAG,eAAe;AAE7B,SAAO;AAAA,IACL,IAAI,WAAW;AAAA,IACf,MAAM,QAAQ;AAAA,IACd;AAAA,EACF;AACF;AAEA,IAAM,iBAAiB,CAAC,SACtB,IAAI,QAAgB,CAAC,SAAS,WAAW;AACvC,QAAM,SAAS,IAAI,WAAW;AAE9B,SAAO,SAAS,MAAM,QAAQ,OAAO,MAAgB;AACrD,SAAO,UAAU,CAAC,UAAU,OAAO,KAAK;AAExC,SAAO,cAAc,IAAI;AAC3B,CAAC;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react-ai-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"zustand": "^5.0.7"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@assistant-ui/react": "^0.10.
|
|
32
|
+
"@assistant-ui/react": "^0.10.41",
|
|
33
33
|
"@types/react": "*",
|
|
34
34
|
"assistant-cloud": "*",
|
|
35
35
|
"react": "^18 || ^19 || ^19.0.0-rc"
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"eslint-config-next": "15.4.5",
|
|
50
50
|
"react": "19.1.1",
|
|
51
51
|
"tsx": "^4.20.3",
|
|
52
|
-
"@assistant-ui/react": "0.10.
|
|
52
|
+
"@assistant-ui/react": "0.10.41",
|
|
53
53
|
"@assistant-ui/x-buildutils": "0.0.1"
|
|
54
54
|
},
|
|
55
55
|
"publishConfig": {
|
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
} from "@assistant-ui/react";
|
|
5
5
|
import type { UIMessage } from "ai";
|
|
6
6
|
|
|
7
|
-
export const getVercelAIMessages =
|
|
8
|
-
|
|
7
|
+
export const getVercelAIMessages = <UI_MESSAGE extends UIMessage = UIMessage>(
|
|
8
|
+
message: ThreadMessage,
|
|
9
|
+
) => {
|
|
10
|
+
return getExternalStoreMessages(message) as UI_MESSAGE[];
|
|
9
11
|
};
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import type { useChat } from "@ai-sdk/react";
|
|
3
|
+
import type { UIMessage, useChat } from "@ai-sdk/react";
|
|
4
4
|
import {
|
|
5
5
|
useExternalStoreRuntime,
|
|
6
6
|
ExternalStoreAdapter,
|
|
7
7
|
ThreadHistoryAdapter,
|
|
8
8
|
AssistantRuntime,
|
|
9
|
+
ThreadMessage,
|
|
10
|
+
MessageFormatAdapter,
|
|
9
11
|
} from "@assistant-ui/react";
|
|
10
12
|
import { sliceMessagesUntil } from "../utils/sliceMessagesUntil";
|
|
11
13
|
import { toCreateMessage } from "../utils/toCreateMessage";
|
|
12
14
|
import { vercelAttachmentAdapter } from "../utils/vercelAttachmentAdapter";
|
|
13
15
|
import { getVercelAIMessages } from "../getVercelAIMessages";
|
|
14
16
|
import { AISDKMessageConverter } from "../utils/convertMessage";
|
|
15
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
AISDKStorageFormat,
|
|
19
|
+
aiSDKV5FormatAdapter,
|
|
20
|
+
} from "../adapters/aiSDKFormatAdapter";
|
|
16
21
|
import { useExternalHistory } from "./useExternalHistory";
|
|
22
|
+
import { useMemo } from "react";
|
|
17
23
|
|
|
18
24
|
export type AISDKRuntimeAdapter = {
|
|
19
25
|
adapters?:
|
|
@@ -23,8 +29,8 @@ export type AISDKRuntimeAdapter = {
|
|
|
23
29
|
| undefined;
|
|
24
30
|
};
|
|
25
31
|
|
|
26
|
-
export const useAISDKRuntime = (
|
|
27
|
-
chatHelpers: ReturnType<typeof useChat
|
|
32
|
+
export const useAISDKRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(
|
|
33
|
+
chatHelpers: ReturnType<typeof useChat<UI_MESSAGE>>,
|
|
28
34
|
adapter: AISDKRuntimeAdapter = {},
|
|
29
35
|
) => {
|
|
30
36
|
const messages = AISDKMessageConverter.useThreadMessages({
|
|
@@ -34,14 +40,23 @@ export const useAISDKRuntime = (
|
|
|
34
40
|
});
|
|
35
41
|
|
|
36
42
|
const isLoading = useExternalHistory(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
useMemo(
|
|
44
|
+
() => ({
|
|
45
|
+
get current(): AssistantRuntime {
|
|
46
|
+
return runtime;
|
|
47
|
+
},
|
|
48
|
+
}),
|
|
49
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
50
|
+
[],
|
|
51
|
+
),
|
|
42
52
|
adapter.adapters?.history,
|
|
43
|
-
AISDKMessageConverter.toThreadMessages
|
|
44
|
-
|
|
53
|
+
AISDKMessageConverter.toThreadMessages as (
|
|
54
|
+
messages: UI_MESSAGE[],
|
|
55
|
+
) => ThreadMessage[],
|
|
56
|
+
aiSDKV5FormatAdapter as MessageFormatAdapter<
|
|
57
|
+
UI_MESSAGE,
|
|
58
|
+
AISDKStorageFormat
|
|
59
|
+
>,
|
|
45
60
|
(messages) => {
|
|
46
61
|
chatHelpers.setMessages(messages);
|
|
47
62
|
},
|
|
@@ -52,10 +67,12 @@ export const useAISDKRuntime = (
|
|
|
52
67
|
chatHelpers.status === "submitted" || chatHelpers.status === "streaming",
|
|
53
68
|
messages,
|
|
54
69
|
setMessages: (messages) =>
|
|
55
|
-
chatHelpers.setMessages(
|
|
70
|
+
chatHelpers.setMessages(
|
|
71
|
+
messages.map(getVercelAIMessages<UI_MESSAGE>).flat(),
|
|
72
|
+
),
|
|
56
73
|
onCancel: async () => chatHelpers.stop(),
|
|
57
74
|
onNew: async (message) => {
|
|
58
|
-
const createMessage = await toCreateMessage(message);
|
|
75
|
+
const createMessage = await toCreateMessage<UI_MESSAGE>(message);
|
|
59
76
|
await chatHelpers.sendMessage(createMessage);
|
|
60
77
|
},
|
|
61
78
|
onEdit: async (message) => {
|
|
@@ -65,7 +82,7 @@ export const useAISDKRuntime = (
|
|
|
65
82
|
);
|
|
66
83
|
chatHelpers.setMessages(newMessages);
|
|
67
84
|
|
|
68
|
-
const createMessage = await toCreateMessage(message);
|
|
85
|
+
const createMessage = await toCreateMessage<UI_MESSAGE>(message);
|
|
69
86
|
await chatHelpers.sendMessage(createMessage);
|
|
70
87
|
},
|
|
71
88
|
onReload: async (parentId: string | null) => {
|
|
@@ -41,7 +41,7 @@ export const useExternalHistory = <TMessage,>(
|
|
|
41
41
|
const [isLoading, setIsLoading] = useState(true);
|
|
42
42
|
const historyIds = useRef(new Set<string>());
|
|
43
43
|
|
|
44
|
-
const onSetMessagesRef = useRef(onSetMessages);
|
|
44
|
+
const onSetMessagesRef = useRef<typeof onSetMessages>(() => onSetMessages);
|
|
45
45
|
useEffect(() => {
|
|
46
46
|
onSetMessagesRef.current = onSetMessages;
|
|
47
47
|
});
|
|
@@ -108,7 +108,7 @@ export const useExternalHistory = <TMessage,>(
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
});
|
|
111
|
-
}, []);
|
|
111
|
+
}, [historyAdapter, storageFormatAdapter]);
|
|
112
112
|
|
|
113
113
|
return isLoading;
|
|
114
114
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { UIMessage } from "ai";
|
|
2
2
|
|
|
3
|
-
export const sliceMessagesUntil = (
|
|
4
|
-
messages:
|
|
3
|
+
export const sliceMessagesUntil = <UI_MESSAGE extends UIMessage = UIMessage>(
|
|
4
|
+
messages: UI_MESSAGE[],
|
|
5
5
|
messageId: string | null,
|
|
6
6
|
) => {
|
|
7
7
|
if (messageId == null) return [];
|
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
UITools,
|
|
10
10
|
} from "ai";
|
|
11
11
|
|
|
12
|
-
export const toCreateMessage = async (
|
|
12
|
+
export const toCreateMessage = async <UI_MESSAGE extends UIMessage = UIMessage>(
|
|
13
13
|
message: AppendMessage,
|
|
14
|
-
): Promise<CreateUIMessage<
|
|
14
|
+
): Promise<CreateUIMessage<UI_MESSAGE>> => {
|
|
15
15
|
const textParts = message.content
|
|
16
16
|
.filter((part) => part.type === "text")
|
|
17
17
|
.map((t) => t.text)
|
|
@@ -57,7 +57,7 @@ export const toCreateMessage = async (
|
|
|
57
57
|
id: generateId(),
|
|
58
58
|
role: message.role,
|
|
59
59
|
parts,
|
|
60
|
-
}
|
|
60
|
+
} satisfies CreateUIMessage<UIMessage> as CreateUIMessage<UI_MESSAGE>;
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
const getFileDataURL = (file: File) =>
|