@e2edev/agent-device 0.1.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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +131 -0
  3. package/dist/backend.d.ts +16 -0
  4. package/dist/backend.d.ts.map +1 -0
  5. package/dist/backend.js +66 -0
  6. package/dist/backend.js.map +1 -0
  7. package/dist/device.d.ts +69 -0
  8. package/dist/device.d.ts.map +1 -0
  9. package/dist/device.js +77 -0
  10. package/dist/device.js.map +1 -0
  11. package/dist/errors.d.ts +25 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +72 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/index.d.ts +18 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +14 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/locate.d.ts +14 -0
  20. package/dist/locate.d.ts.map +1 -0
  21. package/dist/locate.js +100 -0
  22. package/dist/locate.js.map +1 -0
  23. package/dist/nodes.d.ts +82 -0
  24. package/dist/nodes.d.ts.map +1 -0
  25. package/dist/nodes.js +295 -0
  26. package/dist/nodes.js.map +1 -0
  27. package/dist/png.d.ts +22 -0
  28. package/dist/png.d.ts.map +1 -0
  29. package/dist/png.js +172 -0
  30. package/dist/png.js.map +1 -0
  31. package/dist/selector.d.ts +17 -0
  32. package/dist/selector.d.ts.map +1 -0
  33. package/dist/selector.js +84 -0
  34. package/dist/selector.js.map +1 -0
  35. package/dist/support.d.ts +59 -0
  36. package/dist/support.d.ts.map +1 -0
  37. package/dist/support.js +105 -0
  38. package/dist/support.js.map +1 -0
  39. package/dist/surface.d.ts +146 -0
  40. package/dist/surface.d.ts.map +1 -0
  41. package/dist/surface.js +485 -0
  42. package/dist/surface.js.map +1 -0
  43. package/dist/tools.d.ts +24 -0
  44. package/dist/tools.d.ts.map +1 -0
  45. package/dist/tools.js +110 -0
  46. package/dist/tools.js.map +1 -0
  47. package/package.json +80 -0
package/dist/png.js ADDED
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Minimal PNG codec for masking secure regions in device screenshots: 8-bit
3
+ * RGB or RGBA, non-interlaced, which is what a simulator or emulator
4
+ * screenshot is. Anything else is refused loudly, and the caller withholds
5
+ * the image rather than shipping pixels it could not redact.
6
+ */
7
+ import { deflateSync, inflateSync } from 'node:zlib';
8
+ const SIGNATURE = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
9
+ function paeth(a, b, c) {
10
+ const p = a + b - c;
11
+ const pa = Math.abs(p - a);
12
+ const pb = Math.abs(p - b);
13
+ const pc = Math.abs(p - c);
14
+ if (pa <= pb && pa <= pc)
15
+ return a;
16
+ return pb <= pc ? b : c;
17
+ }
18
+ /** Decodes PNG bytes into mutable samples; throws for formats this codec does not read. */
19
+ export function decodePng(bytes) {
20
+ if (bytes.byteLength < 8 || !SIGNATURE.every((byte, index) => bytes[index] === byte)) {
21
+ throw new Error('not a PNG');
22
+ }
23
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
24
+ let offset = 8;
25
+ let width = 0;
26
+ let height = 0;
27
+ let channels = 0;
28
+ const idat = [];
29
+ while (offset + 8 <= bytes.byteLength) {
30
+ const length = view.getUint32(offset);
31
+ const type = String.fromCharCode(...bytes.subarray(offset + 4, offset + 8));
32
+ const data = bytes.subarray(offset + 8, offset + 8 + length);
33
+ if (type === 'IHDR') {
34
+ width = view.getUint32(offset + 8);
35
+ height = view.getUint32(offset + 12);
36
+ const bitDepth = data[8];
37
+ const colorType = data[9];
38
+ const interlace = data[12];
39
+ if (bitDepth !== 8 || interlace !== 0 || (colorType !== 2 && colorType !== 6)) {
40
+ throw new Error(`unsupported PNG: depth ${String(bitDepth)} type ${String(colorType)}`);
41
+ }
42
+ channels = colorType === 6 ? 4 : 3;
43
+ }
44
+ else if (type === 'IDAT') {
45
+ idat.push(data);
46
+ }
47
+ else if (type === 'IEND') {
48
+ break;
49
+ }
50
+ offset += 12 + length;
51
+ }
52
+ if (channels === 0)
53
+ throw new Error('PNG without IHDR');
54
+ const raw = inflateSync(Buffer.concat(idat));
55
+ const stride = width * channels;
56
+ const pixels = new Uint8Array(stride * height);
57
+ for (let y = 0; y < height; y += 1) {
58
+ const filter = raw[y * (stride + 1)];
59
+ const row = raw.subarray(y * (stride + 1) + 1, (y + 1) * (stride + 1));
60
+ const out = pixels.subarray(y * stride, (y + 1) * stride);
61
+ const prior = y === 0 ? new Uint8Array(stride) : pixels.subarray((y - 1) * stride, y * stride);
62
+ for (let i = 0; i < stride; i += 1) {
63
+ const left = i >= channels ? out[i - channels] : 0;
64
+ const up = prior[i];
65
+ const upLeft = i >= channels ? prior[i - channels] : 0;
66
+ const value = row[i];
67
+ let predicted;
68
+ switch (filter) {
69
+ case 0:
70
+ predicted = 0;
71
+ break;
72
+ case 1:
73
+ predicted = left;
74
+ break;
75
+ case 2:
76
+ predicted = up;
77
+ break;
78
+ case 3:
79
+ predicted = Math.floor((left + up) / 2);
80
+ break;
81
+ case 4:
82
+ predicted = paeth(left, up, upLeft);
83
+ break;
84
+ default:
85
+ throw new Error(`unsupported PNG filter ${String(filter)}`);
86
+ }
87
+ out[i] = (value + predicted) & 0xff;
88
+ }
89
+ }
90
+ return { width, height, channels, pixels };
91
+ }
92
+ const CRC_TABLE = new Uint32Array(256).map((_value, n) => {
93
+ let c = n;
94
+ for (let k = 0; k < 8; k += 1)
95
+ c = (c & 1) === 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
96
+ return c >>> 0;
97
+ });
98
+ function crc32(bytes) {
99
+ let crc = 0xffffffff;
100
+ for (const byte of bytes)
101
+ crc = CRC_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);
102
+ return (crc ^ 0xffffffff) >>> 0;
103
+ }
104
+ function chunk(type, data) {
105
+ const out = new Uint8Array(12 + data.byteLength);
106
+ const view = new DataView(out.buffer);
107
+ view.setUint32(0, data.byteLength);
108
+ const typed = new Uint8Array(4 + data.byteLength);
109
+ typed.set([...type].map((char) => char.charCodeAt(0)), 0);
110
+ typed.set(data, 4);
111
+ out.set(typed, 4);
112
+ view.setUint32(8 + data.byteLength, crc32(typed));
113
+ return out;
114
+ }
115
+ /** Encodes samples as a PNG with unfiltered rows; size is not the goal, fidelity is. */
116
+ export function encodePng(image) {
117
+ const { width, height, channels, pixels } = image;
118
+ const stride = width * channels;
119
+ const raw = new Uint8Array((stride + 1) * height);
120
+ for (let y = 0; y < height; y += 1) {
121
+ raw[y * (stride + 1)] = 0;
122
+ raw.set(pixels.subarray(y * stride, (y + 1) * stride), y * (stride + 1) + 1);
123
+ }
124
+ const ihdr = new Uint8Array(13);
125
+ const view = new DataView(ihdr.buffer);
126
+ view.setUint32(0, width);
127
+ view.setUint32(4, height);
128
+ ihdr[8] = 8;
129
+ ihdr[9] = channels === 4 ? 6 : 2;
130
+ ihdr[10] = 0;
131
+ ihdr[11] = 0;
132
+ ihdr[12] = 0;
133
+ return Buffer.concat([
134
+ Uint8Array.from(SIGNATURE),
135
+ chunk('IHDR', ihdr),
136
+ chunk('IDAT', deflateSync(raw)),
137
+ chunk('IEND', new Uint8Array(0)),
138
+ ]);
139
+ }
140
+ /**
141
+ * Paints every rect opaque black, in image pixels. Rects are clamped to the
142
+ * image; a rect entirely outside it masks nothing but still counts as
143
+ * handled, because the field it covers is not on screen either.
144
+ */
145
+ function maskRects(image, rects) {
146
+ const { width, height, channels, pixels } = image;
147
+ for (const rect of rects) {
148
+ const x0 = Math.max(0, Math.floor(rect.x));
149
+ const y0 = Math.max(0, Math.floor(rect.y));
150
+ const x1 = Math.min(width, Math.ceil(rect.x + rect.width));
151
+ const y1 = Math.min(height, Math.ceil(rect.y + rect.height));
152
+ for (let y = y0; y < y1; y += 1) {
153
+ for (let x = x0; x < x1; x += 1) {
154
+ const at = (y * width + x) * channels;
155
+ pixels[at] = 0;
156
+ pixels[at + 1] = 0;
157
+ pixels[at + 2] = 0;
158
+ if (channels === 4)
159
+ pixels[at + 3] = 255;
160
+ }
161
+ }
162
+ }
163
+ }
164
+ /** Decodes, masks, and re-encodes in one step. */
165
+ export function maskPng(bytes, rects) {
166
+ if (rects.length === 0)
167
+ return bytes;
168
+ const image = decodePng(bytes);
169
+ maskRects(image, rects);
170
+ return encodePng(image);
171
+ }
172
+ //# sourceMappingURL=png.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"png.js","sourceRoot":"","sources":["../src/png.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * agent-device selector support for the `selector` locator expression:
3
+ * `screen.locator('id=save role=button')` and the structural hint on every
4
+ * observed node. The grammar is agent-device's own (`parseSelectorChain`), so a
5
+ * selector that works on the agent-device CLI works here unchanged; matching
6
+ * runs against the projected snapshot, one immediate pass, every match returned.
7
+ */
8
+ import { type ProjectedNode } from './nodes.ts';
9
+ export type CompiledSelector = (entries: readonly ProjectedNode[]) => ProjectedNode[];
10
+ /**
11
+ * Compiles one selector string. Alternatives (agent-device's fallback chain)
12
+ * are tried in order and the first that matches anything wins, mirroring how
13
+ * agent-device itself resolves a chain; a term's text compares exactly after
14
+ * whitespace collapsing, like every other text rule in the runner.
15
+ */
16
+ export declare function compileSelector(raw: string): CompiledSelector;
17
+ //# sourceMappingURL=selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../src/selector.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAQ/D,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,KAAK,aAAa,EAAE,CAAC;AAEtF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAiB7D"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * agent-device selector support for the `selector` locator expression:
3
+ * `screen.locator('id=save role=button')` and the structural hint on every
4
+ * observed node. The grammar is agent-device's own (`parseSelectorChain`), so a
5
+ * selector that works on the agent-device CLI works here unchanged; matching
6
+ * runs against the projected snapshot, one immediate pass, every match returned.
7
+ */
8
+ import { parseSelectorChain } from 'agent-device/selectors';
9
+ import { BackendError } from '@e2edev/e2e/backend';
10
+ import { normalizeKind } from './nodes.js';
11
+ import { message } from './errors.js';
12
+ /**
13
+ * Compiles one selector string. Alternatives (agent-device's fallback chain)
14
+ * are tried in order and the first that matches anything wins, mirroring how
15
+ * agent-device itself resolves a chain; a term's text compares exactly after
16
+ * whitespace collapsing, like every other text rule in the runner.
17
+ */
18
+ export function compileSelector(raw) {
19
+ let chain;
20
+ try {
21
+ chain = parseSelectorChain(raw);
22
+ }
23
+ catch (cause) {
24
+ throw new BackendError('BACKEND_FAILURE', `invalid agent-device selector ${JSON.stringify(raw)}: ${message(cause)}`, {
25
+ retryable: false,
26
+ cause,
27
+ });
28
+ }
29
+ return (entries) => {
30
+ for (const alternative of chain.selectors) {
31
+ const matches = entries.filter((entry) => alternative.terms.every((term) => matchesTerm(entry, term)));
32
+ if (matches.length > 0)
33
+ return matches;
34
+ }
35
+ return [];
36
+ };
37
+ }
38
+ function normalize(text) {
39
+ return text.replaceAll(/\s+/g, ' ').trim();
40
+ }
41
+ function textEquals(actual, expected) {
42
+ return actual !== undefined && normalize(actual) === normalize(String(expected));
43
+ }
44
+ function flag(value) {
45
+ return value === true || String(value).toLowerCase() === 'true';
46
+ }
47
+ function matchesTerm(entry, term) {
48
+ const states = entry.node.states ?? {};
49
+ switch (term.key) {
50
+ case 'id':
51
+ return textEquals(entry.raw.identifier, term.value);
52
+ case 'role': {
53
+ const wanted = normalizeKind(String(term.value));
54
+ return entry.kind === wanted || entry.node.role === wanted;
55
+ }
56
+ case 'text':
57
+ return textEquals(entry.raw.label, term.value) || textEquals(entry.raw.value, term.value);
58
+ case 'label':
59
+ return textEquals(entry.raw.label, term.value);
60
+ case 'value':
61
+ return textEquals(entry.raw.value, term.value);
62
+ case 'appname':
63
+ return textEquals(entry.raw.appName, term.value);
64
+ case 'windowtitle':
65
+ return textEquals(entry.raw.windowTitle, term.value);
66
+ case 'visible':
67
+ return (states.hidden !== true) === flag(term.value);
68
+ case 'hidden':
69
+ return (states.hidden === true) === flag(term.value);
70
+ case 'editable':
71
+ return (entry.node.role === 'textbox') === flag(term.value);
72
+ case 'selected':
73
+ return (states.selected === true) === flag(term.value);
74
+ case 'focused':
75
+ return (states.focused === true) === flag(term.value);
76
+ case 'enabled':
77
+ return (states.disabled !== true) === flag(term.value);
78
+ case 'hittable':
79
+ return (entry.raw.hittable !== false) === flag(term.value);
80
+ default:
81
+ return false;
82
+ }
83
+ }
84
+ //# sourceMappingURL=selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.js","sourceRoot":"","sources":["../src/selector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /** Shared helpers for the agent-device backend: abort racing, filenames, PNG headers, gestures, path anchors. */
2
+ import { BackendError, type Momentum, type ScrollDirection } from '@e2edev/e2e/backend';
3
+ export interface Point {
4
+ readonly x: number;
5
+ readonly y: number;
6
+ }
7
+ export interface Rect {
8
+ readonly x: number;
9
+ readonly y: number;
10
+ readonly width: number;
11
+ readonly height: number;
12
+ }
13
+ export declare function cancelled(text: string): BackendError;
14
+ export declare function invalidState(text: string): BackendError;
15
+ export declare function notActionable(text: string): BackendError;
16
+ export declare function unsupported(text: string): BackendError;
17
+ /**
18
+ * Awaits `promise` unless `signal` aborts first, in which case the wait ends
19
+ * with `CANCELLED`. agent-device commands take no signal, so the in-flight
20
+ * call is not stopped; its eventual settlement is absorbed instead of
21
+ * surfacing as an unhandled rejection.
22
+ */
23
+ export declare function raceAbort<T>(promise: Promise<T>, signal: AbortSignal, label: string): Promise<T>;
24
+ /**
25
+ * Best-effort cleanup wait: resolves when `promise` settles, when `signal`
26
+ * aborts, or when `timeoutMs` elapses, whichever comes first. Cleanup never
27
+ * throws through here; a close that outlives its budget is abandoned.
28
+ */
29
+ export declare function withinCleanupBudget(promise: Promise<unknown>, budget: {
30
+ readonly signal: AbortSignal;
31
+ readonly timeoutMs: number;
32
+ }): Promise<void>;
33
+ /** Constrains a caller-supplied artifact label to a safe filename. */
34
+ export declare function sanitizeFilename(name: string): string;
35
+ /** Reads the dimensions out of a PNG's IHDR chunk; undefined for anything else. */
36
+ export declare function readPngSize(data: Uint8Array): {
37
+ width: number;
38
+ height: number;
39
+ } | undefined;
40
+ /**
41
+ * The finger gesture that scrolls one rect's content in `direction`. Scrolling
42
+ * down reveals what is below, so the finger travels up; the travel is a share
43
+ * of the rect's extent scaled by momentum, and never leaves the rect.
44
+ */
45
+ export declare function swipeWithin(rect: Rect, direction: ScrollDirection, momentum: Momentum | undefined): {
46
+ from: Point;
47
+ to: Point;
48
+ };
49
+ /**
50
+ * The location a device surface reports through `url`. A simulator has no
51
+ * address bar, but the trace cache anchors every recorded step on a path and
52
+ * refuses to write a trace for a surface without one, so the backend mints
53
+ * one: `app://device/<app>/<screen title>`. The cache compares pathnames
54
+ * only, so the app identity lives in the path, not the host: two apps with a
55
+ * screen called "General" must not share an anchor. `new URL(...)` parses
56
+ * it, and its pathname changes exactly when the app or its screen changes.
57
+ */
58
+ export declare function screenUrl(app: string | undefined, title: string | undefined): string;
59
+ //# sourceMappingURL=support.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../src/support.ts"],"names":[],"mappings":"AAAA,iHAAiH;AAEjH,OAAO,EAAE,YAAY,EAAE,KAAK,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAExF,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAEpD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAEvD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAExD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAehG;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EACzB,MAAM,EAAE;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACnE,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAID,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAO3F;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,eAAe,EAC1B,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAC7B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAE,CAe5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAIpF"}
@@ -0,0 +1,105 @@
1
+ /** Shared helpers for the agent-device backend: abort racing, filenames, PNG headers, gestures, path anchors. */
2
+ import { BackendError } from '@e2edev/e2e/backend';
3
+ export function cancelled(text) {
4
+ return new BackendError('CANCELLED', text, { retryable: false });
5
+ }
6
+ export function invalidState(text) {
7
+ return new BackendError('INVALID_STATE', text, { retryable: false });
8
+ }
9
+ export function notActionable(text) {
10
+ return new BackendError('NOT_ACTIONABLE', text, { retryable: false });
11
+ }
12
+ export function unsupported(text) {
13
+ return new BackendError('UNSUPPORTED_CAPABILITY', text, { retryable: false });
14
+ }
15
+ /**
16
+ * Awaits `promise` unless `signal` aborts first, in which case the wait ends
17
+ * with `CANCELLED`. agent-device commands take no signal, so the in-flight
18
+ * call is not stopped; its eventual settlement is absorbed instead of
19
+ * surfacing as an unhandled rejection.
20
+ */
21
+ export function raceAbort(promise, signal, label) {
22
+ if (signal.aborted) {
23
+ promise.catch(() => undefined);
24
+ return Promise.reject(cancelled(`${label} cancelled`));
25
+ }
26
+ return new Promise((resolve, reject) => {
27
+ const onAbort = () => {
28
+ promise.catch(() => undefined);
29
+ reject(cancelled(`${label} cancelled`));
30
+ };
31
+ signal.addEventListener('abort', onAbort, { once: true });
32
+ promise.then(resolve, reject).finally(() => {
33
+ signal.removeEventListener('abort', onAbort);
34
+ });
35
+ });
36
+ }
37
+ /**
38
+ * Best-effort cleanup wait: resolves when `promise` settles, when `signal`
39
+ * aborts, or when `timeoutMs` elapses, whichever comes first. Cleanup never
40
+ * throws through here; a close that outlives its budget is abandoned.
41
+ */
42
+ export function withinCleanupBudget(promise, budget) {
43
+ return new Promise((resolve) => {
44
+ const settle = () => {
45
+ clearTimeout(timer);
46
+ budget.signal.removeEventListener('abort', settle);
47
+ resolve();
48
+ };
49
+ const timer = setTimeout(settle, Math.max(0, budget.timeoutMs));
50
+ budget.signal.addEventListener('abort', settle, { once: true });
51
+ promise.then(settle, settle);
52
+ });
53
+ }
54
+ /** Constrains a caller-supplied artifact label to a safe filename. */
55
+ export function sanitizeFilename(name) {
56
+ return name.replaceAll(/[^A-Za-z0-9._-]/g, '_').slice(0, 64) || 'artifact';
57
+ }
58
+ const PNG_SIGNATURE = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
59
+ /** Reads the dimensions out of a PNG's IHDR chunk; undefined for anything else. */
60
+ export function readPngSize(data) {
61
+ if (data.byteLength < 24)
62
+ return undefined;
63
+ for (const [offset, byte] of PNG_SIGNATURE.entries()) {
64
+ if (data[offset] !== byte)
65
+ return undefined;
66
+ }
67
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
68
+ return { width: view.getUint32(16), height: view.getUint32(20) };
69
+ }
70
+ /**
71
+ * The finger gesture that scrolls one rect's content in `direction`. Scrolling
72
+ * down reveals what is below, so the finger travels up; the travel is a share
73
+ * of the rect's extent scaled by momentum, and never leaves the rect.
74
+ */
75
+ export function swipeWithin(rect, direction, momentum) {
76
+ const ratio = momentum === 'fast' ? 0.8 : momentum === 'slow' ? 0.25 : 0.5;
77
+ const centre = { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };
78
+ const dx = (rect.width * ratio) / 2;
79
+ const dy = (rect.height * ratio) / 2;
80
+ switch (direction) {
81
+ case 'down':
82
+ return { from: { x: centre.x, y: centre.y + dy }, to: { x: centre.x, y: centre.y - dy } };
83
+ case 'up':
84
+ return { from: { x: centre.x, y: centre.y - dy }, to: { x: centre.x, y: centre.y + dy } };
85
+ case 'right':
86
+ return { from: { x: centre.x + dx, y: centre.y }, to: { x: centre.x - dx, y: centre.y } };
87
+ case 'left':
88
+ return { from: { x: centre.x - dx, y: centre.y }, to: { x: centre.x + dx, y: centre.y } };
89
+ }
90
+ }
91
+ /**
92
+ * The location a device surface reports through `url`. A simulator has no
93
+ * address bar, but the trace cache anchors every recorded step on a path and
94
+ * refuses to write a trace for a surface without one, so the backend mints
95
+ * one: `app://device/<app>/<screen title>`. The cache compares pathnames
96
+ * only, so the app identity lives in the path, not the host: two apps with a
97
+ * screen called "General" must not share an anchor. `new URL(...)` parses
98
+ * it, and its pathname changes exactly when the app or its screen changes.
99
+ */
100
+ export function screenUrl(app, title) {
101
+ const identity = (app ?? '').replaceAll(/[^A-Za-z0-9.-]/g, '-').replaceAll(/^-+|-+$/g, '').toLowerCase() || 'unknown';
102
+ const trimmed = title === undefined ? '' : title.replaceAll(/\s+/g, ' ').trim();
103
+ return `app://device/${identity}/${trimmed === '' ? '' : encodeURIComponent(trimmed)}`;
104
+ }
105
+ //# sourceMappingURL=support.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"support.js","sourceRoot":"","sources":["../src/support.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * The agent-device surface: one simulator or emulator session, driven through
3
+ * agent-device's typed client, exposed to the runner as the contract's
4
+ * observe/locate/perform members. It owns the id space (one fresh generation
5
+ * per observation), the attempt state (artifact directory, screenshot
6
+ * counter), and every translation between the contract's vocabulary and
7
+ * agent-device's commands. The runner owns everything else.
8
+ */
9
+ import type { createAgentDeviceClient } from 'agent-device';
10
+ import { type BackendAttemptContext, type BackendCleanupContext, type BackendInitInfo, type BackendObserveOptions, type BackendSnapshot, type LocatorAction, type LocatorExpression, type Momentum, type NodeRef, type OperationContext, type ScrollDirection, type SemanticNode } from '@e2edev/e2e/backend';
11
+ export type AgentDeviceClient = ReturnType<typeof createAgentDeviceClient>;
12
+ /** Mints the agent-device client for one session; the seam unit tests script. */
13
+ export type ClientFactory = (session: string) => AgentDeviceClient;
14
+ export type AgentDevicePlatform = 'ios' | 'android';
15
+ export interface AgentDeviceOptions {
16
+ /** Platform the target's device runs. */
17
+ readonly platform: AgentDevicePlatform;
18
+ /**
19
+ * App opened fresh at the start of every attempt: a bundle id, a package
20
+ * name, or a display name agent-device resolves (`Settings`). Without it the
21
+ * surface observes whatever is in the foreground, and `app.restart` and
22
+ * `app.clearState` are not declared.
23
+ */
24
+ readonly app?: string;
25
+ /** Simulator or emulator to use, by name or id; agent-device picks a booted one otherwise. */
26
+ readonly device?: string;
27
+ /**
28
+ * agent-device session name; defaults to `e2e-<target name>`. One run per
29
+ * session at a time: concurrent runs on the same session interleave taps.
30
+ */
31
+ readonly session?: string;
32
+ /**
33
+ * What an observation captures. `full` (default) includes static text, so
34
+ * judgments can read values; `interactive` keeps only actionable nodes and
35
+ * is cheaper on screens with long lists.
36
+ */
37
+ readonly snapshot?: 'full' | 'interactive';
38
+ }
39
+ export declare class AgentDeviceSurface {
40
+ readonly options: AgentDeviceOptions;
41
+ private readonly createClient;
42
+ private client;
43
+ private testIdAttribute;
44
+ private attempt;
45
+ private generation;
46
+ private idCounter;
47
+ private appIdentity;
48
+ /**
49
+ * Commands still running on the device. agent-device takes no abort
50
+ * signal, so a cancelled or timed-out call is only abandoned by its
51
+ * caller; it keeps executing. The next attempt waits for these to settle
52
+ * before it opens anything, so a ghost tap can never land in a retry.
53
+ */
54
+ private readonly inflight;
55
+ constructor(options: AgentDeviceOptions, createClient: ClientFactory);
56
+ /** Whether the manifest declares app restart and state clearing. */
57
+ get managesApp(): boolean;
58
+ /** Whether an attempt is running on this surface right now. */
59
+ get attemptRunning(): boolean;
60
+ /** The live client; INVALID_STATE before init or after dispose. */
61
+ requireClient(): AgentDeviceClient;
62
+ /**
63
+ * Runs one agent-device command under an operation budget and translates
64
+ * its failure. Contributed-fixture methods route through here too, so the
65
+ * device fixture never carries its own error mapping.
66
+ */
67
+ command<T>(label: string, run: (client: AgentDeviceClient) => Promise<T>, signal?: AbortSignal): Promise<T>;
68
+ /** Registers one device command as in flight until it settles. */
69
+ private track;
70
+ /**
71
+ * Waits for every abandoned command to settle, within the caller's
72
+ * budget. A command that never settles fails the attempt launch instead of
73
+ * racing it: the launch timeout is the honest bound on a stuck device.
74
+ */
75
+ private settleInflight;
76
+ init(info: BackendInitInfo): Promise<void>;
77
+ startAttempt(context: BackendAttemptContext): Promise<void>;
78
+ endAttempt(_context: BackendCleanupContext): Promise<void>;
79
+ dispose(context: BackendCleanupContext): Promise<void>;
80
+ /** Opens an app in the session, remembering its identity for the path anchor. */
81
+ openApp(app: string, relaunch: boolean, signal: AbortSignal): Promise<void>;
82
+ private snapshot;
83
+ /**
84
+ * Snapshot for an observation. Without a pinned app, an observation before
85
+ * anything is open is an empty screen rather than a fault: the model's next
86
+ * move is the open tool, and failing the step would take that move away.
87
+ */
88
+ private snapshotOrEmpty;
89
+ private project;
90
+ observe(operation: OperationContext, options?: BackendObserveOptions): Promise<BackendSnapshot>;
91
+ /**
92
+ * The located snapshot joins the current generation instead of replacing
93
+ * it, so an observation's ids stay valid across a `screen` query in the
94
+ * same step. The whole snapshot joins, not only the matches: a later action
95
+ * on a match may need its descendants (`controlOf`).
96
+ */
97
+ locate(expression: LocatorExpression, operation: OperationContext): Promise<readonly SemanticNode[]>;
98
+ private resolveRef;
99
+ private actionTarget;
100
+ /**
101
+ * The node a toggle press must land on. UIKit reports a settings row as a
102
+ * labelled `Switch` spanning the whole row with the real control as an
103
+ * unlabelled `Switch` child at its trailing edge; a press at the row's
104
+ * centre hits the label and changes nothing. The innermost same-role
105
+ * descendant with a ref is the control; a node without one is its own.
106
+ */
107
+ private controlOf;
108
+ perform(ref: NodeRef, action: LocatorAction, operation: OperationContext): Promise<void>;
109
+ /**
110
+ * Keys on a touch surface: Enter submits through the soft keyboard, a
111
+ * single character is typed into the focused field; there is no key event
112
+ * bus to send `Escape` or `Tab` to.
113
+ */
114
+ private pressKey;
115
+ swipe(direction: ScrollDirection, _momentum: Momentum | undefined, operation: OperationContext): Promise<void>;
116
+ back(operation: OperationContext): Promise<void>;
117
+ restart(operation: OperationContext): Promise<void>;
118
+ clearState(operation: OperationContext): Promise<void>;
119
+ /** The path anchor: `app://<app>/<screen title>`; see `screenUrl`. */
120
+ url(operation: OperationContext): Promise<string>;
121
+ /**
122
+ * A redacted screenshot artifact. The device paints secure fields as dots,
123
+ * but the last typed character shows in clear, so every secure node's
124
+ * bounds are painted over before the file is kept. A secure node without
125
+ * bounds cannot be masked, and an image that cannot be redacted is not
126
+ * written at all.
127
+ */
128
+ screenshot(label: string | undefined, operation: OperationContext): Promise<string>;
129
+ /** Redacted screen pixels as a PNG, for the agent's screenshot tool. */
130
+ screenshotBytes(signal?: AbortSignal): Promise<Uint8Array>;
131
+ /** Raw device pixels; the caller owns redaction. */
132
+ private rawScreenshot;
133
+ /**
134
+ * Screenshot with every secure node on the current screen painted over.
135
+ * Observes first so the regions describe the screen the pixels show;
136
+ * throws when a secure field cannot be covered, because an image that may
137
+ * hold a credential must not leave the backend.
138
+ */
139
+ private maskedScreenshot;
140
+ /**
141
+ * Viewport pixels for an observation. Best-effort: a screenshot that cannot
142
+ * be produced or redacted costs the observation its image, not the step.
143
+ */
144
+ private capturePixels;
145
+ }
146
+ //# sourceMappingURL=surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../src/surface.ts"],"names":[],"mappings":"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"}