@alexkroman1/aai-ui 0.9.3 → 0.10.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/_components/app.d.ts +19 -1
- package/dist/_components/app.js +19 -1
- package/dist/_components/button.d.ts +43 -4
- package/dist/_components/button.js +33 -9
- package/dist/_components/chat-view.d.ts +25 -1
- package/dist/_components/chat-view.js +25 -1
- package/dist/_components/controls.d.ts +15 -1
- package/dist/_components/controls.js +15 -1
- package/dist/_components/error-banner.d.ts +15 -1
- package/dist/_components/error-banner.js +15 -1
- package/dist/_components/message-bubble.d.ts +19 -3
- package/dist/_components/message-bubble.js +17 -1
- package/dist/_components/message-list.d.ts +18 -1
- package/dist/_components/message-list.js +20 -3
- package/dist/_components/state-indicator.d.ts +23 -1
- package/dist/_components/state-indicator.js +23 -1
- package/dist/_components/thinking-indicator.d.ts +12 -1
- package/dist/_components/thinking-indicator.js +23 -11
- package/dist/_components/tool-call-block.d.ts +21 -1
- package/dist/_components/tool-call-block.js +33 -11
- package/dist/_components/transcript.d.ts +19 -1
- package/dist/_components/transcript.js +19 -1
- package/dist/_sqlite-stub.d.ts +3 -0
- package/dist/audio.js +13 -3
- package/dist/client-handler.d.ts +43 -0
- package/dist/index.d.ts +23 -6
- package/dist/index.js +3 -4
- package/dist/mount.d.ts +4 -0
- package/dist/mount.js +7 -4
- package/dist/session-D0RdWlWH.js +451 -0
- package/dist/session.d.ts +5 -36
- package/dist/session.js +1 -358
- package/dist/signals.d.ts +48 -0
- package/dist/signals.js +84 -25
- package/dist/types.d.ts +19 -5
- package/package.json +12 -10
- package/styles.css +2 -3
- package/dist/components.d.ts +0 -31
- package/dist/components.js +0 -17
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import type * as preact from "preact";
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* The default top-level UI component for an AAI voice agent.
|
|
4
|
+
* Renders a {@link StartScreen} (with the AAI logo or a custom title from
|
|
5
|
+
* {@link useMountConfig}) followed by a {@link ChatView} once the session starts.
|
|
6
|
+
*
|
|
7
|
+
* This is the component rendered by {@link mount} when no custom component is
|
|
8
|
+
* provided.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* import { App, mount } from "@aai/ui";
|
|
13
|
+
*
|
|
14
|
+
* mount(App, { target: "#app", title: "My Agent" });
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @param className - Additional CSS class names applied to the root element.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
3
21
|
export declare function App({ className }: {
|
|
4
22
|
className?: string;
|
|
5
23
|
}): preact.JSX.Element;
|
package/dist/_components/app.js
CHANGED
|
@@ -9,7 +9,25 @@ function AnsiLogo() {
|
|
|
9
9
|
children: "▄▀█ ▄▀█ █\n█▀█ █▀█ █"
|
|
10
10
|
});
|
|
11
11
|
}
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* The default top-level UI component for an AAI voice agent.
|
|
14
|
+
* Renders a {@link StartScreen} (with the AAI logo or a custom title from
|
|
15
|
+
* {@link useMountConfig}) followed by a {@link ChatView} once the session starts.
|
|
16
|
+
*
|
|
17
|
+
* This is the component rendered by {@link mount} when no custom component is
|
|
18
|
+
* provided.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* import { App, mount } from "@aai/ui";
|
|
23
|
+
*
|
|
24
|
+
* mount(App, { target: "#app", title: "My Agent" });
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @param className - Additional CSS class names applied to the root element.
|
|
28
|
+
*
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
13
31
|
function App({ className }) {
|
|
14
32
|
const { title } = useMountConfig();
|
|
15
33
|
return /* @__PURE__ */ jsx(StartScreen, {
|
|
@@ -1,11 +1,50 @@
|
|
|
1
1
|
import type * as preact from "preact";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Visual style of a {@link Button}.
|
|
4
|
+
*
|
|
5
|
+
* - `"default"` — Primary filled button (accent background).
|
|
6
|
+
* - `"secondary"` — Muted surface background with border.
|
|
7
|
+
* - `"ghost"` — Transparent background with border.
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export type ButtonVariant = "default" | "secondary" | "ghost";
|
|
12
|
+
/**
|
|
13
|
+
* Size preset for a {@link Button}.
|
|
14
|
+
*
|
|
15
|
+
* - `"default"` — Compact (height 2rem / 32 px).
|
|
16
|
+
* - `"lg"` — Large with generous padding, suitable for primary CTAs.
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export type ButtonSize = "default" | "lg";
|
|
21
|
+
/**
|
|
22
|
+
* A styled button with variant and size presets.
|
|
23
|
+
*
|
|
24
|
+
* Accepts all standard `<button>` HTML attributes in addition to the props
|
|
25
|
+
* listed below.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* <Button variant="secondary" onClick={handleClick}>
|
|
30
|
+
* Stop
|
|
31
|
+
* </Button>
|
|
32
|
+
*
|
|
33
|
+
* <Button size="lg" className="w-full">
|
|
34
|
+
* Start Conversation
|
|
35
|
+
* </Button>
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @param variant - Visual style (`"default"` | `"secondary"` | `"ghost"`). Defaults to `"default"`.
|
|
39
|
+
* @param size - Size preset (`"default"` | `"lg"`). Defaults to `"default"`.
|
|
40
|
+
* @param className - Additional CSS class names.
|
|
41
|
+
* @param children - Button label / content.
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
5
45
|
export declare function Button({ variant, size, className, children, ...rest }: {
|
|
6
46
|
variant?: ButtonVariant;
|
|
7
47
|
size?: ButtonSize;
|
|
8
48
|
className?: string;
|
|
9
49
|
children?: preact.ComponentChildren;
|
|
10
50
|
} & Omit<preact.JSX.HTMLAttributes<HTMLButtonElement>, "className">): preact.JSX.Element;
|
|
11
|
-
export {};
|
|
@@ -1,18 +1,42 @@
|
|
|
1
1
|
import clsx from "clsx";
|
|
2
2
|
import { jsx } from "preact/jsx-runtime";
|
|
3
3
|
//#region _components/button.tsx
|
|
4
|
-
|
|
4
|
+
const LG_STYLE = {
|
|
5
|
+
display: "grid",
|
|
6
|
+
placeItems: "center",
|
|
7
|
+
appearance: "none",
|
|
8
|
+
margin: 0,
|
|
9
|
+
padding: "12px 32px",
|
|
10
|
+
lineHeight: 1
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* A styled button with variant and size presets.
|
|
14
|
+
*
|
|
15
|
+
* Accepts all standard `<button>` HTML attributes in addition to the props
|
|
16
|
+
* listed below.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* <Button variant="secondary" onClick={handleClick}>
|
|
21
|
+
* Stop
|
|
22
|
+
* </Button>
|
|
23
|
+
*
|
|
24
|
+
* <Button size="lg" className="w-full">
|
|
25
|
+
* Start Conversation
|
|
26
|
+
* </Button>
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @param variant - Visual style (`"default"` | `"secondary"` | `"ghost"`). Defaults to `"default"`.
|
|
30
|
+
* @param size - Size preset (`"default"` | `"lg"`). Defaults to `"default"`.
|
|
31
|
+
* @param className - Additional CSS class names.
|
|
32
|
+
* @param children - Button label / content.
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
5
36
|
function Button({ variant = "default", size = "default", className, children, ...rest }) {
|
|
6
37
|
return /* @__PURE__ */ jsx("button", {
|
|
7
38
|
type: "button",
|
|
8
|
-
style: size === "lg" ?
|
|
9
|
-
display: "grid",
|
|
10
|
-
placeItems: "center",
|
|
11
|
-
appearance: "none",
|
|
12
|
-
margin: 0,
|
|
13
|
-
padding: "12px 32px",
|
|
14
|
-
lineHeight: 1
|
|
15
|
-
} : void 0,
|
|
39
|
+
style: size === "lg" ? LG_STYLE : void 0,
|
|
16
40
|
class: clsx(size !== "lg" && "flex items-center justify-center appearance-none m-0 h-8 px-3 py-1.5 w-fit leading-none", "rounded-aai text-sm font-medium cursor-pointer border outline-none", variant === "secondary" && "bg-aai-surface-hover text-aai-text-secondary border-aai-border", variant === "ghost" && "bg-transparent text-aai-text-secondary border-aai-border", variant === "default" && "bg-aai-primary text-white border-transparent", className),
|
|
17
41
|
...rest,
|
|
18
42
|
children
|
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
import type * as preact from "preact";
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* The main chat interface for a voice agent session.
|
|
4
|
+
* Displays a header (with title and {@link StateIndicator}), an
|
|
5
|
+
* {@link ErrorBanner}, the {@link MessageList}, and session {@link Controls}.
|
|
6
|
+
*
|
|
7
|
+
* Must be rendered inside a {@link SessionProvider}.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <StartScreen icon="🍕" title="Pizza Palace">
|
|
12
|
+
* <ChatView />
|
|
13
|
+
* </StartScreen>
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* @example Pair with a sidebar
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <SidebarLayout sidebar={<RecipeCard />}>
|
|
19
|
+
* <ChatView className="border-l" />
|
|
20
|
+
* </SidebarLayout>
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @param className - Additional CSS class names applied to the root element.
|
|
24
|
+
*
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
3
27
|
export declare function ChatView({ className }: {
|
|
4
28
|
className?: string;
|
|
5
29
|
}): preact.JSX.Element;
|
|
@@ -7,7 +7,31 @@ import { StateIndicator } from "./state-indicator.js";
|
|
|
7
7
|
import clsx from "clsx";
|
|
8
8
|
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
9
9
|
//#region _components/chat-view.tsx
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* The main chat interface for a voice agent session.
|
|
12
|
+
* Displays a header (with title and {@link StateIndicator}), an
|
|
13
|
+
* {@link ErrorBanner}, the {@link MessageList}, and session {@link Controls}.
|
|
14
|
+
*
|
|
15
|
+
* Must be rendered inside a {@link SessionProvider}.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* <StartScreen icon="🍕" title="Pizza Palace">
|
|
20
|
+
* <ChatView />
|
|
21
|
+
* </StartScreen>
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example Pair with a sidebar
|
|
25
|
+
* ```tsx
|
|
26
|
+
* <SidebarLayout sidebar={<RecipeCard />}>
|
|
27
|
+
* <ChatView className="border-l" />
|
|
28
|
+
* </SidebarLayout>
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @param className - Additional CSS class names applied to the root element.
|
|
32
|
+
*
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
11
35
|
function ChatView({ className }) {
|
|
12
36
|
const { session } = useSession();
|
|
13
37
|
const { title } = useMountConfig();
|
|
@@ -1,4 +1,18 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Session control buttons: **Stop / Resume** and **New Conversation**.
|
|
3
|
+
*
|
|
4
|
+
* Reads session state from {@link useSession}. Must be rendered inside a
|
|
5
|
+
* {@link SessionProvider}.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <Controls className="justify-end" />
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* @param className - Additional CSS class names applied to the container.
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
2
16
|
export declare function Controls({ className }: {
|
|
3
17
|
className?: string;
|
|
4
18
|
}): import("preact").JSX.Element;
|
|
@@ -3,7 +3,21 @@ import { Button } from "./button.js";
|
|
|
3
3
|
import clsx from "clsx";
|
|
4
4
|
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
5
5
|
//#region _components/controls.tsx
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Session control buttons: **Stop / Resume** and **New Conversation**.
|
|
8
|
+
*
|
|
9
|
+
* Reads session state from {@link useSession}. Must be rendered inside a
|
|
10
|
+
* {@link SessionProvider}.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <Controls className="justify-end" />
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @param className - Additional CSS class names applied to the container.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
7
21
|
function Controls({ className }) {
|
|
8
22
|
const { running, toggle, reset } = useSession();
|
|
9
23
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import type * as preact from "preact";
|
|
2
2
|
import type { Reactive, SessionError } from "../types.ts";
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Displays a session error as a styled inline banner.
|
|
5
|
+
* Returns `null` when there is no active error.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* const { session } = useSession();
|
|
10
|
+
* <ErrorBanner error={session.error} />
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* @param error - A reactive {@link SessionError} (or `null`).
|
|
14
|
+
* @param className - Additional CSS class names.
|
|
15
|
+
*
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
4
18
|
export declare function ErrorBanner({ error, className, }: {
|
|
5
19
|
error: Reactive<SessionError | null>;
|
|
6
20
|
className?: string;
|
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
import clsx from "clsx";
|
|
2
2
|
import { jsx } from "preact/jsx-runtime";
|
|
3
3
|
//#region _components/error-banner.tsx
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Displays a session error as a styled inline banner.
|
|
6
|
+
* Returns `null` when there is no active error.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* const { session } = useSession();
|
|
11
|
+
* <ErrorBanner error={session.error} />
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* @param error - A reactive {@link SessionError} (or `null`).
|
|
15
|
+
* @param className - Additional CSS class names.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
5
19
|
function ErrorBanner({ error, className }) {
|
|
6
20
|
if (!error.value) return null;
|
|
7
21
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import type * as preact from "preact";
|
|
2
|
-
import type {
|
|
3
|
-
/**
|
|
2
|
+
import type { ChatMessage } from "../types.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Renders a single chat message as a styled bubble.
|
|
5
|
+
*
|
|
6
|
+
* - **User** messages appear right-aligned with a faint surface background.
|
|
7
|
+
* - **Assistant** messages appear left-aligned as plain text.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <MessageBubble message={{ role: "user", content: "Hello!" }} />
|
|
12
|
+
* <MessageBubble message={{ role: "assistant", content: "Hi there!" }} />
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @param message - The chat message to display (see {@link ChatMessage}).
|
|
16
|
+
* @param className - Additional CSS class names applied to the root element.
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
4
20
|
export declare function MessageBubble({ message, className, }: {
|
|
5
|
-
message:
|
|
21
|
+
message: ChatMessage;
|
|
6
22
|
className?: string;
|
|
7
23
|
}): preact.JSX.Element;
|
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import clsx from "clsx";
|
|
2
2
|
import { jsx } from "preact/jsx-runtime";
|
|
3
3
|
//#region _components/message-bubble.tsx
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Renders a single chat message as a styled bubble.
|
|
6
|
+
*
|
|
7
|
+
* - **User** messages appear right-aligned with a faint surface background.
|
|
8
|
+
* - **Assistant** messages appear left-aligned as plain text.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <MessageBubble message={{ role: "user", content: "Hello!" }} />
|
|
13
|
+
* <MessageBubble message={{ role: "assistant", content: "Hi there!" }} />
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* @param message - The chat message to display (see {@link ChatMessage}).
|
|
17
|
+
* @param className - Additional CSS class names applied to the root element.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
5
21
|
function MessageBubble({ message, className }) {
|
|
6
22
|
if (message.role === "user") return /* @__PURE__ */ jsx("div", {
|
|
7
23
|
class: clsx("flex flex-col w-full items-end", className),
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Scrollable list of all chat messages, tool-call blocks, live transcript,
|
|
3
|
+
* streaming agent utterance, and a thinking indicator.
|
|
4
|
+
*
|
|
5
|
+
* Messages and tool calls are interleaved in the correct order. The list
|
|
6
|
+
* auto-scrolls to the latest content via {@link useAutoScroll}.
|
|
7
|
+
*
|
|
8
|
+
* Must be rendered inside a {@link SessionProvider}.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <MessageList className="flex-1" />
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @param className - Additional CSS class names applied to the scroll container.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
2
19
|
export declare function MessageList({ className }: {
|
|
3
20
|
className?: string;
|
|
4
21
|
}): import("preact").JSX.Element;
|
|
@@ -4,14 +4,31 @@ import { ThinkingIndicator } from "./thinking-indicator.js";
|
|
|
4
4
|
import { ToolCallBlock } from "./tool-call-block.js";
|
|
5
5
|
import { Transcript } from "./transcript.js";
|
|
6
6
|
import clsx from "clsx";
|
|
7
|
-
import {
|
|
7
|
+
import { useComputed } from "@preact/signals";
|
|
8
8
|
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
9
9
|
//#region _components/message-list.tsx
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Scrollable list of all chat messages, tool-call blocks, live transcript,
|
|
12
|
+
* streaming agent utterance, and a thinking indicator.
|
|
13
|
+
*
|
|
14
|
+
* Messages and tool calls are interleaved in the correct order. The list
|
|
15
|
+
* auto-scrolls to the latest content via {@link useAutoScroll}.
|
|
16
|
+
*
|
|
17
|
+
* Must be rendered inside a {@link SessionProvider}.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <MessageList className="flex-1" />
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @param className - Additional CSS class names applied to the scroll container.
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
11
28
|
function MessageList({ className }) {
|
|
12
29
|
const { session } = useSession();
|
|
13
30
|
const scrollRef = useAutoScroll();
|
|
14
|
-
const showThinking =
|
|
31
|
+
const showThinking = useComputed(() => {
|
|
15
32
|
if (session.state.value !== "thinking") return false;
|
|
16
33
|
const last = session.toolCalls.value.at(-1);
|
|
17
34
|
if (last?.status === "pending") return false;
|
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
import type * as preact from "preact";
|
|
2
2
|
import type { AgentState, Reactive } from "../types.ts";
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Colored dot + label showing the current {@link AgentState}.
|
|
5
|
+
*
|
|
6
|
+
* State-to-color mapping:
|
|
7
|
+
* - `disconnected` — gray
|
|
8
|
+
* - `connecting` — yellow
|
|
9
|
+
* - `ready` — green
|
|
10
|
+
* - `listening` — blue
|
|
11
|
+
* - `thinking` — purple
|
|
12
|
+
* - `speaking` — red
|
|
13
|
+
* - `error` — red
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* const { session } = useSession();
|
|
18
|
+
* <StateIndicator state={session.state} />
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @param state - A reactive {@link AgentState} value.
|
|
22
|
+
* @param className - Additional CSS class names.
|
|
23
|
+
*
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
4
26
|
export declare function StateIndicator({ state, className, }: {
|
|
5
27
|
state: Reactive<AgentState>;
|
|
6
28
|
className?: string;
|
|
@@ -1,7 +1,29 @@
|
|
|
1
1
|
import clsx from "clsx";
|
|
2
2
|
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
3
3
|
//#region _components/state-indicator.tsx
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Colored dot + label showing the current {@link AgentState}.
|
|
6
|
+
*
|
|
7
|
+
* State-to-color mapping:
|
|
8
|
+
* - `disconnected` — gray
|
|
9
|
+
* - `connecting` — yellow
|
|
10
|
+
* - `ready` — green
|
|
11
|
+
* - `listening` — blue
|
|
12
|
+
* - `thinking` — purple
|
|
13
|
+
* - `speaking` — red
|
|
14
|
+
* - `error` — red
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const { session } = useSession();
|
|
19
|
+
* <StateIndicator state={session.state} />
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @param state - A reactive {@link AgentState} value.
|
|
23
|
+
* @param className - Additional CSS class names.
|
|
24
|
+
*
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
5
27
|
function StateIndicator({ state, className }) {
|
|
6
28
|
return /* @__PURE__ */ jsxs("div", {
|
|
7
29
|
class: clsx("inline-flex items-center justify-center gap-1.5 text-[13px] font-medium leading-[130%] text-aai-text-muted capitalize", className),
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import type * as preact from "preact";
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Animated three-dot "thinking" indicator shown while the agent is processing.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```tsx
|
|
7
|
+
* {isThinking && <ThinkingIndicator />}
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* @param className - Additional CSS class names.
|
|
11
|
+
*
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
3
14
|
export declare function ThinkingIndicator({ className }: {
|
|
4
15
|
className?: string;
|
|
5
16
|
}): preact.JSX.Element;
|
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
import clsx from "clsx";
|
|
2
2
|
import { jsx } from "preact/jsx-runtime";
|
|
3
3
|
//#region _components/thinking-indicator.tsx
|
|
4
|
-
|
|
4
|
+
const DOT_STYLES = [
|
|
5
|
+
0,
|
|
6
|
+
.16,
|
|
7
|
+
.32
|
|
8
|
+
].map((delay) => ({
|
|
9
|
+
animation: "aai-bounce 1.4s infinite ease-in-out both",
|
|
10
|
+
animationDelay: `${delay}s`
|
|
11
|
+
}));
|
|
12
|
+
/**
|
|
13
|
+
* Animated three-dot "thinking" indicator shown while the agent is processing.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* {isThinking && <ThinkingIndicator />}
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @param className - Additional CSS class names.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
5
24
|
function ThinkingIndicator({ className }) {
|
|
6
25
|
return /* @__PURE__ */ jsx("div", {
|
|
7
26
|
class: clsx("flex items-center gap-2 text-aai-text-dim text-sm font-medium min-h-5", className),
|
|
8
|
-
children:
|
|
9
|
-
0,
|
|
10
|
-
.16,
|
|
11
|
-
.32
|
|
12
|
-
].map((delay) => /* @__PURE__ */ jsx("div", {
|
|
27
|
+
children: DOT_STYLES.map((style, i) => /* @__PURE__ */ jsx("div", {
|
|
13
28
|
class: "w-1.5 h-1.5 rounded-full bg-aai-text-dim",
|
|
14
|
-
style
|
|
15
|
-
|
|
16
|
-
animationDelay: `${delay}s`
|
|
17
|
-
}
|
|
18
|
-
}, delay))
|
|
29
|
+
style
|
|
30
|
+
}, i))
|
|
19
31
|
});
|
|
20
32
|
}
|
|
21
33
|
//#endregion
|
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
import type * as preact from "preact";
|
|
2
2
|
import type { ToolCallInfo } from "../types.ts";
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Renders a tool invocation with an icon, title, subtitle, and a
|
|
5
|
+
* collapsible result viewer.
|
|
6
|
+
*
|
|
7
|
+
* Built-in tool types (`web_search`, `visit_webpage`, `run_code`,
|
|
8
|
+
* `fetch_json`, `user_input`) get custom icons and labels. Unknown tools
|
|
9
|
+
* fall back to a generic bolt icon.
|
|
10
|
+
*
|
|
11
|
+
* While the tool call is pending a shimmer animation is shown. Once
|
|
12
|
+
* complete, clicking the block expands the formatted JSON result.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* <ToolCallBlock toolCall={toolCall} />
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @param toolCall - The tool call to render (see {@link ToolCallInfo}).
|
|
20
|
+
* @param className - Additional CSS class names.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
4
24
|
export declare function ToolCallBlock({ toolCall, className, }: {
|
|
5
25
|
toolCall: ToolCallInfo;
|
|
6
26
|
className?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BoltIcon, ChatBubbleIcon, DownloadIcon, ExternalLinkIcon, SearchIcon, TerminalIcon } from "./tool-icons.js";
|
|
2
|
-
import { useMemo, useState } from "preact/hooks";
|
|
3
2
|
import clsx from "clsx";
|
|
3
|
+
import { useComputed, useSignal } from "@preact/signals";
|
|
4
4
|
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
5
5
|
//#region _components/tool-call-block.tsx
|
|
6
6
|
const argField = (key) => (args) => String(args[key] ?? "");
|
|
@@ -49,22 +49,44 @@ function formatResult(result) {
|
|
|
49
49
|
return result;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
-
/**
|
|
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
|
+
*/
|
|
53
73
|
function ToolCallBlock({ toolCall, className }) {
|
|
54
|
-
const
|
|
74
|
+
const isOpen = useSignal(false);
|
|
55
75
|
const config = TOOL_CONFIG[toolCall.toolName] ?? DEFAULT_CONFIG;
|
|
56
76
|
const isPending = toolCall.status === "pending";
|
|
57
77
|
const title = config.title || toolCall.toolName;
|
|
58
|
-
const canExpand = !isPending &&
|
|
59
|
-
const formatted =
|
|
78
|
+
const canExpand = !isPending && Boolean(toolCall.result);
|
|
79
|
+
const formatted = useComputed(() => toolCall.result ? formatResult(toolCall.result) : "");
|
|
60
80
|
return /* @__PURE__ */ jsxs("div", {
|
|
61
81
|
class: clsx("flex flex-col", className),
|
|
62
82
|
children: [/* @__PURE__ */ jsxs("button", {
|
|
63
83
|
type: "button",
|
|
64
|
-
"aria-expanded": canExpand ? isOpen : void 0,
|
|
84
|
+
"aria-expanded": canExpand ? isOpen.value : void 0,
|
|
65
85
|
disabled: isPending,
|
|
66
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"),
|
|
67
|
-
onClick: () =>
|
|
87
|
+
onClick: () => {
|
|
88
|
+
if (canExpand) isOpen.value = !isOpen.value;
|
|
89
|
+
},
|
|
68
90
|
children: [
|
|
69
91
|
/* @__PURE__ */ jsx(config.Icon, { class: "w-4 h-4 text-aai-text-dim shrink-0" }),
|
|
70
92
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -77,17 +99,17 @@ function ToolCallBlock({ toolCall, className }) {
|
|
|
77
99
|
}),
|
|
78
100
|
canExpand && /* @__PURE__ */ jsx("span", {
|
|
79
101
|
class: "text-xs text-aai-text-dim shrink-0",
|
|
80
|
-
children: isOpen ? "▾" : "▸"
|
|
102
|
+
children: isOpen.value ? "▾" : "▸"
|
|
81
103
|
})
|
|
82
104
|
]
|
|
83
|
-
}), isOpen && /* @__PURE__ */ jsxs("div", {
|
|
105
|
+
}), isOpen.value && /* @__PURE__ */ jsxs("div", {
|
|
84
106
|
class: "border-x border-b border-aai-border rounded-b-aai bg-aai-surface max-h-64 overflow-auto",
|
|
85
107
|
children: [toolCall.toolName === "run_code" && toolCall.args.code && /* @__PURE__ */ jsx("pre", {
|
|
86
108
|
class: "text-xs text-aai-text p-2 whitespace-pre-wrap border-b border-aai-border font-mono",
|
|
87
109
|
children: String(toolCall.args.code)
|
|
88
|
-
}), formatted && /* @__PURE__ */ jsx("pre", {
|
|
110
|
+
}), formatted.value && /* @__PURE__ */ jsx("pre", {
|
|
89
111
|
class: "text-xs text-aai-text-dim p-2 whitespace-pre-wrap",
|
|
90
|
-
children: formatted
|
|
112
|
+
children: formatted.value
|
|
91
113
|
})]
|
|
92
114
|
})]
|
|
93
115
|
});
|