codeam-cli 2.65.14 → 2.65.16

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 +16 -0
  2. package/dist/index.js +459 -211
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -948,6 +948,8 @@ function isKnownAgentId(id) {
948
948
 
949
949
  // ../../packages/shared/src/agents/identity.ts
950
950
  var HOUSE_AGENT_ID = "house-codeagent-cloud";
951
+ var HOUSE_AGENT_NAME = "CodeAgent Cloud";
952
+ var HOUSE_AGENT_SUBTITLE = "Included \u2014 no setup";
951
953
  var PUBLIC_TO_INTERNAL = {
952
954
  claude_code: "claude",
953
955
  // CLI-side extra: self-hosted deploy payloads may carry the internal id.
@@ -3154,11 +3156,11 @@ function quiet(fn) {
3154
3156
  log.debug(TAG, "ignored sync error", err);
3155
3157
  }
3156
3158
  }
3157
- function rmIfExistsQuiet(path93) {
3159
+ function rmIfExistsQuiet(path94) {
3158
3160
  try {
3159
- fs2.rmSync(path93, { force: true });
3161
+ fs2.rmSync(path94, { force: true });
3160
3162
  } catch (err) {
3161
- log.debug(TAG, `rmIfExists failed for ${path93}`, err);
3163
+ log.debug(TAG, `rmIfExists failed for ${path94}`, err);
3162
3164
  }
3163
3165
  }
3164
3166
  function killQuiet(target, signal = "SIGTERM") {
@@ -3365,8 +3367,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
3365
3367
  return decodedFile;
3366
3368
  };
3367
3369
  }
3368
- function normalizeWindowsPath(path93) {
3369
- return path93.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
3370
+ function normalizeWindowsPath(path94) {
3371
+ return path94.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
3370
3372
  }
3371
3373
 
3372
3374
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -5846,9 +5848,9 @@ async function addSourceContext(frames) {
5846
5848
  LRU_FILE_CONTENTS_CACHE.reduce();
5847
5849
  return frames;
5848
5850
  }
5849
- function getContextLinesFromFile(path93, ranges, output) {
5851
+ function getContextLinesFromFile(path94, ranges, output) {
5850
5852
  return new Promise((resolve10) => {
5851
- const stream = (0, import_node_fs.createReadStream)(path93);
5853
+ const stream = (0, import_node_fs.createReadStream)(path94);
5852
5854
  const lineReaded = (0, import_node_readline.createInterface)({
5853
5855
  input: stream
5854
5856
  });
@@ -5863,7 +5865,7 @@ function getContextLinesFromFile(path93, ranges, output) {
5863
5865
  let rangeStart = range[0];
5864
5866
  let rangeEnd = range[1];
5865
5867
  function onStreamError() {
5866
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path93, 1);
5868
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path94, 1);
5867
5869
  lineReaded.close();
5868
5870
  lineReaded.removeAllListeners();
5869
5871
  destroyStreamAndResolve();
@@ -5924,8 +5926,8 @@ function clearLineContext(frame) {
5924
5926
  delete frame.context_line;
5925
5927
  delete frame.post_context;
5926
5928
  }
5927
- function shouldSkipContextLinesForFile(path93) {
5928
- return path93.startsWith("node:") || path93.endsWith(".min.js") || path93.endsWith(".min.cjs") || path93.endsWith(".min.mjs") || path93.startsWith("data:");
5929
+ function shouldSkipContextLinesForFile(path94) {
5930
+ return path94.startsWith("node:") || path94.endsWith(".min.js") || path94.endsWith(".min.cjs") || path94.endsWith(".min.mjs") || path94.startsWith("data:");
5929
5931
  }
5930
5932
  function shouldSkipContextLinesForFrame(frame) {
5931
5933
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -8079,7 +8081,7 @@ function readAnonId() {
8079
8081
  }
8080
8082
  function superProperties() {
8081
8083
  return {
8082
- cliVersion: true ? "2.65.14" : "0.0.0-dev",
8084
+ cliVersion: true ? "2.65.16" : "0.0.0-dev",
8083
8085
  nodeVersion: process.version,
8084
8086
  platform: process.platform,
8085
8087
  arch: process.arch,
@@ -8321,7 +8323,7 @@ var http = __toESM(require("http"));
8321
8323
  // package.json
8322
8324
  var package_default = {
8323
8325
  name: "codeam-cli",
8324
- version: "2.65.14",
8326
+ version: "2.65.16",
8325
8327
  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.",
8326
8328
  type: "commonjs",
8327
8329
  main: "dist/index.js",
@@ -8719,11 +8721,12 @@ async function fetchProvisionCredentialDetailed(input) {
8719
8721
  input.pluginAuthToken
8720
8722
  );
8721
8723
  const data = res?.data;
8722
- if (data && (data.method === "api_key" || data.method === "oauth") && typeof data.credential === "string" && data.credential.length > 0) {
8724
+ if (data && (data.method === "api_key" || data.method === "oauth" || data.method === "house_proxy") && typeof data.credential === "string" && data.credential.length > 0) {
8723
8725
  return {
8724
8726
  ok: true,
8725
8727
  method: data.method,
8726
8728
  credential: data.credential,
8729
+ ...typeof data.baseUrl === "string" && data.baseUrl.length > 0 ? { baseUrl: data.baseUrl } : {},
8727
8730
  ...typeof data.installScript === "string" && data.installScript.length > 0 ? { installScript: data.installScript } : {}
8728
8731
  };
8729
8732
  }
@@ -8737,7 +8740,7 @@ async function fetchProvisionCredentialDetailed(input) {
8737
8740
  }
8738
8741
  async function fetchProvisionCredential(input) {
8739
8742
  const res = await fetchProvisionCredentialDetailed(input);
8740
- if (!res.ok) return null;
8743
+ if (!res.ok || res.method === "house_proxy") return null;
8741
8744
  return {
8742
8745
  method: res.method,
8743
8746
  credential: res.credential,
@@ -9842,7 +9845,7 @@ var CommandRelayService = class _CommandRelayService {
9842
9845
  // fresh + clear the "CLI update available" banner after a self-update
9843
9846
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
9844
9847
  // pair/reconnect). Older backends ignore the extra field.
9845
- ..."2.65.14" ? { ideVersion: "2.65.14" } : {}
9848
+ ..."2.65.16" ? { ideVersion: "2.65.16" } : {}
9846
9849
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
9847
9850
  }
9848
9851
  /**
@@ -10102,10 +10105,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
10102
10105
  /[\\/]Start Menu([\\/]|$)/i,
10103
10106
  /[\\/]Templates([\\/]|$)/i
10104
10107
  ];
10105
- function isUnsafeWindowsWatchRoot(dir, homedir53) {
10108
+ function isUnsafeWindowsWatchRoot(dir, homedir54) {
10106
10109
  const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
10107
10110
  const cwd = norm(dir);
10108
- const home = norm(homedir53);
10111
+ const home = norm(homedir54);
10109
10112
  if (cwd === home) return true;
10110
10113
  if (/^[a-z]:$/.test(cwd)) return true;
10111
10114
  const sysRoots = [
@@ -14761,10 +14764,10 @@ function buildForPlatform(platform3) {
14761
14764
  var import_node_crypto4 = require("crypto");
14762
14765
 
14763
14766
  // src/agents/claude/resolver.ts
14764
- function buildClaudeLaunch(extraArgs = [], os67 = createOsStrategy()) {
14765
- const found = os67.findInPath("claude") ?? os67.findInPath("claude-code");
14767
+ function buildClaudeLaunch(extraArgs = [], os68 = createOsStrategy()) {
14768
+ const found = os68.findInPath("claude") ?? os68.findInPath("claude-code");
14766
14769
  if (!found) return null;
14767
- return os67.buildLaunch(found, extraArgs);
14770
+ return os68.buildLaunch(found, extraArgs);
14768
14771
  }
14769
14772
 
14770
14773
  // src/agents/claude/installer.ts
@@ -15524,8 +15527,8 @@ var ClaudeRuntimeStrategy = class {
15524
15527
  meta = getAgent("claude");
15525
15528
  mode = "interactive";
15526
15529
  os;
15527
- constructor(os67) {
15528
- this.os = os67;
15530
+ constructor(os68) {
15531
+ this.os = os68;
15529
15532
  }
15530
15533
  /**
15531
15534
  * Claude Code's react-ink TUI enables bracketed-paste mode at
@@ -16613,8 +16616,8 @@ function codexCredentialLocator() {
16613
16616
  function codexLoginLauncher() {
16614
16617
  return {
16615
16618
  async ensureInstalled() {
16616
- const os67 = createOsStrategy();
16617
- return os67.findInPath("codex") !== null;
16619
+ const os68 = createOsStrategy();
16620
+ return os68.findInPath("codex") !== null;
16618
16621
  },
16619
16622
  launch() {
16620
16623
  return (0, import_node_child_process4.spawn)("codex", ["login"], { stdio: "inherit" });
@@ -16637,8 +16640,8 @@ var CodexRuntimeStrategy = class {
16637
16640
  meta = getAgent("codex");
16638
16641
  mode = "interactive";
16639
16642
  os;
16640
- constructor(os67) {
16641
- this.os = os67;
16643
+ constructor(os68) {
16644
+ this.os = os68;
16642
16645
  }
16643
16646
  async prepareLaunch() {
16644
16647
  let binary = this.os.findInPath("codex");
@@ -16747,12 +16750,12 @@ var CodexRuntimeStrategy = class {
16747
16750
  });
16748
16751
  }
16749
16752
  };
16750
- function resolveNpm(os67) {
16751
- return os67.id === "win32" ? "npm.cmd" : "npm";
16753
+ function resolveNpm(os68) {
16754
+ return os68.id === "win32" ? "npm.cmd" : "npm";
16752
16755
  }
16753
- async function installCodexViaNpm(os67) {
16756
+ async function installCodexViaNpm(os68) {
16754
16757
  return new Promise((resolve10, reject) => {
16755
- const proc = (0, import_node_child_process5.spawn)(resolveNpm(os67), ["install", "-g", "@openai/codex"], {
16758
+ const proc = (0, import_node_child_process5.spawn)(resolveNpm(os68), ["install", "-g", "@openai/codex"], {
16756
16759
  stdio: "inherit"
16757
16760
  });
16758
16761
  proc.on("close", (code) => {
@@ -16769,16 +16772,16 @@ async function installCodexViaNpm(os67) {
16769
16772
  });
16770
16773
  });
16771
16774
  }
16772
- function augmentNpmGlobalBin(os67) {
16775
+ function augmentNpmGlobalBin(os68) {
16773
16776
  try {
16774
- const result = (0, import_node_child_process5.spawnSync)(resolveNpm(os67), ["prefix", "-g"], {
16777
+ const result = (0, import_node_child_process5.spawnSync)(resolveNpm(os68), ["prefix", "-g"], {
16775
16778
  stdio: ["ignore", "pipe", "ignore"]
16776
16779
  });
16777
16780
  if (result.status !== 0) return;
16778
16781
  const prefix = result.stdout.toString().trim();
16779
16782
  if (!prefix) return;
16780
- const binDir = os67.id === "win32" ? prefix : path27.join(prefix, "bin");
16781
- os67.augmentPath([binDir]);
16783
+ const binDir = os68.id === "win32" ? prefix : path27.join(prefix, "bin");
16784
+ os68.augmentPath([binDir]);
16782
16785
  } catch {
16783
16786
  }
16784
16787
  }
@@ -17189,10 +17192,10 @@ function manualInstallHint(runner, tools) {
17189
17192
  const argv = osPackageInstallArgv(detectPackageManager(runner), [...tools]);
17190
17193
  return argv ? `\`sudo ${argv.join(" ")}\`` : `your package manager (e.g. \`${pkgs}\`)`;
17191
17194
  }
17192
- function writeUnzipShim(os67, runner) {
17195
+ function writeUnzipShim(os68, runner) {
17193
17196
  const python = ["python3", "python"].find((p2) => runner.which(p2));
17194
17197
  if (!python) return null;
17195
- const dir = os67.scratchPath("codeam-cr-prereq");
17198
+ const dir = os68.scratchPath("codeam-cr-prereq");
17196
17199
  const shim = path29.join(dir, "unzip");
17197
17200
  const script = `#!/bin/sh
17198
17201
  set -e
@@ -17214,9 +17217,9 @@ exec ${python} -m zipfile -e "$archive" "$dest"
17214
17217
  (0, import_node_fs5.chmodSync)(shim, 448);
17215
17218
  return dir;
17216
17219
  }
17217
- async function ensureInstallPrerequisites(os67, deps = {}) {
17220
+ async function ensureInstallPrerequisites(os68, deps = {}) {
17218
17221
  const runner = deps.runner ?? defaultHeadroomRunner;
17219
- const missing = REQUIRED_TOOLS.filter((t2) => os67.findInPath(t2) === null);
17222
+ const missing = REQUIRED_TOOLS.filter((t2) => os68.findInPath(t2) === null);
17220
17223
  if (missing.length === 0) return { ok: true, extraPath: [] };
17221
17224
  log.info(
17222
17225
  "coderabbit",
@@ -17235,10 +17238,10 @@ async function ensureInstallPrerequisites(os67, deps = {}) {
17235
17238
  );
17236
17239
  }
17237
17240
  }
17238
- const stillMissing = REQUIRED_TOOLS.filter((t2) => os67.findInPath(t2) === null);
17241
+ const stillMissing = REQUIRED_TOOLS.filter((t2) => os68.findInPath(t2) === null);
17239
17242
  if (stillMissing.length === 0) return { ok: true, extraPath: [] };
17240
17243
  if (stillMissing.length === 1 && stillMissing[0] === "unzip") {
17241
- const shimDir = writeUnzipShim(os67, runner);
17244
+ const shimDir = writeUnzipShim(os68, runner);
17242
17245
  if (shimDir) {
17243
17246
  log.info("coderabbit", "unzip is unavailable \u2014 using a scoped python zipfile shim");
17244
17247
  return { ok: true, extraPath: [shimDir] };
@@ -17301,15 +17304,15 @@ function summarizeInstallFailure(output) {
17301
17304
  }
17302
17305
  return lines.length > 0 ? lines[lines.length - 1] : null;
17303
17306
  }
17304
- async function ensureCoderabbitInstalled(os67, deps = {}) {
17305
- if (os67.findInPath("coderabbit")) return { ok: true };
17306
- if (os67.id === "win32") {
17307
+ async function ensureCoderabbitInstalled(os68, deps = {}) {
17308
+ if (os68.findInPath("coderabbit")) return { ok: true };
17309
+ if (os68.id === "win32") {
17307
17310
  return {
17308
17311
  ok: false,
17309
17312
  error: "CodeRabbit on Windows requires WSL. Install the CLI inside your WSL distribution (curl -fsSL https://cli.coderabbit.ai/install.sh | sh), then try again."
17310
17313
  };
17311
17314
  }
17312
- const prereq = await ensureInstallPrerequisites(os67, deps);
17315
+ const prereq = await ensureInstallPrerequisites(os68, deps);
17313
17316
  if (!prereq.ok) return { ok: false, error: prereq.error };
17314
17317
  const env = { ...process.env };
17315
17318
  if (prereq.extraPath.length > 0) {
@@ -17318,8 +17321,8 @@ async function ensureCoderabbitInstalled(os67, deps = {}) {
17318
17321
  log.info("coderabbit", "CodeRabbit CLI not found \u2014 installing via the official script");
17319
17322
  const run = deps.runInstallScript ?? defaultRunInstallScript;
17320
17323
  const { code, output } = await run(env);
17321
- os67.augmentPath([`${os67.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
17322
- const binary = os67.findInPath("coderabbit");
17324
+ os68.augmentPath([`${os68.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
17325
+ const binary = os68.findInPath("coderabbit");
17323
17326
  const detail = summarizeInstallFailure(output);
17324
17327
  if (binary !== null) {
17325
17328
  if (code === 0) return { ok: true };
@@ -17373,10 +17376,10 @@ function coderabbitCredentialLocator() {
17373
17376
  validate: validateNonEmptyCredential
17374
17377
  };
17375
17378
  }
17376
- function coderabbitLoginLauncher(os67) {
17379
+ function coderabbitLoginLauncher(os68) {
17377
17380
  return {
17378
17381
  async ensureInstalled() {
17379
- const result = await ensureCoderabbitInstalled(os67);
17382
+ const result = await ensureCoderabbitInstalled(os68);
17380
17383
  if (!result.ok && result.error) console.error(`
17381
17384
  \u2717 ${result.error}
17382
17385
  `);
@@ -17436,8 +17439,8 @@ function pickLine(obj) {
17436
17439
  function toHunk(raw, groupSeverity) {
17437
17440
  if (!raw || typeof raw !== "object") return null;
17438
17441
  const o = raw;
17439
- const path93 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
17440
- if (!path93) return null;
17442
+ const path94 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
17443
+ if (!path94) return null;
17441
17444
  const message = asString(
17442
17445
  pick(o, [
17443
17446
  "comment",
@@ -17454,7 +17457,7 @@ function toHunk(raw, groupSeverity) {
17454
17457
  const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
17455
17458
  const locObj = pick(o, ["location"]) ?? o;
17456
17459
  return {
17457
- path: path93.trim(),
17460
+ path: path94.trim(),
17458
17461
  line: pickLine(o) ?? pickLine(locObj),
17459
17462
  severity,
17460
17463
  message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
@@ -17537,10 +17540,10 @@ function parsePlain(stdout) {
17537
17540
  for (const line of stdout.split(/\r?\n/)) {
17538
17541
  const m = line.match(HUNK_LINE_RE);
17539
17542
  if (!m) continue;
17540
- const [, path93, lineNo, sevToken, message] = m;
17541
- if (!path93 || !lineNo || !message) continue;
17543
+ const [, path94, lineNo, sevToken, message] = m;
17544
+ if (!path94 || !lineNo || !message) continue;
17542
17545
  hunks.push({
17543
- path: path93.trim(),
17546
+ path: path94.trim(),
17544
17547
  line: Number(lineNo),
17545
17548
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
17546
17549
  message: message.trim().replace(/^[*-]\s+/, "")
@@ -17600,8 +17603,8 @@ var CoderabbitRuntimeStrategy = class {
17600
17603
  meta = getAgent("coderabbit");
17601
17604
  mode = "batch";
17602
17605
  os;
17603
- constructor(os67) {
17604
- this.os = os67;
17606
+ constructor(os68) {
17607
+ this.os = os68;
17605
17608
  }
17606
17609
  getDefaultArgs() {
17607
17610
  return ["review", "--agent"];
@@ -17872,10 +17875,10 @@ function cursorCredentialLocator() {
17872
17875
  validate: validateNonEmptyCredential
17873
17876
  };
17874
17877
  }
17875
- function cursorLoginLauncher(os67) {
17878
+ function cursorLoginLauncher(os68) {
17876
17879
  return {
17877
17880
  async ensureInstalled() {
17878
- if (os67.findInPath("cursor-agent")) return true;
17881
+ if (os68.findInPath("cursor-agent")) return true;
17879
17882
  console.error(
17880
17883
  "\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"
17881
17884
  );
@@ -17939,8 +17942,8 @@ var CursorRuntimeStrategy = class {
17939
17942
  meta = getAgent("cursor");
17940
17943
  mode = "interactive";
17941
17944
  os;
17942
- constructor(os67) {
17943
- this.os = os67;
17945
+ constructor(os68) {
17946
+ this.os = os68;
17944
17947
  }
17945
17948
  async prepareLaunch() {
17946
17949
  const binary = this.os.findInPath("cursor-agent");
@@ -18156,10 +18159,10 @@ function aiderCredentialLocator() {
18156
18159
  validate: validateNonEmptyCredential
18157
18160
  };
18158
18161
  }
18159
- function aiderLoginLauncher(os67) {
18162
+ function aiderLoginLauncher(os68) {
18160
18163
  return {
18161
18164
  async ensureInstalled() {
18162
- if (os67.findInPath("aider")) return true;
18165
+ if (os68.findInPath("aider")) return true;
18163
18166
  console.error(
18164
18167
  "\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
18165
18168
  );
@@ -18169,7 +18172,7 @@ function aiderLoginLauncher(os67) {
18169
18172
  console.error(
18170
18173
  "\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"
18171
18174
  );
18172
- return (0, import_node_child_process12.spawn)(os67.id === "win32" ? "cmd.exe" : "sh", os67.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
18175
+ return (0, import_node_child_process12.spawn)(os68.id === "win32" ? "cmd.exe" : "sh", os68.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
18173
18176
  stdio: "ignore"
18174
18177
  });
18175
18178
  }
@@ -18315,22 +18318,31 @@ async function waitForCommandOnPath(cmd, opts = {}) {
18315
18318
  }
18316
18319
  return check();
18317
18320
  }
18318
- function augmentUserLocalBinPaths(deps = {}) {
18321
+ function agentInstallBinDirs(deps = {}) {
18319
18322
  const env = deps.env ?? process.env;
18320
18323
  const home = deps.homedir ?? import_os4.default.homedir();
18321
18324
  const p2 = deps.pathApi ?? import_path4.default;
18322
- const candidates = [
18325
+ return [
18323
18326
  // XDG-style per-user bin — npm's default global-prefix bin dir on most
18324
18327
  // Linux setups (`npm config set prefix ~/.local` or an nvm-less
18325
- // per-user npm), and where curl-based agent installers commonly land.
18328
+ // per-user npm), and where curl-based agent installers commonly land
18329
+ // (cursor-agent, coderabbit, pip --user's aider).
18326
18330
  p2.join(home, ".local", "bin"),
18327
18331
  // Common explicit npm global-prefix conventions seen in the wild
18328
18332
  // (`npm config set prefix ~/.npm-global`, and Debian/Fedora's
18329
18333
  // `~/.local/share/npm` layout for `npm config set prefix
18330
18334
  // ~/.local/share/npm`).
18331
18335
  p2.join(home, ".npm-global", "bin"),
18332
- p2.join(home, ".local", "share", "npm", "bin")
18336
+ p2.join(home, ".local", "share", "npm", "bin"),
18337
+ // Vendor curl-installer targets that are NOT on any default PATH.
18338
+ p2.join(env.KIMI_CODE_HOME || p2.join(home, ".kimi-code"), "bin"),
18339
+ p2.join(env.OPENCODE_HOME || p2.join(home, ".opencode"), "bin")
18333
18340
  ];
18341
+ }
18342
+ function augmentUserLocalBinPaths(deps = {}) {
18343
+ const env = deps.env ?? process.env;
18344
+ const p2 = deps.pathApi ?? import_path4.default;
18345
+ const candidates = agentInstallBinDirs(deps);
18334
18346
  const parts = (env.PATH ?? "").split(p2.delimiter).filter((s) => s.length > 0);
18335
18347
  const existing = new Set(parts);
18336
18348
  const additions = candidates.filter((dir) => !existing.has(dir));
@@ -18435,8 +18447,8 @@ var AiderRuntimeStrategy = class {
18435
18447
  meta = getAgent("aider");
18436
18448
  mode = "interactive";
18437
18449
  os;
18438
- constructor(os67) {
18439
- this.os = os67;
18450
+ constructor(os68) {
18451
+ this.os = os68;
18440
18452
  }
18441
18453
  async prepareLaunch() {
18442
18454
  augmentUserLocalBinPaths();
@@ -18569,8 +18581,8 @@ function geminiCredentialLocator() {
18569
18581
  function geminiLoginLauncher() {
18570
18582
  return {
18571
18583
  async ensureInstalled() {
18572
- const os67 = createOsStrategy();
18573
- return os67.findInPath("gemini") !== null;
18584
+ const os68 = createOsStrategy();
18585
+ return os68.findInPath("gemini") !== null;
18574
18586
  },
18575
18587
  launch() {
18576
18588
  return (0, import_node_child_process13.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
@@ -18760,8 +18772,8 @@ var GeminiRuntimeStrategy = class {
18760
18772
  meta = getAgent("gemini");
18761
18773
  mode = "interactive";
18762
18774
  os;
18763
- constructor(os67) {
18764
- this.os = os67;
18775
+ constructor(os68) {
18776
+ this.os = os68;
18765
18777
  }
18766
18778
  async prepareLaunch() {
18767
18779
  const binary = this.os.findInPath("gemini");
@@ -19052,8 +19064,8 @@ var KimiRuntimeStrategy = class {
19052
19064
  meta = getAgent("kimi");
19053
19065
  mode = "interactive";
19054
19066
  os;
19055
- constructor(os67) {
19056
- this.os = os67;
19067
+ constructor(os68) {
19068
+ this.os = os68;
19057
19069
  }
19058
19070
  async prepareLaunch() {
19059
19071
  const binary = this.os.findInPath("kimi");
@@ -19195,8 +19207,8 @@ var OpencodeRuntimeStrategy = class {
19195
19207
  meta = getAgent("opencode");
19196
19208
  mode = "interactive";
19197
19209
  os;
19198
- constructor(os67) {
19199
- this.os = os67;
19210
+ constructor(os68) {
19211
+ this.os = os68;
19200
19212
  }
19201
19213
  async prepareLaunch() {
19202
19214
  const binary = this.os.findInPath("opencode");
@@ -19280,20 +19292,20 @@ var OpencodeRuntimeStrategy = class {
19280
19292
 
19281
19293
  // src/agents/registry.ts
19282
19294
  var runtimeBuilders = {
19283
- claude: (os67) => new ClaudeRuntimeStrategy(os67),
19284
- codex: (os67) => new CodexRuntimeStrategy(os67),
19285
- coderabbit: (os67) => new CoderabbitRuntimeStrategy(os67),
19286
- cursor: (os67) => new CursorRuntimeStrategy(os67),
19287
- aider: (os67) => new AiderRuntimeStrategy(os67),
19288
- gemini: (os67) => new GeminiRuntimeStrategy(os67),
19289
- kimi: (os67) => new KimiRuntimeStrategy(os67),
19290
- opencode: (os67) => new OpencodeRuntimeStrategy(os67)
19295
+ claude: (os68) => new ClaudeRuntimeStrategy(os68),
19296
+ codex: (os68) => new CodexRuntimeStrategy(os68),
19297
+ coderabbit: (os68) => new CoderabbitRuntimeStrategy(os68),
19298
+ cursor: (os68) => new CursorRuntimeStrategy(os68),
19299
+ aider: (os68) => new AiderRuntimeStrategy(os68),
19300
+ gemini: (os68) => new GeminiRuntimeStrategy(os68),
19301
+ kimi: (os68) => new KimiRuntimeStrategy(os68),
19302
+ opencode: (os68) => new OpencodeRuntimeStrategy(os68)
19291
19303
  };
19292
19304
  var deployBuilders = {
19293
19305
  claude: () => new ClaudeDeployStrategy(),
19294
19306
  codex: () => new CodexDeployStrategy()
19295
19307
  };
19296
- function createAgentStrategy(agent, os67 = createOsStrategy()) {
19308
+ function createAgentStrategy(agent, os68 = createOsStrategy()) {
19297
19309
  if (!AGENT_REGISTRY[agent]?.enabled) {
19298
19310
  throw new Error(
19299
19311
  `Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
@@ -19303,10 +19315,10 @@ function createAgentStrategy(agent, os67 = createOsStrategy()) {
19303
19315
  if (!build) {
19304
19316
  throw new Error(`No runtime strategy registered for agent "${agent}"`);
19305
19317
  }
19306
- return build(os67);
19318
+ return build(os68);
19307
19319
  }
19308
- function createInteractiveAgentStrategy(agent, os67 = createOsStrategy()) {
19309
- const s = createAgentStrategy(agent, os67);
19320
+ function createInteractiveAgentStrategy(agent, os68 = createOsStrategy()) {
19321
+ const s = createAgentStrategy(agent, os68);
19310
19322
  if (s.mode !== "interactive") {
19311
19323
  throw new Error(
19312
19324
  `Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
@@ -19984,8 +19996,8 @@ function collectChangedFiles(cwd) {
19984
19996
  }
19985
19997
  return [...byPath.values()];
19986
19998
  }
19987
- function restoreCoderabbitOauthBlob(os67, value) {
19988
- const dir = path41.join(os67.homeDir(), ".coderabbit");
19999
+ function restoreCoderabbitOauthBlob(os68, value) {
20000
+ const dir = path41.join(os68.homeDir(), ".coderabbit");
19989
20001
  (0, import_node_fs6.mkdirSync)(dir, { recursive: true });
19990
20002
  let file = "auth.json";
19991
20003
  let contents = value.trim();
@@ -20005,26 +20017,26 @@ function installFailureMessage(result) {
20005
20017
  return result.error ?? "CodeRabbit CLI could not be installed";
20006
20018
  }
20007
20019
  async function configureCoderabbit(input, deps = {}) {
20008
- const os67 = deps.os ?? createOsStrategy();
20020
+ const os68 = deps.os ?? createOsStrategy();
20009
20021
  const ensureInstalled = deps.ensureInstalled ?? ensureCoderabbitInstalled;
20010
20022
  const isLoggedIn = deps.isLoggedIn ?? defaultIsLoggedIn;
20011
20023
  const runOAuth = deps.runOAuthLogin ?? runCoderabbitOAuthLogin;
20012
20024
  const snapshot = deps.snapshotDir ?? (() => snapshotCredentialDir());
20013
20025
  const capture2 = deps.captureCredential ?? ((b) => diffCapturedCredential(b));
20014
20026
  const loginWithApiKey = deps.loginWithApiKey ?? defaultLoginWithApiKey;
20015
- const home = os67.homeDir();
20016
- os67.augmentPath(
20017
- os67.id === "win32" ? [
20027
+ const home = os68.homeDir();
20028
+ os68.augmentPath(
20029
+ os68.id === "win32" ? [
20018
20030
  path41.join(home, ".local", "bin"),
20019
20031
  path41.join(process.env.APPDATA ?? path41.join(home, "AppData", "Roaming"), "npm"),
20020
20032
  path41.join(home, "scoop", "shims")
20021
20033
  ] : [path41.join(home, ".local", "bin"), "/opt/homebrew/bin", "/usr/local/bin"]
20022
20034
  );
20023
- const installed2 = os67.findInPath("coderabbit") !== null;
20035
+ const installed2 = os68.findInPath("coderabbit") !== null;
20024
20036
  const base = () => ({
20025
20037
  action: input.action,
20026
20038
  supported: true,
20027
- installed: os67.findInPath("coderabbit") !== null,
20039
+ installed: os68.findInPath("coderabbit") !== null,
20028
20040
  loggedIn: false
20029
20041
  });
20030
20042
  if (input.action === "status") {
@@ -20038,7 +20050,7 @@ async function configureCoderabbit(input, deps = {}) {
20038
20050
  const key = (input.apiKey ?? "").trim();
20039
20051
  if (!key) return { ...res2, error: "No API key provided" };
20040
20052
  if (!res2.installed) {
20041
- const inst = await ensureInstalled(os67);
20053
+ const inst = await ensureInstalled(os68);
20042
20054
  res2.installed = inst.ok;
20043
20055
  if (!inst.ok) return { ...res2, error: installFailureMessage(inst) };
20044
20056
  }
@@ -20062,7 +20074,7 @@ async function configureCoderabbit(input, deps = {}) {
20062
20074
  }
20063
20075
  if (!res2.installed) {
20064
20076
  deps.onEvent?.({ kind: "installing" });
20065
- const inst = await ensureInstalled(os67);
20077
+ const inst = await ensureInstalled(os68);
20066
20078
  res2.installed = inst.ok;
20067
20079
  if (!inst.ok) return { ...res2, error: installFailureMessage(inst) };
20068
20080
  }
@@ -20079,7 +20091,7 @@ async function configureCoderabbit(input, deps = {}) {
20079
20091
  return { ...res2, loggedIn: true, linked: true };
20080
20092
  }
20081
20093
  try {
20082
- restoreCoderabbitOauthBlob(os67, cred.credential);
20094
+ restoreCoderabbitOauthBlob(os68, cred.credential);
20083
20095
  } catch (err) {
20084
20096
  return {
20085
20097
  ...res2,
@@ -20103,7 +20115,7 @@ async function configureCoderabbit(input, deps = {}) {
20103
20115
  const res2 = base();
20104
20116
  if (!installed2) {
20105
20117
  deps.onEvent?.({ kind: "installing" });
20106
- const inst = await ensureInstalled(os67);
20118
+ const inst = await ensureInstalled(os68);
20107
20119
  res2.installed = inst.ok;
20108
20120
  if (!inst.ok) return { ...res2, error: installFailureMessage(inst) };
20109
20121
  }
@@ -20143,7 +20155,7 @@ async function configureCoderabbit(input, deps = {}) {
20143
20155
  }
20144
20156
  const res = base();
20145
20157
  if (!res.installed) {
20146
- const inst = await ensureInstalled(os67);
20158
+ const inst = await ensureInstalled(os68);
20147
20159
  res.installed = inst.ok;
20148
20160
  if (!inst.ok) return { ...res, error: installFailureMessage(inst) };
20149
20161
  }
@@ -20784,6 +20796,38 @@ async function reportDeployProgress(auth, deployId, step, message, sessionId) {
20784
20796
  } catch {
20785
20797
  }
20786
20798
  }
20799
+ async function postSessionErrorBubble(auth, message) {
20800
+ const chunks = [
20801
+ { type: "new_turn", done: false },
20802
+ { type: "text", content: message, done: true }
20803
+ ];
20804
+ for (const chunk of chunks) {
20805
+ try {
20806
+ const controller = new AbortController();
20807
+ const timer = setTimeout(() => controller.abort(), PROGRESS_TIMEOUT_MS);
20808
+ timer.unref?.();
20809
+ try {
20810
+ await fetch(`${apiBase()}/api/commands/output`, {
20811
+ method: "POST",
20812
+ headers: {
20813
+ "Content-Type": "application/json",
20814
+ "X-Plugin-Auth-Token": auth.pluginAuthToken,
20815
+ ...vercelBypassHeader()
20816
+ },
20817
+ body: JSON.stringify({
20818
+ sessionId: auth.sessionId,
20819
+ pluginId: auth.pluginId,
20820
+ ...chunk
20821
+ }),
20822
+ signal: controller.signal
20823
+ });
20824
+ } finally {
20825
+ clearTimeout(timer);
20826
+ }
20827
+ } catch {
20828
+ }
20829
+ }
20830
+ }
20787
20831
 
20788
20832
  // src/commands/host/workspace.ts
20789
20833
  var fs39 = __toESM(require("fs"));
@@ -21782,28 +21826,64 @@ function readHouseProxyChildEnv() {
21782
21826
  const o = parsed;
21783
21827
  if (typeof o.baseUrl !== "string" || !o.baseUrl) return {};
21784
21828
  if (typeof o.token !== "string" || !o.token) return {};
21785
- const env = {
21786
- ANTHROPIC_BASE_URL: o.baseUrl,
21787
- ANTHROPIC_AUTH_TOKEN: o.token,
21788
- CLAUDE_CODE_AUTO_COMPACT_WINDOW: "512000",
21789
- API_TIMEOUT_MS: "3000000"
21790
- };
21791
- if (o.openRouter === true) {
21792
- env.ANTHROPIC_API_KEY = "";
21793
- } else {
21794
- env.ANTHROPIC_MODEL = "MiniMax-M3";
21795
- env.ANTHROPIC_DEFAULT_SONNET_MODEL = "MiniMax-M3";
21796
- env.ANTHROPIC_DEFAULT_OPUS_MODEL = "MiniMax-M3";
21797
- env.ANTHROPIC_DEFAULT_HAIKU_MODEL = "MiniMax-M3";
21798
- }
21799
- if (typeof o.claudeConfigDir === "string" && o.claudeConfigDir) {
21800
- env.CLAUDE_CONFIG_DIR = o.claudeConfigDir;
21801
- }
21802
- return env;
21829
+ return buildHouseProxyChildEnv({
21830
+ baseUrl: o.baseUrl,
21831
+ token: o.token,
21832
+ openRouter: o.openRouter === true,
21833
+ ...typeof o.claudeConfigDir === "string" && o.claudeConfigDir ? { claudeConfigDir: o.claudeConfigDir } : {}
21834
+ });
21803
21835
  } catch {
21804
21836
  return {};
21805
21837
  }
21806
21838
  }
21839
+ function buildHouseProxyChildEnv(cfg) {
21840
+ const env = {
21841
+ ANTHROPIC_BASE_URL: cfg.baseUrl,
21842
+ ANTHROPIC_AUTH_TOKEN: cfg.token,
21843
+ CLAUDE_CODE_AUTO_COMPACT_WINDOW: "512000",
21844
+ API_TIMEOUT_MS: "3000000"
21845
+ };
21846
+ if (cfg.openRouter === true) {
21847
+ env.ANTHROPIC_API_KEY = "";
21848
+ } else {
21849
+ env.ANTHROPIC_MODEL = "MiniMax-M3";
21850
+ env.ANTHROPIC_DEFAULT_SONNET_MODEL = "MiniMax-M3";
21851
+ env.ANTHROPIC_DEFAULT_OPUS_MODEL = "MiniMax-M3";
21852
+ env.ANTHROPIC_DEFAULT_HAIKU_MODEL = "MiniMax-M3";
21853
+ }
21854
+ if (typeof cfg.claudeConfigDir === "string" && cfg.claudeConfigDir) {
21855
+ env.CLAUDE_CONFIG_DIR = cfg.claudeConfigDir;
21856
+ }
21857
+ return env;
21858
+ }
21859
+ var HOUSE_PROXY_ENV_KEYS = [
21860
+ "ANTHROPIC_BASE_URL",
21861
+ "ANTHROPIC_AUTH_TOKEN",
21862
+ "ANTHROPIC_API_KEY",
21863
+ "ANTHROPIC_MODEL",
21864
+ "ANTHROPIC_DEFAULT_SONNET_MODEL",
21865
+ "ANTHROPIC_DEFAULT_OPUS_MODEL",
21866
+ "ANTHROPIC_DEFAULT_HAIKU_MODEL",
21867
+ "CLAUDE_CODE_AUTO_COMPACT_WINDOW",
21868
+ "API_TIMEOUT_MS",
21869
+ "CLAUDE_CONFIG_DIR"
21870
+ ];
21871
+ function clearHouseProxyEnvOverrides() {
21872
+ const out2 = {};
21873
+ for (const key of HOUSE_PROXY_ENV_KEYS) out2[key] = void 0;
21874
+ return out2;
21875
+ }
21876
+ function isHouseProxyEnv(env) {
21877
+ return typeof env.ANTHROPIC_AUTH_TOKEN === "string" && env.ANTHROPIC_AUTH_TOKEN.length > 0 && (env.ANTHROPIC_BASE_URL ?? "").includes("/api/v1/agent-proxy");
21878
+ }
21879
+ function pickHouseProxyEnv(env) {
21880
+ const out2 = {};
21881
+ for (const key of HOUSE_PROXY_ENV_KEYS) {
21882
+ const v = env[key];
21883
+ if (typeof v === "string") out2[key] = v;
21884
+ }
21885
+ return out2;
21886
+ }
21807
21887
 
21808
21888
  // src/commands/host/self-update.ts
21809
21889
  var import_node_child_process23 = require("child_process");
@@ -21966,7 +22046,7 @@ async function autoUpgradeBeforeCriticalCommand() {
21966
22046
  if (process.env.NODE_ENV === "test") return;
21967
22047
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
21968
22048
  if (process.env.CI) return;
21969
- const current2 = true ? "2.65.14" : null;
22049
+ const current2 = true ? "2.65.16" : null;
21970
22050
  if (!current2) return;
21971
22051
  const cache = readCache();
21972
22052
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -21983,7 +22063,7 @@ function checkForUpdates() {
21983
22063
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
21984
22064
  if (process.env.CI) return;
21985
22065
  if (!process.stdout.isTTY) return;
21986
- const current2 = true ? "2.65.14" : null;
22066
+ const current2 = true ? "2.65.16" : null;
21987
22067
  if (!current2) return;
21988
22068
  const cache = readCache();
21989
22069
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -22003,7 +22083,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
22003
22083
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
22004
22084
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
22005
22085
  function currentCliVersion() {
22006
- return true ? "2.65.14" : null;
22086
+ return true ? "2.65.16" : null;
22007
22087
  }
22008
22088
  function runCmd(cmd, args2, timeoutMs) {
22009
22089
  return new Promise((resolve10) => {
@@ -22096,6 +22176,9 @@ function resolveInputPricePerMillion(agentId) {
22096
22176
  return getPricing(model).input;
22097
22177
  }
22098
22178
  var HEARTBEAT_INTERVAL_MS = 2e4;
22179
+ var RESUME_RETRY_BACKOFF_MS = [15e3, 3e4, 6e4, 12e4];
22180
+ var RESUME_REPROBE_INTERVAL_MS = 5 * 6e4;
22181
+ var RESUME_HEALTHY_AFTER_MS = 10 * 6e4;
22099
22182
  function maybeStartHeadroomReporter(ctx) {
22100
22183
  if (process.env["HEADROOM_ENABLED"] !== "1") return null;
22101
22184
  try {
@@ -22431,6 +22514,7 @@ var HostAgentSupervisor = class {
22431
22514
  this.selfUpdate = deps.selfUpdate ?? runSelfUpdate;
22432
22515
  this.onUpdated = deps.onUpdated ?? defaultOnUpdated;
22433
22516
  this.docker = deps.docker ?? defaultDockerRunner;
22517
+ this.postResumeFailure = deps.postResumeFailure ?? postSessionErrorBubble;
22434
22518
  }
22435
22519
  identity;
22436
22520
  deps;
@@ -22472,6 +22556,20 @@ var HostAgentSupervisor = class {
22472
22556
  docker;
22473
22557
  /** Guards against firing the self-heal more than once. */
22474
22558
  healing = false;
22559
+ /** Visible-error poster for the exhausted-resume path (injectable). */
22560
+ postResumeFailure;
22561
+ /** How many resume re-spawns have failed since the last healthy child. */
22562
+ resumeRetryAttempts = 0;
22563
+ /** Pending bounded-backoff resume retry (cleared on stop()). */
22564
+ resumeRetryTimer = null;
22565
+ /** Set once the bounded retries exhaust → heartbeat-ridden slow re-probe. */
22566
+ resumeExhausted = false;
22567
+ /** Guards the one-shot visible error bubble per failure episode. */
22568
+ resumeFailurePosted = false;
22569
+ /** Last slow re-probe attempt (epoch ms) — throttles the heartbeat rider. */
22570
+ lastResumeReprobeAt = 0;
22571
+ /** True after stop() — no resume retries may be scheduled past teardown. */
22572
+ stopped = false;
22475
22573
  /**
22476
22574
  * Resolve the self-update interval, honoring `CODEAM_HOST_SELF_UPDATE_MS`.
22477
22575
  * A finite value > 0 overrides the default; 0 or negative DISABLES the
@@ -22515,6 +22613,11 @@ var HostAgentSupervisor = class {
22515
22613
  }
22516
22614
  /** Stop the control channel + heartbeats + kill every child. */
22517
22615
  stop() {
22616
+ this.stopped = true;
22617
+ if (this.resumeRetryTimer) {
22618
+ clearTimeout(this.resumeRetryTimer);
22619
+ this.resumeRetryTimer = null;
22620
+ }
22518
22621
  if (this.heartbeatTimer) {
22519
22622
  clearInterval(this.heartbeatTimer);
22520
22623
  this.heartbeatTimer = null;
@@ -22530,6 +22633,7 @@ var HostAgentSupervisor = class {
22530
22633
  this.children.clear();
22531
22634
  }
22532
22635
  async beat() {
22636
+ this.resumeRecoveryTick();
22533
22637
  try {
22534
22638
  let metrics;
22535
22639
  try {
@@ -23222,15 +23326,12 @@ var HostAgentSupervisor = class {
23222
23326
  proc.once("exit", (code) => {
23223
23327
  if (this.children.get(session.id)?.proc === proc) this.children.delete(session.id);
23224
23328
  if (typeof code === "number" && code !== 0) {
23225
- log.warn(
23226
- "host-agent",
23227
- `resumed session ${session.id.slice(0, 8)} exited (${code}): ${tail.trim().slice(-300)}`
23228
- );
23329
+ this.onResumeChildExit(session, code, tail.trim().slice(-300));
23229
23330
  }
23230
23331
  });
23231
23332
  log.info(
23232
23333
  "host-agent",
23233
- `resumed session ${session.id.slice(0, 8)} pluginId=${session.pluginId.slice(0, 12)} (ACP)`
23334
+ `resumed session ${session.id.slice(0, 8)} pluginId=${session.pluginId.slice(0, 12)} (ACP)` + (this.resumeRetryAttempts > 0 ? ` [retry ${this.resumeRetryAttempts}]` : "")
23234
23335
  );
23235
23336
  } catch (err) {
23236
23337
  log.warn(
@@ -23239,6 +23340,92 @@ var HostAgentSupervisor = class {
23239
23340
  );
23240
23341
  }
23241
23342
  }
23343
+ /**
23344
+ * A resumed session child died with a non-zero exit. Before 2026-08-20 this
23345
+ * was ONE warn log and permanent, silent surrender: the v2.65.13 self-update
23346
+ * restarted the fleet-1 unit, the resumed kimi child died `ENOENT — 'kimi'
23347
+ * was not found on PATH`, and the session sat dead for 3+ hours while the
23348
+ * HOST heartbeat stayed green (nothing retried, nothing surfaced anywhere).
23349
+ * Now: bounded backoff retries ({@link RESUME_RETRY_BACKOFF_MS}); when they
23350
+ * exhaust, post an HONEST error bubble into the session's chat (the relay/
23351
+ * backend are up — only the agent child is dead) and hand off to the
23352
+ * heartbeat-ridden slow re-probe ({@link resumeRecoveryTick}) so an
23353
+ * externally-fixed cause heals without a manual restart.
23354
+ */
23355
+ onResumeChildExit(session, code, detail) {
23356
+ if (this.stopped) return;
23357
+ const reason = detail ? `exit ${code}: ${detail}` : `exit ${code}`;
23358
+ if (this.resumeRetryAttempts < RESUME_RETRY_BACKOFF_MS.length) {
23359
+ const delay = RESUME_RETRY_BACKOFF_MS[this.resumeRetryAttempts];
23360
+ this.resumeRetryAttempts += 1;
23361
+ log.warn(
23362
+ "host-agent",
23363
+ `resumed session ${session.id.slice(0, 8)} died (${reason}) \u2014 retry ${this.resumeRetryAttempts}/${RESUME_RETRY_BACKOFF_MS.length} in ${Math.round(delay / 1e3)}s`
23364
+ );
23365
+ this.resumeRetryTimer = setTimeout(() => {
23366
+ this.resumeRetryTimer = null;
23367
+ this.resumePersistedSession();
23368
+ }, delay);
23369
+ this.resumeRetryTimer.unref?.();
23370
+ return;
23371
+ }
23372
+ this.resumeExhausted = true;
23373
+ this.lastResumeReprobeAt = Date.now();
23374
+ log.error(
23375
+ "host-agent",
23376
+ `resumed session ${session.id.slice(0, 8)} FAILED permanently after ${RESUME_RETRY_BACKOFF_MS.length + 1} attempts (${reason}) \u2014 posting visible error, re-probing every ${Math.round(RESUME_REPROBE_INTERVAL_MS / 6e4)} min`
23377
+ );
23378
+ if (!this.resumeFailurePosted) {
23379
+ this.resumeFailurePosted = true;
23380
+ if (session.pluginId && session.pluginAuthToken) {
23381
+ void this.postResumeFailure(
23382
+ {
23383
+ sessionId: session.id,
23384
+ pluginId: session.pluginId,
23385
+ pluginAuthToken: session.pluginAuthToken
23386
+ },
23387
+ `The agent failed to restart after a CLI update/restart (${reason}). I tried ${RESUME_RETRY_BACKOFF_MS.length + 1} times without success. The host stays online and keeps retrying about every ${Math.round(RESUME_REPROBE_INTERVAL_MS / 6e4)} minutes \u2014 once the cause is fixed (for example the agent binary is reinstalled), the session reconnects automatically. You can also redeploy this server from My Servers.`
23388
+ ).catch(() => void 0);
23389
+ } else {
23390
+ log.warn(
23391
+ "host-agent",
23392
+ "resume failure bubble skipped \u2014 persisted session has no pluginAuthToken"
23393
+ );
23394
+ }
23395
+ }
23396
+ }
23397
+ /**
23398
+ * Heartbeat rider for resume recovery (synchronous scheduling only — the
23399
+ * beat must stay punctual, and this adds NO new timers):
23400
+ * - a live session child ⇒ the failure episode (if any) is over: reset
23401
+ * the retry counter + flags so a FUTURE restart gets fresh retries and
23402
+ * a fresh (single) error bubble.
23403
+ * - retries exhausted + no child ⇒ re-probe the resume, throttled to
23404
+ * {@link RESUME_REPROBE_INTERVAL_MS}, so a fixed PATH / reinstalled
23405
+ * binary heals the session WITHOUT another manual restart. A re-probe
23406
+ * that fails again stays in this state (the bubble is not re-posted).
23407
+ */
23408
+ resumeRecoveryTick() {
23409
+ if (this.children.size > 0) {
23410
+ const now2 = Date.now();
23411
+ const hasHealthyChild = [...this.children.values()].some(
23412
+ (c2) => now2 - c2.startedAt >= RESUME_HEALTHY_AFTER_MS
23413
+ );
23414
+ if (hasHealthyChild && (this.resumeRetryAttempts > 0 || this.resumeExhausted)) {
23415
+ log.info("host-agent", "resume recovered \u2014 session child healthy, retry state reset");
23416
+ this.resumeRetryAttempts = 0;
23417
+ this.resumeExhausted = false;
23418
+ this.resumeFailurePosted = false;
23419
+ }
23420
+ return;
23421
+ }
23422
+ if (!this.resumeExhausted || this.resumeRetryTimer) return;
23423
+ const now = Date.now();
23424
+ if (now - this.lastResumeReprobeAt < RESUME_REPROBE_INTERVAL_MS) return;
23425
+ this.lastResumeReprobeAt = now;
23426
+ log.info("host-agent", "resume re-probe (post-exhaustion heartbeat rider)");
23427
+ this.resumePersistedSession();
23428
+ }
23242
23429
  /**
23243
23430
  * Run the backend-supplied per-agent CLI install script (e.g.
23244
23431
  * `claude.ai/install.sh`, `npm i -g @openai/codex`). Best-effort + bounded:
@@ -23672,7 +23859,7 @@ async function defaultFetchJson(url2) {
23672
23859
  async function readUsageReport(deps = {}) {
23673
23860
  const port = deps.port ?? HEADROOM_PROXY_PORT;
23674
23861
  const base = `http://127.0.0.1:${port}`;
23675
- const get2 = deps.fetchJson ?? ((path93) => defaultFetchJson(`${base}${path93}`));
23862
+ const get2 = deps.fetchJson ?? ((path94) => defaultFetchJson(`${base}${path94}`));
23676
23863
  let history;
23677
23864
  try {
23678
23865
  history = await get2("/stats-history");
@@ -25589,11 +25776,11 @@ function resolveDoltInstallStrategy(platform3) {
25589
25776
  }
25590
25777
  var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
25591
25778
  function doltPlatformTuple(platform3, arch2) {
25592
- const os67 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
25779
+ const os68 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
25593
25780
  const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
25594
25781
  if (!a) return null;
25595
- if (os67 === "windows" && a !== "amd64") return null;
25596
- return `${os67}-${a}`;
25782
+ if (os68 === "windows" && a !== "amd64") return null;
25783
+ return `${os68}-${a}`;
25597
25784
  }
25598
25785
  function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
25599
25786
  const tuple = doltPlatformTuple(platform3, arch2);
@@ -27245,7 +27432,7 @@ var vcsAgentReviewH = async (ctx, cmd, parsed) => {
27245
27432
  });
27246
27433
  const token = ctx.pluginAuthToken;
27247
27434
  void (async () => {
27248
- const os67 = createOsStrategy();
27435
+ const os68 = createOsStrategy();
27249
27436
  try {
27250
27437
  const report = await reviewPullRequest(
27251
27438
  {
@@ -27254,7 +27441,7 @@ var vcsAgentReviewH = async (ctx, cmd, parsed) => {
27254
27441
  baseBranch: parsed.baseBranch
27255
27442
  },
27256
27443
  {
27257
- runReview: (input) => new CoderabbitRuntimeStrategy(os67).runOneShot(input),
27444
+ runReview: (input) => new CoderabbitRuntimeStrategy(os68).runOneShot(input),
27258
27445
  runGh: (args2) => defaultRunGh(args2),
27259
27446
  postReport: async (r) => {
27260
27447
  if (!token) return;
@@ -28357,11 +28544,11 @@ function resolveTokenValue(args2) {
28357
28544
  }
28358
28545
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
28359
28546
  if (fileFlag) {
28360
- const path93 = fileFlag.slice("--token-file=".length);
28547
+ const path94 = fileFlag.slice("--token-file=".length);
28361
28548
  try {
28362
- const content = fs65.readFileSync(path93, "utf8").trim();
28363
- if (content.length === 0) fail(`--token-file ${path93} is empty`);
28364
- rmIfExistsQuiet(path93);
28549
+ const content = fs65.readFileSync(path94, "utf8").trim();
28550
+ if (content.length === 0) fail(`--token-file ${path94} is empty`);
28551
+ rmIfExistsQuiet(path94);
28365
28552
  return content;
28366
28553
  } catch (err) {
28367
28554
  fail(`Could not read --token-file: ${err.message}`);
@@ -29281,6 +29468,9 @@ async function resolveAcpAdapterWithRetry(agent, opts = {}) {
29281
29468
 
29282
29469
  // src/agents/acp/runner.ts
29283
29470
  var import_node_crypto11 = require("crypto");
29471
+ var fs77 = __toESM(require("fs"));
29472
+ var os62 = __toESM(require("os"));
29473
+ var path85 = __toESM(require("path"));
29284
29474
 
29285
29475
  // src/services/history.service.ts
29286
29476
  var fs66 = __toESM(require("fs"));
@@ -35061,6 +35251,7 @@ function knownAgentBinaryDirs() {
35061
35251
  out2.push("/usr/bin");
35062
35252
  out2.push(path75.join(home, ".local/bin"));
35063
35253
  out2.push(path75.join(home, "bin"));
35254
+ out2.push(...agentInstallBinDirs());
35064
35255
  if (process.platform === "win32") {
35065
35256
  const { LOCALAPPDATA, APPDATA } = process.env;
35066
35257
  if (LOCALAPPDATA) out2.push(path75.join(LOCALAPPDATA, "cursor-agent"));
@@ -35125,16 +35316,23 @@ var NON_SWITCHABLE = /* @__PURE__ */ new Set([
35125
35316
  "coderabbit"
35126
35317
  ]);
35127
35318
  function displayName(id) {
35319
+ if (id === HOUSE_AGENT_ID) return HOUSE_AGENT_NAME;
35128
35320
  return isKnownAgentId(id) ? AGENT_REGISTRY[id]?.displayName ?? id : id;
35129
35321
  }
35130
35322
  function credentialFailureMessage(agentId, failure) {
35131
35323
  if (failure.message) return failure.message;
35132
35324
  return `No linked credential for ${displayName(agentId)}. Link it in Profile \u203A Agents first.`;
35133
35325
  }
35134
- function resolveSwitchTarget(raw, currentAgent) {
35326
+ function resolveSwitchTarget(raw, currentAgent, currentIsHouse = false) {
35135
35327
  if (typeof raw !== "string" || raw.length === 0) {
35136
35328
  return { ok: false, error: "switch_agent: missing agentId" };
35137
35329
  }
35330
+ if (raw === HOUSE_AGENT_ID) {
35331
+ if (currentIsHouse) {
35332
+ return { ok: false, error: `${HOUSE_AGENT_NAME} is already this session's agent.` };
35333
+ }
35334
+ return { ok: true, agentId: "claude", wireId: HOUSE_AGENT_ID, house: true };
35335
+ }
35138
35336
  if (!isKnownAgentId(raw)) {
35139
35337
  return { ok: false, error: `Unknown agent "${raw}".` };
35140
35338
  }
@@ -35147,10 +35345,10 @@ function resolveSwitchTarget(raw, currentAgent) {
35147
35345
  error: `${displayName(raw)} can't be switched to in a live session yet.`
35148
35346
  };
35149
35347
  }
35150
- if (raw === currentAgent) {
35348
+ if (raw === currentAgent && !currentIsHouse) {
35151
35349
  return { ok: false, error: `${displayName(raw)} is already this session's agent.` };
35152
35350
  }
35153
- return { ok: true, agentId: raw };
35351
+ return { ok: true, agentId: raw, wireId: raw, house: false };
35154
35352
  }
35155
35353
  function toAgentAuth(method, credential) {
35156
35354
  return { kind: method === "api_key" ? "api_key" : "oauth_token", value: credential };
@@ -35225,7 +35423,8 @@ function makeSerializedSwitchEmitter(post2) {
35225
35423
  }
35226
35424
  async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
35227
35425
  const from = deps.currentAgent();
35228
- const target = resolveSwitchTarget(rawAgentId, from);
35426
+ const fromIsHouse = deps.currentIsHouse();
35427
+ const target = resolveSwitchTarget(rawAgentId, from, fromIsHouse);
35229
35428
  if (!target.ok) {
35230
35429
  return {
35231
35430
  ok: false,
@@ -35234,27 +35433,45 @@ async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
35234
35433
  };
35235
35434
  }
35236
35435
  const agentId = target.agentId;
35436
+ const wireId = target.wireId;
35437
+ const fromWireId = fromIsHouse ? HOUSE_AGENT_ID : from;
35438
+ const targetName = displayName(wireId);
35237
35439
  const emitStatus = (status2) => deps.postEvent("switch_agent_status", { ...status2 });
35238
- const emitStep = (step) => deps.postEvent("switch_agent_progress", { step, agentId });
35440
+ const emitStep = (step) => deps.postEvent("switch_agent_progress", { step, agentId: wireId });
35239
35441
  const fail2 = (error) => {
35240
- log.warn("switchAgent", `switch ${from} \u2192 ${agentId} failed: ${error}`);
35241
- void emitStatus({ state: "error", agentId, fromAgentId: from, error });
35242
- return { ok: false, agentId, error };
35442
+ log.warn("switchAgent", `switch ${fromWireId} \u2192 ${wireId} failed: ${error}`);
35443
+ void emitStatus({ state: "error", agentId: wireId, fromAgentId: fromWireId, error });
35444
+ return { ok: false, agentId: wireId, error };
35243
35445
  };
35244
- log.info("switchAgent", `switch requested ${from} \u2192 ${agentId}`);
35245
- void emitStatus({ state: "switching", agentId, fromAgentId: from });
35446
+ log.info("switchAgent", `switch requested ${fromWireId} \u2192 ${wireId}`);
35447
+ void emitStatus({ state: "switching", agentId: wireId, fromAgentId: fromWireId });
35246
35448
  let installScript;
35247
35449
  if (!fastPath.skipProvision) {
35248
35450
  void emitStep("credential");
35249
- const cred = await deps.fetchCredential(agentId);
35451
+ const cred = await deps.fetchCredential(wireId);
35250
35452
  if (!cred.ok) {
35251
- return fail2(credentialFailureMessage(agentId, cred));
35453
+ return fail2(credentialFailureMessage(wireId, cred));
35252
35454
  }
35253
- try {
35254
- deps.provisionCredential(agentId, toAgentAuth(cred.method, cred.credential));
35255
- } catch (err) {
35256
- log.warn("switchAgent", `credential provisioning failed: ${err.message}`);
35257
- return fail2(`Couldn't write the ${displayName(agentId)} credential on this machine.`);
35455
+ if (target.house) {
35456
+ if (cred.method !== "house_proxy" || !cred.baseUrl) {
35457
+ return fail2(`${targetName} isn't available on this backend yet.`);
35458
+ }
35459
+ try {
35460
+ deps.provisionHouseProxy({ baseUrl: cred.baseUrl, token: cred.credential });
35461
+ } catch (err) {
35462
+ log.warn("switchAgent", `house proxy provisioning failed: ${err.message}`);
35463
+ return fail2(`Couldn't configure ${targetName} on this machine.`);
35464
+ }
35465
+ } else {
35466
+ if (cred.method === "house_proxy") {
35467
+ return fail2(`Couldn't fetch the ${targetName} credential.`);
35468
+ }
35469
+ try {
35470
+ deps.provisionCredential(agentId, toAgentAuth(cred.method, cred.credential));
35471
+ } catch (err) {
35472
+ log.warn("switchAgent", `credential provisioning failed: ${err.message}`);
35473
+ return fail2(`Couldn't write the ${targetName} credential on this machine.`);
35474
+ }
35258
35475
  }
35259
35476
  installScript = cred.installScript;
35260
35477
  }
@@ -35267,19 +35484,19 @@ async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
35267
35484
  }
35268
35485
  void emitStep("restart");
35269
35486
  try {
35270
- await deps.swapRuntime(agentId);
35487
+ await deps.swapRuntime(agentId, { house: target.house });
35271
35488
  } catch (err) {
35272
- log.warn("switchAgent", `swap failed, reverting to ${from}: ${err.message}`);
35489
+ log.warn("switchAgent", `swap failed, reverting to ${fromWireId}: ${err.message}`);
35273
35490
  try {
35274
- await deps.revertRuntime(from);
35491
+ await deps.revertRuntime(from, { house: fromIsHouse });
35275
35492
  } catch (revertErr) {
35276
35493
  log.warn("switchAgent", `revert failed: ${revertErr.message}`);
35277
35494
  return fail2(
35278
- `Switching to ${displayName(agentId)} failed and ${displayName(from)} couldn't be restored \u2014 restart the session.`
35495
+ `Switching to ${targetName} failed and ${displayName(fromWireId)} couldn't be restored \u2014 restart the session.`
35279
35496
  );
35280
35497
  }
35281
35498
  return fail2(
35282
- `Couldn't start ${displayName(agentId)} \u2014 the session stays on ${displayName(from)}.`
35499
+ `Couldn't start ${targetName} \u2014 the session stays on ${displayName(fromWireId)}.`
35283
35500
  );
35284
35501
  }
35285
35502
  try {
@@ -35288,9 +35505,9 @@ async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
35288
35505
  log.warn("switchAgent", `persist failed (non-fatal): ${err.message}`);
35289
35506
  }
35290
35507
  deps.reannounce(agentId);
35291
- await emitStatus({ state: "ready", agentId, fromAgentId: from });
35292
- log.info("switchAgent", `switch complete ${from} \u2192 ${agentId}`);
35293
- return { ok: true, agentId };
35508
+ await emitStatus({ state: "ready", agentId: wireId, fromAgentId: fromWireId });
35509
+ log.info("switchAgent", `switch complete ${fromWireId} \u2192 ${wireId}`);
35510
+ return { ok: true, agentId: wireId };
35294
35511
  }
35295
35512
 
35296
35513
  // src/services/streaming/transport.ts
@@ -36567,7 +36784,7 @@ function defaultRunGit(cwd, args2) {
36567
36784
  });
36568
36785
  }
36569
36786
  async function discoverRepos(workingDir, maxDepth = 4) {
36570
- const fs81 = await import("fs/promises");
36787
+ const fs82 = await import("fs/promises");
36571
36788
  const out2 = [];
36572
36789
  await walk(workingDir, 0);
36573
36790
  return out2;
@@ -36575,7 +36792,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
36575
36792
  if (depth > maxDepth) return;
36576
36793
  let entries = [];
36577
36794
  try {
36578
- const dirents = await fs81.readdir(dir, { withFileTypes: true });
36795
+ const dirents = await fs82.readdir(dir, { withFileTypes: true });
36579
36796
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
36580
36797
  } catch {
36581
36798
  return;
@@ -40124,7 +40341,10 @@ async function runAcpSession(opts) {
40124
40341
  refreshSquadRoster();
40125
40342
  const pendingProposal = { current: null };
40126
40343
  let switchCredentialEnv = {};
40127
- const relaunchWith = async (nextAgent) => {
40344
+ let houseActive = isHouseProxyEnv(process.env);
40345
+ let houseEnv = houseActive ? pickHouseProxyEnv(process.env) : {};
40346
+ let pendingHouseConfig = null;
40347
+ const relaunchWith = async (nextAgent, swapOpts = { house: false }) => {
40128
40348
  try {
40129
40349
  await client3.cancel();
40130
40350
  } catch {
@@ -40138,13 +40358,15 @@ async function runAcpSession(opts) {
40138
40358
  if (!adapter) throw new Error(`no ACP adapter available for ${nextAgent}`);
40139
40359
  const disable1m = loadCliConfig().sessions.find((s) => s.pluginId === opts.pluginId)?.disable1mContext === true;
40140
40360
  clientOptions.adapter = adapter;
40361
+ const leavingHouseEnv = !swapOpts.house && (houseActive || isHouseProxyEnv(process.env) || Object.keys(houseEnv).length > 0) ? clearHouseProxyEnvOverrides() : {};
40141
40362
  clientOptions.extraEnv = {
40142
40363
  ...computeAdapterExtraEnv({
40143
40364
  agent: nextAgent,
40144
40365
  autoApprovePermissions: opts.autoApprovePermissions,
40145
40366
  disable1mContext: disable1m
40146
40367
  }),
40147
- ...switchCredentialEnv
40368
+ ...leavingHouseEnv,
40369
+ ...swapOpts.house ? houseEnv : switchCredentialEnv
40148
40370
  };
40149
40371
  const next = new AcpClient(clientOptions);
40150
40372
  const hs = await next.start();
@@ -40164,13 +40386,23 @@ async function runAcpSession(opts) {
40164
40386
  });
40165
40387
  budgetRecovery = makeBudgetRecovery();
40166
40388
  pendingHandoff.current = buildHandoffPreamble(prevAgent, nextAgent, transcript);
40389
+ const wasHouse = houseActive;
40390
+ houseActive = swapOpts.house;
40391
+ if (swapOpts.house) {
40392
+ if (pendingHouseConfig) {
40393
+ persistHouseProxyConfig(pendingHouseConfig);
40394
+ pendingHouseConfig = null;
40395
+ }
40396
+ } else if (wasHouse) {
40397
+ clearHouseProxyConfig();
40398
+ }
40167
40399
  void publisher.publishOutput({
40168
40400
  type: "agent_banner",
40169
- agentId: nextAgent,
40401
+ agentId: swapOpts.house ? HOUSE_AGENT_ID : nextAgent,
40170
40402
  // A switch starts a FRESH conversation with the new agent — never "back".
40171
- title: bannerTitle(false),
40172
- subtitle: buildBannerSubtitle(nextAgent, hs.sessionId, hs.model, hs.tier),
40173
- path: bannerLocation(opts.cwd),
40403
+ title: swapOpts.house ? HOUSE_AGENT_NAME : bannerTitle(false),
40404
+ subtitle: swapOpts.house ? HOUSE_AGENT_SUBTITLE : buildBannerSubtitle(nextAgent, hs.sessionId, hs.model, hs.tier),
40405
+ path: swapOpts.house ? "" : bannerLocation(opts.cwd),
40174
40406
  done: true
40175
40407
  });
40176
40408
  };
@@ -40185,6 +40417,7 @@ async function runAcpSession(opts) {
40185
40417
  );
40186
40418
  const switchDeps = {
40187
40419
  currentAgent: () => opts.agent,
40420
+ currentIsHouse: () => houseActive,
40188
40421
  postEvent: emitSwitchEvent,
40189
40422
  fetchCredential: (agentId) => fetchProvisionCredentialDetailed({
40190
40423
  agentId,
@@ -40196,6 +40429,21 @@ async function runAcpSession(opts) {
40196
40429
  provisionCredential: (agentId, auth) => {
40197
40430
  switchCredentialEnv = provisionAgentCredentials(agentId, auth);
40198
40431
  },
40432
+ provisionHouseProxy: ({ baseUrl, token }) => {
40433
+ const claudeConfigDir = path85.join(
40434
+ os62.homedir(),
40435
+ ".codeam",
40436
+ "house-claude",
40437
+ `switch-${opts.pluginId}`
40438
+ );
40439
+ try {
40440
+ fs77.mkdirSync(claudeConfigDir, { recursive: true, mode: 448 });
40441
+ } catch {
40442
+ }
40443
+ houseEnv = buildHouseProxyChildEnv({ baseUrl, token, claudeConfigDir });
40444
+ pendingHouseConfig = { baseUrl, token, claudeConfigDir };
40445
+ switchCredentialEnv = {};
40446
+ },
40199
40447
  ensureBinary: (agentId, installScript, onRetry) => ensureAgentBinaryForSwitch(agentId, installScript, { onRetry }),
40200
40448
  swapRuntime: relaunchWith,
40201
40449
  revertRuntime: relaunchWith,
@@ -41391,9 +41639,9 @@ function startClaudeCredentialSync(opts) {
41391
41639
  }
41392
41640
 
41393
41641
  // src/beads/workflow-hint.ts
41394
- var fs77 = __toESM(require("fs"));
41395
- var path85 = __toESM(require("path"));
41396
- var os62 = __toESM(require("os"));
41642
+ var fs78 = __toESM(require("fs"));
41643
+ var path86 = __toESM(require("path"));
41644
+ var os63 = __toESM(require("os"));
41397
41645
  var BEADS_HINT_MARKER = "<!-- codeam:beads-workflow -->";
41398
41646
  var BEADS_HINT = `${BEADS_HINT_MARKER}
41399
41647
  # Beads (bd) \u2014 task tracking + persistent memory (ALWAYS use it)
@@ -41407,22 +41655,22 @@ This environment uses **bd (beads)** for issue/task tracking and persistent memo
41407
41655
  - \`bd ready\` (available work) \xB7 \`bd show <id>\` \xB7 \`bd update <id> --claim\` \xB7 \`bd close <id>\`.
41408
41656
  - Use \`bd remember "..."\` for persistent knowledge \u2014 do NOT use MEMORY.md files.
41409
41657
  ${BEADS_HINT_MARKER}`;
41410
- function ensureBeadsWorkflowHint(homeDir2 = os62.homedir()) {
41658
+ function ensureBeadsWorkflowHint(homeDir2 = os63.homedir()) {
41411
41659
  try {
41412
- const file = path85.join(homeDir2, ".claude", "CLAUDE.md");
41660
+ const file = path86.join(homeDir2, ".claude", "CLAUDE.md");
41413
41661
  let existing = "";
41414
41662
  try {
41415
- existing = fs77.readFileSync(file, "utf8");
41663
+ existing = fs78.readFileSync(file, "utf8");
41416
41664
  } catch {
41417
41665
  }
41418
41666
  if (existing.includes(BEADS_HINT_MARKER)) return;
41419
- fs77.mkdirSync(path85.dirname(file), { recursive: true });
41667
+ fs78.mkdirSync(path86.dirname(file), { recursive: true });
41420
41668
  const next = existing.trim() ? `${existing.trimEnd()}
41421
41669
 
41422
41670
  ${BEADS_HINT}
41423
41671
  ` : `${BEADS_HINT}
41424
41672
  `;
41425
- fs77.writeFileSync(file, next);
41673
+ fs78.writeFileSync(file, next);
41426
41674
  } catch {
41427
41675
  }
41428
41676
  }
@@ -41933,7 +42181,7 @@ var AcpDriver = class {
41933
42181
  };
41934
42182
 
41935
42183
  // src/baton/transcript-mirror.ts
41936
- var fs78 = __toESM(require("fs"));
42184
+ var fs79 = __toESM(require("fs"));
41937
42185
  var TranscriptMirror = class {
41938
42186
  constructor(deps) {
41939
42187
  this.deps = deps;
@@ -42000,7 +42248,7 @@ var TranscriptMirror = class {
42000
42248
  }
42001
42249
  };
42002
42250
  function defaultWatch(file, onChange) {
42003
- const w3 = fs78.watch(file, { persistent: false }, () => onChange());
42251
+ const w3 = fs79.watch(file, { persistent: false }, () => onChange());
42004
42252
  return () => w3.close();
42005
42253
  }
42006
42254
 
@@ -42330,16 +42578,16 @@ function keepDeviceAwake(deps = {}) {
42330
42578
  }
42331
42579
 
42332
42580
  // src/agents/claude/onboarding.ts
42333
- var fs79 = __toESM(require("fs"));
42334
- var os64 = __toESM(require("os"));
42335
- var path86 = __toESM(require("path"));
42581
+ var fs80 = __toESM(require("fs"));
42582
+ var os65 = __toESM(require("os"));
42583
+ var path87 = __toESM(require("path"));
42336
42584
  var ONBOARDING_VERSION_SENTINEL = "9999.0.0";
42337
42585
  function ensureClaudeOnboarded(cwd) {
42338
42586
  try {
42339
- const file = path86.join(os64.homedir(), ".claude.json");
42587
+ const file = path87.join(os65.homedir(), ".claude.json");
42340
42588
  let config = {};
42341
42589
  try {
42342
- config = JSON.parse(fs79.readFileSync(file, "utf8"));
42590
+ config = JSON.parse(fs80.readFileSync(file, "utf8"));
42343
42591
  } catch {
42344
42592
  }
42345
42593
  let changed = false;
@@ -42364,8 +42612,8 @@ function ensureClaudeOnboarded(cwd) {
42364
42612
  }
42365
42613
  }
42366
42614
  if (!changed) return;
42367
- fs79.mkdirSync(path86.dirname(file), { recursive: true });
42368
- fs79.writeFileSync(file, JSON.stringify(config, null, 2));
42615
+ fs80.mkdirSync(path87.dirname(file), { recursive: true });
42616
+ fs80.writeFileSync(file, JSON.stringify(config, null, 2));
42369
42617
  log.info(
42370
42618
  "claude",
42371
42619
  `pre-completed Claude onboarding${cwd ? ` + trusted workspace ${cwd}` : ""}`
@@ -43102,7 +43350,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
43102
43350
  var import_child_process31 = require("child_process");
43103
43351
  var import_util4 = require("util");
43104
43352
  var import_picocolors9 = __toESM(require("picocolors"));
43105
- var path87 = __toESM(require("path"));
43353
+ var path88 = __toESM(require("path"));
43106
43354
  var execFileP6 = (0, import_util4.promisify)(import_child_process31.execFile);
43107
43355
  var MAX_BUFFER = 8 * 1024 * 1024;
43108
43356
  function resetStdinForChild() {
@@ -43591,7 +43839,7 @@ var GitHubCodespacesProvider = class {
43591
43839
  });
43592
43840
  }
43593
43841
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
43594
- const remoteDir = path87.posix.dirname(remotePath);
43842
+ const remoteDir = path88.posix.dirname(remotePath);
43595
43843
  const parts = [
43596
43844
  `mkdir -p ${shellQuote(remoteDir)}`,
43597
43845
  `cat > ${shellQuote(remotePath)}`
@@ -43661,7 +43909,7 @@ function shellQuote(s) {
43661
43909
  // src/services/providers/gitpod.ts
43662
43910
  var import_child_process32 = require("child_process");
43663
43911
  var import_util5 = require("util");
43664
- var path88 = __toESM(require("path"));
43912
+ var path89 = __toESM(require("path"));
43665
43913
  var import_picocolors10 = __toESM(require("picocolors"));
43666
43914
  var execFileP7 = (0, import_util5.promisify)(import_child_process32.execFile);
43667
43915
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -43901,7 +44149,7 @@ var GitpodProvider = class {
43901
44149
  });
43902
44150
  }
43903
44151
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
43904
- const remoteDir = path88.posix.dirname(remotePath);
44152
+ const remoteDir = path89.posix.dirname(remotePath);
43905
44153
  const parts = [
43906
44154
  `mkdir -p ${shellQuote2(remoteDir)}`,
43907
44155
  `cat > ${shellQuote2(remotePath)}`
@@ -43937,7 +44185,7 @@ function shellQuote2(s) {
43937
44185
  // src/services/providers/gitlab-workspaces.ts
43938
44186
  var import_child_process33 = require("child_process");
43939
44187
  var import_util6 = require("util");
43940
- var path89 = __toESM(require("path"));
44188
+ var path90 = __toESM(require("path"));
43941
44189
  var execFileP8 = (0, import_util6.promisify)(import_child_process33.execFile);
43942
44190
  var MAX_BUFFER3 = 8 * 1024 * 1024;
43943
44191
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -44197,7 +44445,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
44197
44445
  }
44198
44446
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
44199
44447
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
44200
- const remoteDir = path89.posix.dirname(remotePath);
44448
+ const remoteDir = path90.posix.dirname(remotePath);
44201
44449
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
44202
44450
  if (options.mode != null) {
44203
44451
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -44265,7 +44513,7 @@ function shellQuote3(s) {
44265
44513
  // src/services/providers/railway.ts
44266
44514
  var import_child_process34 = require("child_process");
44267
44515
  var import_util7 = require("util");
44268
- var path90 = __toESM(require("path"));
44516
+ var path91 = __toESM(require("path"));
44269
44517
  var execFileP9 = (0, import_util7.promisify)(import_child_process34.execFile);
44270
44518
  var MAX_BUFFER4 = 8 * 1024 * 1024;
44271
44519
  function resetStdinForChild4() {
@@ -44501,7 +44749,7 @@ var RailwayProvider = class {
44501
44749
  if (!projectId || !serviceId) {
44502
44750
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
44503
44751
  }
44504
- const remoteDir = path90.posix.dirname(remotePath);
44752
+ const remoteDir = path91.posix.dirname(remotePath);
44505
44753
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
44506
44754
  if (options.mode != null) {
44507
44755
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -45147,8 +45395,8 @@ async function invite() {
45147
45395
  var import_node_dns = require("dns");
45148
45396
  var import_node_util5 = require("util");
45149
45397
  var import_node_crypto13 = require("crypto");
45150
- var fs80 = __toESM(require("fs"));
45151
- var path91 = __toESM(require("path"));
45398
+ var fs81 = __toESM(require("fs"));
45399
+ var path92 = __toESM(require("path"));
45152
45400
  var import_picocolors14 = __toESM(require("picocolors"));
45153
45401
  var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
45154
45402
  async function checkDns(apiBase2) {
@@ -45204,13 +45452,13 @@ async function checkHealth(apiBase2) {
45204
45452
  }
45205
45453
  }
45206
45454
  function checkConfigDir() {
45207
- const dir = path91.join(require("os").homedir(), ".codeam");
45455
+ const dir = path92.join(require("os").homedir(), ".codeam");
45208
45456
  try {
45209
- fs80.mkdirSync(dir, { recursive: true, mode: 448 });
45210
- const probe = path91.join(dir, ".doctor-probe");
45211
- fs80.writeFileSync(probe, "ok", { mode: 384 });
45212
- const read2 = fs80.readFileSync(probe, "utf8");
45213
- fs80.unlinkSync(probe);
45457
+ fs81.mkdirSync(dir, { recursive: true, mode: 448 });
45458
+ const probe = path92.join(dir, ".doctor-probe");
45459
+ fs81.writeFileSync(probe, "ok", { mode: 384 });
45460
+ const read2 = fs81.readFileSync(probe, "utf8");
45461
+ fs81.unlinkSync(probe);
45214
45462
  if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
45215
45463
  return {
45216
45464
  id: "config-dir",
@@ -45250,9 +45498,9 @@ function checkSessions() {
45250
45498
  }
45251
45499
  }
45252
45500
  function checkAgentBinaries() {
45253
- const os67 = createOsStrategy();
45501
+ const os68 = createOsStrategy();
45254
45502
  return getEnabledAgents().map((meta) => {
45255
- const found = os67.findInPath(meta.binaryName);
45503
+ const found = os68.findInPath(meta.binaryName);
45256
45504
  return {
45257
45505
  id: `agent-${meta.id}`,
45258
45506
  label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
@@ -45274,7 +45522,7 @@ function checkNodePty() {
45274
45522
  detail: "not required on this platform"
45275
45523
  };
45276
45524
  }
45277
- const vendoredPath = path91.join(__dirname, "vendor", "node-pty");
45525
+ const vendoredPath = path92.join(__dirname, "vendor", "node-pty");
45278
45526
  for (const target of [vendoredPath, "node-pty"]) {
45279
45527
  try {
45280
45528
  require(target);
@@ -45316,7 +45564,7 @@ function checkChokidar() {
45316
45564
  }
45317
45565
  async function doctor(args2 = []) {
45318
45566
  const json = args2.includes("--json");
45319
- const cliVersion = true ? "2.65.14" : "0.0.0-dev";
45567
+ const cliVersion = true ? "2.65.16" : "0.0.0-dev";
45320
45568
  const apiBase2 = resolveApiBaseUrl();
45321
45569
  const diagnosticId = (0, import_node_crypto13.randomUUID)();
45322
45570
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -45707,7 +45955,7 @@ async function mcpRun(args2) {
45707
45955
  // src/commands/version.ts
45708
45956
  var import_picocolors15 = __toESM(require("picocolors"));
45709
45957
  function version2() {
45710
- const v = true ? "2.65.14" : "unknown";
45958
+ const v = true ? "2.65.16" : "unknown";
45711
45959
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
45712
45960
  }
45713
45961
 
@@ -45856,10 +46104,10 @@ var EXIT_CODE_NAMES = {
45856
46104
  };
45857
46105
 
45858
46106
  // src/index.ts
45859
- var os66 = __toESM(require("os"));
46107
+ var os67 = __toESM(require("os"));
45860
46108
  if (!process.env.HOME) {
45861
46109
  try {
45862
- const home = os66.homedir();
46110
+ const home = os67.homedir();
45863
46111
  if (home) process.env.HOME = home;
45864
46112
  } catch {
45865
46113
  }