@xbrowser/cli 1.24.2 → 1.25.0

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