@sideboard-ai/core 0.1.89 → 0.1.95
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/cursor-runner.cjs +129 -14
- package/dist/agents/cursor-runner.js +4 -1
- package/dist/{agents-LMUFTGKF.js → agents-HBLA6FEV.js} +4 -4
- package/dist/{agents-ODBP7J6E.js → agents-WS5QV6LE.js} +5 -5
- package/dist/{chunk-WANQFU3S.js → chunk-6XBXVXX2.js} +2 -2
- package/dist/{chunk-7D27DD2X.js → chunk-CIRXAYWS.js} +260 -61
- package/dist/{chunk-B2KIO2SD.js → chunk-CLGO7TLO.js} +2 -2
- package/dist/{chunk-CBJSPTBG.js → chunk-GXSYI7FH.js} +206 -5
- package/dist/{chunk-RJLBSYUO.js → chunk-KWNUZ4LR.js} +46 -77
- package/dist/{chunk-UHTNJKZX.js → chunk-NR6APJLD.js} +2 -2
- package/dist/{chunk-6EZRSCIT.js → chunk-QKYO6BHB.js} +2 -2
- package/dist/{chunk-ZXYWWSHZ.js → chunk-R7BQBSDT.js} +254 -61
- package/dist/{chunk-JE75QW2I.js → chunk-WBX46OPD.js} +237 -96
- package/dist/{chunk-OB6IRIFV.js → chunk-XH2GS2LO.js} +2 -2
- package/dist/{chunk-VZ2L4AEJ.js → chunk-XUWDLRAE.js} +2 -2
- package/dist/{coordinator-prompt-UK5LYFN5.js → coordinator-prompt-AKEY4WSO.js} +2 -2
- package/dist/{coordinator-prompt-CI5SHONJ.js → coordinator-prompt-OQOOD5ET.js} +2 -2
- package/dist/{global-workspace-2YZ2V4I5.js → global-workspace-3GNPQCLE.js} +3 -3
- package/dist/{global-workspace-JQQLPJM5.js → global-workspace-M3OMVDDH.js} +3 -3
- package/dist/index.cjs +1021 -473
- package/dist/index.d.cts +91 -20
- package/dist/index.d.ts +91 -20
- package/dist/index.js +244 -59
- package/dist/mcp/run-stdio.cjs +816 -428
- package/dist/mcp/run-stdio.js +77 -40
- package/dist/{workspaces-YWCC3WV4.js → workspaces-ERZC7ULY.js} +4 -4
- package/dist/{workspaces-FDO5L4NI.js → workspaces-J4WG6UFR.js} +4 -4
- package/dist/{worktree-7YNSJ224.js → worktree-DA4BOV7G.js} +7 -1
- package/dist/{worktree-4555QBQ7.js → worktree-EO5QAGJU.js} +7 -1
- package/package.json +1 -1
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -858,17 +858,27 @@ function extractJsonErrorMessage(obj) {
|
|
|
858
858
|
}
|
|
859
859
|
return null;
|
|
860
860
|
}
|
|
861
|
+
function isPinnedStderrLine(line) {
|
|
862
|
+
if (/^\s*at\s/.test(line)) return false;
|
|
863
|
+
return /cannot find (?:package|module)|ERR_MODULE_NOT_FOUND|cursor startup failed:/i.test(
|
|
864
|
+
line
|
|
865
|
+
);
|
|
866
|
+
}
|
|
861
867
|
function pushTurnStderr(tail, line, maxLines = 12) {
|
|
862
868
|
const trimmed = line.trim();
|
|
863
869
|
if (!trimmed) return;
|
|
864
870
|
if (NODE_VERSION_FOOTER.test(trimmed)) return;
|
|
865
871
|
if (/^reconnecting\.\.\./i.test(trimmed)) return;
|
|
866
872
|
tail.push(trimmed);
|
|
867
|
-
while (tail.length > maxLines)
|
|
873
|
+
while (tail.length > maxLines) {
|
|
874
|
+
const dropIdx = tail.findIndex((l) => !isPinnedStderrLine(l));
|
|
875
|
+
if (dropIdx === -1) tail.shift();
|
|
876
|
+
else tail.splice(dropIdx, 1);
|
|
877
|
+
}
|
|
868
878
|
}
|
|
869
879
|
function looksLikeMinifiedJsDump(line) {
|
|
870
880
|
if (line.length < 200) return false;
|
|
871
|
-
return /yield Promise\.all/.test(line) || /\(0,[A-Za-z$]\.\w+\)/.test(line) || /CURSOR_RIPGREP_PATH/.test(line);
|
|
881
|
+
return /yield Promise\.all/.test(line) || /\(0,[A-Za-z$]\.\w+\)/.test(line) || /CURSOR_RIPGREP_PATH/.test(line) || /findFilesWithRipgrep/.test(line) || /@cursor\/sdk\/dist\//.test(line);
|
|
872
882
|
}
|
|
873
883
|
function looksLikeNestedElectronCrash(line) {
|
|
874
884
|
return /HasCustomHostObject|ElectronInitializeICUandStartNode/i.test(line);
|
|
@@ -883,7 +893,15 @@ function summarizeTurnStderr(tail, maxChars = 500) {
|
|
|
883
893
|
const cursorStartup = [...tail].reverse().find((line) => /cursor startup failed:/i.test(line));
|
|
884
894
|
if (cursorStartup) return clipStderr(cursorStartup, maxChars);
|
|
885
895
|
if (tail.some(looksLikeNestedElectronCrash)) return NESTED_ELECTRON_SUMMARY;
|
|
886
|
-
|
|
896
|
+
if (tail.some(
|
|
897
|
+
(line) => /\[resource_exhausted\]|resource_exhausted/i.test(line) || /findFilesWithRipgrep/.test(line)
|
|
898
|
+
)) {
|
|
899
|
+
return clipStderr(
|
|
900
|
+
"Cursor local file search failed (ripgrep / resource_exhausted). Wait a minute and retry; if it keeps happening, check Cursor usage.",
|
|
901
|
+
maxChars
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
const moduleMissing = [...tail].reverse().find((line) => /cannot find (?:package|module)/i.test(line));
|
|
887
905
|
if (moduleMissing) return clipStderr(moduleMissing, maxChars);
|
|
888
906
|
const useful = tail.filter((line) => !looksLikeMinifiedJsDump(line));
|
|
889
907
|
if (useful.length === 0 && tail.some(looksLikeMinifiedJsDump)) {
|
|
@@ -902,7 +920,7 @@ function looksLikeAgentFailureMessage(text3) {
|
|
|
902
920
|
if (!lower) return false;
|
|
903
921
|
return /you've hit your|hit your (session|weekly|opus) limit|usage limit/.test(lower) || /credit balance is too low|out of credits|insufficient.?quota|quota.?exceeded/.test(lower) || /invalid user api key|invalid api key|not logged in|not authenticated|unauthorized/.test(
|
|
904
922
|
lower
|
|
905
|
-
) || /\b429\b|too many requests|rate.?limit/.test(lower) || /prompt is too long|context.*(too long|exceed)|conversation too long/.test(lower);
|
|
923
|
+
) || /\b429\b|too many requests|rate.?limit/.test(lower) || /prompt is too long|context.*(too long|exceed)|conversation too long/.test(lower) || /\[resource_exhausted\]|resource_exhausted/.test(lower) || /findFilesWithRipgrep/.test(text3);
|
|
906
924
|
}
|
|
907
925
|
function fallbackTurnFailDetail(assistantText) {
|
|
908
926
|
const t = assistantText.trim();
|
|
@@ -924,6 +942,9 @@ function humanizeAgentFailDetail(detail) {
|
|
|
924
942
|
if (/\b429\b|rate.?limit|too many requests/.test(lower)) {
|
|
925
943
|
return `${raw} \u2014 wait a moment and retry.`;
|
|
926
944
|
}
|
|
945
|
+
if (/\[resource_exhausted\]|resource_exhausted|findfileswithripgrep/.test(lower)) {
|
|
946
|
+
return "Cursor local file search failed (ripgrep / resource_exhausted). Wait a minute and retry; if it keeps happening, check Cursor usage.";
|
|
947
|
+
}
|
|
927
948
|
if (/invalid user api key|invalid api key|not logged in|not authenticated|unauthorized|authentication|please run.*login|codex login|claude auth|cursor api/.test(
|
|
928
949
|
lower
|
|
929
950
|
)) {
|
|
@@ -2880,42 +2901,124 @@ var init_app_settings = __esm({
|
|
|
2880
2901
|
}
|
|
2881
2902
|
});
|
|
2882
2903
|
|
|
2904
|
+
// src/git/github-agent-auth.ts
|
|
2905
|
+
function githubAgentAuthDir() {
|
|
2906
|
+
const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
|
|
2907
|
+
if (override) return override;
|
|
2908
|
+
return (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
|
|
2909
|
+
}
|
|
2910
|
+
function githubCredentialStorePath() {
|
|
2911
|
+
return (0, import_node_path12.join)(githubAgentAuthDir(), "git-credentials");
|
|
2912
|
+
}
|
|
2913
|
+
function githubGhConfigDir() {
|
|
2914
|
+
return (0, import_node_path12.join)(githubAgentAuthDir(), "gh");
|
|
2915
|
+
}
|
|
2916
|
+
function writePrivateFile2(file, body) {
|
|
2917
|
+
(0, import_node_fs11.mkdirSync)((0, import_node_path12.dirname)(file), { recursive: true, mode: 448 });
|
|
2918
|
+
try {
|
|
2919
|
+
(0, import_node_fs11.chmodSync)((0, import_node_path12.dirname)(file), 448);
|
|
2920
|
+
} catch {
|
|
2921
|
+
}
|
|
2922
|
+
(0, import_node_fs11.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
|
|
2923
|
+
try {
|
|
2924
|
+
(0, import_node_fs11.chmodSync)(file, 384);
|
|
2925
|
+
} catch {
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
function gitCredentialStoreContents(token) {
|
|
2929
|
+
return `https://x-access-token:${encodeURIComponent(token)}@github.com
|
|
2930
|
+
`;
|
|
2931
|
+
}
|
|
2932
|
+
function ghHostsYml(token, user = "x-access-token") {
|
|
2933
|
+
const u = user.replace(/[^A-Za-z0-9._-]/g, "") || "x-access-token";
|
|
2934
|
+
return [
|
|
2935
|
+
"github.com:",
|
|
2936
|
+
" git_protocol: https",
|
|
2937
|
+
` user: ${u}`,
|
|
2938
|
+
` oauth_token: ${token}`,
|
|
2939
|
+
" users:",
|
|
2940
|
+
` ${u}:`,
|
|
2941
|
+
` oauth_token: ${token}`,
|
|
2942
|
+
""
|
|
2943
|
+
].join("\n");
|
|
2944
|
+
}
|
|
2945
|
+
function materializeGithubAgentAuth(token, user) {
|
|
2946
|
+
const trimmed = token.trim();
|
|
2947
|
+
if (!trimmed) return;
|
|
2948
|
+
const root = githubAgentAuthDir();
|
|
2949
|
+
(0, import_node_fs11.mkdirSync)(root, { recursive: true, mode: 448 });
|
|
2950
|
+
try {
|
|
2951
|
+
(0, import_node_fs11.chmodSync)(root, 448);
|
|
2952
|
+
} catch {
|
|
2953
|
+
}
|
|
2954
|
+
writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
|
|
2955
|
+
const ghDir = githubGhConfigDir();
|
|
2956
|
+
(0, import_node_fs11.mkdirSync)(ghDir, { recursive: true, mode: 448 });
|
|
2957
|
+
writePrivateFile2((0, import_node_path12.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
|
|
2958
|
+
writePrivateFile2((0, import_node_path12.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
|
|
2959
|
+
}
|
|
2960
|
+
function githubAgentAuthReady() {
|
|
2961
|
+
return (0, import_node_fs11.existsSync)(githubCredentialStorePath()) && (0, import_node_fs11.existsSync)((0, import_node_path12.join)(githubGhConfigDir(), "hosts.yml"));
|
|
2962
|
+
}
|
|
2963
|
+
function githubCredentialHelperGitConfig() {
|
|
2964
|
+
const file = githubCredentialStorePath();
|
|
2965
|
+
return [
|
|
2966
|
+
{ key: "credential.helper", value: "" },
|
|
2967
|
+
{ key: "credential.helper", value: `store --file=${file}` }
|
|
2968
|
+
];
|
|
2969
|
+
}
|
|
2970
|
+
function githubGhConfigEnv() {
|
|
2971
|
+
return {
|
|
2972
|
+
GH_CONFIG_DIR: githubGhConfigDir(),
|
|
2973
|
+
GH_PROMPT_DISABLED: "1"
|
|
2974
|
+
};
|
|
2975
|
+
}
|
|
2976
|
+
var import_node_fs11, import_node_os4, import_node_path12;
|
|
2977
|
+
var init_github_agent_auth = __esm({
|
|
2978
|
+
"src/git/github-agent-auth.ts"() {
|
|
2979
|
+
"use strict";
|
|
2980
|
+
import_node_fs11 = require("fs");
|
|
2981
|
+
import_node_os4 = require("os");
|
|
2982
|
+
import_node_path12 = require("path");
|
|
2983
|
+
}
|
|
2984
|
+
});
|
|
2985
|
+
|
|
2883
2986
|
// src/agents/path.ts
|
|
2884
2987
|
function prependPathDir(env, dir) {
|
|
2885
|
-
if (!dir || !(0,
|
|
2988
|
+
if (!dir || !(0, import_node_fs12.existsSync)(dir)) return;
|
|
2886
2989
|
const current = env.PATH ?? "";
|
|
2887
|
-
const parts = current.split(
|
|
2990
|
+
const parts = current.split(import_node_path13.delimiter).filter(Boolean);
|
|
2888
2991
|
if (parts.includes(dir)) {
|
|
2889
2992
|
env.PATH = current;
|
|
2890
2993
|
return;
|
|
2891
2994
|
}
|
|
2892
|
-
env.PATH = [dir, ...parts].join(
|
|
2995
|
+
env.PATH = [dir, ...parts].join(import_node_path13.delimiter);
|
|
2893
2996
|
}
|
|
2894
|
-
function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0,
|
|
2895
|
-
return (0,
|
|
2997
|
+
function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os5.homedir)()) {
|
|
2998
|
+
return (0, import_node_path13.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
|
|
2896
2999
|
}
|
|
2897
3000
|
function isConductorBundledCli(filePath) {
|
|
2898
3001
|
const p = (filePath ?? "").replace(/\\/g, "/");
|
|
2899
3002
|
return p.includes("/com.conductor.app/bin/") || p.endsWith("/com.conductor.app/bin");
|
|
2900
3003
|
}
|
|
2901
3004
|
function ensureAgentPath(env = process.env) {
|
|
2902
|
-
const home = env.HOME || env.USERPROFILE || (0,
|
|
3005
|
+
const home = env.HOME || env.USERPROFILE || (0, import_node_os5.homedir)();
|
|
2903
3006
|
const current = env.PATH ?? "";
|
|
2904
|
-
const parts = current.split(
|
|
3007
|
+
const parts = current.split(import_node_path13.delimiter).filter(Boolean);
|
|
2905
3008
|
const seen = new Set(parts);
|
|
2906
3009
|
const extras = [
|
|
2907
|
-
...EXTRA_BIN_DIRS.map((rel) => (0,
|
|
3010
|
+
...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path13.join)(home, rel)),
|
|
2908
3011
|
"/opt/homebrew/bin",
|
|
2909
3012
|
"/usr/local/bin",
|
|
2910
3013
|
// Keep after Homebrew/npm so a user-installed CLI still wins.
|
|
2911
3014
|
conductorBundledBinDir(home)
|
|
2912
3015
|
];
|
|
2913
3016
|
for (const dir of extras.reverse()) {
|
|
2914
|
-
if (!dir || seen.has(dir) || !(0,
|
|
3017
|
+
if (!dir || seen.has(dir) || !(0, import_node_fs12.existsSync)(dir)) continue;
|
|
2915
3018
|
parts.unshift(dir);
|
|
2916
3019
|
seen.add(dir);
|
|
2917
3020
|
}
|
|
2918
|
-
const next = parts.join(
|
|
3021
|
+
const next = parts.join(import_node_path13.delimiter);
|
|
2919
3022
|
env.PATH = next;
|
|
2920
3023
|
return next;
|
|
2921
3024
|
}
|
|
@@ -2929,7 +3032,7 @@ function enrichPathWithNpmGlobalBin(env = process.env) {
|
|
|
2929
3032
|
stdio: ["ignore", "pipe", "ignore"]
|
|
2930
3033
|
}).trim().split(/\r?\n/).find(Boolean);
|
|
2931
3034
|
if (prefix) {
|
|
2932
|
-
const binDir = process.platform === "win32" ? prefix : (0,
|
|
3035
|
+
const binDir = process.platform === "win32" ? prefix : (0, import_node_path13.join)(prefix, "bin");
|
|
2933
3036
|
prependPathDir(env, binDir);
|
|
2934
3037
|
}
|
|
2935
3038
|
} catch {
|
|
@@ -2957,14 +3060,14 @@ function withExportedPath(command, pathValue) {
|
|
|
2957
3060
|
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
2958
3061
|
return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
|
|
2959
3062
|
}
|
|
2960
|
-
var
|
|
3063
|
+
var import_node_fs12, import_node_child_process2, import_node_os5, import_node_path13, EXTRA_BIN_DIRS;
|
|
2961
3064
|
var init_path = __esm({
|
|
2962
3065
|
"src/agents/path.ts"() {
|
|
2963
3066
|
"use strict";
|
|
2964
|
-
|
|
3067
|
+
import_node_fs12 = require("fs");
|
|
2965
3068
|
import_node_child_process2 = require("child_process");
|
|
2966
|
-
|
|
2967
|
-
|
|
3069
|
+
import_node_os5 = require("os");
|
|
3070
|
+
import_node_path13 = require("path");
|
|
2968
3071
|
EXTRA_BIN_DIRS = [
|
|
2969
3072
|
".local/bin",
|
|
2970
3073
|
".cargo/bin",
|
|
@@ -3089,42 +3192,43 @@ function appendIndexedGitConfig(existing, entries) {
|
|
|
3089
3192
|
return out;
|
|
3090
3193
|
}
|
|
3091
3194
|
function githubAgentGitEnv(existing) {
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
function githubHttpsBearerEnv(existing, token) {
|
|
3095
|
-
const rewrite = githubAgentGitEnv(existing);
|
|
3096
|
-
const header = appendIndexedGitConfig(
|
|
3097
|
-
{ ...existing, ...rewrite },
|
|
3098
|
-
[
|
|
3099
|
-
{
|
|
3100
|
-
key: "http.https://github.com/.extraHeader",
|
|
3101
|
-
value: `AUTHORIZATION: bearer ${token}`
|
|
3102
|
-
}
|
|
3103
|
-
]
|
|
3104
|
-
);
|
|
3105
|
-
return { ...rewrite, ...header };
|
|
3195
|
+
const helpers = githubAgentAuthReady() ? githubCredentialHelperGitConfig() : [{ key: "credential.helper", value: "" }];
|
|
3196
|
+
return appendIndexedGitConfig(existing, [...HTTPS_REWRITE, ...helpers]);
|
|
3106
3197
|
}
|
|
3107
3198
|
function applyGithubGitAuthEnv(existing, opts) {
|
|
3108
3199
|
const out = { ...nonInteractiveGitProcessEnv() };
|
|
3200
|
+
const token = opts.token?.trim() || existing?.GH_TOKEN?.trim() || "" || "";
|
|
3201
|
+
if (token) materializeGithubAgentAuth(token);
|
|
3202
|
+
Object.assign(out, githubGhConfigEnv());
|
|
3109
3203
|
if (opts.mode === "ssh") return out;
|
|
3110
|
-
|
|
3111
|
-
const provided = existingToken ? "" : opts.token?.trim() || "";
|
|
3112
|
-
const token = existingToken || provided;
|
|
3113
|
-
Object.assign(
|
|
3114
|
-
out,
|
|
3115
|
-
token ? githubHttpsBearerEnv(existing, token) : githubAgentGitEnv(existing)
|
|
3116
|
-
);
|
|
3117
|
-
if (provided) out.GH_TOKEN = provided;
|
|
3204
|
+
Object.assign(out, githubAgentGitEnv(existing));
|
|
3118
3205
|
return out;
|
|
3119
3206
|
}
|
|
3207
|
+
function scrubGithubTokensFromChildEnv(env) {
|
|
3208
|
+
for (const key of GITHUB_CHILD_TOKEN_KEYS) {
|
|
3209
|
+
delete env[key];
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
function mergeAgentGitAuthEnv(env, gitEnv) {
|
|
3213
|
+
Object.assign(env, gitEnv);
|
|
3214
|
+
scrubGithubTokensFromChildEnv(env);
|
|
3215
|
+
}
|
|
3120
3216
|
async function resolveGithubAgentToken(mode, cwd) {
|
|
3121
|
-
if (mode ===
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3217
|
+
if (tokenMemo && tokenMemo.mode === mode && Date.now() - tokenMemo.at < TOKEN_TTL_MS) {
|
|
3218
|
+
return tokenMemo.value;
|
|
3219
|
+
}
|
|
3220
|
+
let value = null;
|
|
3221
|
+
if (mode === "token") {
|
|
3222
|
+
value = getGithubPat();
|
|
3223
|
+
} else {
|
|
3224
|
+
try {
|
|
3225
|
+
value = await resolveGhAuthToken(cwd);
|
|
3226
|
+
} catch {
|
|
3227
|
+
value = null;
|
|
3228
|
+
}
|
|
3127
3229
|
}
|
|
3230
|
+
tokenMemo = { mode, value, at: Date.now() };
|
|
3231
|
+
return value;
|
|
3128
3232
|
}
|
|
3129
3233
|
async function resolveAgentGitAuthEnv(existing, opts) {
|
|
3130
3234
|
let mode = "auto";
|
|
@@ -3146,7 +3250,40 @@ async function resolveAgentGitAuthEnv(existing, opts) {
|
|
|
3146
3250
|
}
|
|
3147
3251
|
return applyGithubGitAuthEnv(existing, { mode, token });
|
|
3148
3252
|
}
|
|
3149
|
-
function
|
|
3253
|
+
async function warmGithubAgentAuth(opts) {
|
|
3254
|
+
if (!opts?.force && githubAgentAuthReady()) return;
|
|
3255
|
+
await resolveAgentGitAuthEnv(void 0, opts);
|
|
3256
|
+
}
|
|
3257
|
+
function normalizeWritableRoot(raw) {
|
|
3258
|
+
const trimmed = raw.trim().replace(/\/+$/, "");
|
|
3259
|
+
return trimmed && (0, import_node_path14.isAbsolute)(trimmed) ? trimmed : null;
|
|
3260
|
+
}
|
|
3261
|
+
async function resolveCodexGitWritableRoots(cwd) {
|
|
3262
|
+
const roots = /* @__PURE__ */ new Set();
|
|
3263
|
+
const authDir = normalizeWritableRoot(githubAgentAuthDir());
|
|
3264
|
+
if (authDir) roots.add(authDir);
|
|
3265
|
+
try {
|
|
3266
|
+
const [gitDir, commonDir] = await Promise.all([
|
|
3267
|
+
git(["rev-parse", "--absolute-git-dir"], cwd, { reject: false, timeoutMs: 5e3 }),
|
|
3268
|
+
git(["rev-parse", "--path-format=absolute", "--git-common-dir"], cwd, {
|
|
3269
|
+
reject: false,
|
|
3270
|
+
timeoutMs: 5e3
|
|
3271
|
+
})
|
|
3272
|
+
]);
|
|
3273
|
+
const gitDirPath = gitDir.exitCode === 0 ? normalizeWritableRoot(gitDir.stdout) : null;
|
|
3274
|
+
const commonPath = commonDir.exitCode === 0 ? normalizeWritableRoot(commonDir.stdout) : null;
|
|
3275
|
+
if (gitDirPath) roots.add(gitDirPath);
|
|
3276
|
+
if (commonPath) roots.add(commonPath);
|
|
3277
|
+
} catch {
|
|
3278
|
+
}
|
|
3279
|
+
return [...roots];
|
|
3280
|
+
}
|
|
3281
|
+
function codexSandboxWritableRootsArgs(roots) {
|
|
3282
|
+
const abs = [...new Set(roots.map(normalizeWritableRoot).filter(Boolean))];
|
|
3283
|
+
if (abs.length === 0) return [];
|
|
3284
|
+
return ["-c", `sandbox_workspace_write.writable_roots=${JSON.stringify(abs)}`];
|
|
3285
|
+
}
|
|
3286
|
+
function codexUnattendedGitConfigArgs(sandbox, opts) {
|
|
3150
3287
|
const args = [
|
|
3151
3288
|
"-c",
|
|
3152
3289
|
'shell_environment_policy.inherit="all"',
|
|
@@ -3155,54 +3292,65 @@ function codexUnattendedGitConfigArgs(sandbox) {
|
|
|
3155
3292
|
];
|
|
3156
3293
|
if (sandbox === "workspace-write") {
|
|
3157
3294
|
args.push("-c", "sandbox_workspace_write.network_access=true");
|
|
3295
|
+
args.push(...codexSandboxWritableRootsArgs(opts?.writableRoots ?? []));
|
|
3158
3296
|
}
|
|
3159
3297
|
return args;
|
|
3160
3298
|
}
|
|
3161
3299
|
function formatGitAuthModeDirective(mode) {
|
|
3300
|
+
const shared = [
|
|
3301
|
+
"- `git` and `gh` already authenticate in this process. Do not look for tokens in the environment, paste credentials into commands, or switch remotes to SSH.",
|
|
3302
|
+
"- Do not set GitHub token environment variables, pass `--with-token`, or run `gh auth login` from this turn.",
|
|
3303
|
+
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below.",
|
|
3304
|
+
"- If git/gh fail with auth errors, tell the user to run `gh auth login` on this Mac (or set a PAT in Account \u2192 GitHub). Do not wait for a Keychain dialog."
|
|
3305
|
+
];
|
|
3162
3306
|
switch (mode) {
|
|
3163
3307
|
case "gh":
|
|
3164
3308
|
return [
|
|
3165
3309
|
"Git authentication (Account \u2192 GitHub mode: gh CLI):",
|
|
3166
3310
|
"- This process rewrites `git@github.com:` and `ssh://git@github.com/` to HTTPS.",
|
|
3167
|
-
|
|
3168
|
-
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
3311
|
+
...shared
|
|
3169
3312
|
].join("\n");
|
|
3170
3313
|
case "ssh":
|
|
3171
3314
|
return [
|
|
3172
3315
|
"Git authentication (Account \u2192 GitHub mode: SSH):",
|
|
3173
3316
|
"- Keep SSH remotes (`git@github.com:\u2026`). Do not rewrite them to HTTPS.",
|
|
3174
3317
|
"- SSH is batch-mode: it will not prompt for a Keychain password. If push fails with `Permission denied (publickey)`, tell the user to unlock ssh-agent or switch Account \u2192 GitHub to Auto / gh CLI \u2014 do not rewrite remotes yourself.",
|
|
3175
|
-
"-
|
|
3318
|
+
"- `gh` already authenticates for PRs/API (no token in the environment). Do not set GitHub token environment variables or run `gh auth login` from this turn.",
|
|
3319
|
+
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
3176
3320
|
].join("\n");
|
|
3177
3321
|
case "token":
|
|
3178
3322
|
return [
|
|
3179
3323
|
"Git authentication (Account \u2192 GitHub mode: personal access token):",
|
|
3180
3324
|
"- This process rewrites GitHub SSH remotes to HTTPS.",
|
|
3181
|
-
|
|
3182
|
-
"- Push with `git push -u origin HEAD`. Create/update PRs with `gh` as below."
|
|
3325
|
+
...shared
|
|
3183
3326
|
].join("\n");
|
|
3184
3327
|
case "auto":
|
|
3185
3328
|
default:
|
|
3186
3329
|
return [
|
|
3187
3330
|
"Git authentication (Account \u2192 GitHub mode: auto):",
|
|
3188
|
-
"- This process rewrites GitHub SSH remotes to HTTPS
|
|
3189
|
-
|
|
3190
|
-
"- If HTTPS auth fails, tell the user to run `gh auth login` on this Mac or set Account \u2192 GitHub to a PAT \u2014 do not wait for a Keychain dialog."
|
|
3331
|
+
"- This process rewrites GitHub SSH remotes to HTTPS so git/ssh never prompt the macOS Keychain (required for unattended orchestrator turns).",
|
|
3332
|
+
...shared
|
|
3191
3333
|
].join("\n");
|
|
3192
3334
|
}
|
|
3193
3335
|
}
|
|
3194
|
-
var HTTPS_REWRITE;
|
|
3336
|
+
var import_node_path14, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
|
|
3195
3337
|
var init_git_auth_mode = __esm({
|
|
3196
3338
|
"src/git/git-auth-mode.ts"() {
|
|
3197
3339
|
"use strict";
|
|
3340
|
+
import_node_path14 = require("path");
|
|
3198
3341
|
init_app_settings();
|
|
3342
|
+
init_github_agent_auth();
|
|
3199
3343
|
init_run();
|
|
3200
3344
|
HTTPS_REWRITE = [
|
|
3201
3345
|
{ key: "url.https://github.com/.insteadOf", value: "git@github.com:" },
|
|
3202
|
-
{ key: "url.https://github.com/.insteadOf", value: "ssh://git@github.com/" }
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3346
|
+
{ key: "url.https://github.com/.insteadOf", value: "ssh://git@github.com/" }
|
|
3347
|
+
];
|
|
3348
|
+
TOKEN_TTL_MS = 12 * 60 * 60 * 1e3;
|
|
3349
|
+
tokenMemo = null;
|
|
3350
|
+
GITHUB_CHILD_TOKEN_KEYS = [
|
|
3351
|
+
"GH_TOKEN",
|
|
3352
|
+
"GITHUB_TOKEN",
|
|
3353
|
+
"GH_ENTERPRISE_TOKEN"
|
|
3206
3354
|
];
|
|
3207
3355
|
}
|
|
3208
3356
|
});
|
|
@@ -3535,10 +3683,12 @@ __export(worktree_exports, {
|
|
|
3535
3683
|
getPr: () => getPr,
|
|
3536
3684
|
getPrChecks: () => getPrChecks,
|
|
3537
3685
|
getPrDetails: () => getPrDetails,
|
|
3686
|
+
getPrForHeadBranch: () => getPrForHeadBranch,
|
|
3538
3687
|
getPrMeta: () => getPrMeta,
|
|
3539
3688
|
ghHeadRef: () => ghHeadRef,
|
|
3540
3689
|
ghRepoSelectArgs: () => ghRepoSelectArgs,
|
|
3541
3690
|
githubAgentGitEnv: () => githubAgentGitEnv,
|
|
3691
|
+
isDefaultishSourceRef: () => isDefaultishSourceRef,
|
|
3542
3692
|
isDirty: () => isDirty,
|
|
3543
3693
|
isPlaceholderBranch: () => isPlaceholderBranch,
|
|
3544
3694
|
isSideboardScratchPath: () => isSideboardScratchPath,
|
|
@@ -3556,6 +3706,7 @@ __export(worktree_exports, {
|
|
|
3556
3706
|
resolveDiffBaseRef: () => resolveDiffBaseRef,
|
|
3557
3707
|
resolveGithubRepoSlug: () => resolveGithubRepoSlug,
|
|
3558
3708
|
resolvePrSelector: () => resolvePrSelector,
|
|
3709
|
+
resolvePrSelectors: () => resolvePrSelectors,
|
|
3559
3710
|
resolveRepoRoot: () => resolveRepoRoot,
|
|
3560
3711
|
resolveWorktreeStartPoint: () => resolveWorktreeStartPoint,
|
|
3561
3712
|
slugify: () => slugify,
|
|
@@ -3664,7 +3815,7 @@ async function originGhRepoEnv(cwd, opts) {
|
|
|
3664
3815
|
await ensureGhPreferOrigin(cwd);
|
|
3665
3816
|
const slug = await resolveGithubRepoSlug(cwd);
|
|
3666
3817
|
const mode = opts?.mode ?? getGithubGitAuthMode();
|
|
3667
|
-
const token =
|
|
3818
|
+
const token = await resolveGithubAgentToken(mode, cwd);
|
|
3668
3819
|
return {
|
|
3669
3820
|
...applyGithubGitAuthEnv(opts?.env, { mode, token }),
|
|
3670
3821
|
...slug ? { GH_REPO: slug } : {}
|
|
@@ -3804,13 +3955,78 @@ async function getPr(repoPath, number) {
|
|
|
3804
3955
|
if (exitCode !== 0 || !stdout.trim()) return null;
|
|
3805
3956
|
return JSON.parse(stdout);
|
|
3806
3957
|
}
|
|
3807
|
-
function
|
|
3808
|
-
|
|
3958
|
+
function normalizeGitBranchName(ref) {
|
|
3959
|
+
return ref.trim().replace(/^refs\/heads\//, "").replace(/^origin\//, "");
|
|
3960
|
+
}
|
|
3961
|
+
function isDefaultishSourceRef(ref) {
|
|
3962
|
+
const n = normalizeGitBranchName(ref ?? "").toLowerCase();
|
|
3963
|
+
return !n || n === "head" || n === "default" || n === "main" || n === "master" || n === "develop" || n === "trunk";
|
|
3964
|
+
}
|
|
3965
|
+
function resolvePrSelectors(thread) {
|
|
3966
|
+
const out = [];
|
|
3967
|
+
const push = (value) => {
|
|
3968
|
+
const v = value?.trim();
|
|
3969
|
+
if (!v || out.includes(v)) return;
|
|
3970
|
+
out.push(v);
|
|
3971
|
+
};
|
|
3972
|
+
push(thread.prUrl);
|
|
3809
3973
|
if (thread.sourceType === "pr" && thread.sourceRef?.trim()) {
|
|
3810
|
-
|
|
3974
|
+
push(thread.sourceRef.replace(/^#/, "").trim());
|
|
3975
|
+
}
|
|
3976
|
+
push(thread.branchName);
|
|
3977
|
+
if (thread.sourceType === "branch") {
|
|
3978
|
+
const source = normalizeGitBranchName(thread.sourceRef ?? "");
|
|
3979
|
+
if (source && !isDefaultishSourceRef(source) && source !== thread.branchName?.trim()) {
|
|
3980
|
+
push(source);
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3983
|
+
return out;
|
|
3984
|
+
}
|
|
3985
|
+
function resolvePrSelector(thread) {
|
|
3986
|
+
return resolvePrSelectors(thread)[0] ?? null;
|
|
3987
|
+
}
|
|
3988
|
+
async function getPrForHeadBranch(repoPath, branch) {
|
|
3989
|
+
const head = normalizeGitBranchName(branch);
|
|
3990
|
+
if (!head || isDefaultishSourceRef(head)) return null;
|
|
3991
|
+
const slug = await resolveGithubRepoSlug(repoPath);
|
|
3992
|
+
const viewArgs = [
|
|
3993
|
+
"pr",
|
|
3994
|
+
"view",
|
|
3995
|
+
head,
|
|
3996
|
+
"--json",
|
|
3997
|
+
"number,title,headRefName,url,isCrossRepository"
|
|
3998
|
+
];
|
|
3999
|
+
if (slug) viewArgs.push("--repo", slug);
|
|
4000
|
+
const viewed = await gh(viewArgs, repoPath, { reject: false });
|
|
4001
|
+
if (viewed.exitCode === 0 && viewed.stdout.trim()) {
|
|
4002
|
+
try {
|
|
4003
|
+
return JSON.parse(viewed.stdout);
|
|
4004
|
+
} catch {
|
|
4005
|
+
return null;
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
const listHead = slug ? ghHeadRef(slug, head) : head;
|
|
4009
|
+
const listArgs = [
|
|
4010
|
+
"pr",
|
|
4011
|
+
"list",
|
|
4012
|
+
"--head",
|
|
4013
|
+
listHead,
|
|
4014
|
+
"--json",
|
|
4015
|
+
"number,title,headRefName,url,isCrossRepository",
|
|
4016
|
+
"--limit",
|
|
4017
|
+
"1",
|
|
4018
|
+
"--state",
|
|
4019
|
+
"open"
|
|
4020
|
+
];
|
|
4021
|
+
if (slug) listArgs.push("--repo", slug);
|
|
4022
|
+
const listed = await gh(listArgs, repoPath, { reject: false });
|
|
4023
|
+
if (listed.exitCode !== 0 || !listed.stdout.trim()) return null;
|
|
4024
|
+
try {
|
|
4025
|
+
const rows = JSON.parse(listed.stdout);
|
|
4026
|
+
return rows[0] ?? null;
|
|
4027
|
+
} catch {
|
|
4028
|
+
return null;
|
|
3811
4029
|
}
|
|
3812
|
-
if (thread.branchName?.trim()) return thread.branchName.trim();
|
|
3813
|
-
return null;
|
|
3814
4030
|
}
|
|
3815
4031
|
function normalizeGhTime(value) {
|
|
3816
4032
|
if (typeof value !== "string" || !value.trim()) return null;
|
|
@@ -4136,7 +4352,7 @@ async function fetchPrHead(repoPath, number, localBranch) {
|
|
|
4136
4352
|
const label = opts?.ghAuth ? `${remote} (gh auth)` : remote;
|
|
4137
4353
|
const gitOpts = { reject: false };
|
|
4138
4354
|
if (opts?.ghAuth) {
|
|
4139
|
-
const token = await
|
|
4355
|
+
const token = await resolveGithubAgentToken(getGithubGitAuthMode(), repoPath);
|
|
4140
4356
|
if (!token) {
|
|
4141
4357
|
errors.push(`${label}: gh auth token unavailable`);
|
|
4142
4358
|
return false;
|
|
@@ -4187,7 +4403,7 @@ async function fetchPrHead(repoPath, number, localBranch) {
|
|
|
4187
4403
|
const ensureOid = async (remote, opts) => {
|
|
4188
4404
|
const gitOpts = { reject: false };
|
|
4189
4405
|
if (opts?.ghAuth) {
|
|
4190
|
-
const token = await
|
|
4406
|
+
const token = await resolveGithubAgentToken(getGithubGitAuthMode(), repoPath);
|
|
4191
4407
|
if (!token) return false;
|
|
4192
4408
|
gitOpts.env = { GIT_TERMINAL_PROMPT: "0" };
|
|
4193
4409
|
gitOpts.config = {
|
|
@@ -4255,8 +4471,8 @@ function isLocalPrFetchBranch(ref) {
|
|
|
4255
4471
|
}
|
|
4256
4472
|
async function createThreadWorktree(opts) {
|
|
4257
4473
|
let branchName = `thread/${opts.slug}`;
|
|
4258
|
-
const worktreePath = (0,
|
|
4259
|
-
if ((0,
|
|
4474
|
+
const worktreePath = (0, import_node_path15.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
4475
|
+
if ((0, import_node_fs13.existsSync)(worktreePath)) {
|
|
4260
4476
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
4261
4477
|
}
|
|
4262
4478
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -4325,8 +4541,8 @@ ${add.stdout}`;
|
|
|
4325
4541
|
async function createExistingBranchWorktree(opts) {
|
|
4326
4542
|
const branchName = opts.branchName.trim();
|
|
4327
4543
|
if (!branchName) throw new Error("branch name required");
|
|
4328
|
-
const worktreePath = (0,
|
|
4329
|
-
if ((0,
|
|
4544
|
+
const worktreePath = (0, import_node_path15.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
4545
|
+
if ((0, import_node_fs13.existsSync)(worktreePath)) {
|
|
4330
4546
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
4331
4547
|
}
|
|
4332
4548
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -4437,7 +4653,7 @@ async function pushBranch(worktreePath, branchName) {
|
|
|
4437
4653
|
if (ssh.exitCode === 0) return;
|
|
4438
4654
|
const sshErr = (ssh.stderr || ssh.stdout).trim();
|
|
4439
4655
|
const slug = await resolveGithubRepoSlug(worktreePath);
|
|
4440
|
-
const token = await
|
|
4656
|
+
const token = await resolveGithubAgentToken(getGithubGitAuthMode(), worktreePath);
|
|
4441
4657
|
if (!slug || !token) {
|
|
4442
4658
|
throw new Error(
|
|
4443
4659
|
sshErr || `git push origin ${branchName} failed` + (!token ? " (no SSH agent and gh auth token unavailable \u2014 run: gh auth login)" : "")
|
|
@@ -4614,10 +4830,10 @@ function sameRepoPath(a, b) {
|
|
|
4614
4830
|
return normalizeWorktreePath(a) === normalizeWorktreePath(b);
|
|
4615
4831
|
}
|
|
4616
4832
|
function listLocalThreadBranchSlugs(repoPath) {
|
|
4617
|
-
const refsDir = (0,
|
|
4618
|
-
if (!(0,
|
|
4833
|
+
const refsDir = (0, import_node_path15.join)(repoPath, ".git", "refs", "heads", "thread");
|
|
4834
|
+
if (!(0, import_node_fs13.existsSync)(refsDir)) return [];
|
|
4619
4835
|
try {
|
|
4620
|
-
return (0,
|
|
4836
|
+
return (0, import_node_fs13.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
|
|
4621
4837
|
} catch {
|
|
4622
4838
|
return [];
|
|
4623
4839
|
}
|
|
@@ -4625,8 +4841,8 @@ function listLocalThreadBranchSlugs(repoPath) {
|
|
|
4625
4841
|
function collectTakenTeamSlugs(repoPath) {
|
|
4626
4842
|
const taken = /* @__PURE__ */ new Set();
|
|
4627
4843
|
const root = worktreesRoot(repoPath);
|
|
4628
|
-
if ((0,
|
|
4629
|
-
for (const entry of (0,
|
|
4844
|
+
if ((0, import_node_fs13.existsSync)(root)) {
|
|
4845
|
+
for (const entry of (0, import_node_fs13.readdirSync)(root, { withFileTypes: true })) {
|
|
4630
4846
|
if (entry.isDirectory() && entry.name !== ".DS_Store") {
|
|
4631
4847
|
taken.add(normalizeTakenSlug(entry.name));
|
|
4632
4848
|
}
|
|
@@ -4647,18 +4863,18 @@ function allocateTeamSlug(repoPath) {
|
|
|
4647
4863
|
const taken = collectTakenTeamSlugs(repoPath);
|
|
4648
4864
|
for (let attempt = 0; attempt < 32; attempt++) {
|
|
4649
4865
|
const team = allocateTeamName(taken);
|
|
4650
|
-
const path = (0,
|
|
4651
|
-
if (!(0,
|
|
4866
|
+
const path = (0, import_node_path15.join)(worktreesRoot(repoPath), team.slug);
|
|
4867
|
+
if (!(0, import_node_fs13.existsSync)(path)) return team;
|
|
4652
4868
|
taken.add(team.slug);
|
|
4653
4869
|
}
|
|
4654
4870
|
throw new Error("No available soccer team worktree directories left");
|
|
4655
4871
|
}
|
|
4656
|
-
var
|
|
4872
|
+
var import_node_fs13, import_node_path15;
|
|
4657
4873
|
var init_worktree = __esm({
|
|
4658
4874
|
"src/git/worktree.ts"() {
|
|
4659
4875
|
"use strict";
|
|
4660
|
-
|
|
4661
|
-
|
|
4876
|
+
import_node_fs13 = require("fs");
|
|
4877
|
+
import_node_path15 = require("path");
|
|
4662
4878
|
init_paths();
|
|
4663
4879
|
init_thread_store();
|
|
4664
4880
|
init_teams();
|
|
@@ -4800,7 +5016,7 @@ function coordinatorTurnReminder(opts) {
|
|
|
4800
5016
|
function ensureGlobalCoordinatorCwd(opts) {
|
|
4801
5017
|
const dir = globalAgentCwd();
|
|
4802
5018
|
try {
|
|
4803
|
-
(0,
|
|
5019
|
+
(0, import_node_fs14.mkdirSync)(dir, { recursive: true });
|
|
4804
5020
|
} catch {
|
|
4805
5021
|
return dir;
|
|
4806
5022
|
}
|
|
@@ -4808,7 +5024,7 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
4808
5024
|
let orchId = opts?.orchestratorThreadId?.trim() || "";
|
|
4809
5025
|
if (!orchId) {
|
|
4810
5026
|
try {
|
|
4811
|
-
const existing = (0,
|
|
5027
|
+
const existing = (0, import_node_fs14.readFileSync)((0, import_node_path16.join)(dir, "AGENTS.md"), "utf8");
|
|
4812
5028
|
const m = existing.match(
|
|
4813
5029
|
/YOUR orchestration thread id is `([0-9a-f-]{36})`/i
|
|
4814
5030
|
);
|
|
@@ -4850,9 +5066,9 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
4850
5066
|
"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."
|
|
4851
5067
|
].join("\n");
|
|
4852
5068
|
try {
|
|
4853
|
-
(0,
|
|
5069
|
+
(0, import_node_fs14.writeFileSync)((0, import_node_path16.join)(dir, "CLAUDE.md"), `${body}
|
|
4854
5070
|
`, "utf8");
|
|
4855
|
-
(0,
|
|
5071
|
+
(0, import_node_fs14.writeFileSync)((0, import_node_path16.join)(dir, "AGENTS.md"), `${body}
|
|
4856
5072
|
`, "utf8");
|
|
4857
5073
|
} catch {
|
|
4858
5074
|
}
|
|
@@ -4884,12 +5100,12 @@ function coordinatorSystemPrompt(opts) {
|
|
|
4884
5100
|
formatWorkspaceInventory(opts.workspaces)
|
|
4885
5101
|
].join("\n");
|
|
4886
5102
|
}
|
|
4887
|
-
var
|
|
5103
|
+
var import_node_fs14, import_node_path16, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
|
|
4888
5104
|
var init_coordinator_prompt = __esm({
|
|
4889
5105
|
"src/orchestrator/coordinator-prompt.ts"() {
|
|
4890
5106
|
"use strict";
|
|
4891
|
-
|
|
4892
|
-
|
|
5107
|
+
import_node_fs14 = require("fs");
|
|
5108
|
+
import_node_path16 = require("path");
|
|
4893
5109
|
init_worktree();
|
|
4894
5110
|
init_app_settings();
|
|
4895
5111
|
init_paths();
|
|
@@ -4905,7 +5121,7 @@ var init_coordinator_prompt = __esm({
|
|
|
4905
5121
|
"- get_pr_stack / open_pr_stack_layers / add_stack_layer / create_pr_stack \u2014 GitHub stacked PRs (`gh stack`); one worktree per layer",
|
|
4906
5122
|
"- list_models \u2014 only when you need a specific model (rare); otherwise omit model so Account defaults apply",
|
|
4907
5123
|
"- list_threads / get_thread \u2014 fleet status (what is going on)",
|
|
4908
|
-
"- ask_user \u2014 multiple-choice
|
|
5124
|
+
"- ask_user \u2014 composer multiple-choice only when blocked on a concrete choice (approach fork, which API). Never for hellos, check-ins, or invented \u201Cwhat should we do?\u201D menus \u2014 reply in chat. Explain options first, description on every option, then wait.",
|
|
4909
5125
|
"- set_caffeinate \u2014 keep this Mac awake across turns (macOS caffeinate). Turn on for Slack / away-from-keyboard work. Turn OFF when the user says they are done, wrapping up, going to sleep, or no longer need the machine awake. Closing this chat also releases it.",
|
|
4910
5126
|
"Workspaces:",
|
|
4911
5127
|
"- add_workspace / remove_workspace \u2014 register or unregister a git repo",
|
|
@@ -5187,32 +5403,32 @@ var init_global_workspace = __esm({
|
|
|
5187
5403
|
|
|
5188
5404
|
// src/brightsy/config.ts
|
|
5189
5405
|
function brightsyConfigPath() {
|
|
5190
|
-
return (0,
|
|
5406
|
+
return (0, import_node_path17.join)((0, import_node_os6.homedir)(), ".brightsy", "config.json");
|
|
5191
5407
|
}
|
|
5192
5408
|
function loadBrightsyConfig() {
|
|
5193
5409
|
const path = brightsyConfigPath();
|
|
5194
|
-
if (!(0,
|
|
5410
|
+
if (!(0, import_node_fs15.existsSync)(path)) {
|
|
5195
5411
|
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
5196
5412
|
}
|
|
5197
|
-
const raw = JSON.parse((0,
|
|
5413
|
+
const raw = JSON.parse((0, import_node_fs15.readFileSync)(path, "utf8"));
|
|
5198
5414
|
if (!raw.access_token || !raw.account_id) {
|
|
5199
5415
|
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
5200
5416
|
}
|
|
5201
5417
|
return raw;
|
|
5202
5418
|
}
|
|
5203
5419
|
function saveBrightsyConfig(cfg) {
|
|
5204
|
-
(0,
|
|
5420
|
+
(0, import_node_fs15.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
5205
5421
|
`, {
|
|
5206
5422
|
mode: 384
|
|
5207
5423
|
});
|
|
5208
5424
|
}
|
|
5209
|
-
var
|
|
5425
|
+
var import_node_fs15, import_node_os6, import_node_path17;
|
|
5210
5426
|
var init_config = __esm({
|
|
5211
5427
|
"src/brightsy/config.ts"() {
|
|
5212
5428
|
"use strict";
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5429
|
+
import_node_fs15 = require("fs");
|
|
5430
|
+
import_node_os6 = require("os");
|
|
5431
|
+
import_node_path17 = require("path");
|
|
5216
5432
|
}
|
|
5217
5433
|
});
|
|
5218
5434
|
|
|
@@ -5227,22 +5443,22 @@ var init_accounts = __esm({
|
|
|
5227
5443
|
|
|
5228
5444
|
// src/brightsy/connected-teams.ts
|
|
5229
5445
|
function storePath4() {
|
|
5230
|
-
return (0,
|
|
5446
|
+
return (0, import_node_path18.join)(appDataDir(), "brightsy-teams.json");
|
|
5231
5447
|
}
|
|
5232
5448
|
function readStore4() {
|
|
5233
5449
|
const path = storePath4();
|
|
5234
|
-
if (!(0,
|
|
5450
|
+
if (!(0, import_node_fs16.existsSync)(path)) return [];
|
|
5235
5451
|
try {
|
|
5236
|
-
const parsed = JSON.parse((0,
|
|
5452
|
+
const parsed = JSON.parse((0, import_node_fs16.readFileSync)(path, "utf8"));
|
|
5237
5453
|
return Array.isArray(parsed.teams) ? parsed.teams : [];
|
|
5238
5454
|
} catch {
|
|
5239
5455
|
return [];
|
|
5240
5456
|
}
|
|
5241
5457
|
}
|
|
5242
5458
|
function writeStore2(teams) {
|
|
5243
|
-
(0,
|
|
5459
|
+
(0, import_node_fs16.mkdirSync)(appDataDir(), { recursive: true });
|
|
5244
5460
|
const path = storePath4();
|
|
5245
|
-
(0,
|
|
5461
|
+
(0, import_node_fs16.writeFileSync)(path, `${JSON.stringify({ teams }, null, 2)}
|
|
5246
5462
|
`, {
|
|
5247
5463
|
mode: 384
|
|
5248
5464
|
});
|
|
@@ -5354,12 +5570,12 @@ function brightsyMcpServerName(slug) {
|
|
|
5354
5570
|
const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
|
|
5355
5571
|
return `brightsy_${cleaned || "team"}`;
|
|
5356
5572
|
}
|
|
5357
|
-
var
|
|
5573
|
+
var import_node_fs16, import_node_path18;
|
|
5358
5574
|
var init_connected_teams = __esm({
|
|
5359
5575
|
"src/brightsy/connected-teams.ts"() {
|
|
5360
5576
|
"use strict";
|
|
5361
|
-
|
|
5362
|
-
|
|
5577
|
+
import_node_fs16 = require("fs");
|
|
5578
|
+
import_node_path18 = require("path");
|
|
5363
5579
|
init_paths();
|
|
5364
5580
|
init_accounts();
|
|
5365
5581
|
init_config();
|
|
@@ -5686,11 +5902,11 @@ async function syncCliForTarget(accountId) {
|
|
|
5686
5902
|
}
|
|
5687
5903
|
applyConnectedTeamToCli(team);
|
|
5688
5904
|
}
|
|
5689
|
-
var
|
|
5905
|
+
var import_node_fs17, brightsyAdapter;
|
|
5690
5906
|
var init_brightsy = __esm({
|
|
5691
5907
|
"src/agents/brightsy.ts"() {
|
|
5692
5908
|
"use strict";
|
|
5693
|
-
|
|
5909
|
+
import_node_fs17 = require("fs");
|
|
5694
5910
|
init_run();
|
|
5695
5911
|
init_connected_teams();
|
|
5696
5912
|
init_config();
|
|
@@ -5705,7 +5921,7 @@ var init_brightsy = __esm({
|
|
|
5705
5921
|
async detect() {
|
|
5706
5922
|
const brightsy = resolveAgentExecutable("brightsy");
|
|
5707
5923
|
if (brightsy !== "brightsy") {
|
|
5708
|
-
if (!(0,
|
|
5924
|
+
if (!(0, import_node_fs17.existsSync)(brightsy)) {
|
|
5709
5925
|
return {
|
|
5710
5926
|
agent: "brightsy",
|
|
5711
5927
|
installed: false,
|
|
@@ -5833,13 +6049,38 @@ var init_profile = __esm({
|
|
|
5833
6049
|
|
|
5834
6050
|
// src/agents/node-launch.ts
|
|
5835
6051
|
function isAsarPath(filePath) {
|
|
6052
|
+
if (/\.asar\.unpacked([/\\]|$)/.test(filePath)) return false;
|
|
5836
6053
|
return /\.asar([/\\]|$)/.test(filePath);
|
|
5837
6054
|
}
|
|
6055
|
+
function unpackedAsarPath(filePath) {
|
|
6056
|
+
if (!isAsarPath(filePath)) return null;
|
|
6057
|
+
const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
|
|
6058
|
+
if (unpacked === filePath) return null;
|
|
6059
|
+
return (0, import_node_fs18.existsSync)(unpacked) ? unpacked : null;
|
|
6060
|
+
}
|
|
6061
|
+
function nodeReadableScriptPath(scriptPath) {
|
|
6062
|
+
return unpackedAsarPath(scriptPath) ?? scriptPath;
|
|
6063
|
+
}
|
|
6064
|
+
async function findSystemNode() {
|
|
6065
|
+
const whichNode = await run("which", ["node"], { reject: false });
|
|
6066
|
+
const fromWhich = whichNode.exitCode === 0 && whichNode.stdout.trim() ? whichNode.stdout.trim() : "";
|
|
6067
|
+
if (fromWhich && !isElectronLikeCommand(fromWhich)) return fromWhich;
|
|
6068
|
+
const fallbacks = [
|
|
6069
|
+
...WELL_KNOWN_NODE_BINS,
|
|
6070
|
+
(0, import_node_path19.join)((0, import_node_os7.homedir)(), ".local/share/fnm/aliases/default/bin/node"),
|
|
6071
|
+
(0, import_node_path19.join)((0, import_node_os7.homedir)(), ".nvm/current/bin/node")
|
|
6072
|
+
];
|
|
6073
|
+
for (const bin of fallbacks) {
|
|
6074
|
+
if ((0, import_node_fs18.existsSync)(bin) && !isElectronLikeCommand(bin)) return bin;
|
|
6075
|
+
}
|
|
6076
|
+
return null;
|
|
6077
|
+
}
|
|
5838
6078
|
function applyNodeLaunch(launch, args) {
|
|
6079
|
+
const readableArgs = args.map(nodeReadableScriptPath);
|
|
5839
6080
|
if (!launch.env.ELECTRON_RUN_AS_NODE) {
|
|
5840
|
-
return { file: launch.file, args, env: launch.env };
|
|
6081
|
+
return { file: launch.file, args: readableArgs, env: launch.env };
|
|
5841
6082
|
}
|
|
5842
|
-
const wrapped = wrapElectronAsNodeLaunch(launch.file,
|
|
6083
|
+
const wrapped = wrapElectronAsNodeLaunch(launch.file, readableArgs);
|
|
5843
6084
|
if (process.platform === "win32") {
|
|
5844
6085
|
return { file: wrapped.file, args: wrapped.args, env: launch.env };
|
|
5845
6086
|
}
|
|
@@ -5848,27 +6089,73 @@ function applyNodeLaunch(launch, args) {
|
|
|
5848
6089
|
return { file: wrapped.file, args: wrapped.args, env };
|
|
5849
6090
|
}
|
|
5850
6091
|
async function resolveNodeLaunch(scriptPath) {
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
const whichNode = await run("which", ["node"], { reject: false });
|
|
5858
|
-
const nodeBin = whichNode.exitCode === 0 && whichNode.stdout.trim() ? whichNode.stdout.trim() : null;
|
|
5859
|
-
if (nodeBin) {
|
|
5860
|
-
return { file: nodeBin, env: {} };
|
|
6092
|
+
const script = nodeReadableScriptPath(scriptPath);
|
|
6093
|
+
if (!isAsarPath(script)) {
|
|
6094
|
+
const nodeBin = await findSystemNode();
|
|
6095
|
+
if (nodeBin) {
|
|
6096
|
+
return { file: nodeBin, env: {} };
|
|
6097
|
+
}
|
|
5861
6098
|
}
|
|
5862
6099
|
return {
|
|
5863
6100
|
file: process.execPath,
|
|
5864
6101
|
env: { ELECTRON_RUN_AS_NODE: "1" }
|
|
5865
6102
|
};
|
|
5866
6103
|
}
|
|
6104
|
+
var import_node_fs18, import_node_os7, import_node_path19, WELL_KNOWN_NODE_BINS;
|
|
5867
6105
|
var init_node_launch = __esm({
|
|
5868
6106
|
"src/agents/node-launch.ts"() {
|
|
5869
6107
|
"use strict";
|
|
6108
|
+
import_node_fs18 = require("fs");
|
|
6109
|
+
import_node_os7 = require("os");
|
|
6110
|
+
import_node_path19 = require("path");
|
|
5870
6111
|
init_nested_electron_env();
|
|
5871
6112
|
init_run();
|
|
6113
|
+
WELL_KNOWN_NODE_BINS = [
|
|
6114
|
+
"/opt/homebrew/bin/node",
|
|
6115
|
+
"/usr/local/bin/node"
|
|
6116
|
+
];
|
|
6117
|
+
}
|
|
6118
|
+
});
|
|
6119
|
+
|
|
6120
|
+
// src/agents/packaged-runtime.ts
|
|
6121
|
+
function electronResourcesPath() {
|
|
6122
|
+
const resources = process.resourcesPath;
|
|
6123
|
+
if (typeof resources !== "string" || !resources) return null;
|
|
6124
|
+
return resources;
|
|
6125
|
+
}
|
|
6126
|
+
function packagedCursorRuntimeDir() {
|
|
6127
|
+
const resources = electronResourcesPath();
|
|
6128
|
+
if (!resources) return null;
|
|
6129
|
+
const dir = (0, import_node_path20.join)(resources, "cursor-runtime");
|
|
6130
|
+
if (!(0, import_node_fs19.existsSync)((0, import_node_path20.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
|
|
6131
|
+
return dir;
|
|
6132
|
+
}
|
|
6133
|
+
function packagedCursorRunnerPath() {
|
|
6134
|
+
const dir = packagedCursorRuntimeDir();
|
|
6135
|
+
return dir ? (0, import_node_path20.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
|
|
6136
|
+
}
|
|
6137
|
+
function packagedMcpDir() {
|
|
6138
|
+
const resources = electronResourcesPath();
|
|
6139
|
+
if (!resources) return null;
|
|
6140
|
+
const dir = (0, import_node_path20.join)(resources, "sideboard-mcp");
|
|
6141
|
+
if (!(0, import_node_fs19.existsSync)((0, import_node_path20.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
|
|
6142
|
+
return dir;
|
|
6143
|
+
}
|
|
6144
|
+
function packagedMcpStdioPath() {
|
|
6145
|
+
const dir = packagedMcpDir();
|
|
6146
|
+
return dir ? (0, import_node_path20.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
|
|
6147
|
+
}
|
|
6148
|
+
function packagedCursorRipgrepCandidate(platformPkg, binName) {
|
|
6149
|
+
const dir = packagedCursorRuntimeDir();
|
|
6150
|
+
if (!dir) return null;
|
|
6151
|
+
return (0, import_node_path20.join)(dir, "node_modules", platformPkg, "bin", binName);
|
|
6152
|
+
}
|
|
6153
|
+
var import_node_fs19, import_node_path20;
|
|
6154
|
+
var init_packaged_runtime = __esm({
|
|
6155
|
+
"src/agents/packaged-runtime.ts"() {
|
|
6156
|
+
"use strict";
|
|
6157
|
+
import_node_fs19 = require("fs");
|
|
6158
|
+
import_node_path20 = require("path");
|
|
5872
6159
|
}
|
|
5873
6160
|
});
|
|
5874
6161
|
|
|
@@ -5955,35 +6242,37 @@ function corePackageDir() {
|
|
|
5955
6242
|
try {
|
|
5956
6243
|
const url = import_meta.url;
|
|
5957
6244
|
if (typeof url === "string" && url.length > 0) {
|
|
5958
|
-
return (0,
|
|
6245
|
+
return (0, import_node_path21.dirname)((0, import_node_url.fileURLToPath)(url));
|
|
5959
6246
|
}
|
|
5960
6247
|
} catch {
|
|
5961
6248
|
}
|
|
5962
6249
|
try {
|
|
5963
|
-
const req = (0, import_node_module.createRequire)((0,
|
|
5964
|
-
return (0,
|
|
6250
|
+
const req = (0, import_node_module.createRequire)((0, import_node_path21.join)(process.cwd(), "package.json"));
|
|
6251
|
+
return (0, import_node_path21.dirname)(req.resolve("@sideboard-ai/core"));
|
|
5965
6252
|
} catch {
|
|
5966
6253
|
return process.cwd();
|
|
5967
6254
|
}
|
|
5968
6255
|
}
|
|
5969
6256
|
function findSideboardMcpJsEntry() {
|
|
5970
6257
|
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
5971
|
-
if (override && (0,
|
|
6258
|
+
if (override && (0, import_node_fs20.existsSync)(override)) return override;
|
|
6259
|
+
const packaged = packagedMcpStdioPath();
|
|
6260
|
+
if (packaged) return packaged;
|
|
5972
6261
|
let dir = corePackageDir();
|
|
5973
6262
|
for (let i = 0; i < 10; i++) {
|
|
5974
6263
|
const candidates = [
|
|
5975
|
-
(0,
|
|
5976
|
-
(0,
|
|
5977
|
-
(0,
|
|
5978
|
-
(0,
|
|
5979
|
-
(0,
|
|
5980
|
-
(0,
|
|
5981
|
-
(0,
|
|
6264
|
+
(0, import_node_path21.join)(dir, "mcp/run-stdio.js"),
|
|
6265
|
+
(0, import_node_path21.join)(dir, "mcp/run-stdio.cjs"),
|
|
6266
|
+
(0, import_node_path21.join)(dir, "dist/mcp/run-stdio.js"),
|
|
6267
|
+
(0, import_node_path21.join)(dir, "dist/mcp/run-stdio.cjs"),
|
|
6268
|
+
(0, import_node_path21.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
|
|
6269
|
+
(0, import_node_path21.join)(dir, "packages/cli/dist/index.js"),
|
|
6270
|
+
(0, import_node_path21.join)(dir, "cli/dist/index.js")
|
|
5982
6271
|
];
|
|
5983
6272
|
for (const p of candidates) {
|
|
5984
|
-
if ((0,
|
|
6273
|
+
if ((0, import_node_fs20.existsSync)(p) && !isAsarPath(p)) return p;
|
|
5985
6274
|
}
|
|
5986
|
-
const parent = (0,
|
|
6275
|
+
const parent = (0, import_node_path21.dirname)(dir);
|
|
5987
6276
|
if (parent === dir) break;
|
|
5988
6277
|
dir = parent;
|
|
5989
6278
|
}
|
|
@@ -5995,12 +6284,14 @@ async function resolveSideboardMcpServer() {
|
|
|
5995
6284
|
const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
|
|
5996
6285
|
const scriptArgs = isCli ? [entry, "mcp"] : [entry];
|
|
5997
6286
|
const launch = applyNodeLaunch(await resolveNodeLaunch(entry), scriptArgs);
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6287
|
+
if (launch.file !== "/bin/sh" && !isElectronLikeCommand(launch.file)) {
|
|
6288
|
+
return {
|
|
6289
|
+
name: "sideboard",
|
|
6290
|
+
command: launch.file,
|
|
6291
|
+
args: launch.args,
|
|
6292
|
+
...Object.keys(launch.env).length > 0 ? { env: launch.env } : {}
|
|
6293
|
+
};
|
|
6294
|
+
}
|
|
6004
6295
|
}
|
|
6005
6296
|
const which = await run("which", ["sideboard"], { reject: false });
|
|
6006
6297
|
if (which.exitCode === 0 && which.stdout.trim()) {
|
|
@@ -6023,7 +6314,10 @@ async function buildInjectedMcpServers(opts) {
|
|
|
6023
6314
|
sideboard.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID = orchId;
|
|
6024
6315
|
}
|
|
6025
6316
|
try {
|
|
6026
|
-
|
|
6317
|
+
mergeAgentGitAuthEnv(
|
|
6318
|
+
sideboard.env,
|
|
6319
|
+
await resolveAgentGitAuthEnv(sideboard.env)
|
|
6320
|
+
);
|
|
6027
6321
|
} catch {
|
|
6028
6322
|
}
|
|
6029
6323
|
servers.push(sideboard);
|
|
@@ -6045,9 +6339,6 @@ async function buildInjectedMcpServers(opts) {
|
|
|
6045
6339
|
}
|
|
6046
6340
|
return servers;
|
|
6047
6341
|
}
|
|
6048
|
-
function shSingleQuote(value) {
|
|
6049
|
-
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
6050
|
-
}
|
|
6051
6342
|
function cursorSafeMcpLaunch(command, args) {
|
|
6052
6343
|
if (process.platform === "win32") {
|
|
6053
6344
|
return args && args.length > 0 ? { command, args } : { command };
|
|
@@ -6055,31 +6346,13 @@ function cursorSafeMcpLaunch(command, args) {
|
|
|
6055
6346
|
const unwrapped = unwrapStrippedElectronLaunch(command, args);
|
|
6056
6347
|
const file = unwrapped?.file ?? command;
|
|
6057
6348
|
const fileArgs = unwrapped?.args ?? args ?? [];
|
|
6058
|
-
|
|
6059
|
-
return fileArgs.length > 0 ? { command: file, args: fileArgs } : { command: file };
|
|
6060
|
-
}
|
|
6061
|
-
const dir = (0, import_node_path17.join)(appDataDir(), "mcp-launch");
|
|
6062
|
-
(0, import_node_fs17.mkdirSync)(dir, { recursive: true });
|
|
6063
|
-
const wrap = (0, import_node_path17.join)(dir, "cursor-electron-as-node.sh");
|
|
6064
|
-
const execLine = [file, ...fileArgs].map(shSingleQuote).join(" ");
|
|
6065
|
-
(0, import_node_fs17.writeFileSync)(
|
|
6066
|
-
wrap,
|
|
6067
|
-
[
|
|
6068
|
-
"#!/bin/sh",
|
|
6069
|
-
"vars=`printenv | awk -F= '/^(ELECTRON_|CHROME_)/{print $1}'`",
|
|
6070
|
-
'[ -n "$vars" ] && unset $vars',
|
|
6071
|
-
"export ELECTRON_RUN_AS_NODE=1",
|
|
6072
|
-
`exec ${execLine} "$@"`,
|
|
6073
|
-
""
|
|
6074
|
-
].join("\n"),
|
|
6075
|
-
{ mode: 493 }
|
|
6076
|
-
);
|
|
6077
|
-
return { command: wrap };
|
|
6349
|
+
return fileArgs.length > 0 ? { command: file, args: fileArgs } : { command: file };
|
|
6078
6350
|
}
|
|
6079
6351
|
function mcpSpawnEnv(env) {
|
|
6080
6352
|
if (!env) return void 0;
|
|
6081
6353
|
const out = { ...env };
|
|
6082
6354
|
delete out.ELECTRON_RUN_AS_NODE;
|
|
6355
|
+
delete out.ELECTRON_RUN_AS_NODE;
|
|
6083
6356
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
6084
6357
|
}
|
|
6085
6358
|
function toCursorMcpServers(servers) {
|
|
@@ -6088,6 +6361,7 @@ function toCursorMcpServers(servers) {
|
|
|
6088
6361
|
const env = mcpSpawnEnv(s.env);
|
|
6089
6362
|
const launch = cursorSafeMcpLaunch(s.command, s.args);
|
|
6090
6363
|
out[s.name] = {
|
|
6364
|
+
type: "stdio",
|
|
6091
6365
|
command: launch.command,
|
|
6092
6366
|
...launch.args && launch.args.length > 0 ? { args: launch.args } : {},
|
|
6093
6367
|
...env ? { env } : {}
|
|
@@ -6139,19 +6413,19 @@ function writeMcpServersConfig(servers) {
|
|
|
6139
6413
|
...env ? { env } : {}
|
|
6140
6414
|
};
|
|
6141
6415
|
}
|
|
6142
|
-
const dir = (0,
|
|
6143
|
-
const cfgPath = (0,
|
|
6144
|
-
(0,
|
|
6416
|
+
const dir = (0, import_node_fs20.mkdtempSync)((0, import_node_path21.join)((0, import_node_os8.tmpdir)(), "sideboard-mcp-"));
|
|
6417
|
+
const cfgPath = (0, import_node_path21.join)(dir, "mcp.json");
|
|
6418
|
+
(0, import_node_fs20.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
|
|
6145
6419
|
return cfgPath;
|
|
6146
6420
|
}
|
|
6147
|
-
var
|
|
6421
|
+
var import_node_fs20, import_node_module, import_node_os8, import_node_path21, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
|
|
6148
6422
|
var init_injected_mcp = __esm({
|
|
6149
6423
|
"src/agents/injected-mcp.ts"() {
|
|
6150
6424
|
"use strict";
|
|
6151
|
-
|
|
6425
|
+
import_node_fs20 = require("fs");
|
|
6152
6426
|
import_node_module = require("module");
|
|
6153
|
-
|
|
6154
|
-
|
|
6427
|
+
import_node_os8 = require("os");
|
|
6428
|
+
import_node_path21 = require("path");
|
|
6155
6429
|
import_node_url = require("url");
|
|
6156
6430
|
init_run();
|
|
6157
6431
|
init_config();
|
|
@@ -6160,6 +6434,7 @@ var init_injected_mcp = __esm({
|
|
|
6160
6434
|
init_app_settings();
|
|
6161
6435
|
init_paths();
|
|
6162
6436
|
init_node_launch();
|
|
6437
|
+
init_packaged_runtime();
|
|
6163
6438
|
init_nested_electron_env();
|
|
6164
6439
|
init_git_auth_mode();
|
|
6165
6440
|
import_meta = {};
|
|
@@ -6229,7 +6504,7 @@ var PLAN_MODE_INSTRUCTION;
|
|
|
6229
6504
|
var init_types = __esm({
|
|
6230
6505
|
"src/agents/types.ts"() {
|
|
6231
6506
|
"use strict";
|
|
6232
|
-
PLAN_MODE_INSTRUCTION = "Plan mode is active and must remain active until the user turns Plan mode off in the UI (or Approves / Hands off the plan). Analyze the codebase, search and read files as needed, and produce or refine a clear implementation plan. Do not modify, create, or delete any project files except via Sideboard MCP present_plan (writes .context/attachments/plan.md). When you need a clarifying decision (approach forks, auth choice, scope): (1) first write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it) \u2014 do not leave the user staring at bare labels; (2) then call Sideboard MCP ask_user with the same options, including a description on every option. Sideboard shows questions in the composer and mirrors them in chat. After ask_user, wait for the user's next message with their answers before finalizing the plan. When the plan is ready for approval: (1) call present_plan with the full markdown plan (title + content) so Sideboard saves .context/attachments/plan.md and shows it in chat for Approve / Hand off / Copy; (2) Claude should also call ExitPlanMode after present_plan. Do not skip present_plan \u2014 the plan must be a markdown file, not only chat prose.";
|
|
6507
|
+
PLAN_MODE_INSTRUCTION = "Plan mode is active and must remain active until the user turns Plan mode off in the UI (or Approves / Hands off the plan). Analyze the codebase, search and read files as needed, and produce or refine a clear implementation plan. Do not modify, create, or delete any project files except via Sideboard MCP present_plan (writes .context/attachments/plan.md). When you need a clarifying decision (approach forks, auth choice, scope) \u2014 not greetings, check-ins, or an invented task menu: (1) first write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it) \u2014 do not leave the user staring at bare labels; (2) then call Sideboard MCP ask_user with the same options, including a description on every option. If one option is the obvious default, proceed without asking. Sideboard shows questions in the composer and mirrors them in chat. After ask_user, wait for the user's next message with their answers before finalizing the plan. When the plan is ready for approval: (1) call present_plan with the full markdown plan (title + content) so Sideboard saves .context/attachments/plan.md and shows it in chat for Approve / Hand off / Copy; (2) Claude should also call ExitPlanMode after present_plan. Do not skip present_plan \u2014 the plan must be a markdown file, not only chat prose.";
|
|
6233
6508
|
}
|
|
6234
6509
|
});
|
|
6235
6510
|
|
|
@@ -6339,11 +6614,11 @@ function parseIssuesJson(raw) {
|
|
|
6339
6614
|
}
|
|
6340
6615
|
return [];
|
|
6341
6616
|
}
|
|
6342
|
-
var
|
|
6617
|
+
var import_node_fs21, BASE_ALLOWED_TOOLS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
|
|
6343
6618
|
var init_claude = __esm({
|
|
6344
6619
|
"src/agents/claude.ts"() {
|
|
6345
6620
|
"use strict";
|
|
6346
|
-
|
|
6621
|
+
import_node_fs21 = require("fs");
|
|
6347
6622
|
init_run();
|
|
6348
6623
|
init_app_settings();
|
|
6349
6624
|
init_claude_mcp();
|
|
@@ -6372,7 +6647,7 @@ var init_claude = __esm({
|
|
|
6372
6647
|
async detect() {
|
|
6373
6648
|
const claude = resolveClaudeExecutable();
|
|
6374
6649
|
if (claude !== "claude") {
|
|
6375
|
-
if (!(0,
|
|
6650
|
+
if (!(0, import_node_fs21.existsSync)(claude)) {
|
|
6376
6651
|
return {
|
|
6377
6652
|
agent: "claude",
|
|
6378
6653
|
installed: false,
|
|
@@ -6609,7 +6884,7 @@ async function listCodexModels() {
|
|
|
6609
6884
|
if (codex === "codex") {
|
|
6610
6885
|
const which = await run("which", ["codex"], { reject: false });
|
|
6611
6886
|
if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
|
|
6612
|
-
} else if (!(0,
|
|
6887
|
+
} else if (!(0, import_node_fs22.existsSync)(codex)) {
|
|
6613
6888
|
return FALLBACK_CODEX_MODELS;
|
|
6614
6889
|
}
|
|
6615
6890
|
const listed = await run(codex, ["debug", "models"], { reject: false });
|
|
@@ -6644,12 +6919,12 @@ function usageFromCodex(usage) {
|
|
|
6644
6919
|
}
|
|
6645
6920
|
function codexConfigHasNetworkAccess() {
|
|
6646
6921
|
const candidates = [
|
|
6647
|
-
(0,
|
|
6648
|
-
(0,
|
|
6922
|
+
(0, import_node_path22.join)((0, import_node_os9.homedir)(), ".codex", "config.toml"),
|
|
6923
|
+
(0, import_node_path22.join)((0, import_node_os9.homedir)(), ".config", "codex", "config.toml")
|
|
6649
6924
|
];
|
|
6650
6925
|
for (const path of candidates) {
|
|
6651
|
-
if (!(0,
|
|
6652
|
-
const text3 = (0,
|
|
6926
|
+
if (!(0, import_node_fs22.existsSync)(path)) continue;
|
|
6927
|
+
const text3 = (0, import_node_fs22.readFileSync)(path, "utf8");
|
|
6653
6928
|
if (/network_access\s*=\s*true/.test(text3)) return true;
|
|
6654
6929
|
}
|
|
6655
6930
|
return false;
|
|
@@ -6681,21 +6956,21 @@ function asRecord(value) {
|
|
|
6681
6956
|
return void 0;
|
|
6682
6957
|
}
|
|
6683
6958
|
function codexLooksAuthenticated() {
|
|
6684
|
-
const authPath = (0,
|
|
6685
|
-
if (!(0,
|
|
6959
|
+
const authPath = (0, import_node_path22.join)((0, import_node_os9.homedir)(), ".codex", "auth.json");
|
|
6960
|
+
if (!(0, import_node_fs22.existsSync)(authPath)) return false;
|
|
6686
6961
|
try {
|
|
6687
|
-
return (0,
|
|
6962
|
+
return (0, import_node_fs22.statSync)(authPath).size > 2;
|
|
6688
6963
|
} catch {
|
|
6689
6964
|
return false;
|
|
6690
6965
|
}
|
|
6691
6966
|
}
|
|
6692
|
-
var
|
|
6967
|
+
var import_node_fs22, import_node_os9, import_node_path22, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
|
|
6693
6968
|
var init_codex = __esm({
|
|
6694
6969
|
"src/agents/codex.ts"() {
|
|
6695
6970
|
"use strict";
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6971
|
+
import_node_fs22 = require("fs");
|
|
6972
|
+
import_node_os9 = require("os");
|
|
6973
|
+
import_node_path22 = require("path");
|
|
6699
6974
|
init_run();
|
|
6700
6975
|
init_app_settings();
|
|
6701
6976
|
init_global_workspace();
|
|
@@ -6720,7 +6995,7 @@ var init_codex = __esm({
|
|
|
6720
6995
|
async detect() {
|
|
6721
6996
|
const codex = resolveAgentExecutable("codex");
|
|
6722
6997
|
if (codex !== "codex") {
|
|
6723
|
-
if (!(0,
|
|
6998
|
+
if (!(0, import_node_fs22.existsSync)(codex)) {
|
|
6724
6999
|
return {
|
|
6725
7000
|
agent: "codex",
|
|
6726
7001
|
installed: false,
|
|
@@ -6793,8 +7068,13 @@ var init_codex = __esm({
|
|
|
6793
7068
|
// `codex exec` rejects `--ask-for-approval` (global-only on newer CLIs).
|
|
6794
7069
|
"-c",
|
|
6795
7070
|
'approval_policy="never"',
|
|
6796
|
-
// Seatbelt cannot use the login Keychain;
|
|
6797
|
-
|
|
7071
|
+
// Seatbelt cannot use the login Keychain; inherit GH_CONFIG_DIR / GIT_CONFIG_*.
|
|
7072
|
+
// Default policy also strips *TOKEN*. Linked worktrees need the main
|
|
7073
|
+
// repo `.git` (+ `.git/worktrees/<name>`) as writable_roots so git commit
|
|
7074
|
+
// can create index.lock.
|
|
7075
|
+
...codexUnattendedGitConfigArgs(mode.codexSandbox, {
|
|
7076
|
+
writableRoots: mode.codexSandbox === "workspace-write" ? await resolveCodexGitWritableRoots(thread.worktreePath) : []
|
|
7077
|
+
}),
|
|
6798
7078
|
...model ? ["--model", model] : [],
|
|
6799
7079
|
...mcpOverrides
|
|
6800
7080
|
];
|
|
@@ -7115,6 +7395,74 @@ var init_cursor_events = __esm({
|
|
|
7115
7395
|
}
|
|
7116
7396
|
});
|
|
7117
7397
|
|
|
7398
|
+
// src/agents/cursor-ripgrep.ts
|
|
7399
|
+
function rgBinaryName() {
|
|
7400
|
+
return process.platform === "win32" ? "rg.exe" : "rg";
|
|
7401
|
+
}
|
|
7402
|
+
function platformRipgrepPackage() {
|
|
7403
|
+
return `@cursor/sdk-${process.platform}-${process.arch}`;
|
|
7404
|
+
}
|
|
7405
|
+
function usableRipgrepPath(candidate) {
|
|
7406
|
+
const raw = candidate?.trim();
|
|
7407
|
+
if (!raw || !(0, import_node_path23.isAbsolute)(raw)) return null;
|
|
7408
|
+
const readable = nodeReadableScriptPath(raw);
|
|
7409
|
+
if (!(0, import_node_fs23.existsSync)(readable) || isAsarPath(readable)) return null;
|
|
7410
|
+
return readable;
|
|
7411
|
+
}
|
|
7412
|
+
function walkForBundledRipgrep(startFile) {
|
|
7413
|
+
if (!startFile) return null;
|
|
7414
|
+
const pkg = platformRipgrepPackage();
|
|
7415
|
+
const name = rgBinaryName();
|
|
7416
|
+
let dir = (0, import_node_path23.dirname)((0, import_node_path23.resolve)(startFile));
|
|
7417
|
+
const root = (0, import_node_path23.parse)(dir).root;
|
|
7418
|
+
while (dir !== root) {
|
|
7419
|
+
const hit = usableRipgrepPath((0, import_node_path23.join)(dir, "node_modules", pkg, "bin", name));
|
|
7420
|
+
if (hit) return hit;
|
|
7421
|
+
const next = (0, import_node_path23.dirname)(dir);
|
|
7422
|
+
if (next === dir) break;
|
|
7423
|
+
dir = next;
|
|
7424
|
+
}
|
|
7425
|
+
return null;
|
|
7426
|
+
}
|
|
7427
|
+
function requireResolveBundledRipgrep(fromFile) {
|
|
7428
|
+
try {
|
|
7429
|
+
const req = (0, import_node_module2.createRequire)(fromFile);
|
|
7430
|
+
const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
|
|
7431
|
+
return usableRipgrepPath((0, import_node_path23.join)((0, import_node_path23.dirname)(pkgJson), "bin", rgBinaryName()));
|
|
7432
|
+
} catch {
|
|
7433
|
+
return null;
|
|
7434
|
+
}
|
|
7435
|
+
}
|
|
7436
|
+
function resolveCursorRipgrepPath(opts) {
|
|
7437
|
+
const env = opts?.env ?? process.env;
|
|
7438
|
+
const fromEnv = usableRipgrepPath(env[RIPGREP_ENV]);
|
|
7439
|
+
if (fromEnv) return fromEnv;
|
|
7440
|
+
const fromPackaged = usableRipgrepPath(
|
|
7441
|
+
packagedCursorRipgrepCandidate(platformRipgrepPackage(), rgBinaryName())
|
|
7442
|
+
);
|
|
7443
|
+
if (fromPackaged) return fromPackaged;
|
|
7444
|
+
const start = opts?.startFile?.trim() || process.argv[1] || (0, import_node_url2.fileURLToPath)(import_meta2.url);
|
|
7445
|
+
return walkForBundledRipgrep(start) ?? requireResolveBundledRipgrep(start);
|
|
7446
|
+
}
|
|
7447
|
+
function cursorRipgrepEnv(opts) {
|
|
7448
|
+
const path = resolveCursorRipgrepPath(opts);
|
|
7449
|
+
return path ? { [RIPGREP_ENV]: path } : {};
|
|
7450
|
+
}
|
|
7451
|
+
var import_node_fs23, import_node_module2, import_node_path23, import_node_url2, import_meta2, RIPGREP_ENV;
|
|
7452
|
+
var init_cursor_ripgrep = __esm({
|
|
7453
|
+
"src/agents/cursor-ripgrep.ts"() {
|
|
7454
|
+
"use strict";
|
|
7455
|
+
import_node_fs23 = require("fs");
|
|
7456
|
+
import_node_module2 = require("module");
|
|
7457
|
+
import_node_path23 = require("path");
|
|
7458
|
+
import_node_url2 = require("url");
|
|
7459
|
+
init_node_launch();
|
|
7460
|
+
init_packaged_runtime();
|
|
7461
|
+
import_meta2 = {};
|
|
7462
|
+
RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
|
|
7463
|
+
}
|
|
7464
|
+
});
|
|
7465
|
+
|
|
7118
7466
|
// src/agents/cursor.ts
|
|
7119
7467
|
function resolveCursorApiKey() {
|
|
7120
7468
|
const fromEnv = (process.env.CURSOR_API_KEY || "").trim();
|
|
@@ -7154,51 +7502,55 @@ function entryDir() {
|
|
|
7154
7502
|
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
7155
7503
|
if (cjsDir) return cjsDir;
|
|
7156
7504
|
try {
|
|
7157
|
-
return (0,
|
|
7505
|
+
return (0, import_node_path24.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
|
|
7158
7506
|
} catch {
|
|
7159
7507
|
try {
|
|
7160
|
-
const req = (0,
|
|
7161
|
-
return (0,
|
|
7508
|
+
const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
|
|
7509
|
+
return (0, import_node_path24.dirname)(req.resolve("@sideboard-ai/core"));
|
|
7162
7510
|
} catch {
|
|
7163
7511
|
return process.cwd();
|
|
7164
7512
|
}
|
|
7165
7513
|
}
|
|
7166
7514
|
}
|
|
7167
7515
|
function cursorRunnerPath() {
|
|
7516
|
+
const packaged = packagedCursorRunnerPath();
|
|
7517
|
+
if (packaged) return packaged;
|
|
7168
7518
|
const root = entryDir();
|
|
7169
7519
|
const candidates = [
|
|
7170
|
-
(0,
|
|
7171
|
-
(0,
|
|
7520
|
+
(0, import_node_path24.join)(root, "agents", "cursor-runner.js"),
|
|
7521
|
+
(0, import_node_path24.join)(root, "agents", "cursor-runner.cjs"),
|
|
7172
7522
|
// If somehow resolved from package root instead of dist/
|
|
7173
|
-
(0,
|
|
7174
|
-
(0,
|
|
7523
|
+
(0, import_node_path24.join)(root, "dist", "agents", "cursor-runner.js"),
|
|
7524
|
+
(0, import_node_path24.join)(root, "dist", "agents", "cursor-runner.cjs"),
|
|
7175
7525
|
// Source tree (dev): packages/core/src/agents/cursor-runner.ts
|
|
7176
|
-
(0,
|
|
7177
|
-
(0,
|
|
7526
|
+
(0, import_node_path24.join)(root, "cursor-runner.ts"),
|
|
7527
|
+
(0, import_node_path24.join)(root, "src", "agents", "cursor-runner.ts")
|
|
7178
7528
|
];
|
|
7179
7529
|
for (const candidate of candidates) {
|
|
7180
|
-
if ((0,
|
|
7530
|
+
if ((0, import_node_fs24.existsSync)(candidate)) return candidate;
|
|
7181
7531
|
}
|
|
7182
7532
|
return candidates[0];
|
|
7183
7533
|
}
|
|
7184
|
-
var
|
|
7534
|
+
var import_node_fs24, import_node_module3, import_node_path24, import_node_url3, import_sdk, import_meta3, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
|
|
7185
7535
|
var init_cursor = __esm({
|
|
7186
7536
|
"src/agents/cursor.ts"() {
|
|
7187
7537
|
"use strict";
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7538
|
+
import_node_fs24 = require("fs");
|
|
7539
|
+
import_node_module3 = require("module");
|
|
7540
|
+
import_node_path24 = require("path");
|
|
7541
|
+
import_node_url3 = require("url");
|
|
7192
7542
|
import_sdk = require("@cursor/sdk");
|
|
7193
7543
|
init_run();
|
|
7194
7544
|
init_app_settings();
|
|
7195
7545
|
init_global_workspace();
|
|
7196
7546
|
init_cursor_events();
|
|
7197
7547
|
init_injected_mcp();
|
|
7548
|
+
init_cursor_ripgrep();
|
|
7198
7549
|
init_node_launch();
|
|
7550
|
+
init_packaged_runtime();
|
|
7199
7551
|
init_turn_input();
|
|
7200
7552
|
init_cursor_events();
|
|
7201
|
-
|
|
7553
|
+
import_meta3 = {};
|
|
7202
7554
|
FALLBACK_CURSOR_MODELS = [
|
|
7203
7555
|
{ id: "default", displayName: "Auto" },
|
|
7204
7556
|
{ id: "composer-2.5", displayName: "Composer 2.5" },
|
|
@@ -7265,6 +7617,7 @@ var init_cursor = __esm({
|
|
|
7265
7617
|
stdin: JSON.stringify(req),
|
|
7266
7618
|
env: {
|
|
7267
7619
|
...launch.env,
|
|
7620
|
+
...cursorRipgrepEnv({ startFile: runner }),
|
|
7268
7621
|
...apiKey ? { CURSOR_API_KEY: apiKey } : {}
|
|
7269
7622
|
}
|
|
7270
7623
|
};
|
|
@@ -7316,7 +7669,7 @@ async function listOpencodeModels() {
|
|
|
7316
7669
|
if (opencode === "opencode") {
|
|
7317
7670
|
const which = await run("which", ["opencode"], { reject: false });
|
|
7318
7671
|
if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
|
|
7319
|
-
} else if (!(0,
|
|
7672
|
+
} else if (!(0, import_node_fs25.existsSync)(opencode)) {
|
|
7320
7673
|
return FALLBACK_OPENCODE_MODELS;
|
|
7321
7674
|
}
|
|
7322
7675
|
const listed = await run(opencode, ["models"], { reject: false });
|
|
@@ -7346,11 +7699,11 @@ function usageFromOpencode(tokens) {
|
|
|
7346
7699
|
cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
|
|
7347
7700
|
};
|
|
7348
7701
|
}
|
|
7349
|
-
var
|
|
7702
|
+
var import_node_fs25, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
|
|
7350
7703
|
var init_opencode = __esm({
|
|
7351
7704
|
"src/agents/opencode.ts"() {
|
|
7352
7705
|
"use strict";
|
|
7353
|
-
|
|
7706
|
+
import_node_fs25 = require("fs");
|
|
7354
7707
|
init_run();
|
|
7355
7708
|
init_app_settings();
|
|
7356
7709
|
init_global_workspace();
|
|
@@ -7376,7 +7729,7 @@ var init_opencode = __esm({
|
|
|
7376
7729
|
async detect() {
|
|
7377
7730
|
const opencode = resolveAgentExecutable("opencode");
|
|
7378
7731
|
if (opencode !== "opencode") {
|
|
7379
|
-
if (!(0,
|
|
7732
|
+
if (!(0, import_node_fs25.existsSync)(opencode)) {
|
|
7380
7733
|
return {
|
|
7381
7734
|
agent: "opencode",
|
|
7382
7735
|
installed: false,
|
|
@@ -8113,38 +8466,38 @@ __export(workspaces_exports, {
|
|
|
8113
8466
|
syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
|
|
8114
8467
|
});
|
|
8115
8468
|
function workspacesFile() {
|
|
8116
|
-
return (0,
|
|
8469
|
+
return (0, import_node_path27.join)(appDataDir(), "workspaces.json");
|
|
8117
8470
|
}
|
|
8118
8471
|
function removedWorkspacesFile() {
|
|
8119
|
-
return (0,
|
|
8472
|
+
return (0, import_node_path27.join)(appDataDir(), "removed-workspaces.json");
|
|
8120
8473
|
}
|
|
8121
8474
|
function readAll() {
|
|
8122
8475
|
const path = workspacesFile();
|
|
8123
|
-
if (!(0,
|
|
8476
|
+
if (!(0, import_node_fs28.existsSync)(path)) return [];
|
|
8124
8477
|
try {
|
|
8125
|
-
const raw = JSON.parse((0,
|
|
8478
|
+
const raw = JSON.parse((0, import_node_fs28.readFileSync)(path, "utf8"));
|
|
8126
8479
|
return Array.isArray(raw) ? raw : [];
|
|
8127
8480
|
} catch {
|
|
8128
8481
|
return [];
|
|
8129
8482
|
}
|
|
8130
8483
|
}
|
|
8131
8484
|
function writeAll(list) {
|
|
8132
|
-
(0,
|
|
8133
|
-
(0,
|
|
8485
|
+
(0, import_node_fs28.mkdirSync)(appDataDir(), { recursive: true });
|
|
8486
|
+
(0, import_node_fs28.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
|
|
8134
8487
|
}
|
|
8135
8488
|
function readRemoved() {
|
|
8136
8489
|
const path = removedWorkspacesFile();
|
|
8137
|
-
if (!(0,
|
|
8490
|
+
if (!(0, import_node_fs28.existsSync)(path)) return /* @__PURE__ */ new Set();
|
|
8138
8491
|
try {
|
|
8139
|
-
const raw = JSON.parse((0,
|
|
8492
|
+
const raw = JSON.parse((0, import_node_fs28.readFileSync)(path, "utf8"));
|
|
8140
8493
|
return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
|
|
8141
8494
|
} catch {
|
|
8142
8495
|
return /* @__PURE__ */ new Set();
|
|
8143
8496
|
}
|
|
8144
8497
|
}
|
|
8145
8498
|
function writeRemoved(paths) {
|
|
8146
|
-
(0,
|
|
8147
|
-
(0,
|
|
8499
|
+
(0, import_node_fs28.mkdirSync)(appDataDir(), { recursive: true });
|
|
8500
|
+
(0, import_node_fs28.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
|
|
8148
8501
|
}
|
|
8149
8502
|
function rememberRemoved(repoPath) {
|
|
8150
8503
|
const next = readRemoved();
|
|
@@ -8167,7 +8520,7 @@ function listWorkspaces() {
|
|
|
8167
8520
|
async function addWorkspace(repoPath) {
|
|
8168
8521
|
const root = await resolveRepoRoot(repoPath);
|
|
8169
8522
|
if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
|
|
8170
|
-
if (!(0,
|
|
8523
|
+
if (!(0, import_node_fs28.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
|
|
8171
8524
|
forgetRemoved(root);
|
|
8172
8525
|
await ensureGhPreferOrigin(root);
|
|
8173
8526
|
const current = readAll();
|
|
@@ -8175,7 +8528,7 @@ async function addWorkspace(repoPath) {
|
|
|
8175
8528
|
if (existing) return existing;
|
|
8176
8529
|
const next = {
|
|
8177
8530
|
path: root,
|
|
8178
|
-
name: (0,
|
|
8531
|
+
name: (0, import_node_path27.basename)(root),
|
|
8179
8532
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8180
8533
|
};
|
|
8181
8534
|
writeAll([...current, next]);
|
|
@@ -8197,10 +8550,10 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
8197
8550
|
if (!path || path === "/" || isGlobalRepoPath(path) || byPath.has(path) || removed.has(path)) {
|
|
8198
8551
|
continue;
|
|
8199
8552
|
}
|
|
8200
|
-
if (!(0,
|
|
8553
|
+
if (!(0, import_node_fs28.existsSync)(path)) continue;
|
|
8201
8554
|
const ws = {
|
|
8202
8555
|
path,
|
|
8203
|
-
name: (0,
|
|
8556
|
+
name: (0, import_node_path27.basename)(path),
|
|
8204
8557
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8205
8558
|
};
|
|
8206
8559
|
byPath.set(path, ws);
|
|
@@ -8210,12 +8563,12 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
8210
8563
|
if (dirty) writeAll(next);
|
|
8211
8564
|
return next.sort((a, b) => a.name.localeCompare(b.name));
|
|
8212
8565
|
}
|
|
8213
|
-
var
|
|
8566
|
+
var import_node_fs28, import_node_path27;
|
|
8214
8567
|
var init_workspaces = __esm({
|
|
8215
8568
|
"src/store/workspaces.ts"() {
|
|
8216
8569
|
"use strict";
|
|
8217
|
-
|
|
8218
|
-
|
|
8570
|
+
import_node_fs28 = require("fs");
|
|
8571
|
+
import_node_path27 = require("path");
|
|
8219
8572
|
init_paths();
|
|
8220
8573
|
init_global_workspace();
|
|
8221
8574
|
init_worktree();
|
|
@@ -8292,40 +8645,40 @@ __export(plan_file_exports, {
|
|
|
8292
8645
|
writePlanFile: () => writePlanFile
|
|
8293
8646
|
});
|
|
8294
8647
|
function ensureAttachmentsGitignore2(worktreePath) {
|
|
8295
|
-
const gitignoreAbs = (0,
|
|
8296
|
-
if ((0,
|
|
8297
|
-
(0,
|
|
8298
|
-
(0,
|
|
8648
|
+
const gitignoreAbs = (0, import_node_path35.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
8649
|
+
if ((0, import_node_fs38.existsSync)(gitignoreAbs)) return;
|
|
8650
|
+
(0, import_node_fs38.mkdirSync)((0, import_node_path35.dirname)(gitignoreAbs), { recursive: true });
|
|
8651
|
+
(0, import_node_fs38.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
8299
8652
|
}
|
|
8300
8653
|
function planFileAbs(worktreePath) {
|
|
8301
|
-
return (0,
|
|
8654
|
+
return (0, import_node_path35.join)(worktreePath, PLAN_FILE_REL);
|
|
8302
8655
|
}
|
|
8303
8656
|
function readTextIfPresent2(abs) {
|
|
8304
|
-
if (!(0,
|
|
8657
|
+
if (!(0, import_node_fs38.existsSync)(abs)) return null;
|
|
8305
8658
|
try {
|
|
8306
|
-
const content = (0,
|
|
8659
|
+
const content = (0, import_node_fs38.readFileSync)(abs, "utf8");
|
|
8307
8660
|
return content.trim() ? content : null;
|
|
8308
8661
|
} catch {
|
|
8309
8662
|
return null;
|
|
8310
8663
|
}
|
|
8311
8664
|
}
|
|
8312
8665
|
function readPlanFile(worktreePath) {
|
|
8313
|
-
return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0,
|
|
8666
|
+
return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path35.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path35.join)(worktreePath, LEGACY_PLAN_FILE_REL));
|
|
8314
8667
|
}
|
|
8315
8668
|
function writePlanFile(worktreePath, content) {
|
|
8316
8669
|
ensureAttachmentsGitignore2(worktreePath);
|
|
8317
8670
|
const abs = planFileAbs(worktreePath);
|
|
8318
|
-
(0,
|
|
8671
|
+
(0, import_node_fs38.mkdirSync)((0, import_node_path35.dirname)(abs), { recursive: true });
|
|
8319
8672
|
const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
|
|
8320
|
-
(0,
|
|
8673
|
+
(0, import_node_fs38.writeFileSync)(abs, body, "utf8");
|
|
8321
8674
|
return PLAN_FILE_REL;
|
|
8322
8675
|
}
|
|
8323
|
-
var
|
|
8676
|
+
var import_node_fs38, import_node_path35;
|
|
8324
8677
|
var init_plan_file = __esm({
|
|
8325
8678
|
"src/plan/plan-file.ts"() {
|
|
8326
8679
|
"use strict";
|
|
8327
|
-
|
|
8328
|
-
|
|
8680
|
+
import_node_fs38 = require("fs");
|
|
8681
|
+
import_node_path35 = require("path");
|
|
8329
8682
|
init_workspace_scratch();
|
|
8330
8683
|
init_plan_present();
|
|
8331
8684
|
init_plan_present();
|
|
@@ -8346,7 +8699,7 @@ function setCaffeinateHoldHooks(next) {
|
|
|
8346
8699
|
hooks = next;
|
|
8347
8700
|
}
|
|
8348
8701
|
function caffeinateHoldPath() {
|
|
8349
|
-
return (0,
|
|
8702
|
+
return (0, import_node_path36.join)(appDataDir(), "caffeinate-hold.json");
|
|
8350
8703
|
}
|
|
8351
8704
|
function processAlive(pid) {
|
|
8352
8705
|
if (hooks.processAlive) return hooks.processAlive(pid);
|
|
@@ -8380,9 +8733,9 @@ function uniqueIds(ids) {
|
|
|
8380
8733
|
}
|
|
8381
8734
|
function readHold() {
|
|
8382
8735
|
const path = caffeinateHoldPath();
|
|
8383
|
-
if (!(0,
|
|
8736
|
+
if (!(0, import_node_fs39.existsSync)(path)) return null;
|
|
8384
8737
|
try {
|
|
8385
|
-
const parsed = JSON.parse((0,
|
|
8738
|
+
const parsed = JSON.parse((0, import_node_fs39.readFileSync)(path, "utf8"));
|
|
8386
8739
|
if (typeof parsed?.pid === "number" && parsed.pid > 0) {
|
|
8387
8740
|
return {
|
|
8388
8741
|
pid: parsed.pid,
|
|
@@ -8404,7 +8757,7 @@ function writeHold(pid, threadIds) {
|
|
|
8404
8757
|
}
|
|
8405
8758
|
function clearHold() {
|
|
8406
8759
|
try {
|
|
8407
|
-
(0,
|
|
8760
|
+
(0, import_node_fs39.unlinkSync)(caffeinateHoldPath());
|
|
8408
8761
|
} catch {
|
|
8409
8762
|
}
|
|
8410
8763
|
}
|
|
@@ -8489,13 +8842,13 @@ function releaseCaffeinateHoldForThread(threadId) {
|
|
|
8489
8842
|
}
|
|
8490
8843
|
return setCaffeinateHold(false, { threadId: id });
|
|
8491
8844
|
}
|
|
8492
|
-
var import_node_child_process4,
|
|
8845
|
+
var import_node_child_process4, import_node_fs39, import_node_path36, hooks;
|
|
8493
8846
|
var init_caffeinate_hold = __esm({
|
|
8494
8847
|
"src/store/caffeinate-hold.ts"() {
|
|
8495
8848
|
"use strict";
|
|
8496
8849
|
import_node_child_process4 = require("child_process");
|
|
8497
|
-
|
|
8498
|
-
|
|
8850
|
+
import_node_fs39 = require("fs");
|
|
8851
|
+
import_node_path36 = require("path");
|
|
8499
8852
|
init_paths();
|
|
8500
8853
|
init_private_file();
|
|
8501
8854
|
hooks = {};
|
|
@@ -8510,10 +8863,10 @@ __export(cursor_recover_exports, {
|
|
|
8510
8863
|
function recoverFinishedCursorRun(opts) {
|
|
8511
8864
|
const agentId = opts.agentId.trim();
|
|
8512
8865
|
if (!agentId) return null;
|
|
8513
|
-
const runsPath = (0,
|
|
8514
|
-
if (!(0,
|
|
8866
|
+
const runsPath = (0, import_node_path37.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
|
|
8867
|
+
if (!(0, import_node_fs40.existsSync)(runsPath)) return null;
|
|
8515
8868
|
try {
|
|
8516
|
-
const lines = (0,
|
|
8869
|
+
const lines = (0, import_node_fs40.readFileSync)(runsPath, "utf8").split("\n");
|
|
8517
8870
|
let best = null;
|
|
8518
8871
|
for (const line of lines) {
|
|
8519
8872
|
const trimmed = line.trim();
|
|
@@ -8539,12 +8892,12 @@ function recoverFinishedCursorRun(opts) {
|
|
|
8539
8892
|
return null;
|
|
8540
8893
|
}
|
|
8541
8894
|
}
|
|
8542
|
-
var
|
|
8895
|
+
var import_node_fs40, import_node_path37;
|
|
8543
8896
|
var init_cursor_recover = __esm({
|
|
8544
8897
|
"src/agents/cursor-recover.ts"() {
|
|
8545
8898
|
"use strict";
|
|
8546
|
-
|
|
8547
|
-
|
|
8899
|
+
import_node_fs40 = require("fs");
|
|
8900
|
+
import_node_path37 = require("path");
|
|
8548
8901
|
init_paths();
|
|
8549
8902
|
}
|
|
8550
8903
|
});
|
|
@@ -8556,7 +8909,7 @@ init_nested_electron_env();
|
|
|
8556
8909
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
8557
8910
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
8558
8911
|
var import_zod3 = require("zod");
|
|
8559
|
-
var
|
|
8912
|
+
var import_node_path38 = require("path");
|
|
8560
8913
|
|
|
8561
8914
|
// src/orchestrator/orchestrator.ts
|
|
8562
8915
|
var import_node_events = require("events");
|
|
@@ -9067,7 +9420,7 @@ async function refreshSlackReplyBadges(opts) {
|
|
|
9067
9420
|
}
|
|
9068
9421
|
|
|
9069
9422
|
// src/orchestrator/orchestrator.ts
|
|
9070
|
-
var
|
|
9423
|
+
var import_node_fs41 = require("fs");
|
|
9071
9424
|
init_error_detail();
|
|
9072
9425
|
|
|
9073
9426
|
// src/agents/spawn.ts
|
|
@@ -9384,10 +9737,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
9384
9737
|
const env = childEnvWithAppSettings(cmd.env);
|
|
9385
9738
|
try {
|
|
9386
9739
|
if (isOrchestratorThread(thread)) {
|
|
9387
|
-
|
|
9740
|
+
mergeAgentGitAuthEnv(env, await resolveAgentGitAuthEnv(env));
|
|
9388
9741
|
} else {
|
|
9389
|
-
|
|
9390
|
-
Object.assign(env, originEnv);
|
|
9742
|
+
mergeAgentGitAuthEnv(env, await originGhRepoEnv(thread.worktreePath, { env }));
|
|
9391
9743
|
}
|
|
9392
9744
|
} catch (err) {
|
|
9393
9745
|
const detail = err instanceof Error ? err.message : String(err);
|
|
@@ -9600,9 +9952,9 @@ function shouldAutoArchiveOnPrMerge(opts) {
|
|
|
9600
9952
|
}
|
|
9601
9953
|
|
|
9602
9954
|
// src/hook/conductor.ts
|
|
9603
|
-
var
|
|
9955
|
+
var import_node_fs26 = require("fs");
|
|
9604
9956
|
var import_node_net = require("net");
|
|
9605
|
-
var
|
|
9957
|
+
var import_node_path25 = require("path");
|
|
9606
9958
|
var import_execa4 = require("execa");
|
|
9607
9959
|
var import_node_readline3 = require("readline");
|
|
9608
9960
|
init_settings();
|
|
@@ -9617,9 +9969,9 @@ function matchSimpleGlob(pattern, name) {
|
|
|
9617
9969
|
return new RegExp(`^${escaped}$`).test(name);
|
|
9618
9970
|
}
|
|
9619
9971
|
function readWorktreeInclude(repoPath) {
|
|
9620
|
-
const path = (0,
|
|
9621
|
-
if (!(0,
|
|
9622
|
-
return (0,
|
|
9972
|
+
const path = (0, import_node_path25.join)(repoPath, ".worktreeinclude");
|
|
9973
|
+
if (!(0, import_node_fs26.existsSync)(path)) return [];
|
|
9974
|
+
return (0, import_node_fs26.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
9623
9975
|
}
|
|
9624
9976
|
function resolveFilesToCopy(repoPath) {
|
|
9625
9977
|
const fromInclude = readWorktreeInclude(repoPath);
|
|
@@ -9629,10 +9981,10 @@ function resolveFilesToCopy(repoPath) {
|
|
|
9629
9981
|
if (settings?.fileIncludeGlobs?.length) {
|
|
9630
9982
|
const matched = [];
|
|
9631
9983
|
try {
|
|
9632
|
-
for (const entry of (0,
|
|
9984
|
+
for (const entry of (0, import_node_fs26.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
9633
9985
|
if (!entry.isFile()) continue;
|
|
9634
9986
|
for (const glob of settings.fileIncludeGlobs) {
|
|
9635
|
-
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0,
|
|
9987
|
+
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path25.basename)(glob), entry.name)) {
|
|
9636
9988
|
matched.push(entry.name);
|
|
9637
9989
|
break;
|
|
9638
9990
|
}
|
|
@@ -9644,7 +9996,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
9644
9996
|
}
|
|
9645
9997
|
const defaults = [];
|
|
9646
9998
|
try {
|
|
9647
|
-
for (const entry of (0,
|
|
9999
|
+
for (const entry of (0, import_node_fs26.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
9648
10000
|
if (entry.isFile() && entry.name.startsWith(".env")) {
|
|
9649
10001
|
defaults.push(entry.name);
|
|
9650
10002
|
}
|
|
@@ -9658,11 +10010,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
|
|
|
9658
10010
|
const patterns = resolveFilesToCopy(repoPath);
|
|
9659
10011
|
const copied = [];
|
|
9660
10012
|
for (const rel of patterns) {
|
|
9661
|
-
const src = (0,
|
|
9662
|
-
if (!(0,
|
|
9663
|
-
const dest = (0,
|
|
9664
|
-
(0,
|
|
9665
|
-
(0,
|
|
10013
|
+
const src = (0, import_node_path25.join)(repoPath, rel);
|
|
10014
|
+
if (!(0, import_node_fs26.existsSync)(src)) continue;
|
|
10015
|
+
const dest = (0, import_node_path25.join)(worktreePath, rel);
|
|
10016
|
+
(0, import_node_fs26.mkdirSync)((0, import_node_path25.dirname)(dest), { recursive: true });
|
|
10017
|
+
(0, import_node_fs26.copyFileSync)(src, dest);
|
|
9666
10018
|
copied.push(rel);
|
|
9667
10019
|
}
|
|
9668
10020
|
return copied;
|
|
@@ -9698,7 +10050,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
|
|
|
9698
10050
|
const env = stripNestedElectronEnv({
|
|
9699
10051
|
...baseEnv ?? process.env
|
|
9700
10052
|
});
|
|
9701
|
-
const name = opts.workspaceName ?? (0,
|
|
10053
|
+
const name = opts.workspaceName ?? (0, import_node_path25.basename)(opts.worktreePath);
|
|
9702
10054
|
const ports = opts.ports ?? [];
|
|
9703
10055
|
const primary = ports[0];
|
|
9704
10056
|
env.SIDEBOARD_WORKSPACE_NAME = name;
|
|
@@ -9784,7 +10136,10 @@ async function spawnWorkspaceScript(command, opts) {
|
|
|
9784
10136
|
loginEnv
|
|
9785
10137
|
);
|
|
9786
10138
|
try {
|
|
9787
|
-
|
|
10139
|
+
mergeAgentGitAuthEnv(
|
|
10140
|
+
env,
|
|
10141
|
+
await resolveAgentGitAuthEnv(env, { cwd: opts.worktreePath })
|
|
10142
|
+
);
|
|
9788
10143
|
} catch {
|
|
9789
10144
|
}
|
|
9790
10145
|
const shell = process.platform === "darwin" ? "zsh" : "bash";
|
|
@@ -9952,8 +10307,8 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
|
9952
10307
|
}
|
|
9953
10308
|
|
|
9954
10309
|
// src/git/orphan-cleanup.ts
|
|
9955
|
-
var
|
|
9956
|
-
var
|
|
10310
|
+
var import_node_fs27 = require("fs");
|
|
10311
|
+
var import_node_path26 = require("path");
|
|
9957
10312
|
init_worktree();
|
|
9958
10313
|
init_thread_store();
|
|
9959
10314
|
init_paths();
|
|
@@ -9968,9 +10323,9 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
9968
10323
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
9969
10324
|
);
|
|
9970
10325
|
const homeRoot = sideboardWorkspacesDir();
|
|
9971
|
-
if ((0,
|
|
10326
|
+
if ((0, import_node_fs27.existsSync)(homeRoot)) {
|
|
9972
10327
|
try {
|
|
9973
|
-
for (const entry of (0,
|
|
10328
|
+
for (const entry of (0, import_node_fs27.readdirSync)(homeRoot, { withFileTypes: true })) {
|
|
9974
10329
|
if (!entry.isDirectory()) continue;
|
|
9975
10330
|
void entry;
|
|
9976
10331
|
}
|
|
@@ -9980,7 +10335,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
9980
10335
|
const orphans = [];
|
|
9981
10336
|
const seen = /* @__PURE__ */ new Set();
|
|
9982
10337
|
for (const repoPath of repos) {
|
|
9983
|
-
if (!repoPath || !(0,
|
|
10338
|
+
if (!repoPath || !(0, import_node_fs27.existsSync)(repoPath)) continue;
|
|
9984
10339
|
try {
|
|
9985
10340
|
const wts = await listWorktrees(repoPath);
|
|
9986
10341
|
for (const wt of wts) {
|
|
@@ -9991,7 +10346,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
9991
10346
|
seen.add(path);
|
|
9992
10347
|
let mtimeMs = 0;
|
|
9993
10348
|
try {
|
|
9994
|
-
mtimeMs = (0,
|
|
10349
|
+
mtimeMs = (0, import_node_fs27.statSync)(path).mtimeMs;
|
|
9995
10350
|
} catch {
|
|
9996
10351
|
mtimeMs = 0;
|
|
9997
10352
|
}
|
|
@@ -10001,16 +10356,16 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
10001
10356
|
}
|
|
10002
10357
|
try {
|
|
10003
10358
|
const root = worktreesRoot(repoPath);
|
|
10004
|
-
if ((0,
|
|
10005
|
-
for (const entry of (0,
|
|
10359
|
+
if ((0, import_node_fs27.existsSync)(root)) {
|
|
10360
|
+
for (const entry of (0, import_node_fs27.readdirSync)(root, { withFileTypes: true })) {
|
|
10006
10361
|
if (!entry.isDirectory()) continue;
|
|
10007
|
-
const path = (0,
|
|
10362
|
+
const path = (0, import_node_path26.join)(root, entry.name).replace(/\/$/, "");
|
|
10008
10363
|
if (known.has(path) || seen.has(path)) continue;
|
|
10009
|
-
if (!(0,
|
|
10364
|
+
if (!(0, import_node_fs27.existsSync)((0, import_node_path26.join)(path, ".git"))) continue;
|
|
10010
10365
|
seen.add(path);
|
|
10011
10366
|
let mtimeMs = 0;
|
|
10012
10367
|
try {
|
|
10013
|
-
mtimeMs = (0,
|
|
10368
|
+
mtimeMs = (0, import_node_fs27.statSync)(path).mtimeMs;
|
|
10014
10369
|
} catch {
|
|
10015
10370
|
mtimeMs = Date.now();
|
|
10016
10371
|
}
|
|
@@ -10147,8 +10502,8 @@ async function applyThreadIntoMain(thread, opts) {
|
|
|
10147
10502
|
}
|
|
10148
10503
|
|
|
10149
10504
|
// src/git/clone-repo.ts
|
|
10150
|
-
var
|
|
10151
|
-
var
|
|
10505
|
+
var import_node_fs29 = require("fs");
|
|
10506
|
+
var import_node_path28 = require("path");
|
|
10152
10507
|
var import_execa6 = require("execa");
|
|
10153
10508
|
init_paths();
|
|
10154
10509
|
init_workspaces();
|
|
@@ -10158,12 +10513,12 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
10158
10513
|
if (!url) throw new Error("Clone URL is required");
|
|
10159
10514
|
let name = opts.name?.trim();
|
|
10160
10515
|
if (!name) {
|
|
10161
|
-
const leaf = (0,
|
|
10516
|
+
const leaf = (0, import_node_path28.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
|
|
10162
10517
|
name = leaf || "repo";
|
|
10163
10518
|
}
|
|
10164
10519
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
10165
|
-
const dest = (0,
|
|
10166
|
-
if ((0,
|
|
10520
|
+
const dest = (0, import_node_path28.join)(sideboardReposDir(), name);
|
|
10521
|
+
if ((0, import_node_fs29.existsSync)(dest)) {
|
|
10167
10522
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
10168
10523
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
10169
10524
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -10183,7 +10538,7 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
10183
10538
|
init_thread_store();
|
|
10184
10539
|
|
|
10185
10540
|
// src/threads/create.ts
|
|
10186
|
-
var
|
|
10541
|
+
var import_node_fs30 = require("fs");
|
|
10187
10542
|
|
|
10188
10543
|
// src/detect/detect.ts
|
|
10189
10544
|
init_agents();
|
|
@@ -10228,12 +10583,13 @@ async function createThread(input, _onSetupLine) {
|
|
|
10228
10583
|
});
|
|
10229
10584
|
await requireAgent(resolved.agent);
|
|
10230
10585
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
10231
|
-
if (!(0,
|
|
10586
|
+
if (!(0, import_node_fs30.existsSync)(repoPath)) {
|
|
10232
10587
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
10233
10588
|
}
|
|
10234
10589
|
let sourceRef = input.sourceRef;
|
|
10235
10590
|
let sourceIsFork = false;
|
|
10236
10591
|
let prUrl = null;
|
|
10592
|
+
let prTitle = null;
|
|
10237
10593
|
if (input.sourceType === "pr") {
|
|
10238
10594
|
const num2 = Number(input.sourceRef.replace(/^#/, ""));
|
|
10239
10595
|
if (!Number.isFinite(num2)) throw new Error(`Invalid PR number: ${input.sourceRef}`);
|
|
@@ -10249,6 +10605,12 @@ async function createThread(input, _onSetupLine) {
|
|
|
10249
10605
|
} else if (input.sourceType === "branch") {
|
|
10250
10606
|
if (!sourceRef || sourceRef === "HEAD" || sourceRef === "default") {
|
|
10251
10607
|
sourceRef = await resolveDefaultBranch(repoPath);
|
|
10608
|
+
} else {
|
|
10609
|
+
const existing = await getPrForHeadBranch(repoPath, sourceRef);
|
|
10610
|
+
if (existing?.url) {
|
|
10611
|
+
prUrl = existing.url;
|
|
10612
|
+
prTitle = existing.title;
|
|
10613
|
+
}
|
|
10252
10614
|
}
|
|
10253
10615
|
} else if (input.sourceType === "adopt") {
|
|
10254
10616
|
throw new Error("Use adoptThread() for adopt sources");
|
|
@@ -10279,7 +10641,8 @@ async function createThread(input, _onSetupLine) {
|
|
|
10279
10641
|
sourceIsFork,
|
|
10280
10642
|
parentThreadId: input.parentThreadId ?? null,
|
|
10281
10643
|
status: "idle",
|
|
10282
|
-
prUrl
|
|
10644
|
+
prUrl,
|
|
10645
|
+
prTitle
|
|
10283
10646
|
});
|
|
10284
10647
|
writeThread(thread);
|
|
10285
10648
|
await ensureWorkspace(repoPath);
|
|
@@ -10691,8 +11054,8 @@ function forkChatTab(input) {
|
|
|
10691
11054
|
|
|
10692
11055
|
// src/review/request-review.ts
|
|
10693
11056
|
var import_node_crypto5 = require("crypto");
|
|
10694
|
-
var
|
|
10695
|
-
var
|
|
11057
|
+
var import_node_fs31 = require("fs");
|
|
11058
|
+
var import_node_path29 = require("path");
|
|
10696
11059
|
init_global_workspace();
|
|
10697
11060
|
init_thread_store();
|
|
10698
11061
|
|
|
@@ -10840,22 +11203,22 @@ function shouldRefreshReviewRequestTemplate(content) {
|
|
|
10840
11203
|
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
10841
11204
|
}
|
|
10842
11205
|
function readTextIfPresent(abs) {
|
|
10843
|
-
if (!(0,
|
|
11206
|
+
if (!(0, import_node_fs31.existsSync)(abs)) return null;
|
|
10844
11207
|
try {
|
|
10845
|
-
const content = (0,
|
|
11208
|
+
const content = (0, import_node_fs31.readFileSync)(abs, "utf8");
|
|
10846
11209
|
return content.trim() ? content : null;
|
|
10847
11210
|
} catch {
|
|
10848
11211
|
return null;
|
|
10849
11212
|
}
|
|
10850
11213
|
}
|
|
10851
11214
|
function ensureAttachmentsGitignore(worktreePath) {
|
|
10852
|
-
const gitignoreAbs = (0,
|
|
10853
|
-
if ((0,
|
|
10854
|
-
(0,
|
|
10855
|
-
(0,
|
|
11215
|
+
const gitignoreAbs = (0, import_node_path29.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
11216
|
+
if ((0, import_node_fs31.existsSync)(gitignoreAbs)) return;
|
|
11217
|
+
(0, import_node_fs31.mkdirSync)((0, import_node_path29.dirname)(gitignoreAbs), { recursive: true });
|
|
11218
|
+
(0, import_node_fs31.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
10856
11219
|
}
|
|
10857
11220
|
function resolveReviewGuidelines(worktreePath) {
|
|
10858
|
-
const repoAbs = (0,
|
|
11221
|
+
const repoAbs = (0, import_node_path29.join)(worktreePath, REPO_REVIEW_PATH);
|
|
10859
11222
|
const repoContent = readTextIfPresent(repoAbs);
|
|
10860
11223
|
if (repoContent) {
|
|
10861
11224
|
return {
|
|
@@ -10865,7 +11228,7 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
10865
11228
|
source: "repo"
|
|
10866
11229
|
};
|
|
10867
11230
|
}
|
|
10868
|
-
const localAbs = (0,
|
|
11231
|
+
const localAbs = (0, import_node_path29.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
10869
11232
|
const localContent = readTextIfPresent(localAbs);
|
|
10870
11233
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
10871
11234
|
return {
|
|
@@ -10875,7 +11238,7 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
10875
11238
|
source: "local"
|
|
10876
11239
|
};
|
|
10877
11240
|
}
|
|
10878
|
-
const legacyAbs = (0,
|
|
11241
|
+
const legacyAbs = (0, import_node_path29.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
|
|
10879
11242
|
const legacyContent = readTextIfPresent(legacyAbs);
|
|
10880
11243
|
if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
|
|
10881
11244
|
return {
|
|
@@ -10886,8 +11249,8 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
10886
11249
|
};
|
|
10887
11250
|
}
|
|
10888
11251
|
ensureAttachmentsGitignore(worktreePath);
|
|
10889
|
-
(0,
|
|
10890
|
-
(0,
|
|
11252
|
+
(0, import_node_fs31.mkdirSync)((0, import_node_path29.dirname)(localAbs), { recursive: true });
|
|
11253
|
+
(0, import_node_fs31.writeFileSync)(localAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
|
|
10891
11254
|
return {
|
|
10892
11255
|
path: REVIEW_REQUEST_PATH,
|
|
10893
11256
|
name: REVIEW_REQUEST_NAME,
|
|
@@ -11087,20 +11450,26 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
|
|
|
11087
11450
|
|
|
11088
11451
|
// src/threads/adopt.ts
|
|
11089
11452
|
var import_node_child_process3 = require("child_process");
|
|
11090
|
-
var
|
|
11091
|
-
var
|
|
11092
|
-
var
|
|
11093
|
-
var
|
|
11453
|
+
var import_node_fs32 = require("fs");
|
|
11454
|
+
var import_node_os10 = require("os");
|
|
11455
|
+
var import_node_path30 = require("path");
|
|
11456
|
+
var import_node_module4 = require("module");
|
|
11094
11457
|
init_worktree();
|
|
11095
11458
|
init_thread_store();
|
|
11096
|
-
var
|
|
11459
|
+
var import_meta4 = {};
|
|
11460
|
+
var CONDUCTOR_APP_SUPPORT = (0, import_node_path30.join)(
|
|
11097
11461
|
process.env.HOME ?? "",
|
|
11098
11462
|
"Library",
|
|
11099
11463
|
"Application Support",
|
|
11100
11464
|
"com.conductor.app"
|
|
11101
11465
|
);
|
|
11102
|
-
var CONDUCTOR_DB = (0,
|
|
11103
|
-
var CURSOR_SDK_STORE = (0,
|
|
11466
|
+
var CONDUCTOR_DB = (0, import_node_path30.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
11467
|
+
var CURSOR_SDK_STORE = (0, import_node_path30.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
11468
|
+
function openReadonlySqlite(file) {
|
|
11469
|
+
const req = (0, import_node_module4.createRequire)(import_meta4.url);
|
|
11470
|
+
const Database = req("better-sqlite3");
|
|
11471
|
+
return new Database(file, { readonly: true, fileMustExist: true });
|
|
11472
|
+
}
|
|
11104
11473
|
function mapAgentType(raw) {
|
|
11105
11474
|
if (!raw) return null;
|
|
11106
11475
|
const v = raw.toLowerCase();
|
|
@@ -11112,21 +11481,21 @@ function mapAgentType(raw) {
|
|
|
11112
11481
|
return null;
|
|
11113
11482
|
}
|
|
11114
11483
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
11115
|
-
if (!workspacePath || !(0,
|
|
11484
|
+
if (!workspacePath || !(0, import_node_fs32.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
11116
11485
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
11117
11486
|
let best = null;
|
|
11118
11487
|
let hashes;
|
|
11119
11488
|
try {
|
|
11120
|
-
hashes = (0,
|
|
11489
|
+
hashes = (0, import_node_fs32.readdirSync)(CURSOR_SDK_STORE);
|
|
11121
11490
|
} catch {
|
|
11122
11491
|
return null;
|
|
11123
11492
|
}
|
|
11124
11493
|
for (const hash of hashes) {
|
|
11125
|
-
const agentsFile = (0,
|
|
11126
|
-
if (!(0,
|
|
11494
|
+
const agentsFile = (0, import_node_path30.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
11495
|
+
if (!(0, import_node_fs32.existsSync)(agentsFile)) continue;
|
|
11127
11496
|
let text3;
|
|
11128
11497
|
try {
|
|
11129
|
-
text3 = (0,
|
|
11498
|
+
text3 = (0, import_node_fs32.readFileSync)(agentsFile, "utf8");
|
|
11130
11499
|
} catch {
|
|
11131
11500
|
continue;
|
|
11132
11501
|
}
|
|
@@ -11150,7 +11519,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
11150
11519
|
return best?.agentId ?? null;
|
|
11151
11520
|
}
|
|
11152
11521
|
async function adoptThread(input) {
|
|
11153
|
-
if (!(0,
|
|
11522
|
+
if (!(0, import_node_fs32.existsSync)(input.worktreePath)) {
|
|
11154
11523
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
11155
11524
|
}
|
|
11156
11525
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -11174,23 +11543,23 @@ async function adoptThread(input) {
|
|
|
11174
11543
|
return thread;
|
|
11175
11544
|
}
|
|
11176
11545
|
function listConductorWorkspaces() {
|
|
11177
|
-
if (!(0,
|
|
11546
|
+
if (!(0, import_node_fs32.existsSync)(CONDUCTOR_DB)) {
|
|
11178
11547
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
11179
11548
|
}
|
|
11180
|
-
const tmp = (0,
|
|
11181
|
-
const snapshot = (0,
|
|
11549
|
+
const tmp = (0, import_node_fs32.mkdtempSync)((0, import_node_path30.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
|
|
11550
|
+
const snapshot = (0, import_node_path30.join)(tmp, "conductor.db");
|
|
11182
11551
|
try {
|
|
11183
|
-
(0,
|
|
11552
|
+
(0, import_node_fs32.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
11184
11553
|
for (const suffix of ["-wal", "-shm"]) {
|
|
11185
11554
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
11186
|
-
if ((0,
|
|
11555
|
+
if ((0, import_node_fs32.existsSync)(src)) {
|
|
11187
11556
|
try {
|
|
11188
|
-
(0,
|
|
11557
|
+
(0, import_node_fs32.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
11189
11558
|
} catch {
|
|
11190
11559
|
}
|
|
11191
11560
|
}
|
|
11192
11561
|
}
|
|
11193
|
-
const db =
|
|
11562
|
+
const db = openReadonlySqlite(snapshot);
|
|
11194
11563
|
try {
|
|
11195
11564
|
const tables = db.prepare(`SELECT name FROM sqlite_master WHERE type='table'`).all();
|
|
11196
11565
|
const names = new Set(tables.map((t) => t.name));
|
|
@@ -11261,27 +11630,27 @@ function listConductorWorkspaces() {
|
|
|
11261
11630
|
db.close();
|
|
11262
11631
|
}
|
|
11263
11632
|
} finally {
|
|
11264
|
-
(0,
|
|
11633
|
+
(0, import_node_fs32.rmSync)(tmp, { recursive: true, force: true });
|
|
11265
11634
|
}
|
|
11266
11635
|
}
|
|
11267
11636
|
function importConductorWorkspace(workspaceId) {
|
|
11268
|
-
if (!(0,
|
|
11637
|
+
if (!(0, import_node_fs32.existsSync)(CONDUCTOR_DB)) {
|
|
11269
11638
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
11270
11639
|
}
|
|
11271
|
-
const tmp = (0,
|
|
11272
|
-
const snapshot = (0,
|
|
11640
|
+
const tmp = (0, import_node_fs32.mkdtempSync)((0, import_node_path30.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
|
|
11641
|
+
const snapshot = (0, import_node_path30.join)(tmp, "conductor.db");
|
|
11273
11642
|
try {
|
|
11274
|
-
(0,
|
|
11643
|
+
(0, import_node_fs32.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
11275
11644
|
for (const suffix of ["-wal", "-shm"]) {
|
|
11276
11645
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
11277
|
-
if ((0,
|
|
11646
|
+
if ((0, import_node_fs32.existsSync)(src)) {
|
|
11278
11647
|
try {
|
|
11279
|
-
(0,
|
|
11648
|
+
(0, import_node_fs32.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
11280
11649
|
} catch {
|
|
11281
11650
|
}
|
|
11282
11651
|
}
|
|
11283
11652
|
}
|
|
11284
|
-
const db =
|
|
11653
|
+
const db = openReadonlySqlite(snapshot);
|
|
11285
11654
|
try {
|
|
11286
11655
|
const row = db.prepare(
|
|
11287
11656
|
`SELECT
|
|
@@ -11294,7 +11663,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
11294
11663
|
).get(workspaceId);
|
|
11295
11664
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
11296
11665
|
const worktreePath = String(row.workspacePath);
|
|
11297
|
-
if (!(0,
|
|
11666
|
+
if (!(0, import_node_fs32.existsSync)(worktreePath)) {
|
|
11298
11667
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
11299
11668
|
}
|
|
11300
11669
|
let sessionId = null;
|
|
@@ -11357,7 +11726,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
11357
11726
|
db.close();
|
|
11358
11727
|
}
|
|
11359
11728
|
} finally {
|
|
11360
|
-
(0,
|
|
11729
|
+
(0, import_node_fs32.rmSync)(tmp, { recursive: true, force: true });
|
|
11361
11730
|
}
|
|
11362
11731
|
}
|
|
11363
11732
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
@@ -11365,7 +11734,7 @@ async function importConductorWorkspaceAsync(workspaceId) {
|
|
|
11365
11734
|
}
|
|
11366
11735
|
|
|
11367
11736
|
// src/threads/stack-layers.ts
|
|
11368
|
-
var
|
|
11737
|
+
var import_node_fs33 = require("fs");
|
|
11369
11738
|
init_run();
|
|
11370
11739
|
init_stack();
|
|
11371
11740
|
init_worktree();
|
|
@@ -11433,7 +11802,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
11433
11802
|
let createdWorktree = false;
|
|
11434
11803
|
const trees = await listWorktrees(repoPath);
|
|
11435
11804
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
11436
|
-
if (checkedOut?.path && (0,
|
|
11805
|
+
if (checkedOut?.path && (0, import_node_fs33.existsSync)(checkedOut.path)) {
|
|
11437
11806
|
if (input.reuseExistingWorktree !== false) {
|
|
11438
11807
|
worktreePath = checkedOut.path;
|
|
11439
11808
|
} else {
|
|
@@ -11575,7 +11944,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
11575
11944
|
async function createPrStack(input, onSetupLine) {
|
|
11576
11945
|
await requireAgent(input.agent);
|
|
11577
11946
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
11578
|
-
if (!(0,
|
|
11947
|
+
if (!(0, import_node_fs33.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
11579
11948
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
11580
11949
|
const status = await detectGhStack(repoPath);
|
|
11581
11950
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -11642,7 +12011,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
11642
12011
|
}
|
|
11643
12012
|
}
|
|
11644
12013
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
11645
|
-
if (!claimed.has(bootstrap.worktreePath) && (0,
|
|
12014
|
+
if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs33.existsSync)(bootstrap.worktreePath)) {
|
|
11646
12015
|
try {
|
|
11647
12016
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
11648
12017
|
deleteBranch: bootstrap.branchName
|
|
@@ -11657,12 +12026,12 @@ async function createPrStack(input, onSetupLine) {
|
|
|
11657
12026
|
init_worktree();
|
|
11658
12027
|
|
|
11659
12028
|
// src/diff/diff.ts
|
|
11660
|
-
var
|
|
11661
|
-
var
|
|
12029
|
+
var import_node_fs34 = require("fs");
|
|
12030
|
+
var import_node_path31 = require("path");
|
|
11662
12031
|
init_run();
|
|
11663
12032
|
init_worktree();
|
|
11664
12033
|
async function inspectGitWorktree(worktreePath) {
|
|
11665
|
-
if (!worktreePath || !(0,
|
|
12034
|
+
if (!worktreePath || !(0, import_node_fs34.existsSync)(worktreePath)) return "missing_worktree";
|
|
11666
12035
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
11667
12036
|
reject: false
|
|
11668
12037
|
});
|
|
@@ -11670,7 +12039,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
11670
12039
|
return "ok";
|
|
11671
12040
|
}
|
|
11672
12041
|
async function initializeGitRepository(worktreePath) {
|
|
11673
|
-
if (!worktreePath || !(0,
|
|
12042
|
+
if (!worktreePath || !(0, import_node_fs34.existsSync)(worktreePath)) {
|
|
11674
12043
|
throw new Error("Worktree not found");
|
|
11675
12044
|
}
|
|
11676
12045
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -11805,11 +12174,11 @@ new file mode 100644
|
|
|
11805
12174
|
};
|
|
11806
12175
|
}
|
|
11807
12176
|
async function untrackedPatch(worktreePath, path, maxHunk) {
|
|
11808
|
-
const abs = (0,
|
|
12177
|
+
const abs = (0, import_node_path31.join)(worktreePath, path);
|
|
11809
12178
|
try {
|
|
11810
|
-
const st = (0,
|
|
12179
|
+
const st = (0, import_node_fs34.statSync)(abs);
|
|
11811
12180
|
if (st.isFile() && st.size > maxHunk) {
|
|
11812
|
-
const buf = (0,
|
|
12181
|
+
const buf = (0, import_node_fs34.readFileSync)(abs).subarray(0, maxHunk);
|
|
11813
12182
|
return syntheticAddPatch(path, buf.toString("utf8"), maxHunk);
|
|
11814
12183
|
}
|
|
11815
12184
|
} catch {
|
|
@@ -12310,8 +12679,8 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
|
|
|
12310
12679
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
12311
12680
|
assertSafeRelativePath(relativePath);
|
|
12312
12681
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
12313
|
-
const abs = (0,
|
|
12314
|
-
const st = (0,
|
|
12682
|
+
const abs = (0, import_node_path31.join)(worktreePath, relativePath);
|
|
12683
|
+
const st = (0, import_node_fs34.statSync)(abs);
|
|
12315
12684
|
if (!st.isFile()) {
|
|
12316
12685
|
throw new Error(`Not a file: ${relativePath}`);
|
|
12317
12686
|
}
|
|
@@ -12320,7 +12689,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
12320
12689
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
12321
12690
|
);
|
|
12322
12691
|
}
|
|
12323
|
-
const buf = (0,
|
|
12692
|
+
const buf = (0, import_node_fs34.readFileSync)(abs);
|
|
12324
12693
|
return {
|
|
12325
12694
|
path: relativePath,
|
|
12326
12695
|
contentBase64: buf.toString("base64"),
|
|
@@ -12330,12 +12699,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
12330
12699
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
12331
12700
|
assertSafeRelativePath(relativePath);
|
|
12332
12701
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
12333
|
-
const abs = (0,
|
|
12334
|
-
const st = (0,
|
|
12702
|
+
const abs = (0, import_node_path31.join)(worktreePath, relativePath);
|
|
12703
|
+
const st = (0, import_node_fs34.statSync)(abs);
|
|
12335
12704
|
if (!st.isFile()) {
|
|
12336
12705
|
throw new Error(`Not a file: ${relativePath}`);
|
|
12337
12706
|
}
|
|
12338
|
-
const buf = (0,
|
|
12707
|
+
const buf = (0, import_node_fs34.readFileSync)(abs);
|
|
12339
12708
|
if (isImageRelativePath(relativePath)) {
|
|
12340
12709
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
12341
12710
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -12378,9 +12747,9 @@ function assertSafeRelativePath(relativePath) {
|
|
|
12378
12747
|
}
|
|
12379
12748
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
12380
12749
|
assertSafeRelativePath(relativePath);
|
|
12381
|
-
const abs = (0,
|
|
12382
|
-
(0,
|
|
12383
|
-
(0,
|
|
12750
|
+
const abs = (0, import_node_path31.join)(worktreePath, relativePath);
|
|
12751
|
+
(0, import_node_fs34.mkdirSync)((0, import_node_path31.dirname)(abs), { recursive: true });
|
|
12752
|
+
(0, import_node_fs34.writeFileSync)(abs, content, "utf8");
|
|
12384
12753
|
return { path: relativePath };
|
|
12385
12754
|
}
|
|
12386
12755
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
@@ -12484,9 +12853,9 @@ async function confirmLand(thread, opts) {
|
|
|
12484
12853
|
}
|
|
12485
12854
|
|
|
12486
12855
|
// src/skills/discover.ts
|
|
12487
|
-
var
|
|
12488
|
-
var
|
|
12489
|
-
var
|
|
12856
|
+
var import_node_fs35 = require("fs");
|
|
12857
|
+
var import_node_os11 = require("os");
|
|
12858
|
+
var import_node_path32 = require("path");
|
|
12490
12859
|
function toCommand(name) {
|
|
12491
12860
|
return name.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
12492
12861
|
}
|
|
@@ -12518,7 +12887,7 @@ function parseFrontmatter(content) {
|
|
|
12518
12887
|
}
|
|
12519
12888
|
function readSkill(skillMd, source) {
|
|
12520
12889
|
try {
|
|
12521
|
-
const content = (0,
|
|
12890
|
+
const content = (0, import_node_fs35.readFileSync)(skillMd, "utf8");
|
|
12522
12891
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
12523
12892
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
12524
12893
|
const name = fmName || dirName;
|
|
@@ -12537,19 +12906,19 @@ function readSkill(skillMd, source) {
|
|
|
12537
12906
|
}
|
|
12538
12907
|
}
|
|
12539
12908
|
function scanSkillsDir(dir, source, out) {
|
|
12540
|
-
if (!(0,
|
|
12909
|
+
if (!(0, import_node_fs35.existsSync)(dir)) return;
|
|
12541
12910
|
let entries;
|
|
12542
12911
|
try {
|
|
12543
|
-
entries = (0,
|
|
12912
|
+
entries = (0, import_node_fs35.readdirSync)(dir);
|
|
12544
12913
|
} catch {
|
|
12545
12914
|
return;
|
|
12546
12915
|
}
|
|
12547
12916
|
for (const entry of entries) {
|
|
12548
12917
|
if (entry.startsWith(".")) continue;
|
|
12549
|
-
const skillMd = (0,
|
|
12550
|
-
if (!(0,
|
|
12918
|
+
const skillMd = (0, import_node_path32.join)(dir, entry, "SKILL.md");
|
|
12919
|
+
if (!(0, import_node_fs35.existsSync)(skillMd)) continue;
|
|
12551
12920
|
try {
|
|
12552
|
-
if (!(0,
|
|
12921
|
+
if (!(0, import_node_fs35.statSync)(skillMd).isFile()) continue;
|
|
12553
12922
|
} catch {
|
|
12554
12923
|
continue;
|
|
12555
12924
|
}
|
|
@@ -12558,24 +12927,24 @@ function scanSkillsDir(dir, source, out) {
|
|
|
12558
12927
|
}
|
|
12559
12928
|
}
|
|
12560
12929
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
12561
|
-
if (!(0,
|
|
12930
|
+
if (!(0, import_node_fs35.existsSync)(pluginsRoot)) return;
|
|
12562
12931
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
12563
12932
|
if (depth > 7) return;
|
|
12564
12933
|
let entries;
|
|
12565
12934
|
try {
|
|
12566
|
-
entries = (0,
|
|
12935
|
+
entries = (0, import_node_fs35.readdirSync)(dir);
|
|
12567
12936
|
} catch {
|
|
12568
12937
|
return;
|
|
12569
12938
|
}
|
|
12570
12939
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
12571
|
-
const skill = readSkill((0,
|
|
12940
|
+
const skill = readSkill((0, import_node_path32.join)(dir, "SKILL.md"), "cli");
|
|
12572
12941
|
if (skill) out.push(skill);
|
|
12573
12942
|
}
|
|
12574
12943
|
for (const entry of entries) {
|
|
12575
12944
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
12576
|
-
const full = (0,
|
|
12945
|
+
const full = (0, import_node_path32.join)(dir, entry);
|
|
12577
12946
|
try {
|
|
12578
|
-
if (!(0,
|
|
12947
|
+
if (!(0, import_node_fs35.statSync)(full).isDirectory()) continue;
|
|
12579
12948
|
} catch {
|
|
12580
12949
|
continue;
|
|
12581
12950
|
}
|
|
@@ -12590,20 +12959,20 @@ function scanClaudePluginSkills(pluginsRoot, out) {
|
|
|
12590
12959
|
walk(pluginsRoot, 0, false);
|
|
12591
12960
|
}
|
|
12592
12961
|
function discoverSkills(worktreePath) {
|
|
12593
|
-
const home = (0,
|
|
12962
|
+
const home = (0, import_node_os11.homedir)();
|
|
12594
12963
|
const collected = [];
|
|
12595
12964
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
12596
|
-
scanSkillsDir((0,
|
|
12965
|
+
scanSkillsDir((0, import_node_path32.join)(worktreePath, rel), "workspace", collected);
|
|
12597
12966
|
}
|
|
12598
12967
|
for (const abs of [
|
|
12599
|
-
(0,
|
|
12600
|
-
(0,
|
|
12601
|
-
(0,
|
|
12602
|
-
(0,
|
|
12968
|
+
(0, import_node_path32.join)(home, ".claude/skills"),
|
|
12969
|
+
(0, import_node_path32.join)(home, ".cursor/skills"),
|
|
12970
|
+
(0, import_node_path32.join)(home, ".sideboard/skills"),
|
|
12971
|
+
(0, import_node_path32.join)(home, ".brightsy/skills")
|
|
12603
12972
|
]) {
|
|
12604
12973
|
scanSkillsDir(abs, "user", collected);
|
|
12605
12974
|
}
|
|
12606
|
-
scanClaudePluginSkills((0,
|
|
12975
|
+
scanClaudePluginSkills((0, import_node_path32.join)(home, ".claude/plugins"), collected);
|
|
12607
12976
|
const rank = { workspace: 0, user: 1, cli: 2 };
|
|
12608
12977
|
const byCommand = /* @__PURE__ */ new Map();
|
|
12609
12978
|
for (const skill of collected) {
|
|
@@ -12615,7 +12984,7 @@ function discoverSkills(worktreePath) {
|
|
|
12615
12984
|
return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
|
|
12616
12985
|
}
|
|
12617
12986
|
function readSkillBody(skillPath, maxChars = 12e3) {
|
|
12618
|
-
const raw = (0,
|
|
12987
|
+
const raw = (0, import_node_fs35.readFileSync)(skillPath, "utf8");
|
|
12619
12988
|
if (raw.startsWith("---")) {
|
|
12620
12989
|
const end = raw.indexOf("\n---", 3);
|
|
12621
12990
|
if (end >= 0) {
|
|
@@ -12708,8 +13077,8 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
|
|
|
12708
13077
|
}
|
|
12709
13078
|
|
|
12710
13079
|
// src/composer/stage-files.ts
|
|
12711
|
-
var
|
|
12712
|
-
var
|
|
13080
|
+
var import_node_fs36 = require("fs");
|
|
13081
|
+
var import_node_path33 = require("path");
|
|
12713
13082
|
var import_node_crypto7 = require("crypto");
|
|
12714
13083
|
init_workspace_scratch();
|
|
12715
13084
|
var IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
@@ -12735,7 +13104,7 @@ var IMAGE_MIME_BY_EXT = {
|
|
|
12735
13104
|
var MAX_INLINE_BYTES = 4e5;
|
|
12736
13105
|
var MAX_PREVIEW_BYTES = 5e6;
|
|
12737
13106
|
function fileExtension(filePath) {
|
|
12738
|
-
const base = (0,
|
|
13107
|
+
const base = (0, import_node_path33.basename)(filePath).toLowerCase();
|
|
12739
13108
|
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
12740
13109
|
}
|
|
12741
13110
|
function isImageFilePath(filePath) {
|
|
@@ -12745,22 +13114,22 @@ function imageMimeType(filePath) {
|
|
|
12745
13114
|
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
12746
13115
|
}
|
|
12747
13116
|
function ensureAttachmentsDir(worktreePath) {
|
|
12748
|
-
const dir = (0,
|
|
12749
|
-
(0,
|
|
12750
|
-
const gi = (0,
|
|
12751
|
-
if (!(0,
|
|
12752
|
-
(0,
|
|
13117
|
+
const dir = (0, import_node_path33.join)(worktreePath, ATTACHMENTS_DIR);
|
|
13118
|
+
(0, import_node_fs36.mkdirSync)(dir, { recursive: true });
|
|
13119
|
+
const gi = (0, import_node_path33.join)(dir, ".gitignore");
|
|
13120
|
+
if (!(0, import_node_fs36.existsSync)(gi)) {
|
|
13121
|
+
(0, import_node_fs36.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
12753
13122
|
}
|
|
12754
13123
|
return dir;
|
|
12755
13124
|
}
|
|
12756
13125
|
function uniqueAttachmentName(dir, originalName) {
|
|
12757
13126
|
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
12758
|
-
if (!(0,
|
|
12759
|
-
const ext = (0,
|
|
13127
|
+
if (!(0, import_node_fs36.existsSync)((0, import_node_path33.join)(dir, safe))) return safe;
|
|
13128
|
+
const ext = (0, import_node_path33.extname)(safe);
|
|
12760
13129
|
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
12761
13130
|
for (let i = 1; i < 1e4; i++) {
|
|
12762
13131
|
const candidate = `${stem}-${i}${ext}`;
|
|
12763
|
-
if (!(0,
|
|
13132
|
+
if (!(0, import_node_fs36.existsSync)((0, import_node_path33.join)(dir, candidate))) return candidate;
|
|
12764
13133
|
}
|
|
12765
13134
|
return `${stem}-${(0, import_node_crypto7.randomUUID)()}${ext}`;
|
|
12766
13135
|
}
|
|
@@ -12816,15 +13185,15 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
|
12816
13185
|
const dir = ensureAttachmentsDir(worktreePath);
|
|
12817
13186
|
const out = [];
|
|
12818
13187
|
for (const abs of absolutePaths) {
|
|
12819
|
-
const originalName = (0,
|
|
13188
|
+
const originalName = (0, import_node_path33.basename)(abs);
|
|
12820
13189
|
try {
|
|
12821
|
-
const st = (0,
|
|
13190
|
+
const st = (0, import_node_fs36.statSync)(abs);
|
|
12822
13191
|
if (!st.isFile()) continue;
|
|
12823
13192
|
const name = uniqueAttachmentName(dir, originalName);
|
|
12824
|
-
const destAbs = (0,
|
|
12825
|
-
(0,
|
|
13193
|
+
const destAbs = (0, import_node_path33.join)(dir, name);
|
|
13194
|
+
(0, import_node_fs36.copyFileSync)(abs, destAbs);
|
|
12826
13195
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
12827
|
-
const buf = (0,
|
|
13196
|
+
const buf = (0, import_node_fs36.readFileSync)(destAbs);
|
|
12828
13197
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
12829
13198
|
} catch (err) {
|
|
12830
13199
|
out.push({
|
|
@@ -12846,8 +13215,8 @@ function stageBuffersAsAttachments(worktreePath, buffers) {
|
|
|
12846
13215
|
try {
|
|
12847
13216
|
const buf = Buffer.from(item.dataBase64, "base64");
|
|
12848
13217
|
const name = uniqueAttachmentName(dir, originalName);
|
|
12849
|
-
const destAbs = (0,
|
|
12850
|
-
(0,
|
|
13218
|
+
const destAbs = (0, import_node_path33.join)(dir, name);
|
|
13219
|
+
(0, import_node_fs36.writeFileSync)(destAbs, buf);
|
|
12851
13220
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
12852
13221
|
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
12853
13222
|
} catch (err) {
|
|
@@ -12867,18 +13236,18 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
|
12867
13236
|
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
12868
13237
|
out.push({
|
|
12869
13238
|
id: (0, import_node_crypto7.randomUUID)(),
|
|
12870
|
-
name: (0,
|
|
13239
|
+
name: (0, import_node_path33.basename)(rel) || "file",
|
|
12871
13240
|
kind: "file",
|
|
12872
13241
|
content: `(invalid path: ${rel})`
|
|
12873
13242
|
});
|
|
12874
13243
|
continue;
|
|
12875
13244
|
}
|
|
12876
|
-
const name = (0,
|
|
13245
|
+
const name = (0, import_node_path33.basename)(rel);
|
|
12877
13246
|
try {
|
|
12878
|
-
const abs = (0,
|
|
12879
|
-
const st = (0,
|
|
13247
|
+
const abs = (0, import_node_path33.join)(worktreePath, rel);
|
|
13248
|
+
const st = (0, import_node_fs36.statSync)(abs);
|
|
12880
13249
|
if (!st.isFile()) continue;
|
|
12881
|
-
const buf = (0,
|
|
13250
|
+
const buf = (0, import_node_fs36.readFileSync)(abs);
|
|
12882
13251
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
12883
13252
|
} catch (err) {
|
|
12884
13253
|
out.push({
|
|
@@ -12893,8 +13262,8 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
|
12893
13262
|
}
|
|
12894
13263
|
|
|
12895
13264
|
// src/agents/instructions.ts
|
|
12896
|
-
var
|
|
12897
|
-
var
|
|
13265
|
+
var import_node_fs37 = require("fs");
|
|
13266
|
+
var import_node_path34 = require("path");
|
|
12898
13267
|
init_git_auth_mode();
|
|
12899
13268
|
init_worktree_labels();
|
|
12900
13269
|
function normPath3(p) {
|
|
@@ -13027,9 +13396,10 @@ function formatArtifactDirective() {
|
|
|
13027
13396
|
"Files / media browser (CMS file manager column):",
|
|
13028
13397
|
"4) Call Sideboard MCP `present_files` with optional title, path, and datasource (brightsy|memory).",
|
|
13029
13398
|
" Opens the Files column for browse/upload/pick. Do NOT say a file manager UI is missing.",
|
|
13030
|
-
"Multiple-choice questions
|
|
13031
|
-
"5) Call Sideboard MCP `ask_user` when
|
|
13032
|
-
"
|
|
13399
|
+
"Multiple-choice questions:",
|
|
13400
|
+
"5) Call Sideboard MCP `ask_user` only when work is blocked on choosing among a few concrete options (approach forks, which API, auth vs cookies). First write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it). Include a description on every option. After calling, stop and wait for their next message with answers. If you are asking a real multiple-choice, use ask_user rather than chat bullets so Sideboard shows the composer picker.",
|
|
13401
|
+
"Do not call ask_user for greetings, check-ins, \u201Chello\u201D, open-ended how-can-I-help, or to invent a menu of possible next tasks \u2014 reply in chat. If one option is the obvious default, proceed without asking.",
|
|
13402
|
+
"Never say artifacts, CMS UI, or the Files column are unavailable. Prefer present_schema for list/edit/publish; present_files for storage UI; html fences for standalone pages; ask_user only for those blocked predefined-option questions."
|
|
13033
13403
|
].join("\n");
|
|
13034
13404
|
}
|
|
13035
13405
|
function formatUiReminder() {
|
|
@@ -13040,7 +13410,7 @@ function formatUiReminder() {
|
|
|
13040
13410
|
"CMS forms/tables: MCP present_schema (Brightsy resource_id or inline schema+schemaUi).",
|
|
13041
13411
|
"Files column: MCP present_files (brightsy account storage or memory).",
|
|
13042
13412
|
"Do not say artifacts/CMS UI are unavailable.",
|
|
13043
|
-
"
|
|
13413
|
+
"ask_user: only when blocked on a real multiple-choice (approach fork, which API). Never for hellos, check-ins, or \u201Cwhat next?\u201D menus \u2014 reply in chat."
|
|
13044
13414
|
].join(" ");
|
|
13045
13415
|
}
|
|
13046
13416
|
|
|
@@ -13168,7 +13538,7 @@ var Orchestrator = class {
|
|
|
13168
13538
|
}
|
|
13169
13539
|
continue;
|
|
13170
13540
|
}
|
|
13171
|
-
if (!(0,
|
|
13541
|
+
if (!(0, import_node_fs41.existsSync)(thread.worktreePath)) {
|
|
13172
13542
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
13173
13543
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
13174
13544
|
continue;
|
|
@@ -14260,8 +14630,9 @@ var Orchestrator = class {
|
|
|
14260
14630
|
return result;
|
|
14261
14631
|
}
|
|
14262
14632
|
async mergePr(threadRef) {
|
|
14263
|
-
const { thread,
|
|
14633
|
+
const { thread, selectors, cwd } = await this.withPrSelector(threadRef);
|
|
14264
14634
|
this.assertNotGlobal(thread, "Merge PR");
|
|
14635
|
+
const selector = selectors[0];
|
|
14265
14636
|
if (!selector) throw new Error("No pull request linked to this thread");
|
|
14266
14637
|
const result = await mergePr(cwd, selector);
|
|
14267
14638
|
const state = normalizePrState(result.state) || "MERGED";
|
|
@@ -14281,29 +14652,34 @@ var Orchestrator = class {
|
|
|
14281
14652
|
await this.persistPrMetaAndMaybeArchive(thread, metaLike);
|
|
14282
14653
|
return { url: metaLike.url, state };
|
|
14283
14654
|
}
|
|
14284
|
-
/** Resolve PR
|
|
14655
|
+
/** Resolve PR selectors and optionally persist `prUrl` when found. */
|
|
14285
14656
|
async withPrSelector(threadRef) {
|
|
14286
14657
|
const thread = this.requireThread(threadRef);
|
|
14287
|
-
const
|
|
14658
|
+
const selectors = resolvePrSelectors(thread);
|
|
14288
14659
|
const cwd = thread.worktreePath;
|
|
14289
14660
|
if (!cwd?.trim()) {
|
|
14290
14661
|
throw new Error(`Thread ${threadRef} has no worktreePath`);
|
|
14291
14662
|
}
|
|
14292
|
-
return { thread,
|
|
14663
|
+
return { thread, selectors, cwd };
|
|
14293
14664
|
}
|
|
14294
14665
|
async getPrChecks(threadRef) {
|
|
14295
|
-
const {
|
|
14296
|
-
|
|
14297
|
-
|
|
14666
|
+
const { selectors, cwd } = await this.withPrSelector(threadRef);
|
|
14667
|
+
for (const selector of selectors) {
|
|
14668
|
+
const checks = await getPrChecks(cwd, selector);
|
|
14669
|
+
if (checks) return checks;
|
|
14670
|
+
}
|
|
14671
|
+
return null;
|
|
14298
14672
|
}
|
|
14299
14673
|
async getPrMeta(threadRef) {
|
|
14300
|
-
const { thread,
|
|
14301
|
-
|
|
14302
|
-
|
|
14303
|
-
|
|
14304
|
-
|
|
14674
|
+
const { thread, selectors, cwd } = await this.withPrSelector(threadRef);
|
|
14675
|
+
for (const selector of selectors) {
|
|
14676
|
+
const meta = await getPrMeta(cwd, selector);
|
|
14677
|
+
if (meta) {
|
|
14678
|
+
await this.persistPrMetaAndMaybeArchive(thread, meta);
|
|
14679
|
+
return meta;
|
|
14680
|
+
}
|
|
14305
14681
|
}
|
|
14306
|
-
return
|
|
14682
|
+
return null;
|
|
14307
14683
|
}
|
|
14308
14684
|
/**
|
|
14309
14685
|
* Persist PR URL/title/state and Conductor-style auto-archive when the PR
|
|
@@ -14427,9 +14803,12 @@ var Orchestrator = class {
|
|
|
14427
14803
|
return { stack: result.stack, threads: result.threads };
|
|
14428
14804
|
}
|
|
14429
14805
|
async getPrDetails(threadRef) {
|
|
14430
|
-
const { thread,
|
|
14431
|
-
|
|
14432
|
-
const
|
|
14806
|
+
const { thread, selectors, cwd } = await this.withPrSelector(threadRef);
|
|
14807
|
+
let details = null;
|
|
14808
|
+
for (const selector of selectors) {
|
|
14809
|
+
details = await getPrDetails(cwd, selector);
|
|
14810
|
+
if (details) break;
|
|
14811
|
+
}
|
|
14433
14812
|
if (details) {
|
|
14434
14813
|
const patch = {};
|
|
14435
14814
|
if (details.url && details.url !== thread.prUrl) patch.prUrl = details.url;
|
|
@@ -14656,7 +15035,7 @@ var Orchestrator = class {
|
|
|
14656
15035
|
this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
|
|
14657
15036
|
return restored2;
|
|
14658
15037
|
}
|
|
14659
|
-
if (!(0,
|
|
15038
|
+
if (!(0, import_node_fs41.existsSync)(thread.worktreePath)) {
|
|
14660
15039
|
const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
|
|
14661
15040
|
const { execa: execa7 } = await import("execa");
|
|
14662
15041
|
const slug = thread.worktreePath.split("/").pop();
|
|
@@ -15823,6 +16202,7 @@ function registerLinearTools(server) {
|
|
|
15823
16202
|
}
|
|
15824
16203
|
|
|
15825
16204
|
// src/mcp/server.ts
|
|
16205
|
+
init_git_auth_mode();
|
|
15826
16206
|
var MAX_ORCH_THREADS = 5;
|
|
15827
16207
|
var CREATE_THREAD_TIMEOUT_MS = 9e4;
|
|
15828
16208
|
function withTimeout(promise, ms, label) {
|
|
@@ -15844,6 +16224,14 @@ function withTimeout(promise, ms, label) {
|
|
|
15844
16224
|
}
|
|
15845
16225
|
async function startMcpServer() {
|
|
15846
16226
|
const orch = getOrchestrator();
|
|
16227
|
+
try {
|
|
16228
|
+
await warmGithubAgentAuth();
|
|
16229
|
+
} catch (err) {
|
|
16230
|
+
console.error(
|
|
16231
|
+
"[sideboard-mcp] GitHub agent auth warm skipped:",
|
|
16232
|
+
err instanceof Error ? err.message : err
|
|
16233
|
+
);
|
|
16234
|
+
}
|
|
15847
16235
|
try {
|
|
15848
16236
|
const { maxConcurrentAgents: maxConcurrentAgents2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
15849
16237
|
orch.setMaxConcurrent(maxConcurrentAgents2());
|
|
@@ -15887,7 +16275,7 @@ async function startMcpServer() {
|
|
|
15887
16275
|
async () => {
|
|
15888
16276
|
const threads = orch.getThreads(true);
|
|
15889
16277
|
const lines = threads.map((t) => {
|
|
15890
|
-
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0,
|
|
16278
|
+
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path38.basename)(t.repoPath) || t.repoPath;
|
|
15891
16279
|
return `${t.id.slice(0, 8)} ${t.status.padEnd(9)} ${t.agent.padEnd(8)} ${repo} ${t.sourceType}:${t.sourceRef} ${t.title} sideboard://thread/${t.id}${t.devPort ? ` http://localhost:${t.devPort}` : ""}`;
|
|
15892
16280
|
});
|
|
15893
16281
|
return {
|
|
@@ -15950,7 +16338,7 @@ async function startMcpServer() {
|
|
|
15950
16338
|
);
|
|
15951
16339
|
server.tool(
|
|
15952
16340
|
"ask_user",
|
|
15953
|
-
"Ask the user clarifying multiple-choice
|
|
16341
|
+
"Ask the user a clarifying multiple-choice question in Sideboard\u2019s composer. Call only when work is blocked on choosing among a few concrete options (approach fork, which API, auth vs cookies). Do not call for greetings, check-ins, \u201Chello\u201D, open-ended how-can-I-help, or to invent a menu of possible next tasks \u2014 reply in chat instead. If one option is the obvious default, proceed without asking. Before calling, write a short chat message explaining the decision and what each option means. Include a description on every option. After calling, stop and wait for answers. Not for \u201Cis the plan ready?\u201D.",
|
|
15954
16342
|
{
|
|
15955
16343
|
questions: import_zod3.z.array(
|
|
15956
16344
|
import_zod3.z.object({
|