codeam-cli 2.60.36 → 2.60.38

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,18 @@ 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.37] — 2026-07-10
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Time-bound CodeRabbit one-shot so a hung review can't wedge the relay
12
+
13
+ ## [2.60.36] — 2026-07-10
14
+
15
+ ### Fixed
16
+
17
+ - **cli:** CodeRabbit link must preserve the session (it rides the live session)
18
+
7
19
  ## [2.60.35] — 2026-07-10
8
20
 
9
21
  ### Fixed
package/dist/index.js CHANGED
@@ -5689,7 +5689,7 @@ function readAnonId() {
5689
5689
  }
5690
5690
  function superProperties() {
5691
5691
  return {
5692
- cliVersion: true ? "2.60.36" : "0.0.0-dev",
5692
+ cliVersion: true ? "2.60.38" : "0.0.0-dev",
5693
5693
  nodeVersion: process.version,
5694
5694
  platform: process.platform,
5695
5695
  arch: process.arch,
@@ -5870,7 +5870,7 @@ var os4 = __toESM(require("os"));
5870
5870
  // package.json
5871
5871
  var package_default = {
5872
5872
  name: "codeam-cli",
5873
- version: "2.60.36",
5873
+ version: "2.60.38",
5874
5874
  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.",
5875
5875
  type: "commonjs",
5876
5876
  main: "dist/index.js",
@@ -6963,7 +6963,7 @@ var CommandRelayService = class {
6963
6963
  // fresh + clear the "CLI update available" banner after a self-update
6964
6964
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
6965
6965
  // pair/reconnect). Older backends ignore the extra field.
6966
- ..."2.60.36" ? { ideVersion: "2.60.36" } : {}
6966
+ ..."2.60.38" ? { ideVersion: "2.60.38" } : {}
6967
6967
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6968
6968
  }
6969
6969
  /**
@@ -13528,9 +13528,20 @@ function pickLine(obj) {
13528
13528
  function toHunk(raw, groupSeverity) {
13529
13529
  if (!raw || typeof raw !== "object") return null;
13530
13530
  const o = raw;
13531
- const path72 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename"])) ?? asString(pick(o, ["location"])?.path);
13531
+ const path72 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
13532
13532
  if (!path72) return null;
13533
- const message = asString(pick(o, ["comment", "message", "body", "description", "summary", "markdown", "text"])) ?? "";
13533
+ const message = asString(
13534
+ pick(o, [
13535
+ "comment",
13536
+ "message",
13537
+ "body",
13538
+ "description",
13539
+ "codegenInstructions",
13540
+ "summary",
13541
+ "markdown",
13542
+ "text"
13543
+ ])
13544
+ ) ?? "";
13534
13545
  const title = asString(pick(o, ["title", "rule", "category", "check"]));
13535
13546
  const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
13536
13547
  const locObj = pick(o, ["location"]) ?? o;
@@ -13569,7 +13580,11 @@ function errorFrom(obj) {
13569
13580
  return asString(pick(obj, ["message", "error"]));
13570
13581
  }
13571
13582
  function isControlEvent(obj) {
13572
- return obj.type === "review_context" || obj.type === "status" || obj.type === "progress" || obj.type === "error";
13583
+ return obj.type === "review_context" || obj.type === "status" || obj.type === "progress" || obj.type === "heartbeat" || obj.type === "error";
13584
+ }
13585
+ function summaryFrom(obj) {
13586
+ if (obj.type !== "summary") return void 0;
13587
+ return asString(pick(obj, ["content", "text", "markdown", "summary", "body"]));
13573
13588
  }
13574
13589
  function parseStructured(stdout) {
13575
13590
  const trimmed = stdout.trim();
@@ -13595,6 +13610,7 @@ function parseStructured(stdout) {
13595
13610
  sawJson = true;
13596
13611
  const rec = Array.isArray(obj) ? {} : obj;
13597
13612
  error ??= errorFrom(rec);
13613
+ summary ??= summaryFrom(rec);
13598
13614
  if (isControlEvent(rec)) continue;
13599
13615
  const found = findingsFrom(Array.isArray(obj) ? { findings: obj } : obj);
13600
13616
  if (found.length > 0) hunks.push(...found);
@@ -13624,6 +13640,14 @@ function parsePlain(stdout) {
13624
13640
  }
13625
13641
  return hunks;
13626
13642
  }
13643
+ function synthesizeSummary(counts, total) {
13644
+ const parts = [];
13645
+ if (counts.error) parts.push(`${counts.error} critical`);
13646
+ if (counts.warn) parts.push(`${counts.warn} warning`);
13647
+ if (counts.info) parts.push(`${counts.info} suggestion${counts.info === 1 ? "" : "s"}`);
13648
+ const noun = total === 1 ? "finding" : "findings";
13649
+ return parts.length > 0 ? `CodeRabbit found ${total} ${noun} (${parts.join(", ")}).` : `CodeRabbit found ${total} ${noun}.`;
13650
+ }
13627
13651
  function severityCounts(hunks) {
13628
13652
  const c2 = { error: 0, warn: 0, info: 0 };
13629
13653
  for (const h of hunks) if (h.severity) c2[h.severity] += 1;
@@ -13633,7 +13657,21 @@ function parseReview(stdout) {
13633
13657
  const structured = parseStructured(stdout);
13634
13658
  const hunks = structured && structured.hunks.length > 0 ? structured.hunks : parsePlain(stdout);
13635
13659
  const counts = severityCounts(hunks);
13636
- const markdown = (structured?.summary ?? (hunks.length === 0 && structured?.error ? structured.error : stdout)).trim();
13660
+ let markdown;
13661
+ if (structured?.summary) {
13662
+ markdown = structured.summary;
13663
+ } else if (structured) {
13664
+ if (hunks.length === 0 && structured.error) {
13665
+ markdown = structured.error;
13666
+ } else if (hunks.length > 0) {
13667
+ markdown = synthesizeSummary(counts, hunks.length);
13668
+ } else {
13669
+ markdown = "";
13670
+ }
13671
+ } else {
13672
+ markdown = stdout;
13673
+ }
13674
+ markdown = markdown.trim();
13637
13675
  return {
13638
13676
  markdown,
13639
13677
  hunks,
@@ -13648,6 +13686,7 @@ function parseReview(stdout) {
13648
13686
  }
13649
13687
 
13650
13688
  // src/agents/coderabbit/runtime.ts
13689
+ var CODERABBIT_ONESHOT_TIMEOUT_MS = 5 * 6e4;
13651
13690
  var CoderabbitRuntimeStrategy = class {
13652
13691
  id = "coderabbit";
13653
13692
  meta = getAgent("coderabbit");
@@ -13697,11 +13736,47 @@ var CoderabbitRuntimeStrategy = class {
13697
13736
  env: { ...process.env, ...launch.env ?? {} },
13698
13737
  stdio: ["ignore", "pipe", "pipe"]
13699
13738
  });
13739
+ let settled = false;
13740
+ const finish = (out2) => {
13741
+ if (settled) return;
13742
+ settled = true;
13743
+ clearTimeout(timer);
13744
+ resolve7(out2);
13745
+ };
13746
+ const timer = setTimeout(() => {
13747
+ if (settled) return;
13748
+ try {
13749
+ proc.kill("SIGTERM");
13750
+ } catch {
13751
+ }
13752
+ setTimeout(() => {
13753
+ try {
13754
+ proc.kill("SIGKILL");
13755
+ } catch {
13756
+ }
13757
+ }, 2e3).unref?.();
13758
+ finish(
13759
+ this.parseOutput({
13760
+ exitCode: 124,
13761
+ stdout: Buffer.concat(stdoutBuf).toString("utf8"),
13762
+ stderr: Buffer.concat(stderrBuf).toString("utf8") + `
13763
+ CodeRabbit review timed out after ${Math.round(
13764
+ CODERABBIT_ONESHOT_TIMEOUT_MS / 6e4
13765
+ )} min and was terminated.`
13766
+ })
13767
+ );
13768
+ }, CODERABBIT_ONESHOT_TIMEOUT_MS);
13769
+ timer.unref?.();
13700
13770
  proc.stdout?.on("data", (b) => stdoutBuf.push(b));
13701
13771
  proc.stderr?.on("data", (b) => stderrBuf.push(b));
13702
- proc.on("error", (err) => reject(err));
13772
+ proc.on("error", (err) => {
13773
+ if (settled) return;
13774
+ settled = true;
13775
+ clearTimeout(timer);
13776
+ reject(err);
13777
+ });
13703
13778
  proc.on("close", (code) => {
13704
- resolve7(
13779
+ finish(
13705
13780
  this.parseOutput({
13706
13781
  exitCode: code ?? 0,
13707
13782
  stdout: Buffer.concat(stdoutBuf).toString("utf8"),
@@ -17293,7 +17368,7 @@ async function autoUpgradeBeforeCriticalCommand() {
17293
17368
  if (process.env.NODE_ENV === "test") return;
17294
17369
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17295
17370
  if (process.env.CI) return;
17296
- const current = true ? "2.60.36" : null;
17371
+ const current = true ? "2.60.38" : null;
17297
17372
  if (!current) return;
17298
17373
  const cache = readCache();
17299
17374
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17310,7 +17385,7 @@ function checkForUpdates() {
17310
17385
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17311
17386
  if (process.env.CI) return;
17312
17387
  if (!process.stdout.isTTY) return;
17313
- const current = true ? "2.60.36" : null;
17388
+ const current = true ? "2.60.38" : null;
17314
17389
  if (!current) return;
17315
17390
  const cache = readCache();
17316
17391
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17330,7 +17405,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
17330
17405
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
17331
17406
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
17332
17407
  function currentCliVersion() {
17333
- return true ? "2.60.36" : null;
17408
+ return true ? "2.60.38" : null;
17334
17409
  }
17335
17410
  function runCmd(cmd, args2, timeoutMs) {
17336
17411
  return new Promise((resolve7) => {
@@ -34390,7 +34465,7 @@ function checkChokidar() {
34390
34465
  }
34391
34466
  async function doctor(args2 = []) {
34392
34467
  const json = args2.includes("--json");
34393
- const cliVersion = true ? "2.60.36" : "0.0.0-dev";
34468
+ const cliVersion = true ? "2.60.38" : "0.0.0-dev";
34394
34469
  const apiBase2 = resolveApiBaseUrl();
34395
34470
  const diagnosticId = (0, import_node_crypto12.randomUUID)();
34396
34471
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -34589,7 +34664,7 @@ async function completion(args2) {
34589
34664
  // src/commands/version.ts
34590
34665
  var import_picocolors15 = __toESM(require("picocolors"));
34591
34666
  function version2() {
34592
- const v = true ? "2.60.36" : "unknown";
34667
+ const v = true ? "2.60.38" : "unknown";
34593
34668
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
34594
34669
  }
34595
34670
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.60.36",
3
+ "version": "2.60.38",
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",