codeam-cli 2.39.56 → 2.39.58

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.39.57] — 2026-06-20
8
+
9
+ ### Added
10
+
11
+ - **host-agent:** Event-driven session lifecycle (off the heartbeat)
12
+
13
+ ## [2.39.56] — 2026-06-20
14
+
15
+ ### Added
16
+
17
+ - **cli:** Report supervised sessions in self-hosted heartbeat
18
+
7
19
  ## [2.39.55] — 2026-06-20
8
20
 
9
21
  ### Added
package/dist/index.js CHANGED
@@ -5388,7 +5388,7 @@ function readAnonId() {
5388
5388
  }
5389
5389
  function superProperties() {
5390
5390
  return {
5391
- cliVersion: true ? "2.39.56" : "0.0.0-dev",
5391
+ cliVersion: true ? "2.39.58" : "0.0.0-dev",
5392
5392
  nodeVersion: process.version,
5393
5393
  platform: process.platform,
5394
5394
  arch: process.arch,
@@ -5547,7 +5547,7 @@ var os4 = __toESM(require("os"));
5547
5547
  // package.json
5548
5548
  var package_default = {
5549
5549
  name: "codeam-cli",
5550
- version: "2.39.56",
5550
+ version: "2.39.58",
5551
5551
  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.",
5552
5552
  type: "commonjs",
5553
5553
  main: "dist/index.js",
@@ -16919,17 +16919,23 @@ async function redeemEnrollToken(token, label) {
16919
16919
  controlPluginId: data.controlPluginId
16920
16920
  };
16921
16921
  }
16922
- async function sendHostHeartbeat(identity, metrics, sessions3) {
16922
+ async function sendHostHeartbeat(identity, metrics) {
16923
16923
  const start2 = process.hrtime.bigint();
16924
16924
  await postJson("/api/self-hosted/heartbeat", {
16925
16925
  hostId: identity.hostId,
16926
16926
  hostToken: identity.hostToken,
16927
- ...metrics ? { metrics } : {},
16928
- ...sessions3 ? { sessions: sessions3 } : {}
16927
+ ...metrics ? { metrics } : {}
16929
16928
  });
16930
16929
  const elapsedNs = process.hrtime.bigint() - start2;
16931
16930
  return Math.round(Number(elapsedNs) / 1e6);
16932
16931
  }
16932
+ async function reportSessionEvent(identity, body) {
16933
+ await postJson("/api/self-hosted/session-event", {
16934
+ hostId: identity.hostId,
16935
+ hostToken: identity.hostToken,
16936
+ ...body
16937
+ });
16938
+ }
16933
16939
  function isSealedEnvelope(v) {
16934
16940
  if (typeof v !== "object" || v === null) return false;
16935
16941
  const o = v;
@@ -17361,7 +17367,7 @@ function checkForUpdates() {
17361
17367
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17362
17368
  if (process.env.CI) return;
17363
17369
  if (!process.stdout.isTTY) return;
17364
- const current = true ? "2.39.56" : null;
17370
+ const current = true ? "2.39.58" : null;
17365
17371
  if (!current) return;
17366
17372
  const cache = readCache();
17367
17373
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17631,6 +17637,20 @@ function readHeadroomChildEnv() {
17631
17637
  return {};
17632
17638
  }
17633
17639
  }
17640
+ function bundledClaudeBinDir() {
17641
+ const require_2 = require;
17642
+ try {
17643
+ const sdkManifest = require_2.resolve("@anthropic-ai/claude-agent-sdk/package.json");
17644
+ const atAnthropic = path45.dirname(path45.dirname(sdkManifest));
17645
+ for (const entry of fs39.readdirSync(atAnthropic)) {
17646
+ if (!entry.startsWith("claude-agent-sdk-")) continue;
17647
+ const bin = path45.join(atAnthropic, entry, "claude");
17648
+ if (fs39.existsSync(bin)) return path45.dirname(bin);
17649
+ }
17650
+ } catch {
17651
+ }
17652
+ return null;
17653
+ }
17634
17654
  async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner) {
17635
17655
  const PIP_PACKAGES = [
17636
17656
  "headroom-ai",
@@ -17687,8 +17707,18 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
17687
17707
  return false;
17688
17708
  }
17689
17709
  const initKind = agentIdToHeadroomKind(agent);
17710
+ const initEnv = { ...process.env };
17711
+ if (initKind === "claude") {
17712
+ const claudeDir = bundledClaudeBinDir();
17713
+ if (claudeDir) {
17714
+ initEnv.PATH = `${claudeDir}${path45.delimiter}${process.env["PATH"] ?? ""}`;
17715
+ log.info("host-agent", `headroom init: bundled claude on PATH (${claudeDir})`);
17716
+ } else {
17717
+ log.warn("host-agent", "headroom init: bundled claude binary not found \u2014 init may fail");
17718
+ }
17719
+ }
17690
17720
  const initOk = await new Promise((resolve7) => {
17691
- (0, import_node_child_process13.execFile)("headroom", ["init", "--global", initKind], (initErr, stdout, stderr) => {
17721
+ (0, import_node_child_process13.execFile)("headroom", ["init", "--global", initKind], { env: initEnv }, (initErr, stdout, stderr) => {
17692
17722
  if (initErr) {
17693
17723
  const detail = (stderr || initErr.message).replace(/\n+$/g, "");
17694
17724
  log.warn("host-agent", `headroom init failed (best-effort): ${detail}`);
@@ -17721,7 +17751,7 @@ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process13.s
17721
17751
  detached: false
17722
17752
  });
17723
17753
  function currentCliVersion() {
17724
- return true ? "2.39.56" : null;
17754
+ return true ? "2.39.58" : null;
17725
17755
  }
17726
17756
  function runCmd(cmd, args2, timeoutMs) {
17727
17757
  return new Promise((resolve7) => {
@@ -17862,6 +17892,10 @@ var HostAgentSupervisor = class {
17862
17892
  void this.beat();
17863
17893
  this.heartbeatTimer = setInterval(() => void this.beat(), HEARTBEAT_INTERVAL_MS);
17864
17894
  this.heartbeatTimer.unref?.();
17895
+ void reportSessionEvent(
17896
+ { hostId: this.identity.hostId, hostToken: this.identity.hostToken },
17897
+ { event: "reconcile", activeDeployIds: this.activeSessions().map((s) => s.id) }
17898
+ ).catch((err) => log.trace("host-agent", "boot reconcile failed (best-effort)", err));
17865
17899
  const updateMs = this.selfUpdateIntervalMs();
17866
17900
  if (updateMs > 0) {
17867
17901
  this.selfUpdateTimer = setInterval(() => void this.selfUpdateTick(), updateMs);
@@ -17898,8 +17932,7 @@ var HostAgentSupervisor = class {
17898
17932
  } catch (err) {
17899
17933
  log.trace("host-agent", "metrics collection failed", err);
17900
17934
  }
17901
- const sessions3 = this.activeSessions();
17902
- const latencyMs = await sendHostHeartbeat(this.identity, metrics, sessions3);
17935
+ const latencyMs = await sendHostHeartbeat(this.identity, metrics);
17903
17936
  this.metrics.recordLatency(latencyMs);
17904
17937
  if (!this.reportedConnected) {
17905
17938
  this.reportedConnected = true;
@@ -18131,6 +18164,12 @@ var HostAgentSupervisor = class {
18131
18164
  if (tracked) {
18132
18165
  this.children.delete(payload.deployId);
18133
18166
  }
18167
+ if (tracked) {
18168
+ void reportSessionEvent(
18169
+ { hostId: this.identity.hostId, hostToken: this.identity.hostToken },
18170
+ { event: "ended", deployId: payload.deployId }
18171
+ ).catch((err) => log.trace("host-agent", "session ended report failed (best-effort)", err));
18172
+ }
18134
18173
  if (tracked && typeof code === "number" && code !== 0) {
18135
18174
  const detail = tail.trim().slice(-500);
18136
18175
  report("failed", detail ? `agent exited (${code}): ${detail}` : `agent exited (${code})`);
@@ -28264,7 +28303,7 @@ function checkChokidar() {
28264
28303
  }
28265
28304
  async function doctor(args2 = []) {
28266
28305
  const json = args2.includes("--json");
28267
- const cliVersion = true ? "2.39.56" : "0.0.0-dev";
28306
+ const cliVersion = true ? "2.39.58" : "0.0.0-dev";
28268
28307
  const apiBase2 = resolveApiBaseUrl();
28269
28308
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
28270
28309
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -28463,7 +28502,7 @@ async function completion(args2) {
28463
28502
  // src/commands/version.ts
28464
28503
  var import_picocolors14 = __toESM(require("picocolors"));
28465
28504
  function version2() {
28466
- const v = true ? "2.39.56" : "unknown";
28505
+ const v = true ? "2.39.58" : "unknown";
28467
28506
  console.log(`${import_picocolors14.default.bold("codeam-cli")} ${import_picocolors14.default.cyan(v)}`);
28468
28507
  }
28469
28508
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.39.56",
3
+ "version": "2.39.58",
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",