@xbrowser/cli 1.21.0 → 1.23.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/README.md +21 -3
- package/dist/{browser-CNBSH53B.js → browser-BVRFSUXU.js} +3 -2
- package/dist/{browser-C2VEOJC2.js → browser-DSYUAE7H.js} +5 -4
- package/dist/{browser-VZOOFLAH.js → browser-Q67BJTI2.js} +4 -3
- package/dist/{cdp-driver-KFX4A6WR.js → cdp-driver-DC7EIUG5.js} +4 -3
- package/dist/{cdp-driver-7Z6ZAT5E.js → cdp-driver-T7D6H2RW.js} +335 -546
- package/dist/{cdp-driver-26LGCHXV.js → cdp-driver-WWO2UZDR.js} +3 -2
- package/dist/{chunk-Z5RTK4GW.js → chunk-2Q3GQRUP.js} +2 -2
- package/dist/{chunk-CLYZPSDR.js → chunk-4OU37CXP.js} +354 -576
- package/dist/{chunk-HWWG2ISJ.js → chunk-7OP2ISEY.js} +353 -575
- package/dist/{chunk-PIWNMC36.js → chunk-A3MORKYR.js} +1 -1
- package/dist/{chunk-3FWLW7FS.js → chunk-A7NEA4PA.js} +39 -1
- package/dist/{chunk-OMU63E6J.js → chunk-FBQZ3PVD.js} +5 -8
- package/dist/chunk-GYB5BOSP.js +602 -0
- package/dist/{chunk-ESJYANQO.js → chunk-IFKJO2UR.js} +360 -582
- package/dist/{chunk-NODRQGOK.js → chunk-IR6C24P7.js} +97 -0
- package/dist/{chunk-TEXCXIBW.js → chunk-LPW6QS4M.js} +5 -8
- package/dist/{chunk-3KZ34AUC.js → chunk-MYH6FIBZ.js} +2 -1
- package/dist/{chunk-AVSTNODR.js → chunk-T4WTKBWI.js} +2 -2
- package/dist/{chunk-HBHOKZPN.js → chunk-V6KGBU5J.js} +97 -0
- package/dist/{chunk-IWVG4XYZ.js → chunk-VCVDILH6.js} +2 -1
- package/dist/{chunk-NKW4A74J.js → chunk-XTUAUFL3.js} +5 -8
- package/dist/cli.js +497 -252
- package/dist/daemon-main.js +25 -19
- package/dist/{human-interaction-Y5IDH6LD.js → human-interaction-57VYIR56.js} +1 -1
- package/dist/{human-interaction-ZUTR5AC2.js → human-interaction-67K43B4O.js} +1 -1
- package/dist/{human-interaction-4YR2N6R6.js → human-interaction-MXST5ZQM.js} +1 -1
- package/dist/index.d.ts +52 -4
- package/dist/index.js +500 -256
- package/dist/keep-awake-M4KJS4B4.js +29 -0
- package/dist/{launcher-44STYRJC.js → launcher-IK2FKW6T.js} +1 -1
- package/dist/{launcher-EXJHHAUL.js → launcher-LUOMMGZC.js} +1 -1
- package/dist/{plugin-singleton-FCNDN3FX.js → plugin-singleton-GJO7EZXB.js} +1 -1
- package/dist/{recovery-NXC35EQN.js → recovery-6RI2FE3E.js} +1 -1
- package/dist/{recovery-MDWAVXE4.js → recovery-LGY25LIM.js} +1 -1
- package/dist/{recovery-L5GLDX4O.js → recovery-LMJW537X.js} +1 -1
- package/dist/{session-recorder-SLDBENVF.js → session-recorder-563ISSJK.js} +1 -1
- package/dist/{session-recorder-3BEVWHOK.js → session-recorder-GEZVQBKW.js} +1 -1
- package/dist/session-replayer-N665T3G5.js +932 -0
- package/dist/stealth-2AA2FSNN.js +29 -0
- package/dist/stealth-JOXGV34D.js +29 -0
- package/package.json +11 -7
- package/dist/session-replayer-EVD4HZBB.js +0 -413
package/dist/daemon-main.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
detectAntiBot,
|
|
3
|
+
formatDetectionMessage
|
|
4
|
+
} from "./chunk-JKVUFP3G.js";
|
|
1
5
|
import {
|
|
2
6
|
getPluginLoader
|
|
3
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-A3MORKYR.js";
|
|
4
8
|
import {
|
|
5
9
|
version
|
|
6
10
|
} from "./chunk-43TEMG4U.js";
|
|
@@ -19,7 +23,7 @@ import {
|
|
|
19
23
|
} from "./chunk-VEDJ5XSQ.js";
|
|
20
24
|
import {
|
|
21
25
|
SessionRecorder
|
|
22
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-V6KGBU5J.js";
|
|
23
27
|
import {
|
|
24
28
|
closeEphemeralContext,
|
|
25
29
|
closeSessionByName,
|
|
@@ -34,24 +38,22 @@ import {
|
|
|
34
38
|
resolveLaunchOpts,
|
|
35
39
|
saveSessionDiskMeta,
|
|
36
40
|
setActivePage
|
|
37
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-T4WTKBWI.js";
|
|
42
|
+
import {
|
|
43
|
+
createRuleEngine
|
|
44
|
+
} from "./chunk-4OU37CXP.js";
|
|
45
|
+
import {
|
|
46
|
+
queryJS
|
|
47
|
+
} from "./chunk-A7NEA4PA.js";
|
|
38
48
|
import {
|
|
39
|
-
createRuleEngine,
|
|
40
49
|
rand,
|
|
41
50
|
sleep,
|
|
42
51
|
wheelDelta
|
|
43
|
-
} from "./chunk-
|
|
44
|
-
import
|
|
45
|
-
queryJS
|
|
46
|
-
} from "./chunk-3FWLW7FS.js";
|
|
47
|
-
import "./chunk-3KZ34AUC.js";
|
|
52
|
+
} from "./chunk-GYB5BOSP.js";
|
|
53
|
+
import "./chunk-MYH6FIBZ.js";
|
|
48
54
|
import {
|
|
49
55
|
errMsg
|
|
50
56
|
} from "./chunk-GDKLH7ZY.js";
|
|
51
|
-
import {
|
|
52
|
-
detectAntiBot,
|
|
53
|
-
formatDetectionMessage
|
|
54
|
-
} from "./chunk-JKVUFP3G.js";
|
|
55
57
|
import "./chunk-KFQGP6VL.js";
|
|
56
58
|
|
|
57
59
|
// src/daemon/daemon-main.ts
|
|
@@ -7766,7 +7768,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7766
7768
|
}
|
|
7767
7769
|
let targetPageOverride = null;
|
|
7768
7770
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
7769
|
-
const { findTargetPage } = await import("./browser-
|
|
7771
|
+
const { findTargetPage } = await import("./browser-DSYUAE7H.js");
|
|
7770
7772
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
7771
7773
|
if (!targetPageOverride) {
|
|
7772
7774
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -7983,7 +7985,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7983
7985
|
const errorMessage = errMsg(err);
|
|
7984
7986
|
if (session?.page && process.env.XBROWSER_RECOVERY && !extraOpts?._recoveryAttempted) {
|
|
7985
7987
|
try {
|
|
7986
|
-
const { attemptRecovery } = await import("./recovery-
|
|
7988
|
+
const { attemptRecovery } = await import("./recovery-LGY25LIM.js");
|
|
7987
7989
|
const recovery = await attemptRecovery(
|
|
7988
7990
|
session.page,
|
|
7989
7991
|
sessionName,
|
|
@@ -9023,7 +9025,7 @@ function createRPCHandler() {
|
|
|
9023
9025
|
return result;
|
|
9024
9026
|
} catch (err) {
|
|
9025
9027
|
const errorMessage = errMsg(err);
|
|
9026
|
-
const { attemptRecovery } = await import("./recovery-
|
|
9028
|
+
const { attemptRecovery } = await import("./recovery-LGY25LIM.js");
|
|
9027
9029
|
const recovery = await attemptRecovery(
|
|
9028
9030
|
session?.page,
|
|
9029
9031
|
sessionName,
|
|
@@ -9190,9 +9192,9 @@ function createRPCHandler() {
|
|
|
9190
9192
|
return result;
|
|
9191
9193
|
}
|
|
9192
9194
|
async function handlePluginsReload() {
|
|
9193
|
-
const { resetPluginLoader } = await import("./plugin-singleton-
|
|
9195
|
+
const { resetPluginLoader } = await import("./plugin-singleton-GJO7EZXB.js");
|
|
9194
9196
|
resetPluginLoader();
|
|
9195
|
-
const loader = await import("./plugin-singleton-
|
|
9197
|
+
const loader = await import("./plugin-singleton-GJO7EZXB.js").then((m) => m.getPluginLoader());
|
|
9196
9198
|
const sites = loader.getCore().loader.getSites();
|
|
9197
9199
|
return { ok: true, plugins: sites.length };
|
|
9198
9200
|
}
|
|
@@ -9588,7 +9590,7 @@ function createRPCHandler() {
|
|
|
9588
9590
|
if (isNewFormat) {
|
|
9589
9591
|
try {
|
|
9590
9592
|
const replayErrors = [];
|
|
9591
|
-
const { SessionReplayer } = await import("./session-replayer-
|
|
9593
|
+
const { SessionReplayer } = await import("./session-replayer-N665T3G5.js");
|
|
9592
9594
|
const replayer = new SessionReplayer({
|
|
9593
9595
|
page: session.page,
|
|
9594
9596
|
stepDelay: slowMo * 500,
|
|
@@ -9613,6 +9615,8 @@ function createRPCHandler() {
|
|
|
9613
9615
|
duration,
|
|
9614
9616
|
eventsPlayed: result2.success,
|
|
9615
9617
|
totalEvents: result2.success + result2.failed + result2.skipped,
|
|
9618
|
+
healed: result2.healed,
|
|
9619
|
+
healedDetails: result2.healedDetails,
|
|
9616
9620
|
errors: replayErrors
|
|
9617
9621
|
});
|
|
9618
9622
|
} catch (e) {
|
|
@@ -9645,6 +9649,8 @@ function createRPCHandler() {
|
|
|
9645
9649
|
duration: typeof input.duration === "number" ? input.duration : 0,
|
|
9646
9650
|
eventsPlayed,
|
|
9647
9651
|
totalEvents,
|
|
9652
|
+
healed: typeof input.healed === "number" ? input.healed : 0,
|
|
9653
|
+
healedDetails: Array.isArray(input.healedDetails) ? input.healedDetails : [],
|
|
9648
9654
|
errors
|
|
9649
9655
|
};
|
|
9650
9656
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -137,6 +137,12 @@ interface XBContextOptions {
|
|
|
137
137
|
ignoreHTTPSErrors?: boolean;
|
|
138
138
|
/** S194: stealth 伪装配置(UA-CH 档案等)——经 context 传至 page 的注入层 */
|
|
139
139
|
stealthConfig?: Partial<StealthConfig>;
|
|
140
|
+
/** sup-s9: HTTP Basic/Digest 凭证——Fetch.authRequired 自动 ProvideCredentials;
|
|
141
|
+
* 缺省 CancelAuth(快速失败,不弹认证框不挂起) */
|
|
142
|
+
httpCredentials?: {
|
|
143
|
+
username: string;
|
|
144
|
+
password: string;
|
|
145
|
+
};
|
|
140
146
|
}
|
|
141
147
|
interface XBContext {
|
|
142
148
|
newPage(): Promise<XBPage>;
|
|
@@ -270,6 +276,8 @@ interface XBPage {
|
|
|
270
276
|
width: number;
|
|
271
277
|
height: number;
|
|
272
278
|
}): Promise<void>;
|
|
279
|
+
/** env-E2: 缩放变异——deviceScaleFactor 切换(CSS 视口尺寸不变) */
|
|
280
|
+
setDeviceScaleFactor(dsf: number): Promise<void>;
|
|
273
281
|
addInitScript(script: string): Promise<void>;
|
|
274
282
|
/** 覆盖当前页会话的 User-Agent(Network.setUserAgentOverride,会话级持久) */
|
|
275
283
|
setUserAgent(userAgent: string): Promise<void>;
|
|
@@ -286,6 +294,10 @@ interface XBPage {
|
|
|
286
294
|
route(url: string | RegExp, handler: (route: XBRoute) => Promise<void> | void): Promise<void>;
|
|
287
295
|
unroute(url: string | RegExp, handler?: (route: XBRoute) => Promise<void> | void): Promise<void>;
|
|
288
296
|
setInputFiles(selector: string, files: XBFilePayload | XBFilePayload[]): Promise<void>;
|
|
297
|
+
/** sup-s4: Dropzone 拖拽上传模拟——DataTransfer+File 派发 dragenter/dragover/drop */
|
|
298
|
+
dropFiles(selector: string, payload: XBFilePayload): Promise<void>;
|
|
299
|
+
/** sup-s11: beforeunload 自动应答语义(accept=离开默认 / dismiss=留守) */
|
|
300
|
+
setBeforeUnloadBehavior(mode: 'accept' | 'dismiss'): void;
|
|
289
301
|
dragAndDrop(source: string, target: string): Promise<void>;
|
|
290
302
|
on(event: string, handler: Function): void;
|
|
291
303
|
off(event: string, handler: Function): void;
|
|
@@ -1136,7 +1148,7 @@ interface DetectionConfig {
|
|
|
1136
1148
|
* along with optional `waitForHuman` (CAPTCHA handling) and
|
|
1137
1149
|
* `detectAntiBot` (anti-bot detection) capabilities.
|
|
1138
1150
|
*/
|
|
1139
|
-
interface BrowserCommandContext extends CommandContext {
|
|
1151
|
+
interface BrowserCommandContext extends Omit<CommandContext, 'waitForHuman' | 'detectAntiBot' | 'page'> {
|
|
1140
1152
|
page: XBPage;
|
|
1141
1153
|
browser: XBBrowser;
|
|
1142
1154
|
browserContext: XBContext;
|
|
@@ -1853,7 +1865,7 @@ interface HoverContext {
|
|
|
1853
1865
|
}
|
|
1854
1866
|
interface UserAction {
|
|
1855
1867
|
id: number;
|
|
1856
|
-
type: 'click' | 'input' | 'change' | 'keydown' | 'submit' | 'scroll' | 'navigation' | 'goto' | 'cdp-fill' | 'cdp-click' | 'cdp-eval' | 'filechooser' | 'dblclick' | 'contextmenu' | 'hover' | 'drag' | 'resize' | 'clipboard' | 'touch' | 'focus' | 'visibility' | 'popup_appear' | 'discovered_filters';
|
|
1868
|
+
type: 'click' | 'input' | 'change' | 'keydown' | 'submit' | 'scroll' | 'navigation' | 'goto' | 'cdp-fill' | 'cdp-click' | 'cdp-eval' | 'filechooser' | 'dblclick' | 'contextmenu' | 'hover' | 'drag' | 'resize' | 'clipboard' | 'touch' | 'focus' | 'visibility' | 'drop' | 'popup_appear' | 'discovered_filters';
|
|
1857
1869
|
timestamp: number;
|
|
1858
1870
|
url: string;
|
|
1859
1871
|
pageTitle: string;
|
|
@@ -1877,6 +1889,24 @@ interface UserAction {
|
|
|
1877
1889
|
placeholder?: string;
|
|
1878
1890
|
ariaLabel?: string;
|
|
1879
1891
|
href?: string;
|
|
1892
|
+
/** 结构地址(r6):祖先 form 在同级 form 中的序 + 元素在 form 内同 tag
|
|
1893
|
+
* 兄弟中的序(仅 form 直接子元素捕获)。布局位移后坐标失效时仍可定位。 */
|
|
1894
|
+
ordinal?: {
|
|
1895
|
+
formNth: number;
|
|
1896
|
+
tagNth: number;
|
|
1897
|
+
};
|
|
1898
|
+
/** 关联 label 的文本(r16):for= 关联或祖先 label 包裹。行重排/虚拟
|
|
1899
|
+
* 列表重建后结构序失效时的内容锚。 */
|
|
1900
|
+
labelText?: string;
|
|
1901
|
+
/** 元素尺寸(r25):录制时 rounded rect。同指纹诱饵消歧的评分信号
|
|
1902
|
+
* (仅加分不否决——响应式布局合法改变尺寸)。 */
|
|
1903
|
+
size?: {
|
|
1904
|
+
w: number;
|
|
1905
|
+
h: number;
|
|
1906
|
+
};
|
|
1907
|
+
/** 所在行文本(r27):closest('tr,li') 的 textContent 前 40 字符。
|
|
1908
|
+
* 表格/列表行重排后结构序失效时的内容锚(label 锚的行推广)。 */
|
|
1909
|
+
rowText?: string;
|
|
1880
1910
|
};
|
|
1881
1911
|
value?: string;
|
|
1882
1912
|
key?: string;
|
|
@@ -2277,6 +2307,12 @@ interface PlaybackResult {
|
|
|
2277
2307
|
event?: RecordedEvent;
|
|
2278
2308
|
error: string;
|
|
2279
2309
|
}>;
|
|
2310
|
+
/** r13: 自愈步数与明细(SessionReplayer 路径填充) */
|
|
2311
|
+
healed?: number;
|
|
2312
|
+
healedDetails?: Array<{
|
|
2313
|
+
index: number;
|
|
2314
|
+
strategy: string;
|
|
2315
|
+
}>;
|
|
2280
2316
|
}
|
|
2281
2317
|
/**
|
|
2282
2318
|
* Engine for playing back a recorded browser session.
|
|
@@ -2908,26 +2944,38 @@ interface HTTPServerConfig {
|
|
|
2908
2944
|
port?: number;
|
|
2909
2945
|
host?: string;
|
|
2910
2946
|
tokens?: string[];
|
|
2947
|
+
/**
|
|
2948
|
+
* Explicit CORS origin allowlist for remote web clients (e.g.
|
|
2949
|
+
* `['https://app.example']`, or `['*']` to opt back into wildcard).
|
|
2950
|
+
* When omitted, only loopback browser origins are granted CORS.
|
|
2951
|
+
*/
|
|
2952
|
+
corsOrigins?: string[];
|
|
2911
2953
|
}
|
|
2912
2954
|
|
|
2913
2955
|
/**
|
|
2914
2956
|
* HTTP server exposing the xbrowser REST API for remote command execution.
|
|
2915
2957
|
*
|
|
2916
2958
|
* Provides endpoints for health checks, session management, single command
|
|
2917
|
-
* execution, and command chain execution. Supports
|
|
2959
|
+
* execution, and command chain execution. Supports Bearer token
|
|
2918
2960
|
* authentication via config or environment variable.
|
|
2961
|
+
*
|
|
2962
|
+
* Secure defaults: binds loopback (127.0.0.1) only, and grants CORS only
|
|
2963
|
+
* to loopback browser origins. Binding a non-loopback host requires a
|
|
2964
|
+
* token — `start()` refuses otherwise.
|
|
2919
2965
|
*/
|
|
2920
2966
|
declare class HTTPServer {
|
|
2921
2967
|
private port;
|
|
2922
2968
|
private host;
|
|
2923
2969
|
private server;
|
|
2924
2970
|
private validTokens;
|
|
2971
|
+
private corsOrigins;
|
|
2925
2972
|
constructor(config?: HTTPServerConfig);
|
|
2926
2973
|
/**
|
|
2927
2974
|
* Start the HTTP server and begin listening for requests.
|
|
2928
2975
|
*
|
|
2929
2976
|
* @returns The actual port and host the server bound to.
|
|
2930
|
-
* @throws If the server is already running
|
|
2977
|
+
* @throws If the server is already running, if binding a non-loopback
|
|
2978
|
+
* host without an auth token, or if the port cannot be bound.
|
|
2931
2979
|
*/
|
|
2932
2980
|
start(): Promise<{
|
|
2933
2981
|
port: number;
|