chrome-relay 0.5.6 → 0.5.8
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 +150 -88
- package/dist/index.js +1 -1
- package/dist/native-host.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,15 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import { writeFileSync } from "fs";
|
|
6
6
|
|
|
7
|
+
// src/index.ts
|
|
8
|
+
var CHROME_RELAY_VERSION = true ? "0.5.8" : "0.0.0-dev";
|
|
9
|
+
|
|
10
|
+
// src/install/install.ts
|
|
11
|
+
import os from "os";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import { chmod, mkdir, readFile, stat, writeFile } from "fs/promises";
|
|
14
|
+
import { fileURLToPath } from "url";
|
|
15
|
+
|
|
7
16
|
// ../protocol/dist/index.js
|
|
8
17
|
var NATIVE_HOST_NAME = "dev.chrome_relay.native_host";
|
|
9
18
|
var DEFAULT_HTTP_PORT = 12122;
|
|
@@ -42,14 +51,7 @@ var RelayError = class extends Error {
|
|
|
42
51
|
}
|
|
43
52
|
};
|
|
44
53
|
|
|
45
|
-
// src/index.ts
|
|
46
|
-
var CHROME_RELAY_VERSION = true ? "0.5.6" : "0.0.0-dev";
|
|
47
|
-
|
|
48
54
|
// src/install/install.ts
|
|
49
|
-
import os from "os";
|
|
50
|
-
import path from "path";
|
|
51
|
-
import { chmod, mkdir, readFile, stat, writeFile } from "fs/promises";
|
|
52
|
-
import { fileURLToPath } from "url";
|
|
53
55
|
var APP_DIR = path.join(os.homedir(), ".chrome-relay");
|
|
54
56
|
var KNOWN_EXTENSION_IDS = [
|
|
55
57
|
["Chrome Web Store", CHROME_WEB_STORE_EXTENSION_ID],
|
|
@@ -196,6 +198,16 @@ async function callTool(name, args) {
|
|
|
196
198
|
|
|
197
199
|
// src/release-notes.ts
|
|
198
200
|
var RELEASE_NOTES = {
|
|
201
|
+
"0.5.8": [
|
|
202
|
+
"Internal refactor (code-quality-hardening PR 6, first cut): shared CLI helpers moved out of program.ts into packages/cli/src/commands/shared.ts.",
|
|
203
|
+
"tabOpt(), makeBaseArgs(program), and runTool() are now importable from `./commands/shared.js`. program.ts dropped ~100 lines.",
|
|
204
|
+
"No behavior change \u2014 all 355 tests still pass. Future PRs can split per-domain command groups (navigation, input, capture, sessions) into their own modules without churning helpers."
|
|
205
|
+
],
|
|
206
|
+
"0.5.7": [
|
|
207
|
+
"`chrome-relay update` returns structured verification metadata (code-quality-hardening PR 5). Output now has `install: { attempted, packageManager, status, command }`, `binary: { path, reexeced }`, `releaseNotes: { source: 'current_process' | 'updated_binary', changes }`, and a `warnings[]` array.",
|
|
208
|
+
"Surfaces the 'install said success but binary didn't change' failure mode (PATH mismatch, stale shim, cross-package-manager confusion) as `warnings[].code === 'update_not_verified'`. Agents can branch on it.",
|
|
209
|
+
"Falls back gracefully: when the re-exec can't be proven, release notes are read from the current (pre-update) process and marked `source: 'current_process'`. The agent knows the bullets may be stale."
|
|
210
|
+
],
|
|
199
211
|
"0.5.6": [
|
|
200
212
|
"BEHAVIOR CHANGE \u2014 `chrome-relay network har --with-bodies` is now strict by default (code-quality-hardening PR 4). When ANY body fails to fetch, the call throws `partial_success_disallowed` with details about which entries failed.",
|
|
201
213
|
"New `--best-effort-bodies` flag restores the legacy behavior: HAR still emits, missing/errored bodies are recorded per-entry in `_chrome_relay.bodyState` and `_chrome_relay.bodyError` (with code, message, and phase).",
|
|
@@ -261,6 +273,81 @@ function listReleaseNotesSince(since) {
|
|
|
261
273
|
return Object.keys(RELEASE_NOTES).filter((v) => compareSemver(v, since) > 0).sort((a, b) => compareSemver(a, b)).map((version) => ({ version, bullets: RELEASE_NOTES[version] }));
|
|
262
274
|
}
|
|
263
275
|
|
|
276
|
+
// src/commands/shared.ts
|
|
277
|
+
function tabOpt(cmd) {
|
|
278
|
+
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`)");
|
|
279
|
+
}
|
|
280
|
+
function makeBaseArgs(program) {
|
|
281
|
+
return function baseArgs(opts) {
|
|
282
|
+
const parentOpts = program.opts();
|
|
283
|
+
rejectIntraScopeConflict("subcommand", {
|
|
284
|
+
tab: opts.tab,
|
|
285
|
+
workspace: opts.workspace,
|
|
286
|
+
group: opts.group
|
|
287
|
+
});
|
|
288
|
+
rejectIntraScopeConflict("program-level", {
|
|
289
|
+
workspace: parentOpts.workspace,
|
|
290
|
+
group: parentOpts.group
|
|
291
|
+
});
|
|
292
|
+
if (opts.workspace && parentOpts.workspace && opts.workspace !== parentOpts.workspace) {
|
|
293
|
+
emitTargetOverride("workspace", parentOpts.workspace, opts.workspace);
|
|
294
|
+
}
|
|
295
|
+
if (opts.group && parentOpts.group && opts.group !== parentOpts.group) {
|
|
296
|
+
emitTargetOverride("group", parentOpts.group, opts.group);
|
|
297
|
+
}
|
|
298
|
+
if (opts.tab !== void 0 && (parentOpts.workspace || parentOpts.group)) {
|
|
299
|
+
const prior = parentOpts.workspace ? `workspace=${parentOpts.workspace}` : `group=${parentOpts.group}`;
|
|
300
|
+
emitTargetOverride("tab", prior, String(opts.tab));
|
|
301
|
+
}
|
|
302
|
+
const args = {};
|
|
303
|
+
if (opts.tab !== void 0) args.tabId = opts.tab;
|
|
304
|
+
const effectiveWorkspace = opts.workspace ?? parentOpts.workspace;
|
|
305
|
+
const effectiveGroup = opts.group ?? parentOpts.group;
|
|
306
|
+
if (opts.tab === void 0 && effectiveWorkspace) args.workspaceName = effectiveWorkspace;
|
|
307
|
+
if (opts.tab === void 0 && effectiveGroup) args.groupName = effectiveGroup;
|
|
308
|
+
return args;
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function rejectIntraScopeConflict(scope, fields) {
|
|
312
|
+
const present = [];
|
|
313
|
+
if (fields.tab !== void 0) present.push("--tab");
|
|
314
|
+
if (fields.workspace) present.push("--workspace");
|
|
315
|
+
if (fields.group) present.push("--group");
|
|
316
|
+
if (present.length > 1) {
|
|
317
|
+
process.stderr.write(
|
|
318
|
+
`[chrome-relay] target_conflict: ${scope} flags ${present.join(" + ")} are mutually exclusive. Pass exactly one of --tab, --workspace, or --group on the same ${scope}.
|
|
319
|
+
`
|
|
320
|
+
);
|
|
321
|
+
process.exit(2);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function emitTargetOverride(kind, from, to) {
|
|
325
|
+
process.stderr.write(
|
|
326
|
+
`[chrome-relay] target_overridden: ${kind} ${from} \u2192 ${to} (subcommand-level overrides program-level)
|
|
327
|
+
`
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
async function runTool(name, args) {
|
|
331
|
+
try {
|
|
332
|
+
const result = await callTool(name, args);
|
|
333
|
+
if (typeof result === "string") {
|
|
334
|
+
process.stdout.write(result + "\n");
|
|
335
|
+
} else {
|
|
336
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
337
|
+
}
|
|
338
|
+
} catch (error) {
|
|
339
|
+
if (error instanceof RelayError) {
|
|
340
|
+
process.stderr.write(error.message + "\n");
|
|
341
|
+
process.stderr.write(JSON.stringify({ relayError: error.toBridgeError() }, null, 2) + "\n");
|
|
342
|
+
} else {
|
|
343
|
+
process.stderr.write(
|
|
344
|
+
(error instanceof Error ? error.message : String(error)) + "\n"
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
process.exit(1);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
264
351
|
// src/program.ts
|
|
265
352
|
function buildProgram() {
|
|
266
353
|
const program = new Command();
|
|
@@ -294,31 +381,75 @@ Notes:
|
|
|
294
381
|
program.command("update").description("Update chrome-relay CLI to the latest version and print what changed (agent-readable JSON).").option("--dry-run", "skip the install; just show what changed since the current version").action(async (opts) => {
|
|
295
382
|
const fromVersion = CHROME_RELAY_VERSION;
|
|
296
383
|
const { spawnSync } = await import("child_process");
|
|
384
|
+
const out = {
|
|
385
|
+
updatedFrom: fromVersion,
|
|
386
|
+
updatedTo: fromVersion,
|
|
387
|
+
install: { attempted: false },
|
|
388
|
+
binary: { path: process.argv[1] ?? "", reexeced: false },
|
|
389
|
+
releaseNotes: { source: "current_process", changes: [] },
|
|
390
|
+
warnings: []
|
|
391
|
+
};
|
|
297
392
|
if (!opts.dryRun) {
|
|
298
393
|
const argv0 = process.argv[1] ?? "";
|
|
299
394
|
const pm = /[\\/](pnpm|\.pnpm)[\\/]/.test(argv0) ? "pnpm" : /[\\/]bun[\\/]/.test(argv0) ? "bun" : "npm";
|
|
300
395
|
const cmd = pm === "pnpm" ? ["pnpm", ["add", "-g", "chrome-relay@latest"]] : pm === "bun" ? ["bun", ["add", "-g", "chrome-relay@latest"]] : ["npm", ["install", "-g", "chrome-relay@latest"]];
|
|
396
|
+
out.install = {
|
|
397
|
+
attempted: true,
|
|
398
|
+
packageManager: pm,
|
|
399
|
+
command: `${cmd[0]} ${cmd[1].join(" ")}`
|
|
400
|
+
};
|
|
301
401
|
process.stderr.write(`[chrome-relay] updating from ${fromVersion} via ${pm}...
|
|
302
402
|
`);
|
|
303
403
|
const install = spawnSync(cmd[0], cmd[1], { stdio: "inherit" });
|
|
404
|
+
out.install.status = install.status;
|
|
304
405
|
if (install.status !== 0) {
|
|
305
|
-
process.stderr.write(`[chrome-relay] install failed (${pm} exited ${install.status}). Try manually: ${
|
|
406
|
+
process.stderr.write(`[chrome-relay] install failed (${pm} exited ${install.status}). Try manually: ${cmd[0]} ${cmd[1].join(" ")}
|
|
306
407
|
`);
|
|
408
|
+
out.warnings.push({
|
|
409
|
+
code: "update_install_failed",
|
|
410
|
+
message: `Package-manager exit ${install.status}. Active binary unchanged.`
|
|
411
|
+
});
|
|
412
|
+
process.stdout.write(JSON.stringify(out, null, 2) + "\n");
|
|
307
413
|
process.exit(1);
|
|
308
414
|
}
|
|
309
415
|
const which = spawnSync("which", ["chrome-relay"]);
|
|
310
416
|
const newBin = which.stdout?.toString().trim();
|
|
311
|
-
if (which.status === 0 && newBin
|
|
312
|
-
spawnSync(newBin, ["
|
|
313
|
-
|
|
417
|
+
if (which.status === 0 && newBin) {
|
|
418
|
+
const versionOut = spawnSync(newBin, ["--version"]);
|
|
419
|
+
const newVersion = (versionOut.stdout?.toString() ?? "").trim();
|
|
420
|
+
out.binary.path = newBin;
|
|
421
|
+
if (newVersion && newVersion !== fromVersion) {
|
|
422
|
+
out.updatedTo = newVersion;
|
|
423
|
+
const rn = spawnSync(newBin, ["release-notes", "--since", fromVersion]);
|
|
424
|
+
try {
|
|
425
|
+
const parsed = JSON.parse(rn.stdout?.toString() ?? "");
|
|
426
|
+
if (Array.isArray(parsed.changes)) {
|
|
427
|
+
out.releaseNotes = { source: "updated_binary", changes: parsed.changes };
|
|
428
|
+
}
|
|
429
|
+
} catch {
|
|
430
|
+
out.warnings.push({
|
|
431
|
+
code: "release_notes_parse_failed",
|
|
432
|
+
message: `Could not parse output of "${newBin} release-notes --since ${fromVersion}".`
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
out.binary.reexeced = true;
|
|
436
|
+
} else {
|
|
437
|
+
out.warnings.push({
|
|
438
|
+
code: "update_not_verified",
|
|
439
|
+
message: `Install completed but \`${newBin} --version\` still reports ${newVersion || "unknown"}. The active binary may not have changed \u2014 check your PATH or run "${cmd[0]} ${cmd[1].join(" ")}" manually and verify.`
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
} else {
|
|
443
|
+
out.warnings.push({
|
|
444
|
+
code: "update_not_verified",
|
|
445
|
+
message: `Install completed but \`which chrome-relay\` did not return a path. Could not verify the active binary changed.`
|
|
446
|
+
});
|
|
314
447
|
}
|
|
315
448
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
changes
|
|
321
|
-
}, null, 2) + "\n");
|
|
449
|
+
if (out.releaseNotes.source === "current_process") {
|
|
450
|
+
out.releaseNotes.changes = listReleaseNotesSince(fromVersion);
|
|
451
|
+
}
|
|
452
|
+
process.stdout.write(JSON.stringify(out, null, 2) + "\n");
|
|
322
453
|
});
|
|
323
454
|
program.command("release-notes").description("Print release notes since a version (no install). JSON output for agents.").option("--since <version>", "show release notes for versions newer than this", "0.0.0").action((opts) => {
|
|
324
455
|
const changes = listReleaseNotesSince(opts.since);
|
|
@@ -328,77 +459,8 @@ Notes:
|
|
|
328
459
|
changes
|
|
329
460
|
}, null, 2) + "\n");
|
|
330
461
|
});
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
const result = await callTool(name, args);
|
|
334
|
-
if (typeof result === "string") {
|
|
335
|
-
process.stdout.write(result + "\n");
|
|
336
|
-
} else {
|
|
337
|
-
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
338
|
-
}
|
|
339
|
-
} catch (error) {
|
|
340
|
-
if (error instanceof RelayError) {
|
|
341
|
-
process.stderr.write(error.message + "\n");
|
|
342
|
-
process.stderr.write(JSON.stringify({ relayError: error.toBridgeError() }, null, 2) + "\n");
|
|
343
|
-
} else {
|
|
344
|
-
process.stderr.write(
|
|
345
|
-
(error instanceof Error ? error.message : String(error)) + "\n"
|
|
346
|
-
);
|
|
347
|
-
}
|
|
348
|
-
process.exit(1);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
function tabOpt(cmd) {
|
|
352
|
-
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`)");
|
|
353
|
-
}
|
|
354
|
-
function baseArgs(opts) {
|
|
355
|
-
const parentOpts = program.opts();
|
|
356
|
-
rejectIntraScopeConflict("subcommand", {
|
|
357
|
-
tab: opts.tab,
|
|
358
|
-
workspace: opts.workspace,
|
|
359
|
-
group: opts.group
|
|
360
|
-
});
|
|
361
|
-
rejectIntraScopeConflict("program-level", {
|
|
362
|
-
workspace: parentOpts.workspace,
|
|
363
|
-
group: parentOpts.group
|
|
364
|
-
});
|
|
365
|
-
if (opts.workspace && parentOpts.workspace && opts.workspace !== parentOpts.workspace) {
|
|
366
|
-
emitTargetOverride("workspace", parentOpts.workspace, opts.workspace);
|
|
367
|
-
}
|
|
368
|
-
if (opts.group && parentOpts.group && opts.group !== parentOpts.group) {
|
|
369
|
-
emitTargetOverride("group", parentOpts.group, opts.group);
|
|
370
|
-
}
|
|
371
|
-
if (opts.tab !== void 0 && (parentOpts.workspace || parentOpts.group)) {
|
|
372
|
-
const prior = parentOpts.workspace ? `workspace=${parentOpts.workspace}` : `group=${parentOpts.group}`;
|
|
373
|
-
emitTargetOverride("tab", prior, String(opts.tab));
|
|
374
|
-
}
|
|
375
|
-
const args = {};
|
|
376
|
-
if (opts.tab !== void 0) args.tabId = opts.tab;
|
|
377
|
-
const effectiveWorkspace = opts.workspace ?? parentOpts.workspace;
|
|
378
|
-
const effectiveGroup = opts.group ?? parentOpts.group;
|
|
379
|
-
if (opts.tab === void 0 && effectiveWorkspace) args.workspaceName = effectiveWorkspace;
|
|
380
|
-
if (opts.tab === void 0 && effectiveGroup) args.groupName = effectiveGroup;
|
|
381
|
-
return args;
|
|
382
|
-
}
|
|
383
|
-
function rejectIntraScopeConflict(scope, fields) {
|
|
384
|
-
const present = [];
|
|
385
|
-
if (fields.tab !== void 0) present.push("--tab");
|
|
386
|
-
if (fields.workspace) present.push("--workspace");
|
|
387
|
-
if (fields.group) present.push("--group");
|
|
388
|
-
if (present.length > 1) {
|
|
389
|
-
process.stderr.write(
|
|
390
|
-
`[chrome-relay] target_conflict: ${scope} flags ${present.join(" + ")} are mutually exclusive. Pass exactly one of --tab, --workspace, or --group on the same ${scope}.
|
|
391
|
-
`
|
|
392
|
-
);
|
|
393
|
-
process.exit(2);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
function emitTargetOverride(kind, from, to) {
|
|
397
|
-
process.stderr.write(
|
|
398
|
-
`[chrome-relay] target_overridden: ${kind} ${from} \u2192 ${to} (subcommand-level overrides program-level)
|
|
399
|
-
`
|
|
400
|
-
);
|
|
401
|
-
}
|
|
462
|
+
const run = runTool;
|
|
463
|
+
const baseArgs = makeBaseArgs(program);
|
|
402
464
|
program.command("tabs [verb]").description("List open Chrome windows and tabs. (verb 'list' is accepted as alias)").action(async (verb) => {
|
|
403
465
|
if (verb && verb !== "list") {
|
|
404
466
|
process.stderr.write(`unknown tabs verb: ${verb}. Use 'tabs' or 'tabs list'.
|
package/dist/index.js
CHANGED
package/dist/native-host.js
CHANGED
|
@@ -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.
|
|
51
|
+
var CHROME_RELAY_VERSION = true ? "0.5.8" : "0.0.0-dev";
|
|
52
52
|
|
|
53
53
|
// src/release-notes.ts
|
|
54
54
|
function compareSemver(a, b) {
|