@sideboard-ai/core 0.1.110 → 0.1.115

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 (43) hide show
  1. package/dist/agents/cursor-runner.cjs +32 -23
  2. package/dist/agents/cursor-runner.js +3 -3
  3. package/dist/{agents-WK54VP7J.js → agents-3X3EFCQY.js} +7 -7
  4. package/dist/{agents-MQDW3YXL.js → agents-AHAFC6FR.js} +10 -10
  5. package/dist/{chunk-4EWPKYOU.js → chunk-4OJMZ6P2.js} +2 -2
  6. package/dist/{chunk-VOJSO3RM.js → chunk-66XTXHR3.js} +277 -49
  7. package/dist/{chunk-KQBI5HNT.js → chunk-7WC5UWEB.js} +2 -2
  8. package/dist/{chunk-WIHKHR5R.js → chunk-AXQ4ZWHK.js} +5 -0
  9. package/dist/{chunk-RSIWPLRG.js → chunk-C6OBY6IC.js} +268 -27
  10. package/dist/{chunk-EAAB4EK5.js → chunk-DCNR7NAL.js} +44 -32
  11. package/dist/{chunk-LGXBYZZA.js → chunk-DVM4ID64.js} +69 -13
  12. package/dist/{chunk-2GO3YKBA.js → chunk-EKIDHL2T.js} +4 -4
  13. package/dist/{chunk-C4KHDW3U.js → chunk-FZCIQYNQ.js} +1 -1
  14. package/dist/{chunk-7KWYXGIU.js → chunk-K3TIQXOH.js} +2 -2
  15. package/dist/{chunk-3KETJKYA.js → chunk-KPIYENTF.js} +69 -13
  16. package/dist/{chunk-XOZDAVOP.js → chunk-MZ6HJ7VL.js} +52 -35
  17. package/dist/{chunk-3UOKB6VQ.js → chunk-SLU5JVKD.js} +282 -228
  18. package/dist/{chunk-VOD3HFLP.js → chunk-XOYQ7LNQ.js} +2 -2
  19. package/dist/{chunk-7YKXHBIW.js → chunk-YMRT2DU6.js} +3 -3
  20. package/dist/{chunk-YXDR43ZC.js → chunk-ZMROW673.js} +5 -5
  21. package/dist/{chunk-YFAXVUY2.js → chunk-ZRCX43LS.js} +2 -2
  22. package/dist/{chunk-AROMOP3C.js → chunk-ZYEFCSZJ.js} +2 -2
  23. package/dist/{connected-teams-M5XNXRI5.js → connected-teams-O6D4PM7A.js} +2 -2
  24. package/dist/{connected-teams-J4I5AKMR.js → connected-teams-ZCOU6KCD.js} +2 -2
  25. package/dist/{coordinator-prompt-AR66L3N4.js → coordinator-prompt-4KCALEKD.js} +3 -3
  26. package/dist/{coordinator-prompt-BHMLWL64.js → coordinator-prompt-FML4I5AR.js} +3 -3
  27. package/dist/{global-workspace-XSUFEIAQ.js → global-workspace-CSWABOG5.js} +4 -4
  28. package/dist/{global-workspace-SKFODUQQ.js → global-workspace-H4YNASM6.js} +4 -4
  29. package/dist/index.cjs +825 -443
  30. package/dist/index.d.cts +53 -1
  31. package/dist/index.d.ts +53 -1
  32. package/dist/index.js +33 -15
  33. package/dist/mcp/run-stdio.cjs +947 -644
  34. package/dist/mcp/run-stdio.js +18 -14
  35. package/dist/{orchestrator-SCATSB3O.js → orchestrator-GKLYKLRC.js} +8 -8
  36. package/dist/{orchestrator-FCZVCKBK.js → orchestrator-TXASYNHT.js} +10 -10
  37. package/dist/{run-XKTAJRWF.js → run-USF6FRKV.js} +3 -1
  38. package/dist/{run-CFKZPY7F.js → run-XQKGHQZ2.js} +3 -1
  39. package/dist/{workspaces-XAQVKTLO.js → workspaces-HJ3EVATC.js} +5 -5
  40. package/dist/{workspaces-HV3J4TTW.js → workspaces-QG6PGFQR.js} +5 -5
  41. package/dist/{worktree-XFJED3VU.js → worktree-IW3BX26B.js} +2 -2
  42. package/dist/{worktree-N2EV24EE.js → worktree-OTFQO2W7.js} +2 -2
  43. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -3583,12 +3583,47 @@ var init_path = __esm({
3583
3583
  }
3584
3584
  });
3585
3585
 
3586
+ // src/git/stale-lock.ts
3587
+ function isIndexLockError(text4) {
3588
+ return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text4);
3589
+ }
3590
+ function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
3591
+ const lockPath = (0, import_node_path14.join)(gitDir, "index.lock");
3592
+ try {
3593
+ if (!(0, import_node_fs14.existsSync)(lockPath)) return null;
3594
+ if (now - (0, import_node_fs14.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
3595
+ (0, import_node_fs14.unlinkSync)(lockPath);
3596
+ return lockPath;
3597
+ } catch {
3598
+ return null;
3599
+ }
3600
+ }
3601
+ function clearStaleIndexLocks(gitDirs, maxAgeMs = STALE_INDEX_LOCK_MS) {
3602
+ const now = Date.now();
3603
+ const removed = [];
3604
+ for (const dir of new Set(gitDirs)) {
3605
+ const cleared = clearStaleIndexLock(dir, maxAgeMs, now);
3606
+ if (cleared) removed.push(cleared);
3607
+ }
3608
+ return removed;
3609
+ }
3610
+ var import_node_fs14, import_node_path14, STALE_INDEX_LOCK_MS;
3611
+ var init_stale_lock = __esm({
3612
+ "src/git/stale-lock.ts"() {
3613
+ "use strict";
3614
+ import_node_fs14 = require("fs");
3615
+ import_node_path14 = require("path");
3616
+ STALE_INDEX_LOCK_MS = 2e4;
3617
+ }
3618
+ });
3619
+
3586
3620
  // src/git/run.ts
3587
3621
  var run_exports = {};
3588
3622
  __export(run_exports, {
3589
3623
  gh: () => gh,
3590
3624
  git: () => git,
3591
3625
  resolveGhAuthToken: () => resolveGhAuthToken,
3626
+ resolveGitDirsForLockRecovery: () => resolveGitDirsForLockRecovery,
3592
3627
  run: () => run
3593
3628
  });
3594
3629
  async function run(file, args, opts) {
@@ -3617,6 +3652,21 @@ async function run(file, args, opts) {
3617
3652
  throw err;
3618
3653
  }
3619
3654
  }
3655
+ async function resolveGitDirsForLockRecovery(cwd, env = {}) {
3656
+ const dirs = /* @__PURE__ */ new Set();
3657
+ const [gitDir, commonDir] = await Promise.all([
3658
+ run("git", ["rev-parse", "--absolute-git-dir"], { cwd, reject: false, env, timeoutMs: 5e3 }),
3659
+ run("git", ["rev-parse", "--path-format=absolute", "--git-common-dir"], {
3660
+ cwd,
3661
+ reject: false,
3662
+ env,
3663
+ timeoutMs: 5e3
3664
+ })
3665
+ ]);
3666
+ if (gitDir.exitCode === 0 && gitDir.stdout.trim()) dirs.add(gitDir.stdout.trim());
3667
+ if (commonDir.exitCode === 0 && commonDir.stdout.trim()) dirs.add(commonDir.stdout.trim());
3668
+ return [...dirs];
3669
+ }
3620
3670
  async function git(args, cwd, opts) {
3621
3671
  const prefix = [];
3622
3672
  if (opts?.config) {
@@ -3625,21 +3675,32 @@ async function git(args, cwd, opts) {
3625
3675
  prefix.push("-c", `${key}=${value}`);
3626
3676
  }
3627
3677
  }
3628
- return run("git", ["--no-pager", ...prefix, ...args], {
3629
- cwd,
3630
- reject: opts?.reject,
3631
- timeoutMs: opts?.timeoutMs,
3678
+ const gitArgs = ["--no-pager", ...prefix, ...args];
3679
+ const env = {
3632
3680
  // Never block forever on a credential/SSH prompt inside MCP / Electron.
3633
- env: {
3634
- GIT_TERMINAL_PROMPT: "0",
3635
- GIT_ASKPASS: process.env.GIT_ASKPASS || "echo",
3636
- SSH_ASKPASS: process.env.SSH_ASKPASS || "echo",
3637
- GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND || "ssh -o BatchMode=yes -o ConnectTimeout=15",
3638
- GCM_INTERACTIVE: "never",
3639
- GH_PROMPT_DISABLED: "1",
3640
- ...opts?.env
3681
+ GIT_TERMINAL_PROMPT: "0",
3682
+ GIT_ASKPASS: process.env.GIT_ASKPASS || "echo",
3683
+ SSH_ASKPASS: process.env.SSH_ASKPASS || "echo",
3684
+ GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND || "ssh -o BatchMode=yes -o ConnectTimeout=15",
3685
+ GCM_INTERACTIVE: "never",
3686
+ GH_PROMPT_DISABLED: "1",
3687
+ ...opts?.env
3688
+ };
3689
+ let result = await run("git", gitArgs, { cwd, reject: false, timeoutMs: opts?.timeoutMs, env });
3690
+ if (result.exitCode !== 0 && isIndexLockError(result.stderr)) {
3691
+ const gitDirs = await resolveGitDirsForLockRecovery(cwd, env);
3692
+ const cleared = clearStaleIndexLocks(gitDirs);
3693
+ if (cleared.length > 0) {
3694
+ result = await run("git", gitArgs, { cwd, reject: false, timeoutMs: opts?.timeoutMs, env });
3641
3695
  }
3642
- });
3696
+ }
3697
+ if ((opts?.reject ?? true) && result.exitCode !== 0) {
3698
+ throw new Error(
3699
+ `Command failed with exit code ${result.exitCode}: git ${gitArgs.join(" ")}
3700
+ ${result.stderr}`
3701
+ );
3702
+ }
3703
+ return result;
3643
3704
  }
3644
3705
  async function gh(args, cwd, opts) {
3645
3706
  return run("gh", args, {
@@ -3664,6 +3725,7 @@ var init_run = __esm({
3664
3725
  "use strict";
3665
3726
  import_execa2 = require("execa");
3666
3727
  init_path();
3728
+ init_stale_lock();
3667
3729
  }
3668
3730
  });
3669
3731
 
@@ -3758,7 +3820,7 @@ async function warmGithubAgentAuth(opts) {
3758
3820
  }
3759
3821
  function normalizeWritableRoot(raw) {
3760
3822
  const trimmed = raw.trim().replace(/\/+$/, "");
3761
- return trimmed && (0, import_node_path14.isAbsolute)(trimmed) ? trimmed : null;
3823
+ return trimmed && (0, import_node_path15.isAbsolute)(trimmed) ? trimmed : null;
3762
3824
  }
3763
3825
  async function resolveCodexGitWritableRoots(cwd) {
3764
3826
  const roots = /* @__PURE__ */ new Set();
@@ -3835,11 +3897,11 @@ function formatGitAuthModeDirective(mode) {
3835
3897
  ].join("\n");
3836
3898
  }
3837
3899
  }
3838
- var import_node_path14, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
3900
+ var import_node_path15, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
3839
3901
  var init_git_auth_mode = __esm({
3840
3902
  "src/git/git-auth-mode.ts"() {
3841
3903
  "use strict";
3842
- import_node_path14 = require("path");
3904
+ import_node_path15 = require("path");
3843
3905
  init_app_settings();
3844
3906
  init_github_agent_auth();
3845
3907
  init_run();
@@ -5037,8 +5099,8 @@ function isLocalPrFetchBranch(ref) {
5037
5099
  }
5038
5100
  async function createThreadWorktree(opts) {
5039
5101
  let branchName = `thread/${opts.slug}`;
5040
- const worktreePath = (0, import_node_path15.join)(worktreesRoot(opts.repoPath), opts.slug);
5041
- if ((0, import_node_fs14.existsSync)(worktreePath)) {
5102
+ const worktreePath = (0, import_node_path16.join)(worktreesRoot(opts.repoPath), opts.slug);
5103
+ if ((0, import_node_fs15.existsSync)(worktreePath)) {
5042
5104
  throw new Error(`Worktree already exists at ${worktreePath}`);
5043
5105
  }
5044
5106
  await ensureGhPreferOrigin(opts.repoPath);
@@ -5105,8 +5167,8 @@ ${add.stdout}`;
5105
5167
  async function createExistingBranchWorktree(opts) {
5106
5168
  const branchName = opts.branchName.trim();
5107
5169
  if (!branchName) throw new Error("branch name required");
5108
- const worktreePath = (0, import_node_path15.join)(worktreesRoot(opts.repoPath), opts.slug);
5109
- if ((0, import_node_fs14.existsSync)(worktreePath)) {
5170
+ const worktreePath = (0, import_node_path16.join)(worktreesRoot(opts.repoPath), opts.slug);
5171
+ if ((0, import_node_fs15.existsSync)(worktreePath)) {
5110
5172
  throw new Error(`Worktree already exists at ${worktreePath}`);
5111
5173
  }
5112
5174
  await ensureGhPreferOrigin(opts.repoPath);
@@ -5397,10 +5459,10 @@ function sameRepoPath(a, b) {
5397
5459
  return normalizeWorktreePath(a) === normalizeWorktreePath(b);
5398
5460
  }
5399
5461
  function listLocalThreadBranchSlugs(repoPath) {
5400
- const refsDir = (0, import_node_path15.join)(repoPath, ".git", "refs", "heads", "thread");
5401
- if (!(0, import_node_fs14.existsSync)(refsDir)) return [];
5462
+ const refsDir = (0, import_node_path16.join)(repoPath, ".git", "refs", "heads", "thread");
5463
+ if (!(0, import_node_fs15.existsSync)(refsDir)) return [];
5402
5464
  try {
5403
- return (0, import_node_fs14.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
5465
+ return (0, import_node_fs15.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
5404
5466
  } catch {
5405
5467
  return [];
5406
5468
  }
@@ -5408,8 +5470,8 @@ function listLocalThreadBranchSlugs(repoPath) {
5408
5470
  function collectTakenTeamSlugs(repoPath) {
5409
5471
  const taken = /* @__PURE__ */ new Set();
5410
5472
  const root = worktreesRoot(repoPath);
5411
- if ((0, import_node_fs14.existsSync)(root)) {
5412
- for (const entry of (0, import_node_fs14.readdirSync)(root, { withFileTypes: true })) {
5473
+ if ((0, import_node_fs15.existsSync)(root)) {
5474
+ for (const entry of (0, import_node_fs15.readdirSync)(root, { withFileTypes: true })) {
5413
5475
  if (entry.isDirectory() && entry.name !== ".DS_Store") {
5414
5476
  taken.add(normalizeTakenSlug(entry.name));
5415
5477
  }
@@ -5430,18 +5492,18 @@ function allocateTeamSlug(repoPath) {
5430
5492
  const taken = collectTakenTeamSlugs(repoPath);
5431
5493
  for (let attempt = 0; attempt < 32; attempt++) {
5432
5494
  const team = allocateTeamName(taken);
5433
- const path2 = (0, import_node_path15.join)(worktreesRoot(repoPath), team.slug);
5434
- if (!(0, import_node_fs14.existsSync)(path2)) return team;
5495
+ const path2 = (0, import_node_path16.join)(worktreesRoot(repoPath), team.slug);
5496
+ if (!(0, import_node_fs15.existsSync)(path2)) return team;
5435
5497
  taken.add(team.slug);
5436
5498
  }
5437
5499
  throw new Error("No available soccer team worktree directories left");
5438
5500
  }
5439
- var import_node_fs14, import_node_path15;
5501
+ var import_node_fs15, import_node_path16;
5440
5502
  var init_worktree = __esm({
5441
5503
  "src/git/worktree.ts"() {
5442
5504
  "use strict";
5443
- import_node_fs14 = require("fs");
5444
- import_node_path15 = require("path");
5505
+ import_node_fs15 = require("fs");
5506
+ import_node_path16 = require("path");
5445
5507
  init_paths();
5446
5508
  init_thread_store();
5447
5509
  init_teams();
@@ -5518,7 +5580,7 @@ function coordinatorTurnReminder(opts) {
5518
5580
  function ensureGlobalCoordinatorCwd(opts) {
5519
5581
  const dir = globalAgentCwd();
5520
5582
  try {
5521
- (0, import_node_fs15.mkdirSync)(dir, { recursive: true });
5583
+ (0, import_node_fs16.mkdirSync)(dir, { recursive: true });
5522
5584
  } catch {
5523
5585
  return dir;
5524
5586
  }
@@ -5526,7 +5588,7 @@ function ensureGlobalCoordinatorCwd(opts) {
5526
5588
  let orchId = opts?.orchestratorThreadId?.trim() || "";
5527
5589
  if (!orchId) {
5528
5590
  try {
5529
- const existing = (0, import_node_fs15.readFileSync)((0, import_node_path16.join)(dir, "AGENTS.md"), "utf8");
5591
+ const existing = (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(dir, "AGENTS.md"), "utf8");
5530
5592
  const m = existing.match(
5531
5593
  /YOUR orchestration thread id is `([0-9a-f-]{36})`/i
5532
5594
  );
@@ -5568,9 +5630,9 @@ function ensureGlobalCoordinatorCwd(opts) {
5568
5630
  "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."
5569
5631
  ].join("\n");
5570
5632
  try {
5571
- (0, import_node_fs15.writeFileSync)((0, import_node_path16.join)(dir, "CLAUDE.md"), `${body}
5633
+ (0, import_node_fs16.writeFileSync)((0, import_node_path17.join)(dir, "CLAUDE.md"), `${body}
5572
5634
  `, "utf8");
5573
- (0, import_node_fs15.writeFileSync)((0, import_node_path16.join)(dir, "AGENTS.md"), `${body}
5635
+ (0, import_node_fs16.writeFileSync)((0, import_node_path17.join)(dir, "AGENTS.md"), `${body}
5574
5636
  `, "utf8");
5575
5637
  } catch {
5576
5638
  }
@@ -5602,12 +5664,12 @@ function coordinatorSystemPrompt(opts) {
5602
5664
  formatWorkspaceInventory(opts.workspaces)
5603
5665
  ].join("\n");
5604
5666
  }
5605
- var import_node_fs15, import_node_path16, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
5667
+ var import_node_fs16, import_node_path17, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
5606
5668
  var init_coordinator_prompt = __esm({
5607
5669
  "src/orchestrator/coordinator-prompt.ts"() {
5608
5670
  "use strict";
5609
- import_node_fs15 = require("fs");
5610
- import_node_path16 = require("path");
5671
+ import_node_fs16 = require("fs");
5672
+ import_node_path17 = require("path");
5611
5673
  init_worktree();
5612
5674
  init_app_settings();
5613
5675
  init_paths();
@@ -5633,7 +5695,7 @@ var init_coordinator_prompt = __esm({
5633
5695
  "- 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.",
5634
5696
  "- 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.",
5635
5697
  "- 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",
5636
- "- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply. wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success.",
5698
+ "- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply. wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success.",
5637
5699
  "- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
5638
5700
  "- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
5639
5701
  "Setup / run:",
@@ -5950,13 +6012,13 @@ var init_api = __esm({
5950
6012
 
5951
6013
  // src/slack/reply-target.ts
5952
6014
  function storePath() {
5953
- return (0, import_node_path17.join)(appDataDir(), "slack-reply-to.json");
6015
+ return (0, import_node_path18.join)(appDataDir(), "slack-reply-to.json");
5954
6016
  }
5955
6017
  function readStore() {
5956
6018
  const path2 = storePath();
5957
- if (!(0, import_node_fs16.existsSync)(path2)) return {};
6019
+ if (!(0, import_node_fs17.existsSync)(path2)) return {};
5958
6020
  try {
5959
- const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs16.readFileSync)(path2, "utf8"));
6021
+ const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs17.readFileSync)(path2, "utf8"));
5960
6022
  return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
5961
6023
  } catch {
5962
6024
  return {};
@@ -5971,12 +6033,12 @@ function setSlackReplyTarget(target) {
5971
6033
  function getSlackReplyTarget(threadId) {
5972
6034
  return readStore()[threadId] ?? null;
5973
6035
  }
5974
- var import_node_fs16, import_node_path17;
6036
+ var import_node_fs17, import_node_path18;
5975
6037
  var init_reply_target = __esm({
5976
6038
  "src/slack/reply-target.ts"() {
5977
6039
  "use strict";
5978
- import_node_fs16 = require("fs");
5979
- import_node_path17 = require("path");
6040
+ import_node_fs17 = require("fs");
6041
+ import_node_path18 = require("path");
5980
6042
  init_paths();
5981
6043
  init_private_file();
5982
6044
  init_secure_file();
@@ -5985,7 +6047,7 @@ var init_reply_target = __esm({
5985
6047
 
5986
6048
  // src/slack/workspaces.ts
5987
6049
  function storePath2() {
5988
- return (0, import_node_path18.join)(appDataDir(), "slack-workspaces.json");
6050
+ return (0, import_node_path19.join)(appDataDir(), "slack-workspaces.json");
5989
6051
  }
5990
6052
  function readStore2() {
5991
6053
  try {
@@ -6092,11 +6154,11 @@ function requireSlackWorkspace(teamId) {
6092
6154
  }
6093
6155
  return ws;
6094
6156
  }
6095
- var import_node_path18;
6157
+ var import_node_path19;
6096
6158
  var init_workspaces = __esm({
6097
6159
  "src/slack/workspaces.ts"() {
6098
6160
  "use strict";
6099
- import_node_path18 = require("path");
6161
+ import_node_path19 = require("path");
6100
6162
  init_paths();
6101
6163
  init_secure_file();
6102
6164
  init_api();
@@ -6105,7 +6167,7 @@ var init_workspaces = __esm({
6105
6167
 
6106
6168
  // src/slack/outbound-watch.ts
6107
6169
  function storePath3() {
6108
- return (0, import_node_path19.join)(appDataDir(), "slack-outbound-watch.json");
6170
+ return (0, import_node_path20.join)(appDataDir(), "slack-outbound-watch.json");
6109
6171
  }
6110
6172
  function watchId(teamId, channelId, ts) {
6111
6173
  return `${teamId}:${channelId}:${ts}`;
@@ -6135,9 +6197,9 @@ function tsNewer(a, b) {
6135
6197
  }
6136
6198
  function readStore3() {
6137
6199
  const path2 = storePath3();
6138
- if (!(0, import_node_fs17.existsSync)(path2)) return [];
6200
+ if (!(0, import_node_fs18.existsSync)(path2)) return [];
6139
6201
  try {
6140
- const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs17.readFileSync)(path2, "utf8"));
6202
+ const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs18.readFileSync)(path2, "utf8"));
6141
6203
  return Array.isArray(parsed?.watches) ? parsed.watches : [];
6142
6204
  } catch {
6143
6205
  return [];
@@ -6480,12 +6542,12 @@ async function refreshSlackReplyBadges(opts) {
6480
6542
  if (changed) writeStore2(watches);
6481
6543
  return listSlackReplyBadges();
6482
6544
  }
6483
- var import_node_fs17, import_node_path19, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache;
6545
+ var import_node_fs18, import_node_path20, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache;
6484
6546
  var init_outbound_watch = __esm({
6485
6547
  "src/slack/outbound-watch.ts"() {
6486
6548
  "use strict";
6487
- import_node_fs17 = require("fs");
6488
- import_node_path19 = require("path");
6549
+ import_node_fs18 = require("fs");
6550
+ import_node_path20 = require("path");
6489
6551
  init_paths();
6490
6552
  init_private_file();
6491
6553
  init_secure_file();
@@ -6547,7 +6609,7 @@ function extractJsonErrorMessage(obj) {
6547
6609
  }
6548
6610
  function isPinnedStderrLine(line) {
6549
6611
  if (/^\s*at\s/.test(line)) return false;
6550
- return /cannot find (?:package|module)|ERR_MODULE_NOT_FOUND|cursor startup failed:/i.test(
6612
+ return /cannot find (?:package|module)|ERR_MODULE_NOT_FOUND|cursor startup failed:|FATAL ERROR|heap out of memory|javascript heap|OOMErrorHandler|FatalProcessOutOfMemory/i.test(
6551
6613
  line
6552
6614
  );
6553
6615
  }
@@ -6570,12 +6632,17 @@ function looksLikeMinifiedJsDump(line) {
6570
6632
  function looksLikeNestedElectronCrash(line) {
6571
6633
  return /HasCustomHostObject|ElectronInitializeICUandStartNode/i.test(line);
6572
6634
  }
6573
- function looksLikeHomebrewLibuvCrash(line) {
6574
- const uvRun = /uv_run/i.test(line);
6575
- const spin = /SpinEventLoopInternal/i.test(line);
6576
- const homebrewUv = /Cellar\/libuv|libuv\.\d\.dylib/i.test(line);
6577
- const homebrewNode = /Cellar\/node\//i.test(line);
6578
- return uvRun && (homebrewUv || spin || homebrewNode) || spin && (homebrewUv || homebrewNode);
6635
+ function looksLikeNativeEventLoopCrash(text4) {
6636
+ return /uv_run|uv__io_poll|SpinEventLoopInternal/i.test(text4);
6637
+ }
6638
+ function looksLikeV8Oom(text4) {
6639
+ return /javascript heap|reached heap limit|OOMErrorHandler|FatalProcessOutOfMemory|Allocation failed - JavaScript heap/i.test(
6640
+ text4
6641
+ );
6642
+ }
6643
+ function looksLikeHomebrewLibuvCrash(text4) {
6644
+ if (!looksLikeNativeEventLoopCrash(text4)) return false;
6645
+ return /Cellar\/(?:libuv|node)|libuv\.\d+\.dylib/i.test(text4);
6579
6646
  }
6580
6647
  function clipStderr(text4, maxChars) {
6581
6648
  const trimmed = text4.trim();
@@ -6589,7 +6656,12 @@ function summarizeTurnStderr(tail, maxChars = 500) {
6589
6656
  const cursorRunFailed = [...tail].reverse().find((line) => /^cursor run failed\b/i.test(line.trim()));
6590
6657
  if (cursorRunFailed) return clipStderr(cursorRunFailed, maxChars);
6591
6658
  if (tail.some(looksLikeNestedElectronCrash)) return NESTED_ELECTRON_SUMMARY;
6592
- if (tail.some(looksLikeHomebrewLibuvCrash)) return HOMEBREW_LIBUV_SUMMARY;
6659
+ const blob = tail.join("\n");
6660
+ if (looksLikeV8Oom(blob)) return V8_OOM_SUMMARY;
6661
+ if (looksLikeHomebrewLibuvCrash(blob)) return HOMEBREW_LIBUV_SUMMARY;
6662
+ if (looksLikeNativeEventLoopCrash(blob)) {
6663
+ return BUNDLED_NODE_CRASH_SUMMARY;
6664
+ }
6593
6665
  if (tail.some(
6594
6666
  (line) => /\[resource_exhausted\]|resource_exhausted/i.test(line) || /findFilesWithRipgrep/.test(line)
6595
6667
  )) {
@@ -6615,15 +6687,17 @@ function looksLikeInvalidAgentSession(text4) {
6615
6687
  function looksLikeRetryableRunnerCrash(text4) {
6616
6688
  if (looksLikeAgentFailureMessage(text4)) return false;
6617
6689
  if (looksLikeInvalidAgentSession(text4)) return false;
6690
+ if (looksLikeV8Oom(text4)) return false;
6618
6691
  const lower = text4.trim().toLowerCase();
6619
6692
  if (/cannot find (?:package|module)|err_module_not_found/.test(lower)) return false;
6620
6693
  if (!lower) return true;
6621
- return /uv_run|spineventloopinternal|libuv|homebrew node \+ shared libuv|hascustomhostobject|electroninitializeicuandstartnode|nested chromium|truncated crash dump|connection stalled|sig(?:segv|abrt|ill)|segmentation fault|illegal instruction|fatal error/.test(
6694
+ return /uv_run|spineventloopinternal|libuv|homebrew node \+ shared libuv|cursor runner crashed in node|hascustomhostobject|electroninitializeicuandstartnode|nested chromium|truncated crash dump|connection stalled|sig(?:segv|abrt|ill)|segmentation fault|illegal instruction|fatal error/.test(
6622
6695
  lower
6623
6696
  );
6624
6697
  }
6625
6698
  function shouldRetryFailedAgentTurn(detail, opts) {
6626
6699
  if (looksLikeInvalidAgentSession(detail) && opts.hasSession) return true;
6700
+ if (looksLikeV8Oom(detail) && opts.hasSession) return true;
6627
6701
  return looksLikeRetryableRunnerCrash(detail);
6628
6702
  }
6629
6703
  function looksLikeAgentFailureMessage(text4) {
@@ -6670,9 +6744,15 @@ function humanizeAgentFailDetail(detail) {
6670
6744
  if (/hascustomhostobject|electroninitializeicuandstartnode|nested chromium/i.test(lower)) {
6671
6745
  return `${raw} \u2014 retry the turn; if it keeps failing, pick another agent.`;
6672
6746
  }
6673
- if (/homebrew node \+ shared libuv|uv_run|spineventloopinternal/i.test(lower)) {
6747
+ if (looksLikeV8Oom(raw) || /javascript heap out of memory/i.test(lower)) {
6748
+ return /ran out of memory/i.test(raw) ? raw : V8_OOM_SUMMARY;
6749
+ }
6750
+ if (/homebrew node \+ shared libuv|Cellar\/(?:libuv|node)|libuv\.\d+\.dylib/i.test(raw)) {
6674
6751
  return /brew install node@22/i.test(raw) ? raw : `${raw} \u2014 install Node 22 LTS (\`brew install node@22\`) and retry.`;
6675
6752
  }
6753
+ if (/uv_run|spineventloopinternal|uv__io_poll|cursor runner crashed in node/i.test(lower)) {
6754
+ return /retry the turn/i.test(raw) ? raw : BUNDLED_NODE_CRASH_SUMMARY;
6755
+ }
6676
6756
  if (/corrupt local agent checkpoint|missing root blob|truncated crash dump/.test(lower)) {
6677
6757
  return `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
6678
6758
  }
@@ -6702,45 +6782,47 @@ function formatTurnExitError(exitCode, stderrSummary) {
6702
6782
  if (looksLikeAgentFailureMessage(raw)) return detail;
6703
6783
  return `exit ${code}: ${detail}`;
6704
6784
  }
6705
- var NODE_VERSION_FOOTER, NESTED_ELECTRON_SUMMARY, HOMEBREW_LIBUV_SUMMARY, MINIFIED_DUMP_SUMMARY;
6785
+ var NODE_VERSION_FOOTER, NESTED_ELECTRON_SUMMARY, HOMEBREW_LIBUV_SUMMARY, BUNDLED_NODE_CRASH_SUMMARY, V8_OOM_SUMMARY, MINIFIED_DUMP_SUMMARY;
6706
6786
  var init_error_detail = __esm({
6707
6787
  "src/agents/error-detail.ts"() {
6708
6788
  "use strict";
6709
6789
  NODE_VERSION_FOOTER = /^Node\.js v\d+/i;
6710
6790
  NESTED_ELECTRON_SUMMARY = "Cursor local agent crashed at Electron startup (nested Chromium / HasCustomHostObject)";
6711
6791
  HOMEBREW_LIBUV_SUMMARY = "Cursor runner crashed in Node (Homebrew Node + shared libuv). Install Node 22 LTS (`brew install node@22`) and retry.";
6792
+ BUNDLED_NODE_CRASH_SUMMARY = "Cursor runner crashed in Node. Retry the turn.";
6793
+ V8_OOM_SUMMARY = "Agent ran out of memory (JavaScript heap). If it keeps happening, exclude large files from the project folder.";
6712
6794
  MINIFIED_DUMP_SUMMARY = "Cursor local agent crashed during startup (truncated crash dump)";
6713
6795
  }
6714
6796
  });
6715
6797
 
6716
6798
  // src/brightsy/config.ts
6717
6799
  function brightsyConfigPath() {
6718
- return (0, import_node_path20.join)((0, import_node_os6.homedir)(), ".brightsy", "config.json");
6800
+ return (0, import_node_path21.join)((0, import_node_os6.homedir)(), ".brightsy", "config.json");
6719
6801
  }
6720
6802
  function loadBrightsyConfig() {
6721
6803
  const path2 = brightsyConfigPath();
6722
- if (!(0, import_node_fs18.existsSync)(path2)) {
6804
+ if (!(0, import_node_fs19.existsSync)(path2)) {
6723
6805
  throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
6724
6806
  }
6725
- const raw = JSON.parse((0, import_node_fs18.readFileSync)(path2, "utf8"));
6807
+ const raw = JSON.parse((0, import_node_fs19.readFileSync)(path2, "utf8"));
6726
6808
  if (!raw.access_token || !raw.account_id) {
6727
6809
  throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
6728
6810
  }
6729
6811
  return raw;
6730
6812
  }
6731
6813
  function saveBrightsyConfig(cfg) {
6732
- (0, import_node_fs18.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
6814
+ (0, import_node_fs19.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
6733
6815
  `, {
6734
6816
  mode: 384
6735
6817
  });
6736
6818
  }
6737
- var import_node_fs18, import_node_os6, import_node_path20;
6819
+ var import_node_fs19, import_node_os6, import_node_path21;
6738
6820
  var init_config = __esm({
6739
6821
  "src/brightsy/config.ts"() {
6740
6822
  "use strict";
6741
- import_node_fs18 = require("fs");
6823
+ import_node_fs19 = require("fs");
6742
6824
  import_node_os6 = require("os");
6743
- import_node_path20 = require("path");
6825
+ import_node_path21 = require("path");
6744
6826
  }
6745
6827
  });
6746
6828
 
@@ -6843,22 +6925,22 @@ __export(connected_teams_exports, {
6843
6925
  listConnectedBrightsyTeams: () => listConnectedBrightsyTeams
6844
6926
  });
6845
6927
  function storePath4() {
6846
- return (0, import_node_path21.join)(appDataDir(), "brightsy-teams.json");
6928
+ return (0, import_node_path22.join)(appDataDir(), "brightsy-teams.json");
6847
6929
  }
6848
6930
  function readStore4() {
6849
6931
  const path2 = storePath4();
6850
- if (!(0, import_node_fs19.existsSync)(path2)) return [];
6932
+ if (!(0, import_node_fs20.existsSync)(path2)) return [];
6851
6933
  try {
6852
- const parsed = JSON.parse((0, import_node_fs19.readFileSync)(path2, "utf8"));
6934
+ const parsed = JSON.parse((0, import_node_fs20.readFileSync)(path2, "utf8"));
6853
6935
  return Array.isArray(parsed.teams) ? parsed.teams : [];
6854
6936
  } catch {
6855
6937
  return [];
6856
6938
  }
6857
6939
  }
6858
6940
  function writeStore3(teams) {
6859
- (0, import_node_fs19.mkdirSync)(appDataDir(), { recursive: true });
6941
+ (0, import_node_fs20.mkdirSync)(appDataDir(), { recursive: true });
6860
6942
  const path2 = storePath4();
6861
- (0, import_node_fs19.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
6943
+ (0, import_node_fs20.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
6862
6944
  `, {
6863
6945
  mode: 384
6864
6946
  });
@@ -7020,12 +7102,12 @@ function brightsyMcpServerName(slug) {
7020
7102
  const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
7021
7103
  return `brightsy_${cleaned || "team"}`;
7022
7104
  }
7023
- var import_node_fs19, import_node_path21;
7105
+ var import_node_fs20, import_node_path22;
7024
7106
  var init_connected_teams = __esm({
7025
7107
  "src/brightsy/connected-teams.ts"() {
7026
7108
  "use strict";
7027
- import_node_fs19 = require("fs");
7028
- import_node_path21 = require("path");
7109
+ import_node_fs20 = require("fs");
7110
+ import_node_path22 = require("path");
7029
7111
  init_paths();
7030
7112
  init_accounts();
7031
7113
  init_config();
@@ -7403,11 +7485,11 @@ async function syncCliForTarget(accountId) {
7403
7485
  }
7404
7486
  applyConnectedTeamToCli(team);
7405
7487
  }
7406
- var import_node_fs20, brightsyAdapter;
7488
+ var import_node_fs21, brightsyAdapter;
7407
7489
  var init_brightsy = __esm({
7408
7490
  "src/agents/brightsy.ts"() {
7409
7491
  "use strict";
7410
- import_node_fs20 = require("fs");
7492
+ import_node_fs21 = require("fs");
7411
7493
  init_run();
7412
7494
  init_connected_teams();
7413
7495
  init_config();
@@ -7422,7 +7504,7 @@ var init_brightsy = __esm({
7422
7504
  async detect() {
7423
7505
  const brightsy = resolveAgentExecutable("brightsy");
7424
7506
  if (brightsy !== "brightsy") {
7425
- if (!(0, import_node_fs20.existsSync)(brightsy)) {
7507
+ if (!(0, import_node_fs21.existsSync)(brightsy)) {
7426
7508
  return {
7427
7509
  agent: "brightsy",
7428
7510
  installed: false,
@@ -7598,9 +7680,9 @@ function toolDescription(name, input) {
7598
7680
  if (/connectedAgentRequest/i.test(name)) {
7599
7681
  return str2(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
7600
7682
  }
7601
- if (desc && kind) return `${kind}: ${desc}`;
7602
- if (desc) return desc;
7603
- return "Subagent";
7683
+ if (desc && kind) return `${kind}: ${desc}${subagentLiveSuffix(input)}`;
7684
+ if (desc) return `${desc}${subagentLiveSuffix(input)}`;
7685
+ return `Subagent${subagentLiveSuffix(input)}`;
7604
7686
  }
7605
7687
  if (/^(create|update)_artifact$/i.test(name.replace(/^mcp__[^_]+__/, ""))) {
7606
7688
  return str2(input?.title) ? `Artifact ${str2(input?.title)}` : "Artifact";
@@ -7625,13 +7707,148 @@ function toolDescription(name, input) {
7625
7707
  }
7626
7708
  if (/grep/i.test(name)) return "Search files";
7627
7709
  if (/glob/i.test(name)) return "Find files";
7710
+ const compact = n.replace(/[_-]/g, "");
7711
+ if (/^taskoutput$/i.test(compact)) {
7712
+ return str2(input.task_id) ? `Wait for ${str2(input.task_id)}` : "Wait for background task";
7713
+ }
7714
+ if (/^taskstop$/i.test(compact)) {
7715
+ return str2(input.task_id) ? `Stop ${str2(input.task_id)}` : "Stop background task";
7716
+ }
7717
+ if (/^monitor$/i.test(compact)) {
7718
+ const command = str2(input.command);
7719
+ return command ? `Watch ${command.length > 48 ? `${command.slice(0, 45)}\u2026` : command}` : "Watch command";
7720
+ }
7628
7721
  return n;
7629
7722
  }
7723
+ function subagentLiveSuffix(input) {
7724
+ if (!input) return "";
7725
+ const bits = [];
7726
+ const status = str2(input.live_status);
7727
+ if (status && !/^runn(ing)?$|^working$/i.test(status)) bits.push(status);
7728
+ if (typeof input.live_tool_uses === "number") bits.push(`${input.live_tool_uses} tools`);
7729
+ if (typeof input.live_duration_ms === "number") {
7730
+ bits.push(`${Math.max(0, Math.round(Number(input.live_duration_ms) / 1e3))}s`);
7731
+ }
7732
+ const last = str2(input.live_last_tool);
7733
+ if (last) bits.push(last);
7734
+ return bits.length ? ` \xB7 ${bits.join(" \xB7 ")}` : "";
7735
+ }
7630
7736
  function isSubagentToolName(name) {
7631
7737
  const n = (name ?? "").trim();
7632
7738
  if (/^(task|agent|spawn_agent)$/i.test(n)) return true;
7633
7739
  return /connectedAgentRequest/i.test(n);
7634
7740
  }
7741
+ function isPollWrapperToolName(name) {
7742
+ const n = (name ?? "").replace(/[_-]/g, "");
7743
+ return /^(taskoutput|taskstop|sleep)$/i.test(n);
7744
+ }
7745
+ function lastTextPart(parts, type) {
7746
+ for (let i = parts.length - 1; i >= 0; i--) {
7747
+ const p = parts[i];
7748
+ if (p.type === type && p.text.trim()) return p.text.trim();
7749
+ }
7750
+ return "";
7751
+ }
7752
+ function toolLabel(tool) {
7753
+ return tool.description || toolDescription(tool.name, tool.input) || tool.name;
7754
+ }
7755
+ function fileBasename(path2) {
7756
+ const parts = path2.replace(/\/$/, "").split(/[/\\]/);
7757
+ return parts[parts.length - 1] || path2;
7758
+ }
7759
+ function classifyTool(name) {
7760
+ const compact = name.replace(/^mcp__[^_]+__/, "").replace(/[_-]/g, "");
7761
+ if (/bash|shell|terminal|^zsh$|^sh$/i.test(compact)) return "shell";
7762
+ if (/grep|glob|search|ripgrep|findfiles|semsearch/i.test(compact)) return "search";
7763
+ if (/^(read|cat)$/i.test(compact) || /^read/i.test(compact)) return "read";
7764
+ if (/edit|write|apply|strreplace|multiedit|updatefile|createfile/i.test(compact)) {
7765
+ return "edit";
7766
+ }
7767
+ return "other";
7768
+ }
7769
+ function toolActivityLine(parts) {
7770
+ const tools = parts.filter((p) => {
7771
+ if (p.type !== "tool" || p.parentId) return false;
7772
+ if (isPollWrapperToolName(p.name)) return false;
7773
+ if (/present_plan$/i.test(p.name ?? "")) return false;
7774
+ if (/ask_user|AskUserQuestion/i.test(p.name ?? "")) return false;
7775
+ return true;
7776
+ });
7777
+ if (tools.length === 0) return null;
7778
+ const edited = [];
7779
+ let reads = 0;
7780
+ let searches = 0;
7781
+ let shells = 0;
7782
+ let others = 0;
7783
+ let additions = 0;
7784
+ let deletions = 0;
7785
+ for (const tool of tools) {
7786
+ const kind = classifyTool(tool.name);
7787
+ if (kind === "edit") {
7788
+ const path2 = tool.filePath ?? toolFilePath(tool.input);
7789
+ edited.push({
7790
+ name: path2 ? fileBasename(path2) : tool.name,
7791
+ running: tool.status === "running"
7792
+ });
7793
+ } else if (kind === "read") reads += 1;
7794
+ else if (kind === "search") searches += 1;
7795
+ else if (kind === "shell") shells += 1;
7796
+ else others += 1;
7797
+ if (typeof tool.additions === "number") additions += tool.additions;
7798
+ if (typeof tool.deletions === "number") deletions += tool.deletions;
7799
+ }
7800
+ const bits = [];
7801
+ const editing = edited.filter((e) => e.running);
7802
+ const editedDone = edited.filter((e) => !e.running);
7803
+ if (editing.length === 1) bits.push(`Editing ${editing[0].name}`);
7804
+ else if (editing.length > 1) bits.push(`Editing ${editing.length} files`);
7805
+ if (editedDone.length === 1) bits.push(`${editing.length ? "edited" : "Edited"} ${editedDone[0].name}`);
7806
+ else if (editedDone.length > 1) {
7807
+ bits.push(`${editing.length ? "edited" : "Edited"} ${editedDone.length} files`);
7808
+ }
7809
+ if (reads === 1) bits.push("explored 1 file");
7810
+ else if (reads > 1) bits.push(`explored ${reads} files`);
7811
+ if (searches === 1) bits.push("1 search");
7812
+ else if (searches > 1) bits.push(`${searches} searches`);
7813
+ if (shells === 1) bits.push("ran 1 command");
7814
+ else if (shells > 1) bits.push(`ran ${shells} commands`);
7815
+ if (others === 1) bits.push("1 tool");
7816
+ else if (others > 1) bits.push(`${others} tools`);
7817
+ if (bits.length === 0) return null;
7818
+ return { text: bits.join(", "), additions, deletions };
7819
+ }
7820
+ function liveActivitySummary(parts, opts) {
7821
+ if (opts?.queued && parts.length === 0) {
7822
+ return "Queued \u2014 waiting for a slot";
7823
+ }
7824
+ const tools = parts.filter((p) => p.type === "tool");
7825
+ const runningSubs = tools.filter(
7826
+ (t) => t.status === "running" && !t.parentId && isSubagentToolName(t.name)
7827
+ );
7828
+ const runningNested = [...tools].reverse().find((t) => t.status === "running" && t.parentId && !isPollWrapperToolName(t.name));
7829
+ const runningTop = [...tools].reverse().find(
7830
+ (t) => t.status === "running" && !t.parentId && !isPollWrapperToolName(t.name) && !isSubagentToolName(t.name)
7831
+ );
7832
+ const runningPoll = [...tools].reverse().find((t) => t.status === "running" && isPollWrapperToolName(t.name));
7833
+ const thinking = lastTextPart(parts, "thinking");
7834
+ const text4 = lastTextPart(parts, "text");
7835
+ if (runningSubs.length > 0) {
7836
+ const heads = runningSubs.map(toolLabel);
7837
+ const head = runningSubs.length === 1 ? heads[0] : `${runningSubs.length} subagents \xB7 ${heads.slice(0, 2).join(" \xB7 ")}`;
7838
+ if (runningNested) return `${head} \xB7 ${toolLabel(runningNested)}`;
7839
+ return head;
7840
+ }
7841
+ if (runningTop) return toolLabel(runningTop);
7842
+ if (runningPoll) return toolLabel(runningPoll);
7843
+ if (thinking) return thinking.length > 96 ? `\u2026${thinking.slice(-96)}` : thinking;
7844
+ if (text4) return "Writing reply\u2026";
7845
+ const last = [...tools].reverse().find((t) => !isPollWrapperToolName(t.name)) ?? tools.at(-1);
7846
+ if (last) {
7847
+ const label = toolLabel(last);
7848
+ return last.status === "running" ? label : `Finished ${label}`;
7849
+ }
7850
+ return "Working\u2026";
7851
+ }
7635
7852
  function messagePartParentId(part) {
7636
7853
  if ("parentId" in part && typeof part.parentId === "string" && part.parentId.trim()) {
7637
7854
  return part.parentId;
@@ -7717,6 +7934,25 @@ function applyAgentEvent(parts, event) {
7717
7934
  const data = event.data;
7718
7935
  if (!data) return parts;
7719
7936
  const next = [...parts];
7937
+ if (event.replace) {
7938
+ for (let i = next.length - 1; i >= 0; i--) {
7939
+ const prev = next[i];
7940
+ if (prev?.type === "thinking" && sameParentId(prev.parentId, event.parentId)) {
7941
+ next[i] = {
7942
+ type: "thinking",
7943
+ text: data,
7944
+ ...event.parentId ? { parentId: event.parentId } : {}
7945
+ };
7946
+ return next;
7947
+ }
7948
+ }
7949
+ next.push({
7950
+ type: "thinking",
7951
+ text: data,
7952
+ ...event.parentId ? { parentId: event.parentId } : {}
7953
+ });
7954
+ return next;
7955
+ }
7720
7956
  const last = next[next.length - 1];
7721
7957
  if (last?.type === "thinking" && sameParentId(last.parentId, event.parentId)) {
7722
7958
  next[next.length - 1] = {
@@ -7740,14 +7976,18 @@ function applyAgentEvent(parts, event) {
7740
7976
  if (existing >= 0) {
7741
7977
  const prev = parts[existing];
7742
7978
  const next = [...parts];
7743
- const mergedInput = input && Object.keys(input).length > 0 ? input : prev.input ?? input;
7979
+ const mergedInput = {
7980
+ ...prev.input ?? {},
7981
+ ...input ?? {}
7982
+ };
7983
+ const mergedRecord = Object.keys(mergedInput).length > 0 ? mergedInput : void 0;
7744
7984
  next[existing] = {
7745
7985
  ...prev,
7746
7986
  name: event.name || prev.name,
7747
- input: mergedInput,
7748
- description: toolDescription(event.name || prev.name, mergedInput),
7749
- detail: toolDetail(event.name || prev.name, mergedInput) ?? prev.detail,
7750
- filePath: toolFilePath(mergedInput) ?? prev.filePath,
7987
+ input: mergedRecord,
7988
+ description: toolDescription(event.name || prev.name, mergedRecord),
7989
+ detail: toolDetail(event.name || prev.name, mergedRecord) ?? prev.detail,
7990
+ filePath: toolFilePath(mergedRecord) ?? prev.filePath,
7751
7991
  additions: diff.additions ?? prev.additions,
7752
7992
  deletions: diff.deletions ?? prev.deletions,
7753
7993
  parentId: event.parentId ?? prev.parentId
@@ -7865,47 +8105,68 @@ function electronResourcesPath() {
7865
8105
  function packagedCursorRuntimeDir() {
7866
8106
  const resources = electronResourcesPath();
7867
8107
  if (!resources) return null;
7868
- const dir = (0, import_node_path22.join)(resources, "cursor-runtime");
7869
- if (!(0, import_node_fs21.existsSync)((0, import_node_path22.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
8108
+ const dir = (0, import_node_path23.join)(resources, "cursor-runtime");
8109
+ if (!(0, import_node_fs22.existsSync)((0, import_node_path23.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
7870
8110
  return dir;
7871
8111
  }
7872
8112
  function packagedCursorRunnerPath() {
7873
8113
  const dir = packagedCursorRuntimeDir();
7874
- return dir ? (0, import_node_path22.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
8114
+ return dir ? (0, import_node_path23.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
7875
8115
  }
7876
8116
  function packagedMcpDir() {
7877
8117
  const resources = electronResourcesPath();
7878
8118
  if (!resources) return null;
7879
- const dir = (0, import_node_path22.join)(resources, "sideboard-mcp");
7880
- if (!(0, import_node_fs21.existsSync)((0, import_node_path22.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
8119
+ const dir = (0, import_node_path23.join)(resources, "sideboard-mcp");
8120
+ if (!(0, import_node_fs22.existsSync)((0, import_node_path23.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
7881
8121
  return dir;
7882
8122
  }
7883
8123
  function packagedMcpStdioPath() {
7884
8124
  const dir = packagedMcpDir();
7885
- return dir ? (0, import_node_path22.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
8125
+ return dir ? (0, import_node_path23.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
7886
8126
  }
7887
8127
  function packagedBundledNodePath() {
7888
8128
  const resources = electronResourcesPath();
7889
8129
  if (!resources) return null;
7890
- const bin = (0, import_node_path22.join)(resources, "node", "bin", "node");
7891
- if (!(0, import_node_fs21.existsSync)(bin)) return null;
8130
+ const bin = (0, import_node_path23.join)(resources, "node", "bin", "node");
8131
+ if (!(0, import_node_fs22.existsSync)(bin)) return null;
7892
8132
  return bin;
7893
8133
  }
7894
8134
  function packagedCursorRipgrepCandidate(platformPkg, binName) {
7895
8135
  const dir = packagedCursorRuntimeDir();
7896
8136
  if (!dir) return null;
7897
- return (0, import_node_path22.join)(dir, "node_modules", platformPkg, "bin", binName);
8137
+ return (0, import_node_path23.join)(dir, "node_modules", platformPkg, "bin", binName);
7898
8138
  }
7899
- var import_node_fs21, import_node_path22;
8139
+ var import_node_fs22, import_node_path23;
7900
8140
  var init_packaged_runtime = __esm({
7901
8141
  "src/agents/packaged-runtime.ts"() {
7902
8142
  "use strict";
7903
- import_node_fs21 = require("fs");
7904
- import_node_path22 = require("path");
8143
+ import_node_fs22 = require("fs");
8144
+ import_node_path23 = require("path");
7905
8145
  }
7906
8146
  });
7907
8147
 
7908
8148
  // src/agents/node-launch.ts
8149
+ function withMaxOldSpaceSize(nodeOptions, heapMb) {
8150
+ const existing = (nodeOptions ?? "").trim();
8151
+ const match = MAX_OLD_SPACE_FLAG.exec(existing);
8152
+ if (match) {
8153
+ const current = match[2] ? Number(match[2]) : 0;
8154
+ if (Number.isFinite(current) && current >= heapMb) return existing;
8155
+ return existing.replace(MAX_OLD_SPACE_FLAG, ` --max-old-space-size=${heapMb}`).trim();
8156
+ }
8157
+ return existing ? `${existing} --max-old-space-size=${heapMb}` : `--max-old-space-size=${heapMb}`;
8158
+ }
8159
+ function applyAgentRunnerHeapEnv(env) {
8160
+ env.NODE_OPTIONS = withMaxOldSpaceSize(
8161
+ env.NODE_OPTIONS,
8162
+ AGENT_RUNNER_MAX_OLD_SPACE_MB
8163
+ );
8164
+ }
8165
+ function envWithAgentHeap(env) {
8166
+ const next = { ...env };
8167
+ applyAgentRunnerHeapEnv(next);
8168
+ return next;
8169
+ }
7909
8170
  function isAsarPath(filePath) {
7910
8171
  if (/\.asar\.unpacked([/\\]|$)/.test(filePath)) return false;
7911
8172
  return /\.asar([/\\]|$)/.test(filePath);
@@ -7914,7 +8175,7 @@ function unpackedAsarPath(filePath) {
7914
8175
  if (!isAsarPath(filePath)) return null;
7915
8176
  const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
7916
8177
  if (unpacked === filePath) return null;
7917
- return (0, import_node_fs22.existsSync)(unpacked) ? unpacked : null;
8178
+ return (0, import_node_fs23.existsSync)(unpacked) ? unpacked : null;
7918
8179
  }
7919
8180
  function nodeReadableScriptPath(scriptPath) {
7920
8181
  return unpackedAsarPath(scriptPath) ?? scriptPath;
@@ -7954,37 +8215,37 @@ function pickPreferredNode(candidates) {
7954
8215
  return best;
7955
8216
  }
7956
8217
  function versionDirNodeBins(root, toBin) {
7957
- if (!(0, import_node_fs22.existsSync)(root)) return [];
8218
+ if (!(0, import_node_fs23.existsSync)(root)) return [];
7958
8219
  try {
7959
- return (0, import_node_fs22.readdirSync)(root).map(toBin);
8220
+ return (0, import_node_fs23.readdirSync)(root).map(toBin);
7960
8221
  } catch {
7961
8222
  return [];
7962
8223
  }
7963
8224
  }
7964
8225
  function defaultNodeBinCandidates(home = (0, import_node_os7.homedir)()) {
7965
8226
  const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
7966
- (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path23.join)(prefix, "opt", `node@${major}`, "bin", "node"))
8227
+ (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path24.join)(prefix, "opt", `node@${major}`, "bin", "node"))
7967
8228
  );
7968
8229
  return [
7969
8230
  ...kegs,
7970
8231
  "/opt/homebrew/bin/node",
7971
8232
  "/usr/local/bin/node",
7972
- (0, import_node_path23.join)(home, ".local/share/fnm/aliases/default/bin/node"),
7973
- (0, import_node_path23.join)(home, ".nvm/current/bin/node"),
7974
- (0, import_node_path23.join)(home, ".volta/bin/node"),
7975
- (0, import_node_path23.join)(home, ".asdf/shims/node"),
7976
- (0, import_node_path23.join)(home, ".local/share/mise/shims/node"),
8233
+ (0, import_node_path24.join)(home, ".local/share/fnm/aliases/default/bin/node"),
8234
+ (0, import_node_path24.join)(home, ".nvm/current/bin/node"),
8235
+ (0, import_node_path24.join)(home, ".volta/bin/node"),
8236
+ (0, import_node_path24.join)(home, ".asdf/shims/node"),
8237
+ (0, import_node_path24.join)(home, ".local/share/mise/shims/node"),
7977
8238
  ...versionDirNodeBins(
7978
- (0, import_node_path23.join)(home, ".nvm", "versions", "node"),
7979
- (name) => (0, import_node_path23.join)(home, ".nvm", "versions", "node", name, "bin", "node")
8239
+ (0, import_node_path24.join)(home, ".nvm", "versions", "node"),
8240
+ (name) => (0, import_node_path24.join)(home, ".nvm", "versions", "node", name, "bin", "node")
7980
8241
  ),
7981
8242
  ...versionDirNodeBins(
7982
- (0, import_node_path23.join)(home, ".local/share/fnm", "node-versions"),
7983
- (name) => (0, import_node_path23.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
8243
+ (0, import_node_path24.join)(home, ".local/share/fnm", "node-versions"),
8244
+ (name) => (0, import_node_path24.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
7984
8245
  ),
7985
8246
  ...versionDirNodeBins(
7986
- (0, import_node_path23.join)(home, ".volta", "tools", "image", "node"),
7987
- (name) => (0, import_node_path23.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
8247
+ (0, import_node_path24.join)(home, ".volta", "tools", "image", "node"),
8248
+ (name) => (0, import_node_path24.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
7988
8249
  )
7989
8250
  ];
7990
8251
  }
@@ -7993,10 +8254,10 @@ function uniqueExistingNodeBins(paths) {
7993
8254
  const out = [];
7994
8255
  for (const raw of paths) {
7995
8256
  const p = raw.trim();
7996
- if (!p || !(0, import_node_fs22.existsSync)(p) || isElectronLikeCommand(p)) continue;
8257
+ if (!p || !(0, import_node_fs23.existsSync)(p) || isElectronLikeCommand(p)) continue;
7997
8258
  let key = p;
7998
8259
  try {
7999
- key = (0, import_node_fs22.realpathSync)(p);
8260
+ key = (0, import_node_fs23.realpathSync)(p);
8000
8261
  } catch {
8001
8262
  continue;
8002
8263
  }
@@ -8041,13 +8302,21 @@ async function findSystemNode() {
8041
8302
  function applyNodeLaunch(launch, args) {
8042
8303
  const readableArgs = args.map(nodeReadableScriptPath);
8043
8304
  if (!launch.env.ELECTRON_RUN_AS_NODE) {
8044
- return { file: launch.file, args: readableArgs, env: launch.env };
8305
+ return {
8306
+ file: launch.file,
8307
+ args: readableArgs,
8308
+ env: envWithAgentHeap(launch.env)
8309
+ };
8045
8310
  }
8046
8311
  const wrapped = wrapElectronAsNodeLaunch(launch.file, readableArgs);
8047
8312
  if (process.platform === "win32") {
8048
- return { file: wrapped.file, args: wrapped.args, env: launch.env };
8313
+ return {
8314
+ file: wrapped.file,
8315
+ args: wrapped.args,
8316
+ env: envWithAgentHeap(launch.env)
8317
+ };
8049
8318
  }
8050
- const env = { ...launch.env };
8319
+ const env = envWithAgentHeap(launch.env);
8051
8320
  delete env.ELECTRON_RUN_AS_NODE;
8052
8321
  return { file: wrapped.file, args: wrapped.args, env };
8053
8322
  }
@@ -8068,16 +8337,18 @@ async function resolveNodeLaunch(scriptPath) {
8068
8337
  env: { ELECTRON_RUN_AS_NODE: "1" }
8069
8338
  };
8070
8339
  }
8071
- var import_node_fs22, import_node_os7, import_node_path23, PREFERRED_LTS_MAJORS;
8340
+ var import_node_fs23, import_node_os7, import_node_path24, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
8072
8341
  var init_node_launch = __esm({
8073
8342
  "src/agents/node-launch.ts"() {
8074
8343
  "use strict";
8075
- import_node_fs22 = require("fs");
8344
+ import_node_fs23 = require("fs");
8076
8345
  import_node_os7 = require("os");
8077
- import_node_path23 = require("path");
8346
+ import_node_path24 = require("path");
8078
8347
  init_nested_electron_env();
8079
8348
  init_run();
8080
8349
  init_packaged_runtime();
8350
+ AGENT_RUNNER_MAX_OLD_SPACE_MB = 8192;
8351
+ MAX_OLD_SPACE_FLAG = /(?:^|\s)(--max[-_]old[-_]space[-_]size)(?:[= ](\d+))?(?=\s|$)/;
8081
8352
  PREFERRED_LTS_MAJORS = [24, 22, 20];
8082
8353
  }
8083
8354
  });
@@ -8165,37 +8436,37 @@ function corePackageDir() {
8165
8436
  try {
8166
8437
  const url = import_meta.url;
8167
8438
  if (typeof url === "string" && url.length > 0) {
8168
- return (0, import_node_path24.dirname)((0, import_node_url.fileURLToPath)(url));
8439
+ return (0, import_node_path25.dirname)((0, import_node_url.fileURLToPath)(url));
8169
8440
  }
8170
8441
  } catch {
8171
8442
  }
8172
8443
  try {
8173
- const req = (0, import_node_module.createRequire)((0, import_node_path24.join)(process.cwd(), "package.json"));
8174
- return (0, import_node_path24.dirname)(req.resolve("@sideboard-ai/core"));
8444
+ const req = (0, import_node_module.createRequire)((0, import_node_path25.join)(process.cwd(), "package.json"));
8445
+ return (0, import_node_path25.dirname)(req.resolve("@sideboard-ai/core"));
8175
8446
  } catch {
8176
8447
  return process.cwd();
8177
8448
  }
8178
8449
  }
8179
8450
  function findSideboardMcpJsEntry() {
8180
8451
  const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
8181
- if (override && (0, import_node_fs23.existsSync)(override)) return override;
8452
+ if (override && (0, import_node_fs24.existsSync)(override)) return override;
8182
8453
  const packaged = packagedMcpStdioPath();
8183
8454
  if (packaged) return packaged;
8184
8455
  let dir = corePackageDir();
8185
8456
  for (let i = 0; i < 10; i++) {
8186
8457
  const candidates = [
8187
- (0, import_node_path24.join)(dir, "mcp/run-stdio.js"),
8188
- (0, import_node_path24.join)(dir, "mcp/run-stdio.cjs"),
8189
- (0, import_node_path24.join)(dir, "dist/mcp/run-stdio.js"),
8190
- (0, import_node_path24.join)(dir, "dist/mcp/run-stdio.cjs"),
8191
- (0, import_node_path24.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
8192
- (0, import_node_path24.join)(dir, "packages/cli/dist/index.js"),
8193
- (0, import_node_path24.join)(dir, "cli/dist/index.js")
8458
+ (0, import_node_path25.join)(dir, "mcp/run-stdio.js"),
8459
+ (0, import_node_path25.join)(dir, "mcp/run-stdio.cjs"),
8460
+ (0, import_node_path25.join)(dir, "dist/mcp/run-stdio.js"),
8461
+ (0, import_node_path25.join)(dir, "dist/mcp/run-stdio.cjs"),
8462
+ (0, import_node_path25.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
8463
+ (0, import_node_path25.join)(dir, "packages/cli/dist/index.js"),
8464
+ (0, import_node_path25.join)(dir, "cli/dist/index.js")
8194
8465
  ];
8195
8466
  for (const p of candidates) {
8196
- if ((0, import_node_fs23.existsSync)(p) && !isAsarPath(p)) return p;
8467
+ if ((0, import_node_fs24.existsSync)(p) && !isAsarPath(p)) return p;
8197
8468
  }
8198
- const parent = (0, import_node_path24.dirname)(dir);
8469
+ const parent = (0, import_node_path25.dirname)(dir);
8199
8470
  if (parent === dir) break;
8200
8471
  dir = parent;
8201
8472
  }
@@ -8243,6 +8514,7 @@ async function buildInjectedMcpServers(opts) {
8243
8514
  );
8244
8515
  } catch {
8245
8516
  }
8517
+ applyAgentRunnerHeapEnv(sideboard.env);
8246
8518
  servers.push(sideboard);
8247
8519
  }
8248
8520
  if (opts.includeBrightsy && isBrightsyConnected()) {
@@ -8336,22 +8608,22 @@ function writeMcpServersConfig(servers) {
8336
8608
  ...env ? { env } : {}
8337
8609
  };
8338
8610
  }
8339
- const dir = (0, import_node_fs23.mkdtempSync)((0, import_node_path24.join)((0, import_node_os8.tmpdir)(), "sideboard-mcp-"));
8340
- const cfgPath = (0, import_node_path24.join)(dir, "mcp.json");
8341
- (0, import_node_fs23.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
8611
+ const dir = (0, import_node_fs24.mkdtempSync)((0, import_node_path25.join)((0, import_node_os8.tmpdir)(), "sideboard-mcp-"));
8612
+ const cfgPath = (0, import_node_path25.join)(dir, "mcp.json");
8613
+ (0, import_node_fs24.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
8342
8614
  return cfgPath;
8343
8615
  }
8344
8616
  async function writeInjectedMcpConfig(opts) {
8345
8617
  return writeMcpServersConfig(await buildInjectedMcpServers(opts));
8346
8618
  }
8347
- var import_node_fs23, import_node_module, import_node_os8, import_node_path24, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
8619
+ var import_node_fs24, import_node_module, import_node_os8, import_node_path25, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
8348
8620
  var init_injected_mcp = __esm({
8349
8621
  "src/agents/injected-mcp.ts"() {
8350
8622
  "use strict";
8351
- import_node_fs23 = require("fs");
8623
+ import_node_fs24 = require("fs");
8352
8624
  import_node_module = require("module");
8353
8625
  import_node_os8 = require("os");
8354
- import_node_path24 = require("path");
8626
+ import_node_path25 = require("path");
8355
8627
  import_node_url = require("url");
8356
8628
  init_run();
8357
8629
  init_config();
@@ -8529,6 +8801,80 @@ function claudeParentToolUseId(obj) {
8529
8801
  }
8530
8802
  return void 0;
8531
8803
  }
8804
+ function claudeString(obj, key) {
8805
+ const v = obj[key];
8806
+ return typeof v === "string" && v.trim() ? v.trim() : void 0;
8807
+ }
8808
+ function eventsFromClaudeSystem(obj) {
8809
+ const subtype = claudeString(obj, "subtype") ?? "";
8810
+ const parentId = claudeParentToolUseId(obj);
8811
+ if (subtype === "init") {
8812
+ if (parentId) return null;
8813
+ const sid = claudeString(obj, "session_id");
8814
+ return sid ? { type: "session_id", data: sid } : null;
8815
+ }
8816
+ if (subtype === "task_started") {
8817
+ const id = claudeString(obj, "tool_use_id") ?? claudeString(obj, "task_id");
8818
+ if (!id) return null;
8819
+ const description = claudeString(obj, "description");
8820
+ const taskType = claudeString(obj, "task_type");
8821
+ const prompt = claudeString(obj, "prompt");
8822
+ return withEventParentId(
8823
+ {
8824
+ type: "tool_use",
8825
+ id,
8826
+ name: taskType || "Agent",
8827
+ input: {
8828
+ ...description ? { description } : {},
8829
+ ...prompt ? { prompt } : {},
8830
+ ...claudeString(obj, "task_id") ? { task_id: claudeString(obj, "task_id") } : {}
8831
+ }
8832
+ },
8833
+ parentId
8834
+ );
8835
+ }
8836
+ if (subtype === "task_notification") {
8837
+ const id = claudeString(obj, "tool_use_id") ?? claudeString(obj, "task_id") ?? parentId;
8838
+ if (!id) return null;
8839
+ const status = claudeString(obj, "status") ?? "working";
8840
+ const tools = typeof obj.tool_uses === "number" ? obj.tool_uses : void 0;
8841
+ const durationMs = typeof obj.duration_ms === "number" ? obj.duration_ms : void 0;
8842
+ const lastTool = claudeString(obj, "last_tool") ?? claudeString(obj, "current_tool") ?? claudeString(obj, "tool");
8843
+ const snapshot = [
8844
+ status,
8845
+ tools != null ? `${tools} tools` : null,
8846
+ durationMs != null ? `${Math.round(durationMs / 1e3)}s` : null,
8847
+ lastTool
8848
+ ].filter((bit) => Boolean(bit)).join(" \xB7 ");
8849
+ return [
8850
+ {
8851
+ type: "tool_use",
8852
+ id,
8853
+ name: claudeString(obj, "task_type") || "Agent",
8854
+ input: {
8855
+ live_status: status,
8856
+ ...tools != null ? { live_tool_uses: tools } : {},
8857
+ ...durationMs != null ? { live_duration_ms: durationMs } : {},
8858
+ ...lastTool ? { live_last_tool: lastTool } : {}
8859
+ }
8860
+ },
8861
+ withEventParentId(
8862
+ { type: "thinking", data: snapshot, replace: true },
8863
+ id
8864
+ )
8865
+ ];
8866
+ }
8867
+ if (subtype === "api_retry") {
8868
+ const attempt = obj.attempt;
8869
+ const max = obj.max_retries;
8870
+ const delay = obj.retry_delay_ms;
8871
+ return {
8872
+ type: "thinking",
8873
+ data: `API retry ${attempt ?? "?"}/${max ?? "?"}${typeof delay === "number" ? ` (wait ${delay}ms)` : ""}`
8874
+ };
8875
+ }
8876
+ return null;
8877
+ }
8532
8878
  function parseIssuesJson(raw) {
8533
8879
  const text4 = raw.trim();
8534
8880
  const candidates = [text4];
@@ -8554,11 +8900,11 @@ function parseIssuesJson(raw) {
8554
8900
  }
8555
8901
  return [];
8556
8902
  }
8557
- var import_node_fs24, BASE_ALLOWED_TOOLS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
8903
+ var import_node_fs25, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
8558
8904
  var init_claude = __esm({
8559
8905
  "src/agents/claude.ts"() {
8560
8906
  "use strict";
8561
- import_node_fs24 = require("fs");
8907
+ import_node_fs25 = require("fs");
8562
8908
  init_run();
8563
8909
  init_app_settings();
8564
8910
  init_claude_mcp();
@@ -8578,8 +8924,14 @@ var init_claude = __esm({
8578
8924
  "WebSearch",
8579
8925
  // Subagents (Claude Code v2.1.63 renamed Task → Agent; allow both).
8580
8926
  "Task",
8581
- "Agent"
8927
+ "Agent",
8928
+ "TaskOutput",
8929
+ "TaskStop",
8930
+ "EnterWorktree",
8931
+ "ExitWorktree",
8932
+ "Skill"
8582
8933
  ];
8934
+ CLAUDE_PRINT_BG_WAIT_CEILING_MS = 72e5;
8583
8935
  CLAUDE_CHROME_ALLOWED_TOOLS = [
8584
8936
  "mcp__claude-in-chrome",
8585
8937
  "mcp__claude-in-chrome__*",
@@ -8591,7 +8943,7 @@ var init_claude = __esm({
8591
8943
  async detect() {
8592
8944
  const claude = resolveClaudeExecutable();
8593
8945
  if (claude !== "claude") {
8594
- if (!(0, import_node_fs24.existsSync)(claude)) {
8946
+ if (!(0, import_node_fs25.existsSync)(claude)) {
8595
8947
  return {
8596
8948
  agent: "claude",
8597
8949
  installed: false,
@@ -8708,7 +9060,12 @@ var init_claude = __esm({
8708
9060
  stdin: useStdin ? `${promptText}
8709
9061
  ` : void 0,
8710
9062
  // Nested Task/Agent thinking+text in stream-json (Claude Code 2.1.211+).
8711
- env: { CLAUDE_CODE_FORWARD_SUBAGENT_TEXT: "1" }
9063
+ // Raise the -p background-agent wait so long TaskOutput polls are not
9064
+ // abandoned at Claude Code’s 10-minute default.
9065
+ env: {
9066
+ CLAUDE_CODE_FORWARD_SUBAGENT_TEXT: "1",
9067
+ CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS: process.env.CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS ?? String(CLAUDE_PRINT_BG_WAIT_CEILING_MS)
9068
+ }
8712
9069
  };
8713
9070
  },
8714
9071
  parseEvent(line) {
@@ -8716,13 +9073,8 @@ var init_claude = __esm({
8716
9073
  if (!trimmed) return null;
8717
9074
  try {
8718
9075
  const obj = JSON.parse(trimmed);
8719
- if (obj.type === "system" && obj.subtype === "init") {
8720
- const sid = obj.session_id;
8721
- if (typeof sid === "string") return { type: "session_id", data: sid };
8722
- return null;
8723
- }
8724
- if (obj.type === "system" && typeof obj.session_id === "string") {
8725
- return { type: "session_id", data: obj.session_id };
9076
+ if (obj.type === "system") {
9077
+ return eventsFromClaudeSystem(obj);
8726
9078
  }
8727
9079
  if (obj.type === "assistant" || obj.type === "user") {
8728
9080
  const parentId = claudeParentToolUseId(obj);
@@ -8842,7 +9194,7 @@ async function listCodexModels() {
8842
9194
  if (codex === "codex") {
8843
9195
  const which = await run("which", ["codex"], { reject: false });
8844
9196
  if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
8845
- } else if (!(0, import_node_fs25.existsSync)(codex)) {
9197
+ } else if (!(0, import_node_fs26.existsSync)(codex)) {
8846
9198
  return FALLBACK_CODEX_MODELS;
8847
9199
  }
8848
9200
  const listed = await run(codex, ["debug", "models"], { reject: false });
@@ -8877,12 +9229,12 @@ function usageFromCodex(usage) {
8877
9229
  }
8878
9230
  function codexConfigHasNetworkAccess() {
8879
9231
  const candidates = [
8880
- (0, import_node_path25.join)((0, import_node_os9.homedir)(), ".codex", "config.toml"),
8881
- (0, import_node_path25.join)((0, import_node_os9.homedir)(), ".config", "codex", "config.toml")
9232
+ (0, import_node_path26.join)((0, import_node_os9.homedir)(), ".codex", "config.toml"),
9233
+ (0, import_node_path26.join)((0, import_node_os9.homedir)(), ".config", "codex", "config.toml")
8882
9234
  ];
8883
9235
  for (const path2 of candidates) {
8884
- if (!(0, import_node_fs25.existsSync)(path2)) continue;
8885
- const text4 = (0, import_node_fs25.readFileSync)(path2, "utf8");
9236
+ if (!(0, import_node_fs26.existsSync)(path2)) continue;
9237
+ const text4 = (0, import_node_fs26.readFileSync)(path2, "utf8");
8886
9238
  if (/network_access\s*=\s*true/.test(text4)) return true;
8887
9239
  }
8888
9240
  return false;
@@ -8914,21 +9266,21 @@ function asRecord2(value) {
8914
9266
  return void 0;
8915
9267
  }
8916
9268
  function codexLooksAuthenticated() {
8917
- const authPath = (0, import_node_path25.join)((0, import_node_os9.homedir)(), ".codex", "auth.json");
8918
- if (!(0, import_node_fs25.existsSync)(authPath)) return false;
9269
+ const authPath = (0, import_node_path26.join)((0, import_node_os9.homedir)(), ".codex", "auth.json");
9270
+ if (!(0, import_node_fs26.existsSync)(authPath)) return false;
8919
9271
  try {
8920
- return (0, import_node_fs25.statSync)(authPath).size > 2;
9272
+ return (0, import_node_fs26.statSync)(authPath).size > 2;
8921
9273
  } catch {
8922
9274
  return false;
8923
9275
  }
8924
9276
  }
8925
- var import_node_fs25, import_node_os9, import_node_path25, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
9277
+ var import_node_fs26, import_node_os9, import_node_path26, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
8926
9278
  var init_codex = __esm({
8927
9279
  "src/agents/codex.ts"() {
8928
9280
  "use strict";
8929
- import_node_fs25 = require("fs");
9281
+ import_node_fs26 = require("fs");
8930
9282
  import_node_os9 = require("os");
8931
- import_node_path25 = require("path");
9283
+ import_node_path26 = require("path");
8932
9284
  init_run();
8933
9285
  init_app_settings();
8934
9286
  init_global_workspace();
@@ -8953,7 +9305,7 @@ var init_codex = __esm({
8953
9305
  async detect() {
8954
9306
  const codex = resolveAgentExecutable("codex");
8955
9307
  if (codex !== "codex") {
8956
- if (!(0, import_node_fs25.existsSync)(codex)) {
9308
+ if (!(0, import_node_fs26.existsSync)(codex)) {
8957
9309
  return {
8958
9310
  agent: "codex",
8959
9311
  installed: false,
@@ -9142,9 +9494,6 @@ var init_codex = __esm({
9142
9494
  if (sid && (type === "thread.started" || type === "session" || !type)) {
9143
9495
  return { type: "session_id", data: sid };
9144
9496
  }
9145
- if (sid && type.endsWith(".started")) {
9146
- return { type: "session_id", data: sid };
9147
- }
9148
9497
  if (type === "turn.completed" || type === "turn_completed") {
9149
9498
  const usage = usageFromCodex(obj.usage);
9150
9499
  return usage ? { type: "usage", data: usage, scope: "turn" } : null;
@@ -9392,21 +9741,21 @@ function platformRipgrepPackage() {
9392
9741
  }
9393
9742
  function usableRipgrepPath(candidate) {
9394
9743
  const raw = candidate?.trim();
9395
- if (!raw || !(0, import_node_path26.isAbsolute)(raw)) return null;
9744
+ if (!raw || !(0, import_node_path27.isAbsolute)(raw)) return null;
9396
9745
  const readable = nodeReadableScriptPath(raw);
9397
- if (!(0, import_node_fs26.existsSync)(readable) || isAsarPath(readable)) return null;
9746
+ if (!(0, import_node_fs27.existsSync)(readable) || isAsarPath(readable)) return null;
9398
9747
  return readable;
9399
9748
  }
9400
9749
  function walkForBundledRipgrep(startFile) {
9401
9750
  if (!startFile) return null;
9402
9751
  const pkg = platformRipgrepPackage();
9403
9752
  const name = rgBinaryName();
9404
- let dir = (0, import_node_path26.dirname)((0, import_node_path26.resolve)(startFile));
9405
- const root = (0, import_node_path26.parse)(dir).root;
9753
+ let dir = (0, import_node_path27.dirname)((0, import_node_path27.resolve)(startFile));
9754
+ const root = (0, import_node_path27.parse)(dir).root;
9406
9755
  while (dir !== root) {
9407
- const hit = usableRipgrepPath((0, import_node_path26.join)(dir, "node_modules", pkg, "bin", name));
9756
+ const hit = usableRipgrepPath((0, import_node_path27.join)(dir, "node_modules", pkg, "bin", name));
9408
9757
  if (hit) return hit;
9409
- const next = (0, import_node_path26.dirname)(dir);
9758
+ const next = (0, import_node_path27.dirname)(dir);
9410
9759
  if (next === dir) break;
9411
9760
  dir = next;
9412
9761
  }
@@ -9416,7 +9765,7 @@ function requireResolveBundledRipgrep(fromFile) {
9416
9765
  try {
9417
9766
  const req = (0, import_node_module2.createRequire)(fromFile);
9418
9767
  const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
9419
- return usableRipgrepPath((0, import_node_path26.join)((0, import_node_path26.dirname)(pkgJson), "bin", rgBinaryName()));
9768
+ return usableRipgrepPath((0, import_node_path27.join)((0, import_node_path27.dirname)(pkgJson), "bin", rgBinaryName()));
9420
9769
  } catch {
9421
9770
  return null;
9422
9771
  }
@@ -9429,24 +9778,24 @@ function resolveCursorRipgrepPath(opts) {
9429
9778
  packagedCursorRipgrepCandidate(platformRipgrepPackage(), rgBinaryName())
9430
9779
  );
9431
9780
  if (fromPackaged) return fromPackaged;
9432
- const start = opts?.startFile?.trim() || process.argv[1] || (0, import_node_url2.fileURLToPath)(import_meta2.url);
9781
+ const start = opts?.startFile?.trim() || process.argv[1] || // CJS bundle only — ESM has no __filename; argv[1] is the running script.
9782
+ // eslint-disable-next-line camelcase
9783
+ (typeof __filename !== "undefined" ? __filename : "");
9433
9784
  return walkForBundledRipgrep(start) ?? requireResolveBundledRipgrep(start);
9434
9785
  }
9435
9786
  function cursorRipgrepEnv(opts) {
9436
9787
  const path2 = resolveCursorRipgrepPath(opts);
9437
9788
  return path2 ? { [RIPGREP_ENV]: path2 } : {};
9438
9789
  }
9439
- var import_node_fs26, import_node_module2, import_node_path26, import_node_url2, import_meta2, RIPGREP_ENV;
9790
+ var import_node_fs27, import_node_module2, import_node_path27, RIPGREP_ENV;
9440
9791
  var init_cursor_ripgrep = __esm({
9441
9792
  "src/agents/cursor-ripgrep.ts"() {
9442
9793
  "use strict";
9443
- import_node_fs26 = require("fs");
9794
+ import_node_fs27 = require("fs");
9444
9795
  import_node_module2 = require("module");
9445
- import_node_path26 = require("path");
9446
- import_node_url2 = require("url");
9796
+ import_node_path27 = require("path");
9447
9797
  init_node_launch();
9448
9798
  init_packaged_runtime();
9449
- import_meta2 = {};
9450
9799
  RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
9451
9800
  }
9452
9801
  });
@@ -9490,11 +9839,11 @@ function entryDir() {
9490
9839
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
9491
9840
  if (cjsDir) return cjsDir;
9492
9841
  try {
9493
- return (0, import_node_path27.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
9842
+ return (0, import_node_path28.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
9494
9843
  } catch {
9495
9844
  try {
9496
9845
  const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
9497
- return (0, import_node_path27.dirname)(req.resolve("@sideboard-ai/core"));
9846
+ return (0, import_node_path28.dirname)(req.resolve("@sideboard-ai/core"));
9498
9847
  } catch {
9499
9848
  return process.cwd();
9500
9849
  }
@@ -9505,28 +9854,28 @@ function cursorRunnerPath() {
9505
9854
  if (packaged) return packaged;
9506
9855
  const root = entryDir();
9507
9856
  const candidates = [
9508
- (0, import_node_path27.join)(root, "agents", "cursor-runner.js"),
9509
- (0, import_node_path27.join)(root, "agents", "cursor-runner.cjs"),
9857
+ (0, import_node_path28.join)(root, "agents", "cursor-runner.js"),
9858
+ (0, import_node_path28.join)(root, "agents", "cursor-runner.cjs"),
9510
9859
  // If somehow resolved from package root instead of dist/
9511
- (0, import_node_path27.join)(root, "dist", "agents", "cursor-runner.js"),
9512
- (0, import_node_path27.join)(root, "dist", "agents", "cursor-runner.cjs"),
9860
+ (0, import_node_path28.join)(root, "dist", "agents", "cursor-runner.js"),
9861
+ (0, import_node_path28.join)(root, "dist", "agents", "cursor-runner.cjs"),
9513
9862
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
9514
- (0, import_node_path27.join)(root, "cursor-runner.ts"),
9515
- (0, import_node_path27.join)(root, "src", "agents", "cursor-runner.ts")
9863
+ (0, import_node_path28.join)(root, "cursor-runner.ts"),
9864
+ (0, import_node_path28.join)(root, "src", "agents", "cursor-runner.ts")
9516
9865
  ];
9517
9866
  for (const candidate of candidates) {
9518
- if ((0, import_node_fs27.existsSync)(candidate)) return candidate;
9867
+ if ((0, import_node_fs28.existsSync)(candidate)) return candidate;
9519
9868
  }
9520
9869
  return candidates[0];
9521
9870
  }
9522
- var import_node_fs27, import_node_module3, import_node_path27, import_node_url3, import_sdk, import_meta3, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
9871
+ var import_node_fs28, import_node_module3, import_node_path28, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
9523
9872
  var init_cursor = __esm({
9524
9873
  "src/agents/cursor.ts"() {
9525
9874
  "use strict";
9526
- import_node_fs27 = require("fs");
9875
+ import_node_fs28 = require("fs");
9527
9876
  import_node_module3 = require("module");
9528
- import_node_path27 = require("path");
9529
- import_node_url3 = require("url");
9877
+ import_node_path28 = require("path");
9878
+ import_node_url2 = require("url");
9530
9879
  import_sdk = require("@cursor/sdk");
9531
9880
  init_run();
9532
9881
  init_app_settings();
@@ -9538,7 +9887,7 @@ var init_cursor = __esm({
9538
9887
  init_packaged_runtime();
9539
9888
  init_turn_input();
9540
9889
  init_cursor_events();
9541
- import_meta3 = {};
9890
+ import_meta2 = {};
9542
9891
  FALLBACK_CURSOR_MODELS = [
9543
9892
  { id: "default", displayName: "Auto" },
9544
9893
  { id: "composer-2.5", displayName: "Composer 2.5" },
@@ -9675,7 +10024,7 @@ async function listOpencodeModels() {
9675
10024
  if (opencode === "opencode") {
9676
10025
  const which = await run("which", ["opencode"], { reject: false });
9677
10026
  if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
9678
- } else if (!(0, import_node_fs28.existsSync)(opencode)) {
10027
+ } else if (!(0, import_node_fs29.existsSync)(opencode)) {
9679
10028
  return FALLBACK_OPENCODE_MODELS;
9680
10029
  }
9681
10030
  const listed = await run(opencode, ["models"], { reject: false });
@@ -9705,11 +10054,11 @@ function usageFromOpencode(tokens) {
9705
10054
  cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
9706
10055
  };
9707
10056
  }
9708
- var import_node_fs28, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
10057
+ var import_node_fs29, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
9709
10058
  var init_opencode = __esm({
9710
10059
  "src/agents/opencode.ts"() {
9711
10060
  "use strict";
9712
- import_node_fs28 = require("fs");
10061
+ import_node_fs29 = require("fs");
9713
10062
  init_run();
9714
10063
  init_app_settings();
9715
10064
  init_global_workspace();
@@ -9736,7 +10085,7 @@ var init_opencode = __esm({
9736
10085
  async detect() {
9737
10086
  const opencode = resolveAgentExecutable("opencode");
9738
10087
  if (opencode !== "opencode") {
9739
- if (!(0, import_node_fs28.existsSync)(opencode)) {
10088
+ if (!(0, import_node_fs29.existsSync)(opencode)) {
9740
10089
  return {
9741
10090
  agent: "opencode",
9742
10091
  installed: false,
@@ -9822,7 +10171,8 @@ var init_opencode = __esm({
9822
10171
  return { type: "stderr", data: detail };
9823
10172
  }
9824
10173
  const sid = typeof obj.sessionID === "string" && obj.sessionID || typeof obj.sessionId === "string" && obj.sessionId || typeof obj.session_id === "string" && obj.session_id;
9825
- if (sid && (!obj.type || obj.type === "step_start" || obj.type === "session")) {
10174
+ const childSid = str3(obj.childSessionID) ?? str3(obj.childSessionId) ?? str3(obj.parentID) ?? str3(obj.parentId);
10175
+ if (sid && !childSid && (!obj.type || obj.type === "step_start" || obj.type === "session")) {
9826
10176
  return { type: "session_id", data: sid };
9827
10177
  }
9828
10178
  if (obj.type === "text") {
@@ -10553,6 +10903,11 @@ function createAgentStreamCoalescer(emit, opts) {
10553
10903
  return;
10554
10904
  }
10555
10905
  if (!event.data) return;
10906
+ if (event.type === "thinking" && event.replace) {
10907
+ flush2();
10908
+ emit(event);
10909
+ return;
10910
+ }
10556
10911
  if (pending && pending.type === event.type && parentKey(pending) === parentKey(event)) {
10557
10912
  pending.data += event.data;
10558
10913
  } else {
@@ -10609,6 +10964,7 @@ async function spawnAgentTurn(thread, input, onEvent) {
10609
10964
  }
10610
10965
  const env = childEnvWithAppSettings(cmd.env);
10611
10966
  applyPromptCacheTtlEnv(thread.agent, env);
10967
+ applyAgentRunnerHeapEnv(env);
10612
10968
  try {
10613
10969
  if (isOrchestratorThread(thread)) {
10614
10970
  mergeAgentGitAuthEnv(env, await resolveAgentGitAuthEnv(env));
@@ -10716,9 +11072,11 @@ var init_spawn = __esm({
10716
11072
  init_agents();
10717
11073
  init_orchestrator_capable();
10718
11074
  init_message_parts();
11075
+ init_node_launch();
10719
11076
  init_path();
10720
11077
  init_usage();
10721
11078
  init_cursor_stream_coalesce();
11079
+ init_node_launch();
10722
11080
  }
10723
11081
  });
10724
11082
 
@@ -11444,21 +11802,21 @@ function shouldRefreshReviewRequestTemplate(content) {
11444
11802
  return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
11445
11803
  }
11446
11804
  function readTextIfPresent(abs) {
11447
- if (!(0, import_node_fs29.existsSync)(abs)) return null;
11805
+ if (!(0, import_node_fs30.existsSync)(abs)) return null;
11448
11806
  try {
11449
- const content = (0, import_node_fs29.readFileSync)(abs, "utf8");
11807
+ const content = (0, import_node_fs30.readFileSync)(abs, "utf8");
11450
11808
  return content.trim() ? content : null;
11451
11809
  } catch {
11452
11810
  return null;
11453
11811
  }
11454
11812
  }
11455
11813
  function readLocalGuidelines(worktreePath) {
11456
- const localAbs = (0, import_node_path28.join)(worktreePath, REVIEW_REQUEST_PATH);
11814
+ const localAbs = (0, import_node_path29.join)(worktreePath, REVIEW_REQUEST_PATH);
11457
11815
  const localContent = readTextIfPresent(localAbs);
11458
11816
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
11459
11817
  return { path: REVIEW_REQUEST_PATH, content: localContent };
11460
11818
  }
11461
- const legacyAbs = (0, import_node_path28.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
11819
+ const legacyAbs = (0, import_node_path29.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
11462
11820
  const legacyContent = readTextIfPresent(legacyAbs);
11463
11821
  if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
11464
11822
  return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
@@ -11474,20 +11832,20 @@ function skillGuidelines(content, source) {
11474
11832
  };
11475
11833
  }
11476
11834
  function ensureReviewSkillFile(worktreePath) {
11477
- const abs = (0, import_node_path28.join)(worktreePath, REVIEW_SKILL_PATH);
11835
+ const abs = (0, import_node_path29.join)(worktreePath, REVIEW_SKILL_PATH);
11478
11836
  const existing = readTextIfPresent(abs);
11479
11837
  if (existing) {
11480
11838
  return { path: REVIEW_SKILL_PATH, content: existing, wrote: false };
11481
11839
  }
11482
- const fromRepo = readTextIfPresent((0, import_node_path28.join)(worktreePath, REPO_REVIEW_PATH));
11840
+ const fromRepo = readTextIfPresent((0, import_node_path29.join)(worktreePath, REPO_REVIEW_PATH));
11483
11841
  const fromLocal = readLocalGuidelines(worktreePath)?.content ?? null;
11484
11842
  const content = wrapReviewSkillMarkdown(fromRepo ?? fromLocal ?? REVIEW_REQUEST_TEMPLATE);
11485
- (0, import_node_fs29.mkdirSync)((0, import_node_path28.dirname)(abs), { recursive: true });
11486
- (0, import_node_fs29.writeFileSync)(abs, content, "utf8");
11843
+ (0, import_node_fs30.mkdirSync)((0, import_node_path29.dirname)(abs), { recursive: true });
11844
+ (0, import_node_fs30.writeFileSync)(abs, content, "utf8");
11487
11845
  return { path: REVIEW_SKILL_PATH, content, wrote: true };
11488
11846
  }
11489
11847
  function resolveReviewGuidelines(worktreePath) {
11490
- const skillContent = readTextIfPresent((0, import_node_path28.join)(worktreePath, REVIEW_SKILL_PATH));
11848
+ const skillContent = readTextIfPresent((0, import_node_path29.join)(worktreePath, REVIEW_SKILL_PATH));
11491
11849
  if (skillContent) return skillGuidelines(skillContent, "skill");
11492
11850
  const local = readLocalGuidelines(worktreePath);
11493
11851
  if (local) {
@@ -11517,7 +11875,7 @@ function buildReviewRequestAttachment(content, opts) {
11517
11875
  };
11518
11876
  }
11519
11877
  function readExistingReviewRequestFile(worktreePath) {
11520
- return readTextIfPresent((0, import_node_path28.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path28.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path28.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path28.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
11878
+ return readTextIfPresent((0, import_node_path29.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path29.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path29.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path29.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
11521
11879
  }
11522
11880
  async function requestReview(threadRef, send2) {
11523
11881
  const from = findThreadByRef(threadRef);
@@ -11544,13 +11902,13 @@ async function requestReview(threadRef, send2) {
11544
11902
  const started = await send2(tab.id, REVIEW_REQUEST_PREFILL);
11545
11903
  return { tab: started, from };
11546
11904
  }
11547
- var import_node_crypto6, import_node_fs29, import_node_path28, REPO_REVIEW_PATH, REPO_REVIEW_NAME, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
11905
+ var import_node_crypto6, import_node_fs30, import_node_path29, REPO_REVIEW_PATH, REPO_REVIEW_NAME, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
11548
11906
  var init_request_review = __esm({
11549
11907
  "src/review/request-review.ts"() {
11550
11908
  "use strict";
11551
11909
  import_node_crypto6 = require("crypto");
11552
- import_node_fs29 = require("fs");
11553
- import_node_path28 = require("path");
11910
+ import_node_fs30 = require("fs");
11911
+ import_node_path29 = require("path");
11554
11912
  init_global_workspace();
11555
11913
  init_chat_tabs();
11556
11914
  init_thread_store();
@@ -11575,9 +11933,9 @@ function matchSimpleGlob(pattern, name) {
11575
11933
  return new RegExp(`^${escaped}$`).test(name);
11576
11934
  }
11577
11935
  function readWorktreeInclude(repoPath) {
11578
- const path2 = (0, import_node_path29.join)(repoPath, ".worktreeinclude");
11579
- if (!(0, import_node_fs30.existsSync)(path2)) return [];
11580
- return (0, import_node_fs30.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
11936
+ const path2 = (0, import_node_path30.join)(repoPath, ".worktreeinclude");
11937
+ if (!(0, import_node_fs31.existsSync)(path2)) return [];
11938
+ return (0, import_node_fs31.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
11581
11939
  }
11582
11940
  function resolveFilesToCopy(repoPath) {
11583
11941
  const fromInclude = readWorktreeInclude(repoPath);
@@ -11587,10 +11945,10 @@ function resolveFilesToCopy(repoPath) {
11587
11945
  if (settings?.fileIncludeGlobs?.length) {
11588
11946
  const matched = [];
11589
11947
  try {
11590
- for (const entry of (0, import_node_fs30.readdirSync)(repoPath, { withFileTypes: true })) {
11948
+ for (const entry of (0, import_node_fs31.readdirSync)(repoPath, { withFileTypes: true })) {
11591
11949
  if (!entry.isFile()) continue;
11592
11950
  for (const glob of settings.fileIncludeGlobs) {
11593
- if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path29.basename)(glob), entry.name)) {
11951
+ if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path30.basename)(glob), entry.name)) {
11594
11952
  matched.push(entry.name);
11595
11953
  break;
11596
11954
  }
@@ -11602,7 +11960,7 @@ function resolveFilesToCopy(repoPath) {
11602
11960
  }
11603
11961
  const defaults = [];
11604
11962
  try {
11605
- for (const entry of (0, import_node_fs30.readdirSync)(repoPath, { withFileTypes: true })) {
11963
+ for (const entry of (0, import_node_fs31.readdirSync)(repoPath, { withFileTypes: true })) {
11606
11964
  if (entry.isFile() && entry.name.startsWith(".env")) {
11607
11965
  defaults.push(entry.name);
11608
11966
  }
@@ -11616,11 +11974,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
11616
11974
  const patterns = resolveFilesToCopy(repoPath);
11617
11975
  const copied = [];
11618
11976
  for (const rel of patterns) {
11619
- const src = (0, import_node_path29.join)(repoPath, rel);
11620
- if (!(0, import_node_fs30.existsSync)(src)) continue;
11621
- const dest = (0, import_node_path29.join)(worktreePath, rel);
11622
- (0, import_node_fs30.mkdirSync)((0, import_node_path29.dirname)(dest), { recursive: true });
11623
- (0, import_node_fs30.copyFileSync)(src, dest);
11977
+ const src = (0, import_node_path30.join)(repoPath, rel);
11978
+ if (!(0, import_node_fs31.existsSync)(src)) continue;
11979
+ const dest = (0, import_node_path30.join)(worktreePath, rel);
11980
+ (0, import_node_fs31.mkdirSync)((0, import_node_path30.dirname)(dest), { recursive: true });
11981
+ (0, import_node_fs31.copyFileSync)(src, dest);
11624
11982
  copied.push(rel);
11625
11983
  }
11626
11984
  return copied;
@@ -11655,7 +12013,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
11655
12013
  const env = stripNestedElectronEnv({
11656
12014
  ...baseEnv ?? process.env
11657
12015
  });
11658
- const name = opts.workspaceName ?? (0, import_node_path29.basename)(opts.worktreePath);
12016
+ const name = opts.workspaceName ?? (0, import_node_path30.basename)(opts.worktreePath);
11659
12017
  const ports = opts.ports ?? [];
11660
12018
  const primary = ports[0];
11661
12019
  env.SIDEBOARD_WORKSPACE_NAME = name;
@@ -11916,13 +12274,13 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
11916
12274
  done: handle.done
11917
12275
  };
11918
12276
  }
11919
- var import_node_fs30, import_node_net, import_node_path29, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
12277
+ var import_node_fs31, import_node_net, import_node_path30, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
11920
12278
  var init_conductor = __esm({
11921
12279
  "src/hook/conductor.ts"() {
11922
12280
  "use strict";
11923
- import_node_fs30 = require("fs");
12281
+ import_node_fs31 = require("fs");
11924
12282
  import_node_net = require("net");
11925
- import_node_path29 = require("path");
12283
+ import_node_path30 = require("path");
11926
12284
  import_execa4 = require("execa");
11927
12285
  import_node_readline3 = require("readline");
11928
12286
  init_settings();
@@ -11948,9 +12306,9 @@ async function findOrphanWorktrees(repoPaths) {
11948
12306
  repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
11949
12307
  );
11950
12308
  const homeRoot = sideboardWorkspacesDir();
11951
- if ((0, import_node_fs31.existsSync)(homeRoot)) {
12309
+ if ((0, import_node_fs32.existsSync)(homeRoot)) {
11952
12310
  try {
11953
- for (const entry of (0, import_node_fs31.readdirSync)(homeRoot, { withFileTypes: true })) {
12311
+ for (const entry of (0, import_node_fs32.readdirSync)(homeRoot, { withFileTypes: true })) {
11954
12312
  if (!entry.isDirectory()) continue;
11955
12313
  void entry;
11956
12314
  }
@@ -11960,7 +12318,7 @@ async function findOrphanWorktrees(repoPaths) {
11960
12318
  const orphans = [];
11961
12319
  const seen = /* @__PURE__ */ new Set();
11962
12320
  for (const repoPath of repos) {
11963
- if (!repoPath || !(0, import_node_fs31.existsSync)(repoPath)) continue;
12321
+ if (!repoPath || !(0, import_node_fs32.existsSync)(repoPath)) continue;
11964
12322
  try {
11965
12323
  const wts = await listWorktrees(repoPath);
11966
12324
  for (const wt of wts) {
@@ -11971,7 +12329,7 @@ async function findOrphanWorktrees(repoPaths) {
11971
12329
  seen.add(path2);
11972
12330
  let mtimeMs = 0;
11973
12331
  try {
11974
- mtimeMs = (0, import_node_fs31.statSync)(path2).mtimeMs;
12332
+ mtimeMs = (0, import_node_fs32.statSync)(path2).mtimeMs;
11975
12333
  } catch {
11976
12334
  mtimeMs = 0;
11977
12335
  }
@@ -11981,16 +12339,16 @@ async function findOrphanWorktrees(repoPaths) {
11981
12339
  }
11982
12340
  try {
11983
12341
  const root = worktreesRoot(repoPath);
11984
- if ((0, import_node_fs31.existsSync)(root)) {
11985
- for (const entry of (0, import_node_fs31.readdirSync)(root, { withFileTypes: true })) {
12342
+ if ((0, import_node_fs32.existsSync)(root)) {
12343
+ for (const entry of (0, import_node_fs32.readdirSync)(root, { withFileTypes: true })) {
11986
12344
  if (!entry.isDirectory()) continue;
11987
- const path2 = (0, import_node_path30.join)(root, entry.name).replace(/\/$/, "");
12345
+ const path2 = (0, import_node_path31.join)(root, entry.name).replace(/\/$/, "");
11988
12346
  if (known.has(path2) || seen.has(path2)) continue;
11989
- if (!(0, import_node_fs31.existsSync)((0, import_node_path30.join)(path2, ".git"))) continue;
12347
+ if (!(0, import_node_fs32.existsSync)((0, import_node_path31.join)(path2, ".git"))) continue;
11990
12348
  seen.add(path2);
11991
12349
  let mtimeMs = 0;
11992
12350
  try {
11993
- mtimeMs = (0, import_node_fs31.statSync)(path2).mtimeMs;
12351
+ mtimeMs = (0, import_node_fs32.statSync)(path2).mtimeMs;
11994
12352
  } catch {
11995
12353
  mtimeMs = Date.now();
11996
12354
  }
@@ -12051,12 +12409,12 @@ function worktreeCleanupSettings() {
12051
12409
  autoCleanupOrphans: a.autoCleanupOrphans
12052
12410
  };
12053
12411
  }
12054
- var import_node_fs31, import_node_path30;
12412
+ var import_node_fs32, import_node_path31;
12055
12413
  var init_orphan_cleanup = __esm({
12056
12414
  "src/git/orphan-cleanup.ts"() {
12057
12415
  "use strict";
12058
- import_node_fs31 = require("fs");
12059
- import_node_path30 = require("path");
12416
+ import_node_fs32 = require("fs");
12417
+ import_node_path31 = require("path");
12060
12418
  init_worktree();
12061
12419
  init_thread_store();
12062
12420
  init_paths();
@@ -12163,38 +12521,38 @@ __export(workspaces_exports, {
12163
12521
  syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
12164
12522
  });
12165
12523
  function workspacesFile() {
12166
- return (0, import_node_path31.join)(appDataDir(), "workspaces.json");
12524
+ return (0, import_node_path32.join)(appDataDir(), "workspaces.json");
12167
12525
  }
12168
12526
  function removedWorkspacesFile() {
12169
- return (0, import_node_path31.join)(appDataDir(), "removed-workspaces.json");
12527
+ return (0, import_node_path32.join)(appDataDir(), "removed-workspaces.json");
12170
12528
  }
12171
12529
  function readAll2() {
12172
12530
  const path2 = workspacesFile();
12173
- if (!(0, import_node_fs32.existsSync)(path2)) return [];
12531
+ if (!(0, import_node_fs33.existsSync)(path2)) return [];
12174
12532
  try {
12175
- const raw = JSON.parse((0, import_node_fs32.readFileSync)(path2, "utf8"));
12533
+ const raw = JSON.parse((0, import_node_fs33.readFileSync)(path2, "utf8"));
12176
12534
  return Array.isArray(raw) ? raw : [];
12177
12535
  } catch {
12178
12536
  return [];
12179
12537
  }
12180
12538
  }
12181
12539
  function writeAll2(list) {
12182
- (0, import_node_fs32.mkdirSync)(appDataDir(), { recursive: true });
12183
- (0, import_node_fs32.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
12540
+ (0, import_node_fs33.mkdirSync)(appDataDir(), { recursive: true });
12541
+ (0, import_node_fs33.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
12184
12542
  }
12185
12543
  function readRemoved() {
12186
12544
  const path2 = removedWorkspacesFile();
12187
- if (!(0, import_node_fs32.existsSync)(path2)) return /* @__PURE__ */ new Set();
12545
+ if (!(0, import_node_fs33.existsSync)(path2)) return /* @__PURE__ */ new Set();
12188
12546
  try {
12189
- const raw = JSON.parse((0, import_node_fs32.readFileSync)(path2, "utf8"));
12547
+ const raw = JSON.parse((0, import_node_fs33.readFileSync)(path2, "utf8"));
12190
12548
  return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
12191
12549
  } catch {
12192
12550
  return /* @__PURE__ */ new Set();
12193
12551
  }
12194
12552
  }
12195
12553
  function writeRemoved(paths) {
12196
- (0, import_node_fs32.mkdirSync)(appDataDir(), { recursive: true });
12197
- (0, import_node_fs32.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
12554
+ (0, import_node_fs33.mkdirSync)(appDataDir(), { recursive: true });
12555
+ (0, import_node_fs33.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
12198
12556
  }
12199
12557
  function rememberRemoved(repoPath) {
12200
12558
  const next = readRemoved();
@@ -12217,7 +12575,7 @@ function listWorkspaces() {
12217
12575
  async function addWorkspace(repoPath) {
12218
12576
  const root = await resolveRepoRoot(repoPath);
12219
12577
  if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
12220
- if (!(0, import_node_fs32.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
12578
+ if (!(0, import_node_fs33.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
12221
12579
  forgetRemoved(root);
12222
12580
  await ensureGhPreferOrigin(root);
12223
12581
  const current = readAll2();
@@ -12225,7 +12583,7 @@ async function addWorkspace(repoPath) {
12225
12583
  if (existing) return existing;
12226
12584
  const next = {
12227
12585
  path: root,
12228
- name: (0, import_node_path31.basename)(root),
12586
+ name: (0, import_node_path32.basename)(root),
12229
12587
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
12230
12588
  };
12231
12589
  writeAll2([...current, next]);
@@ -12247,10 +12605,10 @@ function syncWorkspacesFromThreads(repoPaths) {
12247
12605
  if (!path2 || path2 === "/" || isGlobalRepoPath(path2) || byPath.has(path2) || removed.has(path2)) {
12248
12606
  continue;
12249
12607
  }
12250
- if (!(0, import_node_fs32.existsSync)(path2)) continue;
12608
+ if (!(0, import_node_fs33.existsSync)(path2)) continue;
12251
12609
  const ws = {
12252
12610
  path: path2,
12253
- name: (0, import_node_path31.basename)(path2),
12611
+ name: (0, import_node_path32.basename)(path2),
12254
12612
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
12255
12613
  };
12256
12614
  byPath.set(path2, ws);
@@ -12260,12 +12618,12 @@ function syncWorkspacesFromThreads(repoPaths) {
12260
12618
  if (dirty) writeAll2(next);
12261
12619
  return next.sort((a, b) => a.name.localeCompare(b.name));
12262
12620
  }
12263
- var import_node_fs32, import_node_path31;
12621
+ var import_node_fs33, import_node_path32;
12264
12622
  var init_workspaces2 = __esm({
12265
12623
  "src/store/workspaces.ts"() {
12266
12624
  "use strict";
12267
- import_node_fs32 = require("fs");
12268
- import_node_path31 = require("path");
12625
+ import_node_fs33 = require("fs");
12626
+ import_node_path32 = require("path");
12269
12627
  init_paths();
12270
12628
  init_global_workspace();
12271
12629
  init_worktree();
@@ -12278,12 +12636,12 @@ async function cloneRepoIntoSideboard(opts) {
12278
12636
  if (!url) throw new Error("Clone URL is required");
12279
12637
  let name = opts.name?.trim();
12280
12638
  if (!name) {
12281
- const leaf = (0, import_node_path32.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
12639
+ const leaf = (0, import_node_path33.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
12282
12640
  name = leaf || "repo";
12283
12641
  }
12284
12642
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
12285
- const dest = (0, import_node_path32.join)(sideboardReposDir(), name);
12286
- if ((0, import_node_fs33.existsSync)(dest)) {
12643
+ const dest = (0, import_node_path33.join)(sideboardReposDir(), name);
12644
+ if ((0, import_node_fs34.existsSync)(dest)) {
12287
12645
  const repoPath2 = await resolveRepoRoot(dest);
12288
12646
  const workspace2 = await ensureWorkspace(repoPath2);
12289
12647
  return { repoPath: repoPath2, workspace: workspace2 };
@@ -12298,12 +12656,12 @@ async function cloneRepoIntoSideboard(opts) {
12298
12656
  const workspace = await ensureWorkspace(repoPath);
12299
12657
  return { repoPath, workspace };
12300
12658
  }
12301
- var import_node_fs33, import_node_path32, import_execa6;
12659
+ var import_node_fs34, import_node_path33, import_execa6;
12302
12660
  var init_clone_repo = __esm({
12303
12661
  "src/git/clone-repo.ts"() {
12304
12662
  "use strict";
12305
- import_node_fs33 = require("fs");
12306
- import_node_path32 = require("path");
12663
+ import_node_fs34 = require("fs");
12664
+ import_node_path33 = require("path");
12307
12665
  import_execa6 = require("execa");
12308
12666
  init_paths();
12309
12667
  init_workspaces2();
@@ -12361,7 +12719,7 @@ async function createThread(input, _onSetupLine) {
12361
12719
  });
12362
12720
  await requireAgent(resolved.agent);
12363
12721
  const repoPath = await resolveRepoRoot(input.repoPath);
12364
- if (!(0, import_node_fs34.existsSync)(repoPath)) {
12722
+ if (!(0, import_node_fs35.existsSync)(repoPath)) {
12365
12723
  throw new Error(`Repo not found: ${repoPath}`);
12366
12724
  }
12367
12725
  if (input.cowboy) {
@@ -12484,11 +12842,11 @@ async function listLinearIssues(agent, repoPath) {
12484
12842
  }
12485
12843
  return adapter.listLinearIssues(repoPath);
12486
12844
  }
12487
- var import_node_fs34;
12845
+ var import_node_fs35;
12488
12846
  var init_create = __esm({
12489
12847
  "src/threads/create.ts"() {
12490
12848
  "use strict";
12491
- import_node_fs34 = require("fs");
12849
+ import_node_fs35 = require("fs");
12492
12850
  init_detect();
12493
12851
  init_worktree();
12494
12852
  init_conductor();
@@ -12533,21 +12891,13 @@ function summarizeTurnLive(parts) {
12533
12891
  (p) => p.type === "tool"
12534
12892
  );
12535
12893
  const lastTool = tools[tools.length - 1];
12536
- const lastToolLabel = lastTool ? lastTool.description || toolDescription(lastTool.name, lastTool.input) || lastTool.name : void 0;
12537
- const running = lastTool?.status === "running";
12894
+ const interesting = [...tools].reverse().find((t) => !isPollWrapperToolName(t.name)) ?? lastTool;
12895
+ const lastToolLabel = interesting ? interesting.description || toolDescription(interesting.name, interesting.input) || interesting.name : void 0;
12538
12896
  const thinking = lastText(parts, "thinking");
12539
12897
  const text4 = lastText(parts, "text");
12540
12898
  const excerptRaw = thinking || text4;
12541
12899
  const excerpt = excerptRaw.length > 280 ? `${excerptRaw.slice(-280)}` : excerptRaw || void 0;
12542
- let summary = "Working\u2026";
12543
- if (lastToolLabel) {
12544
- const verb = running ? lastToolLabel : `Finished ${lastToolLabel}`;
12545
- summary = tools.length > 1 ? `${verb} (${tools.length} tools)` : verb;
12546
- } else if (thinking) {
12547
- summary = "Thinking\u2026";
12548
- } else if (text4) {
12549
- summary = "Writing reply\u2026";
12550
- }
12900
+ const summary = liveActivitySummary(parts);
12551
12901
  return {
12552
12902
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
12553
12903
  summary,
@@ -12597,20 +12947,20 @@ function writeTurnLive(threadId, progress) {
12597
12947
  const path2 = threadLivePath(threadId);
12598
12948
  const tmp = `${path2}.${process.pid}.tmp`;
12599
12949
  try {
12600
- (0, import_node_fs35.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
12601
- (0, import_node_fs35.renameSync)(tmp, path2);
12950
+ (0, import_node_fs36.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
12951
+ (0, import_node_fs36.renameSync)(tmp, path2);
12602
12952
  } catch {
12603
12953
  try {
12604
- (0, import_node_fs35.unlinkSync)(tmp);
12954
+ (0, import_node_fs36.unlinkSync)(tmp);
12605
12955
  } catch {
12606
12956
  }
12607
12957
  }
12608
12958
  }
12609
12959
  function readTurnLive(threadId) {
12610
12960
  const path2 = threadLivePath(threadId);
12611
- if (!(0, import_node_fs35.existsSync)(path2)) return null;
12961
+ if (!(0, import_node_fs36.existsSync)(path2)) return null;
12612
12962
  try {
12613
- const raw = JSON.parse((0, import_node_fs35.readFileSync)(path2, "utf8"));
12963
+ const raw = JSON.parse((0, import_node_fs36.readFileSync)(path2, "utf8"));
12614
12964
  if (!raw || typeof raw.summary !== "string") return null;
12615
12965
  return raw;
12616
12966
  } catch {
@@ -12622,17 +12972,17 @@ function clearTurnLive(threadId) {
12622
12972
  if (buf?.timer) clearTimeout(buf.timer);
12623
12973
  buffers.delete(threadId);
12624
12974
  const path2 = threadLivePath(threadId);
12625
- if (!(0, import_node_fs35.existsSync)(path2)) return;
12975
+ if (!(0, import_node_fs36.existsSync)(path2)) return;
12626
12976
  try {
12627
- (0, import_node_fs35.unlinkSync)(path2);
12977
+ (0, import_node_fs36.unlinkSync)(path2);
12628
12978
  } catch {
12629
12979
  }
12630
12980
  }
12631
- var import_node_fs35, buffers, FLUSH_MS, MAX_PARTS;
12981
+ var import_node_fs36, buffers, FLUSH_MS, MAX_PARTS;
12632
12982
  var init_turn_live = __esm({
12633
12983
  "src/store/turn-live.ts"() {
12634
12984
  "use strict";
12635
- import_node_fs35 = require("fs");
12985
+ import_node_fs36 = require("fs");
12636
12986
  init_message_parts();
12637
12987
  init_paths();
12638
12988
  buffers = /* @__PURE__ */ new Map();
@@ -12809,8 +13159,12 @@ var init_quota_failover = __esm({
12809
13159
  });
12810
13160
 
12811
13161
  // src/threads/adopt.ts
13162
+ function thisModuleFile() {
13163
+ const cjsFile = typeof __filename !== "undefined" ? __filename : "";
13164
+ return cjsFile || process.argv[1] || (0, import_node_path34.join)(process.cwd(), "package.json");
13165
+ }
12812
13166
  function openReadonlySqlite(file) {
12813
- const req = (0, import_node_module4.createRequire)(import_meta4.url);
13167
+ const req = (0, import_node_module4.createRequire)(thisModuleFile());
12814
13168
  const Database = req("better-sqlite3");
12815
13169
  return new Database(file, { readonly: true, fileMustExist: true });
12816
13170
  }
@@ -12825,21 +13179,21 @@ function mapAgentType(raw) {
12825
13179
  return null;
12826
13180
  }
12827
13181
  function resolveConductorCursorAgentId(workspacePath) {
12828
- if (!workspacePath || !(0, import_node_fs36.existsSync)(CURSOR_SDK_STORE)) return null;
13182
+ if (!workspacePath || !(0, import_node_fs37.existsSync)(CURSOR_SDK_STORE)) return null;
12829
13183
  const normalized = workspacePath.replace(/\/$/, "");
12830
13184
  let best = null;
12831
13185
  let hashes;
12832
13186
  try {
12833
- hashes = (0, import_node_fs36.readdirSync)(CURSOR_SDK_STORE);
13187
+ hashes = (0, import_node_fs37.readdirSync)(CURSOR_SDK_STORE);
12834
13188
  } catch {
12835
13189
  return null;
12836
13190
  }
12837
13191
  for (const hash of hashes) {
12838
- const agentsFile = (0, import_node_path33.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
12839
- if (!(0, import_node_fs36.existsSync)(agentsFile)) continue;
13192
+ const agentsFile = (0, import_node_path34.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
13193
+ if (!(0, import_node_fs37.existsSync)(agentsFile)) continue;
12840
13194
  let text4;
12841
13195
  try {
12842
- text4 = (0, import_node_fs36.readFileSync)(agentsFile, "utf8");
13196
+ text4 = (0, import_node_fs37.readFileSync)(agentsFile, "utf8");
12843
13197
  } catch {
12844
13198
  continue;
12845
13199
  }
@@ -12863,7 +13217,7 @@ function resolveConductorCursorAgentId(workspacePath) {
12863
13217
  return best?.agentId ?? null;
12864
13218
  }
12865
13219
  async function adoptThread(input) {
12866
- if (!(0, import_node_fs36.existsSync)(input.worktreePath)) {
13220
+ if (!(0, import_node_fs37.existsSync)(input.worktreePath)) {
12867
13221
  throw new Error(`Worktree not found: ${input.worktreePath}`);
12868
13222
  }
12869
13223
  const repoPath = await resolveRepoRoot(input.worktreePath);
@@ -12890,18 +13244,18 @@ function conductorDbPath() {
12890
13244
  return CONDUCTOR_DB;
12891
13245
  }
12892
13246
  function listConductorWorkspaces() {
12893
- if (!(0, import_node_fs36.existsSync)(CONDUCTOR_DB)) {
13247
+ if (!(0, import_node_fs37.existsSync)(CONDUCTOR_DB)) {
12894
13248
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
12895
13249
  }
12896
- const tmp = (0, import_node_fs36.mkdtempSync)((0, import_node_path33.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
12897
- const snapshot = (0, import_node_path33.join)(tmp, "conductor.db");
13250
+ const tmp = (0, import_node_fs37.mkdtempSync)((0, import_node_path34.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
13251
+ const snapshot = (0, import_node_path34.join)(tmp, "conductor.db");
12898
13252
  try {
12899
- (0, import_node_fs36.copyFileSync)(CONDUCTOR_DB, snapshot);
13253
+ (0, import_node_fs37.copyFileSync)(CONDUCTOR_DB, snapshot);
12900
13254
  for (const suffix of ["-wal", "-shm"]) {
12901
13255
  const src = `${CONDUCTOR_DB}${suffix}`;
12902
- if ((0, import_node_fs36.existsSync)(src)) {
13256
+ if ((0, import_node_fs37.existsSync)(src)) {
12903
13257
  try {
12904
- (0, import_node_fs36.copyFileSync)(src, `${snapshot}${suffix}`);
13258
+ (0, import_node_fs37.copyFileSync)(src, `${snapshot}${suffix}`);
12905
13259
  } catch {
12906
13260
  }
12907
13261
  }
@@ -12977,22 +13331,22 @@ function listConductorWorkspaces() {
12977
13331
  db.close();
12978
13332
  }
12979
13333
  } finally {
12980
- (0, import_node_fs36.rmSync)(tmp, { recursive: true, force: true });
13334
+ (0, import_node_fs37.rmSync)(tmp, { recursive: true, force: true });
12981
13335
  }
12982
13336
  }
12983
13337
  function importConductorWorkspace(workspaceId) {
12984
- if (!(0, import_node_fs36.existsSync)(CONDUCTOR_DB)) {
13338
+ if (!(0, import_node_fs37.existsSync)(CONDUCTOR_DB)) {
12985
13339
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
12986
13340
  }
12987
- const tmp = (0, import_node_fs36.mkdtempSync)((0, import_node_path33.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
12988
- const snapshot = (0, import_node_path33.join)(tmp, "conductor.db");
13341
+ const tmp = (0, import_node_fs37.mkdtempSync)((0, import_node_path34.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
13342
+ const snapshot = (0, import_node_path34.join)(tmp, "conductor.db");
12989
13343
  try {
12990
- (0, import_node_fs36.copyFileSync)(CONDUCTOR_DB, snapshot);
13344
+ (0, import_node_fs37.copyFileSync)(CONDUCTOR_DB, snapshot);
12991
13345
  for (const suffix of ["-wal", "-shm"]) {
12992
13346
  const src = `${CONDUCTOR_DB}${suffix}`;
12993
- if ((0, import_node_fs36.existsSync)(src)) {
13347
+ if ((0, import_node_fs37.existsSync)(src)) {
12994
13348
  try {
12995
- (0, import_node_fs36.copyFileSync)(src, `${snapshot}${suffix}`);
13349
+ (0, import_node_fs37.copyFileSync)(src, `${snapshot}${suffix}`);
12996
13350
  } catch {
12997
13351
  }
12998
13352
  }
@@ -13010,7 +13364,7 @@ function importConductorWorkspace(workspaceId) {
13010
13364
  ).get(workspaceId);
13011
13365
  if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
13012
13366
  const worktreePath = String(row.workspacePath);
13013
- if (!(0, import_node_fs36.existsSync)(worktreePath)) {
13367
+ if (!(0, import_node_fs37.existsSync)(worktreePath)) {
13014
13368
  throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
13015
13369
  }
13016
13370
  let sessionId = null;
@@ -13073,32 +13427,31 @@ function importConductorWorkspace(workspaceId) {
13073
13427
  db.close();
13074
13428
  }
13075
13429
  } finally {
13076
- (0, import_node_fs36.rmSync)(tmp, { recursive: true, force: true });
13430
+ (0, import_node_fs37.rmSync)(tmp, { recursive: true, force: true });
13077
13431
  }
13078
13432
  }
13079
13433
  async function importConductorWorkspaceAsync(workspaceId) {
13080
13434
  return importConductorWorkspace(workspaceId);
13081
13435
  }
13082
- var import_node_child_process4, import_node_fs36, import_node_os10, import_node_path33, import_node_module4, import_meta4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
13436
+ var import_node_child_process4, import_node_fs37, import_node_os10, import_node_path34, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
13083
13437
  var init_adopt = __esm({
13084
13438
  "src/threads/adopt.ts"() {
13085
13439
  "use strict";
13086
13440
  import_node_child_process4 = require("child_process");
13087
- import_node_fs36 = require("fs");
13441
+ import_node_fs37 = require("fs");
13088
13442
  import_node_os10 = require("os");
13089
- import_node_path33 = require("path");
13443
+ import_node_path34 = require("path");
13090
13444
  import_node_module4 = require("module");
13091
13445
  init_worktree();
13092
13446
  init_thread_store();
13093
- import_meta4 = {};
13094
- CONDUCTOR_APP_SUPPORT = (0, import_node_path33.join)(
13447
+ CONDUCTOR_APP_SUPPORT = (0, import_node_path34.join)(
13095
13448
  process.env.HOME ?? "",
13096
13449
  "Library",
13097
13450
  "Application Support",
13098
13451
  "com.conductor.app"
13099
13452
  );
13100
- CONDUCTOR_DB = (0, import_node_path33.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
13101
- CURSOR_SDK_STORE = (0, import_node_path33.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
13453
+ CONDUCTOR_DB = (0, import_node_path34.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
13454
+ CURSOR_SDK_STORE = (0, import_node_path34.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
13102
13455
  }
13103
13456
  });
13104
13457
 
@@ -13165,7 +13518,7 @@ async function openStackLayer(input, _onSetupLine) {
13165
13518
  let createdWorktree = false;
13166
13519
  const trees = await listWorktrees(repoPath);
13167
13520
  const checkedOut = trees.find((w) => w.branch === branchName);
13168
- if (checkedOut?.path && (0, import_node_fs37.existsSync)(checkedOut.path)) {
13521
+ if (checkedOut?.path && (0, import_node_fs38.existsSync)(checkedOut.path)) {
13169
13522
  if (input.reuseExistingWorktree !== false) {
13170
13523
  worktreePath = checkedOut.path;
13171
13524
  } else {
@@ -13307,7 +13660,7 @@ async function initStackFromThread(input, onSetupLine) {
13307
13660
  async function createPrStack(input, onSetupLine) {
13308
13661
  await requireAgent(input.agent);
13309
13662
  const repoPath = await resolveRepoRoot(input.repoPath);
13310
- if (!(0, import_node_fs37.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
13663
+ if (!(0, import_node_fs38.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
13311
13664
  if (!input.branches.length) throw new Error("At least one branch name required");
13312
13665
  const status = await detectGhStack(repoPath);
13313
13666
  if (!status.available) throw new Error(status.reason);
@@ -13374,7 +13727,7 @@ async function createPrStack(input, onSetupLine) {
13374
13727
  }
13375
13728
  }
13376
13729
  const claimed = new Set(threads.map((t) => t.worktreePath));
13377
- if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs37.existsSync)(bootstrap.worktreePath)) {
13730
+ if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs38.existsSync)(bootstrap.worktreePath)) {
13378
13731
  try {
13379
13732
  await removeWorktree(repoPath, bootstrap.worktreePath, {
13380
13733
  deleteBranch: bootstrap.branchName
@@ -13394,11 +13747,11 @@ function stackAgentDefaultsFrom(input) {
13394
13747
  planMode: input.planMode
13395
13748
  };
13396
13749
  }
13397
- var import_node_fs37;
13750
+ var import_node_fs38;
13398
13751
  var init_stack_layers = __esm({
13399
13752
  "src/threads/stack-layers.ts"() {
13400
13753
  "use strict";
13401
- import_node_fs37 = require("fs");
13754
+ import_node_fs38 = require("fs");
13402
13755
  init_detect();
13403
13756
  init_run();
13404
13757
  init_stack();
@@ -13411,7 +13764,7 @@ var init_stack_layers = __esm({
13411
13764
 
13412
13765
  // src/diff/diff.ts
13413
13766
  async function inspectGitWorktree(worktreePath) {
13414
- if (!worktreePath || !(0, import_node_fs38.existsSync)(worktreePath)) return "missing_worktree";
13767
+ if (!worktreePath || !(0, import_node_fs39.existsSync)(worktreePath)) return "missing_worktree";
13415
13768
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
13416
13769
  reject: false
13417
13770
  });
@@ -13419,7 +13772,7 @@ async function inspectGitWorktree(worktreePath) {
13419
13772
  return "ok";
13420
13773
  }
13421
13774
  async function initializeGitRepository(worktreePath) {
13422
- if (!worktreePath || !(0, import_node_fs38.existsSync)(worktreePath)) {
13775
+ if (!worktreePath || !(0, import_node_fs39.existsSync)(worktreePath)) {
13423
13776
  throw new Error("Worktree not found");
13424
13777
  }
13425
13778
  const status = await inspectGitWorktree(worktreePath);
@@ -13553,11 +13906,11 @@ new file mode 100644
13553
13906
  };
13554
13907
  }
13555
13908
  async function untrackedPatch(worktreePath, path2, maxHunk) {
13556
- const abs = (0, import_node_path34.join)(worktreePath, path2);
13909
+ const abs = (0, import_node_path35.join)(worktreePath, path2);
13557
13910
  try {
13558
- const st = (0, import_node_fs38.statSync)(abs);
13911
+ const st = (0, import_node_fs39.statSync)(abs);
13559
13912
  if (st.isFile() && st.size > maxHunk) {
13560
- const buf = (0, import_node_fs38.readFileSync)(abs).subarray(0, maxHunk);
13913
+ const buf = (0, import_node_fs39.readFileSync)(abs).subarray(0, maxHunk);
13561
13914
  return syntheticAddPatch(path2, buf.toString("utf8"), maxHunk);
13562
13915
  }
13563
13916
  } catch {
@@ -14046,8 +14399,8 @@ function isImageRelativePath(relativePath) {
14046
14399
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
14047
14400
  assertSafeRelativePath(relativePath);
14048
14401
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
14049
- const abs = (0, import_node_path34.join)(worktreePath, relativePath);
14050
- const st = (0, import_node_fs38.statSync)(abs);
14402
+ const abs = (0, import_node_path35.join)(worktreePath, relativePath);
14403
+ const st = (0, import_node_fs39.statSync)(abs);
14051
14404
  if (!st.isFile()) {
14052
14405
  throw new Error(`Not a file: ${relativePath}`);
14053
14406
  }
@@ -14056,7 +14409,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
14056
14409
  `File too large to upload (${st.size} bytes; max ${maxBytes})`
14057
14410
  );
14058
14411
  }
14059
- const buf = (0, import_node_fs38.readFileSync)(abs);
14412
+ const buf = (0, import_node_fs39.readFileSync)(abs);
14060
14413
  return {
14061
14414
  path: relativePath,
14062
14415
  contentBase64: buf.toString("base64"),
@@ -14066,12 +14419,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
14066
14419
  function readWorktreeFile(worktreePath, relativePath, opts) {
14067
14420
  assertSafeRelativePath(relativePath);
14068
14421
  const maxBytes = opts?.maxBytes ?? 2e5;
14069
- const abs = (0, import_node_path34.join)(worktreePath, relativePath);
14070
- const st = (0, import_node_fs38.statSync)(abs);
14422
+ const abs = (0, import_node_path35.join)(worktreePath, relativePath);
14423
+ const st = (0, import_node_fs39.statSync)(abs);
14071
14424
  if (!st.isFile()) {
14072
14425
  throw new Error(`Not a file: ${relativePath}`);
14073
14426
  }
14074
- const buf = (0, import_node_fs38.readFileSync)(abs);
14427
+ const buf = (0, import_node_fs39.readFileSync)(abs);
14075
14428
  if (isImageRelativePath(relativePath)) {
14076
14429
  const maxImageBytes = Math.max(maxBytes, 15e6);
14077
14430
  const truncated2 = buf.length > maxImageBytes;
@@ -14114,9 +14467,9 @@ function assertSafeRelativePath(relativePath) {
14114
14467
  }
14115
14468
  function writeWorktreeFile(worktreePath, relativePath, content) {
14116
14469
  assertSafeRelativePath(relativePath);
14117
- const abs = (0, import_node_path34.join)(worktreePath, relativePath);
14118
- (0, import_node_fs38.mkdirSync)((0, import_node_path34.dirname)(abs), { recursive: true });
14119
- (0, import_node_fs38.writeFileSync)(abs, content, "utf8");
14470
+ const abs = (0, import_node_path35.join)(worktreePath, relativePath);
14471
+ (0, import_node_fs39.mkdirSync)((0, import_node_path35.dirname)(abs), { recursive: true });
14472
+ (0, import_node_fs39.writeFileSync)(abs, content, "utf8");
14120
14473
  return { path: relativePath };
14121
14474
  }
14122
14475
  async function getDiffSummary(worktreePath, repoPath, opts) {
@@ -14133,12 +14486,12 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
14133
14486
  truncated: full.files.length > maxFiles
14134
14487
  };
14135
14488
  }
14136
- var import_node_fs38, import_node_path34, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS, DEFAULT_UPLOAD_MAX_BYTES;
14489
+ var import_node_fs39, import_node_path35, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS, DEFAULT_UPLOAD_MAX_BYTES;
14137
14490
  var init_diff = __esm({
14138
14491
  "src/diff/diff.ts"() {
14139
14492
  "use strict";
14140
- import_node_fs38 = require("fs");
14141
- import_node_path34 = require("path");
14493
+ import_node_fs39 = require("fs");
14494
+ import_node_path35 = require("path");
14142
14495
  init_run();
14143
14496
  init_worktree();
14144
14497
  mergeBaseCache = /* @__PURE__ */ new Map();
@@ -14306,7 +14659,7 @@ function parseFrontmatter(content) {
14306
14659
  }
14307
14660
  function readSkill(skillMd, source) {
14308
14661
  try {
14309
- const content = (0, import_node_fs39.readFileSync)(skillMd, "utf8");
14662
+ const content = (0, import_node_fs40.readFileSync)(skillMd, "utf8");
14310
14663
  const { name: fmName, description } = parseFrontmatter(content);
14311
14664
  const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
14312
14665
  const name = fmName || dirName;
@@ -14325,19 +14678,19 @@ function readSkill(skillMd, source) {
14325
14678
  }
14326
14679
  }
14327
14680
  function scanSkillsDir(dir, source, out) {
14328
- if (!(0, import_node_fs39.existsSync)(dir)) return;
14681
+ if (!(0, import_node_fs40.existsSync)(dir)) return;
14329
14682
  let entries;
14330
14683
  try {
14331
- entries = (0, import_node_fs39.readdirSync)(dir);
14684
+ entries = (0, import_node_fs40.readdirSync)(dir);
14332
14685
  } catch {
14333
14686
  return;
14334
14687
  }
14335
14688
  for (const entry of entries) {
14336
14689
  if (entry.startsWith(".")) continue;
14337
- const skillMd = (0, import_node_path35.join)(dir, entry, "SKILL.md");
14338
- if (!(0, import_node_fs39.existsSync)(skillMd)) continue;
14690
+ const skillMd = (0, import_node_path36.join)(dir, entry, "SKILL.md");
14691
+ if (!(0, import_node_fs40.existsSync)(skillMd)) continue;
14339
14692
  try {
14340
- if (!(0, import_node_fs39.statSync)(skillMd).isFile()) continue;
14693
+ if (!(0, import_node_fs40.statSync)(skillMd).isFile()) continue;
14341
14694
  } catch {
14342
14695
  continue;
14343
14696
  }
@@ -14346,24 +14699,24 @@ function scanSkillsDir(dir, source, out) {
14346
14699
  }
14347
14700
  }
14348
14701
  function scanClaudePluginSkills(pluginsRoot, out) {
14349
- if (!(0, import_node_fs39.existsSync)(pluginsRoot)) return;
14702
+ if (!(0, import_node_fs40.existsSync)(pluginsRoot)) return;
14350
14703
  const walk = (dir, depth, lookingForSkillsDir) => {
14351
14704
  if (depth > 7) return;
14352
14705
  let entries;
14353
14706
  try {
14354
- entries = (0, import_node_fs39.readdirSync)(dir);
14707
+ entries = (0, import_node_fs40.readdirSync)(dir);
14355
14708
  } catch {
14356
14709
  return;
14357
14710
  }
14358
14711
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
14359
- const skill = readSkill((0, import_node_path35.join)(dir, "SKILL.md"), "cli");
14712
+ const skill = readSkill((0, import_node_path36.join)(dir, "SKILL.md"), "cli");
14360
14713
  if (skill) out.push(skill);
14361
14714
  }
14362
14715
  for (const entry of entries) {
14363
14716
  if (entry === "node_modules" || entry === ".git") continue;
14364
- const full = (0, import_node_path35.join)(dir, entry);
14717
+ const full = (0, import_node_path36.join)(dir, entry);
14365
14718
  try {
14366
- if (!(0, import_node_fs39.statSync)(full).isDirectory()) continue;
14719
+ if (!(0, import_node_fs40.statSync)(full).isDirectory()) continue;
14367
14720
  } catch {
14368
14721
  continue;
14369
14722
  }
@@ -14381,17 +14734,17 @@ function discoverSkills(worktreePath) {
14381
14734
  const home = (0, import_node_os11.homedir)();
14382
14735
  const collected = [];
14383
14736
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
14384
- scanSkillsDir((0, import_node_path35.join)(worktreePath, rel), "workspace", collected);
14737
+ scanSkillsDir((0, import_node_path36.join)(worktreePath, rel), "workspace", collected);
14385
14738
  }
14386
14739
  for (const abs of [
14387
- (0, import_node_path35.join)(home, ".claude/skills"),
14388
- (0, import_node_path35.join)(home, ".cursor/skills"),
14389
- (0, import_node_path35.join)(home, ".sideboard/skills"),
14390
- (0, import_node_path35.join)(home, ".brightsy/skills")
14740
+ (0, import_node_path36.join)(home, ".claude/skills"),
14741
+ (0, import_node_path36.join)(home, ".cursor/skills"),
14742
+ (0, import_node_path36.join)(home, ".sideboard/skills"),
14743
+ (0, import_node_path36.join)(home, ".brightsy/skills")
14391
14744
  ]) {
14392
14745
  scanSkillsDir(abs, "user", collected);
14393
14746
  }
14394
- scanClaudePluginSkills((0, import_node_path35.join)(home, ".claude/plugins"), collected);
14747
+ scanClaudePluginSkills((0, import_node_path36.join)(home, ".claude/plugins"), collected);
14395
14748
  const rank = { workspace: 0, user: 1, cli: 2 };
14396
14749
  const byCommand = /* @__PURE__ */ new Map();
14397
14750
  for (const skill of collected) {
@@ -14403,7 +14756,7 @@ function discoverSkills(worktreePath) {
14403
14756
  return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
14404
14757
  }
14405
14758
  function readSkillBody(skillPath, maxChars = 12e3) {
14406
- const raw = (0, import_node_fs39.readFileSync)(skillPath, "utf8");
14759
+ const raw = (0, import_node_fs40.readFileSync)(skillPath, "utf8");
14407
14760
  if (raw.startsWith("---")) {
14408
14761
  const end = raw.indexOf("\n---", 3);
14409
14762
  if (end >= 0) {
@@ -14417,13 +14770,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
14417
14770
 
14418
14771
  \u2026(truncated)` : raw;
14419
14772
  }
14420
- var import_node_fs39, import_node_os11, import_node_path35;
14773
+ var import_node_fs40, import_node_os11, import_node_path36;
14421
14774
  var init_discover = __esm({
14422
14775
  "src/skills/discover.ts"() {
14423
14776
  "use strict";
14424
- import_node_fs39 = require("fs");
14777
+ import_node_fs40 = require("fs");
14425
14778
  import_node_os11 = require("os");
14426
- import_node_path35 = require("path");
14779
+ import_node_path36 = require("path");
14427
14780
  }
14428
14781
  });
14429
14782
 
@@ -14514,7 +14867,7 @@ var init_expand = __esm({
14514
14867
 
14515
14868
  // src/composer/stage-files.ts
14516
14869
  function fileExtension(filePath) {
14517
- const base = (0, import_node_path36.basename)(filePath).toLowerCase();
14870
+ const base = (0, import_node_path37.basename)(filePath).toLowerCase();
14518
14871
  return base.includes(".") ? base.split(".").pop() || "" : "";
14519
14872
  }
14520
14873
  function isImageFilePath(filePath) {
@@ -14524,22 +14877,22 @@ function imageMimeType(filePath) {
14524
14877
  return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
14525
14878
  }
14526
14879
  function ensureAttachmentsDir(worktreePath) {
14527
- const dir = (0, import_node_path36.join)(worktreePath, ATTACHMENTS_DIR);
14528
- (0, import_node_fs40.mkdirSync)(dir, { recursive: true });
14529
- const gi = (0, import_node_path36.join)(dir, ".gitignore");
14530
- if (!(0, import_node_fs40.existsSync)(gi)) {
14531
- (0, import_node_fs40.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
14880
+ const dir = (0, import_node_path37.join)(worktreePath, ATTACHMENTS_DIR);
14881
+ (0, import_node_fs41.mkdirSync)(dir, { recursive: true });
14882
+ const gi = (0, import_node_path37.join)(dir, ".gitignore");
14883
+ if (!(0, import_node_fs41.existsSync)(gi)) {
14884
+ (0, import_node_fs41.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
14532
14885
  }
14533
14886
  return dir;
14534
14887
  }
14535
14888
  function uniqueAttachmentName(dir, originalName) {
14536
14889
  const safe = originalName.replace(/[/\\]/g, "_") || "file";
14537
- if (!(0, import_node_fs40.existsSync)((0, import_node_path36.join)(dir, safe))) return safe;
14538
- const ext = (0, import_node_path36.extname)(safe);
14890
+ if (!(0, import_node_fs41.existsSync)((0, import_node_path37.join)(dir, safe))) return safe;
14891
+ const ext = (0, import_node_path37.extname)(safe);
14539
14892
  const stem = ext ? safe.slice(0, -ext.length) : safe;
14540
14893
  for (let i = 1; i < 1e4; i++) {
14541
14894
  const candidate = `${stem}-${i}${ext}`;
14542
- if (!(0, import_node_fs40.existsSync)((0, import_node_path36.join)(dir, candidate))) return candidate;
14895
+ if (!(0, import_node_fs41.existsSync)((0, import_node_path37.join)(dir, candidate))) return candidate;
14543
14896
  }
14544
14897
  return `${stem}-${(0, import_node_crypto8.randomUUID)()}${ext}`;
14545
14898
  }
@@ -14591,9 +14944,9 @@ function attachmentFromBuffer(name, buf, opts) {
14591
14944
  };
14592
14945
  }
14593
14946
  function attachmentFromAbsolutePath(absolutePath) {
14594
- const name = (0, import_node_path36.basename)(absolutePath);
14947
+ const name = (0, import_node_path37.basename)(absolutePath);
14595
14948
  try {
14596
- const st = (0, import_node_fs40.statSync)(absolutePath);
14949
+ const st = (0, import_node_fs41.statSync)(absolutePath);
14597
14950
  if (!st.isFile()) {
14598
14951
  return {
14599
14952
  id: (0, import_node_crypto8.randomUUID)(),
@@ -14602,7 +14955,7 @@ function attachmentFromAbsolutePath(absolutePath) {
14602
14955
  content: `(not a file: ${absolutePath})`
14603
14956
  };
14604
14957
  }
14605
- const buf = (0, import_node_fs40.readFileSync)(absolutePath);
14958
+ const buf = (0, import_node_fs41.readFileSync)(absolutePath);
14606
14959
  return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
14607
14960
  } catch (err) {
14608
14961
  return {
@@ -14618,15 +14971,15 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
14618
14971
  const dir = ensureAttachmentsDir(worktreePath);
14619
14972
  const out = [];
14620
14973
  for (const abs of absolutePaths) {
14621
- const originalName = (0, import_node_path36.basename)(abs);
14974
+ const originalName = (0, import_node_path37.basename)(abs);
14622
14975
  try {
14623
- const st = (0, import_node_fs40.statSync)(abs);
14976
+ const st = (0, import_node_fs41.statSync)(abs);
14624
14977
  if (!st.isFile()) continue;
14625
14978
  const name = uniqueAttachmentName(dir, originalName);
14626
- const destAbs = (0, import_node_path36.join)(dir, name);
14627
- (0, import_node_fs40.copyFileSync)(abs, destAbs);
14979
+ const destAbs = (0, import_node_path37.join)(dir, name);
14980
+ (0, import_node_fs41.copyFileSync)(abs, destAbs);
14628
14981
  const rel = `${ATTACHMENTS_DIR}/${name}`;
14629
- const buf = (0, import_node_fs40.readFileSync)(destAbs);
14982
+ const buf = (0, import_node_fs41.readFileSync)(destAbs);
14630
14983
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
14631
14984
  } catch (err) {
14632
14985
  out.push({
@@ -14648,8 +15001,8 @@ function stageBuffersAsAttachments(worktreePath, buffers2) {
14648
15001
  try {
14649
15002
  const buf = Buffer.from(item.dataBase64, "base64");
14650
15003
  const name = uniqueAttachmentName(dir, originalName);
14651
- const destAbs = (0, import_node_path36.join)(dir, name);
14652
- (0, import_node_fs40.writeFileSync)(destAbs, buf);
15004
+ const destAbs = (0, import_node_path37.join)(dir, name);
15005
+ (0, import_node_fs41.writeFileSync)(destAbs, buf);
14653
15006
  const rel = `${ATTACHMENTS_DIR}/${name}`;
14654
15007
  out.push(attachmentFromBuffer(name, buf, { path: rel }));
14655
15008
  } catch (err) {
@@ -14685,18 +15038,18 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
14685
15038
  if (!rel || rel.includes("..") || rel.startsWith("/")) {
14686
15039
  out.push({
14687
15040
  id: (0, import_node_crypto8.randomUUID)(),
14688
- name: (0, import_node_path36.basename)(rel) || "file",
15041
+ name: (0, import_node_path37.basename)(rel) || "file",
14689
15042
  kind: "file",
14690
15043
  content: `(invalid path: ${rel})`
14691
15044
  });
14692
15045
  continue;
14693
15046
  }
14694
- const name = (0, import_node_path36.basename)(rel);
15047
+ const name = (0, import_node_path37.basename)(rel);
14695
15048
  try {
14696
- const abs = (0, import_node_path36.join)(worktreePath, rel);
14697
- const st = (0, import_node_fs40.statSync)(abs);
15049
+ const abs = (0, import_node_path37.join)(worktreePath, rel);
15050
+ const st = (0, import_node_fs41.statSync)(abs);
14698
15051
  if (!st.isFile()) continue;
14699
- const buf = (0, import_node_fs40.readFileSync)(abs);
15052
+ const buf = (0, import_node_fs41.readFileSync)(abs);
14700
15053
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
14701
15054
  } catch (err) {
14702
15055
  out.push({
@@ -14709,12 +15062,12 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
14709
15062
  }
14710
15063
  return out;
14711
15064
  }
14712
- var import_node_fs40, import_node_path36, import_node_crypto8, IMAGE_EXTENSIONS2, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES;
15065
+ var import_node_fs41, import_node_path37, import_node_crypto8, IMAGE_EXTENSIONS2, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES;
14713
15066
  var init_stage_files = __esm({
14714
15067
  "src/composer/stage-files.ts"() {
14715
15068
  "use strict";
14716
- import_node_fs40 = require("fs");
14717
- import_node_path36 = require("path");
15069
+ import_node_fs41 = require("fs");
15070
+ import_node_path37 = require("path");
14718
15071
  import_node_crypto8 = require("crypto");
14719
15072
  init_workspace_scratch();
14720
15073
  IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
@@ -14890,11 +15243,11 @@ function loadAgentInstructions(worktreePath, agent) {
14890
15243
  const out = [];
14891
15244
  for (const rel of candidates) {
14892
15245
  if (seenPaths.has(rel)) continue;
14893
- const abs = (0, import_node_path37.join)(worktreePath, rel);
14894
- if (!(0, import_node_fs41.existsSync)(abs)) continue;
15246
+ const abs = (0, import_node_path38.join)(worktreePath, rel);
15247
+ if (!(0, import_node_fs42.existsSync)(abs)) continue;
14895
15248
  try {
14896
- if (!(0, import_node_fs41.statSync)(abs).isFile()) continue;
14897
- let content = (0, import_node_fs41.readFileSync)(abs, "utf8");
15249
+ if (!(0, import_node_fs42.statSync)(abs).isFile()) continue;
15250
+ let content = (0, import_node_fs42.readFileSync)(abs, "utf8");
14898
15251
  if (!content.trim()) continue;
14899
15252
  if (content.length > MAX_CHARS_PER_FILE) {
14900
15253
  content = `${content.slice(0, MAX_CHARS_PER_FILE)}
@@ -14934,12 +15287,12 @@ function withAgentInstructions(prompt, files) {
14934
15287
 
14935
15288
  ${prompt}`;
14936
15289
  }
14937
- var import_node_fs41, import_node_path37, FILES_BY_AGENT, MAX_CHARS_PER_FILE;
15290
+ var import_node_fs42, import_node_path38, FILES_BY_AGENT, MAX_CHARS_PER_FILE;
14938
15291
  var init_instructions = __esm({
14939
15292
  "src/agents/instructions.ts"() {
14940
15293
  "use strict";
14941
- import_node_fs41 = require("fs");
14942
- import_node_path37 = require("path");
15294
+ import_node_fs42 = require("fs");
15295
+ import_node_path38 = require("path");
14943
15296
  init_git_auth_mode();
14944
15297
  init_worktree_labels();
14945
15298
  FILES_BY_AGENT = {
@@ -15029,40 +15382,40 @@ __export(plan_file_exports, {
15029
15382
  writePlanFile: () => writePlanFile
15030
15383
  });
15031
15384
  function ensureAttachmentsGitignore(worktreePath) {
15032
- const gitignoreAbs = (0, import_node_path38.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
15033
- if ((0, import_node_fs42.existsSync)(gitignoreAbs)) return;
15034
- (0, import_node_fs42.mkdirSync)((0, import_node_path38.dirname)(gitignoreAbs), { recursive: true });
15035
- (0, import_node_fs42.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
15385
+ const gitignoreAbs = (0, import_node_path39.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
15386
+ if ((0, import_node_fs43.existsSync)(gitignoreAbs)) return;
15387
+ (0, import_node_fs43.mkdirSync)((0, import_node_path39.dirname)(gitignoreAbs), { recursive: true });
15388
+ (0, import_node_fs43.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
15036
15389
  }
15037
15390
  function planFileAbs(worktreePath) {
15038
- return (0, import_node_path38.join)(worktreePath, PLAN_FILE_REL);
15391
+ return (0, import_node_path39.join)(worktreePath, PLAN_FILE_REL);
15039
15392
  }
15040
15393
  function readTextIfPresent2(abs) {
15041
- if (!(0, import_node_fs42.existsSync)(abs)) return null;
15394
+ if (!(0, import_node_fs43.existsSync)(abs)) return null;
15042
15395
  try {
15043
- const content = (0, import_node_fs42.readFileSync)(abs, "utf8");
15396
+ const content = (0, import_node_fs43.readFileSync)(abs, "utf8");
15044
15397
  return content.trim() ? content : null;
15045
15398
  } catch {
15046
15399
  return null;
15047
15400
  }
15048
15401
  }
15049
15402
  function readPlanFile(worktreePath) {
15050
- return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path38.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path38.join)(worktreePath, LEGACY_PLAN_FILE_REL));
15403
+ return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path39.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path39.join)(worktreePath, LEGACY_PLAN_FILE_REL));
15051
15404
  }
15052
15405
  function writePlanFile(worktreePath, content) {
15053
15406
  ensureAttachmentsGitignore(worktreePath);
15054
15407
  const abs = planFileAbs(worktreePath);
15055
- (0, import_node_fs42.mkdirSync)((0, import_node_path38.dirname)(abs), { recursive: true });
15408
+ (0, import_node_fs43.mkdirSync)((0, import_node_path39.dirname)(abs), { recursive: true });
15056
15409
  const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
15057
- (0, import_node_fs42.writeFileSync)(abs, body, "utf8");
15410
+ (0, import_node_fs43.writeFileSync)(abs, body, "utf8");
15058
15411
  return PLAN_FILE_REL;
15059
15412
  }
15060
- var import_node_fs42, import_node_path38;
15413
+ var import_node_fs43, import_node_path39;
15061
15414
  var init_plan_file = __esm({
15062
15415
  "src/plan/plan-file.ts"() {
15063
15416
  "use strict";
15064
- import_node_fs42 = require("fs");
15065
- import_node_path38 = require("path");
15417
+ import_node_fs43 = require("fs");
15418
+ import_node_path39 = require("path");
15066
15419
  init_workspace_scratch();
15067
15420
  init_plan_present();
15068
15421
  init_plan_present();
@@ -15116,10 +15469,10 @@ __export(cursor_recover_exports, {
15116
15469
  function recoverFinishedCursorRun(opts) {
15117
15470
  const agentId = opts.agentId.trim();
15118
15471
  if (!agentId) return null;
15119
- const runsPath = (0, import_node_path39.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
15120
- if (!(0, import_node_fs43.existsSync)(runsPath)) return null;
15472
+ const runsPath = (0, import_node_path40.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
15473
+ if (!(0, import_node_fs44.existsSync)(runsPath)) return null;
15121
15474
  try {
15122
- const lines = (0, import_node_fs43.readFileSync)(runsPath, "utf8").split("\n");
15475
+ const lines = (0, import_node_fs44.readFileSync)(runsPath, "utf8").split("\n");
15123
15476
  let best = null;
15124
15477
  for (const line of lines) {
15125
15478
  const trimmed = line.trim();
@@ -15145,12 +15498,12 @@ function recoverFinishedCursorRun(opts) {
15145
15498
  return null;
15146
15499
  }
15147
15500
  }
15148
- var import_node_fs43, import_node_path39;
15501
+ var import_node_fs44, import_node_path40;
15149
15502
  var init_cursor_recover = __esm({
15150
15503
  "src/agents/cursor-recover.ts"() {
15151
15504
  "use strict";
15152
- import_node_fs43 = require("fs");
15153
- import_node_path39 = require("path");
15505
+ import_node_fs44 = require("fs");
15506
+ import_node_path40 = require("path");
15154
15507
  init_paths();
15155
15508
  }
15156
15509
  });
@@ -15281,14 +15634,16 @@ async function startOrchestration(opts) {
15281
15634
  }
15282
15635
  return updated;
15283
15636
  }
15284
- var import_node_events, import_node_fs44, STALE_AGENT_PID_WAIT_MS, Orchestrator, singleton;
15637
+ var import_node_events, import_node_fs45, STALE_AGENT_PID_WAIT_MS, Orchestrator, singleton;
15285
15638
  var init_orchestrator = __esm({
15286
15639
  "src/orchestrator/orchestrator.ts"() {
15287
15640
  "use strict";
15288
15641
  import_node_events = require("events");
15289
15642
  init_outbound_watch();
15290
- import_node_fs44 = require("fs");
15643
+ import_node_fs45 = require("fs");
15291
15644
  init_error_detail();
15645
+ init_run();
15646
+ init_stale_lock();
15292
15647
  init_spawn();
15293
15648
  init_agents();
15294
15649
  init_worktree();
@@ -15404,7 +15759,7 @@ var init_orchestrator = __esm({
15404
15759
  }
15405
15760
  continue;
15406
15761
  }
15407
- if (!(0, import_node_fs44.existsSync)(thread.worktreePath)) {
15762
+ if (!(0, import_node_fs45.existsSync)(thread.worktreePath)) {
15408
15763
  setStatus(thread.id, "broken", "Worktree missing on disk");
15409
15764
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
15410
15765
  continue;
@@ -15997,7 +16352,15 @@ var init_orchestrator = __esm({
15997
16352
  hasSession: Boolean(this.requireThread(threadId).sessionId)
15998
16353
  })) {
15999
16354
  updateThread(threadId, { sessionId: null });
16000
- const retryNote = looksLikeInvalidAgentSession(detail) ? "Agent session missing \u2014 starting a fresh session" : "Agent runner crashed \u2014 restarting Node once";
16355
+ try {
16356
+ const gitDirs = await resolveGitDirsForLockRecovery(thread.worktreePath);
16357
+ const clearedLocks = clearStaleIndexLocks(gitDirs, 2e3);
16358
+ if (clearedLocks.length > 0) {
16359
+ pushTurnStderr(stderrTail, "Cleared a stale git lock left by the crashed agent process");
16360
+ }
16361
+ } catch {
16362
+ }
16363
+ const retryNote = looksLikeInvalidAgentSession(detail) ? "Agent session missing \u2014 starting a fresh session" : looksLikeV8Oom(detail) ? "Agent ran out of memory \u2014 starting a fresh session" : "Agent runner crashed \u2014 restarting Node once";
16001
16364
  pushTurnStderr(stderrTail, retryNote);
16002
16365
  this.emit({
16003
16366
  type: "turn_output",
@@ -16469,13 +16832,14 @@ var init_orchestrator = __esm({
16469
16832
  const text4 = (lastAgent?.text ?? "").trim() || (thread.status === "error" ? lastError ?? "" : "");
16470
16833
  const stillRunning = thread.status === "running" || thread.status === "queued";
16471
16834
  const live = stillRunning ? readTurnLive(thread.id) : null;
16835
+ const queuedHint = thread.status === "queued" && !live?.summary ? "Queued \u2014 waiting for a concurrency slot" : null;
16472
16836
  return {
16473
16837
  text: text4,
16474
16838
  status: thread.status,
16475
16839
  sessionId: thread.sessionId,
16476
16840
  lastError,
16477
16841
  stillRunning,
16478
- progress: live?.summary ?? null,
16842
+ progress: live?.summary ?? queuedHint,
16479
16843
  lastActivityAt: live?.updatedAt ?? null
16480
16844
  };
16481
16845
  }
@@ -16992,7 +17356,7 @@ var init_orchestrator = __esm({
16992
17356
  this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
16993
17357
  return restored2;
16994
17358
  }
16995
- if (!(0, import_node_fs44.existsSync)(thread.worktreePath)) {
17359
+ if (!(0, import_node_fs45.existsSync)(thread.worktreePath)) {
16996
17360
  if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
16997
17361
  throw new Error(
16998
17362
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
@@ -17194,6 +17558,7 @@ var init_schedule_runner = __esm({
17194
17558
  var index_exports = {};
17195
17559
  __export(index_exports, {
17196
17560
  AGENT_GIT_ACTIONS: () => AGENT_GIT_ACTIONS,
17561
+ AGENT_RUNNER_MAX_OLD_SPACE_MB: () => AGENT_RUNNER_MAX_OLD_SPACE_MB,
17197
17562
  ATTACHMENTS_DIR: () => ATTACHMENTS_DIR,
17198
17563
  BAKED_SLACK_RELAY_URL: () => BAKED_SLACK_RELAY_URL,
17199
17564
  BRIGHTSY_MCP_ALLOWED_TOOLS: () => BRIGHTSY_MCP_ALLOWED_TOOLS,
@@ -17269,6 +17634,7 @@ __export(index_exports, {
17269
17634
  appendIndexedGitConfig: () => appendIndexedGitConfig,
17270
17635
  appendMessage: () => appendMessage,
17271
17636
  applyAgentEvent: () => applyAgentEvent,
17637
+ applyAgentRunnerHeapEnv: () => applyAgentRunnerHeapEnv,
17272
17638
  applyAppEnvironment: () => applyAppEnvironment,
17273
17639
  applyCompaction: () => applyCompaction,
17274
17640
  applyGithubGitAuthEnv: () => applyGithubGitAuthEnv,
@@ -17502,6 +17868,7 @@ __export(index_exports, {
17502
17868
  isOrchestratorThread: () => isOrchestratorThread,
17503
17869
  isPidAlive: () => isPidAlive,
17504
17870
  isPlaceholderBranch: () => isPlaceholderBranch,
17871
+ isPollWrapperToolName: () => isPollWrapperToolName,
17505
17872
  isPrNotMergeableError: () => isPrNotMergeableError,
17506
17873
  isPresentPlanToolName: () => isPresentPlanToolName,
17507
17874
  isPrimaryCheckoutThread: () => isPrimaryCheckoutThread,
@@ -17547,6 +17914,7 @@ __export(index_exports, {
17547
17914
  listWorkspaces: () => listWorkspaces,
17548
17915
  listWorktreeFiles: () => listWorktreeFiles,
17549
17916
  listWorktrees: () => listWorktrees,
17917
+ liveActivitySummary: () => liveActivitySummary,
17550
17918
  loadAgentInstructions: () => loadAgentInstructions,
17551
17919
  loadAppSettings: () => loadAppSettings,
17552
17920
  loadBrightsyConfig: () => loadBrightsyConfig,
@@ -17640,6 +18008,7 @@ __export(index_exports, {
17640
18008
  resolveEffectiveIssueSource: () => resolveEffectiveIssueSource,
17641
18009
  resolveFilesToCopy: () => resolveFilesToCopy,
17642
18010
  resolveGhAuthToken: () => resolveGhAuthToken,
18011
+ resolveGitDirsForLockRecovery: () => resolveGitDirsForLockRecovery,
17643
18012
  resolveGithubAgentToken: () => resolveGithubAgentToken,
17644
18013
  resolveGithubRepoSlug: () => resolveGithubRepoSlug,
17645
18014
  resolveLinearState: () => resolveLinearState,
@@ -17733,6 +18102,7 @@ __export(index_exports, {
17733
18102
  threadsDir: () => threadsDir,
17734
18103
  threadsSharingWorktree: () => threadsSharingWorktree,
17735
18104
  toPublicAppSettings: () => toPublicAppSettings,
18105
+ toolActivityLine: () => toolActivityLine,
17736
18106
  toolDescription: () => toolDescription,
17737
18107
  toolDetail: () => toolDetail,
17738
18108
  toolFilePath: () => toolFilePath,
@@ -17758,6 +18128,7 @@ __export(index_exports, {
17758
18128
  withEventParentId: () => withEventParentId,
17759
18129
  withEventsParentId: () => withEventsParentId,
17760
18130
  withExportedPath: () => withExportedPath,
18131
+ withMaxOldSpaceSize: () => withMaxOldSpaceSize,
17761
18132
  withThreadLock: () => withThreadLock,
17762
18133
  workspaceSettingsSourceLabel: () => workspaceSettingsSourceLabel,
17763
18134
  worktreeCleanupSettings: () => worktreeCleanupSettings,
@@ -18729,7 +19100,7 @@ init_orphan_cleanup();
18729
19100
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
18730
19101
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
18731
19102
  var import_zod4 = require("zod");
18732
- var import_node_path40 = require("path");
19103
+ var import_node_path41 = require("path");
18733
19104
  init_orchestrator();
18734
19105
  init_worktree();
18735
19106
  init_create();
@@ -18756,6 +19127,10 @@ function mcpWaitForTurnTimeoutMs(requested) {
18756
19127
  return Math.min(Math.max(1e3, Math.floor(n)), MCP_WAIT_FOR_TURN_MAX_MS);
18757
19128
  }
18758
19129
  var MCP_WAIT_STILL_RUNNING_HINT = "Child is still working. Call wait_for_turn again. Do not send a check-in prompt or assume a hang while progress is updating.";
19130
+ var MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u2014 it has not started yet. Call wait_for_turn again. Do not send a check-in prompt, force_stop, or assume it failed to start.";
19131
+ function mcpWaitStillRunningHint(status) {
19132
+ return status === "queued" ? MCP_WAIT_QUEUED_HINT : MCP_WAIT_STILL_RUNNING_HINT;
19133
+ }
18759
19134
 
18760
19135
  // src/mcp/server.ts
18761
19136
  init_turn_live();
@@ -19602,7 +19977,7 @@ async function startMcpServer() {
19602
19977
  async () => {
19603
19978
  const threads = orch.getThreads(true);
19604
19979
  const lines = threads.map((t) => {
19605
- const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path40.basename)(t.repoPath) || t.repoPath;
19980
+ const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path41.basename)(t.repoPath) || t.repoPath;
19606
19981
  const live = t.status === "running" || t.status === "queued" ? readTurnLive(t.id) : null;
19607
19982
  const progress = live?.summary ? ` ${live.summary}` : "";
19608
19983
  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}` : ""}${progress}`;
@@ -19638,7 +20013,7 @@ async function startMcpServer() {
19638
20013
  prUrl: t.prUrl,
19639
20014
  lastError: t.lastError ?? null,
19640
20015
  stillRunning: t.status === "running" || t.status === "queued",
19641
- progress: live?.summary ?? null,
20016
+ progress: live?.summary ?? (t.status === "queued" ? "Queued \u2014 waiting for a concurrency slot" : null),
19642
20017
  lastActivityAt: live?.updatedAt ?? null
19643
20018
  };
19644
20019
  return { content: [{ type: "text", text: JSON.stringify(summary, null, 2) }] };
@@ -19972,7 +20347,7 @@ async function startMcpServer() {
19972
20347
  );
19973
20348
  server.tool(
19974
20349
  "wait_for_turn",
19975
- "Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. If stillRunning is true, progress is tools/thinking \u2014 call wait_for_turn again. Do not send a check-in prompt or assume a hang. On status error, lastError/text is the failure.",
20350
+ "Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not send a check-in prompt, force_stop, or assume a hang. On status error, lastError/text is the failure.",
19976
20351
  {
19977
20352
  ref: import_zod4.z.string(),
19978
20353
  timeoutMs: import_zod4.z.number().optional()
@@ -19994,7 +20369,7 @@ async function startMcpServer() {
19994
20369
  stillRunning: result.stillRunning,
19995
20370
  progress: result.progress,
19996
20371
  lastActivityAt: result.lastActivityAt,
19997
- hint: result.stillRunning ? MCP_WAIT_STILL_RUNNING_HINT : void 0
20372
+ hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) : void 0
19998
20373
  })
19999
20374
  }
20000
20375
  ]
@@ -20013,7 +20388,7 @@ async function startMcpServer() {
20013
20388
  type: "text",
20014
20389
  text: JSON.stringify({
20015
20390
  ...result,
20016
- hint: result.stillRunning ? MCP_WAIT_STILL_RUNNING_HINT : void 0
20391
+ hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) : void 0
20017
20392
  })
20018
20393
  }
20019
20394
  ]
@@ -20942,16 +21317,16 @@ init_connected_teams();
20942
21317
  init_injected_mcp();
20943
21318
 
20944
21319
  // src/agents/user-mcp-config.ts
20945
- var import_node_fs45 = require("fs");
21320
+ var import_node_fs46 = require("fs");
20946
21321
  var import_node_os12 = require("os");
20947
- var import_node_path41 = require("path");
21322
+ var import_node_path42 = require("path");
20948
21323
  init_paths();
20949
21324
  init_injected_mcp();
20950
21325
  function userCursorMcpConfigPath() {
20951
- return (0, import_node_path41.join)((0, import_node_os12.homedir)(), ".cursor", "mcp.json");
21326
+ return (0, import_node_path42.join)((0, import_node_os12.homedir)(), ".cursor", "mcp.json");
20952
21327
  }
20953
21328
  function userClaudeMcpConfigPath() {
20954
- return (0, import_node_path41.join)((0, import_node_os12.homedir)(), ".claude.json");
21329
+ return (0, import_node_path42.join)((0, import_node_os12.homedir)(), ".claude.json");
20955
21330
  }
20956
21331
  function asObject(value) {
20957
21332
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
@@ -20978,16 +21353,16 @@ function mergeSideboardIntoMcpServersJson(existing, sideboard) {
20978
21353
  }
20979
21354
  function writeMergedMcpServersJson(configPath, sideboard) {
20980
21355
  let existing = {};
20981
- if ((0, import_node_fs45.existsSync)(configPath)) {
21356
+ if ((0, import_node_fs46.existsSync)(configPath)) {
20982
21357
  try {
20983
- existing = JSON.parse((0, import_node_fs45.readFileSync)(configPath, "utf8"));
21358
+ existing = JSON.parse((0, import_node_fs46.readFileSync)(configPath, "utf8"));
20984
21359
  } catch {
20985
21360
  existing = {};
20986
21361
  }
20987
21362
  }
20988
21363
  const next = mergeSideboardIntoMcpServersJson(existing, sideboard);
20989
- (0, import_node_fs45.mkdirSync)((0, import_node_path41.dirname)(configPath), { recursive: true });
20990
- (0, import_node_fs45.writeFileSync)(configPath, `${JSON.stringify(next, null, 2)}
21364
+ (0, import_node_fs46.mkdirSync)((0, import_node_path42.dirname)(configPath), { recursive: true });
21365
+ (0, import_node_fs46.writeFileSync)(configPath, `${JSON.stringify(next, null, 2)}
20991
21366
  `);
20992
21367
  }
20993
21368
  function launchFromResolved(server) {
@@ -21005,7 +21380,7 @@ async function registerPackagedUserMcpClients() {
21005
21380
  const cursor = userCursorMcpConfigPath();
21006
21381
  writeMergedMcpServersJson(cursor, launch);
21007
21382
  const claude = userClaudeMcpConfigPath();
21008
- if ((0, import_node_fs45.existsSync)(claude)) {
21383
+ if ((0, import_node_fs46.existsSync)(claude)) {
21009
21384
  writeMergedMcpServersJson(claude, launch);
21010
21385
  return { cursor, claude };
21011
21386
  }
@@ -22635,9 +23010,9 @@ var import_node_http3 = require("http");
22635
23010
  var import_ws3 = require("ws");
22636
23011
 
22637
23012
  // src/slack/relay-static.ts
22638
- var import_node_fs46 = require("fs");
23013
+ var import_node_fs47 = require("fs");
22639
23014
  var import_promises = require("fs/promises");
22640
- var import_node_path42 = __toESM(require("path"), 1);
23015
+ var import_node_path43 = __toESM(require("path"), 1);
22641
23016
  var TYPES = {
22642
23017
  ".css": "text/css; charset=utf-8",
22643
23018
  ".html": "text/html; charset=utf-8",
@@ -22668,9 +23043,9 @@ function resolveStaticPath(root, requestUrl) {
22668
23043
  return null;
22669
23044
  }
22670
23045
  if (!pathname.startsWith("/") || pathname.includes("\0")) return null;
22671
- const rootResolved = import_node_path42.default.resolve(root);
22672
- const candidate = import_node_path42.default.resolve(rootResolved, `.${pathname}`);
22673
- if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path42.default.sep)) {
23046
+ const rootResolved = import_node_path43.default.resolve(root);
23047
+ const candidate = import_node_path43.default.resolve(rootResolved, `.${pathname}`);
23048
+ if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path43.default.sep)) {
22674
23049
  return null;
22675
23050
  }
22676
23051
  return candidate;
@@ -22684,7 +23059,7 @@ async function fileSize(file) {
22684
23059
  }
22685
23060
  }
22686
23061
  function sendFile(req, res, file, size) {
22687
- const ext = import_node_path42.default.extname(file).toLowerCase();
23062
+ const ext = import_node_path43.default.extname(file).toLowerCase();
22688
23063
  res.writeHead(200, {
22689
23064
  "Content-Type": TYPES[ext] ?? "application/octet-stream",
22690
23065
  "Content-Length": size,
@@ -22694,7 +23069,7 @@ function sendFile(req, res, file, size) {
22694
23069
  res.end();
22695
23070
  return true;
22696
23071
  }
22697
- (0, import_node_fs46.createReadStream)(file).pipe(res);
23072
+ (0, import_node_fs47.createReadStream)(file).pipe(res);
22698
23073
  return true;
22699
23074
  }
22700
23075
  async function tryServeStatic(req, res, root) {
@@ -22703,7 +23078,7 @@ async function tryServeStatic(req, res, root) {
22703
23078
  if (!candidate) return false;
22704
23079
  const direct = await fileSize(candidate);
22705
23080
  if (direct != null) return sendFile(req, res, candidate, direct);
22706
- const asIndex = import_node_path42.default.join(candidate, "index.html");
23081
+ const asIndex = import_node_path43.default.join(candidate, "index.html");
22707
23082
  const indexSize = await fileSize(asIndex);
22708
23083
  if (indexSize != null) return sendFile(req, res, asIndex, indexSize);
22709
23084
  return false;
@@ -22939,6 +23314,7 @@ init_outbound_watch();
22939
23314
  // Annotate the CommonJS export names for ESM import in node:
22940
23315
  0 && (module.exports = {
22941
23316
  AGENT_GIT_ACTIONS,
23317
+ AGENT_RUNNER_MAX_OLD_SPACE_MB,
22942
23318
  ATTACHMENTS_DIR,
22943
23319
  BAKED_SLACK_RELAY_URL,
22944
23320
  BRIGHTSY_MCP_ALLOWED_TOOLS,
@@ -23014,6 +23390,7 @@ init_outbound_watch();
23014
23390
  appendIndexedGitConfig,
23015
23391
  appendMessage,
23016
23392
  applyAgentEvent,
23393
+ applyAgentRunnerHeapEnv,
23017
23394
  applyAppEnvironment,
23018
23395
  applyCompaction,
23019
23396
  applyGithubGitAuthEnv,
@@ -23247,6 +23624,7 @@ init_outbound_watch();
23247
23624
  isOrchestratorThread,
23248
23625
  isPidAlive,
23249
23626
  isPlaceholderBranch,
23627
+ isPollWrapperToolName,
23250
23628
  isPrNotMergeableError,
23251
23629
  isPresentPlanToolName,
23252
23630
  isPrimaryCheckoutThread,
@@ -23292,6 +23670,7 @@ init_outbound_watch();
23292
23670
  listWorkspaces,
23293
23671
  listWorktreeFiles,
23294
23672
  listWorktrees,
23673
+ liveActivitySummary,
23295
23674
  loadAgentInstructions,
23296
23675
  loadAppSettings,
23297
23676
  loadBrightsyConfig,
@@ -23385,6 +23764,7 @@ init_outbound_watch();
23385
23764
  resolveEffectiveIssueSource,
23386
23765
  resolveFilesToCopy,
23387
23766
  resolveGhAuthToken,
23767
+ resolveGitDirsForLockRecovery,
23388
23768
  resolveGithubAgentToken,
23389
23769
  resolveGithubRepoSlug,
23390
23770
  resolveLinearState,
@@ -23478,6 +23858,7 @@ init_outbound_watch();
23478
23858
  threadsDir,
23479
23859
  threadsSharingWorktree,
23480
23860
  toPublicAppSettings,
23861
+ toolActivityLine,
23481
23862
  toolDescription,
23482
23863
  toolDetail,
23483
23864
  toolFilePath,
@@ -23503,6 +23884,7 @@ init_outbound_watch();
23503
23884
  withEventParentId,
23504
23885
  withEventsParentId,
23505
23886
  withExportedPath,
23887
+ withMaxOldSpaceSize,
23506
23888
  withThreadLock,
23507
23889
  workspaceSettingsSourceLabel,
23508
23890
  worktreeCleanupSettings,