@alexkroman1/aai-ui 6.11.0 → 7.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 (66) hide show
  1. package/README.md +104 -3
  2. package/dist/_run-controls.d.ts +33 -0
  3. package/dist/{chat-view-ByQFf94G.js → chat-view-BKsFfFZJ.js} +57 -11
  4. package/dist/client-config-B4nznRvH.js +134 -0
  5. package/dist/client-config.d.ts +45 -2
  6. package/dist/client-dir.d.ts +3 -1
  7. package/dist/client-dir.js +3 -1
  8. package/dist/components/auto-scroll.d.ts +24 -13
  9. package/dist/components/button.d.ts +8 -4
  10. package/dist/components/button.js +4 -4
  11. package/dist/components/chat-view.d.ts +4 -3
  12. package/dist/components/chat-view.js +1 -1
  13. package/dist/components/console-shell.d.ts +71 -10
  14. package/dist/components/controls.d.ts +15 -4
  15. package/dist/components/controls.js +48 -2
  16. package/dist/components/form-fields.d.ts +142 -0
  17. package/dist/components/form-types.d.ts +6 -0
  18. package/dist/components/form.d.ts +38 -80
  19. package/dist/components/markdown.d.ts +31 -5
  20. package/dist/components/message-list.d.ts +21 -4
  21. package/dist/components/message-list.js +1 -1
  22. package/dist/components/sidebar-layout.d.ts +11 -0
  23. package/dist/components/sidebar-layout.js +2 -0
  24. package/dist/components/start-screen.d.ts +8 -0
  25. package/dist/components/start-screen.js +2 -0
  26. package/dist/components/tool-call-block.js +1 -1
  27. package/dist/components/tool-call-row.d.ts +24 -0
  28. package/dist/components/upload-progress.d.ts +17 -7
  29. package/dist/components/workflow-fields.d.ts +10 -22
  30. package/dist/components/workflow-progress.d.ts +29 -10
  31. package/dist/context.d.ts +36 -0
  32. package/dist/context.js +105 -14
  33. package/dist/default-client/assets/index-S5fkKi6B.css +2 -0
  34. package/dist/default-client/assets/index-fEkrcZgo.js +293 -0
  35. package/dist/default-client/index.html +2 -2
  36. package/dist/define-client.d.ts +67 -62
  37. package/dist/define-client.js +56 -22
  38. package/dist/hooks.d.ts +88 -3
  39. package/dist/index.d.ts +12 -11
  40. package/dist/index.js +501 -167
  41. package/dist/internal.d.ts +40 -0
  42. package/dist/internal.js +6 -0
  43. package/dist/{message-list-CpPV7dGx.js → message-list-DHddO4QC.js} +217 -72
  44. package/dist/{session-core-CAfYmUbg.js → session-core-C2JtLArh.js} +267 -165
  45. package/dist/session-core-audio-setup.d.ts +3 -0
  46. package/dist/session-core-messages.d.ts +3 -0
  47. package/dist/session-core-state.d.ts +146 -0
  48. package/dist/session-core-types.d.ts +77 -32
  49. package/dist/session-core.d.ts +3 -2
  50. package/dist/session-core.js +1 -1
  51. package/dist/{tool-call-block-D6pTEPrT.js → tool-call-block-DoF-cSIZ.js} +27 -19
  52. package/dist/tool-config-context-DzAofqi_.js +19 -0
  53. package/dist/types.d.ts +31 -5
  54. package/dist/types.js +5 -4
  55. package/dist/{controls-CjG91QJ4.js → url-chips-DpM7Oocj.js} +3 -46
  56. package/dist/use-conversation.d.ts +122 -0
  57. package/dist/use-download-url.d.ts +83 -0
  58. package/dist/use-workflow-form.d.ts +59 -3
  59. package/dist/use-workflow-run.d.ts +35 -0
  60. package/dist/use-workflow-stream.d.ts +36 -62
  61. package/dist/workflow-client.d.ts +36 -11
  62. package/dist/workflow-status-labels.d.ts +35 -0
  63. package/package.json +10 -5
  64. package/styles.css +14 -0
  65. package/dist/default-client/assets/index-DTLrhtTF.css +0 -2
  66. package/dist/default-client/assets/index-DXODx_9r.js +0 -293
@@ -46,6 +46,30 @@ export interface ToolCallRowProps {
46
46
  * Colors come from the nearest theme context (see {@link useTheme}); without
47
47
  * a provider the default AssemblyAI theme applies.
48
48
  *
49
+ * @example
50
+ * ```tsx
51
+ * import { ToolCallRow, useSession } from "@alexkroman1/aai-ui";
52
+ *
53
+ * // A custom chrome's tool log, from the snapshot's own `toolCalls`.
54
+ * function ToolLog() {
55
+ * const { toolCalls } = useSession();
56
+ * return (
57
+ * <div>
58
+ * {toolCalls.map((call) => (
59
+ * <ToolCallRow
60
+ * key={call.callId}
61
+ * title={call.name}
62
+ * detail={call.result}
63
+ * pending={call.status === "pending"}
64
+ * />
65
+ * ))}
66
+ * </div>
67
+ * );
68
+ * }
69
+ * ```
70
+ *
71
+ * @param props - See {@link ToolCallRowProps}.
72
+ *
49
73
  * @public
50
74
  */
51
75
  export declare function ToolCallRow({ title, detail, pending, icon, variant, className, children, }: ToolCallRowProps): ReactNode;
@@ -47,19 +47,29 @@ import type { UploadStatus } from "../use-workflow-form.ts";
47
47
  * }
48
48
  * ```
49
49
  *
50
- * @param upload - What `useWorkflowSubmit` reports. `undefined` renders nothing,
51
- * so a page may pass its state straight through.
52
- * @param onPause - The hook's `pauseUpload`. Pass it together with `onResume` to
53
- * get the control; pass neither for a bar that only reports.
54
- * @param onResume - The hook's `resumeUpload`.
55
- * @param className - Replaces the default classes rather than extending them,
56
- * so a custom chrome is not fighting a default it did not ask for.
50
+ * @param props - Progress-bar props.
57
51
  *
58
52
  * @public
59
53
  */
60
54
  export declare function UploadProgressBar({ upload, onPause, onResume, className, }: {
55
+ /**
56
+ * What `useWorkflowSubmit` / `useWorkflowStream` report as `upload`.
57
+ * `undefined` renders nothing, so a page may pass its state straight through
58
+ * and never guard the element.
59
+ */
61
60
  upload?: UploadStatus | undefined;
61
+ /**
62
+ * The hook's `pauseUpload`. **Pass it together with `onResume`** to get the
63
+ * pause control; pass neither for a bar that only reports. One without the
64
+ * other is a one-way door drawn as a toggle, so the control is hidden unless
65
+ * both are present.
66
+ */
62
67
  onPause?: (() => void) | undefined;
68
+ /** The hook's `resumeUpload`. See `onPause` — the two travel together. */
63
69
  onResume?: (() => void) | undefined;
70
+ /**
71
+ * **Replaces** the default classes rather than extending them, so a custom
72
+ * chrome is not fighting a default it did not ask for.
73
+ */
64
74
  className?: string | undefined;
65
75
  }): ReactNode;
@@ -1,24 +1,4 @@
1
- /** @jsxImportSource react */
2
- /**
3
- * A form built from a workflow's declared input schema.
4
- *
5
- * `GET workflows` reports each workflow's `inputSchema` as JSON Schema — the
6
- * zod schema an author wrote in `agent.ts`, converted at listing time precisely
7
- * so a browser can read it. This is what reads it: one `<WorkflowFields>` and a
8
- * workflow's form matches its schema by construction, so adding a field to the
9
- * schema adds it to the page and nothing can drift.
10
- *
11
- * ## It covers SCALARS, and says so rather than guessing
12
- *
13
- * A string, number, integer, boolean or enum has one obvious control each. A
14
- * nested object or an array does not — every choice (a JSON textarea, a repeater,
15
- * a comma-separated string) is a guess about what the author meant, and a guess
16
- * that produces a value the schema then rejects is worse than no field at all.
17
- * So those are SKIPPED, and the fields for them are written by hand: every field
18
- * in this package is a plain named control, so a hand-written one composes with
19
- * a generated one inside the same {@link Form}.
20
- */
21
- import type { WorkflowSummary } from "@alexkroman1/aai";
1
+ import type { WorkflowSummary } from "@alexkroman1/aai/workflow-api";
22
2
  /**
23
3
  * Render one field per scalar property of a workflow's input schema.
24
4
  *
@@ -50,8 +30,16 @@ import type { WorkflowSummary } from "@alexkroman1/aai";
50
30
  * }
51
31
  * ```
52
32
  *
33
+ * @param props - Field-set props.
34
+ *
53
35
  * @public
54
36
  */
55
- export declare function WorkflowFields({ workflow }: {
37
+ export declare function WorkflowFields({ workflow, }: {
38
+ /**
39
+ * The workflow whose input schema to render. A NAME is looked up here (one
40
+ * `GET workflows`); a {@link WorkflowSummary} the page already holds fetches
41
+ * nothing. `undefined` renders nothing, so a page may pass a selection
42
+ * straight through before one is made.
43
+ */
56
44
  workflow?: WorkflowSummary | string | undefined;
57
45
  }): import("react").JSX.Element | null;
@@ -35,21 +35,40 @@ import type { WorkflowApi } from "../workflow-client.ts";
35
35
  * }
36
36
  * ```
37
37
  *
38
- * @param runId - The run to read. `undefined` renders nothing, so a page may
39
- * pass its state straight through before a run exists.
40
- * @param api - The workflow API client, when the page holds its own. Defaults
41
- * to the one `page()` installs.
42
- * @param className - Replaces the default classes rather than extending them,
43
- * so a custom chrome is not fighting a default it did not ask for.
44
- * @param placeholder - Rendered instead of nothing while the run has said
45
- * nothing yet — for a page that would otherwise reflow when the first line
46
- * lands.
38
+ * @param props - Progress-log props.
47
39
  *
48
40
  * @public
49
41
  */
50
- export declare function WorkflowProgress({ runId, api, className, placeholder, }: {
42
+ export declare function WorkflowProgress({ runId, api, className, placeholder, lines, }: {
43
+ /**
44
+ * The run to read. `undefined` renders nothing, so a page may pass its state
45
+ * straight through before a run exists.
46
+ */
51
47
  runId?: string | undefined;
48
+ /**
49
+ * The workflow API client, when the page holds its own. Defaults to the
50
+ * lazily-built one every workflow hook shares.
51
+ */
52
52
  api?: WorkflowApi | undefined;
53
+ /**
54
+ * **Replaces** the default classes rather than extending them, so a custom
55
+ * chrome is not fighting a default it did not ask for.
56
+ */
53
57
  className?: string | undefined;
58
+ /**
59
+ * Rendered instead of nothing while the run has said nothing yet — for a
60
+ * page that would otherwise reflow when the first line lands.
61
+ */
54
62
  placeholder?: ReactNode | undefined;
63
+ /**
64
+ * How many of the newest lines to show. Undefined (the default) shows the
65
+ * whole log; `1` is the newest line only.
66
+ *
67
+ * A run's narration is append-only and unbounded, so a page with a fixed slot
68
+ * for it — a status strip, a card footer — wants a window rather than a log.
69
+ * `0` renders the placeholder, which is the consistent reading of "show none"
70
+ * and the one that keeps a computed `lines` from silently rendering
71
+ * everything.
72
+ */
73
+ lines?: number | undefined;
55
74
  }): ReactNode;
package/dist/context.d.ts CHANGED
@@ -74,6 +74,22 @@ export declare function useSession(): Session;
74
74
  * cheap; when it returns a derived object, pass a custom `isEqual` to avoid
75
75
  * re-renders on referentially-new-but-equal results.
76
76
  *
77
+ * @example
78
+ * ```tsx
79
+ * import { useSessionSelector } from "@alexkroman1/aai-ui";
80
+ *
81
+ * // Re-renders when `running` flips, and on nothing else — not on every
82
+ * // transcript delta the way `useSession()` would.
83
+ * function MicDot() {
84
+ * const running = useSessionSelector((snapshot) => snapshot.running);
85
+ * return <span>{running ? "●" : "○"}</span>;
86
+ * }
87
+ * ```
88
+ *
89
+ * @param selector - Reads the slice out of the snapshot. Must be pure.
90
+ * @param isEqual - Compares two selected values. Defaults to `Object.is`.
91
+ * @returns The selected slice.
92
+ *
77
93
  * @public
78
94
  */
79
95
  export declare function useSessionSelector<T>(selector: (snapshot: SessionSnapshot) => T, isEqual?: (a: T, b: T) => boolean): T;
@@ -93,6 +109,26 @@ export declare function ThemeProvider({ value, children, }: {
93
109
  * default) from the nearest theme context. Returns the default theme when no
94
110
  * provider is present, so components can call it unconditionally.
95
111
  *
112
+ * This is how a custom component stays on the agent's palette: a
113
+ * `client({ theme })` override reaches it here, where a hardcoded colour or a
114
+ * Tailwind class cannot see it.
115
+ *
116
+ * @example
117
+ * ```tsx
118
+ * import { useTheme } from "@alexkroman1/aai-ui";
119
+ *
120
+ * function Total({ amount }: { amount: string }) {
121
+ * const theme = useTheme();
122
+ * return (
123
+ * <strong style={{ color: theme.primary, background: theme.surface }}>
124
+ * {amount}
125
+ * </strong>
126
+ * );
127
+ * }
128
+ * ```
129
+ *
130
+ * @returns Every {@link ClientTheme} field, filled in.
131
+ *
96
132
  * @public
97
133
  */
98
134
  export declare function useTheme(): Required<ClientTheme>;
package/dist/context.js CHANGED
@@ -83,6 +83,22 @@ function useSession() {
83
83
  * cheap; when it returns a derived object, pass a custom `isEqual` to avoid
84
84
  * re-renders on referentially-new-but-equal results.
85
85
  *
86
+ * @example
87
+ * ```tsx
88
+ * import { useSessionSelector } from "@alexkroman1/aai-ui";
89
+ *
90
+ * // Re-renders when `running` flips, and on nothing else — not on every
91
+ * // transcript delta the way `useSession()` would.
92
+ * function MicDot() {
93
+ * const running = useSessionSelector((snapshot) => snapshot.running);
94
+ * return <span>{running ? "●" : "○"}</span>;
95
+ * }
96
+ * ```
97
+ *
98
+ * @param selector - Reads the slice out of the snapshot. Must be pure.
99
+ * @param isEqual - Compares two selected values. Defaults to `Object.is`.
100
+ * @returns The selected slice.
101
+ *
86
102
  * @public
87
103
  */
88
104
  function useSessionSelector(selector, isEqual = Object.is) {
@@ -102,40 +118,115 @@ function ThemeProvider({ value, children }) {
102
118
  ...DEFAULT_THEME,
103
119
  ...value
104
120
  } : DEFAULT_THEME, [value]);
105
- usePageBackground(merged.bg);
121
+ useThemeStyles(merged);
106
122
  return createElement(ThemeCtx.Provider, { value: merged }, children);
107
123
  }
108
124
  /**
109
- * Paint `html`/`body` with the theme background.
110
- *
111
- * Components paint `theme.bg` on their own containers, but the page behind
112
- * them keeps whatever the static `<style>` in index.html set. Any viewport
113
- * wider (or taller) than the app column then shows that color as a border
114
- * around the UI — which is how a cream theme ended up letterboxed in black.
115
- * Driving it from the theme means a custom `client({ theme })` covers the
116
- * page too, instead of trading one hardcoded color for another.
125
+ * The custom property each {@link ClientTheme} field is published as.
126
+ *
127
+ * Named after the field, so `theme.surface` and `--aai-surface` are obviously
128
+ * the same thing, and prefixed for the reason `--aai-btn-bg` and
129
+ * `--aai-sidebar-w` already are: these land on `:root`, where an app's own
130
+ * variables live too.
131
+ *
132
+ * @internal
117
133
  */
118
- function usePageBackground(bg) {
134
+ const THEME_VARS = {
135
+ bg: "--aai-bg",
136
+ surface: "--aai-surface",
137
+ text: "--aai-text",
138
+ border: "--aai-border",
139
+ primary: "--aai-primary"
140
+ };
141
+ /**
142
+ * Publish the theme to CSS, and paint the page with it.
143
+ *
144
+ * Two jobs on one element deliberately — both are about the parts of the page
145
+ * React does not own.
146
+ *
147
+ * **The variables.** {@link useTheme} hands a component a JavaScript object, so
148
+ * everything it styles carries an inline `style={{ }}`; measured across the
149
+ * template tree the ratio of `theme.` reads to inline style objects is
150
+ * essentially one to one. A Tailwind class cannot see a JavaScript object — so
151
+ * the five values are written to `:root` as custom properties, `styles.css`
152
+ * maps them into the `@theme` block's `--color-*` namespace, and
153
+ * `className="bg-aai-surface text-aai-text border-aai-border"` works. This is
154
+ * ADDITIVE: `useTheme()` stays, because the derived tints in
155
+ * `components/_colors.ts` `color-mix` on the resolved values and a page is
156
+ * entitled to read them for a `satisfies`-pinned palette.
157
+ *
158
+ * **The background.** Components paint `theme.bg` on their own containers, but
159
+ * the page behind them keeps whatever the static `<style>` in index.html set.
160
+ * Any viewport wider (or taller) than the app column then shows that color as a
161
+ * border around the UI — which is how a cream theme ended up letterboxed in
162
+ * black. It stays an explicit `background` on `html` AND `body` rather than
163
+ * riding on the new variable: a variable only paints where some rule consumes
164
+ * it, and the two elements this is about are the two nothing in this package
165
+ * renders.
166
+ */
167
+ function useThemeStyles(theme) {
168
+ const { bg, surface, text, border, primary } = theme;
119
169
  useEffect(() => {
120
170
  if (typeof document === "undefined") return;
121
171
  const { body, documentElement: html } = document;
122
- const previous = {
172
+ const values = {
173
+ bg,
174
+ surface,
175
+ text,
176
+ border,
177
+ primary
178
+ };
179
+ const previousVars = Object.entries(THEME_VARS).map(([field, prop]) => [
180
+ prop,
181
+ html.style.getPropertyValue(prop),
182
+ values[field]
183
+ ]);
184
+ for (const [prop, , next] of previousVars) html.style.setProperty(prop, next);
185
+ const previousBg = {
123
186
  body: body.style.background,
124
187
  html: html.style.background
125
188
  };
126
189
  body.style.background = bg;
127
190
  html.style.background = bg;
128
191
  return () => {
129
- body.style.background = previous.body;
130
- html.style.background = previous.html;
192
+ for (const [prop, before] of previousVars) if (before === "") html.style.removeProperty(prop);
193
+ else html.style.setProperty(prop, before);
194
+ body.style.background = previousBg.body;
195
+ html.style.background = previousBg.html;
131
196
  };
132
- }, [bg]);
197
+ }, [
198
+ bg,
199
+ surface,
200
+ text,
201
+ border,
202
+ primary
203
+ ]);
133
204
  }
134
205
  /**
135
206
  * Read the resolved theme (every {@link ClientTheme} field filled with its
136
207
  * default) from the nearest theme context. Returns the default theme when no
137
208
  * provider is present, so components can call it unconditionally.
138
209
  *
210
+ * This is how a custom component stays on the agent's palette: a
211
+ * `client({ theme })` override reaches it here, where a hardcoded colour or a
212
+ * Tailwind class cannot see it.
213
+ *
214
+ * @example
215
+ * ```tsx
216
+ * import { useTheme } from "@alexkroman1/aai-ui";
217
+ *
218
+ * function Total({ amount }: { amount: string }) {
219
+ * const theme = useTheme();
220
+ * return (
221
+ * <strong style={{ color: theme.primary, background: theme.surface }}>
222
+ * {amount}
223
+ * </strong>
224
+ * );
225
+ * }
226
+ * ```
227
+ *
228
+ * @returns Every {@link ClientTheme} field, filled in.
229
+ *
139
230
  * @public
140
231
  */
141
232
  function useTheme() {
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-aai-surface:var(--aai-surface,#fff);--color-aai-text:var(--aai-text,#1b1a18);--color-aai-border:var(--aai-border,#dcd7cc);--font-aai:"Monument Grotesk", "ABC Monument Grotesk", ui-sans-serif, system-ui, -apple-system, sans-serif;--font-aai-serif:"Source Serif 4", "Source Serif Pro", Charter, "Iowan Old Style", Georgia, serif;--font-aai-mono:"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--radius-aai:4px}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html,body{margin:0;padding:0}}@layer components;@layer utilities{.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.order-last{order:9999}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.m-0{margin:0}.mx-auto{margin-inline:auto}.my-0\.5{margin-block:calc(var(--spacing) * .5)}.my-1\.5{margin-block:calc(var(--spacing) * 1.5)}.my-2\.5{margin-block:calc(var(--spacing) * 2.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.box-border{box-sizing:border-box}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-4{height:calc(var(--spacing) * 4)}.h-6{height:calc(var(--spacing) * 6)}.h-9{height:calc(var(--spacing) * 9)}.h-11{height:calc(var(--spacing) * 11)}.h-\[7px\]{height:7px}.h-full{height:100%}.h-screen{height:100vh}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-\[40vh\]{max-height:40vh}.min-h-0{min-height:0}.min-h-5{min-height:calc(var(--spacing) * 5)}.min-h-screen{min-height:100vh}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-4{width:calc(var(--spacing) * 4)}.w-\[7px\]{width:7px}.w-fit{width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-75{max-width:calc(var(--spacing) * 75)}.max-w-105{max-width:calc(var(--spacing) * 105)}.max-w-190{max-width:calc(var(--spacing) * 190)}.max-w-\[82\%\]{max-width:82%}.max-w-\[min\(78\%\,64ch\)\]{max-width:min(78%,64ch)}.min-w-0{min-width:0}.flex-1{flex:1}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.basis-full{flex-basis:100%}.border-collapse{border-collapse:collapse}.rotate-90{rotate:90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.cursor-pointer{cursor:pointer}.resize{resize:both}.\[scrollbar-width\:none\]{scrollbar-width:none}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.appearance-none{appearance:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-aai{border-radius:var(--radius-aai)}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-none{--tw-border-style:none;border-style:none}.border-\(--aai-btn-bd\){border-color:var(--aai-btn-bd)}.border-aai-border{border-color:var(--color-aai-border)}.bg-\(--aai-btn-bg\){background-color:var(--aai-btn-bg)}.bg-aai-surface{background-color:var(--color-aai-surface)}.bg-transparent{background-color:#0000}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-4{padding:calc(var(--spacing) * 4)}.p-7{padding:calc(var(--spacing) * 7)}.p-8{padding:calc(var(--spacing) * 8)}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-7{padding-inline:calc(var(--spacing) * 7)}.px-10{padding-inline:calc(var(--spacing) * 10)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-12{padding-block:calc(var(--spacing) * 12)}.pl-1\.5{padding-left:calc(var(--spacing) * 1.5)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-5{padding-left:calc(var(--spacing) * 5)}.text-center{text-align:center}.text-left{text-align:left}.font-aai{font-family:var(--font-aai)}.font-aai-mono{font-family:var(--font-aai-mono)}.font-aai-serif{font-family:var(--font-aai-serif)}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.625rem\]{font-size:.625rem}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.text-\[17px\]{font-size:17px}.text-\[22px\]{font-size:22px}.text-\[32px\]{font-size:32px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-\[1\.2\]{--tw-leading:1.2;line-height:1.2}.leading-\[1\.15\]{--tw-leading:1.15;line-height:1.15}.leading-\[22px\]{--tw-leading:22px;line-height:22px}.leading-\[23px\]{--tw-leading:23px;line-height:23px}.leading-\[130\%\]{--tw-leading:130%;line-height:130%}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[-0\.2px\]{--tw-tracking:-.2px;letter-spacing:-.2px}.tracking-\[1\.2px\]{--tw-tracking:1.2px;letter-spacing:1.2px}.tracking-\[1\.4px\]{--tw-tracking:1.4px;letter-spacing:1.4px}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-balance{text-wrap:balance}.wrap-break-word{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\(--aai-btn-fg\){color:var(--aai-btn-fg)}.text-aai-text{color:var(--color-aai-text)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.invert{--tw-invert:invert(100%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.file\:mr-3::file-selector-button{margin-right:calc(var(--spacing) * 3)}.file\:cursor-pointer::file-selector-button{cursor:pointer}.file\:rounded-aai::file-selector-button{border-radius:var(--radius-aai)}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:px-3::file-selector-button{padding-inline:calc(var(--spacing) * 3)}.file\:py-1\.5::file-selector-button{padding-block:calc(var(--spacing) * 1.5)}.file\:font-aai::file-selector-button{font-family:var(--font-aai)}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\:\[color\:var\(--aai-file-button-fg\)\]::file-selector-button{color:var(--aai-file-button-fg)}.file\:\[background\:var\(--aai-file-button-bg\)\]::file-selector-button{background:var(--aai-file-button-bg)}.first\:mt-0:first-child{margin-top:0}.last\:mb-0:last-child{margin-bottom:0}.focus-visible\:\[outline\:2px_solid\]:focus-visible{outline:2px solid}.focus-visible\:\[outline-offset\:2px\]:focus-visible{outline-offset:2px}@media (hover:hover){.enabled\:hover\:border-\(--aai-btn-bd-hover\):enabled:hover{border-color:var(--aai-btn-bd-hover)}.enabled\:hover\:bg-\(--aai-btn-bg-hover\):enabled:hover{background-color:var(--aai-btn-bg-hover)}.enabled\:hover\:text-\(--aai-btn-fg-hover\):enabled:hover{color:var(--aai-btn-fg-hover)}}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}@media (width>=40rem){.sm\:ml-auto{margin-left:auto}.sm\:max-w-\[60\%\]{max-width:60%}.sm\:basis-auto{flex-basis:auto}.sm\:px-16{padding-inline:calc(var(--spacing) * 16)}.sm\:py-14{padding-block:calc(var(--spacing) * 14)}}@media (width>=48rem){.md\:order-none{order:0}.md\:h-screen{height:100vh}.md\:max-h-none{max-height:none}.md\:w-\(--aai-sidebar-w\){width:var(--aai-sidebar-w)}.md\:flex-row{flex-direction:row}.md\:border-t-0{border-top-style:var(--tw-border-style);border-top-width:0}.md\:border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.md\:border-b-0{border-bottom-style:var(--tw-border-style);border-bottom-width:0}.md\:border-l{border-left-style:var(--tw-border-style);border-left-width:1px}}}@keyframes aai-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.82)}}@keyframes aai-bounce{0%,80%,to{opacity:.3;transform:scale(.8)}40%{opacity:1;transform:scale(1)}}@keyframes aai-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.tool-shimmer{-webkit-text-fill-color:transparent;background:linear-gradient(90deg,currentColor 25%,#0000 50%,currentColor 75%) 0 0/200% 100%;-webkit-background-clip:text;background-clip:text;animation:2s infinite aai-shimmer}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}}