@assistant-ui/core 0.2.23 → 0.3.0
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/react/adapters/LocalStorageThreadListAdapter.js +2 -2
- package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +40 -55
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/interactables-legacy/useAssistantInteractable.js +1 -1
- package/dist/react/interactables-legacy/useAssistantInteractable.js.map +1 -1
- package/dist/react/interactables-legacy/useInteractableState.js +3 -3
- package/dist/react/interactables-legacy/useInteractableState.js.map +1 -1
- package/dist/react/model-context/useAssistantContext.js +1 -1
- package/dist/react/model-context/useAssistantContext.js.map +1 -1
- package/dist/react/model-context/useAssistantDataUI.js +1 -1
- package/dist/react/model-context/useAssistantDataUI.js.map +1 -1
- package/dist/react/model-context/useAssistantInstructions.js +1 -1
- package/dist/react/model-context/useAssistantInstructions.js.map +1 -1
- package/dist/react/model-context/useAssistantTool.js +29 -25
- package/dist/react/model-context/useAssistantTool.js.map +1 -1
- package/dist/react/model-context/useAssistantToolUI.js +1 -1
- package/dist/react/model-context/useAssistantToolUI.js.map +1 -1
- package/dist/react/model-context/useAuiToolOverrides.js +1 -1
- package/dist/react/model-context/useAuiToolOverrides.js.map +1 -1
- package/dist/react/model-context/useInteractable.js +1 -1
- package/dist/react/model-context/useInteractable.js.map +1 -1
- package/dist/react/model-context/useInteractableState.js +2 -2
- package/dist/react/model-context/useInteractableState.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.js +3 -3
- package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.js +1 -1
- package/dist/react/primitive-hooks/useActionBarEdit.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarFeedback.js +2 -2
- package/dist/react/primitive-hooks/useActionBarFeedback.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.js +1 -1
- package/dist/react/primitive-hooks/useActionBarReload.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarSpeak.js +1 -1
- package/dist/react/primitive-hooks/useActionBarSpeak.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarStopSpeaking.js +1 -1
- package/dist/react/primitive-hooks/useActionBarStopSpeaking.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.js +1 -1
- package/dist/react/primitive-hooks/useBranchPickerNext.js.map +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js +1 -1
- package/dist/react/primitive-hooks/useBranchPickerPrevious.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerAddAttachment.js +1 -1
- package/dist/react/primitive-hooks/useComposerAddAttachment.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.js +1 -1
- package/dist/react/primitive-hooks/useComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerDictate.js +1 -1
- package/dist/react/primitive-hooks/useComposerDictate.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.js +1 -1
- package/dist/react/primitive-hooks/useComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useEditComposerCancel.js +1 -1
- package/dist/react/primitive-hooks/useEditComposerCancel.js.map +1 -1
- package/dist/react/primitive-hooks/useEditComposerSend.js +1 -1
- package/dist/react/primitive-hooks/useEditComposerSend.js.map +1 -1
- package/dist/react/primitive-hooks/useMessageBranching.js +2 -2
- package/dist/react/primitive-hooks/useMessageBranching.js.map +1 -1
- package/dist/react/primitive-hooks/useMessageReload.js +1 -1
- package/dist/react/primitive-hooks/useMessageReload.js.map +1 -1
- package/dist/react/primitive-hooks/useSuggestionTrigger.js +7 -7
- package/dist/react/primitive-hooks/useSuggestionTrigger.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemArchive.js +1 -1
- package/dist/react/primitive-hooks/useThreadListItemArchive.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemDelete.js +1 -1
- package/dist/react/primitive-hooks/useThreadListItemDelete.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemTrigger.js +1 -1
- package/dist/react/primitive-hooks/useThreadListItemTrigger.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListItemUnarchive.js +1 -1
- package/dist/react/primitive-hooks/useThreadListItemUnarchive.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.js +1 -1
- package/dist/react/primitive-hooks/useThreadListLoadMore.js.map +1 -1
- package/dist/react/primitive-hooks/useThreadListNew.js +1 -1
- package/dist/react/primitive-hooks/useThreadListNew.js.map +1 -1
- package/dist/react/primitive-hooks/useVoice.js +5 -13
- package/dist/react/primitive-hooks/useVoice.js.map +1 -1
- package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js +1 -1
- package/dist/react/primitives/chainOfThought/ChainOfThoughtParts.js.map +1 -1
- package/dist/react/primitives/composer/ComposerAttachments.js +1 -1
- package/dist/react/primitives/composer/ComposerAttachments.js.map +1 -1
- package/dist/react/primitives/composer/ComposerQueue.d.ts.map +1 -1
- package/dist/react/primitives/composer/ComposerQueue.js +1 -1
- package/dist/react/primitives/composer/ComposerQueue.js.map +1 -1
- package/dist/react/primitives/message/MessageAttachments.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageAttachments.js +1 -1
- package/dist/react/primitives/message/MessageAttachments.js.map +1 -1
- package/dist/react/primitives/message/MessageParts.js +84 -122
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/primitives/thread/ThreadMessages.js +1 -1
- package/dist/react/primitives/thread/ThreadMessages.js.map +1 -1
- package/dist/react/primitives/thread/ThreadSuggestions.js +1 -1
- package/dist/react/primitives/thread/ThreadSuggestions.js.map +1 -1
- package/dist/react/primitives/threadList/ThreadListItems.js +1 -1
- package/dist/react/primitives/threadList/ThreadListItems.js.map +1 -1
- package/dist/react/providers/AttachmentByIndexProvider.js +2 -2
- package/dist/react/providers/AttachmentByIndexProvider.js.map +1 -1
- package/dist/react/providers/ChainOfThoughtByIndicesProvider.js +1 -1
- package/dist/react/providers/ChainOfThoughtByIndicesProvider.js.map +1 -1
- package/dist/react/providers/ChainOfThoughtPartByIndexProvider.d.ts.map +1 -1
- package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js +30 -18
- package/dist/react/providers/ChainOfThoughtPartByIndexProvider.js.map +1 -1
- package/dist/react/providers/MessageByIdProvider.js +2 -2
- package/dist/react/providers/MessageByIdProvider.js.map +1 -1
- package/dist/react/providers/MessageByIndexProvider.js +2 -2
- package/dist/react/providers/MessageByIndexProvider.js.map +1 -1
- package/dist/react/providers/PartByIndexProvider.d.ts.map +1 -1
- package/dist/react/providers/PartByIndexProvider.js +30 -18
- package/dist/react/providers/PartByIndexProvider.js.map +1 -1
- package/dist/react/providers/QueueItemByIndexProvider.js +1 -1
- package/dist/react/providers/QueueItemByIndexProvider.js.map +1 -1
- package/dist/react/providers/ReadonlyThreadProvider.js +1 -1
- package/dist/react/providers/ReadonlyThreadProvider.js.map +1 -1
- package/dist/react/providers/SuggestionByIndexProvider.js +1 -1
- package/dist/react/providers/SuggestionByIndexProvider.js.map +1 -1
- package/dist/react/providers/ThreadListItemByIndexProvider.js +1 -1
- package/dist/react/providers/ThreadListItemByIndexProvider.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js +3 -3
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.js.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js +32 -20
- package/dist/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.js.map +1 -1
- package/dist/react/runtimes/createRuntimeExtras.js +1 -1
- package/dist/react/runtimes/createRuntimeExtras.js.map +1 -1
- package/dist/react/types/scopes/tools.d.ts +0 -6
- package/dist/react/types/scopes/tools.d.ts.map +1 -1
- package/dist/react/utils/groupParts.d.ts +1 -3
- package/dist/react/utils/groupParts.d.ts.map +1 -1
- package/dist/react/utils/groupParts.js +1 -3
- package/dist/react/utils/groupParts.js.map +1 -1
- package/dist/store/clients/runtime-adapter.js +3 -3
- package/dist/store/clients/runtime-adapter.js.map +1 -1
- package/package.json +5 -5
- package/src/react/adapters/LocalStorageThreadListAdapter.tsx +2 -2
- package/src/react/client/Tools.ts +0 -7
- package/src/react/interactables-legacy/useAssistantInteractable.ts +1 -1
- package/src/react/interactables-legacy/useInteractableState.ts +3 -3
- package/src/react/model-context/useAssistantContext.ts +1 -1
- package/src/react/model-context/useAssistantDataUI.ts +1 -1
- package/src/react/model-context/useAssistantInstructions.ts +1 -1
- package/src/react/model-context/useAssistantTool.ts +2 -2
- package/src/react/model-context/useAssistantToolUI.ts +1 -1
- package/src/react/model-context/useAuiToolOverrides.ts +1 -1
- package/src/react/model-context/useInteractable.ts +1 -1
- package/src/react/model-context/useInteractableState.ts +2 -2
- package/src/react/primitive-hooks/useActionBarCopy.test.ts +2 -2
- package/src/react/primitive-hooks/useActionBarCopy.ts +3 -3
- package/src/react/primitive-hooks/useActionBarEdit.ts +1 -1
- package/src/react/primitive-hooks/useActionBarFeedback.ts +2 -2
- package/src/react/primitive-hooks/useActionBarReload.ts +1 -1
- package/src/react/primitive-hooks/useActionBarSpeak.ts +1 -1
- package/src/react/primitive-hooks/useActionBarStopSpeaking.ts +1 -1
- package/src/react/primitive-hooks/useBranchPickerNext.ts +1 -1
- package/src/react/primitive-hooks/useBranchPickerPrevious.ts +1 -1
- package/src/react/primitive-hooks/useComposerAddAttachment.ts +1 -1
- package/src/react/primitive-hooks/useComposerCancel.ts +1 -1
- package/src/react/primitive-hooks/useComposerDictate.ts +1 -1
- package/src/react/primitive-hooks/useComposerSend.ts +1 -1
- package/src/react/primitive-hooks/useEditComposerCancel.ts +1 -1
- package/src/react/primitive-hooks/useEditComposerSend.ts +1 -1
- package/src/react/primitive-hooks/useMessageBranching.ts +2 -2
- package/src/react/primitive-hooks/useMessageReload.ts +1 -1
- package/src/react/primitive-hooks/useSuggestionTrigger.ts +9 -9
- package/src/react/primitive-hooks/useThreadListItemArchive.ts +1 -1
- package/src/react/primitive-hooks/useThreadListItemDelete.ts +1 -1
- package/src/react/primitive-hooks/useThreadListItemTrigger.ts +1 -1
- package/src/react/primitive-hooks/useThreadListItemUnarchive.ts +1 -1
- package/src/react/primitive-hooks/useThreadListLoadMore.ts +1 -1
- package/src/react/primitive-hooks/useThreadListNew.ts +1 -1
- package/src/react/primitive-hooks/useVoice.ts +5 -5
- package/src/react/primitives/chainOfThought/ChainOfThoughtParts.tsx +1 -1
- package/src/react/primitives/composer/ComposerAttachments.tsx +1 -1
- package/src/react/primitives/composer/ComposerQueue.tsx +1 -3
- package/src/react/primitives/message/MessageAttachments.tsx +1 -3
- package/src/react/primitives/message/MessageParts.tsx +9 -9
- package/src/react/primitives/thread/ThreadMessages.tsx +1 -1
- package/src/react/primitives/thread/ThreadSuggestions.tsx +1 -1
- package/src/react/primitives/threadList/ThreadListItems.tsx +1 -1
- package/src/react/providers/AttachmentByIndexProvider.tsx +2 -2
- package/src/react/providers/ChainOfThoughtByIndicesProvider.tsx +1 -1
- package/src/react/providers/ChainOfThoughtPartByIndexProvider.tsx +2 -19
- package/src/react/providers/MessageByIdProvider.tsx +2 -2
- package/src/react/providers/MessageByIndexProvider.tsx +2 -2
- package/src/react/providers/PartByIndexProvider.tsx +2 -16
- package/src/react/providers/QueueItemByIndexProvider.tsx +1 -1
- package/src/react/providers/ReadonlyThreadProvider.tsx +1 -1
- package/src/react/providers/SuggestionByIndexProvider.tsx +1 -1
- package/src/react/providers/ThreadListItemByIndexProvider.tsx +1 -1
- package/src/react/runtimes/RemoteThreadListHookInstanceManager.tsx +3 -3
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.test.tsx +32 -7
- package/src/react/runtimes/cloud/AssistantCloudThreadHistoryAdapter.ts +26 -16
- package/src/react/runtimes/createRuntimeExtras.test.ts +1 -1
- package/src/react/runtimes/createRuntimeExtras.ts +1 -1
- package/src/react/types/scopes/tools.ts +0 -6
- package/src/react/utils/groupParts.ts +1 -7
- package/src/store/clients/runtime-adapter.ts +3 -3
- package/src/tests/groupParts.test.ts +3 -48
|
@@ -10,7 +10,7 @@ export const MessageAttachmentByIndexProvider: FC<
|
|
|
10
10
|
attachment: Derived({
|
|
11
11
|
source: "message",
|
|
12
12
|
query: { type: "index", index },
|
|
13
|
-
get: (aui) => aui.message
|
|
13
|
+
get: (aui) => aui.message.attachment({ index }),
|
|
14
14
|
}),
|
|
15
15
|
});
|
|
16
16
|
|
|
@@ -26,7 +26,7 @@ export const ComposerAttachmentByIndexProvider: FC<
|
|
|
26
26
|
attachment: Derived({
|
|
27
27
|
source: "composer",
|
|
28
28
|
query: { type: "index", index },
|
|
29
|
-
get: (aui) => aui.composer
|
|
29
|
+
get: (aui) => aui.composer.attachment({ index }),
|
|
30
30
|
}),
|
|
31
31
|
});
|
|
32
32
|
|
|
@@ -25,7 +25,7 @@ export const ChainOfThoughtByIndicesProvider: FC<
|
|
|
25
25
|
`ChainOfThought part index ${index} is out of bounds (0..${parts.length - 1})`,
|
|
26
26
|
);
|
|
27
27
|
}
|
|
28
|
-
return parentAui.message
|
|
28
|
+
return parentAui.message.part({ index: startIndex + index });
|
|
29
29
|
},
|
|
30
30
|
}),
|
|
31
31
|
});
|
|
@@ -1,33 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FC, PropsWithChildren } from "react";
|
|
2
2
|
import { useAui, AuiProvider, Derived } from "@assistant-ui/store";
|
|
3
|
-
import type { PartMethods } from "../../store/scopes/part";
|
|
4
3
|
|
|
5
4
|
export const ChainOfThoughtPartByIndexProvider: FC<
|
|
6
5
|
PropsWithChildren<{
|
|
7
6
|
index: number;
|
|
8
7
|
}>
|
|
9
8
|
> = ({ index, children }) => {
|
|
10
|
-
const lastPartRef = useMemo(
|
|
11
|
-
() => ({ index, current: null as PartMethods | null }),
|
|
12
|
-
[index],
|
|
13
|
-
);
|
|
14
9
|
const aui = useAui({
|
|
15
10
|
part: Derived({
|
|
16
11
|
source: "chainOfThought",
|
|
17
12
|
query: { type: "index", index },
|
|
18
|
-
get: (aui) => {
|
|
19
|
-
const chainOfThought = aui.chainOfThought();
|
|
20
|
-
if (
|
|
21
|
-
index >= chainOfThought.getState().parts.length &&
|
|
22
|
-
lastPartRef.current
|
|
23
|
-
) {
|
|
24
|
-
return lastPartRef.current;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const part = chainOfThought.part({ index });
|
|
28
|
-
lastPartRef.current = part;
|
|
29
|
-
return part;
|
|
30
|
-
},
|
|
13
|
+
get: (aui) => aui.chainOfThought.part({ index }),
|
|
31
14
|
}),
|
|
32
15
|
});
|
|
33
16
|
|
|
@@ -10,12 +10,12 @@ export const MessageByIdProvider: FC<
|
|
|
10
10
|
message: Derived({
|
|
11
11
|
source: "thread",
|
|
12
12
|
query: { type: "id", id },
|
|
13
|
-
get: (aui) => aui.thread
|
|
13
|
+
get: (aui) => aui.thread.message({ id }),
|
|
14
14
|
}),
|
|
15
15
|
composer: Derived({
|
|
16
16
|
source: "message",
|
|
17
17
|
query: {},
|
|
18
|
-
get: (aui) => aui.thread
|
|
18
|
+
get: (aui) => aui.thread.message({ id }).composer(),
|
|
19
19
|
}),
|
|
20
20
|
});
|
|
21
21
|
|
|
@@ -10,12 +10,12 @@ export const MessageByIndexProvider: FC<
|
|
|
10
10
|
message: Derived({
|
|
11
11
|
source: "thread",
|
|
12
12
|
query: { type: "index", index },
|
|
13
|
-
get: (aui) => aui.thread
|
|
13
|
+
get: (aui) => aui.thread.message({ index }),
|
|
14
14
|
}),
|
|
15
15
|
composer: Derived({
|
|
16
16
|
source: "message",
|
|
17
17
|
query: {},
|
|
18
|
-
get: (aui) => aui.thread
|
|
18
|
+
get: (aui) => aui.thread.message({ index }).composer(),
|
|
19
19
|
}),
|
|
20
20
|
});
|
|
21
21
|
|
|
@@ -1,30 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FC, PropsWithChildren } from "react";
|
|
2
2
|
import { useAui, AuiProvider, Derived } from "@assistant-ui/store";
|
|
3
|
-
import type { PartMethods } from "../../store/scopes/part";
|
|
4
3
|
|
|
5
4
|
export const PartByIndexProvider: FC<
|
|
6
5
|
PropsWithChildren<{
|
|
7
6
|
index: number;
|
|
8
7
|
}>
|
|
9
8
|
> = ({ index, children }) => {
|
|
10
|
-
const lastPartRef = useMemo(
|
|
11
|
-
() => ({ index, current: null as PartMethods | null }),
|
|
12
|
-
[index],
|
|
13
|
-
);
|
|
14
9
|
const aui = useAui({
|
|
15
10
|
part: Derived({
|
|
16
11
|
source: "message",
|
|
17
12
|
query: { type: "index", index },
|
|
18
|
-
get: (aui) => {
|
|
19
|
-
const message = aui.message();
|
|
20
|
-
if (index >= message.getState().parts.length && lastPartRef.current) {
|
|
21
|
-
return lastPartRef.current;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const part = message.part({ index });
|
|
25
|
-
lastPartRef.current = part;
|
|
26
|
-
return part;
|
|
27
|
-
},
|
|
13
|
+
get: (aui) => aui.message.part({ index }),
|
|
28
14
|
}),
|
|
29
15
|
});
|
|
30
16
|
|
|
@@ -13,7 +13,7 @@ export const QueueItemByIndexProvider: FC<QueueItemByIndexProviderProps> = ({
|
|
|
13
13
|
queueItem: Derived({
|
|
14
14
|
source: "composer",
|
|
15
15
|
query: { index },
|
|
16
|
-
get: (aui) => aui.composer
|
|
16
|
+
get: (aui) => aui.composer.queueItem({ index }),
|
|
17
17
|
}),
|
|
18
18
|
});
|
|
19
19
|
|
|
@@ -13,7 +13,7 @@ export const SuggestionByIndexProvider: FC<SuggestionByIndexProviderProps> = ({
|
|
|
13
13
|
suggestion: Derived({
|
|
14
14
|
source: "suggestions",
|
|
15
15
|
query: { index },
|
|
16
|
-
get: (aui) => aui.suggestions
|
|
16
|
+
get: (aui) => aui.suggestions.suggestion({ index }),
|
|
17
17
|
}),
|
|
18
18
|
});
|
|
19
19
|
|
|
@@ -11,7 +11,7 @@ export const ThreadListItemByIndexProvider: FC<
|
|
|
11
11
|
threadListItem: Derived({
|
|
12
12
|
source: "threads",
|
|
13
13
|
query: { type: "index", index, archived },
|
|
14
|
-
get: (aui) => aui.threads
|
|
14
|
+
get: (aui) => aui.threads.item({ index, archived }),
|
|
15
15
|
}),
|
|
16
16
|
});
|
|
17
17
|
|
|
@@ -147,15 +147,15 @@ export class RemoteThreadListHookInstanceManager extends BaseSubscribable {
|
|
|
147
147
|
return runtime.threads.main.unstable_on("initialize", () => {
|
|
148
148
|
if (hasInitializedRef.current) return;
|
|
149
149
|
|
|
150
|
-
const state = aui.threadListItem
|
|
150
|
+
const state = aui.threadListItem.getState();
|
|
151
151
|
if (state.status !== "new") return;
|
|
152
152
|
hasInitializedRef.current = true;
|
|
153
153
|
|
|
154
|
-
initPromiseRef.current = aui.threadListItem
|
|
154
|
+
initPromiseRef.current = aui.threadListItem.initialize();
|
|
155
155
|
|
|
156
156
|
const dispose = runtime.thread.unstable_on("runEnd", () => {
|
|
157
157
|
dispose();
|
|
158
|
-
aui.threadListItem
|
|
158
|
+
aui.threadListItem.generateTitle();
|
|
159
159
|
});
|
|
160
160
|
});
|
|
161
161
|
}, [runtime, aui]);
|
|
@@ -6,20 +6,22 @@ import { describe, expect, it, vi } from "vitest";
|
|
|
6
6
|
import { useAssistantCloudThreadHistoryAdapter } from "./AssistantCloudThreadHistoryAdapter";
|
|
7
7
|
|
|
8
8
|
const mocks = vi.hoisted(() => {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const makeClient = (remoteId: string) =>
|
|
10
|
+
({
|
|
11
|
+
threadListItem: {
|
|
12
|
+
getState: () => ({ remoteId }),
|
|
13
|
+
},
|
|
14
|
+
}) as unknown as import("@assistant-ui/store").AssistantClient;
|
|
12
15
|
|
|
13
16
|
return {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
},
|
|
17
|
+
makeClient,
|
|
18
|
+
aui: makeClient("thread-1"),
|
|
17
19
|
};
|
|
18
20
|
});
|
|
19
21
|
|
|
20
22
|
vi.mock("@assistant-ui/store", async (importOriginal) => ({
|
|
21
23
|
...(await importOriginal<typeof import("@assistant-ui/store")>()),
|
|
22
|
-
useAui: () => mocks.
|
|
24
|
+
useAui: () => mocks.aui,
|
|
23
25
|
}));
|
|
24
26
|
|
|
25
27
|
const makeCloud = () =>
|
|
@@ -33,6 +35,7 @@ const makeCloud = () =>
|
|
|
33
35
|
|
|
34
36
|
describe("useAssistantCloudThreadHistoryAdapter", () => {
|
|
35
37
|
it("refreshes formatted persistence when the Cloud client changes", async () => {
|
|
38
|
+
mocks.aui = mocks.makeClient("thread-1");
|
|
36
39
|
const firstCloud = makeCloud();
|
|
37
40
|
const secondCloud = makeCloud();
|
|
38
41
|
const cloudRef = { current: firstCloud };
|
|
@@ -66,4 +69,26 @@ describe("useAssistantCloudThreadHistoryAdapter", () => {
|
|
|
66
69
|
format: "test",
|
|
67
70
|
});
|
|
68
71
|
});
|
|
72
|
+
|
|
73
|
+
it("resolves the aui client at call time instead of capturing it", async () => {
|
|
74
|
+
mocks.aui = mocks.makeClient("thread-1");
|
|
75
|
+
const cloud = makeCloud();
|
|
76
|
+
const cloudRef = { current: cloud };
|
|
77
|
+
const { result, rerender } = renderHook(() =>
|
|
78
|
+
useAssistantCloudThreadHistoryAdapter(cloudRef),
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
await result.current.load();
|
|
82
|
+
expect(cloud.threads.messages.list).toHaveBeenCalledWith("thread-1", {
|
|
83
|
+
format: "aui/v0",
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
mocks.aui = mocks.makeClient("thread-2");
|
|
87
|
+
rerender();
|
|
88
|
+
|
|
89
|
+
await result.current.load();
|
|
90
|
+
expect(cloud.threads.messages.list).toHaveBeenCalledWith("thread-2", {
|
|
91
|
+
format: "aui/v0",
|
|
92
|
+
});
|
|
93
|
+
});
|
|
69
94
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type RefObject, useState } from "react";
|
|
1
|
+
import { type RefObject, useEffect, useRef, useState } from "react";
|
|
2
2
|
import type {
|
|
3
3
|
GenericThreadHistoryAdapter,
|
|
4
4
|
ThreadHistoryAdapter,
|
|
@@ -13,25 +13,31 @@ import {
|
|
|
13
13
|
createFormattedPersistence,
|
|
14
14
|
} from "assistant-cloud";
|
|
15
15
|
import { auiV0Decode, auiV0Encode } from "./auiV0";
|
|
16
|
-
import { type AssistantClient, useAui } from "@assistant-ui/store";
|
|
17
|
-
import type { ThreadListItemMethods } from "../../../store/scopes/thread-list-item";
|
|
16
|
+
import { type AssistantClient, getClientId, useAui } from "@assistant-ui/store";
|
|
18
17
|
|
|
19
18
|
const globalPersistence = new WeakMap<
|
|
20
|
-
|
|
19
|
+
getClientId.ClientId,
|
|
21
20
|
CloudMessagePersistence
|
|
22
21
|
>();
|
|
23
22
|
|
|
24
23
|
class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
|
|
25
24
|
private cloudRef: RefObject<AssistantCloud>;
|
|
26
|
-
private
|
|
25
|
+
private auiRef: RefObject<AssistantClient>;
|
|
27
26
|
|
|
28
|
-
constructor(
|
|
27
|
+
constructor(
|
|
28
|
+
cloudRef: RefObject<AssistantCloud>,
|
|
29
|
+
auiRef: RefObject<AssistantClient>,
|
|
30
|
+
) {
|
|
29
31
|
this.cloudRef = cloudRef;
|
|
30
|
-
this.
|
|
32
|
+
this.auiRef = auiRef;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private get aui(): AssistantClient {
|
|
36
|
+
return this.auiRef.current;
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
private get _persistence(): CloudMessagePersistence {
|
|
34
|
-
const key = this.aui.threadListItem
|
|
40
|
+
const key = getClientId(this.aui.threadListItem);
|
|
35
41
|
if (!globalPersistence.has(key)) {
|
|
36
42
|
globalPersistence.set(
|
|
37
43
|
key,
|
|
@@ -52,11 +58,11 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
|
|
|
52
58
|
return {
|
|
53
59
|
// Note: callers must also call reportTelemetry() for run tracking
|
|
54
60
|
async append(item: MessageFormatItem<TMessage>) {
|
|
55
|
-
const { remoteId } = await adapter.aui.threadListItem
|
|
61
|
+
const { remoteId } = await adapter.aui.threadListItem.initialize();
|
|
56
62
|
await formatted.append(remoteId, item);
|
|
57
63
|
},
|
|
58
64
|
async update(item: MessageFormatItem<TMessage>, localMessageId: string) {
|
|
59
|
-
const remoteId = adapter.aui.threadListItem
|
|
65
|
+
const remoteId = adapter.aui.threadListItem.getState().remoteId;
|
|
60
66
|
if (!remoteId) return;
|
|
61
67
|
await formatted.update?.(remoteId, item, localMessageId);
|
|
62
68
|
},
|
|
@@ -82,7 +88,7 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
|
|
|
82
88
|
);
|
|
83
89
|
},
|
|
84
90
|
async load(): Promise<MessageFormatRepository<TMessage>> {
|
|
85
|
-
const remoteId = adapter.aui.threadListItem
|
|
91
|
+
const remoteId = adapter.aui.threadListItem.getState().remoteId;
|
|
86
92
|
if (!remoteId) return { messages: [] };
|
|
87
93
|
return formatted.load(remoteId);
|
|
88
94
|
},
|
|
@@ -90,7 +96,7 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
|
|
|
90
96
|
}
|
|
91
97
|
|
|
92
98
|
async append({ parentId, message }: ExportedMessageRepositoryItem) {
|
|
93
|
-
const { remoteId } = await this.aui.threadListItem
|
|
99
|
+
const { remoteId } = await this.aui.threadListItem.initialize();
|
|
94
100
|
const encoded = auiV0Encode(message);
|
|
95
101
|
await this._persistence.append(
|
|
96
102
|
remoteId,
|
|
@@ -110,7 +116,7 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
|
|
|
110
116
|
return this.append(item);
|
|
111
117
|
}
|
|
112
118
|
const { message } = item;
|
|
113
|
-
const remoteId = this.aui.threadListItem
|
|
119
|
+
const remoteId = this.aui.threadListItem.getState().remoteId;
|
|
114
120
|
if (!remoteId) return;
|
|
115
121
|
const encoded = auiV0Encode(message);
|
|
116
122
|
await this._persistence.update(remoteId, message.id, "aui/v0", encoded);
|
|
@@ -127,7 +133,7 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
|
|
|
127
133
|
}
|
|
128
134
|
|
|
129
135
|
async load() {
|
|
130
|
-
const remoteId = this.aui.threadListItem
|
|
136
|
+
const remoteId = this.aui.threadListItem.getState().remoteId;
|
|
131
137
|
if (!remoteId) return { messages: [] };
|
|
132
138
|
const messages = await this._persistence.load(remoteId, "aui/v0");
|
|
133
139
|
return {
|
|
@@ -150,7 +156,7 @@ class AssistantCloudThreadHistoryAdapter implements ThreadHistoryAdapter {
|
|
|
150
156
|
) {
|
|
151
157
|
if (!this.cloudRef.current.telemetry.enabled) return;
|
|
152
158
|
|
|
153
|
-
const remoteId = this.aui.threadListItem
|
|
159
|
+
const remoteId = this.aui.threadListItem.getState().remoteId;
|
|
154
160
|
if (!remoteId) return;
|
|
155
161
|
|
|
156
162
|
const extracted = extractRunTelemetry(format, runMessages);
|
|
@@ -810,8 +816,12 @@ export function useAssistantCloudThreadHistoryAdapter(
|
|
|
810
816
|
cloudRef: RefObject<AssistantCloud>,
|
|
811
817
|
): ThreadHistoryAdapter {
|
|
812
818
|
const aui = useAui();
|
|
819
|
+
const auiRef = useRef(aui);
|
|
820
|
+
useEffect(() => {
|
|
821
|
+
auiRef.current = aui;
|
|
822
|
+
});
|
|
813
823
|
const [adapter] = useState(
|
|
814
|
-
() => new AssistantCloudThreadHistoryAdapter(cloudRef,
|
|
824
|
+
() => new AssistantCloudThreadHistoryAdapter(cloudRef, auiRef),
|
|
815
825
|
);
|
|
816
826
|
return adapter;
|
|
817
827
|
}
|
|
@@ -6,7 +6,7 @@ type Extras = { value: number; greet: () => string };
|
|
|
6
6
|
|
|
7
7
|
const clientWith = (extras: unknown) =>
|
|
8
8
|
({
|
|
9
|
-
thread:
|
|
9
|
+
thread: { getState: () => ({ extras }) },
|
|
10
10
|
}) as unknown as AssistantClient;
|
|
11
11
|
|
|
12
12
|
describe("createRuntimeExtras", () => {
|
|
@@ -46,7 +46,7 @@ export const createRuntimeExtras = <T extends object>(
|
|
|
46
46
|
is(extras) ? extras : undefined;
|
|
47
47
|
|
|
48
48
|
const get = (client: AssistantClient): T =>
|
|
49
|
-
assert(client.thread
|
|
49
|
+
assert(client.thread.getState().extras);
|
|
50
50
|
|
|
51
51
|
function use<S>(
|
|
52
52
|
select?: (extras: T) => S,
|
|
@@ -20,12 +20,6 @@ export type ToolsState = {
|
|
|
20
20
|
/** Registered tool UIs (renderer + presentation options) keyed by tool name. */
|
|
21
21
|
toolUIs: Record<string, readonly ToolRegistration[]>;
|
|
22
22
|
mcpApp?: McpAppResourceOutput | undefined;
|
|
23
|
-
/**
|
|
24
|
-
* @deprecated Use {@link toolUIs} instead, whose entries carry the renderer
|
|
25
|
-
* alongside its presentation options. This component-only map is kept for
|
|
26
|
-
* back-compat and will be removed in v0.15.
|
|
27
|
-
*/
|
|
28
|
-
tools: Record<string, ToolCallMessagePartComponent[]>;
|
|
29
23
|
};
|
|
30
24
|
|
|
31
25
|
export type ToolsMethods = {
|
|
@@ -47,10 +47,8 @@ export const GROUPBY_MEMO_KEY: unique symbol = Symbol.for(
|
|
|
47
47
|
* `display: "standalone"`). Resolving the registry-driven cases reads the
|
|
48
48
|
* {@link GroupByContext} passed to the `groupBy` function. Takes precedence
|
|
49
49
|
* over the `"tool-call"` entry.
|
|
50
|
-
* - `"mcp-app"` — **deprecated**, kept for back-compat. Matches only MCP-app
|
|
51
|
-
* tool calls. Prefer `"standalone-tool-call"`, which is a superset.
|
|
52
50
|
*/
|
|
53
|
-
type GroupPartType = PartState["type"] | "standalone-tool-call"
|
|
51
|
+
type GroupPartType = PartState["type"] | "standalone-tool-call";
|
|
54
52
|
|
|
55
53
|
/**
|
|
56
54
|
* Build a `groupBy` from a `part.type → group-key path` lookup.
|
|
@@ -93,10 +91,6 @@ export const groupPartByType = <TKey extends `group-${string}`>(
|
|
|
93
91
|
if (isStandalone && lookup["standalone-tool-call"] !== undefined) {
|
|
94
92
|
return lookup["standalone-tool-call"]!;
|
|
95
93
|
}
|
|
96
|
-
// TODO(v0.15): drop the deprecated "mcp-app" key (superseded by "standalone-tool-call").
|
|
97
|
-
if (isMcpApp && lookup["mcp-app"] !== undefined) {
|
|
98
|
-
return lookup["mcp-app"]!;
|
|
99
|
-
}
|
|
100
94
|
}
|
|
101
95
|
return lookup[part.type] ?? [];
|
|
102
96
|
}) as ((part: PartState, context?: GroupByContext) => readonly TKey[]) & {
|
|
@@ -13,17 +13,17 @@ export const baseRuntimeAdapterTransformScopes = (
|
|
|
13
13
|
scopes.thread ??= Derived({
|
|
14
14
|
source: "threads",
|
|
15
15
|
query: { type: "main" },
|
|
16
|
-
get: (aui) => aui.threads
|
|
16
|
+
get: (aui) => aui.threads.thread("main"),
|
|
17
17
|
});
|
|
18
18
|
scopes.threadListItem ??= Derived({
|
|
19
19
|
source: "threads",
|
|
20
20
|
query: { type: "main" },
|
|
21
|
-
get: (aui) => aui.threads
|
|
21
|
+
get: (aui) => aui.threads.item("main"),
|
|
22
22
|
});
|
|
23
23
|
scopes.composer ??= Derived({
|
|
24
24
|
source: "thread",
|
|
25
25
|
query: {},
|
|
26
|
-
get: (aui) => aui.threads
|
|
26
|
+
get: (aui) => aui.threads.thread("main").composer(),
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
if (!scopes.modelContext && parent.modelContext.source === null) {
|
|
@@ -119,25 +119,7 @@ describe("groupPartByType", () => {
|
|
|
119
119
|
expect(fn(part({ type: "text" }))).toEqual([]);
|
|
120
120
|
});
|
|
121
121
|
|
|
122
|
-
it("
|
|
123
|
-
const fn = groupPartByType({
|
|
124
|
-
"tool-call": ["group-tool"],
|
|
125
|
-
"mcp-app": [],
|
|
126
|
-
});
|
|
127
|
-
const mcpApp = part({
|
|
128
|
-
type: "tool-call",
|
|
129
|
-
toolName: "render",
|
|
130
|
-
mcp: { app: { resourceUri: "ui://my-app" } },
|
|
131
|
-
} as Partial<PartState>);
|
|
132
|
-
const regular = part({
|
|
133
|
-
type: "tool-call",
|
|
134
|
-
toolName: "search",
|
|
135
|
-
} as Partial<PartState>);
|
|
136
|
-
expect(fn(mcpApp)).toEqual([]);
|
|
137
|
-
expect(fn(regular)).toEqual(["group-tool"]);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it("falls back to 'tool-call' for MCP-app parts when 'mcp-app' is absent", () => {
|
|
122
|
+
it("falls back to 'tool-call' for MCP-app parts when 'standalone-tool-call' is absent", () => {
|
|
141
123
|
const fn = groupPartByType({ "tool-call": ["group-tool"] });
|
|
142
124
|
const mcpApp = part({
|
|
143
125
|
type: "tool-call",
|
|
@@ -147,10 +129,10 @@ describe("groupPartByType", () => {
|
|
|
147
129
|
expect(fn(mcpApp)).toEqual(["group-tool"]);
|
|
148
130
|
});
|
|
149
131
|
|
|
150
|
-
it("does not
|
|
132
|
+
it("does not treat non-`ui://` tool calls as standalone", () => {
|
|
151
133
|
const fn = groupPartByType({
|
|
152
134
|
"tool-call": ["group-tool"],
|
|
153
|
-
"
|
|
135
|
+
"standalone-tool-call": ["group-standalone"],
|
|
154
136
|
});
|
|
155
137
|
const notMcp = part({
|
|
156
138
|
type: "tool-call",
|
|
@@ -235,33 +217,6 @@ describe("groupPartByType", () => {
|
|
|
235
217
|
expect(fn(mcpApp)).toEqual([]);
|
|
236
218
|
});
|
|
237
219
|
|
|
238
|
-
it("routes MCP-app parts through the deprecated 'mcp-app' entry", () => {
|
|
239
|
-
const fn = groupPartByType({
|
|
240
|
-
"tool-call": ["group-tool"],
|
|
241
|
-
"mcp-app": ["group-mcp"],
|
|
242
|
-
});
|
|
243
|
-
const mcpApp = part({
|
|
244
|
-
type: "tool-call",
|
|
245
|
-
toolName: "render",
|
|
246
|
-
mcp: { app: { resourceUri: "ui://my-app" } },
|
|
247
|
-
} as Partial<PartState>);
|
|
248
|
-
expect(fn(mcpApp)).toEqual(["group-mcp"]);
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
it("prefers 'standalone-tool-call' over the deprecated 'mcp-app' entry", () => {
|
|
252
|
-
const fn = groupPartByType({
|
|
253
|
-
"tool-call": ["group-tool"],
|
|
254
|
-
"standalone-tool-call": ["group-standalone"],
|
|
255
|
-
"mcp-app": ["group-mcp"],
|
|
256
|
-
});
|
|
257
|
-
const mcpApp = part({
|
|
258
|
-
type: "tool-call",
|
|
259
|
-
toolName: "render",
|
|
260
|
-
mcp: { app: { resourceUri: "ui://x" } },
|
|
261
|
-
} as Partial<PartState>);
|
|
262
|
-
expect(fn(mcpApp)).toEqual(["group-standalone"]);
|
|
263
|
-
});
|
|
264
|
-
|
|
265
220
|
it("tags the function with a GROUPBY_MEMO_KEY fingerprint", () => {
|
|
266
221
|
const fn = groupPartByType({ reasoning: ["group-r"] });
|
|
267
222
|
const memoKey = (fn as unknown as { [GROUPBY_MEMO_KEY]: string })[
|