@xbrowser/cli 1.14.0 → 1.16.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/{browser-KJWBHGHX.js → browser-3KTEVTMU.js} +2 -2
- package/dist/{browser-5A6AL62M.js → browser-AOVQTGJ7.js} +2 -2
- package/dist/{browser-DI6UQN6Q.js → browser-KT4FOWBO.js} +1 -1
- package/dist/{cdp-driver-QXTXJZH7.js → cdp-driver-ALDP2CZT.js} +248 -49
- package/dist/{cdp-driver-4SFS6GNY.js → cdp-driver-DKNLIA6B.js} +1 -1
- package/dist/{cdp-driver-AHKUT57K.js → cdp-driver-OC37OT4B.js} +1 -1
- package/dist/{chunk-BTFKJD7Z.js → chunk-5EYOEB4R.js} +277 -65
- package/dist/{chunk-B753M33E.js → chunk-7V3B7VPX.js} +9 -7
- package/dist/{chunk-PYQGDBAF.js → chunk-A5HJ6IRE.js} +269 -59
- package/dist/{chunk-ZD4OSYOX.js → chunk-GWQ5NTVE.js} +9 -7
- package/dist/{chunk-UPAWITVM.js → chunk-LTBNQERK.js} +269 -59
- package/dist/cli.js +86 -32
- package/dist/clipboard-BOL2GP2E.js +58 -0
- package/dist/clipboard-XRP54ENE.js +58 -0
- package/dist/daemon-main.js +44 -22
- package/dist/index.d.ts +4 -0
- package/dist/index.js +106 -51
- package/dist/{session-replayer-I3PJFO3H.js → session-replayer-MJH5W7BB.js} +1 -1
- package/package.json +1 -1
- package/dist/{recovery-Z3RDZENA.js → recovery-MDWAVXE4.js} +4 -4
- package/dist/{recovery-FTZGV6VY.js → recovery-NXC35EQN.js} +4 -4
package/dist/cli.js
CHANGED
|
@@ -26,6 +26,16 @@ import {
|
|
|
26
26
|
import {
|
|
27
27
|
buildViewerUrl
|
|
28
28
|
} from "./chunk-3OD76SUE.js";
|
|
29
|
+
import {
|
|
30
|
+
NPM_REGISTRY_URL,
|
|
31
|
+
NPM_SCOPE,
|
|
32
|
+
getConfigValue,
|
|
33
|
+
getMarketplaceUrl,
|
|
34
|
+
loadConfig,
|
|
35
|
+
resolveNpmPackageWithFallback,
|
|
36
|
+
resolveScreenshotsDir,
|
|
37
|
+
setConfigValue
|
|
38
|
+
} from "./chunk-ZTHE5RBZ.js";
|
|
29
39
|
import {
|
|
30
40
|
getDaemonConfig,
|
|
31
41
|
getDaemonProcessStatus,
|
|
@@ -56,10 +66,13 @@ import {
|
|
|
56
66
|
getAllSessions,
|
|
57
67
|
getBrowser,
|
|
58
68
|
getSessionById,
|
|
69
|
+
rand,
|
|
59
70
|
resolveLaunchOpts,
|
|
60
71
|
saveSessionDiskMeta,
|
|
61
|
-
setActivePage
|
|
62
|
-
|
|
72
|
+
setActivePage,
|
|
73
|
+
sleep,
|
|
74
|
+
wheelDelta
|
|
75
|
+
} from "./chunk-5EYOEB4R.js";
|
|
63
76
|
import "./chunk-TNEN6VQ2.js";
|
|
64
77
|
import {
|
|
65
78
|
errMsg
|
|
@@ -68,16 +81,6 @@ import {
|
|
|
68
81
|
detectAntiBot,
|
|
69
82
|
formatDetectionMessage
|
|
70
83
|
} from "./chunk-JKVUFP3G.js";
|
|
71
|
-
import {
|
|
72
|
-
NPM_REGISTRY_URL,
|
|
73
|
-
NPM_SCOPE,
|
|
74
|
-
getConfigValue,
|
|
75
|
-
getMarketplaceUrl,
|
|
76
|
-
loadConfig,
|
|
77
|
-
resolveNpmPackageWithFallback,
|
|
78
|
-
resolveScreenshotsDir,
|
|
79
|
-
setConfigValue
|
|
80
|
-
} from "./chunk-ZTHE5RBZ.js";
|
|
81
84
|
import "./chunk-KFQGP6VL.js";
|
|
82
85
|
|
|
83
86
|
// src/router.ts
|
|
@@ -352,7 +355,8 @@ var gotoCommand = registerCommand({
|
|
|
352
355
|
parameters: z.object({
|
|
353
356
|
url: z.string(),
|
|
354
357
|
waitUntil: z.enum(["load", "domcontentloaded", "networkidle", "commit"]).optional(),
|
|
355
|
-
timeout: z.number().optional()
|
|
358
|
+
timeout: z.number().optional(),
|
|
359
|
+
referrer: z.string().optional()
|
|
356
360
|
}),
|
|
357
361
|
result: z.object({
|
|
358
362
|
url: z.string(),
|
|
@@ -373,7 +377,9 @@ var gotoCommand = registerCommand({
|
|
|
373
377
|
try {
|
|
374
378
|
response = await ctx.page.goto(url, {
|
|
375
379
|
waitUntil: p.waitUntil || "domcontentloaded",
|
|
376
|
-
...p.timeout ? { timeout: p.timeout } : {}
|
|
380
|
+
...p.timeout ? { timeout: p.timeout } : {},
|
|
381
|
+
// referrer(d54):模拟从源页面点链接进入 —— document.referrer 非空
|
|
382
|
+
...p.referrer ? { referer: p.referrer } : {}
|
|
377
383
|
});
|
|
378
384
|
} catch (err) {
|
|
379
385
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -900,21 +906,34 @@ var scrollCommand = registerCommand({
|
|
|
900
906
|
}),
|
|
901
907
|
handler: async (p, ctx) => {
|
|
902
908
|
const distance = p.distance ?? 500;
|
|
903
|
-
const
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
right: [distance, 0],
|
|
907
|
-
left: [-distance, 0]
|
|
908
|
-
};
|
|
909
|
-
const [dx, dy] = deltas[p.direction];
|
|
909
|
+
const sign = { down: 1, up: -1, right: 1, left: -1 };
|
|
910
|
+
const vertical = p.direction === "down" || p.direction === "up";
|
|
911
|
+
const s = sign[p.direction];
|
|
910
912
|
if (p.selector) {
|
|
911
913
|
const element = ctx.page.locator(p.selector).first();
|
|
912
914
|
await element.evaluate((el, args) => {
|
|
913
915
|
const [dxx, dyy] = args;
|
|
914
916
|
el.scrollBy(dxx, dyy);
|
|
915
|
-
}, [
|
|
917
|
+
}, [vertical ? 0 : distance * s, vertical ? distance * s : 0]);
|
|
918
|
+
} else if (process.env.XBROWSER_STEALTH !== "off") {
|
|
919
|
+
let acc = 0;
|
|
920
|
+
let step = 0;
|
|
921
|
+
while (acc < distance && step < 60) {
|
|
922
|
+
const d = Math.min(wheelDelta(step), distance - acc);
|
|
923
|
+
if (d < 1) break;
|
|
924
|
+
await ctx.page.mouse.wheel(
|
|
925
|
+
vertical ? 0 : d * s,
|
|
926
|
+
vertical ? d * s : 0
|
|
927
|
+
);
|
|
928
|
+
acc += d;
|
|
929
|
+
step++;
|
|
930
|
+
await sleep(rand(16, 28));
|
|
931
|
+
}
|
|
916
932
|
} else {
|
|
917
|
-
await ctx.page.mouse.wheel(
|
|
933
|
+
await ctx.page.mouse.wheel(
|
|
934
|
+
vertical ? 0 : distance * s,
|
|
935
|
+
vertical ? distance * s : 0
|
|
936
|
+
);
|
|
918
937
|
}
|
|
919
938
|
return ok5({ direction: p.direction, distance });
|
|
920
939
|
}
|
|
@@ -7523,7 +7542,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7523
7542
|
}
|
|
7524
7543
|
let targetPageOverride = null;
|
|
7525
7544
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
7526
|
-
const { findTargetPage } = await import("./browser-
|
|
7545
|
+
const { findTargetPage } = await import("./browser-KT4FOWBO.js");
|
|
7527
7546
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
7528
7547
|
if (!targetPageOverride) {
|
|
7529
7548
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -7737,7 +7756,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7737
7756
|
const errorMessage = errMsg(err);
|
|
7738
7757
|
if (session?.page && process.env.XBROWSER_RECOVERY && !extraOpts?._recoveryAttempted) {
|
|
7739
7758
|
try {
|
|
7740
|
-
const { attemptRecovery } = await import("./recovery-
|
|
7759
|
+
const { attemptRecovery } = await import("./recovery-NXC35EQN.js");
|
|
7741
7760
|
const recovery = await attemptRecovery(
|
|
7742
7761
|
session.page,
|
|
7743
7762
|
sessionName,
|
|
@@ -7803,6 +7822,9 @@ async function executeChain(input, options) {
|
|
|
7803
7822
|
for (const pipeline of pipelines) {
|
|
7804
7823
|
const { type, pipeline: commands } = pipeline;
|
|
7805
7824
|
for (const cmdStr of commands) {
|
|
7825
|
+
if (process.env.XBROWSER_CHAIN_PACE === "human" && results.length > 0) {
|
|
7826
|
+
await new Promise((r) => setTimeout(r, 800 + Math.random() * 1700));
|
|
7827
|
+
}
|
|
7806
7828
|
const parts = splitCommand(cmdStr);
|
|
7807
7829
|
if (parts.length === 0) continue;
|
|
7808
7830
|
const cmdName = parts[0];
|
|
@@ -10173,12 +10195,33 @@ function normalizeSelector(input) {
|
|
|
10173
10195
|
|
|
10174
10196
|
// src/cli/browser-routes.ts
|
|
10175
10197
|
import { helpGenerator } from "@dyyz1993/xcli-core";
|
|
10198
|
+
function autoCompleteParams(cmdName, params, options) {
|
|
10199
|
+
try {
|
|
10200
|
+
const cmd = getCommand(cmdName);
|
|
10201
|
+
if (!cmd?.parameters) return params;
|
|
10202
|
+
const schema = asZodSchema(cmd.parameters);
|
|
10203
|
+
const shape = schema?.shape ?? schema?._def?.shape;
|
|
10204
|
+
if (!shape) return params;
|
|
10205
|
+
for (const key of Object.keys(shape)) {
|
|
10206
|
+
if (params[key] !== void 0) continue;
|
|
10207
|
+
const v = options[key];
|
|
10208
|
+
if (v === void 0 || v === true && key === "json" || key === "yaml") continue;
|
|
10209
|
+
if (typeof v === "string" && v === "") continue;
|
|
10210
|
+
params[key] = v;
|
|
10211
|
+
}
|
|
10212
|
+
return params;
|
|
10213
|
+
} catch {
|
|
10214
|
+
return params;
|
|
10215
|
+
}
|
|
10216
|
+
}
|
|
10176
10217
|
function parseSelectorFlags(args, options) {
|
|
10177
|
-
const
|
|
10178
|
-
const
|
|
10218
|
+
const rawSelector = options.s ?? options.selector;
|
|
10219
|
+
const rawValue = options.v ?? options.value;
|
|
10220
|
+
const selector = typeof rawSelector === "string" ? normalizeSelector(rawSelector) : void 0;
|
|
10221
|
+
const value = typeof rawValue === "string" ? rawValue : void 0;
|
|
10179
10222
|
const remaining = args.filter((a) => !a.startsWith("-"));
|
|
10180
10223
|
return {
|
|
10181
|
-
selector
|
|
10224
|
+
selector,
|
|
10182
10225
|
value,
|
|
10183
10226
|
remaining
|
|
10184
10227
|
};
|
|
@@ -10266,7 +10309,11 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
|
|
|
10266
10309
|
if (!sel || !txt)
|
|
10267
10310
|
outputError("Usage: xbrowser type <selector> <text>\n xbrowser type -s <selector> -v <text>");
|
|
10268
10311
|
cmdName = "type";
|
|
10269
|
-
params = {
|
|
10312
|
+
params = {
|
|
10313
|
+
selector: sel,
|
|
10314
|
+
text: txt,
|
|
10315
|
+
...options.delay !== void 0 ? { delay: Number(options.delay) } : {}
|
|
10316
|
+
};
|
|
10270
10317
|
break;
|
|
10271
10318
|
}
|
|
10272
10319
|
case "press": {
|
|
@@ -10408,7 +10455,13 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
|
|
|
10408
10455
|
outputError("Usage: xbrowser mouse <move|click|dblclick> <x> <y>\n xbrowser mouse --action <action> --x <x> --y <y>");
|
|
10409
10456
|
}
|
|
10410
10457
|
cmdName = "mouse";
|
|
10411
|
-
params = {
|
|
10458
|
+
params = {
|
|
10459
|
+
action,
|
|
10460
|
+
x,
|
|
10461
|
+
y,
|
|
10462
|
+
...options.button ? { button: options.button } : {},
|
|
10463
|
+
...options.steps !== void 0 ? { steps: Number(options.steps) } : {}
|
|
10464
|
+
};
|
|
10412
10465
|
break;
|
|
10413
10466
|
}
|
|
10414
10467
|
case "html":
|
|
@@ -10610,6 +10663,7 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
|
|
|
10610
10663
|
if (target) {
|
|
10611
10664
|
params = { ...params, _target: target };
|
|
10612
10665
|
}
|
|
10666
|
+
params = autoCompleteParams(cmdName, params, options);
|
|
10613
10667
|
const tabIndex = options.tab;
|
|
10614
10668
|
if (tabIndex !== void 0) {
|
|
10615
10669
|
params = { ...params, _tabIndex: Number(tabIndex) };
|
|
@@ -13663,7 +13717,7 @@ Run "xbrowser ${command} ${subCommand} --help" to see available parameters.`
|
|
|
13663
13717
|
const targetPage = pages[cmdTabIndex];
|
|
13664
13718
|
await targetPage.bringToFront().catch(() => {
|
|
13665
13719
|
});
|
|
13666
|
-
const { setActivePage: setActivePage2 } = await import("./browser-
|
|
13720
|
+
const { setActivePage: setActivePage2 } = await import("./browser-KT4FOWBO.js");
|
|
13667
13721
|
setActivePage2(session, targetPage);
|
|
13668
13722
|
}
|
|
13669
13723
|
}
|
|
@@ -13939,7 +13993,7 @@ async function main() {
|
|
|
13939
13993
|
const command = process.argv[2];
|
|
13940
13994
|
const isLongRunning = command === "preview" || command === "serve";
|
|
13941
13995
|
if (!isLongRunning) {
|
|
13942
|
-
const { ensureProcessCanExit } = await import("./browser-
|
|
13996
|
+
const { ensureProcessCanExit } = await import("./browser-KT4FOWBO.js");
|
|
13943
13997
|
await ensureProcessCanExit().catch(() => {
|
|
13944
13998
|
});
|
|
13945
13999
|
process.exit(process.exitCode || exitCode);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import "./chunk-KFQGP6VL.js";
|
|
2
|
+
|
|
3
|
+
// src/utils/clipboard.ts
|
|
4
|
+
import { exec, execSync } from "child_process";
|
|
5
|
+
function writeClipboard(text) {
|
|
6
|
+
const plat = process.platform;
|
|
7
|
+
if (plat === "darwin") {
|
|
8
|
+
const p = exec("pbcopy");
|
|
9
|
+
if (!p.stdin) throw new Error("pbcopy stdin unavailable");
|
|
10
|
+
p.stdin.write(text);
|
|
11
|
+
p.stdin.end();
|
|
12
|
+
execSync("sleep 0.05");
|
|
13
|
+
} else if (plat === "linux") {
|
|
14
|
+
execSync("command -v xclip >/dev/null 2>&1 && echo ok", { stdio: "ignore" });
|
|
15
|
+
const p = exec("xclip -selection clipboard -in");
|
|
16
|
+
if (!p.stdin) throw new Error("xclip stdin unavailable");
|
|
17
|
+
p.stdin.write(text);
|
|
18
|
+
p.stdin.end();
|
|
19
|
+
execSync("sleep 0.05");
|
|
20
|
+
} else if (plat === "win32") {
|
|
21
|
+
const p = exec("clip");
|
|
22
|
+
if (!p.stdin) throw new Error("clip stdin unavailable");
|
|
23
|
+
p.stdin.write(text);
|
|
24
|
+
p.stdin.end();
|
|
25
|
+
execSync("timeout /t 1 /nobreak >nul");
|
|
26
|
+
} else {
|
|
27
|
+
throw new Error(`Unsupported platform for clipboard: ${plat}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function pasteViaClipboard(page, text) {
|
|
31
|
+
writeClipboard(text);
|
|
32
|
+
const kb = page.keyboard;
|
|
33
|
+
const mod = process.platform === "darwin" ? "Meta" : "Control";
|
|
34
|
+
await kb.pressCombo("v", mod);
|
|
35
|
+
await new Promise((r) => setTimeout(r, 150));
|
|
36
|
+
}
|
|
37
|
+
async function syntheticPaste(page, selector, text) {
|
|
38
|
+
const result = await page.evaluate(`
|
|
39
|
+
(function() {
|
|
40
|
+
const el = ${"{SELECTOR}"};
|
|
41
|
+
if (!el) return false;
|
|
42
|
+
el.focus();
|
|
43
|
+
if (el.value) { el.select(); document.execCommand('delete'); }
|
|
44
|
+
try {
|
|
45
|
+
const dt = new DataTransfer();
|
|
46
|
+
dt.setData('text/plain', ${JSON.stringify(text)});
|
|
47
|
+
el.dispatchEvent(new ClipboardEvent('paste', { clipboardData: dt, bubbles: true, cancelable: true }));
|
|
48
|
+
} catch (e) { /* ClipboardEvent ctor guard */ }
|
|
49
|
+
const ok = document.execCommand('insertText', false, ${JSON.stringify(text)});
|
|
50
|
+
return ok === true && (el.value || '') === ${JSON.stringify(text)};
|
|
51
|
+
})()
|
|
52
|
+
`.replace("{SELECTOR}", selector));
|
|
53
|
+
return result === true;
|
|
54
|
+
}
|
|
55
|
+
export {
|
|
56
|
+
pasteViaClipboard,
|
|
57
|
+
syntheticPaste
|
|
58
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import "./chunk-3RG5ZIWI.js";
|
|
2
|
+
|
|
3
|
+
// src/utils/clipboard.ts
|
|
4
|
+
import { exec, execSync } from "child_process";
|
|
5
|
+
function writeClipboard(text) {
|
|
6
|
+
const plat = process.platform;
|
|
7
|
+
if (plat === "darwin") {
|
|
8
|
+
const p = exec("pbcopy");
|
|
9
|
+
if (!p.stdin) throw new Error("pbcopy stdin unavailable");
|
|
10
|
+
p.stdin.write(text);
|
|
11
|
+
p.stdin.end();
|
|
12
|
+
execSync("sleep 0.05");
|
|
13
|
+
} else if (plat === "linux") {
|
|
14
|
+
execSync("command -v xclip >/dev/null 2>&1 && echo ok", { stdio: "ignore" });
|
|
15
|
+
const p = exec("xclip -selection clipboard -in");
|
|
16
|
+
if (!p.stdin) throw new Error("xclip stdin unavailable");
|
|
17
|
+
p.stdin.write(text);
|
|
18
|
+
p.stdin.end();
|
|
19
|
+
execSync("sleep 0.05");
|
|
20
|
+
} else if (plat === "win32") {
|
|
21
|
+
const p = exec("clip");
|
|
22
|
+
if (!p.stdin) throw new Error("clip stdin unavailable");
|
|
23
|
+
p.stdin.write(text);
|
|
24
|
+
p.stdin.end();
|
|
25
|
+
execSync("timeout /t 1 /nobreak >nul");
|
|
26
|
+
} else {
|
|
27
|
+
throw new Error(`Unsupported platform for clipboard: ${plat}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function pasteViaClipboard(page, text) {
|
|
31
|
+
writeClipboard(text);
|
|
32
|
+
const kb = page.keyboard;
|
|
33
|
+
const mod = process.platform === "darwin" ? "Meta" : "Control";
|
|
34
|
+
await kb.pressCombo("v", mod);
|
|
35
|
+
await new Promise((r) => setTimeout(r, 150));
|
|
36
|
+
}
|
|
37
|
+
async function syntheticPaste(page, selector, text) {
|
|
38
|
+
const result = await page.evaluate(`
|
|
39
|
+
(function() {
|
|
40
|
+
const el = ${"{SELECTOR}"};
|
|
41
|
+
if (!el) return false;
|
|
42
|
+
el.focus();
|
|
43
|
+
if (el.value) { el.select(); document.execCommand('delete'); }
|
|
44
|
+
try {
|
|
45
|
+
const dt = new DataTransfer();
|
|
46
|
+
dt.setData('text/plain', ${JSON.stringify(text)});
|
|
47
|
+
el.dispatchEvent(new ClipboardEvent('paste', { clipboardData: dt, bubbles: true, cancelable: true }));
|
|
48
|
+
} catch (e) { /* ClipboardEvent ctor guard */ }
|
|
49
|
+
const ok = document.execCommand('insertText', false, ${JSON.stringify(text)});
|
|
50
|
+
return ok === true && (el.value || '') === ${JSON.stringify(text)};
|
|
51
|
+
})()
|
|
52
|
+
`.replace("{SELECTOR}", selector));
|
|
53
|
+
return result === true;
|
|
54
|
+
}
|
|
55
|
+
export {
|
|
56
|
+
pasteViaClipboard,
|
|
57
|
+
syntheticPaste
|
|
58
|
+
};
|
package/dist/daemon-main.js
CHANGED
|
@@ -7,6 +7,10 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
buildViewerUrl
|
|
9
9
|
} from "./chunk-TZPKFUBT.js";
|
|
10
|
+
import {
|
|
11
|
+
ScreencastCapturer,
|
|
12
|
+
resolveScreenshotsDir
|
|
13
|
+
} from "./chunk-HBMEFSTB.js";
|
|
10
14
|
import "./chunk-CG3D3CHY.js";
|
|
11
15
|
import {
|
|
12
16
|
commandLogStore,
|
|
@@ -30,10 +34,13 @@ import {
|
|
|
30
34
|
resolveLaunchOpts,
|
|
31
35
|
saveSessionDiskMeta,
|
|
32
36
|
setActivePage
|
|
33
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-GWQ5NTVE.js";
|
|
34
38
|
import {
|
|
35
|
-
createRuleEngine
|
|
36
|
-
|
|
39
|
+
createRuleEngine,
|
|
40
|
+
rand,
|
|
41
|
+
sleep,
|
|
42
|
+
wheelDelta
|
|
43
|
+
} from "./chunk-LTBNQERK.js";
|
|
37
44
|
import {
|
|
38
45
|
queryJS
|
|
39
46
|
} from "./chunk-3FWLW7FS.js";
|
|
@@ -45,10 +52,6 @@ import {
|
|
|
45
52
|
detectAntiBot,
|
|
46
53
|
formatDetectionMessage
|
|
47
54
|
} from "./chunk-JKVUFP3G.js";
|
|
48
|
-
import {
|
|
49
|
-
ScreencastCapturer,
|
|
50
|
-
resolveScreenshotsDir
|
|
51
|
-
} from "./chunk-HBMEFSTB.js";
|
|
52
55
|
import "./chunk-KFQGP6VL.js";
|
|
53
56
|
|
|
54
57
|
// src/daemon/daemon-main.ts
|
|
@@ -312,7 +315,8 @@ var gotoCommand = registerCommand({
|
|
|
312
315
|
parameters: z.object({
|
|
313
316
|
url: z.string(),
|
|
314
317
|
waitUntil: z.enum(["load", "domcontentloaded", "networkidle", "commit"]).optional(),
|
|
315
|
-
timeout: z.number().optional()
|
|
318
|
+
timeout: z.number().optional(),
|
|
319
|
+
referrer: z.string().optional()
|
|
316
320
|
}),
|
|
317
321
|
result: z.object({
|
|
318
322
|
url: z.string(),
|
|
@@ -333,7 +337,9 @@ var gotoCommand = registerCommand({
|
|
|
333
337
|
try {
|
|
334
338
|
response = await ctx.page.goto(url, {
|
|
335
339
|
waitUntil: p.waitUntil || "domcontentloaded",
|
|
336
|
-
...p.timeout ? { timeout: p.timeout } : {}
|
|
340
|
+
...p.timeout ? { timeout: p.timeout } : {},
|
|
341
|
+
// referrer(d54):模拟从源页面点链接进入 —— document.referrer 非空
|
|
342
|
+
...p.referrer ? { referer: p.referrer } : {}
|
|
337
343
|
});
|
|
338
344
|
} catch (err) {
|
|
339
345
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -860,21 +866,34 @@ var scrollCommand = registerCommand({
|
|
|
860
866
|
}),
|
|
861
867
|
handler: async (p, ctx) => {
|
|
862
868
|
const distance = p.distance ?? 500;
|
|
863
|
-
const
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
right: [distance, 0],
|
|
867
|
-
left: [-distance, 0]
|
|
868
|
-
};
|
|
869
|
-
const [dx, dy] = deltas[p.direction];
|
|
869
|
+
const sign = { down: 1, up: -1, right: 1, left: -1 };
|
|
870
|
+
const vertical = p.direction === "down" || p.direction === "up";
|
|
871
|
+
const s = sign[p.direction];
|
|
870
872
|
if (p.selector) {
|
|
871
873
|
const element = ctx.page.locator(p.selector).first();
|
|
872
874
|
await element.evaluate((el, args) => {
|
|
873
875
|
const [dxx, dyy] = args;
|
|
874
876
|
el.scrollBy(dxx, dyy);
|
|
875
|
-
}, [
|
|
877
|
+
}, [vertical ? 0 : distance * s, vertical ? distance * s : 0]);
|
|
878
|
+
} else if (process.env.XBROWSER_STEALTH !== "off") {
|
|
879
|
+
let acc = 0;
|
|
880
|
+
let step = 0;
|
|
881
|
+
while (acc < distance && step < 60) {
|
|
882
|
+
const d = Math.min(wheelDelta(step), distance - acc);
|
|
883
|
+
if (d < 1) break;
|
|
884
|
+
await ctx.page.mouse.wheel(
|
|
885
|
+
vertical ? 0 : d * s,
|
|
886
|
+
vertical ? d * s : 0
|
|
887
|
+
);
|
|
888
|
+
acc += d;
|
|
889
|
+
step++;
|
|
890
|
+
await sleep(rand(16, 28));
|
|
891
|
+
}
|
|
876
892
|
} else {
|
|
877
|
-
await ctx.page.mouse.wheel(
|
|
893
|
+
await ctx.page.mouse.wheel(
|
|
894
|
+
vertical ? 0 : distance * s,
|
|
895
|
+
vertical ? distance * s : 0
|
|
896
|
+
);
|
|
878
897
|
}
|
|
879
898
|
return ok5({ direction: p.direction, distance });
|
|
880
899
|
}
|
|
@@ -7041,7 +7060,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7041
7060
|
}
|
|
7042
7061
|
let targetPageOverride = null;
|
|
7043
7062
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
7044
|
-
const { findTargetPage } = await import("./browser-
|
|
7063
|
+
const { findTargetPage } = await import("./browser-AOVQTGJ7.js");
|
|
7045
7064
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
7046
7065
|
if (!targetPageOverride) {
|
|
7047
7066
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -7255,7 +7274,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7255
7274
|
const errorMessage = errMsg(err);
|
|
7256
7275
|
if (session?.page && process.env.XBROWSER_RECOVERY && !extraOpts?._recoveryAttempted) {
|
|
7257
7276
|
try {
|
|
7258
|
-
const { attemptRecovery } = await import("./recovery-
|
|
7277
|
+
const { attemptRecovery } = await import("./recovery-MDWAVXE4.js");
|
|
7259
7278
|
const recovery = await attemptRecovery(
|
|
7260
7279
|
session.page,
|
|
7261
7280
|
sessionName,
|
|
@@ -7321,6 +7340,9 @@ async function executeChain(input, options) {
|
|
|
7321
7340
|
for (const pipeline of pipelines) {
|
|
7322
7341
|
const { type, pipeline: commands } = pipeline;
|
|
7323
7342
|
for (const cmdStr of commands) {
|
|
7343
|
+
if (process.env.XBROWSER_CHAIN_PACE === "human" && results.length > 0) {
|
|
7344
|
+
await new Promise((r) => setTimeout(r, 800 + Math.random() * 1700));
|
|
7345
|
+
}
|
|
7324
7346
|
const parts = splitCommand(cmdStr);
|
|
7325
7347
|
if (parts.length === 0) continue;
|
|
7326
7348
|
const cmdName = parts[0];
|
|
@@ -8292,7 +8314,7 @@ function createRPCHandler() {
|
|
|
8292
8314
|
return result;
|
|
8293
8315
|
} catch (err) {
|
|
8294
8316
|
const errorMessage = errMsg(err);
|
|
8295
|
-
const { attemptRecovery } = await import("./recovery-
|
|
8317
|
+
const { attemptRecovery } = await import("./recovery-MDWAVXE4.js");
|
|
8296
8318
|
const recovery = await attemptRecovery(
|
|
8297
8319
|
session?.page,
|
|
8298
8320
|
sessionName,
|
|
@@ -8857,7 +8879,7 @@ function createRPCHandler() {
|
|
|
8857
8879
|
if (isNewFormat) {
|
|
8858
8880
|
try {
|
|
8859
8881
|
const replayErrors = [];
|
|
8860
|
-
const { SessionReplayer } = await import("./session-replayer-
|
|
8882
|
+
const { SessionReplayer } = await import("./session-replayer-MJH5W7BB.js");
|
|
8861
8883
|
const replayer = new SessionReplayer({
|
|
8862
8884
|
page: session.page,
|
|
8863
8885
|
stepDelay: slowMo * 500,
|
package/dist/index.d.ts
CHANGED
|
@@ -316,6 +316,10 @@ interface XBKeyboard {
|
|
|
316
316
|
press(key: string, opts?: {
|
|
317
317
|
delay?: number;
|
|
318
318
|
}): Promise<void>;
|
|
319
|
+
/** Navigation key with CDP 'keyDown' type (carries browser default actions) */
|
|
320
|
+
pressNav(key: string): Promise<void>;
|
|
321
|
+
/** Shortcut combo (modifier+key) with explicit per-event modifiers bitmask */
|
|
322
|
+
pressCombo(key: string, modifier: 'Meta' | 'Control' | 'Alt' | 'Shift'): Promise<void>;
|
|
319
323
|
down(key: string): Promise<void>;
|
|
320
324
|
up(key: string): Promise<void>;
|
|
321
325
|
type(text: string, opts?: {
|