codeam-cli 2.76.27 → 2.76.29
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 +22 -0
- package/dist/index.js +89 -16
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,28 @@ 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.28] — 2026-10-13
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **cli:** Let a fleet host run another registry tag of the Box image
|
|
12
|
+
|
|
13
|
+
### CI
|
|
14
|
+
|
|
15
|
+
- **release:** Publish to npm next and promote to latest only after the journey canary
|
|
16
|
+
|
|
17
|
+
## [2.76.27] — 2026-10-13
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- **cli:** No baton state before the local agent starts (04jp)
|
|
22
|
+
|
|
23
|
+
## [2.76.26] — 2026-10-13
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- **both-plugins:** Report which agents can take a prompt from the phone
|
|
28
|
+
|
|
7
29
|
## [2.76.25] — 2026-10-12
|
|
8
30
|
|
|
9
31
|
### CI
|
package/dist/index.js
CHANGED
|
@@ -10627,7 +10627,7 @@ function readAnonId() {
|
|
|
10627
10627
|
}
|
|
10628
10628
|
function superProperties() {
|
|
10629
10629
|
return {
|
|
10630
|
-
cliVersion: true ? "2.76.
|
|
10630
|
+
cliVersion: true ? "2.76.29" : "0.0.0-dev",
|
|
10631
10631
|
nodeVersion: process.version,
|
|
10632
10632
|
platform: process.platform,
|
|
10633
10633
|
arch: process.arch,
|
|
@@ -10876,7 +10876,7 @@ var http = __toESM(require("http"));
|
|
|
10876
10876
|
// package.json
|
|
10877
10877
|
var package_default = {
|
|
10878
10878
|
name: "codeam-cli",
|
|
10879
|
-
version: "2.76.
|
|
10879
|
+
version: "2.76.29",
|
|
10880
10880
|
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.",
|
|
10881
10881
|
type: "commonjs",
|
|
10882
10882
|
main: "dist/index.js",
|
|
@@ -12239,7 +12239,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
12239
12239
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
12240
12240
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
12241
12241
|
// pair/reconnect). Older backends ignore the extra field.
|
|
12242
|
-
..."2.76.
|
|
12242
|
+
..."2.76.29" ? { ideVersion: "2.76.29" } : {}
|
|
12243
12243
|
};
|
|
12244
12244
|
try {
|
|
12245
12245
|
const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body, this.pollSecretHeader());
|
|
@@ -25991,6 +25991,8 @@ var AUTH_FAILURE_MESSAGE = (
|
|
|
25991
25991
|
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)";
|
|
25992
25992
|
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.";
|
|
25993
25993
|
var TURN_FAILURE_MESSAGE = "\u26A0\uFE0F **The agent hit an error and couldn\u2019t finish this turn.** Please send your message again.";
|
|
25994
|
+
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.";
|
|
25995
|
+
var IDLE_TURN_RE = /ACP prompt idle/;
|
|
25994
25996
|
function emptyReplyMessage(agent) {
|
|
25995
25997
|
const label = isKnownAgentId(agent) ? AGENT_REGISTRY[agent].displayName : agent;
|
|
25996
25998
|
const binary = isKnownAgentId(agent) ? AGENT_REGISTRY[agent].binaryName : agent;
|
|
@@ -26066,7 +26068,9 @@ ${opts.recentStderr}`);
|
|
|
26066
26068
|
if (looksLikeProviderOutage(opts.detail) || looksLikeProviderOutage(opts.recentStderr)) {
|
|
26067
26069
|
return providerOutageMessage(opts.agent, opts.railWireId);
|
|
26068
26070
|
}
|
|
26069
|
-
if (!opts.hadText)
|
|
26071
|
+
if (!opts.hadText) {
|
|
26072
|
+
return IDLE_TURN_RE.test(opts.detail) ? IDLE_TURN_FAILURE_MESSAGE : TURN_FAILURE_MESSAGE;
|
|
26073
|
+
}
|
|
26070
26074
|
return null;
|
|
26071
26075
|
}
|
|
26072
26076
|
var WINDOWS_CONTROL_C_EXIT = 3221225786;
|
|
@@ -36993,6 +36997,7 @@ var AGENT_ENV_WITHHELD = ["PREVIEW_TUNNEL_TOKEN", "PREVIEW_TUNNEL_HOSTNAME"];
|
|
|
36993
36997
|
var LOADSESSION_TIMEOUT_MS = 6e4;
|
|
36994
36998
|
var PROMPT_IDLE_TIMEOUT_MS = 9e4;
|
|
36995
36999
|
var PROMPT_ACTIVE_IDLE_TIMEOUT_MS = 6e5;
|
|
37000
|
+
var ABANDONED_TURN_SETTLE_MS = 1e4;
|
|
36996
37001
|
var CLIENT_CAPABILITIES = {
|
|
36997
37002
|
fs: { readTextFile: true, writeTextFile: true },
|
|
36998
37003
|
terminal: false
|
|
@@ -37397,15 +37402,20 @@ var AcpClient = class {
|
|
|
37397
37402
|
`prompt \u2192 session=${this.sessionId.slice(0, 8)} textChars=${textLen} imageBlocks=${imageCount}`
|
|
37398
37403
|
);
|
|
37399
37404
|
const t0 = Date.now();
|
|
37405
|
+
const sessionId = this.sessionId;
|
|
37400
37406
|
const send = this.connection.prompt({
|
|
37401
|
-
sessionId
|
|
37407
|
+
sessionId,
|
|
37402
37408
|
prompt: blocks
|
|
37403
37409
|
});
|
|
37410
|
+
let idleTripped = false;
|
|
37404
37411
|
const idle = createIdleTimeout(
|
|
37405
37412
|
PROMPT_IDLE_TIMEOUT_MS,
|
|
37406
|
-
() =>
|
|
37407
|
-
|
|
37408
|
-
|
|
37413
|
+
() => {
|
|
37414
|
+
idleTripped = true;
|
|
37415
|
+
return new Error(
|
|
37416
|
+
`ACP prompt idle \u2014 adapter sent no updates for the idle window (${PROMPT_IDLE_TIMEOUT_MS / 1e3}s silent-from-start / ${PROMPT_ACTIVE_IDLE_TIMEOUT_MS / 1e3}s once active). Likely the underlying agent's auth or network is misconfigured; check the adapter stderr lines above (acpAdapter tag) for the actual error.`
|
|
37417
|
+
);
|
|
37418
|
+
},
|
|
37409
37419
|
PROMPT_ACTIVE_IDLE_TIMEOUT_MS
|
|
37410
37420
|
);
|
|
37411
37421
|
this.promptIdle = idle;
|
|
@@ -37425,12 +37435,41 @@ var AcpClient = class {
|
|
|
37425
37435
|
"acpClient",
|
|
37426
37436
|
`prompt \u2190 failed elapsedMs=${Date.now() - t0} err=${err instanceof Error ? err.message : String(err)}`
|
|
37427
37437
|
);
|
|
37438
|
+
if (idleTripped) await this.cancelAbandonedTurn(sessionId, send);
|
|
37428
37439
|
throw err;
|
|
37429
37440
|
} finally {
|
|
37430
37441
|
idle.clear();
|
|
37431
37442
|
this.promptIdle = null;
|
|
37432
37443
|
}
|
|
37433
37444
|
}
|
|
37445
|
+
/**
|
|
37446
|
+
* Cancel a turn the idle watchdog abandoned and wait, bounded, for the
|
|
37447
|
+
* adapter to answer its `session/prompt` — the proof the turn is over before
|
|
37448
|
+
* the next prompt is sent. Best-effort: a dead adapter can't hold the queue
|
|
37449
|
+
* longer than {@link ABANDONED_TURN_SETTLE_MS}.
|
|
37450
|
+
*/
|
|
37451
|
+
async cancelAbandonedTurn(sessionId, send) {
|
|
37452
|
+
try {
|
|
37453
|
+
await this.connection?.cancel({ sessionId });
|
|
37454
|
+
} catch (err) {
|
|
37455
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
37456
|
+
log.warn("acpClient", `cancel of abandoned turn failed: ${msg}`);
|
|
37457
|
+
return;
|
|
37458
|
+
}
|
|
37459
|
+
let timer;
|
|
37460
|
+
const settled = await Promise.race([
|
|
37461
|
+
send.then(
|
|
37462
|
+
() => true,
|
|
37463
|
+
() => true
|
|
37464
|
+
),
|
|
37465
|
+
new Promise((resolve13) => {
|
|
37466
|
+
timer = setTimeout(() => resolve13(false), ABANDONED_TURN_SETTLE_MS);
|
|
37467
|
+
timer.unref?.();
|
|
37468
|
+
})
|
|
37469
|
+
]);
|
|
37470
|
+
clearTimeout(timer);
|
|
37471
|
+
log.info("acpClient", `abandoned turn cancelled settled=${settled}`);
|
|
37472
|
+
}
|
|
37434
37473
|
/**
|
|
37435
37474
|
* True when a `session/prompt` rejection is the "the agent closed its ACP
|
|
37436
37475
|
* session between turns" fact — the kimi post-turn/idle close. Keyed on the
|
|
@@ -40626,6 +40665,27 @@ async function postCredentialSync(opts, fetchImpl = fetch) {
|
|
|
40626
40665
|
}
|
|
40627
40666
|
}
|
|
40628
40667
|
|
|
40668
|
+
// src/agents/acp/turn-queue.ts
|
|
40669
|
+
var TurnQueue = class {
|
|
40670
|
+
tail = Promise.resolve();
|
|
40671
|
+
active = 0;
|
|
40672
|
+
/** True while a turn runs or waits to run. */
|
|
40673
|
+
get busy() {
|
|
40674
|
+
return this.active > 0;
|
|
40675
|
+
}
|
|
40676
|
+
run(turn) {
|
|
40677
|
+
this.active += 1;
|
|
40678
|
+
const result = this.tail.then(turn).finally(() => {
|
|
40679
|
+
this.active -= 1;
|
|
40680
|
+
});
|
|
40681
|
+
this.tail = result.then(
|
|
40682
|
+
() => void 0,
|
|
40683
|
+
() => void 0
|
|
40684
|
+
);
|
|
40685
|
+
return result;
|
|
40686
|
+
}
|
|
40687
|
+
};
|
|
40688
|
+
|
|
40629
40689
|
// src/services/active-conversation-marker.ts
|
|
40630
40690
|
var import_node_crypto13 = require("crypto");
|
|
40631
40691
|
var import_promises6 = __toESM(require("fs/promises"));
|
|
@@ -43188,7 +43248,7 @@ function reportTurn2(ctx, phase, errorCode) {
|
|
|
43188
43248
|
});
|
|
43189
43249
|
}
|
|
43190
43250
|
async function startTaskH(ctx) {
|
|
43191
|
-
const { cmd, relay, streaming, opts
|
|
43251
|
+
const { cmd, relay, streaming, opts } = ctx;
|
|
43192
43252
|
const payload = cmd.payload;
|
|
43193
43253
|
reportTurn2(ctx, "received");
|
|
43194
43254
|
const requestedAgentId = typeof payload?.agentId === "string" ? payload.agentId.trim() : "";
|
|
@@ -43230,6 +43290,13 @@ async function startTaskH(ctx) {
|
|
|
43230
43290
|
if (echoLine.length > 0) {
|
|
43231
43291
|
showInfo(echoLine);
|
|
43232
43292
|
}
|
|
43293
|
+
if (streaming.turns.busy) {
|
|
43294
|
+
log.info("acpRunner", `start_task queued behind the running turn id=${cmd.id.slice(0, 8)}`);
|
|
43295
|
+
}
|
|
43296
|
+
await streaming.turns.run(() => runStartTaskTurn(ctx, payload, blocks, promptText));
|
|
43297
|
+
}
|
|
43298
|
+
async function runStartTaskTurn(ctx, payload, blocks, promptText) {
|
|
43299
|
+
const { cmd, relay, streaming, opts, turnFiles, publisher, recentStderr } = ctx;
|
|
43233
43300
|
await streaming.beginTurn();
|
|
43234
43301
|
ctx.history.appendUserPrompt(promptText);
|
|
43235
43302
|
maybePrefaceAgentStandard(blocks, opts.agent, opts.sessionId);
|
|
@@ -44123,6 +44190,8 @@ var StreamingState = class {
|
|
|
44123
44190
|
* kinds that key purely off the adapter id.
|
|
44124
44191
|
*/
|
|
44125
44192
|
turnSeq = 0;
|
|
44193
|
+
/** Runs this session's user turns one at a time (see {@link TurnQueue}). */
|
|
44194
|
+
turns = new TurnQueue();
|
|
44126
44195
|
chatTextPublishIntervalMs;
|
|
44127
44196
|
/**
|
|
44128
44197
|
* Register a permission Promise. The Promise stays pending until
|
|
@@ -51344,7 +51413,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
51344
51413
|
if (process.env.NODE_ENV === "test") return;
|
|
51345
51414
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51346
51415
|
if (process.env.CI) return;
|
|
51347
|
-
const current2 = true ? "2.76.
|
|
51416
|
+
const current2 = true ? "2.76.29" : null;
|
|
51348
51417
|
if (!current2) return;
|
|
51349
51418
|
const cache = readCache();
|
|
51350
51419
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51361,7 +51430,7 @@ function checkForUpdates() {
|
|
|
51361
51430
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51362
51431
|
if (process.env.CI) return;
|
|
51363
51432
|
if (!process.stdout.isTTY) return;
|
|
51364
|
-
const current2 = true ? "2.76.
|
|
51433
|
+
const current2 = true ? "2.76.29" : null;
|
|
51365
51434
|
if (!current2) return;
|
|
51366
51435
|
const cache = readCache();
|
|
51367
51436
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51644,7 +51713,7 @@ var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
|
51644
51713
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
51645
51714
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
51646
51715
|
function currentCliVersion() {
|
|
51647
|
-
return true ? "2.76.
|
|
51716
|
+
return true ? "2.76.29" : null;
|
|
51648
51717
|
}
|
|
51649
51718
|
async function installedVersion(deps) {
|
|
51650
51719
|
const ls = await deps.run(
|
|
@@ -51855,7 +51924,7 @@ function signalHostReady(send = process.send?.bind(process)) {
|
|
|
51855
51924
|
}
|
|
51856
51925
|
function defaultDeps() {
|
|
51857
51926
|
return {
|
|
51858
|
-
ownVersion: true ? "2.76.
|
|
51927
|
+
ownVersion: true ? "2.76.29" : null,
|
|
51859
51928
|
root: cliVersionsRoot(),
|
|
51860
51929
|
args: process.argv.slice(3),
|
|
51861
51930
|
execPath: process.execPath,
|
|
@@ -52149,8 +52218,12 @@ function isFleetPruneHostPayload(v) {
|
|
|
52149
52218
|
function isMissingVolumeError(stderr) {
|
|
52150
52219
|
return /no such volume/i.test(stderr);
|
|
52151
52220
|
}
|
|
52221
|
+
var FLEET_BOX_REPO = "ghcr.io/edgar-durand/codeam-box";
|
|
52222
|
+
var DOCKER_TAG_RE = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/;
|
|
52152
52223
|
function resolveFleetBoxImage() {
|
|
52153
|
-
|
|
52224
|
+
if (process.env.CODEAM_FLEET_BOX_IMAGE) return process.env.CODEAM_FLEET_BOX_IMAGE;
|
|
52225
|
+
const tag = process.env.CODEAM_FLEET_BOX_TAG?.trim();
|
|
52226
|
+
return `${FLEET_BOX_REPO}:${tag && DOCKER_TAG_RE.test(tag) ? tag : "latest"}`;
|
|
52154
52227
|
}
|
|
52155
52228
|
function buildFleetBoxMigrateArgs(p2) {
|
|
52156
52229
|
return buildFleetBoxRunArgs(p2).map((a) => a === "run" ? "create" : a).filter((a) => a !== "--pull=always" && a !== "-d");
|
|
@@ -54389,7 +54462,7 @@ function checkChokidar() {
|
|
|
54389
54462
|
}
|
|
54390
54463
|
async function doctor(args2 = []) {
|
|
54391
54464
|
const json = args2.includes("--json");
|
|
54392
|
-
const cliVersion = true ? "2.76.
|
|
54465
|
+
const cliVersion = true ? "2.76.29" : "0.0.0-dev";
|
|
54393
54466
|
const apiBase2 = resolveApiBaseUrl();
|
|
54394
54467
|
const diagnosticId = (0, import_node_crypto17.randomUUID)();
|
|
54395
54468
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -54925,7 +54998,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
54925
54998
|
// src/commands/version.ts
|
|
54926
54999
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
54927
55000
|
function version2() {
|
|
54928
|
-
const v = true ? "2.76.
|
|
55001
|
+
const v = true ? "2.76.29" : "unknown";
|
|
54929
55002
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
54930
55003
|
}
|
|
54931
55004
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.76.
|
|
3
|
+
"version": "2.76.29",
|
|
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",
|