codeam-cli 2.53.0 → 2.53.2
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 +95 -20
- 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.1] — 2026-07-06
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Gate ACP adapter spawn on its JS module graph, not just its binary
|
|
12
|
+
|
|
13
|
+
## [2.53.0] — 2026-07-06
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **cli:** Proactive credential validation on session start / wake
|
|
18
|
+
|
|
7
19
|
## [2.52.12] — 2026-07-05
|
|
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.53.
|
|
5400
|
+
cliVersion: true ? "2.53.2" : "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.53.
|
|
5581
|
+
version: "2.53.2",
|
|
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.53.
|
|
6546
|
+
..."2.53.2" ? { ideVersion: "2.53.2" } : {}
|
|
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.53.
|
|
15026
|
+
const current = true ? "2.53.2" : 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.53.
|
|
15043
|
+
const current = true ? "2.53.2" : 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.53.
|
|
15745
|
+
return true ? "2.53.2" : null;
|
|
15746
15746
|
}
|
|
15747
15747
|
function runCmd(cmd, args2, timeoutMs) {
|
|
15748
15748
|
return new Promise((resolve7) => {
|
|
@@ -16465,7 +16465,13 @@ async function configureHeadroom(action, ctx, deps) {
|
|
|
16465
16465
|
return { enabled: false };
|
|
16466
16466
|
}
|
|
16467
16467
|
deps.persist({ enabled: true, agent: kind, ingestUrl: ctx.savingsIngestUrl });
|
|
16468
|
-
|
|
16468
|
+
if (ctx.pluginAuthToken) {
|
|
16469
|
+
deps.startReporter({
|
|
16470
|
+
agent: kind,
|
|
16471
|
+
ingestUrl: ctx.savingsIngestUrl,
|
|
16472
|
+
pluginAuthToken: ctx.pluginAuthToken
|
|
16473
|
+
});
|
|
16474
|
+
}
|
|
16469
16475
|
deps.emit({ type: "headroom_status", state: "enabled" });
|
|
16470
16476
|
return { enabled: true };
|
|
16471
16477
|
}
|
|
@@ -21198,6 +21204,60 @@ async function waitForCommandOnPath(cmd, opts = {}) {
|
|
|
21198
21204
|
}
|
|
21199
21205
|
return check();
|
|
21200
21206
|
}
|
|
21207
|
+
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;
|
|
21208
|
+
function probeAdapterModuleGraph(command2, args2, opts = {}) {
|
|
21209
|
+
const livenessMs = opts.livenessMs ?? 400;
|
|
21210
|
+
const spawnFn = opts.spawnFn ?? import_child_process24.spawn;
|
|
21211
|
+
return new Promise((resolve7) => {
|
|
21212
|
+
let settled = false;
|
|
21213
|
+
let stderr = "";
|
|
21214
|
+
let timer;
|
|
21215
|
+
let child;
|
|
21216
|
+
const finish = (r) => {
|
|
21217
|
+
if (settled) return;
|
|
21218
|
+
settled = true;
|
|
21219
|
+
if (timer) clearTimeout(timer);
|
|
21220
|
+
try {
|
|
21221
|
+
child?.kill("SIGKILL");
|
|
21222
|
+
} catch {
|
|
21223
|
+
}
|
|
21224
|
+
resolve7(r);
|
|
21225
|
+
};
|
|
21226
|
+
try {
|
|
21227
|
+
child = spawnFn(command2, [...args2], { stdio: ["pipe", "ignore", "pipe"] });
|
|
21228
|
+
} catch {
|
|
21229
|
+
resolve7("ok");
|
|
21230
|
+
return;
|
|
21231
|
+
}
|
|
21232
|
+
child.stderr?.on("data", (d3) => {
|
|
21233
|
+
stderr += d3.toString();
|
|
21234
|
+
if (stderr.length > 8192) stderr = stderr.slice(-8192);
|
|
21235
|
+
});
|
|
21236
|
+
child.on("error", () => finish("ok"));
|
|
21237
|
+
child.on("exit", (code) => {
|
|
21238
|
+
if (code !== 0 && code !== null && ADAPTER_MODULE_LOAD_ERROR_RE.test(stderr)) {
|
|
21239
|
+
finish("transient");
|
|
21240
|
+
} else {
|
|
21241
|
+
finish("ok");
|
|
21242
|
+
}
|
|
21243
|
+
});
|
|
21244
|
+
timer = setTimeout(() => finish("ok"), livenessMs);
|
|
21245
|
+
});
|
|
21246
|
+
}
|
|
21247
|
+
async function waitForAdapterModuleGraph(command2, args2, opts = {}) {
|
|
21248
|
+
const timeoutMs = opts.timeoutMs ?? 18e4;
|
|
21249
|
+
const pollMs = opts.pollMs ?? 500;
|
|
21250
|
+
const now = opts.now ?? Date.now;
|
|
21251
|
+
const sleep3 = opts.sleep ?? realSleep;
|
|
21252
|
+
const probeOpts = { livenessMs: opts.livenessMs, spawnFn: opts.spawnFn };
|
|
21253
|
+
const deadline = now() + timeoutMs;
|
|
21254
|
+
if (await probeAdapterModuleGraph(command2, args2, probeOpts) === "ok") return true;
|
|
21255
|
+
while (now() < deadline) {
|
|
21256
|
+
await sleep3(pollMs);
|
|
21257
|
+
if (await probeAdapterModuleGraph(command2, args2, probeOpts) === "ok") return true;
|
|
21258
|
+
}
|
|
21259
|
+
return false;
|
|
21260
|
+
}
|
|
21201
21261
|
|
|
21202
21262
|
// src/agents/acp/adapters.ts
|
|
21203
21263
|
var require_ = require;
|
|
@@ -26672,6 +26732,7 @@ function replyIsCursorUpgradeRequired(finalText) {
|
|
|
26672
26732
|
return t2.includes("upgrade your plan to continue") || t2.includes("upgrade your plan") && t2.includes("continue");
|
|
26673
26733
|
}
|
|
26674
26734
|
var CURSOR_UPGRADE_MESSAGE = "\u26A1 **Cursor needs a paid plan to run the agent.**\n\nThe headless Cursor Agent requires Cursor **Pro** \u2014 your Free plan\u2019s included usage does NOT cover Agent runs, even with quota left. This is your Cursor account (not CodeAgent). Upgrade, then send your message again:\n\n[Upgrade to Cursor Pro \u2192](https://cursor.com/dashboard)";
|
|
26735
|
+
var ONE_M_CREDITS_MESSAGE = "\u{1F504} **Reconnect your Claude subscription to continue.**\n\nClaude requested 1M-context but your account doesn\u2019t have the usage credits for it on this credential. Reconnecting refreshes your subscription so the agent can keep going \u2014 disabling 1M context won\u2019t fix a credits gate.\n\nTap [Reconnect this agent](codeam://reauth) to reconnect your Claude subscription in Profile \u203A Agents, then send your message again.";
|
|
26675
26736
|
var TURN_FAILURE_MESSAGE = "\u26A0\uFE0F **The agent hit an error and couldn\u2019t finish this turn.** Please send your message again.";
|
|
26676
26737
|
var ACP_QUICK_REPLIES = ["Continue", "Yes, go ahead", "Explain"];
|
|
26677
26738
|
var PROVIDER_OUTAGE_RE = /overloaded_error|\boverloaded\b|service[ _]unavailable|temporarily[ _]unavailable|(?:api error|http|status)[:\s]+(?:529|503|502|504)\b|\b(?:529|503|502|504)\b[^\n]{0,40}(?:overload|unavailable|gateway|upstream|server error)|bad gateway|gateway time-?out|upstream (?:error|connect|timeout)/i;
|
|
@@ -26771,6 +26832,9 @@ function failureBubble(opts) {
|
|
|
26771
26832
|
if (looksLikeAuthFailure(opts.detail) || looksLikeAuthFailure(opts.recentStderr)) {
|
|
26772
26833
|
return AUTH_FAILURE_MESSAGE;
|
|
26773
26834
|
}
|
|
26835
|
+
if (looksLike1mContextCreditsError(opts.detail) || looksLike1mContextCreditsError(opts.recentStderr)) {
|
|
26836
|
+
return ONE_M_CREDITS_MESSAGE;
|
|
26837
|
+
}
|
|
26774
26838
|
const budgetHaystack = `${opts.detail}
|
|
26775
26839
|
${opts.recentStderr}`;
|
|
26776
26840
|
if (looksLikeBudgetExceeded(budgetHaystack)) {
|
|
@@ -27002,9 +27066,9 @@ async function runAcpSession(opts) {
|
|
|
27002
27066
|
});
|
|
27003
27067
|
let _budgetReachedPosted = false;
|
|
27004
27068
|
const relaunchProxyWithoutBudget = async () => {
|
|
27005
|
-
const { spawn:
|
|
27069
|
+
const { spawn: spawn35 } = await import("child_process");
|
|
27006
27070
|
try {
|
|
27007
|
-
const killer =
|
|
27071
|
+
const killer = spawn35("pkill", ["-TERM", "-f", "headroom.*proxy"], {
|
|
27008
27072
|
detached: true,
|
|
27009
27073
|
stdio: "ignore"
|
|
27010
27074
|
});
|
|
@@ -27016,7 +27080,7 @@ async function runAcpSession(opts) {
|
|
|
27016
27080
|
await new Promise((r) => setTimeout(r, 500));
|
|
27017
27081
|
const proxyEnv = buildRelaunchProxyEnv(process.env);
|
|
27018
27082
|
try {
|
|
27019
|
-
const proxy =
|
|
27083
|
+
const proxy = spawn35(
|
|
27020
27084
|
"headroom",
|
|
27021
27085
|
["proxy", "--port", "8787"],
|
|
27022
27086
|
{ stdio: "ignore", detached: true, env: proxyEnv }
|
|
@@ -27258,7 +27322,17 @@ async function handleCommand(cmd, client2, relay, acpSessionId, models, streamin
|
|
|
27258
27322
|
log.info("acpRunner", `start_task \u2190 auth-failure-in-reply id=${cmd.id.slice(0, 8)}`);
|
|
27259
27323
|
await relay.sendResult(cmd.id, "failed", { error: "agent reply reported auth failure" });
|
|
27260
27324
|
} else if (shouldOfferOneMRecovery({ detail: "", recentStderr: recentStderr.join("\n"), finalText })) {
|
|
27261
|
-
await
|
|
27325
|
+
await streaming.closeWithBubble(ONE_M_CREDITS_MESSAGE);
|
|
27326
|
+
history.appendAgentReply(ONE_M_CREDITS_MESSAGE);
|
|
27327
|
+
void history.flush();
|
|
27328
|
+
turnFiles.flushTurn().catch((err) => {
|
|
27329
|
+
log.warn("acpRunner", `turnFiles.flushTurn failed: ${describeError(err)}`);
|
|
27330
|
+
});
|
|
27331
|
+
void reportCredentialInvalid(opts);
|
|
27332
|
+
log.info("acpRunner", `start_task \u2190 1m-credits-reconnect id=${cmd.id.slice(0, 8)}`);
|
|
27333
|
+
await relay.sendResult(cmd.id, "failed", {
|
|
27334
|
+
error: "agent reply reported 1M-context usage-credits gate"
|
|
27335
|
+
});
|
|
27262
27336
|
} else {
|
|
27263
27337
|
await streaming.closeTurnWithInteractiveDetection();
|
|
27264
27338
|
const replyLine = formatAgentReplyLine(finalText);
|
|
@@ -27301,11 +27375,6 @@ ${recentStderr.join("\n")}`)
|
|
|
27301
27375
|
${recentStderr.join("\n")}`);
|
|
27302
27376
|
return;
|
|
27303
27377
|
}
|
|
27304
|
-
if (shouldOfferOneMRecovery({ detail, recentStderr: recentStderr.join("\n"), finalText: "" })) {
|
|
27305
|
-
await streaming.closeAll();
|
|
27306
|
-
await oneMRecovery.offer(cmd.id, blocks);
|
|
27307
|
-
return;
|
|
27308
|
-
}
|
|
27309
27378
|
const bubble = failureBubble({
|
|
27310
27379
|
detail,
|
|
27311
27380
|
recentStderr: recentStderr.join("\n"),
|
|
@@ -27319,7 +27388,7 @@ ${recentStderr.join("\n")}`);
|
|
|
27319
27388
|
} else {
|
|
27320
27389
|
await streaming.closeAll();
|
|
27321
27390
|
}
|
|
27322
|
-
if (bubble === AUTH_FAILURE_MESSAGE) {
|
|
27391
|
+
if (bubble === AUTH_FAILURE_MESSAGE || bubble === ONE_M_CREDITS_MESSAGE) {
|
|
27323
27392
|
void reportCredentialInvalid(opts);
|
|
27324
27393
|
}
|
|
27325
27394
|
await relay.sendResult(cmd.id, "failed", { error: detail });
|
|
@@ -28788,7 +28857,13 @@ async function start(requestedAgent) {
|
|
|
28788
28857
|
const depsReady = process.env.CODESPACES === "true" ? provisionProjectDependencies(cwd).catch(() => void 0) : Promise.resolve();
|
|
28789
28858
|
if (process.env.CODESPACES === "true") {
|
|
28790
28859
|
const GATE_TIMEOUT_MS = 24e4;
|
|
28791
|
-
const
|
|
28860
|
+
const acpAdapterForGate = getAcpAdapter(session.agent);
|
|
28861
|
+
const agentBinaryReady = acpAdapterForGate ? Promise.all([
|
|
28862
|
+
acpAdapterForGate.waitForBinary({ timeoutMs: GATE_TIMEOUT_MS }).catch(() => false),
|
|
28863
|
+
waitForAdapterModuleGraph(acpAdapterForGate.command, acpAdapterForGate.args, {
|
|
28864
|
+
timeoutMs: GATE_TIMEOUT_MS
|
|
28865
|
+
}).catch(() => false)
|
|
28866
|
+
]) : Promise.resolve(true);
|
|
28792
28867
|
let gateTimer;
|
|
28793
28868
|
await Promise.race([
|
|
28794
28869
|
Promise.all([beadsReady.catch(() => null), depsReady, agentBinaryReady]),
|
|
@@ -31549,7 +31624,7 @@ function checkChokidar() {
|
|
|
31549
31624
|
}
|
|
31550
31625
|
async function doctor(args2 = []) {
|
|
31551
31626
|
const json = args2.includes("--json");
|
|
31552
|
-
const cliVersion = true ? "2.53.
|
|
31627
|
+
const cliVersion = true ? "2.53.2" : "0.0.0-dev";
|
|
31553
31628
|
const apiBase2 = resolveApiBaseUrl();
|
|
31554
31629
|
const diagnosticId = (0, import_node_crypto8.randomUUID)();
|
|
31555
31630
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -31748,7 +31823,7 @@ async function completion(args2) {
|
|
|
31748
31823
|
// src/commands/version.ts
|
|
31749
31824
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
31750
31825
|
function version2() {
|
|
31751
|
-
const v = true ? "2.53.
|
|
31826
|
+
const v = true ? "2.53.2" : "unknown";
|
|
31752
31827
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
31753
31828
|
}
|
|
31754
31829
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.53.
|
|
3
|
+
"version": "2.53.2",
|
|
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",
|