@sideboard-ai/core 0.1.228 → 0.1.230

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 (48) hide show
  1. package/dist/{abletime-D6773P33.js → abletime-BGVOCEOU.js} +4 -4
  2. package/dist/{abletime-BF253OZT.js → abletime-WZNDTRVL.js} +4 -4
  3. package/dist/{abletime-oauth-KQPVVBKA.js → abletime-oauth-6M5GWEPX.js} +3 -3
  4. package/dist/{abletime-oauth-H4672PRH.js → abletime-oauth-ZLU2EYRK.js} +3 -3
  5. package/dist/{abletime-rest-DAFPXZ7H.js → abletime-rest-F7XG5NGY.js} +3 -3
  6. package/dist/{abletime-rest-OPEVV3XC.js → abletime-rest-WNHIATB3.js} +3 -3
  7. package/dist/{agents-DV5UROWB.js → agents-ENAQHQRZ.js} +5 -5
  8. package/dist/{agents-QQ77D7VT.js → agents-TCTEAK6M.js} +5 -5
  9. package/dist/{app-settings-5RQMQKSB.js → app-settings-KBL2G7M4.js} +7 -1
  10. package/dist/{app-settings-V2BBCX2H.js → app-settings-UXWCPDEA.js} +7 -1
  11. package/dist/{chunk-NFWPDEN4.js → chunk-4CZ25DO2.js} +2 -2
  12. package/dist/{chunk-3IMSQNTS.js → chunk-4VGCG2HV.js} +17 -0
  13. package/dist/{chunk-SQHRPJ7P.js → chunk-6L25K7BE.js} +14 -4
  14. package/dist/{chunk-HSYE5ID6.js → chunk-AS4UN7QL.js} +5 -5
  15. package/dist/{chunk-3NWUHXU3.js → chunk-C774RJJA.js} +3 -3
  16. package/dist/{chunk-VUW3VKLW.js → chunk-FA4CPYCY.js} +17 -4
  17. package/dist/{chunk-CLI5DVU4.js → chunk-GHRZNPBK.js} +2 -2
  18. package/dist/{chunk-N2VST3NL.js → chunk-HZFLKVGC.js} +3 -3
  19. package/dist/{chunk-72XUASTH.js → chunk-HZLZ34FK.js} +157 -26
  20. package/dist/{chunk-EWHJNJHV.js → chunk-I5NC7DWO.js} +38 -0
  21. package/dist/{chunk-WHYJL7CP.js → chunk-JJRRLCCS.js} +156 -25
  22. package/dist/{chunk-646I442S.js → chunk-MVLXDYN5.js} +5 -5
  23. package/dist/{chunk-KTZESHYH.js → chunk-N5TX66CD.js} +2 -2
  24. package/dist/{chunk-RRW2XWAY.js → chunk-P6ZM5QJW.js} +2 -2
  25. package/dist/{chunk-THLVCXLF.js → chunk-RGNPPRZZ.js} +3 -3
  26. package/dist/{chunk-Y5JES2VV.js → chunk-RZTRWN2V.js} +38 -0
  27. package/dist/{chunk-SOGGKYFV.js → chunk-SWNEA5OZ.js} +3 -3
  28. package/dist/{chunk-P2EAAM3H.js → chunk-UNTOZA3C.js} +3 -3
  29. package/dist/{chunk-HY2GFZ5S.js → chunk-XJETIO4K.js} +17 -0
  30. package/dist/{coordinator-prompt-JLMQVORO.js → coordinator-prompt-DFXYTM6D.js} +4 -4
  31. package/dist/{coordinator-prompt-VZ7OSRLD.js → coordinator-prompt-YKLXQTWH.js} +4 -4
  32. package/dist/{global-workspace-3FDAUNN2.js → global-workspace-4SPANNJT.js} +4 -4
  33. package/dist/{global-workspace-QPSJEXGR.js → global-workspace-EYZKYHAO.js} +4 -4
  34. package/dist/index.cjs +992 -634
  35. package/dist/index.d.cts +120 -6
  36. package/dist/index.d.ts +120 -6
  37. package/dist/index.js +207 -68
  38. package/dist/mcp/run-stdio.cjs +289 -50
  39. package/dist/mcp/run-stdio.js +87 -51
  40. package/dist/{orchestrator-6XEWQWSM.js → orchestrator-HMJPNUN5.js} +8 -6
  41. package/dist/{orchestrator-QUJORSTA.js → orchestrator-ZT3SJVKF.js} +8 -6
  42. package/dist/{thread-store-KDPPXJJ3.js → thread-store-FBK5SZ5P.js} +1 -1
  43. package/dist/{thread-store-N6WQIWZ4.js → thread-store-IKJD4EOK.js} +1 -1
  44. package/dist/{workspaces-76W7IEKR.js → workspaces-73Y7IJY2.js} +4 -4
  45. package/dist/{workspaces-TDBA64II.js → workspaces-FQCSCTNH.js} +4 -4
  46. package/dist/{worktree-7V67XTEO.js → worktree-36VEFUJN.js} +3 -3
  47. package/dist/{worktree-I573UOPD.js → worktree-DOPRKG7K.js} +3 -3
  48. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -30,6 +30,16 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
+ // src/types/thread.ts
34
+ function isUnclaimedRunScriptRequest(req) {
35
+ return Boolean(req && !req.claimedAt && !req.fulfilledAt && !req.error);
36
+ }
37
+ var init_thread = __esm({
38
+ "src/types/thread.ts"() {
39
+ "use strict";
40
+ }
41
+ });
42
+
33
43
  // src/types/thinking-effort.ts
34
44
  function normalizeThinkingEffort(value) {
35
45
  if (typeof value !== "string") return null;
@@ -1214,12 +1224,14 @@ var init_issue_source_labels = __esm({
1214
1224
  // src/store/app-settings.ts
1215
1225
  var app_settings_exports = {};
1216
1226
  __export(app_settings_exports, {
1227
+ AGENT_DONE_SOUNDS: () => AGENT_DONE_SOUNDS,
1217
1228
  FOLLOW_UP_BEHAVIORS: () => FOLLOW_UP_BEHAVIORS,
1218
1229
  GITHUB_GIT_AUTH_MODES: () => GITHUB_GIT_AUTH_MODES,
1219
1230
  HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
1220
1231
  ISSUE_SOURCE_LABELS: () => ISSUE_SOURCE_LABELS,
1221
1232
  PROFILE_NOTES_MAX: () => PROFILE_NOTES_MAX,
1222
1233
  USAGE_ON_LIMIT_VALUES: () => USAGE_ON_LIMIT_VALUES,
1234
+ agentDoneSound: () => agentDoneSound,
1223
1235
  appSettingsPath: () => appSettingsPath,
1224
1236
  applyAppEnvironment: () => applyAppEnvironment,
1225
1237
  autoArchiveOnMergeEnabled: () => autoArchiveOnMergeEnabled,
@@ -1267,6 +1279,7 @@ __export(app_settings_exports, {
1267
1279
  historyMaxCount: () => historyMaxCount,
1268
1280
  historyMaxDays: () => historyMaxDays,
1269
1281
  isAbleTimeConnected: () => isAbleTimeConnected,
1282
+ isAgentDoneSound: () => isAgentDoneSound,
1270
1283
  isIssueSourceConnected: () => isIssueSourceConnected,
1271
1284
  isLinearConnected: () => isLinearConnected,
1272
1285
  isUsageOnLimit: () => isUsageOnLimit,
@@ -1308,6 +1321,9 @@ __export(app_settings_exports, {
1308
1321
  usageOnLimit: () => usageOnLimit,
1309
1322
  writeViewerContext: () => writeViewerContext
1310
1323
  });
1324
+ function isAgentDoneSound(value) {
1325
+ return AGENT_DONE_SOUNDS.includes(value);
1326
+ }
1311
1327
  function emptyPublicIntegrations() {
1312
1328
  return {
1313
1329
  hasLinearApiKey: false,
@@ -1738,6 +1754,13 @@ function normalizeAdvanced(raw) {
1738
1754
  if (source.followUpBehavior === "queue" || source.followUpBehavior === "steer") {
1739
1755
  out.followUpBehavior = source.followUpBehavior;
1740
1756
  }
1757
+ if (isAgentDoneSound(source.agentDoneSound)) {
1758
+ out.agentDoneSound = source.agentDoneSound;
1759
+ }
1760
+ if (typeof source.agentDoneCustomSoundName === "string") {
1761
+ const name = source.agentDoneCustomSoundName.trim();
1762
+ if (name) out.agentDoneCustomSoundName = name.slice(0, 200);
1763
+ }
1741
1764
  return out;
1742
1765
  }
1743
1766
  function normalizeSettings(raw) {
@@ -2648,6 +2671,16 @@ function updateAdvancedSettings(patch) {
2648
2671
  if (patch.followUpBehavior === "queue" || patch.followUpBehavior === "steer") {
2649
2672
  advanced.followUpBehavior = patch.followUpBehavior;
2650
2673
  }
2674
+ if (isAgentDoneSound(patch.agentDoneSound)) {
2675
+ advanced.agentDoneSound = patch.agentDoneSound;
2676
+ }
2677
+ if (patch.agentDoneCustomSoundName === null || patch.agentDoneCustomSoundName === "") {
2678
+ delete advanced.agentDoneCustomSoundName;
2679
+ } else if (typeof patch.agentDoneCustomSoundName === "string") {
2680
+ const name = patch.agentDoneCustomSoundName.trim();
2681
+ if (name) advanced.agentDoneCustomSoundName = name.slice(0, 200);
2682
+ else delete advanced.agentDoneCustomSoundName;
2683
+ }
2651
2684
  return saveAppSettings({ ...current, advanced });
2652
2685
  }
2653
2686
  function autoRenameBranchEnabled(settings = loadAppSettings()) {
@@ -2715,6 +2748,9 @@ function orchestrationQuotaFallbackAgent(settings = loadAppSettings()) {
2715
2748
  function followUpBehavior(settings = loadAppSettings()) {
2716
2749
  return settings.advanced.followUpBehavior === "queue" ? "queue" : "steer";
2717
2750
  }
2751
+ function agentDoneSound(settings = loadAppSettings()) {
2752
+ return isAgentDoneSound(settings.advanced.agentDoneSound) ? settings.advanced.agentDoneSound : "none";
2753
+ }
2718
2754
  function maxConcurrentAgents(settings = loadAppSettings()) {
2719
2755
  const n = settings.advanced.maxConcurrent;
2720
2756
  if (typeof n === "number" && Number.isFinite(n)) {
@@ -2802,7 +2838,7 @@ function childEnvWithAppSettings(extra) {
2802
2838
  function harnessEnvKey(harness) {
2803
2839
  return HARNESS_ENV_KEYS[harness];
2804
2840
  }
2805
- var import_node_crypto2, import_node_fs7, import_node_os3, import_node_path8, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, FOLLOW_UP_BEHAVIORS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, CONFIRM_ACCOUNT, CONFIRM_PROJECT, DEFAULT_CLI_BIN;
2841
+ var import_node_crypto2, import_node_fs7, import_node_os3, import_node_path8, 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;
2806
2842
  var init_app_settings = __esm({
2807
2843
  "src/store/app-settings.ts"() {
2808
2844
  "use strict";
@@ -2839,6 +2875,18 @@ var init_app_settings = __esm({
2839
2875
  ]);
2840
2876
  GITHUB_GIT_AUTH_MODES = ["auto", "gh", "ssh", "token"];
2841
2877
  FOLLOW_UP_BEHAVIORS = ["steer", "queue"];
2878
+ AGENT_DONE_SOUNDS = [
2879
+ "none",
2880
+ "goal",
2881
+ "bell",
2882
+ "level",
2883
+ "coin",
2884
+ "fanfare",
2885
+ "magic",
2886
+ "rooster",
2887
+ "whistle",
2888
+ "custom"
2889
+ ];
2842
2890
  CLOUD_CONNECT_AGENTS = /* @__PURE__ */ new Set([
2843
2891
  "claude",
2844
2892
  "codex",
@@ -2883,7 +2931,7 @@ function setCaffeinateHoldHooks(next) {
2883
2931
  hooks = next;
2884
2932
  }
2885
2933
  function caffeinateHoldPath() {
2886
- return (0, import_node_path9.join)(appDataDir(), "caffeinate-hold.json");
2934
+ return (0, import_node_path10.join)(appDataDir(), "caffeinate-hold.json");
2887
2935
  }
2888
2936
  function processAlive(pid) {
2889
2937
  if (hooks.processAlive) return hooks.processAlive(pid);
@@ -2917,9 +2965,9 @@ function uniqueIds(ids) {
2917
2965
  }
2918
2966
  function readHold() {
2919
2967
  const path2 = caffeinateHoldPath();
2920
- if (!(0, import_node_fs8.existsSync)(path2)) return null;
2968
+ if (!(0, import_node_fs9.existsSync)(path2)) return null;
2921
2969
  try {
2922
- const parsed = JSON.parse((0, import_node_fs8.readFileSync)(path2, "utf8"));
2970
+ const parsed = JSON.parse((0, import_node_fs9.readFileSync)(path2, "utf8"));
2923
2971
  if (typeof parsed?.pid === "number" && parsed.pid > 0) {
2924
2972
  return {
2925
2973
  pid: parsed.pid,
@@ -2941,7 +2989,7 @@ function writeHold(pid, threadIds) {
2941
2989
  }
2942
2990
  function clearHold() {
2943
2991
  try {
2944
- (0, import_node_fs8.unlinkSync)(caffeinateHoldPath());
2992
+ (0, import_node_fs9.unlinkSync)(caffeinateHoldPath());
2945
2993
  } catch {
2946
2994
  }
2947
2995
  }
@@ -3026,13 +3074,13 @@ function releaseCaffeinateHoldForThread(threadId) {
3026
3074
  }
3027
3075
  return setCaffeinateHold(false, { threadId: id });
3028
3076
  }
3029
- var import_node_child_process2, import_node_fs8, import_node_path9, hooks;
3077
+ var import_node_child_process2, import_node_fs9, import_node_path10, hooks;
3030
3078
  var init_caffeinate_hold = __esm({
3031
3079
  "src/store/caffeinate-hold.ts"() {
3032
3080
  "use strict";
3033
3081
  import_node_child_process2 = require("child_process");
3034
- import_node_fs8 = require("fs");
3035
- import_node_path9 = require("path");
3082
+ import_node_fs9 = require("fs");
3083
+ import_node_path10 = require("path");
3036
3084
  init_paths();
3037
3085
  init_private_file();
3038
3086
  hooks = {};
@@ -3041,13 +3089,13 @@ var init_caffeinate_hold = __esm({
3041
3089
 
3042
3090
  // src/agents/cursor-store.ts
3043
3091
  function cursorSdkStoreDir(threadId) {
3044
- const root = (0, import_node_path10.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
3092
+ const root = (0, import_node_path11.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
3045
3093
  const id = sanitizeCursorStoreSegment(threadId);
3046
3094
  if (!id) return root;
3047
- return (0, import_node_path10.join)(root, "threads", id);
3095
+ return (0, import_node_path11.join)(root, "threads", id);
3048
3096
  }
3049
3097
  function cursorSdkRunsNdjsonPath(threadId) {
3050
- return (0, import_node_path10.join)(cursorSdkStoreDir(threadId), "runs.ndjson");
3098
+ return (0, import_node_path11.join)(cursorSdkStoreDir(threadId), "runs.ndjson");
3051
3099
  }
3052
3100
  function cursorSdkRunsNdjsonSearchPaths(threadId) {
3053
3101
  const scoped = cursorSdkRunsNdjsonPath(threadId);
@@ -3060,11 +3108,11 @@ function cursorSdkRunsNdjsonSearchPaths(threadId) {
3060
3108
  function sanitizeCursorStoreSegment(threadId) {
3061
3109
  return (threadId ?? "").trim().replace(/[^a-zA-Z0-9._-]/g, "_");
3062
3110
  }
3063
- var import_node_path10, CURSOR_SDK_STORE_DIR;
3111
+ var import_node_path11, CURSOR_SDK_STORE_DIR;
3064
3112
  var init_cursor_store = __esm({
3065
3113
  "src/agents/cursor-store.ts"() {
3066
3114
  "use strict";
3067
- import_node_path10 = require("path");
3115
+ import_node_path11 = require("path");
3068
3116
  init_paths();
3069
3117
  CURSOR_SDK_STORE_DIR = "cursor-sdk-store";
3070
3118
  }
@@ -3099,6 +3147,22 @@ function resolveThreadEffort(raw) {
3099
3147
  if (raw.fast) return "low";
3100
3148
  return "high";
3101
3149
  }
3150
+ function normalizeRunScriptRequest(raw) {
3151
+ if (!raw || typeof raw !== "object") return void 0;
3152
+ const req = raw;
3153
+ if (req.op !== "start" && req.op !== "stop") return void 0;
3154
+ if (typeof req.requestId !== "string" || !req.requestId.trim()) return void 0;
3155
+ if (typeof req.requestedAt !== "string" || !req.requestedAt.trim()) return void 0;
3156
+ return {
3157
+ op: req.op,
3158
+ scriptName: req.scriptName ?? null,
3159
+ requestId: req.requestId,
3160
+ requestedAt: req.requestedAt,
3161
+ claimedAt: req.claimedAt ?? null,
3162
+ fulfilledAt: req.fulfilledAt ?? null,
3163
+ error: req.error ?? null
3164
+ };
3165
+ }
3102
3166
  function normalizeThread(raw) {
3103
3167
  return {
3104
3168
  ...raw,
@@ -3122,6 +3186,7 @@ function normalizeThread(raw) {
3122
3186
  stackLayer: raw.stackLayer ?? null,
3123
3187
  userSetTitle: Boolean(raw.userSetTitle),
3124
3188
  activeRuns: Array.isArray(raw.activeRuns) ? raw.activeRuns : [],
3189
+ runScriptRequest: normalizeRunScriptRequest(raw.runScriptRequest),
3125
3190
  quotaResumeAt: raw.quotaResumeAt ?? null,
3126
3191
  quotaContinuedFromId: raw.quotaContinuedFromId ?? null,
3127
3192
  archivedAt: typeof raw.archivedAt === "string" && raw.archivedAt.trim() ? raw.archivedAt.trim() : void 0
@@ -3174,7 +3239,7 @@ function createEmptyThread(partial) {
3174
3239
  }
3175
3240
  async function withThreadLock(id, fn) {
3176
3241
  const lockPath = threadLockPath(id);
3177
- (0, import_node_fs9.writeFileSync)(lockPath, "", { flag: "a" });
3242
+ (0, import_node_fs10.writeFileSync)(lockPath, "", { flag: "a" });
3178
3243
  let release;
3179
3244
  try {
3180
3245
  release = await import_proper_lockfile.default.lock(lockPath, {
@@ -3195,7 +3260,7 @@ function cacheForDir() {
3195
3260
  }
3196
3261
  function fileMtimeMs(path2) {
3197
3262
  try {
3198
- return (0, import_node_fs9.statSync)(path2).mtimeMs;
3263
+ return (0, import_node_fs10.statSync)(path2).mtimeMs;
3199
3264
  } catch {
3200
3265
  return null;
3201
3266
  }
@@ -3228,7 +3293,7 @@ function readThread(id) {
3228
3293
  const cache2 = cacheForDir();
3229
3294
  const cached = cache2.byId.get(id);
3230
3295
  if (cached && cache2.mtimeMs.get(id) === mtimeMs) return cached;
3231
- const raw = (0, import_node_fs9.readFileSync)(path2, "utf8");
3296
+ const raw = (0, import_node_fs10.readFileSync)(path2, "utf8");
3232
3297
  const thread = normalizeThread(JSON.parse(raw));
3233
3298
  rememberThread(thread, mtimeMs);
3234
3299
  return thread;
@@ -3237,8 +3302,8 @@ function writeThread(thread, opts) {
3237
3302
  const path2 = threadFilePath(idPath(thread.id));
3238
3303
  const tmp = `${path2}.${process.pid}.tmp`;
3239
3304
  const next = opts?.touch === false ? { ...thread } : { ...thread, updatedAt: nowIso() };
3240
- (0, import_node_fs9.writeFileSync)(tmp, JSON.stringify(next, null, 2), "utf8");
3241
- (0, import_node_fs9.renameSync)(tmp, path2);
3305
+ (0, import_node_fs10.writeFileSync)(tmp, JSON.stringify(next, null, 2), "utf8");
3306
+ (0, import_node_fs10.renameSync)(tmp, path2);
3242
3307
  const mtimeMs = fileMtimeMs(path2) ?? Date.now();
3243
3308
  rememberThread(next, mtimeMs);
3244
3309
  selfWriteMtimes.set(thread.id, mtimeMs);
@@ -3252,12 +3317,12 @@ function idPath(id) {
3252
3317
  return id;
3253
3318
  }
3254
3319
  function isThreadRecordFile(nameOrPath) {
3255
- const name = (0, import_node_path11.basename)(nameOrPath);
3320
+ const name = (0, import_node_path12.basename)(nameOrPath);
3256
3321
  return name.endsWith(".json") && !name.endsWith(".live.json") && !name.endsWith(".setup.log.json");
3257
3322
  }
3258
3323
  function listThreads(opts) {
3259
3324
  const cache2 = cacheForDir();
3260
- const files = (0, import_node_fs9.readdirSync)(threadsDir()).filter(isThreadRecordFile);
3325
+ const files = (0, import_node_fs10.readdirSync)(threadsDir()).filter(isThreadRecordFile);
3261
3326
  const seen = /* @__PURE__ */ new Set();
3262
3327
  for (const f of files) {
3263
3328
  const id = f.replace(/\.json$/, "");
@@ -3280,16 +3345,16 @@ function listThreads(opts) {
3280
3345
  function deleteThreadRecord(id) {
3281
3346
  forgetThread(id);
3282
3347
  const path2 = threadFilePath(id);
3283
- if ((0, import_node_fs9.existsSync)(path2)) (0, import_node_fs9.unlinkSync)(path2);
3348
+ if ((0, import_node_fs10.existsSync)(path2)) (0, import_node_fs10.unlinkSync)(path2);
3284
3349
  const lock = threadLockPath(id);
3285
- if ((0, import_node_fs9.existsSync)(lock)) {
3350
+ if ((0, import_node_fs10.existsSync)(lock)) {
3286
3351
  try {
3287
- (0, import_node_fs9.unlinkSync)(lock);
3352
+ (0, import_node_fs10.unlinkSync)(lock);
3288
3353
  } catch {
3289
3354
  }
3290
3355
  }
3291
3356
  try {
3292
- (0, import_node_fs9.rmSync)(cursorSdkStoreDir(id), { recursive: true, force: true });
3357
+ (0, import_node_fs10.rmSync)(cursorSdkStoreDir(id), { recursive: true, force: true });
3293
3358
  } catch {
3294
3359
  }
3295
3360
  }
@@ -3319,13 +3384,13 @@ function findThreadByRef(ref) {
3319
3384
  (t) => t.id === ref || t.id.startsWith(ref) || t.branchName === ref || t.title === ref
3320
3385
  ) ?? null;
3321
3386
  }
3322
- var import_node_crypto3, import_node_fs9, import_node_path11, import_proper_lockfile, listCache, selfWriteMtimes;
3387
+ var import_node_crypto3, import_node_fs10, import_node_path12, import_proper_lockfile, listCache, selfWriteMtimes;
3323
3388
  var init_thread_store = __esm({
3324
3389
  "src/store/thread-store.ts"() {
3325
3390
  "use strict";
3326
3391
  import_node_crypto3 = require("crypto");
3327
- import_node_fs9 = require("fs");
3328
- import_node_path11 = require("path");
3392
+ import_node_fs10 = require("fs");
3393
+ import_node_path12 = require("path");
3329
3394
  import_proper_lockfile = __toESM(require("proper-lockfile"), 1);
3330
3395
  init_thinking_effort();
3331
3396
  init_cursor_store();
@@ -3810,6 +3875,13 @@ function toolDescription(name, input) {
3810
3875
  if (/stop_job$/i.test(name)) {
3811
3876
  return str(input?.id) ? `Stop ${str(input?.id)}` : "Stop job";
3812
3877
  }
3878
+ if (/list_run_scripts$/i.test(name)) return "List run scripts";
3879
+ if (/run_dev_script$/i.test(name)) {
3880
+ return str(input?.name) ? `Start ${str(input?.name)}` : "Start Dev script";
3881
+ }
3882
+ if (/stop_dev_script$/i.test(name)) {
3883
+ return str(input?.name) ? `Stop ${str(input?.name)}` : "Stop Dev script";
3884
+ }
3813
3885
  if (isSubagentToolName(name)) {
3814
3886
  const desc = str(input?.description);
3815
3887
  const sub = asRecord(input?.subagentType);
@@ -5790,7 +5862,7 @@ function materialize(mem) {
5790
5862
  };
5791
5863
  }
5792
5864
  function setupLogPath(threadId) {
5793
- return (0, import_node_path12.join)(threadsDir(), `${threadId}.setup.log.json`);
5865
+ return (0, import_node_path13.join)(threadsDir(), `${threadId}.setup.log.json`);
5794
5866
  }
5795
5867
  function setupLogKeyForWorktree(worktreePath) {
5796
5868
  const norm = normalizeWorktreePath(worktreePath);
@@ -5816,7 +5888,7 @@ function persistNow(threadId) {
5816
5888
  const mem = memory.get(threadId);
5817
5889
  if (!mem) return;
5818
5890
  try {
5819
- (0, import_node_fs10.writeFileSync)(
5891
+ (0, import_node_fs11.writeFileSync)(
5820
5892
  setupLogPath(threadId),
5821
5893
  `${JSON.stringify(materialize(mem))}
5822
5894
  `,
@@ -5837,9 +5909,9 @@ function schedulePersist(threadId) {
5837
5909
  }
5838
5910
  function loadFromDisk(threadId) {
5839
5911
  const path2 = setupLogPath(threadId);
5840
- if (!(0, import_node_fs10.existsSync)(path2)) return null;
5912
+ if (!(0, import_node_fs11.existsSync)(path2)) return null;
5841
5913
  try {
5842
- const raw = JSON.parse((0, import_node_fs10.readFileSync)(path2, "utf8"));
5914
+ const raw = JSON.parse((0, import_node_fs11.readFileSync)(path2, "utf8"));
5843
5915
  return {
5844
5916
  output: typeof raw.output === "string" ? raw.output : "",
5845
5917
  running: Boolean(raw.running),
@@ -5895,13 +5967,13 @@ function finishSetupLog(threadId, exitCode, source) {
5895
5967
  persistNow(threadId);
5896
5968
  return materialize(mem);
5897
5969
  }
5898
- var import_node_crypto4, import_node_fs10, import_node_path12, EMPTY, MAX_SETUP_LOG_CHARS, memory, persistTimers, PERSIST_DEBOUNCE_MS;
5970
+ var import_node_crypto4, import_node_fs11, import_node_path13, EMPTY, MAX_SETUP_LOG_CHARS, memory, persistTimers, PERSIST_DEBOUNCE_MS;
5899
5971
  var init_setup_log = __esm({
5900
5972
  "src/store/setup-log.ts"() {
5901
5973
  "use strict";
5902
5974
  import_node_crypto4 = require("crypto");
5903
- import_node_fs10 = require("fs");
5904
- import_node_path12 = require("path");
5975
+ import_node_fs11 = require("fs");
5976
+ import_node_path13 = require("path");
5905
5977
  init_worktree_labels();
5906
5978
  init_paths();
5907
5979
  EMPTY = {
@@ -5919,7 +5991,7 @@ var init_setup_log = __esm({
5919
5991
 
5920
5992
  // src/store/schedules.ts
5921
5993
  function schedulesPath() {
5922
- return (0, import_node_path13.join)(appDataDir(), "schedules.json");
5994
+ return (0, import_node_path14.join)(appDataDir(), "schedules.json");
5923
5995
  }
5924
5996
  function parseDurationMs(every) {
5925
5997
  const m = every.trim().match(DURATION_RE);
@@ -6025,9 +6097,9 @@ function normalizeTask(raw) {
6025
6097
  }
6026
6098
  function readAll() {
6027
6099
  const path2 = schedulesPath();
6028
- if (!(0, import_node_fs11.existsSync)(path2)) return [];
6100
+ if (!(0, import_node_fs12.existsSync)(path2)) return [];
6029
6101
  try {
6030
- const parsed = JSON.parse((0, import_node_fs11.readFileSync)(path2, "utf8"));
6102
+ const parsed = JSON.parse((0, import_node_fs12.readFileSync)(path2, "utf8"));
6031
6103
  if (!Array.isArray(parsed)) return [];
6032
6104
  return parsed.map((row) => {
6033
6105
  try {
@@ -6142,13 +6214,13 @@ function recordScheduleRun(id, result) {
6142
6214
  writeAll(rows);
6143
6215
  return next;
6144
6216
  }
6145
- var import_node_crypto5, import_node_fs11, import_node_path13, import_croner, DURATION_RE, UNIT_MS;
6217
+ var import_node_crypto5, import_node_fs12, import_node_path14, import_croner, DURATION_RE, UNIT_MS;
6146
6218
  var init_schedules = __esm({
6147
6219
  "src/store/schedules.ts"() {
6148
6220
  "use strict";
6149
6221
  import_node_crypto5 = require("crypto");
6150
- import_node_fs11 = require("fs");
6151
- import_node_path13 = require("path");
6222
+ import_node_fs12 = require("fs");
6223
+ import_node_path14 = require("path");
6152
6224
  import_croner = require("croner");
6153
6225
  init_orchestrator_capable();
6154
6226
  init_paths();
@@ -6165,22 +6237,22 @@ var init_schedules = __esm({
6165
6237
 
6166
6238
  // src/store/desktop-host.ts
6167
6239
  function desktopHostPidPath() {
6168
- return (0, import_node_path14.join)(appDataDir(), "desktop-host.pid");
6240
+ return (0, import_node_path15.join)(appDataDir(), "desktop-host.pid");
6169
6241
  }
6170
6242
  function claimDesktopHost(pid = process.pid) {
6171
- (0, import_node_fs12.writeFileSync)(desktopHostPidPath(), `${pid}
6243
+ (0, import_node_fs13.writeFileSync)(desktopHostPidPath(), `${pid}
6172
6244
  `, "utf8");
6173
6245
  }
6174
6246
  function releaseDesktopHost(pid = process.pid) {
6175
6247
  if (readDesktopHostPid() !== pid) return;
6176
6248
  try {
6177
- (0, import_node_fs12.unlinkSync)(desktopHostPidPath());
6249
+ (0, import_node_fs13.unlinkSync)(desktopHostPidPath());
6178
6250
  } catch {
6179
6251
  }
6180
6252
  }
6181
6253
  function readDesktopHostPid() {
6182
6254
  try {
6183
- const pid = Number.parseInt((0, import_node_fs12.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
6255
+ const pid = Number.parseInt((0, import_node_fs13.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
6184
6256
  if (!Number.isFinite(pid) || pid <= 0) return null;
6185
6257
  return pid;
6186
6258
  } catch {
@@ -6206,12 +6278,12 @@ function thisProcessShouldDrainAgentQueues() {
6206
6278
  if (isThisProcessDesktopHost()) return true;
6207
6279
  return !isDesktopHostAlive();
6208
6280
  }
6209
- var import_node_fs12, import_node_path14;
6281
+ var import_node_fs13, import_node_path15;
6210
6282
  var init_desktop_host = __esm({
6211
6283
  "src/store/desktop-host.ts"() {
6212
6284
  "use strict";
6213
- import_node_fs12 = require("fs");
6214
- import_node_path14 = require("path");
6285
+ import_node_fs13 = require("fs");
6286
+ import_node_path15 = require("path");
6215
6287
  init_paths();
6216
6288
  }
6217
6289
  });
@@ -6278,7 +6350,7 @@ var init_workspace_scratch = __esm({
6278
6350
 
6279
6351
  // src/composer/stage-files.ts
6280
6352
  function fileExtension(filePath) {
6281
- const base = (0, import_node_path15.basename)(filePath).toLowerCase();
6353
+ const base = (0, import_node_path16.basename)(filePath).toLowerCase();
6282
6354
  return base.includes(".") ? base.split(".").pop() || "" : "";
6283
6355
  }
6284
6356
  function isImageFilePath(filePath) {
@@ -6288,22 +6360,22 @@ function imageMimeType(filePath) {
6288
6360
  return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
6289
6361
  }
6290
6362
  function ensureAttachmentsDir(worktreePath) {
6291
- const dir = (0, import_node_path15.join)(worktreePath, ATTACHMENTS_DIR);
6292
- (0, import_node_fs13.mkdirSync)(dir, { recursive: true });
6293
- const gi = (0, import_node_path15.join)(dir, ".gitignore");
6294
- if (!(0, import_node_fs13.existsSync)(gi)) {
6295
- (0, import_node_fs13.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
6363
+ const dir = (0, import_node_path16.join)(worktreePath, ATTACHMENTS_DIR);
6364
+ (0, import_node_fs14.mkdirSync)(dir, { recursive: true });
6365
+ const gi = (0, import_node_path16.join)(dir, ".gitignore");
6366
+ if (!(0, import_node_fs14.existsSync)(gi)) {
6367
+ (0, import_node_fs14.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
6296
6368
  }
6297
6369
  return dir;
6298
6370
  }
6299
6371
  function uniqueAttachmentName(dir, originalName) {
6300
6372
  const safe = originalName.replace(/[/\\]/g, "_") || "file";
6301
- if (!(0, import_node_fs13.existsSync)((0, import_node_path15.join)(dir, safe))) return safe;
6302
- const ext = (0, import_node_path15.extname)(safe);
6373
+ if (!(0, import_node_fs14.existsSync)((0, import_node_path16.join)(dir, safe))) return safe;
6374
+ const ext = (0, import_node_path16.extname)(safe);
6303
6375
  const stem = ext ? safe.slice(0, -ext.length) : safe;
6304
6376
  for (let i = 1; i < 1e4; i++) {
6305
6377
  const candidate = `${stem}-${i}${ext}`;
6306
- if (!(0, import_node_fs13.existsSync)((0, import_node_path15.join)(dir, candidate))) return candidate;
6378
+ if (!(0, import_node_fs14.existsSync)((0, import_node_path16.join)(dir, candidate))) return candidate;
6307
6379
  }
6308
6380
  return `${stem}-${(0, import_node_crypto6.randomUUID)()}${ext}`;
6309
6381
  }
@@ -6355,9 +6427,9 @@ function attachmentFromBuffer(name, buf, opts) {
6355
6427
  };
6356
6428
  }
6357
6429
  function attachmentFromAbsolutePath(absolutePath) {
6358
- const name = (0, import_node_path15.basename)(absolutePath);
6430
+ const name = (0, import_node_path16.basename)(absolutePath);
6359
6431
  try {
6360
- const st = (0, import_node_fs13.statSync)(absolutePath);
6432
+ const st = (0, import_node_fs14.statSync)(absolutePath);
6361
6433
  if (!st.isFile()) {
6362
6434
  return {
6363
6435
  id: (0, import_node_crypto6.randomUUID)(),
@@ -6366,7 +6438,7 @@ function attachmentFromAbsolutePath(absolutePath) {
6366
6438
  content: `(not a file: ${absolutePath})`
6367
6439
  };
6368
6440
  }
6369
- const buf = (0, import_node_fs13.readFileSync)(absolutePath);
6441
+ const buf = (0, import_node_fs14.readFileSync)(absolutePath);
6370
6442
  return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
6371
6443
  } catch (err) {
6372
6444
  return {
@@ -6382,15 +6454,15 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
6382
6454
  const dir = ensureAttachmentsDir(worktreePath);
6383
6455
  const out = [];
6384
6456
  for (const abs of absolutePaths) {
6385
- const originalName = (0, import_node_path15.basename)(abs);
6457
+ const originalName = (0, import_node_path16.basename)(abs);
6386
6458
  try {
6387
- const st = (0, import_node_fs13.statSync)(abs);
6459
+ const st = (0, import_node_fs14.statSync)(abs);
6388
6460
  if (!st.isFile()) continue;
6389
6461
  const name = uniqueAttachmentName(dir, originalName);
6390
- const destAbs = (0, import_node_path15.join)(dir, name);
6391
- (0, import_node_fs13.copyFileSync)(abs, destAbs);
6462
+ const destAbs = (0, import_node_path16.join)(dir, name);
6463
+ (0, import_node_fs14.copyFileSync)(abs, destAbs);
6392
6464
  const rel = `${ATTACHMENTS_DIR}/${name}`;
6393
- const buf = (0, import_node_fs13.readFileSync)(destAbs);
6465
+ const buf = (0, import_node_fs14.readFileSync)(destAbs);
6394
6466
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
6395
6467
  } catch (err) {
6396
6468
  out.push({
@@ -6412,8 +6484,8 @@ function stageBuffersAsAttachments(worktreePath, buffers2) {
6412
6484
  try {
6413
6485
  const buf = Buffer.from(item.dataBase64, "base64");
6414
6486
  const name = uniqueAttachmentName(dir, originalName);
6415
- const destAbs = (0, import_node_path15.join)(dir, name);
6416
- (0, import_node_fs13.writeFileSync)(destAbs, buf);
6487
+ const destAbs = (0, import_node_path16.join)(dir, name);
6488
+ (0, import_node_fs14.writeFileSync)(destAbs, buf);
6417
6489
  const rel = `${ATTACHMENTS_DIR}/${name}`;
6418
6490
  out.push(attachmentFromBuffer(name, buf, { path: rel }));
6419
6491
  } catch (err) {
@@ -6490,18 +6562,18 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
6490
6562
  if (!rel || rel.includes("..") || rel.startsWith("/")) {
6491
6563
  out.push({
6492
6564
  id: (0, import_node_crypto6.randomUUID)(),
6493
- name: (0, import_node_path15.basename)(rel) || "file",
6565
+ name: (0, import_node_path16.basename)(rel) || "file",
6494
6566
  kind: "file",
6495
6567
  content: `(invalid path: ${rel})`
6496
6568
  });
6497
6569
  continue;
6498
6570
  }
6499
- const name = (0, import_node_path15.basename)(rel);
6571
+ const name = (0, import_node_path16.basename)(rel);
6500
6572
  try {
6501
- const abs = (0, import_node_path15.join)(worktreePath, rel);
6502
- const st = (0, import_node_fs13.statSync)(abs);
6573
+ const abs = (0, import_node_path16.join)(worktreePath, rel);
6574
+ const st = (0, import_node_fs14.statSync)(abs);
6503
6575
  if (!st.isFile()) continue;
6504
- const buf = (0, import_node_fs13.readFileSync)(abs);
6576
+ const buf = (0, import_node_fs14.readFileSync)(abs);
6505
6577
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
6506
6578
  } catch (err) {
6507
6579
  out.push({
@@ -6514,12 +6586,12 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
6514
6586
  }
6515
6587
  return out;
6516
6588
  }
6517
- var import_node_fs13, import_node_path15, import_node_crypto6, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
6589
+ var import_node_fs14, import_node_path16, import_node_crypto6, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
6518
6590
  var init_stage_files = __esm({
6519
6591
  "src/composer/stage-files.ts"() {
6520
6592
  "use strict";
6521
- import_node_fs13 = require("fs");
6522
- import_node_path15 = require("path");
6593
+ import_node_fs14 = require("fs");
6594
+ import_node_path16 = require("path");
6523
6595
  import_node_crypto6 = require("crypto");
6524
6596
  init_workspace_scratch();
6525
6597
  IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
@@ -6661,17 +6733,17 @@ var init_gh_errors = __esm({
6661
6733
 
6662
6734
  // src/agents/path.ts
6663
6735
  function prependPathDir(env, dir) {
6664
- if (!dir || !(0, import_node_fs14.existsSync)(dir)) return;
6736
+ if (!dir || !(0, import_node_fs15.existsSync)(dir)) return;
6665
6737
  const current = env.PATH ?? "";
6666
- const parts = current.split(import_node_path16.delimiter).filter(Boolean);
6738
+ const parts = current.split(import_node_path17.delimiter).filter(Boolean);
6667
6739
  if (parts.includes(dir)) {
6668
6740
  env.PATH = current;
6669
6741
  return;
6670
6742
  }
6671
- env.PATH = [dir, ...parts].join(import_node_path16.delimiter);
6743
+ env.PATH = [dir, ...parts].join(import_node_path17.delimiter);
6672
6744
  }
6673
6745
  function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os4.homedir)()) {
6674
- return (0, import_node_path16.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
6746
+ return (0, import_node_path17.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
6675
6747
  }
6676
6748
  function isConductorBundledCli(filePath) {
6677
6749
  const p = (filePath ?? "").replace(/\\/g, "/");
@@ -6680,21 +6752,21 @@ function isConductorBundledCli(filePath) {
6680
6752
  function ensureAgentPath(env = process.env) {
6681
6753
  const home = env.HOME || env.USERPROFILE || (0, import_node_os4.homedir)();
6682
6754
  const current = env.PATH ?? "";
6683
- const parts = current.split(import_node_path16.delimiter).filter(Boolean);
6755
+ const parts = current.split(import_node_path17.delimiter).filter(Boolean);
6684
6756
  const seen = new Set(parts);
6685
6757
  const extras = [
6686
- ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path16.join)(home, rel)),
6758
+ ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path17.join)(home, rel)),
6687
6759
  "/opt/homebrew/bin",
6688
6760
  "/usr/local/bin",
6689
6761
  // Keep after Homebrew/npm so a user-installed CLI still wins.
6690
6762
  conductorBundledBinDir(home)
6691
6763
  ];
6692
6764
  for (const dir of extras.reverse()) {
6693
- if (!dir || seen.has(dir) || !(0, import_node_fs14.existsSync)(dir)) continue;
6765
+ if (!dir || seen.has(dir) || !(0, import_node_fs15.existsSync)(dir)) continue;
6694
6766
  parts.unshift(dir);
6695
6767
  seen.add(dir);
6696
6768
  }
6697
- const next = parts.join(import_node_path16.delimiter);
6769
+ const next = parts.join(import_node_path17.delimiter);
6698
6770
  env.PATH = next;
6699
6771
  return next;
6700
6772
  }
@@ -6708,7 +6780,7 @@ function enrichPathWithNpmGlobalBin(env = process.env) {
6708
6780
  stdio: ["ignore", "pipe", "ignore"]
6709
6781
  }).trim().split(/\r?\n/).find(Boolean);
6710
6782
  if (prefix) {
6711
- const binDir = process.platform === "win32" ? prefix : (0, import_node_path16.join)(prefix, "bin");
6783
+ const binDir = process.platform === "win32" ? prefix : (0, import_node_path17.join)(prefix, "bin");
6712
6784
  prependPathDir(env, binDir);
6713
6785
  }
6714
6786
  } catch {
@@ -6736,14 +6808,14 @@ function withExportedPath(command, pathValue) {
6736
6808
  if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
6737
6809
  return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
6738
6810
  }
6739
- var import_node_fs14, import_node_child_process3, import_node_os4, import_node_path16, EXTRA_BIN_DIRS;
6811
+ var import_node_fs15, import_node_child_process3, import_node_os4, import_node_path17, EXTRA_BIN_DIRS;
6740
6812
  var init_path = __esm({
6741
6813
  "src/agents/path.ts"() {
6742
6814
  "use strict";
6743
- import_node_fs14 = require("fs");
6815
+ import_node_fs15 = require("fs");
6744
6816
  import_node_child_process3 = require("child_process");
6745
6817
  import_node_os4 = require("os");
6746
- import_node_path16 = require("path");
6818
+ import_node_path17 = require("path");
6747
6819
  EXTRA_BIN_DIRS = [
6748
6820
  ".local/bin",
6749
6821
  ".cargo/bin",
@@ -6764,23 +6836,23 @@ var init_path = __esm({
6764
6836
  function githubAgentAuthDir() {
6765
6837
  const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
6766
6838
  if (override) return override;
6767
- return (0, import_node_path17.join)((0, import_node_os5.homedir)(), ".sideboard-git-auth");
6839
+ return (0, import_node_path18.join)((0, import_node_os5.homedir)(), ".sideboard-git-auth");
6768
6840
  }
6769
6841
  function githubCredentialStorePath() {
6770
- return (0, import_node_path17.join)(githubAgentAuthDir(), "git-credentials");
6842
+ return (0, import_node_path18.join)(githubAgentAuthDir(), "git-credentials");
6771
6843
  }
6772
6844
  function githubGhConfigDir() {
6773
- return (0, import_node_path17.join)(githubAgentAuthDir(), "gh");
6845
+ return (0, import_node_path18.join)(githubAgentAuthDir(), "gh");
6774
6846
  }
6775
6847
  function writePrivateFile2(file, body) {
6776
- (0, import_node_fs15.mkdirSync)((0, import_node_path17.dirname)(file), { recursive: true, mode: 448 });
6848
+ (0, import_node_fs16.mkdirSync)((0, import_node_path18.dirname)(file), { recursive: true, mode: 448 });
6777
6849
  try {
6778
- (0, import_node_fs15.chmodSync)((0, import_node_path17.dirname)(file), 448);
6850
+ (0, import_node_fs16.chmodSync)((0, import_node_path18.dirname)(file), 448);
6779
6851
  } catch {
6780
6852
  }
6781
- (0, import_node_fs15.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
6853
+ (0, import_node_fs16.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
6782
6854
  try {
6783
- (0, import_node_fs15.chmodSync)(file, 384);
6855
+ (0, import_node_fs16.chmodSync)(file, 384);
6784
6856
  } catch {
6785
6857
  }
6786
6858
  }
@@ -6805,19 +6877,19 @@ function materializeGithubAgentAuth(token, user) {
6805
6877
  const trimmed = token.trim();
6806
6878
  if (!trimmed) return;
6807
6879
  const root = githubAgentAuthDir();
6808
- (0, import_node_fs15.mkdirSync)(root, { recursive: true, mode: 448 });
6880
+ (0, import_node_fs16.mkdirSync)(root, { recursive: true, mode: 448 });
6809
6881
  try {
6810
- (0, import_node_fs15.chmodSync)(root, 448);
6882
+ (0, import_node_fs16.chmodSync)(root, 448);
6811
6883
  } catch {
6812
6884
  }
6813
6885
  writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
6814
6886
  const ghDir = githubGhConfigDir();
6815
- (0, import_node_fs15.mkdirSync)(ghDir, { recursive: true, mode: 448 });
6816
- writePrivateFile2((0, import_node_path17.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
6817
- writePrivateFile2((0, import_node_path17.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
6887
+ (0, import_node_fs16.mkdirSync)(ghDir, { recursive: true, mode: 448 });
6888
+ writePrivateFile2((0, import_node_path18.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
6889
+ writePrivateFile2((0, import_node_path18.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
6818
6890
  }
6819
6891
  function githubAgentAuthReady() {
6820
- return (0, import_node_fs15.existsSync)(githubCredentialStorePath()) && (0, import_node_fs15.existsSync)((0, import_node_path17.join)(githubGhConfigDir(), "hosts.yml"));
6892
+ return (0, import_node_fs16.existsSync)(githubCredentialStorePath()) && (0, import_node_fs16.existsSync)((0, import_node_path18.join)(githubGhConfigDir(), "hosts.yml"));
6821
6893
  }
6822
6894
  function githubCredentialHelperGitConfig() {
6823
6895
  const file = githubCredentialStorePath();
@@ -6832,13 +6904,13 @@ function githubGhConfigEnv() {
6832
6904
  GH_PROMPT_DISABLED: "1"
6833
6905
  };
6834
6906
  }
6835
- var import_node_fs15, import_node_os5, import_node_path17;
6907
+ var import_node_fs16, import_node_os5, import_node_path18;
6836
6908
  var init_github_agent_auth = __esm({
6837
6909
  "src/git/github-agent-auth.ts"() {
6838
6910
  "use strict";
6839
- import_node_fs15 = require("fs");
6911
+ import_node_fs16 = require("fs");
6840
6912
  import_node_os5 = require("os");
6841
- import_node_path17 = require("path");
6913
+ import_node_path18 = require("path");
6842
6914
  }
6843
6915
  });
6844
6916
 
@@ -6847,11 +6919,11 @@ function isIndexLockError(text7) {
6847
6919
  return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text7);
6848
6920
  }
6849
6921
  function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
6850
- const lockPath = (0, import_node_path18.join)(gitDir, "index.lock");
6922
+ const lockPath = (0, import_node_path19.join)(gitDir, "index.lock");
6851
6923
  try {
6852
- if (!(0, import_node_fs16.existsSync)(lockPath)) return null;
6853
- if (now - (0, import_node_fs16.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
6854
- (0, import_node_fs16.unlinkSync)(lockPath);
6924
+ if (!(0, import_node_fs17.existsSync)(lockPath)) return null;
6925
+ if (now - (0, import_node_fs17.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
6926
+ (0, import_node_fs17.unlinkSync)(lockPath);
6855
6927
  return lockPath;
6856
6928
  } catch {
6857
6929
  return null;
@@ -6866,12 +6938,12 @@ function clearStaleIndexLocks(gitDirs, maxAgeMs = STALE_INDEX_LOCK_MS) {
6866
6938
  }
6867
6939
  return removed;
6868
6940
  }
6869
- var import_node_fs16, import_node_path18, STALE_INDEX_LOCK_MS;
6941
+ var import_node_fs17, import_node_path19, STALE_INDEX_LOCK_MS;
6870
6942
  var init_stale_lock = __esm({
6871
6943
  "src/git/stale-lock.ts"() {
6872
6944
  "use strict";
6873
- import_node_fs16 = require("fs");
6874
- import_node_path18 = require("path");
6945
+ import_node_fs17 = require("fs");
6946
+ import_node_path19 = require("path");
6875
6947
  STALE_INDEX_LOCK_MS = 2e4;
6876
6948
  }
6877
6949
  });
@@ -7012,11 +7084,11 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
7012
7084
  if (gitDir.exitCode !== 0) return;
7013
7085
  const dir = gitDir.stdout.trim();
7014
7086
  if (!dir) return;
7015
- const excludePath = (0, import_node_path19.join)(dir, "info", "exclude");
7016
- (0, import_node_fs17.mkdirSync)((0, import_node_path19.dirname)(excludePath), { recursive: true });
7087
+ const excludePath = (0, import_node_path20.join)(dir, "info", "exclude");
7088
+ (0, import_node_fs18.mkdirSync)((0, import_node_path20.dirname)(excludePath), { recursive: true });
7017
7089
  let body = "";
7018
7090
  try {
7019
- body = (0, import_node_fs17.readFileSync)(excludePath, "utf8");
7091
+ body = (0, import_node_fs18.readFileSync)(excludePath, "utf8");
7020
7092
  } catch {
7021
7093
  body = "";
7022
7094
  }
@@ -7032,7 +7104,7 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
7032
7104
  ` : body;
7033
7105
  const header = body.includes(EXCLUDE_COMMENT) ? "" : `${EXCLUDE_COMMENT}
7034
7106
  `;
7035
- (0, import_node_fs17.writeFileSync)(excludePath, `${prefix}${header}${missing.join("\n")}
7107
+ (0, import_node_fs18.writeFileSync)(excludePath, `${prefix}${header}${missing.join("\n")}
7036
7108
  `, "utf8");
7037
7109
  }
7038
7110
  const listed = await git(["ls-files", "-z", "--", ".sideboard"], worktreePath, {
@@ -7047,12 +7119,12 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
7047
7119
  timeoutMs: 8e3
7048
7120
  });
7049
7121
  }
7050
- var import_node_fs17, import_node_path19, WORKTREE_SIDEBOARD_EXCLUDE, WORKTREE_CONTEXT_EXCLUDE, EXCLUDE_COMMENT;
7122
+ var import_node_fs18, import_node_path20, WORKTREE_SIDEBOARD_EXCLUDE, WORKTREE_CONTEXT_EXCLUDE, EXCLUDE_COMMENT;
7051
7123
  var init_worktree_exclude = __esm({
7052
7124
  "src/git/worktree-exclude.ts"() {
7053
7125
  "use strict";
7054
- import_node_fs17 = require("fs");
7055
- import_node_path19 = require("path");
7126
+ import_node_fs18 = require("fs");
7127
+ import_node_path20 = require("path");
7056
7128
  init_run();
7057
7129
  WORKTREE_SIDEBOARD_EXCLUDE = ".sideboard/";
7058
7130
  WORKTREE_CONTEXT_EXCLUDE = ".context/";
@@ -7173,7 +7245,7 @@ async function warmGithubAgentAuth(opts) {
7173
7245
  }
7174
7246
  function normalizeWritableRoot(raw) {
7175
7247
  const trimmed = raw.trim().replace(/\/+$/, "");
7176
- return trimmed && (0, import_node_path20.isAbsolute)(trimmed) ? trimmed : null;
7248
+ return trimmed && (0, import_node_path21.isAbsolute)(trimmed) ? trimmed : null;
7177
7249
  }
7178
7250
  async function resolveCodexGitWritableRoots(cwd) {
7179
7251
  const roots = /* @__PURE__ */ new Set();
@@ -7251,11 +7323,11 @@ function formatGitAuthModeDirective(mode) {
7251
7323
  ].join("\n");
7252
7324
  }
7253
7325
  }
7254
- var import_node_path20, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
7326
+ var import_node_path21, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
7255
7327
  var init_git_auth_mode = __esm({
7256
7328
  "src/git/git-auth-mode.ts"() {
7257
7329
  "use strict";
7258
- import_node_path20 = require("path");
7330
+ import_node_path21 = require("path");
7259
7331
  init_app_settings();
7260
7332
  init_github_agent_auth();
7261
7333
  init_run();
@@ -8091,7 +8163,7 @@ async function resolveRepoRoot(cwd) {
8091
8163
  }
8092
8164
  function canonicalizeRepoPath(path2) {
8093
8165
  try {
8094
- return (0, import_node_fs18.realpathSync)(path2);
8166
+ return (0, import_node_fs19.realpathSync)(path2);
8095
8167
  } catch {
8096
8168
  return path2.replace(/\/+$/, "");
8097
8169
  }
@@ -8952,8 +9024,8 @@ async function refreshOriginAndMaybeFastForwardMain(repoPath, sourceRef) {
8952
9024
  }
8953
9025
  async function createThreadWorktree(opts) {
8954
9026
  let branchName = `thread/${opts.slug}`;
8955
- const worktreePath = (0, import_node_path21.join)(worktreesRoot(opts.repoPath), opts.slug);
8956
- if ((0, import_node_fs18.existsSync)(worktreePath)) {
9027
+ const worktreePath = (0, import_node_path22.join)(worktreesRoot(opts.repoPath), opts.slug);
9028
+ if ((0, import_node_fs19.existsSync)(worktreePath)) {
8957
9029
  throw new Error(`Worktree already exists at ${worktreePath}`);
8958
9030
  }
8959
9031
  await ensureGhPreferOrigin(opts.repoPath);
@@ -8994,8 +9066,8 @@ ${add.stdout}`;
8994
9066
  async function createExistingBranchWorktree(opts) {
8995
9067
  const branchName = opts.branchName.trim();
8996
9068
  if (!branchName) throw new Error("branch name required");
8997
- const worktreePath = (0, import_node_path21.join)(worktreesRoot(opts.repoPath), opts.slug);
8998
- if ((0, import_node_fs18.existsSync)(worktreePath)) {
9069
+ const worktreePath = (0, import_node_path22.join)(worktreesRoot(opts.repoPath), opts.slug);
9070
+ if ((0, import_node_fs19.existsSync)(worktreePath)) {
8999
9071
  throw new Error(`Worktree already exists at ${worktreePath}`);
9000
9072
  }
9001
9073
  await ensureGhPreferOrigin(opts.repoPath);
@@ -9276,11 +9348,11 @@ async function createOrUpdatePr(worktreePath, opts) {
9276
9348
  const headRef = ghHeadRef(slug, opts.head);
9277
9349
  const branchOnly = opts.head.trim().replace(/^refs\/heads\//, "");
9278
9350
  const bodyText = clampGithubPrBody(opts.body ?? opts.title);
9279
- const bodyFile = (0, import_node_path21.join)(
9351
+ const bodyFile = (0, import_node_path22.join)(
9280
9352
  (0, import_node_os6.tmpdir)(),
9281
9353
  `sideboard-pr-body-${process.pid}-${(0, import_node_crypto7.randomBytes)(6).toString("hex")}.md`
9282
9354
  );
9283
- (0, import_node_fs18.writeFileSync)(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
9355
+ (0, import_node_fs19.writeFileSync)(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
9284
9356
  `, "utf8");
9285
9357
  const bodyArgs = ["--body-file", bodyFile];
9286
9358
  try {
@@ -9294,7 +9366,7 @@ async function createOrUpdatePr(worktreePath, opts) {
9294
9366
  });
9295
9367
  } finally {
9296
9368
  try {
9297
- (0, import_node_fs18.unlinkSync)(bodyFile);
9369
+ (0, import_node_fs19.unlinkSync)(bodyFile);
9298
9370
  } catch {
9299
9371
  }
9300
9372
  }
@@ -9376,10 +9448,10 @@ function sameRepoPath2(a, b) {
9376
9448
  return normalizeWorktreePath(a) === normalizeWorktreePath(b);
9377
9449
  }
9378
9450
  function listLocalThreadBranchSlugs(repoPath) {
9379
- const refsDir = (0, import_node_path21.join)(repoPath, ".git", "refs", "heads", "thread");
9380
- if (!(0, import_node_fs18.existsSync)(refsDir)) return [];
9451
+ const refsDir = (0, import_node_path22.join)(repoPath, ".git", "refs", "heads", "thread");
9452
+ if (!(0, import_node_fs19.existsSync)(refsDir)) return [];
9381
9453
  try {
9382
- return (0, import_node_fs18.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
9454
+ return (0, import_node_fs19.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
9383
9455
  } catch {
9384
9456
  return [];
9385
9457
  }
@@ -9387,8 +9459,8 @@ function listLocalThreadBranchSlugs(repoPath) {
9387
9459
  function collectTakenTeamSlugs(repoPath) {
9388
9460
  const taken = /* @__PURE__ */ new Set();
9389
9461
  const root = worktreesRoot(repoPath);
9390
- if ((0, import_node_fs18.existsSync)(root)) {
9391
- for (const entry of (0, import_node_fs18.readdirSync)(root, { withFileTypes: true })) {
9462
+ if ((0, import_node_fs19.existsSync)(root)) {
9463
+ for (const entry of (0, import_node_fs19.readdirSync)(root, { withFileTypes: true })) {
9392
9464
  if (entry.isDirectory() && entry.name !== ".DS_Store") {
9393
9465
  for (const slug of takenSlugsFromThread({ worktreePath: entry.name })) {
9394
9466
  taken.add(slug);
@@ -9413,20 +9485,20 @@ function allocateTeamSlug(repoPath) {
9413
9485
  const taken = collectTakenTeamSlugs(repoPath);
9414
9486
  for (let attempt = 0; attempt < 32; attempt++) {
9415
9487
  const team = allocateTeamName(taken);
9416
- const path2 = (0, import_node_path21.join)(worktreesRoot(repoPath), team.slug);
9417
- if (!(0, import_node_fs18.existsSync)(path2)) return team;
9488
+ const path2 = (0, import_node_path22.join)(worktreesRoot(repoPath), team.slug);
9489
+ if (!(0, import_node_fs19.existsSync)(path2)) return team;
9418
9490
  taken.add(team.slug);
9419
9491
  }
9420
9492
  throw new Error("No available soccer team worktree directories left");
9421
9493
  }
9422
- var import_node_crypto7, import_node_fs18, import_node_os6, import_node_path21, PR_DETAILS_JSON_FIELDS;
9494
+ var import_node_crypto7, import_node_fs19, import_node_os6, import_node_path22, PR_DETAILS_JSON_FIELDS;
9423
9495
  var init_worktree = __esm({
9424
9496
  "src/git/worktree.ts"() {
9425
9497
  "use strict";
9426
9498
  import_node_crypto7 = require("crypto");
9427
- import_node_fs18 = require("fs");
9499
+ import_node_fs19 = require("fs");
9428
9500
  import_node_os6 = require("os");
9429
- import_node_path21 = require("path");
9501
+ import_node_path22 = require("path");
9430
9502
  init_paths();
9431
9503
  init_thread_store();
9432
9504
  init_teams();
@@ -9479,38 +9551,38 @@ __export(workspaces_exports, {
9479
9551
  syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
9480
9552
  });
9481
9553
  function workspacesFile() {
9482
- return (0, import_node_path22.join)(appDataDir(), "workspaces.json");
9554
+ return (0, import_node_path23.join)(appDataDir(), "workspaces.json");
9483
9555
  }
9484
9556
  function removedWorkspacesFile() {
9485
- return (0, import_node_path22.join)(appDataDir(), "removed-workspaces.json");
9557
+ return (0, import_node_path23.join)(appDataDir(), "removed-workspaces.json");
9486
9558
  }
9487
9559
  function readAll2() {
9488
9560
  const path2 = workspacesFile();
9489
- if (!(0, import_node_fs19.existsSync)(path2)) return [];
9561
+ if (!(0, import_node_fs20.existsSync)(path2)) return [];
9490
9562
  try {
9491
- const raw = JSON.parse((0, import_node_fs19.readFileSync)(path2, "utf8"));
9563
+ const raw = JSON.parse((0, import_node_fs20.readFileSync)(path2, "utf8"));
9492
9564
  return Array.isArray(raw) ? raw : [];
9493
9565
  } catch {
9494
9566
  return [];
9495
9567
  }
9496
9568
  }
9497
9569
  function writeAll2(list) {
9498
- (0, import_node_fs19.mkdirSync)(appDataDir(), { recursive: true });
9499
- (0, import_node_fs19.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
9570
+ (0, import_node_fs20.mkdirSync)(appDataDir(), { recursive: true });
9571
+ (0, import_node_fs20.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
9500
9572
  }
9501
9573
  function readRemoved() {
9502
9574
  const path2 = removedWorkspacesFile();
9503
- if (!(0, import_node_fs19.existsSync)(path2)) return /* @__PURE__ */ new Set();
9575
+ if (!(0, import_node_fs20.existsSync)(path2)) return /* @__PURE__ */ new Set();
9504
9576
  try {
9505
- const raw = JSON.parse((0, import_node_fs19.readFileSync)(path2, "utf8"));
9577
+ const raw = JSON.parse((0, import_node_fs20.readFileSync)(path2, "utf8"));
9506
9578
  return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
9507
9579
  } catch {
9508
9580
  return /* @__PURE__ */ new Set();
9509
9581
  }
9510
9582
  }
9511
9583
  function writeRemoved(paths) {
9512
- (0, import_node_fs19.mkdirSync)(appDataDir(), { recursive: true });
9513
- (0, import_node_fs19.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
9584
+ (0, import_node_fs20.mkdirSync)(appDataDir(), { recursive: true });
9585
+ (0, import_node_fs20.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
9514
9586
  }
9515
9587
  function rememberRemoved(repoPath) {
9516
9588
  const next = readRemoved();
@@ -9532,10 +9604,10 @@ function listWorkspaces() {
9532
9604
  }
9533
9605
  function isLinkedWorktreeOf(path2, mainRepo) {
9534
9606
  if (!path2 || path2 === mainRepo) return false;
9535
- const git2 = (0, import_node_path22.join)(path2, ".git");
9607
+ const git2 = (0, import_node_path23.join)(path2, ".git");
9536
9608
  try {
9537
- if (!(0, import_node_fs19.existsSync)(git2) || (0, import_node_fs19.statSync)(git2).isDirectory()) return false;
9538
- const text7 = (0, import_node_fs19.readFileSync)(git2, "utf8");
9609
+ if (!(0, import_node_fs20.existsSync)(git2) || (0, import_node_fs20.statSync)(git2).isDirectory()) return false;
9610
+ const text7 = (0, import_node_fs20.readFileSync)(git2, "utf8");
9539
9611
  const needle = `${mainRepo.replace(/\/+$/, "")}/.git`;
9540
9612
  return text7.includes(needle);
9541
9613
  } catch {
@@ -9544,10 +9616,10 @@ function isLinkedWorktreeOf(path2, mainRepo) {
9544
9616
  }
9545
9617
  function primaryCheckoutFromLinkedWorktree(path2) {
9546
9618
  if (!path2) return null;
9547
- const git2 = (0, import_node_path22.join)(path2, ".git");
9619
+ const git2 = (0, import_node_path23.join)(path2, ".git");
9548
9620
  try {
9549
- if (!(0, import_node_fs19.existsSync)(git2) || (0, import_node_fs19.statSync)(git2).isDirectory()) return null;
9550
- const text7 = (0, import_node_fs19.readFileSync)(git2, "utf8");
9621
+ if (!(0, import_node_fs20.existsSync)(git2) || (0, import_node_fs20.statSync)(git2).isDirectory()) return null;
9622
+ const text7 = (0, import_node_fs20.readFileSync)(git2, "utf8");
9551
9623
  const match = /^\s*gitdir:\s*(.+)$/m.exec(text7);
9552
9624
  if (!match) return null;
9553
9625
  const gitdir = match[1].trim().replace(/\/+$/, "");
@@ -9568,7 +9640,7 @@ function resolveSyncWorkspacePath(path2) {
9568
9640
  async function addWorkspace(repoPath) {
9569
9641
  const root = await resolveRepoRoot(repoPath);
9570
9642
  if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
9571
- if (!(0, import_node_fs19.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
9643
+ if (!(0, import_node_fs20.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
9572
9644
  forgetRemoved(root);
9573
9645
  await ensureGhPreferOrigin(root);
9574
9646
  const current = readAll2();
@@ -9577,7 +9649,7 @@ async function addWorkspace(repoPath) {
9577
9649
  if (existing && withoutLinked.length === current.length) return existing;
9578
9650
  const next = existing ?? {
9579
9651
  path: root,
9580
- name: (0, import_node_path22.basename)(root),
9652
+ name: (0, import_node_path23.basename)(root),
9581
9653
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
9582
9654
  };
9583
9655
  writeAll2(existing ? withoutLinked : [...withoutLinked, next]);
@@ -9605,7 +9677,7 @@ function syncWorkspacesFromThreads(repoPaths) {
9605
9677
  if (!byPath.has(resolved)) {
9606
9678
  byPath.set(
9607
9679
  resolved,
9608
- resolved === w.path ? w : { ...w, path: resolved, name: (0, import_node_path22.basename)(resolved) }
9680
+ resolved === w.path ? w : { ...w, path: resolved, name: (0, import_node_path23.basename)(resolved) }
9609
9681
  );
9610
9682
  }
9611
9683
  }
@@ -9614,10 +9686,10 @@ function syncWorkspacesFromThreads(repoPaths) {
9614
9686
  if (!path2 || path2 === "/" || isGlobalRepoPath(path2) || byPath.has(path2) || removed.has(path2)) {
9615
9687
  continue;
9616
9688
  }
9617
- if (!(0, import_node_fs19.existsSync)(path2)) continue;
9689
+ if (!(0, import_node_fs20.existsSync)(path2)) continue;
9618
9690
  const ws = {
9619
9691
  path: path2,
9620
- name: (0, import_node_path22.basename)(path2),
9692
+ name: (0, import_node_path23.basename)(path2),
9621
9693
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
9622
9694
  };
9623
9695
  byPath.set(path2, ws);
@@ -9634,12 +9706,12 @@ function syncWorkspacesFromThreads(repoPaths) {
9634
9706
  if (dirty) writeAll2(next);
9635
9707
  return next.sort((a, b) => a.name.localeCompare(b.name));
9636
9708
  }
9637
- var import_node_fs19, import_node_path22;
9709
+ var import_node_fs20, import_node_path23;
9638
9710
  var init_workspaces = __esm({
9639
9711
  "src/store/workspaces.ts"() {
9640
9712
  "use strict";
9641
- import_node_fs19 = require("fs");
9642
- import_node_path22 = require("path");
9713
+ import_node_fs20 = require("fs");
9714
+ import_node_path23 = require("path");
9643
9715
  init_paths();
9644
9716
  init_global_workspace();
9645
9717
  init_worktree();
@@ -9750,7 +9822,7 @@ function coordinatorTurnReminder(opts) {
9750
9822
  function ensureGlobalCoordinatorCwd(opts) {
9751
9823
  const dir = globalAgentCwd();
9752
9824
  try {
9753
- (0, import_node_fs20.mkdirSync)(dir, { recursive: true });
9825
+ (0, import_node_fs21.mkdirSync)(dir, { recursive: true });
9754
9826
  } catch {
9755
9827
  return dir;
9756
9828
  }
@@ -9758,7 +9830,7 @@ function ensureGlobalCoordinatorCwd(opts) {
9758
9830
  let orchId = opts?.orchestratorThreadId?.trim() || "";
9759
9831
  if (!orchId) {
9760
9832
  try {
9761
- const existing = (0, import_node_fs20.readFileSync)((0, import_node_path23.join)(dir, "AGENTS.md"), "utf8");
9833
+ const existing = (0, import_node_fs21.readFileSync)((0, import_node_path24.join)(dir, "AGENTS.md"), "utf8");
9762
9834
  const m = existing.match(
9763
9835
  /YOUR orchestration thread id is `([0-9a-f-]{36})`/i
9764
9836
  );
@@ -9803,9 +9875,9 @@ function ensureGlobalCoordinatorCwd(opts) {
9803
9875
  "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."
9804
9876
  ].join("\n");
9805
9877
  try {
9806
- (0, import_node_fs20.writeFileSync)((0, import_node_path23.join)(dir, "CLAUDE.md"), `${body}
9878
+ (0, import_node_fs21.writeFileSync)((0, import_node_path24.join)(dir, "CLAUDE.md"), `${body}
9807
9879
  `, "utf8");
9808
- (0, import_node_fs20.writeFileSync)((0, import_node_path23.join)(dir, "AGENTS.md"), `${body}
9880
+ (0, import_node_fs21.writeFileSync)((0, import_node_path24.join)(dir, "AGENTS.md"), `${body}
9809
9881
  `, "utf8");
9810
9882
  } catch {
9811
9883
  }
@@ -9837,12 +9909,12 @@ function coordinatorSystemPrompt(opts) {
9837
9909
  formatWorkspaceInventory(opts.workspaces)
9838
9910
  ].join("\n");
9839
9911
  }
9840
- var import_node_fs20, import_node_path23, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
9912
+ var import_node_fs21, import_node_path24, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
9841
9913
  var init_coordinator_prompt = __esm({
9842
9914
  "src/orchestrator/coordinator-prompt.ts"() {
9843
9915
  "use strict";
9844
- import_node_fs20 = require("fs");
9845
- import_node_path23 = require("path");
9916
+ import_node_fs21 = require("fs");
9917
+ import_node_path24 = require("path");
9846
9918
  init_worktree();
9847
9919
  init_app_settings();
9848
9920
  init_paths();
@@ -10201,13 +10273,13 @@ var init_api = __esm({
10201
10273
 
10202
10274
  // src/slack/reply-target.ts
10203
10275
  function storePath() {
10204
- return (0, import_node_path24.join)(appDataDir(), "slack-reply-to.json");
10276
+ return (0, import_node_path25.join)(appDataDir(), "slack-reply-to.json");
10205
10277
  }
10206
10278
  function readStore() {
10207
10279
  const path2 = storePath();
10208
- if (!(0, import_node_fs21.existsSync)(path2)) return {};
10280
+ if (!(0, import_node_fs22.existsSync)(path2)) return {};
10209
10281
  try {
10210
- const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs21.readFileSync)(path2, "utf8"));
10282
+ const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs22.readFileSync)(path2, "utf8"));
10211
10283
  return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
10212
10284
  } catch {
10213
10285
  return {};
@@ -10222,12 +10294,12 @@ function setSlackReplyTarget(target) {
10222
10294
  function getSlackReplyTarget(threadId) {
10223
10295
  return readStore()[threadId] ?? null;
10224
10296
  }
10225
- var import_node_fs21, import_node_path24;
10297
+ var import_node_fs22, import_node_path25;
10226
10298
  var init_reply_target = __esm({
10227
10299
  "src/slack/reply-target.ts"() {
10228
10300
  "use strict";
10229
- import_node_fs21 = require("fs");
10230
- import_node_path24 = require("path");
10301
+ import_node_fs22 = require("fs");
10302
+ import_node_path25 = require("path");
10231
10303
  init_paths();
10232
10304
  init_private_file();
10233
10305
  init_secure_file();
@@ -10236,7 +10308,7 @@ var init_reply_target = __esm({
10236
10308
 
10237
10309
  // src/slack/workspaces.ts
10238
10310
  function storePath2() {
10239
- return (0, import_node_path25.join)(appDataDir(), "slack-workspaces.json");
10311
+ return (0, import_node_path26.join)(appDataDir(), "slack-workspaces.json");
10240
10312
  }
10241
10313
  function readStore2() {
10242
10314
  try {
@@ -10343,11 +10415,11 @@ function requireSlackWorkspace(teamId) {
10343
10415
  }
10344
10416
  return ws;
10345
10417
  }
10346
- var import_node_path25;
10418
+ var import_node_path26;
10347
10419
  var init_workspaces2 = __esm({
10348
10420
  "src/slack/workspaces.ts"() {
10349
10421
  "use strict";
10350
- import_node_path25 = require("path");
10422
+ import_node_path26 = require("path");
10351
10423
  init_paths();
10352
10424
  init_secure_file();
10353
10425
  init_api();
@@ -10356,7 +10428,7 @@ var init_workspaces2 = __esm({
10356
10428
 
10357
10429
  // src/slack/outbound-watch.ts
10358
10430
  function storePath3() {
10359
- return (0, import_node_path26.join)(appDataDir(), "slack-outbound-watch.json");
10431
+ return (0, import_node_path27.join)(appDataDir(), "slack-outbound-watch.json");
10360
10432
  }
10361
10433
  function watchId(teamId, channelId, ts) {
10362
10434
  return `${teamId}:${channelId}:${ts}`;
@@ -10369,9 +10441,9 @@ function tsNewer(a, b) {
10369
10441
  }
10370
10442
  function readStore3() {
10371
10443
  const path2 = storePath3();
10372
- if (!(0, import_node_fs22.existsSync)(path2)) return [];
10444
+ if (!(0, import_node_fs23.existsSync)(path2)) return [];
10373
10445
  try {
10374
- const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs22.readFileSync)(path2, "utf8"));
10446
+ const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs23.readFileSync)(path2, "utf8"));
10375
10447
  return Array.isArray(parsed?.watches) ? parsed.watches : [];
10376
10448
  } catch {
10377
10449
  return [];
@@ -10693,12 +10765,12 @@ async function pollSlackOutboundWatches(opts) {
10693
10765
  }
10694
10766
  if (changed) writeStore2(watches);
10695
10767
  }
10696
- var import_node_fs22, import_node_path26, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache, continueOnReply;
10768
+ var import_node_fs23, import_node_path27, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache, continueOnReply;
10697
10769
  var init_outbound_watch = __esm({
10698
10770
  "src/slack/outbound-watch.ts"() {
10699
10771
  "use strict";
10700
- import_node_fs22 = require("fs");
10701
- import_node_path26 = require("path");
10772
+ import_node_fs23 = require("fs");
10773
+ import_node_path27 = require("path");
10702
10774
  init_paths();
10703
10775
  init_private_file();
10704
10776
  init_secure_file();
@@ -10720,7 +10792,7 @@ function traceTurn(phase, extra) {
10720
10792
  try {
10721
10793
  const line = `${JSON.stringify({ t: (/* @__PURE__ */ new Date()).toISOString(), phase, ...extra })}
10722
10794
  `;
10723
- (0, import_node_fs23.appendFileSync)((0, import_node_path27.join)(appDataDir(), "turn-spawn.log"), line);
10795
+ (0, import_node_fs24.appendFileSync)((0, import_node_path28.join)(appDataDir(), "turn-spawn.log"), line);
10724
10796
  } catch {
10725
10797
  }
10726
10798
  }
@@ -10740,12 +10812,12 @@ async function withTimeout(promise, ms, label) {
10740
10812
  if (timer) clearTimeout(timer);
10741
10813
  }
10742
10814
  }
10743
- var import_node_fs23, import_node_path27;
10815
+ var import_node_fs24, import_node_path28;
10744
10816
  var init_turn_trace = __esm({
10745
10817
  "src/agents/turn-trace.ts"() {
10746
10818
  "use strict";
10747
- import_node_fs23 = require("fs");
10748
- import_node_path27 = require("path");
10819
+ import_node_fs24 = require("fs");
10820
+ import_node_path28 = require("path");
10749
10821
  init_paths();
10750
10822
  }
10751
10823
  });
@@ -10754,32 +10826,32 @@ var init_turn_trace = __esm({
10754
10826
  function brightsyConfigPath() {
10755
10827
  const override = process.env.BRIGHTSY_CONFIG?.trim();
10756
10828
  if (override) return override;
10757
- return (0, import_node_path28.join)((0, import_node_os7.homedir)(), ".brightsy", "config.json");
10829
+ return (0, import_node_path29.join)((0, import_node_os7.homedir)(), ".brightsy", "config.json");
10758
10830
  }
10759
10831
  function loadBrightsyConfig() {
10760
10832
  const path2 = brightsyConfigPath();
10761
- if (!(0, import_node_fs24.existsSync)(path2)) {
10833
+ if (!(0, import_node_fs25.existsSync)(path2)) {
10762
10834
  throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
10763
10835
  }
10764
- const raw = JSON.parse((0, import_node_fs24.readFileSync)(path2, "utf8"));
10836
+ const raw = JSON.parse((0, import_node_fs25.readFileSync)(path2, "utf8"));
10765
10837
  if (!raw.access_token || !raw.account_id) {
10766
10838
  throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
10767
10839
  }
10768
10840
  return raw;
10769
10841
  }
10770
10842
  function saveBrightsyConfig(cfg) {
10771
- (0, import_node_fs24.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
10843
+ (0, import_node_fs25.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
10772
10844
  `, {
10773
10845
  mode: 384
10774
10846
  });
10775
10847
  }
10776
- var import_node_fs24, import_node_os7, import_node_path28;
10848
+ var import_node_fs25, import_node_os7, import_node_path29;
10777
10849
  var init_config = __esm({
10778
10850
  "src/brightsy/config.ts"() {
10779
10851
  "use strict";
10780
- import_node_fs24 = require("fs");
10852
+ import_node_fs25 = require("fs");
10781
10853
  import_node_os7 = require("os");
10782
- import_node_path28 = require("path");
10854
+ import_node_path29 = require("path");
10783
10855
  }
10784
10856
  });
10785
10857
 
@@ -11081,22 +11153,22 @@ __export(connected_teams_exports, {
11081
11153
  listConnectedBrightsyTeams: () => listConnectedBrightsyTeams
11082
11154
  });
11083
11155
  function storePath4() {
11084
- return (0, import_node_path29.join)(appDataDir(), "brightsy-teams.json");
11156
+ return (0, import_node_path30.join)(appDataDir(), "brightsy-teams.json");
11085
11157
  }
11086
11158
  function readStore4() {
11087
11159
  const path2 = storePath4();
11088
- if (!(0, import_node_fs25.existsSync)(path2)) return [];
11160
+ if (!(0, import_node_fs26.existsSync)(path2)) return [];
11089
11161
  try {
11090
- const parsed = JSON.parse((0, import_node_fs25.readFileSync)(path2, "utf8"));
11162
+ const parsed = JSON.parse((0, import_node_fs26.readFileSync)(path2, "utf8"));
11091
11163
  return Array.isArray(parsed.teams) ? parsed.teams : [];
11092
11164
  } catch {
11093
11165
  return [];
11094
11166
  }
11095
11167
  }
11096
11168
  function writeStore3(teams) {
11097
- (0, import_node_fs25.mkdirSync)(appDataDir(), { recursive: true });
11169
+ (0, import_node_fs26.mkdirSync)(appDataDir(), { recursive: true });
11098
11170
  const path2 = storePath4();
11099
- (0, import_node_fs25.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
11171
+ (0, import_node_fs26.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
11100
11172
  `, {
11101
11173
  mode: 384
11102
11174
  });
@@ -11284,12 +11356,12 @@ function brightsyMcpServerName(slug) {
11284
11356
  const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
11285
11357
  return `brightsy_${cleaned || "team"}`;
11286
11358
  }
11287
- var import_node_fs25, import_node_path29;
11359
+ var import_node_fs26, import_node_path30;
11288
11360
  var init_connected_teams = __esm({
11289
11361
  "src/brightsy/connected-teams.ts"() {
11290
11362
  "use strict";
11291
- import_node_fs25 = require("fs");
11292
- import_node_path29 = require("path");
11363
+ import_node_fs26 = require("fs");
11364
+ import_node_path30 = require("path");
11293
11365
  init_paths();
11294
11366
  init_accounts();
11295
11367
  init_config();
@@ -11654,11 +11726,11 @@ async function syncCliForTarget(accountId) {
11654
11726
  }
11655
11727
  applyConnectedTeamToCli(team);
11656
11728
  }
11657
- var import_node_fs26, brightsyAdapter;
11729
+ var import_node_fs27, brightsyAdapter;
11658
11730
  var init_brightsy = __esm({
11659
11731
  "src/agents/brightsy.ts"() {
11660
11732
  "use strict";
11661
- import_node_fs26 = require("fs");
11733
+ import_node_fs27 = require("fs");
11662
11734
  init_run();
11663
11735
  init_connected_teams();
11664
11736
  init_config();
@@ -11673,7 +11745,7 @@ var init_brightsy = __esm({
11673
11745
  async detect() {
11674
11746
  const brightsy = resolveAgentExecutable("brightsy");
11675
11747
  if (brightsy !== "brightsy") {
11676
- if (!(0, import_node_fs26.existsSync)(brightsy)) {
11748
+ if (!(0, import_node_fs27.existsSync)(brightsy)) {
11677
11749
  return {
11678
11750
  agent: "brightsy",
11679
11751
  installed: false,
@@ -11816,6 +11888,9 @@ var init_profile = __esm({
11816
11888
  "present_files",
11817
11889
  "wait_for_job",
11818
11890
  "stop_job",
11891
+ "list_run_scripts",
11892
+ "run_dev_script",
11893
+ "stop_dev_script",
11819
11894
  "get_viewer_context",
11820
11895
  "update_viewer_context"
11821
11896
  ];
@@ -11854,7 +11929,7 @@ function splitPemCertificates(pem) {
11854
11929
  }
11855
11930
  function readExistingFile(path2) {
11856
11931
  try {
11857
- return (0, import_node_fs27.existsSync)(path2) ? (0, import_node_fs27.readFileSync)(path2, "utf8") : "";
11932
+ return (0, import_node_fs28.existsSync)(path2) ? (0, import_node_fs28.readFileSync)(path2, "utf8") : "";
11858
11933
  } catch {
11859
11934
  return "";
11860
11935
  }
@@ -11886,13 +11961,13 @@ function collectSystemCaPem(io = {}) {
11886
11961
  return "";
11887
11962
  }
11888
11963
  function systemCaBundlePath(io = {}) {
11889
- return (0, import_node_path30.join)((io.appData ?? appDataDir)(), BUNDLE_NAME);
11964
+ return (0, import_node_path31.join)((io.appData ?? appDataDir)(), BUNDLE_NAME);
11890
11965
  }
11891
11966
  function bundleIsFresh(path2, now) {
11892
11967
  try {
11893
- if (!(0, import_node_fs27.existsSync)(path2)) return false;
11894
- if (splitPemCertificates((0, import_node_fs27.readFileSync)(path2, "utf8")).length === 0) return false;
11895
- return now - (0, import_node_fs27.statSync)(path2).mtimeMs < BUNDLE_MAX_AGE_MS;
11968
+ if (!(0, import_node_fs28.existsSync)(path2)) return false;
11969
+ if (splitPemCertificates((0, import_node_fs28.readFileSync)(path2, "utf8")).length === 0) return false;
11970
+ return now - (0, import_node_fs28.statSync)(path2).mtimeMs < BUNDLE_MAX_AGE_MS;
11896
11971
  } catch {
11897
11972
  return false;
11898
11973
  }
@@ -11913,11 +11988,11 @@ function materializeSystemCaBundle(io = {}) {
11913
11988
  if (bundleIsFresh(dest, now)) return dest;
11914
11989
  const pem = collectSystemCaPem(io);
11915
11990
  if (splitPemCertificates(pem).length === 0) {
11916
- return (0, import_node_fs27.existsSync)(dest) && splitPemCertificates(readExistingFile(dest)).length > 0 ? dest : void 0;
11991
+ return (0, import_node_fs28.existsSync)(dest) && splitPemCertificates(readExistingFile(dest)).length > 0 ? dest : void 0;
11917
11992
  }
11918
11993
  try {
11919
- (0, import_node_fs27.mkdirSync)((0, import_node_path30.dirname)(dest), { recursive: true });
11920
- (0, import_node_fs27.writeFileSync)(dest, pem.endsWith("\n") ? pem : `${pem}
11994
+ (0, import_node_fs28.mkdirSync)((0, import_node_path31.dirname)(dest), { recursive: true });
11995
+ (0, import_node_fs28.writeFileSync)(dest, pem.endsWith("\n") ? pem : `${pem}
11921
11996
  `, { mode: 384 });
11922
11997
  return dest;
11923
11998
  } catch {
@@ -11957,13 +12032,13 @@ function trustSystemCertificates(io = {}) {
11957
12032
  return false;
11958
12033
  }
11959
12034
  }
11960
- var import_node_child_process4, import_node_fs27, import_node_path30, import_node_tls, NODE_USE_SYSTEM_CA, NODE_EXTRA_CA_CERTS, BUNDLE_NAME, BUNDLE_MAX_AGE_MS, LINUX_CA_FILES, PEM_CERT_RE;
12035
+ var import_node_child_process4, import_node_fs28, import_node_path31, import_node_tls, NODE_USE_SYSTEM_CA, NODE_EXTRA_CA_CERTS, BUNDLE_NAME, BUNDLE_MAX_AGE_MS, LINUX_CA_FILES, PEM_CERT_RE;
11961
12036
  var init_system_ca = __esm({
11962
12037
  "src/http/system-ca.ts"() {
11963
12038
  "use strict";
11964
12039
  import_node_child_process4 = require("child_process");
11965
- import_node_fs27 = require("fs");
11966
- import_node_path30 = require("path");
12040
+ import_node_fs28 = require("fs");
12041
+ import_node_path31 = require("path");
11967
12042
  import_node_tls = __toESM(require("tls"), 1);
11968
12043
  init_paths();
11969
12044
  NODE_USE_SYSTEM_CA = "NODE_USE_SYSTEM_CA";
@@ -11989,43 +12064,43 @@ function electronResourcesPath() {
11989
12064
  function packagedCursorRuntimeDir() {
11990
12065
  const resources = electronResourcesPath();
11991
12066
  if (!resources) return null;
11992
- const dir = (0, import_node_path31.join)(resources, "cursor-runtime");
11993
- if (!(0, import_node_fs28.existsSync)((0, import_node_path31.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
12067
+ const dir = (0, import_node_path32.join)(resources, "cursor-runtime");
12068
+ if (!(0, import_node_fs29.existsSync)((0, import_node_path32.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
11994
12069
  return dir;
11995
12070
  }
11996
12071
  function packagedCursorRunnerPath() {
11997
12072
  const dir = packagedCursorRuntimeDir();
11998
- return dir ? (0, import_node_path31.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
12073
+ return dir ? (0, import_node_path32.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
11999
12074
  }
12000
12075
  function packagedMcpDir() {
12001
12076
  const resources = electronResourcesPath();
12002
12077
  if (!resources) return null;
12003
- const dir = (0, import_node_path31.join)(resources, "sideboard-mcp");
12004
- if (!(0, import_node_fs28.existsSync)((0, import_node_path31.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
12078
+ const dir = (0, import_node_path32.join)(resources, "sideboard-mcp");
12079
+ if (!(0, import_node_fs29.existsSync)((0, import_node_path32.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
12005
12080
  return dir;
12006
12081
  }
12007
12082
  function packagedMcpStdioPath() {
12008
12083
  const dir = packagedMcpDir();
12009
- return dir ? (0, import_node_path31.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
12084
+ return dir ? (0, import_node_path32.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
12010
12085
  }
12011
12086
  function packagedBundledNodePath() {
12012
12087
  const resources = electronResourcesPath();
12013
12088
  if (!resources) return null;
12014
- const bin = (0, import_node_path31.join)(resources, "node", "bin", "node");
12015
- if (!(0, import_node_fs28.existsSync)(bin)) return null;
12089
+ const bin = (0, import_node_path32.join)(resources, "node", "bin", "node");
12090
+ if (!(0, import_node_fs29.existsSync)(bin)) return null;
12016
12091
  return bin;
12017
12092
  }
12018
12093
  function packagedCursorRipgrepCandidate(platformPkg, binName) {
12019
12094
  const dir = packagedCursorRuntimeDir();
12020
12095
  if (!dir) return null;
12021
- return (0, import_node_path31.join)(dir, "node_modules", platformPkg, "bin", binName);
12096
+ return (0, import_node_path32.join)(dir, "node_modules", platformPkg, "bin", binName);
12022
12097
  }
12023
- var import_node_fs28, import_node_path31;
12098
+ var import_node_fs29, import_node_path32;
12024
12099
  var init_packaged_runtime = __esm({
12025
12100
  "src/agents/packaged-runtime.ts"() {
12026
12101
  "use strict";
12027
- import_node_fs28 = require("fs");
12028
- import_node_path31 = require("path");
12102
+ import_node_fs29 = require("fs");
12103
+ import_node_path32 = require("path");
12029
12104
  }
12030
12105
  });
12031
12106
 
@@ -12060,7 +12135,7 @@ function unpackedAsarPath(filePath) {
12060
12135
  if (!isAsarPath(filePath)) return null;
12061
12136
  const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
12062
12137
  if (unpacked === filePath) return null;
12063
- return (0, import_node_fs29.existsSync)(unpacked) ? unpacked : null;
12138
+ return (0, import_node_fs30.existsSync)(unpacked) ? unpacked : null;
12064
12139
  }
12065
12140
  function nodeReadableScriptPath(scriptPath) {
12066
12141
  return unpackedAsarPath(scriptPath) ?? scriptPath;
@@ -12100,37 +12175,37 @@ function pickPreferredNode(candidates) {
12100
12175
  return best;
12101
12176
  }
12102
12177
  function versionDirNodeBins(root, toBin) {
12103
- if (!(0, import_node_fs29.existsSync)(root)) return [];
12178
+ if (!(0, import_node_fs30.existsSync)(root)) return [];
12104
12179
  try {
12105
- return (0, import_node_fs29.readdirSync)(root).map(toBin);
12180
+ return (0, import_node_fs30.readdirSync)(root).map(toBin);
12106
12181
  } catch {
12107
12182
  return [];
12108
12183
  }
12109
12184
  }
12110
12185
  function defaultNodeBinCandidates(home = (0, import_node_os8.homedir)()) {
12111
12186
  const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
12112
- (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path32.join)(prefix, "opt", `node@${major}`, "bin", "node"))
12187
+ (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path33.join)(prefix, "opt", `node@${major}`, "bin", "node"))
12113
12188
  );
12114
12189
  return [
12115
12190
  ...kegs,
12116
12191
  "/opt/homebrew/bin/node",
12117
12192
  "/usr/local/bin/node",
12118
- (0, import_node_path32.join)(home, ".local/share/fnm/aliases/default/bin/node"),
12119
- (0, import_node_path32.join)(home, ".nvm/current/bin/node"),
12120
- (0, import_node_path32.join)(home, ".volta/bin/node"),
12121
- (0, import_node_path32.join)(home, ".asdf/shims/node"),
12122
- (0, import_node_path32.join)(home, ".local/share/mise/shims/node"),
12193
+ (0, import_node_path33.join)(home, ".local/share/fnm/aliases/default/bin/node"),
12194
+ (0, import_node_path33.join)(home, ".nvm/current/bin/node"),
12195
+ (0, import_node_path33.join)(home, ".volta/bin/node"),
12196
+ (0, import_node_path33.join)(home, ".asdf/shims/node"),
12197
+ (0, import_node_path33.join)(home, ".local/share/mise/shims/node"),
12123
12198
  ...versionDirNodeBins(
12124
- (0, import_node_path32.join)(home, ".nvm", "versions", "node"),
12125
- (name) => (0, import_node_path32.join)(home, ".nvm", "versions", "node", name, "bin", "node")
12199
+ (0, import_node_path33.join)(home, ".nvm", "versions", "node"),
12200
+ (name) => (0, import_node_path33.join)(home, ".nvm", "versions", "node", name, "bin", "node")
12126
12201
  ),
12127
12202
  ...versionDirNodeBins(
12128
- (0, import_node_path32.join)(home, ".local/share/fnm", "node-versions"),
12129
- (name) => (0, import_node_path32.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
12203
+ (0, import_node_path33.join)(home, ".local/share/fnm", "node-versions"),
12204
+ (name) => (0, import_node_path33.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
12130
12205
  ),
12131
12206
  ...versionDirNodeBins(
12132
- (0, import_node_path32.join)(home, ".volta", "tools", "image", "node"),
12133
- (name) => (0, import_node_path32.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
12207
+ (0, import_node_path33.join)(home, ".volta", "tools", "image", "node"),
12208
+ (name) => (0, import_node_path33.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
12134
12209
  )
12135
12210
  ];
12136
12211
  }
@@ -12139,10 +12214,10 @@ function uniqueExistingNodeBins(paths) {
12139
12214
  const out = [];
12140
12215
  for (const raw of paths) {
12141
12216
  const p = raw.trim();
12142
- if (!p || !(0, import_node_fs29.existsSync)(p) || isElectronLikeCommand(p)) continue;
12217
+ if (!p || !(0, import_node_fs30.existsSync)(p) || isElectronLikeCommand(p)) continue;
12143
12218
  let key = p;
12144
12219
  try {
12145
- key = (0, import_node_fs29.realpathSync)(p);
12220
+ key = (0, import_node_fs30.realpathSync)(p);
12146
12221
  } catch {
12147
12222
  continue;
12148
12223
  }
@@ -12222,13 +12297,13 @@ async function resolveNodeLaunch(scriptPath) {
12222
12297
  env: { ELECTRON_RUN_AS_NODE: "1" }
12223
12298
  };
12224
12299
  }
12225
- var import_node_fs29, import_node_os8, import_node_path32, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
12300
+ var import_node_fs30, import_node_os8, import_node_path33, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
12226
12301
  var init_node_launch = __esm({
12227
12302
  "src/agents/node-launch.ts"() {
12228
12303
  "use strict";
12229
- import_node_fs29 = require("fs");
12304
+ import_node_fs30 = require("fs");
12230
12305
  import_node_os8 = require("os");
12231
- import_node_path32 = require("path");
12306
+ import_node_path33 = require("path");
12232
12307
  init_nested_electron_env();
12233
12308
  init_system_ca();
12234
12309
  init_run();
@@ -12331,37 +12406,37 @@ function corePackageDir() {
12331
12406
  try {
12332
12407
  const url = import_meta.url;
12333
12408
  if (typeof url === "string" && url.length > 0) {
12334
- return (0, import_node_path33.dirname)((0, import_node_url.fileURLToPath)(url));
12409
+ return (0, import_node_path34.dirname)((0, import_node_url.fileURLToPath)(url));
12335
12410
  }
12336
12411
  } catch {
12337
12412
  }
12338
12413
  try {
12339
- const req = (0, import_node_module.createRequire)((0, import_node_path33.join)(process.cwd(), "package.json"));
12340
- return (0, import_node_path33.dirname)(req.resolve("@sideboard-ai/core"));
12414
+ const req = (0, import_node_module.createRequire)((0, import_node_path34.join)(process.cwd(), "package.json"));
12415
+ return (0, import_node_path34.dirname)(req.resolve("@sideboard-ai/core"));
12341
12416
  } catch {
12342
12417
  return process.cwd();
12343
12418
  }
12344
12419
  }
12345
12420
  function findSideboardMcpJsEntry() {
12346
12421
  const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
12347
- if (override && (0, import_node_fs30.existsSync)(override)) return override;
12422
+ if (override && (0, import_node_fs31.existsSync)(override)) return override;
12348
12423
  const packaged = packagedMcpStdioPath();
12349
12424
  if (packaged) return packaged;
12350
12425
  let dir = corePackageDir();
12351
12426
  for (let i = 0; i < 10; i++) {
12352
12427
  const candidates = [
12353
- (0, import_node_path33.join)(dir, "mcp/run-stdio.js"),
12354
- (0, import_node_path33.join)(dir, "mcp/run-stdio.cjs"),
12355
- (0, import_node_path33.join)(dir, "dist/mcp/run-stdio.js"),
12356
- (0, import_node_path33.join)(dir, "dist/mcp/run-stdio.cjs"),
12357
- (0, import_node_path33.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
12358
- (0, import_node_path33.join)(dir, "packages/cli/dist/index.js"),
12359
- (0, import_node_path33.join)(dir, "cli/dist/index.js")
12428
+ (0, import_node_path34.join)(dir, "mcp/run-stdio.js"),
12429
+ (0, import_node_path34.join)(dir, "mcp/run-stdio.cjs"),
12430
+ (0, import_node_path34.join)(dir, "dist/mcp/run-stdio.js"),
12431
+ (0, import_node_path34.join)(dir, "dist/mcp/run-stdio.cjs"),
12432
+ (0, import_node_path34.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
12433
+ (0, import_node_path34.join)(dir, "packages/cli/dist/index.js"),
12434
+ (0, import_node_path34.join)(dir, "cli/dist/index.js")
12360
12435
  ];
12361
12436
  for (const p of candidates) {
12362
- if ((0, import_node_fs30.existsSync)(p) && !isAsarPath(p)) return p;
12437
+ if ((0, import_node_fs31.existsSync)(p) && !isAsarPath(p)) return p;
12363
12438
  }
12364
- const parent = (0, import_node_path33.dirname)(dir);
12439
+ const parent = (0, import_node_path34.dirname)(dir);
12365
12440
  if (parent === dir) break;
12366
12441
  dir = parent;
12367
12442
  }
@@ -12524,22 +12599,22 @@ function writeMcpServersConfig(servers, extraServers) {
12524
12599
  }
12525
12600
  }
12526
12601
  if (Object.keys(mcpServers).length === 0) return null;
12527
- const dir = (0, import_node_fs30.mkdtempSync)((0, import_node_path33.join)((0, import_node_os9.tmpdir)(), "sideboard-mcp-"));
12528
- const cfgPath = (0, import_node_path33.join)(dir, "mcp.json");
12529
- (0, import_node_fs30.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
12602
+ const dir = (0, import_node_fs31.mkdtempSync)((0, import_node_path34.join)((0, import_node_os9.tmpdir)(), "sideboard-mcp-"));
12603
+ const cfgPath = (0, import_node_path34.join)(dir, "mcp.json");
12604
+ (0, import_node_fs31.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
12530
12605
  return cfgPath;
12531
12606
  }
12532
12607
  async function writeInjectedMcpConfig(opts) {
12533
12608
  return writeMcpServersConfig(await buildInjectedMcpServers(opts));
12534
12609
  }
12535
- var import_node_fs30, import_node_module, import_node_os9, import_node_path33, 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, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
12610
+ var import_node_fs31, import_node_module, import_node_os9, import_node_path34, 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, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
12536
12611
  var init_injected_mcp = __esm({
12537
12612
  "src/agents/injected-mcp.ts"() {
12538
12613
  "use strict";
12539
- import_node_fs30 = require("fs");
12614
+ import_node_fs31 = require("fs");
12540
12615
  import_node_module = require("module");
12541
12616
  import_node_os9 = require("os");
12542
- import_node_path33 = require("path");
12617
+ import_node_path34 = require("path");
12543
12618
  import_node_url = require("url");
12544
12619
  init_run();
12545
12620
  init_config();
@@ -12564,6 +12639,9 @@ var init_injected_mcp = __esm({
12564
12639
  "mcp__sideboard__present_plan",
12565
12640
  "mcp__sideboard__wait_for_job",
12566
12641
  "mcp__sideboard__stop_job",
12642
+ "mcp__sideboard__list_run_scripts",
12643
+ "mcp__sideboard__run_dev_script",
12644
+ "mcp__sideboard__stop_dev_script",
12567
12645
  "mcp__sideboard__get_viewer_context",
12568
12646
  "mcp__sideboard__update_viewer_context"
12569
12647
  ];
@@ -12581,10 +12659,10 @@ var init_injected_mcp = __esm({
12581
12659
 
12582
12660
  // src/agents/user-mcp-config.ts
12583
12661
  function userCursorMcpConfigPath() {
12584
- return (0, import_node_path34.join)((0, import_node_os10.homedir)(), ".cursor", "mcp.json");
12662
+ return (0, import_node_path35.join)((0, import_node_os10.homedir)(), ".cursor", "mcp.json");
12585
12663
  }
12586
12664
  function userClaudeMcpConfigPath() {
12587
- return (0, import_node_path34.join)((0, import_node_os10.homedir)(), ".claude.json");
12665
+ return (0, import_node_path35.join)((0, import_node_os10.homedir)(), ".claude.json");
12588
12666
  }
12589
12667
  function asObject(value) {
12590
12668
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
@@ -12611,16 +12689,16 @@ function mergeSideboardIntoMcpServersJson(existing, sideboard) {
12611
12689
  }
12612
12690
  function writeMergedMcpServersJson(configPath, sideboard) {
12613
12691
  let existing = {};
12614
- if ((0, import_node_fs31.existsSync)(configPath)) {
12692
+ if ((0, import_node_fs32.existsSync)(configPath)) {
12615
12693
  try {
12616
- existing = JSON.parse((0, import_node_fs31.readFileSync)(configPath, "utf8"));
12694
+ existing = JSON.parse((0, import_node_fs32.readFileSync)(configPath, "utf8"));
12617
12695
  } catch {
12618
12696
  existing = {};
12619
12697
  }
12620
12698
  }
12621
12699
  const next = mergeSideboardIntoMcpServersJson(existing, sideboard);
12622
- (0, import_node_fs31.mkdirSync)((0, import_node_path34.dirname)(configPath), { recursive: true });
12623
- (0, import_node_fs31.writeFileSync)(configPath, `${JSON.stringify(next, null, 2)}
12700
+ (0, import_node_fs32.mkdirSync)((0, import_node_path35.dirname)(configPath), { recursive: true });
12701
+ (0, import_node_fs32.writeFileSync)(configPath, `${JSON.stringify(next, null, 2)}
12624
12702
  `);
12625
12703
  }
12626
12704
  function launchFromResolved(server) {
@@ -12638,19 +12716,19 @@ async function registerPackagedUserMcpClients() {
12638
12716
  const cursor = userCursorMcpConfigPath();
12639
12717
  writeMergedMcpServersJson(cursor, launch);
12640
12718
  const claude = userClaudeMcpConfigPath();
12641
- if ((0, import_node_fs31.existsSync)(claude)) {
12719
+ if ((0, import_node_fs32.existsSync)(claude)) {
12642
12720
  writeMergedMcpServersJson(claude, launch);
12643
12721
  return { cursor, claude };
12644
12722
  }
12645
12723
  return { cursor };
12646
12724
  }
12647
- var import_node_fs31, import_node_os10, import_node_path34;
12725
+ var import_node_fs32, import_node_os10, import_node_path35;
12648
12726
  var init_user_mcp_config = __esm({
12649
12727
  "src/agents/user-mcp-config.ts"() {
12650
12728
  "use strict";
12651
- import_node_fs31 = require("fs");
12729
+ import_node_fs32 = require("fs");
12652
12730
  import_node_os10 = require("os");
12653
- import_node_path34 = require("path");
12731
+ import_node_path35 = require("path");
12654
12732
  init_paths();
12655
12733
  init_injected_mcp();
12656
12734
  }
@@ -12678,25 +12756,25 @@ function listMcpNamesFromCodexToml(text7) {
12678
12756
  }
12679
12757
  function readJsonObject(path2) {
12680
12758
  try {
12681
- return JSON.parse((0, import_node_fs32.readFileSync)(path2, "utf8"));
12759
+ return JSON.parse((0, import_node_fs33.readFileSync)(path2, "utf8"));
12682
12760
  } catch {
12683
12761
  return {};
12684
12762
  }
12685
12763
  }
12686
12764
  function readText(path2) {
12687
12765
  try {
12688
- return (0, import_node_fs32.readFileSync)(path2, "utf8");
12766
+ return (0, import_node_fs33.readFileSync)(path2, "utf8");
12689
12767
  } catch {
12690
12768
  return "";
12691
12769
  }
12692
12770
  }
12693
12771
  function userCodexConfigPaths(home = (0, import_node_os11.homedir)()) {
12694
- return [(0, import_node_path35.join)(home, ".codex", "config.toml"), (0, import_node_path35.join)(home, ".config", "codex", "config.toml")];
12772
+ return [(0, import_node_path36.join)(home, ".codex", "config.toml"), (0, import_node_path36.join)(home, ".config", "codex", "config.toml")];
12695
12773
  }
12696
12774
  function userOpencodeConfigPaths(home = (0, import_node_os11.homedir)()) {
12697
12775
  return [
12698
- (0, import_node_path35.join)(home, ".config", "opencode", "opencode.json"),
12699
- (0, import_node_path35.join)(home, ".config", "opencode", "opencode.jsonc")
12776
+ (0, import_node_path36.join)(home, ".config", "opencode", "opencode.json"),
12777
+ (0, import_node_path36.join)(home, ".config", "opencode", "opencode.jsonc")
12700
12778
  ];
12701
12779
  }
12702
12780
  function userMcpNamesToDisable(opts) {
@@ -12718,7 +12796,7 @@ function userMcpNamesToDisable(opts) {
12718
12796
  function listUserCodexMcpNames(home = (0, import_node_os11.homedir)()) {
12719
12797
  const names = [];
12720
12798
  for (const path2 of userCodexConfigPaths(home)) {
12721
- if (!(0, import_node_fs32.existsSync)(path2)) continue;
12799
+ if (!(0, import_node_fs33.existsSync)(path2)) continue;
12722
12800
  names.push(...listMcpNamesFromCodexToml(readText(path2)));
12723
12801
  }
12724
12802
  return names;
@@ -12726,14 +12804,14 @@ function listUserCodexMcpNames(home = (0, import_node_os11.homedir)()) {
12726
12804
  function listUserOpencodeMcpNames(home = (0, import_node_os11.homedir)()) {
12727
12805
  const names = [];
12728
12806
  for (const path2 of userOpencodeConfigPaths(home)) {
12729
- if (!(0, import_node_fs32.existsSync)(path2)) continue;
12807
+ if (!(0, import_node_fs33.existsSync)(path2)) continue;
12730
12808
  names.push(...listMcpNamesFromJsonMap(readJsonObject(path2), "mcp"));
12731
12809
  }
12732
12810
  return names;
12733
12811
  }
12734
12812
  function userClaudeMcpConfigObject(home = (0, import_node_os11.homedir)()) {
12735
- const claudePath = home === (0, import_node_os11.homedir)() ? userClaudeMcpConfigPath() : (0, import_node_path35.join)(home, ".claude.json");
12736
- if (!(0, import_node_fs32.existsSync)(claudePath)) return {};
12813
+ const claudePath = home === (0, import_node_os11.homedir)() ? userClaudeMcpConfigPath() : (0, import_node_path36.join)(home, ".claude.json");
12814
+ if (!(0, import_node_fs33.existsSync)(claudePath)) return {};
12737
12815
  return asObject2(asObject2(readJsonObject(claudePath)).mcpServers);
12738
12816
  }
12739
12817
  function listUserClaudeMcpServerEntries(home = (0, import_node_os11.homedir)()) {
@@ -12766,13 +12844,13 @@ function toCodexUnattendedAppsArgs() {
12766
12844
  "features.plugins=false"
12767
12845
  ];
12768
12846
  }
12769
- var import_node_fs32, import_node_os11, import_node_path35, import_smol_toml2;
12847
+ var import_node_fs33, import_node_os11, import_node_path36, import_smol_toml2;
12770
12848
  var init_orch_mcp_isolation = __esm({
12771
12849
  "src/agents/orch-mcp-isolation.ts"() {
12772
12850
  "use strict";
12773
- import_node_fs32 = require("fs");
12851
+ import_node_fs33 = require("fs");
12774
12852
  import_node_os11 = require("os");
12775
- import_node_path35 = require("path");
12853
+ import_node_path36 = require("path");
12776
12854
  import_smol_toml2 = require("smol-toml");
12777
12855
  init_user_mcp_config();
12778
12856
  }
@@ -13135,11 +13213,11 @@ function parseIssuesJson(raw) {
13135
13213
  }
13136
13214
  return [];
13137
13215
  }
13138
- var import_node_fs33, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
13216
+ var import_node_fs34, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
13139
13217
  var init_claude = __esm({
13140
13218
  "src/agents/claude.ts"() {
13141
13219
  "use strict";
13142
- import_node_fs33 = require("fs");
13220
+ import_node_fs34 = require("fs");
13143
13221
  init_run();
13144
13222
  init_app_settings();
13145
13223
  init_claude_mcp();
@@ -13179,7 +13257,7 @@ var init_claude = __esm({
13179
13257
  async detect() {
13180
13258
  const claude = resolveClaudeExecutable();
13181
13259
  if (claude !== "claude") {
13182
- if (!(0, import_node_fs33.existsSync)(claude)) {
13260
+ if (!(0, import_node_fs34.existsSync)(claude)) {
13183
13261
  return {
13184
13262
  agent: "claude",
13185
13263
  installed: false,
@@ -13447,7 +13525,7 @@ async function listCodexModels() {
13447
13525
  if (codex === "codex") {
13448
13526
  const which = await run("which", ["codex"], { reject: false });
13449
13527
  if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
13450
- } else if (!(0, import_node_fs34.existsSync)(codex)) {
13528
+ } else if (!(0, import_node_fs35.existsSync)(codex)) {
13451
13529
  return FALLBACK_CODEX_MODELS;
13452
13530
  }
13453
13531
  const listed = await run(codex, ["debug", "models"], { reject: false });
@@ -13482,12 +13560,12 @@ function usageFromCodex(usage) {
13482
13560
  }
13483
13561
  function codexConfigHasNetworkAccess() {
13484
13562
  const candidates = [
13485
- (0, import_node_path36.join)((0, import_node_os12.homedir)(), ".codex", "config.toml"),
13486
- (0, import_node_path36.join)((0, import_node_os12.homedir)(), ".config", "codex", "config.toml")
13563
+ (0, import_node_path37.join)((0, import_node_os12.homedir)(), ".codex", "config.toml"),
13564
+ (0, import_node_path37.join)((0, import_node_os12.homedir)(), ".config", "codex", "config.toml")
13487
13565
  ];
13488
13566
  for (const path2 of candidates) {
13489
- if (!(0, import_node_fs34.existsSync)(path2)) continue;
13490
- const text7 = (0, import_node_fs34.readFileSync)(path2, "utf8");
13567
+ if (!(0, import_node_fs35.existsSync)(path2)) continue;
13568
+ const text7 = (0, import_node_fs35.readFileSync)(path2, "utf8");
13491
13569
  if (/network_access\s*=\s*true/.test(text7)) return true;
13492
13570
  }
13493
13571
  return false;
@@ -13519,21 +13597,21 @@ function asRecord2(value) {
13519
13597
  return void 0;
13520
13598
  }
13521
13599
  function codexLooksAuthenticated() {
13522
- const authPath = (0, import_node_path36.join)((0, import_node_os12.homedir)(), ".codex", "auth.json");
13523
- if (!(0, import_node_fs34.existsSync)(authPath)) return false;
13600
+ const authPath = (0, import_node_path37.join)((0, import_node_os12.homedir)(), ".codex", "auth.json");
13601
+ if (!(0, import_node_fs35.existsSync)(authPath)) return false;
13524
13602
  try {
13525
- return (0, import_node_fs34.statSync)(authPath).size > 2;
13603
+ return (0, import_node_fs35.statSync)(authPath).size > 2;
13526
13604
  } catch {
13527
13605
  return false;
13528
13606
  }
13529
13607
  }
13530
- var import_node_fs34, import_node_os12, import_node_path36, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
13608
+ var import_node_fs35, import_node_os12, import_node_path37, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
13531
13609
  var init_codex = __esm({
13532
13610
  "src/agents/codex.ts"() {
13533
13611
  "use strict";
13534
- import_node_fs34 = require("fs");
13612
+ import_node_fs35 = require("fs");
13535
13613
  import_node_os12 = require("os");
13536
- import_node_path36 = require("path");
13614
+ import_node_path37 = require("path");
13537
13615
  init_run();
13538
13616
  init_app_settings();
13539
13617
  init_global_workspace();
@@ -13559,7 +13637,7 @@ var init_codex = __esm({
13559
13637
  async detect() {
13560
13638
  const codex = resolveAgentExecutable("codex");
13561
13639
  if (codex !== "codex") {
13562
- if (!(0, import_node_fs34.existsSync)(codex)) {
13640
+ if (!(0, import_node_fs35.existsSync)(codex)) {
13563
13641
  return {
13564
13642
  agent: "codex",
13565
13643
  installed: false,
@@ -14059,21 +14137,21 @@ function platformRipgrepPackage() {
14059
14137
  }
14060
14138
  function usableRipgrepPath(candidate) {
14061
14139
  const raw = candidate?.trim();
14062
- if (!raw || !(0, import_node_path37.isAbsolute)(raw)) return null;
14140
+ if (!raw || !(0, import_node_path38.isAbsolute)(raw)) return null;
14063
14141
  const readable = nodeReadableScriptPath(raw);
14064
- if (!(0, import_node_fs35.existsSync)(readable) || isAsarPath(readable)) return null;
14142
+ if (!(0, import_node_fs36.existsSync)(readable) || isAsarPath(readable)) return null;
14065
14143
  return readable;
14066
14144
  }
14067
14145
  function walkForBundledRipgrep(startFile) {
14068
14146
  if (!startFile) return null;
14069
14147
  const pkg = platformRipgrepPackage();
14070
14148
  const name = rgBinaryName();
14071
- let dir = (0, import_node_path37.dirname)((0, import_node_path37.resolve)(startFile));
14072
- const root = (0, import_node_path37.parse)(dir).root;
14149
+ let dir = (0, import_node_path38.dirname)((0, import_node_path38.resolve)(startFile));
14150
+ const root = (0, import_node_path38.parse)(dir).root;
14073
14151
  while (dir !== root) {
14074
- const hit = usableRipgrepPath((0, import_node_path37.join)(dir, "node_modules", pkg, "bin", name));
14152
+ const hit = usableRipgrepPath((0, import_node_path38.join)(dir, "node_modules", pkg, "bin", name));
14075
14153
  if (hit) return hit;
14076
- const next = (0, import_node_path37.dirname)(dir);
14154
+ const next = (0, import_node_path38.dirname)(dir);
14077
14155
  if (next === dir) break;
14078
14156
  dir = next;
14079
14157
  }
@@ -14083,7 +14161,7 @@ function requireResolveBundledRipgrep(fromFile) {
14083
14161
  try {
14084
14162
  const req = (0, import_node_module2.createRequire)(fromFile);
14085
14163
  const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
14086
- return usableRipgrepPath((0, import_node_path37.join)((0, import_node_path37.dirname)(pkgJson), "bin", rgBinaryName()));
14164
+ return usableRipgrepPath((0, import_node_path38.join)((0, import_node_path38.dirname)(pkgJson), "bin", rgBinaryName()));
14087
14165
  } catch {
14088
14166
  return null;
14089
14167
  }
@@ -14105,13 +14183,13 @@ function cursorRipgrepEnv(opts) {
14105
14183
  const path2 = resolveCursorRipgrepPath(opts);
14106
14184
  return path2 ? { [RIPGREP_ENV]: path2 } : {};
14107
14185
  }
14108
- var import_node_fs35, import_node_module2, import_node_path37, RIPGREP_ENV;
14186
+ var import_node_fs36, import_node_module2, import_node_path38, RIPGREP_ENV;
14109
14187
  var init_cursor_ripgrep = __esm({
14110
14188
  "src/agents/cursor-ripgrep.ts"() {
14111
14189
  "use strict";
14112
- import_node_fs35 = require("fs");
14190
+ import_node_fs36 = require("fs");
14113
14191
  import_node_module2 = require("module");
14114
- import_node_path37 = require("path");
14192
+ import_node_path38 = require("path");
14115
14193
  init_node_launch();
14116
14194
  init_packaged_runtime();
14117
14195
  RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
@@ -14160,11 +14238,11 @@ function entryDir() {
14160
14238
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
14161
14239
  if (cjsDir) return cjsDir;
14162
14240
  try {
14163
- return (0, import_node_path38.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
14241
+ return (0, import_node_path39.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
14164
14242
  } catch {
14165
14243
  try {
14166
14244
  const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
14167
- return (0, import_node_path38.dirname)(req.resolve("@sideboard-ai/core"));
14245
+ return (0, import_node_path39.dirname)(req.resolve("@sideboard-ai/core"));
14168
14246
  } catch {
14169
14247
  return process.cwd();
14170
14248
  }
@@ -14175,27 +14253,27 @@ function cursorRunnerPath() {
14175
14253
  if (packaged) return packaged;
14176
14254
  const root = entryDir();
14177
14255
  const candidates = [
14178
- (0, import_node_path38.join)(root, "agents", "cursor-runner.js"),
14179
- (0, import_node_path38.join)(root, "agents", "cursor-runner.cjs"),
14256
+ (0, import_node_path39.join)(root, "agents", "cursor-runner.js"),
14257
+ (0, import_node_path39.join)(root, "agents", "cursor-runner.cjs"),
14180
14258
  // If somehow resolved from package root instead of dist/
14181
- (0, import_node_path38.join)(root, "dist", "agents", "cursor-runner.js"),
14182
- (0, import_node_path38.join)(root, "dist", "agents", "cursor-runner.cjs"),
14259
+ (0, import_node_path39.join)(root, "dist", "agents", "cursor-runner.js"),
14260
+ (0, import_node_path39.join)(root, "dist", "agents", "cursor-runner.cjs"),
14183
14261
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
14184
- (0, import_node_path38.join)(root, "cursor-runner.ts"),
14185
- (0, import_node_path38.join)(root, "src", "agents", "cursor-runner.ts")
14262
+ (0, import_node_path39.join)(root, "cursor-runner.ts"),
14263
+ (0, import_node_path39.join)(root, "src", "agents", "cursor-runner.ts")
14186
14264
  ];
14187
14265
  for (const candidate of candidates) {
14188
- if ((0, import_node_fs36.existsSync)(candidate)) return candidate;
14266
+ if ((0, import_node_fs37.existsSync)(candidate)) return candidate;
14189
14267
  }
14190
14268
  return candidates[0];
14191
14269
  }
14192
- var import_node_fs36, import_node_module3, import_node_path38, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
14270
+ var import_node_fs37, import_node_module3, import_node_path39, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
14193
14271
  var init_cursor = __esm({
14194
14272
  "src/agents/cursor.ts"() {
14195
14273
  "use strict";
14196
- import_node_fs36 = require("fs");
14274
+ import_node_fs37 = require("fs");
14197
14275
  import_node_module3 = require("module");
14198
- import_node_path38 = require("path");
14276
+ import_node_path39 = require("path");
14199
14277
  import_node_url2 = require("url");
14200
14278
  import_sdk = require("@cursor/sdk");
14201
14279
  init_run();
@@ -14347,7 +14425,7 @@ async function listOpencodeModels() {
14347
14425
  if (opencode === "opencode") {
14348
14426
  const which = await run("which", ["opencode"], { reject: false });
14349
14427
  if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
14350
- } else if (!(0, import_node_fs37.existsSync)(opencode)) {
14428
+ } else if (!(0, import_node_fs38.existsSync)(opencode)) {
14351
14429
  return FALLBACK_OPENCODE_MODELS;
14352
14430
  }
14353
14431
  const listed = await run(opencode, ["models"], { reject: false });
@@ -14377,11 +14455,11 @@ function usageFromOpencode(tokens) {
14377
14455
  cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
14378
14456
  };
14379
14457
  }
14380
- var import_node_fs37, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
14458
+ var import_node_fs38, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
14381
14459
  var init_opencode = __esm({
14382
14460
  "src/agents/opencode.ts"() {
14383
14461
  "use strict";
14384
- import_node_fs37 = require("fs");
14462
+ import_node_fs38 = require("fs");
14385
14463
  init_run();
14386
14464
  init_app_settings();
14387
14465
  init_global_workspace();
@@ -14409,7 +14487,7 @@ var init_opencode = __esm({
14409
14487
  async detect() {
14410
14488
  const opencode = resolveAgentExecutable("opencode");
14411
14489
  if (opencode !== "opencode") {
14412
- if (!(0, import_node_fs37.existsSync)(opencode)) {
14490
+ if (!(0, import_node_fs38.existsSync)(opencode)) {
14413
14491
  return {
14414
14492
  agent: "opencode",
14415
14493
  installed: false,
@@ -15128,14 +15206,14 @@ function accessTokenFromCredentialsJson(raw) {
15128
15206
  }
15129
15207
  }
15130
15208
  function claudeCredentialsPath() {
15131
- const root = process.env.CLAUDE_CONFIG_DIR?.trim() || (0, import_node_path39.join)((0, import_node_os13.homedir)(), ".claude");
15132
- return (0, import_node_path39.join)(root, ".credentials.json");
15209
+ const root = process.env.CLAUDE_CONFIG_DIR?.trim() || (0, import_node_path40.join)((0, import_node_os13.homedir)(), ".claude");
15210
+ return (0, import_node_path40.join)(root, ".credentials.json");
15133
15211
  }
15134
15212
  async function readFileAccessToken() {
15135
15213
  const path2 = claudeCredentialsPath();
15136
- if (!(0, import_node_fs38.existsSync)(path2)) return null;
15214
+ if (!(0, import_node_fs39.existsSync)(path2)) return null;
15137
15215
  try {
15138
- return accessTokenFromCredentialsJson((0, import_node_fs38.readFileSync)(path2, "utf8"));
15216
+ return accessTokenFromCredentialsJson((0, import_node_fs39.readFileSync)(path2, "utf8"));
15139
15217
  } catch {
15140
15218
  return null;
15141
15219
  }
@@ -15239,13 +15317,13 @@ async function getClaudePlanUsage(opts = {}) {
15239
15317
  })();
15240
15318
  return inflight;
15241
15319
  }
15242
- var import_node_fs38, import_node_os13, import_node_path39, CLAUDE_OAUTH_USAGE_URL, CLAUDE_USAGE_TTL_MS, CLAUDE_USAGE_ERROR_TTL_MS, CLAUDE_USAGE_STALE_OK_MS, KEYCHAIN_SERVICES, cache, errorUntil, inflight, lastGood, claudeVersion;
15320
+ var import_node_fs39, import_node_os13, import_node_path40, CLAUDE_OAUTH_USAGE_URL, CLAUDE_USAGE_TTL_MS, CLAUDE_USAGE_ERROR_TTL_MS, CLAUDE_USAGE_STALE_OK_MS, KEYCHAIN_SERVICES, cache, errorUntil, inflight, lastGood, claudeVersion;
15243
15321
  var init_claude_usage_client = __esm({
15244
15322
  "src/agents/claude-usage-client.ts"() {
15245
15323
  "use strict";
15246
- import_node_fs38 = require("fs");
15324
+ import_node_fs39 = require("fs");
15247
15325
  import_node_os13 = require("os");
15248
- import_node_path39 = require("path");
15326
+ import_node_path40 = require("path");
15249
15327
  init_run();
15250
15328
  init_fetch();
15251
15329
  init_app_settings();
@@ -15613,7 +15691,7 @@ function isAgentHostEnvKey(key) {
15613
15691
  }
15614
15692
  function stripHostToolingPath(pathValue) {
15615
15693
  if (!pathValue?.trim()) return "";
15616
- return pathValue.split(import_node_path40.delimiter).filter((part) => part && !HOST_PATH_NOISE.test(part.replace(/\\/g, "/"))).join(import_node_path40.delimiter);
15694
+ return pathValue.split(import_node_path41.delimiter).filter((part) => part && !HOST_PATH_NOISE.test(part.replace(/\\/g, "/"))).join(import_node_path41.delimiter);
15617
15695
  }
15618
15696
  function sanitizeAgentHostEnv(env, cwd) {
15619
15697
  for (const key of Object.keys(env)) {
@@ -15627,11 +15705,11 @@ function sanitizeAgentHostEnv(env, cwd) {
15627
15705
  }
15628
15706
  return env;
15629
15707
  }
15630
- var import_node_path40, DROP_EXACT, DROP_PREFIXES, HOST_PATH_NOISE;
15708
+ var import_node_path41, DROP_EXACT, DROP_PREFIXES, HOST_PATH_NOISE;
15631
15709
  var init_agent_host_env = __esm({
15632
15710
  "src/hook/agent-host-env.ts"() {
15633
15711
  "use strict";
15634
- import_node_path40 = require("path");
15712
+ import_node_path41 = require("path");
15635
15713
  DROP_EXACT = /* @__PURE__ */ new Set([
15636
15714
  "NODE_PATH",
15637
15715
  "NODE_ENV_ELECTRON_VITE",
@@ -15670,15 +15748,15 @@ var init_agent_host_env = __esm({
15670
15748
 
15671
15749
  // src/hook/worktree-pkg-cache.ts
15672
15750
  function worktreePkgCacheRoot(worktreePath) {
15673
- return (0, import_node_path41.join)(worktreePath, WORKTREE_PKG_CACHE_REL);
15751
+ return (0, import_node_path42.join)(worktreePath, WORKTREE_PKG_CACHE_REL);
15674
15752
  }
15675
15753
  function worktreePkgCacheEnv(worktreePath) {
15676
15754
  const root = worktreePkgCacheRoot(worktreePath);
15677
- const store = (0, import_node_path41.join)(root, "pnpm-store");
15678
- const pnpmCache = (0, import_node_path41.join)(root, "pnpm");
15679
- const npmCache = (0, import_node_path41.join)(root, "npm");
15680
- const nodeGyp = (0, import_node_path41.join)(root, "node-gyp");
15681
- const electron = (0, import_node_path41.join)(root, "electron");
15755
+ const store = (0, import_node_path42.join)(root, "pnpm-store");
15756
+ const pnpmCache = (0, import_node_path42.join)(root, "pnpm");
15757
+ const npmCache = (0, import_node_path42.join)(root, "npm");
15758
+ const nodeGyp = (0, import_node_path42.join)(root, "node-gyp");
15759
+ const electron = (0, import_node_path42.join)(root, "electron");
15682
15760
  return {
15683
15761
  npm_config_store_dir: store,
15684
15762
  PNPM_STORE_DIR: store,
@@ -15700,8 +15778,8 @@ function fillGroup(env, keys, values) {
15700
15778
  }
15701
15779
  }
15702
15780
  function ensureWorktreePkgCacheDirs(worktreePath) {
15703
- if (!(0, import_node_fs39.existsSync)(worktreePath)) return;
15704
- (0, import_node_fs39.mkdirSync)(worktreePkgCacheRoot(worktreePath), { recursive: true });
15781
+ if (!(0, import_node_fs40.existsSync)(worktreePath)) return;
15782
+ (0, import_node_fs40.mkdirSync)(worktreePkgCacheRoot(worktreePath), { recursive: true });
15705
15783
  }
15706
15784
  function applyWorktreePkgCacheEnv(env, worktreePath) {
15707
15785
  const cwd = worktreePath.trim();
@@ -15714,12 +15792,12 @@ function applyWorktreePkgCacheEnv(env, worktreePath) {
15714
15792
  fillGroup(env, ["electron_config_cache"], next);
15715
15793
  ensureWorktreePkgCacheDirs(cwd);
15716
15794
  }
15717
- var import_node_fs39, import_node_path41, WORKTREE_PKG_CACHE_REL;
15795
+ var import_node_fs40, import_node_path42, WORKTREE_PKG_CACHE_REL;
15718
15796
  var init_worktree_pkg_cache = __esm({
15719
15797
  "src/hook/worktree-pkg-cache.ts"() {
15720
15798
  "use strict";
15721
- import_node_fs39 = require("fs");
15722
- import_node_path41 = require("path");
15799
+ import_node_fs40 = require("fs");
15800
+ import_node_path42 = require("path");
15723
15801
  WORKTREE_PKG_CACHE_REL = ".context/.sideboard/pkg-cache";
15724
15802
  }
15725
15803
  });
@@ -16960,21 +17038,21 @@ function shouldRefreshReviewRequestTemplate(content) {
16960
17038
  return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
16961
17039
  }
16962
17040
  function readTextIfPresent(abs) {
16963
- if (!(0, import_node_fs40.existsSync)(abs)) return null;
17041
+ if (!(0, import_node_fs41.existsSync)(abs)) return null;
16964
17042
  try {
16965
- const content = (0, import_node_fs40.readFileSync)(abs, "utf8");
17043
+ const content = (0, import_node_fs41.readFileSync)(abs, "utf8");
16966
17044
  return content.trim() ? content : null;
16967
17045
  } catch {
16968
17046
  return null;
16969
17047
  }
16970
17048
  }
16971
17049
  function readLocalGuidelines(worktreePath) {
16972
- const localAbs = (0, import_node_path42.join)(worktreePath, REVIEW_REQUEST_PATH);
17050
+ const localAbs = (0, import_node_path43.join)(worktreePath, REVIEW_REQUEST_PATH);
16973
17051
  const localContent = readTextIfPresent(localAbs);
16974
17052
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
16975
17053
  return { path: REVIEW_REQUEST_PATH, content: localContent };
16976
17054
  }
16977
- const legacyAbs = (0, import_node_path42.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
17055
+ const legacyAbs = (0, import_node_path43.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
16978
17056
  const legacyContent = readTextIfPresent(legacyAbs);
16979
17057
  if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
16980
17058
  return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
@@ -16998,27 +17076,27 @@ function contextGuidelines(content, source) {
16998
17076
  };
16999
17077
  }
17000
17078
  function writeContextGuidelines(worktreePath, content) {
17001
- const abs = (0, import_node_path42.join)(worktreePath, CONTEXT_REVIEW_PATH);
17002
- (0, import_node_fs40.mkdirSync)((0, import_node_path42.dirname)(abs), { recursive: true });
17079
+ const abs = (0, import_node_path43.join)(worktreePath, CONTEXT_REVIEW_PATH);
17080
+ (0, import_node_fs41.mkdirSync)((0, import_node_path43.dirname)(abs), { recursive: true });
17003
17081
  const body = content.endsWith("\n") ? content : `${content}
17004
17082
  `;
17005
- (0, import_node_fs40.writeFileSync)(abs, body, "utf8");
17083
+ (0, import_node_fs41.writeFileSync)(abs, body, "utf8");
17006
17084
  return body;
17007
17085
  }
17008
17086
  function readSideboardReview(worktreePath, repoPath) {
17009
- const fromWorktree = readTextIfPresent((0, import_node_path42.join)(worktreePath, REPO_REVIEW_PATH));
17087
+ const fromWorktree = readTextIfPresent((0, import_node_path43.join)(worktreePath, REPO_REVIEW_PATH));
17010
17088
  if (fromWorktree) return fromWorktree;
17011
17089
  const repo = repoPath?.replace(/\/+$/, "");
17012
17090
  const wt = worktreePath.replace(/\/+$/, "");
17013
17091
  if (!repo || repo === wt) return null;
17014
- return readTextIfPresent((0, import_node_path42.join)(repo, REPO_REVIEW_PATH));
17092
+ return readTextIfPresent((0, import_node_path43.join)(repo, REPO_REVIEW_PATH));
17015
17093
  }
17016
17094
  function ensureReviewGuidelinesFile(worktreePath, repoPath) {
17017
- const skillContent = readTextIfPresent((0, import_node_path42.join)(worktreePath, REVIEW_SKILL_PATH));
17095
+ const skillContent = readTextIfPresent((0, import_node_path43.join)(worktreePath, REVIEW_SKILL_PATH));
17018
17096
  if (skillContent) {
17019
17097
  return { ...skillGuidelines(skillContent, "skill"), wrote: false };
17020
17098
  }
17021
- const contextContent = readTextIfPresent((0, import_node_path42.join)(worktreePath, CONTEXT_REVIEW_PATH));
17099
+ const contextContent = readTextIfPresent((0, import_node_path43.join)(worktreePath, CONTEXT_REVIEW_PATH));
17022
17100
  if (contextContent && !shouldRefreshReviewRequestTemplate(contextContent)) {
17023
17101
  return { ...contextGuidelines(contextContent, "local"), wrote: false };
17024
17102
  }
@@ -17056,7 +17134,7 @@ function buildReviewRequestAttachment(content, opts) {
17056
17134
  };
17057
17135
  }
17058
17136
  function readExistingReviewRequestFile(worktreePath) {
17059
- return readTextIfPresent((0, import_node_path42.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path42.join)(worktreePath, CONTEXT_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path42.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path42.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path42.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
17137
+ return readTextIfPresent((0, import_node_path43.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path43.join)(worktreePath, CONTEXT_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path43.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path43.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path43.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
17060
17138
  }
17061
17139
  async function requestReview(threadRef, send2) {
17062
17140
  const from = findThreadByRef(threadRef);
@@ -17083,13 +17161,13 @@ async function requestReview(threadRef, send2) {
17083
17161
  const started = await send2(tab.id, REVIEW_REQUEST_PREFILL);
17084
17162
  return { tab: started, from };
17085
17163
  }
17086
- var import_node_crypto9, import_node_fs40, import_node_path42, 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;
17164
+ var import_node_crypto9, import_node_fs41, import_node_path43, 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;
17087
17165
  var init_request_review = __esm({
17088
17166
  "src/review/request-review.ts"() {
17089
17167
  "use strict";
17090
17168
  import_node_crypto9 = require("crypto");
17091
- import_node_fs40 = require("fs");
17092
- import_node_path42 = require("path");
17169
+ import_node_fs41 = require("fs");
17170
+ import_node_path43 = require("path");
17093
17171
  init_global_workspace();
17094
17172
  init_chat_tabs();
17095
17173
  init_thread_store();
@@ -17115,9 +17193,9 @@ function matchSimpleGlob(pattern, name) {
17115
17193
  return new RegExp(`^${escaped}$`).test(name);
17116
17194
  }
17117
17195
  function readWorktreeInclude(repoPath) {
17118
- const path2 = (0, import_node_path43.join)(repoPath, ".worktreeinclude");
17119
- if (!(0, import_node_fs41.existsSync)(path2)) return [];
17120
- return (0, import_node_fs41.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
17196
+ const path2 = (0, import_node_path44.join)(repoPath, ".worktreeinclude");
17197
+ if (!(0, import_node_fs42.existsSync)(path2)) return [];
17198
+ return (0, import_node_fs42.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
17121
17199
  }
17122
17200
  function resolveFilesToCopy(repoPath) {
17123
17201
  const fromInclude = readWorktreeInclude(repoPath);
@@ -17127,10 +17205,10 @@ function resolveFilesToCopy(repoPath) {
17127
17205
  if (settings?.fileIncludeGlobs?.length) {
17128
17206
  const matched = [];
17129
17207
  try {
17130
- for (const entry of (0, import_node_fs41.readdirSync)(repoPath, { withFileTypes: true })) {
17208
+ for (const entry of (0, import_node_fs42.readdirSync)(repoPath, { withFileTypes: true })) {
17131
17209
  if (!entry.isFile()) continue;
17132
17210
  for (const glob of settings.fileIncludeGlobs) {
17133
- if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path43.basename)(glob), entry.name)) {
17211
+ if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path44.basename)(glob), entry.name)) {
17134
17212
  matched.push(entry.name);
17135
17213
  break;
17136
17214
  }
@@ -17142,7 +17220,7 @@ function resolveFilesToCopy(repoPath) {
17142
17220
  }
17143
17221
  const defaults = [];
17144
17222
  try {
17145
- for (const entry of (0, import_node_fs41.readdirSync)(repoPath, { withFileTypes: true })) {
17223
+ for (const entry of (0, import_node_fs42.readdirSync)(repoPath, { withFileTypes: true })) {
17146
17224
  if (entry.isFile() && entry.name.startsWith(".env")) {
17147
17225
  defaults.push(entry.name);
17148
17226
  }
@@ -17156,11 +17234,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
17156
17234
  const patterns = resolveFilesToCopy(repoPath);
17157
17235
  const copied = [];
17158
17236
  for (const rel of patterns) {
17159
- const src = (0, import_node_path43.join)(repoPath, rel);
17160
- if (!(0, import_node_fs41.existsSync)(src)) continue;
17161
- const dest = (0, import_node_path43.join)(worktreePath, rel);
17162
- (0, import_node_fs41.mkdirSync)((0, import_node_path43.dirname)(dest), { recursive: true });
17163
- (0, import_node_fs41.copyFileSync)(src, dest);
17237
+ const src = (0, import_node_path44.join)(repoPath, rel);
17238
+ if (!(0, import_node_fs42.existsSync)(src)) continue;
17239
+ const dest = (0, import_node_path44.join)(worktreePath, rel);
17240
+ (0, import_node_fs42.mkdirSync)((0, import_node_path44.dirname)(dest), { recursive: true });
17241
+ (0, import_node_fs42.copyFileSync)(src, dest);
17164
17242
  copied.push(rel);
17165
17243
  }
17166
17244
  return copied;
@@ -17195,7 +17273,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
17195
17273
  const env = stripNestedElectronEnv({
17196
17274
  ...baseEnv ?? process.env
17197
17275
  });
17198
- const name = opts.workspaceName ?? (0, import_node_path43.basename)(opts.worktreePath);
17276
+ const name = opts.workspaceName ?? (0, import_node_path44.basename)(opts.worktreePath);
17199
17277
  const ports = opts.ports ?? [];
17200
17278
  const primary = ports[0];
17201
17279
  env.SIDEBOARD_WORKSPACE_NAME = name;
@@ -17519,14 +17597,14 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
17519
17597
  throw err;
17520
17598
  }
17521
17599
  }
17522
- var import_node_fs41, import_node_child_process5, import_node_net, import_node_path43, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
17600
+ var import_node_fs42, import_node_child_process5, import_node_net, import_node_path44, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
17523
17601
  var init_conductor = __esm({
17524
17602
  "src/hook/conductor.ts"() {
17525
17603
  "use strict";
17526
- import_node_fs41 = require("fs");
17604
+ import_node_fs42 = require("fs");
17527
17605
  import_node_child_process5 = require("child_process");
17528
17606
  import_node_net = require("net");
17529
- import_node_path43 = require("path");
17607
+ import_node_path44 = require("path");
17530
17608
  import_execa4 = require("execa");
17531
17609
  import_node_readline3 = require("readline");
17532
17610
  init_settings();
@@ -17554,9 +17632,9 @@ async function findOrphanWorktrees(repoPaths) {
17554
17632
  repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
17555
17633
  );
17556
17634
  const homeRoot = sideboardWorkspacesDir();
17557
- if ((0, import_node_fs42.existsSync)(homeRoot)) {
17635
+ if ((0, import_node_fs43.existsSync)(homeRoot)) {
17558
17636
  try {
17559
- for (const entry of (0, import_node_fs42.readdirSync)(homeRoot, { withFileTypes: true })) {
17637
+ for (const entry of (0, import_node_fs43.readdirSync)(homeRoot, { withFileTypes: true })) {
17560
17638
  if (!entry.isDirectory()) continue;
17561
17639
  void entry;
17562
17640
  }
@@ -17566,7 +17644,7 @@ async function findOrphanWorktrees(repoPaths) {
17566
17644
  const orphans = [];
17567
17645
  const seen = /* @__PURE__ */ new Set();
17568
17646
  for (const repoPath of repos) {
17569
- if (!repoPath || !(0, import_node_fs42.existsSync)(repoPath)) continue;
17647
+ if (!repoPath || !(0, import_node_fs43.existsSync)(repoPath)) continue;
17570
17648
  try {
17571
17649
  const wts = await listWorktrees(repoPath);
17572
17650
  for (const wt of wts) {
@@ -17577,7 +17655,7 @@ async function findOrphanWorktrees(repoPaths) {
17577
17655
  seen.add(path2);
17578
17656
  let mtimeMs = 0;
17579
17657
  try {
17580
- mtimeMs = (0, import_node_fs42.statSync)(path2).mtimeMs;
17658
+ mtimeMs = (0, import_node_fs43.statSync)(path2).mtimeMs;
17581
17659
  } catch {
17582
17660
  mtimeMs = 0;
17583
17661
  }
@@ -17587,16 +17665,16 @@ async function findOrphanWorktrees(repoPaths) {
17587
17665
  }
17588
17666
  try {
17589
17667
  const root = worktreesRoot(repoPath);
17590
- if ((0, import_node_fs42.existsSync)(root)) {
17591
- for (const entry of (0, import_node_fs42.readdirSync)(root, { withFileTypes: true })) {
17668
+ if ((0, import_node_fs43.existsSync)(root)) {
17669
+ for (const entry of (0, import_node_fs43.readdirSync)(root, { withFileTypes: true })) {
17592
17670
  if (!entry.isDirectory()) continue;
17593
- const path2 = (0, import_node_path44.join)(root, entry.name).replace(/\/$/, "");
17671
+ const path2 = (0, import_node_path45.join)(root, entry.name).replace(/\/$/, "");
17594
17672
  if (known.has(path2) || seen.has(path2)) continue;
17595
- if (!(0, import_node_fs42.existsSync)((0, import_node_path44.join)(path2, ".git"))) continue;
17673
+ if (!(0, import_node_fs43.existsSync)((0, import_node_path45.join)(path2, ".git"))) continue;
17596
17674
  seen.add(path2);
17597
17675
  let mtimeMs = 0;
17598
17676
  try {
17599
- mtimeMs = (0, import_node_fs42.statSync)(path2).mtimeMs;
17677
+ mtimeMs = (0, import_node_fs43.statSync)(path2).mtimeMs;
17600
17678
  } catch {
17601
17679
  mtimeMs = Date.now();
17602
17680
  }
@@ -17657,12 +17735,12 @@ function worktreeCleanupSettings() {
17657
17735
  autoCleanupOrphans: a.autoCleanupOrphans
17658
17736
  };
17659
17737
  }
17660
- var import_node_fs42, import_node_path44;
17738
+ var import_node_fs43, import_node_path45;
17661
17739
  var init_orphan_cleanup = __esm({
17662
17740
  "src/git/orphan-cleanup.ts"() {
17663
17741
  "use strict";
17664
- import_node_fs42 = require("fs");
17665
- import_node_path44 = require("path");
17742
+ import_node_fs43 = require("fs");
17743
+ import_node_path45 = require("path");
17666
17744
  init_worktree();
17667
17745
  init_thread_store();
17668
17746
  init_paths();
@@ -17837,12 +17915,12 @@ async function cloneRepoIntoSideboard(opts) {
17837
17915
  if (!url) throw new Error("Clone URL is required");
17838
17916
  let name = opts.name?.trim();
17839
17917
  if (!name) {
17840
- const leaf = (0, import_node_path45.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
17918
+ const leaf = (0, import_node_path46.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
17841
17919
  name = leaf || "repo";
17842
17920
  }
17843
17921
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
17844
- const dest = (0, import_node_path45.join)(sideboardReposDir(), name);
17845
- if ((0, import_node_fs43.existsSync)(dest)) {
17922
+ const dest = (0, import_node_path46.join)(sideboardReposDir(), name);
17923
+ if ((0, import_node_fs44.existsSync)(dest)) {
17846
17924
  const repoPath2 = await resolveRepoRoot(dest);
17847
17925
  const workspace2 = await ensureWorkspace(repoPath2);
17848
17926
  return { repoPath: repoPath2, workspace: workspace2 };
@@ -17857,12 +17935,12 @@ async function cloneRepoIntoSideboard(opts) {
17857
17935
  const workspace = await ensureWorkspace(repoPath);
17858
17936
  return { repoPath, workspace };
17859
17937
  }
17860
- var import_node_fs43, import_node_path45, import_execa6;
17938
+ var import_node_fs44, import_node_path46, import_execa6;
17861
17939
  var init_clone_repo = __esm({
17862
17940
  "src/git/clone-repo.ts"() {
17863
17941
  "use strict";
17864
- import_node_fs43 = require("fs");
17865
- import_node_path45 = require("path");
17942
+ import_node_fs44 = require("fs");
17943
+ import_node_path46 = require("path");
17866
17944
  import_execa6 = require("execa");
17867
17945
  init_paths();
17868
17946
  init_workspaces();
@@ -17983,24 +18061,24 @@ function jobTreeAlive(pid) {
17983
18061
  return jobAlive(pid) || processGroupAlive(pid);
17984
18062
  }
17985
18063
  function readIntFile(file) {
17986
- if (!(0, import_node_fs44.existsSync)(file)) return null;
17987
- const n = Number.parseInt((0, import_node_fs44.readFileSync)(file, "utf8").trim(), 10);
18064
+ if (!(0, import_node_fs45.existsSync)(file)) return null;
18065
+ const n = Number.parseInt((0, import_node_fs45.readFileSync)(file, "utf8").trim(), 10);
17988
18066
  return Number.isInteger(n) ? n : null;
17989
18067
  }
17990
18068
  function jobDir(root, id, legacy = false) {
17991
- return (0, import_node_path46.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
18069
+ return (0, import_node_path47.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
17992
18070
  }
17993
18071
  function resolveJobDir(root, id) {
17994
18072
  const modern = jobDir(root, id, false);
17995
- if ((0, import_node_fs44.existsSync)(modern)) return modern;
18073
+ if ((0, import_node_fs45.existsSync)(modern)) return modern;
17996
18074
  const legacy = jobDir(root, id, true);
17997
- if ((0, import_node_fs44.existsSync)(legacy)) return legacy;
18075
+ if ((0, import_node_fs45.existsSync)(legacy)) return legacy;
17998
18076
  return modern;
17999
18077
  }
18000
18078
  function listJobIdsIn(root, rel) {
18001
- const dir = (0, import_node_path46.join)(root, rel);
18002
- if (!(0, import_node_fs44.existsSync)(dir)) return [];
18003
- return (0, import_node_fs44.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
18079
+ const dir = (0, import_node_path47.join)(root, rel);
18080
+ if (!(0, import_node_fs45.existsSync)(dir)) return [];
18081
+ return (0, import_node_fs45.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
18004
18082
  }
18005
18083
  function listRunningDetachedJobs(worktreePath) {
18006
18084
  const root = worktreePath.trim();
@@ -18012,7 +18090,7 @@ function listRunningDetachedJobs(worktreePath) {
18012
18090
  const running = [];
18013
18091
  for (const id of ids) {
18014
18092
  const dir = resolveJobDir(root, id);
18015
- const pid = readIntFile((0, import_node_path46.join)(dir, "pid"));
18093
+ const pid = readIntFile((0, import_node_path47.join)(dir, "pid"));
18016
18094
  if (jobTreeAlive(pid)) running.push(id);
18017
18095
  }
18018
18096
  return running.sort();
@@ -18095,8 +18173,8 @@ function planJobContinue(opts) {
18095
18173
  return { action: "none" };
18096
18174
  }
18097
18175
  function tailProgress(logFile, maxLines = 12) {
18098
- if (!(0, import_node_fs44.existsSync)(logFile)) return "(no log yet)";
18099
- const lines = (0, import_node_fs44.readFileSync)(logFile, "utf8").split("\n");
18176
+ if (!(0, import_node_fs45.existsSync)(logFile)) return "(no log yet)";
18177
+ const lines = (0, import_node_fs45.readFileSync)(logFile, "utf8").split("\n");
18100
18178
  return lines.slice(-maxLines).join("\n");
18101
18179
  }
18102
18180
  function lastProgressLine(progress) {
@@ -18104,8 +18182,8 @@ function lastProgressLine(progress) {
18104
18182
  return last ? last.slice(0, 72) : void 0;
18105
18183
  }
18106
18184
  function readLogLines(file) {
18107
- if (!(0, import_node_fs44.existsSync)(file)) return [];
18108
- const lines = (0, import_node_fs44.readFileSync)(file, "utf8").split("\n");
18185
+ if (!(0, import_node_fs45.existsSync)(file)) return [];
18186
+ const lines = (0, import_node_fs45.readFileSync)(file, "utf8").split("\n");
18109
18187
  if (lines.length && lines[lines.length - 1] === "") lines.pop();
18110
18188
  return lines;
18111
18189
  }
@@ -18116,15 +18194,15 @@ function takeDelta(logFile, cursorFile) {
18116
18194
  return { delta: capJobLogDelta(lines.slice(start).join("\n")), nextCursor: lines.length };
18117
18195
  }
18118
18196
  function snapshotJob(dir) {
18119
- const pid = readIntFile((0, import_node_path46.join)(dir, "pid"));
18197
+ const pid = readIntFile((0, import_node_path47.join)(dir, "pid"));
18120
18198
  const running = jobTreeAlive(pid);
18121
18199
  return {
18122
18200
  pid,
18123
18201
  running,
18124
- exitCode: readIntFile((0, import_node_path46.join)(dir, "exit")),
18125
- log: (0, import_node_path46.join)(dir, "log"),
18126
- cursor: (0, import_node_path46.join)(dir, "present.cursor"),
18127
- progress: tailProgress((0, import_node_path46.join)(dir, "log"))
18202
+ exitCode: readIntFile((0, import_node_path47.join)(dir, "exit")),
18203
+ log: (0, import_node_path47.join)(dir, "log"),
18204
+ cursor: (0, import_node_path47.join)(dir, "present.cursor"),
18205
+ progress: tailProgress((0, import_node_path47.join)(dir, "log"))
18128
18206
  };
18129
18207
  }
18130
18208
  function toResult(id, snap, extra) {
@@ -18133,8 +18211,8 @@ function toResult(id, snap, extra) {
18133
18211
  const stillRunning = snap.running && !ok;
18134
18212
  const { delta, nextCursor } = takeDelta(snap.log, snap.cursor);
18135
18213
  try {
18136
- (0, import_node_fs44.mkdirSync)((0, import_node_path46.dirname)(snap.cursor), { recursive: true });
18137
- (0, import_node_fs44.writeFileSync)(snap.cursor, `${nextCursor}
18214
+ (0, import_node_fs45.mkdirSync)((0, import_node_path47.dirname)(snap.cursor), { recursive: true });
18215
+ (0, import_node_fs45.writeFileSync)(snap.cursor, `${nextCursor}
18138
18216
  `);
18139
18217
  } catch {
18140
18218
  }
@@ -18163,7 +18241,7 @@ async function waitForDetachedJob(cwd, id, opts) {
18163
18241
  const dir = resolveJobDir(root, jobId);
18164
18242
  const timeoutMs = mcpWaitForJobTimeoutMs(opts?.timeoutMs);
18165
18243
  const sleep2 = opts?.sleep ?? sleepMs;
18166
- if (!(0, import_node_fs44.existsSync)(dir)) {
18244
+ if (!(0, import_node_fs45.existsSync)(dir)) {
18167
18245
  return {
18168
18246
  stillRunning: false,
18169
18247
  ok: false,
@@ -18209,10 +18287,10 @@ function killProcessTree(pid, signal) {
18209
18287
  }
18210
18288
  function appendJobLog(logFile, line) {
18211
18289
  try {
18212
- (0, import_node_fs44.mkdirSync)((0, import_node_path46.dirname)(logFile), { recursive: true });
18290
+ (0, import_node_fs45.mkdirSync)((0, import_node_path47.dirname)(logFile), { recursive: true });
18213
18291
  const body = line.endsWith("\n") ? line : `${line}
18214
18292
  `;
18215
- (0, import_node_fs44.appendFileSync)(logFile, body);
18293
+ (0, import_node_fs45.appendFileSync)(logFile, body);
18216
18294
  } catch {
18217
18295
  }
18218
18296
  }
@@ -18222,7 +18300,7 @@ async function stopDetachedJob(cwd, id, opts) {
18222
18300
  const dir = resolveJobDir(root, jobId);
18223
18301
  const sleep2 = opts?.sleep ?? sleepMs;
18224
18302
  const why = opts?.reason?.trim() ?? "";
18225
- if (!(0, import_node_fs44.existsSync)(dir)) {
18303
+ if (!(0, import_node_fs45.existsSync)(dir)) {
18226
18304
  return {
18227
18305
  stillRunning: false,
18228
18306
  ok: false,
@@ -18258,10 +18336,10 @@ async function stopDetachedJob(cwd, id, opts) {
18258
18336
  killProcessTree(targetPid, "SIGKILL");
18259
18337
  await sleep2(100);
18260
18338
  }
18261
- const exitFile = (0, import_node_path46.join)(dir, "exit");
18262
- if (!(0, import_node_fs44.existsSync)(exitFile)) {
18339
+ const exitFile = (0, import_node_path47.join)(dir, "exit");
18340
+ if (!(0, import_node_fs45.existsSync)(exitFile)) {
18263
18341
  try {
18264
- (0, import_node_fs44.writeFileSync)(exitFile, "1\n");
18342
+ (0, import_node_fs45.writeFileSync)(exitFile, "1\n");
18265
18343
  } catch {
18266
18344
  }
18267
18345
  }
@@ -18281,12 +18359,12 @@ async function stopDetachedJob(cwd, id, opts) {
18281
18359
  hint: stopped ? MCP_STOP_JOB_HINT : MCP_WAIT_JOB_STILL_RUNNING_HINT
18282
18360
  };
18283
18361
  }
18284
- var import_node_fs44, 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;
18362
+ var import_node_fs45, import_node_path47, 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;
18285
18363
  var init_wait_for_job = __esm({
18286
18364
  "src/mcp/wait-for-job.ts"() {
18287
18365
  "use strict";
18288
- import_node_fs44 = require("fs");
18289
- import_node_path46 = require("path");
18366
+ import_node_fs45 = require("fs");
18367
+ import_node_path47 = require("path");
18290
18368
  init_workspace_scratch();
18291
18369
  init_wait_for_turn();
18292
18370
  MAX_JOB_CONTINUES = 8;
@@ -19831,7 +19909,7 @@ function reuseLiveThread(input, repoPath, match) {
19831
19909
  }
19832
19910
  async function createThread(input, _onSetupLine) {
19833
19911
  const repoPath = await resolveRepoRoot(input.repoPath);
19834
- if (!(0, import_node_fs45.existsSync)(repoPath)) {
19912
+ if (!(0, import_node_fs46.existsSync)(repoPath)) {
19835
19913
  throw new Error(`Repo not found: ${repoPath}`);
19836
19914
  }
19837
19915
  const reused = reuseLiveThread(input, repoPath, {
@@ -20016,11 +20094,11 @@ async function listLinearIssues(agent, repoPath) {
20016
20094
  }
20017
20095
  return adapter.listLinearIssues(repoPath);
20018
20096
  }
20019
- var import_node_fs45;
20097
+ var import_node_fs46;
20020
20098
  var init_create = __esm({
20021
20099
  "src/threads/create.ts"() {
20022
20100
  "use strict";
20023
- import_node_fs45 = require("fs");
20101
+ import_node_fs46 = require("fs");
20024
20102
  init_detect();
20025
20103
  init_worktree();
20026
20104
  init_home_board();
@@ -20172,20 +20250,20 @@ function writeTurnLive(threadId, progress) {
20172
20250
  const path2 = threadLivePath(threadId);
20173
20251
  const tmp = `${path2}.${process.pid}.tmp`;
20174
20252
  try {
20175
- (0, import_node_fs46.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
20176
- (0, import_node_fs46.renameSync)(tmp, path2);
20253
+ (0, import_node_fs47.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
20254
+ (0, import_node_fs47.renameSync)(tmp, path2);
20177
20255
  } catch {
20178
20256
  try {
20179
- (0, import_node_fs46.unlinkSync)(tmp);
20257
+ (0, import_node_fs47.unlinkSync)(tmp);
20180
20258
  } catch {
20181
20259
  }
20182
20260
  }
20183
20261
  }
20184
20262
  function readTurnLive(threadId) {
20185
20263
  const path2 = threadLivePath(threadId);
20186
- if (!(0, import_node_fs46.existsSync)(path2)) return null;
20264
+ if (!(0, import_node_fs47.existsSync)(path2)) return null;
20187
20265
  try {
20188
- const raw = JSON.parse((0, import_node_fs46.readFileSync)(path2, "utf8"));
20266
+ const raw = JSON.parse((0, import_node_fs47.readFileSync)(path2, "utf8"));
20189
20267
  if (!raw || typeof raw.summary !== "string") return null;
20190
20268
  return raw;
20191
20269
  } catch {
@@ -20197,17 +20275,17 @@ function clearTurnLive(threadId) {
20197
20275
  if (buf?.timer) clearTimeout(buf.timer);
20198
20276
  buffers.delete(threadId);
20199
20277
  const path2 = threadLivePath(threadId);
20200
- if (!(0, import_node_fs46.existsSync)(path2)) return;
20278
+ if (!(0, import_node_fs47.existsSync)(path2)) return;
20201
20279
  try {
20202
- (0, import_node_fs46.unlinkSync)(path2);
20280
+ (0, import_node_fs47.unlinkSync)(path2);
20203
20281
  } catch {
20204
20282
  }
20205
20283
  }
20206
- var import_node_fs46, buffers, FLUSH_MS, MAX_PARTS;
20284
+ var import_node_fs47, buffers, FLUSH_MS, MAX_PARTS;
20207
20285
  var init_turn_live = __esm({
20208
20286
  "src/store/turn-live.ts"() {
20209
20287
  "use strict";
20210
- import_node_fs46 = require("fs");
20288
+ import_node_fs47 = require("fs");
20211
20289
  init_message_parts();
20212
20290
  init_paths();
20213
20291
  buffers = /* @__PURE__ */ new Map();
@@ -20451,7 +20529,7 @@ var init_quota_failover = __esm({
20451
20529
  // src/threads/adopt.ts
20452
20530
  function thisModuleFile() {
20453
20531
  const cjsFile = typeof __filename !== "undefined" ? __filename : "";
20454
- return cjsFile || process.argv[1] || (0, import_node_path47.join)(process.cwd(), "package.json");
20532
+ return cjsFile || process.argv[1] || (0, import_node_path48.join)(process.cwd(), "package.json");
20455
20533
  }
20456
20534
  function openReadonlySqlite(file) {
20457
20535
  const req = (0, import_node_module4.createRequire)(thisModuleFile());
@@ -20469,21 +20547,21 @@ function mapAgentType(raw) {
20469
20547
  return null;
20470
20548
  }
20471
20549
  function resolveConductorCursorAgentId(workspacePath) {
20472
- if (!workspacePath || !(0, import_node_fs47.existsSync)(CURSOR_SDK_STORE)) return null;
20550
+ if (!workspacePath || !(0, import_node_fs48.existsSync)(CURSOR_SDK_STORE)) return null;
20473
20551
  const normalized = workspacePath.replace(/\/$/, "");
20474
20552
  let best = null;
20475
20553
  let hashes;
20476
20554
  try {
20477
- hashes = (0, import_node_fs47.readdirSync)(CURSOR_SDK_STORE);
20555
+ hashes = (0, import_node_fs48.readdirSync)(CURSOR_SDK_STORE);
20478
20556
  } catch {
20479
20557
  return null;
20480
20558
  }
20481
20559
  for (const hash of hashes) {
20482
- const agentsFile = (0, import_node_path47.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
20483
- if (!(0, import_node_fs47.existsSync)(agentsFile)) continue;
20560
+ const agentsFile = (0, import_node_path48.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
20561
+ if (!(0, import_node_fs48.existsSync)(agentsFile)) continue;
20484
20562
  let text7;
20485
20563
  try {
20486
- text7 = (0, import_node_fs47.readFileSync)(agentsFile, "utf8");
20564
+ text7 = (0, import_node_fs48.readFileSync)(agentsFile, "utf8");
20487
20565
  } catch {
20488
20566
  continue;
20489
20567
  }
@@ -20507,7 +20585,7 @@ function resolveConductorCursorAgentId(workspacePath) {
20507
20585
  return best?.agentId ?? null;
20508
20586
  }
20509
20587
  async function adoptThread(input) {
20510
- if (!(0, import_node_fs47.existsSync)(input.worktreePath)) {
20588
+ if (!(0, import_node_fs48.existsSync)(input.worktreePath)) {
20511
20589
  throw new Error(`Worktree not found: ${input.worktreePath}`);
20512
20590
  }
20513
20591
  const repoPath = await resolveRepoRoot(input.worktreePath);
@@ -20536,18 +20614,18 @@ function conductorDbPath() {
20536
20614
  return CONDUCTOR_DB;
20537
20615
  }
20538
20616
  function listConductorWorkspaces() {
20539
- if (!(0, import_node_fs47.existsSync)(CONDUCTOR_DB)) {
20617
+ if (!(0, import_node_fs48.existsSync)(CONDUCTOR_DB)) {
20540
20618
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
20541
20619
  }
20542
- const tmp = (0, import_node_fs47.mkdtempSync)((0, import_node_path47.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
20543
- const snapshot = (0, import_node_path47.join)(tmp, "conductor.db");
20620
+ const tmp = (0, import_node_fs48.mkdtempSync)((0, import_node_path48.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
20621
+ const snapshot = (0, import_node_path48.join)(tmp, "conductor.db");
20544
20622
  try {
20545
- (0, import_node_fs47.copyFileSync)(CONDUCTOR_DB, snapshot);
20623
+ (0, import_node_fs48.copyFileSync)(CONDUCTOR_DB, snapshot);
20546
20624
  for (const suffix of ["-wal", "-shm"]) {
20547
20625
  const src = `${CONDUCTOR_DB}${suffix}`;
20548
- if ((0, import_node_fs47.existsSync)(src)) {
20626
+ if ((0, import_node_fs48.existsSync)(src)) {
20549
20627
  try {
20550
- (0, import_node_fs47.copyFileSync)(src, `${snapshot}${suffix}`);
20628
+ (0, import_node_fs48.copyFileSync)(src, `${snapshot}${suffix}`);
20551
20629
  } catch {
20552
20630
  }
20553
20631
  }
@@ -20623,22 +20701,22 @@ function listConductorWorkspaces() {
20623
20701
  db.close();
20624
20702
  }
20625
20703
  } finally {
20626
- (0, import_node_fs47.rmSync)(tmp, { recursive: true, force: true });
20704
+ (0, import_node_fs48.rmSync)(tmp, { recursive: true, force: true });
20627
20705
  }
20628
20706
  }
20629
20707
  function importConductorWorkspace(workspaceId) {
20630
- if (!(0, import_node_fs47.existsSync)(CONDUCTOR_DB)) {
20708
+ if (!(0, import_node_fs48.existsSync)(CONDUCTOR_DB)) {
20631
20709
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
20632
20710
  }
20633
- const tmp = (0, import_node_fs47.mkdtempSync)((0, import_node_path47.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
20634
- const snapshot = (0, import_node_path47.join)(tmp, "conductor.db");
20711
+ const tmp = (0, import_node_fs48.mkdtempSync)((0, import_node_path48.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
20712
+ const snapshot = (0, import_node_path48.join)(tmp, "conductor.db");
20635
20713
  try {
20636
- (0, import_node_fs47.copyFileSync)(CONDUCTOR_DB, snapshot);
20714
+ (0, import_node_fs48.copyFileSync)(CONDUCTOR_DB, snapshot);
20637
20715
  for (const suffix of ["-wal", "-shm"]) {
20638
20716
  const src = `${CONDUCTOR_DB}${suffix}`;
20639
- if ((0, import_node_fs47.existsSync)(src)) {
20717
+ if ((0, import_node_fs48.existsSync)(src)) {
20640
20718
  try {
20641
- (0, import_node_fs47.copyFileSync)(src, `${snapshot}${suffix}`);
20719
+ (0, import_node_fs48.copyFileSync)(src, `${snapshot}${suffix}`);
20642
20720
  } catch {
20643
20721
  }
20644
20722
  }
@@ -20656,7 +20734,7 @@ function importConductorWorkspace(workspaceId) {
20656
20734
  ).get(workspaceId);
20657
20735
  if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
20658
20736
  const worktreePath = String(row.workspacePath);
20659
- if (!(0, import_node_fs47.existsSync)(worktreePath)) {
20737
+ if (!(0, import_node_fs48.existsSync)(worktreePath)) {
20660
20738
  throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
20661
20739
  }
20662
20740
  let sessionId = null;
@@ -20719,31 +20797,31 @@ function importConductorWorkspace(workspaceId) {
20719
20797
  db.close();
20720
20798
  }
20721
20799
  } finally {
20722
- (0, import_node_fs47.rmSync)(tmp, { recursive: true, force: true });
20800
+ (0, import_node_fs48.rmSync)(tmp, { recursive: true, force: true });
20723
20801
  }
20724
20802
  }
20725
20803
  async function importConductorWorkspaceAsync(workspaceId) {
20726
20804
  return importConductorWorkspace(workspaceId);
20727
20805
  }
20728
- var import_node_child_process6, import_node_fs47, import_node_os14, import_node_path47, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
20806
+ var import_node_child_process6, import_node_fs48, import_node_os14, import_node_path48, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
20729
20807
  var init_adopt = __esm({
20730
20808
  "src/threads/adopt.ts"() {
20731
20809
  "use strict";
20732
20810
  import_node_child_process6 = require("child_process");
20733
- import_node_fs47 = require("fs");
20811
+ import_node_fs48 = require("fs");
20734
20812
  import_node_os14 = require("os");
20735
- import_node_path47 = require("path");
20813
+ import_node_path48 = require("path");
20736
20814
  import_node_module4 = require("module");
20737
20815
  init_worktree();
20738
20816
  init_thread_store();
20739
- CONDUCTOR_APP_SUPPORT = (0, import_node_path47.join)(
20817
+ CONDUCTOR_APP_SUPPORT = (0, import_node_path48.join)(
20740
20818
  process.env.HOME ?? "",
20741
20819
  "Library",
20742
20820
  "Application Support",
20743
20821
  "com.conductor.app"
20744
20822
  );
20745
- CONDUCTOR_DB = (0, import_node_path47.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
20746
- CURSOR_SDK_STORE = (0, import_node_path47.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
20823
+ CONDUCTOR_DB = (0, import_node_path48.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
20824
+ CURSOR_SDK_STORE = (0, import_node_path48.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
20747
20825
  }
20748
20826
  });
20749
20827
 
@@ -20810,7 +20888,7 @@ async function openStackLayer(input, _onSetupLine) {
20810
20888
  let createdWorktree = false;
20811
20889
  const trees = await listWorktrees(repoPath);
20812
20890
  const checkedOut = trees.find((w) => w.branch === branchName);
20813
- if (checkedOut?.path && (0, import_node_fs48.existsSync)(checkedOut.path)) {
20891
+ if (checkedOut?.path && (0, import_node_fs49.existsSync)(checkedOut.path)) {
20814
20892
  if (input.reuseExistingWorktree !== false) {
20815
20893
  worktreePath = checkedOut.path;
20816
20894
  } else {
@@ -20952,7 +21030,7 @@ async function initStackFromThread(input, onSetupLine) {
20952
21030
  async function createPrStack(input, onSetupLine) {
20953
21031
  await requireAgent(input.agent);
20954
21032
  const repoPath = await resolveRepoRoot(input.repoPath);
20955
- if (!(0, import_node_fs48.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
21033
+ if (!(0, import_node_fs49.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
20956
21034
  if (!input.branches.length) throw new Error("At least one branch name required");
20957
21035
  const status = await detectGhStack(repoPath);
20958
21036
  if (!status.available) throw new Error(status.reason);
@@ -21019,7 +21097,7 @@ async function createPrStack(input, onSetupLine) {
21019
21097
  }
21020
21098
  }
21021
21099
  const claimed = new Set(threads.map((t) => t.worktreePath));
21022
- if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs48.existsSync)(bootstrap.worktreePath)) {
21100
+ if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs49.existsSync)(bootstrap.worktreePath)) {
21023
21101
  try {
21024
21102
  await removeWorktree(repoPath, bootstrap.worktreePath, {
21025
21103
  deleteBranch: bootstrap.branchName
@@ -21039,11 +21117,11 @@ function stackAgentDefaultsFrom(input) {
21039
21117
  planMode: input.planMode
21040
21118
  };
21041
21119
  }
21042
- var import_node_fs48;
21120
+ var import_node_fs49;
21043
21121
  var init_stack_layers = __esm({
21044
21122
  "src/threads/stack-layers.ts"() {
21045
21123
  "use strict";
21046
- import_node_fs48 = require("fs");
21124
+ import_node_fs49 = require("fs");
21047
21125
  init_detect();
21048
21126
  init_run();
21049
21127
  init_stack();
@@ -21056,7 +21134,7 @@ var init_stack_layers = __esm({
21056
21134
 
21057
21135
  // src/diff/diff.ts
21058
21136
  async function inspectGitWorktree(worktreePath) {
21059
- if (!worktreePath || !(0, import_node_fs49.existsSync)(worktreePath)) return "missing_worktree";
21137
+ if (!worktreePath || !(0, import_node_fs50.existsSync)(worktreePath)) return "missing_worktree";
21060
21138
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
21061
21139
  reject: false
21062
21140
  });
@@ -21064,7 +21142,7 @@ async function inspectGitWorktree(worktreePath) {
21064
21142
  return "ok";
21065
21143
  }
21066
21144
  async function initializeGitRepository(worktreePath) {
21067
- if (!worktreePath || !(0, import_node_fs49.existsSync)(worktreePath)) {
21145
+ if (!worktreePath || !(0, import_node_fs50.existsSync)(worktreePath)) {
21068
21146
  throw new Error("Worktree not found");
21069
21147
  }
21070
21148
  const status = await inspectGitWorktree(worktreePath);
@@ -21198,11 +21276,11 @@ new file mode 100644
21198
21276
  };
21199
21277
  }
21200
21278
  async function untrackedPatch(worktreePath, path2, maxHunk) {
21201
- const abs = (0, import_node_path48.join)(worktreePath, path2);
21279
+ const abs = (0, import_node_path49.join)(worktreePath, path2);
21202
21280
  try {
21203
- const st = (0, import_node_fs49.statSync)(abs);
21281
+ const st = (0, import_node_fs50.statSync)(abs);
21204
21282
  if (st.isFile() && st.size > maxHunk) {
21205
- const buf = (0, import_node_fs49.readFileSync)(abs).subarray(0, maxHunk);
21283
+ const buf = (0, import_node_fs50.readFileSync)(abs).subarray(0, maxHunk);
21206
21284
  return syntheticAddPatch(path2, buf.toString("utf8"), maxHunk);
21207
21285
  }
21208
21286
  } catch {
@@ -21669,9 +21747,9 @@ async function getDiff(worktreePath, repoPath, opts) {
21669
21747
  }
21670
21748
  function statWorktreePath(worktreePath, relativePath) {
21671
21749
  assertSafeRelativePath(relativePath);
21672
- const abs = (0, import_node_path48.join)(worktreePath, relativePath);
21673
- if (!(0, import_node_fs49.existsSync)(abs)) return "missing";
21674
- const st = (0, import_node_fs49.statSync)(abs);
21750
+ const abs = (0, import_node_path49.join)(worktreePath, relativePath);
21751
+ if (!(0, import_node_fs50.existsSync)(abs)) return "missing";
21752
+ const st = (0, import_node_fs50.statSync)(abs);
21675
21753
  if (st.isDirectory()) return "dir";
21676
21754
  if (st.isFile()) return "file";
21677
21755
  return "missing";
@@ -21700,8 +21778,8 @@ function isImageRelativePath(relativePath) {
21700
21778
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
21701
21779
  assertSafeRelativePath(relativePath);
21702
21780
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
21703
- const abs = (0, import_node_path48.join)(worktreePath, relativePath);
21704
- const st = (0, import_node_fs49.statSync)(abs);
21781
+ const abs = (0, import_node_path49.join)(worktreePath, relativePath);
21782
+ const st = (0, import_node_fs50.statSync)(abs);
21705
21783
  if (!st.isFile()) {
21706
21784
  throw new Error(`Not a file: ${relativePath}`);
21707
21785
  }
@@ -21710,7 +21788,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
21710
21788
  `File too large to upload (${st.size} bytes; max ${maxBytes})`
21711
21789
  );
21712
21790
  }
21713
- const buf = (0, import_node_fs49.readFileSync)(abs);
21791
+ const buf = (0, import_node_fs50.readFileSync)(abs);
21714
21792
  return {
21715
21793
  path: relativePath,
21716
21794
  contentBase64: buf.toString("base64"),
@@ -21720,12 +21798,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
21720
21798
  function readWorktreeFile(worktreePath, relativePath, opts) {
21721
21799
  assertSafeRelativePath(relativePath);
21722
21800
  const maxBytes = opts?.maxBytes ?? 2e5;
21723
- const abs = (0, import_node_path48.join)(worktreePath, relativePath);
21724
- const st = (0, import_node_fs49.statSync)(abs);
21801
+ const abs = (0, import_node_path49.join)(worktreePath, relativePath);
21802
+ const st = (0, import_node_fs50.statSync)(abs);
21725
21803
  if (!st.isFile()) {
21726
21804
  throw new Error(`Not a file: ${relativePath}`);
21727
21805
  }
21728
- const buf = (0, import_node_fs49.readFileSync)(abs);
21806
+ const buf = (0, import_node_fs50.readFileSync)(abs);
21729
21807
  if (isImageRelativePath(relativePath)) {
21730
21808
  const maxImageBytes = Math.max(maxBytes, 15e6);
21731
21809
  const truncated2 = buf.length > maxImageBytes;
@@ -21768,9 +21846,9 @@ function assertSafeRelativePath(relativePath) {
21768
21846
  }
21769
21847
  function writeWorktreeFile(worktreePath, relativePath, content) {
21770
21848
  assertSafeRelativePath(relativePath);
21771
- const abs = (0, import_node_path48.join)(worktreePath, relativePath);
21772
- (0, import_node_fs49.mkdirSync)((0, import_node_path48.dirname)(abs), { recursive: true });
21773
- (0, import_node_fs49.writeFileSync)(abs, content, "utf8");
21849
+ const abs = (0, import_node_path49.join)(worktreePath, relativePath);
21850
+ (0, import_node_fs50.mkdirSync)((0, import_node_path49.dirname)(abs), { recursive: true });
21851
+ (0, import_node_fs50.writeFileSync)(abs, content, "utf8");
21774
21852
  return { path: relativePath };
21775
21853
  }
21776
21854
  async function getWorktreeDirtyStat(worktreePath) {
@@ -21810,12 +21888,12 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
21810
21888
  truncated: full.files.length > maxFiles
21811
21889
  };
21812
21890
  }
21813
- var import_node_fs49, import_node_path48, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
21891
+ var import_node_fs50, import_node_path49, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
21814
21892
  var init_diff = __esm({
21815
21893
  "src/diff/diff.ts"() {
21816
21894
  "use strict";
21817
- import_node_fs49 = require("fs");
21818
- import_node_path48 = require("path");
21895
+ import_node_fs50 = require("fs");
21896
+ import_node_path49 = require("path");
21819
21897
  init_run();
21820
21898
  init_worktree();
21821
21899
  mergeBaseCache = /* @__PURE__ */ new Map();
@@ -22172,7 +22250,7 @@ function parseFrontmatter(content) {
22172
22250
  }
22173
22251
  function readSkill(skillMd, source) {
22174
22252
  try {
22175
- const content = (0, import_node_fs50.readFileSync)(skillMd, "utf8");
22253
+ const content = (0, import_node_fs51.readFileSync)(skillMd, "utf8");
22176
22254
  const { name: fmName, description } = parseFrontmatter(content);
22177
22255
  const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
22178
22256
  const name = fmName || dirName;
@@ -22191,19 +22269,19 @@ function readSkill(skillMd, source) {
22191
22269
  }
22192
22270
  }
22193
22271
  function scanSkillsDir(dir, source, out) {
22194
- if (!(0, import_node_fs50.existsSync)(dir)) return;
22272
+ if (!(0, import_node_fs51.existsSync)(dir)) return;
22195
22273
  let entries;
22196
22274
  try {
22197
- entries = (0, import_node_fs50.readdirSync)(dir);
22275
+ entries = (0, import_node_fs51.readdirSync)(dir);
22198
22276
  } catch {
22199
22277
  return;
22200
22278
  }
22201
22279
  for (const entry of entries) {
22202
22280
  if (entry.startsWith(".")) continue;
22203
- const skillMd = (0, import_node_path49.join)(dir, entry, "SKILL.md");
22204
- if (!(0, import_node_fs50.existsSync)(skillMd)) continue;
22281
+ const skillMd = (0, import_node_path50.join)(dir, entry, "SKILL.md");
22282
+ if (!(0, import_node_fs51.existsSync)(skillMd)) continue;
22205
22283
  try {
22206
- if (!(0, import_node_fs50.statSync)(skillMd).isFile()) continue;
22284
+ if (!(0, import_node_fs51.statSync)(skillMd).isFile()) continue;
22207
22285
  } catch {
22208
22286
  continue;
22209
22287
  }
@@ -22212,24 +22290,24 @@ function scanSkillsDir(dir, source, out) {
22212
22290
  }
22213
22291
  }
22214
22292
  function scanClaudePluginSkills(pluginsRoot, out) {
22215
- if (!(0, import_node_fs50.existsSync)(pluginsRoot)) return;
22293
+ if (!(0, import_node_fs51.existsSync)(pluginsRoot)) return;
22216
22294
  const walk = (dir, depth, lookingForSkillsDir) => {
22217
22295
  if (depth > 7) return;
22218
22296
  let entries;
22219
22297
  try {
22220
- entries = (0, import_node_fs50.readdirSync)(dir);
22298
+ entries = (0, import_node_fs51.readdirSync)(dir);
22221
22299
  } catch {
22222
22300
  return;
22223
22301
  }
22224
22302
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
22225
- const skill = readSkill((0, import_node_path49.join)(dir, "SKILL.md"), "cli");
22303
+ const skill = readSkill((0, import_node_path50.join)(dir, "SKILL.md"), "cli");
22226
22304
  if (skill) out.push(skill);
22227
22305
  }
22228
22306
  for (const entry of entries) {
22229
22307
  if (entry === "node_modules" || entry === ".git") continue;
22230
- const full = (0, import_node_path49.join)(dir, entry);
22308
+ const full = (0, import_node_path50.join)(dir, entry);
22231
22309
  try {
22232
- if (!(0, import_node_fs50.statSync)(full).isDirectory()) continue;
22310
+ if (!(0, import_node_fs51.statSync)(full).isDirectory()) continue;
22233
22311
  } catch {
22234
22312
  continue;
22235
22313
  }
@@ -22247,17 +22325,17 @@ function discoverSkills(worktreePath) {
22247
22325
  const home = (0, import_node_os15.homedir)();
22248
22326
  const collected = [];
22249
22327
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
22250
- scanSkillsDir((0, import_node_path49.join)(worktreePath, rel), "workspace", collected);
22328
+ scanSkillsDir((0, import_node_path50.join)(worktreePath, rel), "workspace", collected);
22251
22329
  }
22252
22330
  for (const abs of [
22253
- (0, import_node_path49.join)(home, ".claude/skills"),
22254
- (0, import_node_path49.join)(home, ".cursor/skills"),
22255
- (0, import_node_path49.join)(home, ".sideboard/skills"),
22256
- (0, import_node_path49.join)(home, ".brightsy/skills")
22331
+ (0, import_node_path50.join)(home, ".claude/skills"),
22332
+ (0, import_node_path50.join)(home, ".cursor/skills"),
22333
+ (0, import_node_path50.join)(home, ".sideboard/skills"),
22334
+ (0, import_node_path50.join)(home, ".brightsy/skills")
22257
22335
  ]) {
22258
22336
  scanSkillsDir(abs, "user", collected);
22259
22337
  }
22260
- scanClaudePluginSkills((0, import_node_path49.join)(home, ".claude/plugins"), collected);
22338
+ scanClaudePluginSkills((0, import_node_path50.join)(home, ".claude/plugins"), collected);
22261
22339
  collected.push(...bundledSkills());
22262
22340
  const rank = {
22263
22341
  workspace: 0,
@@ -22283,7 +22361,7 @@ function readSkillBody(skillPath, maxChars = 12e3) {
22283
22361
  \u2026(truncated)` : body;
22284
22362
  }
22285
22363
  }
22286
- const raw = (0, import_node_fs50.readFileSync)(skillPath, "utf8");
22364
+ const raw = (0, import_node_fs51.readFileSync)(skillPath, "utf8");
22287
22365
  if (raw.startsWith("---")) {
22288
22366
  const end = raw.indexOf("\n---", 3);
22289
22367
  if (end >= 0) {
@@ -22297,13 +22375,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
22297
22375
 
22298
22376
  \u2026(truncated)` : raw;
22299
22377
  }
22300
- var import_node_fs50, import_node_os15, import_node_path49, BUNDLED_SKILL_PREFIX;
22378
+ var import_node_fs51, import_node_os15, import_node_path50, BUNDLED_SKILL_PREFIX;
22301
22379
  var init_discover = __esm({
22302
22380
  "src/skills/discover.ts"() {
22303
22381
  "use strict";
22304
- import_node_fs50 = require("fs");
22382
+ import_node_fs51 = require("fs");
22305
22383
  import_node_os15 = require("os");
22306
- import_node_path49 = require("path");
22384
+ import_node_path50 = require("path");
22307
22385
  init_long_running();
22308
22386
  BUNDLED_SKILL_PREFIX = "bundled:";
22309
22387
  }
@@ -22458,7 +22536,7 @@ function compiledModuleDir() {
22458
22536
  try {
22459
22537
  const url = import_meta3.url;
22460
22538
  if (typeof url === "string" && url.length > 0) {
22461
- return (0, import_node_path50.dirname)((0, import_node_url3.fileURLToPath)(url));
22539
+ return (0, import_node_path51.dirname)((0, import_node_url3.fileURLToPath)(url));
22462
22540
  }
22463
22541
  } catch {
22464
22542
  }
@@ -22466,8 +22544,8 @@ function compiledModuleDir() {
22466
22544
  }
22467
22545
  function detachedJobScriptIn(dir) {
22468
22546
  for (const name of DETACHED_JOB_FILENAMES) {
22469
- const script = (0, import_node_path50.join)(dir, "scripts", name);
22470
- if ((0, import_node_fs51.existsSync)(script)) return script;
22547
+ const script = (0, import_node_path51.join)(dir, "scripts", name);
22548
+ if ((0, import_node_fs52.existsSync)(script)) return script;
22471
22549
  }
22472
22550
  return null;
22473
22551
  }
@@ -22484,7 +22562,7 @@ function resolveDetachedJobScript() {
22484
22562
  for (let i = 0; i < 8; i++) {
22485
22563
  const candidate = detachedJobScriptIn(dir);
22486
22564
  if (candidate) return candidate;
22487
- const parent = (0, import_node_path50.dirname)(dir);
22565
+ const parent = (0, import_node_path51.dirname)(dir);
22488
22566
  if (parent === dir) break;
22489
22567
  dir = parent;
22490
22568
  }
@@ -22495,12 +22573,12 @@ function formatDetachedJobInvoke(scriptPath) {
22495
22573
  if (resolved) return `node ${JSON.stringify(resolved)}`;
22496
22574
  return "node scripts/detached-job.cjs";
22497
22575
  }
22498
- var import_node_fs51, import_node_path50, import_node_url3, import_meta3, DETACHED_JOB_FILENAMES;
22576
+ var import_node_fs52, import_node_path51, import_node_url3, import_meta3, DETACHED_JOB_FILENAMES;
22499
22577
  var init_detached_job_path = __esm({
22500
22578
  "src/skills/detached-job-path.ts"() {
22501
22579
  "use strict";
22502
- import_node_fs51 = require("fs");
22503
- import_node_path50 = require("path");
22580
+ import_node_fs52 = require("fs");
22581
+ import_node_path51 = require("path");
22504
22582
  import_node_url3 = require("url");
22505
22583
  init_packaged_runtime();
22506
22584
  import_meta3 = {};
@@ -22682,9 +22760,9 @@ function formatPrGateDirective() {
22682
22760
  }
22683
22761
  function formatProcessGuideDirective(opts) {
22684
22762
  const worktree = opts?.worktreePath?.trim();
22685
- const hasGraphSkill = !!worktree && (0, import_node_fs52.existsSync)((0, import_node_path51.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
22686
- const hasReviewSkill = !!worktree && (0, import_node_fs52.existsSync)((0, import_node_path51.join)(worktree, ".claude/skills/review/SKILL.md"));
22687
- const hasInstallSkill = !!worktree && (0, import_node_fs52.existsSync)((0, import_node_path51.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
22763
+ const hasGraphSkill = !!worktree && (0, import_node_fs53.existsSync)((0, import_node_path52.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
22764
+ const hasReviewSkill = !!worktree && (0, import_node_fs53.existsSync)((0, import_node_path52.join)(worktree, ".claude/skills/review/SKILL.md"));
22765
+ const hasInstallSkill = !!worktree && (0, import_node_fs53.existsSync)((0, import_node_path52.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
22688
22766
  return [
22689
22767
  "Process guides (recurring work only):",
22690
22768
  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,
@@ -22703,12 +22781,13 @@ function formatLongRunningDirective(opts) {
22703
22781
  "- Loop Sideboard MCP `wait_for_job` (returns in ~45s). The desktop opens a `type=log` pane from wait/stop (and shell detached-job JSON) automatically \u2014 you may still `present_artifact` with `artifact_id=<id>` for a custom title. stillRunning \u2192 wait again. Shell fallback: the same helper with `wait <id>`.",
22704
22782
  "- 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.",
22705
22783
  "- 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.",
22706
- "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
22784
+ "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available).",
22785
+ "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."
22707
22786
  ].join("\n");
22708
22787
  }
22709
22788
  function formatLongRunningReminder(opts) {
22710
22789
  const invoke = formatDetachedJobInvoke(opts?.scriptPath);
22711
- 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.`;
22790
+ 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).`;
22712
22791
  }
22713
22792
  function formatArtifactDirective() {
22714
22793
  return [
@@ -22720,14 +22799,14 @@ function formatArtifactDirective() {
22720
22799
  ].join("\n");
22721
22800
  }
22722
22801
  function formatUiReminder() {
22723
- 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.";
22802
+ 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.";
22724
22803
  }
22725
- var import_node_fs52, import_node_path51, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
22804
+ var import_node_fs53, import_node_path52, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
22726
22805
  var init_instructions = __esm({
22727
22806
  "src/agents/instructions.ts"() {
22728
22807
  "use strict";
22729
- import_node_fs52 = require("fs");
22730
- import_node_path51 = require("path");
22808
+ import_node_fs53 = require("fs");
22809
+ import_node_path52 = require("path");
22731
22810
  init_git_auth_mode();
22732
22811
  init_branch_prefix();
22733
22812
  init_worktree_labels();
@@ -23113,40 +23192,40 @@ __export(plan_file_exports, {
23113
23192
  writePlanFile: () => writePlanFile
23114
23193
  });
23115
23194
  function ensureAttachmentsGitignore(worktreePath) {
23116
- const gitignoreAbs = (0, import_node_path52.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
23117
- if ((0, import_node_fs53.existsSync)(gitignoreAbs)) return;
23118
- (0, import_node_fs53.mkdirSync)((0, import_node_path52.dirname)(gitignoreAbs), { recursive: true });
23119
- (0, import_node_fs53.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
23195
+ const gitignoreAbs = (0, import_node_path53.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
23196
+ if ((0, import_node_fs54.existsSync)(gitignoreAbs)) return;
23197
+ (0, import_node_fs54.mkdirSync)((0, import_node_path53.dirname)(gitignoreAbs), { recursive: true });
23198
+ (0, import_node_fs54.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
23120
23199
  }
23121
23200
  function planFileAbs(worktreePath) {
23122
- return (0, import_node_path52.join)(worktreePath, PLAN_FILE_REL);
23201
+ return (0, import_node_path53.join)(worktreePath, PLAN_FILE_REL);
23123
23202
  }
23124
23203
  function readTextIfPresent2(abs) {
23125
- if (!(0, import_node_fs53.existsSync)(abs)) return null;
23204
+ if (!(0, import_node_fs54.existsSync)(abs)) return null;
23126
23205
  try {
23127
- const content = (0, import_node_fs53.readFileSync)(abs, "utf8");
23206
+ const content = (0, import_node_fs54.readFileSync)(abs, "utf8");
23128
23207
  return content.trim() ? content : null;
23129
23208
  } catch {
23130
23209
  return null;
23131
23210
  }
23132
23211
  }
23133
23212
  function readPlanFile(worktreePath) {
23134
- 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));
23213
+ return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path53.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path53.join)(worktreePath, LEGACY_PLAN_FILE_REL));
23135
23214
  }
23136
23215
  function writePlanFile(worktreePath, content) {
23137
23216
  ensureAttachmentsGitignore(worktreePath);
23138
23217
  const abs = planFileAbs(worktreePath);
23139
- (0, import_node_fs53.mkdirSync)((0, import_node_path52.dirname)(abs), { recursive: true });
23218
+ (0, import_node_fs54.mkdirSync)((0, import_node_path53.dirname)(abs), { recursive: true });
23140
23219
  const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
23141
- (0, import_node_fs53.writeFileSync)(abs, body, "utf8");
23220
+ (0, import_node_fs54.writeFileSync)(abs, body, "utf8");
23142
23221
  return PLAN_FILE_REL;
23143
23222
  }
23144
- var import_node_fs53, import_node_path52;
23223
+ var import_node_fs54, import_node_path53;
23145
23224
  var init_plan_file = __esm({
23146
23225
  "src/plan/plan-file.ts"() {
23147
23226
  "use strict";
23148
- import_node_fs53 = require("fs");
23149
- import_node_path52 = require("path");
23227
+ import_node_fs54 = require("fs");
23228
+ import_node_path53 = require("path");
23150
23229
  init_workspace_scratch();
23151
23230
  init_plan_present();
23152
23231
  init_plan_present();
@@ -23208,9 +23287,9 @@ function recoverFinishedCursorRun(opts) {
23208
23287
  return best;
23209
23288
  }
23210
23289
  function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
23211
- if (!(0, import_node_fs54.existsSync)(runsPath)) return null;
23290
+ if (!(0, import_node_fs55.existsSync)(runsPath)) return null;
23212
23291
  try {
23213
- const lines = (0, import_node_fs54.readFileSync)(runsPath, "utf8").split("\n");
23292
+ const lines = (0, import_node_fs55.readFileSync)(runsPath, "utf8").split("\n");
23214
23293
  let best = null;
23215
23294
  for (const line of lines) {
23216
23295
  const trimmed = line.trim();
@@ -23236,11 +23315,11 @@ function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
23236
23315
  return null;
23237
23316
  }
23238
23317
  }
23239
- var import_node_fs54;
23318
+ var import_node_fs55;
23240
23319
  var init_cursor_recover = __esm({
23241
23320
  "src/agents/cursor-recover.ts"() {
23242
23321
  "use strict";
23243
- import_node_fs54 = require("fs");
23322
+ import_node_fs55 = require("fs");
23244
23323
  init_cursor_store();
23245
23324
  }
23246
23325
  });
@@ -23282,6 +23361,7 @@ __export(orchestrator_exports, {
23282
23361
  LIGHT_RECONCILE_THROTTLE_MS: () => LIGHT_RECONCILE_THROTTLE_MS,
23283
23362
  LIVE_TURN_SPAWN_GRACE_MS: () => LIVE_TURN_SPAWN_GRACE_MS,
23284
23363
  Orchestrator: () => Orchestrator,
23364
+ RUN_SCRIPT_DESKTOP_ADOPT_MS: () => RUN_SCRIPT_DESKTOP_ADOPT_MS,
23285
23365
  getOrchestrator: () => getOrchestrator,
23286
23366
  isPidAlive: () => isPidAlive,
23287
23367
  resolveOrchChildFollowUp: () => resolveOrchChildFollowUp,
@@ -23393,13 +23473,14 @@ async function startOrchestration(opts) {
23393
23473
  }
23394
23474
  return updated;
23395
23475
  }
23396
- var import_node_events, import_node_fs55, LIVE_TURN_SPAWN_GRACE_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton;
23476
+ var import_node_events, import_node_crypto12, import_node_fs56, LIVE_TURN_SPAWN_GRACE_MS, RUN_SCRIPT_DESKTOP_ADOPT_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton;
23397
23477
  var init_orchestrator = __esm({
23398
23478
  "src/orchestrator/orchestrator.ts"() {
23399
23479
  "use strict";
23400
23480
  import_node_events = require("events");
23401
23481
  init_outbound_watch();
23402
- import_node_fs55 = require("fs");
23482
+ import_node_crypto12 = require("crypto");
23483
+ import_node_fs56 = require("fs");
23403
23484
  init_error_detail();
23404
23485
  init_run();
23405
23486
  init_stale_lock();
@@ -23416,6 +23497,7 @@ var init_orchestrator = __esm({
23416
23497
  init_history_cleanup();
23417
23498
  init_apply_into_main();
23418
23499
  init_clone_repo();
23500
+ init_thread();
23419
23501
  init_message_parts();
23420
23502
  init_usage();
23421
23503
  init_thread_store();
@@ -23461,6 +23543,7 @@ var init_orchestrator = __esm({
23461
23543
  init_schedule_runner();
23462
23544
  init_coordinator_prompt();
23463
23545
  LIVE_TURN_SPAWN_GRACE_MS = 15e3;
23546
+ RUN_SCRIPT_DESKTOP_ADOPT_MS = 2e4;
23464
23547
  STALE_AGENT_PID_WAIT_MS = 2500;
23465
23548
  LIGHT_RECONCILE_THROTTLE_MS = 1e4;
23466
23549
  Orchestrator = class {
@@ -23499,6 +23582,11 @@ var init_orchestrator = __esm({
23499
23582
  jobContinueNudged = /* @__PURE__ */ new Set();
23500
23583
  /** In-flight startDev per worktree run key — agent MCP + UI Start must not double-spawn. */
23501
23584
  startingDev = /* @__PURE__ */ new Map();
23585
+ /**
23586
+ * MCP/CLI poll budget while Electron main adopts `runScriptRequest`.
23587
+ * Tests shorten this so a missing desktop does not wait 20s.
23588
+ */
23589
+ runScriptAdoptTimeoutMs = RUN_SCRIPT_DESKTOP_ADOPT_MS;
23502
23590
  maxConcurrent;
23503
23591
  runningCount = 0;
23504
23592
  constructor(opts) {
@@ -23567,7 +23655,7 @@ var init_orchestrator = __esm({
23567
23655
  this.lightReconcileAt.set(repoPath, Date.now());
23568
23656
  for (const thread of listThreads()) {
23569
23657
  if (isGlobalThread(thread) || thread.repoPath !== repoPath) continue;
23570
- if (!(0, import_node_fs55.existsSync)(thread.worktreePath)) {
23658
+ if (!(0, import_node_fs56.existsSync)(thread.worktreePath)) {
23571
23659
  setStatus(thread.id, "broken", "Worktree missing on disk");
23572
23660
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
23573
23661
  }
@@ -23596,7 +23684,7 @@ var init_orchestrator = __esm({
23596
23684
  }
23597
23685
  continue;
23598
23686
  }
23599
- if (!(0, import_node_fs55.existsSync)(thread.worktreePath)) {
23687
+ if (!(0, import_node_fs56.existsSync)(thread.worktreePath)) {
23600
23688
  setStatus(thread.id, "broken", "Worktree missing on disk");
23601
23689
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
23602
23690
  continue;
@@ -23668,6 +23756,58 @@ var init_orchestrator = __esm({
23668
23756
  this.armDrain(thread.id);
23669
23757
  }
23670
23758
  }
23759
+ this.adoptPersistedRunScripts();
23760
+ }
23761
+ /**
23762
+ * Adopt run-script start/stop persisted by MCP/CLI while this process owns
23763
+ * live children (desktop host). Spawning in stdio leaves the Run tab on
23764
+ * "Starting…" with no logs — `run_output` never reaches the renderer.
23765
+ */
23766
+ adoptPersistedRunScripts() {
23767
+ if (!this.shouldOwnRunScripts()) return;
23768
+ for (const thread of listThreads()) {
23769
+ if (thread.status === "archived") continue;
23770
+ const req = thread.runScriptRequest;
23771
+ if (!isUnclaimedRunScriptRequest(req) || !req) continue;
23772
+ const claimedAt = (/* @__PURE__ */ new Date()).toISOString();
23773
+ const claimed = { ...req, claimedAt };
23774
+ updateThread(thread.id, { runScriptRequest: claimed });
23775
+ void this.applyRunScriptRequest(thread.id, claimed);
23776
+ }
23777
+ }
23778
+ async applyRunScriptRequest(threadId, req) {
23779
+ try {
23780
+ if (req.op === "start") {
23781
+ await this.startDev(threadId, req.scriptName ?? void 0);
23782
+ } else {
23783
+ await this.stopDev(threadId, req.scriptName ?? void 0);
23784
+ }
23785
+ const latest = readThread(threadId);
23786
+ const current = latest?.runScriptRequest;
23787
+ if (current?.requestId === req.requestId && !current.error) {
23788
+ updateThread(threadId, {
23789
+ runScriptRequest: {
23790
+ ...current,
23791
+ fulfilledAt: (/* @__PURE__ */ new Date()).toISOString()
23792
+ }
23793
+ });
23794
+ }
23795
+ } catch (err) {
23796
+ const message = err instanceof Error ? err.message : String(err);
23797
+ const latest = readThread(threadId);
23798
+ const current = latest?.runScriptRequest;
23799
+ if (!current || current.requestId !== req.requestId) return;
23800
+ updateThread(threadId, {
23801
+ runScriptRequest: { ...current, error: message }
23802
+ });
23803
+ }
23804
+ }
23805
+ /**
23806
+ * Same rule as agent-queue drain: MCP stdio must not own Electron children
23807
+ * while Sideboard.app is alive.
23808
+ */
23809
+ shouldOwnRunScripts() {
23810
+ return thisProcessShouldDrainAgentQueues();
23671
23811
  }
23672
23812
  /**
23673
23813
  * Mid-session: a worktree can sit at `running` after the agent process dies
@@ -24716,6 +24856,13 @@ var init_orchestrator = __esm({
24716
24856
  "No run script found for this worktree. Add [scripts.run.*] in the worktree\u2019s .sideboard/settings.toml or .conductor/settings.toml (or settings.local.toml on the main repo)."
24717
24857
  );
24718
24858
  }
24859
+ if (!this.shouldOwnRunScripts()) {
24860
+ const result = await this.requestDesktopRunScript(thread, "start", resolvedName);
24861
+ if (!result) {
24862
+ throw new Error("Desktop did not return a run script port.");
24863
+ }
24864
+ return result;
24865
+ }
24719
24866
  const runKey = worktreeRunProcessKey(thread.worktreePath, resolvedName);
24720
24867
  const inFlight = this.startingDev.get(runKey);
24721
24868
  if (inFlight) return inFlight;
@@ -24838,8 +24985,65 @@ var init_orchestrator = __esm({
24838
24985
  });
24839
24986
  return { port: handle.port, scriptName: resolvedName, ports: handle.ports };
24840
24987
  }
24841
- stopDev(threadRef, scriptName) {
24988
+ /**
24989
+ * Persist a run-script intent for the desktop host (MCP/CLI while the board
24990
+ * is alive). Polls until Electron main adopts and fulfills it.
24991
+ */
24992
+ async requestDesktopRunScript(thread, op, scriptName) {
24993
+ const latest = readThread(thread.id) ?? thread;
24994
+ const pending = latest.runScriptRequest;
24995
+ const claimedAt = pending?.claimedAt;
24996
+ const staleClaim = typeof claimedAt === "string" && Date.now() - Date.parse(claimedAt) > this.runScriptAdoptTimeoutMs;
24997
+ const sameIntent = pending && pending.op === op && (pending.scriptName ?? null) === (scriptName ?? null) && !pending.error && !pending.fulfilledAt && !staleClaim;
24998
+ const request = sameIntent ? pending : {
24999
+ op,
25000
+ scriptName: scriptName ?? null,
25001
+ requestId: (0, import_node_crypto12.randomUUID)(),
25002
+ requestedAt: (/* @__PURE__ */ new Date()).toISOString()
25003
+ };
25004
+ if (!sameIntent) {
25005
+ updateThread(thread.id, { runScriptRequest: request });
25006
+ }
25007
+ return this.waitForDesktopRunScript(thread.id, request, op, scriptName);
25008
+ }
25009
+ async waitForDesktopRunScript(threadId, request, op, scriptName) {
25010
+ const deadline = Date.now() + this.runScriptAdoptTimeoutMs;
25011
+ while (Date.now() < deadline) {
25012
+ const latest = readThread(threadId);
25013
+ if (!latest) {
25014
+ throw new Error("Thread disappeared while waiting for the desktop run script.");
25015
+ }
25016
+ const req = latest.runScriptRequest;
25017
+ if (req?.requestId === request.requestId && req.error) {
25018
+ throw new Error(req.error);
25019
+ }
25020
+ const shared = mergeWorktreeActiveRuns(threadsSharingWorktree(latest.worktreePath));
25021
+ const run2 = scriptName ? shared.activeRuns.find((r) => r.scriptName === scriptName) : shared.activeRuns[0];
25022
+ const fulfilled = req?.requestId === request.requestId && Boolean(req.fulfilledAt);
25023
+ const requestGone = !req || req.requestId !== request.requestId;
25024
+ if (op === "start") {
25025
+ if (run2 && (fulfilled || requestGone || run2.startedAt >= request.requestedAt)) {
25026
+ return { port: run2.port, scriptName: run2.scriptName, ports: run2.ports };
25027
+ }
25028
+ if (fulfilled && !run2) {
25029
+ throw new Error("Desktop reported the run script started, but it is not active.");
25030
+ }
25031
+ } else {
25032
+ const gone = scriptName ? !run2 : shared.activeRuns.length === 0;
25033
+ if (fulfilled || gone) return null;
25034
+ }
25035
+ await new Promise((r) => setTimeout(r, 40));
25036
+ }
25037
+ throw new Error(
25038
+ op === "start" ? "Desktop did not start the run script in time. Is Sideboard.app running this worktree?" : "Desktop did not stop the run script in time."
25039
+ );
25040
+ }
25041
+ async stopDev(threadRef, scriptName) {
24842
25042
  const thread = this.requireThread(threadRef);
25043
+ if (!this.shouldOwnRunScripts()) {
25044
+ await this.requestDesktopRunScript(thread, "stop", scriptName);
25045
+ return;
25046
+ }
24843
25047
  const siblings = threadsSharingWorktree(thread.worktreePath);
24844
25048
  const shared = mergeWorktreeActiveRuns(siblings);
24845
25049
  if (scriptName) {
@@ -25750,7 +25954,7 @@ var init_orchestrator = __esm({
25750
25954
  this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
25751
25955
  return restored2;
25752
25956
  }
25753
- if (!(0, import_node_fs55.existsSync)(thread.worktreePath)) {
25957
+ if (!(0, import_node_fs56.existsSync)(thread.worktreePath)) {
25754
25958
  if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
25755
25959
  throw new Error(
25756
25960
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
@@ -25965,6 +26169,9 @@ __export(index_exports, {
25965
26169
  ABLETIME_ORG_KEY_PREFIX: () => ABLETIME_ORG_KEY_PREFIX,
25966
26170
  ABLETIME_PAT_PREFIX: () => ABLETIME_PAT_PREFIX,
25967
26171
  ABLETIME_PM_TOOL_NAMES: () => ABLETIME_PM_TOOL_NAMES,
26172
+ AGENT_DONE_CUSTOM_SOUND_EXTENSIONS: () => AGENT_DONE_CUSTOM_SOUND_EXTENSIONS,
26173
+ AGENT_DONE_CUSTOM_SOUND_MAX_BYTES: () => AGENT_DONE_CUSTOM_SOUND_MAX_BYTES,
26174
+ AGENT_DONE_SOUNDS: () => AGENT_DONE_SOUNDS,
25968
26175
  AGENT_GIT_ACTIONS: () => AGENT_GIT_ACTIONS,
25969
26176
  AGENT_RUNNER_MAX_OLD_SPACE_MB: () => AGENT_RUNNER_MAX_OLD_SPACE_MB,
25970
26177
  ATTACHMENTS_DIR: () => ATTACHMENTS_DIR,
@@ -26044,6 +26251,7 @@ __export(index_exports, {
26044
26251
  REVIEW_REQUEST_TEMPLATE: () => REVIEW_REQUEST_TEMPLATE,
26045
26252
  REVIEW_SKILL_NAME: () => REVIEW_SKILL_NAME,
26046
26253
  REVIEW_SKILL_PATH: () => REVIEW_SKILL_PATH,
26254
+ RUN_SCRIPT_DESKTOP_ADOPT_MS: () => RUN_SCRIPT_DESKTOP_ADOPT_MS,
26047
26255
  SEED_FULL_TOOL_MESSAGES: () => SEED_FULL_TOOL_MESSAGES,
26048
26256
  SEED_MAX_CHARS: () => SEED_MAX_CHARS,
26049
26257
  SESSION_RESET_OCCUPANCY_TOKENS: () => SESSION_RESET_OCCUPANCY_TOKENS,
@@ -26087,6 +26295,9 @@ __export(index_exports, {
26087
26295
  addStackLayerFromThread: () => addStackLayerFromThread,
26088
26296
  addWorkspace: () => addWorkspace,
26089
26297
  adoptThread: () => adoptThread,
26298
+ agentDoneCustomSoundMime: () => agentDoneCustomSoundMime,
26299
+ agentDoneSound: () => agentDoneSound,
26300
+ agentDoneSoundsDir: () => agentDoneSoundsDir,
26090
26301
  agentGitPrompt: () => agentGitPrompt,
26091
26302
  alignQueueAttachments: () => alignQueueAttachments,
26092
26303
  allAdapters: () => allAdapters,
@@ -26165,6 +26376,7 @@ __export(index_exports, {
26165
26376
  claudeUserSettingsPath: () => claudeUserSettingsPath,
26166
26377
  cleanupArchivedHistory: () => cleanupArchivedHistory,
26167
26378
  cleanupOrphanWorktrees: () => cleanupOrphanWorktrees,
26379
+ clearAgentDoneCustomSoundFile: () => clearAgentDoneCustomSoundFile,
26168
26380
  clearBoardPins: () => clearBoardPins,
26169
26381
  clearHomeBoardCache: () => clearHomeBoardCache,
26170
26382
  clipAgentEventForPaint: () => clipAgentEventForPaint,
@@ -26267,6 +26479,7 @@ __export(index_exports, {
26267
26479
  fetchOriginForWorktree: () => fetchOriginForWorktree,
26268
26480
  fetchPrHead: () => fetchPrHead,
26269
26481
  finalizeParts: () => finalizeParts,
26482
+ findAgentDoneCustomSoundPath: () => findAgentDoneCustomSoundPath,
26270
26483
  findConventionSetup: () => findConventionSetup,
26271
26484
  findInvalidCacheControlTtlOrder: () => findInvalidCacheControlTtlOrder,
26272
26485
  findLastBrightsyContextSummary: () => findLastBrightsyContextSummary,
@@ -26401,6 +26614,7 @@ __export(index_exports, {
26401
26614
  historyMaxDays: () => historyMaxDays,
26402
26615
  hottestClaudeWindow: () => hottestClaudeWindow,
26403
26616
  httpFetch: () => httpFetch,
26617
+ importAgentDoneCustomSound: () => importAgentDoneCustomSound,
26404
26618
  importConductorWorkspace: () => importConductorWorkspace,
26405
26619
  importConductorWorkspaceAsync: () => importConductorWorkspaceAsync,
26406
26620
  initPrStack: () => initPrStack,
@@ -26416,6 +26630,7 @@ __export(index_exports, {
26416
26630
  isAbleTimeConnected: () => isAbleTimeConnected,
26417
26631
  isAbleTimeOAuthCancelled: () => isAbleTimeOAuthCancelled,
26418
26632
  isAbleTimeRejectedCredential: () => isAbleTimeRejectedCredential,
26633
+ isAgentDoneSound: () => isAgentDoneSound,
26419
26634
  isAskUserToolName: () => isAskUserToolName,
26420
26635
  isBrightsyConnected: () => isBrightsyConnected,
26421
26636
  isBrightsyNdjsonLine: () => isBrightsyNdjsonLine,
@@ -26466,6 +26681,7 @@ __export(index_exports, {
26466
26681
  isThisProcessDesktopHost: () => isThisProcessDesktopHost,
26467
26682
  isThreadCaffeinated: () => isThreadCaffeinated,
26468
26683
  isThreadRecordFile: () => isThreadRecordFile,
26684
+ isUnclaimedRunScriptRequest: () => isUnclaimedRunScriptRequest,
26469
26685
  isUsageOnLimit: () => isUsageOnLimit,
26470
26686
  isWorkspaceScratchPath: () => isWorkspaceScratchPath,
26471
26687
  issueAttachmentForAbleTimeTask: () => issueAttachmentForAbleTimeTask,
@@ -26607,6 +26823,7 @@ __export(index_exports, {
26607
26823
  primaryCheckoutFromLinkedWorktree: () => primaryCheckoutFromLinkedWorktree,
26608
26824
  promptMentionsBrightsy: () => promptMentionsBrightsy,
26609
26825
  pushBranch: () => pushBranch,
26826
+ readAgentDoneCustomSound: () => readAgentDoneCustomSound,
26610
26827
  readExistingReviewRequestFile: () => readExistingReviewRequestFile,
26611
26828
  readKeychainVaultKey: () => readKeychainVaultKey,
26612
26829
  readPlanFile: () => readPlanFile,
@@ -26835,9 +27052,99 @@ __export(index_exports, {
26835
27052
  writeWorktreeFile: () => writeWorktreeFile
26836
27053
  });
26837
27054
  module.exports = __toCommonJS(index_exports);
27055
+ init_thread();
26838
27056
  init_thinking_effort();
26839
27057
  init_paths();
26840
27058
  init_app_settings();
27059
+
27060
+ // src/store/agent-done-sound.ts
27061
+ var import_node_fs8 = require("fs");
27062
+ var import_node_path9 = require("path");
27063
+ init_paths();
27064
+ var AGENT_DONE_CUSTOM_SOUND_MAX_BYTES = 5 * 1024 * 1024;
27065
+ var AUDIO_EXT_MIME = {
27066
+ ".mp3": "audio/mpeg",
27067
+ ".wav": "audio/wav",
27068
+ ".ogg": "audio/ogg",
27069
+ ".m4a": "audio/mp4",
27070
+ ".aac": "audio/aac",
27071
+ ".caf": "audio/x-caf",
27072
+ ".flac": "audio/flac"
27073
+ };
27074
+ var AGENT_DONE_CUSTOM_SOUND_EXTENSIONS = Object.keys(AUDIO_EXT_MIME);
27075
+ function agentDoneSoundsDir() {
27076
+ const dir = (0, import_node_path9.join)(appDataDir(), "sounds");
27077
+ (0, import_node_fs8.mkdirSync)(dir, { recursive: true });
27078
+ return dir;
27079
+ }
27080
+ function normalizeExt(ext) {
27081
+ const e = ext.trim().toLowerCase();
27082
+ return e.startsWith(".") ? e : `.${e}`;
27083
+ }
27084
+ function agentDoneCustomSoundMime(extOrPath) {
27085
+ const ext = normalizeExt((0, import_node_path9.extname)(extOrPath) || extOrPath);
27086
+ return AUDIO_EXT_MIME[ext] ?? null;
27087
+ }
27088
+ function findAgentDoneCustomSoundPath() {
27089
+ const dir = agentDoneSoundsDir();
27090
+ for (const name of (0, import_node_fs8.readdirSync)(dir)) {
27091
+ if (!name.startsWith("agent-done.")) continue;
27092
+ const full = (0, import_node_path9.join)(dir, name);
27093
+ if ((0, import_node_fs8.existsSync)(full) && agentDoneCustomSoundMime(name)) return full;
27094
+ }
27095
+ return null;
27096
+ }
27097
+ function clearAgentDoneCustomSoundFile() {
27098
+ const dir = agentDoneSoundsDir();
27099
+ for (const name of (0, import_node_fs8.readdirSync)(dir)) {
27100
+ if (!name.startsWith("agent-done.")) continue;
27101
+ try {
27102
+ (0, import_node_fs8.unlinkSync)((0, import_node_path9.join)(dir, name));
27103
+ } catch {
27104
+ }
27105
+ }
27106
+ }
27107
+ function importAgentDoneCustomSound(sourcePath) {
27108
+ const trimmed = sourcePath.trim();
27109
+ if (!trimmed || !(0, import_node_fs8.existsSync)(trimmed)) {
27110
+ throw new Error("Sound file not found");
27111
+ }
27112
+ const ext = normalizeExt((0, import_node_path9.extname)(trimmed));
27113
+ const mime = AUDIO_EXT_MIME[ext];
27114
+ if (!mime) {
27115
+ throw new Error(
27116
+ `Unsupported audio type (use ${AGENT_DONE_CUSTOM_SOUND_EXTENSIONS.join(", ")})`
27117
+ );
27118
+ }
27119
+ const data = (0, import_node_fs8.readFileSync)(trimmed);
27120
+ if (data.byteLength === 0) throw new Error("Sound file is empty");
27121
+ if (data.byteLength > AGENT_DONE_CUSTOM_SOUND_MAX_BYTES) {
27122
+ throw new Error("Sound file is too large (max 5 MB)");
27123
+ }
27124
+ clearAgentDoneCustomSoundFile();
27125
+ const dest = (0, import_node_path9.join)(agentDoneSoundsDir(), `agent-done${ext}`);
27126
+ (0, import_node_fs8.copyFileSync)(trimmed, dest);
27127
+ return {
27128
+ name: (0, import_node_path9.basename)(trimmed),
27129
+ path: dest,
27130
+ mime
27131
+ };
27132
+ }
27133
+ function readAgentDoneCustomSound(displayName2) {
27134
+ const path2 = findAgentDoneCustomSoundPath();
27135
+ if (!path2) return null;
27136
+ const mime = agentDoneCustomSoundMime(path2);
27137
+ if (!mime) return null;
27138
+ const data = (0, import_node_fs8.readFileSync)(path2);
27139
+ if (data.byteLength === 0) return null;
27140
+ return {
27141
+ name: displayName2?.trim() || (0, import_node_path9.basename)(path2),
27142
+ mime,
27143
+ dataBase64: data.toString("base64")
27144
+ };
27145
+ }
27146
+
27147
+ // src/index.ts
26841
27148
  init_caffeinate_hold();
26842
27149
  init_secure_file();
26843
27150
  init_thread_store();
@@ -27052,7 +27359,7 @@ function issueActivityKind(issue, sinceIso) {
27052
27359
  }
27053
27360
 
27054
27361
  // src/integrations/linear-oauth.ts
27055
- var import_node_crypto12 = require("crypto");
27362
+ var import_node_crypto13 = require("crypto");
27056
27363
  var import_node_http2 = require("http");
27057
27364
  init_app_settings();
27058
27365
  init_fetch();
@@ -27084,8 +27391,8 @@ function linearOAuthCredentials() {
27084
27391
  return { clientId, clientSecret };
27085
27392
  }
27086
27393
  function createLinearPkce() {
27087
- const verifier = (0, import_node_crypto12.randomBytes)(32).toString("base64url");
27088
- const challenge = (0, import_node_crypto12.createHash)("sha256").update(verifier).digest("base64url");
27394
+ const verifier = (0, import_node_crypto13.randomBytes)(32).toString("base64url");
27395
+ const challenge = (0, import_node_crypto13.createHash)("sha256").update(verifier).digest("base64url");
27089
27396
  return { verifier, challenge };
27090
27397
  }
27091
27398
  function linearOAuthAuthorizeUrl(clientId, state, codeChallenge) {
@@ -27216,7 +27523,7 @@ async function startLinearOAuth(opts) {
27216
27523
  throw new LinearOAuthCancelledError();
27217
27524
  }
27218
27525
  const { clientId, clientSecret } = linearOAuthCredentials();
27219
- const state = (0, import_node_crypto12.randomBytes)(16).toString("hex");
27526
+ const state = (0, import_node_crypto13.randomBytes)(16).toString("hex");
27220
27527
  const pkce = createLinearPkce();
27221
27528
  const authorizeUrl = linearOAuthAuthorizeUrl(clientId, state, pkce.challenge);
27222
27529
  const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
@@ -29071,7 +29378,7 @@ init_stage_files();
29071
29378
  init_consume_attachments();
29072
29379
 
29073
29380
  // src/composer/pasted-text.ts
29074
- var import_node_crypto13 = require("crypto");
29381
+ var import_node_crypto14 = require("crypto");
29075
29382
  var PASTE_ATTACH_MIN_CHARS = 1200;
29076
29383
  var PASTE_ATTACH_MIN_LINES = 15;
29077
29384
  var PASTED_NAME_RE = /^Pasted text #(\d+)\.txt$/i;
@@ -29098,7 +29405,7 @@ function nextPastedTextName(existing) {
29098
29405
  }
29099
29406
  function buildPastedTextAttachment(text7, opts) {
29100
29407
  return {
29101
- id: opts?.id ?? (0, import_node_crypto13.randomUUID)(),
29408
+ id: opts?.id ?? (0, import_node_crypto14.randomUUID)(),
29102
29409
  name: opts?.name ?? "Pasted text #1.txt",
29103
29410
  kind: "file",
29104
29411
  path: opts?.path,
@@ -29254,8 +29561,8 @@ init_history_cleanup();
29254
29561
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
29255
29562
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
29256
29563
  var import_zod9 = require("zod");
29257
- var import_node_crypto15 = require("crypto");
29258
- var import_node_path55 = require("path");
29564
+ var import_node_crypto16 = require("crypto");
29565
+ var import_node_path56 = require("path");
29259
29566
  init_orchestrator();
29260
29567
  init_worktree();
29261
29568
  init_global_workspace();
@@ -29272,6 +29579,23 @@ function mcpArchiveBlockedReason(thread) {
29272
29579
 
29273
29580
  // src/mcp/server.ts
29274
29581
  init_profile();
29582
+
29583
+ // src/mcp/run-script-ref.ts
29584
+ init_chat_tabs();
29585
+ function resolveRunScriptThreadRef(ref) {
29586
+ const explicit = ref?.trim();
29587
+ if (explicit) return explicit;
29588
+ const siblings = threadsSharingWorktree(process.cwd());
29589
+ const thread = siblings[0];
29590
+ if (!thread) {
29591
+ throw new Error(
29592
+ "No Sideboard thread for this cwd. Pass ref (thread id), or call from a worktree chat."
29593
+ );
29594
+ }
29595
+ return thread.id;
29596
+ }
29597
+
29598
+ // src/mcp/server.ts
29275
29599
  init_wait_for_turn();
29276
29600
  init_wait_for_job();
29277
29601
  init_message_parts();
@@ -30975,27 +31299,27 @@ init_gh_errors();
30975
31299
  init_git_auth_mode();
30976
31300
 
30977
31301
  // src/board/load-home-board.ts
30978
- var import_node_fs57 = require("fs");
30979
- var import_node_path54 = require("path");
31302
+ var import_node_fs58 = require("fs");
31303
+ var import_node_path55 = require("path");
30980
31304
  init_worktree();
30981
31305
  init_paths();
30982
31306
 
30983
31307
  // src/board/board-pins.ts
30984
- var import_node_crypto14 = require("crypto");
30985
- var import_node_fs56 = require("fs");
30986
- var import_node_path53 = require("path");
31308
+ var import_node_crypto15 = require("crypto");
31309
+ var import_node_fs57 = require("fs");
31310
+ var import_node_path54 = require("path");
30987
31311
  init_paths();
30988
31312
  init_home_board();
30989
31313
  var FILE = "home-board-pins.json";
30990
31314
  var VERSION = 1;
30991
31315
  function pinsFile() {
30992
- return (0, import_node_path53.join)(appDataDir(), FILE);
31316
+ return (0, import_node_path54.join)(appDataDir(), FILE);
30993
31317
  }
30994
31318
  function readDisk() {
30995
31319
  const path2 = pinsFile();
30996
- if (!(0, import_node_fs56.existsSync)(path2)) return [];
31320
+ if (!(0, import_node_fs57.existsSync)(path2)) return [];
30997
31321
  try {
30998
- const raw = JSON.parse((0, import_node_fs56.readFileSync)(path2, "utf8"));
31322
+ const raw = JSON.parse((0, import_node_fs57.readFileSync)(path2, "utf8"));
30999
31323
  if (raw?.version !== VERSION || !Array.isArray(raw.items)) return [];
31000
31324
  return raw.items.filter((item) => item?.id && item.kind && item.ref);
31001
31325
  } catch {
@@ -31003,8 +31327,8 @@ function readDisk() {
31003
31327
  }
31004
31328
  }
31005
31329
  function writeDisk(items) {
31006
- (0, import_node_fs56.mkdirSync)(appDataDir(), { recursive: true });
31007
- (0, import_node_fs56.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
31330
+ (0, import_node_fs57.mkdirSync)(appDataDir(), { recursive: true });
31331
+ (0, import_node_fs57.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
31008
31332
  }
31009
31333
  function listBoardPins() {
31010
31334
  return readDisk();
@@ -31013,7 +31337,7 @@ function addBoardPin(input) {
31013
31337
  const ref = input.ref.trim();
31014
31338
  if (!ref) throw new Error("Board item needs a ref");
31015
31339
  const pin = {
31016
- id: (0, import_node_crypto14.randomUUID)(),
31340
+ id: (0, import_node_crypto15.randomUUID)(),
31017
31341
  kind: input.kind,
31018
31342
  ref,
31019
31343
  repoPath: input.repoPath.trim(),
@@ -31056,7 +31380,7 @@ function replaceBoardPins(items) {
31056
31380
  }
31057
31381
  function clearBoardPins() {
31058
31382
  try {
31059
- (0, import_node_fs56.unlinkSync)(pinsFile());
31383
+ (0, import_node_fs57.unlinkSync)(pinsFile());
31060
31384
  } catch {
31061
31385
  }
31062
31386
  }
@@ -31073,7 +31397,7 @@ function homeBoardWorkspaceKey(workspaces) {
31073
31397
  return workspaces.map((w) => w.path).filter(Boolean).sort().join("\n");
31074
31398
  }
31075
31399
  function cacheFile() {
31076
- return (0, import_node_path54.join)(appDataDir(), "home-board-cache.json");
31400
+ return (0, import_node_path55.join)(appDataDir(), "home-board-cache.json");
31077
31401
  }
31078
31402
  function emptyInputs() {
31079
31403
  return {
@@ -31099,9 +31423,9 @@ function shouldCacheHomeBoardInputs(inputs) {
31099
31423
  }
31100
31424
  function readDiskCache() {
31101
31425
  const path2 = cacheFile();
31102
- if (!(0, import_node_fs57.existsSync)(path2)) return null;
31426
+ if (!(0, import_node_fs58.existsSync)(path2)) return null;
31103
31427
  try {
31104
- const raw = JSON.parse((0, import_node_fs57.readFileSync)(path2, "utf8"));
31428
+ const raw = JSON.parse((0, import_node_fs58.readFileSync)(path2, "utf8"));
31105
31429
  if (raw?.version !== CACHE_VERSION || typeof raw.fetchedAt !== "number") {
31106
31430
  return null;
31107
31431
  }
@@ -31115,14 +31439,14 @@ function readDiskCache() {
31115
31439
  }
31116
31440
  function writeDiskCache(entry) {
31117
31441
  try {
31118
- (0, import_node_fs57.mkdirSync)(appDataDir(), { recursive: true });
31119
- (0, import_node_fs57.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
31442
+ (0, import_node_fs58.mkdirSync)(appDataDir(), { recursive: true });
31443
+ (0, import_node_fs58.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
31120
31444
  } catch {
31121
31445
  }
31122
31446
  }
31123
31447
  function deleteDiskCache() {
31124
31448
  try {
31125
- (0, import_node_fs57.unlinkSync)(cacheFile());
31449
+ (0, import_node_fs58.unlinkSync)(cacheFile());
31126
31450
  } catch {
31127
31451
  }
31128
31452
  }
@@ -31472,7 +31796,7 @@ async function startMcpServer() {
31472
31796
  async () => {
31473
31797
  const threads = orch.getThreads(true);
31474
31798
  const lines = threads.map((t) => {
31475
- const repo = t.repoPath === GLOBAL_WORKSPACE_ID2 ? "Orchestration" : (0, import_node_path55.basename)(t.repoPath) || t.repoPath;
31799
+ const repo = t.repoPath === GLOBAL_WORKSPACE_ID2 ? "Orchestration" : (0, import_node_path56.basename)(t.repoPath) || t.repoPath;
31476
31800
  const live = orch.threadLooksLive(t) ? readTurnLive(t.id) : null;
31477
31801
  const parent = t.parentThreadId ? ` parent:${t.parentThreadId.slice(0, 8)}` : "";
31478
31802
  const preview = lastMessagePreview(t.messages, 80);
@@ -31720,13 +32044,73 @@ async function startMcpServer() {
31720
32044
  "Stop a detached job you started with detached-job.cjs when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress. The type=log pane updates to status=failed with the last delta. Then decide the next step.",
31721
32045
  {
31722
32046
  id: import_zod9.z.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
31723
- reason: import_zod9.z.string().optional().describe("Why you are stopping (hanging, no progress, wrong output, already have the error)")
32047
+ reason: import_zod9.z.string().optional().describe("Why you are stopping (hanging, no progress, wrong output, already have the answer)")
31724
32048
  },
31725
32049
  async ({ id, reason }) => {
31726
32050
  const result = await stopDetachedJob(process.cwd(), id, { reason });
31727
32051
  return mcpJson(result);
31728
32052
  }
31729
32053
  );
32054
+ server.tool(
32055
+ "list_run_scripts",
32056
+ "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).",
32057
+ {
32058
+ ref: import_zod9.z.string().optional().describe("Thread id. Omit on a worktree turn (uses cwd).")
32059
+ },
32060
+ async ({ ref }) => {
32061
+ try {
32062
+ const threadRef = resolveRunScriptThreadRef(ref);
32063
+ const scripts = orch.listThreadRunScripts(threadRef);
32064
+ const active = orch.getActiveRuns(threadRef);
32065
+ return mcpJson({ scripts, active, ref: threadRef });
32066
+ } catch (err) {
32067
+ const message = err instanceof Error ? err.message : String(err);
32068
+ return { content: [{ type: "text", text: message }], isError: true };
32069
+ }
32070
+ }
32071
+ );
32072
+ server.tool(
32073
+ "run_dev_script",
32074
+ "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.",
32075
+ {
32076
+ ref: import_zod9.z.string().optional().describe("Thread id. Omit on a worktree turn (uses cwd)."),
32077
+ name: import_zod9.z.string().optional().describe("Script name from list_run_scripts (default script if omitted).")
32078
+ },
32079
+ async ({ ref, name }) => {
32080
+ try {
32081
+ const threadRef = resolveRunScriptThreadRef(ref);
32082
+ const result = await orch.startDev(threadRef, name);
32083
+ return mcpJson({
32084
+ port: result.port,
32085
+ scriptName: result.scriptName,
32086
+ ports: result.ports,
32087
+ url: `http://localhost:${result.port}`,
32088
+ ref: threadRef
32089
+ });
32090
+ } catch (err) {
32091
+ const message = err instanceof Error ? err.message : String(err);
32092
+ return { content: [{ type: "text", text: message }], isError: true };
32093
+ }
32094
+ }
32095
+ );
32096
+ server.tool(
32097
+ "stop_dev_script",
32098
+ "Stop a run script started with run_dev_script or the desktop Dev button (same as UI Stop). Omit name to stop all scripts on this worktree. Worktree turns may omit ref (uses cwd).",
32099
+ {
32100
+ ref: import_zod9.z.string().optional().describe("Thread id. Omit on a worktree turn (uses cwd)."),
32101
+ name: import_zod9.z.string().optional().describe("Script name to stop; omit to stop all active scripts.")
32102
+ },
32103
+ async ({ ref, name }) => {
32104
+ try {
32105
+ const threadRef = resolveRunScriptThreadRef(ref);
32106
+ await orch.stopDev(threadRef, name);
32107
+ return mcpJson({ ok: true, ref: threadRef, stopped: name ?? "all" });
32108
+ } catch (err) {
32109
+ const message = err instanceof Error ? err.message : String(err);
32110
+ return { content: [{ type: "text", text: message }], isError: true };
32111
+ }
32112
+ }
32113
+ );
31730
32114
  if (!worktreeProfile) {
31731
32115
  registerSlackTools(server);
31732
32116
  registerConnectedIssueVendorTools(server);
@@ -31847,7 +32231,7 @@ async function startMcpServer() {
31847
32231
  const ident = issue?.identifier ?? ref.trim();
31848
32232
  const attachments = issue ? [
31849
32233
  {
31850
- id: (0, import_node_crypto15.randomUUID)(),
32234
+ id: (0, import_node_crypto16.randomUUID)(),
31851
32235
  name: issue.identifier,
31852
32236
  kind: "issue",
31853
32237
  content: [
@@ -32205,45 +32589,6 @@ async function startMcpServer() {
32205
32589
  }
32206
32590
  }
32207
32591
  );
32208
- server.tool(
32209
- "run_dev_script",
32210
- "Start a .sideboard/.conductor run script for a thread (default script if name omitted); returns port",
32211
- {
32212
- ref: import_zod9.z.string(),
32213
- name: import_zod9.z.string().optional()
32214
- },
32215
- async ({ ref, name }) => {
32216
- const result = await orch.startDev(ref, name);
32217
- return mcpJson({
32218
- port: result.port,
32219
- scriptName: result.scriptName,
32220
- ports: result.ports,
32221
- url: `http://localhost:${result.port}`
32222
- });
32223
- }
32224
- );
32225
- server.tool(
32226
- "list_run_scripts",
32227
- "List named run scripts available for a thread",
32228
- { ref: import_zod9.z.string() },
32229
- async ({ ref }) => {
32230
- const scripts = orch.listThreadRunScripts(ref);
32231
- const active = orch.getActiveRuns(ref);
32232
- return mcpJson({ scripts, active });
32233
- }
32234
- );
32235
- server.tool(
32236
- "stop_dev_script",
32237
- "Stop a running script for a thread (all scripts if name omitted)",
32238
- {
32239
- ref: import_zod9.z.string(),
32240
- name: import_zod9.z.string().optional()
32241
- },
32242
- async ({ ref, name }) => {
32243
- orch.stopDev(ref, name);
32244
- return { content: [{ type: "text", text: "ok" }] };
32245
- }
32246
- );
32247
32592
  server.tool(
32248
32593
  "run_setup",
32249
32594
  "Re-run workspace setup (Sideboard/Conductor settings, .cursor/worktrees.json, or script/setup). New worktrees already run this automatically.",
@@ -32815,7 +33160,7 @@ init_orch_mcp_isolation();
32815
33160
  init_workspaces2();
32816
33161
 
32817
33162
  // src/slack/oauth.ts
32818
- var import_node_crypto16 = require("crypto");
33163
+ var import_node_crypto17 = require("crypto");
32819
33164
  init_app_settings();
32820
33165
  init_workspaces2();
32821
33166
 
@@ -33039,7 +33384,7 @@ async function startSlackOAuth(opts) {
33039
33384
  throw new SlackOAuthCancelledError();
33040
33385
  }
33041
33386
  const { clientId } = slackOAuthCredentials();
33042
- const state = (0, import_node_crypto16.randomBytes)(16).toString("hex");
33387
+ const state = (0, import_node_crypto17.randomBytes)(16).toString("hex");
33043
33388
  const authorizeUrl = slackOAuthAuthorizeUrl(clientId, state);
33044
33389
  const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
33045
33390
  const pollIntervalMs = opts?.pollIntervalMs ?? 400;
@@ -33321,7 +33666,7 @@ init_workspaces2();
33321
33666
  init_reply_target();
33322
33667
 
33323
33668
  // src/slack/relay-protocol.ts
33324
- var import_node_crypto17 = require("crypto");
33669
+ var import_node_crypto18 = require("crypto");
33325
33670
  var SLACK_RELAY_PING_INTERVAL_MS = 2e4;
33326
33671
  var SLACK_RELAY_PONG_TIMEOUT_MS = 15e3;
33327
33672
  function slackRelaySessionKey(teamId, userId, deviceId) {
@@ -33331,7 +33676,7 @@ function slackRelayUserKey(teamId, userId) {
33331
33676
  return `${teamId.trim()}:${userId.trim()}`;
33332
33677
  }
33333
33678
  function newSlackRelayEventId() {
33334
- return (0, import_node_crypto17.randomBytes)(12).toString("hex");
33679
+ return (0, import_node_crypto18.randomBytes)(12).toString("hex");
33335
33680
  }
33336
33681
  function parseSlackRelayClientMessage(raw) {
33337
33682
  try {
@@ -34452,9 +34797,9 @@ var import_node_http4 = require("http");
34452
34797
  var import_ws3 = require("ws");
34453
34798
 
34454
34799
  // src/slack/relay-static.ts
34455
- var import_node_fs58 = require("fs");
34800
+ var import_node_fs59 = require("fs");
34456
34801
  var import_promises = require("fs/promises");
34457
- var import_node_path56 = __toESM(require("path"), 1);
34802
+ var import_node_path57 = __toESM(require("path"), 1);
34458
34803
  var TYPES = {
34459
34804
  ".css": "text/css; charset=utf-8",
34460
34805
  ".html": "text/html; charset=utf-8",
@@ -34485,9 +34830,9 @@ function resolveStaticPath(root, requestUrl) {
34485
34830
  return null;
34486
34831
  }
34487
34832
  if (!pathname.startsWith("/") || pathname.includes("\0")) return null;
34488
- const rootResolved = import_node_path56.default.resolve(root);
34489
- const candidate = import_node_path56.default.resolve(rootResolved, `.${pathname}`);
34490
- if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path56.default.sep)) {
34833
+ const rootResolved = import_node_path57.default.resolve(root);
34834
+ const candidate = import_node_path57.default.resolve(rootResolved, `.${pathname}`);
34835
+ if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path57.default.sep)) {
34491
34836
  return null;
34492
34837
  }
34493
34838
  return candidate;
@@ -34501,7 +34846,7 @@ async function fileSize(file) {
34501
34846
  }
34502
34847
  }
34503
34848
  function sendFile(req, res, file, size) {
34504
- const ext = import_node_path56.default.extname(file).toLowerCase();
34849
+ const ext = import_node_path57.default.extname(file).toLowerCase();
34505
34850
  res.writeHead(200, {
34506
34851
  "Content-Type": TYPES[ext] ?? "application/octet-stream",
34507
34852
  "Content-Length": size,
@@ -34511,7 +34856,7 @@ function sendFile(req, res, file, size) {
34511
34856
  res.end();
34512
34857
  return true;
34513
34858
  }
34514
- (0, import_node_fs58.createReadStream)(file).pipe(res);
34859
+ (0, import_node_fs59.createReadStream)(file).pipe(res);
34515
34860
  return true;
34516
34861
  }
34517
34862
  async function tryServeStatic(req, res, root) {
@@ -34520,7 +34865,7 @@ async function tryServeStatic(req, res, root) {
34520
34865
  if (!candidate) return false;
34521
34866
  const direct = await fileSize(candidate);
34522
34867
  if (direct != null) return sendFile(req, res, candidate, direct);
34523
- const asIndex = import_node_path56.default.join(candidate, "index.html");
34868
+ const asIndex = import_node_path57.default.join(candidate, "index.html");
34524
34869
  const indexSize = await fileSize(asIndex);
34525
34870
  if (indexSize != null) return sendFile(req, res, asIndex, indexSize);
34526
34871
  return false;
@@ -34778,6 +35123,9 @@ init_outbound_watch();
34778
35123
  ABLETIME_ORG_KEY_PREFIX,
34779
35124
  ABLETIME_PAT_PREFIX,
34780
35125
  ABLETIME_PM_TOOL_NAMES,
35126
+ AGENT_DONE_CUSTOM_SOUND_EXTENSIONS,
35127
+ AGENT_DONE_CUSTOM_SOUND_MAX_BYTES,
35128
+ AGENT_DONE_SOUNDS,
34781
35129
  AGENT_GIT_ACTIONS,
34782
35130
  AGENT_RUNNER_MAX_OLD_SPACE_MB,
34783
35131
  ATTACHMENTS_DIR,
@@ -34857,6 +35205,7 @@ init_outbound_watch();
34857
35205
  REVIEW_REQUEST_TEMPLATE,
34858
35206
  REVIEW_SKILL_NAME,
34859
35207
  REVIEW_SKILL_PATH,
35208
+ RUN_SCRIPT_DESKTOP_ADOPT_MS,
34860
35209
  SEED_FULL_TOOL_MESSAGES,
34861
35210
  SEED_MAX_CHARS,
34862
35211
  SESSION_RESET_OCCUPANCY_TOKENS,
@@ -34900,6 +35249,9 @@ init_outbound_watch();
34900
35249
  addStackLayerFromThread,
34901
35250
  addWorkspace,
34902
35251
  adoptThread,
35252
+ agentDoneCustomSoundMime,
35253
+ agentDoneSound,
35254
+ agentDoneSoundsDir,
34903
35255
  agentGitPrompt,
34904
35256
  alignQueueAttachments,
34905
35257
  allAdapters,
@@ -34978,6 +35330,7 @@ init_outbound_watch();
34978
35330
  claudeUserSettingsPath,
34979
35331
  cleanupArchivedHistory,
34980
35332
  cleanupOrphanWorktrees,
35333
+ clearAgentDoneCustomSoundFile,
34981
35334
  clearBoardPins,
34982
35335
  clearHomeBoardCache,
34983
35336
  clipAgentEventForPaint,
@@ -35080,6 +35433,7 @@ init_outbound_watch();
35080
35433
  fetchOriginForWorktree,
35081
35434
  fetchPrHead,
35082
35435
  finalizeParts,
35436
+ findAgentDoneCustomSoundPath,
35083
35437
  findConventionSetup,
35084
35438
  findInvalidCacheControlTtlOrder,
35085
35439
  findLastBrightsyContextSummary,
@@ -35214,6 +35568,7 @@ init_outbound_watch();
35214
35568
  historyMaxDays,
35215
35569
  hottestClaudeWindow,
35216
35570
  httpFetch,
35571
+ importAgentDoneCustomSound,
35217
35572
  importConductorWorkspace,
35218
35573
  importConductorWorkspaceAsync,
35219
35574
  initPrStack,
@@ -35229,6 +35584,7 @@ init_outbound_watch();
35229
35584
  isAbleTimeConnected,
35230
35585
  isAbleTimeOAuthCancelled,
35231
35586
  isAbleTimeRejectedCredential,
35587
+ isAgentDoneSound,
35232
35588
  isAskUserToolName,
35233
35589
  isBrightsyConnected,
35234
35590
  isBrightsyNdjsonLine,
@@ -35279,6 +35635,7 @@ init_outbound_watch();
35279
35635
  isThisProcessDesktopHost,
35280
35636
  isThreadCaffeinated,
35281
35637
  isThreadRecordFile,
35638
+ isUnclaimedRunScriptRequest,
35282
35639
  isUsageOnLimit,
35283
35640
  isWorkspaceScratchPath,
35284
35641
  issueAttachmentForAbleTimeTask,
@@ -35420,6 +35777,7 @@ init_outbound_watch();
35420
35777
  primaryCheckoutFromLinkedWorktree,
35421
35778
  promptMentionsBrightsy,
35422
35779
  pushBranch,
35780
+ readAgentDoneCustomSound,
35423
35781
  readExistingReviewRequestFile,
35424
35782
  readKeychainVaultKey,
35425
35783
  readPlanFile,