codeam-cli 2.61.49 → 2.61.50

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 +6 -0
  2. package/dist/index.js +742 -537
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -483,6 +483,23 @@ var AGENT_REGISTRY = {
483
483
  headroomWrappable: false,
484
484
  // Native ACP server: `kimi acp` (stdio JSON-RPC, answers `initialize`).
485
485
  acp: true
486
+ },
487
+ opencode: {
488
+ id: "opencode",
489
+ displayName: "opencode",
490
+ binaryName: "opencode",
491
+ enabled: true,
492
+ // opencode auth = `opencode auth login` (multi-provider; API keys AND
493
+ // provider OAuth), which writes a login-state file at
494
+ // ~/.local/share/opencode/auth.json. The CLI captures that blob (like
495
+ // claude/codex capture their local login), so the vaulted credential is
496
+ // the auth.json — an `oauth_token`-kind login blob, not a bare api_key.
497
+ supportedAuthKinds: ["oauth_token"],
498
+ preferredAuthKind: "oauth_token",
499
+ // Not listed by `headroom init --global` (claude/codex/copilot only) — native.
500
+ headroomWrappable: false,
501
+ // Native ACP server: `opencode acp` (stdio JSON-RPC).
502
+ acp: true
486
503
  }
487
504
  };
488
505
  function getEnabledAgents() {
@@ -512,6 +529,9 @@ var PUBLIC_TO_INTERNAL = {
512
529
  coderabbit: "coderabbit",
513
530
  gemini: "gemini",
514
531
  kimi: "kimi",
532
+ // opencode is a real, distinct agent (its own binary + ACP server) — it does
533
+ // NOT map onto another runtime. Public id === internal id.
534
+ opencode: "opencode",
515
535
  // OmniRoute runs Claude Code under the hood, pointed at the user's OmniRoute
516
536
  // gateway (their vaulted base URL + token) instead of the house MiniMax
517
537
  // proxy. Same internal runtime as the house agent — `claude` — differing only
@@ -1722,11 +1742,11 @@ function quiet(fn) {
1722
1742
  log.debug(TAG, "ignored sync error", err);
1723
1743
  }
1724
1744
  }
1725
- function rmIfExistsQuiet(path79) {
1745
+ function rmIfExistsQuiet(path80) {
1726
1746
  try {
1727
- fs2.rmSync(path79, { force: true });
1747
+ fs2.rmSync(path80, { force: true });
1728
1748
  } catch (err) {
1729
- log.debug(TAG, `rmIfExists failed for ${path79}`, err);
1749
+ log.debug(TAG, `rmIfExists failed for ${path80}`, err);
1730
1750
  }
1731
1751
  }
1732
1752
  function killQuiet(target, signal = "SIGTERM") {
@@ -1872,9 +1892,9 @@ var _default = makeConfig();
1872
1892
  var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, setDisable1mContext, clearAll, saveCliConfig, loadCliConfig } = _default;
1873
1893
 
1874
1894
  // src/commands/pair-auto.ts
1875
- var fs58 = __toESM(require("fs"));
1876
- var os49 = __toESM(require("os"));
1877
- var path62 = __toESM(require("path"));
1895
+ var fs59 = __toESM(require("fs"));
1896
+ var os50 = __toESM(require("os"));
1897
+ var path63 = __toESM(require("path"));
1878
1898
  var import_crypto4 = require("crypto");
1879
1899
 
1880
1900
  // src/services/telemetry.service.ts
@@ -1910,8 +1930,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
1910
1930
  return decodedFile;
1911
1931
  };
1912
1932
  }
1913
- function normalizeWindowsPath(path79) {
1914
- return path79.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1933
+ function normalizeWindowsPath(path80) {
1934
+ return path80.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1915
1935
  }
1916
1936
 
1917
1937
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -4391,9 +4411,9 @@ async function addSourceContext(frames) {
4391
4411
  LRU_FILE_CONTENTS_CACHE.reduce();
4392
4412
  return frames;
4393
4413
  }
4394
- function getContextLinesFromFile(path79, ranges, output) {
4414
+ function getContextLinesFromFile(path80, ranges, output) {
4395
4415
  return new Promise((resolve8) => {
4396
- const stream = (0, import_node_fs.createReadStream)(path79);
4416
+ const stream = (0, import_node_fs.createReadStream)(path80);
4397
4417
  const lineReaded = (0, import_node_readline.createInterface)({
4398
4418
  input: stream
4399
4419
  });
@@ -4408,7 +4428,7 @@ function getContextLinesFromFile(path79, ranges, output) {
4408
4428
  let rangeStart = range[0];
4409
4429
  let rangeEnd = range[1];
4410
4430
  function onStreamError() {
4411
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path79, 1);
4431
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path80, 1);
4412
4432
  lineReaded.close();
4413
4433
  lineReaded.removeAllListeners();
4414
4434
  destroyStreamAndResolve();
@@ -4469,8 +4489,8 @@ function clearLineContext(frame) {
4469
4489
  delete frame.context_line;
4470
4490
  delete frame.post_context;
4471
4491
  }
4472
- function shouldSkipContextLinesForFile(path79) {
4473
- return path79.startsWith("node:") || path79.endsWith(".min.js") || path79.endsWith(".min.cjs") || path79.endsWith(".min.mjs") || path79.startsWith("data:");
4492
+ function shouldSkipContextLinesForFile(path80) {
4493
+ return path80.startsWith("node:") || path80.endsWith(".min.js") || path80.endsWith(".min.cjs") || path80.endsWith(".min.mjs") || path80.startsWith("data:");
4474
4494
  }
4475
4495
  function shouldSkipContextLinesForFrame(frame) {
4476
4496
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -6624,7 +6644,7 @@ function readAnonId() {
6624
6644
  }
6625
6645
  function superProperties() {
6626
6646
  return {
6627
- cliVersion: true ? "2.61.49" : "0.0.0-dev",
6647
+ cliVersion: true ? "2.61.50" : "0.0.0-dev",
6628
6648
  nodeVersion: process.version,
6629
6649
  platform: process.platform,
6630
6650
  arch: process.arch,
@@ -6805,7 +6825,7 @@ var os4 = __toESM(require("os"));
6805
6825
  // package.json
6806
6826
  var package_default = {
6807
6827
  name: "codeam-cli",
6808
- version: "2.61.49",
6828
+ version: "2.61.50",
6809
6829
  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.",
6810
6830
  type: "commonjs",
6811
6831
  main: "dist/index.js",
@@ -7977,7 +7997,7 @@ var CommandRelayService = class _CommandRelayService {
7977
7997
  // fresh + clear the "CLI update available" banner after a self-update
7978
7998
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
7979
7999
  // pair/reconnect). Older backends ignore the extra field.
7980
- ..."2.61.49" ? { ideVersion: "2.61.49" } : {}
8000
+ ..."2.61.50" ? { ideVersion: "2.61.50" } : {}
7981
8001
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
7982
8002
  }
7983
8003
  /**
@@ -8204,10 +8224,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
8204
8224
  /[\\/]Start Menu([\\/]|$)/i,
8205
8225
  /[\\/]Templates([\\/]|$)/i
8206
8226
  ];
8207
- function isUnsafeWindowsWatchRoot(dir, homedir46) {
8227
+ function isUnsafeWindowsWatchRoot(dir, homedir48) {
8208
8228
  const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
8209
8229
  const cwd = norm(dir);
8210
- const home = norm(homedir46);
8230
+ const home = norm(homedir48);
8211
8231
  if (cwd === home) return true;
8212
8232
  if (/^[a-z]:$/.test(cwd)) return true;
8213
8233
  const sysRoots = [
@@ -9351,9 +9371,9 @@ function closeAllTerminals() {
9351
9371
  }
9352
9372
 
9353
9373
  // src/commands/start/handlers.ts
9354
- var fs57 = __toESM(require("fs"));
9355
- var os48 = __toESM(require("os"));
9356
- var path61 = __toESM(require("path"));
9374
+ var fs58 = __toESM(require("fs"));
9375
+ var os49 = __toESM(require("os"));
9376
+ var path62 = __toESM(require("path"));
9357
9377
  var import_crypto3 = require("crypto");
9358
9378
  var import_child_process24 = require("child_process");
9359
9379
 
@@ -10185,8 +10205,8 @@ function findGitRoot2(startDir) {
10185
10205
 
10186
10206
  // src/commands/link.ts
10187
10207
  var import_node_crypto8 = require("crypto");
10188
- var fs30 = __toESM(require("fs"));
10189
- var path34 = __toESM(require("path"));
10208
+ var fs31 = __toESM(require("fs"));
10209
+ var path35 = __toESM(require("path"));
10190
10210
  var import_chokidar = __toESM(require("chokidar"));
10191
10211
  var import_picocolors2 = __toESM(require("picocolors"));
10192
10212
 
@@ -12833,10 +12853,10 @@ function buildForPlatform(platform3) {
12833
12853
  var import_node_crypto4 = require("crypto");
12834
12854
 
12835
12855
  // src/agents/claude/resolver.ts
12836
- function buildClaudeLaunch(extraArgs = [], os59 = createOsStrategy()) {
12837
- const found = os59.findInPath("claude") ?? os59.findInPath("claude-code");
12856
+ function buildClaudeLaunch(extraArgs = [], os60 = createOsStrategy()) {
12857
+ const found = os60.findInPath("claude") ?? os60.findInPath("claude-code");
12838
12858
  if (!found) return null;
12839
- return os59.buildLaunch(found, extraArgs);
12859
+ return os60.buildLaunch(found, extraArgs);
12840
12860
  }
12841
12861
 
12842
12862
  // src/agents/claude/installer.ts
@@ -13426,8 +13446,8 @@ var ClaudeRuntimeStrategy = class {
13426
13446
  meta = getAgent("claude");
13427
13447
  mode = "interactive";
13428
13448
  os;
13429
- constructor(os59) {
13430
- this.os = os59;
13449
+ constructor(os60) {
13450
+ this.os = os60;
13431
13451
  }
13432
13452
  /**
13433
13453
  * Claude Code's react-ink TUI enables bracketed-paste mode at
@@ -14207,8 +14227,8 @@ function codexCredentialLocator() {
14207
14227
  function codexLoginLauncher() {
14208
14228
  return {
14209
14229
  async ensureInstalled() {
14210
- const os59 = createOsStrategy();
14211
- return os59.findInPath("codex") !== null;
14230
+ const os60 = createOsStrategy();
14231
+ return os60.findInPath("codex") !== null;
14212
14232
  },
14213
14233
  launch() {
14214
14234
  return (0, import_node_child_process4.spawn)("codex", ["login"], { stdio: "inherit" });
@@ -14231,8 +14251,8 @@ var CodexRuntimeStrategy = class {
14231
14251
  meta = getAgent("codex");
14232
14252
  mode = "interactive";
14233
14253
  os;
14234
- constructor(os59) {
14235
- this.os = os59;
14254
+ constructor(os60) {
14255
+ this.os = os60;
14236
14256
  }
14237
14257
  async prepareLaunch() {
14238
14258
  let binary = this.os.findInPath("codex");
@@ -14341,12 +14361,12 @@ var CodexRuntimeStrategy = class {
14341
14361
  });
14342
14362
  }
14343
14363
  };
14344
- function resolveNpm(os59) {
14345
- return os59.id === "win32" ? "npm.cmd" : "npm";
14364
+ function resolveNpm(os60) {
14365
+ return os60.id === "win32" ? "npm.cmd" : "npm";
14346
14366
  }
14347
- async function installCodexViaNpm(os59) {
14367
+ async function installCodexViaNpm(os60) {
14348
14368
  return new Promise((resolve8, reject) => {
14349
- const proc = (0, import_node_child_process5.spawn)(resolveNpm(os59), ["install", "-g", "@openai/codex"], {
14369
+ const proc = (0, import_node_child_process5.spawn)(resolveNpm(os60), ["install", "-g", "@openai/codex"], {
14350
14370
  stdio: "inherit"
14351
14371
  });
14352
14372
  proc.on("close", (code) => {
@@ -14363,16 +14383,16 @@ async function installCodexViaNpm(os59) {
14363
14383
  });
14364
14384
  });
14365
14385
  }
14366
- function augmentNpmGlobalBin(os59) {
14386
+ function augmentNpmGlobalBin(os60) {
14367
14387
  try {
14368
- const result = (0, import_node_child_process5.spawnSync)(resolveNpm(os59), ["prefix", "-g"], {
14388
+ const result = (0, import_node_child_process5.spawnSync)(resolveNpm(os60), ["prefix", "-g"], {
14369
14389
  stdio: ["ignore", "pipe", "ignore"]
14370
14390
  });
14371
14391
  if (result.status !== 0) return;
14372
14392
  const prefix = result.stdout.toString().trim();
14373
14393
  if (!prefix) return;
14374
- const binDir = os59.id === "win32" ? prefix : path24.join(prefix, "bin");
14375
- os59.augmentPath([binDir]);
14394
+ const binDir = os60.id === "win32" ? prefix : path24.join(prefix, "bin");
14395
+ os60.augmentPath([binDir]);
14376
14396
  } catch {
14377
14397
  }
14378
14398
  }
@@ -14456,9 +14476,9 @@ var import_node_child_process8 = require("child_process");
14456
14476
  // src/agents/coderabbit/installer.ts
14457
14477
  var import_node_child_process6 = require("child_process");
14458
14478
  var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
14459
- async function ensureCoderabbitInstalled(os59) {
14460
- if (os59.findInPath("coderabbit")) return true;
14461
- if (os59.id === "win32") {
14479
+ async function ensureCoderabbitInstalled(os60) {
14480
+ if (os60.findInPath("coderabbit")) return true;
14481
+ if (os60.id === "win32") {
14462
14482
  console.error(
14463
14483
  "\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"
14464
14484
  );
@@ -14491,8 +14511,8 @@ async function ensureCoderabbitInstalled(os59) {
14491
14511
  proc.on("error", () => finish(false));
14492
14512
  });
14493
14513
  if (!ok) return false;
14494
- os59.augmentPath([`${os59.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
14495
- return os59.findInPath("coderabbit") !== null;
14514
+ os60.augmentPath([`${os60.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
14515
+ return os60.findInPath("coderabbit") !== null;
14496
14516
  }
14497
14517
 
14498
14518
  // src/agents/coderabbit/link.ts
@@ -14527,10 +14547,10 @@ function coderabbitCredentialLocator() {
14527
14547
  validate: validateNonEmptyCredential
14528
14548
  };
14529
14549
  }
14530
- function coderabbitLoginLauncher(os59) {
14550
+ function coderabbitLoginLauncher(os60) {
14531
14551
  return {
14532
14552
  async ensureInstalled() {
14533
- return ensureCoderabbitInstalled(os59);
14553
+ return ensureCoderabbitInstalled(os60);
14534
14554
  },
14535
14555
  launch() {
14536
14556
  return (0, import_node_child_process7.spawn)("coderabbit", ["auth", "login"], { stdio: "inherit" });
@@ -14586,8 +14606,8 @@ function pickLine(obj) {
14586
14606
  function toHunk(raw, groupSeverity) {
14587
14607
  if (!raw || typeof raw !== "object") return null;
14588
14608
  const o = raw;
14589
- const path79 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
14590
- if (!path79) return null;
14609
+ const path80 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
14610
+ if (!path80) return null;
14591
14611
  const message = asString(
14592
14612
  pick(o, [
14593
14613
  "comment",
@@ -14604,7 +14624,7 @@ function toHunk(raw, groupSeverity) {
14604
14624
  const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
14605
14625
  const locObj = pick(o, ["location"]) ?? o;
14606
14626
  return {
14607
- path: path79.trim(),
14627
+ path: path80.trim(),
14608
14628
  line: pickLine(o) ?? pickLine(locObj),
14609
14629
  severity,
14610
14630
  message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
@@ -14687,10 +14707,10 @@ function parsePlain(stdout) {
14687
14707
  for (const line of stdout.split(/\r?\n/)) {
14688
14708
  const m = line.match(HUNK_LINE_RE);
14689
14709
  if (!m) continue;
14690
- const [, path79, lineNo, sevToken, message] = m;
14691
- if (!path79 || !lineNo || !message) continue;
14710
+ const [, path80, lineNo, sevToken, message] = m;
14711
+ if (!path80 || !lineNo || !message) continue;
14692
14712
  hunks.push({
14693
- path: path79.trim(),
14713
+ path: path80.trim(),
14694
14714
  line: Number(lineNo),
14695
14715
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
14696
14716
  message: message.trim().replace(/^[*-]\s+/, "")
@@ -14750,8 +14770,8 @@ var CoderabbitRuntimeStrategy = class {
14750
14770
  meta = getAgent("coderabbit");
14751
14771
  mode = "batch";
14752
14772
  os;
14753
- constructor(os59) {
14754
- this.os = os59;
14773
+ constructor(os60) {
14774
+ this.os = os60;
14755
14775
  }
14756
14776
  getDefaultArgs() {
14757
14777
  return ["review", "--agent"];
@@ -15022,10 +15042,10 @@ function cursorCredentialLocator() {
15022
15042
  validate: validateNonEmptyCredential
15023
15043
  };
15024
15044
  }
15025
- function cursorLoginLauncher(os59) {
15045
+ function cursorLoginLauncher(os60) {
15026
15046
  return {
15027
15047
  async ensureInstalled() {
15028
- if (os59.findInPath("cursor-agent")) return true;
15048
+ if (os60.findInPath("cursor-agent")) return true;
15029
15049
  console.error(
15030
15050
  "\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"
15031
15051
  );
@@ -15089,8 +15109,8 @@ var CursorRuntimeStrategy = class {
15089
15109
  meta = getAgent("cursor");
15090
15110
  mode = "interactive";
15091
15111
  os;
15092
- constructor(os59) {
15093
- this.os = os59;
15112
+ constructor(os60) {
15113
+ this.os = os60;
15094
15114
  }
15095
15115
  async prepareLaunch() {
15096
15116
  const binary = this.os.findInPath("cursor-agent");
@@ -15306,10 +15326,10 @@ function aiderCredentialLocator() {
15306
15326
  validate: validateNonEmptyCredential
15307
15327
  };
15308
15328
  }
15309
- function aiderLoginLauncher(os59) {
15329
+ function aiderLoginLauncher(os60) {
15310
15330
  return {
15311
15331
  async ensureInstalled() {
15312
- if (os59.findInPath("aider")) return true;
15332
+ if (os60.findInPath("aider")) return true;
15313
15333
  console.error(
15314
15334
  "\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
15315
15335
  );
@@ -15319,7 +15339,7 @@ function aiderLoginLauncher(os59) {
15319
15339
  console.error(
15320
15340
  "\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"
15321
15341
  );
15322
- return (0, import_node_child_process11.spawn)(os59.id === "win32" ? "cmd.exe" : "sh", os59.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
15342
+ return (0, import_node_child_process11.spawn)(os60.id === "win32" ? "cmd.exe" : "sh", os60.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
15323
15343
  stdio: "ignore"
15324
15344
  });
15325
15345
  }
@@ -15391,8 +15411,8 @@ var AiderRuntimeStrategy = class {
15391
15411
  meta = getAgent("aider");
15392
15412
  mode = "interactive";
15393
15413
  os;
15394
- constructor(os59) {
15395
- this.os = os59;
15414
+ constructor(os60) {
15415
+ this.os = os60;
15396
15416
  }
15397
15417
  async prepareLaunch() {
15398
15418
  const binary = this.os.findInPath("aider");
@@ -15524,8 +15544,8 @@ function geminiCredentialLocator() {
15524
15544
  function geminiLoginLauncher() {
15525
15545
  return {
15526
15546
  async ensureInstalled() {
15527
- const os59 = createOsStrategy();
15528
- return os59.findInPath("gemini") !== null;
15547
+ const os60 = createOsStrategy();
15548
+ return os60.findInPath("gemini") !== null;
15529
15549
  },
15530
15550
  launch() {
15531
15551
  return (0, import_node_child_process12.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
@@ -15715,8 +15735,8 @@ var GeminiRuntimeStrategy = class {
15715
15735
  meta = getAgent("gemini");
15716
15736
  mode = "interactive";
15717
15737
  os;
15718
- constructor(os59) {
15719
- this.os = os59;
15738
+ constructor(os60) {
15739
+ this.os = os60;
15720
15740
  }
15721
15741
  async prepareLaunch() {
15722
15742
  const binary = this.os.findInPath("gemini");
@@ -16007,8 +16027,8 @@ var KimiRuntimeStrategy = class {
16007
16027
  meta = getAgent("kimi");
16008
16028
  mode = "interactive";
16009
16029
  os;
16010
- constructor(os59) {
16011
- this.os = os59;
16030
+ constructor(os60) {
16031
+ this.os = os60;
16012
16032
  }
16013
16033
  async prepareLaunch() {
16014
16034
  const binary = this.os.findInPath("kimi");
@@ -16119,21 +16139,133 @@ var KimiRuntimeStrategy = class {
16119
16139
  }
16120
16140
  };
16121
16141
 
16142
+ // src/agents/opencode/runtime.ts
16143
+ var import_node_child_process14 = require("child_process");
16144
+
16145
+ // src/agents/opencode/local-token.ts
16146
+ var fs30 = __toESM(require("fs"));
16147
+ var os27 = __toESM(require("os"));
16148
+ var path34 = __toESM(require("path"));
16149
+ function opencodeCredentialsPath() {
16150
+ const xdgData = process.env.XDG_DATA_HOME || path34.join(os27.homedir(), ".local", "share");
16151
+ return path34.join(xdgData, "opencode", "auth.json");
16152
+ }
16153
+ async function extractLocalOpencodeToken() {
16154
+ const file = opencodeCredentialsPath();
16155
+ if (!fs30.existsSync(file)) return null;
16156
+ const credential = fs30.readFileSync(file, "utf8").trim();
16157
+ if (credential.length === 0) return null;
16158
+ return { method: "oauth", credential, source: "flat-file" };
16159
+ }
16160
+ function opencodeCredentialsPaths() {
16161
+ return [opencodeCredentialsPath()];
16162
+ }
16163
+
16164
+ // src/agents/opencode/runtime.ts
16165
+ var OpencodeRuntimeStrategy = class {
16166
+ id = "opencode";
16167
+ meta = getAgent("opencode");
16168
+ mode = "interactive";
16169
+ os;
16170
+ constructor(os60) {
16171
+ this.os = os60;
16172
+ }
16173
+ async prepareLaunch() {
16174
+ const binary = this.os.findInPath("opencode");
16175
+ if (!binary) {
16176
+ throw new Error(
16177
+ "opencode is not on PATH. Install it with:\n curl -fsSL https://opencode.ai/install | bash\n Then run `codeam pair` again."
16178
+ );
16179
+ }
16180
+ const launch = this.os.buildLaunch(binary, []);
16181
+ return { cmd: launch.cmd, args: launch.args };
16182
+ }
16183
+ resumeLaunchArgs(_sessionId, _opts) {
16184
+ return [];
16185
+ }
16186
+ resolveHistoryDir(_cwd) {
16187
+ return null;
16188
+ }
16189
+ parseHistoryFile(_filePath) {
16190
+ return [];
16191
+ }
16192
+ getCurrentUsage(_historyDir) {
16193
+ return null;
16194
+ }
16195
+ async fetchWeeklyUsage() {
16196
+ return null;
16197
+ }
16198
+ async listModels() {
16199
+ return [{ id: "default", label: "Provider default", contextWindow: 2e5 }];
16200
+ }
16201
+ changeModelInstruction(modelId) {
16202
+ return { type: "pty", ptyInput: `/model ${modelId}\r` };
16203
+ }
16204
+ summarizeInstruction(_mode) {
16205
+ return { ptyInput: "/compact\r" };
16206
+ }
16207
+ filterTuiOutput(lines) {
16208
+ return lines;
16209
+ }
16210
+ detectInteractivePrompt(_lines) {
16211
+ return null;
16212
+ }
16213
+ /**
16214
+ * Headless single-prompt invocation — powers `request_ai_summary` /
16215
+ * `request_ai_insight` (Files review) AND Preview detection, same as
16216
+ * claude/codex/gemini/kimi. opencode's non-interactive mode is
16217
+ * `opencode run "<prompt>"`: it runs the prompt to completion and prints the
16218
+ * assistant reply to stdout (auth from ~/.local/share/opencode/auth.json).
16219
+ * Returns `null` on spawn failure / timeout / empty output so callers skip
16220
+ * silently instead of bubbling a partial reply.
16221
+ */
16222
+ async generateOneShot(prompt, opts) {
16223
+ const binary = this.os.findInPath("opencode");
16224
+ if (!binary) return null;
16225
+ const launch = this.os.buildLaunch(binary, ["run", prompt]);
16226
+ return spawnAndCapture(launch.cmd, launch.args, {
16227
+ cwd: opts?.cwd,
16228
+ timeoutMs: opts?.timeoutMs
16229
+ });
16230
+ }
16231
+ credentialLocator() {
16232
+ return {
16233
+ publicId: "opencode",
16234
+ vendor: "opencode",
16235
+ hint: "~/.local/share/opencode/auth.json",
16236
+ watchPaths: opencodeCredentialsPaths,
16237
+ extract: extractLocalOpencodeToken,
16238
+ validate: validateNonEmptyCredential
16239
+ };
16240
+ }
16241
+ loginLauncher() {
16242
+ return {
16243
+ async ensureInstalled() {
16244
+ return createOsStrategy().findInPath("opencode") !== null;
16245
+ },
16246
+ launch() {
16247
+ return (0, import_node_child_process14.spawn)("opencode", ["auth", "login"], { stdio: "inherit" });
16248
+ }
16249
+ };
16250
+ }
16251
+ };
16252
+
16122
16253
  // src/agents/registry.ts
16123
16254
  var runtimeBuilders = {
16124
- claude: (os59) => new ClaudeRuntimeStrategy(os59),
16125
- codex: (os59) => new CodexRuntimeStrategy(os59),
16126
- coderabbit: (os59) => new CoderabbitRuntimeStrategy(os59),
16127
- cursor: (os59) => new CursorRuntimeStrategy(os59),
16128
- aider: (os59) => new AiderRuntimeStrategy(os59),
16129
- gemini: (os59) => new GeminiRuntimeStrategy(os59),
16130
- kimi: (os59) => new KimiRuntimeStrategy(os59)
16255
+ claude: (os60) => new ClaudeRuntimeStrategy(os60),
16256
+ codex: (os60) => new CodexRuntimeStrategy(os60),
16257
+ coderabbit: (os60) => new CoderabbitRuntimeStrategy(os60),
16258
+ cursor: (os60) => new CursorRuntimeStrategy(os60),
16259
+ aider: (os60) => new AiderRuntimeStrategy(os60),
16260
+ gemini: (os60) => new GeminiRuntimeStrategy(os60),
16261
+ kimi: (os60) => new KimiRuntimeStrategy(os60),
16262
+ opencode: (os60) => new OpencodeRuntimeStrategy(os60)
16131
16263
  };
16132
16264
  var deployBuilders = {
16133
16265
  claude: () => new ClaudeDeployStrategy(),
16134
16266
  codex: () => new CodexDeployStrategy()
16135
16267
  };
16136
- function createAgentStrategy(agent, os59 = createOsStrategy()) {
16268
+ function createAgentStrategy(agent, os60 = createOsStrategy()) {
16137
16269
  if (!AGENT_REGISTRY[agent]?.enabled) {
16138
16270
  throw new Error(
16139
16271
  `Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
@@ -16143,10 +16275,10 @@ function createAgentStrategy(agent, os59 = createOsStrategy()) {
16143
16275
  if (!build) {
16144
16276
  throw new Error(`No runtime strategy registered for agent "${agent}"`);
16145
16277
  }
16146
- return build(os59);
16278
+ return build(os60);
16147
16279
  }
16148
- function createInteractiveAgentStrategy(agent, os59 = createOsStrategy()) {
16149
- const s = createAgentStrategy(agent, os59);
16280
+ function createInteractiveAgentStrategy(agent, os60 = createOsStrategy()) {
16281
+ const s = createAgentStrategy(agent, os60);
16150
16282
  if (s.mode !== "interactive") {
16151
16283
  throw new Error(
16152
16284
  `Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
@@ -16202,7 +16334,7 @@ function parseLinkArgs(args2) {
16202
16334
  if (apiKeyFileArg) {
16203
16335
  const filePath = apiKeyFileArg.slice("--api-key-file=".length);
16204
16336
  try {
16205
- apiKey = fs30.readFileSync(path34.resolve(filePath), "utf8").trim();
16337
+ apiKey = fs31.readFileSync(path35.resolve(filePath), "utf8").trim();
16206
16338
  } catch (err) {
16207
16339
  throw new Error(`Could not read --api-key-file ${filePath}: ${err.message}`);
16208
16340
  }
@@ -16329,7 +16461,7 @@ async function link(args2 = []) {
16329
16461
  return;
16330
16462
  }
16331
16463
  if (parsed.tokenFile) {
16332
- const credential = fs30.readFileSync(path34.resolve(parsed.tokenFile), "utf8").trim();
16464
+ const credential = fs31.readFileSync(path35.resolve(parsed.tokenFile), "utf8").trim();
16333
16465
  if (!credential) {
16334
16466
  showError(`--token-file ${parsed.tokenFile} is empty.`);
16335
16467
  process.exit(1);
@@ -16546,16 +16678,16 @@ async function linkDryRunPreflight(ctx) {
16546
16678
  }
16547
16679
 
16548
16680
  // src/agents/coderabbit/configure.ts
16549
- var import_node_child_process15 = require("child_process");
16681
+ var import_node_child_process16 = require("child_process");
16550
16682
  var import_node_os4 = require("os");
16551
16683
  var import_node_fs5 = require("fs");
16552
- var path36 = __toESM(require("path"));
16684
+ var path37 = __toESM(require("path"));
16553
16685
 
16554
16686
  // src/agents/coderabbit/oauth.ts
16555
- var import_node_child_process14 = require("child_process");
16556
- var fs31 = __toESM(require("fs"));
16557
- var os27 = __toESM(require("os"));
16558
- var path35 = __toESM(require("path"));
16687
+ var import_node_child_process15 = require("child_process");
16688
+ var fs32 = __toESM(require("fs"));
16689
+ var os28 = __toESM(require("os"));
16690
+ var path36 = __toESM(require("path"));
16559
16691
  function parseCoderabbitAuthEvent(line) {
16560
16692
  const l = line.replace(/\x1b\[[0-9;?]*[A-Za-z]/g, "").trim();
16561
16693
  if (!l || l[0] !== "{") return null;
@@ -16594,7 +16726,7 @@ function parseCoderabbitAuthEvent(line) {
16594
16726
  function resolvePython() {
16595
16727
  for (const bin of ["python3", "python"]) {
16596
16728
  try {
16597
- const r = (0, import_node_child_process14.spawnSync)(bin, ["--version"], { stdio: "ignore", timeout: 4e3 });
16729
+ const r = (0, import_node_child_process15.spawnSync)(bin, ["--version"], { stdio: "ignore", timeout: 4e3 });
16598
16730
  if (!r.error && r.status === 0) return bin;
16599
16731
  } catch {
16600
16732
  }
@@ -16604,15 +16736,15 @@ function resolvePython() {
16604
16736
  function spawnCoderabbitLoginProc(cmd, args2) {
16605
16737
  const python = resolvePython();
16606
16738
  if (python) {
16607
- const helper = path35.join(os27.tmpdir(), "codeam-cr-pty.py");
16608
- fs31.writeFileSync(helper, PYTHON_PTY_HELPER, { mode: 420 });
16609
- return (0, import_node_child_process14.spawn)(python, [helper, cmd, ...args2], {
16739
+ const helper = path36.join(os28.tmpdir(), "codeam-cr-pty.py");
16740
+ fs32.writeFileSync(helper, PYTHON_PTY_HELPER, { mode: 420 });
16741
+ return (0, import_node_child_process15.spawn)(python, [helper, cmd, ...args2], {
16610
16742
  stdio: ["pipe", "pipe", "pipe"],
16611
16743
  env: { ...process.env, TERM: "xterm-256color", COLUMNS: "220", LINES: "50" },
16612
16744
  shell: false
16613
16745
  });
16614
16746
  }
16615
- return (0, import_node_child_process14.spawn)(cmd, args2, { stdio: ["pipe", "pipe", "pipe"], shell: false });
16747
+ return (0, import_node_child_process15.spawn)(cmd, args2, { stdio: ["pipe", "pipe", "pipe"], shell: false });
16616
16748
  }
16617
16749
  var pendingCoderabbitLogin = null;
16618
16750
  function setPendingCoderabbitLogin(handle) {
@@ -16716,7 +16848,7 @@ function runCoderabbitOAuthLogin(deps) {
16716
16848
  });
16717
16849
  }
16718
16850
  function coderabbitDir(home) {
16719
- return path35.join(home ?? os27.homedir(), ".coderabbit");
16851
+ return path36.join(home ?? os28.homedir(), ".coderabbit");
16720
16852
  }
16721
16853
  var NON_CREDENTIAL = /* @__PURE__ */ new Set(["doctor.json", "machine-id"]);
16722
16854
  function snapshotCredentialDir(home) {
@@ -16724,14 +16856,14 @@ function snapshotCredentialDir(home) {
16724
16856
  const snap = {};
16725
16857
  let entries;
16726
16858
  try {
16727
- entries = fs31.readdirSync(dir, { withFileTypes: true });
16859
+ entries = fs32.readdirSync(dir, { withFileTypes: true });
16728
16860
  } catch {
16729
16861
  return snap;
16730
16862
  }
16731
16863
  for (const e of entries) {
16732
16864
  if (!e.isFile() || NON_CREDENTIAL.has(e.name)) continue;
16733
16865
  try {
16734
- const st3 = fs31.statSync(path35.join(dir, e.name));
16866
+ const st3 = fs32.statSync(path36.join(dir, e.name));
16735
16867
  snap[e.name] = `${st3.mtimeMs}:${st3.size}`;
16736
16868
  } catch {
16737
16869
  }
@@ -16749,7 +16881,7 @@ function diffCapturedCredential(before, home) {
16749
16881
  }
16750
16882
  if (!best) return null;
16751
16883
  try {
16752
- return { file: best.file, contents: fs31.readFileSync(path35.join(dir, best.file), "utf8") };
16884
+ return { file: best.file, contents: fs32.readFileSync(path36.join(dir, best.file), "utf8") };
16753
16885
  } catch {
16754
16886
  return null;
16755
16887
  }
@@ -16757,7 +16889,7 @@ function diffCapturedCredential(before, home) {
16757
16889
 
16758
16890
  // src/agents/coderabbit/configure.ts
16759
16891
  function defaultIsLoggedIn() {
16760
- const r = (0, import_node_child_process15.spawnSync)("coderabbit", ["auth", "status", "--agent"], {
16892
+ const r = (0, import_node_child_process16.spawnSync)("coderabbit", ["auth", "status", "--agent"], {
16761
16893
  encoding: "utf8",
16762
16894
  timeout: 15e3
16763
16895
  });
@@ -16775,7 +16907,7 @@ function defaultIsLoggedIn() {
16775
16907
  return false;
16776
16908
  }
16777
16909
  function defaultLoginWithApiKey(key) {
16778
- const r = (0, import_node_child_process15.spawnSync)("coderabbit", ["auth", "login", "--api-key", key], {
16910
+ const r = (0, import_node_child_process16.spawnSync)("coderabbit", ["auth", "login", "--api-key", key], {
16779
16911
  encoding: "utf8",
16780
16912
  timeout: 3e4
16781
16913
  });
@@ -16789,7 +16921,7 @@ function defaultLoginWithApiKey(key) {
16789
16921
  function collectChangedFiles(cwd) {
16790
16922
  const run = (args2) => {
16791
16923
  try {
16792
- const r = (0, import_node_child_process15.spawnSync)("git", args2, { cwd, encoding: "utf8", timeout: 1e4 });
16924
+ const r = (0, import_node_child_process16.spawnSync)("git", args2, { cwd, encoding: "utf8", timeout: 1e4 });
16793
16925
  return r.status === 0 && typeof r.stdout === "string" ? r.stdout : "";
16794
16926
  } catch {
16795
16927
  return "";
@@ -16826,7 +16958,7 @@ function collectChangedFiles(cwd) {
16826
16958
  return [...byPath.values()];
16827
16959
  }
16828
16960
  function restoreCoderabbitOauthBlob(value) {
16829
- const dir = path36.join((0, import_node_os4.homedir)(), ".coderabbit");
16961
+ const dir = path37.join((0, import_node_os4.homedir)(), ".coderabbit");
16830
16962
  (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
16831
16963
  let file = "auth.json";
16832
16964
  let contents = value.trim();
@@ -16834,35 +16966,35 @@ function restoreCoderabbitOauthBlob(value) {
16834
16966
  try {
16835
16967
  const parsed = JSON.parse(contents);
16836
16968
  if (typeof parsed.file === "string" && typeof parsed.contents === "string") {
16837
- file = path36.basename(parsed.file);
16969
+ file = path37.basename(parsed.file);
16838
16970
  contents = parsed.contents;
16839
16971
  }
16840
16972
  } catch {
16841
16973
  }
16842
16974
  }
16843
- (0, import_node_fs5.writeFileSync)(path36.join(dir, file), contents, { mode: 384 });
16975
+ (0, import_node_fs5.writeFileSync)(path37.join(dir, file), contents, { mode: 384 });
16844
16976
  }
16845
16977
  async function configureCoderabbit(input, deps = {}) {
16846
- const os59 = deps.os ?? createOsStrategy();
16978
+ const os60 = deps.os ?? createOsStrategy();
16847
16979
  const ensureInstalled = deps.ensureInstalled ?? ensureCoderabbitInstalled;
16848
16980
  const isLoggedIn = deps.isLoggedIn ?? defaultIsLoggedIn;
16849
16981
  const runOAuth = deps.runOAuthLogin ?? runCoderabbitOAuthLogin;
16850
16982
  const snapshot = deps.snapshotDir ?? (() => snapshotCredentialDir());
16851
16983
  const capture2 = deps.captureCredential ?? ((b) => diffCapturedCredential(b));
16852
16984
  const loginWithApiKey = deps.loginWithApiKey ?? defaultLoginWithApiKey;
16853
- const home = os59.homeDir();
16854
- os59.augmentPath(
16855
- os59.id === "win32" ? [
16856
- path36.join(home, ".local", "bin"),
16857
- path36.join(process.env.APPDATA ?? path36.join(home, "AppData", "Roaming"), "npm"),
16858
- path36.join(home, "scoop", "shims")
16859
- ] : [path36.join(home, ".local", "bin"), "/opt/homebrew/bin", "/usr/local/bin"]
16985
+ const home = os60.homeDir();
16986
+ os60.augmentPath(
16987
+ os60.id === "win32" ? [
16988
+ path37.join(home, ".local", "bin"),
16989
+ path37.join(process.env.APPDATA ?? path37.join(home, "AppData", "Roaming"), "npm"),
16990
+ path37.join(home, "scoop", "shims")
16991
+ ] : [path37.join(home, ".local", "bin"), "/opt/homebrew/bin", "/usr/local/bin"]
16860
16992
  );
16861
- const installed2 = os59.findInPath("coderabbit") !== null;
16993
+ const installed2 = os60.findInPath("coderabbit") !== null;
16862
16994
  const base = () => ({
16863
16995
  action: input.action,
16864
16996
  supported: true,
16865
- installed: os59.findInPath("coderabbit") !== null,
16997
+ installed: os60.findInPath("coderabbit") !== null,
16866
16998
  loggedIn: false
16867
16999
  });
16868
17000
  if (input.action === "status") {
@@ -16876,7 +17008,7 @@ async function configureCoderabbit(input, deps = {}) {
16876
17008
  const key = (input.apiKey ?? "").trim();
16877
17009
  if (!key) return { ...res2, error: "No API key provided" };
16878
17010
  if (!res2.installed) {
16879
- const ok = await ensureInstalled(os59);
17011
+ const ok = await ensureInstalled(os60);
16880
17012
  res2.installed = ok;
16881
17013
  if (!ok) return { ...res2, error: "CodeRabbit CLI could not be installed" };
16882
17014
  }
@@ -16900,7 +17032,7 @@ async function configureCoderabbit(input, deps = {}) {
16900
17032
  }
16901
17033
  if (!res2.installed) {
16902
17034
  deps.onEvent?.({ kind: "installing" });
16903
- const ok = await ensureInstalled(os59);
17035
+ const ok = await ensureInstalled(os60);
16904
17036
  res2.installed = ok;
16905
17037
  if (!ok) return { ...res2, error: "CodeRabbit CLI could not be installed" };
16906
17038
  }
@@ -16930,7 +17062,7 @@ async function configureCoderabbit(input, deps = {}) {
16930
17062
  const res2 = base();
16931
17063
  if (!installed2) {
16932
17064
  deps.onEvent?.({ kind: "installing" });
16933
- const ok = await ensureInstalled(os59);
17065
+ const ok = await ensureInstalled(os60);
16934
17066
  res2.installed = ok;
16935
17067
  if (!ok) return { ...res2, error: "CodeRabbit CLI could not be installed" };
16936
17068
  }
@@ -16970,7 +17102,7 @@ async function configureCoderabbit(input, deps = {}) {
16970
17102
  }
16971
17103
  const res = base();
16972
17104
  if (!res.installed) {
16973
- const ok = await ensureInstalled(os59);
17105
+ const ok = await ensureInstalled(os60);
16974
17106
  res.installed = ok;
16975
17107
  if (!ok) return { ...res, error: "CodeRabbit CLI is not installed" };
16976
17108
  }
@@ -16998,7 +17130,7 @@ async function configureCoderabbit(input, deps = {}) {
16998
17130
  }
16999
17131
 
17000
17132
  // src/agents/coderabbit/review-pr.ts
17001
- var import_node_child_process16 = require("child_process");
17133
+ var import_node_child_process17 = require("child_process");
17002
17134
  function repoSlug(prRef) {
17003
17135
  return `${prRef.owner}/${prRef.repo}`;
17004
17136
  }
@@ -17132,7 +17264,7 @@ function defaultRunGh(args2) {
17132
17264
  const stderr = [];
17133
17265
  let proc;
17134
17266
  try {
17135
- proc = (0, import_node_child_process16.spawn)("gh", args2, { stdio: ["ignore", "pipe", "pipe"] });
17267
+ proc = (0, import_node_child_process17.spawn)("gh", args2, { stdio: ["ignore", "pipe", "pipe"] });
17136
17268
  } catch (err) {
17137
17269
  resolve8({ code: -1, stdout: "", stderr: err instanceof Error ? err.message : String(err) });
17138
17270
  return;
@@ -17153,10 +17285,10 @@ function defaultRunGh(args2) {
17153
17285
  }
17154
17286
 
17155
17287
  // src/commands/host-agent.ts
17156
- var import_node_child_process24 = require("child_process");
17157
- var os38 = __toESM(require("os"));
17158
- var fs43 = __toESM(require("fs"));
17159
- var path46 = __toESM(require("path"));
17288
+ var import_node_child_process25 = require("child_process");
17289
+ var os39 = __toESM(require("os"));
17290
+ var fs44 = __toESM(require("fs"));
17291
+ var path47 = __toESM(require("path"));
17160
17292
 
17161
17293
  // src/integrations/manifest.ts
17162
17294
  var import_node_fs7 = __toESM(require("fs"));
@@ -17166,7 +17298,7 @@ var import_node_path5 = __toESM(require("path"));
17166
17298
  // src/lib/restrict-to-owner.ts
17167
17299
  var import_node_fs6 = __toESM(require("fs"));
17168
17300
  var import_node_os5 = __toESM(require("os"));
17169
- var import_node_child_process17 = require("child_process");
17301
+ var import_node_child_process18 = require("child_process");
17170
17302
  var BROAD_WINDOWS_SIDS = [
17171
17303
  "*S-1-1-0",
17172
17304
  "*S-1-5-11",
@@ -17178,7 +17310,7 @@ function restrictToOwner(filePath) {
17178
17310
  try {
17179
17311
  if (process.platform === "win32") {
17180
17312
  const username = import_node_os5.default.userInfo().username;
17181
- (0, import_node_child_process17.execFileSync)(
17313
+ (0, import_node_child_process18.execFileSync)(
17182
17314
  "icacls",
17183
17315
  [
17184
17316
  filePath,
@@ -17302,14 +17434,14 @@ function describeReason(reason) {
17302
17434
  }
17303
17435
 
17304
17436
  // src/commands/host/host-client.ts
17305
- var fs35 = __toESM(require("fs"));
17306
- var os31 = __toESM(require("os"));
17307
- var path39 = __toESM(require("path"));
17437
+ var fs36 = __toESM(require("fs"));
17438
+ var os32 = __toESM(require("os"));
17439
+ var path40 = __toESM(require("path"));
17308
17440
  var import_node_crypto9 = require("crypto");
17309
17441
  function sampleCpuTimes() {
17310
17442
  let idle = 0;
17311
17443
  let total = 0;
17312
- for (const cpu of os31.cpus()) {
17444
+ for (const cpu of os32.cpus()) {
17313
17445
  const t2 = cpu.times;
17314
17446
  idle += t2.idle;
17315
17447
  total += t2.user + t2.nice + t2.sys + t2.idle + t2.irq;
@@ -17328,8 +17460,8 @@ var MetricsCollector = class {
17328
17460
  const prev = this.prevCpu;
17329
17461
  this.prevCpu = current;
17330
17462
  if (!prev) {
17331
- const cores = os31.cpus().length || 1;
17332
- const proxy = os31.loadavg()[0] / cores * 100;
17463
+ const cores = os32.cpus().length || 1;
17464
+ const proxy = os32.loadavg()[0] / cores * 100;
17333
17465
  return Math.min(100, Math.max(0, Math.round(proxy)));
17334
17466
  }
17335
17467
  const idleDelta = current.idle - prev.idle;
@@ -17342,8 +17474,8 @@ var MetricsCollector = class {
17342
17474
  collect() {
17343
17475
  return {
17344
17476
  cpuPct: this.cpuPct(),
17345
- ramUsedMb: Math.round((os31.totalmem() - os31.freemem()) / 1048576),
17346
- ramTotalMb: Math.round(os31.totalmem() / 1048576),
17477
+ ramUsedMb: Math.round((os32.totalmem() - os32.freemem()) / 1048576),
17478
+ ramTotalMb: Math.round(os32.totalmem() / 1048576),
17347
17479
  latencyMs: this.lastLatencyMs
17348
17480
  };
17349
17481
  }
@@ -17352,19 +17484,19 @@ function apiBase() {
17352
17484
  return process.env.CODEAM_API_URL ?? resolveApiBaseUrl();
17353
17485
  }
17354
17486
  function hostIdentityPath() {
17355
- return path39.join(os31.homedir(), ".codeam", "host-agent.json");
17487
+ return path40.join(os32.homedir(), ".codeam", "host-agent.json");
17356
17488
  }
17357
17489
  function collectOsInfo() {
17358
17490
  return {
17359
- distro: os31.platform(),
17360
- arch: os31.arch(),
17361
- kernel: os31.release(),
17491
+ distro: os32.platform(),
17492
+ arch: os32.arch(),
17493
+ kernel: os32.release(),
17362
17494
  nodeVersion: process.versions.node
17363
17495
  };
17364
17496
  }
17365
17497
  function loadHostIdentity() {
17366
17498
  try {
17367
- const raw = fs35.readFileSync(hostIdentityPath(), "utf8");
17499
+ const raw = fs36.readFileSync(hostIdentityPath(), "utf8");
17368
17500
  const parsed = JSON.parse(raw);
17369
17501
  if (typeof parsed === "object" && parsed !== null && typeof parsed.hostId === "string" && typeof parsed.hostToken === "string" && typeof parsed.controlPluginId === "string") {
17370
17502
  const p2 = parsed;
@@ -17383,8 +17515,8 @@ function loadHostIdentity() {
17383
17515
  }
17384
17516
  function saveHostIdentity(identity) {
17385
17517
  const file = hostIdentityPath();
17386
- fs35.mkdirSync(path39.dirname(file), { recursive: true, mode: 448 });
17387
- fs35.writeFileSync(file, JSON.stringify(identity, null, 2), {
17518
+ fs36.mkdirSync(path40.dirname(file), { recursive: true, mode: 448 });
17519
+ fs36.writeFileSync(file, JSON.stringify(identity, null, 2), {
17388
17520
  encoding: "utf8",
17389
17521
  mode: 384
17390
17522
  });
@@ -17429,7 +17561,7 @@ function isTerminalEnrollError(err) {
17429
17561
  }
17430
17562
  function deleteHostIdentity() {
17431
17563
  try {
17432
- fs35.rmSync(hostIdentityPath(), { force: true });
17564
+ fs36.rmSync(hostIdentityPath(), { force: true });
17433
17565
  } catch {
17434
17566
  }
17435
17567
  }
@@ -17453,7 +17585,7 @@ async function postJson(pathname, body) {
17453
17585
  function resolveHostLabel(label) {
17454
17586
  const explicit = label?.trim();
17455
17587
  const envLabel = process.env.CODEAM_HOST_LABEL?.trim();
17456
- const resolved = explicit || envLabel || os31.hostname();
17588
+ const resolved = explicit || envLabel || os32.hostname();
17457
17589
  return resolved.slice(0, 80);
17458
17590
  }
17459
17591
  async function redeemEnrollToken(token, label) {
@@ -17564,17 +17696,17 @@ async function reportDeployProgress(auth, deployId, step, message, sessionId) {
17564
17696
  }
17565
17697
 
17566
17698
  // src/commands/host/workspace.ts
17567
- var fs36 = __toESM(require("fs"));
17568
- var os32 = __toESM(require("os"));
17569
- var path40 = __toESM(require("path"));
17570
- var import_node_child_process18 = require("child_process");
17699
+ var fs37 = __toESM(require("fs"));
17700
+ var os33 = __toESM(require("os"));
17701
+ var path41 = __toESM(require("path"));
17702
+ var import_node_child_process19 = require("child_process");
17571
17703
  var import_node_util4 = require("util");
17572
- var execFileP4 = (0, import_node_util4.promisify)(import_node_child_process18.execFile);
17704
+ var execFileP4 = (0, import_node_util4.promisify)(import_node_child_process19.execFile);
17573
17705
  function isAbsolutePathTarget(target) {
17574
- return path40.isAbsolute(target);
17706
+ return path41.isAbsolute(target);
17575
17707
  }
17576
17708
  function selfHostedWorkspaceRoot() {
17577
- return path40.join(os32.homedir(), ".codeam", "self-hosted");
17709
+ return path41.join(os33.homedir(), ".codeam", "self-hosted");
17578
17710
  }
17579
17711
  function nonInteractiveGitEnv() {
17580
17712
  return {
@@ -17644,15 +17776,15 @@ async function configureGitCredentials(dest, repoRef, cloneToken, provider = "gi
17644
17776
  const isGitlab = provider === "gitlab";
17645
17777
  if (isGitlab ? !gitlabProjectPath(repoRef.trim()) : !githubOwnerRepo(repoRef.trim())) return;
17646
17778
  if (!cloneToken) return;
17647
- const credFile = path40.join(dest, ".git", "codeam-credentials");
17779
+ const credFile = path41.join(dest, ".git", "codeam-credentials");
17648
17780
  const credLine = isGitlab ? `https://oauth2:${cloneToken}@gitlab.com
17649
17781
  ` : `https://x-access-token:${cloneToken}@github.com
17650
17782
  `;
17651
- fs36.writeFileSync(credFile, credLine, { mode: 384 });
17783
+ fs37.writeFileSync(credFile, credLine, { mode: 384 });
17652
17784
  restrictToOwner(credFile);
17653
17785
  const env = nonInteractiveGitEnv();
17654
17786
  const git2 = (args2) => execFileP4("git", ["-C", dest, ...args2], { timeout: 3e4, env });
17655
- const credFilePosix = credFile.split(path40.sep).join("/");
17787
+ const credFilePosix = credFile.split(path41.sep).join("/");
17656
17788
  await git2(["config", "--local", "--replace-all", "credential.helper", ""]).catch(() => {
17657
17789
  });
17658
17790
  await git2([
@@ -17685,17 +17817,17 @@ function maskToken(text, cloneToken) {
17685
17817
  }
17686
17818
  async function prepareWorkspace(repoOrPath, deployId, cloneToken, provider = "github", branch) {
17687
17819
  if (isAbsolutePathTarget(repoOrPath)) {
17688
- if (!fs36.existsSync(repoOrPath)) {
17820
+ if (!fs37.existsSync(repoOrPath)) {
17689
17821
  throw new Error(`deploy target path does not exist: ${repoOrPath}`);
17690
17822
  }
17691
17823
  return repoOrPath;
17692
17824
  }
17693
- const dest = path40.join(selfHostedWorkspaceRoot(), deployId);
17694
- if (fs36.existsSync(path40.join(dest, ".git"))) {
17825
+ const dest = path41.join(selfHostedWorkspaceRoot(), deployId);
17826
+ if (fs37.existsSync(path41.join(dest, ".git"))) {
17695
17827
  if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken, provider);
17696
17828
  return dest;
17697
17829
  }
17698
- fs36.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
17830
+ fs37.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
17699
17831
  const cloneUrl = repoCloneUrl(repoOrPath, cloneToken, provider);
17700
17832
  const cloneArgs = branch ? ["clone", "--depth", "1", "--branch", branch, cloneUrl, dest] : ["clone", "--depth", "1", cloneUrl, dest];
17701
17833
  try {
@@ -17713,9 +17845,9 @@ async function prepareWorkspace(repoOrPath, deployId, cloneToken, provider = "gi
17713
17845
  }
17714
17846
 
17715
17847
  // src/commands/host/agent-provisioning.ts
17716
- var fs37 = __toESM(require("fs"));
17717
- var os33 = __toESM(require("os"));
17718
- var path41 = __toESM(require("path"));
17848
+ var fs38 = __toESM(require("fs"));
17849
+ var os34 = __toESM(require("os"));
17850
+ var path42 = __toESM(require("path"));
17719
17851
  var PUBLIC_TO_INTERNAL_AGENT = {
17720
17852
  claude_code: "claude",
17721
17853
  claude: "claude",
@@ -17725,28 +17857,29 @@ var PUBLIC_TO_INTERNAL_AGENT = {
17725
17857
  aider: "aider",
17726
17858
  coderabbit: "coderabbit",
17727
17859
  gemini: "gemini",
17728
- kimi: "kimi"
17860
+ kimi: "kimi",
17861
+ opencode: "opencode"
17729
17862
  };
17730
17863
  function toInternalAgentId(publicAgentId) {
17731
17864
  return PUBLIC_TO_INTERNAL_AGENT[publicAgentId] ?? null;
17732
17865
  }
17733
17866
  function ensureDir(dir) {
17734
- fs37.mkdirSync(dir, { recursive: true, mode: 448 });
17867
+ fs38.mkdirSync(dir, { recursive: true, mode: 448 });
17735
17868
  }
17736
17869
  function writeFile0600(filePath, contents) {
17737
- ensureDir(path41.dirname(filePath));
17738
- fs37.writeFileSync(filePath, contents, { encoding: "utf8", mode: 384 });
17870
+ ensureDir(path42.dirname(filePath));
17871
+ fs38.writeFileSync(filePath, contents, { encoding: "utf8", mode: 384 });
17739
17872
  restrictToOwner(filePath);
17740
17873
  }
17741
17874
  function rmIfExists(filePath) {
17742
17875
  try {
17743
- fs37.rmSync(filePath, { force: true });
17876
+ fs38.rmSync(filePath, { force: true });
17744
17877
  } catch {
17745
17878
  }
17746
17879
  }
17747
17880
  var claudeProvisioner = {
17748
17881
  write(auth, home) {
17749
- const credentialsJson = path41.join(home, ".claude", ".credentials.json");
17882
+ const credentialsJson = path42.join(home, ".claude", ".credentials.json");
17750
17883
  if (auth.kind === "api_key") {
17751
17884
  rmIfExists(credentialsJson);
17752
17885
  return { ANTHROPIC_API_KEY: auth.value };
@@ -17758,8 +17891,8 @@ var claudeProvisioner = {
17758
17891
  } else {
17759
17892
  rmIfExists(credentialsJson);
17760
17893
  }
17761
- const claudeJson = path41.join(home, ".claude.json");
17762
- if (!fs37.existsSync(claudeJson)) {
17894
+ const claudeJson = path42.join(home, ".claude.json");
17895
+ if (!fs38.existsSync(claudeJson)) {
17763
17896
  writeFile0600(
17764
17897
  claudeJson,
17765
17898
  JSON.stringify({ hasCompletedOnboarding: true, customApiKeyResponses: { approved: [] } })
@@ -17770,7 +17903,7 @@ var claudeProvisioner = {
17770
17903
  };
17771
17904
  var codexProvisioner = {
17772
17905
  write(auth, home) {
17773
- const authJson = path41.join(home, ".codex", "auth.json");
17906
+ const authJson = path42.join(home, ".codex", "auth.json");
17774
17907
  if (auth.kind === "api_key") {
17775
17908
  rmIfExists(authJson);
17776
17909
  return { OPENAI_API_KEY: auth.value };
@@ -17781,8 +17914,8 @@ var codexProvisioner = {
17781
17914
  };
17782
17915
  var geminiProvisioner = {
17783
17916
  write(auth, home) {
17784
- const settingsJson = path41.join(home, ".gemini", "settings.json");
17785
- const oauthCreds = path41.join(home, ".gemini", "oauth_creds.json");
17917
+ const settingsJson = path42.join(home, ".gemini", "settings.json");
17918
+ const oauthCreds = path42.join(home, ".gemini", "oauth_creds.json");
17786
17919
  if (auth.kind === "api_key") {
17787
17920
  rmIfExists(oauthCreds);
17788
17921
  writeFile0600(settingsJson, '{"security":{"auth":{"selectedType":"gemini-api-key"}}}');
@@ -17795,7 +17928,7 @@ var geminiProvisioner = {
17795
17928
  };
17796
17929
  var cursorProvisioner = {
17797
17930
  write(auth, home) {
17798
- const authJson = path41.join(home, ".config", "cursor", "auth.json");
17931
+ const authJson = path42.join(home, ".config", "cursor", "auth.json");
17799
17932
  if (auth.kind === "api_key") {
17800
17933
  rmIfExists(authJson);
17801
17934
  return { CURSOR_API_KEY: auth.value };
@@ -17837,22 +17970,22 @@ max_context_size = 262144
17837
17970
  var kimiProvisioner = {
17838
17971
  write(auth, home) {
17839
17972
  const credentialsFiles = [
17840
- path41.join(home, ".kimi", "credentials", "kimi-code.json"),
17841
- path41.join(home, ".kimi-code", "credentials", "kimi-code.json")
17973
+ path42.join(home, ".kimi", "credentials", "kimi-code.json"),
17974
+ path42.join(home, ".kimi-code", "credentials", "kimi-code.json")
17842
17975
  ];
17843
17976
  if (auth.kind === "api_key") {
17844
17977
  credentialsFiles.forEach(rmIfExists);
17845
17978
  return { KIMI_API_KEY: auth.value };
17846
17979
  }
17847
17980
  credentialsFiles.forEach((f) => writeFile0600(f, auth.value));
17848
- writeFile0600(path41.join(home, ".kimi-code", "config.toml"), KIMI_MANAGED_CONFIG_TOML);
17981
+ writeFile0600(path42.join(home, ".kimi-code", "config.toml"), KIMI_MANAGED_CONFIG_TOML);
17849
17982
  return {};
17850
17983
  }
17851
17984
  };
17852
17985
  var coderabbitProvisioner = {
17853
17986
  write(auth, home) {
17854
- const dir = path41.join(home, ".coderabbit");
17855
- const authJson = path41.join(dir, "auth.json");
17987
+ const dir = path42.join(home, ".coderabbit");
17988
+ const authJson = path42.join(dir, "auth.json");
17856
17989
  if (auth.kind === "api_key") {
17857
17990
  rmIfExists(authJson);
17858
17991
  return { CODERABBIT_API_KEY: auth.value };
@@ -17864,13 +17997,20 @@ var coderabbitProvisioner = {
17864
17997
  try {
17865
17998
  const parsed = JSON.parse(value);
17866
17999
  if (typeof parsed.file === "string" && typeof parsed.contents === "string") {
17867
- file = path41.basename(parsed.file);
18000
+ file = path42.basename(parsed.file);
17868
18001
  contents = parsed.contents;
17869
18002
  }
17870
18003
  } catch {
17871
18004
  }
17872
18005
  }
17873
- writeFile0600(path41.join(dir, file), contents);
18006
+ writeFile0600(path42.join(dir, file), contents);
18007
+ return {};
18008
+ }
18009
+ };
18010
+ var opencodeProvisioner = {
18011
+ write(auth, home) {
18012
+ const authJson = path42.join(home, ".local", "share", "opencode", "auth.json");
18013
+ writeFile0600(authJson, auth.value);
17874
18014
  return {};
17875
18015
  }
17876
18016
  };
@@ -17880,7 +18020,8 @@ var PROVISIONERS = {
17880
18020
  codex: codexProvisioner,
17881
18021
  gemini: geminiProvisioner,
17882
18022
  cursor: cursorProvisioner,
17883
- coderabbit: coderabbitProvisioner
18023
+ coderabbit: coderabbitProvisioner,
18024
+ opencode: opencodeProvisioner
17884
18025
  };
17885
18026
  var UnsupportedAgentError = class extends Error {
17886
18027
  agentId;
@@ -17890,7 +18031,7 @@ var UnsupportedAgentError = class extends Error {
17890
18031
  this.agentId = agentId;
17891
18032
  }
17892
18033
  };
17893
- function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os33.homedir()) {
18034
+ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os34.homedir()) {
17894
18035
  const internal = toInternalAgentId(publicAgentId);
17895
18036
  if (!internal) throw new UnsupportedAgentError(publicAgentId);
17896
18037
  const provisioner = PROVISIONERS[internal];
@@ -17899,12 +18040,12 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os33.homedir(
17899
18040
  }
17900
18041
 
17901
18042
  // src/commands/host/git-tooling.ts
17902
- var import_node_child_process19 = require("child_process");
17903
- var fs38 = __toESM(require("fs"));
17904
- var os34 = __toESM(require("os"));
17905
- var path42 = __toESM(require("path"));
18043
+ var import_node_child_process20 = require("child_process");
18044
+ var fs39 = __toESM(require("fs"));
18045
+ var os35 = __toESM(require("os"));
18046
+ var path43 = __toESM(require("path"));
17906
18047
  function codeamBinDir() {
17907
- return process.env.CODEAM_BIN_DIR ?? path42.join(os34.homedir(), ".codeam", "bin");
18048
+ return process.env.CODEAM_BIN_DIR ?? path43.join(os35.homedir(), ".codeam", "bin");
17908
18049
  }
17909
18050
  var FALLBACK_GH_VERSION = "2.62.0";
17910
18051
  var RELEASE_API = "https://api.github.com/repos/cli/cli/releases/latest";
@@ -17936,7 +18077,7 @@ async function download(url2, dest) {
17936
18077
  const res = await fetch(url2, { headers: { "User-Agent": "codeam-cli" } });
17937
18078
  if (!res.ok || !res.body) return false;
17938
18079
  const buf = Buffer.from(await res.arrayBuffer());
17939
- fs38.writeFileSync(dest, buf);
18080
+ fs39.writeFileSync(dest, buf);
17940
18081
  return true;
17941
18082
  } catch {
17942
18083
  return false;
@@ -17959,8 +18100,8 @@ async function ensureGhCli(runner, token, deps = {}) {
17959
18100
  const version3 = await resolveVersionFn(token);
17960
18101
  const asset = `gh_${version3}_${osToken}_${arch2}`;
17961
18102
  const url2 = `https://github.com/cli/cli/releases/download/v${version3}/${asset}.${ext}`;
17962
- const tmpRoot = fs38.mkdtempSync(path42.join(os34.tmpdir(), "codeam-gh-"));
17963
- const archive = path42.join(tmpRoot, `${asset}.${ext}`);
18103
+ const tmpRoot = fs39.mkdtempSync(path43.join(os35.tmpdir(), "codeam-gh-"));
18104
+ const archive = path43.join(tmpRoot, `${asset}.${ext}`);
17964
18105
  if (!await downloadFn(url2, archive)) {
17965
18106
  log.warn("host-agent", "gh download failed \u2014 skipping (git pull/push still work via the credential helper)");
17966
18107
  return null;
@@ -17970,16 +18111,16 @@ async function ensureGhCli(runner, token, deps = {}) {
17970
18111
  log.warn("host-agent", `gh archive extraction failed (code=${String(extract.code)}) \u2014 skipping`);
17971
18112
  return null;
17972
18113
  }
17973
- const extractedBin = path42.join(tmpRoot, asset, "bin", binaryName);
17974
- if (!fs38.existsSync(extractedBin)) {
18114
+ const extractedBin = path43.join(tmpRoot, asset, "bin", binaryName);
18115
+ if (!fs39.existsSync(extractedBin)) {
17975
18116
  log.warn("host-agent", "gh binary not found in the extracted archive \u2014 skipping");
17976
18117
  return null;
17977
18118
  }
17978
18119
  const binDir = codeamBinDir();
17979
- fs38.mkdirSync(binDir, { recursive: true });
17980
- const target = path42.join(binDir, binaryName);
17981
- fs38.copyFileSync(extractedBin, target);
17982
- fs38.chmodSync(target, 493);
18120
+ fs39.mkdirSync(binDir, { recursive: true });
18121
+ const target = path43.join(binDir, binaryName);
18122
+ fs39.copyFileSync(extractedBin, target);
18123
+ fs39.chmodSync(target, 493);
17983
18124
  log.info("host-agent", `gh installed to ${target} (v${version3})`);
17984
18125
  return target;
17985
18126
  } catch (e) {
@@ -18039,8 +18180,8 @@ async function ensureGlabCli(runner, deps = {}) {
18039
18180
  const version3 = await resolveLatestGlabVersion();
18040
18181
  const asset = `glab_${version3}_${osToken}_${arch2}`;
18041
18182
  const url2 = `https://gitlab.com/gitlab-org/cli/-/releases/v${version3}/downloads/${asset}.${ext}`;
18042
- const tmpRoot = fs38.mkdtempSync(path42.join(os34.tmpdir(), "codeam-glab-"));
18043
- const archive = path42.join(tmpRoot, `${asset}.${ext}`);
18183
+ const tmpRoot = fs39.mkdtempSync(path43.join(os35.tmpdir(), "codeam-glab-"));
18184
+ const archive = path43.join(tmpRoot, `${asset}.${ext}`);
18044
18185
  if (!await downloadFn(url2, archive)) {
18045
18186
  log.warn("host-agent", "glab download failed \u2014 skipping (git push/pull still work)");
18046
18187
  return null;
@@ -18051,20 +18192,20 @@ async function ensureGlabCli(runner, deps = {}) {
18051
18192
  return null;
18052
18193
  }
18053
18194
  const candidates = [
18054
- path42.join(tmpRoot, "bin", binaryName),
18055
- path42.join(tmpRoot, asset, "bin", binaryName),
18056
- path42.join(tmpRoot, binaryName)
18195
+ path43.join(tmpRoot, "bin", binaryName),
18196
+ path43.join(tmpRoot, asset, "bin", binaryName),
18197
+ path43.join(tmpRoot, binaryName)
18057
18198
  ];
18058
- const extractedBin = candidates.find((c2) => fs38.existsSync(c2));
18199
+ const extractedBin = candidates.find((c2) => fs39.existsSync(c2));
18059
18200
  if (!extractedBin) {
18060
18201
  log.warn("host-agent", "glab binary not found in the extracted archive \u2014 skipping");
18061
18202
  return null;
18062
18203
  }
18063
18204
  const binDir = codeamBinDir();
18064
- fs38.mkdirSync(binDir, { recursive: true });
18065
- const target = path42.join(binDir, binaryName);
18066
- fs38.copyFileSync(extractedBin, target);
18067
- fs38.chmodSync(target, 493);
18205
+ fs39.mkdirSync(binDir, { recursive: true });
18206
+ const target = path43.join(binDir, binaryName);
18207
+ fs39.copyFileSync(extractedBin, target);
18208
+ fs39.chmodSync(target, 493);
18068
18209
  log.info("host-agent", `glab installed to ${target} (v${version3})`);
18069
18210
  return target;
18070
18211
  } catch (e) {
@@ -18099,7 +18240,7 @@ var defaultGitToolingRunner = {
18099
18240
  which(cmd) {
18100
18241
  try {
18101
18242
  const probe = process.platform === "win32" ? "where" : "which";
18102
- (0, import_node_child_process19.execFileSync)(probe, [cmd], { stdio: "ignore" });
18243
+ (0, import_node_child_process20.execFileSync)(probe, [cmd], { stdio: "ignore" });
18103
18244
  return true;
18104
18245
  } catch {
18105
18246
  return false;
@@ -18107,7 +18248,7 @@ var defaultGitToolingRunner = {
18107
18248
  },
18108
18249
  run(cmd, args2, opts = {}) {
18109
18250
  return new Promise((resolve8) => {
18110
- const child = (0, import_node_child_process19.spawn)(cmd, args2, {
18251
+ const child = (0, import_node_child_process20.spawn)(cmd, args2, {
18111
18252
  stdio: [opts.input !== void 0 ? "pipe" : "ignore", "ignore", "pipe"]
18112
18253
  });
18113
18254
  let stderr = "";
@@ -18261,12 +18402,12 @@ var HeadroomStatsReporter = class {
18261
18402
  };
18262
18403
 
18263
18404
  // src/commands/host/os-packages.ts
18264
- var import_node_child_process20 = require("child_process");
18405
+ var import_node_child_process21 = require("child_process");
18265
18406
  var PM_INSTALL_TIMEOUT_MS = 18e4;
18266
18407
  var defaultHeadroomRunner = {
18267
18408
  which(cmd) {
18268
18409
  try {
18269
- (0, import_node_child_process20.execFileSync)("which", [cmd], { stdio: "ignore" });
18410
+ (0, import_node_child_process21.execFileSync)("which", [cmd], { stdio: "ignore" });
18270
18411
  return true;
18271
18412
  } catch {
18272
18413
  return false;
@@ -18275,7 +18416,7 @@ var defaultHeadroomRunner = {
18275
18416
  run(cmd, args2, opts = {}) {
18276
18417
  return new Promise((resolve8) => {
18277
18418
  const spawnEnv = opts.env ?? process.env;
18278
- const child = (0, import_node_child_process20.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"], env: spawnEnv });
18419
+ const child = (0, import_node_child_process21.spawn)(cmd, args2, { stdio: ["ignore", "pipe", "pipe"], env: spawnEnv });
18279
18420
  let stderrBuf = "";
18280
18421
  let stdoutBuf = "";
18281
18422
  let settled = false;
@@ -18552,24 +18693,24 @@ async function ensureModernPython(runner) {
18552
18693
  }
18553
18694
 
18554
18695
  // src/commands/host/headroom-bootstrap.ts
18555
- var fs40 = __toESM(require("fs"));
18556
- var path44 = __toESM(require("path"));
18557
- var os36 = __toESM(require("os"));
18696
+ var fs41 = __toESM(require("fs"));
18697
+ var path45 = __toESM(require("path"));
18698
+ var os37 = __toESM(require("os"));
18558
18699
 
18559
18700
  // src/commands/host/headroom-config.ts
18560
- var fs39 = __toESM(require("fs"));
18561
- var os35 = __toESM(require("os"));
18562
- var path43 = __toESM(require("path"));
18701
+ var fs40 = __toESM(require("fs"));
18702
+ var os36 = __toESM(require("os"));
18703
+ var path44 = __toESM(require("path"));
18563
18704
  function headroomConfigPath() {
18564
- return path43.join(os35.homedir(), ".codeam", "headroom-config.json");
18705
+ return path44.join(os36.homedir(), ".codeam", "headroom-config.json");
18565
18706
  }
18566
18707
  function persistHeadroomConfig(config) {
18567
18708
  try {
18568
18709
  const file = headroomConfigPath();
18569
- fs39.mkdirSync(path43.dirname(file), { recursive: true, mode: 448 });
18710
+ fs40.mkdirSync(path44.dirname(file), { recursive: true, mode: 448 });
18570
18711
  const tmp = `${file}.tmp-${process.pid}`;
18571
- fs39.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
18572
- fs39.renameSync(tmp, file);
18712
+ fs40.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
18713
+ fs40.renameSync(tmp, file);
18573
18714
  restrictToOwner(file);
18574
18715
  } catch (err) {
18575
18716
  log.warn(
@@ -18579,21 +18720,21 @@ function persistHeadroomConfig(config) {
18579
18720
  }
18580
18721
  }
18581
18722
  function agentSettingsPath(kind) {
18582
- const home = os35.homedir();
18583
- if (kind === "claude") return path43.join(home, ".claude", "settings.json");
18584
- if (kind === "codex") return path43.join(home, ".codex", "auth.json");
18585
- if (kind === "copilot") return path43.join(home, ".config", "github-copilot", "hosts.json");
18723
+ const home = os36.homedir();
18724
+ if (kind === "claude") return path44.join(home, ".claude", "settings.json");
18725
+ if (kind === "codex") return path44.join(home, ".codex", "auth.json");
18726
+ if (kind === "copilot") return path44.join(home, ".config", "github-copilot", "hosts.json");
18586
18727
  return null;
18587
18728
  }
18588
18729
  function backupAgentHeadroomConfig(kind) {
18589
18730
  const src = agentSettingsPath(kind);
18590
18731
  if (!src) return;
18591
18732
  try {
18592
- if (!fs39.existsSync(src)) return;
18593
- const dest = path43.join(os35.homedir(), ".codeam", `headroom-backup-${kind}.json`);
18594
- fs39.mkdirSync(path43.dirname(dest), { recursive: true, mode: 448 });
18595
- fs39.copyFileSync(src, dest);
18596
- fs39.chmodSync(dest, 384);
18733
+ if (!fs40.existsSync(src)) return;
18734
+ const dest = path44.join(os36.homedir(), ".codeam", `headroom-backup-${kind}.json`);
18735
+ fs40.mkdirSync(path44.dirname(dest), { recursive: true, mode: 448 });
18736
+ fs40.copyFileSync(src, dest);
18737
+ fs40.chmodSync(dest, 384);
18597
18738
  log.info("host-agent", `headroom config backup: ${src} \u2192 ${dest}`);
18598
18739
  } catch (err) {
18599
18740
  log.warn(
@@ -18605,12 +18746,12 @@ function backupAgentHeadroomConfig(kind) {
18605
18746
  function restoreAgentHeadroomConfig(kind) {
18606
18747
  const dest = agentSettingsPath(kind);
18607
18748
  if (!dest) return false;
18608
- const src = path43.join(os35.homedir(), ".codeam", `headroom-backup-${kind}.json`);
18609
- if (!fs39.existsSync(src)) return false;
18749
+ const src = path44.join(os36.homedir(), ".codeam", `headroom-backup-${kind}.json`);
18750
+ if (!fs40.existsSync(src)) return false;
18610
18751
  try {
18611
- fs39.mkdirSync(path43.dirname(dest), { recursive: true, mode: 448 });
18612
- fs39.copyFileSync(src, dest);
18613
- fs39.chmodSync(dest, 384);
18752
+ fs40.mkdirSync(path44.dirname(dest), { recursive: true, mode: 448 });
18753
+ fs40.copyFileSync(src, dest);
18754
+ fs40.chmodSync(dest, 384);
18614
18755
  log.info("host-agent", `headroom config restored: ${src} \u2192 ${dest}`);
18615
18756
  return true;
18616
18757
  } catch (err) {
@@ -18623,7 +18764,7 @@ function restoreAgentHeadroomConfig(kind) {
18623
18764
  }
18624
18765
  function readHeadroomChildEnv() {
18625
18766
  try {
18626
- const raw = fs39.readFileSync(headroomConfigPath(), "utf8");
18767
+ const raw = fs40.readFileSync(headroomConfigPath(), "utf8");
18627
18768
  const parsed = JSON.parse(raw);
18628
18769
  if (typeof parsed !== "object" || parsed === null) return {};
18629
18770
  const o = parsed;
@@ -18659,49 +18800,49 @@ function bundledClaudeBinDir() {
18659
18800
  const roots = /* @__PURE__ */ new Set();
18660
18801
  let dir = __dirname;
18661
18802
  for (let i = 0; i < 6; i++) {
18662
- roots.add(path44.join(dir, "node_modules"));
18663
- const parent = path44.dirname(dir);
18803
+ roots.add(path45.join(dir, "node_modules"));
18804
+ const parent = path45.dirname(dir);
18664
18805
  if (parent === dir) break;
18665
18806
  dir = parent;
18666
18807
  }
18667
18808
  try {
18668
18809
  const main2 = require.resolve("@anthropic-ai/claude-agent-sdk");
18669
- const marker = `${path44.sep}@anthropic-ai${path44.sep}`;
18810
+ const marker = `${path45.sep}@anthropic-ai${path45.sep}`;
18670
18811
  const idx = main2.lastIndexOf(marker);
18671
18812
  if (idx !== -1) roots.add(main2.slice(0, idx));
18672
18813
  } catch {
18673
18814
  }
18674
18815
  for (const nm of roots) {
18675
- const atAnthropic = path44.join(nm, "@anthropic-ai");
18816
+ const atAnthropic = path45.join(nm, "@anthropic-ai");
18676
18817
  let entries;
18677
18818
  try {
18678
- entries = fs40.readdirSync(atAnthropic);
18819
+ entries = fs41.readdirSync(atAnthropic);
18679
18820
  } catch {
18680
18821
  continue;
18681
18822
  }
18682
18823
  for (const entry of entries) {
18683
18824
  if (!entry.startsWith("claude-agent-sdk-")) continue;
18684
- const bin = path44.join(atAnthropic, entry, "claude");
18685
- if (fs40.existsSync(bin)) return path44.dirname(bin);
18825
+ const bin = path45.join(atAnthropic, entry, "claude");
18826
+ if (fs41.existsSync(bin)) return path45.dirname(bin);
18686
18827
  }
18687
18828
  }
18688
18829
  return null;
18689
18830
  }
18690
18831
  async function getFreeDiskBytes(dir) {
18691
18832
  try {
18692
- const s = await fs40.promises.statfs(dir);
18833
+ const s = await fs41.promises.statfs(dir);
18693
18834
  return s.bsize * s.bavail;
18694
18835
  } catch {
18695
18836
  return null;
18696
18837
  }
18697
18838
  }
18698
18839
  function headroomModelsCached() {
18699
- const hubDir = process.env.HUGGINGFACE_HUB_CACHE || path44.join(
18700
- process.env.HF_HOME || path44.join(os36.homedir(), ".cache", "huggingface"),
18840
+ const hubDir = process.env.HUGGINGFACE_HUB_CACHE || path45.join(
18841
+ process.env.HF_HOME || path45.join(os37.homedir(), ".cache", "huggingface"),
18701
18842
  "hub"
18702
18843
  );
18703
18844
  return HEADROOM_MODELS.every(
18704
- (m) => fs40.existsSync(path44.join(hubDir, `models--${m.repo.replace("/", "--")}`))
18845
+ (m) => fs41.existsSync(path45.join(hubDir, `models--${m.repo.replace("/", "--")}`))
18705
18846
  );
18706
18847
  }
18707
18848
  async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner, opts = {}) {
@@ -18770,7 +18911,7 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
18770
18911
  if (initKind === "claude") {
18771
18912
  const claudeDir = bundledClaudeBinDir();
18772
18913
  if (claudeDir) {
18773
- initEnv.PATH = `${claudeDir}${path44.delimiter}${process.env["PATH"] ?? ""}`;
18914
+ initEnv.PATH = `${claudeDir}${path45.delimiter}${process.env["PATH"] ?? ""}`;
18774
18915
  log.info("host-agent", `headroom init: bundled claude on PATH (${claudeDir})`);
18775
18916
  } else {
18776
18917
  log.warn("host-agent", "headroom init: bundled claude binary not found \u2014 init may fail");
@@ -18802,26 +18943,26 @@ async function setupHeadroomForSelfHosted(agent, runner = defaultHeadroomRunner,
18802
18943
  }
18803
18944
 
18804
18945
  // src/commands/host/self-update.ts
18805
- var import_node_child_process22 = require("child_process");
18946
+ var import_node_child_process23 = require("child_process");
18806
18947
 
18807
18948
  // src/lib/updateNotifier.ts
18808
- var fs41 = __toESM(require("fs"));
18809
- var os37 = __toESM(require("os"));
18810
- var path45 = __toESM(require("path"));
18949
+ var fs42 = __toESM(require("fs"));
18950
+ var os38 = __toESM(require("os"));
18951
+ var path46 = __toESM(require("path"));
18811
18952
  var https6 = __toESM(require("https"));
18812
- var import_node_child_process21 = require("child_process");
18953
+ var import_node_child_process22 = require("child_process");
18813
18954
  var import_picocolors3 = __toESM(require("picocolors"));
18814
18955
  var PKG_NAME = "codeam-cli";
18815
18956
  var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
18816
18957
  var TTL_MS = 24 * 60 * 60 * 1e3;
18817
18958
  var REQUEST_TIMEOUT_MS = 1500;
18818
18959
  function cachePath() {
18819
- const dir = path45.join(os37.homedir(), ".codeam");
18820
- return path45.join(dir, "update-check.json");
18960
+ const dir = path46.join(os38.homedir(), ".codeam");
18961
+ return path46.join(dir, "update-check.json");
18821
18962
  }
18822
18963
  function readCache() {
18823
18964
  try {
18824
- const raw = fs41.readFileSync(cachePath(), "utf8");
18965
+ const raw = fs42.readFileSync(cachePath(), "utf8");
18825
18966
  const parsed = JSON.parse(raw);
18826
18967
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
18827
18968
  return parsed;
@@ -18832,10 +18973,10 @@ function readCache() {
18832
18973
  function writeCache(cache) {
18833
18974
  try {
18834
18975
  const file = cachePath();
18835
- fs41.mkdirSync(path45.dirname(file), { recursive: true });
18976
+ fs42.mkdirSync(path46.dirname(file), { recursive: true });
18836
18977
  const tmp = `${file}.${process.pid}.tmp`;
18837
- fs41.writeFileSync(tmp, JSON.stringify(cache));
18838
- fs41.renameSync(tmp, file);
18978
+ fs42.writeFileSync(tmp, JSON.stringify(cache));
18979
+ fs42.renameSync(tmp, file);
18839
18980
  } catch {
18840
18981
  }
18841
18982
  }
@@ -18903,14 +19044,14 @@ function notifyIfStale(currentVersion, latest) {
18903
19044
  }
18904
19045
  function isLinkedInstall() {
18905
19046
  try {
18906
- const root = (0, import_node_child_process21.execSync)("npm root -g", {
19047
+ const root = (0, import_node_child_process22.execSync)("npm root -g", {
18907
19048
  encoding: "utf8",
18908
19049
  stdio: ["ignore", "pipe", "ignore"],
18909
19050
  timeout: 2e3
18910
19051
  }).trim();
18911
19052
  if (!root) return false;
18912
- const pkgPath = path45.join(root, PKG_NAME);
18913
- return fs41.lstatSync(pkgPath).isSymbolicLink();
19053
+ const pkgPath = path46.join(root, PKG_NAME);
19054
+ return fs42.lstatSync(pkgPath).isSymbolicLink();
18914
19055
  } catch {
18915
19056
  return false;
18916
19057
  }
@@ -18931,7 +19072,7 @@ function maybeAutoUpdate(currentVersion, latest) {
18931
19072
 
18932
19073
  `
18933
19074
  );
18934
- const install = (0, import_node_child_process21.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
19075
+ const install = (0, import_node_child_process22.spawnSync)("npm", ["install", "-g", `${PKG_NAME}@latest`], {
18935
19076
  stdio: "inherit",
18936
19077
  env: process.env
18937
19078
  });
@@ -18946,13 +19087,13 @@ function maybeAutoUpdate(currentVersion, latest) {
18946
19087
  return;
18947
19088
  }
18948
19089
  try {
18949
- fs41.unlinkSync(cachePath());
19090
+ fs42.unlinkSync(cachePath());
18950
19091
  } catch {
18951
19092
  }
18952
19093
  process.stderr.write(` ${import_picocolors3.default.green("\u2713")} Updated. Resuming session...
18953
19094
 
18954
19095
  `);
18955
- const child = (0, import_node_child_process21.spawnSync)("codeam", process.argv.slice(2), {
19096
+ const child = (0, import_node_child_process22.spawnSync)("codeam", process.argv.slice(2), {
18956
19097
  stdio: "inherit",
18957
19098
  env: process.env
18958
19099
  });
@@ -18962,7 +19103,7 @@ async function autoUpgradeBeforeCriticalCommand() {
18962
19103
  if (process.env.NODE_ENV === "test") return;
18963
19104
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
18964
19105
  if (process.env.CI) return;
18965
- const current = true ? "2.61.49" : null;
19106
+ const current = true ? "2.61.50" : null;
18966
19107
  if (!current) return;
18967
19108
  const cache = readCache();
18968
19109
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -18979,7 +19120,7 @@ function checkForUpdates() {
18979
19120
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
18980
19121
  if (process.env.CI) return;
18981
19122
  if (!process.stdout.isTTY) return;
18982
- const current = true ? "2.61.49" : null;
19123
+ const current = true ? "2.61.50" : null;
18983
19124
  if (!current) return;
18984
19125
  const cache = readCache();
18985
19126
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -18999,11 +19140,11 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
18999
19140
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
19000
19141
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
19001
19142
  function currentCliVersion() {
19002
- return true ? "2.61.49" : null;
19143
+ return true ? "2.61.50" : null;
19003
19144
  }
19004
19145
  function runCmd(cmd, args2, timeoutMs) {
19005
19146
  return new Promise((resolve8) => {
19006
- (0, import_node_child_process22.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
19147
+ (0, import_node_child_process23.execFile)(cmd, args2, { timeout: timeoutMs }, (err, stdout, stderr) => {
19007
19148
  const code = err && typeof err.code === "number" ? err.code : err ? null : 0;
19008
19149
  resolve8({ code, stdout: stdout ?? "", stderr: stderr ?? "" });
19009
19150
  });
@@ -19065,19 +19206,19 @@ async function runSelfUpdate() {
19065
19206
  }
19066
19207
 
19067
19208
  // src/commands/host/teardown.ts
19068
- var import_node_child_process23 = require("child_process");
19069
- var fs42 = __toESM(require("fs"));
19209
+ var import_node_child_process24 = require("child_process");
19210
+ var fs43 = __toESM(require("fs"));
19070
19211
  var defaultDisableService = () => {
19071
19212
  try {
19072
- (0, import_node_child_process23.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
19213
+ (0, import_node_child_process24.execFileSync)("systemctl", ["disable", "--now", "codeam-host-agent"], { stdio: "ignore" });
19073
19214
  } catch {
19074
19215
  }
19075
19216
  };
19076
19217
  var defaultTeardownHeadroom = () => {
19077
19218
  try {
19078
- const kind = JSON.parse(fs42.readFileSync(headroomConfigPath(), "utf8")).agent;
19219
+ const kind = JSON.parse(fs43.readFileSync(headroomConfigPath(), "utf8")).agent;
19079
19220
  if (kind) {
19080
- (0, import_node_child_process23.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
19221
+ (0, import_node_child_process24.execFileSync)("headroom", ["unwrap", kind], { stdio: "ignore", timeout: 15e3 });
19081
19222
  }
19082
19223
  } catch {
19083
19224
  }
@@ -19143,8 +19284,8 @@ function maybeResumeLocalHeadroomReporter(ctx) {
19143
19284
  if (process.env["HEADROOM_ENABLED"] === "1") return null;
19144
19285
  try {
19145
19286
  const file = headroomConfigPath();
19146
- if (!fs43.existsSync(file)) return null;
19147
- const cfg = JSON.parse(fs43.readFileSync(file, "utf8"));
19287
+ if (!fs44.existsSync(file)) return null;
19288
+ const cfg = JSON.parse(fs44.readFileSync(file, "utf8"));
19148
19289
  if (!cfg?.enabled) return null;
19149
19290
  const agent = cfg.agent ?? "claude";
19150
19291
  const ingestUrl = `${resolveApiBaseUrl()}/api/sessions/${ctx.sessionId}/headroom-savings`;
@@ -19329,7 +19470,7 @@ var DOCKER_RUN_TIMEOUT_MS = 12e4;
19329
19470
  var defaultDockerRunner = {
19330
19471
  run(args2, opts = {}) {
19331
19472
  return new Promise((resolve8) => {
19332
- const child = (0, import_node_child_process24.spawn)("docker", args2, {
19473
+ const child = (0, import_node_child_process25.spawn)("docker", args2, {
19333
19474
  stdio: ["ignore", "pipe", "pipe"],
19334
19475
  env: { ...process.env, ...opts.env }
19335
19476
  });
@@ -19375,13 +19516,13 @@ var CONTROL_AGENT_META = {
19375
19516
  headroomWrappable: false,
19376
19517
  acp: false
19377
19518
  };
19378
- var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process24.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
19519
+ var defaultSpawner = (env, cwd, args2 = []) => (0, import_node_child_process25.spawn)(process.execPath, [process.argv[1], "pair-auto", ...args2], {
19379
19520
  cwd,
19380
19521
  env: { ...process.env, ...env },
19381
19522
  stdio: ["ignore", "pipe", "pipe"],
19382
19523
  detached: false
19383
19524
  });
19384
- var defaultResumeSpawner = (env, cwd) => (0, import_node_child_process24.spawn)(process.execPath, [process.argv[1]], {
19525
+ var defaultResumeSpawner = (env, cwd) => (0, import_node_child_process25.spawn)(process.execPath, [process.argv[1]], {
19385
19526
  cwd,
19386
19527
  // CODEAM_AUTO_APPROVE=1 → ACP path (baton off). CODEAM_RESUME_LATEST=1 →
19387
19528
  // continue the user's most-recent conversation instead of opening an empty
@@ -19715,13 +19856,13 @@ var HostAgentSupervisor = class {
19715
19856
  const relay = this.relay;
19716
19857
  if (!relay) return;
19717
19858
  const raw = cmd.payload?.path;
19718
- const target = typeof raw === "string" && raw.trim() ? path46.resolve(raw.trim()) : os38.homedir();
19859
+ const target = typeof raw === "string" && raw.trim() ? path47.resolve(raw.trim()) : os39.homedir();
19719
19860
  try {
19720
- const dirents = await fs43.promises.readdir(target, { withFileTypes: true });
19861
+ const dirents = await fs44.promises.readdir(target, { withFileTypes: true });
19721
19862
  const entries = dirents.filter((d3) => !d3.name.startsWith(".")).map((d3) => ({ name: d3.name, isDir: d3.isDirectory() })).sort(
19722
19863
  (a, b) => a.isDir === b.isDir ? a.name.localeCompare(b.name) : a.isDir ? -1 : 1
19723
19864
  );
19724
- const parent = path46.dirname(target);
19865
+ const parent = path47.dirname(target);
19725
19866
  await relay.sendResult(cmd.id, "completed", {
19726
19867
  path: target,
19727
19868
  // null at the filesystem root so the UI can hide the ".." affordance.
@@ -19949,14 +20090,14 @@ var HostAgentSupervisor = class {
19949
20090
  API_TIMEOUT_MS: "3000000",
19950
20091
  CODEAM_AUTO_TOKEN: payload.autoPairToken
19951
20092
  };
19952
- const houseConfigDir = path46.join(
19953
- os38.homedir(),
20093
+ const houseConfigDir = path47.join(
20094
+ os39.homedir(),
19954
20095
  ".codeam",
19955
20096
  "house-claude",
19956
20097
  payload.deployId
19957
20098
  );
19958
20099
  try {
19959
- fs43.mkdirSync(houseConfigDir, { recursive: true, mode: 448 });
20100
+ fs44.mkdirSync(houseConfigDir, { recursive: true, mode: 448 });
19960
20101
  } catch {
19961
20102
  }
19962
20103
  childEnv.CLAUDE_CONFIG_DIR = houseConfigDir;
@@ -19975,7 +20116,7 @@ var HostAgentSupervisor = class {
19975
20116
  report("installing", "installing agent CLI");
19976
20117
  await this.runAgentInstall(payload.agentInstallScript);
19977
20118
  }
19978
- const home = process.env.HOME || os38.homedir();
20119
+ const home = process.env.HOME || os39.homedir();
19979
20120
  childEnv.PATH = `${home}/.local/bin:${process.env.PATH ?? ""}`;
19980
20121
  if (payload.cloneToken) {
19981
20122
  try {
@@ -19983,13 +20124,13 @@ var HostAgentSupervisor = class {
19983
20124
  if ((payload.repoProvider ?? "github") === "gitlab") {
19984
20125
  const glabCmd = await ensureGlabCli(defaultGitToolingRunner);
19985
20126
  if (glabCmd) {
19986
- childEnv.PATH = `${codeamBinDir()}${path46.delimiter}${childEnv.PATH}`;
20127
+ childEnv.PATH = `${codeamBinDir()}${path47.delimiter}${childEnv.PATH}`;
19987
20128
  await ensureGlabAuth(defaultGitToolingRunner, glabCmd, payload.cloneToken);
19988
20129
  }
19989
20130
  } else {
19990
20131
  const ghCmd = await ensureGhCli(defaultGitToolingRunner, payload.cloneToken);
19991
20132
  if (ghCmd) {
19992
- childEnv.PATH = `${codeamBinDir()}${path46.delimiter}${childEnv.PATH}`;
20133
+ childEnv.PATH = `${codeamBinDir()}${path47.delimiter}${childEnv.PATH}`;
19993
20134
  await ensureGhAuth(defaultGitToolingRunner, ghCmd, payload.cloneToken);
19994
20135
  }
19995
20136
  }
@@ -20006,7 +20147,7 @@ var HostAgentSupervisor = class {
20006
20147
  }
20007
20148
  if (payload.headroomEnabled && payload.headroomAgent && payload.headroomSavingsIngestUrl && isHeadroomSupportedAgent(payload.headroomAgent)) {
20008
20149
  report("headroom", "setting up Headroom proxy");
20009
- const freeBytes = await this.getFreeDisk(os38.homedir());
20150
+ const freeBytes = await this.getFreeDisk(os39.homedir());
20010
20151
  const alreadyInstalled = this.isHeadroomInstalled();
20011
20152
  if (!alreadyInstalled && freeBytes !== null && freeBytes < HEADROOM_MIN_FREE_DISK_BYTES) {
20012
20153
  const freeGb = (freeBytes / 1e9).toFixed(1);
@@ -20197,8 +20338,8 @@ var HostAgentSupervisor = class {
20197
20338
  */
20198
20339
  runAgentInstall(script) {
20199
20340
  return new Promise((resolve8) => {
20200
- const home = process.env.HOME || os38.homedir();
20201
- const child = (0, import_node_child_process24.spawn)("sh", ["-c", script], {
20341
+ const home = process.env.HOME || os39.homedir();
20342
+ const child = (0, import_node_child_process25.spawn)("sh", ["-c", script], {
20202
20343
  env: { ...process.env, HOME: home },
20203
20344
  stdio: ["ignore", "pipe", "pipe"]
20204
20345
  });
@@ -20389,9 +20530,9 @@ async function configureHeadroom(action, ctx, deps) {
20389
20530
  }
20390
20531
 
20391
20532
  // src/services/headroom/budget-relaunch.ts
20392
- var fs44 = __toESM(require("fs"));
20393
- var os39 = __toESM(require("os"));
20394
- var path47 = __toESM(require("path"));
20533
+ var fs45 = __toESM(require("fs"));
20534
+ var os40 = __toESM(require("os"));
20535
+ var path48 = __toESM(require("path"));
20395
20536
  var import_child_process13 = require("child_process");
20396
20537
  function amendDeploymentManifestBudget(manifest, budget) {
20397
20538
  const rawArgs = manifest.proxy_args ?? [];
@@ -20425,7 +20566,7 @@ function amendDeploymentManifestBudget(manifest, budget) {
20425
20566
  return { ...manifest, proxy_args: newArgs, base_env: newEnv };
20426
20567
  }
20427
20568
  function findHeadroomDeployments(homeDir2, deps) {
20428
- const deployDir = path47.join(homeDir2, ".headroom", "deploy");
20569
+ const deployDir = path48.join(homeDir2, ".headroom", "deploy");
20429
20570
  let profiles;
20430
20571
  try {
20431
20572
  profiles = deps.readDir(deployDir);
@@ -20434,7 +20575,7 @@ function findHeadroomDeployments(homeDir2, deps) {
20434
20575
  }
20435
20576
  const results = [];
20436
20577
  for (const profile of profiles) {
20437
- const manifestPath = path47.join(deployDir, profile, "manifest.json");
20578
+ const manifestPath = path48.join(deployDir, profile, "manifest.json");
20438
20579
  let raw;
20439
20580
  try {
20440
20581
  raw = deps.readJson(manifestPath);
@@ -20466,8 +20607,8 @@ async function applyBudgetToHeadroom(budget, deps) {
20466
20607
  }
20467
20608
  function writeManifestReal(manifestPath, manifest) {
20468
20609
  const tmp = manifestPath + ".codeam.tmp";
20469
- fs44.writeFileSync(tmp, JSON.stringify(manifest, null, 2) + "\n", { mode: 384 });
20470
- fs44.renameSync(tmp, manifestPath);
20610
+ fs45.writeFileSync(tmp, JSON.stringify(manifest, null, 2) + "\n", { mode: 384 });
20611
+ fs45.renameSync(tmp, manifestPath);
20471
20612
  }
20472
20613
  function restartDeploymentReal(profile) {
20473
20614
  try {
@@ -20497,11 +20638,11 @@ function spawnProxyReal2(_budget) {
20497
20638
  });
20498
20639
  }
20499
20640
  function makeRealApplyBudgetDeps() {
20500
- const homeDir2 = os39.homedir();
20641
+ const homeDir2 = os40.homedir();
20501
20642
  return {
20502
20643
  findDeployments: () => findHeadroomDeployments(homeDir2, {
20503
- readDir: (dir) => fs44.readdirSync(dir),
20504
- readJson: (filePath) => JSON.parse(fs44.readFileSync(filePath, "utf8"))
20644
+ readDir: (dir) => fs45.readdirSync(dir),
20645
+ readJson: (filePath) => JSON.parse(fs45.readFileSync(filePath, "utf8"))
20505
20646
  }),
20506
20647
  writeManifest: writeManifestReal,
20507
20648
  restartDeployment: restartDeploymentReal,
@@ -20511,16 +20652,16 @@ function makeRealApplyBudgetDeps() {
20511
20652
  }
20512
20653
 
20513
20654
  // src/services/preview/port-registry.ts
20514
- var fs45 = __toESM(require("fs"));
20515
- var os40 = __toESM(require("os"));
20516
- var path48 = __toESM(require("path"));
20655
+ var fs46 = __toESM(require("fs"));
20656
+ var os41 = __toESM(require("os"));
20657
+ var path49 = __toESM(require("path"));
20517
20658
  var import_child_process14 = require("child_process");
20518
20659
  function registryPath() {
20519
- return path48.join(os40.homedir(), ".codeam", "preview-ports.json");
20660
+ return path49.join(os41.homedir(), ".codeam", "preview-ports.json");
20520
20661
  }
20521
20662
  function readRegistry() {
20522
20663
  try {
20523
- const raw = fs45.readFileSync(registryPath(), "utf8");
20664
+ const raw = fs46.readFileSync(registryPath(), "utf8");
20524
20665
  const parsed = JSON.parse(raw);
20525
20666
  if (parsed && typeof parsed === "object") return parsed;
20526
20667
  } catch {
@@ -20530,10 +20671,10 @@ function readRegistry() {
20530
20671
  function writeRegistry(reg) {
20531
20672
  try {
20532
20673
  const file = registryPath();
20533
- fs45.mkdirSync(path48.dirname(file), { recursive: true });
20674
+ fs46.mkdirSync(path49.dirname(file), { recursive: true });
20534
20675
  const tmp = `${file}.tmp`;
20535
- fs45.writeFileSync(tmp, JSON.stringify(reg), "utf8");
20536
- fs45.renameSync(tmp, file);
20676
+ fs46.writeFileSync(tmp, JSON.stringify(reg), "utf8");
20677
+ fs46.renameSync(tmp, file);
20537
20678
  } catch (err) {
20538
20679
  log.warn("preview", `port-registry write failed: ${err instanceof Error ? err.message : String(err)}`);
20539
20680
  }
@@ -20601,11 +20742,11 @@ function reclaimOwnOrphanPort(port) {
20601
20742
  var import_child_process15 = require("child_process");
20602
20743
  var import_fs = require("fs");
20603
20744
  var import_promises = __toESM(require("fs/promises"));
20604
- var import_os8 = __toESM(require("os"));
20745
+ var import_os9 = __toESM(require("os"));
20605
20746
  var import_path4 = __toESM(require("path"));
20606
20747
  var import_promises2 = require("stream/promises");
20607
20748
  var import_which = __toESM(require("which"));
20608
- var CACHED_BINARY = import_path4.default.join(import_os8.default.homedir(), ".codeam", "bin", "cloudflared");
20749
+ var CACHED_BINARY = import_path4.default.join(import_os9.default.homedir(), ".codeam", "bin", "cloudflared");
20609
20750
  async function resolveCloudflared(opts = {}) {
20610
20751
  try {
20611
20752
  return await (0, import_which.default)("cloudflared");
@@ -20705,7 +20846,7 @@ function decodeTunnelToken(token) {
20705
20846
  }
20706
20847
  async function spawnNamedTunnel(bin, token, port) {
20707
20848
  const creds = decodeTunnelToken(token);
20708
- const credDir = import_path4.default.join(import_os8.default.homedir(), ".codeam");
20849
+ const credDir = import_path4.default.join(import_os9.default.homedir(), ".codeam");
20709
20850
  await import_promises.default.mkdir(credDir, { recursive: true });
20710
20851
  const credFile = import_path4.default.join(credDir, `tunnel-${creds.TunnelID}.json`);
20711
20852
  await import_promises.default.writeFile(credFile, JSON.stringify(creds), { mode: 384 });
@@ -21269,8 +21410,8 @@ function activePreviewSessionIds() {
21269
21410
 
21270
21411
  // src/services/preview/start-orchestrator.ts
21271
21412
  var import_child_process18 = require("child_process");
21272
- var fs50 = __toESM(require("fs"));
21273
- var path53 = __toESM(require("path"));
21413
+ var fs51 = __toESM(require("fs"));
21414
+ var path54 = __toESM(require("path"));
21274
21415
  var import_which2 = __toESM(require("which"));
21275
21416
  var INSTALL_TIMEOUT_MS = 5 * 6e4;
21276
21417
  var SETUP_TIMEOUT_MS = 2 * 6e4;
@@ -21337,8 +21478,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
21337
21478
  if (args2.length === 0) return detection;
21338
21479
  const binName = args2[0];
21339
21480
  if (binName.startsWith("-")) return detection;
21340
- const binPath = path53.join(cwd, "node_modules", ".bin", binName);
21341
- if (!fs50.existsSync(binPath)) return detection;
21481
+ const binPath = path54.join(cwd, "node_modules", ".bin", binName);
21482
+ if (!fs51.existsSync(binPath)) return detection;
21342
21483
  return {
21343
21484
  ...detection,
21344
21485
  command: binPath,
@@ -21702,9 +21843,9 @@ async function establishTunnel(ctx, dev) {
21702
21843
 
21703
21844
  // src/beads/bd-adapter.ts
21704
21845
  var import_child_process19 = require("child_process");
21705
- var fs51 = __toESM(require("fs"));
21706
- var os42 = __toESM(require("os"));
21707
- var path54 = __toESM(require("path"));
21846
+ var fs52 = __toESM(require("fs"));
21847
+ var os43 = __toESM(require("os"));
21848
+ var path55 = __toESM(require("path"));
21708
21849
  var BD_PACKAGE = "@beads/bd";
21709
21850
  function resolveBundledBdBinary() {
21710
21851
  return _resolveSeam.resolveBundled();
@@ -21716,11 +21857,11 @@ function _defaultResolveBundled() {
21716
21857
  } catch {
21717
21858
  return null;
21718
21859
  }
21719
- const binDir = path54.join(path54.dirname(pkgJsonPath), "bin");
21860
+ const binDir = path55.join(path55.dirname(pkgJsonPath), "bin");
21720
21861
  const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
21721
- const binaryPath = path54.join(binDir, binaryName);
21862
+ const binaryPath = path55.join(binDir, binaryName);
21722
21863
  try {
21723
- fs51.accessSync(binaryPath, fs51.constants.F_OK);
21864
+ fs52.accessSync(binaryPath, fs52.constants.F_OK);
21724
21865
  return binaryPath;
21725
21866
  } catch {
21726
21867
  return null;
@@ -21730,13 +21871,13 @@ function resolveBdOnPath() {
21730
21871
  return _resolveSeam.resolveOnPath();
21731
21872
  }
21732
21873
  function _defaultResolveOnPath() {
21733
- const dirs = (process.env.PATH ?? "").split(path54.delimiter).filter(Boolean);
21874
+ const dirs = (process.env.PATH ?? "").split(path55.delimiter).filter(Boolean);
21734
21875
  const candidates = process.platform === "win32" ? ["bd.exe", "bd.cmd", "bd"] : ["bd"];
21735
21876
  for (const dir of dirs) {
21736
21877
  for (const candidate of candidates) {
21737
- const full = path54.join(dir, candidate);
21878
+ const full = path55.join(dir, candidate);
21738
21879
  try {
21739
- fs51.accessSync(full, fs51.constants.F_OK);
21880
+ fs52.accessSync(full, fs52.constants.F_OK);
21740
21881
  return full;
21741
21882
  } catch {
21742
21883
  }
@@ -21821,7 +21962,7 @@ var BdAdapter = class {
21821
21962
  const env = { ...process.env };
21822
21963
  if (!env.HOME) {
21823
21964
  try {
21824
- const home = os42.homedir();
21965
+ const home = os43.homedir();
21825
21966
  if (home) env.HOME = home;
21826
21967
  } catch {
21827
21968
  }
@@ -21913,9 +22054,9 @@ function coerceIssue(row, projectKey) {
21913
22054
 
21914
22055
  // src/beads/provisioner.ts
21915
22056
  var import_child_process23 = require("child_process");
21916
- var fs54 = __toESM(require("fs"));
21917
- var os44 = __toESM(require("os"));
21918
- var path57 = __toESM(require("path"));
22057
+ var fs55 = __toESM(require("fs"));
22058
+ var os45 = __toESM(require("os"));
22059
+ var path58 = __toESM(require("path"));
21919
22060
 
21920
22061
  // src/beads/install-bd.ts
21921
22062
  var import_child_process20 = require("child_process");
@@ -21980,9 +22121,9 @@ async function installBd(platform3 = process.platform) {
21980
22121
 
21981
22122
  // src/beads/install-dolt.ts
21982
22123
  var import_child_process21 = require("child_process");
21983
- var fs52 = __toESM(require("fs"));
21984
- var os43 = __toESM(require("os"));
21985
- var path55 = __toESM(require("path"));
22124
+ var fs53 = __toESM(require("fs"));
22125
+ var os44 = __toESM(require("os"));
22126
+ var path56 = __toESM(require("path"));
21986
22127
  var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
21987
22128
  var DOLT_MSI_URL = "https://github.com/dolthub/dolt/releases/latest/download/dolt-windows-amd64.msi";
21988
22129
  function resolveDoltInstallStrategy(platform3) {
@@ -22022,11 +22163,11 @@ function resolveDoltInstallStrategy(platform3) {
22022
22163
  }
22023
22164
  var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
22024
22165
  function doltPlatformTuple(platform3, arch2) {
22025
- const os59 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
22166
+ const os60 = platform3 === "win32" ? "windows" : platform3 === "darwin" ? "darwin" : "linux";
22026
22167
  const a = arch2 === "x64" ? "amd64" : arch2 === "arm64" ? "arm64" : null;
22027
22168
  if (!a) return null;
22028
- if (os59 === "windows" && a !== "amd64") return null;
22029
- return `${os59}-${a}`;
22169
+ if (os60 === "windows" && a !== "amd64") return null;
22170
+ return `${os60}-${a}`;
22030
22171
  }
22031
22172
  function resolveDoltTarballStrategy(targetDir, platform3, arch2) {
22032
22173
  const tuple = doltPlatformTuple(platform3, arch2);
@@ -22071,14 +22212,14 @@ async function installDoltToDir(targetDir, platform3 = process.platform, arch2 =
22071
22212
  return result;
22072
22213
  }
22073
22214
  var _doltPathSeam = {
22074
- homedir: () => os43.homedir(),
22215
+ homedir: () => os44.homedir(),
22075
22216
  getPath: () => process.env.PATH ?? "",
22076
22217
  setPath: (p2) => {
22077
22218
  process.env.PATH = p2;
22078
22219
  },
22079
22220
  exists: (p2) => {
22080
22221
  try {
22081
- fs52.accessSync(p2, fs52.constants.F_OK);
22222
+ fs53.accessSync(p2, fs53.constants.F_OK);
22082
22223
  return true;
22083
22224
  } catch {
22084
22225
  return false;
@@ -22089,7 +22230,7 @@ function doltBinaryNames(platform3) {
22089
22230
  return platform3 === "win32" ? ["dolt.exe", "dolt.cmd", "dolt"] : ["dolt"];
22090
22231
  }
22091
22232
  function knownDoltDirs(platform3) {
22092
- const P3 = platform3 === "win32" ? path55.win32 : path55.posix;
22233
+ const P3 = platform3 === "win32" ? path56.win32 : path56.posix;
22093
22234
  const home = _doltPathSeam.homedir();
22094
22235
  if (platform3 === "win32") {
22095
22236
  return [
@@ -22105,7 +22246,7 @@ function knownDoltDirs(platform3) {
22105
22246
  ].filter(Boolean);
22106
22247
  }
22107
22248
  function ensureDoltResolvable(platform3 = process.platform) {
22108
- const P3 = platform3 === "win32" ? path55.win32 : path55.posix;
22249
+ const P3 = platform3 === "win32" ? path56.win32 : path56.posix;
22109
22250
  const delim = platform3 === "win32" ? ";" : ":";
22110
22251
  const names = doltBinaryNames(platform3);
22111
22252
  const pathDirs = _doltPathSeam.getPath().split(delim).filter(Boolean);
@@ -22241,8 +22382,8 @@ async function ensureSharedServer(adapter, options = {}) {
22241
22382
  // src/beads/project-key.ts
22242
22383
  var import_child_process22 = require("child_process");
22243
22384
  var crypto2 = __toESM(require("crypto"));
22244
- var fs53 = __toESM(require("fs"));
22245
- var path56 = __toESM(require("path"));
22385
+ var fs54 = __toESM(require("fs"));
22386
+ var path57 = __toESM(require("path"));
22246
22387
  function normalizeOrigin(raw) {
22247
22388
  const trimmed = raw.trim();
22248
22389
  if (!trimmed) return null;
@@ -22268,17 +22409,17 @@ function normalizeOrigin(raw) {
22268
22409
  return `${host2}/${pathPart}`;
22269
22410
  }
22270
22411
  function findRepoRoot(cwd) {
22271
- let dir = path56.resolve(cwd);
22412
+ let dir = path57.resolve(cwd);
22272
22413
  const seen = /* @__PURE__ */ new Set();
22273
22414
  for (let i = 0; i < 256; i++) {
22274
22415
  if (seen.has(dir)) return null;
22275
22416
  seen.add(dir);
22276
22417
  try {
22277
- const stat3 = fs53.statSync(path56.join(dir, ".git"), { throwIfNoEntry: false });
22418
+ const stat3 = fs54.statSync(path57.join(dir, ".git"), { throwIfNoEntry: false });
22278
22419
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
22279
22420
  } catch {
22280
22421
  }
22281
- const parent = path56.dirname(dir);
22422
+ const parent = path57.dirname(dir);
22282
22423
  if (parent === dir) return null;
22283
22424
  dir = parent;
22284
22425
  }
@@ -22289,7 +22430,7 @@ var _execSeam2 = {
22289
22430
  const out2 = (0, import_child_process22.execFileSync)(file, args2, opts);
22290
22431
  return typeof out2 === "string" ? out2 : out2.toString("utf8");
22291
22432
  },
22292
- realpath: (p2) => fs53.realpathSync(p2)
22433
+ realpath: (p2) => fs54.realpathSync(p2)
22293
22434
  };
22294
22435
  function readOrigin(cwd) {
22295
22436
  try {
@@ -22318,7 +22459,7 @@ function deriveProjectIdentity(cwd = process.cwd()) {
22318
22459
  } catch {
22319
22460
  }
22320
22461
  const hash = crypto2.createHash("sha256").update(real).digest("hex");
22321
- return { projectKey: `path:${hash}`, projectLabel: path56.basename(real) || "project" };
22462
+ return { projectKey: `path:${hash}`, projectLabel: path57.basename(real) || "project" };
22322
22463
  }
22323
22464
 
22324
22465
  // src/beads/project-prefix.ts
@@ -22343,7 +22484,9 @@ var AGENT_SETUP_RECIPE = {
22343
22484
  // bd 1.0.5 has no Kimi recipe → skip (like coderabbit); beads still works,
22344
22485
  // the agent just isn't wired natively via `bd setup`.
22345
22486
  kimi: null,
22346
- coderabbit: null
22487
+ coderabbit: null,
22488
+ // bd 1.0.5 has no opencode recipe → skip; beads still works.
22489
+ opencode: null
22347
22490
  };
22348
22491
  var _provisionSeam = {
22349
22492
  install: installBd,
@@ -22363,17 +22506,17 @@ var _provisionSeam = {
22363
22506
  };
22364
22507
  var _linkSeam = {
22365
22508
  platform: () => process.platform,
22366
- homedir: () => os44.homedir(),
22509
+ homedir: () => os45.homedir(),
22367
22510
  isWritableDir: (dir) => {
22368
22511
  try {
22369
- fs54.accessSync(dir, fs54.constants.W_OK);
22512
+ fs55.accessSync(dir, fs55.constants.W_OK);
22370
22513
  return true;
22371
22514
  } catch {
22372
22515
  return false;
22373
22516
  }
22374
22517
  },
22375
22518
  ensureDir: (dir) => {
22376
- fs54.mkdirSync(dir, { recursive: true });
22519
+ fs55.mkdirSync(dir, { recursive: true });
22377
22520
  },
22378
22521
  /**
22379
22522
  * A directory to symlink `bd` into so the AGENT's shell + Claude Code's
@@ -22394,9 +22537,9 @@ var _linkSeam = {
22394
22537
  * which `linkBdOntoPath` creates if missing.
22395
22538
  */
22396
22539
  cliBinDir: () => {
22397
- const pathDirs = (process.env.PATH ?? "").split(path57.delimiter).filter(Boolean);
22540
+ const pathDirs = (process.env.PATH ?? "").split(path58.delimiter).filter(Boolean);
22398
22541
  const home = _linkSeam.homedir();
22399
- const localBin = home ? path57.join(home, ".local", "bin") : null;
22542
+ const localBin = home ? path58.join(home, ".local", "bin") : null;
22400
22543
  if (localBin) {
22401
22544
  try {
22402
22545
  _linkSeam.ensureDir(localBin);
@@ -22406,16 +22549,16 @@ var _linkSeam = {
22406
22549
  const candidates = [];
22407
22550
  if (localBin) candidates.push(localBin);
22408
22551
  try {
22409
- candidates.push(path57.dirname(process.execPath));
22552
+ candidates.push(path58.dirname(process.execPath));
22410
22553
  } catch {
22411
22554
  }
22412
22555
  candidates.push("/usr/local/bin");
22413
22556
  const entry = process.argv[1];
22414
22557
  if (entry) {
22415
22558
  try {
22416
- candidates.push(path57.dirname(fs54.realpathSync(entry)));
22559
+ candidates.push(path58.dirname(fs55.realpathSync(entry)));
22417
22560
  } catch {
22418
- candidates.push(path57.dirname(entry));
22561
+ candidates.push(path58.dirname(entry));
22419
22562
  }
22420
22563
  }
22421
22564
  const onPathWritable = candidates.find(
@@ -22427,20 +22570,20 @@ var _linkSeam = {
22427
22570
  /** Current symlink target at `linkPath`, or null when absent / not a link. */
22428
22571
  readlink: (linkPath) => {
22429
22572
  try {
22430
- return fs54.readlinkSync(linkPath);
22573
+ return fs55.readlinkSync(linkPath);
22431
22574
  } catch {
22432
22575
  return null;
22433
22576
  }
22434
22577
  },
22435
- unlink: (linkPath) => fs54.unlinkSync(linkPath),
22436
- symlink: (target, linkPath) => fs54.symlinkSync(target, linkPath)
22578
+ unlink: (linkPath) => fs55.unlinkSync(linkPath),
22579
+ symlink: (target, linkPath) => fs55.symlinkSync(target, linkPath)
22437
22580
  };
22438
22581
  function linkBdOntoPath(binaryPath) {
22439
22582
  if (_linkSeam.platform() === "win32") return;
22440
22583
  const binDir = _linkSeam.cliBinDir();
22441
22584
  if (!binDir) return;
22442
22585
  _linkSeam.ensureDir(binDir);
22443
- const linkPath = path57.join(binDir, "bd");
22586
+ const linkPath = path58.join(binDir, "bd");
22444
22587
  if (linkPath === binaryPath) return;
22445
22588
  const current = _linkSeam.readlink(linkPath);
22446
22589
  if (current === binaryPath) return;
@@ -22635,7 +22778,7 @@ function dedupeRecipes(agents) {
22635
22778
 
22636
22779
  // src/beads/watcher.ts
22637
22780
  var crypto4 = __toESM(require("crypto"));
22638
- var path58 = __toESM(require("path"));
22781
+ var path59 = __toESM(require("path"));
22639
22782
  var API_BASE6 = resolveApiBaseUrl();
22640
22783
  var DEBOUNCE_MS2 = 400;
22641
22784
  var ZERO_SUMMARY = {
@@ -22659,7 +22802,7 @@ var BeadsWatcher = class {
22659
22802
  constructor(opts) {
22660
22803
  this.opts = opts;
22661
22804
  this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
22662
- this.feedPath = opts.feedPath ?? path58.join(opts.cwd ?? process.cwd(), ".beads", "last-touched");
22805
+ this.feedPath = opts.feedPath ?? path59.join(opts.cwd ?? process.cwd(), ".beads", "last-touched");
22663
22806
  this.apiBase = opts.apiBaseUrl ?? API_BASE6;
22664
22807
  }
22665
22808
  opts;
@@ -23158,8 +23301,8 @@ function cleanupAttachmentTempFiles() {
23158
23301
  function saveFilesTemp(files) {
23159
23302
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
23160
23303
  const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
23161
- const tmpPath = path61.join(os48.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
23162
- fs57.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
23304
+ const tmpPath = path62.join(os49.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
23305
+ fs58.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
23163
23306
  pendingAttachmentFiles.add(tmpPath);
23164
23307
  return tmpPath;
23165
23308
  });
@@ -23371,9 +23514,9 @@ var listFiles = async (ctx, cmd, parsed) => {
23371
23514
  await ctx.relay.sendResult(cmd.id, "completed", result);
23372
23515
  };
23373
23516
  var envReadH = async (ctx, cmd) => {
23374
- const envPath = path61.join(process.cwd(), ".env");
23517
+ const envPath = path62.join(process.cwd(), ".env");
23375
23518
  try {
23376
- const raw = await fs57.promises.readFile(envPath, "utf8");
23519
+ const raw = await fs58.promises.readFile(envPath, "utf8");
23377
23520
  await ctx.relay.sendResult(cmd.id, "completed", {
23378
23521
  exists: true,
23379
23522
  vars: parseDotenv(raw)
@@ -23404,14 +23547,14 @@ var envWriteH = async (ctx, cmd, parsed) => {
23404
23547
  }
23405
23548
  seen.add(v.key);
23406
23549
  }
23407
- const envPath = path61.join(process.cwd(), ".env");
23408
- const tmpPath = path61.join(process.cwd(), ".env.codeam.tmp");
23550
+ const envPath = path62.join(process.cwd(), ".env");
23551
+ const tmpPath = path62.join(process.cwd(), ".env.codeam.tmp");
23409
23552
  try {
23410
- await fs57.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
23411
- await fs57.promises.rename(tmpPath, envPath);
23553
+ await fs58.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
23554
+ await fs58.promises.rename(tmpPath, envPath);
23412
23555
  await ctx.relay.sendResult(cmd.id, "completed", { ok: true, count: vars.length });
23413
23556
  } catch (err) {
23414
- await fs57.promises.rm(tmpPath, { force: true }).catch(() => void 0);
23557
+ await fs58.promises.rm(tmpPath, { force: true }).catch(() => void 0);
23415
23558
  await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
23416
23559
  }
23417
23560
  };
@@ -23460,7 +23603,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
23460
23603
  let configuredAgent = rawAgentId;
23461
23604
  if (!configuredAgent) {
23462
23605
  try {
23463
- const raw = JSON.parse(fs57.readFileSync(headroomConfigPath(), "utf8"));
23606
+ const raw = JSON.parse(fs58.readFileSync(headroomConfigPath(), "utf8"));
23464
23607
  configuredAgent = raw.agent ?? "";
23465
23608
  } catch {
23466
23609
  }
@@ -23494,7 +23637,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
23494
23637
  persist: persistHeadroomConfig,
23495
23638
  readEnabled: () => {
23496
23639
  try {
23497
- const raw = JSON.parse(fs57.readFileSync(headroomConfigPath(), "utf8"));
23640
+ const raw = JSON.parse(fs58.readFileSync(headroomConfigPath(), "utf8"));
23498
23641
  return raw.enabled === true;
23499
23642
  } catch {
23500
23643
  return false;
@@ -23751,7 +23894,7 @@ var vcsAgentReviewH = async (ctx, cmd, parsed) => {
23751
23894
  });
23752
23895
  const token = ctx.pluginAuthToken;
23753
23896
  void (async () => {
23754
- const os59 = createOsStrategy();
23897
+ const os60 = createOsStrategy();
23755
23898
  try {
23756
23899
  const report = await reviewPullRequest(
23757
23900
  {
@@ -23760,7 +23903,7 @@ var vcsAgentReviewH = async (ctx, cmd, parsed) => {
23760
23903
  baseBranch: parsed.baseBranch
23761
23904
  },
23762
23905
  {
23763
- runReview: (input) => new CoderabbitRuntimeStrategy(os59).runOneShot(input),
23906
+ runReview: (input) => new CoderabbitRuntimeStrategy(os60).runOneShot(input),
23764
23907
  runGh: (args2) => defaultRunGh(args2),
23765
23908
  postReport: async (r) => {
23766
23909
  if (!token) return;
@@ -23798,7 +23941,7 @@ var headroomBudgetH = async (ctx, cmd) => {
23798
23941
  }
23799
23942
  let headroomActive = false;
23800
23943
  try {
23801
- const raw = JSON.parse(fs57.readFileSync(headroomConfigPath(), "utf8"));
23944
+ const raw = JSON.parse(fs58.readFileSync(headroomConfigPath(), "utf8"));
23802
23945
  headroomActive = raw.enabled === true;
23803
23946
  } catch {
23804
23947
  }
@@ -23808,7 +23951,7 @@ var headroomBudgetH = async (ctx, cmd) => {
23808
23951
  }
23809
23952
  let existingConfig = { enabled: true };
23810
23953
  try {
23811
- existingConfig = JSON.parse(fs57.readFileSync(headroomConfigPath(), "utf8"));
23954
+ existingConfig = JSON.parse(fs58.readFileSync(headroomConfigPath(), "utf8"));
23812
23955
  } catch {
23813
23956
  }
23814
23957
  if (payload.budgetEnabled && payload.budgetUsd != null) {
@@ -23921,9 +24064,9 @@ var CLI_UPDATE_MAX_ATTEMPTS = 3;
23921
24064
  function buildNpmInstallInvocation(opts) {
23922
24065
  const entryScript = opts?.entryScript ?? process.argv[1] ?? "";
23923
24066
  const execPath = opts?.execPath ?? process.execPath;
23924
- const exists2 = opts?.existsSync ?? fs57.existsSync;
24067
+ const exists2 = opts?.existsSync ?? fs58.existsSync;
23925
24068
  const platform3 = opts?.platform ?? process.platform;
23926
- const p2 = platform3 === "win32" ? path61.win32 : path61.posix;
24069
+ const p2 = platform3 === "win32" ? path62.win32 : path62.posix;
23927
24070
  const normalized = entryScript.split(/[\\/]/).join("/");
23928
24071
  const marker = "/lib/node_modules/codeam-cli/";
23929
24072
  const markerIdx = normalized.indexOf(marker);
@@ -24786,11 +24929,11 @@ function resolveTokenValue(args2) {
24786
24929
  }
24787
24930
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
24788
24931
  if (fileFlag) {
24789
- const path79 = fileFlag.slice("--token-file=".length);
24932
+ const path80 = fileFlag.slice("--token-file=".length);
24790
24933
  try {
24791
- const content = fs58.readFileSync(path79, "utf8").trim();
24792
- if (content.length === 0) fail(`--token-file ${path79} is empty`);
24793
- rmIfExistsQuiet(path79);
24934
+ const content = fs59.readFileSync(path80, "utf8").trim();
24935
+ if (content.length === 0) fail(`--token-file ${path80} is empty`);
24936
+ rmIfExistsQuiet(path80);
24794
24937
  return content;
24795
24938
  } catch (err) {
24796
24939
  fail(`Could not read --token-file: ${err.message}`);
@@ -24819,7 +24962,7 @@ async function claimOnce(token, pluginId, pluginSecretHash) {
24819
24962
  pluginId,
24820
24963
  ideName: "codeam-cli (codespace)",
24821
24964
  ideVersion: process.env.npm_package_version ?? "unknown",
24822
- hostname: os49.hostname(),
24965
+ hostname: os50.hostname(),
24823
24966
  codespaceName: process.env.CODESPACE_NAME ?? "",
24824
24967
  // Current git branch of the codespace's working directory, so the
24825
24968
  // backend can populate `PairedSession.branch` for the codespace pair.
@@ -24880,7 +25023,7 @@ async function claim(token, pluginId, pluginSecretHash) {
24880
25023
  }
24881
25024
  }
24882
25025
  function pairAutoLockPath() {
24883
- return path62.join(os49.homedir(), ".codeam", "pair-auto.lock");
25026
+ return path63.join(os50.homedir(), ".codeam", "pair-auto.lock");
24884
25027
  }
24885
25028
  function isLivePairAuto(pid) {
24886
25029
  if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
@@ -24890,7 +25033,7 @@ function isLivePairAuto(pid) {
24890
25033
  if (e.code !== "EPERM") return false;
24891
25034
  }
24892
25035
  try {
24893
- return fs58.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
25036
+ return fs59.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
24894
25037
  } catch {
24895
25038
  return true;
24896
25039
  }
@@ -24900,24 +25043,24 @@ function isLiveCodeam(pid) {
24900
25043
  }
24901
25044
  function daemonLockPath(sessionId) {
24902
25045
  const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
24903
- return path62.join(os49.homedir(), ".codeam", `daemon-${safe}.lock`);
25046
+ return path63.join(os50.homedir(), ".codeam", `daemon-${safe}.lock`);
24904
25047
  }
24905
25048
  function acquireDaemonLock(sessionId) {
24906
25049
  const lockPath = daemonLockPath(sessionId);
24907
25050
  try {
24908
- fs58.mkdirSync(path62.dirname(lockPath), { recursive: true });
25051
+ fs59.mkdirSync(path63.dirname(lockPath), { recursive: true });
24909
25052
  try {
24910
- fs58.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
25053
+ fs59.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
24911
25054
  } catch (e) {
24912
25055
  if (e.code !== "EEXIST") throw e;
24913
- const holder = Number(fs58.readFileSync(lockPath, "utf8").trim());
25056
+ const holder = Number(fs59.readFileSync(lockPath, "utf8").trim());
24914
25057
  if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
24915
- fs58.writeFileSync(lockPath, String(process.pid));
25058
+ fs59.writeFileSync(lockPath, String(process.pid));
24916
25059
  }
24917
25060
  const release3 = () => {
24918
25061
  try {
24919
- if (fs58.existsSync(lockPath) && Number(fs58.readFileSync(lockPath, "utf8").trim()) === process.pid) {
24920
- fs58.unlinkSync(lockPath);
25062
+ if (fs59.existsSync(lockPath) && Number(fs59.readFileSync(lockPath, "utf8").trim()) === process.pid) {
25063
+ fs59.unlinkSync(lockPath);
24921
25064
  }
24922
25065
  } catch {
24923
25066
  }
@@ -24939,19 +25082,19 @@ function acquireDaemonLock(sessionId) {
24939
25082
  function acquireSingletonLock() {
24940
25083
  const lockPath = pairAutoLockPath();
24941
25084
  try {
24942
- fs58.mkdirSync(path62.dirname(lockPath), { recursive: true });
25085
+ fs59.mkdirSync(path63.dirname(lockPath), { recursive: true });
24943
25086
  try {
24944
- fs58.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
25087
+ fs59.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
24945
25088
  } catch (e) {
24946
25089
  if (e.code !== "EEXIST") throw e;
24947
- const holder = Number(fs58.readFileSync(lockPath, "utf8").trim());
25090
+ const holder = Number(fs59.readFileSync(lockPath, "utf8").trim());
24948
25091
  if (isLivePairAuto(holder)) return false;
24949
- fs58.writeFileSync(lockPath, String(process.pid));
25092
+ fs59.writeFileSync(lockPath, String(process.pid));
24950
25093
  }
24951
25094
  process.once("exit", () => {
24952
25095
  try {
24953
- if (fs58.existsSync(lockPath) && Number(fs58.readFileSync(lockPath, "utf8").trim()) === process.pid) {
24954
- fs58.unlinkSync(lockPath);
25096
+ if (fs59.existsSync(lockPath) && Number(fs59.readFileSync(lockPath, "utf8").trim()) === process.pid) {
25097
+ fs59.unlinkSync(lockPath);
24955
25098
  }
24956
25099
  } catch {
24957
25100
  }
@@ -25035,7 +25178,7 @@ async function pairAuto(args2) {
25035
25178
  }
25036
25179
 
25037
25180
  // src/services/headroom/wrap-launch.ts
25038
- var import_node_child_process25 = require("child_process");
25181
+ var import_node_child_process26 = require("child_process");
25039
25182
  function wrapWithHeadroom(launch, opts) {
25040
25183
  if (!opts.enabled || !opts.headroomPresent) return launch;
25041
25184
  return {
@@ -25048,7 +25191,7 @@ var _present;
25048
25191
  function headroomPresent() {
25049
25192
  if (_present !== void 0) return Promise.resolve(_present);
25050
25193
  return new Promise((resolve8) => {
25051
- (0, import_node_child_process25.execFile)("headroom", ["--version"], (err) => {
25194
+ (0, import_node_child_process26.execFile)("headroom", ["--version"], (err) => {
25052
25195
  _present = !err;
25053
25196
  resolve8(_present);
25054
25197
  });
@@ -25398,11 +25541,11 @@ var AgentService = class _AgentService {
25398
25541
  };
25399
25542
 
25400
25543
  // src/agents/acp/adapters.ts
25401
- var path64 = __toESM(require("path"));
25544
+ var path65 = __toESM(require("path"));
25402
25545
 
25403
25546
  // src/agents/acp/agent-binary.ts
25404
25547
  var import_fs4 = __toESM(require("fs"));
25405
- var import_os10 = __toESM(require("os"));
25548
+ var import_os11 = __toESM(require("os"));
25406
25549
  var import_path8 = __toESM(require("path"));
25407
25550
  var import_child_process26 = require("child_process");
25408
25551
  function currentPlatformKey() {
@@ -25431,14 +25574,14 @@ function defaultSdkDir() {
25431
25574
  return resolveSdkDirViaRequire();
25432
25575
  }
25433
25576
  function resolveClaudeNativeBinary(deps = {}) {
25434
- const existsSync27 = deps.existsSync ?? import_fs4.default.existsSync;
25577
+ const existsSync28 = deps.existsSync ?? import_fs4.default.existsSync;
25435
25578
  const platformKey = deps.platformKey ?? currentPlatformKey();
25436
25579
  const sdkDir = deps.sdkDir !== void 0 ? deps.sdkDir : defaultSdkDir();
25437
25580
  if (!sdkDir) return null;
25438
25581
  const scopeDir = import_path8.default.dirname(sdkDir);
25439
25582
  const binName = platformKey.startsWith("win32-") ? "claude.exe" : "claude";
25440
25583
  const candidate = import_path8.default.join(scopeDir, `claude-agent-sdk-${platformKey}`, binName);
25441
- return existsSync27(candidate) ? candidate : null;
25584
+ return existsSync28(candidate) ? candidate : null;
25442
25585
  }
25443
25586
  var realSleep = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
25444
25587
  async function waitForClaudeNativeBinary(opts = {}) {
@@ -25489,18 +25632,18 @@ async function waitForCommandOnPath(cmd, opts = {}) {
25489
25632
  return check();
25490
25633
  }
25491
25634
  function resolveCursorAgentBinary(deps = {}) {
25492
- const existsSync27 = deps.existsSync ?? import_fs4.default.existsSync;
25635
+ const existsSync28 = deps.existsSync ?? import_fs4.default.existsSync;
25493
25636
  const platform3 = deps.platform ?? process.platform;
25494
25637
  const env = deps.env ?? process.env;
25495
25638
  if (platform3 === "win32") {
25496
25639
  const localAppData = env.LOCALAPPDATA;
25497
25640
  if (!localAppData) return null;
25498
25641
  const exe = import_path8.default.win32.join(localAppData, "cursor-agent", "cursor-agent.exe");
25499
- return existsSync27(exe) ? exe : null;
25642
+ return existsSync28(exe) ? exe : null;
25500
25643
  }
25501
- const home = deps.homedir ?? import_os10.default.homedir();
25644
+ const home = deps.homedir ?? import_os11.default.homedir();
25502
25645
  const unix = import_path8.default.posix.join(home, ".local", "bin", "cursor-agent");
25503
- return existsSync27(unix) ? unix : null;
25646
+ return existsSync28(unix) ? unix : null;
25504
25647
  }
25505
25648
  async function waitForCursorAgent(opts = {}) {
25506
25649
  const timeoutMs = opts.timeoutMs ?? 18e4;
@@ -25573,7 +25716,7 @@ async function waitForAdapterModuleGraph(command2, args2, opts = {}) {
25573
25716
  }
25574
25717
 
25575
25718
  // src/agents/kimi/installer.ts
25576
- var import_node_child_process26 = require("child_process");
25719
+ var import_node_child_process27 = require("child_process");
25577
25720
  var import_node_os11 = require("os");
25578
25721
  var import_node_path9 = require("path");
25579
25722
  var INSTALL_URL2 = "https://code.kimi.com/kimi-code/install.sh";
@@ -25581,7 +25724,7 @@ function kimiBinDir() {
25581
25724
  return (0, import_node_path9.join)(process.env.KIMI_CODE_HOME || (0, import_node_path9.join)((0, import_node_os11.homedir)(), ".kimi-code"), "bin");
25582
25725
  }
25583
25726
  function kimiRuns() {
25584
- const r = (0, import_node_child_process26.spawnSync)("kimi", ["--version"], { stdio: "ignore", timeout: 15e3 });
25727
+ const r = (0, import_node_child_process27.spawnSync)("kimi", ["--version"], { stdio: "ignore", timeout: 15e3 });
25585
25728
  return !r.error && r.status === 0;
25586
25729
  }
25587
25730
  function augmentPath2() {
@@ -25591,7 +25734,7 @@ function augmentPath2() {
25591
25734
  }
25592
25735
  async function runInstaller2() {
25593
25736
  return new Promise((resolve8) => {
25594
- const proc = (0, import_node_child_process26.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL2} | bash`], { stdio: "inherit" });
25737
+ const proc = (0, import_node_child_process27.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL2} | bash`], { stdio: "inherit" });
25595
25738
  proc.on("close", (code) => resolve8(code === 0));
25596
25739
  proc.on("error", () => resolve8(false));
25597
25740
  });
@@ -25624,6 +25767,53 @@ async function ensureKimiInstalled() {
25624
25767
  return kimiRuns();
25625
25768
  }
25626
25769
 
25770
+ // src/agents/opencode/installer.ts
25771
+ var import_node_child_process28 = require("child_process");
25772
+ var import_node_os12 = require("os");
25773
+ var import_node_path10 = require("path");
25774
+ var INSTALL_URL3 = "https://opencode.ai/install";
25775
+ function opencodeBinDir() {
25776
+ return (0, import_node_path10.join)(process.env.OPENCODE_HOME || (0, import_node_path10.join)((0, import_node_os12.homedir)(), ".opencode"), "bin");
25777
+ }
25778
+ function opencodeRuns() {
25779
+ const r = (0, import_node_child_process28.spawnSync)("opencode", ["--version"], { stdio: "ignore", timeout: 15e3 });
25780
+ return !r.error && r.status === 0;
25781
+ }
25782
+ function augmentPath3() {
25783
+ const dir = opencodeBinDir();
25784
+ const parts = (process.env.PATH ?? "").split(":");
25785
+ if (!parts.includes(dir)) process.env.PATH = `${dir}:${process.env.PATH ?? ""}`;
25786
+ }
25787
+ async function runInstaller3() {
25788
+ return new Promise((resolve8) => {
25789
+ const proc = (0, import_node_child_process28.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL3} | bash`], { stdio: "inherit" });
25790
+ proc.on("close", (code) => resolve8(code === 0));
25791
+ proc.on("error", () => resolve8(false));
25792
+ });
25793
+ }
25794
+ async function ensureOpencodeInstalled() {
25795
+ augmentPath3();
25796
+ if (opencodeRuns()) return true;
25797
+ if (process.platform === "win32") {
25798
+ console.error(
25799
+ `
25800
+ \u2717 opencode on Windows requires WSL.
25801
+ Install it inside WSL (curl -fsSL ${INSTALL_URL3} | bash)
25802
+ then re-run \`codeam pair\`.
25803
+ `
25804
+ );
25805
+ return false;
25806
+ }
25807
+ console.log("\n opencode not found \u2014 installing via the official script\u2026\n");
25808
+ const ok = await runInstaller3();
25809
+ augmentPath3();
25810
+ if (!ok) {
25811
+ log.warn("opencode", "installer failed \u2014 opencode will be reported as not installed");
25812
+ return false;
25813
+ }
25814
+ return opencodeRuns();
25815
+ }
25816
+
25627
25817
  // src/baton/gate.ts
25628
25818
  function runtimeSupportsBaton(runtime) {
25629
25819
  return typeof runtime.resolveHistoryFile === "function";
@@ -25641,13 +25831,13 @@ function resolveBin(pkgName, binName) {
25641
25831
  try {
25642
25832
  const manifestPath = require_.resolve(`${pkgName}/package.json`);
25643
25833
  const manifest = require_(`${pkgName}/package.json`);
25644
- const pkgDir = path64.dirname(manifestPath);
25834
+ const pkgDir = path65.dirname(manifestPath);
25645
25835
  const bin = manifest.bin;
25646
25836
  if (!bin) return null;
25647
- if (typeof bin === "string") return path64.resolve(pkgDir, bin);
25837
+ if (typeof bin === "string") return path65.resolve(pkgDir, bin);
25648
25838
  const target = binName ?? Object.keys(bin)[0];
25649
25839
  if (!target || !bin[target]) return null;
25650
- return path64.resolve(pkgDir, bin[target]);
25840
+ return path65.resolve(pkgDir, bin[target]);
25651
25841
  } catch {
25652
25842
  return null;
25653
25843
  }
@@ -25737,6 +25927,21 @@ var REGISTRY = {
25737
25927
  if (isLocalSession()) await ensureKimiInstalled();
25738
25928
  return waitForCommandOnPath("kimi", o);
25739
25929
  }
25930
+ }),
25931
+ // opencode speaks ACP natively via `opencode acp` — a stdio JSON-RPC server.
25932
+ // No npm adapter, just the user-installed `opencode` binary on PATH (baked in
25933
+ // the box image; provisioned on codespaces; installed on demand for a LOCAL
25934
+ // pair). Same {@link AdapterSpec} shape as gemini/cursor/kimi. Auth (the
25935
+ // ~/.local/share/opencode/auth.json login-state file) reaches opencode because
25936
+ // the ACP client spawns the adapter with `env: { ...process.env, ...extraEnv }`.
25937
+ opencode: () => ({
25938
+ command: "opencode",
25939
+ args: ["acp"],
25940
+ requiresAgentBinary: "opencode",
25941
+ waitForBinary: async (o) => {
25942
+ if (isLocalSession()) await ensureOpencodeInstalled();
25943
+ return waitForCommandOnPath("opencode", o);
25944
+ }
25740
25945
  })
25741
25946
  };
25742
25947
  var resolvedAdapterCache = /* @__PURE__ */ new Map();
@@ -25782,9 +25987,9 @@ async function resolveAcpAdapterWithRetry(agent, opts = {}) {
25782
25987
  var import_node_crypto11 = require("crypto");
25783
25988
 
25784
25989
  // src/services/history.service.ts
25785
- var fs60 = __toESM(require("fs"));
25786
- var path65 = __toESM(require("path"));
25787
- var os51 = __toESM(require("os"));
25990
+ var fs61 = __toESM(require("fs"));
25991
+ var path66 = __toESM(require("path"));
25992
+ var os52 = __toESM(require("os"));
25788
25993
  var https7 = __toESM(require("https"));
25789
25994
  var http6 = __toESM(require("http"));
25790
25995
  var import_zod2 = require("zod");
@@ -25811,7 +26016,7 @@ function parseJsonl(filePath) {
25811
26016
  const messages = [];
25812
26017
  let raw;
25813
26018
  try {
25814
- raw = fs60.readFileSync(filePath, "utf8");
26019
+ raw = fs61.readFileSync(filePath, "utf8");
25815
26020
  } catch (err) {
25816
26021
  if (err.code !== "ENOENT") {
25817
26022
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -25952,7 +26157,7 @@ var HistoryService = class _HistoryService {
25952
26157
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
25953
26158
  }
25954
26159
  get projectDir() {
25955
- return this.runtime.resolveHistoryDir(this.cwd) ?? path65.join(os51.homedir(), ".claude", "projects", encodeCwd(this.cwd));
26160
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path66.join(os52.homedir(), ".claude", "projects", encodeCwd(this.cwd));
25956
26161
  }
25957
26162
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
25958
26163
  setCurrentConversationId(id) {
@@ -25964,7 +26169,7 @@ var HistoryService = class _HistoryService {
25964
26169
  /** Return the current message count in the active conversation. */
25965
26170
  getCurrentMessageCount() {
25966
26171
  if (!this.currentConversationId) return 0;
25967
- const filePath = path65.join(this.projectDir, `${this.currentConversationId}.jsonl`);
26172
+ const filePath = path66.join(this.projectDir, `${this.currentConversationId}.jsonl`);
25968
26173
  return parseJsonl(filePath).length;
25969
26174
  }
25970
26175
  /**
@@ -25975,7 +26180,7 @@ var HistoryService = class _HistoryService {
25975
26180
  const deadline = Date.now() + timeoutMs;
25976
26181
  while (Date.now() < deadline) {
25977
26182
  if (!this.currentConversationId) return null;
25978
- const filePath = path65.join(this.projectDir, `${this.currentConversationId}.jsonl`);
26183
+ const filePath = path66.join(this.projectDir, `${this.currentConversationId}.jsonl`);
25979
26184
  const messages = parseJsonl(filePath);
25980
26185
  if (messages.length > previousCount) {
25981
26186
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -26001,16 +26206,16 @@ var HistoryService = class _HistoryService {
26001
26206
  const dir = this.projectDir;
26002
26207
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
26003
26208
  try {
26004
- const files = fs60.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
26209
+ const files = fs61.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
26005
26210
  try {
26006
- const stat3 = fs60.statSync(path65.join(dir, e.name));
26211
+ const stat3 = fs61.statSync(path66.join(dir, e.name));
26007
26212
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
26008
26213
  } catch {
26009
26214
  return { name: e.name, mtime: 0, birthtime: 0 };
26010
26215
  }
26011
26216
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
26012
26217
  if (files.length > 0) {
26013
- this.currentConversationId = path65.basename(files[0].name, ".jsonl");
26218
+ this.currentConversationId = path66.basename(files[0].name, ".jsonl");
26014
26219
  }
26015
26220
  } catch {
26016
26221
  }
@@ -26044,13 +26249,13 @@ var HistoryService = class _HistoryService {
26044
26249
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
26045
26250
  let entries;
26046
26251
  try {
26047
- entries = fs60.readdirSync(dir, { withFileTypes: true });
26252
+ entries = fs61.readdirSync(dir, { withFileTypes: true });
26048
26253
  } catch {
26049
26254
  return null;
26050
26255
  }
26051
26256
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
26052
26257
  try {
26053
- const stat3 = fs60.statSync(path65.join(dir, e.name));
26258
+ const stat3 = fs61.statSync(path66.join(dir, e.name));
26054
26259
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
26055
26260
  } catch {
26056
26261
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -26059,12 +26264,12 @@ var HistoryService = class _HistoryService {
26059
26264
  if (files.length === 0) return null;
26060
26265
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
26061
26266
  if (!files.some((f) => f.name === targetFile)) return null;
26062
- return this.extractUsageFromFile(path65.join(dir, targetFile));
26267
+ return this.extractUsageFromFile(path66.join(dir, targetFile));
26063
26268
  }
26064
26269
  extractUsageFromFile(filePath) {
26065
26270
  let raw;
26066
26271
  try {
26067
- raw = fs60.readFileSync(filePath, "utf8");
26272
+ raw = fs61.readFileSync(filePath, "utf8");
26068
26273
  } catch {
26069
26274
  return null;
26070
26275
  }
@@ -26109,9 +26314,9 @@ var HistoryService = class _HistoryService {
26109
26314
  let totalCost = 0;
26110
26315
  let files;
26111
26316
  try {
26112
- files = fs60.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
26317
+ files = fs61.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
26113
26318
  try {
26114
- return fs60.statSync(path65.join(projectDir, f)).mtimeMs >= monthStartMs;
26319
+ return fs61.statSync(path66.join(projectDir, f)).mtimeMs >= monthStartMs;
26115
26320
  } catch {
26116
26321
  return false;
26117
26322
  }
@@ -26122,7 +26327,7 @@ var HistoryService = class _HistoryService {
26122
26327
  for (const file of files) {
26123
26328
  let raw;
26124
26329
  try {
26125
- raw = fs60.readFileSync(path65.join(projectDir, file), "utf8");
26330
+ raw = fs61.readFileSync(path66.join(projectDir, file), "utf8");
26126
26331
  } catch {
26127
26332
  continue;
26128
26333
  }
@@ -26201,7 +26406,7 @@ var HistoryService = class _HistoryService {
26201
26406
  if (this.runtime.resolveHistoryFile) {
26202
26407
  return this.runtime.resolveHistoryFile(this.cwd, sessionId);
26203
26408
  }
26204
- return path65.join(this.projectDir, `${sessionId}.jsonl`);
26409
+ return path66.join(this.projectDir, `${sessionId}.jsonl`);
26205
26410
  }
26206
26411
  /**
26207
26412
  * Parse a conversation's messages from disk, agent-aware. Claude uses the
@@ -26235,7 +26440,7 @@ var HistoryService = class _HistoryService {
26235
26440
  };
26236
26441
  });
26237
26442
  }
26238
- return parseJsonl(path65.join(this.projectDir, `${sessionId}.jsonl`));
26443
+ return parseJsonl(path66.join(this.projectDir, `${sessionId}.jsonl`));
26239
26444
  }
26240
26445
  async loadConversation(sessionId) {
26241
26446
  const messages = this.readConversation(sessionId);
@@ -26303,7 +26508,7 @@ var HistoryService = class _HistoryService {
26303
26508
  if (!filePath) return false;
26304
26509
  let mtimeMs;
26305
26510
  try {
26306
- mtimeMs = fs60.statSync(filePath).mtimeMs;
26511
+ mtimeMs = fs61.statSync(filePath).mtimeMs;
26307
26512
  } catch {
26308
26513
  return false;
26309
26514
  }
@@ -26377,11 +26582,11 @@ var HistoryService = class _HistoryService {
26377
26582
  };
26378
26583
 
26379
26584
  // src/agents/acp/client.ts
26380
- var import_node_child_process27 = require("child_process");
26381
- var fs61 = __toESM(require("fs/promises"));
26585
+ var import_node_child_process29 = require("child_process");
26586
+ var fs62 = __toESM(require("fs/promises"));
26382
26587
  var fsSync = __toESM(require("fs"));
26383
- var os52 = __toESM(require("os"));
26384
- var path66 = __toESM(require("path"));
26588
+ var os53 = __toESM(require("os"));
26589
+ var path67 = __toESM(require("path"));
26385
26590
  var import_node_stream = require("stream");
26386
26591
 
26387
26592
  // ../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
@@ -30583,7 +30788,7 @@ var AcpClient = class {
30583
30788
  "acpClient",
30584
30789
  `spawn cmd=${adapter.command} args=[${adapter.args.join(",")}] cwd=${cwd}`
30585
30790
  );
30586
- const child = (0, import_node_child_process27.spawn)(adapter.command, adapter.args, {
30791
+ const child = (0, import_node_child_process29.spawn)(adapter.command, adapter.args, {
30587
30792
  cwd,
30588
30793
  // extraEnv (e.g. CLAUDE_CODE_DISABLE_1M_CONTEXT=1 on an on-demand
30589
30794
  // re-spawn) layers over process.env; PATH stays last so the augmented
@@ -31166,7 +31371,7 @@ var AcpClient = class {
31166
31371
  },
31167
31372
  readTextFile: async (params) => {
31168
31373
  try {
31169
- const content = await fs61.readFile(params.path, "utf8");
31374
+ const content = await fs62.readFile(params.path, "utf8");
31170
31375
  return applyLineRange(content, params.line ?? null, params.limit ?? null);
31171
31376
  } catch (err) {
31172
31377
  const code = err.code;
@@ -31186,7 +31391,7 @@ var AcpClient = class {
31186
31391
  },
31187
31392
  writeTextFile: async (params) => {
31188
31393
  try {
31189
- await fs61.writeFile(params.path, params.content, "utf8");
31394
+ await fs62.writeFile(params.path, params.content, "utf8");
31190
31395
  return {};
31191
31396
  } catch (err) {
31192
31397
  const code = err.code;
@@ -31246,29 +31451,29 @@ function applyLineRange(content, line, limit) {
31246
31451
  return { content: lines.slice(start2, end).join("\n") };
31247
31452
  }
31248
31453
  function knownAgentBinaryDirs() {
31249
- const home = os52.homedir();
31454
+ const home = os53.homedir();
31250
31455
  const out2 = [];
31251
31456
  out2.push("/tmp/codeam-node20/bin");
31252
31457
  for (const root of [
31253
31458
  "/usr/local/share/nvm/versions/node",
31254
- path66.join(home, ".nvm/versions/node")
31459
+ path67.join(home, ".nvm/versions/node")
31255
31460
  ]) {
31256
31461
  try {
31257
31462
  for (const child of fsSync.readdirSync(root)) {
31258
- out2.push(path66.join(root, child, "bin"));
31463
+ out2.push(path67.join(root, child, "bin"));
31259
31464
  }
31260
31465
  } catch {
31261
31466
  }
31262
31467
  }
31263
- out2.push(path66.join(home, ".volta/bin"));
31468
+ out2.push(path67.join(home, ".volta/bin"));
31264
31469
  out2.push("/usr/local/bin");
31265
31470
  out2.push("/usr/bin");
31266
- out2.push(path66.join(home, ".local/bin"));
31267
- out2.push(path66.join(home, "bin"));
31471
+ out2.push(path67.join(home, ".local/bin"));
31472
+ out2.push(path67.join(home, "bin"));
31268
31473
  if (process.platform === "win32") {
31269
31474
  const { LOCALAPPDATA, APPDATA } = process.env;
31270
- if (LOCALAPPDATA) out2.push(path66.join(LOCALAPPDATA, "cursor-agent"));
31271
- if (APPDATA) out2.push(path66.join(APPDATA, "npm"));
31475
+ if (LOCALAPPDATA) out2.push(path67.join(LOCALAPPDATA, "cursor-agent"));
31476
+ if (APPDATA) out2.push(path67.join(APPDATA, "npm"));
31272
31477
  }
31273
31478
  return out2.filter((p2) => {
31274
31479
  try {
@@ -31280,7 +31485,7 @@ function knownAgentBinaryDirs() {
31280
31485
  }
31281
31486
  function expandPathForAgentBinaries(existingPath) {
31282
31487
  const existing = new Set(
31283
- existingPath.split(path66.delimiter).filter((p2) => p2.length > 0)
31488
+ existingPath.split(path67.delimiter).filter((p2) => p2.length > 0)
31284
31489
  );
31285
31490
  const additions = [];
31286
31491
  for (const dir of knownAgentBinaryDirs()) {
@@ -31290,7 +31495,7 @@ function expandPathForAgentBinaries(existingPath) {
31290
31495
  }
31291
31496
  }
31292
31497
  if (additions.length === 0) return existingPath;
31293
- return [...additions, existingPath].filter((p2) => p2.length > 0).join(path66.delimiter);
31498
+ return [...additions, existingPath].filter((p2) => p2.length > 0).join(path67.delimiter);
31294
31499
  }
31295
31500
 
31296
31501
  // src/agents/acp/headroom-budget-proxy.ts
@@ -31301,12 +31506,12 @@ function buildRelaunchProxyEnv(baseEnv) {
31301
31506
  return env;
31302
31507
  }
31303
31508
  var relaunchProxyWithoutBudget = async () => {
31304
- const { spawn: spawn42 } = await import("child_process");
31509
+ const { spawn: spawn44 } = await import("child_process");
31305
31510
  killHeadroomProxy();
31306
31511
  await new Promise((r) => setTimeout(r, 500));
31307
31512
  const proxyEnv = buildRelaunchProxyEnv(process.env);
31308
31513
  try {
31309
- const proxy = spawn42(
31514
+ const proxy = spawn44(
31310
31515
  "headroom",
31311
31516
  ["proxy", "--port", "8787"],
31312
31517
  { stdio: "ignore", detached: true, env: proxyEnv }
@@ -31772,15 +31977,15 @@ function commonPrefixLength(a, b) {
31772
31977
 
31773
31978
  // src/agents/acp/onboarding.ts
31774
31979
  var import_child_process27 = require("child_process");
31775
- var fs62 = __toESM(require("fs"));
31776
- var os53 = __toESM(require("os"));
31777
- var path67 = __toESM(require("path"));
31980
+ var fs63 = __toESM(require("fs"));
31981
+ var os54 = __toESM(require("os"));
31982
+ var path68 = __toESM(require("path"));
31778
31983
  var _onboardingSeam = {
31779
- markerPath: (sessionId) => path67.join(os53.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
31780
- exists: (p2) => fs62.existsSync(p2),
31984
+ markerPath: (sessionId) => path68.join(os54.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
31985
+ exists: (p2) => fs63.existsSync(p2),
31781
31986
  write: (p2) => {
31782
- fs62.mkdirSync(path67.dirname(p2), { recursive: true });
31783
- fs62.writeFileSync(p2, "");
31987
+ fs63.mkdirSync(path68.dirname(p2), { recursive: true });
31988
+ fs63.writeFileSync(p2, "");
31784
31989
  },
31785
31990
  disabled: () => {
31786
31991
  const v = process.env.CODEAM_ONBOARDING_DISABLED;
@@ -31817,7 +32022,7 @@ function resolveRepoName(cwd) {
31817
32022
  if (name) return name;
31818
32023
  }
31819
32024
  }
31820
- const base = path67.basename(cwd || "");
32025
+ const base = path68.basename(cwd || "");
31821
32026
  if (base && !isUuid(base)) return base;
31822
32027
  return "this project";
31823
32028
  }
@@ -32069,13 +32274,13 @@ var import_crypto5 = require("crypto");
32069
32274
 
32070
32275
  // src/services/turn-files/git-changeset.ts
32071
32276
  var import_child_process28 = require("child_process");
32072
- var fs64 = __toESM(require("fs/promises"));
32073
- var path69 = __toESM(require("path"));
32277
+ var fs65 = __toESM(require("fs/promises"));
32278
+ var path70 = __toESM(require("path"));
32074
32279
 
32075
32280
  // src/services/turn-files/review-ignore.ts
32076
32281
  var import_ignore2 = __toESM(require("ignore"));
32077
- var fs63 = __toESM(require("fs"));
32078
- var path68 = __toESM(require("path"));
32282
+ var fs64 = __toESM(require("fs"));
32283
+ var path69 = __toESM(require("path"));
32079
32284
  var CURATED_REVIEW_IGNORE = [
32080
32285
  // Google Cloud SDK (the incident) — installs a huge python tree.
32081
32286
  "google-cloud-sdk/",
@@ -32114,7 +32319,7 @@ var CURATED_REVIEW_IGNORE = [
32114
32319
  function makeReviewIgnore(repoRoot) {
32115
32320
  const ig = (0, import_ignore2.default)().add(CURATED_REVIEW_IGNORE);
32116
32321
  try {
32117
- const custom = fs63.readFileSync(path68.join(repoRoot, ".codeam", "reviewignore"), "utf8");
32322
+ const custom = fs64.readFileSync(path69.join(repoRoot, ".codeam", "reviewignore"), "utf8");
32118
32323
  ig.add(custom);
32119
32324
  } catch {
32120
32325
  }
@@ -32159,7 +32364,7 @@ async function collectRepoChangeset(opts) {
32159
32364
  let stats;
32160
32365
  if (!truncated && row.fileStatus === "added" && numstatEntry === void 0) {
32161
32366
  const lineCount = await readUntrackedLineCount(
32162
- path69.join(opts.repoRoot, row.filePath)
32367
+ path70.join(opts.repoRoot, row.filePath)
32163
32368
  );
32164
32369
  stats = { added: lineCount, removed: 0 };
32165
32370
  } else {
@@ -32190,7 +32395,7 @@ function readUntrackedLineCount(absPath) {
32190
32395
  }
32191
32396
  async function defaultReadUntrackedLineCount(absPath) {
32192
32397
  try {
32193
- const content = await fs64.readFile(absPath, "utf8");
32398
+ const content = await fs65.readFile(absPath, "utf8");
32194
32399
  let count = 0;
32195
32400
  let pos = -1;
32196
32401
  while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
@@ -32282,7 +32487,7 @@ function defaultRunGit(cwd, args2) {
32282
32487
  });
32283
32488
  }
32284
32489
  async function discoverRepos(workingDir, maxDepth = 4) {
32285
- const fs70 = await import("fs/promises");
32490
+ const fs71 = await import("fs/promises");
32286
32491
  const out2 = [];
32287
32492
  await walk(workingDir, 0);
32288
32493
  return out2;
@@ -32290,7 +32495,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
32290
32495
  if (depth > maxDepth) return;
32291
32496
  let entries = [];
32292
32497
  try {
32293
- const dirents = await fs70.readdir(dir, { withFileTypes: true });
32498
+ const dirents = await fs71.readdir(dir, { withFileTypes: true });
32294
32499
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
32295
32500
  } catch {
32296
32501
  return;
@@ -32301,8 +32506,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
32301
32506
  if (hasGit) {
32302
32507
  out2.push({
32303
32508
  repoRoot: dir,
32304
- repoPath: path69.relative(workingDir, dir),
32305
- repoName: path69.basename(dir)
32509
+ repoPath: path70.relative(workingDir, dir),
32510
+ repoName: path70.basename(dir)
32306
32511
  });
32307
32512
  return;
32308
32513
  }
@@ -32310,15 +32515,15 @@ async function discoverRepos(workingDir, maxDepth = 4) {
32310
32515
  if (!entry.isDirectory) continue;
32311
32516
  if (entry.name === "node_modules") continue;
32312
32517
  if (entry.name === "dist" || entry.name === "build") continue;
32313
- await walk(path69.join(dir, entry.name), depth + 1);
32518
+ await walk(path70.join(dir, entry.name), depth + 1);
32314
32519
  }
32315
32520
  }
32316
32521
  }
32317
32522
 
32318
32523
  // src/services/turn-files/files-outbox.ts
32319
- var fs65 = __toESM(require("fs/promises"));
32320
- var path70 = __toESM(require("path"));
32321
- var import_os11 = require("os");
32524
+ var fs66 = __toESM(require("fs/promises"));
32525
+ var path71 = __toESM(require("path"));
32526
+ var import_os12 = require("os");
32322
32527
  var HOME_OUTBOX_DIR = ".codeam/outbox";
32323
32528
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
32324
32529
  var BACKOFF_STEPS_MS = [
@@ -32350,16 +32555,16 @@ var FilesOutbox = class {
32350
32555
  backoffIndex = 0;
32351
32556
  stopped = false;
32352
32557
  constructor(opts) {
32353
- const base = opts.baseDir ?? path70.join(homeDir(), HOME_OUTBOX_DIR);
32354
- this.filePath = path70.join(base, `${opts.sessionId}.jsonl`);
32558
+ const base = opts.baseDir ?? path71.join(homeDir(), HOME_OUTBOX_DIR);
32559
+ this.filePath = path71.join(base, `${opts.sessionId}.jsonl`);
32355
32560
  this.post = opts.post;
32356
32561
  this.autoSchedule = opts.autoSchedule !== false;
32357
32562
  }
32358
32563
  /** Persist the entry to disk and trigger a flush. Returns once the
32359
32564
  * line is durable on disk (not once the POST succeeds). */
32360
32565
  async enqueue(entry) {
32361
- await fs65.mkdir(path70.dirname(this.filePath), { recursive: true });
32362
- await fs65.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
32566
+ await fs66.mkdir(path71.dirname(this.filePath), { recursive: true });
32567
+ await fs66.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
32363
32568
  this.backoffIndex = 0;
32364
32569
  if (this.autoSchedule) this.scheduleFlush(0);
32365
32570
  }
@@ -32450,7 +32655,7 @@ var FilesOutbox = class {
32450
32655
  async readAll() {
32451
32656
  let raw = "";
32452
32657
  try {
32453
- raw = await fs65.readFile(this.filePath, "utf8");
32658
+ raw = await fs66.readFile(this.filePath, "utf8");
32454
32659
  } catch {
32455
32660
  return [];
32456
32661
  }
@@ -32474,12 +32679,12 @@ var FilesOutbox = class {
32474
32679
  async rewrite(entries) {
32475
32680
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
32476
32681
  if (entries.length === 0) {
32477
- await fs65.unlink(this.filePath).catch(() => void 0);
32682
+ await fs66.unlink(this.filePath).catch(() => void 0);
32478
32683
  return;
32479
32684
  }
32480
32685
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
32481
- await fs65.writeFile(tmpPath, payload, "utf8");
32482
- await fs65.rename(tmpPath, this.filePath);
32686
+ await fs66.writeFile(tmpPath, payload, "utf8");
32687
+ await fs66.rename(tmpPath, this.filePath);
32483
32688
  }
32484
32689
  };
32485
32690
  function applyJitter(ms) {
@@ -32487,7 +32692,7 @@ function applyJitter(ms) {
32487
32692
  return Math.round(ms * factor);
32488
32693
  }
32489
32694
  function homeDir() {
32490
- return process.env.HOME ?? process.env.USERPROFILE ?? (0, import_os11.tmpdir)();
32695
+ return process.env.HOME ?? process.env.USERPROFILE ?? (0, import_os12.tmpdir)();
32491
32696
  }
32492
32697
 
32493
32698
  // src/services/turn-files/turn-file-aggregator.ts
@@ -35393,9 +35598,9 @@ function fetchQuotaUsage(runtime, historySvc) {
35393
35598
  }
35394
35599
 
35395
35600
  // src/beads/workflow-hint.ts
35396
- var fs66 = __toESM(require("fs"));
35397
- var path71 = __toESM(require("path"));
35398
- var os54 = __toESM(require("os"));
35601
+ var fs67 = __toESM(require("fs"));
35602
+ var path72 = __toESM(require("path"));
35603
+ var os55 = __toESM(require("os"));
35399
35604
  var BEADS_HINT_MARKER = "<!-- codeam:beads-workflow -->";
35400
35605
  var BEADS_HINT = `${BEADS_HINT_MARKER}
35401
35606
  # Beads (bd) \u2014 task tracking + persistent memory (ALWAYS use it)
@@ -35409,22 +35614,22 @@ This environment uses **bd (beads)** for issue/task tracking and persistent memo
35409
35614
  - \`bd ready\` (available work) \xB7 \`bd show <id>\` \xB7 \`bd update <id> --claim\` \xB7 \`bd close <id>\`.
35410
35615
  - Use \`bd remember "..."\` for persistent knowledge \u2014 do NOT use MEMORY.md files.
35411
35616
  ${BEADS_HINT_MARKER}`;
35412
- function ensureBeadsWorkflowHint(homeDir2 = os54.homedir()) {
35617
+ function ensureBeadsWorkflowHint(homeDir2 = os55.homedir()) {
35413
35618
  try {
35414
- const file = path71.join(homeDir2, ".claude", "CLAUDE.md");
35619
+ const file = path72.join(homeDir2, ".claude", "CLAUDE.md");
35415
35620
  let existing = "";
35416
35621
  try {
35417
- existing = fs66.readFileSync(file, "utf8");
35622
+ existing = fs67.readFileSync(file, "utf8");
35418
35623
  } catch {
35419
35624
  }
35420
35625
  if (existing.includes(BEADS_HINT_MARKER)) return;
35421
- fs66.mkdirSync(path71.dirname(file), { recursive: true });
35626
+ fs67.mkdirSync(path72.dirname(file), { recursive: true });
35422
35627
  const next = existing.trim() ? `${existing.trimEnd()}
35423
35628
 
35424
35629
  ${BEADS_HINT}
35425
35630
  ` : `${BEADS_HINT}
35426
35631
  `;
35427
- fs66.writeFileSync(file, next);
35632
+ fs67.writeFileSync(file, next);
35428
35633
  } catch {
35429
35634
  }
35430
35635
  }
@@ -35467,8 +35672,8 @@ function buildMcpServersForStart(ctx) {
35467
35672
  }
35468
35673
 
35469
35674
  // src/skills/provision.ts
35470
- var import_node_os12 = __toESM(require("os"));
35471
- function provisionSkillsForStart(home = import_node_os12.default.homedir()) {
35675
+ var import_node_os13 = __toESM(require("os"));
35676
+ function provisionSkillsForStart(home = import_node_os13.default.homedir()) {
35472
35677
  const materialized = [];
35473
35678
  try {
35474
35679
  const manifest = readSkillsManifest();
@@ -35833,7 +36038,7 @@ var AcpDriver = class {
35833
36038
  };
35834
36039
 
35835
36040
  // src/baton/transcript-mirror.ts
35836
- var fs67 = __toESM(require("fs"));
36041
+ var fs68 = __toESM(require("fs"));
35837
36042
  var TranscriptMirror = class {
35838
36043
  constructor(deps) {
35839
36044
  this.deps = deps;
@@ -35900,7 +36105,7 @@ var TranscriptMirror = class {
35900
36105
  }
35901
36106
  };
35902
36107
  function defaultWatch(file, onChange) {
35903
- const w3 = fs67.watch(file, { persistent: false }, () => onChange());
36108
+ const w3 = fs68.watch(file, { persistent: false }, () => onChange());
35904
36109
  return () => w3.close();
35905
36110
  }
35906
36111
 
@@ -36162,16 +36367,16 @@ function toEpochMs(ts) {
36162
36367
  }
36163
36368
 
36164
36369
  // src/agents/claude/onboarding.ts
36165
- var fs68 = __toESM(require("fs"));
36166
- var os56 = __toESM(require("os"));
36167
- var path72 = __toESM(require("path"));
36370
+ var fs69 = __toESM(require("fs"));
36371
+ var os57 = __toESM(require("os"));
36372
+ var path73 = __toESM(require("path"));
36168
36373
  var ONBOARDING_VERSION_SENTINEL = "9999.0.0";
36169
36374
  function ensureClaudeOnboarded(cwd) {
36170
36375
  try {
36171
- const file = path72.join(os56.homedir(), ".claude.json");
36376
+ const file = path73.join(os57.homedir(), ".claude.json");
36172
36377
  let config = {};
36173
36378
  try {
36174
- config = JSON.parse(fs68.readFileSync(file, "utf8"));
36379
+ config = JSON.parse(fs69.readFileSync(file, "utf8"));
36175
36380
  } catch {
36176
36381
  }
36177
36382
  let changed = false;
@@ -36196,8 +36401,8 @@ function ensureClaudeOnboarded(cwd) {
36196
36401
  }
36197
36402
  }
36198
36403
  if (!changed) return;
36199
- fs68.mkdirSync(path72.dirname(file), { recursive: true });
36200
- fs68.writeFileSync(file, JSON.stringify(config, null, 2));
36404
+ fs69.mkdirSync(path73.dirname(file), { recursive: true });
36405
+ fs69.writeFileSync(file, JSON.stringify(config, null, 2));
36201
36406
  log.info(
36202
36407
  "claude",
36203
36408
  `pre-completed Claude onboarding${cwd ? ` + trusted workspace ${cwd}` : ""}`
@@ -36915,7 +37120,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
36915
37120
  var import_child_process29 = require("child_process");
36916
37121
  var import_util4 = require("util");
36917
37122
  var import_picocolors9 = __toESM(require("picocolors"));
36918
- var path73 = __toESM(require("path"));
37123
+ var path74 = __toESM(require("path"));
36919
37124
  var execFileP6 = (0, import_util4.promisify)(import_child_process29.execFile);
36920
37125
  var MAX_BUFFER = 8 * 1024 * 1024;
36921
37126
  function resetStdinForChild() {
@@ -37404,7 +37609,7 @@ var GitHubCodespacesProvider = class {
37404
37609
  });
37405
37610
  }
37406
37611
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
37407
- const remoteDir = path73.posix.dirname(remotePath);
37612
+ const remoteDir = path74.posix.dirname(remotePath);
37408
37613
  const parts = [
37409
37614
  `mkdir -p ${shellQuote(remoteDir)}`,
37410
37615
  `cat > ${shellQuote(remotePath)}`
@@ -37474,7 +37679,7 @@ function shellQuote(s) {
37474
37679
  // src/services/providers/gitpod.ts
37475
37680
  var import_child_process30 = require("child_process");
37476
37681
  var import_util5 = require("util");
37477
- var path74 = __toESM(require("path"));
37682
+ var path75 = __toESM(require("path"));
37478
37683
  var import_picocolors10 = __toESM(require("picocolors"));
37479
37684
  var execFileP7 = (0, import_util5.promisify)(import_child_process30.execFile);
37480
37685
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -37714,7 +37919,7 @@ var GitpodProvider = class {
37714
37919
  });
37715
37920
  }
37716
37921
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
37717
- const remoteDir = path74.posix.dirname(remotePath);
37922
+ const remoteDir = path75.posix.dirname(remotePath);
37718
37923
  const parts = [
37719
37924
  `mkdir -p ${shellQuote2(remoteDir)}`,
37720
37925
  `cat > ${shellQuote2(remotePath)}`
@@ -37750,7 +37955,7 @@ function shellQuote2(s) {
37750
37955
  // src/services/providers/gitlab-workspaces.ts
37751
37956
  var import_child_process31 = require("child_process");
37752
37957
  var import_util6 = require("util");
37753
- var path75 = __toESM(require("path"));
37958
+ var path76 = __toESM(require("path"));
37754
37959
  var execFileP8 = (0, import_util6.promisify)(import_child_process31.execFile);
37755
37960
  var MAX_BUFFER3 = 8 * 1024 * 1024;
37756
37961
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -38010,7 +38215,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
38010
38215
  }
38011
38216
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
38012
38217
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
38013
- const remoteDir = path75.posix.dirname(remotePath);
38218
+ const remoteDir = path76.posix.dirname(remotePath);
38014
38219
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
38015
38220
  if (options.mode != null) {
38016
38221
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -38078,7 +38283,7 @@ function shellQuote3(s) {
38078
38283
  // src/services/providers/railway.ts
38079
38284
  var import_child_process32 = require("child_process");
38080
38285
  var import_util7 = require("util");
38081
- var path76 = __toESM(require("path"));
38286
+ var path77 = __toESM(require("path"));
38082
38287
  var execFileP9 = (0, import_util7.promisify)(import_child_process32.execFile);
38083
38288
  var MAX_BUFFER4 = 8 * 1024 * 1024;
38084
38289
  function resetStdinForChild4() {
@@ -38314,7 +38519,7 @@ var RailwayProvider = class {
38314
38519
  if (!projectId || !serviceId) {
38315
38520
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
38316
38521
  }
38317
- const remoteDir = path76.posix.dirname(remotePath);
38522
+ const remoteDir = path77.posix.dirname(remotePath);
38318
38523
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
38319
38524
  if (options.mode != null) {
38320
38525
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -38960,8 +39165,8 @@ async function invite() {
38960
39165
  var import_node_dns = require("dns");
38961
39166
  var import_node_util5 = require("util");
38962
39167
  var import_node_crypto13 = require("crypto");
38963
- var fs69 = __toESM(require("fs"));
38964
- var path77 = __toESM(require("path"));
39168
+ var fs70 = __toESM(require("fs"));
39169
+ var path78 = __toESM(require("path"));
38965
39170
  var import_picocolors14 = __toESM(require("picocolors"));
38966
39171
  var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
38967
39172
  async function checkDns(apiBase2) {
@@ -39017,13 +39222,13 @@ async function checkHealth(apiBase2) {
39017
39222
  }
39018
39223
  }
39019
39224
  function checkConfigDir() {
39020
- const dir = path77.join(require("os").homedir(), ".codeam");
39225
+ const dir = path78.join(require("os").homedir(), ".codeam");
39021
39226
  try {
39022
- fs69.mkdirSync(dir, { recursive: true, mode: 448 });
39023
- const probe = path77.join(dir, ".doctor-probe");
39024
- fs69.writeFileSync(probe, "ok", { mode: 384 });
39025
- const read2 = fs69.readFileSync(probe, "utf8");
39026
- fs69.unlinkSync(probe);
39227
+ fs70.mkdirSync(dir, { recursive: true, mode: 448 });
39228
+ const probe = path78.join(dir, ".doctor-probe");
39229
+ fs70.writeFileSync(probe, "ok", { mode: 384 });
39230
+ const read2 = fs70.readFileSync(probe, "utf8");
39231
+ fs70.unlinkSync(probe);
39027
39232
  if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
39028
39233
  return {
39029
39234
  id: "config-dir",
@@ -39063,9 +39268,9 @@ function checkSessions() {
39063
39268
  }
39064
39269
  }
39065
39270
  function checkAgentBinaries() {
39066
- const os59 = createOsStrategy();
39271
+ const os60 = createOsStrategy();
39067
39272
  return getEnabledAgents().map((meta) => {
39068
- const found = os59.findInPath(meta.binaryName);
39273
+ const found = os60.findInPath(meta.binaryName);
39069
39274
  return {
39070
39275
  id: `agent-${meta.id}`,
39071
39276
  label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
@@ -39087,7 +39292,7 @@ function checkNodePty() {
39087
39292
  detail: "not required on this platform"
39088
39293
  };
39089
39294
  }
39090
- const vendoredPath = path77.join(__dirname, "vendor", "node-pty");
39295
+ const vendoredPath = path78.join(__dirname, "vendor", "node-pty");
39091
39296
  for (const target of [vendoredPath, "node-pty"]) {
39092
39297
  try {
39093
39298
  require(target);
@@ -39129,7 +39334,7 @@ function checkChokidar() {
39129
39334
  }
39130
39335
  async function doctor(args2 = []) {
39131
39336
  const json = args2.includes("--json");
39132
- const cliVersion = true ? "2.61.49" : "0.0.0-dev";
39337
+ const cliVersion = true ? "2.61.50" : "0.0.0-dev";
39133
39338
  const apiBase2 = resolveApiBaseUrl();
39134
39339
  const diagnosticId = (0, import_node_crypto13.randomUUID)();
39135
39340
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -39326,10 +39531,10 @@ async function completion(args2) {
39326
39531
  }
39327
39532
 
39328
39533
  // src/integrations/mcp-run.ts
39329
- var import_node_child_process29 = require("child_process");
39534
+ var import_node_child_process31 = require("child_process");
39330
39535
  var import_node_fs11 = require("fs");
39331
- var import_node_os13 = __toESM(require("os"));
39332
- var import_node_path10 = __toESM(require("path"));
39536
+ var import_node_os14 = __toESM(require("os"));
39537
+ var import_node_path11 = __toESM(require("path"));
39333
39538
 
39334
39539
  // src/integrations/token-client.ts
39335
39540
  var REFRESH_AHEAD_MS = 5 * 60 * 1e3;
@@ -39382,7 +39587,7 @@ var IntegrationTokenClient = class {
39382
39587
  };
39383
39588
 
39384
39589
  // src/integrations/stdio-proxy.ts
39385
- var import_node_child_process28 = require("child_process");
39590
+ var import_node_child_process30 = require("child_process");
39386
39591
  var import_node_readline3 = __toESM(require("readline"));
39387
39592
  var RESTART_CHECK_INTERVAL_MS = 3e4;
39388
39593
  var SIGKILL_ESCALATION_MS = 2e3;
@@ -39503,8 +39708,8 @@ var RestartableStdioProxy = class {
39503
39708
  }
39504
39709
  async spawnChild(stdout, preResolved) {
39505
39710
  const spec = preResolved ?? await this.opts.spawnSpec();
39506
- const spawn42 = this.opts.spawnImpl ?? import_node_child_process28.spawn;
39507
- const child = spawn42(spec.command, spec.args, {
39711
+ const spawn44 = this.opts.spawnImpl ?? import_node_child_process30.spawn;
39712
+ const child = spawn44(spec.command, spec.args, {
39508
39713
  env: { ...process.env, ...spec.env },
39509
39714
  // env only — never argv
39510
39715
  stdio: ["pipe", "pipe", "inherit"]
@@ -39543,7 +39748,7 @@ function resolveDelivery(id) {
39543
39748
  function commandExists(command2) {
39544
39749
  try {
39545
39750
  const probe = process.platform === "win32" ? "where" : "which";
39546
- (0, import_node_child_process29.execFileSync)(probe, [command2], { stdio: "ignore" });
39751
+ (0, import_node_child_process31.execFileSync)(probe, [command2], { stdio: "ignore" });
39547
39752
  return true;
39548
39753
  } catch {
39549
39754
  return false;
@@ -39551,8 +39756,8 @@ function commandExists(command2) {
39551
39756
  }
39552
39757
  function localBinCandidates(command2) {
39553
39758
  return [
39554
- import_node_path10.default.join(import_node_os13.default.homedir(), ".local", "bin", command2),
39555
- import_node_path10.default.join(import_node_os13.default.homedir(), ".cargo", "bin", command2)
39759
+ import_node_path11.default.join(import_node_os14.default.homedir(), ".local", "bin", command2),
39760
+ import_node_path11.default.join(import_node_os14.default.homedir(), ".cargo", "bin", command2)
39556
39761
  ];
39557
39762
  }
39558
39763
  function resolveLauncherPath(command2, deps = {
@@ -39576,7 +39781,7 @@ function ensureCommand(command2) {
39576
39781
  }
39577
39782
  if (command2 === "uvx") {
39578
39783
  try {
39579
- (0, import_node_child_process29.execSync)("curl -LsSf https://astral.sh/uv/install.sh | sh", {
39784
+ (0, import_node_child_process31.execSync)("curl -LsSf https://astral.sh/uv/install.sh | sh", {
39580
39785
  stdio: ["ignore", process.stderr, process.stderr],
39581
39786
  timeout: 18e4,
39582
39787
  env: { ...process.env, UV_NO_MODIFY_PATH: "1" }
@@ -39585,7 +39790,7 @@ function ensureCommand(command2) {
39585
39790
  }
39586
39791
  if (resolveLauncherPath(command2) !== command2) return;
39587
39792
  try {
39588
- (0, import_node_child_process29.execSync)("python3 -m pip install --user --quiet uv", {
39793
+ (0, import_node_child_process31.execSync)("python3 -m pip install --user --quiet uv", {
39589
39794
  stdio: ["ignore", process.stderr, process.stderr],
39590
39795
  timeout: 18e4
39591
39796
  });
@@ -39651,7 +39856,7 @@ async function mcpRun(args2) {
39651
39856
  // src/commands/version.ts
39652
39857
  var import_picocolors15 = __toESM(require("picocolors"));
39653
39858
  function version2() {
39654
- const v = true ? "2.61.49" : "unknown";
39859
+ const v = true ? "2.61.50" : "unknown";
39655
39860
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
39656
39861
  }
39657
39862
 
@@ -39800,10 +40005,10 @@ var EXIT_CODE_NAMES = {
39800
40005
  };
39801
40006
 
39802
40007
  // src/index.ts
39803
- var os58 = __toESM(require("os"));
40008
+ var os59 = __toESM(require("os"));
39804
40009
  if (!process.env.HOME) {
39805
40010
  try {
39806
- const home = os58.homedir();
40011
+ const home = os59.homedir();
39807
40012
  if (home) process.env.HOME = home;
39808
40013
  } catch {
39809
40014
  }