@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.
- package/dist/record/index.d.ts +322 -100
- package/dist/record/index.js +728 -16
- package/dist/record/index.js.map +1 -1
- package/package.json +2 -2
package/dist/record/index.d.ts
CHANGED
|
@@ -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`,
|
|
1041
|
-
*
|
|
1042
|
-
*
|
|
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
|
|
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,
|
|
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 };
|