codeam-cli 2.62.0 → 2.62.1

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.62.0] — 2026-08-13
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Make the Headroom proxy self-heal actually fire, and stop killing healthy proxies (#613)
12
+
7
13
  ## [2.61.99] — 2026-08-13
8
14
 
9
15
  ### Added
package/dist/index.js CHANGED
@@ -8022,7 +8022,7 @@ function readAnonId() {
8022
8022
  }
8023
8023
  function superProperties() {
8024
8024
  return {
8025
- cliVersion: true ? "2.62.0" : "0.0.0-dev",
8025
+ cliVersion: true ? "2.62.1" : "0.0.0-dev",
8026
8026
  nodeVersion: process.version,
8027
8027
  platform: process.platform,
8028
8028
  arch: process.arch,
@@ -8203,7 +8203,7 @@ var os4 = __toESM(require("os"));
8203
8203
  // package.json
8204
8204
  var package_default = {
8205
8205
  name: "codeam-cli",
8206
- version: "2.62.0",
8206
+ version: "2.62.1",
8207
8207
  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.",
8208
8208
  type: "commonjs",
8209
8209
  main: "dist/index.js",
@@ -8863,6 +8863,7 @@ function computePollDelay({ baseMs, failures }) {
8863
8863
  var fs7 = __toESM(require("fs"));
8864
8864
  var os7 = __toESM(require("os"));
8865
8865
  var path6 = __toESM(require("path"));
8866
+ var net = __toESM(require("net"));
8866
8867
 
8867
8868
  // src/services/headroom/proxy-process.ts
8868
8869
  var import_child_process2 = require("child_process");
@@ -9088,6 +9089,7 @@ function spawnHeadroomProxy(logging, opts = {}) {
9088
9089
 
9089
9090
  // src/services/headroom/proxy-supervisor.ts
9090
9091
  var PROXY_STARTUP_GRACE_MS = 45e3;
9092
+ var PRE_TURN_READY_TIMEOUT_MS = 15e4;
9091
9093
  async function ensureHeadroomProxy(deps) {
9092
9094
  if (!deps.isConfigured()) return "skip";
9093
9095
  let alive = false;
@@ -9119,11 +9121,19 @@ async function ensureHeadroomProxyReady(deps, opts = {}) {
9119
9121
  (deps.spawnProxyForce ?? deps.spawnProxy)();
9120
9122
  const sleep5 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
9121
9123
  const pollMs = opts.pollMs ?? 1500;
9122
- const maxPolls = Math.max(1, Math.ceil((opts.timeoutMs ?? 6e4) / pollMs));
9124
+ const maxPolls = Math.max(1, Math.ceil((opts.timeoutMs ?? PRE_TURN_READY_TIMEOUT_MS) / pollMs));
9123
9125
  for (let i = 0; i < maxPolls; i += 1) {
9124
9126
  await sleep5(pollMs);
9127
+ const elapsed = (i + 1) * pollMs / 1e3;
9125
9128
  if (await deps.probeAlive().catch(() => false)) {
9126
- log.info("headroom-supervisor", `proxy :8787 ready after ~${(i + 1) * pollMs / 1e3}s`);
9129
+ log.info("headroom-supervisor", `proxy :8787 ready after ~${elapsed}s`);
9130
+ return true;
9131
+ }
9132
+ if (await (deps.probePortOpen?.() ?? Promise.resolve(false)).catch(() => false)) {
9133
+ log.info(
9134
+ "headroom-supervisor",
9135
+ `proxy :8787 accepting connections after ~${elapsed}s (still warming \u2014 turn is safe to send)`
9136
+ );
9127
9137
  return true;
9128
9138
  }
9129
9139
  }
@@ -9166,6 +9176,20 @@ async function probeProxyAliveReal() {
9166
9176
  clearTimeout(timer);
9167
9177
  }
9168
9178
  }
9179
+ async function probeProxyPortOpenReal() {
9180
+ return new Promise((resolve9) => {
9181
+ const socket = net.connect({ host: "127.0.0.1", port: 8787 });
9182
+ const done = (ok) => {
9183
+ socket.removeAllListeners();
9184
+ socket.destroy();
9185
+ resolve9(ok);
9186
+ };
9187
+ socket.setTimeout(2e3);
9188
+ socket.once("connect", () => done(true));
9189
+ socket.once("timeout", () => done(false));
9190
+ socket.once("error", () => done(false));
9191
+ });
9192
+ }
9169
9193
  function spawnProxyReal() {
9170
9194
  spawnHeadroomProxy({
9171
9195
  tag: "headroom-supervisor",
@@ -9177,6 +9201,7 @@ function makeRealProxySupervisorDeps() {
9177
9201
  return {
9178
9202
  isConfigured: () => isHeadroomConfiguredReal(),
9179
9203
  probeAlive: probeProxyAliveReal,
9204
+ probePortOpen: probeProxyPortOpenReal,
9180
9205
  proxyProcessAlive: () => isHeadroomProxyProcessAlive(),
9181
9206
  proxyStartupAgeMs: () => headroomProxyPidfileAgeMs(Date.now()),
9182
9207
  adoptRunningProxy: () => adoptRunningProxy(),
@@ -9587,7 +9612,7 @@ var CommandRelayService = class _CommandRelayService {
9587
9612
  // fresh + clear the "CLI update available" banner after a self-update
9588
9613
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
9589
9614
  // pair/reconnect). Older backends ignore the extra field.
9590
- ..."2.62.0" ? { ideVersion: "2.62.0" } : {}
9615
+ ..."2.62.1" ? { ideVersion: "2.62.1" } : {}
9591
9616
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
9592
9617
  }
9593
9618
  /**
@@ -13757,7 +13782,7 @@ function subscribeToPairCompletion(pluginId, onPaired, onTimeout, pollSecret) {
13757
13782
  onPaired(info);
13758
13783
  };
13759
13784
  dispatchers.add(dispatch);
13760
- const connect = () => {
13785
+ const connect2 = () => {
13761
13786
  if (stopped) return;
13762
13787
  const url2 = new URL(`${API_BASE5}/api/commands/pending/stream`);
13763
13788
  url2.searchParams.set("pluginId", pluginId);
@@ -13783,7 +13808,7 @@ function subscribeToPairCompletion(pluginId, onPaired, onTimeout, pollSecret) {
13783
13808
  `sse status=${res.statusCode}; will reconnect in 1s`
13784
13809
  );
13785
13810
  res.resume();
13786
- setTimeout(connect, 1e3);
13811
+ setTimeout(connect2, 1e3);
13787
13812
  return;
13788
13813
  }
13789
13814
  let buf = "";
@@ -13798,23 +13823,23 @@ function subscribeToPairCompletion(pluginId, onPaired, onTimeout, pollSecret) {
13798
13823
  }
13799
13824
  });
13800
13825
  res.on("end", () => {
13801
- if (!stopped) setTimeout(connect, 250);
13826
+ if (!stopped) setTimeout(connect2, 250);
13802
13827
  });
13803
13828
  res.on("error", () => {
13804
- if (!stopped) setTimeout(connect, 1e3);
13829
+ if (!stopped) setTimeout(connect2, 1e3);
13805
13830
  });
13806
13831
  }
13807
13832
  );
13808
13833
  req.on("error", () => {
13809
- if (!stopped) setTimeout(connect, 1e3);
13834
+ if (!stopped) setTimeout(connect2, 1e3);
13810
13835
  });
13811
13836
  req.on("timeout", () => {
13812
13837
  req?.destroy();
13813
- if (!stopped) setTimeout(connect, 250);
13838
+ if (!stopped) setTimeout(connect2, 250);
13814
13839
  });
13815
13840
  req.end();
13816
13841
  };
13817
- connect();
13842
+ connect2();
13818
13843
  timeoutTimer = setTimeout(() => {
13819
13844
  stop();
13820
13845
  onTimeout();
@@ -20790,7 +20815,7 @@ async function autoUpgradeBeforeCriticalCommand() {
20790
20815
  if (process.env.NODE_ENV === "test") return;
20791
20816
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20792
20817
  if (process.env.CI) return;
20793
- const current2 = true ? "2.62.0" : null;
20818
+ const current2 = true ? "2.62.1" : null;
20794
20819
  if (!current2) return;
20795
20820
  const cache = readCache();
20796
20821
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -20807,7 +20832,7 @@ function checkForUpdates() {
20807
20832
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20808
20833
  if (process.env.CI) return;
20809
20834
  if (!process.stdout.isTTY) return;
20810
- const current2 = true ? "2.62.0" : null;
20835
+ const current2 = true ? "2.62.1" : null;
20811
20836
  if (!current2) return;
20812
20837
  const cache = readCache();
20813
20838
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -20827,7 +20852,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
20827
20852
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
20828
20853
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
20829
20854
  function currentCliVersion() {
20830
- return true ? "2.62.0" : null;
20855
+ return true ? "2.62.1" : null;
20831
20856
  }
20832
20857
  function runCmd(cmd, args2, timeoutMs) {
20833
20858
  return new Promise((resolve9) => {
@@ -23169,10 +23194,10 @@ function parseExpoUrl(stdout) {
23169
23194
  }
23170
23195
 
23171
23196
  // src/services/preview/port-ready.ts
23172
- var net = __toESM(require("net"));
23197
+ var net2 = __toESM(require("net"));
23173
23198
  function isPortListening(port, host2 = "127.0.0.1") {
23174
23199
  return new Promise((resolve9) => {
23175
- const socket = new net.Socket();
23200
+ const socket = new net2.Socket();
23176
23201
  const done = (result) => {
23177
23202
  socket.removeAllListeners();
23178
23203
  socket.destroy();
@@ -42808,7 +42833,7 @@ function checkChokidar() {
42808
42833
  }
42809
42834
  async function doctor(args2 = []) {
42810
42835
  const json = args2.includes("--json");
42811
- const cliVersion = true ? "2.62.0" : "0.0.0-dev";
42836
+ const cliVersion = true ? "2.62.1" : "0.0.0-dev";
42812
42837
  const apiBase2 = resolveApiBaseUrl();
42813
42838
  const diagnosticId = (0, import_node_crypto13.randomUUID)();
42814
42839
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -43199,7 +43224,7 @@ async function mcpRun(args2) {
43199
43224
  // src/commands/version.ts
43200
43225
  var import_picocolors15 = __toESM(require("picocolors"));
43201
43226
  function version2() {
43202
- const v = true ? "2.62.0" : "unknown";
43227
+ const v = true ? "2.62.1" : "unknown";
43203
43228
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
43204
43229
  }
43205
43230
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.62.0",
3
+ "version": "2.62.1",
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",