chrome-relay 0.5.18 → 0.5.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +71 -12
- package/dist/index.js +1 -1
- package/dist/native-host.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -383,10 +383,34 @@ function parseChromeReadPageArgs(input) {
|
|
|
383
383
|
}
|
|
384
384
|
function parseChromeClickArgs(input) {
|
|
385
385
|
const obj = asObject(input, TOOL_NAMES.CLICK);
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
386
|
+
const target = parseTargetArgs(obj, TOOL_NAMES.CLICK);
|
|
387
|
+
const x = optNumber(obj, "x", TOOL_NAMES.CLICK);
|
|
388
|
+
const y = optNumber(obj, "y", TOOL_NAMES.CLICK);
|
|
389
|
+
if (x !== void 0 !== (y !== void 0)) {
|
|
390
|
+
throw new RelayError({
|
|
391
|
+
code: "invalid_arguments",
|
|
392
|
+
message: "chrome_click_element: pass BOTH x and y, or neither (selector mode).",
|
|
393
|
+
tool: TOOL_NAMES.CLICK,
|
|
394
|
+
phase: "parse_arguments",
|
|
395
|
+
details: { received: { x: obj.x, y: obj.y } },
|
|
396
|
+
retryable: false
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
if (x !== void 0 && y !== void 0) {
|
|
400
|
+
return { ...target, kind: "coords", x, y };
|
|
401
|
+
}
|
|
402
|
+
const selector = optString(obj, "selector", TOOL_NAMES.CLICK);
|
|
403
|
+
if (selector) {
|
|
404
|
+
return { ...target, kind: "selector", selector };
|
|
405
|
+
}
|
|
406
|
+
throw new RelayError({
|
|
407
|
+
code: "invalid_arguments",
|
|
408
|
+
message: "chrome_click_element requires either a selector or x AND y.",
|
|
409
|
+
tool: TOOL_NAMES.CLICK,
|
|
410
|
+
phase: "parse_arguments",
|
|
411
|
+
details: { received: { selector: obj.selector, x: obj.x, y: obj.y } },
|
|
412
|
+
retryable: false
|
|
413
|
+
});
|
|
390
414
|
}
|
|
391
415
|
function parseChromeFillArgs(input) {
|
|
392
416
|
const obj = asObject(input, TOOL_NAMES.FILL);
|
|
@@ -1077,7 +1101,7 @@ var init_dist = __esm({
|
|
|
1077
1101
|
import { Command } from "commander";
|
|
1078
1102
|
|
|
1079
1103
|
// src/index.ts
|
|
1080
|
-
var CHROME_RELAY_VERSION = true ? "0.5.
|
|
1104
|
+
var CHROME_RELAY_VERSION = true ? "0.5.20" : "0.0.0-dev";
|
|
1081
1105
|
|
|
1082
1106
|
// src/commands/shared.ts
|
|
1083
1107
|
init_dist();
|
|
@@ -1320,6 +1344,19 @@ async function runDoctor() {
|
|
|
1320
1344
|
|
|
1321
1345
|
// src/release-notes.ts
|
|
1322
1346
|
var RELEASE_NOTES = {
|
|
1347
|
+
"0.5.20": [
|
|
1348
|
+
"BREAKING \u2014 `chrome-relay navigate` no longer steals focus by default. Background is now the implicit behavior; agents pass `--active` when they actually want the user looking at the new tab. The whole product pitch is 'operate without stealing focus' \u2014 the default needed to match.",
|
|
1349
|
+
"`--inactive` flag removed entirely. It was the opt-in for the previous (wrong) default; now it'd be a no-op, and no-op flags are dead code. Agents that were passing `--inactive` should drop it (the behavior is now the default). Commander will reject the unknown flag \u2014 that's the right signal to update.",
|
|
1350
|
+
"Workspace `chrome.windows.create({focused: false})` was already correct from earlier work, so workspaces are unaffected.",
|
|
1351
|
+
'Click now dispatches as a pointer event. Added `pointerType: "mouse"` to all three `Input.dispatchMouseEvent` calls in the CLICK handler. Without it, CDP only fires mouse events \u2014 modern UI libs (Radix, React-Aria, Headless UI) listen on `pointerdown` and silently ignore mouse-only clicks, so dropdowns / menu triggers / select widgets stayed closed even though the click registered. Discovered while dogfooding `chrome-relay click --x N --y N` against npm\'s token-creation form; verified by completing the full token-creation flow end-to-end (radio click, combobox open, submit) via chrome-relay tools.',
|
|
1352
|
+
"Tests: navigate test updated to assert no `active` field in default request, plus a new test verifying `--active` opts in to focus."
|
|
1353
|
+
],
|
|
1354
|
+
"0.5.19": [
|
|
1355
|
+
"Coordinate click. `chrome-relay click --x N --y N --tab N` dispatches a trusted Input.dispatchMouseEvent at the given pixel coordinates \u2014 no selector required. The selector positional became optional; the protocol parser collapses click args into a discriminated union (`kind: 'selector'` | `kind: 'coords'`) and rejects partial coords (`--x` without `--y`) with `invalid_arguments`.",
|
|
1356
|
+
"Intentionally NOT shipping `click-text`. Once coord-click exists, finding text + clicking is fully composable with `js` (TreeWalker \u2192 getBoundingClientRect) \u2192 `click --x/--y`. Per the CLI philosophy, that's a smart wrapper, not a primitive. The two-step recipe lives in docs/clicking-strategies.md as the documented pattern.",
|
|
1357
|
+
"Updated docs: docs/clicking-strategies.md now lists the 4 click verbs (click selector/coords, click-ax, js) and the text-recipe; docs/cli-philosophy.md explains the hide-vs-expose calculus that led to this design.",
|
|
1358
|
+
"Tests: +2 in program.test.ts (coord-click + partial-coords rejection), +1 in args-all.test.ts (discriminated-union parsing). Existing click tests updated to expect the parsed `kind: 'selector'` shape now that CLI-side parseToolArgs runs before send."
|
|
1359
|
+
],
|
|
1323
1360
|
"0.5.18": [
|
|
1324
1361
|
"Force-visible on attach \u2014 actually fixes Cloudflare-style SPAs now. 0.5.17 had two bugs: (1) missing `Page.enable` before `Page.addScriptToEvaluateOnNewDocument` (the script registration silently failed, so the shim only applied to the current doc \u2014 page reloads dropped it), (2) the JS shim used one try-block so a deprecated `Object.defineProperty(document, 'webkitVisibilityState')` could throw and skip the `document.hasFocus` patch.",
|
|
1325
1362
|
"0.5.18 fixes both: enables Page domain first, then applies each patch in its own try/catch. New patches added: `document.hasFocus` (overridden on both instance and Document.prototype), `Emulation.setFocusEmulationEnabled` via CDP, `document.wasDiscarded`. End result: Cloudflare Web Analytics dashboard now fully renders on backgrounded tabs without focus theft (verified live).",
|
|
@@ -1567,14 +1604,19 @@ function registerNavigation(ctx) {
|
|
|
1567
1604
|
await run("get_windows_and_tabs", {});
|
|
1568
1605
|
});
|
|
1569
1606
|
tabOpt(
|
|
1570
|
-
program.command("navigate <url>").description("Navigate a tab to a URL. Use --tab <id> to target an existing tab.").option("--new", "open in a new tab").option("--
|
|
1607
|
+
program.command("navigate <url>").description("Navigate a tab to a URL. Use --tab <id> to target an existing tab.").option("--new", "open in a new tab").option("--active", "activate the tab after navigating (default: background \u2014 no focus theft)").addHelpText(
|
|
1571
1608
|
"after",
|
|
1572
1609
|
`
|
|
1573
1610
|
|
|
1574
1611
|
Examples:
|
|
1575
|
-
chrome-relay navigate "https://example.com"
|
|
1576
|
-
chrome-relay navigate --tab
|
|
1577
|
-
chrome-relay navigate "https://example.com" --new
|
|
1612
|
+
chrome-relay navigate "https://example.com" # navigate current tab
|
|
1613
|
+
chrome-relay navigate --tab 123 "https://example.com" # navigate an existing tab
|
|
1614
|
+
chrome-relay navigate "https://example.com" --new # open in a new background tab
|
|
1615
|
+
chrome-relay navigate "https://example.com" --new --active # open new tab AND show it to the user
|
|
1616
|
+
|
|
1617
|
+
By default chrome-relay never steals focus \u2014 navigated tabs (new or
|
|
1618
|
+
existing) stay in whatever state they're in. Pass --active when you
|
|
1619
|
+
actually want the user looking at the page.
|
|
1578
1620
|
`
|
|
1579
1621
|
)
|
|
1580
1622
|
).action(async (url, opts) => {
|
|
@@ -1588,7 +1630,7 @@ Use "chrome-relay switch ${url}" to activate that tab, or "chrome-relay navigate
|
|
|
1588
1630
|
}
|
|
1589
1631
|
const extras = { url };
|
|
1590
1632
|
if (opts.new) extras.newTab = true;
|
|
1591
|
-
if (opts.
|
|
1633
|
+
if (opts.active) extras.active = true;
|
|
1592
1634
|
await run("chrome_navigate", withBase(opts, extras));
|
|
1593
1635
|
});
|
|
1594
1636
|
program.command("switch <tabId>").description("Activate a tab by ID.").action(async (tabId) => {
|
|
@@ -1607,9 +1649,26 @@ Use "chrome-relay switch ${url}" to activate that tab, or "chrome-relay navigate
|
|
|
1607
1649
|
function registerInput(ctx) {
|
|
1608
1650
|
const { program, withBase, run } = ctx;
|
|
1609
1651
|
tabOpt(
|
|
1610
|
-
program.command("click
|
|
1652
|
+
program.command("click [selector]").description("Click an element. Pass a CSS selector OR --x and --y for a coordinate click.").option("--x <px>", "explicit x coordinate (CSS pixels); requires --y", (v) => Number(v)).option("--y <px>", "explicit y coordinate (CSS pixels); requires --x", (v) => Number(v)).addHelpText(
|
|
1653
|
+
"after",
|
|
1654
|
+
`
|
|
1655
|
+
|
|
1656
|
+
Examples:
|
|
1657
|
+
chrome-relay click 'button[aria-label="Save"]'
|
|
1658
|
+
chrome-relay click --tab 123 --x 1327 --y 771
|
|
1659
|
+
|
|
1660
|
+
Pick selector mode when the element has a stable CSS query. Pick
|
|
1661
|
+
coordinate mode when the page wraps content in unmarked divs (Cloudflare
|
|
1662
|
+
dashboard, Vercel dashboard, etc.) and you got the rect from a prior
|
|
1663
|
+
\`chrome-relay js\` call or a screenshot. See docs/clicking-strategies.md.
|
|
1664
|
+
`
|
|
1665
|
+
)
|
|
1611
1666
|
).action(async (selector, opts) => {
|
|
1612
|
-
|
|
1667
|
+
const extras = {};
|
|
1668
|
+
if (selector) extras.selector = selector;
|
|
1669
|
+
if (typeof opts.x === "number") extras.x = opts.x;
|
|
1670
|
+
if (typeof opts.y === "number") extras.y = opts.y;
|
|
1671
|
+
await run("chrome_click_element", withBase(opts, extras));
|
|
1613
1672
|
});
|
|
1614
1673
|
tabOpt(
|
|
1615
1674
|
program.command("fill <selector> <value>").description("Fill an input or textarea.")
|
package/dist/index.js
CHANGED
package/dist/native-host.js
CHANGED
|
@@ -56,7 +56,7 @@ function toBridgeError(unknownErr, fallbackTool) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// src/index.ts
|
|
59
|
-
var CHROME_RELAY_VERSION = true ? "0.5.
|
|
59
|
+
var CHROME_RELAY_VERSION = true ? "0.5.20" : "0.0.0-dev";
|
|
60
60
|
|
|
61
61
|
// src/release-notes.ts
|
|
62
62
|
function compareSemver(a, b) {
|