@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/index.js CHANGED
@@ -1,3 +1,24 @@
1
+ import {
2
+ filterRecording,
3
+ parseExcludeTypes
4
+ } from "./chunk-ANVL2ID2.js";
5
+ import {
6
+ closeAllSessions,
7
+ closeEphemeralContext,
8
+ closeSessionByName,
9
+ createEphemeralContext,
10
+ createSession,
11
+ destroyBrowser,
12
+ findOrRestoreSession,
13
+ findSession,
14
+ getAllSessions,
15
+ getBrowser,
16
+ getSessionById,
17
+ resetForTesting,
18
+ resolveLaunchOpts,
19
+ saveSessionDiskMeta,
20
+ setActivePage
21
+ } from "./chunk-7V3B7VPX.js";
1
22
  import {
2
23
  detectAntiBot,
3
24
  formatDetectionMessage
@@ -62,38 +83,10 @@ import {
62
83
  printExtractSummary
63
84
  } from "./chunk-X46HDAOT.js";
64
85
  import {
65
- filterRecording,
66
- parseExcludeTypes
67
- } from "./chunk-ANVL2ID2.js";
68
- import {
69
- SessionRecorder
70
- } from "./chunk-NODRQGOK.js";
71
- import {
72
- addKnownIssue,
73
- getKnowledgePath,
74
- init_site_knowledge,
75
- listSiteKnowledge,
76
- readSiteKnowledge,
77
- readSiteKnowledgeMarkdown
78
- } from "./chunk-OZKD3W4X.js";
79
- import {
80
- closeAllSessions,
81
- closeEphemeralContext,
82
- closeSessionByName,
83
- createEphemeralContext,
84
- createSession,
85
- destroyBrowser,
86
- findOrRestoreSession,
87
- findSession,
88
- getAllSessions,
89
- getBrowser,
90
- getSessionById,
91
- resetForTesting,
92
- resolveLaunchOpts,
93
- saveSessionDiskMeta,
94
- setActivePage
95
- } from "./chunk-B753M33E.js";
96
- import "./chunk-PYQGDBAF.js";
86
+ rand,
87
+ sleep,
88
+ wheelDelta
89
+ } from "./chunk-A5HJ6IRE.js";
97
90
  import "./chunk-TNEN6VQ2.js";
98
91
  import {
99
92
  errMsg
@@ -114,6 +107,17 @@ import {
114
107
  networkAnomalyRule,
115
108
  pageLifecycleRule
116
109
  } from "./chunk-H2A5JUK5.js";
110
+ import {
111
+ SessionRecorder
112
+ } from "./chunk-NODRQGOK.js";
113
+ import {
114
+ addKnownIssue,
115
+ getKnowledgePath,
116
+ init_site_knowledge,
117
+ listSiteKnowledge,
118
+ readSiteKnowledge,
119
+ readSiteKnowledgeMarkdown
120
+ } from "./chunk-OZKD3W4X.js";
117
121
  import {
118
122
  __require
119
123
  } from "./chunk-KFQGP6VL.js";
@@ -385,7 +389,8 @@ var gotoCommand = registerCommand({
385
389
  parameters: z.object({
386
390
  url: z.string(),
387
391
  waitUntil: z.enum(["load", "domcontentloaded", "networkidle", "commit"]).optional(),
388
- timeout: z.number().optional()
392
+ timeout: z.number().optional(),
393
+ referrer: z.string().optional()
389
394
  }),
390
395
  result: z.object({
391
396
  url: z.string(),
@@ -406,7 +411,9 @@ var gotoCommand = registerCommand({
406
411
  try {
407
412
  response = await ctx.page.goto(url, {
408
413
  waitUntil: p.waitUntil || "domcontentloaded",
409
- ...p.timeout ? { timeout: p.timeout } : {}
414
+ ...p.timeout ? { timeout: p.timeout } : {},
415
+ // referrer(d54):模拟从源页面点链接进入 —— document.referrer 非空
416
+ ...p.referrer ? { referer: p.referrer } : {}
410
417
  });
411
418
  } catch (err) {
412
419
  const msg = err instanceof Error ? err.message : String(err);
@@ -933,21 +940,34 @@ var scrollCommand = registerCommand({
933
940
  }),
934
941
  handler: async (p, ctx) => {
935
942
  const distance = p.distance ?? 500;
936
- const deltas = {
937
- down: [0, distance],
938
- up: [0, -distance],
939
- right: [distance, 0],
940
- left: [-distance, 0]
941
- };
942
- const [dx, dy] = deltas[p.direction];
943
+ const sign = { down: 1, up: -1, right: 1, left: -1 };
944
+ const vertical = p.direction === "down" || p.direction === "up";
945
+ const s = sign[p.direction];
943
946
  if (p.selector) {
944
947
  const element = ctx.page.locator(p.selector).first();
945
948
  await element.evaluate((el, args) => {
946
949
  const [dxx, dyy] = args;
947
950
  el.scrollBy(dxx, dyy);
948
- }, [dx, dy]);
951
+ }, [vertical ? 0 : distance * s, vertical ? distance * s : 0]);
952
+ } else if (process.env.XBROWSER_STEALTH !== "off") {
953
+ let acc = 0;
954
+ let step = 0;
955
+ while (acc < distance && step < 60) {
956
+ const d = Math.min(wheelDelta(step), distance - acc);
957
+ if (d < 1) break;
958
+ await ctx.page.mouse.wheel(
959
+ vertical ? 0 : d * s,
960
+ vertical ? d * s : 0
961
+ );
962
+ acc += d;
963
+ step++;
964
+ await sleep(rand(16, 28));
965
+ }
949
966
  } else {
950
- await ctx.page.mouse.wheel(dx, dy);
967
+ await ctx.page.mouse.wheel(
968
+ vertical ? 0 : distance * s,
969
+ vertical ? distance * s : 0
970
+ );
951
971
  }
952
972
  return ok5({ direction: p.direction, distance });
953
973
  }
@@ -7873,7 +7893,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
7873
7893
  }
7874
7894
  let targetPageOverride = null;
7875
7895
  if (_target && extraOpts?.cdpEndpoint) {
7876
- const { findTargetPage } = await import("./browser-KJWBHGHX.js");
7896
+ const { findTargetPage } = await import("./browser-3KTEVTMU.js");
7877
7897
  targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
7878
7898
  if (!targetPageOverride) {
7879
7899
  return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
@@ -8153,6 +8173,9 @@ async function executeChain(input, options) {
8153
8173
  for (const pipeline of pipelines) {
8154
8174
  const { type, pipeline: commands } = pipeline;
8155
8175
  for (const cmdStr of commands) {
8176
+ if (process.env.XBROWSER_CHAIN_PACE === "human" && results.length > 0) {
8177
+ await new Promise((r) => setTimeout(r, 800 + Math.random() * 1700));
8178
+ }
8156
8179
  const parts = splitCommand(cmdStr);
8157
8180
  if (parts.length === 0) continue;
8158
8181
  const cmdName = parts[0];
@@ -10561,12 +10584,33 @@ function normalizeSelector(input) {
10561
10584
 
10562
10585
  // src/cli/browser-routes.ts
10563
10586
  import { helpGenerator } from "@dyyz1993/xcli-core";
10587
+ function autoCompleteParams(cmdName, params, options) {
10588
+ try {
10589
+ const cmd = getCommand(cmdName);
10590
+ if (!cmd?.parameters) return params;
10591
+ const schema = asZodSchema(cmd.parameters);
10592
+ const shape = schema?.shape ?? schema?._def?.shape;
10593
+ if (!shape) return params;
10594
+ for (const key of Object.keys(shape)) {
10595
+ if (params[key] !== void 0) continue;
10596
+ const v = options[key];
10597
+ if (v === void 0 || v === true && key === "json" || key === "yaml") continue;
10598
+ if (typeof v === "string" && v === "") continue;
10599
+ params[key] = v;
10600
+ }
10601
+ return params;
10602
+ } catch {
10603
+ return params;
10604
+ }
10605
+ }
10564
10606
  function parseSelectorFlags(args, options) {
10565
- const selector = options.s || options.selector || options["selector"];
10566
- const value = options.v || options.value;
10607
+ const rawSelector = options.s ?? options.selector;
10608
+ const rawValue = options.v ?? options.value;
10609
+ const selector = typeof rawSelector === "string" ? normalizeSelector(rawSelector) : void 0;
10610
+ const value = typeof rawValue === "string" ? rawValue : void 0;
10567
10611
  const remaining = args.filter((a) => !a.startsWith("-"));
10568
10612
  return {
10569
- selector: selector ? normalizeSelector(selector) : void 0,
10613
+ selector,
10570
10614
  value,
10571
10615
  remaining
10572
10616
  };
@@ -10654,7 +10698,11 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
10654
10698
  if (!sel || !txt)
10655
10699
  outputError("Usage: xbrowser type <selector> <text>\n xbrowser type -s <selector> -v <text>");
10656
10700
  cmdName = "type";
10657
- params = { selector: sel, text: txt };
10701
+ params = {
10702
+ selector: sel,
10703
+ text: txt,
10704
+ ...options.delay !== void 0 ? { delay: Number(options.delay) } : {}
10705
+ };
10658
10706
  break;
10659
10707
  }
10660
10708
  case "press": {
@@ -10796,7 +10844,13 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
10796
10844
  outputError("Usage: xbrowser mouse <move|click|dblclick> <x> <y>\n xbrowser mouse --action <action> --x <x> --y <y>");
10797
10845
  }
10798
10846
  cmdName = "mouse";
10799
- params = { action, x, y, ...options.button ? { button: options.button } : {} };
10847
+ params = {
10848
+ action,
10849
+ x,
10850
+ y,
10851
+ ...options.button ? { button: options.button } : {},
10852
+ ...options.steps !== void 0 ? { steps: Number(options.steps) } : {}
10853
+ };
10800
10854
  break;
10801
10855
  }
10802
10856
  case "html":
@@ -10998,6 +11052,7 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
10998
11052
  if (target) {
10999
11053
  params = { ...params, _target: target };
11000
11054
  }
11055
+ params = autoCompleteParams(cmdName, params, options);
11001
11056
  const tabIndex = options.tab;
11002
11057
  if (tabIndex !== void 0) {
11003
11058
  params = { ...params, _tabIndex: Number(tabIndex) };
@@ -14051,7 +14106,7 @@ Run "xbrowser ${command} ${subCommand} --help" to see available parameters.`
14051
14106
  const targetPage = pages[cmdTabIndex];
14052
14107
  await targetPage.bringToFront().catch(() => {
14053
14108
  });
14054
- const { setActivePage: setActivePage2 } = await import("./browser-KJWBHGHX.js");
14109
+ const { setActivePage: setActivePage2 } = await import("./browser-3KTEVTMU.js");
14055
14110
  setActivePage2(session, targetPage);
14056
14111
  }
14057
14112
  }
@@ -17224,7 +17279,7 @@ var DataCollector = class {
17224
17279
  return results;
17225
17280
  }
17226
17281
  async createBrowserContext() {
17227
- const { launch } = await import("./cdp-driver-AHKUT57K.js");
17282
+ const { launch } = await import("./cdp-driver-OC37OT4B.js");
17228
17283
  const { browser } = await launch({
17229
17284
  headless: true,
17230
17285
  args: ["--no-sandbox", "--disable-setuid-sandbox"]
@@ -34,7 +34,7 @@ var SessionReplayer = class {
34
34
  if (this.opts.page) {
35
35
  this.page = this.opts.page;
36
36
  } else if (this.opts.cdpUrl) {
37
- const { launch } = await import("./cdp-driver-4SFS6GNY.js");
37
+ const { launch } = await import("./cdp-driver-DKNLIA6B.js");
38
38
  const { browser } = await launch({ cdpEndpoint: this.opts.cdpUrl });
39
39
  let contexts = browser.contexts();
40
40
  for (let i = 0; i < 10 && contexts.length === 0; i++) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xbrowser/cli",
3
- "version": "1.14.0",
3
+ "version": "1.16.0",
4
4
  "description": "Browser automation CLI for web scraping, headless browsing, SEO analysis, and AI agent workflows. A command-line alternative to Playwright, Puppeteer, and Selenium.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,11 +1,11 @@
1
- import {
2
- buildViewerUrl
3
- } from "./chunk-TZPKFUBT.js";
4
- import "./chunk-CG3D3CHY.js";
5
1
  import {
6
2
  HumanInteractionManager
7
3
  } from "./chunk-OMU63E6J.js";
4
+ import {
5
+ buildViewerUrl
6
+ } from "./chunk-TZPKFUBT.js";
8
7
  import "./chunk-HBMEFSTB.js";
8
+ import "./chunk-CG3D3CHY.js";
9
9
  import "./chunk-KFQGP6VL.js";
10
10
 
11
11
  // src/recovery.ts
@@ -1,11 +1,11 @@
1
- import {
2
- buildViewerUrl
3
- } from "./chunk-3OD76SUE.js";
4
- import "./chunk-Q2DFJQGS.js";
5
1
  import {
6
2
  HumanInteractionManager
7
3
  } from "./chunk-TEXCXIBW.js";
4
+ import {
5
+ buildViewerUrl
6
+ } from "./chunk-3OD76SUE.js";
8
7
  import "./chunk-ZTHE5RBZ.js";
8
+ import "./chunk-Q2DFJQGS.js";
9
9
  import "./chunk-KFQGP6VL.js";
10
10
 
11
11
  // src/recovery.ts