codeam-cli 2.60.5 → 2.60.7
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 +20 -0
- package/dist/index.js +75 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,26 @@ 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.60.6] — 2026-07-08
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Serialize ACP prompts so a 2nd in-flight turn can't clobber the watchdog
|
|
12
|
+
|
|
13
|
+
## [2.60.5] — 2026-07-08
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **cli:** Baton support for cursor + gate to agents with a resumable transcript
|
|
18
|
+
|
|
19
|
+
### Documentation
|
|
20
|
+
|
|
21
|
+
- **cli:** Document the Session Baton (native TUI <-> mobile ACP) architecture + hand-off invariants
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **cli:** Serialize baton state POSTs so handback never sticks on "Switching…"
|
|
26
|
+
|
|
7
27
|
## [2.60.4] — 2026-07-08
|
|
8
28
|
|
|
9
29
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -5653,7 +5653,7 @@ function readAnonId() {
|
|
|
5653
5653
|
}
|
|
5654
5654
|
function superProperties() {
|
|
5655
5655
|
return {
|
|
5656
|
-
cliVersion: true ? "2.60.
|
|
5656
|
+
cliVersion: true ? "2.60.7" : "0.0.0-dev",
|
|
5657
5657
|
nodeVersion: process.version,
|
|
5658
5658
|
platform: process.platform,
|
|
5659
5659
|
arch: process.arch,
|
|
@@ -5834,7 +5834,7 @@ var os4 = __toESM(require("os"));
|
|
|
5834
5834
|
// package.json
|
|
5835
5835
|
var package_default = {
|
|
5836
5836
|
name: "codeam-cli",
|
|
5837
|
-
version: "2.60.
|
|
5837
|
+
version: "2.60.7",
|
|
5838
5838
|
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.",
|
|
5839
5839
|
type: "commonjs",
|
|
5840
5840
|
main: "dist/index.js",
|
|
@@ -6905,7 +6905,7 @@ var CommandRelayService = class {
|
|
|
6905
6905
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
6906
6906
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
6907
6907
|
// pair/reconnect). Older backends ignore the extra field.
|
|
6908
|
-
..."2.60.
|
|
6908
|
+
..."2.60.7" ? { ideVersion: "2.60.7" } : {}
|
|
6909
6909
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
6910
6910
|
}
|
|
6911
6911
|
/**
|
|
@@ -15986,7 +15986,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
15986
15986
|
if (process.env.NODE_ENV === "test") return;
|
|
15987
15987
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
15988
15988
|
if (process.env.CI) return;
|
|
15989
|
-
const current = true ? "2.60.
|
|
15989
|
+
const current = true ? "2.60.7" : null;
|
|
15990
15990
|
if (!current) return;
|
|
15991
15991
|
const cache = readCache();
|
|
15992
15992
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -16003,7 +16003,7 @@ function checkForUpdates() {
|
|
|
16003
16003
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
16004
16004
|
if (process.env.CI) return;
|
|
16005
16005
|
if (!process.stdout.isTTY) return;
|
|
16006
|
-
const current = true ? "2.60.
|
|
16006
|
+
const current = true ? "2.60.7" : null;
|
|
16007
16007
|
if (!current) return;
|
|
16008
16008
|
const cache = readCache();
|
|
16009
16009
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -16023,7 +16023,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
|
16023
16023
|
var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
16024
16024
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
16025
16025
|
function currentCliVersion() {
|
|
16026
|
-
return true ? "2.60.
|
|
16026
|
+
return true ? "2.60.7" : null;
|
|
16027
16027
|
}
|
|
16028
16028
|
function runCmd(cmd, args2, timeoutMs) {
|
|
16029
16029
|
return new Promise((resolve7) => {
|
|
@@ -24850,6 +24850,11 @@ function createIdleTimeout(idleMs, makeError) {
|
|
|
24850
24850
|
}
|
|
24851
24851
|
|
|
24852
24852
|
// src/agents/acp/client.ts
|
|
24853
|
+
var TRANSIENT_ADAPTER_SPAWN_RE = /ETXTBSY|ENOENT/;
|
|
24854
|
+
var MAX_START_ATTEMPTS = 5;
|
|
24855
|
+
var _acpStartSeam = {
|
|
24856
|
+
sleep: (ms) => new Promise((r) => setTimeout(r, ms))
|
|
24857
|
+
};
|
|
24853
24858
|
var PROTOCOL_VERSION2 = 1;
|
|
24854
24859
|
var FATAL_STARTUP_RE = /IneligibleTierError|UNSUPPORTED_CLIENT|no longer supported for Gemini Code Assist|not eligible for Gemini Code Assist|Error authenticating|ProjectIdRequiredError/i;
|
|
24855
24860
|
var NEWSESSION_TIMEOUT_MS = 12e4;
|
|
@@ -24880,6 +24885,12 @@ var AcpClient = class {
|
|
|
24880
24885
|
* (the agent is demonstrably working, just blocked on the tool), and
|
|
24881
24886
|
* re-arm only once the last one finishes. Reset per prompt. */
|
|
24882
24887
|
pendingToolCalls = /* @__PURE__ */ new Set();
|
|
24888
|
+
/** Serializes {@link prompt}: each turn waits for the previous to fully
|
|
24889
|
+
* settle before arming its own watchdog. `promptIdle`/`pendingToolCalls`
|
|
24890
|
+
* are single-instance fields, so a 2nd concurrent prompt() would overwrite
|
|
24891
|
+
* them mid-turn and break turn A's idle watchdog (mobile "send-while-active"
|
|
24892
|
+
* can fire two prompts back-to-back). See {@link prompt}. */
|
|
24893
|
+
promptChain = Promise.resolve();
|
|
24883
24894
|
/** Last few adapter stderr lines — so a startup failure surfaces the REAL
|
|
24884
24895
|
* cause (e.g. gemini's `IneligibleTierError`) instead of a bare timeout. */
|
|
24885
24896
|
recentStderr = [];
|
|
@@ -24889,15 +24900,57 @@ var AcpClient = class {
|
|
|
24889
24900
|
* so without this the session hangs forever ("loading… / offline"). */
|
|
24890
24901
|
startupFailureReject = null;
|
|
24891
24902
|
/**
|
|
24892
|
-
* Spawn the adapter +
|
|
24893
|
-
*
|
|
24894
|
-
*
|
|
24895
|
-
*
|
|
24896
|
-
*
|
|
24897
|
-
*
|
|
24903
|
+
* Spawn the adapter + handshake, retrying a TRANSIENT in-adapter spawn race.
|
|
24904
|
+
*
|
|
24905
|
+
* The adapter itself execs the real agent binary (claude-agent-acp spawns the
|
|
24906
|
+
* ~250MB SDK-bundled `claude` during newSession). On a fresh/waking codespace
|
|
24907
|
+
* that binary is momentarily open-for-write → the adapter rejects newSession
|
|
24908
|
+
* with `-32603 … spawn ETXTBSY` (or ENOENT before it lands). Both clear within
|
|
24909
|
+
* ms, so we respawn the adapter + re-handshake up to {@link MAX_START_ATTEMPTS}
|
|
24910
|
+
* times. `startOnce` fully cleans up on failure (see cleanupAfterFailedStart),
|
|
24911
|
+
* so each retry starts from a clean slate. Non-transient failures throw on the
|
|
24912
|
+
* first attempt — no masking of real auth/outage errors.
|
|
24898
24913
|
*/
|
|
24899
24914
|
async start() {
|
|
24915
|
+
let lastErr;
|
|
24916
|
+
for (let attempt = 1; attempt <= MAX_START_ATTEMPTS; attempt += 1) {
|
|
24917
|
+
try {
|
|
24918
|
+
return await this.startOnce();
|
|
24919
|
+
} catch (err) {
|
|
24920
|
+
lastErr = err;
|
|
24921
|
+
if (attempt < MAX_START_ATTEMPTS && this.isTransientAdapterSpawn(err)) {
|
|
24922
|
+
log.info(
|
|
24923
|
+
"acpClient",
|
|
24924
|
+
`adapter hit a transient spawn race (binary busy) \u2014 retrying start ${attempt + 1}/${MAX_START_ATTEMPTS}`
|
|
24925
|
+
);
|
|
24926
|
+
await _acpStartSeam.sleep(400 * attempt);
|
|
24927
|
+
continue;
|
|
24928
|
+
}
|
|
24929
|
+
throw err;
|
|
24930
|
+
}
|
|
24931
|
+
}
|
|
24932
|
+
throw lastErr;
|
|
24933
|
+
}
|
|
24934
|
+
/** True when a failed {@link startOnce} was caused by the adapter's OWN
|
|
24935
|
+
* transient spawn of the agent binary (ETXTBSY/ENOENT). Checks the thrown
|
|
24936
|
+
* error's message/data AND the adapter stderr ring — the adapter logs the
|
|
24937
|
+
* real cause to stderr while returning a generic `-32603 Internal error`. */
|
|
24938
|
+
isTransientAdapterSpawn(err) {
|
|
24939
|
+
const parts = [...this.recentStderr];
|
|
24940
|
+
if (err instanceof Error) parts.push(err.message);
|
|
24941
|
+
if (err && typeof err === "object") {
|
|
24942
|
+
const e = err;
|
|
24943
|
+
try {
|
|
24944
|
+
parts.push(JSON.stringify(e.data));
|
|
24945
|
+
} catch {
|
|
24946
|
+
}
|
|
24947
|
+
if (typeof e.details === "string") parts.push(e.details);
|
|
24948
|
+
}
|
|
24949
|
+
return TRANSIENT_ADAPTER_SPAWN_RE.test(parts.join(" "));
|
|
24950
|
+
}
|
|
24951
|
+
async startOnce() {
|
|
24900
24952
|
if (this.child) throw new Error("AcpClient already started");
|
|
24953
|
+
this.recentStderr.length = 0;
|
|
24901
24954
|
const { adapter, cwd } = this.opts;
|
|
24902
24955
|
const augmentedPath = expandPathForAgentBinaries(process.env.PATH ?? "");
|
|
24903
24956
|
log.info(
|
|
@@ -25034,6 +25087,14 @@ var AcpClient = class {
|
|
|
25034
25087
|
* shows a permanent "Thinking…" spinner with no way to recover.
|
|
25035
25088
|
*/
|
|
25036
25089
|
async prompt(input) {
|
|
25090
|
+
const run = this.promptChain.then(() => this.runPrompt(input));
|
|
25091
|
+
this.promptChain = run.then(
|
|
25092
|
+
() => void 0,
|
|
25093
|
+
() => void 0
|
|
25094
|
+
);
|
|
25095
|
+
return run;
|
|
25096
|
+
}
|
|
25097
|
+
async runPrompt(input) {
|
|
25037
25098
|
if (!this.connection || !this.sessionId) {
|
|
25038
25099
|
throw new Error("AcpClient.prompt called before start()");
|
|
25039
25100
|
}
|
|
@@ -32741,7 +32802,7 @@ function checkChokidar() {
|
|
|
32741
32802
|
}
|
|
32742
32803
|
async function doctor(args2 = []) {
|
|
32743
32804
|
const json = args2.includes("--json");
|
|
32744
|
-
const cliVersion = true ? "2.60.
|
|
32805
|
+
const cliVersion = true ? "2.60.7" : "0.0.0-dev";
|
|
32745
32806
|
const apiBase2 = resolveApiBaseUrl();
|
|
32746
32807
|
const diagnosticId = (0, import_node_crypto9.randomUUID)();
|
|
32747
32808
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -32940,7 +33001,7 @@ async function completion(args2) {
|
|
|
32940
33001
|
// src/commands/version.ts
|
|
32941
33002
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
32942
33003
|
function version2() {
|
|
32943
|
-
const v = true ? "2.60.
|
|
33004
|
+
const v = true ? "2.60.7" : "unknown";
|
|
32944
33005
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
32945
33006
|
}
|
|
32946
33007
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.60.
|
|
3
|
+
"version": "2.60.7",
|
|
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",
|