@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.
- package/dist/{agents-O3AJMI2Y.js → agents-ELWR7A2T.js} +3 -3
- package/dist/{agents-RTQFF7PY.js → agents-QNTTLMG2.js} +3 -3
- package/dist/{chunk-RDULVW3E.js → chunk-4XKUHP6G.js} +1 -1
- package/dist/{chunk-N62K3KXX.js → chunk-CYM5DCHI.js} +38 -4
- package/dist/{chunk-XUEI4GCF.js → chunk-GSKRGF7B.js} +284 -3
- package/dist/{chunk-57GIFU3X.js → chunk-IFZ4MOTN.js} +2 -2
- package/dist/{chunk-KBBXNS2V.js → chunk-JPBRMUM6.js} +8 -4
- package/dist/{chunk-2ESCEK2Q.js → chunk-K5YT5GX2.js} +242 -3
- package/dist/{chunk-LOKXPQ4U.js → chunk-MDCKV2NF.js} +1 -1
- package/dist/{chunk-XIKEUCNC.js → chunk-TIGKDMIA.js} +139 -266
- package/dist/{chunk-K7EX47QG.js → chunk-TQ4S5AGJ.js} +2 -2
- package/dist/{chunk-Z5LYMW7M.js → chunk-WS5LFFU3.js} +135 -217
- package/dist/{coordinator-prompt-Y737IIFR.js → coordinator-prompt-2OWSUAUR.js} +1 -1
- package/dist/{coordinator-prompt-FYMWE33S.js → coordinator-prompt-IPL4Z6SL.js} +1 -1
- package/dist/{global-workspace-6KH6BSKL.js → global-workspace-JDUCUL7S.js} +2 -2
- package/dist/{global-workspace-ZFKNLBZA.js → global-workspace-NIKZAKOO.js} +2 -2
- package/dist/index.cjs +828 -615
- package/dist/index.d.cts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +38 -17
- package/dist/mcp/run-stdio.cjs +657 -485
- package/dist/mcp/run-stdio.js +20 -9
- package/dist/{orchestrator-3YDPPZHZ.js → orchestrator-6I47JMU2.js} +5 -5
- package/dist/{orchestrator-2BRAPJ47.js → orchestrator-KK3CUW37.js} +5 -5
- package/dist/{workspaces-3RRF3LVF.js → workspaces-5EWNNALF.js} +3 -3
- package/dist/{workspaces-AYI5DHK4.js → workspaces-KZA3TCEE.js} +3 -3
- 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,
|
|
3856
|
+
return (0, import_node_path14.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
|
|
3563
3857
|
}
|
|
3564
3858
|
function githubCredentialStorePath() {
|
|
3565
|
-
return (0,
|
|
3859
|
+
return (0, import_node_path14.join)(githubAgentAuthDir(), "git-credentials");
|
|
3566
3860
|
}
|
|
3567
3861
|
function githubGhConfigDir() {
|
|
3568
|
-
return (0,
|
|
3862
|
+
return (0, import_node_path14.join)(githubAgentAuthDir(), "gh");
|
|
3569
3863
|
}
|
|
3570
3864
|
function writePrivateFile2(file, body) {
|
|
3571
|
-
(0,
|
|
3865
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path14.dirname)(file), { recursive: true, mode: 448 });
|
|
3572
3866
|
try {
|
|
3573
|
-
(0,
|
|
3867
|
+
(0, import_node_fs13.chmodSync)((0, import_node_path14.dirname)(file), 448);
|
|
3574
3868
|
} catch {
|
|
3575
3869
|
}
|
|
3576
|
-
(0,
|
|
3870
|
+
(0, import_node_fs13.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
|
|
3577
3871
|
try {
|
|
3578
|
-
(0,
|
|
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,
|
|
3897
|
+
(0, import_node_fs13.mkdirSync)(root, { recursive: true, mode: 448 });
|
|
3604
3898
|
try {
|
|
3605
|
-
(0,
|
|
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,
|
|
3611
|
-
writePrivateFile2((0,
|
|
3612
|
-
writePrivateFile2((0,
|
|
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,
|
|
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
|
|
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
|
-
|
|
3928
|
+
import_node_fs13 = require("fs");
|
|
3635
3929
|
import_node_os4 = require("os");
|
|
3636
|
-
|
|
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,
|
|
3936
|
+
if (!dir || !(0, import_node_fs14.existsSync)(dir)) return;
|
|
3643
3937
|
const current = env.PATH ?? "";
|
|
3644
|
-
const parts = current.split(
|
|
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(
|
|
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,
|
|
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(
|
|
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,
|
|
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,
|
|
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(
|
|
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,
|
|
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
|
|
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
|
-
|
|
4015
|
+
import_node_fs14 = require("fs");
|
|
3722
4016
|
import_node_child_process3 = require("child_process");
|
|
3723
4017
|
import_node_os5 = require("os");
|
|
3724
|
-
|
|
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,
|
|
4040
|
+
const lockPath = (0, import_node_path16.join)(gitDir, "index.lock");
|
|
3747
4041
|
try {
|
|
3748
|
-
if (!(0,
|
|
3749
|
-
if (now - (0,
|
|
3750
|
-
(0,
|
|
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
|
|
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
|
-
|
|
3770
|
-
|
|
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,
|
|
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
|
|
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
|
-
|
|
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,
|
|
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,
|
|
5266
|
-
if ((0,
|
|
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,
|
|
5334
|
-
if ((0,
|
|
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,
|
|
5626
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
5637
|
-
for (const entry of (0,
|
|
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,
|
|
5659
|
-
if (!(0,
|
|
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
|
|
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
|
-
|
|
5669
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
6070
|
+
(0, import_node_fs17.writeFileSync)((0, import_node_path19.join)(dir, "CLAUDE.md"), `${body}
|
|
5798
6071
|
`, "utf8");
|
|
5799
|
-
(0,
|
|
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
|
|
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
|
-
|
|
5836
|
-
|
|
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
|
|
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:
|
|
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,
|
|
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,
|
|
6464
|
+
if (!(0, import_node_fs18.existsSync)(path2)) return {};
|
|
6187
6465
|
try {
|
|
6188
|
-
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0,
|
|
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
|
|
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
|
-
|
|
6208
|
-
|
|
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,
|
|
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
|
|
6602
|
+
var import_node_path21;
|
|
6325
6603
|
var init_workspaces = __esm({
|
|
6326
6604
|
"src/slack/workspaces.ts"() {
|
|
6327
6605
|
"use strict";
|
|
6328
|
-
|
|
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,
|
|
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,
|
|
6628
|
+
if (!(0, import_node_fs19.existsSync)(path2)) return [];
|
|
6351
6629
|
try {
|
|
6352
|
-
const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0,
|
|
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
|
|
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
|
-
|
|
6679
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
7252
|
+
(0, import_node_fs20.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
6975
7253
|
`, {
|
|
6976
7254
|
mode: 384
|
|
6977
7255
|
});
|
|
6978
7256
|
}
|
|
6979
|
-
var
|
|
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
|
-
|
|
7261
|
+
import_node_fs20 = require("fs");
|
|
6984
7262
|
import_node_os6 = require("os");
|
|
6985
|
-
|
|
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,
|
|
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,
|
|
7485
|
+
if (!(0, import_node_fs21.existsSync)(path2)) return [];
|
|
7208
7486
|
try {
|
|
7209
|
-
const parsed = JSON.parse((0,
|
|
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,
|
|
7494
|
+
(0, import_node_fs21.mkdirSync)(appDataDir(), { recursive: true });
|
|
7217
7495
|
const path2 = storePath4();
|
|
7218
|
-
(0,
|
|
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
|
|
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
|
-
|
|
7379
|
-
|
|
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
|
|
8076
|
+
var import_node_fs22, brightsyAdapter;
|
|
7799
8077
|
var init_brightsy = __esm({
|
|
7800
8078
|
"src/agents/brightsy.ts"() {
|
|
7801
8079
|
"use strict";
|
|
7802
|
-
|
|
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,
|
|
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
|
-
|
|
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,
|
|
8475
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
8486
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
8497
|
-
if (!(0,
|
|
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,
|
|
8814
|
+
return (0, import_node_path25.join)(dir, "node_modules", platformPkg, "bin", binName);
|
|
8504
8815
|
}
|
|
8505
|
-
var
|
|
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
|
-
|
|
8510
|
-
|
|
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,
|
|
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,
|
|
8895
|
+
if (!(0, import_node_fs24.existsSync)(root)) return [];
|
|
8585
8896
|
try {
|
|
8586
|
-
return (0,
|
|
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,
|
|
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,
|
|
8600
|
-
(0,
|
|
8601
|
-
(0,
|
|
8602
|
-
(0,
|
|
8603
|
-
(0,
|
|
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,
|
|
8606
|
-
(name) => (0,
|
|
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,
|
|
8610
|
-
(name) => (0,
|
|
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,
|
|
8614
|
-
(name) => (0,
|
|
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,
|
|
8934
|
+
if (!p || !(0, import_node_fs24.existsSync)(p) || isElectronLikeCommand(p)) continue;
|
|
8624
8935
|
let key = p;
|
|
8625
8936
|
try {
|
|
8626
|
-
key = (0,
|
|
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
|
|
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
|
-
|
|
9021
|
+
import_node_fs24 = require("fs");
|
|
8711
9022
|
import_node_os7 = require("os");
|
|
8712
|
-
|
|
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,
|
|
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,
|
|
8812
|
-
return (0,
|
|
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,
|
|
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,
|
|
8826
|
-
(0,
|
|
8827
|
-
(0,
|
|
8828
|
-
(0,
|
|
8829
|
-
(0,
|
|
8830
|
-
(0,
|
|
8831
|
-
(0,
|
|
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,
|
|
9145
|
+
if ((0, import_node_fs25.existsSync)(p) && !isAsarPath(p)) return p;
|
|
8835
9146
|
}
|
|
8836
|
-
const parent = (0,
|
|
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,
|
|
8979
|
-
const cfgPath = (0,
|
|
8980
|
-
(0,
|
|
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
|
|
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
|
-
|
|
9301
|
+
import_node_fs25 = require("fs");
|
|
8991
9302
|
import_node_module = require("module");
|
|
8992
9303
|
import_node_os8 = require("os");
|
|
8993
|
-
|
|
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
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
9632
|
-
(0,
|
|
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,
|
|
9636
|
-
const text5 = (0,
|
|
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,
|
|
9669
|
-
if (!(0,
|
|
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,
|
|
9982
|
+
return (0, import_node_fs27.statSync)(authPath).size > 2;
|
|
9672
9983
|
} catch {
|
|
9673
9984
|
return false;
|
|
9674
9985
|
}
|
|
9675
9986
|
}
|
|
9676
|
-
var
|
|
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
|
-
|
|
9991
|
+
import_node_fs27 = require("fs");
|
|
9681
9992
|
import_node_os9 = require("os");
|
|
9682
|
-
|
|
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,
|
|
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,
|
|
10505
|
+
if (!raw || !(0, import_node_path29.isAbsolute)(raw)) return null;
|
|
10195
10506
|
const readable = nodeReadableScriptPath(raw);
|
|
10196
|
-
if (!(0,
|
|
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,
|
|
10204
|
-
const root = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
10555
|
+
import_node_fs28 = require("fs");
|
|
10245
10556
|
import_node_module2 = require("module");
|
|
10246
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
10308
|
-
(0,
|
|
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,
|
|
10311
|
-
(0,
|
|
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,
|
|
10314
|
-
(0,
|
|
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,
|
|
10628
|
+
if ((0, import_node_fs29.existsSync)(candidate)) return candidate;
|
|
10318
10629
|
}
|
|
10319
10630
|
return candidates[0];
|
|
10320
10631
|
}
|
|
10321
|
-
var
|
|
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
|
-
|
|
10636
|
+
import_node_fs29 = require("fs");
|
|
10326
10637
|
import_node_module3 = require("module");
|
|
10327
|
-
|
|
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,
|
|
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
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
|
12410
|
+
var import_node_crypto6;
|
|
12100
12411
|
var init_chat_tabs = __esm({
|
|
12101
12412
|
"src/threads/chat-tabs.ts"() {
|
|
12102
12413
|
"use strict";
|
|
12103
|
-
|
|
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,
|
|
12584
|
+
if (!(0, import_node_fs31.existsSync)(abs)) return null;
|
|
12274
12585
|
try {
|
|
12275
|
-
const content = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
12312
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
12378
|
-
|
|
12379
|
-
|
|
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,
|
|
12405
|
-
if (!(0,
|
|
12406
|
-
return (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
12446
|
-
if (!(0,
|
|
12447
|
-
const dest = (0,
|
|
12448
|
-
(0,
|
|
12449
|
-
(0,
|
|
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,
|
|
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
|
|
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
|
-
|
|
13060
|
+
import_node_fs32 = require("fs");
|
|
12750
13061
|
import_node_net = require("net");
|
|
12751
|
-
|
|
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,
|
|
13088
|
+
if ((0, import_node_fs33.existsSync)(homeRoot)) {
|
|
12778
13089
|
try {
|
|
12779
|
-
for (const entry of (0,
|
|
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,
|
|
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,
|
|
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,
|
|
12811
|
-
for (const entry of (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
12885
|
-
|
|
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,
|
|
13303
|
+
return (0, import_node_path34.join)(appDataDir(), "workspaces.json");
|
|
12993
13304
|
}
|
|
12994
13305
|
function removedWorkspacesFile() {
|
|
12995
|
-
return (0,
|
|
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,
|
|
13310
|
+
if (!(0, import_node_fs34.existsSync)(path2)) return [];
|
|
13000
13311
|
try {
|
|
13001
|
-
const raw = JSON.parse((0,
|
|
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,
|
|
13009
|
-
(0,
|
|
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,
|
|
13324
|
+
if (!(0, import_node_fs34.existsSync)(path2)) return /* @__PURE__ */ new Set();
|
|
13014
13325
|
try {
|
|
13015
|
-
const raw = JSON.parse((0,
|
|
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,
|
|
13023
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
13387
|
+
if (!(0, import_node_fs34.existsSync)(path2)) continue;
|
|
13077
13388
|
const ws = {
|
|
13078
13389
|
path: path2,
|
|
13079
|
-
name: (0,
|
|
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
|
|
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
|
-
|
|
13094
|
-
|
|
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,
|
|
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,
|
|
13112
|
-
if ((0,
|
|
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
|
|
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
|
-
|
|
13132
|
-
|
|
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,
|
|
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)
|
|
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
|
|
14633
|
+
var import_node_fs36;
|
|
14264
14634
|
var init_create = __esm({
|
|
14265
14635
|
"src/threads/create.ts"() {
|
|
14266
14636
|
"use strict";
|
|
14267
|
-
|
|
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,
|
|
14370
|
-
(0,
|
|
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,
|
|
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,
|
|
14751
|
+
if (!(0, import_node_fs37.existsSync)(path2)) return null;
|
|
14381
14752
|
try {
|
|
14382
|
-
const raw = JSON.parse((0,
|
|
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,
|
|
14765
|
+
if (!(0, import_node_fs37.existsSync)(path2)) return;
|
|
14395
14766
|
try {
|
|
14396
|
-
(0,
|
|
14767
|
+
(0, import_node_fs37.unlinkSync)(path2);
|
|
14397
14768
|
} catch {
|
|
14398
14769
|
}
|
|
14399
14770
|
}
|
|
14400
|
-
var
|
|
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
|
-
|
|
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,
|
|
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
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
14634
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
14692
|
-
const snapshot = (0,
|
|
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,
|
|
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,
|
|
15068
|
+
if ((0, import_node_fs38.existsSync)(src)) {
|
|
14698
15069
|
try {
|
|
14699
|
-
(0,
|
|
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,
|
|
15146
|
+
(0, import_node_fs38.rmSync)(tmp, { recursive: true, force: true });
|
|
14776
15147
|
}
|
|
14777
15148
|
}
|
|
14778
15149
|
function importConductorWorkspace(workspaceId) {
|
|
14779
|
-
if (!(0,
|
|
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,
|
|
14783
|
-
const snapshot = (0,
|
|
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,
|
|
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,
|
|
15159
|
+
if ((0, import_node_fs38.existsSync)(src)) {
|
|
14789
15160
|
try {
|
|
14790
|
-
(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
15253
|
+
import_node_fs38 = require("fs");
|
|
14883
15254
|
import_node_os10 = require("os");
|
|
14884
|
-
|
|
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,
|
|
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,
|
|
14895
|
-
CURSOR_SDK_STORE = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
15562
|
+
var import_node_fs39;
|
|
15192
15563
|
var init_stack_layers = __esm({
|
|
15193
15564
|
"src/threads/stack-layers.ts"() {
|
|
15194
15565
|
"use strict";
|
|
15195
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
15721
|
+
const abs = (0, import_node_path37.join)(worktreePath, path2);
|
|
15351
15722
|
try {
|
|
15352
|
-
const st = (0,
|
|
15723
|
+
const st = (0, import_node_fs40.statSync)(abs);
|
|
15353
15724
|
if (st.isFile() && st.size > maxHunk) {
|
|
15354
|
-
const buf = (0,
|
|
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
|
|
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,
|
|
15844
|
-
const st = (0,
|
|
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,
|
|
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,
|
|
15864
|
-
const st = (0,
|
|
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,
|
|
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,
|
|
15912
|
-
(0,
|
|
15913
|
-
(0,
|
|
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
|
|
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
|
-
|
|
15935
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
16493
|
+
if (!(0, import_node_fs41.existsSync)(dir)) return;
|
|
16123
16494
|
let entries;
|
|
16124
16495
|
try {
|
|
16125
|
-
entries = (0,
|
|
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,
|
|
16132
|
-
if (!(0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
16529
|
+
const full = (0, import_node_path38.join)(dir, entry);
|
|
16159
16530
|
try {
|
|
16160
|
-
if (!(0,
|
|
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,
|
|
16549
|
+
scanSkillsDir((0, import_node_path38.join)(worktreePath, rel), "workspace", collected);
|
|
16179
16550
|
}
|
|
16180
16551
|
for (const abs of [
|
|
16181
|
-
(0,
|
|
16182
|
-
(0,
|
|
16183
|
-
(0,
|
|
16184
|
-
(0,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
16589
|
+
import_node_fs41 = require("fs");
|
|
16219
16590
|
import_node_os11 = require("os");
|
|
16220
|
-
|
|
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 (
|
|
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 === "
|
|
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
|
-
|
|
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 = [
|
|
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) :
|
|
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) :
|
|
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,
|