@assistant-ui/react 0.11.41 → 0.11.44
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/useToolInvocations.js +5 -5
- package/dist/legacy-runtime/runtime-cores/assistant-transport/useToolInvocations.js.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.d.ts +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.d.ts.map +1 -1
- package/dist/legacy-runtime/runtime-cores/assistant-transport/utils.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/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/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 +3 -4
- 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/useToolInvocations.ts +5 -5
- package/src/legacy-runtime/runtime-cores/assistant-transport/utils.ts +1 -1
- 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/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,"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.44",
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"type": "module",
|
|
34
34
|
"exports": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"sideEffects": false,
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"assistant-cloud": "^0.1.8",
|
|
52
|
-
"@assistant-ui/tap": "^0.
|
|
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",
|
|
@@ -60,7 +60,6 @@
|
|
|
60
60
|
"@radix-ui/react-use-escape-keydown": "^1.1.1",
|
|
61
61
|
"@standard-schema/spec": "^1.0.0",
|
|
62
62
|
"assistant-stream": "^0.2.41",
|
|
63
|
-
"json-schema": "^0.4.0",
|
|
64
63
|
"nanoid": "5.1.6",
|
|
65
64
|
"react-textarea-autosize": "^8.5.9",
|
|
66
65
|
"zod": "^4.1.12",
|
|
@@ -98,7 +97,7 @@
|
|
|
98
97
|
"homepage": "https://www.assistant-ui.com/",
|
|
99
98
|
"repository": {
|
|
100
99
|
"type": "git",
|
|
101
|
-
"url": "https://github.com/assistant-ui/assistant-ui
|
|
100
|
+
"url": "https://github.com/assistant-ui/assistant-ui"
|
|
102
101
|
},
|
|
103
102
|
"bugs": {
|
|
104
103
|
"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;
|
|
@@ -447,6 +447,7 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
447
447
|
return {
|
|
448
448
|
message,
|
|
449
449
|
parentId: messages[idx - 1]?.id ?? null,
|
|
450
|
+
index: idx,
|
|
450
451
|
};
|
|
451
452
|
},
|
|
452
453
|
);
|
|
@@ -468,19 +469,20 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
468
469
|
private _getMessageRuntime(
|
|
469
470
|
path: MessageRuntimePath,
|
|
470
471
|
callback: () =>
|
|
471
|
-
| { parentId: string | null; message: ThreadMessage }
|
|
472
|
+
| { parentId: string | null; message: ThreadMessage; index: number }
|
|
472
473
|
| undefined,
|
|
473
474
|
) {
|
|
474
475
|
return new MessageRuntimeImpl(
|
|
475
476
|
new ShallowMemoizeSubject({
|
|
476
477
|
path,
|
|
477
478
|
getState: () => {
|
|
478
|
-
const { message, parentId } = callback() ?? {};
|
|
479
|
+
const { message, parentId, index } = callback() ?? {};
|
|
479
480
|
|
|
480
481
|
const { messages, speech: speechState } =
|
|
481
482
|
this._threadBinding.getState();
|
|
482
483
|
|
|
483
|
-
if (!message || parentId === undefined
|
|
484
|
+
if (!message || parentId === undefined || index === undefined)
|
|
485
|
+
return SKIP_UPDATE;
|
|
484
486
|
|
|
485
487
|
const thread = this._threadBinding.getState();
|
|
486
488
|
|
|
@@ -491,6 +493,7 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
491
493
|
...message,
|
|
492
494
|
...{ [symbolInnerMessage]: (message as any)[symbolInnerMessage] },
|
|
493
495
|
|
|
496
|
+
index,
|
|
494
497
|
isLast: messages.at(-1)?.id === message.id,
|
|
495
498
|
parentId,
|
|
496
499
|
|
|
@@ -131,7 +131,7 @@ export function useToolInvocations({
|
|
|
131
131
|
});
|
|
132
132
|
|
|
133
133
|
const ignoredToolIds = useRef<Set<string>>(new Set());
|
|
134
|
-
const
|
|
134
|
+
const isInitialState = useRef(true);
|
|
135
135
|
|
|
136
136
|
useEffect(() => {
|
|
137
137
|
const processMessages = (
|
|
@@ -140,7 +140,7 @@ export function useToolInvocations({
|
|
|
140
140
|
messages.forEach((message) => {
|
|
141
141
|
message.content.forEach((content) => {
|
|
142
142
|
if (content.type === "tool-call") {
|
|
143
|
-
if (
|
|
143
|
+
if (isInitialState.current) {
|
|
144
144
|
ignoredToolIds.current.add(content.toolCallId);
|
|
145
145
|
} else {
|
|
146
146
|
if (ignoredToolIds.current.has(content.toolCallId)) {
|
|
@@ -225,8 +225,8 @@ export function useToolInvocations({
|
|
|
225
225
|
|
|
226
226
|
processMessages(state.messages);
|
|
227
227
|
|
|
228
|
-
if (
|
|
229
|
-
|
|
228
|
+
if (isInitialState.current) {
|
|
229
|
+
isInitialState.current = false;
|
|
230
230
|
}
|
|
231
231
|
}, [state, controller, onResult]);
|
|
232
232
|
|
|
@@ -244,7 +244,7 @@ export function useToolInvocations({
|
|
|
244
244
|
return {
|
|
245
245
|
reset: () => {
|
|
246
246
|
abort();
|
|
247
|
-
|
|
247
|
+
isInitialState.current = true;
|
|
248
248
|
},
|
|
249
249
|
abort,
|
|
250
250
|
resume: (toolCallId: string, payload: unknown) => {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { forwardRef, useCallback, useState } from "react";
|
|
2
4
|
|
|
3
5
|
import { Slot } from "@radix-ui/react-slot";
|
|
4
6
|
import React from "react";
|
|
5
7
|
import { useAssistantApi } from "../../context";
|
|
6
8
|
|
|
7
|
-
export namespace
|
|
9
|
+
export namespace ComposerPrimitiveAttachmentDropzone {
|
|
8
10
|
export type Element = HTMLDivElement;
|
|
9
11
|
export type Props = React.HTMLAttributes<HTMLDivElement> & {
|
|
10
12
|
asChild?: boolean | undefined;
|
|
@@ -12,19 +14,40 @@ export namespace ComposerAttachmentDropzonePrimitive {
|
|
|
12
14
|
};
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
export const
|
|
17
|
+
export const ComposerPrimitiveAttachmentDropzone = forwardRef<
|
|
16
18
|
HTMLDivElement,
|
|
17
|
-
|
|
19
|
+
ComposerPrimitiveAttachmentDropzone.Props
|
|
18
20
|
>(({ disabled, asChild = false, children, ...rest }, ref) => {
|
|
19
21
|
const [isDragging, setIsDragging] = useState(false);
|
|
20
22
|
const api = useAssistantApi();
|
|
21
23
|
|
|
22
|
-
const
|
|
24
|
+
const handleDragEnterCapture = useCallback(
|
|
25
|
+
(e: React.DragEvent) => {
|
|
26
|
+
if (disabled) return;
|
|
27
|
+
e.preventDefault();
|
|
28
|
+
setIsDragging(true);
|
|
29
|
+
},
|
|
30
|
+
[disabled],
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const handleDragOverCapture = useCallback(
|
|
23
34
|
(e: React.DragEvent) => {
|
|
24
35
|
if (disabled) return;
|
|
25
36
|
e.preventDefault();
|
|
26
|
-
|
|
27
|
-
|
|
37
|
+
if (!isDragging) setIsDragging(true);
|
|
38
|
+
},
|
|
39
|
+
[disabled, isDragging],
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const handleDragLeaveCapture = useCallback(
|
|
43
|
+
(e: React.DragEvent) => {
|
|
44
|
+
if (disabled) return;
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
const next = e.relatedTarget as Node | null;
|
|
47
|
+
if (next && e.currentTarget.contains(next)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
setIsDragging(false);
|
|
28
51
|
},
|
|
29
52
|
[disabled],
|
|
30
53
|
);
|
|
@@ -33,7 +56,6 @@ export const ComposerAttachmentDropzone = forwardRef<
|
|
|
33
56
|
async (e: React.DragEvent) => {
|
|
34
57
|
if (disabled) return;
|
|
35
58
|
e.preventDefault();
|
|
36
|
-
e.stopPropagation();
|
|
37
59
|
setIsDragging(false);
|
|
38
60
|
for (const file of e.dataTransfer.files) {
|
|
39
61
|
try {
|
|
@@ -47,10 +69,10 @@ export const ComposerAttachmentDropzone = forwardRef<
|
|
|
47
69
|
);
|
|
48
70
|
|
|
49
71
|
const dragProps = {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
72
|
+
onDragEnterCapture: handleDragEnterCapture,
|
|
73
|
+
onDragOverCapture: handleDragOverCapture,
|
|
74
|
+
onDragLeaveCapture: handleDragLeaveCapture,
|
|
75
|
+
onDropCapture: handleDrop,
|
|
54
76
|
};
|
|
55
77
|
|
|
56
78
|
const Comp = asChild ? Slot : "div";
|
|
@@ -67,4 +89,5 @@ export const ComposerAttachmentDropzone = forwardRef<
|
|
|
67
89
|
);
|
|
68
90
|
});
|
|
69
91
|
|
|
70
|
-
|
|
92
|
+
ComposerPrimitiveAttachmentDropzone.displayName =
|
|
93
|
+
"ComposerPrimitive.AttachmentDropzone";
|
|
@@ -5,4 +5,5 @@ export { ComposerPrimitiveCancel as Cancel } from "./ComposerCancel";
|
|
|
5
5
|
export { ComposerPrimitiveAddAttachment as AddAttachment } from "./ComposerAddAttachment";
|
|
6
6
|
export { ComposerPrimitiveAttachments as Attachments } from "./ComposerAttachments";
|
|
7
7
|
export { ComposerPrimitiveAttachmentByIndex as AttachmentByIndex } from "./ComposerAttachments";
|
|
8
|
+
export { ComposerPrimitiveAttachmentDropzone as AttachmentDropzone } from "./ComposerAttachmentDropzone";
|
|
8
9
|
export { ComposerPrimitiveIf as If } from "./ComposerIf";
|