codeam-cli 2.67.3 → 2.67.6

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 +505 -273
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3156,11 +3156,11 @@ function quiet(fn) {
3156
3156
  log.debug(TAG, "ignored sync error", err);
3157
3157
  }
3158
3158
  }
3159
- function rmIfExistsQuiet(path94) {
3159
+ function rmIfExistsQuiet(path95) {
3160
3160
  try {
3161
- fs2.rmSync(path94, { force: true });
3161
+ fs2.rmSync(path95, { force: true });
3162
3162
  } catch (err) {
3163
- log.debug(TAG, `rmIfExists failed for ${path94}`, err);
3163
+ log.debug(TAG, `rmIfExists failed for ${path95}`, err);
3164
3164
  }
3165
3165
  }
3166
3166
  function killQuiet(target, signal = "SIGTERM") {
@@ -3329,9 +3329,9 @@ var _default = makeConfig();
3329
3329
  var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, setDisable1mContext, setSessionAgent, setSquadAuto, getSquadAuto, clearAll, saveCliConfig, loadCliConfig } = _default;
3330
3330
 
3331
3331
  // src/commands/pair-auto.ts
3332
- var fs65 = __toESM(require("fs"));
3332
+ var fs66 = __toESM(require("fs"));
3333
3333
  var os55 = __toESM(require("os"));
3334
- var path71 = __toESM(require("path"));
3334
+ var path72 = __toESM(require("path"));
3335
3335
  var import_crypto4 = require("crypto");
3336
3336
 
3337
3337
  // src/services/telemetry.service.ts
@@ -3367,8 +3367,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
3367
3367
  return decodedFile;
3368
3368
  };
3369
3369
  }
3370
- function normalizeWindowsPath(path94) {
3371
- return path94.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
3370
+ function normalizeWindowsPath(path95) {
3371
+ return path95.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
3372
3372
  }
3373
3373
 
3374
3374
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -5848,9 +5848,9 @@ async function addSourceContext(frames) {
5848
5848
  LRU_FILE_CONTENTS_CACHE.reduce();
5849
5849
  return frames;
5850
5850
  }
5851
- function getContextLinesFromFile(path94, ranges, output) {
5851
+ function getContextLinesFromFile(path95, ranges, output) {
5852
5852
  return new Promise((resolve10) => {
5853
- const stream = (0, import_node_fs.createReadStream)(path94);
5853
+ const stream = (0, import_node_fs.createReadStream)(path95);
5854
5854
  const lineReaded = (0, import_node_readline.createInterface)({
5855
5855
  input: stream
5856
5856
  });
@@ -5865,7 +5865,7 @@ function getContextLinesFromFile(path94, ranges, output) {
5865
5865
  let rangeStart = range[0];
5866
5866
  let rangeEnd = range[1];
5867
5867
  function onStreamError() {
5868
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path94, 1);
5868
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path95, 1);
5869
5869
  lineReaded.close();
5870
5870
  lineReaded.removeAllListeners();
5871
5871
  destroyStreamAndResolve();
@@ -5926,8 +5926,8 @@ function clearLineContext(frame) {
5926
5926
  delete frame.context_line;
5927
5927
  delete frame.post_context;
5928
5928
  }
5929
- function shouldSkipContextLinesForFile(path94) {
5930
- return path94.startsWith("node:") || path94.endsWith(".min.js") || path94.endsWith(".min.cjs") || path94.endsWith(".min.mjs") || path94.startsWith("data:");
5929
+ function shouldSkipContextLinesForFile(path95) {
5930
+ return path95.startsWith("node:") || path95.endsWith(".min.js") || path95.endsWith(".min.cjs") || path95.endsWith(".min.mjs") || path95.startsWith("data:");
5931
5931
  }
5932
5932
  function shouldSkipContextLinesForFrame(frame) {
5933
5933
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -8081,7 +8081,7 @@ function readAnonId() {
8081
8081
  }
8082
8082
  function superProperties() {
8083
8083
  return {
8084
- cliVersion: true ? "2.67.3" : "0.0.0-dev",
8084
+ cliVersion: true ? "2.67.6" : "0.0.0-dev",
8085
8085
  nodeVersion: process.version,
8086
8086
  platform: process.platform,
8087
8087
  arch: process.arch,
@@ -8323,7 +8323,7 @@ var http = __toESM(require("http"));
8323
8323
  // package.json
8324
8324
  var package_default = {
8325
8325
  name: "codeam-cli",
8326
- version: "2.67.3",
8326
+ version: "2.67.6",
8327
8327
  description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
8328
8328
  type: "commonjs",
8329
8329
  main: "dist/index.js",
@@ -9855,7 +9855,7 @@ var CommandRelayService = class _CommandRelayService {
9855
9855
  // fresh + clear the "CLI update available" banner after a self-update
9856
9856
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
9857
9857
  // pair/reconnect). Older backends ignore the extra field.
9858
- ..."2.67.3" ? { ideVersion: "2.67.3" } : {}
9858
+ ..."2.67.6" ? { ideVersion: "2.67.6" } : {}
9859
9859
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
9860
9860
  }
9861
9861
  /**
@@ -11262,9 +11262,9 @@ function closeAllTerminals() {
11262
11262
  }
11263
11263
 
11264
11264
  // src/commands/start/handlers.ts
11265
- var fs64 = __toESM(require("fs"));
11265
+ var fs65 = __toESM(require("fs"));
11266
11266
  var os54 = __toESM(require("os"));
11267
- var path70 = __toESM(require("path"));
11267
+ var path71 = __toESM(require("path"));
11268
11268
  var import_crypto3 = require("crypto");
11269
11269
  var import_child_process27 = require("child_process");
11270
11270
 
@@ -17465,8 +17465,8 @@ function pickLine(obj) {
17465
17465
  function toHunk(raw, groupSeverity) {
17466
17466
  if (!raw || typeof raw !== "object") return null;
17467
17467
  const o = raw;
17468
- const path94 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
17469
- if (!path94) return null;
17468
+ const path95 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
17469
+ if (!path95) return null;
17470
17470
  const message = asString(
17471
17471
  pick(o, [
17472
17472
  "comment",
@@ -17483,7 +17483,7 @@ function toHunk(raw, groupSeverity) {
17483
17483
  const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
17484
17484
  const locObj = pick(o, ["location"]) ?? o;
17485
17485
  return {
17486
- path: path94.trim(),
17486
+ path: path95.trim(),
17487
17487
  line: pickLine(o) ?? pickLine(locObj),
17488
17488
  severity,
17489
17489
  message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
@@ -17566,10 +17566,10 @@ function parsePlain(stdout) {
17566
17566
  for (const line of stdout.split(/\r?\n/)) {
17567
17567
  const m = line.match(HUNK_LINE_RE);
17568
17568
  if (!m) continue;
17569
- const [, path94, lineNo, sevToken, message] = m;
17570
- if (!path94 || !lineNo || !message) continue;
17569
+ const [, path95, lineNo, sevToken, message] = m;
17570
+ if (!path95 || !lineNo || !message) continue;
17571
17571
  hunks.push({
17572
- path: path94.trim(),
17572
+ path: path95.trim(),
17573
17573
  line: Number(lineNo),
17574
17574
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
17575
17575
  message: message.trim().replace(/^[*-]\s+/, "")
@@ -18287,14 +18287,14 @@ function defaultSdkDir() {
18287
18287
  return resolveSdkDirViaRequire();
18288
18288
  }
18289
18289
  function resolveClaudeNativeBinary(deps = {}) {
18290
- const existsSync29 = deps.existsSync ?? import_fs.default.existsSync;
18290
+ const existsSync30 = deps.existsSync ?? import_fs.default.existsSync;
18291
18291
  const platformKey = deps.platformKey ?? currentPlatformKey();
18292
18292
  const sdkDir = deps.sdkDir !== void 0 ? deps.sdkDir : defaultSdkDir();
18293
18293
  if (!sdkDir) return null;
18294
18294
  const scopeDir = import_path4.default.dirname(sdkDir);
18295
18295
  const binName = platformKey.startsWith("win32-") ? "claude.exe" : "claude";
18296
18296
  const candidate = import_path4.default.join(scopeDir, `claude-agent-sdk-${platformKey}`, binName);
18297
- return existsSync29(candidate) ? candidate : null;
18297
+ return existsSync30(candidate) ? candidate : null;
18298
18298
  }
18299
18299
  var realSleep = (ms) => new Promise((resolve10) => setTimeout(resolve10, ms));
18300
18300
  async function waitForClaudeNativeBinary(opts = {}) {
@@ -18376,18 +18376,18 @@ function augmentUserLocalBinPaths(deps = {}) {
18376
18376
  env.PATH = [...additions, ...parts].join(p2.delimiter);
18377
18377
  }
18378
18378
  function resolveCursorAgentBinary(deps = {}) {
18379
- const existsSync29 = deps.existsSync ?? import_fs.default.existsSync;
18379
+ const existsSync30 = deps.existsSync ?? import_fs.default.existsSync;
18380
18380
  const platform3 = deps.platform ?? process.platform;
18381
18381
  const env = deps.env ?? process.env;
18382
18382
  if (platform3 === "win32") {
18383
18383
  const localAppData = env.LOCALAPPDATA;
18384
18384
  if (!localAppData) return null;
18385
18385
  const exe = import_path4.default.win32.join(localAppData, "cursor-agent", "cursor-agent.exe");
18386
- return existsSync29(exe) ? exe : null;
18386
+ return existsSync30(exe) ? exe : null;
18387
18387
  }
18388
18388
  const home = deps.homedir ?? import_os4.default.homedir();
18389
18389
  const unix = import_path4.default.posix.join(home, ".local", "bin", "cursor-agent");
18390
- return existsSync29(unix) ? unix : null;
18390
+ return existsSync30(unix) ? unix : null;
18391
18391
  }
18392
18392
  async function waitForCursorAgent(opts = {}) {
18393
18393
  const timeoutMs = opts.timeoutMs ?? 18e4;
@@ -19743,6 +19743,38 @@ async function linkDryRunPreflight(ctx) {
19743
19743
  process.exit(1);
19744
19744
  }
19745
19745
 
19746
+ // src/services/preview/serialized-emitter.ts
19747
+ function makeSerializedEmitter(post2) {
19748
+ let chain = Promise.resolve();
19749
+ return (args2) => {
19750
+ chain = chain.then(() => post2(args2)).then(
19751
+ () => void 0,
19752
+ () => void 0
19753
+ );
19754
+ void chain;
19755
+ };
19756
+ }
19757
+
19758
+ // src/services/preview/reaffirm.ts
19759
+ var PREVIEW_REAFFIRM_INTERVAL_MS = 5 * 6e4;
19760
+ function makePreviewHeartbeatReaffirm(deps) {
19761
+ const now = deps.now ?? Date.now;
19762
+ const intervalMs = deps.intervalMs ?? PREVIEW_REAFFIRM_INTERVAL_MS;
19763
+ let lastAffirmedAt = null;
19764
+ return ({ firstAfterConnect }) => {
19765
+ const current2 = deps.serving();
19766
+ if (!current2) {
19767
+ lastAffirmedAt = null;
19768
+ return;
19769
+ }
19770
+ const at3 = now();
19771
+ if (!firstAfterConnect && lastAffirmedAt !== null && at3 - lastAffirmedAt < intervalMs) return;
19772
+ lastAffirmedAt = at3;
19773
+ log.trace("preview", `reaffirm: preview sigue sirviendo en ${current2.url}`);
19774
+ deps.emitReady(current2);
19775
+ };
19776
+ }
19777
+
19746
19778
  // src/agents/coderabbit/configure.ts
19747
19779
  var import_node_child_process17 = require("child_process");
19748
19780
  var import_node_fs6 = require("fs");
@@ -22082,7 +22114,7 @@ async function autoUpgradeBeforeCriticalCommand() {
22082
22114
  if (process.env.NODE_ENV === "test") return;
22083
22115
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
22084
22116
  if (process.env.CI) return;
22085
- const current2 = true ? "2.67.3" : null;
22117
+ const current2 = true ? "2.67.6" : null;
22086
22118
  if (!current2) return;
22087
22119
  const cache = readCache();
22088
22120
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -22099,7 +22131,7 @@ function checkForUpdates() {
22099
22131
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
22100
22132
  if (process.env.CI) return;
22101
22133
  if (!process.stdout.isTTY) return;
22102
- const current2 = true ? "2.67.3" : null;
22134
+ const current2 = true ? "2.67.6" : null;
22103
22135
  if (!current2) return;
22104
22136
  const cache = readCache();
22105
22137
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -22122,7 +22154,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
22122
22154
  var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
22123
22155
  var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
22124
22156
  function currentCliVersion() {
22125
- return true ? "2.67.3" : null;
22157
+ return true ? "2.67.6" : null;
22126
22158
  }
22127
22159
  async function installedVersion(deps) {
22128
22160
  const ls = await deps.run(
@@ -23993,7 +24025,7 @@ async function defaultFetchJson(url2) {
23993
24025
  async function readUsageReport(deps = {}) {
23994
24026
  const port = deps.port ?? HEADROOM_PROXY_PORT;
23995
24027
  const base = `http://127.0.0.1:${port}`;
23996
- const get2 = deps.fetchJson ?? ((path94) => defaultFetchJson(`${base}${path94}`));
24028
+ const get2 = deps.fetchJson ?? ((path95) => defaultFetchJson(`${base}${path95}`));
23997
24029
  let history;
23998
24030
  try {
23999
24031
  history = await get2("/stats-history");
@@ -24332,6 +24364,112 @@ async function applyPreviewHostAllow(cwd) {
24332
24364
  }
24333
24365
  }
24334
24366
 
24367
+ // src/services/preview/build-heal.ts
24368
+ var fs52 = __toESM(require("fs"));
24369
+ var path57 = __toESM(require("path"));
24370
+ var BUILD_MARKER_NAME = "BUILD_ID";
24371
+ var DEFAULT_DEBOUNCE_MS = 1500;
24372
+ var DEFAULT_MAX_RESTARTS = 3;
24373
+ function isBuildHealSupported(framework) {
24374
+ return /next/i.test(framework);
24375
+ }
24376
+ function defaultWatchDir(dir, onEvent) {
24377
+ try {
24378
+ const w3 = fs52.watch(dir, { persistent: false }, (_eventType, filename) => onEvent(filename));
24379
+ return () => w3.close();
24380
+ } catch {
24381
+ return null;
24382
+ }
24383
+ }
24384
+ var healRestartCounts = /* @__PURE__ */ new Map();
24385
+ function resetBuildHealState(sessionId) {
24386
+ healRestartCounts.delete(sessionId);
24387
+ }
24388
+ function readMarker2(markerPath2) {
24389
+ try {
24390
+ return fs52.readFileSync(markerPath2, "utf8").trim();
24391
+ } catch {
24392
+ return null;
24393
+ }
24394
+ }
24395
+ function watchForBuildClobber(deps) {
24396
+ const watchDir = deps.watchDir ?? defaultWatchDir;
24397
+ const debounceMs = deps.debounceMs ?? DEFAULT_DEBOUNCE_MS;
24398
+ const maxRestarts = deps.maxRestarts ?? DEFAULT_MAX_RESTARTS;
24399
+ const nextDir = path57.join(deps.cwd, ".next");
24400
+ const markerPath2 = path57.join(nextDir, BUILD_MARKER_NAME);
24401
+ let stopped = false;
24402
+ let debounceTimer = null;
24403
+ let dirUnwatch = null;
24404
+ let cwdUnwatch = null;
24405
+ let lastKnownMarker = readMarker2(markerPath2);
24406
+ const stop = () => {
24407
+ if (stopped) return;
24408
+ stopped = true;
24409
+ if (debounceTimer) {
24410
+ clearTimeout(debounceTimer);
24411
+ debounceTimer = null;
24412
+ }
24413
+ dirUnwatch?.();
24414
+ dirUnwatch = null;
24415
+ cwdUnwatch?.();
24416
+ cwdUnwatch = null;
24417
+ };
24418
+ const onDebouncedClobber = () => {
24419
+ if (stopped) return;
24420
+ const current2 = readMarker2(markerPath2);
24421
+ if (current2 === lastKnownMarker) return;
24422
+ lastKnownMarker = current2;
24423
+ const count = (healRestartCounts.get(deps.sessionId) ?? 0) + 1;
24424
+ healRestartCounts.set(deps.sessionId, count);
24425
+ if (count > maxRestarts) {
24426
+ log.warn(
24427
+ "preview",
24428
+ `build-heal: restart cap (${maxRestarts}) reached for session=${deps.sessionId} \u2014 no longer self-healing`
24429
+ );
24430
+ deps.notify(
24431
+ "This preview keeps getting rebuilt \u2014 stopped auto-restarting. Restart it manually once the rebuilds settle."
24432
+ );
24433
+ stop();
24434
+ return;
24435
+ }
24436
+ log.info(
24437
+ "preview",
24438
+ `build-heal: ${markerPath2} changed (a build likely ran) \u2014 restarting the dev server (${count}/${maxRestarts})`
24439
+ );
24440
+ deps.notify("Rebuilt \u2014 restarting preview");
24441
+ deps.restart();
24442
+ };
24443
+ const onMarkerTouched = () => {
24444
+ if (stopped) return;
24445
+ if (debounceTimer) clearTimeout(debounceTimer);
24446
+ debounceTimer = setTimeout(() => {
24447
+ debounceTimer = null;
24448
+ onDebouncedClobber();
24449
+ }, debounceMs);
24450
+ };
24451
+ const attachDirWatch = () => {
24452
+ if (dirUnwatch) return;
24453
+ lastKnownMarker = readMarker2(markerPath2);
24454
+ dirUnwatch = watchDir(nextDir, (filename) => {
24455
+ if (filename === null || filename === BUILD_MARKER_NAME) onMarkerTouched();
24456
+ });
24457
+ };
24458
+ if (fs52.existsSync(nextDir)) {
24459
+ attachDirWatch();
24460
+ } else {
24461
+ cwdUnwatch = watchDir(deps.cwd, (filename) => {
24462
+ if (stopped || dirUnwatch) return;
24463
+ if ((filename === ".next" || filename === null) && fs52.existsSync(nextDir)) {
24464
+ cwdUnwatch?.();
24465
+ cwdUnwatch = null;
24466
+ attachDirWatch();
24467
+ }
24468
+ });
24469
+ }
24470
+ return { stop };
24471
+ }
24472
+
24335
24473
  // src/services/preview/cloudflared.ts
24336
24474
  var import_child_process18 = require("child_process");
24337
24475
  var import_fs3 = require("fs");
@@ -24981,6 +25119,7 @@ function killProcessTree(child, signal = "SIGTERM") {
24981
25119
  async function killPreview(sessionId) {
24982
25120
  const preview = activePreviews.get(sessionId);
24983
25121
  if (!preview) return;
25122
+ preview.buildHealStop?.();
24984
25123
  forgetPreviewPort(preview.detection.port);
24985
25124
  if (preview.tunnel) {
24986
25125
  killProcessTree(preview.tunnel, "SIGTERM");
@@ -25005,19 +25144,19 @@ function activePreviewSessionIds() {
25005
25144
 
25006
25145
  // src/services/preview/start-orchestrator.ts
25007
25146
  var import_child_process22 = require("child_process");
25008
- var fs58 = __toESM(require("fs"));
25009
- var path63 = __toESM(require("path"));
25147
+ var fs59 = __toESM(require("fs"));
25148
+ var path64 = __toESM(require("path"));
25010
25149
  var import_which2 = __toESM(require("which"));
25011
25150
 
25012
25151
  // src/services/project-env/index.ts
25013
25152
  var import_fs6 = require("fs");
25014
- var path62 = __toESM(require("path"));
25153
+ var path63 = __toESM(require("path"));
25015
25154
 
25016
25155
  // src/beads/project-key.ts
25017
25156
  var import_child_process21 = require("child_process");
25018
25157
  var crypto2 = __toESM(require("crypto"));
25019
- var fs56 = __toESM(require("fs"));
25020
- var path61 = __toESM(require("path"));
25158
+ var fs57 = __toESM(require("fs"));
25159
+ var path62 = __toESM(require("path"));
25021
25160
  function normalizeOrigin(raw) {
25022
25161
  const trimmed = raw.trim();
25023
25162
  if (!trimmed) return null;
@@ -25043,17 +25182,17 @@ function normalizeOrigin(raw) {
25043
25182
  return `${host2}/${pathPart}`;
25044
25183
  }
25045
25184
  function findRepoRoot(cwd) {
25046
- let dir = path61.resolve(cwd);
25185
+ let dir = path62.resolve(cwd);
25047
25186
  const seen = /* @__PURE__ */ new Set();
25048
25187
  for (let i = 0; i < 256; i++) {
25049
25188
  if (seen.has(dir)) return null;
25050
25189
  seen.add(dir);
25051
25190
  try {
25052
- const stat3 = fs56.statSync(path61.join(dir, ".git"), { throwIfNoEntry: false });
25191
+ const stat3 = fs57.statSync(path62.join(dir, ".git"), { throwIfNoEntry: false });
25053
25192
  if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
25054
25193
  } catch {
25055
25194
  }
25056
- const parent = path61.dirname(dir);
25195
+ const parent = path62.dirname(dir);
25057
25196
  if (parent === dir) return null;
25058
25197
  dir = parent;
25059
25198
  }
@@ -25064,7 +25203,7 @@ var _execSeam3 = {
25064
25203
  const out2 = (0, import_child_process21.execFileSync)(file, args2, opts);
25065
25204
  return typeof out2 === "string" ? out2 : out2.toString("utf8");
25066
25205
  },
25067
- realpath: (p2) => fs56.realpathSync(p2)
25206
+ realpath: (p2) => fs57.realpathSync(p2)
25068
25207
  };
25069
25208
  function readOrigin(cwd) {
25070
25209
  try {
@@ -25093,7 +25232,7 @@ function deriveProjectIdentity(cwd = process.cwd()) {
25093
25232
  } catch {
25094
25233
  }
25095
25234
  const hash = crypto2.createHash("sha256").update(real).digest("hex");
25096
- return { projectKey: `path:${hash}`, projectLabel: path61.basename(real) || "project" };
25235
+ return { projectKey: `path:${hash}`, projectLabel: path62.basename(real) || "project" };
25097
25236
  }
25098
25237
 
25099
25238
  // src/services/project-env/index.ts
@@ -25106,7 +25245,7 @@ async function readIfExists(p2) {
25106
25245
  }
25107
25246
  async function syncProjectEnvUp(cwd, ctx) {
25108
25247
  if (!ctx.pluginAuthToken) return;
25109
- const content = await readIfExists(path62.join(cwd, ".env"));
25248
+ const content = await readIfExists(path63.join(cwd, ".env"));
25110
25249
  if (content == null) return;
25111
25250
  try {
25112
25251
  const { projectKey, projectLabel } = deriveProjectIdentity(cwd);
@@ -25128,7 +25267,7 @@ async function syncProjectEnvUp(cwd, ctx) {
25128
25267
  }
25129
25268
  async function restoreProjectEnvIfMissing(cwd, ctx) {
25130
25269
  if (!ctx.pluginAuthToken) return false;
25131
- const envPath = path62.join(cwd, ".env");
25270
+ const envPath = path63.join(cwd, ".env");
25132
25271
  if (await readIfExists(envPath) != null) return false;
25133
25272
  try {
25134
25273
  const { projectKey, projectLabel } = deriveProjectIdentity(cwd);
@@ -25139,7 +25278,7 @@ async function restoreProjectEnvIfMissing(cwd, ctx) {
25139
25278
  projectKey
25140
25279
  });
25141
25280
  if (!stored) return false;
25142
- const tmp = path62.join(cwd, ".env.codeam-restore.tmp");
25281
+ const tmp = path63.join(cwd, ".env.codeam-restore.tmp");
25143
25282
  await import_fs6.promises.writeFile(tmp, stored.content, { encoding: "utf8", mode: 384 });
25144
25283
  await import_fs6.promises.rename(tmp, envPath);
25145
25284
  log.info("project-env", `restored .env (${stored.keyCount} vars) for ${projectLabel}`);
@@ -25236,8 +25375,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
25236
25375
  if (args2.length === 0) return detection;
25237
25376
  const binName = args2[0];
25238
25377
  if (binName.startsWith("-")) return detection;
25239
- const binPath = path63.join(cwd, "node_modules", ".bin", binName);
25240
- if (!fs58.existsSync(binPath)) return detection;
25378
+ const binPath = path64.join(cwd, "node_modules", ".bin", binName);
25379
+ if (!fs59.existsSync(binPath)) return detection;
25241
25380
  return {
25242
25381
  ...detection,
25243
25382
  command: binPath,
@@ -25618,9 +25757,9 @@ async function establishTunnel(ctx, dev) {
25618
25757
 
25619
25758
  // src/beads/bd-adapter.ts
25620
25759
  var import_child_process23 = require("child_process");
25621
- var fs59 = __toESM(require("fs"));
25760
+ var fs60 = __toESM(require("fs"));
25622
25761
  var os48 = __toESM(require("os"));
25623
- var path64 = __toESM(require("path"));
25762
+ var path65 = __toESM(require("path"));
25624
25763
  var BD_PACKAGE = "@beads/bd";
25625
25764
  function resolveBundledBdBinary() {
25626
25765
  return _resolveSeam.resolveBundled();
@@ -25632,11 +25771,11 @@ function _defaultResolveBundled() {
25632
25771
  } catch {
25633
25772
  return null;
25634
25773
  }
25635
- const binDir = path64.join(path64.dirname(pkgJsonPath), "bin");
25774
+ const binDir = path65.join(path65.dirname(pkgJsonPath), "bin");
25636
25775
  const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
25637
- const binaryPath = path64.join(binDir, binaryName);
25776
+ const binaryPath = path65.join(binDir, binaryName);
25638
25777
  try {
25639
- fs59.accessSync(binaryPath, fs59.constants.F_OK);
25778
+ fs60.accessSync(binaryPath, fs60.constants.F_OK);
25640
25779
  return binaryPath;
25641
25780
  } catch {
25642
25781
  return null;
@@ -25646,13 +25785,13 @@ function resolveBdOnPath() {
25646
25785
  return _resolveSeam.resolveOnPath();
25647
25786
  }
25648
25787
  function _defaultResolveOnPath() {
25649
- const dirs = (process.env.PATH ?? "").split(path64.delimiter).filter(Boolean);
25788
+ const dirs = (process.env.PATH ?? "").split(path65.delimiter).filter(Boolean);
25650
25789
  const candidates = process.platform === "win32" ? ["bd.exe", "bd.cmd", "bd"] : ["bd"];
25651
25790
  for (const dir of dirs) {
25652
25791
  for (const candidate of candidates) {
25653
- const full = path64.join(dir, candidate);
25792
+ const full = path65.join(dir, candidate);
25654
25793
  try {
25655
- fs59.accessSync(full, fs59.constants.F_OK);
25794
+ fs60.accessSync(full, fs60.constants.F_OK);
25656
25795
  return full;
25657
25796
  } catch {
25658
25797
  }
@@ -25829,9 +25968,9 @@ function coerceIssue(row, projectKey) {
25829
25968
 
25830
25969
  // src/beads/provisioner.ts
25831
25970
  var import_child_process26 = require("child_process");
25832
- var fs61 = __toESM(require("fs"));
25971
+ var fs62 = __toESM(require("fs"));
25833
25972
  var os50 = __toESM(require("os"));
25834
- var path66 = __toESM(require("path"));
25973
+ var path67 = __toESM(require("path"));
25835
25974
 
25836
25975
  // src/beads/install-bd.ts
25837
25976
  var import_child_process24 = require("child_process");
@@ -25896,9 +26035,9 @@ async function installBd(platform3 = process.platform) {
25896
26035
 
25897
26036
  // src/beads/install-dolt.ts
25898
26037
  var import_child_process25 = require("child_process");
25899
- var fs60 = __toESM(require("fs"));
26038
+ var fs61 = __toESM(require("fs"));
25900
26039
  var os49 = __toESM(require("os"));
25901
- var path65 = __toESM(require("path"));
26040
+ var path66 = __toESM(require("path"));
25902
26041
  var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
25903
26042
  var DOLT_MSI_URL = "https://github.com/dolthub/dolt/releases/latest/download/dolt-windows-amd64.msi";
25904
26043
  function resolveDoltInstallStrategy(platform3) {
@@ -25994,7 +26133,7 @@ var _doltPathSeam = {
25994
26133
  },
25995
26134
  exists: (p2) => {
25996
26135
  try {
25997
- fs60.accessSync(p2, fs60.constants.F_OK);
26136
+ fs61.accessSync(p2, fs61.constants.F_OK);
25998
26137
  return true;
25999
26138
  } catch {
26000
26139
  return false;
@@ -26005,7 +26144,7 @@ function doltBinaryNames(platform3) {
26005
26144
  return platform3 === "win32" ? ["dolt.exe", "dolt.cmd", "dolt"] : ["dolt"];
26006
26145
  }
26007
26146
  function knownDoltDirs(platform3) {
26008
- const P3 = platform3 === "win32" ? path65.win32 : path65.posix;
26147
+ const P3 = platform3 === "win32" ? path66.win32 : path66.posix;
26009
26148
  const home = _doltPathSeam.homedir();
26010
26149
  if (platform3 === "win32") {
26011
26150
  return [
@@ -26021,7 +26160,7 @@ function knownDoltDirs(platform3) {
26021
26160
  ].filter(Boolean);
26022
26161
  }
26023
26162
  function ensureDoltResolvable(platform3 = process.platform) {
26024
- const P3 = platform3 === "win32" ? path65.win32 : path65.posix;
26163
+ const P3 = platform3 === "win32" ? path66.win32 : path66.posix;
26025
26164
  const delim = platform3 === "win32" ? ";" : ":";
26026
26165
  const names = doltBinaryNames(platform3);
26027
26166
  const pathDirs = _doltPathSeam.getPath().split(delim).filter(Boolean);
@@ -26201,14 +26340,14 @@ var _linkSeam = {
26201
26340
  homedir: () => os50.homedir(),
26202
26341
  isWritableDir: (dir) => {
26203
26342
  try {
26204
- fs61.accessSync(dir, fs61.constants.W_OK);
26343
+ fs62.accessSync(dir, fs62.constants.W_OK);
26205
26344
  return true;
26206
26345
  } catch {
26207
26346
  return false;
26208
26347
  }
26209
26348
  },
26210
26349
  ensureDir: (dir) => {
26211
- fs61.mkdirSync(dir, { recursive: true });
26350
+ fs62.mkdirSync(dir, { recursive: true });
26212
26351
  },
26213
26352
  /**
26214
26353
  * A directory to symlink `bd` into so the AGENT's shell + Claude Code's
@@ -26229,9 +26368,9 @@ var _linkSeam = {
26229
26368
  * which `linkBdOntoPath` creates if missing.
26230
26369
  */
26231
26370
  cliBinDir: () => {
26232
- const pathDirs = (process.env.PATH ?? "").split(path66.delimiter).filter(Boolean);
26371
+ const pathDirs = (process.env.PATH ?? "").split(path67.delimiter).filter(Boolean);
26233
26372
  const home = _linkSeam.homedir();
26234
- const localBin = home ? path66.join(home, ".local", "bin") : null;
26373
+ const localBin = home ? path67.join(home, ".local", "bin") : null;
26235
26374
  if (localBin) {
26236
26375
  try {
26237
26376
  _linkSeam.ensureDir(localBin);
@@ -26241,16 +26380,16 @@ var _linkSeam = {
26241
26380
  const candidates = [];
26242
26381
  if (localBin) candidates.push(localBin);
26243
26382
  try {
26244
- candidates.push(path66.dirname(process.execPath));
26383
+ candidates.push(path67.dirname(process.execPath));
26245
26384
  } catch {
26246
26385
  }
26247
26386
  candidates.push("/usr/local/bin");
26248
26387
  const entry = process.argv[1];
26249
26388
  if (entry) {
26250
26389
  try {
26251
- candidates.push(path66.dirname(fs61.realpathSync(entry)));
26390
+ candidates.push(path67.dirname(fs62.realpathSync(entry)));
26252
26391
  } catch {
26253
- candidates.push(path66.dirname(entry));
26392
+ candidates.push(path67.dirname(entry));
26254
26393
  }
26255
26394
  }
26256
26395
  const onPathWritable = candidates.find(
@@ -26262,20 +26401,20 @@ var _linkSeam = {
26262
26401
  /** Current symlink target at `linkPath`, or null when absent / not a link. */
26263
26402
  readlink: (linkPath) => {
26264
26403
  try {
26265
- return fs61.readlinkSync(linkPath);
26404
+ return fs62.readlinkSync(linkPath);
26266
26405
  } catch {
26267
26406
  return null;
26268
26407
  }
26269
26408
  },
26270
- unlink: (linkPath) => fs61.unlinkSync(linkPath),
26271
- symlink: (target, linkPath) => fs61.symlinkSync(target, linkPath)
26409
+ unlink: (linkPath) => fs62.unlinkSync(linkPath),
26410
+ symlink: (target, linkPath) => fs62.symlinkSync(target, linkPath)
26272
26411
  };
26273
26412
  function linkBdOntoPath(binaryPath) {
26274
26413
  if (_linkSeam.platform() === "win32") return;
26275
26414
  const binDir = _linkSeam.cliBinDir();
26276
26415
  if (!binDir) return;
26277
26416
  _linkSeam.ensureDir(binDir);
26278
- const linkPath = path66.join(binDir, "bd");
26417
+ const linkPath = path67.join(binDir, "bd");
26279
26418
  if (linkPath === binaryPath) return;
26280
26419
  const current2 = _linkSeam.readlink(linkPath);
26281
26420
  if (current2 === binaryPath) return;
@@ -26470,7 +26609,7 @@ function dedupeRecipes(agents) {
26470
26609
 
26471
26610
  // src/beads/watcher.ts
26472
26611
  var crypto4 = __toESM(require("crypto"));
26473
- var path67 = __toESM(require("path"));
26612
+ var path68 = __toESM(require("path"));
26474
26613
  var API_BASE6 = resolveApiBaseUrl();
26475
26614
  var DEBOUNCE_MS2 = 400;
26476
26615
  var ZERO_SUMMARY = {
@@ -26494,7 +26633,7 @@ var BeadsWatcher = class {
26494
26633
  constructor(opts) {
26495
26634
  this.opts = opts;
26496
26635
  this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
26497
- this.feedPath = opts.feedPath ?? path67.join(opts.cwd ?? process.cwd(), ".beads", "last-touched");
26636
+ this.feedPath = opts.feedPath ?? path68.join(opts.cwd ?? process.cwd(), ".beads", "last-touched");
26498
26637
  this.apiBase = opts.apiBaseUrl ?? API_BASE6;
26499
26638
  }
26500
26639
  opts;
@@ -26993,8 +27132,8 @@ function cleanupAttachmentTempFiles() {
26993
27132
  function saveFilesTemp(files) {
26994
27133
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
26995
27134
  const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
26996
- const tmpPath = path70.join(os54.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
26997
- fs64.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
27135
+ const tmpPath = path71.join(os54.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
27136
+ fs65.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
26998
27137
  pendingAttachmentFiles.add(tmpPath);
26999
27138
  return tmpPath;
27000
27139
  });
@@ -27212,10 +27351,10 @@ var listFiles = async (ctx, cmd, parsed) => {
27212
27351
  await ctx.relay.sendResult(cmd.id, "completed", result);
27213
27352
  };
27214
27353
  var envReadH = async (ctx, cmd) => {
27215
- const envPath = path70.join(process.cwd(), ".env");
27354
+ const envPath = path71.join(process.cwd(), ".env");
27216
27355
  await restoreProjectEnvIfMissing(process.cwd(), ctx);
27217
27356
  try {
27218
- const raw = await fs64.promises.readFile(envPath, "utf8");
27357
+ const raw = await fs65.promises.readFile(envPath, "utf8");
27219
27358
  await ctx.relay.sendResult(cmd.id, "completed", {
27220
27359
  exists: true,
27221
27360
  vars: parseDotenv(raw)
@@ -27246,15 +27385,15 @@ var envWriteH = async (ctx, cmd, parsed) => {
27246
27385
  }
27247
27386
  seen.add(v.key);
27248
27387
  }
27249
- const envPath = path70.join(process.cwd(), ".env");
27250
- const tmpPath = path70.join(process.cwd(), ".env.codeam.tmp");
27388
+ const envPath = path71.join(process.cwd(), ".env");
27389
+ const tmpPath = path71.join(process.cwd(), ".env.codeam.tmp");
27251
27390
  try {
27252
- await fs64.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
27253
- await fs64.promises.rename(tmpPath, envPath);
27391
+ await fs65.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
27392
+ await fs65.promises.rename(tmpPath, envPath);
27254
27393
  await ctx.relay.sendResult(cmd.id, "completed", { ok: true, count: vars.length });
27255
27394
  void syncProjectEnvUp(process.cwd(), ctx);
27256
27395
  } catch (err) {
27257
- await fs64.promises.rm(tmpPath, { force: true }).catch(() => void 0);
27396
+ await fs65.promises.rm(tmpPath, { force: true }).catch(() => void 0);
27258
27397
  await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
27259
27398
  }
27260
27399
  };
@@ -27303,7 +27442,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
27303
27442
  let configuredAgent = rawAgentId;
27304
27443
  if (!configuredAgent) {
27305
27444
  try {
27306
- const raw = JSON.parse(fs64.readFileSync(headroomConfigPath(), "utf8"));
27445
+ const raw = JSON.parse(fs65.readFileSync(headroomConfigPath(), "utf8"));
27307
27446
  configuredAgent = raw.agent ?? "";
27308
27447
  } catch {
27309
27448
  }
@@ -27337,7 +27476,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
27337
27476
  persist: persistHeadroomConfig,
27338
27477
  readEnabled: () => {
27339
27478
  try {
27340
- const raw = JSON.parse(fs64.readFileSync(headroomConfigPath(), "utf8"));
27479
+ const raw = JSON.parse(fs65.readFileSync(headroomConfigPath(), "utf8"));
27341
27480
  return raw.enabled === true;
27342
27481
  } catch {
27343
27482
  return false;
@@ -27659,7 +27798,7 @@ var headroomBudgetH = async (ctx, cmd) => {
27659
27798
  }
27660
27799
  let headroomActive = false;
27661
27800
  try {
27662
- const raw = JSON.parse(fs64.readFileSync(headroomConfigPath(), "utf8"));
27801
+ const raw = JSON.parse(fs65.readFileSync(headroomConfigPath(), "utf8"));
27663
27802
  headroomActive = raw.enabled === true;
27664
27803
  } catch {
27665
27804
  }
@@ -27669,7 +27808,7 @@ var headroomBudgetH = async (ctx, cmd) => {
27669
27808
  }
27670
27809
  let existingConfig = { enabled: true };
27671
27810
  try {
27672
- existingConfig = JSON.parse(fs64.readFileSync(headroomConfigPath(), "utf8"));
27811
+ existingConfig = JSON.parse(fs65.readFileSync(headroomConfigPath(), "utf8"));
27673
27812
  } catch {
27674
27813
  }
27675
27814
  if (payload.budgetEnabled && payload.budgetUsd != null) {
@@ -27782,9 +27921,9 @@ var CLI_UPDATE_MAX_ATTEMPTS = 3;
27782
27921
  function buildNpmInstallInvocation(opts) {
27783
27922
  const entryScript = opts?.entryScript ?? process.argv[1] ?? "";
27784
27923
  const execPath = opts?.execPath ?? process.execPath;
27785
- const exists2 = opts?.existsSync ?? fs64.existsSync;
27924
+ const exists2 = opts?.existsSync ?? fs65.existsSync;
27786
27925
  const platform3 = opts?.platform ?? process.platform;
27787
- const p2 = platform3 === "win32" ? path70.win32 : path70.posix;
27926
+ const p2 = platform3 === "win32" ? path71.win32 : path71.posix;
27788
27927
  const normalized = entryScript.split(/[\\/]/).join("/");
27789
27928
  const marker = "/lib/node_modules/codeam-cli/";
27790
27929
  const markerIdx = normalized.indexOf(marker);
@@ -27806,7 +27945,7 @@ function isPermissionError(stderr) {
27806
27945
  function resolveGlobalNodeModulesDir(opts) {
27807
27946
  const entryScript = opts?.entryScript ?? process.argv[1] ?? "";
27808
27947
  const platform3 = opts?.platform ?? process.platform;
27809
- const p2 = platform3 === "win32" ? path70.win32 : path70.posix;
27948
+ const p2 = platform3 === "win32" ? path71.win32 : path71.posix;
27810
27949
  const marker = "/lib/node_modules/codeam-cli/";
27811
27950
  const markerIdx = entryScript.split(/[\\/]/).join("/").indexOf(marker);
27812
27951
  if (markerIdx <= 0) return null;
@@ -27816,9 +27955,9 @@ function resolveGlobalNodeModulesDir(opts) {
27816
27955
  var STALE_STAGING_AGE_MS = CLI_UPDATE_INSTALL_TIMEOUT_MS;
27817
27956
  function sweepStaleCliStagingDirs(nodeModulesDir, now = Date.now(), deps) {
27818
27957
  if (!nodeModulesDir) return 0;
27819
- const readdirSync15 = deps?.readdirSync ?? fs64.readdirSync;
27820
- const statSync17 = deps?.statSync ?? fs64.statSync;
27821
- const rmSync9 = deps?.rmSync ?? fs64.rmSync;
27958
+ const readdirSync15 = deps?.readdirSync ?? fs65.readdirSync;
27959
+ const statSync17 = deps?.statSync ?? fs65.statSync;
27960
+ const rmSync9 = deps?.rmSync ?? fs65.rmSync;
27822
27961
  let removed = 0;
27823
27962
  let entries;
27824
27963
  try {
@@ -27828,7 +27967,7 @@ function sweepStaleCliStagingDirs(nodeModulesDir, now = Date.now(), deps) {
27828
27967
  }
27829
27968
  for (const name of entries) {
27830
27969
  if (!/^\.codeam-cli-/.test(name)) continue;
27831
- const full = path70.join(nodeModulesDir, name);
27970
+ const full = path71.join(nodeModulesDir, name);
27832
27971
  try {
27833
27972
  const st3 = statSync17(full);
27834
27973
  if (now - st3.mtimeMs < STALE_STAGING_AGE_MS) continue;
@@ -28181,6 +28320,9 @@ function parseInsightText(text) {
28181
28320
  securityNote: securityMatch?.[1]?.trim() || void 0
28182
28321
  };
28183
28322
  }
28323
+ var emitPreviewEvent = makeSerializedEmitter(
28324
+ (args2) => postPreviewEvent(args2)
28325
+ );
28184
28326
  var requestPreviewDetectH = (ctx) => {
28185
28327
  if (!ctx.pluginAuthToken) {
28186
28328
  log.info("preview", "no pluginAuthToken \u2014 skipping detect");
@@ -28188,7 +28330,7 @@ var requestPreviewDetectH = (ctx) => {
28188
28330
  }
28189
28331
  if (typeof ctx.runtime.generateOneShot !== "function") {
28190
28332
  log.info("preview", `runtime ${ctx.runtime.id} has no generateOneShot \u2014 emitting unsupported`);
28191
- void postPreviewEvent({
28333
+ emitPreviewEvent({
28192
28334
  sessionId: ctx.sessionId,
28193
28335
  pluginId: ctx.pluginId,
28194
28336
  pluginAuthToken: ctx.pluginAuthToken,
@@ -28205,7 +28347,7 @@ var requestPreviewDetectH = (ctx) => {
28205
28347
  const fromFile = await readPreviewConfig(process.cwd());
28206
28348
  if (fromFile) {
28207
28349
  log.info("preview", `detect: using .codeam/preview.json (${fromFile.framework})`);
28208
- void postPreviewEvent({
28350
+ emitPreviewEvent({
28209
28351
  sessionId: ctx.sessionId,
28210
28352
  pluginId: ctx.pluginId,
28211
28353
  pluginAuthToken,
@@ -28214,7 +28356,7 @@ var requestPreviewDetectH = (ctx) => {
28214
28356
  });
28215
28357
  return;
28216
28358
  }
28217
- void postPreviewEvent({
28359
+ emitPreviewEvent({
28218
28360
  sessionId: ctx.sessionId,
28219
28361
  pluginId: ctx.pluginId,
28220
28362
  pluginAuthToken,
@@ -28230,7 +28372,7 @@ var requestPreviewDetectH = (ctx) => {
28230
28372
  const detection = safeParseDetection(raw);
28231
28373
  if (!detection) {
28232
28374
  log.info("preview", `detect: invalid agent output after ${tookMs}ms`);
28233
- void postPreviewEvent({
28375
+ emitPreviewEvent({
28234
28376
  sessionId: ctx.sessionId,
28235
28377
  pluginId: ctx.pluginId,
28236
28378
  pluginAuthToken,
@@ -28244,7 +28386,7 @@ var requestPreviewDetectH = (ctx) => {
28244
28386
  }
28245
28387
  if (detection.framework === "unsupported") {
28246
28388
  log.info("preview", "detect: framework=unsupported");
28247
- void postPreviewEvent({
28389
+ emitPreviewEvent({
28248
28390
  sessionId: ctx.sessionId,
28249
28391
  pluginId: ctx.pluginId,
28250
28392
  pluginAuthToken,
@@ -28260,7 +28402,7 @@ var requestPreviewDetectH = (ctx) => {
28260
28402
  void writePreviewConfig(process.cwd(), detection).catch((err) => {
28261
28403
  log.info("preview", `detect: writePreviewConfig failed (non-fatal): ${String(err)}`);
28262
28404
  });
28263
- void postPreviewEvent({
28405
+ emitPreviewEvent({
28264
28406
  sessionId: ctx.sessionId,
28265
28407
  pluginId: ctx.pluginId,
28266
28408
  pluginAuthToken,
@@ -28270,6 +28412,31 @@ var requestPreviewDetectH = (ctx) => {
28270
28412
  })();
28271
28413
  };
28272
28414
  var previewPrewarmStarted = false;
28415
+ function makePreviewReaffirm(args2) {
28416
+ const token = args2.pluginAuthToken;
28417
+ const sessionId = args2.sessionId;
28418
+ if (!token || !sessionId) return void 0;
28419
+ return makePreviewHeartbeatReaffirm({
28420
+ serving: () => {
28421
+ const active2 = activePreviews.get(sessionId);
28422
+ if (!active2 || active2.devServer.exitCode !== null) return null;
28423
+ return {
28424
+ url: active2.url,
28425
+ framework: active2.framework,
28426
+ port: active2.detection.port
28427
+ };
28428
+ },
28429
+ emitReady: (payload) => {
28430
+ emitPreviewEvent({
28431
+ sessionId,
28432
+ pluginId: args2.pluginId,
28433
+ pluginAuthToken: token,
28434
+ type: USER_EVENTS.PREVIEW_READY,
28435
+ payload
28436
+ });
28437
+ }
28438
+ });
28439
+ }
28273
28440
  function prewarmPreviewDetection(runtime) {
28274
28441
  if (previewPrewarmStarted) return;
28275
28442
  previewPrewarmStarted = true;
@@ -28305,7 +28472,7 @@ var previewStartH = (ctx, _cmd, parsed) => {
28305
28472
  };
28306
28473
  function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
28307
28474
  const emit2 = (type, payload) => {
28308
- void postPreviewEvent({
28475
+ emitPreviewEvent({
28309
28476
  sessionId: ctx.sessionId,
28310
28477
  pluginId: ctx.pluginId,
28311
28478
  pluginAuthToken,
@@ -28323,7 +28490,7 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
28323
28490
  // this repo picks up its saved `.env` before the dev server spawns. Optional
28324
28491
  // — a caller without a token just skips the restore.
28325
28492
  projectEnvAuth: { pluginId: ctx.pluginId, pluginAuthToken }
28326
- }).catch((err) => {
28493
+ }).then(() => maybeAttachBuildHeal(ctx, pluginAuthToken)).catch((err) => {
28327
28494
  const message = err instanceof Error ? err.message : String(err);
28328
28495
  log.warn("preview", `start crashed before ready: ${message}`);
28329
28496
  emit2(USER_EVENTS.PREVIEW_ERROR, {
@@ -28332,6 +28499,33 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
28332
28499
  });
28333
28500
  });
28334
28501
  }
28502
+ function maybeAttachBuildHeal(ctx, pluginAuthToken) {
28503
+ const preview = activePreviews.get(ctx.sessionId);
28504
+ if (!preview || preview.buildHealStop) return;
28505
+ if (!isBuildHealSupported(preview.framework)) return;
28506
+ const { stop } = watchForBuildClobber({
28507
+ cwd: preview.cwd,
28508
+ sessionId: ctx.sessionId,
28509
+ restart: () => {
28510
+ void (async () => {
28511
+ if (!activePreviews.has(ctx.sessionId)) return;
28512
+ await killPreview(ctx.sessionId);
28513
+ await new Promise((r) => setTimeout(r, 150));
28514
+ startPreviewFromDetection(ctx, preview.detection, pluginAuthToken);
28515
+ })();
28516
+ },
28517
+ notify: (message) => {
28518
+ emitPreviewEvent({
28519
+ sessionId: ctx.sessionId,
28520
+ pluginId: ctx.pluginId,
28521
+ pluginAuthToken,
28522
+ type: USER_EVENTS.PREVIEW_PROGRESS,
28523
+ payload: { step: "BUILD_HEAL", message, timestamp: Date.now() }
28524
+ });
28525
+ }
28526
+ });
28527
+ preview.buildHealStop = stop;
28528
+ }
28335
28529
  var previewStopH = (ctx) => {
28336
28530
  if (!ctx.pluginAuthToken) {
28337
28531
  log.info("preview", "no pluginAuthToken \u2014 skipping stop");
@@ -28340,8 +28534,9 @@ var previewStopH = (ctx) => {
28340
28534
  const pluginAuthToken = ctx.pluginAuthToken;
28341
28535
  void (async () => {
28342
28536
  await killPreview(ctx.sessionId);
28537
+ resetBuildHealState(ctx.sessionId);
28343
28538
  log.info("preview", `stopped session=${ctx.sessionId}`);
28344
- void postPreviewEvent({
28539
+ emitPreviewEvent({
28345
28540
  sessionId: ctx.sessionId,
28346
28541
  pluginId: ctx.pluginId,
28347
28542
  pluginAuthToken,
@@ -28639,8 +28834,16 @@ async function startInfraOnly(agentId) {
28639
28834
  }
28640
28835
  },
28641
28836
  agentMeta,
28642
- []
28837
+ [],
28643
28838
  // empty agents list → dashboard renders NoAgentHero
28839
+ void 0,
28840
+ // El camino infra-only NO tiene agente, pero SÍ puede tener preview (es la
28841
+ // ruta del panel de archivos), así que su snapshot caduca igual.
28842
+ makePreviewReaffirm({
28843
+ sessionId: session.id,
28844
+ pluginId,
28845
+ pluginAuthToken: session.pluginAuthToken ?? void 0
28846
+ })
28644
28847
  );
28645
28848
  ctx.relay = relay;
28646
28849
  relayRef = relay;
@@ -28706,11 +28909,11 @@ function resolveTokenValue(args2) {
28706
28909
  }
28707
28910
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
28708
28911
  if (fileFlag) {
28709
- const path94 = fileFlag.slice("--token-file=".length);
28912
+ const path95 = fileFlag.slice("--token-file=".length);
28710
28913
  try {
28711
- const content = fs65.readFileSync(path94, "utf8").trim();
28712
- if (content.length === 0) fail(`--token-file ${path94} is empty`);
28713
- rmIfExistsQuiet(path94);
28914
+ const content = fs66.readFileSync(path95, "utf8").trim();
28915
+ if (content.length === 0) fail(`--token-file ${path95} is empty`);
28916
+ rmIfExistsQuiet(path95);
28714
28917
  return content;
28715
28918
  } catch (err) {
28716
28919
  fail(`Could not read --token-file: ${err.message}`);
@@ -28802,7 +29005,7 @@ async function claim(token, pluginId, pluginSecretHash) {
28802
29005
  }
28803
29006
  }
28804
29007
  function pairAutoLockPath() {
28805
- return path71.join(os55.homedir(), ".codeam", "pair-auto.lock");
29008
+ return path72.join(os55.homedir(), ".codeam", "pair-auto.lock");
28806
29009
  }
28807
29010
  function isLivePairAuto(pid) {
28808
29011
  if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
@@ -28812,7 +29015,7 @@ function isLivePairAuto(pid) {
28812
29015
  if (e.code !== "EPERM") return false;
28813
29016
  }
28814
29017
  try {
28815
- return fs65.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
29018
+ return fs66.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
28816
29019
  } catch {
28817
29020
  return true;
28818
29021
  }
@@ -28822,24 +29025,24 @@ function isLiveCodeam(pid) {
28822
29025
  }
28823
29026
  function daemonLockPath(sessionId) {
28824
29027
  const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
28825
- return path71.join(os55.homedir(), ".codeam", `daemon-${safe}.lock`);
29028
+ return path72.join(os55.homedir(), ".codeam", `daemon-${safe}.lock`);
28826
29029
  }
28827
29030
  function acquireDaemonLock(sessionId) {
28828
29031
  const lockPath = daemonLockPath(sessionId);
28829
29032
  try {
28830
- fs65.mkdirSync(path71.dirname(lockPath), { recursive: true });
29033
+ fs66.mkdirSync(path72.dirname(lockPath), { recursive: true });
28831
29034
  try {
28832
- fs65.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
29035
+ fs66.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
28833
29036
  } catch (e) {
28834
29037
  if (e.code !== "EEXIST") throw e;
28835
- const holder = Number(fs65.readFileSync(lockPath, "utf8").trim());
29038
+ const holder = Number(fs66.readFileSync(lockPath, "utf8").trim());
28836
29039
  if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
28837
- fs65.writeFileSync(lockPath, String(process.pid));
29040
+ fs66.writeFileSync(lockPath, String(process.pid));
28838
29041
  }
28839
29042
  const release3 = () => {
28840
29043
  try {
28841
- if (fs65.existsSync(lockPath) && Number(fs65.readFileSync(lockPath, "utf8").trim()) === process.pid) {
28842
- fs65.unlinkSync(lockPath);
29044
+ if (fs66.existsSync(lockPath) && Number(fs66.readFileSync(lockPath, "utf8").trim()) === process.pid) {
29045
+ fs66.unlinkSync(lockPath);
28843
29046
  }
28844
29047
  } catch {
28845
29048
  }
@@ -28861,19 +29064,19 @@ function acquireDaemonLock(sessionId) {
28861
29064
  function acquireSingletonLock() {
28862
29065
  const lockPath = pairAutoLockPath();
28863
29066
  try {
28864
- fs65.mkdirSync(path71.dirname(lockPath), { recursive: true });
29067
+ fs66.mkdirSync(path72.dirname(lockPath), { recursive: true });
28865
29068
  try {
28866
- fs65.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
29069
+ fs66.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
28867
29070
  } catch (e) {
28868
29071
  if (e.code !== "EEXIST") throw e;
28869
- const holder = Number(fs65.readFileSync(lockPath, "utf8").trim());
29072
+ const holder = Number(fs66.readFileSync(lockPath, "utf8").trim());
28870
29073
  if (isLivePairAuto(holder)) return false;
28871
- fs65.writeFileSync(lockPath, String(process.pid));
29074
+ fs66.writeFileSync(lockPath, String(process.pid));
28872
29075
  }
28873
29076
  process.once("exit", () => {
28874
29077
  try {
28875
- if (fs65.existsSync(lockPath) && Number(fs65.readFileSync(lockPath, "utf8").trim()) === process.pid) {
28876
- fs65.unlinkSync(lockPath);
29078
+ if (fs66.existsSync(lockPath) && Number(fs66.readFileSync(lockPath, "utf8").trim()) === process.pid) {
29079
+ fs66.unlinkSync(lockPath);
28877
29080
  }
28878
29081
  } catch {
28879
29082
  }
@@ -29323,7 +29526,7 @@ var AgentService = class _AgentService {
29323
29526
  };
29324
29527
 
29325
29528
  // src/agents/acp/adapters.ts
29326
- var path72 = __toESM(require("path"));
29529
+ var path73 = __toESM(require("path"));
29327
29530
 
29328
29531
  // src/agents/kimi/installer.ts
29329
29532
  var import_node_child_process27 = require("child_process");
@@ -29443,13 +29646,13 @@ function resolveBin(pkgName, binName) {
29443
29646
  try {
29444
29647
  const manifestPath = require_.resolve(`${pkgName}/package.json`);
29445
29648
  const manifest = require_(`${pkgName}/package.json`);
29446
- const pkgDir = path72.dirname(manifestPath);
29649
+ const pkgDir = path73.dirname(manifestPath);
29447
29650
  const bin = manifest.bin;
29448
29651
  if (!bin) return null;
29449
- if (typeof bin === "string") return path72.resolve(pkgDir, bin);
29652
+ if (typeof bin === "string") return path73.resolve(pkgDir, bin);
29450
29653
  const target = binName ?? Object.keys(bin)[0];
29451
29654
  if (!target || !bin[target]) return null;
29452
- return path72.resolve(pkgDir, bin[target]);
29655
+ return path73.resolve(pkgDir, bin[target]);
29453
29656
  } catch {
29454
29657
  return null;
29455
29658
  }
@@ -29630,13 +29833,13 @@ async function resolveAcpAdapterWithRetry(agent, opts = {}) {
29630
29833
 
29631
29834
  // src/agents/acp/runner.ts
29632
29835
  var import_node_crypto11 = require("crypto");
29633
- var fs77 = __toESM(require("fs"));
29836
+ var fs78 = __toESM(require("fs"));
29634
29837
  var os62 = __toESM(require("os"));
29635
- var path85 = __toESM(require("path"));
29838
+ var path86 = __toESM(require("path"));
29636
29839
 
29637
29840
  // src/services/history.service.ts
29638
- var fs66 = __toESM(require("fs"));
29639
- var path73 = __toESM(require("path"));
29841
+ var fs67 = __toESM(require("fs"));
29842
+ var path74 = __toESM(require("path"));
29640
29843
  var os56 = __toESM(require("os"));
29641
29844
  var https7 = __toESM(require("https"));
29642
29845
  var http6 = __toESM(require("http"));
@@ -29678,7 +29881,7 @@ function parseJsonl(filePath) {
29678
29881
  const messages = [];
29679
29882
  let raw;
29680
29883
  try {
29681
- raw = fs66.readFileSync(filePath, "utf8");
29884
+ raw = fs67.readFileSync(filePath, "utf8");
29682
29885
  } catch (err) {
29683
29886
  if (err.code !== "ENOENT") {
29684
29887
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -29823,7 +30026,7 @@ var HistoryService = class _HistoryService {
29823
30026
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
29824
30027
  }
29825
30028
  get projectDir() {
29826
- return this.runtime.resolveHistoryDir(this.cwd) ?? path73.join(os56.homedir(), ".claude", "projects", encodeCwd(this.cwd));
30029
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path74.join(os56.homedir(), ".claude", "projects", encodeCwd(this.cwd));
29827
30030
  }
29828
30031
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
29829
30032
  setCurrentConversationId(id) {
@@ -29835,7 +30038,7 @@ var HistoryService = class _HistoryService {
29835
30038
  /** Return the current message count in the active conversation. */
29836
30039
  getCurrentMessageCount() {
29837
30040
  if (!this.currentConversationId) return 0;
29838
- const filePath = path73.join(this.projectDir, `${this.currentConversationId}.jsonl`);
30041
+ const filePath = path74.join(this.projectDir, `${this.currentConversationId}.jsonl`);
29839
30042
  return parseJsonl(filePath).length;
29840
30043
  }
29841
30044
  /**
@@ -29846,7 +30049,7 @@ var HistoryService = class _HistoryService {
29846
30049
  const deadline = Date.now() + timeoutMs;
29847
30050
  while (Date.now() < deadline) {
29848
30051
  if (!this.currentConversationId) return null;
29849
- const filePath = path73.join(this.projectDir, `${this.currentConversationId}.jsonl`);
30052
+ const filePath = path74.join(this.projectDir, `${this.currentConversationId}.jsonl`);
29850
30053
  const messages = parseJsonl(filePath);
29851
30054
  if (messages.length > previousCount) {
29852
30055
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -29872,16 +30075,16 @@ var HistoryService = class _HistoryService {
29872
30075
  const dir = this.projectDir;
29873
30076
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
29874
30077
  try {
29875
- const files = fs66.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
30078
+ const files = fs67.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
29876
30079
  try {
29877
- const stat3 = fs66.statSync(path73.join(dir, e.name));
30080
+ const stat3 = fs67.statSync(path74.join(dir, e.name));
29878
30081
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
29879
30082
  } catch {
29880
30083
  return { name: e.name, mtime: 0, birthtime: 0 };
29881
30084
  }
29882
30085
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
29883
30086
  if (files.length > 0) {
29884
- this.currentConversationId = path73.basename(files[0].name, ".jsonl");
30087
+ this.currentConversationId = path74.basename(files[0].name, ".jsonl");
29885
30088
  }
29886
30089
  } catch {
29887
30090
  }
@@ -29915,13 +30118,13 @@ var HistoryService = class _HistoryService {
29915
30118
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
29916
30119
  let entries;
29917
30120
  try {
29918
- entries = fs66.readdirSync(dir, { withFileTypes: true });
30121
+ entries = fs67.readdirSync(dir, { withFileTypes: true });
29919
30122
  } catch {
29920
30123
  return null;
29921
30124
  }
29922
30125
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
29923
30126
  try {
29924
- const stat3 = fs66.statSync(path73.join(dir, e.name));
30127
+ const stat3 = fs67.statSync(path74.join(dir, e.name));
29925
30128
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
29926
30129
  } catch {
29927
30130
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -29930,12 +30133,12 @@ var HistoryService = class _HistoryService {
29930
30133
  if (files.length === 0) return null;
29931
30134
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
29932
30135
  if (!files.some((f) => f.name === targetFile)) return null;
29933
- return this.extractUsageFromFile(path73.join(dir, targetFile));
30136
+ return this.extractUsageFromFile(path74.join(dir, targetFile));
29934
30137
  }
29935
30138
  extractUsageFromFile(filePath) {
29936
30139
  let raw;
29937
30140
  try {
29938
- raw = fs66.readFileSync(filePath, "utf8");
30141
+ raw = fs67.readFileSync(filePath, "utf8");
29939
30142
  } catch {
29940
30143
  return null;
29941
30144
  }
@@ -29987,9 +30190,9 @@ var HistoryService = class _HistoryService {
29987
30190
  let totalCost = 0;
29988
30191
  let files;
29989
30192
  try {
29990
- files = fs66.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
30193
+ files = fs67.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
29991
30194
  try {
29992
- return fs66.statSync(path73.join(projectDir, f)).mtimeMs >= monthStartMs;
30195
+ return fs67.statSync(path74.join(projectDir, f)).mtimeMs >= monthStartMs;
29993
30196
  } catch {
29994
30197
  return false;
29995
30198
  }
@@ -30000,7 +30203,7 @@ var HistoryService = class _HistoryService {
30000
30203
  for (const file of files) {
30001
30204
  let raw;
30002
30205
  try {
30003
- raw = fs66.readFileSync(path73.join(projectDir, file), "utf8");
30206
+ raw = fs67.readFileSync(path74.join(projectDir, file), "utf8");
30004
30207
  } catch {
30005
30208
  continue;
30006
30209
  }
@@ -30079,7 +30282,7 @@ var HistoryService = class _HistoryService {
30079
30282
  if (this.runtime.resolveHistoryFile) {
30080
30283
  return this.runtime.resolveHistoryFile(this.cwd, sessionId);
30081
30284
  }
30082
- return path73.join(this.projectDir, `${sessionId}.jsonl`);
30285
+ return path74.join(this.projectDir, `${sessionId}.jsonl`);
30083
30286
  }
30084
30287
  /**
30085
30288
  * Parse a conversation's messages from disk, agent-aware. Claude uses the
@@ -30117,7 +30320,7 @@ var HistoryService = class _HistoryService {
30117
30320
  };
30118
30321
  });
30119
30322
  }
30120
- return parseJsonl(path73.join(this.projectDir, `${sessionId}.jsonl`));
30323
+ return parseJsonl(path74.join(this.projectDir, `${sessionId}.jsonl`));
30121
30324
  }
30122
30325
  async loadConversation(sessionId) {
30123
30326
  const messages = this.readConversation(sessionId);
@@ -30187,7 +30390,7 @@ var HistoryService = class _HistoryService {
30187
30390
  if (!filePath) return false;
30188
30391
  let mtimeMs;
30189
30392
  try {
30190
- mtimeMs = fs66.statSync(filePath).mtimeMs;
30393
+ mtimeMs = fs67.statSync(filePath).mtimeMs;
30191
30394
  } catch {
30192
30395
  return false;
30193
30396
  }
@@ -30262,10 +30465,10 @@ var HistoryService = class _HistoryService {
30262
30465
 
30263
30466
  // src/agents/acp/client.ts
30264
30467
  var import_node_child_process29 = require("child_process");
30265
- var fs67 = __toESM(require("fs/promises"));
30468
+ var fs68 = __toESM(require("fs/promises"));
30266
30469
  var fsSync = __toESM(require("fs"));
30267
30470
  var os58 = __toESM(require("os"));
30268
- var path75 = __toESM(require("path"));
30471
+ var path76 = __toESM(require("path"));
30269
30472
  var import_node_stream = require("stream");
30270
30473
 
30271
30474
  // ../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
@@ -34291,7 +34494,7 @@ function createIdleTimeout(idleMs, makeError, activeIdleMs = idleMs) {
34291
34494
  }
34292
34495
 
34293
34496
  // src/agents/acp/internal-paths.ts
34294
- var path74 = __toESM(require("path"));
34497
+ var path75 = __toESM(require("path"));
34295
34498
  var os57 = __toESM(require("os"));
34296
34499
  var INTERNAL_TOKENS = [".codeam", "house-claude"];
34297
34500
  var PROSE_ONLY_TOOL_KINDS = /* @__PURE__ */ new Set(["think", "switch_mode"]);
@@ -34306,11 +34509,11 @@ function textReferencesInternal(text) {
34306
34509
  }
34307
34510
  function pathIsInternal(p2, homeDir2 = os57.homedir()) {
34308
34511
  if (!p2) return false;
34309
- const abs = path74.resolve(p2);
34310
- const home = path74.resolve(homeDir2);
34311
- const within = (root) => abs === root || abs.startsWith(root + path74.sep);
34312
- if (within(path74.join(home, ".codeam", "self-hosted"))) return false;
34313
- return within(path74.join(home, ".codeam")) || within(path74.join(home, ".beads")) || abs === path74.join(home, ".codeam-host.log") || abs.includes(`${path74.sep}house-claude${path74.sep}`) || abs.endsWith(`${path74.sep}house-claude`);
34512
+ const abs = path75.resolve(p2);
34513
+ const home = path75.resolve(homeDir2);
34514
+ const within = (root) => abs === root || abs.startsWith(root + path75.sep);
34515
+ if (within(path75.join(home, ".codeam", "self-hosted"))) return false;
34516
+ return within(path75.join(home, ".codeam")) || within(path75.join(home, ".beads")) || abs === path75.join(home, ".codeam-host.log") || abs.includes(`${path75.sep}house-claude${path75.sep}`) || abs.endsWith(`${path75.sep}house-claude`);
34314
34517
  }
34315
34518
  function toolCallReferencesInternal(call, homeDir2) {
34316
34519
  if (call.locations?.some((l) => pathIsInternal(l.path, homeDir2))) return true;
@@ -35285,7 +35488,7 @@ var AcpClient = class {
35285
35488
  throw new RequestError(-32002, GUARDRAIL_SECRET_READ_BLOCK_REASON, { uri: params.path });
35286
35489
  }
35287
35490
  try {
35288
- const content = await fs67.readFile(params.path, "utf8");
35491
+ const content = await fs68.readFile(params.path, "utf8");
35289
35492
  return applyLineRange(content, params.line ?? null, params.limit ?? null);
35290
35493
  } catch (err) {
35291
35494
  const code = err.code;
@@ -35306,7 +35509,7 @@ var AcpClient = class {
35306
35509
  throw new RequestError(-32002, INTERNAL_BLOCK_REASON, { uri: params.path });
35307
35510
  }
35308
35511
  try {
35309
- await fs67.writeFile(params.path, params.content, "utf8");
35512
+ await fs68.writeFile(params.path, params.content, "utf8");
35310
35513
  return {};
35311
35514
  } catch (err) {
35312
35515
  const code = err.code;
@@ -35399,25 +35602,25 @@ function knownAgentBinaryDirs() {
35399
35602
  out2.push("/tmp/codeam-node20/bin");
35400
35603
  for (const root of [
35401
35604
  "/usr/local/share/nvm/versions/node",
35402
- path75.join(home, ".nvm/versions/node")
35605
+ path76.join(home, ".nvm/versions/node")
35403
35606
  ]) {
35404
35607
  try {
35405
35608
  for (const child of fsSync.readdirSync(root)) {
35406
- out2.push(path75.join(root, child, "bin"));
35609
+ out2.push(path76.join(root, child, "bin"));
35407
35610
  }
35408
35611
  } catch {
35409
35612
  }
35410
35613
  }
35411
- out2.push(path75.join(home, ".volta/bin"));
35614
+ out2.push(path76.join(home, ".volta/bin"));
35412
35615
  out2.push("/usr/local/bin");
35413
35616
  out2.push("/usr/bin");
35414
- out2.push(path75.join(home, ".local/bin"));
35415
- out2.push(path75.join(home, "bin"));
35617
+ out2.push(path76.join(home, ".local/bin"));
35618
+ out2.push(path76.join(home, "bin"));
35416
35619
  out2.push(...agentInstallBinDirs());
35417
35620
  if (process.platform === "win32") {
35418
35621
  const { LOCALAPPDATA, APPDATA } = process.env;
35419
- if (LOCALAPPDATA) out2.push(path75.join(LOCALAPPDATA, "cursor-agent"));
35420
- if (APPDATA) out2.push(path75.join(APPDATA, "npm"));
35622
+ if (LOCALAPPDATA) out2.push(path76.join(LOCALAPPDATA, "cursor-agent"));
35623
+ if (APPDATA) out2.push(path76.join(APPDATA, "npm"));
35421
35624
  }
35422
35625
  return out2.filter((p2) => {
35423
35626
  try {
@@ -35428,7 +35631,7 @@ function knownAgentBinaryDirs() {
35428
35631
  });
35429
35632
  }
35430
35633
  function expandPathForAgentBinaries(existingPath) {
35431
- const existing = new Set(existingPath.split(path75.delimiter).filter((p2) => p2.length > 0));
35634
+ const existing = new Set(existingPath.split(path76.delimiter).filter((p2) => p2.length > 0));
35432
35635
  const additions = [];
35433
35636
  for (const dir of knownAgentBinaryDirs()) {
35434
35637
  if (!existing.has(dir)) {
@@ -35437,7 +35640,7 @@ function expandPathForAgentBinaries(existingPath) {
35437
35640
  }
35438
35641
  }
35439
35642
  if (additions.length === 0) return existingPath;
35440
- return [...additions, existingPath].filter((p2) => p2.length > 0).join(path75.delimiter);
35643
+ return [...additions, existingPath].filter((p2) => p2.length > 0).join(path76.delimiter);
35441
35644
  }
35442
35645
 
35443
35646
  // src/agents/acp/headroom-budget-proxy.ts
@@ -36360,15 +36563,15 @@ function withholdTrailingPartialFenceMarker(text) {
36360
36563
 
36361
36564
  // src/agents/acp/onboarding.ts
36362
36565
  var import_child_process29 = require("child_process");
36363
- var fs68 = __toESM(require("fs"));
36566
+ var fs69 = __toESM(require("fs"));
36364
36567
  var os59 = __toESM(require("os"));
36365
- var path76 = __toESM(require("path"));
36568
+ var path77 = __toESM(require("path"));
36366
36569
  var _onboardingSeam = {
36367
- markerPath: (sessionId) => path76.join(os59.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
36368
- exists: (p2) => fs68.existsSync(p2),
36570
+ markerPath: (sessionId) => path77.join(os59.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
36571
+ exists: (p2) => fs69.existsSync(p2),
36369
36572
  write: (p2) => {
36370
- fs68.mkdirSync(path76.dirname(p2), { recursive: true });
36371
- fs68.writeFileSync(p2, "");
36573
+ fs69.mkdirSync(path77.dirname(p2), { recursive: true });
36574
+ fs69.writeFileSync(p2, "");
36372
36575
  },
36373
36576
  disabled: () => {
36374
36577
  const v = process.env.CODEAM_ONBOARDING_DISABLED;
@@ -36405,7 +36608,7 @@ function resolveRepoName(cwd) {
36405
36608
  if (name) return name;
36406
36609
  }
36407
36610
  }
36408
- const base = path76.basename(cwd || "");
36611
+ const base = path77.basename(cwd || "");
36409
36612
  if (base && !isUuid(base)) return base;
36410
36613
  return "this project";
36411
36614
  }
@@ -36737,13 +36940,13 @@ var import_crypto5 = require("crypto");
36737
36940
 
36738
36941
  // src/services/turn-files/git-changeset.ts
36739
36942
  var import_child_process30 = require("child_process");
36740
- var fs70 = __toESM(require("fs/promises"));
36741
- var path78 = __toESM(require("path"));
36943
+ var fs71 = __toESM(require("fs/promises"));
36944
+ var path79 = __toESM(require("path"));
36742
36945
 
36743
36946
  // src/services/turn-files/review-ignore.ts
36744
36947
  var import_ignore2 = __toESM(require("ignore"));
36745
- var fs69 = __toESM(require("fs"));
36746
- var path77 = __toESM(require("path"));
36948
+ var fs70 = __toESM(require("fs"));
36949
+ var path78 = __toESM(require("path"));
36747
36950
  var CURATED_REVIEW_IGNORE = [
36748
36951
  // Google Cloud SDK (the incident) — installs a huge python tree.
36749
36952
  "google-cloud-sdk/",
@@ -36782,7 +36985,7 @@ var CURATED_REVIEW_IGNORE = [
36782
36985
  function makeReviewIgnore(repoRoot) {
36783
36986
  const ig = (0, import_ignore2.default)().add(CURATED_REVIEW_IGNORE);
36784
36987
  try {
36785
- const custom = fs69.readFileSync(path77.join(repoRoot, ".codeam", "reviewignore"), "utf8");
36988
+ const custom = fs70.readFileSync(path78.join(repoRoot, ".codeam", "reviewignore"), "utf8");
36786
36989
  ig.add(custom);
36787
36990
  } catch {
36788
36991
  }
@@ -36827,7 +37030,7 @@ async function collectRepoChangeset(opts) {
36827
37030
  let stats;
36828
37031
  if (!truncated && row.fileStatus === "added" && numstatEntry === void 0) {
36829
37032
  const lineCount = await readUntrackedLineCount(
36830
- path78.join(opts.repoRoot, row.filePath)
37033
+ path79.join(opts.repoRoot, row.filePath)
36831
37034
  );
36832
37035
  stats = { added: lineCount, removed: 0 };
36833
37036
  } else {
@@ -36858,7 +37061,7 @@ function readUntrackedLineCount(absPath) {
36858
37061
  }
36859
37062
  async function defaultReadUntrackedLineCount(absPath) {
36860
37063
  try {
36861
- const content = await fs70.readFile(absPath, "utf8");
37064
+ const content = await fs71.readFile(absPath, "utf8");
36862
37065
  let count = 0;
36863
37066
  let pos = -1;
36864
37067
  while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
@@ -36950,7 +37153,7 @@ function defaultRunGit(cwd, args2) {
36950
37153
  });
36951
37154
  }
36952
37155
  async function discoverRepos(workingDir, maxDepth = 4) {
36953
- const fs82 = await import("fs/promises");
37156
+ const fs83 = await import("fs/promises");
36954
37157
  const out2 = [];
36955
37158
  await walk(workingDir, 0);
36956
37159
  return out2;
@@ -36958,7 +37161,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
36958
37161
  if (depth > maxDepth) return;
36959
37162
  let entries = [];
36960
37163
  try {
36961
- const dirents = await fs82.readdir(dir, { withFileTypes: true });
37164
+ const dirents = await fs83.readdir(dir, { withFileTypes: true });
36962
37165
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
36963
37166
  } catch {
36964
37167
  return;
@@ -36969,8 +37172,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
36969
37172
  if (hasGit) {
36970
37173
  out2.push({
36971
37174
  repoRoot: dir,
36972
- repoPath: path78.relative(workingDir, dir),
36973
- repoName: path78.basename(dir)
37175
+ repoPath: path79.relative(workingDir, dir),
37176
+ repoName: path79.basename(dir)
36974
37177
  });
36975
37178
  return;
36976
37179
  }
@@ -36978,14 +37181,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
36978
37181
  if (!entry.isDirectory) continue;
36979
37182
  if (entry.name === "node_modules") continue;
36980
37183
  if (entry.name === "dist" || entry.name === "build") continue;
36981
- await walk(path78.join(dir, entry.name), depth + 1);
37184
+ await walk(path79.join(dir, entry.name), depth + 1);
36982
37185
  }
36983
37186
  }
36984
37187
  }
36985
37188
 
36986
37189
  // src/services/turn-files/files-outbox.ts
36987
- var fs71 = __toESM(require("fs/promises"));
36988
- var path79 = __toESM(require("path"));
37190
+ var fs72 = __toESM(require("fs/promises"));
37191
+ var path80 = __toESM(require("path"));
36989
37192
  var import_os12 = require("os");
36990
37193
  var HOME_OUTBOX_DIR = ".codeam/outbox";
36991
37194
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -37018,16 +37221,16 @@ var FilesOutbox = class {
37018
37221
  backoffIndex = 0;
37019
37222
  stopped = false;
37020
37223
  constructor(opts) {
37021
- const base = opts.baseDir ?? path79.join(homeDir(), HOME_OUTBOX_DIR);
37022
- this.filePath = path79.join(base, `${opts.sessionId}.jsonl`);
37224
+ const base = opts.baseDir ?? path80.join(homeDir(), HOME_OUTBOX_DIR);
37225
+ this.filePath = path80.join(base, `${opts.sessionId}.jsonl`);
37023
37226
  this.post = opts.post;
37024
37227
  this.autoSchedule = opts.autoSchedule !== false;
37025
37228
  }
37026
37229
  /** Persist the entry to disk and trigger a flush. Returns once the
37027
37230
  * line is durable on disk (not once the POST succeeds). */
37028
37231
  async enqueue(entry) {
37029
- await fs71.mkdir(path79.dirname(this.filePath), { recursive: true });
37030
- await fs71.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
37232
+ await fs72.mkdir(path80.dirname(this.filePath), { recursive: true });
37233
+ await fs72.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
37031
37234
  this.backoffIndex = 0;
37032
37235
  if (this.autoSchedule) this.scheduleFlush(0);
37033
37236
  }
@@ -37118,7 +37321,7 @@ var FilesOutbox = class {
37118
37321
  async readAll() {
37119
37322
  let raw = "";
37120
37323
  try {
37121
- raw = await fs71.readFile(this.filePath, "utf8");
37324
+ raw = await fs72.readFile(this.filePath, "utf8");
37122
37325
  } catch {
37123
37326
  return [];
37124
37327
  }
@@ -37142,12 +37345,12 @@ var FilesOutbox = class {
37142
37345
  async rewrite(entries) {
37143
37346
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
37144
37347
  if (entries.length === 0) {
37145
- await fs71.unlink(this.filePath).catch(() => void 0);
37348
+ await fs72.unlink(this.filePath).catch(() => void 0);
37146
37349
  return;
37147
37350
  }
37148
37351
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
37149
- await fs71.writeFile(tmpPath, payload, "utf8");
37150
- await fs71.rename(tmpPath, this.filePath);
37352
+ await fs72.writeFile(tmpPath, payload, "utf8");
37353
+ await fs72.rename(tmpPath, this.filePath);
37151
37354
  }
37152
37355
  };
37153
37356
  function applyJitter(ms) {
@@ -37664,8 +37867,8 @@ async function postBudgetReached(opts, fetchImpl = fetch) {
37664
37867
 
37665
37868
  // src/packs/gates.ts
37666
37869
  var import_node_child_process30 = require("child_process");
37667
- var fs72 = __toESM(require("fs"));
37668
- var path80 = __toESM(require("path"));
37870
+ var fs73 = __toESM(require("fs"));
37871
+ var path81 = __toESM(require("path"));
37669
37872
  var defaultCommandRunner = (file, args2, cwd, timeoutMs) => new Promise((resolve10) => {
37670
37873
  (0, import_node_child_process30.execFile)(
37671
37874
  file,
@@ -37702,14 +37905,14 @@ var NO_TEST_PLACEHOLDER = 'echo "Error: no test specified"';
37702
37905
  var CHECKS_TIMEOUT_MS = 5 * 6e4;
37703
37906
  function detectChecksCommand(cwd) {
37704
37907
  try {
37705
- const cfg = JSON.parse(fs72.readFileSync(path80.join(cwd, ".codeam", "pack.json"), "utf8"));
37908
+ const cfg = JSON.parse(fs73.readFileSync(path81.join(cwd, ".codeam", "pack.json"), "utf8"));
37706
37909
  if (typeof cfg.checksCommand === "string" && cfg.checksCommand.trim().length > 0) {
37707
37910
  return cfg.checksCommand.trim();
37708
37911
  }
37709
37912
  } catch {
37710
37913
  }
37711
37914
  try {
37712
- const pkg = JSON.parse(fs72.readFileSync(path80.join(cwd, "package.json"), "utf8"));
37915
+ const pkg = JSON.parse(fs73.readFileSync(path81.join(cwd, "package.json"), "utf8"));
37713
37916
  const test = pkg.scripts?.test;
37714
37917
  if (typeof test === "string" && test.trim().length > 0 && !test.includes(NO_TEST_PLACEHOLDER)) {
37715
37918
  return "npm test";
@@ -37727,39 +37930,39 @@ ${res.stderr}`.trim();
37727
37930
  }
37728
37931
 
37729
37932
  // src/packs/run-store.ts
37730
- var fs73 = __toESM(require("fs"));
37731
- var path81 = __toESM(require("path"));
37933
+ var fs74 = __toESM(require("fs"));
37934
+ var path82 = __toESM(require("path"));
37732
37935
  var crypto5 = __toESM(require("crypto"));
37733
37936
  function packsDir(cwd) {
37734
- return path81.join(cwd, ".codeam", "packs");
37937
+ return path82.join(cwd, ".codeam", "packs");
37735
37938
  }
37736
37939
  function runDir(cwd, runId) {
37737
- return path81.join(packsDir(cwd), runId);
37940
+ return path82.join(packsDir(cwd), runId);
37738
37941
  }
37739
37942
  function newRunId() {
37740
37943
  return `pk_${Date.now().toString(36)}_${crypto5.randomBytes(4).toString("hex")}`;
37741
37944
  }
37742
37945
  function writeJsonAtomic(file, value) {
37743
- fs73.mkdirSync(path81.dirname(file), { recursive: true });
37946
+ fs74.mkdirSync(path82.dirname(file), { recursive: true });
37744
37947
  const tmp = `${file}.tmp`;
37745
- fs73.writeFileSync(tmp, JSON.stringify(value, null, 2));
37746
- fs73.renameSync(tmp, file);
37948
+ fs74.writeFileSync(tmp, JSON.stringify(value, null, 2));
37949
+ fs74.renameSync(tmp, file);
37747
37950
  }
37748
37951
  function saveRun(cwd, state) {
37749
- writeJsonAtomic(path81.join(runDir(cwd, state.runId), "run.json"), state);
37952
+ writeJsonAtomic(path82.join(runDir(cwd, state.runId), "run.json"), state);
37750
37953
  }
37751
37954
  function saveStageHandoff(cwd, runId, stageIndex, role, handoff) {
37752
37955
  const name = `${String(stageIndex + 1).padStart(2, "0")}-${role}.json`;
37753
- writeJsonAtomic(path81.join(runDir(cwd, runId), name), handoff);
37956
+ writeJsonAtomic(path82.join(runDir(cwd, runId), name), handoff);
37754
37957
  }
37755
37958
  function loadLatestRun(cwd) {
37756
37959
  try {
37757
37960
  const dir = packsDir(cwd);
37758
- const entries = fs73.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
37961
+ const entries = fs74.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
37759
37962
  for (let i = entries.length - 1; i >= 0; i--) {
37760
- const file = path81.join(dir, entries[i], "run.json");
37963
+ const file = path82.join(dir, entries[i], "run.json");
37761
37964
  try {
37762
- const parsed = JSON.parse(fs73.readFileSync(file, "utf8"));
37965
+ const parsed = JSON.parse(fs74.readFileSync(file, "utf8"));
37763
37966
  if (parsed && typeof parsed.runId === "string") return parsed;
37764
37967
  } catch {
37765
37968
  }
@@ -37770,17 +37973,17 @@ function loadLatestRun(cwd) {
37770
37973
  }
37771
37974
  function ensureLedgerIgnored(cwd) {
37772
37975
  try {
37773
- const gitDir = path81.join(cwd, ".git");
37774
- if (!fs73.existsSync(gitDir)) return;
37775
- const exclude = path81.join(gitDir, "info", "exclude");
37976
+ const gitDir = path82.join(cwd, ".git");
37977
+ if (!fs74.existsSync(gitDir)) return;
37978
+ const exclude = path82.join(gitDir, "info", "exclude");
37776
37979
  let existing = "";
37777
37980
  try {
37778
- existing = fs73.readFileSync(exclude, "utf8");
37981
+ existing = fs74.readFileSync(exclude, "utf8");
37779
37982
  } catch {
37780
37983
  }
37781
37984
  if (existing.includes(".codeam/packs/")) return;
37782
- fs73.mkdirSync(path81.dirname(exclude), { recursive: true });
37783
- fs73.writeFileSync(exclude, `${existing.trimEnd()}
37985
+ fs74.mkdirSync(path82.dirname(exclude), { recursive: true });
37986
+ fs74.writeFileSync(exclude, `${existing.trimEnd()}
37784
37987
  .codeam/packs/
37785
37988
  `.trimStart());
37786
37989
  } catch {
@@ -38533,35 +38736,35 @@ function buildAcpPromptBlocks(payload) {
38533
38736
  }
38534
38737
 
38535
38738
  // src/agents/agent-standard.ts
38536
- var fs76 = __toESM(require("fs"));
38537
- var path84 = __toESM(require("path"));
38739
+ var fs77 = __toESM(require("fs"));
38740
+ var path85 = __toESM(require("path"));
38538
38741
  var os61 = __toESM(require("os"));
38539
38742
  function ensureAgentStandard(homeDir2 = os61.homedir()) {
38540
38743
  try {
38541
- const file = path84.join(homeDir2, ".claude", "CLAUDE.md");
38744
+ const file = path85.join(homeDir2, ".claude", "CLAUDE.md");
38542
38745
  let existing = "";
38543
38746
  try {
38544
- existing = fs76.readFileSync(file, "utf8");
38747
+ existing = fs77.readFileSync(file, "utf8");
38545
38748
  } catch {
38546
38749
  }
38547
38750
  if (existing.includes(AGENT_STANDARD_MARKER)) return;
38548
- fs76.mkdirSync(path84.dirname(file), { recursive: true });
38751
+ fs77.mkdirSync(path85.dirname(file), { recursive: true });
38549
38752
  const next = existing.trim() ? `${existing.trimEnd()}
38550
38753
 
38551
38754
  ${AGENT_STANDARD_BLOCK}
38552
38755
  ` : `${AGENT_STANDARD_BLOCK}
38553
38756
  `;
38554
- fs76.writeFileSync(file, next);
38757
+ fs77.writeFileSync(file, next);
38555
38758
  } catch {
38556
38759
  }
38557
38760
  }
38558
38761
  var _agentStandardSeam = {
38559
38762
  isLocalSession: () => isLocalSession(),
38560
- markerPath: (sessionId) => path84.join(os61.homedir(), ".codeam", "agent-standard", `${sessionId}.done`),
38561
- exists: (p2) => fs76.existsSync(p2),
38763
+ markerPath: (sessionId) => path85.join(os61.homedir(), ".codeam", "agent-standard", `${sessionId}.done`),
38764
+ exists: (p2) => fs77.existsSync(p2),
38562
38765
  write: (p2) => {
38563
- fs76.mkdirSync(path84.dirname(p2), { recursive: true });
38564
- fs76.writeFileSync(p2, "");
38766
+ fs77.mkdirSync(path85.dirname(p2), { recursive: true });
38767
+ fs77.writeFileSync(p2, "");
38565
38768
  }
38566
38769
  };
38567
38770
  function isClaude(agent) {
@@ -40515,7 +40718,22 @@ async function runAcpSession(opts) {
40515
40718
  emitSwitchEvent
40516
40719
  );
40517
40720
  },
40518
- { id: opts.agent, name: opts.agent, displayName: opts.agent }
40721
+ { id: opts.agent, name: opts.agent, displayName: opts.agent },
40722
+ void 0,
40723
+ void 0,
40724
+ // Pasajero del tick de 20 s que YA existe: re-afirma el preview mientras su
40725
+ // dev server siga vivo, para que el snapshot (1 h de TTL en Redis) no
40726
+ // caduque y la sesión no vuelva al estado vacío al refrescar. Ni un
40727
+ // temporizador nuevo. Ver `services/preview/reaffirm.ts`.
40728
+ //
40729
+ // ⚠️ Va en ESTE relay, el que vive lo que dura la sesión — no en el
40730
+ // `errRelay` del camino de fallo, que es efímero y donde no hay preview
40731
+ // ninguno que afirmar.
40732
+ makePreviewReaffirm({
40733
+ sessionId: opts.sessionId,
40734
+ pluginId: opts.pluginId,
40735
+ pluginAuthToken: opts.pluginAuthToken
40736
+ })
40519
40737
  );
40520
40738
  const HANDOFF_MAX_CHARS = 16e3;
40521
40739
  const pendingHandoff = { current: null };
@@ -40624,14 +40842,14 @@ async function runAcpSession(opts) {
40624
40842
  switchCredentialEnv = provisionAgentCredentials(agentId, auth);
40625
40843
  },
40626
40844
  provisionHouseProxy: ({ baseUrl, token }) => {
40627
- const claudeConfigDir = path85.join(
40845
+ const claudeConfigDir = path86.join(
40628
40846
  os62.homedir(),
40629
40847
  ".codeam",
40630
40848
  "house-claude",
40631
40849
  `switch-${opts.pluginId}`
40632
40850
  );
40633
40851
  try {
40634
- fs77.mkdirSync(claudeConfigDir, { recursive: true, mode: 448 });
40852
+ fs78.mkdirSync(claudeConfigDir, { recursive: true, mode: 448 });
40635
40853
  } catch {
40636
40854
  }
40637
40855
  houseEnv = buildHouseProxyChildEnv({ baseUrl, token, claudeConfigDir });
@@ -41833,8 +42051,8 @@ function startClaudeCredentialSync(opts) {
41833
42051
  }
41834
42052
 
41835
42053
  // src/beads/workflow-hint.ts
41836
- var fs78 = __toESM(require("fs"));
41837
- var path86 = __toESM(require("path"));
42054
+ var fs79 = __toESM(require("fs"));
42055
+ var path87 = __toESM(require("path"));
41838
42056
  var os63 = __toESM(require("os"));
41839
42057
  var BEADS_HINT_MARKER = "<!-- codeam:beads-workflow -->";
41840
42058
  var BEADS_HINT = `${BEADS_HINT_MARKER}
@@ -41851,20 +42069,20 @@ This environment uses **bd (beads)** for issue/task tracking and persistent memo
41851
42069
  ${BEADS_HINT_MARKER}`;
41852
42070
  function ensureBeadsWorkflowHint(homeDir2 = os63.homedir()) {
41853
42071
  try {
41854
- const file = path86.join(homeDir2, ".claude", "CLAUDE.md");
42072
+ const file = path87.join(homeDir2, ".claude", "CLAUDE.md");
41855
42073
  let existing = "";
41856
42074
  try {
41857
- existing = fs78.readFileSync(file, "utf8");
42075
+ existing = fs79.readFileSync(file, "utf8");
41858
42076
  } catch {
41859
42077
  }
41860
42078
  if (existing.includes(BEADS_HINT_MARKER)) return;
41861
- fs78.mkdirSync(path86.dirname(file), { recursive: true });
42079
+ fs79.mkdirSync(path87.dirname(file), { recursive: true });
41862
42080
  const next = existing.trim() ? `${existing.trimEnd()}
41863
42081
 
41864
42082
  ${BEADS_HINT}
41865
42083
  ` : `${BEADS_HINT}
41866
42084
  `;
41867
- fs78.writeFileSync(file, next);
42085
+ fs79.writeFileSync(file, next);
41868
42086
  } catch {
41869
42087
  }
41870
42088
  }
@@ -42162,9 +42380,9 @@ var NativeTuiDriver = class _NativeTuiDriver {
42162
42380
  armSwitchWatch(currentId) {
42163
42381
  this.unwatchSwitch?.();
42164
42382
  this.unwatchSwitch = null;
42165
- const watch3 = this.deps.runtime.watchConversationSwitch;
42166
- if (!watch3) return;
42167
- this.unwatchSwitch = watch3(this.deps.opts.cwd, { currentId }, (id) => {
42383
+ const watch4 = this.deps.runtime.watchConversationSwitch;
42384
+ if (!watch4) return;
42385
+ this.unwatchSwitch = watch4(this.deps.opts.cwd, { currentId }, (id) => {
42168
42386
  this.historySvc.setCurrentConversationId(id);
42169
42387
  this.deps.onConversationSwitch?.(id);
42170
42388
  });
@@ -42375,7 +42593,7 @@ var AcpDriver = class {
42375
42593
  };
42376
42594
 
42377
42595
  // src/baton/transcript-mirror.ts
42378
- var fs79 = __toESM(require("fs"));
42596
+ var fs80 = __toESM(require("fs"));
42379
42597
  var TranscriptMirror = class {
42380
42598
  constructor(deps) {
42381
42599
  this.deps = deps;
@@ -42418,8 +42636,8 @@ var TranscriptMirror = class {
42418
42636
  if (!file) return false;
42419
42637
  this.attached = true;
42420
42638
  this.emit(file);
42421
- const watch3 = this.deps.watch ?? defaultWatch;
42422
- this.unwatch = watch3(file, () => this.emit(file));
42639
+ const watch4 = this.deps.watch ?? defaultWatch;
42640
+ this.unwatch = watch4(file, () => this.emit(file));
42423
42641
  return true;
42424
42642
  }
42425
42643
  clearPoll() {
@@ -42442,7 +42660,7 @@ var TranscriptMirror = class {
42442
42660
  }
42443
42661
  };
42444
42662
  function defaultWatch(file, onChange) {
42445
- const w3 = fs79.watch(file, { persistent: false }, () => onChange());
42663
+ const w3 = fs80.watch(file, { persistent: false }, () => onChange());
42446
42664
  return () => w3.close();
42447
42665
  }
42448
42666
 
@@ -42772,16 +42990,16 @@ function keepDeviceAwake(deps = {}) {
42772
42990
  }
42773
42991
 
42774
42992
  // src/agents/claude/onboarding.ts
42775
- var fs80 = __toESM(require("fs"));
42993
+ var fs81 = __toESM(require("fs"));
42776
42994
  var os65 = __toESM(require("os"));
42777
- var path87 = __toESM(require("path"));
42995
+ var path88 = __toESM(require("path"));
42778
42996
  var ONBOARDING_VERSION_SENTINEL = "9999.0.0";
42779
42997
  function ensureClaudeOnboarded(cwd) {
42780
42998
  try {
42781
- const file = path87.join(os65.homedir(), ".claude.json");
42999
+ const file = path88.join(os65.homedir(), ".claude.json");
42782
43000
  let config = {};
42783
43001
  try {
42784
- config = JSON.parse(fs80.readFileSync(file, "utf8"));
43002
+ config = JSON.parse(fs81.readFileSync(file, "utf8"));
42785
43003
  } catch {
42786
43004
  }
42787
43005
  let changed = false;
@@ -42806,8 +43024,8 @@ function ensureClaudeOnboarded(cwd) {
42806
43024
  }
42807
43025
  }
42808
43026
  if (!changed) return;
42809
- fs80.mkdirSync(path87.dirname(file), { recursive: true });
42810
- fs80.writeFileSync(file, JSON.stringify(config, null, 2));
43027
+ fs81.mkdirSync(path88.dirname(file), { recursive: true });
43028
+ fs81.writeFileSync(file, JSON.stringify(config, null, 2));
42811
43029
  log.info(
42812
43030
  "claude",
42813
43031
  `pre-completed Claude onboarding${cwd ? ` + trusted workspace ${cwd}` : ""}`
@@ -43141,9 +43359,23 @@ async function start(requestedAgent, presetSession) {
43141
43359
  agentId: session.agent,
43142
43360
  pluginAuthToken: session.pluginAuthToken ?? void 0
43143
43361
  };
43144
- const relay = new CommandRelayService(pluginId, async (cmd) => {
43145
- await dispatchCommand(ctx, cmd);
43146
- }, runtime.meta);
43362
+ const relay = new CommandRelayService(
43363
+ pluginId,
43364
+ async (cmd) => {
43365
+ await dispatchCommand(ctx, cmd);
43366
+ },
43367
+ runtime.meta,
43368
+ void 0,
43369
+ void 0,
43370
+ // Pasajero del tick de 20 s que ya existe: re-afirma el preview para que
43371
+ // su snapshot (1 h de TTL en Redis) no caduque con el dev server vivo.
43372
+ // Ni un temporizador nuevo. Ver `services/preview/reaffirm.ts`.
43373
+ makePreviewReaffirm({
43374
+ sessionId: session.id,
43375
+ pluginId,
43376
+ pluginAuthToken: session.pluginAuthToken
43377
+ })
43378
+ );
43147
43379
  ctx.relay = relay;
43148
43380
  void beadsReady.then((started) => {
43149
43381
  ctx.beads = started;
@@ -43544,7 +43776,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
43544
43776
  var import_child_process31 = require("child_process");
43545
43777
  var import_util4 = require("util");
43546
43778
  var import_picocolors9 = __toESM(require("picocolors"));
43547
- var path88 = __toESM(require("path"));
43779
+ var path89 = __toESM(require("path"));
43548
43780
  var execFileP6 = (0, import_util4.promisify)(import_child_process31.execFile);
43549
43781
  var MAX_BUFFER = 8 * 1024 * 1024;
43550
43782
  function resetStdinForChild() {
@@ -44033,7 +44265,7 @@ var GitHubCodespacesProvider = class {
44033
44265
  });
44034
44266
  }
44035
44267
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
44036
- const remoteDir = path88.posix.dirname(remotePath);
44268
+ const remoteDir = path89.posix.dirname(remotePath);
44037
44269
  const parts = [
44038
44270
  `mkdir -p ${shellQuote(remoteDir)}`,
44039
44271
  `cat > ${shellQuote(remotePath)}`
@@ -44103,7 +44335,7 @@ function shellQuote(s) {
44103
44335
  // src/services/providers/gitpod.ts
44104
44336
  var import_child_process32 = require("child_process");
44105
44337
  var import_util5 = require("util");
44106
- var path89 = __toESM(require("path"));
44338
+ var path90 = __toESM(require("path"));
44107
44339
  var import_picocolors10 = __toESM(require("picocolors"));
44108
44340
  var execFileP7 = (0, import_util5.promisify)(import_child_process32.execFile);
44109
44341
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -44343,7 +44575,7 @@ var GitpodProvider = class {
44343
44575
  });
44344
44576
  }
44345
44577
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
44346
- const remoteDir = path89.posix.dirname(remotePath);
44578
+ const remoteDir = path90.posix.dirname(remotePath);
44347
44579
  const parts = [
44348
44580
  `mkdir -p ${shellQuote2(remoteDir)}`,
44349
44581
  `cat > ${shellQuote2(remotePath)}`
@@ -44379,7 +44611,7 @@ function shellQuote2(s) {
44379
44611
  // src/services/providers/gitlab-workspaces.ts
44380
44612
  var import_child_process33 = require("child_process");
44381
44613
  var import_util6 = require("util");
44382
- var path90 = __toESM(require("path"));
44614
+ var path91 = __toESM(require("path"));
44383
44615
  var execFileP8 = (0, import_util6.promisify)(import_child_process33.execFile);
44384
44616
  var MAX_BUFFER3 = 8 * 1024 * 1024;
44385
44617
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -44639,7 +44871,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
44639
44871
  }
44640
44872
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
44641
44873
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
44642
- const remoteDir = path90.posix.dirname(remotePath);
44874
+ const remoteDir = path91.posix.dirname(remotePath);
44643
44875
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
44644
44876
  if (options.mode != null) {
44645
44877
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -44707,7 +44939,7 @@ function shellQuote3(s) {
44707
44939
  // src/services/providers/railway.ts
44708
44940
  var import_child_process34 = require("child_process");
44709
44941
  var import_util7 = require("util");
44710
- var path91 = __toESM(require("path"));
44942
+ var path92 = __toESM(require("path"));
44711
44943
  var execFileP9 = (0, import_util7.promisify)(import_child_process34.execFile);
44712
44944
  var MAX_BUFFER4 = 8 * 1024 * 1024;
44713
44945
  function resetStdinForChild4() {
@@ -44943,7 +45175,7 @@ var RailwayProvider = class {
44943
45175
  if (!projectId || !serviceId) {
44944
45176
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
44945
45177
  }
44946
- const remoteDir = path91.posix.dirname(remotePath);
45178
+ const remoteDir = path92.posix.dirname(remotePath);
44947
45179
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
44948
45180
  if (options.mode != null) {
44949
45181
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -45589,8 +45821,8 @@ async function invite() {
45589
45821
  var import_node_dns = require("dns");
45590
45822
  var import_node_util5 = require("util");
45591
45823
  var import_node_crypto13 = require("crypto");
45592
- var fs81 = __toESM(require("fs"));
45593
- var path92 = __toESM(require("path"));
45824
+ var fs82 = __toESM(require("fs"));
45825
+ var path93 = __toESM(require("path"));
45594
45826
  var import_picocolors14 = __toESM(require("picocolors"));
45595
45827
  var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
45596
45828
  async function checkDns(apiBase2) {
@@ -45646,13 +45878,13 @@ async function checkHealth(apiBase2) {
45646
45878
  }
45647
45879
  }
45648
45880
  function checkConfigDir() {
45649
- const dir = path92.join(require("os").homedir(), ".codeam");
45881
+ const dir = path93.join(require("os").homedir(), ".codeam");
45650
45882
  try {
45651
- fs81.mkdirSync(dir, { recursive: true, mode: 448 });
45652
- const probe = path92.join(dir, ".doctor-probe");
45653
- fs81.writeFileSync(probe, "ok", { mode: 384 });
45654
- const read2 = fs81.readFileSync(probe, "utf8");
45655
- fs81.unlinkSync(probe);
45883
+ fs82.mkdirSync(dir, { recursive: true, mode: 448 });
45884
+ const probe = path93.join(dir, ".doctor-probe");
45885
+ fs82.writeFileSync(probe, "ok", { mode: 384 });
45886
+ const read2 = fs82.readFileSync(probe, "utf8");
45887
+ fs82.unlinkSync(probe);
45656
45888
  if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
45657
45889
  return {
45658
45890
  id: "config-dir",
@@ -45716,7 +45948,7 @@ function checkNodePty() {
45716
45948
  detail: "not required on this platform"
45717
45949
  };
45718
45950
  }
45719
- const vendoredPath = path92.join(__dirname, "vendor", "node-pty");
45951
+ const vendoredPath = path93.join(__dirname, "vendor", "node-pty");
45720
45952
  for (const target of [vendoredPath, "node-pty"]) {
45721
45953
  try {
45722
45954
  require(target);
@@ -45758,7 +45990,7 @@ function checkChokidar() {
45758
45990
  }
45759
45991
  async function doctor(args2 = []) {
45760
45992
  const json = args2.includes("--json");
45761
- const cliVersion = true ? "2.67.3" : "0.0.0-dev";
45993
+ const cliVersion = true ? "2.67.6" : "0.0.0-dev";
45762
45994
  const apiBase2 = resolveApiBaseUrl();
45763
45995
  const diagnosticId = (0, import_node_crypto13.randomUUID)();
45764
45996
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -46149,7 +46381,7 @@ async function mcpRun(args2) {
46149
46381
  // src/commands/version.ts
46150
46382
  var import_picocolors15 = __toESM(require("picocolors"));
46151
46383
  function version2() {
46152
- const v = true ? "2.67.3" : "unknown";
46384
+ const v = true ? "2.67.6" : "unknown";
46153
46385
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
46154
46386
  }
46155
46387