codeam-cli 2.61.95 → 2.61.97

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.js +126 -30
  3. 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.61.96] — 2026-08-08
8
+
9
+ ### Fixed
10
+
11
+ - **packs:** A review-only stage that approves clean is DONE, not a stall (#606)
12
+
13
+ ## [2.61.95] — 2026-08-08
14
+
15
+ ### Fixed
16
+
17
+ - **cli:** Re-assert full-auto mode on Agent Packs fresh conversations (#605)
18
+
7
19
  ## [2.61.94] — 2026-08-08
8
20
 
9
21
  ### Fixed
package/dist/index.js CHANGED
@@ -90,11 +90,11 @@ var require_src = __commonJS({
90
90
  });
91
91
 
92
92
  // src/integrations/stdio-proxy.ts
93
- var import_node_child_process32, import_node_readline3, RESTART_CHECK_INTERVAL_MS, SIGKILL_ESCALATION_MS, TOOL_CALL_TIMEOUT_MS, REPLAY_INIT_ID, RestartableStdioProxy;
93
+ var import_node_child_process33, import_node_readline3, RESTART_CHECK_INTERVAL_MS, SIGKILL_ESCALATION_MS, TOOL_CALL_TIMEOUT_MS, REPLAY_INIT_ID, RestartableStdioProxy;
94
94
  var init_stdio_proxy = __esm({
95
95
  "src/integrations/stdio-proxy.ts"() {
96
96
  "use strict";
97
- import_node_child_process32 = require("child_process");
97
+ import_node_child_process33 = require("child_process");
98
98
  import_node_readline3 = __toESM(require("readline"));
99
99
  RESTART_CHECK_INTERVAL_MS = 3e4;
100
100
  SIGKILL_ESCALATION_MS = 2e3;
@@ -271,8 +271,8 @@ var init_stdio_proxy = __esm({
271
271
  }
272
272
  async spawnChild(stdout, preResolved) {
273
273
  const spec = preResolved ?? await this.opts.spawnSpec();
274
- const spawn44 = this.opts.spawnImpl ?? import_node_child_process32.spawn;
275
- const child = spawn44(spec.command, spec.args, {
274
+ const spawn45 = this.opts.spawnImpl ?? import_node_child_process33.spawn;
275
+ const child = spawn45(spec.command, spec.args, {
276
276
  env: { ...process.env, ...spec.env },
277
277
  // env only — never argv
278
278
  stdio: ["pipe", "pipe", "inherit"]
@@ -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.95" : "0.0.0-dev",
8024
+ cliVersion: true ? "2.61.97" : "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.95",
8205
+ version: "2.61.97",
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.95" ? { ideVersion: "2.61.95" } : {}
9522
+ ..."2.61.97" ? { ideVersion: "2.61.97" } : {}
9519
9523
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
9520
9524
  }
9521
9525
  /**
@@ -14061,9 +14065,26 @@ var PosixOsStrategy = class {
14061
14065
  };
14062
14066
  var DarwinOsStrategy = class extends PosixOsStrategy {
14063
14067
  id = "darwin";
14068
+ keepAwakeCommand(pid) {
14069
+ return { cmd: "caffeinate", args: ["-i", "-s", "-w", String(pid)] };
14070
+ }
14064
14071
  };
14065
14072
  var LinuxOsStrategy = class extends PosixOsStrategy {
14066
14073
  id = "linux";
14074
+ keepAwakeCommand(pid) {
14075
+ return {
14076
+ cmd: "systemd-inhibit",
14077
+ args: [
14078
+ "--what=sleep:idle",
14079
+ "--why=CodeAgent local session active",
14080
+ "--mode=block",
14081
+ "tail",
14082
+ `--pid=${pid}`,
14083
+ "-f",
14084
+ "/dev/null"
14085
+ ]
14086
+ };
14087
+ }
14067
14088
  };
14068
14089
 
14069
14090
  // src/os/win32.ts
@@ -14347,6 +14368,19 @@ var Win32OsStrategy = class {
14347
14368
  list.push(new WindowsPtyStrategy(opts));
14348
14369
  return list;
14349
14370
  }
14371
+ keepAwakeCommand(pid) {
14372
+ const script = [
14373
+ "$s=Add-Type -Name P -Namespace W -PassThru -MemberDefinition",
14374
+ `'[DllImport("kernel32.dll")] public static extern uint SetThreadExecutionState(uint e);';`,
14375
+ "$s::SetThreadExecutionState(2147483649) | Out-Null;",
14376
+ `try { (Get-Process -Id ${pid} -ErrorAction Stop).WaitForExit() } catch {};`,
14377
+ "$s::SetThreadExecutionState(2147483648) | Out-Null;"
14378
+ ].join(" ");
14379
+ return {
14380
+ cmd: "powershell",
14381
+ args: ["-NoProfile", "-NonInteractive", "-Command", script]
14382
+ };
14383
+ }
14350
14384
  };
14351
14385
 
14352
14386
  // src/os/registry.ts
@@ -20688,7 +20722,7 @@ async function autoUpgradeBeforeCriticalCommand() {
20688
20722
  if (process.env.NODE_ENV === "test") return;
20689
20723
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20690
20724
  if (process.env.CI) return;
20691
- const current2 = true ? "2.61.95" : null;
20725
+ const current2 = true ? "2.61.97" : null;
20692
20726
  if (!current2) return;
20693
20727
  const cache = readCache();
20694
20728
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -20705,7 +20739,7 @@ function checkForUpdates() {
20705
20739
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20706
20740
  if (process.env.CI) return;
20707
20741
  if (!process.stdout.isTTY) return;
20708
- const current2 = true ? "2.61.95" : null;
20742
+ const current2 = true ? "2.61.97" : null;
20709
20743
  if (!current2) return;
20710
20744
  const cache = readCache();
20711
20745
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -20725,7 +20759,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
20725
20759
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
20726
20760
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
20727
20761
  function currentCliVersion() {
20728
- return true ? "2.61.95" : null;
20762
+ return true ? "2.61.97" : null;
20729
20763
  }
20730
20764
  function runCmd(cmd, args2, timeoutMs) {
20731
20765
  return new Promise((resolve9) => {
@@ -33771,12 +33805,12 @@ function buildRelaunchProxyEnv(baseEnv) {
33771
33805
  return env;
33772
33806
  }
33773
33807
  var relaunchProxyWithoutBudget = async () => {
33774
- const { spawn: spawn44 } = await import("child_process");
33808
+ const { spawn: spawn45 } = await import("child_process");
33775
33809
  killHeadroomProxy();
33776
33810
  await new Promise((r) => setTimeout(r, 500));
33777
33811
  const proxyEnv = buildRelaunchProxyEnv(process.env);
33778
33812
  try {
33779
- const proxy = spawn44(
33813
+ const proxy = spawn45(
33780
33814
  "headroom",
33781
33815
  ["proxy", "--port", "8787"],
33782
33816
  { stdio: "ignore", detached: true, env: proxyEnv }
@@ -35742,11 +35776,31 @@ var PackRunner = class _PackRunner {
35742
35776
  await this.settle("aborted");
35743
35777
  return false;
35744
35778
  }
35779
+ const commitOptional = stageDef.requiresCommit === false;
35745
35780
  let endSha = await this.deps.gates.head();
35746
35781
  if (!endSha || endSha === startSha) {
35782
+ if (commitOptional && reply.trim().length > 0) {
35783
+ const reviewedCommit = startSha ? await this.deps.gates.canonicalCommit(startSha) : null;
35784
+ const handoff2 = {
35785
+ commit: reviewedCommit ?? "(no changes)",
35786
+ summary: reply.trim().slice(-SUMMARY_MAX_CHARS),
35787
+ diffStat: "reviewed \u2014 no changes needed",
35788
+ durationMs: Date.now() - startedMs
35789
+ };
35790
+ return this.recordHandoff(index, stageDef.role, handoff2);
35791
+ }
35747
35792
  reply = await this.deps.driver.runTurn(NUDGE_PROMPT, "\u25B6 Waiting for the stage commit\u2026");
35748
35793
  endSha = await this.deps.gates.head();
35749
35794
  if (!endSha || endSha === startSha) {
35795
+ if (commitOptional && reply.trim().length > 0) {
35796
+ const reviewedCommit = startSha ? await this.deps.gates.canonicalCommit(startSha) : null;
35797
+ return this.recordHandoff(index, stageDef.role, {
35798
+ commit: reviewedCommit ?? "(no changes)",
35799
+ summary: reply.trim().slice(-SUMMARY_MAX_CHARS),
35800
+ diffStat: "reviewed \u2014 no changes needed",
35801
+ durationMs: Date.now() - startedMs
35802
+ });
35803
+ }
35750
35804
  return this.stall(index, "stage produced no commit", reply);
35751
35805
  }
35752
35806
  }
@@ -35759,16 +35813,7 @@ var PackRunner = class _PackRunner {
35759
35813
  checks: await this.deps.gates.runChecks() ?? void 0,
35760
35814
  durationMs: Date.now() - startedMs
35761
35815
  };
35762
- stages = this.state.stages.slice();
35763
- stages[index] = { ...stages[index], status: "done", handoff };
35764
- this.state = { ...this.state, stages, currentStage: index + 1 };
35765
- try {
35766
- this.deps.ledger.saveStageHandoff(this.state.runId, index, stageDef.role, handoff);
35767
- } catch (err) {
35768
- this.deps.log(`pack handoff save failed: ${err.message}`);
35769
- }
35770
- await this.publish();
35771
- return true;
35816
+ return this.recordHandoff(index, stageDef.role, handoff);
35772
35817
  } catch (err) {
35773
35818
  if (this.control === "abort") {
35774
35819
  await this.settle("aborted");
@@ -35777,6 +35822,19 @@ var PackRunner = class _PackRunner {
35777
35822
  return this.stall(index, err.message);
35778
35823
  }
35779
35824
  }
35825
+ /** Mark a stage `done` with its handoff, persist, and advance. */
35826
+ async recordHandoff(index, role, handoff) {
35827
+ const stages = this.state.stages.slice();
35828
+ stages[index] = { ...stages[index], status: "done", handoff };
35829
+ this.state = { ...this.state, stages, currentStage: index + 1 };
35830
+ try {
35831
+ this.deps.ledger.saveStageHandoff(this.state.runId, index, role, handoff);
35832
+ } catch (err) {
35833
+ this.deps.log(`pack handoff save failed: ${err.message}`);
35834
+ }
35835
+ await this.publish();
35836
+ return true;
35837
+ }
35780
35838
  async stall(index, reason, lastReply) {
35781
35839
  const stages = this.state.stages.slice();
35782
35840
  stages[index] = { ...stages[index], status: "failed", error: reason };
@@ -39522,6 +39580,42 @@ function toEpochMs(ts) {
39522
39580
  return Number.isFinite(parsed) ? parsed : Date.now();
39523
39581
  }
39524
39582
 
39583
+ // src/services/keep-awake.ts
39584
+ var import_node_child_process32 = require("child_process");
39585
+ function keepDeviceAwake(deps = {}) {
39586
+ const env = deps.env ?? process.env;
39587
+ const isLocal = deps.isLocal ?? isLocalSession(env);
39588
+ const noop = () => {
39589
+ };
39590
+ if (!isLocal) return noop;
39591
+ if (env.CODEAM_NO_KEEP_AWAKE === "1") return noop;
39592
+ const command2 = deps.command !== void 0 ? deps.command : createOsStrategy().keepAwakeCommand(deps.pid ?? process.pid);
39593
+ if (!command2) return noop;
39594
+ const spawnFn = deps.spawnFn ?? import_node_child_process32.spawn;
39595
+ let child = null;
39596
+ try {
39597
+ child = spawnFn(command2.cmd, command2.args, { stdio: "ignore", detached: true });
39598
+ child.once("error", () => {
39599
+ });
39600
+ child.unref();
39601
+ log.info("keep-awake", `holding a power assertion for this local session (${command2.cmd})`);
39602
+ } catch {
39603
+ child = null;
39604
+ }
39605
+ let released = false;
39606
+ return () => {
39607
+ if (released) return;
39608
+ released = true;
39609
+ if (child && child.pid && !child.killed) {
39610
+ try {
39611
+ child.kill("SIGTERM");
39612
+ } catch {
39613
+ }
39614
+ }
39615
+ child = null;
39616
+ };
39617
+ }
39618
+
39525
39619
  // src/agents/claude/onboarding.ts
39526
39620
  var fs77 = __toESM(require("fs"));
39527
39621
  var os60 = __toESM(require("os"));
@@ -39706,6 +39800,8 @@ async function start(requestedAgent, presetSession) {
39706
39800
  `agent-spawn gate released (beads ungated, ${beads ? "already ready" : "still provisioning in background"}); project deps provisioned`
39707
39801
  );
39708
39802
  }
39803
+ const releaseKeepAwake = keepDeviceAwake();
39804
+ process.once("exit", releaseKeepAwake);
39709
39805
  if (isLocalSession() && requiresAcp(session.agent)) {
39710
39806
  const adapter = await resolveAcpAdapterWithRetry(session.agent);
39711
39807
  const batonCapable = runtimeSupportsBaton(createRuntimeStrategy(session.agent));
@@ -42502,7 +42598,7 @@ function checkChokidar() {
42502
42598
  }
42503
42599
  async function doctor(args2 = []) {
42504
42600
  const json = args2.includes("--json");
42505
- const cliVersion = true ? "2.61.95" : "0.0.0-dev";
42601
+ const cliVersion = true ? "2.61.97" : "0.0.0-dev";
42506
42602
  const apiBase2 = resolveApiBaseUrl();
42507
42603
  const diagnosticId = (0, import_node_crypto13.randomUUID)();
42508
42604
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -42699,7 +42795,7 @@ async function completion(args2) {
42699
42795
  }
42700
42796
 
42701
42797
  // src/integrations/mcp-run.ts
42702
- var import_node_child_process33 = require("child_process");
42798
+ var import_node_child_process34 = require("child_process");
42703
42799
  var import_node_fs12 = require("fs");
42704
42800
  var import_node_os14 = __toESM(require("os"));
42705
42801
  var import_node_path12 = __toESM(require("path"));
@@ -42774,7 +42870,7 @@ function resolveDelivery(id) {
42774
42870
  function commandExists(command2) {
42775
42871
  try {
42776
42872
  const probe = process.platform === "win32" ? "where" : "which";
42777
- (0, import_node_child_process33.execFileSync)(probe, [command2], { stdio: "ignore" });
42873
+ (0, import_node_child_process34.execFileSync)(probe, [command2], { stdio: "ignore" });
42778
42874
  return true;
42779
42875
  } catch {
42780
42876
  return false;
@@ -42807,7 +42903,7 @@ function ensureCommand(command2) {
42807
42903
  }
42808
42904
  if (command2 === "uvx") {
42809
42905
  try {
42810
- (0, import_node_child_process33.execSync)("curl -LsSf https://astral.sh/uv/install.sh | sh", {
42906
+ (0, import_node_child_process34.execSync)("curl -LsSf https://astral.sh/uv/install.sh | sh", {
42811
42907
  stdio: ["ignore", process.stderr, process.stderr],
42812
42908
  timeout: 18e4,
42813
42909
  env: { ...process.env, UV_NO_MODIFY_PATH: "1" }
@@ -42816,7 +42912,7 @@ function ensureCommand(command2) {
42816
42912
  }
42817
42913
  if (resolveLauncherPath(command2) !== command2) return;
42818
42914
  try {
42819
- (0, import_node_child_process33.execSync)("python3 -m pip install --user --quiet uv", {
42915
+ (0, import_node_child_process34.execSync)("python3 -m pip install --user --quiet uv", {
42820
42916
  stdio: ["ignore", process.stderr, process.stderr],
42821
42917
  timeout: 18e4
42822
42918
  });
@@ -42893,7 +42989,7 @@ async function mcpRun(args2) {
42893
42989
  // src/commands/version.ts
42894
42990
  var import_picocolors15 = __toESM(require("picocolors"));
42895
42991
  function version2() {
42896
- const v = true ? "2.61.95" : "unknown";
42992
+ const v = true ? "2.61.97" : "unknown";
42897
42993
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
42898
42994
  }
42899
42995
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.61.95",
3
+ "version": "2.61.97",
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",