@alexkroman1/aai-ui 0.12.3 → 0.13.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.
Files changed (201) hide show
  1. package/README.md +257 -0
  2. package/dist/_colors-CpZO-88A.js +78 -0
  3. package/dist/_module-url-C13kAJ87.js +15 -0
  4. package/dist/_page-shell.d.ts +11 -0
  5. package/dist/_recover-run.d.ts +79 -0
  6. package/dist/_repeat-until.d.ts +30 -0
  7. package/dist/_run-controls.d.ts +33 -0
  8. package/dist/_submission-state.d.ts +92 -0
  9. package/dist/_tap-to-talk-state.d.ts +88 -0
  10. package/dist/_utils-Mi-SCFA1.js +47 -0
  11. package/dist/_utils.d.ts +26 -0
  12. package/dist/_web-storage.d.ts +43 -0
  13. package/dist/_workflow-api-ref.d.ts +37 -0
  14. package/dist/_workflow-files.d.ts +34 -0
  15. package/dist/_workflow-test-defs.d.ts +38 -0
  16. package/dist/aai-logo-D8pMVn9_.js +85 -0
  17. package/dist/agent-state-labels.d.ts +65 -0
  18. package/dist/agent-state.d.ts +108 -0
  19. package/dist/audio/capture.d.ts +44 -0
  20. package/dist/audio/index.d.ts +18 -0
  21. package/dist/audio/index.js +431 -0
  22. package/dist/audio/preconnect.d.ts +87 -0
  23. package/dist/audio/voice-io.d.ts +112 -0
  24. package/dist/build-default-client.d.ts +1 -0
  25. package/dist/chat-view-BCbI7gD4.js +396 -0
  26. package/dist/client-config-C7fQrioM.js +139 -0
  27. package/dist/client-config.d.ts +119 -0
  28. package/dist/client-dir.d.ts +44 -0
  29. package/dist/client-dir.js +58 -0
  30. package/dist/client-identity.d.ts +131 -0
  31. package/dist/client-tool.d.ts +51 -0
  32. package/dist/components/_colors.d.ts +73 -0
  33. package/dist/components/_form-readiness.d.ts +56 -0
  34. package/dist/components/_form-values.d.ts +19 -0
  35. package/dist/components/aai-logo.d.ts +12 -0
  36. package/dist/components/audio-result.d.ts +94 -0
  37. package/dist/components/auto-scroll.d.ts +74 -0
  38. package/dist/components/bullet-list.d.ts +74 -0
  39. package/dist/components/button.d.ts +29 -21
  40. package/dist/components/button.js +62 -23
  41. package/dist/components/chat-view.d.ts +24 -18
  42. package/dist/components/chat-view.js +2 -60
  43. package/dist/components/console-shell.d.ts +85 -0
  44. package/dist/components/controls.d.ts +21 -6
  45. package/dist/components/controls.js +31 -19
  46. package/dist/components/conversation-view.d.ts +130 -0
  47. package/dist/components/eyebrow.d.ts +12 -0
  48. package/dist/components/facts.d.ts +81 -0
  49. package/dist/components/form-fields.d.ts +142 -0
  50. package/dist/components/form-types.d.ts +73 -0
  51. package/dist/components/form.d.ts +96 -0
  52. package/dist/components/markdown.d.ts +57 -0
  53. package/dist/components/message-list.d.ts +34 -7
  54. package/dist/components/message-list.js +2 -75
  55. package/dist/components/session-controls.d.ts +125 -0
  56. package/dist/components/session-error-banner.d.ts +69 -0
  57. package/dist/components/session-state-dot.d.ts +111 -0
  58. package/dist/components/sidebar-layout.d.ts +31 -10
  59. package/dist/components/sidebar-layout.js +32 -12
  60. package/dist/components/start-screen.d.ts +17 -6
  61. package/dist/components/start-screen.js +34 -14
  62. package/dist/components/tool-call-block.d.ts +15 -14
  63. package/dist/components/tool-call-block.js +2 -117
  64. package/dist/components/tool-call-row.d.ts +75 -0
  65. package/dist/components/tool-config-context.d.ts +22 -0
  66. package/dist/components/upload-progress.d.ts +76 -0
  67. package/dist/components/url-chips.d.ts +29 -0
  68. package/dist/components/workflow-fields.d.ts +46 -0
  69. package/dist/components/workflow-pending-note.d.ts +81 -0
  70. package/dist/components/workflow-progress.d.ts +81 -0
  71. package/dist/components/workflow-run-error.d.ts +48 -0
  72. package/dist/components/workflow-run-panel.d.ts +79 -0
  73. package/dist/context.d.ts +288 -0
  74. package/dist/context.js +382 -0
  75. package/dist/conversation-log.d.ts +88 -0
  76. package/dist/default-client/assets/_module-url-BX0RuRU2.js +1 -0
  77. package/dist/default-client/assets/audio-cGFGID-2.js +1 -0
  78. package/dist/default-client/assets/capture-processor-BUABoo3_.js +90 -0
  79. package/dist/default-client/assets/index-8ihb1Urm.css +2 -0
  80. package/dist/default-client/assets/index-BQURVARl.js +126 -0
  81. package/dist/default-client/assets/playback-processor-ABOa11j0.js +314 -0
  82. package/dist/default-client/favicon.ico +0 -0
  83. package/dist/default-client/index.html +15 -0
  84. package/dist/default-client.d.ts +23 -0
  85. package/dist/define-client.d.ts +162 -26
  86. package/dist/define-client.js +201 -55
  87. package/dist/eyebrow-UfmSz9yy.js +27 -0
  88. package/dist/hooks-DN4gHYsj.js +182 -0
  89. package/dist/hooks.d.ts +172 -0
  90. package/dist/hooks.js +3 -0
  91. package/dist/hooks.test-d.d.ts +14 -0
  92. package/dist/inbox-protocol.d.ts +128 -0
  93. package/dist/inbox.d.ts +132 -0
  94. package/dist/index.d.ts +126 -29
  95. package/dist/index.js +5500 -15
  96. package/dist/internal.d.ts +43 -0
  97. package/dist/internal.js +8 -0
  98. package/dist/linked-client.d.ts +70 -0
  99. package/dist/message-list-DHZcLhRA.js +682 -0
  100. package/dist/notice-player.d.ts +70 -0
  101. package/dist/page.d.ts +114 -0
  102. package/dist/phone.d.ts +50 -0
  103. package/dist/route-fetch.d.ts +79 -0
  104. package/dist/session/audio-effects.d.ts +31 -0
  105. package/dist/session/audio-setup.d.ts +57 -0
  106. package/dist/session/audio-state.d.ts +157 -0
  107. package/dist/session/browser-session.d.ts +30 -0
  108. package/dist/session/close.d.ts +26 -0
  109. package/dist/session/dial.d.ts +65 -0
  110. package/dist/session/handshake.d.ts +60 -0
  111. package/dist/session/index.d.ts +17 -0
  112. package/dist/session/index.js +2 -0
  113. package/dist/session/messages.d.ts +63 -0
  114. package/dist/session/mic.d.ts +64 -0
  115. package/dist/session/preconnect.d.ts +48 -0
  116. package/dist/session/reconnect.d.ts +25 -0
  117. package/dist/session/resume-store.d.ts +57 -0
  118. package/dist/session/state.d.ts +146 -0
  119. package/dist/session/ticket.d.ts +44 -0
  120. package/dist/session/types.d.ts +476 -0
  121. package/dist/session/url.d.ts +17 -0
  122. package/dist/session/user-turn.d.ts +55 -0
  123. package/dist/session-CE0Ipsb3.js +2129 -0
  124. package/dist/stored-value.d.ts +103 -0
  125. package/dist/tool-call-block-uXtMOUWN.js +204 -0
  126. package/dist/tool-config-context-Es4YUzV2.js +19 -0
  127. package/dist/types.d.ts +272 -34
  128. package/dist/types.js +35 -4
  129. package/dist/upload/files.d.ts +83 -0
  130. package/dist/upload/index.d.ts +15 -0
  131. package/dist/upload/pause.d.ts +31 -0
  132. package/dist/upload/recall.d.ts +67 -0
  133. package/dist/upload/report.d.ts +26 -0
  134. package/dist/upload/session.d.ts +99 -0
  135. package/dist/url-chips-oyy_Eiqh.js +239 -0
  136. package/dist/use-client-runs.d.ts +87 -0
  137. package/dist/use-conversation-log.d.ts +86 -0
  138. package/dist/use-conversation.d.ts +131 -0
  139. package/dist/use-copy.d.ts +74 -0
  140. package/dist/use-download-url.d.ts +84 -0
  141. package/dist/use-flash.d.ts +61 -0
  142. package/dist/use-inbox.d.ts +101 -0
  143. package/dist/use-push-to-talk.d.ts +105 -0
  144. package/dist/use-route-mutation.d.ts +113 -0
  145. package/dist/use-route.d.ts +82 -0
  146. package/dist/use-run-key.d.ts +133 -0
  147. package/dist/use-session-controls.d.ts +69 -0
  148. package/dist/use-session-id.d.ts +57 -0
  149. package/dist/use-tap-to-talk.d.ts +138 -0
  150. package/dist/use-user-transcript-uyHhzy4d.js +73 -0
  151. package/dist/use-user-transcript.d.ts +75 -0
  152. package/dist/use-workflow-form.d.ts +285 -0
  153. package/dist/use-workflow-progress.d.ts +137 -0
  154. package/dist/use-workflow-run-DdhWmbx-.js +697 -0
  155. package/dist/use-workflow-run.d.ts +100 -0
  156. package/dist/use-workflow-runs.d.ts +71 -0
  157. package/dist/use-workflow-stream.d.ts +154 -0
  158. package/dist/use-workflows.d.ts +77 -0
  159. package/dist/workflow-client.d.ts +136 -0
  160. package/dist/workflow-def-types.d.ts +31 -0
  161. package/dist/workflow-events.d.ts +39 -0
  162. package/dist/workflow-field-kind.d.ts +95 -0
  163. package/dist/workflow-status-labels.d.ts +35 -0
  164. package/dist/worklets/_module-url.d.ts +10 -0
  165. package/dist/worklets/_playback-bench-harness.d.ts +181 -0
  166. package/dist/worklets/_playback-bench-host.d.ts +63 -0
  167. package/dist/worklets/_playback-bench-page.d.ts +65 -0
  168. package/dist/worklets/_tts-trace-harness.d.ts +142 -0
  169. package/dist/worklets/_worklet-test-utils.d.ts +27 -0
  170. package/dist/worklets/capture-processor.d.ts +4 -2
  171. package/dist/worklets/capture-processor.js +73 -33
  172. package/dist/worklets/playback-processor.d.ts +4 -2
  173. package/dist/worklets/playback-processor.js +258 -42
  174. package/package.json +57 -32
  175. package/styles.css +152 -30
  176. package/dist/audio.d.ts +0 -45
  177. package/dist/audio.js +0 -121
  178. package/dist/client-context.d.ts +0 -33
  179. package/dist/client-context.js +0 -15
  180. package/dist/client-handler.d.ts +0 -43
  181. package/dist/components/app.d.ts +0 -23
  182. package/dist/components/app.js +0 -41
  183. package/dist/components/error-banner.d.ts +0 -21
  184. package/dist/components/error-banner.js +0 -27
  185. package/dist/components/message-bubble.d.ts +0 -23
  186. package/dist/components/message-bubble.js +0 -35
  187. package/dist/components/state-indicator.d.ts +0 -29
  188. package/dist/components/state-indicator.js +0 -37
  189. package/dist/components/thinking-indicator.d.ts +0 -16
  190. package/dist/components/thinking-indicator.js +0 -34
  191. package/dist/components/tool-icons.d.ts +0 -17
  192. package/dist/components/tool-icons.js +0 -128
  193. package/dist/components/transcript.d.ts +0 -25
  194. package/dist/components/transcript.js +0 -35
  195. package/dist/session-CWB7vmqz.js +0 -429
  196. package/dist/session.d.ts +0 -69
  197. package/dist/session.js +0 -2
  198. package/dist/signals.d.ts +0 -120
  199. package/dist/signals.js +0 -161
  200. package/dist/tsdown.config.d.ts +0 -2
  201. package/dist/types.test-d.d.ts +0 -7
@@ -1,76 +1,3 @@
1
- import { useAutoScroll, useSession } from "../signals.js";
2
- import { MessageBubble } from "./message-bubble.js";
3
- import { ThinkingIndicator } from "./thinking-indicator.js";
4
- import { ToolCallBlock } from "./tool-call-block.js";
5
- import { Transcript } from "./transcript.js";
6
- import clsx from "clsx";
7
- import { useComputed } from "@preact/signals";
8
- import { jsx, jsxs } from "preact/jsx-runtime";
9
- //#region components/message-list.tsx
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
- */
28
- function MessageList({ className }) {
29
- const { session } = useSession();
30
- const scrollRef = useAutoScroll();
31
- const showThinking = useComputed(() => {
32
- if (session.state.value !== "thinking") return false;
33
- const last = session.toolCalls.value.at(-1);
34
- if (last?.status === "pending") return false;
35
- const lastMsg = session.messages.value.at(-1);
36
- return !lastMsg || lastMsg.role === "user" || Boolean(last);
37
- });
38
- const messages = session.messages.value;
39
- const toolCalls = session.toolCalls.value;
40
- const items = [];
41
- let tci = 0;
42
- for (const [i, msg] of messages.entries()) {
43
- items.push(/* @__PURE__ */ jsx(MessageBubble, { message: msg }, `msg-${i}`));
44
- let tc = toolCalls[tci];
45
- while (tc && tc.afterMessageIndex <= i) {
46
- items.push(/* @__PURE__ */ jsx(ToolCallBlock, { toolCall: tc }, tc.toolCallId));
47
- tci++;
48
- tc = toolCalls[tci];
49
- }
50
- }
51
- let tc = toolCalls[tci];
52
- while (tc) {
53
- items.push(/* @__PURE__ */ jsx(ToolCallBlock, { toolCall: tc }, tc.toolCallId));
54
- tci++;
55
- tc = toolCalls[tci];
56
- }
57
- return /* @__PURE__ */ jsx("div", {
58
- role: "log",
59
- class: clsx("flex-1 overflow-y-auto [scrollbar-width:none] bg-aai-surface", className),
60
- children: /* @__PURE__ */ jsxs("div", {
61
- class: "flex flex-col gap-4.5 p-4",
62
- children: [
63
- items,
64
- session.agentUtterance.value && /* @__PURE__ */ jsx(MessageBubble, { message: {
65
- role: "assistant",
66
- content: session.agentUtterance.value
67
- } }),
68
- /* @__PURE__ */ jsx(Transcript, { userUtterance: session.userUtterance }),
69
- showThinking.value && /* @__PURE__ */ jsx(ThinkingIndicator, {}),
70
- /* @__PURE__ */ jsx("div", { ref: scrollRef })
71
- ]
72
- })
73
- });
74
- }
75
- //#endregion
1
+ import "../context.js";
2
+ import { t as MessageList } from "../message-list-DHZcLhRA.js";
76
3
  export { MessageList };
@@ -0,0 +1,125 @@
1
+ import { type ReactNode } from "react";
2
+ /**
3
+ * Which of the four buttons a {@link SessionControlButton} is.
4
+ *
5
+ * @public
6
+ */
7
+ export type SessionControlAction = "start" | "toggle" | "restart" | "end";
8
+ /**
9
+ * One button of {@link SessionControls}, as handed to `renderButton`.
10
+ *
11
+ * @public
12
+ */
13
+ export type SessionControlButton = {
14
+ /** Which button this is. A custom renderer switches on it for its look. */
15
+ action: SessionControlAction;
16
+ /** The label to show — the caller's own word, or the default. */
17
+ label: string;
18
+ /** The handler. Already bound; wire it to `onClick` as it is. */
19
+ onClick: () => void;
20
+ /**
21
+ * Whether the call is live. Meaningful on `toggle`, whose label already says
22
+ * which way it will flip, and handed to every button so a renderer can dim
23
+ * the others while paused.
24
+ */
25
+ running: boolean;
26
+ };
27
+ /**
28
+ * The five words {@link SessionControls} renders, every one overridable.
29
+ *
30
+ * @public
31
+ */
32
+ export type SessionControlsLabels = {
33
+ /** The button shown before the call starts. Default `"Start"`. */
34
+ start: string;
35
+ /** The toggle's label while running. Default `"Pause"`. */
36
+ pause: string;
37
+ /** The toggle's label while paused. Default `"Resume"`. */
38
+ resume: string;
39
+ /** Hang up and dial again. Default `"New Conversation"`. */
40
+ restart: string;
41
+ /** Hang up. Default `"End"`. */
42
+ end: string;
43
+ };
44
+ /**
45
+ * Props of {@link SessionControls}.
46
+ *
47
+ * @public
48
+ */
49
+ export type SessionControlsProps = {
50
+ /** The words this chrome has its own term for; the rest keep the defaults. */
51
+ labels?: Partial<SessionControlsLabels> | undefined;
52
+ /**
53
+ * Renders one button. Absent, each is a stock {@link Button}. A chrome
54
+ * with its own look renders its own `<button>` from the
55
+ * {@link SessionControlButton} it is handed — the component still decides
56
+ * WHICH buttons exist and what each one does.
57
+ */
58
+ renderButton?: ((button: SessionControlButton) => ReactNode) | undefined;
59
+ /** Additional CSS class names for the row, appended to its own layout classes. */
60
+ className?: string | undefined;
61
+ /** Rendered after the buttons — a count, a spacer, a status line. */
62
+ children?: ReactNode;
63
+ };
64
+ /**
65
+ * The full control row of a custom chrome: **Start** before the call, then
66
+ * **Pause / Resume**, **New Conversation** and **End** once it is up.
67
+ *
68
+ * {@link Controls} is the stock console's footer — Stop/Resume and New
69
+ * Conversation, with the URL chips — and it has no Start branch and no End,
70
+ * because the default shell shows a start SCREEN and a session there ends by
71
+ * closing the tab. A chrome that owns its whole frame has no start screen, so
72
+ * three of them each wrote this row: the same `!started` branch, the same
73
+ * three buttons behind it, and the same twelve-line comment on why the middle
74
+ * one is `end(); start()` and not `reset()`. The buttons' look is the
75
+ * chrome's — `renderButton` — and everything else is here once.
76
+ *
77
+ * **Why `restart` is `end()` then `start()`, and never `reset()`.** `reset()`
78
+ * clears the transcript and reconnects carrying the same session id, so every
79
+ * `sessionSlot` on the agent survives: a caller who pressed "New Conversation"
80
+ * on a stateful agent got a blank transcript in front of their old cart, game
81
+ * or incident board, with nothing on screen saying so, and the next tool call
82
+ * repopulated it. `end()` drops the resume identity, so the redial is a
83
+ * brand-new session — fresh state, greeting included — and `start()` puts the
84
+ * chrome straight back on the call rather than at its Start button.
85
+ *
86
+ * **Why End is `end()`.** It hangs up and flips `started` back, so the row
87
+ * returns to its Start button and the next start is a new session. `reset()`
88
+ * would keep the call live — the buttons never toggle back.
89
+ *
90
+ * Reads the session through {@link useSessionControls}: two one-field
91
+ * subscriptions, so the row re-renders when a flag flips and not on every
92
+ * transcript partial.
93
+ *
94
+ * @example A board's controls in its own colours, with a trailing count
95
+ * ```tsx
96
+ * import { SessionControls } from "@alexkroman1/aai-ui";
97
+ *
98
+ * const BUTTON = "px-4 py-2 rounded-md text-xs font-semibold cursor-pointer";
99
+ *
100
+ * function ShiftControls({ logged }: { logged: number }) {
101
+ * return (
102
+ * <SessionControls
103
+ * labels={{ start: "Start Dispatch", end: "End Shift" }}
104
+ * renderButton={({ action, label, onClick }) => (
105
+ * <button
106
+ * type="button"
107
+ * className={BUTTON}
108
+ * style={{ background: action === "end" ? "#dc2626" : "#2563eb", color: "white" }}
109
+ * onClick={onClick}
110
+ * >
111
+ * {label}
112
+ * </button>
113
+ * )}
114
+ * >
115
+ * <span className="ml-auto text-[10px]">{logged} incidents logged</span>
116
+ * </SessionControls>
117
+ * );
118
+ * }
119
+ * ```
120
+ *
121
+ * @param props - See {@link SessionControlsProps}.
122
+ *
123
+ * @public
124
+ */
125
+ export declare function SessionControls({ labels, renderButton, className, children, }: SessionControlsProps): ReactNode;
@@ -0,0 +1,69 @@
1
+ import type { ReactNode } from "react";
2
+ /**
3
+ * Props of {@link SessionErrorBanner}.
4
+ *
5
+ * Every field is optional, so `<SessionErrorBanner />` is the whole call. It is
6
+ * a NAMED type all the same, for the reason `ControlsProps` and
7
+ * `ConsoleShellProps` are: an inline object literal in the signature leaves a
8
+ * `createElement(SessionErrorBanner, { className })` caller unable to infer the
9
+ * props at all, and gives the reference page nothing to link to.
10
+ *
11
+ * @public
12
+ */
13
+ export type SessionErrorBannerProps = {
14
+ /** Additional CSS class names for the banner, appended to its own. */
15
+ className?: string | undefined;
16
+ };
17
+ /**
18
+ * The announced banner for a failed session: the error's message and code, or
19
+ * nothing at all when the session is fine.
20
+ *
21
+ * **This used to be four lines inside `ConsoleShell`, and that is why it is its
22
+ * own component.** The banner was the reason `ConsoleShell` was published —
23
+ * `role="alert"` is the one part of that component a reviewer cannot see is
24
+ * missing, since per the `fatalError` latch in `session/browser-session.ts` the banner is
25
+ * the ONLY remaining signal a session died (the state eyebrow beside it goes
26
+ * back to reading like a live session), and a screen reader is never told an
27
+ * unannounced one appeared. But `ConsoleShell` is a whole FRAME: a centred
28
+ * `max-w-190` column with its own header and footer. Every full-bleed chrome —
29
+ * a two-pane board, a CRT — therefore could not adopt it, rebuilt the banner
30
+ * instead, and the three that did had ALREADY drifted: one rendered
31
+ * `ERROR: {message}` and dropped the code entirely, one `ERROR: {message}
32
+ * ({code})`, one `{message} ({code})`. Splitting the banner out is what lets a
33
+ * chrome take the announced-error decision without taking the layout, and
34
+ * `ConsoleShell` composes this rather than keeping a second copy, so the two
35
+ * cannot drift again.
36
+ *
37
+ * **It reads the session itself.** There is no `error` prop: a banner that
38
+ * takes its text from the caller is a banner a caller can forget to wire, which
39
+ * is exactly the failure above with an extra step. It subscribes narrowly via
40
+ * {@link useSessionError}, so a page that renders it does not re-render with
41
+ * the transcript.
42
+ *
43
+ * **The code is shown, always.** `SessionError.code` is the eight-member wire
44
+ * union — it is what a user pastes into a bug report and the only part of the
45
+ * error that is stable across wordings — and the chrome that dropped it left
46
+ * its readers with a sentence and no way to say which failure it was.
47
+ *
48
+ * Must be rendered inside the providers `client()` installs.
49
+ *
50
+ * @example A full-bleed chrome that wants the banner and not the frame
51
+ * ```tsx
52
+ * import { SessionErrorBanner } from "@alexkroman1/aai-ui";
53
+ *
54
+ * function Board() {
55
+ * return (
56
+ * <div className="grid grid-cols-[1fr_320px] h-screen">
57
+ * <main>…</main>
58
+ * <aside>…</aside>
59
+ * <SessionErrorBanner className="col-span-2" />
60
+ * </div>
61
+ * );
62
+ * }
63
+ * ```
64
+ *
65
+ * @param props - See {@link SessionErrorBannerProps}.
66
+ *
67
+ * @public
68
+ */
69
+ export declare function SessionErrorBanner({ className }: SessionErrorBannerProps): ReactNode;
@@ -0,0 +1,111 @@
1
+ import type { ReactNode } from "react";
2
+ import type { AgentState } from "../types.ts";
3
+ /**
4
+ * The dot itself: a coloured circle, pulsing or still.
5
+ *
6
+ * Shared by {@link SessionStateDot} and `ConsoleShell`, which computes its
7
+ * colour from the theme rather than from a palette prop and decides for itself
8
+ * when to pulse. Not on the package barrel — the public component is the one
9
+ * that reads the session.
10
+ *
11
+ * The colour is written to `background` AND `color`, so a caller can extend
12
+ * the dot with a `currentColor` utility (`shadow-[0_0_6px_currentColor]` for a
13
+ * glow) without restating the palette.
14
+ *
15
+ * @internal
16
+ */
17
+ export declare function StateDot({ color, pulseMs, className, title, }: {
18
+ /** The dot's colour. */
19
+ color: string;
20
+ /** Length of one pulse cycle, or `null` for a still dot. */
21
+ pulseMs: number | null;
22
+ /** Size and any extras; the shape classes are the dot's own. */
23
+ className?: string | undefined;
24
+ /** Tooltip text, typically the raw state. */
25
+ title?: string | undefined;
26
+ }): ReactNode;
27
+ /**
28
+ * Props of {@link SessionStateDot}.
29
+ *
30
+ * @public
31
+ */
32
+ export type SessionStateDotProps = {
33
+ /**
34
+ * The dot's colour per {@link AgentState} — the chrome's own palette. A
35
+ * complete record, so a state added upstream is a compile error here rather
36
+ * than a silently unpainted dot; `satisfies Record<AgentState, string>` on the
37
+ * caller's literal is the shape to write it in.
38
+ */
39
+ colors: Readonly<Record<AgentState, string>>;
40
+ /**
41
+ * The words this chrome has a better term for. Anything not named falls back
42
+ * to {@link AGENT_STATE_LABELS}, so a page overrides one member (`speaking:
43
+ * "Narrating"`) without restating the union.
44
+ */
45
+ labels?: Partial<Readonly<Record<AgentState, string>>> | undefined;
46
+ /**
47
+ * Whether the dot pulses while `listening` (slowly) and `thinking` (faster).
48
+ * Defaults to `true`; a chrome whose dot glows rather than beats passes
49
+ * `false`.
50
+ */
51
+ pulse?: boolean | undefined;
52
+ /** Additional CSS class names for the wrapping `<span>`, appended to its own. */
53
+ className?: string | undefined;
54
+ /**
55
+ * REPLACES the dot's default size (`w-2 h-2`) rather than adding to it —
56
+ * there is no `tailwind-merge` in this package, so two conflicting width
57
+ * utilities would not have a reliable winner. The dot's shape classes stay.
58
+ */
59
+ dotClassName?: string | undefined;
60
+ /** Additional CSS class names for the label `<span>`. */
61
+ labelClassName?: string | undefined;
62
+ };
63
+ /**
64
+ * The live session state as a coloured dot and a word, on its own narrow
65
+ * subscription.
66
+ *
67
+ * Three custom chromes had each written this: a `satisfies Record<AgentState,
68
+ * string>` palette (kept — it is the prop), a `STATE_LABELS` spread over
69
+ * {@link AGENT_STATE_LABELS} (kept — it is `labels`), and then the same
70
+ * fourteen lines of markup around them, including the same two-arm ternary
71
+ * deciding which states pulse and how fast. `agent-state-labels.ts` argued
72
+ * against a dot component on the grounds that it would take the shared part
73
+ * (the words) hostage to the part that is not (the palette); this takes the
74
+ * palette as a prop precisely so it does not. What is shared is the structure
75
+ * — the exhaustive colour lookup, the label fallback, the pulse rule, the
76
+ * `useSessionStatus()` subscription that keeps the rest of the header from
77
+ * re-rendering at STT-partial rate.
78
+ *
79
+ * Must be rendered inside the providers `mountClient()` installs.
80
+ *
81
+ * @example A dispatch board's readout: its own colours, three of its own words
82
+ * ```tsx
83
+ * import type { AgentState } from "@alexkroman1/aai-ui";
84
+ * import { SessionStateDot } from "@alexkroman1/aai-ui";
85
+ *
86
+ * const STATE_COLORS = {
87
+ * disconnected: "#6b7280",
88
+ * connecting: "#6b7280",
89
+ * ready: "#22c55e",
90
+ * listening: "#22c55e",
91
+ * thinking: "#eab308",
92
+ * speaking: "#3b82f6",
93
+ * error: "#6b7280",
94
+ * } satisfies Record<AgentState, string>;
95
+ *
96
+ * function StatusReadout() {
97
+ * return (
98
+ * <SessionStateDot
99
+ * colors={STATE_COLORS}
100
+ * labels={{ listening: "LISTENING", thinking: "PROCESSING", speaking: "TRANSMITTING" }}
101
+ * labelClassName="text-[11px] uppercase"
102
+ * />
103
+ * );
104
+ * }
105
+ * ```
106
+ *
107
+ * @param props - See {@link SessionStateDotProps}.
108
+ *
109
+ * @public
110
+ */
111
+ export declare function SessionStateDot({ colors, labels, pulse, className, dotClassName, labelClassName, }: SessionStateDotProps): ReactNode;
@@ -1,21 +1,42 @@
1
- import type { ComponentChildren } from "preact";
1
+ import type { ReactNode } from "react";
2
2
  /**
3
3
  * A two-column layout with a fixed-width sidebar and a flexible main area.
4
4
  * Commonly used to pair a custom sidebar (cart, dashboard) with `<ChatView />`.
5
5
  *
6
6
  * @example
7
7
  * ```tsx
8
- * <SidebarLayout sidebar={<OrderPanel />}>
9
- * <ChatView />
10
- * </SidebarLayout>
8
+ * import { ChatView, SidebarLayout } from "@alexkroman1/aai-ui";
9
+ *
10
+ * function OrderPanel() {
11
+ * return <div>Cart</div>;
12
+ * }
13
+ *
14
+ * function App() {
15
+ * return (
16
+ * <SidebarLayout sidebar={<OrderPanel />}>
17
+ * <ChatView />
18
+ * </SidebarLayout>
19
+ * );
20
+ * }
11
21
  * ```
12
22
  *
23
+ * @param props - Layout props.
24
+ *
13
25
  * @public
14
26
  */
15
- export declare function SidebarLayout({ sidebar, children, width, side, className, }: {
16
- sidebar: ComponentChildren;
17
- children: ComponentChildren;
18
- width?: string | undefined;
19
- side?: "left" | "right" | undefined;
27
+ export declare function SidebarLayout({ sidebar, children, sidebarWidth, sidebarPosition, className, }: {
28
+ /** The sidebar pane — a cart, a dashboard, a run history. */
29
+ sidebar: ReactNode;
30
+ /** The main pane, normally a `<ChatView />`. */
31
+ children: ReactNode;
32
+ /**
33
+ * Width of the sidebar as a CSS length. Defaults to `"18rem"`, and applies
34
+ * from the `md` breakpoint up: below it the two panes stack, because a fixed
35
+ * width that never shrinks leaves a phone-width main pane unreadable.
36
+ */
37
+ sidebarWidth?: string | undefined;
38
+ /** Which side the sidebar sits on. Defaults to `"left"`. */
39
+ sidebarPosition?: "left" | "right" | undefined;
40
+ /** Additional CSS class names for the root element, appended to its own. */
20
41
  className?: string;
21
- }): import("preact").JSX.Element;
42
+ }): import("react").JSX.Element;
@@ -1,34 +1,54 @@
1
+ import { useTheme } from "../context.js";
1
2
  import clsx from "clsx";
2
- import { jsx, jsxs } from "preact/jsx-runtime";
3
- //#region components/sidebar-layout.tsx
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ //#region src/components/sidebar-layout.tsx
5
+ /** @jsxImportSource react */
4
6
  /**
5
7
  * A two-column layout with a fixed-width sidebar and a flexible main area.
6
8
  * Commonly used to pair a custom sidebar (cart, dashboard) with `<ChatView />`.
7
9
  *
8
10
  * @example
9
11
  * ```tsx
10
- * <SidebarLayout sidebar={<OrderPanel />}>
11
- * <ChatView />
12
- * </SidebarLayout>
12
+ * import { ChatView, SidebarLayout } from "@alexkroman1/aai-ui";
13
+ *
14
+ * function OrderPanel() {
15
+ * return <div>Cart</div>;
16
+ * }
17
+ *
18
+ * function App() {
19
+ * return (
20
+ * <SidebarLayout sidebar={<OrderPanel />}>
21
+ * <ChatView />
22
+ * </SidebarLayout>
23
+ * );
24
+ * }
13
25
  * ```
14
26
  *
27
+ * @param props - Layout props.
28
+ *
15
29
  * @public
16
30
  */
17
- function SidebarLayout({ sidebar, children, width = "20rem", side = "left", className }) {
31
+ function SidebarLayout({ sidebar, children, sidebarWidth = "18rem", sidebarPosition = "left", className }) {
32
+ const theme = useTheme();
18
33
  const sidebarEl = /* @__PURE__ */ jsx("div", {
19
- class: clsx("flex-shrink-0 flex flex-col overflow-y-auto", side === "left" ? "border-r border-aai-border" : "border-l border-aai-border"),
20
- style: { width },
34
+ className: clsx("shrink-0 flex flex-col overflow-y-auto", "w-full max-h-[40vh] md:w-(--aai-sidebar-w) md:max-h-none", sidebarPosition === "left" ? "border-b md:border-b-0 md:border-r" : "border-t md:border-t-0 md:border-l order-last md:order-none"),
35
+ style: { borderColor: theme.border },
21
36
  children: sidebar
22
37
  });
38
+ const vars = {
39
+ background: theme.bg,
40
+ "--aai-sidebar-w": sidebarWidth
41
+ };
23
42
  return /* @__PURE__ */ jsxs("div", {
24
- class: clsx("flex h-screen bg-aai-bg", className),
43
+ className: clsx("flex flex-col md:flex-row min-h-screen md:h-screen", className),
44
+ style: vars,
25
45
  children: [
26
- side === "left" && sidebarEl,
46
+ sidebarPosition === "left" && sidebarEl,
27
47
  /* @__PURE__ */ jsx("div", {
28
- class: "flex-1 min-w-0",
48
+ className: "flex-1 min-w-0 min-h-0",
29
49
  children
30
50
  }),
31
- side === "right" && sidebarEl
51
+ sidebarPosition === "right" && sidebarEl
32
52
  ]
33
53
  });
34
54
  }
@@ -1,10 +1,13 @@
1
- import type { ComponentChildren } from "preact";
1
+ import type { ReactNode } from "react";
2
2
  /**
3
- * A centered start screen with icon, title, subtitle, and a start button.
4
- * Renders `children` (the main app) once the session has started.
3
+ * A centered start screen: a white card on the cream page with the logo, an
4
+ * eyebrow label, a serif title, subtitle, and the start CTA. Renders
5
+ * `children` (the main app) once the session has started.
5
6
  *
6
7
  * @example
7
8
  * ```tsx
9
+ * import { ChatView, StartScreen } from "@alexkroman1/aai-ui";
10
+ *
8
11
  * function MyAgent() {
9
12
  * return (
10
13
  * <StartScreen icon="🍕" title="Pizza Palace" subtitle="Voice-powered ordering">
@@ -14,13 +17,21 @@ import type { ComponentChildren } from "preact";
14
17
  * }
15
18
  * ```
16
19
  *
20
+ * @param props - Start-screen props.
21
+ *
17
22
  * @public
18
23
  */
19
24
  export declare function StartScreen({ children, icon, title, subtitle, buttonText, className, }: {
20
- children: ComponentChildren;
21
- icon?: ComponentChildren | undefined;
25
+ /** The app, rendered once the session has started. */
26
+ children: ReactNode;
27
+ /** Element rendered in place of the logo on the card. */
28
+ icon?: ReactNode | undefined;
29
+ /** The card's serif title. Defaults to the agent's declared name. */
22
30
  title?: string | undefined;
31
+ /** A line under the title. */
23
32
  subtitle?: string | undefined;
33
+ /** Label of the start CTA. Defaults to `"Start Conversation"`. */
24
34
  buttonText?: string | undefined;
35
+ /** Additional CSS class names for the root element, appended to its own. */
25
36
  className?: string | undefined;
26
- }): import("preact").JSX.Element;
37
+ }): ReactNode;
@@ -1,14 +1,21 @@
1
- import { useSession } from "../signals.js";
1
+ import { useSessionCore, useSessionSelector, useTheme } from "../context.js";
2
+ import { a as inkTint } from "../_colors-CpZO-88A.js";
2
3
  import { Button } from "./button.js";
4
+ import { t as AaiLogo } from "../aai-logo-D8pMVn9_.js";
5
+ import { t as Eyebrow } from "../eyebrow-UfmSz9yy.js";
3
6
  import clsx from "clsx";
4
- import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
5
- //#region components/start-screen.tsx
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/components/start-screen.tsx
9
+ /** @jsxImportSource react */
6
10
  /**
7
- * A centered start screen with icon, title, subtitle, and a start button.
8
- * Renders `children` (the main app) once the session has started.
11
+ * A centered start screen: a white card on the cream page with the logo, an
12
+ * eyebrow label, a serif title, subtitle, and the start CTA. Renders
13
+ * `children` (the main app) once the session has started.
9
14
  *
10
15
  * @example
11
16
  * ```tsx
17
+ * import { ChatView, StartScreen } from "@alexkroman1/aai-ui";
18
+ *
12
19
  * function MyAgent() {
13
20
  * return (
14
21
  * <StartScreen icon="🍕" title="Pizza Palace" subtitle="Voice-powered ordering">
@@ -18,28 +25,41 @@ import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
18
25
  * }
19
26
  * ```
20
27
  *
28
+ * @param props - Start-screen props.
29
+ *
21
30
  * @public
22
31
  */
23
- function StartScreen({ children, icon, title, subtitle, buttonText = "Start", className }) {
24
- const { started, start } = useSession();
25
- if (started.value) return /* @__PURE__ */ jsx(Fragment, { children });
32
+ function StartScreen({ children, icon, title, subtitle, buttonText = "Start Conversation", className }) {
33
+ const started = useSessionSelector((s) => s.started);
34
+ const { start } = useSessionCore();
35
+ const theme = useTheme();
36
+ if (started) return children;
26
37
  return /* @__PURE__ */ jsx("div", {
27
- class: clsx("flex items-center justify-center h-screen bg-aai-bg font-aai", className),
38
+ className: clsx("flex items-center justify-center h-screen font-aai", className),
39
+ style: { background: theme.bg },
28
40
  children: /* @__PURE__ */ jsxs("div", {
29
- class: "flex flex-col items-center gap-4 bg-aai-surface border border-aai-border rounded-lg px-12 py-10 max-w-sm text-center",
41
+ className: "flex flex-col items-center gap-5 border rounded-xl px-10 py-12 sm:px-16 sm:py-14 max-w-105 text-center",
42
+ style: {
43
+ background: theme.surface,
44
+ borderColor: theme.border,
45
+ boxShadow: "0 4px 12px -2px rgb(20 18 12 / 0.08)"
46
+ },
30
47
  children: [
31
- icon,
48
+ icon ?? /* @__PURE__ */ jsx(AaiLogo, { size: 24 }),
49
+ /* @__PURE__ */ jsx(Eyebrow, { children: "Voice Agent" }),
32
50
  title && /* @__PURE__ */ jsx("h1", {
33
- class: "font-semibold text-aai-primary m-0",
51
+ className: "font-aai-serif font-normal text-[32px] leading-[1.15] tracking-[-0.2px] m-0 text-balance",
52
+ style: { color: theme.text },
34
53
  children: title
35
54
  }),
36
55
  subtitle && /* @__PURE__ */ jsx("p", {
37
- class: "text-sm text-aai-text-muted m-0",
56
+ className: "text-[15px] leading-[22px] m-0 max-w-75",
57
+ style: { color: inkTint(theme.text, theme.surface, 75) },
38
58
  children: subtitle
39
59
  }),
40
60
  /* @__PURE__ */ jsx(Button, {
41
61
  size: "lg",
42
- className: "mt-2 w-full",
62
+ className: "mt-2",
43
63
  onClick: start,
44
64
  children: buttonText
45
65
  })
@@ -1,27 +1,28 @@
1
- import type * as preact from "preact";
1
+ /** @jsxImportSource react */
2
+ import { type ReactNode } from "react";
2
3
  import type { ToolCallInfo } from "../types.ts";
3
4
  /**
4
- * Renders a tool invocation with an icon, title, subtitle, and a
5
- * collapsible result viewer.
5
+ * Renders a tool invocation as the design system's console row (see
6
+ * `ToolCallRow`): a small outlined "TOOL" chip (or the tool's configured
7
+ * icon), the tool name in mono, a truncated args preview, and a rotating
8
+ * chevron that expands the formatted result.
6
9
  *
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
+ * Tool display is configured via `ToolConfigContext`. If no config is found
11
+ * for a tool name, the raw tool name is shown as the title.
10
12
  *
11
13
  * While the tool call is pending a shimmer animation is shown. Once
12
- * complete, clicking the block expands the formatted JSON result.
14
+ * complete, clicking the row expands the formatted JSON result.
13
15
  *
14
- * @example
15
- * ```tsx
16
- * <ToolCallBlock toolCall={toolCall} />
17
- * ```
16
+ * Memoized: tool-call objects are referentially stable across session
17
+ * snapshots and rows are keyed on the stable `callId`, so a list update only
18
+ * re-renders the rows whose tool call actually changed.
18
19
  *
19
20
  * @param toolCall - The tool call to render (see {@link ToolCallInfo}).
20
21
  * @param className - Additional CSS class names.
21
22
  *
22
- * @public
23
+ * @internal Not exported from the package — rendered by `MessageList`.
23
24
  */
24
- export declare function ToolCallBlock({ toolCall, className, }: {
25
+ export declare const ToolCallBlock: import("react").MemoExoticComponent<({ toolCall, className, }: {
25
26
  toolCall: ToolCallInfo;
26
27
  className?: string;
27
- }): preact.JSX.Element;
28
+ }) => ReactNode>;