@scalebrowser/sdk 0.7.0 → 0.8.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,53 @@
1
+ # Changelog
2
+
3
+ The Node/TypeScript SDK for the Scalebrowser daemon.
4
+
5
+ This file starts at 0.5.0, the oldest release still on npm when it was written
6
+ (2026-09-09). What came before is in the repository's history. It was never
7
+ published as release notes, and reconstructing it here would look like a record
8
+ that had been kept all along.
9
+
10
+ The daemon and the SDK version independently. An SDK release names the daemon
11
+ version it was tested against wherever that matters.
12
+
13
+ ## 0.8.1 (2026-09-16)
14
+
15
+ The published `package.json` no longer lists a `smoke` script. It pointed at a
16
+ file outside the package, so it could not run from an installed copy, and
17
+ nothing called it. The library itself is unchanged.
18
+
19
+ ## 0.8.0 (2026-09-11)
20
+
21
+ Breaking: `host_mode` is gone, and with it the `HostMode` type and the
22
+ `HOST_MODES` list. It named one of two tiers, and there is only one left: a
23
+ daemon runs the engine built for its own operating system, so the tier is the
24
+ host. The field disappears from `Profile`, from `CreateProfileBody` and from a
25
+ preset's `config`. A client that keeps sending it is not refused; the daemon
26
+ ignores the key.
27
+
28
+ ## 0.7.0 (2026-09-09)
29
+
30
+ - `checkProxy` and the exit-address views report the address KIND (mobile, fixed
31
+ line, datacenter, unknown) from an ASN dataset instead of the provider's own
32
+ description. The ownership term for an exit address follows that kind, so a
33
+ wrong classification used to be off by a factor of 30.
34
+ - A proxy row carries a name and lists the profiles bound to it.
35
+ - The exit-exclusivity rule has a switch, globally and per profile.
36
+
37
+ ## 0.6.0 (2026-09-01)
38
+
39
+ - Remote access (the MCP tunnel) has a switch. It ships off, and it can only be
40
+ turned on at the machine itself.
41
+
42
+ ## 0.5.0 (2026-08-31)
43
+
44
+ - Every profile carries a memory (`PROFILE.md`) and a task list. Both are
45
+ reachable through the client.
46
+ - `proxy_short_side` in both SDKs.
47
+ - The agent layer says "lease" throughout, matching the names of its tools.
48
+
49
+ ## What this file does not promise
50
+
51
+ Nothing here promises a stable wire format. The daemon's REST surface is
52
+ versioned under `/v1` and this client tracks it. A breaking change there arrives
53
+ as a major version of the SDK, with the reason written in this file.
package/dist/index.cjs CHANGED
@@ -1386,6 +1386,23 @@ var ScalebrowserClient = class extends ClientCore {
1386
1386
  signal
1387
1387
  });
1388
1388
  }
1389
+ /**
1390
+ * How many profiles match `params`, split by runtime state. One request, and
1391
+ * its size does not grow with the fleet.
1392
+ *
1393
+ * `listProfiles` is paged and answers a bare array, so counting what came back
1394
+ * counts the page. `listProfileIds` carries the same total but ships an
1395
+ * identifier per profile to do it, and cannot split by state at all.
1396
+ *
1397
+ * `params.state` is ignored here on purpose: a caller labelling every state is
1398
+ * sitting in one of them.
1399
+ */
1400
+ countProfiles(params = {}, signal) {
1401
+ return this.request("GET", "/v1/profiles/count", void 0, {
1402
+ query: { group: params.group, q: params.q },
1403
+ signal
1404
+ });
1405
+ }
1389
1406
  getProfile(id, signal) {
1390
1407
  return this.request("GET", `/v1/profiles/${enc(id)}`, void 0, { signal });
1391
1408
  }
@@ -1716,13 +1733,12 @@ applyMixins(ScalebrowserClient, [
1716
1733
 
1717
1734
  // src/types.ts
1718
1735
  var RUNTIME_STATES = ["stopped", "starting", "running", "crashed"];
1719
- var HOST_MODES = ["linux_engine_spoof", "local_native_windows"];
1720
1736
  var GEO_MODES = ["strict_expected", "follow_exit", "off"];
1721
1737
  var PROXY_KINDS = ["http", "socks5", "gateway"];
1722
1738
  var ROTATIONS = ["sticky", "rotating"];
1723
1739
 
1724
1740
  // src/index.ts
1725
- var VERSION = "0.7.0";
1741
+ var VERSION = "0.8.1";
1726
1742
 
1727
1743
  exports.ApiError = ApiError;
1728
1744
  exports.CdpError = CdpError;
@@ -1730,7 +1746,6 @@ exports.CdpSession = CdpSession;
1730
1746
  exports.DEFAULT_CAPACITY = DEFAULT_CAPACITY;
1731
1747
  exports.ErrorCode = ErrorCode;
1732
1748
  exports.GEO_MODES = GEO_MODES;
1733
- exports.HOST_MODES = HOST_MODES;
1734
1749
  exports.NetworkError = NetworkError;
1735
1750
  exports.PROXY_KINDS = PROXY_KINDS;
1736
1751
  exports.ROTATIONS = ROTATIONS;
package/dist/index.d.cts CHANGED
@@ -81,7 +81,6 @@ interface PersonaMisc {
81
81
  get_installed_related_apps: boolean;
82
82
  max_touch_points: number;
83
83
  pdf_viewer_enabled: boolean;
84
- headless_guards: boolean;
85
84
  }
86
85
  interface Persona {
87
86
  os: OsFamily;
@@ -111,7 +110,7 @@ type RecordingState = 'recording' | 'finishing' | 'finished' | 'failed';
111
110
  type VideoState = 'queued' | 'rendering' | 'done' | 'failed' | 'cancelled';
112
111
  type ExportPresetName = 'web' | 'social' | '4k' | 'editing' | 'gif';
113
112
  type AudioStatus = 'ok' | 'silent' | 'off' | 'failed';
114
- type RenderStage = 'planning' | 'narration' | 'compositing' | 'encoding' | 'finishing';
113
+ type RenderStage = 'planning' | 'narration' | 'compositing' | 'encoding' | 'finishing' | 'extras';
115
114
  /** Which files a finished video has. Booleans on purpose, never paths. */
116
115
  interface VideoAssets {
117
116
  video: boolean;
@@ -159,10 +158,11 @@ type TimestampState = {
159
158
  state: 'failed';
160
159
  reason: string;
161
160
  };
161
+ /** One spoken word and when it is heard in the finished video, in milliseconds from its start. */
162
162
  interface TranscriptWord {
163
163
  text: string;
164
- from_ms: number;
165
- to_ms: number;
164
+ start_ms: number;
165
+ end_ms: number;
166
166
  }
167
167
  /** One video row: queued and rendering renders included. */
168
168
  interface Video {
@@ -177,7 +177,7 @@ interface Video {
177
177
  kind: RecordingKind;
178
178
  preset_name: string;
179
179
  /** The resolved recipe this video renders (or rendered) under. */
180
- preset: unknown;
180
+ preset: VideoPresetConfig;
181
181
  export: ExportPresetName;
182
182
  assets: VideoAssets;
183
183
  duration_ms: number | null;
@@ -190,7 +190,8 @@ interface Video {
190
190
  chapters: Chapter[];
191
191
  transcript: TranscriptWord[] | null;
192
192
  flags: VideoFlags | null;
193
- share: unknown | null;
193
+ /** The share link of this video ON THIS MACHINE, or nothing shared yet. */
194
+ share: ShareLinkLocal | null;
194
195
  error: string | null;
195
196
  created_at: number;
196
197
  updated_at: number;
@@ -204,8 +205,11 @@ interface Recording {
204
205
  kind: RecordingKind;
205
206
  state: RecordingState;
206
207
  title: string | null;
208
+ /** The id of the stored preset the recording was made under, `null` when it named none. */
207
209
  preset_id: string | null;
208
- preset: unknown;
210
+ /** That preset's name as it read when the recording started. */
211
+ preset_name: string | null;
212
+ preset: VideoPresetConfig;
209
213
  manifest_version: number;
210
214
  css_width: number;
211
215
  css_height: number;
@@ -299,10 +303,14 @@ interface VideoAccessGrant {
299
303
  interface VideosStorage {
300
304
  recordings_bytes: number;
301
305
  videos_bytes: number;
306
+ /** The main files of the videos this machine still shares. */
302
307
  link_bytes: number;
303
- link_limit: number;
304
- uploads_today: number;
305
- uploads_limit: number;
308
+ /** Known only to the control plane; `null` here. */
309
+ link_limit: number | null;
310
+ /** Known only to the control plane; `null` here. */
311
+ uploads_today: number | null;
312
+ /** Known only to the control plane; `null` here. */
313
+ uploads_limit: number | null;
306
314
  capacity: {
307
315
  recordings_active: number;
308
316
  recordings_max: number;
@@ -322,6 +330,18 @@ interface CodecsStatus {
322
330
  };
323
331
  /** Hardware encoders that passed a real test encode, in preference order. */
324
332
  hardware: string[];
333
+ /** Whether the hardware probe has run. Before it, an empty `hardware` means
334
+ * "not asked yet", not "none". */
335
+ probed: boolean;
336
+ /** Exports this daemon refuses whatever the order says, with the reason. An
337
+ * editor hides them rather than letting a render fail on them. */
338
+ exports_blocked: BlockedExport[];
339
+ }
340
+ /** One export the daemon refuses, e.g. `4k` while a 3840-wide capture is not
341
+ * offered. `reason` starts with its snake code. */
342
+ interface BlockedExport {
343
+ export: ExportPresetName;
344
+ reason: string;
325
345
  }
326
346
  /** What kind of file a media asset is. */
327
347
  type MediaKind = 'image' | 'music' | 'subtitle_style';
@@ -380,23 +400,23 @@ interface ShareLinkLocal {
380
400
  updated_at: number;
381
401
  error: string | null;
382
402
  }
403
+ /** `GET /v1/videos/:id/share`: the order, and the link's access code when this
404
+ * machine keeps one (sealed at rest). A link the daemon makes for a preset with
405
+ * `export.destination.passcode` gets a generated code of ten characters, and
406
+ * this is where its owner reads it. `Video.share`, `video_changed` and the
407
+ * `video` tool never carry the code. */
408
+ interface ShareStatus extends ShareLinkLocal {
409
+ /** Absent when this machine keeps no code: the link has none, or its
410
+ * revocation is ordered. */
411
+ code?: string;
412
+ }
383
413
 
384
414
  /**
385
- * Wire types: a 1:1 mirror of the daemon's serialized domain model
386
- * (`crates/core/src/model.rs`, `persona.rs`, `events.rs`) and the endpoint
387
- * contract in `docs/features/api.md`.
388
- *
389
- * THIS IS THE SOURCE, and since 2026-09-09 it is the only one on the TypeScript
390
- * side: `web-ui/src/api/types.ts` re-exports these files through the
391
- * `@scalebrowser/wire/*` alias instead of keeping a second copy (Decision 022).
392
- * Before that the same 160 declarations stood twice, and each header named the
393
- * other as the truth. The Python SDK
394
- * (`sdks/python/src/scalebrowser/models*.py`) still carries the shapes by hand,
395
- * deliberately without a gate; a TS↔pydantic comparator is its own tool.
415
+ * Wire types: a 1:1 mirror of the daemon's serialized domain model and of the
416
+ * endpoint contract, and the one source of both on the TypeScript side.
396
417
  *
397
- * These files import nothing but each other, and that is load-bearing rather
398
- * than tidy: the web-ui pulls them into a BROWSER bundle. A guard in
399
- * `web-ui/src/test/sdk-type-mirror.test.ts` holds the property.
418
+ * These files import nothing but each other, which keeps them usable inside a
419
+ * browser bundle.
400
420
  *
401
421
  * All Rust enums serialize `snake_case` (serde `rename_all`). Timestamps are
402
422
  * unix seconds (`number`, Rust `i64`). The truth for any disagreement is the
@@ -406,9 +426,6 @@ interface ShareLinkLocal {
406
426
  /** `RuntimeState` (AC-PR-004). */
407
427
  type RuntimeState = 'stopped' | 'starting' | 'running' | 'crashed';
408
428
  declare const RUNTIME_STATES: readonly RuntimeState[];
409
- /** `HostMode` (PRD §B, DEC-004). Default `linux_engine_spoof`. */
410
- type HostMode = 'linux_engine_spoof' | 'local_native_windows';
411
- declare const HOST_MODES: readonly HostMode[];
412
429
  /** `GeoMode` (AC-PX-002). Default `follow_exit`. */
413
430
  type GeoMode = 'strict_expected' | 'follow_exit' | 'off';
414
431
  declare const GEO_MODES: readonly GeoMode[];
@@ -443,7 +460,6 @@ interface Profile {
443
460
  seed: string;
444
461
  engine_version: string;
445
462
  persona: Persona;
446
- host_mode: HostMode;
447
463
  gpu_persona: string | null;
448
464
  group_id: string | null;
449
465
  proxy_id: string | null;
@@ -485,7 +501,6 @@ interface Group {
485
501
  interface PresetConfig {
486
502
  /** Pin the batch to one engine build. Omit for per-profile version diversity. */
487
503
  engine_version?: string | null;
488
- host_mode?: HostMode | null;
489
504
  geo_mode?: GeoMode | null;
490
505
  /** The geo GATE's expectation, not the persona's drawn region. */
491
506
  expected_country?: string | null;
@@ -603,7 +618,8 @@ interface VideoPresetConfig {
603
618
  voice: string | null;
604
619
  language: string;
605
620
  subtitles: 'burned' | 'file' | 'off';
606
- subtitle_style: string;
621
+ /** `custom:<media_id>` names an uploaded font (media kind `subtitle_style`). */
622
+ subtitle_style: 'classic' | 'word' | `custom:${string}`;
607
623
  page_audio: boolean;
608
624
  music: MusicBed | null;
609
625
  };
@@ -839,8 +855,9 @@ interface SessionImportBody {
839
855
  }
840
856
  /**
841
857
  * Trusted-input payload (`POST /v1/profiles/:id/input`, G8, AC-API-003). Only
842
- * `action` and `humanize` are fixed by `docs/features/api.md`; the per-action coordinate
843
- * fields below are the SDK's contract assumption for the daemon's input crate.
858
+ * `action` and `humanize` are fixed by the API contract; the per-action
859
+ * coordinate fields below are the SDK's assumption about the daemon's input
860
+ * layer.
844
861
  */
845
862
  type TrustedInputBody = {
846
863
  action: 'move';
@@ -948,8 +965,7 @@ interface ExitStatus {
948
965
  /**
949
966
  * The per-profile task list and the profile's own durable memory.
950
967
  *
951
- * One of the files that ARE the contract; the web-ui reads them through
952
- * `@scalebrowser/wire/*` rather than keeping a copy (Decision 022).
968
+ * One of the files that are the daemon's wire contract.
953
969
  */
954
970
  /**
955
971
  * Where a task stands.
@@ -1228,13 +1244,6 @@ type StreamedEvent = LifecycleEvent & {
1228
1244
  * the browser `EventSource` cannot do that) and reconnect with backoff. A
1229
1245
  * `/v1/ws` websocket carries the same events; SSE is sufficient for one-way
1230
1246
  * fan-out.
1231
- *
1232
- * Mirrors `web-ui/src/api/events.ts` line for line, deliberately: this package
1233
- * ships to npm and should carry no dependency it does not need, so a shared
1234
- * package would cost more than the copy does. The copy pays for itself with a
1235
- * gate instead: `scripts/verify-mirrored-values.mjs` holds `MAX_BACKOFF_MS` and
1236
- * the backoff line itself against the other side. Two clients of the same daemon
1237
- * that come back at different speeds would be a decision nobody made.
1238
1247
  */
1239
1248
 
1240
1249
  /** Injectable `fetch`; defaults to the global at call time. */
@@ -1278,8 +1287,7 @@ declare function eventStream(params: StreamParams): AsyncIterableIterator<Lifecy
1278
1287
  * What the browser asks (interruptions), the bytes that go in and out
1279
1288
  * (artifacts), and what the licence says (account).
1280
1289
  *
1281
- * One of the files that ARE the contract; the web-ui reads them through
1282
- * `@scalebrowser/wire/*` rather than keeping a copy (Decision 022).
1290
+ * One of the files that are the daemon's wire contract.
1283
1291
  */
1284
1292
  /** What an operator has taken out of an agent's hands. */
1285
1293
  type InterruptionLock = 'always_block' | 'always_allow' | 'agent_decides';
@@ -1542,6 +1550,24 @@ interface ProfileIdsResult {
1542
1550
  count: number;
1543
1551
  ids: string[];
1544
1552
  }
1553
+ /**
1554
+ * `GET /v1/profiles/count`: how many profiles match, split by runtime state.
1555
+ *
1556
+ * `total` counts ROWS, so it is the sum of the four states for every state this
1557
+ * daemon can read; a row in a state a newer build introduced counts in `total`
1558
+ * alone rather than being folded into `stopped`.
1559
+ *
1560
+ * The `state` filter is the one this route ignores. A caller labelling all four
1561
+ * scopes is sitting in one of them, so narrowing by it would answer the other
1562
+ * three with zero. Every other filter binds exactly as it does for the listing.
1563
+ */
1564
+ interface ProfileCounts {
1565
+ total: number;
1566
+ stopped: number;
1567
+ starting: number;
1568
+ running: number;
1569
+ crashed: number;
1570
+ }
1545
1571
  /** `POST /v1/bulk/start`: per-id results plus what the batch as a whole did. */
1546
1572
  interface BulkStartResult {
1547
1573
  results: {
@@ -1566,7 +1592,6 @@ interface ListProfilesParams {
1566
1592
  interface CreateProfileBody {
1567
1593
  name: string;
1568
1594
  seed?: string;
1569
- host_mode?: HostMode;
1570
1595
  geo_mode?: GeoMode;
1571
1596
  expected_country?: string | null;
1572
1597
  /**
@@ -1588,11 +1613,11 @@ interface CreateProfileBody {
1588
1613
  proxy_id?: string | null;
1589
1614
  }
1590
1615
  /**
1591
- * PATCH, all mutable fields optional. `host_mode` and `seed` are fixed at create
1592
- * time (C4/C5): a DIFFERING `host_mode` is refused with 400, an unchanged echo is
1593
- * accepted. Changing a tier requires delete + recreate.
1616
+ * PATCH, all mutable fields optional. `seed` and `persona_country` are fixed at
1617
+ * create time (C5): they draw the identity, and redrawing it under a profile that
1618
+ * has already been used would be a new identity in an old profile's clothes.
1594
1619
  */
1595
- type UpdateProfileBody = Omit<Partial<CreateProfileBody>, "host_mode" | "seed" | "persona_country"> & {
1620
+ type UpdateProfileBody = Omit<Partial<CreateProfileBody>, "seed" | "persona_country"> & {
1596
1621
  /**
1597
1622
  * Turn the exit-address rule off for this profile (DEC-017). Deliberately not
1598
1623
  * part of `CreateProfileBody`: a new profile always claims its address, and
@@ -1790,8 +1815,7 @@ declare class ExtensionsApi extends ClientCore {
1790
1815
  * The account layer: mailboxes, passkeys and the one door a cookie value leaves
1791
1816
  * through.
1792
1817
  *
1793
- * One of the files that ARE the contract; the web-ui reads them through
1794
- * `@scalebrowser/wire/*` rather than keeping a copy (Decision 022). The cookie
1818
+ * One of the files that are the daemon's wire contract. The cookie
1795
1819
  * reveal has no UI counterpart: it is a REST-only route deliberately kept off
1796
1820
  * every screen.
1797
1821
  */
@@ -2196,8 +2220,7 @@ declare class TasksApi extends ClientCore {
2196
2220
  * the live event stream carries them, and the run list describes the same rows.
2197
2221
  * A second copy would let the two drift apart while both looked right.
2198
2222
  *
2199
- * One of the files that ARE the contract; the web-ui reads them through
2200
- * `@scalebrowser/wire/*` rather than keeping a copy (Decision 022).
2223
+ * One of the files that are the daemon's wire contract.
2201
2224
  */
2202
2225
 
2203
2226
  /** Who made the outcome claim. `derived` means nobody did. */
@@ -2317,7 +2340,7 @@ declare class VideosApi extends ClientCore {
2317
2340
  * whether the link still lives is read from the control plane, not from
2318
2341
  * here: a number carried along would be wrong the moment another machine
2319
2342
  * revoked. */
2320
- shareStatus(videoId: string, signal?: AbortSignal): Promise<ShareLinkLocal>;
2343
+ shareStatus(videoId: string, signal?: AbortSignal): Promise<ShareStatus>;
2321
2344
  /** Revoke the link. The files fall at once; the order stays until the control
2322
2345
  * plane confirms. */
2323
2346
  revokeShare(videoId: string, signal?: AbortSignal): Promise<void>;
@@ -2549,7 +2572,7 @@ interface Metrics {
2549
2572
  * (shapes), nowhere else.
2550
2573
  */
2551
2574
 
2552
- /** Mirrors `CapacityConfig::default()` (`crates/core/src/config.rs`). */
2575
+ /** The daemon's own default capacity limits. */
2553
2576
  declare const DEFAULT_CAPACITY: {
2554
2577
  max_concurrent: number;
2555
2578
  ram_budget_mb: number;
@@ -2577,6 +2600,18 @@ declare class ScalebrowserClient extends ClientCore {
2577
2600
  * page you fetched. Asking for ids costs one request and no persona payloads.
2578
2601
  */
2579
2602
  listProfileIds(params?: ListProfilesParams, signal?: AbortSignal): Promise<ProfileIdsResult>;
2603
+ /**
2604
+ * How many profiles match `params`, split by runtime state. One request, and
2605
+ * its size does not grow with the fleet.
2606
+ *
2607
+ * `listProfiles` is paged and answers a bare array, so counting what came back
2608
+ * counts the page. `listProfileIds` carries the same total but ships an
2609
+ * identifier per profile to do it, and cannot split by state at all.
2610
+ *
2611
+ * `params.state` is ignored here on purpose: a caller labelling every state is
2612
+ * sitting in one of them.
2613
+ */
2614
+ countProfiles(params?: ListProfilesParams, signal?: AbortSignal): Promise<ProfileCounts>;
2580
2615
  getProfile(id: string, signal?: AbortSignal): Promise<Profile>;
2581
2616
  createProfile(body: CreateProfileBody): Promise<Profile>;
2582
2617
  updateProfile(id: string, body: UpdateProfileBody): Promise<Profile>;
@@ -2731,8 +2766,8 @@ interface ScalebrowserClient extends IdentityApi, RunsApi, VideosApi, ControlApi
2731
2766
  }
2732
2767
 
2733
2768
  /**
2734
- * Error model: stable numeric API error codes (SPEC §5,
2735
- * `crates/core/src/error.rs`) and the typed exceptions the SDK throws.
2769
+ * Error model: the stable numeric API error codes and the typed exceptions
2770
+ * the SDK throws.
2736
2771
  */
2737
2772
  /** Stable numeric API error codes (4001–4013, append-only: a retired code stays
2738
2773
  * reserved rather than being reused). */
@@ -2769,7 +2804,7 @@ declare const ErrorCode: {
2769
2804
  readonly ExitAddressTaken: 4013;
2770
2805
  };
2771
2806
  type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode];
2772
- /** Error body shape: `{ code, message }` (docs/features/api.md). */
2807
+ /** Error body shape: `{ code, message }`. */
2773
2808
  interface ApiErrorBody {
2774
2809
  code?: number;
2775
2810
  message?: string;
@@ -2824,6 +2859,6 @@ declare function errorMessage(err: unknown): string;
2824
2859
  * ```
2825
2860
  */
2826
2861
 
2827
- declare const VERSION = "0.7.0";
2862
+ declare const VERSION = "0.8.1";
2828
2863
 
2829
- 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 Connection, type CreateGroupBody, type CreateInboxBody, type CreatePresetBody, type CreateTasksBody, type CreateTasksResult, DEFAULT_CAPACITY, type DeleteInterruptionRuleParams, type EffectiveInterruptionLock, ErrorCode, type ErrorCodeValue, type EvaluateOptions, type ExitClaim, type ExitRuleStatus, 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, type ProxyRow, type ProxyUsage, 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 };
2864
+ 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 BlockedExport, type CdpConnectOptions, CdpError, type CdpEvent, CdpSession, type Chapter, type ClickOptions, type CodecsStatus, type Connection, type CreateGroupBody, type CreateInboxBody, type CreatePresetBody, type CreateTasksBody, type CreateTasksResult, DEFAULT_CAPACITY, type DeleteInterruptionRuleParams, type EffectiveInterruptionLock, ErrorCode, type ErrorCodeValue, type EvaluateOptions, type ExitClaim, type ExitRuleStatus, type ExitScope, type ExitStatus, type ExportPresetName, type ExtraOutput, type FetchLike, GEO_MODES, type GeoMode, type GoalSource, type Group, type HealthStatus, 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, type ProxyRow, type ProxyUsage, 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 ShareStatus, 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 };
package/dist/index.d.ts CHANGED
@@ -81,7 +81,6 @@ interface PersonaMisc {
81
81
  get_installed_related_apps: boolean;
82
82
  max_touch_points: number;
83
83
  pdf_viewer_enabled: boolean;
84
- headless_guards: boolean;
85
84
  }
86
85
  interface Persona {
87
86
  os: OsFamily;
@@ -111,7 +110,7 @@ type RecordingState = 'recording' | 'finishing' | 'finished' | 'failed';
111
110
  type VideoState = 'queued' | 'rendering' | 'done' | 'failed' | 'cancelled';
112
111
  type ExportPresetName = 'web' | 'social' | '4k' | 'editing' | 'gif';
113
112
  type AudioStatus = 'ok' | 'silent' | 'off' | 'failed';
114
- type RenderStage = 'planning' | 'narration' | 'compositing' | 'encoding' | 'finishing';
113
+ type RenderStage = 'planning' | 'narration' | 'compositing' | 'encoding' | 'finishing' | 'extras';
115
114
  /** Which files a finished video has. Booleans on purpose, never paths. */
116
115
  interface VideoAssets {
117
116
  video: boolean;
@@ -159,10 +158,11 @@ type TimestampState = {
159
158
  state: 'failed';
160
159
  reason: string;
161
160
  };
161
+ /** One spoken word and when it is heard in the finished video, in milliseconds from its start. */
162
162
  interface TranscriptWord {
163
163
  text: string;
164
- from_ms: number;
165
- to_ms: number;
164
+ start_ms: number;
165
+ end_ms: number;
166
166
  }
167
167
  /** One video row: queued and rendering renders included. */
168
168
  interface Video {
@@ -177,7 +177,7 @@ interface Video {
177
177
  kind: RecordingKind;
178
178
  preset_name: string;
179
179
  /** The resolved recipe this video renders (or rendered) under. */
180
- preset: unknown;
180
+ preset: VideoPresetConfig;
181
181
  export: ExportPresetName;
182
182
  assets: VideoAssets;
183
183
  duration_ms: number | null;
@@ -190,7 +190,8 @@ interface Video {
190
190
  chapters: Chapter[];
191
191
  transcript: TranscriptWord[] | null;
192
192
  flags: VideoFlags | null;
193
- share: unknown | null;
193
+ /** The share link of this video ON THIS MACHINE, or nothing shared yet. */
194
+ share: ShareLinkLocal | null;
194
195
  error: string | null;
195
196
  created_at: number;
196
197
  updated_at: number;
@@ -204,8 +205,11 @@ interface Recording {
204
205
  kind: RecordingKind;
205
206
  state: RecordingState;
206
207
  title: string | null;
208
+ /** The id of the stored preset the recording was made under, `null` when it named none. */
207
209
  preset_id: string | null;
208
- preset: unknown;
210
+ /** That preset's name as it read when the recording started. */
211
+ preset_name: string | null;
212
+ preset: VideoPresetConfig;
209
213
  manifest_version: number;
210
214
  css_width: number;
211
215
  css_height: number;
@@ -299,10 +303,14 @@ interface VideoAccessGrant {
299
303
  interface VideosStorage {
300
304
  recordings_bytes: number;
301
305
  videos_bytes: number;
306
+ /** The main files of the videos this machine still shares. */
302
307
  link_bytes: number;
303
- link_limit: number;
304
- uploads_today: number;
305
- uploads_limit: number;
308
+ /** Known only to the control plane; `null` here. */
309
+ link_limit: number | null;
310
+ /** Known only to the control plane; `null` here. */
311
+ uploads_today: number | null;
312
+ /** Known only to the control plane; `null` here. */
313
+ uploads_limit: number | null;
306
314
  capacity: {
307
315
  recordings_active: number;
308
316
  recordings_max: number;
@@ -322,6 +330,18 @@ interface CodecsStatus {
322
330
  };
323
331
  /** Hardware encoders that passed a real test encode, in preference order. */
324
332
  hardware: string[];
333
+ /** Whether the hardware probe has run. Before it, an empty `hardware` means
334
+ * "not asked yet", not "none". */
335
+ probed: boolean;
336
+ /** Exports this daemon refuses whatever the order says, with the reason. An
337
+ * editor hides them rather than letting a render fail on them. */
338
+ exports_blocked: BlockedExport[];
339
+ }
340
+ /** One export the daemon refuses, e.g. `4k` while a 3840-wide capture is not
341
+ * offered. `reason` starts with its snake code. */
342
+ interface BlockedExport {
343
+ export: ExportPresetName;
344
+ reason: string;
325
345
  }
326
346
  /** What kind of file a media asset is. */
327
347
  type MediaKind = 'image' | 'music' | 'subtitle_style';
@@ -380,23 +400,23 @@ interface ShareLinkLocal {
380
400
  updated_at: number;
381
401
  error: string | null;
382
402
  }
403
+ /** `GET /v1/videos/:id/share`: the order, and the link's access code when this
404
+ * machine keeps one (sealed at rest). A link the daemon makes for a preset with
405
+ * `export.destination.passcode` gets a generated code of ten characters, and
406
+ * this is where its owner reads it. `Video.share`, `video_changed` and the
407
+ * `video` tool never carry the code. */
408
+ interface ShareStatus extends ShareLinkLocal {
409
+ /** Absent when this machine keeps no code: the link has none, or its
410
+ * revocation is ordered. */
411
+ code?: string;
412
+ }
383
413
 
384
414
  /**
385
- * Wire types: a 1:1 mirror of the daemon's serialized domain model
386
- * (`crates/core/src/model.rs`, `persona.rs`, `events.rs`) and the endpoint
387
- * contract in `docs/features/api.md`.
388
- *
389
- * THIS IS THE SOURCE, and since 2026-09-09 it is the only one on the TypeScript
390
- * side: `web-ui/src/api/types.ts` re-exports these files through the
391
- * `@scalebrowser/wire/*` alias instead of keeping a second copy (Decision 022).
392
- * Before that the same 160 declarations stood twice, and each header named the
393
- * other as the truth. The Python SDK
394
- * (`sdks/python/src/scalebrowser/models*.py`) still carries the shapes by hand,
395
- * deliberately without a gate; a TS↔pydantic comparator is its own tool.
415
+ * Wire types: a 1:1 mirror of the daemon's serialized domain model and of the
416
+ * endpoint contract, and the one source of both on the TypeScript side.
396
417
  *
397
- * These files import nothing but each other, and that is load-bearing rather
398
- * than tidy: the web-ui pulls them into a BROWSER bundle. A guard in
399
- * `web-ui/src/test/sdk-type-mirror.test.ts` holds the property.
418
+ * These files import nothing but each other, which keeps them usable inside a
419
+ * browser bundle.
400
420
  *
401
421
  * All Rust enums serialize `snake_case` (serde `rename_all`). Timestamps are
402
422
  * unix seconds (`number`, Rust `i64`). The truth for any disagreement is the
@@ -406,9 +426,6 @@ interface ShareLinkLocal {
406
426
  /** `RuntimeState` (AC-PR-004). */
407
427
  type RuntimeState = 'stopped' | 'starting' | 'running' | 'crashed';
408
428
  declare const RUNTIME_STATES: readonly RuntimeState[];
409
- /** `HostMode` (PRD §B, DEC-004). Default `linux_engine_spoof`. */
410
- type HostMode = 'linux_engine_spoof' | 'local_native_windows';
411
- declare const HOST_MODES: readonly HostMode[];
412
429
  /** `GeoMode` (AC-PX-002). Default `follow_exit`. */
413
430
  type GeoMode = 'strict_expected' | 'follow_exit' | 'off';
414
431
  declare const GEO_MODES: readonly GeoMode[];
@@ -443,7 +460,6 @@ interface Profile {
443
460
  seed: string;
444
461
  engine_version: string;
445
462
  persona: Persona;
446
- host_mode: HostMode;
447
463
  gpu_persona: string | null;
448
464
  group_id: string | null;
449
465
  proxy_id: string | null;
@@ -485,7 +501,6 @@ interface Group {
485
501
  interface PresetConfig {
486
502
  /** Pin the batch to one engine build. Omit for per-profile version diversity. */
487
503
  engine_version?: string | null;
488
- host_mode?: HostMode | null;
489
504
  geo_mode?: GeoMode | null;
490
505
  /** The geo GATE's expectation, not the persona's drawn region. */
491
506
  expected_country?: string | null;
@@ -603,7 +618,8 @@ interface VideoPresetConfig {
603
618
  voice: string | null;
604
619
  language: string;
605
620
  subtitles: 'burned' | 'file' | 'off';
606
- subtitle_style: string;
621
+ /** `custom:<media_id>` names an uploaded font (media kind `subtitle_style`). */
622
+ subtitle_style: 'classic' | 'word' | `custom:${string}`;
607
623
  page_audio: boolean;
608
624
  music: MusicBed | null;
609
625
  };
@@ -839,8 +855,9 @@ interface SessionImportBody {
839
855
  }
840
856
  /**
841
857
  * Trusted-input payload (`POST /v1/profiles/:id/input`, G8, AC-API-003). Only
842
- * `action` and `humanize` are fixed by `docs/features/api.md`; the per-action coordinate
843
- * fields below are the SDK's contract assumption for the daemon's input crate.
858
+ * `action` and `humanize` are fixed by the API contract; the per-action
859
+ * coordinate fields below are the SDK's assumption about the daemon's input
860
+ * layer.
844
861
  */
845
862
  type TrustedInputBody = {
846
863
  action: 'move';
@@ -948,8 +965,7 @@ interface ExitStatus {
948
965
  /**
949
966
  * The per-profile task list and the profile's own durable memory.
950
967
  *
951
- * One of the files that ARE the contract; the web-ui reads them through
952
- * `@scalebrowser/wire/*` rather than keeping a copy (Decision 022).
968
+ * One of the files that are the daemon's wire contract.
953
969
  */
954
970
  /**
955
971
  * Where a task stands.
@@ -1228,13 +1244,6 @@ type StreamedEvent = LifecycleEvent & {
1228
1244
  * the browser `EventSource` cannot do that) and reconnect with backoff. A
1229
1245
  * `/v1/ws` websocket carries the same events; SSE is sufficient for one-way
1230
1246
  * fan-out.
1231
- *
1232
- * Mirrors `web-ui/src/api/events.ts` line for line, deliberately: this package
1233
- * ships to npm and should carry no dependency it does not need, so a shared
1234
- * package would cost more than the copy does. The copy pays for itself with a
1235
- * gate instead: `scripts/verify-mirrored-values.mjs` holds `MAX_BACKOFF_MS` and
1236
- * the backoff line itself against the other side. Two clients of the same daemon
1237
- * that come back at different speeds would be a decision nobody made.
1238
1247
  */
1239
1248
 
1240
1249
  /** Injectable `fetch`; defaults to the global at call time. */
@@ -1278,8 +1287,7 @@ declare function eventStream(params: StreamParams): AsyncIterableIterator<Lifecy
1278
1287
  * What the browser asks (interruptions), the bytes that go in and out
1279
1288
  * (artifacts), and what the licence says (account).
1280
1289
  *
1281
- * One of the files that ARE the contract; the web-ui reads them through
1282
- * `@scalebrowser/wire/*` rather than keeping a copy (Decision 022).
1290
+ * One of the files that are the daemon's wire contract.
1283
1291
  */
1284
1292
  /** What an operator has taken out of an agent's hands. */
1285
1293
  type InterruptionLock = 'always_block' | 'always_allow' | 'agent_decides';
@@ -1542,6 +1550,24 @@ interface ProfileIdsResult {
1542
1550
  count: number;
1543
1551
  ids: string[];
1544
1552
  }
1553
+ /**
1554
+ * `GET /v1/profiles/count`: how many profiles match, split by runtime state.
1555
+ *
1556
+ * `total` counts ROWS, so it is the sum of the four states for every state this
1557
+ * daemon can read; a row in a state a newer build introduced counts in `total`
1558
+ * alone rather than being folded into `stopped`.
1559
+ *
1560
+ * The `state` filter is the one this route ignores. A caller labelling all four
1561
+ * scopes is sitting in one of them, so narrowing by it would answer the other
1562
+ * three with zero. Every other filter binds exactly as it does for the listing.
1563
+ */
1564
+ interface ProfileCounts {
1565
+ total: number;
1566
+ stopped: number;
1567
+ starting: number;
1568
+ running: number;
1569
+ crashed: number;
1570
+ }
1545
1571
  /** `POST /v1/bulk/start`: per-id results plus what the batch as a whole did. */
1546
1572
  interface BulkStartResult {
1547
1573
  results: {
@@ -1566,7 +1592,6 @@ interface ListProfilesParams {
1566
1592
  interface CreateProfileBody {
1567
1593
  name: string;
1568
1594
  seed?: string;
1569
- host_mode?: HostMode;
1570
1595
  geo_mode?: GeoMode;
1571
1596
  expected_country?: string | null;
1572
1597
  /**
@@ -1588,11 +1613,11 @@ interface CreateProfileBody {
1588
1613
  proxy_id?: string | null;
1589
1614
  }
1590
1615
  /**
1591
- * PATCH, all mutable fields optional. `host_mode` and `seed` are fixed at create
1592
- * time (C4/C5): a DIFFERING `host_mode` is refused with 400, an unchanged echo is
1593
- * accepted. Changing a tier requires delete + recreate.
1616
+ * PATCH, all mutable fields optional. `seed` and `persona_country` are fixed at
1617
+ * create time (C5): they draw the identity, and redrawing it under a profile that
1618
+ * has already been used would be a new identity in an old profile's clothes.
1594
1619
  */
1595
- type UpdateProfileBody = Omit<Partial<CreateProfileBody>, "host_mode" | "seed" | "persona_country"> & {
1620
+ type UpdateProfileBody = Omit<Partial<CreateProfileBody>, "seed" | "persona_country"> & {
1596
1621
  /**
1597
1622
  * Turn the exit-address rule off for this profile (DEC-017). Deliberately not
1598
1623
  * part of `CreateProfileBody`: a new profile always claims its address, and
@@ -1790,8 +1815,7 @@ declare class ExtensionsApi extends ClientCore {
1790
1815
  * The account layer: mailboxes, passkeys and the one door a cookie value leaves
1791
1816
  * through.
1792
1817
  *
1793
- * One of the files that ARE the contract; the web-ui reads them through
1794
- * `@scalebrowser/wire/*` rather than keeping a copy (Decision 022). The cookie
1818
+ * One of the files that are the daemon's wire contract. The cookie
1795
1819
  * reveal has no UI counterpart: it is a REST-only route deliberately kept off
1796
1820
  * every screen.
1797
1821
  */
@@ -2196,8 +2220,7 @@ declare class TasksApi extends ClientCore {
2196
2220
  * the live event stream carries them, and the run list describes the same rows.
2197
2221
  * A second copy would let the two drift apart while both looked right.
2198
2222
  *
2199
- * One of the files that ARE the contract; the web-ui reads them through
2200
- * `@scalebrowser/wire/*` rather than keeping a copy (Decision 022).
2223
+ * One of the files that are the daemon's wire contract.
2201
2224
  */
2202
2225
 
2203
2226
  /** Who made the outcome claim. `derived` means nobody did. */
@@ -2317,7 +2340,7 @@ declare class VideosApi extends ClientCore {
2317
2340
  * whether the link still lives is read from the control plane, not from
2318
2341
  * here: a number carried along would be wrong the moment another machine
2319
2342
  * revoked. */
2320
- shareStatus(videoId: string, signal?: AbortSignal): Promise<ShareLinkLocal>;
2343
+ shareStatus(videoId: string, signal?: AbortSignal): Promise<ShareStatus>;
2321
2344
  /** Revoke the link. The files fall at once; the order stays until the control
2322
2345
  * plane confirms. */
2323
2346
  revokeShare(videoId: string, signal?: AbortSignal): Promise<void>;
@@ -2549,7 +2572,7 @@ interface Metrics {
2549
2572
  * (shapes), nowhere else.
2550
2573
  */
2551
2574
 
2552
- /** Mirrors `CapacityConfig::default()` (`crates/core/src/config.rs`). */
2575
+ /** The daemon's own default capacity limits. */
2553
2576
  declare const DEFAULT_CAPACITY: {
2554
2577
  max_concurrent: number;
2555
2578
  ram_budget_mb: number;
@@ -2577,6 +2600,18 @@ declare class ScalebrowserClient extends ClientCore {
2577
2600
  * page you fetched. Asking for ids costs one request and no persona payloads.
2578
2601
  */
2579
2602
  listProfileIds(params?: ListProfilesParams, signal?: AbortSignal): Promise<ProfileIdsResult>;
2603
+ /**
2604
+ * How many profiles match `params`, split by runtime state. One request, and
2605
+ * its size does not grow with the fleet.
2606
+ *
2607
+ * `listProfiles` is paged and answers a bare array, so counting what came back
2608
+ * counts the page. `listProfileIds` carries the same total but ships an
2609
+ * identifier per profile to do it, and cannot split by state at all.
2610
+ *
2611
+ * `params.state` is ignored here on purpose: a caller labelling every state is
2612
+ * sitting in one of them.
2613
+ */
2614
+ countProfiles(params?: ListProfilesParams, signal?: AbortSignal): Promise<ProfileCounts>;
2580
2615
  getProfile(id: string, signal?: AbortSignal): Promise<Profile>;
2581
2616
  createProfile(body: CreateProfileBody): Promise<Profile>;
2582
2617
  updateProfile(id: string, body: UpdateProfileBody): Promise<Profile>;
@@ -2731,8 +2766,8 @@ interface ScalebrowserClient extends IdentityApi, RunsApi, VideosApi, ControlApi
2731
2766
  }
2732
2767
 
2733
2768
  /**
2734
- * Error model: stable numeric API error codes (SPEC §5,
2735
- * `crates/core/src/error.rs`) and the typed exceptions the SDK throws.
2769
+ * Error model: the stable numeric API error codes and the typed exceptions
2770
+ * the SDK throws.
2736
2771
  */
2737
2772
  /** Stable numeric API error codes (4001–4013, append-only: a retired code stays
2738
2773
  * reserved rather than being reused). */
@@ -2769,7 +2804,7 @@ declare const ErrorCode: {
2769
2804
  readonly ExitAddressTaken: 4013;
2770
2805
  };
2771
2806
  type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode];
2772
- /** Error body shape: `{ code, message }` (docs/features/api.md). */
2807
+ /** Error body shape: `{ code, message }`. */
2773
2808
  interface ApiErrorBody {
2774
2809
  code?: number;
2775
2810
  message?: string;
@@ -2824,6 +2859,6 @@ declare function errorMessage(err: unknown): string;
2824
2859
  * ```
2825
2860
  */
2826
2861
 
2827
- declare const VERSION = "0.7.0";
2862
+ declare const VERSION = "0.8.1";
2828
2863
 
2829
- 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 Connection, type CreateGroupBody, type CreateInboxBody, type CreatePresetBody, type CreateTasksBody, type CreateTasksResult, DEFAULT_CAPACITY, type DeleteInterruptionRuleParams, type EffectiveInterruptionLock, ErrorCode, type ErrorCodeValue, type EvaluateOptions, type ExitClaim, type ExitRuleStatus, 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, type ProxyRow, type ProxyUsage, 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 };
2864
+ 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 BlockedExport, type CdpConnectOptions, CdpError, type CdpEvent, CdpSession, type Chapter, type ClickOptions, type CodecsStatus, type Connection, type CreateGroupBody, type CreateInboxBody, type CreatePresetBody, type CreateTasksBody, type CreateTasksResult, DEFAULT_CAPACITY, type DeleteInterruptionRuleParams, type EffectiveInterruptionLock, ErrorCode, type ErrorCodeValue, type EvaluateOptions, type ExitClaim, type ExitRuleStatus, type ExitScope, type ExitStatus, type ExportPresetName, type ExtraOutput, type FetchLike, GEO_MODES, type GeoMode, type GoalSource, type Group, type HealthStatus, 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, type ProxyRow, type ProxyUsage, 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 ShareStatus, 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 };
package/dist/index.js CHANGED
@@ -1380,6 +1380,23 @@ var ScalebrowserClient = class extends ClientCore {
1380
1380
  signal
1381
1381
  });
1382
1382
  }
1383
+ /**
1384
+ * How many profiles match `params`, split by runtime state. One request, and
1385
+ * its size does not grow with the fleet.
1386
+ *
1387
+ * `listProfiles` is paged and answers a bare array, so counting what came back
1388
+ * counts the page. `listProfileIds` carries the same total but ships an
1389
+ * identifier per profile to do it, and cannot split by state at all.
1390
+ *
1391
+ * `params.state` is ignored here on purpose: a caller labelling every state is
1392
+ * sitting in one of them.
1393
+ */
1394
+ countProfiles(params = {}, signal) {
1395
+ return this.request("GET", "/v1/profiles/count", void 0, {
1396
+ query: { group: params.group, q: params.q },
1397
+ signal
1398
+ });
1399
+ }
1383
1400
  getProfile(id, signal) {
1384
1401
  return this.request("GET", `/v1/profiles/${enc(id)}`, void 0, { signal });
1385
1402
  }
@@ -1710,12 +1727,11 @@ applyMixins(ScalebrowserClient, [
1710
1727
 
1711
1728
  // src/types.ts
1712
1729
  var RUNTIME_STATES = ["stopped", "starting", "running", "crashed"];
1713
- var HOST_MODES = ["linux_engine_spoof", "local_native_windows"];
1714
1730
  var GEO_MODES = ["strict_expected", "follow_exit", "off"];
1715
1731
  var PROXY_KINDS = ["http", "socks5", "gateway"];
1716
1732
  var ROTATIONS = ["sticky", "rotating"];
1717
1733
 
1718
1734
  // src/index.ts
1719
- var VERSION = "0.7.0";
1735
+ var VERSION = "0.8.1";
1720
1736
 
1721
- export { ApiError, CdpError, CdpSession, DEFAULT_CAPACITY, ErrorCode, GEO_MODES, HOST_MODES, NetworkError, PROXY_KINDS, ROTATIONS, RUNTIME_STATES, ScalebrowserClient, ScalebrowserError, VERSION, deriveMetricsFromProfiles, errorMessage, eventStream, openCdpSession, parseSseFrame, subscribeEvents };
1737
+ export { ApiError, CdpError, CdpSession, DEFAULT_CAPACITY, ErrorCode, GEO_MODES, NetworkError, PROXY_KINDS, ROTATIONS, RUNTIME_STATES, ScalebrowserClient, ScalebrowserError, VERSION, deriveMetricsFromProfiles, errorMessage, eventStream, openCdpSession, parseSseFrame, subscribeEvents };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@scalebrowser/sdk",
3
- "version": "0.7.0",
4
- "description": "Official Node/TypeScript SDK for the Scalebrowser daemon — typed REST client + direct-CDP driver plane (nodriver-style, not Playwright).",
3
+ "version": "0.8.1",
4
+ "description": "Official Node/TypeScript SDK for the Scalebrowser daemon: typed REST client plus a direct-CDP driver plane (nodriver-style, not Playwright).",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "homepage": "https://scalebrowser.net",
@@ -36,6 +36,7 @@
36
36
  },
37
37
  "files": [
38
38
  "dist",
39
+ "CHANGELOG.md",
39
40
  "README.md",
40
41
  "LICENSE"
41
42
  ],
@@ -45,7 +46,6 @@
45
46
  "test": "vitest run",
46
47
  "test:watch": "vitest",
47
48
  "prepare": "npm run build",
48
- "smoke": "node ../scripts/smoke-node.mjs",
49
49
  "lint": "eslint src test examples",
50
50
  "test:coverage": "vitest run --coverage"
51
51
  },