codeam-cli 2.35.9 → 2.36.1

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 +23 -0
  2. package/dist/index.js +624 -340
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -498,7 +498,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
498
498
  // package.json
499
499
  var package_default = {
500
500
  name: "codeam-cli",
501
- version: "2.35.9",
501
+ version: "2.36.1",
502
502
  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.",
503
503
  type: "commonjs",
504
504
  main: "dist/index.js",
@@ -1186,8 +1186,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
1186
1186
  return decodedFile;
1187
1187
  };
1188
1188
  }
1189
- function normalizeWindowsPath(path50) {
1190
- return path50.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1189
+ function normalizeWindowsPath(path51) {
1190
+ return path51.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1191
1191
  }
1192
1192
 
1193
1193
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -3667,9 +3667,9 @@ async function addSourceContext(frames) {
3667
3667
  LRU_FILE_CONTENTS_CACHE.reduce();
3668
3668
  return frames;
3669
3669
  }
3670
- function getContextLinesFromFile(path50, ranges, output) {
3670
+ function getContextLinesFromFile(path51, ranges, output) {
3671
3671
  return new Promise((resolve7) => {
3672
- const stream = (0, import_node_fs.createReadStream)(path50);
3672
+ const stream = (0, import_node_fs.createReadStream)(path51);
3673
3673
  const lineReaded = (0, import_node_readline.createInterface)({
3674
3674
  input: stream
3675
3675
  });
@@ -3684,7 +3684,7 @@ function getContextLinesFromFile(path50, ranges, output) {
3684
3684
  let rangeStart = range[0];
3685
3685
  let rangeEnd = range[1];
3686
3686
  function onStreamError() {
3687
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path50, 1);
3687
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path51, 1);
3688
3688
  lineReaded.close();
3689
3689
  lineReaded.removeAllListeners();
3690
3690
  destroyStreamAndResolve();
@@ -3745,8 +3745,8 @@ function clearLineContext(frame) {
3745
3745
  delete frame.context_line;
3746
3746
  delete frame.post_context;
3747
3747
  }
3748
- function shouldSkipContextLinesForFile(path50) {
3749
- return path50.startsWith("node:") || path50.endsWith(".min.js") || path50.endsWith(".min.cjs") || path50.endsWith(".min.mjs") || path50.startsWith("data:");
3748
+ function shouldSkipContextLinesForFile(path51) {
3749
+ return path51.startsWith("node:") || path51.endsWith(".min.js") || path51.endsWith(".min.cjs") || path51.endsWith(".min.mjs") || path51.startsWith("data:");
3750
3750
  }
3751
3751
  function shouldSkipContextLinesForFrame(frame) {
3752
3752
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -5900,7 +5900,7 @@ function readAnonId() {
5900
5900
  }
5901
5901
  function superProperties() {
5902
5902
  return {
5903
- cliVersion: true ? "2.35.9" : "0.0.0-dev",
5903
+ cliVersion: true ? "2.36.1" : "0.0.0-dev",
5904
5904
  nodeVersion: process.version,
5905
5905
  platform: process.platform,
5906
5906
  arch: process.arch,
@@ -7248,10 +7248,10 @@ function buildForPlatform(platform2) {
7248
7248
  var import_node_crypto4 = require("crypto");
7249
7249
 
7250
7250
  // src/agents/claude/resolver.ts
7251
- function buildClaudeLaunch(extraArgs = [], os31 = createOsStrategy()) {
7252
- const found = os31.findInPath("claude") ?? os31.findInPath("claude-code");
7251
+ function buildClaudeLaunch(extraArgs = [], os32 = createOsStrategy()) {
7252
+ const found = os32.findInPath("claude") ?? os32.findInPath("claude-code");
7253
7253
  if (!found) return null;
7254
- return os31.buildLaunch(found, extraArgs);
7254
+ return os32.buildLaunch(found, extraArgs);
7255
7255
  }
7256
7256
 
7257
7257
  // src/agents/claude/installer.ts
@@ -9978,13 +9978,13 @@ function detectStartupBanner(lines) {
9978
9978
  while (artStart > 0 && BANNER_ART_RE.test(lines[artStart - 1])) artStart--;
9979
9979
  if (metaIdx - artStart < 2) return null;
9980
9980
  const pathLine = (lines[metaIdx + 1] ?? "").trim();
9981
- const path50 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9981
+ const path51 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9982
9982
  return {
9983
9983
  title: "",
9984
9984
  subtitle: lines[metaIdx].trim(),
9985
- path: path50,
9985
+ path: path51,
9986
9986
  startIdx: artStart,
9987
- endIdx: metaIdx + (path50 ? 1 : 0)
9987
+ endIdx: metaIdx + (path51 ? 1 : 0)
9988
9988
  };
9989
9989
  }
9990
9990
 
@@ -9994,8 +9994,8 @@ var ClaudeRuntimeStrategy = class {
9994
9994
  meta = getAgent("claude");
9995
9995
  mode = "interactive";
9996
9996
  os;
9997
- constructor(os31) {
9998
- this.os = os31;
9997
+ constructor(os32) {
9998
+ this.os = os32;
9999
9999
  }
10000
10000
  /**
10001
10001
  * Claude Code's react-ink TUI enables bracketed-paste mode at
@@ -11025,8 +11025,8 @@ function codexCredentialLocator() {
11025
11025
  function codexLoginLauncher() {
11026
11026
  return {
11027
11027
  async ensureInstalled() {
11028
- const os31 = createOsStrategy();
11029
- return os31.findInPath("codex") !== null;
11028
+ const os32 = createOsStrategy();
11029
+ return os32.findInPath("codex") !== null;
11030
11030
  },
11031
11031
  launch() {
11032
11032
  return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
@@ -11049,8 +11049,8 @@ var CodexRuntimeStrategy = class {
11049
11049
  meta = getAgent("codex");
11050
11050
  mode = "interactive";
11051
11051
  os;
11052
- constructor(os31) {
11053
- this.os = os31;
11052
+ constructor(os32) {
11053
+ this.os = os32;
11054
11054
  }
11055
11055
  async prepareLaunch() {
11056
11056
  let binary = this.os.findInPath("codex");
@@ -11156,12 +11156,12 @@ var CodexRuntimeStrategy = class {
11156
11156
  });
11157
11157
  }
11158
11158
  };
11159
- function resolveNpm(os31) {
11160
- return os31.id === "win32" ? "npm.cmd" : "npm";
11159
+ function resolveNpm(os32) {
11160
+ return os32.id === "win32" ? "npm.cmd" : "npm";
11161
11161
  }
11162
- async function installCodexViaNpm(os31) {
11162
+ async function installCodexViaNpm(os32) {
11163
11163
  return new Promise((resolve7, reject) => {
11164
- const proc = (0, import_node_child_process4.spawn)(resolveNpm(os31), ["install", "-g", "@openai/codex"], {
11164
+ const proc = (0, import_node_child_process4.spawn)(resolveNpm(os32), ["install", "-g", "@openai/codex"], {
11165
11165
  stdio: "inherit"
11166
11166
  });
11167
11167
  proc.on("close", (code) => {
@@ -11178,16 +11178,16 @@ async function installCodexViaNpm(os31) {
11178
11178
  });
11179
11179
  });
11180
11180
  }
11181
- function augmentNpmGlobalBin(os31) {
11181
+ function augmentNpmGlobalBin(os32) {
11182
11182
  try {
11183
- const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os31), ["prefix", "-g"], {
11183
+ const result = (0, import_node_child_process4.spawnSync)(resolveNpm(os32), ["prefix", "-g"], {
11184
11184
  stdio: ["ignore", "pipe", "ignore"]
11185
11185
  });
11186
11186
  if (result.status !== 0) return;
11187
11187
  const prefix = result.stdout.toString().trim();
11188
11188
  if (!prefix) return;
11189
- const binDir = os31.id === "win32" ? prefix : path17.join(prefix, "bin");
11190
- os31.augmentPath([binDir]);
11189
+ const binDir = os32.id === "win32" ? prefix : path17.join(prefix, "bin");
11190
+ os32.augmentPath([binDir]);
11191
11191
  } catch {
11192
11192
  }
11193
11193
  }
@@ -11271,9 +11271,9 @@ var import_node_child_process7 = require("child_process");
11271
11271
  // src/agents/coderabbit/installer.ts
11272
11272
  var import_node_child_process5 = require("child_process");
11273
11273
  var INSTALL_URL = "https://cli.coderabbit.ai/install.sh";
11274
- async function ensureCoderabbitInstalled(os31) {
11275
- if (os31.findInPath("coderabbit")) return true;
11276
- if (os31.id === "win32") {
11274
+ async function ensureCoderabbitInstalled(os32) {
11275
+ if (os32.findInPath("coderabbit")) return true;
11276
+ if (os32.id === "win32") {
11277
11277
  console.error(
11278
11278
  "\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"
11279
11279
  );
@@ -11288,8 +11288,8 @@ async function ensureCoderabbitInstalled(os31) {
11288
11288
  proc.on("error", () => resolve7(false));
11289
11289
  });
11290
11290
  if (!ok) return false;
11291
- os31.augmentPath([`${os31.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
11292
- return os31.findInPath("coderabbit") !== null;
11291
+ os32.augmentPath([`${os32.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
11292
+ return os32.findInPath("coderabbit") !== null;
11293
11293
  }
11294
11294
 
11295
11295
  // src/agents/coderabbit/link.ts
@@ -11316,10 +11316,10 @@ function coderabbitCredentialLocator() {
11316
11316
  extract: extractLocalCoderabbitToken
11317
11317
  };
11318
11318
  }
11319
- function coderabbitLoginLauncher(os31) {
11319
+ function coderabbitLoginLauncher(os32) {
11320
11320
  return {
11321
11321
  async ensureInstalled() {
11322
- return ensureCoderabbitInstalled(os31);
11322
+ return ensureCoderabbitInstalled(os32);
11323
11323
  },
11324
11324
  launch() {
11325
11325
  return (0, import_node_child_process6.spawn)("coderabbit", ["login"], { stdio: "inherit" });
@@ -11342,11 +11342,11 @@ function parseReview(stdout) {
11342
11342
  for (const line of lines) {
11343
11343
  const m = line.match(HUNK_LINE_RE);
11344
11344
  if (!m) continue;
11345
- const [, path50, lineNo, sevToken, message] = m;
11346
- if (!path50 || !lineNo || !message) continue;
11345
+ const [, path51, lineNo, sevToken, message] = m;
11346
+ if (!path51 || !lineNo || !message) continue;
11347
11347
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
11348
11348
  hunks.push({
11349
- path: path50.trim(),
11349
+ path: path51.trim(),
11350
11350
  line: Number(lineNo),
11351
11351
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
11352
11352
  message: cleanedMessage
@@ -11365,8 +11365,8 @@ var CoderabbitRuntimeStrategy = class {
11365
11365
  meta = getAgent("coderabbit");
11366
11366
  mode = "batch";
11367
11367
  os;
11368
- constructor(os31) {
11369
- this.os = os31;
11368
+ constructor(os32) {
11369
+ this.os = os32;
11370
11370
  }
11371
11371
  getDefaultArgs() {
11372
11372
  return ["review"];
@@ -11481,10 +11481,10 @@ function cursorCredentialLocator() {
11481
11481
  extract: extractLocalCursorToken
11482
11482
  };
11483
11483
  }
11484
- function cursorLoginLauncher(os31) {
11484
+ function cursorLoginLauncher(os32) {
11485
11485
  return {
11486
11486
  async ensureInstalled() {
11487
- if (os31.findInPath("cursor-agent")) return true;
11487
+ if (os32.findInPath("cursor-agent")) return true;
11488
11488
  console.error(
11489
11489
  "\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"
11490
11490
  );
@@ -11546,8 +11546,8 @@ var CursorRuntimeStrategy = class {
11546
11546
  meta = getAgent("cursor");
11547
11547
  mode = "interactive";
11548
11548
  os;
11549
- constructor(os31) {
11550
- this.os = os31;
11549
+ constructor(os32) {
11550
+ this.os = os32;
11551
11551
  }
11552
11552
  async prepareLaunch() {
11553
11553
  const binary = this.os.findInPath("cursor-agent");
@@ -11667,10 +11667,10 @@ function aiderCredentialLocator() {
11667
11667
  extract: extractLocalAiderToken
11668
11668
  };
11669
11669
  }
11670
- function aiderLoginLauncher(os31) {
11670
+ function aiderLoginLauncher(os32) {
11671
11671
  return {
11672
11672
  async ensureInstalled() {
11673
- if (os31.findInPath("aider")) return true;
11673
+ if (os32.findInPath("aider")) return true;
11674
11674
  console.error(
11675
11675
  "\n \u2717 aider binary not on PATH.\n Install Aider:\n pip install aider-chat\n then re-run `codeam link aider`.\n"
11676
11676
  );
@@ -11680,7 +11680,7 @@ function aiderLoginLauncher(os31) {
11680
11680
  console.error(
11681
11681
  "\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"
11682
11682
  );
11683
- return (0, import_node_child_process9.spawn)(os31.id === "win32" ? "cmd.exe" : "sh", os31.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
11683
+ return (0, import_node_child_process9.spawn)(os32.id === "win32" ? "cmd.exe" : "sh", os32.id === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"], {
11684
11684
  stdio: "ignore"
11685
11685
  });
11686
11686
  }
@@ -11752,8 +11752,8 @@ var AiderRuntimeStrategy = class {
11752
11752
  meta = getAgent("aider");
11753
11753
  mode = "interactive";
11754
11754
  os;
11755
- constructor(os31) {
11756
- this.os = os31;
11755
+ constructor(os32) {
11756
+ this.os = os32;
11757
11757
  }
11758
11758
  async prepareLaunch() {
11759
11759
  const binary = this.os.findInPath("aider");
@@ -11882,8 +11882,8 @@ function geminiCredentialLocator() {
11882
11882
  function geminiLoginLauncher() {
11883
11883
  return {
11884
11884
  async ensureInstalled() {
11885
- const os31 = createOsStrategy();
11886
- return os31.findInPath("gemini") !== null;
11885
+ const os32 = createOsStrategy();
11886
+ return os32.findInPath("gemini") !== null;
11887
11887
  },
11888
11888
  launch() {
11889
11889
  return (0, import_node_child_process10.spawn)("gemini", ["auth", "login"], { stdio: "inherit" });
@@ -11916,8 +11916,8 @@ var GeminiRuntimeStrategy = class {
11916
11916
  meta = getAgent("gemini");
11917
11917
  mode = "interactive";
11918
11918
  os;
11919
- constructor(os31) {
11920
- this.os = os31;
11919
+ constructor(os32) {
11920
+ this.os = os32;
11921
11921
  }
11922
11922
  async prepareLaunch() {
11923
11923
  const binary = this.os.findInPath("gemini");
@@ -12017,18 +12017,18 @@ var GeminiRuntimeStrategy = class {
12017
12017
 
12018
12018
  // src/agents/registry.ts
12019
12019
  var runtimeBuilders = {
12020
- claude: (os31) => new ClaudeRuntimeStrategy(os31),
12021
- codex: (os31) => new CodexRuntimeStrategy(os31),
12022
- coderabbit: (os31) => new CoderabbitRuntimeStrategy(os31),
12023
- cursor: (os31) => new CursorRuntimeStrategy(os31),
12024
- aider: (os31) => new AiderRuntimeStrategy(os31),
12025
- gemini: (os31) => new GeminiRuntimeStrategy(os31)
12020
+ claude: (os32) => new ClaudeRuntimeStrategy(os32),
12021
+ codex: (os32) => new CodexRuntimeStrategy(os32),
12022
+ coderabbit: (os32) => new CoderabbitRuntimeStrategy(os32),
12023
+ cursor: (os32) => new CursorRuntimeStrategy(os32),
12024
+ aider: (os32) => new AiderRuntimeStrategy(os32),
12025
+ gemini: (os32) => new GeminiRuntimeStrategy(os32)
12026
12026
  };
12027
12027
  var deployBuilders = {
12028
12028
  claude: () => new ClaudeDeployStrategy(),
12029
12029
  codex: () => new CodexDeployStrategy()
12030
12030
  };
12031
- function createAgentStrategy(agent, os31 = createOsStrategy()) {
12031
+ function createAgentStrategy(agent, os32 = createOsStrategy()) {
12032
12032
  if (!AGENT_REGISTRY[agent]?.enabled) {
12033
12033
  throw new Error(
12034
12034
  `Agent "${agent}" is not supported in this codeam-cli version. Upgrade with 'npm i -g codeam-cli@latest'.`
@@ -12038,10 +12038,10 @@ function createAgentStrategy(agent, os31 = createOsStrategy()) {
12038
12038
  if (!build) {
12039
12039
  throw new Error(`No runtime strategy registered for agent "${agent}"`);
12040
12040
  }
12041
- return build(os31);
12041
+ return build(os32);
12042
12042
  }
12043
- function createInteractiveAgentStrategy(agent, os31 = createOsStrategy()) {
12044
- const s = createAgentStrategy(agent, os31);
12043
+ function createInteractiveAgentStrategy(agent, os32 = createOsStrategy()) {
12044
+ const s = createAgentStrategy(agent, os32);
12045
12045
  if (s.mode !== "interactive") {
12046
12046
  throw new Error(
12047
12047
  `Agent "${agent}" is a batch agent; use createAgentStrategy + .runOneShot for one-shot reviews.`
@@ -15830,11 +15830,11 @@ function extractSelectPrompt(text) {
15830
15830
  }
15831
15831
 
15832
15832
  // src/commands/start/handlers.ts
15833
- var fs32 = __toESM(require("fs"));
15834
- var os26 = __toESM(require("os"));
15835
- var path39 = __toESM(require("path"));
15833
+ var fs33 = __toESM(require("fs"));
15834
+ var os27 = __toESM(require("os"));
15835
+ var path40 = __toESM(require("path"));
15836
15836
  var import_crypto3 = require("crypto");
15837
- var import_child_process17 = require("child_process");
15837
+ var import_child_process18 = require("child_process");
15838
15838
 
15839
15839
  // src/lib/payload.ts
15840
15840
  var import_zod = require("zod");
@@ -17509,7 +17509,8 @@ var BdAdapter = class {
17509
17509
  }
17510
17510
  const env = { ...process.env };
17511
17511
  env.BEADS_DIR = this.opts.beadsDir ?? defaultBeadsHomeDir();
17512
- log.trace("beads", `bd ${args2.join(" ")} (BEADS_DIR=${env.BEADS_DIR})`);
17512
+ env.BEADS_DOLT_SHARED_SERVER = "1";
17513
+ log.trace("beads", `bd ${args2.join(" ")} (BEADS_DIR=${env.BEADS_DIR}, shared-server)`);
17513
17514
  return _spawnSeam.run(binary, args2, { cwd: this.opts.cwd, env });
17514
17515
  }
17515
17516
  /**
@@ -17583,10 +17584,10 @@ function defaultBeadsHomeDir() {
17583
17584
  }
17584
17585
 
17585
17586
  // src/beads/provisioner.ts
17586
- var import_child_process15 = require("child_process");
17587
- var fs30 = __toESM(require("fs"));
17588
- var os25 = __toESM(require("os"));
17589
- var path36 = __toESM(require("path"));
17587
+ var import_child_process17 = require("child_process");
17588
+ var fs32 = __toESM(require("fs"));
17589
+ var os26 = __toESM(require("os"));
17590
+ var path38 = __toESM(require("path"));
17590
17591
 
17591
17592
  // src/beads/install-bd.ts
17592
17593
  var import_child_process14 = require("child_process");
@@ -17649,6 +17650,335 @@ async function installBd(platform2 = process.platform) {
17649
17650
  return result;
17650
17651
  }
17651
17652
 
17653
+ // src/beads/install-dolt.ts
17654
+ var import_child_process15 = require("child_process");
17655
+ var fs30 = __toESM(require("fs"));
17656
+ var os25 = __toESM(require("os"));
17657
+ var path36 = __toESM(require("path"));
17658
+ var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
17659
+ var DOLT_MSI_URL = "https://github.com/dolthub/dolt/releases/latest/download/dolt-windows-amd64.msi";
17660
+ function resolveDoltInstallStrategy(platform2) {
17661
+ if (platform2 === "win32") {
17662
+ const script = [
17663
+ `$ErrorActionPreference='Stop';`,
17664
+ `$u='${DOLT_MSI_URL}';`,
17665
+ `$o="$env:TEMP\\dolt-install.msi";`,
17666
+ `Invoke-WebRequest -Uri $u -OutFile $o;`,
17667
+ `Start-Process msiexec.exe -ArgumentList '/i',('"'+$o+'"'),'/quiet','/norestart' -Wait`
17668
+ ].join(" ");
17669
+ return {
17670
+ command: "powershell.exe",
17671
+ args: [
17672
+ "-NoProfile",
17673
+ "-NonInteractive",
17674
+ "-ExecutionPolicy",
17675
+ "Bypass",
17676
+ "-Command",
17677
+ script
17678
+ ],
17679
+ description: "PowerShell: download official dolt MSI + silent msiexec"
17680
+ };
17681
+ }
17682
+ if (platform2 === "darwin") {
17683
+ return {
17684
+ command: "brew",
17685
+ args: ["install", "dolt"],
17686
+ description: "brew install dolt"
17687
+ };
17688
+ }
17689
+ return {
17690
+ command: "bash",
17691
+ args: ["-c", `curl -L ${DOLT_INSTALL_SH_URL} | sudo bash`],
17692
+ description: `curl -L ${DOLT_INSTALL_SH_URL} | sudo bash (\u2192 /usr/local/bin)`
17693
+ };
17694
+ }
17695
+ var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
17696
+ function doltPlatformTuple(platform2, arch) {
17697
+ const os32 = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "darwin" : "linux";
17698
+ const a = arch === "x64" ? "amd64" : arch === "arm64" ? "arm64" : null;
17699
+ if (!a) return null;
17700
+ if (os32 === "windows" && a !== "amd64") return null;
17701
+ return `${os32}-${a}`;
17702
+ }
17703
+ function resolveDoltTarballStrategy(targetDir, platform2, arch) {
17704
+ const tuple = doltPlatformTuple(platform2, arch);
17705
+ if (!tuple) return null;
17706
+ if (platform2 === "win32") {
17707
+ const url2 = `${DOLT_RELEASE_BASE}/dolt-${tuple}.zip`;
17708
+ const script = [
17709
+ `$ErrorActionPreference='Stop';`,
17710
+ `New-Item -ItemType Directory -Force -Path '${targetDir}' | Out-Null;`,
17711
+ `$u='${url2}';`,
17712
+ `$o="$env:TEMP\\dolt-cs.zip";`,
17713
+ `Invoke-WebRequest -Uri $u -OutFile $o;`,
17714
+ `$x="$env:TEMP\\dolt-cs";`,
17715
+ `Expand-Archive -Path $o -DestinationPath $x -Force;`,
17716
+ `Copy-Item "$x\\dolt-${tuple}\\bin\\dolt.exe" '${targetDir}\\dolt.exe' -Force`
17717
+ ].join(" ");
17718
+ return {
17719
+ command: "powershell.exe",
17720
+ args: ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", script],
17721
+ description: `download dolt ${tuple} zip \u2192 ${targetDir} (no sudo)`
17722
+ };
17723
+ }
17724
+ const url = `${DOLT_RELEASE_BASE}/dolt-${tuple}.tar.gz`;
17725
+ const cmd = `mkdir -p "${targetDir}" && curl -fsSL "${url}" | tar -xz -C "${targetDir}" --strip-components=2 "dolt-${tuple}/bin/dolt" && chmod +x "${targetDir}/dolt"`;
17726
+ return {
17727
+ command: "bash",
17728
+ args: ["-c", cmd],
17729
+ description: `download dolt ${tuple} tarball \u2192 ${targetDir} (no sudo)`
17730
+ };
17731
+ }
17732
+ async function installDoltToDir(targetDir, platform2 = process.platform, arch = process.arch) {
17733
+ const strategy = resolveDoltTarballStrategy(targetDir, platform2, arch);
17734
+ if (!strategy) {
17735
+ log.warn("beads", `no dolt prebuilt for ${platform2}/${arch} \u2014 cannot fall back`);
17736
+ return { ok: false, code: -1, stderr: `unsupported platform ${platform2}/${arch}` };
17737
+ }
17738
+ log.info("beads", `dolt fallback: ${strategy.description}`);
17739
+ const result = await _doltInstallSpawnSeam.run(strategy);
17740
+ if (!result.ok) {
17741
+ log.warn("beads", `dolt tarball fallback failed (code=${result.code}): ${result.stderr.slice(0, 200)}`);
17742
+ }
17743
+ return result;
17744
+ }
17745
+ var _doltPathSeam = {
17746
+ homedir: () => os25.homedir(),
17747
+ getPath: () => process.env.PATH ?? "",
17748
+ setPath: (p2) => {
17749
+ process.env.PATH = p2;
17750
+ },
17751
+ exists: (p2) => {
17752
+ try {
17753
+ fs30.accessSync(p2, fs30.constants.F_OK);
17754
+ return true;
17755
+ } catch {
17756
+ return false;
17757
+ }
17758
+ }
17759
+ };
17760
+ function doltBinaryNames(platform2) {
17761
+ return platform2 === "win32" ? ["dolt.exe", "dolt.cmd", "dolt"] : ["dolt"];
17762
+ }
17763
+ function knownDoltDirs(platform2) {
17764
+ const P3 = platform2 === "win32" ? path36.win32 : path36.posix;
17765
+ const home = _doltPathSeam.homedir();
17766
+ if (platform2 === "win32") {
17767
+ return [
17768
+ "C:\\Program Files\\Dolt\\bin",
17769
+ home ? P3.join(home, "AppData", "Local", "Programs", "dolt", "bin") : ""
17770
+ ].filter(Boolean);
17771
+ }
17772
+ return [
17773
+ "/usr/local/bin",
17774
+ "/opt/homebrew/bin",
17775
+ home ? P3.join(home, ".local", "bin") : "",
17776
+ home ? P3.join(home, "bin") : ""
17777
+ ].filter(Boolean);
17778
+ }
17779
+ function ensureDoltResolvable(platform2 = process.platform) {
17780
+ const P3 = platform2 === "win32" ? path36.win32 : path36.posix;
17781
+ const delim = platform2 === "win32" ? ";" : ":";
17782
+ const names = doltBinaryNames(platform2);
17783
+ const pathDirs = _doltPathSeam.getPath().split(delim).filter(Boolean);
17784
+ for (const dir of pathDirs) {
17785
+ for (const n of names) {
17786
+ if (_doltPathSeam.exists(P3.join(dir, n))) return true;
17787
+ }
17788
+ }
17789
+ for (const dir of knownDoltDirs(platform2)) {
17790
+ for (const n of names) {
17791
+ if (_doltPathSeam.exists(P3.join(dir, n))) {
17792
+ _doltPathSeam.setPath(`${dir}${delim}${_doltPathSeam.getPath()}`);
17793
+ log.info("beads", `dolt found in ${dir} (not on PATH) \u2014 prepended to process PATH`);
17794
+ return true;
17795
+ }
17796
+ }
17797
+ }
17798
+ return false;
17799
+ }
17800
+ var _doltInstallSpawnSeam = {
17801
+ run: _defaultDoltInstallSpawn
17802
+ };
17803
+ var DOLT_INSTALL_TIMEOUT_MS = 12e4;
17804
+ function _defaultDoltInstallSpawn(strategy) {
17805
+ return new Promise((resolve7) => {
17806
+ let settled = false;
17807
+ let timer;
17808
+ const finish = (r) => {
17809
+ if (settled) return;
17810
+ settled = true;
17811
+ if (timer) clearTimeout(timer);
17812
+ resolve7(r);
17813
+ };
17814
+ let proc;
17815
+ try {
17816
+ proc = (0, import_child_process15.spawn)(strategy.command, strategy.args, {
17817
+ env: process.env,
17818
+ stdio: ["ignore", "pipe", "pipe"]
17819
+ });
17820
+ } catch (err) {
17821
+ finish({ ok: false, code: -1, stderr: err.message });
17822
+ return;
17823
+ }
17824
+ timer = setTimeout(() => {
17825
+ try {
17826
+ proc.kill("SIGKILL");
17827
+ } catch {
17828
+ }
17829
+ finish({
17830
+ ok: false,
17831
+ code: -1,
17832
+ stderr: `dolt install timed out after ${DOLT_INSTALL_TIMEOUT_MS}ms`
17833
+ });
17834
+ }, DOLT_INSTALL_TIMEOUT_MS);
17835
+ let stderr = "";
17836
+ proc.stderr?.on("data", (c2) => {
17837
+ stderr += c2.toString();
17838
+ });
17839
+ proc.on("error", (err) => finish({ ok: false, code: -1, stderr: err.message }));
17840
+ proc.on("close", (code) => finish({ ok: code === 0, code: code ?? -1, stderr }));
17841
+ });
17842
+ }
17843
+ async function installDolt(platform2 = process.platform) {
17844
+ const strategy = resolveDoltInstallStrategy(platform2);
17845
+ log.info("beads", `installing dolt via ${strategy.description}`);
17846
+ const result = await _doltInstallSpawnSeam.run(strategy);
17847
+ if (!result.ok) {
17848
+ log.warn(
17849
+ "beads",
17850
+ `dolt install failed (code=${result.code}): ${result.stderr.slice(0, 200)}`
17851
+ );
17852
+ }
17853
+ return result;
17854
+ }
17855
+
17856
+ // src/beads/dolt-daemon.ts
17857
+ var _daemonSeam = {
17858
+ /**
17859
+ * Parse `bd dolt status` stdout. Running blocks lead with
17860
+ * `Dolt server: running`; down blocks say `Dolt server: not running`.
17861
+ * Match the affirmative form explicitly so "not running" can't false-positive.
17862
+ */
17863
+ isRunning: (statusStdout) => /Dolt server:\s*running/i.test(statusStdout)
17864
+ };
17865
+ async function ensureSharedServer(adapter) {
17866
+ const status2 = await adapter.run(["dolt", "status"]);
17867
+ if (status2.code === 0 && _daemonSeam.isRunning(status2.stdout)) {
17868
+ log.trace("beads", "shared dolt sql-server already running \u2014 reusing");
17869
+ return { up: true, started: false };
17870
+ }
17871
+ log.info("beads", "shared dolt sql-server not running \u2014 starting (detached)");
17872
+ const start2 = await adapter.run(["dolt", "start"]);
17873
+ if (start2.code !== 0) {
17874
+ log.warn(
17875
+ "beads",
17876
+ `bd dolt start failed (code=${start2.code}): ${start2.stderr.slice(0, 200)} \u2014 beads memory unavailable this run`
17877
+ );
17878
+ return { up: false, started: false };
17879
+ }
17880
+ const recheck = await adapter.run(["dolt", "status"]);
17881
+ const up = recheck.code === 0 && _daemonSeam.isRunning(recheck.stdout);
17882
+ if (!up) {
17883
+ log.warn("beads", "shared dolt sql-server still not reachable after start \u2014 non-fatal");
17884
+ }
17885
+ return { up, started: up };
17886
+ }
17887
+
17888
+ // src/beads/project-key.ts
17889
+ var import_child_process16 = require("child_process");
17890
+ var crypto2 = __toESM(require("crypto"));
17891
+ var fs31 = __toESM(require("fs"));
17892
+ var path37 = __toESM(require("path"));
17893
+ function normalizeOrigin(raw) {
17894
+ const trimmed = raw.trim();
17895
+ if (!trimmed) return null;
17896
+ let host;
17897
+ let pathPart;
17898
+ const scpLike = /^[^/@]+@([^:]+):(.+)$/.exec(trimmed);
17899
+ if (scpLike && !trimmed.includes("://")) {
17900
+ host = scpLike[1];
17901
+ pathPart = scpLike[2];
17902
+ } else {
17903
+ let url;
17904
+ try {
17905
+ url = new URL(trimmed);
17906
+ } catch {
17907
+ return null;
17908
+ }
17909
+ host = url.hostname;
17910
+ pathPart = url.pathname;
17911
+ }
17912
+ host = host.toLowerCase();
17913
+ pathPart = pathPart.replace(/^\/+/, "").replace(/\.git$/i, "").replace(/\/+$/, "");
17914
+ if (!host || !pathPart) return null;
17915
+ return `${host}/${pathPart}`;
17916
+ }
17917
+ function findRepoRoot(cwd) {
17918
+ let dir = path37.resolve(cwd);
17919
+ const seen = /* @__PURE__ */ new Set();
17920
+ for (let i = 0; i < 256; i++) {
17921
+ if (seen.has(dir)) return null;
17922
+ seen.add(dir);
17923
+ try {
17924
+ const stat3 = fs31.statSync(path37.join(dir, ".git"), { throwIfNoEntry: false });
17925
+ if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
17926
+ } catch {
17927
+ }
17928
+ const parent = path37.dirname(dir);
17929
+ if (parent === dir) return null;
17930
+ dir = parent;
17931
+ }
17932
+ return null;
17933
+ }
17934
+ var _execSeam2 = {
17935
+ exec: (file, args2, opts) => {
17936
+ const out2 = (0, import_child_process16.execFileSync)(file, args2, opts);
17937
+ return typeof out2 === "string" ? out2 : out2.toString("utf8");
17938
+ },
17939
+ realpath: (p2) => fs31.realpathSync(p2)
17940
+ };
17941
+ function readOrigin(cwd) {
17942
+ try {
17943
+ const raw = _execSeam2.exec("git", ["remote", "get-url", "origin"], {
17944
+ cwd,
17945
+ timeout: 1e3,
17946
+ stdio: ["ignore", "pipe", "ignore"],
17947
+ encoding: "utf8"
17948
+ });
17949
+ return raw.trim() || null;
17950
+ } catch {
17951
+ return null;
17952
+ }
17953
+ }
17954
+ function deriveProjectIdentity(cwd = process.cwd()) {
17955
+ const repoRoot = findRepoRoot(cwd) ?? cwd;
17956
+ const origin = readOrigin(repoRoot);
17957
+ const normalized = origin ? normalizeOrigin(origin) : null;
17958
+ if (normalized) {
17959
+ const label = normalized.split("/").pop() || normalized;
17960
+ return { projectKey: normalized, projectLabel: label };
17961
+ }
17962
+ let real = repoRoot;
17963
+ try {
17964
+ real = _execSeam2.realpath(repoRoot);
17965
+ } catch {
17966
+ }
17967
+ const hash = crypto2.createHash("sha256").update(real).digest("hex");
17968
+ return { projectKey: `path:${hash}`, projectLabel: path37.basename(real) || "project" };
17969
+ }
17970
+
17971
+ // src/beads/project-prefix.ts
17972
+ var crypto3 = __toESM(require("crypto"));
17973
+ function prefixForProjectKey(projectKey) {
17974
+ const tail = projectKey.split("/").pop() ?? projectKey;
17975
+ let slug = tail.toLowerCase().replace(/\.git$/, "").replace(/[^a-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
17976
+ if (!slug || !/^[a-z]/.test(slug)) slug = `p_${slug}`;
17977
+ slug = slug.replace(/_$/, "").slice(0, 24).replace(/_$/, "");
17978
+ const hash = crypto3.createHash("sha256").update(projectKey).digest("hex").slice(0, 8);
17979
+ return `${slug}_${hash}`;
17980
+ }
17981
+
17652
17982
  // src/beads/provisioner.ts
17653
17983
  var AGENT_SETUP_RECIPE = {
17654
17984
  claude: "claude",
@@ -17661,7 +17991,15 @@ var AGENT_SETUP_RECIPE = {
17661
17991
  };
17662
17992
  var _provisionSeam = {
17663
17993
  install: installBd,
17664
- homeBrainInitialized,
17994
+ installDolt,
17995
+ /** No-sudo fallback: extract the dolt tarball/zip into a user-writable dir. */
17996
+ installDoltToDir,
17997
+ // Probe dolt on PATH AND auto-prepend a known install dir if found off-PATH
17998
+ // (codespace: official install.sh drops dolt in /usr/local/bin, which the
17999
+ // bundled-node CLI's PATH can omit — mirrors the bd-on-PATH symlink fix).
18000
+ doltOnPath: ensureDoltResolvable,
18001
+ ensureSharedServer,
18002
+ deriveProjectIdentity,
17665
18003
  /** GAP 1 — symlink the resolved bd onto PATH for the agent's own shell. */
17666
18004
  linkBdOntoPath,
17667
18005
  /** Silence bd's `beads.role not configured` warning. */
@@ -17669,17 +18007,17 @@ var _provisionSeam = {
17669
18007
  };
17670
18008
  var _linkSeam = {
17671
18009
  platform: () => process.platform,
17672
- homedir: () => os25.homedir(),
18010
+ homedir: () => os26.homedir(),
17673
18011
  isWritableDir: (dir) => {
17674
18012
  try {
17675
- fs30.accessSync(dir, fs30.constants.W_OK);
18013
+ fs32.accessSync(dir, fs32.constants.W_OK);
17676
18014
  return true;
17677
18015
  } catch {
17678
18016
  return false;
17679
18017
  }
17680
18018
  },
17681
18019
  ensureDir: (dir) => {
17682
- fs30.mkdirSync(dir, { recursive: true });
18020
+ fs32.mkdirSync(dir, { recursive: true });
17683
18021
  },
17684
18022
  /**
17685
18023
  * A directory to symlink `bd` into so the AGENT's shell + Claude Code's
@@ -17700,12 +18038,12 @@ var _linkSeam = {
17700
18038
  * which `linkBdOntoPath` creates if missing.
17701
18039
  */
17702
18040
  cliBinDir: () => {
17703
- const pathDirs = (process.env.PATH ?? "").split(path36.delimiter).filter(Boolean);
18041
+ const pathDirs = (process.env.PATH ?? "").split(path38.delimiter).filter(Boolean);
17704
18042
  const home = _linkSeam.homedir();
17705
- const localBin = home ? path36.join(home, ".local", "bin") : null;
18043
+ const localBin = home ? path38.join(home, ".local", "bin") : null;
17706
18044
  const candidates = [];
17707
18045
  try {
17708
- candidates.push(path36.dirname(process.execPath));
18046
+ candidates.push(path38.dirname(process.execPath));
17709
18047
  } catch {
17710
18048
  }
17711
18049
  if (localBin) candidates.push(localBin);
@@ -17713,9 +18051,9 @@ var _linkSeam = {
17713
18051
  const entry = process.argv[1];
17714
18052
  if (entry) {
17715
18053
  try {
17716
- candidates.push(path36.dirname(fs30.realpathSync(entry)));
18054
+ candidates.push(path38.dirname(fs32.realpathSync(entry)));
17717
18055
  } catch {
17718
- candidates.push(path36.dirname(entry));
18056
+ candidates.push(path38.dirname(entry));
17719
18057
  }
17720
18058
  }
17721
18059
  const onPathWritable = candidates.find(
@@ -17727,20 +18065,20 @@ var _linkSeam = {
17727
18065
  /** Current symlink target at `linkPath`, or null when absent / not a link. */
17728
18066
  readlink: (linkPath) => {
17729
18067
  try {
17730
- return fs30.readlinkSync(linkPath);
18068
+ return fs32.readlinkSync(linkPath);
17731
18069
  } catch {
17732
18070
  return null;
17733
18071
  }
17734
18072
  },
17735
- unlink: (linkPath) => fs30.unlinkSync(linkPath),
17736
- symlink: (target, linkPath) => fs30.symlinkSync(target, linkPath)
18073
+ unlink: (linkPath) => fs32.unlinkSync(linkPath),
18074
+ symlink: (target, linkPath) => fs32.symlinkSync(target, linkPath)
17737
18075
  };
17738
18076
  function linkBdOntoPath(binaryPath) {
17739
18077
  if (_linkSeam.platform() === "win32") return;
17740
18078
  const binDir = _linkSeam.cliBinDir();
17741
18079
  if (!binDir) return;
17742
18080
  _linkSeam.ensureDir(binDir);
17743
- const linkPath = path36.join(binDir, "bd");
18081
+ const linkPath = path38.join(binDir, "bd");
17744
18082
  if (linkPath === binaryPath) return;
17745
18083
  const current = _linkSeam.readlink(linkPath);
17746
18084
  if (current === binaryPath) return;
@@ -17749,22 +18087,17 @@ function linkBdOntoPath(binaryPath) {
17749
18087
  log.info("beads", `linked bd onto PATH: ${linkPath} -> ${binaryPath}`);
17750
18088
  }
17751
18089
  function setGitBeadsRole() {
17752
- (0, import_child_process15.execFileSync)("git", ["config", "--global", "beads.role", "contributor"], {
18090
+ (0, import_child_process17.execFileSync)("git", ["config", "--global", "beads.role", "contributor"], {
17753
18091
  stdio: "ignore"
17754
18092
  });
17755
18093
  }
17756
- function homeBrainInitialized(beadsDir) {
17757
- try {
17758
- return fs30.statSync(path36.join(beadsDir, "embeddeddolt")).isDirectory();
17759
- } catch {
17760
- return false;
17761
- }
17762
- }
17763
18094
  async function provisionBeads(opts = {}) {
17764
18095
  const bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
17765
- const beadsDir = opts.beadsDir ?? defaultBeadsHomeDir();
17766
18096
  const result = {
17767
18097
  bdAvailable: false,
18098
+ doltAvailable: false,
18099
+ serverUp: false,
18100
+ prefix: null,
17768
18101
  initialized: false,
17769
18102
  exportEnabled: false,
17770
18103
  agentsWired: []
@@ -17795,24 +18128,57 @@ async function provisionBeads(opts = {}) {
17795
18128
  } catch (err) {
17796
18129
  log.trace("beads", `git config beads.role failed (non-fatal): ${err.message}`);
17797
18130
  }
17798
- if (_provisionSeam.homeBrainInitialized(beadsDir)) {
17799
- log.trace("beads", `home brain already initialized at ${beadsDir}`);
17800
- result.initialized = true;
17801
- } else {
17802
- log.info("beads", `initializing home brain at ${beadsDir}`);
17803
- const init = await bd.run(["init", "--skip-agents", "--skip-hooks", "--non-interactive"]);
17804
- if (init.code !== 0) {
17805
- log.warn("beads", `bd init failed (code=${init.code}): ${init.stderr.slice(0, 200)}`);
17806
- return result;
18131
+ if (!_provisionSeam.doltOnPath()) {
18132
+ log.info("beads", "dolt binary missing \u2014 running per-OS dolt installer");
18133
+ await _provisionSeam.installDolt();
18134
+ }
18135
+ if (!_provisionSeam.doltOnPath()) {
18136
+ const dir = _linkSeam.cliBinDir();
18137
+ if (dir) {
18138
+ try {
18139
+ _linkSeam.ensureDir(dir);
18140
+ } catch {
18141
+ }
18142
+ log.info("beads", `dolt still missing \u2014 no-sudo tarball fallback into ${dir}`);
18143
+ await _provisionSeam.installDoltToDir(dir);
17807
18144
  }
17808
- result.initialized = true;
18145
+ }
18146
+ if (!_provisionSeam.doltOnPath()) {
18147
+ log.warn("beads", "dolt unavailable after install + tarball fallback \u2014 beads memory disabled this run");
18148
+ return result;
18149
+ }
18150
+ result.doltAvailable = true;
18151
+ const { projectKey } = _provisionSeam.deriveProjectIdentity(opts.cwd);
18152
+ const prefix = prefixForProjectKey(projectKey);
18153
+ result.prefix = prefix;
18154
+ log.info("beads", `initializing shared-server prefix DB '${prefix}' (projectKey=${projectKey})`);
18155
+ const init = await bd.run([
18156
+ "init",
18157
+ "-p",
18158
+ prefix,
18159
+ "--shared-server",
18160
+ "--skip-agents",
18161
+ "--skip-hooks",
18162
+ "--non-interactive"
18163
+ ]);
18164
+ const alreadyInit = /already initialized|already exists/i.test(init.stderr + init.stdout);
18165
+ if (init.code !== 0 && !alreadyInit) {
18166
+ log.warn("beads", `bd init -p ${prefix} failed (code=${init.code}): ${init.stderr.slice(0, 200)}`);
18167
+ return result;
18168
+ }
18169
+ result.initialized = true;
18170
+ const server = await _provisionSeam.ensureSharedServer(bd);
18171
+ result.serverUp = server.up;
18172
+ if (!server.up) {
18173
+ log.warn("beads", "shared dolt sql-server not up \u2014 beads disabled this run");
18174
+ return result;
17809
18175
  }
17810
18176
  const exp = await bd.run(["config", "set", "export.auto", "true"]);
17811
18177
  result.exportEnabled = exp.code === 0;
17812
18178
  result.agentsWired = await setupAgents(bd, opts.agents ?? []);
17813
18179
  log.info(
17814
18180
  "beads",
17815
- `provision done initialized=${result.initialized} export=${result.exportEnabled} agentsWired=[${result.agentsWired.join(",")}]`
18181
+ `provision done dolt=${result.doltAvailable} server=${result.serverUp} prefix=${result.prefix} initialized=${result.initialized} export=${result.exportEnabled} agentsWired=[${result.agentsWired.join(",")}]`
17816
18182
  );
17817
18183
  return result;
17818
18184
  }
@@ -17852,91 +18218,8 @@ function dedupeRecipes(agents) {
17852
18218
  }
17853
18219
 
17854
18220
  // src/beads/watcher.ts
17855
- var crypto3 = __toESM(require("crypto"));
17856
- var path38 = __toESM(require("path"));
17857
-
17858
- // src/beads/project-key.ts
17859
- var import_child_process16 = require("child_process");
17860
- var crypto2 = __toESM(require("crypto"));
17861
- var fs31 = __toESM(require("fs"));
17862
- var path37 = __toESM(require("path"));
17863
- function normalizeOrigin(raw) {
17864
- const trimmed = raw.trim();
17865
- if (!trimmed) return null;
17866
- let host;
17867
- let pathPart;
17868
- const scpLike = /^[^/@]+@([^:]+):(.+)$/.exec(trimmed);
17869
- if (scpLike && !trimmed.includes("://")) {
17870
- host = scpLike[1];
17871
- pathPart = scpLike[2];
17872
- } else {
17873
- let url;
17874
- try {
17875
- url = new URL(trimmed);
17876
- } catch {
17877
- return null;
17878
- }
17879
- host = url.hostname;
17880
- pathPart = url.pathname;
17881
- }
17882
- host = host.toLowerCase();
17883
- pathPart = pathPart.replace(/^\/+/, "").replace(/\.git$/i, "").replace(/\/+$/, "");
17884
- if (!host || !pathPart) return null;
17885
- return `${host}/${pathPart}`;
17886
- }
17887
- function findRepoRoot(cwd) {
17888
- let dir = path37.resolve(cwd);
17889
- const seen = /* @__PURE__ */ new Set();
17890
- for (let i = 0; i < 256; i++) {
17891
- if (seen.has(dir)) return null;
17892
- seen.add(dir);
17893
- try {
17894
- const stat3 = fs31.statSync(path37.join(dir, ".git"), { throwIfNoEntry: false });
17895
- if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
17896
- } catch {
17897
- }
17898
- const parent = path37.dirname(dir);
17899
- if (parent === dir) return null;
17900
- dir = parent;
17901
- }
17902
- return null;
17903
- }
17904
- var _execSeam2 = {
17905
- exec: (file, args2, opts) => {
17906
- const out2 = (0, import_child_process16.execFileSync)(file, args2, opts);
17907
- return typeof out2 === "string" ? out2 : out2.toString("utf8");
17908
- },
17909
- realpath: (p2) => fs31.realpathSync(p2)
17910
- };
17911
- function readOrigin(cwd) {
17912
- try {
17913
- const raw = _execSeam2.exec("git", ["remote", "get-url", "origin"], {
17914
- cwd,
17915
- timeout: 1e3,
17916
- stdio: ["ignore", "pipe", "ignore"],
17917
- encoding: "utf8"
17918
- });
17919
- return raw.trim() || null;
17920
- } catch {
17921
- return null;
17922
- }
17923
- }
17924
- function deriveProjectIdentity(cwd = process.cwd()) {
17925
- const repoRoot = findRepoRoot(cwd) ?? cwd;
17926
- const origin = readOrigin(repoRoot);
17927
- const normalized = origin ? normalizeOrigin(origin) : null;
17928
- if (normalized) {
17929
- const label = normalized.split("/").pop() || normalized;
17930
- return { projectKey: normalized, projectLabel: label };
17931
- }
17932
- let real = repoRoot;
17933
- try {
17934
- real = _execSeam2.realpath(repoRoot);
17935
- } catch {
17936
- }
17937
- const hash = crypto2.createHash("sha256").update(real).digest("hex");
17938
- return { projectKey: `path:${hash}`, projectLabel: path37.basename(real) || "project" };
17939
- }
18221
+ var crypto4 = __toESM(require("crypto"));
18222
+ var path39 = __toESM(require("path"));
17940
18223
 
17941
18224
  // src/services/file-watcher/transport.ts
17942
18225
  var http5 = __toESM(require("http"));
@@ -18011,7 +18294,7 @@ var BeadsWatcher = class {
18011
18294
  constructor(opts) {
18012
18295
  this.opts = opts;
18013
18296
  this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
18014
- this.feedPath = opts.feedPath ?? path38.join(defaultBeadsHomeDir(), "issues.jsonl");
18297
+ this.feedPath = opts.feedPath ?? path39.join(defaultBeadsHomeDir(), "issues.jsonl");
18015
18298
  this.apiBase = opts.apiBaseUrl ?? API_BASE4;
18016
18299
  }
18017
18300
  opts;
@@ -18107,7 +18390,7 @@ var BeadsWatcher = class {
18107
18390
  summary: summary ?? ZERO_SUMMARY
18108
18391
  };
18109
18392
  const body = JSON.stringify(payload);
18110
- const hash = crypto3.createHash("sha256").update(body).digest("hex");
18393
+ const hash = crypto4.createHash("sha256").update(body).digest("hex");
18111
18394
  if (hash === this.lastPushedHash) {
18112
18395
  log.trace("beads", "snapshot unchanged \u2014 skipping push");
18113
18396
  return;
@@ -18192,8 +18475,8 @@ async function applyBeadsAction(action, deps) {
18192
18475
  async function startBeads(opts) {
18193
18476
  const adapter = new BdAdapter({ cwd: opts.cwd });
18194
18477
  const provision = await provisionBeads({ cwd: opts.cwd, adapter, agents: opts.agents });
18195
- if (!provision.bdAvailable || !provision.initialized) {
18196
- log.warn("beads", "home brain not provisioned \u2014 watcher not started this run");
18478
+ if (!provision.bdAvailable || !provision.initialized || !provision.serverUp) {
18479
+ log.warn("beads", "beads not fully provisioned \u2014 watcher not started this run");
18197
18480
  return null;
18198
18481
  }
18199
18482
  const watcher = new BeadsWatcher({
@@ -18225,6 +18508,7 @@ async function provisionBeadsForStart(ctx) {
18225
18508
  return null;
18226
18509
  }
18227
18510
  process.env.BEADS_DIR = defaultBeadsHomeDir();
18511
+ process.env.BEADS_DOLT_SHARED_SERVER = "1";
18228
18512
  if (!ctx.pluginAuthToken) {
18229
18513
  log.trace("beads", "no pluginAuthToken \u2014 beads off");
18230
18514
  return null;
@@ -18288,7 +18572,7 @@ var pendingAttachmentFiles = /* @__PURE__ */ new Set();
18288
18572
  function cleanupAttachmentTempFiles() {
18289
18573
  for (const p2 of pendingAttachmentFiles) {
18290
18574
  try {
18291
- fs32.unlinkSync(p2);
18575
+ fs33.unlinkSync(p2);
18292
18576
  } catch {
18293
18577
  }
18294
18578
  }
@@ -18297,8 +18581,8 @@ function cleanupAttachmentTempFiles() {
18297
18581
  function saveFilesTemp(files) {
18298
18582
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
18299
18583
  const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
18300
- const tmpPath = path39.join(os26.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
18301
- fs32.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
18584
+ const tmpPath = path40.join(os27.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
18585
+ fs33.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
18302
18586
  pendingAttachmentFiles.add(tmpPath);
18303
18587
  return tmpPath;
18304
18588
  });
@@ -18318,7 +18602,7 @@ var startTask = (ctx, _cmd, parsed) => {
18318
18602
  setTimeout(() => {
18319
18603
  for (const p2 of paths) {
18320
18604
  try {
18321
- fs32.unlinkSync(p2);
18605
+ fs33.unlinkSync(p2);
18322
18606
  } catch {
18323
18607
  }
18324
18608
  pendingAttachmentFiles.delete(p2);
@@ -18443,7 +18727,7 @@ var sessionTerminated = async (ctx, cmd) => {
18443
18727
  } catch {
18444
18728
  }
18445
18729
  try {
18446
- const proc = (0, import_child_process17.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
18730
+ const proc = (0, import_child_process18.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
18447
18731
  detached: true,
18448
18732
  stdio: "ignore"
18449
18733
  });
@@ -18465,7 +18749,7 @@ var shutdownSession = async (ctx, cmd) => {
18465
18749
  }
18466
18750
  if (ctx.keepAliveCtx.inCodespace && ctx.keepAliveCtx.codespaceName) {
18467
18751
  try {
18468
- const stopProc = (0, import_child_process17.spawn)(
18752
+ const stopProc = (0, import_child_process18.spawn)(
18469
18753
  "bash",
18470
18754
  ["-lc", `sleep 1; gh codespace stop -c ${JSON.stringify(ctx.keepAliveCtx.codespaceName)} >/dev/null 2>&1 || true`],
18471
18755
  { detached: true, stdio: "ignore" }
@@ -18475,7 +18759,7 @@ var shutdownSession = async (ctx, cmd) => {
18475
18759
  }
18476
18760
  }
18477
18761
  try {
18478
- const proc = (0, import_child_process17.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
18762
+ const proc = (0, import_child_process18.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
18479
18763
  detached: true,
18480
18764
  stdio: "ignore"
18481
18765
  });
@@ -18901,8 +19185,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
18901
19185
  if (args2.length === 0) return detection;
18902
19186
  const binName = args2[0];
18903
19187
  if (binName.startsWith("-")) return detection;
18904
- const binPath = path39.join(cwd, "node_modules", ".bin", binName);
18905
- if (!fs32.existsSync(binPath)) return detection;
19188
+ const binPath = path40.join(cwd, "node_modules", ".bin", binName);
19189
+ if (!fs33.existsSync(binPath)) return detection;
18906
19190
  return {
18907
19191
  ...detection,
18908
19192
  command: binPath,
@@ -19028,7 +19312,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
19028
19312
  "BOOT_SEQUENCE",
19029
19313
  `${spawnable.command} ${spawnable.args.join(" ")}`
19030
19314
  );
19031
- const devServer = (0, import_child_process17.spawn)(spawnable.command, spawnable.args, {
19315
+ const devServer = (0, import_child_process18.spawn)(spawnable.command, spawnable.args, {
19032
19316
  cwd: process.cwd(),
19033
19317
  env: { ...process.env, ...spawnable.env ?? {} },
19034
19318
  stdio: ["ignore", "pipe", "pipe"]
@@ -19156,7 +19440,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
19156
19440
  });
19157
19441
  return;
19158
19442
  }
19159
- tunnel = (0, import_child_process17.spawn)(bin, ["tunnel", "--url", `http://localhost:${detection.port}`], {
19443
+ tunnel = (0, import_child_process18.spawn)(bin, ["tunnel", "--url", `http://localhost:${detection.port}`], {
19160
19444
  stdio: ["ignore", "pipe", "pipe"]
19161
19445
  });
19162
19446
  let parsedUrl = null;
@@ -19331,10 +19615,10 @@ async function dispatchCommand(ctx, cmd) {
19331
19615
  }
19332
19616
 
19333
19617
  // src/services/file-watcher.service.ts
19334
- var import_child_process18 = require("child_process");
19335
- var fs33 = __toESM(require("fs"));
19336
- var os27 = __toESM(require("os"));
19337
- var path40 = __toESM(require("path"));
19618
+ var import_child_process19 = require("child_process");
19619
+ var fs34 = __toESM(require("fs"));
19620
+ var os28 = __toESM(require("os"));
19621
+ var path41 = __toESM(require("path"));
19338
19622
  var import_ignore = __toESM(require("ignore"));
19339
19623
 
19340
19624
  // src/services/file-watcher/diff-parser.ts
@@ -19444,10 +19728,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
19444
19728
  /[\\/]Start Menu([\\/]|$)/i,
19445
19729
  /[\\/]Templates([\\/]|$)/i
19446
19730
  ];
19447
- function isUnsafeWindowsWatchRoot(dir, homedir23) {
19731
+ function isUnsafeWindowsWatchRoot(dir, homedir24) {
19448
19732
  const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
19449
19733
  const cwd = norm(dir);
19450
- const home = norm(homedir23);
19734
+ const home = norm(homedir24);
19451
19735
  if (cwd === home) return true;
19452
19736
  if (/^[a-z]:$/.test(cwd)) return true;
19453
19737
  const sysRoots = [
@@ -19477,18 +19761,18 @@ var _findGitRootSeam = {
19477
19761
  resolve: _defaultFindGitRoot
19478
19762
  };
19479
19763
  function _defaultFindGitRoot(startDir) {
19480
- let dir = path40.resolve(startDir);
19764
+ let dir = path41.resolve(startDir);
19481
19765
  const seen = /* @__PURE__ */ new Set();
19482
19766
  for (let i = 0; i < 256; i++) {
19483
19767
  if (seen.has(dir)) return null;
19484
19768
  seen.add(dir);
19485
19769
  try {
19486
- const gitPath = path40.join(dir, ".git");
19487
- const stat3 = fs33.statSync(gitPath, { throwIfNoEntry: false });
19770
+ const gitPath = path41.join(dir, ".git");
19771
+ const stat3 = fs34.statSync(gitPath, { throwIfNoEntry: false });
19488
19772
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
19489
19773
  } catch {
19490
19774
  }
19491
- const parent = path40.dirname(dir);
19775
+ const parent = path41.dirname(dir);
19492
19776
  if (parent === dir) return null;
19493
19777
  dir = parent;
19494
19778
  }
@@ -19546,7 +19830,7 @@ var FileWatcherService = class {
19546
19830
  throw new Error("FileWatcherService has already been stopped \u2014 re-instantiate to restart.");
19547
19831
  }
19548
19832
  const isWin = process.platform === "win32";
19549
- if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os27.homedir())) {
19833
+ if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os28.homedir())) {
19550
19834
  log.warn(
19551
19835
  "fileWatcher",
19552
19836
  `refusing to watch ${this.opts.workingDir} \u2014 looks like a Windows user-profile or system path. Run codeam from your project folder to enable file change emission.`
@@ -19733,7 +20017,7 @@ var FileWatcherService = class {
19733
20017
  }
19734
20018
  async emitForFile(absPath, changeType) {
19735
20019
  if (this.stopped) return;
19736
- const fileDir = path40.dirname(absPath);
20020
+ const fileDir = path41.dirname(absPath);
19737
20021
  let gitRoot = this.gitRootByDir.get(fileDir);
19738
20022
  if (gitRoot === void 0) {
19739
20023
  gitRoot = findGitRoot2(fileDir);
@@ -19746,19 +20030,19 @@ var FileWatcherService = class {
19746
20030
  );
19747
20031
  return;
19748
20032
  }
19749
- const relPathInRepo = path40.relative(gitRoot, absPath);
20033
+ const relPathInRepo = path41.relative(gitRoot, absPath);
19750
20034
  if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
19751
20035
  const matcher = this.getGitIgnoreMatcher(gitRoot);
19752
20036
  if (matcher && matcher.ignores(relPathInRepo)) {
19753
20037
  log.trace(
19754
20038
  "fileWatcher",
19755
- `${relPathInRepo} ignored by ${path40.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
20039
+ `${relPathInRepo} ignored by ${path41.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
19756
20040
  );
19757
20041
  return;
19758
20042
  }
19759
20043
  this.opts.onRepoDirty?.(gitRoot);
19760
- const repoPath = path40.relative(this.opts.workingDir, gitRoot);
19761
- const repoName = path40.basename(gitRoot);
20044
+ const repoPath = path41.relative(this.opts.workingDir, gitRoot);
20045
+ const repoName = path41.basename(gitRoot);
19762
20046
  let diffText = "";
19763
20047
  let fileStatus = "modified";
19764
20048
  if (changeType === "unlink") {
@@ -19933,7 +20217,7 @@ var FileWatcherService = class {
19933
20217
  collectGitignoreFiles(repoRoot, dir, matcher) {
19934
20218
  let entries;
19935
20219
  try {
19936
- entries = fs33.readdirSync(dir, { withFileTypes: true });
20220
+ entries = fs34.readdirSync(dir, { withFileTypes: true });
19937
20221
  } catch {
19938
20222
  return;
19939
20223
  }
@@ -19942,16 +20226,16 @@ var FileWatcherService = class {
19942
20226
  );
19943
20227
  if (gitignoreEntry) {
19944
20228
  try {
19945
- const body = fs33.readFileSync(path40.join(dir, ".gitignore"), "utf8");
19946
- const rel = path40.relative(repoRoot, dir).replace(/\\/g, "/");
20229
+ const body = fs34.readFileSync(path41.join(dir, ".gitignore"), "utf8");
20230
+ const rel = path41.relative(repoRoot, dir).replace(/\\/g, "/");
19947
20231
  const prefixed = body.split(/\r?\n/).map((line) => {
19948
20232
  const trimmed = line.trim();
19949
20233
  if (!trimmed || trimmed.startsWith("#")) return line;
19950
20234
  if (!rel) return line;
19951
20235
  if (trimmed.startsWith("!")) {
19952
- return "!" + path40.posix.join(rel, trimmed.slice(1));
20236
+ return "!" + path41.posix.join(rel, trimmed.slice(1));
19953
20237
  }
19954
- return path40.posix.join(rel, trimmed);
20238
+ return path41.posix.join(rel, trimmed);
19955
20239
  }).join("\n");
19956
20240
  matcher.add(prefixed);
19957
20241
  } catch {
@@ -19960,7 +20244,7 @@ var FileWatcherService = class {
19960
20244
  for (const entry of entries) {
19961
20245
  if (!entry.isDirectory()) continue;
19962
20246
  if (entry.name === ".git") continue;
19963
- const childAbs = path40.join(dir, entry.name);
20247
+ const childAbs = path41.join(dir, entry.name);
19964
20248
  if (isIgnoredFilePath(childAbs)) continue;
19965
20249
  this.collectGitignoreFiles(repoRoot, childAbs, matcher);
19966
20250
  }
@@ -20097,7 +20381,7 @@ async function _runGitImpl(cwd, args2, opts = {}) {
20097
20381
  return new Promise((resolve7) => {
20098
20382
  let proc;
20099
20383
  try {
20100
- proc = (0, import_child_process18.spawn)("git", args2, { cwd, env: process.env });
20384
+ proc = (0, import_child_process19.spawn)("git", args2, { cwd, env: process.env });
20101
20385
  } catch {
20102
20386
  resolve7(null);
20103
20387
  return;
@@ -20129,8 +20413,8 @@ function _runGit(cwd, args2, opts = {}) {
20129
20413
  var import_crypto4 = require("crypto");
20130
20414
 
20131
20415
  // src/services/turn-files/git-changeset.ts
20132
- var import_child_process19 = require("child_process");
20133
- var path41 = __toESM(require("path"));
20416
+ var import_child_process20 = require("child_process");
20417
+ var path42 = __toESM(require("path"));
20134
20418
  async function collectRepoChangeset(opts) {
20135
20419
  const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
20136
20420
  if (status2 === null) return null;
@@ -20213,7 +20497,7 @@ function defaultRunGit(cwd, args2) {
20213
20497
  return new Promise((resolve7) => {
20214
20498
  let proc;
20215
20499
  try {
20216
- proc = (0, import_child_process19.spawn)("git", args2, { cwd, env: process.env });
20500
+ proc = (0, import_child_process20.spawn)("git", args2, { cwd, env: process.env });
20217
20501
  } catch {
20218
20502
  resolve7(null);
20219
20503
  return;
@@ -20241,7 +20525,7 @@ function defaultRunGit(cwd, args2) {
20241
20525
  });
20242
20526
  }
20243
20527
  async function discoverRepos(workingDir, maxDepth = 4) {
20244
- const fs39 = await import("fs/promises");
20528
+ const fs40 = await import("fs/promises");
20245
20529
  const out2 = [];
20246
20530
  await walk(workingDir, 0);
20247
20531
  return out2;
@@ -20249,7 +20533,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
20249
20533
  if (depth > maxDepth) return;
20250
20534
  let entries = [];
20251
20535
  try {
20252
- const dirents = await fs39.readdir(dir, { withFileTypes: true });
20536
+ const dirents = await fs40.readdir(dir, { withFileTypes: true });
20253
20537
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
20254
20538
  } catch {
20255
20539
  return;
@@ -20260,8 +20544,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
20260
20544
  if (hasGit) {
20261
20545
  out2.push({
20262
20546
  repoRoot: dir,
20263
- repoPath: path41.relative(workingDir, dir),
20264
- repoName: path41.basename(dir)
20547
+ repoPath: path42.relative(workingDir, dir),
20548
+ repoName: path42.basename(dir)
20265
20549
  });
20266
20550
  return;
20267
20551
  }
@@ -20269,14 +20553,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
20269
20553
  if (!entry.isDirectory) continue;
20270
20554
  if (entry.name === "node_modules") continue;
20271
20555
  if (entry.name === "dist" || entry.name === "build") continue;
20272
- await walk(path41.join(dir, entry.name), depth + 1);
20556
+ await walk(path42.join(dir, entry.name), depth + 1);
20273
20557
  }
20274
20558
  }
20275
20559
  }
20276
20560
 
20277
20561
  // src/services/turn-files/files-outbox.ts
20278
- var fs34 = __toESM(require("fs/promises"));
20279
- var path42 = __toESM(require("path"));
20562
+ var fs35 = __toESM(require("fs/promises"));
20563
+ var path43 = __toESM(require("path"));
20280
20564
  var import_os7 = require("os");
20281
20565
  var HOME_OUTBOX_DIR = ".codeam/outbox";
20282
20566
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -20309,16 +20593,16 @@ var FilesOutbox = class {
20309
20593
  backoffIndex = 0;
20310
20594
  stopped = false;
20311
20595
  constructor(opts) {
20312
- const base = opts.baseDir ?? path42.join(homeDir(), HOME_OUTBOX_DIR);
20313
- this.filePath = path42.join(base, `${opts.sessionId}.jsonl`);
20596
+ const base = opts.baseDir ?? path43.join(homeDir(), HOME_OUTBOX_DIR);
20597
+ this.filePath = path43.join(base, `${opts.sessionId}.jsonl`);
20314
20598
  this.post = opts.post;
20315
20599
  this.autoSchedule = opts.autoSchedule !== false;
20316
20600
  }
20317
20601
  /** Persist the entry to disk and trigger a flush. Returns once the
20318
20602
  * line is durable on disk (not once the POST succeeds). */
20319
20603
  async enqueue(entry) {
20320
- await fs34.mkdir(path42.dirname(this.filePath), { recursive: true });
20321
- await fs34.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
20604
+ await fs35.mkdir(path43.dirname(this.filePath), { recursive: true });
20605
+ await fs35.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
20322
20606
  this.backoffIndex = 0;
20323
20607
  if (this.autoSchedule) this.scheduleFlush(0);
20324
20608
  }
@@ -20407,7 +20691,7 @@ var FilesOutbox = class {
20407
20691
  async readAll() {
20408
20692
  let raw = "";
20409
20693
  try {
20410
- raw = await fs34.readFile(this.filePath, "utf8");
20694
+ raw = await fs35.readFile(this.filePath, "utf8");
20411
20695
  } catch {
20412
20696
  return [];
20413
20697
  }
@@ -20431,12 +20715,12 @@ var FilesOutbox = class {
20431
20715
  async rewrite(entries) {
20432
20716
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
20433
20717
  if (entries.length === 0) {
20434
- await fs34.unlink(this.filePath).catch(() => void 0);
20718
+ await fs35.unlink(this.filePath).catch(() => void 0);
20435
20719
  return;
20436
20720
  }
20437
20721
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
20438
- await fs34.writeFile(tmpPath, payload, "utf8");
20439
- await fs34.rename(tmpPath, this.filePath);
20722
+ await fs35.writeFile(tmpPath, payload, "utf8");
20723
+ await fs35.rename(tmpPath, this.filePath);
20440
20724
  }
20441
20725
  };
20442
20726
  function applyJitter(ms) {
@@ -22243,9 +22527,9 @@ var OutputService = class _OutputService {
22243
22527
  };
22244
22528
 
22245
22529
  // src/services/history.service.ts
22246
- var fs35 = __toESM(require("fs"));
22247
- var path43 = __toESM(require("path"));
22248
- var os28 = __toESM(require("os"));
22530
+ var fs36 = __toESM(require("fs"));
22531
+ var path44 = __toESM(require("path"));
22532
+ var os29 = __toESM(require("os"));
22249
22533
  var https7 = __toESM(require("https"));
22250
22534
  var http7 = __toESM(require("http"));
22251
22535
  var import_zod2 = require("zod");
@@ -22272,7 +22556,7 @@ function parseJsonl(filePath) {
22272
22556
  const messages = [];
22273
22557
  let raw;
22274
22558
  try {
22275
- raw = fs35.readFileSync(filePath, "utf8");
22559
+ raw = fs36.readFileSync(filePath, "utf8");
22276
22560
  } catch (err) {
22277
22561
  if (err.code !== "ENOENT") {
22278
22562
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -22407,7 +22691,7 @@ var HistoryService = class _HistoryService {
22407
22691
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
22408
22692
  }
22409
22693
  get projectDir() {
22410
- return this.runtime.resolveHistoryDir(this.cwd) ?? path43.join(os28.homedir(), ".claude", "projects", encodeCwd(this.cwd));
22694
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path44.join(os29.homedir(), ".claude", "projects", encodeCwd(this.cwd));
22411
22695
  }
22412
22696
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
22413
22697
  setCurrentConversationId(id) {
@@ -22419,7 +22703,7 @@ var HistoryService = class _HistoryService {
22419
22703
  /** Return the current message count in the active conversation. */
22420
22704
  getCurrentMessageCount() {
22421
22705
  if (!this.currentConversationId) return 0;
22422
- const filePath = path43.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22706
+ const filePath = path44.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22423
22707
  return parseJsonl(filePath).length;
22424
22708
  }
22425
22709
  /**
@@ -22430,7 +22714,7 @@ var HistoryService = class _HistoryService {
22430
22714
  const deadline = Date.now() + timeoutMs;
22431
22715
  while (Date.now() < deadline) {
22432
22716
  if (!this.currentConversationId) return null;
22433
- const filePath = path43.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22717
+ const filePath = path44.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22434
22718
  const messages = parseJsonl(filePath);
22435
22719
  if (messages.length > previousCount) {
22436
22720
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -22456,16 +22740,16 @@ var HistoryService = class _HistoryService {
22456
22740
  const dir = this.projectDir;
22457
22741
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
22458
22742
  try {
22459
- const files = fs35.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
22743
+ const files = fs36.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
22460
22744
  try {
22461
- const stat3 = fs35.statSync(path43.join(dir, e.name));
22745
+ const stat3 = fs36.statSync(path44.join(dir, e.name));
22462
22746
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
22463
22747
  } catch {
22464
22748
  return { name: e.name, mtime: 0, birthtime: 0 };
22465
22749
  }
22466
22750
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
22467
22751
  if (files.length > 0) {
22468
- this.currentConversationId = path43.basename(files[0].name, ".jsonl");
22752
+ this.currentConversationId = path44.basename(files[0].name, ".jsonl");
22469
22753
  }
22470
22754
  } catch {
22471
22755
  }
@@ -22499,13 +22783,13 @@ var HistoryService = class _HistoryService {
22499
22783
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
22500
22784
  let entries;
22501
22785
  try {
22502
- entries = fs35.readdirSync(dir, { withFileTypes: true });
22786
+ entries = fs36.readdirSync(dir, { withFileTypes: true });
22503
22787
  } catch {
22504
22788
  return null;
22505
22789
  }
22506
22790
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
22507
22791
  try {
22508
- const stat3 = fs35.statSync(path43.join(dir, e.name));
22792
+ const stat3 = fs36.statSync(path44.join(dir, e.name));
22509
22793
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
22510
22794
  } catch {
22511
22795
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -22514,12 +22798,12 @@ var HistoryService = class _HistoryService {
22514
22798
  if (files.length === 0) return null;
22515
22799
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
22516
22800
  if (!files.some((f) => f.name === targetFile)) return null;
22517
- return this.extractUsageFromFile(path43.join(dir, targetFile));
22801
+ return this.extractUsageFromFile(path44.join(dir, targetFile));
22518
22802
  }
22519
22803
  extractUsageFromFile(filePath) {
22520
22804
  let raw;
22521
22805
  try {
22522
- raw = fs35.readFileSync(filePath, "utf8");
22806
+ raw = fs36.readFileSync(filePath, "utf8");
22523
22807
  } catch {
22524
22808
  return null;
22525
22809
  }
@@ -22564,9 +22848,9 @@ var HistoryService = class _HistoryService {
22564
22848
  let totalCost = 0;
22565
22849
  let files;
22566
22850
  try {
22567
- files = fs35.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
22851
+ files = fs36.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
22568
22852
  try {
22569
- return fs35.statSync(path43.join(projectDir, f)).mtimeMs >= monthStartMs;
22853
+ return fs36.statSync(path44.join(projectDir, f)).mtimeMs >= monthStartMs;
22570
22854
  } catch {
22571
22855
  return false;
22572
22856
  }
@@ -22577,7 +22861,7 @@ var HistoryService = class _HistoryService {
22577
22861
  for (const file of files) {
22578
22862
  let raw;
22579
22863
  try {
22580
- raw = fs35.readFileSync(path43.join(projectDir, file), "utf8");
22864
+ raw = fs36.readFileSync(path44.join(projectDir, file), "utf8");
22581
22865
  } catch {
22582
22866
  continue;
22583
22867
  }
@@ -22641,7 +22925,7 @@ var HistoryService = class _HistoryService {
22641
22925
  * showing an empty conversation.
22642
22926
  */
22643
22927
  async loadConversation(sessionId) {
22644
- const filePath = path43.join(this.projectDir, `${sessionId}.jsonl`);
22928
+ const filePath = path44.join(this.projectDir, `${sessionId}.jsonl`);
22645
22929
  const messages = parseJsonl(filePath);
22646
22930
  if (messages.length === 0) return;
22647
22931
  const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
@@ -22695,7 +22979,7 @@ var HistoryService = class _HistoryService {
22695
22979
  if (!this.currentConversationId) return 0;
22696
22980
  }
22697
22981
  const sessionId = this.currentConversationId;
22698
- const filePath = path43.join(this.projectDir, `${sessionId}.jsonl`);
22982
+ const filePath = path44.join(this.projectDir, `${sessionId}.jsonl`);
22699
22983
  const messages = parseJsonl(filePath);
22700
22984
  if (messages.length === 0) return 0;
22701
22985
  const marker = this.lastUploadedUuid.get(sessionId);
@@ -23121,13 +23405,13 @@ function fetchQuotaUsage(runtime, historySvc) {
23121
23405
  }
23122
23406
 
23123
23407
  // src/commands/start/keep-alive.ts
23124
- var import_child_process20 = require("child_process");
23408
+ var import_child_process21 = require("child_process");
23125
23409
  function buildKeepAlive(ctx) {
23126
23410
  let timer = null;
23127
23411
  async function setIdleTimeout(minutes) {
23128
23412
  if (!ctx.inCodespace || !ctx.codespaceName) return;
23129
23413
  await new Promise((resolve7) => {
23130
- const proc = (0, import_child_process20.spawn)(
23414
+ const proc = (0, import_child_process21.spawn)(
23131
23415
  "gh",
23132
23416
  [
23133
23417
  "api",
@@ -23612,8 +23896,8 @@ async function autoLinkAfterPair(opts) {
23612
23896
  }
23613
23897
 
23614
23898
  // src/commands/pair-auto.ts
23615
- var fs36 = __toESM(require("fs"));
23616
- var os29 = __toESM(require("os"));
23899
+ var fs37 = __toESM(require("fs"));
23900
+ var os30 = __toESM(require("os"));
23617
23901
  var import_crypto7 = require("crypto");
23618
23902
 
23619
23903
  // src/commands/start-infra-only.ts
@@ -23808,12 +24092,12 @@ function readTokenFromArgs(args2) {
23808
24092
  }
23809
24093
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
23810
24094
  if (fileFlag) {
23811
- const path50 = fileFlag.slice("--token-file=".length);
24095
+ const path51 = fileFlag.slice("--token-file=".length);
23812
24096
  try {
23813
- const content = fs36.readFileSync(path50, "utf8").trim();
23814
- if (content.length === 0) fail(`--token-file ${path50} is empty`);
24097
+ const content = fs37.readFileSync(path51, "utf8").trim();
24098
+ if (content.length === 0) fail(`--token-file ${path51} is empty`);
23815
24099
  try {
23816
- fs36.unlinkSync(path50);
24100
+ fs37.unlinkSync(path51);
23817
24101
  } catch {
23818
24102
  }
23819
24103
  return content;
@@ -23839,7 +24123,7 @@ async function claimOnce(token, pluginId) {
23839
24123
  pluginId,
23840
24124
  ideName: "codeam-cli (codespace)",
23841
24125
  ideVersion: process.env.npm_package_version ?? "unknown",
23842
- hostname: os29.hostname(),
24126
+ hostname: os30.hostname(),
23843
24127
  codespaceName: process.env.CODESPACE_NAME ?? "",
23844
24128
  // Current git branch of the codespace's working directory, so the
23845
24129
  // backend can populate `PairedSession.branch` for the codespace pair.
@@ -24076,11 +24360,11 @@ async function logout() {
24076
24360
  var import_picocolors10 = __toESM(require("picocolors"));
24077
24361
 
24078
24362
  // src/services/providers/github-codespaces.ts
24079
- var import_child_process21 = require("child_process");
24363
+ var import_child_process22 = require("child_process");
24080
24364
  var import_util4 = require("util");
24081
24365
  var import_picocolors8 = __toESM(require("picocolors"));
24082
- var path44 = __toESM(require("path"));
24083
- var execFileP5 = (0, import_util4.promisify)(import_child_process21.execFile);
24366
+ var path45 = __toESM(require("path"));
24367
+ var execFileP5 = (0, import_util4.promisify)(import_child_process22.execFile);
24084
24368
  var MAX_BUFFER = 8 * 1024 * 1024;
24085
24369
  function resetStdinForChild() {
24086
24370
  if (process.stdin.isTTY) {
@@ -24124,7 +24408,7 @@ var GitHubCodespacesProvider = class {
24124
24408
  if (!isAuthed) {
24125
24409
  resetStdinForChild();
24126
24410
  await new Promise((resolve7, reject) => {
24127
- const proc = (0, import_child_process21.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
24411
+ const proc = (0, import_child_process22.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
24128
24412
  stdio: "inherit"
24129
24413
  });
24130
24414
  proc.on("exit", (code) => {
@@ -24158,7 +24442,7 @@ var GitHubCodespacesProvider = class {
24158
24442
  wt(noteLines.join("\n"), "One more permission needed");
24159
24443
  resetStdinForChild();
24160
24444
  const refreshCode = await new Promise((resolve7, reject) => {
24161
- const proc = (0, import_child_process21.spawn)(
24445
+ const proc = (0, import_child_process22.spawn)(
24162
24446
  "gh",
24163
24447
  ["auth", "refresh", "-h", "github.com", "-s", "codespace"],
24164
24448
  { stdio: "inherit" }
@@ -24308,7 +24592,7 @@ var GitHubCodespacesProvider = class {
24308
24592
  O2.step(`Installing gh via ${installCmd.describe}\u2026`);
24309
24593
  resetStdinForChild();
24310
24594
  const ok = await new Promise((resolve7) => {
24311
- const proc = (0, import_child_process21.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
24595
+ const proc = (0, import_child_process22.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
24312
24596
  proc.on("exit", (code) => resolve7(code === 0));
24313
24597
  proc.on("error", () => resolve7(false));
24314
24598
  });
@@ -24335,7 +24619,7 @@ var GitHubCodespacesProvider = class {
24335
24619
  );
24336
24620
  resetStdinForChild();
24337
24621
  await new Promise((resolve7, reject) => {
24338
- const proc = (0, import_child_process21.spawn)(
24622
+ const proc = (0, import_child_process22.spawn)(
24339
24623
  "gh",
24340
24624
  ["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
24341
24625
  { stdio: "inherit" }
@@ -24513,7 +24797,7 @@ var GitHubCodespacesProvider = class {
24513
24797
  async streamCommand(workspaceId, command2) {
24514
24798
  resetStdinForChild();
24515
24799
  return new Promise((resolve7, reject) => {
24516
- const proc = (0, import_child_process21.spawn)(
24800
+ const proc = (0, import_child_process22.spawn)(
24517
24801
  "gh",
24518
24802
  ["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
24519
24803
  { stdio: "inherit" }
@@ -24540,11 +24824,11 @@ var GitHubCodespacesProvider = class {
24540
24824
  `mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
24541
24825
  ];
24542
24826
  await new Promise((resolve7, reject) => {
24543
- const tar = (0, import_child_process21.spawn)("tar", tarArgs, {
24827
+ const tar = (0, import_child_process22.spawn)("tar", tarArgs, {
24544
24828
  stdio: ["ignore", "pipe", "pipe"],
24545
24829
  env: tarEnv
24546
24830
  });
24547
- const ssh = (0, import_child_process21.spawn)("gh", sshArgs, {
24831
+ const ssh = (0, import_child_process22.spawn)("gh", sshArgs, {
24548
24832
  stdio: [tar.stdout, "pipe", "pipe"]
24549
24833
  });
24550
24834
  let tarErr = "";
@@ -24568,7 +24852,7 @@ var GitHubCodespacesProvider = class {
24568
24852
  });
24569
24853
  }
24570
24854
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
24571
- const remoteDir = path44.posix.dirname(remotePath);
24855
+ const remoteDir = path45.posix.dirname(remotePath);
24572
24856
  const parts = [
24573
24857
  `mkdir -p ${shellQuote(remoteDir)}`,
24574
24858
  `cat > ${shellQuote(remotePath)}`
@@ -24578,7 +24862,7 @@ var GitHubCodespacesProvider = class {
24578
24862
  }
24579
24863
  const cmd = parts.join(" && ");
24580
24864
  await new Promise((resolve7, reject) => {
24581
- const proc = (0, import_child_process21.spawn)(
24865
+ const proc = (0, import_child_process22.spawn)(
24582
24866
  "gh",
24583
24867
  ["codespace", "ssh", "-c", workspaceId, "--", cmd],
24584
24868
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -24636,11 +24920,11 @@ function shellQuote(s) {
24636
24920
  }
24637
24921
 
24638
24922
  // src/services/providers/gitpod.ts
24639
- var import_child_process22 = require("child_process");
24923
+ var import_child_process23 = require("child_process");
24640
24924
  var import_util5 = require("util");
24641
- var path45 = __toESM(require("path"));
24925
+ var path46 = __toESM(require("path"));
24642
24926
  var import_picocolors9 = __toESM(require("picocolors"));
24643
- var execFileP6 = (0, import_util5.promisify)(import_child_process22.execFile);
24927
+ var execFileP6 = (0, import_util5.promisify)(import_child_process23.execFile);
24644
24928
  var MAX_BUFFER2 = 8 * 1024 * 1024;
24645
24929
  function resetStdinForChild2() {
24646
24930
  if (process.stdin.isTTY) {
@@ -24680,7 +24964,7 @@ var GitpodProvider = class {
24680
24964
  );
24681
24965
  resetStdinForChild2();
24682
24966
  await new Promise((resolve7, reject) => {
24683
- const proc = (0, import_child_process22.spawn)("gitpod", ["login"], { stdio: "inherit" });
24967
+ const proc = (0, import_child_process23.spawn)("gitpod", ["login"], { stdio: "inherit" });
24684
24968
  proc.on("exit", (code) => {
24685
24969
  if (code === 0) resolve7();
24686
24970
  else reject(new Error("gitpod login failed."));
@@ -24832,7 +25116,7 @@ var GitpodProvider = class {
24832
25116
  async streamCommand(workspaceId, command2) {
24833
25117
  resetStdinForChild2();
24834
25118
  return new Promise((resolve7, reject) => {
24835
- const proc = (0, import_child_process22.spawn)(
25119
+ const proc = (0, import_child_process23.spawn)(
24836
25120
  "gitpod",
24837
25121
  ["workspace", "ssh", workspaceId, "--", "-tt", command2],
24838
25122
  { stdio: "inherit" }
@@ -24852,11 +25136,11 @@ var GitpodProvider = class {
24852
25136
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
24853
25137
  const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
24854
25138
  await new Promise((resolve7, reject) => {
24855
- const tar = (0, import_child_process22.spawn)("tar", tarArgs, {
25139
+ const tar = (0, import_child_process23.spawn)("tar", tarArgs, {
24856
25140
  stdio: ["ignore", "pipe", "pipe"],
24857
25141
  env: tarEnv
24858
25142
  });
24859
- const ssh = (0, import_child_process22.spawn)(
25143
+ const ssh = (0, import_child_process23.spawn)(
24860
25144
  "gitpod",
24861
25145
  ["workspace", "ssh", workspaceId, "--", remoteCmd],
24862
25146
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -24878,7 +25162,7 @@ var GitpodProvider = class {
24878
25162
  });
24879
25163
  }
24880
25164
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
24881
- const remoteDir = path45.posix.dirname(remotePath);
25165
+ const remoteDir = path46.posix.dirname(remotePath);
24882
25166
  const parts = [
24883
25167
  `mkdir -p ${shellQuote2(remoteDir)}`,
24884
25168
  `cat > ${shellQuote2(remotePath)}`
@@ -24888,7 +25172,7 @@ var GitpodProvider = class {
24888
25172
  }
24889
25173
  const cmd = parts.join(" && ");
24890
25174
  await new Promise((resolve7, reject) => {
24891
- const proc = (0, import_child_process22.spawn)(
25175
+ const proc = (0, import_child_process23.spawn)(
24892
25176
  "gitpod",
24893
25177
  ["workspace", "ssh", workspaceId, "--", cmd],
24894
25178
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -24912,10 +25196,10 @@ function shellQuote2(s) {
24912
25196
  }
24913
25197
 
24914
25198
  // src/services/providers/gitlab-workspaces.ts
24915
- var import_child_process23 = require("child_process");
25199
+ var import_child_process24 = require("child_process");
24916
25200
  var import_util6 = require("util");
24917
- var path46 = __toESM(require("path"));
24918
- var execFileP7 = (0, import_util6.promisify)(import_child_process23.execFile);
25201
+ var path47 = __toESM(require("path"));
25202
+ var execFileP7 = (0, import_util6.promisify)(import_child_process24.execFile);
24919
25203
  var MAX_BUFFER3 = 8 * 1024 * 1024;
24920
25204
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
24921
25205
  function resetStdinForChild3() {
@@ -24957,7 +25241,7 @@ var GitLabWorkspacesProvider = class {
24957
25241
  );
24958
25242
  resetStdinForChild3();
24959
25243
  await new Promise((resolve7, reject) => {
24960
- const proc = (0, import_child_process23.spawn)(
25244
+ const proc = (0, import_child_process24.spawn)(
24961
25245
  "glab",
24962
25246
  ["auth", "login", "--scopes", "api,read_user,read_repository"],
24963
25247
  { stdio: "inherit" }
@@ -25129,7 +25413,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
25129
25413
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
25130
25414
  resetStdinForChild3();
25131
25415
  return new Promise((resolve7, reject) => {
25132
- const proc = (0, import_child_process23.spawn)(
25416
+ const proc = (0, import_child_process24.spawn)(
25133
25417
  "ssh",
25134
25418
  ["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
25135
25419
  { stdio: "inherit" }
@@ -25150,8 +25434,8 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
25150
25434
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
25151
25435
  const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
25152
25436
  await new Promise((resolve7, reject) => {
25153
- const tar = (0, import_child_process23.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
25154
- const ssh = (0, import_child_process23.spawn)(
25437
+ const tar = (0, import_child_process24.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
25438
+ const ssh = (0, import_child_process24.spawn)(
25155
25439
  "ssh",
25156
25440
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, remoteCmd],
25157
25441
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -25174,14 +25458,14 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
25174
25458
  }
25175
25459
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
25176
25460
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
25177
- const remoteDir = path46.posix.dirname(remotePath);
25461
+ const remoteDir = path47.posix.dirname(remotePath);
25178
25462
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
25179
25463
  if (options.mode != null) {
25180
25464
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
25181
25465
  }
25182
25466
  const cmd = parts.join(" && ");
25183
25467
  await new Promise((resolve7, reject) => {
25184
- const proc = (0, import_child_process23.spawn)(
25468
+ const proc = (0, import_child_process24.spawn)(
25185
25469
  "ssh",
25186
25470
  ["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
25187
25471
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -25240,10 +25524,10 @@ function shellQuote3(s) {
25240
25524
  }
25241
25525
 
25242
25526
  // src/services/providers/railway.ts
25243
- var import_child_process24 = require("child_process");
25527
+ var import_child_process25 = require("child_process");
25244
25528
  var import_util7 = require("util");
25245
- var path47 = __toESM(require("path"));
25246
- var execFileP8 = (0, import_util7.promisify)(import_child_process24.execFile);
25529
+ var path48 = __toESM(require("path"));
25530
+ var execFileP8 = (0, import_util7.promisify)(import_child_process25.execFile);
25247
25531
  var MAX_BUFFER4 = 8 * 1024 * 1024;
25248
25532
  function resetStdinForChild4() {
25249
25533
  if (process.stdin.isTTY) {
@@ -25284,7 +25568,7 @@ var RailwayProvider = class {
25284
25568
  );
25285
25569
  resetStdinForChild4();
25286
25570
  await new Promise((resolve7, reject) => {
25287
- const proc = (0, import_child_process24.spawn)("railway", ["login"], { stdio: "inherit" });
25571
+ const proc = (0, import_child_process25.spawn)("railway", ["login"], { stdio: "inherit" });
25288
25572
  proc.on("exit", (code) => {
25289
25573
  if (code === 0) resolve7();
25290
25574
  else reject(new Error("railway login failed."));
@@ -25427,7 +25711,7 @@ var RailwayProvider = class {
25427
25711
  }
25428
25712
  resetStdinForChild4();
25429
25713
  return new Promise((resolve7, reject) => {
25430
- const proc = (0, import_child_process24.spawn)(
25714
+ const proc = (0, import_child_process25.spawn)(
25431
25715
  "railway",
25432
25716
  ["shell", "--project", projectId, "--service", serviceId, "--command", command2],
25433
25717
  { stdio: "inherit" }
@@ -25451,8 +25735,8 @@ var RailwayProvider = class {
25451
25735
  const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
25452
25736
  const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
25453
25737
  await new Promise((resolve7, reject) => {
25454
- const tar = (0, import_child_process24.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
25455
- const sh = (0, import_child_process24.spawn)(
25738
+ const tar = (0, import_child_process25.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
25739
+ const sh = (0, import_child_process25.spawn)(
25456
25740
  "railway",
25457
25741
  ["shell", "--project", projectId, "--service", serviceId, "--command", remoteCmd],
25458
25742
  { stdio: [tar.stdout, "pipe", "pipe"] }
@@ -25478,14 +25762,14 @@ var RailwayProvider = class {
25478
25762
  if (!projectId || !serviceId) {
25479
25763
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
25480
25764
  }
25481
- const remoteDir = path47.posix.dirname(remotePath);
25765
+ const remoteDir = path48.posix.dirname(remotePath);
25482
25766
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
25483
25767
  if (options.mode != null) {
25484
25768
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
25485
25769
  }
25486
25770
  const cmd = parts.join(" && ");
25487
25771
  await new Promise((resolve7, reject) => {
25488
- const proc = (0, import_child_process24.spawn)(
25772
+ const proc = (0, import_child_process25.spawn)(
25489
25773
  "railway",
25490
25774
  ["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
25491
25775
  { stdio: ["pipe", "pipe", "pipe"] }
@@ -26021,8 +26305,8 @@ async function stopWorkspaceFromLocal(target) {
26021
26305
  var import_node_dns = require("dns");
26022
26306
  var import_node_util4 = require("util");
26023
26307
  var import_node_crypto8 = require("crypto");
26024
- var fs37 = __toESM(require("fs"));
26025
- var path48 = __toESM(require("path"));
26308
+ var fs38 = __toESM(require("fs"));
26309
+ var path49 = __toESM(require("path"));
26026
26310
  var import_picocolors12 = __toESM(require("picocolors"));
26027
26311
  var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
26028
26312
  async function checkDns(apiBase) {
@@ -26078,13 +26362,13 @@ async function checkHealth(apiBase) {
26078
26362
  }
26079
26363
  }
26080
26364
  function checkConfigDir() {
26081
- const dir = path48.join(require("os").homedir(), ".codeam");
26365
+ const dir = path49.join(require("os").homedir(), ".codeam");
26082
26366
  try {
26083
- fs37.mkdirSync(dir, { recursive: true, mode: 448 });
26084
- const probe = path48.join(dir, ".doctor-probe");
26085
- fs37.writeFileSync(probe, "ok", { mode: 384 });
26086
- const read = fs37.readFileSync(probe, "utf8");
26087
- fs37.unlinkSync(probe);
26367
+ fs38.mkdirSync(dir, { recursive: true, mode: 448 });
26368
+ const probe = path49.join(dir, ".doctor-probe");
26369
+ fs38.writeFileSync(probe, "ok", { mode: 384 });
26370
+ const read = fs38.readFileSync(probe, "utf8");
26371
+ fs38.unlinkSync(probe);
26088
26372
  if (read !== "ok") throw new Error("write/read round-trip mismatch");
26089
26373
  return {
26090
26374
  id: "config-dir",
@@ -26124,9 +26408,9 @@ function checkSessions() {
26124
26408
  }
26125
26409
  }
26126
26410
  function checkAgentBinaries() {
26127
- const os31 = createOsStrategy();
26411
+ const os32 = createOsStrategy();
26128
26412
  return getEnabledAgents().map((meta) => {
26129
- const found = os31.findInPath(meta.binaryName);
26413
+ const found = os32.findInPath(meta.binaryName);
26130
26414
  return {
26131
26415
  id: `agent-${meta.id}`,
26132
26416
  label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
@@ -26148,7 +26432,7 @@ function checkNodePty() {
26148
26432
  detail: "not required on this platform"
26149
26433
  };
26150
26434
  }
26151
- const vendoredPath = path48.join(__dirname, "vendor", "node-pty");
26435
+ const vendoredPath = path49.join(__dirname, "vendor", "node-pty");
26152
26436
  for (const target of [vendoredPath, "node-pty"]) {
26153
26437
  try {
26154
26438
  require(target);
@@ -26190,7 +26474,7 @@ function checkChokidar() {
26190
26474
  }
26191
26475
  async function doctor(args2 = []) {
26192
26476
  const json = args2.includes("--json");
26193
- const cliVersion = true ? "2.35.9" : "0.0.0-dev";
26477
+ const cliVersion = true ? "2.36.1" : "0.0.0-dev";
26194
26478
  const apiBase = resolveApiBaseUrl();
26195
26479
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
26196
26480
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -26389,7 +26673,7 @@ async function completion(args2) {
26389
26673
  // src/commands/version.ts
26390
26674
  var import_picocolors13 = __toESM(require("picocolors"));
26391
26675
  function version2() {
26392
- const v = true ? "2.35.9" : "unknown";
26676
+ const v = true ? "2.36.1" : "unknown";
26393
26677
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
26394
26678
  }
26395
26679
 
@@ -26517,9 +26801,9 @@ function tryShowSubcommandHelp(cmd, args2) {
26517
26801
  var _subcommandHelpKeys = Object.keys(HELPS);
26518
26802
 
26519
26803
  // src/lib/updateNotifier.ts
26520
- var fs38 = __toESM(require("fs"));
26521
- var os30 = __toESM(require("os"));
26522
- var path49 = __toESM(require("path"));
26804
+ var fs39 = __toESM(require("fs"));
26805
+ var os31 = __toESM(require("os"));
26806
+ var path50 = __toESM(require("path"));
26523
26807
  var https8 = __toESM(require("https"));
26524
26808
  var import_node_child_process12 = require("child_process");
26525
26809
  var import_picocolors16 = __toESM(require("picocolors"));
@@ -26528,12 +26812,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
26528
26812
  var TTL_MS = 24 * 60 * 60 * 1e3;
26529
26813
  var REQUEST_TIMEOUT_MS = 1500;
26530
26814
  function cachePath() {
26531
- const dir = path49.join(os30.homedir(), ".codeam");
26532
- return path49.join(dir, "update-check.json");
26815
+ const dir = path50.join(os31.homedir(), ".codeam");
26816
+ return path50.join(dir, "update-check.json");
26533
26817
  }
26534
26818
  function readCache() {
26535
26819
  try {
26536
- const raw = fs38.readFileSync(cachePath(), "utf8");
26820
+ const raw = fs39.readFileSync(cachePath(), "utf8");
26537
26821
  const parsed = JSON.parse(raw);
26538
26822
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
26539
26823
  return parsed;
@@ -26544,10 +26828,10 @@ function readCache() {
26544
26828
  function writeCache(cache) {
26545
26829
  try {
26546
26830
  const file = cachePath();
26547
- fs38.mkdirSync(path49.dirname(file), { recursive: true });
26831
+ fs39.mkdirSync(path50.dirname(file), { recursive: true });
26548
26832
  const tmp = `${file}.${process.pid}.tmp`;
26549
- fs38.writeFileSync(tmp, JSON.stringify(cache));
26550
- fs38.renameSync(tmp, file);
26833
+ fs39.writeFileSync(tmp, JSON.stringify(cache));
26834
+ fs39.renameSync(tmp, file);
26551
26835
  } catch {
26552
26836
  }
26553
26837
  }
@@ -26621,8 +26905,8 @@ function isLinkedInstall() {
26621
26905
  timeout: 2e3
26622
26906
  }).trim();
26623
26907
  if (!root) return false;
26624
- const pkgPath = path49.join(root, PKG_NAME);
26625
- return fs38.lstatSync(pkgPath).isSymbolicLink();
26908
+ const pkgPath = path50.join(root, PKG_NAME);
26909
+ return fs39.lstatSync(pkgPath).isSymbolicLink();
26626
26910
  } catch {
26627
26911
  return false;
26628
26912
  }
@@ -26658,7 +26942,7 @@ function maybeAutoUpdate(currentVersion, latest) {
26658
26942
  return;
26659
26943
  }
26660
26944
  try {
26661
- fs38.unlinkSync(cachePath());
26945
+ fs39.unlinkSync(cachePath());
26662
26946
  } catch {
26663
26947
  }
26664
26948
  process.stderr.write(` ${import_picocolors16.default.green("\u2713")} Updated. Resuming session...
@@ -26675,7 +26959,7 @@ function checkForUpdates() {
26675
26959
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
26676
26960
  if (process.env.CI) return;
26677
26961
  if (!process.stdout.isTTY) return;
26678
- const current = true ? "2.35.9" : null;
26962
+ const current = true ? "2.36.1" : null;
26679
26963
  if (!current) return;
26680
26964
  const cache = readCache();
26681
26965
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;