@xbrowser/cli 1.8.6 → 1.9.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
@@ -57,7 +57,7 @@ import {
57
57
  } from "./chunk-GJAV3QGG.js";
58
58
  import {
59
59
  SessionRecorder
60
- } from "./chunk-RMYEHTLS.js";
60
+ } from "./chunk-YSCY52UJ.js";
61
61
  import {
62
62
  addKnownIssue,
63
63
  getKnowledgePath,
@@ -82,7 +82,7 @@ import {
82
82
  resolveLaunchOpts,
83
83
  saveSessionDiskMeta,
84
84
  setActivePage
85
- } from "./chunk-CJJ564VK.js";
85
+ } from "./chunk-MSQIPXKE.js";
86
86
  import "./chunk-VJNMAWPZ.js";
87
87
  import "./chunk-TNEN6VQ2.js";
88
88
  import {
@@ -109,7 +109,7 @@ import {
109
109
  // src/executor.ts
110
110
  import {
111
111
  ok as ok25,
112
- fail as fail8,
112
+ fail as fail9,
113
113
  isCommandResult,
114
114
  CompositeStorage as CompositeStorage2,
115
115
  TipCollector as TipCollector2,
@@ -2356,7 +2356,7 @@ var scrapeCommand = registerCommand({
2356
2356
  scope: "project",
2357
2357
  selectorParams: ["selector"],
2358
2358
  parameters: z15.object({
2359
- url: z15.string(),
2359
+ url: z15.string().optional(),
2360
2360
  selector: z15.string().optional(),
2361
2361
  timeout: z15.number().default(3e4),
2362
2362
  format: z15.enum(["markdown", "html", "text"]).default("markdown"),
@@ -2369,10 +2369,14 @@ var scrapeCommand = registerCommand({
2369
2369
  const { context, page } = await createEphemeralContext(resolveLaunchOpts(ctx));
2370
2370
  const maxAttempts = p.retries + 1;
2371
2371
  try {
2372
+ const targetUrl = p.url || page.url();
2373
+ if (!targetUrl || targetUrl === "about:blank") {
2374
+ return fail3("URL is required. Provide a URL or connect to a browser (--cdp) with a non-blank page.");
2375
+ }
2372
2376
  let lastError;
2373
2377
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
2374
2378
  try {
2375
- await page.goto(p.url, { waitUntil: "commit", timeout: p.timeout });
2379
+ await page.goto(targetUrl, { waitUntil: "commit", timeout: p.timeout });
2376
2380
  await page.waitForSelector("body", { timeout: p.timeout }).catch(() => {
2377
2381
  });
2378
2382
  await page.waitForLoadState("networkidle", Math.min(p.timeout, 8e3)).catch(() => {
@@ -2433,7 +2437,7 @@ var scrapeCommand = registerCommand({
2433
2437
  return { url: location.href, title: document.title, navigation, tables, forms: forms.slice(0, 20), links: links.slice(0, 30), mainText };
2434
2438
  });
2435
2439
  try {
2436
- persistFromScrape(p.url, structured);
2440
+ persistFromScrape(targetUrl, structured);
2437
2441
  } catch {
2438
2442
  }
2439
2443
  if (p.mode === "smart") {
@@ -2534,7 +2538,7 @@ var scrapeCommand = registerCommand({
2534
2538
 
2535
2539
  // src/commands/map.ts
2536
2540
  import { z as z16 } from "zod";
2537
- import { ok as ok16 } from "@dyyz1993/xcli-core";
2541
+ import { ok as ok16, fail as fail4 } from "@dyyz1993/xcli-core";
2538
2542
 
2539
2543
  // src/utils/url.ts
2540
2544
  var SKIP_EXTENSIONS = /* @__PURE__ */ new Set([
@@ -2770,7 +2774,7 @@ var mapCommand = registerCommand({
2770
2774
  description: "Discover all URLs on a website via sitemap and page link extraction",
2771
2775
  scope: "project",
2772
2776
  parameters: z16.object({
2773
- url: z16.string(),
2777
+ url: z16.string().optional(),
2774
2778
  search: z16.string().optional(),
2775
2779
  sitemap: z16.enum(["include", "only"]).optional(),
2776
2780
  includeSubdomains: z16.boolean().optional(),
@@ -2781,7 +2785,11 @@ var mapCommand = registerCommand({
2781
2785
  handler: async (p, ctx) => {
2782
2786
  const { context, page } = await createEphemeralContext(resolveLaunchOpts(ctx));
2783
2787
  try {
2784
- const links = await discoverUrls(page, p.url, {
2788
+ const targetUrl = p.url || page.url();
2789
+ if (!targetUrl || targetUrl === "about:blank") {
2790
+ return fail4("URL is required. Provide a URL or connect to a browser (--cdp) with a non-blank page.");
2791
+ }
2792
+ const links = await discoverUrls(page, targetUrl, {
2785
2793
  sitemap: p.sitemap,
2786
2794
  includeSubdomains: p.includeSubdomains,
2787
2795
  allowExternalLinks: p.allowExternalLinks,
@@ -3624,7 +3632,7 @@ ${errors.map((e) => ` - ${e.engine}: ${e.error}`).join("\n")}`
3624
3632
 
3625
3633
  // src/commands/network.ts
3626
3634
  import { z as z19 } from "zod";
3627
- import { ok as ok19, fail as fail4 } from "@dyyz1993/xcli-core";
3635
+ import { ok as ok19, fail as fail5 } from "@dyyz1993/xcli-core";
3628
3636
  function extractPath2(url) {
3629
3637
  try {
3630
3638
  const u = new URL(url);
@@ -3789,7 +3797,7 @@ var networkCommand = registerCommand({
3789
3797
  };
3790
3798
  if (p.listen) {
3791
3799
  const page2 = ctx.page;
3792
- if (!page2) return fail4("No active page. Use --cdp to connect first.");
3800
+ if (!page2) return fail5("No active page. Use --cdp to connect first.");
3793
3801
  const captures = [];
3794
3802
  const consoleMessages = [];
3795
3803
  const wsCaptures = [];
@@ -4446,7 +4454,7 @@ function parseMarkdownResults(rawText) {
4446
4454
 
4447
4455
  // src/commands/snapshot.ts
4448
4456
  import { z as z21 } from "zod";
4449
- import { ok as ok20, fail as fail5, normalizeTips as normalizeTips3 } from "@dyyz1993/xcli-core";
4457
+ import { ok as ok20, fail as fail6, normalizeTips as normalizeTips3 } from "@dyyz1993/xcli-core";
4450
4458
 
4451
4459
  // src/runtime/ref-store.ts
4452
4460
  var sessions = /* @__PURE__ */ new Map();
@@ -5417,7 +5425,7 @@ var snapshotCommand = registerCommand({
5417
5425
  persistSemantics(url, aria);
5418
5426
  return ok20({ url, title, aria, text, dom }, normalizeTips3(tips));
5419
5427
  }
5420
- return fail5(`Unknown snapshot type: ${p.type}`);
5428
+ return fail6(`Unknown snapshot type: ${p.type}`);
5421
5429
  }
5422
5430
  });
5423
5431
  function persistSemantics(url, aria) {
@@ -5586,7 +5594,7 @@ var waitForCommand = registerCommand({
5586
5594
 
5587
5595
  // src/commands/tab.ts
5588
5596
  import { z as z23 } from "zod";
5589
- import { ok as ok22, fail as fail6 } from "@dyyz1993/xcli-core";
5597
+ import { ok as ok22, fail as fail7 } from "@dyyz1993/xcli-core";
5590
5598
  var TabParams = z23.object({
5591
5599
  subcommand: z23.enum(["list", "new", "close", "switch"]),
5592
5600
  url: z23.string().optional(),
@@ -5603,7 +5611,7 @@ var tabCommand = registerCommand({
5603
5611
  }),
5604
5612
  handler: async (p, ctx) => {
5605
5613
  if (!ctx.browserContext) {
5606
- return fail6("No browser context available. Use --cdp to connect to a browser first.");
5614
+ return fail7("No browser context available. Use --cdp to connect to a browser first.");
5607
5615
  }
5608
5616
  const pages = ctx.browserContext.pages();
5609
5617
  switch (p.subcommand) {
@@ -5616,7 +5624,7 @@ var tabCommand = registerCommand({
5616
5624
  case "switch":
5617
5625
  return handleSwitch(p, pages, ctx);
5618
5626
  default:
5619
- return fail6(`Unknown subcommand: ${p.subcommand}`);
5627
+ return fail7(`Unknown subcommand: ${p.subcommand}`);
5620
5628
  }
5621
5629
  }
5622
5630
  });
@@ -5673,11 +5681,11 @@ async function handleNew(p, _pages, ctx) {
5673
5681
  }
5674
5682
  async function handleClose(p, pages, ctx) {
5675
5683
  if (pages.length <= 1) {
5676
- return fail6("Cannot close the last remaining tab");
5684
+ return fail7("Cannot close the last remaining tab");
5677
5685
  }
5678
5686
  const closeIndex = p.index ?? pages.indexOf(ctx.page);
5679
5687
  if (closeIndex < 0 || closeIndex >= pages.length) {
5680
- return fail6(`Invalid tab index: ${closeIndex}. Valid range: 0-${pages.length - 1}`);
5688
+ return fail7(`Invalid tab index: ${closeIndex}. Valid range: 0-${pages.length - 1}`);
5681
5689
  }
5682
5690
  const pageToClose = pages[closeIndex];
5683
5691
  const isActivePage = pageToClose === ctx.page;
@@ -5700,10 +5708,10 @@ async function handleClose(p, pages, ctx) {
5700
5708
  }
5701
5709
  async function handleSwitch(p, pages, ctx) {
5702
5710
  if (p.index === void 0) {
5703
- return fail6("Parameter --index is required for switch subcommand");
5711
+ return fail7("Parameter --index is required for switch subcommand");
5704
5712
  }
5705
5713
  if (p.index < 0 || p.index >= pages.length) {
5706
- return fail6(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
5714
+ return fail7(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
5707
5715
  }
5708
5716
  const targetPage = pages[p.index];
5709
5717
  await targetPage.bringToFront().catch(() => {
@@ -5955,7 +5963,7 @@ registerCommandDefinition("addinitscript", ["script"]);
5955
5963
 
5956
5964
  // src/commands/find.ts
5957
5965
  import { z as z25 } from "zod";
5958
- import { ok as ok24, fail as fail7, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
5966
+ import { ok as ok24, fail as fail8, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
5959
5967
  var actionSchema2 = z25.enum(["click", "fill", "type", "select", "hover", "check"]);
5960
5968
  var findCommand = registerCommand({
5961
5969
  name: "find",
@@ -5996,7 +6004,7 @@ var findCommand = registerCommand({
5996
6004
  });
5997
6005
  const count = await locator.count();
5998
6006
  if (count === 0) {
5999
- return fail7(`No element found with ${p.strategy}="${p.value}"`);
6007
+ return fail8(`No element found with ${p.strategy}="${p.value}"`);
6000
6008
  }
6001
6009
  const tips = [];
6002
6010
  const target = selectTarget(locator, p.strategy);
@@ -6008,15 +6016,15 @@ var findCommand = registerCommand({
6008
6016
  await target.click({ timeout: p.timeout, force: true });
6009
6017
  return okWithTips({ matched: count, selector, action: "click" }, tips);
6010
6018
  } else if (actionName === "fill") {
6011
- if (actionValue === void 0) return fail7("find fill requires a value");
6019
+ if (actionValue === void 0) return fail8("find fill requires a value");
6012
6020
  await target.fill(actionValue, { timeout: p.timeout, force: true });
6013
6021
  return okWithTips({ matched: count, selector, action: `fill("${actionValue}")` }, tips);
6014
6022
  } else if (actionName === "type") {
6015
- if (actionValue === void 0) return fail7("find type requires a value");
6023
+ if (actionValue === void 0) return fail8("find type requires a value");
6016
6024
  await target.type(actionValue, { delay: 10, timeout: p.timeout });
6017
6025
  return okWithTips({ matched: count, selector, action: `type("${actionValue}")` }, tips);
6018
6026
  } else if (actionName === "select") {
6019
- if (actionValue === void 0) return fail7("find select requires a value");
6027
+ if (actionValue === void 0) return fail8("find select requires a value");
6020
6028
  await target.selectOption(actionValue);
6021
6029
  return okWithTips({ matched: count, selector, action: `select("${actionValue}")` }, tips);
6022
6030
  } else if (actionName === "hover") {
@@ -7452,7 +7460,7 @@ async function guardCheck(commandName) {
7452
7460
  }
7453
7461
  }
7454
7462
  function errorResult(message) {
7455
- return { ...fail8(message), duration: 0 };
7463
+ return { ...fail9(message), duration: 0 };
7456
7464
  }
7457
7465
  function tipsToMessages(tips) {
7458
7466
  if (!tips || tips.length === 0) return [];
@@ -7532,7 +7540,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
7532
7540
  }
7533
7541
  let targetPageOverride = null;
7534
7542
  if (_target && extraOpts?.cdpEndpoint) {
7535
- const { findTargetPage } = await import("./browser-TLIDFFEG.js");
7543
+ const { findTargetPage } = await import("./browser-C63PFGPT.js");
7536
7544
  targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
7537
7545
  if (!targetPageOverride) {
7538
7546
  return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
@@ -7756,7 +7764,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
7756
7764
  duration,
7757
7765
  timestamp: start
7758
7766
  });
7759
- return { ...fail8(errorMessage), duration };
7767
+ return { ...fail9(errorMessage), duration };
7760
7768
  } finally {
7761
7769
  }
7762
7770
  }
@@ -7797,7 +7805,7 @@ async function executeChain(input, options) {
7797
7805
  results.push({
7798
7806
  command: cmdName,
7799
7807
  raw: cmdStr,
7800
- ...fail8(`Plugin "${cmdName}" requires a sub-command`),
7808
+ ...fail9(`Plugin "${cmdName}" requires a sub-command`),
7801
7809
  duration: 0
7802
7810
  });
7803
7811
  if (type === "and") {
@@ -7816,7 +7824,7 @@ async function executeChain(input, options) {
7816
7824
  results.push({
7817
7825
  command: cmdName,
7818
7826
  raw: cmdStr,
7819
- ...fail8(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
7827
+ ...fail9(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
7820
7828
  duration: 0
7821
7829
  });
7822
7830
  if (type === "and") {
@@ -7948,7 +7956,7 @@ async function executeChain(input, options) {
7948
7956
  results.push({
7949
7957
  command: `${cmdName} ${subCommand}`,
7950
7958
  raw: cmdStr,
7951
- ...fail8(errorMessage),
7959
+ ...fail9(errorMessage),
7952
7960
  duration: duration2
7953
7961
  });
7954
7962
  if (type === "and") {
@@ -11549,7 +11557,7 @@ async function handleFilter(args, _mode, options) {
11549
11557
  console.log(` Original: ${result.originalCount}, After: ${result.filteredCount}, Removed: ${result.removed} (${result.percentage}%)`);
11550
11558
  }
11551
11559
  async function handleGeneratePlugin(sessionName, pluginName, outputDir) {
11552
- const { SessionRecorder: SessionRecorder2 } = await import("./session-recorder-33UKWCIR.js");
11560
+ const { SessionRecorder: SessionRecorder2 } = await import("./session-recorder-KPU4YQAE.js");
11553
11561
  const { readSiteKnowledge: readSiteKnowledge2, toMarkdown } = await import("./site-knowledge-SYC6VCDB.js");
11554
11562
  const { mkdirSync: mkdirSync11, writeFileSync: writeFileSync13 } = await import("fs");
11555
11563
  const { join: join14 } = await import("path");
@@ -13511,7 +13519,7 @@ Run "xbrowser ${command} ${subCommand} --help" to see available parameters.`
13511
13519
  const targetPage = pages[cmdTabIndex];
13512
13520
  await targetPage.bringToFront().catch(() => {
13513
13521
  });
13514
- const { setActivePage: setActivePage2 } = await import("./browser-TLIDFFEG.js");
13522
+ const { setActivePage: setActivePage2 } = await import("./browser-C63PFGPT.js");
13515
13523
  setActivePage2(session, targetPage);
13516
13524
  }
13517
13525
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SessionRecorder
3
- } from "./chunk-RMYEHTLS.js";
3
+ } from "./chunk-YSCY52UJ.js";
4
4
  import "./chunk-OZKD3W4X.js";
5
5
  import "./chunk-KFQGP6VL.js";
6
6
  export {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SessionRecorder
3
- } from "./chunk-FL6DOSWV.js";
3
+ } from "./chunk-TTZNR3QP.js";
4
4
  import "./chunk-KFQGP6VL.js";
5
5
  export {
6
6
  SessionRecorder
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xbrowser/cli",
3
- "version": "1.8.6",
3
+ "version": "1.9.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": {