@alexkroman1/aai-ui 0.12.2 → 1.0.2

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.
Files changed (68) hide show
  1. package/dist/_react-test-utils.d.ts +86 -0
  2. package/dist/audio.js +4 -5
  3. package/dist/build-default-client.d.ts +1 -0
  4. package/dist/{_components → components}/button.d.ts +4 -4
  5. package/dist/{_components → components}/button.js +28 -5
  6. package/dist/components/chat-view.d.ts +38 -0
  7. package/dist/components/chat-view.js +102 -0
  8. package/dist/{_components → components}/controls.d.ts +1 -1
  9. package/dist/{_components → components}/controls.js +8 -5
  10. package/dist/{_components → components}/message-list.d.ts +2 -2
  11. package/dist/components/message-list.js +149 -0
  12. package/dist/components/sidebar-layout.d.ts +21 -0
  13. package/dist/components/sidebar-layout.js +43 -0
  14. package/dist/{_components → components}/start-screen.d.ts +4 -4
  15. package/dist/{_components → components}/start-screen.js +17 -8
  16. package/dist/{_components → components}/tool-call-block.d.ts +5 -6
  17. package/dist/components/tool-call-block.js +3 -0
  18. package/dist/components/tool-config-context.d.ts +22 -0
  19. package/dist/context.d.ts +23 -0
  20. package/dist/context.js +39 -0
  21. package/dist/default-client/assets/audio-DH9LpexG.js +1 -0
  22. package/dist/default-client/assets/capture-processor-C26lSiVr.js +53 -0
  23. package/dist/default-client/assets/default-client-AeJhjHfj.js +49 -0
  24. package/dist/default-client/assets/default-client-BK1ItCvw.css +2 -0
  25. package/dist/default-client/assets/playback-processor-dSA8Im99.js +101 -0
  26. package/dist/default-client/default-client.html +15 -0
  27. package/dist/default-client.d.ts +2 -0
  28. package/dist/define-client.d.ts +72 -24
  29. package/dist/define-client.js +71 -45
  30. package/dist/hooks.d.ts +5 -0
  31. package/dist/hooks.js +55 -0
  32. package/dist/index.d.ts +15 -37
  33. package/dist/index.js +11 -18
  34. package/dist/session-core.d.ts +70 -0
  35. package/dist/session-core.js +437 -0
  36. package/dist/tool-call-block-CCuChsFm.js +131 -0
  37. package/dist/types.d.ts +19 -22
  38. package/package.json +24 -18
  39. package/styles.css +3 -33
  40. package/dist/_components/app.d.ts +0 -23
  41. package/dist/_components/app.js +0 -41
  42. package/dist/_components/chat-view.d.ts +0 -29
  43. package/dist/_components/chat-view.js +0 -61
  44. package/dist/_components/error-banner.d.ts +0 -21
  45. package/dist/_components/error-banner.js +0 -27
  46. package/dist/_components/message-bubble.d.ts +0 -23
  47. package/dist/_components/message-bubble.js +0 -35
  48. package/dist/_components/message-list.js +0 -76
  49. package/dist/_components/sidebar-layout.d.ts +0 -21
  50. package/dist/_components/sidebar-layout.js +0 -36
  51. package/dist/_components/state-indicator.d.ts +0 -29
  52. package/dist/_components/state-indicator.js +0 -37
  53. package/dist/_components/thinking-indicator.d.ts +0 -16
  54. package/dist/_components/thinking-indicator.js +0 -34
  55. package/dist/_components/tool-call-block.js +0 -118
  56. package/dist/_components/tool-icons.d.ts +0 -17
  57. package/dist/_components/tool-icons.js +0 -128
  58. package/dist/_components/transcript.d.ts +0 -25
  59. package/dist/_components/transcript.js +0 -35
  60. package/dist/client-context.d.ts +0 -33
  61. package/dist/client-context.js +0 -15
  62. package/dist/client-handler.d.ts +0 -43
  63. package/dist/session-CWB7vmqz.js +0 -429
  64. package/dist/session.d.ts +0 -69
  65. package/dist/session.js +0 -2
  66. package/dist/signals.d.ts +0 -120
  67. package/dist/signals.js +0 -161
  68. package/dist/types.test-d.d.ts +0 -7
@@ -1,118 +0,0 @@
1
- import { BoltIcon, ChatBubbleIcon, DownloadIcon, ExternalLinkIcon, SearchIcon, TerminalIcon } from "./tool-icons.js";
2
- import clsx from "clsx";
3
- import { useComputed, useSignal } from "@preact/signals";
4
- import { jsx, jsxs } from "preact/jsx-runtime";
5
- //#region _components/tool-call-block.tsx
6
- const argField = (key) => (args) => String(args[key] ?? "");
7
- const TOOL_CONFIG = {
8
- web_search: {
9
- Icon: SearchIcon,
10
- title: "Web Search",
11
- subtitle: argField("query")
12
- },
13
- visit_webpage: {
14
- Icon: ExternalLinkIcon,
15
- title: "Visit Page",
16
- subtitle: argField("url")
17
- },
18
- run_code: {
19
- Icon: TerminalIcon,
20
- title: "Run Code",
21
- subtitle: (args) => {
22
- const firstLine = String(args.code ?? "").split("\n")[0] ?? "";
23
- return firstLine.length > 80 ? `${firstLine.slice(0, 80)}...` : firstLine;
24
- }
25
- },
26
- fetch_json: {
27
- Icon: DownloadIcon,
28
- title: "Fetch JSON",
29
- subtitle: argField("url")
30
- },
31
- user_input: {
32
- Icon: ChatBubbleIcon,
33
- title: "Asking User",
34
- subtitle: argField("question")
35
- }
36
- };
37
- const DEFAULT_CONFIG = {
38
- Icon: BoltIcon,
39
- title: "",
40
- subtitle: (args) => {
41
- const summary = JSON.stringify(args);
42
- return summary.length > 80 ? `${summary.slice(0, 80)}...` : summary;
43
- }
44
- };
45
- function formatResult(result) {
46
- try {
47
- return JSON.stringify(JSON.parse(result), null, 2);
48
- } catch {
49
- return result;
50
- }
51
- }
52
- /**
53
- * Renders a tool invocation with an icon, title, subtitle, and a
54
- * collapsible result viewer.
55
- *
56
- * Built-in tool types (`web_search`, `visit_webpage`, `run_code`,
57
- * `fetch_json`, `user_input`) get custom icons and labels. Unknown tools
58
- * fall back to a generic bolt icon.
59
- *
60
- * While the tool call is pending a shimmer animation is shown. Once
61
- * complete, clicking the block expands the formatted JSON result.
62
- *
63
- * @example
64
- * ```tsx
65
- * <ToolCallBlock toolCall={toolCall} />
66
- * ```
67
- *
68
- * @param toolCall - The tool call to render (see {@link ToolCallInfo}).
69
- * @param className - Additional CSS class names.
70
- *
71
- * @public
72
- */
73
- function ToolCallBlock({ toolCall, className }) {
74
- const isOpen = useSignal(false);
75
- const config = TOOL_CONFIG[toolCall.toolName] ?? DEFAULT_CONFIG;
76
- const isPending = toolCall.status === "pending";
77
- const title = config.title || toolCall.toolName;
78
- const canExpand = !isPending && Boolean(toolCall.result);
79
- const formatted = useComputed(() => toolCall.result ? formatResult(toolCall.result) : "");
80
- return /* @__PURE__ */ jsxs("div", {
81
- class: clsx("flex flex-col", className),
82
- children: [/* @__PURE__ */ jsxs("button", {
83
- type: "button",
84
- "aria-expanded": canExpand ? isOpen.value : void 0,
85
- disabled: isPending,
86
- class: clsx("flex items-center gap-2 px-3 py-2 rounded-aai border border-aai-border bg-aai-surface-faint select-none text-left w-full", canExpand && "cursor-pointer"),
87
- onClick: () => {
88
- if (canExpand) isOpen.value = !isOpen.value;
89
- },
90
- children: [
91
- /* @__PURE__ */ jsx(config.Icon, { class: "w-4 h-4 text-aai-text-dim shrink-0" }),
92
- /* @__PURE__ */ jsx("span", {
93
- class: clsx("text-sm font-medium text-aai-text", isPending && "tool-shimmer"),
94
- children: title
95
- }),
96
- /* @__PURE__ */ jsx("span", {
97
- class: "text-sm text-aai-text-dim truncate flex-1 min-w-0",
98
- children: config.subtitle(toolCall.args)
99
- }),
100
- canExpand && /* @__PURE__ */ jsx("span", {
101
- class: "text-xs text-aai-text-dim shrink-0",
102
- children: isOpen.value ? "▾" : "▸"
103
- })
104
- ]
105
- }), isOpen.value && /* @__PURE__ */ jsxs("div", {
106
- class: "border-x border-b border-aai-border rounded-b-aai bg-aai-surface max-h-64 overflow-auto",
107
- children: [toolCall.toolName === "run_code" && toolCall.args.code && /* @__PURE__ */ jsx("pre", {
108
- class: "text-xs text-aai-text p-2 whitespace-pre-wrap border-b border-aai-border font-mono",
109
- children: String(toolCall.args.code)
110
- }), formatted.value && /* @__PURE__ */ jsx("pre", {
111
- class: "text-xs text-aai-text-dim p-2 whitespace-pre-wrap",
112
- children: formatted.value
113
- })]
114
- })]
115
- });
116
- }
117
- //#endregion
118
- export { ToolCallBlock };
@@ -1,17 +0,0 @@
1
- import type * as preact from "preact";
2
- type IconProps = {
3
- class?: string;
4
- };
5
- /** Magnifying glass icon for web_search. */
6
- export declare function SearchIcon(props: IconProps): preact.JSX.Element;
7
- /** External link icon for visit_webpage. */
8
- export declare function ExternalLinkIcon(props: IconProps): preact.JSX.Element;
9
- /** Terminal icon for run_code. */
10
- export declare function TerminalIcon(props: IconProps): preact.JSX.Element;
11
- /** Download icon for fetch_json. */
12
- export declare function DownloadIcon(props: IconProps): preact.JSX.Element;
13
- /** Chat bubble icon for user_input. */
14
- export declare function ChatBubbleIcon(props: IconProps): preact.JSX.Element;
15
- /** Bolt/lightning icon for default/unknown tools. */
16
- export declare function BoltIcon(props: IconProps): preact.JSX.Element;
17
- export {};
@@ -1,128 +0,0 @@
1
- import { jsx, jsxs } from "preact/jsx-runtime";
2
- //#region _components/tool-icons.tsx
3
- /** Magnifying glass icon for web_search. */
4
- function SearchIcon(props) {
5
- return /* @__PURE__ */ jsxs("svg", {
6
- viewBox: "0 0 16 16",
7
- fill: "none",
8
- stroke: "currentColor",
9
- "stroke-width": "1.5",
10
- class: props.class,
11
- children: [/* @__PURE__ */ jsx("circle", {
12
- cx: "7",
13
- cy: "7",
14
- r: "4.5"
15
- }), /* @__PURE__ */ jsx("path", {
16
- d: "M10.5 10.5L14 14",
17
- "stroke-linecap": "round"
18
- })]
19
- });
20
- }
21
- /** External link icon for visit_webpage. */
22
- function ExternalLinkIcon(props) {
23
- return /* @__PURE__ */ jsxs("svg", {
24
- viewBox: "0 0 16 16",
25
- fill: "none",
26
- stroke: "currentColor",
27
- "stroke-width": "1.5",
28
- class: props.class,
29
- children: [
30
- /* @__PURE__ */ jsx("path", {
31
- d: "M6 2H3a1 1 0 00-1 1v10a1 1 0 001 1h10a1 1 0 001-1v-3",
32
- "stroke-linecap": "round"
33
- }),
34
- /* @__PURE__ */ jsx("path", {
35
- d: "M9 2h5v5",
36
- "stroke-linecap": "round",
37
- "stroke-linejoin": "round"
38
- }),
39
- /* @__PURE__ */ jsx("path", {
40
- d: "M14 2L7 9",
41
- "stroke-linecap": "round"
42
- })
43
- ]
44
- });
45
- }
46
- /** Terminal icon for run_code. */
47
- function TerminalIcon(props) {
48
- return /* @__PURE__ */ jsxs("svg", {
49
- viewBox: "0 0 16 16",
50
- fill: "none",
51
- stroke: "currentColor",
52
- "stroke-width": "1.5",
53
- class: props.class,
54
- children: [
55
- /* @__PURE__ */ jsx("rect", {
56
- x: "1",
57
- y: "2",
58
- width: "14",
59
- height: "12",
60
- rx: "1.5"
61
- }),
62
- /* @__PURE__ */ jsx("path", {
63
- d: "M4 6l3 2.5L4 11",
64
- "stroke-linecap": "round",
65
- "stroke-linejoin": "round"
66
- }),
67
- /* @__PURE__ */ jsx("path", {
68
- d: "M9 11h3",
69
- "stroke-linecap": "round"
70
- })
71
- ]
72
- });
73
- }
74
- /** Download icon for fetch_json. */
75
- function DownloadIcon(props) {
76
- return /* @__PURE__ */ jsxs("svg", {
77
- viewBox: "0 0 16 16",
78
- fill: "none",
79
- stroke: "currentColor",
80
- "stroke-width": "1.5",
81
- class: props.class,
82
- children: [
83
- /* @__PURE__ */ jsx("path", {
84
- d: "M8 2v9",
85
- "stroke-linecap": "round"
86
- }),
87
- /* @__PURE__ */ jsx("path", {
88
- d: "M4.5 8L8 11.5 11.5 8",
89
- "stroke-linecap": "round",
90
- "stroke-linejoin": "round"
91
- }),
92
- /* @__PURE__ */ jsx("path", {
93
- d: "M2 13h12",
94
- "stroke-linecap": "round"
95
- })
96
- ]
97
- });
98
- }
99
- /** Chat bubble icon for user_input. */
100
- function ChatBubbleIcon(props) {
101
- return /* @__PURE__ */ jsx("svg", {
102
- viewBox: "0 0 16 16",
103
- fill: "none",
104
- stroke: "currentColor",
105
- "stroke-width": "1.5",
106
- class: props.class,
107
- children: /* @__PURE__ */ jsx("path", {
108
- d: "M2 3a1 1 0 011-1h10a1 1 0 011 1v7a1 1 0 01-1 1H5l-3 3V3z",
109
- "stroke-linejoin": "round"
110
- })
111
- });
112
- }
113
- /** Bolt/lightning icon for default/unknown tools. */
114
- function BoltIcon(props) {
115
- return /* @__PURE__ */ jsx("svg", {
116
- viewBox: "0 0 16 16",
117
- fill: "none",
118
- stroke: "currentColor",
119
- "stroke-width": "1.5",
120
- class: props.class,
121
- children: /* @__PURE__ */ jsx("path", {
122
- d: "M9 1L3 9h5l-1 6 6-8H8l1-6z",
123
- "stroke-linejoin": "round"
124
- })
125
- });
126
- }
127
- //#endregion
128
- export { BoltIcon, ChatBubbleIcon, DownloadIcon, ExternalLinkIcon, SearchIcon, TerminalIcon };
@@ -1,25 +0,0 @@
1
- import type * as preact from "preact";
2
- import type { Reactive } from "../types.ts";
3
- /**
4
- * Live speech-to-text transcript shown while the user is speaking.
5
- * Returns `null` when there is no active utterance.
6
- *
7
- * Displays a {@link ThinkingIndicator} while waiting for the first
8
- * transcription text (i.e., `userUtterance` is `""`).
9
- *
10
- * @example
11
- * ```tsx
12
- * const { session } = useSession();
13
- * <Transcript userUtterance={session.userUtterance} />
14
- * ```
15
- *
16
- * @param userUtterance - Reactive string (`null` when idle, `""` when
17
- * listening but no text yet, or the transcript text).
18
- * @param className - Additional CSS class names.
19
- *
20
- * @public
21
- */
22
- export declare function Transcript({ userUtterance, className, }: {
23
- userUtterance: Reactive<string | null>;
24
- className?: string;
25
- }): preact.JSX.Element | null;
@@ -1,35 +0,0 @@
1
- import { ThinkingIndicator } from "./thinking-indicator.js";
2
- import clsx from "clsx";
3
- import { jsx } from "preact/jsx-runtime";
4
- //#region _components/transcript.tsx
5
- /**
6
- * Live speech-to-text transcript shown while the user is speaking.
7
- * Returns `null` when there is no active utterance.
8
- *
9
- * Displays a {@link ThinkingIndicator} while waiting for the first
10
- * transcription text (i.e., `userUtterance` is `""`).
11
- *
12
- * @example
13
- * ```tsx
14
- * const { session } = useSession();
15
- * <Transcript userUtterance={session.userUtterance} />
16
- * ```
17
- *
18
- * @param userUtterance - Reactive string (`null` when idle, `""` when
19
- * listening but no text yet, or the transcript text).
20
- * @param className - Additional CSS class names.
21
- *
22
- * @public
23
- */
24
- function Transcript({ userUtterance, className }) {
25
- if (userUtterance.value === null) return null;
26
- return /* @__PURE__ */ jsx("div", {
27
- class: clsx("flex flex-col items-end w-full", className),
28
- children: /* @__PURE__ */ jsx("div", {
29
- class: "max-w-[min(82%,64ch)] whitespace-pre-wrap wrap-break-word text-sm leading-[150%] text-aai-text-muted bg-aai-surface-faint border border-aai-border px-3 py-2 rounded-aai ml-auto",
30
- children: userUtterance.value || /* @__PURE__ */ jsx(ThinkingIndicator, {})
31
- })
32
- });
33
- }
34
- //#endregion
35
- export { Transcript };
@@ -1,33 +0,0 @@
1
- /**
2
- * Theme overrides for the default UI. Applied as CSS custom properties.
3
- *
4
- * @public
5
- */
6
- export type ClientTheme = {
7
- /** Background color. Default: `#101010`. */
8
- bg?: string;
9
- /** Primary accent color. Default: `#fab283`. */
10
- primary?: string;
11
- /** Main text color. */
12
- text?: string;
13
- /** Surface/card color. */
14
- surface?: string;
15
- /** Border color. */
16
- border?: string;
17
- };
18
- /**
19
- * Resolved client-level configuration available to default UI components.
20
- *
21
- * @public
22
- */
23
- export type ClientConfig = {
24
- title?: string | undefined;
25
- theme?: ClientTheme | undefined;
26
- };
27
- export declare const ClientConfigProvider: import("preact").Provider<ClientConfig>;
28
- /**
29
- * Read client config (title, theme) from the nearest provider.
30
- *
31
- * @public
32
- */
33
- export declare function useClientConfig(): ClientConfig;
@@ -1,15 +0,0 @@
1
- import { createContext } from "preact";
2
- import { useContext } from "preact/hooks";
3
- //#region client-context.ts
4
- const Ctx = createContext({});
5
- const ClientConfigProvider = Ctx.Provider;
6
- /**
7
- * Read client config (title, theme) from the nearest provider.
8
- *
9
- * @public
10
- */
11
- function useClientConfig() {
12
- return useContext(Ctx);
13
- }
14
- //#endregion
15
- export { ClientConfigProvider, useClientConfig };
@@ -1,43 +0,0 @@
1
- import type { ReadyConfig } from "@alexkroman1/aai/protocol";
2
- import type { VoiceIO } from "./audio.ts";
3
- import type { AgentState, ChatMessage, Reactive, SessionError, ToolCallInfo } from "./types.ts";
4
- type BatchFn = (fn: () => void) => void;
5
- /**
6
- * Handles server→client messages and updates reactive Preact signals
7
- * accordingly (state transitions, transcripts, messages, audio playback).
8
- *
9
- * @internal Exported for testing only.
10
- */
11
- export declare class ClientHandler {
12
- #private;
13
- constructor(opts: {
14
- state: Reactive<AgentState>;
15
- messages: Reactive<ChatMessage[]>;
16
- toolCalls: Reactive<ToolCallInfo[]>;
17
- userUtterance: Reactive<string | null>;
18
- agentUtterance: Reactive<string | null>;
19
- error: Reactive<SessionError | null>;
20
- voiceIO: () => VoiceIO | null;
21
- batch: BatchFn;
22
- });
23
- /** Single entry point for all server→client session events. */
24
- event(e: import("@alexkroman1/aai/protocol").ClientEvent): void;
25
- /** Enqueue a PCM16 audio chunk for playback. Transitions state to `"speaking"` on the first chunk. */
26
- playAudioChunk(chunk: Uint8Array): void;
27
- /**
28
- * Signal that the server has finished sending audio for this turn.
29
- * Waits for the audio queue to drain, then transitions state to `"listening"`.
30
- * Uses the `#generation` counter to discard stale completions from interrupted turns.
31
- */
32
- playAudioDone(): void;
33
- /**
34
- * Dispatch an incoming WebSocket message (text or binary).
35
- *
36
- * Returns the parsed config if the message is a `config` message,
37
- * otherwise `null`.
38
- */
39
- handleMessage(data: string | ArrayBuffer): (ReadyConfig & {
40
- sessionId?: string;
41
- }) | null;
42
- }
43
- export {};