@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/{browser-XPKM344Y.js → browser-4KRHALJ3.js} +1 -1
- package/dist/{browser-LW2MDJE4.js → browser-6WJHQDPV.js} +1 -1
- package/dist/{browser-TLIDFFEG.js → browser-C63PFGPT.js} +1 -1
- package/dist/{chunk-CJJ564VK.js → chunk-MSQIPXKE.js} +1 -1
- package/dist/{chunk-HXLMMSU3.js → chunk-OOJ2H7IL.js} +1 -1
- package/dist/{chunk-FL6DOSWV.js → chunk-TTZNR3QP.js} +30 -2
- package/dist/{chunk-RMYEHTLS.js → chunk-YSCY52UJ.js} +30 -2
- package/dist/{chunk-SJLRCE6N.js → chunk-Z7WC4P2M.js} +1 -1
- package/dist/cli.js +42 -34
- package/dist/daemon-main.js +57 -171
- package/dist/index.d.ts +11 -1
- package/dist/index.js +41 -33
- package/dist/{session-recorder-33UKWCIR.js → session-recorder-KPU4YQAE.js} +1 -1
- package/dist/{session-recorder-BMIJ3ZJM.js → session-recorder-UTULJFTE.js} +1 -1
- package/package.json +1 -1
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-
|
|
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-
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
5711
|
+
return fail7("Parameter --index is required for switch subcommand");
|
|
5704
5712
|
}
|
|
5705
5713
|
if (p.index < 0 || p.index >= pages.length) {
|
|
5706
|
-
return
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 { ...
|
|
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-
|
|
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 { ...
|
|
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
|
-
...
|
|
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
|
-
...
|
|
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
|
-
...
|
|
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-
|
|
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-
|
|
13522
|
+
const { setActivePage: setActivePage2 } = await import("./browser-C63PFGPT.js");
|
|
13515
13523
|
setActivePage2(session, targetPage);
|
|
13516
13524
|
}
|
|
13517
13525
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xbrowser/cli",
|
|
3
|
-
"version": "1.
|
|
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": {
|