@xbrowser/cli 1.24.3 → 1.25.1
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-DFM2SQDM.js → browser-AGFVVYPN.js} +3 -3
- package/dist/{browser-I3EZY3FL.js → browser-FIEYZRSV.js} +2 -2
- package/dist/{browser-WCHMUN6H.js → browser-PWBUGDTR.js} +3 -3
- package/dist/{cdp-driver-HGWM5NRF.js → cdp-driver-AOHB2BBY.js} +2 -2
- package/dist/{cdp-driver-57QV7C5O.js → cdp-driver-OQDGJ7FW.js} +2 -2
- package/dist/{cdp-driver-BFGFAVAN.js → cdp-driver-SPVN2G5X.js} +2 -2
- package/dist/{chunk-SUHS2EWV.js → chunk-55TCNPMB.js} +566 -490
- package/dist/{chunk-X735U7G7.js → chunk-CRRR4KUO.js} +2 -2
- package/dist/{chunk-UR3R5LWF.js → chunk-DP6VI3UL.js} +2 -2
- package/dist/{chunk-ROAXLDV7.js → chunk-GBACWWFI.js} +1 -1
- package/dist/{chunk-PKXJST62.js → chunk-PZJSCKTI.js} +1 -1
- package/dist/{chunk-GYB5BOSP.js → chunk-R3F4K2SB.js} +19 -0
- package/dist/{chunk-LTLMDKWG.js → chunk-RLWABNIE.js} +562 -490
- package/dist/{chunk-BH3GIMWE.js → chunk-ZGHLHBXX.js} +2 -2
- package/dist/cli.js +27 -11
- package/dist/daemon-main.js +567 -495
- package/dist/index.js +27 -12
- package/dist/{server-Y5VVPRC6.js → server-APHNNIXO.js} +4 -4
- package/dist/{server-A5R4OIGX.js → server-HITV2PS7.js} +3 -3
- package/dist/{session-replayer-PSAPQBZA.js → session-replayer-ZCE45WSW.js} +1 -1
- package/dist/{stealth-JOXGV34D.js → stealth-MHJNBJY7.js} +1 -1
- package/dist/{stealth-2AA2FSNN.js → stealth-QNSMIHQK.js} +1 -1
- package/package.json +1 -1
|
@@ -20,12 +20,12 @@ import {
|
|
|
20
20
|
resolveLaunchOpts,
|
|
21
21
|
saveSessionDiskMeta,
|
|
22
22
|
setActivePage
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-CRRR4KUO.js";
|
|
24
24
|
import {
|
|
25
25
|
rand,
|
|
26
26
|
sleep,
|
|
27
27
|
wheelDelta
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-R3F4K2SB.js";
|
|
29
29
|
import {
|
|
30
30
|
errMsg
|
|
31
31
|
} from "./chunk-GDKLH7ZY.js";
|
|
@@ -63,8 +63,8 @@ function classifyFailure(message) {
|
|
|
63
63
|
|
|
64
64
|
// src/executor.ts
|
|
65
65
|
import {
|
|
66
|
-
ok as
|
|
67
|
-
fail as
|
|
66
|
+
ok as ok31,
|
|
67
|
+
fail as fail16,
|
|
68
68
|
isCommandResult,
|
|
69
69
|
CompositeStorage as CompositeStorage2,
|
|
70
70
|
TipCollector as TipCollector2,
|
|
@@ -273,6 +273,9 @@ function getCommand(name) {
|
|
|
273
273
|
function getAllCommands() {
|
|
274
274
|
return Array.from(registry.values());
|
|
275
275
|
}
|
|
276
|
+
function getCommandNames() {
|
|
277
|
+
return Array.from(registry.keys());
|
|
278
|
+
}
|
|
276
279
|
|
|
277
280
|
// src/utils/ssr-detect.ts
|
|
278
281
|
var SSR_VARIABLE_TO_FRAMEWORK = {
|
|
@@ -1426,37 +1429,109 @@ var uaCommand = registerCommand({
|
|
|
1426
1429
|
}
|
|
1427
1430
|
});
|
|
1428
1431
|
|
|
1429
|
-
// src/commands/
|
|
1432
|
+
// src/commands/preflight.ts
|
|
1430
1433
|
import { z as z11 } from "zod";
|
|
1431
1434
|
import { ok as ok11, fail as fail4 } from "@dyyz1993/xcli-core";
|
|
1435
|
+
var preflightCommand = registerCommand({
|
|
1436
|
+
name: "preflight",
|
|
1437
|
+
description: "Pre-flight anti-bot gate: open local detection page and verify stealth posture before any automation task",
|
|
1438
|
+
scope: "page",
|
|
1439
|
+
parameters: z11.object({
|
|
1440
|
+
strict: z11.boolean().optional().describe("\u5931\u8D25\u65F6\u4EE5\u975E\u96F6\u9000\u51FA\u7801\u7ED3\u675F\uFF08\u94FE\u5F0F/CI \u95E8\u7981\u7528\uFF09"),
|
|
1441
|
+
publish: z11.boolean().optional().describe("\u53D1\u5E03\u7C7B\u4EFB\u52A1\u95E8\u7981\uFF1Aheadless \u73AF\u5883\u76F4\u63A5\u5224\u5931\u8D25\uFF08\u9ED8\u8BA4\u7531 XBROWSER_NO_HEADLESS_PUBLISH \u63A7\u5236\uFF09")
|
|
1442
|
+
}),
|
|
1443
|
+
result: z11.object({
|
|
1444
|
+
gate: z11.enum(["pass", "fail"]),
|
|
1445
|
+
failed: z11.array(z11.string()),
|
|
1446
|
+
headless: z11.boolean()
|
|
1447
|
+
}),
|
|
1448
|
+
handler: async (p, ctx) => {
|
|
1449
|
+
const page = ctx.page;
|
|
1450
|
+
const tips = [];
|
|
1451
|
+
const ua = await page.evaluate("navigator.userAgent").catch(() => "");
|
|
1452
|
+
const outerW = await page.evaluate("window.outerWidth").catch(() => 0);
|
|
1453
|
+
const headless = /headless/i.test(ua) || outerW === 0;
|
|
1454
|
+
const publishMode = p.publish || process.env.XBROWSER_NO_HEADLESS_PUBLISH === "1";
|
|
1455
|
+
if (publishMode && headless) {
|
|
1456
|
+
tips.push("\u53D1\u5E03\u7C7B\u4EFB\u52A1\u7981\u7528 headless\uFF08\u98CE\u63A7\u7EA2\u7EBF\uFF09\uFF1A\u63A5\u6709\u5934\u771F\u6D4F\u89C8\u5668\u540E\u91CD\u8BD5");
|
|
1457
|
+
tips.push(' \u6709\u5934 Chrome: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --user-data-dir=~/.xbrowser/chrome-profile-headed --remote-debugging-port=9222');
|
|
1458
|
+
tips.push(" \u7136\u540E\u52A0 --cdp http://localhost:9222");
|
|
1459
|
+
return fail4("PREFLIGHT-FAIL: headless \u4E0D\u5141\u8BB8\u7528\u4E8E\u53D1\u5E03\u7C7B\u4EFB\u52A1\uFF08\u7528 --cdp \u63A5\u6709\u5934 Chrome\uFF09", tips);
|
|
1460
|
+
}
|
|
1461
|
+
let pageUrl = null;
|
|
1462
|
+
try {
|
|
1463
|
+
const { fileURLToPath } = await import("url");
|
|
1464
|
+
const { join: join9, dirname: dirname4 } = await import("path");
|
|
1465
|
+
const { existsSync: existsSync7 } = await import("fs");
|
|
1466
|
+
const here = typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url);
|
|
1467
|
+
const candidates = [
|
|
1468
|
+
join9(dirname4(here), "..", "assets", "preflight.html"),
|
|
1469
|
+
join9(process.cwd(), "assets", "preflight.html")
|
|
1470
|
+
];
|
|
1471
|
+
pageUrl = candidates.find((c) => existsSync7(c)) || null;
|
|
1472
|
+
} catch {
|
|
1473
|
+
}
|
|
1474
|
+
if (pageUrl) {
|
|
1475
|
+
await page.goto("file://" + pageUrl, { waitUntil: "domcontentloaded", timeout: 15e3 });
|
|
1476
|
+
} else {
|
|
1477
|
+
await page.goto("about:blank");
|
|
1478
|
+
await page.evaluate(`(function(){
|
|
1479
|
+
var fails=[];
|
|
1480
|
+
if(navigator.webdriver!==false)fails.push('webdriver');
|
|
1481
|
+
if(/headless/i.test(navigator.userAgent))fails.push('ua-no-headless');
|
|
1482
|
+
window.__pf=fails.join(',');
|
|
1483
|
+
document.title=fails.length?'PREFLIGHT-FAIL':'PREFLIGHT-PASS';
|
|
1484
|
+
})()`);
|
|
1485
|
+
}
|
|
1486
|
+
await page.waitForTimeout(1200);
|
|
1487
|
+
const result = await page.evaluate(`(function(){
|
|
1488
|
+
var out=document.getElementById('out');
|
|
1489
|
+
return { title: document.title, fails: out ? (out.getAttribute('data-fails')||'') : (window.__pf||'') };
|
|
1490
|
+
})()`).catch(() => ({ title: "PREFLIGHT-FAIL", fails: "evaluate-error" }));
|
|
1491
|
+
const passed = result.title === "PREFLIGHT-PASS";
|
|
1492
|
+
const failed = result.fails ? result.fails.split(",").filter(Boolean) : [];
|
|
1493
|
+
tips.push(`headless=${headless}${publishMode ? "\uFF08publish \u95E8\u7981\u5F00\u542F\uFF09" : ""}`);
|
|
1494
|
+
if (passed) {
|
|
1495
|
+
tips.push("\u9884\u68C0\u901A\u8FC7\uFF1A\u53CD\u722C\u59FF\u6001\u5168\u90E8\u65AD\u8A00\u7EFF\u706F\uFF0C\u53EF\u6267\u884C\u81EA\u52A8\u5316\u4EFB\u52A1");
|
|
1496
|
+
return ok11({ gate: "pass", failed: [], headless }, tips);
|
|
1497
|
+
}
|
|
1498
|
+
tips.push(`\u5931\u8D25\u9879: ${failed.join(", ") || result.title}`);
|
|
1499
|
+
tips.push("\u4FEE\u590D\u6307\u5F15: headless \u73AF\u5883\u63A5\u6709\u5934 Chrome\uFF08--cdp\uFF09\uFF1Bwebdriver \u6CC4\u6F0F\u68C0\u67E5 stealth \u57AB\u7247\uFF08XBROWSER_STEALTH \u4E0D\u4E3A off\uFF09");
|
|
1500
|
+
return fail4(`PREFLIGHT-FAIL: ${failed.join(", ") || result.title}`, tips);
|
|
1501
|
+
}
|
|
1502
|
+
});
|
|
1503
|
+
|
|
1504
|
+
// src/commands/storage.ts
|
|
1505
|
+
import { z as z12 } from "zod";
|
|
1506
|
+
import { ok as ok12, fail as fail5 } from "@dyyz1993/xcli-core";
|
|
1432
1507
|
var getCookiesCommand = registerCommand({
|
|
1433
1508
|
name: "get-cookies",
|
|
1434
1509
|
description: "Get all cookies for the current page",
|
|
1435
1510
|
scope: "page",
|
|
1436
|
-
result:
|
|
1437
|
-
cookies:
|
|
1511
|
+
result: z12.object({
|
|
1512
|
+
cookies: z12.array(z12.record(z12.unknown()))
|
|
1438
1513
|
}),
|
|
1439
1514
|
handler: async (_p, ctx) => {
|
|
1440
1515
|
const cookies = await ctx.browserContext.cookies();
|
|
1441
|
-
return
|
|
1516
|
+
return ok12({ cookies });
|
|
1442
1517
|
}
|
|
1443
1518
|
});
|
|
1444
1519
|
var setCookieCommand = registerCommand({
|
|
1445
1520
|
name: "set-cookie",
|
|
1446
1521
|
description: "Set a cookie",
|
|
1447
1522
|
scope: "page",
|
|
1448
|
-
parameters:
|
|
1449
|
-
name:
|
|
1450
|
-
value:
|
|
1451
|
-
domain:
|
|
1452
|
-
path:
|
|
1453
|
-
url:
|
|
1454
|
-
expires:
|
|
1455
|
-
httpOnly:
|
|
1456
|
-
secure:
|
|
1457
|
-
sameSite:
|
|
1523
|
+
parameters: z12.object({
|
|
1524
|
+
name: z12.coerce.string(),
|
|
1525
|
+
value: z12.coerce.string(),
|
|
1526
|
+
domain: z12.coerce.string().optional(),
|
|
1527
|
+
path: z12.coerce.string().optional(),
|
|
1528
|
+
url: z12.string().optional().describe("Cookie URL (alternative to domain)"),
|
|
1529
|
+
expires: z12.number().optional(),
|
|
1530
|
+
httpOnly: z12.boolean().optional(),
|
|
1531
|
+
secure: z12.boolean().optional(),
|
|
1532
|
+
sameSite: z12.enum(["Strict", "Lax", "None"]).optional()
|
|
1458
1533
|
}),
|
|
1459
|
-
result:
|
|
1534
|
+
result: z12.object({ name: z12.string() }),
|
|
1460
1535
|
handler: async (p, ctx) => {
|
|
1461
1536
|
const cookie = { ...p };
|
|
1462
1537
|
if (!cookie.domain && !cookie.url) {
|
|
@@ -1471,38 +1546,38 @@ var setCookieCommand = registerCommand({
|
|
|
1471
1546
|
}
|
|
1472
1547
|
}
|
|
1473
1548
|
if (!cookie.domain && !cookie.url) {
|
|
1474
|
-
return
|
|
1549
|
+
return fail5("set-cookie requires --domain or --url, or a non-blank page URL to infer from");
|
|
1475
1550
|
}
|
|
1476
1551
|
await ctx.browserContext.addCookies([cookie]);
|
|
1477
|
-
return
|
|
1552
|
+
return ok12({ name: p.name });
|
|
1478
1553
|
}
|
|
1479
1554
|
});
|
|
1480
1555
|
var clearCookiesCommand = registerCommand({
|
|
1481
1556
|
name: "clear-cookies",
|
|
1482
1557
|
description: "Clear all cookies",
|
|
1483
1558
|
scope: "page",
|
|
1484
|
-
result:
|
|
1559
|
+
result: z12.object({ cleared: z12.boolean() }),
|
|
1485
1560
|
handler: async (_p, ctx) => {
|
|
1486
1561
|
await ctx.browserContext.clearCookies();
|
|
1487
|
-
return
|
|
1562
|
+
return ok12({ cleared: true });
|
|
1488
1563
|
}
|
|
1489
1564
|
});
|
|
1490
1565
|
var getLocalStorageCommand = registerCommand({
|
|
1491
1566
|
name: "get-local-storage",
|
|
1492
1567
|
description: "Get localStorage entries",
|
|
1493
1568
|
scope: "page",
|
|
1494
|
-
parameters:
|
|
1495
|
-
key:
|
|
1569
|
+
parameters: z12.object({
|
|
1570
|
+
key: z12.string().optional()
|
|
1496
1571
|
}),
|
|
1497
|
-
result:
|
|
1498
|
-
|
|
1499
|
-
|
|
1572
|
+
result: z12.union([
|
|
1573
|
+
z12.object({ key: z12.string(), value: z12.string().nullable() }),
|
|
1574
|
+
z12.object({ data: z12.record(z12.string()) })
|
|
1500
1575
|
]),
|
|
1501
1576
|
handler: async (p, ctx) => {
|
|
1502
1577
|
try {
|
|
1503
1578
|
if (p.key) {
|
|
1504
1579
|
const value = await ctx.page.evaluate((k) => localStorage.getItem(k), p.key);
|
|
1505
|
-
return
|
|
1580
|
+
return ok12({ key: p.key, value });
|
|
1506
1581
|
}
|
|
1507
1582
|
const data = await ctx.page.evaluate(() => {
|
|
1508
1583
|
const entries = {};
|
|
@@ -1512,9 +1587,9 @@ var getLocalStorageCommand = registerCommand({
|
|
|
1512
1587
|
}
|
|
1513
1588
|
return entries;
|
|
1514
1589
|
});
|
|
1515
|
-
return
|
|
1590
|
+
return ok12({ data });
|
|
1516
1591
|
} catch (e) {
|
|
1517
|
-
return
|
|
1592
|
+
return fail5(`localStorage not accessible on this page: ${e instanceof Error ? e.message : String(e)}`);
|
|
1518
1593
|
}
|
|
1519
1594
|
}
|
|
1520
1595
|
});
|
|
@@ -1522,11 +1597,11 @@ var setLocalStorageCommand = registerCommand({
|
|
|
1522
1597
|
name: "set-local-storage",
|
|
1523
1598
|
description: "Set a localStorage entry",
|
|
1524
1599
|
scope: "page",
|
|
1525
|
-
parameters:
|
|
1526
|
-
key:
|
|
1527
|
-
value:
|
|
1600
|
+
parameters: z12.object({
|
|
1601
|
+
key: z12.string(),
|
|
1602
|
+
value: z12.string()
|
|
1528
1603
|
}),
|
|
1529
|
-
result:
|
|
1604
|
+
result: z12.object({ key: z12.string() }),
|
|
1530
1605
|
handler: async (p, ctx) => {
|
|
1531
1606
|
try {
|
|
1532
1607
|
await ctx.page.evaluate(
|
|
@@ -1535,9 +1610,9 @@ var setLocalStorageCommand = registerCommand({
|
|
|
1535
1610
|
},
|
|
1536
1611
|
{ key: p.key, value: p.value }
|
|
1537
1612
|
);
|
|
1538
|
-
return
|
|
1613
|
+
return ok12({ key: p.key });
|
|
1539
1614
|
} catch (e) {
|
|
1540
|
-
return
|
|
1615
|
+
return fail5(`localStorage not accessible on this page: ${e instanceof Error ? e.message : String(e)}`);
|
|
1541
1616
|
}
|
|
1542
1617
|
}
|
|
1543
1618
|
});
|
|
@@ -1545,20 +1620,20 @@ var clearLocalStorageCommand = registerCommand({
|
|
|
1545
1620
|
name: "clear-local-storage",
|
|
1546
1621
|
description: "Clear all localStorage entries",
|
|
1547
1622
|
scope: "page",
|
|
1548
|
-
result:
|
|
1623
|
+
result: z12.object({ cleared: z12.boolean() }),
|
|
1549
1624
|
handler: async (_p, ctx) => {
|
|
1550
1625
|
try {
|
|
1551
1626
|
await ctx.page.evaluate(() => localStorage.clear());
|
|
1552
|
-
return
|
|
1627
|
+
return ok12({ cleared: true });
|
|
1553
1628
|
} catch (e) {
|
|
1554
|
-
return
|
|
1629
|
+
return fail5(`localStorage not accessible on this page: ${e instanceof Error ? e.message : String(e)}`);
|
|
1555
1630
|
}
|
|
1556
1631
|
}
|
|
1557
1632
|
});
|
|
1558
1633
|
|
|
1559
1634
|
// src/commands/screenshot.ts
|
|
1560
|
-
import { z as
|
|
1561
|
-
import { ok as
|
|
1635
|
+
import { z as z13 } from "zod";
|
|
1636
|
+
import { ok as ok13, fail as fail6 } from "@dyyz1993/xcli-core";
|
|
1562
1637
|
import { writeFileSync, mkdirSync } from "fs";
|
|
1563
1638
|
import { dirname, join as join4 } from "path";
|
|
1564
1639
|
function ensureScreenshotsDir() {
|
|
@@ -1585,23 +1660,23 @@ var screenshotCommand = registerCommand({
|
|
|
1585
1660
|
description: "Take a screenshot of the page or element (auto-saved to the OS temp dir unless --output is given; persistent override: xbrowser config set screenshots.dir <path>)",
|
|
1586
1661
|
scope: "page",
|
|
1587
1662
|
selectorParams: ["selector"],
|
|
1588
|
-
parameters:
|
|
1589
|
-
selector:
|
|
1590
|
-
type:
|
|
1591
|
-
fullPage:
|
|
1592
|
-
output:
|
|
1593
|
-
base64:
|
|
1663
|
+
parameters: z13.object({
|
|
1664
|
+
selector: z13.string().optional(),
|
|
1665
|
+
type: z13.enum(["png", "jpeg"]).optional(),
|
|
1666
|
+
fullPage: z13.boolean().optional(),
|
|
1667
|
+
output: z13.string().optional(),
|
|
1668
|
+
base64: z13.boolean().optional().describe("Return base64 data instead of file path")
|
|
1594
1669
|
}),
|
|
1595
|
-
result:
|
|
1596
|
-
|
|
1597
|
-
data:
|
|
1598
|
-
format:
|
|
1599
|
-
size:
|
|
1670
|
+
result: z13.union([
|
|
1671
|
+
z13.object({
|
|
1672
|
+
data: z13.string(),
|
|
1673
|
+
format: z13.string(),
|
|
1674
|
+
size: z13.number()
|
|
1600
1675
|
}),
|
|
1601
|
-
|
|
1602
|
-
output:
|
|
1603
|
-
format:
|
|
1604
|
-
size:
|
|
1676
|
+
z13.object({
|
|
1677
|
+
output: z13.string(),
|
|
1678
|
+
format: z13.string(),
|
|
1679
|
+
size: z13.number()
|
|
1605
1680
|
})
|
|
1606
1681
|
]),
|
|
1607
1682
|
handler: async (p, ctx) => {
|
|
@@ -1619,21 +1694,21 @@ var screenshotCommand = registerCommand({
|
|
|
1619
1694
|
if (p.output) {
|
|
1620
1695
|
const dirErr = ensureParentDir(p.output);
|
|
1621
1696
|
if (dirErr) {
|
|
1622
|
-
return
|
|
1697
|
+
return fail6(`Cannot create directory for --output "${p.output}": ${dirErr}`);
|
|
1623
1698
|
}
|
|
1624
1699
|
try {
|
|
1625
1700
|
writeFileSync(p.output, buffer, "binary");
|
|
1626
1701
|
} catch (err) {
|
|
1627
|
-
return
|
|
1702
|
+
return fail6(`Failed to write screenshot to "${p.output}": ${err instanceof Error ? err.message : String(err)}`);
|
|
1628
1703
|
}
|
|
1629
|
-
return
|
|
1704
|
+
return ok13({
|
|
1630
1705
|
output: p.output,
|
|
1631
1706
|
format,
|
|
1632
1707
|
size: buffer.length
|
|
1633
1708
|
});
|
|
1634
1709
|
}
|
|
1635
1710
|
if (p.base64) {
|
|
1636
|
-
return
|
|
1711
|
+
return ok13({
|
|
1637
1712
|
data: buffer.toString("base64"),
|
|
1638
1713
|
format,
|
|
1639
1714
|
size: buffer.length
|
|
@@ -1642,7 +1717,7 @@ var screenshotCommand = registerCommand({
|
|
|
1642
1717
|
ensureScreenshotsDir();
|
|
1643
1718
|
const screenshotPath = generateScreenshotPath(format);
|
|
1644
1719
|
writeFileSync(screenshotPath, buffer, "binary");
|
|
1645
|
-
return
|
|
1720
|
+
return ok13({
|
|
1646
1721
|
output: screenshotPath,
|
|
1647
1722
|
format,
|
|
1648
1723
|
size: buffer.length
|
|
@@ -1651,19 +1726,19 @@ var screenshotCommand = registerCommand({
|
|
|
1651
1726
|
});
|
|
1652
1727
|
|
|
1653
1728
|
// src/commands/structure.ts
|
|
1654
|
-
import { z as
|
|
1655
|
-
import { ok as
|
|
1729
|
+
import { z as z14 } from "zod";
|
|
1730
|
+
import { ok as ok14 } from "@dyyz1993/xcli-core";
|
|
1656
1731
|
var structureCommand = registerCommand({
|
|
1657
1732
|
name: "structure",
|
|
1658
1733
|
description: "Get the DOM structure of the page or an element",
|
|
1659
1734
|
scope: "page",
|
|
1660
1735
|
selectorParams: ["selector"],
|
|
1661
|
-
parameters:
|
|
1662
|
-
selector:
|
|
1663
|
-
depth:
|
|
1736
|
+
parameters: z14.object({
|
|
1737
|
+
selector: z14.string().optional(),
|
|
1738
|
+
depth: z14.number().optional()
|
|
1664
1739
|
}),
|
|
1665
|
-
result:
|
|
1666
|
-
structure:
|
|
1740
|
+
result: z14.object({
|
|
1741
|
+
structure: z14.record(z14.unknown())
|
|
1667
1742
|
}),
|
|
1668
1743
|
handler: async (p, ctx) => {
|
|
1669
1744
|
const structure = await ctx.page.evaluate(
|
|
@@ -1695,30 +1770,30 @@ var structureCommand = registerCommand({
|
|
|
1695
1770
|
},
|
|
1696
1771
|
{ sel: p.selector || "body", maxDepth: p.depth || 5 }
|
|
1697
1772
|
);
|
|
1698
|
-
return
|
|
1773
|
+
return ok14({ structure });
|
|
1699
1774
|
}
|
|
1700
1775
|
});
|
|
1701
1776
|
|
|
1702
1777
|
// src/commands/viewport.ts
|
|
1703
|
-
import { z as
|
|
1704
|
-
import { ok as
|
|
1778
|
+
import { z as z15 } from "zod";
|
|
1779
|
+
import { ok as ok15 } from "@dyyz1993/xcli-core";
|
|
1705
1780
|
var setViewportCommand = registerCommand({
|
|
1706
1781
|
name: "set-viewport",
|
|
1707
1782
|
description: "Set the viewport size and properties",
|
|
1708
1783
|
scope: "browser",
|
|
1709
|
-
parameters:
|
|
1710
|
-
width:
|
|
1711
|
-
height:
|
|
1712
|
-
deviceScaleFactor:
|
|
1713
|
-
isMobile:
|
|
1714
|
-
hasTouch:
|
|
1784
|
+
parameters: z15.object({
|
|
1785
|
+
width: z15.coerce.number(),
|
|
1786
|
+
height: z15.coerce.number(),
|
|
1787
|
+
deviceScaleFactor: z15.coerce.number().optional(),
|
|
1788
|
+
isMobile: z15.boolean().optional(),
|
|
1789
|
+
hasTouch: z15.boolean().optional()
|
|
1715
1790
|
}),
|
|
1716
|
-
result:
|
|
1717
|
-
width:
|
|
1718
|
-
height:
|
|
1719
|
-
deviceScaleFactor:
|
|
1720
|
-
isMobile:
|
|
1721
|
-
hasTouch:
|
|
1791
|
+
result: z15.object({
|
|
1792
|
+
width: z15.number(),
|
|
1793
|
+
height: z15.number(),
|
|
1794
|
+
deviceScaleFactor: z15.number().optional(),
|
|
1795
|
+
isMobile: z15.boolean().optional(),
|
|
1796
|
+
hasTouch: z15.boolean().optional()
|
|
1722
1797
|
}),
|
|
1723
1798
|
handler: async (p, ctx) => {
|
|
1724
1799
|
const viewport = ctx.page.viewportSize();
|
|
@@ -1731,7 +1806,7 @@ var setViewportCommand = registerCommand({
|
|
|
1731
1806
|
...p.isMobile !== void 0 && { isMobile: p.isMobile },
|
|
1732
1807
|
...p.hasTouch !== void 0 && { hasTouch: p.hasTouch }
|
|
1733
1808
|
});
|
|
1734
|
-
return
|
|
1809
|
+
return ok15({
|
|
1735
1810
|
width,
|
|
1736
1811
|
height,
|
|
1737
1812
|
...p.deviceScaleFactor !== void 0 && { deviceScaleFactor: p.deviceScaleFactor },
|
|
@@ -1742,17 +1817,17 @@ var setViewportCommand = registerCommand({
|
|
|
1742
1817
|
});
|
|
1743
1818
|
|
|
1744
1819
|
// src/commands/frame.ts
|
|
1745
|
-
import { z as
|
|
1746
|
-
import { ok as
|
|
1820
|
+
import { z as z16 } from "zod";
|
|
1821
|
+
import { ok as ok16, fail as fail7 } from "@dyyz1993/xcli-core";
|
|
1747
1822
|
var framesCommand = registerCommand({
|
|
1748
1823
|
name: "frames",
|
|
1749
1824
|
description: "List all frames in the current page",
|
|
1750
1825
|
scope: "page",
|
|
1751
|
-
result:
|
|
1752
|
-
frames:
|
|
1753
|
-
index:
|
|
1754
|
-
name:
|
|
1755
|
-
url:
|
|
1826
|
+
result: z16.object({
|
|
1827
|
+
frames: z16.array(z16.object({
|
|
1828
|
+
index: z16.number(),
|
|
1829
|
+
name: z16.string().nullable(),
|
|
1830
|
+
url: z16.string()
|
|
1756
1831
|
}))
|
|
1757
1832
|
}),
|
|
1758
1833
|
handler: async (_p, ctx) => {
|
|
@@ -1763,21 +1838,21 @@ var framesCommand = registerCommand({
|
|
|
1763
1838
|
name: frame.name(),
|
|
1764
1839
|
url: frame.url()
|
|
1765
1840
|
}));
|
|
1766
|
-
return
|
|
1841
|
+
return ok16({ frames: frameList });
|
|
1767
1842
|
}
|
|
1768
1843
|
});
|
|
1769
1844
|
var frameCommand = registerCommand({
|
|
1770
1845
|
name: "frame",
|
|
1771
1846
|
description: "Get frame info by index or name",
|
|
1772
1847
|
scope: "page",
|
|
1773
|
-
parameters:
|
|
1774
|
-
index:
|
|
1775
|
-
name:
|
|
1848
|
+
parameters: z16.object({
|
|
1849
|
+
index: z16.number().int().min(0).optional(),
|
|
1850
|
+
name: z16.string().optional()
|
|
1776
1851
|
}),
|
|
1777
|
-
result:
|
|
1778
|
-
name:
|
|
1779
|
-
url:
|
|
1780
|
-
error:
|
|
1852
|
+
result: z16.object({
|
|
1853
|
+
name: z16.string().nullable(),
|
|
1854
|
+
url: z16.string(),
|
|
1855
|
+
error: z16.string().optional()
|
|
1781
1856
|
}),
|
|
1782
1857
|
handler: async (p, ctx) => {
|
|
1783
1858
|
const discover = ctx.page.discoverFrames;
|
|
@@ -1788,12 +1863,12 @@ var frameCommand = registerCommand({
|
|
|
1788
1863
|
} else if (p.name !== void 0) {
|
|
1789
1864
|
targetFrame = rawFrames.find((f) => f.name() === p.name);
|
|
1790
1865
|
} else {
|
|
1791
|
-
return
|
|
1866
|
+
return fail7("Must provide index or name");
|
|
1792
1867
|
}
|
|
1793
1868
|
if (!targetFrame) {
|
|
1794
|
-
return
|
|
1869
|
+
return fail7("Frame not found");
|
|
1795
1870
|
}
|
|
1796
|
-
return
|
|
1871
|
+
return ok16({
|
|
1797
1872
|
name: targetFrame.name(),
|
|
1798
1873
|
url: targetFrame.url()
|
|
1799
1874
|
});
|
|
@@ -1801,27 +1876,27 @@ var frameCommand = registerCommand({
|
|
|
1801
1876
|
});
|
|
1802
1877
|
|
|
1803
1878
|
// src/commands/ui-debug.ts
|
|
1804
|
-
import { z as
|
|
1805
|
-
import { ok as
|
|
1879
|
+
import { z as z17 } from "zod";
|
|
1880
|
+
import { ok as ok17 } from "@dyyz1993/xcli-core";
|
|
1806
1881
|
var consoleCheckCommand = registerCommand({
|
|
1807
1882
|
name: "console",
|
|
1808
1883
|
description: "Collect and analyze browser console messages (errors, warnings, logs)",
|
|
1809
1884
|
scope: "page",
|
|
1810
|
-
parameters:
|
|
1811
|
-
url:
|
|
1812
|
-
duration:
|
|
1813
|
-
filter:
|
|
1814
|
-
includeStackTraces:
|
|
1885
|
+
parameters: z17.object({
|
|
1886
|
+
url: z17.string().optional().describe("URL to navigate first (optional, uses current page if omitted)"),
|
|
1887
|
+
duration: z17.number().optional().default(5e3).describe("How long to collect messages (ms)"),
|
|
1888
|
+
filter: z17.enum(["all", "error", "warning", "info", "log"]).optional().default("all"),
|
|
1889
|
+
includeStackTraces: z17.boolean().optional().default(true)
|
|
1815
1890
|
}),
|
|
1816
|
-
result:
|
|
1817
|
-
url:
|
|
1818
|
-
duration:
|
|
1819
|
-
total:
|
|
1820
|
-
errors:
|
|
1821
|
-
warnings:
|
|
1822
|
-
messages:
|
|
1823
|
-
summary:
|
|
1824
|
-
passed:
|
|
1891
|
+
result: z17.object({
|
|
1892
|
+
url: z17.string(),
|
|
1893
|
+
duration: z17.number(),
|
|
1894
|
+
total: z17.number(),
|
|
1895
|
+
errors: z17.number(),
|
|
1896
|
+
warnings: z17.number(),
|
|
1897
|
+
messages: z17.array(z17.record(z17.unknown())),
|
|
1898
|
+
summary: z17.string(),
|
|
1899
|
+
passed: z17.boolean()
|
|
1825
1900
|
}),
|
|
1826
1901
|
handler: async (p, ctx) => {
|
|
1827
1902
|
const { page } = ctx;
|
|
@@ -1903,7 +1978,7 @@ ${a.stack || ""}`;
|
|
|
1903
1978
|
const filtered = p.filter === "all" ? messages : messages.filter((m) => m.type === p.filter);
|
|
1904
1979
|
const errorCount = messages.filter((m) => m.type === "error").length;
|
|
1905
1980
|
const warnCount = messages.filter((m) => m.type === "warning").length;
|
|
1906
|
-
return
|
|
1981
|
+
return ok17({
|
|
1907
1982
|
url: page.url(),
|
|
1908
1983
|
duration: p.duration,
|
|
1909
1984
|
total: messages.length,
|
|
@@ -1919,23 +1994,23 @@ var networkCheckCommand = registerCommand({
|
|
|
1919
1994
|
name: "net-debug",
|
|
1920
1995
|
description: "Monitor and analyze network requests \u2014 capture failed requests, slow responses, status codes",
|
|
1921
1996
|
scope: "page",
|
|
1922
|
-
parameters:
|
|
1923
|
-
url:
|
|
1924
|
-
duration:
|
|
1925
|
-
filter:
|
|
1926
|
-
slowThreshold:
|
|
1997
|
+
parameters: z17.object({
|
|
1998
|
+
url: z17.string().optional().describe("URL to navigate first"),
|
|
1999
|
+
duration: z17.number().optional().default(5e3).describe("How long to monitor (ms)"),
|
|
2000
|
+
filter: z17.enum(["all", "failed", "slow", "error", "xhr", "fetch", "document", "stylesheet", "script", "image"]).optional().default("all"),
|
|
2001
|
+
slowThreshold: z17.number().optional().default(3e3).describe('Threshold for "slow" requests (ms)')
|
|
1927
2002
|
}),
|
|
1928
|
-
result:
|
|
1929
|
-
url:
|
|
1930
|
-
duration:
|
|
1931
|
-
totalRequests:
|
|
1932
|
-
failedRequests:
|
|
1933
|
-
slowRequests:
|
|
1934
|
-
errorRequests:
|
|
1935
|
-
totalSizeKB:
|
|
1936
|
-
requests:
|
|
1937
|
-
summary:
|
|
1938
|
-
passed:
|
|
2003
|
+
result: z17.object({
|
|
2004
|
+
url: z17.string(),
|
|
2005
|
+
duration: z17.number(),
|
|
2006
|
+
totalRequests: z17.number(),
|
|
2007
|
+
failedRequests: z17.number(),
|
|
2008
|
+
slowRequests: z17.number(),
|
|
2009
|
+
errorRequests: z17.number(),
|
|
2010
|
+
totalSizeKB: z17.number(),
|
|
2011
|
+
requests: z17.array(z17.record(z17.unknown())),
|
|
2012
|
+
summary: z17.string(),
|
|
2013
|
+
passed: z17.boolean()
|
|
1939
2014
|
}),
|
|
1940
2015
|
handler: async (p, ctx) => {
|
|
1941
2016
|
const { page } = ctx;
|
|
@@ -2017,7 +2092,7 @@ var networkCheckCommand = registerCommand({
|
|
|
2017
2092
|
const slowCount = requests.filter((r) => r.duration >= p.slowThreshold).length;
|
|
2018
2093
|
const errorCount = requests.filter((r) => r.error).length;
|
|
2019
2094
|
const totalSize = requests.reduce((sum, r) => sum + r.size, 0);
|
|
2020
|
-
return
|
|
2095
|
+
return ok17({
|
|
2021
2096
|
url: page.url(),
|
|
2022
2097
|
duration: p.duration,
|
|
2023
2098
|
totalRequests: requests.length,
|
|
@@ -2039,17 +2114,17 @@ var perfCheckCommand = registerCommand({
|
|
|
2039
2114
|
name: "perf",
|
|
2040
2115
|
description: "Audit page performance metrics \u2014 load time, FCP, LCP, CLS, TTFB, resource sizes",
|
|
2041
2116
|
scope: "page",
|
|
2042
|
-
parameters:
|
|
2043
|
-
url:
|
|
2044
|
-
iterations:
|
|
2117
|
+
parameters: z17.object({
|
|
2118
|
+
url: z17.string().optional().describe("URL to navigate (uses current page if omitted)"),
|
|
2119
|
+
iterations: z17.number().optional().default(1).describe("Number of iterations to average")
|
|
2045
2120
|
}),
|
|
2046
|
-
result:
|
|
2047
|
-
url:
|
|
2048
|
-
iterations:
|
|
2049
|
-
metrics:
|
|
2050
|
-
allIterations:
|
|
2051
|
-
passed:
|
|
2052
|
-
summary:
|
|
2121
|
+
result: z17.object({
|
|
2122
|
+
url: z17.string(),
|
|
2123
|
+
iterations: z17.number(),
|
|
2124
|
+
metrics: z17.record(z17.unknown()),
|
|
2125
|
+
allIterations: z17.array(z17.record(z17.unknown())).optional(),
|
|
2126
|
+
passed: z17.boolean(),
|
|
2127
|
+
summary: z17.string()
|
|
2053
2128
|
}),
|
|
2054
2129
|
handler: async (p, ctx) => {
|
|
2055
2130
|
const { page } = ctx;
|
|
@@ -2111,7 +2186,7 @@ var perfCheckCommand = registerCommand({
|
|
|
2111
2186
|
if (resourceStats) avg.resourceStats = resourceStats;
|
|
2112
2187
|
return avg;
|
|
2113
2188
|
})();
|
|
2114
|
-
return
|
|
2189
|
+
return ok17({
|
|
2115
2190
|
url: page.url(),
|
|
2116
2191
|
iterations: p.iterations,
|
|
2117
2192
|
metrics: avgMetrics,
|
|
@@ -2125,23 +2200,23 @@ var healthCheckCommand = registerCommand({
|
|
|
2125
2200
|
name: "health",
|
|
2126
2201
|
description: "Comprehensive page health check \u2014 broken links, missing images, console errors, SEO issues",
|
|
2127
2202
|
scope: "page",
|
|
2128
|
-
parameters:
|
|
2129
|
-
url:
|
|
2130
|
-
checkLinks:
|
|
2131
|
-
checkImages:
|
|
2132
|
-
checkMeta:
|
|
2133
|
-
maxLinks:
|
|
2203
|
+
parameters: z17.object({
|
|
2204
|
+
url: z17.string().optional().describe("URL to check"),
|
|
2205
|
+
checkLinks: z17.boolean().optional().default(true).describe("Check for broken links"),
|
|
2206
|
+
checkImages: z17.boolean().optional().default(true).describe("Check for missing/broken images"),
|
|
2207
|
+
checkMeta: z17.boolean().optional().default(true).describe("Check SEO meta tags"),
|
|
2208
|
+
maxLinks: z17.number().optional().default(50).describe("Max links to check")
|
|
2134
2209
|
}),
|
|
2135
|
-
result:
|
|
2136
|
-
url:
|
|
2137
|
-
title:
|
|
2138
|
-
passed:
|
|
2139
|
-
totalIssues:
|
|
2140
|
-
errors:
|
|
2141
|
-
warnings:
|
|
2142
|
-
info:
|
|
2143
|
-
issues:
|
|
2144
|
-
summary:
|
|
2210
|
+
result: z17.object({
|
|
2211
|
+
url: z17.string(),
|
|
2212
|
+
title: z17.string(),
|
|
2213
|
+
passed: z17.boolean(),
|
|
2214
|
+
totalIssues: z17.number(),
|
|
2215
|
+
errors: z17.number(),
|
|
2216
|
+
warnings: z17.number(),
|
|
2217
|
+
info: z17.number(),
|
|
2218
|
+
issues: z17.array(z17.record(z17.unknown())),
|
|
2219
|
+
summary: z17.string()
|
|
2145
2220
|
}),
|
|
2146
2221
|
handler: async (p, ctx) => {
|
|
2147
2222
|
const { page } = ctx;
|
|
@@ -2228,7 +2303,7 @@ var healthCheckCommand = registerCommand({
|
|
|
2228
2303
|
}, { checkLinks: p.checkLinks, checkImages: p.checkImages, checkMeta: p.checkMeta, maxLinks: p.maxLinks });
|
|
2229
2304
|
const errors = result.issues.filter((i) => i.severity === "error").length;
|
|
2230
2305
|
const warnings = result.issues.filter((i) => i.severity === "warning").length;
|
|
2231
|
-
return
|
|
2306
|
+
return ok17({
|
|
2232
2307
|
url: result.url,
|
|
2233
2308
|
title: result.title,
|
|
2234
2309
|
passed: errors === 0,
|
|
@@ -2243,8 +2318,8 @@ var healthCheckCommand = registerCommand({
|
|
|
2243
2318
|
});
|
|
2244
2319
|
|
|
2245
2320
|
// src/commands/actions.ts
|
|
2246
|
-
import { z as
|
|
2247
|
-
import { ok as
|
|
2321
|
+
import { z as z18 } from "zod";
|
|
2322
|
+
import { ok as ok18 } from "@dyyz1993/xcli-core";
|
|
2248
2323
|
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
2249
2324
|
import { join as join5 } from "path";
|
|
2250
2325
|
function ensureScreenshotsDir2() {
|
|
@@ -2256,53 +2331,53 @@ function generateScreenshotPath2(format) {
|
|
|
2256
2331
|
const ext = format === "jpeg" ? "jpg" : "png";
|
|
2257
2332
|
return join5(resolveScreenshotsDir(), `screenshot-${timestamp}-${random}.${ext}`);
|
|
2258
2333
|
}
|
|
2259
|
-
var waitActionSchema =
|
|
2260
|
-
type:
|
|
2261
|
-
milliseconds:
|
|
2262
|
-
selector:
|
|
2334
|
+
var waitActionSchema = z18.object({
|
|
2335
|
+
type: z18.literal("wait"),
|
|
2336
|
+
milliseconds: z18.number().positive().optional(),
|
|
2337
|
+
selector: z18.string().optional()
|
|
2263
2338
|
}).refine(
|
|
2264
2339
|
(d) => (d.milliseconds !== void 0 || d.selector !== void 0) && !(d.milliseconds !== void 0 && d.selector !== void 0),
|
|
2265
2340
|
{ message: "Either 'milliseconds' or 'selector' must be provided, but not both." }
|
|
2266
2341
|
);
|
|
2267
|
-
var clickActionSchema =
|
|
2268
|
-
type:
|
|
2269
|
-
selector:
|
|
2270
|
-
all:
|
|
2342
|
+
var clickActionSchema = z18.object({
|
|
2343
|
+
type: z18.literal("click"),
|
|
2344
|
+
selector: z18.string(),
|
|
2345
|
+
all: z18.boolean().optional()
|
|
2271
2346
|
});
|
|
2272
|
-
var screenshotActionSchema =
|
|
2273
|
-
type:
|
|
2274
|
-
fullPage:
|
|
2275
|
-
quality:
|
|
2276
|
-
viewport:
|
|
2277
|
-
base64:
|
|
2347
|
+
var screenshotActionSchema = z18.object({
|
|
2348
|
+
type: z18.literal("screenshot"),
|
|
2349
|
+
fullPage: z18.boolean().optional(),
|
|
2350
|
+
quality: z18.number().min(1).max(100).optional(),
|
|
2351
|
+
viewport: z18.object({ width: z18.number().int().positive(), height: z18.number().int().positive() }).optional(),
|
|
2352
|
+
base64: z18.boolean().optional().describe("Return base64 data instead of file path")
|
|
2278
2353
|
});
|
|
2279
|
-
var writeActionSchema =
|
|
2280
|
-
type:
|
|
2281
|
-
text:
|
|
2354
|
+
var writeActionSchema = z18.object({
|
|
2355
|
+
type: z18.literal("write"),
|
|
2356
|
+
text: z18.string()
|
|
2282
2357
|
});
|
|
2283
|
-
var pressActionSchema =
|
|
2284
|
-
type:
|
|
2285
|
-
key:
|
|
2358
|
+
var pressActionSchema = z18.object({
|
|
2359
|
+
type: z18.literal("press"),
|
|
2360
|
+
key: z18.string()
|
|
2286
2361
|
});
|
|
2287
|
-
var scrollActionSchema =
|
|
2288
|
-
type:
|
|
2289
|
-
direction:
|
|
2290
|
-
selector:
|
|
2362
|
+
var scrollActionSchema = z18.object({
|
|
2363
|
+
type: z18.literal("scroll"),
|
|
2364
|
+
direction: z18.enum(["up", "down"]).optional(),
|
|
2365
|
+
selector: z18.string().optional()
|
|
2291
2366
|
});
|
|
2292
|
-
var scrapeActionSchema =
|
|
2293
|
-
type:
|
|
2367
|
+
var scrapeActionSchema = z18.object({
|
|
2368
|
+
type: z18.literal("scrape")
|
|
2294
2369
|
});
|
|
2295
|
-
var executeJavascriptActionSchema =
|
|
2296
|
-
type:
|
|
2297
|
-
script:
|
|
2370
|
+
var executeJavascriptActionSchema = z18.object({
|
|
2371
|
+
type: z18.literal("executeJavascript"),
|
|
2372
|
+
script: z18.string()
|
|
2298
2373
|
});
|
|
2299
|
-
var pdfActionSchema =
|
|
2300
|
-
type:
|
|
2301
|
-
landscape:
|
|
2302
|
-
scale:
|
|
2303
|
-
format:
|
|
2374
|
+
var pdfActionSchema = z18.object({
|
|
2375
|
+
type: z18.literal("pdf"),
|
|
2376
|
+
landscape: z18.boolean().optional(),
|
|
2377
|
+
scale: z18.number().optional(),
|
|
2378
|
+
format: z18.enum(["A0", "A1", "A2", "A3", "A4", "A5", "A6", "Letter", "Legal", "Tabloid", "Ledger"]).optional()
|
|
2304
2379
|
});
|
|
2305
|
-
var actionSchema =
|
|
2380
|
+
var actionSchema = z18.union([
|
|
2306
2381
|
waitActionSchema,
|
|
2307
2382
|
clickActionSchema,
|
|
2308
2383
|
screenshotActionSchema,
|
|
@@ -2393,11 +2468,11 @@ var actionsCommand = registerCommand({
|
|
|
2393
2468
|
name: "actions",
|
|
2394
2469
|
description: "Execute a sequence of actions (wait, click, scroll, screenshot, fill, etc.)",
|
|
2395
2470
|
scope: "page",
|
|
2396
|
-
parameters:
|
|
2397
|
-
url:
|
|
2398
|
-
actions:
|
|
2399
|
-
output:
|
|
2400
|
-
timeout:
|
|
2471
|
+
parameters: z18.object({
|
|
2472
|
+
url: z18.string().describe("Starting URL"),
|
|
2473
|
+
actions: z18.array(actionSchema).max(MAX_ACTIONS).describe("Array of actions (max 50)"),
|
|
2474
|
+
output: z18.enum(["text", "json"]).default("json").describe("Output format: text or json"),
|
|
2475
|
+
timeout: z18.number().default(60).describe("Overall timeout in seconds (default: 60)")
|
|
2401
2476
|
}),
|
|
2402
2477
|
handler: async (p, ctx) => {
|
|
2403
2478
|
await ctx.page.goto(p.url, { waitUntil: "domcontentloaded" });
|
|
@@ -2417,14 +2492,14 @@ var actionsCommand = registerCommand({
|
|
|
2417
2492
|
const finalUrl = ctx.page.url();
|
|
2418
2493
|
const timedOut = results.length < p.actions.length;
|
|
2419
2494
|
if (p.output === "text") {
|
|
2420
|
-
return
|
|
2495
|
+
return ok18({
|
|
2421
2496
|
title,
|
|
2422
2497
|
url: finalUrl,
|
|
2423
2498
|
actions: results.map((r) => JSON.stringify(r)).join("\n"),
|
|
2424
2499
|
...timedOut ? { warning: `Timed out after ${p.timeout}s, completed ${results.length}/${p.actions.length} actions` } : {}
|
|
2425
2500
|
});
|
|
2426
2501
|
}
|
|
2427
|
-
return
|
|
2502
|
+
return ok18({
|
|
2428
2503
|
title,
|
|
2429
2504
|
url: finalUrl,
|
|
2430
2505
|
results,
|
|
@@ -2434,8 +2509,8 @@ var actionsCommand = registerCommand({
|
|
|
2434
2509
|
});
|
|
2435
2510
|
|
|
2436
2511
|
// src/commands/scrape.ts
|
|
2437
|
-
import { z as
|
|
2438
|
-
import { ok as
|
|
2512
|
+
import { z as z19 } from "zod";
|
|
2513
|
+
import { ok as ok19, fail as fail8 } from "@dyyz1993/xcli-core";
|
|
2439
2514
|
|
|
2440
2515
|
// src/lib/html-to-markdown.ts
|
|
2441
2516
|
import * as cheerio from "cheerio";
|
|
@@ -2820,15 +2895,15 @@ var scrapeCommand = registerCommand({
|
|
|
2820
2895
|
description: "Scrape a page and convert to Markdown (with JS rendering)",
|
|
2821
2896
|
scope: "project",
|
|
2822
2897
|
selectorParams: ["selector"],
|
|
2823
|
-
parameters:
|
|
2824
|
-
url:
|
|
2825
|
-
selector:
|
|
2826
|
-
timeout:
|
|
2827
|
-
format:
|
|
2828
|
-
onlyMainContent:
|
|
2829
|
-
retries:
|
|
2830
|
-
waitAfterLoad:
|
|
2831
|
-
mode:
|
|
2898
|
+
parameters: z19.object({
|
|
2899
|
+
url: z19.string().optional(),
|
|
2900
|
+
selector: z19.string().optional(),
|
|
2901
|
+
timeout: z19.number().default(3e4),
|
|
2902
|
+
format: z19.enum(["markdown", "html", "text"]).default("markdown"),
|
|
2903
|
+
onlyMainContent: z19.boolean().default(true),
|
|
2904
|
+
retries: z19.number().int().min(0).max(5).optional().default(2).describe("\u91CD\u8BD5\u6B21\u6570\uFF08\u9ED8\u8BA4 2\uFF09"),
|
|
2905
|
+
waitAfterLoad: z19.number().int().optional().default(0).describe("\u9875\u9762\u52A0\u8F7D\u540E\u989D\u5916\u7B49\u5F85\u6BEB\u79D2"),
|
|
2906
|
+
mode: z19.enum(["raw", "clean", "compact", "smart"]).default("raw").describe("\u8F93\u51FA\u6A21\u5F0F\uFF1Araw\uFF08\u9ED8\u8BA4\uFF09/ clean\uFF08\u7ED3\u6784\u5316\uFF09/ compact\uFF08\u7CBE\u7B80\uFF09/ smart\uFF08\u7ED3\u6784\u5316\uFF0C\u7559\u7ED9 agent \u589E\u5F3A\uFF09")
|
|
2832
2907
|
}),
|
|
2833
2908
|
handler: async (p, ctx) => {
|
|
2834
2909
|
const { context, page } = await createEphemeralContext(resolveLaunchOpts(ctx));
|
|
@@ -2836,7 +2911,7 @@ var scrapeCommand = registerCommand({
|
|
|
2836
2911
|
try {
|
|
2837
2912
|
const targetUrl = p.url || page.url();
|
|
2838
2913
|
if (!targetUrl || targetUrl === "about:blank") {
|
|
2839
|
-
return
|
|
2914
|
+
return fail8("URL is required. Provide a URL or connect to a browser (--cdp) with a non-blank page.");
|
|
2840
2915
|
}
|
|
2841
2916
|
let lastError;
|
|
2842
2917
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
@@ -2906,7 +2981,7 @@ var scrapeCommand = registerCommand({
|
|
|
2906
2981
|
} catch {
|
|
2907
2982
|
}
|
|
2908
2983
|
if (p.mode === "smart") {
|
|
2909
|
-
return
|
|
2984
|
+
return ok19(structured);
|
|
2910
2985
|
}
|
|
2911
2986
|
if (p.mode === "compact") {
|
|
2912
2987
|
const compactData = structured.tables.length > 0 ? structured.tables.map((t) => ({
|
|
@@ -2919,9 +2994,9 @@ var scrapeCommand = registerCommand({
|
|
|
2919
2994
|
return compact;
|
|
2920
2995
|
})
|
|
2921
2996
|
})) : structured.mainText?.substring(0, 500);
|
|
2922
|
-
return
|
|
2997
|
+
return ok19({ url: structured.url, title: structured.title, data: compactData });
|
|
2923
2998
|
}
|
|
2924
|
-
return
|
|
2999
|
+
return ok19(structured);
|
|
2925
3000
|
}
|
|
2926
3001
|
let content;
|
|
2927
3002
|
switch (p.format) {
|
|
@@ -2980,7 +3055,7 @@ var scrapeCommand = registerCommand({
|
|
|
2980
3055
|
content = await page.innerText("body");
|
|
2981
3056
|
break;
|
|
2982
3057
|
}
|
|
2983
|
-
return
|
|
3058
|
+
return ok19({ content, title, url: finalUrl });
|
|
2984
3059
|
} catch (err) {
|
|
2985
3060
|
lastError = err instanceof Error ? err : new Error(String(err));
|
|
2986
3061
|
if (attempt < maxAttempts) {
|
|
@@ -2990,20 +3065,20 @@ var scrapeCommand = registerCommand({
|
|
|
2990
3065
|
}
|
|
2991
3066
|
}
|
|
2992
3067
|
}
|
|
2993
|
-
return
|
|
3068
|
+
return fail8(`Scrape failed after ${maxAttempts} attempt(s): ${lastError?.message ?? "unknown error"}`);
|
|
2994
3069
|
} finally {
|
|
2995
3070
|
await closeEphemeralContext(context);
|
|
2996
3071
|
}
|
|
2997
3072
|
},
|
|
2998
|
-
result:
|
|
2999
|
-
url:
|
|
3000
|
-
title:
|
|
3073
|
+
result: z19.object({
|
|
3074
|
+
url: z19.string(),
|
|
3075
|
+
title: z19.string()
|
|
3001
3076
|
}).passthrough()
|
|
3002
3077
|
});
|
|
3003
3078
|
|
|
3004
3079
|
// src/commands/map.ts
|
|
3005
|
-
import { z as
|
|
3006
|
-
import { ok as
|
|
3080
|
+
import { z as z20 } from "zod";
|
|
3081
|
+
import { ok as ok20, fail as fail9 } from "@dyyz1993/xcli-core";
|
|
3007
3082
|
|
|
3008
3083
|
// src/utils/url.ts
|
|
3009
3084
|
var SKIP_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
@@ -3238,21 +3313,21 @@ var mapCommand = registerCommand({
|
|
|
3238
3313
|
name: "map",
|
|
3239
3314
|
description: "Discover all URLs on a website via sitemap and page link extraction",
|
|
3240
3315
|
scope: "project",
|
|
3241
|
-
parameters:
|
|
3242
|
-
url:
|
|
3243
|
-
search:
|
|
3244
|
-
sitemap:
|
|
3245
|
-
includeSubdomains:
|
|
3246
|
-
allowExternalLinks:
|
|
3247
|
-
limit:
|
|
3248
|
-
verbose:
|
|
3316
|
+
parameters: z20.object({
|
|
3317
|
+
url: z20.string().optional(),
|
|
3318
|
+
search: z20.string().optional(),
|
|
3319
|
+
sitemap: z20.enum(["include", "only"]).optional(),
|
|
3320
|
+
includeSubdomains: z20.boolean().optional(),
|
|
3321
|
+
allowExternalLinks: z20.boolean().optional().describe("Include links to external domains"),
|
|
3322
|
+
limit: z20.number().optional(),
|
|
3323
|
+
verbose: z20.boolean().default(false).describe("Show progress feedback")
|
|
3249
3324
|
}),
|
|
3250
3325
|
handler: async (p, ctx) => {
|
|
3251
3326
|
const { context, page } = await createEphemeralContext(resolveLaunchOpts(ctx));
|
|
3252
3327
|
try {
|
|
3253
3328
|
const targetUrl = p.url || page.url();
|
|
3254
3329
|
if (!targetUrl || targetUrl === "about:blank") {
|
|
3255
|
-
return
|
|
3330
|
+
return fail9("URL is required. Provide a URL or connect to a browser (--cdp) with a non-blank page.");
|
|
3256
3331
|
}
|
|
3257
3332
|
const links = await discoverUrls(page, targetUrl, {
|
|
3258
3333
|
sitemap: p.sitemap,
|
|
@@ -3263,7 +3338,7 @@ var mapCommand = registerCommand({
|
|
|
3263
3338
|
verbose: p.verbose
|
|
3264
3339
|
});
|
|
3265
3340
|
const linkObjects = links.map((url) => ({ url }));
|
|
3266
|
-
return
|
|
3341
|
+
return ok20({
|
|
3267
3342
|
links: linkObjects,
|
|
3268
3343
|
success: true
|
|
3269
3344
|
});
|
|
@@ -3271,15 +3346,15 @@ var mapCommand = registerCommand({
|
|
|
3271
3346
|
await closeEphemeralContext(context);
|
|
3272
3347
|
}
|
|
3273
3348
|
},
|
|
3274
|
-
result:
|
|
3275
|
-
links:
|
|
3276
|
-
success:
|
|
3349
|
+
result: z20.object({
|
|
3350
|
+
links: z20.array(z20.object({ url: z20.string() })),
|
|
3351
|
+
success: z20.boolean()
|
|
3277
3352
|
})
|
|
3278
3353
|
});
|
|
3279
3354
|
|
|
3280
3355
|
// src/commands/crawl.ts
|
|
3281
|
-
import { z as
|
|
3282
|
-
import { ok as
|
|
3356
|
+
import { z as z21 } from "zod";
|
|
3357
|
+
import { ok as ok21 } from "@dyyz1993/xcli-core";
|
|
3283
3358
|
function stripHashAnchorQuery(url) {
|
|
3284
3359
|
try {
|
|
3285
3360
|
const parsed = new URL(url);
|
|
@@ -3456,21 +3531,21 @@ var crawlCommand = registerCommand({
|
|
|
3456
3531
|
name: "crawl",
|
|
3457
3532
|
description: "Crawl a website and extract content from all pages",
|
|
3458
3533
|
scope: "project",
|
|
3459
|
-
parameters:
|
|
3460
|
-
url:
|
|
3461
|
-
limit:
|
|
3462
|
-
maxDepth:
|
|
3463
|
-
includePaths:
|
|
3464
|
-
excludePaths:
|
|
3465
|
-
allowSubdomains:
|
|
3466
|
-
allowExternalLinks:
|
|
3467
|
-
allowBackwardCrawling:
|
|
3468
|
-
enableSpa:
|
|
3469
|
-
format:
|
|
3470
|
-
onlyMainContent:
|
|
3471
|
-
concurrency:
|
|
3472
|
-
retries:
|
|
3473
|
-
verbose:
|
|
3534
|
+
parameters: z21.object({
|
|
3535
|
+
url: z21.string(),
|
|
3536
|
+
limit: z21.number().default(10),
|
|
3537
|
+
maxDepth: z21.number().default(3),
|
|
3538
|
+
includePaths: z21.array(z21.string()).optional(),
|
|
3539
|
+
excludePaths: z21.array(z21.string()).optional(),
|
|
3540
|
+
allowSubdomains: z21.boolean().default(false),
|
|
3541
|
+
allowExternalLinks: z21.boolean().default(false),
|
|
3542
|
+
allowBackwardCrawling: z21.boolean().default(false),
|
|
3543
|
+
enableSpa: z21.boolean().default(true).describe("Disable to skip SPA route detection"),
|
|
3544
|
+
format: z21.enum(["markdown", "html"]).default("markdown"),
|
|
3545
|
+
onlyMainContent: z21.boolean().default(true),
|
|
3546
|
+
concurrency: z21.number().default(3),
|
|
3547
|
+
retries: z21.number().default(2),
|
|
3548
|
+
verbose: z21.boolean().default(false)
|
|
3474
3549
|
}),
|
|
3475
3550
|
handler: async (p, ctx) => {
|
|
3476
3551
|
const startUrl = new URL(p.url);
|
|
@@ -3609,7 +3684,7 @@ var crawlCommand = registerCommand({
|
|
|
3609
3684
|
if (errorPages.length > 0) {
|
|
3610
3685
|
response.errors = errorPages;
|
|
3611
3686
|
}
|
|
3612
|
-
return
|
|
3687
|
+
return ok21(response);
|
|
3613
3688
|
} finally {
|
|
3614
3689
|
for (const ctx2 of contexts) {
|
|
3615
3690
|
await ctx2.close().catch(() => {
|
|
@@ -3619,15 +3694,15 @@ var crawlCommand = registerCommand({
|
|
|
3619
3694
|
} catch (err) {
|
|
3620
3695
|
const message = err instanceof Error ? err.message : String(err);
|
|
3621
3696
|
const successPages = results.filter((r) => !isPageError(r));
|
|
3622
|
-
return
|
|
3697
|
+
return ok21({ pages: successPages, total: successPages.length, success: false, error: message });
|
|
3623
3698
|
}
|
|
3624
3699
|
}
|
|
3625
3700
|
});
|
|
3626
3701
|
|
|
3627
3702
|
// src/commands/search.ts
|
|
3628
|
-
import { z as
|
|
3703
|
+
import { z as z22 } from "zod";
|
|
3629
3704
|
import * as cheerio2 from "cheerio";
|
|
3630
|
-
import { ok as
|
|
3705
|
+
import { ok as ok22 } from "@dyyz1993/xcli-core";
|
|
3631
3706
|
function getRecencyParams(recency) {
|
|
3632
3707
|
const now = Math.floor(Date.now() / 1e3);
|
|
3633
3708
|
switch (recency) {
|
|
@@ -3961,16 +4036,16 @@ var searchCommand = registerCommand({
|
|
|
3961
4036
|
name: "search",
|
|
3962
4037
|
description: "Search the web and extract results with engine fallback",
|
|
3963
4038
|
scope: "project",
|
|
3964
|
-
parameters:
|
|
3965
|
-
query:
|
|
3966
|
-
engine:
|
|
3967
|
-
limit:
|
|
3968
|
-
full:
|
|
3969
|
-
format:
|
|
3970
|
-
timeout:
|
|
3971
|
-
recency:
|
|
3972
|
-
fallback:
|
|
3973
|
-
site:
|
|
4039
|
+
parameters: z22.object({
|
|
4040
|
+
query: z22.string(),
|
|
4041
|
+
engine: z22.string().optional(),
|
|
4042
|
+
limit: z22.number().default(10),
|
|
4043
|
+
full: z22.boolean().default(false),
|
|
4044
|
+
format: z22.enum(["markdown", "json", "text"]).default("markdown"),
|
|
4045
|
+
timeout: z22.number().default(15e3),
|
|
4046
|
+
recency: z22.enum(["hour", "day", "week", "month", "year"]).optional().describe("Filter by time: hour/day/week/month/year"),
|
|
4047
|
+
fallback: z22.boolean().default(false).describe("Sequential engine fallback instead of parallel"),
|
|
4048
|
+
site: z22.string().optional().describe("Limit results to a specific site (e.g. github.com, v2ex.com)")
|
|
3974
4049
|
}),
|
|
3975
4050
|
handler: async (p, ctx) => {
|
|
3976
4051
|
const { context } = await createEphemeralContext(resolveLaunchOpts(ctx));
|
|
@@ -4076,7 +4151,7 @@ ${errors.map((e) => ` - ${e.engine}: ${e.error}`).join("\n")}`
|
|
|
4076
4151
|
lines.push(`> ${r.snippet}`);
|
|
4077
4152
|
lines.push("");
|
|
4078
4153
|
}
|
|
4079
|
-
return
|
|
4154
|
+
return ok22({ ...searchResult, content: lines.join("\n") });
|
|
4080
4155
|
}
|
|
4081
4156
|
if (p.format === "text") {
|
|
4082
4157
|
const lines = [`Search: ${searchResult.query} (Engine: ${searchResult.engine}, Total: ${searchResult.total})`, ""];
|
|
@@ -4086,9 +4161,9 @@ ${errors.map((e) => ` - ${e.engine}: ${e.error}`).join("\n")}`
|
|
|
4086
4161
|
lines.push(` ${r.snippet}`);
|
|
4087
4162
|
lines.push("");
|
|
4088
4163
|
}
|
|
4089
|
-
return
|
|
4164
|
+
return ok22({ ...searchResult, content: lines.join("\n") });
|
|
4090
4165
|
}
|
|
4091
|
-
return
|
|
4166
|
+
return ok22(searchResult);
|
|
4092
4167
|
} finally {
|
|
4093
4168
|
await closeEphemeralContext(context);
|
|
4094
4169
|
}
|
|
@@ -4096,8 +4171,8 @@ ${errors.map((e) => ` - ${e.engine}: ${e.error}`).join("\n")}`
|
|
|
4096
4171
|
});
|
|
4097
4172
|
|
|
4098
4173
|
// src/commands/network.ts
|
|
4099
|
-
import { z as
|
|
4100
|
-
import { ok as
|
|
4174
|
+
import { z as z23 } from "zod";
|
|
4175
|
+
import { ok as ok23, fail as fail10 } from "@dyyz1993/xcli-core";
|
|
4101
4176
|
function extractPath2(url) {
|
|
4102
4177
|
try {
|
|
4103
4178
|
const u = new URL(url);
|
|
@@ -4195,19 +4270,19 @@ var networkCommand = registerCommand({
|
|
|
4195
4270
|
name: "network",
|
|
4196
4271
|
description: "Capture and filter network responses from a URL",
|
|
4197
4272
|
scope: "project",
|
|
4198
|
-
parameters:
|
|
4199
|
-
url:
|
|
4200
|
-
filter:
|
|
4201
|
-
match:
|
|
4202
|
-
search:
|
|
4203
|
-
console:
|
|
4204
|
-
timeout:
|
|
4205
|
-
wait:
|
|
4206
|
-
limit:
|
|
4207
|
-
format:
|
|
4208
|
-
ws:
|
|
4209
|
-
listen:
|
|
4210
|
-
duration:
|
|
4273
|
+
parameters: z23.object({
|
|
4274
|
+
url: z23.string(),
|
|
4275
|
+
filter: z23.string().optional(),
|
|
4276
|
+
match: z23.string().optional(),
|
|
4277
|
+
search: z23.string().optional().describe("Search within all captured response bodies"),
|
|
4278
|
+
console: z23.boolean().default(false),
|
|
4279
|
+
timeout: z23.number().default(3e4),
|
|
4280
|
+
wait: z23.number().default(3e3),
|
|
4281
|
+
limit: z23.number().default(50),
|
|
4282
|
+
format: z23.enum(["summary", "json"]).default("summary"),
|
|
4283
|
+
ws: z23.boolean().optional().default(false).describe("Only show WebSocket messages"),
|
|
4284
|
+
listen: z23.boolean().optional().default(false).describe("\u76D1\u542C\u6A21\u5F0F\uFF1A\u4F7F\u7528\u73B0\u6709 session \u7684 page\uFF0C\u7B49\u5F85\u6307\u5B9A\u65F6\u95F4\u6355\u83B7\u8BF7\u6C42"),
|
|
4285
|
+
duration: z23.number().int().optional().default(15e3).describe("\u76D1\u542C\u6A21\u5F0F\u7B49\u5F85\u65F6\u957F\uFF08\u6BEB\u79D2\uFF0C\u9ED8\u8BA4 15000\uFF09")
|
|
4211
4286
|
}),
|
|
4212
4287
|
handler: async (p, ctx) => {
|
|
4213
4288
|
const startTime = Date.now();
|
|
@@ -4262,7 +4337,7 @@ var networkCommand = registerCommand({
|
|
|
4262
4337
|
};
|
|
4263
4338
|
if (p.listen) {
|
|
4264
4339
|
const page2 = ctx.page;
|
|
4265
|
-
if (!page2) return
|
|
4340
|
+
if (!page2) return fail10("No active page. Use --cdp to connect first.");
|
|
4266
4341
|
const captures = [];
|
|
4267
4342
|
const consoleMessages = [];
|
|
4268
4343
|
const wsCaptures = [];
|
|
@@ -4289,7 +4364,7 @@ var networkCommand = registerCommand({
|
|
|
4289
4364
|
page2.off("response", handler);
|
|
4290
4365
|
const duration = Date.now() - startTime;
|
|
4291
4366
|
if (p.ws && wsCaptures.length > 0) {
|
|
4292
|
-
return
|
|
4367
|
+
return ok23({
|
|
4293
4368
|
url: "[listen mode]",
|
|
4294
4369
|
duration,
|
|
4295
4370
|
total: captures.length,
|
|
@@ -4303,9 +4378,9 @@ var networkCommand = registerCommand({
|
|
|
4303
4378
|
});
|
|
4304
4379
|
}
|
|
4305
4380
|
if (p.format === "json") {
|
|
4306
|
-
return
|
|
4381
|
+
return ok23(buildJsonOutput("[listen mode]", captures, consoleMessages, captures.length, wsCaptures));
|
|
4307
4382
|
}
|
|
4308
|
-
return
|
|
4383
|
+
return ok23(buildSummaryOutput("[listen mode]", duration, captures, consoleMessages, captures.length, wsCaptures));
|
|
4309
4384
|
}
|
|
4310
4385
|
const { context, page } = await createEphemeralContext(resolveLaunchOpts(ctx));
|
|
4311
4386
|
try {
|
|
@@ -4360,7 +4435,7 @@ var networkCommand = registerCommand({
|
|
|
4360
4435
|
}
|
|
4361
4436
|
const duration = Date.now() - startTime;
|
|
4362
4437
|
if (p.ws && wsCaptures.length > 0) {
|
|
4363
|
-
return
|
|
4438
|
+
return ok23({
|
|
4364
4439
|
url: p.url,
|
|
4365
4440
|
duration,
|
|
4366
4441
|
total: captures.length,
|
|
@@ -4374,9 +4449,9 @@ var networkCommand = registerCommand({
|
|
|
4374
4449
|
});
|
|
4375
4450
|
}
|
|
4376
4451
|
if (p.format === "json") {
|
|
4377
|
-
return
|
|
4452
|
+
return ok23(buildJsonOutput(p.url, results, consoleMessages, totalCount, wsCaptures, searchResults));
|
|
4378
4453
|
}
|
|
4379
|
-
return
|
|
4454
|
+
return ok23(buildSummaryOutput(p.url, duration, results, consoleMessages, totalCount, wsCaptures));
|
|
4380
4455
|
} finally {
|
|
4381
4456
|
await closeEphemeralContext(context);
|
|
4382
4457
|
}
|
|
@@ -4384,7 +4459,7 @@ var networkCommand = registerCommand({
|
|
|
4384
4459
|
});
|
|
4385
4460
|
|
|
4386
4461
|
// src/commands/ai-search-engines.ts
|
|
4387
|
-
import { z as
|
|
4462
|
+
import { z as z24 } from "zod";
|
|
4388
4463
|
var ENGINE_CONFIGS = {
|
|
4389
4464
|
deepseek: {
|
|
4390
4465
|
key: "deepseek",
|
|
@@ -4638,11 +4713,11 @@ var ENGINE_CONFIGS = {
|
|
|
4638
4713
|
}
|
|
4639
4714
|
};
|
|
4640
4715
|
var ALL_ENGINE_KEYS = Object.keys(ENGINE_CONFIGS);
|
|
4641
|
-
var ENGINE_KEY_ENUM =
|
|
4716
|
+
var ENGINE_KEY_ENUM = z24.enum(ALL_ENGINE_KEYS);
|
|
4642
4717
|
|
|
4643
4718
|
// src/commands/snapshot.ts
|
|
4644
|
-
import { z as
|
|
4645
|
-
import { ok as
|
|
4719
|
+
import { z as z25 } from "zod";
|
|
4720
|
+
import { ok as ok24, fail as fail11, normalizeTips as normalizeTips3 } from "@dyyz1993/xcli-core";
|
|
4646
4721
|
|
|
4647
4722
|
// src/runtime/ref-store.ts
|
|
4648
4723
|
var sessions = /* @__PURE__ */ new Map();
|
|
@@ -5554,24 +5629,24 @@ var snapshotCommand = registerCommand({
|
|
|
5554
5629
|
description: "Capture a quick page state snapshot \u2014 aria tree, visible text, or DOM summary",
|
|
5555
5630
|
scope: "page",
|
|
5556
5631
|
selectorParams: ["selector"],
|
|
5557
|
-
parameters:
|
|
5558
|
-
type:
|
|
5559
|
-
selector:
|
|
5560
|
-
depth:
|
|
5561
|
-
interactive:
|
|
5562
|
-
interactiveOnly:
|
|
5563
|
-
i:
|
|
5564
|
-
compact:
|
|
5565
|
-
c:
|
|
5566
|
-
selectors:
|
|
5567
|
-
all:
|
|
5632
|
+
parameters: z25.object({
|
|
5633
|
+
type: z25.enum(["aria", "text", "dom", "all"]).default("aria").describe("Snapshot type: aria (accessibility tree), text (visible text), dom (element summary), all (combined)"),
|
|
5634
|
+
selector: z25.string().optional().describe("Scope to a specific element"),
|
|
5635
|
+
depth: z25.number().optional().default(6).describe("Max depth for DOM/aria tree"),
|
|
5636
|
+
interactive: z25.boolean().optional().default(false).describe("Return interactive agent refs only"),
|
|
5637
|
+
interactiveOnly: z25.boolean().optional().default(false).describe("Alias for interactive"),
|
|
5638
|
+
i: z25.boolean().optional().default(false).describe("Short alias for interactive"),
|
|
5639
|
+
compact: z25.boolean().optional().default(false).describe("Include compact xbrowser style snapshot text"),
|
|
5640
|
+
c: z25.boolean().optional().default(false).describe("Short alias for compact"),
|
|
5641
|
+
selectors: z25.boolean().optional().default(false).describe("Include ref to CSS selector map"),
|
|
5642
|
+
all: z25.boolean().optional().default(false).describe("Include hidden interactive targets when using interactive snapshot")
|
|
5568
5643
|
}),
|
|
5569
|
-
result:
|
|
5570
|
-
url:
|
|
5571
|
-
title:
|
|
5572
|
-
aria:
|
|
5573
|
-
text:
|
|
5574
|
-
dom:
|
|
5644
|
+
result: z25.object({
|
|
5645
|
+
url: z25.string(),
|
|
5646
|
+
title: z25.string(),
|
|
5647
|
+
aria: z25.string().optional(),
|
|
5648
|
+
text: z25.string().optional(),
|
|
5649
|
+
dom: z25.record(z25.unknown()).optional()
|
|
5575
5650
|
}),
|
|
5576
5651
|
handler: async (p, ctx) => {
|
|
5577
5652
|
const page = ctx.page;
|
|
@@ -5585,7 +5660,7 @@ var snapshotCommand = registerCommand({
|
|
|
5585
5660
|
if (p.compact || p.c || p.interactive || p.interactiveOnly || p.i) {
|
|
5586
5661
|
observation.compact = formatObservationCompact(observation, { selectors: p.selectors });
|
|
5587
5662
|
}
|
|
5588
|
-
return
|
|
5663
|
+
return ok24(observation, normalizeTips3([
|
|
5589
5664
|
`refs refreshed for ${observation.targets.length} targets; use click @e1 or fill @e2 "text"`
|
|
5590
5665
|
]));
|
|
5591
5666
|
}
|
|
@@ -5593,15 +5668,15 @@ var snapshotCommand = registerCommand({
|
|
|
5593
5668
|
const aria = await captureAriaSnapshot(page, p.selector, p.depth);
|
|
5594
5669
|
const tips = await buildRefTips(page, aria);
|
|
5595
5670
|
persistSemantics(url, aria);
|
|
5596
|
-
return
|
|
5671
|
+
return ok24({ url, title, aria }, normalizeTips3(tips));
|
|
5597
5672
|
}
|
|
5598
5673
|
if (p.type === "text") {
|
|
5599
5674
|
const text = await captureTextSnapshot(page, p.selector);
|
|
5600
|
-
return
|
|
5675
|
+
return ok24({ url, title, text });
|
|
5601
5676
|
}
|
|
5602
5677
|
if (p.type === "dom") {
|
|
5603
5678
|
const dom = await captureDomSnapshot(page, p.selector, p.depth ?? 6);
|
|
5604
|
-
return
|
|
5679
|
+
return ok24({ url, title, dom });
|
|
5605
5680
|
}
|
|
5606
5681
|
if (p.type === "all") {
|
|
5607
5682
|
const [aria, text, dom] = await Promise.all([
|
|
@@ -5611,9 +5686,9 @@ var snapshotCommand = registerCommand({
|
|
|
5611
5686
|
]);
|
|
5612
5687
|
const tips = await buildRefTips(page, aria);
|
|
5613
5688
|
persistSemantics(url, aria);
|
|
5614
|
-
return
|
|
5689
|
+
return ok24({ url, title, aria, text, dom }, normalizeTips3(tips));
|
|
5615
5690
|
}
|
|
5616
|
-
return
|
|
5691
|
+
return fail11(`Unknown snapshot type: ${p.type}`);
|
|
5617
5692
|
}
|
|
5618
5693
|
});
|
|
5619
5694
|
function persistSemantics(url, aria) {
|
|
@@ -5690,22 +5765,22 @@ async function captureDomSnapshot(page, selector, maxDepth) {
|
|
|
5690
5765
|
}
|
|
5691
5766
|
|
|
5692
5767
|
// src/commands/agent.ts
|
|
5693
|
-
import { z as
|
|
5694
|
-
import { ok as
|
|
5768
|
+
import { z as z26 } from "zod";
|
|
5769
|
+
import { ok as ok25, normalizeTips as normalizeTips4 } from "@dyyz1993/xcli-core";
|
|
5695
5770
|
var observeCommand = registerCommand({
|
|
5696
5771
|
name: "observe",
|
|
5697
5772
|
description: "Observe the current page as structured agent targets with session refs",
|
|
5698
5773
|
scope: "page",
|
|
5699
|
-
parameters:
|
|
5700
|
-
includeHidden:
|
|
5701
|
-
limit:
|
|
5702
|
-
compact:
|
|
5703
|
-
selectors:
|
|
5774
|
+
parameters: z26.object({
|
|
5775
|
+
includeHidden: z26.boolean().optional().default(false).describe("Include hidden elements in the target list"),
|
|
5776
|
+
limit: z26.number().int().positive().max(300).optional().default(80).describe("Maximum number of targets to return"),
|
|
5777
|
+
compact: z26.boolean().optional().default(false).describe("Include compact xbrowser style snapshot text"),
|
|
5778
|
+
selectors: z26.boolean().optional().default(false).describe("Include ref to stable CSS selector map")
|
|
5704
5779
|
}),
|
|
5705
|
-
result:
|
|
5706
|
-
targets:
|
|
5707
|
-
selectors:
|
|
5708
|
-
compact:
|
|
5780
|
+
result: z26.object({
|
|
5781
|
+
targets: z26.array(z26.record(z26.unknown())),
|
|
5782
|
+
selectors: z26.record(z26.unknown()).optional(),
|
|
5783
|
+
compact: z26.string().optional()
|
|
5709
5784
|
}).passthrough(),
|
|
5710
5785
|
handler: async (p, ctx) => {
|
|
5711
5786
|
const observation = await observePage(ctx.page, ctx.sessionId, {
|
|
@@ -5714,7 +5789,7 @@ var observeCommand = registerCommand({
|
|
|
5714
5789
|
});
|
|
5715
5790
|
if (p.selectors) observation.selectors = buildSelectorMap(observation);
|
|
5716
5791
|
if (p.compact) observation.compact = formatObservationCompact(observation, { selectors: p.selectors });
|
|
5717
|
-
return
|
|
5792
|
+
return ok25(observation, normalizeTips4([
|
|
5718
5793
|
`refs refreshed for ${observation.targets.length} targets; use act --ref @e1 --action click or click @e1`
|
|
5719
5794
|
]));
|
|
5720
5795
|
}
|
|
@@ -5724,14 +5799,14 @@ var actCommand = registerCommand({
|
|
|
5724
5799
|
description: "Perform an agent action using an observe ref or explicit selector",
|
|
5725
5800
|
scope: "element",
|
|
5726
5801
|
selectorParams: ["selector"],
|
|
5727
|
-
parameters:
|
|
5728
|
-
action:
|
|
5729
|
-
ref:
|
|
5730
|
-
selector:
|
|
5731
|
-
value:
|
|
5732
|
-
key:
|
|
5733
|
-
force:
|
|
5734
|
-
timeout:
|
|
5802
|
+
parameters: z26.object({
|
|
5803
|
+
action: z26.enum(["click", "fill", "type", "press", "select", "check", "hover"]).default("click"),
|
|
5804
|
+
ref: z26.string().optional().describe("Session-scoped ref returned by observe, such as e1"),
|
|
5805
|
+
selector: z26.string().optional().describe("CSS selector fallback when no ref is available"),
|
|
5806
|
+
value: z26.string().optional().describe("Value for fill/type/select"),
|
|
5807
|
+
key: z26.string().optional().describe("Key for press"),
|
|
5808
|
+
force: z26.boolean().optional().default(false).describe("Bypass actionability checks"),
|
|
5809
|
+
timeout: z26.number().optional().default(1e4).describe("Playwright action timeout in milliseconds")
|
|
5735
5810
|
}).refine((p) => !!p.ref || !!p.selector, {
|
|
5736
5811
|
message: "Either ref or selector is required"
|
|
5737
5812
|
}),
|
|
@@ -5745,7 +5820,7 @@ var actCommand = registerCommand({
|
|
|
5745
5820
|
tips: normalizeTips4(result.stale ? ["run observe again to refresh refs"] : [])
|
|
5746
5821
|
};
|
|
5747
5822
|
}
|
|
5748
|
-
return
|
|
5823
|
+
return ok25(result, normalizeTips4(result.stale ? ["ref screen hash changed; run observe if the next action is uncertain"] : []));
|
|
5749
5824
|
}
|
|
5750
5825
|
});
|
|
5751
5826
|
var waitForCommand = registerCommand({
|
|
@@ -5753,16 +5828,16 @@ var waitForCommand = registerCommand({
|
|
|
5753
5828
|
description: "Wait for agent predicates such as text, URL, load state, selector state, or screen hash changes",
|
|
5754
5829
|
scope: "page",
|
|
5755
5830
|
selectorParams: ["selector"],
|
|
5756
|
-
parameters:
|
|
5757
|
-
selector:
|
|
5758
|
-
state:
|
|
5759
|
-
text:
|
|
5760
|
-
url:
|
|
5761
|
-
load:
|
|
5762
|
-
fn:
|
|
5763
|
-
screenHashChanged:
|
|
5764
|
-
timeout:
|
|
5765
|
-
pollInterval:
|
|
5831
|
+
parameters: z26.object({
|
|
5832
|
+
selector: z26.string().optional().describe("CSS selector or observe ref to wait for"),
|
|
5833
|
+
state: z26.enum(["attached", "detached", "visible", "hidden"]).optional().default("visible"),
|
|
5834
|
+
text: z26.string().optional().describe("Visible text to wait for"),
|
|
5835
|
+
url: z26.string().optional().describe("URL substring or glob pattern to wait for"),
|
|
5836
|
+
load: z26.enum(["load", "domcontentloaded", "networkidle"]).optional().describe("Load state to wait for"),
|
|
5837
|
+
fn: z26.string().optional().describe("JavaScript predicate to wait for"),
|
|
5838
|
+
screenHashChanged: z26.string().optional().describe("Previous screenHash from observe"),
|
|
5839
|
+
timeout: z26.number().optional().default(3e4),
|
|
5840
|
+
pollInterval: z26.number().optional().default(200)
|
|
5766
5841
|
}).refine((p) => [p.selector, p.text, p.url, p.load, p.fn, p.screenHashChanged].filter(Boolean).length === 1, {
|
|
5767
5842
|
message: "Provide exactly one wait predicate: selector, text, url, load, fn, or screenHashChanged"
|
|
5768
5843
|
}),
|
|
@@ -5776,30 +5851,30 @@ var waitForCommand = registerCommand({
|
|
|
5776
5851
|
tips: []
|
|
5777
5852
|
};
|
|
5778
5853
|
}
|
|
5779
|
-
return
|
|
5854
|
+
return ok25(result);
|
|
5780
5855
|
}
|
|
5781
5856
|
});
|
|
5782
5857
|
|
|
5783
5858
|
// src/commands/tab.ts
|
|
5784
|
-
import { z as
|
|
5785
|
-
import { ok as
|
|
5786
|
-
var TabParams =
|
|
5787
|
-
subcommand:
|
|
5788
|
-
url:
|
|
5789
|
-
index:
|
|
5859
|
+
import { z as z27 } from "zod";
|
|
5860
|
+
import { ok as ok26, fail as fail12 } from "@dyyz1993/xcli-core";
|
|
5861
|
+
var TabParams = z27.object({
|
|
5862
|
+
subcommand: z27.enum(["list", "new", "close", "switch"]),
|
|
5863
|
+
url: z27.string().optional(),
|
|
5864
|
+
index: z27.number().int().min(0).optional()
|
|
5790
5865
|
});
|
|
5791
5866
|
var tabCommand = registerCommand({
|
|
5792
5867
|
name: "tab",
|
|
5793
5868
|
description: "Manage browser tabs: list, new, close, switch",
|
|
5794
5869
|
scope: "page",
|
|
5795
5870
|
parameters: TabParams,
|
|
5796
|
-
result:
|
|
5797
|
-
success:
|
|
5798
|
-
data:
|
|
5871
|
+
result: z27.object({
|
|
5872
|
+
success: z27.boolean(),
|
|
5873
|
+
data: z27.unknown()
|
|
5799
5874
|
}),
|
|
5800
5875
|
handler: async (p, ctx) => {
|
|
5801
5876
|
if (!ctx.browserContext) {
|
|
5802
|
-
return
|
|
5877
|
+
return fail12("No browser context available. Use --cdp to connect to a browser first.");
|
|
5803
5878
|
}
|
|
5804
5879
|
const pages = ctx.browserContext.pages();
|
|
5805
5880
|
switch (p.subcommand) {
|
|
@@ -5812,7 +5887,7 @@ var tabCommand = registerCommand({
|
|
|
5812
5887
|
case "switch":
|
|
5813
5888
|
return handleSwitch(p, pages, ctx);
|
|
5814
5889
|
default:
|
|
5815
|
-
return
|
|
5890
|
+
return fail12(`Unknown subcommand: ${p.subcommand}`);
|
|
5816
5891
|
}
|
|
5817
5892
|
}
|
|
5818
5893
|
});
|
|
@@ -5827,7 +5902,7 @@ async function handleList(pages, ctx) {
|
|
|
5827
5902
|
if (isActive) activeIndex = i;
|
|
5828
5903
|
tabs.push({ index: i, url, title, active: isActive });
|
|
5829
5904
|
}
|
|
5830
|
-
return
|
|
5905
|
+
return ok26({ tabs, total: tabs.length, activeIndex });
|
|
5831
5906
|
}
|
|
5832
5907
|
async function handleNew(p, _pages, ctx) {
|
|
5833
5908
|
const newPage = await ctx.browserContext.newPage();
|
|
@@ -5855,7 +5930,7 @@ async function handleNew(p, _pages, ctx) {
|
|
|
5855
5930
|
const title = await newPage.title().catch(() => "");
|
|
5856
5931
|
const allPages = ctx.browserContext.pages();
|
|
5857
5932
|
const newIndex = allPages.indexOf(newPage);
|
|
5858
|
-
return
|
|
5933
|
+
return ok26({
|
|
5859
5934
|
index: newIndex >= 0 ? newIndex : allPages.length - 1,
|
|
5860
5935
|
url: newPage.url(),
|
|
5861
5936
|
title,
|
|
@@ -5866,11 +5941,11 @@ async function handleNew(p, _pages, ctx) {
|
|
|
5866
5941
|
async function handleClose(p, ctx) {
|
|
5867
5942
|
const currentPages = ctx.browserContext.pages();
|
|
5868
5943
|
if (currentPages.length <= 1) {
|
|
5869
|
-
return
|
|
5944
|
+
return fail12("Cannot close the last remaining tab");
|
|
5870
5945
|
}
|
|
5871
5946
|
const closeIndex = p.index ?? currentPages.findIndex((pg) => pg === ctx.page);
|
|
5872
5947
|
if (closeIndex < 0 || closeIndex >= currentPages.length) {
|
|
5873
|
-
return
|
|
5948
|
+
return fail12(`Invalid tab index: ${closeIndex}. Valid range: 0-${currentPages.length - 1}`);
|
|
5874
5949
|
}
|
|
5875
5950
|
const pageToClose = currentPages[closeIndex];
|
|
5876
5951
|
const isActivePage = pageToClose === ctx.page;
|
|
@@ -5885,7 +5960,7 @@ async function handleClose(p, ctx) {
|
|
|
5885
5960
|
}
|
|
5886
5961
|
ctx.page = newActivePage;
|
|
5887
5962
|
}
|
|
5888
|
-
return
|
|
5963
|
+
return ok26({
|
|
5889
5964
|
closedIndex: closeIndex,
|
|
5890
5965
|
total: remainingPages.length,
|
|
5891
5966
|
activeIndex: isActivePage ? closeIndex < remainingPages.length ? closeIndex : remainingPages.length - 1 : remainingPages.findIndex((pg) => pg === ctx.page)
|
|
@@ -5893,10 +5968,10 @@ async function handleClose(p, ctx) {
|
|
|
5893
5968
|
}
|
|
5894
5969
|
async function handleSwitch(p, pages, ctx) {
|
|
5895
5970
|
if (p.index === void 0) {
|
|
5896
|
-
return
|
|
5971
|
+
return fail12("Parameter --index is required for switch subcommand");
|
|
5897
5972
|
}
|
|
5898
5973
|
if (p.index < 0 || p.index >= pages.length) {
|
|
5899
|
-
return
|
|
5974
|
+
return fail12(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
|
|
5900
5975
|
}
|
|
5901
5976
|
const targetPage = pages[p.index];
|
|
5902
5977
|
await targetPage.bringToFront().catch(() => {
|
|
@@ -5918,7 +5993,7 @@ async function handleSwitch(p, pages, ctx) {
|
|
|
5918
5993
|
}
|
|
5919
5994
|
ctx.page = targetPage;
|
|
5920
5995
|
const title = await targetPage.title().catch(() => "");
|
|
5921
|
-
return
|
|
5996
|
+
return ok26({
|
|
5922
5997
|
index: p.index,
|
|
5923
5998
|
url: targetPage.url(),
|
|
5924
5999
|
title,
|
|
@@ -5927,8 +6002,8 @@ async function handleSwitch(p, pages, ctx) {
|
|
|
5927
6002
|
}
|
|
5928
6003
|
|
|
5929
6004
|
// src/commands/addinitscript.ts
|
|
5930
|
-
import { z as
|
|
5931
|
-
import { ok as
|
|
6005
|
+
import { z as z28 } from "zod";
|
|
6006
|
+
import { ok as ok27 } from "@dyyz1993/xcli-core";
|
|
5932
6007
|
import { readFileSync as readFileSync4 } from "fs";
|
|
5933
6008
|
|
|
5934
6009
|
// src/chain-parser.ts
|
|
@@ -6069,14 +6144,14 @@ registerCommandDefinition("tab", ["subcommand"]);
|
|
|
6069
6144
|
registerCommandDefinition("mouse", ["action", "x", "y"]);
|
|
6070
6145
|
|
|
6071
6146
|
// src/commands/addinitscript.ts
|
|
6072
|
-
var InitScriptParams =
|
|
6073
|
-
script:
|
|
6074
|
-
file:
|
|
6075
|
-
stdin:
|
|
6076
|
-
name:
|
|
6077
|
-
list:
|
|
6078
|
-
remove:
|
|
6079
|
-
base64:
|
|
6147
|
+
var InitScriptParams = z28.object({
|
|
6148
|
+
script: z28.string().optional(),
|
|
6149
|
+
file: z28.string().optional(),
|
|
6150
|
+
stdin: z28.boolean().optional(),
|
|
6151
|
+
name: z28.string().optional(),
|
|
6152
|
+
list: z28.boolean().optional(),
|
|
6153
|
+
remove: z28.union([z28.string(), z28.boolean()]).optional(),
|
|
6154
|
+
base64: z28.string().optional()
|
|
6080
6155
|
});
|
|
6081
6156
|
var registeredScripts = /* @__PURE__ */ new Map();
|
|
6082
6157
|
function resolveScriptContent(params) {
|
|
@@ -6110,14 +6185,14 @@ var addInitScriptCommand = registerCommand({
|
|
|
6110
6185
|
description: "Add an initialization script that runs on every page load",
|
|
6111
6186
|
scope: "page",
|
|
6112
6187
|
parameters: InitScriptParams,
|
|
6113
|
-
result:
|
|
6114
|
-
scripts:
|
|
6115
|
-
removed:
|
|
6116
|
-
existed:
|
|
6117
|
-
error:
|
|
6118
|
-
registered:
|
|
6119
|
-
hint:
|
|
6120
|
-
executedImmediately:
|
|
6188
|
+
result: z28.object({
|
|
6189
|
+
scripts: z28.array(z28.object({ name: z28.string(), size: z28.number(), preview: z28.string() })).optional(),
|
|
6190
|
+
removed: z28.string().optional(),
|
|
6191
|
+
existed: z28.boolean().optional(),
|
|
6192
|
+
error: z28.string().optional(),
|
|
6193
|
+
registered: z28.string().optional(),
|
|
6194
|
+
hint: z28.string().optional(),
|
|
6195
|
+
executedImmediately: z28.boolean().optional()
|
|
6121
6196
|
}).passthrough(),
|
|
6122
6197
|
handler: async (params, ctx) => {
|
|
6123
6198
|
if (params.list) {
|
|
@@ -6126,20 +6201,20 @@ var addInitScriptCommand = registerCommand({
|
|
|
6126
6201
|
size: content2.length,
|
|
6127
6202
|
preview: content2.slice(0, 80)
|
|
6128
6203
|
}));
|
|
6129
|
-
return
|
|
6204
|
+
return ok27({ scripts });
|
|
6130
6205
|
}
|
|
6131
6206
|
if (params.remove && typeof params.remove === "string") {
|
|
6132
6207
|
const existed = registeredScripts.delete(params.remove);
|
|
6133
|
-
return
|
|
6208
|
+
return ok27({ removed: params.remove, existed });
|
|
6134
6209
|
}
|
|
6135
6210
|
const removeTarget = (typeof params.remove === "string" ? params.remove : null) || (params.name && !resolveScriptContent(params) ? params.name : null);
|
|
6136
6211
|
if (removeTarget && !resolveScriptContent(params)) {
|
|
6137
6212
|
const existed = registeredScripts.delete(removeTarget);
|
|
6138
|
-
return
|
|
6213
|
+
return ok27({ removed: removeTarget, existed });
|
|
6139
6214
|
}
|
|
6140
6215
|
let content = params.stdin ? await readStdin() : resolveScriptContent(params);
|
|
6141
6216
|
if (!content) {
|
|
6142
|
-
return
|
|
6217
|
+
return ok27({ error: "No script content provided. Use --script, --file, --stdin, or --base64" });
|
|
6143
6218
|
}
|
|
6144
6219
|
const scriptName = params.name ?? `script-${Date.now()}`;
|
|
6145
6220
|
registeredScripts.set(scriptName, content);
|
|
@@ -6147,45 +6222,45 @@ var addInitScriptCommand = registerCommand({
|
|
|
6147
6222
|
try {
|
|
6148
6223
|
await ctx.page.evaluate(content);
|
|
6149
6224
|
} catch {
|
|
6150
|
-
return
|
|
6225
|
+
return ok27({
|
|
6151
6226
|
registered: scriptName,
|
|
6152
6227
|
hint: "Script registered for future page loads; immediate execution skipped (page may not be ready)"
|
|
6153
6228
|
});
|
|
6154
6229
|
}
|
|
6155
|
-
return
|
|
6230
|
+
return ok27({ registered: scriptName, executedImmediately: true });
|
|
6156
6231
|
}
|
|
6157
6232
|
});
|
|
6158
6233
|
registerCommandDefinition("addinitscript", ["script"]);
|
|
6159
6234
|
|
|
6160
6235
|
// src/commands/find.ts
|
|
6161
|
-
import { z as
|
|
6162
|
-
import { ok as
|
|
6163
|
-
var actionSchema2 =
|
|
6236
|
+
import { z as z29 } from "zod";
|
|
6237
|
+
import { ok as ok28, fail as fail13, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
|
|
6238
|
+
var actionSchema2 = z29.enum(["click", "fill", "type", "select", "hover", "check"]);
|
|
6164
6239
|
var findCommand = registerCommand({
|
|
6165
6240
|
name: "find",
|
|
6166
6241
|
description: "Find elements by semantic strategy (text/role/label/placeholder/testid) and optionally perform an action",
|
|
6167
6242
|
scope: "page",
|
|
6168
|
-
parameters:
|
|
6169
|
-
strategy:
|
|
6170
|
-
value:
|
|
6171
|
-
name:
|
|
6172
|
-
exact:
|
|
6173
|
-
operation:
|
|
6243
|
+
parameters: z29.object({
|
|
6244
|
+
strategy: z29.enum(["text", "role", "label", "placeholder", "testid", "alt", "title", "first", "last", "nth"]),
|
|
6245
|
+
value: z29.string(),
|
|
6246
|
+
name: z29.string().optional(),
|
|
6247
|
+
exact: z29.boolean().optional().default(false),
|
|
6248
|
+
operation: z29.string().optional().describe('Trailing operation syntax, e.g. click, fill "text", type "text"'),
|
|
6174
6249
|
action: actionSchema2.optional().describe("Action to perform when not using trailing operation syntax"),
|
|
6175
|
-
actionValue:
|
|
6176
|
-
index:
|
|
6177
|
-
click:
|
|
6178
|
-
fill:
|
|
6179
|
-
type:
|
|
6180
|
-
select:
|
|
6181
|
-
hover:
|
|
6182
|
-
check:
|
|
6183
|
-
timeout:
|
|
6250
|
+
actionValue: z29.string().optional().describe("Value for fill/type/select when using action"),
|
|
6251
|
+
index: z29.number().int().optional().describe("Index for nth strategy"),
|
|
6252
|
+
click: z29.boolean().optional().default(false),
|
|
6253
|
+
fill: z29.string().optional(),
|
|
6254
|
+
type: z29.string().optional(),
|
|
6255
|
+
select: z29.string().optional(),
|
|
6256
|
+
hover: z29.boolean().optional().default(false),
|
|
6257
|
+
check: z29.boolean().optional().default(false),
|
|
6258
|
+
timeout: z29.number().optional().default(1e4)
|
|
6184
6259
|
}),
|
|
6185
|
-
result:
|
|
6186
|
-
matched:
|
|
6187
|
-
selector:
|
|
6188
|
-
action:
|
|
6260
|
+
result: z29.object({
|
|
6261
|
+
matched: z29.number(),
|
|
6262
|
+
selector: z29.string(),
|
|
6263
|
+
action: z29.string().optional()
|
|
6189
6264
|
}),
|
|
6190
6265
|
handler: async (p, ctx) => {
|
|
6191
6266
|
const page = ctx.page;
|
|
@@ -6200,7 +6275,7 @@ var findCommand = registerCommand({
|
|
|
6200
6275
|
});
|
|
6201
6276
|
const count = await locator.count();
|
|
6202
6277
|
if (count === 0) {
|
|
6203
|
-
return
|
|
6278
|
+
return fail13(`No element found with ${p.strategy}="${p.value}"`);
|
|
6204
6279
|
}
|
|
6205
6280
|
const tips = [];
|
|
6206
6281
|
const target = selectTarget(locator, p.strategy);
|
|
@@ -6212,15 +6287,15 @@ var findCommand = registerCommand({
|
|
|
6212
6287
|
await target.click({ timeout: p.timeout, force: true });
|
|
6213
6288
|
return okWithTips({ matched: count, selector, action: "click" }, tips);
|
|
6214
6289
|
} else if (actionName === "fill") {
|
|
6215
|
-
if (actionValue === void 0) return
|
|
6290
|
+
if (actionValue === void 0) return fail13("find fill requires a value");
|
|
6216
6291
|
await target.fill(actionValue, { timeout: p.timeout, force: true });
|
|
6217
6292
|
return okWithTips({ matched: count, selector, action: `fill("${actionValue}")` }, tips);
|
|
6218
6293
|
} else if (actionName === "type") {
|
|
6219
|
-
if (actionValue === void 0) return
|
|
6294
|
+
if (actionValue === void 0) return fail13("find type requires a value");
|
|
6220
6295
|
await target.type(actionValue, { delay: 10, timeout: p.timeout });
|
|
6221
6296
|
return okWithTips({ matched: count, selector, action: `type("${actionValue}")` }, tips);
|
|
6222
6297
|
} else if (actionName === "select") {
|
|
6223
|
-
if (actionValue === void 0) return
|
|
6298
|
+
if (actionValue === void 0) return fail13("find select requires a value");
|
|
6224
6299
|
await target.selectOption(actionValue);
|
|
6225
6300
|
return okWithTips({ matched: count, selector, action: `select("${actionValue}")` }, tips);
|
|
6226
6301
|
} else if (actionName === "hover") {
|
|
@@ -6234,7 +6309,7 @@ var findCommand = registerCommand({
|
|
|
6234
6309
|
}
|
|
6235
6310
|
});
|
|
6236
6311
|
function okWithTips(data, tips) {
|
|
6237
|
-
const result =
|
|
6312
|
+
const result = ok28(data);
|
|
6238
6313
|
if (tips.length > 0) result.tips = normalizeTips5(tips);
|
|
6239
6314
|
return result;
|
|
6240
6315
|
}
|
|
@@ -6333,8 +6408,8 @@ function describeSelector(strategy, value, name) {
|
|
|
6333
6408
|
}
|
|
6334
6409
|
|
|
6335
6410
|
// src/commands/visual-tag.ts
|
|
6336
|
-
import { z as
|
|
6337
|
-
import { ok as
|
|
6411
|
+
import { z as z30 } from "zod";
|
|
6412
|
+
import { ok as ok29, fail as fail14 } from "@dyyz1993/xcli-core";
|
|
6338
6413
|
var SAFE_SET = "ahjkmnprtw3479".split("");
|
|
6339
6414
|
var TAG_SCRIPT = `
|
|
6340
6415
|
(function() {
|
|
@@ -6425,49 +6500,49 @@ var visualTagCommand = registerCommand({
|
|
|
6425
6500
|
name: "visual-tag",
|
|
6426
6501
|
description: "\u5728\u9875\u9762\u4E0A\u7ED9\u53EF\u4EA4\u4E92\u5143\u7D20\u53E0\u52A0\u9632\u6DF7\u6DC6\u77ED ID \u6807\u7B7E\uFF08\u89C6\u89C9\u5B9A\u4F4D\u7528\uFF09",
|
|
6427
6502
|
scope: "page",
|
|
6428
|
-
parameters:
|
|
6429
|
-
action:
|
|
6430
|
-
id:
|
|
6503
|
+
parameters: z30.object({
|
|
6504
|
+
action: z30.enum(["tag", "lookup", "clear", "list"]),
|
|
6505
|
+
id: z30.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID")
|
|
6431
6506
|
}),
|
|
6432
|
-
result:
|
|
6433
|
-
action:
|
|
6434
|
-
tagged:
|
|
6435
|
-
id:
|
|
6436
|
-
element:
|
|
6507
|
+
result: z30.object({
|
|
6508
|
+
action: z30.string(),
|
|
6509
|
+
tagged: z30.number().optional(),
|
|
6510
|
+
id: z30.string().optional(),
|
|
6511
|
+
element: z30.record(z30.unknown()).optional()
|
|
6437
6512
|
}),
|
|
6438
6513
|
handler: async (p, ctx) => {
|
|
6439
6514
|
switch (p.action) {
|
|
6440
6515
|
case "tag": {
|
|
6441
6516
|
const result = await ctx.page.evaluate(TAG_SCRIPT);
|
|
6442
6517
|
const parsed = JSON.parse(result);
|
|
6443
|
-
return
|
|
6518
|
+
return ok29({ action: "tag", tagged: parsed.tagged });
|
|
6444
6519
|
}
|
|
6445
6520
|
case "lookup": {
|
|
6446
|
-
if (!p.id) return
|
|
6521
|
+
if (!p.id) return fail14("lookup \u9700\u8981 --id \u53C2\u6570");
|
|
6447
6522
|
const result = await ctx.page.evaluate(
|
|
6448
6523
|
`(function() { var m = window.__xbTagMap; if (!m) return JSON.stringify({err:'no-map'}); var e = m[${JSON.stringify(p.id)}]; return e ? JSON.stringify(e) : JSON.stringify({err:'not-found'}); })()`
|
|
6449
6524
|
);
|
|
6450
6525
|
const parsed = JSON.parse(result);
|
|
6451
|
-
if (parsed.err) return
|
|
6452
|
-
return
|
|
6526
|
+
if (parsed.err) return fail14(`ID ${p.id}: ${parsed.err}`);
|
|
6527
|
+
return ok29({ action: "lookup", id: p.id, element: parsed });
|
|
6453
6528
|
}
|
|
6454
6529
|
case "list": {
|
|
6455
6530
|
const result = await ctx.page.evaluate(
|
|
6456
6531
|
`(function() { var m = window.__xbTagMap; if (!m) return '{}'; var out = {}; for (var k in m) { out[k] = m[k].text || m[k].tagName; } return JSON.stringify(out); })()`
|
|
6457
6532
|
);
|
|
6458
|
-
return
|
|
6533
|
+
return ok29({ action: "list", element: JSON.parse(result) });
|
|
6459
6534
|
}
|
|
6460
6535
|
case "clear": {
|
|
6461
6536
|
await ctx.page.evaluate(`(function(){var o=document.getElementById('__xb-tag-overlay');if(o)o.remove();window.__xbTagMap=null;return 'cleared'})()`);
|
|
6462
|
-
return
|
|
6537
|
+
return ok29({ action: "clear" });
|
|
6463
6538
|
}
|
|
6464
6539
|
}
|
|
6465
6540
|
}
|
|
6466
6541
|
});
|
|
6467
6542
|
|
|
6468
6543
|
// src/commands/visual-tag-v2.ts
|
|
6469
|
-
import { z as
|
|
6470
|
-
import { ok as
|
|
6544
|
+
import { z as z31 } from "zod";
|
|
6545
|
+
import { ok as ok30, fail as fail15 } from "@dyyz1993/xcli-core";
|
|
6471
6546
|
var SAFE_SET2 = "ahjkmnprtw3479".split("");
|
|
6472
6547
|
var TAG_V2_SCRIPT = `
|
|
6473
6548
|
(function() {
|
|
@@ -6814,45 +6889,45 @@ var visualTagV2Command = registerCommand({
|
|
|
6814
6889
|
name: "visual-tag-v2",
|
|
6815
6890
|
description: "\u5206\u8272\u6807\u6CE8\u9875\u9762\u5143\u7D20\uFF08\u7EA2=\u53EF\u70B9\u51FB \u84DD=\u8F93\u5165 \u7EFF=\u56FE\u7247 \u9EC4=\u5217\u8868 \u7D2B=\u6570\u5B57 \u6A59=\u6587\u672C\uFF09",
|
|
6816
6891
|
scope: "page",
|
|
6817
|
-
parameters:
|
|
6818
|
-
action:
|
|
6819
|
-
id:
|
|
6820
|
-
query:
|
|
6821
|
-
type:
|
|
6822
|
-
"interact-action":
|
|
6823
|
-
value:
|
|
6892
|
+
parameters: z31.object({
|
|
6893
|
+
action: z31.enum(["tag", "lookup", "clear", "stats", "by-type", "find", "export", "interact"]),
|
|
6894
|
+
id: z31.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID"),
|
|
6895
|
+
query: z31.string().optional().describe('find \u65F6\u6307\u5B9A\u641C\u7D22\u8BCD\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09'),
|
|
6896
|
+
type: z31.string().optional().describe("by-type \u65F6\u8FC7\u6EE4\u7C7B\u578B\uFF1Aclick/input/img/list/count/text"),
|
|
6897
|
+
"interact-action": z31.enum(["click", "fill", "read"]).optional().describe("interact \u52A8\u4F5C\u7C7B\u578B"),
|
|
6898
|
+
value: z31.string().optional().describe("fill \u65F6\u7684\u586B\u5145\u503C")
|
|
6824
6899
|
}),
|
|
6825
|
-
result:
|
|
6826
|
-
action:
|
|
6827
|
-
total:
|
|
6828
|
-
byType:
|
|
6829
|
-
element:
|
|
6900
|
+
result: z31.object({
|
|
6901
|
+
action: z31.string(),
|
|
6902
|
+
total: z31.number().optional(),
|
|
6903
|
+
byType: z31.record(z31.number()).optional(),
|
|
6904
|
+
element: z31.record(z31.unknown()).optional()
|
|
6830
6905
|
}),
|
|
6831
6906
|
handler: async (p, ctx) => {
|
|
6832
6907
|
switch (p.action) {
|
|
6833
6908
|
case "tag": {
|
|
6834
6909
|
const result = await ctx.page.evaluate(TAG_V2_SCRIPT);
|
|
6835
6910
|
const parsed = JSON.parse(result);
|
|
6836
|
-
return
|
|
6911
|
+
return ok30({ action: "tag", total: parsed.total, byType: parsed.byType });
|
|
6837
6912
|
}
|
|
6838
6913
|
case "lookup": {
|
|
6839
|
-
if (!p.id) return
|
|
6914
|
+
if (!p.id) return fail15("lookup \u9700\u8981 --id");
|
|
6840
6915
|
const result = await ctx.page.evaluate(
|
|
6841
6916
|
`(function(){var m=window.__xbTagMap;if(!m)return JSON.stringify({err:'no-map'});var e=m[${JSON.stringify(p.id)}];return e?JSON.stringify(e):JSON.stringify({err:'not-found'})})()`
|
|
6842
6917
|
);
|
|
6843
6918
|
const parsed = JSON.parse(result);
|
|
6844
|
-
if (parsed.err) return
|
|
6845
|
-
return
|
|
6919
|
+
if (parsed.err) return fail15(`ID ${p.id}: ${parsed.err}`);
|
|
6920
|
+
return ok30({ action: "lookup", id: p.id, element: parsed });
|
|
6846
6921
|
}
|
|
6847
6922
|
case "by-type": {
|
|
6848
6923
|
const result = await ctx.page.evaluate(
|
|
6849
6924
|
`(function(){var m=window.__xbTagMap;if(!m)return'{}';var out={};for(var k in m){if(!${JSON.stringify(p.type || "")}||m[k].type===${JSON.stringify(p.type || "")}){out[k]={type:m[k].type,text:m[k].text,num:m[k].num,label:m[k].formLabel}}}return JSON.stringify(out)})()`
|
|
6850
6925
|
);
|
|
6851
|
-
return
|
|
6926
|
+
return ok30({ action: "by-type", element: JSON.parse(result) });
|
|
6852
6927
|
}
|
|
6853
6928
|
case "find": {
|
|
6854
6929
|
const query = p.query;
|
|
6855
|
-
if (!query) return
|
|
6930
|
+
if (!query) return fail15('find \u9700\u8981 --query \u53C2\u6570\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09');
|
|
6856
6931
|
const result = await ctx.page.evaluate(
|
|
6857
6932
|
`(function(){
|
|
6858
6933
|
var map = window.__xbTagSerializable;
|
|
@@ -6894,21 +6969,21 @@ var visualTagV2Command = registerCommand({
|
|
|
6894
6969
|
return JSON.stringify({total:results.length, results:results.slice(0,20)});
|
|
6895
6970
|
})()`
|
|
6896
6971
|
);
|
|
6897
|
-
return
|
|
6972
|
+
return ok30({ action: "find", query, element: JSON.parse(result) });
|
|
6898
6973
|
}
|
|
6899
6974
|
case "stats": {
|
|
6900
6975
|
const result = await ctx.page.evaluate(
|
|
6901
6976
|
`(function(){return JSON.stringify(window.__xbTagStats||{})})()`
|
|
6902
6977
|
);
|
|
6903
|
-
return
|
|
6978
|
+
return ok30({ action: "stats", element: JSON.parse(result) });
|
|
6904
6979
|
}
|
|
6905
6980
|
case "interact": {
|
|
6906
6981
|
const query = p.query;
|
|
6907
6982
|
const pAny = p;
|
|
6908
6983
|
const action = pAny["interact-action"] || pAny.interactAction || pAny.interact_action;
|
|
6909
6984
|
const value = pAny.value;
|
|
6910
|
-
if (!query) return
|
|
6911
|
-
if (!action) return
|
|
6985
|
+
if (!query) return fail15("interact \u9700\u8981 --query \u53C2\u6570");
|
|
6986
|
+
if (!action) return fail15("interact \u9700\u8981 --interact-action \u53C2\u6570\uFF08click/fill/read\uFF09");
|
|
6912
6987
|
const findResult = await ctx.page.evaluate(
|
|
6913
6988
|
`(function(){
|
|
6914
6989
|
var map = window.__xbTagSerializable;
|
|
@@ -6938,11 +7013,11 @@ var visualTagV2Command = registerCommand({
|
|
|
6938
7013
|
})()`
|
|
6939
7014
|
);
|
|
6940
7015
|
const parsed = JSON.parse(findResult);
|
|
6941
|
-
if (parsed.err) return
|
|
6942
|
-
if (!parsed.total || !parsed.results?.length) return
|
|
7016
|
+
if (parsed.err) return fail15(parsed.err);
|
|
7017
|
+
if (!parsed.total || !parsed.results?.length) return fail15(`\u672A\u627E\u5230\u5339\u914D "${query}" \u7684\u5143\u7D20`);
|
|
6943
7018
|
const target = parsed.results[0];
|
|
6944
7019
|
if (action === "read") {
|
|
6945
|
-
return
|
|
7020
|
+
return ok30({ action: "interact", query, target, result: { read: target.text || target.label } });
|
|
6946
7021
|
}
|
|
6947
7022
|
if (action === "click") {
|
|
6948
7023
|
const el = await ctx.page.evaluate(
|
|
@@ -6955,12 +7030,12 @@ var visualTagV2Command = registerCommand({
|
|
|
6955
7030
|
return {x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)};
|
|
6956
7031
|
})()`
|
|
6957
7032
|
);
|
|
6958
|
-
if (!el) return
|
|
7033
|
+
if (!el) return fail15(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
|
|
6959
7034
|
await ctx.page.mouse.click(el.x, el.y, { stealth: true });
|
|
6960
|
-
return
|
|
7035
|
+
return ok30({ action: "interact", query, target, result: { clicked: true, x: el.x, y: el.y } });
|
|
6961
7036
|
}
|
|
6962
7037
|
if (action === "fill") {
|
|
6963
|
-
if (!value) return
|
|
7038
|
+
if (!value) return fail15("fill \u9700\u8981 --value \u53C2\u6570");
|
|
6964
7039
|
const el = await ctx.page.evaluate(
|
|
6965
7040
|
`(function(){
|
|
6966
7041
|
var map = window.__xbTagMap;
|
|
@@ -6971,12 +7046,12 @@ var visualTagV2Command = registerCommand({
|
|
|
6971
7046
|
return {x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)};
|
|
6972
7047
|
})()`
|
|
6973
7048
|
);
|
|
6974
|
-
if (!el) return
|
|
7049
|
+
if (!el) return fail15(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
|
|
6975
7050
|
await ctx.page.mouse.click(el.x, el.y, { stealth: true });
|
|
6976
7051
|
await ctx.page.keyboard.type(value, { stealth: true });
|
|
6977
|
-
return
|
|
7052
|
+
return ok30({ action: "interact", query, target, result: { filled: true, value } });
|
|
6978
7053
|
}
|
|
6979
|
-
return
|
|
7054
|
+
return fail15(`\u672A\u77E5 action: ${action}`);
|
|
6980
7055
|
}
|
|
6981
7056
|
case "export": {
|
|
6982
7057
|
const result = await ctx.page.evaluate(
|
|
@@ -7024,12 +7099,12 @@ var visualTagV2Command = registerCommand({
|
|
|
7024
7099
|
})()`
|
|
7025
7100
|
);
|
|
7026
7101
|
const parsed = JSON.parse(result);
|
|
7027
|
-
if (parsed.err) return
|
|
7028
|
-
return
|
|
7102
|
+
if (parsed.err) return fail15(String(parsed.err));
|
|
7103
|
+
return ok30({ action: "export", element: parsed });
|
|
7029
7104
|
}
|
|
7030
7105
|
case "clear": {
|
|
7031
7106
|
await ctx.page.evaluate(`(function(){var o=document.getElementById('__xb-tag-overlay');if(o)o.remove();window.__xbTagMap=null;window.__xbTagStats=null;return 'ok'})()`);
|
|
7032
|
-
return
|
|
7107
|
+
return ok30({ action: "clear" });
|
|
7033
7108
|
}
|
|
7034
7109
|
}
|
|
7035
7110
|
}
|
|
@@ -8167,7 +8242,7 @@ async function guardCheck(commandName) {
|
|
|
8167
8242
|
}
|
|
8168
8243
|
}
|
|
8169
8244
|
function errorResult(message) {
|
|
8170
|
-
return { ...
|
|
8245
|
+
return { ...fail16(message), duration: 0 };
|
|
8171
8246
|
}
|
|
8172
8247
|
function tipsToMessages(tips) {
|
|
8173
8248
|
if (!tips || tips.length === 0) return [];
|
|
@@ -8244,7 +8319,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
8244
8319
|
}
|
|
8245
8320
|
let targetPageOverride = null;
|
|
8246
8321
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
8247
|
-
const { findTargetPage } = await import("./browser-
|
|
8322
|
+
const { findTargetPage } = await import("./browser-FIEYZRSV.js");
|
|
8248
8323
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
8249
8324
|
if (!targetPageOverride) {
|
|
8250
8325
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -8440,7 +8515,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
8440
8515
|
timestamp: start
|
|
8441
8516
|
});
|
|
8442
8517
|
if (isSuccess) {
|
|
8443
|
-
return { ...
|
|
8518
|
+
return { ...ok31(raw.data, merged.length > 0 ? merged : raw.tips), duration, ...hookOutputs ? { hookOutputs } : {} };
|
|
8444
8519
|
}
|
|
8445
8520
|
const fc = classifyFailure(raw.message);
|
|
8446
8521
|
return {
|
|
@@ -8463,7 +8538,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
8463
8538
|
duration,
|
|
8464
8539
|
timestamp: start
|
|
8465
8540
|
});
|
|
8466
|
-
return { ...
|
|
8541
|
+
return { ...ok31(raw, smartTipNormalized), duration, ...hookOutputs ? { hookOutputs } : {} };
|
|
8467
8542
|
} catch (err) {
|
|
8468
8543
|
const end = Date.now();
|
|
8469
8544
|
const duration = end - start;
|
|
@@ -8508,7 +8583,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
8508
8583
|
duration,
|
|
8509
8584
|
timestamp: start
|
|
8510
8585
|
});
|
|
8511
|
-
return { ...
|
|
8586
|
+
return { ...fail16(errorMessage), duration };
|
|
8512
8587
|
} finally {
|
|
8513
8588
|
}
|
|
8514
8589
|
}
|
|
@@ -8553,7 +8628,7 @@ async function executeChain(input, options) {
|
|
|
8553
8628
|
results.push({
|
|
8554
8629
|
command: cmdName,
|
|
8555
8630
|
raw: cmdStr,
|
|
8556
|
-
...
|
|
8631
|
+
...fail16(`Plugin "${cmdName}" requires a sub-command`),
|
|
8557
8632
|
duration: 0
|
|
8558
8633
|
});
|
|
8559
8634
|
if (type === "and") {
|
|
@@ -8572,7 +8647,7 @@ async function executeChain(input, options) {
|
|
|
8572
8647
|
results.push({
|
|
8573
8648
|
command: cmdName,
|
|
8574
8649
|
raw: cmdStr,
|
|
8575
|
-
...
|
|
8650
|
+
...fail16(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
|
|
8576
8651
|
duration: 0
|
|
8577
8652
|
});
|
|
8578
8653
|
if (type === "and") {
|
|
@@ -8684,7 +8759,7 @@ async function executeChain(input, options) {
|
|
|
8684
8759
|
results.push({
|
|
8685
8760
|
command: `${cmdName} ${subCommand}`,
|
|
8686
8761
|
raw: cmdStr,
|
|
8687
|
-
...
|
|
8762
|
+
...ok31(data),
|
|
8688
8763
|
duration: duration2,
|
|
8689
8764
|
...hookOutputs ? { hookOutputs } : {}
|
|
8690
8765
|
});
|
|
@@ -8712,7 +8787,7 @@ async function executeChain(input, options) {
|
|
|
8712
8787
|
results.push({
|
|
8713
8788
|
command: `${cmdName} ${subCommand}`,
|
|
8714
8789
|
raw: cmdStr,
|
|
8715
|
-
...
|
|
8790
|
+
...fail16(errorMessage),
|
|
8716
8791
|
duration: duration2
|
|
8717
8792
|
});
|
|
8718
8793
|
if (type === "and") {
|
|
@@ -8792,6 +8867,7 @@ export {
|
|
|
8792
8867
|
createStubContext,
|
|
8793
8868
|
getCommand,
|
|
8794
8869
|
getAllCommands,
|
|
8870
|
+
getCommandNames,
|
|
8795
8871
|
attachDetectAntiBot,
|
|
8796
8872
|
readJsonFile,
|
|
8797
8873
|
PluginMetadataParser,
|