@alexkroman1/aai-cli 6.7.2 → 6.8.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.
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"publish:agent": "aai publish"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@alexkroman1/aai": "^6.
|
|
17
|
-
"@alexkroman1/aai-ui": "^6.
|
|
16
|
+
"@alexkroman1/aai": "^6.8.0",
|
|
17
|
+
"@alexkroman1/aai-ui": "^6.8.0",
|
|
18
18
|
"@workflow/world-postgres": "4.3.3",
|
|
19
19
|
"react": "^19.2.8",
|
|
20
20
|
"react-dom": "^19.2.8",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"zod": "^4.4.3"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@alexkroman1/aai-cli": "^6.
|
|
26
|
+
"@alexkroman1/aai-cli": "^6.8.0",
|
|
27
27
|
"@tailwindcss/vite": "^4.3.3",
|
|
28
28
|
"@types/node": "^26.2.0",
|
|
29
29
|
"@types/react": "^19.2.18",
|
|
@@ -107,6 +107,32 @@
|
|
|
107
107
|
* the same `<Form>` — every field in `@alexkroman1/aai-ui` is a plain named
|
|
108
108
|
* control, so declared and hand-written ones mix freely.
|
|
109
109
|
*
|
|
110
|
+
* ## A long upload can be PAUSED, and survives the agent restarting
|
|
111
|
+
*
|
|
112
|
+
* The same wait is the one thing on this page a person may want to interrupt: a
|
|
113
|
+
* 600 MB recording is minutes of a laptop's uplink, and needing it back for a
|
|
114
|
+
* call should not cost the upload. So `<UploadProgressBar>` takes the hook's
|
|
115
|
+
* `pauseUpload`/`resumeUpload` and draws a button — every mode, because every
|
|
116
|
+
* mode is sending a file.
|
|
117
|
+
*
|
|
118
|
+
* **Nothing in this template implements it**, which is the part worth reading.
|
|
119
|
+
* Pausing is an abort plus an id: the windows already sent are stored under an
|
|
120
|
+
* upload id the hook minted, so resuming reads back which ranges landed and sends
|
|
121
|
+
* only the rest. That is the same mechanism the SDK uses on its own when a round
|
|
122
|
+
* fails for a reason that looks like an outage — a redeploy, a sandbox reclaimed
|
|
123
|
+
* on idle, `aai dev` restarting on a save — so an agent that goes away mid-upload
|
|
124
|
+
* is a pause nobody asked for, and the upload picks up where it stopped.
|
|
125
|
+
*
|
|
126
|
+
* The two flows differ in what a pause costs, and only in that:
|
|
127
|
+
*
|
|
128
|
+
* - **"After it uploads"** and **"the async API"** have no run yet, so a pause
|
|
129
|
+
* costs nothing at all. The form simply has not been submitted.
|
|
130
|
+
* - **"While it uploads"** has a run watching the id already, and to a run a
|
|
131
|
+
* paused upload is one whose `size` stopped growing — which is exactly what a
|
|
132
|
+
* slow uplink looks like. `workflows/stream.ts` gives that five minutes
|
|
133
|
+
* (`MAX_IDLE_POLLS`) before it calls the uploader gone and fails the run, so a
|
|
134
|
+
* pause longer than a coffee ends the run rather than the upload.
|
|
135
|
+
*
|
|
110
136
|
* ## Two waits, ONE number
|
|
111
137
|
*
|
|
112
138
|
* The two bars describe the two stretches separately, and neither answers the
|
|
@@ -345,7 +371,7 @@ function TranscriptionDesk() {
|
|
|
345
371
|
// store — so it is the SAME hook against a different workflow. Only the streaming
|
|
346
372
|
// mode needs the other one, because only it needs the id before the bytes.
|
|
347
373
|
const active = mode === "streaming" ? streamed : mode === "batch" ? batched : stored;
|
|
348
|
-
const { submit, run, upload, pending, error, reset } = active;
|
|
374
|
+
const { submit, run, upload, pending, error, reset, pauseUpload, resumeUpload } = active;
|
|
349
375
|
// History is per WORKFLOW, so the list follows the mode: two flows that produce
|
|
350
376
|
// the same output are still two different things to have run, and merging them
|
|
351
377
|
// would put a run under a heading that cannot explain it.
|
|
@@ -408,8 +434,10 @@ function TranscriptionDesk() {
|
|
|
408
434
|
{/* The NAME, so the schema is fetched here rather than by this page. */}
|
|
409
435
|
<WorkflowFields workflow={WORKFLOWS[mode]} />
|
|
410
436
|
{/* Unguarded on purpose: it renders nothing until there are bytes in
|
|
411
|
-
flight, and nothing again once they have landed.
|
|
412
|
-
|
|
437
|
+
flight, and nothing again once they have landed. The handlers are what
|
|
438
|
+
turn the bar into a control — see "A long upload can be PAUSED" above;
|
|
439
|
+
all three hooks expose the same pair, so `active` needs no branch. */}
|
|
440
|
+
<UploadProgressBar upload={upload} onPause={pauseUpload} onResume={resumeUpload} />
|
|
413
441
|
<SubmitButton pending={pending}>Transcribe</SubmitButton>
|
|
414
442
|
</Form>
|
|
415
443
|
|
|
@@ -91,9 +91,29 @@
|
|
|
91
91
|
* realtime, so a recording long enough for the difference to matter is a recording
|
|
92
92
|
* whose upload dominates either way.
|
|
93
93
|
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
94
|
+
* Precisely: both flows are `upload + rounds x one segment`, streaming is always
|
|
95
|
+
* ONE round (only the last segment is left when the bytes land), and the classic
|
|
96
|
+
* flow is `ceil(segments / segmentConcurrency)`. So the saving is
|
|
97
|
+
* `(rounds - 1) x segment latency` and **it is ZERO whenever the classic fan-out
|
|
98
|
+
* fits in one round** — which is most files, because that width is 32:
|
|
99
|
+
*
|
|
100
|
+
* | recording | segments | classic rounds | saving |
|
|
101
|
+
* | --- | --- | --- | --- |
|
|
102
|
+
* | 12 min, 48 kHz stereo (130 MB) | 8 | 1 | none, by construction |
|
|
103
|
+
* | 60 min, 48 kHz stereo (660 MB) | 41 | 2 | one segment |
|
|
104
|
+
* | 6 h, 16 kHz mono (660 MB) | 241 | 8 | seven segments |
|
|
105
|
+
*
|
|
106
|
+
* It therefore grows with the SEGMENT COUNT, which is duration over bitrate — not
|
|
107
|
+
* with file size. The two 660 MB rows are the point: same bytes, same width, and
|
|
108
|
+
* the low-bitrate one has six times the segments and six times the benefit.
|
|
109
|
+
*
|
|
110
|
+
* This paragraph used to claim a 97-minute recording was "~65 segments in ~9
|
|
111
|
+
* rounds, and eight of those rounds happen behind the upload". The segment count
|
|
112
|
+
* was right and the rounds were not: at width 32 that is 3 rounds, so at most 2
|
|
113
|
+
* are hidden. It described a width of ~7, which is what `mapInBatches` and a
|
|
114
|
+
* smaller `BYTES_IN_FLIGHT` gave before either moved — and it overstated this
|
|
115
|
+
* flow's benefit about fourfold, which is exactly the expectation a reader brings
|
|
116
|
+
* to the mode picker and then finds unmet.
|
|
97
117
|
*
|
|
98
118
|
* What it always buys, at any length, is the thing a table cannot show: the page
|
|
99
119
|
* shows real progress — segment timings, arriving — while the bytes are still
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alexkroman1/aai-cli",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"aai": "bin.mjs"
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"p-timeout": "^7.0.1",
|
|
45
45
|
"vite": "^8.2.1",
|
|
46
46
|
"zod": "^4.4.3",
|
|
47
|
-
"@alexkroman1/aai": "6.
|
|
48
|
-
"@alexkroman1/aai
|
|
47
|
+
"@alexkroman1/aai-ui": "6.8.0",
|
|
48
|
+
"@alexkroman1/aai": "6.8.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"playwright": "^1.62.1",
|