@alexkroman1/aai-ui 0.12.3 → 0.14.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 +253 -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 +34 -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 +29 -21
- package/dist/components/button.js +62 -23
- package/dist/components/chat-view.d.ts +24 -18
- package/dist/components/chat-view.js +2 -60
- package/dist/components/console-shell.d.ts +85 -0
- package/dist/components/controls.d.ts +21 -6
- package/dist/components/controls.js +31 -19
- 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 +34 -7
- package/dist/components/message-list.js +2 -75
- 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 +31 -10
- package/dist/components/sidebar-layout.js +32 -12
- package/dist/components/start-screen.d.ts +17 -6
- package/dist/components/start-screen.js +34 -14
- package/dist/components/tool-call-block.d.ts +15 -14
- package/dist/components/tool-call-block.js +2 -117
- 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-mpgipo2Q.js +1 -0
- package/dist/default-client/assets/capture-processor-D0q7Qrdd.js +90 -0
- package/dist/default-client/assets/index-8ihb1Urm.css +2 -0
- package/dist/default-client/assets/index-DPfmSFmc.js +126 -0
- package/dist/default-client/assets/playback-processor-CjDbc9iH.js +314 -0
- package/dist/default-client/favicon.ico +0 -0
- package/dist/default-client/index.html +15 -0
- package/dist/default-client-entry.d.ts +6 -0
- package/dist/default-client.d.ts +19 -0
- package/dist/define-client.d.ts +169 -26
- package/dist/define-client.js +209 -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 +126 -29
- package/dist/index.js +5500 -15
- 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 +37 -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 +39 -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-D9jM5-TF.js +2140 -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 +59 -32
- package/styles.css +152 -30
- package/dist/_jsdom-setup.d.ts +0 -0
- 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/components/app.d.ts +0 -23
- package/dist/components/app.js +0 -41
- 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/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-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/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
|
@@ -1,118 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { useComputed, useSignal } from "@preact/signals";
|
|
4
|
-
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
5
|
-
//#region components/tool-call-block.tsx
|
|
6
|
-
const argField = (key) => (args) => String(args[key] ?? "");
|
|
7
|
-
const TOOL_CONFIG = {
|
|
8
|
-
web_search: {
|
|
9
|
-
Icon: SearchIcon,
|
|
10
|
-
title: "Web Search",
|
|
11
|
-
subtitle: argField("query")
|
|
12
|
-
},
|
|
13
|
-
visit_webpage: {
|
|
14
|
-
Icon: ExternalLinkIcon,
|
|
15
|
-
title: "Visit Page",
|
|
16
|
-
subtitle: argField("url")
|
|
17
|
-
},
|
|
18
|
-
run_code: {
|
|
19
|
-
Icon: TerminalIcon,
|
|
20
|
-
title: "Run Code",
|
|
21
|
-
subtitle: (args) => {
|
|
22
|
-
const firstLine = String(args.code ?? "").split("\n")[0] ?? "";
|
|
23
|
-
return firstLine.length > 80 ? `${firstLine.slice(0, 80)}...` : firstLine;
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
fetch_json: {
|
|
27
|
-
Icon: DownloadIcon,
|
|
28
|
-
title: "Fetch JSON",
|
|
29
|
-
subtitle: argField("url")
|
|
30
|
-
},
|
|
31
|
-
user_input: {
|
|
32
|
-
Icon: ChatBubbleIcon,
|
|
33
|
-
title: "Asking User",
|
|
34
|
-
subtitle: argField("question")
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
const DEFAULT_CONFIG = {
|
|
38
|
-
Icon: BoltIcon,
|
|
39
|
-
title: "",
|
|
40
|
-
subtitle: (args) => {
|
|
41
|
-
const summary = JSON.stringify(args);
|
|
42
|
-
return summary.length > 80 ? `${summary.slice(0, 80)}...` : summary;
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
function formatResult(result) {
|
|
46
|
-
try {
|
|
47
|
-
return JSON.stringify(JSON.parse(result), null, 2);
|
|
48
|
-
} catch {
|
|
49
|
-
return result;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Renders a tool invocation with an icon, title, subtitle, and a
|
|
54
|
-
* collapsible result viewer.
|
|
55
|
-
*
|
|
56
|
-
* Built-in tool types (`web_search`, `visit_webpage`, `run_code`,
|
|
57
|
-
* `fetch_json`, `user_input`) get custom icons and labels. Unknown tools
|
|
58
|
-
* fall back to a generic bolt icon.
|
|
59
|
-
*
|
|
60
|
-
* While the tool call is pending a shimmer animation is shown. Once
|
|
61
|
-
* complete, clicking the block expands the formatted JSON result.
|
|
62
|
-
*
|
|
63
|
-
* @example
|
|
64
|
-
* ```tsx
|
|
65
|
-
* <ToolCallBlock toolCall={toolCall} />
|
|
66
|
-
* ```
|
|
67
|
-
*
|
|
68
|
-
* @param toolCall - The tool call to render (see {@link ToolCallInfo}).
|
|
69
|
-
* @param className - Additional CSS class names.
|
|
70
|
-
*
|
|
71
|
-
* @public
|
|
72
|
-
*/
|
|
73
|
-
function ToolCallBlock({ toolCall, className }) {
|
|
74
|
-
const isOpen = useSignal(false);
|
|
75
|
-
const config = TOOL_CONFIG[toolCall.toolName] ?? DEFAULT_CONFIG;
|
|
76
|
-
const isPending = toolCall.status === "pending";
|
|
77
|
-
const title = config.title || toolCall.toolName;
|
|
78
|
-
const canExpand = !isPending && Boolean(toolCall.result);
|
|
79
|
-
const formatted = useComputed(() => toolCall.result ? formatResult(toolCall.result) : "");
|
|
80
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
81
|
-
class: clsx("flex flex-col", className),
|
|
82
|
-
children: [/* @__PURE__ */ jsxs("button", {
|
|
83
|
-
type: "button",
|
|
84
|
-
"aria-expanded": canExpand ? isOpen.value : void 0,
|
|
85
|
-
disabled: isPending,
|
|
86
|
-
class: clsx("flex items-center gap-2 px-3 py-2 rounded-aai border border-aai-border bg-aai-surface-faint select-none text-left w-full", canExpand && "cursor-pointer"),
|
|
87
|
-
onClick: () => {
|
|
88
|
-
if (canExpand) isOpen.value = !isOpen.value;
|
|
89
|
-
},
|
|
90
|
-
children: [
|
|
91
|
-
/* @__PURE__ */ jsx(config.Icon, { class: "w-4 h-4 text-aai-text-dim shrink-0" }),
|
|
92
|
-
/* @__PURE__ */ jsx("span", {
|
|
93
|
-
class: clsx("text-sm font-medium text-aai-text", isPending && "tool-shimmer"),
|
|
94
|
-
children: title
|
|
95
|
-
}),
|
|
96
|
-
/* @__PURE__ */ jsx("span", {
|
|
97
|
-
class: "text-sm text-aai-text-dim truncate flex-1 min-w-0",
|
|
98
|
-
children: config.subtitle(toolCall.args)
|
|
99
|
-
}),
|
|
100
|
-
canExpand && /* @__PURE__ */ jsx("span", {
|
|
101
|
-
class: "text-xs text-aai-text-dim shrink-0",
|
|
102
|
-
children: isOpen.value ? "▾" : "▸"
|
|
103
|
-
})
|
|
104
|
-
]
|
|
105
|
-
}), isOpen.value && /* @__PURE__ */ jsxs("div", {
|
|
106
|
-
class: "border-x border-b border-aai-border rounded-b-aai bg-aai-surface max-h-64 overflow-auto",
|
|
107
|
-
children: [toolCall.toolName === "run_code" && toolCall.args.code && /* @__PURE__ */ jsx("pre", {
|
|
108
|
-
class: "text-xs text-aai-text p-2 whitespace-pre-wrap border-b border-aai-border font-mono",
|
|
109
|
-
children: String(toolCall.args.code)
|
|
110
|
-
}), formatted.value && /* @__PURE__ */ jsx("pre", {
|
|
111
|
-
class: "text-xs text-aai-text-dim p-2 whitespace-pre-wrap",
|
|
112
|
-
children: formatted.value
|
|
113
|
-
})]
|
|
114
|
-
})]
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
//#endregion
|
|
1
|
+
import "../context.js";
|
|
2
|
+
import { t as ToolCallBlock } from "../tool-call-block-uXtMOUWN.js";
|
|
118
3
|
export { ToolCallBlock };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Size preset for {@link ToolCallRow}: `"default"` is the deployed agent
|
|
4
|
+
* UI's scale, `"compact"` the studio transcript's denser one.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export type ToolCallRowVariant = "default" | "compact";
|
|
9
|
+
/**
|
|
10
|
+
* Props for {@link ToolCallRow}.
|
|
11
|
+
*
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
export interface ToolCallRowProps {
|
|
15
|
+
/** Tool title, rendered in mono (shimmers while `pending`). */
|
|
16
|
+
title: ReactNode;
|
|
17
|
+
/** One-line detail (typically an args preview), truncated to the row. */
|
|
18
|
+
detail?: ReactNode | undefined;
|
|
19
|
+
/** True while the call is in flight — animates the title with a shimmer. */
|
|
20
|
+
pending?: boolean | undefined;
|
|
21
|
+
/** Optional icon rendered in place of the outlined "TOOL" chip. */
|
|
22
|
+
icon?: ReactNode | undefined;
|
|
23
|
+
/** Size preset; defaults to `"default"`. */
|
|
24
|
+
variant?: ToolCallRowVariant | undefined;
|
|
25
|
+
/** Additional CSS class names for the outer container. */
|
|
26
|
+
className?: string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Expanded panel content. When present the row is expandable: a chevron is
|
|
29
|
+
* shown and clicking toggles the panel. When absent the row is inert (the
|
|
30
|
+
* button is disabled). Content provides its own padding and typography;
|
|
31
|
+
* the panel supplies the top border, surface background, and a max height.
|
|
32
|
+
*/
|
|
33
|
+
children?: ReactNode;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The design system's console row for one tool invocation: a small outlined
|
|
37
|
+
* "TOOL" chip (or a custom `icon`), the tool title in mono, a truncated
|
|
38
|
+
* detail preview, and a rotating chevron that expands to the panel content.
|
|
39
|
+
*
|
|
40
|
+
* Purely presentational — callers own the mapping from their tool-call data
|
|
41
|
+
* to `title`/`detail`/`pending` and the expanded panel. The deployed agent
|
|
42
|
+
* UI's message list renders it via its tool-call block, and the studio's
|
|
43
|
+
* chat transcript renders it with `variant="compact"`, so the two surfaces
|
|
44
|
+
* read as one component.
|
|
45
|
+
*
|
|
46
|
+
* Colors come from the nearest theme context (see {@link useTheme}); without
|
|
47
|
+
* a provider the default AssemblyAI theme applies.
|
|
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
|
+
*
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
export declare function ToolCallRow({ title, detail, pending, icon, variant, className, children, }: ToolCallRowProps): ReactNode;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Display configuration for a tool call in the UI.
|
|
3
|
+
*
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export type ToolDisplayConfig = Record<string, {
|
|
7
|
+
icon?: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
}>;
|
|
10
|
+
/**
|
|
11
|
+
* Context for tool display configuration. Installed by `mountClient()` from
|
|
12
|
+
* `ClientConfig.tools`; the built-in components read it via `useToolConfig`.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export declare const ToolConfigContext: import("react").Context<ToolDisplayConfig>;
|
|
17
|
+
/**
|
|
18
|
+
* Read tool display configuration from the nearest `ToolConfigContext.Provider`.
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export declare function useToolConfig(): ToolDisplayConfig;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { UploadStatus } from "../use-workflow-form.ts";
|
|
3
|
+
/**
|
|
4
|
+
* How far a form's files have got, rendered as a bar.
|
|
5
|
+
*
|
|
6
|
+
* The wait this covers is the one a run cannot describe: a workflow run does not
|
|
7
|
+
* EXIST until its input is stored, so from the moment a form is submitted until
|
|
8
|
+
* the last byte lands there is no run id, no status, and nothing for
|
|
9
|
+
* `<WorkflowProgress>` to read — which for a 200 MB recording is minutes of a
|
|
10
|
+
* page that looks stuck. `useWorkflowSubmit` reports the bytes as they go and
|
|
11
|
+
* this is what draws them.
|
|
12
|
+
*
|
|
13
|
+
* Three things it decides, so a page does not:
|
|
14
|
+
*
|
|
15
|
+
* - **It renders nothing when there is nothing to describe.** `upload` is
|
|
16
|
+
* undefined before the first byte and again from the moment the last one
|
|
17
|
+
* lands, so `<UploadProgressBar upload={upload} />` is correct unguarded and a
|
|
18
|
+
* form with no files never shows a bar at all.
|
|
19
|
+
* - **An unknown total is INDETERMINATE, not zero.** A body whose length the
|
|
20
|
+
* transport cannot state up front (see `UploadProgress.total`) has no honest
|
|
21
|
+
* width, and a bar pinned at 0% reads as an upload that is not moving.
|
|
22
|
+
* - **The file is NAMED, and counted when there is more than one.** Files are
|
|
23
|
+
* sent one after another, so a single bar otherwise appears to restart from
|
|
24
|
+
* zero partway through with nothing to say why.
|
|
25
|
+
* - **A paused upload SAYS SO, rather than being a bar that stopped.** Those look
|
|
26
|
+
* identical, which is the whole reason `UploadStatus.paused` exists, and the
|
|
27
|
+
* fill stops animating so the difference is visible without reading.
|
|
28
|
+
*
|
|
29
|
+
* The pause control appears only when a handler for it is passed. That is not
|
|
30
|
+
* politeness about props: a button whose press does nothing is worse than no
|
|
31
|
+
* button, and a page holding an `upload` it did not produce (a saved status, a
|
|
32
|
+
* parent's state) has nothing to pause.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx no-check
|
|
36
|
+
* import { Form, SubmitButton, UploadProgressBar, useWorkflowSubmit, WorkflowFields } from "@alexkroman1/aai-ui";
|
|
37
|
+
* import type { transcribe } from "./agent.ts";
|
|
38
|
+
*
|
|
39
|
+
* function TranscribeForm() {
|
|
40
|
+
* const { submitForm, upload, pending, error } = useWorkflowSubmit<typeof transcribe>("transcribe");
|
|
41
|
+
* return (
|
|
42
|
+
* <Form onSubmit={submitForm} error={error}>
|
|
43
|
+
* <WorkflowFields workflow="transcribe" />
|
|
44
|
+
* <UploadProgressBar upload={upload} />
|
|
45
|
+
* <SubmitButton pending={pending}>Transcribe</SubmitButton>
|
|
46
|
+
* </Form>
|
|
47
|
+
* );
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @param props - Progress-bar props.
|
|
52
|
+
*
|
|
53
|
+
* @public
|
|
54
|
+
*/
|
|
55
|
+
export declare function UploadProgressBar({ upload, onPause, onResume, className, }: {
|
|
56
|
+
/**
|
|
57
|
+
* What `useWorkflowSubmit` / `useWorkflowStream` report as `upload`.
|
|
58
|
+
* `undefined` renders nothing, so a page may pass its state straight through
|
|
59
|
+
* and never guard the element.
|
|
60
|
+
*/
|
|
61
|
+
upload?: UploadStatus | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* The hook's `pauseUpload`. **Pass it together with `onResume`** to get the
|
|
64
|
+
* pause control; pass neither for a bar that only reports. One without the
|
|
65
|
+
* other is a one-way door drawn as a toggle, so the control is hidden unless
|
|
66
|
+
* both are present.
|
|
67
|
+
*/
|
|
68
|
+
onPause?: (() => void) | undefined;
|
|
69
|
+
/** The hook's `resumeUpload`. See `onPause` — the two travel together. */
|
|
70
|
+
onResume?: (() => void) | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* **Replaces** the default classes rather than extending them, so a custom
|
|
73
|
+
* chrome is not fighting a default it did not ask for.
|
|
74
|
+
*/
|
|
75
|
+
className?: string | undefined;
|
|
76
|
+
}): ReactNode;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The session's shareable UI URL — the page this UI is served from, what
|
|
3
|
+
* you'd send someone to talk to the agent.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export declare function UiUrlChip({ className }: {
|
|
8
|
+
className?: string | undefined;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
10
|
+
/**
|
|
11
|
+
* The session's programmatic WebSocket endpoint — the URL a script or backend
|
|
12
|
+
* can connect to directly instead of using this UI.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export declare function ApiUrlChip({ className }: {
|
|
17
|
+
className?: string | undefined;
|
|
18
|
+
}): import("react").JSX.Element;
|
|
19
|
+
/**
|
|
20
|
+
* The UI and API URLs side by side. They answer the same question — "how do I
|
|
21
|
+
* reach this agent?" — so they belong together and each needs its label to be
|
|
22
|
+
* told apart. Rendered by the default shell in every session mode (S2S,
|
|
23
|
+
* pipeline).
|
|
24
|
+
*
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare function SessionUrlChips({ className }: {
|
|
28
|
+
className?: string | undefined;
|
|
29
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { WorkflowSummary } from "@alexkroman1/aai/workflow-api";
|
|
2
|
+
/**
|
|
3
|
+
* Render one field per scalar property of a workflow's input schema.
|
|
4
|
+
*
|
|
5
|
+
* Pass the workflow's NAME and the schema is fetched here; pass a
|
|
6
|
+
* {@link WorkflowSummary} you already hold and nothing is fetched. The name form
|
|
7
|
+
* is the one a page usually wants — it is the same string the submit hook takes,
|
|
8
|
+
* and the alternative is three lines (`useWorkflows()`, a `.find()` by name, and
|
|
9
|
+
* folding that lookup's error into the form's) whose only product is this
|
|
10
|
+
* component's argument.
|
|
11
|
+
*
|
|
12
|
+
* Renders nothing when the workflow declared no schema — a workflow with no
|
|
13
|
+
* declared input takes anything, and a form for "anything" is not a form — and
|
|
14
|
+
* nothing while a named lookup is still in flight, so the hand-written fields
|
|
15
|
+
* beside it are not reordered when the schema lands.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx no-check
|
|
19
|
+
* import { Form, SubmitButton, WorkflowFields, useWorkflowSubmit }
|
|
20
|
+
* from "@alexkroman1/aai-ui";
|
|
21
|
+
* import type { transcribe } from "./agent.ts";
|
|
22
|
+
*
|
|
23
|
+
* function StartRun() {
|
|
24
|
+
* const { submitForm, pending, error } = useWorkflowSubmit<typeof transcribe>("transcribe");
|
|
25
|
+
* return (
|
|
26
|
+
* <Form onSubmit={submitForm} error={error}>
|
|
27
|
+
* <WorkflowFields workflow="transcribe" />
|
|
28
|
+
* <SubmitButton pending={pending}>Transcribe</SubmitButton>
|
|
29
|
+
* </Form>
|
|
30
|
+
* );
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @param props - Field-set props.
|
|
35
|
+
*
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
export declare function WorkflowFields({ workflow, }: {
|
|
39
|
+
/**
|
|
40
|
+
* The workflow whose input schema to render. A NAME is looked up here (one
|
|
41
|
+
* `GET workflows`); a {@link WorkflowSummary} the page already holds fetches
|
|
42
|
+
* nothing. `undefined` renders nothing, so a page may pass a selection
|
|
43
|
+
* straight through before one is made.
|
|
44
|
+
*/
|
|
45
|
+
workflow?: WorkflowSummary | string | undefined;
|
|
46
|
+
}): import("react").JSX.Element | null;
|
|
@@ -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;
|