@ricsam/r5d-browser 0.0.114 → 0.0.115
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/README.md +4 -0
- package/dist/cjs/browser-input.cjs +25 -2
- package/dist/cjs/browser-runtime.cjs +50 -3
- package/dist/cjs/main.cjs +2 -1
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/browser-input.mjs +22 -1
- package/dist/mjs/browser-runtime.mjs +51 -4
- package/dist/mjs/main.mjs +2 -1
- package/dist/mjs/package.json +1 -1
- package/dist/types/browser-input.d.ts +10 -0
- package/dist/types/browser-runtime.d.ts +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,6 +28,10 @@ Agents read pages through `browser_read_page`, an accessibility outline with sta
|
|
|
28
28
|
|
|
29
29
|
Agents running JavaScript in a page can save captured text straight into the active session's artifacts by calling `r5dCreateArtifact(filename, content)`, which takes two strings and must be called before the agent's code returns. Each captured file is written to the session artifacts in r5d.dev, synchronized to every connected worker, and reported back under `$R5D_ROOT/artifacts/$R5D_SESSION_ID`; a single call may create at most 32 files totalling 4 MiB. The function is passed into the agent's code rather than assigned to `window`, so pages can neither call it nor use it to detect automation.
|
|
30
30
|
|
|
31
|
+
For responsive testing that needs an existing login (for example, an app using Google login), agents can call `browser_set_viewport` with `{ tabId, width: 390, height: 844 }`. Both dimensions must be integers from 1 to 4096 CSS pixels. The override is scoped to that tab, even in a shared window: it does not resize the OS window or affect other tabs. It preserves the profile, user agent, touch support, and device pixel ratio; this is layout sizing, not mobile-device emulation. It adds no Chrome launch flags or webdriver spoofing; `navigator.webdriver` remains natively `false`.
|
|
32
|
+
|
|
33
|
+
The viewport survives navigation, reloads, and r5d.dev control-connection reconnects until the agent calls `browser_set_viewport` with `{ tabId, reset: true }`, closes the tab, or exits the browser. Reset restores sizing from the current OS window; omit width/height when resetting. The tool returns the actual width and height. Re-read the page or capture a screenshot after resizing because old coordinates are stale, and reset when testing is finished. To apply a size before the first page load, open `about:blank`, set its viewport, then navigate. An outdated browser client returns an update-and-restart instruction for this tool.
|
|
34
|
+
|
|
31
35
|
As an escape hatch, agents can create loopback-only TCP port forwards from this Mac to the worker bound to a chat when a local flow specifically needs this browser's authenticated state or human interaction, such as testing Google OAuth. Ordinary local application testing should use Playwright directly on the worker without a forward. For example, a forward can map Chrome's `localhost:4323` to `127.0.0.1:3232` on that worker. The relay preserves raw TCP traffic, including HTTP, HTTPS, WebSockets, HMR, and SSE; it never exposes a public listener or permits an arbitrary target host.
|
|
32
36
|
|
|
33
37
|
Port forwards remain active across agent turns and r5d.dev control-connection reconnects. They are owned by the running `r5d-browser` process, so restarting that process ends them. Agents can list and stop forwards, and the user can inspect or stop them from Settings.
|
|
@@ -18,7 +18,9 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var browser_input_exports = {};
|
|
20
20
|
__export(browser_input_exports, {
|
|
21
|
-
|
|
21
|
+
MAX_VIEWPORT_DIMENSION: () => MAX_VIEWPORT_DIMENSION,
|
|
22
|
+
normalizeBrowserInput: () => normalizeBrowserInput,
|
|
23
|
+
parseViewportInput: () => parseViewportInput
|
|
22
24
|
});
|
|
23
25
|
module.exports = __toCommonJS(browser_input_exports);
|
|
24
26
|
const browserInputFields = {
|
|
@@ -28,6 +30,7 @@ const browserInputFields = {
|
|
|
28
30
|
open_tab: { required: [], optional: ["url", "disposition"] },
|
|
29
31
|
close_tab: { required: ["tabId"], optional: [] },
|
|
30
32
|
navigate: { required: ["tabId", "url"], optional: [] },
|
|
33
|
+
set_viewport: { required: ["tabId"], optional: ["width", "height", "reset"] },
|
|
31
34
|
read_page: { required: ["tabId"], optional: ["depth", "maxChars"] },
|
|
32
35
|
screenshot: { required: ["tabId"], optional: ["fullPage"] },
|
|
33
36
|
move_mouse: { required: ["tabId", "x", "y"], optional: [] },
|
|
@@ -42,6 +45,24 @@ const browserInputFields = {
|
|
|
42
45
|
list_port_forwards: { required: [], optional: [] },
|
|
43
46
|
stop_port_forward: { required: ["forwardId"], optional: [] }
|
|
44
47
|
};
|
|
48
|
+
const MAX_VIEWPORT_DIMENSION = 4096;
|
|
49
|
+
function parseViewportInput(input) {
|
|
50
|
+
if (input.reset !== void 0 && typeof input.reset !== "boolean") throw new Error("set_viewport reset must be a boolean.");
|
|
51
|
+
if (input.reset === true) {
|
|
52
|
+
if (input.width !== void 0 || input.height !== void 0)
|
|
53
|
+
throw new Error("set_viewport accepts width/height or reset: true, not both.");
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const { width, height } = input;
|
|
57
|
+
for (const [name, value] of Object.entries({ width, height })) {
|
|
58
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 1 || value > MAX_VIEWPORT_DIMENSION) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
`set_viewport requires ${name} to be an integer from 1 to ${MAX_VIEWPORT_DIMENSION} CSS pixels, or reset: true without dimensions.`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return { width, height };
|
|
65
|
+
}
|
|
45
66
|
function normalizeBrowserInput(action, input) {
|
|
46
67
|
const fields = browserInputFields[action];
|
|
47
68
|
for (const key of fields.required) {
|
|
@@ -55,5 +76,7 @@ function normalizeBrowserInput(action, input) {
|
|
|
55
76
|
}
|
|
56
77
|
// Annotate the CommonJS export names for ESM import in node:
|
|
57
78
|
0 && (module.exports = {
|
|
58
|
-
|
|
79
|
+
MAX_VIEWPORT_DIMENSION,
|
|
80
|
+
normalizeBrowserInput,
|
|
81
|
+
parseViewportInput
|
|
59
82
|
});
|
|
@@ -84,6 +84,7 @@ class BrowserRuntime {
|
|
|
84
84
|
ids = /* @__PURE__ */ new WeakMap();
|
|
85
85
|
pages = /* @__PURE__ */ new Map();
|
|
86
86
|
cursor = /* @__PURE__ */ new Map();
|
|
87
|
+
viewportSessions = /* @__PURE__ */ new Map();
|
|
87
88
|
downloadSaveQueue = Promise.resolve();
|
|
88
89
|
track(page) {
|
|
89
90
|
const existing = this.ids.get(page);
|
|
@@ -100,6 +101,7 @@ class BrowserRuntime {
|
|
|
100
101
|
page.once("close", () => {
|
|
101
102
|
this.pages.delete(id);
|
|
102
103
|
this.cursor.delete(id);
|
|
104
|
+
this.viewportSessions.delete(id);
|
|
103
105
|
});
|
|
104
106
|
return id;
|
|
105
107
|
}
|
|
@@ -235,6 +237,34 @@ class BrowserRuntime {
|
|
|
235
237
|
async drainDownloads() {
|
|
236
238
|
await this.downloadSaveQueue;
|
|
237
239
|
}
|
|
240
|
+
async setViewport(page, tabId, viewport) {
|
|
241
|
+
const existing = this.viewportSessions.get(tabId);
|
|
242
|
+
if (viewport) {
|
|
243
|
+
const cdp = existing ?? await this.context.newCDPSession(page);
|
|
244
|
+
try {
|
|
245
|
+
await cdp.send("Emulation.setDeviceMetricsOverride", { ...viewport, deviceScaleFactor: 0, mobile: false });
|
|
246
|
+
this.viewportSessions.set(tabId, cdp);
|
|
247
|
+
} catch (error) {
|
|
248
|
+
if (!existing) await cdp.detach().catch(() => void 0);
|
|
249
|
+
throw error;
|
|
250
|
+
}
|
|
251
|
+
} else if (existing) {
|
|
252
|
+
await existing.send("Emulation.clearDeviceMetricsOverride");
|
|
253
|
+
this.viewportSessions.delete(tabId);
|
|
254
|
+
await existing.detach().catch(() => void 0);
|
|
255
|
+
}
|
|
256
|
+
this.cursor.delete(tabId);
|
|
257
|
+
if (viewport) {
|
|
258
|
+
const ready = await page.waitForFunction(
|
|
259
|
+
({ width, height }) => window.innerWidth === width && window.innerHeight === height,
|
|
260
|
+
viewport,
|
|
261
|
+
{ timeout: 5e3 }
|
|
262
|
+
);
|
|
263
|
+
await ready.dispose();
|
|
264
|
+
}
|
|
265
|
+
const actual = await page.evaluate(() => ({ width: window.innerWidth, height: window.innerHeight }));
|
|
266
|
+
return { tabId, ...actual, reset: viewport === null };
|
|
267
|
+
}
|
|
238
268
|
async execute(action, input) {
|
|
239
269
|
input = (0, import_browser_input.normalizeBrowserInput)(action, input);
|
|
240
270
|
if (action === "list_tabs") return { tabs: await this.listTabs() };
|
|
@@ -275,6 +305,8 @@ class BrowserRuntime {
|
|
|
275
305
|
case "navigate":
|
|
276
306
|
await this.gotoSettled(page, String(input.url));
|
|
277
307
|
return { tab: await this.tabInfo(page) };
|
|
308
|
+
case "set_viewport":
|
|
309
|
+
return await this.setViewport(page, tabId, (0, import_browser_input.parseViewportInput)(input));
|
|
278
310
|
case "read_page": {
|
|
279
311
|
const maxChars = clampInt(input.maxChars, 1e3, 2e5, 5e4);
|
|
280
312
|
const depth = input.depth === void 0 ? void 0 : clampInt(input.depth, 1, 50, 50);
|
|
@@ -314,13 +346,28 @@ class BrowserRuntime {
|
|
|
314
346
|
case "screenshot": {
|
|
315
347
|
if (input.fullPage === true) {
|
|
316
348
|
const metrics = await page.evaluate(() => ({
|
|
317
|
-
|
|
318
|
-
|
|
349
|
+
// Match Playwright's full-page bounds, which exclude scrollbar gutters.
|
|
350
|
+
docWidth: Math.max(
|
|
351
|
+
document.documentElement.scrollWidth,
|
|
352
|
+
document.documentElement.offsetWidth,
|
|
353
|
+
document.documentElement.clientWidth,
|
|
354
|
+
document.body?.scrollWidth ?? 0,
|
|
355
|
+
document.body?.offsetWidth ?? 0,
|
|
356
|
+
document.body?.clientWidth ?? 0
|
|
357
|
+
),
|
|
358
|
+
docHeight: Math.max(
|
|
359
|
+
document.documentElement.scrollHeight,
|
|
360
|
+
document.documentElement.offsetHeight,
|
|
361
|
+
document.documentElement.clientHeight,
|
|
362
|
+
document.body?.scrollHeight ?? 0,
|
|
363
|
+
document.body?.offsetHeight ?? 0,
|
|
364
|
+
document.body?.clientHeight ?? 0
|
|
365
|
+
)
|
|
319
366
|
}));
|
|
320
367
|
const width = Math.min(metrics.docWidth, MAX_FULL_PAGE_WIDTH);
|
|
321
368
|
const height = Math.min(metrics.docHeight, MAX_FULL_PAGE_HEIGHT);
|
|
322
369
|
const truncated = metrics.docHeight > MAX_FULL_PAGE_HEIGHT || metrics.docWidth > MAX_FULL_PAGE_WIDTH;
|
|
323
|
-
const bytes2 = truncated ? await page.screenshot({ type: "png", scale: "css", timeout: 15e3, clip: { x: 0, y: 0, width, height } }) : await page.screenshot({ type: "png", scale: "css", timeout: 15e3, fullPage: true });
|
|
370
|
+
const bytes2 = truncated ? await page.screenshot({ type: "png", scale: "css", timeout: 15e3, fullPage: true, clip: { x: 0, y: 0, width, height } }) : await page.screenshot({ type: "png", scale: "css", timeout: 15e3, fullPage: true });
|
|
324
371
|
return { base64: bytes2.toString("base64"), width, height, fullPage: true, pageHeight: metrics.docHeight, truncated };
|
|
325
372
|
}
|
|
326
373
|
const bytes = await page.screenshot({ type: "png", scale: "css" });
|
package/dist/cjs/main.cjs
CHANGED
package/dist/cjs/package.json
CHANGED
|
@@ -5,6 +5,7 @@ const browserInputFields = {
|
|
|
5
5
|
open_tab: { required: [], optional: ["url", "disposition"] },
|
|
6
6
|
close_tab: { required: ["tabId"], optional: [] },
|
|
7
7
|
navigate: { required: ["tabId", "url"], optional: [] },
|
|
8
|
+
set_viewport: { required: ["tabId"], optional: ["width", "height", "reset"] },
|
|
8
9
|
read_page: { required: ["tabId"], optional: ["depth", "maxChars"] },
|
|
9
10
|
screenshot: { required: ["tabId"], optional: ["fullPage"] },
|
|
10
11
|
move_mouse: { required: ["tabId", "x", "y"], optional: [] },
|
|
@@ -19,6 +20,24 @@ const browserInputFields = {
|
|
|
19
20
|
list_port_forwards: { required: [], optional: [] },
|
|
20
21
|
stop_port_forward: { required: ["forwardId"], optional: [] }
|
|
21
22
|
};
|
|
23
|
+
const MAX_VIEWPORT_DIMENSION = 4096;
|
|
24
|
+
function parseViewportInput(input) {
|
|
25
|
+
if (input.reset !== void 0 && typeof input.reset !== "boolean") throw new Error("set_viewport reset must be a boolean.");
|
|
26
|
+
if (input.reset === true) {
|
|
27
|
+
if (input.width !== void 0 || input.height !== void 0)
|
|
28
|
+
throw new Error("set_viewport accepts width/height or reset: true, not both.");
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const { width, height } = input;
|
|
32
|
+
for (const [name, value] of Object.entries({ width, height })) {
|
|
33
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 1 || value > MAX_VIEWPORT_DIMENSION) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`set_viewport requires ${name} to be an integer from 1 to ${MAX_VIEWPORT_DIMENSION} CSS pixels, or reset: true without dimensions.`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return { width, height };
|
|
40
|
+
}
|
|
22
41
|
function normalizeBrowserInput(action, input) {
|
|
23
42
|
const fields = browserInputFields[action];
|
|
24
43
|
for (const key of fields.required) {
|
|
@@ -31,5 +50,7 @@ function normalizeBrowserInput(action, input) {
|
|
|
31
50
|
return normalized;
|
|
32
51
|
}
|
|
33
52
|
export {
|
|
34
|
-
|
|
53
|
+
MAX_VIEWPORT_DIMENSION,
|
|
54
|
+
normalizeBrowserInput,
|
|
55
|
+
parseViewportInput
|
|
35
56
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { normalizeBrowserInput } from "./browser-input.mjs";
|
|
3
|
+
import { normalizeBrowserInput, parseViewportInput } from "./browser-input.mjs";
|
|
4
4
|
import { passwordSafeAriaSnapshot } from "./password-safe-snapshot.mjs";
|
|
5
5
|
const MAX_DOWNLOAD_CHUNK_BYTES = 1024 * 1024;
|
|
6
6
|
const MAX_RUN_JS_RESULT_BYTES = 1024 * 1024;
|
|
@@ -51,6 +51,7 @@ class BrowserRuntime {
|
|
|
51
51
|
ids = /* @__PURE__ */ new WeakMap();
|
|
52
52
|
pages = /* @__PURE__ */ new Map();
|
|
53
53
|
cursor = /* @__PURE__ */ new Map();
|
|
54
|
+
viewportSessions = /* @__PURE__ */ new Map();
|
|
54
55
|
downloadSaveQueue = Promise.resolve();
|
|
55
56
|
track(page) {
|
|
56
57
|
const existing = this.ids.get(page);
|
|
@@ -67,6 +68,7 @@ class BrowserRuntime {
|
|
|
67
68
|
page.once("close", () => {
|
|
68
69
|
this.pages.delete(id);
|
|
69
70
|
this.cursor.delete(id);
|
|
71
|
+
this.viewportSessions.delete(id);
|
|
70
72
|
});
|
|
71
73
|
return id;
|
|
72
74
|
}
|
|
@@ -202,6 +204,34 @@ class BrowserRuntime {
|
|
|
202
204
|
async drainDownloads() {
|
|
203
205
|
await this.downloadSaveQueue;
|
|
204
206
|
}
|
|
207
|
+
async setViewport(page, tabId, viewport) {
|
|
208
|
+
const existing = this.viewportSessions.get(tabId);
|
|
209
|
+
if (viewport) {
|
|
210
|
+
const cdp = existing ?? await this.context.newCDPSession(page);
|
|
211
|
+
try {
|
|
212
|
+
await cdp.send("Emulation.setDeviceMetricsOverride", { ...viewport, deviceScaleFactor: 0, mobile: false });
|
|
213
|
+
this.viewportSessions.set(tabId, cdp);
|
|
214
|
+
} catch (error) {
|
|
215
|
+
if (!existing) await cdp.detach().catch(() => void 0);
|
|
216
|
+
throw error;
|
|
217
|
+
}
|
|
218
|
+
} else if (existing) {
|
|
219
|
+
await existing.send("Emulation.clearDeviceMetricsOverride");
|
|
220
|
+
this.viewportSessions.delete(tabId);
|
|
221
|
+
await existing.detach().catch(() => void 0);
|
|
222
|
+
}
|
|
223
|
+
this.cursor.delete(tabId);
|
|
224
|
+
if (viewport) {
|
|
225
|
+
const ready = await page.waitForFunction(
|
|
226
|
+
({ width, height }) => window.innerWidth === width && window.innerHeight === height,
|
|
227
|
+
viewport,
|
|
228
|
+
{ timeout: 5e3 }
|
|
229
|
+
);
|
|
230
|
+
await ready.dispose();
|
|
231
|
+
}
|
|
232
|
+
const actual = await page.evaluate(() => ({ width: window.innerWidth, height: window.innerHeight }));
|
|
233
|
+
return { tabId, ...actual, reset: viewport === null };
|
|
234
|
+
}
|
|
205
235
|
async execute(action, input) {
|
|
206
236
|
input = normalizeBrowserInput(action, input);
|
|
207
237
|
if (action === "list_tabs") return { tabs: await this.listTabs() };
|
|
@@ -242,6 +272,8 @@ class BrowserRuntime {
|
|
|
242
272
|
case "navigate":
|
|
243
273
|
await this.gotoSettled(page, String(input.url));
|
|
244
274
|
return { tab: await this.tabInfo(page) };
|
|
275
|
+
case "set_viewport":
|
|
276
|
+
return await this.setViewport(page, tabId, parseViewportInput(input));
|
|
245
277
|
case "read_page": {
|
|
246
278
|
const maxChars = clampInt(input.maxChars, 1e3, 2e5, 5e4);
|
|
247
279
|
const depth = input.depth === void 0 ? void 0 : clampInt(input.depth, 1, 50, 50);
|
|
@@ -281,13 +313,28 @@ class BrowserRuntime {
|
|
|
281
313
|
case "screenshot": {
|
|
282
314
|
if (input.fullPage === true) {
|
|
283
315
|
const metrics = await page.evaluate(() => ({
|
|
284
|
-
|
|
285
|
-
|
|
316
|
+
// Match Playwright's full-page bounds, which exclude scrollbar gutters.
|
|
317
|
+
docWidth: Math.max(
|
|
318
|
+
document.documentElement.scrollWidth,
|
|
319
|
+
document.documentElement.offsetWidth,
|
|
320
|
+
document.documentElement.clientWidth,
|
|
321
|
+
document.body?.scrollWidth ?? 0,
|
|
322
|
+
document.body?.offsetWidth ?? 0,
|
|
323
|
+
document.body?.clientWidth ?? 0
|
|
324
|
+
),
|
|
325
|
+
docHeight: Math.max(
|
|
326
|
+
document.documentElement.scrollHeight,
|
|
327
|
+
document.documentElement.offsetHeight,
|
|
328
|
+
document.documentElement.clientHeight,
|
|
329
|
+
document.body?.scrollHeight ?? 0,
|
|
330
|
+
document.body?.offsetHeight ?? 0,
|
|
331
|
+
document.body?.clientHeight ?? 0
|
|
332
|
+
)
|
|
286
333
|
}));
|
|
287
334
|
const width = Math.min(metrics.docWidth, MAX_FULL_PAGE_WIDTH);
|
|
288
335
|
const height = Math.min(metrics.docHeight, MAX_FULL_PAGE_HEIGHT);
|
|
289
336
|
const truncated = metrics.docHeight > MAX_FULL_PAGE_HEIGHT || metrics.docWidth > MAX_FULL_PAGE_WIDTH;
|
|
290
|
-
const bytes2 = truncated ? await page.screenshot({ type: "png", scale: "css", timeout: 15e3, clip: { x: 0, y: 0, width, height } }) : await page.screenshot({ type: "png", scale: "css", timeout: 15e3, fullPage: true });
|
|
337
|
+
const bytes2 = truncated ? await page.screenshot({ type: "png", scale: "css", timeout: 15e3, fullPage: true, clip: { x: 0, y: 0, width, height } }) : await page.screenshot({ type: "png", scale: "css", timeout: 15e3, fullPage: true });
|
|
291
338
|
return { base64: bytes2.toString("base64"), width, height, fullPage: true, pageHeight: metrics.docHeight, truncated };
|
|
292
339
|
}
|
|
293
340
|
const bytes = await page.screenshot({ type: "png", scale: "css" });
|
package/dist/mjs/main.mjs
CHANGED
package/dist/mjs/package.json
CHANGED
|
@@ -23,6 +23,10 @@ declare const browserInputFields: {
|
|
|
23
23
|
required: string[];
|
|
24
24
|
optional: never[];
|
|
25
25
|
};
|
|
26
|
+
set_viewport: {
|
|
27
|
+
required: string[];
|
|
28
|
+
optional: string[];
|
|
29
|
+
};
|
|
26
30
|
read_page: {
|
|
27
31
|
required: string[];
|
|
28
32
|
optional: string[];
|
|
@@ -77,5 +81,11 @@ declare const browserInputFields: {
|
|
|
77
81
|
};
|
|
78
82
|
};
|
|
79
83
|
export type BrowserInputAction = keyof typeof browserInputFields;
|
|
84
|
+
export declare const MAX_VIEWPORT_DIMENSION = 4096;
|
|
85
|
+
export type BrowserViewport = {
|
|
86
|
+
width: number;
|
|
87
|
+
height: number;
|
|
88
|
+
};
|
|
89
|
+
export declare function parseViewportInput(input: Readonly<Record<string, unknown>>): BrowserViewport | null;
|
|
80
90
|
export declare function normalizeBrowserInput(action: BrowserInputAction, input: Readonly<Record<string, unknown>>): Record<string, unknown>;
|
|
81
91
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BrowserContext } from "playwright-core";
|
|
2
|
-
export type BrowserAction = "list_tabs" | "list_downloads" | "get_download" | "open_tab" | "close_tab" | "navigate" | "read_page" | "screenshot" | "move_mouse" | "mouse_click" | "scroll" | "wait_for" | "form_input" | "keyboard" | "keyboard_type" | "run_js";
|
|
2
|
+
export type BrowserAction = "list_tabs" | "list_downloads" | "get_download" | "open_tab" | "close_tab" | "navigate" | "set_viewport" | "read_page" | "screenshot" | "move_mouse" | "mouse_click" | "scroll" | "wait_for" | "form_input" | "keyboard" | "keyboard_type" | "run_js";
|
|
3
3
|
export type TabInfo = {
|
|
4
4
|
tabId: string;
|
|
5
5
|
windowId: string;
|
|
@@ -18,6 +18,7 @@ export declare class BrowserRuntime {
|
|
|
18
18
|
private readonly ids;
|
|
19
19
|
private readonly pages;
|
|
20
20
|
private readonly cursor;
|
|
21
|
+
private readonly viewportSessions;
|
|
21
22
|
private downloadSaveQueue;
|
|
22
23
|
constructor(context: BrowserContext, downloadsPath: string);
|
|
23
24
|
private track;
|
|
@@ -34,5 +35,6 @@ export declare class BrowserRuntime {
|
|
|
34
35
|
private tabInfo;
|
|
35
36
|
listTabs(): Promise<TabInfo[]>;
|
|
36
37
|
drainDownloads(): Promise<void>;
|
|
38
|
+
private setViewport;
|
|
37
39
|
execute(action: BrowserAction, input: Record<string, unknown>): Promise<unknown>;
|
|
38
40
|
}
|