@assistant-ui/react-ai-sdk 1.3.26 → 1.3.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/frontendTools.d.ts +9 -5
- package/dist/frontendTools.d.ts.map +1 -1
- package/dist/frontendTools.js +36 -35
- package/dist/frontendTools.js.map +1 -1
- package/dist/index.d.ts +9 -11
- package/dist/index.js +9 -10
- package/dist/injectQuoteContext.d.ts +6 -2
- package/dist/injectQuoteContext.d.ts.map +1 -1
- package/dist/injectQuoteContext.js +46 -53
- package/dist/injectQuoteContext.js.map +1 -1
- package/dist/modelContentEnvelope.d.ts +12 -10
- package/dist/modelContentEnvelope.d.ts.map +1 -1
- package/dist/modelContentEnvelope.js +17 -15
- package/dist/modelContentEnvelope.js.map +1 -1
- package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts +141 -0
- package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts.map +1 -0
- package/dist/packages/assistant-stream/dist/core/AssistantStream.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/AssistantStreamChunk.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/accumulators/AssistantMessageStream.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/accumulators/assistant-message-accumulator.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/modules/assistant-stream.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/modules/text.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/modules/tool-call.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/serialization/PlainText.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/serialization/assistant-transport/AssistantTransport.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/serialization/data-stream/DataStream.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/serialization/ui-message-stream/UIMessageStream.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/tool/ToolExecutionStream.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/tool/schema-utils.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/tool/schema-utils.js +50 -0
- package/dist/packages/assistant-stream/dist/core/tool/schema-utils.js.map +1 -0
- package/dist/packages/assistant-stream/dist/core/tool/tool-types.d.ts +43 -0
- package/dist/packages/assistant-stream/dist/core/tool/tool-types.d.ts.map +1 -0
- package/dist/packages/assistant-stream/dist/core/tool/toolResultStream.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/utils/stream/AssistantMetaTransformStream.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/utils/stream/AssistantTransformStream.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/core/utils/types.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/index.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/resumable/createResumableAssistantStreamResponse.d.ts +6 -0
- package/dist/packages/assistant-stream/dist/resumable/createResumableAssistantStreamResponse.d.ts.map +1 -0
- package/dist/packages/assistant-stream/dist/resumable/createResumableAssistantStreamResponse.js +6 -0
- package/dist/packages/assistant-stream/dist/resumable/createResumableAssistantStreamResponse.js.map +1 -0
- package/dist/packages/assistant-stream/dist/resumable/index.d.ts +1 -0
- package/dist/packages/assistant-stream/dist/utils/json/json-value.d.ts +10 -0
- package/dist/packages/assistant-stream/dist/utils/json/json-value.d.ts.map +1 -0
- package/dist/packages/assistant-stream/dist/utils.d.ts +1 -0
- package/dist/ui/adapters/aiSDKFormatAdapter.d.ts +8 -4
- package/dist/ui/adapters/aiSDKFormatAdapter.d.ts.map +1 -1
- package/dist/ui/adapters/aiSDKFormatAdapter.js +24 -20
- package/dist/ui/adapters/aiSDKFormatAdapter.js.map +1 -1
- package/dist/ui/getVercelAIMessages.d.ts +7 -3
- package/dist/ui/getVercelAIMessages.d.ts.map +1 -1
- package/dist/ui/getVercelAIMessages.js +7 -3
- package/dist/ui/getVercelAIMessages.js.map +1 -1
- package/dist/ui/resumable.d.ts +18 -15
- package/dist/ui/resumable.d.ts.map +1 -1
- package/dist/ui/resumable.js +21 -20
- package/dist/ui/resumable.js.map +1 -1
- package/dist/ui/use-chat/AssistantChatTransport.d.ts +17 -14
- package/dist/ui/use-chat/AssistantChatTransport.d.ts.map +1 -1
- package/dist/ui/use-chat/AssistantChatTransport.js +98 -108
- package/dist/ui/use-chat/AssistantChatTransport.js.map +1 -1
- package/dist/ui/use-chat/useAISDKRuntime.d.ts +43 -33
- package/dist/ui/use-chat/useAISDKRuntime.d.ts.map +1 -1
- package/dist/ui/use-chat/useAISDKRuntime.js +184 -204
- package/dist/ui/use-chat/useAISDKRuntime.js.map +1 -1
- package/dist/ui/use-chat/useChatRuntime.d.ts +19 -12
- package/dist/ui/use-chat/useChatRuntime.d.ts.map +1 -1
- package/dist/ui/use-chat/useChatRuntime.js +60 -81
- package/dist/ui/use-chat/useChatRuntime.js.map +1 -1
- package/dist/ui/use-chat/useExternalHistory.d.ts +8 -4
- package/dist/ui/use-chat/useExternalHistory.d.ts.map +1 -1
- package/dist/ui/use-chat/useExternalHistory.js +178 -200
- package/dist/ui/use-chat/useExternalHistory.js.map +1 -1
- package/dist/ui/use-chat/useStreamingTiming.d.ts +7 -3
- package/dist/ui/use-chat/useStreamingTiming.d.ts.map +1 -1
- package/dist/ui/use-chat/useStreamingTiming.js +60 -75
- package/dist/ui/use-chat/useStreamingTiming.js.map +1 -1
- package/dist/ui/utils/convertMessage.d.ts +29 -20
- package/dist/ui/utils/convertMessage.d.ts.map +1 -1
- package/dist/ui/utils/convertMessage.js +207 -301
- package/dist/ui/utils/convertMessage.js.map +1 -1
- package/dist/ui/utils/sliceMessagesUntil.d.ts +6 -2
- package/dist/ui/utils/sliceMessagesUntil.d.ts.map +1 -1
- package/dist/ui/utils/sliceMessagesUntil.js +10 -10
- package/dist/ui/utils/sliceMessagesUntil.js.map +1 -1
- package/dist/ui/utils/toCreateMessage.d.ts +7 -3
- package/dist/ui/utils/toCreateMessage.d.ts.map +1 -1
- package/dist/ui/utils/toCreateMessage.js +34 -38
- package/dist/ui/utils/toCreateMessage.js.map +1 -1
- package/dist/ui/utils/vercelAttachmentAdapter.d.ts +6 -2
- package/dist/ui/utils/vercelAttachmentAdapter.d.ts.map +1 -1
- package/dist/ui/utils/vercelAttachmentAdapter.js +37 -35
- package/dist/ui/utils/vercelAttachmentAdapter.js.map +1 -1
- package/dist/usage.d.ts +15 -12
- package/dist/usage.d.ts.map +1 -1
- package/dist/usage.js +80 -99
- package/dist/usage.js.map +1 -1
- package/package.json +11 -11
- package/src/ui/use-chat/useAISDKRuntime.test.ts +2 -2
- package/src/ui/use-chat/useAISDKRuntime.ts +8 -0
- package/src/ui/utils/convertMessage.test.ts +71 -6
- package/src/ui/utils/convertMessage.ts +27 -25
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -1,92 +1,71 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { useCloudThreadListAdapter, useRemoteThreadListRuntime, } from "@assistant-ui/core/react";
|
|
4
|
-
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
5
|
-
import { useAISDKRuntime, } from "./useAISDKRuntime.js";
|
|
2
|
+
import { useAISDKRuntime } from "./useAISDKRuntime.js";
|
|
6
3
|
import { AssistantChatTransport } from "./AssistantChatTransport.js";
|
|
7
4
|
import { useEffect, useMemo, useRef } from "react";
|
|
5
|
+
import { useCloudThreadListAdapter, useRemoteThreadListRuntime } from "@assistant-ui/core/react";
|
|
6
|
+
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
7
|
+
import { useChat } from "@ai-sdk/react";
|
|
8
|
+
//#region src/ui/use-chat/useChatRuntime.ts
|
|
8
9
|
const useDynamicChatTransport = (transport) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
get(_, prop) {
|
|
18
|
-
const res = transportRef.current[prop];
|
|
19
|
-
return typeof res === "function"
|
|
20
|
-
? res.bind(transportRef.current)
|
|
21
|
-
: res;
|
|
22
|
-
},
|
|
23
|
-
}), []);
|
|
24
|
-
return dynamicTransport;
|
|
10
|
+
const transportRef = useRef(transport);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
transportRef.current = transport;
|
|
13
|
+
});
|
|
14
|
+
return useMemo(() => new Proxy(transportRef.current, { get(_, prop) {
|
|
15
|
+
const res = transportRef.current[prop];
|
|
16
|
+
return typeof res === "function" ? res.bind(transportRef.current) : res;
|
|
17
|
+
} }), []);
|
|
25
18
|
};
|
|
26
19
|
const getResumableAdapter = (transport) => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
.getResumableAdapter;
|
|
32
|
-
if (typeof candidate !== "function")
|
|
33
|
-
return undefined;
|
|
34
|
-
return candidate.call(transport);
|
|
20
|
+
if (transport instanceof AssistantChatTransport) return transport.getResumableAdapter();
|
|
21
|
+
const candidate = transport.getResumableAdapter;
|
|
22
|
+
if (typeof candidate !== "function") return void 0;
|
|
23
|
+
return candidate.call(transport);
|
|
35
24
|
};
|
|
36
25
|
const useChatThreadRuntime = (options) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return;
|
|
70
|
-
const pending = adapter.storage.getStreamId();
|
|
71
|
-
if (!pending)
|
|
72
|
-
return;
|
|
73
|
-
resumeFiredRef.current = true;
|
|
74
|
-
chat.resumeStream().catch((err) => {
|
|
75
|
-
console.warn("[assistant-ui] resumable: resume failed; clearing stored stream id", err);
|
|
76
|
-
adapter.storage.clear();
|
|
77
|
-
});
|
|
78
|
-
}, [transport, chat]);
|
|
79
|
-
return runtime;
|
|
26
|
+
const { adapters, transport: transportOptions, toCreateMessage, onResume, suggestions, ...chatOptions } = options ?? {};
|
|
27
|
+
const transport = useDynamicChatTransport(transportOptions ?? new AssistantChatTransport());
|
|
28
|
+
const id = useAuiState((s) => s.threadListItem.id);
|
|
29
|
+
const aui = useAui();
|
|
30
|
+
const chat = useChat({
|
|
31
|
+
...chatOptions,
|
|
32
|
+
id,
|
|
33
|
+
transport
|
|
34
|
+
});
|
|
35
|
+
const runtime = useAISDKRuntime(chat, {
|
|
36
|
+
adapters,
|
|
37
|
+
...toCreateMessage && { toCreateMessage },
|
|
38
|
+
...onResume && { onResume },
|
|
39
|
+
...suggestions && { suggestions }
|
|
40
|
+
});
|
|
41
|
+
if (transport instanceof AssistantChatTransport) {
|
|
42
|
+
transport.setRuntime(runtime);
|
|
43
|
+
transport.__internal_setGetThreadListItem(() => aui.threadListItem.source ? aui.threadListItem() : void 0);
|
|
44
|
+
}
|
|
45
|
+
const resumeFiredRef = useRef(false);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (resumeFiredRef.current) return;
|
|
48
|
+
const adapter = getResumableAdapter(transport);
|
|
49
|
+
if (!adapter) return;
|
|
50
|
+
if (!adapter.storage.getStreamId()) return;
|
|
51
|
+
resumeFiredRef.current = true;
|
|
52
|
+
chat.resumeStream().catch((err) => {
|
|
53
|
+
console.warn("[assistant-ui] resumable: resume failed; clearing stored stream id", err);
|
|
54
|
+
adapter.storage.clear();
|
|
55
|
+
});
|
|
56
|
+
}, [transport, chat]);
|
|
57
|
+
return runtime;
|
|
80
58
|
};
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
allowNesting: true,
|
|
90
|
-
});
|
|
59
|
+
const useChatRuntime = ({ cloud, ...options } = {}) => {
|
|
60
|
+
return useRemoteThreadListRuntime({
|
|
61
|
+
runtimeHook: function RuntimeHook() {
|
|
62
|
+
return useChatThreadRuntime(options);
|
|
63
|
+
},
|
|
64
|
+
adapter: useCloudThreadListAdapter({ cloud }),
|
|
65
|
+
allowNesting: true
|
|
66
|
+
});
|
|
91
67
|
};
|
|
68
|
+
//#endregion
|
|
69
|
+
export { useChatRuntime };
|
|
70
|
+
|
|
92
71
|
//# sourceMappingURL=useChatRuntime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChatRuntime.js","
|
|
1
|
+
{"version":3,"file":"useChatRuntime.js","names":[],"sources":["../../../src/ui/use-chat/useChatRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport { useChat, type UIMessage } from \"@ai-sdk/react\";\nimport type { AssistantCloud } from \"assistant-cloud\";\nimport type { AssistantRuntime } from \"@assistant-ui/core\";\nimport {\n useCloudThreadListAdapter,\n useRemoteThreadListRuntime,\n} from \"@assistant-ui/core/react\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport {\n useAISDKRuntime,\n type AISDKRuntimeAdapter,\n type CustomToCreateMessageFunction,\n} from \"./useAISDKRuntime\";\nimport type { ChatInit, ChatTransport } from \"ai\";\nimport { AssistantChatTransport } from \"./AssistantChatTransport\";\nimport type { AssistantChatResumableOptions } from \"../resumable\";\nimport { useEffect, useMemo, useRef } from \"react\";\n\nexport type UseChatRuntimeOptions<UI_MESSAGE extends UIMessage = UIMessage> =\n ChatInit<UI_MESSAGE> & {\n cloud?: AssistantCloud | undefined;\n adapters?: AISDKRuntimeAdapter[\"adapters\"] | undefined;\n toCreateMessage?: CustomToCreateMessageFunction;\n onResume?: AISDKRuntimeAdapter[\"onResume\"];\n suggestions?: AISDKRuntimeAdapter[\"suggestions\"];\n };\n\nconst useDynamicChatTransport = <UI_MESSAGE extends UIMessage = UIMessage>(\n transport: ChatTransport<UI_MESSAGE>,\n): ChatTransport<UI_MESSAGE> => {\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const transportRef = useRef<ChatTransport<UI_MESSAGE>>(transport);\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n useEffect(() => {\n transportRef.current = transport;\n });\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const dynamicTransport = useMemo(\n () =>\n new Proxy(transportRef.current, {\n get(_, prop) {\n const res =\n transportRef.current[prop as keyof ChatTransport<UI_MESSAGE>];\n return typeof res === \"function\"\n ? res.bind(transportRef.current)\n : res;\n },\n }),\n [],\n );\n return dynamicTransport;\n};\n\nconst getResumableAdapter = <UI_MESSAGE extends UIMessage>(\n transport: ChatTransport<UI_MESSAGE>,\n): AssistantChatResumableOptions | undefined => {\n if (transport instanceof AssistantChatTransport) {\n return transport.getResumableAdapter();\n }\n const candidate = (transport as { getResumableAdapter?: () => unknown })\n .getResumableAdapter;\n if (typeof candidate !== \"function\") return undefined;\n return candidate.call(transport) as AssistantChatResumableOptions | undefined;\n};\n\nconst useChatThreadRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(\n options?: UseChatRuntimeOptions<UI_MESSAGE>,\n): AssistantRuntime => {\n const {\n adapters,\n transport: transportOptions,\n toCreateMessage,\n onResume,\n suggestions,\n ...chatOptions\n } = options ?? {};\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const transport = useDynamicChatTransport(\n transportOptions ?? new AssistantChatTransport(),\n );\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const id = useAuiState((s) => s.threadListItem.id);\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const aui = useAui();\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const chat = useChat({\n ...chatOptions,\n id,\n transport,\n });\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const runtime = useAISDKRuntime(chat, {\n adapters,\n ...(toCreateMessage && { toCreateMessage }),\n ...(onResume && { onResume }),\n ...(suggestions && { suggestions }),\n });\n\n if (transport instanceof AssistantChatTransport) {\n transport.setRuntime(runtime);\n transport.__internal_setGetThreadListItem(() =>\n aui.threadListItem.source ? aui.threadListItem() : undefined,\n );\n }\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const resumeFiredRef = useRef(false);\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n useEffect(() => {\n if (resumeFiredRef.current) return;\n const adapter = getResumableAdapter(transport);\n if (!adapter) return;\n const pending = adapter.storage.getStreamId();\n if (!pending) return;\n resumeFiredRef.current = true;\n chat.resumeStream().catch((err: unknown) => {\n console.warn(\n \"[assistant-ui] resumable: resume failed; clearing stored stream id\",\n err,\n );\n adapter.storage.clear();\n });\n }, [transport, chat]);\n\n return runtime;\n};\n\nexport const useChatRuntime = <UI_MESSAGE extends UIMessage = UIMessage>({\n cloud,\n ...options\n}: UseChatRuntimeOptions<UI_MESSAGE> = {}): AssistantRuntime => {\n const cloudAdapter = useCloudThreadListAdapter({ cloud });\n return useRemoteThreadListRuntime({\n runtimeHook: function RuntimeHook() {\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n return useChatThreadRuntime(options);\n },\n adapter: cloudAdapter,\n allowNesting: true,\n });\n};\n"],"mappings":";;;;;;;;AA6BA,MAAM,2BACJ,cAC8B;CAE9B,MAAM,eAAe,OAAkC,SAAS;CAEhE,gBAAgB;EACd,aAAa,UAAU;CACzB,CAAC;CAeD,OAbyB,cAErB,IAAI,MAAM,aAAa,SAAS,EAC9B,IAAI,GAAG,MAAM;EACX,MAAM,MACJ,aAAa,QAAQ;EACvB,OAAO,OAAO,QAAQ,aAClB,IAAI,KAAK,aAAa,OAAO,IAC7B;CACN,EACF,CAAC,GACH,CAAC,CAEmB;AACxB;AAEA,MAAM,uBACJ,cAC8C;CAC9C,IAAI,qBAAqB,wBACvB,OAAO,UAAU,oBAAoB;CAEvC,MAAM,YAAa,UAChB;CACH,IAAI,OAAO,cAAc,YAAY,OAAO,KAAA;CAC5C,OAAO,UAAU,KAAK,SAAS;AACjC;AAEA,MAAM,wBACJ,YACqB;CACrB,MAAM,EACJ,UACA,WAAW,kBACX,iBACA,UACA,aACA,GAAG,gBACD,WAAW,CAAC;CAGhB,MAAM,YAAY,wBAChB,oBAAoB,IAAI,uBAAuB,CACjD;CAGA,MAAM,KAAK,aAAa,MAAM,EAAE,eAAe,EAAE;CAEjD,MAAM,MAAM,OAAO;CAEnB,MAAM,OAAO,QAAQ;EACnB,GAAG;EACH;EACA;CACF,CAAC;CAGD,MAAM,UAAU,gBAAgB,MAAM;EACpC;EACA,GAAI,mBAAmB,EAAE,gBAAgB;EACzC,GAAI,YAAY,EAAE,SAAS;EAC3B,GAAI,eAAe,EAAE,YAAY;CACnC,CAAC;CAED,IAAI,qBAAqB,wBAAwB;EAC/C,UAAU,WAAW,OAAO;EAC5B,UAAU,sCACR,IAAI,eAAe,SAAS,IAAI,eAAe,IAAI,KAAA,CACrD;CACF;CAGA,MAAM,iBAAiB,OAAO,KAAK;CAEnC,gBAAgB;EACd,IAAI,eAAe,SAAS;EAC5B,MAAM,UAAU,oBAAoB,SAAS;EAC7C,IAAI,CAAC,SAAS;EAEd,IAAI,CADY,QAAQ,QAAQ,YACrB,GAAG;EACd,eAAe,UAAU;EACzB,KAAK,aAAa,EAAE,OAAO,QAAiB;GAC1C,QAAQ,KACN,sEACA,GACF;GACA,QAAQ,QAAQ,MAAM;EACxB,CAAC;CACH,GAAG,CAAC,WAAW,IAAI,CAAC;CAEpB,OAAO;AACT;AAEA,MAAa,kBAA4D,EACvE,OACA,GAAG,YACkC,CAAC,MAAwB;CAE9D,OAAO,2BAA2B;EAChC,aAAa,SAAS,cAAc;GAElC,OAAO,qBAAqB,OAAO;EACrC;EACA,SANmB,0BAA0B,EAAE,MAAM,CAMjC;EACpB,cAAc;CAChB,CAAC;AACH"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { RefObject } from "react";
|
|
2
|
+
import { AssistantRuntime, ExportedMessageRepository, MessageFormatAdapter, MessageFormatRepository, ThreadHistoryAdapter, ThreadMessage } from "@assistant-ui/core";
|
|
3
|
+
|
|
4
|
+
//#region src/ui/use-chat/useExternalHistory.d.ts
|
|
5
|
+
declare const toExportedMessageRepository: <TMessage>(toThreadMessages: (messages: TMessage[]) => ThreadMessage[], messages: MessageFormatRepository<TMessage>) => ExportedMessageRepository;
|
|
6
|
+
declare const useExternalHistory: <TMessage>(runtimeRef: RefObject<AssistantRuntime>, historyAdapter: ThreadHistoryAdapter | undefined, toThreadMessages: (messages: TMessage[]) => ThreadMessage[], storageFormatAdapter: MessageFormatAdapter<TMessage, any>, onSetMessages: (messages: TMessage[]) => void) => boolean;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { toExportedMessageRepository, useExternalHistory };
|
|
5
9
|
//# sourceMappingURL=useExternalHistory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useExternalHistory.d.ts","
|
|
1
|
+
{"version":3,"file":"useExternalHistory.d.ts","names":[],"sources":["../../../src/ui/use-chat/useExternalHistory.ts"],"mappings":";;;;cAsBa,2BAAA,aACX,gBAAA,GAAmB,QAAA,EAAU,QAAA,OAAe,aAAA,IAC5C,QAAA,EAAU,uBAAA,CAAwB,QAAA,MACjC,yBAAA;AAAA,cAaU,kBAAA,aACX,UAAA,EAAY,SAAA,CAAU,gBAAA,GACtB,cAAA,EAAgB,oBAAA,cAChB,gBAAA,GAAmB,QAAA,EAAU,QAAA,OAAe,aAAA,IAC5C,oBAAA,EAAsB,oBAAA,CAAqB,QAAA,QAC3C,aAAA,GAAgB,QAAA,EAAU,QAAA"}
|
|
@@ -1,207 +1,185 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
3
|
import { getExternalStoreMessages } from "@assistant-ui/core";
|
|
3
4
|
import { MessageRepository } from "@assistant-ui/core/internal";
|
|
4
5
|
import { useAui } from "@assistant-ui/store";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
//#region src/ui/use-chat/useExternalHistory.ts
|
|
7
|
+
const toExportedMessageRepository = (toThreadMessages, messages) => {
|
|
8
|
+
return {
|
|
9
|
+
headId: messages.headId,
|
|
10
|
+
messages: messages.messages.map((m) => {
|
|
11
|
+
const message = toThreadMessages([m.message])[0];
|
|
12
|
+
return {
|
|
13
|
+
...m,
|
|
14
|
+
message
|
|
15
|
+
};
|
|
16
|
+
})
|
|
17
|
+
};
|
|
17
18
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
lastInnerMessageId =
|
|
183
|
-
getLastInnerId(innerMessages) ?? lastInnerMessageId;
|
|
184
|
-
continue;
|
|
185
|
-
}
|
|
186
|
-
historyIds.current.add(message.id);
|
|
187
|
-
const batchItems = toBatchItems(innerMessages);
|
|
188
|
-
for (const item of batchItems) {
|
|
189
|
-
await formatAdapter.append(item);
|
|
190
|
-
}
|
|
191
|
-
lastInnerMessageId =
|
|
192
|
-
getLastInnerId(innerMessages) ?? lastInnerMessageId;
|
|
193
|
-
formatAdapter.reportTelemetry?.(batchItems, telemetryOptions);
|
|
194
|
-
}
|
|
195
|
-
}, 0);
|
|
196
|
-
});
|
|
197
|
-
return () => {
|
|
198
|
-
unsubscribe();
|
|
199
|
-
if (persistTimerRef.current) {
|
|
200
|
-
clearTimeout(persistTimerRef.current);
|
|
201
|
-
persistTimerRef.current = null;
|
|
202
|
-
}
|
|
203
|
-
};
|
|
204
|
-
}, [formatAdapter, storageFormatAdapter, runtimeRef]);
|
|
205
|
-
return isLoading;
|
|
19
|
+
const useExternalHistory = (runtimeRef, historyAdapter, toThreadMessages, storageFormatAdapter, onSetMessages) => {
|
|
20
|
+
const loadedRef = useRef(false);
|
|
21
|
+
const aui = useAui();
|
|
22
|
+
const optionalThreadListItem = useCallback(() => aui.threadListItem.source ? aui.threadListItem() : null, [aui]);
|
|
23
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
24
|
+
const historyIds = useRef(/* @__PURE__ */ new Set());
|
|
25
|
+
const onSetMessagesRef = useRef(onSetMessages);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
onSetMessagesRef.current = onSetMessages;
|
|
28
|
+
});
|
|
29
|
+
const formatAdapter = useMemo(() => {
|
|
30
|
+
if (!historyAdapter) return void 0;
|
|
31
|
+
if (!historyAdapter.withFormat) throw new Error("useAISDKRuntime: ThreadHistoryAdapter is missing the required `withFormat` method.");
|
|
32
|
+
return historyAdapter.withFormat(storageFormatAdapter);
|
|
33
|
+
}, [historyAdapter, storageFormatAdapter]);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (!formatAdapter || loadedRef.current) return;
|
|
36
|
+
const loadHistory = async () => {
|
|
37
|
+
setIsLoading(true);
|
|
38
|
+
try {
|
|
39
|
+
const repo = await formatAdapter.load();
|
|
40
|
+
if (repo && repo.messages.length > 0) {
|
|
41
|
+
const converted = toExportedMessageRepository(toThreadMessages, repo);
|
|
42
|
+
runtimeRef.current.thread.import(converted);
|
|
43
|
+
const tempRepo = new MessageRepository();
|
|
44
|
+
tempRepo.import(converted);
|
|
45
|
+
const messages = tempRepo.getMessages();
|
|
46
|
+
onSetMessagesRef.current(messages.flatMap(getExternalStoreMessages));
|
|
47
|
+
historyIds.current = new Set(converted.messages.map((m) => m.message.id));
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error("Failed to load message history:", error);
|
|
51
|
+
} finally {
|
|
52
|
+
setIsLoading(false);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
loadedRef.current = true;
|
|
56
|
+
if (!optionalThreadListItem()?.getState().remoteId) {
|
|
57
|
+
setIsLoading(false);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
loadHistory();
|
|
61
|
+
}, [
|
|
62
|
+
formatAdapter,
|
|
63
|
+
toThreadMessages,
|
|
64
|
+
runtimeRef,
|
|
65
|
+
optionalThreadListItem
|
|
66
|
+
]);
|
|
67
|
+
const runStartRef = useRef(null);
|
|
68
|
+
const persistTimerRef = useRef(null);
|
|
69
|
+
const stepBoundariesRef = useRef([]);
|
|
70
|
+
const wasRunningRef = useRef(false);
|
|
71
|
+
const toolCallCountRef = useRef(0);
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
if (!formatAdapter) return;
|
|
74
|
+
const unsubscribe = runtimeRef.current.thread.subscribe(() => {
|
|
75
|
+
const { isRunning } = runtimeRef.current.thread.getState();
|
|
76
|
+
const wasRunning = wasRunningRef.current;
|
|
77
|
+
wasRunningRef.current = isRunning;
|
|
78
|
+
if (runStartRef.current != null) {
|
|
79
|
+
const lastMsg = runtimeRef.current.thread.getState().messages.at(-1);
|
|
80
|
+
if (lastMsg?.role === "assistant") {
|
|
81
|
+
const currentToolCallCount = lastMsg.content.filter((p) => p.type === "tool-call").length;
|
|
82
|
+
while (toolCallCountRef.current < currentToolCallCount) {
|
|
83
|
+
stepBoundariesRef.current.push(Date.now() - runStartRef.current);
|
|
84
|
+
toolCallCountRef.current++;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (isRunning) {
|
|
89
|
+
if (runStartRef.current == null) {
|
|
90
|
+
runStartRef.current = Date.now();
|
|
91
|
+
stepBoundariesRef.current = [];
|
|
92
|
+
toolCallCountRef.current = 0;
|
|
93
|
+
}
|
|
94
|
+
if (persistTimerRef.current) {
|
|
95
|
+
clearTimeout(persistTimerRef.current);
|
|
96
|
+
persistTimerRef.current = null;
|
|
97
|
+
}
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (!wasRunning) return;
|
|
101
|
+
if (runStartRef.current != null) stepBoundariesRef.current.push(Date.now() - runStartRef.current);
|
|
102
|
+
if (persistTimerRef.current) clearTimeout(persistTimerRef.current);
|
|
103
|
+
persistTimerRef.current = setTimeout(async () => {
|
|
104
|
+
persistTimerRef.current = null;
|
|
105
|
+
const latest = runtimeRef.current.thread.getState();
|
|
106
|
+
if (latest.isRunning) return;
|
|
107
|
+
const boundaries = stepBoundariesRef.current;
|
|
108
|
+
const durationMs = boundaries.length > 0 ? boundaries.at(-1) : void 0;
|
|
109
|
+
if (boundaries.length === 1 && durationMs != null) {
|
|
110
|
+
const lastAssistant = latest.messages.findLast((m) => m.role === "assistant");
|
|
111
|
+
if (lastAssistant) {
|
|
112
|
+
const tcCount = lastAssistant.content.filter((p) => p.type === "tool-call").length;
|
|
113
|
+
if (tcCount > 0) {
|
|
114
|
+
const totalSteps = tcCount + 1;
|
|
115
|
+
const stepDur = durationMs / totalSteps;
|
|
116
|
+
boundaries.length = 0;
|
|
117
|
+
for (let i = 0; i < totalSteps; i++) boundaries.push(Math.round((i + 1) * stepDur));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const stepTimestamps = boundaries.length > 1 ? boundaries.map((endMs, i) => ({
|
|
122
|
+
start_ms: i === 0 ? 0 : boundaries[i - 1],
|
|
123
|
+
end_ms: endMs
|
|
124
|
+
})) : void 0;
|
|
125
|
+
runStartRef.current = null;
|
|
126
|
+
stepBoundariesRef.current = [];
|
|
127
|
+
const telemetryOptions = {
|
|
128
|
+
...durationMs != null ? { durationMs } : void 0,
|
|
129
|
+
...stepTimestamps != null ? { stepTimestamps } : void 0
|
|
130
|
+
};
|
|
131
|
+
const { messages } = latest;
|
|
132
|
+
let lastInnerMessageId = null;
|
|
133
|
+
const getLastInnerId = (msgs) => msgs.length > 0 ? storageFormatAdapter.getId(msgs.at(-1)) : null;
|
|
134
|
+
const toBatchItems = (msgs) => msgs.map((msg, idx) => ({
|
|
135
|
+
parentId: idx === 0 ? lastInnerMessageId : storageFormatAdapter.getId(msgs[idx - 1]),
|
|
136
|
+
message: msg
|
|
137
|
+
}));
|
|
138
|
+
for (const message of messages) {
|
|
139
|
+
const innerMessages = getExternalStoreMessages(message);
|
|
140
|
+
if (!(message.status === void 0 || message.status.type === "complete" || message.status.type === "incomplete")) {
|
|
141
|
+
lastInnerMessageId = getLastInnerId(innerMessages) ?? lastInnerMessageId;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (historyIds.current.has(message.id)) {
|
|
145
|
+
if (durationMs !== void 0) {
|
|
146
|
+
let parentId = lastInnerMessageId;
|
|
147
|
+
for (const innerMessage of innerMessages) {
|
|
148
|
+
try {
|
|
149
|
+
await formatAdapter.update?.({
|
|
150
|
+
parentId,
|
|
151
|
+
message: innerMessage
|
|
152
|
+
}, storageFormatAdapter.getId(innerMessage));
|
|
153
|
+
} catch {}
|
|
154
|
+
parentId = storageFormatAdapter.getId(innerMessage);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
lastInnerMessageId = getLastInnerId(innerMessages) ?? lastInnerMessageId;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
historyIds.current.add(message.id);
|
|
161
|
+
const batchItems = toBatchItems(innerMessages);
|
|
162
|
+
for (const item of batchItems) await formatAdapter.append(item);
|
|
163
|
+
lastInnerMessageId = getLastInnerId(innerMessages) ?? lastInnerMessageId;
|
|
164
|
+
formatAdapter.reportTelemetry?.(batchItems, telemetryOptions);
|
|
165
|
+
}
|
|
166
|
+
}, 0);
|
|
167
|
+
});
|
|
168
|
+
return () => {
|
|
169
|
+
unsubscribe();
|
|
170
|
+
if (persistTimerRef.current) {
|
|
171
|
+
clearTimeout(persistTimerRef.current);
|
|
172
|
+
persistTimerRef.current = null;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}, [
|
|
176
|
+
formatAdapter,
|
|
177
|
+
storageFormatAdapter,
|
|
178
|
+
runtimeRef
|
|
179
|
+
]);
|
|
180
|
+
return isLoading;
|
|
206
181
|
};
|
|
182
|
+
//#endregion
|
|
183
|
+
export { toExportedMessageRepository, useExternalHistory };
|
|
184
|
+
|
|
207
185
|
//# sourceMappingURL=useExternalHistory.js.map
|