@scalebrowser/sdk 0.4.1 → 0.5.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.d.ts 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 reservation, or a person at a window. */
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. Mirrors `web-ui/src/api/events.ts`.
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. */
@@ -693,7 +1380,7 @@ declare class ControlApi extends ClientCore {
693
1380
  /**
694
1381
  * Hand the daemon a file so `interact action=upload` has something to attach.
695
1382
  *
696
- * The bytes are bound to the PROFILE, not to a reservation: set a file up
1383
+ * The bytes are bound to the PROFILE, not to a lease: set a file up
697
1384
  * before leasing, and a lease released mid-task does not destroy it.
698
1385
  */
699
1386
  putArtifact(profileId: string, bytes: Uint8Array | ArrayBuffer, name?: string): Promise<ArtifactPutResult>;
@@ -790,6 +1477,12 @@ interface TakeoverResult {
790
1477
  interface StopProfileResult {
791
1478
  stopped: boolean;
792
1479
  }
1480
+ /** `POST /v1/profiles/:id/release`: `released: false` is an honest no-op,
1481
+ * there was nothing to let go. */
1482
+ interface ReleaseProfileResult {
1483
+ released: boolean;
1484
+ stopped: boolean;
1485
+ }
793
1486
  interface BulkCreateBody {
794
1487
  preset_id: string;
795
1488
  count: number;
@@ -1289,6 +1982,53 @@ declare class IdentityApi extends ClientCore {
1289
1982
  revealCookies(profileId: string, body: RevealCookiesBody): Promise<RevealCookiesResult>;
1290
1983
  }
1291
1984
 
1985
+ declare class TasksApi extends ClientCore {
1986
+ /**
1987
+ * What is still to be done. No filter means every task of every profile.
1988
+ *
1989
+ * Pass `state: 'open'` for what is outstanding; without it, tasks finished
1990
+ * within the last day are included too.
1991
+ */
1992
+ listTasks(params?: ListTasksParams, signal?: AbortSignal): Promise<ProfileTask[]>;
1993
+ /**
1994
+ * Put the same task on one or many profiles, one row each.
1995
+ *
1996
+ * A task is a LINE, not a document: name the work and leave the material where
1997
+ * it lives. `due_at` is a deadline, not a trigger; nothing runs by itself.
1998
+ *
1999
+ * Profiles that no longer exist come back in `missing` instead of failing the
2000
+ * whole call.
2001
+ */
2002
+ createTasks(body: CreateTasksBody): Promise<CreateTasksResult>;
2003
+ /**
2004
+ * Call a task off.
2005
+ *
2006
+ * Only a task nobody has claimed can be cancelled here. One an agent is working
2007
+ * on right now is stopped by telling that agent, which is a channel that already
2008
+ * reaches it; this surface answers `409` for it rather than pretending.
2009
+ */
2010
+ cancelTask(id: string): Promise<ProfileTask>;
2011
+ /** Remove a task outright. */
2012
+ deleteTask(id: string): Promise<void>;
2013
+ /**
2014
+ * A profile's durable memory, the `PROFILE.md` at the top of its directory.
2015
+ *
2016
+ * `content` is `null` while nobody has written one: a profile starts with no
2017
+ * file, not with an empty one.
2018
+ */
2019
+ getProfileMemory(profileId: string, signal?: AbortSignal): Promise<ProfileMemory>;
2020
+ /**
2021
+ * Replace a profile's memory.
2022
+ *
2023
+ * Stored verbatim: no trimming, no appended newline, no line-ending
2024
+ * translation. The last write wins and nothing warns, exactly as with a file
2025
+ * two people can open.
2026
+ */
2027
+ putProfileMemory(profileId: string, content: string): Promise<ProfileMemory>;
2028
+ /** Remove a profile's memory. Removing one that is not there is not an error. */
2029
+ deleteProfileMemory(profileId: string): Promise<void>;
2030
+ }
2031
+
1292
2032
  /**
1293
2033
  * Agent runs and live activity (`/v1/runs`, `/v1/activity`).
1294
2034
  *
@@ -1308,7 +2048,7 @@ type OutcomeSource = 'agent' | 'check' | 'human' | 'derived';
1308
2048
  type GoalSource = 'agent' | 'derived';
1309
2049
  interface AgentRun {
1310
2050
  id: string;
1311
- /** Groups runs that shared one profile reservation. */
2051
+ /** Groups runs that shared one profile lease. */
1312
2052
  session_id: string;
1313
2053
  profile_id: string;
1314
2054
  profile_name: string;
@@ -1367,6 +2107,96 @@ declare class RunsApi extends ClientCore {
1367
2107
  getActivity(signal?: AbortSignal): Promise<ActivitySnapshot>;
1368
2108
  }
1369
2109
 
2110
+ declare class VideosApi extends ClientCore {
2111
+ /** One gallery page, newest first. Running renders are videos too. */
2112
+ listVideos(params?: ListVideosParams, signal?: AbortSignal): Promise<VideosPage>;
2113
+ /** One video row, progress included while it renders. */
2114
+ getVideo(videoId: string, signal?: AbortSignal): Promise<Video>;
2115
+ /** Rename. The title also lands in the MP4's metadata on the NEXT render. */
2116
+ renameVideo(videoId: string, title: string, signal?: AbortSignal): Promise<Video>;
2117
+ /**
2118
+ * Delete a video (`raw: true` also purges its recording's raw material).
2119
+ * A live share link is revoked first; 409 `job_running` while it renders.
2120
+ */
2121
+ deleteVideo(videoId: string, opts?: {
2122
+ raw?: boolean;
2123
+ }, signal?: AbortSignal): Promise<void>;
2124
+ /** Cancel a queued or rendering video. `done` stays done (409). */
2125
+ cancelVideo(videoId: string, signal?: AbortSignal): Promise<Video>;
2126
+ /** Render a failed or cancelled video again: same id, new job. */
2127
+ rerenderVideo(videoId: string, body?: RenderRequestBody, signal?: AbortSignal): Promise<Video>;
2128
+ /** A short-lived fetchable address for one asset (default the video). */
2129
+ videoAccess(videoId: string, asset?: VideoAssetName, signal?: AbortSignal): Promise<VideoAccessGrant>;
2130
+ /** One asset's bytes, through a freshly minted grant. */
2131
+ downloadVideoFile(videoId: string, asset?: VideoAssetName, signal?: AbortSignal): Promise<ArtifactBytes>;
2132
+ /** What recordings and videos cost on disk, plus the caps. */
2133
+ videosStorage(signal?: AbortSignal): Promise<VideosStorage>;
2134
+ /** Recordings, newest first. The row outlives its raw bytes. */
2135
+ listRecordings(params?: {
2136
+ profile_id?: string;
2137
+ }, signal?: AbortSignal): Promise<Recording[]>;
2138
+ getRecording(recordingId: string, signal?: AbortSignal): Promise<Recording>;
2139
+ /**
2140
+ * Purge a recording's RAW material; the row stays forever
2141
+ * (`raw_purged_at`). 409 `job_running` while a render of it is open.
2142
+ */
2143
+ deleteRecordingRaw(recordingId: string, signal?: AbortSignal): Promise<void>;
2144
+ /** A NEW video from this recording (the same body the `video` tool takes). */
2145
+ renderRecording(recordingId: string, body?: RenderRequestBody, signal?: AbortSignal): Promise<Video>;
2146
+ /** What this machine can encode with. The hardware list is PROBED, not read
2147
+ * off the binary: `h264_nvenc` is always listed and fails without a driver. */
2148
+ getCodecs(signal?: AbortSignal): Promise<CodecsStatus>;
2149
+ /** Turn Cisco's OpenH264 on or off. The hardware encoders are not switchable. */
2150
+ setCodecEnabled(codec: string, enabled: boolean, signal?: AbortSignal): Promise<CodecsStatus>;
2151
+ /** Make a finished video public. Measures every file, asks the control plane
2152
+ * for permission, uploads, and has the result confirmed. */
2153
+ share(videoId: string, body?: {
2154
+ expires_days?: number | null;
2155
+ passcode?: string | null;
2156
+ download?: boolean;
2157
+ }, signal?: AbortSignal): Promise<ShareLinkLocal>;
2158
+ /** The share ORDER as this machine knows it. How many people watched and
2159
+ * whether the link still lives is read from the control plane, not from
2160
+ * here: a number carried along would be wrong the moment another machine
2161
+ * revoked. */
2162
+ shareStatus(videoId: string, signal?: AbortSignal): Promise<ShareLinkLocal>;
2163
+ /** Revoke the link. The files fall at once; the order stays until the control
2164
+ * plane confirms. */
2165
+ revokeShare(videoId: string, signal?: AbortSignal): Promise<void>;
2166
+ /** Files a preset points at: background image, music bed, subtitle font. */
2167
+ listMedia(kind?: MediaKind, signal?: AbortSignal): Promise<MediaAsset[]>;
2168
+ /** Upload one file. The body IS the file; `name` and `mime` ride in the query. */
2169
+ uploadMedia(kind: MediaKind, name: string, mime: string, bytes: Uint8Array, signal?: AbortSignal): Promise<MediaAsset>;
2170
+ /** Remove a file. Refuses with 409 while a preset still points at it. */
2171
+ deleteMedia(id: string, signal?: AbortSignal): Promise<void>;
2172
+ /** The file itself. */
2173
+ mediaFile(id: string, signal?: AbortSignal): Promise<ArtifactBytes>;
2174
+ /** Which speech providers have a key. The key itself never comes back: the
2175
+ * answer carries a hint, and that is on purpose. */
2176
+ listTtsProviders(signal?: AbortSignal): Promise<TtsProviderView[]>;
2177
+ /** Store a key, or rename one. Leaving `apiKey` out keeps the stored key.
2178
+ *
2179
+ * `apiKey` may also be a secret reference (`{{sb:...}}`), which is what an
2180
+ * agent gets back after fetching a key from the provider's own site: it is
2181
+ * not allowed to read the value. A reference needs `profileId`, because the
2182
+ * value belongs to one profile and there is nothing to open without it.
2183
+ */
2184
+ putTtsProvider(provider: string, body: {
2185
+ apiKey?: string;
2186
+ label?: string;
2187
+ profileId?: string;
2188
+ }, signal?: AbortSignal): Promise<TtsProviderView>;
2189
+ /** Call the provider once for real, and record that the key works.
2190
+ *
2191
+ * Costs one short sentence of the account's own quota. Until this runs, a
2192
+ * provider row says `verified_at: null`, which means untested rather than
2193
+ * broken.
2194
+ */
2195
+ verifyTtsProvider(provider: string, signal?: AbortSignal): Promise<TtsVerifyResult>;
2196
+ /** Forget a provider's key. */
2197
+ deleteTtsProvider(provider: string, signal?: AbortSignal): Promise<void>;
2198
+ }
2199
+
1370
2200
  /**
1371
2201
  * Direct-CDP driver (DEC-006, AC-FP-005): a minimal, nodriver-style Chrome
1372
2202
  * DevTools Protocol client over a raw websocket. This is the recommended SDK
@@ -1596,6 +2426,13 @@ declare class ScalebrowserClient extends ClientCore {
1596
2426
  /** Start a profile → CDP ws endpoint. Errors: 4002/4003/4005/4006/4008. */
1597
2427
  startProfile(id: string, body?: StartProfileBody): Promise<StartProfileResult>;
1598
2428
  stopProfile(id: string): Promise<StopProfileResult>;
2429
+ /** Drop the profile's lease, the operator's way out.
2430
+ *
2431
+ * An agent releases with its handle; this call needs none. The daemon stops
2432
+ * the browser first when one is still up, then lets the lease go, so a dead
2433
+ * session cannot park the profile until its TTL runs out. `released: false`
2434
+ * is an honest no-op: there was nothing to let go. */
2435
+ releaseProfile(id: string): Promise<ReleaseProfileResult>;
1599
2436
  /** Ask for a profile that is open on another machine of this account.
1600
2437
  *
1601
2438
  * Closes nothing here and nothing there: the control plane revokes the holder's
@@ -1631,6 +2468,31 @@ declare class ScalebrowserClient extends ClientCore {
1631
2468
  createPreset(body: CreatePresetBody): Promise<Preset>;
1632
2469
  updatePreset(id: string, body: UpdatePresetBody): Promise<Preset>;
1633
2470
  deletePreset(id: string): Promise<void>;
2471
+ listVideoPresets(signal?: AbortSignal): Promise<VideoPreset[]>;
2472
+ getVideoPreset(id: string, signal?: AbortSignal): Promise<VideoPreset>;
2473
+ /** The daemon validates `config` strictly and names the failing field path. */
2474
+ createVideoPreset(body: {
2475
+ name: string;
2476
+ config?: Record<string, unknown>;
2477
+ }): Promise<VideoPreset>;
2478
+ /** A built-in preset refuses edits. Duplicate it and edit the copy. */
2479
+ updateVideoPreset(id: string, body: {
2480
+ name?: string;
2481
+ config?: Record<string, unknown>;
2482
+ }): Promise<VideoPreset>;
2483
+ /** The only way to make a built-in preset yours: copy, then edit the copy. */
2484
+ duplicateVideoPreset(id: string, body?: {
2485
+ name?: string;
2486
+ }): Promise<VideoPreset>;
2487
+ deleteVideoPreset(id: string): Promise<void>;
2488
+ /** One still of the sample film under an UNSAVED config, drawn by the daemon's own renderer.
2489
+ * `moment` wins over `frame`; both absent means the daemon's default moment. */
2490
+ previewVideoPreset(body: VideoPresetPreviewBody, signal?: AbortSignal): Promise<VideoPresetPreview>;
2491
+ /** A clip of the sample film, blocking until it is encoded (the editor uses the SSE form of the
2492
+ * same route; a script waits). Fetch the bytes with `downloadVideoPresetClip`. */
2493
+ previewVideoPresetClip(body: VideoPresetClipBody, signal?: AbortSignal): Promise<VideoPresetClip>;
2494
+ /** The clip's MP4 bytes. */
2495
+ downloadVideoPresetClip(id: string, signal?: AbortSignal): Promise<ArtifactBytes>;
1634
2496
  /**
1635
2497
  * The values a preset's `constraints` may take. Ask rather than hardcode: the
1636
2498
  * region list comes from the daemon's embedded persona model, so a pinned copy
@@ -1654,6 +2516,13 @@ declare class ScalebrowserClient extends ClientCore {
1654
2516
  startAudit(profileId: string): Promise<AuditStatus>;
1655
2517
  /** State plus the last stored report. */
1656
2518
  getAudit(profileId: string, signal?: AbortSignal): Promise<AuditStatus>;
2519
+ /** Which exit addresses this profile owns, and how far the rule reaches.
2520
+ *
2521
+ * `scope` is `'machine'` while this computer has no account key. That is the
2522
+ * ordinary state of a second machine until sync is unlocked there once, and it is
2523
+ * reported rather than hidden: believing the rule spans three machines when it
2524
+ * spans one is worse than knowing. */
2525
+ getExitStatus(profileId: string, signal?: AbortSignal): Promise<ExitStatus>;
1657
2526
  exportSession(profileId: string, body: SessionExportBody): Promise<SessionExportResult>;
1658
2527
  importSession(profileId: string, body: SessionImportBody): Promise<unknown>;
1659
2528
  sendInput(profileId: string, body: TrustedInputBody): Promise<unknown>;
@@ -1673,14 +2542,14 @@ declare class ScalebrowserClient extends ClientCore {
1673
2542
  */
1674
2543
  launch(profileId: string, body?: StartProfileBody): Promise<LaunchHandle>;
1675
2544
  }
1676
- interface ScalebrowserClient extends IdentityApi, RunsApi, ControlApi, ExtensionsApi {
2545
+ interface ScalebrowserClient extends IdentityApi, RunsApi, VideosApi, ControlApi, ExtensionsApi, TasksApi {
1677
2546
  }
1678
2547
 
1679
2548
  /**
1680
2549
  * Error model: stable numeric API error codes (SPEC §5,
1681
2550
  * `crates/core/src/error.rs`) and the typed exceptions the SDK throws.
1682
2551
  */
1683
- /** Stable numeric API error codes (4001–4012, append-only: a retired code stays
2552
+ /** Stable numeric API error codes (4001–4013, append-only: a retired code stays
1684
2553
  * reserved rather than being reused). */
1685
2554
  declare const ErrorCode: {
1686
2555
  readonly NotFound: 4001;
@@ -1707,6 +2576,12 @@ declare const ErrorCode: {
1707
2576
  * browser): the caller's move here costs nothing. Close it on that machine, or
1708
2577
  * take it over from the app running there. */
1709
2578
  readonly ProfileInUse: 4012;
2579
+ /** The exit address this start drew belongs to another profile (DEC-017).
2580
+ * Distinct from ProxyGeo (4002 = wrong country or wrong kind of exit, so change
2581
+ * the proxy): here the proxy is fine and the address is simply spoken for. Wait
2582
+ * for a term to run out, let the daemon draw again, or turn exclusivity off for
2583
+ * this profile. */
2584
+ readonly ExitAddressTaken: 4013;
1710
2585
  };
1711
2586
  type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode];
1712
2587
  /** Error body shape: `{ code, message }` (docs/features/api.md). */
@@ -1764,6 +2639,6 @@ declare function errorMessage(err: unknown): string;
1764
2639
  * ```
1765
2640
  */
1766
2641
 
1767
- declare const VERSION = "0.4.1";
2642
+ declare const VERSION = "0.5.0";
1768
2643
 
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 };
2644
+ 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 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 };