codeam-cli 2.49.4 → 2.49.5

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.49.4] — 2026-06-27
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Serialize Headroom SSE event POSTs to preserve emit order
12
+
7
13
  ## [2.49.3] — 2026-06-27
8
14
 
9
15
  ### Fixed
package/dist/index.js CHANGED
@@ -5397,7 +5397,7 @@ function readAnonId() {
5397
5397
  }
5398
5398
  function superProperties() {
5399
5399
  return {
5400
- cliVersion: true ? "2.49.4" : "0.0.0-dev",
5400
+ cliVersion: true ? "2.49.5" : "0.0.0-dev",
5401
5401
  nodeVersion: process.version,
5402
5402
  platform: process.platform,
5403
5403
  arch: process.arch,
@@ -5578,7 +5578,7 @@ var os4 = __toESM(require("os"));
5578
5578
  // package.json
5579
5579
  var package_default = {
5580
5580
  name: "codeam-cli",
5581
- version: "2.49.4",
5581
+ version: "2.49.5",
5582
5582
  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.",
5583
5583
  type: "commonjs",
5584
5584
  main: "dist/index.js",
@@ -14747,7 +14747,7 @@ async function autoUpgradeBeforeCriticalCommand() {
14747
14747
  if (process.env.NODE_ENV === "test") return;
14748
14748
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
14749
14749
  if (process.env.CI) return;
14750
- const current = true ? "2.49.4" : null;
14750
+ const current = true ? "2.49.5" : null;
14751
14751
  if (!current) return;
14752
14752
  const cache = readCache();
14753
14753
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -14764,7 +14764,7 @@ function checkForUpdates() {
14764
14764
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
14765
14765
  if (process.env.CI) return;
14766
14766
  if (!process.stdout.isTTY) return;
14767
- const current = true ? "2.49.4" : null;
14767
+ const current = true ? "2.49.5" : null;
14768
14768
  if (!current) return;
14769
14769
  const cache = readCache();
14770
14770
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -14827,6 +14827,51 @@ function maybeStartHeadroomReporter(ctx) {
14827
14827
  return null;
14828
14828
  }
14829
14829
  }
14830
+ function maybeResumeLocalHeadroomReporter(ctx) {
14831
+ if (process.env["HEADROOM_ENABLED"] === "1") return null;
14832
+ try {
14833
+ const file = headroomConfigPath();
14834
+ if (!fs31.existsSync(file)) return null;
14835
+ const cfg = JSON.parse(fs31.readFileSync(file, "utf8"));
14836
+ if (!cfg?.enabled) return null;
14837
+ const agent = cfg.agent ?? "claude";
14838
+ const ingestUrl = `${resolveApiBaseUrl()}/api/sessions/${ctx.sessionId}/headroom-savings`;
14839
+ const reporter = new HeadroomStatsReporter({
14840
+ inputPricePerMillionUsd: resolveInputPricePerMillion(agent),
14841
+ fetchStats: async () => {
14842
+ const res = await fetch("http://localhost:8787/stats");
14843
+ return res.json();
14844
+ },
14845
+ // Body MUST match HeadroomSavingsDto + PluginAuthGuard (sessionId +
14846
+ // pluginId in the body) — same shape as the codespace reporter above and
14847
+ // the on-demand `startReporter` in handlers.ts.
14848
+ postSavings: async (delta) => {
14849
+ await fetch(ingestUrl, {
14850
+ method: "POST",
14851
+ headers: {
14852
+ "Content-Type": "application/json",
14853
+ "X-Plugin-Auth-Token": ctx.pluginAuthToken
14854
+ },
14855
+ body: JSON.stringify({
14856
+ sessionId: ctx.sessionId,
14857
+ pluginId: ctx.pluginId,
14858
+ agentId: agent,
14859
+ savings: delta
14860
+ })
14861
+ });
14862
+ }
14863
+ });
14864
+ reporter.start();
14865
+ log.info("headroom", "resumed on-demand local savings reporter from config");
14866
+ return reporter;
14867
+ } catch (err) {
14868
+ log.warn(
14869
+ "headroom",
14870
+ `failed to resume local Headroom reporter (best-effort): ${err instanceof Error ? err.message : String(err)}`
14871
+ );
14872
+ return null;
14873
+ }
14874
+ }
14830
14875
  function isRefreshCredentialsPayload(p2) {
14831
14876
  return typeof p2.agentId === "string" && typeof p2.sealedAgentAuth === "string";
14832
14877
  }
@@ -15400,7 +15445,7 @@ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process14.s
15400
15445
  detached: false
15401
15446
  });
15402
15447
  function currentCliVersion() {
15403
- return true ? "2.49.4" : null;
15448
+ return true ? "2.49.5" : null;
15404
15449
  }
15405
15450
  function runCmd(cmd, args2, timeoutMs) {
15406
15451
  return new Promise((resolve7) => {
@@ -18383,7 +18428,19 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
18383
18428
  "Content-Type": "application/json",
18384
18429
  ...opts.pluginAuthToken ? { "X-Plugin-Auth-Token": opts.pluginAuthToken } : {}
18385
18430
  },
18386
- body: JSON.stringify({ agentId: opts.agent, ...delta })
18431
+ // Body MUST match HeadroomSavingsDto + PluginAuthGuard, which read
18432
+ // `sessionId` + `pluginId` from the body and 401 if either is
18433
+ // missing. Mirror the self-hosted reporter in host-agent.ts exactly.
18434
+ // Previously this sent `{ agentId, ...delta }` (no sessionId/pluginId,
18435
+ // delta spread flat instead of nested under `savings`) → every POST
18436
+ // was rejected 401 at the guard and silently swallowed (fetch status
18437
+ // unchecked), so local on-demand savings never reached the backend.
18438
+ body: JSON.stringify({
18439
+ sessionId: ctx.sessionId,
18440
+ pluginId: ctx.pluginId,
18441
+ agentId: opts.agent,
18442
+ savings: delta
18443
+ })
18387
18444
  });
18388
18445
  }
18389
18446
  });
@@ -27568,6 +27625,14 @@ async function start(requestedAgent) {
27568
27625
  process.once("exit", () => {
27569
27626
  headroomReporter?.stop();
27570
27627
  });
27628
+ const localHeadroomReporter = session.pluginAuthToken ? maybeResumeLocalHeadroomReporter({
27629
+ sessionId: session.id,
27630
+ pluginId,
27631
+ pluginAuthToken: session.pluginAuthToken
27632
+ }) : null;
27633
+ process.once("exit", () => {
27634
+ localHeadroomReporter?.stop();
27635
+ });
27571
27636
  if (process.env.CODESPACES === "true") ensureClaudeOnboarded();
27572
27637
  let beads = null;
27573
27638
  const getBeads = () => beads;
@@ -30346,7 +30411,7 @@ function checkChokidar() {
30346
30411
  }
30347
30412
  async function doctor(args2 = []) {
30348
30413
  const json = args2.includes("--json");
30349
- const cliVersion = true ? "2.49.4" : "0.0.0-dev";
30414
+ const cliVersion = true ? "2.49.5" : "0.0.0-dev";
30350
30415
  const apiBase2 = resolveApiBaseUrl();
30351
30416
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
30352
30417
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -30545,7 +30610,7 @@ async function completion(args2) {
30545
30610
  // src/commands/version.ts
30546
30611
  var import_picocolors15 = __toESM(require("picocolors"));
30547
30612
  function version2() {
30548
- const v = true ? "2.49.4" : "unknown";
30613
+ const v = true ? "2.49.5" : "unknown";
30549
30614
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
30550
30615
  }
30551
30616
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.49.4",
3
+ "version": "2.49.5",
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",