@vosjs/render-core 0.8.0 → 0.9.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.
@@ -1,4 +1,5 @@
1
- import { RecordingMeta, CursorEvent, RecordingSkip, RecordingOutput, Backdrop, RecordingArtifact, ProjectDoc, RecordingPageMedia } from '@vosjs/studio-core';
1
+ import { RecordingMeta, PeerStepSpan, CursorEvent, RecordingSkip, RecordingOutput, Backdrop, RecordingArtifact, ProjectDoc, RecordingPageMedia } from '@vosjs/studio-core';
2
+ export { PeerStepSpan } from '@vosjs/studio-core';
2
3
 
3
4
  /**
4
5
  * The recorder's driver: what it needs from a browser, as a STRUCTURAL
@@ -872,6 +873,278 @@ declare function overrunOf(plannedMs: number, tookMs: number): number | null;
872
873
  /** The overruns in one line for the log and the done event, or null when none. */
873
874
  declare function overrunLine(overruns: readonly StepOverrun[]): string | null;
874
875
 
876
+ /**
877
+ * What an `expect` and an `await` wait for: a condition on the page, read
878
+ * without touching it (no cursor, no input), polled until it holds or the
879
+ * time runs out. `expect` polls on camera for a few seconds; `await` polls
880
+ * off camera for as long as a slow result takes. One reader for both, so
881
+ * "appeared" means the same thing in either.
882
+ */
883
+
884
+ interface WaitCondition {
885
+ /** an element matching this selector is visible */
886
+ selector?: string;
887
+ /** some visible text on the page contains this */
888
+ text?: string;
889
+ /** no element matching this selector is visible */
890
+ gone?: string;
891
+ /** with `selector`: the element is enabled (true) or disabled (false) */
892
+ enabled?: boolean;
893
+ /**
894
+ * A JavaScript expression evaluated in the page (awaited when it answers
895
+ * a promise): the condition holds when its value is truthy, or, with
896
+ * `equals`, when its value equals that one. For an app that keeps its
897
+ * state in script rather than in the DOM (a canvas, a document model).
898
+ */
899
+ js?: string;
900
+ /** with `js`: the value the expression must equal (compared as JSON) */
901
+ equals?: unknown;
902
+ }
903
+ /** What the condition found the last time it looked: what a miss is said from. */
904
+ interface ConditionState {
905
+ holds: boolean;
906
+ /** with `selector`: whether a match was visible */
907
+ visible?: boolean;
908
+ /**
909
+ * with `js`: what the expression answered the last time it was read, as
910
+ * JSON when it has a JSON form (absent for `undefined`), and in words
911
+ * either way (`said`), or the error it threw (`threw`).
912
+ */
913
+ value?: unknown;
914
+ said?: string;
915
+ threw?: string;
916
+ }
917
+ /**
918
+ * The visible text of the page contains `text`: `innerText` is what the
919
+ * page renders, so a hidden element's words never count.
920
+ */
921
+ declare function visibleTextScript(text: string): string;
922
+ /** The longest a js value is said in a line, in characters. */
923
+ declare const JS_SAID_MAX = 120;
924
+ /** The most a js value kept on the step holds, in characters of JSON. */
925
+ declare const JS_VALUE_MAX = 2048;
926
+ /**
927
+ * The page script that evaluates a step's expression and answers what it
928
+ * found, as a string (the one evaluate shape every driver shares). The
929
+ * expression is the script author's own, run on their own page: it is
930
+ * wrapped, never parsed, and a newline closes it before the paren so a
931
+ * trailing line comment cannot swallow the wrapper.
932
+ */
933
+ declare function jsConditionScript(expr: string): string;
934
+ /** Two JSON values alike: the same keys and values whatever the key order. */
935
+ declare function sameJson(a: unknown, b: unknown): boolean;
936
+ /**
937
+ * A js value as a step keeps it (`meta.steps[].value`): the value itself
938
+ * while its JSON fits, else its JSON cut short as a string.
939
+ */
940
+ declare function keptValue(value: unknown): unknown;
941
+ /** Read the condition once. A page mid-navigation reads as "not yet". */
942
+ declare function readCondition(page: RecorderPage, c: WaitCondition): Promise<ConditionState>;
943
+ /** What a poll found: whether the condition held, after how long, and the last read. */
944
+ interface PollResult {
945
+ ok: boolean;
946
+ ms: number;
947
+ last: ConditionState;
948
+ }
949
+ /**
950
+ * Poll the condition every `everyMs` until it holds or `timeoutMs` pass.
951
+ * `between` runs before each look but the first (an `await`'s reload).
952
+ * With `confirm`, a hold counts only once it has held on that many reads
953
+ * in a row, `confirm.gapMs` apart: a page that renders after network quiet
954
+ * reads half-built for a moment, and a `gone` condition holds on a list
955
+ * that has not been drawn yet. The clock is the wall's: a rehearsal waits
956
+ * as long as a take would, because how long a result takes is what a
957
+ * rehearsal is for.
958
+ */
959
+ declare function pollCondition(page: RecorderPage, c: WaitCondition, opts: {
960
+ timeoutMs: number;
961
+ everyMs: number;
962
+ sleep: (ms: number) => Promise<void>;
963
+ now?: () => number;
964
+ between?: () => Promise<void>;
965
+ confirm?: {
966
+ reads: number;
967
+ gapMs: number;
968
+ };
969
+ }): Promise<PollResult>;
970
+ /** The DOM counts as settled after this long with no change. */
971
+ declare const DOM_QUIET_MS = 800;
972
+ /** The longest a settle waits on a page that never stops changing. */
973
+ declare const DOM_SETTLE_CAP_MS = 5000;
974
+ /**
975
+ * The page's own count of DOM changes: an observer installed once per
976
+ * document, read back as a number. A string, the one evaluate shape every
977
+ * driver shares.
978
+ */
979
+ declare const DOM_CHANGE_PROBE = "(() => {\n if (!window.__vosDomChanges) {\n window.__vosDomChanges = { n: 0 };\n new MutationObserver((list) => { window.__vosDomChanges.n += list.length })\n .observe(document, { subtree: true, childList: true, attributes: true, characterData: true });\n }\n return window.__vosDomChanges.n;\n})()";
980
+ /**
981
+ * Wait until the DOM has not changed for `quietMs`, at most `capMs`: what
982
+ * a page does after its network went quiet (a list rendered from data, a
983
+ * hydration). The count is polled from here rather than timed in the
984
+ * page, because a background tab throttles its own timers.
985
+ */
986
+ declare function domSettled(page: RecorderPage, opts: {
987
+ sleep: (ms: number) => Promise<void>;
988
+ now?: () => number;
989
+ quietMs?: number;
990
+ capMs?: number;
991
+ tickMs?: number;
992
+ }): Promise<{
993
+ settled: boolean;
994
+ ms: number;
995
+ }>;
996
+ /** Seconds as the recorder says them: `5 s`, `2.5 s`, `3 min 20 s`. */
997
+ declare function sayDuration(ms: number): string;
998
+ /** What the condition waits for, in words: `'#result' to appear`. */
999
+ declare function sayCondition(c: WaitCondition): string;
1000
+ /** Why the condition did not hold, in words: `'Generate' stayed disabled for 5 s`. */
1001
+ declare function conditionMiss(c: WaitCondition, last: ConditionState, ms: number): string;
1002
+ /** An expression as a line names it: in backticks, cut short. */
1003
+ declare function sayJs(expr: string): string;
1004
+ /** A kept value as a line says it: its JSON, cut short. */
1005
+ declare function sayValue(value: unknown): string;
1006
+
1007
+ /**
1008
+ * `peers`: other people on the same page, off camera. A collaboration
1009
+ * product shows best with a second person on the canvas: their cursor, the
1010
+ * shape they drew, the comment they left, arriving in the filmed page the
1011
+ * way the app syncs them. A peer is a second browser context (its own
1012
+ * cookies, so its own user, from its own storage state or none) on the
1013
+ * same URL, driven by its own step list, interleaved with the take's.
1014
+ *
1015
+ * What a peer is, and is not:
1016
+ *
1017
+ * - NOT FILMED. Only the take's own page is captured. A peer's page is
1018
+ * never screencast, scanned, masked or listened to; what it does reaches
1019
+ * the footage only through the app (its sync, its presence, its remote
1020
+ * cursors), which is what a viewer would see.
1021
+ * - NOT ON THE CURSOR TRACK. A peer's pointer moves its own page; the take's
1022
+ * CursorTrack is synthesized from the take's own steps alone, so a zoom,
1023
+ * a click ring or a dwell is never planned on a peer's gesture.
1024
+ * - ORDERED BY THE TAKE'S STEPS. A peer step may name a take step by id:
1025
+ * `with` starts it as that step starts (the two run together), `after` as
1026
+ * that step ends. A step naming neither follows the peer's previous step
1027
+ * at once; a peer's first step with neither starts as the camera rolls.
1028
+ * The take never waits on a peer: it waits on what the peer's work
1029
+ * SHOWS, with an `expect` or an `await` on its own page, so the footage
1030
+ * holds exactly the moment the sync landed. When the take's steps end,
1031
+ * a peer step still waiting on a trigger never runs (said), and one
1032
+ * already running finishes, bounded, before the trailing hold.
1033
+ * - PACED, NOT INSTANT. A peer's pointer glides on the same clock as the
1034
+ * take's (an app that draws remote cursors shows it travelling) and its
1035
+ * typing is paced per key, so what it does reads as a person.
1036
+ * - BOUNDED. Every peer step runs inside its own bound, as a take step
1037
+ * does; a selector that never appears or a check that never holds is a
1038
+ * skip with its reason, listed with the take's (`--strict` fails on it).
1039
+ *
1040
+ * A peer takes the take's gestures and checks (`wait`, `move`, `hover`,
1041
+ * `click`, `type`, `press`, `scroll`, `drag` with an inline `path`, and
1042
+ * `expect`), never a `paste`, a `download`, an `await` (a peer that must
1043
+ * wait for a result is the take's `await`), a guard, a `read`, a `caption`
1044
+ * or `settle`, which all belong to the filmed page.
1045
+ */
1046
+
1047
+ /** One other person on the page: their own context, their own steps. */
1048
+ interface Peer {
1049
+ /** How the peer is named in lines and in `meta.peers`: a short word. */
1050
+ id: string;
1051
+ /** The page the peer opens; absent, the take's own `url`. */
1052
+ url?: string;
1053
+ /** The peer's viewport in CSS px; absent, the take's. */
1054
+ viewport?: {
1055
+ width: number;
1056
+ height: number;
1057
+ };
1058
+ /**
1059
+ * A Playwright storage state the peer's context is made from: the second
1060
+ * person's own sign-in. The host resolves the name (the CLI: a path from
1061
+ * the actions file's directory) and never sends the file anywhere.
1062
+ * Absent, the peer is signed out.
1063
+ */
1064
+ storageState?: string;
1065
+ steps: PeerStep[];
1066
+ }
1067
+ /** A peer's step: one of the take's gestures or checks, and when it starts. */
1068
+ type PeerStep = ActionStep & {
1069
+ /**
1070
+ * Start as the take's step with this id starts: the two run together.
1071
+ * (`with`, never `at`: a `type` step's `at` is where its caret goes.)
1072
+ */
1073
+ with?: string;
1074
+ /** Start as the take's step with this id ends. */
1075
+ after?: string;
1076
+ };
1077
+ /** The verbs a peer takes: the gestures and the on-page check. */
1078
+ declare const PEER_VERBS: readonly ["wait", "move", "hover", "click", "type", "press", "scroll", "drag", "expect"];
1079
+ /** The most peers a take may have: each is a whole browser context. */
1080
+ declare const MAX_PEERS = 4;
1081
+ /** The most steps one peer may take. */
1082
+ declare const MAX_PEER_STEPS = 200;
1083
+ /**
1084
+ * Structural validation of `peers`, given the take's own steps (a trigger
1085
+ * names one of their ids). `validate` is the take's step validator, run on
1086
+ * each peer's list so a peer step is checked in exactly the take's words.
1087
+ */
1088
+ declare function validatePeers(value: unknown, takeSteps: unknown, validate: (steps: unknown[]) => string[]): string[];
1089
+ /** What a hosted recorder says of a script with peers, or null. */
1090
+ declare function peersHostedRefusal(peers: unknown): string | null;
1091
+ /**
1092
+ * The take's step boundaries, as promises a peer step waits on. The take
1093
+ * calls `begin` as the camera rolls, `start`/`end` around each step and
1094
+ * `close` once its steps are over; a trigger still pending then resolves
1095
+ * false and its step never runs.
1096
+ */
1097
+ declare class StepSignals {
1098
+ private readonly started;
1099
+ private readonly ended;
1100
+ private readonly began;
1101
+ private closed;
1102
+ constructor(ids: Iterable<string>);
1103
+ begin(): void;
1104
+ start(id: string | undefined): void;
1105
+ end(id: string | undefined): void;
1106
+ close(): void;
1107
+ get isClosed(): boolean;
1108
+ /** When a step with this trigger may start: true, or false for never. */
1109
+ when(trigger: {
1110
+ with?: string;
1111
+ after?: string;
1112
+ }): {
1113
+ ready: Promise<boolean>;
1114
+ already: boolean;
1115
+ };
1116
+ }
1117
+
1118
+ /** The most a peer step's kept value holds, in characters of JSON (as a take step's). */
1119
+ declare const PEER_VALUE_MAX = 2048;
1120
+ /**
1121
+ * What a peer's check last answered, kept on its step the way the take's
1122
+ * own steps keep theirs (`meta.steps[].value`): the value itself while its
1123
+ * JSON fits, else that JSON cut short as a string; absent when the read
1124
+ * answered nothing JSON can hold, or no value at all (a check that only
1125
+ * holds or not).
1126
+ */
1127
+ declare function peerValue(last: ConditionState): unknown;
1128
+ /** What a peer did: its steps as they ran, and the ones that never did. */
1129
+ interface PeerRun {
1130
+ id: string;
1131
+ steps: PeerStepSpan[];
1132
+ /** Steps whose trigger never fired before the take's steps were over. */
1133
+ notRun: number[];
1134
+ }
1135
+ /**
1136
+ * Drive one peer's steps on its page, each when its trigger fires. Never
1137
+ * throws for a page's reasons: a miss is a skip on the run.
1138
+ */
1139
+ declare function runPeer(peer: Peer, rawPage: RecorderPage, signals: StepSignals, opts: {
1140
+ clock: RecorderClock;
1141
+ /** The take's footage clock, ms: what a span is placed by. */
1142
+ footageMs: () => number;
1143
+ log: (msg: string) => void;
1144
+ /** A rehearsal: no travel, every pause cut short. */
1145
+ dry?: boolean;
1146
+ }): Promise<PeerRun>;
1147
+
875
1148
  /**
876
1149
  * The action script — the declarative recipe an agent (or human) writes to
877
1150
  * drive a take. Small on purpose: selectors + a handful of verbs. The recorder
@@ -917,6 +1190,15 @@ interface ActionsFile {
917
1190
  */
918
1191
  settle?: boolean;
919
1192
  steps: ActionStep[];
1193
+ /**
1194
+ * Other people on the page, OFF CAMERA: each a browser context of its
1195
+ * own (its own storage state, so its own user) on the same `url`, driven
1196
+ * by its own steps, each started `with` a take step or `after` one (by
1197
+ * id). Only the take's page is filmed, and only its own steps make the
1198
+ * cursor track; a peer's work reaches the footage through the app's own
1199
+ * sync. A hosted take refuses peers.
1200
+ */
1201
+ peers?: Peer[];
920
1202
  }
921
1203
  type ActionStep = ({
922
1204
  do: 'wait';
@@ -1037,9 +1319,12 @@ type ActionStep = ({
1037
1319
  /**
1038
1320
  * Check that the page is as the flow expects, with no cursor move: an
1039
1321
  * element visible (`selector`; with `enabled`, enabled or disabled), some
1040
- * visible text containing `text`, or `gone` no longer visible. Exactly
1041
- * one of the three. Waits up to `timeout` seconds (default 5); a
1042
- * condition that never holds is a skip with its reason.
1322
+ * visible text containing `text`, `gone` no longer visible, or `js`, an
1323
+ * expression evaluated in the page that holds when its value is truthy
1324
+ * (with `equals`, when its value equals that one): the state a canvas
1325
+ * app keeps in script, never in the DOM. Exactly one of the four. Waits
1326
+ * up to `timeout` seconds (default 5); a condition that never holds is a
1327
+ * skip with its reason, which names the value a `js` last answered.
1043
1328
  */
1044
1329
  | {
1045
1330
  do: 'expect';
@@ -1047,6 +1332,8 @@ type ActionStep = ({
1047
1332
  text?: string;
1048
1333
  gone?: string;
1049
1334
  enabled?: boolean;
1335
+ js?: string;
1336
+ equals?: unknown;
1050
1337
  timeout?: number;
1051
1338
  }
1052
1339
  /**
@@ -1099,6 +1386,15 @@ type ActionStep = ({
1099
1386
  * `vos actions script` leads the beat with it.
1100
1387
  */
1101
1388
  caption?: string;
1389
+ /**
1390
+ * The cut's camera on this step: `true` marks the step as its beat's
1391
+ * payoff, the moment worth the zoom (`vos plan --zooms per-beat` keeps
1392
+ * the proposal on it, and only it); `false` means never zoom here (the
1393
+ * planner's proposal on it is rejected). The planner still decides the
1394
+ * level and the focus; a mark never invents a zoom. On a gesture only
1395
+ * (ZOOM_MARK_VERBS).
1396
+ */
1397
+ zoom?: boolean;
1102
1398
  /**
1103
1399
  * A selector whose words the recorder keeps once the step has settled
1104
1400
  * (`meta.steps[].text`: trimmed, whitespace collapsed, at most 2 KB), so
@@ -1116,15 +1412,19 @@ type ActionStep = ({
1116
1412
  */
1117
1413
  settle?: boolean;
1118
1414
  };
1119
- /** What an `await` waits for: exactly one of the three. */
1415
+ /** What an `await` waits for: exactly one of the four (`equals` rides with `js`). */
1120
1416
  interface AwaitUntil {
1121
1417
  selector?: string;
1122
1418
  text?: string;
1123
1419
  gone?: string;
1420
+ js?: string;
1421
+ equals?: unknown;
1124
1422
  }
1125
1423
  /** The guards a step may carry: one today, a step that spends. */
1126
1424
  declare const STEP_GUARDS: readonly ["spend"];
1127
1425
  type StepGuard = (typeof STEP_GUARDS)[number];
1426
+ /** The verbs a `zoom` mark may sit on: the gestures a camera can be about. */
1427
+ declare const ZOOM_MARK_VERBS: readonly string[];
1128
1428
  /** How long an `expect` waits by default, in seconds. */
1129
1429
  declare const EXPECT_TIMEOUT_S = 5;
1130
1430
  /** An `await`'s defaults, in seconds. */
@@ -1168,10 +1468,11 @@ declare function guardVerdict(actions: Pick<ActionsFile, 'steps'>, confirm: read
1168
1468
  };
1169
1469
  /**
1170
1470
  * What a hosted recorder cannot do with a script, in words, or []: a
1171
- * guarded step has nobody to confirm it on a fleet, and a download has no
1172
- * take directory to land in there.
1471
+ * guarded step has nobody to confirm it on a fleet, a download has no
1472
+ * take directory to land in there, and a `js` check is code a stranger's
1473
+ * script would run in the fleet's browser.
1173
1474
  */
1174
- declare function hostedRefusals(actions: Pick<ActionsFile, 'steps'>): string[];
1475
+ declare function hostedRefusals(actions: Pick<ActionsFile, 'steps' | 'peers'>): string[];
1175
1476
  /**
1176
1477
  * The files a script names beside itself, in order: a drag's path file
1177
1478
  * and a paste's file. A host reads them before anything is captured.
@@ -1293,6 +1594,8 @@ interface SkippedStep {
1293
1594
  selector: string;
1294
1595
  /** why, when it is not a selector that never appeared: an expect that never held, a download that never came */
1295
1596
  reason?: string;
1597
+ /** A PEER's step (`peers[].id`): `step` is then an index into that peer's steps. */
1598
+ peer?: string;
1296
1599
  }
1297
1600
  /** A click whose target was disabled when it was pressed: the press happened, and likely did nothing. */
1298
1601
  interface DisabledClick {
@@ -1378,6 +1681,8 @@ interface RecordResult {
1378
1681
  overruns: StepOverrun[];
1379
1682
  /** The actions as recorded, `url` resolved: what a take directory writes back. */
1380
1683
  actions: ActionsFile;
1684
+ /** What each peer did, off camera (also `meta.peers`); [] with none. */
1685
+ peers: PeerRun[];
1381
1686
  }
1382
1687
  interface RecordOpts {
1383
1688
  /** Stop the capture at this many seconds (the hosted cap). */
@@ -1462,6 +1767,14 @@ interface RecordOpts {
1462
1767
  stopOnHang?: boolean;
1463
1768
  /** How often a long `await` reports it is still waiting (default 30 s). */
1464
1769
  awaitHeartbeatMs?: number;
1770
+ /**
1771
+ * Where a peer's `storageState` is read from: the CLI resolves the name
1772
+ * from the actions file's directory to a path the browser opens, and
1773
+ * throws in words when there is none. A host that hands in none cannot
1774
+ * sign a peer in, and such a script is refused before anything is
1775
+ * captured.
1776
+ */
1777
+ peerStorageState?: (name: string) => Promise<string> | string;
1465
1778
  }
1466
1779
  /**
1467
1780
  * The expression a scroll tick evaluates: move the first scrollable
@@ -1567,97 +1880,6 @@ declare function splitSegmentsAtSkips(segments: ProjectDoc['segments'], skips: r
1567
1880
  at: number;
1568
1881
  }[] | undefined): ProjectDoc['segments'];
1569
1882
 
1570
- /**
1571
- * What an `expect` and an `await` wait for: a condition on the page, read
1572
- * without touching it (no cursor, no input), polled until it holds or the
1573
- * time runs out. `expect` polls on camera for a few seconds; `await` polls
1574
- * off camera for as long as a slow result takes. One reader for both, so
1575
- * "appeared" means the same thing in either.
1576
- */
1577
-
1578
- interface WaitCondition {
1579
- /** an element matching this selector is visible */
1580
- selector?: string;
1581
- /** some visible text on the page contains this */
1582
- text?: string;
1583
- /** no element matching this selector is visible */
1584
- gone?: string;
1585
- /** with `selector`: the element is enabled (true) or disabled (false) */
1586
- enabled?: boolean;
1587
- }
1588
- /** What the condition found the last time it looked: what a miss is said from. */
1589
- interface ConditionState {
1590
- holds: boolean;
1591
- /** with `selector`: whether a match was visible */
1592
- visible?: boolean;
1593
- }
1594
- /**
1595
- * The visible text of the page contains `text`: `innerText` is what the
1596
- * page renders, so a hidden element's words never count.
1597
- */
1598
- declare function visibleTextScript(text: string): string;
1599
- /** Read the condition once. A page mid-navigation reads as "not yet". */
1600
- declare function readCondition(page: RecorderPage, c: WaitCondition): Promise<ConditionState>;
1601
- /** What a poll found: whether the condition held, after how long, and the last read. */
1602
- interface PollResult {
1603
- ok: boolean;
1604
- ms: number;
1605
- last: ConditionState;
1606
- }
1607
- /**
1608
- * Poll the condition every `everyMs` until it holds or `timeoutMs` pass.
1609
- * `between` runs before each look but the first (an `await`'s reload).
1610
- * With `confirm`, a hold counts only once it has held on that many reads
1611
- * in a row, `confirm.gapMs` apart: a page that renders after network quiet
1612
- * reads half-built for a moment, and a `gone` condition holds on a list
1613
- * that has not been drawn yet. The clock is the wall's: a rehearsal waits
1614
- * as long as a take would, because how long a result takes is what a
1615
- * rehearsal is for.
1616
- */
1617
- declare function pollCondition(page: RecorderPage, c: WaitCondition, opts: {
1618
- timeoutMs: number;
1619
- everyMs: number;
1620
- sleep: (ms: number) => Promise<void>;
1621
- now?: () => number;
1622
- between?: () => Promise<void>;
1623
- confirm?: {
1624
- reads: number;
1625
- gapMs: number;
1626
- };
1627
- }): Promise<PollResult>;
1628
- /** The DOM counts as settled after this long with no change. */
1629
- declare const DOM_QUIET_MS = 800;
1630
- /** The longest a settle waits on a page that never stops changing. */
1631
- declare const DOM_SETTLE_CAP_MS = 5000;
1632
- /**
1633
- * The page's own count of DOM changes: an observer installed once per
1634
- * document, read back as a number. A string, the one evaluate shape every
1635
- * driver shares.
1636
- */
1637
- declare const DOM_CHANGE_PROBE = "(() => {\n if (!window.__vosDomChanges) {\n window.__vosDomChanges = { n: 0 };\n new MutationObserver((list) => { window.__vosDomChanges.n += list.length })\n .observe(document, { subtree: true, childList: true, attributes: true, characterData: true });\n }\n return window.__vosDomChanges.n;\n})()";
1638
- /**
1639
- * Wait until the DOM has not changed for `quietMs`, at most `capMs`: what
1640
- * a page does after its network went quiet (a list rendered from data, a
1641
- * hydration). The count is polled from here rather than timed in the
1642
- * page, because a background tab throttles its own timers.
1643
- */
1644
- declare function domSettled(page: RecorderPage, opts: {
1645
- sleep: (ms: number) => Promise<void>;
1646
- now?: () => number;
1647
- quietMs?: number;
1648
- capMs?: number;
1649
- tickMs?: number;
1650
- }): Promise<{
1651
- settled: boolean;
1652
- ms: number;
1653
- }>;
1654
- /** Seconds as the recorder says them: `5 s`, `2.5 s`, `3 min 20 s`. */
1655
- declare function sayDuration(ms: number): string;
1656
- /** What the condition waits for, in words: `'#result' to appear`. */
1657
- declare function sayCondition(c: WaitCondition): string;
1658
- /** Why the condition did not hold, in words: `'Generate' stayed disabled for 5 s`. */
1659
- declare function conditionMiss(c: WaitCondition, last: ConditionState, ms: number): string;
1660
-
1661
1883
  /** The most a download keeps: a file the page made, never a disk's worth. */
1662
1884
  declare const OUTPUT_MAX_BYTES: number;
1663
1885
  /**
@@ -2045,4 +2267,4 @@ declare function inlinePoints(path: {
2045
2267
  */
2046
2268
  declare function inlineScript<T extends Pick<ActionsFile, 'steps'>>(actions: T, files: LoadedFiles): T;
2047
2269
 
2048
- export { APP_QUIET_MS, APP_SETTLE_CAP_MS, AWAIT_HEARTBEAT_MS, AWAIT_POLL_S, AWAIT_TIMEOUT_S, type ActionStep, type ActionsFile, type Arrival, type AwaitUntil, CHANGE_AGE_PROBE, CLICK_BUTTONS, type ClickButton, type ConditionState, DEAD_SHARE_WARN_PCT, DEAD_STRETCH_WARN_MS, DEFAULT_READY, DOM_CHANGE_PROBE, DOM_QUIET_MS, DOM_SETTLE_CAP_MS, DOWNLOAD_TIMEOUT_S, DRAG_HOLD_MS, DRAG_MODIFIERS, type DeadReport, type DeadStep, type DisabledClick, type DragModifier, EXPECT_TIMEOUT_S, EXPOSURE_ADVICE, EXPOSURE_MATCHERS_SRC, EXPOSURE_PROBE, type EncodePageOptions, type Exposure, type ExposureKind, ExposureLog, type FrameRec, type FrameSink, type FreezeSpan, type FreshPlanOptions, type GuardedStep, type HeardSound, IDLE_CALL_MS, KEY_ROUNDTRIP_MS, KEY_SEQUENCE_GAP_MS, type LoadedFiles, MAX_KEYS, MAX_PATH_POINTS, MEDIA_DRAIN_PROBE, MEDIA_WATCH_SCRIPT, MIN_SKIP_MS, MODIFIERS, MOTION_TICK_MS, MULTI_CLICK_GAP_MS, type MaskReport, type MaskRule, type MediaDrain, type MediaNote, type Modifier, NAV_TIMEOUT_MS, NETWORKIDLE_HYDRATION_MS, NOTICE_SRC, type Notice, NoticeLog, OUTPUT_MAX_BYTES, OVERRUN_MIN_MS, OVERRUN_MIN_PLANNED_MS, OVERRUN_SHARE, type OutputSink, PAGE_ERROR_LINE_CHARS, PASTE_MAX_BYTES, PASTE_READ_WINDOW_MS, PASTE_TYPES, PASTE_UNREAD_MS, PATH_DEFAULT_MS, POINTER_MAX_MS, POINTER_MIN_MS, POINTER_MS_PER_PX, PRESS_HOLD_MS, PRESS_KEYS, PRESS_LEAD_MS, type PaceReport, type PageError, PageErrorLog, PageSoundLog, type PasteItem, type PathPoint, type PathSample, type PollResult, type PressKey, QUIET_MS, READY_MODES, READY_SETTLE_CAP_MS, READ_BEAT_MS, RESPONSE_MS, type ReadyMode, type ReadyOpts, type ReadyReport, type RecordOpts, RecordRefusedError, type RecordResult, type RecorderApiResponse, type RecorderBrowser, type RecorderButtonOpts, type RecorderCdp, type RecorderClock, type RecorderConsoleMessage, type RecorderContext, type RecorderDownload, type RecorderLocator, type RecorderLocatorRoot, type RecorderMediaElement, type RecorderPage, type RecorderRect, type RecorderResponse, type RecorderRoute, SCROLL_MAX_MS, SCROLL_MIN_MS, SCROLL_MS_PER_PX, SCROLL_SETTLE_MS, SETTLE_CAP_MS, SETTLE_MS, SETTLE_VERBS, STEP_GUARDS, STEP_MARGIN_MS, type ScannedNotice, type ScriptFiles, SetupEnvError, SetupError, type SetupResult, type SetupStep, type SetupText, type SkippedStep, type SoundSink, StepBound, type StepGuard, type StepOverrun, type StepPace, type StoppedTake, type SurfaceFit, type SurfaceSize, TRAILING_HOLD_MS, TakeClock, WAIT_MARGIN_MS, WALL_PROBE, type WaitCondition, WallError, type WallKind, type WallVerdict, appSettled, askedMs, base64Bytes, bounded, buildEncodePage, buttonNumber, capReached, cappedLine, chordProblem, clampWait, clockMotion, clockTyping, conditionMiss, deadLine, deadTime, deadWarns, domSettled, easeInOutCubic, exposureLine, extForType, fetchInPageScript, fileNameProblem, fitSurfaceToViewport, formatDurationCap, guardVerdict, guardedSteps, hangReason, headersFor, holdLeftMs, hostedRefusals, inlinePoints, inlineScript, isIdpHost, isKeyName, isSignInPath, jpegDims, keySequencePlanMs, loadScriptFiles, maskInitScript, modifierBits, nameFromUrl, noticeAdvice, noticeLine, outputName, overrunLine, overrunOf, paceLine, paceReport, pageErrorLine, parseHeaders, pasteTypeOf, pathDurationMs, plainName, planFreshTake, pointerTravelMs, pollCondition, pressSequence, publicUrl, readAllBytes, readCondition, readMediaSource, readPath, readyLine, readyProblem, realSleep, recordTake, redirectedAway, reloadUntilReady, resolveChord, resolveModifier, resolveSetupText, runSetup, sayCondition, sayDuration, schedulePath, scriptFiles, scrollByScript, scrollTravelMs, settleMs, settleOn, settleVerdict, setupEnvNames, soundSrcForMeta, splitChord, splitSegmentsAtSkips, stageClipboardScript, stepBoundMs, syntheticPasteScript, typeOfName, untilReady, urlSchemeProblem, validateActions, validateSetup, visibleTextScript, wallVerdict, withFittingExport, withPageSound };
2270
+ export { APP_QUIET_MS, APP_SETTLE_CAP_MS, AWAIT_HEARTBEAT_MS, AWAIT_POLL_S, AWAIT_TIMEOUT_S, type ActionStep, type ActionsFile, type Arrival, type AwaitUntil, CHANGE_AGE_PROBE, CLICK_BUTTONS, type ClickButton, type ConditionState, DEAD_SHARE_WARN_PCT, DEAD_STRETCH_WARN_MS, DEFAULT_READY, DOM_CHANGE_PROBE, DOM_QUIET_MS, DOM_SETTLE_CAP_MS, DOWNLOAD_TIMEOUT_S, DRAG_HOLD_MS, DRAG_MODIFIERS, type DeadReport, type DeadStep, type DisabledClick, type DragModifier, EXPECT_TIMEOUT_S, EXPOSURE_ADVICE, EXPOSURE_MATCHERS_SRC, EXPOSURE_PROBE, type EncodePageOptions, type Exposure, type ExposureKind, ExposureLog, type FrameRec, type FrameSink, type FreezeSpan, type FreshPlanOptions, type GuardedStep, type HeardSound, IDLE_CALL_MS, JS_SAID_MAX, JS_VALUE_MAX, KEY_ROUNDTRIP_MS, KEY_SEQUENCE_GAP_MS, type LoadedFiles, MAX_KEYS, MAX_PATH_POINTS, MAX_PEERS, MAX_PEER_STEPS, MEDIA_DRAIN_PROBE, MEDIA_WATCH_SCRIPT, MIN_SKIP_MS, MODIFIERS, MOTION_TICK_MS, MULTI_CLICK_GAP_MS, type MaskReport, type MaskRule, type MediaDrain, type MediaNote, type Modifier, NAV_TIMEOUT_MS, NETWORKIDLE_HYDRATION_MS, NOTICE_SRC, type Notice, NoticeLog, OUTPUT_MAX_BYTES, OVERRUN_MIN_MS, OVERRUN_MIN_PLANNED_MS, OVERRUN_SHARE, type OutputSink, PAGE_ERROR_LINE_CHARS, PASTE_MAX_BYTES, PASTE_READ_WINDOW_MS, PASTE_TYPES, PASTE_UNREAD_MS, PATH_DEFAULT_MS, PEER_VALUE_MAX, PEER_VERBS, POINTER_MAX_MS, POINTER_MIN_MS, POINTER_MS_PER_PX, PRESS_HOLD_MS, PRESS_KEYS, PRESS_LEAD_MS, type PaceReport, type PageError, PageErrorLog, PageSoundLog, type PasteItem, type PathPoint, type PathSample, type Peer, type PeerRun, type PeerStep, type PollResult, type PressKey, QUIET_MS, READY_MODES, READY_SETTLE_CAP_MS, READ_BEAT_MS, RESPONSE_MS, type ReadyMode, type ReadyOpts, type ReadyReport, type RecordOpts, RecordRefusedError, type RecordResult, type RecorderApiResponse, type RecorderBrowser, type RecorderButtonOpts, type RecorderCdp, type RecorderClock, type RecorderConsoleMessage, type RecorderContext, type RecorderDownload, type RecorderLocator, type RecorderLocatorRoot, type RecorderMediaElement, type RecorderPage, type RecorderRect, type RecorderResponse, type RecorderRoute, SCROLL_MAX_MS, SCROLL_MIN_MS, SCROLL_MS_PER_PX, SCROLL_SETTLE_MS, SETTLE_CAP_MS, SETTLE_MS, SETTLE_VERBS, STEP_GUARDS, STEP_MARGIN_MS, type ScannedNotice, type ScriptFiles, SetupEnvError, SetupError, type SetupResult, type SetupStep, type SetupText, type SkippedStep, type SoundSink, StepBound, type StepGuard, type StepOverrun, type StepPace, StepSignals, type StoppedTake, type SurfaceFit, type SurfaceSize, TRAILING_HOLD_MS, TakeClock, WAIT_MARGIN_MS, WALL_PROBE, type WaitCondition, WallError, type WallKind, type WallVerdict, ZOOM_MARK_VERBS, appSettled, askedMs, base64Bytes, bounded, buildEncodePage, buttonNumber, capReached, cappedLine, chordProblem, clampWait, clockMotion, clockTyping, conditionMiss, deadLine, deadTime, deadWarns, domSettled, easeInOutCubic, exposureLine, extForType, fetchInPageScript, fileNameProblem, fitSurfaceToViewport, formatDurationCap, guardVerdict, guardedSteps, hangReason, headersFor, holdLeftMs, hostedRefusals, inlinePoints, inlineScript, isIdpHost, isKeyName, isSignInPath, jpegDims, jsConditionScript, keptValue, keySequencePlanMs, loadScriptFiles, maskInitScript, modifierBits, nameFromUrl, noticeAdvice, noticeLine, outputName, overrunLine, overrunOf, paceLine, paceReport, pageErrorLine, parseHeaders, pasteTypeOf, pathDurationMs, peerValue, peersHostedRefusal, plainName, planFreshTake, pointerTravelMs, pollCondition, pressSequence, publicUrl, readAllBytes, readCondition, readMediaSource, readPath, readyLine, readyProblem, realSleep, recordTake, redirectedAway, reloadUntilReady, resolveChord, resolveModifier, resolveSetupText, runPeer, runSetup, sameJson, sayCondition, sayDuration, sayJs, sayValue, schedulePath, scriptFiles, scrollByScript, scrollTravelMs, settleMs, settleOn, settleVerdict, setupEnvNames, soundSrcForMeta, splitChord, splitSegmentsAtSkips, stageClipboardScript, stepBoundMs, syntheticPasteScript, typeOfName, untilReady, urlSchemeProblem, validateActions, validatePeers, validateSetup, visibleTextScript, wallVerdict, withFittingExport, withPageSound };