@xbrowser/cli 1.1.2 → 1.2.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/cli.js CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  resolveLaunchOpts,
26
26
  saveSessionDiskMeta,
27
27
  setActivePage
28
- } from "./chunk-XVZ6NKRJ.js";
28
+ } from "./chunk-MNFOCOL6.js";
29
29
  import "./chunk-TNEN6VQ2.js";
30
30
  import {
31
31
  forwardCommandLog,
@@ -800,6 +800,21 @@ var waitForSelectorDef = {
800
800
  }
801
801
  };
802
802
  var waitCommand = registerCommand({ name: "wait", selectorParams: ["selector"], ...waitForSelectorDef });
803
+ var waitForTimeoutCommand = registerCommand({
804
+ name: "waitForTimeout",
805
+ description: "Wait for a specified number of milliseconds",
806
+ scope: "project",
807
+ parameters: z4.object({
808
+ timeout: z4.number().describe("Milliseconds to wait").default(1e3)
809
+ }),
810
+ result: z4.object({
811
+ waited: z4.number()
812
+ }),
813
+ handler: async (p) => {
814
+ await new Promise((r) => setTimeout(r, p.timeout));
815
+ return ok4({ waited: p.timeout });
816
+ }
817
+ });
803
818
 
804
819
  // src/commands/scroll.ts
805
820
  import { z as z5 } from "zod";
@@ -1665,7 +1680,7 @@ var healthCheckCommand = registerCommand({
1665
1680
  issues.push({
1666
1681
  severity: "error",
1667
1682
  category: "links",
1668
- message: `Broken link (fetch error): ${href} \u2014 ${errMsg(err) || "unknown"}`
1683
+ message: `Broken link (fetch error): ${href} \u2014 ${(err instanceof Error ? err.message : String(err)) || "unknown"}`
1669
1684
  });
1670
1685
  }
1671
1686
  }
@@ -2341,9 +2356,53 @@ var scrapeCommand = registerCommand({
2341
2356
  }
2342
2357
  let content;
2343
2358
  switch (p.format) {
2344
- case "markdown":
2359
+ case "markdown": {
2360
+ const tablesMd = await page.evaluate(() => {
2361
+ const tableSelectors = [
2362
+ "table",
2363
+ '[role="table"]',
2364
+ '[role="grid"]',
2365
+ '[class*="el-table"]',
2366
+ // Element UI
2367
+ '[class*="ant-table"]',
2368
+ // Ant Design
2369
+ '[class*="MuiTable"]',
2370
+ // Material UI
2371
+ '[class*="table"]'
2372
+ // Generic table-like
2373
+ ].join(",");
2374
+ const tables = document.querySelectorAll(tableSelectors);
2375
+ if (tables.length === 0) return "";
2376
+ return Array.from(tables).map((table) => {
2377
+ const rows = table.querySelectorAll('tr, [role="row"], [class*="row"]');
2378
+ if (rows.length === 0) return "";
2379
+ const mdRows = Array.from(rows).map((row) => {
2380
+ const cells = row.querySelectorAll('th, td, [role="columnheader"], [role="cell"], [class*="cell"], [class*="col"]');
2381
+ return "| " + Array.from(cells).map((c) => {
2382
+ const cellText = c.innerText?.trim().replace(/\n/g, " ") || "";
2383
+ return cellText.replace(/\|/g, "\\|") || "";
2384
+ }).join(" | ") + " |";
2385
+ }).join("\n");
2386
+ const headerRow = rows[0];
2387
+ const headerCells = headerRow.querySelectorAll('th, [role="columnheader"], [class*="header"]');
2388
+ const hasHeader = headerCells.length > 0;
2389
+ if (hasHeader && mdRows) {
2390
+ const headerCount = headerCells.length;
2391
+ const sep = "| " + Array(headerCount).fill("---").join(" | ") + " |";
2392
+ return mdRows.split("\n").map((line, i) => {
2393
+ if (i === 0) return line + "\n" + sep;
2394
+ return line;
2395
+ }).join("\n");
2396
+ }
2397
+ return mdRows;
2398
+ }).join("\n\n");
2399
+ });
2345
2400
  content = htmlToMarkdown(html, { onlyMainContent: p.onlyMainContent });
2401
+ if (tablesMd) {
2402
+ content = tablesMd + "\n\n" + content;
2403
+ }
2346
2404
  break;
2405
+ }
2347
2406
  case "html":
2348
2407
  content = html;
2349
2408
  break;
@@ -5283,6 +5342,7 @@ function parseCommandChain(input, options) {
5283
5342
  continue;
5284
5343
  }
5285
5344
  if (char === ";") {
5345
+ lastOperator = "sequence";
5286
5346
  flushPipeline();
5287
5347
  continue;
5288
5348
  }
@@ -5337,6 +5397,7 @@ registerCommandDefinition("uncheck", ["selector"]);
5337
5397
  registerCommandDefinition("hover", ["selector"]);
5338
5398
  registerCommandDefinition("dblclick", ["selector"]);
5339
5399
  registerCommandDefinition("wait", ["selector"]);
5400
+ registerCommandDefinition("waitForTimeout", ["timeout"]);
5340
5401
  registerCommandDefinition("screenshot", []);
5341
5402
  registerCommandDefinition("eval", ["expression"]);
5342
5403
  registerCommandDefinition("scroll", ["direction"]);
@@ -6969,7 +7030,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
6969
7030
  }
6970
7031
  let targetPageOverride = null;
6971
7032
  if (_target && extraOpts?.cdpEndpoint) {
6972
- const { findTargetPage } = await import("./browser-DZVIVKOA.js");
7033
+ const { findTargetPage } = await import("./browser-PZX7PO23.js");
6973
7034
  targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
6974
7035
  if (!targetPageOverride) {
6975
7036
  return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
@@ -9477,7 +9538,17 @@ var SELECTOR_COMMANDS = /* @__PURE__ */ new Set([
9477
9538
  "dblclick",
9478
9539
  "wait"
9479
9540
  ]);
9541
+ var CAMEL_TO_KEBAB = {
9542
+ getCookies: "get-cookies",
9543
+ setCookie: "set-cookie",
9544
+ clearCookies: "clear-cookies",
9545
+ getLocalStorage: "get-local-storage",
9546
+ setLocalStorage: "set-local-storage",
9547
+ clearLocalStorage: "clear-local-storage",
9548
+ setViewport: "set-viewport"
9549
+ };
9480
9550
  async function handleBrowserCommand(command, args, options, sessionName, mode, cdpEndpoint) {
9551
+ command = CAMEL_TO_KEBAB[command] || command;
9481
9552
  if (args.includes("--help") || args.includes("-h") || options.help || options.h) {
9482
9553
  const cmdDef = getCommand(command);
9483
9554
  if (cmdDef) {
@@ -9607,7 +9678,7 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
9607
9678
  type: options.type,
9608
9679
  selector: options.selector || options.s,
9609
9680
  base64: !!options.base64,
9610
- output: options.output || options.o
9681
+ output: options.output || options.o || args[0]
9611
9682
  };
9612
9683
  break;
9613
9684
  case "eval":
@@ -9844,6 +9915,7 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
9844
9915
  outputResult(result.data, mode);
9845
9916
  console.error(`
9846
9917
  \u26A0\uFE0F ${hint}`);
9918
+ process.exit(1);
9847
9919
  } else {
9848
9920
  outputResult(result.data, mode);
9849
9921
  }
@@ -9938,11 +10010,6 @@ async function handleSession(args, options, mode, _cdpEndpoint) {
9938
10010
  }
9939
10011
 
9940
10012
  // src/cli/plugin-routes.ts
9941
- var pluginLoader3 = null;
9942
- function getPluginLoader2() {
9943
- if (!pluginLoader3) pluginLoader3 = new XBrowserPluginLoader();
9944
- return pluginLoader3;
9945
- }
9946
10013
  async function buildRuntimePluginInfo() {
9947
10014
  const loader = await getPluginLoader();
9948
10015
  const sites = loader.getCore().loader.getSites();
@@ -10200,6 +10267,10 @@ async function handlePlugin(args, options, mode) {
10200
10267
  } else {
10201
10268
  result = await installer.installWithMarketplaceFallback(source, installOpts);
10202
10269
  }
10270
+ try {
10271
+ await (await getPluginLoader()).reloadPlugin(result.name);
10272
+ } catch {
10273
+ }
10203
10274
  outputResult(
10204
10275
  { ok: true, name: result.name, source: result.source, path: result.path },
10205
10276
  mode
@@ -10215,6 +10286,11 @@ async function handlePlugin(args, options, mode) {
10215
10286
  outputError(`Plugin "${name}" is not installed. Use 'xbrowser plugin list' to see installed plugins.`);
10216
10287
  }
10217
10288
  await installer.uninstall(name);
10289
+ try {
10290
+ const loader = await getPluginLoader();
10291
+ await loader.reloadPlugin(name);
10292
+ } catch {
10293
+ }
10218
10294
  outputResult({ ok: true, name }, mode);
10219
10295
  break;
10220
10296
  }
@@ -10268,7 +10344,7 @@ Total: ${enrichedPlugins.length} plugins`);
10268
10344
  case "reload": {
10269
10345
  const name = subArgs[0];
10270
10346
  if (!name) outputError("Usage: xbrowser plugin reload <name>");
10271
- await getPluginLoader2().reloadPlugin(name);
10347
+ (await getPluginLoader()).reloadPlugin(name);
10272
10348
  outputResult({ ok: true, name }, mode);
10273
10349
  break;
10274
10350
  }
@@ -12116,10 +12192,18 @@ function extractCdpFromArgv(argv) {
12116
12192
  async function handleStdinMode(stdinCommands, argv) {
12117
12193
  const chain = stdinCommands.join(" && ");
12118
12194
  const cdpEndpoint = argv ? extractCdpFromArgv(argv) : void 0;
12119
- const chainResult = await executeChain(chain, { fileMode: true, cdpEndpoint });
12195
+ const sessionName = argv ? extractSessionNameFromArgv(argv) : "default";
12196
+ const chainResult = await executeChain(chain, { fileMode: true, cdpEndpoint, sessionName });
12120
12197
  printChainResult(chainResult);
12121
12198
  if (!chainResult.success) throw new Error("Command failed");
12122
12199
  }
12200
+ function extractSessionNameFromArgv(argv) {
12201
+ for (let i = 0; i < argv.length; i++) {
12202
+ if (argv[i] === "--session" && argv[i + 1]) return argv[i + 1];
12203
+ if (typeof argv[i] === "string" && argv[i].startsWith("--session=")) return argv[i].slice(10);
12204
+ }
12205
+ return process.env.XBROWSER_SESSION || "default";
12206
+ }
12123
12207
  async function handleEvalMode(argv) {
12124
12208
  const evalCommands = parseEvalFlags(argv);
12125
12209
  if (evalCommands.length === 0) return;
@@ -12259,6 +12343,31 @@ async function routeCommand(argvIn, stdinCommands) {
12259
12343
  }
12260
12344
  return;
12261
12345
  }
12346
+ const SUBCOMMAND_HELP = {
12347
+ session: "session open|close|kill|list [--session <name>] [--cdp <endpoint>]",
12348
+ plugin: "plugin install|uninstall|list|reload|schema|search|info <name>",
12349
+ record: "record start|stop|status [--url <url>] [--name <flow>]",
12350
+ daemon: "daemon status [--port <port>]",
12351
+ replay: "replay <file> [--slow-mo <ms>] [--stop-on-error]",
12352
+ create: "create <name> [--template static|dynamic|login|api]",
12353
+ run: "run <file>",
12354
+ serve: "serve [--port <port>] [--token <token>]",
12355
+ remote: "remote <url> [command] [--token <token>]",
12356
+ convert: "convert <file> [--to js|py|sh]",
12357
+ extract: "extract <file> [--format json|yaml]",
12358
+ filter: "filter <file> [--include <type>] [--exclude <type>]",
12359
+ test: "test <name> [--cdp <endpoint>]",
12360
+ viewer: "viewer [--session <name>]",
12361
+ kill: "kill [--all]",
12362
+ net: "net [--cdp <endpoint>]"
12363
+ };
12364
+ const subHelp = SUBCOMMAND_HELP[command];
12365
+ if (subHelp) {
12366
+ console.log(`
12367
+ Usage: xbrowser ${subHelp}
12368
+ `);
12369
+ return;
12370
+ }
12262
12371
  showMainHelp();
12263
12372
  return;
12264
12373
  }
@@ -12745,7 +12854,7 @@ async function main() {
12745
12854
  const command = process.argv[2];
12746
12855
  const isLongRunning = command === "preview" || command === "serve";
12747
12856
  if (!isLongRunning) {
12748
- const { ensureProcessCanExit } = await import("./browser-DZVIVKOA.js");
12857
+ const { ensureProcessCanExit } = await import("./browser-PZX7PO23.js");
12749
12858
  await ensureProcessCanExit().catch(() => {
12750
12859
  });
12751
12860
  process.exit(exitCode);
@@ -21,8 +21,8 @@ import {
21
21
  resolveLaunchOpts,
22
22
  saveSessionDiskMeta,
23
23
  setActivePage
24
- } from "./chunk-NDAMCPIJ.js";
25
- import "./chunk-E5WWMKXB.js";
24
+ } from "./chunk-SLQR57XZ.js";
25
+ import "./chunk-QFROODUU.js";
26
26
  import "./chunk-TNEN6VQ2.js";
27
27
  import {
28
28
  getDaemonConfig,
@@ -758,6 +758,21 @@ var waitForSelectorDef = {
758
758
  }
759
759
  };
760
760
  var waitCommand = registerCommand({ name: "wait", selectorParams: ["selector"], ...waitForSelectorDef });
761
+ var waitForTimeoutCommand = registerCommand({
762
+ name: "waitForTimeout",
763
+ description: "Wait for a specified number of milliseconds",
764
+ scope: "project",
765
+ parameters: z4.object({
766
+ timeout: z4.number().describe("Milliseconds to wait").default(1e3)
767
+ }),
768
+ result: z4.object({
769
+ waited: z4.number()
770
+ }),
771
+ handler: async (p) => {
772
+ await new Promise((r) => setTimeout(r, p.timeout));
773
+ return ok4({ waited: p.timeout });
774
+ }
775
+ });
761
776
 
762
777
  // src/commands/scroll.ts
763
778
  import { z as z5 } from "zod";
@@ -1623,7 +1638,7 @@ var healthCheckCommand = registerCommand({
1623
1638
  issues.push({
1624
1639
  severity: "error",
1625
1640
  category: "links",
1626
- message: `Broken link (fetch error): ${href} \u2014 ${errMsg(err) || "unknown"}`
1641
+ message: `Broken link (fetch error): ${href} \u2014 ${(err instanceof Error ? err.message : String(err)) || "unknown"}`
1627
1642
  });
1628
1643
  }
1629
1644
  }
@@ -2299,9 +2314,53 @@ var scrapeCommand = registerCommand({
2299
2314
  }
2300
2315
  let content;
2301
2316
  switch (p.format) {
2302
- case "markdown":
2317
+ case "markdown": {
2318
+ const tablesMd = await page.evaluate(() => {
2319
+ const tableSelectors = [
2320
+ "table",
2321
+ '[role="table"]',
2322
+ '[role="grid"]',
2323
+ '[class*="el-table"]',
2324
+ // Element UI
2325
+ '[class*="ant-table"]',
2326
+ // Ant Design
2327
+ '[class*="MuiTable"]',
2328
+ // Material UI
2329
+ '[class*="table"]'
2330
+ // Generic table-like
2331
+ ].join(",");
2332
+ const tables = document.querySelectorAll(tableSelectors);
2333
+ if (tables.length === 0) return "";
2334
+ return Array.from(tables).map((table) => {
2335
+ const rows = table.querySelectorAll('tr, [role="row"], [class*="row"]');
2336
+ if (rows.length === 0) return "";
2337
+ const mdRows = Array.from(rows).map((row) => {
2338
+ const cells = row.querySelectorAll('th, td, [role="columnheader"], [role="cell"], [class*="cell"], [class*="col"]');
2339
+ return "| " + Array.from(cells).map((c) => {
2340
+ const cellText = c.innerText?.trim().replace(/\n/g, " ") || "";
2341
+ return cellText.replace(/\|/g, "\\|") || "";
2342
+ }).join(" | ") + " |";
2343
+ }).join("\n");
2344
+ const headerRow = rows[0];
2345
+ const headerCells = headerRow.querySelectorAll('th, [role="columnheader"], [class*="header"]');
2346
+ const hasHeader = headerCells.length > 0;
2347
+ if (hasHeader && mdRows) {
2348
+ const headerCount = headerCells.length;
2349
+ const sep = "| " + Array(headerCount).fill("---").join(" | ") + " |";
2350
+ return mdRows.split("\n").map((line, i) => {
2351
+ if (i === 0) return line + "\n" + sep;
2352
+ return line;
2353
+ }).join("\n");
2354
+ }
2355
+ return mdRows;
2356
+ }).join("\n\n");
2357
+ });
2303
2358
  content = htmlToMarkdown(html, { onlyMainContent: p.onlyMainContent });
2359
+ if (tablesMd) {
2360
+ content = tablesMd + "\n\n" + content;
2361
+ }
2304
2362
  break;
2363
+ }
2305
2364
  case "html":
2306
2365
  content = html;
2307
2366
  break;
@@ -5241,6 +5300,7 @@ function parseCommandChain(input, options) {
5241
5300
  continue;
5242
5301
  }
5243
5302
  if (char === ";") {
5303
+ lastOperator = "sequence";
5244
5304
  flushPipeline();
5245
5305
  continue;
5246
5306
  }
@@ -5295,6 +5355,7 @@ registerCommandDefinition("uncheck", ["selector"]);
5295
5355
  registerCommandDefinition("hover", ["selector"]);
5296
5356
  registerCommandDefinition("dblclick", ["selector"]);
5297
5357
  registerCommandDefinition("wait", ["selector"]);
5358
+ registerCommandDefinition("waitForTimeout", ["timeout"]);
5298
5359
  registerCommandDefinition("screenshot", []);
5299
5360
  registerCommandDefinition("eval", ["expression"]);
5300
5361
  registerCommandDefinition("scroll", ["direction"]);
@@ -6927,7 +6988,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
6927
6988
  }
6928
6989
  let targetPageOverride = null;
6929
6990
  if (_target && extraOpts?.cdpEndpoint) {
6930
- const { findTargetPage } = await import("./browser-ZF4EJ3SK.js");
6991
+ const { findTargetPage } = await import("./browser-CWI6BXYK.js");
6931
6992
  targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
6932
6993
  if (!targetPageOverride) {
6933
6994
  return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
@@ -8611,7 +8672,7 @@ function createRPCHandler() {
8611
8672
  const isNewFormat = Array.isArray(parsed.actions);
8612
8673
  if (isNewFormat) {
8613
8674
  try {
8614
- const { SessionReplayer } = await import("./session-replayer-UHITXIOZ.js");
8675
+ const { SessionReplayer } = await import("./session-replayer-IXLSCF5U.js");
8615
8676
  const replayer = new SessionReplayer({
8616
8677
  page: session.page,
8617
8678
  stepDelay: slowMo * 500,
package/dist/index.js CHANGED
@@ -81,8 +81,8 @@ import {
81
81
  resolveLaunchOpts,
82
82
  saveSessionDiskMeta,
83
83
  setActivePage
84
- } from "./chunk-OH7CB2P6.js";
85
- import "./chunk-E5WWMKXB.js";
84
+ } from "./chunk-6V57JME6.js";
85
+ import "./chunk-QFROODUU.js";
86
86
  import "./chunk-TNEN6VQ2.js";
87
87
  import {
88
88
  errMsg
@@ -840,6 +840,21 @@ var waitForSelectorDef = {
840
840
  }
841
841
  };
842
842
  var waitCommand = registerCommand({ name: "wait", selectorParams: ["selector"], ...waitForSelectorDef });
843
+ var waitForTimeoutCommand = registerCommand({
844
+ name: "waitForTimeout",
845
+ description: "Wait for a specified number of milliseconds",
846
+ scope: "project",
847
+ parameters: z4.object({
848
+ timeout: z4.number().describe("Milliseconds to wait").default(1e3)
849
+ }),
850
+ result: z4.object({
851
+ waited: z4.number()
852
+ }),
853
+ handler: async (p) => {
854
+ await new Promise((r) => setTimeout(r, p.timeout));
855
+ return ok4({ waited: p.timeout });
856
+ }
857
+ });
843
858
 
844
859
  // src/commands/scroll.ts
845
860
  import { z as z5 } from "zod";
@@ -1705,7 +1720,7 @@ var healthCheckCommand = registerCommand({
1705
1720
  issues.push({
1706
1721
  severity: "error",
1707
1722
  category: "links",
1708
- message: `Broken link (fetch error): ${href} \u2014 ${errMsg(err) || "unknown"}`
1723
+ message: `Broken link (fetch error): ${href} \u2014 ${(err instanceof Error ? err.message : String(err)) || "unknown"}`
1709
1724
  });
1710
1725
  }
1711
1726
  }
@@ -2381,9 +2396,53 @@ var scrapeCommand = registerCommand({
2381
2396
  }
2382
2397
  let content;
2383
2398
  switch (p.format) {
2384
- case "markdown":
2399
+ case "markdown": {
2400
+ const tablesMd = await page.evaluate(() => {
2401
+ const tableSelectors = [
2402
+ "table",
2403
+ '[role="table"]',
2404
+ '[role="grid"]',
2405
+ '[class*="el-table"]',
2406
+ // Element UI
2407
+ '[class*="ant-table"]',
2408
+ // Ant Design
2409
+ '[class*="MuiTable"]',
2410
+ // Material UI
2411
+ '[class*="table"]'
2412
+ // Generic table-like
2413
+ ].join(",");
2414
+ const tables = document.querySelectorAll(tableSelectors);
2415
+ if (tables.length === 0) return "";
2416
+ return Array.from(tables).map((table) => {
2417
+ const rows = table.querySelectorAll('tr, [role="row"], [class*="row"]');
2418
+ if (rows.length === 0) return "";
2419
+ const mdRows = Array.from(rows).map((row) => {
2420
+ const cells = row.querySelectorAll('th, td, [role="columnheader"], [role="cell"], [class*="cell"], [class*="col"]');
2421
+ return "| " + Array.from(cells).map((c) => {
2422
+ const cellText = c.innerText?.trim().replace(/\n/g, " ") || "";
2423
+ return cellText.replace(/\|/g, "\\|") || "";
2424
+ }).join(" | ") + " |";
2425
+ }).join("\n");
2426
+ const headerRow = rows[0];
2427
+ const headerCells = headerRow.querySelectorAll('th, [role="columnheader"], [class*="header"]');
2428
+ const hasHeader = headerCells.length > 0;
2429
+ if (hasHeader && mdRows) {
2430
+ const headerCount = headerCells.length;
2431
+ const sep = "| " + Array(headerCount).fill("---").join(" | ") + " |";
2432
+ return mdRows.split("\n").map((line, i) => {
2433
+ if (i === 0) return line + "\n" + sep;
2434
+ return line;
2435
+ }).join("\n");
2436
+ }
2437
+ return mdRows;
2438
+ }).join("\n\n");
2439
+ });
2385
2440
  content = htmlToMarkdown(html, { onlyMainContent: p.onlyMainContent });
2441
+ if (tablesMd) {
2442
+ content = tablesMd + "\n\n" + content;
2443
+ }
2386
2444
  break;
2445
+ }
2387
2446
  case "html":
2388
2447
  content = html;
2389
2448
  break;
@@ -5600,6 +5659,7 @@ function parseCommandChain(input, options) {
5600
5659
  continue;
5601
5660
  }
5602
5661
  if (char === ";") {
5662
+ lastOperator = "sequence";
5603
5663
  flushPipeline();
5604
5664
  continue;
5605
5665
  }
@@ -5654,6 +5714,7 @@ registerCommandDefinition("uncheck", ["selector"]);
5654
5714
  registerCommandDefinition("hover", ["selector"]);
5655
5715
  registerCommandDefinition("dblclick", ["selector"]);
5656
5716
  registerCommandDefinition("wait", ["selector"]);
5717
+ registerCommandDefinition("waitForTimeout", ["timeout"]);
5657
5718
  registerCommandDefinition("screenshot", []);
5658
5719
  registerCommandDefinition("eval", ["expression"]);
5659
5720
  registerCommandDefinition("scroll", ["direction"]);
@@ -7289,7 +7350,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
7289
7350
  }
7290
7351
  let targetPageOverride = null;
7291
7352
  if (_target && extraOpts?.cdpEndpoint) {
7292
- const { findTargetPage } = await import("./browser-H55TWH2I.js");
7353
+ const { findTargetPage } = await import("./browser-JP2LFPR2.js");
7293
7354
  targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
7294
7355
  if (!targetPageOverride) {
7295
7356
  return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
@@ -9817,7 +9878,17 @@ var SELECTOR_COMMANDS = /* @__PURE__ */ new Set([
9817
9878
  "dblclick",
9818
9879
  "wait"
9819
9880
  ]);
9881
+ var CAMEL_TO_KEBAB = {
9882
+ getCookies: "get-cookies",
9883
+ setCookie: "set-cookie",
9884
+ clearCookies: "clear-cookies",
9885
+ getLocalStorage: "get-local-storage",
9886
+ setLocalStorage: "set-local-storage",
9887
+ clearLocalStorage: "clear-local-storage",
9888
+ setViewport: "set-viewport"
9889
+ };
9820
9890
  async function handleBrowserCommand(command, args, options, sessionName, mode, cdpEndpoint) {
9891
+ command = CAMEL_TO_KEBAB[command] || command;
9821
9892
  if (args.includes("--help") || args.includes("-h") || options.help || options.h) {
9822
9893
  const cmdDef = getCommand(command);
9823
9894
  if (cmdDef) {
@@ -9947,7 +10018,7 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
9947
10018
  type: options.type,
9948
10019
  selector: options.selector || options.s,
9949
10020
  base64: !!options.base64,
9950
- output: options.output || options.o
10021
+ output: options.output || options.o || args[0]
9951
10022
  };
9952
10023
  break;
9953
10024
  case "eval":
@@ -10184,6 +10255,7 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
10184
10255
  outputResult(result.data, mode);
10185
10256
  console.error(`
10186
10257
  \u26A0\uFE0F ${hint}`);
10258
+ process.exit(1);
10187
10259
  } else {
10188
10260
  outputResult(result.data, mode);
10189
10261
  }
@@ -10278,11 +10350,6 @@ async function handleSession(args, options, mode, _cdpEndpoint) {
10278
10350
  }
10279
10351
 
10280
10352
  // src/cli/plugin-routes.ts
10281
- var pluginLoader3 = null;
10282
- function getPluginLoader2() {
10283
- if (!pluginLoader3) pluginLoader3 = new XBrowserPluginLoader();
10284
- return pluginLoader3;
10285
- }
10286
10353
  async function buildRuntimePluginInfo() {
10287
10354
  const loader = await getPluginLoader();
10288
10355
  const sites = loader.getCore().loader.getSites();
@@ -10540,6 +10607,10 @@ async function handlePlugin(args, options, mode) {
10540
10607
  } else {
10541
10608
  result = await installer.installWithMarketplaceFallback(source, installOpts);
10542
10609
  }
10610
+ try {
10611
+ await (await getPluginLoader()).reloadPlugin(result.name);
10612
+ } catch {
10613
+ }
10543
10614
  outputResult(
10544
10615
  { ok: true, name: result.name, source: result.source, path: result.path },
10545
10616
  mode
@@ -10555,6 +10626,11 @@ async function handlePlugin(args, options, mode) {
10555
10626
  outputError(`Plugin "${name}" is not installed. Use 'xbrowser plugin list' to see installed plugins.`);
10556
10627
  }
10557
10628
  await installer.uninstall(name);
10629
+ try {
10630
+ const loader = await getPluginLoader();
10631
+ await loader.reloadPlugin(name);
10632
+ } catch {
10633
+ }
10558
10634
  outputResult({ ok: true, name }, mode);
10559
10635
  break;
10560
10636
  }
@@ -10608,7 +10684,7 @@ Total: ${enrichedPlugins.length} plugins`);
10608
10684
  case "reload": {
10609
10685
  const name = subArgs[0];
10610
10686
  if (!name) outputError("Usage: xbrowser plugin reload <name>");
10611
- await getPluginLoader2().reloadPlugin(name);
10687
+ (await getPluginLoader()).reloadPlugin(name);
10612
10688
  outputResult({ ok: true, name }, mode);
10613
10689
  break;
10614
10690
  }
@@ -12456,10 +12532,18 @@ function extractCdpFromArgv(argv) {
12456
12532
  async function handleStdinMode(stdinCommands, argv) {
12457
12533
  const chain = stdinCommands.join(" && ");
12458
12534
  const cdpEndpoint = argv ? extractCdpFromArgv(argv) : void 0;
12459
- const chainResult = await executeChain(chain, { fileMode: true, cdpEndpoint });
12535
+ const sessionName = argv ? extractSessionNameFromArgv(argv) : "default";
12536
+ const chainResult = await executeChain(chain, { fileMode: true, cdpEndpoint, sessionName });
12460
12537
  printChainResult(chainResult);
12461
12538
  if (!chainResult.success) throw new Error("Command failed");
12462
12539
  }
12540
+ function extractSessionNameFromArgv(argv) {
12541
+ for (let i = 0; i < argv.length; i++) {
12542
+ if (argv[i] === "--session" && argv[i + 1]) return argv[i + 1];
12543
+ if (typeof argv[i] === "string" && argv[i].startsWith("--session=")) return argv[i].slice(10);
12544
+ }
12545
+ return process.env.XBROWSER_SESSION || "default";
12546
+ }
12463
12547
  async function handleEvalMode(argv) {
12464
12548
  const evalCommands = parseEvalFlags(argv);
12465
12549
  if (evalCommands.length === 0) return;
@@ -12599,6 +12683,31 @@ async function routeCommand(argvIn, stdinCommands) {
12599
12683
  }
12600
12684
  return;
12601
12685
  }
12686
+ const SUBCOMMAND_HELP = {
12687
+ session: "session open|close|kill|list [--session <name>] [--cdp <endpoint>]",
12688
+ plugin: "plugin install|uninstall|list|reload|schema|search|info <name>",
12689
+ record: "record start|stop|status [--url <url>] [--name <flow>]",
12690
+ daemon: "daemon status [--port <port>]",
12691
+ replay: "replay <file> [--slow-mo <ms>] [--stop-on-error]",
12692
+ create: "create <name> [--template static|dynamic|login|api]",
12693
+ run: "run <file>",
12694
+ serve: "serve [--port <port>] [--token <token>]",
12695
+ remote: "remote <url> [command] [--token <token>]",
12696
+ convert: "convert <file> [--to js|py|sh]",
12697
+ extract: "extract <file> [--format json|yaml]",
12698
+ filter: "filter <file> [--include <type>] [--exclude <type>]",
12699
+ test: "test <name> [--cdp <endpoint>]",
12700
+ viewer: "viewer [--session <name>]",
12701
+ kill: "kill [--all]",
12702
+ net: "net [--cdp <endpoint>]"
12703
+ };
12704
+ const subHelp = SUBCOMMAND_HELP[command];
12705
+ if (subHelp) {
12706
+ console.log(`
12707
+ Usage: xbrowser ${subHelp}
12708
+ `);
12709
+ return;
12710
+ }
12602
12711
  showMainHelp();
12603
12712
  return;
12604
12713
  }
@@ -15872,7 +15981,7 @@ var DataCollector = class {
15872
15981
  return results;
15873
15982
  }
15874
15983
  async createBrowserContext() {
15875
- const { launch } = await import("./cdp-driver-WWQBRTPF.js");
15984
+ const { launch } = await import("./cdp-driver-S5STYUZZ.js");
15876
15985
  const { browser } = await launch({
15877
15986
  headless: true,
15878
15987
  args: ["--no-sandbox", "--disable-setuid-sandbox"]
@@ -31,7 +31,7 @@ var SessionReplayer = class {
31
31
  if (this.opts.page) {
32
32
  this.page = this.opts.page;
33
33
  } else if (this.opts.cdpUrl) {
34
- const { launch } = await import("./cdp-driver-WWQBRTPF.js");
34
+ const { launch } = await import("./cdp-driver-S5STYUZZ.js");
35
35
  const { browser } = await launch({ cdpEndpoint: this.opts.cdpUrl });
36
36
  let contexts = browser.contexts();
37
37
  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.1.2",
3
+ "version": "1.2.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": {
@@ -96,7 +96,7 @@
96
96
  "sharp": "^0.34.5",
97
97
  "turndown": "^7.2.4",
98
98
  "turndown-plugin-gfm": "^1.0.2",
99
- "ws": "^8.20.0",
99
+ "ws": "^8.21.0",
100
100
  "yaml": "^2.8.4",
101
101
  "zod": "^3.24.0"
102
102
  },