@sideboard-ai/core 0.1.135 → 0.1.136

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 (27) hide show
  1. package/dist/{agents-O3AJMI2Y.js → agents-ELWR7A2T.js} +3 -3
  2. package/dist/{agents-RTQFF7PY.js → agents-QNTTLMG2.js} +3 -3
  3. package/dist/{chunk-RDULVW3E.js → chunk-4XKUHP6G.js} +1 -1
  4. package/dist/{chunk-N62K3KXX.js → chunk-CYM5DCHI.js} +38 -4
  5. package/dist/{chunk-XUEI4GCF.js → chunk-GSKRGF7B.js} +284 -3
  6. package/dist/{chunk-57GIFU3X.js → chunk-IFZ4MOTN.js} +2 -2
  7. package/dist/{chunk-KBBXNS2V.js → chunk-JPBRMUM6.js} +8 -4
  8. package/dist/{chunk-2ESCEK2Q.js → chunk-K5YT5GX2.js} +242 -3
  9. package/dist/{chunk-LOKXPQ4U.js → chunk-MDCKV2NF.js} +1 -1
  10. package/dist/{chunk-XIKEUCNC.js → chunk-TIGKDMIA.js} +139 -266
  11. package/dist/{chunk-K7EX47QG.js → chunk-TQ4S5AGJ.js} +2 -2
  12. package/dist/{chunk-Z5LYMW7M.js → chunk-WS5LFFU3.js} +135 -217
  13. package/dist/{coordinator-prompt-Y737IIFR.js → coordinator-prompt-2OWSUAUR.js} +1 -1
  14. package/dist/{coordinator-prompt-FYMWE33S.js → coordinator-prompt-IPL4Z6SL.js} +1 -1
  15. package/dist/{global-workspace-6KH6BSKL.js → global-workspace-JDUCUL7S.js} +2 -2
  16. package/dist/{global-workspace-ZFKNLBZA.js → global-workspace-NIKZAKOO.js} +2 -2
  17. package/dist/index.cjs +828 -615
  18. package/dist/index.d.cts +24 -1
  19. package/dist/index.d.ts +24 -1
  20. package/dist/index.js +38 -17
  21. package/dist/mcp/run-stdio.cjs +657 -485
  22. package/dist/mcp/run-stdio.js +20 -9
  23. package/dist/{orchestrator-3YDPPZHZ.js → orchestrator-6I47JMU2.js} +5 -5
  24. package/dist/{orchestrator-2BRAPJ47.js → orchestrator-KK3CUW37.js} +5 -5
  25. package/dist/{workspaces-3RRF3LVF.js → workspaces-5EWNNALF.js} +3 -3
  26. package/dist/{workspaces-AYI5DHK4.js → workspaces-KZA3TCEE.js} +3 -3
  27. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -2648,6 +2648,300 @@ var init_cloud_connect_constants = __esm({
2648
2648
  }
2649
2649
  });
2650
2650
 
2651
+ // src/paths/workspace-scratch.ts
2652
+ function attachmentsGitignoreBody() {
2653
+ return ATTACHMENTS_GITIGNORE;
2654
+ }
2655
+ function isWorkspaceScratchPath(relativePath) {
2656
+ const p = relativePath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
2657
+ return p === ATTACHMENTS_DIR || p.startsWith(`${ATTACHMENTS_DIR}/`) || p === LEGACY_ATTACHMENTS_DIR || p.startsWith(`${LEGACY_ATTACHMENTS_DIR}/`) || p === ".context" || p.startsWith(".context/");
2658
+ }
2659
+ var ATTACHMENTS_DIR, LEGACY_ATTACHMENTS_DIR, ATTACHMENTS_GITIGNORE;
2660
+ var init_workspace_scratch = __esm({
2661
+ "src/paths/workspace-scratch.ts"() {
2662
+ "use strict";
2663
+ ATTACHMENTS_DIR = ".context/attachments";
2664
+ LEGACY_ATTACHMENTS_DIR = ".sideboard/attachments";
2665
+ ATTACHMENTS_GITIGNORE = `# Sideboard / workspace attachments (local only)
2666
+ *
2667
+ !.gitignore
2668
+ `;
2669
+ }
2670
+ });
2671
+
2672
+ // src/composer/stage-files.ts
2673
+ function fileExtension(filePath) {
2674
+ const base = (0, import_node_path13.basename)(filePath).toLowerCase();
2675
+ return base.includes(".") ? base.split(".").pop() || "" : "";
2676
+ }
2677
+ function isImageFilePath(filePath) {
2678
+ return IMAGE_EXTENSIONS.has(fileExtension(filePath));
2679
+ }
2680
+ function imageMimeType(filePath) {
2681
+ return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
2682
+ }
2683
+ function ensureAttachmentsDir(worktreePath) {
2684
+ const dir = (0, import_node_path13.join)(worktreePath, ATTACHMENTS_DIR);
2685
+ (0, import_node_fs12.mkdirSync)(dir, { recursive: true });
2686
+ const gi = (0, import_node_path13.join)(dir, ".gitignore");
2687
+ if (!(0, import_node_fs12.existsSync)(gi)) {
2688
+ (0, import_node_fs12.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
2689
+ }
2690
+ return dir;
2691
+ }
2692
+ function uniqueAttachmentName(dir, originalName) {
2693
+ const safe = originalName.replace(/[/\\]/g, "_") || "file";
2694
+ if (!(0, import_node_fs12.existsSync)((0, import_node_path13.join)(dir, safe))) return safe;
2695
+ const ext = (0, import_node_path13.extname)(safe);
2696
+ const stem = ext ? safe.slice(0, -ext.length) : safe;
2697
+ for (let i = 1; i < 1e4; i++) {
2698
+ const candidate = `${stem}-${i}${ext}`;
2699
+ if (!(0, import_node_fs12.existsSync)((0, import_node_path13.join)(dir, candidate))) return candidate;
2700
+ }
2701
+ return `${stem}-${(0, import_node_crypto5.randomUUID)()}${ext}`;
2702
+ }
2703
+ function previewDataUrlFromBuf(filePath, buf) {
2704
+ if (!isImageFilePath(filePath)) return void 0;
2705
+ if (buf.length > MAX_PREVIEW_BYTES) return void 0;
2706
+ return `data:${imageMimeType(filePath)};base64,${buf.toString("base64")}`;
2707
+ }
2708
+ function attachmentFromBuffer(name, buf, opts) {
2709
+ const previewDataUrl = previewDataUrlFromBuf(name, buf);
2710
+ if (isImageFilePath(name)) {
2711
+ const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
2712
+ return {
2713
+ id: (0, import_node_crypto5.randomUUID)(),
2714
+ name,
2715
+ kind: "file",
2716
+ path: opts.path,
2717
+ previewDataUrl,
2718
+ content: [
2719
+ `Image attached: ${pathHint}`,
2720
+ opts.path ? `Use the Read tool on \`${opts.path}\` to view this image.` : "The image is shown in the composer; copy it into the worktree if you need to inspect pixels."
2721
+ ].join("\n")
2722
+ };
2723
+ }
2724
+ if (buf.length > MAX_INLINE_BYTES) {
2725
+ return {
2726
+ id: (0, import_node_crypto5.randomUUID)(),
2727
+ name,
2728
+ kind: "file",
2729
+ path: opts.path,
2730
+ content: opts.path ? `(file too large to attach inline: \`${opts.path}\`, ${buf.length} bytes \u2014 use the Read tool)` : `(file too large to attach inline: ${opts.sourceLabel || name}, ${buf.length} bytes)`
2731
+ };
2732
+ }
2733
+ if (buf.includes(0)) {
2734
+ return {
2735
+ id: (0, import_node_crypto5.randomUUID)(),
2736
+ name,
2737
+ kind: "file",
2738
+ path: opts.path,
2739
+ content: opts.path ? `(binary file at \`${opts.path}\` \u2014 use tools to inspect)` : `(binary file attached by path only: ${opts.sourceLabel || name})`
2740
+ };
2741
+ }
2742
+ return {
2743
+ id: (0, import_node_crypto5.randomUUID)(),
2744
+ name,
2745
+ kind: "file",
2746
+ path: opts.path,
2747
+ content: buf.toString("utf8")
2748
+ };
2749
+ }
2750
+ function attachmentFromAbsolutePath(absolutePath) {
2751
+ const name = (0, import_node_path13.basename)(absolutePath);
2752
+ try {
2753
+ const st = (0, import_node_fs12.statSync)(absolutePath);
2754
+ if (!st.isFile()) {
2755
+ return {
2756
+ id: (0, import_node_crypto5.randomUUID)(),
2757
+ name,
2758
+ kind: "file",
2759
+ content: `(not a file: ${absolutePath})`
2760
+ };
2761
+ }
2762
+ const buf = (0, import_node_fs12.readFileSync)(absolutePath);
2763
+ return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
2764
+ } catch (err) {
2765
+ return {
2766
+ id: (0, import_node_crypto5.randomUUID)(),
2767
+ name,
2768
+ kind: "file",
2769
+ content: `(could not read ${absolutePath}: ${err instanceof Error ? err.message : String(err)})`
2770
+ };
2771
+ }
2772
+ }
2773
+ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
2774
+ if (absolutePaths.length === 0) return [];
2775
+ const dir = ensureAttachmentsDir(worktreePath);
2776
+ const out = [];
2777
+ for (const abs of absolutePaths) {
2778
+ const originalName = (0, import_node_path13.basename)(abs);
2779
+ try {
2780
+ const st = (0, import_node_fs12.statSync)(abs);
2781
+ if (!st.isFile()) continue;
2782
+ const name = uniqueAttachmentName(dir, originalName);
2783
+ const destAbs = (0, import_node_path13.join)(dir, name);
2784
+ (0, import_node_fs12.copyFileSync)(abs, destAbs);
2785
+ const rel = `${ATTACHMENTS_DIR}/${name}`;
2786
+ const buf = (0, import_node_fs12.readFileSync)(destAbs);
2787
+ out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
2788
+ } catch (err) {
2789
+ out.push({
2790
+ id: (0, import_node_crypto5.randomUUID)(),
2791
+ name: originalName,
2792
+ kind: "file",
2793
+ content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
2794
+ });
2795
+ }
2796
+ }
2797
+ return out;
2798
+ }
2799
+ function stageBuffersAsAttachments(worktreePath, buffers2) {
2800
+ if (buffers2.length === 0) return [];
2801
+ const dir = ensureAttachmentsDir(worktreePath);
2802
+ const out = [];
2803
+ for (const item of buffers2) {
2804
+ const originalName = (item.name || "file").replace(/[/\\]/g, "_") || "file";
2805
+ try {
2806
+ const buf = Buffer.from(item.dataBase64, "base64");
2807
+ const name = uniqueAttachmentName(dir, originalName);
2808
+ const destAbs = (0, import_node_path13.join)(dir, name);
2809
+ (0, import_node_fs12.writeFileSync)(destAbs, buf);
2810
+ const rel = `${ATTACHMENTS_DIR}/${name}`;
2811
+ out.push(attachmentFromBuffer(name, buf, { path: rel }));
2812
+ } catch (err) {
2813
+ out.push({
2814
+ id: (0, import_node_crypto5.randomUUID)(),
2815
+ name: originalName,
2816
+ kind: "file",
2817
+ content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
2818
+ });
2819
+ }
2820
+ }
2821
+ return out;
2822
+ }
2823
+ function attachmentsFromBuffers(buffers2) {
2824
+ return buffers2.map((item) => {
2825
+ const name = (item.name || "file").replace(/[/\\]/g, "_") || "file";
2826
+ try {
2827
+ const buf = Buffer.from(item.dataBase64, "base64");
2828
+ return attachmentFromBuffer(name, buf, { sourceLabel: name });
2829
+ } catch (err) {
2830
+ return {
2831
+ id: (0, import_node_crypto5.randomUUID)(),
2832
+ name,
2833
+ kind: "file",
2834
+ content: `(could not attach ${name}: ${err instanceof Error ? err.message : String(err)})`
2835
+ };
2836
+ }
2837
+ });
2838
+ }
2839
+ function isWorktreeRelativePath(p) {
2840
+ if (!p || p.includes("..")) return false;
2841
+ if (p.startsWith("/")) return false;
2842
+ if (/^[A-Za-z]:[\\/]/.test(p)) return false;
2843
+ return true;
2844
+ }
2845
+ function dataUrlToBase64(url) {
2846
+ if (!url) return null;
2847
+ const m = /^data:[^;]+;base64,(.+)$/s.exec(url);
2848
+ return m?.[1] ?? null;
2849
+ }
2850
+ function persistPendingFileAttachments(worktreePath, attachments) {
2851
+ if (attachments.length === 0) return attachments;
2852
+ const keep = [];
2853
+ const buffers2 = [];
2854
+ for (const att of attachments) {
2855
+ if (att.kind !== "file") {
2856
+ keep.push(att);
2857
+ continue;
2858
+ }
2859
+ if (att.path && isWorktreeRelativePath(att.path)) {
2860
+ keep.push(att);
2861
+ continue;
2862
+ }
2863
+ const fromPreview = dataUrlToBase64(att.previewDataUrl);
2864
+ if (fromPreview) {
2865
+ buffers2.push({ name: att.name, dataBase64: fromPreview });
2866
+ continue;
2867
+ }
2868
+ if (att.content && !IMAGE_HINT_RE.test(att.content) && !PLACEHOLDER_CONTENT_RE.test(att.content)) {
2869
+ buffers2.push({
2870
+ name: att.name,
2871
+ dataBase64: Buffer.from(att.content, "utf8").toString("base64")
2872
+ });
2873
+ continue;
2874
+ }
2875
+ keep.push(att);
2876
+ }
2877
+ if (buffers2.length === 0) return attachments;
2878
+ return [...keep, ...stageBuffersAsAttachments(worktreePath, buffers2)];
2879
+ }
2880
+ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
2881
+ const out = [];
2882
+ for (const rel of relativePaths) {
2883
+ if (!rel || rel.includes("..") || rel.startsWith("/")) {
2884
+ out.push({
2885
+ id: (0, import_node_crypto5.randomUUID)(),
2886
+ name: (0, import_node_path13.basename)(rel) || "file",
2887
+ kind: "file",
2888
+ content: `(invalid path: ${rel})`
2889
+ });
2890
+ continue;
2891
+ }
2892
+ const name = (0, import_node_path13.basename)(rel);
2893
+ try {
2894
+ const abs = (0, import_node_path13.join)(worktreePath, rel);
2895
+ const st = (0, import_node_fs12.statSync)(abs);
2896
+ if (!st.isFile()) continue;
2897
+ const buf = (0, import_node_fs12.readFileSync)(abs);
2898
+ out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
2899
+ } catch (err) {
2900
+ out.push({
2901
+ id: (0, import_node_crypto5.randomUUID)(),
2902
+ name,
2903
+ kind: "file",
2904
+ content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
2905
+ });
2906
+ }
2907
+ }
2908
+ return out;
2909
+ }
2910
+ var import_node_fs12, import_node_path13, import_node_crypto5, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
2911
+ var init_stage_files = __esm({
2912
+ "src/composer/stage-files.ts"() {
2913
+ "use strict";
2914
+ import_node_fs12 = require("fs");
2915
+ import_node_path13 = require("path");
2916
+ import_node_crypto5 = require("crypto");
2917
+ init_workspace_scratch();
2918
+ IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
2919
+ "png",
2920
+ "jpg",
2921
+ "jpeg",
2922
+ "gif",
2923
+ "webp",
2924
+ "svg",
2925
+ "bmp",
2926
+ "ico"
2927
+ ]);
2928
+ IMAGE_MIME_BY_EXT = {
2929
+ png: "image/png",
2930
+ jpg: "image/jpeg",
2931
+ jpeg: "image/jpeg",
2932
+ gif: "image/gif",
2933
+ webp: "image/webp",
2934
+ svg: "image/svg+xml",
2935
+ bmp: "image/bmp",
2936
+ ico: "image/x-icon"
2937
+ };
2938
+ MAX_INLINE_BYTES = 4e5;
2939
+ MAX_PREVIEW_BYTES = 5e6;
2940
+ IMAGE_HINT_RE = /^Image attached:/;
2941
+ PLACEHOLDER_CONTENT_RE = /^\((could not |file too large|binary file|not a file|invalid path)/;
2942
+ }
2943
+ });
2944
+
2651
2945
  // src/git/team-meta.ts
2652
2946
  var SOCCER_TEAM_META;
2653
2947
  var init_team_meta = __esm({
@@ -3559,23 +3853,23 @@ var init_gh_errors = __esm({
3559
3853
  function githubAgentAuthDir() {
3560
3854
  const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
3561
3855
  if (override) return override;
3562
- return (0, import_node_path13.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
3856
+ return (0, import_node_path14.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
3563
3857
  }
3564
3858
  function githubCredentialStorePath() {
3565
- return (0, import_node_path13.join)(githubAgentAuthDir(), "git-credentials");
3859
+ return (0, import_node_path14.join)(githubAgentAuthDir(), "git-credentials");
3566
3860
  }
3567
3861
  function githubGhConfigDir() {
3568
- return (0, import_node_path13.join)(githubAgentAuthDir(), "gh");
3862
+ return (0, import_node_path14.join)(githubAgentAuthDir(), "gh");
3569
3863
  }
3570
3864
  function writePrivateFile2(file, body) {
3571
- (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file), { recursive: true, mode: 448 });
3865
+ (0, import_node_fs13.mkdirSync)((0, import_node_path14.dirname)(file), { recursive: true, mode: 448 });
3572
3866
  try {
3573
- (0, import_node_fs12.chmodSync)((0, import_node_path13.dirname)(file), 448);
3867
+ (0, import_node_fs13.chmodSync)((0, import_node_path14.dirname)(file), 448);
3574
3868
  } catch {
3575
3869
  }
3576
- (0, import_node_fs12.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
3870
+ (0, import_node_fs13.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
3577
3871
  try {
3578
- (0, import_node_fs12.chmodSync)(file, 384);
3872
+ (0, import_node_fs13.chmodSync)(file, 384);
3579
3873
  } catch {
3580
3874
  }
3581
3875
  }
@@ -3600,19 +3894,19 @@ function materializeGithubAgentAuth(token, user) {
3600
3894
  const trimmed = token.trim();
3601
3895
  if (!trimmed) return;
3602
3896
  const root = githubAgentAuthDir();
3603
- (0, import_node_fs12.mkdirSync)(root, { recursive: true, mode: 448 });
3897
+ (0, import_node_fs13.mkdirSync)(root, { recursive: true, mode: 448 });
3604
3898
  try {
3605
- (0, import_node_fs12.chmodSync)(root, 448);
3899
+ (0, import_node_fs13.chmodSync)(root, 448);
3606
3900
  } catch {
3607
3901
  }
3608
3902
  writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
3609
3903
  const ghDir = githubGhConfigDir();
3610
- (0, import_node_fs12.mkdirSync)(ghDir, { recursive: true, mode: 448 });
3611
- writePrivateFile2((0, import_node_path13.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
3612
- writePrivateFile2((0, import_node_path13.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
3904
+ (0, import_node_fs13.mkdirSync)(ghDir, { recursive: true, mode: 448 });
3905
+ writePrivateFile2((0, import_node_path14.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
3906
+ writePrivateFile2((0, import_node_path14.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
3613
3907
  }
3614
3908
  function githubAgentAuthReady() {
3615
- return (0, import_node_fs12.existsSync)(githubCredentialStorePath()) && (0, import_node_fs12.existsSync)((0, import_node_path13.join)(githubGhConfigDir(), "hosts.yml"));
3909
+ return (0, import_node_fs13.existsSync)(githubCredentialStorePath()) && (0, import_node_fs13.existsSync)((0, import_node_path14.join)(githubGhConfigDir(), "hosts.yml"));
3616
3910
  }
3617
3911
  function githubCredentialHelperGitConfig() {
3618
3912
  const file = githubCredentialStorePath();
@@ -3627,29 +3921,29 @@ function githubGhConfigEnv() {
3627
3921
  GH_PROMPT_DISABLED: "1"
3628
3922
  };
3629
3923
  }
3630
- var import_node_fs12, import_node_os4, import_node_path13;
3924
+ var import_node_fs13, import_node_os4, import_node_path14;
3631
3925
  var init_github_agent_auth = __esm({
3632
3926
  "src/git/github-agent-auth.ts"() {
3633
3927
  "use strict";
3634
- import_node_fs12 = require("fs");
3928
+ import_node_fs13 = require("fs");
3635
3929
  import_node_os4 = require("os");
3636
- import_node_path13 = require("path");
3930
+ import_node_path14 = require("path");
3637
3931
  }
3638
3932
  });
3639
3933
 
3640
3934
  // src/agents/path.ts
3641
3935
  function prependPathDir(env, dir) {
3642
- if (!dir || !(0, import_node_fs13.existsSync)(dir)) return;
3936
+ if (!dir || !(0, import_node_fs14.existsSync)(dir)) return;
3643
3937
  const current = env.PATH ?? "";
3644
- const parts = current.split(import_node_path14.delimiter).filter(Boolean);
3938
+ const parts = current.split(import_node_path15.delimiter).filter(Boolean);
3645
3939
  if (parts.includes(dir)) {
3646
3940
  env.PATH = current;
3647
3941
  return;
3648
3942
  }
3649
- env.PATH = [dir, ...parts].join(import_node_path14.delimiter);
3943
+ env.PATH = [dir, ...parts].join(import_node_path15.delimiter);
3650
3944
  }
3651
3945
  function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os5.homedir)()) {
3652
- return (0, import_node_path14.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
3946
+ return (0, import_node_path15.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
3653
3947
  }
3654
3948
  function isConductorBundledCli(filePath) {
3655
3949
  const p = (filePath ?? "").replace(/\\/g, "/");
@@ -3658,21 +3952,21 @@ function isConductorBundledCli(filePath) {
3658
3952
  function ensureAgentPath(env = process.env) {
3659
3953
  const home = env.HOME || env.USERPROFILE || (0, import_node_os5.homedir)();
3660
3954
  const current = env.PATH ?? "";
3661
- const parts = current.split(import_node_path14.delimiter).filter(Boolean);
3955
+ const parts = current.split(import_node_path15.delimiter).filter(Boolean);
3662
3956
  const seen = new Set(parts);
3663
3957
  const extras = [
3664
- ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path14.join)(home, rel)),
3958
+ ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path15.join)(home, rel)),
3665
3959
  "/opt/homebrew/bin",
3666
3960
  "/usr/local/bin",
3667
3961
  // Keep after Homebrew/npm so a user-installed CLI still wins.
3668
3962
  conductorBundledBinDir(home)
3669
3963
  ];
3670
3964
  for (const dir of extras.reverse()) {
3671
- if (!dir || seen.has(dir) || !(0, import_node_fs13.existsSync)(dir)) continue;
3965
+ if (!dir || seen.has(dir) || !(0, import_node_fs14.existsSync)(dir)) continue;
3672
3966
  parts.unshift(dir);
3673
3967
  seen.add(dir);
3674
3968
  }
3675
- const next = parts.join(import_node_path14.delimiter);
3969
+ const next = parts.join(import_node_path15.delimiter);
3676
3970
  env.PATH = next;
3677
3971
  return next;
3678
3972
  }
@@ -3686,7 +3980,7 @@ function enrichPathWithNpmGlobalBin(env = process.env) {
3686
3980
  stdio: ["ignore", "pipe", "ignore"]
3687
3981
  }).trim().split(/\r?\n/).find(Boolean);
3688
3982
  if (prefix) {
3689
- const binDir = process.platform === "win32" ? prefix : (0, import_node_path14.join)(prefix, "bin");
3983
+ const binDir = process.platform === "win32" ? prefix : (0, import_node_path15.join)(prefix, "bin");
3690
3984
  prependPathDir(env, binDir);
3691
3985
  }
3692
3986
  } catch {
@@ -3714,14 +4008,14 @@ function withExportedPath(command, pathValue) {
3714
4008
  if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
3715
4009
  return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
3716
4010
  }
3717
- var import_node_fs13, import_node_child_process3, import_node_os5, import_node_path14, EXTRA_BIN_DIRS;
4011
+ var import_node_fs14, import_node_child_process3, import_node_os5, import_node_path15, EXTRA_BIN_DIRS;
3718
4012
  var init_path = __esm({
3719
4013
  "src/agents/path.ts"() {
3720
4014
  "use strict";
3721
- import_node_fs13 = require("fs");
4015
+ import_node_fs14 = require("fs");
3722
4016
  import_node_child_process3 = require("child_process");
3723
4017
  import_node_os5 = require("os");
3724
- import_node_path14 = require("path");
4018
+ import_node_path15 = require("path");
3725
4019
  EXTRA_BIN_DIRS = [
3726
4020
  ".local/bin",
3727
4021
  ".cargo/bin",
@@ -3743,11 +4037,11 @@ function isIndexLockError(text5) {
3743
4037
  return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text5);
3744
4038
  }
3745
4039
  function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
3746
- const lockPath = (0, import_node_path15.join)(gitDir, "index.lock");
4040
+ const lockPath = (0, import_node_path16.join)(gitDir, "index.lock");
3747
4041
  try {
3748
- if (!(0, import_node_fs14.existsSync)(lockPath)) return null;
3749
- if (now - (0, import_node_fs14.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
3750
- (0, import_node_fs14.unlinkSync)(lockPath);
4042
+ if (!(0, import_node_fs15.existsSync)(lockPath)) return null;
4043
+ if (now - (0, import_node_fs15.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
4044
+ (0, import_node_fs15.unlinkSync)(lockPath);
3751
4045
  return lockPath;
3752
4046
  } catch {
3753
4047
  return null;
@@ -3762,12 +4056,12 @@ function clearStaleIndexLocks(gitDirs, maxAgeMs = STALE_INDEX_LOCK_MS) {
3762
4056
  }
3763
4057
  return removed;
3764
4058
  }
3765
- var import_node_fs14, import_node_path15, STALE_INDEX_LOCK_MS;
4059
+ var import_node_fs15, import_node_path16, STALE_INDEX_LOCK_MS;
3766
4060
  var init_stale_lock = __esm({
3767
4061
  "src/git/stale-lock.ts"() {
3768
4062
  "use strict";
3769
- import_node_fs14 = require("fs");
3770
- import_node_path15 = require("path");
4063
+ import_node_fs15 = require("fs");
4064
+ import_node_path16 = require("path");
3771
4065
  STALE_INDEX_LOCK_MS = 2e4;
3772
4066
  }
3773
4067
  });
@@ -3975,7 +4269,7 @@ async function warmGithubAgentAuth(opts) {
3975
4269
  }
3976
4270
  function normalizeWritableRoot(raw) {
3977
4271
  const trimmed = raw.trim().replace(/\/+$/, "");
3978
- return trimmed && (0, import_node_path16.isAbsolute)(trimmed) ? trimmed : null;
4272
+ return trimmed && (0, import_node_path17.isAbsolute)(trimmed) ? trimmed : null;
3979
4273
  }
3980
4274
  async function resolveCodexGitWritableRoots(cwd) {
3981
4275
  const roots = /* @__PURE__ */ new Set();
@@ -4052,11 +4346,11 @@ function formatGitAuthModeDirective(mode) {
4052
4346
  ].join("\n");
4053
4347
  }
4054
4348
  }
4055
- var import_node_path16, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
4349
+ var import_node_path17, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
4056
4350
  var init_git_auth_mode = __esm({
4057
4351
  "src/git/git-auth-mode.ts"() {
4058
4352
  "use strict";
4059
- import_node_path16 = require("path");
4353
+ import_node_path17 = require("path");
4060
4354
  init_app_settings();
4061
4355
  init_github_agent_auth();
4062
4356
  init_run();
@@ -4426,27 +4720,6 @@ var init_stack = __esm({
4426
4720
  }
4427
4721
  });
4428
4722
 
4429
- // src/paths/workspace-scratch.ts
4430
- function attachmentsGitignoreBody() {
4431
- return ATTACHMENTS_GITIGNORE;
4432
- }
4433
- function isWorkspaceScratchPath(relativePath) {
4434
- const p = relativePath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
4435
- return p === ATTACHMENTS_DIR || p.startsWith(`${ATTACHMENTS_DIR}/`) || p === LEGACY_ATTACHMENTS_DIR || p.startsWith(`${LEGACY_ATTACHMENTS_DIR}/`) || p === ".context" || p.startsWith(".context/");
4436
- }
4437
- var ATTACHMENTS_DIR, LEGACY_ATTACHMENTS_DIR, ATTACHMENTS_GITIGNORE;
4438
- var init_workspace_scratch = __esm({
4439
- "src/paths/workspace-scratch.ts"() {
4440
- "use strict";
4441
- ATTACHMENTS_DIR = ".context/attachments";
4442
- LEGACY_ATTACHMENTS_DIR = ".sideboard/attachments";
4443
- ATTACHMENTS_GITIGNORE = `# Sideboard / workspace attachments (local only)
4444
- *
4445
- !.gitignore
4446
- `;
4447
- }
4448
- });
4449
-
4450
4723
  // src/git/worktree.ts
4451
4724
  var worktree_exports = {};
4452
4725
  __export(worktree_exports, {
@@ -4534,7 +4807,7 @@ async function resolveRepoRoot(cwd) {
4534
4807
  }
4535
4808
  function canonicalizeRepoPath(path2) {
4536
4809
  try {
4537
- return (0, import_node_fs15.realpathSync)(path2);
4810
+ return (0, import_node_fs16.realpathSync)(path2);
4538
4811
  } catch {
4539
4812
  return path2.replace(/\/+$/, "");
4540
4813
  }
@@ -5262,8 +5535,8 @@ function isLocalPrFetchBranch(ref) {
5262
5535
  }
5263
5536
  async function createThreadWorktree(opts) {
5264
5537
  let branchName = `thread/${opts.slug}`;
5265
- const worktreePath = (0, import_node_path17.join)(worktreesRoot(opts.repoPath), opts.slug);
5266
- if ((0, import_node_fs15.existsSync)(worktreePath)) {
5538
+ const worktreePath = (0, import_node_path18.join)(worktreesRoot(opts.repoPath), opts.slug);
5539
+ if ((0, import_node_fs16.existsSync)(worktreePath)) {
5267
5540
  throw new Error(`Worktree already exists at ${worktreePath}`);
5268
5541
  }
5269
5542
  await ensureGhPreferOrigin(opts.repoPath);
@@ -5330,8 +5603,8 @@ ${add.stdout}`;
5330
5603
  async function createExistingBranchWorktree(opts) {
5331
5604
  const branchName = opts.branchName.trim();
5332
5605
  if (!branchName) throw new Error("branch name required");
5333
- const worktreePath = (0, import_node_path17.join)(worktreesRoot(opts.repoPath), opts.slug);
5334
- if ((0, import_node_fs15.existsSync)(worktreePath)) {
5606
+ const worktreePath = (0, import_node_path18.join)(worktreesRoot(opts.repoPath), opts.slug);
5607
+ if ((0, import_node_fs16.existsSync)(worktreePath)) {
5335
5608
  throw new Error(`Worktree already exists at ${worktreePath}`);
5336
5609
  }
5337
5610
  await ensureGhPreferOrigin(opts.repoPath);
@@ -5622,10 +5895,10 @@ function sameRepoPath(a, b) {
5622
5895
  return normalizeWorktreePath(a) === normalizeWorktreePath(b);
5623
5896
  }
5624
5897
  function listLocalThreadBranchSlugs(repoPath) {
5625
- const refsDir = (0, import_node_path17.join)(repoPath, ".git", "refs", "heads", "thread");
5626
- if (!(0, import_node_fs15.existsSync)(refsDir)) return [];
5898
+ const refsDir = (0, import_node_path18.join)(repoPath, ".git", "refs", "heads", "thread");
5899
+ if (!(0, import_node_fs16.existsSync)(refsDir)) return [];
5627
5900
  try {
5628
- return (0, import_node_fs15.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
5901
+ return (0, import_node_fs16.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
5629
5902
  } catch {
5630
5903
  return [];
5631
5904
  }
@@ -5633,8 +5906,8 @@ function listLocalThreadBranchSlugs(repoPath) {
5633
5906
  function collectTakenTeamSlugs(repoPath) {
5634
5907
  const taken = /* @__PURE__ */ new Set();
5635
5908
  const root = worktreesRoot(repoPath);
5636
- if ((0, import_node_fs15.existsSync)(root)) {
5637
- for (const entry of (0, import_node_fs15.readdirSync)(root, { withFileTypes: true })) {
5909
+ if ((0, import_node_fs16.existsSync)(root)) {
5910
+ for (const entry of (0, import_node_fs16.readdirSync)(root, { withFileTypes: true })) {
5638
5911
  if (entry.isDirectory() && entry.name !== ".DS_Store") {
5639
5912
  taken.add(normalizeTakenSlug(entry.name));
5640
5913
  }
@@ -5655,18 +5928,18 @@ function allocateTeamSlug(repoPath) {
5655
5928
  const taken = collectTakenTeamSlugs(repoPath);
5656
5929
  for (let attempt = 0; attempt < 32; attempt++) {
5657
5930
  const team = allocateTeamName(taken);
5658
- const path2 = (0, import_node_path17.join)(worktreesRoot(repoPath), team.slug);
5659
- if (!(0, import_node_fs15.existsSync)(path2)) return team;
5931
+ const path2 = (0, import_node_path18.join)(worktreesRoot(repoPath), team.slug);
5932
+ if (!(0, import_node_fs16.existsSync)(path2)) return team;
5660
5933
  taken.add(team.slug);
5661
5934
  }
5662
5935
  throw new Error("No available soccer team worktree directories left");
5663
5936
  }
5664
- var import_node_fs15, import_node_path17;
5937
+ var import_node_fs16, import_node_path18;
5665
5938
  var init_worktree = __esm({
5666
5939
  "src/git/worktree.ts"() {
5667
5940
  "use strict";
5668
- import_node_fs15 = require("fs");
5669
- import_node_path17 = require("path");
5941
+ import_node_fs16 = require("fs");
5942
+ import_node_path18 = require("path");
5670
5943
  init_paths();
5671
5944
  init_thread_store();
5672
5945
  init_teams();
@@ -5737,13 +6010,13 @@ function coordinatorTurnReminder(opts) {
5737
6010
  `- YOUR orchestration thread id is ${opts.parentId} \u2014 pass parentThreadId="${opts.parentId}" on create_thread, or omit it.`,
5738
6011
  goal ? `- Goal / title: ${goal}` : null,
5739
6012
  accountDefaultsPlaybookLine(),
5740
- "- Status: list_board (worktree Kanban: New \u2192 Draft \u2192 Review \u2192 Merged) or list_threads. Link chats as `[Title](sideboard://thread/<id>)`. Merge only if the user asked."
6013
+ "- Status: list_board (worktree Kanban: New \u2192 Draft \u2192 Review \u2192 Merged) or list_threads. Link chats as `[Title](sideboard://thread/<id>)`. Merge only if the user asked. If a child is stopped/error/broken, it did not finish \u2014 resume or tell the user."
5741
6014
  ].filter(Boolean).join("\n");
5742
6015
  }
5743
6016
  function ensureGlobalCoordinatorCwd(opts) {
5744
6017
  const dir = globalAgentCwd();
5745
6018
  try {
5746
- (0, import_node_fs16.mkdirSync)(dir, { recursive: true });
6019
+ (0, import_node_fs17.mkdirSync)(dir, { recursive: true });
5747
6020
  } catch {
5748
6021
  return dir;
5749
6022
  }
@@ -5751,7 +6024,7 @@ function ensureGlobalCoordinatorCwd(opts) {
5751
6024
  let orchId = opts?.orchestratorThreadId?.trim() || "";
5752
6025
  if (!orchId) {
5753
6026
  try {
5754
- const existing = (0, import_node_fs16.readFileSync)((0, import_node_path18.join)(dir, "AGENTS.md"), "utf8");
6027
+ const existing = (0, import_node_fs17.readFileSync)((0, import_node_path19.join)(dir, "AGENTS.md"), "utf8");
5755
6028
  const m = existing.match(
5756
6029
  /YOUR orchestration thread id is `([0-9a-f-]{36})`/i
5757
6030
  );
@@ -5794,9 +6067,9 @@ function ensureGlobalCoordinatorCwd(opts) {
5794
6067
  "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."
5795
6068
  ].join("\n");
5796
6069
  try {
5797
- (0, import_node_fs16.writeFileSync)((0, import_node_path18.join)(dir, "CLAUDE.md"), `${body}
6070
+ (0, import_node_fs17.writeFileSync)((0, import_node_path19.join)(dir, "CLAUDE.md"), `${body}
5798
6071
  `, "utf8");
5799
- (0, import_node_fs16.writeFileSync)((0, import_node_path18.join)(dir, "AGENTS.md"), `${body}
6072
+ (0, import_node_fs17.writeFileSync)((0, import_node_path19.join)(dir, "AGENTS.md"), `${body}
5800
6073
  `, "utf8");
5801
6074
  } catch {
5802
6075
  }
@@ -5828,12 +6101,12 @@ function coordinatorSystemPrompt(opts) {
5828
6101
  formatWorkspaceInventory(opts.workspaces)
5829
6102
  ].join("\n");
5830
6103
  }
5831
- var import_node_fs16, import_node_path18, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
6104
+ var import_node_fs17, import_node_path19, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
5832
6105
  var init_coordinator_prompt = __esm({
5833
6106
  "src/orchestrator/coordinator-prompt.ts"() {
5834
6107
  "use strict";
5835
- import_node_fs16 = require("fs");
5836
- import_node_path18 = require("path");
6108
+ import_node_fs17 = require("fs");
6109
+ import_node_path19 = require("path");
5837
6110
  init_worktree();
5838
6111
  init_app_settings();
5839
6112
  init_paths();
@@ -5862,7 +6135,7 @@ var init_coordinator_prompt = __esm({
5862
6135
  "- 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.",
5863
6136
  "- 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.",
5864
6137
  "- 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",
5865
- "- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). 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.",
6138
+ "- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). 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. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
5866
6139
  "- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
5867
6140
  "- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
5868
6141
  "Setup / run:",
@@ -5982,6 +6255,7 @@ function createGlobalChat(opts) {
5982
6255
  fast: opts.fast
5983
6256
  });
5984
6257
  const agent = assertOrchestratorCapableAgent(resolved.agent);
6258
+ const worktreePath = globalAgentCwd();
5985
6259
  const thread = createEmptyThread({
5986
6260
  title,
5987
6261
  // Stick nicknames the same way chat tabs do (avoid later sync overwrites).
@@ -5989,7 +6263,7 @@ function createGlobalChat(opts) {
5989
6263
  sourceType: "orchestration",
5990
6264
  sourceRef,
5991
6265
  branchName: "global",
5992
- worktreePath: globalAgentCwd(),
6266
+ worktreePath,
5993
6267
  repoPath: GLOBAL_WORKSPACE_ID,
5994
6268
  agent,
5995
6269
  autonomy: opts.autonomy ?? "default",
@@ -5997,7 +6271,10 @@ function createGlobalChat(opts) {
5997
6271
  effort: resolved.effort,
5998
6272
  fast: resolved.fast,
5999
6273
  planMode: Boolean(opts.planMode),
6000
- attachments: opts.attachments ?? [],
6274
+ attachments: persistPendingFileAttachments(
6275
+ worktreePath,
6276
+ opts.attachments ?? []
6277
+ ),
6001
6278
  parentThreadId: opts.parentThreadId ?? null,
6002
6279
  status: "idle"
6003
6280
  });
@@ -6122,6 +6399,7 @@ var init_global_workspace = __esm({
6122
6399
  "src/store/global-workspace.ts"() {
6123
6400
  "use strict";
6124
6401
  init_cloud_connect_constants();
6402
+ init_stage_files();
6125
6403
  init_orchestrator_capable();
6126
6404
  init_teams();
6127
6405
  init_coordinator_prompt();
@@ -6179,13 +6457,13 @@ var init_api = __esm({
6179
6457
 
6180
6458
  // src/slack/reply-target.ts
6181
6459
  function storePath() {
6182
- return (0, import_node_path19.join)(appDataDir(), "slack-reply-to.json");
6460
+ return (0, import_node_path20.join)(appDataDir(), "slack-reply-to.json");
6183
6461
  }
6184
6462
  function readStore() {
6185
6463
  const path2 = storePath();
6186
- if (!(0, import_node_fs17.existsSync)(path2)) return {};
6464
+ if (!(0, import_node_fs18.existsSync)(path2)) return {};
6187
6465
  try {
6188
- const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs17.readFileSync)(path2, "utf8"));
6466
+ const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs18.readFileSync)(path2, "utf8"));
6189
6467
  return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
6190
6468
  } catch {
6191
6469
  return {};
@@ -6200,12 +6478,12 @@ function setSlackReplyTarget(target) {
6200
6478
  function getSlackReplyTarget(threadId) {
6201
6479
  return readStore()[threadId] ?? null;
6202
6480
  }
6203
- var import_node_fs17, import_node_path19;
6481
+ var import_node_fs18, import_node_path20;
6204
6482
  var init_reply_target = __esm({
6205
6483
  "src/slack/reply-target.ts"() {
6206
6484
  "use strict";
6207
- import_node_fs17 = require("fs");
6208
- import_node_path19 = require("path");
6485
+ import_node_fs18 = require("fs");
6486
+ import_node_path20 = require("path");
6209
6487
  init_paths();
6210
6488
  init_private_file();
6211
6489
  init_secure_file();
@@ -6214,7 +6492,7 @@ var init_reply_target = __esm({
6214
6492
 
6215
6493
  // src/slack/workspaces.ts
6216
6494
  function storePath2() {
6217
- return (0, import_node_path20.join)(appDataDir(), "slack-workspaces.json");
6495
+ return (0, import_node_path21.join)(appDataDir(), "slack-workspaces.json");
6218
6496
  }
6219
6497
  function readStore2() {
6220
6498
  try {
@@ -6321,11 +6599,11 @@ function requireSlackWorkspace(teamId) {
6321
6599
  }
6322
6600
  return ws;
6323
6601
  }
6324
- var import_node_path20;
6602
+ var import_node_path21;
6325
6603
  var init_workspaces = __esm({
6326
6604
  "src/slack/workspaces.ts"() {
6327
6605
  "use strict";
6328
- import_node_path20 = require("path");
6606
+ import_node_path21 = require("path");
6329
6607
  init_paths();
6330
6608
  init_secure_file();
6331
6609
  init_api();
@@ -6334,7 +6612,7 @@ var init_workspaces = __esm({
6334
6612
 
6335
6613
  // src/slack/outbound-watch.ts
6336
6614
  function storePath3() {
6337
- return (0, import_node_path21.join)(appDataDir(), "slack-outbound-watch.json");
6615
+ return (0, import_node_path22.join)(appDataDir(), "slack-outbound-watch.json");
6338
6616
  }
6339
6617
  function watchId(teamId, channelId, ts) {
6340
6618
  return `${teamId}:${channelId}:${ts}`;
@@ -6347,9 +6625,9 @@ function tsNewer(a, b) {
6347
6625
  }
6348
6626
  function readStore3() {
6349
6627
  const path2 = storePath3();
6350
- if (!(0, import_node_fs18.existsSync)(path2)) return [];
6628
+ if (!(0, import_node_fs19.existsSync)(path2)) return [];
6351
6629
  try {
6352
- const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs18.readFileSync)(path2, "utf8"));
6630
+ const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs19.readFileSync)(path2, "utf8"));
6353
6631
  return Array.isArray(parsed?.watches) ? parsed.watches : [];
6354
6632
  } catch {
6355
6633
  return [];
@@ -6671,12 +6949,12 @@ async function pollSlackOutboundWatches(opts) {
6671
6949
  }
6672
6950
  if (changed) writeStore2(watches);
6673
6951
  }
6674
- var import_node_fs18, import_node_path21, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache, continueOnReply;
6952
+ var import_node_fs19, import_node_path22, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache, continueOnReply;
6675
6953
  var init_outbound_watch = __esm({
6676
6954
  "src/slack/outbound-watch.ts"() {
6677
6955
  "use strict";
6678
- import_node_fs18 = require("fs");
6679
- import_node_path21 = require("path");
6956
+ import_node_fs19 = require("fs");
6957
+ import_node_path22 = require("path");
6680
6958
  init_paths();
6681
6959
  init_private_file();
6682
6960
  init_secure_file();
@@ -6957,32 +7235,32 @@ var init_error_detail = __esm({
6957
7235
  function brightsyConfigPath() {
6958
7236
  const override = process.env.BRIGHTSY_CONFIG?.trim();
6959
7237
  if (override) return override;
6960
- return (0, import_node_path22.join)((0, import_node_os6.homedir)(), ".brightsy", "config.json");
7238
+ return (0, import_node_path23.join)((0, import_node_os6.homedir)(), ".brightsy", "config.json");
6961
7239
  }
6962
7240
  function loadBrightsyConfig() {
6963
7241
  const path2 = brightsyConfigPath();
6964
- if (!(0, import_node_fs19.existsSync)(path2)) {
7242
+ if (!(0, import_node_fs20.existsSync)(path2)) {
6965
7243
  throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
6966
7244
  }
6967
- const raw = JSON.parse((0, import_node_fs19.readFileSync)(path2, "utf8"));
7245
+ const raw = JSON.parse((0, import_node_fs20.readFileSync)(path2, "utf8"));
6968
7246
  if (!raw.access_token || !raw.account_id) {
6969
7247
  throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
6970
7248
  }
6971
7249
  return raw;
6972
7250
  }
6973
7251
  function saveBrightsyConfig(cfg) {
6974
- (0, import_node_fs19.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
7252
+ (0, import_node_fs20.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
6975
7253
  `, {
6976
7254
  mode: 384
6977
7255
  });
6978
7256
  }
6979
- var import_node_fs19, import_node_os6, import_node_path22;
7257
+ var import_node_fs20, import_node_os6, import_node_path23;
6980
7258
  var init_config = __esm({
6981
7259
  "src/brightsy/config.ts"() {
6982
7260
  "use strict";
6983
- import_node_fs19 = require("fs");
7261
+ import_node_fs20 = require("fs");
6984
7262
  import_node_os6 = require("os");
6985
- import_node_path22 = require("path");
7263
+ import_node_path23 = require("path");
6986
7264
  }
6987
7265
  });
6988
7266
 
@@ -7200,22 +7478,22 @@ __export(connected_teams_exports, {
7200
7478
  listConnectedBrightsyTeams: () => listConnectedBrightsyTeams
7201
7479
  });
7202
7480
  function storePath4() {
7203
- return (0, import_node_path23.join)(appDataDir(), "brightsy-teams.json");
7481
+ return (0, import_node_path24.join)(appDataDir(), "brightsy-teams.json");
7204
7482
  }
7205
7483
  function readStore4() {
7206
7484
  const path2 = storePath4();
7207
- if (!(0, import_node_fs20.existsSync)(path2)) return [];
7485
+ if (!(0, import_node_fs21.existsSync)(path2)) return [];
7208
7486
  try {
7209
- const parsed = JSON.parse((0, import_node_fs20.readFileSync)(path2, "utf8"));
7487
+ const parsed = JSON.parse((0, import_node_fs21.readFileSync)(path2, "utf8"));
7210
7488
  return Array.isArray(parsed.teams) ? parsed.teams : [];
7211
7489
  } catch {
7212
7490
  return [];
7213
7491
  }
7214
7492
  }
7215
7493
  function writeStore3(teams) {
7216
- (0, import_node_fs20.mkdirSync)(appDataDir(), { recursive: true });
7494
+ (0, import_node_fs21.mkdirSync)(appDataDir(), { recursive: true });
7217
7495
  const path2 = storePath4();
7218
- (0, import_node_fs20.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
7496
+ (0, import_node_fs21.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
7219
7497
  `, {
7220
7498
  mode: 384
7221
7499
  });
@@ -7371,12 +7649,12 @@ function brightsyMcpServerName(slug) {
7371
7649
  const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
7372
7650
  return `brightsy_${cleaned || "team"}`;
7373
7651
  }
7374
- var import_node_fs20, import_node_path23;
7652
+ var import_node_fs21, import_node_path24;
7375
7653
  var init_connected_teams = __esm({
7376
7654
  "src/brightsy/connected-teams.ts"() {
7377
7655
  "use strict";
7378
- import_node_fs20 = require("fs");
7379
- import_node_path23 = require("path");
7656
+ import_node_fs21 = require("fs");
7657
+ import_node_path24 = require("path");
7380
7658
  init_paths();
7381
7659
  init_accounts();
7382
7660
  init_config();
@@ -7795,11 +8073,11 @@ async function syncCliForTarget(accountId) {
7795
8073
  }
7796
8074
  applyConnectedTeamToCli(team);
7797
8075
  }
7798
- var import_node_fs21, brightsyAdapter;
8076
+ var import_node_fs22, brightsyAdapter;
7799
8077
  var init_brightsy = __esm({
7800
8078
  "src/agents/brightsy.ts"() {
7801
8079
  "use strict";
7802
- import_node_fs21 = require("fs");
8080
+ import_node_fs22 = require("fs");
7803
8081
  init_run();
7804
8082
  init_connected_teams();
7805
8083
  init_config();
@@ -7814,7 +8092,7 @@ var init_brightsy = __esm({
7814
8092
  async detect() {
7815
8093
  const brightsy = resolveAgentExecutable("brightsy");
7816
8094
  if (brightsy !== "brightsy") {
7817
- if (!(0, import_node_fs21.existsSync)(brightsy)) {
8095
+ if (!(0, import_node_fs22.existsSync)(brightsy)) {
7818
8096
  return {
7819
8097
  agent: "brightsy",
7820
8098
  installed: false,
@@ -7945,14 +8223,47 @@ function asRecord(input) {
7945
8223
  function str2(v) {
7946
8224
  return typeof v === "string" && v.trim() ? v : void 0;
7947
8225
  }
8226
+ function looksLikeFilePath(value) {
8227
+ if (value.startsWith("/") || value.startsWith("~/")) return true;
8228
+ if (/^[A-Za-z]:[\\/]/.test(value)) return true;
8229
+ return value.includes("/") || value.includes("\\");
8230
+ }
8231
+ function stripWorktreePrefix(path2, worktreePath) {
8232
+ if (!worktreePath) return path2;
8233
+ const prefix = worktreePath.replace(/[/\\]+$/, "");
8234
+ if (path2 === prefix || path2 === `${prefix}/`) return "";
8235
+ if (path2.startsWith(`${prefix}/`)) return path2.slice(prefix.length + 1);
8236
+ return path2;
8237
+ }
8238
+ function visibleToolRowDetail(detail, description, worktreePath) {
8239
+ if (!detail?.trim()) return void 0;
8240
+ const raw = detail.trim();
8241
+ const desc = (description ?? "").trim();
8242
+ if (!looksLikeFilePath(raw)) {
8243
+ if (desc === raw) return void 0;
8244
+ return raw;
8245
+ }
8246
+ const rel = stripWorktreePrefix(raw, worktreePath);
8247
+ if (!rel) return void 0;
8248
+ const base = fileBasename(rel);
8249
+ if (desc && (desc === base || desc.endsWith(` ${base}`))) return void 0;
8250
+ if (rel.length <= 42) return rel;
8251
+ const parts = rel.split(/[/\\]/).filter(Boolean);
8252
+ if (parts.length >= 2) return `\u2026/${parts.slice(-2).join("/")}`;
8253
+ return base;
8254
+ }
7948
8255
  function toolDetail(name, input) {
7949
8256
  if (!input) return void 0;
7950
8257
  const command = str2(input.command) ?? str2(input.cmd);
7951
8258
  if (command) return command;
8259
+ const pattern = str2(input.pattern) ?? str2(input.glob) ?? str2(input.glob_pattern);
8260
+ const isSearch = /grep|glob|search|ripgrep|findfiles|semsearch/i.test(name);
8261
+ if (isSearch && pattern) {
8262
+ return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
8263
+ }
7952
8264
  const path2 = str2(input.file_path) ?? str2(input.path) ?? str2(input.filePath) ?? str2(input.filename);
7953
8265
  if (path2) return path2;
7954
- const pattern = str2(input.pattern) ?? str2(input.glob) ?? str2(input.glob_pattern);
7955
- if (pattern) return pattern;
8266
+ if (pattern) return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
7956
8267
  const query = str2(input.query) ?? str2(input.prompt);
7957
8268
  if (query) return query.length > 80 ? `${query.slice(0, 77)}\u2026` : query;
7958
8269
  try {
@@ -8471,43 +8782,43 @@ function electronResourcesPath() {
8471
8782
  function packagedCursorRuntimeDir() {
8472
8783
  const resources = electronResourcesPath();
8473
8784
  if (!resources) return null;
8474
- const dir = (0, import_node_path24.join)(resources, "cursor-runtime");
8475
- if (!(0, import_node_fs22.existsSync)((0, import_node_path24.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
8785
+ const dir = (0, import_node_path25.join)(resources, "cursor-runtime");
8786
+ if (!(0, import_node_fs23.existsSync)((0, import_node_path25.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
8476
8787
  return dir;
8477
8788
  }
8478
8789
  function packagedCursorRunnerPath() {
8479
8790
  const dir = packagedCursorRuntimeDir();
8480
- return dir ? (0, import_node_path24.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
8791
+ return dir ? (0, import_node_path25.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
8481
8792
  }
8482
8793
  function packagedMcpDir() {
8483
8794
  const resources = electronResourcesPath();
8484
8795
  if (!resources) return null;
8485
- const dir = (0, import_node_path24.join)(resources, "sideboard-mcp");
8486
- if (!(0, import_node_fs22.existsSync)((0, import_node_path24.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
8796
+ const dir = (0, import_node_path25.join)(resources, "sideboard-mcp");
8797
+ if (!(0, import_node_fs23.existsSync)((0, import_node_path25.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
8487
8798
  return dir;
8488
8799
  }
8489
8800
  function packagedMcpStdioPath() {
8490
8801
  const dir = packagedMcpDir();
8491
- return dir ? (0, import_node_path24.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
8802
+ return dir ? (0, import_node_path25.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
8492
8803
  }
8493
8804
  function packagedBundledNodePath() {
8494
8805
  const resources = electronResourcesPath();
8495
8806
  if (!resources) return null;
8496
- const bin = (0, import_node_path24.join)(resources, "node", "bin", "node");
8497
- if (!(0, import_node_fs22.existsSync)(bin)) return null;
8807
+ const bin = (0, import_node_path25.join)(resources, "node", "bin", "node");
8808
+ if (!(0, import_node_fs23.existsSync)(bin)) return null;
8498
8809
  return bin;
8499
8810
  }
8500
8811
  function packagedCursorRipgrepCandidate(platformPkg, binName) {
8501
8812
  const dir = packagedCursorRuntimeDir();
8502
8813
  if (!dir) return null;
8503
- return (0, import_node_path24.join)(dir, "node_modules", platformPkg, "bin", binName);
8814
+ return (0, import_node_path25.join)(dir, "node_modules", platformPkg, "bin", binName);
8504
8815
  }
8505
- var import_node_fs22, import_node_path24;
8816
+ var import_node_fs23, import_node_path25;
8506
8817
  var init_packaged_runtime = __esm({
8507
8818
  "src/agents/packaged-runtime.ts"() {
8508
8819
  "use strict";
8509
- import_node_fs22 = require("fs");
8510
- import_node_path24 = require("path");
8820
+ import_node_fs23 = require("fs");
8821
+ import_node_path25 = require("path");
8511
8822
  }
8512
8823
  });
8513
8824
 
@@ -8541,7 +8852,7 @@ function unpackedAsarPath(filePath) {
8541
8852
  if (!isAsarPath(filePath)) return null;
8542
8853
  const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
8543
8854
  if (unpacked === filePath) return null;
8544
- return (0, import_node_fs23.existsSync)(unpacked) ? unpacked : null;
8855
+ return (0, import_node_fs24.existsSync)(unpacked) ? unpacked : null;
8545
8856
  }
8546
8857
  function nodeReadableScriptPath(scriptPath) {
8547
8858
  return unpackedAsarPath(scriptPath) ?? scriptPath;
@@ -8581,37 +8892,37 @@ function pickPreferredNode(candidates) {
8581
8892
  return best;
8582
8893
  }
8583
8894
  function versionDirNodeBins(root, toBin) {
8584
- if (!(0, import_node_fs23.existsSync)(root)) return [];
8895
+ if (!(0, import_node_fs24.existsSync)(root)) return [];
8585
8896
  try {
8586
- return (0, import_node_fs23.readdirSync)(root).map(toBin);
8897
+ return (0, import_node_fs24.readdirSync)(root).map(toBin);
8587
8898
  } catch {
8588
8899
  return [];
8589
8900
  }
8590
8901
  }
8591
8902
  function defaultNodeBinCandidates(home = (0, import_node_os7.homedir)()) {
8592
8903
  const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
8593
- (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path25.join)(prefix, "opt", `node@${major}`, "bin", "node"))
8904
+ (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path26.join)(prefix, "opt", `node@${major}`, "bin", "node"))
8594
8905
  );
8595
8906
  return [
8596
8907
  ...kegs,
8597
8908
  "/opt/homebrew/bin/node",
8598
8909
  "/usr/local/bin/node",
8599
- (0, import_node_path25.join)(home, ".local/share/fnm/aliases/default/bin/node"),
8600
- (0, import_node_path25.join)(home, ".nvm/current/bin/node"),
8601
- (0, import_node_path25.join)(home, ".volta/bin/node"),
8602
- (0, import_node_path25.join)(home, ".asdf/shims/node"),
8603
- (0, import_node_path25.join)(home, ".local/share/mise/shims/node"),
8910
+ (0, import_node_path26.join)(home, ".local/share/fnm/aliases/default/bin/node"),
8911
+ (0, import_node_path26.join)(home, ".nvm/current/bin/node"),
8912
+ (0, import_node_path26.join)(home, ".volta/bin/node"),
8913
+ (0, import_node_path26.join)(home, ".asdf/shims/node"),
8914
+ (0, import_node_path26.join)(home, ".local/share/mise/shims/node"),
8604
8915
  ...versionDirNodeBins(
8605
- (0, import_node_path25.join)(home, ".nvm", "versions", "node"),
8606
- (name) => (0, import_node_path25.join)(home, ".nvm", "versions", "node", name, "bin", "node")
8916
+ (0, import_node_path26.join)(home, ".nvm", "versions", "node"),
8917
+ (name) => (0, import_node_path26.join)(home, ".nvm", "versions", "node", name, "bin", "node")
8607
8918
  ),
8608
8919
  ...versionDirNodeBins(
8609
- (0, import_node_path25.join)(home, ".local/share/fnm", "node-versions"),
8610
- (name) => (0, import_node_path25.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
8920
+ (0, import_node_path26.join)(home, ".local/share/fnm", "node-versions"),
8921
+ (name) => (0, import_node_path26.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
8611
8922
  ),
8612
8923
  ...versionDirNodeBins(
8613
- (0, import_node_path25.join)(home, ".volta", "tools", "image", "node"),
8614
- (name) => (0, import_node_path25.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
8924
+ (0, import_node_path26.join)(home, ".volta", "tools", "image", "node"),
8925
+ (name) => (0, import_node_path26.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
8615
8926
  )
8616
8927
  ];
8617
8928
  }
@@ -8620,10 +8931,10 @@ function uniqueExistingNodeBins(paths) {
8620
8931
  const out = [];
8621
8932
  for (const raw of paths) {
8622
8933
  const p = raw.trim();
8623
- if (!p || !(0, import_node_fs23.existsSync)(p) || isElectronLikeCommand(p)) continue;
8934
+ if (!p || !(0, import_node_fs24.existsSync)(p) || isElectronLikeCommand(p)) continue;
8624
8935
  let key = p;
8625
8936
  try {
8626
- key = (0, import_node_fs23.realpathSync)(p);
8937
+ key = (0, import_node_fs24.realpathSync)(p);
8627
8938
  } catch {
8628
8939
  continue;
8629
8940
  }
@@ -8703,13 +9014,13 @@ async function resolveNodeLaunch(scriptPath) {
8703
9014
  env: { ELECTRON_RUN_AS_NODE: "1" }
8704
9015
  };
8705
9016
  }
8706
- var import_node_fs23, import_node_os7, import_node_path25, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
9017
+ var import_node_fs24, import_node_os7, import_node_path26, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
8707
9018
  var init_node_launch = __esm({
8708
9019
  "src/agents/node-launch.ts"() {
8709
9020
  "use strict";
8710
- import_node_fs23 = require("fs");
9021
+ import_node_fs24 = require("fs");
8711
9022
  import_node_os7 = require("os");
8712
- import_node_path25 = require("path");
9023
+ import_node_path26 = require("path");
8713
9024
  init_nested_electron_env();
8714
9025
  init_run();
8715
9026
  init_packaged_runtime();
@@ -8803,37 +9114,37 @@ function corePackageDir() {
8803
9114
  try {
8804
9115
  const url = import_meta.url;
8805
9116
  if (typeof url === "string" && url.length > 0) {
8806
- return (0, import_node_path26.dirname)((0, import_node_url.fileURLToPath)(url));
9117
+ return (0, import_node_path27.dirname)((0, import_node_url.fileURLToPath)(url));
8807
9118
  }
8808
9119
  } catch {
8809
9120
  }
8810
9121
  try {
8811
- const req = (0, import_node_module.createRequire)((0, import_node_path26.join)(process.cwd(), "package.json"));
8812
- return (0, import_node_path26.dirname)(req.resolve("@sideboard-ai/core"));
9122
+ const req = (0, import_node_module.createRequire)((0, import_node_path27.join)(process.cwd(), "package.json"));
9123
+ return (0, import_node_path27.dirname)(req.resolve("@sideboard-ai/core"));
8813
9124
  } catch {
8814
9125
  return process.cwd();
8815
9126
  }
8816
9127
  }
8817
9128
  function findSideboardMcpJsEntry() {
8818
9129
  const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
8819
- if (override && (0, import_node_fs24.existsSync)(override)) return override;
9130
+ if (override && (0, import_node_fs25.existsSync)(override)) return override;
8820
9131
  const packaged = packagedMcpStdioPath();
8821
9132
  if (packaged) return packaged;
8822
9133
  let dir = corePackageDir();
8823
9134
  for (let i = 0; i < 10; i++) {
8824
9135
  const candidates = [
8825
- (0, import_node_path26.join)(dir, "mcp/run-stdio.js"),
8826
- (0, import_node_path26.join)(dir, "mcp/run-stdio.cjs"),
8827
- (0, import_node_path26.join)(dir, "dist/mcp/run-stdio.js"),
8828
- (0, import_node_path26.join)(dir, "dist/mcp/run-stdio.cjs"),
8829
- (0, import_node_path26.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
8830
- (0, import_node_path26.join)(dir, "packages/cli/dist/index.js"),
8831
- (0, import_node_path26.join)(dir, "cli/dist/index.js")
9136
+ (0, import_node_path27.join)(dir, "mcp/run-stdio.js"),
9137
+ (0, import_node_path27.join)(dir, "mcp/run-stdio.cjs"),
9138
+ (0, import_node_path27.join)(dir, "dist/mcp/run-stdio.js"),
9139
+ (0, import_node_path27.join)(dir, "dist/mcp/run-stdio.cjs"),
9140
+ (0, import_node_path27.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
9141
+ (0, import_node_path27.join)(dir, "packages/cli/dist/index.js"),
9142
+ (0, import_node_path27.join)(dir, "cli/dist/index.js")
8832
9143
  ];
8833
9144
  for (const p of candidates) {
8834
- if ((0, import_node_fs24.existsSync)(p) && !isAsarPath(p)) return p;
9145
+ if ((0, import_node_fs25.existsSync)(p) && !isAsarPath(p)) return p;
8835
9146
  }
8836
- const parent = (0, import_node_path26.dirname)(dir);
9147
+ const parent = (0, import_node_path27.dirname)(dir);
8837
9148
  if (parent === dir) break;
8838
9149
  dir = parent;
8839
9150
  }
@@ -8975,22 +9286,22 @@ function writeMcpServersConfig(servers) {
8975
9286
  ...env ? { env } : {}
8976
9287
  };
8977
9288
  }
8978
- const dir = (0, import_node_fs24.mkdtempSync)((0, import_node_path26.join)((0, import_node_os8.tmpdir)(), "sideboard-mcp-"));
8979
- const cfgPath = (0, import_node_path26.join)(dir, "mcp.json");
8980
- (0, import_node_fs24.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
9289
+ const dir = (0, import_node_fs25.mkdtempSync)((0, import_node_path27.join)((0, import_node_os8.tmpdir)(), "sideboard-mcp-"));
9290
+ const cfgPath = (0, import_node_path27.join)(dir, "mcp.json");
9291
+ (0, import_node_fs25.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
8981
9292
  return cfgPath;
8982
9293
  }
8983
9294
  async function writeInjectedMcpConfig(opts) {
8984
9295
  return writeMcpServersConfig(await buildInjectedMcpServers(opts));
8985
9296
  }
8986
- var import_node_fs24, import_node_module, import_node_os8, import_node_path26, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
9297
+ var import_node_fs25, import_node_module, import_node_os8, import_node_path27, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
8987
9298
  var init_injected_mcp = __esm({
8988
9299
  "src/agents/injected-mcp.ts"() {
8989
9300
  "use strict";
8990
- import_node_fs24 = require("fs");
9301
+ import_node_fs25 = require("fs");
8991
9302
  import_node_module = require("module");
8992
9303
  import_node_os8 = require("os");
8993
- import_node_path26 = require("path");
9304
+ import_node_path27 = require("path");
8994
9305
  import_node_url = require("url");
8995
9306
  init_run();
8996
9307
  init_config();
@@ -9294,11 +9605,11 @@ function parseIssuesJson(raw) {
9294
9605
  }
9295
9606
  return [];
9296
9607
  }
9297
- var import_node_fs25, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, mcpListCache, claudeAdapter;
9608
+ var import_node_fs26, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, mcpListCache, claudeAdapter;
9298
9609
  var init_claude = __esm({
9299
9610
  "src/agents/claude.ts"() {
9300
9611
  "use strict";
9301
- import_node_fs25 = require("fs");
9612
+ import_node_fs26 = require("fs");
9302
9613
  init_run();
9303
9614
  init_app_settings();
9304
9615
  init_claude_mcp();
@@ -9338,7 +9649,7 @@ var init_claude = __esm({
9338
9649
  async detect() {
9339
9650
  const claude = resolveClaudeExecutable();
9340
9651
  if (claude !== "claude") {
9341
- if (!(0, import_node_fs25.existsSync)(claude)) {
9652
+ if (!(0, import_node_fs26.existsSync)(claude)) {
9342
9653
  return {
9343
9654
  agent: "claude",
9344
9655
  installed: false,
@@ -9593,7 +9904,7 @@ async function listCodexModels() {
9593
9904
  if (codex === "codex") {
9594
9905
  const which = await run("which", ["codex"], { reject: false });
9595
9906
  if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
9596
- } else if (!(0, import_node_fs26.existsSync)(codex)) {
9907
+ } else if (!(0, import_node_fs27.existsSync)(codex)) {
9597
9908
  return FALLBACK_CODEX_MODELS;
9598
9909
  }
9599
9910
  const listed = await run(codex, ["debug", "models"], { reject: false });
@@ -9628,12 +9939,12 @@ function usageFromCodex(usage) {
9628
9939
  }
9629
9940
  function codexConfigHasNetworkAccess() {
9630
9941
  const candidates = [
9631
- (0, import_node_path27.join)((0, import_node_os9.homedir)(), ".codex", "config.toml"),
9632
- (0, import_node_path27.join)((0, import_node_os9.homedir)(), ".config", "codex", "config.toml")
9942
+ (0, import_node_path28.join)((0, import_node_os9.homedir)(), ".codex", "config.toml"),
9943
+ (0, import_node_path28.join)((0, import_node_os9.homedir)(), ".config", "codex", "config.toml")
9633
9944
  ];
9634
9945
  for (const path2 of candidates) {
9635
- if (!(0, import_node_fs26.existsSync)(path2)) continue;
9636
- const text5 = (0, import_node_fs26.readFileSync)(path2, "utf8");
9946
+ if (!(0, import_node_fs27.existsSync)(path2)) continue;
9947
+ const text5 = (0, import_node_fs27.readFileSync)(path2, "utf8");
9637
9948
  if (/network_access\s*=\s*true/.test(text5)) return true;
9638
9949
  }
9639
9950
  return false;
@@ -9665,21 +9976,21 @@ function asRecord2(value) {
9665
9976
  return void 0;
9666
9977
  }
9667
9978
  function codexLooksAuthenticated() {
9668
- const authPath = (0, import_node_path27.join)((0, import_node_os9.homedir)(), ".codex", "auth.json");
9669
- if (!(0, import_node_fs26.existsSync)(authPath)) return false;
9979
+ const authPath = (0, import_node_path28.join)((0, import_node_os9.homedir)(), ".codex", "auth.json");
9980
+ if (!(0, import_node_fs27.existsSync)(authPath)) return false;
9670
9981
  try {
9671
- return (0, import_node_fs26.statSync)(authPath).size > 2;
9982
+ return (0, import_node_fs27.statSync)(authPath).size > 2;
9672
9983
  } catch {
9673
9984
  return false;
9674
9985
  }
9675
9986
  }
9676
- var import_node_fs26, import_node_os9, import_node_path27, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
9987
+ var import_node_fs27, import_node_os9, import_node_path28, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
9677
9988
  var init_codex = __esm({
9678
9989
  "src/agents/codex.ts"() {
9679
9990
  "use strict";
9680
- import_node_fs26 = require("fs");
9991
+ import_node_fs27 = require("fs");
9681
9992
  import_node_os9 = require("os");
9682
- import_node_path27 = require("path");
9993
+ import_node_path28 = require("path");
9683
9994
  init_run();
9684
9995
  init_app_settings();
9685
9996
  init_global_workspace();
@@ -9704,7 +10015,7 @@ var init_codex = __esm({
9704
10015
  async detect() {
9705
10016
  const codex = resolveAgentExecutable("codex");
9706
10017
  if (codex !== "codex") {
9707
- if (!(0, import_node_fs26.existsSync)(codex)) {
10018
+ if (!(0, import_node_fs27.existsSync)(codex)) {
9708
10019
  return {
9709
10020
  agent: "codex",
9710
10021
  installed: false,
@@ -10191,21 +10502,21 @@ function platformRipgrepPackage() {
10191
10502
  }
10192
10503
  function usableRipgrepPath(candidate) {
10193
10504
  const raw = candidate?.trim();
10194
- if (!raw || !(0, import_node_path28.isAbsolute)(raw)) return null;
10505
+ if (!raw || !(0, import_node_path29.isAbsolute)(raw)) return null;
10195
10506
  const readable = nodeReadableScriptPath(raw);
10196
- if (!(0, import_node_fs27.existsSync)(readable) || isAsarPath(readable)) return null;
10507
+ if (!(0, import_node_fs28.existsSync)(readable) || isAsarPath(readable)) return null;
10197
10508
  return readable;
10198
10509
  }
10199
10510
  function walkForBundledRipgrep(startFile) {
10200
10511
  if (!startFile) return null;
10201
10512
  const pkg = platformRipgrepPackage();
10202
10513
  const name = rgBinaryName();
10203
- let dir = (0, import_node_path28.dirname)((0, import_node_path28.resolve)(startFile));
10204
- const root = (0, import_node_path28.parse)(dir).root;
10514
+ let dir = (0, import_node_path29.dirname)((0, import_node_path29.resolve)(startFile));
10515
+ const root = (0, import_node_path29.parse)(dir).root;
10205
10516
  while (dir !== root) {
10206
- const hit = usableRipgrepPath((0, import_node_path28.join)(dir, "node_modules", pkg, "bin", name));
10517
+ const hit = usableRipgrepPath((0, import_node_path29.join)(dir, "node_modules", pkg, "bin", name));
10207
10518
  if (hit) return hit;
10208
- const next = (0, import_node_path28.dirname)(dir);
10519
+ const next = (0, import_node_path29.dirname)(dir);
10209
10520
  if (next === dir) break;
10210
10521
  dir = next;
10211
10522
  }
@@ -10215,7 +10526,7 @@ function requireResolveBundledRipgrep(fromFile) {
10215
10526
  try {
10216
10527
  const req = (0, import_node_module2.createRequire)(fromFile);
10217
10528
  const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
10218
- return usableRipgrepPath((0, import_node_path28.join)((0, import_node_path28.dirname)(pkgJson), "bin", rgBinaryName()));
10529
+ return usableRipgrepPath((0, import_node_path29.join)((0, import_node_path29.dirname)(pkgJson), "bin", rgBinaryName()));
10219
10530
  } catch {
10220
10531
  return null;
10221
10532
  }
@@ -10237,13 +10548,13 @@ function cursorRipgrepEnv(opts) {
10237
10548
  const path2 = resolveCursorRipgrepPath(opts);
10238
10549
  return path2 ? { [RIPGREP_ENV]: path2 } : {};
10239
10550
  }
10240
- var import_node_fs27, import_node_module2, import_node_path28, RIPGREP_ENV;
10551
+ var import_node_fs28, import_node_module2, import_node_path29, RIPGREP_ENV;
10241
10552
  var init_cursor_ripgrep = __esm({
10242
10553
  "src/agents/cursor-ripgrep.ts"() {
10243
10554
  "use strict";
10244
- import_node_fs27 = require("fs");
10555
+ import_node_fs28 = require("fs");
10245
10556
  import_node_module2 = require("module");
10246
- import_node_path28 = require("path");
10557
+ import_node_path29 = require("path");
10247
10558
  init_node_launch();
10248
10559
  init_packaged_runtime();
10249
10560
  RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
@@ -10289,11 +10600,11 @@ function entryDir() {
10289
10600
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
10290
10601
  if (cjsDir) return cjsDir;
10291
10602
  try {
10292
- return (0, import_node_path29.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
10603
+ return (0, import_node_path30.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
10293
10604
  } catch {
10294
10605
  try {
10295
10606
  const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
10296
- return (0, import_node_path29.dirname)(req.resolve("@sideboard-ai/core"));
10607
+ return (0, import_node_path30.dirname)(req.resolve("@sideboard-ai/core"));
10297
10608
  } catch {
10298
10609
  return process.cwd();
10299
10610
  }
@@ -10304,27 +10615,27 @@ function cursorRunnerPath() {
10304
10615
  if (packaged) return packaged;
10305
10616
  const root = entryDir();
10306
10617
  const candidates = [
10307
- (0, import_node_path29.join)(root, "agents", "cursor-runner.js"),
10308
- (0, import_node_path29.join)(root, "agents", "cursor-runner.cjs"),
10618
+ (0, import_node_path30.join)(root, "agents", "cursor-runner.js"),
10619
+ (0, import_node_path30.join)(root, "agents", "cursor-runner.cjs"),
10309
10620
  // If somehow resolved from package root instead of dist/
10310
- (0, import_node_path29.join)(root, "dist", "agents", "cursor-runner.js"),
10311
- (0, import_node_path29.join)(root, "dist", "agents", "cursor-runner.cjs"),
10621
+ (0, import_node_path30.join)(root, "dist", "agents", "cursor-runner.js"),
10622
+ (0, import_node_path30.join)(root, "dist", "agents", "cursor-runner.cjs"),
10312
10623
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
10313
- (0, import_node_path29.join)(root, "cursor-runner.ts"),
10314
- (0, import_node_path29.join)(root, "src", "agents", "cursor-runner.ts")
10624
+ (0, import_node_path30.join)(root, "cursor-runner.ts"),
10625
+ (0, import_node_path30.join)(root, "src", "agents", "cursor-runner.ts")
10315
10626
  ];
10316
10627
  for (const candidate of candidates) {
10317
- if ((0, import_node_fs28.existsSync)(candidate)) return candidate;
10628
+ if ((0, import_node_fs29.existsSync)(candidate)) return candidate;
10318
10629
  }
10319
10630
  return candidates[0];
10320
10631
  }
10321
- var import_node_fs28, import_node_module3, import_node_path29, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
10632
+ var import_node_fs29, import_node_module3, import_node_path30, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
10322
10633
  var init_cursor = __esm({
10323
10634
  "src/agents/cursor.ts"() {
10324
10635
  "use strict";
10325
- import_node_fs28 = require("fs");
10636
+ import_node_fs29 = require("fs");
10326
10637
  import_node_module3 = require("module");
10327
- import_node_path29 = require("path");
10638
+ import_node_path30 = require("path");
10328
10639
  import_node_url2 = require("url");
10329
10640
  import_sdk = require("@cursor/sdk");
10330
10641
  init_run();
@@ -10475,7 +10786,7 @@ async function listOpencodeModels() {
10475
10786
  if (opencode === "opencode") {
10476
10787
  const which = await run("which", ["opencode"], { reject: false });
10477
10788
  if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
10478
- } else if (!(0, import_node_fs29.existsSync)(opencode)) {
10789
+ } else if (!(0, import_node_fs30.existsSync)(opencode)) {
10479
10790
  return FALLBACK_OPENCODE_MODELS;
10480
10791
  }
10481
10792
  const listed = await run(opencode, ["models"], { reject: false });
@@ -10505,11 +10816,11 @@ function usageFromOpencode(tokens) {
10505
10816
  cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
10506
10817
  };
10507
10818
  }
10508
- var import_node_fs29, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
10819
+ var import_node_fs30, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
10509
10820
  var init_opencode = __esm({
10510
10821
  "src/agents/opencode.ts"() {
10511
10822
  "use strict";
10512
- import_node_fs29 = require("fs");
10823
+ import_node_fs30 = require("fs");
10513
10824
  init_run();
10514
10825
  init_app_settings();
10515
10826
  init_global_workspace();
@@ -10536,7 +10847,7 @@ var init_opencode = __esm({
10536
10847
  async detect() {
10537
10848
  const opencode = resolveAgentExecutable("opencode");
10538
10849
  if (opencode !== "opencode") {
10539
- if (!(0, import_node_fs29.existsSync)(opencode)) {
10850
+ if (!(0, import_node_fs30.existsSync)(opencode)) {
10540
10851
  return {
10541
10852
  agent: "opencode",
10542
10853
  installed: false,
@@ -12039,7 +12350,7 @@ function forkMessageSlice(from, throughIndex) {
12039
12350
  function buildForkTranscriptAttachment(baseTitle, messages) {
12040
12351
  const title = baseTitle || "Chat";
12041
12352
  return {
12042
- id: (0, import_node_crypto5.randomUUID)(),
12353
+ id: (0, import_node_crypto6.randomUUID)(),
12043
12354
  name: `Transcript of ${title}.md`,
12044
12355
  kind: "transcript",
12045
12356
  content: formatTranscriptMarkdown(title, messages)
@@ -12096,11 +12407,11 @@ function forkChatTab(input) {
12096
12407
  }
12097
12408
  return tab;
12098
12409
  }
12099
- var import_node_crypto5;
12410
+ var import_node_crypto6;
12100
12411
  var init_chat_tabs = __esm({
12101
12412
  "src/threads/chat-tabs.ts"() {
12102
12413
  "use strict";
12103
- import_node_crypto5 = require("crypto");
12414
+ import_node_crypto6 = require("crypto");
12104
12415
  init_context_compact();
12105
12416
  init_teams();
12106
12417
  init_worktree_labels();
@@ -12270,21 +12581,21 @@ function shouldRefreshReviewRequestTemplate(content) {
12270
12581
  return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
12271
12582
  }
12272
12583
  function readTextIfPresent(abs) {
12273
- if (!(0, import_node_fs30.existsSync)(abs)) return null;
12584
+ if (!(0, import_node_fs31.existsSync)(abs)) return null;
12274
12585
  try {
12275
- const content = (0, import_node_fs30.readFileSync)(abs, "utf8");
12586
+ const content = (0, import_node_fs31.readFileSync)(abs, "utf8");
12276
12587
  return content.trim() ? content : null;
12277
12588
  } catch {
12278
12589
  return null;
12279
12590
  }
12280
12591
  }
12281
12592
  function readLocalGuidelines(worktreePath) {
12282
- const localAbs = (0, import_node_path30.join)(worktreePath, REVIEW_REQUEST_PATH);
12593
+ const localAbs = (0, import_node_path31.join)(worktreePath, REVIEW_REQUEST_PATH);
12283
12594
  const localContent = readTextIfPresent(localAbs);
12284
12595
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
12285
12596
  return { path: REVIEW_REQUEST_PATH, content: localContent };
12286
12597
  }
12287
- const legacyAbs = (0, import_node_path30.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
12598
+ const legacyAbs = (0, import_node_path31.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
12288
12599
  const legacyContent = readTextIfPresent(legacyAbs);
12289
12600
  if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
12290
12601
  return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
@@ -12300,20 +12611,20 @@ function skillGuidelines(content, source) {
12300
12611
  };
12301
12612
  }
12302
12613
  function ensureReviewSkillFile(worktreePath) {
12303
- const abs = (0, import_node_path30.join)(worktreePath, REVIEW_SKILL_PATH);
12614
+ const abs = (0, import_node_path31.join)(worktreePath, REVIEW_SKILL_PATH);
12304
12615
  const existing = readTextIfPresent(abs);
12305
12616
  if (existing) {
12306
12617
  return { path: REVIEW_SKILL_PATH, content: existing, wrote: false };
12307
12618
  }
12308
- const fromRepo = readTextIfPresent((0, import_node_path30.join)(worktreePath, REPO_REVIEW_PATH));
12619
+ const fromRepo = readTextIfPresent((0, import_node_path31.join)(worktreePath, REPO_REVIEW_PATH));
12309
12620
  const fromLocal = readLocalGuidelines(worktreePath)?.content ?? null;
12310
12621
  const content = wrapReviewSkillMarkdown(fromRepo ?? fromLocal ?? REVIEW_REQUEST_TEMPLATE);
12311
- (0, import_node_fs30.mkdirSync)((0, import_node_path30.dirname)(abs), { recursive: true });
12312
- (0, import_node_fs30.writeFileSync)(abs, content, "utf8");
12622
+ (0, import_node_fs31.mkdirSync)((0, import_node_path31.dirname)(abs), { recursive: true });
12623
+ (0, import_node_fs31.writeFileSync)(abs, content, "utf8");
12313
12624
  return { path: REVIEW_SKILL_PATH, content, wrote: true };
12314
12625
  }
12315
12626
  function resolveReviewGuidelines(worktreePath) {
12316
- const skillContent = readTextIfPresent((0, import_node_path30.join)(worktreePath, REVIEW_SKILL_PATH));
12627
+ const skillContent = readTextIfPresent((0, import_node_path31.join)(worktreePath, REVIEW_SKILL_PATH));
12317
12628
  if (skillContent) return skillGuidelines(skillContent, "skill");
12318
12629
  const local = readLocalGuidelines(worktreePath);
12319
12630
  if (local) {
@@ -12335,7 +12646,7 @@ function buildReviewRequestAttachment(content, opts) {
12335
12646
  const path2 = opts?.path ?? REVIEW_SKILL_PATH;
12336
12647
  const name = opts?.name ?? (path2 === REVIEW_SKILL_PATH ? REVIEW_SKILL_NAME : path2 === REPO_REVIEW_PATH ? REPO_REVIEW_NAME : REVIEW_REQUEST_NAME);
12337
12648
  return {
12338
- id: (0, import_node_crypto6.randomUUID)(),
12649
+ id: (0, import_node_crypto7.randomUUID)(),
12339
12650
  name,
12340
12651
  kind: "file",
12341
12652
  path: path2,
@@ -12343,7 +12654,7 @@ function buildReviewRequestAttachment(content, opts) {
12343
12654
  };
12344
12655
  }
12345
12656
  function readExistingReviewRequestFile(worktreePath) {
12346
- return readTextIfPresent((0, import_node_path30.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path30.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path30.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path30.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
12657
+ return readTextIfPresent((0, import_node_path31.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path31.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path31.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path31.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
12347
12658
  }
12348
12659
  async function requestReview(threadRef, send2) {
12349
12660
  const from = findThreadByRef(threadRef);
@@ -12370,13 +12681,13 @@ async function requestReview(threadRef, send2) {
12370
12681
  const started = await send2(tab.id, REVIEW_REQUEST_PREFILL);
12371
12682
  return { tab: started, from };
12372
12683
  }
12373
- var import_node_crypto6, import_node_fs30, import_node_path30, REPO_REVIEW_PATH, REPO_REVIEW_NAME, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
12684
+ var import_node_crypto7, import_node_fs31, import_node_path31, REPO_REVIEW_PATH, REPO_REVIEW_NAME, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
12374
12685
  var init_request_review = __esm({
12375
12686
  "src/review/request-review.ts"() {
12376
12687
  "use strict";
12377
- import_node_crypto6 = require("crypto");
12378
- import_node_fs30 = require("fs");
12379
- import_node_path30 = require("path");
12688
+ import_node_crypto7 = require("crypto");
12689
+ import_node_fs31 = require("fs");
12690
+ import_node_path31 = require("path");
12380
12691
  init_global_workspace();
12381
12692
  init_chat_tabs();
12382
12693
  init_thread_store();
@@ -12401,9 +12712,9 @@ function matchSimpleGlob(pattern, name) {
12401
12712
  return new RegExp(`^${escaped}$`).test(name);
12402
12713
  }
12403
12714
  function readWorktreeInclude(repoPath) {
12404
- const path2 = (0, import_node_path31.join)(repoPath, ".worktreeinclude");
12405
- if (!(0, import_node_fs31.existsSync)(path2)) return [];
12406
- return (0, import_node_fs31.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
12715
+ const path2 = (0, import_node_path32.join)(repoPath, ".worktreeinclude");
12716
+ if (!(0, import_node_fs32.existsSync)(path2)) return [];
12717
+ return (0, import_node_fs32.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
12407
12718
  }
12408
12719
  function resolveFilesToCopy(repoPath) {
12409
12720
  const fromInclude = readWorktreeInclude(repoPath);
@@ -12413,10 +12724,10 @@ function resolveFilesToCopy(repoPath) {
12413
12724
  if (settings?.fileIncludeGlobs?.length) {
12414
12725
  const matched = [];
12415
12726
  try {
12416
- for (const entry of (0, import_node_fs31.readdirSync)(repoPath, { withFileTypes: true })) {
12727
+ for (const entry of (0, import_node_fs32.readdirSync)(repoPath, { withFileTypes: true })) {
12417
12728
  if (!entry.isFile()) continue;
12418
12729
  for (const glob of settings.fileIncludeGlobs) {
12419
- if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path31.basename)(glob), entry.name)) {
12730
+ if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path32.basename)(glob), entry.name)) {
12420
12731
  matched.push(entry.name);
12421
12732
  break;
12422
12733
  }
@@ -12428,7 +12739,7 @@ function resolveFilesToCopy(repoPath) {
12428
12739
  }
12429
12740
  const defaults = [];
12430
12741
  try {
12431
- for (const entry of (0, import_node_fs31.readdirSync)(repoPath, { withFileTypes: true })) {
12742
+ for (const entry of (0, import_node_fs32.readdirSync)(repoPath, { withFileTypes: true })) {
12432
12743
  if (entry.isFile() && entry.name.startsWith(".env")) {
12433
12744
  defaults.push(entry.name);
12434
12745
  }
@@ -12442,11 +12753,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
12442
12753
  const patterns = resolveFilesToCopy(repoPath);
12443
12754
  const copied = [];
12444
12755
  for (const rel of patterns) {
12445
- const src = (0, import_node_path31.join)(repoPath, rel);
12446
- if (!(0, import_node_fs31.existsSync)(src)) continue;
12447
- const dest = (0, import_node_path31.join)(worktreePath, rel);
12448
- (0, import_node_fs31.mkdirSync)((0, import_node_path31.dirname)(dest), { recursive: true });
12449
- (0, import_node_fs31.copyFileSync)(src, dest);
12756
+ const src = (0, import_node_path32.join)(repoPath, rel);
12757
+ if (!(0, import_node_fs32.existsSync)(src)) continue;
12758
+ const dest = (0, import_node_path32.join)(worktreePath, rel);
12759
+ (0, import_node_fs32.mkdirSync)((0, import_node_path32.dirname)(dest), { recursive: true });
12760
+ (0, import_node_fs32.copyFileSync)(src, dest);
12450
12761
  copied.push(rel);
12451
12762
  }
12452
12763
  return copied;
@@ -12481,7 +12792,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
12481
12792
  const env = stripNestedElectronEnv({
12482
12793
  ...baseEnv ?? process.env
12483
12794
  });
12484
- const name = opts.workspaceName ?? (0, import_node_path31.basename)(opts.worktreePath);
12795
+ const name = opts.workspaceName ?? (0, import_node_path32.basename)(opts.worktreePath);
12485
12796
  const ports = opts.ports ?? [];
12486
12797
  const primary = ports[0];
12487
12798
  env.SIDEBOARD_WORKSPACE_NAME = name;
@@ -12742,13 +13053,13 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
12742
13053
  done: handle.done
12743
13054
  };
12744
13055
  }
12745
- var import_node_fs31, import_node_net, import_node_path31, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
13056
+ var import_node_fs32, import_node_net, import_node_path32, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
12746
13057
  var init_conductor = __esm({
12747
13058
  "src/hook/conductor.ts"() {
12748
13059
  "use strict";
12749
- import_node_fs31 = require("fs");
13060
+ import_node_fs32 = require("fs");
12750
13061
  import_node_net = require("net");
12751
- import_node_path31 = require("path");
13062
+ import_node_path32 = require("path");
12752
13063
  import_execa4 = require("execa");
12753
13064
  import_node_readline3 = require("readline");
12754
13065
  init_settings();
@@ -12774,9 +13085,9 @@ async function findOrphanWorktrees(repoPaths) {
12774
13085
  repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
12775
13086
  );
12776
13087
  const homeRoot = sideboardWorkspacesDir();
12777
- if ((0, import_node_fs32.existsSync)(homeRoot)) {
13088
+ if ((0, import_node_fs33.existsSync)(homeRoot)) {
12778
13089
  try {
12779
- for (const entry of (0, import_node_fs32.readdirSync)(homeRoot, { withFileTypes: true })) {
13090
+ for (const entry of (0, import_node_fs33.readdirSync)(homeRoot, { withFileTypes: true })) {
12780
13091
  if (!entry.isDirectory()) continue;
12781
13092
  void entry;
12782
13093
  }
@@ -12786,7 +13097,7 @@ async function findOrphanWorktrees(repoPaths) {
12786
13097
  const orphans = [];
12787
13098
  const seen = /* @__PURE__ */ new Set();
12788
13099
  for (const repoPath of repos) {
12789
- if (!repoPath || !(0, import_node_fs32.existsSync)(repoPath)) continue;
13100
+ if (!repoPath || !(0, import_node_fs33.existsSync)(repoPath)) continue;
12790
13101
  try {
12791
13102
  const wts = await listWorktrees(repoPath);
12792
13103
  for (const wt of wts) {
@@ -12797,7 +13108,7 @@ async function findOrphanWorktrees(repoPaths) {
12797
13108
  seen.add(path2);
12798
13109
  let mtimeMs = 0;
12799
13110
  try {
12800
- mtimeMs = (0, import_node_fs32.statSync)(path2).mtimeMs;
13111
+ mtimeMs = (0, import_node_fs33.statSync)(path2).mtimeMs;
12801
13112
  } catch {
12802
13113
  mtimeMs = 0;
12803
13114
  }
@@ -12807,16 +13118,16 @@ async function findOrphanWorktrees(repoPaths) {
12807
13118
  }
12808
13119
  try {
12809
13120
  const root = worktreesRoot(repoPath);
12810
- if ((0, import_node_fs32.existsSync)(root)) {
12811
- for (const entry of (0, import_node_fs32.readdirSync)(root, { withFileTypes: true })) {
13121
+ if ((0, import_node_fs33.existsSync)(root)) {
13122
+ for (const entry of (0, import_node_fs33.readdirSync)(root, { withFileTypes: true })) {
12812
13123
  if (!entry.isDirectory()) continue;
12813
- const path2 = (0, import_node_path32.join)(root, entry.name).replace(/\/$/, "");
13124
+ const path2 = (0, import_node_path33.join)(root, entry.name).replace(/\/$/, "");
12814
13125
  if (known.has(path2) || seen.has(path2)) continue;
12815
- if (!(0, import_node_fs32.existsSync)((0, import_node_path32.join)(path2, ".git"))) continue;
13126
+ if (!(0, import_node_fs33.existsSync)((0, import_node_path33.join)(path2, ".git"))) continue;
12816
13127
  seen.add(path2);
12817
13128
  let mtimeMs = 0;
12818
13129
  try {
12819
- mtimeMs = (0, import_node_fs32.statSync)(path2).mtimeMs;
13130
+ mtimeMs = (0, import_node_fs33.statSync)(path2).mtimeMs;
12820
13131
  } catch {
12821
13132
  mtimeMs = Date.now();
12822
13133
  }
@@ -12877,12 +13188,12 @@ function worktreeCleanupSettings() {
12877
13188
  autoCleanupOrphans: a.autoCleanupOrphans
12878
13189
  };
12879
13190
  }
12880
- var import_node_fs32, import_node_path32;
13191
+ var import_node_fs33, import_node_path33;
12881
13192
  var init_orphan_cleanup = __esm({
12882
13193
  "src/git/orphan-cleanup.ts"() {
12883
13194
  "use strict";
12884
- import_node_fs32 = require("fs");
12885
- import_node_path32 = require("path");
13195
+ import_node_fs33 = require("fs");
13196
+ import_node_path33 = require("path");
12886
13197
  init_worktree();
12887
13198
  init_thread_store();
12888
13199
  init_paths();
@@ -12989,38 +13300,38 @@ __export(workspaces_exports, {
12989
13300
  syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
12990
13301
  });
12991
13302
  function workspacesFile() {
12992
- return (0, import_node_path33.join)(appDataDir(), "workspaces.json");
13303
+ return (0, import_node_path34.join)(appDataDir(), "workspaces.json");
12993
13304
  }
12994
13305
  function removedWorkspacesFile() {
12995
- return (0, import_node_path33.join)(appDataDir(), "removed-workspaces.json");
13306
+ return (0, import_node_path34.join)(appDataDir(), "removed-workspaces.json");
12996
13307
  }
12997
13308
  function readAll2() {
12998
13309
  const path2 = workspacesFile();
12999
- if (!(0, import_node_fs33.existsSync)(path2)) return [];
13310
+ if (!(0, import_node_fs34.existsSync)(path2)) return [];
13000
13311
  try {
13001
- const raw = JSON.parse((0, import_node_fs33.readFileSync)(path2, "utf8"));
13312
+ const raw = JSON.parse((0, import_node_fs34.readFileSync)(path2, "utf8"));
13002
13313
  return Array.isArray(raw) ? raw : [];
13003
13314
  } catch {
13004
13315
  return [];
13005
13316
  }
13006
13317
  }
13007
13318
  function writeAll2(list) {
13008
- (0, import_node_fs33.mkdirSync)(appDataDir(), { recursive: true });
13009
- (0, import_node_fs33.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
13319
+ (0, import_node_fs34.mkdirSync)(appDataDir(), { recursive: true });
13320
+ (0, import_node_fs34.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
13010
13321
  }
13011
13322
  function readRemoved() {
13012
13323
  const path2 = removedWorkspacesFile();
13013
- if (!(0, import_node_fs33.existsSync)(path2)) return /* @__PURE__ */ new Set();
13324
+ if (!(0, import_node_fs34.existsSync)(path2)) return /* @__PURE__ */ new Set();
13014
13325
  try {
13015
- const raw = JSON.parse((0, import_node_fs33.readFileSync)(path2, "utf8"));
13326
+ const raw = JSON.parse((0, import_node_fs34.readFileSync)(path2, "utf8"));
13016
13327
  return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
13017
13328
  } catch {
13018
13329
  return /* @__PURE__ */ new Set();
13019
13330
  }
13020
13331
  }
13021
13332
  function writeRemoved(paths) {
13022
- (0, import_node_fs33.mkdirSync)(appDataDir(), { recursive: true });
13023
- (0, import_node_fs33.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
13333
+ (0, import_node_fs34.mkdirSync)(appDataDir(), { recursive: true });
13334
+ (0, import_node_fs34.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
13024
13335
  }
13025
13336
  function rememberRemoved(repoPath) {
13026
13337
  const next = readRemoved();
@@ -13043,7 +13354,7 @@ function listWorkspaces() {
13043
13354
  async function addWorkspace(repoPath) {
13044
13355
  const root = await resolveRepoRoot(repoPath);
13045
13356
  if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
13046
- if (!(0, import_node_fs33.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
13357
+ if (!(0, import_node_fs34.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
13047
13358
  forgetRemoved(root);
13048
13359
  await ensureGhPreferOrigin(root);
13049
13360
  const current = readAll2();
@@ -13051,7 +13362,7 @@ async function addWorkspace(repoPath) {
13051
13362
  if (existing) return existing;
13052
13363
  const next = {
13053
13364
  path: root,
13054
- name: (0, import_node_path33.basename)(root),
13365
+ name: (0, import_node_path34.basename)(root),
13055
13366
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
13056
13367
  };
13057
13368
  writeAll2([...current, next]);
@@ -13073,10 +13384,10 @@ function syncWorkspacesFromThreads(repoPaths) {
13073
13384
  if (!path2 || path2 === "/" || isGlobalRepoPath(path2) || byPath.has(path2) || removed.has(path2)) {
13074
13385
  continue;
13075
13386
  }
13076
- if (!(0, import_node_fs33.existsSync)(path2)) continue;
13387
+ if (!(0, import_node_fs34.existsSync)(path2)) continue;
13077
13388
  const ws = {
13078
13389
  path: path2,
13079
- name: (0, import_node_path33.basename)(path2),
13390
+ name: (0, import_node_path34.basename)(path2),
13080
13391
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
13081
13392
  };
13082
13393
  byPath.set(path2, ws);
@@ -13086,12 +13397,12 @@ function syncWorkspacesFromThreads(repoPaths) {
13086
13397
  if (dirty) writeAll2(next);
13087
13398
  return next.sort((a, b) => a.name.localeCompare(b.name));
13088
13399
  }
13089
- var import_node_fs33, import_node_path33;
13400
+ var import_node_fs34, import_node_path34;
13090
13401
  var init_workspaces2 = __esm({
13091
13402
  "src/store/workspaces.ts"() {
13092
13403
  "use strict";
13093
- import_node_fs33 = require("fs");
13094
- import_node_path33 = require("path");
13404
+ import_node_fs34 = require("fs");
13405
+ import_node_path34 = require("path");
13095
13406
  init_paths();
13096
13407
  init_global_workspace();
13097
13408
  init_worktree();
@@ -13104,12 +13415,12 @@ async function cloneRepoIntoSideboard(opts) {
13104
13415
  if (!url) throw new Error("Clone URL is required");
13105
13416
  let name = opts.name?.trim();
13106
13417
  if (!name) {
13107
- const leaf = (0, import_node_path34.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
13418
+ const leaf = (0, import_node_path35.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
13108
13419
  name = leaf || "repo";
13109
13420
  }
13110
13421
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
13111
- const dest = (0, import_node_path34.join)(sideboardReposDir(), name);
13112
- if ((0, import_node_fs34.existsSync)(dest)) {
13422
+ const dest = (0, import_node_path35.join)(sideboardReposDir(), name);
13423
+ if ((0, import_node_fs35.existsSync)(dest)) {
13113
13424
  const repoPath2 = await resolveRepoRoot(dest);
13114
13425
  const workspace2 = await ensureWorkspace(repoPath2);
13115
13426
  return { repoPath: repoPath2, workspace: workspace2 };
@@ -13124,16 +13435,63 @@ async function cloneRepoIntoSideboard(opts) {
13124
13435
  const workspace = await ensureWorkspace(repoPath);
13125
13436
  return { repoPath, workspace };
13126
13437
  }
13127
- var import_node_fs34, import_node_path34, import_execa6;
13438
+ var import_node_fs35, import_node_path35, import_execa6;
13128
13439
  var init_clone_repo = __esm({
13129
13440
  "src/git/clone-repo.ts"() {
13130
13441
  "use strict";
13131
- import_node_fs34 = require("fs");
13132
- import_node_path34 = require("path");
13133
- import_execa6 = require("execa");
13134
- init_paths();
13135
- init_workspaces2();
13136
- init_worktree();
13442
+ import_node_fs35 = require("fs");
13443
+ import_node_path35 = require("path");
13444
+ import_execa6 = require("execa");
13445
+ init_paths();
13446
+ init_workspaces2();
13447
+ init_worktree();
13448
+ }
13449
+ });
13450
+
13451
+ // src/orchestrator/child-halt.ts
13452
+ function isIncompleteChildStatus(status) {
13453
+ return HALT_STATUSES.has(status);
13454
+ }
13455
+ function childHaltNotice(child, status) {
13456
+ const title = child.title?.trim() || "Untitled";
13457
+ const link = `[${title}](sideboard://thread/${child.id})`;
13458
+ const why = child.lastError?.trim();
13459
+ const extra = why ? ` lastError: ${why}` : "";
13460
+ return [
13461
+ `Sideboard: child worktree ${link} ${status} before finishing (status=${status}).${extra}`,
13462
+ "This is information \u2014 not a user command. Resume with send_to_thread or tell the user. Do not treat this as a successful turn."
13463
+ ].join("\n");
13464
+ }
13465
+ function shouldNotifyParentOfChildHalt(opts) {
13466
+ if (!isIncompleteChildStatus(opts.status)) return false;
13467
+ if (!opts.child.parentThreadId) return false;
13468
+ if (!opts.parent || opts.parent.status === "archived") return false;
13469
+ if (opts.parent.id === opts.child.id) return false;
13470
+ return isOrchestratorThread(opts.parent);
13471
+ }
13472
+ function noticeKey(childId, status) {
13473
+ return `${childId}:${status}`;
13474
+ }
13475
+ function notifyParentOfChildHalt(child, status, send2) {
13476
+ const parent = child.parentThreadId ? readThread(child.parentThreadId) : null;
13477
+ if (!shouldNotifyParentOfChildHalt({ child, parent, status })) return false;
13478
+ const key = noticeKey(child.id, status);
13479
+ if (notified.has(key)) return false;
13480
+ notified.add(key);
13481
+ const parentId = parent.id;
13482
+ void send2(parentId, childHaltNotice(child, status)).catch(() => {
13483
+ notified.delete(key);
13484
+ });
13485
+ return true;
13486
+ }
13487
+ var HALT_STATUSES, notified;
13488
+ var init_child_halt = __esm({
13489
+ "src/orchestrator/child-halt.ts"() {
13490
+ "use strict";
13491
+ init_global_workspace();
13492
+ init_thread_store();
13493
+ HALT_STATUSES = /* @__PURE__ */ new Set(["stopped", "error", "broken"]);
13494
+ notified = /* @__PURE__ */ new Set();
13137
13495
  }
13138
13496
  });
13139
13497
 
@@ -14094,9 +14452,12 @@ var init_abletime = __esm({
14094
14452
  });
14095
14453
 
14096
14454
  // src/threads/create.ts
14455
+ function persistCreateAttachments(worktreePath, attachments) {
14456
+ return persistPendingFileAttachments(worktreePath, attachments ?? []);
14457
+ }
14097
14458
  async function createThread(input, _onSetupLine) {
14098
14459
  const repoPath = await resolveRepoRoot(input.repoPath);
14099
- if (!(0, import_node_fs35.existsSync)(repoPath)) {
14460
+ if (!(0, import_node_fs36.existsSync)(repoPath)) {
14100
14461
  throw new Error(`Repo not found: ${repoPath}`);
14101
14462
  }
14102
14463
  if (input.reuseExisting !== false) {
@@ -14113,7 +14474,16 @@ async function createThread(input, _onSetupLine) {
14113
14474
  repoPath: canonicalizeRepoPath(t.repoPath)
14114
14475
  }))
14115
14476
  );
14116
- if (existing) return readThread(existing.id) ?? existing;
14477
+ if (existing) {
14478
+ const thread2 = readThread(existing.id) ?? existing;
14479
+ if (!input.attachments?.length) return thread2;
14480
+ return updateThread(thread2.id, {
14481
+ attachments: persistCreateAttachments(thread2.worktreePath, [
14482
+ ...thread2.attachments,
14483
+ ...input.attachments
14484
+ ])
14485
+ });
14486
+ }
14117
14487
  }
14118
14488
  const resolved = resolveNewThreadOptions({
14119
14489
  agent: input.agent,
@@ -14161,7 +14531,7 @@ async function createThread(input, _onSetupLine) {
14161
14531
  effort: resolved.effort,
14162
14532
  fast: resolved.fast,
14163
14533
  planMode: Boolean(input.planMode),
14164
- attachments: input.attachments ?? [],
14534
+ attachments: persistCreateAttachments(repoPath, input.attachments),
14165
14535
  sourceIsFork: false,
14166
14536
  parentThreadId: input.parentThreadId ?? null,
14167
14537
  status: "idle",
@@ -14240,7 +14610,7 @@ async function createThread(input, _onSetupLine) {
14240
14610
  effort: resolved.effort,
14241
14611
  fast: resolved.fast,
14242
14612
  planMode: Boolean(input.planMode),
14243
- attachments,
14613
+ attachments: persistCreateAttachments(worktreePath, attachments),
14244
14614
  sourceIsFork,
14245
14615
  parentThreadId: input.parentThreadId ?? null,
14246
14616
  status: "idle",
@@ -14260,16 +14630,17 @@ async function listLinearIssues(agent, repoPath) {
14260
14630
  }
14261
14631
  return adapter.listLinearIssues(repoPath);
14262
14632
  }
14263
- var import_node_fs35;
14633
+ var import_node_fs36;
14264
14634
  var init_create = __esm({
14265
14635
  "src/threads/create.ts"() {
14266
14636
  "use strict";
14267
- import_node_fs35 = require("fs");
14637
+ import_node_fs36 = require("fs");
14268
14638
  init_detect();
14269
14639
  init_worktree();
14270
14640
  init_home_board();
14271
14641
  init_conductor();
14272
14642
  init_app_settings();
14643
+ init_stage_files();
14273
14644
  init_thread_store();
14274
14645
  init_workspaces2();
14275
14646
  }
@@ -14366,20 +14737,20 @@ function writeTurnLive(threadId, progress) {
14366
14737
  const path2 = threadLivePath(threadId);
14367
14738
  const tmp = `${path2}.${process.pid}.tmp`;
14368
14739
  try {
14369
- (0, import_node_fs36.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
14370
- (0, import_node_fs36.renameSync)(tmp, path2);
14740
+ (0, import_node_fs37.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
14741
+ (0, import_node_fs37.renameSync)(tmp, path2);
14371
14742
  } catch {
14372
14743
  try {
14373
- (0, import_node_fs36.unlinkSync)(tmp);
14744
+ (0, import_node_fs37.unlinkSync)(tmp);
14374
14745
  } catch {
14375
14746
  }
14376
14747
  }
14377
14748
  }
14378
14749
  function readTurnLive(threadId) {
14379
14750
  const path2 = threadLivePath(threadId);
14380
- if (!(0, import_node_fs36.existsSync)(path2)) return null;
14751
+ if (!(0, import_node_fs37.existsSync)(path2)) return null;
14381
14752
  try {
14382
- const raw = JSON.parse((0, import_node_fs36.readFileSync)(path2, "utf8"));
14753
+ const raw = JSON.parse((0, import_node_fs37.readFileSync)(path2, "utf8"));
14383
14754
  if (!raw || typeof raw.summary !== "string") return null;
14384
14755
  return raw;
14385
14756
  } catch {
@@ -14391,17 +14762,17 @@ function clearTurnLive(threadId) {
14391
14762
  if (buf?.timer) clearTimeout(buf.timer);
14392
14763
  buffers.delete(threadId);
14393
14764
  const path2 = threadLivePath(threadId);
14394
- if (!(0, import_node_fs36.existsSync)(path2)) return;
14765
+ if (!(0, import_node_fs37.existsSync)(path2)) return;
14395
14766
  try {
14396
- (0, import_node_fs36.unlinkSync)(path2);
14767
+ (0, import_node_fs37.unlinkSync)(path2);
14397
14768
  } catch {
14398
14769
  }
14399
14770
  }
14400
- var import_node_fs36, buffers, FLUSH_MS, MAX_PARTS;
14771
+ var import_node_fs37, buffers, FLUSH_MS, MAX_PARTS;
14401
14772
  var init_turn_live = __esm({
14402
14773
  "src/store/turn-live.ts"() {
14403
14774
  "use strict";
14404
- import_node_fs36 = require("fs");
14775
+ import_node_fs37 = require("fs");
14405
14776
  init_message_parts();
14406
14777
  init_paths();
14407
14778
  buffers = /* @__PURE__ */ new Map();
@@ -14560,7 +14931,7 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
14560
14931
  `- Do not wait on the limited ${from.agent} account; keep going on ${fallbackAgent}.`
14561
14932
  ].join("\n");
14562
14933
  return {
14563
- id: (0, import_node_crypto7.randomUUID)(),
14934
+ id: (0, import_node_crypto8.randomUUID)(),
14564
14935
  name: "Orchestration quota handoff.md",
14565
14936
  kind: "transcript",
14566
14937
  content: body
@@ -14581,11 +14952,11 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
14581
14952
  sourceType: "orchestration"
14582
14953
  });
14583
14954
  }
14584
- var import_node_crypto7, QUOTA_CONTINUE_PROMPT, QUOTA_RESUME_PROMPT;
14955
+ var import_node_crypto8, QUOTA_CONTINUE_PROMPT, QUOTA_RESUME_PROMPT;
14585
14956
  var init_quota_failover = __esm({
14586
14957
  "src/orchestrator/quota-failover.ts"() {
14587
14958
  "use strict";
14588
- import_node_crypto7 = require("crypto");
14959
+ import_node_crypto8 = require("crypto");
14589
14960
  init_session_quota();
14590
14961
  init_app_settings();
14591
14962
  init_global_workspace();
@@ -14602,7 +14973,7 @@ var init_quota_failover = __esm({
14602
14973
  // src/threads/adopt.ts
14603
14974
  function thisModuleFile() {
14604
14975
  const cjsFile = typeof __filename !== "undefined" ? __filename : "";
14605
- return cjsFile || process.argv[1] || (0, import_node_path35.join)(process.cwd(), "package.json");
14976
+ return cjsFile || process.argv[1] || (0, import_node_path36.join)(process.cwd(), "package.json");
14606
14977
  }
14607
14978
  function openReadonlySqlite(file) {
14608
14979
  const req = (0, import_node_module4.createRequire)(thisModuleFile());
@@ -14620,21 +14991,21 @@ function mapAgentType(raw) {
14620
14991
  return null;
14621
14992
  }
14622
14993
  function resolveConductorCursorAgentId(workspacePath) {
14623
- if (!workspacePath || !(0, import_node_fs37.existsSync)(CURSOR_SDK_STORE)) return null;
14994
+ if (!workspacePath || !(0, import_node_fs38.existsSync)(CURSOR_SDK_STORE)) return null;
14624
14995
  const normalized = workspacePath.replace(/\/$/, "");
14625
14996
  let best = null;
14626
14997
  let hashes;
14627
14998
  try {
14628
- hashes = (0, import_node_fs37.readdirSync)(CURSOR_SDK_STORE);
14999
+ hashes = (0, import_node_fs38.readdirSync)(CURSOR_SDK_STORE);
14629
15000
  } catch {
14630
15001
  return null;
14631
15002
  }
14632
15003
  for (const hash of hashes) {
14633
- const agentsFile = (0, import_node_path35.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
14634
- if (!(0, import_node_fs37.existsSync)(agentsFile)) continue;
15004
+ const agentsFile = (0, import_node_path36.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
15005
+ if (!(0, import_node_fs38.existsSync)(agentsFile)) continue;
14635
15006
  let text5;
14636
15007
  try {
14637
- text5 = (0, import_node_fs37.readFileSync)(agentsFile, "utf8");
15008
+ text5 = (0, import_node_fs38.readFileSync)(agentsFile, "utf8");
14638
15009
  } catch {
14639
15010
  continue;
14640
15011
  }
@@ -14658,7 +15029,7 @@ function resolveConductorCursorAgentId(workspacePath) {
14658
15029
  return best?.agentId ?? null;
14659
15030
  }
14660
15031
  async function adoptThread(input) {
14661
- if (!(0, import_node_fs37.existsSync)(input.worktreePath)) {
15032
+ if (!(0, import_node_fs38.existsSync)(input.worktreePath)) {
14662
15033
  throw new Error(`Worktree not found: ${input.worktreePath}`);
14663
15034
  }
14664
15035
  const repoPath = await resolveRepoRoot(input.worktreePath);
@@ -14685,18 +15056,18 @@ function conductorDbPath() {
14685
15056
  return CONDUCTOR_DB;
14686
15057
  }
14687
15058
  function listConductorWorkspaces() {
14688
- if (!(0, import_node_fs37.existsSync)(CONDUCTOR_DB)) {
15059
+ if (!(0, import_node_fs38.existsSync)(CONDUCTOR_DB)) {
14689
15060
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
14690
15061
  }
14691
- const tmp = (0, import_node_fs37.mkdtempSync)((0, import_node_path35.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
14692
- const snapshot = (0, import_node_path35.join)(tmp, "conductor.db");
15062
+ const tmp = (0, import_node_fs38.mkdtempSync)((0, import_node_path36.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
15063
+ const snapshot = (0, import_node_path36.join)(tmp, "conductor.db");
14693
15064
  try {
14694
- (0, import_node_fs37.copyFileSync)(CONDUCTOR_DB, snapshot);
15065
+ (0, import_node_fs38.copyFileSync)(CONDUCTOR_DB, snapshot);
14695
15066
  for (const suffix of ["-wal", "-shm"]) {
14696
15067
  const src = `${CONDUCTOR_DB}${suffix}`;
14697
- if ((0, import_node_fs37.existsSync)(src)) {
15068
+ if ((0, import_node_fs38.existsSync)(src)) {
14698
15069
  try {
14699
- (0, import_node_fs37.copyFileSync)(src, `${snapshot}${suffix}`);
15070
+ (0, import_node_fs38.copyFileSync)(src, `${snapshot}${suffix}`);
14700
15071
  } catch {
14701
15072
  }
14702
15073
  }
@@ -14772,22 +15143,22 @@ function listConductorWorkspaces() {
14772
15143
  db.close();
14773
15144
  }
14774
15145
  } finally {
14775
- (0, import_node_fs37.rmSync)(tmp, { recursive: true, force: true });
15146
+ (0, import_node_fs38.rmSync)(tmp, { recursive: true, force: true });
14776
15147
  }
14777
15148
  }
14778
15149
  function importConductorWorkspace(workspaceId) {
14779
- if (!(0, import_node_fs37.existsSync)(CONDUCTOR_DB)) {
15150
+ if (!(0, import_node_fs38.existsSync)(CONDUCTOR_DB)) {
14780
15151
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
14781
15152
  }
14782
- const tmp = (0, import_node_fs37.mkdtempSync)((0, import_node_path35.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
14783
- const snapshot = (0, import_node_path35.join)(tmp, "conductor.db");
15153
+ const tmp = (0, import_node_fs38.mkdtempSync)((0, import_node_path36.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
15154
+ const snapshot = (0, import_node_path36.join)(tmp, "conductor.db");
14784
15155
  try {
14785
- (0, import_node_fs37.copyFileSync)(CONDUCTOR_DB, snapshot);
15156
+ (0, import_node_fs38.copyFileSync)(CONDUCTOR_DB, snapshot);
14786
15157
  for (const suffix of ["-wal", "-shm"]) {
14787
15158
  const src = `${CONDUCTOR_DB}${suffix}`;
14788
- if ((0, import_node_fs37.existsSync)(src)) {
15159
+ if ((0, import_node_fs38.existsSync)(src)) {
14789
15160
  try {
14790
- (0, import_node_fs37.copyFileSync)(src, `${snapshot}${suffix}`);
15161
+ (0, import_node_fs38.copyFileSync)(src, `${snapshot}${suffix}`);
14791
15162
  } catch {
14792
15163
  }
14793
15164
  }
@@ -14805,7 +15176,7 @@ function importConductorWorkspace(workspaceId) {
14805
15176
  ).get(workspaceId);
14806
15177
  if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
14807
15178
  const worktreePath = String(row.workspacePath);
14808
- if (!(0, import_node_fs37.existsSync)(worktreePath)) {
15179
+ if (!(0, import_node_fs38.existsSync)(worktreePath)) {
14809
15180
  throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
14810
15181
  }
14811
15182
  let sessionId = null;
@@ -14868,31 +15239,31 @@ function importConductorWorkspace(workspaceId) {
14868
15239
  db.close();
14869
15240
  }
14870
15241
  } finally {
14871
- (0, import_node_fs37.rmSync)(tmp, { recursive: true, force: true });
15242
+ (0, import_node_fs38.rmSync)(tmp, { recursive: true, force: true });
14872
15243
  }
14873
15244
  }
14874
15245
  async function importConductorWorkspaceAsync(workspaceId) {
14875
15246
  return importConductorWorkspace(workspaceId);
14876
15247
  }
14877
- var import_node_child_process4, import_node_fs37, import_node_os10, import_node_path35, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
15248
+ var import_node_child_process4, import_node_fs38, import_node_os10, import_node_path36, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
14878
15249
  var init_adopt = __esm({
14879
15250
  "src/threads/adopt.ts"() {
14880
15251
  "use strict";
14881
15252
  import_node_child_process4 = require("child_process");
14882
- import_node_fs37 = require("fs");
15253
+ import_node_fs38 = require("fs");
14883
15254
  import_node_os10 = require("os");
14884
- import_node_path35 = require("path");
15255
+ import_node_path36 = require("path");
14885
15256
  import_node_module4 = require("module");
14886
15257
  init_worktree();
14887
15258
  init_thread_store();
14888
- CONDUCTOR_APP_SUPPORT = (0, import_node_path35.join)(
15259
+ CONDUCTOR_APP_SUPPORT = (0, import_node_path36.join)(
14889
15260
  process.env.HOME ?? "",
14890
15261
  "Library",
14891
15262
  "Application Support",
14892
15263
  "com.conductor.app"
14893
15264
  );
14894
- CONDUCTOR_DB = (0, import_node_path35.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
14895
- CURSOR_SDK_STORE = (0, import_node_path35.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
15265
+ CONDUCTOR_DB = (0, import_node_path36.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
15266
+ CURSOR_SDK_STORE = (0, import_node_path36.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
14896
15267
  }
14897
15268
  });
14898
15269
 
@@ -14959,7 +15330,7 @@ async function openStackLayer(input, _onSetupLine) {
14959
15330
  let createdWorktree = false;
14960
15331
  const trees = await listWorktrees(repoPath);
14961
15332
  const checkedOut = trees.find((w) => w.branch === branchName);
14962
- if (checkedOut?.path && (0, import_node_fs38.existsSync)(checkedOut.path)) {
15333
+ if (checkedOut?.path && (0, import_node_fs39.existsSync)(checkedOut.path)) {
14963
15334
  if (input.reuseExistingWorktree !== false) {
14964
15335
  worktreePath = checkedOut.path;
14965
15336
  } else {
@@ -15101,7 +15472,7 @@ async function initStackFromThread(input, onSetupLine) {
15101
15472
  async function createPrStack(input, onSetupLine) {
15102
15473
  await requireAgent(input.agent);
15103
15474
  const repoPath = await resolveRepoRoot(input.repoPath);
15104
- if (!(0, import_node_fs38.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
15475
+ if (!(0, import_node_fs39.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
15105
15476
  if (!input.branches.length) throw new Error("At least one branch name required");
15106
15477
  const status = await detectGhStack(repoPath);
15107
15478
  if (!status.available) throw new Error(status.reason);
@@ -15168,7 +15539,7 @@ async function createPrStack(input, onSetupLine) {
15168
15539
  }
15169
15540
  }
15170
15541
  const claimed = new Set(threads.map((t) => t.worktreePath));
15171
- if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs38.existsSync)(bootstrap.worktreePath)) {
15542
+ if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs39.existsSync)(bootstrap.worktreePath)) {
15172
15543
  try {
15173
15544
  await removeWorktree(repoPath, bootstrap.worktreePath, {
15174
15545
  deleteBranch: bootstrap.branchName
@@ -15188,11 +15559,11 @@ function stackAgentDefaultsFrom(input) {
15188
15559
  planMode: input.planMode
15189
15560
  };
15190
15561
  }
15191
- var import_node_fs38;
15562
+ var import_node_fs39;
15192
15563
  var init_stack_layers = __esm({
15193
15564
  "src/threads/stack-layers.ts"() {
15194
15565
  "use strict";
15195
- import_node_fs38 = require("fs");
15566
+ import_node_fs39 = require("fs");
15196
15567
  init_detect();
15197
15568
  init_run();
15198
15569
  init_stack();
@@ -15205,7 +15576,7 @@ var init_stack_layers = __esm({
15205
15576
 
15206
15577
  // src/diff/diff.ts
15207
15578
  async function inspectGitWorktree(worktreePath) {
15208
- if (!worktreePath || !(0, import_node_fs39.existsSync)(worktreePath)) return "missing_worktree";
15579
+ if (!worktreePath || !(0, import_node_fs40.existsSync)(worktreePath)) return "missing_worktree";
15209
15580
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
15210
15581
  reject: false
15211
15582
  });
@@ -15213,7 +15584,7 @@ async function inspectGitWorktree(worktreePath) {
15213
15584
  return "ok";
15214
15585
  }
15215
15586
  async function initializeGitRepository(worktreePath) {
15216
- if (!worktreePath || !(0, import_node_fs39.existsSync)(worktreePath)) {
15587
+ if (!worktreePath || !(0, import_node_fs40.existsSync)(worktreePath)) {
15217
15588
  throw new Error("Worktree not found");
15218
15589
  }
15219
15590
  const status = await inspectGitWorktree(worktreePath);
@@ -15347,11 +15718,11 @@ new file mode 100644
15347
15718
  };
15348
15719
  }
15349
15720
  async function untrackedPatch(worktreePath, path2, maxHunk) {
15350
- const abs = (0, import_node_path36.join)(worktreePath, path2);
15721
+ const abs = (0, import_node_path37.join)(worktreePath, path2);
15351
15722
  try {
15352
- const st = (0, import_node_fs39.statSync)(abs);
15723
+ const st = (0, import_node_fs40.statSync)(abs);
15353
15724
  if (st.isFile() && st.size > maxHunk) {
15354
- const buf = (0, import_node_fs39.readFileSync)(abs).subarray(0, maxHunk);
15725
+ const buf = (0, import_node_fs40.readFileSync)(abs).subarray(0, maxHunk);
15355
15726
  return syntheticAddPatch(path2, buf.toString("utf8"), maxHunk);
15356
15727
  }
15357
15728
  } catch {
@@ -15835,13 +16206,13 @@ async function listWorktreeFiles(worktreePath, opts) {
15835
16206
  function isImageRelativePath(relativePath) {
15836
16207
  const base = relativePath.split("/").pop()?.toLowerCase() || "";
15837
16208
  const ext = base.includes(".") ? base.split(".").pop() || "" : "";
15838
- return IMAGE_EXTENSIONS.has(ext);
16209
+ return IMAGE_EXTENSIONS2.has(ext);
15839
16210
  }
15840
16211
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
15841
16212
  assertSafeRelativePath(relativePath);
15842
16213
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
15843
- const abs = (0, import_node_path36.join)(worktreePath, relativePath);
15844
- const st = (0, import_node_fs39.statSync)(abs);
16214
+ const abs = (0, import_node_path37.join)(worktreePath, relativePath);
16215
+ const st = (0, import_node_fs40.statSync)(abs);
15845
16216
  if (!st.isFile()) {
15846
16217
  throw new Error(`Not a file: ${relativePath}`);
15847
16218
  }
@@ -15850,7 +16221,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
15850
16221
  `File too large to upload (${st.size} bytes; max ${maxBytes})`
15851
16222
  );
15852
16223
  }
15853
- const buf = (0, import_node_fs39.readFileSync)(abs);
16224
+ const buf = (0, import_node_fs40.readFileSync)(abs);
15854
16225
  return {
15855
16226
  path: relativePath,
15856
16227
  contentBase64: buf.toString("base64"),
@@ -15860,12 +16231,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
15860
16231
  function readWorktreeFile(worktreePath, relativePath, opts) {
15861
16232
  assertSafeRelativePath(relativePath);
15862
16233
  const maxBytes = opts?.maxBytes ?? 2e5;
15863
- const abs = (0, import_node_path36.join)(worktreePath, relativePath);
15864
- const st = (0, import_node_fs39.statSync)(abs);
16234
+ const abs = (0, import_node_path37.join)(worktreePath, relativePath);
16235
+ const st = (0, import_node_fs40.statSync)(abs);
15865
16236
  if (!st.isFile()) {
15866
16237
  throw new Error(`Not a file: ${relativePath}`);
15867
16238
  }
15868
- const buf = (0, import_node_fs39.readFileSync)(abs);
16239
+ const buf = (0, import_node_fs40.readFileSync)(abs);
15869
16240
  if (isImageRelativePath(relativePath)) {
15870
16241
  const maxImageBytes = Math.max(maxBytes, 15e6);
15871
16242
  const truncated2 = buf.length > maxImageBytes;
@@ -15908,9 +16279,9 @@ function assertSafeRelativePath(relativePath) {
15908
16279
  }
15909
16280
  function writeWorktreeFile(worktreePath, relativePath, content) {
15910
16281
  assertSafeRelativePath(relativePath);
15911
- const abs = (0, import_node_path36.join)(worktreePath, relativePath);
15912
- (0, import_node_fs39.mkdirSync)((0, import_node_path36.dirname)(abs), { recursive: true });
15913
- (0, import_node_fs39.writeFileSync)(abs, content, "utf8");
16282
+ const abs = (0, import_node_path37.join)(worktreePath, relativePath);
16283
+ (0, import_node_fs40.mkdirSync)((0, import_node_path37.dirname)(abs), { recursive: true });
16284
+ (0, import_node_fs40.writeFileSync)(abs, content, "utf8");
15914
16285
  return { path: relativePath };
15915
16286
  }
15916
16287
  async function getDiffSummary(worktreePath, repoPath, opts) {
@@ -15927,18 +16298,18 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
15927
16298
  truncated: full.files.length > maxFiles
15928
16299
  };
15929
16300
  }
15930
- var import_node_fs39, import_node_path36, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS, DEFAULT_UPLOAD_MAX_BYTES;
16301
+ var import_node_fs40, import_node_path37, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
15931
16302
  var init_diff = __esm({
15932
16303
  "src/diff/diff.ts"() {
15933
16304
  "use strict";
15934
- import_node_fs39 = require("fs");
15935
- import_node_path36 = require("path");
16305
+ import_node_fs40 = require("fs");
16306
+ import_node_path37 = require("path");
15936
16307
  init_run();
15937
16308
  init_worktree();
15938
16309
  mergeBaseCache = /* @__PURE__ */ new Map();
15939
16310
  MERGE_BASE_TTL_MS = 45e3;
15940
16311
  SHA_RE = /^[0-9a-f]{7,40}$/i;
15941
- IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
16312
+ IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
15942
16313
  "png",
15943
16314
  "jpg",
15944
16315
  "jpeg",
@@ -16100,7 +16471,7 @@ function parseFrontmatter(content) {
16100
16471
  }
16101
16472
  function readSkill(skillMd, source) {
16102
16473
  try {
16103
- const content = (0, import_node_fs40.readFileSync)(skillMd, "utf8");
16474
+ const content = (0, import_node_fs41.readFileSync)(skillMd, "utf8");
16104
16475
  const { name: fmName, description } = parseFrontmatter(content);
16105
16476
  const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
16106
16477
  const name = fmName || dirName;
@@ -16119,19 +16490,19 @@ function readSkill(skillMd, source) {
16119
16490
  }
16120
16491
  }
16121
16492
  function scanSkillsDir(dir, source, out) {
16122
- if (!(0, import_node_fs40.existsSync)(dir)) return;
16493
+ if (!(0, import_node_fs41.existsSync)(dir)) return;
16123
16494
  let entries;
16124
16495
  try {
16125
- entries = (0, import_node_fs40.readdirSync)(dir);
16496
+ entries = (0, import_node_fs41.readdirSync)(dir);
16126
16497
  } catch {
16127
16498
  return;
16128
16499
  }
16129
16500
  for (const entry of entries) {
16130
16501
  if (entry.startsWith(".")) continue;
16131
- const skillMd = (0, import_node_path37.join)(dir, entry, "SKILL.md");
16132
- if (!(0, import_node_fs40.existsSync)(skillMd)) continue;
16502
+ const skillMd = (0, import_node_path38.join)(dir, entry, "SKILL.md");
16503
+ if (!(0, import_node_fs41.existsSync)(skillMd)) continue;
16133
16504
  try {
16134
- if (!(0, import_node_fs40.statSync)(skillMd).isFile()) continue;
16505
+ if (!(0, import_node_fs41.statSync)(skillMd).isFile()) continue;
16135
16506
  } catch {
16136
16507
  continue;
16137
16508
  }
@@ -16140,24 +16511,24 @@ function scanSkillsDir(dir, source, out) {
16140
16511
  }
16141
16512
  }
16142
16513
  function scanClaudePluginSkills(pluginsRoot, out) {
16143
- if (!(0, import_node_fs40.existsSync)(pluginsRoot)) return;
16514
+ if (!(0, import_node_fs41.existsSync)(pluginsRoot)) return;
16144
16515
  const walk = (dir, depth, lookingForSkillsDir) => {
16145
16516
  if (depth > 7) return;
16146
16517
  let entries;
16147
16518
  try {
16148
- entries = (0, import_node_fs40.readdirSync)(dir);
16519
+ entries = (0, import_node_fs41.readdirSync)(dir);
16149
16520
  } catch {
16150
16521
  return;
16151
16522
  }
16152
16523
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
16153
- const skill = readSkill((0, import_node_path37.join)(dir, "SKILL.md"), "cli");
16524
+ const skill = readSkill((0, import_node_path38.join)(dir, "SKILL.md"), "cli");
16154
16525
  if (skill) out.push(skill);
16155
16526
  }
16156
16527
  for (const entry of entries) {
16157
16528
  if (entry === "node_modules" || entry === ".git") continue;
16158
- const full = (0, import_node_path37.join)(dir, entry);
16529
+ const full = (0, import_node_path38.join)(dir, entry);
16159
16530
  try {
16160
- if (!(0, import_node_fs40.statSync)(full).isDirectory()) continue;
16531
+ if (!(0, import_node_fs41.statSync)(full).isDirectory()) continue;
16161
16532
  } catch {
16162
16533
  continue;
16163
16534
  }
@@ -16175,17 +16546,17 @@ function discoverSkills(worktreePath) {
16175
16546
  const home = (0, import_node_os11.homedir)();
16176
16547
  const collected = [];
16177
16548
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
16178
- scanSkillsDir((0, import_node_path37.join)(worktreePath, rel), "workspace", collected);
16549
+ scanSkillsDir((0, import_node_path38.join)(worktreePath, rel), "workspace", collected);
16179
16550
  }
16180
16551
  for (const abs of [
16181
- (0, import_node_path37.join)(home, ".claude/skills"),
16182
- (0, import_node_path37.join)(home, ".cursor/skills"),
16183
- (0, import_node_path37.join)(home, ".sideboard/skills"),
16184
- (0, import_node_path37.join)(home, ".brightsy/skills")
16552
+ (0, import_node_path38.join)(home, ".claude/skills"),
16553
+ (0, import_node_path38.join)(home, ".cursor/skills"),
16554
+ (0, import_node_path38.join)(home, ".sideboard/skills"),
16555
+ (0, import_node_path38.join)(home, ".brightsy/skills")
16185
16556
  ]) {
16186
16557
  scanSkillsDir(abs, "user", collected);
16187
16558
  }
16188
- scanClaudePluginSkills((0, import_node_path37.join)(home, ".claude/plugins"), collected);
16559
+ scanClaudePluginSkills((0, import_node_path38.join)(home, ".claude/plugins"), collected);
16189
16560
  const rank = { workspace: 0, user: 1, cli: 2 };
16190
16561
  const byCommand = /* @__PURE__ */ new Map();
16191
16562
  for (const skill of collected) {
@@ -16197,7 +16568,7 @@ function discoverSkills(worktreePath) {
16197
16568
  return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
16198
16569
  }
16199
16570
  function readSkillBody(skillPath, maxChars = 12e3) {
16200
- const raw = (0, import_node_fs40.readFileSync)(skillPath, "utf8");
16571
+ const raw = (0, import_node_fs41.readFileSync)(skillPath, "utf8");
16201
16572
  if (raw.startsWith("---")) {
16202
16573
  const end = raw.indexOf("\n---", 3);
16203
16574
  if (end >= 0) {
@@ -16211,13 +16582,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
16211
16582
 
16212
16583
  \u2026(truncated)` : raw;
16213
16584
  }
16214
- var import_node_fs40, import_node_os11, import_node_path37;
16585
+ var import_node_fs41, import_node_os11, import_node_path38;
16215
16586
  var init_discover = __esm({
16216
16587
  "src/skills/discover.ts"() {
16217
16588
  "use strict";
16218
- import_node_fs40 = require("fs");
16589
+ import_node_fs41 = require("fs");
16219
16590
  import_node_os11 = require("os");
16220
- import_node_path37 = require("path");
16591
+ import_node_path38 = require("path");
16221
16592
  }
16222
16593
  });
16223
16594
 
@@ -16306,236 +16677,6 @@ var init_expand = __esm({
16306
16677
  }
16307
16678
  });
16308
16679
 
16309
- // src/composer/stage-files.ts
16310
- function fileExtension(filePath) {
16311
- const base = (0, import_node_path38.basename)(filePath).toLowerCase();
16312
- return base.includes(".") ? base.split(".").pop() || "" : "";
16313
- }
16314
- function isImageFilePath(filePath) {
16315
- return IMAGE_EXTENSIONS2.has(fileExtension(filePath));
16316
- }
16317
- function imageMimeType(filePath) {
16318
- return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
16319
- }
16320
- function ensureAttachmentsDir(worktreePath) {
16321
- const dir = (0, import_node_path38.join)(worktreePath, ATTACHMENTS_DIR);
16322
- (0, import_node_fs41.mkdirSync)(dir, { recursive: true });
16323
- const gi = (0, import_node_path38.join)(dir, ".gitignore");
16324
- if (!(0, import_node_fs41.existsSync)(gi)) {
16325
- (0, import_node_fs41.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
16326
- }
16327
- return dir;
16328
- }
16329
- function uniqueAttachmentName(dir, originalName) {
16330
- const safe = originalName.replace(/[/\\]/g, "_") || "file";
16331
- if (!(0, import_node_fs41.existsSync)((0, import_node_path38.join)(dir, safe))) return safe;
16332
- const ext = (0, import_node_path38.extname)(safe);
16333
- const stem = ext ? safe.slice(0, -ext.length) : safe;
16334
- for (let i = 1; i < 1e4; i++) {
16335
- const candidate = `${stem}-${i}${ext}`;
16336
- if (!(0, import_node_fs41.existsSync)((0, import_node_path38.join)(dir, candidate))) return candidate;
16337
- }
16338
- return `${stem}-${(0, import_node_crypto8.randomUUID)()}${ext}`;
16339
- }
16340
- function previewDataUrlFromBuf(filePath, buf) {
16341
- if (!isImageFilePath(filePath)) return void 0;
16342
- if (buf.length > MAX_PREVIEW_BYTES) return void 0;
16343
- return `data:${imageMimeType(filePath)};base64,${buf.toString("base64")}`;
16344
- }
16345
- function attachmentFromBuffer(name, buf, opts) {
16346
- const previewDataUrl = previewDataUrlFromBuf(name, buf);
16347
- if (isImageFilePath(name)) {
16348
- const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
16349
- return {
16350
- id: (0, import_node_crypto8.randomUUID)(),
16351
- name,
16352
- kind: "file",
16353
- path: opts.path,
16354
- previewDataUrl,
16355
- content: [
16356
- `Image attached: ${pathHint}`,
16357
- opts.path ? `Use the Read tool on \`${opts.path}\` to view this image.` : "The image is shown in the composer; copy it into the worktree if you need to inspect pixels."
16358
- ].join("\n")
16359
- };
16360
- }
16361
- if (buf.length > MAX_INLINE_BYTES) {
16362
- return {
16363
- id: (0, import_node_crypto8.randomUUID)(),
16364
- name,
16365
- kind: "file",
16366
- path: opts.path,
16367
- content: opts.path ? `(file too large to attach inline: \`${opts.path}\`, ${buf.length} bytes \u2014 use the Read tool)` : `(file too large to attach inline: ${opts.sourceLabel || name}, ${buf.length} bytes)`
16368
- };
16369
- }
16370
- if (buf.includes(0)) {
16371
- return {
16372
- id: (0, import_node_crypto8.randomUUID)(),
16373
- name,
16374
- kind: "file",
16375
- path: opts.path,
16376
- content: opts.path ? `(binary file at \`${opts.path}\` \u2014 use tools to inspect)` : `(binary file attached by path only: ${opts.sourceLabel || name})`
16377
- };
16378
- }
16379
- return {
16380
- id: (0, import_node_crypto8.randomUUID)(),
16381
- name,
16382
- kind: "file",
16383
- path: opts.path,
16384
- content: buf.toString("utf8")
16385
- };
16386
- }
16387
- function attachmentFromAbsolutePath(absolutePath) {
16388
- const name = (0, import_node_path38.basename)(absolutePath);
16389
- try {
16390
- const st = (0, import_node_fs41.statSync)(absolutePath);
16391
- if (!st.isFile()) {
16392
- return {
16393
- id: (0, import_node_crypto8.randomUUID)(),
16394
- name,
16395
- kind: "file",
16396
- content: `(not a file: ${absolutePath})`
16397
- };
16398
- }
16399
- const buf = (0, import_node_fs41.readFileSync)(absolutePath);
16400
- return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
16401
- } catch (err) {
16402
- return {
16403
- id: (0, import_node_crypto8.randomUUID)(),
16404
- name,
16405
- kind: "file",
16406
- content: `(could not read ${absolutePath}: ${err instanceof Error ? err.message : String(err)})`
16407
- };
16408
- }
16409
- }
16410
- function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
16411
- if (absolutePaths.length === 0) return [];
16412
- const dir = ensureAttachmentsDir(worktreePath);
16413
- const out = [];
16414
- for (const abs of absolutePaths) {
16415
- const originalName = (0, import_node_path38.basename)(abs);
16416
- try {
16417
- const st = (0, import_node_fs41.statSync)(abs);
16418
- if (!st.isFile()) continue;
16419
- const name = uniqueAttachmentName(dir, originalName);
16420
- const destAbs = (0, import_node_path38.join)(dir, name);
16421
- (0, import_node_fs41.copyFileSync)(abs, destAbs);
16422
- const rel = `${ATTACHMENTS_DIR}/${name}`;
16423
- const buf = (0, import_node_fs41.readFileSync)(destAbs);
16424
- out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
16425
- } catch (err) {
16426
- out.push({
16427
- id: (0, import_node_crypto8.randomUUID)(),
16428
- name: originalName,
16429
- kind: "file",
16430
- content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
16431
- });
16432
- }
16433
- }
16434
- return out;
16435
- }
16436
- function stageBuffersAsAttachments(worktreePath, buffers2) {
16437
- if (buffers2.length === 0) return [];
16438
- const dir = ensureAttachmentsDir(worktreePath);
16439
- const out = [];
16440
- for (const item of buffers2) {
16441
- const originalName = (item.name || "file").replace(/[/\\]/g, "_") || "file";
16442
- try {
16443
- const buf = Buffer.from(item.dataBase64, "base64");
16444
- const name = uniqueAttachmentName(dir, originalName);
16445
- const destAbs = (0, import_node_path38.join)(dir, name);
16446
- (0, import_node_fs41.writeFileSync)(destAbs, buf);
16447
- const rel = `${ATTACHMENTS_DIR}/${name}`;
16448
- out.push(attachmentFromBuffer(name, buf, { path: rel }));
16449
- } catch (err) {
16450
- out.push({
16451
- id: (0, import_node_crypto8.randomUUID)(),
16452
- name: originalName,
16453
- kind: "file",
16454
- content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
16455
- });
16456
- }
16457
- }
16458
- return out;
16459
- }
16460
- function attachmentsFromBuffers(buffers2) {
16461
- return buffers2.map((item) => {
16462
- const name = (item.name || "file").replace(/[/\\]/g, "_") || "file";
16463
- try {
16464
- const buf = Buffer.from(item.dataBase64, "base64");
16465
- return attachmentFromBuffer(name, buf, { sourceLabel: name });
16466
- } catch (err) {
16467
- return {
16468
- id: (0, import_node_crypto8.randomUUID)(),
16469
- name,
16470
- kind: "file",
16471
- content: `(could not attach ${name}: ${err instanceof Error ? err.message : String(err)})`
16472
- };
16473
- }
16474
- });
16475
- }
16476
- function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
16477
- const out = [];
16478
- for (const rel of relativePaths) {
16479
- if (!rel || rel.includes("..") || rel.startsWith("/")) {
16480
- out.push({
16481
- id: (0, import_node_crypto8.randomUUID)(),
16482
- name: (0, import_node_path38.basename)(rel) || "file",
16483
- kind: "file",
16484
- content: `(invalid path: ${rel})`
16485
- });
16486
- continue;
16487
- }
16488
- const name = (0, import_node_path38.basename)(rel);
16489
- try {
16490
- const abs = (0, import_node_path38.join)(worktreePath, rel);
16491
- const st = (0, import_node_fs41.statSync)(abs);
16492
- if (!st.isFile()) continue;
16493
- const buf = (0, import_node_fs41.readFileSync)(abs);
16494
- out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
16495
- } catch (err) {
16496
- out.push({
16497
- id: (0, import_node_crypto8.randomUUID)(),
16498
- name,
16499
- kind: "file",
16500
- content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
16501
- });
16502
- }
16503
- }
16504
- return out;
16505
- }
16506
- var import_node_fs41, import_node_path38, import_node_crypto8, IMAGE_EXTENSIONS2, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES;
16507
- var init_stage_files = __esm({
16508
- "src/composer/stage-files.ts"() {
16509
- "use strict";
16510
- import_node_fs41 = require("fs");
16511
- import_node_path38 = require("path");
16512
- import_node_crypto8 = require("crypto");
16513
- init_workspace_scratch();
16514
- IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
16515
- "png",
16516
- "jpg",
16517
- "jpeg",
16518
- "gif",
16519
- "webp",
16520
- "svg",
16521
- "bmp",
16522
- "ico"
16523
- ]);
16524
- IMAGE_MIME_BY_EXT = {
16525
- png: "image/png",
16526
- jpg: "image/jpeg",
16527
- jpeg: "image/jpeg",
16528
- gif: "image/gif",
16529
- webp: "image/webp",
16530
- svg: "image/svg+xml",
16531
- bmp: "image/bmp",
16532
- ico: "image/x-icon"
16533
- };
16534
- MAX_INLINE_BYTES = 4e5;
16535
- MAX_PREVIEW_BYTES = 5e6;
16536
- }
16537
- });
16538
-
16539
16680
  // src/agents/instructions.ts
16540
16681
  function normPath3(p) {
16541
16682
  return p.replace(/\/+$/, "");
@@ -17138,6 +17279,7 @@ var init_orchestrator = __esm({
17138
17279
  init_usage();
17139
17280
  init_thread_store();
17140
17281
  init_desktop_host();
17282
+ init_child_halt();
17141
17283
  init_create();
17142
17284
  init_cowboy();
17143
17285
  init_orchestrator_capable();
@@ -17285,6 +17427,9 @@ var init_orchestrator = __esm({
17285
17427
  * MCP-created review threads don't stay `queued` after the MCP child exits.
17286
17428
  */
17287
17429
  adoptPersistedQueues() {
17430
+ if (thisProcessShouldDrainAgentQueues()) {
17431
+ this.healStaleRunningTurns();
17432
+ }
17288
17433
  for (const thread of listThreads()) {
17289
17434
  if (thread.status === "stopped" || thread.status === "archived") continue;
17290
17435
  const pid = thread.agentPid;
@@ -17305,6 +17450,32 @@ var init_orchestrator = __esm({
17305
17450
  }
17306
17451
  }
17307
17452
  }
17453
+ /**
17454
+ * Mid-session: a worktree can sit at `running` after the agent process dies
17455
+ * (Cursor/CLI crash, OOM) while wait_for_turn still reports stillRunning.
17456
+ * Reclaim those and wake the parent orchestration chat.
17457
+ */
17458
+ healStaleRunningTurns() {
17459
+ for (const thread of listThreads()) {
17460
+ if (thread.status === "archived") continue;
17461
+ const handle = this.activeTurns.get(thread.id);
17462
+ if (handle) {
17463
+ const pid = thread.agentPid;
17464
+ if (typeof pid === "number" && pid > 0 && !isPidAlive(pid)) {
17465
+ handle.kill();
17466
+ }
17467
+ continue;
17468
+ }
17469
+ if (!this.shouldReclaimRunningThread(thread)) continue;
17470
+ setStatus(thread.id, "stopped", "Process died (agent exited)");
17471
+ this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
17472
+ this.emit({ type: "turn_finished", threadId: thread.id, exitCode: 1 });
17473
+ const latest = readThread(thread.id);
17474
+ if (latest) {
17475
+ notifyParentOfChildHalt(latest, "stopped", (id, prompt) => this.send(id, prompt));
17476
+ }
17477
+ }
17478
+ }
17308
17479
  clearQuotaResumeTimer(threadId) {
17309
17480
  const timer = this.quotaResumeTimers.get(threadId);
17310
17481
  if (timer) clearTimeout(timer);
@@ -18022,6 +18193,12 @@ var init_orchestrator = __esm({
18022
18193
  assistantText: chatText,
18023
18194
  partsCount: parts.length
18024
18195
  });
18196
+ if (!this.crashContinued.has(threadId)) {
18197
+ const failed = readThread(threadId);
18198
+ if (failed) {
18199
+ notifyParentOfChildHalt(failed, "error", (id, prompt2) => this.send(id, prompt2));
18200
+ }
18201
+ }
18025
18202
  }
18026
18203
  }
18027
18204
  } catch (err) {
@@ -18046,6 +18223,12 @@ var init_orchestrator = __esm({
18046
18223
  assistantText: "",
18047
18224
  partsCount: 0
18048
18225
  });
18226
+ if (!this.crashContinued.has(threadId)) {
18227
+ const failed = readThread(threadId);
18228
+ if (failed) {
18229
+ notifyParentOfChildHalt(failed, "error", (id, prompt2) => this.send(id, prompt2));
18230
+ }
18231
+ }
18049
18232
  }
18050
18233
  } finally {
18051
18234
  this.startingTurns.delete(threadId);
@@ -18101,6 +18284,9 @@ var init_orchestrator = __esm({
18101
18284
  const stopped = writeLiveStatus(thread.id, "stopped") ?? readThread(thread.id) ?? thread;
18102
18285
  if (stopped.status === "stopped") {
18103
18286
  this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
18287
+ if (opts?.notifyParent !== false) {
18288
+ notifyParentOfChildHalt(stopped, "stopped", (id, prompt) => this.send(id, prompt));
18289
+ }
18104
18290
  }
18105
18291
  return stopped;
18106
18292
  }
@@ -18345,21 +18531,25 @@ var init_orchestrator = __esm({
18345
18531
  fn();
18346
18532
  };
18347
18533
  const off = this.on((event) => {
18348
- if (event.type === "turn_finished" && event.threadId === thread.id) {
18534
+ if (!("threadId" in event) || event.threadId !== thread.id) return;
18535
+ if (event.type === "turn_finished" || event.type === "error") {
18349
18536
  const latest = readThread(thread.id);
18350
18537
  if (!latest) {
18351
18538
  finish(() => reject(new Error(`Thread not found: ${thread.id}`)));
18352
18539
  return;
18353
18540
  }
18354
18541
  finish(() => resolve(latest));
18542
+ return;
18355
18543
  }
18356
- if (event.type === "error" && event.threadId === thread.id) {
18544
+ if (event.type === "status_changed") {
18357
18545
  const latest = readThread(thread.id);
18358
18546
  if (!latest) {
18359
18547
  finish(() => reject(new Error(`Thread not found: ${thread.id}`)));
18360
18548
  return;
18361
18549
  }
18362
- finish(() => resolve(latest));
18550
+ if (!["running", "queued"].includes(latest.status)) {
18551
+ finish(() => resolve(latest));
18552
+ }
18363
18553
  }
18364
18554
  });
18365
18555
  timer = setInterval(() => {
@@ -18394,7 +18584,7 @@ var init_orchestrator = __esm({
18394
18584
  const thread = this.requireThread(threadRef);
18395
18585
  const lastAgent = [...thread.messages].reverse().find((m) => m.role === "agent");
18396
18586
  const lastError = thread.lastError ?? null;
18397
- const text5 = (lastAgent?.text ?? "").trim() || (thread.status === "error" ? lastError ?? "" : "");
18587
+ const text5 = (lastAgent?.text ?? "").trim() || (thread.status === "error" || thread.status === "stopped" || thread.status === "broken" ? lastError ?? "" : "");
18398
18588
  const stillRunning = thread.status === "running" || thread.status === "queued";
18399
18589
  const live = stillRunning ? readTurnLive(thread.id) : null;
18400
18590
  const queuedHint = thread.status === "queued" && !live?.summary ? "Queued \u2014 waiting for a concurrency slot" : null;
@@ -19172,6 +19362,7 @@ __export(index_exports, {
19172
19362
  PLAN_FILE_NAME: () => PLAN_FILE_NAME,
19173
19363
  PLAN_FILE_REL: () => PLAN_FILE_REL,
19174
19364
  PLAN_MODE_INSTRUCTION: () => PLAN_MODE_INSTRUCTION,
19365
+ PLAN_QUESTION_ANSWERS_PREFIX: () => PLAN_QUESTION_ANSWERS_PREFIX,
19175
19366
  REPO_REVIEW_NAME: () => REPO_REVIEW_NAME,
19176
19367
  REPO_REVIEW_PATH: () => REPO_REVIEW_PATH,
19177
19368
  REVIEW_REQUEST_NAME: () => REVIEW_REQUEST_NAME,
@@ -19471,6 +19662,7 @@ __export(index_exports, {
19471
19662
  isOrchestratorThread: () => isOrchestratorThread,
19472
19663
  isPidAlive: () => isPidAlive,
19473
19664
  isPlaceholderBranch: () => isPlaceholderBranch,
19665
+ isPlanQuestionAnswersMessage: () => isPlanQuestionAnswersMessage,
19474
19666
  isPollWrapperToolName: () => isPollWrapperToolName,
19475
19667
  isPrNotMergeableError: () => isPrNotMergeableError,
19476
19668
  isPresentPlanToolName: () => isPresentPlanToolName,
@@ -19581,6 +19773,7 @@ __export(index_exports, {
19581
19773
  pastedTextStats: () => pastedTextStats,
19582
19774
  pendingSlackExternalReplies: () => pendingSlackExternalReplies,
19583
19775
  permissionMode: () => permissionMode,
19776
+ persistPendingFileAttachments: () => persistPendingFileAttachments,
19584
19777
  persistVaultKeyInKeychain: () => persistVaultKeyInKeychain,
19585
19778
  planFileAbs: () => planFileAbs,
19586
19779
  planQuestionsSignature: () => planQuestionsSignature,
@@ -19750,6 +19943,7 @@ __export(index_exports, {
19750
19943
  userCursorMcpConfigPath: () => userCursorMcpConfigPath,
19751
19944
  validateLinearApiKey: () => validateLinearApiKey,
19752
19945
  verifyAbleTimeConnection: () => verifyAbleTimeConnection,
19946
+ visibleToolRowDetail: () => visibleToolRowDetail,
19753
19947
  waitForPidExit: () => waitForPidExit,
19754
19948
  warmGithubAgentAuth: () => warmGithubAgentAuth,
19755
19949
  withAgentInstructions: () => withAgentInstructions,
@@ -20775,8 +20969,12 @@ function latestPendingPlanQuestions(input) {
20775
20969
  if (last?.role === "agent") return extractPendingPlanQuestions(last.parts);
20776
20970
  return null;
20777
20971
  }
20972
+ var PLAN_QUESTION_ANSWERS_PREFIX = "Answers to your questions:";
20973
+ function isPlanQuestionAnswersMessage(text5) {
20974
+ return text5.startsWith(PLAN_QUESTION_ANSWERS_PREFIX);
20975
+ }
20778
20976
  function formatPlanQuestionAnswers(questions, answers) {
20779
- const lines = ["Answers to your questions:"];
20977
+ const lines = [PLAN_QUESTION_ANSWERS_PREFIX, ""];
20780
20978
  for (let i = 0; i < questions.length; i++) {
20781
20979
  const q = questions[i];
20782
20980
  const a = answers.find((x) => x.questionIndex === i);
@@ -20785,7 +20983,7 @@ function formatPlanQuestionAnswers(questions, answers) {
20785
20983
  if (a?.selected.length) parts.push(a.selected.join(", "));
20786
20984
  if (a?.other?.trim()) parts.push(a.other.trim());
20787
20985
  const body = parts.length ? parts.join(" \xB7 ") : "(no answer)";
20788
- lines.push(`${i + 1}. ${header}${q.question}`);
20986
+ lines.push(`${i + 1}. ${header}${q.question} `);
20789
20987
  lines.push(` \u2192 ${body}`);
20790
20988
  }
20791
20989
  return lines.join("\n");
@@ -20853,6 +21051,15 @@ var MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u201
20853
21051
  function mcpWaitStillRunningHint(status) {
20854
21052
  return status === "queued" ? MCP_WAIT_QUEUED_HINT : MCP_WAIT_STILL_RUNNING_HINT;
20855
21053
  }
21054
+ var MCP_WAIT_STOPPED_HINT = "Child was stopped before the turn finished. Do not treat this as success. send_to_thread to resume, or tell the user.";
21055
+ var MCP_WAIT_BROKEN_HINT = "Child worktree is broken (missing on disk). Tell the user \u2014 do not treat this as success.";
21056
+ var MCP_WAIT_ERROR_HINT = "Child turn failed. lastError/text is the failure \u2014 switch agent, tell the user, or retry. Do not treat empty text as success.";
21057
+ function mcpWaitFinishedHint(status) {
21058
+ if (status === "stopped") return MCP_WAIT_STOPPED_HINT;
21059
+ if (status === "broken") return MCP_WAIT_BROKEN_HINT;
21060
+ if (status === "error") return MCP_WAIT_ERROR_HINT;
21061
+ return void 0;
21062
+ }
20856
21063
 
20857
21064
  // src/mcp/server.ts
20858
21065
  init_turn_live();
@@ -22631,7 +22838,7 @@ async function startMcpServer() {
22631
22838
  );
22632
22839
  server.tool(
22633
22840
  "wait_for_turn",
22634
- "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. When finished, usage is the last agent turn\u2019s tokens + costUsd (when the provider reported cost).",
22841
+ "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. On status stopped or broken, the child did not finish \u2014 resume with send_to_thread or tell the user; do not treat that as success. When finished, usage is the last agent turn\u2019s tokens + costUsd (when the provider reported cost).",
22635
22842
  {
22636
22843
  ref: import_zod5.z.string(),
22637
22844
  timeoutMs: import_zod5.z.number().optional()
@@ -22653,7 +22860,8 @@ async function startMcpServer() {
22653
22860
  stillRunning: result.stillRunning,
22654
22861
  progress: result.progress,
22655
22862
  lastActivityAt: result.lastActivityAt,
22656
- hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) : void 0
22863
+ hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) : mcpWaitFinishedHint(result.status),
22864
+ incomplete: !result.stillRunning && Boolean(mcpWaitFinishedHint(result.status))
22657
22865
  })
22658
22866
  }
22659
22867
  ]
@@ -22672,7 +22880,8 @@ async function startMcpServer() {
22672
22880
  type: "text",
22673
22881
  text: JSON.stringify({
22674
22882
  ...result,
22675
- hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) : void 0
22883
+ hint: result.stillRunning ? mcpWaitStillRunningHint(result.status) : mcpWaitFinishedHint(result.status),
22884
+ incomplete: !result.stillRunning && Boolean(mcpWaitFinishedHint(result.status))
22676
22885
  })
22677
22886
  }
22678
22887
  ]
@@ -22696,7 +22905,7 @@ async function startMcpServer() {
22696
22905
  }
22697
22906
  const clearQueue = force !== false;
22698
22907
  const hadQueued = t.queue.length > 0;
22699
- const stopped = orch.stop(ref, { clearQueue });
22908
+ const stopped = orch.stop(ref, { clearQueue, notifyParent: false });
22700
22909
  return {
22701
22910
  content: [
22702
22911
  {
@@ -25631,6 +25840,7 @@ init_outbound_watch();
25631
25840
  PLAN_FILE_NAME,
25632
25841
  PLAN_FILE_REL,
25633
25842
  PLAN_MODE_INSTRUCTION,
25843
+ PLAN_QUESTION_ANSWERS_PREFIX,
25634
25844
  REPO_REVIEW_NAME,
25635
25845
  REPO_REVIEW_PATH,
25636
25846
  REVIEW_REQUEST_NAME,
@@ -25930,6 +26140,7 @@ init_outbound_watch();
25930
26140
  isOrchestratorThread,
25931
26141
  isPidAlive,
25932
26142
  isPlaceholderBranch,
26143
+ isPlanQuestionAnswersMessage,
25933
26144
  isPollWrapperToolName,
25934
26145
  isPrNotMergeableError,
25935
26146
  isPresentPlanToolName,
@@ -26040,6 +26251,7 @@ init_outbound_watch();
26040
26251
  pastedTextStats,
26041
26252
  pendingSlackExternalReplies,
26042
26253
  permissionMode,
26254
+ persistPendingFileAttachments,
26043
26255
  persistVaultKeyInKeychain,
26044
26256
  planFileAbs,
26045
26257
  planQuestionsSignature,
@@ -26209,6 +26421,7 @@ init_outbound_watch();
26209
26421
  userCursorMcpConfigPath,
26210
26422
  validateLinearApiKey,
26211
26423
  verifyAbleTimeConnection,
26424
+ visibleToolRowDetail,
26212
26425
  waitForPidExit,
26213
26426
  warmGithubAgentAuth,
26214
26427
  withAgentInstructions,