codeam-cli 2.60.22 → 2.60.23

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/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to `codeam-cli` are documented here.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.60.22] — 2026-07-09
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Baton — late-bind Codex's session id instead of blocking start()
12
+
7
13
  ## [2.60.21] — 2026-07-09
8
14
 
9
15
  ### Fixed
package/dist/index.js CHANGED
@@ -5680,7 +5680,7 @@ function readAnonId() {
5680
5680
  }
5681
5681
  function superProperties() {
5682
5682
  return {
5683
- cliVersion: true ? "2.60.22" : "0.0.0-dev",
5683
+ cliVersion: true ? "2.60.23" : "0.0.0-dev",
5684
5684
  nodeVersion: process.version,
5685
5685
  platform: process.platform,
5686
5686
  arch: process.arch,
@@ -5861,7 +5861,7 @@ var os4 = __toESM(require("os"));
5861
5861
  // package.json
5862
5862
  var package_default = {
5863
5863
  name: "codeam-cli",
5864
- version: "2.60.22",
5864
+ version: "2.60.23",
5865
5865
  description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
5866
5866
  type: "commonjs",
5867
5867
  main: "dist/index.js",
@@ -6932,7 +6932,7 @@ var CommandRelayService = class {
6932
6932
  // fresh + clear the "CLI update available" banner after a self-update
6933
6933
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
6934
6934
  // pair/reconnect). Older backends ignore the extra field.
6935
- ..."2.60.22" ? { ideVersion: "2.60.22" } : {}
6935
+ ..."2.60.23" ? { ideVersion: "2.60.23" } : {}
6936
6936
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6937
6937
  }
6938
6938
  /**
@@ -13420,7 +13420,7 @@ function coderabbitLoginLauncher(os49) {
13420
13420
  return ensureCoderabbitInstalled(os49);
13421
13421
  },
13422
13422
  launch() {
13423
- return (0, import_node_child_process7.spawn)("coderabbit", ["login"], { stdio: "inherit" });
13423
+ return (0, import_node_child_process7.spawn)("coderabbit", ["auth", "login"], { stdio: "inherit" });
13424
13424
  }
13425
13425
  };
13426
13426
  }
@@ -13429,31 +13429,166 @@ function coderabbitLoginLauncher(os49) {
13429
13429
  var HUNK_LINE_RE = /^([^\s:][^:]*?):(\d+)[\s:—-]+(?:\[?(info|warn|warning|error|critical)\]?[:\s—-]+)?(.+)$/i;
13430
13430
  var SEVERITY_MAP = {
13431
13431
  info: "info",
13432
+ note: "info",
13433
+ low: "info",
13434
+ minor: "info",
13432
13435
  warn: "warn",
13433
13436
  warning: "warn",
13437
+ medium: "warn",
13438
+ major: "warn",
13434
13439
  error: "error",
13435
- critical: "error"
13440
+ critical: "error",
13441
+ high: "error",
13442
+ blocker: "error"
13436
13443
  };
13437
- function parseReview(stdout) {
13444
+ function normSeverity(v) {
13445
+ if (typeof v !== "string") return void 0;
13446
+ return SEVERITY_MAP[v.trim().toLowerCase()];
13447
+ }
13448
+ function pick(obj, keys) {
13449
+ for (const k2 of keys) {
13450
+ if (obj[k2] !== void 0 && obj[k2] !== null) return obj[k2];
13451
+ }
13452
+ return void 0;
13453
+ }
13454
+ function asString(v) {
13455
+ return typeof v === "string" && v.trim().length > 0 ? v : void 0;
13456
+ }
13457
+ function pickLine(obj) {
13458
+ const direct = pick(obj, ["line", "start_line", "startLine", "line_number", "lineNumber"]);
13459
+ if (typeof direct === "number") return direct;
13460
+ if (typeof direct === "string" && /^\d+$/.test(direct)) return Number(direct);
13461
+ const range = pick(obj, ["line_range", "lineRange", "range", "lines"]);
13462
+ if (Array.isArray(range) && typeof range[0] === "number") return range[0];
13463
+ if (range && typeof range === "object") {
13464
+ const start2 = pick(range, ["start", "begin", "from"]);
13465
+ if (typeof start2 === "number") return start2;
13466
+ if (start2 && typeof start2 === "object") {
13467
+ const l = start2.line;
13468
+ if (typeof l === "number") return l;
13469
+ }
13470
+ }
13471
+ return void 0;
13472
+ }
13473
+ function toHunk(raw, groupSeverity) {
13474
+ if (!raw || typeof raw !== "object") return null;
13475
+ const o = raw;
13476
+ const path70 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename"])) ?? asString(pick(o, ["location"])?.path);
13477
+ if (!path70) return null;
13478
+ const message = asString(pick(o, ["comment", "message", "body", "description", "summary", "markdown", "text"])) ?? "";
13479
+ const title = asString(pick(o, ["title", "rule", "category", "check"]));
13480
+ const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
13481
+ const locObj = pick(o, ["location"]) ?? o;
13482
+ return {
13483
+ path: path70.trim(),
13484
+ line: pickLine(o) ?? pickLine(locObj),
13485
+ severity,
13486
+ message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
13487
+ };
13488
+ }
13489
+ function findingsFrom(value) {
13490
+ const out2 = [];
13491
+ if (!value || typeof value !== "object") return out2;
13492
+ const root = value;
13493
+ const flat = pick(root, ["findings", "comments", "issues", "results", "review_comments", "reviewComments"]);
13494
+ if (Array.isArray(flat)) {
13495
+ for (const f of flat) {
13496
+ const h = toHunk(f);
13497
+ if (h) out2.push(h);
13498
+ }
13499
+ }
13500
+ const grouped = flat && !Array.isArray(flat) ? flat : root;
13501
+ for (const sev of ["critical", "warning", "warn", "error", "info", "note"]) {
13502
+ const bucket = grouped[sev];
13503
+ if (Array.isArray(bucket)) {
13504
+ for (const f of bucket) {
13505
+ const h = toHunk(f, sev);
13506
+ if (h) out2.push(h);
13507
+ }
13508
+ }
13509
+ }
13510
+ return out2;
13511
+ }
13512
+ function errorFrom(obj) {
13513
+ if (obj.type !== "error") return void 0;
13514
+ return asString(pick(obj, ["message", "error"]));
13515
+ }
13516
+ function isControlEvent(obj) {
13517
+ return obj.type === "review_context" || obj.type === "status" || obj.type === "progress" || obj.type === "error";
13518
+ }
13519
+ function parseStructured(stdout) {
13520
+ const trimmed = stdout.trim();
13521
+ if (!trimmed || trimmed[0] !== "{" && trimmed[0] !== "[") return null;
13522
+ try {
13523
+ const doc = JSON.parse(trimmed);
13524
+ const hunks2 = findingsFrom(Array.isArray(doc) ? { findings: doc } : doc);
13525
+ const summary2 = asString(
13526
+ pick(Array.isArray(doc) ? {} : doc, ["summary", "markdown", "report", "overview"])
13527
+ );
13528
+ if (hunks2.length > 0 || summary2) return { hunks: hunks2, summary: summary2 };
13529
+ } catch {
13530
+ }
13438
13531
  const hunks = [];
13439
- const lines = stdout.split(/\r?\n/);
13440
- for (const line of lines) {
13532
+ let summary;
13533
+ let error;
13534
+ let sawJson = false;
13535
+ for (const line of trimmed.split(/\r?\n/)) {
13536
+ const l = line.trim();
13537
+ if (!l || l[0] !== "{" && l[0] !== "[") continue;
13538
+ try {
13539
+ const obj = JSON.parse(l);
13540
+ sawJson = true;
13541
+ const rec = Array.isArray(obj) ? {} : obj;
13542
+ error ??= errorFrom(rec);
13543
+ if (isControlEvent(rec)) continue;
13544
+ const found = findingsFrom(Array.isArray(obj) ? { findings: obj } : obj);
13545
+ if (found.length > 0) hunks.push(...found);
13546
+ else {
13547
+ const single = toHunk(obj);
13548
+ if (single) hunks.push(single);
13549
+ }
13550
+ summary ??= asString(pick(rec, ["summary", "markdown", "report"]));
13551
+ } catch {
13552
+ }
13553
+ }
13554
+ return sawJson ? { hunks, summary, error } : null;
13555
+ }
13556
+ function parsePlain(stdout) {
13557
+ const hunks = [];
13558
+ for (const line of stdout.split(/\r?\n/)) {
13441
13559
  const m = line.match(HUNK_LINE_RE);
13442
13560
  if (!m) continue;
13443
13561
  const [, path70, lineNo, sevToken, message] = m;
13444
13562
  if (!path70 || !lineNo || !message) continue;
13445
- const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
13446
13563
  hunks.push({
13447
13564
  path: path70.trim(),
13448
13565
  line: Number(lineNo),
13449
13566
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
13450
- message: cleanedMessage
13567
+ message: message.trim().replace(/^[*-]\s+/, "")
13451
13568
  });
13452
13569
  }
13570
+ return hunks;
13571
+ }
13572
+ function severityCounts(hunks) {
13573
+ const c2 = { error: 0, warn: 0, info: 0 };
13574
+ for (const h of hunks) if (h.severity) c2[h.severity] += 1;
13575
+ return c2;
13576
+ }
13577
+ function parseReview(stdout) {
13578
+ const structured = parseStructured(stdout);
13579
+ const hunks = structured && structured.hunks.length > 0 ? structured.hunks : parsePlain(stdout);
13580
+ const counts = severityCounts(hunks);
13581
+ const markdown = (structured?.summary ?? (hunks.length === 0 && structured?.error ? structured.error : stdout)).trim();
13453
13582
  return {
13454
- markdown: stdout.trim(),
13583
+ markdown,
13455
13584
  hunks,
13456
- stats: { linesReviewed: lines.length, hunkCount: hunks.length }
13585
+ stats: {
13586
+ findingCount: hunks.length,
13587
+ critical: counts.error,
13588
+ warning: counts.warn,
13589
+ info: counts.info,
13590
+ ...structured?.error ? { error: structured.error } : {}
13591
+ }
13457
13592
  };
13458
13593
  }
13459
13594
 
@@ -13467,7 +13602,7 @@ var CoderabbitRuntimeStrategy = class {
13467
13602
  this.os = os49;
13468
13603
  }
13469
13604
  getDefaultArgs() {
13470
- return ["review"];
13605
+ return ["review", "--agent"];
13471
13606
  }
13472
13607
  async prepareInvocation(input) {
13473
13608
  const binary = this.os.findInPath(this.meta.binaryName);
@@ -13476,14 +13611,12 @@ var CoderabbitRuntimeStrategy = class {
13476
13611
  `CodeRabbit binary "${this.meta.binaryName}" not on PATH. Run \`codeam link coderabbit\` to install it first.`
13477
13612
  );
13478
13613
  }
13479
- const args2 = this.getDefaultArgs();
13480
- if (input.prRef) args2.push("--pr", input.prRef);
13481
- if (input.files && input.files.length > 0) {
13482
- args2.push(...input.files);
13483
- }
13484
- if (input.prompt) {
13485
- args2.push("--message", input.prompt);
13486
- }
13614
+ const args2 = input.structured === false ? ["review", "--plain"] : this.getDefaultArgs();
13615
+ if (input.changeSet) args2.push("--type", input.changeSet);
13616
+ if (input.base) args2.push("--base", input.base);
13617
+ if (input.baseCommit) args2.push("--base-commit", input.baseCommit);
13618
+ if (input.dir) args2.push("--dir", input.dir);
13619
+ if (input.apiKey) args2.push("--api-key", input.apiKey);
13487
13620
  if (input.extraArgs && input.extraArgs.length > 0) {
13488
13621
  args2.push(...input.extraArgs);
13489
13622
  }
@@ -13791,10 +13924,20 @@ var CursorRuntimeStrategy = class {
13791
13924
  * failure. `cursor-agent create-chat` prints a bare UUID and exits 0 (verified
13792
13925
  * on cursor-agent 2026.06.24). Synchronous + bounded so prepareLaunch stays a
13793
13926
  * single deterministic step; a timeout/parse failure just disables pre-mint.
13927
+ *
13928
+ * ⚠️ Windows: `findInPath` resolves `cursor-agent.cmd` (or `.ps1`) via PATHEXT,
13929
+ * and Windows CANNOT spawn a `.cmd`/`.bat`/`.ps1` directly — it needs
13930
+ * `cmd.exe /c` / `powershell -File`. Spawning `binary` raw (as this used to)
13931
+ * failed with EINVAL on Windows → null id → no pre-mint → the baton threw
13932
+ * "agent did not expose a session id after spawn" (Windows-only). Route the
13933
+ * spawn through `os.buildLaunch`, exactly like the TUI launch above, so the
13934
+ * command is wrapped correctly per-platform. On macOS/Linux buildLaunch returns
13935
+ * the bare `{cmd: binary, args: ['create-chat']}` → behaviour unchanged.
13794
13936
  */
13795
13937
  mintChatId(binary) {
13796
13938
  try {
13797
- const r = (0, import_node_child_process10.spawnSync)(binary, ["create-chat"], {
13939
+ const launch = this.os.buildLaunch(binary, ["create-chat"]);
13940
+ const r = (0, import_node_child_process10.spawnSync)(launch.cmd, launch.args, {
13798
13941
  encoding: "utf8",
13799
13942
  timeout: 2e4,
13800
13943
  stdio: ["ignore", "pipe", "pipe"]
@@ -16733,7 +16876,7 @@ async function autoUpgradeBeforeCriticalCommand() {
16733
16876
  if (process.env.NODE_ENV === "test") return;
16734
16877
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16735
16878
  if (process.env.CI) return;
16736
- const current = true ? "2.60.22" : null;
16879
+ const current = true ? "2.60.23" : null;
16737
16880
  if (!current) return;
16738
16881
  const cache = readCache();
16739
16882
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16750,7 +16893,7 @@ function checkForUpdates() {
16750
16893
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16751
16894
  if (process.env.CI) return;
16752
16895
  if (!process.stdout.isTTY) return;
16753
- const current = true ? "2.60.22" : null;
16896
+ const current = true ? "2.60.23" : null;
16754
16897
  if (!current) return;
16755
16898
  const cache = readCache();
16756
16899
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16770,7 +16913,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
16770
16913
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
16771
16914
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
16772
16915
  function currentCliVersion() {
16773
- return true ? "2.60.22" : null;
16916
+ return true ? "2.60.23" : null;
16774
16917
  }
16775
16918
  function runCmd(cmd, args2, timeoutMs) {
16776
16919
  return new Promise((resolve7) => {
@@ -33663,7 +33806,7 @@ function checkChokidar() {
33663
33806
  }
33664
33807
  async function doctor(args2 = []) {
33665
33808
  const json = args2.includes("--json");
33666
- const cliVersion = true ? "2.60.22" : "0.0.0-dev";
33809
+ const cliVersion = true ? "2.60.23" : "0.0.0-dev";
33667
33810
  const apiBase2 = resolveApiBaseUrl();
33668
33811
  const diagnosticId = (0, import_node_crypto12.randomUUID)();
33669
33812
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -33862,7 +34005,7 @@ async function completion(args2) {
33862
34005
  // src/commands/version.ts
33863
34006
  var import_picocolors15 = __toESM(require("picocolors"));
33864
34007
  function version2() {
33865
- const v = true ? "2.60.22" : "unknown";
34008
+ const v = true ? "2.60.23" : "unknown";
33866
34009
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
33867
34010
  }
33868
34011
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.60.22",
3
+ "version": "2.60.23",
4
4
  "description": "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device — async. The terminal companion for CodeAgent Mobile.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/index.js",