codeam-cli 2.52.12 → 2.53.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 +12 -0
- package/dist/index.js +114 -12
- package/package.json +1 -1
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.53.0] — 2026-07-06
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **cli:** Proactive credential validation on session start / wake
|
|
12
|
+
|
|
13
|
+
## [2.52.12] — 2026-07-05
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **cli:** Supervise the Headroom proxy + report version on heartbeat
|
|
18
|
+
|
|
7
19
|
## [2.52.11] — 2026-07-04
|
|
8
20
|
|
|
9
21
|
### 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.
|
|
5400
|
+
cliVersion: true ? "2.53.1" : "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.
|
|
5581
|
+
version: "2.53.1",
|
|
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",
|
|
@@ -6543,7 +6543,7 @@ var CommandRelayService = class {
|
|
|
6543
6543
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
6544
6544
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
6545
6545
|
// pair/reconnect). Older backends ignore the extra field.
|
|
6546
|
-
..."2.
|
|
6546
|
+
..."2.53.1" ? { ideVersion: "2.53.1" } : {}
|
|
6547
6547
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
6548
6548
|
}
|
|
6549
6549
|
/**
|
|
@@ -15023,7 +15023,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
15023
15023
|
if (process.env.NODE_ENV === "test") return;
|
|
15024
15024
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
15025
15025
|
if (process.env.CI) return;
|
|
15026
|
-
const current = true ? "2.
|
|
15026
|
+
const current = true ? "2.53.1" : null;
|
|
15027
15027
|
if (!current) return;
|
|
15028
15028
|
const cache = readCache();
|
|
15029
15029
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -15040,7 +15040,7 @@ function checkForUpdates() {
|
|
|
15040
15040
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
15041
15041
|
if (process.env.CI) return;
|
|
15042
15042
|
if (!process.stdout.isTTY) return;
|
|
15043
|
-
const current = true ? "2.
|
|
15043
|
+
const current = true ? "2.53.1" : null;
|
|
15044
15044
|
if (!current) return;
|
|
15045
15045
|
const cache = readCache();
|
|
15046
15046
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -15742,7 +15742,7 @@ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process15.s
|
|
|
15742
15742
|
detached: false
|
|
15743
15743
|
});
|
|
15744
15744
|
function currentCliVersion() {
|
|
15745
|
-
return true ? "2.
|
|
15745
|
+
return true ? "2.53.1" : null;
|
|
15746
15746
|
}
|
|
15747
15747
|
function runCmd(cmd, args2, timeoutMs) {
|
|
15748
15748
|
return new Promise((resolve7) => {
|
|
@@ -21198,6 +21198,60 @@ async function waitForCommandOnPath(cmd, opts = {}) {
|
|
|
21198
21198
|
}
|
|
21199
21199
|
return check();
|
|
21200
21200
|
}
|
|
21201
|
+
var ADAPTER_MODULE_LOAD_ERROR_RE = /ERR_MODULE_NOT_FOUND|Cannot find module|ERR_REQUIRE_ESM|ERR_UNKNOWN_BUILTIN_MODULE|SyntaxError|Unexpected (token|end|identifier)|missing \) after argument list/i;
|
|
21202
|
+
function probeAdapterModuleGraph(command2, args2, opts = {}) {
|
|
21203
|
+
const livenessMs = opts.livenessMs ?? 400;
|
|
21204
|
+
const spawnFn = opts.spawnFn ?? import_child_process24.spawn;
|
|
21205
|
+
return new Promise((resolve7) => {
|
|
21206
|
+
let settled = false;
|
|
21207
|
+
let stderr = "";
|
|
21208
|
+
let timer;
|
|
21209
|
+
let child;
|
|
21210
|
+
const finish = (r) => {
|
|
21211
|
+
if (settled) return;
|
|
21212
|
+
settled = true;
|
|
21213
|
+
if (timer) clearTimeout(timer);
|
|
21214
|
+
try {
|
|
21215
|
+
child?.kill("SIGKILL");
|
|
21216
|
+
} catch {
|
|
21217
|
+
}
|
|
21218
|
+
resolve7(r);
|
|
21219
|
+
};
|
|
21220
|
+
try {
|
|
21221
|
+
child = spawnFn(command2, [...args2], { stdio: ["pipe", "ignore", "pipe"] });
|
|
21222
|
+
} catch {
|
|
21223
|
+
resolve7("ok");
|
|
21224
|
+
return;
|
|
21225
|
+
}
|
|
21226
|
+
child.stderr?.on("data", (d3) => {
|
|
21227
|
+
stderr += d3.toString();
|
|
21228
|
+
if (stderr.length > 8192) stderr = stderr.slice(-8192);
|
|
21229
|
+
});
|
|
21230
|
+
child.on("error", () => finish("ok"));
|
|
21231
|
+
child.on("exit", (code) => {
|
|
21232
|
+
if (code !== 0 && code !== null && ADAPTER_MODULE_LOAD_ERROR_RE.test(stderr)) {
|
|
21233
|
+
finish("transient");
|
|
21234
|
+
} else {
|
|
21235
|
+
finish("ok");
|
|
21236
|
+
}
|
|
21237
|
+
});
|
|
21238
|
+
timer = setTimeout(() => finish("ok"), livenessMs);
|
|
21239
|
+
});
|
|
21240
|
+
}
|
|
21241
|
+
async function waitForAdapterModuleGraph(command2, args2, opts = {}) {
|
|
21242
|
+
const timeoutMs = opts.timeoutMs ?? 18e4;
|
|
21243
|
+
const pollMs = opts.pollMs ?? 500;
|
|
21244
|
+
const now = opts.now ?? Date.now;
|
|
21245
|
+
const sleep3 = opts.sleep ?? realSleep;
|
|
21246
|
+
const probeOpts = { livenessMs: opts.livenessMs, spawnFn: opts.spawnFn };
|
|
21247
|
+
const deadline = now() + timeoutMs;
|
|
21248
|
+
if (await probeAdapterModuleGraph(command2, args2, probeOpts) === "ok") return true;
|
|
21249
|
+
while (now() < deadline) {
|
|
21250
|
+
await sleep3(pollMs);
|
|
21251
|
+
if (await probeAdapterModuleGraph(command2, args2, probeOpts) === "ok") return true;
|
|
21252
|
+
}
|
|
21253
|
+
return false;
|
|
21254
|
+
}
|
|
21201
21255
|
|
|
21202
21256
|
// src/agents/acp/adapters.ts
|
|
21203
21257
|
var require_ = require;
|
|
@@ -25305,6 +25359,37 @@ You have two options:
|
|
|
25305
25359
|
};
|
|
25306
25360
|
}
|
|
25307
25361
|
|
|
25362
|
+
// src/agents/acp/wakeCredentialProbe.ts
|
|
25363
|
+
async function localCredentialExpiryStatus(agent) {
|
|
25364
|
+
if (!/claude/i.test(agent)) return "unknown";
|
|
25365
|
+
const token = await extractLocalClaudeToken();
|
|
25366
|
+
if (!token) return "unknown";
|
|
25367
|
+
return validateClaudeToken(token).status;
|
|
25368
|
+
}
|
|
25369
|
+
function createWakeCredentialProbe(deps) {
|
|
25370
|
+
return {
|
|
25371
|
+
run: async () => {
|
|
25372
|
+
let status2;
|
|
25373
|
+
try {
|
|
25374
|
+
status2 = await deps.getStatus();
|
|
25375
|
+
} catch {
|
|
25376
|
+
return false;
|
|
25377
|
+
}
|
|
25378
|
+
if (status2 !== "expired") return false;
|
|
25379
|
+
deps.log?.("wake credential probe \u2014 local token expired, surfacing re-auth");
|
|
25380
|
+
try {
|
|
25381
|
+
await deps.emitReauthBubble();
|
|
25382
|
+
} catch {
|
|
25383
|
+
}
|
|
25384
|
+
try {
|
|
25385
|
+
await deps.reportCredentialInvalid();
|
|
25386
|
+
} catch {
|
|
25387
|
+
}
|
|
25388
|
+
return true;
|
|
25389
|
+
}
|
|
25390
|
+
};
|
|
25391
|
+
}
|
|
25392
|
+
|
|
25308
25393
|
// src/agents/acp/reconcileDelta.ts
|
|
25309
25394
|
function reconcileCumulative(existing, incoming) {
|
|
25310
25395
|
if (incoming.length === 0) return existing;
|
|
@@ -26971,9 +27056,9 @@ async function runAcpSession(opts) {
|
|
|
26971
27056
|
});
|
|
26972
27057
|
let _budgetReachedPosted = false;
|
|
26973
27058
|
const relaunchProxyWithoutBudget = async () => {
|
|
26974
|
-
const { spawn:
|
|
27059
|
+
const { spawn: spawn35 } = await import("child_process");
|
|
26975
27060
|
try {
|
|
26976
|
-
const killer =
|
|
27061
|
+
const killer = spawn35("pkill", ["-TERM", "-f", "headroom.*proxy"], {
|
|
26977
27062
|
detached: true,
|
|
26978
27063
|
stdio: "ignore"
|
|
26979
27064
|
});
|
|
@@ -26985,7 +27070,7 @@ async function runAcpSession(opts) {
|
|
|
26985
27070
|
await new Promise((r) => setTimeout(r, 500));
|
|
26986
27071
|
const proxyEnv = buildRelaunchProxyEnv(process.env);
|
|
26987
27072
|
try {
|
|
26988
|
-
const proxy =
|
|
27073
|
+
const proxy = spawn35(
|
|
26989
27074
|
"headroom",
|
|
26990
27075
|
["proxy", "--port", "8787"],
|
|
26991
27076
|
{ stdio: "ignore", detached: true, env: proxyEnv }
|
|
@@ -27141,6 +27226,17 @@ async function runAcpSession(opts) {
|
|
|
27141
27226
|
);
|
|
27142
27227
|
await onboardingWelcomeDone;
|
|
27143
27228
|
relay.start();
|
|
27229
|
+
void createWakeCredentialProbe({
|
|
27230
|
+
getStatus: () => localCredentialExpiryStatus(opts.agent),
|
|
27231
|
+
emitReauthBubble: async () => {
|
|
27232
|
+
await publisher.publishOutput({ type: "new_turn", done: false });
|
|
27233
|
+
await publisher.publishOutput({ type: "text", content: AUTH_FAILURE_MESSAGE, done: true });
|
|
27234
|
+
history.appendAgentInitiatedReply(AUTH_FAILURE_MESSAGE);
|
|
27235
|
+
await history.flush();
|
|
27236
|
+
},
|
|
27237
|
+
reportCredentialInvalid: () => reportCredentialInvalid(opts),
|
|
27238
|
+
log: (msg) => showInfo(msg)
|
|
27239
|
+
}).run();
|
|
27144
27240
|
const prewarmTimer = setTimeout(() => prewarmPreviewDetection(runtime), 2e4);
|
|
27145
27241
|
const shutdown = async (signal) => {
|
|
27146
27242
|
showInfo(`Shutting down ACP session (${signal})\u2026`);
|
|
@@ -28746,7 +28842,13 @@ async function start(requestedAgent) {
|
|
|
28746
28842
|
const depsReady = process.env.CODESPACES === "true" ? provisionProjectDependencies(cwd).catch(() => void 0) : Promise.resolve();
|
|
28747
28843
|
if (process.env.CODESPACES === "true") {
|
|
28748
28844
|
const GATE_TIMEOUT_MS = 24e4;
|
|
28749
|
-
const
|
|
28845
|
+
const acpAdapterForGate = getAcpAdapter(session.agent);
|
|
28846
|
+
const agentBinaryReady = acpAdapterForGate ? Promise.all([
|
|
28847
|
+
acpAdapterForGate.waitForBinary({ timeoutMs: GATE_TIMEOUT_MS }).catch(() => false),
|
|
28848
|
+
waitForAdapterModuleGraph(acpAdapterForGate.command, acpAdapterForGate.args, {
|
|
28849
|
+
timeoutMs: GATE_TIMEOUT_MS
|
|
28850
|
+
}).catch(() => false)
|
|
28851
|
+
]) : Promise.resolve(true);
|
|
28750
28852
|
let gateTimer;
|
|
28751
28853
|
await Promise.race([
|
|
28752
28854
|
Promise.all([beadsReady.catch(() => null), depsReady, agentBinaryReady]),
|
|
@@ -31507,7 +31609,7 @@ function checkChokidar() {
|
|
|
31507
31609
|
}
|
|
31508
31610
|
async function doctor(args2 = []) {
|
|
31509
31611
|
const json = args2.includes("--json");
|
|
31510
|
-
const cliVersion = true ? "2.
|
|
31612
|
+
const cliVersion = true ? "2.53.1" : "0.0.0-dev";
|
|
31511
31613
|
const apiBase2 = resolveApiBaseUrl();
|
|
31512
31614
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
31513
31615
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -31706,7 +31808,7 @@ async function completion(args2) {
|
|
|
31706
31808
|
// src/commands/version.ts
|
|
31707
31809
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
31708
31810
|
function version2() {
|
|
31709
|
-
const v = true ? "2.
|
|
31811
|
+
const v = true ? "2.53.1" : "unknown";
|
|
31710
31812
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
31711
31813
|
}
|
|
31712
31814
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.53.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",
|