@scalebrowser/sdk 0.4.1 → 0.6.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/dist/index.cjs +367 -5
- package/dist/index.d.cts +905 -8
- package/dist/index.d.ts +905 -8
- package/dist/index.js +367 -5
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -106,6 +106,281 @@ interface Persona {
|
|
|
106
106
|
misc: PersonaMisc;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
type RecordingKind = 'showcase' | 'proof';
|
|
110
|
+
type RecordingState = 'recording' | 'finishing' | 'finished' | 'failed';
|
|
111
|
+
type VideoState = 'queued' | 'rendering' | 'done' | 'failed' | 'cancelled';
|
|
112
|
+
type ExportPresetName = 'web' | 'social' | '4k' | 'editing' | 'gif';
|
|
113
|
+
type AudioStatus = 'ok' | 'silent' | 'off' | 'failed';
|
|
114
|
+
type RenderStage = 'planning' | 'narration' | 'compositing' | 'encoding' | 'finishing';
|
|
115
|
+
/** Which files a finished video has. Booleans on purpose, never paths. */
|
|
116
|
+
interface VideoAssets {
|
|
117
|
+
video: boolean;
|
|
118
|
+
poster: boolean;
|
|
119
|
+
preview_gif: boolean;
|
|
120
|
+
srt: boolean;
|
|
121
|
+
vtt: boolean;
|
|
122
|
+
proof: boolean;
|
|
123
|
+
timestamp: boolean;
|
|
124
|
+
extras: ExportPresetName[];
|
|
125
|
+
}
|
|
126
|
+
interface RenderProgress {
|
|
127
|
+
stage: RenderStage;
|
|
128
|
+
frames_done: number;
|
|
129
|
+
frames_total: number | null;
|
|
130
|
+
eta_ms: number | null;
|
|
131
|
+
/** Which attempt this is; three is the last one. */
|
|
132
|
+
attempts: number;
|
|
133
|
+
heartbeat_at: number;
|
|
134
|
+
}
|
|
135
|
+
/** A chapter in OUTPUT time: it survives cuts and time-lapse. */
|
|
136
|
+
interface Chapter {
|
|
137
|
+
out_ms: number;
|
|
138
|
+
src_ms: number;
|
|
139
|
+
label: string;
|
|
140
|
+
mark_id?: string | null;
|
|
141
|
+
step_seq?: number | null;
|
|
142
|
+
}
|
|
143
|
+
interface VideoFlags {
|
|
144
|
+
page_audio: AudioStatus;
|
|
145
|
+
tightened: boolean;
|
|
146
|
+
masked_regions: number;
|
|
147
|
+
gaps: number;
|
|
148
|
+
ai_label: boolean;
|
|
149
|
+
gpu: string;
|
|
150
|
+
h264_profile: string;
|
|
151
|
+
}
|
|
152
|
+
type TimestampState = {
|
|
153
|
+
state: 'pending';
|
|
154
|
+
} | {
|
|
155
|
+
state: 'stamped';
|
|
156
|
+
at: number;
|
|
157
|
+
tsa: string;
|
|
158
|
+
} | {
|
|
159
|
+
state: 'failed';
|
|
160
|
+
reason: string;
|
|
161
|
+
};
|
|
162
|
+
interface TranscriptWord {
|
|
163
|
+
text: string;
|
|
164
|
+
from_ms: number;
|
|
165
|
+
to_ms: number;
|
|
166
|
+
}
|
|
167
|
+
/** One video row: queued and rendering renders included. */
|
|
168
|
+
interface Video {
|
|
169
|
+
id: string;
|
|
170
|
+
recording_id: string;
|
|
171
|
+
run_id: string | null;
|
|
172
|
+
profile_id: string;
|
|
173
|
+
job_id: string | null;
|
|
174
|
+
state: VideoState;
|
|
175
|
+
progress: RenderProgress | null;
|
|
176
|
+
title: string;
|
|
177
|
+
kind: RecordingKind;
|
|
178
|
+
preset_name: string;
|
|
179
|
+
/** The resolved recipe this video renders (or rendered) under. */
|
|
180
|
+
preset: unknown;
|
|
181
|
+
export: ExportPresetName;
|
|
182
|
+
assets: VideoAssets;
|
|
183
|
+
duration_ms: number | null;
|
|
184
|
+
width: number | null;
|
|
185
|
+
height: number | null;
|
|
186
|
+
fps: number | null;
|
|
187
|
+
bytes: number | null;
|
|
188
|
+
sha256: string | null;
|
|
189
|
+
timestamp: TimestampState | null;
|
|
190
|
+
chapters: Chapter[];
|
|
191
|
+
transcript: TranscriptWord[] | null;
|
|
192
|
+
flags: VideoFlags | null;
|
|
193
|
+
share: unknown | null;
|
|
194
|
+
error: string | null;
|
|
195
|
+
created_at: number;
|
|
196
|
+
updated_at: number;
|
|
197
|
+
}
|
|
198
|
+
/** One recording row. The row outlives its raw bytes (`raw_purged_at`). */
|
|
199
|
+
interface Recording {
|
|
200
|
+
id: string;
|
|
201
|
+
profile_id: string;
|
|
202
|
+
run_id: string | null;
|
|
203
|
+
fence: number;
|
|
204
|
+
kind: RecordingKind;
|
|
205
|
+
state: RecordingState;
|
|
206
|
+
title: string | null;
|
|
207
|
+
preset_id: string | null;
|
|
208
|
+
preset: unknown;
|
|
209
|
+
manifest_version: number;
|
|
210
|
+
css_width: number;
|
|
211
|
+
css_height: number;
|
|
212
|
+
dpr: number;
|
|
213
|
+
capture_width: number;
|
|
214
|
+
started_at: number;
|
|
215
|
+
ended_at: number | null;
|
|
216
|
+
duration_ms: number | null;
|
|
217
|
+
frames: number;
|
|
218
|
+
frames_dropped: number;
|
|
219
|
+
gaps: number;
|
|
220
|
+
anchors: number;
|
|
221
|
+
bytes: number;
|
|
222
|
+
audio: AudioStatus;
|
|
223
|
+
audio_reason: string | null;
|
|
224
|
+
end_reason: string | null;
|
|
225
|
+
raw_purged_at: number | null;
|
|
226
|
+
purge_after: number | null;
|
|
227
|
+
error: string | null;
|
|
228
|
+
}
|
|
229
|
+
interface NarrationLine {
|
|
230
|
+
mark_id?: string;
|
|
231
|
+
step_seq?: number;
|
|
232
|
+
text: string;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Where a directing intent looks. `region` coordinates are page fractions
|
|
236
|
+
* in 0..1; the other kinds need no coordinates.
|
|
237
|
+
*/
|
|
238
|
+
interface ShotFocus {
|
|
239
|
+
kind: 'overview' | 'target' | 'container' | 'region';
|
|
240
|
+
x?: number;
|
|
241
|
+
y?: number;
|
|
242
|
+
w?: number;
|
|
243
|
+
h?: number;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* One directing intent: you decide WHAT is on screen at a moment, the
|
|
247
|
+
* camera executes it smoothly and keeps its guarantees. Anchor it to one
|
|
248
|
+
* action (`at_anchor`, the ids listed in `plan.actions`) or to a source
|
|
249
|
+
* moment (`at_ms`). Malformed intents are refused as `shot_invalid`;
|
|
250
|
+
* anchors the recording does not know are skipped with a note.
|
|
251
|
+
*/
|
|
252
|
+
interface ShotIntent {
|
|
253
|
+
at_anchor?: string;
|
|
254
|
+
at_ms?: number;
|
|
255
|
+
focus: ShotFocus;
|
|
256
|
+
zoom?: 'off' | 'gentle' | 'medium' | 'strong';
|
|
257
|
+
/** Minimum dwell in ms before the next camera move (max 20000). */
|
|
258
|
+
hold_ms?: number;
|
|
259
|
+
note?: string;
|
|
260
|
+
}
|
|
261
|
+
/** The shared render-order schema (SPEC §5.2: one producer, every surface). */
|
|
262
|
+
interface RenderRequestBody {
|
|
263
|
+
preset?: string;
|
|
264
|
+
export?: ExportPresetName;
|
|
265
|
+
title?: string;
|
|
266
|
+
subtitle?: string;
|
|
267
|
+
/** `auto`, or a BCP-47 tag such as `de` or `en-US`. */
|
|
268
|
+
language?: string;
|
|
269
|
+
narration?: NarrationLine[];
|
|
270
|
+
/** Directing intents; empty means the built-in direction decides. */
|
|
271
|
+
shots?: ShotIntent[];
|
|
272
|
+
}
|
|
273
|
+
interface ListVideosParams {
|
|
274
|
+
q?: string;
|
|
275
|
+
profile_id?: string;
|
|
276
|
+
run_id?: string;
|
|
277
|
+
kind?: RecordingKind;
|
|
278
|
+
preset?: string;
|
|
279
|
+
state?: VideoState;
|
|
280
|
+
page?: number;
|
|
281
|
+
}
|
|
282
|
+
interface VideosPage {
|
|
283
|
+
videos: Video[];
|
|
284
|
+
next: number | null;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Which file an access grant is minted for.
|
|
288
|
+
*
|
|
289
|
+
* The extras carry the same prefix the daemon's own key register uses
|
|
290
|
+
* (`extra:<preset>`), so a second export is reachable under the name it was
|
|
291
|
+
* stored with rather than a name a caller invents.
|
|
292
|
+
*/
|
|
293
|
+
type VideoAssetName = 'video' | 'poster' | 'preview' | 'srt' | 'vtt' | 'proof' | 'timestamp' | `extra:${ExportPresetName}`;
|
|
294
|
+
interface VideoAccessGrant {
|
|
295
|
+
/** Relative URL carrying the grant; fetch it against the daemon base. */
|
|
296
|
+
url: string;
|
|
297
|
+
expires_at: number;
|
|
298
|
+
}
|
|
299
|
+
interface VideosStorage {
|
|
300
|
+
recordings_bytes: number;
|
|
301
|
+
videos_bytes: number;
|
|
302
|
+
link_bytes: number;
|
|
303
|
+
link_limit: number;
|
|
304
|
+
uploads_today: number;
|
|
305
|
+
uploads_limit: number;
|
|
306
|
+
capacity: {
|
|
307
|
+
recordings_active: number;
|
|
308
|
+
recordings_max: number;
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
/** What the machine can encode with, and the one switch an operator has. */
|
|
312
|
+
interface CodecsStatus {
|
|
313
|
+
openh264: {
|
|
314
|
+
/** The operator's decision. */
|
|
315
|
+
enabled: boolean;
|
|
316
|
+
/** Measured now: the library is on disk and its hash is the pinned one. */
|
|
317
|
+
installed: boolean;
|
|
318
|
+
version: string | null;
|
|
319
|
+
/** `downloaded` | `manual` | `absent`. */
|
|
320
|
+
source: string;
|
|
321
|
+
notice: string;
|
|
322
|
+
};
|
|
323
|
+
/** Hardware encoders that passed a real test encode, in preference order. */
|
|
324
|
+
hardware: string[];
|
|
325
|
+
}
|
|
326
|
+
/** What kind of file a media asset is. */
|
|
327
|
+
type MediaKind = 'image' | 'music' | 'subtitle_style';
|
|
328
|
+
/** One uploaded file a preset refers to by id. */
|
|
329
|
+
interface MediaAsset {
|
|
330
|
+
id: string;
|
|
331
|
+
kind: MediaKind;
|
|
332
|
+
name: string;
|
|
333
|
+
mime: string;
|
|
334
|
+
bytes: number;
|
|
335
|
+
/** The content's checksum. It is also the file name on disk, so the same
|
|
336
|
+
* bytes are stored once however often they are uploaded. */
|
|
337
|
+
sha256: string;
|
|
338
|
+
created_at: number;
|
|
339
|
+
}
|
|
340
|
+
/** A speech provider that has a key stored.
|
|
341
|
+
*
|
|
342
|
+
* There is deliberately no `api_key` here: the daemon answers with a hint and
|
|
343
|
+
* never with the value. A client that could read it back would be the one
|
|
344
|
+
* place it lands in a log again. */
|
|
345
|
+
interface TtsProviderView {
|
|
346
|
+
provider: 'elevenlabs' | 'fish_audio' | 'openai';
|
|
347
|
+
/** The last few characters, never more. */
|
|
348
|
+
key_hint: string;
|
|
349
|
+
label: string | null;
|
|
350
|
+
verified_at: number | null;
|
|
351
|
+
updated_at: number;
|
|
352
|
+
}
|
|
353
|
+
/** What one real call to the provider proved.
|
|
354
|
+
*
|
|
355
|
+
* A stored key and a working key are two things, so this speaks a short word
|
|
356
|
+
* and reports what came back. Only an answer that carried both audio and word
|
|
357
|
+
* timings counts: a 200 with an empty body proves nothing.
|
|
358
|
+
*/
|
|
359
|
+
interface TtsVerifyResult {
|
|
360
|
+
provider: 'elevenlabs' | 'fish_audio' | 'openai';
|
|
361
|
+
/** Unix seconds. The same value the provider row now carries. */
|
|
362
|
+
verified_at: number;
|
|
363
|
+
wav_bytes: number;
|
|
364
|
+
words: number;
|
|
365
|
+
}
|
|
366
|
+
/** Where a share link stands ON THIS MACHINE: an order, not a copy.
|
|
367
|
+
*
|
|
368
|
+
* `outbox` is what is still owed: `pending` while the files are going up,
|
|
369
|
+
* `live` once the control plane confirmed, `revoke_pending` after a revoke that
|
|
370
|
+
* has not been acknowledged yet. A revoke-pending link STILL BLOCKS: between
|
|
371
|
+
* the order and the confirmation the page may still answer. */
|
|
372
|
+
interface ShareLinkLocal {
|
|
373
|
+
link_id: string;
|
|
374
|
+
url: string;
|
|
375
|
+
version: number;
|
|
376
|
+
outbox: 'pending' | 'live' | 'revoke_pending';
|
|
377
|
+
/** Whether the link asks for an access code. Never the code itself. */
|
|
378
|
+
passcode: boolean;
|
|
379
|
+
download: boolean;
|
|
380
|
+
updated_at: number;
|
|
381
|
+
error: string | null;
|
|
382
|
+
}
|
|
383
|
+
|
|
109
384
|
/**
|
|
110
385
|
* Wire types: a 1:1 mirror of the daemon's serialized domain model
|
|
111
386
|
* (`crates/core/src/model.rs`, `persona.rs`, `events.rs`) and the endpoint
|
|
@@ -227,6 +502,211 @@ interface Preset {
|
|
|
227
502
|
config: PresetConfig;
|
|
228
503
|
created_at: number;
|
|
229
504
|
}
|
|
505
|
+
/** Was hinter der Seite liegt: ein Verlauf, eine Farbe, ein Bild, oder nichts. */
|
|
506
|
+
type VideoBackground = {
|
|
507
|
+
kind: 'gradient';
|
|
508
|
+
colors: string[];
|
|
509
|
+
} | {
|
|
510
|
+
kind: 'solid';
|
|
511
|
+
color: string;
|
|
512
|
+
} | {
|
|
513
|
+
kind: 'image';
|
|
514
|
+
media_id: string;
|
|
515
|
+
} | {
|
|
516
|
+
kind: 'none';
|
|
517
|
+
};
|
|
518
|
+
/** Intro und Outro. `hold_result` haelt das letzte Bild statt einer Karte. */
|
|
519
|
+
type VideoCard = {
|
|
520
|
+
style: 'title_card';
|
|
521
|
+
seconds: number;
|
|
522
|
+
} | {
|
|
523
|
+
style: 'hold_result';
|
|
524
|
+
seconds: number;
|
|
525
|
+
};
|
|
526
|
+
/** Wohin das fertige Video geht. */
|
|
527
|
+
type VideoDestination = {
|
|
528
|
+
kind: 'local';
|
|
529
|
+
} | {
|
|
530
|
+
kind: 'link';
|
|
531
|
+
expires_days: number | null;
|
|
532
|
+
download: boolean;
|
|
533
|
+
passcode: boolean;
|
|
534
|
+
};
|
|
535
|
+
/** Eine Zusatz-Ausgabe mit eigenen Massen. Objekte, nie blosse Strings. */
|
|
536
|
+
interface ExtraOutput {
|
|
537
|
+
preset: ExportPresetName;
|
|
538
|
+
width?: number | null;
|
|
539
|
+
height?: number | null;
|
|
540
|
+
fps?: number | null;
|
|
541
|
+
colors?: number | null;
|
|
542
|
+
max_bytes?: number | null;
|
|
543
|
+
}
|
|
544
|
+
/** Hintergrundmusik, per Medien-Id, mit dem Pegel. */
|
|
545
|
+
interface MusicBed {
|
|
546
|
+
media_id: string;
|
|
547
|
+
gain_db: number;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Das Rezept eines Videos: alles ueber die FORM, nichts ueber den Inhalt.
|
|
551
|
+
*
|
|
552
|
+
* Schritte, Laenge, Titel und Sprechtext kommen aus dem Auftrag, nie von hier
|
|
553
|
+
* (AC-CTL-001); das einzige freie Textfeld ist `ai_label.text`.
|
|
554
|
+
*/
|
|
555
|
+
interface VideoPresetConfig {
|
|
556
|
+
output: {
|
|
557
|
+
aspect: '16:9' | '9:16' | '1:1';
|
|
558
|
+
resolution: '720p' | '1080p' | '4k';
|
|
559
|
+
fps: number;
|
|
560
|
+
};
|
|
561
|
+
frame: {
|
|
562
|
+
background: VideoBackground;
|
|
563
|
+
padding_pct: number;
|
|
564
|
+
corner_radius_px: number;
|
|
565
|
+
shadow: 'none' | 'soft' | 'hard';
|
|
566
|
+
inset_px: number;
|
|
567
|
+
window_chrome: 'none' | 'plain' | 'address_bar';
|
|
568
|
+
};
|
|
569
|
+
cursor: {
|
|
570
|
+
scale: number;
|
|
571
|
+
style: 'arrow_dark' | 'arrow_light' | 'dot' | 'touch';
|
|
572
|
+
click: 'ripple' | 'ring' | 'none';
|
|
573
|
+
/** `null` haelt den Zeiger fuer immer sichtbar. */
|
|
574
|
+
hide_after_ms: number | null;
|
|
575
|
+
loop: boolean;
|
|
576
|
+
};
|
|
577
|
+
camera: {
|
|
578
|
+
zoom: 'off' | 'gentle' | 'medium' | 'strong';
|
|
579
|
+
motion_blur: boolean;
|
|
580
|
+
tightening: 'none' | 'normal' | 'strong';
|
|
581
|
+
ride: 'calm' | 'standard' | 'brisk';
|
|
582
|
+
zoom_scope: 'canvas' | 'card';
|
|
583
|
+
};
|
|
584
|
+
audio: {
|
|
585
|
+
/** `"<anbieter>:<stimme>"` oder `null` fuer ein stummes Video. */
|
|
586
|
+
voice: string | null;
|
|
587
|
+
language: string;
|
|
588
|
+
subtitles: 'burned' | 'file' | 'off';
|
|
589
|
+
subtitle_style: string;
|
|
590
|
+
page_audio: boolean;
|
|
591
|
+
music: MusicBed | null;
|
|
592
|
+
};
|
|
593
|
+
cards: {
|
|
594
|
+
intro: VideoCard | null;
|
|
595
|
+
outro: VideoCard | null;
|
|
596
|
+
};
|
|
597
|
+
masking: {
|
|
598
|
+
level: 'off' | 'secrets' | 'secrets_and_ids';
|
|
599
|
+
style: 'bar' | 'pixelate' | 'blur' | 'placeholder';
|
|
600
|
+
};
|
|
601
|
+
export: {
|
|
602
|
+
preset: ExportPresetName;
|
|
603
|
+
also: ExtraOutput[];
|
|
604
|
+
destination: VideoDestination;
|
|
605
|
+
};
|
|
606
|
+
ai_label: {
|
|
607
|
+
enabled: boolean;
|
|
608
|
+
text: string;
|
|
609
|
+
position: 'top_left' | 'top_right' | 'bottom_left' | 'bottom_right';
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* A video RECIPE: how a recording becomes a video (`/v1/video-presets`).
|
|
614
|
+
*
|
|
615
|
+
* `config` was an open object for a long time, on the argument that a second
|
|
616
|
+
* TypeScript copy of a two-dozen-enum schema is a second place for it to rot.
|
|
617
|
+
* The copy exists now because a form over an open object is a pile of casts and
|
|
618
|
+
* a typo in it only surfaces as a 400 after somebody pressed save; what took
|
|
619
|
+
* the argument's teeth is that the copy is held against the Rust source field
|
|
620
|
+
* by field (`preset-schema-mirror`), so it cannot rot quietly.
|
|
621
|
+
*/
|
|
622
|
+
interface VideoPreset {
|
|
623
|
+
id: string;
|
|
624
|
+
name: string;
|
|
625
|
+
/** Shipped with the product; can be duplicated but not edited or deleted. */
|
|
626
|
+
builtin: boolean;
|
|
627
|
+
config: VideoPresetConfig;
|
|
628
|
+
created_at: number;
|
|
629
|
+
updated_at: number;
|
|
630
|
+
}
|
|
631
|
+
/** One named frame of the sample film the preview can jump to, with the clip window around it. */
|
|
632
|
+
interface PreviewMoment {
|
|
633
|
+
key: string;
|
|
634
|
+
label: string;
|
|
635
|
+
frame: number;
|
|
636
|
+
from: number;
|
|
637
|
+
to: number;
|
|
638
|
+
}
|
|
639
|
+
/** A preset field the sample film cannot show, and why. */
|
|
640
|
+
interface PreviewHidden {
|
|
641
|
+
field: string;
|
|
642
|
+
why: string;
|
|
643
|
+
}
|
|
644
|
+
/** `POST /v1/video-presets/preview`: one still of the sample film under an unsaved config. */
|
|
645
|
+
interface VideoPresetPreviewBody {
|
|
646
|
+
config: VideoPresetConfig;
|
|
647
|
+
frame?: number;
|
|
648
|
+
moment?: string;
|
|
649
|
+
name?: string;
|
|
650
|
+
/** Draw at this short side instead of the recipe's own, 360 to 2160. */
|
|
651
|
+
proxy_short_side?: number;
|
|
652
|
+
}
|
|
653
|
+
/** The reply: the picture as a data URL plus what the film looks like under this config. */
|
|
654
|
+
interface VideoPresetPreview {
|
|
655
|
+
width: number;
|
|
656
|
+
height: number;
|
|
657
|
+
fps: number;
|
|
658
|
+
frames: number;
|
|
659
|
+
frame: number;
|
|
660
|
+
moments: PreviewMoment[];
|
|
661
|
+
hidden: PreviewHidden[];
|
|
662
|
+
notes: string[];
|
|
663
|
+
image: string;
|
|
664
|
+
}
|
|
665
|
+
/** `POST /v1/video-presets/preview/clip`: frames `from_frame..to_frame` of the sample film as an MP4. */
|
|
666
|
+
interface VideoPresetClipBody {
|
|
667
|
+
config: VideoPresetConfig;
|
|
668
|
+
/** Absent means the start of the film. */
|
|
669
|
+
from_frame?: number;
|
|
670
|
+
/** Exclusive; absent means the end of the film. */
|
|
671
|
+
to_frame?: number;
|
|
672
|
+
name?: string;
|
|
673
|
+
/** Draw at this short side instead of the recipe's own, 360 to 2160. */
|
|
674
|
+
proxy_short_side?: number;
|
|
675
|
+
}
|
|
676
|
+
/** One progress frame of the clip's SSE stream (`event: progress`). */
|
|
677
|
+
interface VideoPresetClipProgress {
|
|
678
|
+
done: number;
|
|
679
|
+
total: number;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* `event: started`, the FIRST frame of the SSE answer: the id under which the
|
|
683
|
+
* bytes can already be followed (`?follow=1`), and the shape of the film.
|
|
684
|
+
*
|
|
685
|
+
* It exists so a player can begin while the render still runs. Without it the
|
|
686
|
+
* id arrives with `done`, and by then there is nothing left to follow.
|
|
687
|
+
*/
|
|
688
|
+
interface VideoPresetClipStarted {
|
|
689
|
+
id: string;
|
|
690
|
+
frames: number;
|
|
691
|
+
fps: number;
|
|
692
|
+
width: number;
|
|
693
|
+
height: number;
|
|
694
|
+
}
|
|
695
|
+
/** The finished clip (`event: done`, or the blocking JSON reply); the bytes come from `GET /v1/video-presets/preview/clip/:id`. */
|
|
696
|
+
interface VideoPresetClip {
|
|
697
|
+
id: string;
|
|
698
|
+
from_frame: number;
|
|
699
|
+
to_frame: number;
|
|
700
|
+
fps: number;
|
|
701
|
+
width: number;
|
|
702
|
+
height: number;
|
|
703
|
+
frames: number;
|
|
704
|
+
seconds: number;
|
|
705
|
+
bytes: number;
|
|
706
|
+
encoder: string;
|
|
707
|
+
cached: boolean;
|
|
708
|
+
audio: boolean;
|
|
709
|
+
}
|
|
230
710
|
/** `GET /v1/persona/constraints`: the values a preset may constrain to. */
|
|
231
711
|
interface PersonaConstraintOptions {
|
|
232
712
|
countries: string[];
|
|
@@ -329,7 +809,7 @@ type TrustedInputBody = {
|
|
|
329
809
|
delta_y?: number;
|
|
330
810
|
humanize?: boolean;
|
|
331
811
|
};
|
|
332
|
-
/** Who is driving: an agent holding a
|
|
812
|
+
/** Who is driving: an agent holding a lease, or a person at a window. */
|
|
333
813
|
type RunActor = 'agent' | 'human';
|
|
334
814
|
/** How a run ended. `reached`/`partial` appear only when a source claimed it. */
|
|
335
815
|
type RunOutcome = 'running' | 'reached' | 'partial' | 'blocked' | 'interrupted' | 'unknown';
|
|
@@ -379,6 +859,144 @@ interface ProfileActivity {
|
|
|
379
859
|
/** The browser did not answer the last sweep; this is the last known value. */
|
|
380
860
|
stale: boolean;
|
|
381
861
|
}
|
|
862
|
+
/** How far a claim reaches. `machine` means this computer has no account key yet. */
|
|
863
|
+
type ExitScope = 'machine' | 'account';
|
|
864
|
+
/** One exit address a profile owns. */
|
|
865
|
+
interface ExitClaim {
|
|
866
|
+
/** The comparison unit: the whole address for IPv4, the `/64` block for IPv6. */
|
|
867
|
+
addr: string;
|
|
868
|
+
/** `mobile` | `residential` | `datacenter` | `unknown`. Sets how long it is held. */
|
|
869
|
+
class: string;
|
|
870
|
+
scope: ExitScope;
|
|
871
|
+
first_seen: number;
|
|
872
|
+
last_seen: number;
|
|
873
|
+
expires_at: number;
|
|
874
|
+
}
|
|
875
|
+
/** A profile's exit-address situation. */
|
|
876
|
+
interface ExitStatus {
|
|
877
|
+
/** Whether the rule applies to this installation at all. */
|
|
878
|
+
enabled: boolean;
|
|
879
|
+
/** Derived from the newest claim, not from configuration. */
|
|
880
|
+
scope: ExitScope;
|
|
881
|
+
/** The address in use, when one is claimed. */
|
|
882
|
+
current: string | null;
|
|
883
|
+
owned: number;
|
|
884
|
+
claims: ExitClaim[];
|
|
885
|
+
/** Set when the profile has no proxy and is therefore exempt. */
|
|
886
|
+
note: string | null;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/**
|
|
890
|
+
* The per-profile task list and the profile's own durable memory.
|
|
891
|
+
*
|
|
892
|
+
* Mirrors `web-ui/src/api/types/tasks.ts`, the shared source of contract truth.
|
|
893
|
+
*/
|
|
894
|
+
/**
|
|
895
|
+
* Where a task stands.
|
|
896
|
+
*
|
|
897
|
+
* Four words and no more. There is deliberately no `blocked` and no `partial`:
|
|
898
|
+
* `in_progress` already carries "somebody tried and did not finish", and why it
|
|
899
|
+
* failed belongs in the run trail, which is built to hold exactly that.
|
|
900
|
+
*
|
|
901
|
+
* `cancelled` is `done` with a different word. Both are endings, both fall out
|
|
902
|
+
* of the list a day later; the separate word is so a reader can tell "we did it"
|
|
903
|
+
* from "we called it off".
|
|
904
|
+
*/
|
|
905
|
+
type TaskState = 'open' | 'in_progress' | 'done' | 'cancelled';
|
|
906
|
+
/** One task on one profile. */
|
|
907
|
+
interface ProfileTask {
|
|
908
|
+
id: string;
|
|
909
|
+
profile_id: string;
|
|
910
|
+
/** Carried along so a fleet-wide list can say whose task a row is. */
|
|
911
|
+
profile_name: string;
|
|
912
|
+
/**
|
|
913
|
+
* The IANA zone `due_at` should be READ in: the profile's own.
|
|
914
|
+
*
|
|
915
|
+
* Without it a viewer reads their own clock and acts on the wrong number, and
|
|
916
|
+
* an account posting at three in the morning local time is exactly the
|
|
917
|
+
* behavioural tell this product avoids everywhere else. Derived at query time,
|
|
918
|
+
* never stored on the task: `geo_mode = follow_exit` rewrites the persona's
|
|
919
|
+
* zone at every launch.
|
|
920
|
+
*/
|
|
921
|
+
profile_timezone: string | null;
|
|
922
|
+
/** One line saying what to do. A task names its material, it does not hold it. */
|
|
923
|
+
title: string;
|
|
924
|
+
state: TaskState;
|
|
925
|
+
/**
|
|
926
|
+
* Deadline in unix seconds (UTC), or `null` for work that is owed but not owed
|
|
927
|
+
* at any particular moment.
|
|
928
|
+
*
|
|
929
|
+
* Read it in the PROFILE's timezone, not the viewer's: a task due at nine means
|
|
930
|
+
* nine where the identity lives, and an account that posts at three in the
|
|
931
|
+
* morning local time is a behavioural tell.
|
|
932
|
+
*
|
|
933
|
+
* It is a deadline, not a trigger. Nothing runs by itself.
|
|
934
|
+
*/
|
|
935
|
+
due_at: number | null;
|
|
936
|
+
created_at: number;
|
|
937
|
+
/** When the current claim was taken; cleared when the task leaves `in_progress`. */
|
|
938
|
+
claimed_at: number | null;
|
|
939
|
+
finished_at: number | null;
|
|
940
|
+
/**
|
|
941
|
+
* Set when a claim nobody finished was handed back after six hours.
|
|
942
|
+
*
|
|
943
|
+
* Whoever picks such a task up has to check whether the work already happened:
|
|
944
|
+
* the previous run may have published the post and died before it could say so.
|
|
945
|
+
*/
|
|
946
|
+
last_attempt_at: number | null;
|
|
947
|
+
}
|
|
948
|
+
/** Filters for listing tasks. All are narrowings; absent means unconstrained. */
|
|
949
|
+
interface ListTasksParams {
|
|
950
|
+
profile_id?: string;
|
|
951
|
+
state?: TaskState;
|
|
952
|
+
/** Only tasks whose deadline is at or before this unix second. */
|
|
953
|
+
due_before?: number;
|
|
954
|
+
/** Substring of the title, case-insensitive. */
|
|
955
|
+
q?: string;
|
|
956
|
+
limit?: number;
|
|
957
|
+
offset?: number;
|
|
958
|
+
}
|
|
959
|
+
/** Add the same task to one or many profiles, one row each. */
|
|
960
|
+
interface CreateTasksBody {
|
|
961
|
+
profile_ids: string[];
|
|
962
|
+
title: string;
|
|
963
|
+
due_at?: number | null;
|
|
964
|
+
}
|
|
965
|
+
/** What one create call did. */
|
|
966
|
+
interface CreateTasksResult {
|
|
967
|
+
created: ProfileTask[];
|
|
968
|
+
/**
|
|
969
|
+
* Profiles that no longer exist. Named rather than dropped: adding a task to
|
|
970
|
+
* twenty profiles of which three were deleted writes seventeen rows and says
|
|
971
|
+
* which three it could not.
|
|
972
|
+
*/
|
|
973
|
+
missing: string[];
|
|
974
|
+
}
|
|
975
|
+
/** The one transition this surface performs. */
|
|
976
|
+
interface PatchTaskBody {
|
|
977
|
+
/** Only `cancelled`, and only on a task nobody has claimed. */
|
|
978
|
+
state: 'cancelled';
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* A profile's durable memory: the `PROFILE.md` at the top of its directory.
|
|
982
|
+
*
|
|
983
|
+
* Same purpose as a repository's `CLAUDE.md`. What goes in it is the customer's
|
|
984
|
+
* business; nothing writes a scaffold or seeds a value, and a profile starts with
|
|
985
|
+
* no file rather than an empty one.
|
|
986
|
+
*/
|
|
987
|
+
interface ProfileMemory {
|
|
988
|
+
/** `null` while nobody has written one. */
|
|
989
|
+
content: string | null;
|
|
990
|
+
/** The absolute path, so a person can open it in their own editor. */
|
|
991
|
+
path: string;
|
|
992
|
+
updated_at: number | null;
|
|
993
|
+
/** The ceiling a write is measured against, in bytes. */
|
|
994
|
+
max_bytes: number;
|
|
995
|
+
}
|
|
996
|
+
/** Replace a profile's memory. The text is stored verbatim. */
|
|
997
|
+
interface WriteMemoryBody {
|
|
998
|
+
content: string;
|
|
999
|
+
}
|
|
382
1000
|
|
|
383
1001
|
/**
|
|
384
1002
|
* A daemon lifecycle event. Named `LifecycleEvent` (not `Event`) to avoid
|
|
@@ -461,11 +1079,73 @@ type LifecycleEvent = {
|
|
|
461
1079
|
profile_id: string;
|
|
462
1080
|
at: number;
|
|
463
1081
|
}
|
|
1082
|
+
/** A recording appeared or changed: the whole row, upsert it. */
|
|
1083
|
+
| {
|
|
1084
|
+
type: 'recording_changed';
|
|
1085
|
+
recording: Recording;
|
|
1086
|
+
at: number;
|
|
1087
|
+
}
|
|
1088
|
+
/**
|
|
1089
|
+
* A video appeared or changed. Carries state AND progress: while it renders
|
|
1090
|
+
* this fires every 2 % or 2 s, and the row is the whole truth.
|
|
1091
|
+
*/
|
|
1092
|
+
| {
|
|
1093
|
+
type: 'video_changed';
|
|
1094
|
+
video: Video;
|
|
1095
|
+
at: number;
|
|
1096
|
+
}
|
|
1097
|
+
/** A video is gone: deleted, remove its row. */
|
|
1098
|
+
| {
|
|
1099
|
+
type: 'video_gone';
|
|
1100
|
+
video_id: string;
|
|
1101
|
+
at: number;
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* A task appeared or changed. One variant for both, because the row is
|
|
1105
|
+
* complete: a reader writes it whether or not it knew the task before, and a
|
|
1106
|
+
* separate "created" event would only buy a distinction that goes wrong the
|
|
1107
|
+
* first time one is missed.
|
|
1108
|
+
*/
|
|
1109
|
+
| {
|
|
1110
|
+
type: 'task_changed';
|
|
1111
|
+
task: ProfileTask;
|
|
1112
|
+
at: number;
|
|
1113
|
+
}
|
|
1114
|
+
/** A task is gone: cancelled and swept, finished and swept, or deleted. */
|
|
1115
|
+
| {
|
|
1116
|
+
type: 'task_gone';
|
|
1117
|
+
task_id: string;
|
|
1118
|
+
profile_id: string;
|
|
1119
|
+
at: number;
|
|
1120
|
+
}
|
|
464
1121
|
/**
|
|
465
1122
|
* Frames were lost; re-read rather than carry on. Raised when the daemon
|
|
466
1123
|
* notices this connection fell behind. `dropped` counts what it skipped.
|
|
467
1124
|
*/
|
|
1125
|
+
/**
|
|
1126
|
+
* The exit-address guard's verdict for one running profile (DEC-017).
|
|
1127
|
+
*
|
|
1128
|
+
* The whole state, like every other live row here: a display rebuilt from
|
|
1129
|
+
* parts is what makes it confidently wrong, and the one frame that matters
|
|
1130
|
+
* most is the wire being cut.
|
|
1131
|
+
*/
|
|
468
1132
|
| {
|
|
1133
|
+
type: 'exit_guard_changed';
|
|
1134
|
+
profile_id: string;
|
|
1135
|
+
state: 'ok' | 'degraded' | 'unverified' | 'severed';
|
|
1136
|
+
addr: string;
|
|
1137
|
+
class: string;
|
|
1138
|
+
scope: ExitScope;
|
|
1139
|
+
owned: number;
|
|
1140
|
+
detail: string | null;
|
|
1141
|
+
at: number;
|
|
1142
|
+
}
|
|
1143
|
+
/** A profile stopped: its guard row goes away. */
|
|
1144
|
+
| {
|
|
1145
|
+
type: 'exit_guard_gone';
|
|
1146
|
+
profile_id: string;
|
|
1147
|
+
at: number;
|
|
1148
|
+
} | {
|
|
469
1149
|
type: 'resync';
|
|
470
1150
|
dropped: number;
|
|
471
1151
|
at: number;
|
|
@@ -487,7 +1167,14 @@ type StreamedEvent = LifecycleEvent & {
|
|
|
487
1167
|
* Read as `text/event-stream` over `fetch` (so the Bearer header is attached, which
|
|
488
1168
|
* the browser `EventSource` cannot do that) and reconnect with backoff. A
|
|
489
1169
|
* `/v1/ws` websocket carries the same events; SSE is sufficient for one-way
|
|
490
|
-
* fan-out.
|
|
1170
|
+
* fan-out.
|
|
1171
|
+
*
|
|
1172
|
+
* Mirrors `web-ui/src/api/events.ts` line for line, deliberately: this package
|
|
1173
|
+
* ships to npm and should carry no dependency it does not need, so a shared
|
|
1174
|
+
* package would cost more than the copy does. The copy pays for itself with a
|
|
1175
|
+
* gate instead: `scripts/verify-mirrored-values.mjs` holds `MAX_BACKOFF_MS` and
|
|
1176
|
+
* the backoff line itself against the other side. Two clients of the same daemon
|
|
1177
|
+
* that come back at different speeds would be a decision nobody made.
|
|
491
1178
|
*/
|
|
492
1179
|
|
|
493
1180
|
/** Injectable `fetch`; defaults to the global at call time. */
|
|
@@ -645,6 +1332,18 @@ interface ReadyStatus {
|
|
|
645
1332
|
* launch-time question the preflight answers properly. */
|
|
646
1333
|
engines_dir: string;
|
|
647
1334
|
}
|
|
1335
|
+
/** What `GET /v1/remote` answers: the machine's own remote-access switch. */
|
|
1336
|
+
interface RemoteStatus {
|
|
1337
|
+
/** Is remote access on? */
|
|
1338
|
+
enabled: boolean;
|
|
1339
|
+
/** Did a person decide this, or is the configured default still standing? */
|
|
1340
|
+
explicit: boolean;
|
|
1341
|
+
/** The relay the tunnel goes to. */
|
|
1342
|
+
relay_url: string;
|
|
1343
|
+
/** Without a control-plane session there is no ticket and so no tunnel,
|
|
1344
|
+
* whatever the switch says. */
|
|
1345
|
+
ready: boolean;
|
|
1346
|
+
}
|
|
648
1347
|
|
|
649
1348
|
interface ScalebrowserClientOptions {
|
|
650
1349
|
/** Daemon base URL. Default `http://127.0.0.1:8787`. */
|
|
@@ -693,7 +1392,7 @@ declare class ControlApi extends ClientCore {
|
|
|
693
1392
|
/**
|
|
694
1393
|
* Hand the daemon a file so `interact action=upload` has something to attach.
|
|
695
1394
|
*
|
|
696
|
-
* The bytes are bound to the PROFILE, not to a
|
|
1395
|
+
* The bytes are bound to the PROFILE, not to a lease: set a file up
|
|
697
1396
|
* before leasing, and a lease released mid-task does not destroy it.
|
|
698
1397
|
*/
|
|
699
1398
|
putArtifact(profileId: string, bytes: Uint8Array | ArrayBuffer, name?: string): Promise<ArtifactPutResult>;
|
|
@@ -790,6 +1489,12 @@ interface TakeoverResult {
|
|
|
790
1489
|
interface StopProfileResult {
|
|
791
1490
|
stopped: boolean;
|
|
792
1491
|
}
|
|
1492
|
+
/** `POST /v1/profiles/:id/release`: `released: false` is an honest no-op,
|
|
1493
|
+
* there was nothing to let go. */
|
|
1494
|
+
interface ReleaseProfileResult {
|
|
1495
|
+
released: boolean;
|
|
1496
|
+
stopped: boolean;
|
|
1497
|
+
}
|
|
793
1498
|
interface BulkCreateBody {
|
|
794
1499
|
preset_id: string;
|
|
795
1500
|
count: number;
|
|
@@ -1289,6 +1994,53 @@ declare class IdentityApi extends ClientCore {
|
|
|
1289
1994
|
revealCookies(profileId: string, body: RevealCookiesBody): Promise<RevealCookiesResult>;
|
|
1290
1995
|
}
|
|
1291
1996
|
|
|
1997
|
+
declare class TasksApi extends ClientCore {
|
|
1998
|
+
/**
|
|
1999
|
+
* What is still to be done. No filter means every task of every profile.
|
|
2000
|
+
*
|
|
2001
|
+
* Pass `state: 'open'` for what is outstanding; without it, tasks finished
|
|
2002
|
+
* within the last day are included too.
|
|
2003
|
+
*/
|
|
2004
|
+
listTasks(params?: ListTasksParams, signal?: AbortSignal): Promise<ProfileTask[]>;
|
|
2005
|
+
/**
|
|
2006
|
+
* Put the same task on one or many profiles, one row each.
|
|
2007
|
+
*
|
|
2008
|
+
* A task is a LINE, not a document: name the work and leave the material where
|
|
2009
|
+
* it lives. `due_at` is a deadline, not a trigger; nothing runs by itself.
|
|
2010
|
+
*
|
|
2011
|
+
* Profiles that no longer exist come back in `missing` instead of failing the
|
|
2012
|
+
* whole call.
|
|
2013
|
+
*/
|
|
2014
|
+
createTasks(body: CreateTasksBody): Promise<CreateTasksResult>;
|
|
2015
|
+
/**
|
|
2016
|
+
* Call a task off.
|
|
2017
|
+
*
|
|
2018
|
+
* Only a task nobody has claimed can be cancelled here. One an agent is working
|
|
2019
|
+
* on right now is stopped by telling that agent, which is a channel that already
|
|
2020
|
+
* reaches it; this surface answers `409` for it rather than pretending.
|
|
2021
|
+
*/
|
|
2022
|
+
cancelTask(id: string): Promise<ProfileTask>;
|
|
2023
|
+
/** Remove a task outright. */
|
|
2024
|
+
deleteTask(id: string): Promise<void>;
|
|
2025
|
+
/**
|
|
2026
|
+
* A profile's durable memory, the `PROFILE.md` at the top of its directory.
|
|
2027
|
+
*
|
|
2028
|
+
* `content` is `null` while nobody has written one: a profile starts with no
|
|
2029
|
+
* file, not with an empty one.
|
|
2030
|
+
*/
|
|
2031
|
+
getProfileMemory(profileId: string, signal?: AbortSignal): Promise<ProfileMemory>;
|
|
2032
|
+
/**
|
|
2033
|
+
* Replace a profile's memory.
|
|
2034
|
+
*
|
|
2035
|
+
* Stored verbatim: no trimming, no appended newline, no line-ending
|
|
2036
|
+
* translation. The last write wins and nothing warns, exactly as with a file
|
|
2037
|
+
* two people can open.
|
|
2038
|
+
*/
|
|
2039
|
+
putProfileMemory(profileId: string, content: string): Promise<ProfileMemory>;
|
|
2040
|
+
/** Remove a profile's memory. Removing one that is not there is not an error. */
|
|
2041
|
+
deleteProfileMemory(profileId: string): Promise<void>;
|
|
2042
|
+
}
|
|
2043
|
+
|
|
1292
2044
|
/**
|
|
1293
2045
|
* Agent runs and live activity (`/v1/runs`, `/v1/activity`).
|
|
1294
2046
|
*
|
|
@@ -1308,7 +2060,7 @@ type OutcomeSource = 'agent' | 'check' | 'human' | 'derived';
|
|
|
1308
2060
|
type GoalSource = 'agent' | 'derived';
|
|
1309
2061
|
interface AgentRun {
|
|
1310
2062
|
id: string;
|
|
1311
|
-
/** Groups runs that shared one profile
|
|
2063
|
+
/** Groups runs that shared one profile lease. */
|
|
1312
2064
|
session_id: string;
|
|
1313
2065
|
profile_id: string;
|
|
1314
2066
|
profile_name: string;
|
|
@@ -1367,6 +2119,96 @@ declare class RunsApi extends ClientCore {
|
|
|
1367
2119
|
getActivity(signal?: AbortSignal): Promise<ActivitySnapshot>;
|
|
1368
2120
|
}
|
|
1369
2121
|
|
|
2122
|
+
declare class VideosApi extends ClientCore {
|
|
2123
|
+
/** One gallery page, newest first. Running renders are videos too. */
|
|
2124
|
+
listVideos(params?: ListVideosParams, signal?: AbortSignal): Promise<VideosPage>;
|
|
2125
|
+
/** One video row, progress included while it renders. */
|
|
2126
|
+
getVideo(videoId: string, signal?: AbortSignal): Promise<Video>;
|
|
2127
|
+
/** Rename. The title also lands in the MP4's metadata on the NEXT render. */
|
|
2128
|
+
renameVideo(videoId: string, title: string, signal?: AbortSignal): Promise<Video>;
|
|
2129
|
+
/**
|
|
2130
|
+
* Delete a video (`raw: true` also purges its recording's raw material).
|
|
2131
|
+
* A live share link is revoked first; 409 `job_running` while it renders.
|
|
2132
|
+
*/
|
|
2133
|
+
deleteVideo(videoId: string, opts?: {
|
|
2134
|
+
raw?: boolean;
|
|
2135
|
+
}, signal?: AbortSignal): Promise<void>;
|
|
2136
|
+
/** Cancel a queued or rendering video. `done` stays done (409). */
|
|
2137
|
+
cancelVideo(videoId: string, signal?: AbortSignal): Promise<Video>;
|
|
2138
|
+
/** Render a failed or cancelled video again: same id, new job. */
|
|
2139
|
+
rerenderVideo(videoId: string, body?: RenderRequestBody, signal?: AbortSignal): Promise<Video>;
|
|
2140
|
+
/** A short-lived fetchable address for one asset (default the video). */
|
|
2141
|
+
videoAccess(videoId: string, asset?: VideoAssetName, signal?: AbortSignal): Promise<VideoAccessGrant>;
|
|
2142
|
+
/** One asset's bytes, through a freshly minted grant. */
|
|
2143
|
+
downloadVideoFile(videoId: string, asset?: VideoAssetName, signal?: AbortSignal): Promise<ArtifactBytes>;
|
|
2144
|
+
/** What recordings and videos cost on disk, plus the caps. */
|
|
2145
|
+
videosStorage(signal?: AbortSignal): Promise<VideosStorage>;
|
|
2146
|
+
/** Recordings, newest first. The row outlives its raw bytes. */
|
|
2147
|
+
listRecordings(params?: {
|
|
2148
|
+
profile_id?: string;
|
|
2149
|
+
}, signal?: AbortSignal): Promise<Recording[]>;
|
|
2150
|
+
getRecording(recordingId: string, signal?: AbortSignal): Promise<Recording>;
|
|
2151
|
+
/**
|
|
2152
|
+
* Purge a recording's RAW material; the row stays forever
|
|
2153
|
+
* (`raw_purged_at`). 409 `job_running` while a render of it is open.
|
|
2154
|
+
*/
|
|
2155
|
+
deleteRecordingRaw(recordingId: string, signal?: AbortSignal): Promise<void>;
|
|
2156
|
+
/** A NEW video from this recording (the same body the `video` tool takes). */
|
|
2157
|
+
renderRecording(recordingId: string, body?: RenderRequestBody, signal?: AbortSignal): Promise<Video>;
|
|
2158
|
+
/** What this machine can encode with. The hardware list is PROBED, not read
|
|
2159
|
+
* off the binary: `h264_nvenc` is always listed and fails without a driver. */
|
|
2160
|
+
getCodecs(signal?: AbortSignal): Promise<CodecsStatus>;
|
|
2161
|
+
/** Turn Cisco's OpenH264 on or off. The hardware encoders are not switchable. */
|
|
2162
|
+
setCodecEnabled(codec: string, enabled: boolean, signal?: AbortSignal): Promise<CodecsStatus>;
|
|
2163
|
+
/** Make a finished video public. Measures every file, asks the control plane
|
|
2164
|
+
* for permission, uploads, and has the result confirmed. */
|
|
2165
|
+
share(videoId: string, body?: {
|
|
2166
|
+
expires_days?: number | null;
|
|
2167
|
+
passcode?: string | null;
|
|
2168
|
+
download?: boolean;
|
|
2169
|
+
}, signal?: AbortSignal): Promise<ShareLinkLocal>;
|
|
2170
|
+
/** The share ORDER as this machine knows it. How many people watched and
|
|
2171
|
+
* whether the link still lives is read from the control plane, not from
|
|
2172
|
+
* here: a number carried along would be wrong the moment another machine
|
|
2173
|
+
* revoked. */
|
|
2174
|
+
shareStatus(videoId: string, signal?: AbortSignal): Promise<ShareLinkLocal>;
|
|
2175
|
+
/** Revoke the link. The files fall at once; the order stays until the control
|
|
2176
|
+
* plane confirms. */
|
|
2177
|
+
revokeShare(videoId: string, signal?: AbortSignal): Promise<void>;
|
|
2178
|
+
/** Files a preset points at: background image, music bed, subtitle font. */
|
|
2179
|
+
listMedia(kind?: MediaKind, signal?: AbortSignal): Promise<MediaAsset[]>;
|
|
2180
|
+
/** Upload one file. The body IS the file; `name` and `mime` ride in the query. */
|
|
2181
|
+
uploadMedia(kind: MediaKind, name: string, mime: string, bytes: Uint8Array, signal?: AbortSignal): Promise<MediaAsset>;
|
|
2182
|
+
/** Remove a file. Refuses with 409 while a preset still points at it. */
|
|
2183
|
+
deleteMedia(id: string, signal?: AbortSignal): Promise<void>;
|
|
2184
|
+
/** The file itself. */
|
|
2185
|
+
mediaFile(id: string, signal?: AbortSignal): Promise<ArtifactBytes>;
|
|
2186
|
+
/** Which speech providers have a key. The key itself never comes back: the
|
|
2187
|
+
* answer carries a hint, and that is on purpose. */
|
|
2188
|
+
listTtsProviders(signal?: AbortSignal): Promise<TtsProviderView[]>;
|
|
2189
|
+
/** Store a key, or rename one. Leaving `apiKey` out keeps the stored key.
|
|
2190
|
+
*
|
|
2191
|
+
* `apiKey` may also be a secret reference (`{{sb:...}}`), which is what an
|
|
2192
|
+
* agent gets back after fetching a key from the provider's own site: it is
|
|
2193
|
+
* not allowed to read the value. A reference needs `profileId`, because the
|
|
2194
|
+
* value belongs to one profile and there is nothing to open without it.
|
|
2195
|
+
*/
|
|
2196
|
+
putTtsProvider(provider: string, body: {
|
|
2197
|
+
apiKey?: string;
|
|
2198
|
+
label?: string;
|
|
2199
|
+
profileId?: string;
|
|
2200
|
+
}, signal?: AbortSignal): Promise<TtsProviderView>;
|
|
2201
|
+
/** Call the provider once for real, and record that the key works.
|
|
2202
|
+
*
|
|
2203
|
+
* Costs one short sentence of the account's own quota. Until this runs, a
|
|
2204
|
+
* provider row says `verified_at: null`, which means untested rather than
|
|
2205
|
+
* broken.
|
|
2206
|
+
*/
|
|
2207
|
+
verifyTtsProvider(provider: string, signal?: AbortSignal): Promise<TtsVerifyResult>;
|
|
2208
|
+
/** Forget a provider's key. */
|
|
2209
|
+
deleteTtsProvider(provider: string, signal?: AbortSignal): Promise<void>;
|
|
2210
|
+
}
|
|
2211
|
+
|
|
1370
2212
|
/**
|
|
1371
2213
|
* Direct-CDP driver (DEC-006, AC-FP-005): a minimal, nodriver-style Chrome
|
|
1372
2214
|
* DevTools Protocol client over a raw websocket. This is the recommended SDK
|
|
@@ -1596,6 +2438,13 @@ declare class ScalebrowserClient extends ClientCore {
|
|
|
1596
2438
|
/** Start a profile → CDP ws endpoint. Errors: 4002/4003/4005/4006/4008. */
|
|
1597
2439
|
startProfile(id: string, body?: StartProfileBody): Promise<StartProfileResult>;
|
|
1598
2440
|
stopProfile(id: string): Promise<StopProfileResult>;
|
|
2441
|
+
/** Drop the profile's lease, the operator's way out.
|
|
2442
|
+
*
|
|
2443
|
+
* An agent releases with its handle; this call needs none. The daemon stops
|
|
2444
|
+
* the browser first when one is still up, then lets the lease go, so a dead
|
|
2445
|
+
* session cannot park the profile until its TTL runs out. `released: false`
|
|
2446
|
+
* is an honest no-op: there was nothing to let go. */
|
|
2447
|
+
releaseProfile(id: string): Promise<ReleaseProfileResult>;
|
|
1599
2448
|
/** Ask for a profile that is open on another machine of this account.
|
|
1600
2449
|
*
|
|
1601
2450
|
* Closes nothing here and nothing there: the control plane revokes the holder's
|
|
@@ -1631,6 +2480,31 @@ declare class ScalebrowserClient extends ClientCore {
|
|
|
1631
2480
|
createPreset(body: CreatePresetBody): Promise<Preset>;
|
|
1632
2481
|
updatePreset(id: string, body: UpdatePresetBody): Promise<Preset>;
|
|
1633
2482
|
deletePreset(id: string): Promise<void>;
|
|
2483
|
+
listVideoPresets(signal?: AbortSignal): Promise<VideoPreset[]>;
|
|
2484
|
+
getVideoPreset(id: string, signal?: AbortSignal): Promise<VideoPreset>;
|
|
2485
|
+
/** The daemon validates `config` strictly and names the failing field path. */
|
|
2486
|
+
createVideoPreset(body: {
|
|
2487
|
+
name: string;
|
|
2488
|
+
config?: Record<string, unknown>;
|
|
2489
|
+
}): Promise<VideoPreset>;
|
|
2490
|
+
/** A built-in preset refuses edits. Duplicate it and edit the copy. */
|
|
2491
|
+
updateVideoPreset(id: string, body: {
|
|
2492
|
+
name?: string;
|
|
2493
|
+
config?: Record<string, unknown>;
|
|
2494
|
+
}): Promise<VideoPreset>;
|
|
2495
|
+
/** The only way to make a built-in preset yours: copy, then edit the copy. */
|
|
2496
|
+
duplicateVideoPreset(id: string, body?: {
|
|
2497
|
+
name?: string;
|
|
2498
|
+
}): Promise<VideoPreset>;
|
|
2499
|
+
deleteVideoPreset(id: string): Promise<void>;
|
|
2500
|
+
/** One still of the sample film under an UNSAVED config, drawn by the daemon's own renderer.
|
|
2501
|
+
* `moment` wins over `frame`; both absent means the daemon's default moment. */
|
|
2502
|
+
previewVideoPreset(body: VideoPresetPreviewBody, signal?: AbortSignal): Promise<VideoPresetPreview>;
|
|
2503
|
+
/** A clip of the sample film, blocking until it is encoded (the editor uses the SSE form of the
|
|
2504
|
+
* same route; a script waits). Fetch the bytes with `downloadVideoPresetClip`. */
|
|
2505
|
+
previewVideoPresetClip(body: VideoPresetClipBody, signal?: AbortSignal): Promise<VideoPresetClip>;
|
|
2506
|
+
/** The clip's MP4 bytes. */
|
|
2507
|
+
downloadVideoPresetClip(id: string, signal?: AbortSignal): Promise<ArtifactBytes>;
|
|
1634
2508
|
/**
|
|
1635
2509
|
* The values a preset's `constraints` may take. Ask rather than hardcode: the
|
|
1636
2510
|
* region list comes from the daemon's embedded persona model, so a pinned copy
|
|
@@ -1654,10 +2528,27 @@ declare class ScalebrowserClient extends ClientCore {
|
|
|
1654
2528
|
startAudit(profileId: string): Promise<AuditStatus>;
|
|
1655
2529
|
/** State plus the last stored report. */
|
|
1656
2530
|
getAudit(profileId: string, signal?: AbortSignal): Promise<AuditStatus>;
|
|
2531
|
+
/** Which exit addresses this profile owns, and how far the rule reaches.
|
|
2532
|
+
*
|
|
2533
|
+
* `scope` is `'machine'` while this computer has no account key. That is the
|
|
2534
|
+
* ordinary state of a second machine until sync is unlocked there once, and it is
|
|
2535
|
+
* reported rather than hidden: believing the rule spans three machines when it
|
|
2536
|
+
* spans one is worse than knowing. */
|
|
2537
|
+
getExitStatus(profileId: string, signal?: AbortSignal): Promise<ExitStatus>;
|
|
1657
2538
|
exportSession(profileId: string, body: SessionExportBody): Promise<SessionExportResult>;
|
|
1658
2539
|
importSession(profileId: string, body: SessionImportBody): Promise<unknown>;
|
|
1659
2540
|
sendInput(profileId: string, body: TrustedInputBody): Promise<unknown>;
|
|
1660
2541
|
getMetrics(signal?: AbortSignal): Promise<Metrics>;
|
|
2542
|
+
/**
|
|
2543
|
+
* Is remote access on for this machine?
|
|
2544
|
+
*
|
|
2545
|
+
* The switch is deliberately local: a chat service reaches this browser only
|
|
2546
|
+
* once somebody at the machine has turned it on. On a headless install there
|
|
2547
|
+
* is no UI to click, which is why it is here as well.
|
|
2548
|
+
*/
|
|
2549
|
+
getRemoteAccess(signal?: AbortSignal): Promise<RemoteStatus>;
|
|
2550
|
+
/** Turn remote access on or off for this machine. */
|
|
2551
|
+
setRemoteAccess(enabled: boolean, signal?: AbortSignal): Promise<RemoteStatus>;
|
|
1661
2552
|
/** Subscribe to lifecycle events. Returns an unsubscribe function. */
|
|
1662
2553
|
subscribeEvents(handlers: StreamHandlers): () => void;
|
|
1663
2554
|
/** `for await (const event of client.events())` over lifecycle events. */
|
|
@@ -1673,14 +2564,14 @@ declare class ScalebrowserClient extends ClientCore {
|
|
|
1673
2564
|
*/
|
|
1674
2565
|
launch(profileId: string, body?: StartProfileBody): Promise<LaunchHandle>;
|
|
1675
2566
|
}
|
|
1676
|
-
interface ScalebrowserClient extends IdentityApi, RunsApi, ControlApi, ExtensionsApi {
|
|
2567
|
+
interface ScalebrowserClient extends IdentityApi, RunsApi, VideosApi, ControlApi, ExtensionsApi, TasksApi {
|
|
1677
2568
|
}
|
|
1678
2569
|
|
|
1679
2570
|
/**
|
|
1680
2571
|
* Error model: stable numeric API error codes (SPEC §5,
|
|
1681
2572
|
* `crates/core/src/error.rs`) and the typed exceptions the SDK throws.
|
|
1682
2573
|
*/
|
|
1683
|
-
/** Stable numeric API error codes (4001–
|
|
2574
|
+
/** Stable numeric API error codes (4001–4013, append-only: a retired code stays
|
|
1684
2575
|
* reserved rather than being reused). */
|
|
1685
2576
|
declare const ErrorCode: {
|
|
1686
2577
|
readonly NotFound: 4001;
|
|
@@ -1707,6 +2598,12 @@ declare const ErrorCode: {
|
|
|
1707
2598
|
* browser): the caller's move here costs nothing. Close it on that machine, or
|
|
1708
2599
|
* take it over from the app running there. */
|
|
1709
2600
|
readonly ProfileInUse: 4012;
|
|
2601
|
+
/** The exit address this start drew belongs to another profile (DEC-017).
|
|
2602
|
+
* Distinct from ProxyGeo (4002 = wrong country or wrong kind of exit, so change
|
|
2603
|
+
* the proxy): here the proxy is fine and the address is simply spoken for. Wait
|
|
2604
|
+
* for a term to run out, let the daemon draw again, or turn exclusivity off for
|
|
2605
|
+
* this profile. */
|
|
2606
|
+
readonly ExitAddressTaken: 4013;
|
|
1710
2607
|
};
|
|
1711
2608
|
type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
1712
2609
|
/** Error body shape: `{ code, message }` (docs/features/api.md). */
|
|
@@ -1764,6 +2661,6 @@ declare function errorMessage(err: unknown): string;
|
|
|
1764
2661
|
* ```
|
|
1765
2662
|
*/
|
|
1766
2663
|
|
|
1767
|
-
declare const VERSION = "0.
|
|
2664
|
+
declare const VERSION = "0.6.0";
|
|
1768
2665
|
|
|
1769
|
-
export { type Account, type ActivitySnapshot, type AgentRun, ApiError, type ApiErrorBody, type ArtifactBytes, type ArtifactPutResult, type AttachOptions, type AuditDetectorReport, type AuditReport, type AuditStatus, type AuditVerdict, type BindInboxBody, type CdpConnectOptions, CdpError, type CdpEvent, CdpSession, type ClickOptions, type CreateGroupBody, type CreateInboxBody, type CreatePresetBody, DEFAULT_CAPACITY, type DeleteInterruptionRuleParams, type EffectiveInterruptionLock, ErrorCode, type ErrorCodeValue, type EvaluateOptions, type FetchLike, GEO_MODES, type GeoMode, type GoalSource, type Group, HOST_MODES, type HealthStatus, type HostMode, type Inbox, type InboxBinding, type InboxBindings, type InboxChannel, type InputClient, type InterruptionChoice, type InterruptionLock, type InterruptionLockRow, type InterruptionLockView, type InterruptionRuleRow, type LaunchHandle, type ListRunsParams, type ListStepsParams, type NavigateOptions, NetworkError, type OsFamily, type OutcomeSource, PROXY_KINDS, type PasskeyRow, type PersonaConstraintOptions, type Preset, type PresetConfig, type PresetConstraints, type Profile, type ProfileActivity, type ProtectionLevel, type ProtectionStatus, type Proxy, type ProxyKind, ROTATIONS, RUNTIME_STATES, type ReadyStatus, type RevealCookiesBody, type RevealCookiesResult, type RevealedCookie, type Rotation, type RunActor, type RunOutcome, type RunStep, type RuntimeState, ScalebrowserClient, type ScalebrowserClientOptions, ScalebrowserError, type ScrollOptions, type SecretBindingMode, type SecretDeleteResult, type SecretKind, type SecretListResult, type SecretOrigin, type SecretPatchBody, type SecretRow, type SecretRunBody, type SecretRunMention, type SecretRunResult, type SecretScrubResult, type SecretState, type SessionExportBody, type SessionExportResult, type SessionImportBody, type SessionKind, type SetInterruptionLockBody, type SetInterruptionRuleBody, type StepKind, type StepTarget, type StreamHandlers, type StreamParams, type StreamStatus, type TrustedInputBody, type UpdateGroupBody, type UpdateInboxBody, type UpdatePresetBody, VERSION, deriveMetricsFromProfiles, errorMessage, eventStream, openCdpSession, parseSseFrame, subscribeEvents };
|
|
2666
|
+
export { type Account, type ActivitySnapshot, type AgentRun, ApiError, type ApiErrorBody, type ArtifactBytes, type ArtifactPutResult, type AttachOptions, type AudioStatus, type AuditDetectorReport, type AuditReport, type AuditStatus, type AuditVerdict, type BindInboxBody, type CdpConnectOptions, CdpError, type CdpEvent, CdpSession, type Chapter, type ClickOptions, type CodecsStatus, type CreateGroupBody, type CreateInboxBody, type CreatePresetBody, type CreateTasksBody, type CreateTasksResult, DEFAULT_CAPACITY, type DeleteInterruptionRuleParams, type EffectiveInterruptionLock, ErrorCode, type ErrorCodeValue, type EvaluateOptions, type ExitClaim, type ExitScope, type ExitStatus, type ExportPresetName, type ExtraOutput, type FetchLike, GEO_MODES, type GeoMode, type GoalSource, type Group, HOST_MODES, type HealthStatus, type HostMode, type Inbox, type InboxBinding, type InboxBindings, type InboxChannel, type InputClient, type InterruptionChoice, type InterruptionLock, type InterruptionLockRow, type InterruptionLockView, type InterruptionRuleRow, type LaunchHandle, type ListRunsParams, type ListStepsParams, type ListTasksParams, type ListVideosParams, type MediaAsset, type MediaKind, type MusicBed, type NarrationLine, type NavigateOptions, NetworkError, type OsFamily, type OutcomeSource, PROXY_KINDS, type PasskeyRow, type PatchTaskBody, type PersonaConstraintOptions, type Preset, type PresetConfig, type PresetConstraints, type PreviewHidden, type PreviewMoment, type Profile, type ProfileActivity, type ProfileMemory, type ProfileTask, type ProtectionLevel, type ProtectionStatus, type Proxy, type ProxyKind, ROTATIONS, RUNTIME_STATES, type ReadyStatus, type Recording, type RecordingKind, type RecordingState, type RemoteStatus, type RenderProgress, type RenderRequestBody, type RenderStage, type RevealCookiesBody, type RevealCookiesResult, type RevealedCookie, type Rotation, type RunActor, type RunOutcome, type RunStep, type RuntimeState, ScalebrowserClient, type ScalebrowserClientOptions, ScalebrowserError, type ScrollOptions, type SecretBindingMode, type SecretDeleteResult, type SecretKind, type SecretListResult, type SecretOrigin, type SecretPatchBody, type SecretRow, type SecretRunBody, type SecretRunMention, type SecretRunResult, type SecretScrubResult, type SecretState, type SessionExportBody, type SessionExportResult, type SessionImportBody, type SessionKind, type SetInterruptionLockBody, type SetInterruptionRuleBody, type ShareLinkLocal, type ShotFocus, type ShotIntent, type StepKind, type StepTarget, type StreamHandlers, type StreamParams, type StreamStatus, type TaskState, type TimestampState, type TranscriptWord, type TrustedInputBody, type TtsProviderView, type TtsVerifyResult, type UpdateGroupBody, type UpdateInboxBody, type UpdatePresetBody, VERSION, type Video, type VideoAccessGrant, type VideoAssetName, type VideoAssets, type VideoBackground, type VideoCard, type VideoDestination, type VideoFlags, type VideoPreset, type VideoPresetClip, type VideoPresetClipBody, type VideoPresetClipProgress, type VideoPresetClipStarted, type VideoPresetConfig, type VideoPresetPreview, type VideoPresetPreviewBody, type VideoState, type VideosPage, type VideosStorage, type WriteMemoryBody, deriveMetricsFromProfiles, errorMessage, eventStream, openCdpSession, parseSseFrame, subscribeEvents };
|