codeam-cli 2.60.17 → 2.60.19

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 +157 -57
  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.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.19" : "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.19",
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.19" ? { ideVersion: "2.60.19" } : {}
6936
6936
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6937
6937
  }
6938
6938
  /**
@@ -13601,6 +13601,8 @@ function detectCursorSelector(lines) {
13601
13601
  }
13602
13602
 
13603
13603
  // src/agents/cursor/runtime.ts
13604
+ var import_node_child_process10 = require("child_process");
13605
+ var UUID_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
13604
13606
  var CURSOR_CONTEXT_WINDOW = 2e5;
13605
13607
  var CURSOR_MODELS = [
13606
13608
  { id: "cursor-default", label: "Cursor (auto)", contextWindow: CURSOR_CONTEXT_WINDOW },
@@ -13622,12 +13624,54 @@ var CursorRuntimeStrategy = class {
13622
13624
  'Cursor Agent CLI ("cursor-agent") is not on PATH.\n Install Cursor (https://cursor.com/), enable its CLI plugin,\n then run `codeam pair` again.'
13623
13625
  );
13624
13626
  }
13625
- return this.os.buildLaunch(binary);
13627
+ const sessionId = this.mintChatId(binary);
13628
+ if (sessionId) {
13629
+ const launch2 = this.os.buildLaunch(binary, ["--resume", sessionId]);
13630
+ return { cmd: launch2.cmd, args: launch2.args, sessionId };
13631
+ }
13632
+ const launch = this.os.buildLaunch(binary);
13633
+ return { cmd: launch.cmd, args: launch.args };
13634
+ }
13635
+ /**
13636
+ * Pre-create an empty, resumable Cursor chat and return its id, or null on any
13637
+ * failure. `cursor-agent create-chat` prints a bare UUID and exits 0 (verified
13638
+ * on cursor-agent 2026.06.24). Synchronous + bounded so prepareLaunch stays a
13639
+ * single deterministic step; a timeout/parse failure just disables pre-mint.
13640
+ */
13641
+ mintChatId(binary) {
13642
+ try {
13643
+ const r = (0, import_node_child_process10.spawnSync)(binary, ["create-chat"], {
13644
+ encoding: "utf8",
13645
+ timeout: 2e4,
13646
+ stdio: ["ignore", "pipe", "pipe"]
13647
+ });
13648
+ if (r.status !== 0 || r.error) {
13649
+ log.warn("cursor", `create-chat failed (status=${r.status}) \u2014 baton id pre-mint skipped`);
13650
+ return null;
13651
+ }
13652
+ const id = (r.stdout ?? "").match(UUID_RE)?.[0] ?? null;
13653
+ if (!id) log.warn("cursor", "create-chat produced no chat id \u2014 baton id pre-mint skipped");
13654
+ return id;
13655
+ } catch (err) {
13656
+ log.warn("cursor", `create-chat threw: ${err instanceof Error ? err.message : String(err)}`);
13657
+ return null;
13658
+ }
13626
13659
  }
13627
13660
  /** Cursor mirrors Claude's `--resume <id>` flag for session resume. */
13628
13661
  resumeLaunchArgs(sessionId, _opts) {
13629
13662
  return ["--resume", sessionId];
13630
13663
  }
13664
+ /**
13665
+ * Resume as a COMPLETE relaunch (mirrors Claude). The initial spawn already
13666
+ * carries `--resume <preMintedId>` from {@link prepareLaunch}, so appending
13667
+ * `resumeLaunchArgs` onto `initialLaunch.args` would emit a duplicate
13668
+ * `--resume … --resume …`. Rebuild a clean `--resume <id>` launch instead.
13669
+ */
13670
+ prepareResumeLaunch(sessionId, opts) {
13671
+ const binary = this.os.findInPath("cursor-agent") ?? this.meta.binaryName;
13672
+ const launch = this.os.buildLaunch(binary, this.resumeLaunchArgs(sessionId, opts));
13673
+ return { cmd: launch.cmd, args: launch.args };
13674
+ }
13631
13675
  resolveHistoryDir(cwd) {
13632
13676
  return resolveHistoryDir3(cwd);
13633
13677
  }
@@ -13714,7 +13758,7 @@ function getCurrentUsage4(_historyDir) {
13714
13758
  }
13715
13759
 
13716
13760
  // src/agents/aider/link.ts
13717
- var import_node_child_process10 = require("child_process");
13761
+ var import_node_child_process11 = require("child_process");
13718
13762
 
13719
13763
  // src/agents/aider/local-token.ts
13720
13764
  var fs26 = __toESM(require("fs"));
@@ -13772,7 +13816,7 @@ function aiderLoginLauncher(os49) {
13772
13816
  console.error(
13773
13817
  "\n Aider has no interactive login flow.\n Set ANTHROPIC_API_KEY or OPENAI_API_KEY in your shell,\n or re-run `codeam link aider --api-key=<your-key>`.\n"
13774
13818
  );
13775
- return (0, import_node_child_process10.spawn)(os49.id === "win32" ? "cmd.exe" : "sh", os49.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
13819
+ return (0, import_node_child_process11.spawn)(os49.id === "win32" ? "cmd.exe" : "sh", os49.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
13776
13820
  stdio: "ignore"
13777
13821
  });
13778
13822
  }
@@ -13916,7 +13960,7 @@ var AiderRuntimeStrategy = class {
13916
13960
  var import_node_crypto5 = require("crypto");
13917
13961
 
13918
13962
  // src/agents/gemini/link.ts
13919
- var import_node_child_process11 = require("child_process");
13963
+ var import_node_child_process12 = require("child_process");
13920
13964
 
13921
13965
  // src/agents/gemini/local-token.ts
13922
13966
  var fs27 = __toESM(require("fs"));
@@ -13981,7 +14025,7 @@ function geminiLoginLauncher() {
13981
14025
  return os49.findInPath("gemini") !== null;
13982
14026
  },
13983
14027
  launch() {
13984
- return (0, import_node_child_process11.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
14028
+ return (0, import_node_child_process12.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
13985
14029
  }
13986
14030
  };
13987
14031
  }
@@ -14277,7 +14321,7 @@ var GeminiRuntimeStrategy = class {
14277
14321
  };
14278
14322
 
14279
14323
  // src/agents/kimi/runtime.ts
14280
- var import_node_child_process12 = require("child_process");
14324
+ var import_node_child_process13 = require("child_process");
14281
14325
  var import_node_os3 = require("os");
14282
14326
  var import_node_path4 = require("path");
14283
14327
 
@@ -14347,6 +14391,44 @@ function scanBucketsForSession(sessionId) {
14347
14391
  }
14348
14392
  return null;
14349
14393
  }
14394
+ async function discoverSessionId(cwd, opts) {
14395
+ const bucket = path33.join(kimiHome(), "sessions", workDirKey(cwd));
14396
+ const floor = opts.sinceMs - 2e3;
14397
+ const deadline = Date.now() + (opts.timeoutMs ?? 15e3);
14398
+ for (; ; ) {
14399
+ const id = newestSessionSince(bucket, floor);
14400
+ if (id) return id;
14401
+ if (Date.now() >= deadline) return null;
14402
+ await sleep2(250);
14403
+ }
14404
+ }
14405
+ function newestSessionSince(bucket, floorMs) {
14406
+ let entries;
14407
+ try {
14408
+ entries = fs29.readdirSync(bucket, { withFileTypes: true });
14409
+ } catch {
14410
+ return null;
14411
+ }
14412
+ let bestId = null;
14413
+ let bestMtime = -1;
14414
+ for (const e of entries) {
14415
+ if (!e.isDirectory() || !e.name.startsWith("session_")) continue;
14416
+ let mtime;
14417
+ try {
14418
+ mtime = fs29.statSync(path33.join(bucket, e.name)).mtimeMs;
14419
+ } catch {
14420
+ continue;
14421
+ }
14422
+ if (mtime >= floorMs && mtime > bestMtime) {
14423
+ bestMtime = mtime;
14424
+ bestId = e.name;
14425
+ }
14426
+ }
14427
+ return bestId;
14428
+ }
14429
+ function sleep2(ms) {
14430
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
14431
+ }
14350
14432
  function joinTextParts(parts) {
14351
14433
  if (!Array.isArray(parts)) return "";
14352
14434
  return parts.filter((p2) => p2 && p2.type === "text" && typeof p2.text === "string").map((p2) => p2.text).join("").trim();
@@ -14456,6 +14538,19 @@ var KimiRuntimeStrategy = class {
14456
14538
  parseHistoryFile(filePath) {
14457
14539
  return parseHistoryFile6(filePath);
14458
14540
  }
14541
+ /**
14542
+ * Kimi neither accepts a pre-set session id (`kimi -S <newid>` fails
14543
+ * "Session not found") NOR prints its id on stdout — it MINTS one itself and
14544
+ * writes it to `<KIMI_CODE_HOME>/sessions/wd_<key>/<sessionId>/` when the
14545
+ * native TUI boots. So `prepareLaunch` can't return a `sessionId` and the
14546
+ * baton's NativeTuiDriver has nothing to bind. This hook bounded-polls that
14547
+ * store for the dir kimi just created (mtime ≥ spawn time) and returns its id.
14548
+ * Kimi-specific — no other agent implements this (claude pre-mints; the rest
14549
+ * have no baton), so the driver's optional call is inert for them.
14550
+ */
14551
+ discoverSessionId(cwd, opts) {
14552
+ return discoverSessionId(cwd, opts);
14553
+ }
14459
14554
  getCurrentUsage(historyDir) {
14460
14555
  return getCurrentUsage5(historyDir);
14461
14556
  }
@@ -14516,7 +14611,7 @@ var KimiRuntimeStrategy = class {
14516
14611
  return createOsStrategy().findInPath("kimi") !== null;
14517
14612
  },
14518
14613
  launch() {
14519
- return (0, import_node_child_process12.spawn)("kimi", [], { stdio: "inherit" });
14614
+ return (0, import_node_child_process13.spawn)("kimi", [], { stdio: "inherit" });
14520
14615
  }
14521
14616
  };
14522
14617
  }
@@ -14949,7 +15044,7 @@ async function linkDryRunPreflight(ctx) {
14949
15044
  }
14950
15045
 
14951
15046
  // src/commands/host-agent.ts
14952
- var import_node_child_process20 = require("child_process");
15047
+ var import_node_child_process21 = require("child_process");
14953
15048
  var os34 = __toESM(require("os"));
14954
15049
  var fs40 = __toESM(require("fs"));
14955
15050
  var path42 = __toESM(require("path"));
@@ -14962,7 +15057,7 @@ var path35 = __toESM(require("path"));
14962
15057
  // src/lib/restrict-to-owner.ts
14963
15058
  var import_node_fs5 = __toESM(require("fs"));
14964
15059
  var import_node_os4 = __toESM(require("os"));
14965
- var import_node_child_process13 = require("child_process");
15060
+ var import_node_child_process14 = require("child_process");
14966
15061
  var BROAD_WINDOWS_SIDS = [
14967
15062
  "*S-1-1-0",
14968
15063
  "*S-1-5-11",
@@ -14974,7 +15069,7 @@ function restrictToOwner(filePath) {
14974
15069
  try {
14975
15070
  if (process.platform === "win32") {
14976
15071
  const username = import_node_os4.default.userInfo().username;
14977
- (0, import_node_child_process13.execFileSync)(
15072
+ (0, import_node_child_process14.execFileSync)(
14978
15073
  "icacls",
14979
15074
  [
14980
15075
  filePath,
@@ -15236,9 +15331,9 @@ async function reportDeployProgress(auth, deployId, step, message, sessionId) {
15236
15331
  var fs33 = __toESM(require("fs"));
15237
15332
  var os29 = __toESM(require("os"));
15238
15333
  var path36 = __toESM(require("path"));
15239
- var import_node_child_process14 = require("child_process");
15334
+ var import_node_child_process15 = require("child_process");
15240
15335
  var import_node_util4 = require("util");
15241
- var execFileP4 = (0, import_node_util4.promisify)(import_node_child_process14.execFile);
15336
+ var execFileP4 = (0, import_node_util4.promisify)(import_node_child_process15.execFile);
15242
15337
  function isAbsolutePathTarget(target) {
15243
15338
  return path36.isAbsolute(target);
15244
15339
  }
@@ -15508,7 +15603,7 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os30.homedir(
15508
15603
  }
15509
15604
 
15510
15605
  // src/commands/host/git-tooling.ts
15511
- var import_node_child_process15 = require("child_process");
15606
+ var import_node_child_process16 = require("child_process");
15512
15607
  var fs35 = __toESM(require("fs"));
15513
15608
  var os31 = __toESM(require("os"));
15514
15609
  var path38 = __toESM(require("path"));
@@ -15622,7 +15717,7 @@ var defaultGitToolingRunner = {
15622
15717
  which(cmd) {
15623
15718
  try {
15624
15719
  const probe = process.platform === "win32" ? "where" : "which";
15625
- (0, import_node_child_process15.execFileSync)(probe, [cmd], { stdio: "ignore" });
15720
+ (0, import_node_child_process16.execFileSync)(probe, [cmd], { stdio: "ignore" });
15626
15721
  return true;
15627
15722
  } catch {
15628
15723
  return false;
@@ -15630,7 +15725,7 @@ var defaultGitToolingRunner = {
15630
15725
  },
15631
15726
  run(cmd, args2, opts = {}) {
15632
15727
  return new Promise((resolve7) => {
15633
- const child = (0, import_node_child_process15.spawn)(cmd, args2, {
15728
+ const child = (0, import_node_child_process16.spawn)(cmd, args2, {
15634
15729
  stdio: [opts.input !== void 0 ? "pipe" : "ignore", "ignore", "pipe"]
15635
15730
  });
15636
15731
  let stderr = "";
@@ -15784,12 +15879,12 @@ var HeadroomStatsReporter = class {
15784
15879
  };
15785
15880
 
15786
15881
  // src/commands/host/os-packages.ts
15787
- var import_node_child_process16 = require("child_process");
15882
+ var import_node_child_process17 = require("child_process");
15788
15883
  var PM_INSTALL_TIMEOUT_MS = 18e4;
15789
15884
  var defaultHeadroomRunner = {
15790
15885
  which(cmd) {
15791
15886
  try {
15792
- (0, import_node_child_process16.execFileSync)("which", [cmd], { stdio: "ignore" });
15887
+ (0, import_node_child_process17.execFileSync)("which", [cmd], { stdio: "ignore" });
15793
15888
  return true;
15794
15889
  } catch {
15795
15890
  return false;
@@ -15798,7 +15893,7 @@ var defaultHeadroomRunner = {
15798
15893
  run(cmd, args2, opts = {}) {
15799
15894
  return new Promise((resolve7) => {
15800
15895
  const spawnEnv = opts.env ?? process.env;
15801
- const child = (0, import_node_child_process16.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"], env: spawnEnv });
15896
+ const child = (0, import_node_child_process17.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"], env: spawnEnv });
15802
15897
  let stderrBuf = "";
15803
15898
  let stdoutBuf = "";
15804
15899
  let settled = false;
@@ -16305,14 +16400,14 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
16305
16400
  }
16306
16401
 
16307
16402
  // src/commands/host/self-update.ts
16308
- var import_node_child_process18 = require("child_process");
16403
+ var import_node_child_process19 = require("child_process");
16309
16404
 
16310
16405
  // src/lib/updateNotifier.ts
16311
16406
  var fs38 = __toESM(require("fs"));
16312
16407
  var os33 = __toESM(require("os"));
16313
16408
  var path41 = __toESM(require("path"));
16314
16409
  var https6 = __toESM(require("https"));
16315
- var import_node_child_process17 = require("child_process");
16410
+ var import_node_child_process18 = require("child_process");
16316
16411
  var import_picocolors3 = __toESM(require("picocolors"));
16317
16412
  var PKG_NAME = "codeam-cli";
16318
16413
  var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
@@ -16406,7 +16501,7 @@ function notifyIfStale(currentVersion, latest) {
16406
16501
  }
16407
16502
  function isLinkedInstall() {
16408
16503
  try {
16409
- const root = (0, import_node_child_process17.execSync)("npm root -g", {
16504
+ const root = (0, import_node_child_process18.execSync)("npm root -g", {
16410
16505
  encoding: "utf8",
16411
16506
  stdio: ["ignore", "pipe", "ignore"],
16412
16507
  timeout: 2e3
@@ -16434,7 +16529,7 @@ function maybeAutoUpdate(currentVersion, latest) {
16434
16529
 
16435
16530
  `
16436
16531
  );
16437
- const install = (0, import_node_child_process17.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
16532
+ const install = (0, import_node_child_process18.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
16438
16533
  stdio: "inherit",
16439
16534
  env: process.env
16440
16535
  });
@@ -16455,7 +16550,7 @@ function maybeAutoUpdate(currentVersion, latest) {
16455
16550
  process.stderr.write(` ${import_picocolors3.default.green("\u2713")} Updated. Resuming session...
16456
16551
 
16457
16552
  `);
16458
- const child = (0, import_node_child_process17.spawnSync)("codeam", process.argv.slice(2), {
16553
+ const child = (0, import_node_child_process18.spawnSync)("codeam", process.argv.slice(2), {
16459
16554
  stdio: "inherit",
16460
16555
  env: process.env
16461
16556
  });
@@ -16465,7 +16560,7 @@ async function autoUpgradeBeforeCriticalCommand() {
16465
16560
  if (process.env.NODE_ENV === "test") return;
16466
16561
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16467
16562
  if (process.env.CI) return;
16468
- const current = true ? "2.60.17" : null;
16563
+ const current = true ? "2.60.19" : null;
16469
16564
  if (!current) return;
16470
16565
  const cache = readCache();
16471
16566
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16482,7 +16577,7 @@ function checkForUpdates() {
16482
16577
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16483
16578
  if (process.env.CI) return;
16484
16579
  if (!process.stdout.isTTY) return;
16485
- const current = true ? "2.60.17" : null;
16580
+ const current = true ? "2.60.19" : null;
16486
16581
  if (!current) return;
16487
16582
  const cache = readCache();
16488
16583
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16502,11 +16597,11 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
16502
16597
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
16503
16598
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
16504
16599
  function currentCliVersion() {
16505
- return true ? "2.60.17" : null;
16600
+ return true ? "2.60.19" : null;
16506
16601
  }
16507
16602
  function runCmd(cmd, args2, timeoutMs) {
16508
16603
  return new Promise((resolve7) => {
16509
- (0, import_node_child_process18.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
16604
+ (0, import_node_child_process19.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
16510
16605
  const code = err && typeof err.code === "number" ? err.code : err ? null : 0;
16511
16606
  resolve7({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
16512
16607
  });
@@ -16568,11 +16663,11 @@ async function runSelfUpdate() {
16568
16663
  }
16569
16664
 
16570
16665
  // src/commands/host/teardown.ts
16571
- var import_node_child_process19 = require("child_process");
16666
+ var import_node_child_process20 = require("child_process");
16572
16667
  var fs39 = __toESM(require("fs"));
16573
16668
  var defaultDisableService = () => {
16574
16669
  try {
16575
- (0, import_node_child_process19.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
16670
+ (0, import_node_child_process20.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
16576
16671
  } catch {
16577
16672
  }
16578
16673
  };
@@ -16580,7 +16675,7 @@ var defaultTeardownHeadroom = () => {
16580
16675
  try {
16581
16676
  const kind = JSON.parse(fs39.readFileSync(headroomConfigPath(), "utf8")).agent;
16582
16677
  if (kind) {
16583
- (0, import_node_child_process19.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
16678
+ (0, import_node_child_process20.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
16584
16679
  }
16585
16680
  } catch {
16586
16681
  }
@@ -16738,7 +16833,7 @@ var CONTROL_AGENT_META = {
16738
16833
  headroomWrappable: false,
16739
16834
  acp: false
16740
16835
  };
16741
- var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process20.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
16836
+ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process21.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
16742
16837
  cwd,
16743
16838
  env: { ...process.env, ...env },
16744
16839
  stdio: ["ignore", "pipe", "pipe"],
@@ -17218,7 +17313,7 @@ var HostAgentSupervisor = class {
17218
17313
  runAgentInstall(script) {
17219
17314
  return new Promise((resolve7) => {
17220
17315
  const home = process.env.HOME || os34.homedir();
17221
- const child = (0, import_node_child_process20.spawn)("sh", ["-c", script], {
17316
+ const child = (0, import_node_child_process21.spawn)("sh", ["-c", script], {
17222
17317
  env: { ...process.env, HOME: home },
17223
17318
  stdio: ["ignore", "pipe", "pipe"]
17224
17319
  });
@@ -21624,7 +21719,7 @@ async function pairAuto(args2) {
21624
21719
  }
21625
21720
 
21626
21721
  // src/services/headroom/wrap-launch.ts
21627
- var import_node_child_process21 = require("child_process");
21722
+ var import_node_child_process22 = require("child_process");
21628
21723
  function wrapWithHeadroom(launch, opts) {
21629
21724
  if (!opts.enabled || !opts.headroomPresent) return launch;
21630
21725
  return {
@@ -21637,7 +21732,7 @@ var _present;
21637
21732
  function headroomPresent() {
21638
21733
  if (_present !== void 0) return Promise.resolve(_present);
21639
21734
  return new Promise((resolve7) => {
21640
- (0, import_node_child_process21.execFile)("headroom", ["--version"], (err) => {
21735
+ (0, import_node_child_process22.execFile)("headroom", ["--version"], (err) => {
21641
21736
  _present = !err;
21642
21737
  resolve7(_present);
21643
21738
  });
@@ -22034,7 +22129,7 @@ async function waitForClaudeNativeBinary(opts = {}) {
22034
22129
  const timeoutMs = opts.timeoutMs ?? 18e4;
22035
22130
  const pollMs = opts.pollMs ?? 500;
22036
22131
  const now = opts.now ?? Date.now;
22037
- const sleep3 = opts.sleep ?? realSleep;
22132
+ const sleep4 = opts.sleep ?? realSleep;
22038
22133
  const deps = {
22039
22134
  sdkDir: opts.sdkDir,
22040
22135
  platformKey: opts.platformKey,
@@ -22044,7 +22139,7 @@ async function waitForClaudeNativeBinary(opts = {}) {
22044
22139
  let found = resolveClaudeNativeBinary(deps);
22045
22140
  if (found) return found;
22046
22141
  while (now() < deadline) {
22047
- await sleep3(pollMs);
22142
+ await sleep4(pollMs);
22048
22143
  found = resolveClaudeNativeBinary(deps);
22049
22144
  if (found) return found;
22050
22145
  }
@@ -22066,13 +22161,13 @@ async function waitForCommandOnPath(cmd, opts = {}) {
22066
22161
  const timeoutMs = opts.timeoutMs ?? 18e4;
22067
22162
  const pollMs = opts.pollMs ?? 500;
22068
22163
  const now = opts.now ?? Date.now;
22069
- const sleep3 = opts.sleep ?? realSleep;
22164
+ const sleep4 = opts.sleep ?? realSleep;
22070
22165
  const probe = opts.probe;
22071
22166
  const check = () => isCommandOnPath(cmd, probe);
22072
22167
  const deadline = now() + timeoutMs;
22073
22168
  if (check()) return true;
22074
22169
  while (now() < deadline) {
22075
- await sleep3(pollMs);
22170
+ await sleep4(pollMs);
22076
22171
  if (check()) return true;
22077
22172
  }
22078
22173
  return check();
@@ -22095,12 +22190,12 @@ async function waitForCursorAgent(opts = {}) {
22095
22190
  const timeoutMs = opts.timeoutMs ?? 18e4;
22096
22191
  const pollMs = opts.pollMs ?? 500;
22097
22192
  const now = opts.now ?? Date.now;
22098
- const sleep3 = opts.sleep ?? realSleep;
22193
+ const sleep4 = opts.sleep ?? realSleep;
22099
22194
  const check = () => resolveCursorAgentBinary(opts) !== null || isCommandOnPath("cursor-agent", opts.probe);
22100
22195
  const deadline = now() + timeoutMs;
22101
22196
  if (check()) return true;
22102
22197
  while (now() < deadline) {
22103
- await sleep3(pollMs);
22198
+ await sleep4(pollMs);
22104
22199
  if (check()) return true;
22105
22200
  }
22106
22201
  return check();
@@ -22149,19 +22244,19 @@ async function waitForAdapterModuleGraph(command2, args2, opts = {}) {
22149
22244
  const timeoutMs = opts.timeoutMs ?? 18e4;
22150
22245
  const pollMs = opts.pollMs ?? 500;
22151
22246
  const now = opts.now ?? Date.now;
22152
- const sleep3 = opts.sleep ?? realSleep;
22247
+ const sleep4 = opts.sleep ?? realSleep;
22153
22248
  const probeOpts = { livenessMs: opts.livenessMs, spawnFn: opts.spawnFn };
22154
22249
  const deadline = now() + timeoutMs;
22155
22250
  if (await probeAdapterModuleGraph(command2, args2, probeOpts) === "ok") return true;
22156
22251
  while (now() < deadline) {
22157
- await sleep3(pollMs);
22252
+ await sleep4(pollMs);
22158
22253
  if (await probeAdapterModuleGraph(command2, args2, probeOpts) === "ok") return true;
22159
22254
  }
22160
22255
  return false;
22161
22256
  }
22162
22257
 
22163
22258
  // src/agents/kimi/installer.ts
22164
- var import_node_child_process22 = require("child_process");
22259
+ var import_node_child_process23 = require("child_process");
22165
22260
  var import_node_os6 = require("os");
22166
22261
  var import_node_path6 = require("path");
22167
22262
  var INSTALL_URL2 = "https://code.kimi.com/kimi-code/install.sh";
@@ -22169,7 +22264,7 @@ function kimiBinDir() {
22169
22264
  return (0, import_node_path6.join)(process.env.KIMI_CODE_HOME || (0, import_node_path6.join)((0, import_node_os6.homedir)(), ".kimi-code"), "bin");
22170
22265
  }
22171
22266
  function kimiRuns() {
22172
- const r = (0, import_node_child_process22.spawnSync)("kimi", ["--version"], { stdio: "ignore", timeout: 15e3 });
22267
+ const r = (0, import_node_child_process23.spawnSync)("kimi", ["--version"], { stdio: "ignore", timeout: 15e3 });
22173
22268
  return !r.error && r.status === 0;
22174
22269
  }
22175
22270
  function augmentPath2() {
@@ -22179,7 +22274,7 @@ function augmentPath2() {
22179
22274
  }
22180
22275
  async function runInstaller2() {
22181
22276
  return new Promise((resolve7) => {
22182
- const proc = (0, import_node_child_process22.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL2} | bash`], { stdio: "inherit" });
22277
+ const proc = (0, import_node_child_process23.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL2} | bash`], { stdio: "inherit" });
22183
22278
  proc.on("close", (code) => resolve7(code === 0));
22184
22279
  proc.on("error", () => resolve7(false));
22185
22280
  });
@@ -22916,7 +23011,7 @@ var HistoryService = class _HistoryService {
22916
23011
  };
22917
23012
 
22918
23013
  // src/agents/acp/client.ts
22919
- var import_node_child_process23 = require("child_process");
23014
+ var import_node_child_process24 = require("child_process");
22920
23015
  var fs56 = __toESM(require("fs/promises"));
22921
23016
  var fsSync = __toESM(require("fs"));
22922
23017
  var os45 = __toESM(require("os"));
@@ -25520,7 +25615,7 @@ var AcpClient = class {
25520
25615
  "acpClient",
25521
25616
  `spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
25522
25617
  );
25523
- const child = (0, import_node_child_process23.spawn)(adapter.command, adapter.args, {
25618
+ const child = (0, import_node_child_process24.spawn)(adapter.command, adapter.args, {
25524
25619
  cwd,
25525
25620
  // extraEnv (e.g. CLAUDE_CODE_DISABLE_1M_CONTEXT=1 on an on-demand
25526
25621
  // re-spawn) layers over process.env; PATH stays last so the augmented
@@ -29762,12 +29857,12 @@ var StreamingEmitterService = class {
29762
29857
  log.warn("streamingEmitter", `post error url=${url} attempt=${attempt + 1}`, err);
29763
29858
  }
29764
29859
  if (attempt < MAX_RETRIES2) {
29765
- await sleep2(RETRY_BACKOFF_MS3 * (attempt + 1));
29860
+ await sleep3(RETRY_BACKOFF_MS3 * (attempt + 1));
29766
29861
  }
29767
29862
  }
29768
29863
  }
29769
29864
  };
29770
- function sleep2(ms) {
29865
+ function sleep3(ms) {
29771
29866
  return new Promise((r) => setTimeout(r, ms));
29772
29867
  }
29773
29868
  var TREE_CONTINUATION_RE = /^\s*└/;
@@ -29949,10 +30044,15 @@ var NativeTuiDriver = class {
29949
30044
  await this.agent.restart(resumeId, false);
29950
30045
  return resumeId;
29951
30046
  }
30047
+ const spawnedAt = this.now();
29952
30048
  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;
30049
+ const preMinted = this.agent.spawnedSessionId;
30050
+ if (preMinted) return preMinted;
30051
+ const discovered = await this.deps.runtime.discoverSessionId?.(this.deps.opts.cwd, {
30052
+ sinceMs: spawnedAt
30053
+ });
30054
+ if (discovered) return discovered;
30055
+ throw new Error("NativeTuiDriver: agent did not expose a session id after spawn");
29956
30056
  }
29957
30057
  async stop() {
29958
30058
  this.agent.kill();
@@ -33357,7 +33457,7 @@ function checkChokidar() {
33357
33457
  }
33358
33458
  async function doctor(args2 = []) {
33359
33459
  const json = args2.includes("--json");
33360
- const cliVersion = true ? "2.60.17" : "0.0.0-dev";
33460
+ const cliVersion = true ? "2.60.19" : "0.0.0-dev";
33361
33461
  const apiBase2 = resolveApiBaseUrl();
33362
33462
  const diagnosticId = (0, import_node_crypto11.randomUUID)();
33363
33463
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -33556,7 +33656,7 @@ async function completion(args2) {
33556
33656
  // src/commands/version.ts
33557
33657
  var import_picocolors15 = __toESM(require("picocolors"));
33558
33658
  function version2() {
33559
- const v = true ? "2.60.17" : "unknown";
33659
+ const v = true ? "2.60.19" : "unknown";
33560
33660
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
33561
33661
  }
33562
33662
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.60.17",
3
+ "version": "2.60.19",
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",