@alexkroman1/aai-ui 0.17.0 → 0.18.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 +6 -7
- package/dist/_submission-timing.d.ts +40 -0
- package/dist/_submission.d.ts +56 -0
- package/dist/_theme.d.ts +17 -0
- package/dist/_theme.test-d.d.ts +14 -0
- package/dist/{_utils-Mi-SCFA1.js → _utils-BlZBJPdj.js} +4 -5
- package/dist/_utils.d.ts +4 -5
- package/dist/agent-state.d.ts +4 -2
- package/dist/append-dictation.d.ts +23 -0
- package/dist/audio/dictation.d.ts +36 -0
- package/dist/audio/index.d.ts +4 -2
- package/dist/audio/index.js +44 -1
- package/dist/{chat-view-W6KcdjJY.js → chat-view-BwKpF0MN.js} +27 -17
- package/dist/{client-config-CzvWmw4X.js → client-config-DcMCWmkO.js} +1 -1
- package/dist/components/button.js +1 -1
- package/dist/components/chat-view.js +1 -2
- package/dist/components/controls.js +2 -2
- package/dist/components/form-fields.d.ts +24 -5
- package/dist/components/form-types.d.ts +32 -0
- package/dist/components/form.d.ts +1 -1
- package/dist/components/message-list.js +1 -2
- package/dist/components/session-state-dot.d.ts +30 -18
- package/dist/components/sidebar-layout.js +1 -1
- package/dist/components/start-screen.js +2 -2
- package/dist/components/tool-call-block.js +1 -2
- package/dist/components/tool-config-context.d.ts +21 -4
- package/dist/components/workflow-fields.d.ts +36 -12
- package/dist/components/workflow-pending-note.d.ts +30 -12
- package/dist/context-BF0KsI9X.js +473 -0
- package/dist/context.js +1 -381
- package/dist/default-client/assets/audio-CtBvSS3L.js +1 -0
- package/dist/default-client/assets/{capture-processor-Cx1AdMHL.js → capture-processor-BZXisGjZ.js} +1 -1
- package/dist/default-client/assets/index-BkjCv4MX.css +2 -0
- package/dist/default-client/assets/index-DUQoaxdq.js +127 -0
- package/dist/default-client/assets/{playback-processor-CCwTknSu.js → playback-processor-BHk-iXEU.js} +1 -1
- package/dist/default-client/index.html +2 -2
- package/dist/default-client.d.ts +1 -3
- package/dist/define-client.d.ts +30 -28
- package/dist/define-client.js +84 -43
- package/dist/dictation-transcriber.d.ts +49 -0
- package/dist/{eyebrow-UfmSz9yy.js → eyebrow-Bp4y1rZ9.js} +1 -1
- package/dist/{hooks-DN4gHYsj.js → hooks-1CoQY_Fc.js} +2 -2
- package/dist/hooks.js +1 -2
- package/dist/index.d.ts +11 -8
- package/dist/index.js +849 -263
- package/dist/internal.d.ts +1 -1
- package/dist/internal.js +6 -6
- package/dist/{message-list-BsaBkBgo.js → message-list-BBHLK05X.js} +3 -3
- package/dist/route-fetch.d.ts +7 -1
- package/dist/session/index.js +1 -1
- package/dist/{session-3lgPYNNO.js → session-Rud8mmU-.js} +2 -2
- package/dist/{tool-call-block-uXtMOUWN.js → tool-call-block-C8s6AhjS.js} +4 -4
- package/dist/tool-config-context-Bd-7xrfP.js +28 -0
- package/dist/types.d.ts +47 -2
- package/dist/{url-chips-oyy_Eiqh.js → url-chips-C_SHU6fq.js} +2 -2
- package/dist/use-dictation.d.ts +145 -0
- package/dist/use-route.d.ts +49 -7
- package/dist/use-run-key.d.ts +6 -1
- package/dist/{use-user-transcript-uyHhzy4d.js → use-user-transcript-lOu_uMnf.js} +1 -1
- package/dist/use-workflow-form.d.ts +74 -172
- package/dist/{use-workflow-run-DdhWmbx-.js → use-workflow-run-BTEemod0.js} +2 -2
- package/dist/use-workflow-runs.d.ts +8 -2
- package/dist/use-workflow-stream.d.ts +9 -5
- package/dist/workflow-def-types.d.ts +18 -2
- package/dist/workflow-field-kind.d.ts +59 -7
- package/dist/workflow-submission.d.ts +265 -0
- package/package.json +2 -2
- package/dist/default-client/assets/audio-Ct7JpSNT.js +0 -1
- package/dist/default-client/assets/index-BlUYCTB5.js +0 -126
- package/dist/default-client/assets/index-_-x5JLLa.css +0 -2
- package/dist/tool-config-context-Es4YUzV2.js +0 -19
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* `useWorkflowRun` (`workflow-client.ts`) watches a run you already have.
|
|
5
5
|
* This is what comes before it: `useWorkflowSubmit` starts a run and hands the
|
|
6
6
|
* id straight to `useWorkflowRun`. Its sibling `useWorkflows` — the listing
|
|
7
|
-
* `<WorkflowFields>` renders a form from — is `use-workflows.ts`.
|
|
7
|
+
* `<WorkflowFields>` renders a form from — is `use-workflows.ts`. What it hands
|
|
8
|
+
* back is `WorkflowSubmission` (`workflow-submission.ts`).
|
|
8
9
|
*
|
|
9
10
|
* ## `useWorkflowSubmit` — a form's two halves in one hook
|
|
10
11
|
*
|
|
@@ -31,168 +32,11 @@
|
|
|
31
32
|
* `wait` here when the page really does want one request, and the run is
|
|
32
33
|
* followed from the same id either way.
|
|
33
34
|
*/
|
|
34
|
-
import type { AnyWorkflowDef, UploadParallelOption,
|
|
35
|
-
import type {
|
|
36
|
-
import type {
|
|
37
|
-
import type {
|
|
38
|
-
|
|
39
|
-
* What {@link WorkflowSubmission.upload} reports while the bytes are going.
|
|
40
|
-
*
|
|
41
|
-
* The SDK's per-request {@link UploadProgress} plus WHICH file it describes,
|
|
42
|
-
* because a form is allowed more than one and a bar over "the upload" would
|
|
43
|
-
* restart at zero partway through with nothing to say why.
|
|
44
|
-
*
|
|
45
|
-
* @sealed
|
|
46
|
-
* @public
|
|
47
|
-
*/
|
|
48
|
-
export type UploadStatus = UploadProgress & {
|
|
49
|
-
/** The file being sent, by the name the picker gave it. */
|
|
50
|
-
name: string;
|
|
51
|
-
/** Which file of the submission this is, counting from 1. */
|
|
52
|
-
index: number;
|
|
53
|
-
/** How many files this submission sends in total. */
|
|
54
|
-
count: number;
|
|
55
|
-
/**
|
|
56
|
-
* Whether the person has parked this upload.
|
|
57
|
-
*
|
|
58
|
-
* A paused upload is not a stopped one: the windows already stored stay stored,
|
|
59
|
-
* `loaded` holds where it got to, and resuming sends what is missing rather than
|
|
60
|
-
* the file. So a bar rendering this reads "Paused at 62%", never "62% and
|
|
61
|
-
* frozen" — which is what a page could otherwise only guess from a number that
|
|
62
|
-
* stopped moving, the same ambiguity `complete` exists to remove on the run side.
|
|
63
|
-
*/
|
|
64
|
-
paused: boolean;
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* What {@link useWorkflowSubmit} returns.
|
|
68
|
-
*
|
|
69
|
-
* @see {@link WorkflowStreamSubmission} — an ALIAS of this type, returned by
|
|
70
|
-
* `useWorkflowStream`, which is a drop-in sibling. Exactly two fields MEAN
|
|
71
|
-
* something different there, and both differences follow from WHEN the run is
|
|
72
|
-
* created: there, `submit()` resolves when the UPLOAD finishes rather than when
|
|
73
|
-
* the run is accepted, and `run` is non-`undefined` from before the bytes are
|
|
74
|
-
* in, so a page can render `<WorkflowProgress>` beside the upload bar instead
|
|
75
|
-
* of after it. Here the run does not exist until the last byte lands.
|
|
76
|
-
*
|
|
77
|
-
* @sealed
|
|
78
|
-
*/
|
|
79
|
-
export type WorkflowSubmission<R = unknown, I = unknown> = {
|
|
80
|
-
/**
|
|
81
|
-
* Start a run with this input. Resolves once the run EXISTS — progress
|
|
82
|
-
* arrives through `run` — so a `<Form>`'s handler can await it to know the
|
|
83
|
-
* submission was accepted.
|
|
84
|
-
*/
|
|
85
|
-
submit: (input: I) => Promise<void>;
|
|
86
|
-
/**
|
|
87
|
-
* Start a run from a `<Form>`'s values, which are UNVALIDATED.
|
|
88
|
-
*
|
|
89
|
-
* The same function as {@link WorkflowSubmission.submit}, with the type the
|
|
90
|
-
* form path can honestly offer. `FormValues` is `Record<string, unknown>`
|
|
91
|
-
* scraped off the DOM at submit time — a `<TextField name="limit">`
|
|
92
|
-
* contributes a string whatever the schema says — so the shape is not known
|
|
93
|
-
* here and the SERVER is what checks it against the workflow's schema.
|
|
94
|
-
*
|
|
95
|
-
* Two doors rather than one loose one: `submit` takes the workflow's own
|
|
96
|
-
* input type, so a hand-built object is checked at compile time and
|
|
97
|
-
* `submit({ ur1: 42 })` is an error; widening it to accept `FormValues` would
|
|
98
|
-
* have made every object satisfy it and given the typing back. Reaching for
|
|
99
|
-
* this one is the author saying "these came from a form", which is a fact
|
|
100
|
-
* about the values and not a cast.
|
|
101
|
-
*/
|
|
102
|
-
submitForm: (values: FormValues) => Promise<void>;
|
|
103
|
-
/** Clear the run and any error, putting the form back to its initial state. */
|
|
104
|
-
reset: () => void;
|
|
105
|
-
/**
|
|
106
|
-
* End the current run's `sleep()` early — "file it now" — resolving how many
|
|
107
|
-
* pending sleeps were interrupted.
|
|
108
|
-
*
|
|
109
|
-
* Bound to the run this submission is following, which is the point: it is
|
|
110
|
-
* the only reason a page holding one of these hooks needed an `api` of its
|
|
111
|
-
* own. `0` is an answer rather than a failure (the run had already moved past
|
|
112
|
-
* its wait, or there is no run yet), so nothing here has to be guarded.
|
|
113
|
-
*/
|
|
114
|
-
wake: () => Promise<number>;
|
|
115
|
-
/**
|
|
116
|
-
* Stop the current run, resolving whether this call is what ended it.
|
|
117
|
-
*
|
|
118
|
-
* `false` for a run that had already finished, and for no run at all — the
|
|
119
|
-
* SDK's contract, because two tabs pressing Stop is ordinary. Distinct from
|
|
120
|
-
* `reset()`, which puts the FORM back and leaves the run running.
|
|
121
|
-
*/
|
|
122
|
-
cancel: () => Promise<boolean>;
|
|
123
|
-
/** The run, once started, followed to completion. */
|
|
124
|
-
run: WorkflowRun<R> | undefined;
|
|
125
|
-
/**
|
|
126
|
-
* True from `submit()` on this mount until `reset()` — did THIS page start
|
|
127
|
-
* the run it is showing?
|
|
128
|
-
*
|
|
129
|
-
* A page needs it to say the right sentence and cannot derive it: a run
|
|
130
|
-
* ADOPTED by the mount-time lookup after a reload looks exactly like one this
|
|
131
|
-
* page started. Six templates kept a `useState(false)` next to this hook, set
|
|
132
|
-
* it in their `onSubmit` and mirrored it in their `onClear` — shadow state
|
|
133
|
-
* for a fact only this hook can know, since it is the thing that decides
|
|
134
|
-
* between `submit()` and the recovery lookup. One of the six grew a fourth
|
|
135
|
-
* branch and had to move the whole note into its own module with its own
|
|
136
|
-
* spec, which is what a seam missing one layer down looks like.
|
|
137
|
-
*
|
|
138
|
-
* The RAW fact rather than a derived "recovered", deliberately: with `run`
|
|
139
|
-
* these are three states, not two, and the third is the one a page most needs
|
|
140
|
-
* to explain. `startedHere` is "you pressed the button"; `!startedHere &&
|
|
141
|
-
* !run` is the mount-time lookup still going; `!startedHere && run` is a run
|
|
142
|
-
* this browser started earlier, now in front of somebody who did not press
|
|
143
|
-
* anything. A boolean meaning only the last of those cannot express the
|
|
144
|
-
* middle one.
|
|
145
|
-
*
|
|
146
|
-
* @example
|
|
147
|
-
* ```ts
|
|
148
|
-
* declare const submission: import("@alexkroman1/aai-ui").WorkflowSubmission;
|
|
149
|
-
* const note = submission.startedHere
|
|
150
|
-
* ? "You can close this tab or reload it — this page will find the run again."
|
|
151
|
-
* : submission.run === undefined
|
|
152
|
-
* ? "Looking for a run this tab started earlier…"
|
|
153
|
-
* : "Still working on the run this tab started earlier. Reloading is safe.";
|
|
154
|
-
* ```
|
|
155
|
-
*/
|
|
156
|
-
startedHere: boolean;
|
|
157
|
-
/**
|
|
158
|
-
* True from `submit()` until the run reaches a terminal status.
|
|
159
|
-
*
|
|
160
|
-
* The WORK, not the request: a run outlives its `POST`, and a submit button
|
|
161
|
-
* that re-enabled on the response would invite a second submission of work
|
|
162
|
-
* already in flight.
|
|
163
|
-
*/
|
|
164
|
-
pending: boolean;
|
|
165
|
-
/**
|
|
166
|
-
* How far the submission's files have got, while any are still going.
|
|
167
|
-
*
|
|
168
|
-
* Undefined before the first byte and again from the moment the last one
|
|
169
|
-
* lands, so a page can render `{upload && <UploadProgressBar upload={upload} />}`
|
|
170
|
-
* and the bar exists exactly for as long as there is an upload to describe. A
|
|
171
|
-
* form with no files never sets it at all.
|
|
172
|
-
*
|
|
173
|
-
* The wait it covers is the one `run` cannot: a run does not EXIST until its
|
|
174
|
-
* input is stored, so `pending` is true and there is nothing to poll — which
|
|
175
|
-
* for a 200 MB recording is minutes of a page that looks stuck.
|
|
176
|
-
*/
|
|
177
|
-
upload: UploadStatus | undefined;
|
|
178
|
-
/**
|
|
179
|
-
* Park the upload where it is, stopping the bytes in flight.
|
|
180
|
-
*
|
|
181
|
-
* The windows already stored stay stored, so `resumeUpload()` sends what is
|
|
182
|
-
* missing rather than the file — which is the difference between a pause a
|
|
183
|
-
* person will actually use on a 200 MB recording and a cancel dressed up as one.
|
|
184
|
-
*
|
|
185
|
-
* `submit()`'s promise stays unresolved across a pause, because the submission
|
|
186
|
-
* genuinely has not finished: the run does not exist until the last byte lands,
|
|
187
|
-
* so resolving here would tell a `<Form>` the work was accepted when nothing has
|
|
188
|
-
* been started. A no-op when there is no upload in flight.
|
|
189
|
-
*/
|
|
190
|
-
pauseUpload: () => void;
|
|
191
|
-
/** Continue a paused upload, sending only the windows the store does not have. */
|
|
192
|
-
resumeUpload: () => void;
|
|
193
|
-
/** The submit's own failure (a rejected input), or the watch's. */
|
|
194
|
-
error: string | undefined;
|
|
195
|
-
};
|
|
35
|
+
import type { AnyWorkflowDef, UploadParallelOption, WorkflowOutputOf } from "@alexkroman1/aai/workflow-api";
|
|
36
|
+
import type { WorkflowApi } from "./workflow-client.ts";
|
|
37
|
+
import type { SubmitInputOf, WorkflowAppLike, WorkflowDefOf, WorkflowNameOf } from "./workflow-def-types.ts";
|
|
38
|
+
import type { WorkflowSubmission } from "./workflow-submission.ts";
|
|
39
|
+
export type { UploadStatus, WorkflowSubmission } from "./workflow-submission.ts";
|
|
196
40
|
/**
|
|
197
41
|
* Options for {@link useWorkflowSubmit}.
|
|
198
42
|
*
|
|
@@ -208,13 +52,22 @@ export type UseWorkflowSubmitOptions = {
|
|
|
208
52
|
* load produces again — `useRunKey()`'s, minted by the hook. Pass one to
|
|
209
53
|
* scope runs to something the page knows better: an ACCOUNT's own id, which
|
|
210
54
|
* is what makes a run follow the person to a new device, or
|
|
211
|
-
* `
|
|
212
|
-
* design. The key is a lookup
|
|
213
|
-
* behind `find`), it must fit the
|
|
214
|
-
* derived from a person's own
|
|
215
|
-
* typed — `use-run-key.ts` argues
|
|
55
|
+
* `{ storage: "local" }` — `useRunKey({ storage: "local" })`'s key, minted
|
|
56
|
+
* here — for a run that outlives the tab by design. The key is a lookup
|
|
57
|
+
* CAPABILITY (there is no per-user filtering behind `find`), it must fit the
|
|
58
|
+
* route's 256-character bound, and anything derived from a person's own
|
|
59
|
+
* input both collides and carries what they typed — `use-run-key.ts` argues
|
|
60
|
+
* every alternative. What was chosen is reported back as
|
|
61
|
+
* `WorkflowSubmission.scope`.
|
|
62
|
+
*
|
|
63
|
+
* **An empty or whitespace key THROWS** at the hook (and the route answers
|
|
64
|
+
* 400): `""` is not "no key" but one key shared by every visitor whose key
|
|
65
|
+
* computed to it — `user?.id ?? ""` before login. Pass `undefined` until the
|
|
66
|
+
* key is known.
|
|
216
67
|
*/
|
|
217
|
-
key?: string
|
|
68
|
+
key?: string | {
|
|
69
|
+
readonly storage?: "session" | "local" | undefined;
|
|
70
|
+
};
|
|
218
71
|
/**
|
|
219
72
|
* On mount, adopt the newest run this `key` already has.
|
|
220
73
|
*
|
|
@@ -270,15 +123,35 @@ export type UseWorkflowSubmitOptions = {
|
|
|
270
123
|
* Passing an output type where a def belongs is now a compile error rather
|
|
271
124
|
* than a silent loss of typing, which is the point.
|
|
272
125
|
*
|
|
126
|
+
* **Or the AGENT.** `useWorkflowSubmit<typeof agentDef>("digest")` reads the
|
|
127
|
+
* def off the agent's own `workflows` map, and the NAME is then a literal the
|
|
128
|
+
* compiler checks — a typo is an error naming the keys the agent declares,
|
|
129
|
+
* where the def form accepts any string and 404s. See `WorkflowNameOf`; an
|
|
130
|
+
* app with several workflows names the one it means as a second type
|
|
131
|
+
* argument.
|
|
132
|
+
*
|
|
273
133
|
* @example
|
|
274
|
-
* ```tsx
|
|
134
|
+
* ```tsx
|
|
135
|
+
* // file: agent.ts
|
|
136
|
+
* import { agent, workflow } from "@alexkroman1/aai";
|
|
137
|
+
* import { z } from "zod";
|
|
138
|
+
*
|
|
139
|
+
* export const digest = workflow({
|
|
140
|
+
* input: z.object({ url: z.string() }),
|
|
141
|
+
* output: z.object({ title: z.string() }),
|
|
142
|
+
* run: async ({ url }) => ({ title: url }),
|
|
143
|
+
* });
|
|
144
|
+
*
|
|
145
|
+
* export default agent({ name: "Digest", workflows: { digest } });
|
|
146
|
+
*
|
|
147
|
+
* // file: client.tsx
|
|
275
148
|
* import { Form, SubmitButton, TextField, useWorkflowSubmit } from "@alexkroman1/aai-ui";
|
|
276
149
|
* import type { digest } from "./agent.ts";
|
|
277
150
|
*
|
|
278
151
|
* function DigestForm() {
|
|
279
|
-
* const {
|
|
152
|
+
* const { submitForm, run, pending, error } = useWorkflowSubmit<typeof digest>("digest");
|
|
280
153
|
* return (
|
|
281
|
-
* <Form onSubmit={(values) =>
|
|
154
|
+
* <Form onSubmit={(values) => submitForm(values)} error={error}>
|
|
282
155
|
* <TextField name="url" label="Link" type="url" required />
|
|
283
156
|
* <SubmitButton pending={pending}>Digest</SubmitButton>
|
|
284
157
|
* {run?.status === "completed" && <p>{run.output.title}</p>}
|
|
@@ -287,6 +160,35 @@ export type UseWorkflowSubmitOptions = {
|
|
|
287
160
|
* }
|
|
288
161
|
* ```
|
|
289
162
|
*
|
|
163
|
+
* @example Named through the agent, so the name is checked
|
|
164
|
+
* ```tsx
|
|
165
|
+
* // file: agent.ts
|
|
166
|
+
* import { agent, workflow } from "@alexkroman1/aai";
|
|
167
|
+
* import { z } from "zod";
|
|
168
|
+
*
|
|
169
|
+
* export const digest = workflow({
|
|
170
|
+
* input: z.object({ url: z.string() }),
|
|
171
|
+
* output: z.object({ title: z.string() }),
|
|
172
|
+
* run: async ({ url }) => ({ title: url }),
|
|
173
|
+
* });
|
|
174
|
+
*
|
|
175
|
+
* export default agent({ name: "Digest", workflows: { digest } });
|
|
176
|
+
*
|
|
177
|
+
* // file: client.tsx
|
|
178
|
+
* import { useWorkflowSubmit } from "@alexkroman1/aai-ui";
|
|
179
|
+
* import type agentDef from "./agent.ts";
|
|
180
|
+
*
|
|
181
|
+
* export function DigestForm() {
|
|
182
|
+
* const { submit } = useWorkflowSubmit<typeof agentDef>("digest"); // "digset" would not compile
|
|
183
|
+
* return (
|
|
184
|
+
* <button type="button" onClick={() => submit({ url: "https://example.com/a" })}>
|
|
185
|
+
* Digest
|
|
186
|
+
* </button>
|
|
187
|
+
* );
|
|
188
|
+
* }
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
290
191
|
* @public
|
|
291
192
|
*/
|
|
193
|
+
export declare function useWorkflowSubmit<App extends WorkflowAppLike = never, Name extends WorkflowNameOf<App> = WorkflowNameOf<App>>(workflow: Name, options?: UseWorkflowSubmitOptions): WorkflowSubmission<WorkflowOutputOf<WorkflowDefOf<App, Name>>, SubmitInputOf<WorkflowDefOf<App, Name>>>;
|
|
292
194
|
export declare function useWorkflowSubmit<D extends AnyWorkflowDef>(workflow: string, options?: UseWorkflowSubmitOptions): WorkflowSubmission<WorkflowOutputOf<D>, SubmitInputOf<D>>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as pageBaseUrl } from "./_utils-
|
|
1
|
+
import { n as pageBaseUrl } from "./_utils-BlZBJPdj.js";
|
|
2
2
|
import { errorMessage } from "@alexkroman1/aai";
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
4
|
import { omitUndefined } from "@alexkroman1/aai/utils";
|
|
@@ -694,4 +694,4 @@ function useWorkflowRun(runId, options = {}) {
|
|
|
694
694
|
};
|
|
695
695
|
}
|
|
696
696
|
//#endregion
|
|
697
|
-
export { useWorkflowProgress as a,
|
|
697
|
+
export { useWorkflowProgress as a, createWorkflowApi as c, DEFAULT_PROGRESS_POLL_MS as i, isTerminal$1 as l, MAX_MISSING_READS as n, repeatUntil as o, useWorkflowRun as r, useWorkflowApiRef as s, DEFAULT_WORKFLOW_POLL_MS as t };
|
|
@@ -20,7 +20,9 @@
|
|
|
20
20
|
* a page calls when its own run settles, which is exactly when the list is
|
|
21
21
|
* stale.
|
|
22
22
|
*/
|
|
23
|
+
import type { WorkflowOutputOf } from "@alexkroman1/aai/workflow-api";
|
|
23
24
|
import type { WorkflowApi, WorkflowRun } from "./workflow-client.ts";
|
|
25
|
+
import type { WorkflowAppLike, WorkflowDefOf, WorkflowNameOf, WorkflowsOf } from "./workflow-def-types.ts";
|
|
24
26
|
/**
|
|
25
27
|
* Options for {@link useWorkflowRuns}.
|
|
26
28
|
*
|
|
@@ -62,7 +64,10 @@ export type UseWorkflowRunsResult<R = unknown> = {
|
|
|
62
64
|
* Read a workflow's recent runs.
|
|
63
65
|
*
|
|
64
66
|
* @typeParam R - The workflow's output type, so a completed run's `output` is
|
|
65
|
-
* typed rather than `unknown`. Derive it with `WorkflowOutputOf
|
|
67
|
+
* typed rather than `unknown`. Derive it with `WorkflowOutputOf` — or name
|
|
68
|
+
* the AGENT instead, `useWorkflowRuns<typeof agentDef>("transcribe")`, and
|
|
69
|
+
* both the name and the output come off its `workflows` map (see
|
|
70
|
+
* `WorkflowNameOf`).
|
|
66
71
|
*
|
|
67
72
|
* @example
|
|
68
73
|
* ```tsx
|
|
@@ -76,4 +81,5 @@ export type UseWorkflowRunsResult<R = unknown> = {
|
|
|
76
81
|
*
|
|
77
82
|
* @public
|
|
78
83
|
*/
|
|
79
|
-
export declare function useWorkflowRuns<
|
|
84
|
+
export declare function useWorkflowRuns<App extends WorkflowAppLike = never, Name extends WorkflowNameOf<App> = WorkflowNameOf<App>>(workflow: [App] extends [never] ? never : Name | undefined, options?: UseWorkflowRunsOptions): UseWorkflowRunsResult<WorkflowOutputOf<WorkflowDefOf<App, Name>>>;
|
|
85
|
+
export declare function useWorkflowRuns<R = unknown>(workflow: [WorkflowsOf<R>] extends [never] ? string | undefined : never, options?: UseWorkflowRunsOptions): UseWorkflowRunsResult<R>;
|
|
@@ -77,9 +77,9 @@
|
|
|
77
77
|
* pause has become an abandonment.
|
|
78
78
|
*/
|
|
79
79
|
import type { AnyWorkflowDef, UploadParallelOption, WorkflowOutputOf } from "@alexkroman1/aai/workflow-api";
|
|
80
|
-
import type { WorkflowSubmission } from "./use-workflow-form.ts";
|
|
81
80
|
import type { WorkflowApi } from "./workflow-client.ts";
|
|
82
|
-
import type { SubmitInputOf } from "./workflow-def-types.ts";
|
|
81
|
+
import type { SubmitInputOf, WorkflowAppLike, WorkflowDefOf, WorkflowNameOf } from "./workflow-def-types.ts";
|
|
82
|
+
import type { WorkflowSubmission } from "./workflow-submission.ts";
|
|
83
83
|
/**
|
|
84
84
|
* Options for {@link useWorkflowStream}.
|
|
85
85
|
*
|
|
@@ -130,13 +130,13 @@ export type UseWorkflowStreamOptions = {
|
|
|
130
130
|
/**
|
|
131
131
|
* What {@link useWorkflowStream} returns: a {@link WorkflowSubmission}, exactly.
|
|
132
132
|
*
|
|
133
|
-
* The same
|
|
133
|
+
* The same fields `useWorkflowSubmit` returns, of which this hook is a
|
|
134
134
|
* drop-in sibling — same `<Form>`, same `<UploadProgressBar>`, same
|
|
135
|
-
* `<WorkflowProgress>`. An ALIAS rather than a second declaration of
|
|
135
|
+
* `<WorkflowProgress>`. An ALIAS rather than a second declaration of them:
|
|
136
136
|
* the two have to agree field for field to be drop-in, and two copies of a type
|
|
137
137
|
* that have to agree are two copies that can stop agreeing.
|
|
138
138
|
*
|
|
139
|
-
* Exactly
|
|
139
|
+
* Exactly three of the fields mean something different here, and all three
|
|
140
140
|
* follow from WHEN the run is created — it exists before its bytes do:
|
|
141
141
|
*
|
|
142
142
|
* - `submit()` resolves when the UPLOAD finishes, not when the run is accepted;
|
|
@@ -146,6 +146,9 @@ export type UseWorkflowStreamOptions = {
|
|
|
146
146
|
* - `run` is set from the moment the run EXISTS, which here is before the bytes
|
|
147
147
|
* are in. That is what lets a page render `<WorkflowProgress>` beside the
|
|
148
148
|
* upload bar rather than after it.
|
|
149
|
+
* - `scope` is always `"none"`: the run is reading the bytes THIS page sends,
|
|
150
|
+
* so a reload does not orphan it, it ENDS it — and `<WorkflowPendingNote>`
|
|
151
|
+
* says so instead of promising the run will be found again.
|
|
149
152
|
*/
|
|
150
153
|
export type WorkflowStreamSubmission<R = unknown, I = unknown> = WorkflowSubmission<R, I>;
|
|
151
154
|
/**
|
|
@@ -173,4 +176,5 @@ export type WorkflowStreamSubmission<R = unknown, I = unknown> = WorkflowSubmiss
|
|
|
173
176
|
*
|
|
174
177
|
* @public
|
|
175
178
|
*/
|
|
179
|
+
export declare function useWorkflowStream<App extends WorkflowAppLike = never, Name extends WorkflowNameOf<App> = WorkflowNameOf<App>>(workflow: Name, options?: UseWorkflowStreamOptions): WorkflowStreamSubmission<WorkflowOutputOf<WorkflowDefOf<App, Name>>, SubmitInputOf<WorkflowDefOf<App, Name>>>;
|
|
176
180
|
export declare function useWorkflowStream<D extends AnyWorkflowDef>(workflow: string, options?: UseWorkflowStreamOptions): WorkflowStreamSubmission<WorkflowOutputOf<D>, SubmitInputOf<D>>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The narrowings the workflow hooks apply to a DEF's input type, and the
|
|
3
|
+
* readings that let a page name a workflow through its AGENT instead.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
+
* `SubmitInputOf` used to fall back to `unknown` so an un-parameterized
|
|
5
6
|
* `useWorkflowSubmit("digest")` kept compiling. It does not any more — the def
|
|
6
7
|
* is required — because the fallback was the last way to get an untyped
|
|
7
8
|
* `submit` back, and an escape hatch nobody needs is one somebody uses.
|
|
@@ -10,6 +11,20 @@
|
|
|
10
11
|
* spelled a second way and nothing else, so the hooks name `WorkflowOutputOf`
|
|
11
12
|
* directly — the SDK type this package already re-exports, and the one a page
|
|
12
13
|
* reading the rendered signature can click through to.
|
|
14
|
+
*
|
|
15
|
+
* ## Naming a workflow through the agent
|
|
16
|
+
*
|
|
17
|
+
* A page used to need the def itself in scope — `import type { digest } from
|
|
18
|
+
* "./agent.ts"` — which works only when `agent.ts` exports it under a name,
|
|
19
|
+
* and says nothing about the STRING the page then passes: `useWorkflowSubmit<
|
|
20
|
+
* typeof digest>("digets")` typechecks and 404s. {@link WorkflowNameOf} and
|
|
21
|
+
* {@link WorkflowDefOf} read both off the agent's own `workflows` map, so a
|
|
22
|
+
* page writes `import type agentDef from "./agent.ts"` and the name is a
|
|
23
|
+
* literal the compiler knows; a typo is an error naming the keys the agent has.
|
|
24
|
+
* The workflows a build DISCOVERS in `workflows/` are not in that map at the
|
|
25
|
+
* type level — only `agent({ workflows })`'s entries are — so those pages keep
|
|
26
|
+
* the def form. The four readings are declared by the SDK
|
|
27
|
+
* (`@alexkroman1/aai/workflow-api`) and re-exported here.
|
|
13
28
|
*/
|
|
14
29
|
import type { WorkflowInputOf } from "@alexkroman1/aai/workflow-api";
|
|
15
30
|
/**
|
|
@@ -29,3 +44,4 @@ import type { WorkflowInputOf } from "@alexkroman1/aai/workflow-api";
|
|
|
29
44
|
* @public
|
|
30
45
|
*/
|
|
31
46
|
export type SubmitInputOf<D> = [WorkflowInputOf<D>] extends [never] ? undefined : WorkflowInputOf<D>;
|
|
47
|
+
export type { WorkflowAppLike, WorkflowDefOf, WorkflowNameOf, WorkflowsOf, } from "@alexkroman1/aai/workflow-api";
|
|
@@ -38,18 +38,60 @@
|
|
|
38
38
|
* text field is — the same value over the wire — so it is a hand-written swap
|
|
39
39
|
* rather than a shape the schema can ask for.
|
|
40
40
|
*
|
|
41
|
+
* Two NON-scalar shapes do have an honest control, and are the two members
|
|
42
|
+
* past the scalars: `"lines"` is `<TextAreaField split="lines">` for an array
|
|
43
|
+
* of strings (one per line), and `"namedText"` is `<FileField read="text"
|
|
44
|
+
* as="namedText">` for an object of exactly `{ name: string, text: string }` —
|
|
45
|
+
* a draft, a config, read in the browser and journaled with the input. Both
|
|
46
|
+
* were the hand-written half of `document-redline-workflow`'s mixed form; a
|
|
47
|
+
* page may also ASK for either by name through `render`.
|
|
48
|
+
*
|
|
41
49
|
* Open (`| (string & {})`): a control added later is a new value, so read an
|
|
42
50
|
* unknown kind as `"none"`.
|
|
43
51
|
*
|
|
44
52
|
* @public
|
|
45
53
|
*/
|
|
46
|
-
export type WorkflowFieldKind = "text" | "number" | "select" | "checkbox" | "file" | "none" | (string & {});
|
|
54
|
+
export type WorkflowFieldKind = "text" | "number" | "select" | "checkbox" | "file" | "lines" | "namedText" | "none" | (string & {});
|
|
55
|
+
/**
|
|
56
|
+
* The kinds a page may ask `<WorkflowFields render>` for by property name —
|
|
57
|
+
* the two non-scalar controls, which a schema cannot always say it wants.
|
|
58
|
+
*
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
61
|
+
export type WorkflowFieldRender = "lines" | "namedText";
|
|
62
|
+
/**
|
|
63
|
+
* The schema with a NULLABLE union unwrapped: `anyOf: [X, { type: "null" }]`
|
|
64
|
+
* reads as `X`, the way `type: ["string", "null"]` reads as `"string"`.
|
|
65
|
+
*
|
|
66
|
+
* Zod 4 converts `z.enum([…]).nullable()` (and any nullable whose inner schema
|
|
67
|
+
* carries keywords of its own) to that `anyOf`, where a bare
|
|
68
|
+
* `z.string().nullable()` becomes the type list — so a required nullable enum
|
|
69
|
+
* used to reach the type switch with no `type` at all, render NO control, and
|
|
70
|
+
* leave a required property out of every submission. A union with two or more
|
|
71
|
+
* non-null members is some other shape and is answered as itself; a schema
|
|
72
|
+
* that is not an object has no answer.
|
|
73
|
+
*
|
|
74
|
+
* Not exported from the package barrel, like {@link schemaTypeOf}.
|
|
75
|
+
*/
|
|
76
|
+
export declare function nonNullSchemaOf(schema: unknown): Record<string, unknown> | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* The choices a select renders for `schema`, or undefined when it is not a
|
|
79
|
+
* closed set: a non-empty `enum`, or the `const` of each member of a union of
|
|
80
|
+
* literals — which is how zod 4 converts `z.union([z.literal("p"),
|
|
81
|
+
* z.literal("q")])`, where `z.enum` and `z.literal([1, 2])` convert to `enum`.
|
|
82
|
+
* The values keep their own type (`[1, 2]` stays numeric), so the control can
|
|
83
|
+
* submit what the schema declared.
|
|
84
|
+
*
|
|
85
|
+
* Not exported from the package barrel, like {@link schemaTypeOf}.
|
|
86
|
+
*/
|
|
87
|
+
export declare function schemaChoicesOf(schema: unknown): readonly unknown[] | undefined;
|
|
47
88
|
/**
|
|
48
89
|
* A property's declared type, taking the first non-null member of a union.
|
|
49
90
|
*
|
|
50
91
|
* `["string", "null"]` is how an optional-and-nullable field converts; the
|
|
51
|
-
* control is the one the non-null half wants.
|
|
52
|
-
*
|
|
92
|
+
* control is the one the non-null half wants. A nullable `anyOf` is read the
|
|
93
|
+
* same way ({@link nonNullSchemaOf}). Not exported from the package barrel —
|
|
94
|
+
* the published question is the KIND, and this is the one detail
|
|
53
95
|
* `<WorkflowFields>` needs past it (an integer's `step`).
|
|
54
96
|
*/
|
|
55
97
|
export declare function schemaTypeOf(schema: unknown): string | undefined;
|
|
@@ -64,10 +106,18 @@ export declare function schemaTypeOf(schema: unknown): string | undefined;
|
|
|
64
106
|
* person to type an id no person has. The declaration is the workflow's
|
|
65
107
|
* (`workflow({ uploads: [...] })`), not the schema's, precisely because a
|
|
66
108
|
* marker inside the schema would only work for the library that carried it.
|
|
67
|
-
* 2. **Then a
|
|
68
|
-
*
|
|
109
|
+
* 2. **Then a closed set of choices**, before the type switch: a non-empty
|
|
110
|
+
* `enum`, or a union of `const` literals (`schemaChoicesOf`) — an enum
|
|
111
|
+
* of strings is a `string` too, and a select is the narrower, better
|
|
112
|
+
* control. A nullable union (`anyOf: [X, { type: "null" }]`) is read as `X`
|
|
113
|
+
* throughout, as `type: [X, "null"]` already was.
|
|
69
114
|
* 3. **Then the type** — `boolean`, `number`/`integer`, `string`.
|
|
70
|
-
* 4. **
|
|
115
|
+
* 4. **Then the two non-scalar shapes with a control** — an array of strings
|
|
116
|
+
* is `"lines"`, an object of exactly `{ name: string, text: string }` is
|
|
117
|
+
* `"namedText"`. A page may also name either through `render`, which beats
|
|
118
|
+
* the schema for that property (it is the author saying what the shape
|
|
119
|
+
* means) but never a declared upload.
|
|
120
|
+
* 5. **Anything else is `"none"`** rather than a guess. See
|
|
71
121
|
* {@link WorkflowFieldKind}.
|
|
72
122
|
*
|
|
73
123
|
* @example
|
|
@@ -90,10 +140,12 @@ export declare function schemaTypeOf(schema: unknown): string | undefined;
|
|
|
90
140
|
* @param schema - The property's JSON Schema, as `GET workflows` reports it.
|
|
91
141
|
* Anything that is not an object reads as `"none"`.
|
|
92
142
|
* @param options - `upload` says the property is named in the workflow's own
|
|
93
|
-
* `uploads` declaration, which is what step 1 above tests
|
|
143
|
+
* `uploads` declaration, which is what step 1 above tests; `render` is the
|
|
144
|
+
* page's own choice for the property (`<WorkflowFields render>`).
|
|
94
145
|
*
|
|
95
146
|
* @public
|
|
96
147
|
*/
|
|
97
148
|
export declare function fieldKindFor(schema: unknown, options?: {
|
|
98
149
|
upload?: boolean | undefined;
|
|
150
|
+
render?: WorkflowFieldRender | undefined;
|
|
99
151
|
}): WorkflowFieldKind;
|