codeam-cli 2.39.77 → 2.39.79
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 +6 -0
- package/dist/index.js +109 -35
- package/package.json +1 -1
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.39.77] — 2026-06-21
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **cli:** Report runtime 401 to mark the credential invalid
|
|
12
|
+
|
|
7
13
|
## [2.39.76] — 2026-06-21
|
|
8
14
|
|
|
9
15
|
### Added
|
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.
|
|
5393
|
+
cliVersion: true ? "2.39.79" : "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.
|
|
5552
|
+
version: "2.39.79",
|
|
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",
|
|
@@ -17224,14 +17224,17 @@ var ZERO = {
|
|
|
17224
17224
|
retrieveHops: 0,
|
|
17225
17225
|
cacheReadTokens: 0,
|
|
17226
17226
|
cacheSavingsUsd: 0,
|
|
17227
|
-
|
|
17227
|
+
compressionTokens: 0,
|
|
17228
|
+
compressionSavingsUsd: 0,
|
|
17229
|
+
compressionPct: 0
|
|
17228
17230
|
};
|
|
17229
17231
|
function read(stats, inputPricePerMillion) {
|
|
17230
17232
|
const totals = stats.agent_usage?.totals;
|
|
17231
17233
|
const compression = stats.summary?.compression;
|
|
17232
17234
|
const rawTokensEst = totals?.before_tokens ?? compression?.total_tokens_before_with_cli_filtering ?? 0;
|
|
17233
17235
|
const sentTokensEst = totals?.after_tokens ?? rawTokensEst - (compression?.total_tokens_removed ?? 0);
|
|
17234
|
-
const
|
|
17236
|
+
const compressionTokens = compression?.total_tokens_saved_with_cli_filtering ?? compression?.total_tokens_removed ?? Math.max(0, rawTokensEst - sentTokensEst);
|
|
17237
|
+
const compressionSavingsUsd = stats.summary?.cost?.breakdown?.compression_savings_usd ?? Math.max(0, compressionTokens) / 1e6 * inputPricePerMillion;
|
|
17235
17238
|
return {
|
|
17236
17239
|
rawTokensEst,
|
|
17237
17240
|
sentTokensEst,
|
|
@@ -17239,7 +17242,9 @@ function read(stats, inputPricePerMillion) {
|
|
|
17239
17242
|
retrieveHops: stats.summary?.mcp?.retrievals ?? 0,
|
|
17240
17243
|
cacheReadTokens: stats.prefix_cache?.totals?.cache_read_tokens ?? 0,
|
|
17241
17244
|
cacheSavingsUsd: stats.summary?.cost?.breakdown?.cache_savings_usd ?? 0,
|
|
17242
|
-
|
|
17245
|
+
compressionTokens,
|
|
17246
|
+
compressionSavingsUsd,
|
|
17247
|
+
compressionPct: compression?.avg_compression_pct ?? 0
|
|
17243
17248
|
};
|
|
17244
17249
|
}
|
|
17245
17250
|
function mapStatsToSavings(stats, prev, inputPricePerMillion = DEFAULT_INPUT_PRICE_PER_MILLION) {
|
|
@@ -17252,7 +17257,10 @@ function mapStatsToSavings(stats, prev, inputPricePerMillion = DEFAULT_INPUT_PRI
|
|
|
17252
17257
|
retrieveHops: d3(next.retrieveHops, prev.retrieveHops),
|
|
17253
17258
|
cacheReadTokens: d3(next.cacheReadTokens, prev.cacheReadTokens),
|
|
17254
17259
|
cacheSavingsUsd: d3(next.cacheSavingsUsd, prev.cacheSavingsUsd),
|
|
17255
|
-
|
|
17260
|
+
compressionTokens: d3(next.compressionTokens, prev.compressionTokens),
|
|
17261
|
+
compressionSavingsUsd: d3(next.compressionSavingsUsd, prev.compressionSavingsUsd),
|
|
17262
|
+
// RATE — carry the latest absolute value through, never diff it.
|
|
17263
|
+
compressionPct: next.compressionPct
|
|
17256
17264
|
};
|
|
17257
17265
|
return { next, delta };
|
|
17258
17266
|
}
|
|
@@ -17275,7 +17283,7 @@ var HeadroomStatsReporter = class {
|
|
|
17275
17283
|
this.deps.inputPricePerMillionUsd ?? DEFAULT_INPUT_PRICE_PER_MILLION
|
|
17276
17284
|
);
|
|
17277
17285
|
this.prev = next;
|
|
17278
|
-
if (delta.
|
|
17286
|
+
if (delta.compressionTokens > 0 || delta.compressionSavingsUsd > 0 || delta.rawTokensEst > 0 || delta.cacheReadTokens > 0 || delta.cacheSavingsUsd > 0) {
|
|
17279
17287
|
await this.deps.postSavings(delta);
|
|
17280
17288
|
}
|
|
17281
17289
|
} catch {
|
|
@@ -17448,7 +17456,7 @@ function checkForUpdates() {
|
|
|
17448
17456
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
17449
17457
|
if (process.env.CI) return;
|
|
17450
17458
|
if (!process.stdout.isTTY) return;
|
|
17451
|
-
const current = true ? "2.39.
|
|
17459
|
+
const current = true ? "2.39.79" : null;
|
|
17452
17460
|
if (!current) return;
|
|
17453
17461
|
const cache = readCache();
|
|
17454
17462
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -17504,7 +17512,10 @@ function maybeStartHeadroomReporter(ctx) {
|
|
|
17504
17512
|
reporter.start();
|
|
17505
17513
|
return reporter;
|
|
17506
17514
|
} catch (err) {
|
|
17507
|
-
log.warn(
|
|
17515
|
+
log.warn(
|
|
17516
|
+
"headroom",
|
|
17517
|
+
`failed to start Headroom reporter (best-effort): ${err instanceof Error ? err.message : String(err)}`
|
|
17518
|
+
);
|
|
17508
17519
|
return null;
|
|
17509
17520
|
}
|
|
17510
17521
|
}
|
|
@@ -17584,7 +17595,10 @@ var defaultHeadroomRunner = {
|
|
|
17584
17595
|
let timer;
|
|
17585
17596
|
if (timeoutMs !== void 0) {
|
|
17586
17597
|
timer = setTimeout(() => {
|
|
17587
|
-
log.warn(
|
|
17598
|
+
log.warn(
|
|
17599
|
+
"host-agent",
|
|
17600
|
+
`headroom[${cmd}] timed out after ${timeoutMs / 1e3}s \u2014 aborting`
|
|
17601
|
+
);
|
|
17588
17602
|
try {
|
|
17589
17603
|
child.kill("SIGTERM");
|
|
17590
17604
|
} catch {
|
|
@@ -17615,7 +17629,16 @@ var PACKAGE_MANAGERS = [
|
|
|
17615
17629
|
var PROVISION_RECIPES = {
|
|
17616
17630
|
"apt-get": {
|
|
17617
17631
|
update: ["apt-get", "update"],
|
|
17618
|
-
install: [
|
|
17632
|
+
install: [
|
|
17633
|
+
"apt-get",
|
|
17634
|
+
"install",
|
|
17635
|
+
"-y",
|
|
17636
|
+
"python3",
|
|
17637
|
+
"python3-pip",
|
|
17638
|
+
"python3-venv",
|
|
17639
|
+
"ca-certificates",
|
|
17640
|
+
"curl"
|
|
17641
|
+
]
|
|
17619
17642
|
},
|
|
17620
17643
|
apk: {
|
|
17621
17644
|
install: ["apk", "add", "--no-cache", "python3", "py3-pip", "ca-certificates", "curl"]
|
|
@@ -17630,7 +17653,15 @@ var PROVISION_RECIPES = {
|
|
|
17630
17653
|
install: ["pacman", "-Sy", "--noconfirm", "python", "python-pip", "ca-certificates", "curl"]
|
|
17631
17654
|
},
|
|
17632
17655
|
zypper: {
|
|
17633
|
-
install: [
|
|
17656
|
+
install: [
|
|
17657
|
+
"zypper",
|
|
17658
|
+
"--non-interactive",
|
|
17659
|
+
"install",
|
|
17660
|
+
"python3",
|
|
17661
|
+
"python3-pip",
|
|
17662
|
+
"ca-certificates",
|
|
17663
|
+
"curl"
|
|
17664
|
+
]
|
|
17634
17665
|
}
|
|
17635
17666
|
};
|
|
17636
17667
|
function detectPackageManager(runner) {
|
|
@@ -17821,17 +17852,22 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
|
|
|
17821
17852
|
}
|
|
17822
17853
|
}
|
|
17823
17854
|
const initOk = await new Promise((resolve7) => {
|
|
17824
|
-
(0, import_node_child_process13.execFile)(
|
|
17825
|
-
|
|
17826
|
-
|
|
17827
|
-
|
|
17828
|
-
|
|
17829
|
-
|
|
17830
|
-
|
|
17831
|
-
|
|
17832
|
-
|
|
17855
|
+
(0, import_node_child_process13.execFile)(
|
|
17856
|
+
"headroom",
|
|
17857
|
+
["init", "--global", initKind],
|
|
17858
|
+
{ env: initEnv },
|
|
17859
|
+
(initErr, stdout, stderr) => {
|
|
17860
|
+
if (initErr) {
|
|
17861
|
+
const detail = (stderr || initErr.message).replace(/\n+$/g, "");
|
|
17862
|
+
log.warn("host-agent", `headroom init failed (best-effort): ${detail}`);
|
|
17863
|
+
resolve7(false);
|
|
17864
|
+
} else {
|
|
17865
|
+
if (stdout.trim()) log.info("host-agent", `headroom init: ${stdout.trim()}`);
|
|
17866
|
+
log.info("host-agent", "headroom init --global succeeded");
|
|
17867
|
+
resolve7(true);
|
|
17868
|
+
}
|
|
17833
17869
|
}
|
|
17834
|
-
|
|
17870
|
+
);
|
|
17835
17871
|
});
|
|
17836
17872
|
if (!initOk) {
|
|
17837
17873
|
return false;
|
|
@@ -17844,7 +17880,10 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner)
|
|
|
17844
17880
|
});
|
|
17845
17881
|
proxy.unref();
|
|
17846
17882
|
} catch (e) {
|
|
17847
|
-
log.warn(
|
|
17883
|
+
log.warn(
|
|
17884
|
+
"host-agent",
|
|
17885
|
+
`headroom proxy warm-start failed (best-effort): ${e instanceof Error ? e.message : String(e)}`
|
|
17886
|
+
);
|
|
17848
17887
|
}
|
|
17849
17888
|
return true;
|
|
17850
17889
|
}
|
|
@@ -17855,7 +17894,7 @@ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process13.s
|
|
|
17855
17894
|
detached: false
|
|
17856
17895
|
});
|
|
17857
17896
|
function currentCliVersion() {
|
|
17858
|
-
return true ? "2.39.
|
|
17897
|
+
return true ? "2.39.79" : null;
|
|
17859
17898
|
}
|
|
17860
17899
|
function runCmd(cmd, args2, timeoutMs) {
|
|
17861
17900
|
return new Promise((resolve7) => {
|
|
@@ -17872,7 +17911,11 @@ async function runSelfUpdate() {
|
|
|
17872
17911
|
log.trace("host-agent", "self-update: no __CLI_VERSION__ \u2014 skipping");
|
|
17873
17912
|
return { status: "skipped" };
|
|
17874
17913
|
}
|
|
17875
|
-
const view = await runCmd(
|
|
17914
|
+
const view = await runCmd(
|
|
17915
|
+
"npm",
|
|
17916
|
+
["view", SELF_UPDATE_PKG, "version"],
|
|
17917
|
+
SELF_UPDATE_VIEW_TIMEOUT_MS
|
|
17918
|
+
);
|
|
17876
17919
|
if (view.code !== 0) {
|
|
17877
17920
|
log.trace("host-agent", `self-update: npm view exited ${String(view.code)} \u2014 skipping`);
|
|
17878
17921
|
return { status: "skipped" };
|
|
@@ -17900,7 +17943,11 @@ async function runSelfUpdate() {
|
|
|
17900
17943
|
);
|
|
17901
17944
|
return { status: "skipped" };
|
|
17902
17945
|
}
|
|
17903
|
-
const after = await runCmd(
|
|
17946
|
+
const after = await runCmd(
|
|
17947
|
+
"npm",
|
|
17948
|
+
["view", SELF_UPDATE_PKG, "version"],
|
|
17949
|
+
SELF_UPDATE_VIEW_TIMEOUT_MS
|
|
17950
|
+
);
|
|
17904
17951
|
const installed = after.code === 0 ? after.stdout.trim() || latest : latest;
|
|
17905
17952
|
return { status: "updated", version: installed };
|
|
17906
17953
|
} catch (err) {
|
|
@@ -17947,6 +17994,8 @@ var HostAgentSupervisor = class {
|
|
|
17947
17994
|
this.spawnChild = deps.spawnChild ?? defaultSpawner;
|
|
17948
17995
|
this.resolveAgentAuth = deps.resolveAgentAuth ?? unsealAgentAuth;
|
|
17949
17996
|
this.setupHeadroom = deps.setupHeadroom ?? setupHeadroomForSelfHosted;
|
|
17997
|
+
this.isHeadroomInstalled = deps.isHeadroomInstalled ?? (() => defaultHeadroomRunner.which("headroom"));
|
|
17998
|
+
this.getFreeDisk = deps.getFreeDisk ?? getFreeDiskBytes;
|
|
17950
17999
|
this.metrics = deps.metricsCollector ?? new MetricsCollector();
|
|
17951
18000
|
this.onIdentityRejected = deps.onIdentityRejected ?? defaultOnIdentityRejected;
|
|
17952
18001
|
this.disableService = deps.disableService ?? defaultDisableService;
|
|
@@ -17960,6 +18009,10 @@ var HostAgentSupervisor = class {
|
|
|
17960
18009
|
spawnChild;
|
|
17961
18010
|
resolveAgentAuth;
|
|
17962
18011
|
setupHeadroom;
|
|
18012
|
+
/** Probe whether Headroom is already installed (defaults to `which headroom`). */
|
|
18013
|
+
isHeadroomInstalled;
|
|
18014
|
+
/** Free-disk reader for the install preflight (defaults to getFreeDiskBytes). */
|
|
18015
|
+
getFreeDisk;
|
|
17963
18016
|
relay = null;
|
|
17964
18017
|
heartbeatTimer = null;
|
|
17965
18018
|
/** Periodic self-update timer (npm check + install + restart). */
|
|
@@ -18258,8 +18311,9 @@ var HostAgentSupervisor = class {
|
|
|
18258
18311
|
}
|
|
18259
18312
|
if (payload.headroomEnabled && payload.headroomAgent && payload.headroomSavingsIngestUrl) {
|
|
18260
18313
|
report("headroom", "setting up Headroom proxy");
|
|
18261
|
-
const freeBytes = await
|
|
18262
|
-
|
|
18314
|
+
const freeBytes = await this.getFreeDisk(os32.homedir());
|
|
18315
|
+
const alreadyInstalled = this.isHeadroomInstalled();
|
|
18316
|
+
if (!alreadyInstalled && freeBytes !== null && freeBytes < HEADROOM_MIN_FREE_DISK_BYTES) {
|
|
18263
18317
|
const freeGb = (freeBytes / 1e9).toFixed(1);
|
|
18264
18318
|
const needGb = Math.round(HEADROOM_MIN_FREE_DISK_BYTES / 1e9);
|
|
18265
18319
|
report(
|
|
@@ -18272,6 +18326,12 @@ var HostAgentSupervisor = class {
|
|
|
18272
18326
|
);
|
|
18273
18327
|
persistHeadroomConfig({ enabled: false });
|
|
18274
18328
|
} else {
|
|
18329
|
+
if (alreadyInstalled && freeBytes !== null && freeBytes < HEADROOM_MIN_FREE_DISK_BYTES) {
|
|
18330
|
+
log.info(
|
|
18331
|
+
"host-agent",
|
|
18332
|
+
`Headroom already installed \u2014 bypassing install disk gate (free=${(freeBytes / 1e9).toFixed(1)}GB); reporting stays enabled`
|
|
18333
|
+
);
|
|
18334
|
+
}
|
|
18275
18335
|
const headroomOk = await this.setupHeadroom(payload.headroomAgent);
|
|
18276
18336
|
if (headroomOk) {
|
|
18277
18337
|
persistHeadroomConfig({
|
|
@@ -18279,10 +18339,16 @@ var HostAgentSupervisor = class {
|
|
|
18279
18339
|
agent: agentIdToHeadroomKind(payload.headroomAgent),
|
|
18280
18340
|
ingestUrl: payload.headroomSavingsIngestUrl
|
|
18281
18341
|
});
|
|
18282
|
-
log.info(
|
|
18342
|
+
log.info(
|
|
18343
|
+
"host-agent",
|
|
18344
|
+
"Headroom proxy ready; persisted headroom config for child spawns"
|
|
18345
|
+
);
|
|
18283
18346
|
} else {
|
|
18284
18347
|
persistHeadroomConfig({ enabled: false });
|
|
18285
|
-
log.warn(
|
|
18348
|
+
log.warn(
|
|
18349
|
+
"host-agent",
|
|
18350
|
+
"Headroom setup failed (best-effort) \u2014 child will run without Headroom"
|
|
18351
|
+
);
|
|
18286
18352
|
}
|
|
18287
18353
|
}
|
|
18288
18354
|
} else if (payload.headroomEnabled === false) {
|
|
@@ -18313,7 +18379,9 @@ var HostAgentSupervisor = class {
|
|
|
18313
18379
|
void reportSessionEvent(
|
|
18314
18380
|
{ hostId: this.identity.hostId, hostToken: this.identity.hostToken },
|
|
18315
18381
|
{ event: "ended", deployId: payload.deployId }
|
|
18316
|
-
).catch(
|
|
18382
|
+
).catch(
|
|
18383
|
+
(err) => log.trace("host-agent", "session ended report failed (best-effort)", err)
|
|
18384
|
+
);
|
|
18317
18385
|
}
|
|
18318
18386
|
if (tracked && typeof code === "number" && code !== 0) {
|
|
18319
18387
|
const detail = tail.trim().slice(-500);
|
|
@@ -18377,7 +18445,10 @@ var HostAgentSupervisor = class {
|
|
|
18377
18445
|
resolve7();
|
|
18378
18446
|
};
|
|
18379
18447
|
const timer = setTimeout(() => {
|
|
18380
|
-
log.warn(
|
|
18448
|
+
log.warn(
|
|
18449
|
+
"host-agent",
|
|
18450
|
+
"agent install timed out (180s) \u2014 preview detection may be unavailable"
|
|
18451
|
+
);
|
|
18381
18452
|
try {
|
|
18382
18453
|
child.kill("SIGTERM");
|
|
18383
18454
|
} catch {
|
|
@@ -18387,7 +18458,10 @@ var HostAgentSupervisor = class {
|
|
|
18387
18458
|
child.once("exit", (code) => {
|
|
18388
18459
|
clearTimeout(timer);
|
|
18389
18460
|
if (code !== 0) {
|
|
18390
|
-
log.warn(
|
|
18461
|
+
log.warn(
|
|
18462
|
+
"host-agent",
|
|
18463
|
+
`agent install exited code=${code} \u2014 preview detection may be unavailable; agent still runs`
|
|
18464
|
+
);
|
|
18391
18465
|
} else {
|
|
18392
18466
|
log.info("host-agent", "agent CLI installed");
|
|
18393
18467
|
}
|
|
@@ -28525,7 +28599,7 @@ function checkChokidar() {
|
|
|
28525
28599
|
}
|
|
28526
28600
|
async function doctor(args2 = []) {
|
|
28527
28601
|
const json = args2.includes("--json");
|
|
28528
|
-
const cliVersion = true ? "2.39.
|
|
28602
|
+
const cliVersion = true ? "2.39.79" : "0.0.0-dev";
|
|
28529
28603
|
const apiBase2 = resolveApiBaseUrl();
|
|
28530
28604
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
28531
28605
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -28724,7 +28798,7 @@ async function completion(args2) {
|
|
|
28724
28798
|
// src/commands/version.ts
|
|
28725
28799
|
var import_picocolors14 = __toESM(require("picocolors"));
|
|
28726
28800
|
function version2() {
|
|
28727
|
-
const v = true ? "2.39.
|
|
28801
|
+
const v = true ? "2.39.79" : "unknown";
|
|
28728
28802
|
console.log(`${import_picocolors14.default.bold("codeam-cli")} ${import_picocolors14.default.cyan(v)}`);
|
|
28729
28803
|
}
|
|
28730
28804
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.39.
|
|
3
|
+
"version": "2.39.79",
|
|
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",
|