codeam-cli 2.60.17 → 2.60.18

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.60.17] — 2026-07-09
8
+
9
+ ### Added
10
+
11
+ - **cli:** Auto-install Kimi on local pair when the binary is missing
12
+
13
+ ## [2.60.16] — 2026-07-09
14
+
15
+ ### Added
16
+
17
+ - **cli:** Session Baton support for Kimi Code (local Take Control)
18
+
7
19
  ## [2.60.15] — 2026-07-09
8
20
 
9
21
  ### 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.17" : "0.0.0-dev",
5683
+ cliVersion: true ? "2.60.18" : "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.17",
5864
+ version: "2.60.18",
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.17" ? { ideVersion: "2.60.17" } : {}
6935
+ ..."2.60.18" ? { ideVersion: "2.60.18" } : {}
6936
6936
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6937
6937
  }
6938
6938
  /**
@@ -14347,6 +14347,44 @@ function scanBucketsForSession(sessionId) {
14347
14347
  }
14348
14348
  return null;
14349
14349
  }
14350
+ async function discoverSessionId(cwd, opts) {
14351
+ const bucket = path33.join(kimiHome(), "sessions", workDirKey(cwd));
14352
+ const floor = opts.sinceMs - 2e3;
14353
+ const deadline = Date.now() + (opts.timeoutMs ?? 15e3);
14354
+ for (; ; ) {
14355
+ const id = newestSessionSince(bucket, floor);
14356
+ if (id) return id;
14357
+ if (Date.now() >= deadline) return null;
14358
+ await sleep2(250);
14359
+ }
14360
+ }
14361
+ function newestSessionSince(bucket, floorMs) {
14362
+ let entries;
14363
+ try {
14364
+ entries = fs29.readdirSync(bucket, { withFileTypes: true });
14365
+ } catch {
14366
+ return null;
14367
+ }
14368
+ let bestId = null;
14369
+ let bestMtime = -1;
14370
+ for (const e of entries) {
14371
+ if (!e.isDirectory() || !e.name.startsWith("session_")) continue;
14372
+ let mtime;
14373
+ try {
14374
+ mtime = fs29.statSync(path33.join(bucket, e.name)).mtimeMs;
14375
+ } catch {
14376
+ continue;
14377
+ }
14378
+ if (mtime >= floorMs && mtime > bestMtime) {
14379
+ bestMtime = mtime;
14380
+ bestId = e.name;
14381
+ }
14382
+ }
14383
+ return bestId;
14384
+ }
14385
+ function sleep2(ms) {
14386
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
14387
+ }
14350
14388
  function joinTextParts(parts) {
14351
14389
  if (!Array.isArray(parts)) return "";
14352
14390
  return parts.filter((p2) => p2 && p2.type === "text" && typeof p2.text === "string").map((p2) => p2.text).join("").trim();
@@ -14456,6 +14494,19 @@ var KimiRuntimeStrategy = class {
14456
14494
  parseHistoryFile(filePath) {
14457
14495
  return parseHistoryFile6(filePath);
14458
14496
  }
14497
+ /**
14498
+ * Kimi neither accepts a pre-set session id (`kimi -S <newid>` fails
14499
+ * "Session not found") NOR prints its id on stdout — it MINTS one itself and
14500
+ * writes it to `<KIMI_CODE_HOME>/sessions/wd_<key>/<sessionId>/` when the
14501
+ * native TUI boots. So `prepareLaunch` can't return a `sessionId` and the
14502
+ * baton's NativeTuiDriver has nothing to bind. This hook bounded-polls that
14503
+ * store for the dir kimi just created (mtime ≥ spawn time) and returns its id.
14504
+ * Kimi-specific — no other agent implements this (claude pre-mints; the rest
14505
+ * have no baton), so the driver's optional call is inert for them.
14506
+ */
14507
+ discoverSessionId(cwd, opts) {
14508
+ return discoverSessionId(cwd, opts);
14509
+ }
14459
14510
  getCurrentUsage(historyDir) {
14460
14511
  return getCurrentUsage5(historyDir);
14461
14512
  }
@@ -16465,7 +16516,7 @@ async function autoUpgradeBeforeCriticalCommand() {
16465
16516
  if (process.env.NODE_ENV === "test") return;
16466
16517
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16467
16518
  if (process.env.CI) return;
16468
- const current = true ? "2.60.17" : null;
16519
+ const current = true ? "2.60.18" : null;
16469
16520
  if (!current) return;
16470
16521
  const cache = readCache();
16471
16522
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16482,7 +16533,7 @@ function checkForUpdates() {
16482
16533
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16483
16534
  if (process.env.CI) return;
16484
16535
  if (!process.stdout.isTTY) return;
16485
- const current = true ? "2.60.17" : null;
16536
+ const current = true ? "2.60.18" : null;
16486
16537
  if (!current) return;
16487
16538
  const cache = readCache();
16488
16539
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16502,7 +16553,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
16502
16553
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
16503
16554
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
16504
16555
  function currentCliVersion() {
16505
- return true ? "2.60.17" : null;
16556
+ return true ? "2.60.18" : null;
16506
16557
  }
16507
16558
  function runCmd(cmd, args2, timeoutMs) {
16508
16559
  return new Promise((resolve7) => {
@@ -22034,7 +22085,7 @@ async function waitForClaudeNativeBinary(opts = {}) {
22034
22085
  const timeoutMs = opts.timeoutMs ?? 18e4;
22035
22086
  const pollMs = opts.pollMs ?? 500;
22036
22087
  const now = opts.now ?? Date.now;
22037
- const sleep3 = opts.sleep ?? realSleep;
22088
+ const sleep4 = opts.sleep ?? realSleep;
22038
22089
  const deps = {
22039
22090
  sdkDir: opts.sdkDir,
22040
22091
  platformKey: opts.platformKey,
@@ -22044,7 +22095,7 @@ async function waitForClaudeNativeBinary(opts = {}) {
22044
22095
  let found = resolveClaudeNativeBinary(deps);
22045
22096
  if (found) return found;
22046
22097
  while (now() < deadline) {
22047
- await sleep3(pollMs);
22098
+ await sleep4(pollMs);
22048
22099
  found = resolveClaudeNativeBinary(deps);
22049
22100
  if (found) return found;
22050
22101
  }
@@ -22066,13 +22117,13 @@ async function waitForCommandOnPath(cmd, opts = {}) {
22066
22117
  const timeoutMs = opts.timeoutMs ?? 18e4;
22067
22118
  const pollMs = opts.pollMs ?? 500;
22068
22119
  const now = opts.now ?? Date.now;
22069
- const sleep3 = opts.sleep ?? realSleep;
22120
+ const sleep4 = opts.sleep ?? realSleep;
22070
22121
  const probe = opts.probe;
22071
22122
  const check = () => isCommandOnPath(cmd, probe);
22072
22123
  const deadline = now() + timeoutMs;
22073
22124
  if (check()) return true;
22074
22125
  while (now() < deadline) {
22075
- await sleep3(pollMs);
22126
+ await sleep4(pollMs);
22076
22127
  if (check()) return true;
22077
22128
  }
22078
22129
  return check();
@@ -22095,12 +22146,12 @@ async function waitForCursorAgent(opts = {}) {
22095
22146
  const timeoutMs = opts.timeoutMs ?? 18e4;
22096
22147
  const pollMs = opts.pollMs ?? 500;
22097
22148
  const now = opts.now ?? Date.now;
22098
- const sleep3 = opts.sleep ?? realSleep;
22149
+ const sleep4 = opts.sleep ?? realSleep;
22099
22150
  const check = () => resolveCursorAgentBinary(opts) !== null || isCommandOnPath("cursor-agent", opts.probe);
22100
22151
  const deadline = now() + timeoutMs;
22101
22152
  if (check()) return true;
22102
22153
  while (now() < deadline) {
22103
- await sleep3(pollMs);
22154
+ await sleep4(pollMs);
22104
22155
  if (check()) return true;
22105
22156
  }
22106
22157
  return check();
@@ -22149,12 +22200,12 @@ async function waitForAdapterModuleGraph(command2, args2, opts = {}) {
22149
22200
  const timeoutMs = opts.timeoutMs ?? 18e4;
22150
22201
  const pollMs = opts.pollMs ?? 500;
22151
22202
  const now = opts.now ?? Date.now;
22152
- const sleep3 = opts.sleep ?? realSleep;
22203
+ const sleep4 = opts.sleep ?? realSleep;
22153
22204
  const probeOpts = { livenessMs: opts.livenessMs, spawnFn: opts.spawnFn };
22154
22205
  const deadline = now() + timeoutMs;
22155
22206
  if (await probeAdapterModuleGraph(command2, args2, probeOpts) === "ok") return true;
22156
22207
  while (now() < deadline) {
22157
- await sleep3(pollMs);
22208
+ await sleep4(pollMs);
22158
22209
  if (await probeAdapterModuleGraph(command2, args2, probeOpts) === "ok") return true;
22159
22210
  }
22160
22211
  return false;
@@ -29762,12 +29813,12 @@ var StreamingEmitterService = class {
29762
29813
  log.warn("streamingEmitter", `post error url=${url} attempt=${attempt + 1}`, err);
29763
29814
  }
29764
29815
  if (attempt < MAX_RETRIES2) {
29765
- await sleep2(RETRY_BACKOFF_MS3 * (attempt + 1));
29816
+ await sleep3(RETRY_BACKOFF_MS3 * (attempt + 1));
29766
29817
  }
29767
29818
  }
29768
29819
  }
29769
29820
  };
29770
- function sleep2(ms) {
29821
+ function sleep3(ms) {
29771
29822
  return new Promise((r) => setTimeout(r, ms));
29772
29823
  }
29773
29824
  var TREE_CONTINUATION_RE = /^\s*└/;
@@ -29949,10 +30000,15 @@ var NativeTuiDriver = class {
29949
30000
  await this.agent.restart(resumeId, false);
29950
30001
  return resumeId;
29951
30002
  }
30003
+ const spawnedAt = this.now();
29952
30004
  await this.agent.spawn();
29953
- const id = this.agent.spawnedSessionId;
29954
- if (!id) throw new Error("NativeTuiDriver: agent did not expose a session id after spawn");
29955
- return id;
30005
+ const preMinted = this.agent.spawnedSessionId;
30006
+ if (preMinted) return preMinted;
30007
+ const discovered = await this.deps.runtime.discoverSessionId?.(this.deps.opts.cwd, {
30008
+ sinceMs: spawnedAt
30009
+ });
30010
+ if (discovered) return discovered;
30011
+ throw new Error("NativeTuiDriver: agent did not expose a session id after spawn");
29956
30012
  }
29957
30013
  async stop() {
29958
30014
  this.agent.kill();
@@ -33357,7 +33413,7 @@ function checkChokidar() {
33357
33413
  }
33358
33414
  async function doctor(args2 = []) {
33359
33415
  const json = args2.includes("--json");
33360
- const cliVersion = true ? "2.60.17" : "0.0.0-dev";
33416
+ const cliVersion = true ? "2.60.18" : "0.0.0-dev";
33361
33417
  const apiBase2 = resolveApiBaseUrl();
33362
33418
  const diagnosticId = (0, import_node_crypto11.randomUUID)();
33363
33419
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -33556,7 +33612,7 @@ async function completion(args2) {
33556
33612
  // src/commands/version.ts
33557
33613
  var import_picocolors15 = __toESM(require("picocolors"));
33558
33614
  function version2() {
33559
- const v = true ? "2.60.17" : "unknown";
33615
+ const v = true ? "2.60.18" : "unknown";
33560
33616
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
33561
33617
  }
33562
33618
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.60.17",
3
+ "version": "2.60.18",
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",