chrome-relay 0.5.3 → 0.5.4

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
@@ -43,7 +43,7 @@ var RelayError = class extends Error {
43
43
  };
44
44
 
45
45
  // src/index.ts
46
- var CHROME_RELAY_VERSION = true ? "0.5.3" : "0.0.0-dev";
46
+ var CHROME_RELAY_VERSION = true ? "0.5.4" : "0.0.0-dev";
47
47
 
48
48
  // src/install/install.ts
49
49
  import os from "os";
@@ -196,6 +196,13 @@ async function callTool(name, args) {
196
196
 
197
197
  // src/release-notes.ts
198
198
  var RELEASE_NOTES = {
199
+ "0.5.4": [
200
+ "Strict target routing (code-quality-hardening PR 2). Within a single scope, --tab / --workspace / --group are mutually exclusive \u2014 passing more than one on the same subcommand (or both at the program level) now fails with `target_conflict` and exit code 2.",
201
+ "Cross-scope override is still allowed but visible: `chrome-relay --workspace W <cmd> --workspace W2` works, but stderr prints a `target_overridden: workspace W \u2192 W2` notice so the agent (or user) knows what happened.",
202
+ "Fixed silent drops: `viewport set` and `console` previously hand-rolled their args and ignored global --workspace/--group. They now route through baseArgs() like every other targetable command.",
203
+ "New target-routing test matrix (55 tests) proves every targetable subcommand forwards --tab, --workspace, and --group correctly \u2014 and that the strict-conflict + override behavior holds. If you add a new targetable command to the CLI, add it to TARGETABLE_COMMANDS in packages/cli/test/target-routing.test.ts.",
204
+ "New TargetSelector type in @chrome-relay/protocol (future-proofing). Wire still carries the three loose fields; a future PR migrates the extension to read a single structured `target` field."
205
+ ],
199
206
  "0.5.3": [
200
207
  "Structured errors and notices (code-quality-hardening PR 1). New `BridgeError` and `BridgeNotice` types in @chrome-relay/protocol carry a code, tool, phase, and details \u2014 agents can branch on `errorDetails.code === 'invalid_arguments'` instead of regex-matching message strings.",
201
208
  "Tool result JSON now carries BOTH the legacy fields (`error: string`, `notice: string`) AND the new structured fields (`errorDetails: BridgeError`, `notices: BridgeNotice[]`). Old consumers keep working; new consumers prefer the structured shape.",
@@ -333,15 +340,53 @@ Notes:
333
340
  return cmd.option("-t, --tab <id>", "target tab ID", (v) => Number(v)).option("--workspace <name>", "target the active tab in a named workspace window (see `chrome-relay workspace`)").option("--group <name>", "target the active tab in a named tab-group (see `chrome-relay group`)");
334
341
  }
335
342
  function baseArgs(opts) {
343
+ const parentOpts = program.opts();
344
+ rejectIntraScopeConflict("subcommand", {
345
+ tab: opts.tab,
346
+ workspace: opts.workspace,
347
+ group: opts.group
348
+ });
349
+ rejectIntraScopeConflict("program-level", {
350
+ workspace: parentOpts.workspace,
351
+ group: parentOpts.group
352
+ });
353
+ if (opts.workspace && parentOpts.workspace && opts.workspace !== parentOpts.workspace) {
354
+ emitTargetOverride("workspace", parentOpts.workspace, opts.workspace);
355
+ }
356
+ if (opts.group && parentOpts.group && opts.group !== parentOpts.group) {
357
+ emitTargetOverride("group", parentOpts.group, opts.group);
358
+ }
359
+ if (opts.tab !== void 0 && (parentOpts.workspace || parentOpts.group)) {
360
+ const prior = parentOpts.workspace ? `workspace=${parentOpts.workspace}` : `group=${parentOpts.group}`;
361
+ emitTargetOverride("tab", prior, String(opts.tab));
362
+ }
336
363
  const args = {};
337
364
  if (opts.tab !== void 0) args.tabId = opts.tab;
338
- const parentOpts = program.opts();
339
365
  const effectiveWorkspace = opts.workspace ?? parentOpts.workspace;
340
366
  const effectiveGroup = opts.group ?? parentOpts.group;
341
- if (effectiveWorkspace) args.workspaceName = effectiveWorkspace;
342
- if (effectiveGroup) args.groupName = effectiveGroup;
367
+ if (opts.tab === void 0 && effectiveWorkspace) args.workspaceName = effectiveWorkspace;
368
+ if (opts.tab === void 0 && effectiveGroup) args.groupName = effectiveGroup;
343
369
  return args;
344
370
  }
371
+ function rejectIntraScopeConflict(scope, fields) {
372
+ const present = [];
373
+ if (fields.tab !== void 0) present.push("--tab");
374
+ if (fields.workspace) present.push("--workspace");
375
+ if (fields.group) present.push("--group");
376
+ if (present.length > 1) {
377
+ process.stderr.write(
378
+ `[chrome-relay] target_conflict: ${scope} flags ${present.join(" + ")} are mutually exclusive. Pass exactly one of --tab, --workspace, or --group on the same ${scope}.
379
+ `
380
+ );
381
+ process.exit(2);
382
+ }
383
+ }
384
+ function emitTargetOverride(kind, from, to) {
385
+ process.stderr.write(
386
+ `[chrome-relay] target_overridden: ${kind} ${from} \u2192 ${to} (subcommand-level overrides program-level)
387
+ `
388
+ );
389
+ }
345
390
  program.command("tabs [verb]").description("List open Chrome windows and tabs. (verb 'list' is accepted as alias)").action(async (verb) => {
346
391
  if (verb && verb !== "list") {
347
392
  process.stderr.write(`unknown tabs verb: ${verb}. Use 'tabs' or 'tabs list'.
@@ -537,7 +582,7 @@ Notes:
537
582
  viewport.command("set").description("Apply explicit viewport dimensions.").requiredOption("--width <px>", "viewport width in CSS pixels", (v) => Number(v)).requiredOption("--height <px>", "viewport height in CSS pixels", (v) => Number(v)).option("--dpr <ratio>", "device pixel ratio (1, 2, 3...)", (v) => Number(v)).option("--mobile", "set the mobile flag (affects meta viewport interpretation)").option("--touch", "enable touch event emulation").option("--user-agent <ua>", "override the User-Agent header")
538
583
  ).action(async (opts) => {
539
584
  const args = { action: "set", width: opts.width, height: opts.height };
540
- if (opts.tab !== void 0) args.tabId = opts.tab;
585
+ Object.assign(args, baseArgs(opts));
541
586
  if (opts.dpr !== void 0) args.dpr = opts.dpr;
542
587
  if (opts.mobile) args.mobile = true;
543
588
  if (opts.touch) args.hasTouch = true;
@@ -769,8 +814,7 @@ Notes:
769
814
  `
770
815
  )
771
816
  ).action(async (opts) => {
772
- const args = {};
773
- if (opts.tab !== void 0) args.tabId = opts.tab;
817
+ const args = baseArgs(opts);
774
818
  if (opts.clear) args.action = "clear";
775
819
  if (opts.level) args.levels = opts.level;
776
820
  if (typeof opts.since === "number") args.since = opts.since;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- var CHROME_RELAY_VERSION = true ? "0.5.3" : "0.0.0-dev";
2
+ var CHROME_RELAY_VERSION = true ? "0.5.4" : "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.3" : "0.0.0-dev";
51
+ var CHROME_RELAY_VERSION = true ? "0.5.4" : "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.3",
3
+ "version": "0.5.4",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",