codeam-cli 2.75.23 → 2.75.26

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 +13 -0
  2. package/dist/index.js +1232 -507
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -357,8 +357,8 @@ function defaultSpawn(timeoutMs) {
357
357
  });
358
358
  }
359
359
  function resolveConvexBin(cwd) {
360
- const local = path93.join(cwd, "node_modules", ".bin", process.platform === "win32" ? "convex.cmd" : "convex");
361
- if (fs79.existsSync(local)) return { cmd: local, args: [] };
360
+ const local = path94.join(cwd, "node_modules", ".bin", process.platform === "win32" ? "convex.cmd" : "convex");
361
+ if (fs80.existsSync(local)) return { cmd: local, args: [] };
362
362
  return { cmd: "npx", args: ["--yes", "convex"] };
363
363
  }
364
364
  function redact(text, key) {
@@ -489,13 +489,13 @@ async function runConvexAdminMcp(client3, id) {
489
489
  });
490
490
  await server.connect(new StdioServerTransport());
491
491
  }
492
- var import_node_child_process32, fs79, path93, TOOLS;
492
+ var import_node_child_process32, fs80, path94, TOOLS;
493
493
  var init_convex_admin_mcp = __esm({
494
494
  "src/integrations/convex-admin-mcp.ts"() {
495
495
  "use strict";
496
496
  import_node_child_process32 = require("child_process");
497
- fs79 = __toESM(require("fs"));
498
- path93 = __toESM(require("path"));
497
+ fs80 = __toESM(require("fs"));
498
+ path94 = __toESM(require("path"));
499
499
  TOOLS = [
500
500
  {
501
501
  name: "tables",
@@ -3248,6 +3248,9 @@ var USER_EVENTS = {
3248
3248
  PREVIEW_STOPPED: "preview_stopped",
3249
3249
  PREVIEW_ERROR: "preview_error",
3250
3250
  PREVIEW_PROGRESS: "preview_progress",
3251
+ /** The agent points at an element of the running preview (`highlight_element`
3252
+ * MCP tool) — the inspector client draws the agent's mark over it. */
3253
+ PREVIEW_AGENT_HIGHLIGHT: "preview_agent_highlight",
3251
3254
  BEADS_STATE_CHANGED: "beads_state_changed",
3252
3255
  BEADS_PROVISIONING: "beads_provisioning",
3253
3256
  BEADS_TEAM_MEMORY_CHANGED: "beads_team_memory_changed",
@@ -3525,11 +3528,11 @@ function quiet(fn) {
3525
3528
  log.debug(TAG, "ignored sync error", err);
3526
3529
  }
3527
3530
  }
3528
- function rmIfExistsQuiet(path95) {
3531
+ function rmIfExistsQuiet(path96) {
3529
3532
  try {
3530
- fs2.rmSync(path95, { force: true });
3533
+ fs2.rmSync(path96, { force: true });
3531
3534
  } catch (err) {
3532
- log.debug(TAG, `rmIfExists failed for ${path95}`, err);
3535
+ log.debug(TAG, `rmIfExists failed for ${path96}`, err);
3533
3536
  }
3534
3537
  }
3535
3538
  function killQuiet(target, signal = "SIGTERM") {
@@ -3695,9 +3698,9 @@ var _default = makeConfig();
3695
3698
  var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, setDisable1mContext, setSessionAgent, setSquadAuto, getSquadAuto, clearAll, saveCliConfig, loadCliConfig } = _default;
3696
3699
 
3697
3700
  // src/commands/pair-auto.ts
3698
- var fs51 = __toESM(require("fs"));
3701
+ var fs52 = __toESM(require("fs"));
3699
3702
  var os40 = __toESM(require("os"));
3700
- var path59 = __toESM(require("path"));
3703
+ var path60 = __toESM(require("path"));
3701
3704
  var import_crypto3 = require("crypto");
3702
3705
 
3703
3706
  // src/services/telemetry.service.ts
@@ -3733,8 +3736,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
3733
3736
  return decodedFile;
3734
3737
  };
3735
3738
  }
3736
- function normalizeWindowsPath(path95) {
3737
- return path95.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
3739
+ function normalizeWindowsPath(path96) {
3740
+ return path96.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
3738
3741
  }
3739
3742
 
3740
3743
  // ../../node_modules/@posthog/core/dist/error-tracking/index.mjs
@@ -6467,13 +6470,13 @@ var PostHogCoreStateless = class {
6467
6470
  sentFromRoute += batchMessages.length;
6468
6471
  }
6469
6472
  }
6470
- async _sendOtlpBatch({ path: path95, payload }) {
6473
+ async _sendOtlpBatch({ path: path96, payload }) {
6471
6474
  if (this.disabled) return {
6472
6475
  kind: "fatal",
6473
6476
  error: new Error("The client is disabled")
6474
6477
  };
6475
6478
  const serialized = JSON.stringify(payload);
6476
- const url2 = `${this.host}/i/v1/${path95}?token=${encodeURIComponent(this.apiKey)}`;
6479
+ const url2 = `${this.host}/i/v1/${path96}?token=${encodeURIComponent(this.apiKey)}`;
6477
6480
  const gzippedPayload = this.disableCompression ? null : await this.compressPayload(serialized);
6478
6481
  const fetchOptions = {
6479
6482
  method: "POST",
@@ -7713,14 +7716,14 @@ async function addSourceContext(frames, openSourceFile = import_promises.open, l
7713
7716
  LRU_FILE_CONTENTS_CACHE.reduce();
7714
7717
  return frames;
7715
7718
  }
7716
- async function openRegularSourceFile(path95, openSourceFile, logger) {
7719
+ async function openRegularSourceFile(path96, openSourceFile, logger) {
7717
7720
  let fileHandle;
7718
7721
  let isValid = false;
7719
7722
  try {
7720
- fileHandle = await openSourceFile(path95, import_node_fs.constants.O_RDONLY | import_node_fs.constants.O_NONBLOCK);
7723
+ fileHandle = await openSourceFile(path96, import_node_fs.constants.O_RDONLY | import_node_fs.constants.O_NONBLOCK);
7721
7724
  const fileStat = await fileHandle.stat();
7722
7725
  if (!fileStat.isFile()) return;
7723
- if (fileStat.size > MAX_CONTEXTLINES_FILE_SIZE) return void logger?.debug(`Skipping source context for oversized file ${path95}: ${fileStat.size} bytes exceeds ${MAX_CONTEXTLINES_FILE_SIZE}`);
7726
+ if (fileStat.size > MAX_CONTEXTLINES_FILE_SIZE) return void logger?.debug(`Skipping source context for oversized file ${path96}: ${fileStat.size} bytes exceeds ${MAX_CONTEXTLINES_FILE_SIZE}`);
7724
7727
  isValid = true;
7725
7728
  return fileHandle;
7726
7729
  } catch {
@@ -7730,8 +7733,8 @@ async function openRegularSourceFile(path95, openSourceFile, logger) {
7730
7733
  });
7731
7734
  }
7732
7735
  }
7733
- async function getContextLinesFromFile(path95, ranges, output, cacheKey, openSourceFile, logger) {
7734
- const fileHandle = await openRegularSourceFile(path95, openSourceFile, logger);
7736
+ async function getContextLinesFromFile(path96, ranges, output, cacheKey, openSourceFile, logger) {
7737
+ const fileHandle = await openRegularSourceFile(path96, openSourceFile, logger);
7735
7738
  if (void 0 === fileHandle) return void LRU_FILE_CONTENTS_FS_READ_FAILED.set(cacheKey, 1);
7736
7739
  const openedFileHandle = fileHandle;
7737
7740
  return new Promise((resolve12) => {
@@ -7833,22 +7836,22 @@ function clearLineContext(frame) {
7833
7836
  delete frame.context_line;
7834
7837
  delete frame.post_context;
7835
7838
  }
7836
- function shouldSkipContextLinesForFile(path95) {
7837
- return path95.startsWith("node:") || path95.endsWith(".min.js") || path95.endsWith(".min.cjs") || path95.endsWith(".min.mjs") || path95.startsWith("data:");
7839
+ function shouldSkipContextLinesForFile(path96) {
7840
+ return path96.startsWith("node:") || path96.endsWith(".min.js") || path96.endsWith(".min.cjs") || path96.endsWith(".min.mjs") || path96.startsWith("data:");
7838
7841
  }
7839
7842
  function shouldSkipContextLinesForFrame(frame) {
7840
7843
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
7841
7844
  if (void 0 !== frame.colno && frame.colno > MAX_CONTEXTLINES_COLNO) return true;
7842
7845
  return false;
7843
7846
  }
7844
- function makeSourceCacheKey(path95, basePath) {
7845
- if ((0, import_node_path.isAbsolute)(path95)) return JSON.stringify([
7847
+ function makeSourceCacheKey(path96, basePath) {
7848
+ if ((0, import_node_path.isAbsolute)(path96)) return JSON.stringify([
7846
7849
  null,
7847
- path95
7850
+ path96
7848
7851
  ]);
7849
7852
  return void 0 === basePath ? void 0 : JSON.stringify([
7850
7853
  basePath,
7851
- path95
7854
+ path96
7852
7855
  ]);
7853
7856
  }
7854
7857
  function rangeExistsInContentCache(cacheKey, range) {
@@ -10509,7 +10512,7 @@ function readAnonId() {
10509
10512
  }
10510
10513
  function superProperties() {
10511
10514
  return {
10512
- cliVersion: true ? "2.75.23" : "0.0.0-dev",
10515
+ cliVersion: true ? "2.75.26" : "0.0.0-dev",
10513
10516
  nodeVersion: process.version,
10514
10517
  platform: process.platform,
10515
10518
  arch: process.arch,
@@ -10751,7 +10754,7 @@ var http = __toESM(require("http"));
10751
10754
  // package.json
10752
10755
  var package_default = {
10753
10756
  name: "codeam-cli",
10754
- version: "2.75.23",
10757
+ version: "2.75.26",
10755
10758
  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.",
10756
10759
  type: "commonjs",
10757
10760
  main: "dist/index.js",
@@ -12081,7 +12084,7 @@ var CommandRelayService = class _CommandRelayService {
12081
12084
  // fresh + clear the "CLI update available" banner after a self-update
12082
12085
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
12083
12086
  // pair/reconnect). Older backends ignore the extra field.
12084
- ..."2.75.23" ? { ideVersion: "2.75.23" } : {}
12087
+ ..."2.75.26" ? { ideVersion: "2.75.26" } : {}
12085
12088
  };
12086
12089
  try {
12087
12090
  const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body);
@@ -13534,9 +13537,9 @@ function closeAllTerminals() {
13534
13537
  }
13535
13538
 
13536
13539
  // src/commands/start/handlers.ts
13537
- var fs50 = __toESM(require("fs"));
13540
+ var fs51 = __toESM(require("fs"));
13538
13541
  var os39 = __toESM(require("os"));
13539
- var path58 = __toESM(require("path"));
13542
+ var path59 = __toESM(require("path"));
13540
13543
  var import_crypto2 = require("crypto");
13541
13544
  var import_child_process25 = require("child_process");
13542
13545
 
@@ -17150,12 +17153,12 @@ function isAvailable() {
17150
17153
  }
17151
17154
  function augmentPath() {
17152
17155
  const dirs = probeInstallDirs();
17153
- const sep6 = path15.delimiter;
17156
+ const sep7 = path15.delimiter;
17154
17157
  const current2 = process.env.PATH ?? "";
17155
- const existing = new Set(current2.split(sep6).filter(Boolean));
17158
+ const existing = new Set(current2.split(sep7).filter(Boolean));
17156
17159
  const additions = dirs.filter((d3) => !existing.has(d3));
17157
17160
  if (additions.length === 0) return;
17158
- process.env.PATH = additions.join(sep6) + sep6 + current2;
17161
+ process.env.PATH = additions.join(sep7) + sep7 + current2;
17159
17162
  }
17160
17163
  function runInstaller() {
17161
17164
  const isWindows = process.platform === "win32";
@@ -19603,8 +19606,8 @@ function pickLine(obj) {
19603
19606
  function toHunk(raw, groupSeverity) {
19604
19607
  if (!raw || typeof raw !== "object") return null;
19605
19608
  const o = raw;
19606
- const path95 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
19607
- if (!path95) return null;
19609
+ const path96 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
19610
+ if (!path96) return null;
19608
19611
  const message = asString(
19609
19612
  pick(o, [
19610
19613
  "comment",
@@ -19621,7 +19624,7 @@ function toHunk(raw, groupSeverity) {
19621
19624
  const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
19622
19625
  const locObj = pick(o, ["location"]) ?? o;
19623
19626
  return {
19624
- path: path95.trim(),
19627
+ path: path96.trim(),
19625
19628
  line: pickLine(o) ?? pickLine(locObj),
19626
19629
  severity,
19627
19630
  message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
@@ -19704,10 +19707,10 @@ function parsePlain(stdout) {
19704
19707
  for (const line of stdout.split(/\r?\n/)) {
19705
19708
  const m = line.match(HUNK_LINE_RE);
19706
19709
  if (!m) continue;
19707
- const [, path95, lineNo, sevToken, message] = m;
19708
- if (!path95 || !lineNo || !message) continue;
19710
+ const [, path96, lineNo, sevToken, message] = m;
19711
+ if (!path96 || !lineNo || !message) continue;
19709
19712
  hunks.push({
19710
- path: path95.trim(),
19713
+ path: path96.trim(),
19711
19714
  line: Number(lineNo),
19712
19715
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
19713
19716
  message: message.trim().replace(/^[*-]\s+/, "")
@@ -23164,7 +23167,8 @@ async function readPreviewConfig(cwd) {
23164
23167
  async function writePreviewConfig(cwd, detection) {
23165
23168
  const filePath = configPath(cwd);
23166
23169
  await import_promises4.default.mkdir(import_path6.default.dirname(filePath), { recursive: true });
23167
- await import_promises4.default.writeFile(filePath, JSON.stringify(detection, null, 2) + "\n", "utf-8");
23170
+ const { candidates: _candidates, ...config } = detection;
23171
+ await import_promises4.default.writeFile(filePath, JSON.stringify(config, null, 2) + "\n", "utf-8");
23168
23172
  }
23169
23173
 
23170
23174
  // src/services/preview/dotenv.ts
@@ -23839,6 +23843,107 @@ function isJsInstallCommand(cmd, args2) {
23839
23843
  return verb === "install" || verb === "i" || verb === "ci";
23840
23844
  }
23841
23845
 
23846
+ // src/services/preview/script-candidates.ts
23847
+ var fs40 = __toESM(require("fs"));
23848
+ var path48 = __toESM(require("path"));
23849
+ var EXCLUDE_RE = /(^|:)(deploy|publish|release|build|test|e2e|lint|format|typecheck|type-check|clean|prebuild|postinstall|preinstall|prepare|install|migrate|seed|db|prisma|codegen|storybook-build)(:|$)/i;
23850
+ var EXCLUDE_BODY_RE = /\b(run:android|run:ios|gradlew|fastlane|xcodebuild|eas build|eas submit)\b/i;
23851
+ var MAX_APPS = 40;
23852
+ var MAX_CANDIDATES = 120;
23853
+ function frameworkFor(pkg, body) {
23854
+ const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
23855
+ const has = (d3) => d3 in deps || new RegExp(`\\b${d3}\\b`).test(body);
23856
+ if (has("expo")) return { framework: "Expo", port: 8081, ready_pattern: "Waiting on http|Metro waiting|Logs for your project" };
23857
+ if (has("next")) return { framework: "Next.js", port: 3e3, ready_pattern: "Ready in|Local:.*http" };
23858
+ if (has("vite")) return { framework: "Vite", port: 5173, ready_pattern: "Local:.*http" };
23859
+ if (has("@angular/cli") || /\bng serve\b/.test(body)) return { framework: "Angular", port: 4200, ready_pattern: "Local:.*http|compiled successfully" };
23860
+ if (has("react-scripts")) return { framework: "Create React App", port: 3e3, ready_pattern: "Compiled|Local:.*http" };
23861
+ if (has("nx") || /\bnx\b/.test(body)) return { framework: "Nx", port: 4200, ready_pattern: "Local:.*http|ready|listening" };
23862
+ return { framework: "Node", port: 3e3, ready_pattern: "Local:.*http|ready|listening|started" };
23863
+ }
23864
+ function readPkg(file) {
23865
+ try {
23866
+ return JSON.parse(fs40.readFileSync(file, "utf8"));
23867
+ } catch {
23868
+ return null;
23869
+ }
23870
+ }
23871
+ function expandGlob(root, pattern) {
23872
+ const clean = pattern.replace(/\/+$/, "");
23873
+ if (!clean.endsWith("/*")) return [clean];
23874
+ const base = clean.slice(0, -2);
23875
+ try {
23876
+ return fs40.readdirSync(path48.join(root, base), { withFileTypes: true }).filter((d3) => d3.isDirectory() && !d3.name.startsWith(".") && d3.name !== "node_modules").map((d3) => path48.join(base, d3.name));
23877
+ } catch {
23878
+ return [];
23879
+ }
23880
+ }
23881
+ function workspaceDirs(root, rootPkg) {
23882
+ const ws = rootPkg?.workspaces;
23883
+ const patterns = Array.isArray(ws) ? ws : ws?.packages ?? [];
23884
+ try {
23885
+ const pnpm = fs40.readFileSync(path48.join(root, "pnpm-workspace.yaml"), "utf8");
23886
+ for (const m of pnpm.matchAll(/^\s*-\s*['"]?([^'"\n]+)['"]?\s*$/gm)) patterns.push(m[1]);
23887
+ } catch {
23888
+ }
23889
+ if (patterns.length === 0) patterns.push("apps/*", "packages/*");
23890
+ const dirs = /* @__PURE__ */ new Set();
23891
+ for (const p2 of patterns) for (const d3 of expandGlob(root, p2)) dirs.add(d3);
23892
+ return [...dirs].slice(0, MAX_APPS);
23893
+ }
23894
+ function listScriptCandidates(root) {
23895
+ const out2 = [];
23896
+ const rootPkg = readPkg(path48.join(root, "package.json"));
23897
+ const add = (pkg, appDir) => {
23898
+ for (const [script, body] of Object.entries(pkg.scripts ?? {})) {
23899
+ if (out2.length >= MAX_CANDIDATES) return;
23900
+ if (EXCLUDE_RE.test(script) || EXCLUDE_BODY_RE.test(body)) continue;
23901
+ const fw = frameworkFor(pkg, body);
23902
+ out2.push({
23903
+ app: pkg.name ?? (appDir === "." ? path48.basename(root) : appDir),
23904
+ appDir,
23905
+ script,
23906
+ body,
23907
+ framework: fw.framework,
23908
+ command: "npm",
23909
+ args: appDir === "." ? ["run", script] : ["--prefix", appDir, "run", script],
23910
+ port: fw.port,
23911
+ ready_pattern: fw.ready_pattern
23912
+ });
23913
+ }
23914
+ };
23915
+ if (rootPkg) add(rootPkg, ".");
23916
+ for (const dir of workspaceDirs(root, rootPkg)) {
23917
+ const pkg = readPkg(path48.join(root, dir, "package.json"));
23918
+ if (pkg) add(pkg, dir.split(path48.sep).join("/"));
23919
+ }
23920
+ return out2;
23921
+ }
23922
+
23923
+ // src/services/preview/prewarm-deps.ts
23924
+ var inFlight = null;
23925
+ var PREWARM_INSTALL_TIMEOUT_MS = 5 * 6e4;
23926
+ function prewarmNodeDeps(cwd) {
23927
+ if (inFlight) return inFlight;
23928
+ const missing = detectMissingNodeDeps(cwd);
23929
+ if (!missing || missing.cmd !== "npm") return Promise.resolve();
23930
+ log.info("preview", `prewarm: installing deps (${missing.cmd} ${missing.args.join(" ")})`);
23931
+ const started = Date.now();
23932
+ inFlight = runSetupCommand(missing.cmd, missing.args, cwd, void 0, {
23933
+ timeoutMs: PREWARM_INSTALL_TIMEOUT_MS
23934
+ }).then((r) => {
23935
+ log.info("preview", `prewarm: deps ${r.status} after ${Date.now() - started}ms`);
23936
+ }).catch((err) => {
23937
+ log.info("preview", `prewarm: deps install threw (${String(err)})`);
23938
+ }).finally(() => {
23939
+ inFlight = null;
23940
+ });
23941
+ return inFlight;
23942
+ }
23943
+ function awaitPrewarmInstall() {
23944
+ return inFlight ?? Promise.resolve();
23945
+ }
23946
+
23842
23947
  // src/services/preview/tunnel-bringup.ts
23843
23948
  var TUNNEL_REGISTERED_RE = /Registered tunnel connection/i;
23844
23949
  async function awaitTunnelRegistered(candidate, hostname3, deadlineMs) {
@@ -23975,19 +24080,19 @@ function activePreviewSessionIds() {
23975
24080
 
23976
24081
  // src/services/preview/start-orchestrator.ts
23977
24082
  var import_child_process20 = require("child_process");
23978
- var fs42 = __toESM(require("fs"));
23979
- var path50 = __toESM(require("path"));
24083
+ var fs43 = __toESM(require("fs"));
24084
+ var path51 = __toESM(require("path"));
23980
24085
  var import_which2 = __toESM(require("which"));
23981
24086
 
23982
24087
  // src/services/project-env/index.ts
23983
24088
  var import_fs6 = require("fs");
23984
- var path49 = __toESM(require("path"));
24089
+ var path50 = __toESM(require("path"));
23985
24090
 
23986
24091
  // src/beads/project-key.ts
23987
24092
  var import_child_process19 = require("child_process");
23988
24093
  var crypto2 = __toESM(require("crypto"));
23989
- var fs40 = __toESM(require("fs"));
23990
- var path48 = __toESM(require("path"));
24094
+ var fs41 = __toESM(require("fs"));
24095
+ var path49 = __toESM(require("path"));
23991
24096
  function normalizeOrigin(raw) {
23992
24097
  const trimmed = raw.trim();
23993
24098
  if (!trimmed) return null;
@@ -24013,17 +24118,17 @@ function normalizeOrigin(raw) {
24013
24118
  return `${host2}/${pathPart}`;
24014
24119
  }
24015
24120
  function findRepoRoot(cwd) {
24016
- let dir = path48.resolve(cwd);
24121
+ let dir = path49.resolve(cwd);
24017
24122
  const seen2 = /* @__PURE__ */ new Set();
24018
24123
  for (let i = 0; i < 256; i++) {
24019
24124
  if (seen2.has(dir)) return null;
24020
24125
  seen2.add(dir);
24021
24126
  try {
24022
- const stat3 = fs40.statSync(path48.join(dir, ".git"), { throwIfNoEntry: false });
24127
+ const stat3 = fs41.statSync(path49.join(dir, ".git"), { throwIfNoEntry: false });
24023
24128
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
24024
24129
  } catch {
24025
24130
  }
24026
- const parent = path48.dirname(dir);
24131
+ const parent = path49.dirname(dir);
24027
24132
  if (parent === dir) return null;
24028
24133
  dir = parent;
24029
24134
  }
@@ -24034,7 +24139,7 @@ var _execSeam3 = {
24034
24139
  const out2 = (0, import_child_process19.execFileSync)(file, args2, opts);
24035
24140
  return typeof out2 === "string" ? out2 : out2.toString("utf8");
24036
24141
  },
24037
- realpath: (p2) => fs40.realpathSync(p2)
24142
+ realpath: (p2) => fs41.realpathSync(p2)
24038
24143
  };
24039
24144
  function readOrigin(cwd) {
24040
24145
  try {
@@ -24063,7 +24168,7 @@ function deriveProjectIdentity(cwd = process.cwd()) {
24063
24168
  } catch {
24064
24169
  }
24065
24170
  const hash = crypto2.createHash("sha256").update(real).digest("hex");
24066
- return { projectKey: `path:${hash}`, projectLabel: path48.basename(real) || "project" };
24171
+ return { projectKey: `path:${hash}`, projectLabel: path49.basename(real) || "project" };
24067
24172
  }
24068
24173
 
24069
24174
  // src/services/project-env/index.ts
@@ -24076,7 +24181,7 @@ async function readIfExists(p2) {
24076
24181
  }
24077
24182
  async function syncProjectEnvUp(cwd, ctx) {
24078
24183
  if (!ctx.pluginAuthToken) return;
24079
- const content = await readIfExists(path49.join(cwd, ".env"));
24184
+ const content = await readIfExists(path50.join(cwd, ".env"));
24080
24185
  if (content == null) return;
24081
24186
  try {
24082
24187
  const { projectKey, projectLabel } = deriveProjectIdentity(cwd);
@@ -24098,7 +24203,7 @@ async function syncProjectEnvUp(cwd, ctx) {
24098
24203
  }
24099
24204
  async function restoreProjectEnvIfMissing(cwd, ctx) {
24100
24205
  if (!ctx.pluginAuthToken) return false;
24101
- const envPath = path49.join(cwd, ".env");
24206
+ const envPath = path50.join(cwd, ".env");
24102
24207
  if (await readIfExists(envPath) != null) return false;
24103
24208
  try {
24104
24209
  const { projectKey, projectLabel } = deriveProjectIdentity(cwd);
@@ -24109,7 +24214,7 @@ async function restoreProjectEnvIfMissing(cwd, ctx) {
24109
24214
  projectKey
24110
24215
  });
24111
24216
  if (!stored) return false;
24112
- const tmp = path49.join(cwd, ".env.codeam-restore.tmp");
24217
+ const tmp = path50.join(cwd, ".env.codeam-restore.tmp");
24113
24218
  await import_fs6.promises.writeFile(tmp, stored.content, { encoding: "utf8", mode: 384 });
24114
24219
  await import_fs6.promises.rename(tmp, envPath);
24115
24220
  log.info("project-env", `restored .env (${stored.keyCount} vars) for ${projectLabel}`);
@@ -24526,6 +24631,145 @@ function inspectorClientSource(opts) {
24526
24631
  redrawMarks();
24527
24632
  }
24528
24633
 
24634
+ /**
24635
+ * Las marcas del AGENTE \u2014 la herramienta highlight_element.
24636
+ *
24637
+ * Van aparte de las del usuario a proposito: no se numeran, no se pueden
24638
+ * borrar desde el composer y no dependen de que el modo inspector este
24639
+ * encendido. Son el agente SE\xD1ALANDO algo, y el usuario las ve aunque no
24640
+ * haya tocado nada: un cursor que viaja hasta el elemento, lo centra en
24641
+ * pantalla y deja una caja con su etiqueta.
24642
+ *
24643
+ * Mismo anclaje que las marcas fijadas (coordenadas de documento), asi que
24644
+ * acompa\xF1an al scroll. Un selector que no encuentra nada no pinta nada: el
24645
+ * agente ya sabe por la herramienta que puede fallar.
24646
+ */
24647
+ var AGENT = '#22d3ee';
24648
+ var agentMarks = [];
24649
+ var agentHost = null;
24650
+ var agentCursor = null;
24651
+ var agentStyle = null;
24652
+ var agentListening = false;
24653
+
24654
+ function ensureAgentStyle() {
24655
+ if (agentStyle && agentStyle.parentNode) return;
24656
+ agentStyle = document.createElement('style');
24657
+ agentStyle.setAttribute('data-codeam', 'agent-style');
24658
+ agentStyle.textContent =
24659
+ '@keyframes codeam-agent-pulse{0%{box-shadow:0 0 0 0 rgba(34,211,238,.55)}' +
24660
+ '70%{box-shadow:0 0 0 10px rgba(34,211,238,0)}100%{box-shadow:0 0 0 0 rgba(34,211,238,0)}}' +
24661
+ '@keyframes codeam-agent-in{from{opacity:0;transform:scale(1.06)}to{opacity:1;transform:scale(1)}}';
24662
+ (document.head || document.documentElement).appendChild(agentStyle);
24663
+ }
24664
+
24665
+ function ensureAgentCursor() {
24666
+ if (agentCursor && agentCursor.parentNode) return agentCursor;
24667
+ agentCursor = document.createElement('div');
24668
+ agentCursor.setAttribute('data-codeam', 'agent-cursor');
24669
+ agentCursor.style.cssText = [
24670
+ 'position:fixed', 'pointer-events:none', 'z-index:2147483647',
24671
+ 'left:' + Math.round(window.innerWidth / 2) + 'px', 'top:' + Math.round(window.innerHeight - 40) + 'px',
24672
+ 'transition:left .6s cubic-bezier(.22,1,.36,1),top .6s cubic-bezier(.22,1,.36,1),opacity .3s',
24673
+ 'opacity:0'
24674
+ ].join(';');
24675
+ agentCursor.innerHTML =
24676
+ '<svg width="22" height="22" viewBox="0 0 24 24" style="display:block;filter:drop-shadow(0 1px 2px rgba(0,0,0,.5))">' +
24677
+ '<path d="M4 2l15 8.5-6.6 1.6L9 18.5z" fill="' + AGENT + '" stroke="#000" stroke-width="1.2"/></svg>' +
24678
+ '<div style="margin:2px 0 0 14px;background:' + AGENT + ';color:#000;font:700 10px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;' +
24679
+ 'padding:1px 6px;border-radius:8px;white-space:nowrap">Agent</div>';
24680
+ document.body.appendChild(agentCursor);
24681
+ return agentCursor;
24682
+ }
24683
+
24684
+ function redrawAgentMarks() {
24685
+ if (agentMarks.length === 0) {
24686
+ if (agentHost && agentHost.parentNode) agentHost.parentNode.removeChild(agentHost);
24687
+ agentHost = null;
24688
+ return;
24689
+ }
24690
+ if (!agentHost || !agentHost.parentNode) {
24691
+ agentHost = document.createElement('div');
24692
+ agentHost.setAttribute('data-codeam', 'agent-marks');
24693
+ agentHost.style.cssText = 'position:absolute;left:0;top:0;width:0;height:0;z-index:2147483646';
24694
+ document.body.appendChild(agentHost);
24695
+ }
24696
+ agentHost.innerHTML = '';
24697
+ var sx = window.scrollX || window.pageXOffset || 0;
24698
+ var sy = window.scrollY || window.pageYOffset || 0;
24699
+ for (var i = 0; i < agentMarks.length; i++) {
24700
+ var m = agentMarks[i];
24701
+ if (!m.el.isConnected) continue;
24702
+ var r = m.el.getBoundingClientRect();
24703
+ var box = document.createElement('div');
24704
+ box.setAttribute('data-codeam', 'agent-mark');
24705
+ box.style.cssText = [
24706
+ 'position:absolute', 'pointer-events:none', 'box-sizing:border-box',
24707
+ 'border:2px solid ' + AGENT, 'background:rgba(34,211,238,0.10)', 'border-radius:4px',
24708
+ 'left:' + (r.left + sx - 3) + 'px', 'top:' + (r.top + sy - 3) + 'px',
24709
+ 'width:' + (r.width + 6) + 'px', 'height:' + (r.height + 6) + 'px',
24710
+ 'animation:codeam-agent-in .25s ease-out,codeam-agent-pulse 1.6s ease-out 3'
24711
+ ].join(';');
24712
+ if (m.label) {
24713
+ var tag = document.createElement('div');
24714
+ tag.setAttribute('data-codeam', 'agent-mark-label');
24715
+ tag.style.cssText = [
24716
+ 'position:absolute', 'left:-2px', (r.top >= 22 ? 'top:-22px' : 'bottom:-22px'),
24717
+ 'background:' + AGENT, 'color:#000', 'font:700 11px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace',
24718
+ 'padding:0 6px', 'border-radius:3px', 'white-space:nowrap', 'max-width:260px',
24719
+ 'overflow:hidden', 'text-overflow:ellipsis'
24720
+ ].join(';');
24721
+ tag.textContent = m.label;
24722
+ box.appendChild(tag);
24723
+ }
24724
+ agentHost.appendChild(box);
24725
+ }
24726
+ }
24727
+
24728
+ function listenAgentLayout() {
24729
+ if (agentListening) return;
24730
+ agentListening = true;
24731
+ window.addEventListener('scroll', redrawAgentMarks, true);
24732
+ window.addEventListener('resize', redrawAgentMarks);
24733
+ }
24734
+
24735
+ function agentHighlight(selector, labelText) {
24736
+ var el = null;
24737
+ try { el = document.querySelector(String(selector)); } catch (e) { el = null; }
24738
+ if (!el || !el.getBoundingClientRect) return false;
24739
+ ensureAgentStyle();
24740
+ listenAgentLayout();
24741
+ try { el.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'smooth' }); } catch (e) { /* viejo */ }
24742
+ var cursor = ensureAgentCursor();
24743
+ // Tras el scroll suave: el cursor viaja al centro del elemento y, al
24744
+ // llegar, aparece la caja. El orden es lo que se lee como \xABel agente
24745
+ // lo esta se\xF1alando\xBB y no como un recuadro que salta.
24746
+ setTimeout(function () {
24747
+ var r = el.getBoundingClientRect();
24748
+ cursor.style.opacity = '1';
24749
+ cursor.style.left = Math.round(r.left + Math.min(r.width / 2, 40)) + 'px';
24750
+ cursor.style.top = Math.round(r.top + Math.min(r.height / 2, 24)) + 'px';
24751
+ setTimeout(function () {
24752
+ agentMarks.push({ el: el, label: labelText ? String(labelText).slice(0, 80) : '' });
24753
+ redrawAgentMarks();
24754
+ }, 620);
24755
+ }, 380);
24756
+ return true;
24757
+ }
24758
+
24759
+ function agentClear() {
24760
+ agentMarks = [];
24761
+ redrawAgentMarks();
24762
+ if (agentCursor && agentCursor.parentNode) agentCursor.parentNode.removeChild(agentCursor);
24763
+ agentCursor = null;
24764
+ if (agentStyle && agentStyle.parentNode) agentStyle.parentNode.removeChild(agentStyle);
24765
+ agentStyle = null;
24766
+ if (agentListening) {
24767
+ window.removeEventListener('scroll', redrawAgentMarks, true);
24768
+ window.removeEventListener('resize', redrawAgentMarks);
24769
+ agentListening = false;
24770
+ }
24771
+ }
24772
+
24529
24773
  function enable(origin) {
24530
24774
  if (enabled) return;
24531
24775
  enabled = true;
@@ -24559,6 +24803,8 @@ function inspectorClientSource(opts) {
24559
24803
  if (data.type === 'enable') enable(e.origin);
24560
24804
  else if (data.type === 'disable') disable();
24561
24805
  else if (data.type === 'marks' && data.ids) syncMarks(data.ids);
24806
+ else if (data.type === 'agent-highlight' && data.selector) agentHighlight(data.selector, data.label);
24807
+ else if (data.type === 'agent-clear') agentClear();
24562
24808
  });
24563
24809
 
24564
24810
  /**
@@ -24577,6 +24823,11 @@ function inspectorClientSource(opts) {
24577
24823
  window.__codeamInspector = {
24578
24824
  enable: function () { enable('react-native'); },
24579
24825
  disable: disable,
24826
+ // La app movil ya llamaba \`marks\` al borrar un chip y no existia:
24827
+ // la marca se quedaba pintada en la pagina.
24828
+ marks: function (ids) { if (ids && ids.length !== undefined) syncMarks(ids); },
24829
+ highlight: function (selector, text) { return agentHighlight(selector, text); },
24830
+ clear: agentClear,
24580
24831
  };
24581
24832
  }
24582
24833
  } catch (e) {
@@ -24630,6 +24881,12 @@ var TUNNEL_REGISTER_DEADLINE_MS = 45e3;
24630
24881
  function compileReadyPattern(pattern) {
24631
24882
  return new RegExp(pattern, "i");
24632
24883
  }
24884
+ var DEV_SERVER_READY_TIMEOUT_MS = 12e4;
24885
+ var MONOREPO_READY_TIMEOUT_MS = 36e4;
24886
+ function devServerReadyTimeoutMs(detection) {
24887
+ const text = [detection.framework, detection.command ?? "", ...detection.args ?? []].join(" ");
24888
+ return /\b(nx|turbo|turborepo|lerna)\b/i.test(text) ? MONOREPO_READY_TIMEOUT_MS : DEV_SERVER_READY_TIMEOUT_MS;
24889
+ }
24633
24890
  async function waitForDevServerReady(devServer, readyRe, opts = {
24634
24891
  timeoutMs: 12e4
24635
24892
  }) {
@@ -24689,8 +24946,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
24689
24946
  if (args2.length === 0) return detection;
24690
24947
  const binName = args2[0];
24691
24948
  if (binName.startsWith("-")) return detection;
24692
- const binPath = path50.join(cwd, "node_modules", ".bin", binName);
24693
- if (!fs42.existsSync(binPath)) return detection;
24949
+ const binPath = path51.join(cwd, "node_modules", ".bin", binName);
24950
+ if (!fs43.existsSync(binPath)) return detection;
24694
24951
  return {
24695
24952
  ...detection,
24696
24953
  command: binPath,
@@ -24784,6 +25041,7 @@ async function provisionDeps(ctx) {
24784
25041
  pluginAuthToken: ctx.projectEnvAuth.pluginAuthToken
24785
25042
  });
24786
25043
  }
25044
+ await awaitPrewarmInstall();
24787
25045
  const missingDeps = detectMissingNodeDeps(cwd);
24788
25046
  let preflightRan = false;
24789
25047
  if (missingDeps) {
@@ -24963,7 +25221,7 @@ async function startDevServer(ctx, extraEnv = {}) {
24963
25221
  const isNextJs = /next/i.test(detection.framework);
24964
25222
  const portProbe = isExpo ? () => waitForExpoManifest(detection.port, { timeoutMs: 1e3, intervalMs: 250 }) : isNextJs ? () => waitForPortListening(detection.port, { timeoutMs: 1e3, intervalMs: 250 }) : void 0;
24965
25223
  const outcome = await waitForDevServerReady(devServer, readyRe, {
24966
- timeoutMs: 12e4,
25224
+ timeoutMs: devServerReadyTimeoutMs(detection),
24967
25225
  onChunk: (s) => {
24968
25226
  outputTail = (outputTail + s).slice(-16e3);
24969
25227
  },
@@ -25089,9 +25347,9 @@ async function bringUpPublicUrl(ctx, tunnelPort) {
25089
25347
 
25090
25348
  // src/beads/bd-adapter.ts
25091
25349
  var import_child_process21 = require("child_process");
25092
- var fs43 = __toESM(require("fs"));
25350
+ var fs44 = __toESM(require("fs"));
25093
25351
  var os31 = __toESM(require("os"));
25094
- var path51 = __toESM(require("path"));
25352
+ var path52 = __toESM(require("path"));
25095
25353
  var BD_PACKAGE = "@beads/bd";
25096
25354
  function resolveBundledBdBinary() {
25097
25355
  return _resolveSeam.resolveBundled();
@@ -25103,11 +25361,11 @@ function _defaultResolveBundled() {
25103
25361
  } catch {
25104
25362
  return null;
25105
25363
  }
25106
- const binDir = path51.join(path51.dirname(pkgJsonPath), "bin");
25364
+ const binDir = path52.join(path52.dirname(pkgJsonPath), "bin");
25107
25365
  const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
25108
- const binaryPath = path51.join(binDir, binaryName);
25366
+ const binaryPath = path52.join(binDir, binaryName);
25109
25367
  try {
25110
- fs43.accessSync(binaryPath, fs43.constants.F_OK);
25368
+ fs44.accessSync(binaryPath, fs44.constants.F_OK);
25111
25369
  return binaryPath;
25112
25370
  } catch {
25113
25371
  return null;
@@ -25117,13 +25375,13 @@ function resolveBdOnPath() {
25117
25375
  return _resolveSeam.resolveOnPath();
25118
25376
  }
25119
25377
  function _defaultResolveOnPath() {
25120
- const dirs = (process.env.PATH ?? "").split(path51.delimiter).filter(Boolean);
25378
+ const dirs = (process.env.PATH ?? "").split(path52.delimiter).filter(Boolean);
25121
25379
  const candidates = process.platform === "win32" ? ["bd.exe", "bd.cmd", "bd"] : ["bd"];
25122
25380
  for (const dir of dirs) {
25123
25381
  for (const candidate of candidates) {
25124
- const full = path51.join(dir, candidate);
25382
+ const full = path52.join(dir, candidate);
25125
25383
  try {
25126
- fs43.accessSync(full, fs43.constants.F_OK);
25384
+ fs44.accessSync(full, fs44.constants.F_OK);
25127
25385
  return full;
25128
25386
  } catch {
25129
25387
  }
@@ -25300,9 +25558,9 @@ function coerceIssue(row, projectKey) {
25300
25558
 
25301
25559
  // src/beads/provisioner.ts
25302
25560
  var import_child_process24 = require("child_process");
25303
- var fs45 = __toESM(require("fs"));
25561
+ var fs46 = __toESM(require("fs"));
25304
25562
  var os33 = __toESM(require("os"));
25305
- var path53 = __toESM(require("path"));
25563
+ var path54 = __toESM(require("path"));
25306
25564
 
25307
25565
  // src/beads/install-bd.ts
25308
25566
  var import_child_process22 = require("child_process");
@@ -25367,9 +25625,9 @@ async function installBd(platform3 = process.platform) {
25367
25625
 
25368
25626
  // src/beads/install-dolt.ts
25369
25627
  var import_child_process23 = require("child_process");
25370
- var fs44 = __toESM(require("fs"));
25628
+ var fs45 = __toESM(require("fs"));
25371
25629
  var os32 = __toESM(require("os"));
25372
- var path52 = __toESM(require("path"));
25630
+ var path53 = __toESM(require("path"));
25373
25631
  var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
25374
25632
  var DOLT_MSI_URL = "https://github.com/dolthub/dolt/releases/latest/download/dolt-windows-amd64.msi";
25375
25633
  function resolveDoltInstallStrategy(platform3) {
@@ -25465,7 +25723,7 @@ var _doltPathSeam = {
25465
25723
  },
25466
25724
  exists: (p2) => {
25467
25725
  try {
25468
- fs44.accessSync(p2, fs44.constants.F_OK);
25726
+ fs45.accessSync(p2, fs45.constants.F_OK);
25469
25727
  return true;
25470
25728
  } catch {
25471
25729
  return false;
@@ -25476,7 +25734,7 @@ function doltBinaryNames(platform3) {
25476
25734
  return platform3 === "win32" ? ["dolt.exe", "dolt.cmd", "dolt"] : ["dolt"];
25477
25735
  }
25478
25736
  function knownDoltDirs(platform3) {
25479
- const P3 = platform3 === "win32" ? path52.win32 : path52.posix;
25737
+ const P3 = platform3 === "win32" ? path53.win32 : path53.posix;
25480
25738
  const home = _doltPathSeam.homedir();
25481
25739
  if (platform3 === "win32") {
25482
25740
  return [
@@ -25492,7 +25750,7 @@ function knownDoltDirs(platform3) {
25492
25750
  ].filter(Boolean);
25493
25751
  }
25494
25752
  function ensureDoltResolvable(platform3 = process.platform) {
25495
- const P3 = platform3 === "win32" ? path52.win32 : path52.posix;
25753
+ const P3 = platform3 === "win32" ? path53.win32 : path53.posix;
25496
25754
  const delim = platform3 === "win32" ? ";" : ":";
25497
25755
  const names = doltBinaryNames(platform3);
25498
25756
  const pathDirs = _doltPathSeam.getPath().split(delim).filter(Boolean);
@@ -25689,14 +25947,14 @@ var _linkSeam = {
25689
25947
  homedir: () => os33.homedir(),
25690
25948
  isWritableDir: (dir) => {
25691
25949
  try {
25692
- fs45.accessSync(dir, fs45.constants.W_OK);
25950
+ fs46.accessSync(dir, fs46.constants.W_OK);
25693
25951
  return true;
25694
25952
  } catch {
25695
25953
  return false;
25696
25954
  }
25697
25955
  },
25698
25956
  ensureDir: (dir) => {
25699
- fs45.mkdirSync(dir, { recursive: true });
25957
+ fs46.mkdirSync(dir, { recursive: true });
25700
25958
  },
25701
25959
  /**
25702
25960
  * A directory to symlink `bd` into so the AGENT's shell + Claude Code's
@@ -25717,9 +25975,9 @@ var _linkSeam = {
25717
25975
  * which `linkBdOntoPath` creates if missing.
25718
25976
  */
25719
25977
  cliBinDir: () => {
25720
- const pathDirs = (process.env.PATH ?? "").split(path53.delimiter).filter(Boolean);
25978
+ const pathDirs = (process.env.PATH ?? "").split(path54.delimiter).filter(Boolean);
25721
25979
  const home = _linkSeam.homedir();
25722
- const localBin = home ? path53.join(home, ".local", "bin") : null;
25980
+ const localBin = home ? path54.join(home, ".local", "bin") : null;
25723
25981
  if (localBin) {
25724
25982
  try {
25725
25983
  _linkSeam.ensureDir(localBin);
@@ -25729,16 +25987,16 @@ var _linkSeam = {
25729
25987
  const candidates = [];
25730
25988
  if (localBin) candidates.push(localBin);
25731
25989
  try {
25732
- candidates.push(path53.dirname(process.execPath));
25990
+ candidates.push(path54.dirname(process.execPath));
25733
25991
  } catch {
25734
25992
  }
25735
25993
  candidates.push("/usr/local/bin");
25736
25994
  const entry = process.argv[1];
25737
25995
  if (entry) {
25738
25996
  try {
25739
- candidates.push(path53.dirname(fs45.realpathSync(entry)));
25997
+ candidates.push(path54.dirname(fs46.realpathSync(entry)));
25740
25998
  } catch {
25741
- candidates.push(path53.dirname(entry));
25999
+ candidates.push(path54.dirname(entry));
25742
26000
  }
25743
26001
  }
25744
26002
  const onPathWritable = candidates.find(
@@ -25750,20 +26008,20 @@ var _linkSeam = {
25750
26008
  /** Current symlink target at `linkPath`, or null when absent / not a link. */
25751
26009
  readlink: (linkPath) => {
25752
26010
  try {
25753
- return fs45.readlinkSync(linkPath);
26011
+ return fs46.readlinkSync(linkPath);
25754
26012
  } catch {
25755
26013
  return null;
25756
26014
  }
25757
26015
  },
25758
- unlink: (linkPath) => fs45.unlinkSync(linkPath),
25759
- symlink: (target, linkPath) => fs45.symlinkSync(target, linkPath)
26016
+ unlink: (linkPath) => fs46.unlinkSync(linkPath),
26017
+ symlink: (target, linkPath) => fs46.symlinkSync(target, linkPath)
25760
26018
  };
25761
26019
  function linkBdOntoPath(binaryPath) {
25762
26020
  if (_linkSeam.platform() === "win32") return;
25763
26021
  const binDir = _linkSeam.cliBinDir();
25764
26022
  if (!binDir) return;
25765
26023
  _linkSeam.ensureDir(binDir);
25766
- const linkPath = path53.join(binDir, "bd");
26024
+ const linkPath = path54.join(binDir, "bd");
25767
26025
  if (linkPath === binaryPath) return;
25768
26026
  const current2 = _linkSeam.readlink(linkPath);
25769
26027
  if (current2 === binaryPath) return;
@@ -25968,7 +26226,7 @@ function dedupeRecipes(agents) {
25968
26226
 
25969
26227
  // src/beads/watcher.ts
25970
26228
  var crypto4 = __toESM(require("crypto"));
25971
- var path54 = __toESM(require("path"));
26229
+ var path55 = __toESM(require("path"));
25972
26230
  var API_BASE5 = resolveApiBaseUrl();
25973
26231
  var DEBOUNCE_MS2 = 400;
25974
26232
  var ZERO_SUMMARY = {
@@ -25992,7 +26250,7 @@ var BeadsWatcher = class {
25992
26250
  constructor(opts) {
25993
26251
  this.opts = opts;
25994
26252
  this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
25995
- this.feedPath = opts.feedPath ?? path54.join(opts.cwd ?? process.cwd(), ".beads", "last-touched");
26253
+ this.feedPath = opts.feedPath ?? path55.join(opts.cwd ?? process.cwd(), ".beads", "last-touched");
25996
26254
  this.apiBase = opts.apiBaseUrl ?? API_BASE5;
25997
26255
  }
25998
26256
  opts;
@@ -26409,9 +26667,9 @@ async function configureBeads(action, ctx, deps) {
26409
26667
  return { enabled: false, running: false };
26410
26668
  }
26411
26669
  const p3 = await deps.probe();
26412
- const running2 = p3.serverUp && p3.bdAvailable;
26413
- deps.emit({ type: "beads_status", state: running2 ? "enabled" : "disabled", running: running2, ...p3 });
26414
- return { enabled: running2, running: running2, ...p3 };
26670
+ const running3 = p3.serverUp && p3.bdAvailable;
26671
+ deps.emit({ type: "beads_status", state: running3 ? "enabled" : "disabled", running: running3, ...p3 });
26672
+ return { enabled: running3, running: running3, ...p3 };
26415
26673
  }
26416
26674
  if (action === "disable") {
26417
26675
  deps.persist({ enabled: false });
@@ -26428,9 +26686,9 @@ async function configureBeads(action, ctx, deps) {
26428
26686
  return { enabled: false, ...p2 };
26429
26687
  }
26430
26688
  await deps.startWatcher().catch(() => void 0);
26431
- const running = true;
26432
- deps.emit({ type: "beads_status", state: "enabled", running, ...p2 });
26433
- return { enabled: true, running, ...p2 };
26689
+ const running2 = true;
26690
+ deps.emit({ type: "beads_status", state: "enabled", running: running2, ...p2 });
26691
+ return { enabled: true, running: running2, ...p2 };
26434
26692
  }
26435
26693
 
26436
26694
  // src/skills/configure.ts
@@ -26567,8 +26825,8 @@ function cleanupAttachmentTempFiles() {
26567
26825
  function saveFilesTemp(files) {
26568
26826
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
26569
26827
  const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
26570
- const tmpPath = path58.join(os39.tmpdir(), `codeam-${(0, import_crypto2.randomUUID)()}-${safeName}`);
26571
- fs50.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
26828
+ const tmpPath = path59.join(os39.tmpdir(), `codeam-${(0, import_crypto2.randomUUID)()}-${safeName}`);
26829
+ fs51.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
26572
26830
  pendingAttachmentFiles.add(tmpPath);
26573
26831
  return tmpPath;
26574
26832
  });
@@ -26803,10 +27061,10 @@ var listFiles = async (ctx, cmd, parsed) => {
26803
27061
  await ctx.relay.sendResult(cmd.id, "completed", result);
26804
27062
  };
26805
27063
  var envReadH = async (ctx, cmd) => {
26806
- const envPath = path58.join(process.cwd(), ".env");
27064
+ const envPath = path59.join(process.cwd(), ".env");
26807
27065
  await restoreProjectEnvIfMissing(process.cwd(), ctx);
26808
27066
  try {
26809
- const raw = await fs50.promises.readFile(envPath, "utf8");
27067
+ const raw = await fs51.promises.readFile(envPath, "utf8");
26810
27068
  await ctx.relay.sendResult(cmd.id, "completed", {
26811
27069
  exists: true,
26812
27070
  vars: parseDotenv(raw)
@@ -26835,7 +27093,7 @@ var envParseH = async (ctx, cmd, parsed) => {
26835
27093
  const existing = /* @__PURE__ */ new Map();
26836
27094
  if (!replace) {
26837
27095
  try {
26838
- const raw = await fs50.promises.readFile(path58.join(process.cwd(), ".env"), "utf8");
27096
+ const raw = await fs51.promises.readFile(path59.join(process.cwd(), ".env"), "utf8");
26839
27097
  for (const v of parseDotenv(raw)) existing.set(v.key, v.value);
26840
27098
  } catch {
26841
27099
  }
@@ -26875,15 +27133,15 @@ var envWriteH = async (ctx, cmd, parsed) => {
26875
27133
  }
26876
27134
  seen2.add(v.key);
26877
27135
  }
26878
- const envPath = path58.join(process.cwd(), ".env");
26879
- const tmpPath = path58.join(process.cwd(), ".env.codeam.tmp");
27136
+ const envPath = path59.join(process.cwd(), ".env");
27137
+ const tmpPath = path59.join(process.cwd(), ".env.codeam.tmp");
26880
27138
  try {
26881
- await fs50.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
26882
- await fs50.promises.rename(tmpPath, envPath);
27139
+ await fs51.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
27140
+ await fs51.promises.rename(tmpPath, envPath);
26883
27141
  await ctx.relay.sendResult(cmd.id, "completed", { ok: true, count: vars.length });
26884
27142
  void syncProjectEnvUp(process.cwd(), ctx);
26885
27143
  } catch (err) {
26886
- await fs50.promises.rm(tmpPath, { force: true }).catch(() => void 0);
27144
+ await fs51.promises.rm(tmpPath, { force: true }).catch(() => void 0);
26887
27145
  await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
26888
27146
  }
26889
27147
  };
@@ -27215,9 +27473,9 @@ var CLI_UPDATE_MAX_ATTEMPTS = 3;
27215
27473
  function buildNpmInstallInvocation(opts) {
27216
27474
  const entryScript = opts?.entryScript ?? process.argv[1] ?? "";
27217
27475
  const execPath = opts?.execPath ?? process.execPath;
27218
- const exists2 = opts?.existsSync ?? fs50.existsSync;
27476
+ const exists2 = opts?.existsSync ?? fs51.existsSync;
27219
27477
  const platform3 = opts?.platform ?? process.platform;
27220
- const p2 = platform3 === "win32" ? path58.win32 : path58.posix;
27478
+ const p2 = platform3 === "win32" ? path59.win32 : path59.posix;
27221
27479
  const normalized = entryScript.split(/[\\/]/).join("/");
27222
27480
  const marker = "/lib/node_modules/codeam-cli/";
27223
27481
  const markerIdx = normalized.indexOf(marker);
@@ -27239,7 +27497,7 @@ function isPermissionError(stderr) {
27239
27497
  function resolveGlobalNodeModulesDir(opts) {
27240
27498
  const entryScript = opts?.entryScript ?? process.argv[1] ?? "";
27241
27499
  const platform3 = opts?.platform ?? process.platform;
27242
- const p2 = platform3 === "win32" ? path58.win32 : path58.posix;
27500
+ const p2 = platform3 === "win32" ? path59.win32 : path59.posix;
27243
27501
  const marker = "/lib/node_modules/codeam-cli/";
27244
27502
  const markerIdx = entryScript.split(/[\\/]/).join("/").indexOf(marker);
27245
27503
  if (markerIdx <= 0) return null;
@@ -27249,19 +27507,19 @@ function resolveGlobalNodeModulesDir(opts) {
27249
27507
  var STALE_STAGING_AGE_MS = CLI_UPDATE_INSTALL_TIMEOUT_MS;
27250
27508
  function sweepStaleCliStagingDirs(nodeModulesDir, now = Date.now(), deps) {
27251
27509
  if (!nodeModulesDir) return 0;
27252
- const readdirSync12 = deps?.readdirSync ?? fs50.readdirSync;
27253
- const statSync15 = deps?.statSync ?? fs50.statSync;
27254
- const rmSync9 = deps?.rmSync ?? fs50.rmSync;
27510
+ const readdirSync13 = deps?.readdirSync ?? fs51.readdirSync;
27511
+ const statSync15 = deps?.statSync ?? fs51.statSync;
27512
+ const rmSync9 = deps?.rmSync ?? fs51.rmSync;
27255
27513
  let removed = 0;
27256
27514
  let entries;
27257
27515
  try {
27258
- entries = readdirSync12(nodeModulesDir);
27516
+ entries = readdirSync13(nodeModulesDir);
27259
27517
  } catch {
27260
27518
  return 0;
27261
27519
  }
27262
27520
  for (const name of entries) {
27263
27521
  if (!/^\.codeam-cli-/.test(name)) continue;
27264
- const full = path58.join(nodeModulesDir, name);
27522
+ const full = path59.join(nodeModulesDir, name);
27265
27523
  try {
27266
27524
  const st3 = statSync15(full);
27267
27525
  if (now - st3.mtimeMs < STALE_STAGING_AGE_MS) continue;
@@ -27650,114 +27908,106 @@ async function runDetectOneShot(generate, timeoutMs = PREVIEW_DETECT_TIMEOUT_MS)
27650
27908
  if (timer) clearTimeout(timer);
27651
27909
  }
27652
27910
  }
27653
- var requestPreviewDetectH = (ctx) => {
27654
- if (!ctx.pluginAuthToken) {
27655
- log.info("preview", "no pluginAuthToken \u2014 skipping detect");
27656
- return;
27657
- }
27658
- if (typeof ctx.runtime.generateOneShot !== "function") {
27659
- log.info("preview", `runtime ${ctx.runtime.id} has no generateOneShot \u2014 emitting unsupported`);
27911
+ function originPayload(payload, origin) {
27912
+ if (origin !== "agent") return payload;
27913
+ return { ...payload ?? {}, origin };
27914
+ }
27915
+ async function resolvePreviewDetection(args2) {
27916
+ const { ctx, runtime, pluginAuthToken, origin } = args2;
27917
+ const emit2 = (type, payload) => {
27660
27918
  emitPreviewEvent({
27661
27919
  sessionId: ctx.sessionId,
27662
27920
  pluginId: ctx.pluginId,
27663
- pluginAuthToken: ctx.pluginAuthToken,
27664
- type: USER_EVENTS.PREVIEW_ERROR,
27665
- payload: {
27666
- stage: "detection",
27667
- message: `Preview detection isn't available on ${ctx.runtime.id} sessions yet \u2014 link a Claude or Codex agent.`
27668
- }
27921
+ pluginAuthToken,
27922
+ type,
27923
+ payload: originPayload(payload, origin)
27669
27924
  });
27670
- return;
27925
+ };
27926
+ if (typeof runtime.generateOneShot !== "function") {
27927
+ log.info("preview", `runtime ${runtime.id} has no generateOneShot \u2014 emitting unsupported`);
27928
+ emit2(USER_EVENTS.PREVIEW_ERROR, {
27929
+ stage: "detection",
27930
+ message: `Preview detection isn't available on ${runtime.id} sessions yet \u2014 link a Claude or Codex agent.`
27931
+ });
27932
+ return null;
27671
27933
  }
27672
- const pluginAuthToken = ctx.pluginAuthToken;
27673
- const generateOneShot = ctx.runtime.generateOneShot.bind(ctx.runtime);
27674
- void (async () => {
27675
- const fromFile = await readPreviewConfig(process.cwd());
27676
- if (fromFile) {
27677
- log.info("preview", `detect: using .codeam/preview.json (${fromFile.framework})`);
27678
- emitPreviewEvent({
27679
- sessionId: ctx.sessionId,
27680
- pluginId: ctx.pluginId,
27681
- pluginAuthToken,
27682
- type: USER_EVENTS.PREVIEW_DETECTION_READY,
27683
- payload: { detection: fromFile }
27684
- });
27685
- return;
27686
- }
27687
- emitPreviewEvent({
27688
- sessionId: ctx.sessionId,
27689
- pluginId: ctx.pluginId,
27690
- pluginAuthToken,
27691
- type: USER_EVENTS.PREVIEW_DETECTION_PENDING
27934
+ const generateOneShot = runtime.generateOneShot.bind(runtime);
27935
+ const fromFile = await readPreviewConfig(process.cwd());
27936
+ if (fromFile) {
27937
+ log.info("preview", `detect: using .codeam/preview.json (${fromFile.framework})`);
27938
+ return fromFile;
27939
+ }
27940
+ emit2(USER_EVENTS.PREVIEW_DETECTION_PENDING);
27941
+ log.info("preview", "detect: invoking generateOneShot");
27942
+ const startedAt = Date.now();
27943
+ const { raw, timedOut, stderr } = await runDetectOneShot(generateOneShot);
27944
+ const tookMs = Date.now() - startedAt;
27945
+ if (timedOut) {
27946
+ log.info("preview", `detect: timed out after ${tookMs}ms \u2014 emitting preview_error`);
27947
+ emit2(USER_EVENTS.PREVIEW_ERROR, {
27948
+ stage: "detection",
27949
+ message: `Project detection timed out after ${Math.round(PREVIEW_DETECT_TIMEOUT_MS / 1e3)} s \u2014 the agent did not answer. Try again, or add a .codeam/preview.json override.`
27692
27950
  });
27693
- log.info("preview", "detect: invoking generateOneShot");
27694
- const startedAt = Date.now();
27695
- const { raw, timedOut, stderr } = await runDetectOneShot(generateOneShot);
27696
- const tookMs = Date.now() - startedAt;
27697
- if (timedOut) {
27698
- log.info("preview", `detect: timed out after ${tookMs}ms \u2014 emitting preview_error`);
27699
- emitPreviewEvent({
27700
- sessionId: ctx.sessionId,
27701
- pluginId: ctx.pluginId,
27702
- pluginAuthToken,
27703
- type: USER_EVENTS.PREVIEW_ERROR,
27704
- payload: {
27705
- stage: "detection",
27706
- message: `Project detection timed out after ${Math.round(PREVIEW_DETECT_TIMEOUT_MS / 1e3)} s \u2014 the agent did not answer. Try again, or add a .codeam/preview.json override.`
27707
- }
27708
- });
27709
- return;
27710
- }
27711
- const detection = safeParseDetection(raw);
27712
- if (!detection) {
27713
- const failure = describeDetectionFailure(raw);
27714
- log.info(
27715
- "preview",
27716
- `detect: failed after ${tookMs}ms reason=${failure?.reason ?? "unknown"}` + (failure?.missing ? ` missing=${failure.missing.join(",")}` : "") + `
27951
+ return null;
27952
+ }
27953
+ const detection = safeParseDetection(raw);
27954
+ if (!detection) {
27955
+ const failure = describeDetectionFailure(raw);
27956
+ log.info(
27957
+ "preview",
27958
+ `detect: failed after ${tookMs}ms reason=${failure?.reason ?? "unknown"}` + (failure?.missing ? ` missing=${failure.missing.join(",")}` : "") + `
27717
27959
  --- salida cruda del agente (acotada) ---
27718
27960
  ${failure?.rawExcerpt ?? ""}`
27719
- );
27720
- emitPreviewEvent({
27721
- sessionId: ctx.sessionId,
27722
- pluginId: ctx.pluginId,
27723
- pluginAuthToken,
27724
- type: USER_EVENTS.PREVIEW_ERROR,
27725
- payload: {
27726
- stage: "detection",
27727
- // El mensaje sale del diagnostico: decir "JSON invalido" cuando el
27728
- // agente no contesto manda al usuario a mirar un JSON que no existe.
27729
- message: (failure?.reason === "no_output" ? describeOneShotAgentError(stderr) : null) ?? failure?.message ?? "Agent returned invalid JSON. Try again, or add a .codeam/preview.json override."
27730
- }
27731
- });
27732
- return;
27733
- }
27734
- if (isUnsupportedDetection(detection)) {
27735
- log.info("preview", "detect: framework=unsupported");
27736
- emitPreviewEvent({
27737
- sessionId: ctx.sessionId,
27738
- pluginId: ctx.pluginId,
27739
- pluginAuthToken,
27740
- type: USER_EVENTS.PREVIEW_ERROR,
27741
- payload: {
27742
- stage: "unsupported",
27743
- message: detection.notes ?? "No dev server applies to this project."
27744
- }
27745
- });
27746
- return;
27747
- }
27748
- log.info("preview", `detect: ${detection.framework} on :${detection.port} (took ${tookMs}ms)`);
27749
- void writePreviewConfig(process.cwd(), detection).catch((err) => {
27750
- log.info("preview", `detect: writePreviewConfig failed (non-fatal): ${String(err)}`);
27961
+ );
27962
+ emit2(USER_EVENTS.PREVIEW_ERROR, {
27963
+ stage: "detection",
27964
+ // El mensaje sale del diagnostico: decir "JSON invalido" cuando el
27965
+ // agente no contesto manda al usuario a mirar un JSON que no existe.
27966
+ message: (failure?.reason === "no_output" ? describeOneShotAgentError(stderr) : null) ?? failure?.message ?? "Agent returned invalid JSON. Try again, or add a .codeam/preview.json override."
27967
+ });
27968
+ return null;
27969
+ }
27970
+ if (isUnsupportedDetection(detection)) {
27971
+ log.info("preview", "detect: framework=unsupported");
27972
+ emit2(USER_EVENTS.PREVIEW_ERROR, {
27973
+ stage: "unsupported",
27974
+ message: detection.notes ?? "No dev server applies to this project."
27751
27975
  });
27976
+ return null;
27977
+ }
27978
+ log.info("preview", `detect: ${detection.framework} on :${detection.port} (took ${tookMs}ms)`);
27979
+ void writePreviewConfig(process.cwd(), detection).catch((err) => {
27980
+ log.info("preview", `detect: writePreviewConfig failed (non-fatal): ${String(err)}`);
27981
+ });
27982
+ return detection;
27983
+ }
27984
+ var requestPreviewDetectH = (ctx) => {
27985
+ if (!ctx.pluginAuthToken) {
27986
+ log.info("preview", "no pluginAuthToken \u2014 skipping detect");
27987
+ return;
27988
+ }
27989
+ const pluginAuthToken = ctx.pluginAuthToken;
27990
+ void (async () => {
27991
+ const detection = await resolvePreviewDetection({ ctx, runtime: ctx.runtime, pluginAuthToken });
27992
+ if (!detection) return;
27752
27993
  emitPreviewEvent({
27753
27994
  sessionId: ctx.sessionId,
27754
27995
  pluginId: ctx.pluginId,
27755
27996
  pluginAuthToken,
27756
27997
  type: USER_EVENTS.PREVIEW_DETECTION_READY,
27757
- payload: { detection }
27998
+ payload: { detection: withScriptCandidates(detection) }
27758
27999
  });
27759
28000
  })();
27760
28001
  };
28002
+ function withScriptCandidates(detection) {
28003
+ try {
28004
+ const candidates = listScriptCandidates(process.cwd());
28005
+ return candidates.length > 0 ? { ...detection, candidates } : detection;
28006
+ } catch (err) {
28007
+ log.info("preview", `detect: listing script candidates failed (non-fatal): ${String(err)}`);
28008
+ return detection;
28009
+ }
28010
+ }
27761
28011
  var previewPrewarmStarted = false;
27762
28012
  function makePreviewReaffirm(args2) {
27763
28013
  const token = args2.pluginAuthToken;
@@ -27787,6 +28037,7 @@ function makePreviewReaffirm(args2) {
27787
28037
  function prewarmPreviewDetection(runtime) {
27788
28038
  if (previewPrewarmStarted) return;
27789
28039
  previewPrewarmStarted = true;
28040
+ void prewarmNodeDeps(process.cwd());
27790
28041
  if (typeof runtime.generateOneShot !== "function") return;
27791
28042
  const generateOneShot = runtime.generateOneShot.bind(runtime);
27792
28043
  void (async () => {
@@ -27821,19 +28072,21 @@ var previewStartH = (ctx, _cmd, parsed) => {
27821
28072
  log.info("preview", "start: no detection in payload");
27822
28073
  return;
27823
28074
  }
27824
- startPreviewFromDetection(ctx, rawDetection, ctx.pluginAuthToken);
28075
+ void startPreviewFromDetection(ctx, rawDetection, ctx.pluginAuthToken);
27825
28076
  };
27826
- function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
28077
+ function startPreviewFromDetection(ctx, detection, pluginAuthToken, opts = {}) {
27827
28078
  const emit2 = (type, payload) => {
28079
+ const tagged = originPayload(payload, opts.origin) ?? {};
28080
+ opts.onEvent?.(type, tagged);
27828
28081
  emitPreviewEvent({
27829
28082
  sessionId: ctx.sessionId,
27830
28083
  pluginId: ctx.pluginId,
27831
28084
  pluginAuthToken,
27832
28085
  type,
27833
- payload
28086
+ payload: tagged
27834
28087
  });
27835
28088
  };
27836
- runPreviewStart({
28089
+ return runPreviewStart({
27837
28090
  sessionId: ctx.sessionId,
27838
28091
  detection,
27839
28092
  cwd: process.cwd(),
@@ -27864,7 +28117,7 @@ function maybeAttachBuildHeal(ctx, pluginAuthToken) {
27864
28117
  if (!activePreviews.has(ctx.sessionId)) return;
27865
28118
  await killPreview(ctx.sessionId);
27866
28119
  await new Promise((r) => setTimeout(r, 150));
27867
- startPreviewFromDetection(ctx, preview.detection, pluginAuthToken);
28120
+ void startPreviewFromDetection(ctx, preview.detection, pluginAuthToken);
27868
28121
  })();
27869
28122
  },
27870
28123
  notify: (message) => {
@@ -27910,7 +28163,7 @@ var previewRestartH = async (ctx, cmd) => {
27910
28163
  }
27911
28164
  await killPreview(ctx.sessionId);
27912
28165
  await new Promise((r) => setTimeout(r, 150));
27913
- startPreviewFromDetection(ctx, preview.detection, ctx.pluginAuthToken);
28166
+ void startPreviewFromDetection(ctx, preview.detection, ctx.pluginAuthToken);
27914
28167
  await ctx.relay.sendResult(cmd.id, "completed", { restarted: true });
27915
28168
  };
27916
28169
  var savePreviewConfigH = (_ctx, _cmd, parsed) => {
@@ -28283,11 +28536,11 @@ function resolveTokenValue(args2) {
28283
28536
  }
28284
28537
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
28285
28538
  if (fileFlag) {
28286
- const path95 = fileFlag.slice("--token-file=".length);
28539
+ const path96 = fileFlag.slice("--token-file=".length);
28287
28540
  try {
28288
- const content = fs51.readFileSync(path95, "utf8").trim();
28289
- if (content.length === 0) fail(`--token-file ${path95} is empty`);
28290
- rmIfExistsQuiet(path95);
28541
+ const content = fs52.readFileSync(path96, "utf8").trim();
28542
+ if (content.length === 0) fail(`--token-file ${path96} is empty`);
28543
+ rmIfExistsQuiet(path96);
28291
28544
  return content;
28292
28545
  } catch (err) {
28293
28546
  fail(`Could not read --token-file: ${err.message}`);
@@ -28379,12 +28632,12 @@ async function claim(token, pluginId, pluginSecretHash) {
28379
28632
  }
28380
28633
  }
28381
28634
  function pairAutoLockPath() {
28382
- return path59.join(os40.homedir(), ".codeam", "pair-auto.lock");
28635
+ return path60.join(os40.homedir(), ".codeam", "pair-auto.lock");
28383
28636
  }
28384
28637
  var procRoot = "/proc";
28385
28638
  function readProcFile(rel) {
28386
28639
  try {
28387
- return fs51.readFileSync(path59.join(procRoot, rel), "utf8");
28640
+ return fs52.readFileSync(path60.join(procRoot, rel), "utf8");
28388
28641
  } catch {
28389
28642
  return void 0;
28390
28643
  }
@@ -28405,7 +28658,7 @@ function currentBootId() {
28405
28658
  function readLockRecord(lockPath) {
28406
28659
  let raw;
28407
28660
  try {
28408
- raw = fs51.readFileSync(lockPath, "utf8");
28661
+ raw = fs52.readFileSync(lockPath, "utf8");
28409
28662
  } catch {
28410
28663
  return void 0;
28411
28664
  }
@@ -28454,24 +28707,24 @@ function isLiveLockHolder(rec) {
28454
28707
  }
28455
28708
  function releaseOwnLock(lockPath) {
28456
28709
  try {
28457
- if (readLockRecord(lockPath)?.pid === process.pid) fs51.unlinkSync(lockPath);
28710
+ if (readLockRecord(lockPath)?.pid === process.pid) fs52.unlinkSync(lockPath);
28458
28711
  } catch {
28459
28712
  }
28460
28713
  }
28461
28714
  function daemonLockPath(sessionId) {
28462
28715
  const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
28463
- return path59.join(os40.homedir(), ".codeam", `daemon-${safe}.lock`);
28716
+ return path60.join(os40.homedir(), ".codeam", `daemon-${safe}.lock`);
28464
28717
  }
28465
28718
  function acquireDaemonLock(sessionId) {
28466
28719
  const lockPath = daemonLockPath(sessionId);
28467
28720
  try {
28468
- fs51.mkdirSync(path59.dirname(lockPath), { recursive: true });
28721
+ fs52.mkdirSync(path60.dirname(lockPath), { recursive: true });
28469
28722
  try {
28470
- fs51.writeFileSync(lockPath, ownLockBody(), { flag: "wx" });
28723
+ fs52.writeFileSync(lockPath, ownLockBody(), { flag: "wx" });
28471
28724
  } catch (e) {
28472
28725
  if (e.code !== "EEXIST") throw e;
28473
28726
  if (isLiveLockHolder(readLockRecord(lockPath))) return false;
28474
- fs51.writeFileSync(lockPath, ownLockBody());
28727
+ fs52.writeFileSync(lockPath, ownLockBody());
28475
28728
  }
28476
28729
  const release3 = () => releaseOwnLock(lockPath);
28477
28730
  process.once("exit", release3);
@@ -28491,13 +28744,13 @@ function acquireDaemonLock(sessionId) {
28491
28744
  function acquireSingletonLock() {
28492
28745
  const lockPath = pairAutoLockPath();
28493
28746
  try {
28494
- fs51.mkdirSync(path59.dirname(lockPath), { recursive: true });
28747
+ fs52.mkdirSync(path60.dirname(lockPath), { recursive: true });
28495
28748
  try {
28496
- fs51.writeFileSync(lockPath, ownLockBody(), { flag: "wx" });
28749
+ fs52.writeFileSync(lockPath, ownLockBody(), { flag: "wx" });
28497
28750
  } catch (e) {
28498
28751
  if (e.code !== "EEXIST") throw e;
28499
28752
  if (isLiveLockHolder(readLockRecord(lockPath))) return false;
28500
- fs51.writeFileSync(lockPath, ownLockBody());
28753
+ fs52.writeFileSync(lockPath, ownLockBody());
28501
28754
  }
28502
28755
  process.once("exit", () => releaseOwnLock(lockPath));
28503
28756
  return true;
@@ -28914,7 +29167,7 @@ var AgentService = class _AgentService {
28914
29167
  };
28915
29168
 
28916
29169
  // src/agents/acp/adapters.ts
28917
- var path60 = __toESM(require("path"));
29170
+ var path61 = __toESM(require("path"));
28918
29171
 
28919
29172
  // src/agents/kimi/installer.ts
28920
29173
  var import_node_child_process19 = require("child_process");
@@ -29034,13 +29287,13 @@ function resolveBin(pkgName, binName) {
29034
29287
  try {
29035
29288
  const manifestPath = require_.resolve(`${pkgName}/package.json`);
29036
29289
  const manifest = require_(`${pkgName}/package.json`);
29037
- const pkgDir = path60.dirname(manifestPath);
29290
+ const pkgDir = path61.dirname(manifestPath);
29038
29291
  const bin = manifest.bin;
29039
29292
  if (!bin) return null;
29040
- if (typeof bin === "string") return path60.resolve(pkgDir, bin);
29293
+ if (typeof bin === "string") return path61.resolve(pkgDir, bin);
29041
29294
  const target = binName ?? Object.keys(bin)[0];
29042
29295
  if (!target || !bin[target]) return null;
29043
- return path60.resolve(pkgDir, bin[target]);
29296
+ return path61.resolve(pkgDir, bin[target]);
29044
29297
  } catch {
29045
29298
  return null;
29046
29299
  }
@@ -29220,30 +29473,30 @@ async function resolveAcpAdapterWithRetry(agent, opts = {}) {
29220
29473
  }
29221
29474
 
29222
29475
  // src/agents/acp/runner.ts
29223
- var import_node_crypto10 = require("crypto");
29224
- var fs68 = __toESM(require("fs"));
29476
+ var import_node_crypto11 = require("crypto");
29477
+ var fs69 = __toESM(require("fs"));
29225
29478
  var os53 = __toESM(require("os"));
29226
- var path79 = __toESM(require("path"));
29479
+ var path80 = __toESM(require("path"));
29227
29480
 
29228
29481
  // src/lib/provider-routing.ts
29229
- var fs53 = __toESM(require("fs"));
29482
+ var fs54 = __toESM(require("fs"));
29230
29483
  var os42 = __toESM(require("os"));
29231
- var path62 = __toESM(require("path"));
29484
+ var path63 = __toESM(require("path"));
29232
29485
 
29233
29486
  // src/commands/host/house-proxy-config.ts
29234
- var fs52 = __toESM(require("fs"));
29487
+ var fs53 = __toESM(require("fs"));
29235
29488
  var os41 = __toESM(require("os"));
29236
- var path61 = __toESM(require("path"));
29489
+ var path62 = __toESM(require("path"));
29237
29490
  function houseProxyConfigPath() {
29238
- return path61.join(os41.homedir(), ".codeam", "house-proxy.json");
29491
+ return path62.join(os41.homedir(), ".codeam", "house-proxy.json");
29239
29492
  }
29240
29493
  function persistHouseProxyConfig(config) {
29241
29494
  try {
29242
29495
  const file = houseProxyConfigPath();
29243
- fs52.mkdirSync(path61.dirname(file), { recursive: true, mode: 448 });
29496
+ fs53.mkdirSync(path62.dirname(file), { recursive: true, mode: 448 });
29244
29497
  const tmp = `${file}.tmp-${process.pid}`;
29245
- fs52.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
29246
- fs52.renameSync(tmp, file);
29498
+ fs53.writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: "utf8", mode: 384 });
29499
+ fs53.renameSync(tmp, file);
29247
29500
  restrictToOwner(file);
29248
29501
  } catch (err) {
29249
29502
  log.warn(
@@ -29254,13 +29507,13 @@ function persistHouseProxyConfig(config) {
29254
29507
  }
29255
29508
  function clearHouseProxyConfig() {
29256
29509
  try {
29257
- fs52.rmSync(houseProxyConfigPath(), { force: true });
29510
+ fs53.rmSync(houseProxyConfigPath(), { force: true });
29258
29511
  } catch {
29259
29512
  }
29260
29513
  }
29261
29514
  function readHouseProxyChildEnv() {
29262
29515
  try {
29263
- const raw = fs52.readFileSync(houseProxyConfigPath(), "utf8");
29516
+ const raw = fs53.readFileSync(houseProxyConfigPath(), "utf8");
29264
29517
  const parsed = JSON.parse(raw);
29265
29518
  if (typeof parsed !== "object" || parsed === null) return {};
29266
29519
  const o = parsed;
@@ -29387,14 +29640,14 @@ function redactUrlToOrigin(raw) {
29387
29640
  }
29388
29641
  function readOpencodeProviderOrigins(opts = {}) {
29389
29642
  const home = opts.homeDir ?? os42.homedir();
29390
- const readFile7 = opts.readFile ?? ((f) => fs53.readFileSync(f, "utf8"));
29643
+ const readFile7 = opts.readFile ?? ((f) => fs54.readFileSync(f, "utf8"));
29391
29644
  const candidates = [];
29392
29645
  if (opts.cwd) {
29393
- candidates.push(path62.join(opts.cwd, "opencode.json"), path62.join(opts.cwd, "opencode.jsonc"));
29646
+ candidates.push(path63.join(opts.cwd, "opencode.json"), path63.join(opts.cwd, "opencode.jsonc"));
29394
29647
  }
29395
29648
  candidates.push(
29396
- path62.join(home, ".config", "opencode", "opencode.json"),
29397
- path62.join(home, ".config", "opencode", "opencode.jsonc")
29649
+ path63.join(home, ".config", "opencode", "opencode.json"),
29650
+ path63.join(home, ".config", "opencode", "opencode.jsonc")
29398
29651
  );
29399
29652
  const out2 = [];
29400
29653
  const seen2 = /* @__PURE__ */ new Set();
@@ -29501,8 +29754,8 @@ function noteProviderBillingSignal(opts) {
29501
29754
  }
29502
29755
 
29503
29756
  // src/services/history.service.ts
29504
- var fs54 = __toESM(require("fs"));
29505
- var path63 = __toESM(require("path"));
29757
+ var fs55 = __toESM(require("fs"));
29758
+ var path64 = __toESM(require("path"));
29506
29759
  var os43 = __toESM(require("os"));
29507
29760
  var https6 = __toESM(require("https"));
29508
29761
  var http9 = __toESM(require("http"));
@@ -29564,7 +29817,7 @@ function parseJsonl(filePath) {
29564
29817
  const messages = [];
29565
29818
  let raw;
29566
29819
  try {
29567
- raw = fs54.readFileSync(filePath, "utf8");
29820
+ raw = fs55.readFileSync(filePath, "utf8");
29568
29821
  } catch (err) {
29569
29822
  if (err.code !== "ENOENT") {
29570
29823
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -29718,7 +29971,7 @@ var HistoryService = class _HistoryService {
29718
29971
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
29719
29972
  }
29720
29973
  get projectDir() {
29721
- return this.runtime.resolveHistoryDir(this.cwd) ?? path63.join(os43.homedir(), ".claude", "projects", encodeCwd(this.cwd));
29974
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path64.join(os43.homedir(), ".claude", "projects", encodeCwd(this.cwd));
29722
29975
  }
29723
29976
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
29724
29977
  setCurrentConversationId(id) {
@@ -29730,7 +29983,7 @@ var HistoryService = class _HistoryService {
29730
29983
  /** Return the current message count in the active conversation. */
29731
29984
  getCurrentMessageCount() {
29732
29985
  if (!this.currentConversationId) return 0;
29733
- const filePath = path63.join(this.projectDir, `${this.currentConversationId}.jsonl`);
29986
+ const filePath = path64.join(this.projectDir, `${this.currentConversationId}.jsonl`);
29734
29987
  return parseJsonl(filePath).length;
29735
29988
  }
29736
29989
  /**
@@ -29741,7 +29994,7 @@ var HistoryService = class _HistoryService {
29741
29994
  const deadline = Date.now() + timeoutMs;
29742
29995
  while (Date.now() < deadline) {
29743
29996
  if (!this.currentConversationId) return null;
29744
- const filePath = path63.join(this.projectDir, `${this.currentConversationId}.jsonl`);
29997
+ const filePath = path64.join(this.projectDir, `${this.currentConversationId}.jsonl`);
29745
29998
  const messages = parseJsonl(filePath);
29746
29999
  if (messages.length > previousCount) {
29747
30000
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -29767,16 +30020,16 @@ var HistoryService = class _HistoryService {
29767
30020
  const dir = this.projectDir;
29768
30021
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
29769
30022
  try {
29770
- const files = fs54.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
30023
+ const files = fs55.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
29771
30024
  try {
29772
- const stat3 = fs54.statSync(path63.join(dir, e.name));
30025
+ const stat3 = fs55.statSync(path64.join(dir, e.name));
29773
30026
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
29774
30027
  } catch {
29775
30028
  return { name: e.name, mtime: 0, birthtime: 0 };
29776
30029
  }
29777
30030
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
29778
30031
  if (files.length > 0) {
29779
- this.currentConversationId = path63.basename(files[0].name, ".jsonl");
30032
+ this.currentConversationId = path64.basename(files[0].name, ".jsonl");
29780
30033
  }
29781
30034
  } catch {
29782
30035
  }
@@ -29810,13 +30063,13 @@ var HistoryService = class _HistoryService {
29810
30063
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
29811
30064
  let entries;
29812
30065
  try {
29813
- entries = fs54.readdirSync(dir, { withFileTypes: true });
30066
+ entries = fs55.readdirSync(dir, { withFileTypes: true });
29814
30067
  } catch {
29815
30068
  return null;
29816
30069
  }
29817
30070
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
29818
30071
  try {
29819
- const stat3 = fs54.statSync(path63.join(dir, e.name));
30072
+ const stat3 = fs55.statSync(path64.join(dir, e.name));
29820
30073
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
29821
30074
  } catch {
29822
30075
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -29825,12 +30078,12 @@ var HistoryService = class _HistoryService {
29825
30078
  if (files.length === 0) return null;
29826
30079
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
29827
30080
  if (!files.some((f) => f.name === targetFile)) return null;
29828
- return this.extractUsageFromFile(path63.join(dir, targetFile));
30081
+ return this.extractUsageFromFile(path64.join(dir, targetFile));
29829
30082
  }
29830
30083
  extractUsageFromFile(filePath) {
29831
30084
  let raw;
29832
30085
  try {
29833
- raw = fs54.readFileSync(filePath, "utf8");
30086
+ raw = fs55.readFileSync(filePath, "utf8");
29834
30087
  } catch {
29835
30088
  return null;
29836
30089
  }
@@ -29882,9 +30135,9 @@ var HistoryService = class _HistoryService {
29882
30135
  let totalCost = 0;
29883
30136
  let files;
29884
30137
  try {
29885
- files = fs54.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
30138
+ files = fs55.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
29886
30139
  try {
29887
- return fs54.statSync(path63.join(projectDir, f)).mtimeMs >= monthStartMs;
30140
+ return fs55.statSync(path64.join(projectDir, f)).mtimeMs >= monthStartMs;
29888
30141
  } catch {
29889
30142
  return false;
29890
30143
  }
@@ -29895,7 +30148,7 @@ var HistoryService = class _HistoryService {
29895
30148
  for (const file of files) {
29896
30149
  let raw;
29897
30150
  try {
29898
- raw = fs54.readFileSync(path63.join(projectDir, file), "utf8");
30151
+ raw = fs55.readFileSync(path64.join(projectDir, file), "utf8");
29899
30152
  } catch {
29900
30153
  continue;
29901
30154
  }
@@ -29974,7 +30227,7 @@ var HistoryService = class _HistoryService {
29974
30227
  if (this.runtime.resolveHistoryFile) {
29975
30228
  return this.runtime.resolveHistoryFile(this.cwd, sessionId);
29976
30229
  }
29977
- return path63.join(this.projectDir, `${sessionId}.jsonl`);
30230
+ return path64.join(this.projectDir, `${sessionId}.jsonl`);
29978
30231
  }
29979
30232
  /**
29980
30233
  * Parse a conversation's messages from disk, agent-aware. Claude uses the
@@ -30012,14 +30265,14 @@ var HistoryService = class _HistoryService {
30012
30265
  };
30013
30266
  });
30014
30267
  }
30015
- return parseJsonl(path63.join(this.projectDir, `${sessionId}.jsonl`));
30268
+ return parseJsonl(path64.join(this.projectDir, `${sessionId}.jsonl`));
30016
30269
  }
30017
30270
  /** One in-flight full upload per conversation — the baton mirror and a
30018
30271
  * `get_conversation` used to upload the same transcript concurrently. */
30019
30272
  uploadsInFlight = /* @__PURE__ */ new Map();
30020
30273
  async loadConversation(sessionId) {
30021
- const inFlight = this.uploadsInFlight.get(sessionId);
30022
- if (inFlight) return inFlight;
30274
+ const inFlight2 = this.uploadsInFlight.get(sessionId);
30275
+ if (inFlight2) return inFlight2;
30023
30276
  const run = this.loadConversationNow(sessionId).finally(() => {
30024
30277
  this.uploadsInFlight.delete(sessionId);
30025
30278
  });
@@ -30094,7 +30347,7 @@ var HistoryService = class _HistoryService {
30094
30347
  if (!filePath) return false;
30095
30348
  let mtimeMs;
30096
30349
  try {
30097
- mtimeMs = fs54.statSync(filePath).mtimeMs;
30350
+ mtimeMs = fs55.statSync(filePath).mtimeMs;
30098
30351
  } catch {
30099
30352
  return false;
30100
30353
  }
@@ -30169,10 +30422,10 @@ var HistoryService = class _HistoryService {
30169
30422
 
30170
30423
  // src/agents/acp/client.ts
30171
30424
  var import_node_child_process21 = require("child_process");
30172
- var fs55 = __toESM(require("fs/promises"));
30425
+ var fs56 = __toESM(require("fs/promises"));
30173
30426
  var fsSync = __toESM(require("fs"));
30174
30427
  var os45 = __toESM(require("os"));
30175
- var path65 = __toESM(require("path"));
30428
+ var path66 = __toESM(require("path"));
30176
30429
  var import_node_stream = require("stream");
30177
30430
 
30178
30431
  // ../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
@@ -34198,7 +34451,7 @@ function createIdleTimeout(idleMs, makeError, activeIdleMs = idleMs) {
34198
34451
  }
34199
34452
 
34200
34453
  // src/agents/acp/internal-paths.ts
34201
- var path64 = __toESM(require("path"));
34454
+ var path65 = __toESM(require("path"));
34202
34455
  var os44 = __toESM(require("os"));
34203
34456
  var INTERNAL_TOKENS = [".codeam", "house-claude"];
34204
34457
  var PROSE_ONLY_TOOL_KINDS = /* @__PURE__ */ new Set(["think", "switch_mode"]);
@@ -34213,11 +34466,11 @@ function textReferencesInternal(text) {
34213
34466
  }
34214
34467
  function pathIsInternal(p2, homeDir2 = os44.homedir()) {
34215
34468
  if (!p2) return false;
34216
- const abs = path64.resolve(p2);
34217
- const home = path64.resolve(homeDir2);
34218
- const within = (root) => abs === root || abs.startsWith(root + path64.sep);
34219
- if (within(path64.join(home, ".codeam", "self-hosted"))) return false;
34220
- return within(path64.join(home, ".codeam")) || within(path64.join(home, ".beads")) || abs === path64.join(home, ".codeam-host.log") || abs.includes(`${path64.sep}house-claude${path64.sep}`) || abs.endsWith(`${path64.sep}house-claude`);
34469
+ const abs = path65.resolve(p2);
34470
+ const home = path65.resolve(homeDir2);
34471
+ const within = (root) => abs === root || abs.startsWith(root + path65.sep);
34472
+ if (within(path65.join(home, ".codeam", "self-hosted"))) return false;
34473
+ return within(path65.join(home, ".codeam")) || within(path65.join(home, ".beads")) || abs === path65.join(home, ".codeam-host.log") || abs.includes(`${path65.sep}house-claude${path65.sep}`) || abs.endsWith(`${path65.sep}house-claude`);
34221
34474
  }
34222
34475
  function toolCallReferencesInternal(call, homeDir2) {
34223
34476
  if (call.locations?.some((l) => pathIsInternal(l.path, homeDir2))) return true;
@@ -35312,7 +35565,7 @@ var AcpClient = class {
35312
35565
  throw new RequestError(-32002, GUARDRAIL_SECRET_READ_BLOCK_REASON, { uri: params.path });
35313
35566
  }
35314
35567
  try {
35315
- const content = await fs55.readFile(params.path, "utf8");
35568
+ const content = await fs56.readFile(params.path, "utf8");
35316
35569
  return applyLineRange(content, params.line ?? null, params.limit ?? null);
35317
35570
  } catch (err) {
35318
35571
  const code = err.code;
@@ -35333,7 +35586,7 @@ var AcpClient = class {
35333
35586
  throw new RequestError(-32002, INTERNAL_BLOCK_REASON, { uri: params.path });
35334
35587
  }
35335
35588
  try {
35336
- await fs55.writeFile(params.path, params.content, "utf8");
35589
+ await fs56.writeFile(params.path, params.content, "utf8");
35337
35590
  return {};
35338
35591
  } catch (err) {
35339
35592
  const code = err.code;
@@ -35426,25 +35679,25 @@ function knownAgentBinaryDirs() {
35426
35679
  out2.push("/tmp/codeam-node20/bin");
35427
35680
  for (const root of [
35428
35681
  "/usr/local/share/nvm/versions/node",
35429
- path65.join(home, ".nvm/versions/node")
35682
+ path66.join(home, ".nvm/versions/node")
35430
35683
  ]) {
35431
35684
  try {
35432
35685
  for (const child of fsSync.readdirSync(root)) {
35433
- out2.push(path65.join(root, child, "bin"));
35686
+ out2.push(path66.join(root, child, "bin"));
35434
35687
  }
35435
35688
  } catch {
35436
35689
  }
35437
35690
  }
35438
- out2.push(path65.join(home, ".volta/bin"));
35691
+ out2.push(path66.join(home, ".volta/bin"));
35439
35692
  out2.push("/usr/local/bin");
35440
35693
  out2.push("/usr/bin");
35441
- out2.push(path65.join(home, ".local/bin"));
35442
- out2.push(path65.join(home, "bin"));
35694
+ out2.push(path66.join(home, ".local/bin"));
35695
+ out2.push(path66.join(home, "bin"));
35443
35696
  out2.push(...agentInstallBinDirs());
35444
35697
  if (process.platform === "win32") {
35445
35698
  const { LOCALAPPDATA, APPDATA } = process.env;
35446
- if (LOCALAPPDATA) out2.push(path65.join(LOCALAPPDATA, "cursor-agent"));
35447
- if (APPDATA) out2.push(path65.join(APPDATA, "npm"));
35699
+ if (LOCALAPPDATA) out2.push(path66.join(LOCALAPPDATA, "cursor-agent"));
35700
+ if (APPDATA) out2.push(path66.join(APPDATA, "npm"));
35448
35701
  }
35449
35702
  return out2.filter((p2) => {
35450
35703
  try {
@@ -35455,7 +35708,7 @@ function knownAgentBinaryDirs() {
35455
35708
  });
35456
35709
  }
35457
35710
  function expandPathForAgentBinaries(existingPath) {
35458
- const existing = new Set(existingPath.split(path65.delimiter).filter((p2) => p2.length > 0));
35711
+ const existing = new Set(existingPath.split(path66.delimiter).filter((p2) => p2.length > 0));
35459
35712
  const additions = [];
35460
35713
  for (const dir of knownAgentBinaryDirs()) {
35461
35714
  if (!existing.has(dir)) {
@@ -35464,7 +35717,7 @@ function expandPathForAgentBinaries(existingPath) {
35464
35717
  }
35465
35718
  }
35466
35719
  if (additions.length === 0) return existingPath;
35467
- return [...additions, existingPath].filter((p2) => p2.length > 0).join(path65.delimiter);
35720
+ return [...additions, existingPath].filter((p2) => p2.length > 0).join(path66.delimiter);
35468
35721
  }
35469
35722
 
35470
35723
  // src/commands/host/agent-install.ts
@@ -35736,9 +35989,9 @@ async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
35736
35989
  }
35737
35990
 
35738
35991
  // src/commands/host/agent-provisioning.ts
35739
- var fs56 = __toESM(require("fs"));
35992
+ var fs57 = __toESM(require("fs"));
35740
35993
  var os47 = __toESM(require("os"));
35741
- var path66 = __toESM(require("path"));
35994
+ var path67 = __toESM(require("path"));
35742
35995
  var PUBLIC_TO_INTERNAL_AGENT = {
35743
35996
  claude_code: "claude",
35744
35997
  claude: "claude",
@@ -35755,22 +36008,22 @@ function toInternalAgentId(publicAgentId) {
35755
36008
  return PUBLIC_TO_INTERNAL_AGENT[publicAgentId] ?? null;
35756
36009
  }
35757
36010
  function ensureDir(dir) {
35758
- fs56.mkdirSync(dir, { recursive: true, mode: 448 });
36011
+ fs57.mkdirSync(dir, { recursive: true, mode: 448 });
35759
36012
  }
35760
36013
  function writeFile0600(filePath, contents) {
35761
- ensureDir(path66.dirname(filePath));
35762
- fs56.writeFileSync(filePath, contents, { encoding: "utf8", mode: 384 });
36014
+ ensureDir(path67.dirname(filePath));
36015
+ fs57.writeFileSync(filePath, contents, { encoding: "utf8", mode: 384 });
35763
36016
  restrictToOwner(filePath);
35764
36017
  }
35765
36018
  function rmIfExists(filePath) {
35766
36019
  try {
35767
- fs56.rmSync(filePath, { force: true });
36020
+ fs57.rmSync(filePath, { force: true });
35768
36021
  } catch {
35769
36022
  }
35770
36023
  }
35771
36024
  var claudeProvisioner = {
35772
36025
  write(auth, home) {
35773
- const credentialsJson = path66.join(home, ".claude", ".credentials.json");
36026
+ const credentialsJson = path67.join(home, ".claude", ".credentials.json");
35774
36027
  if (auth.kind === "api_key") {
35775
36028
  rmIfExists(credentialsJson);
35776
36029
  return { ANTHROPIC_API_KEY: auth.value };
@@ -35782,8 +36035,8 @@ var claudeProvisioner = {
35782
36035
  } else {
35783
36036
  rmIfExists(credentialsJson);
35784
36037
  }
35785
- const claudeJson = path66.join(home, ".claude.json");
35786
- if (!fs56.existsSync(claudeJson)) {
36038
+ const claudeJson = path67.join(home, ".claude.json");
36039
+ if (!fs57.existsSync(claudeJson)) {
35787
36040
  writeFile0600(
35788
36041
  claudeJson,
35789
36042
  JSON.stringify({ hasCompletedOnboarding: true, customApiKeyResponses: { approved: [] } })
@@ -35794,7 +36047,7 @@ var claudeProvisioner = {
35794
36047
  };
35795
36048
  var codexProvisioner = {
35796
36049
  write(auth, home) {
35797
- const authJson = path66.join(home, ".codex", "auth.json");
36050
+ const authJson = path67.join(home, ".codex", "auth.json");
35798
36051
  if (auth.kind === "api_key") {
35799
36052
  writeFile0600(authJson, JSON.stringify({ auth_mode: "apikey", OPENAI_API_KEY: auth.value }));
35800
36053
  return { OPENAI_API_KEY: auth.value };
@@ -35805,8 +36058,8 @@ var codexProvisioner = {
35805
36058
  };
35806
36059
  var geminiProvisioner = {
35807
36060
  write(auth, home) {
35808
- const settingsJson = path66.join(home, ".gemini", "settings.json");
35809
- const oauthCreds = path66.join(home, ".gemini", "oauth_creds.json");
36061
+ const settingsJson = path67.join(home, ".gemini", "settings.json");
36062
+ const oauthCreds = path67.join(home, ".gemini", "oauth_creds.json");
35810
36063
  if (auth.kind === "api_key") {
35811
36064
  rmIfExists(oauthCreds);
35812
36065
  writeFile0600(settingsJson, '{"security":{"auth":{"selectedType":"gemini-api-key"}}}');
@@ -35819,7 +36072,7 @@ var geminiProvisioner = {
35819
36072
  };
35820
36073
  var cursorProvisioner = {
35821
36074
  write(auth, home) {
35822
- const authJson = path66.join(home, ".config", "cursor", "auth.json");
36075
+ const authJson = path67.join(home, ".config", "cursor", "auth.json");
35823
36076
  if (auth.kind === "api_key") {
35824
36077
  rmIfExists(authJson);
35825
36078
  return { CURSOR_API_KEY: auth.value };
@@ -35861,22 +36114,22 @@ max_context_size = 262144
35861
36114
  var kimiProvisioner = {
35862
36115
  write(auth, home) {
35863
36116
  const credentialsFiles = [
35864
- path66.join(home, ".kimi", "credentials", "kimi-code.json"),
35865
- path66.join(home, ".kimi-code", "credentials", "kimi-code.json")
36117
+ path67.join(home, ".kimi", "credentials", "kimi-code.json"),
36118
+ path67.join(home, ".kimi-code", "credentials", "kimi-code.json")
35866
36119
  ];
35867
36120
  if (auth.kind === "api_key") {
35868
36121
  credentialsFiles.forEach(rmIfExists);
35869
36122
  return { KIMI_API_KEY: auth.value };
35870
36123
  }
35871
36124
  credentialsFiles.forEach((f) => writeFile0600(f, auth.value));
35872
- writeFile0600(path66.join(home, ".kimi-code", "config.toml"), KIMI_MANAGED_CONFIG_TOML);
36125
+ writeFile0600(path67.join(home, ".kimi-code", "config.toml"), KIMI_MANAGED_CONFIG_TOML);
35873
36126
  return {};
35874
36127
  }
35875
36128
  };
35876
36129
  var coderabbitProvisioner = {
35877
36130
  write(auth, home) {
35878
- const dir = path66.join(home, ".coderabbit");
35879
- const authJson = path66.join(dir, "auth.json");
36131
+ const dir = path67.join(home, ".coderabbit");
36132
+ const authJson = path67.join(dir, "auth.json");
35880
36133
  if (auth.kind === "api_key") {
35881
36134
  rmIfExists(authJson);
35882
36135
  return { CODERABBIT_API_KEY: auth.value };
@@ -35888,13 +36141,13 @@ var coderabbitProvisioner = {
35888
36141
  try {
35889
36142
  const parsed = JSON.parse(value);
35890
36143
  if (typeof parsed.file === "string" && typeof parsed.contents === "string") {
35891
- file = path66.basename(parsed.file);
36144
+ file = path67.basename(parsed.file);
35892
36145
  contents = parsed.contents;
35893
36146
  }
35894
36147
  } catch {
35895
36148
  }
35896
36149
  }
35897
- writeFile0600(path66.join(dir, file), contents);
36150
+ writeFile0600(path67.join(dir, file), contents);
35898
36151
  return {};
35899
36152
  }
35900
36153
  };
@@ -35931,16 +36184,16 @@ function provisionAgentCredentials(publicAgentId, auth, homeDir2 = os47.homedir(
35931
36184
  }
35932
36185
 
35933
36186
  // src/beads/workflow-hint.ts
35934
- var fs57 = __toESM(require("fs"));
35935
- var path68 = __toESM(require("path"));
36187
+ var fs58 = __toESM(require("fs"));
36188
+ var path69 = __toESM(require("path"));
35936
36189
 
35937
36190
  // src/agents/claude-memory-file.ts
35938
36191
  var os48 = __toESM(require("os"));
35939
- var path67 = __toESM(require("path"));
36192
+ var path68 = __toESM(require("path"));
35940
36193
  function claudeMemoryFile(homeDir2, env = process.env) {
35941
- if (homeDir2) return path67.join(homeDir2, ".claude", "CLAUDE.md");
36194
+ if (homeDir2) return path68.join(homeDir2, ".claude", "CLAUDE.md");
35942
36195
  const configDir = env.CLAUDE_CONFIG_DIR?.trim();
35943
- return configDir ? path67.join(configDir, "CLAUDE.md") : path67.join(os48.homedir(), ".claude", "CLAUDE.md");
36196
+ return configDir ? path68.join(configDir, "CLAUDE.md") : path68.join(os48.homedir(), ".claude", "CLAUDE.md");
35944
36197
  }
35945
36198
 
35946
36199
  // src/beads/workflow-hint.ts
@@ -35970,11 +36223,11 @@ function ensureBeadsWorkflowHint(homeDir2, file = claudeMemoryFile(homeDir2)) {
35970
36223
  try {
35971
36224
  let existing = "";
35972
36225
  try {
35973
- existing = fs57.readFileSync(file, "utf8");
36226
+ existing = fs58.readFileSync(file, "utf8");
35974
36227
  } catch {
35975
36228
  }
35976
36229
  if (existing.includes(BEADS_HINT)) return;
35977
- fs57.mkdirSync(path68.dirname(file), { recursive: true });
36230
+ fs58.mkdirSync(path69.dirname(file), { recursive: true });
35978
36231
  let next;
35979
36232
  const open = existing.indexOf(BEADS_HINT_MARKER);
35980
36233
  const close = open === -1 ? -1 : existing.indexOf(BEADS_HINT_MARKER, open + BEADS_HINT_MARKER.length);
@@ -35987,40 +36240,40 @@ ${BEADS_HINT}
35987
36240
  ` : `${BEADS_HINT}
35988
36241
  `;
35989
36242
  }
35990
- fs57.writeFileSync(file, next);
36243
+ fs58.writeFileSync(file, next);
35991
36244
  } catch {
35992
36245
  }
35993
36246
  }
35994
36247
 
35995
36248
  // src/agents/agent-standard.ts
35996
- var fs58 = __toESM(require("fs"));
35997
- var path69 = __toESM(require("path"));
36249
+ var fs59 = __toESM(require("fs"));
36250
+ var path70 = __toESM(require("path"));
35998
36251
  var os49 = __toESM(require("os"));
35999
36252
  function ensureAgentStandard(homeDir2, file = claudeMemoryFile(homeDir2)) {
36000
36253
  try {
36001
36254
  let existing = "";
36002
36255
  try {
36003
- existing = fs58.readFileSync(file, "utf8");
36256
+ existing = fs59.readFileSync(file, "utf8");
36004
36257
  } catch {
36005
36258
  }
36006
36259
  if (existing.includes(AGENT_STANDARD_MARKER)) return;
36007
- fs58.mkdirSync(path69.dirname(file), { recursive: true });
36260
+ fs59.mkdirSync(path70.dirname(file), { recursive: true });
36008
36261
  const next = existing.trim() ? `${existing.trimEnd()}
36009
36262
 
36010
36263
  ${AGENT_STANDARD_BLOCK}
36011
36264
  ` : `${AGENT_STANDARD_BLOCK}
36012
36265
  `;
36013
- fs58.writeFileSync(file, next);
36266
+ fs59.writeFileSync(file, next);
36014
36267
  } catch {
36015
36268
  }
36016
36269
  }
36017
36270
  var _agentStandardSeam = {
36018
36271
  isLocalSession: () => isLocalSession(),
36019
- markerPath: (sessionId) => path69.join(os49.homedir(), ".codeam", "agent-standard", `${sessionId}.done`),
36020
- exists: (p2) => fs58.existsSync(p2),
36272
+ markerPath: (sessionId) => path70.join(os49.homedir(), ".codeam", "agent-standard", `${sessionId}.done`),
36273
+ exists: (p2) => fs59.existsSync(p2),
36021
36274
  write: (p2) => {
36022
- fs58.mkdirSync(path69.dirname(p2), { recursive: true });
36023
- fs58.writeFileSync(p2, "");
36275
+ fs59.mkdirSync(path70.dirname(p2), { recursive: true });
36276
+ fs59.writeFileSync(p2, "");
36024
36277
  }
36025
36278
  };
36026
36279
  function isClaude(agent) {
@@ -36713,15 +36966,15 @@ function withholdTrailingPartialFenceMarker(text) {
36713
36966
 
36714
36967
  // src/agents/acp/onboarding.ts
36715
36968
  var import_child_process28 = require("child_process");
36716
- var fs59 = __toESM(require("fs"));
36969
+ var fs60 = __toESM(require("fs"));
36717
36970
  var os50 = __toESM(require("os"));
36718
- var path70 = __toESM(require("path"));
36971
+ var path71 = __toESM(require("path"));
36719
36972
  var _onboardingSeam = {
36720
- markerPath: (sessionId) => path70.join(os50.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
36721
- exists: (p2) => fs59.existsSync(p2),
36973
+ markerPath: (sessionId) => path71.join(os50.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
36974
+ exists: (p2) => fs60.existsSync(p2),
36722
36975
  write: (p2) => {
36723
- fs59.mkdirSync(path70.dirname(p2), { recursive: true });
36724
- fs59.writeFileSync(p2, "");
36976
+ fs60.mkdirSync(path71.dirname(p2), { recursive: true });
36977
+ fs60.writeFileSync(p2, "");
36725
36978
  },
36726
36979
  disabled: () => {
36727
36980
  const v = process.env.CODEAM_ONBOARDING_DISABLED;
@@ -36758,7 +37011,7 @@ function resolveRepoName(cwd) {
36758
37011
  if (name) return name;
36759
37012
  }
36760
37013
  }
36761
- const base = path70.basename(cwd || "");
37014
+ const base = path71.basename(cwd || "");
36762
37015
  if (base && !isUuid(base)) return base;
36763
37016
  return "this project";
36764
37017
  }
@@ -37150,13 +37403,13 @@ var import_crypto4 = require("crypto");
37150
37403
 
37151
37404
  // src/services/turn-files/git-changeset.ts
37152
37405
  var import_child_process29 = require("child_process");
37153
- var fs61 = __toESM(require("fs/promises"));
37154
- var path72 = __toESM(require("path"));
37406
+ var fs62 = __toESM(require("fs/promises"));
37407
+ var path73 = __toESM(require("path"));
37155
37408
 
37156
37409
  // src/services/turn-files/review-ignore.ts
37157
37410
  var import_ignore2 = __toESM(require("ignore"));
37158
- var fs60 = __toESM(require("fs"));
37159
- var path71 = __toESM(require("path"));
37411
+ var fs61 = __toESM(require("fs"));
37412
+ var path72 = __toESM(require("path"));
37160
37413
  var CURATED_REVIEW_IGNORE = [
37161
37414
  // Google Cloud SDK (the incident) — installs a huge python tree.
37162
37415
  "google-cloud-sdk/",
@@ -37195,7 +37448,7 @@ var CURATED_REVIEW_IGNORE = [
37195
37448
  function makeReviewIgnore(repoRoot) {
37196
37449
  const ig = (0, import_ignore2.default)().add(CURATED_REVIEW_IGNORE);
37197
37450
  try {
37198
- const custom = fs60.readFileSync(path71.join(repoRoot, ".codeam", "reviewignore"), "utf8");
37451
+ const custom = fs61.readFileSync(path72.join(repoRoot, ".codeam", "reviewignore"), "utf8");
37199
37452
  ig.add(custom);
37200
37453
  } catch {
37201
37454
  }
@@ -37240,7 +37493,7 @@ async function collectRepoChangeset(opts) {
37240
37493
  let stats;
37241
37494
  if (!truncated && row.fileStatus === "added" && numstatEntry === void 0) {
37242
37495
  const lineCount = await readUntrackedLineCount(
37243
- path72.join(opts.repoRoot, row.filePath)
37496
+ path73.join(opts.repoRoot, row.filePath)
37244
37497
  );
37245
37498
  stats = { added: lineCount, removed: 0 };
37246
37499
  } else {
@@ -37271,7 +37524,7 @@ function readUntrackedLineCount(absPath) {
37271
37524
  }
37272
37525
  async function defaultReadUntrackedLineCount(absPath) {
37273
37526
  try {
37274
- const content = await fs61.readFile(absPath, "utf8");
37527
+ const content = await fs62.readFile(absPath, "utf8");
37275
37528
  let count = 0;
37276
37529
  let pos = -1;
37277
37530
  while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
@@ -37363,7 +37616,7 @@ function defaultRunGit(cwd, args2) {
37363
37616
  });
37364
37617
  }
37365
37618
  async function discoverRepos(workingDir, maxDepth = 4) {
37366
- const fs80 = await import("fs/promises");
37619
+ const fs81 = await import("fs/promises");
37367
37620
  const out2 = [];
37368
37621
  await walk(workingDir, 0);
37369
37622
  return out2;
@@ -37371,7 +37624,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
37371
37624
  if (depth > maxDepth) return;
37372
37625
  let entries = [];
37373
37626
  try {
37374
- const dirents = await fs80.readdir(dir, { withFileTypes: true });
37627
+ const dirents = await fs81.readdir(dir, { withFileTypes: true });
37375
37628
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
37376
37629
  } catch {
37377
37630
  return;
@@ -37382,8 +37635,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
37382
37635
  if (hasGit) {
37383
37636
  out2.push({
37384
37637
  repoRoot: dir,
37385
- repoPath: path72.relative(workingDir, dir),
37386
- repoName: path72.basename(dir)
37638
+ repoPath: path73.relative(workingDir, dir),
37639
+ repoName: path73.basename(dir)
37387
37640
  });
37388
37641
  return;
37389
37642
  }
@@ -37391,14 +37644,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
37391
37644
  if (!entry.isDirectory) continue;
37392
37645
  if (entry.name === "node_modules") continue;
37393
37646
  if (entry.name === "dist" || entry.name === "build") continue;
37394
- await walk(path72.join(dir, entry.name), depth + 1);
37647
+ await walk(path73.join(dir, entry.name), depth + 1);
37395
37648
  }
37396
37649
  }
37397
37650
  }
37398
37651
 
37399
37652
  // src/services/turn-files/files-outbox.ts
37400
- var fs62 = __toESM(require("fs/promises"));
37401
- var path73 = __toESM(require("path"));
37653
+ var fs63 = __toESM(require("fs/promises"));
37654
+ var path74 = __toESM(require("path"));
37402
37655
  var import_os12 = require("os");
37403
37656
  var HOME_OUTBOX_DIR = ".codeam/outbox";
37404
37657
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -37431,16 +37684,16 @@ var FilesOutbox = class {
37431
37684
  backoffIndex = 0;
37432
37685
  stopped = false;
37433
37686
  constructor(opts) {
37434
- const base = opts.baseDir ?? path73.join(homeDir(), HOME_OUTBOX_DIR);
37435
- this.filePath = path73.join(base, `${opts.sessionId}.jsonl`);
37687
+ const base = opts.baseDir ?? path74.join(homeDir(), HOME_OUTBOX_DIR);
37688
+ this.filePath = path74.join(base, `${opts.sessionId}.jsonl`);
37436
37689
  this.post = opts.post;
37437
37690
  this.autoSchedule = opts.autoSchedule !== false;
37438
37691
  }
37439
37692
  /** Persist the entry to disk and trigger a flush. Returns once the
37440
37693
  * line is durable on disk (not once the POST succeeds). */
37441
37694
  async enqueue(entry) {
37442
- await fs62.mkdir(path73.dirname(this.filePath), { recursive: true });
37443
- await fs62.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
37695
+ await fs63.mkdir(path74.dirname(this.filePath), { recursive: true });
37696
+ await fs63.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
37444
37697
  this.backoffIndex = 0;
37445
37698
  if (this.autoSchedule) this.scheduleFlush(0);
37446
37699
  }
@@ -37531,7 +37784,7 @@ var FilesOutbox = class {
37531
37784
  async readAll() {
37532
37785
  let raw = "";
37533
37786
  try {
37534
- raw = await fs62.readFile(this.filePath, "utf8");
37787
+ raw = await fs63.readFile(this.filePath, "utf8");
37535
37788
  } catch {
37536
37789
  return [];
37537
37790
  }
@@ -37555,12 +37808,12 @@ var FilesOutbox = class {
37555
37808
  async rewrite(entries) {
37556
37809
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
37557
37810
  if (entries.length === 0) {
37558
- await fs62.unlink(this.filePath).catch(() => void 0);
37811
+ await fs63.unlink(this.filePath).catch(() => void 0);
37559
37812
  return;
37560
37813
  }
37561
37814
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
37562
- await fs62.writeFile(tmpPath, payload, "utf8");
37563
- await fs62.rename(tmpPath, this.filePath);
37815
+ await fs63.writeFile(tmpPath, payload, "utf8");
37816
+ await fs63.rename(tmpPath, this.filePath);
37564
37817
  }
37565
37818
  };
37566
37819
  function applyJitter(ms) {
@@ -38108,8 +38361,8 @@ async function postCredentialSync(opts, fetchImpl = fetch) {
38108
38361
 
38109
38362
  // src/packs/gates.ts
38110
38363
  var import_node_child_process22 = require("child_process");
38111
- var fs63 = __toESM(require("fs"));
38112
- var path74 = __toESM(require("path"));
38364
+ var fs64 = __toESM(require("fs"));
38365
+ var path75 = __toESM(require("path"));
38113
38366
  var defaultCommandRunner = (file, args2, cwd, timeoutMs, env) => new Promise((resolve12) => {
38114
38367
  (0, import_node_child_process22.execFile)(
38115
38368
  file,
@@ -38159,7 +38412,7 @@ async function changedFiles(run, cwd, from, to) {
38159
38412
  }
38160
38413
  function readWorkspaceFile(cwd, relPath) {
38161
38414
  try {
38162
- return fs63.readFileSync(path74.join(cwd, relPath), "utf8");
38415
+ return fs64.readFileSync(path75.join(cwd, relPath), "utf8");
38163
38416
  } catch {
38164
38417
  return null;
38165
38418
  }
@@ -38168,14 +38421,14 @@ var NO_TEST_PLACEHOLDER = 'echo "Error: no test specified"';
38168
38421
  var CHECKS_TIMEOUT_MS = 5 * 6e4;
38169
38422
  function detectChecksCommand(cwd) {
38170
38423
  try {
38171
- const cfg = JSON.parse(fs63.readFileSync(path74.join(cwd, ".codeam", "pack.json"), "utf8"));
38424
+ const cfg = JSON.parse(fs64.readFileSync(path75.join(cwd, ".codeam", "pack.json"), "utf8"));
38172
38425
  if (typeof cfg.checksCommand === "string" && cfg.checksCommand.trim().length > 0) {
38173
38426
  return cfg.checksCommand.trim();
38174
38427
  }
38175
38428
  } catch {
38176
38429
  }
38177
38430
  try {
38178
- const pkg = JSON.parse(fs63.readFileSync(path74.join(cwd, "package.json"), "utf8"));
38431
+ const pkg = JSON.parse(fs64.readFileSync(path75.join(cwd, "package.json"), "utf8"));
38179
38432
  const test = pkg.scripts?.test;
38180
38433
  if (typeof test === "string" && test.trim().length > 0 && !test.includes(NO_TEST_PLACEHOLDER)) {
38181
38434
  return "npm test";
@@ -38193,39 +38446,39 @@ ${res.stderr}`.trim();
38193
38446
  }
38194
38447
 
38195
38448
  // src/packs/run-store.ts
38196
- var fs64 = __toESM(require("fs"));
38197
- var path75 = __toESM(require("path"));
38449
+ var fs65 = __toESM(require("fs"));
38450
+ var path76 = __toESM(require("path"));
38198
38451
  var crypto5 = __toESM(require("crypto"));
38199
38452
  function packsDir(cwd) {
38200
- return path75.join(cwd, ".codeam", "packs");
38453
+ return path76.join(cwd, ".codeam", "packs");
38201
38454
  }
38202
38455
  function runDir(cwd, runId) {
38203
- return path75.join(packsDir(cwd), runId);
38456
+ return path76.join(packsDir(cwd), runId);
38204
38457
  }
38205
38458
  function newRunId() {
38206
38459
  return `pk_${Date.now().toString(36)}_${crypto5.randomBytes(4).toString("hex")}`;
38207
38460
  }
38208
38461
  function writeJsonAtomic(file, value) {
38209
- fs64.mkdirSync(path75.dirname(file), { recursive: true });
38462
+ fs65.mkdirSync(path76.dirname(file), { recursive: true });
38210
38463
  const tmp = `${file}.tmp`;
38211
- fs64.writeFileSync(tmp, JSON.stringify(value, null, 2));
38212
- fs64.renameSync(tmp, file);
38464
+ fs65.writeFileSync(tmp, JSON.stringify(value, null, 2));
38465
+ fs65.renameSync(tmp, file);
38213
38466
  }
38214
38467
  function saveRun(cwd, state) {
38215
- writeJsonAtomic(path75.join(runDir(cwd, state.runId), "run.json"), state);
38468
+ writeJsonAtomic(path76.join(runDir(cwd, state.runId), "run.json"), state);
38216
38469
  }
38217
38470
  function saveStageHandoff(cwd, runId, stageIndex, role, handoff) {
38218
38471
  const name = `${String(stageIndex + 1).padStart(2, "0")}-${role}.json`;
38219
- writeJsonAtomic(path75.join(runDir(cwd, runId), name), handoff);
38472
+ writeJsonAtomic(path76.join(runDir(cwd, runId), name), handoff);
38220
38473
  }
38221
38474
  function loadLatestRun(cwd) {
38222
38475
  try {
38223
38476
  const dir = packsDir(cwd);
38224
- const entries = fs64.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
38477
+ const entries = fs65.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
38225
38478
  for (let i = entries.length - 1; i >= 0; i--) {
38226
- const file = path75.join(dir, entries[i], "run.json");
38479
+ const file = path76.join(dir, entries[i], "run.json");
38227
38480
  try {
38228
- const parsed = JSON.parse(fs64.readFileSync(file, "utf8"));
38481
+ const parsed = JSON.parse(fs65.readFileSync(file, "utf8"));
38229
38482
  if (parsed && typeof parsed.runId === "string") return parsed;
38230
38483
  } catch {
38231
38484
  }
@@ -38236,17 +38489,17 @@ function loadLatestRun(cwd) {
38236
38489
  }
38237
38490
  function ensureLedgerIgnored(cwd) {
38238
38491
  try {
38239
- const gitDir = path75.join(cwd, ".git");
38240
- if (!fs64.existsSync(gitDir)) return;
38241
- const exclude = path75.join(gitDir, "info", "exclude");
38492
+ const gitDir = path76.join(cwd, ".git");
38493
+ if (!fs65.existsSync(gitDir)) return;
38494
+ const exclude = path76.join(gitDir, "info", "exclude");
38242
38495
  let existing = "";
38243
38496
  try {
38244
- existing = fs64.readFileSync(exclude, "utf8");
38497
+ existing = fs65.readFileSync(exclude, "utf8");
38245
38498
  } catch {
38246
38499
  }
38247
38500
  if (existing.includes(".codeam/packs/")) return;
38248
- fs64.mkdirSync(path75.dirname(exclude), { recursive: true });
38249
- fs64.writeFileSync(exclude, `${existing.trimEnd()}
38501
+ fs65.mkdirSync(path76.dirname(exclude), { recursive: true });
38502
+ fs65.writeFileSync(exclude, `${existing.trimEnd()}
38250
38503
  .codeam/packs/
38251
38504
  `.trimStart());
38252
38505
  } catch {
@@ -39226,8 +39479,175 @@ async function mcpRouter() {
39226
39479
  });
39227
39480
  }
39228
39481
 
39482
+ // src/commands/preview-mcp.ts
39483
+ var PREVIEW_MCP_SERVER_NAME = "codeagent_preview";
39484
+ var PREVIEW_IPC_URL_ENV = "CODEAM_PREVIEW_IPC_URL";
39485
+ var PREVIEW_IPC_TOKEN_ENV = "CODEAM_PREVIEW_IPC_TOKEN";
39486
+ var START_TIMEOUT_MS = 27e4;
39487
+ var SHORT_TIMEOUT_MS = 2e4;
39488
+ var PREVIEW_TOOLS = [
39489
+ {
39490
+ name: "start_preview",
39491
+ description: "Open this project's live Preview in the user's CodeAgent app \u2014 the same thing as their Preview button: it installs dependencies if needed, starts the dev server, publishes it on a public URL and switches the user's screen to it. Use it after you change anything visual (UI, styles, layout, copy) so you and the user can check the result, or whenever the user asks to see the app. Returns the public URL (you can curl it) or the exact error. Reuses a preview that is already running. Usually leave the arguments out: the project is detected automatically. Pass command/args/port only if you know the exact dev command.",
39492
+ inputSchema: {
39493
+ type: "object",
39494
+ properties: {
39495
+ command: { type: "string", description: 'Dev server executable, e.g. "npm". Optional.' },
39496
+ args: { type: "array", items: { type: "string" }, description: 'e.g. ["run","dev"]. Optional.' },
39497
+ port: { type: "number", description: "Port the dev server listens on. Required with command." },
39498
+ framework: { type: "string", description: 'Label shown to the user, e.g. "next". Optional.' }
39499
+ },
39500
+ additionalProperties: false
39501
+ }
39502
+ },
39503
+ {
39504
+ name: "preview_status",
39505
+ description: "Current state of the Preview: running (with its URL), starting, error (with the reason) or idle. Use it when start_preview answered that the preview is still starting.",
39506
+ inputSchema: { type: "object", properties: {}, additionalProperties: false }
39507
+ },
39508
+ {
39509
+ name: "highlight_element",
39510
+ description: 'Point at an element in the running Preview: the user sees your cursor move to it and a labelled box drawn around it, scrolled into view. Use it to show the user exactly what you changed or what you are talking about ("this button", "the header spacing"). Takes a CSS selector (prefer ids, data-testid or specific classes you saw in the code). Several calls add several marks; clear_highlights removes them.',
39511
+ inputSchema: {
39512
+ type: "object",
39513
+ properties: {
39514
+ selector: { type: "string", description: 'CSS selector, e.g. "#checkout" or "[data-testid=hero-cta]".' },
39515
+ label: { type: "string", description: 'Short caption on the mark, e.g. "New CTA". Optional.' }
39516
+ },
39517
+ required: ["selector"],
39518
+ additionalProperties: false
39519
+ }
39520
+ },
39521
+ {
39522
+ name: "clear_highlights",
39523
+ description: "Remove every mark you drew in the Preview with highlight_element.",
39524
+ inputSchema: { type: "object", properties: {}, additionalProperties: false }
39525
+ },
39526
+ {
39527
+ name: "stop_preview",
39528
+ description: "Stop the Preview (dev server + public URL). Only when the user asks, or to restart it cleanly.",
39529
+ inputSchema: { type: "object", properties: {}, additionalProperties: false }
39530
+ }
39531
+ ];
39532
+ function previewMcpServer(bridge) {
39533
+ if (!bridge) return null;
39534
+ return {
39535
+ name: PREVIEW_MCP_SERVER_NAME,
39536
+ // Same runtime + entrypoint as this CLI — never trust the agent's PATH.
39537
+ command: process.execPath,
39538
+ args: [process.argv[1], "preview-mcp"],
39539
+ env: [
39540
+ { name: PREVIEW_IPC_URL_ENV, value: bridge.url },
39541
+ { name: PREVIEW_IPC_TOKEN_ENV, value: bridge.token }
39542
+ ]
39543
+ };
39544
+ }
39545
+ function httpCall(baseUrl, token) {
39546
+ return async (path96, method, body, timeoutMs) => {
39547
+ const ac = new AbortController();
39548
+ const timer = setTimeout(() => ac.abort(), timeoutMs);
39549
+ try {
39550
+ const res = await fetch(`${baseUrl}${path96}`, {
39551
+ method,
39552
+ headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
39553
+ ...method === "POST" ? { body: JSON.stringify(body ?? {}) } : {},
39554
+ signal: ac.signal
39555
+ });
39556
+ return await res.json();
39557
+ } finally {
39558
+ clearTimeout(timer);
39559
+ }
39560
+ };
39561
+ }
39562
+ async function runPreviewTool(name, args2, call) {
39563
+ switch (name) {
39564
+ case "start_preview":
39565
+ return describeResult(await call("/preview/start", "POST", args2, START_TIMEOUT_MS));
39566
+ case "preview_status":
39567
+ return describeResult(await call("/preview/status", "GET", void 0, SHORT_TIMEOUT_MS));
39568
+ case "highlight_element":
39569
+ return describeAck(await call("/preview/highlight", "POST", args2, SHORT_TIMEOUT_MS));
39570
+ case "clear_highlights":
39571
+ return describeAck(await call("/preview/highlight", "POST", { clear: true }, SHORT_TIMEOUT_MS));
39572
+ case "stop_preview":
39573
+ return describeAck(await call("/preview/stop", "POST", {}, SHORT_TIMEOUT_MS));
39574
+ default:
39575
+ return { text: `Unknown tool: ${name}`, isError: true };
39576
+ }
39577
+ }
39578
+ function describeResult(raw) {
39579
+ const r = raw && typeof raw === "object" ? raw : {};
39580
+ switch (r.status) {
39581
+ case "running": {
39582
+ const inspector = r.inspector ? " You can point at elements with highlight_element." : " (No element highlighting for this framework.)";
39583
+ return {
39584
+ text: `Preview ${r.reused ? "already running" : "is live"}: ${String(r.url)} (${String(r.framework)}). The user's app is showing it now.${inspector}`,
39585
+ isError: false
39586
+ };
39587
+ }
39588
+ case "starting":
39589
+ return { text: String(r.message ?? "The preview is starting."), isError: false };
39590
+ case "idle":
39591
+ return { text: "No preview is running.", isError: false };
39592
+ case "error":
39593
+ return {
39594
+ text: `Preview failed at ${String(r.stage)}: ${String(r.message)}`,
39595
+ isError: true
39596
+ };
39597
+ default:
39598
+ return { text: `Unexpected answer from the preview bridge: ${JSON.stringify(raw)}`, isError: true };
39599
+ }
39600
+ }
39601
+ function describeAck(raw) {
39602
+ const r = raw && typeof raw === "object" ? raw : {};
39603
+ return { text: String(r.message ?? r.error ?? "done"), isError: r.ok !== true };
39604
+ }
39605
+ async function previewMcp() {
39606
+ const url2 = process.env[PREVIEW_IPC_URL_ENV];
39607
+ const token = process.env[PREVIEW_IPC_TOKEN_ENV];
39608
+ const { Server } = await import("@modelcontextprotocol/sdk/server/index.js");
39609
+ const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
39610
+ const { ListToolsRequestSchema, CallToolRequestSchema } = await import("@modelcontextprotocol/sdk/types.js");
39611
+ const call = url2 && token ? httpCall(url2, token) : null;
39612
+ const server = new Server({ name: PREVIEW_MCP_SERVER_NAME, version: "1.0.0" }, { capabilities: { tools: {} } });
39613
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: PREVIEW_TOOLS }));
39614
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
39615
+ if (!call) {
39616
+ return {
39617
+ content: [{ type: "text", text: "Preview is not available in this session." }],
39618
+ isError: true
39619
+ };
39620
+ }
39621
+ try {
39622
+ const { text, isError: isError2 } = await runPreviewTool(
39623
+ req.params.name,
39624
+ req.params.arguments ?? {},
39625
+ call
39626
+ );
39627
+ return { content: [{ type: "text", text }], isError: isError2 };
39628
+ } catch (err) {
39629
+ const aborted = err instanceof Error && err.name === "AbortError";
39630
+ return {
39631
+ content: [
39632
+ {
39633
+ type: "text",
39634
+ text: aborted ? "The preview is taking long \u2014 it keeps going in the background; call preview_status shortly." : `Preview bridge unreachable: ${err instanceof Error ? err.message : String(err)}`
39635
+ }
39636
+ ],
39637
+ isError: !aborted
39638
+ };
39639
+ }
39640
+ });
39641
+ await server.connect(new StdioServerTransport());
39642
+ }
39643
+
39229
39644
  // src/integrations/provision.ts
39230
39645
  function buildMcpServersForStart(ctx) {
39646
+ const servers = buildIntegrationMcpServers(ctx);
39647
+ const preview = previewMcpServer(ctx.preview ?? null);
39648
+ return preview ? [...servers, preview] : servers;
39649
+ }
39650
+ function buildIntegrationMcpServers(ctx) {
39231
39651
  const manifest = readIntegrationsManifest();
39232
39652
  if (!manifest || manifest.integrations.length === 0) return [];
39233
39653
  if (!ctx.pluginAuthToken) {
@@ -39399,6 +39819,299 @@ function mergeWithLocalMcpServers(integrationServers) {
39399
39819
  return merged;
39400
39820
  }
39401
39821
 
39822
+ // src/commands/start/agent-preview-bridge.ts
39823
+ var http11 = __toESM(require("http"));
39824
+ var import_node_crypto10 = require("crypto");
39825
+ var START_WAIT_MS = 24e4;
39826
+ var MAX_SELECTOR = 500;
39827
+ var MAX_LABEL = 80;
39828
+ var AgentPreviewBridge = class {
39829
+ server = null;
39830
+ listening = null;
39831
+ token = (0, import_node_crypto10.randomBytes)(24).toString("hex");
39832
+ ctx = null;
39833
+ /** The bring-up in flight, so two tool calls never start two dev servers. */
39834
+ inflight = null;
39835
+ lastError = null;
39836
+ bound = null;
39837
+ /** Start the loopback server once. `null` when it could not bind — the
39838
+ * preview tools are then simply absent, never a failed session. */
39839
+ listen() {
39840
+ if (this.listening) return this.listening;
39841
+ this.listening = new Promise((resolve12) => {
39842
+ const server = http11.createServer((req, res) => {
39843
+ void this.handle(req, res);
39844
+ });
39845
+ server.on("error", (err) => {
39846
+ log.warn("agent-preview", `bridge failed to listen: ${String(err)}`);
39847
+ resolve12(null);
39848
+ });
39849
+ server.listen(0, "127.0.0.1", () => {
39850
+ const addr = server.address();
39851
+ if (!addr || typeof addr === "string") {
39852
+ resolve12(null);
39853
+ return;
39854
+ }
39855
+ server.unref();
39856
+ this.server = server;
39857
+ this.bound = { url: `http://127.0.0.1:${addr.port}`, token: this.token };
39858
+ resolve12(this.bound);
39859
+ });
39860
+ });
39861
+ return this.listening;
39862
+ }
39863
+ /** The bound address once {@link listen} resolved, else null (sync, for
39864
+ * the MCP list rebuilds that happen mid-session). */
39865
+ address() {
39866
+ return this.bound;
39867
+ }
39868
+ /** Bind the live session. Tool calls before this answer "still starting". */
39869
+ attach(ctx) {
39870
+ this.ctx = ctx;
39871
+ }
39872
+ close() {
39873
+ this.server?.close();
39874
+ this.server = null;
39875
+ }
39876
+ // ─── Operations (public for tests) ─────────────────────────────────────
39877
+ async start(override, waitMs = START_WAIT_MS) {
39878
+ const ctx = this.ctx;
39879
+ if (!ctx?.pluginAuthToken) {
39880
+ return {
39881
+ status: "error",
39882
+ stage: "session",
39883
+ message: "The session is still starting (or has no pairing token) \u2014 try again in a few seconds."
39884
+ };
39885
+ }
39886
+ if (!this.inflight) {
39887
+ const run = this.launch(ctx, ctx.pluginAuthToken, override);
39888
+ this.inflight = run;
39889
+ void run.finally(() => {
39890
+ if (this.inflight === run) this.inflight = null;
39891
+ });
39892
+ }
39893
+ const inflight = this.inflight;
39894
+ let timer;
39895
+ const pending = new Promise((resolve12) => {
39896
+ timer = setTimeout(
39897
+ () => resolve12({
39898
+ status: "starting",
39899
+ message: "The preview is still coming up (dependencies or a slow dev server). It keeps going in the background \u2014 call preview_status in a minute."
39900
+ }),
39901
+ waitMs
39902
+ );
39903
+ timer.unref?.();
39904
+ });
39905
+ try {
39906
+ return await Promise.race([inflight, pending]);
39907
+ } finally {
39908
+ if (timer) clearTimeout(timer);
39909
+ }
39910
+ }
39911
+ status() {
39912
+ const ctx = this.ctx;
39913
+ if (!ctx) return { status: "idle" };
39914
+ const active2 = serving(ctx.sessionId);
39915
+ if (active2) return running(active2, true);
39916
+ if (this.inflight) return { status: "starting", message: "The preview is starting." };
39917
+ if (this.lastError) return { status: "error", ...this.lastError };
39918
+ return { status: "idle" };
39919
+ }
39920
+ async highlight(input) {
39921
+ const ctx = this.ctx;
39922
+ if (!ctx?.pluginAuthToken) return { ok: false, message: "The session is still starting." };
39923
+ const active2 = serving(ctx.sessionId);
39924
+ if (!active2) {
39925
+ return { ok: false, message: "No preview is running \u2014 call start_preview first." };
39926
+ }
39927
+ if (!active2.inspector) {
39928
+ return {
39929
+ ok: false,
39930
+ message: `Element highlighting needs the web inspector, which ${active2.framework} previews don't have.`
39931
+ };
39932
+ }
39933
+ let payload;
39934
+ if (input.clear === true) {
39935
+ payload = { clear: true };
39936
+ } else {
39937
+ const selector = typeof input.selector === "string" ? input.selector.trim() : "";
39938
+ if (!selector || selector.length > MAX_SELECTOR) {
39939
+ return { ok: false, message: `selector must be a CSS selector of 1-${MAX_SELECTOR} characters.` };
39940
+ }
39941
+ const label = typeof input.label === "string" ? input.label.trim().slice(0, MAX_LABEL) : "";
39942
+ payload = label ? { selector, label } : { selector };
39943
+ }
39944
+ const res = await postPreviewEvent({
39945
+ sessionId: ctx.sessionId,
39946
+ pluginId: ctx.pluginId,
39947
+ pluginAuthToken: ctx.pluginAuthToken,
39948
+ type: USER_EVENTS.PREVIEW_AGENT_HIGHLIGHT,
39949
+ payload
39950
+ });
39951
+ if (!res.ok) {
39952
+ return { ok: false, message: `Could not reach the app (${res.status}): ${res.message}` };
39953
+ }
39954
+ return {
39955
+ ok: true,
39956
+ message: payload.clear === true ? "Cleared your marks from the preview." : `Marked ${String(payload.selector)} in the user's preview. If the selector matches nothing, no mark appears.`
39957
+ };
39958
+ }
39959
+ async stop() {
39960
+ const ctx = this.ctx;
39961
+ if (!ctx?.pluginAuthToken) return { ok: false, message: "The session is still starting." };
39962
+ if (!activePreviews.has(ctx.sessionId)) return { ok: true, message: "No preview was running." };
39963
+ await killPreview(ctx.sessionId);
39964
+ resetBuildHealState(ctx.sessionId);
39965
+ await postPreviewEvent({
39966
+ sessionId: ctx.sessionId,
39967
+ pluginId: ctx.pluginId,
39968
+ pluginAuthToken: ctx.pluginAuthToken,
39969
+ type: USER_EVENTS.PREVIEW_STOPPED,
39970
+ payload: { reason: "user", origin: "agent" }
39971
+ });
39972
+ return { ok: true, message: "Preview stopped." };
39973
+ }
39974
+ // ─── Internals ─────────────────────────────────────────────────────────
39975
+ async launch(ctx, pluginAuthToken, override) {
39976
+ this.lastError = null;
39977
+ const already = serving(ctx.sessionId);
39978
+ if (already) {
39979
+ await postPreviewEvent({
39980
+ sessionId: ctx.sessionId,
39981
+ pluginId: ctx.pluginId,
39982
+ pluginAuthToken,
39983
+ type: USER_EVENTS.PREVIEW_READY,
39984
+ payload: {
39985
+ url: already.url,
39986
+ framework: already.framework,
39987
+ port: already.detection.port,
39988
+ origin: "agent"
39989
+ }
39990
+ });
39991
+ return running(already, true);
39992
+ }
39993
+ void postPreviewEvent({
39994
+ sessionId: ctx.sessionId,
39995
+ pluginId: ctx.pluginId,
39996
+ pluginAuthToken,
39997
+ type: USER_EVENTS.PREVIEW_DETECTION_PENDING,
39998
+ payload: { origin: "agent" }
39999
+ });
40000
+ const detection = (override && detectionFromOverride(override)) ?? await resolvePreviewDetection({ ctx, runtime: ctx.getRuntime(), pluginAuthToken, origin: "agent" });
40001
+ if (!detection) {
40002
+ const err2 = { stage: "detection", message: "Could not work out how to start this project." };
40003
+ this.lastError = err2;
40004
+ return { status: "error", ...err2 };
40005
+ }
40006
+ let failure = null;
40007
+ await startPreviewFromDetection(ctx, detection, pluginAuthToken, {
40008
+ origin: "agent",
40009
+ onEvent: (type, payload) => {
40010
+ if (type === USER_EVENTS.PREVIEW_ERROR) {
40011
+ failure = {
40012
+ stage: String(payload.stage ?? "spawn"),
40013
+ message: String(payload.message ?? "The preview failed to start.")
40014
+ };
40015
+ }
40016
+ }
40017
+ });
40018
+ const up = serving(ctx.sessionId);
40019
+ if (up) return running(up, false);
40020
+ const err = failure ?? { stage: "spawn", message: "The preview did not come up." };
40021
+ this.lastError = err;
40022
+ return { status: "error", ...err };
40023
+ }
40024
+ async handle(req, res) {
40025
+ const reply = (code, body) => {
40026
+ res.writeHead(code, { "content-type": "application/json" });
40027
+ res.end(JSON.stringify(body));
40028
+ };
40029
+ if (!authorized(req.headers.authorization, this.token)) return reply(401, { error: "unauthorized" });
40030
+ try {
40031
+ const body = req.method === "POST" ? await readJson(req) : {};
40032
+ switch (`${req.method} ${req.url}`) {
40033
+ case "POST /preview/start":
40034
+ return reply(200, await this.start(overrideFrom(body)));
40035
+ case "GET /preview/status":
40036
+ return reply(200, this.status());
40037
+ case "POST /preview/highlight":
40038
+ return reply(200, await this.highlight(body));
40039
+ case "POST /preview/stop":
40040
+ return reply(200, await this.stop());
40041
+ default:
40042
+ return reply(404, { error: "not found" });
40043
+ }
40044
+ } catch (err) {
40045
+ log.warn("agent-preview", `bridge request failed: ${String(err)}`);
40046
+ return reply(500, { error: err instanceof Error ? err.message : String(err) });
40047
+ }
40048
+ }
40049
+ };
40050
+ function serving(sessionId) {
40051
+ const active2 = activePreviews.get(sessionId);
40052
+ if (!active2 || active2.devServer && active2.devServer.exitCode !== null) return null;
40053
+ return active2;
40054
+ }
40055
+ function running(active2, reused) {
40056
+ return {
40057
+ status: "running",
40058
+ url: active2.url,
40059
+ framework: active2.framework,
40060
+ ...reused ? { reused: true } : {},
40061
+ inspector: Boolean(active2.inspector)
40062
+ };
40063
+ }
40064
+ function detectionFromOverride(o) {
40065
+ if (!o.command || !Number.isInteger(o.port) || o.port <= 0 || o.port > 65535) return null;
40066
+ return {
40067
+ framework: o.framework?.trim() || "custom",
40068
+ command: o.command,
40069
+ args: Array.isArray(o.args) ? o.args.map(String) : [],
40070
+ port: o.port,
40071
+ // Any Local/ready/listening line; the TCP probe is the real fallback.
40072
+ ready_pattern: o.ready_pattern?.trim() || "(ready|local:|listening|started server|compiled)"
40073
+ };
40074
+ }
40075
+ function overrideFrom(body) {
40076
+ if (typeof body.command !== "string" || typeof body.port !== "number") return void 0;
40077
+ return {
40078
+ command: body.command,
40079
+ args: Array.isArray(body.args) ? body.args.map(String) : void 0,
40080
+ port: body.port,
40081
+ framework: typeof body.framework === "string" ? body.framework : void 0,
40082
+ ready_pattern: typeof body.ready_pattern === "string" ? body.ready_pattern : void 0
40083
+ };
40084
+ }
40085
+ function authorized(header, token) {
40086
+ const presented = Buffer.from((header ?? "").replace(/^Bearer\s+/i, ""));
40087
+ const expected = Buffer.from(token);
40088
+ return presented.length === expected.length && (0, import_node_crypto10.timingSafeEqual)(presented, expected);
40089
+ }
40090
+ function readJson(req) {
40091
+ return new Promise((resolve12, reject) => {
40092
+ let raw = "";
40093
+ req.setEncoding("utf8");
40094
+ req.on("data", (chunk) => {
40095
+ raw += chunk;
40096
+ if (raw.length > 64e3) {
40097
+ reject(new Error("body too large"));
40098
+ req.destroy();
40099
+ }
40100
+ });
40101
+ req.on("end", () => {
40102
+ if (!raw) return resolve12({});
40103
+ try {
40104
+ const parsed = JSON.parse(raw);
40105
+ resolve12(parsed && typeof parsed === "object" ? parsed : {});
40106
+ } catch {
40107
+ reject(new Error("invalid JSON"));
40108
+ }
40109
+ });
40110
+ req.on("error", reject);
40111
+ });
40112
+ }
40113
+ var agentPreviewBridge = new AgentPreviewBridge();
40114
+
39402
40115
  // src/integrations/detect-stack.ts
39403
40116
  var import_node_fs13 = __toESM(require("fs"));
39404
40117
  var import_node_path13 = __toESM(require("path"));
@@ -40539,7 +41252,8 @@ async function integrationsSyncH(ctx) {
40539
41252
  sessionId: opts.sessionId,
40540
41253
  pluginId: opts.pluginId,
40541
41254
  pluginAuthToken: opts.pluginAuthToken,
40542
- pollSecret: opts.pollSecret
41255
+ pollSecret: opts.pollSecret,
41256
+ preview: agentPreviewBridge.address()
40543
41257
  })
40544
41258
  );
40545
41259
  const applied = await client3.reprovisionMcp(servers);
@@ -41176,7 +41890,7 @@ var AcpHistory = class {
41176
41890
  this.summary = trimmed.length > 120 ? trimmed.slice(0, 117) + "\u2026" : trimmed;
41177
41891
  }
41178
41892
  this.messages.push({
41179
- id: (0, import_node_crypto10.randomUUID)(),
41893
+ id: (0, import_node_crypto11.randomUUID)(),
41180
41894
  role: "user",
41181
41895
  text,
41182
41896
  timestamp: Date.now(),
@@ -41192,7 +41906,7 @@ var AcpHistory = class {
41192
41906
  appendAgentReply(text, agentId = this.opts.agent) {
41193
41907
  if (text.length === 0) return;
41194
41908
  this.messages.push({
41195
- id: (0, import_node_crypto10.randomUUID)(),
41909
+ id: (0, import_node_crypto11.randomUUID)(),
41196
41910
  role: "agent",
41197
41911
  text,
41198
41912
  timestamp: Date.now(),
@@ -41723,17 +42437,17 @@ async function runAcpSession(opts) {
41723
42437
  switchCredentialEnv = provisionAgentCredentials(agentId, auth);
41724
42438
  },
41725
42439
  provisionHouseProxy: ({ baseUrl, token, model, managedAgentId }) => {
41726
- const claudeConfigDir = path79.join(
42440
+ const claudeConfigDir = path80.join(
41727
42441
  os53.homedir(),
41728
42442
  ".codeam",
41729
42443
  "house-claude",
41730
42444
  `switch-${opts.pluginId}`
41731
42445
  );
41732
42446
  try {
41733
- fs68.mkdirSync(claudeConfigDir, { recursive: true, mode: 448 });
42447
+ fs69.mkdirSync(claudeConfigDir, { recursive: true, mode: 448 });
41734
42448
  } catch {
41735
42449
  }
41736
- const memoryFile = path79.join(claudeConfigDir, "CLAUDE.md");
42450
+ const memoryFile = path80.join(claudeConfigDir, "CLAUDE.md");
41737
42451
  ensureBeadsWorkflowHint(void 0, memoryFile);
41738
42452
  ensureAgentStandard(void 0, memoryFile);
41739
42453
  const cfg = {
@@ -42956,8 +43670,8 @@ function pickPinnedSession(pinnedId, listSessions2) {
42956
43670
  }
42957
43671
 
42958
43672
  // src/agents/retired-proxy-cleanup.ts
42959
- var fs69 = __toESM(require("fs"));
42960
- var path80 = __toESM(require("path"));
43673
+ var fs70 = __toESM(require("fs"));
43674
+ var path81 = __toESM(require("path"));
42961
43675
  var os54 = __toESM(require("os"));
42962
43676
  var RETIRED_PROXY_RE = /^https?:\/\/(?:127\.0\.0\.1|localhost|\[::1\]):8787(?:[/?#]|$)/i;
42963
43677
  var HEADROOM_CMD_RE = /(^|[\s/"'])headroom(\s|$)/i;
@@ -42969,10 +43683,10 @@ function isHeadroomHook(group) {
42969
43683
  }
42970
43684
  function sanitizeRetiredProxyConfig(homeDir2 = os54.homedir()) {
42971
43685
  const out2 = { inspected: false, changed: false, removed: [] };
42972
- const file = path80.join(homeDir2, ".claude", "settings.json");
43686
+ const file = path81.join(homeDir2, ".claude", "settings.json");
42973
43687
  let parsed;
42974
43688
  try {
42975
- parsed = JSON.parse(fs69.readFileSync(file, "utf8"));
43689
+ parsed = JSON.parse(fs70.readFileSync(file, "utf8"));
42976
43690
  } catch {
42977
43691
  return out2;
42978
43692
  }
@@ -43014,9 +43728,9 @@ function sanitizeRetiredProxyConfig(homeDir2 = os54.homedir()) {
43014
43728
  if (!out2.changed) return out2;
43015
43729
  try {
43016
43730
  const tmp = `${file}.codeam.tmp`;
43017
- fs69.writeFileSync(tmp, `${JSON.stringify(parsed, null, 2)}
43731
+ fs70.writeFileSync(tmp, `${JSON.stringify(parsed, null, 2)}
43018
43732
  `, { mode: 384 });
43019
- fs69.renameSync(tmp, file);
43733
+ fs70.renameSync(tmp, file);
43020
43734
  } catch {
43021
43735
  out2.changed = false;
43022
43736
  }
@@ -43548,7 +44262,7 @@ var AcpDriver = class {
43548
44262
  };
43549
44263
 
43550
44264
  // src/baton/transcript-mirror.ts
43551
- var fs70 = __toESM(require("fs"));
44265
+ var fs71 = __toESM(require("fs"));
43552
44266
  var TranscriptMirror = class {
43553
44267
  constructor(deps) {
43554
44268
  this.deps = deps;
@@ -43642,7 +44356,7 @@ var TranscriptMirror = class {
43642
44356
  }
43643
44357
  };
43644
44358
  function defaultWatch(file, onChange) {
43645
- const w3 = fs70.watch(file, { persistent: false }, () => onChange());
44359
+ const w3 = fs71.watch(file, { persistent: false }, () => onChange());
43646
44360
  return () => w3.close();
43647
44361
  }
43648
44362
 
@@ -43988,16 +44702,16 @@ function keepDeviceAwake(deps = {}) {
43988
44702
  }
43989
44703
 
43990
44704
  // src/agents/claude/onboarding.ts
43991
- var fs71 = __toESM(require("fs"));
44705
+ var fs72 = __toESM(require("fs"));
43992
44706
  var os56 = __toESM(require("os"));
43993
- var path81 = __toESM(require("path"));
44707
+ var path82 = __toESM(require("path"));
43994
44708
  var ONBOARDING_VERSION_SENTINEL = "9999.0.0";
43995
44709
  function ensureClaudeOnboarded(cwd) {
43996
44710
  try {
43997
- const file = path81.join(os56.homedir(), ".claude.json");
44711
+ const file = path82.join(os56.homedir(), ".claude.json");
43998
44712
  let config = {};
43999
44713
  try {
44000
- config = JSON.parse(fs71.readFileSync(file, "utf8"));
44714
+ config = JSON.parse(fs72.readFileSync(file, "utf8"));
44001
44715
  } catch {
44002
44716
  }
44003
44717
  let changed = false;
@@ -44022,8 +44736,8 @@ function ensureClaudeOnboarded(cwd) {
44022
44736
  }
44023
44737
  }
44024
44738
  if (!changed) return;
44025
- fs71.mkdirSync(path81.dirname(file), { recursive: true });
44026
- fs71.writeFileSync(file, JSON.stringify(config, null, 2));
44739
+ fs72.mkdirSync(path82.dirname(file), { recursive: true });
44740
+ fs72.writeFileSync(file, JSON.stringify(config, null, 2));
44027
44741
  log.info(
44028
44742
  "claude",
44029
44743
  `pre-completed Claude onboarding${cwd ? ` + trusted workspace ${cwd}` : ""}`
@@ -44146,12 +44860,20 @@ async function start(requestedAgent, presetSession) {
44146
44860
  agent: isHouseProxyEnv(process.env) ? houseRailWireId(process.env) : session.agent
44147
44861
  });
44148
44862
  }
44863
+ const previewBridge = await agentPreviewBridge.listen();
44864
+ agentPreviewBridge.attach({
44865
+ sessionId: session.id,
44866
+ pluginId,
44867
+ pluginAuthToken: session.pluginAuthToken ?? void 0,
44868
+ getRuntime: () => createInteractiveAgentStrategy(session.agent, createOsStrategy())
44869
+ });
44149
44870
  const mcpServers = mergeWithLocalMcpServers(
44150
44871
  buildMcpServersForStart({
44151
44872
  sessionId: session.id,
44152
44873
  pluginId,
44153
44874
  pluginAuthToken: session.pluginAuthToken ?? void 0,
44154
- pollSecret: session.pollSecret
44875
+ pollSecret: session.pollSecret,
44876
+ preview: previewBridge
44155
44877
  })
44156
44878
  );
44157
44879
  provisionSkillsForStart();
@@ -44792,7 +45514,7 @@ var import_picocolors10 = __toESM(require("picocolors"));
44792
45514
  var import_child_process30 = require("child_process");
44793
45515
  var import_util4 = require("util");
44794
45516
  var import_picocolors8 = __toESM(require("picocolors"));
44795
- var path82 = __toESM(require("path"));
45517
+ var path83 = __toESM(require("path"));
44796
45518
  var execFileP5 = (0, import_util4.promisify)(import_child_process30.execFile);
44797
45519
  var MAX_BUFFER = 8 * 1024 * 1024;
44798
45520
  function resetStdinForChild() {
@@ -45281,7 +46003,7 @@ var GitHubCodespacesProvider = class {
45281
46003
  });
45282
46004
  }
45283
46005
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
45284
- const remoteDir = path82.posix.dirname(remotePath);
46006
+ const remoteDir = path83.posix.dirname(remotePath);
45285
46007
  const parts = [
45286
46008
  `mkdir -p ${shellQuote(remoteDir)}`,
45287
46009
  `cat > ${shellQuote(remotePath)}`
@@ -45351,7 +46073,7 @@ function shellQuote(s) {
45351
46073
  // src/services/providers/gitpod.ts
45352
46074
  var import_child_process31 = require("child_process");
45353
46075
  var import_util5 = require("util");
45354
- var path83 = __toESM(require("path"));
46076
+ var path84 = __toESM(require("path"));
45355
46077
  var import_picocolors9 = __toESM(require("picocolors"));
45356
46078
  var execFileP6 = (0, import_util5.promisify)(import_child_process31.execFile);
45357
46079
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -45591,7 +46313,7 @@ var GitpodProvider = class {
45591
46313
  });
45592
46314
  }
45593
46315
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
45594
- const remoteDir = path83.posix.dirname(remotePath);
46316
+ const remoteDir = path84.posix.dirname(remotePath);
45595
46317
  const parts = [
45596
46318
  `mkdir -p ${shellQuote2(remoteDir)}`,
45597
46319
  `cat > ${shellQuote2(remotePath)}`
@@ -45627,7 +46349,7 @@ function shellQuote2(s) {
45627
46349
  // src/services/providers/gitlab-workspaces.ts
45628
46350
  var import_child_process32 = require("child_process");
45629
46351
  var import_util6 = require("util");
45630
- var path84 = __toESM(require("path"));
46352
+ var path85 = __toESM(require("path"));
45631
46353
  var execFileP7 = (0, import_util6.promisify)(import_child_process32.execFile);
45632
46354
  var MAX_BUFFER3 = 8 * 1024 * 1024;
45633
46355
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -45887,7 +46609,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
45887
46609
  }
45888
46610
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
45889
46611
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
45890
- const remoteDir = path84.posix.dirname(remotePath);
46612
+ const remoteDir = path85.posix.dirname(remotePath);
45891
46613
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
45892
46614
  if (options.mode != null) {
45893
46615
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -45955,7 +46677,7 @@ function shellQuote3(s) {
45955
46677
  // src/services/providers/railway.ts
45956
46678
  var import_child_process33 = require("child_process");
45957
46679
  var import_util7 = require("util");
45958
- var path85 = __toESM(require("path"));
46680
+ var path86 = __toESM(require("path"));
45959
46681
  var execFileP8 = (0, import_util7.promisify)(import_child_process33.execFile);
45960
46682
  var MAX_BUFFER4 = 8 * 1024 * 1024;
45961
46683
  function resetStdinForChild4() {
@@ -46191,7 +46913,7 @@ var RailwayProvider = class {
46191
46913
  if (!projectId || !serviceId) {
46192
46914
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
46193
46915
  }
46194
- const remoteDir = path85.posix.dirname(remotePath);
46916
+ const remoteDir = path86.posix.dirname(remotePath);
46195
46917
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
46196
46918
  if (options.mode != null) {
46197
46919
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -46731,10 +47453,10 @@ async function stopWorkspaceFromLocal(target) {
46731
47453
  }
46732
47454
 
46733
47455
  // src/commands/host/host-client.ts
46734
- var fs72 = __toESM(require("fs"));
47456
+ var fs73 = __toESM(require("fs"));
46735
47457
  var os57 = __toESM(require("os"));
46736
- var path86 = __toESM(require("path"));
46737
- var import_node_crypto11 = require("crypto");
47458
+ var path87 = __toESM(require("path"));
47459
+ var import_node_crypto12 = require("crypto");
46738
47460
  function sampleCpuTimes() {
46739
47461
  let idle = 0;
46740
47462
  let total = 0;
@@ -46781,7 +47503,7 @@ function apiBase() {
46781
47503
  return process.env.CODEAM_API_URL ?? resolveApiBaseUrl();
46782
47504
  }
46783
47505
  function hostIdentityPath() {
46784
- return path86.join(os57.homedir(), ".codeam", "host-agent.json");
47506
+ return path87.join(os57.homedir(), ".codeam", "host-agent.json");
46785
47507
  }
46786
47508
  function collectOsInfo() {
46787
47509
  return {
@@ -46793,7 +47515,7 @@ function collectOsInfo() {
46793
47515
  }
46794
47516
  function loadHostIdentity() {
46795
47517
  try {
46796
- const raw = fs72.readFileSync(hostIdentityPath(), "utf8");
47518
+ const raw = fs73.readFileSync(hostIdentityPath(), "utf8");
46797
47519
  const parsed = JSON.parse(raw);
46798
47520
  if (typeof parsed === "object" && parsed !== null && typeof parsed.hostId === "string" && typeof parsed.hostToken === "string" && typeof parsed.controlPluginId === "string") {
46799
47521
  const p2 = parsed;
@@ -46812,8 +47534,8 @@ function loadHostIdentity() {
46812
47534
  }
46813
47535
  function saveHostIdentity(identity) {
46814
47536
  const file = hostIdentityPath();
46815
- fs72.mkdirSync(path86.dirname(file), { recursive: true, mode: 448 });
46816
- fs72.writeFileSync(file, JSON.stringify(identity, null, 2), {
47537
+ fs73.mkdirSync(path87.dirname(file), { recursive: true, mode: 448 });
47538
+ fs73.writeFileSync(file, JSON.stringify(identity, null, 2), {
46817
47539
  encoding: "utf8",
46818
47540
  mode: 384
46819
47541
  });
@@ -46858,7 +47580,7 @@ function isTerminalEnrollError(err) {
46858
47580
  }
46859
47581
  function deleteHostIdentity() {
46860
47582
  try {
46861
- fs72.rmSync(hostIdentityPath(), { force: true });
47583
+ fs73.rmSync(hostIdentityPath(), { force: true });
46862
47584
  } catch {
46863
47585
  }
46864
47586
  }
@@ -46886,8 +47608,8 @@ function resolveHostLabel(label) {
46886
47608
  return resolved.slice(0, 80);
46887
47609
  }
46888
47610
  async function redeemEnrollToken(token, label) {
46889
- const controlPollSecret = (0, import_node_crypto11.randomBytes)(32).toString("base64url");
46890
- const pluginSecretHash = (0, import_node_crypto11.createHash)("sha256").update(controlPollSecret).digest("hex");
47611
+ const controlPollSecret = (0, import_node_crypto12.randomBytes)(32).toString("base64url");
47612
+ const pluginSecretHash = (0, import_node_crypto12.createHash)("sha256").update(controlPollSecret).digest("hex");
46891
47613
  const data = await postJson("/api/self-hosted/redeem", {
46892
47614
  token,
46893
47615
  label: resolveHostLabel(label),
@@ -47072,8 +47794,8 @@ async function host(args2) {
47072
47794
  // src/commands/host-agent.ts
47073
47795
  var import_node_child_process30 = require("child_process");
47074
47796
  var os62 = __toESM(require("os"));
47075
- var fs77 = __toESM(require("fs"));
47076
- var path91 = __toESM(require("path"));
47797
+ var fs78 = __toESM(require("fs"));
47798
+ var path92 = __toESM(require("path"));
47077
47799
 
47078
47800
  // src/skills/persist-from-payload.ts
47079
47801
  function persistOrClearSkillsFromPayload(skills) {
@@ -47082,13 +47804,13 @@ function persistOrClearSkillsFromPayload(skills) {
47082
47804
  }
47083
47805
 
47084
47806
  // src/commands/host/session-state.ts
47085
- var fs73 = __toESM(require("fs"));
47807
+ var fs74 = __toESM(require("fs"));
47086
47808
  var os58 = __toESM(require("os"));
47087
- var path87 = __toESM(require("path"));
47809
+ var path88 = __toESM(require("path"));
47088
47810
  function hostSessionStatePath(env = process.env) {
47089
47811
  const override = env.CODEAM_HOST_SESSION_STATE_FILE;
47090
47812
  if (override && override.trim()) return override.trim();
47091
- return path87.join(os58.homedir(), ".codeam", "host-agent-sessions.json");
47813
+ return path88.join(os58.homedir(), ".codeam", "host-agent-sessions.json");
47092
47814
  }
47093
47815
  function isRecord5(v) {
47094
47816
  if (typeof v !== "object" || v === null) return false;
@@ -47099,7 +47821,7 @@ function fileSessionChildStore(file = hostSessionStatePath()) {
47099
47821
  return {
47100
47822
  load() {
47101
47823
  try {
47102
- const raw = JSON.parse(fs73.readFileSync(file, "utf8"));
47824
+ const raw = JSON.parse(fs74.readFileSync(file, "utf8"));
47103
47825
  return Array.isArray(raw?.sessions) ? raw.sessions.filter(isRecord5) : [];
47104
47826
  } catch {
47105
47827
  return [];
@@ -47107,18 +47829,18 @@ function fileSessionChildStore(file = hostSessionStatePath()) {
47107
47829
  },
47108
47830
  save(list) {
47109
47831
  try {
47110
- fs73.mkdirSync(path87.dirname(file), { recursive: true, mode: 448 });
47832
+ fs74.mkdirSync(path88.dirname(file), { recursive: true, mode: 448 });
47111
47833
  const tmp = `${file}.${process.pid}.tmp`;
47112
- fs73.writeFileSync(tmp, JSON.stringify({ version: 1, sessions: list }, null, 2), {
47834
+ fs74.writeFileSync(tmp, JSON.stringify({ version: 1, sessions: list }, null, 2), {
47113
47835
  mode: 384
47114
47836
  });
47115
- fs73.renameSync(tmp, file);
47837
+ fs74.renameSync(tmp, file);
47116
47838
  } catch {
47117
47839
  }
47118
47840
  },
47119
47841
  clear() {
47120
47842
  try {
47121
- fs73.rmSync(file, { force: true });
47843
+ fs74.rmSync(file, { force: true });
47122
47844
  } catch {
47123
47845
  }
47124
47846
  }
@@ -47141,9 +47863,9 @@ function planSessionResume(records, max) {
47141
47863
  return { resume: ordered.slice(0, bound), dropped: ordered.slice(bound) };
47142
47864
  }
47143
47865
  function pickSavedSessionForWorkspace(sessions3, cwd) {
47144
- const target = path87.resolve(cwd);
47866
+ const target = path88.resolve(cwd);
47145
47867
  const matches = sessions3.filter(
47146
- (s) => !!s.cwd && path87.resolve(s.cwd) === target && !!s.pluginId && !!s.pollSecret && !!s.agent
47868
+ (s) => !!s.cwd && path88.resolve(s.cwd) === target && !!s.pluginId && !!s.pollSecret && !!s.agent
47147
47869
  );
47148
47870
  if (matches.length === 0) return null;
47149
47871
  matches.sort((a, b) => b.pairedAt - a.pairedAt);
@@ -47151,25 +47873,25 @@ function pickSavedSessionForWorkspace(sessions3, cwd) {
47151
47873
  }
47152
47874
 
47153
47875
  // src/commands/host/workspace.ts
47154
- var fs74 = __toESM(require("fs"));
47876
+ var fs75 = __toESM(require("fs"));
47155
47877
  var os59 = __toESM(require("os"));
47156
- var path88 = __toESM(require("path"));
47878
+ var path89 = __toESM(require("path"));
47157
47879
  var import_node_child_process25 = require("child_process");
47158
47880
  var import_node_util5 = require("util");
47159
47881
  var execFileP9 = (0, import_node_util5.promisify)(import_node_child_process25.execFile);
47160
47882
  function isAbsolutePathTarget(target) {
47161
- return path88.isAbsolute(target);
47883
+ return path89.isAbsolute(target);
47162
47884
  }
47163
47885
  function selfHostedWorkspaceRoot() {
47164
- return path88.join(os59.homedir(), ".codeam", "self-hosted");
47886
+ return path89.join(os59.homedir(), ".codeam", "self-hosted");
47165
47887
  }
47166
47888
  function deployIdFromWorkspace(cwd) {
47167
47889
  if (!cwd) return null;
47168
47890
  const root = selfHostedWorkspaceRoot();
47169
- const resolved = path88.resolve(cwd);
47170
- const rel = path88.relative(root, resolved);
47171
- if (!rel || rel.startsWith("..") || path88.isAbsolute(rel)) return null;
47172
- const parts = rel.split(path88.sep).filter(Boolean);
47891
+ const resolved = path89.resolve(cwd);
47892
+ const rel = path89.relative(root, resolved);
47893
+ if (!rel || rel.startsWith("..") || path89.isAbsolute(rel)) return null;
47894
+ const parts = rel.split(path89.sep).filter(Boolean);
47173
47895
  if (parts.length !== 1) return null;
47174
47896
  return parts[0];
47175
47897
  }
@@ -47241,15 +47963,15 @@ async function configureGitCredentials(dest, repoRef, cloneToken, provider = "gi
47241
47963
  const isGitlab = provider === "gitlab";
47242
47964
  if (isGitlab ? !gitlabProjectPath(repoRef.trim()) : !githubOwnerRepo(repoRef.trim())) return;
47243
47965
  if (!cloneToken) return;
47244
- const credFile = path88.join(dest, ".git", "codeam-credentials");
47966
+ const credFile = path89.join(dest, ".git", "codeam-credentials");
47245
47967
  const credLine = isGitlab ? `https://oauth2:${cloneToken}@gitlab.com
47246
47968
  ` : `https://x-access-token:${cloneToken}@github.com
47247
47969
  `;
47248
- fs74.writeFileSync(credFile, credLine, { mode: 384 });
47970
+ fs75.writeFileSync(credFile, credLine, { mode: 384 });
47249
47971
  restrictToOwner(credFile);
47250
47972
  const env = nonInteractiveGitEnv();
47251
47973
  const git2 = (args2) => execFileP9("git", ["-C", dest, ...args2], { timeout: 3e4, env });
47252
- const credFilePosix = credFile.split(path88.sep).join("/");
47974
+ const credFilePosix = credFile.split(path89.sep).join("/");
47253
47975
  await git2(["config", "--local", "--replace-all", "credential.helper", ""]).catch(() => {
47254
47976
  });
47255
47977
  await git2([
@@ -47282,17 +48004,17 @@ function maskToken(text, cloneToken) {
47282
48004
  }
47283
48005
  async function prepareWorkspace(repoOrPath, deployId, cloneToken, provider = "github", branch) {
47284
48006
  if (isAbsolutePathTarget(repoOrPath)) {
47285
- if (!fs74.existsSync(repoOrPath)) {
48007
+ if (!fs75.existsSync(repoOrPath)) {
47286
48008
  throw new Error(`deploy target path does not exist: ${repoOrPath}`);
47287
48009
  }
47288
48010
  return repoOrPath;
47289
48011
  }
47290
- const dest = path88.join(selfHostedWorkspaceRoot(), deployId);
47291
- if (fs74.existsSync(path88.join(dest, ".git"))) {
48012
+ const dest = path89.join(selfHostedWorkspaceRoot(), deployId);
48013
+ if (fs75.existsSync(path89.join(dest, ".git"))) {
47292
48014
  if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken, provider);
47293
48015
  return dest;
47294
48016
  }
47295
- fs74.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
48017
+ fs75.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
47296
48018
  const cloneUrl = repoCloneUrl(repoOrPath, cloneToken, provider);
47297
48019
  const cloneArgs = branch ? ["clone", "--depth", "1", "--branch", branch, cloneUrl, dest] : ["clone", "--depth", "1", cloneUrl, dest];
47298
48020
  try {
@@ -47311,11 +48033,11 @@ async function prepareWorkspace(repoOrPath, deployId, cloneToken, provider = "gi
47311
48033
 
47312
48034
  // src/commands/host/git-tooling.ts
47313
48035
  var import_node_child_process26 = require("child_process");
47314
- var fs75 = __toESM(require("fs"));
48036
+ var fs76 = __toESM(require("fs"));
47315
48037
  var os60 = __toESM(require("os"));
47316
- var path89 = __toESM(require("path"));
48038
+ var path90 = __toESM(require("path"));
47317
48039
  function codeamBinDir() {
47318
- return process.env.CODEAM_BIN_DIR ?? path89.join(os60.homedir(), ".codeam", "bin");
48040
+ return process.env.CODEAM_BIN_DIR ?? path90.join(os60.homedir(), ".codeam", "bin");
47319
48041
  }
47320
48042
  var FALLBACK_GH_VERSION = "2.62.0";
47321
48043
  var RELEASE_API = "https://api.github.com/repos/cli/cli/releases/latest";
@@ -47347,7 +48069,7 @@ async function download(url2, dest) {
47347
48069
  const res = await fetch(url2, { headers: { "User-Agent": "codeam-cli" } });
47348
48070
  if (!res.ok || !res.body) return false;
47349
48071
  const buf = Buffer.from(await res.arrayBuffer());
47350
- fs75.writeFileSync(dest, buf);
48072
+ fs76.writeFileSync(dest, buf);
47351
48073
  return true;
47352
48074
  } catch {
47353
48075
  return false;
@@ -47370,8 +48092,8 @@ async function ensureGhCli(runner, token, deps = {}) {
47370
48092
  const version3 = await resolveVersionFn(token);
47371
48093
  const asset = `gh_${version3}_${osToken}_${arch2}`;
47372
48094
  const url2 = `https://github.com/cli/cli/releases/download/v${version3}/${asset}.${ext}`;
47373
- const tmpRoot = fs75.mkdtempSync(path89.join(os60.tmpdir(), "codeam-gh-"));
47374
- const archive = path89.join(tmpRoot, `${asset}.${ext}`);
48095
+ const tmpRoot = fs76.mkdtempSync(path90.join(os60.tmpdir(), "codeam-gh-"));
48096
+ const archive = path90.join(tmpRoot, `${asset}.${ext}`);
47375
48097
  if (!await downloadFn(url2, archive)) {
47376
48098
  log.warn("host-agent", "gh download failed \u2014 skipping (git pull/push still work via the credential helper)");
47377
48099
  return null;
@@ -47381,16 +48103,16 @@ async function ensureGhCli(runner, token, deps = {}) {
47381
48103
  log.warn("host-agent", `gh archive extraction failed (code=${String(extract.code)}) \u2014 skipping`);
47382
48104
  return null;
47383
48105
  }
47384
- const extractedBin = path89.join(tmpRoot, asset, "bin", binaryName);
47385
- if (!fs75.existsSync(extractedBin)) {
48106
+ const extractedBin = path90.join(tmpRoot, asset, "bin", binaryName);
48107
+ if (!fs76.existsSync(extractedBin)) {
47386
48108
  log.warn("host-agent", "gh binary not found in the extracted archive \u2014 skipping");
47387
48109
  return null;
47388
48110
  }
47389
48111
  const binDir = codeamBinDir();
47390
- fs75.mkdirSync(binDir, { recursive: true });
47391
- const target = path89.join(binDir, binaryName);
47392
- fs75.copyFileSync(extractedBin, target);
47393
- fs75.chmodSync(target, 493);
48112
+ fs76.mkdirSync(binDir, { recursive: true });
48113
+ const target = path90.join(binDir, binaryName);
48114
+ fs76.copyFileSync(extractedBin, target);
48115
+ fs76.chmodSync(target, 493);
47394
48116
  log.info("host-agent", `gh installed to ${target} (v${version3})`);
47395
48117
  return target;
47396
48118
  } catch (e) {
@@ -47427,19 +48149,19 @@ async function ensureGhAuth(runner, ghCmd, token) {
47427
48149
  }
47428
48150
  function ghConfigDir() {
47429
48151
  if (process.env.GH_CONFIG_DIR) return process.env.GH_CONFIG_DIR;
47430
- if (process.env.XDG_CONFIG_HOME) return path89.join(process.env.XDG_CONFIG_HOME, "gh");
48152
+ if (process.env.XDG_CONFIG_HOME) return path90.join(process.env.XDG_CONFIG_HOME, "gh");
47431
48153
  if (process.platform === "win32" && process.env.APPDATA) {
47432
- return path89.join(process.env.APPDATA, "GitHub CLI");
48154
+ return path90.join(process.env.APPDATA, "GitHub CLI");
47433
48155
  }
47434
- return path89.join(os60.homedir(), ".config", "gh");
48156
+ return path90.join(os60.homedir(), ".config", "gh");
47435
48157
  }
47436
48158
  function writeGhHostsToken(token) {
47437
48159
  try {
47438
48160
  const dir = ghConfigDir();
47439
- const file = path89.join(dir, "hosts.yml");
47440
- if (fs75.existsSync(file)) return false;
47441
- fs75.mkdirSync(dir, { recursive: true, mode: 448 });
47442
- fs75.writeFileSync(
48161
+ const file = path90.join(dir, "hosts.yml");
48162
+ if (fs76.existsSync(file)) return false;
48163
+ fs76.mkdirSync(dir, { recursive: true, mode: 448 });
48164
+ fs76.writeFileSync(
47443
48165
  file,
47444
48166
  `github.com:
47445
48167
  oauth_token: ${token}
@@ -47482,8 +48204,8 @@ async function ensureGlabCli(runner, deps = {}) {
47482
48204
  const version3 = await resolveLatestGlabVersion();
47483
48205
  const asset = `glab_${version3}_${osToken}_${arch2}`;
47484
48206
  const url2 = `https://gitlab.com/gitlab-org/cli/-/releases/v${version3}/downloads/${asset}.${ext}`;
47485
- const tmpRoot = fs75.mkdtempSync(path89.join(os60.tmpdir(), "codeam-glab-"));
47486
- const archive = path89.join(tmpRoot, `${asset}.${ext}`);
48207
+ const tmpRoot = fs76.mkdtempSync(path90.join(os60.tmpdir(), "codeam-glab-"));
48208
+ const archive = path90.join(tmpRoot, `${asset}.${ext}`);
47487
48209
  if (!await downloadFn(url2, archive)) {
47488
48210
  log.warn("host-agent", "glab download failed \u2014 skipping (git push/pull still work)");
47489
48211
  return null;
@@ -47494,20 +48216,20 @@ async function ensureGlabCli(runner, deps = {}) {
47494
48216
  return null;
47495
48217
  }
47496
48218
  const candidates = [
47497
- path89.join(tmpRoot, "bin", binaryName),
47498
- path89.join(tmpRoot, asset, "bin", binaryName),
47499
- path89.join(tmpRoot, binaryName)
48219
+ path90.join(tmpRoot, "bin", binaryName),
48220
+ path90.join(tmpRoot, asset, "bin", binaryName),
48221
+ path90.join(tmpRoot, binaryName)
47500
48222
  ];
47501
- const extractedBin = candidates.find((c2) => fs75.existsSync(c2));
48223
+ const extractedBin = candidates.find((c2) => fs76.existsSync(c2));
47502
48224
  if (!extractedBin) {
47503
48225
  log.warn("host-agent", "glab binary not found in the extracted archive \u2014 skipping");
47504
48226
  return null;
47505
48227
  }
47506
48228
  const binDir = codeamBinDir();
47507
- fs75.mkdirSync(binDir, { recursive: true });
47508
- const target = path89.join(binDir, binaryName);
47509
- fs75.copyFileSync(extractedBin, target);
47510
- fs75.chmodSync(target, 493);
48229
+ fs76.mkdirSync(binDir, { recursive: true });
48230
+ const target = path90.join(binDir, binaryName);
48231
+ fs76.copyFileSync(extractedBin, target);
48232
+ fs76.chmodSync(target, 493);
47511
48233
  log.info("host-agent", `glab installed to ${target} (v${version3})`);
47512
48234
  return target;
47513
48235
  } catch (e) {
@@ -47589,9 +48311,9 @@ var defaultGitToolingRunner = {
47589
48311
  var import_node_child_process28 = require("child_process");
47590
48312
 
47591
48313
  // src/lib/updateNotifier.ts
47592
- var fs76 = __toESM(require("fs"));
48314
+ var fs77 = __toESM(require("fs"));
47593
48315
  var os61 = __toESM(require("os"));
47594
- var path90 = __toESM(require("path"));
48316
+ var path91 = __toESM(require("path"));
47595
48317
  var https8 = __toESM(require("https"));
47596
48318
  var import_node_child_process27 = require("child_process");
47597
48319
  var import_picocolors12 = __toESM(require("picocolors"));
@@ -47600,12 +48322,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
47600
48322
  var TTL_MS = 24 * 60 * 60 * 1e3;
47601
48323
  var REQUEST_TIMEOUT_MS = 1500;
47602
48324
  function cachePath() {
47603
- const dir = path90.join(os61.homedir(), ".codeam");
47604
- return path90.join(dir, "update-check.json");
48325
+ const dir = path91.join(os61.homedir(), ".codeam");
48326
+ return path91.join(dir, "update-check.json");
47605
48327
  }
47606
48328
  function readCache() {
47607
48329
  try {
47608
- const raw = fs76.readFileSync(cachePath(), "utf8");
48330
+ const raw = fs77.readFileSync(cachePath(), "utf8");
47609
48331
  const parsed = JSON.parse(raw);
47610
48332
  if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
47611
48333
  return parsed;
@@ -47616,10 +48338,10 @@ function readCache() {
47616
48338
  function writeCache(cache) {
47617
48339
  try {
47618
48340
  const file = cachePath();
47619
- fs76.mkdirSync(path90.dirname(file), { recursive: true });
48341
+ fs77.mkdirSync(path91.dirname(file), { recursive: true });
47620
48342
  const tmp = `${file}.${process.pid}.tmp`;
47621
- fs76.writeFileSync(tmp, JSON.stringify(cache));
47622
- fs76.renameSync(tmp, file);
48343
+ fs77.writeFileSync(tmp, JSON.stringify(cache));
48344
+ fs77.renameSync(tmp, file);
47623
48345
  } catch {
47624
48346
  }
47625
48347
  }
@@ -47693,8 +48415,8 @@ function isLinkedInstall() {
47693
48415
  timeout: 2e3
47694
48416
  }).trim();
47695
48417
  if (!root) return false;
47696
- const pkgPath = path90.join(root, PKG_NAME);
47697
- return fs76.lstatSync(pkgPath).isSymbolicLink();
48418
+ const pkgPath = path91.join(root, PKG_NAME);
48419
+ return fs77.lstatSync(pkgPath).isSymbolicLink();
47698
48420
  } catch {
47699
48421
  return false;
47700
48422
  }
@@ -47730,7 +48452,7 @@ function maybeAutoUpdate(currentVersion, latest) {
47730
48452
  return;
47731
48453
  }
47732
48454
  try {
47733
- fs76.unlinkSync(cachePath());
48455
+ fs77.unlinkSync(cachePath());
47734
48456
  } catch {
47735
48457
  }
47736
48458
  process.stderr.write(` ${import_picocolors12.default.green("\u2713")} Updated. Resuming session...
@@ -47746,7 +48468,7 @@ async function autoUpgradeBeforeCriticalCommand() {
47746
48468
  if (process.env.NODE_ENV === "test") return;
47747
48469
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
47748
48470
  if (process.env.CI) return;
47749
- const current2 = true ? "2.75.23" : null;
48471
+ const current2 = true ? "2.75.26" : null;
47750
48472
  if (!current2) return;
47751
48473
  const cache = readCache();
47752
48474
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -47763,7 +48485,7 @@ function checkForUpdates() {
47763
48485
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
47764
48486
  if (process.env.CI) return;
47765
48487
  if (!process.stdout.isTTY) return;
47766
- const current2 = true ? "2.75.23" : null;
48488
+ const current2 = true ? "2.75.26" : null;
47767
48489
  if (!current2) return;
47768
48490
  const cache = readCache();
47769
48491
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -47786,7 +48508,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
47786
48508
  var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
47787
48509
  var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
47788
48510
  function currentCliVersion() {
47789
- return true ? "2.75.23" : null;
48511
+ return true ? "2.75.26" : null;
47790
48512
  }
47791
48513
  async function installedVersion(deps) {
47792
48514
  const ls = await deps.run(
@@ -48519,13 +49241,13 @@ var HostAgentSupervisor = class {
48519
49241
  const relay = this.relay;
48520
49242
  if (!relay) return;
48521
49243
  const raw = cmd.payload?.path;
48522
- const target = typeof raw === "string" && raw.trim() ? path91.resolve(raw.trim()) : os62.homedir();
49244
+ const target = typeof raw === "string" && raw.trim() ? path92.resolve(raw.trim()) : os62.homedir();
48523
49245
  try {
48524
- const dirents = await fs77.promises.readdir(target, { withFileTypes: true });
49246
+ const dirents = await fs78.promises.readdir(target, { withFileTypes: true });
48525
49247
  const entries = dirents.filter((d3) => !d3.name.startsWith(".")).map((d3) => ({ name: d3.name, isDir: d3.isDirectory() })).sort(
48526
49248
  (a, b) => a.isDir === b.isDir ? a.name.localeCompare(b.name) : a.isDir ? -1 : 1
48527
49249
  );
48528
- const parent = path91.dirname(target);
49250
+ const parent = path92.dirname(target);
48529
49251
  await relay.sendResult(cmd.id, "completed", {
48530
49252
  path: target,
48531
49253
  // null at the filesystem root so the UI can hide the ".." affordance.
@@ -48872,14 +49594,14 @@ var HostAgentSupervisor = class {
48872
49594
  ...buildHouseProxyChildEnv({ baseUrl, token, openRouter: openRouter === true }),
48873
49595
  CODEAM_AUTO_TOKEN: payload.autoPairToken
48874
49596
  };
48875
- const houseConfigDir = path91.join(
49597
+ const houseConfigDir = path92.join(
48876
49598
  os62.homedir(),
48877
49599
  ".codeam",
48878
49600
  "house-claude",
48879
49601
  payload.deployId
48880
49602
  );
48881
49603
  try {
48882
- fs77.mkdirSync(houseConfigDir, { recursive: true, mode: 448 });
49604
+ fs78.mkdirSync(houseConfigDir, { recursive: true, mode: 448 });
48883
49605
  } catch {
48884
49606
  }
48885
49607
  childEnv.CLAUDE_CONFIG_DIR = houseConfigDir;
@@ -48913,13 +49635,13 @@ var HostAgentSupervisor = class {
48913
49635
  if ((payload.repoProvider ?? "github") === "gitlab") {
48914
49636
  const glabCmd = await ensureGlabCli(defaultGitToolingRunner);
48915
49637
  if (glabCmd) {
48916
- childEnv.PATH = `${codeamBinDir()}${path91.delimiter}${childEnv.PATH}`;
49638
+ childEnv.PATH = `${codeamBinDir()}${path92.delimiter}${childEnv.PATH}`;
48917
49639
  await ensureGlabAuth(defaultGitToolingRunner, glabCmd, payload.cloneToken);
48918
49640
  }
48919
49641
  } else {
48920
49642
  const ghCmd = await ensureGhCli(defaultGitToolingRunner, payload.cloneToken);
48921
49643
  if (ghCmd) {
48922
- childEnv.PATH = `${codeamBinDir()}${path91.delimiter}${childEnv.PATH}`;
49644
+ childEnv.PATH = `${codeamBinDir()}${path92.delimiter}${childEnv.PATH}`;
48923
49645
  await ensureGhAuth(defaultGitToolingRunner, ghCmd, payload.cloneToken);
48924
49646
  }
48925
49647
  }
@@ -48947,9 +49669,9 @@ var HostAgentSupervisor = class {
48947
49669
  );
48948
49670
  if (!payload.suppressOnboardingWelcome) {
48949
49671
  try {
48950
- const cfgDir = childEnv.CLAUDE_CONFIG_DIR || path91.join(os62.homedir(), ".claude");
48951
- const projectDir = path91.join(cfgDir, "projects", encodeCwd(cwd));
48952
- const hasPriorConversation = fs77.existsSync(projectDir) && fs77.readdirSync(projectDir).some((f) => f.endsWith(".jsonl"));
49672
+ const cfgDir = childEnv.CLAUDE_CONFIG_DIR || path92.join(os62.homedir(), ".claude");
49673
+ const projectDir = path92.join(cfgDir, "projects", encodeCwd(cwd));
49674
+ const hasPriorConversation = fs78.existsSync(projectDir) && fs78.readdirSync(projectDir).some((f) => f.endsWith(".jsonl"));
48953
49675
  if (hasPriorConversation) {
48954
49676
  childEnv.CODEAM_RESUME_LATEST = "1";
48955
49677
  log.info(
@@ -49100,7 +49822,7 @@ var HostAgentSupervisor = class {
49100
49822
  fallbackResumeTarget() {
49101
49823
  const session = getActiveSession();
49102
49824
  if (!session || !session.pluginId || !session.pollSecret || !session.agent) return null;
49103
- const cwd = session.cwd && fs77.existsSync(session.cwd) ? session.cwd : process.cwd();
49825
+ const cwd = session.cwd && fs78.existsSync(session.cwd) ? session.cwd : process.cwd();
49104
49826
  const deployId = deployIdFromWorkspace(session.cwd) ?? session.id;
49105
49827
  return { deployId, cwd, session };
49106
49828
  }
@@ -49120,7 +49842,7 @@ var HostAgentSupervisor = class {
49120
49842
  if (this.children.has(deployId)) return;
49121
49843
  const st3 = this.resumeStateFor(target);
49122
49844
  try {
49123
- const cwd = fs77.existsSync(target.cwd) ? target.cwd : process.cwd();
49845
+ const cwd = fs78.existsSync(target.cwd) ? target.cwd : process.cwd();
49124
49846
  const proc = this.resumeSpawner(
49125
49847
  { ...readHouseProxyChildEnv(), CODEAM_RESUME_SESSION_ID: session.id },
49126
49848
  cwd
@@ -49338,12 +50060,12 @@ var HostAgentSupervisor = class {
49338
50060
  this.untrackChild(deployId);
49339
50061
  }
49340
50062
  const dirs = [
49341
- path91.join(selfHostedWorkspaceRoot(), deployId),
49342
- path91.join(os62.homedir(), ".codeam", "house-claude", deployId)
50063
+ path92.join(selfHostedWorkspaceRoot(), deployId),
50064
+ path92.join(os62.homedir(), ".codeam", "house-claude", deployId)
49343
50065
  ];
49344
50066
  for (const dir of dirs) {
49345
50067
  try {
49346
- fs77.rmSync(dir, { recursive: true, force: true });
50068
+ fs78.rmSync(dir, { recursive: true, force: true });
49347
50069
  } catch (err) {
49348
50070
  log.warn(
49349
50071
  "host-agent",
@@ -49502,9 +50224,9 @@ async function invite() {
49502
50224
  // src/commands/doctor.ts
49503
50225
  var import_node_dns = require("dns");
49504
50226
  var import_node_util6 = require("util");
49505
- var import_node_crypto12 = require("crypto");
49506
- var fs78 = __toESM(require("fs"));
49507
- var path92 = __toESM(require("path"));
50227
+ var import_node_crypto13 = require("crypto");
50228
+ var fs79 = __toESM(require("fs"));
50229
+ var path93 = __toESM(require("path"));
49508
50230
  var import_picocolors14 = __toESM(require("picocolors"));
49509
50231
  var dnsResolveP = (0, import_node_util6.promisify)(import_node_dns.resolve);
49510
50232
  async function checkDns(apiBase2) {
@@ -49560,13 +50282,13 @@ async function checkHealth(apiBase2) {
49560
50282
  }
49561
50283
  }
49562
50284
  function checkConfigDir() {
49563
- const dir = path92.join(require("os").homedir(), ".codeam");
50285
+ const dir = path93.join(require("os").homedir(), ".codeam");
49564
50286
  try {
49565
- fs78.mkdirSync(dir, { recursive: true, mode: 448 });
49566
- const probe = path92.join(dir, ".doctor-probe");
49567
- fs78.writeFileSync(probe, "ok", { mode: 384 });
49568
- const read = fs78.readFileSync(probe, "utf8");
49569
- fs78.unlinkSync(probe);
50287
+ fs79.mkdirSync(dir, { recursive: true, mode: 448 });
50288
+ const probe = path93.join(dir, ".doctor-probe");
50289
+ fs79.writeFileSync(probe, "ok", { mode: 384 });
50290
+ const read = fs79.readFileSync(probe, "utf8");
50291
+ fs79.unlinkSync(probe);
49570
50292
  if (read !== "ok") throw new Error("write/read round-trip mismatch");
49571
50293
  return {
49572
50294
  id: "config-dir",
@@ -49630,7 +50352,7 @@ function checkNodePty() {
49630
50352
  detail: "not required on this platform"
49631
50353
  };
49632
50354
  }
49633
- const vendoredPath = path92.join(__dirname, "vendor", "node-pty");
50355
+ const vendoredPath = path93.join(__dirname, "vendor", "node-pty");
49634
50356
  for (const target of [vendoredPath, "node-pty"]) {
49635
50357
  try {
49636
50358
  require(target);
@@ -49672,9 +50394,9 @@ function checkChokidar() {
49672
50394
  }
49673
50395
  async function doctor(args2 = []) {
49674
50396
  const json = args2.includes("--json");
49675
- const cliVersion = true ? "2.75.23" : "0.0.0-dev";
50397
+ const cliVersion = true ? "2.75.26" : "0.0.0-dev";
49676
50398
  const apiBase2 = resolveApiBaseUrl();
49677
- const diagnosticId = (0, import_node_crypto12.randomUUID)();
50399
+ const diagnosticId = (0, import_node_crypto13.randomUUID)();
49678
50400
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
49679
50401
  const [dns, health] = await Promise.all([
49680
50402
  checkDns(apiBase2),
@@ -50196,7 +50918,7 @@ async function mcpWarm(argv = [], opts = {}) {
50196
50918
  // src/commands/version.ts
50197
50919
  var import_picocolors15 = __toESM(require("picocolors"));
50198
50920
  function version2() {
50199
- const v = true ? "2.75.23" : "unknown";
50921
+ const v = true ? "2.75.26" : "unknown";
50200
50922
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
50201
50923
  }
50202
50924
 
@@ -50397,6 +51119,9 @@ async function main() {
50397
51119
  if (command === "mcp-run") {
50398
51120
  return mcpRun(args);
50399
51121
  }
51122
+ if (command === "preview-mcp") {
51123
+ return previewMcp();
51124
+ }
50400
51125
  if (command === "mcp-warm") {
50401
51126
  await mcpWarm(args);
50402
51127
  return;