codeam-cli 2.39.75 → 2.39.77

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,22 @@ 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.76] — 2026-06-21
8
+
9
+ ### Added
10
+
11
+ - **cli:** Report compression-$ savings (eliminated tokens × model input price)
12
+
13
+ ### Fixed
14
+
15
+ - **cli:** Smoke probe /health not /api/health
16
+
17
+ ## [2.39.75] — 2026-06-21
18
+
19
+ ### Fixed
20
+
21
+ - **cli:** Render pairing code + QR on stderr, not stdout (fixes #356)
22
+
7
23
  ## [2.39.74] — 2026-06-21
8
24
 
9
25
  ### Fixed
package/dist/index.js CHANGED
@@ -5390,7 +5390,7 @@ function readAnonId() {
5390
5390
  }
5391
5391
  function superProperties() {
5392
5392
  return {
5393
- cliVersion: true ? "2.39.75" : "0.0.0-dev",
5393
+ cliVersion: true ? "2.39.77" : "0.0.0-dev",
5394
5394
  nodeVersion: process.version,
5395
5395
  platform: process.platform,
5396
5396
  arch: process.arch,
@@ -5549,7 +5549,7 @@ var os4 = __toESM(require("os"));
5549
5549
  // package.json
5550
5550
  var package_default = {
5551
5551
  name: "codeam-cli",
5552
- version: "2.39.75",
5552
+ version: "2.39.77",
5553
5553
  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.",
5554
5554
  type: "commonjs",
5555
5555
  main: "dist/index.js",
@@ -17216,30 +17216,34 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os30.homedir(
17216
17216
  }
17217
17217
 
17218
17218
  // src/services/headroom/stats-reporter.ts
17219
+ var DEFAULT_INPUT_PRICE_PER_MILLION = 3;
17219
17220
  var ZERO = {
17220
17221
  rawTokensEst: 0,
17221
17222
  sentTokensEst: 0,
17222
17223
  cachedTokens: 0,
17223
17224
  retrieveHops: 0,
17224
17225
  cacheReadTokens: 0,
17225
- cacheSavingsUsd: 0
17226
+ cacheSavingsUsd: 0,
17227
+ compressionSavingsUsd: 0
17226
17228
  };
17227
- function read(stats) {
17229
+ function read(stats, inputPricePerMillion) {
17228
17230
  const totals = stats.agent_usage?.totals;
17229
17231
  const compression = stats.summary?.compression;
17230
17232
  const rawTokensEst = totals?.before_tokens ?? compression?.total_tokens_before_with_cli_filtering ?? 0;
17231
17233
  const sentTokensEst = totals?.after_tokens ?? rawTokensEst - (compression?.total_tokens_removed ?? 0);
17234
+ const compressionSavingsUsd = Math.max(0, rawTokensEst - sentTokensEst) / 1e6 * inputPricePerMillion;
17232
17235
  return {
17233
17236
  rawTokensEst,
17234
17237
  sentTokensEst,
17235
17238
  cachedTokens: 0,
17236
17239
  retrieveHops: stats.summary?.mcp?.retrievals ?? 0,
17237
17240
  cacheReadTokens: stats.prefix_cache?.totals?.cache_read_tokens ?? 0,
17238
- cacheSavingsUsd: stats.summary?.cost?.breakdown?.cache_savings_usd ?? 0
17241
+ cacheSavingsUsd: stats.summary?.cost?.breakdown?.cache_savings_usd ?? 0,
17242
+ compressionSavingsUsd
17239
17243
  };
17240
17244
  }
17241
- function mapStatsToSavings(stats, prev) {
17242
- const next = read(stats);
17245
+ function mapStatsToSavings(stats, prev, inputPricePerMillion = DEFAULT_INPUT_PRICE_PER_MILLION) {
17246
+ const next = read(stats, inputPricePerMillion);
17243
17247
  const d3 = (a, b) => Math.max(0, a - b);
17244
17248
  const delta = next.rawTokensEst < prev.rawTokensEst ? next : {
17245
17249
  rawTokensEst: d3(next.rawTokensEst, prev.rawTokensEst),
@@ -17247,7 +17251,8 @@ function mapStatsToSavings(stats, prev) {
17247
17251
  cachedTokens: d3(next.cachedTokens, prev.cachedTokens),
17248
17252
  retrieveHops: d3(next.retrieveHops, prev.retrieveHops),
17249
17253
  cacheReadTokens: d3(next.cacheReadTokens, prev.cacheReadTokens),
17250
- cacheSavingsUsd: d3(next.cacheSavingsUsd, prev.cacheSavingsUsd)
17254
+ cacheSavingsUsd: d3(next.cacheSavingsUsd, prev.cacheSavingsUsd),
17255
+ compressionSavingsUsd: d3(next.compressionSavingsUsd, prev.compressionSavingsUsd)
17251
17256
  };
17252
17257
  return { next, delta };
17253
17258
  }
@@ -17264,9 +17269,13 @@ var HeadroomStatsReporter = class {
17264
17269
  }
17265
17270
  async tick() {
17266
17271
  try {
17267
- const { next, delta } = mapStatsToSavings(await this.deps.fetchStats(), this.prev);
17272
+ const { next, delta } = mapStatsToSavings(
17273
+ await this.deps.fetchStats(),
17274
+ this.prev,
17275
+ this.deps.inputPricePerMillionUsd ?? DEFAULT_INPUT_PRICE_PER_MILLION
17276
+ );
17268
17277
  this.prev = next;
17269
- if (delta.rawTokensEst > 0 || delta.cacheReadTokens > 0 || delta.cacheSavingsUsd > 0) {
17278
+ if (delta.rawTokensEst > 0 || delta.cacheReadTokens > 0 || delta.cacheSavingsUsd > 0 || delta.compressionSavingsUsd > 0) {
17270
17279
  await this.deps.postSavings(delta);
17271
17280
  }
17272
17281
  } catch {
@@ -17439,7 +17448,7 @@ function checkForUpdates() {
17439
17448
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
17440
17449
  if (process.env.CI) return;
17441
17450
  if (!process.stdout.isTTY) return;
17442
- const current = true ? "2.39.75" : null;
17451
+ const current = true ? "2.39.77" : null;
17443
17452
  if (!current) return;
17444
17453
  const cache = readCache();
17445
17454
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -17454,6 +17463,11 @@ function checkForUpdates() {
17454
17463
  }
17455
17464
 
17456
17465
  // src/commands/host-agent.ts
17466
+ function resolveInputPricePerMillion(agentId) {
17467
+ const a = agentId.toLowerCase();
17468
+ const model = a.includes("codex") || a.includes("gpt") ? "gpt-5.5" : "claude-sonnet-4";
17469
+ return getPricing(model).input;
17470
+ }
17457
17471
  var HEARTBEAT_INTERVAL_MS = 2e4;
17458
17472
  var SELF_UPDATE_PKG = "codeam-cli";
17459
17473
  var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
@@ -17464,6 +17478,9 @@ function maybeStartHeadroomReporter(ctx) {
17464
17478
  try {
17465
17479
  const ingestUrl = process.env["HEADROOM_SAVINGS_INGEST_URL"] ?? `${resolveApiBaseUrl()}/api/codespaces/${ctx.codespaceId}/headroom-savings`;
17466
17480
  const reporter = new HeadroomStatsReporter({
17481
+ inputPricePerMillionUsd: resolveInputPricePerMillion(
17482
+ process.env["HEADROOM_AGENT"] ?? "claude"
17483
+ ),
17467
17484
  fetchStats: async () => {
17468
17485
  const res = await fetch("http://localhost:8787/stats");
17469
17486
  return res.json();
@@ -17838,7 +17855,7 @@ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process13.s
17838
17855
  detached: false
17839
17856
  });
17840
17857
  function currentCliVersion() {
17841
- return true ? "2.39.75" : null;
17858
+ return true ? "2.39.77" : null;
17842
17859
  }
17843
17860
  function runCmd(cmd, args2, timeoutMs) {
17844
17861
  return new Promise((resolve7) => {
@@ -23675,6 +23692,19 @@ async function runAcpSession(opts) {
23675
23692
  onUnexpectedExit: (code, signal) => {
23676
23693
  log.warn("acpRunner", `adapter died code=${code} signal=${signal}; shutting down session`);
23677
23694
  const authFail = looksLikeAuthFailure(recentStderr.join("\n"));
23695
+ if (authFail) {
23696
+ void fetch(
23697
+ `${resolveApiBaseUrl()}/api/plugin/agents/${encodeURIComponent(opts.agent)}/credential-invalid`,
23698
+ {
23699
+ method: "POST",
23700
+ headers: {
23701
+ "Content-Type": "application/json",
23702
+ "X-Plugin-Auth-Token": opts.pluginAuthToken
23703
+ },
23704
+ body: JSON.stringify({ sessionId: opts.sessionId, pluginId: opts.pluginId })
23705
+ }
23706
+ ).catch(() => void 0);
23707
+ }
23678
23708
  void streaming.closeAll().then(
23679
23709
  () => publisher.publishOutput({
23680
23710
  type: "text",
@@ -28495,7 +28525,7 @@ function checkChokidar() {
28495
28525
  }
28496
28526
  async function doctor(args2 = []) {
28497
28527
  const json = args2.includes("--json");
28498
- const cliVersion = true ? "2.39.75" : "0.0.0-dev";
28528
+ const cliVersion = true ? "2.39.77" : "0.0.0-dev";
28499
28529
  const apiBase2 = resolveApiBaseUrl();
28500
28530
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
28501
28531
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -28694,7 +28724,7 @@ async function completion(args2) {
28694
28724
  // src/commands/version.ts
28695
28725
  var import_picocolors14 = __toESM(require("picocolors"));
28696
28726
  function version2() {
28697
- const v = true ? "2.39.75" : "unknown";
28727
+ const v = true ? "2.39.77" : "unknown";
28698
28728
  console.log(`${import_picocolors14.default.bold("codeam-cli")} ${import_picocolors14.default.cyan(v)}`);
28699
28729
  }
28700
28730
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.39.75",
3
+ "version": "2.39.77",
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",