codeam-cli 2.36.5 → 2.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/index.js +311 -252
  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.36.5",
501
+ version: "2.37.0",
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(path51) {
1190
- return path51.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
1189
+ function normalizeWindowsPath(path52) {
1190
+ return path52.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(path51, ranges, output) {
3670
+ function getContextLinesFromFile(path52, ranges, output) {
3671
3671
  return new Promise((resolve7) => {
3672
- const stream = (0, import_node_fs.createReadStream)(path51);
3672
+ const stream = (0, import_node_fs.createReadStream)(path52);
3673
3673
  const lineReaded = (0, import_node_readline.createInterface)({
3674
3674
  input: stream
3675
3675
  });
@@ -3684,7 +3684,7 @@ function getContextLinesFromFile(path51, 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(path51, 1);
3687
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path52, 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(path51) {
3749
- return path51.startsWith("node:") || path51.endsWith(".min.js") || path51.endsWith(".min.cjs") || path51.endsWith(".min.mjs") || path51.startsWith("data:");
3748
+ function shouldSkipContextLinesForFile(path52) {
3749
+ return path52.startsWith("node:") || path52.endsWith(".min.js") || path52.endsWith(".min.cjs") || path52.endsWith(".min.mjs") || path52.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.36.5" : "0.0.0-dev",
5903
+ cliVersion: true ? "2.37.0" : "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 path51 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9981
+ const path52 = pathLine && !BANNER_ART_RE.test(pathLine) ? pathLine : "";
9982
9982
  return {
9983
9983
  title: "",
9984
9984
  subtitle: lines[metaIdx].trim(),
9985
- path: path51,
9985
+ path: path52,
9986
9986
  startIdx: artStart,
9987
- endIdx: metaIdx + (path51 ? 1 : 0)
9987
+ endIdx: metaIdx + (path52 ? 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 [, path51, lineNo, sevToken, message] = m;
11346
- if (!path51 || !lineNo || !message) continue;
11345
+ const [, path52, lineNo, sevToken, message] = m;
11346
+ if (!path52 || !lineNo || !message) continue;
11347
11347
  const cleanedMessage = message.trim().replace(/^[*-]\s+/, "");
11348
11348
  hunks.push({
11349
- path: path51.trim(),
11349
+ path: path52.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.`
@@ -15356,6 +15356,64 @@ function buildAcpPromptBlocks(payload) {
15356
15356
  return blocks;
15357
15357
  }
15358
15358
 
15359
+ // src/agents/acp/onboarding.ts
15360
+ var fs22 = __toESM(require("fs"));
15361
+ var os23 = __toESM(require("os"));
15362
+ var path27 = __toESM(require("path"));
15363
+ var _onboardingSeam = {
15364
+ markerPath: (sessionId) => path27.join(os23.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
15365
+ exists: (p2) => fs22.existsSync(p2),
15366
+ write: (p2) => {
15367
+ fs22.mkdirSync(path27.dirname(p2), { recursive: true });
15368
+ fs22.writeFileSync(p2, "");
15369
+ },
15370
+ disabled: () => {
15371
+ const v = process.env.CODEAM_ONBOARDING_DISABLED;
15372
+ return !!v && v !== "0" && v.toLowerCase() !== "false";
15373
+ }
15374
+ };
15375
+ function buildOnboardingPrompt(cwd) {
15376
+ const repo = path27.basename(cwd || "") || "this project";
15377
+ return [
15378
+ "SYSTEM / BACKGROUND TASK \u2014 this message is NOT from the user. The user just",
15379
+ "connected this session through CodeAgent Mobile and has only seen a welcome",
15380
+ "card. Take the initiative and write THEIR first message: a short, warm",
15381
+ "onboarding welcome that you (the agent) send proactively to invite them to start.",
15382
+ "",
15383
+ "Write it for a phone screen \u2014 under ~110 words, friendly, easy to scan, a little",
15384
+ "energy. Cover briefly, in your own words:",
15385
+ "- Glad they spun up this session.",
15386
+ "- Through CodeAgent Mobile, agents like you get native context, persistent",
15387
+ " memory, and an issue tracker \u2014 powered by Beads on Dolt \u2014 out of the box, zero setup.",
15388
+ "- They can drive you from their phone: live preview, rich visual output, a file viewer.",
15389
+ `- End with a SHORT, concrete invitation tied to THIS project (working dir: ${cwd},`,
15390
+ ` repo: "${repo}") \u2014 suggest 1\u20132 specific things you could help with here.`,
15391
+ "",
15392
+ "Rules: do NOT run any tools or shell commands \u2014 base the project hint only on the",
15393
+ 'repo name/path above so your reply is instant. No preamble like "Sure" or "Of',
15394
+ 'course" \u2014 start directly with the greeting. Use light markdown (one intro line +',
15395
+ "a few bullets). Keep it tight."
15396
+ ].join("\n");
15397
+ }
15398
+ function maybeSendOnboardingWelcome(opts) {
15399
+ if (_onboardingSeam.disabled()) return;
15400
+ const marker = _onboardingSeam.markerPath(opts.sessionId);
15401
+ try {
15402
+ if (_onboardingSeam.exists(marker)) return;
15403
+ _onboardingSeam.write(marker);
15404
+ } catch (err) {
15405
+ log.trace("acpRunner", `onboarding marker check failed: ${err.message}`);
15406
+ return;
15407
+ }
15408
+ log.info("acpRunner", `sending first-pair onboarding welcome for session=${opts.sessionId.slice(0, 8)}`);
15409
+ void opts.client.prompt(buildOnboardingPrompt(opts.cwd)).catch((err) => {
15410
+ log.warn(
15411
+ "acpRunner",
15412
+ `onboarding welcome prompt failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`
15413
+ );
15414
+ });
15415
+ }
15416
+
15359
15417
  // src/agents/acp/promptEcho.ts
15360
15418
  var MAX_PROMPT_CHARS = 200;
15361
15419
  function formatPromptEchoLine(payload) {
@@ -15830,9 +15888,9 @@ function extractSelectPrompt(text) {
15830
15888
  }
15831
15889
 
15832
15890
  // src/commands/start/handlers.ts
15833
- var fs33 = __toESM(require("fs"));
15834
- var os26 = __toESM(require("os"));
15835
- var path40 = __toESM(require("path"));
15891
+ var fs34 = __toESM(require("fs"));
15892
+ var os27 = __toESM(require("os"));
15893
+ var path41 = __toESM(require("path"));
15836
15894
  var import_crypto3 = require("crypto");
15837
15895
  var import_child_process18 = require("child_process");
15838
15896
 
@@ -15956,8 +16014,8 @@ function parsePayload2(schema, raw) {
15956
16014
  }
15957
16015
 
15958
16016
  // src/services/file-ops.service.ts
15959
- var fs22 = __toESM(require("fs/promises"));
15960
- var path28 = __toESM(require("path"));
16017
+ var fs23 = __toESM(require("fs/promises"));
16018
+ var path29 = __toESM(require("path"));
15961
16019
  var MAX_FILE_BYTES = 5 * 1024 * 1024;
15962
16020
  var MAX_WALK_DEPTH = 6;
15963
16021
  var MAX_VISITED_DIRS = 5e3;
@@ -15992,12 +16050,12 @@ var SUBDIR_IGNORE = /* @__PURE__ */ new Set([
15992
16050
  "__pycache__"
15993
16051
  ]);
15994
16052
  function isUnder(parent, candidate) {
15995
- const rel = path28.relative(parent, candidate);
15996
- return rel === "" || !rel.startsWith("..") && !path28.isAbsolute(rel);
16053
+ const rel = path29.relative(parent, candidate);
16054
+ return rel === "" || !rel.startsWith("..") && !path29.isAbsolute(rel);
15997
16055
  }
15998
16056
  async function isExistingFile(absPath) {
15999
16057
  try {
16000
- const stat3 = await fs22.stat(absPath);
16058
+ const stat3 = await fs23.stat(absPath);
16001
16059
  return stat3.isFile();
16002
16060
  } catch {
16003
16061
  return false;
@@ -16010,13 +16068,13 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
16010
16068
  ctx.visited++;
16011
16069
  let entries = [];
16012
16070
  try {
16013
- entries = await fs22.readdir(dir, { withFileTypes: true });
16071
+ entries = await fs23.readdir(dir, { withFileTypes: true });
16014
16072
  } catch {
16015
16073
  return;
16016
16074
  }
16017
16075
  for (const e of entries) {
16018
16076
  if (!e.isFile()) continue;
16019
- const full = path28.join(dir, e.name);
16077
+ const full = path29.join(dir, e.name);
16020
16078
  if (needleVariants.some((needle) => full.endsWith(needle))) {
16021
16079
  ctx.matches.push(full);
16022
16080
  if (ctx.matches.length >= ctx.cap) return;
@@ -16026,21 +16084,21 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
16026
16084
  if (!e.isDirectory()) continue;
16027
16085
  if (SUBDIR_IGNORE.has(e.name)) continue;
16028
16086
  if (e.name.startsWith(".") && SUBDIR_IGNORE.has(e.name)) continue;
16029
- await walkForSuffix(path28.join(dir, e.name), needleVariants, depth + 1, ctx);
16087
+ await walkForSuffix(path29.join(dir, e.name), needleVariants, depth + 1, ctx);
16030
16088
  if (ctx.matches.length >= ctx.cap) return;
16031
16089
  }
16032
16090
  }
16033
16091
  async function findFile(rawPath) {
16034
16092
  const cwd = process.cwd();
16035
- if (path28.isAbsolute(rawPath)) {
16036
- const abs = path28.normalize(rawPath);
16093
+ if (path29.isAbsolute(rawPath)) {
16094
+ const abs = path29.normalize(rawPath);
16037
16095
  if (isUnder(cwd, abs) && await isExistingFile(abs)) return abs;
16038
16096
  }
16039
- const direct = path28.resolve(cwd, rawPath);
16097
+ const direct = path29.resolve(cwd, rawPath);
16040
16098
  if (isUnder(cwd, direct) && await isExistingFile(direct)) return direct;
16041
- const normalized = path28.normalize(rawPath).replace(/^[./\\]+/, "");
16099
+ const normalized = path29.normalize(rawPath).replace(/^[./\\]+/, "");
16042
16100
  const needles = [
16043
- `${path28.sep}${normalized}`,
16101
+ `${path29.sep}${normalized}`,
16044
16102
  `/${normalized}`
16045
16103
  ].filter((v, i, a) => a.indexOf(v) === i);
16046
16104
  const ctx = { visited: 0, matches: [], cap: 16 };
@@ -16054,7 +16112,7 @@ async function findWriteTarget(rawPath) {
16054
16112
  const found = await findFile(rawPath);
16055
16113
  if (found) return found;
16056
16114
  const cwd = process.cwd();
16057
- const fallback = path28.isAbsolute(rawPath) ? path28.normalize(rawPath) : path28.resolve(cwd, rawPath);
16115
+ const fallback = path29.isAbsolute(rawPath) ? path29.normalize(rawPath) : path29.resolve(cwd, rawPath);
16058
16116
  if (!isUnder(cwd, fallback)) return null;
16059
16117
  return fallback;
16060
16118
  }
@@ -16071,11 +16129,11 @@ async function readProjectFile(rawPath) {
16071
16129
  if (!abs) {
16072
16130
  return { error: `File not found in the project tree: ${rawPath}` };
16073
16131
  }
16074
- const stat3 = await fs22.stat(abs);
16132
+ const stat3 = await fs23.stat(abs);
16075
16133
  if (stat3.size > MAX_FILE_BYTES) {
16076
16134
  return { error: `File too large (${(stat3.size / 1024 / 1024).toFixed(1)} MB > ${MAX_FILE_BYTES / 1024 / 1024} MB).` };
16077
16135
  }
16078
- const buf = await fs22.readFile(abs);
16136
+ const buf = await fs23.readFile(abs);
16079
16137
  if (looksBinary(buf)) {
16080
16138
  return { error: "Binary file \u2014 refusing to open in a code editor." };
16081
16139
  }
@@ -16094,8 +16152,8 @@ async function writeProjectFile(rawPath, content) {
16094
16152
  if (Buffer.byteLength(content, "utf-8") > MAX_FILE_BYTES) {
16095
16153
  return { error: "Content too large." };
16096
16154
  }
16097
- await fs22.mkdir(path28.dirname(abs), { recursive: true });
16098
- await fs22.writeFile(abs, content, "utf-8");
16155
+ await fs23.mkdir(path29.dirname(abs), { recursive: true });
16156
+ await fs23.writeFile(abs, content, "utf-8");
16099
16157
  return { ok: true };
16100
16158
  } catch (e) {
16101
16159
  const msg = e instanceof Error ? e.message : "Write failed";
@@ -16106,8 +16164,8 @@ async function writeProjectFile(rawPath, content) {
16106
16164
  // src/services/project-ops.service.ts
16107
16165
  var import_child_process9 = require("child_process");
16108
16166
  var import_util2 = require("util");
16109
- var fs23 = __toESM(require("fs/promises"));
16110
- var path29 = __toESM(require("path"));
16167
+ var fs24 = __toESM(require("fs/promises"));
16168
+ var path30 = __toESM(require("path"));
16111
16169
  var execFileP3 = (0, import_util2.promisify)(import_child_process9.execFile);
16112
16170
  var PROJECT_IGNORE = /* @__PURE__ */ new Set([
16113
16171
  "node_modules",
@@ -16155,7 +16213,7 @@ async function listProjectFiles(opts = {}) {
16155
16213
  }
16156
16214
  let entries = [];
16157
16215
  try {
16158
- entries = await fs23.readdir(dir, { withFileTypes: true });
16216
+ entries = await fs24.readdir(dir, { withFileTypes: true });
16159
16217
  } catch {
16160
16218
  return;
16161
16219
  }
@@ -16165,18 +16223,18 @@ async function listProjectFiles(opts = {}) {
16165
16223
  return;
16166
16224
  }
16167
16225
  if (PROJECT_IGNORE.has(e.name)) continue;
16168
- const full = path29.join(dir, e.name);
16226
+ const full = path30.join(dir, e.name);
16169
16227
  if (e.isDirectory()) {
16170
16228
  if (depth >= 12) continue;
16171
16229
  await walk(full, depth + 1);
16172
16230
  } else if (e.isFile()) {
16173
- const rel = path29.relative(root, full);
16231
+ const rel = path30.relative(root, full);
16174
16232
  if (q2 && !rel.toLowerCase().includes(q2) && !e.name.toLowerCase().includes(q2)) {
16175
16233
  continue;
16176
16234
  }
16177
16235
  let size = 0;
16178
16236
  try {
16179
- const st3 = await fs23.stat(full);
16237
+ const st3 = await fs24.stat(full);
16180
16238
  size = st3.size;
16181
16239
  } catch {
16182
16240
  }
@@ -16278,8 +16336,8 @@ async function gitStatus(cwd) {
16278
16336
  let hasMergeInProgress = false;
16279
16337
  try {
16280
16338
  const gitDir = (await git(["rev-parse", "--git-dir"], root)).stdout.trim();
16281
- const mergeHead = path29.isAbsolute(gitDir) ? path29.join(gitDir, "MERGE_HEAD") : path29.join(root, gitDir, "MERGE_HEAD");
16282
- await fs23.access(mergeHead);
16339
+ const mergeHead = path30.isAbsolute(gitDir) ? path30.join(gitDir, "MERGE_HEAD") : path30.join(root, gitDir, "MERGE_HEAD");
16340
+ await fs24.access(mergeHead);
16283
16341
  hasMergeInProgress = true;
16284
16342
  } catch {
16285
16343
  }
@@ -16425,7 +16483,7 @@ async function jsSearchFiles(opts, cwd, cap) {
16425
16483
  }
16426
16484
  let content = "";
16427
16485
  try {
16428
- content = await fs23.readFile(path29.join(cwd, f.path), "utf8");
16486
+ content = await fs24.readFile(path30.join(cwd, f.path), "utf8");
16429
16487
  } catch {
16430
16488
  continue;
16431
16489
  }
@@ -16449,14 +16507,14 @@ async function jsSearchFiles(opts, cwd, cap) {
16449
16507
 
16450
16508
  // src/services/apply-file-review.service.ts
16451
16509
  var import_child_process10 = require("child_process");
16452
- var fs24 = __toESM(require("fs"));
16453
- var path30 = __toESM(require("path"));
16510
+ var fs25 = __toESM(require("fs"));
16511
+ var path31 = __toESM(require("path"));
16454
16512
  async function applyFileReview(workingDir, filePath, action) {
16455
- if (filePath.includes("..") || path30.isAbsolute(filePath)) {
16513
+ if (filePath.includes("..") || path31.isAbsolute(filePath)) {
16456
16514
  return { ok: false, action, filePath, error: "invalid file path" };
16457
16515
  }
16458
- const absFile = path30.resolve(workingDir, filePath);
16459
- const repoRoot = findGitRoot(path30.dirname(absFile));
16516
+ const absFile = path31.resolve(workingDir, filePath);
16517
+ const repoRoot = findGitRoot(path31.dirname(absFile));
16460
16518
  if (!repoRoot) {
16461
16519
  return {
16462
16520
  ok: false,
@@ -16465,7 +16523,7 @@ async function applyFileReview(workingDir, filePath, action) {
16465
16523
  error: `no enclosing git repo for ${filePath}`
16466
16524
  };
16467
16525
  }
16468
- const relInRepo = path30.relative(repoRoot, absFile);
16526
+ const relInRepo = path31.relative(repoRoot, absFile);
16469
16527
  if (!relInRepo || relInRepo.startsWith("..")) {
16470
16528
  return { ok: false, action, filePath, error: "path escapes repo root" };
16471
16529
  }
@@ -16514,17 +16572,17 @@ function runGit(cwd, args2) {
16514
16572
  });
16515
16573
  }
16516
16574
  function findGitRoot(startDir) {
16517
- let dir = path30.resolve(startDir);
16575
+ let dir = path31.resolve(startDir);
16518
16576
  const seen = /* @__PURE__ */ new Set();
16519
16577
  for (let i = 0; i < 256; i++) {
16520
16578
  if (seen.has(dir)) return null;
16521
16579
  seen.add(dir);
16522
16580
  try {
16523
- const stat3 = fs24.statSync(path30.join(dir, ".git"), { throwIfNoEntry: false });
16581
+ const stat3 = fs25.statSync(path31.join(dir, ".git"), { throwIfNoEntry: false });
16524
16582
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
16525
16583
  } catch {
16526
16584
  }
16527
- const parent = path30.dirname(dir);
16585
+ const parent = path31.dirname(dir);
16528
16586
  if (parent === dir) return null;
16529
16587
  dir = parent;
16530
16588
  }
@@ -16533,8 +16591,8 @@ function findGitRoot(startDir) {
16533
16591
 
16534
16592
  // src/commands/link.ts
16535
16593
  var import_node_crypto6 = require("crypto");
16536
- var fs25 = __toESM(require("fs"));
16537
- var path31 = __toESM(require("path"));
16594
+ var fs26 = __toESM(require("fs"));
16595
+ var path32 = __toESM(require("path"));
16538
16596
  var import_chokidar = __toESM(require("chokidar"));
16539
16597
  var import_picocolors2 = __toESM(require("picocolors"));
16540
16598
 
@@ -16713,7 +16771,7 @@ function parseLinkArgs(args2) {
16713
16771
  if (apiKeyFileArg) {
16714
16772
  const filePath = apiKeyFileArg.slice("--api-key-file=".length);
16715
16773
  try {
16716
- apiKey = fs25.readFileSync(path31.resolve(filePath), "utf8").trim();
16774
+ apiKey = fs26.readFileSync(path32.resolve(filePath), "utf8").trim();
16717
16775
  } catch (err) {
16718
16776
  throw new Error(`Could not read --api-key-file ${filePath}: ${err.message}`);
16719
16777
  }
@@ -16817,7 +16875,7 @@ async function link(args2 = []) {
16817
16875
  return;
16818
16876
  }
16819
16877
  if (parsed.tokenFile) {
16820
- const credential = fs25.readFileSync(path31.resolve(parsed.tokenFile), "utf8").trim();
16878
+ const credential = fs26.readFileSync(path32.resolve(parsed.tokenFile), "utf8").trim();
16821
16879
  if (!credential) {
16822
16880
  showError(`--token-file ${parsed.tokenFile} is empty.`);
16823
16881
  process.exit(1);
@@ -17394,8 +17452,8 @@ function activePreviewSessionIds() {
17394
17452
 
17395
17453
  // src/beads/bd-adapter.ts
17396
17454
  var import_child_process13 = require("child_process");
17397
- var fs29 = __toESM(require("fs"));
17398
- var path35 = __toESM(require("path"));
17455
+ var fs30 = __toESM(require("fs"));
17456
+ var path36 = __toESM(require("path"));
17399
17457
  var BD_PACKAGE = "@beads/bd";
17400
17458
  function resolveBundledBdBinary() {
17401
17459
  return _resolveSeam.resolveBundled();
@@ -17407,11 +17465,11 @@ function _defaultResolveBundled() {
17407
17465
  } catch {
17408
17466
  return null;
17409
17467
  }
17410
- const binDir = path35.join(path35.dirname(pkgJsonPath), "bin");
17468
+ const binDir = path36.join(path36.dirname(pkgJsonPath), "bin");
17411
17469
  const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
17412
- const binaryPath = path35.join(binDir, binaryName);
17470
+ const binaryPath = path36.join(binDir, binaryName);
17413
17471
  try {
17414
- fs29.accessSync(binaryPath, fs29.constants.F_OK);
17472
+ fs30.accessSync(binaryPath, fs30.constants.F_OK);
17415
17473
  return binaryPath;
17416
17474
  } catch {
17417
17475
  return null;
@@ -17421,13 +17479,13 @@ function resolveBdOnPath() {
17421
17479
  return _resolveSeam.resolveOnPath();
17422
17480
  }
17423
17481
  function _defaultResolveOnPath() {
17424
- const dirs = (process.env.PATH ?? "").split(path35.delimiter).filter(Boolean);
17482
+ const dirs = (process.env.PATH ?? "").split(path36.delimiter).filter(Boolean);
17425
17483
  const candidates = process.platform === "win32" ? ["bd.exe", "bd.cmd", "bd"] : ["bd"];
17426
17484
  for (const dir of dirs) {
17427
17485
  for (const candidate of candidates) {
17428
- const full = path35.join(dir, candidate);
17486
+ const full = path36.join(dir, candidate);
17429
17487
  try {
17430
- fs29.accessSync(full, fs29.constants.F_OK);
17488
+ fs30.accessSync(full, fs30.constants.F_OK);
17431
17489
  return full;
17432
17490
  } catch {
17433
17491
  }
@@ -17593,9 +17651,9 @@ function coerceIssue(row, projectKey) {
17593
17651
 
17594
17652
  // src/beads/provisioner.ts
17595
17653
  var import_child_process17 = require("child_process");
17596
- var fs32 = __toESM(require("fs"));
17597
- var os25 = __toESM(require("os"));
17598
- var path38 = __toESM(require("path"));
17654
+ var fs33 = __toESM(require("fs"));
17655
+ var os26 = __toESM(require("os"));
17656
+ var path39 = __toESM(require("path"));
17599
17657
 
17600
17658
  // src/beads/install-bd.ts
17601
17659
  var import_child_process14 = require("child_process");
@@ -17660,9 +17718,9 @@ async function installBd(platform2 = process.platform) {
17660
17718
 
17661
17719
  // src/beads/install-dolt.ts
17662
17720
  var import_child_process15 = require("child_process");
17663
- var fs30 = __toESM(require("fs"));
17664
- var os24 = __toESM(require("os"));
17665
- var path36 = __toESM(require("path"));
17721
+ var fs31 = __toESM(require("fs"));
17722
+ var os25 = __toESM(require("os"));
17723
+ var path37 = __toESM(require("path"));
17666
17724
  var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
17667
17725
  var DOLT_MSI_URL = "https://github.com/dolthub/dolt/releases/latest/download/dolt-windows-amd64.msi";
17668
17726
  function resolveDoltInstallStrategy(platform2) {
@@ -17702,11 +17760,11 @@ function resolveDoltInstallStrategy(platform2) {
17702
17760
  }
17703
17761
  var DOLT_RELEASE_BASE = "https://github.com/dolthub/dolt/releases/latest/download";
17704
17762
  function doltPlatformTuple(platform2, arch) {
17705
- const os31 = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "darwin" : "linux";
17763
+ const os32 = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "darwin" : "linux";
17706
17764
  const a = arch === "x64" ? "amd64" : arch === "arm64" ? "arm64" : null;
17707
17765
  if (!a) return null;
17708
- if (os31 === "windows" && a !== "amd64") return null;
17709
- return `${os31}-${a}`;
17766
+ if (os32 === "windows" && a !== "amd64") return null;
17767
+ return `${os32}-${a}`;
17710
17768
  }
17711
17769
  function resolveDoltTarballStrategy(targetDir, platform2, arch) {
17712
17770
  const tuple = doltPlatformTuple(platform2, arch);
@@ -17751,14 +17809,14 @@ async function installDoltToDir(targetDir, platform2 = process.platform, arch =
17751
17809
  return result;
17752
17810
  }
17753
17811
  var _doltPathSeam = {
17754
- homedir: () => os24.homedir(),
17812
+ homedir: () => os25.homedir(),
17755
17813
  getPath: () => process.env.PATH ?? "",
17756
17814
  setPath: (p2) => {
17757
17815
  process.env.PATH = p2;
17758
17816
  },
17759
17817
  exists: (p2) => {
17760
17818
  try {
17761
- fs30.accessSync(p2, fs30.constants.F_OK);
17819
+ fs31.accessSync(p2, fs31.constants.F_OK);
17762
17820
  return true;
17763
17821
  } catch {
17764
17822
  return false;
@@ -17769,7 +17827,7 @@ function doltBinaryNames(platform2) {
17769
17827
  return platform2 === "win32" ? ["dolt.exe", "dolt.cmd", "dolt"] : ["dolt"];
17770
17828
  }
17771
17829
  function knownDoltDirs(platform2) {
17772
- const P3 = platform2 === "win32" ? path36.win32 : path36.posix;
17830
+ const P3 = platform2 === "win32" ? path37.win32 : path37.posix;
17773
17831
  const home = _doltPathSeam.homedir();
17774
17832
  if (platform2 === "win32") {
17775
17833
  return [
@@ -17785,7 +17843,7 @@ function knownDoltDirs(platform2) {
17785
17843
  ].filter(Boolean);
17786
17844
  }
17787
17845
  function ensureDoltResolvable(platform2 = process.platform) {
17788
- const P3 = platform2 === "win32" ? path36.win32 : path36.posix;
17846
+ const P3 = platform2 === "win32" ? path37.win32 : path37.posix;
17789
17847
  const delim = platform2 === "win32" ? ";" : ":";
17790
17848
  const names = doltBinaryNames(platform2);
17791
17849
  const pathDirs = _doltPathSeam.getPath().split(delim).filter(Boolean);
@@ -17896,8 +17954,8 @@ async function ensureSharedServer(adapter) {
17896
17954
  // src/beads/project-key.ts
17897
17955
  var import_child_process16 = require("child_process");
17898
17956
  var crypto2 = __toESM(require("crypto"));
17899
- var fs31 = __toESM(require("fs"));
17900
- var path37 = __toESM(require("path"));
17957
+ var fs32 = __toESM(require("fs"));
17958
+ var path38 = __toESM(require("path"));
17901
17959
  function normalizeOrigin(raw) {
17902
17960
  const trimmed = raw.trim();
17903
17961
  if (!trimmed) return null;
@@ -17923,17 +17981,17 @@ function normalizeOrigin(raw) {
17923
17981
  return `${host}/${pathPart}`;
17924
17982
  }
17925
17983
  function findRepoRoot(cwd) {
17926
- let dir = path37.resolve(cwd);
17984
+ let dir = path38.resolve(cwd);
17927
17985
  const seen = /* @__PURE__ */ new Set();
17928
17986
  for (let i = 0; i < 256; i++) {
17929
17987
  if (seen.has(dir)) return null;
17930
17988
  seen.add(dir);
17931
17989
  try {
17932
- const stat3 = fs31.statSync(path37.join(dir, ".git"), { throwIfNoEntry: false });
17990
+ const stat3 = fs32.statSync(path38.join(dir, ".git"), { throwIfNoEntry: false });
17933
17991
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
17934
17992
  } catch {
17935
17993
  }
17936
- const parent = path37.dirname(dir);
17994
+ const parent = path38.dirname(dir);
17937
17995
  if (parent === dir) return null;
17938
17996
  dir = parent;
17939
17997
  }
@@ -17944,7 +18002,7 @@ var _execSeam2 = {
17944
18002
  const out2 = (0, import_child_process16.execFileSync)(file, args2, opts);
17945
18003
  return typeof out2 === "string" ? out2 : out2.toString("utf8");
17946
18004
  },
17947
- realpath: (p2) => fs31.realpathSync(p2)
18005
+ realpath: (p2) => fs32.realpathSync(p2)
17948
18006
  };
17949
18007
  function readOrigin(cwd) {
17950
18008
  try {
@@ -17973,7 +18031,7 @@ function deriveProjectIdentity(cwd = process.cwd()) {
17973
18031
  } catch {
17974
18032
  }
17975
18033
  const hash = crypto2.createHash("sha256").update(real).digest("hex");
17976
- return { projectKey: `path:${hash}`, projectLabel: path37.basename(real) || "project" };
18034
+ return { projectKey: `path:${hash}`, projectLabel: path38.basename(real) || "project" };
17977
18035
  }
17978
18036
 
17979
18037
  // src/beads/project-prefix.ts
@@ -18015,17 +18073,17 @@ var _provisionSeam = {
18015
18073
  };
18016
18074
  var _linkSeam = {
18017
18075
  platform: () => process.platform,
18018
- homedir: () => os25.homedir(),
18076
+ homedir: () => os26.homedir(),
18019
18077
  isWritableDir: (dir) => {
18020
18078
  try {
18021
- fs32.accessSync(dir, fs32.constants.W_OK);
18079
+ fs33.accessSync(dir, fs33.constants.W_OK);
18022
18080
  return true;
18023
18081
  } catch {
18024
18082
  return false;
18025
18083
  }
18026
18084
  },
18027
18085
  ensureDir: (dir) => {
18028
- fs32.mkdirSync(dir, { recursive: true });
18086
+ fs33.mkdirSync(dir, { recursive: true });
18029
18087
  },
18030
18088
  /**
18031
18089
  * A directory to symlink `bd` into so the AGENT's shell + Claude Code's
@@ -18046,12 +18104,12 @@ var _linkSeam = {
18046
18104
  * which `linkBdOntoPath` creates if missing.
18047
18105
  */
18048
18106
  cliBinDir: () => {
18049
- const pathDirs = (process.env.PATH ?? "").split(path38.delimiter).filter(Boolean);
18107
+ const pathDirs = (process.env.PATH ?? "").split(path39.delimiter).filter(Boolean);
18050
18108
  const home = _linkSeam.homedir();
18051
- const localBin = home ? path38.join(home, ".local", "bin") : null;
18109
+ const localBin = home ? path39.join(home, ".local", "bin") : null;
18052
18110
  const candidates = [];
18053
18111
  try {
18054
- candidates.push(path38.dirname(process.execPath));
18112
+ candidates.push(path39.dirname(process.execPath));
18055
18113
  } catch {
18056
18114
  }
18057
18115
  if (localBin) candidates.push(localBin);
@@ -18059,9 +18117,9 @@ var _linkSeam = {
18059
18117
  const entry = process.argv[1];
18060
18118
  if (entry) {
18061
18119
  try {
18062
- candidates.push(path38.dirname(fs32.realpathSync(entry)));
18120
+ candidates.push(path39.dirname(fs33.realpathSync(entry)));
18063
18121
  } catch {
18064
- candidates.push(path38.dirname(entry));
18122
+ candidates.push(path39.dirname(entry));
18065
18123
  }
18066
18124
  }
18067
18125
  const onPathWritable = candidates.find(
@@ -18073,20 +18131,20 @@ var _linkSeam = {
18073
18131
  /** Current symlink target at `linkPath`, or null when absent / not a link. */
18074
18132
  readlink: (linkPath) => {
18075
18133
  try {
18076
- return fs32.readlinkSync(linkPath);
18134
+ return fs33.readlinkSync(linkPath);
18077
18135
  } catch {
18078
18136
  return null;
18079
18137
  }
18080
18138
  },
18081
- unlink: (linkPath) => fs32.unlinkSync(linkPath),
18082
- symlink: (target, linkPath) => fs32.symlinkSync(target, linkPath)
18139
+ unlink: (linkPath) => fs33.unlinkSync(linkPath),
18140
+ symlink: (target, linkPath) => fs33.symlinkSync(target, linkPath)
18083
18141
  };
18084
18142
  function linkBdOntoPath(binaryPath) {
18085
18143
  if (_linkSeam.platform() === "win32") return;
18086
18144
  const binDir = _linkSeam.cliBinDir();
18087
18145
  if (!binDir) return;
18088
18146
  _linkSeam.ensureDir(binDir);
18089
- const linkPath = path38.join(binDir, "bd");
18147
+ const linkPath = path39.join(binDir, "bd");
18090
18148
  if (linkPath === binaryPath) return;
18091
18149
  const current = _linkSeam.readlink(linkPath);
18092
18150
  if (current === binaryPath) return;
@@ -18227,7 +18285,7 @@ function dedupeRecipes(agents) {
18227
18285
 
18228
18286
  // src/beads/watcher.ts
18229
18287
  var crypto4 = __toESM(require("crypto"));
18230
- var path39 = __toESM(require("path"));
18288
+ var path40 = __toESM(require("path"));
18231
18289
 
18232
18290
  // src/services/file-watcher/transport.ts
18233
18291
  var http5 = __toESM(require("http"));
@@ -18302,7 +18360,7 @@ var BeadsWatcher = class {
18302
18360
  constructor(opts) {
18303
18361
  this.opts = opts;
18304
18362
  this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
18305
- this.feedPath = opts.feedPath ?? path39.join(opts.cwd ?? process.cwd(), ".beads", "issues.jsonl");
18363
+ this.feedPath = opts.feedPath ?? path40.join(opts.cwd ?? process.cwd(), ".beads", "issues.jsonl");
18306
18364
  this.apiBase = opts.apiBaseUrl ?? API_BASE4;
18307
18365
  }
18308
18366
  opts;
@@ -18580,7 +18638,7 @@ var pendingAttachmentFiles = /* @__PURE__ */ new Set();
18580
18638
  function cleanupAttachmentTempFiles() {
18581
18639
  for (const p2 of pendingAttachmentFiles) {
18582
18640
  try {
18583
- fs33.unlinkSync(p2);
18641
+ fs34.unlinkSync(p2);
18584
18642
  } catch {
18585
18643
  }
18586
18644
  }
@@ -18589,8 +18647,8 @@ function cleanupAttachmentTempFiles() {
18589
18647
  function saveFilesTemp(files) {
18590
18648
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
18591
18649
  const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
18592
- const tmpPath = path40.join(os26.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
18593
- fs33.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
18650
+ const tmpPath = path41.join(os27.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
18651
+ fs34.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
18594
18652
  pendingAttachmentFiles.add(tmpPath);
18595
18653
  return tmpPath;
18596
18654
  });
@@ -18610,7 +18668,7 @@ var startTask = (ctx, _cmd, parsed) => {
18610
18668
  setTimeout(() => {
18611
18669
  for (const p2 of paths) {
18612
18670
  try {
18613
- fs33.unlinkSync(p2);
18671
+ fs34.unlinkSync(p2);
18614
18672
  } catch {
18615
18673
  }
18616
18674
  pendingAttachmentFiles.delete(p2);
@@ -19193,8 +19251,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
19193
19251
  if (args2.length === 0) return detection;
19194
19252
  const binName = args2[0];
19195
19253
  if (binName.startsWith("-")) return detection;
19196
- const binPath = path40.join(cwd, "node_modules", ".bin", binName);
19197
- if (!fs33.existsSync(binPath)) return detection;
19254
+ const binPath = path41.join(cwd, "node_modules", ".bin", binName);
19255
+ if (!fs34.existsSync(binPath)) return detection;
19198
19256
  return {
19199
19257
  ...detection,
19200
19258
  command: binPath,
@@ -19624,9 +19682,9 @@ async function dispatchCommand(ctx, cmd) {
19624
19682
 
19625
19683
  // src/services/file-watcher.service.ts
19626
19684
  var import_child_process19 = require("child_process");
19627
- var fs34 = __toESM(require("fs"));
19628
- var os27 = __toESM(require("os"));
19629
- var path41 = __toESM(require("path"));
19685
+ var fs35 = __toESM(require("fs"));
19686
+ var os28 = __toESM(require("os"));
19687
+ var path42 = __toESM(require("path"));
19630
19688
  var import_ignore = __toESM(require("ignore"));
19631
19689
 
19632
19690
  // src/services/file-watcher/diff-parser.ts
@@ -19736,10 +19794,10 @@ var WINDOWS_LEGACY_JUNCTIONS = [
19736
19794
  /[\\/]Start Menu([\\/]|$)/i,
19737
19795
  /[\\/]Templates([\\/]|$)/i
19738
19796
  ];
19739
- function isUnsafeWindowsWatchRoot(dir, homedir23) {
19797
+ function isUnsafeWindowsWatchRoot(dir, homedir24) {
19740
19798
  const norm = (p2) => p2.replace(/\//g, "\\").replace(/\\+$/, "").toLowerCase();
19741
19799
  const cwd = norm(dir);
19742
- const home = norm(homedir23);
19800
+ const home = norm(homedir24);
19743
19801
  if (cwd === home) return true;
19744
19802
  if (/^[a-z]:$/.test(cwd)) return true;
19745
19803
  const sysRoots = [
@@ -19769,18 +19827,18 @@ var _findGitRootSeam = {
19769
19827
  resolve: _defaultFindGitRoot
19770
19828
  };
19771
19829
  function _defaultFindGitRoot(startDir) {
19772
- let dir = path41.resolve(startDir);
19830
+ let dir = path42.resolve(startDir);
19773
19831
  const seen = /* @__PURE__ */ new Set();
19774
19832
  for (let i = 0; i < 256; i++) {
19775
19833
  if (seen.has(dir)) return null;
19776
19834
  seen.add(dir);
19777
19835
  try {
19778
- const gitPath = path41.join(dir, ".git");
19779
- const stat3 = fs34.statSync(gitPath, { throwIfNoEntry: false });
19836
+ const gitPath = path42.join(dir, ".git");
19837
+ const stat3 = fs35.statSync(gitPath, { throwIfNoEntry: false });
19780
19838
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
19781
19839
  } catch {
19782
19840
  }
19783
- const parent = path41.dirname(dir);
19841
+ const parent = path42.dirname(dir);
19784
19842
  if (parent === dir) return null;
19785
19843
  dir = parent;
19786
19844
  }
@@ -19838,7 +19896,7 @@ var FileWatcherService = class {
19838
19896
  throw new Error("FileWatcherService has already been stopped \u2014 re-instantiate to restart.");
19839
19897
  }
19840
19898
  const isWin = process.platform === "win32";
19841
- if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os27.homedir())) {
19899
+ if (isWin && isUnsafeWindowsWatchRoot(this.opts.workingDir, os28.homedir())) {
19842
19900
  log.warn(
19843
19901
  "fileWatcher",
19844
19902
  `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.`
@@ -20025,7 +20083,7 @@ var FileWatcherService = class {
20025
20083
  }
20026
20084
  async emitForFile(absPath, changeType) {
20027
20085
  if (this.stopped) return;
20028
- const fileDir = path41.dirname(absPath);
20086
+ const fileDir = path42.dirname(absPath);
20029
20087
  let gitRoot = this.gitRootByDir.get(fileDir);
20030
20088
  if (gitRoot === void 0) {
20031
20089
  gitRoot = findGitRoot2(fileDir);
@@ -20038,19 +20096,19 @@ var FileWatcherService = class {
20038
20096
  );
20039
20097
  return;
20040
20098
  }
20041
- const relPathInRepo = path41.relative(gitRoot, absPath);
20099
+ const relPathInRepo = path42.relative(gitRoot, absPath);
20042
20100
  if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
20043
20101
  const matcher = this.getGitIgnoreMatcher(gitRoot);
20044
20102
  if (matcher && matcher.ignores(relPathInRepo)) {
20045
20103
  log.trace(
20046
20104
  "fileWatcher",
20047
- `${relPathInRepo} ignored by ${path41.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
20105
+ `${relPathInRepo} ignored by ${path42.basename(gitRoot)}/.gitignore \u2014 suppressing emit`
20048
20106
  );
20049
20107
  return;
20050
20108
  }
20051
20109
  this.opts.onRepoDirty?.(gitRoot);
20052
- const repoPath = path41.relative(this.opts.workingDir, gitRoot);
20053
- const repoName = path41.basename(gitRoot);
20110
+ const repoPath = path42.relative(this.opts.workingDir, gitRoot);
20111
+ const repoName = path42.basename(gitRoot);
20054
20112
  let diffText = "";
20055
20113
  let fileStatus = "modified";
20056
20114
  if (changeType === "unlink") {
@@ -20225,7 +20283,7 @@ var FileWatcherService = class {
20225
20283
  collectGitignoreFiles(repoRoot, dir, matcher) {
20226
20284
  let entries;
20227
20285
  try {
20228
- entries = fs34.readdirSync(dir, { withFileTypes: true });
20286
+ entries = fs35.readdirSync(dir, { withFileTypes: true });
20229
20287
  } catch {
20230
20288
  return;
20231
20289
  }
@@ -20234,16 +20292,16 @@ var FileWatcherService = class {
20234
20292
  );
20235
20293
  if (gitignoreEntry) {
20236
20294
  try {
20237
- const body = fs34.readFileSync(path41.join(dir, ".gitignore"), "utf8");
20238
- const rel = path41.relative(repoRoot, dir).replace(/\\/g, "/");
20295
+ const body = fs35.readFileSync(path42.join(dir, ".gitignore"), "utf8");
20296
+ const rel = path42.relative(repoRoot, dir).replace(/\\/g, "/");
20239
20297
  const prefixed = body.split(/\r?\n/).map((line) => {
20240
20298
  const trimmed = line.trim();
20241
20299
  if (!trimmed || trimmed.startsWith("#")) return line;
20242
20300
  if (!rel) return line;
20243
20301
  if (trimmed.startsWith("!")) {
20244
- return "!" + path41.posix.join(rel, trimmed.slice(1));
20302
+ return "!" + path42.posix.join(rel, trimmed.slice(1));
20245
20303
  }
20246
- return path41.posix.join(rel, trimmed);
20304
+ return path42.posix.join(rel, trimmed);
20247
20305
  }).join("\n");
20248
20306
  matcher.add(prefixed);
20249
20307
  } catch {
@@ -20252,7 +20310,7 @@ var FileWatcherService = class {
20252
20310
  for (const entry of entries) {
20253
20311
  if (!entry.isDirectory()) continue;
20254
20312
  if (entry.name === ".git") continue;
20255
- const childAbs = path41.join(dir, entry.name);
20313
+ const childAbs = path42.join(dir, entry.name);
20256
20314
  if (isIgnoredFilePath(childAbs)) continue;
20257
20315
  this.collectGitignoreFiles(repoRoot, childAbs, matcher);
20258
20316
  }
@@ -20422,7 +20480,7 @@ var import_crypto4 = require("crypto");
20422
20480
 
20423
20481
  // src/services/turn-files/git-changeset.ts
20424
20482
  var import_child_process20 = require("child_process");
20425
- var path42 = __toESM(require("path"));
20483
+ var path43 = __toESM(require("path"));
20426
20484
  async function collectRepoChangeset(opts) {
20427
20485
  const status2 = await runGit3(opts.repoRoot, ["status", "--porcelain=v1", "-z"]);
20428
20486
  if (status2 === null) return null;
@@ -20533,7 +20591,7 @@ function defaultRunGit(cwd, args2) {
20533
20591
  });
20534
20592
  }
20535
20593
  async function discoverRepos(workingDir, maxDepth = 4) {
20536
- const fs40 = await import("fs/promises");
20594
+ const fs41 = await import("fs/promises");
20537
20595
  const out2 = [];
20538
20596
  await walk(workingDir, 0);
20539
20597
  return out2;
@@ -20541,7 +20599,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
20541
20599
  if (depth > maxDepth) return;
20542
20600
  let entries = [];
20543
20601
  try {
20544
- const dirents = await fs40.readdir(dir, { withFileTypes: true });
20602
+ const dirents = await fs41.readdir(dir, { withFileTypes: true });
20545
20603
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
20546
20604
  } catch {
20547
20605
  return;
@@ -20552,8 +20610,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
20552
20610
  if (hasGit) {
20553
20611
  out2.push({
20554
20612
  repoRoot: dir,
20555
- repoPath: path42.relative(workingDir, dir),
20556
- repoName: path42.basename(dir)
20613
+ repoPath: path43.relative(workingDir, dir),
20614
+ repoName: path43.basename(dir)
20557
20615
  });
20558
20616
  return;
20559
20617
  }
@@ -20561,14 +20619,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
20561
20619
  if (!entry.isDirectory) continue;
20562
20620
  if (entry.name === "node_modules") continue;
20563
20621
  if (entry.name === "dist" || entry.name === "build") continue;
20564
- await walk(path42.join(dir, entry.name), depth + 1);
20622
+ await walk(path43.join(dir, entry.name), depth + 1);
20565
20623
  }
20566
20624
  }
20567
20625
  }
20568
20626
 
20569
20627
  // src/services/turn-files/files-outbox.ts
20570
- var fs35 = __toESM(require("fs/promises"));
20571
- var path43 = __toESM(require("path"));
20628
+ var fs36 = __toESM(require("fs/promises"));
20629
+ var path44 = __toESM(require("path"));
20572
20630
  var import_os7 = require("os");
20573
20631
  var HOME_OUTBOX_DIR = ".codeam/outbox";
20574
20632
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -20601,16 +20659,16 @@ var FilesOutbox = class {
20601
20659
  backoffIndex = 0;
20602
20660
  stopped = false;
20603
20661
  constructor(opts) {
20604
- const base = opts.baseDir ?? path43.join(homeDir(), HOME_OUTBOX_DIR);
20605
- this.filePath = path43.join(base, `${opts.sessionId}.jsonl`);
20662
+ const base = opts.baseDir ?? path44.join(homeDir(), HOME_OUTBOX_DIR);
20663
+ this.filePath = path44.join(base, `${opts.sessionId}.jsonl`);
20606
20664
  this.post = opts.post;
20607
20665
  this.autoSchedule = opts.autoSchedule !== false;
20608
20666
  }
20609
20667
  /** Persist the entry to disk and trigger a flush. Returns once the
20610
20668
  * line is durable on disk (not once the POST succeeds). */
20611
20669
  async enqueue(entry) {
20612
- await fs35.mkdir(path43.dirname(this.filePath), { recursive: true });
20613
- await fs35.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
20670
+ await fs36.mkdir(path44.dirname(this.filePath), { recursive: true });
20671
+ await fs36.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
20614
20672
  this.backoffIndex = 0;
20615
20673
  if (this.autoSchedule) this.scheduleFlush(0);
20616
20674
  }
@@ -20699,7 +20757,7 @@ var FilesOutbox = class {
20699
20757
  async readAll() {
20700
20758
  let raw = "";
20701
20759
  try {
20702
- raw = await fs35.readFile(this.filePath, "utf8");
20760
+ raw = await fs36.readFile(this.filePath, "utf8");
20703
20761
  } catch {
20704
20762
  return [];
20705
20763
  }
@@ -20723,12 +20781,12 @@ var FilesOutbox = class {
20723
20781
  async rewrite(entries) {
20724
20782
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
20725
20783
  if (entries.length === 0) {
20726
- await fs35.unlink(this.filePath).catch(() => void 0);
20784
+ await fs36.unlink(this.filePath).catch(() => void 0);
20727
20785
  return;
20728
20786
  }
20729
20787
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
20730
- await fs35.writeFile(tmpPath, payload, "utf8");
20731
- await fs35.rename(tmpPath, this.filePath);
20788
+ await fs36.writeFile(tmpPath, payload, "utf8");
20789
+ await fs36.rename(tmpPath, this.filePath);
20732
20790
  }
20733
20791
  };
20734
20792
  function applyJitter(ms) {
@@ -21327,6 +21385,7 @@ async function runAcpSession(opts) {
21327
21385
  path: opts.cwd,
21328
21386
  done: true
21329
21387
  });
21388
+ maybeSendOnboardingWelcome({ client: client2, sessionId: opts.sessionId, cwd: opts.cwd });
21330
21389
  const runtime = createInteractiveAgentStrategy(opts.agent, createOsStrategy());
21331
21390
  const models = await runtime.listModels();
21332
21391
  const history = new AcpHistory(publisher, { agent: opts.agent, acpSessionId });
@@ -22549,9 +22608,9 @@ var OutputService = class _OutputService {
22549
22608
  };
22550
22609
 
22551
22610
  // src/services/history.service.ts
22552
- var fs36 = __toESM(require("fs"));
22553
- var path44 = __toESM(require("path"));
22554
- var os28 = __toESM(require("os"));
22611
+ var fs37 = __toESM(require("fs"));
22612
+ var path45 = __toESM(require("path"));
22613
+ var os29 = __toESM(require("os"));
22555
22614
  var https7 = __toESM(require("https"));
22556
22615
  var http7 = __toESM(require("http"));
22557
22616
  var import_zod2 = require("zod");
@@ -22578,7 +22637,7 @@ function parseJsonl(filePath) {
22578
22637
  const messages = [];
22579
22638
  let raw;
22580
22639
  try {
22581
- raw = fs36.readFileSync(filePath, "utf8");
22640
+ raw = fs37.readFileSync(filePath, "utf8");
22582
22641
  } catch (err) {
22583
22642
  if (err.code !== "ENOENT") {
22584
22643
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -22713,7 +22772,7 @@ var HistoryService = class _HistoryService {
22713
22772
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
22714
22773
  }
22715
22774
  get projectDir() {
22716
- return this.runtime.resolveHistoryDir(this.cwd) ?? path44.join(os28.homedir(), ".claude", "projects", encodeCwd(this.cwd));
22775
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path45.join(os29.homedir(), ".claude", "projects", encodeCwd(this.cwd));
22717
22776
  }
22718
22777
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
22719
22778
  setCurrentConversationId(id) {
@@ -22725,7 +22784,7 @@ var HistoryService = class _HistoryService {
22725
22784
  /** Return the current message count in the active conversation. */
22726
22785
  getCurrentMessageCount() {
22727
22786
  if (!this.currentConversationId) return 0;
22728
- const filePath = path44.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22787
+ const filePath = path45.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22729
22788
  return parseJsonl(filePath).length;
22730
22789
  }
22731
22790
  /**
@@ -22736,7 +22795,7 @@ var HistoryService = class _HistoryService {
22736
22795
  const deadline = Date.now() + timeoutMs;
22737
22796
  while (Date.now() < deadline) {
22738
22797
  if (!this.currentConversationId) return null;
22739
- const filePath = path44.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22798
+ const filePath = path45.join(this.projectDir, `${this.currentConversationId}.jsonl`);
22740
22799
  const messages = parseJsonl(filePath);
22741
22800
  if (messages.length > previousCount) {
22742
22801
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -22762,16 +22821,16 @@ var HistoryService = class _HistoryService {
22762
22821
  const dir = this.projectDir;
22763
22822
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
22764
22823
  try {
22765
- const files = fs36.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
22824
+ const files = fs37.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
22766
22825
  try {
22767
- const stat3 = fs36.statSync(path44.join(dir, e.name));
22826
+ const stat3 = fs37.statSync(path45.join(dir, e.name));
22768
22827
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
22769
22828
  } catch {
22770
22829
  return { name: e.name, mtime: 0, birthtime: 0 };
22771
22830
  }
22772
22831
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
22773
22832
  if (files.length > 0) {
22774
- this.currentConversationId = path44.basename(files[0].name, ".jsonl");
22833
+ this.currentConversationId = path45.basename(files[0].name, ".jsonl");
22775
22834
  }
22776
22835
  } catch {
22777
22836
  }
@@ -22805,13 +22864,13 @@ var HistoryService = class _HistoryService {
22805
22864
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
22806
22865
  let entries;
22807
22866
  try {
22808
- entries = fs36.readdirSync(dir, { withFileTypes: true });
22867
+ entries = fs37.readdirSync(dir, { withFileTypes: true });
22809
22868
  } catch {
22810
22869
  return null;
22811
22870
  }
22812
22871
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
22813
22872
  try {
22814
- const stat3 = fs36.statSync(path44.join(dir, e.name));
22873
+ const stat3 = fs37.statSync(path45.join(dir, e.name));
22815
22874
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
22816
22875
  } catch {
22817
22876
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -22820,12 +22879,12 @@ var HistoryService = class _HistoryService {
22820
22879
  if (files.length === 0) return null;
22821
22880
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
22822
22881
  if (!files.some((f) => f.name === targetFile)) return null;
22823
- return this.extractUsageFromFile(path44.join(dir, targetFile));
22882
+ return this.extractUsageFromFile(path45.join(dir, targetFile));
22824
22883
  }
22825
22884
  extractUsageFromFile(filePath) {
22826
22885
  let raw;
22827
22886
  try {
22828
- raw = fs36.readFileSync(filePath, "utf8");
22887
+ raw = fs37.readFileSync(filePath, "utf8");
22829
22888
  } catch {
22830
22889
  return null;
22831
22890
  }
@@ -22870,9 +22929,9 @@ var HistoryService = class _HistoryService {
22870
22929
  let totalCost = 0;
22871
22930
  let files;
22872
22931
  try {
22873
- files = fs36.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
22932
+ files = fs37.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
22874
22933
  try {
22875
- return fs36.statSync(path44.join(projectDir, f)).mtimeMs >= monthStartMs;
22934
+ return fs37.statSync(path45.join(projectDir, f)).mtimeMs >= monthStartMs;
22876
22935
  } catch {
22877
22936
  return false;
22878
22937
  }
@@ -22883,7 +22942,7 @@ var HistoryService = class _HistoryService {
22883
22942
  for (const file of files) {
22884
22943
  let raw;
22885
22944
  try {
22886
- raw = fs36.readFileSync(path44.join(projectDir, file), "utf8");
22945
+ raw = fs37.readFileSync(path45.join(projectDir, file), "utf8");
22887
22946
  } catch {
22888
22947
  continue;
22889
22948
  }
@@ -22947,7 +23006,7 @@ var HistoryService = class _HistoryService {
22947
23006
  * showing an empty conversation.
22948
23007
  */
22949
23008
  async loadConversation(sessionId) {
22950
- const filePath = path44.join(this.projectDir, `${sessionId}.jsonl`);
23009
+ const filePath = path45.join(this.projectDir, `${sessionId}.jsonl`);
22951
23010
  const messages = parseJsonl(filePath);
22952
23011
  if (messages.length === 0) return;
22953
23012
  const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
@@ -23001,7 +23060,7 @@ var HistoryService = class _HistoryService {
23001
23060
  if (!this.currentConversationId) return 0;
23002
23061
  }
23003
23062
  const sessionId = this.currentConversationId;
23004
- const filePath = path44.join(this.projectDir, `${sessionId}.jsonl`);
23063
+ const filePath = path45.join(this.projectDir, `${sessionId}.jsonl`);
23005
23064
  const messages = parseJsonl(filePath);
23006
23065
  if (messages.length === 0) return 0;
23007
23066
  const marker = this.lastUploadedUuid.get(sessionId);
@@ -23922,8 +23981,8 @@ async function autoLinkAfterPair(opts) {
23922
23981
  }
23923
23982
 
23924
23983
  // src/commands/pair-auto.ts
23925
- var fs37 = __toESM(require("fs"));
23926
- var os29 = __toESM(require("os"));
23984
+ var fs38 = __toESM(require("fs"));
23985
+ var os30 = __toESM(require("os"));
23927
23986
  var import_crypto7 = require("crypto");
23928
23987
 
23929
23988
  // src/commands/start-infra-only.ts
@@ -24118,12 +24177,12 @@ function readTokenFromArgs(args2) {
24118
24177
  }
24119
24178
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
24120
24179
  if (fileFlag) {
24121
- const path51 = fileFlag.slice("--token-file=".length);
24180
+ const path52 = fileFlag.slice("--token-file=".length);
24122
24181
  try {
24123
- const content = fs37.readFileSync(path51, "utf8").trim();
24124
- if (content.length === 0) fail(`--token-file ${path51} is empty`);
24182
+ const content = fs38.readFileSync(path52, "utf8").trim();
24183
+ if (content.length === 0) fail(`--token-file ${path52} is empty`);
24125
24184
  try {
24126
- fs37.unlinkSync(path51);
24185
+ fs38.unlinkSync(path52);
24127
24186
  } catch {
24128
24187
  }
24129
24188
  return content;
@@ -24149,7 +24208,7 @@ async function claimOnce(token, pluginId) {
24149
24208
  pluginId,
24150
24209
  ideName: "codeam-cli (codespace)",
24151
24210
  ideVersion: process.env.npm_package_version ?? "unknown",
24152
- hostname: os29.hostname(),
24211
+ hostname: os30.hostname(),
24153
24212
  codespaceName: process.env.CODESPACE_NAME ?? "",
24154
24213
  // Current git branch of the codespace's working directory, so the
24155
24214
  // backend can populate `PairedSession.branch` for the codespace pair.
@@ -24389,7 +24448,7 @@ var import_picocolors10 = __toESM(require("picocolors"));
24389
24448
  var import_child_process22 = require("child_process");
24390
24449
  var import_util4 = require("util");
24391
24450
  var import_picocolors8 = __toESM(require("picocolors"));
24392
- var path45 = __toESM(require("path"));
24451
+ var path46 = __toESM(require("path"));
24393
24452
  var execFileP5 = (0, import_util4.promisify)(import_child_process22.execFile);
24394
24453
  var MAX_BUFFER = 8 * 1024 * 1024;
24395
24454
  function resetStdinForChild() {
@@ -24878,7 +24937,7 @@ var GitHubCodespacesProvider = class {
24878
24937
  });
24879
24938
  }
24880
24939
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
24881
- const remoteDir = path45.posix.dirname(remotePath);
24940
+ const remoteDir = path46.posix.dirname(remotePath);
24882
24941
  const parts = [
24883
24942
  `mkdir -p ${shellQuote(remoteDir)}`,
24884
24943
  `cat > ${shellQuote(remotePath)}`
@@ -24948,7 +25007,7 @@ function shellQuote(s) {
24948
25007
  // src/services/providers/gitpod.ts
24949
25008
  var import_child_process23 = require("child_process");
24950
25009
  var import_util5 = require("util");
24951
- var path46 = __toESM(require("path"));
25010
+ var path47 = __toESM(require("path"));
24952
25011
  var import_picocolors9 = __toESM(require("picocolors"));
24953
25012
  var execFileP6 = (0, import_util5.promisify)(import_child_process23.execFile);
24954
25013
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -25188,7 +25247,7 @@ var GitpodProvider = class {
25188
25247
  });
25189
25248
  }
25190
25249
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
25191
- const remoteDir = path46.posix.dirname(remotePath);
25250
+ const remoteDir = path47.posix.dirname(remotePath);
25192
25251
  const parts = [
25193
25252
  `mkdir -p ${shellQuote2(remoteDir)}`,
25194
25253
  `cat > ${shellQuote2(remotePath)}`
@@ -25224,7 +25283,7 @@ function shellQuote2(s) {
25224
25283
  // src/services/providers/gitlab-workspaces.ts
25225
25284
  var import_child_process24 = require("child_process");
25226
25285
  var import_util6 = require("util");
25227
- var path47 = __toESM(require("path"));
25286
+ var path48 = __toESM(require("path"));
25228
25287
  var execFileP7 = (0, import_util6.promisify)(import_child_process24.execFile);
25229
25288
  var MAX_BUFFER3 = 8 * 1024 * 1024;
25230
25289
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -25484,7 +25543,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
25484
25543
  }
25485
25544
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
25486
25545
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
25487
- const remoteDir = path47.posix.dirname(remotePath);
25546
+ const remoteDir = path48.posix.dirname(remotePath);
25488
25547
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
25489
25548
  if (options.mode != null) {
25490
25549
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -25552,7 +25611,7 @@ function shellQuote3(s) {
25552
25611
  // src/services/providers/railway.ts
25553
25612
  var import_child_process25 = require("child_process");
25554
25613
  var import_util7 = require("util");
25555
- var path48 = __toESM(require("path"));
25614
+ var path49 = __toESM(require("path"));
25556
25615
  var execFileP8 = (0, import_util7.promisify)(import_child_process25.execFile);
25557
25616
  var MAX_BUFFER4 = 8 * 1024 * 1024;
25558
25617
  function resetStdinForChild4() {
@@ -25788,7 +25847,7 @@ var RailwayProvider = class {
25788
25847
  if (!projectId || !serviceId) {
25789
25848
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
25790
25849
  }
25791
- const remoteDir = path48.posix.dirname(remotePath);
25850
+ const remoteDir = path49.posix.dirname(remotePath);
25792
25851
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
25793
25852
  if (options.mode != null) {
25794
25853
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -26331,8 +26390,8 @@ async function stopWorkspaceFromLocal(target) {
26331
26390
  var import_node_dns = require("dns");
26332
26391
  var import_node_util4 = require("util");
26333
26392
  var import_node_crypto8 = require("crypto");
26334
- var fs38 = __toESM(require("fs"));
26335
- var path49 = __toESM(require("path"));
26393
+ var fs39 = __toESM(require("fs"));
26394
+ var path50 = __toESM(require("path"));
26336
26395
  var import_picocolors12 = __toESM(require("picocolors"));
26337
26396
  var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
26338
26397
  async function checkDns(apiBase) {
@@ -26388,13 +26447,13 @@ async function checkHealth(apiBase) {
26388
26447
  }
26389
26448
  }
26390
26449
  function checkConfigDir() {
26391
- const dir = path49.join(require("os").homedir(), ".codeam");
26450
+ const dir = path50.join(require("os").homedir(), ".codeam");
26392
26451
  try {
26393
- fs38.mkdirSync(dir, { recursive: true, mode: 448 });
26394
- const probe = path49.join(dir, ".doctor-probe");
26395
- fs38.writeFileSync(probe, "ok", { mode: 384 });
26396
- const read = fs38.readFileSync(probe, "utf8");
26397
- fs38.unlinkSync(probe);
26452
+ fs39.mkdirSync(dir, { recursive: true, mode: 448 });
26453
+ const probe = path50.join(dir, ".doctor-probe");
26454
+ fs39.writeFileSync(probe, "ok", { mode: 384 });
26455
+ const read = fs39.readFileSync(probe, "utf8");
26456
+ fs39.unlinkSync(probe);
26398
26457
  if (read !== "ok") throw new Error("write/read round-trip mismatch");
26399
26458
  return {
26400
26459
  id: "config-dir",
@@ -26434,9 +26493,9 @@ function checkSessions() {
26434
26493
  }
26435
26494
  }
26436
26495
  function checkAgentBinaries() {
26437
- const os31 = createOsStrategy();
26496
+ const os32 = createOsStrategy();
26438
26497
  return getEnabledAgents().map((meta) => {
26439
- const found = os31.findInPath(meta.binaryName);
26498
+ const found = os32.findInPath(meta.binaryName);
26440
26499
  return {
26441
26500
  id: `agent-${meta.id}`,
26442
26501
  label: `Agent binary: ${meta.displayName} (${meta.binaryName})`,
@@ -26458,7 +26517,7 @@ function checkNodePty() {
26458
26517
  detail: "not required on this platform"
26459
26518
  };
26460
26519
  }
26461
- const vendoredPath = path49.join(__dirname, "vendor", "node-pty");
26520
+ const vendoredPath = path50.join(__dirname, "vendor", "node-pty");
26462
26521
  for (const target of [vendoredPath, "node-pty"]) {
26463
26522
  try {
26464
26523
  require(target);
@@ -26500,7 +26559,7 @@ function checkChokidar() {
26500
26559
  }
26501
26560
  async function doctor(args2 = []) {
26502
26561
  const json = args2.includes("--json");
26503
- const cliVersion = true ? "2.36.5" : "0.0.0-dev";
26562
+ const cliVersion = true ? "2.37.0" : "0.0.0-dev";
26504
26563
  const apiBase = resolveApiBaseUrl();
26505
26564
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
26506
26565
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -26699,7 +26758,7 @@ async function completion(args2) {
26699
26758
  // src/commands/version.ts
26700
26759
  var import_picocolors13 = __toESM(require("picocolors"));
26701
26760
  function version2() {
26702
- const v = true ? "2.36.5" : "unknown";
26761
+ const v = true ? "2.37.0" : "unknown";
26703
26762
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
26704
26763
  }
26705
26764
 
@@ -26827,9 +26886,9 @@ function tryShowSubcommandHelp(cmd, args2) {
26827
26886
  var _subcommandHelpKeys = Object.keys(HELPS);
26828
26887
 
26829
26888
  // src/lib/updateNotifier.ts
26830
- var fs39 = __toESM(require("fs"));
26831
- var os30 = __toESM(require("os"));
26832
- var path50 = __toESM(require("path"));
26889
+ var fs40 = __toESM(require("fs"));
26890
+ var os31 = __toESM(require("os"));
26891
+ var path51 = __toESM(require("path"));
26833
26892
  var https8 = __toESM(require("https"));
26834
26893
  var import_node_child_process12 = require("child_process");
26835
26894
  var import_picocolors16 = __toESM(require("picocolors"));
@@ -26838,12 +26897,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
26838
26897
  var TTL_MS = 24 * 60 * 60 * 1e3;
26839
26898
  var REQUEST_TIMEOUT_MS = 1500;
26840
26899
  function cachePath() {
26841
- const dir = path50.join(os30.homedir(), ".codeam");
26842
- return path50.join(dir, "update-check.json");
26900
+ const dir = path51.join(os31.homedir(), ".codeam");
26901
+ return path51.join(dir, "update-check.json");
26843
26902
  }
26844
26903
  function readCache() {
26845
26904
  try {
26846
- const raw = fs39.readFileSync(cachePath(), "utf8");
26905
+ const raw = fs40.readFileSync(cachePath(), "utf8");
26847
26906
  const parsed = JSON.parse(raw);
26848
26907
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
26849
26908
  return parsed;
@@ -26854,10 +26913,10 @@ function readCache() {
26854
26913
  function writeCache(cache) {
26855
26914
  try {
26856
26915
  const file = cachePath();
26857
- fs39.mkdirSync(path50.dirname(file), { recursive: true });
26916
+ fs40.mkdirSync(path51.dirname(file), { recursive: true });
26858
26917
  const tmp = `${file}.${process.pid}.tmp`;
26859
- fs39.writeFileSync(tmp, JSON.stringify(cache));
26860
- fs39.renameSync(tmp, file);
26918
+ fs40.writeFileSync(tmp, JSON.stringify(cache));
26919
+ fs40.renameSync(tmp, file);
26861
26920
  } catch {
26862
26921
  }
26863
26922
  }
@@ -26931,8 +26990,8 @@ function isLinkedInstall() {
26931
26990
  timeout: 2e3
26932
26991
  }).trim();
26933
26992
  if (!root) return false;
26934
- const pkgPath = path50.join(root, PKG_NAME);
26935
- return fs39.lstatSync(pkgPath).isSymbolicLink();
26993
+ const pkgPath = path51.join(root, PKG_NAME);
26994
+ return fs40.lstatSync(pkgPath).isSymbolicLink();
26936
26995
  } catch {
26937
26996
  return false;
26938
26997
  }
@@ -26968,7 +27027,7 @@ function maybeAutoUpdate(currentVersion, latest) {
26968
27027
  return;
26969
27028
  }
26970
27029
  try {
26971
- fs39.unlinkSync(cachePath());
27030
+ fs40.unlinkSync(cachePath());
26972
27031
  } catch {
26973
27032
  }
26974
27033
  process.stderr.write(` ${import_picocolors16.default.green("\u2713")} Updated. Resuming session...
@@ -26985,7 +27044,7 @@ function checkForUpdates() {
26985
27044
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
26986
27045
  if (process.env.CI) return;
26987
27046
  if (!process.stdout.isTTY) return;
26988
- const current = true ? "2.36.5" : null;
27047
+ const current = true ? "2.37.0" : null;
26989
27048
  if (!current) return;
26990
27049
  const cache = readCache();
26991
27050
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;