codeam-cli 2.76.19 → 2.76.21

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 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.76.20] — 2026-10-10
8
+
9
+ ### Added
10
+
11
+ - **shared:** Own the Composer, feature-gate and compression-savings wire types (#934)
12
+
13
+ ### Fixed
14
+
15
+ - **cli:** Wake recreates a fleet box whose container is gone but volume remains (#933)
16
+ - **cli:** Provision aider credentials on self-hosted and Box deploys (#935)
17
+ - **both-plugins:** Open the command SSE on the stream host, not apiBaseUrl (#936)
18
+ - **cli:** Keep the typed blocker tag on failure bubbles in pushed history (#937)
19
+ - **cli:** Point USERPROFILE at the tmp home in the re-link credential test (#938)
20
+
21
+ ## [2.76.19] — 2026-10-09
22
+
23
+ ### Fixed
24
+
25
+ - **cli:** Send sessionId on turn-events so PluginAuthGuard stops 401ing them (#929)
26
+
7
27
  ## [2.76.18] — 2026-10-09
8
28
 
9
29
  ### Fixed
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.19" : "0.0.0-dev",
10620
+ cliVersion: true ? "2.76.21" : "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.19",
10869
+ version: "2.76.21",
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",
@@ -12229,7 +12229,7 @@ var CommandRelayService = class _CommandRelayService {
12229
12229
  // fresh + clear the "CLI update available" banner after a self-update
12230
12230
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
12231
12231
  // pair/reconnect). Older backends ignore the extra field.
12232
- ..."2.76.19" ? { ideVersion: "2.76.19" } : {}
12232
+ ..."2.76.21" ? { ideVersion: "2.76.21" } : {}
12233
12233
  };
12234
12234
  try {
12235
12235
  const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body, this.pollSecretHeader());
@@ -38474,7 +38474,7 @@ var coderabbitProvisioner = {
38474
38474
  return {};
38475
38475
  }
38476
38476
  };
38477
- var opencodeProvisioner = {
38477
+ var providerKeyProvisioner = {
38478
38478
  write(auth) {
38479
38479
  const key = auth.value.trim();
38480
38480
  const envName = key.startsWith("sk-ant-") ? "ANTHROPIC_API_KEY" : key.startsWith("AIza") ? "GEMINI_API_KEY" : "OPENAI_API_KEY";
@@ -38488,7 +38488,11 @@ var PROVISIONERS = {
38488
38488
  gemini: geminiProvisioner,
38489
38489
  cursor: cursorProvisioner,
38490
38490
  coderabbit: coderabbitProvisioner,
38491
- opencode: opencodeProvisioner
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
38492
38496
  };
38493
38497
  var UnsupportedAgentError = class extends Error {
38494
38498
  agentId;
@@ -44485,12 +44489,14 @@ var AcpHistory = class {
44485
44489
  */
44486
44490
  appendAgentReply(text, agentId = this.opts.agent) {
44487
44491
  if (text.length === 0) return;
44492
+ const blocker = failureBlocker(text);
44488
44493
  this.messages.push({
44489
44494
  id: (0, import_node_crypto15.randomUUID)(),
44490
44495
  role: "agent",
44491
44496
  text,
44492
44497
  timestamp: Date.now(),
44493
- agentId
44498
+ agentId,
44499
+ ...blocker ? { blocker } : {}
44494
44500
  });
44495
44501
  }
44496
44502
  /**
@@ -46376,7 +46382,7 @@ function sanitizeRetiredProxyConfig(homeDir2 = os62.homedir()) {
46376
46382
  // src/integrations/refresh-manifest.ts
46377
46383
  function fingerprint(m) {
46378
46384
  const norm = [...m.integrations].map((e) => ({ id: e.id, delivery: e.delivery })).sort((a, b) => a.id.localeCompare(b.id));
46379
- return JSON.stringify(norm);
46385
+ return JSON.stringify({ integrations: norm, toolRouter: m.toolRouter === true });
46380
46386
  }
46381
46387
  async function refreshIntegrationsManifest(ctx, fetchImpl = fetch, timeoutMs = 8e3) {
46382
46388
  const result = await fetchAndPersist(ctx, fetchImpl, timeoutMs);
@@ -51218,7 +51224,7 @@ async function autoUpgradeBeforeCriticalCommand() {
51218
51224
  if (process.env.NODE_ENV === "test") return;
51219
51225
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
51220
51226
  if (process.env.CI) return;
51221
- const current2 = true ? "2.76.19" : null;
51227
+ const current2 = true ? "2.76.21" : null;
51222
51228
  if (!current2) return;
51223
51229
  const cache = readCache();
51224
51230
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -51235,7 +51241,7 @@ function checkForUpdates() {
51235
51241
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
51236
51242
  if (process.env.CI) return;
51237
51243
  if (!process.stdout.isTTY) return;
51238
- const current2 = true ? "2.76.19" : null;
51244
+ const current2 = true ? "2.76.21" : null;
51239
51245
  if (!current2) return;
51240
51246
  const cache = readCache();
51241
51247
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -51517,7 +51523,7 @@ var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
51517
51523
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
51518
51524
  var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
51519
51525
  function currentCliVersion() {
51520
- return true ? "2.76.19" : null;
51526
+ return true ? "2.76.21" : null;
51521
51527
  }
51522
51528
  async function installedVersion(deps) {
51523
51529
  const ls = await deps.run(
@@ -51728,7 +51734,7 @@ function signalHostReady(send = process.send?.bind(process)) {
51728
51734
  }
51729
51735
  function defaultDeps() {
51730
51736
  return {
51731
- ownVersion: true ? "2.76.19" : null,
51737
+ ownVersion: true ? "2.76.21" : null,
51732
51738
  root: cliVersionsRoot(),
51733
51739
  args: process.argv.slice(3),
51734
51740
  execPath: process.execPath,
@@ -52307,6 +52313,15 @@ var HostAgentSupervisor = class {
52307
52313
  * one session's crash-loop must not spend another's retry budget).
52308
52314
  */
52309
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();
52310
52325
  /** Set once the bounded retries exhaust → heartbeat-ridden slow re-probe. */
52311
52326
  /** True after stop() — no resume retries may be scheduled past teardown. */
52312
52327
  stopped = false;
@@ -52827,6 +52842,7 @@ var HostAgentSupervisor = class {
52827
52842
  async fleetMigrateBoxImage(payload) {
52828
52843
  const { containerName } = payload;
52829
52844
  const state = await this.docker.run([
52845
+ "container",
52830
52846
  "inspect",
52831
52847
  "--format",
52832
52848
  "{{.State.Running}}",
@@ -52939,7 +52955,13 @@ var HostAgentSupervisor = class {
52939
52955
  async fleetBoxImageStale(containerName) {
52940
52956
  if (process.env.CODEAM_FLEET_BOX_IMAGE) return false;
52941
52957
  const image = resolveFleetBoxImage();
52942
- const cur = await this.docker.run(["inspect", "--format", "{{.Image}}", containerName]);
52958
+ const cur = await this.docker.run([
52959
+ "container",
52960
+ "inspect",
52961
+ "--format",
52962
+ "{{.Image}}",
52963
+ containerName
52964
+ ]);
52943
52965
  if (cur.code !== 0) {
52944
52966
  return isMissingContainerError(cur.stderr);
52945
52967
  }
@@ -53216,6 +53238,8 @@ var HostAgentSupervisor = class {
53216
53238
  } else {
53217
53239
  const auth = await this.resolveAgentAuth(this.identity, payload.sealedAgentAuth);
53218
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);
53219
53243
  childEnv = {
53220
53244
  ...credEnv,
53221
53245
  CODEAM_AUTO_TOKEN: payload.autoPairToken
@@ -53613,7 +53637,11 @@ var HostAgentSupervisor = class {
53613
53637
  `resume: session ${session.id.slice(0, 8)} deploy=${deployId.slice(0, 8)} cwd=${cwd}`
53614
53638
  );
53615
53639
  const proc = this.resumeSpawner(
53616
- { ...readHouseProxyChildEnv(deployId), CODEAM_RESUME_SESSION_ID: session.id },
53640
+ {
53641
+ ...readHouseProxyChildEnv(deployId),
53642
+ ...this.credentialEnvByDeploy.get(deployId) ?? {},
53643
+ CODEAM_RESUME_SESSION_ID: session.id
53644
+ },
53617
53645
  cwd
53618
53646
  );
53619
53647
  const child = {
@@ -53821,6 +53849,7 @@ var HostAgentSupervisor = class {
53821
53849
  */
53822
53850
  cleanupWorkspace(deployId) {
53823
53851
  const short = deployId.slice(0, 8);
53852
+ this.credentialEnvByDeploy.delete(deployId);
53824
53853
  const child = this.children.get(deployId);
53825
53854
  if (child) {
53826
53855
  try {
@@ -53847,20 +53876,43 @@ var HostAgentSupervisor = class {
53847
53876
  }
53848
53877
  /**
53849
53878
  * Handle `self_hosted_refresh_credentials` (the user re-linked the agent).
53850
- * Unseal the fresh credential and re-provision the agent's on-disk auth IN
53851
- * PLACE (`provisionAgentCredentials` rewrites `~/.claude/.credentials.json`
53852
- * etc.). The running pair-auto child re-reads its auth file on the next API
53853
- * call, so a 401'd session recovers WITHOUT a restart — the self-hosted
53854
- * parallel to the codespace `refreshAgentCredentialsOnly` sweep. Best-effort:
53855
- * a failure is logged, never throws (the relay dispatch must not crash).
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).
53856
53895
  */
53857
53896
  async refreshCredentials(payload) {
53858
53897
  try {
53859
53898
  const auth = await this.resolveAgentAuth(this.identity, payload.sealedAgentAuth);
53860
- 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
+ }
53861
53913
  log.info(
53862
53914
  "host-agent",
53863
- `refreshed credentials in place for agent=${payload.agentId} (${this.children.size} active child(ren))`
53915
+ `refreshed env credential for agent=${payload.agentId}; restarted ${affected.length} child(ren)`
53864
53916
  );
53865
53917
  } catch (err) {
53866
53918
  log.warn(
@@ -53869,6 +53921,28 @@ var HostAgentSupervisor = class {
53869
53921
  );
53870
53922
  }
53871
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
+ }
53872
53946
  };
53873
53947
  async function resolveHostIdentity(enrollToken) {
53874
53948
  const existing = ensureControlPollSecret(loadHostIdentity());
@@ -54171,7 +54245,7 @@ function checkChokidar() {
54171
54245
  }
54172
54246
  async function doctor(args2 = []) {
54173
54247
  const json = args2.includes("--json");
54174
- const cliVersion = true ? "2.76.19" : "0.0.0-dev";
54248
+ const cliVersion = true ? "2.76.21" : "0.0.0-dev";
54175
54249
  const apiBase2 = resolveApiBaseUrl();
54176
54250
  const diagnosticId = (0, import_node_crypto17.randomUUID)();
54177
54251
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -54707,7 +54781,7 @@ async function mcpWarm(argv = [], opts = {}) {
54707
54781
  // src/commands/version.ts
54708
54782
  var import_picocolors15 = __toESM(require("picocolors"));
54709
54783
  function version2() {
54710
- const v = true ? "2.76.19" : "unknown";
54784
+ const v = true ? "2.76.21" : "unknown";
54711
54785
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
54712
54786
  }
54713
54787
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.76.19",
3
+ "version": "2.76.21",
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",