codeam-cli 2.60.1 → 2.60.2

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,16 @@ 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.1] — 2026-07-08
8
+
9
+ ### Chore
10
+
11
+ - **cli:** Remove CODEAM_BATON flag — baton unconditional for local sessions
12
+
13
+ ### Fixed
14
+
15
+ - **cli:** Baton LOCAL_DRIVE mirror publishes turns live via the output stream
16
+
7
17
  ## [2.60.0] — 2026-07-08
8
18
 
9
19
  ### 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.1" : "0.0.0-dev",
5656
+ cliVersion: true ? "2.60.2" : "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.1",
5837
+ version: "2.60.2",
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.1" ? { ideVersion: "2.60.1" } : {}
6908
+ ..."2.60.2" ? { ideVersion: "2.60.2" } : {}
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.1" : null;
15924
+ const current = true ? "2.60.2" : 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.1" : null;
15941
+ const current = true ? "2.60.2" : 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.1" : null;
15961
+ return true ? "2.60.2" : null;
15962
15962
  }
15963
15963
  function runCmd(cmd, args2, timeoutMs) {
15964
15964
  return new Promise((resolve7) => {
@@ -29410,20 +29410,54 @@ var fs58 = __toESM(require("fs"));
29410
29410
  var TranscriptMirror = class {
29411
29411
  constructor(deps) {
29412
29412
  this.deps = deps;
29413
+ this.pollIntervalMs = deps.pollIntervalMs ?? 750;
29414
+ this.waitTimeoutMs = deps.waitTimeoutMs ?? 10 * 6e4;
29415
+ this.setIntervalFn = deps.setInterval ?? ((fn, ms) => setInterval(fn, ms));
29416
+ this.clearIntervalFn = deps.clearInterval ?? ((handle) => clearInterval(handle));
29413
29417
  }
29414
29418
  deps;
29415
29419
  emitted = 0;
29416
29420
  unwatch = null;
29421
+ pollHandle = null;
29422
+ attached = false;
29423
+ pollIntervalMs;
29424
+ waitTimeoutMs;
29425
+ setIntervalFn;
29426
+ clearIntervalFn;
29417
29427
  start() {
29428
+ if (this.tryAttach()) return;
29429
+ let waited = 0;
29430
+ this.pollHandle = this.setIntervalFn(() => {
29431
+ waited += this.pollIntervalMs;
29432
+ if (this.tryAttach()) {
29433
+ this.clearPoll();
29434
+ return;
29435
+ }
29436
+ if (this.waitTimeoutMs > 0 && waited >= this.waitTimeoutMs) this.clearPoll();
29437
+ }, this.pollIntervalMs);
29438
+ }
29439
+ stop() {
29440
+ this.clearPoll();
29441
+ this.unwatch?.();
29442
+ this.unwatch = null;
29443
+ }
29444
+ /** Resolve the transcript file; if present, emit the current contents and
29445
+ * begin watching. Returns whether it attached. */
29446
+ tryAttach() {
29447
+ if (this.attached) return true;
29418
29448
  const file = this.deps.runtime.resolveHistoryFile?.(this.deps.cwd, this.deps.conversationId);
29419
- if (!file) return;
29449
+ if (!file) return false;
29450
+ this.attached = true;
29420
29451
  this.emit(file);
29421
29452
  const watch2 = this.deps.watch ?? defaultWatch;
29422
29453
  this.unwatch = watch2(file, () => this.emit(file));
29454
+ return true;
29423
29455
  }
29424
- stop() {
29425
- this.unwatch?.();
29426
- this.unwatch = null;
29456
+ clearPoll() {
29457
+ if (this.pollHandle !== null) {
29458
+ this.clearIntervalFn(this.pollHandle);
29459
+ this.pollHandle = null;
29460
+ }
29427
29461
  }
29428
29462
  emit(file) {
29429
29463
  let all;
@@ -29489,6 +29523,7 @@ async function publishMirroredTurnsLive(publisher, messages) {
29489
29523
  function makeMirrorOnNewMessages(deps) {
29490
29524
  let isFirstEmit = true;
29491
29525
  let publishChain = Promise.resolve();
29526
+ const conversation = [];
29492
29527
  return (messages) => {
29493
29528
  const relevant = messages.filter((m) => m.role !== "system");
29494
29529
  if (relevant.length === 0) return;
@@ -29498,12 +29533,13 @@ function makeMirrorOnNewMessages(deps) {
29498
29533
  text: m.text,
29499
29534
  timestamp: toEpochMs(m.timestamp)
29500
29535
  }));
29536
+ conversation.push(...mapped);
29501
29537
  void deps.publisher.pushConversation({
29502
29538
  agentId: deps.agentId,
29503
29539
  sessionId: deps.conversationId,
29504
- messages: mapped
29540
+ messages: conversation.slice()
29505
29541
  });
29506
- if (!isFirstEmit) {
29542
+ if (deps.fresh || !isFirstEmit) {
29507
29543
  publishChain = publishChain.then(() => publishMirroredTurnsLive(deps.publisher, relevant)).catch((err) => {
29508
29544
  log.warn(
29509
29545
  "wireBaton",
@@ -29593,7 +29629,8 @@ async function runBatonSession(opts) {
29593
29629
  getBeads: opts.getBeads ?? (() => null)
29594
29630
  });
29595
29631
  let mirror = null;
29596
- const startMirror = (conversationId) => {
29632
+ let firstLocalDrive = true;
29633
+ const startMirror = (conversationId, fresh) => {
29597
29634
  mirror?.stop();
29598
29635
  mirror = new TranscriptMirror({
29599
29636
  runtime,
@@ -29602,7 +29639,8 @@ async function runBatonSession(opts) {
29602
29639
  onNewMessages: makeMirrorOnNewMessages({
29603
29640
  publisher,
29604
29641
  agentId: opts.agent,
29605
- conversationId
29642
+ conversationId,
29643
+ fresh
29606
29644
  })
29607
29645
  });
29608
29646
  mirror.start();
@@ -29619,8 +29657,12 @@ async function runBatonSession(opts) {
29619
29657
  driver,
29620
29658
  conversationId
29621
29659
  });
29622
- if (state === "LOCAL_DRIVE" && conversationId) startMirror(conversationId);
29623
- else if (state !== "LOCAL_DRIVE") mirror?.stop();
29660
+ if (state === "LOCAL_DRIVE" && conversationId) {
29661
+ startMirror(conversationId, firstLocalDrive);
29662
+ firstLocalDrive = false;
29663
+ } else if (state !== "LOCAL_DRIVE") {
29664
+ mirror?.stop();
29665
+ }
29624
29666
  }
29625
29667
  });
29626
29668
  const dispatchActive = (cmd) => controller.activeSessionDriver.dispatch(cmd);
@@ -32574,7 +32616,7 @@ function checkChokidar() {
32574
32616
  }
32575
32617
  async function doctor(args2 = []) {
32576
32618
  const json = args2.includes("--json");
32577
- const cliVersion = true ? "2.60.1" : "0.0.0-dev";
32619
+ const cliVersion = true ? "2.60.2" : "0.0.0-dev";
32578
32620
  const apiBase2 = resolveApiBaseUrl();
32579
32621
  const diagnosticId = (0, import_node_crypto9.randomUUID)();
32580
32622
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -32773,7 +32815,7 @@ async function completion(args2) {
32773
32815
  // src/commands/version.ts
32774
32816
  var import_picocolors15 = __toESM(require("picocolors"));
32775
32817
  function version2() {
32776
- const v = true ? "2.60.1" : "unknown";
32818
+ const v = true ? "2.60.2" : "unknown";
32777
32819
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
32778
32820
  }
32779
32821
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.60.1",
3
+ "version": "2.60.2",
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",