@assistant-ui/core 0.1.8 → 0.1.10
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/adapters/attachment.d.ts +4 -0
- package/dist/adapters/attachment.d.ts.map +1 -1
- package/dist/adapters/attachment.js +1 -1
- package/dist/adapters/attachment.js.map +1 -1
- package/dist/adapters/index.d.ts +3 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +1 -0
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/voice.d.ts +49 -0
- package/dist/adapters/voice.d.ts.map +1 -0
- package/dist/adapters/voice.js +109 -0
- package/dist/adapters/voice.js.map +1 -0
- package/dist/index.d.ts +5 -2
- 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/types.d.ts +4 -0
- package/dist/model-context/types.d.ts.map +1 -1
- package/dist/model-context/types.js.map +1 -1
- package/dist/react/client/Interactables.d.ts +3 -0
- package/dist/react/client/Interactables.d.ts.map +1 -0
- package/dist/react/client/Interactables.js +263 -0
- package/dist/react/client/Interactables.js.map +1 -0
- package/dist/react/client/interactable-model-context.d.ts +8 -0
- package/dist/react/client/interactable-model-context.d.ts.map +1 -0
- package/dist/react/client/interactable-model-context.js +62 -0
- package/dist/react/client/interactable-model-context.js.map +1 -0
- package/dist/react/index.d.ts +7 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +6 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/model-context/useAssistantContext.d.ts +4 -0
- package/dist/react/model-context/useAssistantContext.d.ts.map +1 -0
- package/dist/react/model-context/useAssistantContext.js +18 -0
- package/dist/react/model-context/useAssistantContext.js.map +1 -0
- package/dist/react/model-context/useAssistantInteractable.d.ts +18 -0
- package/dist/react/model-context/useAssistantInteractable.d.ts.map +1 -0
- package/dist/react/model-context/useAssistantInteractable.js +31 -0
- package/dist/react/model-context/useAssistantInteractable.js.map +1 -0
- package/dist/react/model-context/useInteractableState.d.ts +15 -0
- package/dist/react/model-context/useInteractableState.d.ts.map +1 -0
- package/dist/react/model-context/useInteractableState.js +36 -0
- package/dist/react/model-context/useInteractableState.js.map +1 -0
- package/dist/react/model-context/useToolArgsStatus.d.ts +8 -0
- package/dist/react/model-context/useToolArgsStatus.d.ts.map +1 -0
- package/dist/react/model-context/useToolArgsStatus.js +31 -0
- package/dist/react/model-context/useToolArgsStatus.js.map +1 -0
- package/dist/react/primitive-hooks/useVoice.d.ts +10 -0
- package/dist/react/primitive-hooks/useVoice.d.ts.map +1 -0
- package/dist/react/primitive-hooks/useVoice.js +28 -0
- package/dist/react/primitive-hooks/useVoice.js.map +1 -0
- package/dist/react/primitives/message/MessageParts.d.ts.map +1 -1
- package/dist/react/primitives/message/MessageParts.js +2 -0
- package/dist/react/primitives/message/MessageParts.js.map +1 -1
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts +14 -0
- package/dist/react/runtimes/RemoteThreadListHookInstanceManager.d.ts.map +1 -1
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +14 -0
- package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
- package/dist/react/runtimes/useLocalRuntime.d.ts +1 -0
- package/dist/react/runtimes/useLocalRuntime.d.ts.map +1 -1
- package/dist/react/types/scopes/interactables.d.ts +56 -0
- package/dist/react/types/scopes/interactables.d.ts.map +1 -0
- package/dist/react/types/scopes/interactables.js +2 -0
- package/dist/react/types/scopes/interactables.js.map +1 -0
- package/dist/react/types/store-augmentation.d.ts +2 -0
- package/dist/react/types/store-augmentation.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.d.ts +21 -1
- package/dist/runtime/api/thread-runtime.d.ts.map +1 -1
- package/dist/runtime/api/thread-runtime.js +25 -0
- package/dist/runtime/api/thread-runtime.js.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts +1 -1
- package/dist/runtime/base/base-composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-composer-runtime-core.js +33 -8
- package/dist/runtime/base/base-composer-runtime-core.js.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts +24 -1
- package/dist/runtime/base/base-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtime/base/base-thread-runtime-core.js +205 -1
- package/dist/runtime/base/base-thread-runtime-core.js.map +1 -1
- package/dist/runtime/interfaces/composer-runtime-core.d.ts +1 -1
- package/dist/runtime/interfaces/composer-runtime-core.d.ts.map +1 -1
- package/dist/runtime/interfaces/thread-runtime-core.d.ts +14 -0
- package/dist/runtime/interfaces/thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-adapter.d.ts +2 -0
- package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.d.ts +2 -1
- 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 +3 -1
- package/dist/runtimes/external-store/external-store-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/local/local-runtime-options.d.ts +2 -0
- package/dist/runtimes/local/local-runtime-options.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.d.ts +2 -0
- package/dist/runtimes/local/local-thread-runtime-core.d.ts.map +1 -1
- package/dist/runtimes/local/local-thread-runtime-core.js +6 -0
- package/dist/runtimes/local/local-thread-runtime-core.js.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts +8 -0
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.d.ts.map +1 -1
- package/dist/runtimes/readonly/ReadonlyThreadRuntimeCore.js +15 -6
- 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 +17 -1
- package/dist/runtimes/remote-thread-list/empty-thread-core.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 +12 -5
- package/dist/store/runtime-clients/composer-runtime-client.js.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.d.ts.map +1 -1
- package/dist/store/runtime-clients/thread-runtime-client.js +7 -8
- package/dist/store/runtime-clients/thread-runtime-client.js.map +1 -1
- package/dist/store/scopes/composer.d.ts +5 -0
- package/dist/store/scopes/composer.d.ts.map +1 -1
- package/dist/store/scopes/thread.d.ts +9 -9
- package/dist/store/scopes/thread.d.ts.map +1 -1
- package/dist/types/message.d.ts +1 -0
- package/dist/types/message.d.ts.map +1 -1
- package/package.json +9 -15
- package/src/adapters/attachment.ts +1 -1
- package/src/adapters/index.ts +5 -0
- package/src/adapters/voice.ts +166 -0
- package/src/index.ts +10 -0
- package/src/model-context/types.ts +5 -0
- package/src/react/client/Interactables.ts +332 -0
- package/src/react/client/interactable-model-context.ts +83 -0
- package/src/react/index.ts +30 -0
- package/src/react/model-context/useAssistantContext.ts +22 -0
- package/src/react/model-context/useAssistantInteractable.ts +47 -0
- package/src/react/model-context/useInteractableState.ts +63 -0
- package/src/react/model-context/useToolArgsStatus.ts +51 -0
- package/src/react/primitive-hooks/useVoice.ts +41 -0
- package/src/react/primitives/message/MessageParts.tsx +2 -0
- package/src/react/types/scopes/interactables.ts +66 -0
- package/src/react/types/store-augmentation.ts +2 -0
- package/src/runtime/api/thread-runtime.ts +41 -0
- package/src/runtime/base/base-composer-runtime-core.ts +45 -9
- package/src/runtime/base/base-thread-runtime-core.ts +243 -2
- package/src/runtime/interfaces/composer-runtime-core.ts +4 -1
- package/src/runtime/interfaces/thread-runtime-core.ts +17 -0
- package/src/runtimes/external-store/external-store-adapter.ts +2 -0
- package/src/runtimes/external-store/external-store-thread-runtime-core.ts +3 -1
- package/src/runtimes/local/local-runtime-options.ts +2 -0
- package/src/runtimes/local/local-thread-runtime-core.ts +7 -0
- package/src/runtimes/readonly/ReadonlyThreadRuntimeCore.ts +20 -6
- package/src/runtimes/remote-thread-list/empty-thread-core.ts +22 -1
- package/src/store/runtime-clients/composer-runtime-client.ts +18 -7
- package/src/store/runtime-clients/thread-runtime-client.ts +7 -8
- package/src/store/scopes/composer.ts +5 -0
- package/src/store/scopes/thread.ts +9 -8
- package/src/types/message.ts +1 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useEffect, useId, useRef } from "react";
|
|
2
|
+
import { useAui } from "@assistant-ui/store";
|
|
3
|
+
import type { InteractableStateSchema } from "../types/scopes/interactables";
|
|
4
|
+
|
|
5
|
+
export type AssistantInteractableProps = {
|
|
6
|
+
description: string;
|
|
7
|
+
stateSchema: InteractableStateSchema;
|
|
8
|
+
initialState: unknown;
|
|
9
|
+
id?: string;
|
|
10
|
+
selected?: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Registers an interactable with the AI assistant.
|
|
15
|
+
*
|
|
16
|
+
* This hook handles registration only. To read and write the interactable's
|
|
17
|
+
* state, use {@link useInteractableState} with the returned id.
|
|
18
|
+
*
|
|
19
|
+
* @returns The interactable instance id.
|
|
20
|
+
*/
|
|
21
|
+
export const useAssistantInteractable = (
|
|
22
|
+
name: string,
|
|
23
|
+
config: AssistantInteractableProps,
|
|
24
|
+
): string => {
|
|
25
|
+
const aui = useAui();
|
|
26
|
+
|
|
27
|
+
const autoId = useId().replace(/[^a-zA-Z0-9]/g, "");
|
|
28
|
+
const id = config.id ?? autoId;
|
|
29
|
+
|
|
30
|
+
const stateSchemaRef = useRef(config.stateSchema);
|
|
31
|
+
stateSchemaRef.current = config.stateSchema;
|
|
32
|
+
const initialStateRef = useRef(config.initialState);
|
|
33
|
+
initialStateRef.current = config.initialState;
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
return aui.interactables().register({
|
|
37
|
+
id,
|
|
38
|
+
name,
|
|
39
|
+
description: config.description,
|
|
40
|
+
stateSchema: stateSchemaRef.current,
|
|
41
|
+
initialState: initialStateRef.current,
|
|
42
|
+
selected: config.selected,
|
|
43
|
+
});
|
|
44
|
+
}, [aui, id, name, config.description, config.selected]);
|
|
45
|
+
|
|
46
|
+
return id;
|
|
47
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
3
|
+
|
|
4
|
+
type StateUpdater<TState> = TState | ((prev: TState) => TState);
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Reads and writes the state of a registered interactable.
|
|
8
|
+
*
|
|
9
|
+
* Pair with {@link useAssistantInteractable} which handles registration.
|
|
10
|
+
*/
|
|
11
|
+
export const useInteractableState = <TState>(
|
|
12
|
+
id: string,
|
|
13
|
+
fallback: TState,
|
|
14
|
+
): [
|
|
15
|
+
TState,
|
|
16
|
+
{
|
|
17
|
+
setState: (updater: StateUpdater<TState>) => void;
|
|
18
|
+
setSelected: (selected: boolean) => void;
|
|
19
|
+
isPending: boolean;
|
|
20
|
+
error: unknown;
|
|
21
|
+
flush: () => Promise<void>;
|
|
22
|
+
},
|
|
23
|
+
] => {
|
|
24
|
+
const aui = useAui();
|
|
25
|
+
|
|
26
|
+
const state =
|
|
27
|
+
(useAuiState((s) => s.interactables.definitions[id]?.state) as TState) ??
|
|
28
|
+
(fallback as TState);
|
|
29
|
+
|
|
30
|
+
const persistenceStatus = useAuiState((s) => s.interactables.persistence[id]);
|
|
31
|
+
|
|
32
|
+
const setState = useCallback(
|
|
33
|
+
(updater: StateUpdater<TState>) => {
|
|
34
|
+
aui.interactables().setState(id, (prev) => {
|
|
35
|
+
if (typeof updater === "function") {
|
|
36
|
+
return (updater as (prev: TState) => TState)(prev as TState);
|
|
37
|
+
}
|
|
38
|
+
return updater;
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
[aui, id],
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const setSelected = useCallback(
|
|
45
|
+
(selected: boolean) => {
|
|
46
|
+
aui.interactables().setSelected(id, selected);
|
|
47
|
+
},
|
|
48
|
+
[aui, id],
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const flush = useCallback(() => aui.interactables().flush(), [aui]);
|
|
52
|
+
|
|
53
|
+
return [
|
|
54
|
+
state,
|
|
55
|
+
{
|
|
56
|
+
setState,
|
|
57
|
+
setSelected,
|
|
58
|
+
isPending: persistenceStatus?.isPending ?? false,
|
|
59
|
+
error: persistenceStatus?.error,
|
|
60
|
+
flush,
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useAuiState } from "@assistant-ui/store";
|
|
3
|
+
import {
|
|
4
|
+
getPartialJsonObjectFieldState,
|
|
5
|
+
getPartialJsonObjectMeta,
|
|
6
|
+
} from "assistant-stream/utils";
|
|
7
|
+
|
|
8
|
+
type PropFieldStatus = "streaming" | "complete";
|
|
9
|
+
|
|
10
|
+
export type ToolArgsStatus<
|
|
11
|
+
TArgs extends Record<string, unknown> = Record<string, unknown>,
|
|
12
|
+
> = {
|
|
13
|
+
status: "running" | "complete" | "incomplete" | "requires-action";
|
|
14
|
+
propStatus: Partial<Record<keyof TArgs, PropFieldStatus>>;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const useToolArgsStatus = <
|
|
18
|
+
TArgs extends Record<string, unknown> = Record<string, unknown>,
|
|
19
|
+
>(): ToolArgsStatus<TArgs> => {
|
|
20
|
+
const part = useAuiState((s) => s.part);
|
|
21
|
+
|
|
22
|
+
return useMemo(() => {
|
|
23
|
+
const statusType = part.status.type;
|
|
24
|
+
|
|
25
|
+
if (part.type !== "tool-call") {
|
|
26
|
+
throw new Error(
|
|
27
|
+
"useToolArgsStatus can only be used inside tool-call message parts",
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const isStreaming = statusType === "running";
|
|
32
|
+
const args = part.args as Record<string, unknown>;
|
|
33
|
+
const meta = getPartialJsonObjectMeta(args as Record<symbol, unknown>);
|
|
34
|
+
const propStatus: Partial<Record<string, PropFieldStatus>> = {};
|
|
35
|
+
|
|
36
|
+
for (const key of Object.keys(args)) {
|
|
37
|
+
if (meta) {
|
|
38
|
+
const fieldState = getPartialJsonObjectFieldState(args, [key]);
|
|
39
|
+
propStatus[key] =
|
|
40
|
+
fieldState === "complete" || !isStreaming ? "complete" : "streaming";
|
|
41
|
+
} else {
|
|
42
|
+
propStatus[key] = isStreaming ? "streaming" : "complete";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
status: statusType,
|
|
48
|
+
propStatus: propStatus as Partial<Record<keyof TArgs, PropFieldStatus>>,
|
|
49
|
+
};
|
|
50
|
+
}, [part]);
|
|
51
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useCallback, useSyncExternalStore } from "react";
|
|
2
|
+
import { useAui, useAuiState } from "@assistant-ui/store";
|
|
3
|
+
import type { VoiceSessionState } from "../../runtime/interfaces/thread-runtime-core";
|
|
4
|
+
|
|
5
|
+
export const useVoiceState = (): VoiceSessionState | undefined => {
|
|
6
|
+
return useAuiState((s) => s.thread.voice);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const getServerVolume = () => 0;
|
|
10
|
+
|
|
11
|
+
export const useVoiceVolume = (): number => {
|
|
12
|
+
const aui = useAui();
|
|
13
|
+
const thread = aui.thread();
|
|
14
|
+
return useSyncExternalStore(
|
|
15
|
+
thread.subscribeVoiceVolume,
|
|
16
|
+
thread.getVoiceVolume,
|
|
17
|
+
getServerVolume,
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const useVoiceControls = () => {
|
|
22
|
+
const aui = useAui();
|
|
23
|
+
|
|
24
|
+
const connect = useCallback(() => {
|
|
25
|
+
aui.thread().connectVoice();
|
|
26
|
+
}, [aui]);
|
|
27
|
+
|
|
28
|
+
const disconnect = useCallback(() => {
|
|
29
|
+
aui.thread().disconnectVoice();
|
|
30
|
+
}, [aui]);
|
|
31
|
+
|
|
32
|
+
const mute = useCallback(() => {
|
|
33
|
+
aui.thread().muteVoice();
|
|
34
|
+
}, [aui]);
|
|
35
|
+
|
|
36
|
+
const unmute = useCallback(() => {
|
|
37
|
+
aui.thread().unmuteVoice();
|
|
38
|
+
}, [aui]);
|
|
39
|
+
|
|
40
|
+
return { connect, disconnect, mute, unmute };
|
|
41
|
+
};
|
|
@@ -440,6 +440,8 @@ const EmptyPartsImpl: FC<MessagePartComponentProps> = ({ components }) => {
|
|
|
440
440
|
|
|
441
441
|
if (components?.Empty) return <components.Empty status={status} />;
|
|
442
442
|
|
|
443
|
+
if (status.type !== "running") return null;
|
|
444
|
+
|
|
443
445
|
return (
|
|
444
446
|
<EmptyPartFallback
|
|
445
447
|
status={status}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Tool } from "assistant-stream";
|
|
2
|
+
import type { Unsubscribe } from "../../..";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Schema type matching Tool["parameters"] from assistant-stream.
|
|
6
|
+
* Accepts both StandardSchemaV1 and JSONSchema7.
|
|
7
|
+
*/
|
|
8
|
+
export type InteractableStateSchema = NonNullable<
|
|
9
|
+
Extract<Tool, { parameters: unknown }>["parameters"]
|
|
10
|
+
>;
|
|
11
|
+
|
|
12
|
+
export type InteractableDefinition = {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
description: string;
|
|
16
|
+
stateSchema: InteractableStateSchema;
|
|
17
|
+
state: unknown;
|
|
18
|
+
selected?: boolean | undefined;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type InteractableRegistration = {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
description: string;
|
|
25
|
+
stateSchema: InteractableStateSchema;
|
|
26
|
+
initialState: unknown;
|
|
27
|
+
selected?: boolean | undefined;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type InteractablePersistenceStatus = {
|
|
31
|
+
isPending: boolean;
|
|
32
|
+
error: unknown;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type InteractablesState = {
|
|
36
|
+
/** Keyed by instance id */
|
|
37
|
+
definitions: Record<string, InteractableDefinition>;
|
|
38
|
+
/** Per-id persistence sync status */
|
|
39
|
+
persistence: Record<string, InteractablePersistenceStatus>;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type InteractablePersistedState = Record<
|
|
43
|
+
string,
|
|
44
|
+
{ name: string; state: unknown }
|
|
45
|
+
>;
|
|
46
|
+
|
|
47
|
+
export type InteractablePersistenceAdapter = {
|
|
48
|
+
save(state: InteractablePersistedState): void | Promise<void>;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type InteractablesMethods = {
|
|
52
|
+
getState(): InteractablesState;
|
|
53
|
+
register(def: InteractableRegistration): Unsubscribe;
|
|
54
|
+
setState(id: string, updater: (prev: unknown) => unknown): void;
|
|
55
|
+
setSelected(id: string, selected: boolean): void;
|
|
56
|
+
exportState(): InteractablePersistedState;
|
|
57
|
+
importState(saved: InteractablePersistedState): void;
|
|
58
|
+
setPersistenceAdapter(
|
|
59
|
+
adapter: InteractablePersistenceAdapter | undefined,
|
|
60
|
+
): void;
|
|
61
|
+
flush(): Promise<void>;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export type InteractablesClientSchema = {
|
|
65
|
+
methods: InteractablesMethods;
|
|
66
|
+
};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { ToolsClientSchema } from "./scopes/tools";
|
|
2
2
|
import type { DataRenderersClientSchema } from "./scopes/dataRenderers";
|
|
3
|
+
import type { InteractablesClientSchema } from "./scopes/interactables";
|
|
3
4
|
|
|
4
5
|
declare module "@assistant-ui/store" {
|
|
5
6
|
interface ScopeRegistry {
|
|
6
7
|
tools: ToolsClientSchema;
|
|
7
8
|
dataRenderers: DataRenderersClientSchema;
|
|
9
|
+
interactables: InteractablesClientSchema;
|
|
8
10
|
}
|
|
9
11
|
}
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
RuntimeCapabilities,
|
|
4
4
|
ThreadRuntimeCore,
|
|
5
5
|
SpeechState,
|
|
6
|
+
VoiceSessionState,
|
|
6
7
|
ThreadRuntimeEventType,
|
|
7
8
|
StartRunConfig,
|
|
8
9
|
ResumeRunConfig,
|
|
@@ -187,6 +188,8 @@ export type ThreadState = {
|
|
|
187
188
|
* @deprecated This API is still under active development and might change without notice.
|
|
188
189
|
*/
|
|
189
190
|
readonly speech: SpeechState | undefined;
|
|
191
|
+
|
|
192
|
+
readonly voice: VoiceSessionState | undefined;
|
|
190
193
|
};
|
|
191
194
|
|
|
192
195
|
export const getThreadState = (
|
|
@@ -209,6 +212,7 @@ export const getThreadState = (
|
|
|
209
212
|
suggestions: runtime.suggestions,
|
|
210
213
|
extras: runtime.extras,
|
|
211
214
|
speech: runtime.speech,
|
|
215
|
+
voice: runtime.voice,
|
|
212
216
|
});
|
|
213
217
|
};
|
|
214
218
|
|
|
@@ -317,6 +321,13 @@ export type ThreadRuntime = {
|
|
|
317
321
|
*/
|
|
318
322
|
stopSpeaking(): void;
|
|
319
323
|
|
|
324
|
+
connectVoice(): void;
|
|
325
|
+
disconnectVoice(): void;
|
|
326
|
+
getVoiceVolume(): number;
|
|
327
|
+
subscribeVoiceVolume(callback: () => void): Unsubscribe;
|
|
328
|
+
muteVoice(): void;
|
|
329
|
+
unmuteVoice(): void;
|
|
330
|
+
|
|
320
331
|
unstable_on(event: ThreadRuntimeEventType, callback: () => void): Unsubscribe;
|
|
321
332
|
};
|
|
322
333
|
|
|
@@ -388,6 +399,12 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
388
399
|
this.startRun = this.startRun.bind(this);
|
|
389
400
|
this.cancelRun = this.cancelRun.bind(this);
|
|
390
401
|
this.stopSpeaking = this.stopSpeaking.bind(this);
|
|
402
|
+
this.connectVoice = this.connectVoice.bind(this);
|
|
403
|
+
this.disconnectVoice = this.disconnectVoice.bind(this);
|
|
404
|
+
this.muteVoice = this.muteVoice.bind(this);
|
|
405
|
+
this.unmuteVoice = this.unmuteVoice.bind(this);
|
|
406
|
+
this.getVoiceVolume = this.getVoiceVolume.bind(this);
|
|
407
|
+
this.subscribeVoiceVolume = this.subscribeVoiceVolume.bind(this);
|
|
391
408
|
this.export = this.export.bind(this);
|
|
392
409
|
this.import = this.import.bind(this);
|
|
393
410
|
this.reset = this.reset.bind(this);
|
|
@@ -463,6 +480,30 @@ export class ThreadRuntimeImpl implements ThreadRuntime {
|
|
|
463
480
|
return this._threadBinding.getState().stopSpeaking();
|
|
464
481
|
}
|
|
465
482
|
|
|
483
|
+
public connectVoice() {
|
|
484
|
+
this._threadBinding.getState().connectVoice();
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
public disconnectVoice() {
|
|
488
|
+
this._threadBinding.getState().disconnectVoice();
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
public getVoiceVolume() {
|
|
492
|
+
return this._threadBinding.getState().getVoiceVolume();
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
public subscribeVoiceVolume(callback: () => void) {
|
|
496
|
+
return this._threadBinding.getState().subscribeVoiceVolume(callback);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
public muteVoice() {
|
|
500
|
+
this._threadBinding.getState().muteVoice();
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
public unmuteVoice() {
|
|
504
|
+
this._threadBinding.getState().unmuteVoice();
|
|
505
|
+
}
|
|
506
|
+
|
|
466
507
|
public export() {
|
|
467
508
|
return this._threadBinding.getState().export();
|
|
468
509
|
}
|
|
@@ -9,7 +9,10 @@ import type { QuoteInfo } from "../../types/quote";
|
|
|
9
9
|
import type { Unsubscribe } from "../../types/unsubscribe";
|
|
10
10
|
import type { RunConfig } from "../../types/message";
|
|
11
11
|
import { BaseSubscribable } from "../../subscribable/subscribable";
|
|
12
|
-
import
|
|
12
|
+
import {
|
|
13
|
+
type AttachmentAdapter,
|
|
14
|
+
fileMatchesAccept,
|
|
15
|
+
} from "../../adapters/attachment";
|
|
13
16
|
import type {
|
|
14
17
|
ComposerRuntimeCore,
|
|
15
18
|
ComposerRuntimeEventType,
|
|
@@ -216,6 +219,17 @@ export abstract class BaseComposerRuntimeCore
|
|
|
216
219
|
const adapter = this.getAttachmentAdapter();
|
|
217
220
|
if (!adapter) throw new Error("Attachments are not supported");
|
|
218
221
|
|
|
222
|
+
if (
|
|
223
|
+
!fileMatchesAccept(
|
|
224
|
+
{ name: fileOrAttachment.name, type: fileOrAttachment.type },
|
|
225
|
+
adapter.accept,
|
|
226
|
+
)
|
|
227
|
+
) {
|
|
228
|
+
throw new Error(
|
|
229
|
+
`File type ${fileOrAttachment.type || "unknown"} is not accepted. Accepted types: ${adapter.accept}`,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
219
233
|
const upsertAttachment = (a: PendingAttachment) => {
|
|
220
234
|
const idx = this._attachments.findIndex(
|
|
221
235
|
(attachment) => attachment.id === a.id,
|
|
@@ -233,17 +247,39 @@ export abstract class BaseComposerRuntimeCore
|
|
|
233
247
|
this._notifySubscribers();
|
|
234
248
|
};
|
|
235
249
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
250
|
+
let lastAttachment: PendingAttachment | undefined;
|
|
251
|
+
try {
|
|
252
|
+
const promiseOrGenerator = adapter.add({ file: fileOrAttachment });
|
|
253
|
+
if (Symbol.asyncIterator in promiseOrGenerator) {
|
|
254
|
+
for await (const r of promiseOrGenerator) {
|
|
255
|
+
lastAttachment = r;
|
|
256
|
+
upsertAttachment(r);
|
|
257
|
+
}
|
|
258
|
+
} else {
|
|
259
|
+
lastAttachment = await promiseOrGenerator;
|
|
260
|
+
upsertAttachment(lastAttachment);
|
|
240
261
|
}
|
|
241
|
-
}
|
|
242
|
-
|
|
262
|
+
} catch (e) {
|
|
263
|
+
if (lastAttachment) {
|
|
264
|
+
upsertAttachment({
|
|
265
|
+
...lastAttachment,
|
|
266
|
+
status: { type: "incomplete", reason: "error" },
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
this._notifyEventSubscribers("attachmentAddError");
|
|
271
|
+
} catch {
|
|
272
|
+
// prevent subscriber errors from masking the adapter error
|
|
273
|
+
}
|
|
274
|
+
throw e;
|
|
243
275
|
}
|
|
244
276
|
|
|
245
|
-
|
|
246
|
-
|
|
277
|
+
const hasError =
|
|
278
|
+
lastAttachment?.status.type === "incomplete" &&
|
|
279
|
+
lastAttachment.status.reason === "error";
|
|
280
|
+
this._notifyEventSubscribers(
|
|
281
|
+
hasError ? "attachmentAddError" : "attachmentAdd",
|
|
282
|
+
);
|
|
247
283
|
}
|
|
248
284
|
|
|
249
285
|
async removeAttachment(attachmentId: string) {
|