@alexkroman1/aai-ui 13.2.0 → 14.0.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 (83) hide show
  1. package/README.md +159 -69
  2. package/dist/{_colors-j8XMToi9.js → _colors-CpZO-88A.js} +25 -2
  3. package/dist/{_module-url-C_4gRVL0.js → _module-url-C13kAJ87.js} +1 -1
  4. package/dist/_recover-run.d.ts +13 -7
  5. package/dist/_submission-state.d.ts +92 -0
  6. package/dist/_upload-files.d.ts +2 -2
  7. package/dist/_upload-report.d.ts +26 -0
  8. package/dist/{_utils-B6498_bm.js → _utils-DnQDM9Uy.js} +4 -4
  9. package/dist/_utils.d.ts +3 -3
  10. package/dist/_web-storage.d.ts +43 -0
  11. package/dist/_workflow-files.d.ts +1 -1
  12. package/dist/{aai-logo-CXZGPSIY.js → aai-logo-CFlomZlS.js} +1 -1
  13. package/dist/agent-state-labels.d.ts +60 -0
  14. package/dist/audio.js +21 -15
  15. package/dist/{chat-view-DDTtrh7N.js → chat-view-C_3T7Ln8.js} +100 -33
  16. package/dist/{client-config-BT_kWID5.js → client-config-DJQHnYjm.js} +5 -5
  17. package/dist/client-config.d.ts +4 -4
  18. package/dist/client-dir.d.ts +1 -1
  19. package/dist/client-dir.js +2 -2
  20. package/dist/components/_colors.d.ts +23 -0
  21. package/dist/components/_form-readiness.d.ts +1 -1
  22. package/dist/components/bullet-list.d.ts +74 -0
  23. package/dist/components/button.js +4 -4
  24. package/dist/components/chat-view.js +1 -1
  25. package/dist/components/console-shell.d.ts +16 -20
  26. package/dist/components/controls.js +4 -4
  27. package/dist/components/facts.d.ts +81 -0
  28. package/dist/components/form-fields.d.ts +6 -6
  29. package/dist/components/form-types.d.ts +1 -1
  30. package/dist/components/form.d.ts +1 -1
  31. package/dist/components/message-list.js +1 -1
  32. package/dist/components/session-error-banner.d.ts +69 -0
  33. package/dist/components/sidebar-layout.js +1 -1
  34. package/dist/components/start-screen.js +4 -4
  35. package/dist/components/tool-call-block.js +1 -1
  36. package/dist/components/tool-config-context.d.ts +1 -1
  37. package/dist/components/workflow-progress.d.ts +11 -4
  38. package/dist/context.d.ts +142 -19
  39. package/dist/context.js +156 -18
  40. package/dist/default-client/assets/{audio-BuDICbPf.js → audio-9zQsNc1w.js} +1 -1
  41. package/dist/default-client/assets/index-BTv30Z4F.css +2 -0
  42. package/dist/default-client/assets/index-RAZ-29Sz.js +284 -0
  43. package/dist/default-client/index.html +2 -2
  44. package/dist/default-client.d.ts +1 -1
  45. package/dist/define-client.d.ts +19 -19
  46. package/dist/define-client.js +20 -20
  47. package/dist/{eyebrow-C6ZFuiz6.js → eyebrow-UfmSz9yy.js} +1 -1
  48. package/dist/hooks.d.ts +44 -8
  49. package/dist/hooks.js +20 -14
  50. package/dist/index.d.ts +13 -8
  51. package/dist/index.js +1447 -1160
  52. package/dist/internal.d.ts +2 -2
  53. package/dist/internal.js +5 -5
  54. package/dist/{message-list-BJYyuIcR.js → message-list-CdOnSh5m.js} +23 -16
  55. package/dist/page.d.ts +11 -11
  56. package/dist/session-core-audio-setup.d.ts +1 -1
  57. package/dist/session-core-dial.d.ts +0 -2
  58. package/dist/{session-core-DxBYsfHA.js → session-core-gwePM95B.js} +135 -62
  59. package/dist/session-core-messages.d.ts +2 -2
  60. package/dist/session-core-types.d.ts +58 -1
  61. package/dist/session-core.d.ts +6 -6
  62. package/dist/session-core.js +2 -2
  63. package/dist/session-resume-store.d.ts +3 -3
  64. package/dist/{tool-call-block-tcPQAkcP.js → tool-call-block-C2t_5fpp.js} +30 -12
  65. package/dist/{tool-config-context-DzAofqi_.js → tool-config-context-Es4YUzV2.js} +2 -2
  66. package/dist/types.d.ts +19 -4
  67. package/dist/types.js +3 -3
  68. package/dist/{url-chips-YqhCjWfQ.js → url-chips-BxhzZgk2.js} +5 -5
  69. package/dist/use-conversation.d.ts +1 -1
  70. package/dist/use-run-key.d.ts +44 -10
  71. package/dist/{use-user-transcript-C14qWFu2.js → use-user-transcript-uyHhzy4d.js} +4 -3
  72. package/dist/use-workflow-form.d.ts +64 -91
  73. package/dist/{use-workflow-progress-Cu0SxMyg.js → use-workflow-run-CP2ekKPV.js} +254 -257
  74. package/dist/use-workflow-stream.d.ts +5 -2
  75. package/dist/use-workflows.d.ts +77 -0
  76. package/dist/workflow-client.d.ts +1 -1
  77. package/dist/worklets/capture-processor.js +2 -2
  78. package/dist/worklets/playback-processor.js +2 -2
  79. package/package.json +6 -6
  80. package/styles.css +78 -0
  81. package/dist/default-client/assets/index-B1_ROnTJ.js +0 -284
  82. package/dist/default-client/assets/index-S5fkKi6B.css +0 -2
  83. package/dist/tsdown.config.d.ts +0 -2
@@ -6,9 +6,9 @@
6
6
  <title>aai</title>
7
7
  <link rel="icon" href="./favicon.ico" />
8
8
  <style>html, body { background: #FBF8F2; margin: 0; }</style>
9
- <script type="module" crossorigin src="./assets/index-B1_ROnTJ.js"></script>
9
+ <script type="module" crossorigin src="./assets/index-RAZ-29Sz.js"></script>
10
10
  <link rel="modulepreload" crossorigin href="./assets/client-audio-constants-CP13UQZt.js">
11
- <link rel="stylesheet" crossorigin href="./assets/index-S5fkKi6B.css">
11
+ <link rel="stylesheet" crossorigin href="./assets/index-BTv30Z4F.css">
12
12
  </head>
13
13
  <body>
14
14
  <main id="app"></main>
@@ -1,2 +1,2 @@
1
1
  /** @jsxImportSource react */
2
- import "./styles.css";
2
+ import "../styles.css";
@@ -1,16 +1,16 @@
1
1
  /** @jsxImportSource react */
2
2
  import { type ComponentType, type ReactNode } from "react";
3
3
  import { type ToolDisplayConfig } from "./components/tool-config-context.ts";
4
- import type { SessionCore } from "./session-core-types.ts";
4
+ import type { BrowserSession } from "./session-core-types.ts";
5
5
  import type { ClientTheme, VoiceSessionOptions } from "./types.ts";
6
6
  /**
7
- * Configuration passed to {@link client}.
7
+ * Configuration passed to {@link mountClient}.
8
8
  *
9
9
  * The session-forwarded fields are picked from {@link VoiceSessionOptions}
10
10
  * (one source of truth for types and docs) rather than re-declared — a
11
11
  * re-declared copy is exactly how doc comments drift. It is NOT the session's
12
12
  * own options type: that is {@link VoiceSessionOptions}, which
13
- * `createSessionCore` takes and which three of these fields come from.
13
+ * `createBrowserSession` takes and which three of these fields come from.
14
14
  *
15
15
  * @remarks
16
16
  * **One flat type, not a union of tiers.** `component` is what decides which
@@ -19,12 +19,12 @@ import type { ClientTheme, VoiceSessionOptions } from "./types.ts";
19
19
  * and that decision is made at runtime, where every field can be honoured. It
20
20
  * used to be a union whose two arms banned each other's fields with `?: never`,
21
21
  * and the failure that shape produces is recorded twice in this file's history:
22
- * `client({ name, component })` and `client({ component, tools })` were both
22
+ * `mountClient({ name, component })` and `mountClient({ component, tools })` were both
23
23
  * the natural thing to write, both were refused with *"Type 'string' is not
24
24
  * assignable to type 'undefined'"*, and both cost a build round each time
25
25
  * before the ban was lifted. What was left banned was `sidebar` beside a
26
26
  * `component`, which invited the identical failure for a combination
27
- * {@link client} can simply render.
27
+ * {@link mountClient} can simply render.
28
28
  *
29
29
  * @public
30
30
  */
@@ -81,7 +81,7 @@ export type ClientConfig = Pick<VoiceSessionOptions, "onSessionId" | "resumeSess
81
81
  /**
82
82
  * Tool display config: icon and label overrides keyed by tool name.
83
83
  *
84
- * Honoured with a custom `component` too: {@link client} installs it into
84
+ * Honoured with a custom `component` too: {@link mountClient} installs it into
85
85
  * `ToolConfigContext`, and the consumer is `ToolCallBlock` — which a custom
86
86
  * component renders as soon as it uses `MessageList` or `ChatView`, the usual
87
87
  * way to build one.
@@ -89,7 +89,7 @@ export type ClientConfig = Pick<VoiceSessionOptions, "onSessionId" | "resumeSess
89
89
  tools?: ToolDisplayConfig;
90
90
  };
91
91
  /**
92
- * Handle returned by {@link client} for cleanup.
92
+ * Handle returned by {@link mountClient} for cleanup.
93
93
  *
94
94
  * Implements `Disposable` so it can be used with `using`.
95
95
  *
@@ -97,7 +97,7 @@ export type ClientConfig = Pick<VoiceSessionOptions, "onSessionId" | "resumeSess
97
97
  */
98
98
  export type ClientHandle = {
99
99
  /** The underlying session core. */
100
- session: SessionCore;
100
+ session: BrowserSession;
101
101
  /** Unmount the UI and disconnect the session. */
102
102
  dispose(): void;
103
103
  /** Alias for `dispose` for use with `using`. */
@@ -106,7 +106,7 @@ export type ClientHandle = {
106
106
  /**
107
107
  * The element a mount renders into.
108
108
  *
109
- * Exported so `page()` resolves its target the same way `client()` does — the
109
+ * Exported so `mountPage()` resolves its target the same way `mountClient()` does — the
110
110
  * default selector and the "element not found" sentence are part of what an
111
111
  * author has learned, and a second copy is how the two mounts come to disagree
112
112
  * about which one they were given.
@@ -120,7 +120,7 @@ export declare function resolveContainer(target?: string | HTMLElement): HTMLEle
120
120
  * @internal
121
121
  */
122
122
  export type MountedRoot = {
123
- /** Unmount the React tree (and, for `client()`, dispose the session). */
123
+ /** Unmount the React tree (and, for `mountClient()`, dispose the session). */
124
124
  dispose(): void;
125
125
  /** Alias for `dispose` for use with `using`. */
126
126
  [Symbol.dispose](): void;
@@ -128,15 +128,15 @@ export type MountedRoot = {
128
128
  /**
129
129
  * Render `node` into `container` and hand back its teardown.
130
130
  *
131
- * Shared by {@link client} and `page()` because the plumbing is identical and
131
+ * Shared by {@link mountClient} and `mountPage()` because the plumbing is identical and
132
132
  * the two decisions in it are not obvious enough to be re-derived: the root is
133
133
  * created here rather than by the caller so nothing else can hold one, and the
134
134
  * render is `flushSync` so the mount is observable to the caller's NEXT
135
- * STATEMENT (and to a test) rather than scheduled — `client()` returns a handle
136
- * whose session is expected to be live, and `page()` returns one a caller may
135
+ * STATEMENT (and to a test) rather than scheduled — `mountClient()` returns a handle
136
+ * whose session is expected to be live, and `mountPage()` returns one a caller may
137
137
  * dispose immediately.
138
138
  *
139
- * `onDispose` runs after the unmount, which is the order `client()` needs: the
139
+ * `onDispose` runs after the unmount, which is the order `mountClient()` needs: the
140
140
  * tree comes down before the session under it goes away.
141
141
  *
142
142
  * @internal
@@ -159,13 +159,13 @@ export declare function mountRoot(container: HTMLElement, node: ReactNode, onDis
159
159
  *
160
160
  * @example The default shell
161
161
  * ```tsx
162
- * import { client } from "@alexkroman1/aai-ui";
162
+ * import { mountClient } from "@alexkroman1/aai-ui";
163
163
  *
164
164
  * function OrderPanel() {
165
165
  * return <div>Cart</div>;
166
166
  * }
167
167
  *
168
- * client({
168
+ * mountClient({
169
169
  * name: "Pizza Ordering",
170
170
  * theme: { bg: "#1a1a1a", primary: "#e55" },
171
171
  * sidebar: OrderPanel,
@@ -175,14 +175,14 @@ export declare function mountRoot(container: HTMLElement, node: ReactNode, onDis
175
175
  *
176
176
  * @example A custom component
177
177
  * ```tsx
178
- * import { client, useSession } from "@alexkroman1/aai-ui";
178
+ * import { mountClient, useSession } from "@alexkroman1/aai-ui";
179
179
  *
180
180
  * function MyCustomApp() {
181
181
  * const session = useSession();
182
182
  * return <div>{session.state}</div>;
183
183
  * }
184
184
  *
185
- * client({ component: MyCustomApp });
185
+ * mountClient({ component: MyCustomApp });
186
186
  * ```
187
187
  *
188
188
  * @returns A {@link ClientHandle} for cleanup.
@@ -190,4 +190,4 @@ export declare function mountRoot(container: HTMLElement, node: ReactNode, onDis
190
190
  *
191
191
  * @public
192
192
  */
193
- export declare function client(config: ClientConfig): ClientHandle;
193
+ export declare function mountClient(config: ClientConfig): ClientHandle;
@@ -1,21 +1,21 @@
1
- import { n as fetchClientConfig } from "./client-config-BT_kWID5.js";
1
+ import { n as fetchClientConfig } from "./client-config-DJQHnYjm.js";
2
2
  import { SessionProvider, ThemeProvider } from "./context.js";
3
- import { t as ChatView } from "./chat-view-DDTtrh7N.js";
4
- import { n as setPageTitle, t as pageBaseUrl } from "./_utils-B6498_bm.js";
5
- import { t as ToolConfigContext } from "./tool-config-context-DzAofqi_.js";
3
+ import { t as ChatView } from "./chat-view-C_3T7Ln8.js";
4
+ import { n as setPageTitle, t as pageBaseUrl } from "./_utils-DnQDM9Uy.js";
5
+ import { t as ToolConfigContext } from "./tool-config-context-Es4YUzV2.js";
6
6
  import { SidebarLayout } from "./components/sidebar-layout.js";
7
7
  import { StartScreen } from "./components/start-screen.js";
8
- import { t as createSessionCore } from "./session-core-DxBYsfHA.js";
8
+ import { t as createBrowserSession } from "./session-core-gwePM95B.js";
9
9
  import { jsx } from "react/jsx-runtime";
10
10
  import { createElement, useEffect, useState } from "react";
11
11
  import { flushSync } from "react-dom";
12
12
  import { createRoot } from "react-dom/client";
13
- //#region define-client.tsx
13
+ //#region src/define-client.tsx
14
14
  /** @jsxImportSource react */
15
15
  /**
16
16
  * The element a mount renders into.
17
17
  *
18
- * Exported so `page()` resolves its target the same way `client()` does — the
18
+ * Exported so `mountPage()` resolves its target the same way `mountClient()` does — the
19
19
  * default selector and the "element not found" sentence are part of what an
20
20
  * author has learned, and a second copy is how the two mounts come to disagree
21
21
  * about which one they were given.
@@ -31,15 +31,15 @@ function resolveContainer(target = "#app") {
31
31
  /**
32
32
  * Render `node` into `container` and hand back its teardown.
33
33
  *
34
- * Shared by {@link client} and `page()` because the plumbing is identical and
34
+ * Shared by {@link mountClient} and `mountPage()` because the plumbing is identical and
35
35
  * the two decisions in it are not obvious enough to be re-derived: the root is
36
36
  * created here rather than by the caller so nothing else can hold one, and the
37
37
  * render is `flushSync` so the mount is observable to the caller's NEXT
38
- * STATEMENT (and to a test) rather than scheduled — `client()` returns a handle
39
- * whose session is expected to be live, and `page()` returns one a caller may
38
+ * STATEMENT (and to a test) rather than scheduled — `mountClient()` returns a handle
39
+ * whose session is expected to be live, and `mountPage()` returns one a caller may
40
40
  * dispose immediately.
41
41
  *
42
- * `onDispose` runs after the unmount, which is the order `client()` needs: the
42
+ * `onDispose` runs after the unmount, which is the order `mountClient()` needs: the
43
43
  * tree comes down before the session under it goes away.
44
44
  *
45
45
  * @internal
@@ -90,7 +90,7 @@ function DefaultShell({ name, icon, subtitle, buttonText, Sidebar, ...layout })
90
90
  *
91
91
  * **The lookup is SKIPPED when the caller already named the agent.** The
92
92
  * response's only consumer here is the fallback below, so with an explicit
93
- * `client({ name })` the request was issued and its answer thrown away — and on
93
+ * `mountClient({ name })` the request was issued and its answer thrown away — and on
94
94
  * the platform this endpoint is the BROKER, so the discarded request is one that
95
95
  * can boot a sandbox. The session's own per-attempt lookup
96
96
  * (`session-core.ts`'s URL provider) is a different question and deliberately
@@ -122,7 +122,7 @@ function DefaultRoot({ platformUrl, ...display }) {
122
122
  *
123
123
  * A custom component owns the whole page, so there is no header to hang a
124
124
  * `sidebar` off — but the layout the default shell uses is right here, and
125
- * `client({ component, sidebar })` names one pane and one aside, which is
125
+ * `mountClient({ component, sidebar })` names one pane and one aside, which is
126
126
  * exactly what it renders. Honouring the combination rather than ignoring it is
127
127
  * the same call this file already made for `name` and `tools`.
128
128
  */
@@ -164,13 +164,13 @@ function rootFor(config, platformUrl) {
164
164
  *
165
165
  * @example The default shell
166
166
  * ```tsx
167
- * import { client } from "@alexkroman1/aai-ui";
167
+ * import { mountClient } from "@alexkroman1/aai-ui";
168
168
  *
169
169
  * function OrderPanel() {
170
170
  * return <div>Cart</div>;
171
171
  * }
172
172
  *
173
- * client({
173
+ * mountClient({
174
174
  * name: "Pizza Ordering",
175
175
  * theme: { bg: "#1a1a1a", primary: "#e55" },
176
176
  * sidebar: OrderPanel,
@@ -180,14 +180,14 @@ function rootFor(config, platformUrl) {
180
180
  *
181
181
  * @example A custom component
182
182
  * ```tsx
183
- * import { client, useSession } from "@alexkroman1/aai-ui";
183
+ * import { mountClient, useSession } from "@alexkroman1/aai-ui";
184
184
  *
185
185
  * function MyCustomApp() {
186
186
  * const session = useSession();
187
187
  * return <div>{session.state}</div>;
188
188
  * }
189
189
  *
190
- * client({ component: MyCustomApp });
190
+ * mountClient({ component: MyCustomApp });
191
191
  * ```
192
192
  *
193
193
  * @returns A {@link ClientHandle} for cleanup.
@@ -195,10 +195,10 @@ function rootFor(config, platformUrl) {
195
195
  *
196
196
  * @public
197
197
  */
198
- function client(config) {
198
+ function mountClient(config) {
199
199
  const container = resolveContainer(config.target);
200
200
  const platformUrl = config.platformUrl ?? pageBaseUrl();
201
- const session = createSessionCore({
201
+ const session = createBrowserSession({
202
202
  platformUrl,
203
203
  onSessionId: config.onSessionId,
204
204
  resumeSessionId: config.resumeSessionId,
@@ -213,4 +213,4 @@ function client(config) {
213
213
  };
214
214
  }
215
215
  //#endregion
216
- export { client, mountRoot, resolveContainer };
216
+ export { mountClient, mountRoot, resolveContainer };
@@ -1,7 +1,7 @@
1
1
  import { useTheme } from "./context.js";
2
2
  import clsx from "clsx";
3
3
  import { jsx } from "react/jsx-runtime";
4
- //#region components/eyebrow.tsx
4
+ //#region src/components/eyebrow.tsx
5
5
  /** @jsxImportSource react */
6
6
  /**
7
7
  * Eyebrow label — the design system's small outlined pill with ALL-CAPS,
package/dist/hooks.d.ts CHANGED
@@ -24,15 +24,26 @@ import type { ToolCallInfo } from "./types.ts";
24
24
  * }
25
25
  * ```
26
26
  *
27
- * @typeParam R - The result shape. Defaults to {@link DefaultToolResult}
28
- * (`any`) so the ordinary untyped spelling compiles; pass the shape —
29
- * `useToolResult<Quote>(…)` — for real checking.
27
+ * @typeParam R - The result shape. Defaults to `unknown`, NOT to
28
+ * {@link DefaultToolResult} (`any`): the return type is inferred perfectly
29
+ * at `tool()` and this hook is the one place a client reads it, so an `any`
30
+ * default threw the whole inference away exactly where it was wanted —
31
+ * `useToolResult("get_order", (r) => r.a.b.c.d.e)` reported nothing. It is
32
+ * the tool's own shape that belongs here, and the spelling that costs a
33
+ * browser bundle nothing is a TYPE-ONLY import of the tool module:
34
+ * `import type getOrder from "./tools/get_order.ts"` is erased, so
35
+ * `useToolResult<InferToolOutput<typeof getOrder>>(…)` pulls no host code
36
+ * into the client graph. `useToolResult<Quote>(…)` against a hand-written
37
+ * shape is the other spelling. {@link DefaultToolResult} itself stays `any`
38
+ * — see `ToolCallInfo.args` for why a value the framework cannot see is
39
+ * typed that way at REST; the argument does not extend to a call site whose
40
+ * whole job is to name the shape.
30
41
  * @param toolName - Only calls of this tool fire the callback.
31
42
  * @param callback - Called with the parsed result and the call itself.
32
43
  *
33
44
  * @public
34
45
  */
35
- export declare function useToolResult<R = DefaultToolResult>(toolName: string, callback: (result: R, toolCall: ToolCallInfo) => void): void;
46
+ export declare function useToolResult<R = unknown>(toolName: string, callback: (result: R, toolCall: ToolCallInfo) => void): void;
36
47
  /**
37
48
  * Fire a callback when ANY tool call settles — the tool's name is the
38
49
  * callback's first argument.
@@ -54,13 +65,16 @@ export declare function useToolResult<R = DefaultToolResult>(toolName: string, c
54
65
  * }
55
66
  * ```
56
67
  *
57
- * @typeParam R - The result shape. Defaults to {@link DefaultToolResult}.
68
+ * @typeParam R - The result shape. Defaults to `unknown`, for the reason the
69
+ * filtered overload's `@typeParam` gives. A log renderer is the one caller
70
+ * that legitimately wants no shape, and `unknown` is what it should say:
71
+ * `JSON.stringify(result)` takes it unchanged.
58
72
  * @param callback - Called with the tool's name, the parsed result, and the
59
73
  * call itself.
60
74
  *
61
75
  * @public
62
76
  */
63
- export declare function useToolResult<R = DefaultToolResult>(callback: (name: string, result: R, toolCall: ToolCallInfo) => void): void;
77
+ export declare function useToolResult<R = unknown>(callback: (name: string, result: R, toolCall: ToolCallInfo) => void): void;
64
78
  /**
65
79
  * The agent's projected session state, or `null` before the first push.
66
80
  *
@@ -198,12 +212,28 @@ export declare function useEvent<T = unknown>(event: string, callback: (data: T)
198
212
  * }
199
213
  * ```
200
214
  *
215
+ * @typeParam A - The tool's ARGUMENT shape. Defaults to
216
+ * `ToolCallInfo["args"]`, which is `Record<string, any>` — so an
217
+ * un-parameterized call behaves exactly as it always has, and
218
+ * `toolCall.args.totally_made_up_field` still compiles. That default is a
219
+ * property of {@link ToolCallInfo} rather than a choice made here (its doc
220
+ * carries the argument, and the escape hatch it recommends —
221
+ * `args as { url: string }` — is what this type parameter replaces); until
222
+ * that field is tightened there is nothing stricter for this hook to fall
223
+ * back to. What was missing was any way to opt IN: there was no type
224
+ * parameter at all, so a custom client could not check args even when it
225
+ * knew the shape. Name it — `useToolCallStart<{ query: string }>(…)` — or
226
+ * derive it from the tool with a TYPE-ONLY import, which is erased and so
227
+ * pulls no host code into the browser graph:
228
+ * `useToolCallStart<InferToolInput<typeof search>>("search", …)`.
201
229
  * @param toolName - Only calls of this tool fire the callback.
202
230
  * @param callback - Called with the pending call.
203
231
  *
204
232
  * @public
205
233
  */
206
- export declare function useToolCallStart(toolName: string, callback: (toolCall: ToolCallInfo) => void): void;
234
+ export declare function useToolCallStart<A = ToolCallInfo["args"]>(toolName: string, callback: (toolCall: Omit<ToolCallInfo, "args"> & {
235
+ args: A;
236
+ }) => void): void;
207
237
  /**
208
238
  * Fire a callback when ANY tool call starts — read the tool's name off the
209
239
  * call itself (`toolCall.name`).
@@ -220,8 +250,14 @@ export declare function useToolCallStart(toolName: string, callback: (toolCall:
220
250
  * }
221
251
  * ```
222
252
  *
253
+ * @typeParam A - The tool's ARGUMENT shape; see the filtered overload. On the
254
+ * unfiltered form every tool's call arrives, so naming one shape here is
255
+ * only right for a page that switches on `toolCall.name` and narrows it
256
+ * itself — the default is the honest answer for a log renderer.
223
257
  * @param callback - Called with the pending call.
224
258
  *
225
259
  * @public
226
260
  */
227
- export declare function useToolCallStart(callback: (toolCall: ToolCallInfo) => void): void;
261
+ export declare function useToolCallStart<A = ToolCallInfo["args"]>(callback: (toolCall: Omit<ToolCallInfo, "args"> & {
262
+ args: A;
263
+ }) => void): void;
package/dist/hooks.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { useSessionSelector } from "./context.js";
2
- import { i as tryParseJSON } from "./_utils-B6498_bm.js";
2
+ import { i as tryParseJSON } from "./_utils-DnQDM9Uy.js";
3
3
  import { useEffect, useMemo, useRef } from "react";
4
- //#region hooks.ts
4
+ //#region src/hooks.ts
5
5
  /** Index of the first item whose sequence number is above the watermark (tail scan from the end). */
6
6
  function tailStart(items, seqOf, watermark) {
7
7
  let start = items.length;
@@ -39,6 +39,19 @@ function processToolCallTail(toolCalls, cursor, isSettled, onNew) {
39
39
  }
40
40
  }
41
41
  /**
42
+ * The two `fire` implementations, at module scope so they are stable across
43
+ * renders — which is what lets `useToolCallEffect` name `fire` as a plain
44
+ * dependency instead of holding it in a ref.
45
+ */
46
+ const fireResult = (callback, tc, filtered) => {
47
+ const parsed = tryParseJSON(tc.result);
48
+ if (filtered) callback(parsed, tc);
49
+ else callback(tc.name, parsed, tc);
50
+ };
51
+ const fireStart = (callback, tc) => {
52
+ callback(tc);
53
+ };
54
+ /**
42
55
  * Shared scaffold for the tool-call lifecycle hooks: parses the optional
43
56
  * `(toolName, callback)` / `(callback)` overload args, dedups by call ID,
44
57
  * and invokes `fire` once per tool call reaching `status`.
@@ -55,28 +68,23 @@ function useToolCallEffect(status, args, fire) {
55
68
  const mountedRef = useRef(false);
56
69
  const callbackRef = useRef(callback);
57
70
  callbackRef.current = callback;
58
- const fireRef = useRef(fire);
59
- fireRef.current = fire;
60
71
  useEffect(() => {
61
72
  const firstRun = !mountedRef.current;
62
73
  mountedRef.current = true;
63
74
  processToolCallTail(toolCalls, cursorRef.current, (tc) => status === "pending" || tc.status === status, (tc) => {
64
75
  if (tc.status !== status && firstRun) return;
65
76
  if (filterName && tc.name !== filterName) return;
66
- fireRef.current(callbackRef.current, tc, filterName !== null);
77
+ fire(callbackRef.current, tc, filterName !== null);
67
78
  });
68
79
  }, [
69
80
  toolCalls,
70
81
  filterName,
71
- status
82
+ status,
83
+ fire
72
84
  ]);
73
85
  }
74
86
  function useToolResult(...args) {
75
- useToolCallEffect("done", args, (callback, tc, filtered) => {
76
- const parsed = tryParseJSON(tc.result);
77
- if (filtered) callback(parsed, tc);
78
- else callback(tc.name, parsed, tc);
79
- });
87
+ useToolCallEffect("done", args, fireResult);
80
88
  }
81
89
  function useAgentState(fallback) {
82
90
  const state = useSessionSelector((snapshot) => snapshot.agentState);
@@ -132,9 +140,7 @@ function useEvent(event, callback) {
132
140
  }, [customEvents, event]);
133
141
  }
134
142
  function useToolCallStart(...args) {
135
- useToolCallEffect("pending", args, (callback, tc) => {
136
- callback(tc);
137
- });
143
+ useToolCallEffect("pending", args, fireStart);
138
144
  }
139
145
  //#endregion
140
146
  export { useAgentState, useEvent, useToolCallStart, useToolResult };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,16 @@
1
+ export { AGENT_STATE_LABELS } from "./agent-state-labels.ts";
1
2
  export { type ClientConfigResponse, fetchClientConfig, } from "./client-config.ts";
2
3
  export { AutoScroll } from "./components/auto-scroll.tsx";
4
+ export { BulletList, type BulletListProps } from "./components/bullet-list.tsx";
3
5
  export { Button, type ButtonSize, type ButtonVariant } from "./components/button.tsx";
4
6
  export { ChatView } from "./components/chat-view.tsx";
5
7
  export { ConsoleShell, type ConsoleShellProps } from "./components/console-shell.tsx";
6
8
  export { Controls, type ControlsProps } from "./components/controls.tsx";
7
- export { CheckboxField, Field, type FieldShell, FileField, type FileRead, type FileValue, Form, type FormProps, type FormValues, NumberField, SelectField, SubmitButton, TextAreaField, TextField, } from "./components/form.tsx";
9
+ export { Facts, type FactsProps } from "./components/facts.tsx";
10
+ export { CheckboxField, Field, type FieldShell, FileField, type FileReadMode, type FileValue, Form, type FormProps, type FormValues, NumberField, SelectField, SubmitButton, TextAreaField, TextField, } from "./components/form.tsx";
8
11
  export { Markdown, type MarkdownProps, type MarkdownVariant } from "./components/markdown.tsx";
9
12
  export { MessageList, type MessageListProps } from "./components/message-list.tsx";
13
+ export { SessionErrorBanner, type SessionErrorBannerProps, } from "./components/session-error-banner.tsx";
10
14
  export { SidebarLayout } from "./components/sidebar-layout.tsx";
11
15
  export { StartScreen } from "./components/start-screen.tsx";
12
16
  export { ToolCallRow, type ToolCallRowProps, type ToolCallRowVariant, } from "./components/tool-call-row.tsx";
@@ -14,24 +18,25 @@ export type { ToolDisplayConfig } from "./components/tool-config-context.ts";
14
18
  export { UploadProgressBar } from "./components/upload-progress.tsx";
15
19
  export { WorkflowFields } from "./components/workflow-fields.tsx";
16
20
  export { WorkflowProgress } from "./components/workflow-progress.tsx";
17
- export type { Session } from "./context.ts";
18
- export { useSession, useSessionSelector, useTheme } from "./context.ts";
21
+ export type { Session, SessionActions } from "./context.ts";
22
+ export { useSession, useSessionActions, useSessionError, useSessionSelector, useSessionStatus, useTheme, } from "./context.ts";
19
23
  export type { ClientConfig, ClientHandle } from "./define-client.tsx";
20
- export { client } from "./define-client.tsx";
24
+ export { mountClient } from "./define-client.tsx";
21
25
  export { useAgentState, useEvent, useToolCallStart, useToolResult } from "./hooks.ts";
22
- export { type PageConfig, type PageHandle, page } from "./page.tsx";
23
- export { createSessionCore } from "./session-core.ts";
24
- export type { AgentCustomEvent, SessionCore, SessionSnapshot, } from "./session-core-types.ts";
26
+ export { mountPage, type PageConfig, type PageHandle } from "./page.tsx";
27
+ export { createBrowserSession } from "./session-core.ts";
28
+ export type { AgentCustomEvent, BrowserSession, SessionSnapshot, } from "./session-core-types.ts";
25
29
  export type { AgentState, ChatMessage, ClientTheme, SessionError, SessionErrorCode, ToolCallInfo, VoiceSessionOptions, WebSocketConstructor, } from "./types.ts";
26
30
  export { type ConversationItem, type UseConversationResult, useConversation, } from "./use-conversation.ts";
27
31
  export { type UseDownloadUrlOptions, type UseDownloadUrlResult, useDownloadUrl, } from "./use-download-url.ts";
28
32
  export { useRunKey } from "./use-run-key.ts";
29
33
  export { type UseUserTranscriptResult, useUserTranscript } from "./use-user-transcript.ts";
30
- export { type UploadStatus, type UseWorkflowSubmitOptions, type UseWorkflowsOptions, type UseWorkflowsResult, useWorkflowSubmit, useWorkflows, type WorkflowSubmission, } from "./use-workflow-form.ts";
34
+ export { type UploadStatus, type UseWorkflowSubmitOptions, useWorkflowSubmit, type WorkflowSubmission, } from "./use-workflow-form.ts";
31
35
  export { type UseWorkflowProgressResult, useWorkflowProgress, } from "./use-workflow-progress.ts";
32
36
  export { type UseWorkflowRunResult, useWorkflowRun } from "./use-workflow-run.ts";
33
37
  export { type UseWorkflowRunsOptions, type UseWorkflowRunsResult, useWorkflowRuns, } from "./use-workflow-runs.ts";
34
38
  export { type UseWorkflowStreamOptions, useWorkflowStream, type WorkflowStreamSubmission, } from "./use-workflow-stream.ts";
39
+ export { type UseWorkflowsOptions, type UseWorkflowsResult, useWorkflows, } from "./use-workflows.ts";
35
40
  export { createWorkflowApi, isTerminal, type WorkflowApi, type WorkflowApiOptions, type WorkflowInputOf, type WorkflowOutputOf, type WorkflowRun, type WorkflowRunStatus, type WorkflowSummary, } from "./workflow-client.ts";
36
41
  export type { SubmitInputOf } from "./workflow-def-types.ts";
37
42
  export { WORKFLOW_STATUS_LABELS } from "./workflow-status-labels.ts";