@alexkroman1/aai-ui 0.17.0 → 0.18.1

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 (71) 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.d.ts +4 -2
  9. package/dist/append-dictation.d.ts +23 -0
  10. package/dist/audio/dictation.d.ts +36 -0
  11. package/dist/audio/index.d.ts +4 -2
  12. package/dist/audio/index.js +44 -1
  13. package/dist/{chat-view-W6KcdjJY.js → chat-view-BwKpF0MN.js} +27 -17
  14. package/dist/{client-config-CzvWmw4X.js → client-config-DcMCWmkO.js} +1 -1
  15. package/dist/components/button.js +1 -1
  16. package/dist/components/chat-view.js +1 -2
  17. package/dist/components/controls.js +2 -2
  18. package/dist/components/form-fields.d.ts +24 -5
  19. package/dist/components/form-types.d.ts +32 -0
  20. package/dist/components/form.d.ts +1 -1
  21. package/dist/components/message-list.js +1 -2
  22. package/dist/components/session-state-dot.d.ts +30 -18
  23. package/dist/components/sidebar-layout.js +1 -1
  24. package/dist/components/start-screen.js +2 -2
  25. package/dist/components/tool-call-block.js +1 -2
  26. package/dist/components/tool-config-context.d.ts +21 -4
  27. package/dist/components/workflow-fields.d.ts +36 -12
  28. package/dist/components/workflow-pending-note.d.ts +30 -12
  29. package/dist/context-BF0KsI9X.js +473 -0
  30. package/dist/context.js +1 -381
  31. package/dist/default-client/assets/audio-CtBvSS3L.js +1 -0
  32. package/dist/default-client/assets/{capture-processor-Cx1AdMHL.js → capture-processor-BZXisGjZ.js} +1 -1
  33. package/dist/default-client/assets/index-BkjCv4MX.css +2 -0
  34. package/dist/default-client/assets/index-DUQoaxdq.js +127 -0
  35. package/dist/default-client/assets/{playback-processor-CCwTknSu.js → playback-processor-BHk-iXEU.js} +1 -1
  36. package/dist/default-client/index.html +2 -2
  37. package/dist/default-client.d.ts +1 -3
  38. package/dist/define-client.d.ts +30 -28
  39. package/dist/define-client.js +84 -43
  40. package/dist/dictation-transcriber.d.ts +49 -0
  41. package/dist/{eyebrow-UfmSz9yy.js → eyebrow-Bp4y1rZ9.js} +1 -1
  42. package/dist/{hooks-DN4gHYsj.js → hooks-1CoQY_Fc.js} +2 -2
  43. package/dist/hooks.js +1 -2
  44. package/dist/index.d.ts +11 -8
  45. package/dist/index.js +849 -263
  46. package/dist/internal.d.ts +1 -1
  47. package/dist/internal.js +6 -6
  48. package/dist/{message-list-BsaBkBgo.js → message-list-BBHLK05X.js} +3 -3
  49. package/dist/route-fetch.d.ts +7 -1
  50. package/dist/session/index.js +1 -1
  51. package/dist/{session-3lgPYNNO.js → session-Rud8mmU-.js} +2 -2
  52. package/dist/{tool-call-block-uXtMOUWN.js → tool-call-block-C8s6AhjS.js} +4 -4
  53. package/dist/tool-config-context-Bd-7xrfP.js +28 -0
  54. package/dist/types.d.ts +47 -2
  55. package/dist/{url-chips-oyy_Eiqh.js → url-chips-C_SHU6fq.js} +2 -2
  56. package/dist/use-dictation.d.ts +145 -0
  57. package/dist/use-route.d.ts +49 -7
  58. package/dist/use-run-key.d.ts +6 -1
  59. package/dist/{use-user-transcript-uyHhzy4d.js → use-user-transcript-lOu_uMnf.js} +1 -1
  60. package/dist/use-workflow-form.d.ts +74 -172
  61. package/dist/{use-workflow-run-DdhWmbx-.js → use-workflow-run-BTEemod0.js} +2 -2
  62. package/dist/use-workflow-runs.d.ts +8 -2
  63. package/dist/use-workflow-stream.d.ts +9 -5
  64. package/dist/workflow-def-types.d.ts +18 -2
  65. package/dist/workflow-field-kind.d.ts +59 -7
  66. package/dist/workflow-submission.d.ts +265 -0
  67. package/package.json +2 -2
  68. package/dist/default-client/assets/audio-Ct7JpSNT.js +0 -1
  69. package/dist/default-client/assets/index-BlUYCTB5.js +0 -126
  70. package/dist/default-client/assets/index-_-x5JLLa.css +0 -2
  71. package/dist/tool-config-context-Es4YUzV2.js +0 -19
@@ -35,6 +35,24 @@ export declare function StateDot({ color, pulseMs, className, title, }: {
35
35
  /** Tooltip text, typically the raw state. */
36
36
  title?: string | undefined;
37
37
  }): ReactNode;
38
+ /**
39
+ * The coarse colour groups {@link SessionStateDotColors} accepts beside the
40
+ * exact states: `idle` (disconnected, connecting, and any state this version
41
+ * does not know), `live` (ready, listening, speaking) and `busy` (thinking).
42
+ * `error` has no group: its red is semantic and is only replaced by name.
43
+ *
44
+ * @public
45
+ */
46
+ export type SessionStateDotGroup = "idle" | "live" | "busy";
47
+ /**
48
+ * What {@link SessionStateDot} takes as `colors`: a colour per
49
+ * {@link AgentState}, per {@link SessionStateDotGroup}, or any mix. An exact
50
+ * state wins over its group; a state neither names is painted from the theme.
51
+ *
52
+ * @input
53
+ * @public
54
+ */
55
+ export type SessionStateDotColors = Partial<Readonly<Record<AgentState | SessionStateDotGroup, string>>>;
38
56
  /**
39
57
  * Props of {@link SessionStateDot}.
40
58
  *
@@ -43,12 +61,14 @@ export declare function StateDot({ color, pulseMs, className, title, }: {
43
61
  */
44
62
  export type SessionStateDotProps = {
45
63
  /**
46
- * The dot's colour per {@link AgentState} — the chrome's own palette. Any
47
- * state not named (including one a later release adds) is painted the way
48
- * `ConsoleShell` paints it, from the theme: the primary colour while live, a
49
- * fixed amber while thinking, red on error, a faint ink otherwise.
64
+ * The dot's colour per {@link AgentState}, per coarse group (`idle`, `live`,
65
+ * `busy`), or both — the chrome's own palette, see
66
+ * {@link SessionStateDotColors}. Any state not named either way (including
67
+ * one a later release adds) is painted from the mounted theme: the primary
68
+ * colour while live, the text colour at half strength while idle, a fixed
69
+ * amber while thinking, red on error.
50
70
  */
51
- colors?: Partial<Readonly<Record<AgentState, string>>> | undefined;
71
+ colors?: SessionStateDotColors | undefined;
52
72
  /**
53
73
  * The words this chrome has a better term for. Anything not named falls back
54
74
  * to {@link AGENT_STATE_LABELS}, so a page overrides one member (`speaking:
@@ -91,25 +111,14 @@ export type SessionStateDotProps = {
91
111
  *
92
112
  * Must be rendered inside the providers `mountClient()` installs.
93
113
  *
94
- * @example A dispatch board's readout: its own colours, three of its own words
114
+ * @example A dispatch board's readout: coarse colours, three of its own words
95
115
  * ```tsx
96
- * import type { AgentState } from "@alexkroman1/aai-ui";
97
116
  * import { SessionStateDot } from "@alexkroman1/aai-ui";
98
117
  *
99
- * const STATE_COLORS = {
100
- * disconnected: "#6b7280",
101
- * connecting: "#6b7280",
102
- * ready: "#22c55e",
103
- * listening: "#22c55e",
104
- * thinking: "#eab308",
105
- * speaking: "#3b82f6",
106
- * error: "#6b7280",
107
- * } satisfies Record<AgentState, string>;
108
- *
109
118
  * function StatusReadout() {
110
119
  * return (
111
120
  * <SessionStateDot
112
- * colors={STATE_COLORS}
121
+ * colors={{ idle: "#6b7280", live: "#22c55e", busy: "#eab308", speaking: "#3b82f6" }}
113
122
  * labels={{ listening: "LISTENING", thinking: "PROCESSING", speaking: "TRANSMITTING" }}
114
123
  * labelClassName="text-[11px] uppercase"
115
124
  * />
@@ -117,6 +126,9 @@ export type SessionStateDotProps = {
117
126
  * }
118
127
  * ```
119
128
  *
129
+ * With no `colors` at all the dot follows the mounted theme — a chrome that
130
+ * sets `mountClient({ theme })` gets a matching dot for free.
131
+ *
120
132
  * @param props - See {@link SessionStateDotProps}.
121
133
  *
122
134
  * @public
@@ -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, jsxs } from "react/jsx-runtime";
4
4
  //#region src/components/sidebar-layout.tsx
@@ -1,7 +1,7 @@
1
- import { useSessionCore, useSessionSelector, useTheme } from "../context.js";
1
+ import { c as useSessionSelector, o as useSessionCore, u as useTheme } from "../context-BF0KsI9X.js";
2
2
  import { a as inkTint } from "../_colors-CpZO-88A.js";
3
3
  import { Button } from "./button.js";
4
- import { t as Eyebrow } from "../eyebrow-UfmSz9yy.js";
4
+ import { t as Eyebrow } from "../eyebrow-Bp4y1rZ9.js";
5
5
  import clsx from "clsx";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  //#region src/components/start-screen.tsx
@@ -1,3 +1,2 @@
1
- import "../context.js";
2
- import { t as ToolCallBlock } from "../tool-call-block-uXtMOUWN.js";
1
+ import { t as ToolCallBlock } from "../tool-call-block-C8s6AhjS.js";
3
2
  export { ToolCallBlock };
@@ -1,16 +1,33 @@
1
1
  import { type Context } from "react";
2
2
  /**
3
- * Display configuration for a tool call in the UI.
3
+ * Display configuration for a tool call in the UI, keyed by tool name: the
4
+ * icon and label each tool declared with `tool({ ui })`, as the agent serves
5
+ * them in its `GET /client-config` body. `mountClient()` installs the served
6
+ * map as it is — a page has no map of its own to merge over it, so the tool's
7
+ * declaration is the one place a tool's icon lives.
4
8
  *
9
+ * Not on the package barrel: nothing an author writes names it (the value a
10
+ * page reads comes from the agent), so it is the context's value type only.
11
+ *
12
+ * @sealed
5
13
  * @public
6
14
  */
7
15
  export type ToolDisplayConfig = Record<string, {
8
- icon?: string;
9
- label?: string;
16
+ icon?: string | undefined;
17
+ label?: string | undefined;
10
18
  }>;
19
+ /**
20
+ * The value the context holds before the lookup lands (and forever, when the
21
+ * lookup fails): one frozen object, so the provider's value is stable across
22
+ * renders rather than a fresh `{}` per commit.
23
+ *
24
+ * @internal
25
+ */
26
+ export declare const EMPTY_TOOL_DISPLAY: ToolDisplayConfig;
11
27
  /**
12
28
  * Context for tool display configuration. Installed by `mountClient()` from
13
- * `ClientConfig.tools`; the built-in components read it via `useToolConfig`.
29
+ * the agent's `GET /client-config` `tools`; the built-in components read it
30
+ * via `useToolConfig`.
14
31
  *
15
32
  * @internal
16
33
  */
@@ -1,7 +1,39 @@
1
1
  import type { WorkflowSummary } from "@alexkroman1/aai/workflow-api";
2
- import type { JSX } from "react";
2
+ import { type JSX } from "react";
3
+ import type { WorkflowAppLike, WorkflowNameOf } from "../workflow-def-types.ts";
4
+ import { type WorkflowFieldRender } from "../workflow-field-kind.ts";
3
5
  /**
4
- * Render one field per scalar property of a workflow's input schema.
6
+ * Props for {@link WorkflowFields}.
7
+ *
8
+ * @typeParam App - The agent, when the page names it
9
+ * (`<WorkflowFields<typeof agentDef> workflow="digest" />`): `workflow` is
10
+ * then a name the agent declares, checked. Left to its default, any string:
11
+ * `WorkflowNameOf<WorkflowAppLike>` is `string`. The default is the
12
+ * constraint rather than the hooks' `never` because this is ONE signature —
13
+ * a form has no def form to fall to, so there is no second overload for a
14
+ * `never` to hand the call on to.
15
+ *
16
+ * @input
17
+ * @public
18
+ */
19
+ export type WorkflowFieldsProps<App extends WorkflowAppLike = WorkflowAppLike> = {
20
+ /**
21
+ * The workflow whose input schema to render. A NAME is looked up here (one
22
+ * `GET workflows`); a {@link WorkflowSummary} the page already holds fetches
23
+ * nothing. `undefined` renders nothing, so a page may pass a selection
24
+ * straight through before one is made.
25
+ */
26
+ workflow?: WorkflowSummary | WorkflowNameOf<App> | undefined;
27
+ /**
28
+ * The control to draw for a property, by name, where the schema alone does
29
+ * not say — `{ mustCover: "lines", source: "namedText" }`. Beats the schema
30
+ * for that property, never a declared upload. See `WorkflowFieldKind`.
31
+ */
32
+ render?: Readonly<Record<string, WorkflowFieldRender>> | undefined;
33
+ };
34
+ /**
35
+ * Render one field per property of a workflow's input schema that has an
36
+ * honest control — every scalar, an array of strings, a `{ name, text }` object.
5
37
  *
6
38
  * Pass the workflow's NAME and the schema is fetched here; pass a
7
39
  * {@link WorkflowSummary} you already hold and nothing is fetched. The name form
@@ -32,16 +64,8 @@ import type { JSX } from "react";
32
64
  * }
33
65
  * ```
34
66
  *
35
- * @param props - Field-set props.
67
+ * @param props - See {@link WorkflowFieldsProps}.
36
68
  *
37
69
  * @public
38
70
  */
39
- export declare function WorkflowFields({ workflow, }: {
40
- /**
41
- * The workflow whose input schema to render. A NAME is looked up here (one
42
- * `GET workflows`); a {@link WorkflowSummary} the page already holds fetches
43
- * nothing. `undefined` renders nothing, so a page may pass a selection
44
- * straight through before one is made.
45
- */
46
- workflow?: WorkflowSummary | string | undefined;
47
- }): JSX.Element | null;
71
+ export declare function WorkflowFields<App extends WorkflowAppLike = WorkflowAppLike>({ workflow, render, }: WorkflowFieldsProps<App>): JSX.Element | null;
@@ -1,5 +1,6 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { WorkflowRun } from "../workflow-client.ts";
3
+ import type { UploadStatus, WorkflowSubmissionScope } from "../workflow-submission.ts";
3
4
  /**
4
5
  * Props for {@link WorkflowPendingNote}.
5
6
  *
@@ -9,13 +10,18 @@ import type { WorkflowRun } from "../workflow-client.ts";
9
10
  export type WorkflowPendingNoteProps = {
10
11
  /**
11
12
  * The submission the page is rendering — `useWorkflowSubmit`'s or
12
- * `useWorkflowStream`'s result, or any object carrying these three fields.
13
- * Nothing renders while `pending` is false.
13
+ * `useWorkflowStream`'s result, or any object carrying the three required
14
+ * fields. Nothing renders while `pending` is false. `scope` and `upload`,
15
+ * when present, choose two more sentences — see below.
14
16
  */
15
17
  submission: {
16
18
  readonly pending: boolean;
17
19
  readonly startedHere: boolean;
18
20
  readonly run: WorkflowRun | undefined;
21
+ /** Who finds the run again — `WorkflowSubmission.scope`; the `scope` prop overrides it. */
22
+ readonly scope?: WorkflowSubmissionScope | undefined;
23
+ /** The bytes in flight — `WorkflowSubmission.upload`; a PAUSED one gets its own line. */
24
+ readonly upload?: UploadStatus | undefined;
19
25
  };
20
26
  /**
21
27
  * What the run produces, as the noun the sentences name: `"draft"`,
@@ -23,13 +29,16 @@ export type WorkflowPendingNoteProps = {
23
29
  */
24
30
  subject?: string | undefined;
25
31
  /**
26
- * Where the key that finds the run again lives. `"tab"` (the default) is
27
- * `useWorkflowSubmit`'s own `sessionStorage` key; `"browser"` is a page that
28
- * passed `useRunKey({ storage: "local" })`, whose runs any tab on this browser
29
- * can find — so the sentence says "this browser" and stops promising that
30
- * closing the tab loses anything.
32
+ * Where the key that finds the run again lives, overriding what the
33
+ * submission reports. `"tab"` is `useWorkflowSubmit`'s own `sessionStorage`
34
+ * key; `"browser"` is a page that passed `useRunKey({ storage: "local" })`,
35
+ * whose runs any tab on this browser can find — so the sentence says "this
36
+ * browser" and stops promising that closing the tab loses anything;
37
+ * `"none"` is a run nothing will find again (`recover: false`,
38
+ * `useWorkflowStream`), which the sentence has to say instead. Default: the
39
+ * submission's own `scope`, else `"tab"`.
31
40
  */
32
- scope?: "tab" | "browser" | undefined;
41
+ scope?: WorkflowSubmissionScope | undefined;
33
42
  /**
34
43
  * ADDED to the note's own `text-sm opacity-70` rather than replacing it.
35
44
  * There is no `tailwind-merge` in this package, so a class that CONFLICTS with
@@ -38,7 +47,7 @@ export type WorkflowPendingNoteProps = {
38
47
  className?: string | undefined;
39
48
  };
40
49
  /**
41
- * The one sentence a page says while a run is in flight — three situations,
50
+ * The one sentence a page says while a run is in flight — five situations,
42
51
  * one line each — as a muted line under the form, and nothing otherwise.
43
52
  *
44
53
  * Six template pages had each written the function under this, byte-identical
@@ -61,9 +70,18 @@ export type WorkflowPendingNoteProps = {
61
70
  *
62
71
  * `startedHere`, `run` and `pending` are what {@link WorkflowSubmission}
63
72
  * reports, which is why the prop is the submission itself rather than three
64
- * booleans a page would re-derive. A page with a FOURTH situation — a run that a
65
- * reload does not recover but ENDS, as `transcription-workflow`'s streaming
66
- * flow has — writes its own sentence, and that template is the one doing so.
73
+ * booleans a page would re-derive. The two situations past those three read
74
+ * two more of its fields, and used to be the one page that wrote its own note:
75
+ *
76
+ * - **A run nothing will find again** (`scope: "none"` — `useWorkflowStream`,
77
+ * whose run reads the recording as this page sends it and gives up on one
78
+ * that stops arriving, or `recover: false`): "keep this tab open", because
79
+ * a reload does not orphan that run, it ENDS it. A page telling a reader they
80
+ * can close the tab would be wrong in exactly that mode.
81
+ * - **A PAUSED upload** is that same fact arriving through a button, which is
82
+ * why it is tested first and why its two sentences differ: with no run yet
83
+ * a pause costs nothing, and in the streaming mode the run is already
84
+ * watching an upload it will give up on.
67
85
  *
68
86
  * @example
69
87
  * ```tsx