@xbrowser/cli 1.0.2 → 1.0.4

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.
@@ -20,9 +20,9 @@ import {
20
20
  saveSessionDiskMeta,
21
21
  setActivePage,
22
22
  touchSession
23
- } from "./chunk-QIK2I3VQ.js";
24
- import "./chunk-PPG4D2EW.js";
25
- import "./chunk-BBMRDUYQ.js";
23
+ } from "./chunk-DKWR54XQ.js";
24
+ import "./chunk-TNEN6VQ2.js";
25
+ import "./chunk-GDKLH7ZY.js";
26
26
  import "./chunk-KFQGP6VL.js";
27
27
  export {
28
28
  closeAllSessions,
@@ -20,8 +20,10 @@ import {
20
20
  saveSessionDiskMeta,
21
21
  setActivePage,
22
22
  touchSession
23
- } from "./chunk-CAFNSGYM.js";
24
- import "./chunk-BBMRDUYQ.js";
23
+ } from "./chunk-LRBSUKUZ.js";
24
+ import "./chunk-N2JFPWMI.js";
25
+ import "./chunk-TNEN6VQ2.js";
26
+ import "./chunk-GDKLH7ZY.js";
25
27
  import "./chunk-KFQGP6VL.js";
26
28
  export {
27
29
  closeAllSessions,
@@ -20,10 +20,11 @@ import {
20
20
  saveSessionDiskMeta,
21
21
  setActivePage,
22
22
  touchSession
23
- } from "./chunk-JPA2ZT2R.js";
24
- import "./chunk-PPG4D2EW.js";
25
- import "./chunk-BBMRDUYQ.js";
26
- import "./chunk-ZZ2TFWIV.js";
23
+ } from "./chunk-TWWOIJM7.js";
24
+ import "./chunk-N2JFPWMI.js";
25
+ import "./chunk-TNEN6VQ2.js";
26
+ import "./chunk-GDKLH7ZY.js";
27
+ import "./chunk-ABXMBNQ6.js";
27
28
  import "./chunk-KFQGP6VL.js";
28
29
  export {
29
30
  closeAllSessions,
@@ -1,10 +1,11 @@
1
1
  import {
2
2
  connectToCDP,
3
+ errMsg,
3
4
  findChrome,
4
5
  getCDPTargets,
5
6
  killChrome,
6
7
  launchChrome
7
- } from "./chunk-JPHCY4TC.js";
8
+ } from "./chunk-AMI64BSD.js";
8
9
  import {
9
10
  __require
10
11
  } from "./chunk-3RG5ZIWI.js";
@@ -1200,7 +1201,7 @@ var XBPageImpl = class _XBPageImpl {
1200
1201
  );
1201
1202
  if (result) return result;
1202
1203
  } catch (err) {
1203
- lastError = err;
1204
+ lastError = err instanceof Error ? err : new Error(errMsg(err));
1204
1205
  }
1205
1206
  const pollMs = typeof polling === "number" ? polling : 16;
1206
1207
  await this.waitForTimeout(pollMs);
@@ -1610,6 +1611,19 @@ Last error: ${lastError.message}` : "";
1610
1611
  async _cdpSend(method, params) {
1611
1612
  return this.conn.send(method, params, this.sessionId);
1612
1613
  }
1614
+ /**
1615
+ * 开启/关闭原生文件选择框拦截(CDP stateful 开关)。
1616
+ *
1617
+ * - enabled=true(执行期默认):点击上传按钮时不弹系统文件框,改发 Page.fileChooserOpened 事件,
1618
+ * page 的 'filechooser' 监听器拿到 chooser 后用 setFiles/setInputFiles 注入文件。
1619
+ * - enabled=false(录制期默认):真实文件选择框正常弹出,用户手动选文件;
1620
+ * 前端 input[type=file] 的 change 事件由 action signal 脚本捕获记录。
1621
+ *
1622
+ * 可多次调用切换状态(CDP 协议是 stateful 的)。
1623
+ */
1624
+ async setFileDialogInterception(enabled) {
1625
+ await this.conn.send("Page.setInterceptFileChooserDialog", { enabled }, this.sessionId).catch((e) => console.error("[XBPage] setInterceptFileChooserDialog failed:", errMsg(e)));
1626
+ }
1613
1627
  /** Subscribe to a CDP event on this page's session. Returns unsubscribe function. */
1614
1628
  _subscribe(event, handler) {
1615
1629
  return this.conn.subscribe(event, this.sessionId, handler);
@@ -2310,7 +2324,7 @@ var XBBrowserImpl = class {
2310
2324
  this._exitHandler = null;
2311
2325
  }
2312
2326
  if (this.childProcess) {
2313
- const { killChrome: killChrome2 } = await import("./launcher-YARP45UY.js");
2327
+ const { killChrome: killChrome2 } = await import("./launcher-OZXJQPNG.js");
2314
2328
  await killChrome2(this.childProcess, this.tmpDir);
2315
2329
  }
2316
2330
  await this.conn.close();
@@ -2445,7 +2459,7 @@ var XBBrowserImpl = class {
2445
2459
  if (pageTargets.length === 0 && httpFallbackUrl) {
2446
2460
  console.log(`[discoverContexts] Target.getTargets returned ${targetInfos.length} targets (0 page type). Falling back to HTTP /json/list at ${httpFallbackUrl}`);
2447
2461
  try {
2448
- const { getCDPTargets: getCDPTargets2 } = await import("./launcher-YARP45UY.js");
2462
+ const { getCDPTargets: getCDPTargets2 } = await import("./launcher-OZXJQPNG.js");
2449
2463
  const httpPages = await getCDPTargets2(httpFallbackUrl);
2450
2464
  console.log(`[discoverContexts] HTTP /json/list returned ${httpPages.length} pages`);
2451
2465
  for (const p of httpPages) {
@@ -2460,7 +2474,7 @@ var XBBrowserImpl = class {
2460
2474
  }
2461
2475
  console.log(`[discoverContexts] After HTTP fallback: ${targetInfos.length} total targets, ${targetInfos.filter((t) => t.type === "page").length} pages`);
2462
2476
  } catch (err) {
2463
- console.log(`[discoverContexts] HTTP fallback failed: ${err.message}`);
2477
+ console.log(`[discoverContexts] HTTP fallback failed: ${errMsg(err)}`);
2464
2478
  }
2465
2479
  }
2466
2480
  const pagesByContext = /* @__PURE__ */ new Map();
@@ -14,14 +14,15 @@ import {
14
14
  scrollIntoView,
15
15
  waitForActionable,
16
16
  waitForNetworkIdle
17
- } from "./chunk-PPG4D2EW.js";
17
+ } from "./chunk-N2JFPWMI.js";
18
18
  import {
19
19
  connectToCDP,
20
20
  findChrome,
21
21
  getCDPTargets,
22
22
  killChrome,
23
23
  launchChrome
24
- } from "./chunk-BBMRDUYQ.js";
24
+ } from "./chunk-TNEN6VQ2.js";
25
+ import "./chunk-GDKLH7ZY.js";
25
26
  import "./chunk-KFQGP6VL.js";
26
27
  export {
27
28
  CDPConnection,
@@ -1,3 +1,7 @@
1
+ import {
2
+ errMsg
3
+ } from "./chunk-GDKLH7ZY.js";
4
+
1
5
  // src/daemon/daemon.ts
2
6
  import { spawn } from "child_process";
3
7
  import { join, dirname } from "path";
@@ -170,7 +174,7 @@ async function forwardExec(command, params, session = "default", cdpEndpoint, ti
170
174
  try {
171
175
  return await rpcCall("exec", rpcParams, timeoutMs);
172
176
  } catch (e) {
173
- return { success: false, data: null, message: e.message, duration: 0 };
177
+ return { success: false, data: null, message: errMsg(e), duration: 0 };
174
178
  }
175
179
  }
176
180
  async function forwardChain(input, session = "default", cdpEndpoint) {
@@ -179,7 +183,7 @@ async function forwardChain(input, session = "default", cdpEndpoint) {
179
183
  try {
180
184
  return await rpcCall("chain", params, 12e4);
181
185
  } catch (e) {
182
- return { success: false, steps: [], totalDuration: 0, stoppedReason: e.message };
186
+ return { success: false, steps: [], totalDuration: 0, stoppedReason: errMsg(e) };
183
187
  }
184
188
  }
185
189
  async function forwardAgentObserve(session = "default", options) {
@@ -1290,7 +1290,7 @@ var CDPInterceptorProxy = class {
1290
1290
  const ctx = {
1291
1291
  method: request.method,
1292
1292
  params: request.params ?? {},
1293
- sessionId: makeCompoundId(browserWs._cdpSession, request.sessionId),
1293
+ sessionId: makeCompoundId("_cdpSession" in browserWs ? browserWs._cdpSession : void 0, request.sessionId),
1294
1294
  direction: "client\u2192browser"
1295
1295
  };
1296
1296
  const decision = this.engine.evaluate(ctx);
@@ -4,6 +4,13 @@ import {
4
4
 
5
5
  // src/cdp-driver/launcher.ts
6
6
  import { spawn } from "child_process";
7
+
8
+ // src/utils/error.ts
9
+ function errMsg(e) {
10
+ return e instanceof Error ? e.message : String(e);
11
+ }
12
+
13
+ // src/cdp-driver/launcher.ts
7
14
  import { existsSync as fsExistsSync } from "fs";
8
15
  var DEFAULT_CHROME_PATHS = {
9
16
  darwin: [
@@ -146,7 +153,7 @@ async function launchChrome(options = {}) {
146
153
  } catch (err) {
147
154
  const stderr = stderrLines.slice(-20).join("\n");
148
155
  const exitInfo = child.exitCode !== null ? ` (exit code: ${child.exitCode})` : " (still running)";
149
- throw new Error(`${err.message}${exitInfo}
156
+ throw new Error(`${errMsg(err)}${exitInfo}
150
157
  Chrome stderr:
151
158
  ${stderr || "(empty)"}`);
152
159
  }
@@ -250,6 +257,7 @@ function sleep(ms) {
250
257
  }
251
258
 
252
259
  export {
260
+ errMsg,
253
261
  DEFAULT_ARGS,
254
262
  ANTI_DETECT_ARGS,
255
263
  findChrome,
@@ -1,7 +1,10 @@
1
1
  import {
2
2
  connectToCDP,
3
3
  launchChrome
4
- } from "./chunk-BBMRDUYQ.js";
4
+ } from "./chunk-TNEN6VQ2.js";
5
+ import {
6
+ errMsg
7
+ } from "./chunk-GDKLH7ZY.js";
5
8
  import {
6
9
  __require
7
10
  } from "./chunk-KFQGP6VL.js";
@@ -1203,7 +1206,7 @@ var XBPageImpl = class _XBPageImpl {
1203
1206
  );
1204
1207
  if (result) return result;
1205
1208
  } catch (err) {
1206
- lastError = err;
1209
+ lastError = err instanceof Error ? err : new Error(errMsg(err));
1207
1210
  }
1208
1211
  const pollMs = typeof polling === "number" ? polling : 16;
1209
1212
  await this.waitForTimeout(pollMs);
@@ -1613,6 +1616,19 @@ Last error: ${lastError.message}` : "";
1613
1616
  async _cdpSend(method, params) {
1614
1617
  return this.conn.send(method, params, this.sessionId);
1615
1618
  }
1619
+ /**
1620
+ * 开启/关闭原生文件选择框拦截(CDP stateful 开关)。
1621
+ *
1622
+ * - enabled=true(执行期默认):点击上传按钮时不弹系统文件框,改发 Page.fileChooserOpened 事件,
1623
+ * page 的 'filechooser' 监听器拿到 chooser 后用 setFiles/setInputFiles 注入文件。
1624
+ * - enabled=false(录制期默认):真实文件选择框正常弹出,用户手动选文件;
1625
+ * 前端 input[type=file] 的 change 事件由 action signal 脚本捕获记录。
1626
+ *
1627
+ * 可多次调用切换状态(CDP 协议是 stateful 的)。
1628
+ */
1629
+ async setFileDialogInterception(enabled) {
1630
+ await this.conn.send("Page.setInterceptFileChooserDialog", { enabled }, this.sessionId).catch((e) => console.error("[XBPage] setInterceptFileChooserDialog failed:", errMsg(e)));
1631
+ }
1616
1632
  /** Subscribe to a CDP event on this page's session. Returns unsubscribe function. */
1617
1633
  _subscribe(event, handler) {
1618
1634
  return this.conn.subscribe(event, this.sessionId, handler);
@@ -2313,7 +2329,7 @@ var XBBrowserImpl = class {
2313
2329
  this._exitHandler = null;
2314
2330
  }
2315
2331
  if (this.childProcess) {
2316
- const { killChrome: killChrome2 } = await import("./launcher-QUJ4M2VS.js");
2332
+ const { killChrome: killChrome2 } = await import("./launcher-L2JNDB2H.js");
2317
2333
  await killChrome2(this.childProcess, this.tmpDir);
2318
2334
  }
2319
2335
  await this.conn.close();
@@ -2448,7 +2464,7 @@ var XBBrowserImpl = class {
2448
2464
  if (pageTargets.length === 0 && httpFallbackUrl) {
2449
2465
  console.log(`[discoverContexts] Target.getTargets returned ${targetInfos.length} targets (0 page type). Falling back to HTTP /json/list at ${httpFallbackUrl}`);
2450
2466
  try {
2451
- const { getCDPTargets: getCDPTargets3 } = await import("./launcher-QUJ4M2VS.js");
2467
+ const { getCDPTargets: getCDPTargets3 } = await import("./launcher-L2JNDB2H.js");
2452
2468
  const httpPages = await getCDPTargets3(httpFallbackUrl);
2453
2469
  console.log(`[discoverContexts] HTTP /json/list returned ${httpPages.length} pages`);
2454
2470
  for (const p of httpPages) {
@@ -2463,7 +2479,7 @@ var XBBrowserImpl = class {
2463
2479
  }
2464
2480
  console.log(`[discoverContexts] After HTTP fallback: ${targetInfos.length} total targets, ${targetInfos.filter((t) => t.type === "page").length} pages`);
2465
2481
  } catch (err) {
2466
- console.log(`[discoverContexts] HTTP fallback failed: ${err.message}`);
2482
+ console.log(`[discoverContexts] HTTP fallback failed: ${errMsg(err)}`);
2467
2483
  }
2468
2484
  }
2469
2485
  const pagesByContext = /* @__PURE__ */ new Map();
@@ -4015,7 +4031,7 @@ var CDPInterceptorProxy = class {
4015
4031
  const ctx = {
4016
4032
  method: request.method,
4017
4033
  params: request.params ?? {},
4018
- sessionId: makeCompoundId(browserWs._cdpSession, request.sessionId),
4034
+ sessionId: makeCompoundId("_cdpSession" in browserWs ? browserWs._cdpSession : void 0, request.sessionId),
4019
4035
  direction: "client\u2192browser"
4020
4036
  };
4021
4037
  const decision = this.engine.evaluate(ctx);
@@ -4283,7 +4299,7 @@ async function createBrowser(options) {
4283
4299
  }
4284
4300
  const { browser: browser2 } = await launch({ cdpEndpoint: realEndpoint });
4285
4301
  await browser2.discoverContexts().catch((err) => {
4286
- console.error(`[browser] discoverContexts failed: ${err.message}`);
4302
+ console.error(`[browser] discoverContexts failed: ${errMsg(err)}`);
4287
4303
  });
4288
4304
  return browser2;
4289
4305
  }
@@ -4434,7 +4450,7 @@ async function findOrRestoreSession(name, cdpEndpoint) {
4434
4450
  await installNetworkCapture(page, name);
4435
4451
  return session;
4436
4452
  } catch (e) {
4437
- console.error(`[Session Restore] Failed for "${name}":`, e.message);
4453
+ console.error(`[Session Restore] Failed for "${name}":`, errMsg(e));
4438
4454
  deleteSessionDiskMeta(name);
4439
4455
  return void 0;
4440
4456
  }
@@ -0,0 +1,8 @@
1
+ // src/utils/error.ts
2
+ function errMsg(e) {
3
+ return e instanceof Error ? e.message : String(e);
4
+ }
5
+
6
+ export {
7
+ errMsg
8
+ };
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  launch
3
- } from "./chunk-PPG4D2EW.js";
3
+ } from "./chunk-N2JFPWMI.js";
4
+ import {
5
+ errMsg
6
+ } from "./chunk-GDKLH7ZY.js";
4
7
 
5
8
  // src/browser.ts
6
9
  import { randomUUID } from "crypto";
@@ -1300,7 +1303,7 @@ var CDPInterceptorProxy = class {
1300
1303
  const ctx = {
1301
1304
  method: request.method,
1302
1305
  params: request.params ?? {},
1303
- sessionId: makeCompoundId(browserWs._cdpSession, request.sessionId),
1306
+ sessionId: makeCompoundId("_cdpSession" in browserWs ? browserWs._cdpSession : void 0, request.sessionId),
1304
1307
  direction: "client\u2192browser"
1305
1308
  };
1306
1309
  const decision = this.engine.evaluate(ctx);
@@ -1568,7 +1571,7 @@ async function createBrowser(options) {
1568
1571
  }
1569
1572
  const { browser: browser2 } = await launch({ cdpEndpoint: realEndpoint });
1570
1573
  await browser2.discoverContexts().catch((err) => {
1571
- console.error(`[browser] discoverContexts failed: ${err.message}`);
1574
+ console.error(`[browser] discoverContexts failed: ${errMsg(err)}`);
1572
1575
  });
1573
1576
  return browser2;
1574
1577
  }
@@ -1719,7 +1722,7 @@ async function findOrRestoreSession(name, cdpEndpoint) {
1719
1722
  await installNetworkCapture(page, name);
1720
1723
  return session;
1721
1724
  } catch (e) {
1722
- console.error(`[Session Restore] Failed for "${name}":`, e.message);
1725
+ console.error(`[Session Restore] Failed for "${name}":`, errMsg(e));
1723
1726
  deleteSessionDiskMeta(name);
1724
1727
  return void 0;
1725
1728
  }
@@ -1,7 +1,10 @@
1
1
  import {
2
2
  connectToCDP,
3
3
  launchChrome
4
- } from "./chunk-BBMRDUYQ.js";
4
+ } from "./chunk-TNEN6VQ2.js";
5
+ import {
6
+ errMsg
7
+ } from "./chunk-GDKLH7ZY.js";
5
8
  import {
6
9
  __require
7
10
  } from "./chunk-KFQGP6VL.js";
@@ -1197,7 +1200,7 @@ var XBPageImpl = class _XBPageImpl {
1197
1200
  );
1198
1201
  if (result) return result;
1199
1202
  } catch (err) {
1200
- lastError = err;
1203
+ lastError = err instanceof Error ? err : new Error(errMsg(err));
1201
1204
  }
1202
1205
  const pollMs = typeof polling === "number" ? polling : 16;
1203
1206
  await this.waitForTimeout(pollMs);
@@ -1607,6 +1610,19 @@ Last error: ${lastError.message}` : "";
1607
1610
  async _cdpSend(method, params) {
1608
1611
  return this.conn.send(method, params, this.sessionId);
1609
1612
  }
1613
+ /**
1614
+ * 开启/关闭原生文件选择框拦截(CDP stateful 开关)。
1615
+ *
1616
+ * - enabled=true(执行期默认):点击上传按钮时不弹系统文件框,改发 Page.fileChooserOpened 事件,
1617
+ * page 的 'filechooser' 监听器拿到 chooser 后用 setFiles/setInputFiles 注入文件。
1618
+ * - enabled=false(录制期默认):真实文件选择框正常弹出,用户手动选文件;
1619
+ * 前端 input[type=file] 的 change 事件由 action signal 脚本捕获记录。
1620
+ *
1621
+ * 可多次调用切换状态(CDP 协议是 stateful 的)。
1622
+ */
1623
+ async setFileDialogInterception(enabled) {
1624
+ await this.conn.send("Page.setInterceptFileChooserDialog", { enabled }, this.sessionId).catch((e) => console.error("[XBPage] setInterceptFileChooserDialog failed:", errMsg(e)));
1625
+ }
1610
1626
  /** Subscribe to a CDP event on this page's session. Returns unsubscribe function. */
1611
1627
  _subscribe(event, handler) {
1612
1628
  return this.conn.subscribe(event, this.sessionId, handler);
@@ -2307,7 +2323,7 @@ var XBBrowserImpl = class {
2307
2323
  this._exitHandler = null;
2308
2324
  }
2309
2325
  if (this.childProcess) {
2310
- const { killChrome: killChrome2 } = await import("./launcher-QUJ4M2VS.js");
2326
+ const { killChrome: killChrome2 } = await import("./launcher-L2JNDB2H.js");
2311
2327
  await killChrome2(this.childProcess, this.tmpDir);
2312
2328
  }
2313
2329
  await this.conn.close();
@@ -2442,7 +2458,7 @@ var XBBrowserImpl = class {
2442
2458
  if (pageTargets.length === 0 && httpFallbackUrl) {
2443
2459
  console.log(`[discoverContexts] Target.getTargets returned ${targetInfos.length} targets (0 page type). Falling back to HTTP /json/list at ${httpFallbackUrl}`);
2444
2460
  try {
2445
- const { getCDPTargets: getCDPTargets2 } = await import("./launcher-QUJ4M2VS.js");
2461
+ const { getCDPTargets: getCDPTargets2 } = await import("./launcher-L2JNDB2H.js");
2446
2462
  const httpPages = await getCDPTargets2(httpFallbackUrl);
2447
2463
  console.log(`[discoverContexts] HTTP /json/list returned ${httpPages.length} pages`);
2448
2464
  for (const p of httpPages) {
@@ -2457,7 +2473,7 @@ var XBBrowserImpl = class {
2457
2473
  }
2458
2474
  console.log(`[discoverContexts] After HTTP fallback: ${targetInfos.length} total targets, ${targetInfos.filter((t) => t.type === "page").length} pages`);
2459
2475
  } catch (err) {
2460
- console.log(`[discoverContexts] HTTP fallback failed: ${err.message}`);
2476
+ console.log(`[discoverContexts] HTTP fallback failed: ${errMsg(err)}`);
2461
2477
  }
2462
2478
  }
2463
2479
  const pagesByContext = /* @__PURE__ */ new Map();
@@ -1,3 +1,6 @@
1
+ import {
2
+ errMsg
3
+ } from "./chunk-GDKLH7ZY.js";
1
4
  import {
2
5
  __require
3
6
  } from "./chunk-KFQGP6VL.js";
@@ -146,7 +149,7 @@ async function launchChrome(options = {}) {
146
149
  } catch (err) {
147
150
  const stderr = stderrLines.slice(-20).join("\n");
148
151
  const exitInfo = child.exitCode !== null ? ` (exit code: ${child.exitCode})` : " (still running)";
149
- throw new Error(`${err.message}${exitInfo}
152
+ throw new Error(`${errMsg(err)}${exitInfo}
150
153
  Chrome stderr:
151
154
  ${stderr || "(empty)"}`);
152
155
  }
@@ -1,9 +1,12 @@
1
1
  import {
2
2
  launch
3
- } from "./chunk-PPG4D2EW.js";
3
+ } from "./chunk-N2JFPWMI.js";
4
+ import {
5
+ errMsg
6
+ } from "./chunk-GDKLH7ZY.js";
4
7
  import {
5
8
  CDPInterceptorProxy
6
- } from "./chunk-ZZ2TFWIV.js";
9
+ } from "./chunk-ABXMBNQ6.js";
7
10
 
8
11
  // src/browser.ts
9
12
  import { randomUUID } from "crypto";
@@ -203,7 +206,7 @@ async function createBrowser(options) {
203
206
  }
204
207
  const { browser: browser2 } = await launch({ cdpEndpoint: realEndpoint });
205
208
  await browser2.discoverContexts().catch((err) => {
206
- console.error(`[browser] discoverContexts failed: ${err.message}`);
209
+ console.error(`[browser] discoverContexts failed: ${errMsg(err)}`);
207
210
  });
208
211
  return browser2;
209
212
  }
@@ -354,7 +357,7 @@ async function findOrRestoreSession(name, cdpEndpoint) {
354
357
  await installNetworkCapture(page, name);
355
358
  return session;
356
359
  } catch (e) {
357
- console.error(`[Session Restore] Failed for "${name}":`, e.message);
360
+ console.error(`[Session Restore] Failed for "${name}":`, errMsg(e));
358
361
  deleteSessionDiskMeta(name);
359
362
  return void 0;
360
363
  }