codeam-cli 2.60.8 → 2.60.10

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 +587 -417
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -751,11 +751,11 @@ function quiet(fn) {
751
751
  log.debug(TAG, "ignored sync error", err);
752
752
  }
753
753
  }
754
- function rmIfExistsQuiet(path68) {
754
+ function rmIfExistsQuiet(path69) {
755
755
  try {
756
- fs2.rmSync(path68, { force: true });
756
+ fs2.rmSync(path69, { force: true });
757
757
  } catch (err) {
758
- log.debug(TAG, `rmIfExists failed for ${path68}`, err);
758
+ log.debug(TAG, `rmIfExists failed for ${path69}`, err);
759
759
  }
760
760
  }
761
761
  function killQuiet(target, signal = "SIGTERM") {
@@ -901,9 +901,9 @@ var _default = makeConfig();
901
901
  var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, setDisable1mContext, clearAll, saveCliConfig, loadCliConfig } = _default;
902
902
 
903
903
  // src/commands/pair-auto.ts
904
- var fs51 = __toESM(require("fs"));
905
- var os40 = __toESM(require("os"));
906
- var path54 = __toESM(require("path"));
904
+ var fs52 = __toESM(require("fs"));
905
+ var os41 = __toESM(require("os"));
906
+ var path55 = __toESM(require("path"));
907
907
  var import_crypto4 = require("crypto");
908
908
 
909
909
  // src/services/telemetry.service.ts
@@ -939,8 +939,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
939
939
  return decodedFile;
940
940
  };
941
941
  }
942
- function normalizeWindowsPath(path68) {
943
- return path68.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
942
+ function normalizeWindowsPath(path69) {
943
+ return path69.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
944
944
  }
945
945
 
946
946
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -3420,9 +3420,9 @@ async function addSourceContext(frames) {
3420
3420
  LRU_FILE_CONTENTS_CACHE.reduce();
3421
3421
  return frames;
3422
3422
  }
3423
- function getContextLinesFromFile(path68, ranges, output) {
3423
+ function getContextLinesFromFile(path69, ranges, output) {
3424
3424
  return new Promise((resolve7) => {
3425
- const stream = (0, import_node_fs.createReadStream)(path68);
3425
+ const stream = (0, import_node_fs.createReadStream)(path69);
3426
3426
  const lineReaded = (0, import_node_readline.createInterface)({
3427
3427
  input: stream
3428
3428
  });
@@ -3437,7 +3437,7 @@ function getContextLinesFromFile(path68, ranges, output) {
3437
3437
  let rangeStart = range[0];
3438
3438
  let rangeEnd = range[1];
3439
3439
  function onStreamError() {
3440
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path68, 1);
3440
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path69, 1);
3441
3441
  lineReaded.close();
3442
3442
  lineReaded.removeAllListeners();
3443
3443
  destroyStreamAndResolve();
@@ -3498,8 +3498,8 @@ function clearLineContext(frame) {
3498
3498
  delete frame.context_line;
3499
3499
  delete frame.post_context;
3500
3500
  }
3501
- function shouldSkipContextLinesForFile(path68) {
3502
- return path68.startsWith("node:") || path68.endsWith(".min.js") || path68.endsWith(".min.cjs") || path68.endsWith(".min.mjs") || path68.startsWith("data:");
3501
+ function shouldSkipContextLinesForFile(path69) {
3502
+ return path69.startsWith("node:") || path69.endsWith(".min.js") || path69.endsWith(".min.cjs") || path69.endsWith(".min.mjs") || path69.startsWith("data:");
3503
3503
  }
3504
3504
  function shouldSkipContextLinesForFrame(frame) {
3505
3505
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -5653,7 +5653,7 @@ function readAnonId() {
5653
5653
  }
5654
5654
  function superProperties() {
5655
5655
  return {
5656
- cliVersion: true ? "2.60.8" : "0.0.0-dev",
5656
+ cliVersion: true ? "2.60.10" : "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.8",
5837
+ version: "2.60.10",
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.8" ? { ideVersion: "2.60.8" } : {}
6908
+ ..."2.60.10" ? { ideVersion: "2.60.10" } : {}
6909
6909
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
6910
6910
  }
6911
6911
  /**
@@ -7132,10 +7132,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
7132
7132
  /[\\/]Start Menu([\\/]|$)/i,
7133
7133
  /[\\/]Templates([\\/]|$)/i
7134
7134
  ];
7135
- function isUnsafeWindowsWatchRoot(dir, homedir37) {
7135
+ function isUnsafeWindowsWatchRoot(dir, homedir38) {
7136
7136
  const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
7137
7137
  const cwd = norm(dir);
7138
- const home = norm(homedir37);
7138
+ const home = norm(homedir38);
7139
7139
  if (cwd === home) return true;
7140
7140
  if (/^[a-z]:$/.test(cwd)) return true;
7141
7141
  const sysRoots = [
@@ -8279,9 +8279,9 @@ function closeAllTerminals() {
8279
8279
  }
8280
8280
 
8281
8281
  // src/commands/start/handlers.ts
8282
- var fs50 = __toESM(require("fs"));
8283
- var os39 = __toESM(require("os"));
8284
- var path53 = __toESM(require("path"));
8282
+ var fs51 = __toESM(require("fs"));
8283
+ var os40 = __toESM(require("os"));
8284
+ var path54 = __toESM(require("path"));
8285
8285
  var import_crypto3 = require("crypto");
8286
8286
  var import_child_process23 = require("child_process");
8287
8287
 
@@ -9062,9 +9062,9 @@ function findGitRoot2(startDir) {
9062
9062
  }
9063
9063
 
9064
9064
  // src/commands/link.ts
9065
- var import_node_crypto5 = require("crypto");
9066
- var fs28 = __toESM(require("fs"));
9067
- var path32 = __toESM(require("path"));
9065
+ var import_node_crypto6 = require("crypto");
9066
+ var fs29 = __toESM(require("fs"));
9067
+ var path33 = __toESM(require("path"));
9068
9068
  var import_chokidar = __toESM(require("chokidar"));
9069
9069
  var import_picocolors2 = __toESM(require("picocolors"));
9070
9070
 
@@ -11711,10 +11711,10 @@ function buildForPlatform(platform3) {
11711
11711
  var import_node_crypto4 = require("crypto");
11712
11712
 
11713
11713
  // src/agents/claude/resolver.ts
11714
- function buildClaudeLaunch(extraArgs = [], os47 = createOsStrategy()) {
11715
- const found = os47.findInPath("claude") ?? os47.findInPath("claude-code");
11714
+ function buildClaudeLaunch(extraArgs = [], os48 = createOsStrategy()) {
11715
+ const found = os48.findInPath("claude") ?? os48.findInPath("claude-code");
11716
11716
  if (!found) return null;
11717
- return os47.buildLaunch(found, extraArgs);
11717
+ return os48.buildLaunch(found, extraArgs);
11718
11718
  }
11719
11719
 
11720
11720
  // src/agents/claude/installer.ts
@@ -12304,8 +12304,8 @@ var ClaudeRuntimeStrategy = class {
12304
12304
  meta = getAgent("claude");
12305
12305
  mode = "interactive";
12306
12306
  os;
12307
- constructor(os47) {
12308
- this.os = os47;
12307
+ constructor(os48) {
12308
+ this.os = os48;
12309
12309
  }
12310
12310
  /**
12311
12311
  * Claude Code's react-ink TUI enables bracketed-paste mode at
@@ -13004,8 +13004,8 @@ function codexCredentialLocator() {
13004
13004
  function codexLoginLauncher() {
13005
13005
  return {
13006
13006
  async ensureInstalled() {
13007
- const os47 = createOsStrategy();
13008
- return os47.findInPath("codex") !== null;
13007
+ const os48 = createOsStrategy();
13008
+ return os48.findInPath("codex") !== null;
13009
13009
  },
13010
13010
  launch() {
13011
13011
  return (0, import_node_child_process4.spawn)("codex", ["login"], { stdio: "inherit" });
@@ -13028,8 +13028,8 @@ var CodexRuntimeStrategy = class {
13028
13028
  meta = getAgent("codex");
13029
13029
  mode = "interactive";
13030
13030
  os;
13031
- constructor(os47) {
13032
- this.os = os47;
13031
+ constructor(os48) {
13032
+ this.os = os48;
13033
13033
  }
13034
13034
  async prepareLaunch() {
13035
13035
  let binary = this.os.findInPath("codex");
@@ -13128,12 +13128,12 @@ var CodexRuntimeStrategy = class {
13128
13128
  });
13129
13129
  }
13130
13130
  };
13131
- function resolveNpm(os47) {
13132
- return os47.id === "win32" ? "npm.cmd" : "npm";
13131
+ function resolveNpm(os48) {
13132
+ return os48.id === "win32" ? "npm.cmd" : "npm";
13133
13133
  }
13134
- async function installCodexViaNpm(os47) {
13134
+ async function installCodexViaNpm(os48) {
13135
13135
  return new Promise((resolve7, reject) => {
13136
- const proc = (0, import_node_child_process5.spawn)(resolveNpm(os47), ["install", "-g", "@openai/codex"], {
13136
+ const proc = (0, import_node_child_process5.spawn)(resolveNpm(os48), ["install", "-g", "@openai/codex"], {
13137
13137
  stdio: "inherit"
13138
13138
  });
13139
13139
  proc.on("close", (code) => {
@@ -13150,16 +13150,16 @@ async function installCodexViaNpm(os47) {
13150
13150
  });
13151
13151
  });
13152
13152
  }
13153
- function augmentNpmGlobalBin(os47) {
13153
+ function augmentNpmGlobalBin(os48) {
13154
13154
  try {
13155
- const result = (0, import_node_child_process5.spawnSync)(resolveNpm(os47), ["prefix", "-g"], {
13155
+ const result = (0, import_node_child_process5.spawnSync)(resolveNpm(os48), ["prefix", "-g"], {
13156
13156
  stdio: ["ignore", "pipe", "ignore"]
13157
13157
  });
13158
13158
  if (result.status !== 0) return;
13159
13159
  const prefix = result.stdout.toString().trim();
13160
13160
  if (!prefix) return;
13161
- const binDir = os47.id === "win32" ? prefix : path24.join(prefix, "bin");
13162
- os47.augmentPath([binDir]);
13161
+ const binDir = os48.id === "win32" ? prefix : path24.join(prefix, "bin");
13162
+ os48.augmentPath([binDir]);
13163
13163
  } catch {
13164
13164
  }
13165
13165
  }
@@ -13243,9 +13243,9 @@ var import_node_child_process8 = require("child_process");
13243
13243
  // src/agents/coderabbit/installer.ts
13244
13244
  var import_node_child_process6 = require("child_process");
13245
13245
  var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
13246
- async function ensureCoderabbitInstalled(os47) {
13247
- if (os47.findInPath("coderabbit")) return true;
13248
- if (os47.id === "win32") {
13246
+ async function ensureCoderabbitInstalled(os48) {
13247
+ if (os48.findInPath("coderabbit")) return true;
13248
+ if (os48.id === "win32") {
13249
13249
  console.error(
13250
13250
  "\n \u2717 CodeRabbit on Windows requires WSL.\n Install the CLI inside your WSL distribution\n (curl -fsSL https://cli.coderabbit.ai/install.sh | sh)\n then re-run `codeam link coderabbit` from WSL.\n"
13251
13251
  );
@@ -13260,8 +13260,8 @@ async function ensureCoderabbitInstalled(os47) {
13260
13260
  proc.on("error", () => resolve7(false));
13261
13261
  });
13262
13262
  if (!ok) return false;
13263
- os47.augmentPath([`${os47.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
13264
- return os47.findInPath("coderabbit") !== null;
13263
+ os48.augmentPath([`${os48.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
13264
+ return os48.findInPath("coderabbit") !== null;
13265
13265
  }
13266
13266
 
13267
13267
  // src/agents/coderabbit/link.ts
@@ -13296,10 +13296,10 @@ function coderabbitCredentialLocator() {
13296
13296
  validate: validateNonEmptyCredential
13297
13297
  };
13298
13298
  }
13299
- function coderabbitLoginLauncher(os47) {
13299
+ function coderabbitLoginLauncher(os48) {
13300
13300
  return {
13301
13301
  async ensureInstalled() {
13302
- return ensureCoderabbitInstalled(os47);
13302
+ return ensureCoderabbitInstalled(os48);
13303
13303
  },
13304
13304
  launch() {
13305
13305
  return (0, import_node_child_process7.spawn)("coderabbit", ["login"], { stdio: "inherit" });
@@ -13322,11 +13322,11 @@ function parseReview(stdout) {
13322
13322
  for (const line of lines) {
13323
13323
  const m = line.match(HUNK_LINE_RE);
13324
13324
  if (!m) continue;
13325
- const [, path68, lineNo, sevToken, message] = m;
13326
- if (!path68 || !lineNo || !message) continue;
13325
+ const [, path69, lineNo, sevToken, message] = m;
13326
+ if (!path69 || !lineNo || !message) continue;
13327
13327
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
13328
13328
  hunks.push({
13329
- path: path68.trim(),
13329
+ path: path69.trim(),
13330
13330
  line: Number(lineNo),
13331
13331
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
13332
13332
  message: cleanedMessage
@@ -13345,8 +13345,8 @@ var CoderabbitRuntimeStrategy = class {
13345
13345
  meta = getAgent("coderabbit");
13346
13346
  mode = "batch";
13347
13347
  os;
13348
- constructor(os47) {
13349
- this.os = os47;
13348
+ constructor(os48) {
13349
+ this.os = os48;
13350
13350
  }
13351
13351
  getDefaultArgs() {
13352
13352
  return ["review"];
@@ -13520,10 +13520,10 @@ function cursorCredentialLocator() {
13520
13520
  validate: validateNonEmptyCredential
13521
13521
  };
13522
13522
  }
13523
- function cursorLoginLauncher(os47) {
13523
+ function cursorLoginLauncher(os48) {
13524
13524
  return {
13525
13525
  async ensureInstalled() {
13526
- if (os47.findInPath("cursor-agent")) return true;
13526
+ if (os48.findInPath("cursor-agent")) return true;
13527
13527
  console.error(
13528
13528
  "\n \u2717 cursor-agent binary not on PATH.\n Install Cursor (https://cursor.com/) and ensure the CLI\n plugin is enabled, then re-run `codeam link cursor`.\n"
13529
13529
  );
@@ -13585,8 +13585,8 @@ var CursorRuntimeStrategy = class {
13585
13585
  meta = getAgent("cursor");
13586
13586
  mode = "interactive";
13587
13587
  os;
13588
- constructor(os47) {
13589
- this.os = os47;
13588
+ constructor(os48) {
13589
+ this.os = os48;
13590
13590
  }
13591
13591
  async prepareLaunch() {
13592
13592
  const binary = this.os.findInPath("cursor-agent");
@@ -13732,10 +13732,10 @@ function aiderCredentialLocator() {
13732
13732
  validate: validateNonEmptyCredential
13733
13733
  };
13734
13734
  }
13735
- function aiderLoginLauncher(os47) {
13735
+ function aiderLoginLauncher(os48) {
13736
13736
  return {
13737
13737
  async ensureInstalled() {
13738
- if (os47.findInPath("aider")) return true;
13738
+ if (os48.findInPath("aider")) return true;
13739
13739
  console.error(
13740
13740
  "\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
13741
13741
  );
@@ -13745,7 +13745,7 @@ function aiderLoginLauncher(os47) {
13745
13745
  console.error(
13746
13746
  "\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"
13747
13747
  );
13748
- return (0, import_node_child_process10.spawn)(os47.id === "win32" ? "cmd.exe" : "sh", os47.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
13748
+ return (0, import_node_child_process10.spawn)(os48.id === "win32" ? "cmd.exe" : "sh", os48.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
13749
13749
  stdio: "ignore"
13750
13750
  });
13751
13751
  }
@@ -13817,8 +13817,8 @@ var AiderRuntimeStrategy = class {
13817
13817
  meta = getAgent("aider");
13818
13818
  mode = "interactive";
13819
13819
  os;
13820
- constructor(os47) {
13821
- this.os = os47;
13820
+ constructor(os48) {
13821
+ this.os = os48;
13822
13822
  }
13823
13823
  async prepareLaunch() {
13824
13824
  const binary = this.os.findInPath("aider");
@@ -13885,6 +13885,9 @@ var AiderRuntimeStrategy = class {
13885
13885
  }
13886
13886
  };
13887
13887
 
13888
+ // src/agents/gemini/runtime.ts
13889
+ var import_node_crypto5 = require("crypto");
13890
+
13888
13891
  // src/agents/gemini/link.ts
13889
13892
  var import_node_child_process11 = require("child_process");
13890
13893
 
@@ -13947,8 +13950,8 @@ function geminiCredentialLocator() {
13947
13950
  function geminiLoginLauncher() {
13948
13951
  return {
13949
13952
  async ensureInstalled() {
13950
- const os47 = createOsStrategy();
13951
- return os47.findInPath("gemini") !== null;
13953
+ const os48 = createOsStrategy();
13954
+ return os48.findInPath("gemini") !== null;
13952
13955
  },
13953
13956
  launch() {
13954
13957
  return (0, import_node_child_process11.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
@@ -13956,6 +13959,163 @@ function geminiLoginLauncher() {
13956
13959
  };
13957
13960
  }
13958
13961
 
13962
+ // src/agents/gemini/history.ts
13963
+ var fs28 = __toESM(require("fs"));
13964
+ var os25 = __toESM(require("os"));
13965
+ var path32 = __toESM(require("path"));
13966
+ var GEMINI_ROOT = path32.join(os25.homedir(), ".gemini");
13967
+ function projectNameForCwd(cwd, root) {
13968
+ try {
13969
+ const parsed = JSON.parse(
13970
+ fs28.readFileSync(path32.join(root, "projects.json"), "utf8")
13971
+ );
13972
+ const map = parsed.projects;
13973
+ if (map && typeof map === "object") {
13974
+ if (typeof map[cwd] === "string") return map[cwd];
13975
+ try {
13976
+ const rp = fs28.realpathSync(cwd);
13977
+ if (typeof map[rp] === "string") return map[rp];
13978
+ } catch {
13979
+ }
13980
+ }
13981
+ log.debug("gemini", `projects.json has no entry for cwd=${cwd} \u2014 using basename fallback`);
13982
+ } catch (err) {
13983
+ log.debug("gemini", `projects.json unreadable at ${root} \u2014 using basename fallback`, err);
13984
+ }
13985
+ return path32.basename(cwd) || null;
13986
+ }
13987
+ function resolveHistoryDir5(cwd, root = GEMINI_ROOT) {
13988
+ const name = projectNameForCwd(cwd, root);
13989
+ if (!name) {
13990
+ log.warn("gemini", `resolveHistoryDir \u2014 could not derive a project name for cwd=${cwd}`);
13991
+ return null;
13992
+ }
13993
+ const dir = path32.join(root, "tmp", name, "chats");
13994
+ if (!fs28.existsSync(dir)) {
13995
+ log.debug("gemini", `resolveHistoryDir \u2014 chats dir not present yet: ${dir} (project=${name})`);
13996
+ return null;
13997
+ }
13998
+ return dir;
13999
+ }
14000
+ function resolveHistoryFile4(cwd, sessionId, root = GEMINI_ROOT) {
14001
+ const id8 = sessionId.slice(0, 8);
14002
+ const dir = resolveHistoryDir5(cwd, root);
14003
+ if (!dir) return null;
14004
+ let files;
14005
+ try {
14006
+ files = fs28.readdirSync(dir).filter((f) => f.startsWith("session-") && f.endsWith(".jsonl"));
14007
+ } catch (err) {
14008
+ log.warn("gemini", `resolveHistoryFile \u2014 cannot read chats dir ${dir} (id8=${id8})`, err);
14009
+ return null;
14010
+ }
14011
+ if (files.length === 0) {
14012
+ log.debug("gemini", `resolveHistoryFile \u2014 no session-*.jsonl yet in ${dir} (id8=${id8})`);
14013
+ return null;
14014
+ }
14015
+ const byName = files.find((f) => id8.length > 0 && f.includes(id8));
14016
+ if (byName) {
14017
+ log.info("gemini", `resolveHistoryFile \u2014 matched by filename id8=${id8}: ${byName}`);
14018
+ return path32.join(dir, byName);
14019
+ }
14020
+ for (const f of files) {
14021
+ const full = path32.join(dir, f);
14022
+ try {
14023
+ const firstLine = fs28.readFileSync(full, "utf8").split("\n", 1)[0] ?? "";
14024
+ const hdr = JSON.parse(firstLine);
14025
+ if (hdr.sessionId === sessionId) {
14026
+ log.info("gemini", `resolveHistoryFile \u2014 matched by header sessionId: ${f}`);
14027
+ return full;
14028
+ }
14029
+ } catch (err) {
14030
+ log.debug("gemini", `resolveHistoryFile \u2014 unreadable/non-JSON header in ${f}`, err);
14031
+ }
14032
+ }
14033
+ let newest = null;
14034
+ for (const f of files) {
14035
+ try {
14036
+ const mtime = fs28.statSync(path32.join(dir, f)).mtimeMs;
14037
+ if (!newest || mtime > newest.mtime) newest = { file: f, mtime };
14038
+ } catch {
14039
+ }
14040
+ }
14041
+ log.warn(
14042
+ "gemini",
14043
+ `resolveHistoryFile \u2014 no id8=${id8} match among ${files.length} file(s) in ${dir}; falling back to newest=${newest?.file ?? "none"}`
14044
+ );
14045
+ return newest ? path32.join(dir, newest.file) : null;
14046
+ }
14047
+ function extractGeminiText(content) {
14048
+ const fromParts = (arr) => Array.isArray(arr) ? arr.map((p2) => {
14049
+ const part = p2;
14050
+ return typeof part?.text === "string" ? part.text : "";
14051
+ }).join("") : null;
14052
+ const parts = fromParts(content);
14053
+ if (parts !== null) return parts;
14054
+ if (typeof content === "string") {
14055
+ const trimmed = content.trim();
14056
+ if (trimmed.startsWith("[")) {
14057
+ try {
14058
+ const asParts = fromParts(JSON.parse(trimmed));
14059
+ if (asParts !== null) return asParts;
14060
+ } catch {
14061
+ }
14062
+ }
14063
+ return content;
14064
+ }
14065
+ return "";
14066
+ }
14067
+ function isSyntheticGeminiTurn(text) {
14068
+ return text.trim().startsWith("<session_context>");
14069
+ }
14070
+ function parseHistoryFile5(filePath) {
14071
+ let raw;
14072
+ try {
14073
+ raw = fs28.readFileSync(filePath, "utf8");
14074
+ } catch (err) {
14075
+ log.warn("gemini", `parseHistoryFile \u2014 cannot read ${filePath}`, err);
14076
+ return [];
14077
+ }
14078
+ const out2 = [];
14079
+ const seen = /* @__PURE__ */ new Set();
14080
+ let idx = 0;
14081
+ let malformed = 0;
14082
+ const consider = (m) => {
14083
+ if (m.type !== "user" && m.type !== "gemini") return;
14084
+ const id = typeof m.id === "string" ? m.id : `pos-${idx}`;
14085
+ if (seen.has(id)) return;
14086
+ const text = extractGeminiText(m.content);
14087
+ if (!text || isSyntheticGeminiTurn(text)) return;
14088
+ seen.add(id);
14089
+ out2.push({
14090
+ id: `gemini:${id}`,
14091
+ role: m.type === "user" ? "user" : "agent",
14092
+ text,
14093
+ timestamp: typeof m.timestamp === "string" ? m.timestamp : (/* @__PURE__ */ new Date(0)).toISOString()
14094
+ });
14095
+ idx += 1;
14096
+ };
14097
+ for (const line of raw.split("\n")) {
14098
+ if (!line.trim()) continue;
14099
+ let rec;
14100
+ try {
14101
+ rec = JSON.parse(line);
14102
+ } catch {
14103
+ malformed += 1;
14104
+ continue;
14105
+ }
14106
+ if (rec.$set && Array.isArray(rec.$set.messages)) {
14107
+ for (const m of rec.$set.messages) consider(m);
14108
+ } else if (rec.type === "user" || rec.type === "gemini") {
14109
+ consider(rec);
14110
+ }
14111
+ }
14112
+ log.trace(
14113
+ "gemini",
14114
+ `parseHistoryFile \u2014 ${out2.length} turn(s) from ${path32.basename(filePath)}` + (malformed > 0 ? ` (${malformed} malformed line(s) skipped)` : "")
14115
+ );
14116
+ return out2;
14117
+ }
14118
+
13959
14119
  // src/agents/gemini/runtime.ts
13960
14120
  var GEMINI_PRO_CONTEXT_WINDOW = 1e6;
13961
14121
  var GEMINI_FLASH_CONTEXT_WINDOW = 1e6;
@@ -13981,8 +14141,8 @@ var GeminiRuntimeStrategy = class {
13981
14141
  meta = getAgent("gemini");
13982
14142
  mode = "interactive";
13983
14143
  os;
13984
- constructor(os47) {
13985
- this.os = os47;
14144
+ constructor(os48) {
14145
+ this.os = os48;
13986
14146
  }
13987
14147
  async prepareLaunch() {
13988
14148
  const binary = this.os.findInPath("gemini");
@@ -13991,19 +14151,29 @@ var GeminiRuntimeStrategy = class {
13991
14151
  "Gemini CLI is not on PATH. Install it with:\n npm install -g @google/gemini-cli\n Then run `codeam pair` again."
13992
14152
  );
13993
14153
  }
13994
- return this.os.buildLaunch(binary);
14154
+ const sessionId = (0, import_node_crypto5.randomUUID)();
14155
+ const launch = this.os.buildLaunch(binary, ["--session-id", sessionId]);
14156
+ log.info(
14157
+ "gemini",
14158
+ `prepareLaunch \u2014 native TUI, binary=${binary} sessionId=${sessionId} (id8=${sessionId.slice(0, 8)})`
14159
+ );
14160
+ return { cmd: launch.cmd, args: launch.args, sessionId };
13995
14161
  }
13996
- // Gemini's REPL has no documented "resume previous session" flag,
13997
- // so a relaunch starts fresh. Returning an empty array is the
13998
- // documented "no-op resume" path (Cursor / Aider do the same).
13999
- resumeLaunchArgs(_sessionId, _opts) {
14000
- return [];
14162
+ // Re-attach the same conversation on hand-back (baton) by passing the same
14163
+ // `--session-id`. Gemini resolves an existing id to the prior transcript.
14164
+ resumeLaunchArgs(sessionId, _opts) {
14165
+ return ["--session-id", sessionId];
14001
14166
  }
14002
- resolveHistoryDir(_cwd) {
14003
- return null;
14167
+ resolveHistoryDir(cwd) {
14168
+ return resolveHistoryDir5(cwd);
14004
14169
  }
14005
- parseHistoryFile(_filePath) {
14006
- return [];
14170
+ /** `~/.gemini/tmp/<project>/chats/session-<ts>-<id8>.jsonl`. Presence of this
14171
+ * method is what lets the baton engage for Gemini (`runtimeSupportsBaton`). */
14172
+ resolveHistoryFile(cwd, sessionId) {
14173
+ return resolveHistoryFile4(cwd, sessionId);
14174
+ }
14175
+ parseHistoryFile(filePath) {
14176
+ return parseHistoryFile5(filePath);
14007
14177
  }
14008
14178
  getCurrentUsage(_historyDir) {
14009
14179
  return null;
@@ -14081,18 +14251,18 @@ var GeminiRuntimeStrategy = class {
14081
14251
 
14082
14252
  // src/agents/registry.ts
14083
14253
  var runtimeBuilders = {
14084
- claude: (os47) => new ClaudeRuntimeStrategy(os47),
14085
- codex: (os47) => new CodexRuntimeStrategy(os47),
14086
- coderabbit: (os47) => new CoderabbitRuntimeStrategy(os47),
14087
- cursor: (os47) => new CursorRuntimeStrategy(os47),
14088
- aider: (os47) => new AiderRuntimeStrategy(os47),
14089
- gemini: (os47) => new GeminiRuntimeStrategy(os47)
14254
+ claude: (os48) => new ClaudeRuntimeStrategy(os48),
14255
+ codex: (os48) => new CodexRuntimeStrategy(os48),
14256
+ coderabbit: (os48) => new CoderabbitRuntimeStrategy(os48),
14257
+ cursor: (os48) => new CursorRuntimeStrategy(os48),
14258
+ aider: (os48) => new AiderRuntimeStrategy(os48),
14259
+ gemini: (os48) => new GeminiRuntimeStrategy(os48)
14090
14260
  };
14091
14261
  var deployBuilders = {
14092
14262
  claude: () => new ClaudeDeployStrategy(),
14093
14263
  codex: () => new CodexDeployStrategy()
14094
14264
  };
14095
- function createAgentStrategy(agent, os47 = createOsStrategy()) {
14265
+ function createAgentStrategy(agent, os48 = createOsStrategy()) {
14096
14266
  if (!AGENT_REGISTRY[agent]?.enabled) {
14097
14267
  throw new Error(
14098
14268
  `Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
@@ -14102,10 +14272,10 @@ function createAgentStrategy(agent, os47 = createOsStrategy()) {
14102
14272
  if (!build) {
14103
14273
  throw new Error(`No runtime strategy registered for agent "${agent}"`);
14104
14274
  }
14105
- return build(os47);
14275
+ return build(os48);
14106
14276
  }
14107
- function createInteractiveAgentStrategy(agent, os47 = createOsStrategy()) {
14108
- const s = createAgentStrategy(agent, os47);
14277
+ function createInteractiveAgentStrategy(agent, os48 = createOsStrategy()) {
14278
+ const s = createAgentStrategy(agent, os48);
14109
14279
  if (s.mode !== "interactive") {
14110
14280
  throw new Error(
14111
14281
  `Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
@@ -14161,7 +14331,7 @@ function parseLinkArgs(args2) {
14161
14331
  if (apiKeyFileArg) {
14162
14332
  const filePath = apiKeyFileArg.slice("--api-key-file=".length);
14163
14333
  try {
14164
- apiKey = fs28.readFileSync(path32.resolve(filePath), "utf8").trim();
14334
+ apiKey = fs29.readFileSync(path33.resolve(filePath), "utf8").trim();
14165
14335
  } catch (err) {
14166
14336
  throw new Error(`Could not read --api-key-file ${filePath}: ${err.message}`);
14167
14337
  }
@@ -14188,9 +14358,9 @@ async function link(args2 = []) {
14188
14358
  await linkDryRunPreflight(ctx);
14189
14359
  return;
14190
14360
  }
14191
- const pluginId = (0, import_node_crypto5.randomUUID)();
14192
- const pollSecret = (0, import_node_crypto5.randomBytes)(32).toString("base64url");
14193
- const pluginSecretHash = (0, import_node_crypto5.createHash)("sha256").update(pollSecret).digest("hex");
14361
+ const pluginId = (0, import_node_crypto6.randomUUID)();
14362
+ const pollSecret = (0, import_node_crypto6.randomBytes)(32).toString("base64url");
14363
+ const pluginSecretHash = (0, import_node_crypto6.createHash)("sha256").update(pollSecret).digest("hex");
14194
14364
  const spin = dist_exports.spinner();
14195
14365
  spin.start("Requesting pairing code...");
14196
14366
  const pairing = await requestCode(pluginId, pluginSecretHash);
@@ -14288,7 +14458,7 @@ async function link(args2 = []) {
14288
14458
  return;
14289
14459
  }
14290
14460
  if (parsed.tokenFile) {
14291
- const credential = fs28.readFileSync(path32.resolve(parsed.tokenFile), "utf8").trim();
14461
+ const credential = fs29.readFileSync(path33.resolve(parsed.tokenFile), "utf8").trim();
14292
14462
  if (!credential) {
14293
14463
  showError(`--token-file ${parsed.tokenFile} is empty.`);
14294
14464
  process.exit(1);
@@ -14506,14 +14676,14 @@ async function linkDryRunPreflight(ctx) {
14506
14676
 
14507
14677
  // src/commands/host-agent.ts
14508
14678
  var import_node_child_process19 = require("child_process");
14509
- var os32 = __toESM(require("os"));
14510
- var fs38 = __toESM(require("fs"));
14511
- var path40 = __toESM(require("path"));
14679
+ var os33 = __toESM(require("os"));
14680
+ var fs39 = __toESM(require("fs"));
14681
+ var path41 = __toESM(require("path"));
14512
14682
 
14513
14683
  // src/commands/host/host-client.ts
14514
- var fs30 = __toESM(require("fs"));
14515
- var os26 = __toESM(require("os"));
14516
- var path33 = __toESM(require("path"));
14684
+ var fs31 = __toESM(require("fs"));
14685
+ var os27 = __toESM(require("os"));
14686
+ var path34 = __toESM(require("path"));
14517
14687
 
14518
14688
  // src/lib/restrict-to-owner.ts
14519
14689
  var import_node_fs5 = __toESM(require("fs"));
@@ -14552,7 +14722,7 @@ function restrictToOwner(filePath) {
14552
14722
  function sampleCpuTimes() {
14553
14723
  let idle = 0;
14554
14724
  let total = 0;
14555
- for (const cpu of os26.cpus()) {
14725
+ for (const cpu of os27.cpus()) {
14556
14726
  const t2 = cpu.times;
14557
14727
  idle += t2.idle;
14558
14728
  total += t2.user + t2.nice + t2.sys + t2.idle + t2.irq;
@@ -14571,8 +14741,8 @@ var MetricsCollector = class {
14571
14741
  const prev = this.prevCpu;
14572
14742
  this.prevCpu = current;
14573
14743
  if (!prev) {
14574
- const cores = os26.cpus().length || 1;
14575
- const proxy = os26.loadavg()[0] / cores * 100;
14744
+ const cores = os27.cpus().length || 1;
14745
+ const proxy = os27.loadavg()[0] / cores * 100;
14576
14746
  return Math.min(100, Math.max(0, Math.round(proxy)));
14577
14747
  }
14578
14748
  const idleDelta = current.idle - prev.idle;
@@ -14585,8 +14755,8 @@ var MetricsCollector = class {
14585
14755
  collect() {
14586
14756
  return {
14587
14757
  cpuPct: this.cpuPct(),
14588
- ramUsedMb: Math.round((os26.totalmem() - os26.freemem()) / 1048576),
14589
- ramTotalMb: Math.round(os26.totalmem() / 1048576),
14758
+ ramUsedMb: Math.round((os27.totalmem() - os27.freemem()) / 1048576),
14759
+ ramTotalMb: Math.round(os27.totalmem() / 1048576),
14590
14760
  latencyMs: this.lastLatencyMs
14591
14761
  };
14592
14762
  }
@@ -14595,19 +14765,19 @@ function apiBase() {
14595
14765
  return process.env.CODEAM_API_URL ?? resolveApiBaseUrl();
14596
14766
  }
14597
14767
  function hostIdentityPath() {
14598
- return path33.join(os26.homedir(), ".codeam", "host-agent.json");
14768
+ return path34.join(os27.homedir(), ".codeam", "host-agent.json");
14599
14769
  }
14600
14770
  function collectOsInfo() {
14601
14771
  return {
14602
- distro: os26.platform(),
14603
- arch: os26.arch(),
14604
- kernel: os26.release(),
14772
+ distro: os27.platform(),
14773
+ arch: os27.arch(),
14774
+ kernel: os27.release(),
14605
14775
  nodeVersion: process.versions.node
14606
14776
  };
14607
14777
  }
14608
14778
  function loadHostIdentity() {
14609
14779
  try {
14610
- const raw = fs30.readFileSync(hostIdentityPath(), "utf8");
14780
+ const raw = fs31.readFileSync(hostIdentityPath(), "utf8");
14611
14781
  const parsed = JSON.parse(raw);
14612
14782
  if (typeof parsed === "object" && parsed !== null && typeof parsed.hostId === "string" && typeof parsed.hostToken === "string" && typeof parsed.controlPluginId === "string") {
14613
14783
  const p2 = parsed;
@@ -14620,8 +14790,8 @@ function loadHostIdentity() {
14620
14790
  }
14621
14791
  function saveHostIdentity(identity) {
14622
14792
  const file = hostIdentityPath();
14623
- fs30.mkdirSync(path33.dirname(file), { recursive: true, mode: 448 });
14624
- fs30.writeFileSync(file, JSON.stringify(identity, null, 2), {
14793
+ fs31.mkdirSync(path34.dirname(file), { recursive: true, mode: 448 });
14794
+ fs31.writeFileSync(file, JSON.stringify(identity, null, 2), {
14625
14795
  encoding: "utf8",
14626
14796
  mode: 384
14627
14797
  });
@@ -14666,7 +14836,7 @@ function isTerminalEnrollError(err) {
14666
14836
  }
14667
14837
  function deleteHostIdentity() {
14668
14838
  try {
14669
- fs30.rmSync(hostIdentityPath(), { force: true });
14839
+ fs31.rmSync(hostIdentityPath(), { force: true });
14670
14840
  } catch {
14671
14841
  }
14672
14842
  }
@@ -14789,17 +14959,17 @@ async function reportDeployProgress(auth, deployId, step, message, sessionId) {
14789
14959
  }
14790
14960
 
14791
14961
  // src/commands/host/workspace.ts
14792
- var fs31 = __toESM(require("fs"));
14793
- var os27 = __toESM(require("os"));
14794
- var path34 = __toESM(require("path"));
14962
+ var fs32 = __toESM(require("fs"));
14963
+ var os28 = __toESM(require("os"));
14964
+ var path35 = __toESM(require("path"));
14795
14965
  var import_node_child_process13 = require("child_process");
14796
14966
  var import_node_util4 = require("util");
14797
14967
  var execFileP4 = (0, import_node_util4.promisify)(import_node_child_process13.execFile);
14798
14968
  function isAbsolutePathTarget(target) {
14799
- return path34.isAbsolute(target);
14969
+ return path35.isAbsolute(target);
14800
14970
  }
14801
14971
  function selfHostedWorkspaceRoot() {
14802
- return path34.join(os27.homedir(), ".codeam", "self-hosted");
14972
+ return path35.join(os28.homedir(), ".codeam", "self-hosted");
14803
14973
  }
14804
14974
  function nonInteractiveGitEnv() {
14805
14975
  return {
@@ -14852,13 +15022,13 @@ async function fetchGithubIdentity(token) {
14852
15022
  async function configureGitCredentials(dest, repoRef, cloneToken) {
14853
15023
  const gh = githubOwnerRepo(repoRef.trim());
14854
15024
  if (!gh || !cloneToken) return;
14855
- const credFile = path34.join(dest, ".git", "codeam-credentials");
14856
- fs31.writeFileSync(credFile, `https://x-access-token:${cloneToken}@github.com
15025
+ const credFile = path35.join(dest, ".git", "codeam-credentials");
15026
+ fs32.writeFileSync(credFile, `https://x-access-token:${cloneToken}@github.com
14857
15027
  `, { mode: 384 });
14858
15028
  restrictToOwner(credFile);
14859
15029
  const env = nonInteractiveGitEnv();
14860
15030
  const git2 = (args2) => execFileP4("git", ["-C", dest, ...args2], { timeout: 3e4, env });
14861
- const credFilePosix = credFile.split(path34.sep).join("/");
15031
+ const credFilePosix = credFile.split(path35.sep).join("/");
14862
15032
  await git2(["config", "--local", "--replace-all", "credential.helper", ""]).catch(() => {
14863
15033
  });
14864
15034
  await git2([
@@ -14894,17 +15064,17 @@ function maskToken(text, cloneToken) {
14894
15064
  }
14895
15065
  async function prepareWorkspace(repoOrPath, deployId, cloneToken) {
14896
15066
  if (isAbsolutePathTarget(repoOrPath)) {
14897
- if (!fs31.existsSync(repoOrPath)) {
15067
+ if (!fs32.existsSync(repoOrPath)) {
14898
15068
  throw new Error(`deploy target path does not exist: ${repoOrPath}`);
14899
15069
  }
14900
15070
  return repoOrPath;
14901
15071
  }
14902
- const dest = path34.join(selfHostedWorkspaceRoot(), deployId);
14903
- if (fs31.existsSync(path34.join(dest, ".git"))) {
15072
+ const dest = path35.join(selfHostedWorkspaceRoot(), deployId);
15073
+ if (fs32.existsSync(path35.join(dest, ".git"))) {
14904
15074
  if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken);
14905
15075
  return dest;
14906
15076
  }
14907
- fs31.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
15077
+ fs32.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
14908
15078
  const cloneUrl = repoCloneUrl(repoOrPath, cloneToken);
14909
15079
  try {
14910
15080
  await execFileP4("git", ["clone", "--depth", "1", cloneUrl, dest], {
@@ -14921,9 +15091,9 @@ async function prepareWorkspace(repoOrPath, deployId, cloneToken) {
14921
15091
  }
14922
15092
 
14923
15093
  // src/commands/host/agent-provisioning.ts
14924
- var fs32 = __toESM(require("fs"));
14925
- var os28 = __toESM(require("os"));
14926
- var path35 = __toESM(require("path"));
15094
+ var fs33 = __toESM(require("fs"));
15095
+ var os29 = __toESM(require("os"));
15096
+ var path36 = __toESM(require("path"));
14927
15097
  var PUBLIC_TO_INTERNAL_AGENT = {
14928
15098
  claude_code: "claude",
14929
15099
  claude: "claude",
@@ -14938,22 +15108,22 @@ function toInternalAgentId(publicAgentId) {
14938
15108
  return PUBLIC_TO_INTERNAL_AGENT[publicAgentId] ?? null;
14939
15109
  }
14940
15110
  function ensureDir(dir) {
14941
- fs32.mkdirSync(dir, { recursive: true, mode: 448 });
15111
+ fs33.mkdirSync(dir, { recursive: true, mode: 448 });
14942
15112
  }
14943
15113
  function writeFile0600(filePath, contents) {
14944
- ensureDir(path35.dirname(filePath));
14945
- fs32.writeFileSync(filePath, contents, { encoding: "utf8", mode: 384 });
15114
+ ensureDir(path36.dirname(filePath));
15115
+ fs33.writeFileSync(filePath, contents, { encoding: "utf8", mode: 384 });
14946
15116
  restrictToOwner(filePath);
14947
15117
  }
14948
15118
  function rmIfExists(filePath) {
14949
15119
  try {
14950
- fs32.rmSync(filePath, { force: true });
15120
+ fs33.rmSync(filePath, { force: true });
14951
15121
  } catch {
14952
15122
  }
14953
15123
  }
14954
15124
  var claudeProvisioner = {
14955
15125
  write(auth, home) {
14956
- const credentialsJson = path35.join(home, ".claude", ".credentials.json");
15126
+ const credentialsJson = path36.join(home, ".claude", ".credentials.json");
14957
15127
  if (auth.kind === "api_key") {
14958
15128
  rmIfExists(credentialsJson);
14959
15129
  return { ANTHROPIC_API_KEY: auth.value };
@@ -14965,8 +15135,8 @@ var claudeProvisioner = {
14965
15135
  } else {
14966
15136
  rmIfExists(credentialsJson);
14967
15137
  }
14968
- const claudeJson = path35.join(home, ".claude.json");
14969
- if (!fs32.existsSync(claudeJson)) {
15138
+ const claudeJson = path36.join(home, ".claude.json");
15139
+ if (!fs33.existsSync(claudeJson)) {
14970
15140
  writeFile0600(
14971
15141
  claudeJson,
14972
15142
  JSON.stringify({ hasCompletedOnboarding: true, customApiKeyResponses: { approved: [] } })
@@ -14977,7 +15147,7 @@ var claudeProvisioner = {
14977
15147
  };
14978
15148
  var codexProvisioner = {
14979
15149
  write(auth, home) {
14980
- const authJson = path35.join(home, ".codex", "auth.json");
15150
+ const authJson = path36.join(home, ".codex", "auth.json");
14981
15151
  if (auth.kind === "api_key") {
14982
15152
  rmIfExists(authJson);
14983
15153
  return { OPENAI_API_KEY: auth.value };
@@ -14988,8 +15158,8 @@ var codexProvisioner = {
14988
15158
  };
14989
15159
  var geminiProvisioner = {
14990
15160
  write(auth, home) {
14991
- const settingsJson = path35.join(home, ".gemini", "settings.json");
14992
- const oauthCreds = path35.join(home, ".gemini", "oauth_creds.json");
15161
+ const settingsJson = path36.join(home, ".gemini", "settings.json");
15162
+ const oauthCreds = path36.join(home, ".gemini", "oauth_creds.json");
14993
15163
  if (auth.kind === "api_key") {
14994
15164
  rmIfExists(oauthCreds);
14995
15165
  writeFile0600(settingsJson, '{"security":{"auth":{"selectedType":"gemini-api-key"}}}');
@@ -15002,7 +15172,7 @@ var geminiProvisioner = {
15002
15172
  };
15003
15173
  var cursorProvisioner = {
15004
15174
  write(auth, home) {
15005
- const authJson = path35.join(home, ".config", "cursor", "auth.json");
15175
+ const authJson = path36.join(home, ".config", "cursor", "auth.json");
15006
15176
  if (auth.kind === "api_key") {
15007
15177
  rmIfExists(authJson);
15008
15178
  return { CURSOR_API_KEY: auth.value };
@@ -15039,7 +15209,7 @@ var UnsupportedAgentError = class extends Error {
15039
15209
  this.agentId = agentId;
15040
15210
  }
15041
15211
  };
15042
- function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os28.homedir()) {
15212
+ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os29.homedir()) {
15043
15213
  const internal = toInternalAgentId(publicAgentId);
15044
15214
  if (!internal) throw new UnsupportedAgentError(publicAgentId);
15045
15215
  const provisioner = PROVISIONERS[internal];
@@ -15049,11 +15219,11 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os28.homedir(
15049
15219
 
15050
15220
  // src/commands/host/git-tooling.ts
15051
15221
  var import_node_child_process14 = require("child_process");
15052
- var fs33 = __toESM(require("fs"));
15053
- var os29 = __toESM(require("os"));
15054
- var path36 = __toESM(require("path"));
15222
+ var fs34 = __toESM(require("fs"));
15223
+ var os30 = __toESM(require("os"));
15224
+ var path37 = __toESM(require("path"));
15055
15225
  function codeamBinDir() {
15056
- return process.env.CODEAM_BIN_DIR ?? path36.join(os29.homedir(), ".codeam", "bin");
15226
+ return process.env.CODEAM_BIN_DIR ?? path37.join(os30.homedir(), ".codeam", "bin");
15057
15227
  }
15058
15228
  var FALLBACK_GH_VERSION = "2.62.0";
15059
15229
  var RELEASE_API = "https://api.github.com/repos/cli/cli/releases/latest";
@@ -15085,7 +15255,7 @@ async function download(url, dest) {
15085
15255
  const res = await fetch(url, { headers: { "User-Agent": "codeam-cli" } });
15086
15256
  if (!res.ok || !res.body) return false;
15087
15257
  const buf = Buffer.from(await res.arrayBuffer());
15088
- fs33.writeFileSync(dest, buf);
15258
+ fs34.writeFileSync(dest, buf);
15089
15259
  return true;
15090
15260
  } catch {
15091
15261
  return false;
@@ -15108,8 +15278,8 @@ async function ensureGhCli(runner, token, deps = {}) {
15108
15278
  const version3 = await resolveVersionFn(token);
15109
15279
  const asset = `gh_${version3}_${osToken}_${arch2}`;
15110
15280
  const url = `https://github.com/cli/cli/releases/download/v${version3}/${asset}.${ext}`;
15111
- const tmpRoot = fs33.mkdtempSync(path36.join(os29.tmpdir(), "codeam-gh-"));
15112
- const archive = path36.join(tmpRoot, `${asset}.${ext}`);
15281
+ const tmpRoot = fs34.mkdtempSync(path37.join(os30.tmpdir(), "codeam-gh-"));
15282
+ const archive = path37.join(tmpRoot, `${asset}.${ext}`);
15113
15283
  if (!await downloadFn(url, archive)) {
15114
15284
  log.warn("host-agent", "gh download failed \u2014 skipping (git pull/push still work via the credential helper)");
15115
15285
  return null;
@@ -15119,16 +15289,16 @@ async function ensureGhCli(runner, token, deps = {}) {
15119
15289
  log.warn("host-agent", `gh archive extraction failed (code=${String(extract.code)}) \u2014 skipping`);
15120
15290
  return null;
15121
15291
  }
15122
- const extractedBin = path36.join(tmpRoot, asset, "bin", binaryName);
15123
- if (!fs33.existsSync(extractedBin)) {
15292
+ const extractedBin = path37.join(tmpRoot, asset, "bin", binaryName);
15293
+ if (!fs34.existsSync(extractedBin)) {
15124
15294
  log.warn("host-agent", "gh binary not found in the extracted archive \u2014 skipping");
15125
15295
  return null;
15126
15296
  }
15127
15297
  const binDir = codeamBinDir();
15128
- fs33.mkdirSync(binDir, { recursive: true });
15129
- const target = path36.join(binDir, binaryName);
15130
- fs33.copyFileSync(extractedBin, target);
15131
- fs33.chmodSync(target, 493);
15298
+ fs34.mkdirSync(binDir, { recursive: true });
15299
+ const target = path37.join(binDir, binaryName);
15300
+ fs34.copyFileSync(extractedBin, target);
15301
+ fs34.chmodSync(target, 493);
15132
15302
  log.info("host-agent", `gh installed to ${target} (v${version3})`);
15133
15303
  return target;
15134
15304
  } catch (e) {
@@ -15615,23 +15785,23 @@ async function ensureModernPython(runner) {
15615
15785
  }
15616
15786
 
15617
15787
  // src/commands/host/headroom-bootstrap.ts
15618
- var fs35 = __toESM(require("fs"));
15619
- var path38 = __toESM(require("path"));
15788
+ var fs36 = __toESM(require("fs"));
15789
+ var path39 = __toESM(require("path"));
15620
15790
 
15621
15791
  // src/commands/host/headroom-config.ts
15622
- var fs34 = __toESM(require("fs"));
15623
- var os30 = __toESM(require("os"));
15624
- var path37 = __toESM(require("path"));
15792
+ var fs35 = __toESM(require("fs"));
15793
+ var os31 = __toESM(require("os"));
15794
+ var path38 = __toESM(require("path"));
15625
15795
  function headroomConfigPath() {
15626
- return path37.join(os30.homedir(), ".codeam", "headroom-config.json");
15796
+ return path38.join(os31.homedir(), ".codeam", "headroom-config.json");
15627
15797
  }
15628
15798
  function persistHeadroomConfig(config) {
15629
15799
  try {
15630
15800
  const file = headroomConfigPath();
15631
- fs34.mkdirSync(path37.dirname(file), { recursive: true, mode: 448 });
15801
+ fs35.mkdirSync(path38.dirname(file), { recursive: true, mode: 448 });
15632
15802
  const tmp = `${file}.tmp-${process.pid}`;
15633
- fs34.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
15634
- fs34.renameSync(tmp, file);
15803
+ fs35.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
15804
+ fs35.renameSync(tmp, file);
15635
15805
  restrictToOwner(file);
15636
15806
  } catch (err) {
15637
15807
  log.warn(
@@ -15641,21 +15811,21 @@ function persistHeadroomConfig(config) {
15641
15811
  }
15642
15812
  }
15643
15813
  function agentSettingsPath(kind) {
15644
- const home = os30.homedir();
15645
- if (kind === "claude") return path37.join(home, ".claude", "settings.json");
15646
- if (kind === "codex") return path37.join(home, ".codex", "auth.json");
15647
- if (kind === "copilot") return path37.join(home, ".config", "github-copilot", "hosts.json");
15814
+ const home = os31.homedir();
15815
+ if (kind === "claude") return path38.join(home, ".claude", "settings.json");
15816
+ if (kind === "codex") return path38.join(home, ".codex", "auth.json");
15817
+ if (kind === "copilot") return path38.join(home, ".config", "github-copilot", "hosts.json");
15648
15818
  return null;
15649
15819
  }
15650
15820
  function backupAgentHeadroomConfig(kind) {
15651
15821
  const src = agentSettingsPath(kind);
15652
15822
  if (!src) return;
15653
15823
  try {
15654
- if (!fs34.existsSync(src)) return;
15655
- const dest = path37.join(os30.homedir(), ".codeam", `headroom-backup-${kind}.json`);
15656
- fs34.mkdirSync(path37.dirname(dest), { recursive: true, mode: 448 });
15657
- fs34.copyFileSync(src, dest);
15658
- fs34.chmodSync(dest, 384);
15824
+ if (!fs35.existsSync(src)) return;
15825
+ const dest = path38.join(os31.homedir(), ".codeam", `headroom-backup-${kind}.json`);
15826
+ fs35.mkdirSync(path38.dirname(dest), { recursive: true, mode: 448 });
15827
+ fs35.copyFileSync(src, dest);
15828
+ fs35.chmodSync(dest, 384);
15659
15829
  log.info("host-agent", `headroom config backup: ${src} \u2192 ${dest}`);
15660
15830
  } catch (err) {
15661
15831
  log.warn(
@@ -15667,12 +15837,12 @@ function backupAgentHeadroomConfig(kind) {
15667
15837
  function restoreAgentHeadroomConfig(kind) {
15668
15838
  const dest = agentSettingsPath(kind);
15669
15839
  if (!dest) return false;
15670
- const src = path37.join(os30.homedir(), ".codeam", `headroom-backup-${kind}.json`);
15671
- if (!fs34.existsSync(src)) return false;
15840
+ const src = path38.join(os31.homedir(), ".codeam", `headroom-backup-${kind}.json`);
15841
+ if (!fs35.existsSync(src)) return false;
15672
15842
  try {
15673
- fs34.mkdirSync(path37.dirname(dest), { recursive: true, mode: 448 });
15674
- fs34.copyFileSync(src, dest);
15675
- fs34.chmodSync(dest, 384);
15843
+ fs35.mkdirSync(path38.dirname(dest), { recursive: true, mode: 448 });
15844
+ fs35.copyFileSync(src, dest);
15845
+ fs35.chmodSync(dest, 384);
15676
15846
  log.info("host-agent", `headroom config restored: ${src} \u2192 ${dest}`);
15677
15847
  return true;
15678
15848
  } catch (err) {
@@ -15685,7 +15855,7 @@ function restoreAgentHeadroomConfig(kind) {
15685
15855
  }
15686
15856
  function readHeadroomChildEnv() {
15687
15857
  try {
15688
- const raw = fs34.readFileSync(headroomConfigPath(), "utf8");
15858
+ const raw = fs35.readFileSync(headroomConfigPath(), "utf8");
15689
15859
  const parsed = JSON.parse(raw);
15690
15860
  if (typeof parsed !== "object" || parsed === null) return {};
15691
15861
  const o = parsed;
@@ -15721,37 +15891,37 @@ function bundledClaudeBinDir() {
15721
15891
  const roots = /* @__PURE__ */ new Set();
15722
15892
  let dir = __dirname;
15723
15893
  for (let i = 0; i < 6; i++) {
15724
- roots.add(path38.join(dir, "node_modules"));
15725
- const parent = path38.dirname(dir);
15894
+ roots.add(path39.join(dir, "node_modules"));
15895
+ const parent = path39.dirname(dir);
15726
15896
  if (parent === dir) break;
15727
15897
  dir = parent;
15728
15898
  }
15729
15899
  try {
15730
15900
  const main2 = require.resolve("@anthropic-ai/claude-agent-sdk");
15731
- const marker = `${path38.sep}@anthropic-ai${path38.sep}`;
15901
+ const marker = `${path39.sep}@anthropic-ai${path39.sep}`;
15732
15902
  const idx = main2.lastIndexOf(marker);
15733
15903
  if (idx !== -1) roots.add(main2.slice(0, idx));
15734
15904
  } catch {
15735
15905
  }
15736
15906
  for (const nm of roots) {
15737
- const atAnthropic = path38.join(nm, "@anthropic-ai");
15907
+ const atAnthropic = path39.join(nm, "@anthropic-ai");
15738
15908
  let entries;
15739
15909
  try {
15740
- entries = fs35.readdirSync(atAnthropic);
15910
+ entries = fs36.readdirSync(atAnthropic);
15741
15911
  } catch {
15742
15912
  continue;
15743
15913
  }
15744
15914
  for (const entry of entries) {
15745
15915
  if (!entry.startsWith("claude-agent-sdk-")) continue;
15746
- const bin = path38.join(atAnthropic, entry, "claude");
15747
- if (fs35.existsSync(bin)) return path38.dirname(bin);
15916
+ const bin = path39.join(atAnthropic, entry, "claude");
15917
+ if (fs36.existsSync(bin)) return path39.dirname(bin);
15748
15918
  }
15749
15919
  }
15750
15920
  return null;
15751
15921
  }
15752
15922
  async function getFreeDiskBytes(dir) {
15753
15923
  try {
15754
- const s = await fs35.promises.statfs(dir);
15924
+ const s = await fs36.promises.statfs(dir);
15755
15925
  return s.bsize * s.bavail;
15756
15926
  } catch {
15757
15927
  return null;
@@ -15813,7 +15983,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
15813
15983
  if (initKind === "claude") {
15814
15984
  const claudeDir = bundledClaudeBinDir();
15815
15985
  if (claudeDir) {
15816
- initEnv.PATH = `${claudeDir}${path38.delimiter}${process.env["PATH"] ?? ""}`;
15986
+ initEnv.PATH = `${claudeDir}${path39.delimiter}${process.env["PATH"] ?? ""}`;
15817
15987
  log.info("host-agent", `headroom init: bundled claude on PATH (${claudeDir})`);
15818
15988
  } else {
15819
15989
  log.warn("host-agent", "headroom init: bundled claude binary not found \u2014 init may fail");
@@ -15848,9 +16018,9 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
15848
16018
  var import_node_child_process17 = require("child_process");
15849
16019
 
15850
16020
  // src/lib/updateNotifier.ts
15851
- var fs36 = __toESM(require("fs"));
15852
- var os31 = __toESM(require("os"));
15853
- var path39 = __toESM(require("path"));
16021
+ var fs37 = __toESM(require("fs"));
16022
+ var os32 = __toESM(require("os"));
16023
+ var path40 = __toESM(require("path"));
15854
16024
  var https6 = __toESM(require("https"));
15855
16025
  var import_node_child_process16 = require("child_process");
15856
16026
  var import_picocolors3 = __toESM(require("picocolors"));
@@ -15859,12 +16029,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
15859
16029
  var TTL_MS = 24 * 60 * 60 * 1e3;
15860
16030
  var REQUEST_TIMEOUT_MS = 1500;
15861
16031
  function cachePath() {
15862
- const dir = path39.join(os31.homedir(), ".codeam");
15863
- return path39.join(dir, "update-check.json");
16032
+ const dir = path40.join(os32.homedir(), ".codeam");
16033
+ return path40.join(dir, "update-check.json");
15864
16034
  }
15865
16035
  function readCache() {
15866
16036
  try {
15867
- const raw = fs36.readFileSync(cachePath(), "utf8");
16037
+ const raw = fs37.readFileSync(cachePath(), "utf8");
15868
16038
  const parsed = JSON.parse(raw);
15869
16039
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
15870
16040
  return parsed;
@@ -15875,10 +16045,10 @@ function readCache() {
15875
16045
  function writeCache(cache) {
15876
16046
  try {
15877
16047
  const file = cachePath();
15878
- fs36.mkdirSync(path39.dirname(file), { recursive: true });
16048
+ fs37.mkdirSync(path40.dirname(file), { recursive: true });
15879
16049
  const tmp = `${file}.${process.pid}.tmp`;
15880
- fs36.writeFileSync(tmp, JSON.stringify(cache));
15881
- fs36.renameSync(tmp, file);
16050
+ fs37.writeFileSync(tmp, JSON.stringify(cache));
16051
+ fs37.renameSync(tmp, file);
15882
16052
  } catch {
15883
16053
  }
15884
16054
  }
@@ -15952,8 +16122,8 @@ function isLinkedInstall() {
15952
16122
  timeout: 2e3
15953
16123
  }).trim();
15954
16124
  if (!root) return false;
15955
- const pkgPath = path39.join(root, PKG_NAME);
15956
- return fs36.lstatSync(pkgPath).isSymbolicLink();
16125
+ const pkgPath = path40.join(root, PKG_NAME);
16126
+ return fs37.lstatSync(pkgPath).isSymbolicLink();
15957
16127
  } catch {
15958
16128
  return false;
15959
16129
  }
@@ -15989,7 +16159,7 @@ function maybeAutoUpdate(currentVersion, latest) {
15989
16159
  return;
15990
16160
  }
15991
16161
  try {
15992
- fs36.unlinkSync(cachePath());
16162
+ fs37.unlinkSync(cachePath());
15993
16163
  } catch {
15994
16164
  }
15995
16165
  process.stderr.write(` ${import_picocolors3.default.green("\u2713")} Updated. Resuming session...
@@ -16005,7 +16175,7 @@ async function autoUpgradeBeforeCriticalCommand() {
16005
16175
  if (process.env.NODE_ENV === "test") return;
16006
16176
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16007
16177
  if (process.env.CI) return;
16008
- const current = true ? "2.60.8" : null;
16178
+ const current = true ? "2.60.10" : null;
16009
16179
  if (!current) return;
16010
16180
  const cache = readCache();
16011
16181
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16022,7 +16192,7 @@ function checkForUpdates() {
16022
16192
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
16023
16193
  if (process.env.CI) return;
16024
16194
  if (!process.stdout.isTTY) return;
16025
- const current = true ? "2.60.8" : null;
16195
+ const current = true ? "2.60.10" : null;
16026
16196
  if (!current) return;
16027
16197
  const cache = readCache();
16028
16198
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -16042,7 +16212,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
16042
16212
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
16043
16213
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
16044
16214
  function currentCliVersion() {
16045
- return true ? "2.60.8" : null;
16215
+ return true ? "2.60.10" : null;
16046
16216
  }
16047
16217
  function runCmd(cmd, args2, timeoutMs) {
16048
16218
  return new Promise((resolve7) => {
@@ -16109,7 +16279,7 @@ async function runSelfUpdate() {
16109
16279
 
16110
16280
  // src/commands/host/teardown.ts
16111
16281
  var import_node_child_process18 = require("child_process");
16112
- var fs37 = __toESM(require("fs"));
16282
+ var fs38 = __toESM(require("fs"));
16113
16283
  var defaultDisableService = () => {
16114
16284
  try {
16115
16285
  (0, import_node_child_process18.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
@@ -16118,7 +16288,7 @@ var defaultDisableService = () => {
16118
16288
  };
16119
16289
  var defaultTeardownHeadroom = () => {
16120
16290
  try {
16121
- const kind = JSON.parse(fs37.readFileSync(headroomConfigPath(), "utf8")).agent;
16291
+ const kind = JSON.parse(fs38.readFileSync(headroomConfigPath(), "utf8")).agent;
16122
16292
  if (kind) {
16123
16293
  (0, import_node_child_process18.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
16124
16294
  }
@@ -16186,8 +16356,8 @@ function maybeResumeLocalHeadroomReporter(ctx) {
16186
16356
  if (process.env["HEADROOM_ENABLED"] === "1") return null;
16187
16357
  try {
16188
16358
  const file = headroomConfigPath();
16189
- if (!fs38.existsSync(file)) return null;
16190
- const cfg = JSON.parse(fs38.readFileSync(file, "utf8"));
16359
+ if (!fs39.existsSync(file)) return null;
16360
+ const cfg = JSON.parse(fs39.readFileSync(file, "utf8"));
16191
16361
  if (!cfg?.enabled) return null;
16192
16362
  const agent = cfg.agent ?? "claude";
16193
16363
  const ingestUrl = `${resolveApiBaseUrl()}/api/sessions/${ctx.sessionId}/headroom-savings`;
@@ -16592,9 +16762,9 @@ var HostAgentSupervisor = class {
16592
16762
  API_TIMEOUT_MS: "3000000",
16593
16763
  CODEAM_AUTO_TOKEN: payload.autoPairToken
16594
16764
  };
16595
- const houseConfigDir = path40.join(os32.homedir(), ".codeam", "house-claude");
16765
+ const houseConfigDir = path41.join(os33.homedir(), ".codeam", "house-claude");
16596
16766
  try {
16597
- fs38.mkdirSync(houseConfigDir, { recursive: true, mode: 448 });
16767
+ fs39.mkdirSync(houseConfigDir, { recursive: true, mode: 448 });
16598
16768
  } catch {
16599
16769
  }
16600
16770
  childEnv.CLAUDE_CONFIG_DIR = houseConfigDir;
@@ -16612,14 +16782,14 @@ var HostAgentSupervisor = class {
16612
16782
  report("installing", "installing agent CLI");
16613
16783
  await this.runAgentInstall(payload.agentInstallScript);
16614
16784
  }
16615
- const home = process.env.HOME || os32.homedir();
16785
+ const home = process.env.HOME || os33.homedir();
16616
16786
  childEnv.PATH = `${home}/.local/bin:${process.env.PATH ?? ""}`;
16617
16787
  if (payload.cloneToken) {
16618
16788
  try {
16619
16789
  report("preparing", "configuring git tooling");
16620
16790
  const ghCmd = await ensureGhCli(defaultGitToolingRunner, payload.cloneToken);
16621
16791
  if (ghCmd) {
16622
- childEnv.PATH = `${codeamBinDir()}${path40.delimiter}${childEnv.PATH}`;
16792
+ childEnv.PATH = `${codeamBinDir()}${path41.delimiter}${childEnv.PATH}`;
16623
16793
  await ensureGhAuth(defaultGitToolingRunner, ghCmd, payload.cloneToken);
16624
16794
  }
16625
16795
  } catch (e) {
@@ -16635,7 +16805,7 @@ var HostAgentSupervisor = class {
16635
16805
  }
16636
16806
  if (payload.headroomEnabled && payload.headroomAgent && payload.headroomSavingsIngestUrl && isHeadroomSupportedAgent(payload.headroomAgent)) {
16637
16807
  report("headroom", "setting up Headroom proxy");
16638
- const freeBytes = await this.getFreeDisk(os32.homedir());
16808
+ const freeBytes = await this.getFreeDisk(os33.homedir());
16639
16809
  const alreadyInstalled = this.isHeadroomInstalled();
16640
16810
  if (!alreadyInstalled && freeBytes !== null && freeBytes < HEADROOM_MIN_FREE_DISK_BYTES) {
16641
16811
  const freeGb = (freeBytes / 1e9).toFixed(1);
@@ -16757,7 +16927,7 @@ var HostAgentSupervisor = class {
16757
16927
  */
16758
16928
  runAgentInstall(script) {
16759
16929
  return new Promise((resolve7) => {
16760
- const home = process.env.HOME || os32.homedir();
16930
+ const home = process.env.HOME || os33.homedir();
16761
16931
  const child = (0, import_node_child_process19.spawn)("sh", ["-c", script], {
16762
16932
  env: { ...process.env, HOME: home },
16763
16933
  stdio: ["ignore", "pipe", "pipe"]
@@ -16941,9 +17111,9 @@ async function configureHeadroom(action, ctx, deps) {
16941
17111
  }
16942
17112
 
16943
17113
  // src/services/headroom/budget-relaunch.ts
16944
- var fs39 = __toESM(require("fs"));
16945
- var os33 = __toESM(require("os"));
16946
- var path41 = __toESM(require("path"));
17114
+ var fs40 = __toESM(require("fs"));
17115
+ var os34 = __toESM(require("os"));
17116
+ var path42 = __toESM(require("path"));
16947
17117
  var import_child_process13 = require("child_process");
16948
17118
  function amendDeploymentManifestBudget(manifest, budget) {
16949
17119
  const rawArgs = manifest.proxy_args ?? [];
@@ -16977,7 +17147,7 @@ function amendDeploymentManifestBudget(manifest, budget) {
16977
17147
  return { ...manifest, proxy_args: newArgs, base_env: newEnv };
16978
17148
  }
16979
17149
  function findHeadroomDeployments(homeDir2, deps) {
16980
- const deployDir = path41.join(homeDir2, ".headroom", "deploy");
17150
+ const deployDir = path42.join(homeDir2, ".headroom", "deploy");
16981
17151
  let profiles;
16982
17152
  try {
16983
17153
  profiles = deps.readDir(deployDir);
@@ -16986,7 +17156,7 @@ function findHeadroomDeployments(homeDir2, deps) {
16986
17156
  }
16987
17157
  const results = [];
16988
17158
  for (const profile of profiles) {
16989
- const manifestPath = path41.join(deployDir, profile, "manifest.json");
17159
+ const manifestPath = path42.join(deployDir, profile, "manifest.json");
16990
17160
  let raw;
16991
17161
  try {
16992
17162
  raw = deps.readJson(manifestPath);
@@ -17018,8 +17188,8 @@ async function applyBudgetToHeadroom(budget, deps) {
17018
17188
  }
17019
17189
  function writeManifestReal(manifestPath, manifest) {
17020
17190
  const tmp = manifestPath + ".codeam.tmp";
17021
- fs39.writeFileSync(tmp, JSON.stringify(manifest, null, 2) + "\n", { mode: 384 });
17022
- fs39.renameSync(tmp, manifestPath);
17191
+ fs40.writeFileSync(tmp, JSON.stringify(manifest, null, 2) + "\n", { mode: 384 });
17192
+ fs40.renameSync(tmp, manifestPath);
17023
17193
  }
17024
17194
  function restartDeploymentReal(profile) {
17025
17195
  try {
@@ -17049,11 +17219,11 @@ function spawnProxyReal2(_budget) {
17049
17219
  });
17050
17220
  }
17051
17221
  function makeRealApplyBudgetDeps() {
17052
- const homeDir2 = os33.homedir();
17222
+ const homeDir2 = os34.homedir();
17053
17223
  return {
17054
17224
  findDeployments: () => findHeadroomDeployments(homeDir2, {
17055
- readDir: (dir) => fs39.readdirSync(dir),
17056
- readJson: (filePath) => JSON.parse(fs39.readFileSync(filePath, "utf8"))
17225
+ readDir: (dir) => fs40.readdirSync(dir),
17226
+ readJson: (filePath) => JSON.parse(fs40.readFileSync(filePath, "utf8"))
17057
17227
  }),
17058
17228
  writeManifest: writeManifestReal,
17059
17229
  restartDeployment: restartDeploymentReal,
@@ -17733,8 +17903,8 @@ function activePreviewSessionIds() {
17733
17903
 
17734
17904
  // src/services/preview/start-orchestrator.ts
17735
17905
  var import_child_process17 = require("child_process");
17736
- var fs44 = __toESM(require("fs"));
17737
- var path46 = __toESM(require("path"));
17906
+ var fs45 = __toESM(require("fs"));
17907
+ var path47 = __toESM(require("path"));
17738
17908
  var import_which2 = __toESM(require("which"));
17739
17909
  var INSTALL_TIMEOUT_MS = 5 * 6e4;
17740
17910
  var SETUP_TIMEOUT_MS = 2 * 6e4;
@@ -17801,8 +17971,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
17801
17971
  if (args2.length === 0) return detection;
17802
17972
  const binName = args2[0];
17803
17973
  if (binName.startsWith("-")) return detection;
17804
- const binPath = path46.join(cwd, "node_modules", ".bin", binName);
17805
- if (!fs44.existsSync(binPath)) return detection;
17974
+ const binPath = path47.join(cwd, "node_modules", ".bin", binName);
17975
+ if (!fs45.existsSync(binPath)) return detection;
17806
17976
  return {
17807
17977
  ...detection,
17808
17978
  command: binPath,
@@ -18152,9 +18322,9 @@ async function establishTunnel(ctx, dev) {
18152
18322
 
18153
18323
  // src/beads/bd-adapter.ts
18154
18324
  var import_child_process18 = require("child_process");
18155
- var fs45 = __toESM(require("fs"));
18156
- var os35 = __toESM(require("os"));
18157
- var path47 = __toESM(require("path"));
18325
+ var fs46 = __toESM(require("fs"));
18326
+ var os36 = __toESM(require("os"));
18327
+ var path48 = __toESM(require("path"));
18158
18328
  var BD_PACKAGE = "@beads/bd";
18159
18329
  function resolveBundledBdBinary() {
18160
18330
  return _resolveSeam.resolveBundled();
@@ -18166,11 +18336,11 @@ function _defaultResolveBundled() {
18166
18336
  } catch {
18167
18337
  return null;
18168
18338
  }
18169
- const binDir = path47.join(path47.dirname(pkgJsonPath), "bin");
18339
+ const binDir = path48.join(path48.dirname(pkgJsonPath), "bin");
18170
18340
  const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
18171
- const binaryPath = path47.join(binDir, binaryName);
18341
+ const binaryPath = path48.join(binDir, binaryName);
18172
18342
  try {
18173
- fs45.accessSync(binaryPath, fs45.constants.F_OK);
18343
+ fs46.accessSync(binaryPath, fs46.constants.F_OK);
18174
18344
  return binaryPath;
18175
18345
  } catch {
18176
18346
  return null;
@@ -18180,13 +18350,13 @@ function resolveBdOnPath() {
18180
18350
  return _resolveSeam.resolveOnPath();
18181
18351
  }
18182
18352
  function _defaultResolveOnPath() {
18183
- const dirs = (process.env.PATH ?? "").split(path47.delimiter).filter(Boolean);
18353
+ const dirs = (process.env.PATH ?? "").split(path48.delimiter).filter(Boolean);
18184
18354
  const candidates = process.platform === "win32" ? ["bd.exe", "bd.cmd", "bd"] : ["bd"];
18185
18355
  for (const dir of dirs) {
18186
18356
  for (const candidate of candidates) {
18187
- const full = path47.join(dir, candidate);
18357
+ const full = path48.join(dir, candidate);
18188
18358
  try {
18189
- fs45.accessSync(full, fs45.constants.F_OK);
18359
+ fs46.accessSync(full, fs46.constants.F_OK);
18190
18360
  return full;
18191
18361
  } catch {
18192
18362
  }
@@ -18271,7 +18441,7 @@ var BdAdapter = class {
18271
18441
  const env = { ...process.env };
18272
18442
  if (!env.HOME) {
18273
18443
  try {
18274
- const home = os35.homedir();
18444
+ const home = os36.homedir();
18275
18445
  if (home) env.HOME = home;
18276
18446
  } catch {
18277
18447
  }
@@ -18363,9 +18533,9 @@ function coerceIssue(row, projectKey) {
18363
18533
 
18364
18534
  // src/beads/provisioner.ts
18365
18535
  var import_child_process22 = require("child_process");
18366
- var fs48 = __toESM(require("fs"));
18367
- var os37 = __toESM(require("os"));
18368
- var path50 = __toESM(require("path"));
18536
+ var fs49 = __toESM(require("fs"));
18537
+ var os38 = __toESM(require("os"));
18538
+ var path51 = __toESM(require("path"));
18369
18539
 
18370
18540
  // src/beads/install-bd.ts
18371
18541
  var import_child_process19 = require("child_process");
@@ -18430,9 +18600,9 @@ async function installBd(platform3 = process.platform) {
18430
18600
 
18431
18601
  // src/beads/install-dolt.ts
18432
18602
  var import_child_process20 = require("child_process");
18433
- var fs46 = __toESM(require("fs"));
18434
- var os36 = __toESM(require("os"));
18435
- var path48 = __toESM(require("path"));
18603
+ var fs47 = __toESM(require("fs"));
18604
+ var os37 = __toESM(require("os"));
18605
+ var path49 = __toESM(require("path"));
18436
18606
  var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
18437
18607
  var DOLT_MSI_URL = "https://github.com/dolthub/dolt/releases/latest/download/dolt-windows-amd64.msi";
18438
18608
  function resolveDoltInstallStrategy(platform3) {
@@ -18472,11 +18642,11 @@ function resolveDoltInstallStrategy(platform3) {
18472
18642
  }
18473
18643
  var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
18474
18644
  function doltPlatformTuple(platform3, arch2) {
18475
- const os47 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
18645
+ const os48 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
18476
18646
  const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
18477
18647
  if (!a) return null;
18478
- if (os47 === "windows" && a !== "amd64") return null;
18479
- return `${os47}-${a}`;
18648
+ if (os48 === "windows" && a !== "amd64") return null;
18649
+ return `${os48}-${a}`;
18480
18650
  }
18481
18651
  function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
18482
18652
  const tuple = doltPlatformTuple(platform3, arch2);
@@ -18521,14 +18691,14 @@ async function installDoltToDir(targetDir, platform3 = process.platform, arch2 =
18521
18691
  return result;
18522
18692
  }
18523
18693
  var _doltPathSeam = {
18524
- homedir: () => os36.homedir(),
18694
+ homedir: () => os37.homedir(),
18525
18695
  getPath: () => process.env.PATH ?? "",
18526
18696
  setPath: (p2) => {
18527
18697
  process.env.PATH = p2;
18528
18698
  },
18529
18699
  exists: (p2) => {
18530
18700
  try {
18531
- fs46.accessSync(p2, fs46.constants.F_OK);
18701
+ fs47.accessSync(p2, fs47.constants.F_OK);
18532
18702
  return true;
18533
18703
  } catch {
18534
18704
  return false;
@@ -18539,7 +18709,7 @@ function doltBinaryNames(platform3) {
18539
18709
  return platform3 === "win32" ? ["dolt.exe", "dolt.cmd", "dolt"] : ["dolt"];
18540
18710
  }
18541
18711
  function knownDoltDirs(platform3) {
18542
- const P3 = platform3 === "win32" ? path48.win32 : path48.posix;
18712
+ const P3 = platform3 === "win32" ? path49.win32 : path49.posix;
18543
18713
  const home = _doltPathSeam.homedir();
18544
18714
  if (platform3 === "win32") {
18545
18715
  return [
@@ -18555,7 +18725,7 @@ function knownDoltDirs(platform3) {
18555
18725
  ].filter(Boolean);
18556
18726
  }
18557
18727
  function ensureDoltResolvable(platform3 = process.platform) {
18558
- const P3 = platform3 === "win32" ? path48.win32 : path48.posix;
18728
+ const P3 = platform3 === "win32" ? path49.win32 : path49.posix;
18559
18729
  const delim = platform3 === "win32" ? ";" : ":";
18560
18730
  const names = doltBinaryNames(platform3);
18561
18731
  const pathDirs = _doltPathSeam.getPath().split(delim).filter(Boolean);
@@ -18691,8 +18861,8 @@ async function ensureSharedServer(adapter, options = {}) {
18691
18861
  // src/beads/project-key.ts
18692
18862
  var import_child_process21 = require("child_process");
18693
18863
  var crypto2 = __toESM(require("crypto"));
18694
- var fs47 = __toESM(require("fs"));
18695
- var path49 = __toESM(require("path"));
18864
+ var fs48 = __toESM(require("fs"));
18865
+ var path50 = __toESM(require("path"));
18696
18866
  function normalizeOrigin(raw) {
18697
18867
  const trimmed = raw.trim();
18698
18868
  if (!trimmed) return null;
@@ -18718,17 +18888,17 @@ function normalizeOrigin(raw) {
18718
18888
  return `${host2}/${pathPart}`;
18719
18889
  }
18720
18890
  function findRepoRoot(cwd) {
18721
- let dir = path49.resolve(cwd);
18891
+ let dir = path50.resolve(cwd);
18722
18892
  const seen = /* @__PURE__ */ new Set();
18723
18893
  for (let i = 0; i < 256; i++) {
18724
18894
  if (seen.has(dir)) return null;
18725
18895
  seen.add(dir);
18726
18896
  try {
18727
- const stat3 = fs47.statSync(path49.join(dir, ".git"), { throwIfNoEntry: false });
18897
+ const stat3 = fs48.statSync(path50.join(dir, ".git"), { throwIfNoEntry: false });
18728
18898
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
18729
18899
  } catch {
18730
18900
  }
18731
- const parent = path49.dirname(dir);
18901
+ const parent = path50.dirname(dir);
18732
18902
  if (parent === dir) return null;
18733
18903
  dir = parent;
18734
18904
  }
@@ -18739,7 +18909,7 @@ var _execSeam2 = {
18739
18909
  const out2 = (0, import_child_process21.execFileSync)(file, args2, opts);
18740
18910
  return typeof out2 === "string" ? out2 : out2.toString("utf8");
18741
18911
  },
18742
- realpath: (p2) => fs47.realpathSync(p2)
18912
+ realpath: (p2) => fs48.realpathSync(p2)
18743
18913
  };
18744
18914
  function readOrigin(cwd) {
18745
18915
  try {
@@ -18768,7 +18938,7 @@ function deriveProjectIdentity(cwd = process.cwd()) {
18768
18938
  } catch {
18769
18939
  }
18770
18940
  const hash = crypto2.createHash("sha256").update(real).digest("hex");
18771
- return { projectKey: `path:${hash}`, projectLabel: path49.basename(real) || "project" };
18941
+ return { projectKey: `path:${hash}`, projectLabel: path50.basename(real) || "project" };
18772
18942
  }
18773
18943
 
18774
18944
  // src/beads/project-prefix.ts
@@ -18810,17 +18980,17 @@ var _provisionSeam = {
18810
18980
  };
18811
18981
  var _linkSeam = {
18812
18982
  platform: () => process.platform,
18813
- homedir: () => os37.homedir(),
18983
+ homedir: () => os38.homedir(),
18814
18984
  isWritableDir: (dir) => {
18815
18985
  try {
18816
- fs48.accessSync(dir, fs48.constants.W_OK);
18986
+ fs49.accessSync(dir, fs49.constants.W_OK);
18817
18987
  return true;
18818
18988
  } catch {
18819
18989
  return false;
18820
18990
  }
18821
18991
  },
18822
18992
  ensureDir: (dir) => {
18823
- fs48.mkdirSync(dir, { recursive: true });
18993
+ fs49.mkdirSync(dir, { recursive: true });
18824
18994
  },
18825
18995
  /**
18826
18996
  * A directory to symlink `bd` into so the AGENT's shell + Claude Code's
@@ -18841,9 +19011,9 @@ var _linkSeam = {
18841
19011
  * which `linkBdOntoPath` creates if missing.
18842
19012
  */
18843
19013
  cliBinDir: () => {
18844
- const pathDirs = (process.env.PATH ?? "").split(path50.delimiter).filter(Boolean);
19014
+ const pathDirs = (process.env.PATH ?? "").split(path51.delimiter).filter(Boolean);
18845
19015
  const home = _linkSeam.homedir();
18846
- const localBin = home ? path50.join(home, ".local", "bin") : null;
19016
+ const localBin = home ? path51.join(home, ".local", "bin") : null;
18847
19017
  if (localBin) {
18848
19018
  try {
18849
19019
  _linkSeam.ensureDir(localBin);
@@ -18853,16 +19023,16 @@ var _linkSeam = {
18853
19023
  const candidates = [];
18854
19024
  if (localBin) candidates.push(localBin);
18855
19025
  try {
18856
- candidates.push(path50.dirname(process.execPath));
19026
+ candidates.push(path51.dirname(process.execPath));
18857
19027
  } catch {
18858
19028
  }
18859
19029
  candidates.push("/usr/local/bin");
18860
19030
  const entry = process.argv[1];
18861
19031
  if (entry) {
18862
19032
  try {
18863
- candidates.push(path50.dirname(fs48.realpathSync(entry)));
19033
+ candidates.push(path51.dirname(fs49.realpathSync(entry)));
18864
19034
  } catch {
18865
- candidates.push(path50.dirname(entry));
19035
+ candidates.push(path51.dirname(entry));
18866
19036
  }
18867
19037
  }
18868
19038
  const onPathWritable = candidates.find(
@@ -18874,20 +19044,20 @@ var _linkSeam = {
18874
19044
  /** Current symlink target at `linkPath`, or null when absent / not a link. */
18875
19045
  readlink: (linkPath) => {
18876
19046
  try {
18877
- return fs48.readlinkSync(linkPath);
19047
+ return fs49.readlinkSync(linkPath);
18878
19048
  } catch {
18879
19049
  return null;
18880
19050
  }
18881
19051
  },
18882
- unlink: (linkPath) => fs48.unlinkSync(linkPath),
18883
- symlink: (target, linkPath) => fs48.symlinkSync(target, linkPath)
19052
+ unlink: (linkPath) => fs49.unlinkSync(linkPath),
19053
+ symlink: (target, linkPath) => fs49.symlinkSync(target, linkPath)
18884
19054
  };
18885
19055
  function linkBdOntoPath(binaryPath) {
18886
19056
  if (_linkSeam.platform() === "win32") return;
18887
19057
  const binDir = _linkSeam.cliBinDir();
18888
19058
  if (!binDir) return;
18889
19059
  _linkSeam.ensureDir(binDir);
18890
- const linkPath = path50.join(binDir, "bd");
19060
+ const linkPath = path51.join(binDir, "bd");
18891
19061
  if (linkPath === binaryPath) return;
18892
19062
  const current = _linkSeam.readlink(linkPath);
18893
19063
  if (current === binaryPath) return;
@@ -19082,7 +19252,7 @@ function dedupeRecipes(agents) {
19082
19252
 
19083
19253
  // src/beads/watcher.ts
19084
19254
  var crypto4 = __toESM(require("crypto"));
19085
- var path51 = __toESM(require("path"));
19255
+ var path52 = __toESM(require("path"));
19086
19256
  var API_BASE6 = resolveApiBaseUrl();
19087
19257
  var DEBOUNCE_MS2 = 400;
19088
19258
  var ZERO_SUMMARY = {
@@ -19106,7 +19276,7 @@ var BeadsWatcher = class {
19106
19276
  constructor(opts) {
19107
19277
  this.opts = opts;
19108
19278
  this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
19109
- this.feedPath = opts.feedPath ?? path51.join(opts.cwd ?? process.cwd(), ".beads", "last-touched");
19279
+ this.feedPath = opts.feedPath ?? path52.join(opts.cwd ?? process.cwd(), ".beads", "last-touched");
19110
19280
  this.apiBase = opts.apiBaseUrl ?? API_BASE6;
19111
19281
  }
19112
19282
  opts;
@@ -19523,8 +19693,8 @@ function cleanupAttachmentTempFiles() {
19523
19693
  function saveFilesTemp(files) {
19524
19694
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
19525
19695
  const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
19526
- const tmpPath = path53.join(os39.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
19527
- fs50.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
19696
+ const tmpPath = path54.join(os40.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
19697
+ fs51.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
19528
19698
  pendingAttachmentFiles.add(tmpPath);
19529
19699
  return tmpPath;
19530
19700
  });
@@ -19736,9 +19906,9 @@ var listFiles = async (ctx, cmd, parsed) => {
19736
19906
  await ctx.relay.sendResult(cmd.id, "completed", result);
19737
19907
  };
19738
19908
  var envReadH = async (ctx, cmd) => {
19739
- const envPath = path53.join(process.cwd(), ".env");
19909
+ const envPath = path54.join(process.cwd(), ".env");
19740
19910
  try {
19741
- const raw = await fs50.promises.readFile(envPath, "utf8");
19911
+ const raw = await fs51.promises.readFile(envPath, "utf8");
19742
19912
  await ctx.relay.sendResult(cmd.id, "completed", {
19743
19913
  exists: true,
19744
19914
  vars: parseDotenv(raw)
@@ -19769,14 +19939,14 @@ var envWriteH = async (ctx, cmd, parsed) => {
19769
19939
  }
19770
19940
  seen.add(v.key);
19771
19941
  }
19772
- const envPath = path53.join(process.cwd(), ".env");
19773
- const tmpPath = path53.join(process.cwd(), ".env.codeam.tmp");
19942
+ const envPath = path54.join(process.cwd(), ".env");
19943
+ const tmpPath = path54.join(process.cwd(), ".env.codeam.tmp");
19774
19944
  try {
19775
- await fs50.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
19776
- await fs50.promises.rename(tmpPath, envPath);
19945
+ await fs51.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
19946
+ await fs51.promises.rename(tmpPath, envPath);
19777
19947
  await ctx.relay.sendResult(cmd.id, "completed", { ok: true, count: vars.length });
19778
19948
  } catch (err) {
19779
- await fs50.promises.rm(tmpPath, { force: true }).catch(() => void 0);
19949
+ await fs51.promises.rm(tmpPath, { force: true }).catch(() => void 0);
19780
19950
  await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
19781
19951
  }
19782
19952
  };
@@ -19820,7 +19990,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
19820
19990
  let configuredAgent = rawAgentId;
19821
19991
  if (!configuredAgent) {
19822
19992
  try {
19823
- const raw = JSON.parse(fs50.readFileSync(headroomConfigPath(), "utf8"));
19993
+ const raw = JSON.parse(fs51.readFileSync(headroomConfigPath(), "utf8"));
19824
19994
  configuredAgent = raw.agent ?? "";
19825
19995
  } catch {
19826
19996
  }
@@ -19854,7 +20024,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
19854
20024
  persist: persistHeadroomConfig,
19855
20025
  readEnabled: () => {
19856
20026
  try {
19857
- const raw = JSON.parse(fs50.readFileSync(headroomConfigPath(), "utf8"));
20027
+ const raw = JSON.parse(fs51.readFileSync(headroomConfigPath(), "utf8"));
19858
20028
  return raw.enabled === true;
19859
20029
  } catch {
19860
20030
  return false;
@@ -19943,7 +20113,7 @@ var headroomBudgetH = async (ctx, cmd) => {
19943
20113
  }
19944
20114
  let headroomActive = false;
19945
20115
  try {
19946
- const raw = JSON.parse(fs50.readFileSync(headroomConfigPath(), "utf8"));
20116
+ const raw = JSON.parse(fs51.readFileSync(headroomConfigPath(), "utf8"));
19947
20117
  headroomActive = raw.enabled === true;
19948
20118
  } catch {
19949
20119
  }
@@ -19953,7 +20123,7 @@ var headroomBudgetH = async (ctx, cmd) => {
19953
20123
  }
19954
20124
  let existingConfig = { enabled: true };
19955
20125
  try {
19956
- existingConfig = JSON.parse(fs50.readFileSync(headroomConfigPath(), "utf8"));
20126
+ existingConfig = JSON.parse(fs51.readFileSync(headroomConfigPath(), "utf8"));
19957
20127
  } catch {
19958
20128
  }
19959
20129
  if (payload.budgetEnabled && payload.budgetUsd != null) {
@@ -20071,13 +20241,13 @@ var CLI_UPDATE_MAX_ATTEMPTS = 3;
20071
20241
  function buildNpmInstallInvocation(opts) {
20072
20242
  const entryScript = opts?.entryScript ?? process.argv[1] ?? "";
20073
20243
  const execPath = opts?.execPath ?? process.execPath;
20074
- const exists2 = opts?.existsSync ?? fs50.existsSync;
20075
- const normalized = entryScript.split(path53.sep).join("/");
20244
+ const exists2 = opts?.existsSync ?? fs51.existsSync;
20245
+ const normalized = entryScript.split(path54.sep).join("/");
20076
20246
  const marker = "/lib/node_modules/codeam-cli/";
20077
20247
  const markerIdx = normalized.indexOf(marker);
20078
20248
  const prefix = markerIdx > 0 ? entryScript.slice(0, markerIdx) : null;
20079
- const siblingNpm = path53.join(
20080
- path53.dirname(execPath),
20249
+ const siblingNpm = path54.join(
20250
+ path54.dirname(execPath),
20081
20251
  process.platform === "win32" ? "npm.cmd" : "npm"
20082
20252
  );
20083
20253
  const command2 = exists2(siblingNpm) ? siblingNpm : "npm";
@@ -20919,11 +21089,11 @@ function readTokenFromArgs(args2) {
20919
21089
  }
20920
21090
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
20921
21091
  if (fileFlag) {
20922
- const path68 = fileFlag.slice("--token-file=".length);
21092
+ const path69 = fileFlag.slice("--token-file=".length);
20923
21093
  try {
20924
- const content = fs51.readFileSync(path68, "utf8").trim();
20925
- if (content.length === 0) fail(`--token-file ${path68} is empty`);
20926
- rmIfExistsQuiet(path68);
21094
+ const content = fs52.readFileSync(path69, "utf8").trim();
21095
+ if (content.length === 0) fail(`--token-file ${path69} is empty`);
21096
+ rmIfExistsQuiet(path69);
20927
21097
  return content;
20928
21098
  } catch (err) {
20929
21099
  fail(`Could not read --token-file: ${err.message}`);
@@ -20947,7 +21117,7 @@ async function claimOnce(token, pluginId, pluginSecretHash) {
20947
21117
  pluginId,
20948
21118
  ideName: "codeam-cli (codespace)",
20949
21119
  ideVersion: process.env.npm_package_version ?? "unknown",
20950
- hostname: os40.hostname(),
21120
+ hostname: os41.hostname(),
20951
21121
  codespaceName: process.env.CODESPACE_NAME ?? "",
20952
21122
  // Current git branch of the codespace's working directory, so the
20953
21123
  // backend can populate `PairedSession.branch` for the codespace pair.
@@ -21008,7 +21178,7 @@ async function claim(token, pluginId, pluginSecretHash) {
21008
21178
  }
21009
21179
  }
21010
21180
  function pairAutoLockPath() {
21011
- return path54.join(os40.homedir(), ".codeam", "pair-auto.lock");
21181
+ return path55.join(os41.homedir(), ".codeam", "pair-auto.lock");
21012
21182
  }
21013
21183
  function isLivePairAuto(pid) {
21014
21184
  if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
@@ -21018,7 +21188,7 @@ function isLivePairAuto(pid) {
21018
21188
  if (e.code !== "EPERM") return false;
21019
21189
  }
21020
21190
  try {
21021
- return fs51.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
21191
+ return fs52.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
21022
21192
  } catch {
21023
21193
  return true;
21024
21194
  }
@@ -21028,24 +21198,24 @@ function isLiveCodeam(pid) {
21028
21198
  }
21029
21199
  function daemonLockPath(sessionId) {
21030
21200
  const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
21031
- return path54.join(os40.homedir(), ".codeam", `daemon-${safe}.lock`);
21201
+ return path55.join(os41.homedir(), ".codeam", `daemon-${safe}.lock`);
21032
21202
  }
21033
21203
  function acquireDaemonLock(sessionId) {
21034
21204
  const lockPath = daemonLockPath(sessionId);
21035
21205
  try {
21036
- fs51.mkdirSync(path54.dirname(lockPath), { recursive: true });
21206
+ fs52.mkdirSync(path55.dirname(lockPath), { recursive: true });
21037
21207
  try {
21038
- fs51.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
21208
+ fs52.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
21039
21209
  } catch (e) {
21040
21210
  if (e.code !== "EEXIST") throw e;
21041
- const holder = Number(fs51.readFileSync(lockPath, "utf8").trim());
21211
+ const holder = Number(fs52.readFileSync(lockPath, "utf8").trim());
21042
21212
  if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
21043
- fs51.writeFileSync(lockPath, String(process.pid));
21213
+ fs52.writeFileSync(lockPath, String(process.pid));
21044
21214
  }
21045
21215
  const release3 = () => {
21046
21216
  try {
21047
- if (fs51.existsSync(lockPath) && Number(fs51.readFileSync(lockPath, "utf8").trim()) === process.pid) {
21048
- fs51.unlinkSync(lockPath);
21217
+ if (fs52.existsSync(lockPath) && Number(fs52.readFileSync(lockPath, "utf8").trim()) === process.pid) {
21218
+ fs52.unlinkSync(lockPath);
21049
21219
  }
21050
21220
  } catch {
21051
21221
  }
@@ -21067,19 +21237,19 @@ function acquireDaemonLock(sessionId) {
21067
21237
  function acquireSingletonLock() {
21068
21238
  const lockPath = pairAutoLockPath();
21069
21239
  try {
21070
- fs51.mkdirSync(path54.dirname(lockPath), { recursive: true });
21240
+ fs52.mkdirSync(path55.dirname(lockPath), { recursive: true });
21071
21241
  try {
21072
- fs51.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
21242
+ fs52.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
21073
21243
  } catch (e) {
21074
21244
  if (e.code !== "EEXIST") throw e;
21075
- const holder = Number(fs51.readFileSync(lockPath, "utf8").trim());
21245
+ const holder = Number(fs52.readFileSync(lockPath, "utf8").trim());
21076
21246
  if (isLivePairAuto(holder)) return false;
21077
- fs51.writeFileSync(lockPath, String(process.pid));
21247
+ fs52.writeFileSync(lockPath, String(process.pid));
21078
21248
  }
21079
21249
  process.once("exit", () => {
21080
21250
  try {
21081
- if (fs51.existsSync(lockPath) && Number(fs51.readFileSync(lockPath, "utf8").trim()) === process.pid) {
21082
- fs51.unlinkSync(lockPath);
21251
+ if (fs52.existsSync(lockPath) && Number(fs52.readFileSync(lockPath, "utf8").trim()) === process.pid) {
21252
+ fs52.unlinkSync(lockPath);
21083
21253
  }
21084
21254
  } catch {
21085
21255
  }
@@ -21524,7 +21694,7 @@ var AgentService = class _AgentService {
21524
21694
  };
21525
21695
 
21526
21696
  // src/agents/acp/adapters.ts
21527
- var path56 = __toESM(require("path"));
21697
+ var path57 = __toESM(require("path"));
21528
21698
 
21529
21699
  // src/agents/acp/agent-binary.ts
21530
21700
  var import_fs4 = __toESM(require("fs"));
@@ -21557,14 +21727,14 @@ function defaultSdkDir() {
21557
21727
  return resolveSdkDirViaRequire();
21558
21728
  }
21559
21729
  function resolveClaudeNativeBinary(deps = {}) {
21560
- const existsSync24 = deps.existsSync ?? import_fs4.default.existsSync;
21730
+ const existsSync25 = deps.existsSync ?? import_fs4.default.existsSync;
21561
21731
  const platformKey = deps.platformKey ?? currentPlatformKey();
21562
21732
  const sdkDir = deps.sdkDir !== void 0 ? deps.sdkDir : defaultSdkDir();
21563
21733
  if (!sdkDir) return null;
21564
21734
  const scopeDir = import_path8.default.dirname(sdkDir);
21565
21735
  const binName = platformKey.startsWith("win32-") ? "claude.exe" : "claude";
21566
21736
  const candidate = import_path8.default.join(scopeDir, `claude-agent-sdk-${platformKey}`, binName);
21567
- return existsSync24(candidate) ? candidate : null;
21737
+ return existsSync25(candidate) ? candidate : null;
21568
21738
  }
21569
21739
  var realSleep = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
21570
21740
  async function waitForClaudeNativeBinary(opts = {}) {
@@ -21615,18 +21785,18 @@ async function waitForCommandOnPath(cmd, opts = {}) {
21615
21785
  return check();
21616
21786
  }
21617
21787
  function resolveCursorAgentBinary(deps = {}) {
21618
- const existsSync24 = deps.existsSync ?? import_fs4.default.existsSync;
21788
+ const existsSync25 = deps.existsSync ?? import_fs4.default.existsSync;
21619
21789
  const platform3 = deps.platform ?? process.platform;
21620
21790
  const env = deps.env ?? process.env;
21621
21791
  if (platform3 === "win32") {
21622
21792
  const localAppData = env.LOCALAPPDATA;
21623
21793
  if (!localAppData) return null;
21624
21794
  const exe = import_path8.default.win32.join(localAppData, "cursor-agent", "cursor-agent.exe");
21625
- return existsSync24(exe) ? exe : null;
21795
+ return existsSync25(exe) ? exe : null;
21626
21796
  }
21627
21797
  const home = deps.homedir ?? import_os7.default.homedir();
21628
21798
  const unix = import_path8.default.posix.join(home, ".local", "bin", "cursor-agent");
21629
- return existsSync24(unix) ? unix : null;
21799
+ return existsSync25(unix) ? unix : null;
21630
21800
  }
21631
21801
  async function waitForCursorAgent(opts = {}) {
21632
21802
  const timeoutMs = opts.timeoutMs ?? 18e4;
@@ -21706,13 +21876,13 @@ function resolveBin(pkgName, binName) {
21706
21876
  try {
21707
21877
  const manifestPath = require_.resolve(`${pkgName}/package.json`);
21708
21878
  const manifest = require_(`${pkgName}/package.json`);
21709
- const pkgDir = path56.dirname(manifestPath);
21879
+ const pkgDir = path57.dirname(manifestPath);
21710
21880
  const bin = manifest.bin;
21711
21881
  if (!bin) return null;
21712
- if (typeof bin === "string") return path56.resolve(pkgDir, bin);
21882
+ if (typeof bin === "string") return path57.resolve(pkgDir, bin);
21713
21883
  const target = binName ?? Object.keys(bin)[0];
21714
21884
  if (!target || !bin[target]) return null;
21715
- return path56.resolve(pkgDir, bin[target]);
21885
+ return path57.resolve(pkgDir, bin[target]);
21716
21886
  } catch {
21717
21887
  return null;
21718
21888
  }
@@ -21792,12 +21962,12 @@ function requiresAcp(agent) {
21792
21962
  }
21793
21963
 
21794
21964
  // src/agents/acp/runner.ts
21795
- var import_node_crypto7 = require("crypto");
21965
+ var import_node_crypto8 = require("crypto");
21796
21966
 
21797
21967
  // src/services/history.service.ts
21798
- var fs53 = __toESM(require("fs"));
21799
- var path57 = __toESM(require("path"));
21800
- var os42 = __toESM(require("os"));
21968
+ var fs54 = __toESM(require("fs"));
21969
+ var path58 = __toESM(require("path"));
21970
+ var os43 = __toESM(require("os"));
21801
21971
  var https7 = __toESM(require("https"));
21802
21972
  var http6 = __toESM(require("http"));
21803
21973
  var import_zod2 = require("zod");
@@ -21824,7 +21994,7 @@ function parseJsonl(filePath) {
21824
21994
  const messages = [];
21825
21995
  let raw;
21826
21996
  try {
21827
- raw = fs53.readFileSync(filePath, "utf8");
21997
+ raw = fs54.readFileSync(filePath, "utf8");
21828
21998
  } catch (err) {
21829
21999
  if (err.code !== "ENOENT") {
21830
22000
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -21965,7 +22135,7 @@ var HistoryService = class _HistoryService {
21965
22135
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
21966
22136
  }
21967
22137
  get projectDir() {
21968
- return this.runtime.resolveHistoryDir(this.cwd) ?? path57.join(os42.homedir(), ".claude", "projects", encodeCwd(this.cwd));
22138
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path58.join(os43.homedir(), ".claude", "projects", encodeCwd(this.cwd));
21969
22139
  }
21970
22140
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
21971
22141
  setCurrentConversationId(id) {
@@ -21977,7 +22147,7 @@ var HistoryService = class _HistoryService {
21977
22147
  /** Return the current message count in the active conversation. */
21978
22148
  getCurrentMessageCount() {
21979
22149
  if (!this.currentConversationId) return 0;
21980
- const filePath = path57.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22150
+ const filePath = path58.join(this.projectDir, `${this.currentConversationId}.jsonl`);
21981
22151
  return parseJsonl(filePath).length;
21982
22152
  }
21983
22153
  /**
@@ -21988,7 +22158,7 @@ var HistoryService = class _HistoryService {
21988
22158
  const deadline = Date.now() + timeoutMs;
21989
22159
  while (Date.now() < deadline) {
21990
22160
  if (!this.currentConversationId) return null;
21991
- const filePath = path57.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22161
+ const filePath = path58.join(this.projectDir, `${this.currentConversationId}.jsonl`);
21992
22162
  const messages = parseJsonl(filePath);
21993
22163
  if (messages.length > previousCount) {
21994
22164
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -22014,16 +22184,16 @@ var HistoryService = class _HistoryService {
22014
22184
  const dir = this.projectDir;
22015
22185
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
22016
22186
  try {
22017
- const files = fs53.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
22187
+ const files = fs54.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
22018
22188
  try {
22019
- const stat3 = fs53.statSync(path57.join(dir, e.name));
22189
+ const stat3 = fs54.statSync(path58.join(dir, e.name));
22020
22190
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
22021
22191
  } catch {
22022
22192
  return { name: e.name, mtime: 0, birthtime: 0 };
22023
22193
  }
22024
22194
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
22025
22195
  if (files.length > 0) {
22026
- this.currentConversationId = path57.basename(files[0].name, ".jsonl");
22196
+ this.currentConversationId = path58.basename(files[0].name, ".jsonl");
22027
22197
  }
22028
22198
  } catch {
22029
22199
  }
@@ -22057,13 +22227,13 @@ var HistoryService = class _HistoryService {
22057
22227
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
22058
22228
  let entries;
22059
22229
  try {
22060
- entries = fs53.readdirSync(dir, { withFileTypes: true });
22230
+ entries = fs54.readdirSync(dir, { withFileTypes: true });
22061
22231
  } catch {
22062
22232
  return null;
22063
22233
  }
22064
22234
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
22065
22235
  try {
22066
- const stat3 = fs53.statSync(path57.join(dir, e.name));
22236
+ const stat3 = fs54.statSync(path58.join(dir, e.name));
22067
22237
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
22068
22238
  } catch {
22069
22239
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -22072,12 +22242,12 @@ var HistoryService = class _HistoryService {
22072
22242
  if (files.length === 0) return null;
22073
22243
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
22074
22244
  if (!files.some((f) => f.name === targetFile)) return null;
22075
- return this.extractUsageFromFile(path57.join(dir, targetFile));
22245
+ return this.extractUsageFromFile(path58.join(dir, targetFile));
22076
22246
  }
22077
22247
  extractUsageFromFile(filePath) {
22078
22248
  let raw;
22079
22249
  try {
22080
- raw = fs53.readFileSync(filePath, "utf8");
22250
+ raw = fs54.readFileSync(filePath, "utf8");
22081
22251
  } catch {
22082
22252
  return null;
22083
22253
  }
@@ -22122,9 +22292,9 @@ var HistoryService = class _HistoryService {
22122
22292
  let totalCost = 0;
22123
22293
  let files;
22124
22294
  try {
22125
- files = fs53.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
22295
+ files = fs54.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
22126
22296
  try {
22127
- return fs53.statSync(path57.join(projectDir, f)).mtimeMs >= monthStartMs;
22297
+ return fs54.statSync(path58.join(projectDir, f)).mtimeMs >= monthStartMs;
22128
22298
  } catch {
22129
22299
  return false;
22130
22300
  }
@@ -22135,7 +22305,7 @@ var HistoryService = class _HistoryService {
22135
22305
  for (const file of files) {
22136
22306
  let raw;
22137
22307
  try {
22138
- raw = fs53.readFileSync(path57.join(projectDir, file), "utf8");
22308
+ raw = fs54.readFileSync(path58.join(projectDir, file), "utf8");
22139
22309
  } catch {
22140
22310
  continue;
22141
22311
  }
@@ -22214,7 +22384,7 @@ var HistoryService = class _HistoryService {
22214
22384
  if (this.runtime.resolveHistoryFile) {
22215
22385
  return this.runtime.resolveHistoryFile(this.cwd, sessionId);
22216
22386
  }
22217
- return path57.join(this.projectDir, `${sessionId}.jsonl`);
22387
+ return path58.join(this.projectDir, `${sessionId}.jsonl`);
22218
22388
  }
22219
22389
  /**
22220
22390
  * Parse a conversation's messages from disk, agent-aware. Claude uses the
@@ -22248,7 +22418,7 @@ var HistoryService = class _HistoryService {
22248
22418
  };
22249
22419
  });
22250
22420
  }
22251
- return parseJsonl(path57.join(this.projectDir, `${sessionId}.jsonl`));
22421
+ return parseJsonl(path58.join(this.projectDir, `${sessionId}.jsonl`));
22252
22422
  }
22253
22423
  async loadConversation(sessionId) {
22254
22424
  const messages = this.readConversation(sessionId);
@@ -22304,7 +22474,7 @@ var HistoryService = class _HistoryService {
22304
22474
  if (!filePath) return false;
22305
22475
  let mtimeMs;
22306
22476
  try {
22307
- mtimeMs = fs53.statSync(filePath).mtimeMs;
22477
+ mtimeMs = fs54.statSync(filePath).mtimeMs;
22308
22478
  } catch {
22309
22479
  return false;
22310
22480
  }
@@ -22373,10 +22543,10 @@ var HistoryService = class _HistoryService {
22373
22543
 
22374
22544
  // src/agents/acp/client.ts
22375
22545
  var import_node_child_process21 = require("child_process");
22376
- var fs54 = __toESM(require("fs/promises"));
22546
+ var fs55 = __toESM(require("fs/promises"));
22377
22547
  var fsSync = __toESM(require("fs"));
22378
- var os43 = __toESM(require("os"));
22379
- var path58 = __toESM(require("path"));
22548
+ var os44 = __toESM(require("os"));
22549
+ var path59 = __toESM(require("path"));
22380
22550
  var import_node_stream = require("stream");
22381
22551
 
22382
22552
  // ../../node_modules/@agentclientprotocol/sdk/dist/acp.js
@@ -25290,7 +25460,7 @@ var AcpClient = class {
25290
25460
  },
25291
25461
  readTextFile: async (params) => {
25292
25462
  try {
25293
- const content = await fs54.readFile(params.path, "utf8");
25463
+ const content = await fs55.readFile(params.path, "utf8");
25294
25464
  return applyLineRange(content, params.line ?? null, params.limit ?? null);
25295
25465
  } catch (err) {
25296
25466
  const code = err.code;
@@ -25310,7 +25480,7 @@ var AcpClient = class {
25310
25480
  },
25311
25481
  writeTextFile: async (params) => {
25312
25482
  try {
25313
- await fs54.writeFile(params.path, params.content, "utf8");
25483
+ await fs55.writeFile(params.path, params.content, "utf8");
25314
25484
  return {};
25315
25485
  } catch (err) {
25316
25486
  const code = err.code;
@@ -25359,29 +25529,29 @@ function applyLineRange(content, line, limit) {
25359
25529
  return { content: lines.slice(start2, end).join("\n") };
25360
25530
  }
25361
25531
  function knownAgentBinaryDirs() {
25362
- const home = os43.homedir();
25532
+ const home = os44.homedir();
25363
25533
  const out2 = [];
25364
25534
  out2.push("/tmp/codeam-node20/bin");
25365
25535
  for (const root of [
25366
25536
  "/usr/local/share/nvm/versions/node",
25367
- path58.join(home, ".nvm/versions/node")
25537
+ path59.join(home, ".nvm/versions/node")
25368
25538
  ]) {
25369
25539
  try {
25370
25540
  for (const child of fsSync.readdirSync(root)) {
25371
- out2.push(path58.join(root, child, "bin"));
25541
+ out2.push(path59.join(root, child, "bin"));
25372
25542
  }
25373
25543
  } catch {
25374
25544
  }
25375
25545
  }
25376
- out2.push(path58.join(home, ".volta/bin"));
25546
+ out2.push(path59.join(home, ".volta/bin"));
25377
25547
  out2.push("/usr/local/bin");
25378
25548
  out2.push("/usr/bin");
25379
- out2.push(path58.join(home, ".local/bin"));
25380
- out2.push(path58.join(home, "bin"));
25549
+ out2.push(path59.join(home, ".local/bin"));
25550
+ out2.push(path59.join(home, "bin"));
25381
25551
  if (process.platform === "win32") {
25382
25552
  const { LOCALAPPDATA, APPDATA } = process.env;
25383
- if (LOCALAPPDATA) out2.push(path58.join(LOCALAPPDATA, "cursor-agent"));
25384
- if (APPDATA) out2.push(path58.join(APPDATA, "npm"));
25553
+ if (LOCALAPPDATA) out2.push(path59.join(LOCALAPPDATA, "cursor-agent"));
25554
+ if (APPDATA) out2.push(path59.join(APPDATA, "npm"));
25385
25555
  }
25386
25556
  return out2.filter((p2) => {
25387
25557
  try {
@@ -25393,7 +25563,7 @@ function knownAgentBinaryDirs() {
25393
25563
  }
25394
25564
  function expandPathForAgentBinaries(existingPath) {
25395
25565
  const existing = new Set(
25396
- existingPath.split(path58.delimiter).filter((p2) => p2.length > 0)
25566
+ existingPath.split(path59.delimiter).filter((p2) => p2.length > 0)
25397
25567
  );
25398
25568
  const additions = [];
25399
25569
  for (const dir of knownAgentBinaryDirs()) {
@@ -25403,7 +25573,7 @@ function expandPathForAgentBinaries(existingPath) {
25403
25573
  }
25404
25574
  }
25405
25575
  if (additions.length === 0) return existingPath;
25406
- return [...additions, existingPath].filter((p2) => p2.length > 0).join(path58.delimiter);
25576
+ return [...additions, existingPath].filter((p2) => p2.length > 0).join(path59.delimiter);
25407
25577
  }
25408
25578
 
25409
25579
  // src/agents/acp/headroom-budget-proxy.ts
@@ -25885,15 +26055,15 @@ function commonPrefixLength(a, b) {
25885
26055
 
25886
26056
  // src/agents/acp/onboarding.ts
25887
26057
  var import_child_process26 = require("child_process");
25888
- var fs55 = __toESM(require("fs"));
25889
- var os44 = __toESM(require("os"));
25890
- var path59 = __toESM(require("path"));
26058
+ var fs56 = __toESM(require("fs"));
26059
+ var os45 = __toESM(require("os"));
26060
+ var path60 = __toESM(require("path"));
25891
26061
  var _onboardingSeam = {
25892
- markerPath: (sessionId) => path59.join(os44.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
25893
- exists: (p2) => fs55.existsSync(p2),
26062
+ markerPath: (sessionId) => path60.join(os45.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
26063
+ exists: (p2) => fs56.existsSync(p2),
25894
26064
  write: (p2) => {
25895
- fs55.mkdirSync(path59.dirname(p2), { recursive: true });
25896
- fs55.writeFileSync(p2, "");
26065
+ fs56.mkdirSync(path60.dirname(p2), { recursive: true });
26066
+ fs56.writeFileSync(p2, "");
25897
26067
  },
25898
26068
  disabled: () => {
25899
26069
  const v = process.env.CODEAM_ONBOARDING_DISABLED;
@@ -25930,7 +26100,7 @@ function resolveRepoName(cwd) {
25930
26100
  if (name) return name;
25931
26101
  }
25932
26102
  }
25933
- const base = path59.basename(cwd || "");
26103
+ const base = path60.basename(cwd || "");
25934
26104
  if (base && !isUuid(base)) return base;
25935
26105
  return "this project";
25936
26106
  }
@@ -25993,7 +26163,7 @@ async function runOnboardingTurn(opts) {
25993
26163
  }
25994
26164
 
25995
26165
  // src/agents/acp/mappers.ts
25996
- var import_node_crypto6 = require("crypto");
26166
+ var import_node_crypto7 = require("crypto");
25997
26167
  function mapSessionUpdate(notification) {
25998
26168
  const update = notification.update;
25999
26169
  switch (update.sessionUpdate) {
@@ -26056,7 +26226,7 @@ function mapPermissionRequest(request) {
26056
26226
  }
26057
26227
  return {
26058
26228
  event: {
26059
- questionId: (0, import_node_crypto6.randomUUID)(),
26229
+ questionId: (0, import_node_crypto7.randomUUID)(),
26060
26230
  prompt,
26061
26231
  options: labels.length > 0 ? labels : void 0
26062
26232
  },
@@ -26066,7 +26236,7 @@ function mapPermissionRequest(request) {
26066
26236
  }
26067
26237
  function messageChunkId(messageId) {
26068
26238
  if (typeof messageId === "string" && messageId.length > 0) return messageId;
26069
- return (0, import_node_crypto6.randomUUID)();
26239
+ return (0, import_node_crypto7.randomUUID)();
26070
26240
  }
26071
26241
  function extractText4(content) {
26072
26242
  if (!content || typeof content !== "object") return null;
@@ -26182,8 +26352,8 @@ var import_crypto5 = require("crypto");
26182
26352
 
26183
26353
  // src/services/turn-files/git-changeset.ts
26184
26354
  var import_child_process27 = require("child_process");
26185
- var fs56 = __toESM(require("fs/promises"));
26186
- var path60 = __toESM(require("path"));
26355
+ var fs57 = __toESM(require("fs/promises"));
26356
+ var path61 = __toESM(require("path"));
26187
26357
  async function collectRepoChangeset(opts) {
26188
26358
  const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
26189
26359
  if (status2 === null) return null;
@@ -26201,7 +26371,7 @@ async function collectRepoChangeset(opts) {
26201
26371
  let stats;
26202
26372
  if (row.fileStatus === "added" && numstatEntry === void 0) {
26203
26373
  const lineCount = await readUntrackedLineCount(
26204
- path60.join(opts.repoRoot, row.filePath)
26374
+ path61.join(opts.repoRoot, row.filePath)
26205
26375
  );
26206
26376
  stats = { added: lineCount, removed: 0 };
26207
26377
  } else {
@@ -26232,7 +26402,7 @@ function readUntrackedLineCount(absPath) {
26232
26402
  }
26233
26403
  async function defaultReadUntrackedLineCount(absPath) {
26234
26404
  try {
26235
- const content = await fs56.readFile(absPath, "utf8");
26405
+ const content = await fs57.readFile(absPath, "utf8");
26236
26406
  let count = 0;
26237
26407
  let pos = -1;
26238
26408
  while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
@@ -26324,7 +26494,7 @@ function defaultRunGit(cwd, args2) {
26324
26494
  });
26325
26495
  }
26326
26496
  async function discoverRepos(workingDir, maxDepth = 4) {
26327
- const fs61 = await import("fs/promises");
26497
+ const fs62 = await import("fs/promises");
26328
26498
  const out2 = [];
26329
26499
  await walk(workingDir, 0);
26330
26500
  return out2;
@@ -26332,7 +26502,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
26332
26502
  if (depth > maxDepth) return;
26333
26503
  let entries = [];
26334
26504
  try {
26335
- const dirents = await fs61.readdir(dir, { withFileTypes: true });
26505
+ const dirents = await fs62.readdir(dir, { withFileTypes: true });
26336
26506
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
26337
26507
  } catch {
26338
26508
  return;
@@ -26343,8 +26513,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
26343
26513
  if (hasGit) {
26344
26514
  out2.push({
26345
26515
  repoRoot: dir,
26346
- repoPath: path60.relative(workingDir, dir),
26347
- repoName: path60.basename(dir)
26516
+ repoPath: path61.relative(workingDir, dir),
26517
+ repoName: path61.basename(dir)
26348
26518
  });
26349
26519
  return;
26350
26520
  }
@@ -26352,14 +26522,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
26352
26522
  if (!entry.isDirectory) continue;
26353
26523
  if (entry.name === "node_modules") continue;
26354
26524
  if (entry.name === "dist" || entry.name === "build") continue;
26355
- await walk(path60.join(dir, entry.name), depth + 1);
26525
+ await walk(path61.join(dir, entry.name), depth + 1);
26356
26526
  }
26357
26527
  }
26358
26528
  }
26359
26529
 
26360
26530
  // src/services/turn-files/files-outbox.ts
26361
- var fs57 = __toESM(require("fs/promises"));
26362
- var path61 = __toESM(require("path"));
26531
+ var fs58 = __toESM(require("fs/promises"));
26532
+ var path62 = __toESM(require("path"));
26363
26533
  var import_os8 = require("os");
26364
26534
  var HOME_OUTBOX_DIR = ".codeam/outbox";
26365
26535
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -26392,16 +26562,16 @@ var FilesOutbox = class {
26392
26562
  backoffIndex = 0;
26393
26563
  stopped = false;
26394
26564
  constructor(opts) {
26395
- const base = opts.baseDir ?? path61.join(homeDir(), HOME_OUTBOX_DIR);
26396
- this.filePath = path61.join(base, `${opts.sessionId}.jsonl`);
26565
+ const base = opts.baseDir ?? path62.join(homeDir(), HOME_OUTBOX_DIR);
26566
+ this.filePath = path62.join(base, `${opts.sessionId}.jsonl`);
26397
26567
  this.post = opts.post;
26398
26568
  this.autoSchedule = opts.autoSchedule !== false;
26399
26569
  }
26400
26570
  /** Persist the entry to disk and trigger a flush. Returns once the
26401
26571
  * line is durable on disk (not once the POST succeeds). */
26402
26572
  async enqueue(entry) {
26403
- await fs57.mkdir(path61.dirname(this.filePath), { recursive: true });
26404
- await fs57.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
26573
+ await fs58.mkdir(path62.dirname(this.filePath), { recursive: true });
26574
+ await fs58.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
26405
26575
  this.backoffIndex = 0;
26406
26576
  if (this.autoSchedule) this.scheduleFlush(0);
26407
26577
  }
@@ -26490,7 +26660,7 @@ var FilesOutbox = class {
26490
26660
  async readAll() {
26491
26661
  let raw = "";
26492
26662
  try {
26493
- raw = await fs57.readFile(this.filePath, "utf8");
26663
+ raw = await fs58.readFile(this.filePath, "utf8");
26494
26664
  } catch {
26495
26665
  return [];
26496
26666
  }
@@ -26514,12 +26684,12 @@ var FilesOutbox = class {
26514
26684
  async rewrite(entries) {
26515
26685
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
26516
26686
  if (entries.length === 0) {
26517
- await fs57.unlink(this.filePath).catch(() => void 0);
26687
+ await fs58.unlink(this.filePath).catch(() => void 0);
26518
26688
  return;
26519
26689
  }
26520
26690
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
26521
- await fs57.writeFile(tmpPath, payload, "utf8");
26522
- await fs57.rename(tmpPath, this.filePath);
26691
+ await fs58.writeFile(tmpPath, payload, "utf8");
26692
+ await fs58.rename(tmpPath, this.filePath);
26523
26693
  }
26524
26694
  };
26525
26695
  function applyJitter(ms) {
@@ -27879,7 +28049,7 @@ var AcpHistory = class {
27879
28049
  this.summary = trimmed.length > 120 ? trimmed.slice(0, 117) + "\u2026" : trimmed;
27880
28050
  }
27881
28051
  this.messages.push({
27882
- id: (0, import_node_crypto7.randomUUID)(),
28052
+ id: (0, import_node_crypto8.randomUUID)(),
27883
28053
  role: "user",
27884
28054
  text,
27885
28055
  timestamp: Date.now()
@@ -27888,7 +28058,7 @@ var AcpHistory = class {
27888
28058
  appendAgentReply(text) {
27889
28059
  if (text.length === 0) return;
27890
28060
  this.messages.push({
27891
- id: (0, import_node_crypto7.randomUUID)(),
28061
+ id: (0, import_node_crypto8.randomUUID)(),
27892
28062
  role: "agent",
27893
28063
  text,
27894
28064
  timestamp: Date.now()
@@ -28094,7 +28264,7 @@ async function runAcpSession(opts) {
28094
28264
  currentIndex: 0,
28095
28265
  done: true
28096
28266
  }),
28097
- publishAwaitingAnswer: (prompt, options) => publisher.publishAwaitingAnswer({ questionId: (0, import_node_crypto7.randomUUID)(), prompt, options }),
28267
+ publishAwaitingAnswer: (prompt, options) => publisher.publishAwaitingAnswer({ questionId: (0, import_node_crypto8.randomUUID)(), prompt, options }),
28098
28268
  publishRawChunk: (chunk) => publisher.publishOutput(chunk),
28099
28269
  sendResult: (commandId, status2, result) => relay.sendResult(commandId, status2, result),
28100
28270
  appendAgentReply: (text) => history.appendAgentReply(text),
@@ -29463,7 +29633,7 @@ var NativeTuiDriver = class {
29463
29633
  };
29464
29634
 
29465
29635
  // src/baton/acp-driver.ts
29466
- var import_node_crypto8 = require("crypto");
29636
+ var import_node_crypto9 = require("crypto");
29467
29637
  var AcpDriver = class {
29468
29638
  constructor(deps) {
29469
29639
  this.deps = deps;
@@ -29556,7 +29726,7 @@ var AcpDriver = class {
29556
29726
  currentIndex: 0,
29557
29727
  done: true
29558
29728
  }),
29559
- publishAwaitingAnswer: (prompt, options) => publisher.publishAwaitingAnswer({ questionId: (0, import_node_crypto8.randomUUID)(), prompt, options }),
29729
+ publishAwaitingAnswer: (prompt, options) => publisher.publishAwaitingAnswer({ questionId: (0, import_node_crypto9.randomUUID)(), prompt, options }),
29560
29730
  publishRawChunk: (chunk) => publisher.publishOutput(chunk),
29561
29731
  sendResult: (commandId, status2, result) => relay.sendResult(commandId, status2, result),
29562
29732
  appendAgentReply: (text) => history.appendAgentReply(text),
@@ -29599,7 +29769,7 @@ var AcpDriver = class {
29599
29769
  };
29600
29770
 
29601
29771
  // src/baton/transcript-mirror.ts
29602
- var fs58 = __toESM(require("fs"));
29772
+ var fs59 = __toESM(require("fs"));
29603
29773
  var TranscriptMirror = class {
29604
29774
  constructor(deps) {
29605
29775
  this.deps = deps;
@@ -29666,7 +29836,7 @@ var TranscriptMirror = class {
29666
29836
  }
29667
29837
  };
29668
29838
  function defaultWatch(file, onChange) {
29669
- const w3 = fs58.watch(file, { persistent: false }, () => onChange());
29839
+ const w3 = fs59.watch(file, { persistent: false }, () => onChange());
29670
29840
  return () => w3.close();
29671
29841
  }
29672
29842
 
@@ -29913,15 +30083,15 @@ function toEpochMs(ts) {
29913
30083
  }
29914
30084
 
29915
30085
  // src/agents/claude/onboarding.ts
29916
- var fs59 = __toESM(require("fs"));
29917
- var os45 = __toESM(require("os"));
29918
- var path62 = __toESM(require("path"));
30086
+ var fs60 = __toESM(require("fs"));
30087
+ var os46 = __toESM(require("os"));
30088
+ var path63 = __toESM(require("path"));
29919
30089
  function ensureClaudeOnboarded() {
29920
30090
  try {
29921
- const file = path62.join(os45.homedir(), ".claude.json");
30091
+ const file = path63.join(os46.homedir(), ".claude.json");
29922
30092
  let config = {};
29923
30093
  try {
29924
- config = JSON.parse(fs59.readFileSync(file, "utf8"));
30094
+ config = JSON.parse(fs60.readFileSync(file, "utf8"));
29925
30095
  } catch {
29926
30096
  }
29927
30097
  if (config.hasCompletedOnboarding === true && typeof config.theme === "string") {
@@ -29932,8 +30102,8 @@ function ensureClaudeOnboarded() {
29932
30102
  if (typeof config.lastOnboardingVersion !== "string") {
29933
30103
  config.lastOnboardingVersion = "2.1.177";
29934
30104
  }
29935
- fs59.mkdirSync(path62.dirname(file), { recursive: true });
29936
- fs59.writeFileSync(file, JSON.stringify(config, null, 2));
30105
+ fs60.mkdirSync(path63.dirname(file), { recursive: true });
30106
+ fs60.writeFileSync(file, JSON.stringify(config, null, 2));
29937
30107
  log.info("claude", "pre-completed Claude onboarding (skip first-run theme picker)");
29938
30108
  } catch (err) {
29939
30109
  log.warn("claude", `ensureClaudeOnboarded failed (non-fatal): ${err.message}`);
@@ -30607,7 +30777,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
30607
30777
  var import_child_process28 = require("child_process");
30608
30778
  var import_util4 = require("util");
30609
30779
  var import_picocolors9 = __toESM(require("picocolors"));
30610
- var path63 = __toESM(require("path"));
30780
+ var path64 = __toESM(require("path"));
30611
30781
  var execFileP6 = (0, import_util4.promisify)(import_child_process28.execFile);
30612
30782
  var MAX_BUFFER = 8 * 1024 * 1024;
30613
30783
  function resetStdinForChild() {
@@ -31096,7 +31266,7 @@ var GitHubCodespacesProvider = class {
31096
31266
  });
31097
31267
  }
31098
31268
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
31099
- const remoteDir = path63.posix.dirname(remotePath);
31269
+ const remoteDir = path64.posix.dirname(remotePath);
31100
31270
  const parts = [
31101
31271
  `mkdir -p ${shellQuote(remoteDir)}`,
31102
31272
  `cat > ${shellQuote(remotePath)}`
@@ -31166,7 +31336,7 @@ function shellQuote(s) {
31166
31336
  // src/services/providers/gitpod.ts
31167
31337
  var import_child_process29 = require("child_process");
31168
31338
  var import_util5 = require("util");
31169
- var path64 = __toESM(require("path"));
31339
+ var path65 = __toESM(require("path"));
31170
31340
  var import_picocolors10 = __toESM(require("picocolors"));
31171
31341
  var execFileP7 = (0, import_util5.promisify)(import_child_process29.execFile);
31172
31342
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -31406,7 +31576,7 @@ var GitpodProvider = class {
31406
31576
  });
31407
31577
  }
31408
31578
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
31409
- const remoteDir = path64.posix.dirname(remotePath);
31579
+ const remoteDir = path65.posix.dirname(remotePath);
31410
31580
  const parts = [
31411
31581
  `mkdir -p ${shellQuote2(remoteDir)}`,
31412
31582
  `cat > ${shellQuote2(remotePath)}`
@@ -31442,7 +31612,7 @@ function shellQuote2(s) {
31442
31612
  // src/services/providers/gitlab-workspaces.ts
31443
31613
  var import_child_process30 = require("child_process");
31444
31614
  var import_util6 = require("util");
31445
- var path65 = __toESM(require("path"));
31615
+ var path66 = __toESM(require("path"));
31446
31616
  var execFileP8 = (0, import_util6.promisify)(import_child_process30.execFile);
31447
31617
  var MAX_BUFFER3 = 8 * 1024 * 1024;
31448
31618
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -31702,7 +31872,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
31702
31872
  }
31703
31873
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
31704
31874
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
31705
- const remoteDir = path65.posix.dirname(remotePath);
31875
+ const remoteDir = path66.posix.dirname(remotePath);
31706
31876
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
31707
31877
  if (options.mode != null) {
31708
31878
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -31770,7 +31940,7 @@ function shellQuote3(s) {
31770
31940
  // src/services/providers/railway.ts
31771
31941
  var import_child_process31 = require("child_process");
31772
31942
  var import_util7 = require("util");
31773
- var path66 = __toESM(require("path"));
31943
+ var path67 = __toESM(require("path"));
31774
31944
  var execFileP9 = (0, import_util7.promisify)(import_child_process31.execFile);
31775
31945
  var MAX_BUFFER4 = 8 * 1024 * 1024;
31776
31946
  function resetStdinForChild4() {
@@ -32006,7 +32176,7 @@ var RailwayProvider = class {
32006
32176
  if (!projectId || !serviceId) {
32007
32177
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
32008
32178
  }
32009
- const remoteDir = path66.posix.dirname(remotePath);
32179
+ const remoteDir = path67.posix.dirname(remotePath);
32010
32180
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
32011
32181
  if (options.mode != null) {
32012
32182
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -32651,9 +32821,9 @@ async function invite() {
32651
32821
  // src/commands/doctor.ts
32652
32822
  var import_node_dns = require("dns");
32653
32823
  var import_node_util5 = require("util");
32654
- var import_node_crypto9 = require("crypto");
32655
- var fs60 = __toESM(require("fs"));
32656
- var path67 = __toESM(require("path"));
32824
+ var import_node_crypto10 = require("crypto");
32825
+ var fs61 = __toESM(require("fs"));
32826
+ var path68 = __toESM(require("path"));
32657
32827
  var import_picocolors14 = __toESM(require("picocolors"));
32658
32828
  var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
32659
32829
  async function checkDns(apiBase2) {
@@ -32709,13 +32879,13 @@ async function checkHealth(apiBase2) {
32709
32879
  }
32710
32880
  }
32711
32881
  function checkConfigDir() {
32712
- const dir = path67.join(require("os").homedir(), ".codeam");
32882
+ const dir = path68.join(require("os").homedir(), ".codeam");
32713
32883
  try {
32714
- fs60.mkdirSync(dir, { recursive: true, mode: 448 });
32715
- const probe = path67.join(dir, ".doctor-probe");
32716
- fs60.writeFileSync(probe, "ok", { mode: 384 });
32717
- const read2 = fs60.readFileSync(probe, "utf8");
32718
- fs60.unlinkSync(probe);
32884
+ fs61.mkdirSync(dir, { recursive: true, mode: 448 });
32885
+ const probe = path68.join(dir, ".doctor-probe");
32886
+ fs61.writeFileSync(probe, "ok", { mode: 384 });
32887
+ const read2 = fs61.readFileSync(probe, "utf8");
32888
+ fs61.unlinkSync(probe);
32719
32889
  if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
32720
32890
  return {
32721
32891
  id: "config-dir",
@@ -32755,9 +32925,9 @@ function checkSessions() {
32755
32925
  }
32756
32926
  }
32757
32927
  function checkAgentBinaries() {
32758
- const os47 = createOsStrategy();
32928
+ const os48 = createOsStrategy();
32759
32929
  return getEnabledAgents().map((meta) => {
32760
- const found = os47.findInPath(meta.binaryName);
32930
+ const found = os48.findInPath(meta.binaryName);
32761
32931
  return {
32762
32932
  id: `agent-${meta.id}`,
32763
32933
  label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
@@ -32779,7 +32949,7 @@ function checkNodePty() {
32779
32949
  detail: "not required on this platform"
32780
32950
  };
32781
32951
  }
32782
- const vendoredPath = path67.join(__dirname, "vendor", "node-pty");
32952
+ const vendoredPath = path68.join(__dirname, "vendor", "node-pty");
32783
32953
  for (const target of [vendoredPath, "node-pty"]) {
32784
32954
  try {
32785
32955
  require(target);
@@ -32821,9 +32991,9 @@ function checkChokidar() {
32821
32991
  }
32822
32992
  async function doctor(args2 = []) {
32823
32993
  const json = args2.includes("--json");
32824
- const cliVersion = true ? "2.60.8" : "0.0.0-dev";
32994
+ const cliVersion = true ? "2.60.10" : "0.0.0-dev";
32825
32995
  const apiBase2 = resolveApiBaseUrl();
32826
- const diagnosticId = (0, import_node_crypto9.randomUUID)();
32996
+ const diagnosticId = (0, import_node_crypto10.randomUUID)();
32827
32997
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
32828
32998
  const [dns, health] = await Promise.all([
32829
32999
  checkDns(apiBase2),
@@ -33020,7 +33190,7 @@ async function completion(args2) {
33020
33190
  // src/commands/version.ts
33021
33191
  var import_picocolors15 = __toESM(require("picocolors"));
33022
33192
  function version2() {
33023
- const v = true ? "2.60.8" : "unknown";
33193
+ const v = true ? "2.60.10" : "unknown";
33024
33194
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
33025
33195
  }
33026
33196
 
@@ -33169,10 +33339,10 @@ var EXIT_CODE_NAMES = {
33169
33339
  };
33170
33340
 
33171
33341
  // src/index.ts
33172
- var os46 = __toESM(require("os"));
33342
+ var os47 = __toESM(require("os"));
33173
33343
  if (!process.env.HOME) {
33174
33344
  try {
33175
- const home = os46.homedir();
33345
+ const home = os47.homedir();
33176
33346
  if (home) process.env.HOME = home;
33177
33347
  } catch {
33178
33348
  }