@sideboard-ai/core 0.1.98 → 0.1.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/cursor-runner.cjs +69 -24
- package/dist/agents/cursor-runner.js +48 -3
- package/dist/{agents-ESJKIQQA.js → agents-CLP5BG4O.js} +3 -3
- package/dist/{agents-3MWWWSMF.js → agents-OXZDMPSE.js} +4 -4
- package/dist/{chunk-FYS2BULQ.js → chunk-EQPQTLW6.js} +209 -59
- package/dist/{chunk-FO67IJTY.js → chunk-GR4JKWR4.js} +1 -1
- package/dist/{chunk-GXSYI7FH.js → chunk-HUKCGRAT.js} +209 -59
- package/dist/{chunk-XUWDLRAE.js → chunk-HYKZEP5A.js} +2 -2
- package/dist/{chunk-XH2GS2LO.js → chunk-IFHKPZHA.js} +2 -2
- package/dist/{chunk-UYQYK2RY.js → chunk-MHJV4WS3.js} +1 -1
- package/dist/{chunk-OANJQTVG.js → chunk-MRBKGFTL.js} +1 -1
- package/dist/{chunk-MBP3XG57.js → chunk-OXC3MEFI.js} +3 -3
- package/dist/{chunk-HI2OTFFR.js → chunk-WQTTUC4N.js} +1 -1
- package/dist/{coordinator-prompt-AKEY4WSO.js → coordinator-prompt-HHRKQWCX.js} +1 -1
- package/dist/{coordinator-prompt-OQOOD5ET.js → coordinator-prompt-OOBSQCWQ.js} +1 -1
- package/dist/{global-workspace-RSQXRLT7.js → global-workspace-KYEBFWKB.js} +2 -2
- package/dist/{global-workspace-WMF3BJP5.js → global-workspace-YZWYHLQY.js} +2 -2
- package/dist/index.cjs +662 -440
- package/dist/index.d.cts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +194 -128
- package/dist/mcp/run-stdio.cjs +424 -227
- package/dist/mcp/run-stdio.js +141 -92
- package/dist/{workspaces-MZVQHRSJ.js → workspaces-ENVUDK6C.js} +3 -3
- package/dist/{workspaces-4ZY4QPWQ.js → workspaces-NNPD7QVV.js} +3 -3
- package/package.json +2 -2
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -883,6 +883,13 @@ function looksLikeMinifiedJsDump(line) {
|
|
|
883
883
|
function looksLikeNestedElectronCrash(line) {
|
|
884
884
|
return /HasCustomHostObject|ElectronInitializeICUandStartNode/i.test(line);
|
|
885
885
|
}
|
|
886
|
+
function looksLikeHomebrewLibuvCrash(line) {
|
|
887
|
+
const uvRun = /uv_run/i.test(line);
|
|
888
|
+
const spin = /SpinEventLoopInternal/i.test(line);
|
|
889
|
+
const homebrewUv = /Cellar\/libuv|libuv\.\d\.dylib/i.test(line);
|
|
890
|
+
const homebrewNode = /Cellar\/node\//i.test(line);
|
|
891
|
+
return uvRun && (homebrewUv || spin || homebrewNode) || spin && (homebrewUv || homebrewNode);
|
|
892
|
+
}
|
|
886
893
|
function clipStderr(text3, maxChars) {
|
|
887
894
|
const trimmed = text3.trim();
|
|
888
895
|
if (trimmed.length <= maxChars) return trimmed;
|
|
@@ -893,6 +900,7 @@ function summarizeTurnStderr(tail, maxChars = 500) {
|
|
|
893
900
|
const cursorStartup = [...tail].reverse().find((line) => /cursor startup failed:/i.test(line));
|
|
894
901
|
if (cursorStartup) return clipStderr(cursorStartup, maxChars);
|
|
895
902
|
if (tail.some(looksLikeNestedElectronCrash)) return NESTED_ELECTRON_SUMMARY;
|
|
903
|
+
if (tail.some(looksLikeHomebrewLibuvCrash)) return HOMEBREW_LIBUV_SUMMARY;
|
|
896
904
|
if (tail.some(
|
|
897
905
|
(line) => /\[resource_exhausted\]|resource_exhausted/i.test(line) || /findFilesWithRipgrep/.test(line)
|
|
898
906
|
)) {
|
|
@@ -915,6 +923,20 @@ function looksLikeInvalidAgentSession(text3) {
|
|
|
915
923
|
if (!lower) return false;
|
|
916
924
|
return /session not found/.test(lower) || /no conversation found/.test(lower) || /conversation .+ not found/.test(lower) || /thread .+ not found/.test(lower) || /unknown session/.test(lower) || /invalid session/.test(lower) || /session .+ (missing|expired|deleted|gone)/.test(lower) || /cannot resume/.test(lower) || /failed to (load|resume|open) session/.test(lower) || /corrupt local agent checkpoint/.test(lower) || /missing root blob/.test(lower) || /\bagent\b.{0,120}\bnot found\b/.test(lower);
|
|
917
925
|
}
|
|
926
|
+
function looksLikeRetryableRunnerCrash(text3) {
|
|
927
|
+
if (looksLikeAgentFailureMessage(text3)) return false;
|
|
928
|
+
if (looksLikeInvalidAgentSession(text3)) return false;
|
|
929
|
+
const lower = text3.trim().toLowerCase();
|
|
930
|
+
if (/cannot find (?:package|module)|err_module_not_found/.test(lower)) return false;
|
|
931
|
+
if (!lower) return true;
|
|
932
|
+
return /uv_run|spineventloopinternal|libuv|homebrew node \+ shared libuv|hascustomhostobject|electroninitializeicuandstartnode|nested chromium|truncated crash dump|sig(?:segv|abrt|ill)|segmentation fault|illegal instruction|fatal error/.test(
|
|
933
|
+
lower
|
|
934
|
+
);
|
|
935
|
+
}
|
|
936
|
+
function shouldRetryFailedAgentTurn(detail, opts) {
|
|
937
|
+
if (looksLikeInvalidAgentSession(detail) && opts.hasSession) return true;
|
|
938
|
+
return looksLikeRetryableRunnerCrash(detail);
|
|
939
|
+
}
|
|
918
940
|
function looksLikeAgentFailureMessage(text3) {
|
|
919
941
|
const lower = text3.trim().toLowerCase();
|
|
920
942
|
if (!lower) return false;
|
|
@@ -959,11 +981,22 @@ function humanizeAgentFailDetail(detail) {
|
|
|
959
981
|
if (/hascustomhostobject|electroninitializeicuandstartnode|nested chromium/i.test(lower)) {
|
|
960
982
|
return `${raw} \u2014 retry the turn; if it keeps failing, pick another agent.`;
|
|
961
983
|
}
|
|
984
|
+
if (/homebrew node \+ shared libuv|uv_run|spineventloopinternal/i.test(lower)) {
|
|
985
|
+
return /brew install node@22/i.test(raw) ? raw : `${raw} \u2014 install Node 22 LTS (\`brew install node@22\`) and retry.`;
|
|
986
|
+
}
|
|
962
987
|
if (/corrupt local agent checkpoint|missing root blob|truncated crash dump/.test(lower)) {
|
|
963
988
|
return `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
|
|
964
989
|
}
|
|
965
990
|
return raw;
|
|
966
991
|
}
|
|
992
|
+
function turnFailChatText(opts) {
|
|
993
|
+
const chat = opts.assistantText.trim();
|
|
994
|
+
if (chat) return chat;
|
|
995
|
+
if (opts.exitCode === 0) return "";
|
|
996
|
+
const detail = opts.detail.trim();
|
|
997
|
+
if (detail) return humanizeAgentFailDetail(detail);
|
|
998
|
+
return formatTurnExitError(opts.exitCode ?? 1, "");
|
|
999
|
+
}
|
|
967
1000
|
function formatTurnExitError(exitCode, stderrSummary) {
|
|
968
1001
|
const code = exitCode ?? 1;
|
|
969
1002
|
const raw = stderrSummary.trim();
|
|
@@ -977,12 +1010,13 @@ function formatTurnExitError(exitCode, stderrSummary) {
|
|
|
977
1010
|
if (looksLikeAgentFailureMessage(raw)) return detail;
|
|
978
1011
|
return `exit ${code}: ${detail}`;
|
|
979
1012
|
}
|
|
980
|
-
var NODE_VERSION_FOOTER, NESTED_ELECTRON_SUMMARY, MINIFIED_DUMP_SUMMARY;
|
|
1013
|
+
var NODE_VERSION_FOOTER, NESTED_ELECTRON_SUMMARY, HOMEBREW_LIBUV_SUMMARY, MINIFIED_DUMP_SUMMARY;
|
|
981
1014
|
var init_error_detail = __esm({
|
|
982
1015
|
"src/agents/error-detail.ts"() {
|
|
983
1016
|
"use strict";
|
|
984
1017
|
NODE_VERSION_FOOTER = /^Node\.js v\d+/i;
|
|
985
1018
|
NESTED_ELECTRON_SUMMARY = "Cursor local agent crashed at Electron startup (nested Chromium / HasCustomHostObject)";
|
|
1019
|
+
HOMEBREW_LIBUV_SUMMARY = "Cursor runner crashed in Node (Homebrew Node + shared libuv). Install Node 22 LTS (`brew install node@22`) and retry.";
|
|
986
1020
|
MINIFIED_DUMP_SUMMARY = "Cursor local agent crashed during startup (truncated crash dump)";
|
|
987
1021
|
}
|
|
988
1022
|
});
|
|
@@ -5007,7 +5041,7 @@ function coordinatorTurnReminder(opts) {
|
|
|
5007
5041
|
goal ? `- Goal / title: ${goal}` : null,
|
|
5008
5042
|
accountDefaultsPlaybookLine(),
|
|
5009
5043
|
`- For "what's going on": call list_threads (and list_workspaces if needed). Summarize fleet status \u2014 do not ls/git-status this synthetic home.`,
|
|
5010
|
-
"- Existing repo: create_thread on a repoPath \u2192 send_to_thread \u2192 wait_for_turn. Commit/push/draft PR with ask_git on the child, then wait_for_turn \u2014 never git/gh from this cwd. Call ask_git merge only if the user explicitly asked to merge.",
|
|
5044
|
+
"- Existing repo: create_thread on a repoPath \u2192 send_to_thread \u2192 wait_for_turn. If status is error, lastError/text is the failure \u2014 adapt (switch agent, tell the user). Commit/push/draft PR with ask_git on the child, then wait_for_turn \u2014 never git/gh from this cwd. Call ask_git merge only if the user explicitly asked to merge.",
|
|
5011
5045
|
"- New repo: Bash (clone or gh repo create under ~/sideboard/repos/<name>) \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 ask_git create-draft.",
|
|
5012
5046
|
"- When naming threads for the user, link them as `[Title](sideboard://thread/<id>)`.",
|
|
5013
5047
|
"- If they will wait on Slack or leave the Mac, call set_caffeinate enabled=true. When they say they are done / wrapping up / going to sleep, call set_caffeinate enabled=false. Closing this chat also turns it off."
|
|
@@ -5130,7 +5164,7 @@ var init_coordinator_prompt = __esm({
|
|
|
5130
5164
|
"- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
|
|
5131
5165
|
"- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
|
|
5132
5166
|
"- send_to_thread \u2014 queue a prompt (start/continue a chat turn); pass force_stop: true to interrupt mid-turn / clear stale queued prompts before replacing with a new request",
|
|
5133
|
-
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply",
|
|
5167
|
+
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success.",
|
|
5134
5168
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
5135
5169
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
5136
5170
|
"Setup / run:",
|
|
@@ -6046,6 +6080,55 @@ var init_profile = __esm({
|
|
|
6046
6080
|
}
|
|
6047
6081
|
});
|
|
6048
6082
|
|
|
6083
|
+
// src/agents/packaged-runtime.ts
|
|
6084
|
+
function electronResourcesPath() {
|
|
6085
|
+
const resources = process.resourcesPath;
|
|
6086
|
+
if (typeof resources !== "string" || !resources) return null;
|
|
6087
|
+
return resources;
|
|
6088
|
+
}
|
|
6089
|
+
function packagedCursorRuntimeDir() {
|
|
6090
|
+
const resources = electronResourcesPath();
|
|
6091
|
+
if (!resources) return null;
|
|
6092
|
+
const dir = (0, import_node_path19.join)(resources, "cursor-runtime");
|
|
6093
|
+
if (!(0, import_node_fs18.existsSync)((0, import_node_path19.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
|
|
6094
|
+
return dir;
|
|
6095
|
+
}
|
|
6096
|
+
function packagedCursorRunnerPath() {
|
|
6097
|
+
const dir = packagedCursorRuntimeDir();
|
|
6098
|
+
return dir ? (0, import_node_path19.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
|
|
6099
|
+
}
|
|
6100
|
+
function packagedMcpDir() {
|
|
6101
|
+
const resources = electronResourcesPath();
|
|
6102
|
+
if (!resources) return null;
|
|
6103
|
+
const dir = (0, import_node_path19.join)(resources, "sideboard-mcp");
|
|
6104
|
+
if (!(0, import_node_fs18.existsSync)((0, import_node_path19.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
|
|
6105
|
+
return dir;
|
|
6106
|
+
}
|
|
6107
|
+
function packagedMcpStdioPath() {
|
|
6108
|
+
const dir = packagedMcpDir();
|
|
6109
|
+
return dir ? (0, import_node_path19.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
|
|
6110
|
+
}
|
|
6111
|
+
function packagedBundledNodePath() {
|
|
6112
|
+
const resources = electronResourcesPath();
|
|
6113
|
+
if (!resources) return null;
|
|
6114
|
+
const bin = (0, import_node_path19.join)(resources, "node", "bin", "node");
|
|
6115
|
+
if (!(0, import_node_fs18.existsSync)(bin)) return null;
|
|
6116
|
+
return bin;
|
|
6117
|
+
}
|
|
6118
|
+
function packagedCursorRipgrepCandidate(platformPkg, binName) {
|
|
6119
|
+
const dir = packagedCursorRuntimeDir();
|
|
6120
|
+
if (!dir) return null;
|
|
6121
|
+
return (0, import_node_path19.join)(dir, "node_modules", platformPkg, "bin", binName);
|
|
6122
|
+
}
|
|
6123
|
+
var import_node_fs18, import_node_path19;
|
|
6124
|
+
var init_packaged_runtime = __esm({
|
|
6125
|
+
"src/agents/packaged-runtime.ts"() {
|
|
6126
|
+
"use strict";
|
|
6127
|
+
import_node_fs18 = require("fs");
|
|
6128
|
+
import_node_path19 = require("path");
|
|
6129
|
+
}
|
|
6130
|
+
});
|
|
6131
|
+
|
|
6049
6132
|
// src/agents/node-launch.ts
|
|
6050
6133
|
function isAsarPath(filePath) {
|
|
6051
6134
|
if (/\.asar\.unpacked([/\\]|$)/.test(filePath)) return false;
|
|
@@ -6055,24 +6138,129 @@ function unpackedAsarPath(filePath) {
|
|
|
6055
6138
|
if (!isAsarPath(filePath)) return null;
|
|
6056
6139
|
const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
|
|
6057
6140
|
if (unpacked === filePath) return null;
|
|
6058
|
-
return (0,
|
|
6141
|
+
return (0, import_node_fs19.existsSync)(unpacked) ? unpacked : null;
|
|
6059
6142
|
}
|
|
6060
6143
|
function nodeReadableScriptPath(scriptPath) {
|
|
6061
6144
|
return unpackedAsarPath(scriptPath) ?? scriptPath;
|
|
6062
6145
|
}
|
|
6063
|
-
|
|
6064
|
-
const
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
|
|
6070
|
-
|
|
6146
|
+
function parseNodeMajor(version) {
|
|
6147
|
+
const match = /^v?(\d+)/.exec(version.trim());
|
|
6148
|
+
if (!match) return null;
|
|
6149
|
+
const major = Number(match[1]);
|
|
6150
|
+
return Number.isInteger(major) ? major : null;
|
|
6151
|
+
}
|
|
6152
|
+
function scoreNodeForAgentRuntime(candidate) {
|
|
6153
|
+
const major = parseNodeMajor(candidate.version);
|
|
6154
|
+
if (major == null) return Number.NEGATIVE_INFINITY;
|
|
6155
|
+
if (major < 20) return major - 100;
|
|
6156
|
+
const posix = candidate.path.replace(/\\/g, "/");
|
|
6157
|
+
let score = 0;
|
|
6158
|
+
if (major % 2 === 0) {
|
|
6159
|
+
score += 1e3 + major * 10;
|
|
6160
|
+
} else {
|
|
6161
|
+
score += major;
|
|
6162
|
+
}
|
|
6163
|
+
if (/\/Cellar\/node\/\d/.test(posix) && !/\/Cellar\/node@\d+/.test(posix)) {
|
|
6164
|
+
score -= 50;
|
|
6165
|
+
}
|
|
6166
|
+
return score;
|
|
6167
|
+
}
|
|
6168
|
+
function pickPreferredNode(candidates) {
|
|
6169
|
+
let best = null;
|
|
6170
|
+
let bestScore = Number.NEGATIVE_INFINITY;
|
|
6171
|
+
for (const candidate of candidates) {
|
|
6172
|
+
const score = scoreNodeForAgentRuntime(candidate);
|
|
6173
|
+
if (score > bestScore) {
|
|
6174
|
+
bestScore = score;
|
|
6175
|
+
best = candidate;
|
|
6176
|
+
}
|
|
6177
|
+
}
|
|
6178
|
+
return best;
|
|
6179
|
+
}
|
|
6180
|
+
function versionDirNodeBins(root, toBin) {
|
|
6181
|
+
if (!(0, import_node_fs19.existsSync)(root)) return [];
|
|
6182
|
+
try {
|
|
6183
|
+
return (0, import_node_fs19.readdirSync)(root).map(toBin);
|
|
6184
|
+
} catch {
|
|
6185
|
+
return [];
|
|
6186
|
+
}
|
|
6187
|
+
}
|
|
6188
|
+
function defaultNodeBinCandidates(home = (0, import_node_os7.homedir)()) {
|
|
6189
|
+
const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
|
|
6190
|
+
(prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path20.join)(prefix, "opt", `node@${major}`, "bin", "node"))
|
|
6191
|
+
);
|
|
6192
|
+
return [
|
|
6193
|
+
...kegs,
|
|
6194
|
+
"/opt/homebrew/bin/node",
|
|
6195
|
+
"/usr/local/bin/node",
|
|
6196
|
+
(0, import_node_path20.join)(home, ".local/share/fnm/aliases/default/bin/node"),
|
|
6197
|
+
(0, import_node_path20.join)(home, ".nvm/current/bin/node"),
|
|
6198
|
+
(0, import_node_path20.join)(home, ".volta/bin/node"),
|
|
6199
|
+
(0, import_node_path20.join)(home, ".asdf/shims/node"),
|
|
6200
|
+
(0, import_node_path20.join)(home, ".local/share/mise/shims/node"),
|
|
6201
|
+
...versionDirNodeBins(
|
|
6202
|
+
(0, import_node_path20.join)(home, ".nvm", "versions", "node"),
|
|
6203
|
+
(name) => (0, import_node_path20.join)(home, ".nvm", "versions", "node", name, "bin", "node")
|
|
6204
|
+
),
|
|
6205
|
+
...versionDirNodeBins(
|
|
6206
|
+
(0, import_node_path20.join)(home, ".local/share/fnm", "node-versions"),
|
|
6207
|
+
(name) => (0, import_node_path20.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
|
|
6208
|
+
),
|
|
6209
|
+
...versionDirNodeBins(
|
|
6210
|
+
(0, import_node_path20.join)(home, ".volta", "tools", "image", "node"),
|
|
6211
|
+
(name) => (0, import_node_path20.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
|
|
6212
|
+
)
|
|
6071
6213
|
];
|
|
6072
|
-
|
|
6073
|
-
|
|
6214
|
+
}
|
|
6215
|
+
function uniqueExistingNodeBins(paths) {
|
|
6216
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6217
|
+
const out = [];
|
|
6218
|
+
for (const raw of paths) {
|
|
6219
|
+
const p = raw.trim();
|
|
6220
|
+
if (!p || !(0, import_node_fs19.existsSync)(p) || isElectronLikeCommand(p)) continue;
|
|
6221
|
+
let key = p;
|
|
6222
|
+
try {
|
|
6223
|
+
key = (0, import_node_fs19.realpathSync)(p);
|
|
6224
|
+
} catch {
|
|
6225
|
+
continue;
|
|
6226
|
+
}
|
|
6227
|
+
if (seen.has(key)) continue;
|
|
6228
|
+
seen.add(key);
|
|
6229
|
+
out.push(p);
|
|
6074
6230
|
}
|
|
6075
|
-
return
|
|
6231
|
+
return out;
|
|
6232
|
+
}
|
|
6233
|
+
async function whichAllNode() {
|
|
6234
|
+
if (process.platform === "win32") {
|
|
6235
|
+
const located = await run("where", ["node"], { reject: false, timeoutMs: 5e3 });
|
|
6236
|
+
if (located.exitCode !== 0) return [];
|
|
6237
|
+
return located.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
6238
|
+
}
|
|
6239
|
+
const all = await run("which", ["-a", "node"], { reject: false, timeoutMs: 5e3 });
|
|
6240
|
+
if (all.exitCode === 0 && all.stdout.trim()) {
|
|
6241
|
+
return all.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
6242
|
+
}
|
|
6243
|
+
const single = await run("which", ["node"], { reject: false, timeoutMs: 5e3 });
|
|
6244
|
+
if (single.exitCode !== 0 || !single.stdout.trim()) return [];
|
|
6245
|
+
return [single.stdout.trim()];
|
|
6246
|
+
}
|
|
6247
|
+
async function probeNodeVersion(bin) {
|
|
6248
|
+
const probed = await run(bin, ["-v"], { reject: false, timeoutMs: 4e3 });
|
|
6249
|
+
if (probed.exitCode !== 0) return null;
|
|
6250
|
+
const version = probed.stdout.trim().split(/\r?\n/).find(Boolean);
|
|
6251
|
+
return version || null;
|
|
6252
|
+
}
|
|
6253
|
+
async function findSystemNode() {
|
|
6254
|
+
const fromPath = await whichAllNode();
|
|
6255
|
+
const bins = uniqueExistingNodeBins([...fromPath, ...defaultNodeBinCandidates()]);
|
|
6256
|
+
if (bins.length === 0) return null;
|
|
6257
|
+
const probed = await Promise.all(
|
|
6258
|
+
bins.map(async (path) => {
|
|
6259
|
+
const version = await probeNodeVersion(path);
|
|
6260
|
+
return version ? { path, version } : null;
|
|
6261
|
+
})
|
|
6262
|
+
);
|
|
6263
|
+
return pickPreferredNode(probed.filter((c) => c != null));
|
|
6076
6264
|
}
|
|
6077
6265
|
function applyNodeLaunch(launch, args) {
|
|
6078
6266
|
const readableArgs = args.map(nodeReadableScriptPath);
|
|
@@ -6090,9 +6278,13 @@ function applyNodeLaunch(launch, args) {
|
|
|
6090
6278
|
async function resolveNodeLaunch(scriptPath) {
|
|
6091
6279
|
const script = nodeReadableScriptPath(scriptPath);
|
|
6092
6280
|
if (!isAsarPath(script)) {
|
|
6093
|
-
const
|
|
6094
|
-
if (
|
|
6095
|
-
return { file:
|
|
6281
|
+
const bundled = packagedBundledNodePath();
|
|
6282
|
+
if (bundled && !isElectronLikeCommand(bundled)) {
|
|
6283
|
+
return { file: bundled, env: {} };
|
|
6284
|
+
}
|
|
6285
|
+
const node = await findSystemNode();
|
|
6286
|
+
if (node) {
|
|
6287
|
+
return { file: node.path, env: {}, nodeVersion: node.version };
|
|
6096
6288
|
}
|
|
6097
6289
|
}
|
|
6098
6290
|
return {
|
|
@@ -6100,61 +6292,17 @@ async function resolveNodeLaunch(scriptPath) {
|
|
|
6100
6292
|
env: { ELECTRON_RUN_AS_NODE: "1" }
|
|
6101
6293
|
};
|
|
6102
6294
|
}
|
|
6103
|
-
var
|
|
6295
|
+
var import_node_fs19, import_node_os7, import_node_path20, PREFERRED_LTS_MAJORS;
|
|
6104
6296
|
var init_node_launch = __esm({
|
|
6105
6297
|
"src/agents/node-launch.ts"() {
|
|
6106
6298
|
"use strict";
|
|
6107
|
-
|
|
6299
|
+
import_node_fs19 = require("fs");
|
|
6108
6300
|
import_node_os7 = require("os");
|
|
6109
|
-
|
|
6301
|
+
import_node_path20 = require("path");
|
|
6110
6302
|
init_nested_electron_env();
|
|
6111
6303
|
init_run();
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
"/usr/local/bin/node"
|
|
6115
|
-
];
|
|
6116
|
-
}
|
|
6117
|
-
});
|
|
6118
|
-
|
|
6119
|
-
// src/agents/packaged-runtime.ts
|
|
6120
|
-
function electronResourcesPath() {
|
|
6121
|
-
const resources = process.resourcesPath;
|
|
6122
|
-
if (typeof resources !== "string" || !resources) return null;
|
|
6123
|
-
return resources;
|
|
6124
|
-
}
|
|
6125
|
-
function packagedCursorRuntimeDir() {
|
|
6126
|
-
const resources = electronResourcesPath();
|
|
6127
|
-
if (!resources) return null;
|
|
6128
|
-
const dir = (0, import_node_path20.join)(resources, "cursor-runtime");
|
|
6129
|
-
if (!(0, import_node_fs19.existsSync)((0, import_node_path20.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
|
|
6130
|
-
return dir;
|
|
6131
|
-
}
|
|
6132
|
-
function packagedCursorRunnerPath() {
|
|
6133
|
-
const dir = packagedCursorRuntimeDir();
|
|
6134
|
-
return dir ? (0, import_node_path20.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
|
|
6135
|
-
}
|
|
6136
|
-
function packagedMcpDir() {
|
|
6137
|
-
const resources = electronResourcesPath();
|
|
6138
|
-
if (!resources) return null;
|
|
6139
|
-
const dir = (0, import_node_path20.join)(resources, "sideboard-mcp");
|
|
6140
|
-
if (!(0, import_node_fs19.existsSync)((0, import_node_path20.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
|
|
6141
|
-
return dir;
|
|
6142
|
-
}
|
|
6143
|
-
function packagedMcpStdioPath() {
|
|
6144
|
-
const dir = packagedMcpDir();
|
|
6145
|
-
return dir ? (0, import_node_path20.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
|
|
6146
|
-
}
|
|
6147
|
-
function packagedCursorRipgrepCandidate(platformPkg, binName) {
|
|
6148
|
-
const dir = packagedCursorRuntimeDir();
|
|
6149
|
-
if (!dir) return null;
|
|
6150
|
-
return (0, import_node_path20.join)(dir, "node_modules", platformPkg, "bin", binName);
|
|
6151
|
-
}
|
|
6152
|
-
var import_node_fs19, import_node_path20;
|
|
6153
|
-
var init_packaged_runtime = __esm({
|
|
6154
|
-
"src/agents/packaged-runtime.ts"() {
|
|
6155
|
-
"use strict";
|
|
6156
|
-
import_node_fs19 = require("fs");
|
|
6157
|
-
import_node_path20 = require("path");
|
|
6304
|
+
init_packaged_runtime();
|
|
6305
|
+
PREFERRED_LTS_MAJORS = [24, 22, 20];
|
|
6158
6306
|
}
|
|
6159
6307
|
});
|
|
6160
6308
|
|
|
@@ -8644,40 +8792,40 @@ __export(plan_file_exports, {
|
|
|
8644
8792
|
writePlanFile: () => writePlanFile
|
|
8645
8793
|
});
|
|
8646
8794
|
function ensureAttachmentsGitignore2(worktreePath) {
|
|
8647
|
-
const gitignoreAbs = (0,
|
|
8648
|
-
if ((0,
|
|
8649
|
-
(0,
|
|
8650
|
-
(0,
|
|
8795
|
+
const gitignoreAbs = (0, import_node_path36.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
8796
|
+
if ((0, import_node_fs39.existsSync)(gitignoreAbs)) return;
|
|
8797
|
+
(0, import_node_fs39.mkdirSync)((0, import_node_path36.dirname)(gitignoreAbs), { recursive: true });
|
|
8798
|
+
(0, import_node_fs39.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
8651
8799
|
}
|
|
8652
8800
|
function planFileAbs(worktreePath) {
|
|
8653
|
-
return (0,
|
|
8801
|
+
return (0, import_node_path36.join)(worktreePath, PLAN_FILE_REL);
|
|
8654
8802
|
}
|
|
8655
8803
|
function readTextIfPresent2(abs) {
|
|
8656
|
-
if (!(0,
|
|
8804
|
+
if (!(0, import_node_fs39.existsSync)(abs)) return null;
|
|
8657
8805
|
try {
|
|
8658
|
-
const content = (0,
|
|
8806
|
+
const content = (0, import_node_fs39.readFileSync)(abs, "utf8");
|
|
8659
8807
|
return content.trim() ? content : null;
|
|
8660
8808
|
} catch {
|
|
8661
8809
|
return null;
|
|
8662
8810
|
}
|
|
8663
8811
|
}
|
|
8664
8812
|
function readPlanFile(worktreePath) {
|
|
8665
|
-
return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0,
|
|
8813
|
+
return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path36.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path36.join)(worktreePath, LEGACY_PLAN_FILE_REL));
|
|
8666
8814
|
}
|
|
8667
8815
|
function writePlanFile(worktreePath, content) {
|
|
8668
8816
|
ensureAttachmentsGitignore2(worktreePath);
|
|
8669
8817
|
const abs = planFileAbs(worktreePath);
|
|
8670
|
-
(0,
|
|
8818
|
+
(0, import_node_fs39.mkdirSync)((0, import_node_path36.dirname)(abs), { recursive: true });
|
|
8671
8819
|
const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
|
|
8672
|
-
(0,
|
|
8820
|
+
(0, import_node_fs39.writeFileSync)(abs, body, "utf8");
|
|
8673
8821
|
return PLAN_FILE_REL;
|
|
8674
8822
|
}
|
|
8675
|
-
var
|
|
8823
|
+
var import_node_fs39, import_node_path36;
|
|
8676
8824
|
var init_plan_file = __esm({
|
|
8677
8825
|
"src/plan/plan-file.ts"() {
|
|
8678
8826
|
"use strict";
|
|
8679
|
-
|
|
8680
|
-
|
|
8827
|
+
import_node_fs39 = require("fs");
|
|
8828
|
+
import_node_path36 = require("path");
|
|
8681
8829
|
init_workspace_scratch();
|
|
8682
8830
|
init_plan_present();
|
|
8683
8831
|
init_plan_present();
|
|
@@ -8698,7 +8846,7 @@ function setCaffeinateHoldHooks(next) {
|
|
|
8698
8846
|
hooks = next;
|
|
8699
8847
|
}
|
|
8700
8848
|
function caffeinateHoldPath() {
|
|
8701
|
-
return (0,
|
|
8849
|
+
return (0, import_node_path37.join)(appDataDir(), "caffeinate-hold.json");
|
|
8702
8850
|
}
|
|
8703
8851
|
function processAlive(pid) {
|
|
8704
8852
|
if (hooks.processAlive) return hooks.processAlive(pid);
|
|
@@ -8732,9 +8880,9 @@ function uniqueIds(ids) {
|
|
|
8732
8880
|
}
|
|
8733
8881
|
function readHold() {
|
|
8734
8882
|
const path = caffeinateHoldPath();
|
|
8735
|
-
if (!(0,
|
|
8883
|
+
if (!(0, import_node_fs40.existsSync)(path)) return null;
|
|
8736
8884
|
try {
|
|
8737
|
-
const parsed = JSON.parse((0,
|
|
8885
|
+
const parsed = JSON.parse((0, import_node_fs40.readFileSync)(path, "utf8"));
|
|
8738
8886
|
if (typeof parsed?.pid === "number" && parsed.pid > 0) {
|
|
8739
8887
|
return {
|
|
8740
8888
|
pid: parsed.pid,
|
|
@@ -8756,7 +8904,7 @@ function writeHold(pid, threadIds) {
|
|
|
8756
8904
|
}
|
|
8757
8905
|
function clearHold() {
|
|
8758
8906
|
try {
|
|
8759
|
-
(0,
|
|
8907
|
+
(0, import_node_fs40.unlinkSync)(caffeinateHoldPath());
|
|
8760
8908
|
} catch {
|
|
8761
8909
|
}
|
|
8762
8910
|
}
|
|
@@ -8841,13 +8989,13 @@ function releaseCaffeinateHoldForThread(threadId) {
|
|
|
8841
8989
|
}
|
|
8842
8990
|
return setCaffeinateHold(false, { threadId: id });
|
|
8843
8991
|
}
|
|
8844
|
-
var import_node_child_process4,
|
|
8992
|
+
var import_node_child_process4, import_node_fs40, import_node_path37, hooks;
|
|
8845
8993
|
var init_caffeinate_hold = __esm({
|
|
8846
8994
|
"src/store/caffeinate-hold.ts"() {
|
|
8847
8995
|
"use strict";
|
|
8848
8996
|
import_node_child_process4 = require("child_process");
|
|
8849
|
-
|
|
8850
|
-
|
|
8997
|
+
import_node_fs40 = require("fs");
|
|
8998
|
+
import_node_path37 = require("path");
|
|
8851
8999
|
init_paths();
|
|
8852
9000
|
init_private_file();
|
|
8853
9001
|
hooks = {};
|
|
@@ -8862,10 +9010,10 @@ __export(cursor_recover_exports, {
|
|
|
8862
9010
|
function recoverFinishedCursorRun(opts) {
|
|
8863
9011
|
const agentId = opts.agentId.trim();
|
|
8864
9012
|
if (!agentId) return null;
|
|
8865
|
-
const runsPath = (0,
|
|
8866
|
-
if (!(0,
|
|
9013
|
+
const runsPath = (0, import_node_path38.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
|
|
9014
|
+
if (!(0, import_node_fs41.existsSync)(runsPath)) return null;
|
|
8867
9015
|
try {
|
|
8868
|
-
const lines = (0,
|
|
9016
|
+
const lines = (0, import_node_fs41.readFileSync)(runsPath, "utf8").split("\n");
|
|
8869
9017
|
let best = null;
|
|
8870
9018
|
for (const line of lines) {
|
|
8871
9019
|
const trimmed = line.trim();
|
|
@@ -8891,12 +9039,12 @@ function recoverFinishedCursorRun(opts) {
|
|
|
8891
9039
|
return null;
|
|
8892
9040
|
}
|
|
8893
9041
|
}
|
|
8894
|
-
var
|
|
9042
|
+
var import_node_fs41, import_node_path38;
|
|
8895
9043
|
var init_cursor_recover = __esm({
|
|
8896
9044
|
"src/agents/cursor-recover.ts"() {
|
|
8897
9045
|
"use strict";
|
|
8898
|
-
|
|
8899
|
-
|
|
9046
|
+
import_node_fs41 = require("fs");
|
|
9047
|
+
import_node_path38 = require("path");
|
|
8900
9048
|
init_paths();
|
|
8901
9049
|
}
|
|
8902
9050
|
});
|
|
@@ -8908,7 +9056,7 @@ init_nested_electron_env();
|
|
|
8908
9056
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
8909
9057
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
8910
9058
|
var import_zod3 = require("zod");
|
|
8911
|
-
var
|
|
9059
|
+
var import_node_path39 = require("path");
|
|
8912
9060
|
|
|
8913
9061
|
// src/orchestrator/orchestrator.ts
|
|
8914
9062
|
var import_node_events = require("events");
|
|
@@ -9419,7 +9567,7 @@ async function refreshSlackReplyBadges(opts) {
|
|
|
9419
9567
|
}
|
|
9420
9568
|
|
|
9421
9569
|
// src/orchestrator/orchestrator.ts
|
|
9422
|
-
var
|
|
9570
|
+
var import_node_fs42 = require("fs");
|
|
9423
9571
|
init_error_detail();
|
|
9424
9572
|
|
|
9425
9573
|
// src/agents/spawn.ts
|
|
@@ -10536,8 +10684,44 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
10536
10684
|
// src/orchestrator/orchestrator.ts
|
|
10537
10685
|
init_thread_store();
|
|
10538
10686
|
|
|
10539
|
-
// src/
|
|
10687
|
+
// src/store/desktop-host.ts
|
|
10540
10688
|
var import_node_fs30 = require("fs");
|
|
10689
|
+
var import_node_path29 = require("path");
|
|
10690
|
+
init_paths();
|
|
10691
|
+
function desktopHostPidPath() {
|
|
10692
|
+
return (0, import_node_path29.join)(appDataDir(), "desktop-host.pid");
|
|
10693
|
+
}
|
|
10694
|
+
function readDesktopHostPid() {
|
|
10695
|
+
try {
|
|
10696
|
+
const pid = Number.parseInt((0, import_node_fs30.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
|
|
10697
|
+
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
10698
|
+
return pid;
|
|
10699
|
+
} catch {
|
|
10700
|
+
return null;
|
|
10701
|
+
}
|
|
10702
|
+
}
|
|
10703
|
+
function pidAlive(pid) {
|
|
10704
|
+
try {
|
|
10705
|
+
process.kill(pid, 0);
|
|
10706
|
+
return true;
|
|
10707
|
+
} catch {
|
|
10708
|
+
return false;
|
|
10709
|
+
}
|
|
10710
|
+
}
|
|
10711
|
+
function isDesktopHostAlive() {
|
|
10712
|
+
const pid = readDesktopHostPid();
|
|
10713
|
+
return pid != null && pidAlive(pid);
|
|
10714
|
+
}
|
|
10715
|
+
function isThisProcessDesktopHost() {
|
|
10716
|
+
return readDesktopHostPid() === process.pid && pidAlive(process.pid);
|
|
10717
|
+
}
|
|
10718
|
+
function thisProcessShouldDrainAgentQueues() {
|
|
10719
|
+
if (isThisProcessDesktopHost()) return true;
|
|
10720
|
+
return !isDesktopHostAlive();
|
|
10721
|
+
}
|
|
10722
|
+
|
|
10723
|
+
// src/threads/create.ts
|
|
10724
|
+
var import_node_fs31 = require("fs");
|
|
10541
10725
|
|
|
10542
10726
|
// src/detect/detect.ts
|
|
10543
10727
|
init_agents();
|
|
@@ -10582,7 +10766,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
10582
10766
|
});
|
|
10583
10767
|
await requireAgent(resolved.agent);
|
|
10584
10768
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
10585
|
-
if (!(0,
|
|
10769
|
+
if (!(0, import_node_fs31.existsSync)(repoPath)) {
|
|
10586
10770
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
10587
10771
|
}
|
|
10588
10772
|
let sourceRef = input.sourceRef;
|
|
@@ -11058,8 +11242,8 @@ function forkChatTab(input) {
|
|
|
11058
11242
|
|
|
11059
11243
|
// src/review/request-review.ts
|
|
11060
11244
|
var import_node_crypto5 = require("crypto");
|
|
11061
|
-
var
|
|
11062
|
-
var
|
|
11245
|
+
var import_node_fs32 = require("fs");
|
|
11246
|
+
var import_node_path30 = require("path");
|
|
11063
11247
|
init_global_workspace();
|
|
11064
11248
|
init_thread_store();
|
|
11065
11249
|
|
|
@@ -11207,22 +11391,22 @@ function shouldRefreshReviewRequestTemplate(content) {
|
|
|
11207
11391
|
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
11208
11392
|
}
|
|
11209
11393
|
function readTextIfPresent(abs) {
|
|
11210
|
-
if (!(0,
|
|
11394
|
+
if (!(0, import_node_fs32.existsSync)(abs)) return null;
|
|
11211
11395
|
try {
|
|
11212
|
-
const content = (0,
|
|
11396
|
+
const content = (0, import_node_fs32.readFileSync)(abs, "utf8");
|
|
11213
11397
|
return content.trim() ? content : null;
|
|
11214
11398
|
} catch {
|
|
11215
11399
|
return null;
|
|
11216
11400
|
}
|
|
11217
11401
|
}
|
|
11218
11402
|
function ensureAttachmentsGitignore(worktreePath) {
|
|
11219
|
-
const gitignoreAbs = (0,
|
|
11220
|
-
if ((0,
|
|
11221
|
-
(0,
|
|
11222
|
-
(0,
|
|
11403
|
+
const gitignoreAbs = (0, import_node_path30.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
11404
|
+
if ((0, import_node_fs32.existsSync)(gitignoreAbs)) return;
|
|
11405
|
+
(0, import_node_fs32.mkdirSync)((0, import_node_path30.dirname)(gitignoreAbs), { recursive: true });
|
|
11406
|
+
(0, import_node_fs32.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
11223
11407
|
}
|
|
11224
11408
|
function resolveReviewGuidelines(worktreePath) {
|
|
11225
|
-
const repoAbs = (0,
|
|
11409
|
+
const repoAbs = (0, import_node_path30.join)(worktreePath, REPO_REVIEW_PATH);
|
|
11226
11410
|
const repoContent = readTextIfPresent(repoAbs);
|
|
11227
11411
|
if (repoContent) {
|
|
11228
11412
|
return {
|
|
@@ -11232,7 +11416,7 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
11232
11416
|
source: "repo"
|
|
11233
11417
|
};
|
|
11234
11418
|
}
|
|
11235
|
-
const localAbs = (0,
|
|
11419
|
+
const localAbs = (0, import_node_path30.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
11236
11420
|
const localContent = readTextIfPresent(localAbs);
|
|
11237
11421
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
11238
11422
|
return {
|
|
@@ -11242,7 +11426,7 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
11242
11426
|
source: "local"
|
|
11243
11427
|
};
|
|
11244
11428
|
}
|
|
11245
|
-
const legacyAbs = (0,
|
|
11429
|
+
const legacyAbs = (0, import_node_path30.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
|
|
11246
11430
|
const legacyContent = readTextIfPresent(legacyAbs);
|
|
11247
11431
|
if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
|
|
11248
11432
|
return {
|
|
@@ -11253,8 +11437,8 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
11253
11437
|
};
|
|
11254
11438
|
}
|
|
11255
11439
|
ensureAttachmentsGitignore(worktreePath);
|
|
11256
|
-
(0,
|
|
11257
|
-
(0,
|
|
11440
|
+
(0, import_node_fs32.mkdirSync)((0, import_node_path30.dirname)(localAbs), { recursive: true });
|
|
11441
|
+
(0, import_node_fs32.writeFileSync)(localAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
|
|
11258
11442
|
return {
|
|
11259
11443
|
path: REVIEW_REQUEST_PATH,
|
|
11260
11444
|
name: REVIEW_REQUEST_NAME,
|
|
@@ -11454,21 +11638,21 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
|
|
|
11454
11638
|
|
|
11455
11639
|
// src/threads/adopt.ts
|
|
11456
11640
|
var import_node_child_process3 = require("child_process");
|
|
11457
|
-
var
|
|
11641
|
+
var import_node_fs33 = require("fs");
|
|
11458
11642
|
var import_node_os10 = require("os");
|
|
11459
|
-
var
|
|
11643
|
+
var import_node_path31 = require("path");
|
|
11460
11644
|
var import_node_module4 = require("module");
|
|
11461
11645
|
init_worktree();
|
|
11462
11646
|
init_thread_store();
|
|
11463
11647
|
var import_meta4 = {};
|
|
11464
|
-
var CONDUCTOR_APP_SUPPORT = (0,
|
|
11648
|
+
var CONDUCTOR_APP_SUPPORT = (0, import_node_path31.join)(
|
|
11465
11649
|
process.env.HOME ?? "",
|
|
11466
11650
|
"Library",
|
|
11467
11651
|
"Application Support",
|
|
11468
11652
|
"com.conductor.app"
|
|
11469
11653
|
);
|
|
11470
|
-
var CONDUCTOR_DB = (0,
|
|
11471
|
-
var CURSOR_SDK_STORE = (0,
|
|
11654
|
+
var CONDUCTOR_DB = (0, import_node_path31.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
11655
|
+
var CURSOR_SDK_STORE = (0, import_node_path31.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
11472
11656
|
function openReadonlySqlite(file) {
|
|
11473
11657
|
const req = (0, import_node_module4.createRequire)(import_meta4.url);
|
|
11474
11658
|
const Database = req("better-sqlite3");
|
|
@@ -11485,21 +11669,21 @@ function mapAgentType(raw) {
|
|
|
11485
11669
|
return null;
|
|
11486
11670
|
}
|
|
11487
11671
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
11488
|
-
if (!workspacePath || !(0,
|
|
11672
|
+
if (!workspacePath || !(0, import_node_fs33.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
11489
11673
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
11490
11674
|
let best = null;
|
|
11491
11675
|
let hashes;
|
|
11492
11676
|
try {
|
|
11493
|
-
hashes = (0,
|
|
11677
|
+
hashes = (0, import_node_fs33.readdirSync)(CURSOR_SDK_STORE);
|
|
11494
11678
|
} catch {
|
|
11495
11679
|
return null;
|
|
11496
11680
|
}
|
|
11497
11681
|
for (const hash of hashes) {
|
|
11498
|
-
const agentsFile = (0,
|
|
11499
|
-
if (!(0,
|
|
11682
|
+
const agentsFile = (0, import_node_path31.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
11683
|
+
if (!(0, import_node_fs33.existsSync)(agentsFile)) continue;
|
|
11500
11684
|
let text3;
|
|
11501
11685
|
try {
|
|
11502
|
-
text3 = (0,
|
|
11686
|
+
text3 = (0, import_node_fs33.readFileSync)(agentsFile, "utf8");
|
|
11503
11687
|
} catch {
|
|
11504
11688
|
continue;
|
|
11505
11689
|
}
|
|
@@ -11523,7 +11707,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
11523
11707
|
return best?.agentId ?? null;
|
|
11524
11708
|
}
|
|
11525
11709
|
async function adoptThread(input) {
|
|
11526
|
-
if (!(0,
|
|
11710
|
+
if (!(0, import_node_fs33.existsSync)(input.worktreePath)) {
|
|
11527
11711
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
11528
11712
|
}
|
|
11529
11713
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -11547,18 +11731,18 @@ async function adoptThread(input) {
|
|
|
11547
11731
|
return thread;
|
|
11548
11732
|
}
|
|
11549
11733
|
function listConductorWorkspaces() {
|
|
11550
|
-
if (!(0,
|
|
11734
|
+
if (!(0, import_node_fs33.existsSync)(CONDUCTOR_DB)) {
|
|
11551
11735
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
11552
11736
|
}
|
|
11553
|
-
const tmp = (0,
|
|
11554
|
-
const snapshot = (0,
|
|
11737
|
+
const tmp = (0, import_node_fs33.mkdtempSync)((0, import_node_path31.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
|
|
11738
|
+
const snapshot = (0, import_node_path31.join)(tmp, "conductor.db");
|
|
11555
11739
|
try {
|
|
11556
|
-
(0,
|
|
11740
|
+
(0, import_node_fs33.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
11557
11741
|
for (const suffix of ["-wal", "-shm"]) {
|
|
11558
11742
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
11559
|
-
if ((0,
|
|
11743
|
+
if ((0, import_node_fs33.existsSync)(src)) {
|
|
11560
11744
|
try {
|
|
11561
|
-
(0,
|
|
11745
|
+
(0, import_node_fs33.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
11562
11746
|
} catch {
|
|
11563
11747
|
}
|
|
11564
11748
|
}
|
|
@@ -11634,22 +11818,22 @@ function listConductorWorkspaces() {
|
|
|
11634
11818
|
db.close();
|
|
11635
11819
|
}
|
|
11636
11820
|
} finally {
|
|
11637
|
-
(0,
|
|
11821
|
+
(0, import_node_fs33.rmSync)(tmp, { recursive: true, force: true });
|
|
11638
11822
|
}
|
|
11639
11823
|
}
|
|
11640
11824
|
function importConductorWorkspace(workspaceId) {
|
|
11641
|
-
if (!(0,
|
|
11825
|
+
if (!(0, import_node_fs33.existsSync)(CONDUCTOR_DB)) {
|
|
11642
11826
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
11643
11827
|
}
|
|
11644
|
-
const tmp = (0,
|
|
11645
|
-
const snapshot = (0,
|
|
11828
|
+
const tmp = (0, import_node_fs33.mkdtempSync)((0, import_node_path31.join)((0, import_node_os10.tmpdir)(), "sideboard-conductor-"));
|
|
11829
|
+
const snapshot = (0, import_node_path31.join)(tmp, "conductor.db");
|
|
11646
11830
|
try {
|
|
11647
|
-
(0,
|
|
11831
|
+
(0, import_node_fs33.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
11648
11832
|
for (const suffix of ["-wal", "-shm"]) {
|
|
11649
11833
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
11650
|
-
if ((0,
|
|
11834
|
+
if ((0, import_node_fs33.existsSync)(src)) {
|
|
11651
11835
|
try {
|
|
11652
|
-
(0,
|
|
11836
|
+
(0, import_node_fs33.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
11653
11837
|
} catch {
|
|
11654
11838
|
}
|
|
11655
11839
|
}
|
|
@@ -11667,7 +11851,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
11667
11851
|
).get(workspaceId);
|
|
11668
11852
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
11669
11853
|
const worktreePath = String(row.workspacePath);
|
|
11670
|
-
if (!(0,
|
|
11854
|
+
if (!(0, import_node_fs33.existsSync)(worktreePath)) {
|
|
11671
11855
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
11672
11856
|
}
|
|
11673
11857
|
let sessionId = null;
|
|
@@ -11730,7 +11914,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
11730
11914
|
db.close();
|
|
11731
11915
|
}
|
|
11732
11916
|
} finally {
|
|
11733
|
-
(0,
|
|
11917
|
+
(0, import_node_fs33.rmSync)(tmp, { recursive: true, force: true });
|
|
11734
11918
|
}
|
|
11735
11919
|
}
|
|
11736
11920
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
@@ -11738,7 +11922,7 @@ async function importConductorWorkspaceAsync(workspaceId) {
|
|
|
11738
11922
|
}
|
|
11739
11923
|
|
|
11740
11924
|
// src/threads/stack-layers.ts
|
|
11741
|
-
var
|
|
11925
|
+
var import_node_fs34 = require("fs");
|
|
11742
11926
|
init_run();
|
|
11743
11927
|
init_stack();
|
|
11744
11928
|
init_worktree();
|
|
@@ -11806,7 +11990,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
11806
11990
|
let createdWorktree = false;
|
|
11807
11991
|
const trees = await listWorktrees(repoPath);
|
|
11808
11992
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
11809
|
-
if (checkedOut?.path && (0,
|
|
11993
|
+
if (checkedOut?.path && (0, import_node_fs34.existsSync)(checkedOut.path)) {
|
|
11810
11994
|
if (input.reuseExistingWorktree !== false) {
|
|
11811
11995
|
worktreePath = checkedOut.path;
|
|
11812
11996
|
} else {
|
|
@@ -11948,7 +12132,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
11948
12132
|
async function createPrStack(input, onSetupLine) {
|
|
11949
12133
|
await requireAgent(input.agent);
|
|
11950
12134
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
11951
|
-
if (!(0,
|
|
12135
|
+
if (!(0, import_node_fs34.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
11952
12136
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
11953
12137
|
const status = await detectGhStack(repoPath);
|
|
11954
12138
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -12015,7 +12199,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
12015
12199
|
}
|
|
12016
12200
|
}
|
|
12017
12201
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
12018
|
-
if (!claimed.has(bootstrap.worktreePath) && (0,
|
|
12202
|
+
if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs34.existsSync)(bootstrap.worktreePath)) {
|
|
12019
12203
|
try {
|
|
12020
12204
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
12021
12205
|
deleteBranch: bootstrap.branchName
|
|
@@ -12030,12 +12214,12 @@ async function createPrStack(input, onSetupLine) {
|
|
|
12030
12214
|
init_worktree();
|
|
12031
12215
|
|
|
12032
12216
|
// src/diff/diff.ts
|
|
12033
|
-
var
|
|
12034
|
-
var
|
|
12217
|
+
var import_node_fs35 = require("fs");
|
|
12218
|
+
var import_node_path32 = require("path");
|
|
12035
12219
|
init_run();
|
|
12036
12220
|
init_worktree();
|
|
12037
12221
|
async function inspectGitWorktree(worktreePath) {
|
|
12038
|
-
if (!worktreePath || !(0,
|
|
12222
|
+
if (!worktreePath || !(0, import_node_fs35.existsSync)(worktreePath)) return "missing_worktree";
|
|
12039
12223
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
12040
12224
|
reject: false
|
|
12041
12225
|
});
|
|
@@ -12043,7 +12227,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
12043
12227
|
return "ok";
|
|
12044
12228
|
}
|
|
12045
12229
|
async function initializeGitRepository(worktreePath) {
|
|
12046
|
-
if (!worktreePath || !(0,
|
|
12230
|
+
if (!worktreePath || !(0, import_node_fs35.existsSync)(worktreePath)) {
|
|
12047
12231
|
throw new Error("Worktree not found");
|
|
12048
12232
|
}
|
|
12049
12233
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -12179,11 +12363,11 @@ new file mode 100644
|
|
|
12179
12363
|
};
|
|
12180
12364
|
}
|
|
12181
12365
|
async function untrackedPatch(worktreePath, path, maxHunk) {
|
|
12182
|
-
const abs = (0,
|
|
12366
|
+
const abs = (0, import_node_path32.join)(worktreePath, path);
|
|
12183
12367
|
try {
|
|
12184
|
-
const st = (0,
|
|
12368
|
+
const st = (0, import_node_fs35.statSync)(abs);
|
|
12185
12369
|
if (st.isFile() && st.size > maxHunk) {
|
|
12186
|
-
const buf = (0,
|
|
12370
|
+
const buf = (0, import_node_fs35.readFileSync)(abs).subarray(0, maxHunk);
|
|
12187
12371
|
return syntheticAddPatch(path, buf.toString("utf8"), maxHunk);
|
|
12188
12372
|
}
|
|
12189
12373
|
} catch {
|
|
@@ -12684,8 +12868,8 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
|
|
|
12684
12868
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
12685
12869
|
assertSafeRelativePath(relativePath);
|
|
12686
12870
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
12687
|
-
const abs = (0,
|
|
12688
|
-
const st = (0,
|
|
12871
|
+
const abs = (0, import_node_path32.join)(worktreePath, relativePath);
|
|
12872
|
+
const st = (0, import_node_fs35.statSync)(abs);
|
|
12689
12873
|
if (!st.isFile()) {
|
|
12690
12874
|
throw new Error(`Not a file: ${relativePath}`);
|
|
12691
12875
|
}
|
|
@@ -12694,7 +12878,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
12694
12878
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
12695
12879
|
);
|
|
12696
12880
|
}
|
|
12697
|
-
const buf = (0,
|
|
12881
|
+
const buf = (0, import_node_fs35.readFileSync)(abs);
|
|
12698
12882
|
return {
|
|
12699
12883
|
path: relativePath,
|
|
12700
12884
|
contentBase64: buf.toString("base64"),
|
|
@@ -12704,12 +12888,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
12704
12888
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
12705
12889
|
assertSafeRelativePath(relativePath);
|
|
12706
12890
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
12707
|
-
const abs = (0,
|
|
12708
|
-
const st = (0,
|
|
12891
|
+
const abs = (0, import_node_path32.join)(worktreePath, relativePath);
|
|
12892
|
+
const st = (0, import_node_fs35.statSync)(abs);
|
|
12709
12893
|
if (!st.isFile()) {
|
|
12710
12894
|
throw new Error(`Not a file: ${relativePath}`);
|
|
12711
12895
|
}
|
|
12712
|
-
const buf = (0,
|
|
12896
|
+
const buf = (0, import_node_fs35.readFileSync)(abs);
|
|
12713
12897
|
if (isImageRelativePath(relativePath)) {
|
|
12714
12898
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
12715
12899
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -12752,9 +12936,9 @@ function assertSafeRelativePath(relativePath) {
|
|
|
12752
12936
|
}
|
|
12753
12937
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
12754
12938
|
assertSafeRelativePath(relativePath);
|
|
12755
|
-
const abs = (0,
|
|
12756
|
-
(0,
|
|
12757
|
-
(0,
|
|
12939
|
+
const abs = (0, import_node_path32.join)(worktreePath, relativePath);
|
|
12940
|
+
(0, import_node_fs35.mkdirSync)((0, import_node_path32.dirname)(abs), { recursive: true });
|
|
12941
|
+
(0, import_node_fs35.writeFileSync)(abs, content, "utf8");
|
|
12758
12942
|
return { path: relativePath };
|
|
12759
12943
|
}
|
|
12760
12944
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
@@ -12858,9 +13042,9 @@ async function confirmLand(thread, opts) {
|
|
|
12858
13042
|
}
|
|
12859
13043
|
|
|
12860
13044
|
// src/skills/discover.ts
|
|
12861
|
-
var
|
|
13045
|
+
var import_node_fs36 = require("fs");
|
|
12862
13046
|
var import_node_os11 = require("os");
|
|
12863
|
-
var
|
|
13047
|
+
var import_node_path33 = require("path");
|
|
12864
13048
|
function toCommand(name) {
|
|
12865
13049
|
return name.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
12866
13050
|
}
|
|
@@ -12892,7 +13076,7 @@ function parseFrontmatter(content) {
|
|
|
12892
13076
|
}
|
|
12893
13077
|
function readSkill(skillMd, source) {
|
|
12894
13078
|
try {
|
|
12895
|
-
const content = (0,
|
|
13079
|
+
const content = (0, import_node_fs36.readFileSync)(skillMd, "utf8");
|
|
12896
13080
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
12897
13081
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
12898
13082
|
const name = fmName || dirName;
|
|
@@ -12911,19 +13095,19 @@ function readSkill(skillMd, source) {
|
|
|
12911
13095
|
}
|
|
12912
13096
|
}
|
|
12913
13097
|
function scanSkillsDir(dir, source, out) {
|
|
12914
|
-
if (!(0,
|
|
13098
|
+
if (!(0, import_node_fs36.existsSync)(dir)) return;
|
|
12915
13099
|
let entries;
|
|
12916
13100
|
try {
|
|
12917
|
-
entries = (0,
|
|
13101
|
+
entries = (0, import_node_fs36.readdirSync)(dir);
|
|
12918
13102
|
} catch {
|
|
12919
13103
|
return;
|
|
12920
13104
|
}
|
|
12921
13105
|
for (const entry of entries) {
|
|
12922
13106
|
if (entry.startsWith(".")) continue;
|
|
12923
|
-
const skillMd = (0,
|
|
12924
|
-
if (!(0,
|
|
13107
|
+
const skillMd = (0, import_node_path33.join)(dir, entry, "SKILL.md");
|
|
13108
|
+
if (!(0, import_node_fs36.existsSync)(skillMd)) continue;
|
|
12925
13109
|
try {
|
|
12926
|
-
if (!(0,
|
|
13110
|
+
if (!(0, import_node_fs36.statSync)(skillMd).isFile()) continue;
|
|
12927
13111
|
} catch {
|
|
12928
13112
|
continue;
|
|
12929
13113
|
}
|
|
@@ -12932,24 +13116,24 @@ function scanSkillsDir(dir, source, out) {
|
|
|
12932
13116
|
}
|
|
12933
13117
|
}
|
|
12934
13118
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
12935
|
-
if (!(0,
|
|
13119
|
+
if (!(0, import_node_fs36.existsSync)(pluginsRoot)) return;
|
|
12936
13120
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
12937
13121
|
if (depth > 7) return;
|
|
12938
13122
|
let entries;
|
|
12939
13123
|
try {
|
|
12940
|
-
entries = (0,
|
|
13124
|
+
entries = (0, import_node_fs36.readdirSync)(dir);
|
|
12941
13125
|
} catch {
|
|
12942
13126
|
return;
|
|
12943
13127
|
}
|
|
12944
13128
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
12945
|
-
const skill = readSkill((0,
|
|
13129
|
+
const skill = readSkill((0, import_node_path33.join)(dir, "SKILL.md"), "cli");
|
|
12946
13130
|
if (skill) out.push(skill);
|
|
12947
13131
|
}
|
|
12948
13132
|
for (const entry of entries) {
|
|
12949
13133
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
12950
|
-
const full = (0,
|
|
13134
|
+
const full = (0, import_node_path33.join)(dir, entry);
|
|
12951
13135
|
try {
|
|
12952
|
-
if (!(0,
|
|
13136
|
+
if (!(0, import_node_fs36.statSync)(full).isDirectory()) continue;
|
|
12953
13137
|
} catch {
|
|
12954
13138
|
continue;
|
|
12955
13139
|
}
|
|
@@ -12967,17 +13151,17 @@ function discoverSkills(worktreePath) {
|
|
|
12967
13151
|
const home = (0, import_node_os11.homedir)();
|
|
12968
13152
|
const collected = [];
|
|
12969
13153
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
12970
|
-
scanSkillsDir((0,
|
|
13154
|
+
scanSkillsDir((0, import_node_path33.join)(worktreePath, rel), "workspace", collected);
|
|
12971
13155
|
}
|
|
12972
13156
|
for (const abs of [
|
|
12973
|
-
(0,
|
|
12974
|
-
(0,
|
|
12975
|
-
(0,
|
|
12976
|
-
(0,
|
|
13157
|
+
(0, import_node_path33.join)(home, ".claude/skills"),
|
|
13158
|
+
(0, import_node_path33.join)(home, ".cursor/skills"),
|
|
13159
|
+
(0, import_node_path33.join)(home, ".sideboard/skills"),
|
|
13160
|
+
(0, import_node_path33.join)(home, ".brightsy/skills")
|
|
12977
13161
|
]) {
|
|
12978
13162
|
scanSkillsDir(abs, "user", collected);
|
|
12979
13163
|
}
|
|
12980
|
-
scanClaudePluginSkills((0,
|
|
13164
|
+
scanClaudePluginSkills((0, import_node_path33.join)(home, ".claude/plugins"), collected);
|
|
12981
13165
|
const rank = { workspace: 0, user: 1, cli: 2 };
|
|
12982
13166
|
const byCommand = /* @__PURE__ */ new Map();
|
|
12983
13167
|
for (const skill of collected) {
|
|
@@ -12989,7 +13173,7 @@ function discoverSkills(worktreePath) {
|
|
|
12989
13173
|
return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
|
|
12990
13174
|
}
|
|
12991
13175
|
function readSkillBody(skillPath, maxChars = 12e3) {
|
|
12992
|
-
const raw = (0,
|
|
13176
|
+
const raw = (0, import_node_fs36.readFileSync)(skillPath, "utf8");
|
|
12993
13177
|
if (raw.startsWith("---")) {
|
|
12994
13178
|
const end = raw.indexOf("\n---", 3);
|
|
12995
13179
|
if (end >= 0) {
|
|
@@ -13082,8 +13266,8 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
|
|
|
13082
13266
|
}
|
|
13083
13267
|
|
|
13084
13268
|
// src/composer/stage-files.ts
|
|
13085
|
-
var
|
|
13086
|
-
var
|
|
13269
|
+
var import_node_fs37 = require("fs");
|
|
13270
|
+
var import_node_path34 = require("path");
|
|
13087
13271
|
var import_node_crypto7 = require("crypto");
|
|
13088
13272
|
init_workspace_scratch();
|
|
13089
13273
|
var IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
@@ -13109,7 +13293,7 @@ var IMAGE_MIME_BY_EXT = {
|
|
|
13109
13293
|
var MAX_INLINE_BYTES = 4e5;
|
|
13110
13294
|
var MAX_PREVIEW_BYTES = 5e6;
|
|
13111
13295
|
function fileExtension(filePath) {
|
|
13112
|
-
const base = (0,
|
|
13296
|
+
const base = (0, import_node_path34.basename)(filePath).toLowerCase();
|
|
13113
13297
|
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
13114
13298
|
}
|
|
13115
13299
|
function isImageFilePath(filePath) {
|
|
@@ -13119,22 +13303,22 @@ function imageMimeType(filePath) {
|
|
|
13119
13303
|
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
13120
13304
|
}
|
|
13121
13305
|
function ensureAttachmentsDir(worktreePath) {
|
|
13122
|
-
const dir = (0,
|
|
13123
|
-
(0,
|
|
13124
|
-
const gi = (0,
|
|
13125
|
-
if (!(0,
|
|
13126
|
-
(0,
|
|
13306
|
+
const dir = (0, import_node_path34.join)(worktreePath, ATTACHMENTS_DIR);
|
|
13307
|
+
(0, import_node_fs37.mkdirSync)(dir, { recursive: true });
|
|
13308
|
+
const gi = (0, import_node_path34.join)(dir, ".gitignore");
|
|
13309
|
+
if (!(0, import_node_fs37.existsSync)(gi)) {
|
|
13310
|
+
(0, import_node_fs37.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
13127
13311
|
}
|
|
13128
13312
|
return dir;
|
|
13129
13313
|
}
|
|
13130
13314
|
function uniqueAttachmentName(dir, originalName) {
|
|
13131
13315
|
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
13132
|
-
if (!(0,
|
|
13133
|
-
const ext = (0,
|
|
13316
|
+
if (!(0, import_node_fs37.existsSync)((0, import_node_path34.join)(dir, safe))) return safe;
|
|
13317
|
+
const ext = (0, import_node_path34.extname)(safe);
|
|
13134
13318
|
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
13135
13319
|
for (let i = 1; i < 1e4; i++) {
|
|
13136
13320
|
const candidate = `${stem}-${i}${ext}`;
|
|
13137
|
-
if (!(0,
|
|
13321
|
+
if (!(0, import_node_fs37.existsSync)((0, import_node_path34.join)(dir, candidate))) return candidate;
|
|
13138
13322
|
}
|
|
13139
13323
|
return `${stem}-${(0, import_node_crypto7.randomUUID)()}${ext}`;
|
|
13140
13324
|
}
|
|
@@ -13190,15 +13374,15 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
|
13190
13374
|
const dir = ensureAttachmentsDir(worktreePath);
|
|
13191
13375
|
const out = [];
|
|
13192
13376
|
for (const abs of absolutePaths) {
|
|
13193
|
-
const originalName = (0,
|
|
13377
|
+
const originalName = (0, import_node_path34.basename)(abs);
|
|
13194
13378
|
try {
|
|
13195
|
-
const st = (0,
|
|
13379
|
+
const st = (0, import_node_fs37.statSync)(abs);
|
|
13196
13380
|
if (!st.isFile()) continue;
|
|
13197
13381
|
const name = uniqueAttachmentName(dir, originalName);
|
|
13198
|
-
const destAbs = (0,
|
|
13199
|
-
(0,
|
|
13382
|
+
const destAbs = (0, import_node_path34.join)(dir, name);
|
|
13383
|
+
(0, import_node_fs37.copyFileSync)(abs, destAbs);
|
|
13200
13384
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
13201
|
-
const buf = (0,
|
|
13385
|
+
const buf = (0, import_node_fs37.readFileSync)(destAbs);
|
|
13202
13386
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
13203
13387
|
} catch (err) {
|
|
13204
13388
|
out.push({
|
|
@@ -13220,8 +13404,8 @@ function stageBuffersAsAttachments(worktreePath, buffers) {
|
|
|
13220
13404
|
try {
|
|
13221
13405
|
const buf = Buffer.from(item.dataBase64, "base64");
|
|
13222
13406
|
const name = uniqueAttachmentName(dir, originalName);
|
|
13223
|
-
const destAbs = (0,
|
|
13224
|
-
(0,
|
|
13407
|
+
const destAbs = (0, import_node_path34.join)(dir, name);
|
|
13408
|
+
(0, import_node_fs37.writeFileSync)(destAbs, buf);
|
|
13225
13409
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
13226
13410
|
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
13227
13411
|
} catch (err) {
|
|
@@ -13241,18 +13425,18 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
|
13241
13425
|
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
13242
13426
|
out.push({
|
|
13243
13427
|
id: (0, import_node_crypto7.randomUUID)(),
|
|
13244
|
-
name: (0,
|
|
13428
|
+
name: (0, import_node_path34.basename)(rel) || "file",
|
|
13245
13429
|
kind: "file",
|
|
13246
13430
|
content: `(invalid path: ${rel})`
|
|
13247
13431
|
});
|
|
13248
13432
|
continue;
|
|
13249
13433
|
}
|
|
13250
|
-
const name = (0,
|
|
13434
|
+
const name = (0, import_node_path34.basename)(rel);
|
|
13251
13435
|
try {
|
|
13252
|
-
const abs = (0,
|
|
13253
|
-
const st = (0,
|
|
13436
|
+
const abs = (0, import_node_path34.join)(worktreePath, rel);
|
|
13437
|
+
const st = (0, import_node_fs37.statSync)(abs);
|
|
13254
13438
|
if (!st.isFile()) continue;
|
|
13255
|
-
const buf = (0,
|
|
13439
|
+
const buf = (0, import_node_fs37.readFileSync)(abs);
|
|
13256
13440
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
13257
13441
|
} catch (err) {
|
|
13258
13442
|
out.push({
|
|
@@ -13267,8 +13451,8 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
|
13267
13451
|
}
|
|
13268
13452
|
|
|
13269
13453
|
// src/agents/instructions.ts
|
|
13270
|
-
var
|
|
13271
|
-
var
|
|
13454
|
+
var import_node_fs38 = require("fs");
|
|
13455
|
+
var import_node_path35 = require("path");
|
|
13272
13456
|
init_git_auth_mode();
|
|
13273
13457
|
init_worktree_labels();
|
|
13274
13458
|
function normPath3(p) {
|
|
@@ -13548,7 +13732,7 @@ var Orchestrator = class {
|
|
|
13548
13732
|
}
|
|
13549
13733
|
continue;
|
|
13550
13734
|
}
|
|
13551
|
-
if (!(0,
|
|
13735
|
+
if (!(0, import_node_fs42.existsSync)(thread.worktreePath)) {
|
|
13552
13736
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
13553
13737
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
13554
13738
|
continue;
|
|
@@ -13799,7 +13983,9 @@ var Orchestrator = class {
|
|
|
13799
13983
|
updateThread(thread.id, patch);
|
|
13800
13984
|
this.emit({ type: "queue_changed", threadId: thread.id, queue });
|
|
13801
13985
|
this.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
|
|
13802
|
-
|
|
13986
|
+
if (thisProcessShouldDrainAgentQueues()) {
|
|
13987
|
+
void this.drainQueue(thread.id);
|
|
13988
|
+
}
|
|
13803
13989
|
return this.requireThread(thread.id);
|
|
13804
13990
|
});
|
|
13805
13991
|
}
|
|
@@ -13852,10 +14038,10 @@ var Orchestrator = class {
|
|
|
13852
14038
|
async sendQueuedMessageNow(threadRef, index) {
|
|
13853
14039
|
const thread = this.requireThread(threadRef);
|
|
13854
14040
|
const promoted = await withThreadLock(thread.id, async () => {
|
|
13855
|
-
const
|
|
13856
|
-
if (index < 0 || index >=
|
|
13857
|
-
const item =
|
|
13858
|
-
const rest =
|
|
14041
|
+
const current2 = this.requireThread(thread.id);
|
|
14042
|
+
if (index < 0 || index >= current2.queue.length) return false;
|
|
14043
|
+
const item = current2.queue[index];
|
|
14044
|
+
const rest = current2.queue.filter((_, i) => i !== index);
|
|
13859
14045
|
const queue = [item, ...rest];
|
|
13860
14046
|
this.haltDrain.delete(thread.id);
|
|
13861
14047
|
updateThread(thread.id, { queue });
|
|
@@ -13863,10 +14049,16 @@ var Orchestrator = class {
|
|
|
13863
14049
|
return true;
|
|
13864
14050
|
});
|
|
13865
14051
|
if (!promoted) return this.requireThread(thread.id);
|
|
14052
|
+
const current = this.requireThread(thread.id);
|
|
13866
14053
|
const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id);
|
|
14054
|
+
const livePid = current.agentPid;
|
|
14055
|
+
const foreignLive = !inFlight && typeof livePid === "number" && livePid > 0 && isPidAlive(livePid);
|
|
13867
14056
|
if (inFlight) {
|
|
13868
14057
|
this.stop(thread.id, { clearQueue: false, continueQueue: true });
|
|
13869
14058
|
} else {
|
|
14059
|
+
if (foreignLive) {
|
|
14060
|
+
this.stop(thread.id, { clearQueue: false, continueQueue: true });
|
|
14061
|
+
}
|
|
13870
14062
|
void this.drainQueue(thread.id);
|
|
13871
14063
|
}
|
|
13872
14064
|
return this.requireThread(thread.id);
|
|
@@ -14117,19 +14309,16 @@ var Orchestrator = class {
|
|
|
14117
14309
|
}
|
|
14118
14310
|
let lastStderr = summarizeTurnStderr(stderrTail);
|
|
14119
14311
|
let detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
14120
|
-
if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) &&
|
|
14312
|
+
if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) && this.requireThread(threadId).agent !== "brightsy" && shouldRetryFailedAgentTurn(detail, {
|
|
14313
|
+
hasSession: Boolean(this.requireThread(threadId).sessionId)
|
|
14314
|
+
})) {
|
|
14121
14315
|
updateThread(threadId, { sessionId: null });
|
|
14122
|
-
|
|
14123
|
-
|
|
14124
|
-
"Agent session missing \u2014 starting a fresh session"
|
|
14125
|
-
);
|
|
14316
|
+
const retryNote = looksLikeInvalidAgentSession(detail) ? "Agent session missing \u2014 starting a fresh session" : "Agent runner crashed \u2014 restarting Node once";
|
|
14317
|
+
pushTurnStderr(stderrTail, retryNote);
|
|
14126
14318
|
this.emit({
|
|
14127
14319
|
type: "turn_output",
|
|
14128
14320
|
threadId,
|
|
14129
|
-
event: {
|
|
14130
|
-
type: "stderr",
|
|
14131
|
-
data: "Agent session missing \u2014 starting a fresh session"
|
|
14132
|
-
}
|
|
14321
|
+
event: { type: "stderr", data: retryNote }
|
|
14133
14322
|
});
|
|
14134
14323
|
const retryThread = this.requireThread(threadId);
|
|
14135
14324
|
const prior = retryThread.messages.slice(0, -1);
|
|
@@ -14178,10 +14367,7 @@ var Orchestrator = class {
|
|
|
14178
14367
|
lastStderr = summarizeTurnStderr(stderrTail);
|
|
14179
14368
|
detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
14180
14369
|
}
|
|
14181
|
-
let chatText = assistantText;
|
|
14182
|
-
if (exitCode !== 0 && !chatText && looksLikeAgentFailureMessage(detail)) {
|
|
14183
|
-
chatText = humanizeAgentFailDetail(detail);
|
|
14184
|
-
}
|
|
14370
|
+
let chatText = this.stoppedTurns.has(threadId) ? assistantText : turnFailChatText({ exitCode, assistantText, detail });
|
|
14185
14371
|
if (chatText || parts.length > 0) {
|
|
14186
14372
|
appendMessage(threadId, {
|
|
14187
14373
|
role: "agent",
|
|
@@ -14301,6 +14487,13 @@ var Orchestrator = class {
|
|
|
14301
14487
|
if (handle) handle.kill();
|
|
14302
14488
|
const proc = this.processes.get(`${thread.id}:agent`);
|
|
14303
14489
|
if (proc) proc.kill();
|
|
14490
|
+
const pid = thread.agentPid;
|
|
14491
|
+
if (typeof pid === "number" && pid > 0 && isPidAlive(pid)) {
|
|
14492
|
+
try {
|
|
14493
|
+
process.kill(pid, "SIGTERM");
|
|
14494
|
+
} catch {
|
|
14495
|
+
}
|
|
14496
|
+
}
|
|
14304
14497
|
const stopped = writeLiveStatus(thread.id, "stopped") ?? readThread(thread.id) ?? thread;
|
|
14305
14498
|
if (stopped.status === "stopped") {
|
|
14306
14499
|
this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
|
|
@@ -14582,10 +14775,13 @@ var Orchestrator = class {
|
|
|
14582
14775
|
getTurnResult(threadRef) {
|
|
14583
14776
|
const thread = this.requireThread(threadRef);
|
|
14584
14777
|
const lastAgent = [...thread.messages].reverse().find((m) => m.role === "agent");
|
|
14778
|
+
const lastError = thread.lastError ?? null;
|
|
14779
|
+
const text3 = (lastAgent?.text ?? "").trim() || (thread.status === "error" ? lastError ?? "" : "");
|
|
14585
14780
|
return {
|
|
14586
|
-
text:
|
|
14781
|
+
text: text3,
|
|
14587
14782
|
status: thread.status,
|
|
14588
|
-
sessionId: thread.sessionId
|
|
14783
|
+
sessionId: thread.sessionId,
|
|
14784
|
+
lastError
|
|
14589
14785
|
};
|
|
14590
14786
|
}
|
|
14591
14787
|
assertNotGlobal(thread, action) {
|
|
@@ -15081,7 +15277,7 @@ var Orchestrator = class {
|
|
|
15081
15277
|
this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
|
|
15082
15278
|
return restored2;
|
|
15083
15279
|
}
|
|
15084
|
-
if (!(0,
|
|
15280
|
+
if (!(0, import_node_fs42.existsSync)(thread.worktreePath)) {
|
|
15085
15281
|
const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
|
|
15086
15282
|
const { execa: execa7 } = await import("execa");
|
|
15087
15283
|
const slug = thread.worktreePath.split("/").pop();
|
|
@@ -16321,7 +16517,7 @@ async function startMcpServer() {
|
|
|
16321
16517
|
async () => {
|
|
16322
16518
|
const threads = orch.getThreads(true);
|
|
16323
16519
|
const lines = threads.map((t) => {
|
|
16324
|
-
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0,
|
|
16520
|
+
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path39.basename)(t.repoPath) || t.repoPath;
|
|
16325
16521
|
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}` : ""}`;
|
|
16326
16522
|
});
|
|
16327
16523
|
return {
|
|
@@ -16678,7 +16874,7 @@ async function startMcpServer() {
|
|
|
16678
16874
|
);
|
|
16679
16875
|
server.tool(
|
|
16680
16876
|
"wait_for_turn",
|
|
16681
|
-
"Block until the thread finishes its current/queued turn (avoids polling). Use after send_to_thread or ask_git
|
|
16877
|
+
"Block until the thread finishes its current/queued turn (avoids polling). Use after send_to_thread or ask_git. Returns status, text, and lastError. If status is error, lastError/text is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success.",
|
|
16682
16878
|
{
|
|
16683
16879
|
ref: import_zod3.z.string(),
|
|
16684
16880
|
timeoutMs: import_zod3.z.number().optional()
|
|
@@ -16693,7 +16889,8 @@ async function startMcpServer() {
|
|
|
16693
16889
|
text: JSON.stringify({
|
|
16694
16890
|
id: thread.id,
|
|
16695
16891
|
status: result.status,
|
|
16696
|
-
text: result.text
|
|
16892
|
+
text: result.text,
|
|
16893
|
+
lastError: result.lastError
|
|
16697
16894
|
})
|
|
16698
16895
|
}
|
|
16699
16896
|
]
|
|
@@ -16702,7 +16899,7 @@ async function startMcpServer() {
|
|
|
16702
16899
|
);
|
|
16703
16900
|
server.tool(
|
|
16704
16901
|
"get_turn_result",
|
|
16705
|
-
"Final assistant message
|
|
16902
|
+
"Final assistant message (and lastError when the turn failed). Not the full transcript.",
|
|
16706
16903
|
{ ref: import_zod3.z.string() },
|
|
16707
16904
|
async ({ ref }) => {
|
|
16708
16905
|
const result = orch.getTurnResult(ref);
|