codeam-cli 2.76.18 → 2.76.20
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 +101 -24
- 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.76.19] — 2026-10-09
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Send sessionId on turn-events so PluginAuthGuard stops 401ing them (#929)
|
|
12
|
+
|
|
13
|
+
## [2.76.18] — 2026-10-09
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **box:** Pull the node base image from mirror.gcr.io (Docker Hub 429) (#927)
|
|
18
|
+
|
|
7
19
|
## [2.76.17] — 2026-10-09
|
|
8
20
|
|
|
9
21
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -10617,7 +10617,7 @@ function readAnonId() {
|
|
|
10617
10617
|
}
|
|
10618
10618
|
function superProperties() {
|
|
10619
10619
|
return {
|
|
10620
|
-
cliVersion: true ? "2.76.
|
|
10620
|
+
cliVersion: true ? "2.76.20" : "0.0.0-dev",
|
|
10621
10621
|
nodeVersion: process.version,
|
|
10622
10622
|
platform: process.platform,
|
|
10623
10623
|
arch: process.arch,
|
|
@@ -10866,7 +10866,7 @@ var http = __toESM(require("http"));
|
|
|
10866
10866
|
// package.json
|
|
10867
10867
|
var package_default = {
|
|
10868
10868
|
name: "codeam-cli",
|
|
10869
|
-
version: "2.76.
|
|
10869
|
+
version: "2.76.20",
|
|
10870
10870
|
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.",
|
|
10871
10871
|
type: "commonjs",
|
|
10872
10872
|
main: "dist/index.js",
|
|
@@ -11246,6 +11246,7 @@ async function postTurnEvent(input) {
|
|
|
11246
11246
|
await _transport.postJsonAuthed(
|
|
11247
11247
|
`${API_BASE}/api/commands/turn-events`,
|
|
11248
11248
|
{
|
|
11249
|
+
sessionId: input.sessionId,
|
|
11249
11250
|
pluginId: input.pluginId,
|
|
11250
11251
|
commandId: input.commandId,
|
|
11251
11252
|
phase: input.phase,
|
|
@@ -12228,7 +12229,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
12228
12229
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
12229
12230
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
12230
12231
|
// pair/reconnect). Older backends ignore the extra field.
|
|
12231
|
-
..."2.76.
|
|
12232
|
+
..."2.76.20" ? { ideVersion: "2.76.20" } : {}
|
|
12232
12233
|
};
|
|
12233
12234
|
try {
|
|
12234
12235
|
const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body, this.pollSecretHeader());
|
|
@@ -28965,8 +28966,9 @@ var startTask = async (ctx, cmd, parsed) => {
|
|
|
28965
28966
|
reportTurn(ctx, cmd.id, "started");
|
|
28966
28967
|
};
|
|
28967
28968
|
function reportTurn(ctx, commandId, phase, errorCode) {
|
|
28968
|
-
if (!ctx.pluginId || !ctx.pluginAuthToken) return;
|
|
28969
|
+
if (!ctx.sessionId || !ctx.pluginId || !ctx.pluginAuthToken) return;
|
|
28969
28970
|
void postTurnEvent({
|
|
28971
|
+
sessionId: ctx.sessionId,
|
|
28970
28972
|
pluginId: ctx.pluginId,
|
|
28971
28973
|
pluginAuthToken: ctx.pluginAuthToken,
|
|
28972
28974
|
commandId,
|
|
@@ -38472,7 +38474,7 @@ var coderabbitProvisioner = {
|
|
|
38472
38474
|
return {};
|
|
38473
38475
|
}
|
|
38474
38476
|
};
|
|
38475
|
-
var
|
|
38477
|
+
var providerKeyProvisioner = {
|
|
38476
38478
|
write(auth) {
|
|
38477
38479
|
const key = auth.value.trim();
|
|
38478
38480
|
const envName = key.startsWith("sk-ant-") ? "ANTHROPIC_API_KEY" : key.startsWith("AIza") ? "GEMINI_API_KEY" : "OPENAI_API_KEY";
|
|
@@ -38486,7 +38488,11 @@ var PROVISIONERS = {
|
|
|
38486
38488
|
gemini: geminiProvisioner,
|
|
38487
38489
|
cursor: cursorProvisioner,
|
|
38488
38490
|
coderabbit: coderabbitProvisioner,
|
|
38489
|
-
opencode:
|
|
38491
|
+
opencode: providerKeyProvisioner,
|
|
38492
|
+
// ⚠️ Was missing: every self-hosted / fleet-Box aider deploy failed with
|
|
38493
|
+
// "Self-hosted provisioning is not implemented for agent "aider"" (23 in
|
|
38494
|
+
// prod Cloud Run, 2026-09-10..10-08).
|
|
38495
|
+
aider: providerKeyProvisioner
|
|
38490
38496
|
};
|
|
38491
38497
|
var UnsupportedAgentError = class extends Error {
|
|
38492
38498
|
agentId;
|
|
@@ -43058,8 +43064,9 @@ function recordCoderabbitTurn(ctx, prompt, replySummary) {
|
|
|
43058
43064
|
}
|
|
43059
43065
|
function reportTurn2(ctx, phase, errorCode) {
|
|
43060
43066
|
const { opts, cmd } = ctx;
|
|
43061
|
-
if (!opts.pluginId || !opts.pluginAuthToken) return;
|
|
43067
|
+
if (!opts.sessionId || !opts.pluginId || !opts.pluginAuthToken) return;
|
|
43062
43068
|
void postTurnEvent({
|
|
43069
|
+
sessionId: opts.sessionId,
|
|
43063
43070
|
pluginId: opts.pluginId,
|
|
43064
43071
|
pluginAuthToken: opts.pluginAuthToken,
|
|
43065
43072
|
commandId: cmd.id,
|
|
@@ -44482,12 +44489,14 @@ var AcpHistory = class {
|
|
|
44482
44489
|
*/
|
|
44483
44490
|
appendAgentReply(text, agentId = this.opts.agent) {
|
|
44484
44491
|
if (text.length === 0) return;
|
|
44492
|
+
const blocker = failureBlocker(text);
|
|
44485
44493
|
this.messages.push({
|
|
44486
44494
|
id: (0, import_node_crypto15.randomUUID)(),
|
|
44487
44495
|
role: "agent",
|
|
44488
44496
|
text,
|
|
44489
44497
|
timestamp: Date.now(),
|
|
44490
|
-
agentId
|
|
44498
|
+
agentId,
|
|
44499
|
+
...blocker ? { blocker } : {}
|
|
44491
44500
|
});
|
|
44492
44501
|
}
|
|
44493
44502
|
/**
|
|
@@ -51215,7 +51224,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
51215
51224
|
if (process.env.NODE_ENV === "test") return;
|
|
51216
51225
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51217
51226
|
if (process.env.CI) return;
|
|
51218
|
-
const current2 = true ? "2.76.
|
|
51227
|
+
const current2 = true ? "2.76.20" : null;
|
|
51219
51228
|
if (!current2) return;
|
|
51220
51229
|
const cache = readCache();
|
|
51221
51230
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51232,7 +51241,7 @@ function checkForUpdates() {
|
|
|
51232
51241
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
51233
51242
|
if (process.env.CI) return;
|
|
51234
51243
|
if (!process.stdout.isTTY) return;
|
|
51235
|
-
const current2 = true ? "2.76.
|
|
51244
|
+
const current2 = true ? "2.76.20" : null;
|
|
51236
51245
|
if (!current2) return;
|
|
51237
51246
|
const cache = readCache();
|
|
51238
51247
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -51514,7 +51523,7 @@ var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
|
51514
51523
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
51515
51524
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
51516
51525
|
function currentCliVersion() {
|
|
51517
|
-
return true ? "2.76.
|
|
51526
|
+
return true ? "2.76.20" : null;
|
|
51518
51527
|
}
|
|
51519
51528
|
async function installedVersion(deps) {
|
|
51520
51529
|
const ls = await deps.run(
|
|
@@ -51725,7 +51734,7 @@ function signalHostReady(send = process.send?.bind(process)) {
|
|
|
51725
51734
|
}
|
|
51726
51735
|
function defaultDeps() {
|
|
51727
51736
|
return {
|
|
51728
|
-
ownVersion: true ? "2.76.
|
|
51737
|
+
ownVersion: true ? "2.76.20" : null,
|
|
51729
51738
|
root: cliVersionsRoot(),
|
|
51730
51739
|
args: process.argv.slice(3),
|
|
51731
51740
|
execPath: process.execPath,
|
|
@@ -52304,6 +52313,15 @@ var HostAgentSupervisor = class {
|
|
|
52304
52313
|
* one session's crash-loop must not spend another's retry budget).
|
|
52305
52314
|
*/
|
|
52306
52315
|
resumeStates = /* @__PURE__ */ new Map();
|
|
52316
|
+
/**
|
|
52317
|
+
* Env-delivered agent credentials per deploy (the `api_key` path:
|
|
52318
|
+
* ANTHROPIC_API_KEY / GEMINI_API_KEY / CURSOR_API_KEY / OPENAI_API_KEY).
|
|
52319
|
+
* Such a key lives ONLY in the child's spawn env — nothing on disk carries
|
|
52320
|
+
* it — so every re-spawn of the session (crash respawn, resume, a re-link
|
|
52321
|
+
* restart) must re-inject it. Memory only: credential plaintext is never
|
|
52322
|
+
* persisted by the host-agent (codeagent-5m12).
|
|
52323
|
+
*/
|
|
52324
|
+
credentialEnvByDeploy = /* @__PURE__ */ new Map();
|
|
52307
52325
|
/** Set once the bounded retries exhaust → heartbeat-ridden slow re-probe. */
|
|
52308
52326
|
/** True after stop() — no resume retries may be scheduled past teardown. */
|
|
52309
52327
|
stopped = false;
|
|
@@ -52824,6 +52842,7 @@ var HostAgentSupervisor = class {
|
|
|
52824
52842
|
async fleetMigrateBoxImage(payload) {
|
|
52825
52843
|
const { containerName } = payload;
|
|
52826
52844
|
const state = await this.docker.run([
|
|
52845
|
+
"container",
|
|
52827
52846
|
"inspect",
|
|
52828
52847
|
"--format",
|
|
52829
52848
|
"{{.State.Running}}",
|
|
@@ -52936,7 +52955,13 @@ var HostAgentSupervisor = class {
|
|
|
52936
52955
|
async fleetBoxImageStale(containerName) {
|
|
52937
52956
|
if (process.env.CODEAM_FLEET_BOX_IMAGE) return false;
|
|
52938
52957
|
const image = resolveFleetBoxImage();
|
|
52939
|
-
const cur = await this.docker.run([
|
|
52958
|
+
const cur = await this.docker.run([
|
|
52959
|
+
"container",
|
|
52960
|
+
"inspect",
|
|
52961
|
+
"--format",
|
|
52962
|
+
"{{.Image}}",
|
|
52963
|
+
containerName
|
|
52964
|
+
]);
|
|
52940
52965
|
if (cur.code !== 0) {
|
|
52941
52966
|
return isMissingContainerError(cur.stderr);
|
|
52942
52967
|
}
|
|
@@ -53213,6 +53238,8 @@ var HostAgentSupervisor = class {
|
|
|
53213
53238
|
} else {
|
|
53214
53239
|
const auth = await this.resolveAgentAuth(this.identity, payload.sealedAgentAuth);
|
|
53215
53240
|
const credEnv = provisionAgentCredentials(payload.agentId, auth, void 0);
|
|
53241
|
+
if (Object.keys(credEnv).length > 0) this.credentialEnvByDeploy.set(payload.deployId, credEnv);
|
|
53242
|
+
else this.credentialEnvByDeploy.delete(payload.deployId);
|
|
53216
53243
|
childEnv = {
|
|
53217
53244
|
...credEnv,
|
|
53218
53245
|
CODEAM_AUTO_TOKEN: payload.autoPairToken
|
|
@@ -53610,7 +53637,11 @@ var HostAgentSupervisor = class {
|
|
|
53610
53637
|
`resume: session ${session.id.slice(0, 8)} deploy=${deployId.slice(0, 8)} cwd=${cwd}`
|
|
53611
53638
|
);
|
|
53612
53639
|
const proc = this.resumeSpawner(
|
|
53613
|
-
{
|
|
53640
|
+
{
|
|
53641
|
+
...readHouseProxyChildEnv(deployId),
|
|
53642
|
+
...this.credentialEnvByDeploy.get(deployId) ?? {},
|
|
53643
|
+
CODEAM_RESUME_SESSION_ID: session.id
|
|
53644
|
+
},
|
|
53614
53645
|
cwd
|
|
53615
53646
|
);
|
|
53616
53647
|
const child = {
|
|
@@ -53818,6 +53849,7 @@ var HostAgentSupervisor = class {
|
|
|
53818
53849
|
*/
|
|
53819
53850
|
cleanupWorkspace(deployId) {
|
|
53820
53851
|
const short = deployId.slice(0, 8);
|
|
53852
|
+
this.credentialEnvByDeploy.delete(deployId);
|
|
53821
53853
|
const child = this.children.get(deployId);
|
|
53822
53854
|
if (child) {
|
|
53823
53855
|
try {
|
|
@@ -53844,20 +53876,43 @@ var HostAgentSupervisor = class {
|
|
|
53844
53876
|
}
|
|
53845
53877
|
/**
|
|
53846
53878
|
* Handle `self_hosted_refresh_credentials` (the user re-linked the agent).
|
|
53847
|
-
* Unseal the fresh credential and re-provision the agent's
|
|
53848
|
-
*
|
|
53849
|
-
*
|
|
53850
|
-
*
|
|
53851
|
-
*
|
|
53852
|
-
*
|
|
53879
|
+
* Unseal the fresh credential and re-provision the agent's auth IN PLACE.
|
|
53880
|
+
*
|
|
53881
|
+
* Two delivery shapes, two outcomes (codeagent-5m12):
|
|
53882
|
+
* - **Login-state FILE** (`oauth_token`; `provisionAgentCredentials`
|
|
53883
|
+
* returns `{}`): the file is rewritten and running children are left
|
|
53884
|
+
* alone. Claude Code and Codex re-read their auth file on a 401 (Claude's
|
|
53885
|
+
* `oauth_401_recovered_from_disk`, Codex's `UnauthorizedRecovery` Reload
|
|
53886
|
+
* step), so a 401'd session recovers without losing its turn.
|
|
53887
|
+
* - **Env var** (`api_key`; it returns e.g. `{ ANTHROPIC_API_KEY }`): the
|
|
53888
|
+
* key exists only in each child's spawn env, which a rewrite cannot reach
|
|
53889
|
+
* — the old key keeps 401ing until the process is replaced. Every running
|
|
53890
|
+
* child of THIS agent is restarted through the resume path with the new
|
|
53891
|
+
* env (same conversation, `CODEAM_RESUME_SESSION_ID`).
|
|
53892
|
+
*
|
|
53893
|
+
* Best-effort: a failure is logged, never throws (the relay dispatch must
|
|
53894
|
+
* not crash).
|
|
53853
53895
|
*/
|
|
53854
53896
|
async refreshCredentials(payload) {
|
|
53855
53897
|
try {
|
|
53856
53898
|
const auth = await this.resolveAgentAuth(this.identity, payload.sealedAgentAuth);
|
|
53857
|
-
provisionAgentCredentials(payload.agentId, auth, void 0);
|
|
53899
|
+
const credEnv = provisionAgentCredentials(payload.agentId, auth, void 0);
|
|
53900
|
+
const affected = [...this.children.values()].filter((c2) => c2.agent === payload.agentId);
|
|
53901
|
+
if (Object.keys(credEnv).length === 0) {
|
|
53902
|
+
for (const c2 of affected) this.credentialEnvByDeploy.delete(c2.deployId);
|
|
53903
|
+
log.info(
|
|
53904
|
+
"host-agent",
|
|
53905
|
+
`refreshed credentials in place for agent=${payload.agentId} (${this.children.size} active child(ren))`
|
|
53906
|
+
);
|
|
53907
|
+
return;
|
|
53908
|
+
}
|
|
53909
|
+
for (const child of affected) {
|
|
53910
|
+
this.credentialEnvByDeploy.set(child.deployId, credEnv);
|
|
53911
|
+
this.restartWithFreshCredentials(child);
|
|
53912
|
+
}
|
|
53858
53913
|
log.info(
|
|
53859
53914
|
"host-agent",
|
|
53860
|
-
`refreshed
|
|
53915
|
+
`refreshed env credential for agent=${payload.agentId}; restarted ${affected.length} child(ren)`
|
|
53861
53916
|
);
|
|
53862
53917
|
} catch (err) {
|
|
53863
53918
|
log.warn(
|
|
@@ -53866,6 +53921,28 @@ var HostAgentSupervisor = class {
|
|
|
53866
53921
|
);
|
|
53867
53922
|
}
|
|
53868
53923
|
}
|
|
53924
|
+
/**
|
|
53925
|
+
* Replace one session child so it picks up a re-linked env credential.
|
|
53926
|
+
* Kill THEN untrack (an intentional stop, so its exit handler neither
|
|
53927
|
+
* reports `ended` nor crash-respawns), then resume the same conversation;
|
|
53928
|
+
* `resumeOne` waits out the dying daemon if it still holds the session.
|
|
53929
|
+
*/
|
|
53930
|
+
restartWithFreshCredentials(child) {
|
|
53931
|
+
const session = pickSavedSessionForWorkspace(this.listSavedSessions(), child.cwd, child.deployId);
|
|
53932
|
+
if (!session) {
|
|
53933
|
+
log.warn(
|
|
53934
|
+
"host-agent",
|
|
53935
|
+
`credential refresh: no saved pairing for deploy=${child.deployId.slice(0, 8)} \u2014 it keeps the old key until its next restart`
|
|
53936
|
+
);
|
|
53937
|
+
return;
|
|
53938
|
+
}
|
|
53939
|
+
try {
|
|
53940
|
+
child.proc.kill("SIGTERM");
|
|
53941
|
+
} catch {
|
|
53942
|
+
}
|
|
53943
|
+
this.untrackChild(child.deployId);
|
|
53944
|
+
this.resumeOne({ deployId: child.deployId, cwd: child.cwd, session, agent: child.agent });
|
|
53945
|
+
}
|
|
53869
53946
|
};
|
|
53870
53947
|
async function resolveHostIdentity(enrollToken) {
|
|
53871
53948
|
const existing = ensureControlPollSecret(loadHostIdentity());
|
|
@@ -54168,7 +54245,7 @@ function checkChokidar() {
|
|
|
54168
54245
|
}
|
|
54169
54246
|
async function doctor(args2 = []) {
|
|
54170
54247
|
const json = args2.includes("--json");
|
|
54171
|
-
const cliVersion = true ? "2.76.
|
|
54248
|
+
const cliVersion = true ? "2.76.20" : "0.0.0-dev";
|
|
54172
54249
|
const apiBase2 = resolveApiBaseUrl();
|
|
54173
54250
|
const diagnosticId = (0, import_node_crypto17.randomUUID)();
|
|
54174
54251
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -54704,7 +54781,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
54704
54781
|
// src/commands/version.ts
|
|
54705
54782
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
54706
54783
|
function version2() {
|
|
54707
|
-
const v = true ? "2.76.
|
|
54784
|
+
const v = true ? "2.76.20" : "unknown";
|
|
54708
54785
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
54709
54786
|
}
|
|
54710
54787
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.76.
|
|
3
|
+
"version": "2.76.20",
|
|
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",
|