chrome-relay 0.5.9 → 0.5.11

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 CHANGED
@@ -1,50 +1,142 @@
1
1
  #!/usr/bin/env node
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __esm = (fn, res) => function __init() {
5
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
+ };
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+
12
+ // ../protocol/dist/index.js
13
+ var dist_exports = {};
14
+ __export(dist_exports, {
15
+ CHROME_WEB_STORE_EXTENSION_ID: () => CHROME_WEB_STORE_EXTENSION_ID,
16
+ DEFAULT_EXTENSION_ID: () => DEFAULT_EXTENSION_ID,
17
+ DEFAULT_EXTENSION_IDS: () => DEFAULT_EXTENSION_IDS,
18
+ DEFAULT_HTTP_PORT: () => DEFAULT_HTTP_PORT,
19
+ LEGACY_DEV_EXTENSION_ID: () => LEGACY_DEV_EXTENSION_ID,
20
+ LOCAL_UNPACKED_EXTENSION_ID: () => LOCAL_UNPACKED_EXTENSION_ID,
21
+ NATIVE_HOST_NAME: () => NATIVE_HOST_NAME,
22
+ RelayError: () => RelayError,
23
+ TOOL_NAMES: () => TOOL_NAMES,
24
+ toBridgeError: () => toBridgeError
25
+ });
26
+ function toBridgeError(unknownErr, fallbackTool) {
27
+ if (unknownErr instanceof RelayError) {
28
+ const e = unknownErr.toBridgeError();
29
+ return fallbackTool && !e.tool ? { ...e, tool: fallbackTool } : e;
30
+ }
31
+ const message = unknownErr instanceof Error ? unknownErr.message : String(unknownErr);
32
+ return {
33
+ code: "internal_error",
34
+ message,
35
+ ...fallbackTool ? { tool: fallbackTool } : {}
36
+ };
37
+ }
38
+ var NATIVE_HOST_NAME, DEFAULT_HTTP_PORT, CHROME_WEB_STORE_EXTENSION_ID, LEGACY_DEV_EXTENSION_ID, LOCAL_UNPACKED_EXTENSION_ID, DEFAULT_EXTENSION_ID, DEFAULT_EXTENSION_IDS, TOOL_NAMES, RelayError;
39
+ var init_dist = __esm({
40
+ "../protocol/dist/index.js"() {
41
+ "use strict";
42
+ NATIVE_HOST_NAME = "dev.chrome_relay.native_host";
43
+ DEFAULT_HTTP_PORT = 12122;
44
+ CHROME_WEB_STORE_EXTENSION_ID = "cpdiapbifblhlcpnmlmfpgfjlacebokb";
45
+ LEGACY_DEV_EXTENSION_ID = "cdmmkpadhnpcfjljhgpdnnljhjafmhop";
46
+ LOCAL_UNPACKED_EXTENSION_ID = "cleiodnaklknhhfopegimjelfibjmbkc";
47
+ DEFAULT_EXTENSION_ID = CHROME_WEB_STORE_EXTENSION_ID;
48
+ DEFAULT_EXTENSION_IDS = [
49
+ CHROME_WEB_STORE_EXTENSION_ID,
50
+ LEGACY_DEV_EXTENSION_ID,
51
+ LOCAL_UNPACKED_EXTENSION_ID
52
+ ];
53
+ TOOL_NAMES = {
54
+ GET_WINDOWS_AND_TABS: "get_windows_and_tabs",
55
+ NAVIGATE: "chrome_navigate",
56
+ SWITCH_TAB: "chrome_switch_tab",
57
+ CLOSE_TABS: "chrome_close_tabs",
58
+ SCREENSHOT: "chrome_screenshot",
59
+ READ_PAGE: "chrome_read_page",
60
+ CLICK: "chrome_click_element",
61
+ FILL: "chrome_fill_or_select",
62
+ KEYBOARD: "chrome_keyboard",
63
+ TYPE: "chrome_type",
64
+ EVALUATE: "chrome_evaluate",
65
+ // §2.2 — viewport emulation (set/preset/clear share one tool, action via args.action)
66
+ VIEWPORT: "chrome_viewport",
67
+ // chrome_self_reload — calls chrome.runtime.reload() inside the extension.
68
+ // Lets the dev loop refresh the extension without manually clicking reload
69
+ // on chrome://extensions (Chrome blocks CDP attach on chrome:// pages).
70
+ SELF_RELOAD: "chrome_self_reload",
71
+ // §2.7c — console capture. Ring-buffer per tab; actions read/clear via args.
72
+ CONSOLE: "chrome_console",
73
+ // Workspaces — named Chrome windows for parallel agent work. Single tool
74
+ // with action: create | list | close. Every existing tool also accepts an
75
+ // optional workspaceName arg that routes ops into that workspace's window.
76
+ // (Was "chrome_group" pre-0.4.0; renamed because "group" collides with
77
+ // Chrome's own tab-group UI primitive, which is now exposed separately.)
78
+ WORKSPACE: "chrome_workspace",
79
+ // Tab groups — Chrome's native colored, collapsible folder of tabs inside
80
+ // a single window. Single tool with action: create | list | close | add | remove.
81
+ // Every existing tool also accepts an optional groupName arg that routes
82
+ // ops to a tab inside that tab-group.
83
+ GROUP: "chrome_group",
84
+ // §2.4 — accessibility tree. ~30× smaller than DOM serialization, more
85
+ // semantic. click_ax pairs with it: targets by backendDOMNodeId, no CSS.
86
+ AX: "chrome_ax",
87
+ CLICK_AX: "chrome_click_ax",
88
+ // §2.7a — network capture. Ring-buffer per tab; actions read/clear/har/body.
89
+ NETWORK: "chrome_network",
90
+ // Hover — dispatches mouseMoved at element center (or x,y) so :hover/
91
+ // :focus-within styles fire before a click or screencast frame is read.
92
+ HOVER: "chrome_hover",
93
+ // Screencast — wraps CDP Page.startScreencast / stopScreencast. SW buffers
94
+ // base64 JPEG frames per tab between start and stop. Paint-driven (catches
95
+ // CSS transitions, fade-ins, focus-ring motion) — at the cost of requiring
96
+ // the tab to be ACTIVE (Chrome doesn't paint backgrounded tabs). See
97
+ // docs/recording.md for the active-tab matrix.
98
+ SCREENCAST: "chrome_screencast"
99
+ };
100
+ RelayError = class extends Error {
101
+ code;
102
+ tool;
103
+ phase;
104
+ details;
105
+ retryable;
106
+ constructor(spec) {
107
+ super(spec.message);
108
+ this.name = "RelayError";
109
+ this.code = spec.code;
110
+ this.tool = spec.tool;
111
+ this.phase = spec.phase;
112
+ this.details = spec.details;
113
+ this.retryable = spec.retryable;
114
+ }
115
+ toBridgeError() {
116
+ return {
117
+ code: this.code,
118
+ message: this.message,
119
+ ...this.tool ? { tool: this.tool } : {},
120
+ ...this.phase ? { phase: this.phase } : {},
121
+ ...this.details ? { details: this.details } : {},
122
+ ...this.retryable !== void 0 ? { retryable: this.retryable } : {}
123
+ };
124
+ }
125
+ };
126
+ }
127
+ });
2
128
 
3
129
  // src/program.ts
4
130
  import { Command } from "commander";
5
131
 
6
132
  // src/index.ts
7
- var CHROME_RELAY_VERSION = true ? "0.5.9" : "0.0.0-dev";
133
+ var CHROME_RELAY_VERSION = true ? "0.5.11" : "0.0.0-dev";
8
134
 
9
- // ../protocol/dist/index.js
10
- var NATIVE_HOST_NAME = "dev.chrome_relay.native_host";
11
- var DEFAULT_HTTP_PORT = 12122;
12
- var CHROME_WEB_STORE_EXTENSION_ID = "cpdiapbifblhlcpnmlmfpgfjlacebokb";
13
- var LEGACY_DEV_EXTENSION_ID = "cdmmkpadhnpcfjljhgpdnnljhjafmhop";
14
- var LOCAL_UNPACKED_EXTENSION_ID = "cleiodnaklknhhfopegimjelfibjmbkc";
15
- var DEFAULT_EXTENSION_IDS = [
16
- CHROME_WEB_STORE_EXTENSION_ID,
17
- LEGACY_DEV_EXTENSION_ID,
18
- LOCAL_UNPACKED_EXTENSION_ID
19
- ];
20
- var RelayError = class extends Error {
21
- code;
22
- tool;
23
- phase;
24
- details;
25
- retryable;
26
- constructor(spec) {
27
- super(spec.message);
28
- this.name = "RelayError";
29
- this.code = spec.code;
30
- this.tool = spec.tool;
31
- this.phase = spec.phase;
32
- this.details = spec.details;
33
- this.retryable = spec.retryable;
34
- }
35
- toBridgeError() {
36
- return {
37
- code: this.code,
38
- message: this.message,
39
- ...this.tool ? { tool: this.tool } : {},
40
- ...this.phase ? { phase: this.phase } : {},
41
- ...this.details ? { details: this.details } : {},
42
- ...this.retryable !== void 0 ? { retryable: this.retryable } : {}
43
- };
44
- }
45
- };
135
+ // src/commands/shared.ts
136
+ init_dist();
46
137
 
47
138
  // src/client/call.ts
139
+ init_dist();
48
140
  var noticePrinted = false;
49
141
  function emitNoticeOnce(notice) {
50
142
  if (noticePrinted) return;
@@ -162,6 +254,7 @@ async function runToolImpl(name, args) {
162
254
  var runTool = runToolImpl;
163
255
 
164
256
  // src/install/install.ts
257
+ init_dist();
165
258
  import os from "os";
166
259
  import path from "path";
167
260
  import { chmod, mkdir, readFile, stat, writeFile } from "fs/promises";
@@ -271,6 +364,17 @@ async function runDoctor() {
271
364
 
272
365
  // src/release-notes.ts
273
366
  var RELEASE_NOTES = {
367
+ "0.5.11": [
368
+ "Tests-only: 6 new edge-case tests for `chrome-relay update`. Covers --dry-run, install failure, install-success-but-binary-version-unchanged (PATH mismatch / stale shim), install-success-but-which-fails, install-success-but-release-notes-parse-fails, and the happy path. Locks in the structured-metadata contract from 0.5.7.",
369
+ "Total tests now 378 (was 372)."
370
+ ],
371
+ "0.5.10": [
372
+ "Direct /call target conflict enforcement. Third-party callers posting to /call with multiple loose target fields (tabId + workspaceName, etc.) now throw `target_conflict` instead of silently applying precedence. Matches the CLI rule the CLI itself enforced since 0.5.4.",
373
+ "All useful plain Error throws in extension handlers converted to RelayError(invalid_arguments). Affected tools: chrome_click_element, chrome_fill_or_select, chrome_keyboard, chrome_type, chrome_evaluate, chrome_switch_tab, chrome_close_tabs, chrome_viewport (preset name + width/height), chrome_workspace (create/close), chrome_group (create/close/add/remove), chrome_network (body without --request-id), chrome_hover (no selector or x,y), chrome_click_ax (no --node), and bbox parser. Agents can now branch on `errorDetails.code === 'invalid_arguments'` for all of these.",
374
+ "chrome_hover with a selector that doesn't match now throws RelayError(`element_not_found`) (was plain Error).",
375
+ "BEHAVIOR CHANGE \u2014 `chrome-relay screencast stop --gif/--mp4` is no longer best-effort when ffmpeg is missing. Old behavior printed 'skipping' and exited 0 (agent saw success but no GIF existed). New behavior throws `external_dependency_missing` with exit 1. Pass `--allow-missing-ffmpeg` to restore the legacy skip-with-warning behavior.",
376
+ "Tests: +17 in handler-strict.test.ts covering the conflict + 13 missing-arg paths. Total now 372."
377
+ ],
274
378
  "0.5.9": [
275
379
  "Internal refactor (code-quality-hardening PR 7): program.ts and tools.ts split into per-domain modules. Pure code motion, no behavior change.",
276
380
  "CLI: packages/cli/src/program.ts shrank from 1041 \u2192 75 lines. Per-domain modules now live in packages/cli/src/commands/{install-update,navigation,input,capture,sessions}.ts.",
@@ -728,7 +832,7 @@ Notes:
728
832
  await run("chrome_screencast", args);
729
833
  });
730
834
  tabOpt(
731
- screencast.command("stop").description("Stop the screencast and emit frames (or write to disk).").option("-o, --out <dir>", "write frames as JPEGs into this directory (created if missing)").option("--gif", "after writing frames, ffmpeg them into <dir>.gif").option("--mp4", "after writing frames, ffmpeg them into <dir>.mp4").option("--fps <n>", "assumed framerate when invoking ffmpeg (default 15)", (v) => Number(v)).option("--no-dedupe", "keep raw frames; default collapses consecutive identical frames via SHA-256")
835
+ screencast.command("stop").description("Stop the screencast and emit frames (or write to disk).").option("-o, --out <dir>", "write frames as JPEGs into this directory (created if missing)").option("--gif", "after writing frames, ffmpeg them into <dir>.gif (requires ffmpeg on PATH)").option("--mp4", "after writing frames, ffmpeg them into <dir>.mp4 (requires ffmpeg on PATH)").option("--fps <n>", "assumed framerate when invoking ffmpeg (default 15)", (v) => Number(v)).option("--no-dedupe", "keep raw frames; default collapses consecutive identical frames via SHA-256").option("--allow-missing-ffmpeg", "with --gif/--mp4: skip ffmpeg step (and emit a warning) if ffmpeg isn't on PATH, instead of failing with external_dependency_missing")
732
836
  ).action(async (opts) => {
733
837
  const args = { action: "stop" };
734
838
  Object.assign(args, baseArgs(opts));
@@ -790,8 +894,22 @@ Notes:
790
894
  const { spawnSync } = await import("child_process");
791
895
  const which = spawnSync("which", ["ffmpeg"]);
792
896
  if (which.status !== 0) {
793
- process.stderr.write("[chrome-relay] ffmpeg not on PATH \u2014 skipping --gif/--mp4.\n");
794
- return;
897
+ if (opts.allowMissingFfmpeg) {
898
+ process.stderr.write("[chrome-relay] ffmpeg not on PATH \u2014 skipping --gif/--mp4 (allow-missing-ffmpeg).\n");
899
+ return;
900
+ }
901
+ const { RelayError: RelayError2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
902
+ const err = new RelayError2({
903
+ code: "external_dependency_missing",
904
+ message: "chrome-relay screencast stop --gif/--mp4 requires ffmpeg on PATH. Install ffmpeg (brew install ffmpeg) or pass --allow-missing-ffmpeg to skip the stitch step with a warning.",
905
+ tool: "chrome_screencast",
906
+ phase: "ffmpeg_stitch",
907
+ details: { dependency: "ffmpeg", outputs: { gif: !!opts.gif, mp4: !!opts.mp4 } },
908
+ retryable: false
909
+ });
910
+ process.stderr.write(err.message + "\n");
911
+ process.stderr.write(JSON.stringify({ relayError: err.toBridgeError() }, null, 2) + "\n");
912
+ process.exit(1);
795
913
  }
796
914
  if (opts.gif) {
797
915
  const gifOut = `${opts.out.replace(/\/$/, "")}.gif`;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- var CHROME_RELAY_VERSION = true ? "0.5.9" : "0.0.0-dev";
2
+ var CHROME_RELAY_VERSION = true ? "0.5.11" : "0.0.0-dev";
3
3
  export {
4
4
  CHROME_RELAY_VERSION
5
5
  };
@@ -48,7 +48,7 @@ function toBridgeError(unknownErr, fallbackTool) {
48
48
  }
49
49
 
50
50
  // src/index.ts
51
- var CHROME_RELAY_VERSION = true ? "0.5.9" : "0.0.0-dev";
51
+ var CHROME_RELAY_VERSION = true ? "0.5.11" : "0.0.0-dev";
52
52
 
53
53
  // src/release-notes.ts
54
54
  function compareSemver(a, b) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrome-relay",
3
- "version": "0.5.9",
3
+ "version": "0.5.11",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",