browser-pilot 0.0.13 → 0.0.15
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 +82 -617
- package/dist/actions.cjs +1438 -17
- package/dist/actions.d.cts +21 -3
- package/dist/actions.d.ts +21 -3
- package/dist/actions.mjs +1 -1
- package/dist/browser-MEWT75IB.mjs +11 -0
- package/dist/browser.cjs +1583 -22
- package/dist/browser.d.cts +12 -3
- package/dist/browser.d.ts +12 -3
- package/dist/browser.mjs +3 -3
- package/dist/cdp.cjs +36 -3
- package/dist/cdp.d.cts +1 -1
- package/dist/cdp.d.ts +1 -1
- package/dist/cdp.mjs +3 -1
- package/dist/{chunk-A2ZRAEO3.mjs → chunk-7YVCOL2W.mjs} +1428 -17
- package/dist/chunk-BVZALQT4.mjs +303 -0
- package/dist/chunk-DTVRFXKI.mjs +35 -0
- package/dist/{chunk-HP6R3W32.mjs → chunk-LCNFBXB5.mjs} +33 -6
- package/dist/chunk-LUGLEMVR.mjs +11 -0
- package/dist/chunk-USYSHCI3.mjs +8640 -0
- package/dist/chunk-WPNW23CE.mjs +466 -0
- package/dist/{chunk-VDAMDOS6.mjs → chunk-ZAXQ5OTV.mjs} +151 -7
- package/dist/cli.mjs +3225 -8434
- package/dist/{client-DRqxBdHv.d.ts → client-B5QBRgIy.d.cts} +10 -6
- package/dist/{client-DRqxBdHv.d.cts → client-B5QBRgIy.d.ts} +10 -6
- package/dist/client-JWWZWO6L.mjs +12 -0
- package/dist/index.cjs +1629 -24
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.mjs +3 -3
- package/dist/page-XPS6IC6V.mjs +7 -0
- package/dist/transport-WHEBAZUP.mjs +83 -0
- package/dist/{types-CzgQjai9.d.ts → types-C9ySEdOX.d.cts} +78 -4
- package/dist/{types-BXMGFtnB.d.cts → types-Cvvf0oGu.d.ts} +78 -4
- package/package.json +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
createCDPClient
|
|
3
|
-
|
|
2
|
+
createCDPClient,
|
|
3
|
+
stringifyUnknown
|
|
4
|
+
} from "./chunk-BVZALQT4.mjs";
|
|
4
5
|
import {
|
|
5
6
|
createProvider
|
|
6
7
|
} from "./chunk-BRAFQUMG.mjs";
|
|
@@ -11,7 +12,7 @@ import {
|
|
|
11
12
|
TimeoutError,
|
|
12
13
|
ensureActionable,
|
|
13
14
|
generateHints
|
|
14
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-7YVCOL2W.mjs";
|
|
15
16
|
|
|
16
17
|
// src/audio/encoding.ts
|
|
17
18
|
function bufferToBase64(data) {
|
|
@@ -142,6 +143,10 @@ async function grantAudioPermissions(cdp, origin) {
|
|
|
142
143
|
await cdp.send("Page.addScriptToEvaluateOnNewDocument", {
|
|
143
144
|
source: PERMISSIONS_OVERRIDE_SCRIPT
|
|
144
145
|
});
|
|
146
|
+
await cdp.send("Runtime.evaluate", {
|
|
147
|
+
expression: PERMISSIONS_OVERRIDE_SCRIPT,
|
|
148
|
+
awaitPromise: false
|
|
149
|
+
});
|
|
145
150
|
}
|
|
146
151
|
var PERMISSIONS_OVERRIDE_SCRIPT = `
|
|
147
152
|
(function() {
|
|
@@ -2327,6 +2332,9 @@ var Page = class {
|
|
|
2327
2332
|
brokenFrame = null;
|
|
2328
2333
|
/** Last matched selector from findElement (for selectorUsed tracking) */
|
|
2329
2334
|
_lastMatchedSelector;
|
|
2335
|
+
_lastActionCoordinates = null;
|
|
2336
|
+
_lastActionBoundingBox = null;
|
|
2337
|
+
_lastActionTargetMetadata = null;
|
|
2330
2338
|
/** Last snapshot for stale ref recovery */
|
|
2331
2339
|
lastSnapshot;
|
|
2332
2340
|
/** Audio input controller (lazy-initialized) */
|
|
@@ -2358,6 +2366,76 @@ var Page = class {
|
|
|
2358
2366
|
getLastMatchedSelector() {
|
|
2359
2367
|
return this._lastMatchedSelector;
|
|
2360
2368
|
}
|
|
2369
|
+
async getActionTargetMetadata(identifiers) {
|
|
2370
|
+
try {
|
|
2371
|
+
const objectId = identifiers.objectId ?? (identifiers.nodeId ? await this.resolveObjectId(identifiers.nodeId) : void 0);
|
|
2372
|
+
if (!objectId) return null;
|
|
2373
|
+
const response = await this.cdp.send("Runtime.callFunctionOn", {
|
|
2374
|
+
objectId,
|
|
2375
|
+
functionDeclaration: `function() {
|
|
2376
|
+
const tagName = this.tagName?.toLowerCase?.() || '';
|
|
2377
|
+
const inputType =
|
|
2378
|
+
tagName === 'input' && typeof this.type === 'string' ? this.type.toLowerCase() : '';
|
|
2379
|
+
const autocomplete =
|
|
2380
|
+
typeof this.autocomplete === 'string' ? this.autocomplete.toLowerCase() : '';
|
|
2381
|
+
return { tagName, inputType, autocomplete };
|
|
2382
|
+
}`,
|
|
2383
|
+
returnByValue: true
|
|
2384
|
+
});
|
|
2385
|
+
return response.result.value ?? null;
|
|
2386
|
+
} catch {
|
|
2387
|
+
return null;
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
async getElementPosition(identifiers) {
|
|
2391
|
+
try {
|
|
2392
|
+
const { quads } = await this.cdp.send(
|
|
2393
|
+
"DOM.getContentQuads",
|
|
2394
|
+
identifiers
|
|
2395
|
+
);
|
|
2396
|
+
if (quads?.length > 0) {
|
|
2397
|
+
const q = quads[0];
|
|
2398
|
+
const minX = Math.min(q[0], q[2], q[4], q[6]);
|
|
2399
|
+
const maxX = Math.max(q[0], q[2], q[4], q[6]);
|
|
2400
|
+
const minY = Math.min(q[1], q[3], q[5], q[7]);
|
|
2401
|
+
const maxY = Math.max(q[1], q[3], q[5], q[7]);
|
|
2402
|
+
return {
|
|
2403
|
+
center: { x: (minX + maxX) / 2, y: (minY + maxY) / 2 },
|
|
2404
|
+
bbox: { x: minX, y: minY, width: maxX - minX, height: maxY - minY }
|
|
2405
|
+
};
|
|
2406
|
+
}
|
|
2407
|
+
} catch {
|
|
2408
|
+
}
|
|
2409
|
+
if (identifiers.nodeId) {
|
|
2410
|
+
const box = await this.getBoxModel(identifiers.nodeId);
|
|
2411
|
+
if (box) {
|
|
2412
|
+
return {
|
|
2413
|
+
center: { x: box.content[0] + box.width / 2, y: box.content[1] + box.height / 2 },
|
|
2414
|
+
bbox: { x: box.content[0], y: box.content[1], width: box.width, height: box.height }
|
|
2415
|
+
};
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
return null;
|
|
2419
|
+
}
|
|
2420
|
+
setLastActionPosition(coords, bbox) {
|
|
2421
|
+
this._lastActionCoordinates = coords;
|
|
2422
|
+
this._lastActionBoundingBox = bbox;
|
|
2423
|
+
}
|
|
2424
|
+
getLastActionCoordinates() {
|
|
2425
|
+
return this._lastActionCoordinates;
|
|
2426
|
+
}
|
|
2427
|
+
getLastActionBoundingBox() {
|
|
2428
|
+
return this._lastActionBoundingBox;
|
|
2429
|
+
}
|
|
2430
|
+
getLastActionTargetMetadata() {
|
|
2431
|
+
return this._lastActionTargetMetadata;
|
|
2432
|
+
}
|
|
2433
|
+
/** Reset position tracking (call before each executor step) */
|
|
2434
|
+
resetLastActionPosition() {
|
|
2435
|
+
this._lastActionCoordinates = null;
|
|
2436
|
+
this._lastActionBoundingBox = null;
|
|
2437
|
+
this._lastActionTargetMetadata = null;
|
|
2438
|
+
}
|
|
2361
2439
|
/**
|
|
2362
2440
|
* Initialize the page (enable required CDP domains)
|
|
2363
2441
|
*/
|
|
@@ -2525,6 +2603,14 @@ var Page = class {
|
|
|
2525
2603
|
const quad = quads[0];
|
|
2526
2604
|
clickX = (quad[0] + quad[2] + quad[4] + quad[6]) / 4;
|
|
2527
2605
|
clickY = (quad[1] + quad[3] + quad[5] + quad[7]) / 4;
|
|
2606
|
+
const minX = Math.min(quad[0], quad[2], quad[4], quad[6]);
|
|
2607
|
+
const maxX = Math.max(quad[0], quad[2], quad[4], quad[6]);
|
|
2608
|
+
const minY = Math.min(quad[1], quad[3], quad[5], quad[7]);
|
|
2609
|
+
const maxY = Math.max(quad[1], quad[3], quad[5], quad[7]);
|
|
2610
|
+
this.setLastActionPosition(
|
|
2611
|
+
{ x: clickX, y: clickY },
|
|
2612
|
+
{ x: minX, y: minY, width: maxX - minX, height: maxY - minY }
|
|
2613
|
+
);
|
|
2528
2614
|
} else {
|
|
2529
2615
|
throw new Error("No quads");
|
|
2530
2616
|
}
|
|
@@ -2533,6 +2619,10 @@ var Page = class {
|
|
|
2533
2619
|
if (!box) throw new Error("Could not get element position");
|
|
2534
2620
|
clickX = box.content[0] + box.width / 2;
|
|
2535
2621
|
clickY = box.content[1] + box.height / 2;
|
|
2622
|
+
this.setLastActionPosition(
|
|
2623
|
+
{ x: clickX, y: clickY },
|
|
2624
|
+
{ x: box.content[0], y: box.content[1], width: box.width, height: box.height }
|
|
2625
|
+
);
|
|
2536
2626
|
}
|
|
2537
2627
|
const hitTargetCoordinates = this.currentFrame ? void 0 : { x: clickX, y: clickY };
|
|
2538
2628
|
const HIT_TARGET_RETRIES = 3;
|
|
@@ -2583,13 +2673,20 @@ var Page = class {
|
|
|
2583
2673
|
if (options.optional) return false;
|
|
2584
2674
|
throw e;
|
|
2585
2675
|
}
|
|
2676
|
+
const fillPos = await this.getElementPosition({ nodeId: element.nodeId });
|
|
2677
|
+
if (fillPos) this.setLastActionPosition(fillPos.center, fillPos.bbox);
|
|
2586
2678
|
const tagInfo = await this.cdp.send("Runtime.callFunctionOn", {
|
|
2587
2679
|
objectId,
|
|
2588
2680
|
functionDeclaration: `function() {
|
|
2589
|
-
return {
|
|
2681
|
+
return {
|
|
2682
|
+
tagName: this.tagName?.toLowerCase() || '',
|
|
2683
|
+
inputType: (this.type || '').toLowerCase(),
|
|
2684
|
+
autocomplete: typeof this.autocomplete === 'string' ? this.autocomplete.toLowerCase() : '',
|
|
2685
|
+
};
|
|
2590
2686
|
}`,
|
|
2591
2687
|
returnByValue: true
|
|
2592
2688
|
});
|
|
2689
|
+
this._lastActionTargetMetadata = tagInfo.result.value;
|
|
2593
2690
|
const { tagName, inputType } = tagInfo.result.value;
|
|
2594
2691
|
const specialInputTypes = /* @__PURE__ */ new Set([
|
|
2595
2692
|
"date",
|
|
@@ -2671,6 +2768,9 @@ var Page = class {
|
|
|
2671
2768
|
if (options.optional) return false;
|
|
2672
2769
|
throw e;
|
|
2673
2770
|
}
|
|
2771
|
+
const typePos = await this.getElementPosition({ nodeId: element.nodeId });
|
|
2772
|
+
if (typePos) this.setLastActionPosition(typePos.center, typePos.bbox);
|
|
2773
|
+
this._lastActionTargetMetadata = await this.getActionTargetMetadata({ objectId });
|
|
2674
2774
|
await this.cdp.send("DOM.focus", { nodeId: element.nodeId });
|
|
2675
2775
|
for (const char of text) {
|
|
2676
2776
|
const def = US_KEYBOARD[char];
|
|
@@ -2750,6 +2850,9 @@ var Page = class {
|
|
|
2750
2850
|
if (options.optional) return false;
|
|
2751
2851
|
throw e;
|
|
2752
2852
|
}
|
|
2853
|
+
const selectPos = await this.getElementPosition({ nodeId: element.nodeId });
|
|
2854
|
+
if (selectPos) this.setLastActionPosition(selectPos.center, selectPos.bbox);
|
|
2855
|
+
this._lastActionTargetMetadata = await this.getActionTargetMetadata({ objectId });
|
|
2753
2856
|
const metadata = await this.getNativeSelectMetadata(objectId, values);
|
|
2754
2857
|
if (!metadata.isSelect) {
|
|
2755
2858
|
throw new Error("select() target must be a native <select> element");
|
|
@@ -2886,6 +2989,8 @@ var Page = class {
|
|
|
2886
2989
|
if (options.optional) return false;
|
|
2887
2990
|
throw e;
|
|
2888
2991
|
}
|
|
2992
|
+
const checkPos = await this.getElementPosition({ nodeId: element.nodeId });
|
|
2993
|
+
if (checkPos) this.setLastActionPosition(checkPos.center, checkPos.bbox);
|
|
2889
2994
|
const before = await this.cdp.send("Runtime.callFunctionOn", {
|
|
2890
2995
|
objectId: object.objectId,
|
|
2891
2996
|
functionDeclaration: "function() { return !!this.checked; }",
|
|
@@ -2934,6 +3039,8 @@ var Page = class {
|
|
|
2934
3039
|
if (options.optional) return false;
|
|
2935
3040
|
throw e;
|
|
2936
3041
|
}
|
|
3042
|
+
const uncheckPos = await this.getElementPosition({ nodeId: element.nodeId });
|
|
3043
|
+
if (uncheckPos) this.setLastActionPosition(uncheckPos.center, uncheckPos.bbox);
|
|
2937
3044
|
const isRadio = await this.cdp.send(
|
|
2938
3045
|
"Runtime.callFunctionOn",
|
|
2939
3046
|
{
|
|
@@ -2989,6 +3096,8 @@ var Page = class {
|
|
|
2989
3096
|
throw new ElementNotFoundError(selector, hints);
|
|
2990
3097
|
}
|
|
2991
3098
|
const objectId = await this.resolveObjectId(element.nodeId);
|
|
3099
|
+
const submitPos = await this.getElementPosition({ nodeId: element.nodeId });
|
|
3100
|
+
if (submitPos) this.setLastActionPosition(submitPos.center, submitPos.bbox);
|
|
2992
3101
|
const isFormElement = await this.cdp.send(
|
|
2993
3102
|
"Runtime.callFunctionOn",
|
|
2994
3103
|
{
|
|
@@ -3085,6 +3194,8 @@ var Page = class {
|
|
|
3085
3194
|
const hints = await generateHints(this, selectorList, "focus");
|
|
3086
3195
|
throw new ElementNotFoundError(selector, hints);
|
|
3087
3196
|
}
|
|
3197
|
+
const focusPos = await this.getElementPosition({ nodeId: element.nodeId });
|
|
3198
|
+
if (focusPos) this.setLastActionPosition(focusPos.center, focusPos.bbox);
|
|
3088
3199
|
await this.cdp.send("DOM.focus", { nodeId: element.nodeId });
|
|
3089
3200
|
return true;
|
|
3090
3201
|
}
|
|
@@ -3120,6 +3231,14 @@ var Page = class {
|
|
|
3120
3231
|
const quad = quads[0];
|
|
3121
3232
|
x = (quad[0] + quad[2] + quad[4] + quad[6]) / 4;
|
|
3122
3233
|
y = (quad[1] + quad[3] + quad[5] + quad[7]) / 4;
|
|
3234
|
+
const minX = Math.min(quad[0], quad[2], quad[4], quad[6]);
|
|
3235
|
+
const maxX = Math.max(quad[0], quad[2], quad[4], quad[6]);
|
|
3236
|
+
const minY = Math.min(quad[1], quad[3], quad[5], quad[7]);
|
|
3237
|
+
const maxY = Math.max(quad[1], quad[3], quad[5], quad[7]);
|
|
3238
|
+
this.setLastActionPosition(
|
|
3239
|
+
{ x, y },
|
|
3240
|
+
{ x: minX, y: minY, width: maxX - minX, height: maxY - minY }
|
|
3241
|
+
);
|
|
3123
3242
|
} else {
|
|
3124
3243
|
throw new Error("No quads");
|
|
3125
3244
|
}
|
|
@@ -3131,6 +3250,10 @@ var Page = class {
|
|
|
3131
3250
|
}
|
|
3132
3251
|
x = box.content[0] + box.width / 2;
|
|
3133
3252
|
y = box.content[1] + box.height / 2;
|
|
3253
|
+
this.setLastActionPosition(
|
|
3254
|
+
{ x, y },
|
|
3255
|
+
{ x: box.content[0], y: box.content[1], width: box.width, height: box.height }
|
|
3256
|
+
);
|
|
3134
3257
|
}
|
|
3135
3258
|
await this.cdp.send("Input.dispatchMouseEvent", {
|
|
3136
3259
|
type: "mouseMoved",
|
|
@@ -3156,6 +3279,8 @@ var Page = class {
|
|
|
3156
3279
|
if (options.optional) return false;
|
|
3157
3280
|
throw new ElementNotFoundError(selector);
|
|
3158
3281
|
}
|
|
3282
|
+
const scrollPos = await this.getElementPosition({ nodeId: element.nodeId });
|
|
3283
|
+
if (scrollPos) this.setLastActionPosition(scrollPos.center, scrollPos.bbox);
|
|
3159
3284
|
await this.scrollIntoView(element.nodeId);
|
|
3160
3285
|
return true;
|
|
3161
3286
|
}
|
|
@@ -3917,7 +4042,7 @@ var Page = class {
|
|
|
3917
4042
|
return {
|
|
3918
4043
|
role,
|
|
3919
4044
|
name,
|
|
3920
|
-
value: value !== void 0 ?
|
|
4045
|
+
value: value !== void 0 ? stringifyUnknown(value) : void 0,
|
|
3921
4046
|
ref,
|
|
3922
4047
|
children: children.length > 0 ? children : void 0,
|
|
3923
4048
|
disabled,
|
|
@@ -3979,7 +4104,7 @@ var Page = class {
|
|
|
3979
4104
|
selector,
|
|
3980
4105
|
disabled,
|
|
3981
4106
|
checked,
|
|
3982
|
-
value: value !== void 0 ?
|
|
4107
|
+
value: value !== void 0 ? stringifyUnknown(value) : void 0
|
|
3983
4108
|
});
|
|
3984
4109
|
}
|
|
3985
4110
|
}
|
|
@@ -4449,7 +4574,7 @@ var Page = class {
|
|
|
4449
4574
|
*/
|
|
4450
4575
|
formatConsoleArgs(args) {
|
|
4451
4576
|
return args.map((arg) => {
|
|
4452
|
-
if (arg.value !== void 0) return
|
|
4577
|
+
if (arg.value !== void 0) return stringifyUnknown(arg.value);
|
|
4453
4578
|
if (arg.description) return arg.description;
|
|
4454
4579
|
return "[object]";
|
|
4455
4580
|
}).join(" ");
|
|
@@ -5238,6 +5363,25 @@ var Browser = class _Browser {
|
|
|
5238
5363
|
this.cdp = cdp;
|
|
5239
5364
|
this.providerSession = providerSession;
|
|
5240
5365
|
}
|
|
5366
|
+
/**
|
|
5367
|
+
* Create a Browser from an existing CDPClient (used by daemon fast-path).
|
|
5368
|
+
* The caller is responsible for the CDP connection lifecycle.
|
|
5369
|
+
*/
|
|
5370
|
+
static fromCDP(cdp, sessionInfo) {
|
|
5371
|
+
const providerSession = {
|
|
5372
|
+
wsUrl: sessionInfo.wsUrl,
|
|
5373
|
+
sessionId: sessionInfo.sessionId,
|
|
5374
|
+
async close() {
|
|
5375
|
+
}
|
|
5376
|
+
};
|
|
5377
|
+
const provider = {
|
|
5378
|
+
name: sessionInfo.provider ?? "daemon",
|
|
5379
|
+
async createSession() {
|
|
5380
|
+
return providerSession;
|
|
5381
|
+
}
|
|
5382
|
+
};
|
|
5383
|
+
return new _Browser(cdp, provider, providerSession, { provider: "generic" });
|
|
5384
|
+
}
|
|
5241
5385
|
/**
|
|
5242
5386
|
* Connect to a browser instance
|
|
5243
5387
|
*/
|