codeam-cli 2.60.43 → 2.60.45

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.44] — 2026-07-10
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Recover ACP adapter install-race crashes structurally, not by error-code list
12
+
13
+ ## [2.60.43] — 2026-07-10
14
+
15
+ ### Fixed
16
+
17
+ - **cli:** Keep relay daemon alive on stray unhandled rejection
18
+
7
19
  ## [2.60.42] — 2026-07-10
8
20
 
9
21
  ### Added
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.43" : "0.0.0-dev",
5692
+ cliVersion: true ? "2.60.45" : "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.43",
5873
+ version: "2.60.45",
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",
@@ -6979,7 +6979,7 @@ var CommandRelayService = class {
6979
6979
  // fresh + clear the "CLI update available" banner after a self-update
6980
6980
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
6981
6981
  // pair/reconnect). Older backends ignore the extra field.
6982
- ..."2.60.43" ? { ideVersion: "2.60.43" } : {}
6982
+ ..."2.60.45" ? { ideVersion: "2.60.45" } : {}
6983
6983
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6984
6984
  }
6985
6985
  /**
@@ -17493,7 +17493,7 @@ async function autoUpgradeBeforeCriticalCommand() {
17493
17493
  if (process.env.NODE_ENV === "test") return;
17494
17494
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17495
17495
  if (process.env.CI) return;
17496
- const current = true ? "2.60.43" : null;
17496
+ const current = true ? "2.60.45" : null;
17497
17497
  if (!current) return;
17498
17498
  const cache = readCache();
17499
17499
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17510,7 +17510,7 @@ function checkForUpdates() {
17510
17510
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17511
17511
  if (process.env.CI) return;
17512
17512
  if (!process.stdout.isTTY) return;
17513
- const current = true ? "2.60.43" : null;
17513
+ const current = true ? "2.60.45" : null;
17514
17514
  if (!current) return;
17515
17515
  const cache = readCache();
17516
17516
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17530,7 +17530,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
17530
17530
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
17531
17531
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
17532
17532
  function currentCliVersion() {
17533
- return true ? "2.60.43" : null;
17533
+ return true ? "2.60.45" : null;
17534
17534
  }
17535
17535
  function runCmd(cmd, args2, timeoutMs) {
17536
17536
  return new Promise((resolve7) => {
@@ -23317,7 +23317,8 @@ async function waitForCursorAgent(opts = {}) {
23317
23317
  }
23318
23318
  return check();
23319
23319
  }
23320
- var ADAPTER_MODULE_LOAD_ERROR_RE = /ERR_MODULE_NOT_FOUND|Cannot find module|ERR_REQUIRE_ESM|ERR_UNKNOWN_BUILTIN_MODULE|SyntaxError|Unexpected (token|end|identifier)|missing \) after argument list/i;
23320
+ var ADAPTER_MODULE_LOAD_ERROR_RE = /ERR_MODULE_NOT_FOUND|Cannot find module|ERR_REQUIRE_ESM|ERR_UNKNOWN_BUILTIN_MODULE|ERR_UNSUPPORTED_DIR_IMPORT|ERR_PACKAGE_PATH_NOT_EXPORTED|ERR_INVALID_PACKAGE_CONFIG|ERR_INVALID_PACKAGE_TARGET|ERR_INVALID_MODULE_SPECIFIER|node:internal\/modules\/|Directory import|SyntaxError|Unexpected (token|end|identifier)|missing \) after argument list/i;
23321
+ var PERMANENT_ADAPTER_STARTUP_RE = /IneligibleTierError|UNSUPPORTED_CLIENT|no longer supported for Gemini Code Assist|not eligible for Gemini Code Assist|Error authenticating|ProjectIdRequiredError/i;
23321
23322
  function probeAdapterModuleGraph(command2, args2, opts = {}) {
23322
23323
  const livenessMs = opts.livenessMs ?? 400;
23323
23324
  const spawnFn = opts.spawnFn ?? import_child_process25.spawn;
@@ -23348,7 +23349,7 @@ function probeAdapterModuleGraph(command2, args2, opts = {}) {
23348
23349
  });
23349
23350
  child.on("error", () => finish("ok"));
23350
23351
  child.on("exit", (code) => {
23351
- if (code !== 0 && code !== null && ADAPTER_MODULE_LOAD_ERROR_RE.test(stderr)) {
23352
+ if (code !== 0 && code !== null && !PERMANENT_ADAPTER_STARTUP_RE.test(stderr)) {
23352
23353
  finish("transient");
23353
23354
  } else {
23354
23355
  finish("ok");
@@ -26627,6 +26628,14 @@ function createIdleTimeout(idleMs, makeError) {
26627
26628
  // src/agents/acp/client.ts
26628
26629
  var TRANSIENT_ADAPTER_SPAWN_RE = /ETXTBSY|ENOENT/;
26629
26630
  var MAX_START_ATTEMPTS = 5;
26631
+ var TRANSPORT_DOWN_DURING_START_RE = /connection (is )?closed|stream (is )?closed|ECONNRESET|EPIPE|write after end|premature close/i;
26632
+ var AdapterStartCrashError = class extends Error {
26633
+ adapterExitedDuringStart = true;
26634
+ constructor(message) {
26635
+ super(message);
26636
+ this.name = "AdapterStartCrashError";
26637
+ }
26638
+ };
26630
26639
  var _acpStartSeam = {
26631
26640
  sleep: (ms) => new Promise((r) => setTimeout(r, ms))
26632
26641
  };
@@ -26731,6 +26740,7 @@ var AcpClient = class {
26731
26740
  * Checks the thrown error's message/data AND the adapter stderr ring — the
26732
26741
  * adapter logs the real cause to stderr while returning a generic error. */
26733
26742
  isTransientAdapterSpawn(err) {
26743
+ if (err instanceof AdapterStartCrashError) return true;
26734
26744
  const parts = [...this.recentStderr];
26735
26745
  if (err instanceof Error) parts.push(err.message);
26736
26746
  if (err && typeof err === "object") {
@@ -26742,7 +26752,9 @@ var AcpClient = class {
26742
26752
  if (typeof e.details === "string") parts.push(e.details);
26743
26753
  }
26744
26754
  const joined = parts.join(" ");
26745
- return TRANSIENT_ADAPTER_SPAWN_RE.test(joined) || ADAPTER_MODULE_LOAD_ERROR_RE.test(joined);
26755
+ return TRANSIENT_ADAPTER_SPAWN_RE.test(joined) || ADAPTER_MODULE_LOAD_ERROR_RE.test(joined) || // The transport dying mid-handshake = the adapter crashed starting up,
26756
+ // even when the child-exit handler lost the race (see the RE's doc).
26757
+ TRANSPORT_DOWN_DURING_START_RE.test(joined);
26746
26758
  }
26747
26759
  async startOnce() {
26748
26760
  if (this.child) throw new Error("AcpClient already started");
@@ -26784,7 +26796,7 @@ var AcpClient = class {
26784
26796
  if (this.startAbortReject) {
26785
26797
  const tail = this.recentStderr.slice(-6).join(" | ");
26786
26798
  this.startAbortReject(
26787
- new Error(
26799
+ new AdapterStartCrashError(
26788
26800
  `ADAPTER_EXITED_DURING_START code=${code} signal=${signal}${tail ? ` \u2014 ${tail}` : ""}`
26789
26801
  )
26790
26802
  );
@@ -27064,9 +27076,22 @@ var AcpClient = class {
27064
27076
  }
27065
27077
  if (u2.sessionUpdate === "tool_call_update" && (u2.status === "completed" || u2.status === "failed")) {
27066
27078
  if (typeof u2.toolCallId === "string") this.pendingToolCalls.delete(u2.toolCallId);
27067
- if (this.pendingToolCalls.size === 0) this.promptIdle?.bump();
27079
+ this.rearmIdleIfIdle();
27068
27080
  return;
27069
27081
  }
27082
+ this.rearmIdleIfIdle();
27083
+ }
27084
+ /**
27085
+ * Re-arm the idle watchdog ONLY when the agent is genuinely idle — no tool
27086
+ * call in flight. A pending tool (a `yarn install` / build / test that runs
27087
+ * silently for minutes, emitting no `session/update`) is active work, NOT a
27088
+ * wedged adapter, so re-arming the 90s window over it would false-kill the
27089
+ * turn. Every re-arm MUST route through here so no path can accidentally arm
27090
+ * the watchdog while a tool is executing (the 2026-07-10 bug: the
27091
+ * auto-approve permission `finally` bumped unconditionally → a ~150s
27092
+ * `yarn install` tripped "ACP prompt idle for 90s").
27093
+ */
27094
+ rearmIdleIfIdle() {
27070
27095
  if (this.pendingToolCalls.size === 0) this.promptIdle?.bump();
27071
27096
  }
27072
27097
  // ─── Client surface (what the agent calls into) ───────────────────
@@ -27081,7 +27106,7 @@ var AcpClient = class {
27081
27106
  try {
27082
27107
  return await this.opts.onRequestPermission(params);
27083
27108
  } finally {
27084
- this.promptIdle?.bump();
27109
+ this.rearmIdleIfIdle();
27085
27110
  }
27086
27111
  },
27087
27112
  readTextFile: async (params) => {
@@ -34666,7 +34691,7 @@ function checkChokidar() {
34666
34691
  }
34667
34692
  async function doctor(args2 = []) {
34668
34693
  const json = args2.includes("--json");
34669
- const cliVersion = true ? "2.60.43" : "0.0.0-dev";
34694
+ const cliVersion = true ? "2.60.45" : "0.0.0-dev";
34670
34695
  const apiBase2 = resolveApiBaseUrl();
34671
34696
  const diagnosticId = (0, import_node_crypto12.randomUUID)();
34672
34697
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -34865,7 +34890,7 @@ async function completion(args2) {
34865
34890
  // src/commands/version.ts
34866
34891
  var import_picocolors15 = __toESM(require("picocolors"));
34867
34892
  function version2() {
34868
- const v = true ? "2.60.43" : "unknown";
34893
+ const v = true ? "2.60.45" : "unknown";
34869
34894
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
34870
34895
  }
34871
34896
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.60.43",
3
+ "version": "2.60.45",
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",