@sideboard-ai/core 0.1.98 → 0.1.100

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 (26) hide show
  1. package/dist/agents/cursor-runner.cjs +69 -24
  2. package/dist/agents/cursor-runner.js +48 -3
  3. package/dist/{agents-ESJKIQQA.js → agents-CLP5BG4O.js} +3 -3
  4. package/dist/{agents-3MWWWSMF.js → agents-OXZDMPSE.js} +4 -4
  5. package/dist/{chunk-FYS2BULQ.js → chunk-EQPQTLW6.js} +209 -59
  6. package/dist/{chunk-FO67IJTY.js → chunk-GR4JKWR4.js} +1 -1
  7. package/dist/{chunk-GXSYI7FH.js → chunk-HUKCGRAT.js} +209 -59
  8. package/dist/{chunk-XUWDLRAE.js → chunk-HYKZEP5A.js} +2 -2
  9. package/dist/{chunk-XH2GS2LO.js → chunk-IFHKPZHA.js} +2 -2
  10. package/dist/{chunk-UYQYK2RY.js → chunk-MHJV4WS3.js} +1 -1
  11. package/dist/{chunk-OANJQTVG.js → chunk-MRBKGFTL.js} +1 -1
  12. package/dist/{chunk-MBP3XG57.js → chunk-OXC3MEFI.js} +3 -3
  13. package/dist/{chunk-HI2OTFFR.js → chunk-WQTTUC4N.js} +1 -1
  14. package/dist/{coordinator-prompt-AKEY4WSO.js → coordinator-prompt-HHRKQWCX.js} +1 -1
  15. package/dist/{coordinator-prompt-OQOOD5ET.js → coordinator-prompt-OOBSQCWQ.js} +1 -1
  16. package/dist/{global-workspace-RSQXRLT7.js → global-workspace-KYEBFWKB.js} +2 -2
  17. package/dist/{global-workspace-WMF3BJP5.js → global-workspace-YZWYHLQY.js} +2 -2
  18. package/dist/index.cjs +662 -440
  19. package/dist/index.d.cts +16 -2
  20. package/dist/index.d.ts +16 -2
  21. package/dist/index.js +194 -128
  22. package/dist/mcp/run-stdio.cjs +424 -227
  23. package/dist/mcp/run-stdio.js +141 -92
  24. package/dist/{workspaces-MZVQHRSJ.js → workspaces-ENVUDK6C.js} +3 -3
  25. package/dist/{workspaces-4ZY4QPWQ.js → workspaces-NNPD7QVV.js} +3 -3
  26. package/package.json +2 -2
package/dist/index.cjs CHANGED
@@ -3072,23 +3072,23 @@ var init_gh_errors = __esm({
3072
3072
  function githubAgentAuthDir() {
3073
3073
  const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
3074
3074
  if (override) return override;
3075
- return (0, import_node_path10.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
3075
+ return (0, import_node_path11.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
3076
3076
  }
3077
3077
  function githubCredentialStorePath() {
3078
- return (0, import_node_path10.join)(githubAgentAuthDir(), "git-credentials");
3078
+ return (0, import_node_path11.join)(githubAgentAuthDir(), "git-credentials");
3079
3079
  }
3080
3080
  function githubGhConfigDir() {
3081
- return (0, import_node_path10.join)(githubAgentAuthDir(), "gh");
3081
+ return (0, import_node_path11.join)(githubAgentAuthDir(), "gh");
3082
3082
  }
3083
3083
  function writePrivateFile2(file, body) {
3084
- (0, import_node_fs10.mkdirSync)((0, import_node_path10.dirname)(file), { recursive: true, mode: 448 });
3084
+ (0, import_node_fs11.mkdirSync)((0, import_node_path11.dirname)(file), { recursive: true, mode: 448 });
3085
3085
  try {
3086
- (0, import_node_fs10.chmodSync)((0, import_node_path10.dirname)(file), 448);
3086
+ (0, import_node_fs11.chmodSync)((0, import_node_path11.dirname)(file), 448);
3087
3087
  } catch {
3088
3088
  }
3089
- (0, import_node_fs10.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
3089
+ (0, import_node_fs11.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
3090
3090
  try {
3091
- (0, import_node_fs10.chmodSync)(file, 384);
3091
+ (0, import_node_fs11.chmodSync)(file, 384);
3092
3092
  } catch {
3093
3093
  }
3094
3094
  }
@@ -3113,19 +3113,19 @@ function materializeGithubAgentAuth(token, user) {
3113
3113
  const trimmed = token.trim();
3114
3114
  if (!trimmed) return;
3115
3115
  const root = githubAgentAuthDir();
3116
- (0, import_node_fs10.mkdirSync)(root, { recursive: true, mode: 448 });
3116
+ (0, import_node_fs11.mkdirSync)(root, { recursive: true, mode: 448 });
3117
3117
  try {
3118
- (0, import_node_fs10.chmodSync)(root, 448);
3118
+ (0, import_node_fs11.chmodSync)(root, 448);
3119
3119
  } catch {
3120
3120
  }
3121
3121
  writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
3122
3122
  const ghDir = githubGhConfigDir();
3123
- (0, import_node_fs10.mkdirSync)(ghDir, { recursive: true, mode: 448 });
3124
- writePrivateFile2((0, import_node_path10.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
3125
- writePrivateFile2((0, import_node_path10.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
3123
+ (0, import_node_fs11.mkdirSync)(ghDir, { recursive: true, mode: 448 });
3124
+ writePrivateFile2((0, import_node_path11.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
3125
+ writePrivateFile2((0, import_node_path11.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
3126
3126
  }
3127
3127
  function githubAgentAuthReady() {
3128
- return (0, import_node_fs10.existsSync)(githubCredentialStorePath()) && (0, import_node_fs10.existsSync)((0, import_node_path10.join)(githubGhConfigDir(), "hosts.yml"));
3128
+ return (0, import_node_fs11.existsSync)(githubCredentialStorePath()) && (0, import_node_fs11.existsSync)((0, import_node_path11.join)(githubGhConfigDir(), "hosts.yml"));
3129
3129
  }
3130
3130
  function githubCredentialHelperGitConfig() {
3131
3131
  const file = githubCredentialStorePath();
@@ -3140,29 +3140,29 @@ function githubGhConfigEnv() {
3140
3140
  GH_PROMPT_DISABLED: "1"
3141
3141
  };
3142
3142
  }
3143
- var import_node_fs10, import_node_os4, import_node_path10;
3143
+ var import_node_fs11, import_node_os4, import_node_path11;
3144
3144
  var init_github_agent_auth = __esm({
3145
3145
  "src/git/github-agent-auth.ts"() {
3146
3146
  "use strict";
3147
- import_node_fs10 = require("fs");
3147
+ import_node_fs11 = require("fs");
3148
3148
  import_node_os4 = require("os");
3149
- import_node_path10 = require("path");
3149
+ import_node_path11 = require("path");
3150
3150
  }
3151
3151
  });
3152
3152
 
3153
3153
  // src/agents/path.ts
3154
3154
  function prependPathDir(env, dir) {
3155
- if (!dir || !(0, import_node_fs11.existsSync)(dir)) return;
3155
+ if (!dir || !(0, import_node_fs12.existsSync)(dir)) return;
3156
3156
  const current = env.PATH ?? "";
3157
- const parts = current.split(import_node_path11.delimiter).filter(Boolean);
3157
+ const parts = current.split(import_node_path12.delimiter).filter(Boolean);
3158
3158
  if (parts.includes(dir)) {
3159
3159
  env.PATH = current;
3160
3160
  return;
3161
3161
  }
3162
- env.PATH = [dir, ...parts].join(import_node_path11.delimiter);
3162
+ env.PATH = [dir, ...parts].join(import_node_path12.delimiter);
3163
3163
  }
3164
3164
  function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os5.homedir)()) {
3165
- return (0, import_node_path11.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
3165
+ return (0, import_node_path12.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
3166
3166
  }
3167
3167
  function isConductorBundledCli(filePath) {
3168
3168
  const p = (filePath ?? "").replace(/\\/g, "/");
@@ -3171,21 +3171,21 @@ function isConductorBundledCli(filePath) {
3171
3171
  function ensureAgentPath(env = process.env) {
3172
3172
  const home = env.HOME || env.USERPROFILE || (0, import_node_os5.homedir)();
3173
3173
  const current = env.PATH ?? "";
3174
- const parts = current.split(import_node_path11.delimiter).filter(Boolean);
3174
+ const parts = current.split(import_node_path12.delimiter).filter(Boolean);
3175
3175
  const seen = new Set(parts);
3176
3176
  const extras = [
3177
- ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path11.join)(home, rel)),
3177
+ ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path12.join)(home, rel)),
3178
3178
  "/opt/homebrew/bin",
3179
3179
  "/usr/local/bin",
3180
3180
  // Keep after Homebrew/npm so a user-installed CLI still wins.
3181
3181
  conductorBundledBinDir(home)
3182
3182
  ];
3183
3183
  for (const dir of extras.reverse()) {
3184
- if (!dir || seen.has(dir) || !(0, import_node_fs11.existsSync)(dir)) continue;
3184
+ if (!dir || seen.has(dir) || !(0, import_node_fs12.existsSync)(dir)) continue;
3185
3185
  parts.unshift(dir);
3186
3186
  seen.add(dir);
3187
3187
  }
3188
- const next = parts.join(import_node_path11.delimiter);
3188
+ const next = parts.join(import_node_path12.delimiter);
3189
3189
  env.PATH = next;
3190
3190
  return next;
3191
3191
  }
@@ -3199,7 +3199,7 @@ function enrichPathWithNpmGlobalBin(env = process.env) {
3199
3199
  stdio: ["ignore", "pipe", "ignore"]
3200
3200
  }).trim().split(/\r?\n/).find(Boolean);
3201
3201
  if (prefix) {
3202
- const binDir = process.platform === "win32" ? prefix : (0, import_node_path11.join)(prefix, "bin");
3202
+ const binDir = process.platform === "win32" ? prefix : (0, import_node_path12.join)(prefix, "bin");
3203
3203
  prependPathDir(env, binDir);
3204
3204
  }
3205
3205
  } catch {
@@ -3227,14 +3227,14 @@ function withExportedPath(command, pathValue) {
3227
3227
  if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
3228
3228
  return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
3229
3229
  }
3230
- var import_node_fs11, import_node_child_process3, import_node_os5, import_node_path11, EXTRA_BIN_DIRS;
3230
+ var import_node_fs12, import_node_child_process3, import_node_os5, import_node_path12, EXTRA_BIN_DIRS;
3231
3231
  var init_path = __esm({
3232
3232
  "src/agents/path.ts"() {
3233
3233
  "use strict";
3234
- import_node_fs11 = require("fs");
3234
+ import_node_fs12 = require("fs");
3235
3235
  import_node_child_process3 = require("child_process");
3236
3236
  import_node_os5 = require("os");
3237
- import_node_path11 = require("path");
3237
+ import_node_path12 = require("path");
3238
3238
  EXTRA_BIN_DIRS = [
3239
3239
  ".local/bin",
3240
3240
  ".cargo/bin",
@@ -3426,7 +3426,7 @@ async function warmGithubAgentAuth(opts) {
3426
3426
  }
3427
3427
  function normalizeWritableRoot(raw) {
3428
3428
  const trimmed = raw.trim().replace(/\/+$/, "");
3429
- return trimmed && (0, import_node_path12.isAbsolute)(trimmed) ? trimmed : null;
3429
+ return trimmed && (0, import_node_path13.isAbsolute)(trimmed) ? trimmed : null;
3430
3430
  }
3431
3431
  async function resolveCodexGitWritableRoots(cwd) {
3432
3432
  const roots = /* @__PURE__ */ new Set();
@@ -3503,11 +3503,11 @@ function formatGitAuthModeDirective(mode) {
3503
3503
  ].join("\n");
3504
3504
  }
3505
3505
  }
3506
- var import_node_path12, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
3506
+ var import_node_path13, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
3507
3507
  var init_git_auth_mode = __esm({
3508
3508
  "src/git/git-auth-mode.ts"() {
3509
3509
  "use strict";
3510
- import_node_path12 = require("path");
3510
+ import_node_path13 = require("path");
3511
3511
  init_app_settings();
3512
3512
  init_github_agent_auth();
3513
3513
  init_run();
@@ -4669,8 +4669,8 @@ function isLocalPrFetchBranch(ref) {
4669
4669
  }
4670
4670
  async function createThreadWorktree(opts) {
4671
4671
  let branchName = `thread/${opts.slug}`;
4672
- const worktreePath = (0, import_node_path13.join)(worktreesRoot(opts.repoPath), opts.slug);
4673
- if ((0, import_node_fs12.existsSync)(worktreePath)) {
4672
+ const worktreePath = (0, import_node_path14.join)(worktreesRoot(opts.repoPath), opts.slug);
4673
+ if ((0, import_node_fs13.existsSync)(worktreePath)) {
4674
4674
  throw new Error(`Worktree already exists at ${worktreePath}`);
4675
4675
  }
4676
4676
  await ensureGhPreferOrigin(opts.repoPath);
@@ -4739,8 +4739,8 @@ ${add.stdout}`;
4739
4739
  async function createExistingBranchWorktree(opts) {
4740
4740
  const branchName = opts.branchName.trim();
4741
4741
  if (!branchName) throw new Error("branch name required");
4742
- const worktreePath = (0, import_node_path13.join)(worktreesRoot(opts.repoPath), opts.slug);
4743
- if ((0, import_node_fs12.existsSync)(worktreePath)) {
4742
+ const worktreePath = (0, import_node_path14.join)(worktreesRoot(opts.repoPath), opts.slug);
4743
+ if ((0, import_node_fs13.existsSync)(worktreePath)) {
4744
4744
  throw new Error(`Worktree already exists at ${worktreePath}`);
4745
4745
  }
4746
4746
  await ensureGhPreferOrigin(opts.repoPath);
@@ -5028,10 +5028,10 @@ function sameRepoPath(a, b) {
5028
5028
  return normalizeWorktreePath(a) === normalizeWorktreePath(b);
5029
5029
  }
5030
5030
  function listLocalThreadBranchSlugs(repoPath) {
5031
- const refsDir = (0, import_node_path13.join)(repoPath, ".git", "refs", "heads", "thread");
5032
- if (!(0, import_node_fs12.existsSync)(refsDir)) return [];
5031
+ const refsDir = (0, import_node_path14.join)(repoPath, ".git", "refs", "heads", "thread");
5032
+ if (!(0, import_node_fs13.existsSync)(refsDir)) return [];
5033
5033
  try {
5034
- return (0, import_node_fs12.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
5034
+ return (0, import_node_fs13.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
5035
5035
  } catch {
5036
5036
  return [];
5037
5037
  }
@@ -5039,8 +5039,8 @@ function listLocalThreadBranchSlugs(repoPath) {
5039
5039
  function collectTakenTeamSlugs(repoPath) {
5040
5040
  const taken = /* @__PURE__ */ new Set();
5041
5041
  const root = worktreesRoot(repoPath);
5042
- if ((0, import_node_fs12.existsSync)(root)) {
5043
- for (const entry of (0, import_node_fs12.readdirSync)(root, { withFileTypes: true })) {
5042
+ if ((0, import_node_fs13.existsSync)(root)) {
5043
+ for (const entry of (0, import_node_fs13.readdirSync)(root, { withFileTypes: true })) {
5044
5044
  if (entry.isDirectory() && entry.name !== ".DS_Store") {
5045
5045
  taken.add(normalizeTakenSlug(entry.name));
5046
5046
  }
@@ -5061,18 +5061,18 @@ function allocateTeamSlug(repoPath) {
5061
5061
  const taken = collectTakenTeamSlugs(repoPath);
5062
5062
  for (let attempt = 0; attempt < 32; attempt++) {
5063
5063
  const team = allocateTeamName(taken);
5064
- const path2 = (0, import_node_path13.join)(worktreesRoot(repoPath), team.slug);
5065
- if (!(0, import_node_fs12.existsSync)(path2)) return team;
5064
+ const path2 = (0, import_node_path14.join)(worktreesRoot(repoPath), team.slug);
5065
+ if (!(0, import_node_fs13.existsSync)(path2)) return team;
5066
5066
  taken.add(team.slug);
5067
5067
  }
5068
5068
  throw new Error("No available soccer team worktree directories left");
5069
5069
  }
5070
- var import_node_fs12, import_node_path13;
5070
+ var import_node_fs13, import_node_path14;
5071
5071
  var init_worktree = __esm({
5072
5072
  "src/git/worktree.ts"() {
5073
5073
  "use strict";
5074
- import_node_fs12 = require("fs");
5075
- import_node_path13 = require("path");
5074
+ import_node_fs13 = require("fs");
5075
+ import_node_path14 = require("path");
5076
5076
  init_paths();
5077
5077
  init_thread_store();
5078
5078
  init_teams();
@@ -5147,7 +5147,7 @@ function coordinatorTurnReminder(opts) {
5147
5147
  goal ? `- Goal / title: ${goal}` : null,
5148
5148
  accountDefaultsPlaybookLine(),
5149
5149
  `- For "what's going on": call list_threads (and list_workspaces if needed). Summarize fleet status \u2014 do not ls/git-status this synthetic home.`,
5150
- "- Existing repo: create_thread on a repoPath \u2192 send_to_thread \u2192 wait_for_turn. Commit/push/draft PR with ask_git on the child, then wait_for_turn \u2014 never git/gh from this cwd. Call ask_git merge only if the user explicitly asked to merge.",
5150
+ "- Existing repo: create_thread on a repoPath \u2192 send_to_thread \u2192 wait_for_turn. If status is error, lastError/text is the failure \u2014 adapt (switch agent, tell the user). Commit/push/draft PR with ask_git on the child, then wait_for_turn \u2014 never git/gh from this cwd. Call ask_git merge only if the user explicitly asked to merge.",
5151
5151
  "- New repo: Bash (clone or gh repo create under ~/sideboard/repos/<name>) \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 ask_git create-draft.",
5152
5152
  "- When naming threads for the user, link them as `[Title](sideboard://thread/<id>)`.",
5153
5153
  "- If they will wait on Slack or leave the Mac, call set_caffeinate enabled=true. When they say they are done / wrapping up / going to sleep, call set_caffeinate enabled=false. Closing this chat also turns it off."
@@ -5156,7 +5156,7 @@ function coordinatorTurnReminder(opts) {
5156
5156
  function ensureGlobalCoordinatorCwd(opts) {
5157
5157
  const dir = globalAgentCwd();
5158
5158
  try {
5159
- (0, import_node_fs13.mkdirSync)(dir, { recursive: true });
5159
+ (0, import_node_fs14.mkdirSync)(dir, { recursive: true });
5160
5160
  } catch {
5161
5161
  return dir;
5162
5162
  }
@@ -5164,7 +5164,7 @@ function ensureGlobalCoordinatorCwd(opts) {
5164
5164
  let orchId = opts?.orchestratorThreadId?.trim() || "";
5165
5165
  if (!orchId) {
5166
5166
  try {
5167
- const existing = (0, import_node_fs13.readFileSync)((0, import_node_path14.join)(dir, "AGENTS.md"), "utf8");
5167
+ const existing = (0, import_node_fs14.readFileSync)((0, import_node_path15.join)(dir, "AGENTS.md"), "utf8");
5168
5168
  const m = existing.match(
5169
5169
  /YOUR orchestration thread id is `([0-9a-f-]{36})`/i
5170
5170
  );
@@ -5206,9 +5206,9 @@ function ensureGlobalCoordinatorCwd(opts) {
5206
5206
  "Always ask worktree agents to commit, push, and open draft PRs (`ask_git` / `send_to_thread`). Tell them to merge only when the user explicitly asked. The worktree agent runs git/gh; never merge from this orchestration cwd."
5207
5207
  ].join("\n");
5208
5208
  try {
5209
- (0, import_node_fs13.writeFileSync)((0, import_node_path14.join)(dir, "CLAUDE.md"), `${body}
5209
+ (0, import_node_fs14.writeFileSync)((0, import_node_path15.join)(dir, "CLAUDE.md"), `${body}
5210
5210
  `, "utf8");
5211
- (0, import_node_fs13.writeFileSync)((0, import_node_path14.join)(dir, "AGENTS.md"), `${body}
5211
+ (0, import_node_fs14.writeFileSync)((0, import_node_path15.join)(dir, "AGENTS.md"), `${body}
5212
5212
  `, "utf8");
5213
5213
  } catch {
5214
5214
  }
@@ -5240,12 +5240,12 @@ function coordinatorSystemPrompt(opts) {
5240
5240
  formatWorkspaceInventory(opts.workspaces)
5241
5241
  ].join("\n");
5242
5242
  }
5243
- var import_node_fs13, import_node_path14, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
5243
+ var import_node_fs14, import_node_path15, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
5244
5244
  var init_coordinator_prompt = __esm({
5245
5245
  "src/orchestrator/coordinator-prompt.ts"() {
5246
5246
  "use strict";
5247
- import_node_fs13 = require("fs");
5248
- import_node_path14 = require("path");
5247
+ import_node_fs14 = require("fs");
5248
+ import_node_path15 = require("path");
5249
5249
  init_worktree();
5250
5250
  init_app_settings();
5251
5251
  init_paths();
@@ -5270,7 +5270,7 @@ var init_coordinator_prompt = __esm({
5270
5270
  "- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
5271
5271
  "- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
5272
5272
  "- send_to_thread \u2014 queue a prompt (start/continue a chat turn); pass force_stop: true to interrupt mid-turn / clear stale queued prompts before replacing with a new request",
5273
- "- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply",
5273
+ "- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success.",
5274
5274
  "- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
5275
5275
  "- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
5276
5276
  "Setup / run:",
@@ -5550,38 +5550,38 @@ __export(workspaces_exports, {
5550
5550
  syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
5551
5551
  });
5552
5552
  function workspacesFile() {
5553
- return (0, import_node_path15.join)(appDataDir(), "workspaces.json");
5553
+ return (0, import_node_path16.join)(appDataDir(), "workspaces.json");
5554
5554
  }
5555
5555
  function removedWorkspacesFile() {
5556
- return (0, import_node_path15.join)(appDataDir(), "removed-workspaces.json");
5556
+ return (0, import_node_path16.join)(appDataDir(), "removed-workspaces.json");
5557
5557
  }
5558
5558
  function readAll() {
5559
5559
  const path2 = workspacesFile();
5560
- if (!(0, import_node_fs14.existsSync)(path2)) return [];
5560
+ if (!(0, import_node_fs15.existsSync)(path2)) return [];
5561
5561
  try {
5562
- const raw = JSON.parse((0, import_node_fs14.readFileSync)(path2, "utf8"));
5562
+ const raw = JSON.parse((0, import_node_fs15.readFileSync)(path2, "utf8"));
5563
5563
  return Array.isArray(raw) ? raw : [];
5564
5564
  } catch {
5565
5565
  return [];
5566
5566
  }
5567
5567
  }
5568
5568
  function writeAll(list) {
5569
- (0, import_node_fs14.mkdirSync)(appDataDir(), { recursive: true });
5570
- (0, import_node_fs14.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
5569
+ (0, import_node_fs15.mkdirSync)(appDataDir(), { recursive: true });
5570
+ (0, import_node_fs15.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
5571
5571
  }
5572
5572
  function readRemoved() {
5573
5573
  const path2 = removedWorkspacesFile();
5574
- if (!(0, import_node_fs14.existsSync)(path2)) return /* @__PURE__ */ new Set();
5574
+ if (!(0, import_node_fs15.existsSync)(path2)) return /* @__PURE__ */ new Set();
5575
5575
  try {
5576
- const raw = JSON.parse((0, import_node_fs14.readFileSync)(path2, "utf8"));
5576
+ const raw = JSON.parse((0, import_node_fs15.readFileSync)(path2, "utf8"));
5577
5577
  return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
5578
5578
  } catch {
5579
5579
  return /* @__PURE__ */ new Set();
5580
5580
  }
5581
5581
  }
5582
5582
  function writeRemoved(paths) {
5583
- (0, import_node_fs14.mkdirSync)(appDataDir(), { recursive: true });
5584
- (0, import_node_fs14.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
5583
+ (0, import_node_fs15.mkdirSync)(appDataDir(), { recursive: true });
5584
+ (0, import_node_fs15.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
5585
5585
  }
5586
5586
  function rememberRemoved(repoPath) {
5587
5587
  const next = readRemoved();
@@ -5604,7 +5604,7 @@ function listWorkspaces() {
5604
5604
  async function addWorkspace(repoPath) {
5605
5605
  const root = await resolveRepoRoot(repoPath);
5606
5606
  if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
5607
- if (!(0, import_node_fs14.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
5607
+ if (!(0, import_node_fs15.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
5608
5608
  forgetRemoved(root);
5609
5609
  await ensureGhPreferOrigin(root);
5610
5610
  const current = readAll();
@@ -5612,7 +5612,7 @@ async function addWorkspace(repoPath) {
5612
5612
  if (existing) return existing;
5613
5613
  const next = {
5614
5614
  path: root,
5615
- name: (0, import_node_path15.basename)(root),
5615
+ name: (0, import_node_path16.basename)(root),
5616
5616
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
5617
5617
  };
5618
5618
  writeAll([...current, next]);
@@ -5634,10 +5634,10 @@ function syncWorkspacesFromThreads(repoPaths) {
5634
5634
  if (!path2 || path2 === "/" || isGlobalRepoPath(path2) || byPath.has(path2) || removed.has(path2)) {
5635
5635
  continue;
5636
5636
  }
5637
- if (!(0, import_node_fs14.existsSync)(path2)) continue;
5637
+ if (!(0, import_node_fs15.existsSync)(path2)) continue;
5638
5638
  const ws = {
5639
5639
  path: path2,
5640
- name: (0, import_node_path15.basename)(path2),
5640
+ name: (0, import_node_path16.basename)(path2),
5641
5641
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
5642
5642
  };
5643
5643
  byPath.set(path2, ws);
@@ -5647,12 +5647,12 @@ function syncWorkspacesFromThreads(repoPaths) {
5647
5647
  if (dirty) writeAll(next);
5648
5648
  return next.sort((a, b) => a.name.localeCompare(b.name));
5649
5649
  }
5650
- var import_node_fs14, import_node_path15;
5650
+ var import_node_fs15, import_node_path16;
5651
5651
  var init_workspaces = __esm({
5652
5652
  "src/store/workspaces.ts"() {
5653
5653
  "use strict";
5654
- import_node_fs14 = require("fs");
5655
- import_node_path15 = require("path");
5654
+ import_node_fs15 = require("fs");
5655
+ import_node_path16 = require("path");
5656
5656
  init_paths();
5657
5657
  init_global_workspace();
5658
5658
  init_worktree();
@@ -5661,32 +5661,32 @@ var init_workspaces = __esm({
5661
5661
 
5662
5662
  // src/brightsy/config.ts
5663
5663
  function brightsyConfigPath() {
5664
- return (0, import_node_path16.join)((0, import_node_os6.homedir)(), ".brightsy", "config.json");
5664
+ return (0, import_node_path17.join)((0, import_node_os6.homedir)(), ".brightsy", "config.json");
5665
5665
  }
5666
5666
  function loadBrightsyConfig() {
5667
5667
  const path2 = brightsyConfigPath();
5668
- if (!(0, import_node_fs15.existsSync)(path2)) {
5668
+ if (!(0, import_node_fs16.existsSync)(path2)) {
5669
5669
  throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
5670
5670
  }
5671
- const raw = JSON.parse((0, import_node_fs15.readFileSync)(path2, "utf8"));
5671
+ const raw = JSON.parse((0, import_node_fs16.readFileSync)(path2, "utf8"));
5672
5672
  if (!raw.access_token || !raw.account_id) {
5673
5673
  throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
5674
5674
  }
5675
5675
  return raw;
5676
5676
  }
5677
5677
  function saveBrightsyConfig(cfg) {
5678
- (0, import_node_fs15.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
5678
+ (0, import_node_fs16.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
5679
5679
  `, {
5680
5680
  mode: 384
5681
5681
  });
5682
5682
  }
5683
- var import_node_fs15, import_node_os6, import_node_path16;
5683
+ var import_node_fs16, import_node_os6, import_node_path17;
5684
5684
  var init_config = __esm({
5685
5685
  "src/brightsy/config.ts"() {
5686
5686
  "use strict";
5687
- import_node_fs15 = require("fs");
5687
+ import_node_fs16 = require("fs");
5688
5688
  import_node_os6 = require("os");
5689
- import_node_path16 = require("path");
5689
+ import_node_path17 = require("path");
5690
5690
  }
5691
5691
  });
5692
5692
 
@@ -5789,22 +5789,22 @@ __export(connected_teams_exports, {
5789
5789
  listConnectedBrightsyTeams: () => listConnectedBrightsyTeams
5790
5790
  });
5791
5791
  function storePath() {
5792
- return (0, import_node_path17.join)(appDataDir(), "brightsy-teams.json");
5792
+ return (0, import_node_path18.join)(appDataDir(), "brightsy-teams.json");
5793
5793
  }
5794
5794
  function readStore() {
5795
5795
  const path2 = storePath();
5796
- if (!(0, import_node_fs16.existsSync)(path2)) return [];
5796
+ if (!(0, import_node_fs17.existsSync)(path2)) return [];
5797
5797
  try {
5798
- const parsed = JSON.parse((0, import_node_fs16.readFileSync)(path2, "utf8"));
5798
+ const parsed = JSON.parse((0, import_node_fs17.readFileSync)(path2, "utf8"));
5799
5799
  return Array.isArray(parsed.teams) ? parsed.teams : [];
5800
5800
  } catch {
5801
5801
  return [];
5802
5802
  }
5803
5803
  }
5804
5804
  function writeStore(teams) {
5805
- (0, import_node_fs16.mkdirSync)(appDataDir(), { recursive: true });
5805
+ (0, import_node_fs17.mkdirSync)(appDataDir(), { recursive: true });
5806
5806
  const path2 = storePath();
5807
- (0, import_node_fs16.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
5807
+ (0, import_node_fs17.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
5808
5808
  `, {
5809
5809
  mode: 384
5810
5810
  });
@@ -5966,12 +5966,12 @@ function brightsyMcpServerName(slug) {
5966
5966
  const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
5967
5967
  return `brightsy_${cleaned || "team"}`;
5968
5968
  }
5969
- var import_node_fs16, import_node_path17;
5969
+ var import_node_fs17, import_node_path18;
5970
5970
  var init_connected_teams = __esm({
5971
5971
  "src/brightsy/connected-teams.ts"() {
5972
5972
  "use strict";
5973
- import_node_fs16 = require("fs");
5974
- import_node_path17 = require("path");
5973
+ import_node_fs17 = require("fs");
5974
+ import_node_path18 = require("path");
5975
5975
  init_paths();
5976
5976
  init_accounts();
5977
5977
  init_config();
@@ -6133,6 +6133,13 @@ function looksLikeMinifiedJsDump(line) {
6133
6133
  function looksLikeNestedElectronCrash(line) {
6134
6134
  return /HasCustomHostObject|ElectronInitializeICUandStartNode/i.test(line);
6135
6135
  }
6136
+ function looksLikeHomebrewLibuvCrash(line) {
6137
+ const uvRun = /uv_run/i.test(line);
6138
+ const spin = /SpinEventLoopInternal/i.test(line);
6139
+ const homebrewUv = /Cellar\/libuv|libuv\.\d\.dylib/i.test(line);
6140
+ const homebrewNode = /Cellar\/node\//i.test(line);
6141
+ return uvRun && (homebrewUv || spin || homebrewNode) || spin && (homebrewUv || homebrewNode);
6142
+ }
6136
6143
  function clipStderr(text3, maxChars) {
6137
6144
  const trimmed = text3.trim();
6138
6145
  if (trimmed.length <= maxChars) return trimmed;
@@ -6143,6 +6150,7 @@ function summarizeTurnStderr(tail, maxChars = 500) {
6143
6150
  const cursorStartup = [...tail].reverse().find((line) => /cursor startup failed:/i.test(line));
6144
6151
  if (cursorStartup) return clipStderr(cursorStartup, maxChars);
6145
6152
  if (tail.some(looksLikeNestedElectronCrash)) return NESTED_ELECTRON_SUMMARY;
6153
+ if (tail.some(looksLikeHomebrewLibuvCrash)) return HOMEBREW_LIBUV_SUMMARY;
6146
6154
  if (tail.some(
6147
6155
  (line) => /\[resource_exhausted\]|resource_exhausted/i.test(line) || /findFilesWithRipgrep/.test(line)
6148
6156
  )) {
@@ -6165,6 +6173,20 @@ function looksLikeInvalidAgentSession(text3) {
6165
6173
  if (!lower) return false;
6166
6174
  return /session not found/.test(lower) || /no conversation found/.test(lower) || /conversation .+ not found/.test(lower) || /thread .+ not found/.test(lower) || /unknown session/.test(lower) || /invalid session/.test(lower) || /session .+ (missing|expired|deleted|gone)/.test(lower) || /cannot resume/.test(lower) || /failed to (load|resume|open) session/.test(lower) || /corrupt local agent checkpoint/.test(lower) || /missing root blob/.test(lower) || /\bagent\b.{0,120}\bnot found\b/.test(lower);
6167
6175
  }
6176
+ function looksLikeRetryableRunnerCrash(text3) {
6177
+ if (looksLikeAgentFailureMessage(text3)) return false;
6178
+ if (looksLikeInvalidAgentSession(text3)) return false;
6179
+ const lower = text3.trim().toLowerCase();
6180
+ if (/cannot find (?:package|module)|err_module_not_found/.test(lower)) return false;
6181
+ if (!lower) return true;
6182
+ return /uv_run|spineventloopinternal|libuv|homebrew node \+ shared libuv|hascustomhostobject|electroninitializeicuandstartnode|nested chromium|truncated crash dump|sig(?:segv|abrt|ill)|segmentation fault|illegal instruction|fatal error/.test(
6183
+ lower
6184
+ );
6185
+ }
6186
+ function shouldRetryFailedAgentTurn(detail, opts) {
6187
+ if (looksLikeInvalidAgentSession(detail) && opts.hasSession) return true;
6188
+ return looksLikeRetryableRunnerCrash(detail);
6189
+ }
6168
6190
  function looksLikeAgentFailureMessage(text3) {
6169
6191
  const lower = text3.trim().toLowerCase();
6170
6192
  if (!lower) return false;
@@ -6209,11 +6231,22 @@ function humanizeAgentFailDetail(detail) {
6209
6231
  if (/hascustomhostobject|electroninitializeicuandstartnode|nested chromium/i.test(lower)) {
6210
6232
  return `${raw} \u2014 retry the turn; if it keeps failing, pick another agent.`;
6211
6233
  }
6234
+ if (/homebrew node \+ shared libuv|uv_run|spineventloopinternal/i.test(lower)) {
6235
+ return /brew install node@22/i.test(raw) ? raw : `${raw} \u2014 install Node 22 LTS (\`brew install node@22\`) and retry.`;
6236
+ }
6212
6237
  if (/corrupt local agent checkpoint|missing root blob|truncated crash dump/.test(lower)) {
6213
6238
  return `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
6214
6239
  }
6215
6240
  return raw;
6216
6241
  }
6242
+ function turnFailChatText(opts) {
6243
+ const chat = opts.assistantText.trim();
6244
+ if (chat) return chat;
6245
+ if (opts.exitCode === 0) return "";
6246
+ const detail = opts.detail.trim();
6247
+ if (detail) return humanizeAgentFailDetail(detail);
6248
+ return formatTurnExitError(opts.exitCode ?? 1, "");
6249
+ }
6217
6250
  function formatTurnExitError(exitCode, stderrSummary) {
6218
6251
  const code = exitCode ?? 1;
6219
6252
  const raw = stderrSummary.trim();
@@ -6227,12 +6260,13 @@ function formatTurnExitError(exitCode, stderrSummary) {
6227
6260
  if (looksLikeAgentFailureMessage(raw)) return detail;
6228
6261
  return `exit ${code}: ${detail}`;
6229
6262
  }
6230
- var NODE_VERSION_FOOTER, NESTED_ELECTRON_SUMMARY, MINIFIED_DUMP_SUMMARY;
6263
+ var NODE_VERSION_FOOTER, NESTED_ELECTRON_SUMMARY, HOMEBREW_LIBUV_SUMMARY, MINIFIED_DUMP_SUMMARY;
6231
6264
  var init_error_detail = __esm({
6232
6265
  "src/agents/error-detail.ts"() {
6233
6266
  "use strict";
6234
6267
  NODE_VERSION_FOOTER = /^Node\.js v\d+/i;
6235
6268
  NESTED_ELECTRON_SUMMARY = "Cursor local agent crashed at Electron startup (nested Chromium / HasCustomHostObject)";
6269
+ HOMEBREW_LIBUV_SUMMARY = "Cursor runner crashed in Node (Homebrew Node + shared libuv). Install Node 22 LTS (`brew install node@22`) and retry.";
6236
6270
  MINIFIED_DUMP_SUMMARY = "Cursor local agent crashed during startup (truncated crash dump)";
6237
6271
  }
6238
6272
  });
@@ -6521,11 +6555,11 @@ async function syncCliForTarget(accountId) {
6521
6555
  }
6522
6556
  applyConnectedTeamToCli(team);
6523
6557
  }
6524
- var import_node_fs17, brightsyAdapter;
6558
+ var import_node_fs18, brightsyAdapter;
6525
6559
  var init_brightsy = __esm({
6526
6560
  "src/agents/brightsy.ts"() {
6527
6561
  "use strict";
6528
- import_node_fs17 = require("fs");
6562
+ import_node_fs18 = require("fs");
6529
6563
  init_run();
6530
6564
  init_connected_teams();
6531
6565
  init_config();
@@ -6540,7 +6574,7 @@ var init_brightsy = __esm({
6540
6574
  async detect() {
6541
6575
  const brightsy = resolveAgentExecutable("brightsy");
6542
6576
  if (brightsy !== "brightsy") {
6543
- if (!(0, import_node_fs17.existsSync)(brightsy)) {
6577
+ if (!(0, import_node_fs18.existsSync)(brightsy)) {
6544
6578
  return {
6545
6579
  agent: "brightsy",
6546
6580
  installed: false,
@@ -6673,6 +6707,55 @@ var init_profile = __esm({
6673
6707
  }
6674
6708
  });
6675
6709
 
6710
+ // src/agents/packaged-runtime.ts
6711
+ function electronResourcesPath() {
6712
+ const resources = process.resourcesPath;
6713
+ if (typeof resources !== "string" || !resources) return null;
6714
+ return resources;
6715
+ }
6716
+ function packagedCursorRuntimeDir() {
6717
+ const resources = electronResourcesPath();
6718
+ if (!resources) return null;
6719
+ const dir = (0, import_node_path19.join)(resources, "cursor-runtime");
6720
+ if (!(0, import_node_fs19.existsSync)((0, import_node_path19.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
6721
+ return dir;
6722
+ }
6723
+ function packagedCursorRunnerPath() {
6724
+ const dir = packagedCursorRuntimeDir();
6725
+ return dir ? (0, import_node_path19.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
6726
+ }
6727
+ function packagedMcpDir() {
6728
+ const resources = electronResourcesPath();
6729
+ if (!resources) return null;
6730
+ const dir = (0, import_node_path19.join)(resources, "sideboard-mcp");
6731
+ if (!(0, import_node_fs19.existsSync)((0, import_node_path19.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
6732
+ return dir;
6733
+ }
6734
+ function packagedMcpStdioPath() {
6735
+ const dir = packagedMcpDir();
6736
+ return dir ? (0, import_node_path19.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
6737
+ }
6738
+ function packagedBundledNodePath() {
6739
+ const resources = electronResourcesPath();
6740
+ if (!resources) return null;
6741
+ const bin = (0, import_node_path19.join)(resources, "node", "bin", "node");
6742
+ if (!(0, import_node_fs19.existsSync)(bin)) return null;
6743
+ return bin;
6744
+ }
6745
+ function packagedCursorRipgrepCandidate(platformPkg, binName) {
6746
+ const dir = packagedCursorRuntimeDir();
6747
+ if (!dir) return null;
6748
+ return (0, import_node_path19.join)(dir, "node_modules", platformPkg, "bin", binName);
6749
+ }
6750
+ var import_node_fs19, import_node_path19;
6751
+ var init_packaged_runtime = __esm({
6752
+ "src/agents/packaged-runtime.ts"() {
6753
+ "use strict";
6754
+ import_node_fs19 = require("fs");
6755
+ import_node_path19 = require("path");
6756
+ }
6757
+ });
6758
+
6676
6759
  // src/agents/node-launch.ts
6677
6760
  function isAsarPath(filePath) {
6678
6761
  if (/\.asar\.unpacked([/\\]|$)/.test(filePath)) return false;
@@ -6682,24 +6765,129 @@ function unpackedAsarPath(filePath) {
6682
6765
  if (!isAsarPath(filePath)) return null;
6683
6766
  const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
6684
6767
  if (unpacked === filePath) return null;
6685
- return (0, import_node_fs18.existsSync)(unpacked) ? unpacked : null;
6768
+ return (0, import_node_fs20.existsSync)(unpacked) ? unpacked : null;
6686
6769
  }
6687
6770
  function nodeReadableScriptPath(scriptPath) {
6688
6771
  return unpackedAsarPath(scriptPath) ?? scriptPath;
6689
6772
  }
6690
- async function findSystemNode() {
6691
- const whichNode = await run("which", ["node"], { reject: false });
6692
- const fromWhich = whichNode.exitCode === 0 && whichNode.stdout.trim() ? whichNode.stdout.trim() : "";
6693
- if (fromWhich && !isElectronLikeCommand(fromWhich)) return fromWhich;
6694
- const fallbacks = [
6695
- ...WELL_KNOWN_NODE_BINS,
6696
- (0, import_node_path18.join)((0, import_node_os7.homedir)(), ".local/share/fnm/aliases/default/bin/node"),
6697
- (0, import_node_path18.join)((0, import_node_os7.homedir)(), ".nvm/current/bin/node")
6773
+ function parseNodeMajor(version) {
6774
+ const match = /^v?(\d+)/.exec(version.trim());
6775
+ if (!match) return null;
6776
+ const major = Number(match[1]);
6777
+ return Number.isInteger(major) ? major : null;
6778
+ }
6779
+ function scoreNodeForAgentRuntime(candidate) {
6780
+ const major = parseNodeMajor(candidate.version);
6781
+ if (major == null) return Number.NEGATIVE_INFINITY;
6782
+ if (major < 20) return major - 100;
6783
+ const posix = candidate.path.replace(/\\/g, "/");
6784
+ let score = 0;
6785
+ if (major % 2 === 0) {
6786
+ score += 1e3 + major * 10;
6787
+ } else {
6788
+ score += major;
6789
+ }
6790
+ if (/\/Cellar\/node\/\d/.test(posix) && !/\/Cellar\/node@\d+/.test(posix)) {
6791
+ score -= 50;
6792
+ }
6793
+ return score;
6794
+ }
6795
+ function pickPreferredNode(candidates) {
6796
+ let best = null;
6797
+ let bestScore = Number.NEGATIVE_INFINITY;
6798
+ for (const candidate of candidates) {
6799
+ const score = scoreNodeForAgentRuntime(candidate);
6800
+ if (score > bestScore) {
6801
+ bestScore = score;
6802
+ best = candidate;
6803
+ }
6804
+ }
6805
+ return best;
6806
+ }
6807
+ function versionDirNodeBins(root, toBin) {
6808
+ if (!(0, import_node_fs20.existsSync)(root)) return [];
6809
+ try {
6810
+ return (0, import_node_fs20.readdirSync)(root).map(toBin);
6811
+ } catch {
6812
+ return [];
6813
+ }
6814
+ }
6815
+ function defaultNodeBinCandidates(home = (0, import_node_os7.homedir)()) {
6816
+ const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
6817
+ (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path20.join)(prefix, "opt", `node@${major}`, "bin", "node"))
6818
+ );
6819
+ return [
6820
+ ...kegs,
6821
+ "/opt/homebrew/bin/node",
6822
+ "/usr/local/bin/node",
6823
+ (0, import_node_path20.join)(home, ".local/share/fnm/aliases/default/bin/node"),
6824
+ (0, import_node_path20.join)(home, ".nvm/current/bin/node"),
6825
+ (0, import_node_path20.join)(home, ".volta/bin/node"),
6826
+ (0, import_node_path20.join)(home, ".asdf/shims/node"),
6827
+ (0, import_node_path20.join)(home, ".local/share/mise/shims/node"),
6828
+ ...versionDirNodeBins(
6829
+ (0, import_node_path20.join)(home, ".nvm", "versions", "node"),
6830
+ (name) => (0, import_node_path20.join)(home, ".nvm", "versions", "node", name, "bin", "node")
6831
+ ),
6832
+ ...versionDirNodeBins(
6833
+ (0, import_node_path20.join)(home, ".local/share/fnm", "node-versions"),
6834
+ (name) => (0, import_node_path20.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
6835
+ ),
6836
+ ...versionDirNodeBins(
6837
+ (0, import_node_path20.join)(home, ".volta", "tools", "image", "node"),
6838
+ (name) => (0, import_node_path20.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
6839
+ )
6698
6840
  ];
6699
- for (const bin of fallbacks) {
6700
- if ((0, import_node_fs18.existsSync)(bin) && !isElectronLikeCommand(bin)) return bin;
6841
+ }
6842
+ function uniqueExistingNodeBins(paths) {
6843
+ const seen = /* @__PURE__ */ new Set();
6844
+ const out = [];
6845
+ for (const raw of paths) {
6846
+ const p = raw.trim();
6847
+ if (!p || !(0, import_node_fs20.existsSync)(p) || isElectronLikeCommand(p)) continue;
6848
+ let key = p;
6849
+ try {
6850
+ key = (0, import_node_fs20.realpathSync)(p);
6851
+ } catch {
6852
+ continue;
6853
+ }
6854
+ if (seen.has(key)) continue;
6855
+ seen.add(key);
6856
+ out.push(p);
6701
6857
  }
6702
- return null;
6858
+ return out;
6859
+ }
6860
+ async function whichAllNode() {
6861
+ if (process.platform === "win32") {
6862
+ const located = await run("where", ["node"], { reject: false, timeoutMs: 5e3 });
6863
+ if (located.exitCode !== 0) return [];
6864
+ return located.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
6865
+ }
6866
+ const all = await run("which", ["-a", "node"], { reject: false, timeoutMs: 5e3 });
6867
+ if (all.exitCode === 0 && all.stdout.trim()) {
6868
+ return all.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
6869
+ }
6870
+ const single = await run("which", ["node"], { reject: false, timeoutMs: 5e3 });
6871
+ if (single.exitCode !== 0 || !single.stdout.trim()) return [];
6872
+ return [single.stdout.trim()];
6873
+ }
6874
+ async function probeNodeVersion(bin) {
6875
+ const probed = await run(bin, ["-v"], { reject: false, timeoutMs: 4e3 });
6876
+ if (probed.exitCode !== 0) return null;
6877
+ const version = probed.stdout.trim().split(/\r?\n/).find(Boolean);
6878
+ return version || null;
6879
+ }
6880
+ async function findSystemNode() {
6881
+ const fromPath = await whichAllNode();
6882
+ const bins = uniqueExistingNodeBins([...fromPath, ...defaultNodeBinCandidates()]);
6883
+ if (bins.length === 0) return null;
6884
+ const probed = await Promise.all(
6885
+ bins.map(async (path2) => {
6886
+ const version = await probeNodeVersion(path2);
6887
+ return version ? { path: path2, version } : null;
6888
+ })
6889
+ );
6890
+ return pickPreferredNode(probed.filter((c) => c != null));
6703
6891
  }
6704
6892
  function applyNodeLaunch(launch, args) {
6705
6893
  const readableArgs = args.map(nodeReadableScriptPath);
@@ -6717,9 +6905,13 @@ function applyNodeLaunch(launch, args) {
6717
6905
  async function resolveNodeLaunch(scriptPath) {
6718
6906
  const script = nodeReadableScriptPath(scriptPath);
6719
6907
  if (!isAsarPath(script)) {
6720
- const nodeBin = await findSystemNode();
6721
- if (nodeBin) {
6722
- return { file: nodeBin, env: {} };
6908
+ const bundled = packagedBundledNodePath();
6909
+ if (bundled && !isElectronLikeCommand(bundled)) {
6910
+ return { file: bundled, env: {} };
6911
+ }
6912
+ const node = await findSystemNode();
6913
+ if (node) {
6914
+ return { file: node.path, env: {}, nodeVersion: node.version };
6723
6915
  }
6724
6916
  }
6725
6917
  return {
@@ -6727,61 +6919,17 @@ async function resolveNodeLaunch(scriptPath) {
6727
6919
  env: { ELECTRON_RUN_AS_NODE: "1" }
6728
6920
  };
6729
6921
  }
6730
- var import_node_fs18, import_node_os7, import_node_path18, WELL_KNOWN_NODE_BINS;
6922
+ var import_node_fs20, import_node_os7, import_node_path20, PREFERRED_LTS_MAJORS;
6731
6923
  var init_node_launch = __esm({
6732
6924
  "src/agents/node-launch.ts"() {
6733
6925
  "use strict";
6734
- import_node_fs18 = require("fs");
6926
+ import_node_fs20 = require("fs");
6735
6927
  import_node_os7 = require("os");
6736
- import_node_path18 = require("path");
6928
+ import_node_path20 = require("path");
6737
6929
  init_nested_electron_env();
6738
6930
  init_run();
6739
- WELL_KNOWN_NODE_BINS = [
6740
- "/opt/homebrew/bin/node",
6741
- "/usr/local/bin/node"
6742
- ];
6743
- }
6744
- });
6745
-
6746
- // src/agents/packaged-runtime.ts
6747
- function electronResourcesPath() {
6748
- const resources = process.resourcesPath;
6749
- if (typeof resources !== "string" || !resources) return null;
6750
- return resources;
6751
- }
6752
- function packagedCursorRuntimeDir() {
6753
- const resources = electronResourcesPath();
6754
- if (!resources) return null;
6755
- const dir = (0, import_node_path19.join)(resources, "cursor-runtime");
6756
- if (!(0, import_node_fs19.existsSync)((0, import_node_path19.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
6757
- return dir;
6758
- }
6759
- function packagedCursorRunnerPath() {
6760
- const dir = packagedCursorRuntimeDir();
6761
- return dir ? (0, import_node_path19.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
6762
- }
6763
- function packagedMcpDir() {
6764
- const resources = electronResourcesPath();
6765
- if (!resources) return null;
6766
- const dir = (0, import_node_path19.join)(resources, "sideboard-mcp");
6767
- if (!(0, import_node_fs19.existsSync)((0, import_node_path19.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
6768
- return dir;
6769
- }
6770
- function packagedMcpStdioPath() {
6771
- const dir = packagedMcpDir();
6772
- return dir ? (0, import_node_path19.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
6773
- }
6774
- function packagedCursorRipgrepCandidate(platformPkg, binName) {
6775
- const dir = packagedCursorRuntimeDir();
6776
- if (!dir) return null;
6777
- return (0, import_node_path19.join)(dir, "node_modules", platformPkg, "bin", binName);
6778
- }
6779
- var import_node_fs19, import_node_path19;
6780
- var init_packaged_runtime = __esm({
6781
- "src/agents/packaged-runtime.ts"() {
6782
- "use strict";
6783
- import_node_fs19 = require("fs");
6784
- import_node_path19 = require("path");
6931
+ init_packaged_runtime();
6932
+ PREFERRED_LTS_MAJORS = [24, 22, 20];
6785
6933
  }
6786
6934
  });
6787
6935
 
@@ -6868,37 +7016,37 @@ function corePackageDir() {
6868
7016
  try {
6869
7017
  const url = import_meta.url;
6870
7018
  if (typeof url === "string" && url.length > 0) {
6871
- return (0, import_node_path20.dirname)((0, import_node_url.fileURLToPath)(url));
7019
+ return (0, import_node_path21.dirname)((0, import_node_url.fileURLToPath)(url));
6872
7020
  }
6873
7021
  } catch {
6874
7022
  }
6875
7023
  try {
6876
- const req = (0, import_node_module.createRequire)((0, import_node_path20.join)(process.cwd(), "package.json"));
6877
- return (0, import_node_path20.dirname)(req.resolve("@sideboard-ai/core"));
7024
+ const req = (0, import_node_module.createRequire)((0, import_node_path21.join)(process.cwd(), "package.json"));
7025
+ return (0, import_node_path21.dirname)(req.resolve("@sideboard-ai/core"));
6878
7026
  } catch {
6879
7027
  return process.cwd();
6880
7028
  }
6881
7029
  }
6882
7030
  function findSideboardMcpJsEntry() {
6883
7031
  const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
6884
- if (override && (0, import_node_fs20.existsSync)(override)) return override;
7032
+ if (override && (0, import_node_fs21.existsSync)(override)) return override;
6885
7033
  const packaged = packagedMcpStdioPath();
6886
7034
  if (packaged) return packaged;
6887
7035
  let dir = corePackageDir();
6888
7036
  for (let i = 0; i < 10; i++) {
6889
7037
  const candidates = [
6890
- (0, import_node_path20.join)(dir, "mcp/run-stdio.js"),
6891
- (0, import_node_path20.join)(dir, "mcp/run-stdio.cjs"),
6892
- (0, import_node_path20.join)(dir, "dist/mcp/run-stdio.js"),
6893
- (0, import_node_path20.join)(dir, "dist/mcp/run-stdio.cjs"),
6894
- (0, import_node_path20.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
6895
- (0, import_node_path20.join)(dir, "packages/cli/dist/index.js"),
6896
- (0, import_node_path20.join)(dir, "cli/dist/index.js")
7038
+ (0, import_node_path21.join)(dir, "mcp/run-stdio.js"),
7039
+ (0, import_node_path21.join)(dir, "mcp/run-stdio.cjs"),
7040
+ (0, import_node_path21.join)(dir, "dist/mcp/run-stdio.js"),
7041
+ (0, import_node_path21.join)(dir, "dist/mcp/run-stdio.cjs"),
7042
+ (0, import_node_path21.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
7043
+ (0, import_node_path21.join)(dir, "packages/cli/dist/index.js"),
7044
+ (0, import_node_path21.join)(dir, "cli/dist/index.js")
6897
7045
  ];
6898
7046
  for (const p of candidates) {
6899
- if ((0, import_node_fs20.existsSync)(p) && !isAsarPath(p)) return p;
7047
+ if ((0, import_node_fs21.existsSync)(p) && !isAsarPath(p)) return p;
6900
7048
  }
6901
- const parent = (0, import_node_path20.dirname)(dir);
7049
+ const parent = (0, import_node_path21.dirname)(dir);
6902
7050
  if (parent === dir) break;
6903
7051
  dir = parent;
6904
7052
  }
@@ -7039,22 +7187,22 @@ function writeMcpServersConfig(servers) {
7039
7187
  ...env ? { env } : {}
7040
7188
  };
7041
7189
  }
7042
- const dir = (0, import_node_fs20.mkdtempSync)((0, import_node_path20.join)((0, import_node_os8.tmpdir)(), "sideboard-mcp-"));
7043
- const cfgPath = (0, import_node_path20.join)(dir, "mcp.json");
7044
- (0, import_node_fs20.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
7190
+ const dir = (0, import_node_fs21.mkdtempSync)((0, import_node_path21.join)((0, import_node_os8.tmpdir)(), "sideboard-mcp-"));
7191
+ const cfgPath = (0, import_node_path21.join)(dir, "mcp.json");
7192
+ (0, import_node_fs21.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
7045
7193
  return cfgPath;
7046
7194
  }
7047
7195
  async function writeInjectedMcpConfig(opts) {
7048
7196
  return writeMcpServersConfig(await buildInjectedMcpServers(opts));
7049
7197
  }
7050
- var import_node_fs20, import_node_module, import_node_os8, import_node_path20, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
7198
+ var import_node_fs21, import_node_module, import_node_os8, import_node_path21, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
7051
7199
  var init_injected_mcp = __esm({
7052
7200
  "src/agents/injected-mcp.ts"() {
7053
7201
  "use strict";
7054
- import_node_fs20 = require("fs");
7202
+ import_node_fs21 = require("fs");
7055
7203
  import_node_module = require("module");
7056
7204
  import_node_os8 = require("os");
7057
- import_node_path20 = require("path");
7205
+ import_node_path21 = require("path");
7058
7206
  import_node_url = require("url");
7059
7207
  init_run();
7060
7208
  init_config();
@@ -7247,11 +7395,11 @@ function parseIssuesJson(raw) {
7247
7395
  }
7248
7396
  return [];
7249
7397
  }
7250
- var import_node_fs21, BASE_ALLOWED_TOOLS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
7398
+ var import_node_fs22, BASE_ALLOWED_TOOLS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
7251
7399
  var init_claude = __esm({
7252
7400
  "src/agents/claude.ts"() {
7253
7401
  "use strict";
7254
- import_node_fs21 = require("fs");
7402
+ import_node_fs22 = require("fs");
7255
7403
  init_run();
7256
7404
  init_app_settings();
7257
7405
  init_claude_mcp();
@@ -7280,7 +7428,7 @@ var init_claude = __esm({
7280
7428
  async detect() {
7281
7429
  const claude = resolveClaudeExecutable();
7282
7430
  if (claude !== "claude") {
7283
- if (!(0, import_node_fs21.existsSync)(claude)) {
7431
+ if (!(0, import_node_fs22.existsSync)(claude)) {
7284
7432
  return {
7285
7433
  agent: "claude",
7286
7434
  installed: false,
@@ -7517,7 +7665,7 @@ async function listCodexModels() {
7517
7665
  if (codex === "codex") {
7518
7666
  const which = await run("which", ["codex"], { reject: false });
7519
7667
  if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
7520
- } else if (!(0, import_node_fs22.existsSync)(codex)) {
7668
+ } else if (!(0, import_node_fs23.existsSync)(codex)) {
7521
7669
  return FALLBACK_CODEX_MODELS;
7522
7670
  }
7523
7671
  const listed = await run(codex, ["debug", "models"], { reject: false });
@@ -7552,12 +7700,12 @@ function usageFromCodex(usage) {
7552
7700
  }
7553
7701
  function codexConfigHasNetworkAccess() {
7554
7702
  const candidates = [
7555
- (0, import_node_path21.join)((0, import_node_os9.homedir)(), ".codex", "config.toml"),
7556
- (0, import_node_path21.join)((0, import_node_os9.homedir)(), ".config", "codex", "config.toml")
7703
+ (0, import_node_path22.join)((0, import_node_os9.homedir)(), ".codex", "config.toml"),
7704
+ (0, import_node_path22.join)((0, import_node_os9.homedir)(), ".config", "codex", "config.toml")
7557
7705
  ];
7558
7706
  for (const path2 of candidates) {
7559
- if (!(0, import_node_fs22.existsSync)(path2)) continue;
7560
- const text3 = (0, import_node_fs22.readFileSync)(path2, "utf8");
7707
+ if (!(0, import_node_fs23.existsSync)(path2)) continue;
7708
+ const text3 = (0, import_node_fs23.readFileSync)(path2, "utf8");
7561
7709
  if (/network_access\s*=\s*true/.test(text3)) return true;
7562
7710
  }
7563
7711
  return false;
@@ -7589,21 +7737,21 @@ function asRecord(value) {
7589
7737
  return void 0;
7590
7738
  }
7591
7739
  function codexLooksAuthenticated() {
7592
- const authPath = (0, import_node_path21.join)((0, import_node_os9.homedir)(), ".codex", "auth.json");
7593
- if (!(0, import_node_fs22.existsSync)(authPath)) return false;
7740
+ const authPath = (0, import_node_path22.join)((0, import_node_os9.homedir)(), ".codex", "auth.json");
7741
+ if (!(0, import_node_fs23.existsSync)(authPath)) return false;
7594
7742
  try {
7595
- return (0, import_node_fs22.statSync)(authPath).size > 2;
7743
+ return (0, import_node_fs23.statSync)(authPath).size > 2;
7596
7744
  } catch {
7597
7745
  return false;
7598
7746
  }
7599
7747
  }
7600
- var import_node_fs22, import_node_os9, import_node_path21, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
7748
+ var import_node_fs23, import_node_os9, import_node_path22, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
7601
7749
  var init_codex = __esm({
7602
7750
  "src/agents/codex.ts"() {
7603
7751
  "use strict";
7604
- import_node_fs22 = require("fs");
7752
+ import_node_fs23 = require("fs");
7605
7753
  import_node_os9 = require("os");
7606
- import_node_path21 = require("path");
7754
+ import_node_path22 = require("path");
7607
7755
  init_run();
7608
7756
  init_app_settings();
7609
7757
  init_global_workspace();
@@ -7628,7 +7776,7 @@ var init_codex = __esm({
7628
7776
  async detect() {
7629
7777
  const codex = resolveAgentExecutable("codex");
7630
7778
  if (codex !== "codex") {
7631
- if (!(0, import_node_fs22.existsSync)(codex)) {
7779
+ if (!(0, import_node_fs23.existsSync)(codex)) {
7632
7780
  return {
7633
7781
  agent: "codex",
7634
7782
  installed: false,
@@ -8037,21 +8185,21 @@ function platformRipgrepPackage() {
8037
8185
  }
8038
8186
  function usableRipgrepPath(candidate) {
8039
8187
  const raw = candidate?.trim();
8040
- if (!raw || !(0, import_node_path22.isAbsolute)(raw)) return null;
8188
+ if (!raw || !(0, import_node_path23.isAbsolute)(raw)) return null;
8041
8189
  const readable = nodeReadableScriptPath(raw);
8042
- if (!(0, import_node_fs23.existsSync)(readable) || isAsarPath(readable)) return null;
8190
+ if (!(0, import_node_fs24.existsSync)(readable) || isAsarPath(readable)) return null;
8043
8191
  return readable;
8044
8192
  }
8045
8193
  function walkForBundledRipgrep(startFile) {
8046
8194
  if (!startFile) return null;
8047
8195
  const pkg = platformRipgrepPackage();
8048
8196
  const name = rgBinaryName();
8049
- let dir = (0, import_node_path22.dirname)((0, import_node_path22.resolve)(startFile));
8050
- const root = (0, import_node_path22.parse)(dir).root;
8197
+ let dir = (0, import_node_path23.dirname)((0, import_node_path23.resolve)(startFile));
8198
+ const root = (0, import_node_path23.parse)(dir).root;
8051
8199
  while (dir !== root) {
8052
- const hit = usableRipgrepPath((0, import_node_path22.join)(dir, "node_modules", pkg, "bin", name));
8200
+ const hit = usableRipgrepPath((0, import_node_path23.join)(dir, "node_modules", pkg, "bin", name));
8053
8201
  if (hit) return hit;
8054
- const next = (0, import_node_path22.dirname)(dir);
8202
+ const next = (0, import_node_path23.dirname)(dir);
8055
8203
  if (next === dir) break;
8056
8204
  dir = next;
8057
8205
  }
@@ -8061,7 +8209,7 @@ function requireResolveBundledRipgrep(fromFile) {
8061
8209
  try {
8062
8210
  const req = (0, import_node_module2.createRequire)(fromFile);
8063
8211
  const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
8064
- return usableRipgrepPath((0, import_node_path22.join)((0, import_node_path22.dirname)(pkgJson), "bin", rgBinaryName()));
8212
+ return usableRipgrepPath((0, import_node_path23.join)((0, import_node_path23.dirname)(pkgJson), "bin", rgBinaryName()));
8065
8213
  } catch {
8066
8214
  return null;
8067
8215
  }
@@ -8081,13 +8229,13 @@ function cursorRipgrepEnv(opts) {
8081
8229
  const path2 = resolveCursorRipgrepPath(opts);
8082
8230
  return path2 ? { [RIPGREP_ENV]: path2 } : {};
8083
8231
  }
8084
- var import_node_fs23, import_node_module2, import_node_path22, import_node_url2, import_meta2, RIPGREP_ENV;
8232
+ var import_node_fs24, import_node_module2, import_node_path23, import_node_url2, import_meta2, RIPGREP_ENV;
8085
8233
  var init_cursor_ripgrep = __esm({
8086
8234
  "src/agents/cursor-ripgrep.ts"() {
8087
8235
  "use strict";
8088
- import_node_fs23 = require("fs");
8236
+ import_node_fs24 = require("fs");
8089
8237
  import_node_module2 = require("module");
8090
- import_node_path22 = require("path");
8238
+ import_node_path23 = require("path");
8091
8239
  import_node_url2 = require("url");
8092
8240
  init_node_launch();
8093
8241
  init_packaged_runtime();
@@ -8135,11 +8283,11 @@ function entryDir() {
8135
8283
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
8136
8284
  if (cjsDir) return cjsDir;
8137
8285
  try {
8138
- return (0, import_node_path23.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
8286
+ return (0, import_node_path24.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
8139
8287
  } catch {
8140
8288
  try {
8141
8289
  const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
8142
- return (0, import_node_path23.dirname)(req.resolve("@sideboard-ai/core"));
8290
+ return (0, import_node_path24.dirname)(req.resolve("@sideboard-ai/core"));
8143
8291
  } catch {
8144
8292
  return process.cwd();
8145
8293
  }
@@ -8150,27 +8298,27 @@ function cursorRunnerPath() {
8150
8298
  if (packaged) return packaged;
8151
8299
  const root = entryDir();
8152
8300
  const candidates = [
8153
- (0, import_node_path23.join)(root, "agents", "cursor-runner.js"),
8154
- (0, import_node_path23.join)(root, "agents", "cursor-runner.cjs"),
8301
+ (0, import_node_path24.join)(root, "agents", "cursor-runner.js"),
8302
+ (0, import_node_path24.join)(root, "agents", "cursor-runner.cjs"),
8155
8303
  // If somehow resolved from package root instead of dist/
8156
- (0, import_node_path23.join)(root, "dist", "agents", "cursor-runner.js"),
8157
- (0, import_node_path23.join)(root, "dist", "agents", "cursor-runner.cjs"),
8304
+ (0, import_node_path24.join)(root, "dist", "agents", "cursor-runner.js"),
8305
+ (0, import_node_path24.join)(root, "dist", "agents", "cursor-runner.cjs"),
8158
8306
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
8159
- (0, import_node_path23.join)(root, "cursor-runner.ts"),
8160
- (0, import_node_path23.join)(root, "src", "agents", "cursor-runner.ts")
8307
+ (0, import_node_path24.join)(root, "cursor-runner.ts"),
8308
+ (0, import_node_path24.join)(root, "src", "agents", "cursor-runner.ts")
8161
8309
  ];
8162
8310
  for (const candidate of candidates) {
8163
- if ((0, import_node_fs24.existsSync)(candidate)) return candidate;
8311
+ if ((0, import_node_fs25.existsSync)(candidate)) return candidate;
8164
8312
  }
8165
8313
  return candidates[0];
8166
8314
  }
8167
- var import_node_fs24, import_node_module3, import_node_path23, import_node_url3, import_sdk, import_meta3, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
8315
+ var import_node_fs25, import_node_module3, import_node_path24, import_node_url3, import_sdk, import_meta3, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
8168
8316
  var init_cursor = __esm({
8169
8317
  "src/agents/cursor.ts"() {
8170
8318
  "use strict";
8171
- import_node_fs24 = require("fs");
8319
+ import_node_fs25 = require("fs");
8172
8320
  import_node_module3 = require("module");
8173
- import_node_path23 = require("path");
8321
+ import_node_path24 = require("path");
8174
8322
  import_node_url3 = require("url");
8175
8323
  import_sdk = require("@cursor/sdk");
8176
8324
  init_run();
@@ -8302,7 +8450,7 @@ async function listOpencodeModels() {
8302
8450
  if (opencode === "opencode") {
8303
8451
  const which = await run("which", ["opencode"], { reject: false });
8304
8452
  if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
8305
- } else if (!(0, import_node_fs25.existsSync)(opencode)) {
8453
+ } else if (!(0, import_node_fs26.existsSync)(opencode)) {
8306
8454
  return FALLBACK_OPENCODE_MODELS;
8307
8455
  }
8308
8456
  const listed = await run(opencode, ["models"], { reject: false });
@@ -8332,11 +8480,11 @@ function usageFromOpencode(tokens) {
8332
8480
  cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
8333
8481
  };
8334
8482
  }
8335
- var import_node_fs25, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
8483
+ var import_node_fs26, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
8336
8484
  var init_opencode = __esm({
8337
8485
  "src/agents/opencode.ts"() {
8338
8486
  "use strict";
8339
- import_node_fs25 = require("fs");
8487
+ import_node_fs26 = require("fs");
8340
8488
  init_run();
8341
8489
  init_app_settings();
8342
8490
  init_global_workspace();
@@ -8362,7 +8510,7 @@ var init_opencode = __esm({
8362
8510
  async detect() {
8363
8511
  const opencode = resolveAgentExecutable("opencode");
8364
8512
  if (opencode !== "opencode") {
8365
- if (!(0, import_node_fs25.existsSync)(opencode)) {
8513
+ if (!(0, import_node_fs26.existsSync)(opencode)) {
8366
8514
  return {
8367
8515
  agent: "opencode",
8368
8516
  installed: false,
@@ -9159,40 +9307,40 @@ __export(plan_file_exports, {
9159
9307
  writePlanFile: () => writePlanFile
9160
9308
  });
9161
9309
  function ensureAttachmentsGitignore2(worktreePath) {
9162
- const gitignoreAbs = (0, import_node_path36.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
9163
- if ((0, import_node_fs39.existsSync)(gitignoreAbs)) return;
9164
- (0, import_node_fs39.mkdirSync)((0, import_node_path36.dirname)(gitignoreAbs), { recursive: true });
9165
- (0, import_node_fs39.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
9310
+ const gitignoreAbs = (0, import_node_path37.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
9311
+ if ((0, import_node_fs40.existsSync)(gitignoreAbs)) return;
9312
+ (0, import_node_fs40.mkdirSync)((0, import_node_path37.dirname)(gitignoreAbs), { recursive: true });
9313
+ (0, import_node_fs40.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
9166
9314
  }
9167
9315
  function planFileAbs(worktreePath) {
9168
- return (0, import_node_path36.join)(worktreePath, PLAN_FILE_REL);
9316
+ return (0, import_node_path37.join)(worktreePath, PLAN_FILE_REL);
9169
9317
  }
9170
9318
  function readTextIfPresent2(abs) {
9171
- if (!(0, import_node_fs39.existsSync)(abs)) return null;
9319
+ if (!(0, import_node_fs40.existsSync)(abs)) return null;
9172
9320
  try {
9173
- const content = (0, import_node_fs39.readFileSync)(abs, "utf8");
9321
+ const content = (0, import_node_fs40.readFileSync)(abs, "utf8");
9174
9322
  return content.trim() ? content : null;
9175
9323
  } catch {
9176
9324
  return null;
9177
9325
  }
9178
9326
  }
9179
9327
  function readPlanFile(worktreePath) {
9180
- return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path36.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path36.join)(worktreePath, LEGACY_PLAN_FILE_REL));
9328
+ return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path37.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path37.join)(worktreePath, LEGACY_PLAN_FILE_REL));
9181
9329
  }
9182
9330
  function writePlanFile(worktreePath, content) {
9183
9331
  ensureAttachmentsGitignore2(worktreePath);
9184
9332
  const abs = planFileAbs(worktreePath);
9185
- (0, import_node_fs39.mkdirSync)((0, import_node_path36.dirname)(abs), { recursive: true });
9333
+ (0, import_node_fs40.mkdirSync)((0, import_node_path37.dirname)(abs), { recursive: true });
9186
9334
  const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
9187
- (0, import_node_fs39.writeFileSync)(abs, body, "utf8");
9335
+ (0, import_node_fs40.writeFileSync)(abs, body, "utf8");
9188
9336
  return PLAN_FILE_REL;
9189
9337
  }
9190
- var import_node_fs39, import_node_path36;
9338
+ var import_node_fs40, import_node_path37;
9191
9339
  var init_plan_file = __esm({
9192
9340
  "src/plan/plan-file.ts"() {
9193
9341
  "use strict";
9194
- import_node_fs39 = require("fs");
9195
- import_node_path36 = require("path");
9342
+ import_node_fs40 = require("fs");
9343
+ import_node_path37 = require("path");
9196
9344
  init_workspace_scratch();
9197
9345
  init_plan_present();
9198
9346
  init_plan_present();
@@ -9207,10 +9355,10 @@ __export(cursor_recover_exports, {
9207
9355
  function recoverFinishedCursorRun(opts) {
9208
9356
  const agentId = opts.agentId.trim();
9209
9357
  if (!agentId) return null;
9210
- const runsPath = (0, import_node_path37.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
9211
- if (!(0, import_node_fs40.existsSync)(runsPath)) return null;
9358
+ const runsPath = (0, import_node_path38.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
9359
+ if (!(0, import_node_fs41.existsSync)(runsPath)) return null;
9212
9360
  try {
9213
- const lines = (0, import_node_fs40.readFileSync)(runsPath, "utf8").split("\n");
9361
+ const lines = (0, import_node_fs41.readFileSync)(runsPath, "utf8").split("\n");
9214
9362
  let best = null;
9215
9363
  for (const line of lines) {
9216
9364
  const trimmed = line.trim();
@@ -9236,12 +9384,12 @@ function recoverFinishedCursorRun(opts) {
9236
9384
  return null;
9237
9385
  }
9238
9386
  }
9239
- var import_node_fs40, import_node_path37;
9387
+ var import_node_fs41, import_node_path38;
9240
9388
  var init_cursor_recover = __esm({
9241
9389
  "src/agents/cursor-recover.ts"() {
9242
9390
  "use strict";
9243
- import_node_fs40 = require("fs");
9244
- import_node_path37 = require("path");
9391
+ import_node_fs41 = require("fs");
9392
+ import_node_path38 = require("path");
9245
9393
  init_paths();
9246
9394
  }
9247
9395
  });
@@ -9388,6 +9536,7 @@ __export(index_exports, {
9388
9536
  captureTurnBaseline: () => captureTurnBaseline,
9389
9537
  checkoutPrStackLayer: () => checkoutPrStackLayer,
9390
9538
  childEnvWithAppSettings: () => childEnvWithAppSettings,
9539
+ claimDesktopHost: () => claimDesktopHost,
9391
9540
  claudeAdapter: () => claudeAdapter,
9392
9541
  claudeChromeEnabled: () => claudeChromeEnabled,
9393
9542
  claudeUserSettingsPath: () => claudeUserSettingsPath,
@@ -9426,6 +9575,7 @@ __export(index_exports, {
9426
9575
  decodeBrightsyTarget: () => decodeBrightsyTarget,
9427
9576
  deleteBranchOnPurgeEnabled: () => deleteBranchOnPurgeEnabled,
9428
9577
  deleteThreadRecord: () => deleteThreadRecord,
9578
+ desktopHostPidPath: () => desktopHostPidPath,
9429
9579
  detectAgents: () => detectAgents,
9430
9580
  detectGhStack: () => detectGhStack,
9431
9581
  detectLocalMergeConflicts: () => detectLocalMergeConflicts,
@@ -9551,6 +9701,7 @@ __export(index_exports, {
9551
9701
  isConductorBundledCli: () => isConductorBundledCli,
9552
9702
  isCursorAutoModel: () => isCursorAutoModel,
9553
9703
  isDefaultishSourceRef: () => isDefaultishSourceRef,
9704
+ isDesktopHostAlive: () => isDesktopHostAlive,
9554
9705
  isDirty: () => isDirty,
9555
9706
  isGhRateLimitError: () => isGhRateLimitError,
9556
9707
  isGlobalRepoPath: () => isGlobalRepoPath,
@@ -9572,6 +9723,7 @@ __export(index_exports, {
9572
9723
  isSlackExternalReplyPrompt: () => isSlackExternalReplyPrompt,
9573
9724
  isSlackOAuthCancelled: () => isSlackOAuthCancelled,
9574
9725
  isThinkingEffort: () => isThinkingEffort,
9726
+ isThisProcessDesktopHost: () => isThisProcessDesktopHost,
9575
9727
  isThreadCaffeinated: () => isThreadCaffeinated,
9576
9728
  isWorkspaceScratchPath: () => isWorkspaceScratchPath,
9577
9729
  linearAuthorizationHeader: () => linearAuthorizationHeader,
@@ -9673,6 +9825,7 @@ __export(index_exports, {
9673
9825
  refreshSlackReplyBadges: () => refreshSlackReplyBadges,
9674
9826
  registerPackagedUserMcpClients: () => registerPackagedUserMcpClients,
9675
9827
  releaseCaffeinateHoldForThread: () => releaseCaffeinateHoldForThread,
9828
+ releaseDesktopHost: () => releaseDesktopHost,
9676
9829
  removeWorkspace: () => removeWorkspace,
9677
9830
  removeWorktree: () => removeWorktree,
9678
9831
  repoSlug: () => repoSlug,
@@ -9773,6 +9926,7 @@ __export(index_exports, {
9773
9926
  taskMessageText: () => taskMessageText,
9774
9927
  thinkingEffortBars: () => thinkingEffortBars,
9775
9928
  thinkingEffortLabel: () => thinkingEffortLabel,
9929
+ thisProcessShouldDrainAgentQueues: () => thisProcessShouldDrainAgentQueues,
9776
9930
  threadDisplayLabel: () => threadDisplayLabel,
9777
9931
  threadFilePath: () => threadFilePath,
9778
9932
  threadLockPath: () => threadLockPath,
@@ -9820,6 +9974,55 @@ init_app_settings();
9820
9974
  init_caffeinate_hold();
9821
9975
  init_secure_file();
9822
9976
  init_thread_store();
9977
+
9978
+ // src/store/desktop-host.ts
9979
+ var import_node_fs10 = require("fs");
9980
+ var import_node_path10 = require("path");
9981
+ init_paths();
9982
+ function desktopHostPidPath() {
9983
+ return (0, import_node_path10.join)(appDataDir(), "desktop-host.pid");
9984
+ }
9985
+ function claimDesktopHost(pid = process.pid) {
9986
+ (0, import_node_fs10.writeFileSync)(desktopHostPidPath(), `${pid}
9987
+ `, "utf8");
9988
+ }
9989
+ function releaseDesktopHost(pid = process.pid) {
9990
+ if (readDesktopHostPid() !== pid) return;
9991
+ try {
9992
+ (0, import_node_fs10.unlinkSync)(desktopHostPidPath());
9993
+ } catch {
9994
+ }
9995
+ }
9996
+ function readDesktopHostPid() {
9997
+ try {
9998
+ const pid = Number.parseInt((0, import_node_fs10.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
9999
+ if (!Number.isFinite(pid) || pid <= 0) return null;
10000
+ return pid;
10001
+ } catch {
10002
+ return null;
10003
+ }
10004
+ }
10005
+ function pidAlive(pid) {
10006
+ try {
10007
+ process.kill(pid, 0);
10008
+ return true;
10009
+ } catch {
10010
+ return false;
10011
+ }
10012
+ }
10013
+ function isDesktopHostAlive() {
10014
+ const pid = readDesktopHostPid();
10015
+ return pid != null && pidAlive(pid);
10016
+ }
10017
+ function isThisProcessDesktopHost() {
10018
+ return readDesktopHostPid() === process.pid && pidAlive(process.pid);
10019
+ }
10020
+ function thisProcessShouldDrainAgentQueues() {
10021
+ if (isThisProcessDesktopHost()) return true;
10022
+ return !isDesktopHostAlive();
10023
+ }
10024
+
10025
+ // src/index.ts
9823
10026
  init_workspaces();
9824
10027
  init_global_workspace();
9825
10028
  init_run();
@@ -10979,8 +11182,8 @@ init_usage();
10979
11182
  init_claude_mcp();
10980
11183
 
10981
11184
  // src/agents/instructions.ts
10982
- var import_node_fs26 = require("fs");
10983
- var import_node_path24 = require("path");
11185
+ var import_node_fs27 = require("fs");
11186
+ var import_node_path25 = require("path");
10984
11187
  init_git_auth_mode();
10985
11188
  init_worktree_labels();
10986
11189
  function normPath3(p) {
@@ -11151,11 +11354,11 @@ function loadAgentInstructions(worktreePath, agent) {
11151
11354
  const out = [];
11152
11355
  for (const rel of candidates) {
11153
11356
  if (seenPaths.has(rel)) continue;
11154
- const abs = (0, import_node_path24.join)(worktreePath, rel);
11155
- if (!(0, import_node_fs26.existsSync)(abs)) continue;
11357
+ const abs = (0, import_node_path25.join)(worktreePath, rel);
11358
+ if (!(0, import_node_fs27.existsSync)(abs)) continue;
11156
11359
  try {
11157
- if (!(0, import_node_fs26.statSync)(abs).isFile()) continue;
11158
- let content = (0, import_node_fs26.readFileSync)(abs, "utf8");
11360
+ if (!(0, import_node_fs27.statSync)(abs).isFile()) continue;
11361
+ let content = (0, import_node_fs27.readFileSync)(abs, "utf8");
11159
11362
  if (!content.trim()) continue;
11160
11363
  if (content.length > MAX_CHARS_PER_FILE) {
11161
11364
  content = `${content.slice(0, MAX_CHARS_PER_FILE)}
@@ -11237,9 +11440,9 @@ async function requireAgent(agent, opts) {
11237
11440
  init_settings();
11238
11441
 
11239
11442
  // src/hook/conductor.ts
11240
- var import_node_fs27 = require("fs");
11443
+ var import_node_fs28 = require("fs");
11241
11444
  var import_node_net = require("net");
11242
- var import_node_path25 = require("path");
11445
+ var import_node_path26 = require("path");
11243
11446
  var import_execa4 = require("execa");
11244
11447
  var import_node_readline3 = require("readline");
11245
11448
  init_settings();
@@ -11254,9 +11457,9 @@ function matchSimpleGlob(pattern, name) {
11254
11457
  return new RegExp(`^${escaped}$`).test(name);
11255
11458
  }
11256
11459
  function readWorktreeInclude(repoPath) {
11257
- const path2 = (0, import_node_path25.join)(repoPath, ".worktreeinclude");
11258
- if (!(0, import_node_fs27.existsSync)(path2)) return [];
11259
- return (0, import_node_fs27.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
11460
+ const path2 = (0, import_node_path26.join)(repoPath, ".worktreeinclude");
11461
+ if (!(0, import_node_fs28.existsSync)(path2)) return [];
11462
+ return (0, import_node_fs28.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
11260
11463
  }
11261
11464
  function resolveFilesToCopy(repoPath) {
11262
11465
  const fromInclude = readWorktreeInclude(repoPath);
@@ -11266,10 +11469,10 @@ function resolveFilesToCopy(repoPath) {
11266
11469
  if (settings?.fileIncludeGlobs?.length) {
11267
11470
  const matched = [];
11268
11471
  try {
11269
- for (const entry of (0, import_node_fs27.readdirSync)(repoPath, { withFileTypes: true })) {
11472
+ for (const entry of (0, import_node_fs28.readdirSync)(repoPath, { withFileTypes: true })) {
11270
11473
  if (!entry.isFile()) continue;
11271
11474
  for (const glob of settings.fileIncludeGlobs) {
11272
- if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path25.basename)(glob), entry.name)) {
11475
+ if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path26.basename)(glob), entry.name)) {
11273
11476
  matched.push(entry.name);
11274
11477
  break;
11275
11478
  }
@@ -11281,7 +11484,7 @@ function resolveFilesToCopy(repoPath) {
11281
11484
  }
11282
11485
  const defaults = [];
11283
11486
  try {
11284
- for (const entry of (0, import_node_fs27.readdirSync)(repoPath, { withFileTypes: true })) {
11487
+ for (const entry of (0, import_node_fs28.readdirSync)(repoPath, { withFileTypes: true })) {
11285
11488
  if (entry.isFile() && entry.name.startsWith(".env")) {
11286
11489
  defaults.push(entry.name);
11287
11490
  }
@@ -11295,11 +11498,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
11295
11498
  const patterns = resolveFilesToCopy(repoPath);
11296
11499
  const copied = [];
11297
11500
  for (const rel of patterns) {
11298
- const src = (0, import_node_path25.join)(repoPath, rel);
11299
- if (!(0, import_node_fs27.existsSync)(src)) continue;
11300
- const dest = (0, import_node_path25.join)(worktreePath, rel);
11301
- (0, import_node_fs27.mkdirSync)((0, import_node_path25.dirname)(dest), { recursive: true });
11302
- (0, import_node_fs27.copyFileSync)(src, dest);
11501
+ const src = (0, import_node_path26.join)(repoPath, rel);
11502
+ if (!(0, import_node_fs28.existsSync)(src)) continue;
11503
+ const dest = (0, import_node_path26.join)(worktreePath, rel);
11504
+ (0, import_node_fs28.mkdirSync)((0, import_node_path26.dirname)(dest), { recursive: true });
11505
+ (0, import_node_fs28.copyFileSync)(src, dest);
11303
11506
  copied.push(rel);
11304
11507
  }
11305
11508
  return copied;
@@ -11335,7 +11538,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
11335
11538
  const env = stripNestedElectronEnv({
11336
11539
  ...baseEnv ?? process.env
11337
11540
  });
11338
- const name = opts.workspaceName ?? (0, import_node_path25.basename)(opts.worktreePath);
11541
+ const name = opts.workspaceName ?? (0, import_node_path26.basename)(opts.worktreePath);
11339
11542
  const ports = opts.ports ?? [];
11340
11543
  const primary = ports[0];
11341
11544
  env.SIDEBOARD_WORKSPACE_NAME = name;
@@ -11596,12 +11799,12 @@ init_convention_setup();
11596
11799
  init_cursor_worktrees();
11597
11800
 
11598
11801
  // src/diff/diff.ts
11599
- var import_node_fs28 = require("fs");
11600
- var import_node_path26 = require("path");
11802
+ var import_node_fs29 = require("fs");
11803
+ var import_node_path27 = require("path");
11601
11804
  init_run();
11602
11805
  init_worktree();
11603
11806
  async function inspectGitWorktree(worktreePath) {
11604
- if (!worktreePath || !(0, import_node_fs28.existsSync)(worktreePath)) return "missing_worktree";
11807
+ if (!worktreePath || !(0, import_node_fs29.existsSync)(worktreePath)) return "missing_worktree";
11605
11808
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
11606
11809
  reject: false
11607
11810
  });
@@ -11609,7 +11812,7 @@ async function inspectGitWorktree(worktreePath) {
11609
11812
  return "ok";
11610
11813
  }
11611
11814
  async function initializeGitRepository(worktreePath) {
11612
- if (!worktreePath || !(0, import_node_fs28.existsSync)(worktreePath)) {
11815
+ if (!worktreePath || !(0, import_node_fs29.existsSync)(worktreePath)) {
11613
11816
  throw new Error("Worktree not found");
11614
11817
  }
11615
11818
  const status = await inspectGitWorktree(worktreePath);
@@ -11745,11 +11948,11 @@ new file mode 100644
11745
11948
  };
11746
11949
  }
11747
11950
  async function untrackedPatch(worktreePath, path2, maxHunk) {
11748
- const abs = (0, import_node_path26.join)(worktreePath, path2);
11951
+ const abs = (0, import_node_path27.join)(worktreePath, path2);
11749
11952
  try {
11750
- const st = (0, import_node_fs28.statSync)(abs);
11953
+ const st = (0, import_node_fs29.statSync)(abs);
11751
11954
  if (st.isFile() && st.size > maxHunk) {
11752
- const buf = (0, import_node_fs28.readFileSync)(abs).subarray(0, maxHunk);
11955
+ const buf = (0, import_node_fs29.readFileSync)(abs).subarray(0, maxHunk);
11753
11956
  return syntheticAddPatch(path2, buf.toString("utf8"), maxHunk);
11754
11957
  }
11755
11958
  } catch {
@@ -12250,8 +12453,8 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
12250
12453
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
12251
12454
  assertSafeRelativePath(relativePath);
12252
12455
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
12253
- const abs = (0, import_node_path26.join)(worktreePath, relativePath);
12254
- const st = (0, import_node_fs28.statSync)(abs);
12456
+ const abs = (0, import_node_path27.join)(worktreePath, relativePath);
12457
+ const st = (0, import_node_fs29.statSync)(abs);
12255
12458
  if (!st.isFile()) {
12256
12459
  throw new Error(`Not a file: ${relativePath}`);
12257
12460
  }
@@ -12260,7 +12463,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
12260
12463
  `File too large to upload (${st.size} bytes; max ${maxBytes})`
12261
12464
  );
12262
12465
  }
12263
- const buf = (0, import_node_fs28.readFileSync)(abs);
12466
+ const buf = (0, import_node_fs29.readFileSync)(abs);
12264
12467
  return {
12265
12468
  path: relativePath,
12266
12469
  contentBase64: buf.toString("base64"),
@@ -12270,12 +12473,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
12270
12473
  function readWorktreeFile(worktreePath, relativePath, opts) {
12271
12474
  assertSafeRelativePath(relativePath);
12272
12475
  const maxBytes = opts?.maxBytes ?? 2e5;
12273
- const abs = (0, import_node_path26.join)(worktreePath, relativePath);
12274
- const st = (0, import_node_fs28.statSync)(abs);
12476
+ const abs = (0, import_node_path27.join)(worktreePath, relativePath);
12477
+ const st = (0, import_node_fs29.statSync)(abs);
12275
12478
  if (!st.isFile()) {
12276
12479
  throw new Error(`Not a file: ${relativePath}`);
12277
12480
  }
12278
- const buf = (0, import_node_fs28.readFileSync)(abs);
12481
+ const buf = (0, import_node_fs29.readFileSync)(abs);
12279
12482
  if (isImageRelativePath(relativePath)) {
12280
12483
  const maxImageBytes = Math.max(maxBytes, 15e6);
12281
12484
  const truncated2 = buf.length > maxImageBytes;
@@ -12318,9 +12521,9 @@ function assertSafeRelativePath(relativePath) {
12318
12521
  }
12319
12522
  function writeWorktreeFile(worktreePath, relativePath, content) {
12320
12523
  assertSafeRelativePath(relativePath);
12321
- const abs = (0, import_node_path26.join)(worktreePath, relativePath);
12322
- (0, import_node_fs28.mkdirSync)((0, import_node_path26.dirname)(abs), { recursive: true });
12323
- (0, import_node_fs28.writeFileSync)(abs, content, "utf8");
12524
+ const abs = (0, import_node_path27.join)(worktreePath, relativePath);
12525
+ (0, import_node_fs29.mkdirSync)((0, import_node_path27.dirname)(abs), { recursive: true });
12526
+ (0, import_node_fs29.writeFileSync)(abs, content, "utf8");
12324
12527
  return { path: relativePath };
12325
12528
  }
12326
12529
  async function getDiffSummary(worktreePath, repoPath, opts) {
@@ -12339,9 +12542,9 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
12339
12542
  }
12340
12543
 
12341
12544
  // src/skills/discover.ts
12342
- var import_node_fs29 = require("fs");
12545
+ var import_node_fs30 = require("fs");
12343
12546
  var import_node_os10 = require("os");
12344
- var import_node_path27 = require("path");
12547
+ var import_node_path28 = require("path");
12345
12548
  function toCommand(name) {
12346
12549
  return name.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
12347
12550
  }
@@ -12373,7 +12576,7 @@ function parseFrontmatter(content) {
12373
12576
  }
12374
12577
  function readSkill(skillMd, source) {
12375
12578
  try {
12376
- const content = (0, import_node_fs29.readFileSync)(skillMd, "utf8");
12579
+ const content = (0, import_node_fs30.readFileSync)(skillMd, "utf8");
12377
12580
  const { name: fmName, description } = parseFrontmatter(content);
12378
12581
  const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
12379
12582
  const name = fmName || dirName;
@@ -12392,19 +12595,19 @@ function readSkill(skillMd, source) {
12392
12595
  }
12393
12596
  }
12394
12597
  function scanSkillsDir(dir, source, out) {
12395
- if (!(0, import_node_fs29.existsSync)(dir)) return;
12598
+ if (!(0, import_node_fs30.existsSync)(dir)) return;
12396
12599
  let entries;
12397
12600
  try {
12398
- entries = (0, import_node_fs29.readdirSync)(dir);
12601
+ entries = (0, import_node_fs30.readdirSync)(dir);
12399
12602
  } catch {
12400
12603
  return;
12401
12604
  }
12402
12605
  for (const entry of entries) {
12403
12606
  if (entry.startsWith(".")) continue;
12404
- const skillMd = (0, import_node_path27.join)(dir, entry, "SKILL.md");
12405
- if (!(0, import_node_fs29.existsSync)(skillMd)) continue;
12607
+ const skillMd = (0, import_node_path28.join)(dir, entry, "SKILL.md");
12608
+ if (!(0, import_node_fs30.existsSync)(skillMd)) continue;
12406
12609
  try {
12407
- if (!(0, import_node_fs29.statSync)(skillMd).isFile()) continue;
12610
+ if (!(0, import_node_fs30.statSync)(skillMd).isFile()) continue;
12408
12611
  } catch {
12409
12612
  continue;
12410
12613
  }
@@ -12413,24 +12616,24 @@ function scanSkillsDir(dir, source, out) {
12413
12616
  }
12414
12617
  }
12415
12618
  function scanClaudePluginSkills(pluginsRoot, out) {
12416
- if (!(0, import_node_fs29.existsSync)(pluginsRoot)) return;
12619
+ if (!(0, import_node_fs30.existsSync)(pluginsRoot)) return;
12417
12620
  const walk = (dir, depth, lookingForSkillsDir) => {
12418
12621
  if (depth > 7) return;
12419
12622
  let entries;
12420
12623
  try {
12421
- entries = (0, import_node_fs29.readdirSync)(dir);
12624
+ entries = (0, import_node_fs30.readdirSync)(dir);
12422
12625
  } catch {
12423
12626
  return;
12424
12627
  }
12425
12628
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
12426
- const skill = readSkill((0, import_node_path27.join)(dir, "SKILL.md"), "cli");
12629
+ const skill = readSkill((0, import_node_path28.join)(dir, "SKILL.md"), "cli");
12427
12630
  if (skill) out.push(skill);
12428
12631
  }
12429
12632
  for (const entry of entries) {
12430
12633
  if (entry === "node_modules" || entry === ".git") continue;
12431
- const full = (0, import_node_path27.join)(dir, entry);
12634
+ const full = (0, import_node_path28.join)(dir, entry);
12432
12635
  try {
12433
- if (!(0, import_node_fs29.statSync)(full).isDirectory()) continue;
12636
+ if (!(0, import_node_fs30.statSync)(full).isDirectory()) continue;
12434
12637
  } catch {
12435
12638
  continue;
12436
12639
  }
@@ -12448,17 +12651,17 @@ function discoverSkills(worktreePath) {
12448
12651
  const home = (0, import_node_os10.homedir)();
12449
12652
  const collected = [];
12450
12653
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
12451
- scanSkillsDir((0, import_node_path27.join)(worktreePath, rel), "workspace", collected);
12654
+ scanSkillsDir((0, import_node_path28.join)(worktreePath, rel), "workspace", collected);
12452
12655
  }
12453
12656
  for (const abs of [
12454
- (0, import_node_path27.join)(home, ".claude/skills"),
12455
- (0, import_node_path27.join)(home, ".cursor/skills"),
12456
- (0, import_node_path27.join)(home, ".sideboard/skills"),
12457
- (0, import_node_path27.join)(home, ".brightsy/skills")
12657
+ (0, import_node_path28.join)(home, ".claude/skills"),
12658
+ (0, import_node_path28.join)(home, ".cursor/skills"),
12659
+ (0, import_node_path28.join)(home, ".sideboard/skills"),
12660
+ (0, import_node_path28.join)(home, ".brightsy/skills")
12458
12661
  ]) {
12459
12662
  scanSkillsDir(abs, "user", collected);
12460
12663
  }
12461
- scanClaudePluginSkills((0, import_node_path27.join)(home, ".claude/plugins"), collected);
12664
+ scanClaudePluginSkills((0, import_node_path28.join)(home, ".claude/plugins"), collected);
12462
12665
  const rank = { workspace: 0, user: 1, cli: 2 };
12463
12666
  const byCommand = /* @__PURE__ */ new Map();
12464
12667
  for (const skill of collected) {
@@ -12470,7 +12673,7 @@ function discoverSkills(worktreePath) {
12470
12673
  return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
12471
12674
  }
12472
12675
  function readSkillBody(skillPath, maxChars = 12e3) {
12473
- const raw = (0, import_node_fs29.readFileSync)(skillPath, "utf8");
12676
+ const raw = (0, import_node_fs30.readFileSync)(skillPath, "utf8");
12474
12677
  if (raw.startsWith("---")) {
12475
12678
  const end = raw.indexOf("\n---", 3);
12476
12679
  if (end >= 0) {
@@ -12611,8 +12814,8 @@ function buildDiffCommentAttachment(input) {
12611
12814
  }
12612
12815
 
12613
12816
  // src/composer/stage-files.ts
12614
- var import_node_fs30 = require("fs");
12615
- var import_node_path28 = require("path");
12817
+ var import_node_fs31 = require("fs");
12818
+ var import_node_path29 = require("path");
12616
12819
  var import_node_crypto5 = require("crypto");
12617
12820
  init_workspace_scratch();
12618
12821
  var IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
@@ -12638,7 +12841,7 @@ var IMAGE_MIME_BY_EXT = {
12638
12841
  var MAX_INLINE_BYTES = 4e5;
12639
12842
  var MAX_PREVIEW_BYTES = 5e6;
12640
12843
  function fileExtension(filePath) {
12641
- const base = (0, import_node_path28.basename)(filePath).toLowerCase();
12844
+ const base = (0, import_node_path29.basename)(filePath).toLowerCase();
12642
12845
  return base.includes(".") ? base.split(".").pop() || "" : "";
12643
12846
  }
12644
12847
  function isImageFilePath(filePath) {
@@ -12648,22 +12851,22 @@ function imageMimeType(filePath) {
12648
12851
  return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
12649
12852
  }
12650
12853
  function ensureAttachmentsDir(worktreePath) {
12651
- const dir = (0, import_node_path28.join)(worktreePath, ATTACHMENTS_DIR);
12652
- (0, import_node_fs30.mkdirSync)(dir, { recursive: true });
12653
- const gi = (0, import_node_path28.join)(dir, ".gitignore");
12654
- if (!(0, import_node_fs30.existsSync)(gi)) {
12655
- (0, import_node_fs30.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
12854
+ const dir = (0, import_node_path29.join)(worktreePath, ATTACHMENTS_DIR);
12855
+ (0, import_node_fs31.mkdirSync)(dir, { recursive: true });
12856
+ const gi = (0, import_node_path29.join)(dir, ".gitignore");
12857
+ if (!(0, import_node_fs31.existsSync)(gi)) {
12858
+ (0, import_node_fs31.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
12656
12859
  }
12657
12860
  return dir;
12658
12861
  }
12659
12862
  function uniqueAttachmentName(dir, originalName) {
12660
12863
  const safe = originalName.replace(/[/\\]/g, "_") || "file";
12661
- if (!(0, import_node_fs30.existsSync)((0, import_node_path28.join)(dir, safe))) return safe;
12662
- const ext = (0, import_node_path28.extname)(safe);
12864
+ if (!(0, import_node_fs31.existsSync)((0, import_node_path29.join)(dir, safe))) return safe;
12865
+ const ext = (0, import_node_path29.extname)(safe);
12663
12866
  const stem = ext ? safe.slice(0, -ext.length) : safe;
12664
12867
  for (let i = 1; i < 1e4; i++) {
12665
12868
  const candidate = `${stem}-${i}${ext}`;
12666
- if (!(0, import_node_fs30.existsSync)((0, import_node_path28.join)(dir, candidate))) return candidate;
12869
+ if (!(0, import_node_fs31.existsSync)((0, import_node_path29.join)(dir, candidate))) return candidate;
12667
12870
  }
12668
12871
  return `${stem}-${(0, import_node_crypto5.randomUUID)()}${ext}`;
12669
12872
  }
@@ -12715,9 +12918,9 @@ function attachmentFromBuffer(name, buf, opts) {
12715
12918
  };
12716
12919
  }
12717
12920
  function attachmentFromAbsolutePath(absolutePath) {
12718
- const name = (0, import_node_path28.basename)(absolutePath);
12921
+ const name = (0, import_node_path29.basename)(absolutePath);
12719
12922
  try {
12720
- const st = (0, import_node_fs30.statSync)(absolutePath);
12923
+ const st = (0, import_node_fs31.statSync)(absolutePath);
12721
12924
  if (!st.isFile()) {
12722
12925
  return {
12723
12926
  id: (0, import_node_crypto5.randomUUID)(),
@@ -12726,7 +12929,7 @@ function attachmentFromAbsolutePath(absolutePath) {
12726
12929
  content: `(not a file: ${absolutePath})`
12727
12930
  };
12728
12931
  }
12729
- const buf = (0, import_node_fs30.readFileSync)(absolutePath);
12932
+ const buf = (0, import_node_fs31.readFileSync)(absolutePath);
12730
12933
  return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
12731
12934
  } catch (err) {
12732
12935
  return {
@@ -12742,15 +12945,15 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
12742
12945
  const dir = ensureAttachmentsDir(worktreePath);
12743
12946
  const out = [];
12744
12947
  for (const abs of absolutePaths) {
12745
- const originalName = (0, import_node_path28.basename)(abs);
12948
+ const originalName = (0, import_node_path29.basename)(abs);
12746
12949
  try {
12747
- const st = (0, import_node_fs30.statSync)(abs);
12950
+ const st = (0, import_node_fs31.statSync)(abs);
12748
12951
  if (!st.isFile()) continue;
12749
12952
  const name = uniqueAttachmentName(dir, originalName);
12750
- const destAbs = (0, import_node_path28.join)(dir, name);
12751
- (0, import_node_fs30.copyFileSync)(abs, destAbs);
12953
+ const destAbs = (0, import_node_path29.join)(dir, name);
12954
+ (0, import_node_fs31.copyFileSync)(abs, destAbs);
12752
12955
  const rel = `${ATTACHMENTS_DIR}/${name}`;
12753
- const buf = (0, import_node_fs30.readFileSync)(destAbs);
12956
+ const buf = (0, import_node_fs31.readFileSync)(destAbs);
12754
12957
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
12755
12958
  } catch (err) {
12756
12959
  out.push({
@@ -12772,8 +12975,8 @@ function stageBuffersAsAttachments(worktreePath, buffers) {
12772
12975
  try {
12773
12976
  const buf = Buffer.from(item.dataBase64, "base64");
12774
12977
  const name = uniqueAttachmentName(dir, originalName);
12775
- const destAbs = (0, import_node_path28.join)(dir, name);
12776
- (0, import_node_fs30.writeFileSync)(destAbs, buf);
12978
+ const destAbs = (0, import_node_path29.join)(dir, name);
12979
+ (0, import_node_fs31.writeFileSync)(destAbs, buf);
12777
12980
  const rel = `${ATTACHMENTS_DIR}/${name}`;
12778
12981
  out.push(attachmentFromBuffer(name, buf, { path: rel }));
12779
12982
  } catch (err) {
@@ -12809,18 +13012,18 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
12809
13012
  if (!rel || rel.includes("..") || rel.startsWith("/")) {
12810
13013
  out.push({
12811
13014
  id: (0, import_node_crypto5.randomUUID)(),
12812
- name: (0, import_node_path28.basename)(rel) || "file",
13015
+ name: (0, import_node_path29.basename)(rel) || "file",
12813
13016
  kind: "file",
12814
13017
  content: `(invalid path: ${rel})`
12815
13018
  });
12816
13019
  continue;
12817
13020
  }
12818
- const name = (0, import_node_path28.basename)(rel);
13021
+ const name = (0, import_node_path29.basename)(rel);
12819
13022
  try {
12820
- const abs = (0, import_node_path28.join)(worktreePath, rel);
12821
- const st = (0, import_node_fs30.statSync)(abs);
13023
+ const abs = (0, import_node_path29.join)(worktreePath, rel);
13024
+ const st = (0, import_node_fs31.statSync)(abs);
12822
13025
  if (!st.isFile()) continue;
12823
- const buf = (0, import_node_fs30.readFileSync)(abs);
13026
+ const buf = (0, import_node_fs31.readFileSync)(abs);
12824
13027
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
12825
13028
  } catch (err) {
12826
13029
  out.push({
@@ -13308,7 +13511,7 @@ async function confirmLand(thread, opts) {
13308
13511
  }
13309
13512
 
13310
13513
  // src/threads/create.ts
13311
- var import_node_fs31 = require("fs");
13514
+ var import_node_fs32 = require("fs");
13312
13515
  init_worktree();
13313
13516
  init_app_settings();
13314
13517
  init_thread_store();
@@ -13322,7 +13525,7 @@ async function createThread(input, _onSetupLine) {
13322
13525
  });
13323
13526
  await requireAgent(resolved.agent);
13324
13527
  const repoPath = await resolveRepoRoot(input.repoPath);
13325
- if (!(0, import_node_fs31.existsSync)(repoPath)) {
13528
+ if (!(0, import_node_fs32.existsSync)(repoPath)) {
13326
13529
  throw new Error(`Repo not found: ${repoPath}`);
13327
13530
  }
13328
13531
  let sourceRef = input.sourceRef;
@@ -13562,7 +13765,7 @@ async function forkThreadWorktree(input, onSetupLine) {
13562
13765
  }
13563
13766
 
13564
13767
  // src/threads/stack-layers.ts
13565
- var import_node_fs32 = require("fs");
13768
+ var import_node_fs33 = require("fs");
13566
13769
  init_run();
13567
13770
  init_stack();
13568
13771
  init_worktree();
@@ -13630,7 +13833,7 @@ async function openStackLayer(input, _onSetupLine) {
13630
13833
  let createdWorktree = false;
13631
13834
  const trees = await listWorktrees(repoPath);
13632
13835
  const checkedOut = trees.find((w) => w.branch === branchName);
13633
- if (checkedOut?.path && (0, import_node_fs32.existsSync)(checkedOut.path)) {
13836
+ if (checkedOut?.path && (0, import_node_fs33.existsSync)(checkedOut.path)) {
13634
13837
  if (input.reuseExistingWorktree !== false) {
13635
13838
  worktreePath = checkedOut.path;
13636
13839
  } else {
@@ -13772,7 +13975,7 @@ async function initStackFromThread(input, onSetupLine) {
13772
13975
  async function createPrStack(input, onSetupLine) {
13773
13976
  await requireAgent(input.agent);
13774
13977
  const repoPath = await resolveRepoRoot(input.repoPath);
13775
- if (!(0, import_node_fs32.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
13978
+ if (!(0, import_node_fs33.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
13776
13979
  if (!input.branches.length) throw new Error("At least one branch name required");
13777
13980
  const status = await detectGhStack(repoPath);
13778
13981
  if (!status.available) throw new Error(status.reason);
@@ -13839,7 +14042,7 @@ async function createPrStack(input, onSetupLine) {
13839
14042
  }
13840
14043
  }
13841
14044
  const claimed = new Set(threads.map((t) => t.worktreePath));
13842
- if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs32.existsSync)(bootstrap.worktreePath)) {
14045
+ if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs33.existsSync)(bootstrap.worktreePath)) {
13843
14046
  try {
13844
14047
  await removeWorktree(repoPath, bootstrap.worktreePath, {
13845
14048
  deleteBranch: bootstrap.branchName
@@ -13862,21 +14065,21 @@ function stackAgentDefaultsFrom(input) {
13862
14065
 
13863
14066
  // src/threads/adopt.ts
13864
14067
  var import_node_child_process4 = require("child_process");
13865
- var import_node_fs33 = require("fs");
14068
+ var import_node_fs34 = require("fs");
13866
14069
  var import_node_os11 = require("os");
13867
- var import_node_path29 = require("path");
14070
+ var import_node_path30 = require("path");
13868
14071
  var import_node_module4 = require("module");
13869
14072
  init_worktree();
13870
14073
  init_thread_store();
13871
14074
  var import_meta4 = {};
13872
- var CONDUCTOR_APP_SUPPORT = (0, import_node_path29.join)(
14075
+ var CONDUCTOR_APP_SUPPORT = (0, import_node_path30.join)(
13873
14076
  process.env.HOME ?? "",
13874
14077
  "Library",
13875
14078
  "Application Support",
13876
14079
  "com.conductor.app"
13877
14080
  );
13878
- var CONDUCTOR_DB = (0, import_node_path29.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
13879
- var CURSOR_SDK_STORE = (0, import_node_path29.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
14081
+ var CONDUCTOR_DB = (0, import_node_path30.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
14082
+ var CURSOR_SDK_STORE = (0, import_node_path30.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
13880
14083
  function openReadonlySqlite(file) {
13881
14084
  const req = (0, import_node_module4.createRequire)(import_meta4.url);
13882
14085
  const Database = req("better-sqlite3");
@@ -13893,21 +14096,21 @@ function mapAgentType(raw) {
13893
14096
  return null;
13894
14097
  }
13895
14098
  function resolveConductorCursorAgentId(workspacePath) {
13896
- if (!workspacePath || !(0, import_node_fs33.existsSync)(CURSOR_SDK_STORE)) return null;
14099
+ if (!workspacePath || !(0, import_node_fs34.existsSync)(CURSOR_SDK_STORE)) return null;
13897
14100
  const normalized = workspacePath.replace(/\/$/, "");
13898
14101
  let best = null;
13899
14102
  let hashes;
13900
14103
  try {
13901
- hashes = (0, import_node_fs33.readdirSync)(CURSOR_SDK_STORE);
14104
+ hashes = (0, import_node_fs34.readdirSync)(CURSOR_SDK_STORE);
13902
14105
  } catch {
13903
14106
  return null;
13904
14107
  }
13905
14108
  for (const hash of hashes) {
13906
- const agentsFile = (0, import_node_path29.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
13907
- if (!(0, import_node_fs33.existsSync)(agentsFile)) continue;
14109
+ const agentsFile = (0, import_node_path30.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
14110
+ if (!(0, import_node_fs34.existsSync)(agentsFile)) continue;
13908
14111
  let text3;
13909
14112
  try {
13910
- text3 = (0, import_node_fs33.readFileSync)(agentsFile, "utf8");
14113
+ text3 = (0, import_node_fs34.readFileSync)(agentsFile, "utf8");
13911
14114
  } catch {
13912
14115
  continue;
13913
14116
  }
@@ -13931,7 +14134,7 @@ function resolveConductorCursorAgentId(workspacePath) {
13931
14134
  return best?.agentId ?? null;
13932
14135
  }
13933
14136
  async function adoptThread(input) {
13934
- if (!(0, import_node_fs33.existsSync)(input.worktreePath)) {
14137
+ if (!(0, import_node_fs34.existsSync)(input.worktreePath)) {
13935
14138
  throw new Error(`Worktree not found: ${input.worktreePath}`);
13936
14139
  }
13937
14140
  const repoPath = await resolveRepoRoot(input.worktreePath);
@@ -13958,18 +14161,18 @@ function conductorDbPath() {
13958
14161
  return CONDUCTOR_DB;
13959
14162
  }
13960
14163
  function listConductorWorkspaces() {
13961
- if (!(0, import_node_fs33.existsSync)(CONDUCTOR_DB)) {
14164
+ if (!(0, import_node_fs34.existsSync)(CONDUCTOR_DB)) {
13962
14165
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
13963
14166
  }
13964
- const tmp = (0, import_node_fs33.mkdtempSync)((0, import_node_path29.join)((0, import_node_os11.tmpdir)(), "sideboard-conductor-"));
13965
- const snapshot = (0, import_node_path29.join)(tmp, "conductor.db");
14167
+ const tmp = (0, import_node_fs34.mkdtempSync)((0, import_node_path30.join)((0, import_node_os11.tmpdir)(), "sideboard-conductor-"));
14168
+ const snapshot = (0, import_node_path30.join)(tmp, "conductor.db");
13966
14169
  try {
13967
- (0, import_node_fs33.copyFileSync)(CONDUCTOR_DB, snapshot);
14170
+ (0, import_node_fs34.copyFileSync)(CONDUCTOR_DB, snapshot);
13968
14171
  for (const suffix of ["-wal", "-shm"]) {
13969
14172
  const src = `${CONDUCTOR_DB}${suffix}`;
13970
- if ((0, import_node_fs33.existsSync)(src)) {
14173
+ if ((0, import_node_fs34.existsSync)(src)) {
13971
14174
  try {
13972
- (0, import_node_fs33.copyFileSync)(src, `${snapshot}${suffix}`);
14175
+ (0, import_node_fs34.copyFileSync)(src, `${snapshot}${suffix}`);
13973
14176
  } catch {
13974
14177
  }
13975
14178
  }
@@ -14045,22 +14248,22 @@ function listConductorWorkspaces() {
14045
14248
  db.close();
14046
14249
  }
14047
14250
  } finally {
14048
- (0, import_node_fs33.rmSync)(tmp, { recursive: true, force: true });
14251
+ (0, import_node_fs34.rmSync)(tmp, { recursive: true, force: true });
14049
14252
  }
14050
14253
  }
14051
14254
  function importConductorWorkspace(workspaceId) {
14052
- if (!(0, import_node_fs33.existsSync)(CONDUCTOR_DB)) {
14255
+ if (!(0, import_node_fs34.existsSync)(CONDUCTOR_DB)) {
14053
14256
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
14054
14257
  }
14055
- const tmp = (0, import_node_fs33.mkdtempSync)((0, import_node_path29.join)((0, import_node_os11.tmpdir)(), "sideboard-conductor-"));
14056
- const snapshot = (0, import_node_path29.join)(tmp, "conductor.db");
14258
+ const tmp = (0, import_node_fs34.mkdtempSync)((0, import_node_path30.join)((0, import_node_os11.tmpdir)(), "sideboard-conductor-"));
14259
+ const snapshot = (0, import_node_path30.join)(tmp, "conductor.db");
14057
14260
  try {
14058
- (0, import_node_fs33.copyFileSync)(CONDUCTOR_DB, snapshot);
14261
+ (0, import_node_fs34.copyFileSync)(CONDUCTOR_DB, snapshot);
14059
14262
  for (const suffix of ["-wal", "-shm"]) {
14060
14263
  const src = `${CONDUCTOR_DB}${suffix}`;
14061
- if ((0, import_node_fs33.existsSync)(src)) {
14264
+ if ((0, import_node_fs34.existsSync)(src)) {
14062
14265
  try {
14063
- (0, import_node_fs33.copyFileSync)(src, `${snapshot}${suffix}`);
14266
+ (0, import_node_fs34.copyFileSync)(src, `${snapshot}${suffix}`);
14064
14267
  } catch {
14065
14268
  }
14066
14269
  }
@@ -14078,7 +14281,7 @@ function importConductorWorkspace(workspaceId) {
14078
14281
  ).get(workspaceId);
14079
14282
  if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
14080
14283
  const worktreePath = String(row.workspacePath);
14081
- if (!(0, import_node_fs33.existsSync)(worktreePath)) {
14284
+ if (!(0, import_node_fs34.existsSync)(worktreePath)) {
14082
14285
  throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
14083
14286
  }
14084
14287
  let sessionId = null;
@@ -14141,7 +14344,7 @@ function importConductorWorkspace(workspaceId) {
14141
14344
  db.close();
14142
14345
  }
14143
14346
  } finally {
14144
- (0, import_node_fs33.rmSync)(tmp, { recursive: true, force: true });
14347
+ (0, import_node_fs34.rmSync)(tmp, { recursive: true, force: true });
14145
14348
  }
14146
14349
  }
14147
14350
  async function importConductorWorkspaceAsync(workspaceId) {
@@ -14152,8 +14355,8 @@ async function importConductorWorkspaceAsync(workspaceId) {
14152
14355
  var import_node_events = require("events");
14153
14356
 
14154
14357
  // src/slack/outbound-watch.ts
14155
- var import_node_fs35 = require("fs");
14156
- var import_node_path32 = require("path");
14358
+ var import_node_fs36 = require("fs");
14359
+ var import_node_path33 = require("path");
14157
14360
  init_paths();
14158
14361
  init_private_file();
14159
14362
  init_secure_file();
@@ -14199,19 +14402,19 @@ async function slackAuthTest(token) {
14199
14402
  }
14200
14403
 
14201
14404
  // src/slack/reply-target.ts
14202
- var import_node_fs34 = require("fs");
14203
- var import_node_path30 = require("path");
14405
+ var import_node_fs35 = require("fs");
14406
+ var import_node_path31 = require("path");
14204
14407
  init_paths();
14205
14408
  init_private_file();
14206
14409
  init_secure_file();
14207
14410
  function storePath2() {
14208
- return (0, import_node_path30.join)(appDataDir(), "slack-reply-to.json");
14411
+ return (0, import_node_path31.join)(appDataDir(), "slack-reply-to.json");
14209
14412
  }
14210
14413
  function readStore2() {
14211
14414
  const path2 = storePath2();
14212
- if (!(0, import_node_fs34.existsSync)(path2)) return {};
14415
+ if (!(0, import_node_fs35.existsSync)(path2)) return {};
14213
14416
  try {
14214
- const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs34.readFileSync)(path2, "utf8"));
14417
+ const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs35.readFileSync)(path2, "utf8"));
14215
14418
  return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
14216
14419
  } catch {
14217
14420
  return {};
@@ -14228,11 +14431,11 @@ function getSlackReplyTarget(threadId) {
14228
14431
  }
14229
14432
 
14230
14433
  // src/slack/workspaces.ts
14231
- var import_node_path31 = require("path");
14434
+ var import_node_path32 = require("path");
14232
14435
  init_paths();
14233
14436
  init_secure_file();
14234
14437
  function storePath3() {
14235
- return (0, import_node_path31.join)(appDataDir(), "slack-workspaces.json");
14438
+ return (0, import_node_path32.join)(appDataDir(), "slack-workspaces.json");
14236
14439
  }
14237
14440
  function readStore3() {
14238
14441
  try {
@@ -14348,7 +14551,7 @@ var POLL_INTERVAL_MS = 12e3;
14348
14551
  var lastPollMs = 0;
14349
14552
  var nameCache = /* @__PURE__ */ new Map();
14350
14553
  function storePath4() {
14351
- return (0, import_node_path32.join)(appDataDir(), "slack-outbound-watch.json");
14554
+ return (0, import_node_path33.join)(appDataDir(), "slack-outbound-watch.json");
14352
14555
  }
14353
14556
  function watchId(teamId, channelId, ts) {
14354
14557
  return `${teamId}:${channelId}:${ts}`;
@@ -14378,9 +14581,9 @@ function tsNewer(a, b) {
14378
14581
  }
14379
14582
  function readStore4() {
14380
14583
  const path2 = storePath4();
14381
- if (!(0, import_node_fs35.existsSync)(path2)) return [];
14584
+ if (!(0, import_node_fs36.existsSync)(path2)) return [];
14382
14585
  try {
14383
- const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs35.readFileSync)(path2, "utf8"));
14586
+ const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs36.readFileSync)(path2, "utf8"));
14384
14587
  return Array.isArray(parsed?.watches) ? parsed.watches : [];
14385
14588
  } catch {
14386
14589
  return [];
@@ -14725,7 +14928,7 @@ async function refreshSlackReplyBadges(opts) {
14725
14928
  }
14726
14929
 
14727
14930
  // src/orchestrator/orchestrator.ts
14728
- var import_node_fs41 = require("fs");
14931
+ var import_node_fs42 = require("fs");
14729
14932
  init_error_detail();
14730
14933
  init_agents();
14731
14934
  init_worktree();
@@ -14746,8 +14949,8 @@ function shouldAutoArchiveOnPrMerge(opts) {
14746
14949
  }
14747
14950
 
14748
14951
  // src/git/orphan-cleanup.ts
14749
- var import_node_fs36 = require("fs");
14750
- var import_node_path33 = require("path");
14952
+ var import_node_fs37 = require("fs");
14953
+ var import_node_path34 = require("path");
14751
14954
  init_worktree();
14752
14955
  init_thread_store();
14753
14956
  init_paths();
@@ -14762,9 +14965,9 @@ async function findOrphanWorktrees(repoPaths) {
14762
14965
  repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
14763
14966
  );
14764
14967
  const homeRoot = sideboardWorkspacesDir();
14765
- if ((0, import_node_fs36.existsSync)(homeRoot)) {
14968
+ if ((0, import_node_fs37.existsSync)(homeRoot)) {
14766
14969
  try {
14767
- for (const entry of (0, import_node_fs36.readdirSync)(homeRoot, { withFileTypes: true })) {
14970
+ for (const entry of (0, import_node_fs37.readdirSync)(homeRoot, { withFileTypes: true })) {
14768
14971
  if (!entry.isDirectory()) continue;
14769
14972
  void entry;
14770
14973
  }
@@ -14774,7 +14977,7 @@ async function findOrphanWorktrees(repoPaths) {
14774
14977
  const orphans = [];
14775
14978
  const seen = /* @__PURE__ */ new Set();
14776
14979
  for (const repoPath of repos) {
14777
- if (!repoPath || !(0, import_node_fs36.existsSync)(repoPath)) continue;
14980
+ if (!repoPath || !(0, import_node_fs37.existsSync)(repoPath)) continue;
14778
14981
  try {
14779
14982
  const wts = await listWorktrees(repoPath);
14780
14983
  for (const wt of wts) {
@@ -14785,7 +14988,7 @@ async function findOrphanWorktrees(repoPaths) {
14785
14988
  seen.add(path2);
14786
14989
  let mtimeMs = 0;
14787
14990
  try {
14788
- mtimeMs = (0, import_node_fs36.statSync)(path2).mtimeMs;
14991
+ mtimeMs = (0, import_node_fs37.statSync)(path2).mtimeMs;
14789
14992
  } catch {
14790
14993
  mtimeMs = 0;
14791
14994
  }
@@ -14795,16 +14998,16 @@ async function findOrphanWorktrees(repoPaths) {
14795
14998
  }
14796
14999
  try {
14797
15000
  const root = worktreesRoot(repoPath);
14798
- if ((0, import_node_fs36.existsSync)(root)) {
14799
- for (const entry of (0, import_node_fs36.readdirSync)(root, { withFileTypes: true })) {
15001
+ if ((0, import_node_fs37.existsSync)(root)) {
15002
+ for (const entry of (0, import_node_fs37.readdirSync)(root, { withFileTypes: true })) {
14800
15003
  if (!entry.isDirectory()) continue;
14801
- const path2 = (0, import_node_path33.join)(root, entry.name).replace(/\/$/, "");
15004
+ const path2 = (0, import_node_path34.join)(root, entry.name).replace(/\/$/, "");
14802
15005
  if (known.has(path2) || seen.has(path2)) continue;
14803
- if (!(0, import_node_fs36.existsSync)((0, import_node_path33.join)(path2, ".git"))) continue;
15006
+ if (!(0, import_node_fs37.existsSync)((0, import_node_path34.join)(path2, ".git"))) continue;
14804
15007
  seen.add(path2);
14805
15008
  let mtimeMs = 0;
14806
15009
  try {
14807
- mtimeMs = (0, import_node_fs36.statSync)(path2).mtimeMs;
15010
+ mtimeMs = (0, import_node_fs37.statSync)(path2).mtimeMs;
14808
15011
  } catch {
14809
15012
  mtimeMs = Date.now();
14810
15013
  }
@@ -14950,8 +15153,8 @@ async function applyThreadIntoMain(thread, opts) {
14950
15153
  }
14951
15154
 
14952
15155
  // src/git/clone-repo.ts
14953
- var import_node_fs37 = require("fs");
14954
- var import_node_path34 = require("path");
15156
+ var import_node_fs38 = require("fs");
15157
+ var import_node_path35 = require("path");
14955
15158
  var import_execa6 = require("execa");
14956
15159
  init_paths();
14957
15160
  init_workspaces();
@@ -14961,12 +15164,12 @@ async function cloneRepoIntoSideboard(opts) {
14961
15164
  if (!url) throw new Error("Clone URL is required");
14962
15165
  let name = opts.name?.trim();
14963
15166
  if (!name) {
14964
- const leaf = (0, import_node_path34.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
15167
+ const leaf = (0, import_node_path35.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
14965
15168
  name = leaf || "repo";
14966
15169
  }
14967
15170
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
14968
- const dest = (0, import_node_path34.join)(sideboardReposDir(), name);
14969
- if ((0, import_node_fs37.existsSync)(dest)) {
15171
+ const dest = (0, import_node_path35.join)(sideboardReposDir(), name);
15172
+ if ((0, import_node_fs38.existsSync)(dest)) {
14970
15173
  const repoPath2 = await resolveRepoRoot(dest);
14971
15174
  const workspace2 = await ensureWorkspace(repoPath2);
14972
15175
  return { repoPath: repoPath2, workspace: workspace2 };
@@ -14988,8 +15191,8 @@ init_orchestrator_capable();
14988
15191
 
14989
15192
  // src/review/request-review.ts
14990
15193
  var import_node_crypto8 = require("crypto");
14991
- var import_node_fs38 = require("fs");
14992
- var import_node_path35 = require("path");
15194
+ var import_node_fs39 = require("fs");
15195
+ var import_node_path36 = require("path");
14993
15196
  init_global_workspace();
14994
15197
  init_thread_store();
14995
15198
 
@@ -15137,22 +15340,22 @@ function shouldRefreshReviewRequestTemplate(content) {
15137
15340
  return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
15138
15341
  }
15139
15342
  function readTextIfPresent(abs) {
15140
- if (!(0, import_node_fs38.existsSync)(abs)) return null;
15343
+ if (!(0, import_node_fs39.existsSync)(abs)) return null;
15141
15344
  try {
15142
- const content = (0, import_node_fs38.readFileSync)(abs, "utf8");
15345
+ const content = (0, import_node_fs39.readFileSync)(abs, "utf8");
15143
15346
  return content.trim() ? content : null;
15144
15347
  } catch {
15145
15348
  return null;
15146
15349
  }
15147
15350
  }
15148
15351
  function ensureAttachmentsGitignore(worktreePath) {
15149
- const gitignoreAbs = (0, import_node_path35.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
15150
- if ((0, import_node_fs38.existsSync)(gitignoreAbs)) return;
15151
- (0, import_node_fs38.mkdirSync)((0, import_node_path35.dirname)(gitignoreAbs), { recursive: true });
15152
- (0, import_node_fs38.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
15352
+ const gitignoreAbs = (0, import_node_path36.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
15353
+ if ((0, import_node_fs39.existsSync)(gitignoreAbs)) return;
15354
+ (0, import_node_fs39.mkdirSync)((0, import_node_path36.dirname)(gitignoreAbs), { recursive: true });
15355
+ (0, import_node_fs39.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
15153
15356
  }
15154
15357
  function resolveReviewGuidelines(worktreePath) {
15155
- const repoAbs = (0, import_node_path35.join)(worktreePath, REPO_REVIEW_PATH);
15358
+ const repoAbs = (0, import_node_path36.join)(worktreePath, REPO_REVIEW_PATH);
15156
15359
  const repoContent = readTextIfPresent(repoAbs);
15157
15360
  if (repoContent) {
15158
15361
  return {
@@ -15162,7 +15365,7 @@ function resolveReviewGuidelines(worktreePath) {
15162
15365
  source: "repo"
15163
15366
  };
15164
15367
  }
15165
- const localAbs = (0, import_node_path35.join)(worktreePath, REVIEW_REQUEST_PATH);
15368
+ const localAbs = (0, import_node_path36.join)(worktreePath, REVIEW_REQUEST_PATH);
15166
15369
  const localContent = readTextIfPresent(localAbs);
15167
15370
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
15168
15371
  return {
@@ -15172,7 +15375,7 @@ function resolveReviewGuidelines(worktreePath) {
15172
15375
  source: "local"
15173
15376
  };
15174
15377
  }
15175
- const legacyAbs = (0, import_node_path35.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
15378
+ const legacyAbs = (0, import_node_path36.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
15176
15379
  const legacyContent = readTextIfPresent(legacyAbs);
15177
15380
  if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
15178
15381
  return {
@@ -15183,8 +15386,8 @@ function resolveReviewGuidelines(worktreePath) {
15183
15386
  };
15184
15387
  }
15185
15388
  ensureAttachmentsGitignore(worktreePath);
15186
- (0, import_node_fs38.mkdirSync)((0, import_node_path35.dirname)(localAbs), { recursive: true });
15187
- (0, import_node_fs38.writeFileSync)(localAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
15389
+ (0, import_node_fs39.mkdirSync)((0, import_node_path36.dirname)(localAbs), { recursive: true });
15390
+ (0, import_node_fs39.writeFileSync)(localAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
15188
15391
  return {
15189
15392
  path: REVIEW_REQUEST_PATH,
15190
15393
  name: REVIEW_REQUEST_NAME,
@@ -15193,7 +15396,7 @@ function resolveReviewGuidelines(worktreePath) {
15193
15396
  };
15194
15397
  }
15195
15398
  function ensureReviewRequestFile(worktreePath) {
15196
- const repoAbs = (0, import_node_path35.join)(worktreePath, REPO_REVIEW_PATH);
15399
+ const repoAbs = (0, import_node_path36.join)(worktreePath, REPO_REVIEW_PATH);
15197
15400
  const repoContent = readTextIfPresent(repoAbs);
15198
15401
  if (repoContent) {
15199
15402
  return {
@@ -15203,10 +15406,10 @@ function ensureReviewRequestFile(worktreePath) {
15203
15406
  source: "repo"
15204
15407
  };
15205
15408
  }
15206
- const localAbs = (0, import_node_path35.join)(worktreePath, REVIEW_REQUEST_PATH);
15207
- const localContent = readTextIfPresent(localAbs) ?? readTextIfPresent((0, import_node_path35.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
15409
+ const localAbs = (0, import_node_path36.join)(worktreePath, REVIEW_REQUEST_PATH);
15410
+ const localContent = readTextIfPresent(localAbs) ?? readTextIfPresent((0, import_node_path36.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
15208
15411
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
15209
- const path2 = (0, import_node_fs38.existsSync)(localAbs) ? REVIEW_REQUEST_PATH : LEGACY_REVIEW_REQUEST_PATH;
15412
+ const path2 = (0, import_node_fs39.existsSync)(localAbs) ? REVIEW_REQUEST_PATH : LEGACY_REVIEW_REQUEST_PATH;
15210
15413
  return {
15211
15414
  path: path2,
15212
15415
  name: REVIEW_REQUEST_NAME,
@@ -15214,8 +15417,8 @@ function ensureReviewRequestFile(worktreePath) {
15214
15417
  source: "local"
15215
15418
  };
15216
15419
  }
15217
- (0, import_node_fs38.mkdirSync)((0, import_node_path35.dirname)(repoAbs), { recursive: true });
15218
- (0, import_node_fs38.writeFileSync)(repoAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
15420
+ (0, import_node_fs39.mkdirSync)((0, import_node_path36.dirname)(repoAbs), { recursive: true });
15421
+ (0, import_node_fs39.writeFileSync)(repoAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
15219
15422
  return {
15220
15423
  path: REPO_REVIEW_PATH,
15221
15424
  name: REPO_REVIEW_NAME,
@@ -15235,7 +15438,7 @@ function buildReviewRequestAttachment(content, opts) {
15235
15438
  };
15236
15439
  }
15237
15440
  function readExistingReviewRequestFile(worktreePath) {
15238
- return readTextIfPresent((0, import_node_path35.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path35.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path35.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
15441
+ return readTextIfPresent((0, import_node_path36.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path36.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path36.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
15239
15442
  }
15240
15443
  async function requestReview(threadRef, send2) {
15241
15444
  const from = findThreadByRef(threadRef);
@@ -15501,7 +15704,7 @@ var Orchestrator = class {
15501
15704
  }
15502
15705
  continue;
15503
15706
  }
15504
- if (!(0, import_node_fs41.existsSync)(thread.worktreePath)) {
15707
+ if (!(0, import_node_fs42.existsSync)(thread.worktreePath)) {
15505
15708
  setStatus(thread.id, "broken", "Worktree missing on disk");
15506
15709
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
15507
15710
  continue;
@@ -15752,7 +15955,9 @@ var Orchestrator = class {
15752
15955
  updateThread(thread.id, patch);
15753
15956
  this.emit({ type: "queue_changed", threadId: thread.id, queue });
15754
15957
  this.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
15755
- void this.drainQueue(thread.id);
15958
+ if (thisProcessShouldDrainAgentQueues()) {
15959
+ void this.drainQueue(thread.id);
15960
+ }
15756
15961
  return this.requireThread(thread.id);
15757
15962
  });
15758
15963
  }
@@ -15805,10 +16010,10 @@ var Orchestrator = class {
15805
16010
  async sendQueuedMessageNow(threadRef, index) {
15806
16011
  const thread = this.requireThread(threadRef);
15807
16012
  const promoted = await withThreadLock(thread.id, async () => {
15808
- const current = this.requireThread(thread.id);
15809
- if (index < 0 || index >= current.queue.length) return false;
15810
- const item = current.queue[index];
15811
- const rest = current.queue.filter((_, i) => i !== index);
16013
+ const current2 = this.requireThread(thread.id);
16014
+ if (index < 0 || index >= current2.queue.length) return false;
16015
+ const item = current2.queue[index];
16016
+ const rest = current2.queue.filter((_, i) => i !== index);
15812
16017
  const queue = [item, ...rest];
15813
16018
  this.haltDrain.delete(thread.id);
15814
16019
  updateThread(thread.id, { queue });
@@ -15816,10 +16021,16 @@ var Orchestrator = class {
15816
16021
  return true;
15817
16022
  });
15818
16023
  if (!promoted) return this.requireThread(thread.id);
16024
+ const current = this.requireThread(thread.id);
15819
16025
  const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id);
16026
+ const livePid = current.agentPid;
16027
+ const foreignLive = !inFlight && typeof livePid === "number" && livePid > 0 && isPidAlive(livePid);
15820
16028
  if (inFlight) {
15821
16029
  this.stop(thread.id, { clearQueue: false, continueQueue: true });
15822
16030
  } else {
16031
+ if (foreignLive) {
16032
+ this.stop(thread.id, { clearQueue: false, continueQueue: true });
16033
+ }
15823
16034
  void this.drainQueue(thread.id);
15824
16035
  }
15825
16036
  return this.requireThread(thread.id);
@@ -16070,19 +16281,16 @@ var Orchestrator = class {
16070
16281
  }
16071
16282
  let lastStderr = summarizeTurnStderr(stderrTail);
16072
16283
  let detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
16073
- if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) && looksLikeInvalidAgentSession(detail) && this.requireThread(threadId).sessionId && this.requireThread(threadId).agent !== "brightsy") {
16284
+ if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) && this.requireThread(threadId).agent !== "brightsy" && shouldRetryFailedAgentTurn(detail, {
16285
+ hasSession: Boolean(this.requireThread(threadId).sessionId)
16286
+ })) {
16074
16287
  updateThread(threadId, { sessionId: null });
16075
- pushTurnStderr(
16076
- stderrTail,
16077
- "Agent session missing \u2014 starting a fresh session"
16078
- );
16288
+ const retryNote = looksLikeInvalidAgentSession(detail) ? "Agent session missing \u2014 starting a fresh session" : "Agent runner crashed \u2014 restarting Node once";
16289
+ pushTurnStderr(stderrTail, retryNote);
16079
16290
  this.emit({
16080
16291
  type: "turn_output",
16081
16292
  threadId,
16082
- event: {
16083
- type: "stderr",
16084
- data: "Agent session missing \u2014 starting a fresh session"
16085
- }
16293
+ event: { type: "stderr", data: retryNote }
16086
16294
  });
16087
16295
  const retryThread = this.requireThread(threadId);
16088
16296
  const prior = retryThread.messages.slice(0, -1);
@@ -16131,10 +16339,7 @@ var Orchestrator = class {
16131
16339
  lastStderr = summarizeTurnStderr(stderrTail);
16132
16340
  detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
16133
16341
  }
16134
- let chatText = assistantText;
16135
- if (exitCode !== 0 && !chatText && looksLikeAgentFailureMessage(detail)) {
16136
- chatText = humanizeAgentFailDetail(detail);
16137
- }
16342
+ let chatText = this.stoppedTurns.has(threadId) ? assistantText : turnFailChatText({ exitCode, assistantText, detail });
16138
16343
  if (chatText || parts.length > 0) {
16139
16344
  appendMessage(threadId, {
16140
16345
  role: "agent",
@@ -16254,6 +16459,13 @@ var Orchestrator = class {
16254
16459
  if (handle) handle.kill();
16255
16460
  const proc = this.processes.get(`${thread.id}:agent`);
16256
16461
  if (proc) proc.kill();
16462
+ const pid = thread.agentPid;
16463
+ if (typeof pid === "number" && pid > 0 && isPidAlive(pid)) {
16464
+ try {
16465
+ process.kill(pid, "SIGTERM");
16466
+ } catch {
16467
+ }
16468
+ }
16257
16469
  const stopped = writeLiveStatus(thread.id, "stopped") ?? readThread(thread.id) ?? thread;
16258
16470
  if (stopped.status === "stopped") {
16259
16471
  this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
@@ -16535,10 +16747,13 @@ var Orchestrator = class {
16535
16747
  getTurnResult(threadRef) {
16536
16748
  const thread = this.requireThread(threadRef);
16537
16749
  const lastAgent = [...thread.messages].reverse().find((m) => m.role === "agent");
16750
+ const lastError = thread.lastError ?? null;
16751
+ const text3 = (lastAgent?.text ?? "").trim() || (thread.status === "error" ? lastError ?? "" : "");
16538
16752
  return {
16539
- text: lastAgent?.text ?? "",
16753
+ text: text3,
16540
16754
  status: thread.status,
16541
- sessionId: thread.sessionId
16755
+ sessionId: thread.sessionId,
16756
+ lastError
16542
16757
  };
16543
16758
  }
16544
16759
  assertNotGlobal(thread, action) {
@@ -17034,7 +17249,7 @@ var Orchestrator = class {
17034
17249
  this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
17035
17250
  return restored2;
17036
17251
  }
17037
- if (!(0, import_node_fs41.existsSync)(thread.worktreePath)) {
17252
+ if (!(0, import_node_fs42.existsSync)(thread.worktreePath)) {
17038
17253
  const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
17039
17254
  const { execa: execa7 } = await import("execa");
17040
17255
  const slug = thread.worktreePath.split("/").pop();
@@ -17275,7 +17490,7 @@ init_coordinator_prompt();
17275
17490
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
17276
17491
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
17277
17492
  var import_zod3 = require("zod");
17278
- var import_node_path38 = require("path");
17493
+ var import_node_path39 = require("path");
17279
17494
  init_worktree();
17280
17495
  init_global_workspace();
17281
17496
  init_list_models();
@@ -17962,7 +18177,7 @@ async function startMcpServer() {
17962
18177
  async () => {
17963
18178
  const threads = orch.getThreads(true);
17964
18179
  const lines = threads.map((t) => {
17965
- const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path38.basename)(t.repoPath) || t.repoPath;
18180
+ const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path39.basename)(t.repoPath) || t.repoPath;
17966
18181
  return `${t.id.slice(0, 8)} ${t.status.padEnd(9)} ${t.agent.padEnd(8)} ${repo} ${t.sourceType}:${t.sourceRef} ${t.title} sideboard://thread/${t.id}${t.devPort ? ` http://localhost:${t.devPort}` : ""}`;
17967
18182
  });
17968
18183
  return {
@@ -18319,7 +18534,7 @@ async function startMcpServer() {
18319
18534
  );
18320
18535
  server.tool(
18321
18536
  "wait_for_turn",
18322
- "Block until the thread finishes its current/queued turn (avoids polling). Use after send_to_thread or ask_git to read the agent reply.",
18537
+ "Block until the thread finishes its current/queued turn (avoids polling). Use after send_to_thread or ask_git. Returns status, text, and lastError. If status is error, lastError/text is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success.",
18323
18538
  {
18324
18539
  ref: import_zod3.z.string(),
18325
18540
  timeoutMs: import_zod3.z.number().optional()
@@ -18334,7 +18549,8 @@ async function startMcpServer() {
18334
18549
  text: JSON.stringify({
18335
18550
  id: thread.id,
18336
18551
  status: result.status,
18337
- text: result.text
18552
+ text: result.text,
18553
+ lastError: result.lastError
18338
18554
  })
18339
18555
  }
18340
18556
  ]
@@ -18343,7 +18559,7 @@ async function startMcpServer() {
18343
18559
  );
18344
18560
  server.tool(
18345
18561
  "get_turn_result",
18346
- "Final assistant message only (not full transcript)",
18562
+ "Final assistant message (and lastError when the turn failed). Not the full transcript.",
18347
18563
  { ref: import_zod3.z.string() },
18348
18564
  async ({ ref }) => {
18349
18565
  const result = orch.getTurnResult(ref);
@@ -19271,16 +19487,16 @@ init_connected_teams();
19271
19487
  init_injected_mcp();
19272
19488
 
19273
19489
  // src/agents/user-mcp-config.ts
19274
- var import_node_fs42 = require("fs");
19490
+ var import_node_fs43 = require("fs");
19275
19491
  var import_node_os12 = require("os");
19276
- var import_node_path39 = require("path");
19492
+ var import_node_path40 = require("path");
19277
19493
  init_paths();
19278
19494
  init_injected_mcp();
19279
19495
  function userCursorMcpConfigPath() {
19280
- return (0, import_node_path39.join)((0, import_node_os12.homedir)(), ".cursor", "mcp.json");
19496
+ return (0, import_node_path40.join)((0, import_node_os12.homedir)(), ".cursor", "mcp.json");
19281
19497
  }
19282
19498
  function userClaudeMcpConfigPath() {
19283
- return (0, import_node_path39.join)((0, import_node_os12.homedir)(), ".claude.json");
19499
+ return (0, import_node_path40.join)((0, import_node_os12.homedir)(), ".claude.json");
19284
19500
  }
19285
19501
  function asObject(value) {
19286
19502
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
@@ -19307,16 +19523,16 @@ function mergeSideboardIntoMcpServersJson(existing, sideboard) {
19307
19523
  }
19308
19524
  function writeMergedMcpServersJson(configPath, sideboard) {
19309
19525
  let existing = {};
19310
- if ((0, import_node_fs42.existsSync)(configPath)) {
19526
+ if ((0, import_node_fs43.existsSync)(configPath)) {
19311
19527
  try {
19312
- existing = JSON.parse((0, import_node_fs42.readFileSync)(configPath, "utf8"));
19528
+ existing = JSON.parse((0, import_node_fs43.readFileSync)(configPath, "utf8"));
19313
19529
  } catch {
19314
19530
  existing = {};
19315
19531
  }
19316
19532
  }
19317
19533
  const next = mergeSideboardIntoMcpServersJson(existing, sideboard);
19318
- (0, import_node_fs42.mkdirSync)((0, import_node_path39.dirname)(configPath), { recursive: true });
19319
- (0, import_node_fs42.writeFileSync)(configPath, `${JSON.stringify(next, null, 2)}
19534
+ (0, import_node_fs43.mkdirSync)((0, import_node_path40.dirname)(configPath), { recursive: true });
19535
+ (0, import_node_fs43.writeFileSync)(configPath, `${JSON.stringify(next, null, 2)}
19320
19536
  `);
19321
19537
  }
19322
19538
  function launchFromResolved(server) {
@@ -19334,7 +19550,7 @@ async function registerPackagedUserMcpClients() {
19334
19550
  const cursor = userCursorMcpConfigPath();
19335
19551
  writeMergedMcpServersJson(cursor, launch);
19336
19552
  const claude = userClaudeMcpConfigPath();
19337
- if ((0, import_node_fs42.existsSync)(claude)) {
19553
+ if ((0, import_node_fs43.existsSync)(claude)) {
19338
19554
  writeMergedMcpServersJson(claude, launch);
19339
19555
  return { cursor, claude };
19340
19556
  }
@@ -20748,9 +20964,9 @@ var import_node_http3 = require("http");
20748
20964
  var import_ws3 = require("ws");
20749
20965
 
20750
20966
  // src/slack/relay-static.ts
20751
- var import_node_fs43 = require("fs");
20967
+ var import_node_fs44 = require("fs");
20752
20968
  var import_promises = require("fs/promises");
20753
- var import_node_path40 = __toESM(require("path"), 1);
20969
+ var import_node_path41 = __toESM(require("path"), 1);
20754
20970
  var TYPES = {
20755
20971
  ".css": "text/css; charset=utf-8",
20756
20972
  ".html": "text/html; charset=utf-8",
@@ -20781,9 +20997,9 @@ function resolveStaticPath(root, requestUrl) {
20781
20997
  return null;
20782
20998
  }
20783
20999
  if (!pathname.startsWith("/") || pathname.includes("\0")) return null;
20784
- const rootResolved = import_node_path40.default.resolve(root);
20785
- const candidate = import_node_path40.default.resolve(rootResolved, `.${pathname}`);
20786
- if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path40.default.sep)) {
21000
+ const rootResolved = import_node_path41.default.resolve(root);
21001
+ const candidate = import_node_path41.default.resolve(rootResolved, `.${pathname}`);
21002
+ if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path41.default.sep)) {
20787
21003
  return null;
20788
21004
  }
20789
21005
  return candidate;
@@ -20797,7 +21013,7 @@ async function fileSize(file) {
20797
21013
  }
20798
21014
  }
20799
21015
  function sendFile(req, res, file, size) {
20800
- const ext = import_node_path40.default.extname(file).toLowerCase();
21016
+ const ext = import_node_path41.default.extname(file).toLowerCase();
20801
21017
  res.writeHead(200, {
20802
21018
  "Content-Type": TYPES[ext] ?? "application/octet-stream",
20803
21019
  "Content-Length": size,
@@ -20807,7 +21023,7 @@ function sendFile(req, res, file, size) {
20807
21023
  res.end();
20808
21024
  return true;
20809
21025
  }
20810
- (0, import_node_fs43.createReadStream)(file).pipe(res);
21026
+ (0, import_node_fs44.createReadStream)(file).pipe(res);
20811
21027
  return true;
20812
21028
  }
20813
21029
  async function tryServeStatic(req, res, root) {
@@ -20816,7 +21032,7 @@ async function tryServeStatic(req, res, root) {
20816
21032
  if (!candidate) return false;
20817
21033
  const direct = await fileSize(candidate);
20818
21034
  if (direct != null) return sendFile(req, res, candidate, direct);
20819
- const asIndex = import_node_path40.default.join(candidate, "index.html");
21035
+ const asIndex = import_node_path41.default.join(candidate, "index.html");
20820
21036
  const indexSize = await fileSize(asIndex);
20821
21037
  if (indexSize != null) return sendFile(req, res, asIndex, indexSize);
20822
21038
  return false;
@@ -21142,6 +21358,7 @@ async function startSlackRelayServer(opts) {
21142
21358
  captureTurnBaseline,
21143
21359
  checkoutPrStackLayer,
21144
21360
  childEnvWithAppSettings,
21361
+ claimDesktopHost,
21145
21362
  claudeAdapter,
21146
21363
  claudeChromeEnabled,
21147
21364
  claudeUserSettingsPath,
@@ -21180,6 +21397,7 @@ async function startSlackRelayServer(opts) {
21180
21397
  decodeBrightsyTarget,
21181
21398
  deleteBranchOnPurgeEnabled,
21182
21399
  deleteThreadRecord,
21400
+ desktopHostPidPath,
21183
21401
  detectAgents,
21184
21402
  detectGhStack,
21185
21403
  detectLocalMergeConflicts,
@@ -21305,6 +21523,7 @@ async function startSlackRelayServer(opts) {
21305
21523
  isConductorBundledCli,
21306
21524
  isCursorAutoModel,
21307
21525
  isDefaultishSourceRef,
21526
+ isDesktopHostAlive,
21308
21527
  isDirty,
21309
21528
  isGhRateLimitError,
21310
21529
  isGlobalRepoPath,
@@ -21326,6 +21545,7 @@ async function startSlackRelayServer(opts) {
21326
21545
  isSlackExternalReplyPrompt,
21327
21546
  isSlackOAuthCancelled,
21328
21547
  isThinkingEffort,
21548
+ isThisProcessDesktopHost,
21329
21549
  isThreadCaffeinated,
21330
21550
  isWorkspaceScratchPath,
21331
21551
  linearAuthorizationHeader,
@@ -21427,6 +21647,7 @@ async function startSlackRelayServer(opts) {
21427
21647
  refreshSlackReplyBadges,
21428
21648
  registerPackagedUserMcpClients,
21429
21649
  releaseCaffeinateHoldForThread,
21650
+ releaseDesktopHost,
21430
21651
  removeWorkspace,
21431
21652
  removeWorktree,
21432
21653
  repoSlug,
@@ -21527,6 +21748,7 @@ async function startSlackRelayServer(opts) {
21527
21748
  taskMessageText,
21528
21749
  thinkingEffortBars,
21529
21750
  thinkingEffortLabel,
21751
+ thisProcessShouldDrainAgentQueues,
21530
21752
  threadDisplayLabel,
21531
21753
  threadFilePath,
21532
21754
  threadLockPath,