codeam-cli 2.60.20 → 2.60.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,13 @@ 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.20] — 2026-07-09
8
+
9
+ ### Fixed
10
+
11
+ - **cli:** Baton — pre-mint Cursor session id via `create-chat`
12
+ - **cli:** Baton Take Control for Cursor — bridge native↔ACP session stores
13
+
7
14
  ## [2.60.19] — 2026-07-09
8
15
 
9
16
  ### Fixed
package/dist/index.js CHANGED
@@ -5680,7 +5680,7 @@ function readAnonId() {
5680
5680
  }
5681
5681
  function superProperties() {
5682
5682
  return {
5683
- cliVersion: true ? "2.60.20" : "0.0.0-dev",
5683
+ cliVersion: true ? "2.60.21" : "0.0.0-dev",
5684
5684
  nodeVersion: process.version,
5685
5685
  platform: process.platform,
5686
5686
  arch: process.arch,
@@ -5861,7 +5861,7 @@ var os4 = __toESM(require("os"));
5861
5861
  // package.json
5862
5862
  var package_default = {
5863
5863
  name: "codeam-cli",
5864
- version: "2.60.20",
5864
+ version: "2.60.21",
5865
5865
  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.",
5866
5866
  type: "commonjs",
5867
5867
  main: "dist/index.js",
@@ -6932,7 +6932,7 @@ var CommandRelayService = class {
6932
6932
  // fresh + clear the "CLI update available" banner after a self-update
6933
6933
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
6934
6934
  // pair/reconnect). Older backends ignore the extra field.
6935
- ..."2.60.20" ? { ideVersion: "2.60.20" } : {}
6935
+ ..."2.60.21" ? { ideVersion: "2.60.21" } : {}
6936
6936
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6937
6937
  }
6938
6938
  /**
@@ -12931,6 +12931,87 @@ function resolveHistoryFile2(cwd, sessionId, homeOverride) {
12931
12931
  }
12932
12932
  return null;
12933
12933
  }
12934
+ async function discoverSessionId(cwd, opts, homeOverride) {
12935
+ const home = homeOverride ?? import_node_os.default.homedir();
12936
+ const sessionsRoot = import_node_path2.default.join(home, ".codex", "sessions");
12937
+ const floor = opts.sinceMs - 2e3;
12938
+ const deadline = Date.now() + (opts.timeoutMs ?? 24e4);
12939
+ let resolvedCurrent;
12940
+ try {
12941
+ resolvedCurrent = import_node_fs3.default.realpathSync(cwd);
12942
+ } catch {
12943
+ resolvedCurrent = import_node_path2.default.resolve(cwd);
12944
+ }
12945
+ for (; ; ) {
12946
+ const id = newestRolloutIdSince(sessionsRoot, resolvedCurrent, floor);
12947
+ if (id) return id;
12948
+ if (Date.now() >= deadline) return null;
12949
+ await sleep2(500);
12950
+ }
12951
+ }
12952
+ function newestRolloutIdSince(sessionsRoot, resolvedCwd, floorMs) {
12953
+ if (!import_node_fs3.default.existsSync(sessionsRoot)) return null;
12954
+ const now = /* @__PURE__ */ new Date();
12955
+ let bestId = null;
12956
+ let bestMtime = -1;
12957
+ for (let dayOffset = 0; dayOffset < 2; dayOffset += 1) {
12958
+ const d3 = new Date(now.getTime() - dayOffset * 24 * 60 * 60 * 1e3);
12959
+ const yyyy = String(d3.getUTCFullYear());
12960
+ const mm = String(d3.getUTCMonth() + 1).padStart(2, "0");
12961
+ const dd = String(d3.getUTCDate()).padStart(2, "0");
12962
+ const dayDir = import_node_path2.default.join(sessionsRoot, yyyy, mm, dd);
12963
+ let dayFiles;
12964
+ try {
12965
+ dayFiles = import_node_fs3.default.readdirSync(dayDir, { withFileTypes: true });
12966
+ } catch {
12967
+ continue;
12968
+ }
12969
+ for (const entry of dayFiles) {
12970
+ if (!entry.isFile()) continue;
12971
+ if (!entry.name.startsWith("rollout-") || !entry.name.endsWith(".jsonl")) continue;
12972
+ const filePath = import_node_path2.default.join(dayDir, entry.name);
12973
+ let mtime;
12974
+ try {
12975
+ mtime = import_node_fs3.default.statSync(filePath).mtimeMs;
12976
+ } catch {
12977
+ continue;
12978
+ }
12979
+ if (mtime < floorMs || mtime <= bestMtime) continue;
12980
+ let metaCwd;
12981
+ let metaId;
12982
+ try {
12983
+ const raw = import_node_fs3.default.readFileSync(filePath, "utf8");
12984
+ for (const line of raw.split("\n")) {
12985
+ if (!line.trim()) continue;
12986
+ const rec = parseLine(line);
12987
+ if (!rec) continue;
12988
+ if (rec.type === "session_meta") {
12989
+ const meta = rec.payload;
12990
+ metaCwd = typeof meta?.cwd === "string" ? meta.cwd : void 0;
12991
+ metaId = typeof meta?.id === "string" ? meta.id : void 0;
12992
+ }
12993
+ break;
12994
+ }
12995
+ } catch {
12996
+ continue;
12997
+ }
12998
+ if (!metaId || !metaCwd) continue;
12999
+ let resolvedMeta;
13000
+ try {
13001
+ resolvedMeta = import_node_fs3.default.realpathSync(metaCwd);
13002
+ } catch {
13003
+ resolvedMeta = import_node_path2.default.resolve(metaCwd);
13004
+ }
13005
+ if (resolvedMeta !== resolvedCwd) continue;
13006
+ bestMtime = mtime;
13007
+ bestId = metaId;
13008
+ }
13009
+ }
13010
+ return bestId;
13011
+ }
13012
+ function sleep2(ms) {
13013
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
13014
+ }
12934
13015
  function getCurrentUsage2(historyDir) {
12935
13016
  if (!import_node_fs3.default.existsSync(historyDir)) return null;
12936
13017
  const files = import_node_fs3.default.readdirSync(historyDir).filter((f) => f.startsWith("rollout-") && f.endsWith(".jsonl")).map((f) => ({ name: f, full: import_node_path2.default.join(historyDir, f) })).map((e) => ({ ...e, mtime: import_node_fs3.default.statSync(e.full).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
@@ -13098,6 +13179,16 @@ var CodexRuntimeStrategy = class {
13098
13179
  resolveHistoryFile(cwd, sessionId) {
13099
13180
  return resolveHistoryFile2(cwd, sessionId);
13100
13181
  }
13182
+ /**
13183
+ * Codex mints its own session id (into a `rollout-*.jsonl` at TUI boot) and
13184
+ * neither accepts a pre-set one nor prints it — so, like Kimi, the baton's
13185
+ * NativeTuiDriver discovers it post-spawn. Codex shares that rollout store with
13186
+ * its ACP adapter, so discovery alone is enough (no cross-store bridge). The
13187
+ * TUI boots slowly, hence the generous poll budget inside.
13188
+ */
13189
+ discoverSessionId(cwd, opts) {
13190
+ return discoverSessionId(cwd, opts);
13191
+ }
13101
13192
  getCurrentUsage(historyDir) {
13102
13193
  return getCurrentUsage2(historyDir);
13103
13194
  }
@@ -14473,7 +14564,7 @@ function scanBucketsForSession(sessionId) {
14473
14564
  }
14474
14565
  return null;
14475
14566
  }
14476
- async function discoverSessionId(cwd, opts) {
14567
+ async function discoverSessionId2(cwd, opts) {
14477
14568
  const bucket = path33.join(kimiHome(), "sessions", workDirKey(cwd));
14478
14569
  const floor = opts.sinceMs - 2e3;
14479
14570
  const deadline = Date.now() + (opts.timeoutMs ?? 15e3);
@@ -14481,7 +14572,7 @@ async function discoverSessionId(cwd, opts) {
14481
14572
  const id = newestSessionSince(bucket, floor);
14482
14573
  if (id) return id;
14483
14574
  if (Date.now() >= deadline) return null;
14484
- await sleep2(250);
14575
+ await sleep3(250);
14485
14576
  }
14486
14577
  }
14487
14578
  function newestSessionSince(bucket, floorMs) {
@@ -14508,7 +14599,7 @@ function newestSessionSince(bucket, floorMs) {
14508
14599
  }
14509
14600
  return bestId;
14510
14601
  }
14511
- function sleep2(ms) {
14602
+ function sleep3(ms) {
14512
14603
  return new Promise((resolve7) => setTimeout(resolve7, ms));
14513
14604
  }
14514
14605
  function joinTextParts(parts) {
@@ -14631,7 +14722,7 @@ var KimiRuntimeStrategy = class {
14631
14722
  * have no baton), so the driver's optional call is inert for them.
14632
14723
  */
14633
14724
  discoverSessionId(cwd, opts) {
14634
- return discoverSessionId(cwd, opts);
14725
+ return discoverSessionId2(cwd, opts);
14635
14726
  }
14636
14727
  getCurrentUsage(historyDir) {
14637
14728
  return getCurrentUsage5(historyDir);
@@ -16642,7 +16733,7 @@ async function autoUpgradeBeforeCriticalCommand() {
16642
16733
  if (process.env.NODE_ENV === "test") return;
16643
16734
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16644
16735
  if (process.env.CI) return;
16645
- const current = true ? "2.60.20" : null;
16736
+ const current = true ? "2.60.21" : null;
16646
16737
  if (!current) return;
16647
16738
  const cache = readCache();
16648
16739
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16659,7 +16750,7 @@ function checkForUpdates() {
16659
16750
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16660
16751
  if (process.env.CI) return;
16661
16752
  if (!process.stdout.isTTY) return;
16662
- const current = true ? "2.60.20" : null;
16753
+ const current = true ? "2.60.21" : null;
16663
16754
  if (!current) return;
16664
16755
  const cache = readCache();
16665
16756
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16679,7 +16770,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
16679
16770
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
16680
16771
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
16681
16772
  function currentCliVersion() {
16682
- return true ? "2.60.20" : null;
16773
+ return true ? "2.60.21" : null;
16683
16774
  }
16684
16775
  function runCmd(cmd, args2, timeoutMs) {
16685
16776
  return new Promise((resolve7) => {
@@ -22211,7 +22302,7 @@ async function waitForClaudeNativeBinary(opts = {}) {
22211
22302
  const timeoutMs = opts.timeoutMs ?? 18e4;
22212
22303
  const pollMs = opts.pollMs ?? 500;
22213
22304
  const now = opts.now ?? Date.now;
22214
- const sleep4 = opts.sleep ?? realSleep;
22305
+ const sleep5 = opts.sleep ?? realSleep;
22215
22306
  const deps = {
22216
22307
  sdkDir: opts.sdkDir,
22217
22308
  platformKey: opts.platformKey,
@@ -22221,7 +22312,7 @@ async function waitForClaudeNativeBinary(opts = {}) {
22221
22312
  let found = resolveClaudeNativeBinary(deps);
22222
22313
  if (found) return found;
22223
22314
  while (now() < deadline) {
22224
- await sleep4(pollMs);
22315
+ await sleep5(pollMs);
22225
22316
  found = resolveClaudeNativeBinary(deps);
22226
22317
  if (found) return found;
22227
22318
  }
@@ -22243,13 +22334,13 @@ async function waitForCommandOnPath(cmd, opts = {}) {
22243
22334
  const timeoutMs = opts.timeoutMs ?? 18e4;
22244
22335
  const pollMs = opts.pollMs ?? 500;
22245
22336
  const now = opts.now ?? Date.now;
22246
- const sleep4 = opts.sleep ?? realSleep;
22337
+ const sleep5 = opts.sleep ?? realSleep;
22247
22338
  const probe = opts.probe;
22248
22339
  const check = () => isCommandOnPath(cmd, probe);
22249
22340
  const deadline = now() + timeoutMs;
22250
22341
  if (check()) return true;
22251
22342
  while (now() < deadline) {
22252
- await sleep4(pollMs);
22343
+ await sleep5(pollMs);
22253
22344
  if (check()) return true;
22254
22345
  }
22255
22346
  return check();
@@ -22272,12 +22363,12 @@ async function waitForCursorAgent(opts = {}) {
22272
22363
  const timeoutMs = opts.timeoutMs ?? 18e4;
22273
22364
  const pollMs = opts.pollMs ?? 500;
22274
22365
  const now = opts.now ?? Date.now;
22275
- const sleep4 = opts.sleep ?? realSleep;
22366
+ const sleep5 = opts.sleep ?? realSleep;
22276
22367
  const check = () => resolveCursorAgentBinary(opts) !== null || isCommandOnPath("cursor-agent", opts.probe);
22277
22368
  const deadline = now() + timeoutMs;
22278
22369
  if (check()) return true;
22279
22370
  while (now() < deadline) {
22280
- await sleep4(pollMs);
22371
+ await sleep5(pollMs);
22281
22372
  if (check()) return true;
22282
22373
  }
22283
22374
  return check();
@@ -22326,12 +22417,12 @@ async function waitForAdapterModuleGraph(command2, args2, opts = {}) {
22326
22417
  const timeoutMs = opts.timeoutMs ?? 18e4;
22327
22418
  const pollMs = opts.pollMs ?? 500;
22328
22419
  const now = opts.now ?? Date.now;
22329
- const sleep4 = opts.sleep ?? realSleep;
22420
+ const sleep5 = opts.sleep ?? realSleep;
22330
22421
  const probeOpts = { livenessMs: opts.livenessMs, spawnFn: opts.spawnFn };
22331
22422
  const deadline = now() + timeoutMs;
22332
22423
  if (await probeAdapterModuleGraph(command2, args2, probeOpts) === "ok") return true;
22333
22424
  while (now() < deadline) {
22334
- await sleep4(pollMs);
22425
+ await sleep5(pollMs);
22335
22426
  if (await probeAdapterModuleGraph(command2, args2, probeOpts) === "ok") return true;
22336
22427
  }
22337
22428
  return false;
@@ -29939,12 +30030,12 @@ var StreamingEmitterService = class {
29939
30030
  log.warn("streamingEmitter", `post error url=${url} attempt=${attempt + 1}`, err);
29940
30031
  }
29941
30032
  if (attempt < MAX_RETRIES2) {
29942
- await sleep3(RETRY_BACKOFF_MS3 * (attempt + 1));
30033
+ await sleep4(RETRY_BACKOFF_MS3 * (attempt + 1));
29943
30034
  }
29944
30035
  }
29945
30036
  }
29946
30037
  };
29947
- function sleep3(ms) {
30038
+ function sleep4(ms) {
29948
30039
  return new Promise((r) => setTimeout(r, ms));
29949
30040
  }
29950
30041
  var TREE_CONTINUATION_RE = /^\s*└/;
@@ -33541,7 +33632,7 @@ function checkChokidar() {
33541
33632
  }
33542
33633
  async function doctor(args2 = []) {
33543
33634
  const json = args2.includes("--json");
33544
- const cliVersion = true ? "2.60.20" : "0.0.0-dev";
33635
+ const cliVersion = true ? "2.60.21" : "0.0.0-dev";
33545
33636
  const apiBase2 = resolveApiBaseUrl();
33546
33637
  const diagnosticId = (0, import_node_crypto12.randomUUID)();
33547
33638
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -33740,7 +33831,7 @@ async function completion(args2) {
33740
33831
  // src/commands/version.ts
33741
33832
  var import_picocolors15 = __toESM(require("picocolors"));
33742
33833
  function version2() {
33743
- const v = true ? "2.60.20" : "unknown";
33834
+ const v = true ? "2.60.21" : "unknown";
33744
33835
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
33745
33836
  }
33746
33837
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.60.20",
3
+ "version": "2.60.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",