codeam-cli 2.61.94 → 2.61.96

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,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.61.95] — 2026-08-08
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Re-assert full-auto mode on Agent Packs fresh conversations (#605)
12
+
13
+ ## [2.61.94] — 2026-08-08
14
+
15
+ ### Fixed
16
+
17
+ - **cli:** Harden Headroom proxy against resume death — accurate liveness + proactive boot relaunch (#604)
18
+
7
19
  ## [2.61.93] — 2026-08-08
8
20
 
9
21
  ### Fixed
package/dist/index.js CHANGED
@@ -2711,7 +2711,9 @@ var PACK_REGISTRY = {
2711
2711
  name: "Reviewer",
2712
2712
  description: "Skeptical review in a fresh context \u2014 finds and fixes what the coder missed.",
2713
2713
  skillIds: ["code-review", "code-naming"],
2714
- prompt: REVIEWER_PROMPT
2714
+ prompt: REVIEWER_PROMPT,
2715
+ // Review-only: approving clean with no change is success, not a stall.
2716
+ requiresCommit: false
2715
2717
  }
2716
2718
  ]
2717
2719
  },
@@ -2740,7 +2742,9 @@ var PACK_REGISTRY = {
2740
2742
  name: "Reviewer",
2741
2743
  description: "Audits correctness, scope, design, and conventions with fresh eyes.",
2742
2744
  skillIds: ["code-review", "code-naming"],
2743
- prompt: REVIEWER_PROMPT
2745
+ prompt: REVIEWER_PROMPT,
2746
+ // Review-only: approving clean with no change is success, not a stall.
2747
+ requiresCommit: false
2744
2748
  },
2745
2749
  {
2746
2750
  role: "qa",
@@ -8017,7 +8021,7 @@ function readAnonId() {
8017
8021
  }
8018
8022
  function superProperties() {
8019
8023
  return {
8020
- cliVersion: true ? "2.61.94" : "0.0.0-dev",
8024
+ cliVersion: true ? "2.61.96" : "0.0.0-dev",
8021
8025
  nodeVersion: process.version,
8022
8026
  platform: process.platform,
8023
8027
  arch: process.arch,
@@ -8198,7 +8202,7 @@ var os4 = __toESM(require("os"));
8198
8202
  // package.json
8199
8203
  var package_default = {
8200
8204
  name: "codeam-cli",
8201
- version: "2.61.94",
8205
+ version: "2.61.96",
8202
8206
  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.",
8203
8207
  type: "commonjs",
8204
8208
  main: "dist/index.js",
@@ -9515,7 +9519,7 @@ var CommandRelayService = class _CommandRelayService {
9515
9519
  // fresh + clear the "CLI update available" banner after a self-update
9516
9520
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
9517
9521
  // pair/reconnect). Older backends ignore the extra field.
9518
- ..."2.61.94" ? { ideVersion: "2.61.94" } : {}
9522
+ ..."2.61.96" ? { ideVersion: "2.61.96" } : {}
9519
9523
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
9520
9524
  }
9521
9525
  /**
@@ -20688,7 +20692,7 @@ async function autoUpgradeBeforeCriticalCommand() {
20688
20692
  if (process.env.NODE_ENV === "test") return;
20689
20693
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20690
20694
  if (process.env.CI) return;
20691
- const current2 = true ? "2.61.94" : null;
20695
+ const current2 = true ? "2.61.96" : null;
20692
20696
  if (!current2) return;
20693
20697
  const cache = readCache();
20694
20698
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -20705,7 +20709,7 @@ function checkForUpdates() {
20705
20709
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20706
20710
  if (process.env.CI) return;
20707
20711
  if (!process.stdout.isTTY) return;
20708
- const current2 = true ? "2.61.94" : null;
20712
+ const current2 = true ? "2.61.96" : null;
20709
20713
  if (!current2) return;
20710
20714
  const cache = readCache();
20711
20715
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -20725,7 +20729,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
20725
20729
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
20726
20730
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
20727
20731
  function currentCliVersion() {
20728
- return true ? "2.61.94" : null;
20732
+ return true ? "2.61.96" : null;
20729
20733
  }
20730
20734
  function runCmd(cmd, args2, timeoutMs) {
20731
20735
  return new Promise((resolve9) => {
@@ -32778,6 +32782,12 @@ function guardrailDecision(request, policy) {
32778
32782
  return null;
32779
32783
  }
32780
32784
 
32785
+ // src/agents/acp/modes.ts
32786
+ var FULL_AUTO_MODE_RE = /bypass|yolo|danger|full.?access|skip.?perm|auto.?approve/i;
32787
+ function modeIsFullAutoApprove(modeId) {
32788
+ return FULL_AUTO_MODE_RE.test(modeId);
32789
+ }
32790
+
32781
32791
  // src/agents/acp/client.ts
32782
32792
  var TRANSIENT_ADAPTER_SPAWN_RE = /ETXTBSY|ENOENT/;
32783
32793
  var MAX_START_ATTEMPTS = 5;
@@ -33244,7 +33254,7 @@ var AcpClient = class {
33244
33254
  * (`AcpHistory.switchActiveSession` + `onActiveSessionChanged`), exactly like
33245
33255
  * the `resume_session` rail.
33246
33256
  */
33247
- async newConversation() {
33257
+ async newConversation(opts) {
33248
33258
  if (!this.connection) {
33249
33259
  throw new Error("AcpClient.newConversation called before start()");
33250
33260
  }
@@ -33253,6 +33263,21 @@ var AcpClient = class {
33253
33263
  mcpServers: this.opts.mcpServers ?? []
33254
33264
  });
33255
33265
  this.sessionId = ns.sessionId;
33266
+ this.captureModelConfig(ns.configOptions ?? []);
33267
+ this.captureModes(ns.modes ?? null);
33268
+ if (opts?.ensureFullAutoMode && this.availableModes.length > 0) {
33269
+ const full = this.availableModes.find((m) => modeIsFullAutoApprove(m.id));
33270
+ if (full && this.currentModeId !== full.id) {
33271
+ try {
33272
+ await this.connection.setSessionMode({ sessionId: ns.sessionId, modeId: full.id });
33273
+ this.currentModeId = full.id;
33274
+ log.info("acpClient", `newConversation \u2192 re-asserted full-auto mode ${full.id}`);
33275
+ } catch (err) {
33276
+ const msg = err instanceof Error ? err.message : String(err);
33277
+ log.warn("acpClient", `newConversation \u2014 could not re-assert full-auto mode: ${msg}`);
33278
+ }
33279
+ }
33280
+ }
33256
33281
  log.info("acpClient", `newConversation \u2190 ok sid=${ns.sessionId.slice(0, 8)}`);
33257
33282
  return ns.sessionId;
33258
33283
  }
@@ -35721,11 +35746,31 @@ var PackRunner = class _PackRunner {
35721
35746
  await this.settle("aborted");
35722
35747
  return false;
35723
35748
  }
35749
+ const commitOptional = stageDef.requiresCommit === false;
35724
35750
  let endSha = await this.deps.gates.head();
35725
35751
  if (!endSha || endSha === startSha) {
35752
+ if (commitOptional && reply.trim().length > 0) {
35753
+ const reviewedCommit = startSha ? await this.deps.gates.canonicalCommit(startSha) : null;
35754
+ const handoff2 = {
35755
+ commit: reviewedCommit ?? "(no changes)",
35756
+ summary: reply.trim().slice(-SUMMARY_MAX_CHARS),
35757
+ diffStat: "reviewed \u2014 no changes needed",
35758
+ durationMs: Date.now() - startedMs
35759
+ };
35760
+ return this.recordHandoff(index, stageDef.role, handoff2);
35761
+ }
35726
35762
  reply = await this.deps.driver.runTurn(NUDGE_PROMPT, "\u25B6 Waiting for the stage commit\u2026");
35727
35763
  endSha = await this.deps.gates.head();
35728
35764
  if (!endSha || endSha === startSha) {
35765
+ if (commitOptional && reply.trim().length > 0) {
35766
+ const reviewedCommit = startSha ? await this.deps.gates.canonicalCommit(startSha) : null;
35767
+ return this.recordHandoff(index, stageDef.role, {
35768
+ commit: reviewedCommit ?? "(no changes)",
35769
+ summary: reply.trim().slice(-SUMMARY_MAX_CHARS),
35770
+ diffStat: "reviewed \u2014 no changes needed",
35771
+ durationMs: Date.now() - startedMs
35772
+ });
35773
+ }
35729
35774
  return this.stall(index, "stage produced no commit", reply);
35730
35775
  }
35731
35776
  }
@@ -35738,16 +35783,7 @@ var PackRunner = class _PackRunner {
35738
35783
  checks: await this.deps.gates.runChecks() ?? void 0,
35739
35784
  durationMs: Date.now() - startedMs
35740
35785
  };
35741
- stages = this.state.stages.slice();
35742
- stages[index] = { ...stages[index], status: "done", handoff };
35743
- this.state = { ...this.state, stages, currentStage: index + 1 };
35744
- try {
35745
- this.deps.ledger.saveStageHandoff(this.state.runId, index, stageDef.role, handoff);
35746
- } catch (err) {
35747
- this.deps.log(`pack handoff save failed: ${err.message}`);
35748
- }
35749
- await this.publish();
35750
- return true;
35786
+ return this.recordHandoff(index, stageDef.role, handoff);
35751
35787
  } catch (err) {
35752
35788
  if (this.control === "abort") {
35753
35789
  await this.settle("aborted");
@@ -35756,6 +35792,19 @@ var PackRunner = class _PackRunner {
35756
35792
  return this.stall(index, err.message);
35757
35793
  }
35758
35794
  }
35795
+ /** Mark a stage `done` with its handoff, persist, and advance. */
35796
+ async recordHandoff(index, role, handoff) {
35797
+ const stages = this.state.stages.slice();
35798
+ stages[index] = { ...stages[index], status: "done", handoff };
35799
+ this.state = { ...this.state, stages, currentStage: index + 1 };
35800
+ try {
35801
+ this.deps.ledger.saveStageHandoff(this.state.runId, index, role, handoff);
35802
+ } catch (err) {
35803
+ this.deps.log(`pack handoff save failed: ${err.message}`);
35804
+ }
35805
+ await this.publish();
35806
+ return true;
35807
+ }
35759
35808
  async stall(index, reason, lastReply) {
35760
35809
  const stages = this.state.stages.slice();
35761
35810
  stages[index] = { ...stages[index], status: "failed", error: reason };
@@ -35791,7 +35840,9 @@ function buildPackRunnerDeps(ctx) {
35791
35840
  return {
35792
35841
  driver: {
35793
35842
  newConversation: async () => {
35794
- const id = await ctx.client.newConversation();
35843
+ const id = await ctx.client.newConversation({
35844
+ ensureFullAutoMode: ctx.opts.autoApprovePermissions === true
35845
+ });
35795
35846
  ctx.history.switchActiveSession(id);
35796
35847
  ctx.onActiveSessionChanged?.(id);
35797
35848
  return id;
@@ -36439,10 +36490,6 @@ async function listModesH(ctx) {
36439
36490
  });
36440
36491
  return;
36441
36492
  }
36442
- var FULL_AUTO_MODE_RE = /bypass|yolo|danger|full.?access|skip.?perm|auto.?approve/i;
36443
- function modeIsFullAutoApprove(modeId) {
36444
- return FULL_AUTO_MODE_RE.test(modeId);
36445
- }
36446
36493
  async function setModeH(ctx) {
36447
36494
  const { cmd, client: client3, relay, opts } = ctx;
36448
36495
  const payload = cmd.payload;
@@ -42483,7 +42530,7 @@ function checkChokidar() {
42483
42530
  }
42484
42531
  async function doctor(args2 = []) {
42485
42532
  const json = args2.includes("--json");
42486
- const cliVersion = true ? "2.61.94" : "0.0.0-dev";
42533
+ const cliVersion = true ? "2.61.96" : "0.0.0-dev";
42487
42534
  const apiBase2 = resolveApiBaseUrl();
42488
42535
  const diagnosticId = (0, import_node_crypto13.randomUUID)();
42489
42536
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -42874,7 +42921,7 @@ async function mcpRun(args2) {
42874
42921
  // src/commands/version.ts
42875
42922
  var import_picocolors15 = __toESM(require("picocolors"));
42876
42923
  function version2() {
42877
- const v = true ? "2.61.94" : "unknown";
42924
+ const v = true ? "2.61.96" : "unknown";
42878
42925
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
42879
42926
  }
42880
42927
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.61.94",
3
+ "version": "2.61.96",
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",