codeam-cli 2.60.0 → 2.60.1

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,38 @@ 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.0] — 2026-07-08
8
+
9
+ ### Added
10
+
11
+ - **cli:** Baton local-session gate + feature flag
12
+ - **cli:** BatonController turn-safe single-driver state machine
13
+ - **cli:** TranscriptMirror emits JSONL deltas for the read-only view
14
+ - **cli:** NativeTuiDriver over AgentService with idle turn-boundary
15
+ - **cli:** AcpDriver over AcpClient (spawn + loadSession resume)
16
+ - **cli:** PostBatonEvent publisher driver-state
17
+ - **cli:** Take_control/handback relay handlers
18
+ - **cli:** Wire local baton branch before the ACP fork (flag-gated)
19
+ - **cli:** Make the session baton drivable after a hand-off
20
+ - **cli:** Enable the session baton by default for local sessions (CODEAM_BATON=0 kill switch)
21
+ - **shared:** Add baton_state to USER_EVENTS (session baton wire type)
22
+
23
+ ### Changed
24
+
25
+ - **cli:** Extract shared ACP command-context assembler + proxy-relaunch helper
26
+
27
+ ### Fixed
28
+
29
+ - **cli:** Mark SessionDriver.kind readonly (contract)
30
+ - **cli:** Baton switch-failure recovery + ack-on-failure; test cleanups
31
+ - **cli:** EncodeCwd underscore-collapse + ClaudeRuntimeStrategy.resolveHistoryFile (baton mirror)
32
+ - **cli:** AcpClient.start cleans up on handshake failure (baton take-control recovery)
33
+
34
+ ### Tests
35
+
36
+ - **cli:** Prove noteOutput resets the idle window + cover throw/undefined branches
37
+ - **cli:** Gated cross-mode-resume integration test (real claude)
38
+
7
39
  ## [2.59.0] — 2026-07-08
8
40
 
9
41
  ### Added
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.0" : "0.0.0-dev",
5656
+ cliVersion: true ? "2.60.1" : "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.0",
5837
+ version: "2.60.1",
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.0" ? { ideVersion: "2.60.0" } : {}
6908
+ ..."2.60.1" ? { ideVersion: "2.60.1" } : {}
6909
6909
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6910
6910
  }
6911
6911
  /**
@@ -15921,7 +15921,7 @@ async function autoUpgradeBeforeCriticalCommand() {
15921
15921
  if (process.env.NODE_ENV === "test") return;
15922
15922
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
15923
15923
  if (process.env.CI) return;
15924
- const current = true ? "2.60.0" : null;
15924
+ const current = true ? "2.60.1" : null;
15925
15925
  if (!current) return;
15926
15926
  const cache = readCache();
15927
15927
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -15938,7 +15938,7 @@ function checkForUpdates() {
15938
15938
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
15939
15939
  if (process.env.CI) return;
15940
15940
  if (!process.stdout.isTTY) return;
15941
- const current = true ? "2.60.0" : null;
15941
+ const current = true ? "2.60.1" : null;
15942
15942
  if (!current) return;
15943
15943
  const cache = readCache();
15944
15944
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -15958,7 +15958,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
15958
15958
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
15959
15959
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
15960
15960
  function currentCliVersion() {
15961
- return true ? "2.60.0" : null;
15961
+ return true ? "2.60.1" : null;
15962
15962
  }
15963
15963
  function runCmd(cmd, args2, timeoutMs) {
15964
15964
  return new Promise((resolve7) => {
@@ -29110,11 +29110,6 @@ function fetchQuotaUsage(runtime, historySvc) {
29110
29110
  function isLocalSession(env = process.env) {
29111
29111
  return env.CODESPACES !== "true" && env.CODEAM_AUTO_APPROVE !== "1" && env.HEADROOM_ENABLED !== "1" && !env.CODEAM_AUTO_TOKEN && !env.CODEAM_ENROLL_TOKEN;
29112
29112
  }
29113
- function batonEnabled(env = process.env) {
29114
- const v = env.CODEAM_BATON;
29115
- if (v === void 0 || v === "") return true;
29116
- return v !== "0" && v.toLowerCase() !== "false";
29117
- }
29118
29113
 
29119
29114
  // src/baton/baton-controller.ts
29120
29115
  var BatonController = class {
@@ -29480,6 +29475,45 @@ function makeOnCommand(deps) {
29480
29475
  await deps.dispatchActive(cmd);
29481
29476
  };
29482
29477
  }
29478
+ async function publishMirroredTurnsLive(publisher, messages) {
29479
+ for (const m of messages) {
29480
+ if (m.role === "user") {
29481
+ await publisher.publishOutput({ type: "clear" });
29482
+ await publisher.publishOutput({ type: "user_message", content: m.text, done: true });
29483
+ await publisher.publishOutput({ type: "new_turn", done: false });
29484
+ } else {
29485
+ await publisher.publishOutput({ type: "text", content: m.text, done: true });
29486
+ }
29487
+ }
29488
+ }
29489
+ function makeMirrorOnNewMessages(deps) {
29490
+ let isFirstEmit = true;
29491
+ let publishChain = Promise.resolve();
29492
+ return (messages) => {
29493
+ const relevant = messages.filter((m) => m.role !== "system");
29494
+ if (relevant.length === 0) return;
29495
+ const mapped = relevant.map((m) => ({
29496
+ id: m.id,
29497
+ role: m.role === "user" ? "user" : "agent",
29498
+ text: m.text,
29499
+ timestamp: toEpochMs(m.timestamp)
29500
+ }));
29501
+ void deps.publisher.pushConversation({
29502
+ agentId: deps.agentId,
29503
+ sessionId: deps.conversationId,
29504
+ messages: mapped
29505
+ });
29506
+ if (!isFirstEmit) {
29507
+ publishChain = publishChain.then(() => publishMirroredTurnsLive(deps.publisher, relevant)).catch((err) => {
29508
+ log.warn(
29509
+ "wireBaton",
29510
+ `mirror live-publish failed: ${err instanceof Error ? err.message : String(err)}`
29511
+ );
29512
+ });
29513
+ }
29514
+ isFirstEmit = false;
29515
+ };
29516
+ }
29483
29517
  async function runBatonSession(opts) {
29484
29518
  const publisher = new AcpPublisher({
29485
29519
  sessionId: opts.sessionId,
@@ -29565,20 +29599,11 @@ async function runBatonSession(opts) {
29565
29599
  runtime,
29566
29600
  cwd: opts.cwd,
29567
29601
  conversationId,
29568
- onNewMessages: (messages) => {
29569
- const mapped = messages.filter((m) => m.role !== "system").map((m) => ({
29570
- id: m.id,
29571
- role: m.role === "user" ? "user" : "agent",
29572
- text: m.text,
29573
- timestamp: toEpochMs(m.timestamp)
29574
- }));
29575
- if (mapped.length === 0) return;
29576
- void publisher.pushConversation({
29577
- agentId: opts.agent,
29578
- sessionId: conversationId,
29579
- messages: mapped
29580
- });
29581
- }
29602
+ onNewMessages: makeMirrorOnNewMessages({
29603
+ publisher,
29604
+ agentId: opts.agent,
29605
+ conversationId
29606
+ })
29582
29607
  });
29583
29608
  mirror.start();
29584
29609
  };
@@ -29786,7 +29811,7 @@ async function start(requestedAgent) {
29786
29811
  `agent-spawn gate released \u2014 beads ${beads ? "ready" : "pending"}; project deps provisioned`
29787
29812
  );
29788
29813
  }
29789
- if (isLocalSession() && batonEnabled() && requiresAcp(session.agent)) {
29814
+ if (isLocalSession() && requiresAcp(session.agent)) {
29790
29815
  const adapter = getAcpAdapter(session.agent);
29791
29816
  if (adapter && session.pluginAuthToken) {
29792
29817
  await runBatonSession({
@@ -32549,7 +32574,7 @@ function checkChokidar() {
32549
32574
  }
32550
32575
  async function doctor(args2 = []) {
32551
32576
  const json = args2.includes("--json");
32552
- const cliVersion = true ? "2.60.0" : "0.0.0-dev";
32577
+ const cliVersion = true ? "2.60.1" : "0.0.0-dev";
32553
32578
  const apiBase2 = resolveApiBaseUrl();
32554
32579
  const diagnosticId = (0, import_node_crypto9.randomUUID)();
32555
32580
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -32748,7 +32773,7 @@ async function completion(args2) {
32748
32773
  // src/commands/version.ts
32749
32774
  var import_picocolors15 = __toESM(require("picocolors"));
32750
32775
  function version2() {
32751
- const v = true ? "2.60.0" : "unknown";
32776
+ const v = true ? "2.60.1" : "unknown";
32752
32777
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
32753
32778
  }
32754
32779
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.60.0",
3
+ "version": "2.60.1",
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",