@sideboard-ai/core 0.1.235 → 0.1.236

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 (67) hide show
  1. package/dist/{abletime-WZNDTRVL.js → abletime-KOGCIQCO.js} +5 -5
  2. package/dist/{abletime-BGVOCEOU.js → abletime-VSV6AUBV.js} +5 -5
  3. package/dist/{abletime-oauth-ZLU2EYRK.js → abletime-oauth-LY7KZICW.js} +4 -4
  4. package/dist/{abletime-oauth-6M5GWEPX.js → abletime-oauth-QMDV45JC.js} +4 -4
  5. package/dist/{abletime-rest-WNHIATB3.js → abletime-rest-LXOWKPL7.js} +4 -4
  6. package/dist/{abletime-rest-F7XG5NGY.js → abletime-rest-NL56UVK5.js} +4 -4
  7. package/dist/agents/cursor-runner.cjs +39 -35
  8. package/dist/agents/cursor-runner.js +3 -3
  9. package/dist/{agents-37JCAVSC.js → agents-JC6DRIT3.js} +9 -9
  10. package/dist/{agents-MOMMKSYV.js → agents-S4HYHRL3.js} +8 -8
  11. package/dist/{app-settings-KBL2G7M4.js → app-settings-2CFCRYD7.js} +2 -2
  12. package/dist/{app-settings-UXWCPDEA.js → app-settings-I27UBVI4.js} +2 -2
  13. package/dist/{caffeinate-hold-OK4JJ5PP.js → caffeinate-hold-FNKIPXDU.js} +2 -2
  14. package/dist/{caffeinate-hold-22VFDPSO.js → caffeinate-hold-PXHGH7ZN.js} +2 -2
  15. package/dist/{chunk-7J72QJOM.js → chunk-224IXQOM.js} +1 -1
  16. package/dist/{chunk-4VGCG2HV.js → chunk-3AJUH66R.js} +2 -2
  17. package/dist/{chunk-P6ZM5QJW.js → chunk-3PGFAVFL.js} +2 -2
  18. package/dist/{chunk-RZTRWN2V.js → chunk-4H5WO4H3.js} +1 -1
  19. package/dist/{chunk-MVLXDYN5.js → chunk-5ELC3KK3.js} +5 -5
  20. package/dist/{chunk-WPD7BR6C.js → chunk-5SHYLRTU.js} +1 -1
  21. package/dist/{chunk-S2OEFXST.js → chunk-5UN5C5WP.js} +5 -5
  22. package/dist/{chunk-LJWF3VA3.js → chunk-6Q2CFQ4D.js} +74 -30
  23. package/dist/{chunk-WFUDY6PC.js → chunk-A4JGXX2F.js} +155 -24
  24. package/dist/{chunk-EAYXD2IC.js → chunk-ANGPU5JL.js} +282 -14
  25. package/dist/{chunk-GHRZNPBK.js → chunk-C2CBF4YE.js} +2 -2
  26. package/dist/{chunk-TNVJPFHM.js → chunk-CJKL7A4G.js} +5 -5
  27. package/dist/{chunk-SWNEA5OZ.js → chunk-CRAXJAYJ.js} +3 -3
  28. package/dist/{chunk-C774RJJA.js → chunk-CWHMLCLN.js} +3 -3
  29. package/dist/{chunk-YWI3IBP2.js → chunk-DQN5U2VH.js} +1 -1
  30. package/dist/{chunk-D4VKJO5C.js → chunk-DYXNBXE3.js} +304 -16
  31. package/dist/{chunk-SPAMHHJH.js → chunk-J5GON4SU.js} +1 -1
  32. package/dist/{chunk-4VFOJZPS.js → chunk-JXZS56VW.js} +3 -3
  33. package/dist/{chunk-EQNRWDLN.js → chunk-KK63BFYN.js} +151 -24
  34. package/dist/{chunk-X5B3OS5I.js → chunk-N6XI5KXL.js} +1 -1
  35. package/dist/{chunk-XJETIO4K.js → chunk-NJ5OXOTN.js} +2 -2
  36. package/dist/{chunk-RGNPPRZZ.js → chunk-NYAEMZ3L.js} +3 -3
  37. package/dist/{chunk-7H2CVVLF.js → chunk-O3UAQAYA.js} +3 -3
  38. package/dist/{chunk-4TYXWPAJ.js → chunk-OJFEVWZN.js} +1 -1
  39. package/dist/{chunk-I5NC7DWO.js → chunk-P3DCZRER.js} +1 -1
  40. package/dist/{chunk-TWXSZYR2.js → chunk-RRXRLHIE.js} +5 -5
  41. package/dist/{chunk-AS4UN7QL.js → chunk-VVOAXBND.js} +5 -5
  42. package/dist/{chunk-7366AB7E.js → chunk-XMCJDWPA.js} +77 -32
  43. package/dist/{connected-teams-KQUDU7LZ.js → connected-teams-62AJRDDD.js} +2 -2
  44. package/dist/{connected-teams-JUJAQZZE.js → connected-teams-GXV22ZSF.js} +2 -2
  45. package/dist/{coordinator-prompt-CE7MN6QY.js → coordinator-prompt-2BRUH7PJ.js} +6 -6
  46. package/dist/{coordinator-prompt-IGDMFKCD.js → coordinator-prompt-BIP7ZEJ3.js} +6 -6
  47. package/dist/{cursor-recover-DTQAUDGO.js → cursor-recover-DFMCTZA4.js} +2 -2
  48. package/dist/{cursor-recover-4PQAADAU.js → cursor-recover-K3EBEM7M.js} +2 -2
  49. package/dist/{global-workspace-7WH24UFO.js → global-workspace-3XZN3QHZ.js} +6 -6
  50. package/dist/{global-workspace-NCIC2Y2U.js → global-workspace-DWCFG7LP.js} +6 -6
  51. package/dist/index.cjs +1219 -707
  52. package/dist/index.d.cts +70 -1
  53. package/dist/index.d.ts +70 -1
  54. package/dist/index.js +79 -23
  55. package/dist/mcp/run-stdio.cjs +1123 -659
  56. package/dist/mcp/run-stdio.js +45 -22
  57. package/dist/{orchestrator-6NPBOBNA.js → orchestrator-AYPDBGIF.js} +10 -10
  58. package/dist/{orchestrator-RKWRI3PJ.js → orchestrator-TEJJAQWP.js} +11 -11
  59. package/dist/{paths-C2VERLAE.js → paths-LGKOG7MY.js} +1 -1
  60. package/dist/{paths-LOXCISLX.js → paths-O6ZEAEUD.js} +1 -1
  61. package/dist/{thread-store-IKJD4EOK.js → thread-store-AYPBEZT5.js} +3 -3
  62. package/dist/{thread-store-FBK5SZ5P.js → thread-store-YOPKY74K.js} +3 -3
  63. package/dist/{workspaces-H2TRFDE2.js → workspaces-NYT2472Z.js} +6 -6
  64. package/dist/{workspaces-NSQZSDQD.js → workspaces-V7522TQH.js} +6 -6
  65. package/dist/{worktree-W7BSI4GU.js → worktree-AGVPKDBH.js} +5 -5
  66. package/dist/{worktree-FMIX4BRV.js → worktree-IRALYI6A.js} +5 -5
  67. package/package.json +1 -1
@@ -202,10 +202,139 @@ var init_cursor_worktrees = __esm({
202
202
  }
203
203
  });
204
204
 
205
+ // src/hook/dev-preview.ts
206
+ function parseDevPreview(raw) {
207
+ return raw === "url" || raw === "window" ? raw : void 0;
208
+ }
209
+ function commandLooksLikeElectron(command) {
210
+ return ELECTRON_CMD_RE.test(command);
211
+ }
212
+ function pnpmFilterPackage(command) {
213
+ const m = command.match(PNPM_FILTER_RE);
214
+ return m?.[1] ?? m?.[2] ?? m?.[3] ?? null;
215
+ }
216
+ function readJsonObject(path) {
217
+ try {
218
+ const raw = JSON.parse((0, import_node_fs3.readFileSync)(path, "utf8"));
219
+ return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : null;
220
+ } catch {
221
+ return null;
222
+ }
223
+ }
224
+ function packageLooksLikeElectron(pkg) {
225
+ const deps = {
226
+ ...pkg.dependencies,
227
+ ...pkg.devDependencies,
228
+ ...pkg.optionalDependencies
229
+ };
230
+ if (deps.electron || deps["electron-vite"] || deps["electron-builder"] || deps["@electron-forge/cli"] || deps["electron-forge"]) {
231
+ return true;
232
+ }
233
+ const scripts = pkg.scripts;
234
+ if (scripts && typeof scripts === "object") {
235
+ for (const value of Object.values(scripts)) {
236
+ if (typeof value === "string" && commandLooksLikeElectron(value)) {
237
+ return true;
238
+ }
239
+ }
240
+ }
241
+ return false;
242
+ }
243
+ function findPackageJsonByName(root, name, budget = 80) {
244
+ const queue = [root];
245
+ let seen = 0;
246
+ while (queue.length && seen < budget) {
247
+ const dir = queue.shift();
248
+ const pkgPath = (0, import_node_path3.join)(dir, "package.json");
249
+ if ((0, import_node_fs3.existsSync)(pkgPath)) {
250
+ seen += 1;
251
+ const pkg = readJsonObject(pkgPath);
252
+ if (pkg?.name === name) return pkgPath;
253
+ }
254
+ let entries;
255
+ try {
256
+ entries = (0, import_node_fs3.readdirSync)(dir, { withFileTypes: true });
257
+ } catch {
258
+ continue;
259
+ }
260
+ for (const entry of entries) {
261
+ if (!entry.isDirectory() || entry.isSymbolicLink() || SKIP_DIR.has(entry.name) || entry.name.startsWith(".")) {
262
+ continue;
263
+ }
264
+ queue.push((0, import_node_path3.join)(dir, entry.name));
265
+ }
266
+ }
267
+ return null;
268
+ }
269
+ function classifyRunScriptPreview(opts) {
270
+ if (opts.preview === "url" || opts.preview === "window") return opts.preview;
271
+ if (commandLooksLikeElectron(opts.command)) return "window";
272
+ const root = opts.worktreePath?.trim();
273
+ if (!root) return "url";
274
+ const filter = pnpmFilterPackage(opts.command);
275
+ if (filter) {
276
+ if (filter.startsWith(".") || filter.startsWith("/")) {
277
+ const pkg = readJsonObject((0, import_node_path3.join)(root, filter, "package.json"));
278
+ if (pkg && packageLooksLikeElectron(pkg)) return "window";
279
+ } else {
280
+ const found = findPackageJsonByName(root, filter);
281
+ if (found) {
282
+ const pkg = readJsonObject(found);
283
+ if (pkg && packageLooksLikeElectron(pkg)) return "window";
284
+ return "url";
285
+ }
286
+ }
287
+ }
288
+ const rootPkg = readJsonObject((0, import_node_path3.join)(root, "package.json"));
289
+ if (rootPkg && packageLooksLikeElectron(rootPkg)) return "window";
290
+ return "url";
291
+ }
292
+ function runScriptPreview(script, worktreePath) {
293
+ if (!script) return "url";
294
+ return classifyRunScriptPreview({
295
+ command: script.command,
296
+ preview: script.preview,
297
+ worktreePath
298
+ });
299
+ }
300
+ function activeRunPreview(scriptName, scripts, worktreePath) {
301
+ return runScriptPreview(
302
+ scripts.find((s) => s.name === scriptName),
303
+ worktreePath
304
+ );
305
+ }
306
+ function annotateDevAccessRuns(runs, scripts, worktreePath) {
307
+ return runs.map((run2) => ({
308
+ ...run2,
309
+ preview: activeRunPreview(run2.scriptName, scripts, worktreePath)
310
+ }));
311
+ }
312
+ var import_node_fs3, import_node_path3, ELECTRON_CMD_RE, PNPM_FILTER_RE, SKIP_DIR;
313
+ var init_dev_preview = __esm({
314
+ "src/hook/dev-preview.ts"() {
315
+ "use strict";
316
+ import_node_fs3 = require("fs");
317
+ import_node_path3 = require("path");
318
+ ELECTRON_CMD_RE = /\belectron(?:-vite|-forge|-builder|mon)?\b/i;
319
+ PNPM_FILTER_RE = /--filter(?:=|\s+)(?:"([^"]+)"|'([^']+)'|([^\s]+))/;
320
+ SKIP_DIR = /* @__PURE__ */ new Set([
321
+ "node_modules",
322
+ "dist",
323
+ "out",
324
+ "coverage",
325
+ ".git",
326
+ ".context",
327
+ ".next",
328
+ ".turbo",
329
+ ".output"
330
+ ]);
331
+ }
332
+ });
333
+
205
334
  // src/hook/settings.ts
206
335
  function expandHome(path) {
207
336
  if (path.startsWith("~/") || path === "~") {
208
- return (0, import_node_path3.join)((0, import_node_os.homedir)(), path.slice(2));
337
+ return (0, import_node_path4.join)((0, import_node_os.homedir)(), path.slice(2));
209
338
  }
210
339
  return path;
211
340
  }
@@ -218,8 +347,8 @@ function parseAvailableIn(raw) {
218
347
  return out.length ? out : void 0;
219
348
  }
220
349
  function parseSettingsFile(path, source) {
221
- if (!(0, import_node_fs3.existsSync)(path)) return null;
222
- const raw = (0, import_node_fs3.readFileSync)(path, "utf8");
350
+ if (!(0, import_node_fs4.existsSync)(path)) return null;
351
+ const raw = (0, import_node_fs4.readFileSync)(path, "utf8");
223
352
  const data = (0, import_smol_toml.parse)(raw);
224
353
  const scripts = data.scripts ?? {};
225
354
  const setup = typeof scripts.setup === "string" ? scripts.setup : void 0;
@@ -257,7 +386,8 @@ function parseSettingsFile(path, source) {
257
386
  command: value.command,
258
387
  default: Boolean(value.default),
259
388
  icon: typeof value.icon === "string" ? value.icon : void 0,
260
- availableIn: parseAvailableIn(value.available_in)
389
+ availableIn: parseAvailableIn(value.available_in),
390
+ preview: parseDevPreview(value.preview)
261
391
  });
262
392
  }
263
393
  }
@@ -328,15 +458,15 @@ function finalizeSettings(parsed) {
328
458
  };
329
459
  }
330
460
  function familyFiles(rootPath, source) {
331
- const dir = (0, import_node_path3.join)(rootPath, `.${source}`);
461
+ const dir = (0, import_node_path4.join)(rootPath, `.${source}`);
332
462
  return {
333
- toml: (0, import_node_path3.join)(dir, "settings.toml"),
334
- local: (0, import_node_path3.join)(dir, "settings.local.toml")
463
+ toml: (0, import_node_path4.join)(dir, "settings.toml"),
464
+ local: (0, import_node_path4.join)(dir, "settings.local.toml")
335
465
  };
336
466
  }
337
467
  function familyExists(rootPath, source) {
338
468
  const files = familyFiles(rootPath, source);
339
- return (0, import_node_fs3.existsSync)(files.toml) || (0, import_node_fs3.existsSync)(files.local);
469
+ return (0, import_node_fs4.existsSync)(files.toml) || (0, import_node_fs4.existsSync)(files.local);
340
470
  }
341
471
  function detectFamily(rootPath) {
342
472
  if (familyExists(rootPath, "sideboard")) return "sideboard";
@@ -383,10 +513,10 @@ function settingsSourceLabel(rootPath) {
383
513
  const family = detectFamily(rootPath);
384
514
  if (!family) return null;
385
515
  const files = familyFiles(rootPath, family);
386
- if ((0, import_node_fs3.existsSync)(files.toml) && (0, import_node_fs3.existsSync)(files.local)) {
516
+ if ((0, import_node_fs4.existsSync)(files.toml) && (0, import_node_fs4.existsSync)(files.local)) {
387
517
  return `.${family}/settings.toml + local`;
388
518
  }
389
- if ((0, import_node_fs3.existsSync)(files.local)) return `.${family}/settings.local.toml`;
519
+ if ((0, import_node_fs4.existsSync)(files.local)) return `.${family}/settings.local.toml`;
390
520
  return `.${family}/settings.toml`;
391
521
  }
392
522
  function workspaceSettingsSourceLabel(worktreePath, repoPath) {
@@ -398,16 +528,17 @@ function workspaceSettingsSourceLabel(worktreePath, repoPath) {
398
528
  }
399
529
  return null;
400
530
  }
401
- var import_node_fs3, import_node_os, import_node_path3, import_smol_toml;
531
+ var import_node_fs4, import_node_os, import_node_path4, import_smol_toml;
402
532
  var init_settings = __esm({
403
533
  "src/hook/settings.ts"() {
404
534
  "use strict";
405
- import_node_fs3 = require("fs");
535
+ import_node_fs4 = require("fs");
406
536
  import_node_os = require("os");
407
- import_node_path3 = require("path");
537
+ import_node_path4 = require("path");
408
538
  import_smol_toml = require("smol-toml");
409
539
  init_convention_setup();
410
540
  init_cursor_worktrees();
541
+ init_dev_preview();
411
542
  }
412
543
  });
413
544
 
@@ -429,70 +560,70 @@ __export(paths_exports, {
429
560
  });
430
561
  function appDataDir() {
431
562
  const override = process.env.SIDEBOARD_APP_DATA?.trim();
432
- const base = override ? override : process.platform === "darwin" ? (0, import_node_path5.join)((0, import_node_os2.homedir)(), "Library", "Application Support", "sideboard") : process.platform === "win32" ? (0, import_node_path5.join)(process.env.APPDATA ?? (0, import_node_path5.join)((0, import_node_os2.homedir)(), "AppData", "Roaming"), "sideboard") : (0, import_node_path5.join)((0, import_node_os2.homedir)(), ".local", "share", "sideboard");
433
- (0, import_node_fs4.mkdirSync)(base, { recursive: true });
563
+ const base = override ? override : process.platform === "darwin" ? (0, import_node_path6.join)((0, import_node_os2.homedir)(), "Library", "Application Support", "sideboard") : process.platform === "win32" ? (0, import_node_path6.join)(process.env.APPDATA ?? (0, import_node_path6.join)((0, import_node_os2.homedir)(), "AppData", "Roaming"), "sideboard") : (0, import_node_path6.join)((0, import_node_os2.homedir)(), ".local", "share", "sideboard");
564
+ (0, import_node_fs5.mkdirSync)(base, { recursive: true });
434
565
  return base;
435
566
  }
436
567
  function threadsDir() {
437
- const dir = (0, import_node_path5.join)(appDataDir(), "threads");
438
- (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
568
+ const dir = (0, import_node_path6.join)(appDataDir(), "threads");
569
+ (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
439
570
  return dir;
440
571
  }
441
572
  function locksDir() {
442
- const dir = (0, import_node_path5.join)(appDataDir(), "locks");
443
- (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
573
+ const dir = (0, import_node_path6.join)(appDataDir(), "locks");
574
+ (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
444
575
  return dir;
445
576
  }
446
577
  function sideboardHomeDir() {
447
- const dir = (0, import_node_path5.join)((0, import_node_os2.homedir)(), "sideboard");
448
- (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
578
+ const dir = (0, import_node_path6.join)((0, import_node_os2.homedir)(), "sideboard");
579
+ (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
449
580
  return dir;
450
581
  }
451
582
  function sideboardReposDir() {
452
- const dir = (0, import_node_path5.join)(sideboardHomeDir(), "repos");
453
- (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
583
+ const dir = (0, import_node_path6.join)(sideboardHomeDir(), "repos");
584
+ (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
454
585
  return dir;
455
586
  }
456
587
  function sideboardWorkspacesDir() {
457
- const dir = (0, import_node_path5.join)(sideboardHomeDir(), "workspaces");
458
- (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
588
+ const dir = (0, import_node_path6.join)(sideboardHomeDir(), "workspaces");
589
+ (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
459
590
  return dir;
460
591
  }
461
592
  function repoSlug(repoPath) {
462
- return (0, import_node_path4.basename)(repoPath.replace(/\/$/, "")) || "repo";
593
+ return (0, import_node_path5.basename)(repoPath.replace(/\/$/, "")) || "repo";
463
594
  }
464
595
  function worktreesRoot(repoPath) {
465
596
  const settings = loadRepoSettings(repoPath);
466
597
  if (settings?.worktreesRoot) {
467
- (0, import_node_fs4.mkdirSync)(settings.worktreesRoot, { recursive: true });
598
+ (0, import_node_fs5.mkdirSync)(settings.worktreesRoot, { recursive: true });
468
599
  return settings.worktreesRoot;
469
600
  }
470
- const dir = (0, import_node_path5.join)(sideboardWorkspacesDir(), repoSlug(repoPath));
471
- (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
601
+ const dir = (0, import_node_path6.join)(sideboardWorkspacesDir(), repoSlug(repoPath));
602
+ (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
472
603
  return dir;
473
604
  }
474
605
  function threadFilePath(id) {
475
- return (0, import_node_path5.join)(threadsDir(), `${id}.json`);
606
+ return (0, import_node_path6.join)(threadsDir(), `${id}.json`);
476
607
  }
477
608
  function threadLivePath(id) {
478
- return (0, import_node_path5.join)(threadsDir(), `${id}.live.json`);
609
+ return (0, import_node_path6.join)(threadsDir(), `${id}.live.json`);
479
610
  }
480
611
  function threadLockPath(id) {
481
- return (0, import_node_path5.join)(locksDir(), `${id}.lock`);
612
+ return (0, import_node_path6.join)(locksDir(), `${id}.lock`);
482
613
  }
483
614
  function globalAgentCwd() {
484
- const dir = (0, import_node_path5.join)(appDataDir(), "global");
485
- (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
615
+ const dir = (0, import_node_path6.join)(appDataDir(), "global");
616
+ (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
486
617
  return dir;
487
618
  }
488
- var import_node_path4, import_node_os2, import_node_path5, import_node_fs4;
619
+ var import_node_path5, import_node_os2, import_node_path6, import_node_fs5;
489
620
  var init_paths = __esm({
490
621
  "src/store/paths.ts"() {
491
622
  "use strict";
492
- import_node_path4 = require("path");
493
- import_node_os2 = require("os");
494
623
  import_node_path5 = require("path");
495
- import_node_fs4 = require("fs");
624
+ import_node_os2 = require("os");
625
+ import_node_path6 = require("path");
626
+ import_node_fs5 = require("fs");
496
627
  init_settings();
497
628
  }
498
629
  });
@@ -503,7 +634,7 @@ function splitPemCertificates(pem) {
503
634
  }
504
635
  function readExistingFile(path) {
505
636
  try {
506
- return (0, import_node_fs5.existsSync)(path) ? (0, import_node_fs5.readFileSync)(path, "utf8") : "";
637
+ return (0, import_node_fs6.existsSync)(path) ? (0, import_node_fs6.readFileSync)(path, "utf8") : "";
507
638
  } catch {
508
639
  return "";
509
640
  }
@@ -535,13 +666,13 @@ function collectSystemCaPem(io = {}) {
535
666
  return "";
536
667
  }
537
668
  function systemCaBundlePath(io = {}) {
538
- return (0, import_node_path6.join)((io.appData ?? appDataDir)(), BUNDLE_NAME);
669
+ return (0, import_node_path7.join)((io.appData ?? appDataDir)(), BUNDLE_NAME);
539
670
  }
540
671
  function bundleIsFresh(path, now) {
541
672
  try {
542
- if (!(0, import_node_fs5.existsSync)(path)) return false;
543
- if (splitPemCertificates((0, import_node_fs5.readFileSync)(path, "utf8")).length === 0) return false;
544
- return now - (0, import_node_fs5.statSync)(path).mtimeMs < BUNDLE_MAX_AGE_MS;
673
+ if (!(0, import_node_fs6.existsSync)(path)) return false;
674
+ if (splitPemCertificates((0, import_node_fs6.readFileSync)(path, "utf8")).length === 0) return false;
675
+ return now - (0, import_node_fs6.statSync)(path).mtimeMs < BUNDLE_MAX_AGE_MS;
545
676
  } catch {
546
677
  return false;
547
678
  }
@@ -562,11 +693,11 @@ function materializeSystemCaBundle(io = {}) {
562
693
  if (bundleIsFresh(dest, now)) return dest;
563
694
  const pem = collectSystemCaPem(io);
564
695
  if (splitPemCertificates(pem).length === 0) {
565
- return (0, import_node_fs5.existsSync)(dest) && splitPemCertificates(readExistingFile(dest)).length > 0 ? dest : void 0;
696
+ return (0, import_node_fs6.existsSync)(dest) && splitPemCertificates(readExistingFile(dest)).length > 0 ? dest : void 0;
566
697
  }
567
698
  try {
568
- (0, import_node_fs5.mkdirSync)((0, import_node_path6.dirname)(dest), { recursive: true });
569
- (0, import_node_fs5.writeFileSync)(dest, pem.endsWith("\n") ? pem : `${pem}
699
+ (0, import_node_fs6.mkdirSync)((0, import_node_path7.dirname)(dest), { recursive: true });
700
+ (0, import_node_fs6.writeFileSync)(dest, pem.endsWith("\n") ? pem : `${pem}
570
701
  `, { mode: 384 });
571
702
  return dest;
572
703
  } catch {
@@ -606,13 +737,13 @@ function trustSystemCertificates(io = {}) {
606
737
  return false;
607
738
  }
608
739
  }
609
- var import_node_child_process, import_node_fs5, import_node_path6, import_node_tls, NODE_USE_SYSTEM_CA, NODE_EXTRA_CA_CERTS, BUNDLE_NAME, BUNDLE_MAX_AGE_MS, LINUX_CA_FILES, PEM_CERT_RE;
740
+ var import_node_child_process, import_node_fs6, import_node_path7, import_node_tls, NODE_USE_SYSTEM_CA, NODE_EXTRA_CA_CERTS, BUNDLE_NAME, BUNDLE_MAX_AGE_MS, LINUX_CA_FILES, PEM_CERT_RE;
610
741
  var init_system_ca = __esm({
611
742
  "src/http/system-ca.ts"() {
612
743
  "use strict";
613
744
  import_node_child_process = require("child_process");
614
- import_node_fs5 = require("fs");
615
- import_node_path6 = require("path");
745
+ import_node_fs6 = require("fs");
746
+ import_node_path7 = require("path");
616
747
  import_node_tls = __toESM(require("tls"), 1);
617
748
  init_paths();
618
749
  NODE_USE_SYSTEM_CA = "NODE_USE_SYSTEM_CA";
@@ -631,22 +762,22 @@ var init_system_ca = __esm({
631
762
 
632
763
  // src/store/private-file.ts
633
764
  function writePrivateFile(path, contents) {
634
- (0, import_node_fs6.mkdirSync)((0, import_node_path7.dirname)(path), { recursive: true });
635
- (0, import_node_fs6.writeFileSync)(path, contents, { encoding: "utf8", mode: PRIVATE_FILE_MODE });
765
+ (0, import_node_fs7.mkdirSync)((0, import_node_path8.dirname)(path), { recursive: true });
766
+ (0, import_node_fs7.writeFileSync)(path, contents, { encoding: "utf8", mode: PRIVATE_FILE_MODE });
636
767
  chmodOwnerOnly(path);
637
768
  }
638
769
  function chmodOwnerOnly(path) {
639
770
  try {
640
- (0, import_node_fs6.chmodSync)(path, PRIVATE_FILE_MODE);
771
+ (0, import_node_fs7.chmodSync)(path, PRIVATE_FILE_MODE);
641
772
  } catch {
642
773
  }
643
774
  }
644
- var import_node_fs6, import_node_path7, PRIVATE_FILE_MODE;
775
+ var import_node_fs7, import_node_path8, PRIVATE_FILE_MODE;
645
776
  var init_private_file = __esm({
646
777
  "src/store/private-file.ts"() {
647
778
  "use strict";
648
- import_node_fs6 = require("fs");
649
- import_node_path7 = require("path");
779
+ import_node_fs7 = require("fs");
780
+ import_node_path8 = require("path");
650
781
  PRIVATE_FILE_MODE = 384;
651
782
  }
652
783
  });
@@ -732,11 +863,11 @@ function decryptEnvelope(envelope, key) {
732
863
  return JSON.parse(plaintext.toString("utf8"));
733
864
  }
734
865
  function readSecureJson(path) {
735
- if (!(0, import_node_fs7.existsSync)(path)) return null;
866
+ if (!(0, import_node_fs8.existsSync)(path)) return null;
736
867
  chmodOwnerOnly(path);
737
868
  let parsed;
738
869
  try {
739
- parsed = JSON.parse((0, import_node_fs7.readFileSync)(path, "utf8"));
870
+ parsed = JSON.parse((0, import_node_fs8.readFileSync)(path, "utf8"));
740
871
  } catch {
741
872
  return null;
742
873
  }
@@ -756,20 +887,20 @@ function writeSecureJson(path, value) {
756
887
  `);
757
888
  }
758
889
  function isSecureFileEncrypted(path) {
759
- if (!(0, import_node_fs7.existsSync)(path)) return false;
890
+ if (!(0, import_node_fs8.existsSync)(path)) return false;
760
891
  try {
761
- return isEnvelope(JSON.parse((0, import_node_fs7.readFileSync)(path, "utf8")));
892
+ return isEnvelope(JSON.parse((0, import_node_fs8.readFileSync)(path, "utf8")));
762
893
  } catch {
763
894
  return false;
764
895
  }
765
896
  }
766
- var import_node_child_process2, import_node_crypto, import_node_fs7, KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, ALG, injectedKey;
897
+ var import_node_child_process2, import_node_crypto, import_node_fs8, KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, ALG, injectedKey;
767
898
  var init_secure_file = __esm({
768
899
  "src/store/secure-file.ts"() {
769
900
  "use strict";
770
901
  import_node_child_process2 = require("child_process");
771
902
  import_node_crypto = require("crypto");
772
- import_node_fs7 = require("fs");
903
+ import_node_fs8 = require("fs");
773
904
  init_private_file();
774
905
  KEYCHAIN_SERVICE = "ai.sideboard.app";
775
906
  KEYCHAIN_ACCOUNT = "secret-vault-v1";
@@ -803,13 +934,13 @@ var init_thinking_effort = __esm({
803
934
 
804
935
  // src/agents/cursor-store.ts
805
936
  function cursorSdkStoreDir(threadId) {
806
- const root = (0, import_node_path8.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
937
+ const root = (0, import_node_path9.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
807
938
  const id = sanitizeCursorStoreSegment(threadId);
808
939
  if (!id) return root;
809
- return (0, import_node_path8.join)(root, "threads", id);
940
+ return (0, import_node_path9.join)(root, "threads", id);
810
941
  }
811
942
  function cursorSdkRunsNdjsonPath(threadId) {
812
- return (0, import_node_path8.join)(cursorSdkStoreDir(threadId), "runs.ndjson");
943
+ return (0, import_node_path9.join)(cursorSdkStoreDir(threadId), "runs.ndjson");
813
944
  }
814
945
  function cursorSdkRunsNdjsonSearchPaths(threadId) {
815
946
  const scoped = cursorSdkRunsNdjsonPath(threadId);
@@ -822,11 +953,11 @@ function cursorSdkRunsNdjsonSearchPaths(threadId) {
822
953
  function sanitizeCursorStoreSegment(threadId) {
823
954
  return (threadId ?? "").trim().replace(/[^a-zA-Z0-9._-]/g, "_");
824
955
  }
825
- var import_node_path8, CURSOR_SDK_STORE_DIR;
956
+ var import_node_path9, CURSOR_SDK_STORE_DIR;
826
957
  var init_cursor_store = __esm({
827
958
  "src/agents/cursor-store.ts"() {
828
959
  "use strict";
829
- import_node_path8 = require("path");
960
+ import_node_path9 = require("path");
830
961
  init_paths();
831
962
  CURSOR_SDK_STORE_DIR = "cursor-sdk-store";
832
963
  }
@@ -953,7 +1084,7 @@ function createEmptyThread(partial) {
953
1084
  }
954
1085
  async function withThreadLock(id, fn) {
955
1086
  const lockPath = threadLockPath(id);
956
- (0, import_node_fs8.writeFileSync)(lockPath, "", { flag: "a" });
1087
+ (0, import_node_fs9.writeFileSync)(lockPath, "", { flag: "a" });
957
1088
  let release;
958
1089
  try {
959
1090
  release = await import_proper_lockfile.default.lock(lockPath, {
@@ -974,7 +1105,7 @@ function cacheForDir() {
974
1105
  }
975
1106
  function fileMtimeMs(path) {
976
1107
  try {
977
- return (0, import_node_fs8.statSync)(path).mtimeMs;
1108
+ return (0, import_node_fs9.statSync)(path).mtimeMs;
978
1109
  } catch {
979
1110
  return null;
980
1111
  }
@@ -1007,7 +1138,7 @@ function readThread(id) {
1007
1138
  const cache = cacheForDir();
1008
1139
  const cached = cache.byId.get(id);
1009
1140
  if (cached && cache.mtimeMs.get(id) === mtimeMs) return cached;
1010
- const raw = (0, import_node_fs8.readFileSync)(path, "utf8");
1141
+ const raw = (0, import_node_fs9.readFileSync)(path, "utf8");
1011
1142
  const thread = normalizeThread(JSON.parse(raw));
1012
1143
  rememberThread(thread, mtimeMs);
1013
1144
  return thread;
@@ -1016,8 +1147,8 @@ function writeThread(thread, opts) {
1016
1147
  const path = threadFilePath(idPath(thread.id));
1017
1148
  const tmp = `${path}.${process.pid}.tmp`;
1018
1149
  const next = opts?.touch === false ? { ...thread } : { ...thread, updatedAt: nowIso() };
1019
- (0, import_node_fs8.writeFileSync)(tmp, JSON.stringify(next, null, 2), "utf8");
1020
- (0, import_node_fs8.renameSync)(tmp, path);
1150
+ (0, import_node_fs9.writeFileSync)(tmp, JSON.stringify(next, null, 2), "utf8");
1151
+ (0, import_node_fs9.renameSync)(tmp, path);
1021
1152
  const mtimeMs = fileMtimeMs(path) ?? Date.now();
1022
1153
  rememberThread(next, mtimeMs);
1023
1154
  selfWriteMtimes.set(thread.id, mtimeMs);
@@ -1031,12 +1162,12 @@ function idPath(id) {
1031
1162
  return id;
1032
1163
  }
1033
1164
  function isThreadRecordFile(nameOrPath) {
1034
- const name = (0, import_node_path9.basename)(nameOrPath);
1165
+ const name = (0, import_node_path10.basename)(nameOrPath);
1035
1166
  return name.endsWith(".json") && !name.endsWith(".live.json") && !name.endsWith(".setup.log.json");
1036
1167
  }
1037
1168
  function listThreads(opts) {
1038
1169
  const cache = cacheForDir();
1039
- const files = (0, import_node_fs8.readdirSync)(threadsDir()).filter(isThreadRecordFile);
1170
+ const files = (0, import_node_fs9.readdirSync)(threadsDir()).filter(isThreadRecordFile);
1040
1171
  const seen = /* @__PURE__ */ new Set();
1041
1172
  for (const f of files) {
1042
1173
  const id = f.replace(/\.json$/, "");
@@ -1059,16 +1190,16 @@ function listThreads(opts) {
1059
1190
  function deleteThreadRecord(id) {
1060
1191
  forgetThread(id);
1061
1192
  const path = threadFilePath(id);
1062
- if ((0, import_node_fs8.existsSync)(path)) (0, import_node_fs8.unlinkSync)(path);
1193
+ if ((0, import_node_fs9.existsSync)(path)) (0, import_node_fs9.unlinkSync)(path);
1063
1194
  const lock = threadLockPath(id);
1064
- if ((0, import_node_fs8.existsSync)(lock)) {
1195
+ if ((0, import_node_fs9.existsSync)(lock)) {
1065
1196
  try {
1066
- (0, import_node_fs8.unlinkSync)(lock);
1197
+ (0, import_node_fs9.unlinkSync)(lock);
1067
1198
  } catch {
1068
1199
  }
1069
1200
  }
1070
1201
  try {
1071
- (0, import_node_fs8.rmSync)(cursorSdkStoreDir(id), { recursive: true, force: true });
1202
+ (0, import_node_fs9.rmSync)(cursorSdkStoreDir(id), { recursive: true, force: true });
1072
1203
  } catch {
1073
1204
  }
1074
1205
  }
@@ -1098,13 +1229,13 @@ function findThreadByRef(ref) {
1098
1229
  (t) => t.id === ref || t.id.startsWith(ref) || t.branchName === ref || t.title === ref
1099
1230
  ) ?? null;
1100
1231
  }
1101
- var import_node_crypto2, import_node_fs8, import_node_path9, import_proper_lockfile, listCache, selfWriteMtimes;
1232
+ var import_node_crypto2, import_node_fs9, import_node_path10, import_proper_lockfile, listCache, selfWriteMtimes;
1102
1233
  var init_thread_store = __esm({
1103
1234
  "src/store/thread-store.ts"() {
1104
1235
  "use strict";
1105
1236
  import_node_crypto2 = require("crypto");
1106
- import_node_fs8 = require("fs");
1107
- import_node_path9 = require("path");
1237
+ import_node_fs9 = require("fs");
1238
+ import_node_path10 = require("path");
1108
1239
  import_proper_lockfile = __toESM(require("proper-lockfile"), 1);
1109
1240
  init_thinking_effort();
1110
1241
  init_cursor_store();
@@ -1158,13 +1289,13 @@ var init_api = __esm({
1158
1289
 
1159
1290
  // src/slack/reply-target.ts
1160
1291
  function storePath() {
1161
- return (0, import_node_path10.join)(appDataDir(), "slack-reply-to.json");
1292
+ return (0, import_node_path11.join)(appDataDir(), "slack-reply-to.json");
1162
1293
  }
1163
1294
  function readStore() {
1164
1295
  const path = storePath();
1165
- if (!(0, import_node_fs9.existsSync)(path)) return {};
1296
+ if (!(0, import_node_fs10.existsSync)(path)) return {};
1166
1297
  try {
1167
- const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs9.readFileSync)(path, "utf8"));
1298
+ const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs10.readFileSync)(path, "utf8"));
1168
1299
  return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
1169
1300
  } catch {
1170
1301
  return {};
@@ -1173,12 +1304,12 @@ function readStore() {
1173
1304
  function getSlackReplyTarget(threadId) {
1174
1305
  return readStore()[threadId] ?? null;
1175
1306
  }
1176
- var import_node_fs9, import_node_path10;
1307
+ var import_node_fs10, import_node_path11;
1177
1308
  var init_reply_target = __esm({
1178
1309
  "src/slack/reply-target.ts"() {
1179
1310
  "use strict";
1180
- import_node_fs9 = require("fs");
1181
- import_node_path10 = require("path");
1311
+ import_node_fs10 = require("fs");
1312
+ import_node_path11 = require("path");
1182
1313
  init_paths();
1183
1314
  init_private_file();
1184
1315
  init_secure_file();
@@ -1187,7 +1318,7 @@ var init_reply_target = __esm({
1187
1318
 
1188
1319
  // src/slack/workspaces.ts
1189
1320
  function storePath2() {
1190
- return (0, import_node_path11.join)(appDataDir(), "slack-workspaces.json");
1321
+ return (0, import_node_path12.join)(appDataDir(), "slack-workspaces.json");
1191
1322
  }
1192
1323
  function readStore2() {
1193
1324
  try {
@@ -1248,11 +1379,11 @@ function requireSlackWorkspace(teamId) {
1248
1379
  }
1249
1380
  return ws;
1250
1381
  }
1251
- var import_node_path11;
1382
+ var import_node_path12;
1252
1383
  var init_workspaces = __esm({
1253
1384
  "src/slack/workspaces.ts"() {
1254
1385
  "use strict";
1255
- import_node_path11 = require("path");
1386
+ import_node_path12 = require("path");
1256
1387
  init_paths();
1257
1388
  init_secure_file();
1258
1389
  init_api();
@@ -1261,7 +1392,7 @@ var init_workspaces = __esm({
1261
1392
 
1262
1393
  // src/slack/outbound-watch.ts
1263
1394
  function storePath3() {
1264
- return (0, import_node_path12.join)(appDataDir(), "slack-outbound-watch.json");
1395
+ return (0, import_node_path13.join)(appDataDir(), "slack-outbound-watch.json");
1265
1396
  }
1266
1397
  function watchId(teamId, channelId, ts) {
1267
1398
  return `${teamId}:${channelId}:${ts}`;
@@ -1274,9 +1405,9 @@ function tsNewer(a, b) {
1274
1405
  }
1275
1406
  function readStore3() {
1276
1407
  const path = storePath3();
1277
- if (!(0, import_node_fs10.existsSync)(path)) return [];
1408
+ if (!(0, import_node_fs11.existsSync)(path)) return [];
1278
1409
  try {
1279
- const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs10.readFileSync)(path, "utf8"));
1410
+ const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs11.readFileSync)(path, "utf8"));
1280
1411
  return Array.isArray(parsed?.watches) ? parsed.watches : [];
1281
1412
  } catch {
1282
1413
  return [];
@@ -1598,12 +1729,12 @@ async function pollSlackOutboundWatches(opts) {
1598
1729
  }
1599
1730
  if (changed) writeStore(watches);
1600
1731
  }
1601
- var import_node_fs10, import_node_path12, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache, continueOnReply;
1732
+ var import_node_fs11, import_node_path13, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache, continueOnReply;
1602
1733
  var init_outbound_watch = __esm({
1603
1734
  "src/slack/outbound-watch.ts"() {
1604
1735
  "use strict";
1605
- import_node_fs10 = require("fs");
1606
- import_node_path12 = require("path");
1736
+ import_node_fs11 = require("fs");
1737
+ import_node_path13 = require("path");
1607
1738
  init_paths();
1608
1739
  init_private_file();
1609
1740
  init_secure_file();
@@ -1999,36 +2130,36 @@ var init_error_detail = __esm({
1999
2130
 
2000
2131
  // src/agents/path.ts
2001
2132
  function prependPathDir(env, dir) {
2002
- if (!dir || !(0, import_node_fs11.existsSync)(dir)) return;
2133
+ if (!dir || !(0, import_node_fs12.existsSync)(dir)) return;
2003
2134
  const current = env.PATH ?? "";
2004
- const parts = current.split(import_node_path13.delimiter).filter(Boolean);
2135
+ const parts = current.split(import_node_path14.delimiter).filter(Boolean);
2005
2136
  if (parts.includes(dir)) {
2006
2137
  env.PATH = current;
2007
2138
  return;
2008
2139
  }
2009
- env.PATH = [dir, ...parts].join(import_node_path13.delimiter);
2140
+ env.PATH = [dir, ...parts].join(import_node_path14.delimiter);
2010
2141
  }
2011
2142
  function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os3.homedir)()) {
2012
- return (0, import_node_path13.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
2143
+ return (0, import_node_path14.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
2013
2144
  }
2014
2145
  function ensureAgentPath(env = process.env) {
2015
2146
  const home = env.HOME || env.USERPROFILE || (0, import_node_os3.homedir)();
2016
2147
  const current = env.PATH ?? "";
2017
- const parts = current.split(import_node_path13.delimiter).filter(Boolean);
2148
+ const parts = current.split(import_node_path14.delimiter).filter(Boolean);
2018
2149
  const seen = new Set(parts);
2019
2150
  const extras = [
2020
- ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path13.join)(home, rel)),
2151
+ ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path14.join)(home, rel)),
2021
2152
  "/opt/homebrew/bin",
2022
2153
  "/usr/local/bin",
2023
2154
  // Keep after Homebrew/npm so a user-installed CLI still wins.
2024
2155
  conductorBundledBinDir(home)
2025
2156
  ];
2026
2157
  for (const dir of extras.reverse()) {
2027
- if (!dir || seen.has(dir) || !(0, import_node_fs11.existsSync)(dir)) continue;
2158
+ if (!dir || seen.has(dir) || !(0, import_node_fs12.existsSync)(dir)) continue;
2028
2159
  parts.unshift(dir);
2029
2160
  seen.add(dir);
2030
2161
  }
2031
- const next = parts.join(import_node_path13.delimiter);
2162
+ const next = parts.join(import_node_path14.delimiter);
2032
2163
  env.PATH = next;
2033
2164
  return next;
2034
2165
  }
@@ -2036,7 +2167,7 @@ function enrichPathWithNpmGlobalBin(env = process.env) {
2036
2167
  ensureAgentPath(env);
2037
2168
  const prefix = npmGlobalPrefix(env);
2038
2169
  if (prefix) {
2039
- const binDir = process.platform === "win32" ? prefix : (0, import_node_path13.join)(prefix, "bin");
2170
+ const binDir = process.platform === "win32" ? prefix : (0, import_node_path14.join)(prefix, "bin");
2040
2171
  prependPathDir(env, binDir);
2041
2172
  }
2042
2173
  return env.PATH ?? "";
@@ -2057,17 +2188,17 @@ function npmGlobalPrefix(env = process.env) {
2057
2188
  function npmGlobalNodeModules(env = process.env) {
2058
2189
  const prefix = npmGlobalPrefix(env);
2059
2190
  if (!prefix) return null;
2060
- const dir = process.platform === "win32" ? (0, import_node_path13.join)(prefix, "node_modules") : (0, import_node_path13.join)(prefix, "lib", "node_modules");
2061
- return (0, import_node_fs11.existsSync)(dir) ? dir : null;
2191
+ const dir = process.platform === "win32" ? (0, import_node_path14.join)(prefix, "node_modules") : (0, import_node_path14.join)(prefix, "lib", "node_modules");
2192
+ return (0, import_node_fs12.existsSync)(dir) ? dir : null;
2062
2193
  }
2063
- var import_node_fs11, import_node_child_process3, import_node_os3, import_node_path13, EXTRA_BIN_DIRS;
2194
+ var import_node_fs12, import_node_child_process3, import_node_os3, import_node_path14, EXTRA_BIN_DIRS;
2064
2195
  var init_path = __esm({
2065
2196
  "src/agents/path.ts"() {
2066
2197
  "use strict";
2067
- import_node_fs11 = require("fs");
2198
+ import_node_fs12 = require("fs");
2068
2199
  import_node_child_process3 = require("child_process");
2069
2200
  import_node_os3 = require("os");
2070
- import_node_path13 = require("path");
2201
+ import_node_path14 = require("path");
2071
2202
  EXTRA_BIN_DIRS = [
2072
2203
  ".local/bin",
2073
2204
  ".cargo/bin",
@@ -2088,23 +2219,23 @@ var init_path = __esm({
2088
2219
  function githubAgentAuthDir() {
2089
2220
  const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
2090
2221
  if (override) return override;
2091
- return (0, import_node_path14.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
2222
+ return (0, import_node_path15.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
2092
2223
  }
2093
2224
  function githubCredentialStorePath() {
2094
- return (0, import_node_path14.join)(githubAgentAuthDir(), "git-credentials");
2225
+ return (0, import_node_path15.join)(githubAgentAuthDir(), "git-credentials");
2095
2226
  }
2096
2227
  function githubGhConfigDir() {
2097
- return (0, import_node_path14.join)(githubAgentAuthDir(), "gh");
2228
+ return (0, import_node_path15.join)(githubAgentAuthDir(), "gh");
2098
2229
  }
2099
2230
  function writePrivateFile2(file, body) {
2100
- (0, import_node_fs12.mkdirSync)((0, import_node_path14.dirname)(file), { recursive: true, mode: 448 });
2231
+ (0, import_node_fs13.mkdirSync)((0, import_node_path15.dirname)(file), { recursive: true, mode: 448 });
2101
2232
  try {
2102
- (0, import_node_fs12.chmodSync)((0, import_node_path14.dirname)(file), 448);
2233
+ (0, import_node_fs13.chmodSync)((0, import_node_path15.dirname)(file), 448);
2103
2234
  } catch {
2104
2235
  }
2105
- (0, import_node_fs12.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
2236
+ (0, import_node_fs13.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
2106
2237
  try {
2107
- (0, import_node_fs12.chmodSync)(file, 384);
2238
+ (0, import_node_fs13.chmodSync)(file, 384);
2108
2239
  } catch {
2109
2240
  }
2110
2241
  }
@@ -2129,19 +2260,19 @@ function materializeGithubAgentAuth(token, user) {
2129
2260
  const trimmed = token.trim();
2130
2261
  if (!trimmed) return;
2131
2262
  const root = githubAgentAuthDir();
2132
- (0, import_node_fs12.mkdirSync)(root, { recursive: true, mode: 448 });
2263
+ (0, import_node_fs13.mkdirSync)(root, { recursive: true, mode: 448 });
2133
2264
  try {
2134
- (0, import_node_fs12.chmodSync)(root, 448);
2265
+ (0, import_node_fs13.chmodSync)(root, 448);
2135
2266
  } catch {
2136
2267
  }
2137
2268
  writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
2138
2269
  const ghDir = githubGhConfigDir();
2139
- (0, import_node_fs12.mkdirSync)(ghDir, { recursive: true, mode: 448 });
2140
- writePrivateFile2((0, import_node_path14.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
2141
- writePrivateFile2((0, import_node_path14.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
2270
+ (0, import_node_fs13.mkdirSync)(ghDir, { recursive: true, mode: 448 });
2271
+ writePrivateFile2((0, import_node_path15.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
2272
+ writePrivateFile2((0, import_node_path15.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
2142
2273
  }
2143
2274
  function githubAgentAuthReady() {
2144
- return (0, import_node_fs12.existsSync)(githubCredentialStorePath()) && (0, import_node_fs12.existsSync)((0, import_node_path14.join)(githubGhConfigDir(), "hosts.yml"));
2275
+ return (0, import_node_fs13.existsSync)(githubCredentialStorePath()) && (0, import_node_fs13.existsSync)((0, import_node_path15.join)(githubGhConfigDir(), "hosts.yml"));
2145
2276
  }
2146
2277
  function githubCredentialHelperGitConfig() {
2147
2278
  const file = githubCredentialStorePath();
@@ -2156,13 +2287,13 @@ function githubGhConfigEnv() {
2156
2287
  GH_PROMPT_DISABLED: "1"
2157
2288
  };
2158
2289
  }
2159
- var import_node_fs12, import_node_os4, import_node_path14;
2290
+ var import_node_fs13, import_node_os4, import_node_path15;
2160
2291
  var init_github_agent_auth = __esm({
2161
2292
  "src/git/github-agent-auth.ts"() {
2162
2293
  "use strict";
2163
- import_node_fs12 = require("fs");
2294
+ import_node_fs13 = require("fs");
2164
2295
  import_node_os4 = require("os");
2165
- import_node_path14 = require("path");
2296
+ import_node_path15 = require("path");
2166
2297
  }
2167
2298
  });
2168
2299
 
@@ -2171,11 +2302,11 @@ function isIndexLockError(text7) {
2171
2302
  return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text7);
2172
2303
  }
2173
2304
  function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
2174
- const lockPath = (0, import_node_path15.join)(gitDir, "index.lock");
2305
+ const lockPath = (0, import_node_path16.join)(gitDir, "index.lock");
2175
2306
  try {
2176
- if (!(0, import_node_fs13.existsSync)(lockPath)) return null;
2177
- if (now - (0, import_node_fs13.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
2178
- (0, import_node_fs13.unlinkSync)(lockPath);
2307
+ if (!(0, import_node_fs14.existsSync)(lockPath)) return null;
2308
+ if (now - (0, import_node_fs14.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
2309
+ (0, import_node_fs14.unlinkSync)(lockPath);
2179
2310
  return lockPath;
2180
2311
  } catch {
2181
2312
  return null;
@@ -2190,12 +2321,12 @@ function clearStaleIndexLocks(gitDirs, maxAgeMs = STALE_INDEX_LOCK_MS) {
2190
2321
  }
2191
2322
  return removed;
2192
2323
  }
2193
- var import_node_fs13, import_node_path15, STALE_INDEX_LOCK_MS;
2324
+ var import_node_fs14, import_node_path16, STALE_INDEX_LOCK_MS;
2194
2325
  var init_stale_lock = __esm({
2195
2326
  "src/git/stale-lock.ts"() {
2196
2327
  "use strict";
2197
- import_node_fs13 = require("fs");
2198
- import_node_path15 = require("path");
2328
+ import_node_fs14 = require("fs");
2329
+ import_node_path16 = require("path");
2199
2330
  STALE_INDEX_LOCK_MS = 2e4;
2200
2331
  }
2201
2332
  });
@@ -3306,11 +3437,11 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
3306
3437
  if (gitDir.exitCode !== 0) return;
3307
3438
  const dir = gitDir.stdout.trim();
3308
3439
  if (!dir) return;
3309
- const excludePath = (0, import_node_path16.join)(dir, "info", "exclude");
3310
- (0, import_node_fs14.mkdirSync)((0, import_node_path16.dirname)(excludePath), { recursive: true });
3440
+ const excludePath = (0, import_node_path17.join)(dir, "info", "exclude");
3441
+ (0, import_node_fs15.mkdirSync)((0, import_node_path17.dirname)(excludePath), { recursive: true });
3311
3442
  let body = "";
3312
3443
  try {
3313
- body = (0, import_node_fs14.readFileSync)(excludePath, "utf8");
3444
+ body = (0, import_node_fs15.readFileSync)(excludePath, "utf8");
3314
3445
  } catch {
3315
3446
  body = "";
3316
3447
  }
@@ -3326,7 +3457,7 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
3326
3457
  ` : body;
3327
3458
  const header = body.includes(EXCLUDE_COMMENT) ? "" : `${EXCLUDE_COMMENT}
3328
3459
  `;
3329
- (0, import_node_fs14.writeFileSync)(excludePath, `${prefix}${header}${missing.join("\n")}
3460
+ (0, import_node_fs15.writeFileSync)(excludePath, `${prefix}${header}${missing.join("\n")}
3330
3461
  `, "utf8");
3331
3462
  }
3332
3463
  const listed = await git(["ls-files", "-z", "--", ".sideboard"], worktreePath, {
@@ -3341,12 +3472,12 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
3341
3472
  timeoutMs: 8e3
3342
3473
  });
3343
3474
  }
3344
- var import_node_fs14, import_node_path16, WORKTREE_SIDEBOARD_EXCLUDE, WORKTREE_CONTEXT_EXCLUDE, EXCLUDE_COMMENT;
3475
+ var import_node_fs15, import_node_path17, WORKTREE_SIDEBOARD_EXCLUDE, WORKTREE_CONTEXT_EXCLUDE, EXCLUDE_COMMENT;
3345
3476
  var init_worktree_exclude = __esm({
3346
3477
  "src/git/worktree-exclude.ts"() {
3347
3478
  "use strict";
3348
- import_node_fs14 = require("fs");
3349
- import_node_path16 = require("path");
3479
+ import_node_fs15 = require("fs");
3480
+ import_node_path17 = require("path");
3350
3481
  init_run();
3351
3482
  WORKTREE_SIDEBOARD_EXCLUDE = ".sideboard/";
3352
3483
  WORKTREE_CONTEXT_EXCLUDE = ".context/";
@@ -3497,7 +3628,7 @@ var init_account_profile = __esm({
3497
3628
 
3498
3629
  // src/store/secret-vault.ts
3499
3630
  function secretVaultPath() {
3500
- return (0, import_node_path17.join)(appDataDir(), "secrets.json");
3631
+ return (0, import_node_path18.join)(appDataDir(), "secrets.json");
3501
3632
  }
3502
3633
  function loadSecretVault() {
3503
3634
  const parsed = readSecureJson(secretVaultPath());
@@ -3559,11 +3690,11 @@ function normalizeVault(raw) {
3559
3690
  }
3560
3691
  return out;
3561
3692
  }
3562
- var import_node_path17;
3693
+ var import_node_path18;
3563
3694
  var init_secret_vault = __esm({
3564
3695
  "src/store/secret-vault.ts"() {
3565
3696
  "use strict";
3566
- import_node_path17 = require("path");
3697
+ import_node_path18 = require("path");
3567
3698
  init_paths();
3568
3699
  init_secure_file();
3569
3700
  }
@@ -3986,10 +4117,10 @@ function toPublicAppSettings(settings) {
3986
4117
  };
3987
4118
  }
3988
4119
  function appSettingsPath() {
3989
- return (0, import_node_path18.join)(appDataDir(), "settings.json");
4120
+ return (0, import_node_path19.join)(appDataDir(), "settings.json");
3990
4121
  }
3991
4122
  function claudeUserSettingsPath() {
3992
- return (0, import_node_path18.join)((0, import_node_os5.homedir)(), ".claude", "settings.json");
4123
+ return (0, import_node_path19.join)((0, import_node_os5.homedir)(), ".claude", "settings.json");
3993
4124
  }
3994
4125
  function normalizeClaude(raw) {
3995
4126
  if (!raw || typeof raw !== "object") return {};
@@ -3997,7 +4128,7 @@ function normalizeClaude(raw) {
3997
4128
  const out = {};
3998
4129
  if (typeof source.executablePath === "string") {
3999
4130
  const path = source.executablePath.trim();
4000
- if (path && (0, import_node_path18.isAbsolute)(path)) out.executablePath = path;
4131
+ if (path && (0, import_node_path19.isAbsolute)(path)) out.executablePath = path;
4001
4132
  }
4002
4133
  if (typeof source.chromeEnabled === "boolean") {
4003
4134
  out.chromeEnabled = source.chromeEnabled;
@@ -4010,13 +4141,13 @@ function normalizeCliExecutable(raw) {
4010
4141
  const out = {};
4011
4142
  if (typeof source.executablePath === "string") {
4012
4143
  const path = source.executablePath.trim();
4013
- if (path && (0, import_node_path18.isAbsolute)(path)) out.executablePath = path;
4144
+ if (path && (0, import_node_path19.isAbsolute)(path)) out.executablePath = path;
4014
4145
  }
4015
4146
  return out;
4016
4147
  }
4017
4148
  function absoluteExecutablePath(value) {
4018
4149
  const path = value.trim();
4019
- if (!(0, import_node_path18.isAbsolute)(path)) {
4150
+ if (!(0, import_node_path19.isAbsolute)(path)) {
4020
4151
  throw new Error("Executable path must be absolute. Leave it empty to use the system CLI.");
4021
4152
  }
4022
4153
  return path;
@@ -4027,7 +4158,7 @@ function normalizeBrightsy(raw) {
4027
4158
  const out = {};
4028
4159
  if (typeof source.executablePath === "string") {
4029
4160
  const path = source.executablePath.trim();
4030
- if (path && (0, import_node_path18.isAbsolute)(path)) out.executablePath = path;
4161
+ if (path && (0, import_node_path19.isAbsolute)(path)) out.executablePath = path;
4031
4162
  }
4032
4163
  if (typeof source.cloudConnectEnabled === "boolean") {
4033
4164
  out.cloudConnectEnabled = source.cloudConnectEnabled;
@@ -4416,10 +4547,10 @@ function normalizeSettings(raw) {
4416
4547
  }
4417
4548
  function readSettingsFile() {
4418
4549
  const path = appSettingsPath();
4419
- if (!(0, import_node_fs15.existsSync)(path)) return { ...EMPTY_SETTINGS };
4550
+ if (!(0, import_node_fs16.existsSync)(path)) return { ...EMPTY_SETTINGS };
4420
4551
  try {
4421
4552
  chmodOwnerOnly(path);
4422
- const parsed = JSON.parse((0, import_node_fs15.readFileSync)(path, "utf8"));
4553
+ const parsed = JSON.parse((0, import_node_fs16.readFileSync)(path, "utf8"));
4423
4554
  return normalizeSettings(parsed);
4424
4555
  } catch {
4425
4556
  return { ...EMPTY_SETTINGS };
@@ -5429,14 +5560,14 @@ function childEnvWithAppSettings(extra) {
5429
5560
  function harnessEnvKey(harness) {
5430
5561
  return HARNESS_ENV_KEYS[harness];
5431
5562
  }
5432
- var import_node_crypto3, import_node_fs15, import_node_os5, import_node_path18, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, FOLLOW_UP_BEHAVIORS, AGENT_DONE_SOUNDS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, CONFIRM_ACCOUNT, CONFIRM_PROJECT, DEFAULT_CLI_BIN;
5563
+ var import_node_crypto3, import_node_fs16, import_node_os5, import_node_path19, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, FOLLOW_UP_BEHAVIORS, AGENT_DONE_SOUNDS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, CONFIRM_ACCOUNT, CONFIRM_PROJECT, DEFAULT_CLI_BIN;
5433
5564
  var init_app_settings = __esm({
5434
5565
  "src/store/app-settings.ts"() {
5435
5566
  "use strict";
5436
5567
  import_node_crypto3 = require("crypto");
5437
- import_node_fs15 = require("fs");
5568
+ import_node_fs16 = require("fs");
5438
5569
  import_node_os5 = require("os");
5439
- import_node_path18 = require("path");
5570
+ import_node_path19 = require("path");
5440
5571
  init_orchestrator_capable();
5441
5572
  init_thinking_effort();
5442
5573
  init_nested_electron_env();
@@ -5618,7 +5749,7 @@ async function warmGithubAgentAuth(opts) {
5618
5749
  }
5619
5750
  function normalizeWritableRoot(raw) {
5620
5751
  const trimmed = raw.trim().replace(/\/+$/, "");
5621
- return trimmed && (0, import_node_path19.isAbsolute)(trimmed) ? trimmed : null;
5752
+ return trimmed && (0, import_node_path20.isAbsolute)(trimmed) ? trimmed : null;
5622
5753
  }
5623
5754
  async function resolveCodexGitWritableRoots(cwd) {
5624
5755
  const roots = /* @__PURE__ */ new Set();
@@ -5696,11 +5827,11 @@ function formatGitAuthModeDirective(mode) {
5696
5827
  ].join("\n");
5697
5828
  }
5698
5829
  }
5699
- var import_node_path19, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
5830
+ var import_node_path20, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
5700
5831
  var init_git_auth_mode = __esm({
5701
5832
  "src/git/git-auth-mode.ts"() {
5702
5833
  "use strict";
5703
- import_node_path19 = require("path");
5834
+ import_node_path20 = require("path");
5704
5835
  init_app_settings();
5705
5836
  init_github_agent_auth();
5706
5837
  init_run();
@@ -6532,7 +6663,7 @@ async function resolveRepoRoot(cwd) {
6532
6663
  }
6533
6664
  function canonicalizeRepoPath(path) {
6534
6665
  try {
6535
- return (0, import_node_fs16.realpathSync)(path);
6666
+ return (0, import_node_fs17.realpathSync)(path);
6536
6667
  } catch {
6537
6668
  return path.replace(/\/+$/, "");
6538
6669
  }
@@ -7393,8 +7524,8 @@ async function refreshOriginAndMaybeFastForwardMain(repoPath, sourceRef) {
7393
7524
  }
7394
7525
  async function createThreadWorktree(opts) {
7395
7526
  let branchName = `thread/${opts.slug}`;
7396
- const worktreePath = (0, import_node_path20.join)(worktreesRoot(opts.repoPath), opts.slug);
7397
- if ((0, import_node_fs16.existsSync)(worktreePath)) {
7527
+ const worktreePath = (0, import_node_path21.join)(worktreesRoot(opts.repoPath), opts.slug);
7528
+ if ((0, import_node_fs17.existsSync)(worktreePath)) {
7398
7529
  throw new Error(`Worktree already exists at ${worktreePath}`);
7399
7530
  }
7400
7531
  await ensureGhPreferOrigin(opts.repoPath);
@@ -7435,8 +7566,8 @@ ${add.stdout}`;
7435
7566
  async function createExistingBranchWorktree(opts) {
7436
7567
  const branchName = opts.branchName.trim();
7437
7568
  if (!branchName) throw new Error("branch name required");
7438
- const worktreePath = (0, import_node_path20.join)(worktreesRoot(opts.repoPath), opts.slug);
7439
- if ((0, import_node_fs16.existsSync)(worktreePath)) {
7569
+ const worktreePath = (0, import_node_path21.join)(worktreesRoot(opts.repoPath), opts.slug);
7570
+ if ((0, import_node_fs17.existsSync)(worktreePath)) {
7440
7571
  throw new Error(`Worktree already exists at ${worktreePath}`);
7441
7572
  }
7442
7573
  await ensureGhPreferOrigin(opts.repoPath);
@@ -7717,11 +7848,11 @@ async function createOrUpdatePr(worktreePath, opts) {
7717
7848
  const headRef = ghHeadRef(slug, opts.head);
7718
7849
  const branchOnly = opts.head.trim().replace(/^refs\/heads\//, "");
7719
7850
  const bodyText = clampGithubPrBody(opts.body ?? opts.title);
7720
- const bodyFile = (0, import_node_path20.join)(
7851
+ const bodyFile = (0, import_node_path21.join)(
7721
7852
  (0, import_node_os6.tmpdir)(),
7722
7853
  `sideboard-pr-body-${process.pid}-${(0, import_node_crypto4.randomBytes)(6).toString("hex")}.md`
7723
7854
  );
7724
- (0, import_node_fs16.writeFileSync)(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
7855
+ (0, import_node_fs17.writeFileSync)(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
7725
7856
  `, "utf8");
7726
7857
  const bodyArgs = ["--body-file", bodyFile];
7727
7858
  try {
@@ -7735,7 +7866,7 @@ async function createOrUpdatePr(worktreePath, opts) {
7735
7866
  });
7736
7867
  } finally {
7737
7868
  try {
7738
- (0, import_node_fs16.unlinkSync)(bodyFile);
7869
+ (0, import_node_fs17.unlinkSync)(bodyFile);
7739
7870
  } catch {
7740
7871
  }
7741
7872
  }
@@ -7817,10 +7948,10 @@ function sameRepoPath(a, b) {
7817
7948
  return normalizeWorktreePath(a) === normalizeWorktreePath(b);
7818
7949
  }
7819
7950
  function listLocalThreadBranchSlugs(repoPath) {
7820
- const refsDir = (0, import_node_path20.join)(repoPath, ".git", "refs", "heads", "thread");
7821
- if (!(0, import_node_fs16.existsSync)(refsDir)) return [];
7951
+ const refsDir = (0, import_node_path21.join)(repoPath, ".git", "refs", "heads", "thread");
7952
+ if (!(0, import_node_fs17.existsSync)(refsDir)) return [];
7822
7953
  try {
7823
- return (0, import_node_fs16.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
7954
+ return (0, import_node_fs17.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
7824
7955
  } catch {
7825
7956
  return [];
7826
7957
  }
@@ -7828,8 +7959,8 @@ function listLocalThreadBranchSlugs(repoPath) {
7828
7959
  function collectTakenTeamSlugs(repoPath) {
7829
7960
  const taken = /* @__PURE__ */ new Set();
7830
7961
  const root = worktreesRoot(repoPath);
7831
- if ((0, import_node_fs16.existsSync)(root)) {
7832
- for (const entry of (0, import_node_fs16.readdirSync)(root, { withFileTypes: true })) {
7962
+ if ((0, import_node_fs17.existsSync)(root)) {
7963
+ for (const entry of (0, import_node_fs17.readdirSync)(root, { withFileTypes: true })) {
7833
7964
  if (entry.isDirectory() && entry.name !== ".DS_Store") {
7834
7965
  for (const slug of takenSlugsFromThread({ worktreePath: entry.name })) {
7835
7966
  taken.add(slug);
@@ -7854,20 +7985,20 @@ function allocateTeamSlug(repoPath) {
7854
7985
  const taken = collectTakenTeamSlugs(repoPath);
7855
7986
  for (let attempt = 0; attempt < 32; attempt++) {
7856
7987
  const team = allocateTeamName(taken);
7857
- const path = (0, import_node_path20.join)(worktreesRoot(repoPath), team.slug);
7858
- if (!(0, import_node_fs16.existsSync)(path)) return team;
7988
+ const path = (0, import_node_path21.join)(worktreesRoot(repoPath), team.slug);
7989
+ if (!(0, import_node_fs17.existsSync)(path)) return team;
7859
7990
  taken.add(team.slug);
7860
7991
  }
7861
7992
  throw new Error("No available soccer team worktree directories left");
7862
7993
  }
7863
- var import_node_crypto4, import_node_fs16, import_node_os6, import_node_path20, PR_DETAILS_JSON_FIELDS;
7994
+ var import_node_crypto4, import_node_fs17, import_node_os6, import_node_path21, PR_DETAILS_JSON_FIELDS;
7864
7995
  var init_worktree = __esm({
7865
7996
  "src/git/worktree.ts"() {
7866
7997
  "use strict";
7867
7998
  import_node_crypto4 = require("crypto");
7868
- import_node_fs16 = require("fs");
7999
+ import_node_fs17 = require("fs");
7869
8000
  import_node_os6 = require("os");
7870
- import_node_path20 = require("path");
8001
+ import_node_path21 = require("path");
7871
8002
  init_paths();
7872
8003
  init_thread_store();
7873
8004
  init_teams();
@@ -7939,7 +8070,7 @@ var init_cloud_connect_constants = __esm({
7939
8070
 
7940
8071
  // src/composer/stage-files.ts
7941
8072
  function fileExtension(filePath) {
7942
- const base = (0, import_node_path21.basename)(filePath).toLowerCase();
8073
+ const base = (0, import_node_path22.basename)(filePath).toLowerCase();
7943
8074
  return base.includes(".") ? base.split(".").pop() || "" : "";
7944
8075
  }
7945
8076
  function isImageFilePath(filePath) {
@@ -7949,22 +8080,22 @@ function imageMimeType(filePath) {
7949
8080
  return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
7950
8081
  }
7951
8082
  function ensureAttachmentsDir(worktreePath) {
7952
- const dir = (0, import_node_path21.join)(worktreePath, ATTACHMENTS_DIR);
7953
- (0, import_node_fs17.mkdirSync)(dir, { recursive: true });
7954
- const gi = (0, import_node_path21.join)(dir, ".gitignore");
7955
- if (!(0, import_node_fs17.existsSync)(gi)) {
7956
- (0, import_node_fs17.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
8083
+ const dir = (0, import_node_path22.join)(worktreePath, ATTACHMENTS_DIR);
8084
+ (0, import_node_fs18.mkdirSync)(dir, { recursive: true });
8085
+ const gi = (0, import_node_path22.join)(dir, ".gitignore");
8086
+ if (!(0, import_node_fs18.existsSync)(gi)) {
8087
+ (0, import_node_fs18.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
7957
8088
  }
7958
8089
  return dir;
7959
8090
  }
7960
8091
  function uniqueAttachmentName(dir, originalName) {
7961
8092
  const safe = originalName.replace(/[/\\]/g, "_") || "file";
7962
- if (!(0, import_node_fs17.existsSync)((0, import_node_path21.join)(dir, safe))) return safe;
7963
- const ext = (0, import_node_path21.extname)(safe);
8093
+ if (!(0, import_node_fs18.existsSync)((0, import_node_path22.join)(dir, safe))) return safe;
8094
+ const ext = (0, import_node_path22.extname)(safe);
7964
8095
  const stem = ext ? safe.slice(0, -ext.length) : safe;
7965
8096
  for (let i = 1; i < 1e4; i++) {
7966
8097
  const candidate = `${stem}-${i}${ext}`;
7967
- if (!(0, import_node_fs17.existsSync)((0, import_node_path21.join)(dir, candidate))) return candidate;
8098
+ if (!(0, import_node_fs18.existsSync)((0, import_node_path22.join)(dir, candidate))) return candidate;
7968
8099
  }
7969
8100
  return `${stem}-${(0, import_node_crypto5.randomUUID)()}${ext}`;
7970
8101
  }
@@ -8020,15 +8151,15 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
8020
8151
  const dir = ensureAttachmentsDir(worktreePath);
8021
8152
  const out = [];
8022
8153
  for (const abs of absolutePaths) {
8023
- const originalName = (0, import_node_path21.basename)(abs);
8154
+ const originalName = (0, import_node_path22.basename)(abs);
8024
8155
  try {
8025
- const st = (0, import_node_fs17.statSync)(abs);
8156
+ const st = (0, import_node_fs18.statSync)(abs);
8026
8157
  if (!st.isFile()) continue;
8027
8158
  const name = uniqueAttachmentName(dir, originalName);
8028
- const destAbs = (0, import_node_path21.join)(dir, name);
8029
- (0, import_node_fs17.copyFileSync)(abs, destAbs);
8159
+ const destAbs = (0, import_node_path22.join)(dir, name);
8160
+ (0, import_node_fs18.copyFileSync)(abs, destAbs);
8030
8161
  const rel = `${ATTACHMENTS_DIR}/${name}`;
8031
- const buf = (0, import_node_fs17.readFileSync)(destAbs);
8162
+ const buf = (0, import_node_fs18.readFileSync)(destAbs);
8032
8163
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
8033
8164
  } catch (err) {
8034
8165
  out.push({
@@ -8050,8 +8181,8 @@ function stageBuffersAsAttachments(worktreePath, buffers2) {
8050
8181
  try {
8051
8182
  const buf = Buffer.from(item.dataBase64, "base64");
8052
8183
  const name = uniqueAttachmentName(dir, originalName);
8053
- const destAbs = (0, import_node_path21.join)(dir, name);
8054
- (0, import_node_fs17.writeFileSync)(destAbs, buf);
8184
+ const destAbs = (0, import_node_path22.join)(dir, name);
8185
+ (0, import_node_fs18.writeFileSync)(destAbs, buf);
8055
8186
  const rel = `${ATTACHMENTS_DIR}/${name}`;
8056
8187
  out.push(attachmentFromBuffer(name, buf, { path: rel }));
8057
8188
  } catch (err) {
@@ -8112,18 +8243,18 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
8112
8243
  if (!rel || rel.includes("..") || rel.startsWith("/")) {
8113
8244
  out.push({
8114
8245
  id: (0, import_node_crypto5.randomUUID)(),
8115
- name: (0, import_node_path21.basename)(rel) || "file",
8246
+ name: (0, import_node_path22.basename)(rel) || "file",
8116
8247
  kind: "file",
8117
8248
  content: `(invalid path: ${rel})`
8118
8249
  });
8119
8250
  continue;
8120
8251
  }
8121
- const name = (0, import_node_path21.basename)(rel);
8252
+ const name = (0, import_node_path22.basename)(rel);
8122
8253
  try {
8123
- const abs = (0, import_node_path21.join)(worktreePath, rel);
8124
- const st = (0, import_node_fs17.statSync)(abs);
8254
+ const abs = (0, import_node_path22.join)(worktreePath, rel);
8255
+ const st = (0, import_node_fs18.statSync)(abs);
8125
8256
  if (!st.isFile()) continue;
8126
- const buf = (0, import_node_fs17.readFileSync)(abs);
8257
+ const buf = (0, import_node_fs18.readFileSync)(abs);
8127
8258
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
8128
8259
  } catch (err) {
8129
8260
  out.push({
@@ -8136,12 +8267,12 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
8136
8267
  }
8137
8268
  return out;
8138
8269
  }
8139
- var import_node_fs17, import_node_path21, import_node_crypto5, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
8270
+ var import_node_fs18, import_node_path22, import_node_crypto5, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
8140
8271
  var init_stage_files = __esm({
8141
8272
  "src/composer/stage-files.ts"() {
8142
8273
  "use strict";
8143
- import_node_fs17 = require("fs");
8144
- import_node_path21 = require("path");
8274
+ import_node_fs18 = require("fs");
8275
+ import_node_path22 = require("path");
8145
8276
  import_node_crypto5 = require("crypto");
8146
8277
  init_workspace_scratch();
8147
8278
  IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
@@ -8182,38 +8313,38 @@ __export(workspaces_exports, {
8182
8313
  syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
8183
8314
  });
8184
8315
  function workspacesFile() {
8185
- return (0, import_node_path22.join)(appDataDir(), "workspaces.json");
8316
+ return (0, import_node_path23.join)(appDataDir(), "workspaces.json");
8186
8317
  }
8187
8318
  function removedWorkspacesFile() {
8188
- return (0, import_node_path22.join)(appDataDir(), "removed-workspaces.json");
8319
+ return (0, import_node_path23.join)(appDataDir(), "removed-workspaces.json");
8189
8320
  }
8190
8321
  function readAll() {
8191
8322
  const path = workspacesFile();
8192
- if (!(0, import_node_fs18.existsSync)(path)) return [];
8323
+ if (!(0, import_node_fs19.existsSync)(path)) return [];
8193
8324
  try {
8194
- const raw = JSON.parse((0, import_node_fs18.readFileSync)(path, "utf8"));
8325
+ const raw = JSON.parse((0, import_node_fs19.readFileSync)(path, "utf8"));
8195
8326
  return Array.isArray(raw) ? raw : [];
8196
8327
  } catch {
8197
8328
  return [];
8198
8329
  }
8199
8330
  }
8200
8331
  function writeAll(list) {
8201
- (0, import_node_fs18.mkdirSync)(appDataDir(), { recursive: true });
8202
- (0, import_node_fs18.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
8332
+ (0, import_node_fs19.mkdirSync)(appDataDir(), { recursive: true });
8333
+ (0, import_node_fs19.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
8203
8334
  }
8204
8335
  function readRemoved() {
8205
8336
  const path = removedWorkspacesFile();
8206
- if (!(0, import_node_fs18.existsSync)(path)) return /* @__PURE__ */ new Set();
8337
+ if (!(0, import_node_fs19.existsSync)(path)) return /* @__PURE__ */ new Set();
8207
8338
  try {
8208
- const raw = JSON.parse((0, import_node_fs18.readFileSync)(path, "utf8"));
8339
+ const raw = JSON.parse((0, import_node_fs19.readFileSync)(path, "utf8"));
8209
8340
  return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
8210
8341
  } catch {
8211
8342
  return /* @__PURE__ */ new Set();
8212
8343
  }
8213
8344
  }
8214
8345
  function writeRemoved(paths) {
8215
- (0, import_node_fs18.mkdirSync)(appDataDir(), { recursive: true });
8216
- (0, import_node_fs18.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
8346
+ (0, import_node_fs19.mkdirSync)(appDataDir(), { recursive: true });
8347
+ (0, import_node_fs19.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
8217
8348
  }
8218
8349
  function rememberRemoved(repoPath) {
8219
8350
  const next = readRemoved();
@@ -8235,10 +8366,10 @@ function listWorkspaces() {
8235
8366
  }
8236
8367
  function isLinkedWorktreeOf(path, mainRepo) {
8237
8368
  if (!path || path === mainRepo) return false;
8238
- const git2 = (0, import_node_path22.join)(path, ".git");
8369
+ const git2 = (0, import_node_path23.join)(path, ".git");
8239
8370
  try {
8240
- if (!(0, import_node_fs18.existsSync)(git2) || (0, import_node_fs18.statSync)(git2).isDirectory()) return false;
8241
- const text7 = (0, import_node_fs18.readFileSync)(git2, "utf8");
8371
+ if (!(0, import_node_fs19.existsSync)(git2) || (0, import_node_fs19.statSync)(git2).isDirectory()) return false;
8372
+ const text7 = (0, import_node_fs19.readFileSync)(git2, "utf8");
8242
8373
  const needle = `${mainRepo.replace(/\/+$/, "")}/.git`;
8243
8374
  return text7.includes(needle);
8244
8375
  } catch {
@@ -8247,10 +8378,10 @@ function isLinkedWorktreeOf(path, mainRepo) {
8247
8378
  }
8248
8379
  function primaryCheckoutFromLinkedWorktree(path) {
8249
8380
  if (!path) return null;
8250
- const git2 = (0, import_node_path22.join)(path, ".git");
8381
+ const git2 = (0, import_node_path23.join)(path, ".git");
8251
8382
  try {
8252
- if (!(0, import_node_fs18.existsSync)(git2) || (0, import_node_fs18.statSync)(git2).isDirectory()) return null;
8253
- const text7 = (0, import_node_fs18.readFileSync)(git2, "utf8");
8383
+ if (!(0, import_node_fs19.existsSync)(git2) || (0, import_node_fs19.statSync)(git2).isDirectory()) return null;
8384
+ const text7 = (0, import_node_fs19.readFileSync)(git2, "utf8");
8254
8385
  const match = /^\s*gitdir:\s*(.+)$/m.exec(text7);
8255
8386
  if (!match) return null;
8256
8387
  const gitdir = match[1].trim().replace(/\/+$/, "");
@@ -8271,7 +8402,7 @@ function resolveSyncWorkspacePath(path) {
8271
8402
  async function addWorkspace(repoPath) {
8272
8403
  const root = await resolveRepoRoot(repoPath);
8273
8404
  if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
8274
- if (!(0, import_node_fs18.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
8405
+ if (!(0, import_node_fs19.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
8275
8406
  forgetRemoved(root);
8276
8407
  await ensureGhPreferOrigin(root);
8277
8408
  const current = readAll();
@@ -8280,7 +8411,7 @@ async function addWorkspace(repoPath) {
8280
8411
  if (existing && withoutLinked.length === current.length) return existing;
8281
8412
  const next = existing ?? {
8282
8413
  path: root,
8283
- name: (0, import_node_path22.basename)(root),
8414
+ name: (0, import_node_path23.basename)(root),
8284
8415
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
8285
8416
  };
8286
8417
  writeAll(existing ? withoutLinked : [...withoutLinked, next]);
@@ -8308,7 +8439,7 @@ function syncWorkspacesFromThreads(repoPaths) {
8308
8439
  if (!byPath.has(resolved)) {
8309
8440
  byPath.set(
8310
8441
  resolved,
8311
- resolved === w.path ? w : { ...w, path: resolved, name: (0, import_node_path22.basename)(resolved) }
8442
+ resolved === w.path ? w : { ...w, path: resolved, name: (0, import_node_path23.basename)(resolved) }
8312
8443
  );
8313
8444
  }
8314
8445
  }
@@ -8317,10 +8448,10 @@ function syncWorkspacesFromThreads(repoPaths) {
8317
8448
  if (!path || path === "/" || isGlobalRepoPath(path) || byPath.has(path) || removed.has(path)) {
8318
8449
  continue;
8319
8450
  }
8320
- if (!(0, import_node_fs18.existsSync)(path)) continue;
8451
+ if (!(0, import_node_fs19.existsSync)(path)) continue;
8321
8452
  const ws = {
8322
8453
  path,
8323
- name: (0, import_node_path22.basename)(path),
8454
+ name: (0, import_node_path23.basename)(path),
8324
8455
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
8325
8456
  };
8326
8457
  byPath.set(path, ws);
@@ -8337,12 +8468,12 @@ function syncWorkspacesFromThreads(repoPaths) {
8337
8468
  if (dirty) writeAll(next);
8338
8469
  return next.sort((a, b) => a.name.localeCompare(b.name));
8339
8470
  }
8340
- var import_node_fs18, import_node_path22;
8471
+ var import_node_fs19, import_node_path23;
8341
8472
  var init_workspaces2 = __esm({
8342
8473
  "src/store/workspaces.ts"() {
8343
8474
  "use strict";
8344
- import_node_fs18 = require("fs");
8345
- import_node_path22 = require("path");
8475
+ import_node_fs19 = require("fs");
8476
+ import_node_path23 = require("path");
8346
8477
  init_paths();
8347
8478
  init_global_workspace();
8348
8479
  init_worktree();
@@ -8453,7 +8584,7 @@ function coordinatorTurnReminder(opts) {
8453
8584
  function ensureGlobalCoordinatorCwd(opts) {
8454
8585
  const dir = globalAgentCwd();
8455
8586
  try {
8456
- (0, import_node_fs19.mkdirSync)(dir, { recursive: true });
8587
+ (0, import_node_fs20.mkdirSync)(dir, { recursive: true });
8457
8588
  } catch {
8458
8589
  return dir;
8459
8590
  }
@@ -8461,7 +8592,7 @@ function ensureGlobalCoordinatorCwd(opts) {
8461
8592
  let orchId = opts?.orchestratorThreadId?.trim() || "";
8462
8593
  if (!orchId) {
8463
8594
  try {
8464
- const existing = (0, import_node_fs19.readFileSync)((0, import_node_path23.join)(dir, "AGENTS.md"), "utf8");
8595
+ const existing = (0, import_node_fs20.readFileSync)((0, import_node_path24.join)(dir, "AGENTS.md"), "utf8");
8465
8596
  const m = existing.match(
8466
8597
  /YOUR orchestration thread id is `([0-9a-f-]{36})`/i
8467
8598
  );
@@ -8506,9 +8637,9 @@ function ensureGlobalCoordinatorCwd(opts) {
8506
8637
  "Always ask worktree agents to commit, push, and open draft PRs (`ask_git` / `send_to_thread`). If the user gave a goal (Greptile 5/5, CI green), pass that goal through so they watch-fix-push until it lands \u2014 do not start that loop on a plain push, and do not tell the human to poll. Tell them to merge only when the user explicitly asked. The worktree agent runs git/gh; never merge from this orchestration cwd."
8507
8638
  ].join("\n");
8508
8639
  try {
8509
- (0, import_node_fs19.writeFileSync)((0, import_node_path23.join)(dir, "CLAUDE.md"), `${body}
8640
+ (0, import_node_fs20.writeFileSync)((0, import_node_path24.join)(dir, "CLAUDE.md"), `${body}
8510
8641
  `, "utf8");
8511
- (0, import_node_fs19.writeFileSync)((0, import_node_path23.join)(dir, "AGENTS.md"), `${body}
8642
+ (0, import_node_fs20.writeFileSync)((0, import_node_path24.join)(dir, "AGENTS.md"), `${body}
8512
8643
  `, "utf8");
8513
8644
  } catch {
8514
8645
  }
@@ -8540,12 +8671,12 @@ function coordinatorSystemPrompt(opts) {
8540
8671
  formatWorkspaceInventory(opts.workspaces)
8541
8672
  ].join("\n");
8542
8673
  }
8543
- var import_node_fs19, import_node_path23, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
8674
+ var import_node_fs20, import_node_path24, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
8544
8675
  var init_coordinator_prompt = __esm({
8545
8676
  "src/orchestrator/coordinator-prompt.ts"() {
8546
8677
  "use strict";
8547
- import_node_fs19 = require("fs");
8548
- import_node_path23 = require("path");
8678
+ import_node_fs20 = require("fs");
8679
+ import_node_path24 = require("path");
8549
8680
  init_worktree();
8550
8681
  init_app_settings();
8551
8682
  init_paths();
@@ -8585,7 +8716,7 @@ var init_coordinator_prompt = __esm({
8585
8716
  "- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
8586
8717
  "Setup / run:",
8587
8718
  "- run_setup \u2014 re-run worktree setup (already runs automatically on create when a script exists)",
8588
- "- list_run_scripts / run_dev_script / stop_dev_script \u2014 start/stop named run scripts",
8719
+ "- list_run_scripts / run_dev_script / stop_dev_script \u2014 start/stop named run scripts. run_dev_script returns {url, port, preview} (SIDEBOARD_PORT). preview=url \u2192 tell the worktree agent to open that URL; preview=window \u2192 Electron: the native window is the app (url is renderer/HMR only). Never localhost:3000. list_run_scripts active[].url if already running.",
8589
8720
  "Inspect / review / PRs:",
8590
8721
  "- get_diff \u2014 compact diff summary",
8591
8722
  "- get_pr_checks \u2014 snapshot of a worktree thread's PR checks (null = no PR). Use this to inspect status. If the user gave a goal, the worktree agent watches with `gh pr checks --watch` \u2014 do not poll for the human.",
@@ -8862,7 +8993,7 @@ function traceTurn(phase, extra) {
8862
8993
  try {
8863
8994
  const line = `${JSON.stringify({ t: (/* @__PURE__ */ new Date()).toISOString(), phase, ...extra })}
8864
8995
  `;
8865
- (0, import_node_fs20.appendFileSync)((0, import_node_path24.join)(appDataDir(), "turn-spawn.log"), line);
8996
+ (0, import_node_fs21.appendFileSync)((0, import_node_path25.join)(appDataDir(), "turn-spawn.log"), line);
8866
8997
  } catch {
8867
8998
  }
8868
8999
  }
@@ -8882,12 +9013,12 @@ async function withTimeout(promise, ms, label) {
8882
9013
  if (timer) clearTimeout(timer);
8883
9014
  }
8884
9015
  }
8885
- var import_node_fs20, import_node_path24;
9016
+ var import_node_fs21, import_node_path25;
8886
9017
  var init_turn_trace = __esm({
8887
9018
  "src/agents/turn-trace.ts"() {
8888
9019
  "use strict";
8889
- import_node_fs20 = require("fs");
8890
- import_node_path24 = require("path");
9020
+ import_node_fs21 = require("fs");
9021
+ import_node_path25 = require("path");
8891
9022
  init_paths();
8892
9023
  }
8893
9024
  });
@@ -8896,32 +9027,32 @@ var init_turn_trace = __esm({
8896
9027
  function brightsyConfigPath() {
8897
9028
  const override = process.env.BRIGHTSY_CONFIG?.trim();
8898
9029
  if (override) return override;
8899
- return (0, import_node_path25.join)((0, import_node_os7.homedir)(), ".brightsy", "config.json");
9030
+ return (0, import_node_path26.join)((0, import_node_os7.homedir)(), ".brightsy", "config.json");
8900
9031
  }
8901
9032
  function loadBrightsyConfig() {
8902
9033
  const path = brightsyConfigPath();
8903
- if (!(0, import_node_fs21.existsSync)(path)) {
9034
+ if (!(0, import_node_fs22.existsSync)(path)) {
8904
9035
  throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
8905
9036
  }
8906
- const raw = JSON.parse((0, import_node_fs21.readFileSync)(path, "utf8"));
9037
+ const raw = JSON.parse((0, import_node_fs22.readFileSync)(path, "utf8"));
8907
9038
  if (!raw.access_token || !raw.account_id) {
8908
9039
  throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
8909
9040
  }
8910
9041
  return raw;
8911
9042
  }
8912
9043
  function saveBrightsyConfig(cfg) {
8913
- (0, import_node_fs21.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
9044
+ (0, import_node_fs22.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
8914
9045
  `, {
8915
9046
  mode: 384
8916
9047
  });
8917
9048
  }
8918
- var import_node_fs21, import_node_os7, import_node_path25;
9049
+ var import_node_fs22, import_node_os7, import_node_path26;
8919
9050
  var init_config = __esm({
8920
9051
  "src/brightsy/config.ts"() {
8921
9052
  "use strict";
8922
- import_node_fs21 = require("fs");
9053
+ import_node_fs22 = require("fs");
8923
9054
  import_node_os7 = require("os");
8924
- import_node_path25 = require("path");
9055
+ import_node_path26 = require("path");
8925
9056
  }
8926
9057
  });
8927
9058
 
@@ -9117,22 +9248,22 @@ var init_oauth = __esm({
9117
9248
 
9118
9249
  // src/brightsy/connected-teams.ts
9119
9250
  function storePath4() {
9120
- return (0, import_node_path26.join)(appDataDir(), "brightsy-teams.json");
9251
+ return (0, import_node_path27.join)(appDataDir(), "brightsy-teams.json");
9121
9252
  }
9122
9253
  function readStore4() {
9123
9254
  const path = storePath4();
9124
- if (!(0, import_node_fs22.existsSync)(path)) return [];
9255
+ if (!(0, import_node_fs23.existsSync)(path)) return [];
9125
9256
  try {
9126
- const parsed = JSON.parse((0, import_node_fs22.readFileSync)(path, "utf8"));
9257
+ const parsed = JSON.parse((0, import_node_fs23.readFileSync)(path, "utf8"));
9127
9258
  return Array.isArray(parsed.teams) ? parsed.teams : [];
9128
9259
  } catch {
9129
9260
  return [];
9130
9261
  }
9131
9262
  }
9132
9263
  function writeStore2(teams) {
9133
- (0, import_node_fs22.mkdirSync)(appDataDir(), { recursive: true });
9264
+ (0, import_node_fs23.mkdirSync)(appDataDir(), { recursive: true });
9134
9265
  const path = storePath4();
9135
- (0, import_node_fs22.writeFileSync)(path, `${JSON.stringify({ teams }, null, 2)}
9266
+ (0, import_node_fs23.writeFileSync)(path, `${JSON.stringify({ teams }, null, 2)}
9136
9267
  `, {
9137
9268
  mode: 384
9138
9269
  });
@@ -9269,12 +9400,12 @@ function brightsyMcpServerName(slug) {
9269
9400
  const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
9270
9401
  return `brightsy_${cleaned || "team"}`;
9271
9402
  }
9272
- var import_node_fs22, import_node_path26;
9403
+ var import_node_fs23, import_node_path27;
9273
9404
  var init_connected_teams = __esm({
9274
9405
  "src/brightsy/connected-teams.ts"() {
9275
9406
  "use strict";
9276
- import_node_fs22 = require("fs");
9277
- import_node_path26 = require("path");
9407
+ import_node_fs23 = require("fs");
9408
+ import_node_path27 = require("path");
9278
9409
  init_paths();
9279
9410
  init_accounts();
9280
9411
  init_config();
@@ -9595,11 +9726,11 @@ async function syncCliForTarget(accountId) {
9595
9726
  }
9596
9727
  applyConnectedTeamToCli(team);
9597
9728
  }
9598
- var import_node_fs23, brightsyAdapter;
9729
+ var import_node_fs24, brightsyAdapter;
9599
9730
  var init_brightsy = __esm({
9600
9731
  "src/agents/brightsy.ts"() {
9601
9732
  "use strict";
9602
- import_node_fs23 = require("fs");
9733
+ import_node_fs24 = require("fs");
9603
9734
  init_run();
9604
9735
  init_connected_teams();
9605
9736
  init_config();
@@ -9614,7 +9745,7 @@ var init_brightsy = __esm({
9614
9745
  async detect() {
9615
9746
  const brightsy = resolveAgentExecutable("brightsy");
9616
9747
  if (brightsy !== "brightsy") {
9617
- if (!(0, import_node_fs23.existsSync)(brightsy)) {
9748
+ if (!(0, import_node_fs24.existsSync)(brightsy)) {
9618
9749
  return {
9619
9750
  agent: "brightsy",
9620
9751
  installed: false,
@@ -9736,43 +9867,43 @@ function electronResourcesPath() {
9736
9867
  function packagedCursorRuntimeDir() {
9737
9868
  const resources = electronResourcesPath();
9738
9869
  if (!resources) return null;
9739
- const dir = (0, import_node_path27.join)(resources, "cursor-runtime");
9740
- if (!(0, import_node_fs24.existsSync)((0, import_node_path27.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
9870
+ const dir = (0, import_node_path28.join)(resources, "cursor-runtime");
9871
+ if (!(0, import_node_fs25.existsSync)((0, import_node_path28.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
9741
9872
  return dir;
9742
9873
  }
9743
9874
  function packagedCursorRunnerPath() {
9744
9875
  const dir = packagedCursorRuntimeDir();
9745
- return dir ? (0, import_node_path27.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
9876
+ return dir ? (0, import_node_path28.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
9746
9877
  }
9747
9878
  function packagedMcpDir() {
9748
9879
  const resources = electronResourcesPath();
9749
9880
  if (!resources) return null;
9750
- const dir = (0, import_node_path27.join)(resources, "sideboard-mcp");
9751
- if (!(0, import_node_fs24.existsSync)((0, import_node_path27.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
9881
+ const dir = (0, import_node_path28.join)(resources, "sideboard-mcp");
9882
+ if (!(0, import_node_fs25.existsSync)((0, import_node_path28.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
9752
9883
  return dir;
9753
9884
  }
9754
9885
  function packagedMcpStdioPath() {
9755
9886
  const dir = packagedMcpDir();
9756
- return dir ? (0, import_node_path27.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
9887
+ return dir ? (0, import_node_path28.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
9757
9888
  }
9758
9889
  function packagedBundledNodePath() {
9759
9890
  const resources = electronResourcesPath();
9760
9891
  if (!resources) return null;
9761
- const bin = (0, import_node_path27.join)(resources, "node", "bin", "node");
9762
- if (!(0, import_node_fs24.existsSync)(bin)) return null;
9892
+ const bin = (0, import_node_path28.join)(resources, "node", "bin", "node");
9893
+ if (!(0, import_node_fs25.existsSync)(bin)) return null;
9763
9894
  return bin;
9764
9895
  }
9765
9896
  function packagedCursorRipgrepCandidate(platformPkg, binName) {
9766
9897
  const dir = packagedCursorRuntimeDir();
9767
9898
  if (!dir) return null;
9768
- return (0, import_node_path27.join)(dir, "node_modules", platformPkg, "bin", binName);
9899
+ return (0, import_node_path28.join)(dir, "node_modules", platformPkg, "bin", binName);
9769
9900
  }
9770
- var import_node_fs24, import_node_path27;
9901
+ var import_node_fs25, import_node_path28;
9771
9902
  var init_packaged_runtime = __esm({
9772
9903
  "src/agents/packaged-runtime.ts"() {
9773
9904
  "use strict";
9774
- import_node_fs24 = require("fs");
9775
- import_node_path27 = require("path");
9905
+ import_node_fs25 = require("fs");
9906
+ import_node_path28 = require("path");
9776
9907
  }
9777
9908
  });
9778
9909
 
@@ -9807,7 +9938,7 @@ function unpackedAsarPath(filePath) {
9807
9938
  if (!isAsarPath(filePath)) return null;
9808
9939
  const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
9809
9940
  if (unpacked === filePath) return null;
9810
- return (0, import_node_fs25.existsSync)(unpacked) ? unpacked : null;
9941
+ return (0, import_node_fs26.existsSync)(unpacked) ? unpacked : null;
9811
9942
  }
9812
9943
  function nodeReadableScriptPath(scriptPath) {
9813
9944
  return unpackedAsarPath(scriptPath) ?? scriptPath;
@@ -9847,37 +9978,37 @@ function pickPreferredNode(candidates) {
9847
9978
  return best;
9848
9979
  }
9849
9980
  function versionDirNodeBins(root, toBin) {
9850
- if (!(0, import_node_fs25.existsSync)(root)) return [];
9981
+ if (!(0, import_node_fs26.existsSync)(root)) return [];
9851
9982
  try {
9852
- return (0, import_node_fs25.readdirSync)(root).map(toBin);
9983
+ return (0, import_node_fs26.readdirSync)(root).map(toBin);
9853
9984
  } catch {
9854
9985
  return [];
9855
9986
  }
9856
9987
  }
9857
9988
  function defaultNodeBinCandidates(home = (0, import_node_os8.homedir)()) {
9858
9989
  const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
9859
- (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path28.join)(prefix, "opt", `node@${major}`, "bin", "node"))
9990
+ (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path29.join)(prefix, "opt", `node@${major}`, "bin", "node"))
9860
9991
  );
9861
9992
  return [
9862
9993
  ...kegs,
9863
9994
  "/opt/homebrew/bin/node",
9864
9995
  "/usr/local/bin/node",
9865
- (0, import_node_path28.join)(home, ".local/share/fnm/aliases/default/bin/node"),
9866
- (0, import_node_path28.join)(home, ".nvm/current/bin/node"),
9867
- (0, import_node_path28.join)(home, ".volta/bin/node"),
9868
- (0, import_node_path28.join)(home, ".asdf/shims/node"),
9869
- (0, import_node_path28.join)(home, ".local/share/mise/shims/node"),
9996
+ (0, import_node_path29.join)(home, ".local/share/fnm/aliases/default/bin/node"),
9997
+ (0, import_node_path29.join)(home, ".nvm/current/bin/node"),
9998
+ (0, import_node_path29.join)(home, ".volta/bin/node"),
9999
+ (0, import_node_path29.join)(home, ".asdf/shims/node"),
10000
+ (0, import_node_path29.join)(home, ".local/share/mise/shims/node"),
9870
10001
  ...versionDirNodeBins(
9871
- (0, import_node_path28.join)(home, ".nvm", "versions", "node"),
9872
- (name) => (0, import_node_path28.join)(home, ".nvm", "versions", "node", name, "bin", "node")
10002
+ (0, import_node_path29.join)(home, ".nvm", "versions", "node"),
10003
+ (name) => (0, import_node_path29.join)(home, ".nvm", "versions", "node", name, "bin", "node")
9873
10004
  ),
9874
10005
  ...versionDirNodeBins(
9875
- (0, import_node_path28.join)(home, ".local/share/fnm", "node-versions"),
9876
- (name) => (0, import_node_path28.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
10006
+ (0, import_node_path29.join)(home, ".local/share/fnm", "node-versions"),
10007
+ (name) => (0, import_node_path29.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
9877
10008
  ),
9878
10009
  ...versionDirNodeBins(
9879
- (0, import_node_path28.join)(home, ".volta", "tools", "image", "node"),
9880
- (name) => (0, import_node_path28.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
10010
+ (0, import_node_path29.join)(home, ".volta", "tools", "image", "node"),
10011
+ (name) => (0, import_node_path29.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
9881
10012
  )
9882
10013
  ];
9883
10014
  }
@@ -9886,10 +10017,10 @@ function uniqueExistingNodeBins(paths) {
9886
10017
  const out = [];
9887
10018
  for (const raw of paths) {
9888
10019
  const p = raw.trim();
9889
- if (!p || !(0, import_node_fs25.existsSync)(p) || isElectronLikeCommand(p)) continue;
10020
+ if (!p || !(0, import_node_fs26.existsSync)(p) || isElectronLikeCommand(p)) continue;
9890
10021
  let key = p;
9891
10022
  try {
9892
- key = (0, import_node_fs25.realpathSync)(p);
10023
+ key = (0, import_node_fs26.realpathSync)(p);
9893
10024
  } catch {
9894
10025
  continue;
9895
10026
  }
@@ -9969,13 +10100,13 @@ async function resolveNodeLaunch(scriptPath) {
9969
10100
  env: { ELECTRON_RUN_AS_NODE: "1" }
9970
10101
  };
9971
10102
  }
9972
- var import_node_fs25, import_node_os8, import_node_path28, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
10103
+ var import_node_fs26, import_node_os8, import_node_path29, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
9973
10104
  var init_node_launch = __esm({
9974
10105
  "src/agents/node-launch.ts"() {
9975
10106
  "use strict";
9976
- import_node_fs25 = require("fs");
10107
+ import_node_fs26 = require("fs");
9977
10108
  import_node_os8 = require("os");
9978
- import_node_path28 = require("path");
10109
+ import_node_path29 = require("path");
9979
10110
  init_nested_electron_env();
9980
10111
  init_system_ca();
9981
10112
  init_run();
@@ -10078,37 +10209,37 @@ function corePackageDir() {
10078
10209
  try {
10079
10210
  const url = import_meta.url;
10080
10211
  if (typeof url === "string" && url.length > 0) {
10081
- return (0, import_node_path29.dirname)((0, import_node_url.fileURLToPath)(url));
10212
+ return (0, import_node_path30.dirname)((0, import_node_url.fileURLToPath)(url));
10082
10213
  }
10083
10214
  } catch {
10084
10215
  }
10085
10216
  try {
10086
- const req = (0, import_node_module.createRequire)((0, import_node_path29.join)(process.cwd(), "package.json"));
10087
- return (0, import_node_path29.dirname)(req.resolve("@sideboard-ai/core"));
10217
+ const req = (0, import_node_module.createRequire)((0, import_node_path30.join)(process.cwd(), "package.json"));
10218
+ return (0, import_node_path30.dirname)(req.resolve("@sideboard-ai/core"));
10088
10219
  } catch {
10089
10220
  return process.cwd();
10090
10221
  }
10091
10222
  }
10092
10223
  function findSideboardMcpJsEntry() {
10093
10224
  const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
10094
- if (override && (0, import_node_fs26.existsSync)(override)) return override;
10225
+ if (override && (0, import_node_fs27.existsSync)(override)) return override;
10095
10226
  const packaged = packagedMcpStdioPath();
10096
10227
  if (packaged) return packaged;
10097
10228
  let dir = corePackageDir();
10098
10229
  for (let i = 0; i < 10; i++) {
10099
10230
  const candidates = [
10100
- (0, import_node_path29.join)(dir, "mcp/run-stdio.js"),
10101
- (0, import_node_path29.join)(dir, "mcp/run-stdio.cjs"),
10102
- (0, import_node_path29.join)(dir, "dist/mcp/run-stdio.js"),
10103
- (0, import_node_path29.join)(dir, "dist/mcp/run-stdio.cjs"),
10104
- (0, import_node_path29.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
10105
- (0, import_node_path29.join)(dir, "packages/cli/dist/index.js"),
10106
- (0, import_node_path29.join)(dir, "cli/dist/index.js")
10231
+ (0, import_node_path30.join)(dir, "mcp/run-stdio.js"),
10232
+ (0, import_node_path30.join)(dir, "mcp/run-stdio.cjs"),
10233
+ (0, import_node_path30.join)(dir, "dist/mcp/run-stdio.js"),
10234
+ (0, import_node_path30.join)(dir, "dist/mcp/run-stdio.cjs"),
10235
+ (0, import_node_path30.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
10236
+ (0, import_node_path30.join)(dir, "packages/cli/dist/index.js"),
10237
+ (0, import_node_path30.join)(dir, "cli/dist/index.js")
10107
10238
  ];
10108
10239
  for (const p of candidates) {
10109
- if ((0, import_node_fs26.existsSync)(p) && !isAsarPath(p)) return p;
10240
+ if ((0, import_node_fs27.existsSync)(p) && !isAsarPath(p)) return p;
10110
10241
  }
10111
- const parent = (0, import_node_path29.dirname)(dir);
10242
+ const parent = (0, import_node_path30.dirname)(dir);
10112
10243
  if (parent === dir) break;
10113
10244
  dir = parent;
10114
10245
  }
@@ -10271,19 +10402,19 @@ function writeMcpServersConfig(servers, extraServers) {
10271
10402
  }
10272
10403
  }
10273
10404
  if (Object.keys(mcpServers).length === 0) return null;
10274
- const dir = (0, import_node_fs26.mkdtempSync)((0, import_node_path29.join)((0, import_node_os9.tmpdir)(), "sideboard-mcp-"));
10275
- const cfgPath = (0, import_node_path29.join)(dir, "mcp.json");
10276
- (0, import_node_fs26.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
10405
+ const dir = (0, import_node_fs27.mkdtempSync)((0, import_node_path30.join)((0, import_node_os9.tmpdir)(), "sideboard-mcp-"));
10406
+ const cfgPath = (0, import_node_path30.join)(dir, "mcp.json");
10407
+ (0, import_node_fs27.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
10277
10408
  return cfgPath;
10278
10409
  }
10279
- var import_node_fs26, import_node_module, import_node_os9, import_node_path29, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS, SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS, SIDEBOARD_ABLETIME_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
10410
+ var import_node_fs27, import_node_module, import_node_os9, import_node_path30, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS, SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS, SIDEBOARD_ABLETIME_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
10280
10411
  var init_injected_mcp = __esm({
10281
10412
  "src/agents/injected-mcp.ts"() {
10282
10413
  "use strict";
10283
- import_node_fs26 = require("fs");
10414
+ import_node_fs27 = require("fs");
10284
10415
  import_node_module = require("module");
10285
10416
  import_node_os9 = require("os");
10286
- import_node_path29 = require("path");
10417
+ import_node_path30 = require("path");
10287
10418
  import_node_url = require("url");
10288
10419
  init_run();
10289
10420
  init_config();
@@ -10324,15 +10455,15 @@ var init_injected_mcp = __esm({
10324
10455
 
10325
10456
  // src/agents/user-mcp-config.ts
10326
10457
  function userClaudeMcpConfigPath() {
10327
- return (0, import_node_path30.join)((0, import_node_os10.homedir)(), ".claude.json");
10458
+ return (0, import_node_path31.join)((0, import_node_os10.homedir)(), ".claude.json");
10328
10459
  }
10329
- var import_node_fs27, import_node_os10, import_node_path30;
10460
+ var import_node_fs28, import_node_os10, import_node_path31;
10330
10461
  var init_user_mcp_config = __esm({
10331
10462
  "src/agents/user-mcp-config.ts"() {
10332
10463
  "use strict";
10333
- import_node_fs27 = require("fs");
10464
+ import_node_fs28 = require("fs");
10334
10465
  import_node_os10 = require("os");
10335
- import_node_path30 = require("path");
10466
+ import_node_path31 = require("path");
10336
10467
  init_paths();
10337
10468
  init_injected_mcp();
10338
10469
  }
@@ -10358,27 +10489,27 @@ function listMcpNamesFromCodexToml(text7) {
10358
10489
  return [];
10359
10490
  }
10360
10491
  }
10361
- function readJsonObject(path) {
10492
+ function readJsonObject2(path) {
10362
10493
  try {
10363
- return JSON.parse((0, import_node_fs28.readFileSync)(path, "utf8"));
10494
+ return JSON.parse((0, import_node_fs29.readFileSync)(path, "utf8"));
10364
10495
  } catch {
10365
10496
  return {};
10366
10497
  }
10367
10498
  }
10368
10499
  function readText(path) {
10369
10500
  try {
10370
- return (0, import_node_fs28.readFileSync)(path, "utf8");
10501
+ return (0, import_node_fs29.readFileSync)(path, "utf8");
10371
10502
  } catch {
10372
10503
  return "";
10373
10504
  }
10374
10505
  }
10375
10506
  function userCodexConfigPaths(home = (0, import_node_os11.homedir)()) {
10376
- return [(0, import_node_path31.join)(home, ".codex", "config.toml"), (0, import_node_path31.join)(home, ".config", "codex", "config.toml")];
10507
+ return [(0, import_node_path32.join)(home, ".codex", "config.toml"), (0, import_node_path32.join)(home, ".config", "codex", "config.toml")];
10377
10508
  }
10378
10509
  function userOpencodeConfigPaths(home = (0, import_node_os11.homedir)()) {
10379
10510
  return [
10380
- (0, import_node_path31.join)(home, ".config", "opencode", "opencode.json"),
10381
- (0, import_node_path31.join)(home, ".config", "opencode", "opencode.jsonc")
10511
+ (0, import_node_path32.join)(home, ".config", "opencode", "opencode.json"),
10512
+ (0, import_node_path32.join)(home, ".config", "opencode", "opencode.jsonc")
10382
10513
  ];
10383
10514
  }
10384
10515
  function userMcpNamesToDisable(opts) {
@@ -10400,7 +10531,7 @@ function userMcpNamesToDisable(opts) {
10400
10531
  function listUserCodexMcpNames(home = (0, import_node_os11.homedir)()) {
10401
10532
  const names = [];
10402
10533
  for (const path of userCodexConfigPaths(home)) {
10403
- if (!(0, import_node_fs28.existsSync)(path)) continue;
10534
+ if (!(0, import_node_fs29.existsSync)(path)) continue;
10404
10535
  names.push(...listMcpNamesFromCodexToml(readText(path)));
10405
10536
  }
10406
10537
  return names;
@@ -10408,15 +10539,15 @@ function listUserCodexMcpNames(home = (0, import_node_os11.homedir)()) {
10408
10539
  function listUserOpencodeMcpNames(home = (0, import_node_os11.homedir)()) {
10409
10540
  const names = [];
10410
10541
  for (const path of userOpencodeConfigPaths(home)) {
10411
- if (!(0, import_node_fs28.existsSync)(path)) continue;
10412
- names.push(...listMcpNamesFromJsonMap(readJsonObject(path), "mcp"));
10542
+ if (!(0, import_node_fs29.existsSync)(path)) continue;
10543
+ names.push(...listMcpNamesFromJsonMap(readJsonObject2(path), "mcp"));
10413
10544
  }
10414
10545
  return names;
10415
10546
  }
10416
10547
  function userClaudeMcpConfigObject(home = (0, import_node_os11.homedir)()) {
10417
- const claudePath = home === (0, import_node_os11.homedir)() ? userClaudeMcpConfigPath() : (0, import_node_path31.join)(home, ".claude.json");
10418
- if (!(0, import_node_fs28.existsSync)(claudePath)) return {};
10419
- return asObject(asObject(readJsonObject(claudePath)).mcpServers);
10548
+ const claudePath = home === (0, import_node_os11.homedir)() ? userClaudeMcpConfigPath() : (0, import_node_path32.join)(home, ".claude.json");
10549
+ if (!(0, import_node_fs29.existsSync)(claudePath)) return {};
10550
+ return asObject(asObject(readJsonObject2(claudePath)).mcpServers);
10420
10551
  }
10421
10552
  function listUserClaudeMcpServerEntries(home = (0, import_node_os11.homedir)()) {
10422
10553
  const out = {};
@@ -10448,13 +10579,13 @@ function toCodexUnattendedAppsArgs() {
10448
10579
  "features.plugins=false"
10449
10580
  ];
10450
10581
  }
10451
- var import_node_fs28, import_node_os11, import_node_path31, import_smol_toml2;
10582
+ var import_node_fs29, import_node_os11, import_node_path32, import_smol_toml2;
10452
10583
  var init_orch_mcp_isolation = __esm({
10453
10584
  "src/agents/orch-mcp-isolation.ts"() {
10454
10585
  "use strict";
10455
- import_node_fs28 = require("fs");
10586
+ import_node_fs29 = require("fs");
10456
10587
  import_node_os11 = require("os");
10457
- import_node_path31 = require("path");
10588
+ import_node_path32 = require("path");
10458
10589
  import_smol_toml2 = require("smol-toml");
10459
10590
  init_user_mcp_config();
10460
10591
  }
@@ -10475,7 +10606,76 @@ function clipChatLine(value, max = CHAT_DETAIL_MAX) {
10475
10606
  if (line.length <= max) return line;
10476
10607
  return `${line.slice(0, Math.max(1, max - 1))}\u2026`;
10477
10608
  }
10609
+ function isSkillToolName(name) {
10610
+ const n = (name ?? "").trim();
10611
+ if (/^(Skill|SlashCommand)$/i.test(n)) return true;
10612
+ return /(?:^|__)Skill$/i.test(n);
10613
+ }
10614
+ function skillCommandFromInput(input) {
10615
+ const raw = str2(input?.skill) ?? str2(input?.command) ?? str2(input?.name) ?? str2(input?.skill_name) ?? str2(input?.skillName);
10616
+ if (raw) return raw.replace(/^\//, "").trim() || void 0;
10617
+ const path = str2(input?.file_path) ?? str2(input?.path);
10618
+ if (path && /SKILL\.md$/i.test(path)) {
10619
+ const parts = path.replace(/\\/g, "/").split("/");
10620
+ const dir = parts[parts.length - 2];
10621
+ if (dir && dir !== "skills") return dir;
10622
+ }
10623
+ return void 0;
10624
+ }
10625
+ function looksLikeSkillBody(text7) {
10626
+ const t = text7.trim();
10627
+ if (!t) return false;
10628
+ if (/^## Skill: \//m.test(t) && /Follow this skill for the request above:/i.test(t)) {
10629
+ return true;
10630
+ }
10631
+ return skillNameFromFrontmatter(t) != null;
10632
+ }
10633
+ function skillNameFromFrontmatter(text7) {
10634
+ const t = text7.trim();
10635
+ if (!t.startsWith("---")) return void 0;
10636
+ const close = t.indexOf("\n---", 3);
10637
+ if (close < 0) return void 0;
10638
+ const fm = t.slice(3, close);
10639
+ const m = fm.match(/^\s*name\s*:\s*['"]?([A-Za-z0-9][A-Za-z0-9._-]*)['"]?\s*$/m);
10640
+ return m?.[1];
10641
+ }
10642
+ function skillCommandFromBody(text7) {
10643
+ return skillNameFromFrontmatter(text7) ?? text7.match(/^## Skill: \/([A-Za-z0-9][A-Za-z0-9._-]*)/m)?.[1];
10644
+ }
10645
+ function isCompactToolName(name) {
10646
+ const short = (name ?? "").replace(/^mcp__[^_]+__/, "").trim();
10647
+ return /^(Compact|ConversationCompact|summarize_context|SummarizeContext|SummarizeConversation)$/i.test(
10648
+ short
10649
+ );
10650
+ }
10651
+ function isContextCompactInProgress(text7) {
10652
+ return /^Compressing context/i.test(text7.trim());
10653
+ }
10654
+ function isContextCompactDone(text7) {
10655
+ return /^Context compressed\b/i.test(text7.trim());
10656
+ }
10657
+ function looksLikeConversationSummary(text7) {
10658
+ const t = text7.trim();
10659
+ if (t.length < 80) return false;
10660
+ if (/<summarized_conversation\b/i.test(t) || /<conversation_summary\b/i.test(t)) {
10661
+ return true;
10662
+ }
10663
+ if (/this session is being continued from a previous conversation/i.test(t)) {
10664
+ return true;
10665
+ }
10666
+ if (/conversation compacted|replaced with a summary/i.test(t)) return true;
10667
+ if (/^## Prior summary\b/m.test(t)) return true;
10668
+ if (/_Automatic extractive summary/i.test(t)) return true;
10669
+ if (/"context_summary"\s*:/.test(t)) return true;
10670
+ if (/^(?:#+\s*)?(?:conversation summary|summary of (?:the )?conversation|compacted (?:conversation|context))\b/im.test(
10671
+ t
10672
+ )) {
10673
+ return true;
10674
+ }
10675
+ return false;
10676
+ }
10478
10677
  function toolDetail(name, input) {
10678
+ if (isSkillToolName(name) || isCompactToolName(name)) return void 0;
10479
10679
  if (!input) return void 0;
10480
10680
  const command = str2(input.command) ?? str2(input.cmd);
10481
10681
  if (command) return clipChatLine(command);
@@ -10527,6 +10727,17 @@ function toolDescription(name, input) {
10527
10727
  if (/stop_dev_script$/i.test(name)) {
10528
10728
  return str2(input?.name) ? `Stop ${str2(input?.name)}` : "Stop Dev script";
10529
10729
  }
10730
+ if (isSkillToolName(name)) {
10731
+ const cmd = skillCommandFromInput(input);
10732
+ return cmd ? `Using /${cmd}` : "Using skill";
10733
+ }
10734
+ if (isCompactToolName(name)) {
10735
+ const trigger = str2(input?.trigger);
10736
+ if (trigger && !/^auto$/i.test(trigger) && trigger !== "injected") {
10737
+ return `Summarized conversation (${trigger})`;
10738
+ }
10739
+ return "Summarized conversation";
10740
+ }
10530
10741
  if (isSubagentToolName(name)) {
10531
10742
  const desc = str2(input?.description);
10532
10743
  const sub = asRecord(input?.subagentType);
@@ -10739,10 +10950,107 @@ function withPartTimes(next, prev) {
10739
10950
  const startedAt = prev && typeof prev.startedAt === "number" ? prev.startedAt : now;
10740
10951
  return { ...next, startedAt, updatedAt: now };
10741
10952
  }
10953
+ function skillToolFromTextPart(part, id) {
10954
+ const command = skillCommandFromBody(part.text);
10955
+ const input = command ? { skill: command } : void 0;
10956
+ return {
10957
+ type: "tool",
10958
+ id,
10959
+ name: "Skill",
10960
+ input,
10961
+ description: toolDescription("Skill", input),
10962
+ status: "done",
10963
+ result: clipToolResultForStore(part.text),
10964
+ ...part.parentId ? { parentId: part.parentId } : {},
10965
+ startedAt: part.startedAt,
10966
+ updatedAt: Date.now()
10967
+ };
10968
+ }
10969
+ function compactToolPart(text7, id, opts) {
10970
+ const input = { trigger: opts?.trigger ?? "auto" };
10971
+ return withPartTimes(
10972
+ {
10973
+ type: "tool",
10974
+ id,
10975
+ name: "Compact",
10976
+ input,
10977
+ description: toolDescription("Compact", input),
10978
+ status: opts?.status ?? "done",
10979
+ result: clipToolResultForStore(text7) ?? "",
10980
+ ...opts?.parentId ? { parentId: opts.parentId } : {}
10981
+ },
10982
+ opts?.prev
10983
+ );
10984
+ }
10985
+ function contextCompactInProgress(parts, parentId) {
10986
+ let compressing = false;
10987
+ for (const p of parts) {
10988
+ if (!sameParentId(p.parentId, parentId)) continue;
10989
+ if (p.type === "thinking" && isContextCompactInProgress(p.text)) compressing = true;
10990
+ if (p.type === "thinking" && isContextCompactDone(p.text)) compressing = false;
10991
+ }
10992
+ return compressing;
10993
+ }
10994
+ function lastRunningCompactIndex(parts, parentId) {
10995
+ for (let i = parts.length - 1; i >= 0; i--) {
10996
+ const p = parts[i];
10997
+ if (p.type === "tool" && isCompactToolName(p.name) && p.status === "running" && sameParentId(p.parentId, parentId)) {
10998
+ return i;
10999
+ }
11000
+ }
11001
+ return -1;
11002
+ }
11003
+ function markRunningCompactDone(parts, parentId) {
11004
+ return parts.map((p) => {
11005
+ if (p.type === "tool" && isCompactToolName(p.name) && p.status === "running" && sameParentId(p.parentId, parentId)) {
11006
+ return withPartTimes({ ...p, status: "done" }, p);
11007
+ }
11008
+ return p;
11009
+ });
11010
+ }
11011
+ function ensureCompactTool(parts, parentId) {
11012
+ const hasCompact = parts.some(
11013
+ (p) => p.type === "tool" && isCompactToolName(p.name) && sameParentId(p.parentId, parentId)
11014
+ );
11015
+ if (hasCompact) return parts;
11016
+ return [
11017
+ ...parts,
11018
+ compactToolPart("Context compressed", `compact-${parts.length}`, {
11019
+ parentId,
11020
+ status: "done"
11021
+ })
11022
+ ];
11023
+ }
11024
+ function withCompactFinish(parts, thinking, parentId) {
11025
+ if (!isContextCompactDone(thinking)) return parts;
11026
+ return ensureCompactTool(markRunningCompactDone(parts, parentId), parentId);
11027
+ }
10742
11028
  function applyAgentEvent(parts, event) {
10743
11029
  if (event.type === "stdout") {
10744
11030
  const data = event.data;
10745
11031
  if (!data) return parts;
11032
+ const runningIdx = lastRunningCompactIndex(parts, event.parentId);
11033
+ if (runningIdx >= 0) {
11034
+ const prev = parts[runningIdx];
11035
+ const next2 = [...parts];
11036
+ next2[runningIdx] = withPartTimes(
11037
+ {
11038
+ ...prev,
11039
+ result: clipToolResultForStore(`${prev.result ?? ""}${data}`)
11040
+ },
11041
+ prev
11042
+ );
11043
+ return next2;
11044
+ }
11045
+ if (contextCompactInProgress(parts, event.parentId)) {
11046
+ return [
11047
+ ...parts,
11048
+ compactToolPart(data, `compact-${parts.length}`, {
11049
+ parentId: event.parentId,
11050
+ status: "running"
11051
+ })
11052
+ ];
11053
+ }
10746
11054
  const next = [...parts];
10747
11055
  const last = next[next.length - 1];
10748
11056
  if (last?.type === "text" && sameParentId(last.parentId, event.parentId)) {
@@ -10763,6 +11071,16 @@ function applyAgentEvent(parts, event) {
10763
11071
  })
10764
11072
  );
10765
11073
  }
11074
+ const acc = next[next.length - 1];
11075
+ if (acc?.type === "text" && looksLikeSkillBody(acc.text)) {
11076
+ next[next.length - 1] = skillToolFromTextPart(acc, `skill-${next.length}`);
11077
+ } else if (acc?.type === "text" && looksLikeConversationSummary(acc.text)) {
11078
+ next[next.length - 1] = compactToolPart(acc.text, `compact-${next.length}`, {
11079
+ parentId: acc.parentId,
11080
+ status: "done",
11081
+ prev: acc
11082
+ });
11083
+ }
10766
11084
  return next;
10767
11085
  }
10768
11086
  if (event.type === "thinking") {
@@ -10781,7 +11099,7 @@ function applyAgentEvent(parts, event) {
10781
11099
  },
10782
11100
  prev
10783
11101
  );
10784
- return next;
11102
+ return withCompactFinish(next, data, event.parentId);
10785
11103
  }
10786
11104
  }
10787
11105
  next.push(
@@ -10791,7 +11109,7 @@ function applyAgentEvent(parts, event) {
10791
11109
  ...event.parentId ? { parentId: event.parentId } : {}
10792
11110
  })
10793
11111
  );
10794
- return next;
11112
+ return withCompactFinish(next, data, event.parentId);
10795
11113
  }
10796
11114
  const last = next[next.length - 1];
10797
11115
  if (last?.type === "thinking" && sameParentId(last.parentId, event.parentId)) {
@@ -10812,7 +11130,7 @@ function applyAgentEvent(parts, event) {
10812
11130
  })
10813
11131
  );
10814
11132
  }
10815
- return next;
11133
+ return withCompactFinish(next, data, event.parentId);
10816
11134
  }
10817
11135
  if (event.type === "tool_use") {
10818
11136
  const input = asRecord(event.input);
@@ -11072,6 +11390,87 @@ function claudeResultErrorDetail(obj) {
11072
11390
  }
11073
11391
  return "Claude turn failed";
11074
11392
  }
11393
+ function toolResultContent(block) {
11394
+ if (typeof block.content === "string") return block.content;
11395
+ if (Array.isArray(block.content)) {
11396
+ return block.content.map(
11397
+ (c) => typeof c === "string" ? c : c && typeof c === "object" && "text" in c ? String(c.text ?? "") : ""
11398
+ ).join("");
11399
+ }
11400
+ if (block.content != null) return JSON.stringify(block.content);
11401
+ return void 0;
11402
+ }
11403
+ function skillToolEventsFromBody(text7, parentId) {
11404
+ const command = skillCommandFromBody(text7) ?? "skill";
11405
+ const id = `skill-${command}`;
11406
+ return [
11407
+ withEventParentId(
11408
+ { type: "tool_use", id, name: "Skill", input: { skill: command } },
11409
+ parentId
11410
+ ),
11411
+ withEventParentId({ type: "tool_result", id, content: text7 }, parentId)
11412
+ ];
11413
+ }
11414
+ function compactToolEventsFromBody(text7, parentId) {
11415
+ const id = "compact-summary";
11416
+ return [
11417
+ withEventParentId(
11418
+ { type: "tool_use", id, name: "Compact", input: { trigger: "injected" } },
11419
+ parentId
11420
+ ),
11421
+ withEventParentId({ type: "tool_result", id, content: text7 }, parentId)
11422
+ ];
11423
+ }
11424
+ function eventsFromInjectedUserText(text7, parentId) {
11425
+ if (looksLikeSkillBody(text7)) return skillToolEventsFromBody(text7, parentId);
11426
+ if (looksLikeConversationSummary(text7)) return compactToolEventsFromBody(text7, parentId);
11427
+ return [];
11428
+ }
11429
+ function eventsFromUserContent(content, parentId) {
11430
+ if (typeof content === "string" && content.trim()) {
11431
+ return eventsFromInjectedUserText(content, parentId);
11432
+ }
11433
+ if (!Array.isArray(content) || content.length === 0) return [];
11434
+ const out = [];
11435
+ const textBlocks = [];
11436
+ for (const block of content) {
11437
+ if (!block?.type) continue;
11438
+ if (block.type === "tool_use" && block.id && block.name) {
11439
+ out.push(
11440
+ withEventParentId(
11441
+ {
11442
+ type: "tool_use",
11443
+ id: block.id,
11444
+ name: block.name,
11445
+ input: block.input
11446
+ },
11447
+ parentId
11448
+ )
11449
+ );
11450
+ continue;
11451
+ }
11452
+ if (block.type === "tool_result" && block.tool_use_id) {
11453
+ out.push(
11454
+ withEventParentId(
11455
+ {
11456
+ type: "tool_result",
11457
+ id: block.tool_use_id,
11458
+ content: toolResultContent(block),
11459
+ isError: Boolean(block.is_error)
11460
+ },
11461
+ parentId
11462
+ )
11463
+ );
11464
+ continue;
11465
+ }
11466
+ if (block.type === "text" && block.text) textBlocks.push(block.text);
11467
+ }
11468
+ if (out.length > 0) return out;
11469
+ for (const text7 of textBlocks) {
11470
+ out.push(...eventsFromInjectedUserText(text7, parentId));
11471
+ }
11472
+ return out;
11473
+ }
11075
11474
  function eventsFromContentBlocks(blocks, parentId) {
11076
11475
  if (!blocks?.length) return [];
11077
11476
  const out = [];
@@ -11100,15 +11499,12 @@ function eventsFromContentBlocks(blocks, parentId) {
11100
11499
  continue;
11101
11500
  }
11102
11501
  if (block.type === "tool_result" && block.tool_use_id) {
11103
- const content = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map(
11104
- (c) => typeof c === "string" ? c : c && typeof c === "object" && "text" in c ? String(c.text ?? "") : ""
11105
- ).join("") : block.content != null ? JSON.stringify(block.content) : void 0;
11106
11502
  out.push(
11107
11503
  withEventParentId(
11108
11504
  {
11109
11505
  type: "tool_result",
11110
11506
  id: block.tool_use_id,
11111
- content,
11507
+ content: toolResultContent(block),
11112
11508
  isError: Boolean(block.is_error)
11113
11509
  },
11114
11510
  parentId
@@ -11318,11 +11714,11 @@ function parseIssuesJson(raw) {
11318
11714
  }
11319
11715
  return [];
11320
11716
  }
11321
- var import_node_fs29, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
11717
+ var import_node_fs30, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
11322
11718
  var init_claude = __esm({
11323
11719
  "src/agents/claude.ts"() {
11324
11720
  "use strict";
11325
- import_node_fs29 = require("fs");
11721
+ import_node_fs30 = require("fs");
11326
11722
  init_run();
11327
11723
  init_app_settings();
11328
11724
  init_claude_mcp();
@@ -11362,7 +11758,7 @@ var init_claude = __esm({
11362
11758
  async detect() {
11363
11759
  const claude = resolveClaudeExecutable();
11364
11760
  if (claude !== "claude") {
11365
- if (!(0, import_node_fs29.existsSync)(claude)) {
11761
+ if (!(0, import_node_fs30.existsSync)(claude)) {
11366
11762
  return {
11367
11763
  agent: "claude",
11368
11764
  installed: false,
@@ -11511,7 +11907,10 @@ var init_claude = __esm({
11511
11907
  if (obj.type === "assistant" || obj.type === "user") {
11512
11908
  const parentId = claudeParentToolUseId(obj);
11513
11909
  const message = obj.message;
11514
- const events = eventsFromContentBlocks(message?.content, parentId);
11910
+ const events = obj.type === "user" ? eventsFromUserContent(message?.content, parentId) : eventsFromContentBlocks(
11911
+ Array.isArray(message?.content) ? message.content : void 0,
11912
+ parentId
11913
+ );
11515
11914
  if (obj.type === "assistant") {
11516
11915
  const usage = usageFromClaude(message?.usage);
11517
11916
  if (usage) events.push({ type: "usage", data: usage, scope: "request" });
@@ -11630,7 +12029,7 @@ async function listCodexModels() {
11630
12029
  if (codex === "codex") {
11631
12030
  const which = await run("which", ["codex"], { reject: false });
11632
12031
  if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
11633
- } else if (!(0, import_node_fs30.existsSync)(codex)) {
12032
+ } else if (!(0, import_node_fs31.existsSync)(codex)) {
11634
12033
  return FALLBACK_CODEX_MODELS;
11635
12034
  }
11636
12035
  const listed = await run(codex, ["debug", "models"], { reject: false });
@@ -11665,12 +12064,12 @@ function usageFromCodex(usage) {
11665
12064
  }
11666
12065
  function codexConfigHasNetworkAccess() {
11667
12066
  const candidates = [
11668
- (0, import_node_path32.join)((0, import_node_os12.homedir)(), ".codex", "config.toml"),
11669
- (0, import_node_path32.join)((0, import_node_os12.homedir)(), ".config", "codex", "config.toml")
12067
+ (0, import_node_path33.join)((0, import_node_os12.homedir)(), ".codex", "config.toml"),
12068
+ (0, import_node_path33.join)((0, import_node_os12.homedir)(), ".config", "codex", "config.toml")
11670
12069
  ];
11671
12070
  for (const path of candidates) {
11672
- if (!(0, import_node_fs30.existsSync)(path)) continue;
11673
- const text7 = (0, import_node_fs30.readFileSync)(path, "utf8");
12071
+ if (!(0, import_node_fs31.existsSync)(path)) continue;
12072
+ const text7 = (0, import_node_fs31.readFileSync)(path, "utf8");
11674
12073
  if (/network_access\s*=\s*true/.test(text7)) return true;
11675
12074
  }
11676
12075
  return false;
@@ -11702,21 +12101,21 @@ function asRecord2(value) {
11702
12101
  return void 0;
11703
12102
  }
11704
12103
  function codexLooksAuthenticated() {
11705
- const authPath = (0, import_node_path32.join)((0, import_node_os12.homedir)(), ".codex", "auth.json");
11706
- if (!(0, import_node_fs30.existsSync)(authPath)) return false;
12104
+ const authPath = (0, import_node_path33.join)((0, import_node_os12.homedir)(), ".codex", "auth.json");
12105
+ if (!(0, import_node_fs31.existsSync)(authPath)) return false;
11707
12106
  try {
11708
- return (0, import_node_fs30.statSync)(authPath).size > 2;
12107
+ return (0, import_node_fs31.statSync)(authPath).size > 2;
11709
12108
  } catch {
11710
12109
  return false;
11711
12110
  }
11712
12111
  }
11713
- var import_node_fs30, import_node_os12, import_node_path32, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
12112
+ var import_node_fs31, import_node_os12, import_node_path33, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
11714
12113
  var init_codex = __esm({
11715
12114
  "src/agents/codex.ts"() {
11716
12115
  "use strict";
11717
- import_node_fs30 = require("fs");
12116
+ import_node_fs31 = require("fs");
11718
12117
  import_node_os12 = require("os");
11719
- import_node_path32 = require("path");
12118
+ import_node_path33 = require("path");
11720
12119
  init_run();
11721
12120
  init_app_settings();
11722
12121
  init_global_workspace();
@@ -11742,7 +12141,7 @@ var init_codex = __esm({
11742
12141
  async detect() {
11743
12142
  const codex = resolveAgentExecutable("codex");
11744
12143
  if (codex !== "codex") {
11745
- if (!(0, import_node_fs30.existsSync)(codex)) {
12144
+ if (!(0, import_node_fs31.existsSync)(codex)) {
11746
12145
  return {
11747
12146
  agent: "codex",
11748
12147
  installed: false,
@@ -12019,18 +12418,18 @@ var init_codex = __esm({
12019
12418
  // src/agents/cursor-sdk-resolve.ts
12020
12419
  function thisModuleFile() {
12021
12420
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
12022
- if (cjsDir) return (0, import_node_path33.join)(cjsDir, "cursor-sdk-resolve.js");
12421
+ if (cjsDir) return (0, import_node_path34.join)(cjsDir, "cursor-sdk-resolve.js");
12023
12422
  try {
12024
12423
  return (0, import_node_url2.fileURLToPath)(import_meta2.url);
12025
12424
  } catch {
12026
- return (0, import_node_path33.join)(process.cwd(), "package.json");
12425
+ return (0, import_node_path34.join)(process.cwd(), "package.json");
12027
12426
  }
12028
12427
  }
12029
12428
  function packageRootLooksLikeSdk(dir) {
12030
12429
  try {
12031
- const raw = (0, import_node_fs31.readFileSync)((0, import_node_path33.join)(dir, "package.json"), "utf8");
12430
+ const raw = (0, import_node_fs32.readFileSync)((0, import_node_path34.join)(dir, "package.json"), "utf8");
12032
12431
  const pkg = JSON.parse(raw);
12033
- return pkg.name === "@cursor/sdk" && (0, import_node_fs31.existsSync)(dir);
12432
+ return pkg.name === "@cursor/sdk" && (0, import_node_fs32.existsSync)(dir);
12034
12433
  } catch {
12035
12434
  return false;
12036
12435
  }
@@ -12039,7 +12438,7 @@ function resolvedPackageRoot(fromFile) {
12039
12438
  try {
12040
12439
  const req = (0, import_node_module2.createRequire)(fromFile);
12041
12440
  const pkgJson = req.resolve("@cursor/sdk/package.json");
12042
- const root = (0, import_node_path33.dirname)(pkgJson);
12441
+ const root = (0, import_node_path34.dirname)(pkgJson);
12043
12442
  return packageRootLooksLikeSdk(root) ? root : null;
12044
12443
  } catch {
12045
12444
  return null;
@@ -12053,10 +12452,10 @@ function resolveCursorSdkRoot(opts) {
12053
12452
  }
12054
12453
  const globalNm = npmGlobalNodeModules(env);
12055
12454
  if (globalNm) {
12056
- const globalRoot = (0, import_node_path33.join)(globalNm, "@cursor/sdk");
12455
+ const globalRoot = (0, import_node_path34.join)(globalNm, "@cursor/sdk");
12057
12456
  if (packageRootLooksLikeSdk(globalRoot)) return globalRoot;
12058
12457
  }
12059
- const cwdPkg = (0, import_node_path33.join)(process.cwd(), "package.json");
12458
+ const cwdPkg = (0, import_node_path34.join)(process.cwd(), "package.json");
12060
12459
  return resolvedPackageRoot(thisModuleFile()) ?? resolvedPackageRoot(cwdPkg);
12061
12460
  }
12062
12461
  function isCursorSdkInstalled(opts) {
@@ -12072,13 +12471,13 @@ function exportTarget(value) {
12072
12471
  }
12073
12472
  function cursorSdkEsmEntry(root) {
12074
12473
  try {
12075
- const pkg = JSON.parse((0, import_node_fs31.readFileSync)((0, import_node_path33.join)(root, "package.json"), "utf8"));
12474
+ const pkg = JSON.parse((0, import_node_fs32.readFileSync)((0, import_node_path34.join)(root, "package.json"), "utf8"));
12076
12475
  const exp = pkg.exports;
12077
12476
  const dot = exp && typeof exp === "object" && !Array.isArray(exp) && "." in exp ? exp["."] : exp;
12078
12477
  const rel = exportTarget(dot) ?? (typeof pkg.module === "string" ? pkg.module : null);
12079
12478
  if (!rel) return null;
12080
- const entry = (0, import_node_path33.join)(root, rel);
12081
- return (0, import_node_fs31.existsSync)(entry) ? entry : null;
12479
+ const entry = (0, import_node_path34.join)(root, rel);
12480
+ return (0, import_node_fs32.existsSync)(entry) ? entry : null;
12082
12481
  } catch {
12083
12482
  return null;
12084
12483
  }
@@ -12094,7 +12493,7 @@ async function importCursorSdk(opts) {
12094
12493
  try {
12095
12494
  let entry = cursorSdkEsmEntry(root);
12096
12495
  if (!entry) {
12097
- const req = (0, import_node_module2.createRequire)((0, import_node_path33.join)(root, "package.json"));
12496
+ const req = (0, import_node_module2.createRequire)((0, import_node_path34.join)(root, "package.json"));
12098
12497
  entry = req.resolve("@cursor/sdk");
12099
12498
  }
12100
12499
  return unwrapCursorSdkModule(await import((0, import_node_url2.pathToFileURL)(entry).href));
@@ -12106,8 +12505,8 @@ function cursorSdkPlatformRipgrepPackage() {
12106
12505
  return `@cursor/sdk-${process.platform}-${process.arch}`;
12107
12506
  }
12108
12507
  function nodeModulesDirForPackageRoot(packageRoot) {
12109
- const parent = (0, import_node_path33.dirname)(packageRoot);
12110
- return (0, import_node_path33.basename)(parent).startsWith("@") ? (0, import_node_path33.dirname)(parent) : parent;
12508
+ const parent = (0, import_node_path34.dirname)(packageRoot);
12509
+ return (0, import_node_path34.basename)(parent).startsWith("@") ? (0, import_node_path34.dirname)(parent) : parent;
12111
12510
  }
12112
12511
  function cursorSdkRipgrepCandidate(opts) {
12113
12512
  const root = resolveCursorSdkRoot(opts);
@@ -12115,18 +12514,18 @@ function cursorSdkRipgrepCandidate(opts) {
12115
12514
  const nm = nodeModulesDirForPackageRoot(root);
12116
12515
  const pkg = cursorSdkPlatformRipgrepPackage();
12117
12516
  const bin = process.platform === "win32" ? "rg.exe" : "rg";
12118
- const sibling = (0, import_node_path33.join)(nm, pkg, "bin", bin);
12119
- if ((0, import_node_fs31.existsSync)(sibling)) return sibling;
12120
- const nested = (0, import_node_path33.join)(root, "node_modules", pkg, "bin", bin);
12121
- return (0, import_node_fs31.existsSync)(nested) ? nested : null;
12517
+ const sibling = (0, import_node_path34.join)(nm, pkg, "bin", bin);
12518
+ if ((0, import_node_fs32.existsSync)(sibling)) return sibling;
12519
+ const nested = (0, import_node_path34.join)(root, "node_modules", pkg, "bin", bin);
12520
+ return (0, import_node_fs32.existsSync)(nested) ? nested : null;
12122
12521
  }
12123
- var import_node_fs31, import_node_module2, import_node_path33, import_node_url2, import_meta2, CURSOR_SDK_INSTALL_HINT;
12522
+ var import_node_fs32, import_node_module2, import_node_path34, import_node_url2, import_meta2, CURSOR_SDK_INSTALL_HINT;
12124
12523
  var init_cursor_sdk_resolve = __esm({
12125
12524
  "src/agents/cursor-sdk-resolve.ts"() {
12126
12525
  "use strict";
12127
- import_node_fs31 = require("fs");
12526
+ import_node_fs32 = require("fs");
12128
12527
  import_node_module2 = require("module");
12129
- import_node_path33 = require("path");
12528
+ import_node_path34 = require("path");
12130
12529
  import_node_url2 = require("url");
12131
12530
  init_path();
12132
12531
  import_meta2 = {};
@@ -12168,21 +12567,21 @@ function platformRipgrepPackage() {
12168
12567
  }
12169
12568
  function usableRipgrepPath(candidate) {
12170
12569
  const raw = candidate?.trim();
12171
- if (!raw || !(0, import_node_path34.isAbsolute)(raw)) return null;
12570
+ if (!raw || !(0, import_node_path35.isAbsolute)(raw)) return null;
12172
12571
  const readable = nodeReadableScriptPath(raw);
12173
- if (!(0, import_node_fs32.existsSync)(readable) || isAsarPath(readable)) return null;
12572
+ if (!(0, import_node_fs33.existsSync)(readable) || isAsarPath(readable)) return null;
12174
12573
  return readable;
12175
12574
  }
12176
12575
  function walkForBundledRipgrep(startFile) {
12177
12576
  if (!startFile) return null;
12178
12577
  const pkg = platformRipgrepPackage();
12179
12578
  const name = rgBinaryName();
12180
- let dir = (0, import_node_path34.dirname)((0, import_node_path34.resolve)(startFile));
12181
- const root = (0, import_node_path34.parse)(dir).root;
12579
+ let dir = (0, import_node_path35.dirname)((0, import_node_path35.resolve)(startFile));
12580
+ const root = (0, import_node_path35.parse)(dir).root;
12182
12581
  while (dir !== root) {
12183
- const hit = usableRipgrepPath((0, import_node_path34.join)(dir, "node_modules", pkg, "bin", name));
12582
+ const hit = usableRipgrepPath((0, import_node_path35.join)(dir, "node_modules", pkg, "bin", name));
12184
12583
  if (hit) return hit;
12185
- const next = (0, import_node_path34.dirname)(dir);
12584
+ const next = (0, import_node_path35.dirname)(dir);
12186
12585
  if (next === dir) break;
12187
12586
  dir = next;
12188
12587
  }
@@ -12192,7 +12591,7 @@ function requireResolveBundledRipgrep(fromFile) {
12192
12591
  try {
12193
12592
  const req = (0, import_node_module3.createRequire)(fromFile);
12194
12593
  const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
12195
- return usableRipgrepPath((0, import_node_path34.join)((0, import_node_path34.dirname)(pkgJson), "bin", rgBinaryName()));
12594
+ return usableRipgrepPath((0, import_node_path35.join)((0, import_node_path35.dirname)(pkgJson), "bin", rgBinaryName()));
12196
12595
  } catch {
12197
12596
  return null;
12198
12597
  }
@@ -12214,13 +12613,13 @@ function cursorRipgrepEnv(opts) {
12214
12613
  const path = resolveCursorRipgrepPath(opts);
12215
12614
  return path ? { [RIPGREP_ENV]: path } : {};
12216
12615
  }
12217
- var import_node_fs32, import_node_module3, import_node_path34, RIPGREP_ENV;
12616
+ var import_node_fs33, import_node_module3, import_node_path35, RIPGREP_ENV;
12218
12617
  var init_cursor_ripgrep = __esm({
12219
12618
  "src/agents/cursor-ripgrep.ts"() {
12220
12619
  "use strict";
12221
- import_node_fs32 = require("fs");
12620
+ import_node_fs33 = require("fs");
12222
12621
  import_node_module3 = require("module");
12223
- import_node_path34 = require("path");
12622
+ import_node_path35 = require("path");
12224
12623
  init_cursor_sdk_resolve();
12225
12624
  init_node_launch();
12226
12625
  init_packaged_runtime();
@@ -12264,11 +12663,11 @@ function entryDir() {
12264
12663
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
12265
12664
  if (cjsDir) return cjsDir;
12266
12665
  try {
12267
- return (0, import_node_path35.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
12666
+ return (0, import_node_path36.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
12268
12667
  } catch {
12269
12668
  try {
12270
12669
  const req = (0, import_node_module4.createRequire)(process.cwd() + "/");
12271
- return (0, import_node_path35.dirname)(req.resolve("@sideboard-ai/core"));
12670
+ return (0, import_node_path36.dirname)(req.resolve("@sideboard-ai/core"));
12272
12671
  } catch {
12273
12672
  return process.cwd();
12274
12673
  }
@@ -12279,27 +12678,27 @@ function cursorRunnerPath() {
12279
12678
  if (packaged) return packaged;
12280
12679
  const root = entryDir();
12281
12680
  const candidates = [
12282
- (0, import_node_path35.join)(root, "agents", "cursor-runner.js"),
12283
- (0, import_node_path35.join)(root, "agents", "cursor-runner.cjs"),
12681
+ (0, import_node_path36.join)(root, "agents", "cursor-runner.js"),
12682
+ (0, import_node_path36.join)(root, "agents", "cursor-runner.cjs"),
12284
12683
  // If somehow resolved from package root instead of dist/
12285
- (0, import_node_path35.join)(root, "dist", "agents", "cursor-runner.js"),
12286
- (0, import_node_path35.join)(root, "dist", "agents", "cursor-runner.cjs"),
12684
+ (0, import_node_path36.join)(root, "dist", "agents", "cursor-runner.js"),
12685
+ (0, import_node_path36.join)(root, "dist", "agents", "cursor-runner.cjs"),
12287
12686
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
12288
- (0, import_node_path35.join)(root, "cursor-runner.ts"),
12289
- (0, import_node_path35.join)(root, "src", "agents", "cursor-runner.ts")
12687
+ (0, import_node_path36.join)(root, "cursor-runner.ts"),
12688
+ (0, import_node_path36.join)(root, "src", "agents", "cursor-runner.ts")
12290
12689
  ];
12291
12690
  for (const candidate of candidates) {
12292
- if ((0, import_node_fs33.existsSync)(candidate)) return candidate;
12691
+ if ((0, import_node_fs34.existsSync)(candidate)) return candidate;
12293
12692
  }
12294
12693
  return candidates[0];
12295
12694
  }
12296
- var import_node_fs33, import_node_module4, import_node_path35, import_node_url3, import_meta3, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
12695
+ var import_node_fs34, import_node_module4, import_node_path36, import_node_url3, import_meta3, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
12297
12696
  var init_cursor = __esm({
12298
12697
  "src/agents/cursor.ts"() {
12299
12698
  "use strict";
12300
- import_node_fs33 = require("fs");
12699
+ import_node_fs34 = require("fs");
12301
12700
  import_node_module4 = require("module");
12302
- import_node_path35 = require("path");
12701
+ import_node_path36 = require("path");
12303
12702
  import_node_url3 = require("url");
12304
12703
  init_run();
12305
12704
  init_app_settings();
@@ -12461,7 +12860,7 @@ async function listOpencodeModels() {
12461
12860
  if (opencode === "opencode") {
12462
12861
  const which = await run("which", ["opencode"], { reject: false });
12463
12862
  if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
12464
- } else if (!(0, import_node_fs34.existsSync)(opencode)) {
12863
+ } else if (!(0, import_node_fs35.existsSync)(opencode)) {
12465
12864
  return FALLBACK_OPENCODE_MODELS;
12466
12865
  }
12467
12866
  const listed = await run(opencode, ["models"], { reject: false });
@@ -12491,11 +12890,11 @@ function usageFromOpencode(tokens) {
12491
12890
  cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
12492
12891
  };
12493
12892
  }
12494
- var import_node_fs34, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
12893
+ var import_node_fs35, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
12495
12894
  var init_opencode = __esm({
12496
12895
  "src/agents/opencode.ts"() {
12497
12896
  "use strict";
12498
- import_node_fs34 = require("fs");
12897
+ import_node_fs35 = require("fs");
12499
12898
  init_run();
12500
12899
  init_app_settings();
12501
12900
  init_global_workspace();
@@ -12523,7 +12922,7 @@ var init_opencode = __esm({
12523
12922
  async detect() {
12524
12923
  const opencode = resolveAgentExecutable("opencode");
12525
12924
  if (opencode !== "opencode") {
12526
- if (!(0, import_node_fs34.existsSync)(opencode)) {
12925
+ if (!(0, import_node_fs35.existsSync)(opencode)) {
12527
12926
  return {
12528
12927
  agent: "opencode",
12529
12928
  installed: false,
@@ -13010,13 +13409,13 @@ var init_claude_usage = __esm({
13010
13409
  });
13011
13410
 
13012
13411
  // src/agents/claude-usage-client.ts
13013
- var import_node_fs35, import_node_os13, import_node_path36, CLAUDE_USAGE_ERROR_TTL_MS, CLAUDE_USAGE_STALE_OK_MS;
13412
+ var import_node_fs36, import_node_os13, import_node_path37, CLAUDE_USAGE_ERROR_TTL_MS, CLAUDE_USAGE_STALE_OK_MS;
13014
13413
  var init_claude_usage_client = __esm({
13015
13414
  "src/agents/claude-usage-client.ts"() {
13016
13415
  "use strict";
13017
- import_node_fs35 = require("fs");
13416
+ import_node_fs36 = require("fs");
13018
13417
  import_node_os13 = require("os");
13019
- import_node_path36 = require("path");
13418
+ import_node_path37 = require("path");
13020
13419
  init_run();
13021
13420
  init_fetch();
13022
13421
  init_app_settings();
@@ -13027,11 +13426,11 @@ var init_claude_usage_client = __esm({
13027
13426
  });
13028
13427
 
13029
13428
  // src/agents/install.ts
13030
- var import_node_fs36;
13429
+ var import_node_fs37;
13031
13430
  var init_install = __esm({
13032
13431
  "src/agents/install.ts"() {
13033
13432
  "use strict";
13034
- import_node_fs36 = require("fs");
13433
+ import_node_fs37 = require("fs");
13035
13434
  init_run();
13036
13435
  init_app_settings();
13037
13436
  init_path();
@@ -13085,7 +13484,7 @@ function isAgentHostEnvKey(key) {
13085
13484
  }
13086
13485
  function stripHostToolingPath(pathValue) {
13087
13486
  if (!pathValue?.trim()) return "";
13088
- return pathValue.split(import_node_path37.delimiter).filter((part) => part && !HOST_PATH_NOISE.test(part.replace(/\\/g, "/"))).join(import_node_path37.delimiter);
13487
+ return pathValue.split(import_node_path38.delimiter).filter((part) => part && !HOST_PATH_NOISE.test(part.replace(/\\/g, "/"))).join(import_node_path38.delimiter);
13089
13488
  }
13090
13489
  function sanitizeAgentHostEnv(env, cwd) {
13091
13490
  for (const key of Object.keys(env)) {
@@ -13099,11 +13498,11 @@ function sanitizeAgentHostEnv(env, cwd) {
13099
13498
  }
13100
13499
  return env;
13101
13500
  }
13102
- var import_node_path37, DROP_EXACT, DROP_PREFIXES, HOST_PATH_NOISE;
13501
+ var import_node_path38, DROP_EXACT, DROP_PREFIXES, HOST_PATH_NOISE;
13103
13502
  var init_agent_host_env = __esm({
13104
13503
  "src/hook/agent-host-env.ts"() {
13105
13504
  "use strict";
13106
- import_node_path37 = require("path");
13505
+ import_node_path38 = require("path");
13107
13506
  DROP_EXACT = /* @__PURE__ */ new Set([
13108
13507
  "NODE_PATH",
13109
13508
  "NODE_ENV_ELECTRON_VITE",
@@ -13142,15 +13541,15 @@ var init_agent_host_env = __esm({
13142
13541
 
13143
13542
  // src/hook/worktree-pkg-cache.ts
13144
13543
  function worktreePkgCacheRoot(worktreePath) {
13145
- return (0, import_node_path38.join)(worktreePath, WORKTREE_PKG_CACHE_REL);
13544
+ return (0, import_node_path39.join)(worktreePath, WORKTREE_PKG_CACHE_REL);
13146
13545
  }
13147
13546
  function worktreePkgCacheEnv(worktreePath) {
13148
13547
  const root = worktreePkgCacheRoot(worktreePath);
13149
- const store = (0, import_node_path38.join)(root, "pnpm-store");
13150
- const pnpmCache = (0, import_node_path38.join)(root, "pnpm");
13151
- const npmCache = (0, import_node_path38.join)(root, "npm");
13152
- const nodeGyp = (0, import_node_path38.join)(root, "node-gyp");
13153
- const electron = (0, import_node_path38.join)(root, "electron");
13548
+ const store = (0, import_node_path39.join)(root, "pnpm-store");
13549
+ const pnpmCache = (0, import_node_path39.join)(root, "pnpm");
13550
+ const npmCache = (0, import_node_path39.join)(root, "npm");
13551
+ const nodeGyp = (0, import_node_path39.join)(root, "node-gyp");
13552
+ const electron = (0, import_node_path39.join)(root, "electron");
13154
13553
  return {
13155
13554
  npm_config_store_dir: store,
13156
13555
  PNPM_STORE_DIR: store,
@@ -13172,8 +13571,8 @@ function fillGroup(env, keys, values) {
13172
13571
  }
13173
13572
  }
13174
13573
  function ensureWorktreePkgCacheDirs(worktreePath) {
13175
- if (!(0, import_node_fs37.existsSync)(worktreePath)) return;
13176
- (0, import_node_fs37.mkdirSync)(worktreePkgCacheRoot(worktreePath), { recursive: true });
13574
+ if (!(0, import_node_fs38.existsSync)(worktreePath)) return;
13575
+ (0, import_node_fs38.mkdirSync)(worktreePkgCacheRoot(worktreePath), { recursive: true });
13177
13576
  }
13178
13577
  function applyWorktreePkgCacheEnv(env, worktreePath) {
13179
13578
  const cwd = worktreePath.trim();
@@ -13186,12 +13585,12 @@ function applyWorktreePkgCacheEnv(env, worktreePath) {
13186
13585
  fillGroup(env, ["electron_config_cache"], next);
13187
13586
  ensureWorktreePkgCacheDirs(cwd);
13188
13587
  }
13189
- var import_node_fs37, import_node_path38, WORKTREE_PKG_CACHE_REL;
13588
+ var import_node_fs38, import_node_path39, WORKTREE_PKG_CACHE_REL;
13190
13589
  var init_worktree_pkg_cache = __esm({
13191
13590
  "src/hook/worktree-pkg-cache.ts"() {
13192
13591
  "use strict";
13193
- import_node_fs37 = require("fs");
13194
- import_node_path38 = require("path");
13592
+ import_node_fs38 = require("fs");
13593
+ import_node_path39 = require("path");
13195
13594
  WORKTREE_PKG_CACHE_REL = ".context/.sideboard/pkg-cache";
13196
13595
  }
13197
13596
  });
@@ -14389,21 +14788,21 @@ function shouldRefreshReviewRequestTemplate(content) {
14389
14788
  return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
14390
14789
  }
14391
14790
  function readTextIfPresent(abs) {
14392
- if (!(0, import_node_fs38.existsSync)(abs)) return null;
14791
+ if (!(0, import_node_fs39.existsSync)(abs)) return null;
14393
14792
  try {
14394
- const content = (0, import_node_fs38.readFileSync)(abs, "utf8");
14793
+ const content = (0, import_node_fs39.readFileSync)(abs, "utf8");
14395
14794
  return content.trim() ? content : null;
14396
14795
  } catch {
14397
14796
  return null;
14398
14797
  }
14399
14798
  }
14400
14799
  function readLocalGuidelines(worktreePath) {
14401
- const localAbs = (0, import_node_path39.join)(worktreePath, REVIEW_REQUEST_PATH);
14800
+ const localAbs = (0, import_node_path40.join)(worktreePath, REVIEW_REQUEST_PATH);
14402
14801
  const localContent = readTextIfPresent(localAbs);
14403
14802
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
14404
14803
  return { path: REVIEW_REQUEST_PATH, content: localContent };
14405
14804
  }
14406
- const legacyAbs = (0, import_node_path39.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
14805
+ const legacyAbs = (0, import_node_path40.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
14407
14806
  const legacyContent = readTextIfPresent(legacyAbs);
14408
14807
  if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
14409
14808
  return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
@@ -14427,27 +14826,27 @@ function contextGuidelines(content, source) {
14427
14826
  };
14428
14827
  }
14429
14828
  function writeContextGuidelines(worktreePath, content) {
14430
- const abs = (0, import_node_path39.join)(worktreePath, CONTEXT_REVIEW_PATH);
14431
- (0, import_node_fs38.mkdirSync)((0, import_node_path39.dirname)(abs), { recursive: true });
14829
+ const abs = (0, import_node_path40.join)(worktreePath, CONTEXT_REVIEW_PATH);
14830
+ (0, import_node_fs39.mkdirSync)((0, import_node_path40.dirname)(abs), { recursive: true });
14432
14831
  const body = content.endsWith("\n") ? content : `${content}
14433
14832
  `;
14434
- (0, import_node_fs38.writeFileSync)(abs, body, "utf8");
14833
+ (0, import_node_fs39.writeFileSync)(abs, body, "utf8");
14435
14834
  return body;
14436
14835
  }
14437
14836
  function readSideboardReview(worktreePath, repoPath) {
14438
- const fromWorktree = readTextIfPresent((0, import_node_path39.join)(worktreePath, REPO_REVIEW_PATH));
14837
+ const fromWorktree = readTextIfPresent((0, import_node_path40.join)(worktreePath, REPO_REVIEW_PATH));
14439
14838
  if (fromWorktree) return fromWorktree;
14440
14839
  const repo = repoPath?.replace(/\/+$/, "");
14441
14840
  const wt = worktreePath.replace(/\/+$/, "");
14442
14841
  if (!repo || repo === wt) return null;
14443
- return readTextIfPresent((0, import_node_path39.join)(repo, REPO_REVIEW_PATH));
14842
+ return readTextIfPresent((0, import_node_path40.join)(repo, REPO_REVIEW_PATH));
14444
14843
  }
14445
14844
  function ensureReviewGuidelinesFile(worktreePath, repoPath) {
14446
- const skillContent = readTextIfPresent((0, import_node_path39.join)(worktreePath, REVIEW_SKILL_PATH));
14845
+ const skillContent = readTextIfPresent((0, import_node_path40.join)(worktreePath, REVIEW_SKILL_PATH));
14447
14846
  if (skillContent) {
14448
14847
  return { ...skillGuidelines(skillContent, "skill"), wrote: false };
14449
14848
  }
14450
- const contextContent = readTextIfPresent((0, import_node_path39.join)(worktreePath, CONTEXT_REVIEW_PATH));
14849
+ const contextContent = readTextIfPresent((0, import_node_path40.join)(worktreePath, CONTEXT_REVIEW_PATH));
14451
14850
  if (contextContent && !shouldRefreshReviewRequestTemplate(contextContent)) {
14452
14851
  return { ...contextGuidelines(contextContent, "local"), wrote: false };
14453
14852
  }
@@ -14502,13 +14901,13 @@ async function requestReview(threadRef, send) {
14502
14901
  const started = await send(tab.id, REVIEW_REQUEST_PREFILL);
14503
14902
  return { tab: started, from };
14504
14903
  }
14505
- var import_node_crypto7, import_node_fs38, import_node_path39, REPO_REVIEW_PATH, REPO_REVIEW_NAME, CONTEXT_REVIEW_PATH, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
14904
+ var import_node_crypto7, import_node_fs39, import_node_path40, REPO_REVIEW_PATH, REPO_REVIEW_NAME, CONTEXT_REVIEW_PATH, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
14506
14905
  var init_request_review = __esm({
14507
14906
  "src/review/request-review.ts"() {
14508
14907
  "use strict";
14509
14908
  import_node_crypto7 = require("crypto");
14510
- import_node_fs38 = require("fs");
14511
- import_node_path39 = require("path");
14909
+ import_node_fs39 = require("fs");
14910
+ import_node_path40 = require("path");
14512
14911
  init_global_workspace();
14513
14912
  init_chat_tabs();
14514
14913
  init_thread_store();
@@ -14534,9 +14933,9 @@ function matchSimpleGlob(pattern, name) {
14534
14933
  return new RegExp(`^${escaped}$`).test(name);
14535
14934
  }
14536
14935
  function readWorktreeInclude(repoPath) {
14537
- const path = (0, import_node_path40.join)(repoPath, ".worktreeinclude");
14538
- if (!(0, import_node_fs39.existsSync)(path)) return [];
14539
- return (0, import_node_fs39.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
14936
+ const path = (0, import_node_path41.join)(repoPath, ".worktreeinclude");
14937
+ if (!(0, import_node_fs40.existsSync)(path)) return [];
14938
+ return (0, import_node_fs40.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
14540
14939
  }
14541
14940
  function resolveFilesToCopy(repoPath) {
14542
14941
  const fromInclude = readWorktreeInclude(repoPath);
@@ -14546,10 +14945,10 @@ function resolveFilesToCopy(repoPath) {
14546
14945
  if (settings?.fileIncludeGlobs?.length) {
14547
14946
  const matched = [];
14548
14947
  try {
14549
- for (const entry of (0, import_node_fs39.readdirSync)(repoPath, { withFileTypes: true })) {
14948
+ for (const entry of (0, import_node_fs40.readdirSync)(repoPath, { withFileTypes: true })) {
14550
14949
  if (!entry.isFile()) continue;
14551
14950
  for (const glob of settings.fileIncludeGlobs) {
14552
- if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path40.basename)(glob), entry.name)) {
14951
+ if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path41.basename)(glob), entry.name)) {
14553
14952
  matched.push(entry.name);
14554
14953
  break;
14555
14954
  }
@@ -14561,7 +14960,7 @@ function resolveFilesToCopy(repoPath) {
14561
14960
  }
14562
14961
  const defaults = [];
14563
14962
  try {
14564
- for (const entry of (0, import_node_fs39.readdirSync)(repoPath, { withFileTypes: true })) {
14963
+ for (const entry of (0, import_node_fs40.readdirSync)(repoPath, { withFileTypes: true })) {
14565
14964
  if (entry.isFile() && entry.name.startsWith(".env")) {
14566
14965
  defaults.push(entry.name);
14567
14966
  }
@@ -14575,11 +14974,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
14575
14974
  const patterns = resolveFilesToCopy(repoPath);
14576
14975
  const copied = [];
14577
14976
  for (const rel of patterns) {
14578
- const src = (0, import_node_path40.join)(repoPath, rel);
14579
- if (!(0, import_node_fs39.existsSync)(src)) continue;
14580
- const dest = (0, import_node_path40.join)(worktreePath, rel);
14581
- (0, import_node_fs39.mkdirSync)((0, import_node_path40.dirname)(dest), { recursive: true });
14582
- (0, import_node_fs39.copyFileSync)(src, dest);
14977
+ const src = (0, import_node_path41.join)(repoPath, rel);
14978
+ if (!(0, import_node_fs40.existsSync)(src)) continue;
14979
+ const dest = (0, import_node_path41.join)(worktreePath, rel);
14980
+ (0, import_node_fs40.mkdirSync)((0, import_node_path41.dirname)(dest), { recursive: true });
14981
+ (0, import_node_fs40.copyFileSync)(src, dest);
14583
14982
  copied.push(rel);
14584
14983
  }
14585
14984
  return copied;
@@ -14614,7 +15013,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
14614
15013
  const env = stripNestedElectronEnv({
14615
15014
  ...baseEnv ?? process.env
14616
15015
  });
14617
- const name = opts.workspaceName ?? (0, import_node_path40.basename)(opts.worktreePath);
15016
+ const name = opts.workspaceName ?? (0, import_node_path41.basename)(opts.worktreePath);
14618
15017
  const ports = opts.ports ?? [];
14619
15018
  const primary = ports[0];
14620
15019
  env.SIDEBOARD_WORKSPACE_NAME = name;
@@ -14938,14 +15337,14 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
14938
15337
  throw err;
14939
15338
  }
14940
15339
  }
14941
- var import_node_fs39, import_node_child_process4, import_node_net, import_node_path40, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
15340
+ var import_node_fs40, import_node_child_process4, import_node_net, import_node_path41, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
14942
15341
  var init_conductor = __esm({
14943
15342
  "src/hook/conductor.ts"() {
14944
15343
  "use strict";
14945
- import_node_fs39 = require("fs");
15344
+ import_node_fs40 = require("fs");
14946
15345
  import_node_child_process4 = require("child_process");
14947
15346
  import_node_net = require("net");
14948
- import_node_path40 = require("path");
15347
+ import_node_path41 = require("path");
14949
15348
  import_execa4 = require("execa");
14950
15349
  import_node_readline3 = require("readline");
14951
15350
  init_settings();
@@ -14995,7 +15394,7 @@ function materialize(mem) {
14995
15394
  };
14996
15395
  }
14997
15396
  function setupLogPath(threadId) {
14998
- return (0, import_node_path41.join)(threadsDir(), `${threadId}.setup.log.json`);
15397
+ return (0, import_node_path42.join)(threadsDir(), `${threadId}.setup.log.json`);
14999
15398
  }
15000
15399
  function setupLogKeyForWorktree(worktreePath) {
15001
15400
  const norm = normalizeWorktreePath(worktreePath);
@@ -15013,7 +15412,7 @@ function persistNow(threadId) {
15013
15412
  const mem = memory.get(threadId);
15014
15413
  if (!mem) return;
15015
15414
  try {
15016
- (0, import_node_fs40.writeFileSync)(
15415
+ (0, import_node_fs41.writeFileSync)(
15017
15416
  setupLogPath(threadId),
15018
15417
  `${JSON.stringify(materialize(mem))}
15019
15418
  `,
@@ -15034,9 +15433,9 @@ function schedulePersist(threadId) {
15034
15433
  }
15035
15434
  function loadFromDisk(threadId) {
15036
15435
  const path = setupLogPath(threadId);
15037
- if (!(0, import_node_fs40.existsSync)(path)) return null;
15436
+ if (!(0, import_node_fs41.existsSync)(path)) return null;
15038
15437
  try {
15039
- const raw = JSON.parse((0, import_node_fs40.readFileSync)(path, "utf8"));
15438
+ const raw = JSON.parse((0, import_node_fs41.readFileSync)(path, "utf8"));
15040
15439
  return {
15041
15440
  output: typeof raw.output === "string" ? raw.output : "",
15042
15441
  running: Boolean(raw.running),
@@ -15092,13 +15491,13 @@ function finishSetupLog(threadId, exitCode, source) {
15092
15491
  persistNow(threadId);
15093
15492
  return materialize(mem);
15094
15493
  }
15095
- var import_node_crypto8, import_node_fs40, import_node_path41, EMPTY, MAX_SETUP_LOG_CHARS, memory, persistTimers, PERSIST_DEBOUNCE_MS;
15494
+ var import_node_crypto8, import_node_fs41, import_node_path42, EMPTY, MAX_SETUP_LOG_CHARS, memory, persistTimers, PERSIST_DEBOUNCE_MS;
15096
15495
  var init_setup_log = __esm({
15097
15496
  "src/store/setup-log.ts"() {
15098
15497
  "use strict";
15099
15498
  import_node_crypto8 = require("crypto");
15100
- import_node_fs40 = require("fs");
15101
- import_node_path41 = require("path");
15499
+ import_node_fs41 = require("fs");
15500
+ import_node_path42 = require("path");
15102
15501
  init_worktree_labels();
15103
15502
  init_paths();
15104
15503
  EMPTY = {
@@ -15125,9 +15524,9 @@ async function findOrphanWorktrees(repoPaths) {
15125
15524
  repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
15126
15525
  );
15127
15526
  const homeRoot = sideboardWorkspacesDir();
15128
- if ((0, import_node_fs41.existsSync)(homeRoot)) {
15527
+ if ((0, import_node_fs42.existsSync)(homeRoot)) {
15129
15528
  try {
15130
- for (const entry of (0, import_node_fs41.readdirSync)(homeRoot, { withFileTypes: true })) {
15529
+ for (const entry of (0, import_node_fs42.readdirSync)(homeRoot, { withFileTypes: true })) {
15131
15530
  if (!entry.isDirectory()) continue;
15132
15531
  void entry;
15133
15532
  }
@@ -15137,7 +15536,7 @@ async function findOrphanWorktrees(repoPaths) {
15137
15536
  const orphans = [];
15138
15537
  const seen = /* @__PURE__ */ new Set();
15139
15538
  for (const repoPath of repos) {
15140
- if (!repoPath || !(0, import_node_fs41.existsSync)(repoPath)) continue;
15539
+ if (!repoPath || !(0, import_node_fs42.existsSync)(repoPath)) continue;
15141
15540
  try {
15142
15541
  const wts = await listWorktrees(repoPath);
15143
15542
  for (const wt of wts) {
@@ -15148,7 +15547,7 @@ async function findOrphanWorktrees(repoPaths) {
15148
15547
  seen.add(path);
15149
15548
  let mtimeMs = 0;
15150
15549
  try {
15151
- mtimeMs = (0, import_node_fs41.statSync)(path).mtimeMs;
15550
+ mtimeMs = (0, import_node_fs42.statSync)(path).mtimeMs;
15152
15551
  } catch {
15153
15552
  mtimeMs = 0;
15154
15553
  }
@@ -15158,16 +15557,16 @@ async function findOrphanWorktrees(repoPaths) {
15158
15557
  }
15159
15558
  try {
15160
15559
  const root = worktreesRoot(repoPath);
15161
- if ((0, import_node_fs41.existsSync)(root)) {
15162
- for (const entry of (0, import_node_fs41.readdirSync)(root, { withFileTypes: true })) {
15560
+ if ((0, import_node_fs42.existsSync)(root)) {
15561
+ for (const entry of (0, import_node_fs42.readdirSync)(root, { withFileTypes: true })) {
15163
15562
  if (!entry.isDirectory()) continue;
15164
- const path = (0, import_node_path42.join)(root, entry.name).replace(/\/$/, "");
15563
+ const path = (0, import_node_path43.join)(root, entry.name).replace(/\/$/, "");
15165
15564
  if (known.has(path) || seen.has(path)) continue;
15166
- if (!(0, import_node_fs41.existsSync)((0, import_node_path42.join)(path, ".git"))) continue;
15565
+ if (!(0, import_node_fs42.existsSync)((0, import_node_path43.join)(path, ".git"))) continue;
15167
15566
  seen.add(path);
15168
15567
  let mtimeMs = 0;
15169
15568
  try {
15170
- mtimeMs = (0, import_node_fs41.statSync)(path).mtimeMs;
15569
+ mtimeMs = (0, import_node_fs42.statSync)(path).mtimeMs;
15171
15570
  } catch {
15172
15571
  mtimeMs = Date.now();
15173
15572
  }
@@ -15219,12 +15618,12 @@ function shouldRunWorktreeCleanup(settings = loadAppSettings()) {
15219
15618
  const elapsed = Date.now() - Date.parse(last);
15220
15619
  return elapsed >= intervalHours * 36e5;
15221
15620
  }
15222
- var import_node_fs41, import_node_path42;
15621
+ var import_node_fs42, import_node_path43;
15223
15622
  var init_orphan_cleanup = __esm({
15224
15623
  "src/git/orphan-cleanup.ts"() {
15225
15624
  "use strict";
15226
- import_node_fs41 = require("fs");
15227
- import_node_path42 = require("path");
15625
+ import_node_fs42 = require("fs");
15626
+ import_node_path43 = require("path");
15228
15627
  init_worktree();
15229
15628
  init_thread_store();
15230
15629
  init_paths();
@@ -15399,12 +15798,12 @@ async function cloneRepoIntoSideboard(opts) {
15399
15798
  if (!url) throw new Error("Clone URL is required");
15400
15799
  let name = opts.name?.trim();
15401
15800
  if (!name) {
15402
- const leaf = (0, import_node_path43.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
15801
+ const leaf = (0, import_node_path44.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
15403
15802
  name = leaf || "repo";
15404
15803
  }
15405
15804
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
15406
- const dest = (0, import_node_path43.join)(sideboardReposDir(), name);
15407
- if ((0, import_node_fs42.existsSync)(dest)) {
15805
+ const dest = (0, import_node_path44.join)(sideboardReposDir(), name);
15806
+ if ((0, import_node_fs43.existsSync)(dest)) {
15408
15807
  const repoPath2 = await resolveRepoRoot(dest);
15409
15808
  const workspace2 = await ensureWorkspace(repoPath2);
15410
15809
  return { repoPath: repoPath2, workspace: workspace2 };
@@ -15419,12 +15818,12 @@ async function cloneRepoIntoSideboard(opts) {
15419
15818
  const workspace = await ensureWorkspace(repoPath);
15420
15819
  return { repoPath, workspace };
15421
15820
  }
15422
- var import_node_fs42, import_node_path43, import_execa6;
15821
+ var import_node_fs43, import_node_path44, import_execa6;
15423
15822
  var init_clone_repo = __esm({
15424
15823
  "src/git/clone-repo.ts"() {
15425
15824
  "use strict";
15426
- import_node_fs42 = require("fs");
15427
- import_node_path43 = require("path");
15825
+ import_node_fs43 = require("fs");
15826
+ import_node_path44 = require("path");
15428
15827
  import_execa6 = require("execa");
15429
15828
  init_paths();
15430
15829
  init_workspaces2();
@@ -15444,11 +15843,11 @@ var init_thread = __esm({
15444
15843
 
15445
15844
  // src/store/desktop-host.ts
15446
15845
  function desktopHostPidPath() {
15447
- return (0, import_node_path44.join)(appDataDir(), "desktop-host.pid");
15846
+ return (0, import_node_path45.join)(appDataDir(), "desktop-host.pid");
15448
15847
  }
15449
15848
  function readDesktopHostPid() {
15450
15849
  try {
15451
- const pid = Number.parseInt((0, import_node_fs43.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
15850
+ const pid = Number.parseInt((0, import_node_fs44.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
15452
15851
  if (!Number.isFinite(pid) || pid <= 0) return null;
15453
15852
  return pid;
15454
15853
  } catch {
@@ -15474,12 +15873,12 @@ function thisProcessShouldDrainAgentQueues() {
15474
15873
  if (isThisProcessDesktopHost()) return true;
15475
15874
  return !isDesktopHostAlive();
15476
15875
  }
15477
- var import_node_fs43, import_node_path44;
15876
+ var import_node_fs44, import_node_path45;
15478
15877
  var init_desktop_host = __esm({
15479
15878
  "src/store/desktop-host.ts"() {
15480
15879
  "use strict";
15481
- import_node_fs43 = require("fs");
15482
- import_node_path44 = require("path");
15880
+ import_node_fs44 = require("fs");
15881
+ import_node_path45 = require("path");
15483
15882
  init_paths();
15484
15883
  }
15485
15884
  });
@@ -15597,24 +15996,24 @@ function jobTreeAlive(pid) {
15597
15996
  return jobAlive(pid) || processGroupAlive(pid);
15598
15997
  }
15599
15998
  function readIntFile(file) {
15600
- if (!(0, import_node_fs44.existsSync)(file)) return null;
15601
- const n = Number.parseInt((0, import_node_fs44.readFileSync)(file, "utf8").trim(), 10);
15999
+ if (!(0, import_node_fs45.existsSync)(file)) return null;
16000
+ const n = Number.parseInt((0, import_node_fs45.readFileSync)(file, "utf8").trim(), 10);
15602
16001
  return Number.isInteger(n) ? n : null;
15603
16002
  }
15604
16003
  function jobDir(root, id, legacy = false) {
15605
- return (0, import_node_path45.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
16004
+ return (0, import_node_path46.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
15606
16005
  }
15607
16006
  function resolveJobDir(root, id) {
15608
16007
  const modern = jobDir(root, id, false);
15609
- if ((0, import_node_fs44.existsSync)(modern)) return modern;
16008
+ if ((0, import_node_fs45.existsSync)(modern)) return modern;
15610
16009
  const legacy = jobDir(root, id, true);
15611
- if ((0, import_node_fs44.existsSync)(legacy)) return legacy;
16010
+ if ((0, import_node_fs45.existsSync)(legacy)) return legacy;
15612
16011
  return modern;
15613
16012
  }
15614
16013
  function listJobIdsIn(root, rel) {
15615
- const dir = (0, import_node_path45.join)(root, rel);
15616
- if (!(0, import_node_fs44.existsSync)(dir)) return [];
15617
- return (0, import_node_fs44.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
16014
+ const dir = (0, import_node_path46.join)(root, rel);
16015
+ if (!(0, import_node_fs45.existsSync)(dir)) return [];
16016
+ return (0, import_node_fs45.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
15618
16017
  }
15619
16018
  function listRunningDetachedJobs(worktreePath) {
15620
16019
  const root = worktreePath.trim();
@@ -15626,7 +16025,7 @@ function listRunningDetachedJobs(worktreePath) {
15626
16025
  const running = [];
15627
16026
  for (const id of ids) {
15628
16027
  const dir = resolveJobDir(root, id);
15629
- const pid = readIntFile((0, import_node_path45.join)(dir, "pid"));
16028
+ const pid = readIntFile((0, import_node_path46.join)(dir, "pid"));
15630
16029
  if (jobTreeAlive(pid)) running.push(id);
15631
16030
  }
15632
16031
  return running.sort();
@@ -15709,8 +16108,8 @@ function planJobContinue(opts) {
15709
16108
  return { action: "none" };
15710
16109
  }
15711
16110
  function tailProgress(logFile, maxLines = 12) {
15712
- if (!(0, import_node_fs44.existsSync)(logFile)) return "(no log yet)";
15713
- const lines = (0, import_node_fs44.readFileSync)(logFile, "utf8").split("\n");
16111
+ if (!(0, import_node_fs45.existsSync)(logFile)) return "(no log yet)";
16112
+ const lines = (0, import_node_fs45.readFileSync)(logFile, "utf8").split("\n");
15714
16113
  return lines.slice(-maxLines).join("\n");
15715
16114
  }
15716
16115
  function lastProgressLine(progress) {
@@ -15718,8 +16117,8 @@ function lastProgressLine(progress) {
15718
16117
  return last ? last.slice(0, 72) : void 0;
15719
16118
  }
15720
16119
  function readLogLines(file) {
15721
- if (!(0, import_node_fs44.existsSync)(file)) return [];
15722
- const lines = (0, import_node_fs44.readFileSync)(file, "utf8").split("\n");
16120
+ if (!(0, import_node_fs45.existsSync)(file)) return [];
16121
+ const lines = (0, import_node_fs45.readFileSync)(file, "utf8").split("\n");
15723
16122
  if (lines.length && lines[lines.length - 1] === "") lines.pop();
15724
16123
  return lines;
15725
16124
  }
@@ -15730,15 +16129,15 @@ function takeDelta(logFile, cursorFile) {
15730
16129
  return { delta: capJobLogDelta(lines.slice(start).join("\n")), nextCursor: lines.length };
15731
16130
  }
15732
16131
  function snapshotJob(dir) {
15733
- const pid = readIntFile((0, import_node_path45.join)(dir, "pid"));
16132
+ const pid = readIntFile((0, import_node_path46.join)(dir, "pid"));
15734
16133
  const running = jobTreeAlive(pid);
15735
16134
  return {
15736
16135
  pid,
15737
16136
  running,
15738
- exitCode: readIntFile((0, import_node_path45.join)(dir, "exit")),
15739
- log: (0, import_node_path45.join)(dir, "log"),
15740
- cursor: (0, import_node_path45.join)(dir, "present.cursor"),
15741
- progress: tailProgress((0, import_node_path45.join)(dir, "log"))
16137
+ exitCode: readIntFile((0, import_node_path46.join)(dir, "exit")),
16138
+ log: (0, import_node_path46.join)(dir, "log"),
16139
+ cursor: (0, import_node_path46.join)(dir, "present.cursor"),
16140
+ progress: tailProgress((0, import_node_path46.join)(dir, "log"))
15742
16141
  };
15743
16142
  }
15744
16143
  function toResult(id, snap, extra) {
@@ -15747,8 +16146,8 @@ function toResult(id, snap, extra) {
15747
16146
  const stillRunning = snap.running && !ok;
15748
16147
  const { delta, nextCursor } = takeDelta(snap.log, snap.cursor);
15749
16148
  try {
15750
- (0, import_node_fs44.mkdirSync)((0, import_node_path45.dirname)(snap.cursor), { recursive: true });
15751
- (0, import_node_fs44.writeFileSync)(snap.cursor, `${nextCursor}
16149
+ (0, import_node_fs45.mkdirSync)((0, import_node_path46.dirname)(snap.cursor), { recursive: true });
16150
+ (0, import_node_fs45.writeFileSync)(snap.cursor, `${nextCursor}
15752
16151
  `);
15753
16152
  } catch {
15754
16153
  }
@@ -15777,7 +16176,7 @@ async function waitForDetachedJob(cwd, id, opts) {
15777
16176
  const dir = resolveJobDir(root, jobId);
15778
16177
  const timeoutMs = mcpWaitForJobTimeoutMs(opts?.timeoutMs);
15779
16178
  const sleep = opts?.sleep ?? sleepMs;
15780
- if (!(0, import_node_fs44.existsSync)(dir)) {
16179
+ if (!(0, import_node_fs45.existsSync)(dir)) {
15781
16180
  return {
15782
16181
  stillRunning: false,
15783
16182
  ok: false,
@@ -15823,10 +16222,10 @@ function killProcessTree(pid, signal) {
15823
16222
  }
15824
16223
  function appendJobLog(logFile, line) {
15825
16224
  try {
15826
- (0, import_node_fs44.mkdirSync)((0, import_node_path45.dirname)(logFile), { recursive: true });
16225
+ (0, import_node_fs45.mkdirSync)((0, import_node_path46.dirname)(logFile), { recursive: true });
15827
16226
  const body = line.endsWith("\n") ? line : `${line}
15828
16227
  `;
15829
- (0, import_node_fs44.appendFileSync)(logFile, body);
16228
+ (0, import_node_fs45.appendFileSync)(logFile, body);
15830
16229
  } catch {
15831
16230
  }
15832
16231
  }
@@ -15836,7 +16235,7 @@ async function stopDetachedJob(cwd, id, opts) {
15836
16235
  const dir = resolveJobDir(root, jobId);
15837
16236
  const sleep = opts?.sleep ?? sleepMs;
15838
16237
  const why = opts?.reason?.trim() ?? "";
15839
- if (!(0, import_node_fs44.existsSync)(dir)) {
16238
+ if (!(0, import_node_fs45.existsSync)(dir)) {
15840
16239
  return {
15841
16240
  stillRunning: false,
15842
16241
  ok: false,
@@ -15872,10 +16271,10 @@ async function stopDetachedJob(cwd, id, opts) {
15872
16271
  killProcessTree(targetPid, "SIGKILL");
15873
16272
  await sleep(100);
15874
16273
  }
15875
- const exitFile = (0, import_node_path45.join)(dir, "exit");
15876
- if (!(0, import_node_fs44.existsSync)(exitFile)) {
16274
+ const exitFile = (0, import_node_path46.join)(dir, "exit");
16275
+ if (!(0, import_node_fs45.existsSync)(exitFile)) {
15877
16276
  try {
15878
- (0, import_node_fs44.writeFileSync)(exitFile, "1\n");
16277
+ (0, import_node_fs45.writeFileSync)(exitFile, "1\n");
15879
16278
  } catch {
15880
16279
  }
15881
16280
  }
@@ -15895,12 +16294,12 @@ async function stopDetachedJob(cwd, id, opts) {
15895
16294
  hint: stopped ? MCP_STOP_JOB_HINT : MCP_WAIT_JOB_STILL_RUNNING_HINT
15896
16295
  };
15897
16296
  }
15898
- var import_node_fs44, import_node_path45, MAX_JOB_CONTINUES, MAX_JOB_DELTA_LINES, MAX_JOB_DELTA_CHARS, DEFERRED_DONE_MAX_CHARS, GH_WATCH_REFRESH, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
16297
+ var import_node_fs45, import_node_path46, MAX_JOB_CONTINUES, MAX_JOB_DELTA_LINES, MAX_JOB_DELTA_CHARS, DEFERRED_DONE_MAX_CHARS, GH_WATCH_REFRESH, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
15899
16298
  var init_wait_for_job = __esm({
15900
16299
  "src/mcp/wait-for-job.ts"() {
15901
16300
  "use strict";
15902
- import_node_fs44 = require("fs");
15903
- import_node_path45 = require("path");
16301
+ import_node_fs45 = require("fs");
16302
+ import_node_path46 = require("path");
15904
16303
  init_workspace_scratch();
15905
16304
  init_wait_for_turn();
15906
16305
  MAX_JOB_CONTINUES = 8;
@@ -17935,7 +18334,7 @@ function reuseLiveThread(input, repoPath, match) {
17935
18334
  }
17936
18335
  async function createThread(input, _onSetupLine) {
17937
18336
  const repoPath = await resolveRepoRoot(input.repoPath);
17938
- if (!(0, import_node_fs45.existsSync)(repoPath)) {
18337
+ if (!(0, import_node_fs46.existsSync)(repoPath)) {
17939
18338
  throw new Error(`Repo not found: ${repoPath}`);
17940
18339
  }
17941
18340
  const reused = reuseLiveThread(input, repoPath, {
@@ -18111,11 +18510,11 @@ async function createThread(input, _onSetupLine) {
18111
18510
  await ensureWorkspace(repoPath);
18112
18511
  return readThread(thread.id) ?? thread;
18113
18512
  }
18114
- var import_node_fs45;
18513
+ var import_node_fs46;
18115
18514
  var init_create = __esm({
18116
18515
  "src/threads/create.ts"() {
18117
18516
  "use strict";
18118
- import_node_fs45 = require("fs");
18517
+ import_node_fs46 = require("fs");
18119
18518
  init_detect();
18120
18519
  init_worktree();
18121
18520
  init_home_board();
@@ -18267,20 +18666,20 @@ function writeTurnLive(threadId, progress) {
18267
18666
  const path = threadLivePath(threadId);
18268
18667
  const tmp = `${path}.${process.pid}.tmp`;
18269
18668
  try {
18270
- (0, import_node_fs46.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
18271
- (0, import_node_fs46.renameSync)(tmp, path);
18669
+ (0, import_node_fs47.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
18670
+ (0, import_node_fs47.renameSync)(tmp, path);
18272
18671
  } catch {
18273
18672
  try {
18274
- (0, import_node_fs46.unlinkSync)(tmp);
18673
+ (0, import_node_fs47.unlinkSync)(tmp);
18275
18674
  } catch {
18276
18675
  }
18277
18676
  }
18278
18677
  }
18279
18678
  function readTurnLive(threadId) {
18280
18679
  const path = threadLivePath(threadId);
18281
- if (!(0, import_node_fs46.existsSync)(path)) return null;
18680
+ if (!(0, import_node_fs47.existsSync)(path)) return null;
18282
18681
  try {
18283
- const raw = JSON.parse((0, import_node_fs46.readFileSync)(path, "utf8"));
18682
+ const raw = JSON.parse((0, import_node_fs47.readFileSync)(path, "utf8"));
18284
18683
  if (!raw || typeof raw.summary !== "string") return null;
18285
18684
  return raw;
18286
18685
  } catch {
@@ -18292,17 +18691,17 @@ function clearTurnLive(threadId) {
18292
18691
  if (buf?.timer) clearTimeout(buf.timer);
18293
18692
  buffers.delete(threadId);
18294
18693
  const path = threadLivePath(threadId);
18295
- if (!(0, import_node_fs46.existsSync)(path)) return;
18694
+ if (!(0, import_node_fs47.existsSync)(path)) return;
18296
18695
  try {
18297
- (0, import_node_fs46.unlinkSync)(path);
18696
+ (0, import_node_fs47.unlinkSync)(path);
18298
18697
  } catch {
18299
18698
  }
18300
18699
  }
18301
- var import_node_fs46, buffers, FLUSH_MS, MAX_PARTS;
18700
+ var import_node_fs47, buffers, FLUSH_MS, MAX_PARTS;
18302
18701
  var init_turn_live = __esm({
18303
18702
  "src/store/turn-live.ts"() {
18304
18703
  "use strict";
18305
- import_node_fs46 = require("fs");
18704
+ import_node_fs47 = require("fs");
18306
18705
  init_message_parts();
18307
18706
  init_paths();
18308
18707
  buffers = /* @__PURE__ */ new Map();
@@ -18543,7 +18942,7 @@ var init_quota_failover = __esm({
18543
18942
  // src/threads/adopt.ts
18544
18943
  function thisModuleFile2() {
18545
18944
  const cjsFile = typeof __filename !== "undefined" ? __filename : "";
18546
- return cjsFile || process.argv[1] || (0, import_node_path46.join)(process.cwd(), "package.json");
18945
+ return cjsFile || process.argv[1] || (0, import_node_path47.join)(process.cwd(), "package.json");
18547
18946
  }
18548
18947
  function openReadonlySqlite(file) {
18549
18948
  const req = (0, import_node_module5.createRequire)(thisModuleFile2());
@@ -18561,21 +18960,21 @@ function mapAgentType(raw) {
18561
18960
  return null;
18562
18961
  }
18563
18962
  function resolveConductorCursorAgentId(workspacePath) {
18564
- if (!workspacePath || !(0, import_node_fs47.existsSync)(CURSOR_SDK_STORE)) return null;
18963
+ if (!workspacePath || !(0, import_node_fs48.existsSync)(CURSOR_SDK_STORE)) return null;
18565
18964
  const normalized = workspacePath.replace(/\/$/, "");
18566
18965
  let best = null;
18567
18966
  let hashes;
18568
18967
  try {
18569
- hashes = (0, import_node_fs47.readdirSync)(CURSOR_SDK_STORE);
18968
+ hashes = (0, import_node_fs48.readdirSync)(CURSOR_SDK_STORE);
18570
18969
  } catch {
18571
18970
  return null;
18572
18971
  }
18573
18972
  for (const hash of hashes) {
18574
- const agentsFile = (0, import_node_path46.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
18575
- if (!(0, import_node_fs47.existsSync)(agentsFile)) continue;
18973
+ const agentsFile = (0, import_node_path47.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
18974
+ if (!(0, import_node_fs48.existsSync)(agentsFile)) continue;
18576
18975
  let text7;
18577
18976
  try {
18578
- text7 = (0, import_node_fs47.readFileSync)(agentsFile, "utf8");
18977
+ text7 = (0, import_node_fs48.readFileSync)(agentsFile, "utf8");
18579
18978
  } catch {
18580
18979
  continue;
18581
18980
  }
@@ -18599,7 +18998,7 @@ function resolveConductorCursorAgentId(workspacePath) {
18599
18998
  return best?.agentId ?? null;
18600
18999
  }
18601
19000
  async function adoptThread(input) {
18602
- if (!(0, import_node_fs47.existsSync)(input.worktreePath)) {
19001
+ if (!(0, import_node_fs48.existsSync)(input.worktreePath)) {
18603
19002
  throw new Error(`Worktree not found: ${input.worktreePath}`);
18604
19003
  }
18605
19004
  const repoPath = await resolveRepoRoot(input.worktreePath);
@@ -18625,18 +19024,18 @@ async function adoptThread(input) {
18625
19024
  return thread;
18626
19025
  }
18627
19026
  function listConductorWorkspaces() {
18628
- if (!(0, import_node_fs47.existsSync)(CONDUCTOR_DB)) {
19027
+ if (!(0, import_node_fs48.existsSync)(CONDUCTOR_DB)) {
18629
19028
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
18630
19029
  }
18631
- const tmp = (0, import_node_fs47.mkdtempSync)((0, import_node_path46.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
18632
- const snapshot = (0, import_node_path46.join)(tmp, "conductor.db");
19030
+ const tmp = (0, import_node_fs48.mkdtempSync)((0, import_node_path47.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
19031
+ const snapshot = (0, import_node_path47.join)(tmp, "conductor.db");
18633
19032
  try {
18634
- (0, import_node_fs47.copyFileSync)(CONDUCTOR_DB, snapshot);
19033
+ (0, import_node_fs48.copyFileSync)(CONDUCTOR_DB, snapshot);
18635
19034
  for (const suffix of ["-wal", "-shm"]) {
18636
19035
  const src = `${CONDUCTOR_DB}${suffix}`;
18637
- if ((0, import_node_fs47.existsSync)(src)) {
19036
+ if ((0, import_node_fs48.existsSync)(src)) {
18638
19037
  try {
18639
- (0, import_node_fs47.copyFileSync)(src, `${snapshot}${suffix}`);
19038
+ (0, import_node_fs48.copyFileSync)(src, `${snapshot}${suffix}`);
18640
19039
  } catch {
18641
19040
  }
18642
19041
  }
@@ -18712,22 +19111,22 @@ function listConductorWorkspaces() {
18712
19111
  db.close();
18713
19112
  }
18714
19113
  } finally {
18715
- (0, import_node_fs47.rmSync)(tmp, { recursive: true, force: true });
19114
+ (0, import_node_fs48.rmSync)(tmp, { recursive: true, force: true });
18716
19115
  }
18717
19116
  }
18718
19117
  function importConductorWorkspace(workspaceId) {
18719
- if (!(0, import_node_fs47.existsSync)(CONDUCTOR_DB)) {
19118
+ if (!(0, import_node_fs48.existsSync)(CONDUCTOR_DB)) {
18720
19119
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
18721
19120
  }
18722
- const tmp = (0, import_node_fs47.mkdtempSync)((0, import_node_path46.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
18723
- const snapshot = (0, import_node_path46.join)(tmp, "conductor.db");
19121
+ const tmp = (0, import_node_fs48.mkdtempSync)((0, import_node_path47.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
19122
+ const snapshot = (0, import_node_path47.join)(tmp, "conductor.db");
18724
19123
  try {
18725
- (0, import_node_fs47.copyFileSync)(CONDUCTOR_DB, snapshot);
19124
+ (0, import_node_fs48.copyFileSync)(CONDUCTOR_DB, snapshot);
18726
19125
  for (const suffix of ["-wal", "-shm"]) {
18727
19126
  const src = `${CONDUCTOR_DB}${suffix}`;
18728
- if ((0, import_node_fs47.existsSync)(src)) {
19127
+ if ((0, import_node_fs48.existsSync)(src)) {
18729
19128
  try {
18730
- (0, import_node_fs47.copyFileSync)(src, `${snapshot}${suffix}`);
19129
+ (0, import_node_fs48.copyFileSync)(src, `${snapshot}${suffix}`);
18731
19130
  } catch {
18732
19131
  }
18733
19132
  }
@@ -18745,7 +19144,7 @@ function importConductorWorkspace(workspaceId) {
18745
19144
  ).get(workspaceId);
18746
19145
  if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
18747
19146
  const worktreePath = String(row.workspacePath);
18748
- if (!(0, import_node_fs47.existsSync)(worktreePath)) {
19147
+ if (!(0, import_node_fs48.existsSync)(worktreePath)) {
18749
19148
  throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
18750
19149
  }
18751
19150
  let sessionId = null;
@@ -18808,31 +19207,31 @@ function importConductorWorkspace(workspaceId) {
18808
19207
  db.close();
18809
19208
  }
18810
19209
  } finally {
18811
- (0, import_node_fs47.rmSync)(tmp, { recursive: true, force: true });
19210
+ (0, import_node_fs48.rmSync)(tmp, { recursive: true, force: true });
18812
19211
  }
18813
19212
  }
18814
19213
  async function importConductorWorkspaceAsync(workspaceId) {
18815
19214
  return importConductorWorkspace(workspaceId);
18816
19215
  }
18817
- var import_node_child_process5, import_node_fs47, import_node_os14, import_node_path46, import_node_module5, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
19216
+ var import_node_child_process5, import_node_fs48, import_node_os14, import_node_path47, import_node_module5, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
18818
19217
  var init_adopt = __esm({
18819
19218
  "src/threads/adopt.ts"() {
18820
19219
  "use strict";
18821
19220
  import_node_child_process5 = require("child_process");
18822
- import_node_fs47 = require("fs");
19221
+ import_node_fs48 = require("fs");
18823
19222
  import_node_os14 = require("os");
18824
- import_node_path46 = require("path");
19223
+ import_node_path47 = require("path");
18825
19224
  import_node_module5 = require("module");
18826
19225
  init_worktree();
18827
19226
  init_thread_store();
18828
- CONDUCTOR_APP_SUPPORT = (0, import_node_path46.join)(
19227
+ CONDUCTOR_APP_SUPPORT = (0, import_node_path47.join)(
18829
19228
  process.env.HOME ?? "",
18830
19229
  "Library",
18831
19230
  "Application Support",
18832
19231
  "com.conductor.app"
18833
19232
  );
18834
- CONDUCTOR_DB = (0, import_node_path46.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
18835
- CURSOR_SDK_STORE = (0, import_node_path46.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
19233
+ CONDUCTOR_DB = (0, import_node_path47.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
19234
+ CURSOR_SDK_STORE = (0, import_node_path47.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
18836
19235
  }
18837
19236
  });
18838
19237
 
@@ -18899,7 +19298,7 @@ async function openStackLayer(input, _onSetupLine) {
18899
19298
  let createdWorktree = false;
18900
19299
  const trees = await listWorktrees(repoPath);
18901
19300
  const checkedOut = trees.find((w) => w.branch === branchName);
18902
- if (checkedOut?.path && (0, import_node_fs48.existsSync)(checkedOut.path)) {
19301
+ if (checkedOut?.path && (0, import_node_fs49.existsSync)(checkedOut.path)) {
18903
19302
  if (input.reuseExistingWorktree !== false) {
18904
19303
  worktreePath = checkedOut.path;
18905
19304
  } else {
@@ -19041,7 +19440,7 @@ async function initStackFromThread(input, onSetupLine) {
19041
19440
  async function createPrStack(input, onSetupLine) {
19042
19441
  await requireAgent(input.agent);
19043
19442
  const repoPath = await resolveRepoRoot(input.repoPath);
19044
- if (!(0, import_node_fs48.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
19443
+ if (!(0, import_node_fs49.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
19045
19444
  if (!input.branches.length) throw new Error("At least one branch name required");
19046
19445
  const status = await detectGhStack(repoPath);
19047
19446
  if (!status.available) throw new Error(status.reason);
@@ -19108,7 +19507,7 @@ async function createPrStack(input, onSetupLine) {
19108
19507
  }
19109
19508
  }
19110
19509
  const claimed = new Set(threads.map((t) => t.worktreePath));
19111
- if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs48.existsSync)(bootstrap.worktreePath)) {
19510
+ if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs49.existsSync)(bootstrap.worktreePath)) {
19112
19511
  try {
19113
19512
  await removeWorktree(repoPath, bootstrap.worktreePath, {
19114
19513
  deleteBranch: bootstrap.branchName
@@ -19118,11 +19517,11 @@ async function createPrStack(input, onSetupLine) {
19118
19517
  }
19119
19518
  return { stack, threads, createdThreadIds };
19120
19519
  }
19121
- var import_node_fs48;
19520
+ var import_node_fs49;
19122
19521
  var init_stack_layers = __esm({
19123
19522
  "src/threads/stack-layers.ts"() {
19124
19523
  "use strict";
19125
- import_node_fs48 = require("fs");
19524
+ import_node_fs49 = require("fs");
19126
19525
  init_detect();
19127
19526
  init_run();
19128
19527
  init_stack();
@@ -19135,7 +19534,7 @@ var init_stack_layers = __esm({
19135
19534
 
19136
19535
  // src/diff/diff.ts
19137
19536
  async function inspectGitWorktree(worktreePath) {
19138
- if (!worktreePath || !(0, import_node_fs49.existsSync)(worktreePath)) return "missing_worktree";
19537
+ if (!worktreePath || !(0, import_node_fs50.existsSync)(worktreePath)) return "missing_worktree";
19139
19538
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
19140
19539
  reject: false
19141
19540
  });
@@ -19143,7 +19542,7 @@ async function inspectGitWorktree(worktreePath) {
19143
19542
  return "ok";
19144
19543
  }
19145
19544
  async function initializeGitRepository(worktreePath) {
19146
- if (!worktreePath || !(0, import_node_fs49.existsSync)(worktreePath)) {
19545
+ if (!worktreePath || !(0, import_node_fs50.existsSync)(worktreePath)) {
19147
19546
  throw new Error("Worktree not found");
19148
19547
  }
19149
19548
  const status = await inspectGitWorktree(worktreePath);
@@ -19277,11 +19676,11 @@ new file mode 100644
19277
19676
  };
19278
19677
  }
19279
19678
  async function untrackedPatch(worktreePath, path, maxHunk) {
19280
- const abs = (0, import_node_path47.join)(worktreePath, path);
19679
+ const abs = (0, import_node_path48.join)(worktreePath, path);
19281
19680
  try {
19282
- const st = (0, import_node_fs49.statSync)(abs);
19681
+ const st = (0, import_node_fs50.statSync)(abs);
19283
19682
  if (st.isFile() && st.size > maxHunk) {
19284
- const buf = (0, import_node_fs49.readFileSync)(abs).subarray(0, maxHunk);
19683
+ const buf = (0, import_node_fs50.readFileSync)(abs).subarray(0, maxHunk);
19285
19684
  return syntheticAddPatch(path, buf.toString("utf8"), maxHunk);
19286
19685
  }
19287
19686
  } catch {
@@ -19748,9 +20147,9 @@ async function getDiff(worktreePath, repoPath, opts) {
19748
20147
  }
19749
20148
  function statWorktreePath(worktreePath, relativePath) {
19750
20149
  assertSafeRelativePath(relativePath);
19751
- const abs = (0, import_node_path47.join)(worktreePath, relativePath);
19752
- if (!(0, import_node_fs49.existsSync)(abs)) return "missing";
19753
- const st = (0, import_node_fs49.statSync)(abs);
20150
+ const abs = (0, import_node_path48.join)(worktreePath, relativePath);
20151
+ if (!(0, import_node_fs50.existsSync)(abs)) return "missing";
20152
+ const st = (0, import_node_fs50.statSync)(abs);
19754
20153
  if (st.isDirectory()) return "dir";
19755
20154
  if (st.isFile()) return "file";
19756
20155
  return "missing";
@@ -19779,8 +20178,8 @@ function isImageRelativePath(relativePath) {
19779
20178
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
19780
20179
  assertSafeRelativePath(relativePath);
19781
20180
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
19782
- const abs = (0, import_node_path47.join)(worktreePath, relativePath);
19783
- const st = (0, import_node_fs49.statSync)(abs);
20181
+ const abs = (0, import_node_path48.join)(worktreePath, relativePath);
20182
+ const st = (0, import_node_fs50.statSync)(abs);
19784
20183
  if (!st.isFile()) {
19785
20184
  throw new Error(`Not a file: ${relativePath}`);
19786
20185
  }
@@ -19789,7 +20188,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
19789
20188
  `File too large to upload (${st.size} bytes; max ${maxBytes})`
19790
20189
  );
19791
20190
  }
19792
- const buf = (0, import_node_fs49.readFileSync)(abs);
20191
+ const buf = (0, import_node_fs50.readFileSync)(abs);
19793
20192
  return {
19794
20193
  path: relativePath,
19795
20194
  contentBase64: buf.toString("base64"),
@@ -19799,12 +20198,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
19799
20198
  function readWorktreeFile(worktreePath, relativePath, opts) {
19800
20199
  assertSafeRelativePath(relativePath);
19801
20200
  const maxBytes = opts?.maxBytes ?? 2e5;
19802
- const abs = (0, import_node_path47.join)(worktreePath, relativePath);
19803
- const st = (0, import_node_fs49.statSync)(abs);
20201
+ const abs = (0, import_node_path48.join)(worktreePath, relativePath);
20202
+ const st = (0, import_node_fs50.statSync)(abs);
19804
20203
  if (!st.isFile()) {
19805
20204
  throw new Error(`Not a file: ${relativePath}`);
19806
20205
  }
19807
- const buf = (0, import_node_fs49.readFileSync)(abs);
20206
+ const buf = (0, import_node_fs50.readFileSync)(abs);
19808
20207
  if (isImageRelativePath(relativePath)) {
19809
20208
  const maxImageBytes = Math.max(maxBytes, 15e6);
19810
20209
  const truncated2 = buf.length > maxImageBytes;
@@ -19847,9 +20246,9 @@ function assertSafeRelativePath(relativePath) {
19847
20246
  }
19848
20247
  function writeWorktreeFile(worktreePath, relativePath, content) {
19849
20248
  assertSafeRelativePath(relativePath);
19850
- const abs = (0, import_node_path47.join)(worktreePath, relativePath);
19851
- (0, import_node_fs49.mkdirSync)((0, import_node_path47.dirname)(abs), { recursive: true });
19852
- (0, import_node_fs49.writeFileSync)(abs, content, "utf8");
20249
+ const abs = (0, import_node_path48.join)(worktreePath, relativePath);
20250
+ (0, import_node_fs50.mkdirSync)((0, import_node_path48.dirname)(abs), { recursive: true });
20251
+ (0, import_node_fs50.writeFileSync)(abs, content, "utf8");
19853
20252
  return { path: relativePath };
19854
20253
  }
19855
20254
  async function getWorktreeDirtyStat(worktreePath) {
@@ -19889,12 +20288,12 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
19889
20288
  truncated: full.files.length > maxFiles
19890
20289
  };
19891
20290
  }
19892
- var import_node_fs49, import_node_path47, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
20291
+ var import_node_fs50, import_node_path48, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
19893
20292
  var init_diff = __esm({
19894
20293
  "src/diff/diff.ts"() {
19895
20294
  "use strict";
19896
- import_node_fs49 = require("fs");
19897
- import_node_path47 = require("path");
20295
+ import_node_fs50 = require("fs");
20296
+ import_node_path48 = require("path");
19898
20297
  init_run();
19899
20298
  init_worktree();
19900
20299
  mergeBaseCache = /* @__PURE__ */ new Map();
@@ -20251,7 +20650,7 @@ function parseFrontmatter(content) {
20251
20650
  }
20252
20651
  function readSkill(skillMd, source) {
20253
20652
  try {
20254
- const content = (0, import_node_fs50.readFileSync)(skillMd, "utf8");
20653
+ const content = (0, import_node_fs51.readFileSync)(skillMd, "utf8");
20255
20654
  const { name: fmName, description } = parseFrontmatter(content);
20256
20655
  const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
20257
20656
  const name = fmName || dirName;
@@ -20270,19 +20669,19 @@ function readSkill(skillMd, source) {
20270
20669
  }
20271
20670
  }
20272
20671
  function scanSkillsDir(dir, source, out) {
20273
- if (!(0, import_node_fs50.existsSync)(dir)) return;
20672
+ if (!(0, import_node_fs51.existsSync)(dir)) return;
20274
20673
  let entries;
20275
20674
  try {
20276
- entries = (0, import_node_fs50.readdirSync)(dir);
20675
+ entries = (0, import_node_fs51.readdirSync)(dir);
20277
20676
  } catch {
20278
20677
  return;
20279
20678
  }
20280
20679
  for (const entry of entries) {
20281
20680
  if (entry.startsWith(".")) continue;
20282
- const skillMd = (0, import_node_path48.join)(dir, entry, "SKILL.md");
20283
- if (!(0, import_node_fs50.existsSync)(skillMd)) continue;
20681
+ const skillMd = (0, import_node_path49.join)(dir, entry, "SKILL.md");
20682
+ if (!(0, import_node_fs51.existsSync)(skillMd)) continue;
20284
20683
  try {
20285
- if (!(0, import_node_fs50.statSync)(skillMd).isFile()) continue;
20684
+ if (!(0, import_node_fs51.statSync)(skillMd).isFile()) continue;
20286
20685
  } catch {
20287
20686
  continue;
20288
20687
  }
@@ -20291,24 +20690,24 @@ function scanSkillsDir(dir, source, out) {
20291
20690
  }
20292
20691
  }
20293
20692
  function scanClaudePluginSkills(pluginsRoot, out) {
20294
- if (!(0, import_node_fs50.existsSync)(pluginsRoot)) return;
20693
+ if (!(0, import_node_fs51.existsSync)(pluginsRoot)) return;
20295
20694
  const walk = (dir, depth, lookingForSkillsDir) => {
20296
20695
  if (depth > 7) return;
20297
20696
  let entries;
20298
20697
  try {
20299
- entries = (0, import_node_fs50.readdirSync)(dir);
20698
+ entries = (0, import_node_fs51.readdirSync)(dir);
20300
20699
  } catch {
20301
20700
  return;
20302
20701
  }
20303
20702
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
20304
- const skill = readSkill((0, import_node_path48.join)(dir, "SKILL.md"), "cli");
20703
+ const skill = readSkill((0, import_node_path49.join)(dir, "SKILL.md"), "cli");
20305
20704
  if (skill) out.push(skill);
20306
20705
  }
20307
20706
  for (const entry of entries) {
20308
20707
  if (entry === "node_modules" || entry === ".git") continue;
20309
- const full = (0, import_node_path48.join)(dir, entry);
20708
+ const full = (0, import_node_path49.join)(dir, entry);
20310
20709
  try {
20311
- if (!(0, import_node_fs50.statSync)(full).isDirectory()) continue;
20710
+ if (!(0, import_node_fs51.statSync)(full).isDirectory()) continue;
20312
20711
  } catch {
20313
20712
  continue;
20314
20713
  }
@@ -20326,17 +20725,17 @@ function discoverSkills(worktreePath) {
20326
20725
  const home = (0, import_node_os15.homedir)();
20327
20726
  const collected = [];
20328
20727
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
20329
- scanSkillsDir((0, import_node_path48.join)(worktreePath, rel), "workspace", collected);
20728
+ scanSkillsDir((0, import_node_path49.join)(worktreePath, rel), "workspace", collected);
20330
20729
  }
20331
20730
  for (const abs of [
20332
- (0, import_node_path48.join)(home, ".claude/skills"),
20333
- (0, import_node_path48.join)(home, ".cursor/skills"),
20334
- (0, import_node_path48.join)(home, ".sideboard/skills"),
20335
- (0, import_node_path48.join)(home, ".brightsy/skills")
20731
+ (0, import_node_path49.join)(home, ".claude/skills"),
20732
+ (0, import_node_path49.join)(home, ".cursor/skills"),
20733
+ (0, import_node_path49.join)(home, ".sideboard/skills"),
20734
+ (0, import_node_path49.join)(home, ".brightsy/skills")
20336
20735
  ]) {
20337
20736
  scanSkillsDir(abs, "user", collected);
20338
20737
  }
20339
- scanClaudePluginSkills((0, import_node_path48.join)(home, ".claude/plugins"), collected);
20738
+ scanClaudePluginSkills((0, import_node_path49.join)(home, ".claude/plugins"), collected);
20340
20739
  collected.push(...bundledSkills());
20341
20740
  const rank = {
20342
20741
  workspace: 0,
@@ -20362,7 +20761,7 @@ function readSkillBody(skillPath, maxChars = 12e3) {
20362
20761
  \u2026(truncated)` : body;
20363
20762
  }
20364
20763
  }
20365
- const raw = (0, import_node_fs50.readFileSync)(skillPath, "utf8");
20764
+ const raw = (0, import_node_fs51.readFileSync)(skillPath, "utf8");
20366
20765
  if (raw.startsWith("---")) {
20367
20766
  const end = raw.indexOf("\n---", 3);
20368
20767
  if (end >= 0) {
@@ -20376,13 +20775,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
20376
20775
 
20377
20776
  \u2026(truncated)` : raw;
20378
20777
  }
20379
- var import_node_fs50, import_node_os15, import_node_path48, BUNDLED_SKILL_PREFIX;
20778
+ var import_node_fs51, import_node_os15, import_node_path49, BUNDLED_SKILL_PREFIX;
20380
20779
  var init_discover = __esm({
20381
20780
  "src/skills/discover.ts"() {
20382
20781
  "use strict";
20383
- import_node_fs50 = require("fs");
20782
+ import_node_fs51 = require("fs");
20384
20783
  import_node_os15 = require("os");
20385
- import_node_path48 = require("path");
20784
+ import_node_path49 = require("path");
20386
20785
  init_long_running();
20387
20786
  BUNDLED_SKILL_PREFIX = "bundled:";
20388
20787
  }
@@ -20537,7 +20936,7 @@ function compiledModuleDir() {
20537
20936
  try {
20538
20937
  const url = import_meta4.url;
20539
20938
  if (typeof url === "string" && url.length > 0) {
20540
- return (0, import_node_path49.dirname)((0, import_node_url4.fileURLToPath)(url));
20939
+ return (0, import_node_path50.dirname)((0, import_node_url4.fileURLToPath)(url));
20541
20940
  }
20542
20941
  } catch {
20543
20942
  }
@@ -20545,8 +20944,8 @@ function compiledModuleDir() {
20545
20944
  }
20546
20945
  function detachedJobScriptIn(dir) {
20547
20946
  for (const name of DETACHED_JOB_FILENAMES) {
20548
- const script = (0, import_node_path49.join)(dir, "scripts", name);
20549
- if ((0, import_node_fs51.existsSync)(script)) return script;
20947
+ const script = (0, import_node_path50.join)(dir, "scripts", name);
20948
+ if ((0, import_node_fs52.existsSync)(script)) return script;
20550
20949
  }
20551
20950
  return null;
20552
20951
  }
@@ -20563,7 +20962,7 @@ function resolveDetachedJobScript() {
20563
20962
  for (let i = 0; i < 8; i++) {
20564
20963
  const candidate = detachedJobScriptIn(dir);
20565
20964
  if (candidate) return candidate;
20566
- const parent = (0, import_node_path49.dirname)(dir);
20965
+ const parent = (0, import_node_path50.dirname)(dir);
20567
20966
  if (parent === dir) break;
20568
20967
  dir = parent;
20569
20968
  }
@@ -20574,12 +20973,12 @@ function formatDetachedJobInvoke(scriptPath) {
20574
20973
  if (resolved) return `node ${JSON.stringify(resolved)}`;
20575
20974
  return "node scripts/detached-job.cjs";
20576
20975
  }
20577
- var import_node_fs51, import_node_path49, import_node_url4, import_meta4, DETACHED_JOB_FILENAMES;
20976
+ var import_node_fs52, import_node_path50, import_node_url4, import_meta4, DETACHED_JOB_FILENAMES;
20578
20977
  var init_detached_job_path = __esm({
20579
20978
  "src/skills/detached-job-path.ts"() {
20580
20979
  "use strict";
20581
- import_node_fs51 = require("fs");
20582
- import_node_path49 = require("path");
20980
+ import_node_fs52 = require("fs");
20981
+ import_node_path50 = require("path");
20583
20982
  import_node_url4 = require("url");
20584
20983
  init_packaged_runtime();
20585
20984
  import_meta4 = {};
@@ -20614,6 +21013,34 @@ function formatRenameBranchDirective(thread, opts) {
20614
21013
  }
20615
21014
  return lines.join("\n");
20616
21015
  }
21016
+ function localhostPreviewUrl(port) {
21017
+ return `http://localhost:${port}`;
21018
+ }
21019
+ function describeLiveDevRun(run2) {
21020
+ const url = localhostPreviewUrl(run2.port);
21021
+ if (run2.preview === "window") {
21022
+ return `${run2.scriptName} Electron window (renderer ${url})`;
21023
+ }
21024
+ return `${run2.scriptName} ${url}`;
21025
+ }
21026
+ function formatDevAccessHint(runs) {
21027
+ const live = (runs ?? []).filter(
21028
+ (r) => Number.isFinite(r.port) && r.port > 0
21029
+ );
21030
+ if (live.length === 1) {
21031
+ const r = live[0];
21032
+ const url = localhostPreviewUrl(r.port);
21033
+ if (r.preview === "window") {
21034
+ return `This worktree's Dev app is the Electron window (${r.scriptName}). Renderer origin ${url} \u2014 curl to confirm Vite; do not open it in a browser (no preload/IPC). Do not guess :3000.`;
21035
+ }
21036
+ return `This worktree's Dev app is ${url} (${r.scriptName}). Open that URL (browser, curl, Playwright) \u2014 do not guess :3000.`;
21037
+ }
21038
+ if (live.length > 1) {
21039
+ const bits = live.map(describeLiveDevRun).join("; ");
21040
+ return `This worktree's Dev apps: ${bits}. preview=url \u2192 open the URL; preview=window \u2192 Electron window is the app. Do not guess :3000.`;
21041
+ }
21042
+ return "To open the project Dev app: MCP `run_dev_script` (same as the desktop Dev button) returns `{url, port, preview}` (`SIDEBOARD_PORT`, not 3000). preview=url \u2192 open that URL (browser, curl, Playwright). preview=window \u2192 Electron: the native window is the app; url is renderer/HMR only (no preload/IPC in a browser). If already running, `list_run_scripts` `active[].url`. `stop_dev_script` to stop.";
21043
+ }
20617
21044
  function formatWorktreeDirective(thread, opts) {
20618
21045
  const worktree = normPath3(thread.worktreePath);
20619
21046
  const repo = normPath3(thread.repoPath);
@@ -20661,6 +21088,8 @@ function formatWorktreeDirective(thread, opts) {
20661
21088
  '- Sideboard git buttons send short phrases ("Commit and push.", "Ready for review.", "Merge PR.", \u2026) with their meaning attached \u2014 act on them without asking for clarification. If the user gives a goal (Greptile 5/5, CI green, until checks pass), you get the watch-fix-push playbook with that request.'
20662
21089
  );
20663
21090
  lines.push("");
21091
+ lines.push(formatDevAccessHint(opts?.activeRuns));
21092
+ lines.push("");
20664
21093
  lines.push(formatProcessGuideDirective({ worktreePath: thread.worktreePath }));
20665
21094
  return lines.join("\n");
20666
21095
  }
@@ -20739,9 +21168,9 @@ function formatPrGateDirective() {
20739
21168
  }
20740
21169
  function formatProcessGuideDirective(opts) {
20741
21170
  const worktree = opts?.worktreePath?.trim();
20742
- const hasGraphSkill = !!worktree && (0, import_node_fs52.existsSync)((0, import_node_path50.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
20743
- const hasReviewSkill = !!worktree && (0, import_node_fs52.existsSync)((0, import_node_path50.join)(worktree, ".claude/skills/review/SKILL.md"));
20744
- const hasInstallSkill = !!worktree && (0, import_node_fs52.existsSync)((0, import_node_path50.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
21171
+ const hasGraphSkill = !!worktree && (0, import_node_fs53.existsSync)((0, import_node_path51.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
21172
+ const hasReviewSkill = !!worktree && (0, import_node_fs53.existsSync)((0, import_node_path51.join)(worktree, ".claude/skills/review/SKILL.md"));
21173
+ const hasInstallSkill = !!worktree && (0, import_node_fs53.existsSync)((0, import_node_path51.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
20745
21174
  return [
20746
21175
  "Process guides (recurring work only):",
20747
21176
  hasGraphSkill ? "- Migrations, ports, batch fixes, and other fan-out: follow `.claude/skills/graph-engineering/SKILL.md` (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch around it." : null,
@@ -20761,12 +21190,12 @@ function formatLongRunningDirective(opts) {
20761
21190
  "- Hanging, no useful output, or the wrong thing \u2192 `stop_job` (or the helper with `stop <id>`). Do not stop a pack/test/deploy that is clearly making progress.",
20762
21191
  "- Stay in the loop until stillRunning is false (or you stopped it). ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
20763
21192
  "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available).",
20764
- "Project Dev / run scripts (`.sideboard` `[scripts.run.*]`, same as the desktop Dev button): use MCP `list_run_scripts` / `run_dev_script` / `stop_dev_script` \u2014 logs and Stop live in the thread UI. Do not detached-job or shell-spawn that same command."
21193
+ "Project Dev / run scripts (`.sideboard` `[scripts.run.*]`, same as the desktop Dev button): use MCP `list_run_scripts` / `run_dev_script` / `stop_dev_script` \u2014 logs and Stop live in the thread UI. Do not detached-job or shell-spawn that same command. `run_dev_script` returns `{url, port, preview}` (`SIDEBOARD_PORT`). preview=url \u2192 open that URL; preview=window \u2192 Electron window is the app (url is renderer/HMR only). Never guess :3000."
20765
21194
  ].join("\n");
20766
21195
  }
20767
21196
  function formatLongRunningReminder(opts) {
20768
21197
  const invoke = formatDetachedJobInvoke(opts?.scriptPath);
20769
- return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait). The log pane updates from wait JSON; present_artifact type=log is optional. stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn. Project Dev button: list_run_scripts / run_dev_script / stop_dev_script (UI-connected \u2014 not detached-job).`;
21198
+ return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait). The log pane updates from wait JSON; present_artifact type=log is optional. stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn. Project Dev button: list_run_scripts / run_dev_script / stop_dev_script (UI-connected \u2014 not detached-job). ${formatDevAccessHint(opts?.activeRuns)}`;
20770
21199
  }
20771
21200
  function formatArtifactDirective() {
20772
21201
  return [
@@ -20778,14 +21207,14 @@ function formatArtifactDirective() {
20778
21207
  ].join("\n");
20779
21208
  }
20780
21209
  function formatUiReminder() {
20781
- return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos, \u201Cwhat next?\u201D, or after a review) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable. Dev / preview: run_dev_script (same as the Dev button); stop_dev_script to stop.";
21210
+ return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos, \u201Cwhat next?\u201D, or after a review) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable. Dev / preview: run_dev_script (same as the Dev button) returns {url, port, preview} (SIDEBOARD_PORT \u2014 never guess :3000). preview=url \u2192 open url; preview=window \u2192 Electron window is the app, url is renderer/HMR only. list_run_scripts active[].url if already running; stop_dev_script to stop.";
20782
21211
  }
20783
- var import_node_fs52, import_node_path50, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
21212
+ var import_node_fs53, import_node_path51, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
20784
21213
  var init_instructions = __esm({
20785
21214
  "src/agents/instructions.ts"() {
20786
21215
  "use strict";
20787
- import_node_fs52 = require("fs");
20788
- import_node_path50 = require("path");
21216
+ import_node_fs53 = require("fs");
21217
+ import_node_path51 = require("path");
20789
21218
  init_git_auth_mode();
20790
21219
  init_branch_prefix();
20791
21220
  init_worktree_labels();
@@ -21009,40 +21438,40 @@ __export(plan_file_exports, {
21009
21438
  writePlanFile: () => writePlanFile
21010
21439
  });
21011
21440
  function ensureAttachmentsGitignore(worktreePath) {
21012
- const gitignoreAbs = (0, import_node_path51.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
21013
- if ((0, import_node_fs53.existsSync)(gitignoreAbs)) return;
21014
- (0, import_node_fs53.mkdirSync)((0, import_node_path51.dirname)(gitignoreAbs), { recursive: true });
21015
- (0, import_node_fs53.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
21441
+ const gitignoreAbs = (0, import_node_path52.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
21442
+ if ((0, import_node_fs54.existsSync)(gitignoreAbs)) return;
21443
+ (0, import_node_fs54.mkdirSync)((0, import_node_path52.dirname)(gitignoreAbs), { recursive: true });
21444
+ (0, import_node_fs54.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
21016
21445
  }
21017
21446
  function planFileAbs(worktreePath) {
21018
- return (0, import_node_path51.join)(worktreePath, PLAN_FILE_REL);
21447
+ return (0, import_node_path52.join)(worktreePath, PLAN_FILE_REL);
21019
21448
  }
21020
21449
  function readTextIfPresent2(abs) {
21021
- if (!(0, import_node_fs53.existsSync)(abs)) return null;
21450
+ if (!(0, import_node_fs54.existsSync)(abs)) return null;
21022
21451
  try {
21023
- const content = (0, import_node_fs53.readFileSync)(abs, "utf8");
21452
+ const content = (0, import_node_fs54.readFileSync)(abs, "utf8");
21024
21453
  return content.trim() ? content : null;
21025
21454
  } catch {
21026
21455
  return null;
21027
21456
  }
21028
21457
  }
21029
21458
  function readPlanFile(worktreePath) {
21030
- return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path51.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path51.join)(worktreePath, LEGACY_PLAN_FILE_REL));
21459
+ return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path52.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path52.join)(worktreePath, LEGACY_PLAN_FILE_REL));
21031
21460
  }
21032
21461
  function writePlanFile(worktreePath, content) {
21033
21462
  ensureAttachmentsGitignore(worktreePath);
21034
21463
  const abs = planFileAbs(worktreePath);
21035
- (0, import_node_fs53.mkdirSync)((0, import_node_path51.dirname)(abs), { recursive: true });
21464
+ (0, import_node_fs54.mkdirSync)((0, import_node_path52.dirname)(abs), { recursive: true });
21036
21465
  const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
21037
- (0, import_node_fs53.writeFileSync)(abs, body, "utf8");
21466
+ (0, import_node_fs54.writeFileSync)(abs, body, "utf8");
21038
21467
  return PLAN_FILE_REL;
21039
21468
  }
21040
- var import_node_fs53, import_node_path51;
21469
+ var import_node_fs54, import_node_path52;
21041
21470
  var init_plan_file = __esm({
21042
21471
  "src/plan/plan-file.ts"() {
21043
21472
  "use strict";
21044
- import_node_fs53 = require("fs");
21045
- import_node_path51 = require("path");
21473
+ import_node_fs54 = require("fs");
21474
+ import_node_path52 = require("path");
21046
21475
  init_workspace_scratch();
21047
21476
  init_plan_present();
21048
21477
  init_plan_present();
@@ -21102,7 +21531,7 @@ function setCaffeinateHoldHooks(next) {
21102
21531
  hooks = next;
21103
21532
  }
21104
21533
  function caffeinateHoldPath() {
21105
- return (0, import_node_path52.join)(appDataDir(), "caffeinate-hold.json");
21534
+ return (0, import_node_path53.join)(appDataDir(), "caffeinate-hold.json");
21106
21535
  }
21107
21536
  function processAlive(pid) {
21108
21537
  if (hooks.processAlive) return hooks.processAlive(pid);
@@ -21136,9 +21565,9 @@ function uniqueIds(ids) {
21136
21565
  }
21137
21566
  function readHold() {
21138
21567
  const path = caffeinateHoldPath();
21139
- if (!(0, import_node_fs54.existsSync)(path)) return null;
21568
+ if (!(0, import_node_fs55.existsSync)(path)) return null;
21140
21569
  try {
21141
- const parsed = JSON.parse((0, import_node_fs54.readFileSync)(path, "utf8"));
21570
+ const parsed = JSON.parse((0, import_node_fs55.readFileSync)(path, "utf8"));
21142
21571
  if (typeof parsed?.pid === "number" && parsed.pid > 0) {
21143
21572
  return {
21144
21573
  pid: parsed.pid,
@@ -21160,7 +21589,7 @@ function writeHold(pid, threadIds) {
21160
21589
  }
21161
21590
  function clearHold() {
21162
21591
  try {
21163
- (0, import_node_fs54.unlinkSync)(caffeinateHoldPath());
21592
+ (0, import_node_fs55.unlinkSync)(caffeinateHoldPath());
21164
21593
  } catch {
21165
21594
  }
21166
21595
  }
@@ -21245,13 +21674,13 @@ function releaseCaffeinateHoldForThread(threadId) {
21245
21674
  }
21246
21675
  return setCaffeinateHold(false, { threadId: id });
21247
21676
  }
21248
- var import_node_child_process6, import_node_fs54, import_node_path52, hooks;
21677
+ var import_node_child_process6, import_node_fs55, import_node_path53, hooks;
21249
21678
  var init_caffeinate_hold = __esm({
21250
21679
  "src/store/caffeinate-hold.ts"() {
21251
21680
  "use strict";
21252
21681
  import_node_child_process6 = require("child_process");
21253
- import_node_fs54 = require("fs");
21254
- import_node_path52 = require("path");
21682
+ import_node_fs55 = require("fs");
21683
+ import_node_path53 = require("path");
21255
21684
  init_paths();
21256
21685
  init_private_file();
21257
21686
  hooks = {};
@@ -21260,7 +21689,7 @@ var init_caffeinate_hold = __esm({
21260
21689
 
21261
21690
  // src/store/schedules.ts
21262
21691
  function schedulesPath() {
21263
- return (0, import_node_path53.join)(appDataDir(), "schedules.json");
21692
+ return (0, import_node_path54.join)(appDataDir(), "schedules.json");
21264
21693
  }
21265
21694
  function parseDurationMs(every) {
21266
21695
  const m = every.trim().match(DURATION_RE);
@@ -21360,9 +21789,9 @@ function normalizeTask(raw) {
21360
21789
  }
21361
21790
  function readAll2() {
21362
21791
  const path = schedulesPath();
21363
- if (!(0, import_node_fs55.existsSync)(path)) return [];
21792
+ if (!(0, import_node_fs56.existsSync)(path)) return [];
21364
21793
  try {
21365
- const parsed = JSON.parse((0, import_node_fs55.readFileSync)(path, "utf8"));
21794
+ const parsed = JSON.parse((0, import_node_fs56.readFileSync)(path, "utf8"));
21366
21795
  if (!Array.isArray(parsed)) return [];
21367
21796
  return parsed.map((row) => {
21368
21797
  try {
@@ -21474,13 +21903,13 @@ function recordScheduleRun(id, result) {
21474
21903
  writeAll2(rows);
21475
21904
  return next;
21476
21905
  }
21477
- var import_node_crypto11, import_node_fs55, import_node_path53, import_croner, DURATION_RE, UNIT_MS;
21906
+ var import_node_crypto11, import_node_fs56, import_node_path54, import_croner, DURATION_RE, UNIT_MS;
21478
21907
  var init_schedules = __esm({
21479
21908
  "src/store/schedules.ts"() {
21480
21909
  "use strict";
21481
21910
  import_node_crypto11 = require("crypto");
21482
- import_node_fs55 = require("fs");
21483
- import_node_path53 = require("path");
21911
+ import_node_fs56 = require("fs");
21912
+ import_node_path54 = require("path");
21484
21913
  import_croner = require("croner");
21485
21914
  init_orchestrator_capable();
21486
21915
  init_paths();
@@ -21636,9 +22065,9 @@ function recoverFinishedCursorRun(opts) {
21636
22065
  return best;
21637
22066
  }
21638
22067
  function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
21639
- if (!(0, import_node_fs56.existsSync)(runsPath)) return null;
22068
+ if (!(0, import_node_fs57.existsSync)(runsPath)) return null;
21640
22069
  try {
21641
- const lines = (0, import_node_fs56.readFileSync)(runsPath, "utf8").split("\n");
22070
+ const lines = (0, import_node_fs57.readFileSync)(runsPath, "utf8").split("\n");
21642
22071
  let best = null;
21643
22072
  for (const line of lines) {
21644
22073
  const trimmed = line.trim();
@@ -21664,11 +22093,11 @@ function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
21664
22093
  return null;
21665
22094
  }
21666
22095
  }
21667
- var import_node_fs56;
22096
+ var import_node_fs57;
21668
22097
  var init_cursor_recover = __esm({
21669
22098
  "src/agents/cursor-recover.ts"() {
21670
22099
  "use strict";
21671
- import_node_fs56 = require("fs");
22100
+ import_node_fs57 = require("fs");
21672
22101
  init_cursor_store();
21673
22102
  }
21674
22103
  });
@@ -21822,14 +22251,14 @@ async function startOrchestration(opts) {
21822
22251
  }
21823
22252
  return updated;
21824
22253
  }
21825
- var import_node_events, import_node_crypto12, import_node_fs57, LIVE_TURN_SPAWN_GRACE_MS, RUN_SCRIPT_DESKTOP_ADOPT_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton;
22254
+ var import_node_events, import_node_crypto12, import_node_fs58, LIVE_TURN_SPAWN_GRACE_MS, RUN_SCRIPT_DESKTOP_ADOPT_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton;
21826
22255
  var init_orchestrator = __esm({
21827
22256
  "src/orchestrator/orchestrator.ts"() {
21828
22257
  "use strict";
21829
22258
  import_node_events = require("events");
21830
22259
  init_outbound_watch();
21831
22260
  import_node_crypto12 = require("crypto");
21832
- import_node_fs57 = require("fs");
22261
+ import_node_fs58 = require("fs");
21833
22262
  init_error_detail();
21834
22263
  init_run();
21835
22264
  init_stale_lock();
@@ -21841,6 +22270,7 @@ var init_orchestrator = __esm({
21841
22270
  init_agent_git_actions();
21842
22271
  init_pr_merge_archive();
21843
22272
  init_conductor();
22273
+ init_dev_preview();
21844
22274
  init_setup_log();
21845
22275
  init_orphan_cleanup();
21846
22276
  init_history_cleanup();
@@ -22006,7 +22436,7 @@ var init_orchestrator = __esm({
22006
22436
  this.lightReconcileAt.set(repoPath, Date.now());
22007
22437
  for (const thread of listThreads()) {
22008
22438
  if (isGlobalThread(thread) || thread.repoPath !== repoPath) continue;
22009
- if (!(0, import_node_fs57.existsSync)(thread.worktreePath)) {
22439
+ if (!(0, import_node_fs58.existsSync)(thread.worktreePath)) {
22010
22440
  setStatus(thread.id, "broken", "Worktree missing on disk");
22011
22441
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
22012
22442
  }
@@ -22035,7 +22465,7 @@ var init_orchestrator = __esm({
22035
22465
  }
22036
22466
  continue;
22037
22467
  }
22038
- if (!(0, import_node_fs57.existsSync)(thread.worktreePath)) {
22468
+ if (!(0, import_node_fs58.existsSync)(thread.worktreePath)) {
22039
22469
  setStatus(thread.id, "broken", "Worktree missing on disk");
22040
22470
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
22041
22471
  continue;
@@ -22722,8 +23152,13 @@ var init_orchestrator = __esm({
22722
23152
  SLACK_REPLY_FORMATTING
22723
23153
  ].join("\n") : null
22724
23154
  ].filter(Boolean).join("\n") : null;
23155
+ const worktreeActiveRuns = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && thread.worktreePath ? annotateDevAccessRuns(
23156
+ mergeWorktreeActiveRuns(threadsSharingWorktree(thread.worktreePath)).activeRuns,
23157
+ listRunScripts(thread.worktreePath, thread.repoPath),
23158
+ thread.worktreePath
23159
+ ) : [];
22725
23160
  const artifactReminder = thread.agent !== "brightsy" ? formatUiReminder() : null;
22726
- const longRunningReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatLongRunningReminder() : null;
23161
+ const longRunningReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatLongRunningReminder({ activeRuns: worktreeActiveRuns }) : null;
22727
23162
  const worktreeReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatWorktreeReminder() : null;
22728
23163
  const optionalServicesReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatOptionalServicesReminder(loadAppSettings().integrations) : null;
22729
23164
  const issueTicket = issueTicketFromThread(thread, resolveEffectiveIssueSource());
@@ -22783,7 +23218,14 @@ var init_orchestrator = __esm({
22783
23218
  8e3,
22784
23219
  "resolveGithubRepoSlug"
22785
23220
  ).catch(() => null),
22786
- gitAuthMode
23221
+ gitAuthMode,
23222
+ activeRuns: annotateDevAccessRuns(
23223
+ mergeWorktreeActiveRuns(
23224
+ threadsSharingWorktree(fresh.worktreePath)
23225
+ ).activeRuns,
23226
+ listRunScripts(fresh.worktreePath, fresh.repoPath),
23227
+ fresh.worktreePath
23228
+ )
22787
23229
  });
22788
23230
  const artifactDirective = isBrightsy ? null : formatArtifactDirective();
22789
23231
  const longRunningDirective = isBrightsy || isOrchestration ? null : formatLongRunningDirective();
@@ -24336,7 +24778,7 @@ var init_orchestrator = __esm({
24336
24778
  this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
24337
24779
  return restored2;
24338
24780
  }
24339
- if (!(0, import_node_fs57.existsSync)(thread.worktreePath)) {
24781
+ if (!(0, import_node_fs58.existsSync)(thread.worktreePath)) {
24340
24782
  if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
24341
24783
  throw new Error(
24342
24784
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
@@ -24420,7 +24862,7 @@ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
24420
24862
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
24421
24863
  var import_zod9 = require("zod");
24422
24864
  var import_node_crypto15 = require("crypto");
24423
- var import_node_path56 = require("path");
24865
+ var import_node_path57 = require("path");
24424
24866
  init_orchestrator();
24425
24867
  init_worktree();
24426
24868
 
@@ -26137,6 +26579,8 @@ function resolveRunScriptThreadRef(ref) {
26137
26579
  }
26138
26580
 
26139
26581
  // src/mcp/server.ts
26582
+ init_dev_preview();
26583
+ init_instructions();
26140
26584
  init_wait_for_turn();
26141
26585
  init_wait_for_job();
26142
26586
  init_message_parts();
@@ -27840,27 +28284,27 @@ init_gh_errors();
27840
28284
  init_git_auth_mode();
27841
28285
 
27842
28286
  // src/board/load-home-board.ts
27843
- var import_node_fs59 = require("fs");
27844
- var import_node_path55 = require("path");
28287
+ var import_node_fs60 = require("fs");
28288
+ var import_node_path56 = require("path");
27845
28289
  init_worktree();
27846
28290
  init_paths();
27847
28291
 
27848
28292
  // src/board/board-pins.ts
27849
28293
  var import_node_crypto14 = require("crypto");
27850
- var import_node_fs58 = require("fs");
27851
- var import_node_path54 = require("path");
28294
+ var import_node_fs59 = require("fs");
28295
+ var import_node_path55 = require("path");
27852
28296
  init_paths();
27853
28297
  init_home_board();
27854
28298
  var FILE = "home-board-pins.json";
27855
28299
  var VERSION = 1;
27856
28300
  function pinsFile() {
27857
- return (0, import_node_path54.join)(appDataDir(), FILE);
28301
+ return (0, import_node_path55.join)(appDataDir(), FILE);
27858
28302
  }
27859
28303
  function readDisk() {
27860
28304
  const path = pinsFile();
27861
- if (!(0, import_node_fs58.existsSync)(path)) return [];
28305
+ if (!(0, import_node_fs59.existsSync)(path)) return [];
27862
28306
  try {
27863
- const raw = JSON.parse((0, import_node_fs58.readFileSync)(path, "utf8"));
28307
+ const raw = JSON.parse((0, import_node_fs59.readFileSync)(path, "utf8"));
27864
28308
  if (raw?.version !== VERSION || !Array.isArray(raw.items)) return [];
27865
28309
  return raw.items.filter((item) => item?.id && item.kind && item.ref);
27866
28310
  } catch {
@@ -27868,8 +28312,8 @@ function readDisk() {
27868
28312
  }
27869
28313
  }
27870
28314
  function writeDisk(items) {
27871
- (0, import_node_fs58.mkdirSync)(appDataDir(), { recursive: true });
27872
- (0, import_node_fs58.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
28315
+ (0, import_node_fs59.mkdirSync)(appDataDir(), { recursive: true });
28316
+ (0, import_node_fs59.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
27873
28317
  }
27874
28318
  function listBoardPins() {
27875
28319
  return readDisk();
@@ -27890,7 +28334,7 @@ function homeBoardWorkspaceKey(workspaces) {
27890
28334
  return workspaces.map((w) => w.path).filter(Boolean).sort().join("\n");
27891
28335
  }
27892
28336
  function cacheFile() {
27893
- return (0, import_node_path55.join)(appDataDir(), "home-board-cache.json");
28337
+ return (0, import_node_path56.join)(appDataDir(), "home-board-cache.json");
27894
28338
  }
27895
28339
  function emptyInputs() {
27896
28340
  return {
@@ -27916,9 +28360,9 @@ function shouldCacheHomeBoardInputs(inputs) {
27916
28360
  }
27917
28361
  function readDiskCache() {
27918
28362
  const path = cacheFile();
27919
- if (!(0, import_node_fs59.existsSync)(path)) return null;
28363
+ if (!(0, import_node_fs60.existsSync)(path)) return null;
27920
28364
  try {
27921
- const raw = JSON.parse((0, import_node_fs59.readFileSync)(path, "utf8"));
28365
+ const raw = JSON.parse((0, import_node_fs60.readFileSync)(path, "utf8"));
27922
28366
  if (raw?.version !== CACHE_VERSION || typeof raw.fetchedAt !== "number") {
27923
28367
  return null;
27924
28368
  }
@@ -27932,8 +28376,8 @@ function readDiskCache() {
27932
28376
  }
27933
28377
  function writeDiskCache(entry) {
27934
28378
  try {
27935
- (0, import_node_fs59.mkdirSync)(appDataDir(), { recursive: true });
27936
- (0, import_node_fs59.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
28379
+ (0, import_node_fs60.mkdirSync)(appDataDir(), { recursive: true });
28380
+ (0, import_node_fs60.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
27937
28381
  } catch {
27938
28382
  }
27939
28383
  }
@@ -28254,6 +28698,9 @@ async function createOrchChildThread(orch, args, resolveNewThreadOptions2) {
28254
28698
  return { ok: false, text: `create_thread failed: ${message}` };
28255
28699
  }
28256
28700
  }
28701
+ function previewHint(preview) {
28702
+ return preview === "window" ? "Electron: the native window is the app. url is the renderer/HMR origin only \u2014 do not open it in a browser (no preload/IPC)." : "Open url in a browser, curl, or Playwright to use the app.";
28703
+ }
28257
28704
  async function startMcpServer() {
28258
28705
  const orch = getOrchestrator();
28259
28706
  try {
@@ -28320,7 +28767,7 @@ async function startMcpServer() {
28320
28767
  async () => {
28321
28768
  const threads = orch.getThreads(true);
28322
28769
  const lines = threads.map((t) => {
28323
- const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path56.basename)(t.repoPath) || t.repoPath;
28770
+ const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path57.basename)(t.repoPath) || t.repoPath;
28324
28771
  const live = orch.threadLooksLive(t) ? readTurnLive(t.id) : null;
28325
28772
  const parent = t.parentThreadId ? ` parent:${t.parentThreadId.slice(0, 8)}` : "";
28326
28773
  const preview = lastMessagePreview(t.messages, 80);
@@ -28577,15 +29024,27 @@ async function startMcpServer() {
28577
29024
  );
28578
29025
  server.tool(
28579
29026
  "list_run_scripts",
28580
- "List .sideboard/.conductor run scripts for this thread (same menu as the desktop Dev button) and which are active. Worktree turns may omit ref (uses cwd).",
29027
+ "List .sideboard/.conductor run scripts for this thread (same menu as the desktop Dev button) and which are active. Each script and active run includes preview: url (open http://localhost:<SIDEBOARD_PORT>) or window (Electron: native window is the app; url is renderer/HMR only). Never guess :3000. Worktree turns may omit ref (uses cwd).",
28581
29028
  {
28582
29029
  ref: import_zod9.z.string().optional().describe("Thread id. Omit on a worktree turn (uses cwd).")
28583
29030
  },
28584
29031
  async ({ ref }) => {
28585
29032
  try {
28586
29033
  const threadRef = resolveRunScriptThreadRef(ref);
28587
- const scripts = orch.listThreadRunScripts(threadRef);
28588
- const active = orch.getActiveRuns(threadRef);
29034
+ const worktreePath = orch.getThread(threadRef)?.worktreePath ?? "";
29035
+ const scripts = orch.listThreadRunScripts(threadRef).map((script) => ({
29036
+ ...script,
29037
+ preview: runScriptPreview(script, worktreePath)
29038
+ }));
29039
+ const active = orch.getActiveRuns(threadRef).map((run2) => {
29040
+ const preview = activeRunPreview(run2.scriptName, scripts, worktreePath);
29041
+ return {
29042
+ ...run2,
29043
+ url: localhostPreviewUrl(run2.port),
29044
+ preview,
29045
+ hint: previewHint(preview)
29046
+ };
29047
+ });
28589
29048
  return mcpJson({ scripts, active, ref: threadRef });
28590
29049
  } catch (err) {
28591
29050
  const message = err instanceof Error ? err.message : String(err);
@@ -28595,7 +29054,7 @@ async function startMcpServer() {
28595
29054
  );
28596
29055
  server.tool(
28597
29056
  "run_dev_script",
28598
- "Start a .sideboard/.conductor run script (same as the desktop Dev / play button). Logs and Stop appear in the thread UI \u2014 do not detached-job or shell-spawn the same command. Returns the allocated port. Worktree turns may omit ref (uses cwd). Omit name for the default script.",
29057
+ "Start a .sideboard/.conductor run script (same as the desktop Dev / play button). Logs and Stop appear in the thread UI \u2014 do not detached-job or shell-spawn the same command. Returns {port, ports, url, preview}. preview=url \u2192 open url (browser, curl, Playwright). preview=window \u2192 Electron: the native window is the app; url is renderer/HMR only (no preload/IPC in a browser). The port is allocated SIDEBOARD_PORT, not 3000. Worktree turns may omit ref (uses cwd). Omit name for the default script.",
28599
29058
  {
28600
29059
  ref: import_zod9.z.string().optional().describe("Thread id. Omit on a worktree turn (uses cwd)."),
28601
29060
  name: import_zod9.z.string().optional().describe("Script name from list_run_scripts (default script if omitted).")
@@ -28604,11 +29063,16 @@ async function startMcpServer() {
28604
29063
  try {
28605
29064
  const threadRef = resolveRunScriptThreadRef(ref);
28606
29065
  const result = await orch.startDev(threadRef, name);
29066
+ const worktreePath = orch.getThread(threadRef)?.worktreePath ?? "";
29067
+ const scripts = orch.listThreadRunScripts(threadRef);
29068
+ const preview = activeRunPreview(result.scriptName, scripts, worktreePath);
28607
29069
  return mcpJson({
28608
29070
  port: result.port,
28609
29071
  scriptName: result.scriptName,
28610
29072
  ports: result.ports,
28611
- url: `http://localhost:${result.port}`,
29073
+ url: localhostPreviewUrl(result.port),
29074
+ preview,
29075
+ hint: previewHint(preview),
28612
29076
  ref: threadRef
28613
29077
  });
28614
29078
  } catch (err) {