@alexkroman1/aai-ui 0.12.2 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +257 -0
- package/dist/_colors-CpZO-88A.js +78 -0
- package/dist/_module-url-C13kAJ87.js +15 -0
- package/dist/_page-shell.d.ts +11 -0
- package/dist/_recover-run.d.ts +79 -0
- package/dist/_repeat-until.d.ts +30 -0
- package/dist/_run-controls.d.ts +33 -0
- package/dist/_submission-state.d.ts +92 -0
- package/dist/_tap-to-talk-state.d.ts +88 -0
- package/dist/_utils-Mi-SCFA1.js +47 -0
- package/dist/_utils.d.ts +26 -0
- package/dist/_web-storage.d.ts +43 -0
- package/dist/_workflow-api-ref.d.ts +37 -0
- package/dist/_workflow-files.d.ts +34 -0
- package/dist/_workflow-test-defs.d.ts +38 -0
- package/dist/aai-logo-D8pMVn9_.js +85 -0
- package/dist/agent-state-labels.d.ts +65 -0
- package/dist/agent-state.d.ts +108 -0
- package/dist/audio/capture.d.ts +44 -0
- package/dist/audio/index.d.ts +18 -0
- package/dist/audio/index.js +431 -0
- package/dist/audio/preconnect.d.ts +87 -0
- package/dist/audio/voice-io.d.ts +112 -0
- package/dist/build-default-client.d.ts +1 -0
- package/dist/chat-view-BCbI7gD4.js +396 -0
- package/dist/client-config-C7fQrioM.js +139 -0
- package/dist/client-config.d.ts +119 -0
- package/dist/client-dir.d.ts +44 -0
- package/dist/client-dir.js +58 -0
- package/dist/client-identity.d.ts +131 -0
- package/dist/client-tool.d.ts +51 -0
- package/dist/components/_colors.d.ts +73 -0
- package/dist/components/_form-readiness.d.ts +56 -0
- package/dist/components/_form-values.d.ts +19 -0
- package/dist/components/aai-logo.d.ts +12 -0
- package/dist/components/audio-result.d.ts +94 -0
- package/dist/components/auto-scroll.d.ts +74 -0
- package/dist/components/bullet-list.d.ts +74 -0
- package/dist/components/button.d.ts +58 -0
- package/dist/components/button.js +85 -0
- package/dist/components/chat-view.d.ts +35 -0
- package/dist/components/chat-view.js +3 -0
- package/dist/components/console-shell.d.ts +85 -0
- package/dist/components/controls.d.ts +33 -0
- package/dist/components/controls.js +49 -0
- package/dist/components/conversation-view.d.ts +130 -0
- package/dist/components/eyebrow.d.ts +12 -0
- package/dist/components/facts.d.ts +81 -0
- package/dist/components/form-fields.d.ts +142 -0
- package/dist/components/form-types.d.ts +73 -0
- package/dist/components/form.d.ts +96 -0
- package/dist/components/markdown.d.ts +57 -0
- package/dist/components/message-list.d.ts +48 -0
- package/dist/components/message-list.js +3 -0
- package/dist/components/session-controls.d.ts +125 -0
- package/dist/components/session-error-banner.d.ts +69 -0
- package/dist/components/session-state-dot.d.ts +111 -0
- package/dist/components/sidebar-layout.d.ts +42 -0
- package/dist/components/sidebar-layout.js +56 -0
- package/dist/components/start-screen.d.ts +37 -0
- package/dist/components/start-screen.js +71 -0
- package/dist/components/tool-call-block.d.ts +28 -0
- package/dist/components/tool-call-block.js +3 -0
- package/dist/components/tool-call-row.d.ts +75 -0
- package/dist/components/tool-config-context.d.ts +22 -0
- package/dist/components/upload-progress.d.ts +76 -0
- package/dist/components/url-chips.d.ts +29 -0
- package/dist/components/workflow-fields.d.ts +46 -0
- package/dist/components/workflow-pending-note.d.ts +81 -0
- package/dist/components/workflow-progress.d.ts +81 -0
- package/dist/components/workflow-run-error.d.ts +48 -0
- package/dist/components/workflow-run-panel.d.ts +79 -0
- package/dist/context.d.ts +288 -0
- package/dist/context.js +382 -0
- package/dist/conversation-log.d.ts +88 -0
- package/dist/default-client/assets/_module-url-BX0RuRU2.js +1 -0
- package/dist/default-client/assets/audio-cGFGID-2.js +1 -0
- package/dist/default-client/assets/capture-processor-BUABoo3_.js +90 -0
- package/dist/default-client/assets/index-8ihb1Urm.css +2 -0
- package/dist/default-client/assets/index-BQURVARl.js +126 -0
- package/dist/default-client/assets/playback-processor-ABOa11j0.js +314 -0
- package/dist/default-client/favicon.ico +0 -0
- package/dist/default-client/index.html +15 -0
- package/dist/default-client.d.ts +23 -0
- package/dist/define-client.d.ts +162 -26
- package/dist/define-client.js +201 -55
- package/dist/eyebrow-UfmSz9yy.js +27 -0
- package/dist/hooks-DN4gHYsj.js +182 -0
- package/dist/hooks.d.ts +172 -0
- package/dist/hooks.js +3 -0
- package/dist/hooks.test-d.d.ts +14 -0
- package/dist/inbox-protocol.d.ts +128 -0
- package/dist/inbox.d.ts +132 -0
- package/dist/index.d.ts +129 -32
- package/dist/index.js +5503 -18
- package/dist/internal.d.ts +43 -0
- package/dist/internal.js +8 -0
- package/dist/linked-client.d.ts +70 -0
- package/dist/message-list-DHZcLhRA.js +682 -0
- package/dist/notice-player.d.ts +70 -0
- package/dist/page.d.ts +114 -0
- package/dist/phone.d.ts +50 -0
- package/dist/route-fetch.d.ts +79 -0
- package/dist/session/audio-effects.d.ts +31 -0
- package/dist/session/audio-setup.d.ts +57 -0
- package/dist/session/audio-state.d.ts +157 -0
- package/dist/session/browser-session.d.ts +30 -0
- package/dist/session/close.d.ts +26 -0
- package/dist/session/dial.d.ts +65 -0
- package/dist/session/handshake.d.ts +60 -0
- package/dist/session/index.d.ts +17 -0
- package/dist/session/index.js +2 -0
- package/dist/session/messages.d.ts +63 -0
- package/dist/session/mic.d.ts +64 -0
- package/dist/session/preconnect.d.ts +48 -0
- package/dist/session/reconnect.d.ts +25 -0
- package/dist/session/resume-store.d.ts +57 -0
- package/dist/session/state.d.ts +146 -0
- package/dist/session/ticket.d.ts +44 -0
- package/dist/session/types.d.ts +476 -0
- package/dist/session/url.d.ts +17 -0
- package/dist/session/user-turn.d.ts +55 -0
- package/dist/session-CE0Ipsb3.js +2129 -0
- package/dist/stored-value.d.ts +103 -0
- package/dist/tool-call-block-uXtMOUWN.js +204 -0
- package/dist/tool-config-context-Es4YUzV2.js +19 -0
- package/dist/types.d.ts +272 -34
- package/dist/types.js +35 -4
- package/dist/upload/files.d.ts +83 -0
- package/dist/upload/index.d.ts +15 -0
- package/dist/upload/pause.d.ts +31 -0
- package/dist/upload/recall.d.ts +67 -0
- package/dist/upload/report.d.ts +26 -0
- package/dist/upload/session.d.ts +99 -0
- package/dist/url-chips-oyy_Eiqh.js +239 -0
- package/dist/use-client-runs.d.ts +87 -0
- package/dist/use-conversation-log.d.ts +86 -0
- package/dist/use-conversation.d.ts +131 -0
- package/dist/use-copy.d.ts +74 -0
- package/dist/use-download-url.d.ts +84 -0
- package/dist/use-flash.d.ts +61 -0
- package/dist/use-inbox.d.ts +101 -0
- package/dist/use-push-to-talk.d.ts +105 -0
- package/dist/use-route-mutation.d.ts +113 -0
- package/dist/use-route.d.ts +82 -0
- package/dist/use-run-key.d.ts +133 -0
- package/dist/use-session-controls.d.ts +69 -0
- package/dist/use-session-id.d.ts +57 -0
- package/dist/use-tap-to-talk.d.ts +138 -0
- package/dist/use-user-transcript-uyHhzy4d.js +73 -0
- package/dist/use-user-transcript.d.ts +75 -0
- package/dist/use-workflow-form.d.ts +285 -0
- package/dist/use-workflow-progress.d.ts +137 -0
- package/dist/use-workflow-run-DdhWmbx-.js +697 -0
- package/dist/use-workflow-run.d.ts +100 -0
- package/dist/use-workflow-runs.d.ts +71 -0
- package/dist/use-workflow-stream.d.ts +154 -0
- package/dist/use-workflows.d.ts +77 -0
- package/dist/workflow-client.d.ts +136 -0
- package/dist/workflow-def-types.d.ts +31 -0
- package/dist/workflow-events.d.ts +39 -0
- package/dist/workflow-field-kind.d.ts +95 -0
- package/dist/workflow-status-labels.d.ts +35 -0
- package/dist/worklets/_module-url.d.ts +10 -0
- package/dist/worklets/_playback-bench-harness.d.ts +181 -0
- package/dist/worklets/_playback-bench-host.d.ts +63 -0
- package/dist/worklets/_playback-bench-page.d.ts +65 -0
- package/dist/worklets/_tts-trace-harness.d.ts +142 -0
- package/dist/worklets/_worklet-test-utils.d.ts +27 -0
- package/dist/worklets/capture-processor.d.ts +4 -2
- package/dist/worklets/capture-processor.js +73 -33
- package/dist/worklets/playback-processor.d.ts +4 -2
- package/dist/worklets/playback-processor.js +258 -42
- package/package.json +58 -31
- package/styles.css +152 -30
- package/dist/_components/app.d.ts +0 -23
- package/dist/_components/app.js +0 -41
- package/dist/_components/button.d.ts +0 -50
- package/dist/_components/button.js +0 -46
- package/dist/_components/chat-view.d.ts +0 -29
- package/dist/_components/chat-view.js +0 -61
- package/dist/_components/controls.d.ts +0 -18
- package/dist/_components/controls.js +0 -37
- package/dist/_components/error-banner.d.ts +0 -21
- package/dist/_components/error-banner.js +0 -27
- package/dist/_components/message-bubble.d.ts +0 -23
- package/dist/_components/message-bubble.js +0 -35
- package/dist/_components/message-list.d.ts +0 -21
- package/dist/_components/message-list.js +0 -76
- package/dist/_components/sidebar-layout.d.ts +0 -21
- package/dist/_components/sidebar-layout.js +0 -36
- package/dist/_components/start-screen.d.ts +0 -26
- package/dist/_components/start-screen.js +0 -51
- package/dist/_components/state-indicator.d.ts +0 -29
- package/dist/_components/state-indicator.js +0 -37
- package/dist/_components/thinking-indicator.d.ts +0 -16
- package/dist/_components/thinking-indicator.js +0 -34
- package/dist/_components/tool-call-block.d.ts +0 -27
- package/dist/_components/tool-call-block.js +0 -118
- package/dist/_components/tool-icons.d.ts +0 -17
- package/dist/_components/tool-icons.js +0 -128
- package/dist/_components/transcript.d.ts +0 -25
- package/dist/_components/transcript.js +0 -35
- package/dist/audio.d.ts +0 -45
- package/dist/audio.js +0 -121
- package/dist/client-context.d.ts +0 -33
- package/dist/client-context.js +0 -15
- package/dist/client-handler.d.ts +0 -43
- package/dist/session-CWB7vmqz.js +0 -429
- package/dist/session.d.ts +0 -69
- package/dist/session.js +0 -2
- package/dist/signals.d.ts +0 -120
- package/dist/signals.js +0 -161
- package/dist/tsdown.config.d.ts +0 -2
- package/dist/types.test-d.d.ts +0 -7
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { WorkflowRun } from "../workflow-client.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Props for {@link WorkflowPendingNote}.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export type WorkflowPendingNoteProps = {
|
|
9
|
+
/**
|
|
10
|
+
* The submission the page is rendering — `useWorkflowSubmit`'s or
|
|
11
|
+
* `useWorkflowStream`'s result, or any object carrying these three fields.
|
|
12
|
+
* Nothing renders while `pending` is false.
|
|
13
|
+
*/
|
|
14
|
+
submission: {
|
|
15
|
+
readonly pending: boolean;
|
|
16
|
+
readonly startedHere: boolean;
|
|
17
|
+
readonly run: WorkflowRun | undefined;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* What the run produces, as the noun the sentences name: `"draft"`,
|
|
21
|
+
* `"summary"`, `"transcript"`. Default `"run"`.
|
|
22
|
+
*/
|
|
23
|
+
subject?: string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Where the key that finds the run again lives. `"tab"` (the default) is
|
|
26
|
+
* `useWorkflowSubmit`'s own `sessionStorage` key; `"browser"` is a page that
|
|
27
|
+
* passed `useRunKey({ storage: "local" })`, whose runs any tab on this browser
|
|
28
|
+
* can find — so the sentence says "this browser" and stops promising that
|
|
29
|
+
* closing the tab loses anything.
|
|
30
|
+
*/
|
|
31
|
+
scope?: "tab" | "browser" | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* ADDED to the note's own `text-sm opacity-70` rather than replacing it.
|
|
34
|
+
* There is no `tailwind-merge` in this package, so a class that CONFLICTS with
|
|
35
|
+
* a base one is not reliably the winner.
|
|
36
|
+
*/
|
|
37
|
+
className?: string | undefined;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* The one sentence a page says while a run is in flight — three situations,
|
|
41
|
+
* one line each — as a muted line under the form, and nothing otherwise.
|
|
42
|
+
*
|
|
43
|
+
* Six template pages had each written the function under this, byte-identical
|
|
44
|
+
* in control flow and different only in the noun, under a doc arguing the same
|
|
45
|
+
* two things. Both survive here, once:
|
|
46
|
+
*
|
|
47
|
+
* - **The reload case gets its own words.** `!startedHere && run` is a run in
|
|
48
|
+
* front of somebody who did not press anything — a reload, or another tab on
|
|
49
|
+
* the same key — and they are owed an explanation for work appearing, plus
|
|
50
|
+
* the line that stops them starting it again. The sentence a page reaches for
|
|
51
|
+
* instead ("you can close this tab") was true about the RUN and false about
|
|
52
|
+
* the page for as long as a reload could not find its run.
|
|
53
|
+
* - **The lookup is a state, not an absence.** `!startedHere && !run` is the
|
|
54
|
+
* stretch on a reload where the key is being resolved and an empty form would
|
|
55
|
+
* read as "nothing is happening". It is the same length as the request.
|
|
56
|
+
*
|
|
57
|
+
* The render site had drifted too — three pages muted the line and two did not
|
|
58
|
+
* — so the typography is the component's, in the same `text-sm opacity-70`
|
|
59
|
+
* every other muted line on these pages uses.
|
|
60
|
+
*
|
|
61
|
+
* `startedHere`, `run` and `pending` are what {@link WorkflowSubmission}
|
|
62
|
+
* reports, which is why the prop is the submission itself rather than three
|
|
63
|
+
* booleans a page would re-derive. A page with a FOURTH situation — a run that a
|
|
64
|
+
* reload does not recover but ENDS, as `transcription-workflow`'s streaming
|
|
65
|
+
* flow has — writes its own sentence, and that template is the one doing so.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```tsx
|
|
69
|
+
* import { useWorkflowSubmit, WorkflowPendingNote } from "@alexkroman1/aai-ui";
|
|
70
|
+
*
|
|
71
|
+
* function App() {
|
|
72
|
+
* const submission = useWorkflowSubmit("redline");
|
|
73
|
+
* return <WorkflowPendingNote submission={submission} subject="draft" />;
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @param props - See {@link WorkflowPendingNoteProps}.
|
|
78
|
+
*
|
|
79
|
+
* @public
|
|
80
|
+
*/
|
|
81
|
+
export declare function WorkflowPendingNote({ submission, subject, scope, className, }: WorkflowPendingNoteProps): ReactNode;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { WorkflowApi } from "../workflow-client.ts";
|
|
3
|
+
/**
|
|
4
|
+
* What a run has said so far, rendered.
|
|
5
|
+
*
|
|
6
|
+
* The complement of a status line, and the reason both exist: a run is
|
|
7
|
+
* `running` for its whole life, so a one-round job and a ten-round one look
|
|
8
|
+
* identical while they happen. These lines come from the run itself (`stepReport()`
|
|
9
|
+
* in a `"use step"` body), which is the only channel a workflow has before it
|
|
10
|
+
* produces an output.
|
|
11
|
+
*
|
|
12
|
+
* Four rules are baked in, and they are why this is a component rather than
|
|
13
|
+
* three lines each page writes for itself — the two templates that had written
|
|
14
|
+
* it had written three of them, comments included:
|
|
15
|
+
*
|
|
16
|
+
* - **It renders nothing until there is something to render.** `supported` is
|
|
17
|
+
* what keeps this from being an empty box forever on an agent deployed before
|
|
18
|
+
* progress streams existed: "wrote nothing yet" and "serves no stream" are
|
|
19
|
+
* indistinguishable from the chunk list alone.
|
|
20
|
+
* - **The lines are TEXT, not elements.** They are append-only and two rounds
|
|
21
|
+
* legitimately produce identical text, so there is no stable per-line key to
|
|
22
|
+
* give React. Joining sidesteps the question instead of suppressing the lint
|
|
23
|
+
* rule that asks it.
|
|
24
|
+
* - **They REPLAY.** Chunks are retained with the run, so a reload mid-run —
|
|
25
|
+
* or opening a finished run tomorrow — shows how it got there rather than an
|
|
26
|
+
* empty box. That is `useWorkflowProgress`'s doing; this is what makes it
|
|
27
|
+
* visible.
|
|
28
|
+
* - **They are ANNOUNCED**, for the reason the first paragraph gives: this is
|
|
29
|
+
* the only channel a run has before it produces an output, and a `<pre>` that
|
|
30
|
+
* grows is a silent one. A screen-reader user pressing "Digest" got nothing
|
|
31
|
+
* between the click and a terminal state minutes later — no "fetching", no
|
|
32
|
+
* "summarising", no evidence the button did anything. See `role="log"` below.
|
|
33
|
+
* The six pages that render this pass only `className`, so no template could
|
|
34
|
+
* have fixed it locally; that is what makes it this component's job.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```tsx
|
|
38
|
+
* import { WorkflowProgress } from "@alexkroman1/aai-ui";
|
|
39
|
+
*
|
|
40
|
+
* function RunPanel({ runId }: { runId: string }) {
|
|
41
|
+
* return <WorkflowProgress runId={runId} />;
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @param props - Progress-log props.
|
|
46
|
+
*
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
export declare function WorkflowProgress({ runId, api, className, placeholder, lines, }: {
|
|
50
|
+
/**
|
|
51
|
+
* The run to read. `undefined` renders nothing, so a page may pass its state
|
|
52
|
+
* straight through before a run exists.
|
|
53
|
+
*/
|
|
54
|
+
runId?: string | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* The workflow API client, when the page holds its own. Defaults to the
|
|
57
|
+
* lazily-built one every workflow hook shares.
|
|
58
|
+
*/
|
|
59
|
+
api?: WorkflowApi | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* **Replaces** the default classes rather than extending them, so a custom
|
|
62
|
+
* chrome is not fighting a default it did not ask for.
|
|
63
|
+
*/
|
|
64
|
+
className?: string | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Rendered instead of nothing while the run has said nothing yet — for a
|
|
67
|
+
* page that would otherwise reflow when the first line lands.
|
|
68
|
+
*/
|
|
69
|
+
placeholder?: ReactNode | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* How many of the newest lines to show. Undefined (the default) shows the
|
|
72
|
+
* whole log; `1` is the newest line only.
|
|
73
|
+
*
|
|
74
|
+
* A run's narration is append-only and unbounded, so a page with a fixed slot
|
|
75
|
+
* for it — a status strip, a card footer — wants a window rather than a log.
|
|
76
|
+
* `0` renders the placeholder, which is the consistent reading of "show none"
|
|
77
|
+
* and the one that keeps a computed `lines` from silently rendering
|
|
78
|
+
* everything.
|
|
79
|
+
*/
|
|
80
|
+
lines?: number | undefined;
|
|
81
|
+
}): ReactNode;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { WorkflowRun } from "../workflow-client.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Props for {@link WorkflowRunError}.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export type WorkflowRunErrorProps = {
|
|
9
|
+
/** The run the page is following. Nothing renders unless it has FAILED. */
|
|
10
|
+
run: WorkflowRun | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* ADDED to the alert's own `text-red-600` rather than replacing it. There is
|
|
13
|
+
* no `tailwind-merge` in this package, so a class that CONFLICTS with a base
|
|
14
|
+
* one is not reliably the winner.
|
|
15
|
+
*/
|
|
16
|
+
className?: string | undefined;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* The announced line for a run that failed: its error, or nothing at all while
|
|
20
|
+
* the run is anything else.
|
|
21
|
+
*
|
|
22
|
+
* Six workflow pages had written this paragraph by hand, and the one thing that
|
|
23
|
+
* mattered about it was the part a reviewer cannot see is missing:
|
|
24
|
+
* `role="alert"`. A run fails minutes after the reader looked away — days, for
|
|
25
|
+
* a scheduled one — and `<Form>` announces only the SUBMIT error, so without
|
|
26
|
+
* the role a screen reader is never told the outcome it waited for arrived.
|
|
27
|
+
* Three of the six also disagreed on the sentence ("That one failed", "That run
|
|
28
|
+
* failed", the bare message), which is the drift a component ends.
|
|
29
|
+
*
|
|
30
|
+
* Discriminated on `status`, so `error` is reachable without a cast — the
|
|
31
|
+
* reason {@link WorkflowRun} is a union rather than a flat object with optional
|
|
32
|
+
* fields.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* import { useWorkflowSubmit, WorkflowRunError } from "@alexkroman1/aai-ui";
|
|
37
|
+
*
|
|
38
|
+
* function App() {
|
|
39
|
+
* const { run } = useWorkflowSubmit("digest");
|
|
40
|
+
* return <WorkflowRunError run={run} />;
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @param props - See {@link WorkflowRunErrorProps}.
|
|
45
|
+
*
|
|
46
|
+
* @public
|
|
47
|
+
*/
|
|
48
|
+
export declare function WorkflowRunError({ run, className }: WorkflowRunErrorProps): ReactNode;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { WorkflowRunStatus } from "../workflow-client.ts";
|
|
3
|
+
import { type WorkflowApi, type WorkflowRun } from "../workflow-client.ts";
|
|
4
|
+
/**
|
|
5
|
+
* Props of {@link WorkflowRunPanel}.
|
|
6
|
+
*
|
|
7
|
+
* @typeParam O - The run's output type; `run.output` narrows to it in the
|
|
8
|
+
* completed slot.
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export type WorkflowRunPanelProps<O> = {
|
|
13
|
+
/** The run to show. Nothing here handles `undefined` — a page renders the panel once it has one. */
|
|
14
|
+
run: WorkflowRun<O>;
|
|
15
|
+
/**
|
|
16
|
+
* The status lines this page has a better word for — `{ running:
|
|
17
|
+
* "Writing…" }`. The rest come from {@link WORKFLOW_STATUS_LABELS}.
|
|
18
|
+
*/
|
|
19
|
+
statusLabels?: Partial<Readonly<Record<WorkflowRunStatus, string>>> | undefined;
|
|
20
|
+
/** Renders a Clear button in the header that calls this. Absent, no button. */
|
|
21
|
+
onClear?: (() => void) | undefined;
|
|
22
|
+
/** The workflow API client, when the page holds its own. */
|
|
23
|
+
api?: WorkflowApi | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Rendered beneath the narration while the run is NOT terminal — a live
|
|
26
|
+
* transcript, a partial result. Nothing once it settles.
|
|
27
|
+
*/
|
|
28
|
+
live?: ReactNode | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* The completed body: what the run PRODUCED. A function receives the typed
|
|
31
|
+
* output; a node is rendered as it is. Either appears only while
|
|
32
|
+
* `run.status === "completed"`.
|
|
33
|
+
*/
|
|
34
|
+
children?: ReactNode | ((output: O) => ReactNode) | undefined;
|
|
35
|
+
/** Additional CSS class names for the wrapping `<section>`, appended to its own. */
|
|
36
|
+
className?: string | undefined;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* The bordered panel a workflow page shows one run in: a status line, a Clear
|
|
40
|
+
* button, the run's own narration, the live slot while it works, the completed
|
|
41
|
+
* body once it has, and the announced error if it failed.
|
|
42
|
+
*
|
|
43
|
+
* Two pages had written this shell — `document-redline-workflow` and `transcription-workflow` —
|
|
44
|
+
* with the same header, the same `text-xs underline` Clear, the same
|
|
45
|
+
* {@link WorkflowProgress} under it, the same `run.status === "completed"`
|
|
46
|
+
* discrimination above the same {@link WorkflowRunError}, and each spread
|
|
47
|
+
* {@link WORKFLOW_STATUS_LABELS} into a local map to change `running`. The
|
|
48
|
+
* ORDER is the part worth owning: the narration is the complement of the status
|
|
49
|
+
* line (a run is `running` for its whole life, so a one-round job and a
|
|
50
|
+
* ten-round one look identical without it), and the error goes last because it
|
|
51
|
+
* is the outcome the reader waited minutes for.
|
|
52
|
+
*
|
|
53
|
+
* `children` is discriminated on the run for the caller, so the body reads
|
|
54
|
+
* `run.output` typed, without a cast and without the page repeating the guard —
|
|
55
|
+
* the reason {@link WorkflowRun} is a union rather than a flat object with
|
|
56
|
+
* optional fields.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```tsx
|
|
60
|
+
* import { useWorkflowRun, WorkflowRunPanel } from "@alexkroman1/aai-ui";
|
|
61
|
+
*
|
|
62
|
+
* // `useWorkflowRun<R>` is where a page names the output's shape; a page that
|
|
63
|
+
* // started the run itself has it typed already, from `useWorkflowSubmit<D>`.
|
|
64
|
+
* function Panel({ runId, onClear }: { runId: string; onClear: () => void }) {
|
|
65
|
+
* const { run } = useWorkflowRun<{ draft: string }>(runId);
|
|
66
|
+
* if (!run) return null;
|
|
67
|
+
* return (
|
|
68
|
+
* <WorkflowRunPanel run={run} statusLabels={{ running: "Writing…" }} onClear={onClear}>
|
|
69
|
+
* {(output) => <article className="whitespace-pre-wrap">{output.draft}</article>}
|
|
70
|
+
* </WorkflowRunPanel>
|
|
71
|
+
* );
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* @param props - See {@link WorkflowRunPanelProps}.
|
|
76
|
+
*
|
|
77
|
+
* @public
|
|
78
|
+
*/
|
|
79
|
+
export declare function WorkflowRunPanel<O = unknown>({ run, statusLabels, onClear, api, live, children, className, }: WorkflowRunPanelProps<O>): ReactNode;
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { BrowserSession, SendTextOptions, SessionSnapshot } from "./session/index.ts";
|
|
3
|
+
import type { AgentState, ClientTheme, SessionError } from "./types.ts";
|
|
4
|
+
/**
|
|
5
|
+
* Provides the {@link BrowserSession} the session hooks read. `mountClient()`
|
|
6
|
+
* installs it automatically; a custom tree only needs it when bypassing
|
|
7
|
+
* `mountClient()` and mounting React itself.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare function SessionProvider({ value, children, }: {
|
|
12
|
+
value: BrowserSession;
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
}): import("react").FunctionComponentElement<import("react").ProviderProps<BrowserSession | null>>;
|
|
15
|
+
/**
|
|
16
|
+
* The session's control methods, and nothing else — what a `client.tsx` may
|
|
17
|
+
* legitimately CALL on a session, as against what it may read.
|
|
18
|
+
*
|
|
19
|
+
* Declared once and merged into {@link Session} rather than written out at both
|
|
20
|
+
* places: the two lists have to be the same list, and a member added to one and
|
|
21
|
+
* not the other is a hook that cannot do what `useSession()` can.
|
|
22
|
+
*
|
|
23
|
+
* DECLARED here rather than picked out of {@link BrowserSession}: that handle is
|
|
24
|
+
* sealed and grows, and a `Pick` made every member it gained a candidate for
|
|
25
|
+
* this list without anyone deciding. Push-to-talk is the case in point — its
|
|
26
|
+
* three edges are `session.userTurn`, reached through `usePushToTalk`, and not
|
|
27
|
+
* actions every chrome is handed. `createBrowserSession` is what keeps each of
|
|
28
|
+
* these assignable from the session's own methods.
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
export type SessionActions = {
|
|
33
|
+
/** Start the call for the first time — see {@link BrowserSession.start}. */
|
|
34
|
+
start(): void;
|
|
35
|
+
/** Cancel the current agent turn and discard in-flight TTS audio. */
|
|
36
|
+
cancel(): void;
|
|
37
|
+
/** Send a typed user turn, answered as if spoken — see {@link BrowserSession.sendText}. */
|
|
38
|
+
sendText(text: string, options?: SendTextOptions): void;
|
|
39
|
+
/** Mute or unmute the mic without dropping the session — see {@link BrowserSession.setMicMuted}. */
|
|
40
|
+
setMicMuted(muted: boolean): void;
|
|
41
|
+
/** Clear messages, transcripts and error state, keeping the connection. */
|
|
42
|
+
resetState(): void;
|
|
43
|
+
/** Clear state and reopen the connection — the same session id. */
|
|
44
|
+
reset(): void;
|
|
45
|
+
/** End the call and begin a fresh one — see {@link BrowserSession.restart}. */
|
|
46
|
+
restart(): void;
|
|
47
|
+
/** Continue an earlier session by its id — see {@link BrowserSession.resume}. */
|
|
48
|
+
resume(sessionId: string): void;
|
|
49
|
+
/** Close the WebSocket and release all audio resources. */
|
|
50
|
+
disconnect(): void;
|
|
51
|
+
/** Toggle between connected and disconnected (after `start()`). */
|
|
52
|
+
toggle(): void;
|
|
53
|
+
/** End the call and return to the not-started state — see {@link BrowserSession.end}. */
|
|
54
|
+
end(): void;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* What {@link useSession} returns: the live {@link SessionSnapshot} fields
|
|
58
|
+
* (`state`, `messages`, `toolCalls`, `agentState`, live transcripts, `error`,
|
|
59
|
+
* `apiUrl`, `started`/`running`/`recording`, …) merged with the session's
|
|
60
|
+
* control methods (`start`, `toggle`, `reset`, `restart`, `resume`, `resetState`,
|
|
61
|
+
* `disconnect`, `cancel`, `end`, `sendText`, `setMicMuted`).
|
|
62
|
+
*
|
|
63
|
+
* `sendText(text)` is the one input besides the microphone: a typed turn the
|
|
64
|
+
* agent answers aloud, as if it had been spoken.
|
|
65
|
+
*
|
|
66
|
+
* @public
|
|
67
|
+
*/
|
|
68
|
+
export type Session = SessionSnapshot & SessionActions;
|
|
69
|
+
/**
|
|
70
|
+
* Return the raw {@link BrowserSession} from context without subscribing to
|
|
71
|
+
* snapshot changes. Useful for accessing stable methods (`start`, `toggle`,
|
|
72
|
+
* `reset`, …) from components that select narrow state via
|
|
73
|
+
* {@link useSessionSelector}.
|
|
74
|
+
*
|
|
75
|
+
* Not part of the package's public export surface — internal to aai-ui
|
|
76
|
+
* components.
|
|
77
|
+
*/
|
|
78
|
+
export declare function useSessionCore(): BrowserSession;
|
|
79
|
+
/** The session from context, or `null` outside the provider (`useRoute` on a `mountPage()` page). */
|
|
80
|
+
export declare function useOptionalSessionCore(): BrowserSession | null;
|
|
81
|
+
/**
|
|
82
|
+
* The session's control methods — `start`, `cancel`, `sendText`,
|
|
83
|
+
* `setMicMuted`, `resetState`, `reset`, `restart`, `resume`, `disconnect`,
|
|
84
|
+
* `toggle`, `end` — with **no snapshot subscription**.
|
|
85
|
+
* Push-to-talk is not among them: that is `usePushToTalk`.
|
|
86
|
+
*
|
|
87
|
+
* This is the narrow half of {@link useSession}, and it is the half a custom
|
|
88
|
+
* chrome could not reach. `<Controls>` and `<StartScreen>` in this package pair
|
|
89
|
+
* a one-field `useSessionSelector` with this package's own `useSessionCore`
|
|
90
|
+
* (`context.ts`, unpublished); a `client.tsx`
|
|
91
|
+
* could not, because that hook is not published — so a footer needing `start`
|
|
92
|
+
* and `toggle` held a WHOLE-SNAPSHOT `useSession()`, and `session/browser-session.ts`
|
|
93
|
+
* rebuilds the snapshot object on every change. Measured consequence: four
|
|
94
|
+
* components across three templates re-rendered on every STT partial and every
|
|
95
|
+
* streaming delta, in files whose every other component is narrowly subscribed
|
|
96
|
+
* on purpose. One of them (`text-adventure-agent`'s `TitleScreen`) reads nothing
|
|
97
|
+
* from the snapshot at all and subscribes to all of it for `session.start`.
|
|
98
|
+
*
|
|
99
|
+
* **Why publishing this does not reopen what `/internal` closed.**
|
|
100
|
+
* `useSessionCore` hands back the STORE — `subscribe`, `getSnapshot`,
|
|
101
|
+
* `connect`, `Symbol.dispose` — which is the framework's own plumbing, the same
|
|
102
|
+
* category as the providers and `buildAgentUrl` that live on
|
|
103
|
+
* `@alexkroman1/aai-ui/internal`. A client that holds it can subscribe out of
|
|
104
|
+
* band of React, dial a socket the mount did not, and dispose the session under
|
|
105
|
+
* the tree that is rendering it. What comes back from here is the SAME
|
|
106
|
+
* methods `useSession()` already publishes on its result, built into a fresh
|
|
107
|
+
* object rather than passed through, so the store is not reachable from it.
|
|
108
|
+
* There is no new capability here — only the existing one without the
|
|
109
|
+
* subscription tax.
|
|
110
|
+
*
|
|
111
|
+
* Identity-stable per core, so it is safe in a dependency array and in a
|
|
112
|
+
* `memo()` child's props: the methods are closures created once by
|
|
113
|
+
* `createBrowserSession`, and the object wrapping them is memoized on the core.
|
|
114
|
+
*
|
|
115
|
+
* Throws outside the provider `mountClient()` installs, like every session hook.
|
|
116
|
+
*
|
|
117
|
+
* @example A footer that acts on the session without re-rendering with it
|
|
118
|
+
* ```tsx
|
|
119
|
+
* import { useSessionActions, useSessionSelector } from "@alexkroman1/aai-ui";
|
|
120
|
+
*
|
|
121
|
+
* function Footer() {
|
|
122
|
+
* // Two narrow subscriptions and no snapshot read: this row re-renders when
|
|
123
|
+
* // `running` flips, and not on every transcript delta.
|
|
124
|
+
* const running = useSessionSelector((s) => s.running);
|
|
125
|
+
* const { toggle, end } = useSessionActions();
|
|
126
|
+
* return (
|
|
127
|
+
* <>
|
|
128
|
+
* <button onClick={toggle}>{running ? "Pause" : "Resume"}</button>
|
|
129
|
+
* <button onClick={end}>Hang up</button>
|
|
130
|
+
* </>
|
|
131
|
+
* );
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* @returns The control methods — see {@link SessionActions}.
|
|
136
|
+
*
|
|
137
|
+
* @public
|
|
138
|
+
*/
|
|
139
|
+
export declare function useSessionActions(): SessionActions;
|
|
140
|
+
/**
|
|
141
|
+
* Return the live {@link Session}: the current snapshot fields plus the
|
|
142
|
+
* control methods (`start`, `toggle`, `reset`, `resetState`, `disconnect`,
|
|
143
|
+
* `cancel`, `end`).
|
|
144
|
+
*
|
|
145
|
+
* Throws if used outside the provider `mountClient()` installs (the error names
|
|
146
|
+
* `<SessionProvider>` — you only mount that yourself when bypassing
|
|
147
|
+
* `mountClient()`). Re-renders the component on *every* snapshot change; for a
|
|
148
|
+
* component that reads one field, prefer {@link useSessionSelector} for a
|
|
149
|
+
* targeted subscription.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```tsx
|
|
153
|
+
* import { useSession } from "@alexkroman1/aai-ui";
|
|
154
|
+
*
|
|
155
|
+
* function Controls() {
|
|
156
|
+
* const session = useSession();
|
|
157
|
+
* if (!session.started) return <button onClick={session.start}>Start</button>;
|
|
158
|
+
* return <button onClick={session.toggle}>{session.running ? "Pause" : "Resume"}</button>;
|
|
159
|
+
* }
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* @public
|
|
163
|
+
*/
|
|
164
|
+
export declare function useSession(): Session;
|
|
165
|
+
/**
|
|
166
|
+
* Subscribe to a narrow slice of the session snapshot.
|
|
167
|
+
*
|
|
168
|
+
* Unlike {@link useSession} — which re-renders the component on *every*
|
|
169
|
+
* snapshot change — this only triggers a re-render when the selected value
|
|
170
|
+
* changes (per `isEqual`, default `Object.is`). Use it for components that
|
|
171
|
+
* read a single field, e.g. `useSessionSelector((s) => s.running)`.
|
|
172
|
+
*
|
|
173
|
+
* The selector must be pure. It may run on every snapshot change, so keep it
|
|
174
|
+
* cheap; when it returns a derived object, pass a custom `isEqual` to avoid
|
|
175
|
+
* re-renders on referentially-new-but-equal results.
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* ```tsx
|
|
179
|
+
* import { useSessionSelector } from "@alexkroman1/aai-ui";
|
|
180
|
+
*
|
|
181
|
+
* // Re-renders when `running` flips, and on nothing else — not on every
|
|
182
|
+
* // transcript delta the way `useSession()` would.
|
|
183
|
+
* function MicDot() {
|
|
184
|
+
* const running = useSessionSelector((snapshot) => snapshot.running);
|
|
185
|
+
* return <span>{running ? "●" : "○"}</span>;
|
|
186
|
+
* }
|
|
187
|
+
* ```
|
|
188
|
+
*
|
|
189
|
+
* @param selector - Reads the slice out of the snapshot. Must be pure.
|
|
190
|
+
* @param isEqual - Compares two selected values. Defaults to `Object.is`.
|
|
191
|
+
* @returns The selected slice.
|
|
192
|
+
*
|
|
193
|
+
* @public
|
|
194
|
+
*/
|
|
195
|
+
export declare function useSessionSelector<T>(selector: (snapshot: SessionSnapshot) => T, isEqual?: (a: T, b: T) => boolean): T;
|
|
196
|
+
/**
|
|
197
|
+
* The agent's live {@link AgentState} — `disconnected`, `connecting`, `ready`,
|
|
198
|
+
* `listening`, `thinking`, `speaking`, `error` — on its own narrow
|
|
199
|
+
* subscription.
|
|
200
|
+
*
|
|
201
|
+
* `useSessionSelector((s) => s.state)` spelled once. It is one of exactly two
|
|
202
|
+
* snapshot fields that more than one custom chrome ever selects (the other is
|
|
203
|
+
* {@link useSessionError}), and it had been written inline at eight sites —
|
|
204
|
+
* including inside this package and, worse, in `ConsoleShell`'s own `@example`,
|
|
205
|
+
* which taught the inline form to everyone who read it.
|
|
206
|
+
*
|
|
207
|
+
* **Named `useSessionStatus`, not `useSessionState`.** `useAgentState` is the
|
|
208
|
+
* SLOT hook — the agent's own synced application state, whatever a
|
|
209
|
+
* `sessionSlot()` projects — and `AgentState` here is the phase of the CALL.
|
|
210
|
+
* Two different concepts one letter apart, so the shorter-sounding name is the
|
|
211
|
+
* one deliberately not taken.
|
|
212
|
+
*
|
|
213
|
+
* Pair it with {@link AGENT_STATE_LABELS} for a rendered word; the raw member
|
|
214
|
+
* is a wire value, not a label.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```tsx
|
|
218
|
+
* import { AGENT_STATE_LABELS, useSessionStatus } from "@alexkroman1/aai-ui";
|
|
219
|
+
*
|
|
220
|
+
* function StatusDot() {
|
|
221
|
+
* const status = useSessionStatus();
|
|
222
|
+
* return <span data-state={status}>{AGENT_STATE_LABELS[status]}</span>;
|
|
223
|
+
* }
|
|
224
|
+
* ```
|
|
225
|
+
*
|
|
226
|
+
* @returns The current agent state.
|
|
227
|
+
*
|
|
228
|
+
* @public
|
|
229
|
+
*/
|
|
230
|
+
export declare function useSessionStatus(): AgentState;
|
|
231
|
+
/**
|
|
232
|
+
* The session's current {@link SessionError}, or `null` when there is none, on
|
|
233
|
+
* its own narrow subscription.
|
|
234
|
+
*
|
|
235
|
+
* The other half of {@link useSessionStatus} — the second of the two fields a
|
|
236
|
+
* custom chrome reads over and over, and the one whose absence is invisible:
|
|
237
|
+
* per the `fatalError` latch in `session/browser-session.ts` the error is the ONLY
|
|
238
|
+
* remaining signal that a session died, since the state beside it goes back to
|
|
239
|
+
* reading like a live one.
|
|
240
|
+
*
|
|
241
|
+
* A chrome rendering it owes `role="alert"` — which is what
|
|
242
|
+
* {@link SessionErrorBanner} is for, and why reaching for that beats reaching
|
|
243
|
+
* for this.
|
|
244
|
+
*
|
|
245
|
+
* @returns The current error, or `null`.
|
|
246
|
+
*
|
|
247
|
+
* @public
|
|
248
|
+
*/
|
|
249
|
+
export declare function useSessionError(): SessionError | null;
|
|
250
|
+
/**
|
|
251
|
+
* Provides the theme the components read via `useTheme`. `mountClient()` installs
|
|
252
|
+
* it automatically (from `ClientConfig.theme`); a custom tree only needs it
|
|
253
|
+
* when bypassing `mountClient()` and mounting React itself.
|
|
254
|
+
*
|
|
255
|
+
* @internal
|
|
256
|
+
*/
|
|
257
|
+
export declare function ThemeProvider({ value, children, }: {
|
|
258
|
+
value?: ClientTheme | undefined;
|
|
259
|
+
children?: ReactNode;
|
|
260
|
+
}): import("react").FunctionComponentElement<import("react").ProviderProps<Required<ClientTheme>>>;
|
|
261
|
+
/**
|
|
262
|
+
* Read the resolved theme (every {@link ClientTheme} field filled with its
|
|
263
|
+
* default) from the nearest theme context. Returns the default theme when no
|
|
264
|
+
* provider is present, so components can call it unconditionally.
|
|
265
|
+
*
|
|
266
|
+
* This is how a custom component stays on the agent's palette: a
|
|
267
|
+
* `mountClient({ theme })` override reaches it here, where a hardcoded colour or a
|
|
268
|
+
* Tailwind class cannot see it.
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* ```tsx
|
|
272
|
+
* import { useTheme } from "@alexkroman1/aai-ui";
|
|
273
|
+
*
|
|
274
|
+
* function Total({ amount }: { amount: string }) {
|
|
275
|
+
* const theme = useTheme();
|
|
276
|
+
* return (
|
|
277
|
+
* <strong style={{ color: theme.primary, background: theme.surface }}>
|
|
278
|
+
* {amount}
|
|
279
|
+
* </strong>
|
|
280
|
+
* );
|
|
281
|
+
* }
|
|
282
|
+
* ```
|
|
283
|
+
*
|
|
284
|
+
* @returns Every {@link ClientTheme} field, filled in.
|
|
285
|
+
*
|
|
286
|
+
* @public
|
|
287
|
+
*/
|
|
288
|
+
export declare function useTheme(): Required<ClientTheme>;
|