@assistant-ui/core 0.2.0 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/model-context/tool.d.ts +25 -0
- package/dist/model-context/tool.d.ts.map +1 -1
- package/dist/model-context/tool.js +25 -0
- package/dist/model-context/tool.js.map +1 -1
- package/dist/react/AssistantRuntimeProvider.d.ts +33 -0
- package/dist/react/AssistantRuntimeProvider.d.ts.map +1 -1
- package/dist/react/AssistantRuntimeProvider.js +22 -0
- package/dist/react/AssistantRuntimeProvider.js.map +1 -1
- package/dist/react/client/DataRenderers.d.ts +7 -0
- package/dist/react/client/DataRenderers.d.ts.map +1 -1
- package/dist/react/client/DataRenderers.js +7 -0
- package/dist/react/client/DataRenderers.js.map +1 -1
- package/dist/react/client/Tools.d.ts +18 -1
- package/dist/react/client/Tools.d.ts.map +1 -1
- package/dist/react/client/Tools.js +24 -19
- package/dist/react/client/Tools.js.map +1 -1
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/model-context/makeAssistantDataUI.d.ts +13 -0
- package/dist/react/model-context/makeAssistantDataUI.d.ts.map +1 -1
- package/dist/react/model-context/makeAssistantDataUI.js +6 -0
- package/dist/react/model-context/makeAssistantDataUI.js.map +1 -1
- package/dist/react/model-context/makeAssistantTool.d.ts +15 -0
- package/dist/react/model-context/makeAssistantTool.d.ts.map +1 -1
- package/dist/react/model-context/makeAssistantTool.js +8 -0
- package/dist/react/model-context/makeAssistantTool.js.map +1 -1
- package/dist/react/model-context/makeAssistantToolUI.d.ts +15 -0
- package/dist/react/model-context/makeAssistantToolUI.d.ts.map +1 -1
- package/dist/react/model-context/makeAssistantToolUI.js +8 -0
- package/dist/react/model-context/makeAssistantToolUI.js.map +1 -1
- package/dist/react/model-context/toolbox.d.ts +29 -0
- package/dist/react/model-context/toolbox.d.ts.map +1 -1
- package/dist/react/model-context/useAssistantDataUI.d.ts +9 -0
- package/dist/react/model-context/useAssistantDataUI.d.ts.map +1 -1
- package/dist/react/model-context/useAssistantDataUI.js +6 -0
- package/dist/react/model-context/useAssistantDataUI.js.map +1 -1
- package/dist/react/model-context/useAssistantTool.d.ts +34 -0
- package/dist/react/model-context/useAssistantTool.d.ts.map +1 -1
- package/dist/react/model-context/useAssistantTool.js +30 -0
- package/dist/react/model-context/useAssistantTool.js.map +1 -1
- package/dist/react/model-context/useAssistantToolUI.d.ts +12 -0
- package/dist/react/model-context/useAssistantToolUI.d.ts.map +1 -1
- package/dist/react/model-context/useAssistantToolUI.js +9 -0
- package/dist/react/model-context/useAssistantToolUI.js.map +1 -1
- package/dist/react/model-context/useToolArgsStatus.d.ts +29 -0
- package/dist/react/model-context/useToolArgsStatus.d.ts.map +1 -1
- package/dist/react/model-context/useToolArgsStatus.js +24 -0
- package/dist/react/model-context/useToolArgsStatus.js.map +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useActionBarCopy.js +4 -3
- package/dist/react/primitive-hooks/useActionBarCopy.js.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.d.ts.map +1 -1
- package/dist/react/primitive-hooks/useComposerSend.js +2 -3
- package/dist/react/primitive-hooks/useComposerSend.js.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.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageParts.js +14 -10
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/primitives/messagePart/MessagePartInProgress.d.ts +6 -0
- package/dist/react/primitives/messagePart/MessagePartInProgress.d.ts.map +1 -0
- package/dist/react/primitives/messagePart/MessagePartInProgress.js +7 -0
- package/dist/react/primitives/messagePart/MessagePartInProgress.js.map +1 -0
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +2 -0
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +2 -0
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts +10 -1
- package/dist/react/runtimes/cloud/auiV0.d.ts.map +1 -1
- package/dist/react/runtimes/cloud/auiV0.js +21 -3
- package/dist/react/runtimes/cloud/auiV0.js.map +1 -1
- package/dist/react/runtimes/useToolInvocations.d.ts +11 -1
- package/dist/react/runtimes/useToolInvocations.d.ts.map +1 -1
- package/dist/react/runtimes/useToolInvocations.js +325 -256
- package/dist/react/runtimes/useToolInvocations.js.map +1 -1
- package/dist/react/types/MessagePartComponentTypes.d.ts +11 -0
- package/dist/react/types/MessagePartComponentTypes.d.ts.map +1 -1
- package/dist/react/types/scopes/tools.d.ts +4 -0
- package/dist/react/types/scopes/tools.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.d.ts +1 -0
- package/dist/runtime/api/composer-runtime.d.ts.map +1 -1
- package/dist/runtime/api/composer-runtime.js +2 -0
- package/dist/runtime/api/composer-runtime.js.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +2 -0
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -0
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +1 -0
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts +1 -0
- package/dist/runtime/base/default-edit-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-edit-composer-runtime-core.js +3 -0
- package/dist/runtime/base/default-edit-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts +1 -0
- package/dist/runtime/base/default-thread-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js +12 -1
- package/dist/runtime/base/default-thread-composer-runtime-core.js.map +1 -1
- package/dist/runtime/interfaces/composer-runtime-core.d.ts +1 -0
- package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +6 -0
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-adapter.d.ts +15 -0
- package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +14 -12
- package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +2 -0
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js +13 -0
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +1 -0
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +1 -0
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +2 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +2 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.d.ts.map +1 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.js +2 -0
- package/dist/runtimes/remote-thread-list/empty-thread-core.js.map +1 -1
- package/dist/store/clients/model-context-client.d.ts.map +1 -1
- package/dist/store/clients/model-context-client.js +24 -4
- package/dist/store/clients/model-context-client.js.map +1 -1
- package/dist/store/clients/no-op-composer-client.d.ts.map +1 -1
- package/dist/store/clients/no-op-composer-client.js +1 -0
- package/dist/store/clients/no-op-composer-client.js.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/composer-runtime-client.js +1 -0
- package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
- package/dist/store/scopes/composer.d.ts +9 -0
- package/dist/store/scopes/composer.d.ts.map +1 -1
- package/dist/store/scopes/model-context.d.ts +4 -1
- package/dist/store/scopes/model-context.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/message.d.ts +50 -1
- package/dist/types/message.d.ts.map +1 -1
- package/dist/types/message.js +2 -1
- package/dist/types/message.js.map +1 -1
- package/package.json +7 -7
- package/src/index.ts +6 -0
- package/src/model-context/tool.ts +25 -0
- package/src/react/AssistantRuntimeProvider.tsx +33 -0
- package/src/react/client/DataRenderers.ts +7 -0
- package/src/react/client/Tools.ts +56 -22
- package/src/react/index.ts +2 -1
- package/src/react/model-context/makeAssistantDataUI.ts +13 -0
- package/src/react/model-context/makeAssistantTool.ts +15 -0
- package/src/react/model-context/makeAssistantToolUI.ts +15 -0
- package/src/react/model-context/toolbox.ts +32 -1
- package/src/react/model-context/useAssistantDataUI.ts +9 -0
- package/src/react/model-context/useAssistantTool.ts +34 -0
- package/src/react/model-context/useAssistantToolUI.ts +12 -0
- package/src/react/model-context/useToolArgsStatus.ts +29 -0
- package/src/react/primitive-hooks/useActionBarCopy.ts +9 -5
- package/src/react/primitive-hooks/useComposerSend.ts +2 -3
- package/src/react/primitives/message/MessageAttachments.test.tsx +50 -0
- package/src/react/primitives/message/MessageAttachments.tsx +1 -1
- package/src/react/primitives/message/MessageParts.tsx +20 -9
- package/src/react/primitives/messagePart/MessagePartInProgress.ts +15 -0
- package/src/react/runtimes/cloud/auiV0.ts +37 -4
- package/src/react/runtimes/useToolInvocations.ts +422 -333
- package/src/react/types/MessagePartComponentTypes.ts +11 -0
- package/src/react/types/scopes/tools.ts +5 -0
- package/src/runtime/api/composer-runtime.ts +3 -0
- package/src/runtime/base/base-composer-runtime-core.ts +2 -1
- package/src/runtime/base/base-thread-runtime-core.ts +1 -0
- package/src/runtime/base/default-edit-composer-runtime-core.ts +4 -0
- package/src/runtime/base/default-thread-composer-runtime-core.ts +12 -1
- package/src/runtime/interfaces/composer-runtime-core.ts +1 -0
- package/src/runtime/interfaces/thread-runtime-core.ts +6 -0
- package/src/runtimes/external-store/external-store-adapter.ts +15 -0
- package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +15 -9
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +13 -0
- package/src/runtimes/local/local-thread-runtime-core.ts +1 -0
- package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +2 -0
- package/src/runtimes/remote-thread-list/empty-thread-core.ts +2 -0
- package/src/store/clients/model-context-client.test.ts +108 -0
- package/src/store/clients/model-context-client.ts +36 -6
- package/src/store/clients/no-op-composer-client.ts +1 -0
- package/src/store/runtime-clients/composer-runtime-client.ts +1 -0
- package/src/store/scopes/composer.ts +9 -0
- package/src/store/scopes/model-context.ts +4 -1
- package/src/tests/auiV0Encode.test.ts +55 -0
- package/src/tests/composer-can-send.test.ts +112 -0
- package/src/tests/external-store-thread-list-runtime-core.test.ts +34 -0
- package/src/tests/external-store-thread-runtime-core.test.ts +113 -0
- package/src/types/index.ts +2 -0
- package/src/types/message.ts +66 -7
|
@@ -2,11 +2,20 @@ import { useEffect } from "react";
|
|
|
2
2
|
import { useAui } from "@assistant-ui/store";
|
|
3
3
|
import type { DataMessagePartComponent } from "../types/MessagePartComponentTypes";
|
|
4
4
|
|
|
5
|
+
/** Props used to register a renderer for `data` message parts. */
|
|
5
6
|
export type AssistantDataUIProps<T = any> = {
|
|
7
|
+
/** Data part name this renderer handles. */
|
|
6
8
|
name: string;
|
|
9
|
+
/** Component rendered for matching data message parts. */
|
|
7
10
|
render: DataMessagePartComponent<T>;
|
|
8
11
|
};
|
|
9
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Registers a renderer for named `data` message parts while the component is
|
|
15
|
+
* mounted.
|
|
16
|
+
*
|
|
17
|
+
* @param dataUI - Data renderer registration, or `null` to skip registration.
|
|
18
|
+
*/
|
|
10
19
|
export const useAssistantDataUI = (dataUI: AssistantDataUIProps | null) => {
|
|
11
20
|
const aui = useAui();
|
|
12
21
|
useEffect(() => {
|
|
@@ -3,13 +3,47 @@ import { useAui } from "@assistant-ui/store";
|
|
|
3
3
|
import type { ToolCallMessagePartComponent } from "../types/MessagePartComponentTypes";
|
|
4
4
|
import type { AssistantToolProps as CoreAssistantToolProps } from "../..";
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Props used to register a tool from React.
|
|
8
|
+
*/
|
|
6
9
|
export type AssistantToolProps<
|
|
7
10
|
TArgs extends Record<string, unknown>,
|
|
8
11
|
TResult,
|
|
9
12
|
> = CoreAssistantToolProps<TArgs, TResult> & {
|
|
13
|
+
/** Component used to render calls to this tool in assistant messages. */
|
|
10
14
|
render?: ToolCallMessagePartComponent<TArgs, TResult> | undefined;
|
|
11
15
|
};
|
|
12
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Registers a tool with the assistant model context while the component is
|
|
19
|
+
* mounted.
|
|
20
|
+
*
|
|
21
|
+
* If `render` is provided, it is also installed as the renderer for matching
|
|
22
|
+
* tool-call message parts. The registration is removed automatically when the
|
|
23
|
+
* component unmounts or the tool definition changes.
|
|
24
|
+
*
|
|
25
|
+
* Pass a referentially stable tool object, such as one declared at module
|
|
26
|
+
* scope or memoized with `useMemo`, to avoid re-registering on every render.
|
|
27
|
+
*
|
|
28
|
+
* @param tool - Tool definition and name to register.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* const weatherTool = {
|
|
33
|
+
* toolName: "get_weather",
|
|
34
|
+
* type: "frontend",
|
|
35
|
+
* description: "Get the weather for a city.",
|
|
36
|
+
* parameters: weatherSchema,
|
|
37
|
+
* execute: async ({ city }: { city: string }) => fetchWeather(city),
|
|
38
|
+
* render: WeatherToolUI,
|
|
39
|
+
* } satisfies AssistantToolProps<{ city: string }, Weather>;
|
|
40
|
+
*
|
|
41
|
+
* function WeatherToolRegistration() {
|
|
42
|
+
* useAssistantTool(weatherTool);
|
|
43
|
+
* return null;
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
13
47
|
export const useAssistantTool = <
|
|
14
48
|
TArgs extends Record<string, unknown>,
|
|
15
49
|
TResult,
|
|
@@ -2,11 +2,23 @@ import { useEffect } from "react";
|
|
|
2
2
|
import { useAui } from "@assistant-ui/store";
|
|
3
3
|
import type { ToolCallMessagePartComponent } from "../types/MessagePartComponentTypes";
|
|
4
4
|
|
|
5
|
+
/** Props used to register a renderer for tool-call message parts. */
|
|
5
6
|
export type AssistantToolUIProps<TArgs, TResult> = {
|
|
7
|
+
/** Name of the tool whose calls should use this renderer. */
|
|
6
8
|
toolName: string;
|
|
9
|
+
/** Component rendered for matching tool-call message parts. */
|
|
7
10
|
render: ToolCallMessagePartComponent<TArgs, TResult>;
|
|
8
11
|
};
|
|
9
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Registers a tool-call renderer while the component is mounted.
|
|
15
|
+
*
|
|
16
|
+
* This only affects rendering. Pair it with {@link useAssistantTool},
|
|
17
|
+
* {@link Tools}, or a backend tool registry to expose the actual tool
|
|
18
|
+
* definition to the model.
|
|
19
|
+
*
|
|
20
|
+
* @param tool - Tool renderer registration, or `null` to skip registration.
|
|
21
|
+
*/
|
|
10
22
|
export const useAssistantToolUI = (
|
|
11
23
|
tool: AssistantToolUIProps<any, any> | null,
|
|
12
24
|
) => {
|
|
@@ -7,13 +7,42 @@ import {
|
|
|
7
7
|
|
|
8
8
|
type PropFieldStatus = "streaming" | "complete";
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Streaming completion status for the arguments of the current tool call.
|
|
12
|
+
*/
|
|
10
13
|
export type ToolArgsStatus<
|
|
11
14
|
TArgs extends Record<string, unknown> = Record<string, unknown>,
|
|
12
15
|
> = {
|
|
16
|
+
/** Overall lifecycle state of the tool-call part. */
|
|
13
17
|
status: "running" | "complete" | "incomplete" | "requires-action";
|
|
18
|
+
/** Per-argument status keyed by argument name. */
|
|
14
19
|
propStatus: Partial<Record<keyof TArgs, PropFieldStatus>>;
|
|
15
20
|
};
|
|
16
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Reads whether each argument field for the current tool-call message part is
|
|
24
|
+
* still streaming or complete.
|
|
25
|
+
*
|
|
26
|
+
* Use inside a tool-call renderer to avoid showing incomplete argument values
|
|
27
|
+
* as final.
|
|
28
|
+
*
|
|
29
|
+
* @throws If called outside a tool-call message part.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* function WeatherToolUI({
|
|
34
|
+
* args,
|
|
35
|
+
* }: ToolCallMessagePartProps<{ city: string }>) {
|
|
36
|
+
* const { propStatus } = useToolArgsStatus<{ city: string }>();
|
|
37
|
+
*
|
|
38
|
+
* return (
|
|
39
|
+
* <span>
|
|
40
|
+
* {propStatus.city === "streaming" ? "Reading city..." : args.city}
|
|
41
|
+
* </span>
|
|
42
|
+
* );
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
17
46
|
export const useToolArgsStatus = <
|
|
18
47
|
TArgs extends Record<string, unknown> = Record<string, unknown>,
|
|
19
48
|
>(): ToolArgsStatus<TArgs> => {
|
|
@@ -27,11 +27,15 @@ export const useActionBarCopy = ({
|
|
|
27
27
|
if (!valueToCopy) return;
|
|
28
28
|
|
|
29
29
|
const write = copyToClipboard ?? (() => {});
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
// The rejection handler swallows clipboard write failures (permission denied,
|
|
31
|
+
// API unavailable) so they don't surface as unhandled promise rejections.
|
|
32
|
+
Promise.resolve(write(valueToCopy)).then(
|
|
33
|
+
() => {
|
|
34
|
+
aui.message().setIsCopied(true);
|
|
35
|
+
setTimeout(() => aui.message().setIsCopied(false), copiedDuration);
|
|
36
|
+
},
|
|
37
|
+
() => {},
|
|
38
|
+
);
|
|
35
39
|
}, [aui, isEditing, composerValue, copiedDuration, copyToClipboard]);
|
|
36
40
|
|
|
37
41
|
return { copy, disabled, isCopied };
|
|
@@ -6,9 +6,8 @@ export const useComposerSend = () => {
|
|
|
6
6
|
const aui = useAui();
|
|
7
7
|
const disabled = useAuiState(
|
|
8
8
|
(s) =>
|
|
9
|
-
|
|
10
|
-
!s.
|
|
11
|
-
s.composer.isEmpty,
|
|
9
|
+
!s.composer.canSend ||
|
|
10
|
+
(s.thread.isRunning && !s.thread.capabilities.queue),
|
|
12
11
|
);
|
|
13
12
|
|
|
14
13
|
const send = useCallback(
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import type { ReactElement } from "react";
|
|
3
|
+
import { MessagePrimitiveAttachments } from "./MessageAttachments";
|
|
4
|
+
|
|
5
|
+
const mockUseAuiState = vi.fn();
|
|
6
|
+
type UseAuiStateSelector = Parameters<
|
|
7
|
+
typeof import("@assistant-ui/store")["useAuiState"]
|
|
8
|
+
>[0];
|
|
9
|
+
type AttachmentsElement = ReactElement<{ children: () => null }>;
|
|
10
|
+
|
|
11
|
+
vi.mock("react", async (importOriginal) => {
|
|
12
|
+
const actual = await importOriginal<typeof import("react")>();
|
|
13
|
+
return {
|
|
14
|
+
...actual,
|
|
15
|
+
useMemo: (factory: () => unknown) => factory(),
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
vi.mock("@assistant-ui/store", async (importOriginal) => {
|
|
20
|
+
const actual = await importOriginal<typeof import("@assistant-ui/store")>();
|
|
21
|
+
return {
|
|
22
|
+
...actual,
|
|
23
|
+
useAuiState: (selector: UseAuiStateSelector) => mockUseAuiState(selector),
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const renderAttachmentsInner = () => {
|
|
28
|
+
const element = MessagePrimitiveAttachments({
|
|
29
|
+
children: () => null,
|
|
30
|
+
}) as AttachmentsElement;
|
|
31
|
+
|
|
32
|
+
const Inner = element.type as (props: typeof element.props) => unknown;
|
|
33
|
+
return Inner(element.props);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
describe("MessagePrimitiveAttachments", () => {
|
|
37
|
+
it("treats missing user message attachments as empty", () => {
|
|
38
|
+
mockUseAuiState.mockImplementation((selector: UseAuiStateSelector) =>
|
|
39
|
+
selector({
|
|
40
|
+
message: {
|
|
41
|
+
role: "user",
|
|
42
|
+
attachments: undefined,
|
|
43
|
+
},
|
|
44
|
+
} as never),
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(() => renderAttachmentsInner()).not.toThrow();
|
|
48
|
+
expect(renderAttachmentsInner()).toEqual([]);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -93,7 +93,7 @@ const MessagePrimitiveAttachmentsInner: FC<{
|
|
|
93
93
|
}> = ({ children }) => {
|
|
94
94
|
const attachmentsCount = useAuiState((s) => {
|
|
95
95
|
if (s.message.role !== "user") return 0;
|
|
96
|
-
return s.message.attachments.length;
|
|
96
|
+
return (s.message.attachments ?? []).length;
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
return useMemo(
|
|
@@ -31,8 +31,9 @@ import type {
|
|
|
31
31
|
ReasoningGroupComponent,
|
|
32
32
|
QuoteMessagePartComponent,
|
|
33
33
|
} from "../../types/MessagePartComponentTypes";
|
|
34
|
-
import type
|
|
34
|
+
import { isMcpAppUri, type MessagePartStatus } from "../../../types/message";
|
|
35
35
|
import type { DataRenderersState } from "../../types/scopes/dataRenderers";
|
|
36
|
+
import type { ToolsState } from "../../types/scopes/tools";
|
|
36
37
|
import { useShallow } from "zustand/shallow";
|
|
37
38
|
|
|
38
39
|
type MessagePartRange =
|
|
@@ -511,6 +512,19 @@ const QuoteRendererImpl: FC<{ Quote: QuoteMessagePartComponent }> = ({
|
|
|
511
512
|
|
|
512
513
|
const QuoteRenderer = memo(QuoteRendererImpl);
|
|
513
514
|
|
|
515
|
+
function resolveToolRender(
|
|
516
|
+
toolsState: ToolsState,
|
|
517
|
+
part: Extract<PartState, { type: "tool-call" }>,
|
|
518
|
+
): ToolCallMessagePartComponent | null {
|
|
519
|
+
const entry = toolsState.tools[part.toolName];
|
|
520
|
+
const named = Array.isArray(entry) ? (entry[0] ?? null) : (entry ?? null);
|
|
521
|
+
if (named) return named;
|
|
522
|
+
if (isMcpAppUri(part.mcp?.app?.resourceUri) && toolsState.mcpApp) {
|
|
523
|
+
return toolsState.mcpApp.render;
|
|
524
|
+
}
|
|
525
|
+
return null;
|
|
526
|
+
}
|
|
527
|
+
|
|
514
528
|
/**
|
|
515
529
|
* Stable propless component that renders the registered tool UI for the
|
|
516
530
|
* current part context. Reads tool registry and part state from context.
|
|
@@ -518,12 +532,9 @@ const QuoteRenderer = memo(QuoteRendererImpl);
|
|
|
518
532
|
const RegisteredToolUI: FC = () => {
|
|
519
533
|
const aui = useAui();
|
|
520
534
|
const part = useAuiState((s) => s.part);
|
|
521
|
-
const Render = useAuiState((s) =>
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
if (Array.isArray(entry)) return entry[0] ?? null;
|
|
525
|
-
return entry ?? null;
|
|
526
|
-
});
|
|
535
|
+
const Render = useAuiState((s) =>
|
|
536
|
+
s.part.type === "tool-call" ? resolveToolRender(s.tools, s.part) : null,
|
|
537
|
+
);
|
|
527
538
|
|
|
528
539
|
if (!Render || part.type !== "tool-call") return null;
|
|
529
540
|
|
|
@@ -638,8 +649,8 @@ export const MessagePartChildren: FC<{
|
|
|
638
649
|
get part() {
|
|
639
650
|
const state = getItem();
|
|
640
651
|
if (state.type === "tool-call") {
|
|
641
|
-
const
|
|
642
|
-
const hasUI =
|
|
652
|
+
const toolsState = aui.tools().getState();
|
|
653
|
+
const hasUI = resolveToolRender(toolsState, state) !== null;
|
|
643
654
|
const partMethods = aui.message().part({ index });
|
|
644
655
|
return {
|
|
645
656
|
...state,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { FC, PropsWithChildren } from "react";
|
|
2
|
+
import { useAuiState } from "@assistant-ui/store";
|
|
3
|
+
|
|
4
|
+
export namespace MessagePartPrimitiveInProgress {
|
|
5
|
+
export type Props = PropsWithChildren;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const MessagePartPrimitiveInProgress: FC<
|
|
9
|
+
MessagePartPrimitiveInProgress.Props
|
|
10
|
+
> = ({ children }) => {
|
|
11
|
+
const isInProgress = useAuiState((s) => s.part.status.type === "running");
|
|
12
|
+
return isInProgress ? children : null;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
MessagePartPrimitiveInProgress.displayName = "MessagePartPrimitive.InProgress";
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
MessageStatus,
|
|
3
|
+
SourceProviderMetadata,
|
|
4
|
+
ThreadMessage,
|
|
5
|
+
} from "../../../types/message";
|
|
2
6
|
import { fromThreadMessageLike } from "../../../runtime/utils/thread-message-like";
|
|
3
7
|
import type { CloudMessage } from "assistant-cloud";
|
|
4
8
|
import { isJSONValue } from "../../../utils/json/is-json";
|
|
@@ -23,6 +27,16 @@ type AuiV0MessagePart =
|
|
|
23
27
|
readonly id: string;
|
|
24
28
|
readonly url: string;
|
|
25
29
|
readonly title?: string;
|
|
30
|
+
readonly providerMetadata?: SourceProviderMetadata;
|
|
31
|
+
}
|
|
32
|
+
| {
|
|
33
|
+
readonly type: "source";
|
|
34
|
+
readonly sourceType: "document";
|
|
35
|
+
readonly id: string;
|
|
36
|
+
readonly title: string;
|
|
37
|
+
readonly mediaType: string;
|
|
38
|
+
readonly filename?: string;
|
|
39
|
+
readonly providerMetadata?: SourceProviderMetadata;
|
|
26
40
|
}
|
|
27
41
|
| {
|
|
28
42
|
readonly type: "tool-call";
|
|
@@ -90,12 +104,31 @@ export function auiV0Encode(message: ThreadMessage): AuiV0Message {
|
|
|
90
104
|
return { type: "reasoning", text: part.text };
|
|
91
105
|
|
|
92
106
|
case "source":
|
|
107
|
+
if (part.sourceType === "url") {
|
|
108
|
+
return {
|
|
109
|
+
type: "source",
|
|
110
|
+
sourceType: "url",
|
|
111
|
+
id: part.id,
|
|
112
|
+
url: part.url,
|
|
113
|
+
...(part.title != null ? { title: part.title } : undefined),
|
|
114
|
+
...(part.providerMetadata != null
|
|
115
|
+
? { providerMetadata: part.providerMetadata }
|
|
116
|
+
: undefined),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
93
120
|
return {
|
|
94
121
|
type: "source",
|
|
95
|
-
sourceType:
|
|
122
|
+
sourceType: "document",
|
|
96
123
|
id: part.id,
|
|
97
|
-
|
|
98
|
-
|
|
124
|
+
title: part.title,
|
|
125
|
+
mediaType: part.mediaType,
|
|
126
|
+
...(part.filename != null
|
|
127
|
+
? { filename: part.filename }
|
|
128
|
+
: undefined),
|
|
129
|
+
...(part.providerMetadata != null
|
|
130
|
+
? { providerMetadata: part.providerMetadata }
|
|
131
|
+
: undefined),
|
|
99
132
|
};
|
|
100
133
|
|
|
101
134
|
case "tool-call": {
|