@alexkroman1/aai-ui 0.16.0 → 0.18.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 (123) hide show
  1. package/README.md +6 -7
  2. package/dist/_submission-timing.d.ts +40 -0
  3. package/dist/_submission.d.ts +56 -0
  4. package/dist/_theme.d.ts +17 -0
  5. package/dist/_theme.test-d.d.ts +14 -0
  6. package/dist/{_utils-Mi-SCFA1.js → _utils-BlZBJPdj.js} +4 -5
  7. package/dist/_utils.d.ts +4 -5
  8. package/dist/agent-state-labels.d.ts +8 -3
  9. package/dist/agent-state.d.ts +4 -2
  10. package/dist/append-dictation.d.ts +23 -0
  11. package/dist/audio/dictation.d.ts +36 -0
  12. package/dist/audio/index.d.ts +4 -2
  13. package/dist/audio/index.js +44 -1
  14. package/dist/{chat-view-DIwPoAEG.js → chat-view-BwKpF0MN.js} +65 -45
  15. package/dist/{client-config-C7fQrioM.js → client-config-DcMCWmkO.js} +8 -13
  16. package/dist/client-config.d.ts +29 -10
  17. package/dist/components/_form-readiness.d.ts +2 -1
  18. package/dist/components/audio-result.d.ts +2 -0
  19. package/dist/components/bullet-list.d.ts +1 -0
  20. package/dist/components/button.d.ts +2 -2
  21. package/dist/components/button.js +1 -1
  22. package/dist/components/chat-view.js +1 -2
  23. package/dist/components/console-shell.d.ts +8 -5
  24. package/dist/components/controls.d.ts +1 -0
  25. package/dist/components/controls.js +2 -2
  26. package/dist/components/conversation-view.d.ts +1 -0
  27. package/dist/components/facts.d.ts +1 -0
  28. package/dist/components/form-fields.d.ts +31 -12
  29. package/dist/components/form-types.d.ts +48 -2
  30. package/dist/components/form.d.ts +10 -5
  31. package/dist/components/markdown.d.ts +1 -0
  32. package/dist/components/message-list.d.ts +1 -0
  33. package/dist/components/message-list.js +1 -2
  34. package/dist/components/session-controls.d.ts +7 -2
  35. package/dist/components/session-error-banner.d.ts +1 -0
  36. package/dist/components/session-state-dot.d.ts +45 -20
  37. package/dist/components/sidebar-layout.d.ts +2 -2
  38. package/dist/components/sidebar-layout.js +1 -1
  39. package/dist/components/start-screen.js +2 -2
  40. package/dist/components/tool-call-block.d.ts +3 -3
  41. package/dist/components/tool-call-block.js +1 -2
  42. package/dist/components/tool-call-row.d.ts +1 -0
  43. package/dist/components/tool-config-context.d.ts +23 -5
  44. package/dist/components/url-chips.d.ts +4 -3
  45. package/dist/components/workflow-fields.d.ts +36 -11
  46. package/dist/components/workflow-pending-note.d.ts +31 -12
  47. package/dist/components/workflow-run-error.d.ts +1 -0
  48. package/dist/components/workflow-run-panel.d.ts +1 -0
  49. package/dist/context-BF0KsI9X.js +473 -0
  50. package/dist/context.d.ts +8 -7
  51. package/dist/context.js +1 -381
  52. package/dist/default-client/assets/audio-CtBvSS3L.js +1 -0
  53. package/dist/default-client/assets/{capture-processor-CXCWxCO8.js → capture-processor-BZXisGjZ.js} +1 -1
  54. package/dist/default-client/assets/index-BkjCv4MX.css +2 -0
  55. package/dist/default-client/assets/index-DUQoaxdq.js +127 -0
  56. package/dist/default-client/assets/{playback-processor-DXHfyQD9.js → playback-processor-BHk-iXEU.js} +1 -1
  57. package/dist/default-client/index.html +2 -2
  58. package/dist/default-client.d.ts +1 -3
  59. package/dist/define-client.d.ts +32 -28
  60. package/dist/define-client.js +85 -44
  61. package/dist/dictation-transcriber.d.ts +49 -0
  62. package/dist/{eyebrow-UfmSz9yy.js → eyebrow-Bp4y1rZ9.js} +1 -1
  63. package/dist/{hooks-DN4gHYsj.js → hooks-1CoQY_Fc.js} +2 -2
  64. package/dist/hooks.js +1 -2
  65. package/dist/inbox-protocol.d.ts +14 -4
  66. package/dist/inbox.d.ts +1 -0
  67. package/dist/index.d.ts +12 -9
  68. package/dist/index.js +905 -277
  69. package/dist/internal.d.ts +1 -1
  70. package/dist/internal.js +6 -6
  71. package/dist/linked-client.d.ts +2 -0
  72. package/dist/{message-list-DHZcLhRA.js → message-list-BBHLK05X.js} +24 -13
  73. package/dist/page.d.ts +2 -0
  74. package/dist/phone.d.ts +1 -0
  75. package/dist/route-fetch.d.ts +8 -1
  76. package/dist/session/audio-setup.d.ts +1 -1
  77. package/dist/session/audio-state.d.ts +6 -6
  78. package/dist/session/index.js +1 -1
  79. package/dist/session/messages.d.ts +1 -9
  80. package/dist/session/preconnect.d.ts +1 -1
  81. package/dist/session/types.d.ts +4 -0
  82. package/dist/{session-CYdjRvbl.js → session-Rud8mmU-.js} +26 -15
  83. package/dist/stored-value.d.ts +2 -0
  84. package/dist/{tool-call-block-uXtMOUWN.js → tool-call-block-C8s6AhjS.js} +4 -4
  85. package/dist/tool-config-context-Bd-7xrfP.js +28 -0
  86. package/dist/types.d.ts +95 -6
  87. package/dist/{url-chips-oyy_Eiqh.js → url-chips-C_SHU6fq.js} +2 -2
  88. package/dist/use-client-runs.d.ts +2 -0
  89. package/dist/use-conversation-log.d.ts +2 -0
  90. package/dist/use-conversation.d.ts +24 -9
  91. package/dist/use-copy.d.ts +1 -0
  92. package/dist/use-dictation.d.ts +145 -0
  93. package/dist/use-download-url.d.ts +6 -1
  94. package/dist/use-flash.d.ts +1 -0
  95. package/dist/use-inbox.d.ts +2 -0
  96. package/dist/use-push-to-talk.d.ts +6 -1
  97. package/dist/use-route-mutation.d.ts +3 -0
  98. package/dist/use-route.d.ts +51 -7
  99. package/dist/use-run-key.d.ts +6 -1
  100. package/dist/use-session-controls.d.ts +1 -0
  101. package/dist/use-tap-to-talk.d.ts +5 -2
  102. package/dist/{use-user-transcript-uyHhzy4d.js → use-user-transcript-lOu_uMnf.js} +1 -1
  103. package/dist/use-user-transcript.d.ts +5 -1
  104. package/dist/use-workflow-form.d.ts +76 -167
  105. package/dist/use-workflow-progress.d.ts +5 -0
  106. package/dist/{use-workflow-run-DdhWmbx-.js → use-workflow-run-BTEemod0.js} +2 -2
  107. package/dist/use-workflow-run.d.ts +5 -0
  108. package/dist/use-workflow-runs.d.ts +18 -4
  109. package/dist/use-workflow-stream.d.ts +33 -7
  110. package/dist/use-workflows.d.ts +10 -2
  111. package/dist/workflow-client.d.ts +5 -0
  112. package/dist/workflow-def-types.d.ts +18 -2
  113. package/dist/workflow-field-kind.d.ts +66 -10
  114. package/dist/workflow-submission.d.ts +265 -0
  115. package/dist/worklets/capture-processor.d.ts +3 -3
  116. package/dist/worklets/capture-processor.js +2 -2
  117. package/dist/worklets/playback-processor.d.ts +3 -3
  118. package/dist/worklets/playback-processor.js +2 -2
  119. package/package.json +2 -2
  120. package/dist/default-client/assets/audio-DzwGxdv4.js +0 -1
  121. package/dist/default-client/assets/index-BOTLwsNO.js +0 -126
  122. package/dist/default-client/assets/index-_-x5JLLa.css +0 -2
  123. package/dist/tool-config-context-Es4YUzV2.js +0 -19
@@ -1,4 +1,4 @@
1
- import{r as e}from"./index-BOTLwsNO.js";import{t}from"./_module-url-BX0RuRU2.js";var n=`
1
+ import{r as e}from"./index-DUQoaxdq.js";import{t}from"./_module-url-BX0RuRU2.js";var n=`
2
2
  class PlaybackProcessor extends AudioWorkletProcessor {
3
3
  constructor(options) {
4
4
  super();
@@ -6,8 +6,8 @@
6
6
  <title>aai</title>
7
7
  <link rel="icon" href="./favicon.ico" />
8
8
  <style>html,body{background:#fafafa;margin:0}</style>
9
- <script type="module" crossorigin src="./assets/index-BOTLwsNO.js"></script>
10
- <link rel="stylesheet" crossorigin href="./assets/index-_-x5JLLa.css">
9
+ <script type="module" crossorigin src="./assets/index-DUQoaxdq.js"></script>
10
+ <link rel="stylesheet" crossorigin href="./assets/index-BkjCv4MX.css">
11
11
  </head>
12
12
  <body>
13
13
  <main id="app"></main>
@@ -1,8 +1,6 @@
1
1
  /** The two mounts the default client chooses between, injectable for a spec. */
2
2
  export type DefaultClientMounts = {
3
- mountClient: (config: {
4
- name?: string;
5
- }) => unknown;
3
+ mountClient: (config: Record<string, never>) => unknown;
6
4
  mountPage: (config: {
7
5
  name?: string;
8
6
  }) => unknown;
@@ -1,6 +1,5 @@
1
1
  /** @jsxImportSource react */
2
2
  import { type ComponentType, type ReactNode } from "react";
3
- import { type ToolDisplayConfig } from "./components/tool-config-context.ts";
4
3
  import type { BrowserSession } from "./session/index.ts";
5
4
  import { createBrowserSession } from "./session/index.ts";
6
5
  import type { ClientTheme, VoiceSessionOptions } from "./types.ts";
@@ -19,14 +18,17 @@ import type { ClientTheme, VoiceSessionOptions } from "./types.ts";
19
18
  * sidebar); present, the caller's own component inside the same providers —
20
19
  * and that decision is made at runtime, where every field can be honoured. It
21
20
  * used to be a union whose two arms banned each other's fields with `?: never`,
22
- * and the failure that shape produces is recorded twice in this file's history:
23
- * `mountClient({ name, component })` and `mountClient({ component, tools })` were both
24
- * the natural thing to write, both were refused with *"Type 'string' is not
25
- * assignable to type 'undefined'"*, and both cost a build round each time
26
- * before the ban was lifted. What was left banned was `sidebar` beside a
27
- * `component`, which invited the identical failure for a combination
28
- * {@link mountClient} can simply render.
21
+ * and the failure that shape produces is recorded in this file's history:
22
+ * `sidebar` beside a `component` was the natural thing to write, was refused
23
+ * with *"Type '…' is not assignable to type 'undefined'"*, and cost a build
24
+ * round each time, for a combination {@link mountClient} can simply render.
29
25
  *
26
+ * The agent's name and each tool's icon and label are not options here: both
27
+ * come from the agent's own `GET /client-config` body — `agent({ name })` and
28
+ * `tool({ ui })` — which the mount looks up, so a page never restates what the
29
+ * agent already declared.
30
+ *
31
+ * @input
30
32
  * @public
31
33
  */
32
34
  export type ClientConfig = Pick<VoiceSessionOptions, "onSessionId" | "resumeSessionId" | "location" | "phone" | "client" | "token" | "WebSocket"> & {
@@ -34,8 +36,22 @@ export type ClientConfig = Pick<VoiceSessionOptions, "onSessionId" | "resumeSess
34
36
  target?: string | HTMLElement;
35
37
  /** Base URL of the AAI platform server. Derived from `location.href` by default. */
36
38
  platformUrl?: string;
37
- /** Theme color overrides. */
39
+ /**
40
+ * Theme colors — the five tokens, or `{ primary, mode: "dark" | "light" }`
41
+ * with the rest derived. See {@link ClientTheme}.
42
+ */
38
43
  theme?: ClientTheme;
44
+ /**
45
+ * A stylesheet for the PAGE, injected into `<head>` for the life of the
46
+ * mount and removed on dispose.
47
+ *
48
+ * For the rules a custom chrome has that no component prop reaches — a
49
+ * `@keyframes`, a scrollbar palette, a font face — which otherwise meant a
50
+ * `<style>` element written into `index.html` beside the mount, in the one
51
+ * file the scaffold's CSP is strict about. The five theme tokens are already
52
+ * on `:root` as `--aai-*` when these rules run, so a sheet may use them.
53
+ */
54
+ css?: string;
39
55
  /**
40
56
  * Full custom component to render instead of the default shell.
41
57
  *
@@ -43,12 +59,6 @@ export type ClientConfig = Pick<VoiceSessionOptions, "onSessionId" | "resumeSess
43
59
  * session hook, `useTheme` and the tool display config work in it unchanged.
44
60
  */
45
61
  component?: ComponentType;
46
- /**
47
- * Agent name shown in the header and start screen — and, with a `component`,
48
- * the page title, there being no shell header to put it in. Left out, the
49
- * default shell asks the agent for its own declared name.
50
- */
51
- name?: string;
52
62
  /**
53
63
  * Optional sidebar component rendered alongside the main pane.
54
64
  *
@@ -79,21 +89,13 @@ export type ClientConfig = Pick<VoiceSessionOptions, "onSessionId" | "resumeSess
79
89
  subtitle?: string;
80
90
  /** Label of the start CTA. Defaults to `"Start Conversation"`. */
81
91
  buttonText?: string;
82
- /**
83
- * Tool display config: icon and label overrides keyed by tool name.
84
- *
85
- * Honoured with a custom `component` too: {@link mountClient} installs it into
86
- * `ToolConfigContext`, and the consumer is `ToolCallBlock` — which a custom
87
- * component renders as soon as it uses `MessageList` or `ChatView`, the usual
88
- * way to build one.
89
- */
90
- tools?: ToolDisplayConfig;
91
92
  };
92
93
  /**
93
94
  * Handle returned by {@link mountClient} for cleanup.
94
95
  *
95
96
  * Implements `Disposable` so it can be used with `using`.
96
97
  *
98
+ * @sealed
97
99
  * @public
98
100
  */
99
101
  export type ClientHandle = {
@@ -151,8 +153,12 @@ export declare function mountRoot(container: HTMLElement, node: ReactNode, onDis
151
153
  *
152
154
  * **A custom component:** pass `component` and it is rendered inside the same
153
155
  * providers instead of the default shell — beside a `sidebar` if one is given,
154
- * in the same {@link SidebarLayout}. A provided `name` then also sets
155
- * `document.title`, there being no shell header to show it in.
156
+ * in the same {@link SidebarLayout}. The page title is the HTML's own; a
157
+ * custom component that wants another sets `document.title` itself.
158
+ *
159
+ * The agent's name on the start card and in the header, and each tool's icon
160
+ * and label, are what the agent declared (`agent({ name })`, `tool({ ui })`),
161
+ * read from its `GET /client-config` body — not options here.
156
162
  *
157
163
  * Mounts into `target` — a CSS selector or DOM element, defaulting to
158
164
  * `"#app"` — and throws `Element not found: <target>` when the selector
@@ -167,10 +173,8 @@ export declare function mountRoot(container: HTMLElement, node: ReactNode, onDis
167
173
  * }
168
174
  *
169
175
  * mountClient({
170
- * name: "Pizza Ordering",
171
176
  * theme: { bg: "#1a1a1a", primary: "#e55" },
172
177
  * sidebar: OrderPanel,
173
- * tools: { add_pizza: { icon: "🍕", label: "Adding pizza" } },
174
178
  * });
175
179
  * ```
176
180
  *
@@ -1,13 +1,13 @@
1
- import { t as ChatView } from "./chat-view-DIwPoAEG.js";
2
- import { n as pageBaseUrl, r as setPageTitle } from "./_utils-Mi-SCFA1.js";
3
- import { n as fetchClientConfig } from "./client-config-C7fQrioM.js";
4
- import { t as createBrowserSession } from "./session-CYdjRvbl.js";
5
- import { SessionProvider, ThemeProvider } from "./context.js";
6
- import { t as ToolConfigContext } from "./tool-config-context-Es4YUzV2.js";
1
+ import { t as ChatView } from "./chat-view-BwKpF0MN.js";
2
+ import { n as pageBaseUrl } from "./_utils-BlZBJPdj.js";
3
+ import { n as fetchClientConfig } from "./client-config-DcMCWmkO.js";
4
+ import { t as createBrowserSession } from "./session-Rud8mmU-.js";
5
+ import { c as useSessionSelector, n as ThemeProvider, t as SessionProvider } from "./context-BF0KsI9X.js";
6
+ import { n as ToolConfigContext, t as EMPTY_TOOL_DISPLAY } from "./tool-config-context-Bd-7xrfP.js";
7
7
  import { SidebarLayout } from "./components/sidebar-layout.js";
8
8
  import { StartScreen } from "./components/start-screen.js";
9
9
  import { createElement, useEffect, useState } from "react";
10
- import { jsx } from "react/jsx-runtime";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
11
  import { flushSync } from "react-dom";
12
12
  import { createRoot } from "react-dom/client";
13
13
  //#region src/define-client.tsx
@@ -82,39 +82,75 @@ function DefaultShell({ name, icon, subtitle, buttonText, Sidebar, ...layout })
82
82
  });
83
83
  }
84
84
  /**
85
- * Config-tier root: fetches the server-declared display name via
86
- * `GET client-config` and renders the chat shell. The shell renders
87
- * immediately — optimistically — while the lookup is in flight; servers
88
- * without the endpoint (every lookup failure resolves to the empty default)
89
- * work exactly as before.
90
- *
91
- * **The lookup is SKIPPED when the caller already named the agent.** The
92
- * response's only consumer here is the fallback below, so with an explicit
93
- * `mountClient({ name })` the request was issued and its answer thrown away — and on
94
- * the platform this endpoint is the BROKER, so the discarded request is one that
95
- * can boot a sandbox. The session's own per-attempt lookup
96
- * (`session/browser-session.ts`'s URL provider) is a different question and deliberately
97
- * left alone: it re-brokers on every connection attempt, which is what makes a
98
- * reconnect land on a REPLACEMENT sandbox, so it may not be served from
99
- * anything this render already has.
85
+ * The session-config lookup the mount makes, and WHEN.
86
+ *
87
+ * The response feeds two things: the default shell's title (the agent's own
88
+ * declared name), and every tool's declared icon and label (`tools`), which a
89
+ * custom component's `ToolCallBlock` reads too. The timing rule is the one
90
+ * this file has always had, kept because on the platform this endpoint is the
91
+ * BROKER and a request to it can boot a sandbox: the lookup is issued at mount
92
+ * only when the default shell renders, since its start card needs the name;
93
+ * under a custom `component` it waits until the session has STARTED — at
94
+ * which point the session's own per-attempt lookup is booting that sandbox
95
+ * anyway, so the second request costs no boot. Either way it is issued once;
96
+ * the session's own lookup stays separate (it re-brokers per attempt, which
97
+ * this must not interfere with — see `session/dial.ts`).
100
98
  */
101
- function DefaultRoot({ platformUrl, ...display }) {
102
- const { name } = display;
99
+ function useMountLookup(platformUrl, eager) {
100
+ const started = useSessionSelector(selectStarted);
101
+ const wanted = eager || started;
103
102
  const [resolved, setResolved] = useState(null);
104
- const needsLookup = name === void 0;
105
103
  useEffect(() => {
106
- if (!needsLookup) return;
104
+ if (!wanted || resolved !== null) return;
107
105
  let cancelled = false;
108
- fetchClientConfig(platformUrl).then((cfg) => {
106
+ fetchClientConfig({ platformUrl }).then((cfg) => {
109
107
  if (!cancelled) setResolved(cfg);
110
108
  });
111
109
  return () => {
112
110
  cancelled = true;
113
111
  };
114
- }, [platformUrl, needsLookup]);
115
- return /* @__PURE__ */ jsx(DefaultShell, {
116
- ...display,
117
- name: name ?? resolved?.name
112
+ }, [
113
+ platformUrl,
114
+ wanted,
115
+ resolved
116
+ ]);
117
+ return resolved;
118
+ }
119
+ /** Module-scope, for the reason `context.ts` hoists its own two selectors. */
120
+ const selectStarted = (snapshot) => snapshot.started;
121
+ /**
122
+ * The page-level stylesheet `mountClient({ css })` injects — see that field.
123
+ * A `<style>` in `<head>` rather than inline on an element, so `@keyframes`,
124
+ * `@font-face` and pseudo-element rules all work; removed on unmount so a
125
+ * client disposed mid-page leaves the page as it found it.
126
+ */
127
+ function PageCss({ css }) {
128
+ useEffect(() => {
129
+ if (css === void 0 || css === "" || typeof document === "undefined") return;
130
+ const style = document.createElement("style");
131
+ style.setAttribute("data-aai-css", "");
132
+ style.textContent = css;
133
+ document.head.appendChild(style);
134
+ return () => {
135
+ style.remove();
136
+ };
137
+ }, [css]);
138
+ return null;
139
+ }
140
+ /**
141
+ * Everything under the session provider: the lookup, the two display
142
+ * contexts, the page stylesheet, then the caller's component or the default
143
+ * shell. Inside `SessionProvider` because the lookup's timing reads the
144
+ * session (`useMountLookup`).
145
+ */
146
+ function ClientRoot({ config, platformUrl }) {
147
+ const resolved = useMountLookup(platformUrl, config.component === void 0);
148
+ return /* @__PURE__ */ jsx(ToolConfigContext.Provider, {
149
+ value: resolved?.tools ?? EMPTY_TOOL_DISPLAY,
150
+ children: /* @__PURE__ */ jsxs(ThemeProvider, {
151
+ value: config.theme,
152
+ children: [/* @__PURE__ */ jsx(PageCss, { css: config.css }), rootFor(config, resolved?.name)]
153
+ })
118
154
  });
119
155
  }
120
156
  /**
@@ -124,14 +160,17 @@ function DefaultRoot({ platformUrl, ...display }) {
124
160
  * `sidebar` off — but the layout the default shell uses is right here, and
125
161
  * `mountClient({ component, sidebar })` names one pane and one aside, which is
126
162
  * exactly what it renders. Honouring the combination rather than ignoring it is
127
- * the same call this file already made for `name` and `tools`.
163
+ * the same call this file makes for every display field.
164
+ *
165
+ * The default shell renders immediately — optimistically — without a name;
166
+ * `serverName` arrives from the mount's lookup, which is the agent's own
167
+ * `agent({ name })`.
128
168
  */
129
- function rootFor(config, platformUrl) {
169
+ function rootFor(config, serverName) {
130
170
  const Custom = config.component;
131
171
  const Sidebar = config.sidebar;
132
- if (!Custom) return /* @__PURE__ */ jsx(DefaultRoot, {
133
- platformUrl,
134
- name: config.name,
172
+ if (!Custom) return /* @__PURE__ */ jsx(DefaultShell, {
173
+ name: serverName,
135
174
  icon: config.icon,
136
175
  subtitle: config.subtitle,
137
176
  buttonText: config.buttonText,
@@ -155,8 +194,12 @@ function rootFor(config, platformUrl) {
155
194
  *
156
195
  * **A custom component:** pass `component` and it is rendered inside the same
157
196
  * providers instead of the default shell — beside a `sidebar` if one is given,
158
- * in the same {@link SidebarLayout}. A provided `name` then also sets
159
- * `document.title`, there being no shell header to show it in.
197
+ * in the same {@link SidebarLayout}. The page title is the HTML's own; a
198
+ * custom component that wants another sets `document.title` itself.
199
+ *
200
+ * The agent's name on the start card and in the header, and each tool's icon
201
+ * and label, are what the agent declared (`agent({ name })`, `tool({ ui })`),
202
+ * read from its `GET /client-config` body — not options here.
160
203
  *
161
204
  * Mounts into `target` — a CSS selector or DOM element, defaulting to
162
205
  * `"#app"` — and throws `Element not found: <target>` when the selector
@@ -171,10 +214,8 @@ function rootFor(config, platformUrl) {
171
214
  * }
172
215
  *
173
216
  * mountClient({
174
- * name: "Pizza Ordering",
175
217
  * theme: { bg: "#1a1a1a", primary: "#e55" },
176
218
  * sidebar: OrderPanel,
177
- * tools: { add_pizza: { icon: "🍕", label: "Adding pizza" } },
178
219
  * });
179
220
  * ```
180
221
  *
@@ -216,12 +257,12 @@ function mountClientWith(config, createSession) {
216
257
  token: config.token,
217
258
  WebSocket: config.WebSocket
218
259
  });
219
- setPageTitle(config.name);
220
- const rootNode = rootFor(config, platformUrl);
221
- const toolConfig = config.tools ?? {};
222
260
  return {
223
261
  session,
224
- ...mountRoot(container, createElement(ToolConfigContext.Provider, { value: toolConfig }, createElement(ThemeProvider, { value: config.theme }, createElement(SessionProvider, { value: session }, rootNode))), () => session[Symbol.dispose]())
262
+ ...mountRoot(container, createElement(SessionProvider, { value: session }, createElement(ClientRoot, {
263
+ config,
264
+ platformUrl
265
+ })), () => session[Symbol.dispose]())
225
266
  };
226
267
  }
227
268
  //#endregion
@@ -0,0 +1,49 @@
1
+ /**
2
+ * `dictationTranscriber(url)` — the `transcribe` callback `useDictation` needs,
3
+ * for a server answering the SDK's `handleDictationRequest`.
4
+ *
5
+ * Every page that dictates writes the same few lines: POST the clip, read
6
+ * `{ text }`, and turn a refusal into an error whose message is the SERVER's
7
+ * sentence ("Recording too long — keep it under 120 seconds", "Transcription
8
+ * is rate limited — try again shortly") rather than a bare status. This is
9
+ * those lines, against the one reply shape the SDK route answers with.
10
+ */
11
+ /**
12
+ * Options for {@link dictationTranscriber}.
13
+ *
14
+ * @input
15
+ */
16
+ export type DictationTranscriberOptions = {
17
+ /**
18
+ * Headers sent with each clip — an `authorization` for a route behind a
19
+ * bearer. A FUNCTION is read per request, so a token that rotates is never
20
+ * sent stale.
21
+ */
22
+ headers?: Record<string, string> | (() => Record<string, string>);
23
+ /** The transport. Defaults to the global `fetch`. */
24
+ fetch?: typeof fetch;
25
+ };
26
+ /**
27
+ * A `transcribe` for `useDictation` that POSTs each clip to `url` and
28
+ * reads the `{ text } | { error }` reply `handleDictationRequest` answers with.
29
+ *
30
+ * Rejects with the server's own `error` sentence on a refusal, and with a
31
+ * status-naming message when the reply is not that shape (a proxy's HTML error
32
+ * page) — `useDictation` shows either as its `error`.
33
+ *
34
+ * @param url - The route, resolved like any `fetch` URL (relative to the page).
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * import { dictationTranscriber } from "@alexkroman1/aai-ui";
39
+ *
40
+ * export const transcribe = dictationTranscriber("/api/dictation", {
41
+ * headers: () => ({ authorization: `Bearer ${localStorage.getItem("token") ?? ""}` }),
42
+ * });
43
+ * ```
44
+ *
45
+ * @public
46
+ */
47
+ export declare function dictationTranscriber(url: string, options?: DictationTranscriberOptions): (audio: Blob, options: {
48
+ signal: AbortSignal;
49
+ }) => Promise<string>;
@@ -1,4 +1,4 @@
1
- import { useTheme } from "./context.js";
1
+ import { u as useTheme } from "./context-BF0KsI9X.js";
2
2
  import clsx from "clsx";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region src/components/eyebrow.tsx
@@ -1,5 +1,5 @@
1
- import { a as tryParseJSON } from "./_utils-Mi-SCFA1.js";
2
- import { useSessionSelector } from "./context.js";
1
+ import { a as tryParseJSON } from "./_utils-BlZBJPdj.js";
2
+ import { c as useSessionSelector } from "./context-BF0KsI9X.js";
3
3
  import { useEffect, useMemo, useRef } from "react";
4
4
  //#region src/agent-state.ts
5
5
  /** One stable selector per slot name — see {@link selectAgentState}. */
package/dist/hooks.js CHANGED
@@ -1,3 +1,2 @@
1
- import "./context.js";
2
- import { a as useAgentState, i as selectAgentState, n as useToolCallStart, r as useToolResult, t as useEvent } from "./hooks-DN4gHYsj.js";
1
+ import { a as useAgentState, i as selectAgentState, n as useToolCallStart, r as useToolResult, t as useEvent } from "./hooks-1CoQY_Fc.js";
3
2
  export { selectAgentState, useAgentState, useEvent, useToolCallStart, useToolResult };
@@ -37,6 +37,7 @@ import { type InboxClientFrame, type InboxServerFrame } from "@alexkroman1/aai/p
37
37
  * One notice from the agent — what a workflow step sent with
38
38
  * `stepNotifyClient`, e.g. a reminder coming due.
39
39
  *
40
+ * @sealed
40
41
  * @public
41
42
  */
42
43
  export type InboxNotice = {
@@ -57,6 +58,11 @@ export type InboxNotice = {
57
58
  * for events: every session bound to the client, this tab's own included —
58
59
  * filter on `sessionId` (`useSessionId()`) to show only the OTHER ones.
59
60
  *
61
+ * `"other"` is a frame this version does not know (`frameType` is the wire
62
+ * `type` it arrived with) — a member from the start so that a frame the server
63
+ * adds later reaches an existing `switch`'s `default`, not a compile error.
64
+ * Ignore it.
65
+ *
60
66
  * @public
61
67
  */
62
68
  export type InboxEvent = {
@@ -69,6 +75,9 @@ export type InboxEvent = {
69
75
  } | {
70
76
  readonly type: "session_ended";
71
77
  readonly sessionId: string;
78
+ } | {
79
+ readonly type: "other";
80
+ readonly frameType: string;
72
81
  };
73
82
  /**
74
83
  * The largest notice taken: 60 s of 16 kHz PCM16, the firmware's
@@ -103,10 +112,11 @@ export type AssemblerOutput = {
103
112
  */
104
113
  export declare function parseNoticeHeader(json: string): NoticeHeader | undefined;
105
114
  /**
106
- * A live-event frame, or undefined for anything else (a notice header, say).
107
- * The wire's live frames are returned as the published {@link InboxEvent}, so
108
- * that view cannot drift from what the server sends without this failing to
109
- * compile.
115
+ * A live-event frame, or undefined for a notice header or a frame that is not
116
+ * one at all. The wire's live frames are returned as the published
117
+ * {@link InboxEvent}, so that view cannot drift from what the server sends
118
+ * without this failing to compile; a well-formed frame of a type this version
119
+ * does not know is `{ type: "other" }`.
110
120
  */
111
121
  export declare function parseInboxEvent(json: string): InboxEvent | undefined;
112
122
  /**
package/dist/inbox.d.ts CHANGED
@@ -44,6 +44,7 @@ export declare const INBOX_RECONNECT_MAX_MS = 30000;
44
44
  /**
45
45
  * Options for {@link createInbox}.
46
46
  *
47
+ * @input
47
48
  * @public
48
49
  */
49
50
  export type CreateInboxOptions = {
package/dist/index.d.ts CHANGED
@@ -63,7 +63,8 @@
63
63
  */
64
64
  export { type ClientRun, type ClientRunStatus, type ClientRunsResponse, errorMessage, } from "@alexkroman1/aai";
65
65
  export { AGENT_STATE_LABELS } from "./agent-state-labels.ts";
66
- export { type ClientConfigResponse, fetchClientConfig, } from "./client-config.ts";
66
+ export { appendDictation } from "./append-dictation.ts";
67
+ export { type ClientConfigResponse, type FetchClientConfigOptions, fetchClientConfig, } from "./client-config.ts";
67
68
  export { browserClientId, type SessionIdentity } from "./client-identity.ts";
68
69
  export { useClientTool } from "./client-tool.ts";
69
70
  export { AudioResult, type AudioResultCaptions, type AudioResultProps, } from "./components/audio-result.tsx";
@@ -75,18 +76,17 @@ export { ConsoleShell, type ConsoleShellProps } from "./components/console-shell
75
76
  export { Controls, type ControlsProps } from "./components/controls.tsx";
76
77
  export { ConversationView, type ConversationViewProps, } from "./components/conversation-view.tsx";
77
78
  export { Facts, type FactsProps } from "./components/facts.tsx";
78
- export { CheckboxField, Field, type FieldShell, FileField, type FileReadMode, type FileValue, Form, type FormProps, type FormValues, NumberField, SelectField, SubmitButton, TextAreaField, TextField, } from "./components/form.tsx";
79
+ export { CheckboxField, Field, type FieldShell, FileField, type FileReadMode, type FileValue, type FileValueShape, Form, type FormProps, type FormValues, isFileValue, type NamedTextValue, NumberField, SelectField, SubmitButton, TextAreaField, TextField, type TextSplitMode, } from "./components/form.tsx";
79
80
  export { Markdown, type MarkdownProps, type MarkdownVariant } from "./components/markdown.tsx";
80
81
  export { MessageList, type MessageListProps } from "./components/message-list.tsx";
81
82
  export { type SessionControlAction, type SessionControlButton, SessionControls, type SessionControlsLabels, type SessionControlsProps, } from "./components/session-controls.tsx";
82
83
  export { SessionErrorBanner, type SessionErrorBannerProps, } from "./components/session-error-banner.tsx";
83
- export { SessionStateDot, type SessionStateDotProps, } from "./components/session-state-dot.tsx";
84
+ export { SessionStateDot, type SessionStateDotColors, type SessionStateDotGroup, type SessionStateDotProps, } from "./components/session-state-dot.tsx";
84
85
  export { SidebarLayout } from "./components/sidebar-layout.tsx";
85
86
  export { StartScreen } from "./components/start-screen.tsx";
86
87
  export { ToolCallRow, type ToolCallRowProps, type ToolCallRowVariant, } from "./components/tool-call-row.tsx";
87
- export type { ToolDisplayConfig } from "./components/tool-config-context.ts";
88
88
  export { UploadProgressBar } from "./components/upload-progress.tsx";
89
- export { WorkflowFields } from "./components/workflow-fields.tsx";
89
+ export { WorkflowFields, type WorkflowFieldsProps } from "./components/workflow-fields.tsx";
90
90
  export { WorkflowPendingNote, type WorkflowPendingNoteProps, } from "./components/workflow-pending-note.tsx";
91
91
  export { WorkflowProgress } from "./components/workflow-progress.tsx";
92
92
  export { WorkflowRunError, type WorkflowRunErrorProps, } from "./components/workflow-run-error.tsx";
@@ -96,6 +96,7 @@ export { useSession, useSessionActions, useSessionError, useSessionSelector, use
96
96
  export { type ConversationLogEntry, inboxEventToItem } from "./conversation-log.ts";
97
97
  export type { ClientConfig, ClientHandle } from "./define-client.tsx";
98
98
  export { mountClient } from "./define-client.tsx";
99
+ export { type DictationTranscriberOptions, dictationTranscriber } from "./dictation-transcriber.ts";
99
100
  export { selectAgentState, useAgentState, useEvent, useToolCallStart, useToolResult, } from "./hooks.ts";
100
101
  export { type CreateInboxOptions, createInbox, type Inbox } from "./inbox.ts";
101
102
  export type { InboxEvent, InboxNotice } from "./inbox-protocol.ts";
@@ -106,11 +107,12 @@ export { type RouteFetchOptions, type RouteMethod, routeFetch } from "./route-fe
106
107
  export type { AgentCustomEvent, AgentStateFrame, BrowserSession, browserSessionBrand, SendTextOptions, SessionSnapshot, ToolCallOutcome, UserTurnControls, } from "./session/index.ts";
107
108
  export { createBrowserSession } from "./session/index.ts";
108
109
  export { createStoredValue, type StoredValue, type StoredValueOptions, useStoredValue, } from "./stored-value.ts";
109
- export type { AgentState, ChatMessage, ClientTheme, SessionError, SessionErrorCode, ToolCallInfo, VoiceSessionOptions, WebSocketConstructor, } from "./types.ts";
110
+ export type { AgentState, ChatMessage, ClientTheme, ClientThemePreset, ClientThemeTokens, ResolvedClientTheme, SessionError, SessionErrorCode, ToolCallInfo, VoiceSessionOptions, WebSocketConstructor, } from "./types.ts";
110
111
  export { type UseClientRunsOptions, type UseClientRunsResult, useClientRuns, } from "./use-client-runs.ts";
111
112
  export { type ConversationItem, type UseConversationResult, useConversation, } from "./use-conversation.ts";
112
113
  export { type UseConversationLogOptions, type UseConversationLogResult, useConversationLog, } from "./use-conversation-log.ts";
113
114
  export { type UseCopyResult, useCopy } from "./use-copy.ts";
115
+ export { type UseDictationOptions, type UseDictationResult, useDictation, } from "./use-dictation.ts";
114
116
  export { type UseDownloadUrlOptions, type UseDownloadUrlResult, useDownloadUrl, } from "./use-download-url.ts";
115
117
  export { type UseFlashResult, useFlash } from "./use-flash.ts";
116
118
  export { type UseInboxOptions, type UseInboxResult, useInbox } from "./use-inbox.ts";
@@ -122,13 +124,14 @@ export { type UseSessionControlsResult, useSessionControls } from "./use-session
122
124
  export { useClientId, useSessionId } from "./use-session-id.ts";
123
125
  export { type UseTapToTalkOptions, type UseTapToTalkResult, useTapToTalk, } from "./use-tap-to-talk.ts";
124
126
  export { type UseUserTranscriptResult, useUserTranscript } from "./use-user-transcript.ts";
125
- export { type UploadStatus, type UseWorkflowSubmitOptions, useWorkflowSubmit, type WorkflowSubmission, } from "./use-workflow-form.ts";
127
+ export { type UseWorkflowSubmitOptions, useWorkflowSubmit } from "./use-workflow-form.ts";
126
128
  export { type UseWorkflowProgressResult, useWorkflowProgress, } from "./use-workflow-progress.ts";
127
129
  export { type UseWorkflowRunResult, useWorkflowRun } from "./use-workflow-run.ts";
128
130
  export { type UseWorkflowRunsOptions, type UseWorkflowRunsResult, useWorkflowRuns, } from "./use-workflow-runs.ts";
129
131
  export { type UseWorkflowStreamOptions, useWorkflowStream, type WorkflowStreamSubmission, } from "./use-workflow-stream.ts";
130
132
  export { type UseWorkflowsOptions, type UseWorkflowsResult, useWorkflows, } from "./use-workflows.ts";
131
133
  export { type AgentClient, createWorkflowApi, isTerminal, type WorkflowApi, type WorkflowApiOptions, type WorkflowInputOf, type WorkflowOutputOf, type WorkflowRun, type WorkflowRunStatus, type WorkflowSummary, } from "./workflow-client.ts";
132
- export type { SubmitInputOf } from "./workflow-def-types.ts";
133
- export { fieldKindFor, type WorkflowFieldKind } from "./workflow-field-kind.ts";
134
+ export type { SubmitInputOf, WorkflowAppLike, WorkflowDefOf, WorkflowNameOf, WorkflowsOf, } from "./workflow-def-types.ts";
135
+ export { fieldKindFor, type WorkflowFieldKind, type WorkflowFieldRender, } from "./workflow-field-kind.ts";
134
136
  export { WORKFLOW_STATUS_LABELS } from "./workflow-status-labels.ts";
137
+ export type { UploadStatus, WorkflowSubmission, WorkflowSubmissionOf, WorkflowSubmissionScope, WorkflowSubmissionTiming, } from "./workflow-submission.ts";