@assistant-ui/react 0.11.39 → 0.11.43
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/client/AssistantClient.d.ts.map +1 -1
- package/dist/client/AssistantClient.js.map +1 -1
- package/dist/client/ModelContext.d.ts +1 -1
- package/dist/client/ModelContext.d.ts.map +1 -1
- package/dist/client/ModelContext.js.map +1 -1
- package/dist/client/ModelContextClient.d.ts +1 -1
- package/dist/client/ThreadMessageClient.d.ts +1 -0
- package/dist/client/ThreadMessageClient.d.ts.map +1 -1
- package/dist/client/ThreadMessageClient.js +3 -1
- package/dist/client/ThreadMessageClient.js.map +1 -1
- package/dist/client/types/Message.d.ts +2 -0
- package/dist/client/types/Message.d.ts.map +1 -1
- package/dist/client/types/ModelContext.d.ts +1 -1
- package/dist/client/types/ModelContext.d.ts.map +1 -1
- package/dist/client/types/Tools.d.ts +1 -2
- package/dist/client/types/Tools.d.ts.map +1 -1
- package/dist/context/providers/ThreadViewportProvider.d.ts +5 -1
- package/dist/context/providers/ThreadViewportProvider.d.ts.map +1 -1
- package/dist/context/providers/ThreadViewportProvider.js +17 -6
- package/dist/context/providers/ThreadViewportProvider.js.map +1 -1
- package/dist/context/react/AssistantApiContext.d.ts +1 -1
- package/dist/context/react/AssistantApiContext.d.ts.map +1 -1
- package/dist/context/react/AssistantApiContext.js +1 -2
- package/dist/context/react/AssistantApiContext.js.map +1 -1
- package/dist/context/stores/ThreadViewport.d.ts +33 -3
- package/dist/context/stores/ThreadViewport.d.ts.map +1 -1
- package/dist/context/stores/ThreadViewport.js +67 -5
- package/dist/context/stores/ThreadViewport.js.map +1 -1
- package/dist/devtools/DevToolsHooks.d.ts +1 -1
- package/dist/devtools/DevToolsHooks.d.ts.map +1 -1
- package/dist/devtools/DevToolsHooks.js.map +1 -1
- package/dist/legacy-runtime/AssistantRuntimeProvider.d.ts.map +1 -1
- package/dist/legacy-runtime/AssistantRuntimeProvider.js +2 -1
- package/dist/legacy-runtime/AssistantRuntimeProvider.js.map +1 -1
- package/dist/legacy-runtime/client/ComposerRuntimeClient.d.ts +3 -3
- package/dist/legacy-runtime/client/ComposerRuntimeClient.d.ts.map +1 -1
- package/dist/legacy-runtime/client/ComposerRuntimeClient.js.map +1 -1
- package/dist/legacy-runtime/client/EventManagerRuntimeClient.d.ts +1 -1
- package/dist/legacy-runtime/client/ThreadRuntimeClient.js.map +1 -1
- package/dist/legacy-runtime/runtime/MessageRuntime.d.ts +3 -0
- package/dist/legacy-runtime/runtime/MessageRuntime.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime/MessageRuntime.js.map +1 -1
- package/dist/legacy-runtime/runtime/RuntimeBindings.d.ts +2 -0
- package/dist/legacy-runtime/runtime/RuntimeBindings.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime/ThreadRuntime.d.ts +1 -0
- package/dist/legacy-runtime/runtime/ThreadRuntime.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime/ThreadRuntime.js +6 -3
- package/dist/legacy-runtime/runtime/ThreadRuntime.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.d.ts +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.js +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/runManager.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/types.d.ts +8 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/types.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js +23 -11
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.js +5 -5
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.d.ts +1 -0
- package/dist/legacy-runtime/runtime-cores/core/BaseThreadRuntimeCore.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.d.ts +1 -0
- package/dist/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts +2 -0
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts +2 -0
- package/dist/legacy-runtime/runtime-cores/remote-thread-list/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.d.ts +1 -0
- package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.js +2 -1
- package/dist/legacy-runtime/runtime-cores/utils/MessageRepository.js.map +1 -1
- package/dist/primitives/composer/ComposerAttachmentDropzone.d.ts +2 -2
- package/dist/primitives/composer/ComposerAttachmentDropzone.d.ts.map +1 -1
- package/dist/primitives/composer/ComposerAttachmentDropzone.js +31 -11
- package/dist/primitives/composer/ComposerAttachmentDropzone.js.map +1 -1
- package/dist/primitives/composer/index.d.ts +1 -0
- package/dist/primitives/composer/index.d.ts.map +1 -1
- package/dist/primitives/composer/index.js +2 -0
- package/dist/primitives/composer/index.js.map +1 -1
- package/dist/primitives/message/MessageRoot.d.ts +3 -0
- package/dist/primitives/message/MessageRoot.d.ts.map +1 -1
- package/dist/primitives/message/MessageRoot.js +24 -2
- package/dist/primitives/message/MessageRoot.js.map +1 -1
- package/dist/primitives/messagePart/useMessagePartData.d.ts.map +1 -1
- package/dist/primitives/messagePart/useMessagePartData.js.map +1 -1
- package/dist/primitives/thread/ThreadScrollToBottom.d.ts +7 -2
- package/dist/primitives/thread/ThreadScrollToBottom.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadScrollToBottom.js +7 -4
- package/dist/primitives/thread/ThreadScrollToBottom.js.map +1 -1
- package/dist/primitives/thread/ThreadViewport.d.ts +17 -3
- package/dist/primitives/thread/ThreadViewport.d.ts.map +1 -1
- package/dist/primitives/thread/ThreadViewport.js +19 -5
- package/dist/primitives/thread/ThreadViewport.js.map +1 -1
- package/dist/primitives/thread/ThreadViewportFooter.d.ts +31 -0
- package/dist/primitives/thread/ThreadViewportFooter.d.ts.map +1 -0
- package/dist/primitives/thread/ThreadViewportFooter.js +27 -0
- package/dist/primitives/thread/ThreadViewportFooter.js.map +1 -0
- package/dist/primitives/thread/ThreadViewportSlack.d.ts +20 -0
- package/dist/primitives/thread/ThreadViewportSlack.d.ts.map +1 -0
- package/dist/primitives/thread/ThreadViewportSlack.js +77 -0
- package/dist/primitives/thread/ThreadViewportSlack.js.map +1 -0
- package/dist/primitives/thread/index.d.ts +3 -0
- package/dist/primitives/thread/index.d.ts.map +1 -1
- package/dist/primitives/thread/index.js +7 -1
- package/dist/primitives/thread/index.js.map +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts +6 -0
- package/dist/primitives/thread/useThreadViewportAutoScroll.d.ts.map +1 -1
- package/dist/primitives/thread/useThreadViewportAutoScroll.js +17 -8
- package/dist/primitives/thread/useThreadViewportAutoScroll.js.map +1 -1
- package/dist/tests/setup.js +14 -14
- package/dist/tests/setup.js.map +1 -1
- package/dist/utils/hooks/useOnScrollToBottom.d.ts +3 -1
- package/dist/utils/hooks/useOnScrollToBottom.d.ts.map +1 -1
- package/dist/utils/hooks/useOnScrollToBottom.js.map +1 -1
- package/dist/utils/hooks/useSizeHandle.d.ts +11 -0
- package/dist/utils/hooks/useSizeHandle.d.ts.map +1 -0
- package/dist/utils/hooks/useSizeHandle.js +30 -0
- package/dist/utils/hooks/useSizeHandle.js.map +1 -0
- package/dist/utils/tap-store/derived-scopes.d.ts +2 -1
- package/dist/utils/tap-store/derived-scopes.d.ts.map +1 -1
- package/dist/utils/tap-store/derived-scopes.js.map +1 -1
- package/dist/utils/tap-store/store.d.ts +2 -1
- package/dist/utils/tap-store/store.d.ts.map +1 -1
- package/dist/utils/tap-store/store.js.map +1 -1
- package/package.json +6 -6
- package/src/client/AssistantClient.ts +1 -1
- package/src/client/ModelContext.ts +1 -1
- package/src/client/ThreadMessageClient.tsx +4 -1
- package/src/client/types/Message.ts +3 -0
- package/src/client/types/ModelContext.ts +1 -1
- package/src/client/types/Tools.ts +1 -2
- package/src/context/providers/ThreadViewportProvider.tsx +27 -5
- package/src/context/react/AssistantApiContext.tsx +2 -5
- package/src/context/stores/ThreadViewport.tsx +125 -7
- package/src/devtools/DevToolsHooks.ts +1 -1
- package/src/legacy-runtime/AssistantRuntimeProvider.tsx +6 -1
- package/src/legacy-runtime/client/ComposerRuntimeClient.ts +3 -3
- package/src/legacy-runtime/client/ThreadRuntimeClient.ts +2 -2
- package/src/legacy-runtime/runtime/MessageRuntime.ts +2 -0
- package/src/legacy-runtime/runtime/RuntimeBindings.ts +2 -0
- package/src/legacy-runtime/runtime/ThreadRuntime.ts +6 -3
- package/src/legacy-runtime/runtime-cores/assistant-transport/runManager.ts +2 -2
- package/src/legacy-runtime/runtime-cores/assistant-transport/types.ts +8 -1
- package/src/legacy-runtime/runtime-cores/assistant-transport/useAssistantTransportRuntime.tsx +26 -11
- package/src/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.ts +5 -5
- package/src/legacy-runtime/runtime-cores/core/ThreadRuntimeCore.tsx +1 -0
- package/src/legacy-runtime/runtime-cores/utils/MessageRepository.tsx +1 -0
- package/src/primitives/composer/ComposerAttachmentDropzone.tsx +35 -12
- package/src/primitives/composer/index.ts +1 -0
- package/src/primitives/message/MessageRoot.tsx +45 -2
- package/src/primitives/messagePart/useMessagePartData.tsx +0 -1
- package/src/primitives/thread/ThreadScrollToBottom.tsx +12 -3
- package/src/primitives/thread/ThreadViewport.tsx +35 -9
- package/src/primitives/thread/ThreadViewportFooter.tsx +57 -0
- package/src/primitives/thread/ThreadViewportSlack.tsx +109 -0
- package/src/primitives/thread/index.ts +3 -0
- package/src/primitives/thread/useThreadViewportAutoScroll.tsx +24 -12
- package/src/utils/hooks/useOnScrollToBottom.tsx +3 -1
- package/src/utils/hooks/useSizeHandle.ts +43 -0
- package/src/utils/tap-store/derived-scopes.ts +2 -1
- package/src/utils/tap-store/store.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOnScrollToBottom.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useOnScrollToBottom.tsx"],"names":[],"mappings":"AAMA,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"useOnScrollToBottom.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useOnScrollToBottom.tsx"],"names":[],"mappings":"AAMA,eAAO,MAAM,mBAAmB,GAC9B,UAAU,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,cAAc,CAAA;CAAE,KAAK,IAAI,SAQzD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/hooks/useOnScrollToBottom.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallbackRef } from \"@radix-ui/react-use-callback-ref\";\nimport { useEffect } from \"react\";\nimport { useThreadViewport } from \"../../context/react/ThreadViewportContext\";\n\nexport const useOnScrollToBottom = (callback: () => void) => {\n const callbackRef = useCallbackRef(callback);\n const onScrollToBottom = useThreadViewport((vp) => vp.onScrollToBottom);\n\n useEffect(() => {\n return onScrollToBottom(callbackRef);\n }, [onScrollToBottom, callbackRef]);\n};\n"],"mappings":";;;AAEA,SAAS,sBAAsB;AAC/B,SAAS,iBAAiB;AAC1B,SAAS,yBAAyB;AAE3B,IAAM,sBAAsB,
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/hooks/useOnScrollToBottom.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallbackRef } from \"@radix-ui/react-use-callback-ref\";\nimport { useEffect } from \"react\";\nimport { useThreadViewport } from \"../../context/react/ThreadViewportContext\";\n\nexport const useOnScrollToBottom = (\n callback: (config: { behavior: ScrollBehavior }) => void,\n) => {\n const callbackRef = useCallbackRef(callback);\n const onScrollToBottom = useThreadViewport((vp) => vp.onScrollToBottom);\n\n useEffect(() => {\n return onScrollToBottom(callbackRef);\n }, [onScrollToBottom, callbackRef]);\n};\n"],"mappings":";;;AAEA,SAAS,sBAAsB;AAC/B,SAAS,iBAAiB;AAC1B,SAAS,yBAAyB;AAE3B,IAAM,sBAAsB,CACjC,aACG;AACH,QAAM,cAAc,eAAe,QAAQ;AAC3C,QAAM,mBAAmB,kBAAkB,CAAC,OAAO,GAAG,gBAAgB;AAEtE,YAAU,MAAM;AACd,WAAO,iBAAiB,WAAW;AAAA,EACrC,GAAG,CAAC,kBAAkB,WAAW,CAAC;AACpC;","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SizeHandle } from "../../context/stores/ThreadViewport";
|
|
2
|
+
/**
|
|
3
|
+
* Hook that creates a ref for tracking element size via a SizeHandle.
|
|
4
|
+
* Automatically sets up ResizeObserver and reports height changes.
|
|
5
|
+
*
|
|
6
|
+
* @param register - Function that returns a SizeHandle (e.g., registerContentInset)
|
|
7
|
+
* @param getHeight - Optional function to compute height (defaults to el.offsetHeight)
|
|
8
|
+
* @returns A ref callback to attach to the element
|
|
9
|
+
*/
|
|
10
|
+
export declare const useSizeHandle: (register: (() => SizeHandle) | null | undefined, getHeight?: (el: HTMLElement) => number) => (el: HTMLElement | null) => void;
|
|
11
|
+
//# sourceMappingURL=useSizeHandle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSizeHandle.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/useSizeHandle.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAEtE;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GACxB,UAAU,CAAC,MAAM,UAAU,CAAC,GAAG,IAAI,GAAG,SAAS,EAC/C,YAAY,CAAC,EAAE,EAAE,WAAW,KAAK,MAAM,qCA0BxC,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/utils/hooks/useSizeHandle.ts
|
|
4
|
+
import { useCallback } from "react";
|
|
5
|
+
import { useManagedRef } from "./useManagedRef.js";
|
|
6
|
+
var useSizeHandle = (register, getHeight) => {
|
|
7
|
+
const callbackRef = useCallback(
|
|
8
|
+
(el) => {
|
|
9
|
+
if (!register) return;
|
|
10
|
+
const sizeHandle = register();
|
|
11
|
+
const updateHeight = () => {
|
|
12
|
+
const height = getHeight ? getHeight(el) : el.offsetHeight;
|
|
13
|
+
sizeHandle.setHeight(height);
|
|
14
|
+
};
|
|
15
|
+
const ro = new ResizeObserver(updateHeight);
|
|
16
|
+
ro.observe(el);
|
|
17
|
+
updateHeight();
|
|
18
|
+
return () => {
|
|
19
|
+
ro.disconnect();
|
|
20
|
+
sizeHandle.unregister();
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
[register, getHeight]
|
|
24
|
+
);
|
|
25
|
+
return useManagedRef(callbackRef);
|
|
26
|
+
};
|
|
27
|
+
export {
|
|
28
|
+
useSizeHandle
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=useSizeHandle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/hooks/useSizeHandle.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback } from \"react\";\nimport { useManagedRef } from \"./useManagedRef\";\nimport type { SizeHandle } from \"../../context/stores/ThreadViewport\";\n\n/**\n * Hook that creates a ref for tracking element size via a SizeHandle.\n * Automatically sets up ResizeObserver and reports height changes.\n *\n * @param register - Function that returns a SizeHandle (e.g., registerContentInset)\n * @param getHeight - Optional function to compute height (defaults to el.offsetHeight)\n * @returns A ref callback to attach to the element\n */\nexport const useSizeHandle = (\n register: (() => SizeHandle) | null | undefined,\n getHeight?: (el: HTMLElement) => number,\n) => {\n const callbackRef = useCallback(\n (el: HTMLElement) => {\n if (!register) return;\n\n const sizeHandle = register();\n\n const updateHeight = () => {\n const height = getHeight ? getHeight(el) : el.offsetHeight;\n sizeHandle.setHeight(height);\n };\n\n const ro = new ResizeObserver(updateHeight);\n ro.observe(el);\n updateHeight();\n\n return () => {\n ro.disconnect();\n sizeHandle.unregister();\n };\n },\n [register, getHeight],\n );\n\n return useManagedRef(callbackRef);\n};\n"],"mappings":";;;AAEA,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAWvB,IAAM,gBAAgB,CAC3B,UACA,cACG;AACH,QAAM,cAAc;AAAA,IAClB,CAAC,OAAoB;AACnB,UAAI,CAAC,SAAU;AAEf,YAAM,aAAa,SAAS;AAE5B,YAAM,eAAe,MAAM;AACzB,cAAM,SAAS,YAAY,UAAU,EAAE,IAAI,GAAG;AAC9C,mBAAW,UAAU,MAAM;AAAA,MAC7B;AAEA,YAAM,KAAK,IAAI,eAAe,YAAY;AAC1C,SAAG,QAAQ,EAAE;AACb,mBAAa;AAEb,aAAO,MAAM;AACX,WAAG,WAAW;AACd,mBAAW,WAAW;AAAA,MACxB;AAAA,IACF;AAAA,IACA,CAAC,UAAU,SAAS;AAAA,EACtB;AAEA,SAAO,cAAc,WAAW;AAClC;","names":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AssistantApi, AssistantApiField } from "../../context/react/AssistantApiContext";
|
|
2
2
|
import type { AssistantEvent, AssistantEventCallback, AssistantEventSelector } from "../../types/EventTypes";
|
|
3
|
-
import type { ResourceElement
|
|
3
|
+
import type { ResourceElement } from "@assistant-ui/tap";
|
|
4
|
+
import { Unsubscribe } from "../../types";
|
|
4
5
|
/**
|
|
5
6
|
* Extract the API return type from an AssistantApiField
|
|
6
7
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derived-scopes.d.ts","sourceRoot":"","sources":["../../../src/utils/tap-store/derived-scopes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"derived-scopes.d.ts","sourceRoot":"","sources":["../../../src/utils/tap-store/derived-scopes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;GAEG;AACH,KAAK,cAAc,CAAC,CAAC,IACnB,CAAC,SAAS,iBAAiB,CAAC,MAAM,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;AAE9D;;;;;GAKG;AACH,KAAK,WAAW,CAAC,CAAC,IAChB,CAAC,SAAS,iBAAiB,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC;AAEhE;;GAEG;AACH,KAAK,sBAAsB,GAAG;KAC3B,CAAC,IAAI,MAAM,YAAY,GAAG,YAAY,CAAC,CAAC,CAAC,SAAS;QAAE,MAAM,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,GAC1E,CAAC,GACD,KAAK;CACV,CAAC,MAAM,YAAY,CAAC,CAAC;AAEtB;;GAEG;AACH,MAAM,MAAM,kBAAkB,CAAC,OAAO,SAAS,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,IAAI;IAC5E,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,SAAS,cAAc,EACvD,QAAQ,EAAE,sBAAsB,CAAC,MAAM,CAAC,EACxC,QAAQ,EAAE,sBAAsB,CAAC,MAAM,CAAC,KACrC,WAAW,CAAC;AAEjB;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,WAAW,CAAC;AAExE;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,SAAS,CAAC,EAAE,mBAAmB,CAAC;CACjC,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG;KAC9B,CAAC,IAAI,sBAAsB,CAAC,CAAC,EAAE,eAAe,CAC7C,iBAAiB,CACf,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAC/B;QACE,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC/C,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;KAC9C,CACF,CACF;CACF,GAAG,gBAAgB,CAAC;AAErB;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GACtB,OAAO,SAAS,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI;;;YAKhC,OAAO;WACR,MAAM;8CAgBlB,CAAC;AAmBF;;;GAGG;AACH,eAAO,MAAM,aAAa,iFAyCzB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/tap-store/derived-scopes.ts"],"sourcesContent":["import { resource, tapEffect } from \"@assistant-ui/tap\";\nimport { tapMemo, tapRef, tapResource, tapResources } from \"@assistant-ui/tap\";\nimport { createAssistantApiField } from \"../../context/react/AssistantApiContext\";\nimport type {\n AssistantApi,\n AssistantApiField,\n} from \"../../context/react/AssistantApiContext\";\nimport type {\n AssistantEvent,\n AssistantEventCallback,\n AssistantEventSelector,\n} from \"../../types/EventTypes\";\nimport type { ResourceElement
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/tap-store/derived-scopes.ts"],"sourcesContent":["import { resource, tapEffect } from \"@assistant-ui/tap\";\nimport { tapMemo, tapRef, tapResource, tapResources } from \"@assistant-ui/tap\";\nimport { createAssistantApiField } from \"../../context/react/AssistantApiContext\";\nimport type {\n AssistantApi,\n AssistantApiField,\n} from \"../../context/react/AssistantApiContext\";\nimport type {\n AssistantEvent,\n AssistantEventCallback,\n AssistantEventSelector,\n} from \"../../types/EventTypes\";\nimport type { ResourceElement } from \"@assistant-ui/tap\";\nimport { Unsubscribe } from \"../../types\";\n\n/**\n * Extract the API return type from an AssistantApiField\n */\ntype ExtractApiType<T> =\n T extends AssistantApiField<infer TApi, any> ? TApi : never;\n\n/**\n * Extract the metadata type from an AssistantApiField\n *\n * Used in DerivedScopesInput to validate that each field's source/query types match\n * the expected types from AssistantApi.\n */\ntype ExtractMeta<T> =\n T extends AssistantApiField<any, infer TMeta> ? TMeta : never;\n\n/**\n * Get only the field names from AssistantApi (exclude method names)\n */\ntype AssistantApiFieldNames = {\n [K in keyof AssistantApi]: AssistantApi[K] extends { source: any; query: any }\n ? K\n : never;\n}[keyof AssistantApi];\n\n/**\n * Configuration for a derived scope field - infers types from the actual values provided\n */\nexport type DerivedScopeConfig<TSource extends string | null, TQuery, TApi> = {\n source: TSource;\n query: TQuery;\n get: () => TApi;\n};\n\n/**\n * Type for the special `on` callback function\n */\nexport type OnCallbackFn = <TEvent extends AssistantEvent>(\n selector: AssistantEventSelector<TEvent>,\n callback: AssistantEventCallback<TEvent>,\n) => Unsubscribe;\n\n/**\n * Type for the special `subscribe` callback function\n */\nexport type SubscribeCallbackFn = (listener: () => void) => Unsubscribe;\n\n/**\n * Type for the special `flushSync` callback function\n */\nexport type FlushSyncCallbackFn = () => void;\n\n/**\n * Type for special non-field functions in AssistantApi\n */\nexport type SpecialCallbacks = {\n on?: OnCallbackFn;\n subscribe?: SubscribeCallbackFn;\n flushSync?: FlushSyncCallbackFn;\n};\n\n/**\n * Type for the scopes parameter - allows both DerivedScope elements and special callbacks.\n * Field names are restricted to valid AssistantApi field names.\n * TypeScript validates that the source/query/get types match the expected field type.\n */\nexport type DerivedScopesInput = {\n [K in AssistantApiFieldNames]?: ResourceElement<\n AssistantApiField<\n ExtractApiType<AssistantApi[K]>,\n {\n source: ExtractMeta<AssistantApi[K]>[\"source\"];\n query: ExtractMeta<AssistantApi[K]>[\"query\"];\n }\n >\n >;\n} & SpecialCallbacks;\n\n/**\n * DerivedScope resource - memoizes an AssistantApiField based on source and query.\n * The get callback always calls the most recent version (useEffectEvent pattern).\n * TypeScript infers TSource, TQuery, and TApi from the config object.\n * Validation happens at the DerivedScopesInput level.\n */\nexport const DerivedScope = resource(\n <TSource extends string | null, TQuery, TApi>(\n config: DerivedScopeConfig<TSource, TQuery, TApi>,\n ): AssistantApiField<\n TApi,\n {\n source: TSource;\n query: TQuery;\n }\n > => {\n const getRef = tapRef(config.get);\n tapEffect(() => {\n getRef.current = config.get;\n });\n\n return tapMemo(() => {\n return createAssistantApiField({\n source: config.source,\n query: config.query,\n get: () => getRef.current(),\n });\n }, [config.source, JSON.stringify(config.query)]);\n },\n);\n\n/**\n * Helper resource to wrap each scope field - stable resource identity for proper memoization.\n * Creating this outside the map ensures tapResources can properly track and memoize each field.\n */\nconst ScopeFieldWithNameResource = resource(\n (config: {\n fieldName: string;\n scopeElement: ReturnType<typeof DerivedScope>;\n }) => {\n const field = tapResource(config.scopeElement);\n return tapMemo(\n () => [config.fieldName, field] as const,\n [config.fieldName, field],\n );\n },\n);\n\n/**\n * DerivedScopes resource - takes an object of DerivedScope resource elements and special callbacks,\n * and returns a Partial<AssistantApi> with all the derived fields.\n */\nexport const DerivedScopes = resource(\n (scopes: DerivedScopesInput): Partial<AssistantApi> => {\n const { on, subscribe, flushSync, ...scopeFields } = scopes;\n const callbacksRef = tapRef({ on, subscribe, flushSync });\n tapEffect(() => {\n callbacksRef.current = { on, subscribe, flushSync };\n });\n\n const results = tapResources(\n Object.entries(scopeFields).map(([fieldName, scopeElement]) =>\n ScopeFieldWithNameResource(\n {\n fieldName,\n scopeElement: scopeElement as ReturnType<typeof DerivedScope>,\n },\n { key: fieldName },\n ),\n ),\n );\n\n return tapMemo(() => {\n const result = Object.fromEntries(results) as Partial<AssistantApi>;\n\n const {\n on: onCb,\n subscribe: subCb,\n flushSync: flushCb,\n } = callbacksRef.current;\n\n if (onCb) {\n result.on = <TEvent extends AssistantEvent>(\n selector: AssistantEventSelector<TEvent>,\n callback: AssistantEventCallback<TEvent>,\n ) => onCb(selector, callback);\n }\n if (subCb) result.subscribe = (listener) => subCb(listener);\n if (flushCb) result.flushSync = () => flushCb();\n\n return result;\n }, [...results]);\n },\n);\n"],"mappings":";AAAA,SAAS,UAAU,iBAAiB;AACpC,SAAS,SAAS,QAAQ,aAAa,oBAAoB;AAC3D,SAAS,+BAA+B;AAgGjC,IAAM,eAAe;AAAA,EAC1B,CACE,WAOG;AACH,UAAM,SAAS,OAAO,OAAO,GAAG;AAChC,cAAU,MAAM;AACd,aAAO,UAAU,OAAO;AAAA,IAC1B,CAAC;AAED,WAAO,QAAQ,MAAM;AACnB,aAAO,wBAAwB;AAAA,QAC7B,QAAQ,OAAO;AAAA,QACf,OAAO,OAAO;AAAA,QACd,KAAK,MAAM,OAAO,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACH,GAAG,CAAC,OAAO,QAAQ,KAAK,UAAU,OAAO,KAAK,CAAC,CAAC;AAAA,EAClD;AACF;AAMA,IAAM,6BAA6B;AAAA,EACjC,CAAC,WAGK;AACJ,UAAM,QAAQ,YAAY,OAAO,YAAY;AAC7C,WAAO;AAAA,MACL,MAAM,CAAC,OAAO,WAAW,KAAK;AAAA,MAC9B,CAAC,OAAO,WAAW,KAAK;AAAA,IAC1B;AAAA,EACF;AACF;AAMO,IAAM,gBAAgB;AAAA,EAC3B,CAAC,WAAsD;AACrD,UAAM,EAAE,IAAI,WAAW,WAAW,GAAG,YAAY,IAAI;AACrD,UAAM,eAAe,OAAO,EAAE,IAAI,WAAW,UAAU,CAAC;AACxD,cAAU,MAAM;AACd,mBAAa,UAAU,EAAE,IAAI,WAAW,UAAU;AAAA,IACpD,CAAC;AAED,UAAM,UAAU;AAAA,MACd,OAAO,QAAQ,WAAW,EAAE;AAAA,QAAI,CAAC,CAAC,WAAW,YAAY,MACvD;AAAA,UACE;AAAA,YACE;AAAA,YACA;AAAA,UACF;AAAA,UACA,EAAE,KAAK,UAAU;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAEA,WAAO,QAAQ,MAAM;AACnB,YAAM,SAAS,OAAO,YAAY,OAAO;AAEzC,YAAM;AAAA,QACJ,IAAI;AAAA,QACJ,WAAW;AAAA,QACX,WAAW;AAAA,MACb,IAAI,aAAa;AAEjB,UAAI,MAAM;AACR,eAAO,KAAK,CACV,UACA,aACG,KAAK,UAAU,QAAQ;AAAA,MAC9B;AACA,UAAI,MAAO,QAAO,YAAY,CAAC,aAAa,MAAM,QAAQ;AAC1D,UAAI,QAAS,QAAO,YAAY,MAAM,QAAQ;AAE9C,aAAO;AAAA,IACT,GAAG,CAAC,GAAG,OAAO,CAAC;AAAA,EACjB;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/utils/tap-store/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,eAAe,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/utils/tap-store/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,eAAe,EAGhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,KAAK,CAAC,MAAM;IAC3B;;OAEG;IACH,QAAQ,IAAI,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,WAAW,CAAC;IAE7C;;OAEG;IACH,SAAS,IAAI,IAAI,CAAC;CACnB;AAED,eAAO,MAAM,OAAO,GACjB,MAAM,EAAE,MAAM;;iFAYhB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/tap-store/store.ts"],"sourcesContent":["import {\n tapMemo,\n tapEffect,\n ResourceElement,\n resource,\n createResource,\n
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/tap-store/store.ts"],"sourcesContent":["import {\n tapMemo,\n tapEffect,\n ResourceElement,\n resource,\n createResource,\n} from \"@assistant-ui/tap\";\nimport { Unsubscribe } from \"../../types\";\n\nexport interface Store<TState> {\n /**\n * Get the current state of the store.\n */\n getState(): TState;\n\n /**\n * Subscribe to the store.\n */\n subscribe(listener: () => void): Unsubscribe;\n\n /**\n * Synchronously flush all the updates to the store.\n */\n flushSync(): void;\n}\n\nexport const asStore = resource(\n <TState, TProps>(element: ResourceElement<TState, TProps>): Store<TState> => {\n const resource = tapMemo(\n () => createResource(element, true),\n [element.type],\n );\n\n tapEffect(() => {\n resource.updateInput(element.props);\n });\n\n return resource;\n },\n);\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,OACK;AAoBA,IAAM,UAAU;AAAA,EACrB,CAAiB,YAA4D;AAC3E,UAAMA,YAAW;AAAA,MACf,MAAM,eAAe,SAAS,IAAI;AAAA,MAClC,CAAC,QAAQ,IAAI;AAAA,IACf;AAEA,cAAU,MAAM;AACd,MAAAA,UAAS,YAAY,QAAQ,KAAK;AAAA,IACpC,CAAC;AAED,WAAOA;AAAA,EACT;AACF;","names":["resource"]}
|
package/package.json
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"conversational-ui",
|
|
29
29
|
"conversational-ai"
|
|
30
30
|
],
|
|
31
|
-
"version": "0.11.
|
|
31
|
+
"version": "0.11.43",
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"type": "module",
|
|
34
34
|
"exports": {
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
],
|
|
49
49
|
"sideEffects": false,
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"assistant-cloud": "^0.1.
|
|
52
|
-
"@assistant-ui/tap": "^0.
|
|
51
|
+
"assistant-cloud": "^0.1.8",
|
|
52
|
+
"@assistant-ui/tap": "^0.3.0",
|
|
53
53
|
"@radix-ui/primitive": "^1.1.3",
|
|
54
54
|
"@radix-ui/react-compose-refs": "^1.1.2",
|
|
55
55
|
"@radix-ui/react-context": "^1.1.3",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@radix-ui/react-use-callback-ref": "^1.1.1",
|
|
60
60
|
"@radix-ui/react-use-escape-keydown": "^1.1.1",
|
|
61
61
|
"@standard-schema/spec": "^1.0.0",
|
|
62
|
-
"assistant-stream": "^0.2.
|
|
62
|
+
"assistant-stream": "^0.2.41",
|
|
63
63
|
"json-schema": "^0.4.0",
|
|
64
64
|
"nanoid": "5.1.6",
|
|
65
65
|
"react-textarea-autosize": "^8.5.9",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"eslint": "^9",
|
|
89
89
|
"eslint-config-next": "16.0.3",
|
|
90
90
|
"tsx": "^4.20.6",
|
|
91
|
-
"vitest": "^4.0.
|
|
91
|
+
"vitest": "^4.0.10",
|
|
92
92
|
"@assistant-ui/x-buildutils": "0.0.1"
|
|
93
93
|
},
|
|
94
94
|
"publishConfig": {
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"homepage": "https://www.assistant-ui.com/",
|
|
99
99
|
"repository": {
|
|
100
100
|
"type": "git",
|
|
101
|
-
"url": "https://github.com/assistant-ui/assistant-ui
|
|
101
|
+
"url": "https://github.com/assistant-ui/assistant-ui"
|
|
102
102
|
},
|
|
103
103
|
"bugs": {
|
|
104
104
|
"url": "https://github.com/assistant-ui/assistant-ui/issues"
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
tapMemo,
|
|
3
3
|
resource,
|
|
4
|
-
Unsubscribe,
|
|
5
4
|
tapInlineResource,
|
|
6
5
|
ResourceElement,
|
|
7
6
|
tapResource,
|
|
@@ -29,6 +28,7 @@ import { withModelContextProvider } from "./ModelContext";
|
|
|
29
28
|
import { ToolsApi, ToolsState } from "./types/Tools";
|
|
30
29
|
import { ModelContextApi, ModelContextState } from "./types/ModelContext";
|
|
31
30
|
import { ModelContext as ModelContextResource } from "./ModelContextClient";
|
|
31
|
+
import { Unsubscribe } from "../types";
|
|
32
32
|
|
|
33
33
|
type AssistantClientState = {
|
|
34
34
|
readonly threads: ThreadListClientState;
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
createContext,
|
|
3
3
|
tapContext,
|
|
4
4
|
withContextProvider,
|
|
5
|
-
Unsubscribe,
|
|
6
5
|
} from "@assistant-ui/tap";
|
|
7
6
|
import { ModelContextProvider } from "../model-context/ModelContextTypes";
|
|
7
|
+
import { Unsubscribe } from "../types";
|
|
8
8
|
|
|
9
9
|
export type ModelContextRegistrar = ModelContextProvider & {
|
|
10
10
|
register: (provider: ModelContextProvider) => Unsubscribe;
|
|
@@ -63,6 +63,7 @@ const ThreadMessageAttachmentClient = resource(
|
|
|
63
63
|
);
|
|
64
64
|
export type ThreadMessageClientProps = {
|
|
65
65
|
message: ThreadMessage;
|
|
66
|
+
index: number;
|
|
66
67
|
isLast?: boolean;
|
|
67
68
|
branchNumber?: number;
|
|
68
69
|
branchCount?: number;
|
|
@@ -70,6 +71,7 @@ export type ThreadMessageClientProps = {
|
|
|
70
71
|
export const ThreadMessageClient = resource(
|
|
71
72
|
({
|
|
72
73
|
message,
|
|
74
|
+
index,
|
|
73
75
|
isLast = true,
|
|
74
76
|
branchNumber = 1,
|
|
75
77
|
branchCount = 1,
|
|
@@ -102,6 +104,7 @@ export const ThreadMessageClient = resource(
|
|
|
102
104
|
parts: parts.state,
|
|
103
105
|
composer: composerState.state,
|
|
104
106
|
parentId: null,
|
|
107
|
+
index,
|
|
105
108
|
isLast,
|
|
106
109
|
branchNumber,
|
|
107
110
|
branchCount,
|
|
@@ -110,7 +113,7 @@ export const ThreadMessageClient = resource(
|
|
|
110
113
|
isCopied: isCopiedState,
|
|
111
114
|
isHovering: isHoveringState,
|
|
112
115
|
};
|
|
113
|
-
}, [message, isCopiedState, isHoveringState, isLast]);
|
|
116
|
+
}, [message, index, isCopiedState, isHoveringState, isLast]);
|
|
114
117
|
|
|
115
118
|
return tapApi<MessageClientApi>({
|
|
116
119
|
getState: () => state,
|
|
@@ -30,6 +30,9 @@ export type MessageClientState = ThreadMessage & {
|
|
|
30
30
|
|
|
31
31
|
readonly isCopied: boolean;
|
|
32
32
|
readonly isHovering: boolean;
|
|
33
|
+
|
|
34
|
+
/** The position of this message in the thread (0 for first message) */
|
|
35
|
+
readonly index: number;
|
|
33
36
|
};
|
|
34
37
|
|
|
35
38
|
export type MessageClientApi = {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Unsubscribe } from "
|
|
2
|
-
import { ToolCallMessagePartComponent } from "../../types";
|
|
1
|
+
import { ToolCallMessagePartComponent, Unsubscribe } from "../../types";
|
|
3
2
|
|
|
4
3
|
export type ToolsState = {
|
|
5
4
|
tools: Record<string, ToolCallMessagePartComponent[]>;
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import type { FC, PropsWithChildren } from "react";
|
|
4
4
|
import { useEffect, useState } from "react";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
makeThreadViewportStore,
|
|
7
|
+
type ThreadViewportStoreOptions,
|
|
8
|
+
} from "../stores/ThreadViewport";
|
|
6
9
|
import {
|
|
7
10
|
ThreadViewportContext,
|
|
8
11
|
ThreadViewportContextValue,
|
|
@@ -10,10 +13,15 @@ import {
|
|
|
10
13
|
} from "../react/ThreadViewportContext";
|
|
11
14
|
import { writableStore } from "../ReadonlyStore";
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
export type ThreadViewportProviderProps = PropsWithChildren<{
|
|
17
|
+
options?: ThreadViewportStoreOptions;
|
|
18
|
+
}>;
|
|
19
|
+
|
|
20
|
+
const useThreadViewportStoreValue = (options: ThreadViewportStoreOptions) => {
|
|
14
21
|
const outerViewport = useThreadViewportStore({ optional: true });
|
|
15
|
-
const [store] = useState(() => makeThreadViewportStore());
|
|
22
|
+
const [store] = useState(() => makeThreadViewportStore(options));
|
|
16
23
|
|
|
24
|
+
// Forward scrollToBottom from outer viewport to inner viewport
|
|
17
25
|
useEffect(() => {
|
|
18
26
|
return outerViewport?.getState().onScrollToBottom(() => {
|
|
19
27
|
store.getState().scrollToBottom();
|
|
@@ -29,11 +37,25 @@ const useThreadViewportStoreValue = () => {
|
|
|
29
37
|
});
|
|
30
38
|
}, [store, outerViewport]);
|
|
31
39
|
|
|
40
|
+
// Sync options to store when they change
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const nextState = {
|
|
43
|
+
turnAnchor: options.turnAnchor ?? "bottom",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const currentState = store.getState();
|
|
47
|
+
if (currentState.turnAnchor !== nextState.turnAnchor) {
|
|
48
|
+
writableStore(store).setState(nextState);
|
|
49
|
+
}
|
|
50
|
+
}, [store, options.turnAnchor]);
|
|
51
|
+
|
|
32
52
|
return store;
|
|
33
53
|
};
|
|
34
54
|
|
|
35
|
-
export const
|
|
36
|
-
|
|
55
|
+
export const ThreadPrimitiveViewportProvider: FC<
|
|
56
|
+
ThreadViewportProviderProps
|
|
57
|
+
> = ({ children, options = {} }) => {
|
|
58
|
+
const useThreadViewport = useThreadViewportStoreValue(options);
|
|
37
59
|
|
|
38
60
|
const [context] = useState<ThreadViewportContextValue>(() => {
|
|
39
61
|
return {
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
AttachmentClientApi,
|
|
32
32
|
AttachmentClientState,
|
|
33
33
|
} from "../../client/types/Attachment";
|
|
34
|
-
import { Unsubscribe } from "
|
|
34
|
+
import { Unsubscribe } from "../../types";
|
|
35
35
|
import {
|
|
36
36
|
AssistantEvent,
|
|
37
37
|
AssistantEventCallback,
|
|
@@ -42,7 +42,6 @@ import {
|
|
|
42
42
|
ThreadListClientApi,
|
|
43
43
|
ThreadListClientState,
|
|
44
44
|
} from "../../client/types/ThreadList";
|
|
45
|
-
import { ThreadViewportProvider } from "../providers/ThreadViewportProvider";
|
|
46
45
|
import { DevToolsProviderApi } from "../../devtools/DevToolsHooks";
|
|
47
46
|
import {
|
|
48
47
|
AssistantClientProps,
|
|
@@ -354,9 +353,7 @@ export const AssistantProvider: FC<
|
|
|
354
353
|
|
|
355
354
|
return (
|
|
356
355
|
<AssistantApiContext.Provider value={api}>
|
|
357
|
-
{
|
|
358
|
-
{/* TODO figure out if this behavior should be deprecated, since it is quite hacky */}
|
|
359
|
-
<ThreadViewportProvider>{children}</ThreadViewportProvider>
|
|
356
|
+
{children}
|
|
360
357
|
</AssistantApiContext.Provider>
|
|
361
358
|
);
|
|
362
359
|
};
|
|
@@ -3,20 +3,124 @@
|
|
|
3
3
|
import { create } from "zustand";
|
|
4
4
|
import type { Unsubscribe } from "../../types/Unsubscribe";
|
|
5
5
|
|
|
6
|
+
export type SizeHandle = {
|
|
7
|
+
/** Update the height */
|
|
8
|
+
setHeight: (height: number) => void;
|
|
9
|
+
/** Unregister this handle */
|
|
10
|
+
unregister: Unsubscribe;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type SizeRegistry = {
|
|
14
|
+
register: () => SizeHandle;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const createSizeRegistry = (
|
|
18
|
+
onChange: (total: number) => void,
|
|
19
|
+
): SizeRegistry => {
|
|
20
|
+
const entries = new Map<symbol, number>();
|
|
21
|
+
|
|
22
|
+
const recalculate = () => {
|
|
23
|
+
let total = 0;
|
|
24
|
+
for (const height of entries.values()) {
|
|
25
|
+
total += height;
|
|
26
|
+
}
|
|
27
|
+
onChange(total);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
register: () => {
|
|
32
|
+
const id = Symbol();
|
|
33
|
+
entries.set(id, 0);
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
setHeight: (height: number) => {
|
|
37
|
+
if (entries.get(id) !== height) {
|
|
38
|
+
entries.set(id, height);
|
|
39
|
+
recalculate();
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
unregister: () => {
|
|
43
|
+
entries.delete(id);
|
|
44
|
+
recalculate();
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
6
51
|
export type ThreadViewportState = {
|
|
7
52
|
readonly isAtBottom: boolean;
|
|
8
|
-
readonly scrollToBottom: (
|
|
9
|
-
|
|
53
|
+
readonly scrollToBottom: (config?: {
|
|
54
|
+
behavior?: ScrollBehavior | undefined;
|
|
55
|
+
}) => void;
|
|
56
|
+
readonly onScrollToBottom: (
|
|
57
|
+
callback: ({ behavior }: { behavior: ScrollBehavior }) => void,
|
|
58
|
+
) => Unsubscribe;
|
|
59
|
+
|
|
60
|
+
/** Controls scroll anchoring: "top" anchors user messages at top, "bottom" is classic behavior */
|
|
61
|
+
readonly turnAnchor: "top" | "bottom";
|
|
62
|
+
|
|
63
|
+
/** Raw height values from registered elements */
|
|
64
|
+
readonly height: {
|
|
65
|
+
/** Total viewport height */
|
|
66
|
+
readonly viewport: number;
|
|
67
|
+
/** Total content inset height (footer, anchor message, etc.) */
|
|
68
|
+
readonly inset: number;
|
|
69
|
+
/** Height of the anchor user message (full height) */
|
|
70
|
+
readonly userMessage: number;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/** Register a viewport and get a handle to update its height */
|
|
74
|
+
readonly registerViewport: () => SizeHandle;
|
|
75
|
+
|
|
76
|
+
/** Register a content inset (footer, anchor message, etc.) and get a handle to update its height */
|
|
77
|
+
readonly registerContentInset: () => SizeHandle;
|
|
78
|
+
|
|
79
|
+
/** Register the anchor user message height */
|
|
80
|
+
readonly registerUserMessageHeight: () => SizeHandle;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export type ThreadViewportStoreOptions = {
|
|
84
|
+
turnAnchor?: "top" | "bottom" | undefined;
|
|
10
85
|
};
|
|
11
86
|
|
|
12
|
-
export const makeThreadViewportStore = (
|
|
13
|
-
|
|
87
|
+
export const makeThreadViewportStore = (
|
|
88
|
+
options: ThreadViewportStoreOptions = {},
|
|
89
|
+
) => {
|
|
90
|
+
const scrollToBottomListeners = new Set<
|
|
91
|
+
(config: { behavior: ScrollBehavior }) => void
|
|
92
|
+
>();
|
|
14
93
|
|
|
15
|
-
|
|
94
|
+
const viewportRegistry = createSizeRegistry((total) => {
|
|
95
|
+
store.setState({
|
|
96
|
+
height: {
|
|
97
|
+
...store.getState().height,
|
|
98
|
+
viewport: total,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
const insetRegistry = createSizeRegistry((total) => {
|
|
103
|
+
store.setState({
|
|
104
|
+
height: {
|
|
105
|
+
...store.getState().height,
|
|
106
|
+
inset: total,
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
const userMessageRegistry = createSizeRegistry((total) => {
|
|
111
|
+
store.setState({
|
|
112
|
+
height: {
|
|
113
|
+
...store.getState().height,
|
|
114
|
+
userMessage: total,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const store = create<ThreadViewportState>(() => ({
|
|
16
120
|
isAtBottom: true,
|
|
17
|
-
scrollToBottom: () => {
|
|
121
|
+
scrollToBottom: ({ behavior = "auto" } = {}) => {
|
|
18
122
|
for (const listener of scrollToBottomListeners) {
|
|
19
|
-
listener();
|
|
123
|
+
listener({ behavior });
|
|
20
124
|
}
|
|
21
125
|
},
|
|
22
126
|
onScrollToBottom: (callback) => {
|
|
@@ -25,5 +129,19 @@ export const makeThreadViewportStore = () => {
|
|
|
25
129
|
scrollToBottomListeners.delete(callback);
|
|
26
130
|
};
|
|
27
131
|
},
|
|
132
|
+
|
|
133
|
+
turnAnchor: options.turnAnchor ?? "bottom",
|
|
134
|
+
|
|
135
|
+
height: {
|
|
136
|
+
viewport: 0,
|
|
137
|
+
inset: 0,
|
|
138
|
+
userMessage: 0,
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
registerViewport: viewportRegistry.register,
|
|
142
|
+
registerContentInset: insetRegistry.register,
|
|
143
|
+
registerUserMessageHeight: userMessageRegistry.register,
|
|
28
144
|
}));
|
|
145
|
+
|
|
146
|
+
return store;
|
|
29
147
|
};
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
import { AssistantRuntime } from "./runtime/AssistantRuntime";
|
|
9
9
|
import { AssistantRuntimeCore } from "./runtime-cores/core/AssistantRuntimeCore";
|
|
10
10
|
import { RuntimeAdapter } from "./RuntimeAdapter";
|
|
11
|
+
import { ThreadPrimitiveViewportProvider } from "../context/providers/ThreadViewportProvider";
|
|
11
12
|
|
|
12
13
|
export namespace AssistantProvider {
|
|
13
14
|
export type Props = PropsWithChildren<{
|
|
@@ -36,7 +37,11 @@ export const AssistantRuntimeProviderImpl: FC<AssistantProvider.Props> = ({
|
|
|
36
37
|
<AssistantProvider api={api}>
|
|
37
38
|
{RenderComponent && <RenderComponent />}
|
|
38
39
|
|
|
39
|
-
{
|
|
40
|
+
{/* TODO temporarily allow accessing viewport state from outside the viewport */}
|
|
41
|
+
{/* TODO figure out if this behavior should be deprecated, since it is quite hacky */}
|
|
42
|
+
<ThreadPrimitiveViewportProvider>
|
|
43
|
+
{children}
|
|
44
|
+
</ThreadPrimitiveViewportProvider>
|
|
40
45
|
</AssistantProvider>
|
|
41
46
|
);
|
|
42
47
|
};
|
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
resource,
|
|
3
3
|
tapMemo,
|
|
4
4
|
tapEffect,
|
|
5
|
-
RefObject,
|
|
6
5
|
tapInlineResource,
|
|
6
|
+
type tapRef,
|
|
7
7
|
} from "@assistant-ui/tap";
|
|
8
8
|
import {
|
|
9
9
|
ComposerRuntime,
|
|
@@ -43,8 +43,8 @@ export const ComposerClient = resource(
|
|
|
43
43
|
messageIdRef,
|
|
44
44
|
runtime,
|
|
45
45
|
}: {
|
|
46
|
-
threadIdRef: RefObject<string>;
|
|
47
|
-
messageIdRef?: RefObject<string>;
|
|
46
|
+
threadIdRef: tapRef.RefObject<string>;
|
|
47
|
+
messageIdRef?: tapRef.RefObject<string>;
|
|
48
48
|
runtime: ComposerRuntime;
|
|
49
49
|
}) => {
|
|
50
50
|
const runtimeState = tapSubscribable(runtime);
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
tapInlineResource,
|
|
6
6
|
tapMemo,
|
|
7
7
|
tapEffect,
|
|
8
|
-
|
|
8
|
+
type tapRef,
|
|
9
9
|
} from "@assistant-ui/tap";
|
|
10
10
|
import { ComposerClient } from "./ComposerRuntimeClient";
|
|
11
11
|
import { MessageClient } from "./MessageRuntimeClient";
|
|
@@ -24,7 +24,7 @@ const MessageClientById = resource(
|
|
|
24
24
|
}: {
|
|
25
25
|
runtime: ThreadRuntime;
|
|
26
26
|
id: string;
|
|
27
|
-
threadIdRef: RefObject<string>;
|
|
27
|
+
threadIdRef: tapRef.RefObject<string>;
|
|
28
28
|
}) => {
|
|
29
29
|
const messageRuntime = tapMemo(
|
|
30
30
|
() => runtime.getMessageById(id),
|
|
@@ -80,6 +80,8 @@ const getMessagePartState = (
|
|
|
80
80
|
|
|
81
81
|
export type MessageState = ThreadMessage & {
|
|
82
82
|
readonly parentId: string | null;
|
|
83
|
+
/** The position of this message in the thread (0 for first message) */
|
|
84
|
+
readonly index: number;
|
|
83
85
|
readonly isLast: boolean;
|
|
84
86
|
|
|
85
87
|
readonly branchNumber: number;
|
|
@@ -45,6 +45,8 @@ export type ThreadListRuntimeCoreBinding = SubscribableWithState<
|
|
|
45
45
|
export type MessageStateBinding = SubscribableWithState<
|
|
46
46
|
ThreadMessage & {
|
|
47
47
|
readonly parentId: string | null;
|
|
48
|
+
/** The position of this message in the thread (0 for first message) */
|
|
49
|
+
readonly index: number;
|
|
48
50
|
readonly isLast: boolean;
|
|
49
51
|
readonly branchNumber: number;
|
|
50
52
|
readonly branchCount: number;
|