@react-grab/cli 0.1.0-beta.8 → 0.1.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -19
- package/dist/cli.cjs +211 -101
- package/dist/cli.js +211 -101
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -136,18 +136,18 @@ var MCP_CLIENTS = [
|
|
|
136
136
|
// "claude",
|
|
137
137
|
];
|
|
138
138
|
var MCP_CLIENT_NAMES = {
|
|
139
|
-
|
|
139
|
+
cursor: "Cursor",
|
|
140
140
|
"claude-code": "Claude Code",
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
vscode: "VSCode",
|
|
142
|
+
opencode: "OpenCode",
|
|
143
|
+
codex: "Codex",
|
|
144
144
|
"gemini-cli": "Gemini CLI",
|
|
145
145
|
// "cline": "Cline",
|
|
146
146
|
// "roo-cline": "Roo Cline",
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
windsurf: "Windsurf",
|
|
148
|
+
zed: "Zed",
|
|
149
149
|
// "warp": "Warp",
|
|
150
|
-
|
|
150
|
+
droid: "Droid"
|
|
151
151
|
// "claude": "Claude Desktop",
|
|
152
152
|
};
|
|
153
153
|
var SKILL_AGENTS = [
|
|
@@ -1267,7 +1267,9 @@ var findSkillAgent = (id) => {
|
|
|
1267
1267
|
};
|
|
1268
1268
|
var formatInstalledAgentNames = (agents) => agents.map((agent) => AGENT_NAMES[agent] ?? agent).join(", ");
|
|
1269
1269
|
var applyTransformWithFeedback = (result, message) => {
|
|
1270
|
-
const writeSpinner = spinner(
|
|
1270
|
+
const writeSpinner = spinner(
|
|
1271
|
+
message ?? `Applying changes to ${result.filePath}.`
|
|
1272
|
+
).start();
|
|
1271
1273
|
const writeResult = applyTransform(result);
|
|
1272
1274
|
if (!writeResult.success) {
|
|
1273
1275
|
writeSpinner.fail();
|
|
@@ -1279,7 +1281,9 @@ var applyTransformWithFeedback = (result, message) => {
|
|
|
1279
1281
|
writeSpinner.succeed();
|
|
1280
1282
|
};
|
|
1281
1283
|
var applyPackageJsonWithFeedback = (result, message) => {
|
|
1282
|
-
const writeSpinner = spinner(
|
|
1284
|
+
const writeSpinner = spinner(
|
|
1285
|
+
message ?? `Applying changes to ${result.filePath}.`
|
|
1286
|
+
).start();
|
|
1283
1287
|
const writeResult = applyPackageJsonTransform(result);
|
|
1284
1288
|
if (!writeResult.success) {
|
|
1285
1289
|
writeSpinner.fail();
|
|
@@ -1711,21 +1715,29 @@ ${BOLD}File: ${filePath}${RESET}`);
|
|
|
1711
1715
|
console.log(formatDiff(diff));
|
|
1712
1716
|
console.log("\u2500".repeat(60));
|
|
1713
1717
|
};
|
|
1714
|
-
var VERSION = "0.1.0-beta.
|
|
1718
|
+
var VERSION = "0.1.0-beta.8";
|
|
1715
1719
|
var configureMcp = (mcpClient, cwd, customPkg) => {
|
|
1716
|
-
const mcpCommand = customPkg ? `npx -y ${customPkg} browser mcp` : `npx -y
|
|
1717
|
-
const mcpSpinner = spinner(
|
|
1720
|
+
const mcpCommand = customPkg ? `npx -y ${customPkg} browser mcp` : `npx -y grab browser mcp`;
|
|
1721
|
+
const mcpSpinner = spinner(
|
|
1722
|
+
`Installing MCP server for ${MCP_CLIENT_NAMES[mcpClient]}`
|
|
1723
|
+
).start();
|
|
1718
1724
|
try {
|
|
1719
|
-
child_process.execSync(
|
|
1720
|
-
|
|
1721
|
-
|
|
1725
|
+
child_process.execSync(`npx -y install-mcp '${mcpCommand}' --client ${mcpClient} --yes`, {
|
|
1726
|
+
stdio: "ignore",
|
|
1727
|
+
cwd
|
|
1728
|
+
});
|
|
1729
|
+
mcpSpinner.succeed(
|
|
1730
|
+
`MCP server installed for ${MCP_CLIENT_NAMES[mcpClient]}`
|
|
1722
1731
|
);
|
|
1723
|
-
mcpSpinner.succeed(`MCP server installed for ${MCP_CLIENT_NAMES[mcpClient]}`);
|
|
1724
1732
|
logger.break();
|
|
1725
1733
|
process.exit(0);
|
|
1726
1734
|
} catch {
|
|
1727
|
-
mcpSpinner.fail(
|
|
1728
|
-
|
|
1735
|
+
mcpSpinner.fail(
|
|
1736
|
+
`Failed to configure MCP for ${MCP_CLIENT_NAMES[mcpClient]}`
|
|
1737
|
+
);
|
|
1738
|
+
logger.dim(
|
|
1739
|
+
`Try manually: npx -y install-mcp '${mcpCommand}' --client ${mcpClient}`
|
|
1740
|
+
);
|
|
1729
1741
|
logger.break();
|
|
1730
1742
|
process.exit(1);
|
|
1731
1743
|
}
|
|
@@ -1743,21 +1755,17 @@ var installSkill = (agent, cwd) => {
|
|
|
1743
1755
|
process.exit(0);
|
|
1744
1756
|
} catch {
|
|
1745
1757
|
skillSpinner.fail(`Failed to install skill for ${agent.name}`);
|
|
1746
|
-
logger.warn(
|
|
1758
|
+
logger.warn(
|
|
1759
|
+
`Try manually: npx -y add-skill aidenybai/react-grab --agent ${agent.id}`
|
|
1760
|
+
);
|
|
1747
1761
|
logger.break();
|
|
1748
1762
|
process.exit(1);
|
|
1749
1763
|
}
|
|
1750
1764
|
};
|
|
1751
|
-
var add = new commander.Command().name("add").alias("install").description("add browser automation for your AI agent").argument(
|
|
1752
|
-
"[agent]",
|
|
1753
|
-
`agent to add (${AGENTS.join(", ")}, mcp, skill)`
|
|
1754
|
-
).option("-y, --yes", "skip confirmation prompts", false).option(
|
|
1765
|
+
var add = new commander.Command().name("add").alias("install").description("add browser automation for your AI agent").argument("[agent]", `agent to add (${AGENTS.join(", ")}, mcp, skill)`).option("-y, --yes", "skip confirmation prompts", false).option(
|
|
1755
1766
|
"--client <client>",
|
|
1756
1767
|
"MCP client to configure (cursor, claude-code, vscode, etc.)"
|
|
1757
|
-
).option(
|
|
1758
|
-
"--pkg <pkg>",
|
|
1759
|
-
"custom package URL for CLI (e.g., @react-grab/cli)"
|
|
1760
|
-
).option(
|
|
1768
|
+
).option("--pkg <pkg>", "custom package URL for CLI (e.g., grab)").option(
|
|
1761
1769
|
"-c, --cwd <cwd>",
|
|
1762
1770
|
"working directory (defaults to current directory)",
|
|
1763
1771
|
process.cwd()
|
|
@@ -1814,7 +1822,9 @@ var add = new commander.Command().name("add").alias("install").description("add
|
|
|
1814
1822
|
if (clientArg && !selectedAgent) {
|
|
1815
1823
|
logger.break();
|
|
1816
1824
|
logger.error(`Invalid skill agent: ${clientArg}`);
|
|
1817
|
-
logger.error(
|
|
1825
|
+
logger.error(
|
|
1826
|
+
`Available agents: ${SKILL_AGENTS.map((a) => a.id).join(", ")}`
|
|
1827
|
+
);
|
|
1818
1828
|
logger.break();
|
|
1819
1829
|
process.exit(1);
|
|
1820
1830
|
}
|
|
@@ -1822,7 +1832,9 @@ var add = new commander.Command().name("add").alias("install").description("add
|
|
|
1822
1832
|
if (detectedAgents.length === 0) {
|
|
1823
1833
|
logger.break();
|
|
1824
1834
|
logger.warn("No supported agent folders detected.");
|
|
1825
|
-
logger.log(
|
|
1835
|
+
logger.log(
|
|
1836
|
+
"Supported agents: " + SKILL_AGENTS.map((a) => a.id).join(", ")
|
|
1837
|
+
);
|
|
1826
1838
|
logger.break();
|
|
1827
1839
|
process.exit(0);
|
|
1828
1840
|
}
|
|
@@ -1848,7 +1860,9 @@ var add = new commander.Command().name("add").alias("install").description("add
|
|
|
1848
1860
|
if (!selectedAgent) {
|
|
1849
1861
|
logger.break();
|
|
1850
1862
|
logger.error("Please specify an agent with --client");
|
|
1851
|
-
logger.error(
|
|
1863
|
+
logger.error(
|
|
1864
|
+
`Available agents: ${SKILL_AGENTS.map((a) => a.id).join(", ")}`
|
|
1865
|
+
);
|
|
1852
1866
|
logger.break();
|
|
1853
1867
|
process.exit(1);
|
|
1854
1868
|
}
|
|
@@ -1896,14 +1910,20 @@ var add = new commander.Command().name("add").alias("install").description("add
|
|
|
1896
1910
|
logger.break();
|
|
1897
1911
|
process.exit(1);
|
|
1898
1912
|
}
|
|
1899
|
-
configureMcp(
|
|
1913
|
+
configureMcp(
|
|
1914
|
+
client,
|
|
1915
|
+
cwd,
|
|
1916
|
+
opts2.pkg
|
|
1917
|
+
);
|
|
1900
1918
|
}
|
|
1901
1919
|
if (addType === "skill") {
|
|
1902
1920
|
const detectedAgents = detectSkillAgents(cwd);
|
|
1903
1921
|
if (detectedAgents.length === 0) {
|
|
1904
1922
|
logger.break();
|
|
1905
1923
|
logger.warn("No supported agent folders detected.");
|
|
1906
|
-
logger.log(
|
|
1924
|
+
logger.log(
|
|
1925
|
+
"Supported agents: " + SKILL_AGENTS.map((a) => a.id).join(", ")
|
|
1926
|
+
);
|
|
1907
1927
|
logger.break();
|
|
1908
1928
|
process.exit(0);
|
|
1909
1929
|
}
|
|
@@ -2460,9 +2480,14 @@ var createComponentHelper = (getActivePage2) => {
|
|
|
2460
2480
|
async (args) => {
|
|
2461
2481
|
const g2 = globalThis;
|
|
2462
2482
|
if (!g2.__REACT_GRAB_FIND_BY_COMPONENT__) {
|
|
2463
|
-
throw new Error(
|
|
2483
|
+
throw new Error(
|
|
2484
|
+
"React introspection not available. Make sure react-grab is installed."
|
|
2485
|
+
);
|
|
2464
2486
|
}
|
|
2465
|
-
const result = await g2.__REACT_GRAB_FIND_BY_COMPONENT__(
|
|
2487
|
+
const result = await g2.__REACT_GRAB_FIND_BY_COMPONENT__(
|
|
2488
|
+
args.name,
|
|
2489
|
+
args.nth !== void 0 ? { nth: args.nth } : void 0
|
|
2490
|
+
);
|
|
2466
2491
|
if (!result) return null;
|
|
2467
2492
|
if (args.nth !== void 0) {
|
|
2468
2493
|
const single = result;
|
|
@@ -2473,7 +2498,10 @@ var createComponentHelper = (getActivePage2) => {
|
|
|
2473
2498
|
},
|
|
2474
2499
|
{ name: componentName, nth }
|
|
2475
2500
|
);
|
|
2476
|
-
const isNull = await currentPage2.evaluate(
|
|
2501
|
+
const isNull = await currentPage2.evaluate(
|
|
2502
|
+
(value) => value === null,
|
|
2503
|
+
elementHandles
|
|
2504
|
+
);
|
|
2477
2505
|
if (isNull) {
|
|
2478
2506
|
await elementHandles.dispose();
|
|
2479
2507
|
return null;
|
|
@@ -2521,7 +2549,8 @@ var createDragHelper = (getActivePage2) => {
|
|
|
2521
2549
|
}) => {
|
|
2522
2550
|
const fromElement = document.querySelector(fromSel);
|
|
2523
2551
|
const toElement = document.querySelector(toSel);
|
|
2524
|
-
if (!fromElement)
|
|
2552
|
+
if (!fromElement)
|
|
2553
|
+
throw new Error(`Source element not found: ${fromSel}`);
|
|
2525
2554
|
if (!toElement) throw new Error(`Target element not found: ${toSel}`);
|
|
2526
2555
|
const dataTransferObject = new DataTransfer();
|
|
2527
2556
|
for (const [type, value] of Object.entries(data)) {
|
|
@@ -2583,16 +2612,26 @@ var createDispatchHelper = (getActivePage2) => {
|
|
|
2583
2612
|
for (const [type, value] of Object.entries(opts2.dataTransfer)) {
|
|
2584
2613
|
dataTransferObject.setData(type, value);
|
|
2585
2614
|
}
|
|
2586
|
-
return new DragEvent(eventType, {
|
|
2615
|
+
return new DragEvent(eventType, {
|
|
2616
|
+
...baseOpts,
|
|
2617
|
+
dataTransfer: dataTransferObject
|
|
2618
|
+
});
|
|
2587
2619
|
}
|
|
2588
2620
|
if (opts2.detail !== void 0) {
|
|
2589
|
-
return new CustomEvent(eventType, {
|
|
2621
|
+
return new CustomEvent(eventType, {
|
|
2622
|
+
...baseOpts,
|
|
2623
|
+
detail: opts2.detail
|
|
2624
|
+
});
|
|
2590
2625
|
}
|
|
2591
2626
|
return new Event(eventType, baseOpts);
|
|
2592
2627
|
};
|
|
2593
2628
|
return element.dispatchEvent(createEvent());
|
|
2594
2629
|
},
|
|
2595
|
-
{
|
|
2630
|
+
{
|
|
2631
|
+
sel: selector,
|
|
2632
|
+
eventType: event,
|
|
2633
|
+
opts: { bubbles, cancelable, dataTransfer, detail }
|
|
2634
|
+
}
|
|
2596
2635
|
);
|
|
2597
2636
|
};
|
|
2598
2637
|
};
|
|
@@ -2641,11 +2680,16 @@ var createWaitForHelper = (getActivePage2) => {
|
|
|
2641
2680
|
const currentPage2 = getActivePage2();
|
|
2642
2681
|
const timeout = options2?.timeout;
|
|
2643
2682
|
if (LOAD_STATES.has(selectorOrState)) {
|
|
2644
|
-
await currentPage2.waitForLoadState(
|
|
2683
|
+
await currentPage2.waitForLoadState(
|
|
2684
|
+
selectorOrState,
|
|
2685
|
+
{ timeout }
|
|
2686
|
+
);
|
|
2645
2687
|
return;
|
|
2646
2688
|
}
|
|
2647
2689
|
if (/^e\d+$/.test(selectorOrState)) {
|
|
2648
|
-
await currentPage2.waitForSelector(`[aria-ref="${selectorOrState}"]`, {
|
|
2690
|
+
await currentPage2.waitForSelector(`[aria-ref="${selectorOrState}"]`, {
|
|
2691
|
+
timeout
|
|
2692
|
+
});
|
|
2649
2693
|
return;
|
|
2650
2694
|
}
|
|
2651
2695
|
await currentPage2.waitForSelector(selectorOrState, { timeout });
|
|
@@ -16482,7 +16526,9 @@ After getting refs, use browser_execute with: getRef('e1').click()`,
|
|
|
16482
16526
|
screenshot: external_exports.boolean().optional().default(false).describe(
|
|
16483
16527
|
"Viewport screenshot. For element screenshots (PREFERRED), use browser_execute: getRef('eX').screenshot()"
|
|
16484
16528
|
),
|
|
16485
|
-
reactTree: external_exports.boolean().optional().default(false).describe(
|
|
16529
|
+
reactTree: external_exports.boolean().optional().default(false).describe(
|
|
16530
|
+
"(Experimental) React tree view. Note: Regular snapshot already includes [component=X] and [source=X] - prefer that."
|
|
16531
|
+
),
|
|
16486
16532
|
includeProps: external_exports.boolean().optional().default(false).describe("Include props when reactTree=true")
|
|
16487
16533
|
}
|
|
16488
16534
|
},
|
|
@@ -16511,7 +16557,10 @@ After getting refs, use browser_execute with: getRef('e1').click()`,
|
|
|
16511
16557
|
}
|
|
16512
16558
|
return g2.__REACT_GRAB_GET_COMPONENT_TREE__(opts2);
|
|
16513
16559
|
},
|
|
16514
|
-
{
|
|
16560
|
+
{
|
|
16561
|
+
maxDepth: maxDepth ?? DEFAULT_COMPONENT_TREE_MAX_DEPTH,
|
|
16562
|
+
includeProps: includeProps ?? false
|
|
16563
|
+
}
|
|
16515
16564
|
);
|
|
16516
16565
|
const renderTree = (nodes) => {
|
|
16517
16566
|
const lines = [];
|
|
@@ -16532,7 +16581,9 @@ After getting refs, use browser_execute with: getRef('e1').click()`,
|
|
|
16532
16581
|
};
|
|
16533
16582
|
textResult = renderTree(componentTree) || "No React components found. Make sure react-grab is installed and the page uses React.";
|
|
16534
16583
|
} else {
|
|
16535
|
-
textResult = await createSnapshotHelper(() => activePage)({
|
|
16584
|
+
textResult = await createSnapshotHelper(() => activePage)({
|
|
16585
|
+
maxDepth
|
|
16586
|
+
});
|
|
16536
16587
|
}
|
|
16537
16588
|
if (screenshot) {
|
|
16538
16589
|
const screenshotBuffer = await activePage.screenshot({
|
|
@@ -16700,7 +16751,7 @@ PERFORMANCE: Batch multiple actions in one execute call.`,
|
|
|
16700
16751
|
};
|
|
16701
16752
|
|
|
16702
16753
|
// src/commands/browser.ts
|
|
16703
|
-
var VERSION2 = "0.1.0-beta.
|
|
16754
|
+
var VERSION2 = "0.1.0-beta.8";
|
|
16704
16755
|
var printHeader = () => {
|
|
16705
16756
|
console.log(
|
|
16706
16757
|
`${pc__default.default.magenta("\u273F")} ${pc__default.default.bold("React Grab")} ${pc__default.default.gray(VERSION2)}`
|
|
@@ -16766,7 +16817,10 @@ var dump = new commander.Command().name("dump").description("dump cookies from a
|
|
|
16766
16817
|
exitWithError(error48);
|
|
16767
16818
|
}
|
|
16768
16819
|
});
|
|
16769
|
-
var start = new commander.Command().name("start").description("start browser server manually (auto-starts on first execute)").option("-p, --port <port>", "HTTP API port", String(browser$1.DEFAULT_SERVER_PORT)).option("--headed", "show browser window (default is headless)").option(
|
|
16820
|
+
var start = new commander.Command().name("start").description("start browser server manually (auto-starts on first execute)").option("-p, --port <port>", "HTTP API port", String(browser$1.DEFAULT_SERVER_PORT)).option("--headed", "show browser window (default is headless)").option(
|
|
16821
|
+
"-b, --browser <browser>",
|
|
16822
|
+
"source browser for cookies (chrome, edge, brave, arc)"
|
|
16823
|
+
).option("-d, --domain <domain>", "only load cookies matching this domain").option("--foreground", "run in foreground instead of detaching").action(async (options2) => {
|
|
16770
16824
|
const isForeground = options2.foreground;
|
|
16771
16825
|
if (!isForeground) {
|
|
16772
16826
|
printHeader();
|
|
@@ -16826,7 +16880,9 @@ var start = new commander.Command().name("start").description("start browser ser
|
|
|
16826
16880
|
await new Promise(() => {
|
|
16827
16881
|
});
|
|
16828
16882
|
} catch (error48) {
|
|
16829
|
-
console.error(
|
|
16883
|
+
console.error(
|
|
16884
|
+
error48 instanceof Error ? error48.message : "Failed to start server"
|
|
16885
|
+
);
|
|
16830
16886
|
process.exit(1);
|
|
16831
16887
|
}
|
|
16832
16888
|
});
|
|
@@ -16853,17 +16909,21 @@ var status = new commander.Command().name("status").description("check server st
|
|
|
16853
16909
|
const info = browser$1.getServerInfo();
|
|
16854
16910
|
let pagesData = [];
|
|
16855
16911
|
try {
|
|
16856
|
-
const pagesResponse = await fetch(
|
|
16912
|
+
const pagesResponse = await fetch(
|
|
16913
|
+
`http://127.0.0.1:${info?.port}/pages`
|
|
16914
|
+
);
|
|
16857
16915
|
const pagesResult = await pagesResponse.json();
|
|
16858
16916
|
pagesData = pagesResult.pages;
|
|
16859
16917
|
} catch {
|
|
16860
16918
|
}
|
|
16861
16919
|
if (jsonMode) {
|
|
16862
|
-
console.log(
|
|
16863
|
-
|
|
16864
|
-
|
|
16865
|
-
|
|
16866
|
-
|
|
16920
|
+
console.log(
|
|
16921
|
+
JSON.stringify({
|
|
16922
|
+
running: true,
|
|
16923
|
+
port: info?.port,
|
|
16924
|
+
pages: pagesData
|
|
16925
|
+
})
|
|
16926
|
+
);
|
|
16867
16927
|
} else {
|
|
16868
16928
|
logger.success(`Server running on port ${info?.port}`);
|
|
16869
16929
|
if (pagesData.length > 0) {
|
|
@@ -16876,17 +16936,30 @@ var status = new commander.Command().name("status").description("check server st
|
|
|
16876
16936
|
}
|
|
16877
16937
|
} else {
|
|
16878
16938
|
if (jsonMode) {
|
|
16879
|
-
console.log(
|
|
16880
|
-
|
|
16881
|
-
|
|
16882
|
-
|
|
16883
|
-
|
|
16939
|
+
console.log(
|
|
16940
|
+
JSON.stringify({
|
|
16941
|
+
running: false,
|
|
16942
|
+
port: null,
|
|
16943
|
+
pages: []
|
|
16944
|
+
})
|
|
16945
|
+
);
|
|
16884
16946
|
} else {
|
|
16885
16947
|
logger.log("Server not running");
|
|
16886
16948
|
}
|
|
16887
16949
|
}
|
|
16888
16950
|
});
|
|
16889
|
-
var execute = new commander.Command().name("execute").description("run Playwright code with 'page' variable available").argument(
|
|
16951
|
+
var execute = new commander.Command().name("execute").description("run Playwright code with 'page' variable available").argument(
|
|
16952
|
+
"<code>",
|
|
16953
|
+
"JavaScript code to execute (use 'page' for Playwright Page, 'return' for output)"
|
|
16954
|
+
).option("-b, --browser <browser>", "source browser for cookies").option("-d, --domain <domain>", "filter cookies by domain").option("-u, --url <url>", "navigate to URL before executing").option(
|
|
16955
|
+
"-p, --page <name>",
|
|
16956
|
+
"named page context for multi-turn sessions",
|
|
16957
|
+
"default"
|
|
16958
|
+
).option(
|
|
16959
|
+
"-t, --timeout <ms>",
|
|
16960
|
+
`navigation timeout in milliseconds (default: ${browser$1.DEFAULT_NAVIGATION_TIMEOUT_MS})`,
|
|
16961
|
+
String(browser$1.DEFAULT_NAVIGATION_TIMEOUT_MS)
|
|
16962
|
+
).action(async (code, options2) => {
|
|
16890
16963
|
const pageName = options2.page;
|
|
16891
16964
|
const navigationTimeout = parseInt(options2.timeout, 10);
|
|
16892
16965
|
let activePage = null;
|
|
@@ -16952,7 +17025,15 @@ var execute = new commander.Command().name("execute").description("run Playwrigh
|
|
|
16952
17025
|
);
|
|
16953
17026
|
console.log(JSON.stringify(await outputJson(true, result)));
|
|
16954
17027
|
} catch (error48) {
|
|
16955
|
-
console.log(
|
|
17028
|
+
console.log(
|
|
17029
|
+
JSON.stringify(
|
|
17030
|
+
await outputJson(
|
|
17031
|
+
false,
|
|
17032
|
+
void 0,
|
|
17033
|
+
error48 instanceof Error ? error48.message : "Failed"
|
|
17034
|
+
)
|
|
17035
|
+
)
|
|
17036
|
+
);
|
|
16956
17037
|
exitCode = 1;
|
|
16957
17038
|
} finally {
|
|
16958
17039
|
if (activePage && pageOpenHandler) {
|
|
@@ -16974,13 +17055,19 @@ var pages = new commander.Command().name("pages").description("manage server pag
|
|
|
16974
17055
|
const pagesResponse2 = await fetch(`${serverUrl}/pages`);
|
|
16975
17056
|
const pagesResult2 = await pagesResponse2.json();
|
|
16976
17057
|
for (const pageEntry of pagesResult2.pages) {
|
|
16977
|
-
await fetch(
|
|
17058
|
+
await fetch(
|
|
17059
|
+
`${serverUrl}/pages/${encodeURIComponent(pageEntry.name)}`,
|
|
17060
|
+
{ method: "DELETE" }
|
|
17061
|
+
);
|
|
16978
17062
|
logger.success(`Unregistered ${pageEntry.name}`);
|
|
16979
17063
|
}
|
|
16980
17064
|
return;
|
|
16981
17065
|
}
|
|
16982
17066
|
if (options2.kill) {
|
|
16983
|
-
const deleteResponse = await fetch(
|
|
17067
|
+
const deleteResponse = await fetch(
|
|
17068
|
+
`${serverUrl}/pages/${encodeURIComponent(options2.kill)}`,
|
|
17069
|
+
{ method: "DELETE" }
|
|
17070
|
+
);
|
|
16984
17071
|
if (deleteResponse.ok) {
|
|
16985
17072
|
logger.success(`Unregistered ${options2.kill}`);
|
|
16986
17073
|
} else {
|
|
@@ -17120,7 +17207,9 @@ MULTI-PAGE SESSIONS
|
|
|
17120
17207
|
|
|
17121
17208
|
PLAYWRIGHT DOCS: https://playwright.dev/docs/api/class-page
|
|
17122
17209
|
`;
|
|
17123
|
-
var browser = new commander.Command().name("browser").description(
|
|
17210
|
+
var browser = new commander.Command().name("browser").description(
|
|
17211
|
+
"browser automation with persistent page state and real cookie injection"
|
|
17212
|
+
).addHelpText("after", BROWSER_HELP).action(() => {
|
|
17124
17213
|
browser.help();
|
|
17125
17214
|
});
|
|
17126
17215
|
var mcp = new commander.Command().name("mcp").description("start MCP server for browser automation (stdio transport)").action(async () => {
|
|
@@ -17170,7 +17259,7 @@ browser.addCommand(status);
|
|
|
17170
17259
|
browser.addCommand(execute);
|
|
17171
17260
|
browser.addCommand(pages);
|
|
17172
17261
|
browser.addCommand(mcp);
|
|
17173
|
-
var VERSION3 = "0.1.0-beta.
|
|
17262
|
+
var VERSION3 = "0.1.0-beta.8";
|
|
17174
17263
|
var isMac = process.platform === "darwin";
|
|
17175
17264
|
var META_LABEL = isMac ? "Cmd" : "Win";
|
|
17176
17265
|
var ALT_LABEL = isMac ? "Option" : "Alt";
|
|
@@ -17368,19 +17457,13 @@ var comboToString = (combo) => {
|
|
|
17368
17457
|
var configure = new commander.Command().name("configure").alias("config").description("configure React Grab options").option("-y, --yes", "skip confirmation prompts", false).option(
|
|
17369
17458
|
"-k, --key <key>",
|
|
17370
17459
|
"activation key (e.g., Meta+K, Ctrl+Shift+G, Space)"
|
|
17371
|
-
).option(
|
|
17372
|
-
"-m, --mode <mode>",
|
|
17373
|
-
"activation mode (toggle, hold)"
|
|
17374
|
-
).option(
|
|
17460
|
+
).option("-m, --mode <mode>", "activation mode (toggle, hold)").option(
|
|
17375
17461
|
"--hold-duration <ms>",
|
|
17376
17462
|
"key hold duration in milliseconds (for hold mode)"
|
|
17377
17463
|
).option(
|
|
17378
17464
|
"--allow-input <boolean>",
|
|
17379
17465
|
"allow activation inside input fields (true/false)"
|
|
17380
|
-
).option(
|
|
17381
|
-
"--context-lines <lines>",
|
|
17382
|
-
"max context lines to include"
|
|
17383
|
-
).option(
|
|
17466
|
+
).option("--context-lines <lines>", "max context lines to include").option(
|
|
17384
17467
|
"-c, --cwd <cwd>",
|
|
17385
17468
|
"working directory (defaults to current directory)",
|
|
17386
17469
|
process.cwd()
|
|
@@ -17427,22 +17510,30 @@ var configure = new commander.Command().name("configure").alias("config").descri
|
|
|
17427
17510
|
if (opts2.holdDuration) {
|
|
17428
17511
|
const duration3 = parseInt(opts2.holdDuration, 10);
|
|
17429
17512
|
if (isNaN(duration3) || duration3 < 0 || duration3 > MAX_KEY_HOLD_DURATION_MS) {
|
|
17430
|
-
logger.error(
|
|
17513
|
+
logger.error(
|
|
17514
|
+
`Invalid hold duration. Must be 0-${MAX_KEY_HOLD_DURATION_MS}ms.`
|
|
17515
|
+
);
|
|
17431
17516
|
logger.break();
|
|
17432
17517
|
process.exit(1);
|
|
17433
17518
|
}
|
|
17434
17519
|
collectedOptions.keyHoldDuration = duration3;
|
|
17435
|
-
logger.log(
|
|
17520
|
+
logger.log(
|
|
17521
|
+
` Key hold duration: ${highlighter.info(`${duration3}ms`)}`
|
|
17522
|
+
);
|
|
17436
17523
|
}
|
|
17437
17524
|
if (opts2.allowInput !== void 0) {
|
|
17438
17525
|
const allowInput = opts2.allowInput === "true" || opts2.allowInput === true;
|
|
17439
17526
|
collectedOptions.allowActivationInsideInput = allowInput;
|
|
17440
|
-
logger.log(
|
|
17527
|
+
logger.log(
|
|
17528
|
+
` Allow activation inside input: ${highlighter.info(String(allowInput))}`
|
|
17529
|
+
);
|
|
17441
17530
|
}
|
|
17442
17531
|
if (opts2.contextLines) {
|
|
17443
17532
|
const lines = parseInt(opts2.contextLines, 10);
|
|
17444
17533
|
if (isNaN(lines) || lines < 0 || lines > MAX_CONTEXT_LINES) {
|
|
17445
|
-
logger.error(
|
|
17534
|
+
logger.error(
|
|
17535
|
+
`Invalid context lines. Must be 0-${MAX_CONTEXT_LINES}.`
|
|
17536
|
+
);
|
|
17446
17537
|
logger.break();
|
|
17447
17538
|
process.exit(1);
|
|
17448
17539
|
}
|
|
@@ -17492,7 +17583,10 @@ var configure = new commander.Command().name("configure").alias("config").descri
|
|
|
17492
17583
|
name: "activationMode",
|
|
17493
17584
|
message: `Select ${highlighter.info("activation mode")}:`,
|
|
17494
17585
|
choices: [
|
|
17495
|
-
{
|
|
17586
|
+
{
|
|
17587
|
+
title: "Toggle (press to activate/deactivate)",
|
|
17588
|
+
value: "toggle"
|
|
17589
|
+
},
|
|
17496
17590
|
{ title: "Hold (hold key to keep active)", value: "hold" }
|
|
17497
17591
|
],
|
|
17498
17592
|
initial: 0
|
|
@@ -17558,7 +17652,9 @@ var configure = new commander.Command().name("configure").alias("config").descri
|
|
|
17558
17652
|
logger.warn(result.message);
|
|
17559
17653
|
logger.break();
|
|
17560
17654
|
const configJson = JSON.stringify(collectedOptions);
|
|
17561
|
-
logger.log(
|
|
17655
|
+
logger.log(
|
|
17656
|
+
`Add this to your ${highlighter.info("init()")} call or ${highlighter.info("data-options")} attribute:`
|
|
17657
|
+
);
|
|
17562
17658
|
logger.break();
|
|
17563
17659
|
console.log(` ${pc__default.default.cyan(configJson)}`);
|
|
17564
17660
|
logger.break();
|
|
@@ -17608,7 +17704,7 @@ var configure = new commander.Command().name("configure").alias("config").descri
|
|
|
17608
17704
|
handleError(error48);
|
|
17609
17705
|
}
|
|
17610
17706
|
});
|
|
17611
|
-
var VERSION4 = "0.1.0-beta.
|
|
17707
|
+
var VERSION4 = "0.1.0-beta.8";
|
|
17612
17708
|
var REPORT_URL = "https://react-grab.com/api/report-cli";
|
|
17613
17709
|
var DOCS_URL = "https://github.com/aidenybai/react-grab";
|
|
17614
17710
|
var promptSkillInstall = async (cwd) => {
|
|
@@ -17616,7 +17712,9 @@ var promptSkillInstall = async (cwd) => {
|
|
|
17616
17712
|
if (detectedAgents.length === 0) {
|
|
17617
17713
|
return;
|
|
17618
17714
|
}
|
|
17619
|
-
logger.log(
|
|
17715
|
+
logger.log(
|
|
17716
|
+
`The ${highlighter.info("React Grab skill")} gives your agent access to the browser.`
|
|
17717
|
+
);
|
|
17620
17718
|
logger.log(`Learn more at ${highlighter.info("https://skill.md")}`);
|
|
17621
17719
|
logger.break();
|
|
17622
17720
|
const { wantSkill } = await prompts3__default.default({
|
|
@@ -17640,16 +17738,23 @@ var promptSkillInstall = async (cwd) => {
|
|
|
17640
17738
|
});
|
|
17641
17739
|
if (selectedAgent) {
|
|
17642
17740
|
logger.break();
|
|
17643
|
-
const skillSpinner = spinner(
|
|
17741
|
+
const skillSpinner = spinner(
|
|
17742
|
+
`Installing skill for ${selectedAgent.name}`
|
|
17743
|
+
).start();
|
|
17644
17744
|
try {
|
|
17645
|
-
child_process.execSync(
|
|
17646
|
-
|
|
17647
|
-
|
|
17648
|
-
|
|
17745
|
+
child_process.execSync(
|
|
17746
|
+
`npx -y add-skill aidenybai/react-grab -y --agent ${selectedAgent.id}`,
|
|
17747
|
+
{
|
|
17748
|
+
stdio: "ignore",
|
|
17749
|
+
cwd
|
|
17750
|
+
}
|
|
17751
|
+
);
|
|
17649
17752
|
skillSpinner.succeed(`Skill installed for ${selectedAgent.name}.`);
|
|
17650
17753
|
} catch {
|
|
17651
17754
|
skillSpinner.fail(`Failed to install skill for ${selectedAgent.name}.`);
|
|
17652
|
-
logger.warn(
|
|
17755
|
+
logger.warn(
|
|
17756
|
+
`Try manually: npx -y add-skill aidenybai/react-grab --agent ${selectedAgent.id}`
|
|
17757
|
+
);
|
|
17653
17758
|
}
|
|
17654
17759
|
}
|
|
17655
17760
|
logger.break();
|
|
@@ -17710,10 +17815,7 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
17710
17815
|
).option(
|
|
17711
17816
|
"-k, --key <key>",
|
|
17712
17817
|
"activation key (e.g., Meta+K, Ctrl+Shift+G, Space)"
|
|
17713
|
-
).option("--skip-install", "skip package installation", false).option(
|
|
17714
|
-
"--pkg <pkg>",
|
|
17715
|
-
"custom package URL for CLI (e.g., @react-grab/cli)"
|
|
17716
|
-
).option(
|
|
17818
|
+
).option("--skip-install", "skip package installation", false).option("--pkg <pkg>", "custom package URL for CLI (e.g., grab)").option(
|
|
17717
17819
|
"-c, --cwd <cwd>",
|
|
17718
17820
|
"working directory (defaults to current directory)",
|
|
17719
17821
|
process.cwd()
|
|
@@ -17961,7 +18063,9 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
17961
18063
|
const agentIntegration2 = agent;
|
|
17962
18064
|
let agentsToRemove2 = [];
|
|
17963
18065
|
if (projectInfo.installedAgents.length > 0) {
|
|
17964
|
-
const installedNames = formatInstalledAgentNames(
|
|
18066
|
+
const installedNames = formatInstalledAgentNames(
|
|
18067
|
+
projectInfo.installedAgents
|
|
18068
|
+
);
|
|
17965
18069
|
const { action } = await prompts3__default.default({
|
|
17966
18070
|
type: "select",
|
|
17967
18071
|
name: "action",
|
|
@@ -18289,7 +18393,7 @@ var init = new commander.Command().name("init").description("initialize React Gr
|
|
|
18289
18393
|
reportToCli("error", void 0, error48);
|
|
18290
18394
|
}
|
|
18291
18395
|
});
|
|
18292
|
-
var VERSION5 = "0.1.0-beta.
|
|
18396
|
+
var VERSION5 = "0.1.0-beta.8";
|
|
18293
18397
|
var remove = new commander.Command().name("remove").description("remove an agent integration").argument(
|
|
18294
18398
|
"[agent]",
|
|
18295
18399
|
"agent to remove (claude-code, cursor, opencode, codex, gemini, amp, ami, visual-edit)"
|
|
@@ -18469,18 +18573,18 @@ var remove = new commander.Command().name("remove").description("remove an agent
|
|
|
18469
18573
|
var uninstall = new commander.Command().name("uninstall").description("uninstall React Grab CLI globally").action(() => {
|
|
18470
18574
|
console.log("Uninstalling React Grab CLI...");
|
|
18471
18575
|
try {
|
|
18472
|
-
child_process.execSync("npm uninstall -g
|
|
18576
|
+
child_process.execSync("npm uninstall -g grab", { stdio: "inherit" });
|
|
18473
18577
|
console.log("React Grab CLI has been uninstalled.");
|
|
18474
18578
|
} catch {
|
|
18475
|
-
console.error("Failed to uninstall. Please try: npm uninstall -g
|
|
18579
|
+
console.error("Failed to uninstall. Please try: npm uninstall -g grab");
|
|
18476
18580
|
process.exit(1);
|
|
18477
18581
|
}
|
|
18478
18582
|
});
|
|
18479
|
-
var VERSION6 = "0.1.0-beta.
|
|
18480
|
-
var UPDATE_COMMAND = "npm install -g
|
|
18583
|
+
var VERSION6 = "0.1.0-beta.8";
|
|
18584
|
+
var UPDATE_COMMAND = "npm install -g grab@latest";
|
|
18481
18585
|
var getLatestVersion = () => {
|
|
18482
18586
|
try {
|
|
18483
|
-
return child_process.execSync("npm view
|
|
18587
|
+
return child_process.execSync("npm view grab version", {
|
|
18484
18588
|
encoding: "utf-8",
|
|
18485
18589
|
stdio: ["pipe", "pipe", "pipe"]
|
|
18486
18590
|
}).trim();
|
|
@@ -18498,7 +18602,9 @@ var update = new commander.Command().name("update").alias("upgrade").description
|
|
|
18498
18602
|
if (!latestVersion) {
|
|
18499
18603
|
checkSpinner.fail("Failed to fetch latest version");
|
|
18500
18604
|
logger.break();
|
|
18501
|
-
logger.error(
|
|
18605
|
+
logger.error(
|
|
18606
|
+
"Could not reach npm registry. Check your network connection."
|
|
18607
|
+
);
|
|
18502
18608
|
logger.break();
|
|
18503
18609
|
process.exit(1);
|
|
18504
18610
|
}
|
|
@@ -18513,7 +18619,9 @@ var update = new commander.Command().name("update").alias("upgrade").description
|
|
|
18513
18619
|
logger.break();
|
|
18514
18620
|
if (opts2.check) {
|
|
18515
18621
|
logger.log(`Update available: ${VERSION6} \u2192 ${latestVersion}`);
|
|
18516
|
-
logger.log(
|
|
18622
|
+
logger.log(
|
|
18623
|
+
`Run ${highlighter.info("grab update")} to install the update.`
|
|
18624
|
+
);
|
|
18517
18625
|
logger.break();
|
|
18518
18626
|
process.exit(0);
|
|
18519
18627
|
}
|
|
@@ -18542,7 +18650,9 @@ var update = new commander.Command().name("update").alias("upgrade").description
|
|
|
18542
18650
|
} catch (error48) {
|
|
18543
18651
|
updateSpinner.fail("Failed to update");
|
|
18544
18652
|
logger.break();
|
|
18545
|
-
logger.error(
|
|
18653
|
+
logger.error(
|
|
18654
|
+
`Update failed. Try manually: ${highlighter.info(UPDATE_COMMAND)}`
|
|
18655
|
+
);
|
|
18546
18656
|
if (error48 instanceof Error && error48.message) {
|
|
18547
18657
|
logger.dim(error48.message);
|
|
18548
18658
|
}
|
|
@@ -18552,7 +18662,7 @@ var update = new commander.Command().name("update").alias("upgrade").description
|
|
|
18552
18662
|
});
|
|
18553
18663
|
|
|
18554
18664
|
// src/cli.ts
|
|
18555
|
-
var VERSION7 = "0.1.0-beta.
|
|
18665
|
+
var VERSION7 = "0.1.0-beta.8";
|
|
18556
18666
|
var VERSION_API_URL = "https://www.react-grab.com/api/version";
|
|
18557
18667
|
process.on("SIGINT", () => process.exit(0));
|
|
18558
18668
|
process.on("SIGTERM", () => process.exit(0));
|