@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.
@@ -102,8 +102,8 @@ function classifyFailure(message) {
102
102
 
103
103
  // src/executor.ts
104
104
  import {
105
- ok as ok30,
106
- fail as fail15,
105
+ ok as ok31,
106
+ fail as fail16,
107
107
  isCommandResult,
108
108
  CompositeStorage as CompositeStorage2,
109
109
  TipCollector as TipCollector2,
@@ -1449,37 +1449,109 @@ var uaCommand = registerCommand({
1449
1449
  }
1450
1450
  });
1451
1451
 
1452
- // src/commands/storage.ts
1452
+ // src/commands/preflight.ts
1453
1453
  import { z as z11 } from "zod";
1454
1454
  import { ok as ok11, fail as fail4 } from "@dyyz1993/xcli-core";
1455
+ var preflightCommand = registerCommand({
1456
+ name: "preflight",
1457
+ description: "Pre-flight anti-bot gate: open local detection page and verify stealth posture before any automation task",
1458
+ scope: "page",
1459
+ parameters: z11.object({
1460
+ strict: z11.boolean().optional().describe("\u5931\u8D25\u65F6\u4EE5\u975E\u96F6\u9000\u51FA\u7801\u7ED3\u675F\uFF08\u94FE\u5F0F/CI \u95E8\u7981\u7528\uFF09"),
1461
+ 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")
1462
+ }),
1463
+ result: z11.object({
1464
+ gate: z11.enum(["pass", "fail"]),
1465
+ failed: z11.array(z11.string()),
1466
+ headless: z11.boolean()
1467
+ }),
1468
+ handler: async (p, ctx) => {
1469
+ const page = ctx.page;
1470
+ const tips = [];
1471
+ const ua = await page.evaluate("navigator.userAgent").catch(() => "");
1472
+ const outerW = await page.evaluate("window.outerWidth").catch(() => 0);
1473
+ const headless = /headless/i.test(ua) || outerW === 0;
1474
+ const publishMode = p.publish || process.env.XBROWSER_NO_HEADLESS_PUBLISH === "1";
1475
+ if (publishMode && headless) {
1476
+ 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");
1477
+ tips.push(' \u6709\u5934 Chrome: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --user-data-dir=~/.xbrowser/chrome-profile-headed --remote-debugging-port=9222');
1478
+ tips.push(" \u7136\u540E\u52A0 --cdp http://localhost:9222");
1479
+ return fail4("PREFLIGHT-FAIL: headless \u4E0D\u5141\u8BB8\u7528\u4E8E\u53D1\u5E03\u7C7B\u4EFB\u52A1\uFF08\u7528 --cdp \u63A5\u6709\u5934 Chrome\uFF09", tips);
1480
+ }
1481
+ let pageUrl = null;
1482
+ try {
1483
+ const { fileURLToPath } = await import("url");
1484
+ const { join: join10, dirname: dirname3 } = await import("path");
1485
+ const { existsSync: existsSync4 } = await import("fs");
1486
+ const here = typeof __filename !== "undefined" ? __filename : fileURLToPath(import.meta.url);
1487
+ const candidates = [
1488
+ join10(dirname3(here), "..", "assets", "preflight.html"),
1489
+ join10(process.cwd(), "assets", "preflight.html")
1490
+ ];
1491
+ pageUrl = candidates.find((c) => existsSync4(c)) || null;
1492
+ } catch {
1493
+ }
1494
+ if (pageUrl) {
1495
+ await page.goto("file://" + pageUrl, { waitUntil: "domcontentloaded", timeout: 15e3 });
1496
+ } else {
1497
+ await page.goto("about:blank");
1498
+ await page.evaluate(`(function(){
1499
+ var fails=[];
1500
+ if(navigator.webdriver!==false)fails.push('webdriver');
1501
+ if(/headless/i.test(navigator.userAgent))fails.push('ua-no-headless');
1502
+ window.__pf=fails.join(',');
1503
+ document.title=fails.length?'PREFLIGHT-FAIL':'PREFLIGHT-PASS';
1504
+ })()`);
1505
+ }
1506
+ await page.waitForTimeout(1200);
1507
+ const result = await page.evaluate(`(function(){
1508
+ var out=document.getElementById('out');
1509
+ return { title: document.title, fails: out ? (out.getAttribute('data-fails')||'') : (window.__pf||'') };
1510
+ })()`).catch(() => ({ title: "PREFLIGHT-FAIL", fails: "evaluate-error" }));
1511
+ const passed = result.title === "PREFLIGHT-PASS";
1512
+ const failed = result.fails ? result.fails.split(",").filter(Boolean) : [];
1513
+ tips.push(`headless=${headless}${publishMode ? "\uFF08publish \u95E8\u7981\u5F00\u542F\uFF09" : ""}`);
1514
+ if (passed) {
1515
+ 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");
1516
+ return ok11({ gate: "pass", failed: [], headless }, tips);
1517
+ }
1518
+ tips.push(`\u5931\u8D25\u9879: ${failed.join(", ") || result.title}`);
1519
+ 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");
1520
+ return fail4(`PREFLIGHT-FAIL: ${failed.join(", ") || result.title}`, tips);
1521
+ }
1522
+ });
1523
+
1524
+ // src/commands/storage.ts
1525
+ import { z as z12 } from "zod";
1526
+ import { ok as ok12, fail as fail5 } from "@dyyz1993/xcli-core";
1455
1527
  var getCookiesCommand = registerCommand({
1456
1528
  name: "get-cookies",
1457
1529
  description: "Get all cookies for the current page",
1458
1530
  scope: "page",
1459
- result: z11.object({
1460
- cookies: z11.array(z11.record(z11.unknown()))
1531
+ result: z12.object({
1532
+ cookies: z12.array(z12.record(z12.unknown()))
1461
1533
  }),
1462
1534
  handler: async (_p, ctx) => {
1463
1535
  const cookies = await ctx.browserContext.cookies();
1464
- return ok11({ cookies });
1536
+ return ok12({ cookies });
1465
1537
  }
1466
1538
  });
1467
1539
  var setCookieCommand = registerCommand({
1468
1540
  name: "set-cookie",
1469
1541
  description: "Set a cookie",
1470
1542
  scope: "page",
1471
- parameters: z11.object({
1472
- name: z11.coerce.string(),
1473
- value: z11.coerce.string(),
1474
- domain: z11.coerce.string().optional(),
1475
- path: z11.coerce.string().optional(),
1476
- url: z11.string().optional().describe("Cookie URL (alternative to domain)"),
1477
- expires: z11.number().optional(),
1478
- httpOnly: z11.boolean().optional(),
1479
- secure: z11.boolean().optional(),
1480
- sameSite: z11.enum(["Strict", "Lax", "None"]).optional()
1543
+ parameters: z12.object({
1544
+ name: z12.coerce.string(),
1545
+ value: z12.coerce.string(),
1546
+ domain: z12.coerce.string().optional(),
1547
+ path: z12.coerce.string().optional(),
1548
+ url: z12.string().optional().describe("Cookie URL (alternative to domain)"),
1549
+ expires: z12.number().optional(),
1550
+ httpOnly: z12.boolean().optional(),
1551
+ secure: z12.boolean().optional(),
1552
+ sameSite: z12.enum(["Strict", "Lax", "None"]).optional()
1481
1553
  }),
1482
- result: z11.object({ name: z11.string() }),
1554
+ result: z12.object({ name: z12.string() }),
1483
1555
  handler: async (p, ctx) => {
1484
1556
  const cookie = { ...p };
1485
1557
  if (!cookie.domain && !cookie.url) {
@@ -1494,38 +1566,38 @@ var setCookieCommand = registerCommand({
1494
1566
  }
1495
1567
  }
1496
1568
  if (!cookie.domain && !cookie.url) {
1497
- return fail4("set-cookie requires --domain or --url, or a non-blank page URL to infer from");
1569
+ return fail5("set-cookie requires --domain or --url, or a non-blank page URL to infer from");
1498
1570
  }
1499
1571
  await ctx.browserContext.addCookies([cookie]);
1500
- return ok11({ name: p.name });
1572
+ return ok12({ name: p.name });
1501
1573
  }
1502
1574
  });
1503
1575
  var clearCookiesCommand = registerCommand({
1504
1576
  name: "clear-cookies",
1505
1577
  description: "Clear all cookies",
1506
1578
  scope: "page",
1507
- result: z11.object({ cleared: z11.boolean() }),
1579
+ result: z12.object({ cleared: z12.boolean() }),
1508
1580
  handler: async (_p, ctx) => {
1509
1581
  await ctx.browserContext.clearCookies();
1510
- return ok11({ cleared: true });
1582
+ return ok12({ cleared: true });
1511
1583
  }
1512
1584
  });
1513
1585
  var getLocalStorageCommand = registerCommand({
1514
1586
  name: "get-local-storage",
1515
1587
  description: "Get localStorage entries",
1516
1588
  scope: "page",
1517
- parameters: z11.object({
1518
- key: z11.string().optional()
1589
+ parameters: z12.object({
1590
+ key: z12.string().optional()
1519
1591
  }),
1520
- result: z11.union([
1521
- z11.object({ key: z11.string(), value: z11.string().nullable() }),
1522
- z11.object({ data: z11.record(z11.string()) })
1592
+ result: z12.union([
1593
+ z12.object({ key: z12.string(), value: z12.string().nullable() }),
1594
+ z12.object({ data: z12.record(z12.string()) })
1523
1595
  ]),
1524
1596
  handler: async (p, ctx) => {
1525
1597
  try {
1526
1598
  if (p.key) {
1527
1599
  const value = await ctx.page.evaluate((k) => localStorage.getItem(k), p.key);
1528
- return ok11({ key: p.key, value });
1600
+ return ok12({ key: p.key, value });
1529
1601
  }
1530
1602
  const data = await ctx.page.evaluate(() => {
1531
1603
  const entries = {};
@@ -1535,9 +1607,9 @@ var getLocalStorageCommand = registerCommand({
1535
1607
  }
1536
1608
  return entries;
1537
1609
  });
1538
- return ok11({ data });
1610
+ return ok12({ data });
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,11 +1617,11 @@ var setLocalStorageCommand = registerCommand({
1545
1617
  name: "set-local-storage",
1546
1618
  description: "Set a localStorage entry",
1547
1619
  scope: "page",
1548
- parameters: z11.object({
1549
- key: z11.string(),
1550
- value: z11.string()
1620
+ parameters: z12.object({
1621
+ key: z12.string(),
1622
+ value: z12.string()
1551
1623
  }),
1552
- result: z11.object({ key: z11.string() }),
1624
+ result: z12.object({ key: z12.string() }),
1553
1625
  handler: async (p, ctx) => {
1554
1626
  try {
1555
1627
  await ctx.page.evaluate(
@@ -1558,9 +1630,9 @@ var setLocalStorageCommand = registerCommand({
1558
1630
  },
1559
1631
  { key: p.key, value: p.value }
1560
1632
  );
1561
- return ok11({ key: p.key });
1633
+ return ok12({ key: p.key });
1562
1634
  } catch (e) {
1563
- return fail4(`localStorage not accessible on this page: ${e instanceof Error ? e.message : String(e)}`);
1635
+ return fail5(`localStorage not accessible on this page: ${e instanceof Error ? e.message : String(e)}`);
1564
1636
  }
1565
1637
  }
1566
1638
  });
@@ -1568,20 +1640,20 @@ var clearLocalStorageCommand = registerCommand({
1568
1640
  name: "clear-local-storage",
1569
1641
  description: "Clear all localStorage entries",
1570
1642
  scope: "page",
1571
- result: z11.object({ cleared: z11.boolean() }),
1643
+ result: z12.object({ cleared: z12.boolean() }),
1572
1644
  handler: async (_p, ctx) => {
1573
1645
  try {
1574
1646
  await ctx.page.evaluate(() => localStorage.clear());
1575
- return ok11({ cleared: true });
1647
+ return ok12({ cleared: true });
1576
1648
  } catch (e) {
1577
- return fail4(`localStorage not accessible on this page: ${e instanceof Error ? e.message : String(e)}`);
1649
+ return fail5(`localStorage not accessible on this page: ${e instanceof Error ? e.message : String(e)}`);
1578
1650
  }
1579
1651
  }
1580
1652
  });
1581
1653
 
1582
1654
  // src/commands/screenshot.ts
1583
- import { z as z12 } from "zod";
1584
- import { ok as ok12, fail as fail5 } from "@dyyz1993/xcli-core";
1655
+ import { z as z13 } from "zod";
1656
+ import { ok as ok13, fail as fail6 } from "@dyyz1993/xcli-core";
1585
1657
  import { writeFileSync, mkdirSync } from "fs";
1586
1658
  import { dirname, join as join4 } from "path";
1587
1659
  function ensureScreenshotsDir() {
@@ -1608,23 +1680,23 @@ var screenshotCommand = registerCommand({
1608
1680
  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>)",
1609
1681
  scope: "page",
1610
1682
  selectorParams: ["selector"],
1611
- parameters: z12.object({
1612
- selector: z12.string().optional(),
1613
- type: z12.enum(["png", "jpeg"]).optional(),
1614
- fullPage: z12.boolean().optional(),
1615
- output: z12.string().optional(),
1616
- base64: z12.boolean().optional().describe("Return base64 data instead of file path")
1683
+ parameters: z13.object({
1684
+ selector: z13.string().optional(),
1685
+ type: z13.enum(["png", "jpeg"]).optional(),
1686
+ fullPage: z13.boolean().optional(),
1687
+ output: z13.string().optional(),
1688
+ base64: z13.boolean().optional().describe("Return base64 data instead of file path")
1617
1689
  }),
1618
- result: z12.union([
1619
- z12.object({
1620
- data: z12.string(),
1621
- format: z12.string(),
1622
- size: z12.number()
1690
+ result: z13.union([
1691
+ z13.object({
1692
+ data: z13.string(),
1693
+ format: z13.string(),
1694
+ size: z13.number()
1623
1695
  }),
1624
- z12.object({
1625
- output: z12.string(),
1626
- format: z12.string(),
1627
- size: z12.number()
1696
+ z13.object({
1697
+ output: z13.string(),
1698
+ format: z13.string(),
1699
+ size: z13.number()
1628
1700
  })
1629
1701
  ]),
1630
1702
  handler: async (p, ctx) => {
@@ -1642,21 +1714,21 @@ var screenshotCommand = registerCommand({
1642
1714
  if (p.output) {
1643
1715
  const dirErr = ensureParentDir(p.output);
1644
1716
  if (dirErr) {
1645
- return fail5(`Cannot create directory for --output "${p.output}": ${dirErr}`);
1717
+ return fail6(`Cannot create directory for --output "${p.output}": ${dirErr}`);
1646
1718
  }
1647
1719
  try {
1648
1720
  writeFileSync(p.output, buffer, "binary");
1649
1721
  } catch (err) {
1650
- return fail5(`Failed to write screenshot to "${p.output}": ${err instanceof Error ? err.message : String(err)}`);
1722
+ return fail6(`Failed to write screenshot to "${p.output}": ${err instanceof Error ? err.message : String(err)}`);
1651
1723
  }
1652
- return ok12({
1724
+ return ok13({
1653
1725
  output: p.output,
1654
1726
  format,
1655
1727
  size: buffer.length
1656
1728
  });
1657
1729
  }
1658
1730
  if (p.base64) {
1659
- return ok12({
1731
+ return ok13({
1660
1732
  data: buffer.toString("base64"),
1661
1733
  format,
1662
1734
  size: buffer.length
@@ -1665,7 +1737,7 @@ var screenshotCommand = registerCommand({
1665
1737
  ensureScreenshotsDir();
1666
1738
  const screenshotPath = generateScreenshotPath(format);
1667
1739
  writeFileSync(screenshotPath, buffer, "binary");
1668
- return ok12({
1740
+ return ok13({
1669
1741
  output: screenshotPath,
1670
1742
  format,
1671
1743
  size: buffer.length
@@ -1674,19 +1746,19 @@ var screenshotCommand = registerCommand({
1674
1746
  });
1675
1747
 
1676
1748
  // src/commands/structure.ts
1677
- import { z as z13 } from "zod";
1678
- import { ok as ok13 } from "@dyyz1993/xcli-core";
1749
+ import { z as z14 } from "zod";
1750
+ import { ok as ok14 } from "@dyyz1993/xcli-core";
1679
1751
  var structureCommand = registerCommand({
1680
1752
  name: "structure",
1681
1753
  description: "Get the DOM structure of the page or an element",
1682
1754
  scope: "page",
1683
1755
  selectorParams: ["selector"],
1684
- parameters: z13.object({
1685
- selector: z13.string().optional(),
1686
- depth: z13.number().optional()
1756
+ parameters: z14.object({
1757
+ selector: z14.string().optional(),
1758
+ depth: z14.number().optional()
1687
1759
  }),
1688
- result: z13.object({
1689
- structure: z13.record(z13.unknown())
1760
+ result: z14.object({
1761
+ structure: z14.record(z14.unknown())
1690
1762
  }),
1691
1763
  handler: async (p, ctx) => {
1692
1764
  const structure = await ctx.page.evaluate(
@@ -1718,30 +1790,30 @@ var structureCommand = registerCommand({
1718
1790
  },
1719
1791
  { sel: p.selector || "body", maxDepth: p.depth || 5 }
1720
1792
  );
1721
- return ok13({ structure });
1793
+ return ok14({ structure });
1722
1794
  }
1723
1795
  });
1724
1796
 
1725
1797
  // src/commands/viewport.ts
1726
- import { z as z14 } from "zod";
1727
- import { ok as ok14 } from "@dyyz1993/xcli-core";
1798
+ import { z as z15 } from "zod";
1799
+ import { ok as ok15 } from "@dyyz1993/xcli-core";
1728
1800
  var setViewportCommand = registerCommand({
1729
1801
  name: "set-viewport",
1730
1802
  description: "Set the viewport size and properties",
1731
1803
  scope: "browser",
1732
- parameters: z14.object({
1733
- width: z14.coerce.number(),
1734
- height: z14.coerce.number(),
1735
- deviceScaleFactor: z14.coerce.number().optional(),
1736
- isMobile: z14.boolean().optional(),
1737
- hasTouch: z14.boolean().optional()
1804
+ parameters: z15.object({
1805
+ width: z15.coerce.number(),
1806
+ height: z15.coerce.number(),
1807
+ deviceScaleFactor: z15.coerce.number().optional(),
1808
+ isMobile: z15.boolean().optional(),
1809
+ hasTouch: z15.boolean().optional()
1738
1810
  }),
1739
- result: z14.object({
1740
- width: z14.number(),
1741
- height: z14.number(),
1742
- deviceScaleFactor: z14.number().optional(),
1743
- isMobile: z14.boolean().optional(),
1744
- hasTouch: z14.boolean().optional()
1811
+ result: z15.object({
1812
+ width: z15.number(),
1813
+ height: z15.number(),
1814
+ deviceScaleFactor: z15.number().optional(),
1815
+ isMobile: z15.boolean().optional(),
1816
+ hasTouch: z15.boolean().optional()
1745
1817
  }),
1746
1818
  handler: async (p, ctx) => {
1747
1819
  const viewport = ctx.page.viewportSize();
@@ -1754,7 +1826,7 @@ var setViewportCommand = registerCommand({
1754
1826
  ...p.isMobile !== void 0 && { isMobile: p.isMobile },
1755
1827
  ...p.hasTouch !== void 0 && { hasTouch: p.hasTouch }
1756
1828
  });
1757
- return ok14({
1829
+ return ok15({
1758
1830
  width,
1759
1831
  height,
1760
1832
  ...p.deviceScaleFactor !== void 0 && { deviceScaleFactor: p.deviceScaleFactor },
@@ -1765,17 +1837,17 @@ var setViewportCommand = registerCommand({
1765
1837
  });
1766
1838
 
1767
1839
  // src/commands/frame.ts
1768
- import { z as z15 } from "zod";
1769
- import { ok as ok15, fail as fail6 } from "@dyyz1993/xcli-core";
1840
+ import { z as z16 } from "zod";
1841
+ import { ok as ok16, fail as fail7 } from "@dyyz1993/xcli-core";
1770
1842
  var framesCommand = registerCommand({
1771
1843
  name: "frames",
1772
1844
  description: "List all frames in the current page",
1773
1845
  scope: "page",
1774
- result: z15.object({
1775
- frames: z15.array(z15.object({
1776
- index: z15.number(),
1777
- name: z15.string().nullable(),
1778
- url: z15.string()
1846
+ result: z16.object({
1847
+ frames: z16.array(z16.object({
1848
+ index: z16.number(),
1849
+ name: z16.string().nullable(),
1850
+ url: z16.string()
1779
1851
  }))
1780
1852
  }),
1781
1853
  handler: async (_p, ctx) => {
@@ -1786,21 +1858,21 @@ var framesCommand = registerCommand({
1786
1858
  name: frame.name(),
1787
1859
  url: frame.url()
1788
1860
  }));
1789
- return ok15({ frames: frameList });
1861
+ return ok16({ frames: frameList });
1790
1862
  }
1791
1863
  });
1792
1864
  var frameCommand = registerCommand({
1793
1865
  name: "frame",
1794
1866
  description: "Get frame info by index or name",
1795
1867
  scope: "page",
1796
- parameters: z15.object({
1797
- index: z15.number().int().min(0).optional(),
1798
- name: z15.string().optional()
1868
+ parameters: z16.object({
1869
+ index: z16.number().int().min(0).optional(),
1870
+ name: z16.string().optional()
1799
1871
  }),
1800
- result: z15.object({
1801
- name: z15.string().nullable(),
1802
- url: z15.string(),
1803
- error: z15.string().optional()
1872
+ result: z16.object({
1873
+ name: z16.string().nullable(),
1874
+ url: z16.string(),
1875
+ error: z16.string().optional()
1804
1876
  }),
1805
1877
  handler: async (p, ctx) => {
1806
1878
  const discover = ctx.page.discoverFrames;
@@ -1811,12 +1883,12 @@ var frameCommand = registerCommand({
1811
1883
  } else if (p.name !== void 0) {
1812
1884
  targetFrame = rawFrames.find((f) => f.name() === p.name);
1813
1885
  } else {
1814
- return fail6("Must provide index or name");
1886
+ return fail7("Must provide index or name");
1815
1887
  }
1816
1888
  if (!targetFrame) {
1817
- return fail6("Frame not found");
1889
+ return fail7("Frame not found");
1818
1890
  }
1819
- return ok15({
1891
+ return ok16({
1820
1892
  name: targetFrame.name(),
1821
1893
  url: targetFrame.url()
1822
1894
  });
@@ -1824,27 +1896,27 @@ var frameCommand = registerCommand({
1824
1896
  });
1825
1897
 
1826
1898
  // src/commands/ui-debug.ts
1827
- import { z as z16 } from "zod";
1828
- import { ok as ok16 } from "@dyyz1993/xcli-core";
1899
+ import { z as z17 } from "zod";
1900
+ import { ok as ok17 } from "@dyyz1993/xcli-core";
1829
1901
  var consoleCheckCommand = registerCommand({
1830
1902
  name: "console",
1831
1903
  description: "Collect and analyze browser console messages (errors, warnings, logs)",
1832
1904
  scope: "page",
1833
- parameters: z16.object({
1834
- url: z16.string().optional().describe("URL to navigate first (optional, uses current page if omitted)"),
1835
- duration: z16.number().optional().default(5e3).describe("How long to collect messages (ms)"),
1836
- filter: z16.enum(["all", "error", "warning", "info", "log"]).optional().default("all"),
1837
- includeStackTraces: z16.boolean().optional().default(true)
1905
+ parameters: z17.object({
1906
+ url: z17.string().optional().describe("URL to navigate first (optional, uses current page if omitted)"),
1907
+ duration: z17.number().optional().default(5e3).describe("How long to collect messages (ms)"),
1908
+ filter: z17.enum(["all", "error", "warning", "info", "log"]).optional().default("all"),
1909
+ includeStackTraces: z17.boolean().optional().default(true)
1838
1910
  }),
1839
- result: z16.object({
1840
- url: z16.string(),
1841
- duration: z16.number(),
1842
- total: z16.number(),
1843
- errors: z16.number(),
1844
- warnings: z16.number(),
1845
- messages: z16.array(z16.record(z16.unknown())),
1846
- summary: z16.string(),
1847
- passed: z16.boolean()
1911
+ result: z17.object({
1912
+ url: z17.string(),
1913
+ duration: z17.number(),
1914
+ total: z17.number(),
1915
+ errors: z17.number(),
1916
+ warnings: z17.number(),
1917
+ messages: z17.array(z17.record(z17.unknown())),
1918
+ summary: z17.string(),
1919
+ passed: z17.boolean()
1848
1920
  }),
1849
1921
  handler: async (p, ctx) => {
1850
1922
  const { page } = ctx;
@@ -1926,7 +1998,7 @@ ${a.stack || ""}`;
1926
1998
  const filtered = p.filter === "all" ? messages : messages.filter((m) => m.type === p.filter);
1927
1999
  const errorCount = messages.filter((m) => m.type === "error").length;
1928
2000
  const warnCount = messages.filter((m) => m.type === "warning").length;
1929
- return ok16({
2001
+ return ok17({
1930
2002
  url: page.url(),
1931
2003
  duration: p.duration,
1932
2004
  total: messages.length,
@@ -1942,23 +2014,23 @@ var networkCheckCommand = registerCommand({
1942
2014
  name: "net-debug",
1943
2015
  description: "Monitor and analyze network requests \u2014 capture failed requests, slow responses, status codes",
1944
2016
  scope: "page",
1945
- parameters: z16.object({
1946
- url: z16.string().optional().describe("URL to navigate first"),
1947
- duration: z16.number().optional().default(5e3).describe("How long to monitor (ms)"),
1948
- filter: z16.enum(["all", "failed", "slow", "error", "xhr", "fetch", "document", "stylesheet", "script", "image"]).optional().default("all"),
1949
- slowThreshold: z16.number().optional().default(3e3).describe('Threshold for "slow" requests (ms)')
2017
+ parameters: z17.object({
2018
+ url: z17.string().optional().describe("URL to navigate first"),
2019
+ duration: z17.number().optional().default(5e3).describe("How long to monitor (ms)"),
2020
+ filter: z17.enum(["all", "failed", "slow", "error", "xhr", "fetch", "document", "stylesheet", "script", "image"]).optional().default("all"),
2021
+ slowThreshold: z17.number().optional().default(3e3).describe('Threshold for "slow" requests (ms)')
1950
2022
  }),
1951
- result: z16.object({
1952
- url: z16.string(),
1953
- duration: z16.number(),
1954
- totalRequests: z16.number(),
1955
- failedRequests: z16.number(),
1956
- slowRequests: z16.number(),
1957
- errorRequests: z16.number(),
1958
- totalSizeKB: z16.number(),
1959
- requests: z16.array(z16.record(z16.unknown())),
1960
- summary: z16.string(),
1961
- passed: z16.boolean()
2023
+ result: z17.object({
2024
+ url: z17.string(),
2025
+ duration: z17.number(),
2026
+ totalRequests: z17.number(),
2027
+ failedRequests: z17.number(),
2028
+ slowRequests: z17.number(),
2029
+ errorRequests: z17.number(),
2030
+ totalSizeKB: z17.number(),
2031
+ requests: z17.array(z17.record(z17.unknown())),
2032
+ summary: z17.string(),
2033
+ passed: z17.boolean()
1962
2034
  }),
1963
2035
  handler: async (p, ctx) => {
1964
2036
  const { page } = ctx;
@@ -2040,7 +2112,7 @@ var networkCheckCommand = registerCommand({
2040
2112
  const slowCount = requests.filter((r) => r.duration >= p.slowThreshold).length;
2041
2113
  const errorCount = requests.filter((r) => r.error).length;
2042
2114
  const totalSize = requests.reduce((sum, r) => sum + r.size, 0);
2043
- return ok16({
2115
+ return ok17({
2044
2116
  url: page.url(),
2045
2117
  duration: p.duration,
2046
2118
  totalRequests: requests.length,
@@ -2062,17 +2134,17 @@ var perfCheckCommand = registerCommand({
2062
2134
  name: "perf",
2063
2135
  description: "Audit page performance metrics \u2014 load time, FCP, LCP, CLS, TTFB, resource sizes",
2064
2136
  scope: "page",
2065
- parameters: z16.object({
2066
- url: z16.string().optional().describe("URL to navigate (uses current page if omitted)"),
2067
- iterations: z16.number().optional().default(1).describe("Number of iterations to average")
2137
+ parameters: z17.object({
2138
+ url: z17.string().optional().describe("URL to navigate (uses current page if omitted)"),
2139
+ iterations: z17.number().optional().default(1).describe("Number of iterations to average")
2068
2140
  }),
2069
- result: z16.object({
2070
- url: z16.string(),
2071
- iterations: z16.number(),
2072
- metrics: z16.record(z16.unknown()),
2073
- allIterations: z16.array(z16.record(z16.unknown())).optional(),
2074
- passed: z16.boolean(),
2075
- summary: z16.string()
2141
+ result: z17.object({
2142
+ url: z17.string(),
2143
+ iterations: z17.number(),
2144
+ metrics: z17.record(z17.unknown()),
2145
+ allIterations: z17.array(z17.record(z17.unknown())).optional(),
2146
+ passed: z17.boolean(),
2147
+ summary: z17.string()
2076
2148
  }),
2077
2149
  handler: async (p, ctx) => {
2078
2150
  const { page } = ctx;
@@ -2134,7 +2206,7 @@ var perfCheckCommand = registerCommand({
2134
2206
  if (resourceStats) avg.resourceStats = resourceStats;
2135
2207
  return avg;
2136
2208
  })();
2137
- return ok16({
2209
+ return ok17({
2138
2210
  url: page.url(),
2139
2211
  iterations: p.iterations,
2140
2212
  metrics: avgMetrics,
@@ -2148,23 +2220,23 @@ var healthCheckCommand = registerCommand({
2148
2220
  name: "health",
2149
2221
  description: "Comprehensive page health check \u2014 broken links, missing images, console errors, SEO issues",
2150
2222
  scope: "page",
2151
- parameters: z16.object({
2152
- url: z16.string().optional().describe("URL to check"),
2153
- checkLinks: z16.boolean().optional().default(true).describe("Check for broken links"),
2154
- checkImages: z16.boolean().optional().default(true).describe("Check for missing/broken images"),
2155
- checkMeta: z16.boolean().optional().default(true).describe("Check SEO meta tags"),
2156
- maxLinks: z16.number().optional().default(50).describe("Max links to check")
2223
+ parameters: z17.object({
2224
+ url: z17.string().optional().describe("URL to check"),
2225
+ checkLinks: z17.boolean().optional().default(true).describe("Check for broken links"),
2226
+ checkImages: z17.boolean().optional().default(true).describe("Check for missing/broken images"),
2227
+ checkMeta: z17.boolean().optional().default(true).describe("Check SEO meta tags"),
2228
+ maxLinks: z17.number().optional().default(50).describe("Max links to check")
2157
2229
  }),
2158
- result: z16.object({
2159
- url: z16.string(),
2160
- title: z16.string(),
2161
- passed: z16.boolean(),
2162
- totalIssues: z16.number(),
2163
- errors: z16.number(),
2164
- warnings: z16.number(),
2165
- info: z16.number(),
2166
- issues: z16.array(z16.record(z16.unknown())),
2167
- summary: z16.string()
2230
+ result: z17.object({
2231
+ url: z17.string(),
2232
+ title: z17.string(),
2233
+ passed: z17.boolean(),
2234
+ totalIssues: z17.number(),
2235
+ errors: z17.number(),
2236
+ warnings: z17.number(),
2237
+ info: z17.number(),
2238
+ issues: z17.array(z17.record(z17.unknown())),
2239
+ summary: z17.string()
2168
2240
  }),
2169
2241
  handler: async (p, ctx) => {
2170
2242
  const { page } = ctx;
@@ -2251,7 +2323,7 @@ var healthCheckCommand = registerCommand({
2251
2323
  }, { checkLinks: p.checkLinks, checkImages: p.checkImages, checkMeta: p.checkMeta, maxLinks: p.maxLinks });
2252
2324
  const errors = result.issues.filter((i) => i.severity === "error").length;
2253
2325
  const warnings = result.issues.filter((i) => i.severity === "warning").length;
2254
- return ok16({
2326
+ return ok17({
2255
2327
  url: result.url,
2256
2328
  title: result.title,
2257
2329
  passed: errors === 0,
@@ -2266,8 +2338,8 @@ var healthCheckCommand = registerCommand({
2266
2338
  });
2267
2339
 
2268
2340
  // src/commands/actions.ts
2269
- import { z as z17 } from "zod";
2270
- import { ok as ok17 } from "@dyyz1993/xcli-core";
2341
+ import { z as z18 } from "zod";
2342
+ import { ok as ok18 } from "@dyyz1993/xcli-core";
2271
2343
  import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
2272
2344
  import { join as join5 } from "path";
2273
2345
  function ensureScreenshotsDir2() {
@@ -2279,53 +2351,53 @@ function generateScreenshotPath2(format) {
2279
2351
  const ext = format === "jpeg" ? "jpg" : "png";
2280
2352
  return join5(resolveScreenshotsDir(), `screenshot-${timestamp}-${random}.${ext}`);
2281
2353
  }
2282
- var waitActionSchema = z17.object({
2283
- type: z17.literal("wait"),
2284
- milliseconds: z17.number().positive().optional(),
2285
- selector: z17.string().optional()
2354
+ var waitActionSchema = z18.object({
2355
+ type: z18.literal("wait"),
2356
+ milliseconds: z18.number().positive().optional(),
2357
+ selector: z18.string().optional()
2286
2358
  }).refine(
2287
2359
  (d) => (d.milliseconds !== void 0 || d.selector !== void 0) && !(d.milliseconds !== void 0 && d.selector !== void 0),
2288
2360
  { message: "Either 'milliseconds' or 'selector' must be provided, but not both." }
2289
2361
  );
2290
- var clickActionSchema = z17.object({
2291
- type: z17.literal("click"),
2292
- selector: z17.string(),
2293
- all: z17.boolean().optional()
2362
+ var clickActionSchema = z18.object({
2363
+ type: z18.literal("click"),
2364
+ selector: z18.string(),
2365
+ all: z18.boolean().optional()
2294
2366
  });
2295
- var screenshotActionSchema = z17.object({
2296
- type: z17.literal("screenshot"),
2297
- fullPage: z17.boolean().optional(),
2298
- quality: z17.number().min(1).max(100).optional(),
2299
- viewport: z17.object({ width: z17.number().int().positive(), height: z17.number().int().positive() }).optional(),
2300
- base64: z17.boolean().optional().describe("Return base64 data instead of file path")
2367
+ var screenshotActionSchema = z18.object({
2368
+ type: z18.literal("screenshot"),
2369
+ fullPage: z18.boolean().optional(),
2370
+ quality: z18.number().min(1).max(100).optional(),
2371
+ viewport: z18.object({ width: z18.number().int().positive(), height: z18.number().int().positive() }).optional(),
2372
+ base64: z18.boolean().optional().describe("Return base64 data instead of file path")
2301
2373
  });
2302
- var writeActionSchema = z17.object({
2303
- type: z17.literal("write"),
2304
- text: z17.string()
2374
+ var writeActionSchema = z18.object({
2375
+ type: z18.literal("write"),
2376
+ text: z18.string()
2305
2377
  });
2306
- var pressActionSchema = z17.object({
2307
- type: z17.literal("press"),
2308
- key: z17.string()
2378
+ var pressActionSchema = z18.object({
2379
+ type: z18.literal("press"),
2380
+ key: z18.string()
2309
2381
  });
2310
- var scrollActionSchema = z17.object({
2311
- type: z17.literal("scroll"),
2312
- direction: z17.enum(["up", "down"]).optional(),
2313
- selector: z17.string().optional()
2382
+ var scrollActionSchema = z18.object({
2383
+ type: z18.literal("scroll"),
2384
+ direction: z18.enum(["up", "down"]).optional(),
2385
+ selector: z18.string().optional()
2314
2386
  });
2315
- var scrapeActionSchema = z17.object({
2316
- type: z17.literal("scrape")
2387
+ var scrapeActionSchema = z18.object({
2388
+ type: z18.literal("scrape")
2317
2389
  });
2318
- var executeJavascriptActionSchema = z17.object({
2319
- type: z17.literal("executeJavascript"),
2320
- script: z17.string()
2390
+ var executeJavascriptActionSchema = z18.object({
2391
+ type: z18.literal("executeJavascript"),
2392
+ script: z18.string()
2321
2393
  });
2322
- var pdfActionSchema = z17.object({
2323
- type: z17.literal("pdf"),
2324
- landscape: z17.boolean().optional(),
2325
- scale: z17.number().optional(),
2326
- format: z17.enum(["A0", "A1", "A2", "A3", "A4", "A5", "A6", "Letter", "Legal", "Tabloid", "Ledger"]).optional()
2394
+ var pdfActionSchema = z18.object({
2395
+ type: z18.literal("pdf"),
2396
+ landscape: z18.boolean().optional(),
2397
+ scale: z18.number().optional(),
2398
+ format: z18.enum(["A0", "A1", "A2", "A3", "A4", "A5", "A6", "Letter", "Legal", "Tabloid", "Ledger"]).optional()
2327
2399
  });
2328
- var actionSchema = z17.union([
2400
+ var actionSchema = z18.union([
2329
2401
  waitActionSchema,
2330
2402
  clickActionSchema,
2331
2403
  screenshotActionSchema,
@@ -2416,11 +2488,11 @@ var actionsCommand = registerCommand({
2416
2488
  name: "actions",
2417
2489
  description: "Execute a sequence of actions (wait, click, scroll, screenshot, fill, etc.)",
2418
2490
  scope: "page",
2419
- parameters: z17.object({
2420
- url: z17.string().describe("Starting URL"),
2421
- actions: z17.array(actionSchema).max(MAX_ACTIONS).describe("Array of actions (max 50)"),
2422
- output: z17.enum(["text", "json"]).default("json").describe("Output format: text or json"),
2423
- timeout: z17.number().default(60).describe("Overall timeout in seconds (default: 60)")
2491
+ parameters: z18.object({
2492
+ url: z18.string().describe("Starting URL"),
2493
+ actions: z18.array(actionSchema).max(MAX_ACTIONS).describe("Array of actions (max 50)"),
2494
+ output: z18.enum(["text", "json"]).default("json").describe("Output format: text or json"),
2495
+ timeout: z18.number().default(60).describe("Overall timeout in seconds (default: 60)")
2424
2496
  }),
2425
2497
  handler: async (p, ctx) => {
2426
2498
  await ctx.page.goto(p.url, { waitUntil: "domcontentloaded" });
@@ -2440,14 +2512,14 @@ var actionsCommand = registerCommand({
2440
2512
  const finalUrl = ctx.page.url();
2441
2513
  const timedOut = results.length < p.actions.length;
2442
2514
  if (p.output === "text") {
2443
- return ok17({
2515
+ return ok18({
2444
2516
  title,
2445
2517
  url: finalUrl,
2446
2518
  actions: results.map((r) => JSON.stringify(r)).join("\n"),
2447
2519
  ...timedOut ? { warning: `Timed out after ${p.timeout}s, completed ${results.length}/${p.actions.length} actions` } : {}
2448
2520
  });
2449
2521
  }
2450
- return ok17({
2522
+ return ok18({
2451
2523
  title,
2452
2524
  url: finalUrl,
2453
2525
  results,
@@ -2457,8 +2529,8 @@ var actionsCommand = registerCommand({
2457
2529
  });
2458
2530
 
2459
2531
  // src/commands/scrape.ts
2460
- import { z as z18 } from "zod";
2461
- import { ok as ok18, fail as fail7 } from "@dyyz1993/xcli-core";
2532
+ import { z as z19 } from "zod";
2533
+ import { ok as ok19, fail as fail8 } from "@dyyz1993/xcli-core";
2462
2534
 
2463
2535
  // src/lib/html-to-markdown.ts
2464
2536
  import * as cheerio from "cheerio";
@@ -2843,15 +2915,15 @@ var scrapeCommand = registerCommand({
2843
2915
  description: "Scrape a page and convert to Markdown (with JS rendering)",
2844
2916
  scope: "project",
2845
2917
  selectorParams: ["selector"],
2846
- parameters: z18.object({
2847
- url: z18.string().optional(),
2848
- selector: z18.string().optional(),
2849
- timeout: z18.number().default(3e4),
2850
- format: z18.enum(["markdown", "html", "text"]).default("markdown"),
2851
- onlyMainContent: z18.boolean().default(true),
2852
- retries: z18.number().int().min(0).max(5).optional().default(2).describe("\u91CD\u8BD5\u6B21\u6570\uFF08\u9ED8\u8BA4 2\uFF09"),
2853
- waitAfterLoad: z18.number().int().optional().default(0).describe("\u9875\u9762\u52A0\u8F7D\u540E\u989D\u5916\u7B49\u5F85\u6BEB\u79D2"),
2854
- 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")
2918
+ parameters: z19.object({
2919
+ url: z19.string().optional(),
2920
+ selector: z19.string().optional(),
2921
+ timeout: z19.number().default(3e4),
2922
+ format: z19.enum(["markdown", "html", "text"]).default("markdown"),
2923
+ onlyMainContent: z19.boolean().default(true),
2924
+ retries: z19.number().int().min(0).max(5).optional().default(2).describe("\u91CD\u8BD5\u6B21\u6570\uFF08\u9ED8\u8BA4 2\uFF09"),
2925
+ waitAfterLoad: z19.number().int().optional().default(0).describe("\u9875\u9762\u52A0\u8F7D\u540E\u989D\u5916\u7B49\u5F85\u6BEB\u79D2"),
2926
+ 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")
2855
2927
  }),
2856
2928
  handler: async (p, ctx) => {
2857
2929
  const { context, page } = await createEphemeralContext(resolveLaunchOpts(ctx));
@@ -2859,7 +2931,7 @@ var scrapeCommand = registerCommand({
2859
2931
  try {
2860
2932
  const targetUrl = p.url || page.url();
2861
2933
  if (!targetUrl || targetUrl === "about:blank") {
2862
- return fail7("URL is required. Provide a URL or connect to a browser (--cdp) with a non-blank page.");
2934
+ return fail8("URL is required. Provide a URL or connect to a browser (--cdp) with a non-blank page.");
2863
2935
  }
2864
2936
  let lastError;
2865
2937
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
@@ -2929,7 +3001,7 @@ var scrapeCommand = registerCommand({
2929
3001
  } catch {
2930
3002
  }
2931
3003
  if (p.mode === "smart") {
2932
- return ok18(structured);
3004
+ return ok19(structured);
2933
3005
  }
2934
3006
  if (p.mode === "compact") {
2935
3007
  const compactData = structured.tables.length > 0 ? structured.tables.map((t) => ({
@@ -2942,9 +3014,9 @@ var scrapeCommand = registerCommand({
2942
3014
  return compact;
2943
3015
  })
2944
3016
  })) : structured.mainText?.substring(0, 500);
2945
- return ok18({ url: structured.url, title: structured.title, data: compactData });
3017
+ return ok19({ url: structured.url, title: structured.title, data: compactData });
2946
3018
  }
2947
- return ok18(structured);
3019
+ return ok19(structured);
2948
3020
  }
2949
3021
  let content;
2950
3022
  switch (p.format) {
@@ -3003,7 +3075,7 @@ var scrapeCommand = registerCommand({
3003
3075
  content = await page.innerText("body");
3004
3076
  break;
3005
3077
  }
3006
- return ok18({ content, title, url: finalUrl });
3078
+ return ok19({ content, title, url: finalUrl });
3007
3079
  } catch (err) {
3008
3080
  lastError = err instanceof Error ? err : new Error(String(err));
3009
3081
  if (attempt < maxAttempts) {
@@ -3013,20 +3085,20 @@ var scrapeCommand = registerCommand({
3013
3085
  }
3014
3086
  }
3015
3087
  }
3016
- return fail7(`Scrape failed after ${maxAttempts} attempt(s): ${lastError?.message ?? "unknown error"}`);
3088
+ return fail8(`Scrape failed after ${maxAttempts} attempt(s): ${lastError?.message ?? "unknown error"}`);
3017
3089
  } finally {
3018
3090
  await closeEphemeralContext(context);
3019
3091
  }
3020
3092
  },
3021
- result: z18.object({
3022
- url: z18.string(),
3023
- title: z18.string()
3093
+ result: z19.object({
3094
+ url: z19.string(),
3095
+ title: z19.string()
3024
3096
  }).passthrough()
3025
3097
  });
3026
3098
 
3027
3099
  // src/commands/map.ts
3028
- import { z as z19 } from "zod";
3029
- import { ok as ok19, fail as fail8 } from "@dyyz1993/xcli-core";
3100
+ import { z as z20 } from "zod";
3101
+ import { ok as ok20, fail as fail9 } from "@dyyz1993/xcli-core";
3030
3102
 
3031
3103
  // src/utils/url.ts
3032
3104
  var SKIP_EXTENSIONS = /* @__PURE__ */ new Set([
@@ -3261,21 +3333,21 @@ var mapCommand = registerCommand({
3261
3333
  name: "map",
3262
3334
  description: "Discover all URLs on a website via sitemap and page link extraction",
3263
3335
  scope: "project",
3264
- parameters: z19.object({
3265
- url: z19.string().optional(),
3266
- search: z19.string().optional(),
3267
- sitemap: z19.enum(["include", "only"]).optional(),
3268
- includeSubdomains: z19.boolean().optional(),
3269
- allowExternalLinks: z19.boolean().optional().describe("Include links to external domains"),
3270
- limit: z19.number().optional(),
3271
- verbose: z19.boolean().default(false).describe("Show progress feedback")
3336
+ parameters: z20.object({
3337
+ url: z20.string().optional(),
3338
+ search: z20.string().optional(),
3339
+ sitemap: z20.enum(["include", "only"]).optional(),
3340
+ includeSubdomains: z20.boolean().optional(),
3341
+ allowExternalLinks: z20.boolean().optional().describe("Include links to external domains"),
3342
+ limit: z20.number().optional(),
3343
+ verbose: z20.boolean().default(false).describe("Show progress feedback")
3272
3344
  }),
3273
3345
  handler: async (p, ctx) => {
3274
3346
  const { context, page } = await createEphemeralContext(resolveLaunchOpts(ctx));
3275
3347
  try {
3276
3348
  const targetUrl = p.url || page.url();
3277
3349
  if (!targetUrl || targetUrl === "about:blank") {
3278
- return fail8("URL is required. Provide a URL or connect to a browser (--cdp) with a non-blank page.");
3350
+ return fail9("URL is required. Provide a URL or connect to a browser (--cdp) with a non-blank page.");
3279
3351
  }
3280
3352
  const links = await discoverUrls(page, targetUrl, {
3281
3353
  sitemap: p.sitemap,
@@ -3286,7 +3358,7 @@ var mapCommand = registerCommand({
3286
3358
  verbose: p.verbose
3287
3359
  });
3288
3360
  const linkObjects = links.map((url) => ({ url }));
3289
- return ok19({
3361
+ return ok20({
3290
3362
  links: linkObjects,
3291
3363
  success: true
3292
3364
  });
@@ -3294,15 +3366,15 @@ var mapCommand = registerCommand({
3294
3366
  await closeEphemeralContext(context);
3295
3367
  }
3296
3368
  },
3297
- result: z19.object({
3298
- links: z19.array(z19.object({ url: z19.string() })),
3299
- success: z19.boolean()
3369
+ result: z20.object({
3370
+ links: z20.array(z20.object({ url: z20.string() })),
3371
+ success: z20.boolean()
3300
3372
  })
3301
3373
  });
3302
3374
 
3303
3375
  // src/commands/crawl.ts
3304
- import { z as z20 } from "zod";
3305
- import { ok as ok20 } from "@dyyz1993/xcli-core";
3376
+ import { z as z21 } from "zod";
3377
+ import { ok as ok21 } from "@dyyz1993/xcli-core";
3306
3378
  function stripHashAnchorQuery(url) {
3307
3379
  try {
3308
3380
  const parsed = new URL(url);
@@ -3479,21 +3551,21 @@ var crawlCommand = registerCommand({
3479
3551
  name: "crawl",
3480
3552
  description: "Crawl a website and extract content from all pages",
3481
3553
  scope: "project",
3482
- parameters: z20.object({
3483
- url: z20.string(),
3484
- limit: z20.number().default(10),
3485
- maxDepth: z20.number().default(3),
3486
- includePaths: z20.array(z20.string()).optional(),
3487
- excludePaths: z20.array(z20.string()).optional(),
3488
- allowSubdomains: z20.boolean().default(false),
3489
- allowExternalLinks: z20.boolean().default(false),
3490
- allowBackwardCrawling: z20.boolean().default(false),
3491
- enableSpa: z20.boolean().default(true).describe("Disable to skip SPA route detection"),
3492
- format: z20.enum(["markdown", "html"]).default("markdown"),
3493
- onlyMainContent: z20.boolean().default(true),
3494
- concurrency: z20.number().default(3),
3495
- retries: z20.number().default(2),
3496
- verbose: z20.boolean().default(false)
3554
+ parameters: z21.object({
3555
+ url: z21.string(),
3556
+ limit: z21.number().default(10),
3557
+ maxDepth: z21.number().default(3),
3558
+ includePaths: z21.array(z21.string()).optional(),
3559
+ excludePaths: z21.array(z21.string()).optional(),
3560
+ allowSubdomains: z21.boolean().default(false),
3561
+ allowExternalLinks: z21.boolean().default(false),
3562
+ allowBackwardCrawling: z21.boolean().default(false),
3563
+ enableSpa: z21.boolean().default(true).describe("Disable to skip SPA route detection"),
3564
+ format: z21.enum(["markdown", "html"]).default("markdown"),
3565
+ onlyMainContent: z21.boolean().default(true),
3566
+ concurrency: z21.number().default(3),
3567
+ retries: z21.number().default(2),
3568
+ verbose: z21.boolean().default(false)
3497
3569
  }),
3498
3570
  handler: async (p, ctx) => {
3499
3571
  const startUrl = new URL(p.url);
@@ -3632,7 +3704,7 @@ var crawlCommand = registerCommand({
3632
3704
  if (errorPages.length > 0) {
3633
3705
  response.errors = errorPages;
3634
3706
  }
3635
- return ok20(response);
3707
+ return ok21(response);
3636
3708
  } finally {
3637
3709
  for (const ctx2 of contexts) {
3638
3710
  await ctx2.close().catch(() => {
@@ -3642,15 +3714,15 @@ var crawlCommand = registerCommand({
3642
3714
  } catch (err) {
3643
3715
  const message = err instanceof Error ? err.message : String(err);
3644
3716
  const successPages = results.filter((r) => !isPageError(r));
3645
- return ok20({ pages: successPages, total: successPages.length, success: false, error: message });
3717
+ return ok21({ pages: successPages, total: successPages.length, success: false, error: message });
3646
3718
  }
3647
3719
  }
3648
3720
  });
3649
3721
 
3650
3722
  // src/commands/search.ts
3651
- import { z as z21 } from "zod";
3723
+ import { z as z22 } from "zod";
3652
3724
  import * as cheerio2 from "cheerio";
3653
- import { ok as ok21 } from "@dyyz1993/xcli-core";
3725
+ import { ok as ok22 } from "@dyyz1993/xcli-core";
3654
3726
  function getRecencyParams(recency) {
3655
3727
  const now = Math.floor(Date.now() / 1e3);
3656
3728
  switch (recency) {
@@ -3984,16 +4056,16 @@ var searchCommand = registerCommand({
3984
4056
  name: "search",
3985
4057
  description: "Search the web and extract results with engine fallback",
3986
4058
  scope: "project",
3987
- parameters: z21.object({
3988
- query: z21.string(),
3989
- engine: z21.string().optional(),
3990
- limit: z21.number().default(10),
3991
- full: z21.boolean().default(false),
3992
- format: z21.enum(["markdown", "json", "text"]).default("markdown"),
3993
- timeout: z21.number().default(15e3),
3994
- recency: z21.enum(["hour", "day", "week", "month", "year"]).optional().describe("Filter by time: hour/day/week/month/year"),
3995
- fallback: z21.boolean().default(false).describe("Sequential engine fallback instead of parallel"),
3996
- site: z21.string().optional().describe("Limit results to a specific site (e.g. github.com, v2ex.com)")
4059
+ parameters: z22.object({
4060
+ query: z22.string(),
4061
+ engine: z22.string().optional(),
4062
+ limit: z22.number().default(10),
4063
+ full: z22.boolean().default(false),
4064
+ format: z22.enum(["markdown", "json", "text"]).default("markdown"),
4065
+ timeout: z22.number().default(15e3),
4066
+ recency: z22.enum(["hour", "day", "week", "month", "year"]).optional().describe("Filter by time: hour/day/week/month/year"),
4067
+ fallback: z22.boolean().default(false).describe("Sequential engine fallback instead of parallel"),
4068
+ site: z22.string().optional().describe("Limit results to a specific site (e.g. github.com, v2ex.com)")
3997
4069
  }),
3998
4070
  handler: async (p, ctx) => {
3999
4071
  const { context } = await createEphemeralContext(resolveLaunchOpts(ctx));
@@ -4099,7 +4171,7 @@ ${errors.map((e) => ` - ${e.engine}: ${e.error}`).join("\n")}`
4099
4171
  lines.push(`> ${r.snippet}`);
4100
4172
  lines.push("");
4101
4173
  }
4102
- return ok21({ ...searchResult, content: lines.join("\n") });
4174
+ return ok22({ ...searchResult, content: lines.join("\n") });
4103
4175
  }
4104
4176
  if (p.format === "text") {
4105
4177
  const lines = [`Search: ${searchResult.query} (Engine: ${searchResult.engine}, Total: ${searchResult.total})`, ""];
@@ -4109,9 +4181,9 @@ ${errors.map((e) => ` - ${e.engine}: ${e.error}`).join("\n")}`
4109
4181
  lines.push(` ${r.snippet}`);
4110
4182
  lines.push("");
4111
4183
  }
4112
- return ok21({ ...searchResult, content: lines.join("\n") });
4184
+ return ok22({ ...searchResult, content: lines.join("\n") });
4113
4185
  }
4114
- return ok21(searchResult);
4186
+ return ok22(searchResult);
4115
4187
  } finally {
4116
4188
  await closeEphemeralContext(context);
4117
4189
  }
@@ -4119,8 +4191,8 @@ ${errors.map((e) => ` - ${e.engine}: ${e.error}`).join("\n")}`
4119
4191
  });
4120
4192
 
4121
4193
  // src/commands/network.ts
4122
- import { z as z22 } from "zod";
4123
- import { ok as ok22, fail as fail9 } from "@dyyz1993/xcli-core";
4194
+ import { z as z23 } from "zod";
4195
+ import { ok as ok23, fail as fail10 } from "@dyyz1993/xcli-core";
4124
4196
  function extractPath2(url) {
4125
4197
  try {
4126
4198
  const u = new URL(url);
@@ -4218,19 +4290,19 @@ var networkCommand = registerCommand({
4218
4290
  name: "network",
4219
4291
  description: "Capture and filter network responses from a URL",
4220
4292
  scope: "project",
4221
- parameters: z22.object({
4222
- url: z22.string(),
4223
- filter: z22.string().optional(),
4224
- match: z22.string().optional(),
4225
- search: z22.string().optional().describe("Search within all captured response bodies"),
4226
- console: z22.boolean().default(false),
4227
- timeout: z22.number().default(3e4),
4228
- wait: z22.number().default(3e3),
4229
- limit: z22.number().default(50),
4230
- format: z22.enum(["summary", "json"]).default("summary"),
4231
- ws: z22.boolean().optional().default(false).describe("Only show WebSocket messages"),
4232
- 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"),
4233
- duration: z22.number().int().optional().default(15e3).describe("\u76D1\u542C\u6A21\u5F0F\u7B49\u5F85\u65F6\u957F\uFF08\u6BEB\u79D2\uFF0C\u9ED8\u8BA4 15000\uFF09")
4293
+ parameters: z23.object({
4294
+ url: z23.string(),
4295
+ filter: z23.string().optional(),
4296
+ match: z23.string().optional(),
4297
+ search: z23.string().optional().describe("Search within all captured response bodies"),
4298
+ console: z23.boolean().default(false),
4299
+ timeout: z23.number().default(3e4),
4300
+ wait: z23.number().default(3e3),
4301
+ limit: z23.number().default(50),
4302
+ format: z23.enum(["summary", "json"]).default("summary"),
4303
+ ws: z23.boolean().optional().default(false).describe("Only show WebSocket messages"),
4304
+ 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"),
4305
+ duration: z23.number().int().optional().default(15e3).describe("\u76D1\u542C\u6A21\u5F0F\u7B49\u5F85\u65F6\u957F\uFF08\u6BEB\u79D2\uFF0C\u9ED8\u8BA4 15000\uFF09")
4234
4306
  }),
4235
4307
  handler: async (p, ctx) => {
4236
4308
  const startTime = Date.now();
@@ -4285,7 +4357,7 @@ var networkCommand = registerCommand({
4285
4357
  };
4286
4358
  if (p.listen) {
4287
4359
  const page2 = ctx.page;
4288
- if (!page2) return fail9("No active page. Use --cdp to connect first.");
4360
+ if (!page2) return fail10("No active page. Use --cdp to connect first.");
4289
4361
  const captures = [];
4290
4362
  const consoleMessages = [];
4291
4363
  const wsCaptures = [];
@@ -4312,7 +4384,7 @@ var networkCommand = registerCommand({
4312
4384
  page2.off("response", handler);
4313
4385
  const duration = Date.now() - startTime;
4314
4386
  if (p.ws && wsCaptures.length > 0) {
4315
- return ok22({
4387
+ return ok23({
4316
4388
  url: "[listen mode]",
4317
4389
  duration,
4318
4390
  total: captures.length,
@@ -4326,9 +4398,9 @@ var networkCommand = registerCommand({
4326
4398
  });
4327
4399
  }
4328
4400
  if (p.format === "json") {
4329
- return ok22(buildJsonOutput("[listen mode]", captures, consoleMessages, captures.length, wsCaptures));
4401
+ return ok23(buildJsonOutput("[listen mode]", captures, consoleMessages, captures.length, wsCaptures));
4330
4402
  }
4331
- return ok22(buildSummaryOutput("[listen mode]", duration, captures, consoleMessages, captures.length, wsCaptures));
4403
+ return ok23(buildSummaryOutput("[listen mode]", duration, captures, consoleMessages, captures.length, wsCaptures));
4332
4404
  }
4333
4405
  const { context, page } = await createEphemeralContext(resolveLaunchOpts(ctx));
4334
4406
  try {
@@ -4383,7 +4455,7 @@ var networkCommand = registerCommand({
4383
4455
  }
4384
4456
  const duration = Date.now() - startTime;
4385
4457
  if (p.ws && wsCaptures.length > 0) {
4386
- return ok22({
4458
+ return ok23({
4387
4459
  url: p.url,
4388
4460
  duration,
4389
4461
  total: captures.length,
@@ -4397,9 +4469,9 @@ var networkCommand = registerCommand({
4397
4469
  });
4398
4470
  }
4399
4471
  if (p.format === "json") {
4400
- return ok22(buildJsonOutput(p.url, results, consoleMessages, totalCount, wsCaptures, searchResults));
4472
+ return ok23(buildJsonOutput(p.url, results, consoleMessages, totalCount, wsCaptures, searchResults));
4401
4473
  }
4402
- return ok22(buildSummaryOutput(p.url, duration, results, consoleMessages, totalCount, wsCaptures));
4474
+ return ok23(buildSummaryOutput(p.url, duration, results, consoleMessages, totalCount, wsCaptures));
4403
4475
  } finally {
4404
4476
  await closeEphemeralContext(context);
4405
4477
  }
@@ -4407,7 +4479,7 @@ var networkCommand = registerCommand({
4407
4479
  });
4408
4480
 
4409
4481
  // src/commands/ai-search-engines.ts
4410
- import { z as z23 } from "zod";
4482
+ import { z as z24 } from "zod";
4411
4483
  var ENGINE_CONFIGS = {
4412
4484
  deepseek: {
4413
4485
  key: "deepseek",
@@ -4661,11 +4733,11 @@ var ENGINE_CONFIGS = {
4661
4733
  }
4662
4734
  };
4663
4735
  var ALL_ENGINE_KEYS = Object.keys(ENGINE_CONFIGS);
4664
- var ENGINE_KEY_ENUM = z23.enum(ALL_ENGINE_KEYS);
4736
+ var ENGINE_KEY_ENUM = z24.enum(ALL_ENGINE_KEYS);
4665
4737
 
4666
4738
  // src/commands/snapshot.ts
4667
- import { z as z24 } from "zod";
4668
- import { ok as ok23, fail as fail10, normalizeTips as normalizeTips3 } from "@dyyz1993/xcli-core";
4739
+ import { z as z25 } from "zod";
4740
+ import { ok as ok24, fail as fail11, normalizeTips as normalizeTips3 } from "@dyyz1993/xcli-core";
4669
4741
 
4670
4742
  // src/runtime/ref-store.ts
4671
4743
  var sessions = /* @__PURE__ */ new Map();
@@ -5577,24 +5649,24 @@ var snapshotCommand = registerCommand({
5577
5649
  description: "Capture a quick page state snapshot \u2014 aria tree, visible text, or DOM summary",
5578
5650
  scope: "page",
5579
5651
  selectorParams: ["selector"],
5580
- parameters: z24.object({
5581
- type: z24.enum(["aria", "text", "dom", "all"]).default("aria").describe("Snapshot type: aria (accessibility tree), text (visible text), dom (element summary), all (combined)"),
5582
- selector: z24.string().optional().describe("Scope to a specific element"),
5583
- depth: z24.number().optional().default(6).describe("Max depth for DOM/aria tree"),
5584
- interactive: z24.boolean().optional().default(false).describe("Return interactive agent refs only"),
5585
- interactiveOnly: z24.boolean().optional().default(false).describe("Alias for interactive"),
5586
- i: z24.boolean().optional().default(false).describe("Short alias for interactive"),
5587
- compact: z24.boolean().optional().default(false).describe("Include compact xbrowser style snapshot text"),
5588
- c: z24.boolean().optional().default(false).describe("Short alias for compact"),
5589
- selectors: z24.boolean().optional().default(false).describe("Include ref to CSS selector map"),
5590
- all: z24.boolean().optional().default(false).describe("Include hidden interactive targets when using interactive snapshot")
5652
+ parameters: z25.object({
5653
+ type: z25.enum(["aria", "text", "dom", "all"]).default("aria").describe("Snapshot type: aria (accessibility tree), text (visible text), dom (element summary), all (combined)"),
5654
+ selector: z25.string().optional().describe("Scope to a specific element"),
5655
+ depth: z25.number().optional().default(6).describe("Max depth for DOM/aria tree"),
5656
+ interactive: z25.boolean().optional().default(false).describe("Return interactive agent refs only"),
5657
+ interactiveOnly: z25.boolean().optional().default(false).describe("Alias for interactive"),
5658
+ i: z25.boolean().optional().default(false).describe("Short alias for interactive"),
5659
+ compact: z25.boolean().optional().default(false).describe("Include compact xbrowser style snapshot text"),
5660
+ c: z25.boolean().optional().default(false).describe("Short alias for compact"),
5661
+ selectors: z25.boolean().optional().default(false).describe("Include ref to CSS selector map"),
5662
+ all: z25.boolean().optional().default(false).describe("Include hidden interactive targets when using interactive snapshot")
5591
5663
  }),
5592
- result: z24.object({
5593
- url: z24.string(),
5594
- title: z24.string(),
5595
- aria: z24.string().optional(),
5596
- text: z24.string().optional(),
5597
- dom: z24.record(z24.unknown()).optional()
5664
+ result: z25.object({
5665
+ url: z25.string(),
5666
+ title: z25.string(),
5667
+ aria: z25.string().optional(),
5668
+ text: z25.string().optional(),
5669
+ dom: z25.record(z25.unknown()).optional()
5598
5670
  }),
5599
5671
  handler: async (p, ctx) => {
5600
5672
  const page = ctx.page;
@@ -5608,7 +5680,7 @@ var snapshotCommand = registerCommand({
5608
5680
  if (p.compact || p.c || p.interactive || p.interactiveOnly || p.i) {
5609
5681
  observation.compact = formatObservationCompact(observation, { selectors: p.selectors });
5610
5682
  }
5611
- return ok23(observation, normalizeTips3([
5683
+ return ok24(observation, normalizeTips3([
5612
5684
  `refs refreshed for ${observation.targets.length} targets; use click @e1 or fill @e2 "text"`
5613
5685
  ]));
5614
5686
  }
@@ -5616,15 +5688,15 @@ var snapshotCommand = registerCommand({
5616
5688
  const aria = await captureAriaSnapshot(page, p.selector, p.depth);
5617
5689
  const tips = await buildRefTips(page, aria);
5618
5690
  persistSemantics(url, aria);
5619
- return ok23({ url, title, aria }, normalizeTips3(tips));
5691
+ return ok24({ url, title, aria }, normalizeTips3(tips));
5620
5692
  }
5621
5693
  if (p.type === "text") {
5622
5694
  const text = await captureTextSnapshot(page, p.selector);
5623
- return ok23({ url, title, text });
5695
+ return ok24({ url, title, text });
5624
5696
  }
5625
5697
  if (p.type === "dom") {
5626
5698
  const dom = await captureDomSnapshot(page, p.selector, p.depth ?? 6);
5627
- return ok23({ url, title, dom });
5699
+ return ok24({ url, title, dom });
5628
5700
  }
5629
5701
  if (p.type === "all") {
5630
5702
  const [aria, text, dom] = await Promise.all([
@@ -5634,9 +5706,9 @@ var snapshotCommand = registerCommand({
5634
5706
  ]);
5635
5707
  const tips = await buildRefTips(page, aria);
5636
5708
  persistSemantics(url, aria);
5637
- return ok23({ url, title, aria, text, dom }, normalizeTips3(tips));
5709
+ return ok24({ url, title, aria, text, dom }, normalizeTips3(tips));
5638
5710
  }
5639
- return fail10(`Unknown snapshot type: ${p.type}`);
5711
+ return fail11(`Unknown snapshot type: ${p.type}`);
5640
5712
  }
5641
5713
  });
5642
5714
  function persistSemantics(url, aria) {
@@ -5713,22 +5785,22 @@ async function captureDomSnapshot(page, selector, maxDepth) {
5713
5785
  }
5714
5786
 
5715
5787
  // src/commands/agent.ts
5716
- import { z as z25 } from "zod";
5717
- import { ok as ok24, normalizeTips as normalizeTips4 } from "@dyyz1993/xcli-core";
5788
+ import { z as z26 } from "zod";
5789
+ import { ok as ok25, normalizeTips as normalizeTips4 } from "@dyyz1993/xcli-core";
5718
5790
  var observeCommand = registerCommand({
5719
5791
  name: "observe",
5720
5792
  description: "Observe the current page as structured agent targets with session refs",
5721
5793
  scope: "page",
5722
- parameters: z25.object({
5723
- includeHidden: z25.boolean().optional().default(false).describe("Include hidden elements in the target list"),
5724
- limit: z25.number().int().positive().max(300).optional().default(80).describe("Maximum number of targets to return"),
5725
- compact: z25.boolean().optional().default(false).describe("Include compact xbrowser style snapshot text"),
5726
- selectors: z25.boolean().optional().default(false).describe("Include ref to stable CSS selector map")
5794
+ parameters: z26.object({
5795
+ includeHidden: z26.boolean().optional().default(false).describe("Include hidden elements in the target list"),
5796
+ limit: z26.number().int().positive().max(300).optional().default(80).describe("Maximum number of targets to return"),
5797
+ compact: z26.boolean().optional().default(false).describe("Include compact xbrowser style snapshot text"),
5798
+ selectors: z26.boolean().optional().default(false).describe("Include ref to stable CSS selector map")
5727
5799
  }),
5728
- result: z25.object({
5729
- targets: z25.array(z25.record(z25.unknown())),
5730
- selectors: z25.record(z25.unknown()).optional(),
5731
- compact: z25.string().optional()
5800
+ result: z26.object({
5801
+ targets: z26.array(z26.record(z26.unknown())),
5802
+ selectors: z26.record(z26.unknown()).optional(),
5803
+ compact: z26.string().optional()
5732
5804
  }).passthrough(),
5733
5805
  handler: async (p, ctx) => {
5734
5806
  const observation = await observePage(ctx.page, ctx.sessionId, {
@@ -5737,7 +5809,7 @@ var observeCommand = registerCommand({
5737
5809
  });
5738
5810
  if (p.selectors) observation.selectors = buildSelectorMap(observation);
5739
5811
  if (p.compact) observation.compact = formatObservationCompact(observation, { selectors: p.selectors });
5740
- return ok24(observation, normalizeTips4([
5812
+ return ok25(observation, normalizeTips4([
5741
5813
  `refs refreshed for ${observation.targets.length} targets; use act --ref @e1 --action click or click @e1`
5742
5814
  ]));
5743
5815
  }
@@ -5747,14 +5819,14 @@ var actCommand = registerCommand({
5747
5819
  description: "Perform an agent action using an observe ref or explicit selector",
5748
5820
  scope: "element",
5749
5821
  selectorParams: ["selector"],
5750
- parameters: z25.object({
5751
- action: z25.enum(["click", "fill", "type", "press", "select", "check", "hover"]).default("click"),
5752
- ref: z25.string().optional().describe("Session-scoped ref returned by observe, such as e1"),
5753
- selector: z25.string().optional().describe("CSS selector fallback when no ref is available"),
5754
- value: z25.string().optional().describe("Value for fill/type/select"),
5755
- key: z25.string().optional().describe("Key for press"),
5756
- force: z25.boolean().optional().default(false).describe("Bypass actionability checks"),
5757
- timeout: z25.number().optional().default(1e4).describe("Playwright action timeout in milliseconds")
5822
+ parameters: z26.object({
5823
+ action: z26.enum(["click", "fill", "type", "press", "select", "check", "hover"]).default("click"),
5824
+ ref: z26.string().optional().describe("Session-scoped ref returned by observe, such as e1"),
5825
+ selector: z26.string().optional().describe("CSS selector fallback when no ref is available"),
5826
+ value: z26.string().optional().describe("Value for fill/type/select"),
5827
+ key: z26.string().optional().describe("Key for press"),
5828
+ force: z26.boolean().optional().default(false).describe("Bypass actionability checks"),
5829
+ timeout: z26.number().optional().default(1e4).describe("Playwright action timeout in milliseconds")
5758
5830
  }).refine((p) => !!p.ref || !!p.selector, {
5759
5831
  message: "Either ref or selector is required"
5760
5832
  }),
@@ -5768,7 +5840,7 @@ var actCommand = registerCommand({
5768
5840
  tips: normalizeTips4(result.stale ? ["run observe again to refresh refs"] : [])
5769
5841
  };
5770
5842
  }
5771
- return ok24(result, normalizeTips4(result.stale ? ["ref screen hash changed; run observe if the next action is uncertain"] : []));
5843
+ return ok25(result, normalizeTips4(result.stale ? ["ref screen hash changed; run observe if the next action is uncertain"] : []));
5772
5844
  }
5773
5845
  });
5774
5846
  var waitForCommand = registerCommand({
@@ -5776,16 +5848,16 @@ var waitForCommand = registerCommand({
5776
5848
  description: "Wait for agent predicates such as text, URL, load state, selector state, or screen hash changes",
5777
5849
  scope: "page",
5778
5850
  selectorParams: ["selector"],
5779
- parameters: z25.object({
5780
- selector: z25.string().optional().describe("CSS selector or observe ref to wait for"),
5781
- state: z25.enum(["attached", "detached", "visible", "hidden"]).optional().default("visible"),
5782
- text: z25.string().optional().describe("Visible text to wait for"),
5783
- url: z25.string().optional().describe("URL substring or glob pattern to wait for"),
5784
- load: z25.enum(["load", "domcontentloaded", "networkidle"]).optional().describe("Load state to wait for"),
5785
- fn: z25.string().optional().describe("JavaScript predicate to wait for"),
5786
- screenHashChanged: z25.string().optional().describe("Previous screenHash from observe"),
5787
- timeout: z25.number().optional().default(3e4),
5788
- pollInterval: z25.number().optional().default(200)
5851
+ parameters: z26.object({
5852
+ selector: z26.string().optional().describe("CSS selector or observe ref to wait for"),
5853
+ state: z26.enum(["attached", "detached", "visible", "hidden"]).optional().default("visible"),
5854
+ text: z26.string().optional().describe("Visible text to wait for"),
5855
+ url: z26.string().optional().describe("URL substring or glob pattern to wait for"),
5856
+ load: z26.enum(["load", "domcontentloaded", "networkidle"]).optional().describe("Load state to wait for"),
5857
+ fn: z26.string().optional().describe("JavaScript predicate to wait for"),
5858
+ screenHashChanged: z26.string().optional().describe("Previous screenHash from observe"),
5859
+ timeout: z26.number().optional().default(3e4),
5860
+ pollInterval: z26.number().optional().default(200)
5789
5861
  }).refine((p) => [p.selector, p.text, p.url, p.load, p.fn, p.screenHashChanged].filter(Boolean).length === 1, {
5790
5862
  message: "Provide exactly one wait predicate: selector, text, url, load, fn, or screenHashChanged"
5791
5863
  }),
@@ -5799,30 +5871,30 @@ var waitForCommand = registerCommand({
5799
5871
  tips: []
5800
5872
  };
5801
5873
  }
5802
- return ok24(result);
5874
+ return ok25(result);
5803
5875
  }
5804
5876
  });
5805
5877
 
5806
5878
  // src/commands/tab.ts
5807
- import { z as z26 } from "zod";
5808
- import { ok as ok25, fail as fail11 } from "@dyyz1993/xcli-core";
5809
- var TabParams = z26.object({
5810
- subcommand: z26.enum(["list", "new", "close", "switch"]),
5811
- url: z26.string().optional(),
5812
- index: z26.number().int().min(0).optional()
5879
+ import { z as z27 } from "zod";
5880
+ import { ok as ok26, fail as fail12 } from "@dyyz1993/xcli-core";
5881
+ var TabParams = z27.object({
5882
+ subcommand: z27.enum(["list", "new", "close", "switch"]),
5883
+ url: z27.string().optional(),
5884
+ index: z27.number().int().min(0).optional()
5813
5885
  });
5814
5886
  var tabCommand = registerCommand({
5815
5887
  name: "tab",
5816
5888
  description: "Manage browser tabs: list, new, close, switch",
5817
5889
  scope: "page",
5818
5890
  parameters: TabParams,
5819
- result: z26.object({
5820
- success: z26.boolean(),
5821
- data: z26.unknown()
5891
+ result: z27.object({
5892
+ success: z27.boolean(),
5893
+ data: z27.unknown()
5822
5894
  }),
5823
5895
  handler: async (p, ctx) => {
5824
5896
  if (!ctx.browserContext) {
5825
- return fail11("No browser context available. Use --cdp to connect to a browser first.");
5897
+ return fail12("No browser context available. Use --cdp to connect to a browser first.");
5826
5898
  }
5827
5899
  const pages = ctx.browserContext.pages();
5828
5900
  switch (p.subcommand) {
@@ -5835,7 +5907,7 @@ var tabCommand = registerCommand({
5835
5907
  case "switch":
5836
5908
  return handleSwitch(p, pages, ctx);
5837
5909
  default:
5838
- return fail11(`Unknown subcommand: ${p.subcommand}`);
5910
+ return fail12(`Unknown subcommand: ${p.subcommand}`);
5839
5911
  }
5840
5912
  }
5841
5913
  });
@@ -5850,7 +5922,7 @@ async function handleList(pages, ctx) {
5850
5922
  if (isActive) activeIndex = i;
5851
5923
  tabs.push({ index: i, url, title, active: isActive });
5852
5924
  }
5853
- return ok25({ tabs, total: tabs.length, activeIndex });
5925
+ return ok26({ tabs, total: tabs.length, activeIndex });
5854
5926
  }
5855
5927
  async function handleNew(p, _pages, ctx) {
5856
5928
  const newPage = await ctx.browserContext.newPage();
@@ -5878,7 +5950,7 @@ async function handleNew(p, _pages, ctx) {
5878
5950
  const title = await newPage.title().catch(() => "");
5879
5951
  const allPages = ctx.browserContext.pages();
5880
5952
  const newIndex = allPages.indexOf(newPage);
5881
- return ok25({
5953
+ return ok26({
5882
5954
  index: newIndex >= 0 ? newIndex : allPages.length - 1,
5883
5955
  url: newPage.url(),
5884
5956
  title,
@@ -5889,11 +5961,11 @@ async function handleNew(p, _pages, ctx) {
5889
5961
  async function handleClose(p, ctx) {
5890
5962
  const currentPages = ctx.browserContext.pages();
5891
5963
  if (currentPages.length <= 1) {
5892
- return fail11("Cannot close the last remaining tab");
5964
+ return fail12("Cannot close the last remaining tab");
5893
5965
  }
5894
5966
  const closeIndex = p.index ?? currentPages.findIndex((pg) => pg === ctx.page);
5895
5967
  if (closeIndex < 0 || closeIndex >= currentPages.length) {
5896
- return fail11(`Invalid tab index: ${closeIndex}. Valid range: 0-${currentPages.length - 1}`);
5968
+ return fail12(`Invalid tab index: ${closeIndex}. Valid range: 0-${currentPages.length - 1}`);
5897
5969
  }
5898
5970
  const pageToClose = currentPages[closeIndex];
5899
5971
  const isActivePage = pageToClose === ctx.page;
@@ -5908,7 +5980,7 @@ async function handleClose(p, ctx) {
5908
5980
  }
5909
5981
  ctx.page = newActivePage;
5910
5982
  }
5911
- return ok25({
5983
+ return ok26({
5912
5984
  closedIndex: closeIndex,
5913
5985
  total: remainingPages.length,
5914
5986
  activeIndex: isActivePage ? closeIndex < remainingPages.length ? closeIndex : remainingPages.length - 1 : remainingPages.findIndex((pg) => pg === ctx.page)
@@ -5916,10 +5988,10 @@ async function handleClose(p, ctx) {
5916
5988
  }
5917
5989
  async function handleSwitch(p, pages, ctx) {
5918
5990
  if (p.index === void 0) {
5919
- return fail11("Parameter --index is required for switch subcommand");
5991
+ return fail12("Parameter --index is required for switch subcommand");
5920
5992
  }
5921
5993
  if (p.index < 0 || p.index >= pages.length) {
5922
- return fail11(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
5994
+ return fail12(`Invalid tab index: ${p.index}. Valid range: 0-${pages.length - 1}`);
5923
5995
  }
5924
5996
  const targetPage = pages[p.index];
5925
5997
  await targetPage.bringToFront().catch(() => {
@@ -5941,7 +6013,7 @@ async function handleSwitch(p, pages, ctx) {
5941
6013
  }
5942
6014
  ctx.page = targetPage;
5943
6015
  const title = await targetPage.title().catch(() => "");
5944
- return ok25({
6016
+ return ok26({
5945
6017
  index: p.index,
5946
6018
  url: targetPage.url(),
5947
6019
  title,
@@ -5950,8 +6022,8 @@ async function handleSwitch(p, pages, ctx) {
5950
6022
  }
5951
6023
 
5952
6024
  // src/commands/addinitscript.ts
5953
- import { z as z27 } from "zod";
5954
- import { ok as ok26 } from "@dyyz1993/xcli-core";
6025
+ import { z as z28 } from "zod";
6026
+ import { ok as ok27 } from "@dyyz1993/xcli-core";
5955
6027
  import { readFileSync as readFileSync4 } from "fs";
5956
6028
 
5957
6029
  // src/chain-parser.ts
@@ -6092,14 +6164,14 @@ registerCommandDefinition("tab", ["subcommand"]);
6092
6164
  registerCommandDefinition("mouse", ["action", "x", "y"]);
6093
6165
 
6094
6166
  // src/commands/addinitscript.ts
6095
- var InitScriptParams = z27.object({
6096
- script: z27.string().optional(),
6097
- file: z27.string().optional(),
6098
- stdin: z27.boolean().optional(),
6099
- name: z27.string().optional(),
6100
- list: z27.boolean().optional(),
6101
- remove: z27.union([z27.string(), z27.boolean()]).optional(),
6102
- base64: z27.string().optional()
6167
+ var InitScriptParams = z28.object({
6168
+ script: z28.string().optional(),
6169
+ file: z28.string().optional(),
6170
+ stdin: z28.boolean().optional(),
6171
+ name: z28.string().optional(),
6172
+ list: z28.boolean().optional(),
6173
+ remove: z28.union([z28.string(), z28.boolean()]).optional(),
6174
+ base64: z28.string().optional()
6103
6175
  });
6104
6176
  var registeredScripts = /* @__PURE__ */ new Map();
6105
6177
  function resolveScriptContent(params) {
@@ -6133,14 +6205,14 @@ var addInitScriptCommand = registerCommand({
6133
6205
  description: "Add an initialization script that runs on every page load",
6134
6206
  scope: "page",
6135
6207
  parameters: InitScriptParams,
6136
- result: z27.object({
6137
- scripts: z27.array(z27.object({ name: z27.string(), size: z27.number(), preview: z27.string() })).optional(),
6138
- removed: z27.string().optional(),
6139
- existed: z27.boolean().optional(),
6140
- error: z27.string().optional(),
6141
- registered: z27.string().optional(),
6142
- hint: z27.string().optional(),
6143
- executedImmediately: z27.boolean().optional()
6208
+ result: z28.object({
6209
+ scripts: z28.array(z28.object({ name: z28.string(), size: z28.number(), preview: z28.string() })).optional(),
6210
+ removed: z28.string().optional(),
6211
+ existed: z28.boolean().optional(),
6212
+ error: z28.string().optional(),
6213
+ registered: z28.string().optional(),
6214
+ hint: z28.string().optional(),
6215
+ executedImmediately: z28.boolean().optional()
6144
6216
  }).passthrough(),
6145
6217
  handler: async (params, ctx) => {
6146
6218
  if (params.list) {
@@ -6149,20 +6221,20 @@ var addInitScriptCommand = registerCommand({
6149
6221
  size: content2.length,
6150
6222
  preview: content2.slice(0, 80)
6151
6223
  }));
6152
- return ok26({ scripts });
6224
+ return ok27({ scripts });
6153
6225
  }
6154
6226
  if (params.remove && typeof params.remove === "string") {
6155
6227
  const existed = registeredScripts.delete(params.remove);
6156
- return ok26({ removed: params.remove, existed });
6228
+ return ok27({ removed: params.remove, existed });
6157
6229
  }
6158
6230
  const removeTarget = (typeof params.remove === "string" ? params.remove : null) || (params.name && !resolveScriptContent(params) ? params.name : null);
6159
6231
  if (removeTarget && !resolveScriptContent(params)) {
6160
6232
  const existed = registeredScripts.delete(removeTarget);
6161
- return ok26({ removed: removeTarget, existed });
6233
+ return ok27({ removed: removeTarget, existed });
6162
6234
  }
6163
6235
  let content = params.stdin ? await readStdin() : resolveScriptContent(params);
6164
6236
  if (!content) {
6165
- return ok26({ error: "No script content provided. Use --script, --file, --stdin, or --base64" });
6237
+ return ok27({ error: "No script content provided. Use --script, --file, --stdin, or --base64" });
6166
6238
  }
6167
6239
  const scriptName = params.name ?? `script-${Date.now()}`;
6168
6240
  registeredScripts.set(scriptName, content);
@@ -6170,45 +6242,45 @@ var addInitScriptCommand = registerCommand({
6170
6242
  try {
6171
6243
  await ctx.page.evaluate(content);
6172
6244
  } catch {
6173
- return ok26({
6245
+ return ok27({
6174
6246
  registered: scriptName,
6175
6247
  hint: "Script registered for future page loads; immediate execution skipped (page may not be ready)"
6176
6248
  });
6177
6249
  }
6178
- return ok26({ registered: scriptName, executedImmediately: true });
6250
+ return ok27({ registered: scriptName, executedImmediately: true });
6179
6251
  }
6180
6252
  });
6181
6253
  registerCommandDefinition("addinitscript", ["script"]);
6182
6254
 
6183
6255
  // src/commands/find.ts
6184
- import { z as z28 } from "zod";
6185
- import { ok as ok27, fail as fail12, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
6186
- var actionSchema2 = z28.enum(["click", "fill", "type", "select", "hover", "check"]);
6256
+ import { z as z29 } from "zod";
6257
+ import { ok as ok28, fail as fail13, normalizeTips as normalizeTips5 } from "@dyyz1993/xcli-core";
6258
+ var actionSchema2 = z29.enum(["click", "fill", "type", "select", "hover", "check"]);
6187
6259
  var findCommand = registerCommand({
6188
6260
  name: "find",
6189
6261
  description: "Find elements by semantic strategy (text/role/label/placeholder/testid) and optionally perform an action",
6190
6262
  scope: "page",
6191
- parameters: z28.object({
6192
- strategy: z28.enum(["text", "role", "label", "placeholder", "testid", "alt", "title", "first", "last", "nth"]),
6193
- value: z28.string(),
6194
- name: z28.string().optional(),
6195
- exact: z28.boolean().optional().default(false),
6196
- operation: z28.string().optional().describe('Trailing operation syntax, e.g. click, fill "text", type "text"'),
6263
+ parameters: z29.object({
6264
+ strategy: z29.enum(["text", "role", "label", "placeholder", "testid", "alt", "title", "first", "last", "nth"]),
6265
+ value: z29.string(),
6266
+ name: z29.string().optional(),
6267
+ exact: z29.boolean().optional().default(false),
6268
+ operation: z29.string().optional().describe('Trailing operation syntax, e.g. click, fill "text", type "text"'),
6197
6269
  action: actionSchema2.optional().describe("Action to perform when not using trailing operation syntax"),
6198
- actionValue: z28.string().optional().describe("Value for fill/type/select when using action"),
6199
- index: z28.number().int().optional().describe("Index for nth strategy"),
6200
- click: z28.boolean().optional().default(false),
6201
- fill: z28.string().optional(),
6202
- type: z28.string().optional(),
6203
- select: z28.string().optional(),
6204
- hover: z28.boolean().optional().default(false),
6205
- check: z28.boolean().optional().default(false),
6206
- timeout: z28.number().optional().default(1e4)
6270
+ actionValue: z29.string().optional().describe("Value for fill/type/select when using action"),
6271
+ index: z29.number().int().optional().describe("Index for nth strategy"),
6272
+ click: z29.boolean().optional().default(false),
6273
+ fill: z29.string().optional(),
6274
+ type: z29.string().optional(),
6275
+ select: z29.string().optional(),
6276
+ hover: z29.boolean().optional().default(false),
6277
+ check: z29.boolean().optional().default(false),
6278
+ timeout: z29.number().optional().default(1e4)
6207
6279
  }),
6208
- result: z28.object({
6209
- matched: z28.number(),
6210
- selector: z28.string(),
6211
- action: z28.string().optional()
6280
+ result: z29.object({
6281
+ matched: z29.number(),
6282
+ selector: z29.string(),
6283
+ action: z29.string().optional()
6212
6284
  }),
6213
6285
  handler: async (p, ctx) => {
6214
6286
  const page = ctx.page;
@@ -6223,7 +6295,7 @@ var findCommand = registerCommand({
6223
6295
  });
6224
6296
  const count = await locator.count();
6225
6297
  if (count === 0) {
6226
- return fail12(`No element found with ${p.strategy}="${p.value}"`);
6298
+ return fail13(`No element found with ${p.strategy}="${p.value}"`);
6227
6299
  }
6228
6300
  const tips = [];
6229
6301
  const target = selectTarget(locator, p.strategy);
@@ -6235,15 +6307,15 @@ var findCommand = registerCommand({
6235
6307
  await target.click({ timeout: p.timeout, force: true });
6236
6308
  return okWithTips({ matched: count, selector, action: "click" }, tips);
6237
6309
  } else if (actionName === "fill") {
6238
- if (actionValue === void 0) return fail12("find fill requires a value");
6310
+ if (actionValue === void 0) return fail13("find fill requires a value");
6239
6311
  await target.fill(actionValue, { timeout: p.timeout, force: true });
6240
6312
  return okWithTips({ matched: count, selector, action: `fill("${actionValue}")` }, tips);
6241
6313
  } else if (actionName === "type") {
6242
- if (actionValue === void 0) return fail12("find type requires a value");
6314
+ if (actionValue === void 0) return fail13("find type requires a value");
6243
6315
  await target.type(actionValue, { delay: 10, timeout: p.timeout });
6244
6316
  return okWithTips({ matched: count, selector, action: `type("${actionValue}")` }, tips);
6245
6317
  } else if (actionName === "select") {
6246
- if (actionValue === void 0) return fail12("find select requires a value");
6318
+ if (actionValue === void 0) return fail13("find select requires a value");
6247
6319
  await target.selectOption(actionValue);
6248
6320
  return okWithTips({ matched: count, selector, action: `select("${actionValue}")` }, tips);
6249
6321
  } else if (actionName === "hover") {
@@ -6257,7 +6329,7 @@ var findCommand = registerCommand({
6257
6329
  }
6258
6330
  });
6259
6331
  function okWithTips(data, tips) {
6260
- const result = ok27(data);
6332
+ const result = ok28(data);
6261
6333
  if (tips.length > 0) result.tips = normalizeTips5(tips);
6262
6334
  return result;
6263
6335
  }
@@ -6356,8 +6428,8 @@ function describeSelector(strategy, value, name) {
6356
6428
  }
6357
6429
 
6358
6430
  // src/commands/visual-tag.ts
6359
- import { z as z29 } from "zod";
6360
- import { ok as ok28, fail as fail13 } from "@dyyz1993/xcli-core";
6431
+ import { z as z30 } from "zod";
6432
+ import { ok as ok29, fail as fail14 } from "@dyyz1993/xcli-core";
6361
6433
  var SAFE_SET = "ahjkmnprtw3479".split("");
6362
6434
  var TAG_SCRIPT = `
6363
6435
  (function() {
@@ -6448,49 +6520,49 @@ var visualTagCommand = registerCommand({
6448
6520
  name: "visual-tag",
6449
6521
  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",
6450
6522
  scope: "page",
6451
- parameters: z29.object({
6452
- action: z29.enum(["tag", "lookup", "clear", "list"]),
6453
- id: z29.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID")
6523
+ parameters: z30.object({
6524
+ action: z30.enum(["tag", "lookup", "clear", "list"]),
6525
+ id: z30.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID")
6454
6526
  }),
6455
- result: z29.object({
6456
- action: z29.string(),
6457
- tagged: z29.number().optional(),
6458
- id: z29.string().optional(),
6459
- element: z29.record(z29.unknown()).optional()
6527
+ result: z30.object({
6528
+ action: z30.string(),
6529
+ tagged: z30.number().optional(),
6530
+ id: z30.string().optional(),
6531
+ element: z30.record(z30.unknown()).optional()
6460
6532
  }),
6461
6533
  handler: async (p, ctx) => {
6462
6534
  switch (p.action) {
6463
6535
  case "tag": {
6464
6536
  const result = await ctx.page.evaluate(TAG_SCRIPT);
6465
6537
  const parsed = JSON.parse(result);
6466
- return ok28({ action: "tag", tagged: parsed.tagged });
6538
+ return ok29({ action: "tag", tagged: parsed.tagged });
6467
6539
  }
6468
6540
  case "lookup": {
6469
- if (!p.id) return fail13("lookup \u9700\u8981 --id \u53C2\u6570");
6541
+ if (!p.id) return fail14("lookup \u9700\u8981 --id \u53C2\u6570");
6470
6542
  const result = await ctx.page.evaluate(
6471
6543
  `(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'}); })()`
6472
6544
  );
6473
6545
  const parsed = JSON.parse(result);
6474
- if (parsed.err) return fail13(`ID ${p.id}: ${parsed.err}`);
6475
- return ok28({ action: "lookup", id: p.id, element: parsed });
6546
+ if (parsed.err) return fail14(`ID ${p.id}: ${parsed.err}`);
6547
+ return ok29({ action: "lookup", id: p.id, element: parsed });
6476
6548
  }
6477
6549
  case "list": {
6478
6550
  const result = await ctx.page.evaluate(
6479
6551
  `(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); })()`
6480
6552
  );
6481
- return ok28({ action: "list", element: JSON.parse(result) });
6553
+ return ok29({ action: "list", element: JSON.parse(result) });
6482
6554
  }
6483
6555
  case "clear": {
6484
6556
  await ctx.page.evaluate(`(function(){var o=document.getElementById('__xb-tag-overlay');if(o)o.remove();window.__xbTagMap=null;return 'cleared'})()`);
6485
- return ok28({ action: "clear" });
6557
+ return ok29({ action: "clear" });
6486
6558
  }
6487
6559
  }
6488
6560
  }
6489
6561
  });
6490
6562
 
6491
6563
  // src/commands/visual-tag-v2.ts
6492
- import { z as z30 } from "zod";
6493
- import { ok as ok29, fail as fail14 } from "@dyyz1993/xcli-core";
6564
+ import { z as z31 } from "zod";
6565
+ import { ok as ok30, fail as fail15 } from "@dyyz1993/xcli-core";
6494
6566
  var SAFE_SET2 = "ahjkmnprtw3479".split("");
6495
6567
  var TAG_V2_SCRIPT = `
6496
6568
  (function() {
@@ -6837,45 +6909,45 @@ var visualTagV2Command = registerCommand({
6837
6909
  name: "visual-tag-v2",
6838
6910
  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",
6839
6911
  scope: "page",
6840
- parameters: z30.object({
6841
- action: z30.enum(["tag", "lookup", "clear", "stats", "by-type", "find", "export", "interact"]),
6842
- id: z30.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID"),
6843
- query: z30.string().optional().describe('find \u65F6\u6307\u5B9A\u641C\u7D22\u8BCD\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09'),
6844
- type: z30.string().optional().describe("by-type \u65F6\u8FC7\u6EE4\u7C7B\u578B\uFF1Aclick/input/img/list/count/text"),
6845
- "interact-action": z30.enum(["click", "fill", "read"]).optional().describe("interact \u52A8\u4F5C\u7C7B\u578B"),
6846
- value: z30.string().optional().describe("fill \u65F6\u7684\u586B\u5145\u503C")
6912
+ parameters: z31.object({
6913
+ action: z31.enum(["tag", "lookup", "clear", "stats", "by-type", "find", "export", "interact"]),
6914
+ id: z31.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID"),
6915
+ query: z31.string().optional().describe('find \u65F6\u6307\u5B9A\u641C\u7D22\u8BCD\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09'),
6916
+ type: z31.string().optional().describe("by-type \u65F6\u8FC7\u6EE4\u7C7B\u578B\uFF1Aclick/input/img/list/count/text"),
6917
+ "interact-action": z31.enum(["click", "fill", "read"]).optional().describe("interact \u52A8\u4F5C\u7C7B\u578B"),
6918
+ value: z31.string().optional().describe("fill \u65F6\u7684\u586B\u5145\u503C")
6847
6919
  }),
6848
- result: z30.object({
6849
- action: z30.string(),
6850
- total: z30.number().optional(),
6851
- byType: z30.record(z30.number()).optional(),
6852
- element: z30.record(z30.unknown()).optional()
6920
+ result: z31.object({
6921
+ action: z31.string(),
6922
+ total: z31.number().optional(),
6923
+ byType: z31.record(z31.number()).optional(),
6924
+ element: z31.record(z31.unknown()).optional()
6853
6925
  }),
6854
6926
  handler: async (p, ctx) => {
6855
6927
  switch (p.action) {
6856
6928
  case "tag": {
6857
6929
  const result = await ctx.page.evaluate(TAG_V2_SCRIPT);
6858
6930
  const parsed = JSON.parse(result);
6859
- return ok29({ action: "tag", total: parsed.total, byType: parsed.byType });
6931
+ return ok30({ action: "tag", total: parsed.total, byType: parsed.byType });
6860
6932
  }
6861
6933
  case "lookup": {
6862
- if (!p.id) return fail14("lookup \u9700\u8981 --id");
6934
+ if (!p.id) return fail15("lookup \u9700\u8981 --id");
6863
6935
  const result = await ctx.page.evaluate(
6864
6936
  `(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'})})()`
6865
6937
  );
6866
6938
  const parsed = JSON.parse(result);
6867
- if (parsed.err) return fail14(`ID ${p.id}: ${parsed.err}`);
6868
- return ok29({ action: "lookup", id: p.id, element: parsed });
6939
+ if (parsed.err) return fail15(`ID ${p.id}: ${parsed.err}`);
6940
+ return ok30({ action: "lookup", id: p.id, element: parsed });
6869
6941
  }
6870
6942
  case "by-type": {
6871
6943
  const result = await ctx.page.evaluate(
6872
6944
  `(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)})()`
6873
6945
  );
6874
- return ok29({ action: "by-type", element: JSON.parse(result) });
6946
+ return ok30({ action: "by-type", element: JSON.parse(result) });
6875
6947
  }
6876
6948
  case "find": {
6877
6949
  const query = p.query;
6878
- if (!query) return fail14('find \u9700\u8981 --query \u53C2\u6570\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09');
6950
+ if (!query) return fail15('find \u9700\u8981 --query \u53C2\u6570\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09');
6879
6951
  const result = await ctx.page.evaluate(
6880
6952
  `(function(){
6881
6953
  var map = window.__xbTagSerializable;
@@ -6917,21 +6989,21 @@ var visualTagV2Command = registerCommand({
6917
6989
  return JSON.stringify({total:results.length, results:results.slice(0,20)});
6918
6990
  })()`
6919
6991
  );
6920
- return ok29({ action: "find", query, element: JSON.parse(result) });
6992
+ return ok30({ action: "find", query, element: JSON.parse(result) });
6921
6993
  }
6922
6994
  case "stats": {
6923
6995
  const result = await ctx.page.evaluate(
6924
6996
  `(function(){return JSON.stringify(window.__xbTagStats||{})})()`
6925
6997
  );
6926
- return ok29({ action: "stats", element: JSON.parse(result) });
6998
+ return ok30({ action: "stats", element: JSON.parse(result) });
6927
6999
  }
6928
7000
  case "interact": {
6929
7001
  const query = p.query;
6930
7002
  const pAny = p;
6931
7003
  const action = pAny["interact-action"] || pAny.interactAction || pAny.interact_action;
6932
7004
  const value = pAny.value;
6933
- if (!query) return fail14("interact \u9700\u8981 --query \u53C2\u6570");
6934
- if (!action) return fail14("interact \u9700\u8981 --interact-action \u53C2\u6570\uFF08click/fill/read\uFF09");
7005
+ if (!query) return fail15("interact \u9700\u8981 --query \u53C2\u6570");
7006
+ if (!action) return fail15("interact \u9700\u8981 --interact-action \u53C2\u6570\uFF08click/fill/read\uFF09");
6935
7007
  const findResult = await ctx.page.evaluate(
6936
7008
  `(function(){
6937
7009
  var map = window.__xbTagSerializable;
@@ -6961,11 +7033,11 @@ var visualTagV2Command = registerCommand({
6961
7033
  })()`
6962
7034
  );
6963
7035
  const parsed = JSON.parse(findResult);
6964
- if (parsed.err) return fail14(parsed.err);
6965
- if (!parsed.total || !parsed.results?.length) return fail14(`\u672A\u627E\u5230\u5339\u914D "${query}" \u7684\u5143\u7D20`);
7036
+ if (parsed.err) return fail15(parsed.err);
7037
+ if (!parsed.total || !parsed.results?.length) return fail15(`\u672A\u627E\u5230\u5339\u914D "${query}" \u7684\u5143\u7D20`);
6966
7038
  const target = parsed.results[0];
6967
7039
  if (action === "read") {
6968
- return ok29({ action: "interact", query, target, result: { read: target.text || target.label } });
7040
+ return ok30({ action: "interact", query, target, result: { read: target.text || target.label } });
6969
7041
  }
6970
7042
  if (action === "click") {
6971
7043
  const el = await ctx.page.evaluate(
@@ -6978,12 +7050,12 @@ var visualTagV2Command = registerCommand({
6978
7050
  return {x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)};
6979
7051
  })()`
6980
7052
  );
6981
- if (!el) return fail14(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7053
+ if (!el) return fail15(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
6982
7054
  await ctx.page.mouse.click(el.x, el.y, { stealth: true });
6983
- return ok29({ action: "interact", query, target, result: { clicked: true, x: el.x, y: el.y } });
7055
+ return ok30({ action: "interact", query, target, result: { clicked: true, x: el.x, y: el.y } });
6984
7056
  }
6985
7057
  if (action === "fill") {
6986
- if (!value) return fail14("fill \u9700\u8981 --value \u53C2\u6570");
7058
+ if (!value) return fail15("fill \u9700\u8981 --value \u53C2\u6570");
6987
7059
  const el = await ctx.page.evaluate(
6988
7060
  `(function(){
6989
7061
  var map = window.__xbTagMap;
@@ -6994,12 +7066,12 @@ var visualTagV2Command = registerCommand({
6994
7066
  return {x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)};
6995
7067
  })()`
6996
7068
  );
6997
- if (!el) return fail14(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
7069
+ if (!el) return fail15(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
6998
7070
  await ctx.page.mouse.click(el.x, el.y, { stealth: true });
6999
7071
  await ctx.page.keyboard.type(value, { stealth: true });
7000
- return ok29({ action: "interact", query, target, result: { filled: true, value } });
7072
+ return ok30({ action: "interact", query, target, result: { filled: true, value } });
7001
7073
  }
7002
- return fail14(`\u672A\u77E5 action: ${action}`);
7074
+ return fail15(`\u672A\u77E5 action: ${action}`);
7003
7075
  }
7004
7076
  case "export": {
7005
7077
  const result = await ctx.page.evaluate(
@@ -7047,12 +7119,12 @@ var visualTagV2Command = registerCommand({
7047
7119
  })()`
7048
7120
  );
7049
7121
  const parsed = JSON.parse(result);
7050
- if (parsed.err) return fail14(String(parsed.err));
7051
- return ok29({ action: "export", element: parsed });
7122
+ if (parsed.err) return fail15(String(parsed.err));
7123
+ return ok30({ action: "export", element: parsed });
7052
7124
  }
7053
7125
  case "clear": {
7054
7126
  await ctx.page.evaluate(`(function(){var o=document.getElementById('__xb-tag-overlay');if(o)o.remove();window.__xbTagMap=null;window.__xbTagStats=null;return 'ok'})()`);
7055
- return ok29({ action: "clear" });
7127
+ return ok30({ action: "clear" });
7056
7128
  }
7057
7129
  }
7058
7130
  }
@@ -7722,7 +7794,7 @@ async function guardCheck(commandName) {
7722
7794
  }
7723
7795
  }
7724
7796
  function errorResult(message) {
7725
- return { ...fail15(message), duration: 0 };
7797
+ return { ...fail16(message), duration: 0 };
7726
7798
  }
7727
7799
  function tipsToMessages(tips) {
7728
7800
  if (!tips || tips.length === 0) return [];
@@ -7995,7 +8067,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
7995
8067
  timestamp: start
7996
8068
  });
7997
8069
  if (isSuccess) {
7998
- return { ...ok30(raw.data, merged.length > 0 ? merged : raw.tips), duration, ...hookOutputs ? { hookOutputs } : {} };
8070
+ return { ...ok31(raw.data, merged.length > 0 ? merged : raw.tips), duration, ...hookOutputs ? { hookOutputs } : {} };
7999
8071
  }
8000
8072
  const fc = classifyFailure(raw.message);
8001
8073
  return {
@@ -8018,7 +8090,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8018
8090
  duration,
8019
8091
  timestamp: start
8020
8092
  });
8021
- return { ...ok30(raw, smartTipNormalized), duration, ...hookOutputs ? { hookOutputs } : {} };
8093
+ return { ...ok31(raw, smartTipNormalized), duration, ...hookOutputs ? { hookOutputs } : {} };
8022
8094
  } catch (err) {
8023
8095
  const end = Date.now();
8024
8096
  const duration = end - start;
@@ -8063,7 +8135,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
8063
8135
  duration,
8064
8136
  timestamp: start
8065
8137
  });
8066
- return { ...fail15(errorMessage), duration };
8138
+ return { ...fail16(errorMessage), duration };
8067
8139
  } finally {
8068
8140
  }
8069
8141
  }
@@ -8108,7 +8180,7 @@ async function executeChain(input, options) {
8108
8180
  results.push({
8109
8181
  command: cmdName,
8110
8182
  raw: cmdStr,
8111
- ...fail15(`Plugin "${cmdName}" requires a sub-command`),
8183
+ ...fail16(`Plugin "${cmdName}" requires a sub-command`),
8112
8184
  duration: 0
8113
8185
  });
8114
8186
  if (type === "and") {
@@ -8127,7 +8199,7 @@ async function executeChain(input, options) {
8127
8199
  results.push({
8128
8200
  command: cmdName,
8129
8201
  raw: cmdStr,
8130
- ...fail15(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
8202
+ ...fail16(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
8131
8203
  duration: 0
8132
8204
  });
8133
8205
  if (type === "and") {
@@ -8239,7 +8311,7 @@ async function executeChain(input, options) {
8239
8311
  results.push({
8240
8312
  command: `${cmdName} ${subCommand}`,
8241
8313
  raw: cmdStr,
8242
- ...ok30(data),
8314
+ ...ok31(data),
8243
8315
  duration: duration2,
8244
8316
  ...hookOutputs ? { hookOutputs } : {}
8245
8317
  });
@@ -8267,7 +8339,7 @@ async function executeChain(input, options) {
8267
8339
  results.push({
8268
8340
  command: `${cmdName} ${subCommand}`,
8269
8341
  raw: cmdStr,
8270
- ...fail15(errorMessage),
8342
+ ...fail16(errorMessage),
8271
8343
  duration: duration2
8272
8344
  });
8273
8345
  if (type === "and") {
@@ -9691,10 +9763,10 @@ function createRPCHandler() {
9691
9763
  const errors = Array.isArray(input.errors) ? input.errors : [];
9692
9764
  const eventsPlayed = typeof input.eventsPlayed === "number" ? input.eventsPlayed : 0;
9693
9765
  const totalEvents = typeof input.totalEvents === "number" ? input.totalEvents : eventsPlayed + errors.length;
9694
- const ok31 = input.ok ?? errors.length === 0;
9766
+ const ok32 = input.ok ?? errors.length === 0;
9695
9767
  return {
9696
- ok: ok31,
9697
- success: ok31,
9768
+ ok: ok32,
9769
+ success: ok32,
9698
9770
  duration: typeof input.duration === "number" ? input.duration : 0,
9699
9771
  eventsPlayed,
9700
9772
  totalEvents,