codeam-cli 2.76.34 → 2.76.35
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 +7 -0
- package/dist/index.js +69 -24
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@ 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.76.34] — 2026-10-21
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Collect old versioned installs on every self-update tick (#983)
|
|
12
|
+
- **cli:** Migrate the beads schema on start and pin bd to 1.3.1 in CLI and Box (#984)
|
|
13
|
+
|
|
7
14
|
## [2.76.33] — 2026-10-14
|
|
8
15
|
|
|
9
16
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -10636,7 +10636,7 @@ function readAnonId() {
|
|
|
10636
10636
|
}
|
|
10637
10637
|
function superProperties() {
|
|
10638
10638
|
return {
|
|
10639
|
-
cliVersion: true ? "2.76.
|
|
10639
|
+
cliVersion: true ? "2.76.35" : "0.0.0-dev",
|
|
10640
10640
|
nodeVersion: process.version,
|
|
10641
10641
|
platform: process.platform,
|
|
10642
10642
|
arch: process.arch,
|
|
@@ -10885,7 +10885,7 @@ var http = __toESM(require("http"));
|
|
|
10885
10885
|
// package.json
|
|
10886
10886
|
var package_default = {
|
|
10887
10887
|
name: "codeam-cli",
|
|
10888
|
-
version: "2.76.
|
|
10888
|
+
version: "2.76.35",
|
|
10889
10889
|
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.",
|
|
10890
10890
|
type: "commonjs",
|
|
10891
10891
|
main: "dist/index.js",
|
|
@@ -12261,7 +12261,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
12261
12261
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
12262
12262
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
12263
12263
|
// pair/reconnect). Older backends ignore the extra field.
|
|
12264
|
-
..."2.76.
|
|
12264
|
+
..."2.76.35" ? { ideVersion: "2.76.35" } : {}
|
|
12265
12265
|
};
|
|
12266
12266
|
try {
|
|
12267
12267
|
const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body, this.pollSecretHeader());
|
|
@@ -26033,6 +26033,18 @@ var ONE_M_CREDITS_MESSAGE = "\u{1F504} **Reconnect your Claude subscription to c
|
|
|
26033
26033
|
var TURN_FAILURE_MESSAGE = "\u26A0\uFE0F **The agent hit an error and couldn\u2019t finish this turn.** Please send your message again.";
|
|
26034
26034
|
var IDLE_TURN_FAILURE_MESSAGE = "\u26A0\uFE0F **The agent stopped responding, so this turn was ended.** Your message wasn\u2019t answered \u2014 send it again.";
|
|
26035
26035
|
var IDLE_TURN_RE = /ACP prompt idle/;
|
|
26036
|
+
var AGENT_FREE_LIMIT_RE = /Free usage limit reached/i;
|
|
26037
|
+
function looksLikeAgentFreeLimit(text) {
|
|
26038
|
+
return AGENT_FREE_LIMIT_RE.test(text);
|
|
26039
|
+
}
|
|
26040
|
+
var AGENT_FREE_LIMIT_MESSAGE = [
|
|
26041
|
+
"\u26A0\uFE0F **OpenCode\u2019s free models have hit their usage limit, so this message wasn\u2019t answered.**",
|
|
26042
|
+
"",
|
|
26043
|
+
"Messages will keep failing until the limit resets. To keep going now:",
|
|
26044
|
+
"\u2022 add your own provider key for opencode in **Profile \u203A Agents** (OpenRouter, Anthropic, OpenAI, \u2026),",
|
|
26045
|
+
"\u2022 switch this session to another agent, or",
|
|
26046
|
+
"\u2022 subscribe to OpenCode Go: [opencode.ai/go](https://opencode.ai/go)."
|
|
26047
|
+
].join("\n");
|
|
26036
26048
|
function emptyReplyMessage(agent) {
|
|
26037
26049
|
const label = isKnownAgentId(agent) ? AGENT_REGISTRY[agent].displayName : agent;
|
|
26038
26050
|
const binary = isKnownAgentId(agent) ? AGENT_REGISTRY[agent].binaryName : agent;
|
|
@@ -26096,6 +26108,9 @@ function failureBubble(opts) {
|
|
|
26096
26108
|
return houseAgentLimitMessage(`${opts.detail}
|
|
26097
26109
|
${opts.recentStderr}`);
|
|
26098
26110
|
}
|
|
26111
|
+
if (looksLikeAgentFreeLimit(opts.detail) || looksLikeAgentFreeLimit(opts.recentStderr)) {
|
|
26112
|
+
return AGENT_FREE_LIMIT_MESSAGE;
|
|
26113
|
+
}
|
|
26099
26114
|
if (looksLikeByoProviderBilling(opts.detail, env) || looksLikeByoProviderBilling(opts.recentStderr, env)) {
|
|
26100
26115
|
return byoProviderBillingMessage(byoProviderName({ env, agent: opts.agent }));
|
|
26101
26116
|
}
|
|
@@ -31845,6 +31860,7 @@ function isLocalSession(env = process.env) {
|
|
|
31845
31860
|
|
|
31846
31861
|
// src/agents/acp/adapters.ts
|
|
31847
31862
|
var require_ = require;
|
|
31863
|
+
var OPENCODE_FATAL_TURN_STDERR_RE = /message="stream error".*error\.error="[^"]*(Free usage limit reached|insufficient[_ ]quota|invalid[_ ]api[_ ]key|incorrect api key|unauthorized)/i;
|
|
31848
31864
|
function claudeBinaryWaiter(opts = {}) {
|
|
31849
31865
|
return waitForClaudeNativeBinary(opts).then((p2) => p2 !== null);
|
|
31850
31866
|
}
|
|
@@ -32004,8 +32020,12 @@ var REGISTRY = {
|
|
|
32004
32020
|
// the ACP client spawns the adapter with `env: { ...process.env, ...extraEnv }`.
|
|
32005
32021
|
opencode: () => ({
|
|
32006
32022
|
command: "opencode",
|
|
32007
|
-
|
|
32023
|
+
// `--print-logs --log-level ERROR`: opencode writes its provider errors only
|
|
32024
|
+
// to its own log file, so without these flags they never reach the adapter
|
|
32025
|
+
// stderr we read (see OPENCODE_FATAL_TURN_STDERR_RE).
|
|
32026
|
+
args: ["acp", "--print-logs", "--log-level", "ERROR"],
|
|
32008
32027
|
requiresAgentBinary: "opencode",
|
|
32028
|
+
fatalTurnStderr: OPENCODE_FATAL_TURN_STDERR_RE,
|
|
32009
32029
|
waitForBinary: async (o) => {
|
|
32010
32030
|
if (isLocalSession()) await ensureOpencodeInstalled();
|
|
32011
32031
|
augmentOpencodePath();
|
|
@@ -37132,6 +37152,9 @@ var _acpStartSeam = {
|
|
|
37132
37152
|
var PROTOCOL_VERSION3 = 1;
|
|
37133
37153
|
var FATAL_STARTUP_RE = /IneligibleTierError|UNSUPPORTED_CLIENT|no longer supported for Gemini Code Assist|not eligible for Gemini Code Assist|Error authenticating|ProjectIdRequiredError/i;
|
|
37134
37154
|
var NEWSESSION_TIMEOUT_MS = 12e4;
|
|
37155
|
+
function agentErrorOf(line) {
|
|
37156
|
+
return /error\.error="([^"]+)"/.exec(line)?.[1] ?? line;
|
|
37157
|
+
}
|
|
37135
37158
|
var MCP_STARTUP_TIMEOUT_MS = NEWSESSION_TIMEOUT_MS - 3e4;
|
|
37136
37159
|
var AGENT_ENV_WITHHELD = ["PREVIEW_TUNNEL_TOKEN", "PREVIEW_TUNNEL_HOSTNAME"];
|
|
37137
37160
|
var LOADSESSION_TIMEOUT_MS = 6e4;
|
|
@@ -37237,6 +37260,12 @@ var AcpClient = class {
|
|
|
37237
37260
|
* engages; with it, the crash rejects immediately → retry respawns once the
|
|
37238
37261
|
* install settles. Broader than {@link startupFailureReject} (newSession-only). */
|
|
37239
37262
|
startAbortReject = null;
|
|
37263
|
+
/** The adapter's {@link AdapterSpec.fatalTurnStderr}, set at spawn. */
|
|
37264
|
+
fatalTurnStderr = null;
|
|
37265
|
+
/** Set while a `session/prompt` is in flight; the stderr watcher calls it on
|
|
37266
|
+
* a {@link fatalTurnStderr} line to end the turn now (opencode keeps a turn
|
|
37267
|
+
* open forever after a terminal provider error — see the adapter spec). */
|
|
37268
|
+
turnFailureReject = null;
|
|
37240
37269
|
/**
|
|
37241
37270
|
* Spawn the adapter + handshake, retrying a TRANSIENT in-adapter spawn race.
|
|
37242
37271
|
*
|
|
@@ -37325,6 +37354,7 @@ var AcpClient = class {
|
|
|
37325
37354
|
"acpClient",
|
|
37326
37355
|
`provider routing ${formatProviderRouting(describeProviderRouting(childEnv, { cwd }), adapter.command)}`
|
|
37327
37356
|
);
|
|
37357
|
+
this.fatalTurnStderr = adapter.fatalTurnStderr ?? null;
|
|
37328
37358
|
const child = (0, import_node_child_process28.spawn)(adapter.command, adapter.args, {
|
|
37329
37359
|
cwd,
|
|
37330
37360
|
env: childEnv,
|
|
@@ -37350,16 +37380,7 @@ var AcpClient = class {
|
|
|
37350
37380
|
child.stderr?.on("data", (chunk) => {
|
|
37351
37381
|
for (const line of chunk.split(/\r?\n/)) {
|
|
37352
37382
|
const trimmed = line.trim();
|
|
37353
|
-
if (trimmed)
|
|
37354
|
-
log.info("acpAdapter", trimmed);
|
|
37355
|
-
this.opts.onStderr?.(trimmed);
|
|
37356
|
-
this.recentStderr.push(trimmed);
|
|
37357
|
-
if (this.recentStderr.length > 12) this.recentStderr.shift();
|
|
37358
|
-
if (this.startupFailureReject && FATAL_STARTUP_RE.test(trimmed)) {
|
|
37359
|
-
this.startupFailureReject(new Error(`AGENT_STARTUP_FAILED: ${trimmed}`));
|
|
37360
|
-
this.startupFailureReject = null;
|
|
37361
|
-
}
|
|
37362
|
-
}
|
|
37383
|
+
if (trimmed) this.onAdapterStderrLine(trimmed);
|
|
37363
37384
|
}
|
|
37364
37385
|
});
|
|
37365
37386
|
child.on("exit", (code, signal) => {
|
|
@@ -37559,9 +37580,16 @@ var AcpClient = class {
|
|
|
37559
37580
|
PROMPT_ACTIVE_IDLE_TIMEOUT_MS
|
|
37560
37581
|
);
|
|
37561
37582
|
this.promptIdle = idle;
|
|
37583
|
+
let fatalTripped = false;
|
|
37584
|
+
const fatal = new Promise((_2, reject) => {
|
|
37585
|
+
this.turnFailureReject = (err) => {
|
|
37586
|
+
fatalTripped = true;
|
|
37587
|
+
reject(err);
|
|
37588
|
+
};
|
|
37589
|
+
});
|
|
37562
37590
|
this.pendingToolCalls.clear();
|
|
37563
37591
|
try {
|
|
37564
|
-
const result = await Promise.race([send, idle.promise]);
|
|
37592
|
+
const result = await Promise.race([send, idle.promise, fatal]);
|
|
37565
37593
|
await new Promise((resolve13) => setImmediate(resolve13));
|
|
37566
37594
|
log.info(
|
|
37567
37595
|
"acpClient",
|
|
@@ -37575,15 +37603,32 @@ var AcpClient = class {
|
|
|
37575
37603
|
"acpClient",
|
|
37576
37604
|
`prompt \u2190 failed elapsedMs=${Date.now() - t0} err=${err instanceof Error ? err.message : String(err)}`
|
|
37577
37605
|
);
|
|
37578
|
-
if (idleTripped) await this.cancelAbandonedTurn(sessionId, send);
|
|
37606
|
+
if (idleTripped || fatalTripped) await this.cancelAbandonedTurn(sessionId, send);
|
|
37579
37607
|
throw err;
|
|
37580
37608
|
} finally {
|
|
37581
37609
|
idle.clear();
|
|
37582
37610
|
this.promptIdle = null;
|
|
37611
|
+
this.turnFailureReject = null;
|
|
37612
|
+
}
|
|
37613
|
+
}
|
|
37614
|
+
/** One non-empty adapter stderr line: logged, kept in the ring, and checked
|
|
37615
|
+
* for the fatal startup / fatal turn errors that end a stuck RPC early. */
|
|
37616
|
+
onAdapterStderrLine(trimmed) {
|
|
37617
|
+
log.info("acpAdapter", trimmed);
|
|
37618
|
+
this.opts.onStderr?.(trimmed);
|
|
37619
|
+
this.recentStderr.push(trimmed);
|
|
37620
|
+
if (this.recentStderr.length > 12) this.recentStderr.shift();
|
|
37621
|
+
if (this.startupFailureReject && FATAL_STARTUP_RE.test(trimmed)) {
|
|
37622
|
+
this.startupFailureReject(new Error(`AGENT_STARTUP_FAILED: ${trimmed}`));
|
|
37623
|
+
this.startupFailureReject = null;
|
|
37624
|
+
}
|
|
37625
|
+
if (this.turnFailureReject && this.fatalTurnStderr?.test(trimmed)) {
|
|
37626
|
+
this.turnFailureReject(new Error(`AGENT_TURN_FAILED: ${agentErrorOf(trimmed)}`));
|
|
37627
|
+
this.turnFailureReject = null;
|
|
37583
37628
|
}
|
|
37584
37629
|
}
|
|
37585
37630
|
/**
|
|
37586
|
-
* Cancel a turn the idle watchdog abandoned and wait, bounded, for the
|
|
37631
|
+
* Cancel a turn the idle watchdog (or a fatal stderr error) abandoned and wait, bounded, for the
|
|
37587
37632
|
* adapter to answer its `session/prompt` — the proof the turn is over before
|
|
37588
37633
|
* the next prompt is sent. Best-effort: a dead adapter can't hold the queue
|
|
37589
37634
|
* longer than {@link ABANDONED_TURN_SETTLE_MS}.
|
|
@@ -43678,7 +43723,7 @@ async function runStartTaskTurn(ctx, payload, blocks, promptText) {
|
|
|
43678
43723
|
reportTurn2(
|
|
43679
43724
|
ctx,
|
|
43680
43725
|
"failed",
|
|
43681
|
-
bubble === AUTH_FAILURE_MESSAGE ? "AUTH_FAILED" : bubble === ONE_M_CREDITS_MESSAGE ? "ONE_M_CREDITS" : failed.partialReplyKept ? "TURN_ERROR_PARTIAL" : "TURN_ERROR"
|
|
43726
|
+
bubble === AUTH_FAILURE_MESSAGE ? "AUTH_FAILED" : bubble === ONE_M_CREDITS_MESSAGE ? "ONE_M_CREDITS" : bubble === AGENT_FREE_LIMIT_MESSAGE ? "AGENT_FREE_LIMIT" : failed.partialReplyKept ? "TURN_ERROR_PARTIAL" : "TURN_ERROR"
|
|
43682
43727
|
);
|
|
43683
43728
|
if (bubble === AUTH_FAILURE_MESSAGE || bubble === ONE_M_CREDITS_MESSAGE) {
|
|
43684
43729
|
void reportCredentialInvalid(opts);
|
|
@@ -51622,7 +51667,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
51622
51667
|
if (process.env.NODE_ENV === "test") return;
|
|
51623
51668
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51624
51669
|
if (process.env.CI) return;
|
|
51625
|
-
const current2 = true ? "2.76.
|
|
51670
|
+
const current2 = true ? "2.76.35" : null;
|
|
51626
51671
|
if (!current2) return;
|
|
51627
51672
|
const cache = readCache();
|
|
51628
51673
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51639,7 +51684,7 @@ function checkForUpdates() {
|
|
|
51639
51684
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51640
51685
|
if (process.env.CI) return;
|
|
51641
51686
|
if (!process.stdout.isTTY) return;
|
|
51642
|
-
const current2 = true ? "2.76.
|
|
51687
|
+
const current2 = true ? "2.76.35" : null;
|
|
51643
51688
|
if (!current2) return;
|
|
51644
51689
|
const cache = readCache();
|
|
51645
51690
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51945,7 +51990,7 @@ var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
|
51945
51990
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
51946
51991
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
51947
51992
|
function currentCliVersion() {
|
|
51948
|
-
return true ? "2.76.
|
|
51993
|
+
return true ? "2.76.35" : null;
|
|
51949
51994
|
}
|
|
51950
51995
|
async function installedVersion(deps) {
|
|
51951
51996
|
const ls = await deps.run(
|
|
@@ -52168,7 +52213,7 @@ function signalHostReady(send = process.send?.bind(process)) {
|
|
|
52168
52213
|
}
|
|
52169
52214
|
function defaultDeps() {
|
|
52170
52215
|
return {
|
|
52171
|
-
ownVersion: true ? "2.76.
|
|
52216
|
+
ownVersion: true ? "2.76.35" : null,
|
|
52172
52217
|
root: cliVersionsRoot(),
|
|
52173
52218
|
args: process.argv.slice(3),
|
|
52174
52219
|
execPath: process.execPath,
|
|
@@ -54706,7 +54751,7 @@ function checkChokidar() {
|
|
|
54706
54751
|
}
|
|
54707
54752
|
async function doctor(args2 = []) {
|
|
54708
54753
|
const json = args2.includes("--json");
|
|
54709
|
-
const cliVersion = true ? "2.76.
|
|
54754
|
+
const cliVersion = true ? "2.76.35" : "0.0.0-dev";
|
|
54710
54755
|
const apiBase2 = resolveApiBaseUrl();
|
|
54711
54756
|
const diagnosticId = (0, import_node_crypto17.randomUUID)();
|
|
54712
54757
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -55242,7 +55287,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
55242
55287
|
// src/commands/version.ts
|
|
55243
55288
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
55244
55289
|
function version2() {
|
|
55245
|
-
const v = true ? "2.76.
|
|
55290
|
+
const v = true ? "2.76.35" : "unknown";
|
|
55246
55291
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
55247
55292
|
}
|
|
55248
55293
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.76.
|
|
3
|
+
"version": "2.76.35",
|
|
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",
|