@sideboard-ai/core 0.1.62 → 0.1.66
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-QLSFIQAO.js → agents-EWFD765A.js} +23 -7
- package/dist/{agents-KF3J3C53.js → agents-MD7SCFYX.js} +23 -7
- package/dist/{app-settings-LTSFG7QJ.js → app-settings-GJVZGU3M.js} +13 -3
- package/dist/{app-settings-HK4KAM4R.js → app-settings-ONKMFSEJ.js} +13 -3
- package/dist/{chunk-RIWUU7FO.js → chunk-5AG5BUQN.js} +61 -3
- package/dist/{chunk-27MAWNKY.js → chunk-AKPEXIKK.js} +2 -2
- package/dist/{chunk-2MCNURQV.js → chunk-BBEH2CJE.js} +264 -93
- package/dist/{chunk-DDN3UF4R.js → chunk-BPOTVI5J.js} +115 -3
- package/dist/{chunk-2FEA4LDA.js → chunk-DNPP7QMK.js} +31 -6
- package/dist/{chunk-MBAL5FE6.js → chunk-DZYMNW2A.js} +4 -4
- package/dist/{chunk-JB2H7E7V.js → chunk-EVD4KNKR.js} +1 -1
- package/dist/{chunk-A6FOKNOU.js → chunk-HTOTTJJX.js} +2 -2
- package/dist/{chunk-3KKNTHUC.js → chunk-I2KGRAXC.js} +1 -1
- package/dist/{chunk-ZF5YJCXO.js → chunk-IFAU2DEY.js} +269 -93
- package/dist/{chunk-NVU7EC2E.js → chunk-LRBRQFBU.js} +2 -2
- package/dist/{chunk-6CUJQKTJ.js → chunk-MHR4OGZ4.js} +115 -3
- package/dist/{chunk-46KMKHSD.js → chunk-PESJDZTB.js} +2 -2
- package/dist/{chunk-UGXSSBFJ.js → chunk-R7GUDEPY.js} +1 -1
- package/dist/{chunk-73AT5K4A.js → chunk-TXQ6K2GR.js} +61 -3
- package/dist/{chunk-DXTGDXO2.js → chunk-YTNLOJPK.js} +31 -6
- package/dist/{connected-teams-RSL4VB3X.js → connected-teams-CHXO5FFA.js} +2 -2
- package/dist/{connected-teams-MKIYKOYA.js → connected-teams-GJTESSTX.js} +2 -2
- package/dist/{coordinator-prompt-LKG3SHMI.js → coordinator-prompt-E5UGSJES.js} +4 -4
- package/dist/{coordinator-prompt-N2R6FGZK.js → coordinator-prompt-ILSULI7C.js} +4 -4
- package/dist/{global-workspace-LALWQWRJ.js → global-workspace-44UG64NA.js} +5 -6
- package/dist/{global-workspace-YOAUQCMA.js → global-workspace-5PM5LA6E.js} +5 -6
- package/dist/index.cjs +1308 -925
- package/dist/index.d.cts +92 -1
- package/dist/index.d.ts +92 -1
- package/dist/index.js +746 -715
- package/dist/mcp/run-stdio.cjs +1267 -976
- package/dist/mcp/run-stdio.js +691 -748
- package/dist/{run-HZTBWGQR.js → run-74S2NZWB.js} +1 -1
- package/dist/{run-GPSVV5OH.js → run-JLN5JK7Q.js} +1 -1
- package/dist/{workspaces-VCAIHVIE.js → workspaces-OVBCSS5Y.js} +6 -7
- package/dist/{workspaces-E75POJXP.js → workspaces-RXFXQRRF.js} +6 -7
- package/dist/{worktree-MV4WRW6G.js → worktree-K2JB53R5.js} +2 -2
- package/dist/{worktree-LZEGVQSN.js → worktree-S2N63FLV.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-GI7E5733.js +0 -30
- package/dist/chunk-S2LL5HA4.js +0 -33
package/dist/index.cjs
CHANGED
|
@@ -397,6 +397,7 @@ __export(app_settings_exports, {
|
|
|
397
397
|
autoRunAfterSetupEnabled: () => autoRunAfterSetupEnabled,
|
|
398
398
|
brightsyCloudConnectAgent: () => brightsyCloudConnectAgent,
|
|
399
399
|
brightsyCloudConnectEnabled: () => brightsyCloudConnectEnabled,
|
|
400
|
+
brightsyInjectWorktreeMcpEnabled: () => brightsyInjectWorktreeMcpEnabled,
|
|
400
401
|
caffeinateWhileCloudConnectEnabled: () => caffeinateWhileCloudConnectEnabled,
|
|
401
402
|
caffeinateWhileRunningEnabled: () => caffeinateWhileRunningEnabled,
|
|
402
403
|
childEnvWithAppSettings: () => childEnvWithAppSettings,
|
|
@@ -415,17 +416,21 @@ __export(app_settings_exports, {
|
|
|
415
416
|
maxConcurrentAgents: () => maxConcurrentAgents,
|
|
416
417
|
orchestrationQuotaFallbackAgent: () => orchestrationQuotaFallbackAgent,
|
|
417
418
|
orchestrationQuotaOnLimit: () => orchestrationQuotaOnLimit,
|
|
419
|
+
resolveAgentExecutable: () => resolveAgentExecutable,
|
|
418
420
|
resolveClaudeExecutable: () => resolveClaudeExecutable,
|
|
419
421
|
resolveEffectiveIssueSource: () => resolveEffectiveIssueSource,
|
|
420
422
|
resolveNewThreadOptions: () => resolveNewThreadOptions,
|
|
421
423
|
resolveThreadDefaults: () => resolveThreadDefaults,
|
|
422
424
|
saveAppSettings: () => saveAppSettings,
|
|
423
425
|
updateAdvancedSettings: () => updateAdvancedSettings,
|
|
426
|
+
updateAgentExecutable: () => updateAgentExecutable,
|
|
424
427
|
updateAppEnvironment: () => updateAppEnvironment,
|
|
425
428
|
updateBrightsySettings: () => updateBrightsySettings,
|
|
426
429
|
updateClaudeSettings: () => updateClaudeSettings,
|
|
430
|
+
updateCodexSettings: () => updateCodexSettings,
|
|
427
431
|
updateDefaultsSettings: () => updateDefaultsSettings,
|
|
428
|
-
updateIntegrationsSettings: () => updateIntegrationsSettings
|
|
432
|
+
updateIntegrationsSettings: () => updateIntegrationsSettings,
|
|
433
|
+
updateOpencodeSettings: () => updateOpencodeSettings
|
|
429
434
|
});
|
|
430
435
|
function appSettingsPath() {
|
|
431
436
|
return (0, import_node_path4.join)(appDataDir(), "settings.json");
|
|
@@ -446,16 +451,33 @@ function normalizeClaude(raw) {
|
|
|
446
451
|
}
|
|
447
452
|
return out;
|
|
448
453
|
}
|
|
454
|
+
function normalizeCliExecutable(raw) {
|
|
455
|
+
if (!raw || typeof raw !== "object") return {};
|
|
456
|
+
const source = raw;
|
|
457
|
+
const out = {};
|
|
458
|
+
if (typeof source.executablePath === "string") {
|
|
459
|
+
const path = source.executablePath.trim();
|
|
460
|
+
if (path) out.executablePath = path;
|
|
461
|
+
}
|
|
462
|
+
return out;
|
|
463
|
+
}
|
|
449
464
|
function normalizeBrightsy(raw) {
|
|
450
465
|
if (!raw || typeof raw !== "object") return {};
|
|
451
466
|
const source = raw;
|
|
452
467
|
const out = {};
|
|
468
|
+
if (typeof source.executablePath === "string") {
|
|
469
|
+
const path = source.executablePath.trim();
|
|
470
|
+
if (path) out.executablePath = path;
|
|
471
|
+
}
|
|
453
472
|
if (typeof source.cloudConnectEnabled === "boolean") {
|
|
454
473
|
out.cloudConnectEnabled = source.cloudConnectEnabled;
|
|
455
474
|
}
|
|
456
475
|
if (typeof source.cloudConnectAgent === "string" && CLOUD_CONNECT_AGENTS.has(source.cloudConnectAgent)) {
|
|
457
476
|
out.cloudConnectAgent = source.cloudConnectAgent;
|
|
458
477
|
}
|
|
478
|
+
if (typeof source.injectWorktreeMcp === "boolean") {
|
|
479
|
+
out.injectWorktreeMcp = source.injectWorktreeMcp;
|
|
480
|
+
}
|
|
459
481
|
return out;
|
|
460
482
|
}
|
|
461
483
|
function normalizeIntegrations(raw) {
|
|
@@ -541,6 +563,8 @@ function normalizeAdvanced(raw) {
|
|
|
541
563
|
function normalizeSettings(raw) {
|
|
542
564
|
const env = {};
|
|
543
565
|
let claude = {};
|
|
566
|
+
let codex = {};
|
|
567
|
+
let opencode = {};
|
|
544
568
|
let brightsy = {};
|
|
545
569
|
let integrations = {};
|
|
546
570
|
let defaults = {};
|
|
@@ -559,6 +583,12 @@ function normalizeSettings(raw) {
|
|
|
559
583
|
if ("claude" in raw) {
|
|
560
584
|
claude = normalizeClaude(raw.claude);
|
|
561
585
|
}
|
|
586
|
+
if ("codex" in raw) {
|
|
587
|
+
codex = normalizeCliExecutable(raw.codex);
|
|
588
|
+
}
|
|
589
|
+
if ("opencode" in raw) {
|
|
590
|
+
opencode = normalizeCliExecutable(raw.opencode);
|
|
591
|
+
}
|
|
562
592
|
if ("brightsy" in raw) {
|
|
563
593
|
brightsy = normalizeBrightsy(raw.brightsy);
|
|
564
594
|
}
|
|
@@ -574,7 +604,16 @@ function normalizeSettings(raw) {
|
|
|
574
604
|
advanced = normalizeAdvanced(raw.advanced);
|
|
575
605
|
}
|
|
576
606
|
}
|
|
577
|
-
return {
|
|
607
|
+
return {
|
|
608
|
+
environment: env,
|
|
609
|
+
claude,
|
|
610
|
+
codex,
|
|
611
|
+
opencode,
|
|
612
|
+
brightsy,
|
|
613
|
+
integrations,
|
|
614
|
+
defaults,
|
|
615
|
+
advanced
|
|
616
|
+
};
|
|
578
617
|
}
|
|
579
618
|
function loadAppSettings() {
|
|
580
619
|
const path = appSettingsPath();
|
|
@@ -627,6 +666,13 @@ function updateClaudeSettings(patch) {
|
|
|
627
666
|
function updateBrightsySettings(patch) {
|
|
628
667
|
const current = loadAppSettings();
|
|
629
668
|
const brightsy = { ...current.brightsy };
|
|
669
|
+
if ("executablePath" in patch) {
|
|
670
|
+
if (patch.executablePath == null || patch.executablePath.trim() === "") {
|
|
671
|
+
delete brightsy.executablePath;
|
|
672
|
+
} else {
|
|
673
|
+
brightsy.executablePath = patch.executablePath.trim();
|
|
674
|
+
}
|
|
675
|
+
}
|
|
630
676
|
if (typeof patch.cloudConnectEnabled === "boolean") {
|
|
631
677
|
brightsy.cloudConnectEnabled = patch.cloudConnectEnabled;
|
|
632
678
|
}
|
|
@@ -637,8 +683,35 @@ function updateBrightsySettings(patch) {
|
|
|
637
683
|
brightsy.cloudConnectAgent = patch.cloudConnectAgent;
|
|
638
684
|
}
|
|
639
685
|
}
|
|
686
|
+
if (typeof patch.injectWorktreeMcp === "boolean") {
|
|
687
|
+
brightsy.injectWorktreeMcp = patch.injectWorktreeMcp;
|
|
688
|
+
}
|
|
640
689
|
return saveAppSettings({ ...current, brightsy });
|
|
641
690
|
}
|
|
691
|
+
function updateCodexSettings(patch) {
|
|
692
|
+
const current = loadAppSettings();
|
|
693
|
+
const codex = { ...current.codex };
|
|
694
|
+
if ("executablePath" in patch) {
|
|
695
|
+
if (patch.executablePath == null || patch.executablePath.trim() === "") {
|
|
696
|
+
delete codex.executablePath;
|
|
697
|
+
} else {
|
|
698
|
+
codex.executablePath = patch.executablePath.trim();
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
return saveAppSettings({ ...current, codex });
|
|
702
|
+
}
|
|
703
|
+
function updateOpencodeSettings(patch) {
|
|
704
|
+
const current = loadAppSettings();
|
|
705
|
+
const opencode = { ...current.opencode };
|
|
706
|
+
if ("executablePath" in patch) {
|
|
707
|
+
if (patch.executablePath == null || patch.executablePath.trim() === "") {
|
|
708
|
+
delete opencode.executablePath;
|
|
709
|
+
} else {
|
|
710
|
+
opencode.executablePath = patch.executablePath.trim();
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
return saveAppSettings({ ...current, opencode });
|
|
714
|
+
}
|
|
642
715
|
function updateIntegrationsSettings(patch) {
|
|
643
716
|
const current = loadAppSettings();
|
|
644
717
|
const integrations = { ...current.integrations };
|
|
@@ -746,6 +819,9 @@ function getLinearApiKey(settings = loadAppSettings()) {
|
|
|
746
819
|
function brightsyCloudConnectEnabled(settings = loadAppSettings()) {
|
|
747
820
|
return Boolean(settings.brightsy.cloudConnectEnabled);
|
|
748
821
|
}
|
|
822
|
+
function brightsyInjectWorktreeMcpEnabled(settings = loadAppSettings()) {
|
|
823
|
+
return Boolean(settings.brightsy.injectWorktreeMcp);
|
|
824
|
+
}
|
|
749
825
|
function brightsyCloudConnectAgent(settings = loadAppSettings()) {
|
|
750
826
|
const fallback = settings.brightsy.cloudConnectAgent && CLOUD_CONNECT_AGENTS.has(settings.brightsy.cloudConnectAgent) ? settings.brightsy.cloudConnectAgent : "claude";
|
|
751
827
|
const preferred = getDefaultAgent(settings);
|
|
@@ -840,8 +916,36 @@ function maxConcurrentAgents(settings = loadAppSettings()) {
|
|
|
840
916
|
return 3;
|
|
841
917
|
}
|
|
842
918
|
function resolveClaudeExecutable(settings = loadAppSettings()) {
|
|
843
|
-
|
|
844
|
-
|
|
919
|
+
return resolveAgentExecutable("claude", settings);
|
|
920
|
+
}
|
|
921
|
+
function resolveAgentExecutable(agent, settings = loadAppSettings()) {
|
|
922
|
+
const fallback = DEFAULT_CLI_BIN[agent];
|
|
923
|
+
if (agent === "claude") {
|
|
924
|
+
const override2 = settings.claude.executablePath?.trim();
|
|
925
|
+
return override2 || fallback;
|
|
926
|
+
}
|
|
927
|
+
if (agent === "codex") {
|
|
928
|
+
const override2 = settings.codex.executablePath?.trim();
|
|
929
|
+
return override2 || fallback;
|
|
930
|
+
}
|
|
931
|
+
if (agent === "opencode") {
|
|
932
|
+
const override2 = settings.opencode.executablePath?.trim();
|
|
933
|
+
return override2 || fallback;
|
|
934
|
+
}
|
|
935
|
+
const override = settings.brightsy.executablePath?.trim();
|
|
936
|
+
return override || fallback;
|
|
937
|
+
}
|
|
938
|
+
function updateAgentExecutable(agent, executablePath) {
|
|
939
|
+
if (agent === "claude") {
|
|
940
|
+
return updateClaudeSettings({ executablePath });
|
|
941
|
+
}
|
|
942
|
+
if (agent === "codex") {
|
|
943
|
+
return updateCodexSettings({ executablePath });
|
|
944
|
+
}
|
|
945
|
+
if (agent === "opencode") {
|
|
946
|
+
return updateOpencodeSettings({ executablePath });
|
|
947
|
+
}
|
|
948
|
+
return updateBrightsySettings({ executablePath });
|
|
845
949
|
}
|
|
846
950
|
function claudeChromeEnabled(settings = loadAppSettings()) {
|
|
847
951
|
return Boolean(settings.claude.chromeEnabled);
|
|
@@ -869,7 +973,7 @@ function childEnvWithAppSettings(extra) {
|
|
|
869
973
|
function harnessEnvKey(harness) {
|
|
870
974
|
return HARNESS_ENV_KEYS[harness];
|
|
871
975
|
}
|
|
872
|
-
var import_node_fs3, import_node_os3, import_node_path4, HARNESS_ENV_KEYS, DEFAULT_AGENTS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, EMPTY_SETTINGS;
|
|
976
|
+
var import_node_fs3, import_node_os3, import_node_path4, HARNESS_ENV_KEYS, DEFAULT_AGENTS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, EMPTY_SETTINGS, DEFAULT_CLI_BIN;
|
|
873
977
|
var init_app_settings = __esm({
|
|
874
978
|
"src/store/app-settings.ts"() {
|
|
875
979
|
"use strict";
|
|
@@ -902,11 +1006,19 @@ var init_app_settings = __esm({
|
|
|
902
1006
|
EMPTY_SETTINGS = {
|
|
903
1007
|
environment: {},
|
|
904
1008
|
claude: {},
|
|
1009
|
+
codex: {},
|
|
1010
|
+
opencode: {},
|
|
905
1011
|
brightsy: {},
|
|
906
1012
|
integrations: {},
|
|
907
1013
|
defaults: {},
|
|
908
1014
|
advanced: {}
|
|
909
1015
|
};
|
|
1016
|
+
DEFAULT_CLI_BIN = {
|
|
1017
|
+
claude: "claude",
|
|
1018
|
+
codex: "codex",
|
|
1019
|
+
opencode: "opencode",
|
|
1020
|
+
brightsy: "brightsy"
|
|
1021
|
+
};
|
|
910
1022
|
}
|
|
911
1023
|
});
|
|
912
1024
|
|
|
@@ -2041,18 +2153,28 @@ var init_gh_errors = __esm({
|
|
|
2041
2153
|
});
|
|
2042
2154
|
|
|
2043
2155
|
// src/agents/path.ts
|
|
2156
|
+
function prependPathDir(env, dir) {
|
|
2157
|
+
if (!dir || !(0, import_node_fs5.existsSync)(dir)) return;
|
|
2158
|
+
const current = env.PATH ?? "";
|
|
2159
|
+
const parts = current.split(import_node_path5.delimiter).filter(Boolean);
|
|
2160
|
+
if (parts.includes(dir)) {
|
|
2161
|
+
env.PATH = current;
|
|
2162
|
+
return;
|
|
2163
|
+
}
|
|
2164
|
+
env.PATH = [dir, ...parts].join(import_node_path5.delimiter);
|
|
2165
|
+
}
|
|
2044
2166
|
function ensureAgentPath(env = process.env) {
|
|
2045
2167
|
const home = env.HOME || env.USERPROFILE || (0, import_node_os4.homedir)();
|
|
2046
2168
|
const current = env.PATH ?? "";
|
|
2047
2169
|
const parts = current.split(import_node_path5.delimiter).filter(Boolean);
|
|
2048
2170
|
const seen = new Set(parts);
|
|
2049
2171
|
const extras = [
|
|
2050
|
-
...EXTRA_BIN_DIRS.map((rel) =>
|
|
2172
|
+
...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path5.join)(home, rel)),
|
|
2051
2173
|
"/opt/homebrew/bin",
|
|
2052
2174
|
"/usr/local/bin"
|
|
2053
2175
|
];
|
|
2054
2176
|
for (const dir of extras.reverse()) {
|
|
2055
|
-
if (!dir || seen.has(dir)) continue;
|
|
2177
|
+
if (!dir || seen.has(dir) || !(0, import_node_fs5.existsSync)(dir)) continue;
|
|
2056
2178
|
parts.unshift(dir);
|
|
2057
2179
|
seen.add(dir);
|
|
2058
2180
|
}
|
|
@@ -2060,10 +2182,50 @@ function ensureAgentPath(env = process.env) {
|
|
|
2060
2182
|
env.PATH = next;
|
|
2061
2183
|
return next;
|
|
2062
2184
|
}
|
|
2063
|
-
|
|
2185
|
+
function enrichPathWithNpmGlobalBin(env = process.env) {
|
|
2186
|
+
ensureAgentPath(env);
|
|
2187
|
+
try {
|
|
2188
|
+
const prefix = (0, import_node_child_process.execFileSync)("npm", ["prefix", "-g"], {
|
|
2189
|
+
encoding: "utf8",
|
|
2190
|
+
env: { ...process.env, ...env },
|
|
2191
|
+
timeout: 8e3,
|
|
2192
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2193
|
+
}).trim().split(/\r?\n/).find(Boolean);
|
|
2194
|
+
if (prefix) {
|
|
2195
|
+
const binDir = process.platform === "win32" ? prefix : (0, import_node_path5.join)(prefix, "bin");
|
|
2196
|
+
prependPathDir(env, binDir);
|
|
2197
|
+
}
|
|
2198
|
+
} catch {
|
|
2199
|
+
}
|
|
2200
|
+
return env.PATH ?? "";
|
|
2201
|
+
}
|
|
2202
|
+
function posixShellSingleQuote(value) {
|
|
2203
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
2204
|
+
}
|
|
2205
|
+
function resolveCommandBinarySync(command, whichPath) {
|
|
2206
|
+
const trimmed = command.trim();
|
|
2207
|
+
if (!trimmed) return trimmed;
|
|
2208
|
+
const match = /^(\S+)(\s[\s\S]*)?$/.exec(trimmed);
|
|
2209
|
+
if (!match) return trimmed;
|
|
2210
|
+
const bin = match[1];
|
|
2211
|
+
const rest = match[2] ?? "";
|
|
2212
|
+
if (bin.includes("/") || bin.includes("\\")) return trimmed;
|
|
2213
|
+
const abs = whichPath?.trim().split(/\r?\n/).find(Boolean);
|
|
2214
|
+
if (!abs) return trimmed;
|
|
2215
|
+
return `${abs}${rest}`;
|
|
2216
|
+
}
|
|
2217
|
+
function withExportedPath(command, pathValue) {
|
|
2218
|
+
const trimmed = command.trim();
|
|
2219
|
+
if (!trimmed) return trimmed;
|
|
2220
|
+
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
2221
|
+
return `export PATH=${posixShellSingleQuote(pathValue)}; ${trimmed}`;
|
|
2222
|
+
}
|
|
2223
|
+
var import_node_fs5, import_node_child_process, import_node_os4, import_node_path5, EXTRA_BIN_DIRS;
|
|
2064
2224
|
var init_path = __esm({
|
|
2065
2225
|
"src/agents/path.ts"() {
|
|
2066
2226
|
"use strict";
|
|
2227
|
+
import_node_fs5 = require("fs");
|
|
2228
|
+
import_node_child_process = require("child_process");
|
|
2067
2229
|
import_node_os4 = require("os");
|
|
2068
2230
|
import_node_path5 = require("path");
|
|
2069
2231
|
EXTRA_BIN_DIRS = [
|
|
@@ -2071,6 +2233,10 @@ var init_path = __esm({
|
|
|
2071
2233
|
".cargo/bin",
|
|
2072
2234
|
".nvm/current/bin",
|
|
2073
2235
|
".asdf/shims",
|
|
2236
|
+
".volta/bin",
|
|
2237
|
+
".npm-global/bin",
|
|
2238
|
+
// fnm default alias (common when shell init is skipped)
|
|
2239
|
+
".local/share/fnm/aliases/default/bin",
|
|
2074
2240
|
// pnpm / npm global bins (where `@brightsy/cli` typically lands)
|
|
2075
2241
|
"Library/pnpm",
|
|
2076
2242
|
".pnpm"
|
|
@@ -3158,7 +3324,7 @@ function isLocalPrFetchBranch(ref) {
|
|
|
3158
3324
|
async function createThreadWorktree(opts) {
|
|
3159
3325
|
let branchName = `thread/${opts.slug}`;
|
|
3160
3326
|
const worktreePath = (0, import_node_path6.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
3161
|
-
if ((0,
|
|
3327
|
+
if ((0, import_node_fs6.existsSync)(worktreePath)) {
|
|
3162
3328
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
3163
3329
|
}
|
|
3164
3330
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -3228,7 +3394,7 @@ async function createExistingBranchWorktree(opts) {
|
|
|
3228
3394
|
const branchName = opts.branchName.trim();
|
|
3229
3395
|
if (!branchName) throw new Error("branch name required");
|
|
3230
3396
|
const worktreePath = (0, import_node_path6.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
3231
|
-
if ((0,
|
|
3397
|
+
if ((0, import_node_fs6.existsSync)(worktreePath)) {
|
|
3232
3398
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
3233
3399
|
}
|
|
3234
3400
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -3489,9 +3655,9 @@ function sameRepoPath(a, b) {
|
|
|
3489
3655
|
}
|
|
3490
3656
|
function listLocalThreadBranchSlugs(repoPath) {
|
|
3491
3657
|
const refsDir = (0, import_node_path6.join)(repoPath, ".git", "refs", "heads", "thread");
|
|
3492
|
-
if (!(0,
|
|
3658
|
+
if (!(0, import_node_fs6.existsSync)(refsDir)) return [];
|
|
3493
3659
|
try {
|
|
3494
|
-
return (0,
|
|
3660
|
+
return (0, import_node_fs6.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
|
|
3495
3661
|
} catch {
|
|
3496
3662
|
return [];
|
|
3497
3663
|
}
|
|
@@ -3499,8 +3665,8 @@ function listLocalThreadBranchSlugs(repoPath) {
|
|
|
3499
3665
|
function collectTakenTeamSlugs(repoPath) {
|
|
3500
3666
|
const taken = /* @__PURE__ */ new Set();
|
|
3501
3667
|
const root = worktreesRoot(repoPath);
|
|
3502
|
-
if ((0,
|
|
3503
|
-
for (const entry of (0,
|
|
3668
|
+
if ((0, import_node_fs6.existsSync)(root)) {
|
|
3669
|
+
for (const entry of (0, import_node_fs6.readdirSync)(root, { withFileTypes: true })) {
|
|
3504
3670
|
if (entry.isDirectory() && entry.name !== ".DS_Store") {
|
|
3505
3671
|
taken.add(normalizeTakenSlug(entry.name));
|
|
3506
3672
|
}
|
|
@@ -3522,16 +3688,16 @@ function allocateTeamSlug(repoPath) {
|
|
|
3522
3688
|
for (let attempt = 0; attempt < 32; attempt++) {
|
|
3523
3689
|
const team = allocateTeamName(taken);
|
|
3524
3690
|
const path = (0, import_node_path6.join)(worktreesRoot(repoPath), team.slug);
|
|
3525
|
-
if (!(0,
|
|
3691
|
+
if (!(0, import_node_fs6.existsSync)(path)) return team;
|
|
3526
3692
|
taken.add(team.slug);
|
|
3527
3693
|
}
|
|
3528
3694
|
throw new Error("No available soccer team worktree directories left");
|
|
3529
3695
|
}
|
|
3530
|
-
var
|
|
3696
|
+
var import_node_fs6, import_node_path6;
|
|
3531
3697
|
var init_worktree = __esm({
|
|
3532
3698
|
"src/git/worktree.ts"() {
|
|
3533
3699
|
"use strict";
|
|
3534
|
-
|
|
3700
|
+
import_node_fs6 = require("fs");
|
|
3535
3701
|
import_node_path6 = require("path");
|
|
3536
3702
|
init_paths();
|
|
3537
3703
|
init_thread_store();
|
|
@@ -3611,7 +3777,7 @@ function coordinatorTurnReminder(opts) {
|
|
|
3611
3777
|
function ensureGlobalCoordinatorCwd(opts) {
|
|
3612
3778
|
const dir = globalAgentCwd();
|
|
3613
3779
|
try {
|
|
3614
|
-
(0,
|
|
3780
|
+
(0, import_node_fs7.mkdirSync)(dir, { recursive: true });
|
|
3615
3781
|
} catch {
|
|
3616
3782
|
return dir;
|
|
3617
3783
|
}
|
|
@@ -3619,7 +3785,7 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
3619
3785
|
let orchId = opts?.orchestratorThreadId?.trim() || "";
|
|
3620
3786
|
if (!orchId) {
|
|
3621
3787
|
try {
|
|
3622
|
-
const existing = (0,
|
|
3788
|
+
const existing = (0, import_node_fs7.readFileSync)((0, import_node_path7.join)(dir, "AGENTS.md"), "utf8");
|
|
3623
3789
|
const m = existing.match(
|
|
3624
3790
|
/YOUR orchestration thread id is `([0-9a-f-]{36})`/i
|
|
3625
3791
|
);
|
|
@@ -3661,9 +3827,9 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
3661
3827
|
"Always ask worktree agents to open draft PRs (`send_to_thread` + `gh pr create --draft -R <origin>`); never open PRs from the orchestrator."
|
|
3662
3828
|
].join("\n");
|
|
3663
3829
|
try {
|
|
3664
|
-
(0,
|
|
3830
|
+
(0, import_node_fs7.writeFileSync)((0, import_node_path7.join)(dir, "CLAUDE.md"), `${body}
|
|
3665
3831
|
`, "utf8");
|
|
3666
|
-
(0,
|
|
3832
|
+
(0, import_node_fs7.writeFileSync)((0, import_node_path7.join)(dir, "AGENTS.md"), `${body}
|
|
3667
3833
|
`, "utf8");
|
|
3668
3834
|
} catch {
|
|
3669
3835
|
}
|
|
@@ -3696,11 +3862,11 @@ function coordinatorSystemPrompt(opts) {
|
|
|
3696
3862
|
formatWorkspaceInventory(opts.workspaces)
|
|
3697
3863
|
].join("\n");
|
|
3698
3864
|
}
|
|
3699
|
-
var
|
|
3865
|
+
var import_node_fs7, import_node_path7, COORDINATOR_TOOL_PLAYBOOK;
|
|
3700
3866
|
var init_coordinator_prompt = __esm({
|
|
3701
3867
|
"src/orchestrator/coordinator-prompt.ts"() {
|
|
3702
3868
|
"use strict";
|
|
3703
|
-
|
|
3869
|
+
import_node_fs7 = require("fs");
|
|
3704
3870
|
import_node_path7 = require("path");
|
|
3705
3871
|
init_worktree();
|
|
3706
3872
|
init_app_settings();
|
|
@@ -3937,31 +4103,31 @@ function removedWorkspacesFile() {
|
|
|
3937
4103
|
}
|
|
3938
4104
|
function readAll() {
|
|
3939
4105
|
const path = workspacesFile();
|
|
3940
|
-
if (!(0,
|
|
4106
|
+
if (!(0, import_node_fs8.existsSync)(path)) return [];
|
|
3941
4107
|
try {
|
|
3942
|
-
const raw = JSON.parse((0,
|
|
4108
|
+
const raw = JSON.parse((0, import_node_fs8.readFileSync)(path, "utf8"));
|
|
3943
4109
|
return Array.isArray(raw) ? raw : [];
|
|
3944
4110
|
} catch {
|
|
3945
4111
|
return [];
|
|
3946
4112
|
}
|
|
3947
4113
|
}
|
|
3948
4114
|
function writeAll(list) {
|
|
3949
|
-
(0,
|
|
3950
|
-
(0,
|
|
4115
|
+
(0, import_node_fs8.mkdirSync)(appDataDir(), { recursive: true });
|
|
4116
|
+
(0, import_node_fs8.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
|
|
3951
4117
|
}
|
|
3952
4118
|
function readRemoved() {
|
|
3953
4119
|
const path = removedWorkspacesFile();
|
|
3954
|
-
if (!(0,
|
|
4120
|
+
if (!(0, import_node_fs8.existsSync)(path)) return /* @__PURE__ */ new Set();
|
|
3955
4121
|
try {
|
|
3956
|
-
const raw = JSON.parse((0,
|
|
4122
|
+
const raw = JSON.parse((0, import_node_fs8.readFileSync)(path, "utf8"));
|
|
3957
4123
|
return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
|
|
3958
4124
|
} catch {
|
|
3959
4125
|
return /* @__PURE__ */ new Set();
|
|
3960
4126
|
}
|
|
3961
4127
|
}
|
|
3962
4128
|
function writeRemoved(paths) {
|
|
3963
|
-
(0,
|
|
3964
|
-
(0,
|
|
4129
|
+
(0, import_node_fs8.mkdirSync)(appDataDir(), { recursive: true });
|
|
4130
|
+
(0, import_node_fs8.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
|
|
3965
4131
|
}
|
|
3966
4132
|
function rememberRemoved(repoPath) {
|
|
3967
4133
|
const next = readRemoved();
|
|
@@ -3984,7 +4150,7 @@ function listWorkspaces() {
|
|
|
3984
4150
|
async function addWorkspace(repoPath) {
|
|
3985
4151
|
const root = await resolveRepoRoot(repoPath);
|
|
3986
4152
|
if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
|
|
3987
|
-
if (!(0,
|
|
4153
|
+
if (!(0, import_node_fs8.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
|
|
3988
4154
|
forgetRemoved(root);
|
|
3989
4155
|
await ensureGhPreferOrigin(root);
|
|
3990
4156
|
const current = readAll();
|
|
@@ -4014,7 +4180,7 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
4014
4180
|
if (!path || path === "/" || isGlobalRepoPath(path) || byPath.has(path) || removed.has(path)) {
|
|
4015
4181
|
continue;
|
|
4016
4182
|
}
|
|
4017
|
-
if (!(0,
|
|
4183
|
+
if (!(0, import_node_fs8.existsSync)(path)) continue;
|
|
4018
4184
|
const ws = {
|
|
4019
4185
|
path,
|
|
4020
4186
|
name: (0, import_node_path8.basename)(path),
|
|
@@ -4027,11 +4193,11 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
4027
4193
|
if (dirty) writeAll(next);
|
|
4028
4194
|
return next.sort((a, b) => a.name.localeCompare(b.name));
|
|
4029
4195
|
}
|
|
4030
|
-
var
|
|
4196
|
+
var import_node_fs8, import_node_path8;
|
|
4031
4197
|
var init_workspaces = __esm({
|
|
4032
4198
|
"src/store/workspaces.ts"() {
|
|
4033
4199
|
"use strict";
|
|
4034
|
-
|
|
4200
|
+
import_node_fs8 = require("fs");
|
|
4035
4201
|
import_node_path8 = require("path");
|
|
4036
4202
|
init_paths();
|
|
4037
4203
|
init_global_workspace();
|
|
@@ -4045,26 +4211,26 @@ function brightsyConfigPath() {
|
|
|
4045
4211
|
}
|
|
4046
4212
|
function loadBrightsyConfig() {
|
|
4047
4213
|
const path = brightsyConfigPath();
|
|
4048
|
-
if (!(0,
|
|
4214
|
+
if (!(0, import_node_fs9.existsSync)(path)) {
|
|
4049
4215
|
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
4050
4216
|
}
|
|
4051
|
-
const raw = JSON.parse((0,
|
|
4217
|
+
const raw = JSON.parse((0, import_node_fs9.readFileSync)(path, "utf8"));
|
|
4052
4218
|
if (!raw.access_token || !raw.account_id) {
|
|
4053
4219
|
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
4054
4220
|
}
|
|
4055
4221
|
return raw;
|
|
4056
4222
|
}
|
|
4057
4223
|
function saveBrightsyConfig(cfg) {
|
|
4058
|
-
(0,
|
|
4224
|
+
(0, import_node_fs9.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
4059
4225
|
`, {
|
|
4060
4226
|
mode: 384
|
|
4061
4227
|
});
|
|
4062
4228
|
}
|
|
4063
|
-
var
|
|
4229
|
+
var import_node_fs9, import_node_os5, import_node_path9;
|
|
4064
4230
|
var init_config = __esm({
|
|
4065
4231
|
"src/brightsy/config.ts"() {
|
|
4066
4232
|
"use strict";
|
|
4067
|
-
|
|
4233
|
+
import_node_fs9 = require("fs");
|
|
4068
4234
|
import_node_os5 = require("os");
|
|
4069
4235
|
import_node_path9 = require("path");
|
|
4070
4236
|
}
|
|
@@ -4173,18 +4339,18 @@ function storePath() {
|
|
|
4173
4339
|
}
|
|
4174
4340
|
function readStore() {
|
|
4175
4341
|
const path = storePath();
|
|
4176
|
-
if (!(0,
|
|
4342
|
+
if (!(0, import_node_fs10.existsSync)(path)) return [];
|
|
4177
4343
|
try {
|
|
4178
|
-
const parsed = JSON.parse((0,
|
|
4344
|
+
const parsed = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf8"));
|
|
4179
4345
|
return Array.isArray(parsed.teams) ? parsed.teams : [];
|
|
4180
4346
|
} catch {
|
|
4181
4347
|
return [];
|
|
4182
4348
|
}
|
|
4183
4349
|
}
|
|
4184
4350
|
function writeStore(teams) {
|
|
4185
|
-
(0,
|
|
4351
|
+
(0, import_node_fs10.mkdirSync)(appDataDir(), { recursive: true });
|
|
4186
4352
|
const path = storePath();
|
|
4187
|
-
(0,
|
|
4353
|
+
(0, import_node_fs10.writeFileSync)(path, `${JSON.stringify({ teams }, null, 2)}
|
|
4188
4354
|
`, {
|
|
4189
4355
|
mode: 384
|
|
4190
4356
|
});
|
|
@@ -4346,11 +4512,11 @@ function brightsyMcpServerName(slug) {
|
|
|
4346
4512
|
const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
|
|
4347
4513
|
return `brightsy_${cleaned || "team"}`;
|
|
4348
4514
|
}
|
|
4349
|
-
var
|
|
4515
|
+
var import_node_fs10, import_node_path10;
|
|
4350
4516
|
var init_connected_teams = __esm({
|
|
4351
4517
|
"src/brightsy/connected-teams.ts"() {
|
|
4352
4518
|
"use strict";
|
|
4353
|
-
|
|
4519
|
+
import_node_fs10 = require("fs");
|
|
4354
4520
|
import_node_path10 = require("path");
|
|
4355
4521
|
init_paths();
|
|
4356
4522
|
init_accounts();
|
|
@@ -4525,6 +4691,11 @@ function normalizeTurnInput(input) {
|
|
|
4525
4691
|
if (typeof input === "string") return { prompt: input };
|
|
4526
4692
|
return { prompt: input.prompt, cachedPrefix: input.cachedPrefix?.trim() || void 0 };
|
|
4527
4693
|
}
|
|
4694
|
+
function dropCachedPrefixOnResume(input, sessionId) {
|
|
4695
|
+
const turn = normalizeTurnInput(input);
|
|
4696
|
+
if (sessionId) return { prompt: turn.prompt };
|
|
4697
|
+
return turn;
|
|
4698
|
+
}
|
|
4528
4699
|
function flattenTurnInput(input) {
|
|
4529
4700
|
const { cachedPrefix, prompt } = normalizeTurnInput(input);
|
|
4530
4701
|
if (!cachedPrefix) return prompt;
|
|
@@ -4713,9 +4884,13 @@ async function fetchTeamChatTargets(team) {
|
|
|
4713
4884
|
};
|
|
4714
4885
|
}
|
|
4715
4886
|
async function listBrightsyChatTargetsViaCli() {
|
|
4716
|
-
const listed = await run(
|
|
4717
|
-
|
|
4718
|
-
|
|
4887
|
+
const listed = await run(
|
|
4888
|
+
resolveAgentExecutable("brightsy"),
|
|
4889
|
+
["chat", "--list-targets", "--json"],
|
|
4890
|
+
{
|
|
4891
|
+
reject: false
|
|
4892
|
+
}
|
|
4893
|
+
);
|
|
4719
4894
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
4720
4895
|
throw new Error(
|
|
4721
4896
|
listed.stderr.trim() || "Failed to list Brightsy chat targets \u2014 is `brightsy` installed and logged in?"
|
|
@@ -4799,13 +4974,15 @@ async function syncCliForTarget(accountId) {
|
|
|
4799
4974
|
}
|
|
4800
4975
|
applyConnectedTeamToCli(team);
|
|
4801
4976
|
}
|
|
4802
|
-
var brightsyAdapter;
|
|
4977
|
+
var import_node_fs11, brightsyAdapter;
|
|
4803
4978
|
var init_brightsy = __esm({
|
|
4804
4979
|
"src/agents/brightsy.ts"() {
|
|
4805
4980
|
"use strict";
|
|
4981
|
+
import_node_fs11 = require("fs");
|
|
4806
4982
|
init_run();
|
|
4807
4983
|
init_connected_teams();
|
|
4808
4984
|
init_config();
|
|
4985
|
+
init_app_settings();
|
|
4809
4986
|
init_brightsy_targets();
|
|
4810
4987
|
init_error_detail();
|
|
4811
4988
|
init_turn_input();
|
|
@@ -4813,18 +4990,32 @@ var init_brightsy = __esm({
|
|
|
4813
4990
|
brightsyAdapter = {
|
|
4814
4991
|
kind: "brightsy",
|
|
4815
4992
|
async detect() {
|
|
4816
|
-
const
|
|
4817
|
-
if (
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4993
|
+
const brightsy = resolveAgentExecutable("brightsy");
|
|
4994
|
+
if (brightsy !== "brightsy") {
|
|
4995
|
+
if (!(0, import_node_fs11.existsSync)(brightsy)) {
|
|
4996
|
+
return {
|
|
4997
|
+
agent: "brightsy",
|
|
4998
|
+
installed: false,
|
|
4999
|
+
authenticated: false,
|
|
5000
|
+
linearMcp: false,
|
|
5001
|
+
warnings: [],
|
|
5002
|
+
reason: `Brightsy executable not found: ${brightsy}`
|
|
5003
|
+
};
|
|
5004
|
+
}
|
|
5005
|
+
} else {
|
|
5006
|
+
const which = await run("which", ["brightsy"], { reject: false });
|
|
5007
|
+
if (which.exitCode !== 0) {
|
|
5008
|
+
return {
|
|
5009
|
+
agent: "brightsy",
|
|
5010
|
+
installed: false,
|
|
5011
|
+
authenticated: false,
|
|
5012
|
+
linearMcp: false,
|
|
5013
|
+
warnings: [],
|
|
5014
|
+
reason: "brightsy CLI not found on PATH \u2014 npm i -g @brightsy/cli"
|
|
5015
|
+
};
|
|
5016
|
+
}
|
|
4826
5017
|
}
|
|
4827
|
-
const who = await run(
|
|
5018
|
+
const who = await run(brightsy, ["whoami"], { reject: false });
|
|
4828
5019
|
const authenticated = who.exitCode === 0 && /logged in as/i.test(who.stdout);
|
|
4829
5020
|
return {
|
|
4830
5021
|
agent: "brightsy",
|
|
@@ -4849,7 +5040,7 @@ var init_brightsy = __esm({
|
|
|
4849
5040
|
target.id
|
|
4850
5041
|
];
|
|
4851
5042
|
return {
|
|
4852
|
-
file: "brightsy",
|
|
5043
|
+
file: resolveAgentExecutable("brightsy"),
|
|
4853
5044
|
args,
|
|
4854
5045
|
cwd: thread.worktreePath,
|
|
4855
5046
|
// Piped stdin becomes the message body (avoids ARG_MAX for long seeds).
|
|
@@ -4866,7 +5057,11 @@ var init_brightsy = __esm({
|
|
|
4866
5057
|
const target = decodeBrightsyTarget(thread.model);
|
|
4867
5058
|
await syncCliForTarget(target.accountId);
|
|
4868
5059
|
const args = target.type === "model" ? ["chat", "--model", target.id] : ["chat", "--agent", target.id];
|
|
4869
|
-
return {
|
|
5060
|
+
return {
|
|
5061
|
+
file: resolveAgentExecutable("brightsy"),
|
|
5062
|
+
args,
|
|
5063
|
+
cwd: thread.worktreePath
|
|
5064
|
+
};
|
|
4870
5065
|
}
|
|
4871
5066
|
};
|
|
4872
5067
|
}
|
|
@@ -4918,6 +5113,18 @@ var init_claude_mcp = __esm({
|
|
|
4918
5113
|
}
|
|
4919
5114
|
});
|
|
4920
5115
|
|
|
5116
|
+
// src/mcp/profile.ts
|
|
5117
|
+
function sideboardMcpProfile(env = process.env) {
|
|
5118
|
+
return env[SIDEBOARD_MCP_PROFILE_ENV]?.trim().toLowerCase() === "worktree" ? "worktree" : "orchestration";
|
|
5119
|
+
}
|
|
5120
|
+
var SIDEBOARD_MCP_PROFILE_ENV;
|
|
5121
|
+
var init_profile = __esm({
|
|
5122
|
+
"src/mcp/profile.ts"() {
|
|
5123
|
+
"use strict";
|
|
5124
|
+
SIDEBOARD_MCP_PROFILE_ENV = "SIDEBOARD_MCP_PROFILE";
|
|
5125
|
+
}
|
|
5126
|
+
});
|
|
5127
|
+
|
|
4921
5128
|
// src/agents/node-launch.ts
|
|
4922
5129
|
function isAsarPath(filePath) {
|
|
4923
5130
|
return /\.asar([/\\]|$)/.test(filePath);
|
|
@@ -4965,6 +5172,38 @@ function isBrightsyConnected() {
|
|
|
4965
5172
|
return false;
|
|
4966
5173
|
}
|
|
4967
5174
|
}
|
|
5175
|
+
function promptMentionsBrightsy(text) {
|
|
5176
|
+
return BRIGHTSY_WORD.test(text ?? "");
|
|
5177
|
+
}
|
|
5178
|
+
function isBrightsyMcpToolName(name) {
|
|
5179
|
+
const n = name.toLowerCase();
|
|
5180
|
+
return n === "brightsy" || n.startsWith("mcp__brightsy") || n.startsWith("brightsy_");
|
|
5181
|
+
}
|
|
5182
|
+
function toolInputUsesBrightsyDatasource(input) {
|
|
5183
|
+
const ds = input?.datasource;
|
|
5184
|
+
return typeof ds === "string" && ds.toLowerCase() === "brightsy";
|
|
5185
|
+
}
|
|
5186
|
+
function messageUsedBrightsyMcp(msg) {
|
|
5187
|
+
if (msg.role === "user" && promptMentionsBrightsy(msg.text)) return true;
|
|
5188
|
+
for (const part of msg.parts ?? []) {
|
|
5189
|
+
if (part.type !== "tool") continue;
|
|
5190
|
+
if (isBrightsyMcpToolName(part.name)) return true;
|
|
5191
|
+
if (/present_(schema|files)$/i.test(part.name) && toolInputUsesBrightsyDatasource(part.input)) {
|
|
5192
|
+
return true;
|
|
5193
|
+
}
|
|
5194
|
+
}
|
|
5195
|
+
return false;
|
|
5196
|
+
}
|
|
5197
|
+
function threadRequestsBrightsyMcp(thread) {
|
|
5198
|
+
return (thread?.messages ?? []).some(messageUsedBrightsyMcp);
|
|
5199
|
+
}
|
|
5200
|
+
function shouldInjectBrightsyMcp(thread, opts) {
|
|
5201
|
+
if (!(opts?.connected ?? isBrightsyConnected())) return false;
|
|
5202
|
+
if (opts?.orchestrator) return true;
|
|
5203
|
+
const alwaysOn = opts?.alwaysOnWorktree ?? Boolean(loadAppSettings().brightsy?.injectWorktreeMcp);
|
|
5204
|
+
if (alwaysOn) return true;
|
|
5205
|
+
return threadRequestsBrightsyMcp(thread);
|
|
5206
|
+
}
|
|
4968
5207
|
function mcpLaunch(cmd, name, env) {
|
|
4969
5208
|
if (cmd === "brightsy-mcp") {
|
|
4970
5209
|
return { name, command: "brightsy-mcp", ...env ? { env } : {} };
|
|
@@ -5010,7 +5249,7 @@ function corePackageDir() {
|
|
|
5010
5249
|
}
|
|
5011
5250
|
function findSideboardMcpJsEntry() {
|
|
5012
5251
|
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
5013
|
-
if (override && (0,
|
|
5252
|
+
if (override && (0, import_node_fs12.existsSync)(override)) return override;
|
|
5014
5253
|
let dir = corePackageDir();
|
|
5015
5254
|
for (let i = 0; i < 10; i++) {
|
|
5016
5255
|
const candidates = [
|
|
@@ -5023,7 +5262,7 @@ function findSideboardMcpJsEntry() {
|
|
|
5023
5262
|
(0, import_node_path11.join)(dir, "cli/dist/index.js")
|
|
5024
5263
|
];
|
|
5025
5264
|
for (const p of candidates) {
|
|
5026
|
-
if ((0,
|
|
5265
|
+
if ((0, import_node_fs12.existsSync)(p)) return p;
|
|
5027
5266
|
}
|
|
5028
5267
|
const parent = (0, import_node_path11.dirname)(dir);
|
|
5029
5268
|
if (parent === dir) break;
|
|
@@ -5054,11 +5293,13 @@ async function buildInjectedMcpServers(opts) {
|
|
|
5054
5293
|
const servers = [];
|
|
5055
5294
|
if (opts.includeSideboard) {
|
|
5056
5295
|
const sideboard = await resolveSideboardMcpServer();
|
|
5296
|
+
const orchId = opts.orchestratorThreadId?.trim();
|
|
5297
|
+
const profile = orchId ? "orchestration" : "worktree";
|
|
5057
5298
|
sideboard.env = {
|
|
5058
5299
|
...sideboard.env ?? {},
|
|
5059
|
-
SIDEBOARD_APP_DATA: appDataDir()
|
|
5300
|
+
SIDEBOARD_APP_DATA: appDataDir(),
|
|
5301
|
+
[SIDEBOARD_MCP_PROFILE_ENV]: profile
|
|
5060
5302
|
};
|
|
5061
|
-
const orchId = opts.orchestratorThreadId?.trim();
|
|
5062
5303
|
if (orchId) {
|
|
5063
5304
|
sideboard.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID = orchId;
|
|
5064
5305
|
}
|
|
@@ -5133,19 +5374,19 @@ function writeMcpServersConfig(servers) {
|
|
|
5133
5374
|
...s.env ? { env: s.env } : {}
|
|
5134
5375
|
};
|
|
5135
5376
|
}
|
|
5136
|
-
const dir = (0,
|
|
5377
|
+
const dir = (0, import_node_fs12.mkdtempSync)((0, import_node_path11.join)((0, import_node_os6.tmpdir)(), "sideboard-mcp-"));
|
|
5137
5378
|
const cfgPath = (0, import_node_path11.join)(dir, "mcp.json");
|
|
5138
|
-
(0,
|
|
5379
|
+
(0, import_node_fs12.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
|
|
5139
5380
|
return cfgPath;
|
|
5140
5381
|
}
|
|
5141
5382
|
async function writeInjectedMcpConfig(opts) {
|
|
5142
5383
|
return writeMcpServersConfig(await buildInjectedMcpServers(opts));
|
|
5143
5384
|
}
|
|
5144
|
-
var
|
|
5385
|
+
var import_node_fs12, import_node_module, import_node_os6, import_node_path11, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
|
|
5145
5386
|
var init_injected_mcp = __esm({
|
|
5146
5387
|
"src/agents/injected-mcp.ts"() {
|
|
5147
5388
|
"use strict";
|
|
5148
|
-
|
|
5389
|
+
import_node_fs12 = require("fs");
|
|
5149
5390
|
import_node_module = require("module");
|
|
5150
5391
|
import_node_os6 = require("os");
|
|
5151
5392
|
import_node_path11 = require("path");
|
|
@@ -5153,6 +5394,8 @@ var init_injected_mcp = __esm({
|
|
|
5153
5394
|
init_run();
|
|
5154
5395
|
init_config();
|
|
5155
5396
|
init_connected_teams();
|
|
5397
|
+
init_profile();
|
|
5398
|
+
init_app_settings();
|
|
5156
5399
|
init_paths();
|
|
5157
5400
|
init_node_launch();
|
|
5158
5401
|
import_meta = {};
|
|
@@ -5172,6 +5415,7 @@ var init_injected_mcp = __esm({
|
|
|
5172
5415
|
"mcp__brightsy__*"
|
|
5173
5416
|
];
|
|
5174
5417
|
brightsyMcpCommandCache = null;
|
|
5418
|
+
BRIGHTSY_WORD = /(?<![a-z0-9_-])brightsy(?![a-z0-9_-])/i;
|
|
5175
5419
|
}
|
|
5176
5420
|
});
|
|
5177
5421
|
|
|
@@ -5326,11 +5570,11 @@ function parseIssuesJson(raw) {
|
|
|
5326
5570
|
}
|
|
5327
5571
|
return [];
|
|
5328
5572
|
}
|
|
5329
|
-
var
|
|
5573
|
+
var import_node_fs13, BASE_ALLOWED_TOOLS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
|
|
5330
5574
|
var init_claude = __esm({
|
|
5331
5575
|
"src/agents/claude.ts"() {
|
|
5332
5576
|
"use strict";
|
|
5333
|
-
|
|
5577
|
+
import_node_fs13 = require("fs");
|
|
5334
5578
|
init_run();
|
|
5335
5579
|
init_app_settings();
|
|
5336
5580
|
init_claude_mcp();
|
|
@@ -5359,7 +5603,7 @@ var init_claude = __esm({
|
|
|
5359
5603
|
async detect() {
|
|
5360
5604
|
const claude = resolveClaudeExecutable();
|
|
5361
5605
|
if (claude !== "claude") {
|
|
5362
|
-
if (!(0,
|
|
5606
|
+
if (!(0, import_node_fs13.existsSync)(claude)) {
|
|
5363
5607
|
return {
|
|
5364
5608
|
agent: "claude",
|
|
5365
5609
|
installed: false,
|
|
@@ -5398,9 +5642,8 @@ var init_claude = __esm({
|
|
|
5398
5642
|
},
|
|
5399
5643
|
async buildTurn(thread, input) {
|
|
5400
5644
|
const claude = resolveClaudeExecutable();
|
|
5401
|
-
const turn = normalizeTurnInput(input);
|
|
5402
5645
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
5403
|
-
const effective = sessionId
|
|
5646
|
+
const effective = dropCachedPrefixOnResume(input, sessionId);
|
|
5404
5647
|
const promptText = flattenTurnInput(effective);
|
|
5405
5648
|
const useStdin = promptText.length > CLAUDE_PROMPT_ARG_MAX;
|
|
5406
5649
|
if (process.env.SIDEBOARD_DEBUG_CLAUDE_TURN === "1") {
|
|
@@ -5413,7 +5656,9 @@ var init_claude = __esm({
|
|
|
5413
5656
|
const isOrchestrator = isOrchestratorThread2(thread);
|
|
5414
5657
|
const injectedServers = await buildInjectedMcpServers({
|
|
5415
5658
|
includeSideboard: true,
|
|
5416
|
-
includeBrightsy:
|
|
5659
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
5660
|
+
orchestrator: isOrchestrator
|
|
5661
|
+
}),
|
|
5417
5662
|
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
5418
5663
|
});
|
|
5419
5664
|
const injectedBrightsyNames = injectedServers.filter((s) => s.name === "brightsy" || s.name.startsWith("brightsy_")).map((s) => s.name);
|
|
@@ -5587,9 +5832,14 @@ async function listCodexModels() {
|
|
|
5587
5832
|
if (cachedCodexModels && now - cachedCodexModels.at < CODEX_MODEL_CACHE_MS) {
|
|
5588
5833
|
return cachedCodexModels.models;
|
|
5589
5834
|
}
|
|
5590
|
-
const
|
|
5591
|
-
if (
|
|
5592
|
-
|
|
5835
|
+
const codex = resolveAgentExecutable("codex");
|
|
5836
|
+
if (codex === "codex") {
|
|
5837
|
+
const which = await run("which", ["codex"], { reject: false });
|
|
5838
|
+
if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
|
|
5839
|
+
} else if (!(0, import_node_fs14.existsSync)(codex)) {
|
|
5840
|
+
return FALLBACK_CODEX_MODELS;
|
|
5841
|
+
}
|
|
5842
|
+
const listed = await run(codex, ["debug", "models"], { reject: false });
|
|
5593
5843
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
5594
5844
|
return cachedCodexModels?.models ?? FALLBACK_CODEX_MODELS;
|
|
5595
5845
|
}
|
|
@@ -5628,8 +5878,8 @@ function codexConfigHasNetworkAccess() {
|
|
|
5628
5878
|
(0, import_node_path12.join)((0, import_node_os7.homedir)(), ".config", "codex", "config.toml")
|
|
5629
5879
|
];
|
|
5630
5880
|
for (const path of candidates) {
|
|
5631
|
-
if (!(0,
|
|
5632
|
-
const text = (0,
|
|
5881
|
+
if (!(0, import_node_fs14.existsSync)(path)) continue;
|
|
5882
|
+
const text = (0, import_node_fs14.readFileSync)(path, "utf8");
|
|
5633
5883
|
if (/network_access\s*=\s*true/.test(text)) return true;
|
|
5634
5884
|
}
|
|
5635
5885
|
return false;
|
|
@@ -5662,21 +5912,23 @@ function asRecord(value) {
|
|
|
5662
5912
|
}
|
|
5663
5913
|
function codexLooksAuthenticated() {
|
|
5664
5914
|
const authPath = (0, import_node_path12.join)((0, import_node_os7.homedir)(), ".codex", "auth.json");
|
|
5665
|
-
if (!(0,
|
|
5915
|
+
if (!(0, import_node_fs14.existsSync)(authPath)) return false;
|
|
5666
5916
|
try {
|
|
5667
|
-
return (0,
|
|
5917
|
+
return (0, import_node_fs14.statSync)(authPath).size > 2;
|
|
5668
5918
|
} catch {
|
|
5669
5919
|
return false;
|
|
5670
5920
|
}
|
|
5671
5921
|
}
|
|
5672
|
-
var
|
|
5922
|
+
var import_node_fs14, import_node_os7, import_node_path12, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
|
|
5673
5923
|
var init_codex = __esm({
|
|
5674
5924
|
"src/agents/codex.ts"() {
|
|
5675
5925
|
"use strict";
|
|
5676
|
-
|
|
5926
|
+
import_node_fs14 = require("fs");
|
|
5677
5927
|
import_node_os7 = require("os");
|
|
5678
5928
|
import_node_path12 = require("path");
|
|
5679
5929
|
init_run();
|
|
5930
|
+
init_app_settings();
|
|
5931
|
+
init_global_workspace();
|
|
5680
5932
|
init_error_detail();
|
|
5681
5933
|
init_injected_mcp();
|
|
5682
5934
|
init_turn_input();
|
|
@@ -5694,16 +5946,30 @@ var init_codex = __esm({
|
|
|
5694
5946
|
codexAdapter = {
|
|
5695
5947
|
kind: "codex",
|
|
5696
5948
|
async detect() {
|
|
5697
|
-
const
|
|
5698
|
-
if (
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5949
|
+
const codex = resolveAgentExecutable("codex");
|
|
5950
|
+
if (codex !== "codex") {
|
|
5951
|
+
if (!(0, import_node_fs14.existsSync)(codex)) {
|
|
5952
|
+
return {
|
|
5953
|
+
agent: "codex",
|
|
5954
|
+
installed: false,
|
|
5955
|
+
authenticated: false,
|
|
5956
|
+
linearMcp: false,
|
|
5957
|
+
warnings: [],
|
|
5958
|
+
reason: `Codex executable not found: ${codex}`
|
|
5959
|
+
};
|
|
5960
|
+
}
|
|
5961
|
+
} else {
|
|
5962
|
+
const which = await run("which", ["codex"], { reject: false, timeoutMs: 3e3 });
|
|
5963
|
+
if (which.exitCode !== 0) {
|
|
5964
|
+
return {
|
|
5965
|
+
agent: "codex",
|
|
5966
|
+
installed: false,
|
|
5967
|
+
authenticated: false,
|
|
5968
|
+
linearMcp: false,
|
|
5969
|
+
warnings: [],
|
|
5970
|
+
reason: "codex CLI not found on PATH"
|
|
5971
|
+
};
|
|
5972
|
+
}
|
|
5707
5973
|
}
|
|
5708
5974
|
const authenticated = codexLooksAuthenticated();
|
|
5709
5975
|
const linearMcp = false;
|
|
@@ -5723,22 +5989,24 @@ var init_codex = __esm({
|
|
|
5723
5989
|
};
|
|
5724
5990
|
},
|
|
5725
5991
|
async buildTurn(thread, input) {
|
|
5726
|
-
const prompt = flattenTurnInput(input);
|
|
5727
5992
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
5993
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, sessionId));
|
|
5728
5994
|
const useStdin = prompt.length > CODEX_PROMPT_ARG_MAX;
|
|
5729
5995
|
const promptArg = useStdin ? "-" : prompt;
|
|
5730
5996
|
if (process.env.SIDEBOARD_DEBUG_CODEX_TURN === "1") {
|
|
5731
|
-
const { cachedPrefix } = normalizeTurnInput(input);
|
|
5732
5997
|
console.error(
|
|
5733
|
-
`[sideboard/codex] promptChars=${prompt.length} resumed=${Boolean(sessionId)} stdin=${useStdin} hasPrefix=${
|
|
5998
|
+
`[sideboard/codex] promptChars=${prompt.length} resumed=${Boolean(sessionId)} stdin=${useStdin} hasPrefix=${prompt.includes("Current request:")}`
|
|
5734
5999
|
);
|
|
5735
6000
|
}
|
|
5736
6001
|
const mode = permissionMode(thread);
|
|
5737
6002
|
const model = thread.model?.trim();
|
|
6003
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
5738
6004
|
const injected = await buildInjectedMcpServers({
|
|
5739
6005
|
includeSideboard: true,
|
|
5740
|
-
includeBrightsy:
|
|
5741
|
-
|
|
6006
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
6007
|
+
orchestrator: isOrchestrator
|
|
6008
|
+
}),
|
|
6009
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
5742
6010
|
});
|
|
5743
6011
|
const mcpOverrides = toCodexMcpConfigArgs(injected);
|
|
5744
6012
|
const execOpts = [
|
|
@@ -5758,7 +6026,7 @@ var init_codex = __esm({
|
|
|
5758
6026
|
];
|
|
5759
6027
|
const args = sessionId ? ["exec", ...execOpts, "resume", sessionId, promptArg] : ["exec", ...execOpts, promptArg];
|
|
5760
6028
|
return {
|
|
5761
|
-
file: "codex",
|
|
6029
|
+
file: resolveAgentExecutable("codex"),
|
|
5762
6030
|
args,
|
|
5763
6031
|
cwd: thread.worktreePath,
|
|
5764
6032
|
stdin: useStdin ? `${prompt}
|
|
@@ -5854,16 +6122,17 @@ var init_codex = __esm({
|
|
|
5854
6122
|
return cached;
|
|
5855
6123
|
},
|
|
5856
6124
|
async buildAttach(thread) {
|
|
6125
|
+
const codex = resolveAgentExecutable("codex");
|
|
5857
6126
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
5858
6127
|
if (sessionId) {
|
|
5859
6128
|
return {
|
|
5860
|
-
file:
|
|
6129
|
+
file: codex,
|
|
5861
6130
|
args: ["exec", "--cd", thread.worktreePath, "resume", sessionId],
|
|
5862
6131
|
cwd: thread.worktreePath
|
|
5863
6132
|
};
|
|
5864
6133
|
}
|
|
5865
6134
|
return {
|
|
5866
|
-
file:
|
|
6135
|
+
file: codex,
|
|
5867
6136
|
args: ["--cd", thread.worktreePath],
|
|
5868
6137
|
cwd: thread.worktreePath
|
|
5869
6138
|
};
|
|
@@ -5871,7 +6140,7 @@ var init_codex = __esm({
|
|
|
5871
6140
|
async listLinearIssues(_repoPath) {
|
|
5872
6141
|
const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
|
|
5873
6142
|
const { stdout, exitCode } = await run(
|
|
5874
|
-
"codex",
|
|
6143
|
+
resolveAgentExecutable("codex"),
|
|
5875
6144
|
[
|
|
5876
6145
|
"exec",
|
|
5877
6146
|
"--json",
|
|
@@ -6134,21 +6403,22 @@ function cursorRunnerPath() {
|
|
|
6134
6403
|
(0, import_node_path13.join)(root, "src", "agents", "cursor-runner.ts")
|
|
6135
6404
|
];
|
|
6136
6405
|
for (const candidate of candidates) {
|
|
6137
|
-
if ((0,
|
|
6406
|
+
if ((0, import_node_fs15.existsSync)(candidate)) return candidate;
|
|
6138
6407
|
}
|
|
6139
6408
|
return candidates[0];
|
|
6140
6409
|
}
|
|
6141
|
-
var
|
|
6410
|
+
var import_node_fs15, import_node_module2, import_node_path13, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
|
|
6142
6411
|
var init_cursor = __esm({
|
|
6143
6412
|
"src/agents/cursor.ts"() {
|
|
6144
6413
|
"use strict";
|
|
6145
|
-
|
|
6414
|
+
import_node_fs15 = require("fs");
|
|
6146
6415
|
import_node_module2 = require("module");
|
|
6147
6416
|
import_node_path13 = require("path");
|
|
6148
6417
|
import_node_url2 = require("url");
|
|
6149
6418
|
import_sdk = require("@cursor/sdk");
|
|
6150
6419
|
init_run();
|
|
6151
6420
|
init_app_settings();
|
|
6421
|
+
init_global_workspace();
|
|
6152
6422
|
init_cursor_events();
|
|
6153
6423
|
init_injected_mcp();
|
|
6154
6424
|
init_node_launch();
|
|
@@ -6185,13 +6455,16 @@ var init_cursor = __esm({
|
|
|
6185
6455
|
};
|
|
6186
6456
|
},
|
|
6187
6457
|
async buildTurn(thread, input) {
|
|
6188
|
-
const prompt = flattenTurnInput(input);
|
|
6189
6458
|
const agentId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
6459
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, agentId));
|
|
6190
6460
|
const apiKey = resolveCursorApiKey() || void 0;
|
|
6461
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
6191
6462
|
const injected = await buildInjectedMcpServers({
|
|
6192
6463
|
includeSideboard: true,
|
|
6193
|
-
includeBrightsy:
|
|
6194
|
-
|
|
6464
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
6465
|
+
orchestrator: isOrchestrator
|
|
6466
|
+
}),
|
|
6467
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
6195
6468
|
});
|
|
6196
6469
|
const mcpServers = toCursorMcpServers(injected);
|
|
6197
6470
|
const req = {
|
|
@@ -6262,9 +6535,14 @@ async function listOpencodeModels() {
|
|
|
6262
6535
|
if (cachedOpencodeModels && now - cachedOpencodeModels.at < OPENCODE_MODEL_CACHE_MS) {
|
|
6263
6536
|
return cachedOpencodeModels.models;
|
|
6264
6537
|
}
|
|
6265
|
-
const
|
|
6266
|
-
if (
|
|
6267
|
-
|
|
6538
|
+
const opencode = resolveAgentExecutable("opencode");
|
|
6539
|
+
if (opencode === "opencode") {
|
|
6540
|
+
const which = await run("which", ["opencode"], { reject: false });
|
|
6541
|
+
if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
|
|
6542
|
+
} else if (!(0, import_node_fs16.existsSync)(opencode)) {
|
|
6543
|
+
return FALLBACK_OPENCODE_MODELS;
|
|
6544
|
+
}
|
|
6545
|
+
const listed = await run(opencode, ["models"], { reject: false });
|
|
6268
6546
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
6269
6547
|
return cachedOpencodeModels?.models ?? FALLBACK_OPENCODE_MODELS;
|
|
6270
6548
|
}
|
|
@@ -6291,11 +6569,14 @@ function usageFromOpencode(tokens) {
|
|
|
6291
6569
|
cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
|
|
6292
6570
|
};
|
|
6293
6571
|
}
|
|
6294
|
-
var FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
|
|
6572
|
+
var import_node_fs16, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
|
|
6295
6573
|
var init_opencode = __esm({
|
|
6296
6574
|
"src/agents/opencode.ts"() {
|
|
6297
6575
|
"use strict";
|
|
6576
|
+
import_node_fs16 = require("fs");
|
|
6298
6577
|
init_run();
|
|
6578
|
+
init_app_settings();
|
|
6579
|
+
init_global_workspace();
|
|
6299
6580
|
init_error_detail();
|
|
6300
6581
|
init_injected_mcp();
|
|
6301
6582
|
init_turn_input();
|
|
@@ -6316,20 +6597,34 @@ var init_opencode = __esm({
|
|
|
6316
6597
|
opencodeAdapter = {
|
|
6317
6598
|
kind: "opencode",
|
|
6318
6599
|
async detect() {
|
|
6319
|
-
const
|
|
6320
|
-
if (
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6600
|
+
const opencode = resolveAgentExecutable("opencode");
|
|
6601
|
+
if (opencode !== "opencode") {
|
|
6602
|
+
if (!(0, import_node_fs16.existsSync)(opencode)) {
|
|
6603
|
+
return {
|
|
6604
|
+
agent: "opencode",
|
|
6605
|
+
installed: false,
|
|
6606
|
+
authenticated: false,
|
|
6607
|
+
linearMcp: false,
|
|
6608
|
+
warnings: [],
|
|
6609
|
+
reason: `OpenCode executable not found: ${opencode}`
|
|
6610
|
+
};
|
|
6611
|
+
}
|
|
6612
|
+
} else {
|
|
6613
|
+
const which = await run("which", ["opencode"], { reject: false });
|
|
6614
|
+
if (which.exitCode !== 0) {
|
|
6615
|
+
return {
|
|
6616
|
+
agent: "opencode",
|
|
6617
|
+
installed: false,
|
|
6618
|
+
authenticated: false,
|
|
6619
|
+
linearMcp: false,
|
|
6620
|
+
warnings: [],
|
|
6621
|
+
reason: "opencode CLI not found on PATH"
|
|
6622
|
+
};
|
|
6623
|
+
}
|
|
6329
6624
|
}
|
|
6330
|
-
const auth = await run(
|
|
6625
|
+
const auth = await run(opencode, ["auth", "list"], { reject: false });
|
|
6331
6626
|
const authenticated = auth.exitCode === 0 && auth.stdout.trim().length > 0;
|
|
6332
|
-
const mcp = await run(
|
|
6627
|
+
const mcp = await run(opencode, ["mcp", "list"], { reject: false });
|
|
6333
6628
|
const linearMcp = /linear/i.test(mcp.stdout + mcp.stderr);
|
|
6334
6629
|
return {
|
|
6335
6630
|
agent: "opencode",
|
|
@@ -6341,8 +6636,8 @@ var init_opencode = __esm({
|
|
|
6341
6636
|
};
|
|
6342
6637
|
},
|
|
6343
6638
|
async buildTurn(thread, input) {
|
|
6344
|
-
const prompt = flattenTurnInput(input);
|
|
6345
6639
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
6640
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, sessionId));
|
|
6346
6641
|
const mode = permissionMode(thread);
|
|
6347
6642
|
const model = thread.model?.trim();
|
|
6348
6643
|
const args = [
|
|
@@ -6358,14 +6653,17 @@ var init_opencode = __esm({
|
|
|
6358
6653
|
if (model) {
|
|
6359
6654
|
args.push("--model", model);
|
|
6360
6655
|
}
|
|
6656
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
6361
6657
|
const injected = await buildInjectedMcpServers({
|
|
6362
6658
|
includeSideboard: true,
|
|
6363
|
-
includeBrightsy:
|
|
6364
|
-
|
|
6659
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
6660
|
+
orchestrator: isOrchestrator
|
|
6661
|
+
}),
|
|
6662
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
6365
6663
|
});
|
|
6366
6664
|
const mcpContent = injected.length > 0 ? toOpencodeMcpConfigContent(injected) : null;
|
|
6367
6665
|
return {
|
|
6368
|
-
file: "opencode",
|
|
6666
|
+
file: resolveAgentExecutable("opencode"),
|
|
6369
6667
|
args,
|
|
6370
6668
|
cwd: thread.worktreePath,
|
|
6371
6669
|
// `opencode run` treats non-TTY stdin as the message body when no positional
|
|
@@ -6441,7 +6739,7 @@ var init_opencode = __esm({
|
|
|
6441
6739
|
async resolveSessionId(worktreePath, cached) {
|
|
6442
6740
|
const cachedId = cached?.trim() || null;
|
|
6443
6741
|
const listed = await run(
|
|
6444
|
-
"opencode",
|
|
6742
|
+
resolveAgentExecutable("opencode"),
|
|
6445
6743
|
["session", "list", "--format", "json"],
|
|
6446
6744
|
{ cwd: worktreePath, reject: false }
|
|
6447
6745
|
);
|
|
@@ -6472,7 +6770,7 @@ var init_opencode = __esm({
|
|
|
6472
6770
|
const args = ["--dir", thread.worktreePath];
|
|
6473
6771
|
if (sessionId) args.push("--session", sessionId);
|
|
6474
6772
|
return {
|
|
6475
|
-
file: "opencode",
|
|
6773
|
+
file: resolveAgentExecutable("opencode"),
|
|
6476
6774
|
args,
|
|
6477
6775
|
cwd: thread.worktreePath,
|
|
6478
6776
|
env: {
|
|
@@ -6483,7 +6781,7 @@ var init_opencode = __esm({
|
|
|
6483
6781
|
async listLinearIssues(_repoPath) {
|
|
6484
6782
|
const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
|
|
6485
6783
|
const { stdout, exitCode } = await run(
|
|
6486
|
-
"opencode",
|
|
6784
|
+
resolveAgentExecutable("opencode"),
|
|
6487
6785
|
["run", prompt, "--format", "json"],
|
|
6488
6786
|
{
|
|
6489
6787
|
reject: false,
|
|
@@ -6716,9 +7014,30 @@ function getAgentSetupInfo(agent) {
|
|
|
6716
7014
|
function listAgentSetupInfo() {
|
|
6717
7015
|
return Object.values(SETUP);
|
|
6718
7016
|
}
|
|
6719
|
-
|
|
6720
|
-
|
|
7017
|
+
function resolveLoginCommand(agent) {
|
|
7018
|
+
const info = getAgentSetupInfo(agent);
|
|
7019
|
+
if (!info.loginCommand) return null;
|
|
7020
|
+
if (!CLI_LOGIN_AGENTS.has(agent)) return info.loginCommand;
|
|
7021
|
+
const exe = resolveAgentExecutable(agent);
|
|
7022
|
+
return info.loginCommand.replace(/^\S+/, exe);
|
|
7023
|
+
}
|
|
7024
|
+
async function prepareTerminalCommand(command) {
|
|
7025
|
+
enrichPathWithNpmGlobalBin();
|
|
6721
7026
|
const trimmed = command.trim();
|
|
7027
|
+
if (!trimmed) return trimmed;
|
|
7028
|
+
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
7029
|
+
const match = /^(\S+)(\s[\s\S]*)?$/.exec(trimmed);
|
|
7030
|
+
const bin = match?.[1];
|
|
7031
|
+
let whichPath = null;
|
|
7032
|
+
if (bin && !bin.includes("/") && !bin.includes("\\")) {
|
|
7033
|
+
const which = await run("which", [bin], { reject: false, timeoutMs: 3e3 });
|
|
7034
|
+
whichPath = which.exitCode === 0 ? which.stdout.trim() : null;
|
|
7035
|
+
}
|
|
7036
|
+
const resolved = resolveCommandBinarySync(trimmed, whichPath);
|
|
7037
|
+
return withExportedPath(resolved, process.env.PATH ?? "");
|
|
7038
|
+
}
|
|
7039
|
+
async function openInSystemTerminal(command) {
|
|
7040
|
+
const trimmed = (await prepareTerminalCommand(command)).trim();
|
|
6722
7041
|
if (!trimmed) throw new Error("Command is empty");
|
|
6723
7042
|
if (process.platform === "darwin") {
|
|
6724
7043
|
const escaped = trimmed.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
@@ -6779,7 +7098,7 @@ async function installAgent(agent) {
|
|
|
6779
7098
|
message: `Opened Terminal to run: ${info.installCommand}`
|
|
6780
7099
|
};
|
|
6781
7100
|
}
|
|
6782
|
-
|
|
7101
|
+
enrichPathWithNpmGlobalBin();
|
|
6783
7102
|
const result = await run("npm", ["install", "-g", info.npmPackage], { reject: false });
|
|
6784
7103
|
const ok = result.exitCode === 0;
|
|
6785
7104
|
if (!ok) {
|
|
@@ -6805,36 +7124,46 @@ async function installAgent(agent) {
|
|
|
6805
7124
|
};
|
|
6806
7125
|
}
|
|
6807
7126
|
}
|
|
7127
|
+
enrichPathWithNpmGlobalBin();
|
|
7128
|
+
const cliBin = agent === "cursor" ? null : CLI_BIN[agent];
|
|
7129
|
+
let binPath = null;
|
|
7130
|
+
if (cliBin) {
|
|
7131
|
+
const which = await run("which", [cliBin], { reject: false, timeoutMs: 3e3 });
|
|
7132
|
+
binPath = which.exitCode === 0 ? which.stdout.trim().split(/\r?\n/).find(Boolean) ?? null : null;
|
|
7133
|
+
}
|
|
6808
7134
|
return {
|
|
6809
7135
|
ok: true,
|
|
6810
7136
|
command: info.installCommand,
|
|
6811
7137
|
exitCode: 0,
|
|
6812
7138
|
stdout: result.stdout,
|
|
6813
7139
|
stderr: result.stderr,
|
|
6814
|
-
message: `Installed ${info.npmPackage}`
|
|
7140
|
+
message: binPath ? `Installed ${info.npmPackage} \u2192 ${binPath}` : `Installed ${info.npmPackage} (CLI not yet on PATH \u2014 Log in still exports Electron\u2019s PATH into Terminal)`
|
|
6815
7141
|
};
|
|
6816
7142
|
}
|
|
6817
7143
|
async function loginAgent(agent) {
|
|
6818
7144
|
const info = getAgentSetupInfo(agent);
|
|
6819
|
-
|
|
7145
|
+
const loginCommand = resolveLoginCommand(agent);
|
|
7146
|
+
if (!loginCommand) {
|
|
6820
7147
|
return {
|
|
6821
7148
|
ok: true,
|
|
6822
7149
|
message: info.kind === "bundled-sdk" || info.kind === "api-key" ? info.summary : `No login command for ${agent}`
|
|
6823
7150
|
};
|
|
6824
7151
|
}
|
|
6825
|
-
await
|
|
7152
|
+
const prepared = await prepareTerminalCommand(loginCommand);
|
|
7153
|
+
await openInSystemTerminal(prepared);
|
|
6826
7154
|
return {
|
|
6827
7155
|
ok: true,
|
|
6828
7156
|
openedTerminal: true,
|
|
6829
|
-
command:
|
|
6830
|
-
message: `Opened Terminal to run: ${
|
|
7157
|
+
command: prepared,
|
|
7158
|
+
message: `Opened Terminal to run: ${prepared}`
|
|
6831
7159
|
};
|
|
6832
7160
|
}
|
|
6833
|
-
var SETUP;
|
|
7161
|
+
var SETUP, CLI_BIN, CLI_LOGIN_AGENTS;
|
|
6834
7162
|
var init_install = __esm({
|
|
6835
7163
|
"src/agents/install.ts"() {
|
|
6836
7164
|
"use strict";
|
|
6837
7165
|
init_run();
|
|
7166
|
+
init_app_settings();
|
|
6838
7167
|
init_path();
|
|
6839
7168
|
SETUP = {
|
|
6840
7169
|
claude: {
|
|
@@ -6883,6 +7212,18 @@ var init_install = __esm({
|
|
|
6883
7212
|
npmPackage: "@brightsy/cli"
|
|
6884
7213
|
}
|
|
6885
7214
|
};
|
|
7215
|
+
CLI_BIN = {
|
|
7216
|
+
claude: "claude",
|
|
7217
|
+
codex: "codex",
|
|
7218
|
+
opencode: "opencode",
|
|
7219
|
+
brightsy: "brightsy"
|
|
7220
|
+
};
|
|
7221
|
+
CLI_LOGIN_AGENTS = /* @__PURE__ */ new Set([
|
|
7222
|
+
"claude",
|
|
7223
|
+
"codex",
|
|
7224
|
+
"opencode",
|
|
7225
|
+
"brightsy"
|
|
7226
|
+
]);
|
|
6886
7227
|
}
|
|
6887
7228
|
});
|
|
6888
7229
|
|
|
@@ -6902,6 +7243,7 @@ __export(agents_exports, {
|
|
|
6902
7243
|
cursorSdkMessageToEvents: () => cursorSdkMessageToEvents,
|
|
6903
7244
|
decodeBrightsyTarget: () => decodeBrightsyTarget,
|
|
6904
7245
|
encodeBrightsyTarget: () => encodeBrightsyTarget,
|
|
7246
|
+
enrichPathWithNpmGlobalBin: () => enrichPathWithNpmGlobalBin,
|
|
6905
7247
|
ensureAgentPath: () => ensureAgentPath,
|
|
6906
7248
|
getAdapter: () => getAdapter,
|
|
6907
7249
|
getAgentSetupInfo: () => getAgentSetupInfo,
|
|
@@ -6921,8 +7263,13 @@ __export(agents_exports, {
|
|
|
6921
7263
|
parseCursorRunnerLine: () => parseCursorRunnerLine,
|
|
6922
7264
|
parseSessionQuotaResetAt: () => parseSessionQuotaResetAt,
|
|
6923
7265
|
permissionMode: () => permissionMode,
|
|
7266
|
+
posixShellSingleQuote: () => posixShellSingleQuote,
|
|
7267
|
+
prepareTerminalCommand: () => prepareTerminalCommand,
|
|
7268
|
+
resolveCommandBinarySync: () => resolveCommandBinarySync,
|
|
6924
7269
|
resolveCursorModelId: () => resolveCursorModelId,
|
|
6925
|
-
|
|
7270
|
+
resolveLoginCommand: () => resolveLoginCommand,
|
|
7271
|
+
resolveQuotaFallbackAgent: () => resolveQuotaFallbackAgent,
|
|
7272
|
+
withExportedPath: () => withExportedPath
|
|
6926
7273
|
});
|
|
6927
7274
|
function getAdapter(kind) {
|
|
6928
7275
|
return adapters[kind];
|
|
@@ -7034,17 +7381,17 @@ __export(plan_file_exports, {
|
|
|
7034
7381
|
});
|
|
7035
7382
|
function ensureAttachmentsGitignore2(worktreePath) {
|
|
7036
7383
|
const gitignoreAbs = (0, import_node_path24.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
7037
|
-
if ((0,
|
|
7038
|
-
(0,
|
|
7039
|
-
(0,
|
|
7384
|
+
if ((0, import_node_fs29.existsSync)(gitignoreAbs)) return;
|
|
7385
|
+
(0, import_node_fs29.mkdirSync)((0, import_node_path24.dirname)(gitignoreAbs), { recursive: true });
|
|
7386
|
+
(0, import_node_fs29.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
7040
7387
|
}
|
|
7041
7388
|
function planFileAbs(worktreePath) {
|
|
7042
7389
|
return (0, import_node_path24.join)(worktreePath, PLAN_FILE_REL);
|
|
7043
7390
|
}
|
|
7044
7391
|
function readTextIfPresent2(abs) {
|
|
7045
|
-
if (!(0,
|
|
7392
|
+
if (!(0, import_node_fs29.existsSync)(abs)) return null;
|
|
7046
7393
|
try {
|
|
7047
|
-
const content = (0,
|
|
7394
|
+
const content = (0, import_node_fs29.readFileSync)(abs, "utf8");
|
|
7048
7395
|
return content.trim() ? content : null;
|
|
7049
7396
|
} catch {
|
|
7050
7397
|
return null;
|
|
@@ -7056,16 +7403,16 @@ function readPlanFile(worktreePath) {
|
|
|
7056
7403
|
function writePlanFile(worktreePath, content) {
|
|
7057
7404
|
ensureAttachmentsGitignore2(worktreePath);
|
|
7058
7405
|
const abs = planFileAbs(worktreePath);
|
|
7059
|
-
(0,
|
|
7406
|
+
(0, import_node_fs29.mkdirSync)((0, import_node_path24.dirname)(abs), { recursive: true });
|
|
7060
7407
|
const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
|
|
7061
|
-
(0,
|
|
7408
|
+
(0, import_node_fs29.writeFileSync)(abs, body, "utf8");
|
|
7062
7409
|
return PLAN_FILE_REL;
|
|
7063
7410
|
}
|
|
7064
|
-
var
|
|
7411
|
+
var import_node_fs29, import_node_path24;
|
|
7065
7412
|
var init_plan_file = __esm({
|
|
7066
7413
|
"src/plan/plan-file.ts"() {
|
|
7067
7414
|
"use strict";
|
|
7068
|
-
|
|
7415
|
+
import_node_fs29 = require("fs");
|
|
7069
7416
|
import_node_path24 = require("path");
|
|
7070
7417
|
init_workspace_scratch();
|
|
7071
7418
|
init_plan_present();
|
|
@@ -7082,9 +7429,9 @@ function recoverFinishedCursorRun(opts) {
|
|
|
7082
7429
|
const agentId = opts.agentId.trim();
|
|
7083
7430
|
if (!agentId) return null;
|
|
7084
7431
|
const runsPath = (0, import_node_path25.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
|
|
7085
|
-
if (!(0,
|
|
7432
|
+
if (!(0, import_node_fs30.existsSync)(runsPath)) return null;
|
|
7086
7433
|
try {
|
|
7087
|
-
const lines = (0,
|
|
7434
|
+
const lines = (0, import_node_fs30.readFileSync)(runsPath, "utf8").split("\n");
|
|
7088
7435
|
let best = null;
|
|
7089
7436
|
for (const line of lines) {
|
|
7090
7437
|
const trimmed = line.trim();
|
|
@@ -7110,11 +7457,11 @@ function recoverFinishedCursorRun(opts) {
|
|
|
7110
7457
|
return null;
|
|
7111
7458
|
}
|
|
7112
7459
|
}
|
|
7113
|
-
var
|
|
7460
|
+
var import_node_fs30, import_node_path25;
|
|
7114
7461
|
var init_cursor_recover = __esm({
|
|
7115
7462
|
"src/agents/cursor-recover.ts"() {
|
|
7116
7463
|
"use strict";
|
|
7117
|
-
|
|
7464
|
+
import_node_fs30 = require("fs");
|
|
7118
7465
|
import_node_path25 = require("path");
|
|
7119
7466
|
init_paths();
|
|
7120
7467
|
}
|
|
@@ -7188,6 +7535,7 @@ __export(index_exports, {
|
|
|
7188
7535
|
REVIEW_REQUEST_PREFILL: () => REVIEW_REQUEST_PREFILL,
|
|
7189
7536
|
SIDEBOARD_FORCE_STOP: () => SIDEBOARD_FORCE_STOP,
|
|
7190
7537
|
SIDEBOARD_MCP_ALLOWED_TOOLS: () => SIDEBOARD_MCP_ALLOWED_TOOLS,
|
|
7538
|
+
SIDEBOARD_MCP_PROFILE_ENV: () => SIDEBOARD_MCP_PROFILE_ENV,
|
|
7191
7539
|
THINKING_EFFORTS: () => THINKING_EFFORTS,
|
|
7192
7540
|
addPrStackLayer: () => addPrStackLayer,
|
|
7193
7541
|
addStackLayerFromThread: () => addStackLayerFromThread,
|
|
@@ -7219,6 +7567,7 @@ __export(index_exports, {
|
|
|
7219
7567
|
brightsyCloudConnectAgent: () => brightsyCloudConnectAgent,
|
|
7220
7568
|
brightsyCloudConnectEnabled: () => brightsyCloudConnectEnabled,
|
|
7221
7569
|
brightsyConfigPath: () => brightsyConfigPath,
|
|
7570
|
+
brightsyInjectWorktreeMcpEnabled: () => brightsyInjectWorktreeMcpEnabled,
|
|
7222
7571
|
brightsyMcpAllowedTools: () => brightsyMcpAllowedTools,
|
|
7223
7572
|
brightsyMcpServerName: () => brightsyMcpServerName,
|
|
7224
7573
|
buildCachedUserContent: () => buildCachedUserContent,
|
|
@@ -7270,7 +7619,9 @@ __export(index_exports, {
|
|
|
7270
7619
|
detectLocalMergeConflicts: () => detectLocalMergeConflicts,
|
|
7271
7620
|
disconnectBrightsyTeam: () => disconnectBrightsyTeam,
|
|
7272
7621
|
discoverSkills: () => discoverSkills,
|
|
7622
|
+
dropCachedPrefixOnResume: () => dropCachedPrefixOnResume,
|
|
7273
7623
|
encodeBrightsyTarget: () => encodeBrightsyTarget,
|
|
7624
|
+
enrichPathWithNpmGlobalBin: () => enrichPathWithNpmGlobalBin,
|
|
7274
7625
|
enrichWorkspacesWithGithub: () => enrichWorkspacesWithGithub,
|
|
7275
7626
|
ensureAgentPath: () => ensureAgentPath,
|
|
7276
7627
|
ensureCloudCoordinator: () => ensureCloudCoordinator,
|
|
@@ -7308,6 +7659,7 @@ __export(index_exports, {
|
|
|
7308
7659
|
formatTranscriptMarkdown: () => formatTranscriptMarkdown,
|
|
7309
7660
|
formatWorkspaceInventory: () => formatWorkspaceInventory,
|
|
7310
7661
|
formatWorktreeDirective: () => formatWorktreeDirective,
|
|
7662
|
+
formatWorktreeReminder: () => formatWorktreeReminder,
|
|
7311
7663
|
getAdapter: () => getAdapter,
|
|
7312
7664
|
getAgentSetupInfo: () => getAgentSetupInfo,
|
|
7313
7665
|
getBrightsySession: () => getBrightsySession,
|
|
@@ -7434,7 +7786,10 @@ __export(index_exports, {
|
|
|
7434
7786
|
pastedTextStats: () => pastedTextStats,
|
|
7435
7787
|
permissionMode: () => permissionMode,
|
|
7436
7788
|
planFileAbs: () => planFileAbs,
|
|
7789
|
+
posixShellSingleQuote: () => posixShellSingleQuote,
|
|
7790
|
+
prepareTerminalCommand: () => prepareTerminalCommand,
|
|
7437
7791
|
previewLand: () => previewLand,
|
|
7792
|
+
promptMentionsBrightsy: () => promptMentionsBrightsy,
|
|
7438
7793
|
pushBranch: () => pushBranch,
|
|
7439
7794
|
readExistingReviewRequestFile: () => readExistingReviewRequestFile,
|
|
7440
7795
|
readPlanFile: () => readPlanFile,
|
|
@@ -7450,7 +7805,9 @@ __export(index_exports, {
|
|
|
7450
7805
|
requestReview: () => requestReview,
|
|
7451
7806
|
requireAgent: () => requireAgent,
|
|
7452
7807
|
resetGhStackDetectCache: () => resetGhStackDetectCache,
|
|
7808
|
+
resolveAgentExecutable: () => resolveAgentExecutable,
|
|
7453
7809
|
resolveClaudeExecutable: () => resolveClaudeExecutable,
|
|
7810
|
+
resolveCommandBinarySync: () => resolveCommandBinarySync,
|
|
7454
7811
|
resolveConductorCursorAgentId: () => resolveConductorCursorAgentId,
|
|
7455
7812
|
resolveCursorModelId: () => resolveCursorModelId,
|
|
7456
7813
|
resolveDefaultBranch: () => resolveDefaultBranch,
|
|
@@ -7459,6 +7816,7 @@ __export(index_exports, {
|
|
|
7459
7816
|
resolveFilesToCopy: () => resolveFilesToCopy,
|
|
7460
7817
|
resolveGhAuthToken: () => resolveGhAuthToken,
|
|
7461
7818
|
resolveGithubRepoSlug: () => resolveGithubRepoSlug,
|
|
7819
|
+
resolveLoginCommand: () => resolveLoginCommand,
|
|
7462
7820
|
resolveNewThreadOptions: () => resolveNewThreadOptions,
|
|
7463
7821
|
resolvePlanMarkdown: () => resolvePlanMarkdown,
|
|
7464
7822
|
resolvePrSelector: () => resolvePrSelector,
|
|
@@ -7480,9 +7838,11 @@ __export(index_exports, {
|
|
|
7480
7838
|
settingsSourceLabel: () => settingsSourceLabel,
|
|
7481
7839
|
shouldAttachPastedText: () => shouldAttachPastedText,
|
|
7482
7840
|
shouldCompactContext: () => shouldCompactContext,
|
|
7841
|
+
shouldInjectBrightsyMcp: () => shouldInjectBrightsyMcp,
|
|
7483
7842
|
shouldRefreshReviewRequestTemplate: () => shouldRefreshReviewRequestTemplate,
|
|
7484
7843
|
shouldRunWorktreeCleanup: () => shouldRunWorktreeCleanup,
|
|
7485
7844
|
sideboardHomeDir: () => sideboardHomeDir,
|
|
7845
|
+
sideboardMcpProfile: () => sideboardMcpProfile,
|
|
7486
7846
|
sideboardReposDir: () => sideboardReposDir,
|
|
7487
7847
|
sideboardWorkspacesDir: () => sideboardWorkspacesDir,
|
|
7488
7848
|
slugify: () => slugify,
|
|
@@ -7510,6 +7870,7 @@ __export(index_exports, {
|
|
|
7510
7870
|
threadDisplayLabel: () => threadDisplayLabel,
|
|
7511
7871
|
threadFilePath: () => threadFilePath,
|
|
7512
7872
|
threadLockPath: () => threadLockPath,
|
|
7873
|
+
threadRequestsBrightsyMcp: () => threadRequestsBrightsyMcp,
|
|
7513
7874
|
threadsDir: () => threadsDir,
|
|
7514
7875
|
threadsSharingWorktree: () => threadsSharingWorktree,
|
|
7515
7876
|
toolDescription: () => toolDescription,
|
|
@@ -7517,14 +7878,18 @@ __export(index_exports, {
|
|
|
7517
7878
|
toolFilePath: () => toolFilePath,
|
|
7518
7879
|
totalTokens: () => totalTokens,
|
|
7519
7880
|
updateAdvancedSettings: () => updateAdvancedSettings,
|
|
7881
|
+
updateAgentExecutable: () => updateAgentExecutable,
|
|
7520
7882
|
updateAppEnvironment: () => updateAppEnvironment,
|
|
7521
7883
|
updateBrightsySettings: () => updateBrightsySettings,
|
|
7522
7884
|
updateClaudeSettings: () => updateClaudeSettings,
|
|
7885
|
+
updateCodexSettings: () => updateCodexSettings,
|
|
7523
7886
|
updateDefaultsSettings: () => updateDefaultsSettings,
|
|
7524
7887
|
updateIntegrationsSettings: () => updateIntegrationsSettings,
|
|
7888
|
+
updateOpencodeSettings: () => updateOpencodeSettings,
|
|
7525
7889
|
updateThread: () => updateThread,
|
|
7526
7890
|
validateLinearApiKey: () => validateLinearApiKey,
|
|
7527
7891
|
withAgentInstructions: () => withAgentInstructions,
|
|
7892
|
+
withExportedPath: () => withExportedPath,
|
|
7528
7893
|
withThreadLock: () => withThreadLock,
|
|
7529
7894
|
workspaceSettingsSourceLabel: () => workspaceSettingsSourceLabel,
|
|
7530
7895
|
worktreeCleanupSettings: () => worktreeCleanupSettings,
|
|
@@ -8101,7 +8466,7 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
8101
8466
|
init_claude_mcp();
|
|
8102
8467
|
|
|
8103
8468
|
// src/agents/instructions.ts
|
|
8104
|
-
var
|
|
8469
|
+
var import_node_fs17 = require("fs");
|
|
8105
8470
|
var import_node_path14 = require("path");
|
|
8106
8471
|
init_worktree_labels();
|
|
8107
8472
|
function normPath2(p) {
|
|
@@ -8201,6 +8566,9 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
8201
8566
|
);
|
|
8202
8567
|
return lines.join("\n");
|
|
8203
8568
|
}
|
|
8569
|
+
function formatWorktreeReminder() {
|
|
8570
|
+
return "Sideboard worktree: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout.";
|
|
8571
|
+
}
|
|
8204
8572
|
function formatArtifactDirective() {
|
|
8205
8573
|
return [
|
|
8206
8574
|
"Sideboard side column (desktop UI):",
|
|
@@ -8242,10 +8610,10 @@ function loadAgentInstructions(worktreePath, agent) {
|
|
|
8242
8610
|
for (const rel of candidates) {
|
|
8243
8611
|
if (seen.has(rel)) continue;
|
|
8244
8612
|
const abs = (0, import_node_path14.join)(worktreePath, rel);
|
|
8245
|
-
if (!(0,
|
|
8613
|
+
if (!(0, import_node_fs17.existsSync)(abs)) continue;
|
|
8246
8614
|
try {
|
|
8247
|
-
if (!(0,
|
|
8248
|
-
let content = (0,
|
|
8615
|
+
if (!(0, import_node_fs17.statSync)(abs).isFile()) continue;
|
|
8616
|
+
let content = (0, import_node_fs17.readFileSync)(abs, "utf8");
|
|
8249
8617
|
if (!content.trim()) continue;
|
|
8250
8618
|
if (content.length > MAX_CHARS_PER_FILE) {
|
|
8251
8619
|
content = `${content.slice(0, MAX_CHARS_PER_FILE)}
|
|
@@ -8290,11 +8658,13 @@ init_turn_input();
|
|
|
8290
8658
|
init_agents();
|
|
8291
8659
|
async function detectAgents() {
|
|
8292
8660
|
ensureAgentPath();
|
|
8661
|
+
enrichPathWithNpmGlobalBin();
|
|
8293
8662
|
return Promise.all(allAdapters().map((a) => a.detect()));
|
|
8294
8663
|
}
|
|
8295
8664
|
var REQUIRE_AGENT_TIMEOUT_MS = 8e3;
|
|
8296
8665
|
async function requireAgent(agent, opts) {
|
|
8297
8666
|
ensureAgentPath();
|
|
8667
|
+
enrichPathWithNpmGlobalBin();
|
|
8298
8668
|
const status = await Promise.race([
|
|
8299
8669
|
getAdapter(agent).detect(),
|
|
8300
8670
|
new Promise((_, reject) => {
|
|
@@ -8322,7 +8692,7 @@ async function requireAgent(agent, opts) {
|
|
|
8322
8692
|
init_settings();
|
|
8323
8693
|
|
|
8324
8694
|
// src/hook/conductor.ts
|
|
8325
|
-
var
|
|
8695
|
+
var import_node_fs18 = require("fs");
|
|
8326
8696
|
var import_node_net = require("net");
|
|
8327
8697
|
var import_node_path15 = require("path");
|
|
8328
8698
|
var import_execa3 = require("execa");
|
|
@@ -8335,8 +8705,8 @@ function matchSimpleGlob(pattern, name) {
|
|
|
8335
8705
|
}
|
|
8336
8706
|
function readWorktreeInclude(repoPath) {
|
|
8337
8707
|
const path = (0, import_node_path15.join)(repoPath, ".worktreeinclude");
|
|
8338
|
-
if (!(0,
|
|
8339
|
-
return (0,
|
|
8708
|
+
if (!(0, import_node_fs18.existsSync)(path)) return [];
|
|
8709
|
+
return (0, import_node_fs18.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
8340
8710
|
}
|
|
8341
8711
|
function resolveFilesToCopy(repoPath) {
|
|
8342
8712
|
const fromInclude = readWorktreeInclude(repoPath);
|
|
@@ -8346,7 +8716,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
8346
8716
|
if (settings?.fileIncludeGlobs?.length) {
|
|
8347
8717
|
const matched = [];
|
|
8348
8718
|
try {
|
|
8349
|
-
for (const entry of (0,
|
|
8719
|
+
for (const entry of (0, import_node_fs18.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
8350
8720
|
if (!entry.isFile()) continue;
|
|
8351
8721
|
for (const glob of settings.fileIncludeGlobs) {
|
|
8352
8722
|
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path15.basename)(glob), entry.name)) {
|
|
@@ -8361,7 +8731,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
8361
8731
|
}
|
|
8362
8732
|
const defaults = [];
|
|
8363
8733
|
try {
|
|
8364
|
-
for (const entry of (0,
|
|
8734
|
+
for (const entry of (0, import_node_fs18.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
8365
8735
|
if (entry.isFile() && entry.name.startsWith(".env")) {
|
|
8366
8736
|
defaults.push(entry.name);
|
|
8367
8737
|
}
|
|
@@ -8376,10 +8746,10 @@ function copyConfiguredFiles(repoPath, worktreePath) {
|
|
|
8376
8746
|
const copied = [];
|
|
8377
8747
|
for (const rel of patterns) {
|
|
8378
8748
|
const src = (0, import_node_path15.join)(repoPath, rel);
|
|
8379
|
-
if (!(0,
|
|
8749
|
+
if (!(0, import_node_fs18.existsSync)(src)) continue;
|
|
8380
8750
|
const dest = (0, import_node_path15.join)(worktreePath, rel);
|
|
8381
|
-
(0,
|
|
8382
|
-
(0,
|
|
8751
|
+
(0, import_node_fs18.mkdirSync)((0, import_node_path15.dirname)(dest), { recursive: true });
|
|
8752
|
+
(0, import_node_fs18.copyFileSync)(src, dest);
|
|
8383
8753
|
copied.push(rel);
|
|
8384
8754
|
}
|
|
8385
8755
|
return copied;
|
|
@@ -8632,15 +9002,15 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
|
8632
9002
|
}
|
|
8633
9003
|
|
|
8634
9004
|
// src/hook/cursor-worktrees.ts
|
|
8635
|
-
var
|
|
9005
|
+
var import_node_fs19 = require("fs");
|
|
8636
9006
|
var import_node_path16 = require("path");
|
|
8637
9007
|
var import_execa4 = require("execa");
|
|
8638
9008
|
var import_node_readline3 = require("readline");
|
|
8639
9009
|
function loadCursorWorktreesJson(rootPath) {
|
|
8640
9010
|
const path = (0, import_node_path16.join)(rootPath, ".cursor", "worktrees.json");
|
|
8641
|
-
if (!(0,
|
|
9011
|
+
if (!(0, import_node_fs19.existsSync)(path)) return null;
|
|
8642
9012
|
try {
|
|
8643
|
-
return JSON.parse((0,
|
|
9013
|
+
return JSON.parse((0, import_node_fs19.readFileSync)(path, "utf8"));
|
|
8644
9014
|
} catch {
|
|
8645
9015
|
return null;
|
|
8646
9016
|
}
|
|
@@ -8705,12 +9075,12 @@ function hasCursorWorktreeSetup(worktreePath, repoPath) {
|
|
|
8705
9075
|
}
|
|
8706
9076
|
|
|
8707
9077
|
// src/diff/diff.ts
|
|
8708
|
-
var
|
|
9078
|
+
var import_node_fs20 = require("fs");
|
|
8709
9079
|
var import_node_path17 = require("path");
|
|
8710
9080
|
init_run();
|
|
8711
9081
|
init_worktree();
|
|
8712
9082
|
async function inspectGitWorktree(worktreePath) {
|
|
8713
|
-
if (!worktreePath || !(0,
|
|
9083
|
+
if (!worktreePath || !(0, import_node_fs20.existsSync)(worktreePath)) return "missing_worktree";
|
|
8714
9084
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
8715
9085
|
reject: false
|
|
8716
9086
|
});
|
|
@@ -8718,7 +9088,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
8718
9088
|
return "ok";
|
|
8719
9089
|
}
|
|
8720
9090
|
async function initializeGitRepository(worktreePath) {
|
|
8721
|
-
if (!worktreePath || !(0,
|
|
9091
|
+
if (!worktreePath || !(0, import_node_fs20.existsSync)(worktreePath)) {
|
|
8722
9092
|
throw new Error("Worktree not found");
|
|
8723
9093
|
}
|
|
8724
9094
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -9156,7 +9526,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
9156
9526
|
assertSafeRelativePath(relativePath);
|
|
9157
9527
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
9158
9528
|
const abs = (0, import_node_path17.join)(worktreePath, relativePath);
|
|
9159
|
-
const st = (0,
|
|
9529
|
+
const st = (0, import_node_fs20.statSync)(abs);
|
|
9160
9530
|
if (!st.isFile()) {
|
|
9161
9531
|
throw new Error(`Not a file: ${relativePath}`);
|
|
9162
9532
|
}
|
|
@@ -9165,7 +9535,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
9165
9535
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
9166
9536
|
);
|
|
9167
9537
|
}
|
|
9168
|
-
const buf = (0,
|
|
9538
|
+
const buf = (0, import_node_fs20.readFileSync)(abs);
|
|
9169
9539
|
return {
|
|
9170
9540
|
path: relativePath,
|
|
9171
9541
|
contentBase64: buf.toString("base64"),
|
|
@@ -9176,11 +9546,11 @@ function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
|
9176
9546
|
assertSafeRelativePath(relativePath);
|
|
9177
9547
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
9178
9548
|
const abs = (0, import_node_path17.join)(worktreePath, relativePath);
|
|
9179
|
-
const st = (0,
|
|
9549
|
+
const st = (0, import_node_fs20.statSync)(abs);
|
|
9180
9550
|
if (!st.isFile()) {
|
|
9181
9551
|
throw new Error(`Not a file: ${relativePath}`);
|
|
9182
9552
|
}
|
|
9183
|
-
const buf = (0,
|
|
9553
|
+
const buf = (0, import_node_fs20.readFileSync)(abs);
|
|
9184
9554
|
if (isImageRelativePath(relativePath)) {
|
|
9185
9555
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
9186
9556
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -9224,8 +9594,8 @@ function assertSafeRelativePath(relativePath) {
|
|
|
9224
9594
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
9225
9595
|
assertSafeRelativePath(relativePath);
|
|
9226
9596
|
const abs = (0, import_node_path17.join)(worktreePath, relativePath);
|
|
9227
|
-
(0,
|
|
9228
|
-
(0,
|
|
9597
|
+
(0, import_node_fs20.mkdirSync)((0, import_node_path17.dirname)(abs), { recursive: true });
|
|
9598
|
+
(0, import_node_fs20.writeFileSync)(abs, content, "utf8");
|
|
9229
9599
|
return { path: relativePath };
|
|
9230
9600
|
}
|
|
9231
9601
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
@@ -9244,7 +9614,7 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
|
9244
9614
|
}
|
|
9245
9615
|
|
|
9246
9616
|
// src/skills/discover.ts
|
|
9247
|
-
var
|
|
9617
|
+
var import_node_fs21 = require("fs");
|
|
9248
9618
|
var import_node_os8 = require("os");
|
|
9249
9619
|
var import_node_path18 = require("path");
|
|
9250
9620
|
function toCommand(name) {
|
|
@@ -9278,7 +9648,7 @@ function parseFrontmatter(content) {
|
|
|
9278
9648
|
}
|
|
9279
9649
|
function readSkill(skillMd, source) {
|
|
9280
9650
|
try {
|
|
9281
|
-
const content = (0,
|
|
9651
|
+
const content = (0, import_node_fs21.readFileSync)(skillMd, "utf8");
|
|
9282
9652
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
9283
9653
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
9284
9654
|
const name = fmName || dirName;
|
|
@@ -9297,19 +9667,19 @@ function readSkill(skillMd, source) {
|
|
|
9297
9667
|
}
|
|
9298
9668
|
}
|
|
9299
9669
|
function scanSkillsDir(dir, source, out) {
|
|
9300
|
-
if (!(0,
|
|
9670
|
+
if (!(0, import_node_fs21.existsSync)(dir)) return;
|
|
9301
9671
|
let entries;
|
|
9302
9672
|
try {
|
|
9303
|
-
entries = (0,
|
|
9673
|
+
entries = (0, import_node_fs21.readdirSync)(dir);
|
|
9304
9674
|
} catch {
|
|
9305
9675
|
return;
|
|
9306
9676
|
}
|
|
9307
9677
|
for (const entry of entries) {
|
|
9308
9678
|
if (entry.startsWith(".")) continue;
|
|
9309
9679
|
const skillMd = (0, import_node_path18.join)(dir, entry, "SKILL.md");
|
|
9310
|
-
if (!(0,
|
|
9680
|
+
if (!(0, import_node_fs21.existsSync)(skillMd)) continue;
|
|
9311
9681
|
try {
|
|
9312
|
-
if (!(0,
|
|
9682
|
+
if (!(0, import_node_fs21.statSync)(skillMd).isFile()) continue;
|
|
9313
9683
|
} catch {
|
|
9314
9684
|
continue;
|
|
9315
9685
|
}
|
|
@@ -9318,12 +9688,12 @@ function scanSkillsDir(dir, source, out) {
|
|
|
9318
9688
|
}
|
|
9319
9689
|
}
|
|
9320
9690
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
9321
|
-
if (!(0,
|
|
9691
|
+
if (!(0, import_node_fs21.existsSync)(pluginsRoot)) return;
|
|
9322
9692
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
9323
9693
|
if (depth > 7) return;
|
|
9324
9694
|
let entries;
|
|
9325
9695
|
try {
|
|
9326
|
-
entries = (0,
|
|
9696
|
+
entries = (0, import_node_fs21.readdirSync)(dir);
|
|
9327
9697
|
} catch {
|
|
9328
9698
|
return;
|
|
9329
9699
|
}
|
|
@@ -9335,7 +9705,7 @@ function scanClaudePluginSkills(pluginsRoot, out) {
|
|
|
9335
9705
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
9336
9706
|
const full = (0, import_node_path18.join)(dir, entry);
|
|
9337
9707
|
try {
|
|
9338
|
-
if (!(0,
|
|
9708
|
+
if (!(0, import_node_fs21.statSync)(full).isDirectory()) continue;
|
|
9339
9709
|
} catch {
|
|
9340
9710
|
continue;
|
|
9341
9711
|
}
|
|
@@ -9375,7 +9745,7 @@ function discoverSkills(worktreePath) {
|
|
|
9375
9745
|
return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
|
|
9376
9746
|
}
|
|
9377
9747
|
function readSkillBody(skillPath, maxChars = 12e3) {
|
|
9378
|
-
const raw = (0,
|
|
9748
|
+
const raw = (0, import_node_fs21.readFileSync)(skillPath, "utf8");
|
|
9379
9749
|
if (raw.startsWith("---")) {
|
|
9380
9750
|
const end = raw.indexOf("\n---", 3);
|
|
9381
9751
|
if (end >= 0) {
|
|
@@ -9516,7 +9886,7 @@ function buildDiffCommentAttachment(input) {
|
|
|
9516
9886
|
}
|
|
9517
9887
|
|
|
9518
9888
|
// src/composer/stage-files.ts
|
|
9519
|
-
var
|
|
9889
|
+
var import_node_fs22 = require("fs");
|
|
9520
9890
|
var import_node_path19 = require("path");
|
|
9521
9891
|
var import_node_crypto2 = require("crypto");
|
|
9522
9892
|
init_workspace_scratch();
|
|
@@ -9554,21 +9924,21 @@ function imageMimeType(filePath) {
|
|
|
9554
9924
|
}
|
|
9555
9925
|
function ensureAttachmentsDir(worktreePath) {
|
|
9556
9926
|
const dir = (0, import_node_path19.join)(worktreePath, ATTACHMENTS_DIR);
|
|
9557
|
-
(0,
|
|
9927
|
+
(0, import_node_fs22.mkdirSync)(dir, { recursive: true });
|
|
9558
9928
|
const gi = (0, import_node_path19.join)(dir, ".gitignore");
|
|
9559
|
-
if (!(0,
|
|
9560
|
-
(0,
|
|
9929
|
+
if (!(0, import_node_fs22.existsSync)(gi)) {
|
|
9930
|
+
(0, import_node_fs22.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
9561
9931
|
}
|
|
9562
9932
|
return dir;
|
|
9563
9933
|
}
|
|
9564
9934
|
function uniqueAttachmentName(dir, originalName) {
|
|
9565
9935
|
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
9566
|
-
if (!(0,
|
|
9936
|
+
if (!(0, import_node_fs22.existsSync)((0, import_node_path19.join)(dir, safe))) return safe;
|
|
9567
9937
|
const ext = (0, import_node_path19.extname)(safe);
|
|
9568
9938
|
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
9569
9939
|
for (let i = 1; i < 1e4; i++) {
|
|
9570
9940
|
const candidate = `${stem}-${i}${ext}`;
|
|
9571
|
-
if (!(0,
|
|
9941
|
+
if (!(0, import_node_fs22.existsSync)((0, import_node_path19.join)(dir, candidate))) return candidate;
|
|
9572
9942
|
}
|
|
9573
9943
|
return `${stem}-${(0, import_node_crypto2.randomUUID)()}${ext}`;
|
|
9574
9944
|
}
|
|
@@ -9622,7 +9992,7 @@ function attachmentFromBuffer(name, buf, opts) {
|
|
|
9622
9992
|
function attachmentFromAbsolutePath(absolutePath) {
|
|
9623
9993
|
const name = (0, import_node_path19.basename)(absolutePath);
|
|
9624
9994
|
try {
|
|
9625
|
-
const st = (0,
|
|
9995
|
+
const st = (0, import_node_fs22.statSync)(absolutePath);
|
|
9626
9996
|
if (!st.isFile()) {
|
|
9627
9997
|
return {
|
|
9628
9998
|
id: (0, import_node_crypto2.randomUUID)(),
|
|
@@ -9631,7 +10001,7 @@ function attachmentFromAbsolutePath(absolutePath) {
|
|
|
9631
10001
|
content: `(not a file: ${absolutePath})`
|
|
9632
10002
|
};
|
|
9633
10003
|
}
|
|
9634
|
-
const buf = (0,
|
|
10004
|
+
const buf = (0, import_node_fs22.readFileSync)(absolutePath);
|
|
9635
10005
|
return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
|
|
9636
10006
|
} catch (err) {
|
|
9637
10007
|
return {
|
|
@@ -9649,13 +10019,13 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
|
9649
10019
|
for (const abs of absolutePaths) {
|
|
9650
10020
|
const originalName = (0, import_node_path19.basename)(abs);
|
|
9651
10021
|
try {
|
|
9652
|
-
const st = (0,
|
|
10022
|
+
const st = (0, import_node_fs22.statSync)(abs);
|
|
9653
10023
|
if (!st.isFile()) continue;
|
|
9654
10024
|
const name = uniqueAttachmentName(dir, originalName);
|
|
9655
10025
|
const destAbs = (0, import_node_path19.join)(dir, name);
|
|
9656
|
-
(0,
|
|
10026
|
+
(0, import_node_fs22.copyFileSync)(abs, destAbs);
|
|
9657
10027
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
9658
|
-
const buf = (0,
|
|
10028
|
+
const buf = (0, import_node_fs22.readFileSync)(destAbs);
|
|
9659
10029
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
9660
10030
|
} catch (err) {
|
|
9661
10031
|
out.push({
|
|
@@ -9678,7 +10048,7 @@ function stageBuffersAsAttachments(worktreePath, buffers) {
|
|
|
9678
10048
|
const buf = Buffer.from(item.dataBase64, "base64");
|
|
9679
10049
|
const name = uniqueAttachmentName(dir, originalName);
|
|
9680
10050
|
const destAbs = (0, import_node_path19.join)(dir, name);
|
|
9681
|
-
(0,
|
|
10051
|
+
(0, import_node_fs22.writeFileSync)(destAbs, buf);
|
|
9682
10052
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
9683
10053
|
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
9684
10054
|
} catch (err) {
|
|
@@ -9723,9 +10093,9 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
|
9723
10093
|
const name = (0, import_node_path19.basename)(rel);
|
|
9724
10094
|
try {
|
|
9725
10095
|
const abs = (0, import_node_path19.join)(worktreePath, rel);
|
|
9726
|
-
const st = (0,
|
|
10096
|
+
const st = (0, import_node_fs22.statSync)(abs);
|
|
9727
10097
|
if (!st.isFile()) continue;
|
|
9728
|
-
const buf = (0,
|
|
10098
|
+
const buf = (0, import_node_fs22.readFileSync)(abs);
|
|
9729
10099
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
9730
10100
|
} catch (err) {
|
|
9731
10101
|
out.push({
|
|
@@ -10213,7 +10583,7 @@ async function confirmLand(thread, opts) {
|
|
|
10213
10583
|
}
|
|
10214
10584
|
|
|
10215
10585
|
// src/threads/create.ts
|
|
10216
|
-
var
|
|
10586
|
+
var import_node_fs23 = require("fs");
|
|
10217
10587
|
init_worktree();
|
|
10218
10588
|
init_app_settings();
|
|
10219
10589
|
init_thread_store();
|
|
@@ -10227,7 +10597,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
10227
10597
|
});
|
|
10228
10598
|
await requireAgent(resolved.agent);
|
|
10229
10599
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
10230
|
-
if (!(0,
|
|
10600
|
+
if (!(0, import_node_fs23.existsSync)(repoPath)) {
|
|
10231
10601
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
10232
10602
|
}
|
|
10233
10603
|
let sourceRef = input.sourceRef;
|
|
@@ -10454,7 +10824,7 @@ async function forkThreadWorktree(input, onSetupLine) {
|
|
|
10454
10824
|
}
|
|
10455
10825
|
|
|
10456
10826
|
// src/threads/stack-layers.ts
|
|
10457
|
-
var
|
|
10827
|
+
var import_node_fs24 = require("fs");
|
|
10458
10828
|
init_run();
|
|
10459
10829
|
init_stack();
|
|
10460
10830
|
init_worktree();
|
|
@@ -10522,7 +10892,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
10522
10892
|
let createdWorktree = false;
|
|
10523
10893
|
const trees = await listWorktrees(repoPath);
|
|
10524
10894
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
10525
|
-
if (checkedOut?.path && (0,
|
|
10895
|
+
if (checkedOut?.path && (0, import_node_fs24.existsSync)(checkedOut.path)) {
|
|
10526
10896
|
if (input.reuseExistingWorktree !== false) {
|
|
10527
10897
|
worktreePath = checkedOut.path;
|
|
10528
10898
|
} else {
|
|
@@ -10664,7 +11034,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
10664
11034
|
async function createPrStack(input, onSetupLine) {
|
|
10665
11035
|
await requireAgent(input.agent);
|
|
10666
11036
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
10667
|
-
if (!(0,
|
|
11037
|
+
if (!(0, import_node_fs24.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
10668
11038
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
10669
11039
|
const status = await detectGhStack(repoPath);
|
|
10670
11040
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -10731,7 +11101,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
10731
11101
|
}
|
|
10732
11102
|
}
|
|
10733
11103
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
10734
|
-
if (!claimed.has(bootstrap.worktreePath) && (0,
|
|
11104
|
+
if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs24.existsSync)(bootstrap.worktreePath)) {
|
|
10735
11105
|
try {
|
|
10736
11106
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
10737
11107
|
deleteBranch: bootstrap.branchName
|
|
@@ -10753,8 +11123,8 @@ function stackAgentDefaultsFrom(input) {
|
|
|
10753
11123
|
}
|
|
10754
11124
|
|
|
10755
11125
|
// src/threads/adopt.ts
|
|
10756
|
-
var
|
|
10757
|
-
var
|
|
11126
|
+
var import_node_child_process2 = require("child_process");
|
|
11127
|
+
var import_node_fs25 = require("fs");
|
|
10758
11128
|
var import_node_os9 = require("os");
|
|
10759
11129
|
var import_node_path20 = require("path");
|
|
10760
11130
|
var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
@@ -10779,21 +11149,21 @@ function mapAgentType(raw) {
|
|
|
10779
11149
|
return null;
|
|
10780
11150
|
}
|
|
10781
11151
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
10782
|
-
if (!workspacePath || !(0,
|
|
11152
|
+
if (!workspacePath || !(0, import_node_fs25.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
10783
11153
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
10784
11154
|
let best = null;
|
|
10785
11155
|
let hashes;
|
|
10786
11156
|
try {
|
|
10787
|
-
hashes = (0,
|
|
11157
|
+
hashes = (0, import_node_fs25.readdirSync)(CURSOR_SDK_STORE);
|
|
10788
11158
|
} catch {
|
|
10789
11159
|
return null;
|
|
10790
11160
|
}
|
|
10791
11161
|
for (const hash of hashes) {
|
|
10792
11162
|
const agentsFile = (0, import_node_path20.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
10793
|
-
if (!(0,
|
|
11163
|
+
if (!(0, import_node_fs25.existsSync)(agentsFile)) continue;
|
|
10794
11164
|
let text;
|
|
10795
11165
|
try {
|
|
10796
|
-
text = (0,
|
|
11166
|
+
text = (0, import_node_fs25.readFileSync)(agentsFile, "utf8");
|
|
10797
11167
|
} catch {
|
|
10798
11168
|
continue;
|
|
10799
11169
|
}
|
|
@@ -10817,7 +11187,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
10817
11187
|
return best?.agentId ?? null;
|
|
10818
11188
|
}
|
|
10819
11189
|
async function adoptThread(input) {
|
|
10820
|
-
if (!(0,
|
|
11190
|
+
if (!(0, import_node_fs25.existsSync)(input.worktreePath)) {
|
|
10821
11191
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
10822
11192
|
}
|
|
10823
11193
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -10844,18 +11214,18 @@ function conductorDbPath() {
|
|
|
10844
11214
|
return CONDUCTOR_DB;
|
|
10845
11215
|
}
|
|
10846
11216
|
function listConductorWorkspaces() {
|
|
10847
|
-
if (!(0,
|
|
11217
|
+
if (!(0, import_node_fs25.existsSync)(CONDUCTOR_DB)) {
|
|
10848
11218
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
10849
11219
|
}
|
|
10850
|
-
const tmp = (0,
|
|
11220
|
+
const tmp = (0, import_node_fs25.mkdtempSync)((0, import_node_path20.join)((0, import_node_os9.tmpdir)(), "sideboard-conductor-"));
|
|
10851
11221
|
const snapshot = (0, import_node_path20.join)(tmp, "conductor.db");
|
|
10852
11222
|
try {
|
|
10853
|
-
(0,
|
|
11223
|
+
(0, import_node_fs25.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
10854
11224
|
for (const suffix of ["-wal", "-shm"]) {
|
|
10855
11225
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
10856
|
-
if ((0,
|
|
11226
|
+
if ((0, import_node_fs25.existsSync)(src)) {
|
|
10857
11227
|
try {
|
|
10858
|
-
(0,
|
|
11228
|
+
(0, import_node_fs25.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
10859
11229
|
} catch {
|
|
10860
11230
|
}
|
|
10861
11231
|
}
|
|
@@ -10931,22 +11301,22 @@ function listConductorWorkspaces() {
|
|
|
10931
11301
|
db.close();
|
|
10932
11302
|
}
|
|
10933
11303
|
} finally {
|
|
10934
|
-
(0,
|
|
11304
|
+
(0, import_node_fs25.rmSync)(tmp, { recursive: true, force: true });
|
|
10935
11305
|
}
|
|
10936
11306
|
}
|
|
10937
11307
|
function importConductorWorkspace(workspaceId) {
|
|
10938
|
-
if (!(0,
|
|
11308
|
+
if (!(0, import_node_fs25.existsSync)(CONDUCTOR_DB)) {
|
|
10939
11309
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
10940
11310
|
}
|
|
10941
|
-
const tmp = (0,
|
|
11311
|
+
const tmp = (0, import_node_fs25.mkdtempSync)((0, import_node_path20.join)((0, import_node_os9.tmpdir)(), "sideboard-conductor-"));
|
|
10942
11312
|
const snapshot = (0, import_node_path20.join)(tmp, "conductor.db");
|
|
10943
11313
|
try {
|
|
10944
|
-
(0,
|
|
11314
|
+
(0, import_node_fs25.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
10945
11315
|
for (const suffix of ["-wal", "-shm"]) {
|
|
10946
11316
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
10947
|
-
if ((0,
|
|
11317
|
+
if ((0, import_node_fs25.existsSync)(src)) {
|
|
10948
11318
|
try {
|
|
10949
|
-
(0,
|
|
11319
|
+
(0, import_node_fs25.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
10950
11320
|
} catch {
|
|
10951
11321
|
}
|
|
10952
11322
|
}
|
|
@@ -10964,7 +11334,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
10964
11334
|
).get(workspaceId);
|
|
10965
11335
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
10966
11336
|
const worktreePath = String(row.workspacePath);
|
|
10967
|
-
if (!(0,
|
|
11337
|
+
if (!(0, import_node_fs25.existsSync)(worktreePath)) {
|
|
10968
11338
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
10969
11339
|
}
|
|
10970
11340
|
let sessionId = null;
|
|
@@ -11004,7 +11374,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
11004
11374
|
}
|
|
11005
11375
|
let repoPath = worktreePath;
|
|
11006
11376
|
try {
|
|
11007
|
-
repoPath = (0,
|
|
11377
|
+
repoPath = (0, import_node_child_process2.execFileSync)("git", ["rev-parse", "--show-toplevel"], {
|
|
11008
11378
|
cwd: worktreePath,
|
|
11009
11379
|
encoding: "utf8"
|
|
11010
11380
|
}).trim();
|
|
@@ -11027,7 +11397,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
11027
11397
|
db.close();
|
|
11028
11398
|
}
|
|
11029
11399
|
} finally {
|
|
11030
|
-
(0,
|
|
11400
|
+
(0, import_node_fs25.rmSync)(tmp, { recursive: true, force: true });
|
|
11031
11401
|
}
|
|
11032
11402
|
}
|
|
11033
11403
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
@@ -11036,7 +11406,7 @@ async function importConductorWorkspaceAsync(workspaceId) {
|
|
|
11036
11406
|
|
|
11037
11407
|
// src/orchestrator/orchestrator.ts
|
|
11038
11408
|
var import_node_events = require("events");
|
|
11039
|
-
var
|
|
11409
|
+
var import_node_fs31 = require("fs");
|
|
11040
11410
|
init_error_detail();
|
|
11041
11411
|
init_agents();
|
|
11042
11412
|
init_worktree();
|
|
@@ -11057,7 +11427,7 @@ function shouldAutoArchiveOnPrMerge(opts) {
|
|
|
11057
11427
|
}
|
|
11058
11428
|
|
|
11059
11429
|
// src/git/orphan-cleanup.ts
|
|
11060
|
-
var
|
|
11430
|
+
var import_node_fs26 = require("fs");
|
|
11061
11431
|
var import_node_path21 = require("path");
|
|
11062
11432
|
init_worktree();
|
|
11063
11433
|
init_thread_store();
|
|
@@ -11073,9 +11443,9 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11073
11443
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
11074
11444
|
);
|
|
11075
11445
|
const homeRoot = sideboardWorkspacesDir();
|
|
11076
|
-
if ((0,
|
|
11446
|
+
if ((0, import_node_fs26.existsSync)(homeRoot)) {
|
|
11077
11447
|
try {
|
|
11078
|
-
for (const entry of (0,
|
|
11448
|
+
for (const entry of (0, import_node_fs26.readdirSync)(homeRoot, { withFileTypes: true })) {
|
|
11079
11449
|
if (!entry.isDirectory()) continue;
|
|
11080
11450
|
void entry;
|
|
11081
11451
|
}
|
|
@@ -11085,7 +11455,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11085
11455
|
const orphans = [];
|
|
11086
11456
|
const seen = /* @__PURE__ */ new Set();
|
|
11087
11457
|
for (const repoPath of repos) {
|
|
11088
|
-
if (!repoPath || !(0,
|
|
11458
|
+
if (!repoPath || !(0, import_node_fs26.existsSync)(repoPath)) continue;
|
|
11089
11459
|
try {
|
|
11090
11460
|
const wts = await listWorktrees(repoPath);
|
|
11091
11461
|
for (const wt of wts) {
|
|
@@ -11096,7 +11466,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11096
11466
|
seen.add(path);
|
|
11097
11467
|
let mtimeMs = 0;
|
|
11098
11468
|
try {
|
|
11099
|
-
mtimeMs = (0,
|
|
11469
|
+
mtimeMs = (0, import_node_fs26.statSync)(path).mtimeMs;
|
|
11100
11470
|
} catch {
|
|
11101
11471
|
mtimeMs = 0;
|
|
11102
11472
|
}
|
|
@@ -11106,16 +11476,16 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11106
11476
|
}
|
|
11107
11477
|
try {
|
|
11108
11478
|
const root = worktreesRoot(repoPath);
|
|
11109
|
-
if ((0,
|
|
11110
|
-
for (const entry of (0,
|
|
11479
|
+
if ((0, import_node_fs26.existsSync)(root)) {
|
|
11480
|
+
for (const entry of (0, import_node_fs26.readdirSync)(root, { withFileTypes: true })) {
|
|
11111
11481
|
if (!entry.isDirectory()) continue;
|
|
11112
11482
|
const path = (0, import_node_path21.join)(root, entry.name).replace(/\/$/, "");
|
|
11113
11483
|
if (known.has(path) || seen.has(path)) continue;
|
|
11114
|
-
if (!(0,
|
|
11484
|
+
if (!(0, import_node_fs26.existsSync)((0, import_node_path21.join)(path, ".git"))) continue;
|
|
11115
11485
|
seen.add(path);
|
|
11116
11486
|
let mtimeMs = 0;
|
|
11117
11487
|
try {
|
|
11118
|
-
mtimeMs = (0,
|
|
11488
|
+
mtimeMs = (0, import_node_fs26.statSync)(path).mtimeMs;
|
|
11119
11489
|
} catch {
|
|
11120
11490
|
mtimeMs = Date.now();
|
|
11121
11491
|
}
|
|
@@ -11261,7 +11631,7 @@ async function applyThreadIntoMain(thread, opts) {
|
|
|
11261
11631
|
}
|
|
11262
11632
|
|
|
11263
11633
|
// src/git/clone-repo.ts
|
|
11264
|
-
var
|
|
11634
|
+
var import_node_fs27 = require("fs");
|
|
11265
11635
|
var import_node_path22 = require("path");
|
|
11266
11636
|
var import_execa6 = require("execa");
|
|
11267
11637
|
init_paths();
|
|
@@ -11277,7 +11647,7 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
11277
11647
|
}
|
|
11278
11648
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
11279
11649
|
const dest = (0, import_node_path22.join)(sideboardReposDir(), name);
|
|
11280
|
-
if ((0,
|
|
11650
|
+
if ((0, import_node_fs27.existsSync)(dest)) {
|
|
11281
11651
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
11282
11652
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
11283
11653
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -11299,7 +11669,7 @@ init_orchestrator_capable();
|
|
|
11299
11669
|
|
|
11300
11670
|
// src/review/request-review.ts
|
|
11301
11671
|
var import_node_crypto5 = require("crypto");
|
|
11302
|
-
var
|
|
11672
|
+
var import_node_fs28 = require("fs");
|
|
11303
11673
|
var import_node_path23 = require("path");
|
|
11304
11674
|
init_global_workspace();
|
|
11305
11675
|
init_thread_store();
|
|
@@ -11444,9 +11814,9 @@ function shouldRefreshReviewRequestTemplate(content) {
|
|
|
11444
11814
|
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
11445
11815
|
}
|
|
11446
11816
|
function readTextIfPresent(abs) {
|
|
11447
|
-
if (!(0,
|
|
11817
|
+
if (!(0, import_node_fs28.existsSync)(abs)) return null;
|
|
11448
11818
|
try {
|
|
11449
|
-
const content = (0,
|
|
11819
|
+
const content = (0, import_node_fs28.readFileSync)(abs, "utf8");
|
|
11450
11820
|
return content.trim() ? content : null;
|
|
11451
11821
|
} catch {
|
|
11452
11822
|
return null;
|
|
@@ -11454,9 +11824,9 @@ function readTextIfPresent(abs) {
|
|
|
11454
11824
|
}
|
|
11455
11825
|
function ensureAttachmentsGitignore(worktreePath) {
|
|
11456
11826
|
const gitignoreAbs = (0, import_node_path23.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
11457
|
-
if ((0,
|
|
11458
|
-
(0,
|
|
11459
|
-
(0,
|
|
11827
|
+
if ((0, import_node_fs28.existsSync)(gitignoreAbs)) return;
|
|
11828
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path23.dirname)(gitignoreAbs), { recursive: true });
|
|
11829
|
+
(0, import_node_fs28.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
11460
11830
|
}
|
|
11461
11831
|
function resolveReviewGuidelines(worktreePath) {
|
|
11462
11832
|
const repoAbs = (0, import_node_path23.join)(worktreePath, REPO_REVIEW_PATH);
|
|
@@ -11490,8 +11860,8 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
11490
11860
|
};
|
|
11491
11861
|
}
|
|
11492
11862
|
ensureAttachmentsGitignore(worktreePath);
|
|
11493
|
-
(0,
|
|
11494
|
-
(0,
|
|
11863
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path23.dirname)(localAbs), { recursive: true });
|
|
11864
|
+
(0, import_node_fs28.writeFileSync)(localAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
|
|
11495
11865
|
return {
|
|
11496
11866
|
path: REVIEW_REQUEST_PATH,
|
|
11497
11867
|
name: REVIEW_REQUEST_NAME,
|
|
@@ -11513,7 +11883,7 @@ function ensureReviewRequestFile(worktreePath) {
|
|
|
11513
11883
|
const localAbs = (0, import_node_path23.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
11514
11884
|
const localContent = readTextIfPresent(localAbs) ?? readTextIfPresent((0, import_node_path23.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
|
|
11515
11885
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
11516
|
-
const path = (0,
|
|
11886
|
+
const path = (0, import_node_fs28.existsSync)(localAbs) ? REVIEW_REQUEST_PATH : LEGACY_REVIEW_REQUEST_PATH;
|
|
11517
11887
|
return {
|
|
11518
11888
|
path,
|
|
11519
11889
|
name: REVIEW_REQUEST_NAME,
|
|
@@ -11521,8 +11891,8 @@ function ensureReviewRequestFile(worktreePath) {
|
|
|
11521
11891
|
source: "local"
|
|
11522
11892
|
};
|
|
11523
11893
|
}
|
|
11524
|
-
(0,
|
|
11525
|
-
(0,
|
|
11894
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path23.dirname)(repoAbs), { recursive: true });
|
|
11895
|
+
(0, import_node_fs28.writeFileSync)(repoAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
|
|
11526
11896
|
return {
|
|
11527
11897
|
path: REPO_REVIEW_PATH,
|
|
11528
11898
|
name: REPO_REVIEW_NAME,
|
|
@@ -11802,7 +12172,7 @@ var Orchestrator = class {
|
|
|
11802
12172
|
}
|
|
11803
12173
|
continue;
|
|
11804
12174
|
}
|
|
11805
|
-
if (!(0,
|
|
12175
|
+
if (!(0, import_node_fs31.existsSync)(thread.worktreePath)) {
|
|
11806
12176
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
11807
12177
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
11808
12178
|
continue;
|
|
@@ -12219,13 +12589,14 @@ var Orchestrator = class {
|
|
|
12219
12589
|
"Files column: MCP present_files (brightsy account storage or memory).",
|
|
12220
12590
|
"Do not say artifacts/CMS UI are unavailable."
|
|
12221
12591
|
].join(" ") : null;
|
|
12592
|
+
const worktreeReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatWorktreeReminder() : null;
|
|
12222
12593
|
const agentPrompt = [
|
|
12223
12594
|
thread.planMode ? PLAN_MODE_INSTRUCTION : null,
|
|
12224
12595
|
orchestrationReminder,
|
|
12596
|
+
worktreeReminder,
|
|
12225
12597
|
artifactReminder,
|
|
12226
12598
|
expandedPrompt
|
|
12227
12599
|
].filter(Boolean).join("\n\n");
|
|
12228
|
-
const instructionFiles = loadAgentInstructions(thread.worktreePath, thread.agent);
|
|
12229
12600
|
if (thread.attachments.length > 0) {
|
|
12230
12601
|
updateThread(threadId, { attachments: [] });
|
|
12231
12602
|
}
|
|
@@ -12253,7 +12624,6 @@ var Orchestrator = class {
|
|
|
12253
12624
|
const renameBranchDirective = !isBrightsy && !isOrchestration && autoRenameBranchEnabled2() ? formatRenameBranchDirective(fresh, {
|
|
12254
12625
|
customPrompt: settings?.prompts?.renameBranch
|
|
12255
12626
|
}) : null;
|
|
12256
|
-
const instructions = fresh.agent === "claude" || isBrightsy ? null : formatAgentInstructions(instructionFiles);
|
|
12257
12627
|
let seed = null;
|
|
12258
12628
|
if (!fresh.sessionId) {
|
|
12259
12629
|
const prior = fresh.messages.slice(0, -1);
|
|
@@ -12274,12 +12644,12 @@ var Orchestrator = class {
|
|
|
12274
12644
|
});
|
|
12275
12645
|
}
|
|
12276
12646
|
}
|
|
12277
|
-
const cachedPrefix = [
|
|
12647
|
+
const cachedPrefix = fresh.sessionId ? "" : [
|
|
12278
12648
|
coordinatorDirective,
|
|
12279
12649
|
worktreeDirective,
|
|
12280
12650
|
artifactDirective,
|
|
12281
12651
|
renameBranchDirective,
|
|
12282
|
-
|
|
12652
|
+
seed
|
|
12283
12653
|
].filter(Boolean).join("\n\n---\n\n");
|
|
12284
12654
|
try {
|
|
12285
12655
|
const stderrTail = [];
|
|
@@ -12366,15 +12736,11 @@ var Orchestrator = class {
|
|
|
12366
12736
|
const retryThread = this.requireThread(threadId);
|
|
12367
12737
|
const prior = retryThread.messages.slice(0, -1);
|
|
12368
12738
|
const retrySeed = buildSessionSeed(prior);
|
|
12369
|
-
const retryInstructions = retryThread.agent === "claude" ? null : formatAgentInstructions(
|
|
12370
|
-
loadAgentInstructions(retryThread.worktreePath, retryThread.agent)
|
|
12371
|
-
);
|
|
12372
12739
|
const retryPrefix = [
|
|
12373
12740
|
coordinatorDirective,
|
|
12374
12741
|
worktreeDirective,
|
|
12375
12742
|
artifactDirective,
|
|
12376
12743
|
renameBranchDirective,
|
|
12377
|
-
retryInstructions,
|
|
12378
12744
|
retrySeed
|
|
12379
12745
|
].filter(Boolean).join("\n\n---\n\n");
|
|
12380
12746
|
const retryHandle = await spawnAgentTurn(
|
|
@@ -13209,7 +13575,7 @@ var Orchestrator = class {
|
|
|
13209
13575
|
this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
|
|
13210
13576
|
return restored2;
|
|
13211
13577
|
}
|
|
13212
|
-
if (!(0,
|
|
13578
|
+
if (!(0, import_node_fs31.existsSync)(thread.worktreePath)) {
|
|
13213
13579
|
const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
|
|
13214
13580
|
const { execa: execa7 } = await import("execa");
|
|
13215
13581
|
const slug = thread.worktreePath.split("/").pop();
|
|
@@ -13465,6 +13831,7 @@ function mcpArchiveBlockedReason(thread) {
|
|
|
13465
13831
|
}
|
|
13466
13832
|
|
|
13467
13833
|
// src/mcp/server.ts
|
|
13834
|
+
init_profile();
|
|
13468
13835
|
var MAX_ORCH_THREADS = 5;
|
|
13469
13836
|
var CREATE_THREAD_TIMEOUT_MS = 9e4;
|
|
13470
13837
|
function withTimeout(promise, ms, label) {
|
|
@@ -13578,14 +13945,13 @@ async function startMcpServer() {
|
|
|
13578
13945
|
),
|
|
13579
13946
|
artifact_id: import_zod.z.string().optional().describe("Stable id when updating the same artifact across turns")
|
|
13580
13947
|
},
|
|
13581
|
-
async ({ title, type,
|
|
13948
|
+
async ({ title, type, artifact_id }) => {
|
|
13582
13949
|
const id = artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
13583
13950
|
const payload = {
|
|
13584
13951
|
ok: true,
|
|
13585
13952
|
artifact_id: id,
|
|
13586
13953
|
title,
|
|
13587
13954
|
type,
|
|
13588
|
-
content,
|
|
13589
13955
|
message: "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
|
|
13590
13956
|
};
|
|
13591
13957
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
@@ -13638,7 +14004,6 @@ async function startMcpServer() {
|
|
|
13638
14004
|
ok: true,
|
|
13639
14005
|
path,
|
|
13640
14006
|
title: title?.trim() || "Plan",
|
|
13641
|
-
content,
|
|
13642
14007
|
message: "Plan saved to .context/attachments/plan.md and shown in Sideboard chat for approval."
|
|
13643
14008
|
};
|
|
13644
14009
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
@@ -13668,9 +14033,6 @@ async function startMcpServer() {
|
|
|
13668
14033
|
datasource: args.datasource ?? (args.resource ? "inline" : "brightsy"),
|
|
13669
14034
|
resource_id: args.resource_id,
|
|
13670
14035
|
record_id: args.record_id,
|
|
13671
|
-
resource: args.resource,
|
|
13672
|
-
record: args.record,
|
|
13673
|
-
records: args.records,
|
|
13674
14036
|
message: "Schema pane accepted. Sideboard desktop opens the CMS column beside chat."
|
|
13675
14037
|
};
|
|
13676
14038
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
@@ -13698,744 +14060,747 @@ async function startMcpServer() {
|
|
|
13698
14060
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
13699
14061
|
}
|
|
13700
14062
|
);
|
|
13701
|
-
|
|
13702
|
-
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
13710
|
-
|
|
13711
|
-
|
|
13712
|
-
|
|
13713
|
-
|
|
13714
|
-
|
|
13715
|
-
|
|
13716
|
-
|
|
13717
|
-
|
|
13718
|
-
|
|
13719
|
-
|
|
13720
|
-
|
|
13721
|
-
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
13726
|
-
|
|
13727
|
-
|
|
13728
|
-
if (
|
|
13729
|
-
|
|
13730
|
-
|
|
13731
|
-
|
|
14063
|
+
if (sideboardMcpProfile() !== "worktree") {
|
|
14064
|
+
const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
14065
|
+
const accountDefaults = resolveThreadDefaults2();
|
|
14066
|
+
const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
|
|
14067
|
+
server.tool(
|
|
14068
|
+
"create_thread",
|
|
14069
|
+
`Create a new worktree thread (chat) from branch, pr, or ticket. Pass repoPath from list_workspaces. From an orchestration chat, omit parentThreadId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Prefer omitting agent/model so Sideboard applies ${accountDefaultsHint}. Then use send_to_thread to chat.`,
|
|
14070
|
+
{
|
|
14071
|
+
sourceType: import_zod.z.enum(["branch", "pr", "ticket"]),
|
|
14072
|
+
sourceRef: import_zod.z.string(),
|
|
14073
|
+
agent: import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]).optional().describe(`Omit to use Account default agent (${accountDefaults.agent})`),
|
|
14074
|
+
model: import_zod.z.string().nullable().optional().describe(
|
|
14075
|
+
`Usually omit to use Account default model (${accountDefaults.model?.trim() || "Auto"}). Pass null only to force Auto / agent-default.`
|
|
14076
|
+
),
|
|
14077
|
+
repoPath: import_zod.z.string(),
|
|
14078
|
+
title: import_zod.z.string().optional(),
|
|
14079
|
+
parentThreadId: import_zod.z.string().optional().describe(
|
|
14080
|
+
"Orchestration: omit (preferred) or pass YOUR chat id from the turn reminder / AGENTS.md. Do not invent uuids."
|
|
14081
|
+
)
|
|
14082
|
+
},
|
|
14083
|
+
async (args) => {
|
|
14084
|
+
const envParentId = process.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID?.trim() || "";
|
|
14085
|
+
let parentId = args.parentThreadId?.trim() || "";
|
|
14086
|
+
let parent = parentId ? orch.getThread(parentId) : null;
|
|
14087
|
+
let parentCorrectedFrom;
|
|
14088
|
+
if (envParentId) {
|
|
14089
|
+
const envParent = orch.getThread(envParentId);
|
|
14090
|
+
if (envParent) {
|
|
14091
|
+
if (parentId && parentId !== envParentId) parentCorrectedFrom = parentId;
|
|
14092
|
+
else if (!parentId) parentCorrectedFrom = void 0;
|
|
14093
|
+
parentId = envParentId;
|
|
14094
|
+
parent = envParent;
|
|
14095
|
+
}
|
|
13732
14096
|
}
|
|
13733
|
-
|
|
13734
|
-
|
|
13735
|
-
|
|
13736
|
-
|
|
13737
|
-
|
|
13738
|
-
|
|
13739
|
-
|
|
13740
|
-
|
|
13741
|
-
|
|
14097
|
+
if (parentId && !parent) {
|
|
14098
|
+
parentCorrectedFrom = parentId;
|
|
14099
|
+
parentId = "";
|
|
14100
|
+
parent = null;
|
|
14101
|
+
}
|
|
14102
|
+
if (parentId) {
|
|
14103
|
+
const children = orch.getThreads(false).filter((t) => t.parentThreadId === parentId);
|
|
14104
|
+
if (children.length >= MAX_ORCH_THREADS) {
|
|
14105
|
+
return {
|
|
14106
|
+
content: [
|
|
14107
|
+
{
|
|
14108
|
+
type: "text",
|
|
14109
|
+
text: `Thread-creation cap (${MAX_ORCH_THREADS}) reached for this orchestration session`
|
|
14110
|
+
}
|
|
14111
|
+
],
|
|
14112
|
+
isError: true
|
|
14113
|
+
};
|
|
14114
|
+
}
|
|
14115
|
+
}
|
|
14116
|
+
let agentArg = args.agent;
|
|
14117
|
+
let agentCoercedFrom;
|
|
14118
|
+
const resolvedProbe = resolveNewThreadOptions2({ agent: agentArg }).agent;
|
|
14119
|
+
if (resolvedProbe === "codex") {
|
|
14120
|
+
agentCoercedFrom = agentArg ?? "codex";
|
|
14121
|
+
const accountAgent = resolveNewThreadOptions2({}).agent;
|
|
14122
|
+
agentArg = accountAgent !== "codex" ? accountAgent : "cursor";
|
|
14123
|
+
}
|
|
14124
|
+
const opts = resolveNewThreadOptions2({
|
|
14125
|
+
agent: agentArg,
|
|
14126
|
+
model: args.model
|
|
14127
|
+
});
|
|
14128
|
+
try {
|
|
14129
|
+
const thread = await withTimeout(
|
|
14130
|
+
orch.createThread({
|
|
14131
|
+
sourceType: args.sourceType,
|
|
14132
|
+
sourceRef: args.sourceRef,
|
|
14133
|
+
agent: opts.agent,
|
|
14134
|
+
model: opts.model,
|
|
14135
|
+
effort: opts.effort,
|
|
14136
|
+
fast: opts.fast,
|
|
14137
|
+
repoPath: args.repoPath,
|
|
14138
|
+
title: args.title,
|
|
14139
|
+
parentThreadId: parentId || null
|
|
14140
|
+
}),
|
|
14141
|
+
CREATE_THREAD_TIMEOUT_MS,
|
|
14142
|
+
"create_thread"
|
|
14143
|
+
);
|
|
14144
|
+
const parentNote = parentCorrectedFrom ? parentId ? `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; nested under ${parentId}` : `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; created without parent` : void 0;
|
|
14145
|
+
return {
|
|
14146
|
+
content: [
|
|
14147
|
+
{
|
|
14148
|
+
type: "text",
|
|
14149
|
+
text: JSON.stringify({
|
|
14150
|
+
id: thread.id,
|
|
14151
|
+
title: thread.title,
|
|
14152
|
+
branchName: thread.branchName,
|
|
14153
|
+
worktreePath: thread.worktreePath,
|
|
14154
|
+
agent: thread.agent,
|
|
14155
|
+
model: thread.model,
|
|
14156
|
+
status: thread.status,
|
|
14157
|
+
link: `sideboard://thread/${thread.id}`,
|
|
14158
|
+
parentThreadId: thread.parentThreadId,
|
|
14159
|
+
...agentCoercedFrom ? {
|
|
14160
|
+
agentCoercedFrom,
|
|
14161
|
+
note: `Avoid nested Codex under a Codex orchestrator \u2014 used Account default agent=${thread.agent}`
|
|
14162
|
+
} : {},
|
|
14163
|
+
...parentCorrectedFrom ? { parentCorrectedFrom, parentNote } : {}
|
|
14164
|
+
})
|
|
14165
|
+
}
|
|
14166
|
+
]
|
|
14167
|
+
};
|
|
14168
|
+
} catch (err) {
|
|
14169
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
13742
14170
|
return {
|
|
13743
14171
|
content: [
|
|
13744
14172
|
{
|
|
13745
14173
|
type: "text",
|
|
13746
|
-
text: `
|
|
14174
|
+
text: `create_thread failed: ${message}`
|
|
13747
14175
|
}
|
|
13748
14176
|
],
|
|
13749
14177
|
isError: true
|
|
13750
14178
|
};
|
|
13751
14179
|
}
|
|
13752
14180
|
}
|
|
13753
|
-
|
|
13754
|
-
|
|
13755
|
-
|
|
13756
|
-
|
|
13757
|
-
|
|
13758
|
-
|
|
13759
|
-
|
|
13760
|
-
|
|
13761
|
-
|
|
13762
|
-
|
|
13763
|
-
|
|
13764
|
-
|
|
13765
|
-
|
|
13766
|
-
|
|
13767
|
-
|
|
13768
|
-
|
|
13769
|
-
|
|
13770
|
-
agent: opts.agent,
|
|
13771
|
-
model: opts.model,
|
|
13772
|
-
effort: opts.effort,
|
|
13773
|
-
fast: opts.fast,
|
|
13774
|
-
repoPath: args.repoPath,
|
|
13775
|
-
title: args.title,
|
|
13776
|
-
parentThreadId: parentId || null
|
|
13777
|
-
}),
|
|
13778
|
-
CREATE_THREAD_TIMEOUT_MS,
|
|
13779
|
-
"create_thread"
|
|
13780
|
-
);
|
|
13781
|
-
const parentNote = parentCorrectedFrom ? parentId ? `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; nested under ${parentId}` : `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; created without parent` : void 0;
|
|
14181
|
+
);
|
|
14182
|
+
server.tool(
|
|
14183
|
+
"send_to_thread",
|
|
14184
|
+
"Queue a prompt on a worktree thread chat (runs under concurrency cap). Use after create_thread to start or continue a conversation. Set force_stop=true to interrupt an in-flight/queued turn (kill + clear queue) before queueing this prompt \u2014 use when the thread is mid-turn or has stale queued prompts you need to replace.",
|
|
14185
|
+
{
|
|
14186
|
+
ref: import_zod.z.string(),
|
|
14187
|
+
prompt: import_zod.z.string(),
|
|
14188
|
+
force_stop: import_zod.z.boolean().optional()
|
|
14189
|
+
},
|
|
14190
|
+
async ({ ref, prompt, force_stop }) => {
|
|
14191
|
+
if (force_stop) {
|
|
14192
|
+
const existing = orch.getThread(ref);
|
|
14193
|
+
if (existing) {
|
|
14194
|
+
orch.stop(ref, { clearQueue: true });
|
|
14195
|
+
}
|
|
14196
|
+
}
|
|
14197
|
+
const thread = await orch.send(ref, prompt);
|
|
13782
14198
|
return {
|
|
13783
14199
|
content: [
|
|
13784
14200
|
{
|
|
13785
14201
|
type: "text",
|
|
13786
14202
|
text: JSON.stringify({
|
|
13787
14203
|
id: thread.id,
|
|
13788
|
-
title: thread.title,
|
|
13789
|
-
branchName: thread.branchName,
|
|
13790
|
-
worktreePath: thread.worktreePath,
|
|
13791
|
-
agent: thread.agent,
|
|
13792
|
-
model: thread.model,
|
|
13793
14204
|
status: thread.status,
|
|
13794
|
-
|
|
13795
|
-
|
|
13796
|
-
...agentCoercedFrom ? {
|
|
13797
|
-
agentCoercedFrom,
|
|
13798
|
-
note: `Avoid nested Codex under a Codex orchestrator \u2014 used Account default agent=${thread.agent}`
|
|
13799
|
-
} : {},
|
|
13800
|
-
...parentCorrectedFrom ? { parentCorrectedFrom, parentNote } : {}
|
|
14205
|
+
queueLength: thread.queue.length,
|
|
14206
|
+
forceStopped: Boolean(force_stop)
|
|
13801
14207
|
})
|
|
13802
14208
|
}
|
|
13803
14209
|
]
|
|
13804
14210
|
};
|
|
13805
|
-
}
|
|
13806
|
-
|
|
14211
|
+
}
|
|
14212
|
+
);
|
|
14213
|
+
server.tool(
|
|
14214
|
+
"wait_for_turn",
|
|
14215
|
+
"Block until the thread finishes its current/queued turn (avoids polling). Use after send_to_thread to read the agent reply.",
|
|
14216
|
+
{
|
|
14217
|
+
ref: import_zod.z.string(),
|
|
14218
|
+
timeoutMs: import_zod.z.number().optional()
|
|
14219
|
+
},
|
|
14220
|
+
async ({ ref, timeoutMs }) => {
|
|
14221
|
+
const thread = await orch.waitForTurn(ref, timeoutMs ?? 6e5);
|
|
14222
|
+
const result = orch.getTurnResult(thread.id);
|
|
13807
14223
|
return {
|
|
13808
14224
|
content: [
|
|
13809
14225
|
{
|
|
13810
14226
|
type: "text",
|
|
13811
|
-
text:
|
|
14227
|
+
text: JSON.stringify({
|
|
14228
|
+
id: thread.id,
|
|
14229
|
+
status: result.status,
|
|
14230
|
+
text: result.text
|
|
14231
|
+
})
|
|
13812
14232
|
}
|
|
13813
|
-
]
|
|
13814
|
-
isError: true
|
|
14233
|
+
]
|
|
13815
14234
|
};
|
|
13816
14235
|
}
|
|
13817
|
-
|
|
13818
|
-
|
|
13819
|
-
|
|
13820
|
-
|
|
13821
|
-
|
|
13822
|
-
|
|
13823
|
-
|
|
13824
|
-
|
|
13825
|
-
force_stop: import_zod.z.boolean().optional()
|
|
13826
|
-
},
|
|
13827
|
-
async ({ ref, prompt, force_stop }) => {
|
|
13828
|
-
if (force_stop) {
|
|
13829
|
-
const existing = orch.getThread(ref);
|
|
13830
|
-
if (existing) {
|
|
13831
|
-
orch.stop(ref, { clearQueue: true });
|
|
13832
|
-
}
|
|
14236
|
+
);
|
|
14237
|
+
server.tool(
|
|
14238
|
+
"get_turn_result",
|
|
14239
|
+
"Final assistant message only (not full transcript)",
|
|
14240
|
+
{ ref: import_zod.z.string() },
|
|
14241
|
+
async ({ ref }) => {
|
|
14242
|
+
const result = orch.getTurnResult(ref);
|
|
14243
|
+
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
13833
14244
|
}
|
|
13834
|
-
|
|
13835
|
-
|
|
13836
|
-
|
|
13837
|
-
|
|
13838
|
-
|
|
13839
|
-
|
|
13840
|
-
|
|
13841
|
-
|
|
13842
|
-
|
|
13843
|
-
|
|
13844
|
-
|
|
13845
|
-
|
|
13846
|
-
|
|
13847
|
-
|
|
13848
|
-
|
|
13849
|
-
|
|
13850
|
-
|
|
13851
|
-
|
|
13852
|
-
|
|
13853
|
-
{
|
|
13854
|
-
ref: import_zod.z.string(),
|
|
13855
|
-
timeoutMs: import_zod.z.number().optional()
|
|
13856
|
-
},
|
|
13857
|
-
async ({ ref, timeoutMs }) => {
|
|
13858
|
-
const thread = await orch.waitForTurn(ref, timeoutMs ?? 6e5);
|
|
13859
|
-
const result = orch.getTurnResult(thread.id);
|
|
13860
|
-
return {
|
|
13861
|
-
content: [
|
|
13862
|
-
{
|
|
13863
|
-
type: "text",
|
|
13864
|
-
text: JSON.stringify({
|
|
13865
|
-
id: thread.id,
|
|
13866
|
-
status: result.status,
|
|
13867
|
-
text: result.text
|
|
13868
|
-
})
|
|
13869
|
-
}
|
|
13870
|
-
]
|
|
13871
|
-
};
|
|
13872
|
-
}
|
|
13873
|
-
);
|
|
13874
|
-
server.tool(
|
|
13875
|
-
"get_turn_result",
|
|
13876
|
-
"Final assistant message only (not full transcript)",
|
|
13877
|
-
{ ref: import_zod.z.string() },
|
|
13878
|
-
async ({ ref }) => {
|
|
13879
|
-
const result = orch.getTurnResult(ref);
|
|
13880
|
-
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
13881
|
-
}
|
|
13882
|
-
);
|
|
13883
|
-
server.tool(
|
|
13884
|
-
"stop_thread",
|
|
13885
|
-
"Force-stop a thread: kill any in-flight agent turn AND clear queued prompts so drainQueue cannot continue. Does not archive the worktree. Optional force defaults to true.",
|
|
13886
|
-
{
|
|
13887
|
-
ref: import_zod.z.string(),
|
|
13888
|
-
force: import_zod.z.boolean().optional()
|
|
13889
|
-
},
|
|
13890
|
-
async ({ ref, force }) => {
|
|
13891
|
-
const t = orch.getThread(ref);
|
|
13892
|
-
if (!t) {
|
|
14245
|
+
);
|
|
14246
|
+
server.tool(
|
|
14247
|
+
"stop_thread",
|
|
14248
|
+
"Force-stop a thread: kill any in-flight agent turn AND clear queued prompts so drainQueue cannot continue. Does not archive the worktree. Optional force defaults to true.",
|
|
14249
|
+
{
|
|
14250
|
+
ref: import_zod.z.string(),
|
|
14251
|
+
force: import_zod.z.boolean().optional()
|
|
14252
|
+
},
|
|
14253
|
+
async ({ ref, force }) => {
|
|
14254
|
+
const t = orch.getThread(ref);
|
|
14255
|
+
if (!t) {
|
|
14256
|
+
return {
|
|
14257
|
+
content: [{ type: "text", text: `Thread not found: ${ref}` }],
|
|
14258
|
+
isError: true
|
|
14259
|
+
};
|
|
14260
|
+
}
|
|
14261
|
+
const clearQueue = force !== false;
|
|
14262
|
+
const hadQueued = t.queue.length > 0;
|
|
14263
|
+
const stopped = orch.stop(ref, { clearQueue });
|
|
13893
14264
|
return {
|
|
13894
|
-
content: [
|
|
13895
|
-
|
|
14265
|
+
content: [
|
|
14266
|
+
{
|
|
14267
|
+
type: "text",
|
|
14268
|
+
text: JSON.stringify({
|
|
14269
|
+
id: stopped.id,
|
|
14270
|
+
status: stopped.status,
|
|
14271
|
+
clearedQueue: clearQueue && hadQueued
|
|
14272
|
+
})
|
|
14273
|
+
}
|
|
14274
|
+
]
|
|
13896
14275
|
};
|
|
13897
14276
|
}
|
|
13898
|
-
|
|
13899
|
-
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
|
|
13907
|
-
|
|
13908
|
-
|
|
13909
|
-
|
|
13910
|
-
|
|
13911
|
-
|
|
13912
|
-
|
|
13913
|
-
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
|
|
13917
|
-
|
|
13918
|
-
|
|
13919
|
-
async ({ ref }) => {
|
|
13920
|
-
const t = orch.getThread(ref);
|
|
13921
|
-
if (!t) {
|
|
14277
|
+
);
|
|
14278
|
+
server.tool(
|
|
14279
|
+
"archive_thread",
|
|
14280
|
+
"Archive a thread (stops agent/dev, runs archive script, removes worktree when last chat tab). Cannot archive the cloud coordinator \u2014 use the Sideboard UI for that.",
|
|
14281
|
+
{ ref: import_zod.z.string() },
|
|
14282
|
+
async ({ ref }) => {
|
|
14283
|
+
const t = orch.getThread(ref);
|
|
14284
|
+
if (!t) {
|
|
14285
|
+
return {
|
|
14286
|
+
content: [{ type: "text", text: `Thread not found: ${ref}` }],
|
|
14287
|
+
isError: true
|
|
14288
|
+
};
|
|
14289
|
+
}
|
|
14290
|
+
const blocked = mcpArchiveBlockedReason(t);
|
|
14291
|
+
if (blocked) {
|
|
14292
|
+
return {
|
|
14293
|
+
content: [{ type: "text", text: blocked }],
|
|
14294
|
+
isError: true
|
|
14295
|
+
};
|
|
14296
|
+
}
|
|
14297
|
+
const archived = await orch.archive(ref);
|
|
13922
14298
|
return {
|
|
13923
|
-
content: [
|
|
13924
|
-
|
|
14299
|
+
content: [
|
|
14300
|
+
{
|
|
14301
|
+
type: "text",
|
|
14302
|
+
text: JSON.stringify({
|
|
14303
|
+
id: archived.id,
|
|
14304
|
+
status: archived.status
|
|
14305
|
+
})
|
|
14306
|
+
}
|
|
14307
|
+
]
|
|
13925
14308
|
};
|
|
13926
14309
|
}
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
14310
|
+
);
|
|
14311
|
+
server.tool(
|
|
14312
|
+
"restore_thread",
|
|
14313
|
+
"Restore an archived thread (recreates worktree from branch when needed)",
|
|
14314
|
+
{ ref: import_zod.z.string() },
|
|
14315
|
+
async ({ ref }) => {
|
|
14316
|
+
try {
|
|
14317
|
+
const restored = await orch.restore(ref);
|
|
14318
|
+
return {
|
|
14319
|
+
content: [
|
|
14320
|
+
{
|
|
14321
|
+
type: "text",
|
|
14322
|
+
text: JSON.stringify({
|
|
14323
|
+
id: restored.id,
|
|
14324
|
+
status: restored.status,
|
|
14325
|
+
worktreePath: restored.worktreePath
|
|
14326
|
+
})
|
|
14327
|
+
}
|
|
14328
|
+
]
|
|
14329
|
+
};
|
|
14330
|
+
} catch (err) {
|
|
14331
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14332
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14333
|
+
}
|
|
13933
14334
|
}
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
]
|
|
13945
|
-
};
|
|
13946
|
-
}
|
|
13947
|
-
);
|
|
13948
|
-
server.tool(
|
|
13949
|
-
"restore_thread",
|
|
13950
|
-
"Restore an archived thread (recreates worktree from branch when needed)",
|
|
13951
|
-
{ ref: import_zod.z.string() },
|
|
13952
|
-
async ({ ref }) => {
|
|
13953
|
-
try {
|
|
13954
|
-
const restored = await orch.restore(ref);
|
|
14335
|
+
);
|
|
14336
|
+
server.tool(
|
|
14337
|
+
"get_diff",
|
|
14338
|
+
"Compact diff summary (capped hunks, paginated)",
|
|
14339
|
+
{
|
|
14340
|
+
ref: import_zod.z.string(),
|
|
14341
|
+
maxFiles: import_zod.z.number().optional()
|
|
14342
|
+
},
|
|
14343
|
+
async ({ ref, maxFiles }) => {
|
|
14344
|
+
const summary = await orch.diffSummary(ref);
|
|
13955
14345
|
return {
|
|
13956
14346
|
content: [
|
|
13957
14347
|
{
|
|
13958
14348
|
type: "text",
|
|
13959
14349
|
text: JSON.stringify({
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
worktreePath: restored.worktreePath
|
|
14350
|
+
...summary,
|
|
14351
|
+
files: summary.files.slice(0, maxFiles ?? 10)
|
|
13963
14352
|
})
|
|
13964
14353
|
}
|
|
13965
14354
|
]
|
|
13966
14355
|
};
|
|
13967
|
-
} catch (err) {
|
|
13968
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
13969
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
13970
14356
|
}
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
13974
|
-
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
13989
|
-
|
|
14357
|
+
);
|
|
14358
|
+
server.tool(
|
|
14359
|
+
"request_review",
|
|
14360
|
+
'Start a merge-readiness Review on a worktree agent thread (same as the desktop Review button). Opens a new Review chat tab, attaches .sideboard/review.md when present (else local Review request.md / stock template), and sends "Review changes in this workspace." Expect Approve / Approve with nits / Request changes / Needs more information. Pass a worktree thread ref \u2014 not the orchestrator. Then wait_for_turn / get_turn_result on the returned review tab id.',
|
|
14361
|
+
{ ref: import_zod.z.string().describe("Worktree thread id/ref to review") },
|
|
14362
|
+
async ({ ref }) => {
|
|
14363
|
+
try {
|
|
14364
|
+
const tab = await orch.requestReview(ref);
|
|
14365
|
+
const from = orch.getThread(ref);
|
|
14366
|
+
return {
|
|
14367
|
+
content: [
|
|
14368
|
+
{
|
|
14369
|
+
type: "text",
|
|
14370
|
+
text: JSON.stringify({
|
|
14371
|
+
id: tab.id,
|
|
14372
|
+
title: tab.title,
|
|
14373
|
+
status: tab.status,
|
|
14374
|
+
fromThreadId: from?.id ?? ref,
|
|
14375
|
+
link: `sideboard://thread/${tab.id}`
|
|
14376
|
+
})
|
|
14377
|
+
}
|
|
14378
|
+
]
|
|
14379
|
+
};
|
|
14380
|
+
} catch (err) {
|
|
14381
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14382
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14383
|
+
}
|
|
14384
|
+
}
|
|
14385
|
+
);
|
|
14386
|
+
const agentEnum = import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]);
|
|
14387
|
+
server.tool(
|
|
14388
|
+
"list_models",
|
|
14389
|
+
"List models for an agent. Prefer Auto: do not call this unless you have a reason to pin a specific model (user request, cost/latency, capability). Omit agent to list all.",
|
|
14390
|
+
{
|
|
14391
|
+
agent: agentEnum.optional().describe("Limit to one agent; omit for all")
|
|
14392
|
+
},
|
|
14393
|
+
async ({ agent }) => {
|
|
14394
|
+
try {
|
|
14395
|
+
const catalogs = await listModelsForAgent(agent);
|
|
14396
|
+
return {
|
|
14397
|
+
content: [{ type: "text", text: JSON.stringify(catalogs, null, 2) }]
|
|
14398
|
+
};
|
|
14399
|
+
} catch (err) {
|
|
14400
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14401
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14402
|
+
}
|
|
14403
|
+
}
|
|
14404
|
+
);
|
|
14405
|
+
server.tool(
|
|
14406
|
+
"fork_worktree",
|
|
14407
|
+
"Fork a worktree agent chat into a NEW git worktree + chat (desktop \u201CFork to new workspace\u201D). Seeds a transcript (through through_index, default all). Optional agent override. Leave model unset for Auto (default) \u2014 only pass model when you have a reason. Not for the orchestrator. Then send_to_thread / wait_for_turn on the returned id.",
|
|
14408
|
+
{
|
|
14409
|
+
ref: import_zod.z.string().describe("Worktree thread id/ref to fork"),
|
|
14410
|
+
through_index: import_zod.z.number().optional().describe("Inclusive message index to include in the transcript (default: all)"),
|
|
14411
|
+
agent: agentEnum.optional().describe("Agent for the forked chat (default: same as source)"),
|
|
14412
|
+
model: import_zod.z.string().nullable().optional().describe("Usually omit (Auto). Only set from list_models when you need a specific model"),
|
|
14413
|
+
title: import_zod.z.string().optional()
|
|
14414
|
+
},
|
|
14415
|
+
async ({ ref, through_index, agent, model, title }) => {
|
|
14416
|
+
try {
|
|
14417
|
+
const source = orch.getThread(ref);
|
|
14418
|
+
if (source) await orch.reconcile(source.repoPath, { drainQueues: false });
|
|
14419
|
+
const thread = await orch.forkThreadWorktree({
|
|
14420
|
+
threadId: ref,
|
|
14421
|
+
throughIndex: through_index,
|
|
14422
|
+
agent,
|
|
14423
|
+
model,
|
|
14424
|
+
title
|
|
14425
|
+
});
|
|
14426
|
+
return {
|
|
14427
|
+
content: [
|
|
14428
|
+
{
|
|
14429
|
+
type: "text",
|
|
14430
|
+
text: JSON.stringify({
|
|
14431
|
+
id: thread.id,
|
|
14432
|
+
title: thread.title,
|
|
14433
|
+
status: thread.status,
|
|
14434
|
+
agent: thread.agent,
|
|
14435
|
+
model: thread.model,
|
|
14436
|
+
branchName: thread.branchName,
|
|
14437
|
+
worktreePath: thread.worktreePath,
|
|
14438
|
+
fromThreadId: source?.id ?? ref,
|
|
14439
|
+
link: `sideboard://thread/${thread.id}`
|
|
14440
|
+
})
|
|
14441
|
+
}
|
|
14442
|
+
]
|
|
14443
|
+
};
|
|
14444
|
+
} catch (err) {
|
|
14445
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14446
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14447
|
+
}
|
|
14448
|
+
}
|
|
14449
|
+
);
|
|
14450
|
+
server.tool(
|
|
14451
|
+
"fork_chat",
|
|
14452
|
+
"Fork a chat into a NEW tab on the SAME workspace: worktree agent \u2192 same worktree tab; Global orchestration chat \u2192 new orchestration chat (same synthetic home). Seeds a transcript; optional agent override. Leave model unset for Auto unless you have a reason. Orchestration forks require an MCP-capable agent (claude, cursor, codex, opencode \u2014 not brightsy). Remote coordinators use this to continue an orchestration chat on another agent after session limits. Then send_to_thread / wait_for_turn on the returned id. Use fork_worktree only for worktree agents that need a new git worktree.",
|
|
14453
|
+
{
|
|
14454
|
+
ref: import_zod.z.string().describe("Thread id/ref to fork (worktree agent or orchestration chat)"),
|
|
14455
|
+
through_index: import_zod.z.number().optional().describe("Inclusive message index to include in the transcript (default: all)"),
|
|
14456
|
+
agent: agentEnum.optional().describe("Agent for the forked chat (default: same as source)"),
|
|
14457
|
+
model: import_zod.z.string().nullable().optional().describe("Usually omit (Auto). Only set from list_models when you need a specific model"),
|
|
14458
|
+
title: import_zod.z.string().optional()
|
|
14459
|
+
},
|
|
14460
|
+
async ({ ref, through_index, agent, model, title }) => {
|
|
14461
|
+
try {
|
|
14462
|
+
const source = orch.getThread(ref);
|
|
14463
|
+
if (!source) {
|
|
14464
|
+
return {
|
|
14465
|
+
content: [{ type: "text", text: `Thread not found: ${ref}` }],
|
|
14466
|
+
isError: true
|
|
14467
|
+
};
|
|
13990
14468
|
}
|
|
13991
|
-
|
|
13992
|
-
|
|
13993
|
-
|
|
13994
|
-
|
|
13995
|
-
|
|
13996
|
-
|
|
13997
|
-
|
|
13998
|
-
|
|
13999
|
-
|
|
14000
|
-
|
|
14001
|
-
|
|
14002
|
-
|
|
14469
|
+
const tab = orch.forkChatTab({
|
|
14470
|
+
threadId: source.id,
|
|
14471
|
+
throughIndex: through_index,
|
|
14472
|
+
agent,
|
|
14473
|
+
model,
|
|
14474
|
+
title
|
|
14475
|
+
});
|
|
14476
|
+
return {
|
|
14477
|
+
content: [
|
|
14478
|
+
{
|
|
14479
|
+
type: "text",
|
|
14480
|
+
text: JSON.stringify({
|
|
14481
|
+
id: tab.id,
|
|
14482
|
+
title: tab.title,
|
|
14483
|
+
status: tab.status,
|
|
14484
|
+
agent: tab.agent,
|
|
14485
|
+
model: tab.model,
|
|
14486
|
+
sourceType: tab.sourceType,
|
|
14487
|
+
worktreePath: tab.worktreePath,
|
|
14488
|
+
fromThreadId: source.id,
|
|
14489
|
+
link: `sideboard://thread/${tab.id}`
|
|
14490
|
+
})
|
|
14491
|
+
}
|
|
14492
|
+
]
|
|
14493
|
+
};
|
|
14494
|
+
} catch (err) {
|
|
14495
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14496
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14497
|
+
}
|
|
14498
|
+
}
|
|
14499
|
+
);
|
|
14500
|
+
server.tool(
|
|
14501
|
+
"run_dev_script",
|
|
14502
|
+
"Start a .sideboard/.conductor run script for a thread (default script if name omitted); returns port",
|
|
14503
|
+
{
|
|
14504
|
+
ref: import_zod.z.string(),
|
|
14505
|
+
name: import_zod.z.string().optional()
|
|
14506
|
+
},
|
|
14507
|
+
async ({ ref, name }) => {
|
|
14508
|
+
const result = await orch.startDev(ref, name);
|
|
14003
14509
|
return {
|
|
14004
14510
|
content: [
|
|
14005
14511
|
{
|
|
14006
14512
|
type: "text",
|
|
14007
14513
|
text: JSON.stringify({
|
|
14008
|
-
|
|
14009
|
-
|
|
14010
|
-
|
|
14011
|
-
|
|
14012
|
-
link: `sideboard://thread/${tab.id}`
|
|
14514
|
+
port: result.port,
|
|
14515
|
+
scriptName: result.scriptName,
|
|
14516
|
+
ports: result.ports,
|
|
14517
|
+
url: `http://localhost:${result.port}`
|
|
14013
14518
|
})
|
|
14014
14519
|
}
|
|
14015
14520
|
]
|
|
14016
14521
|
};
|
|
14017
|
-
} catch (err) {
|
|
14018
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
14019
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
14020
14522
|
}
|
|
14021
|
-
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
|
|
14025
|
-
|
|
14026
|
-
|
|
14027
|
-
|
|
14028
|
-
|
|
14029
|
-
},
|
|
14030
|
-
async ({ agent }) => {
|
|
14031
|
-
try {
|
|
14032
|
-
const catalogs = await listModelsForAgent(agent);
|
|
14523
|
+
);
|
|
14524
|
+
server.tool(
|
|
14525
|
+
"list_run_scripts",
|
|
14526
|
+
"List named run scripts available for a thread",
|
|
14527
|
+
{ ref: import_zod.z.string() },
|
|
14528
|
+
async ({ ref }) => {
|
|
14529
|
+
const scripts = orch.listThreadRunScripts(ref);
|
|
14530
|
+
const active = orch.getActiveRuns(ref);
|
|
14033
14531
|
return {
|
|
14034
|
-
content: [
|
|
14532
|
+
content: [
|
|
14533
|
+
{
|
|
14534
|
+
type: "text",
|
|
14535
|
+
text: JSON.stringify({ scripts, active }, null, 2)
|
|
14536
|
+
}
|
|
14537
|
+
]
|
|
14035
14538
|
};
|
|
14036
|
-
} catch (err) {
|
|
14037
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
14038
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
14039
14539
|
}
|
|
14040
|
-
|
|
14041
|
-
|
|
14042
|
-
|
|
14043
|
-
|
|
14044
|
-
|
|
14045
|
-
|
|
14046
|
-
|
|
14047
|
-
|
|
14048
|
-
|
|
14049
|
-
|
|
14050
|
-
|
|
14051
|
-
|
|
14052
|
-
|
|
14053
|
-
|
|
14054
|
-
|
|
14055
|
-
|
|
14056
|
-
|
|
14057
|
-
|
|
14058
|
-
|
|
14059
|
-
|
|
14060
|
-
|
|
14061
|
-
|
|
14540
|
+
);
|
|
14541
|
+
server.tool(
|
|
14542
|
+
"stop_dev_script",
|
|
14543
|
+
"Stop a running script for a thread (all scripts if name omitted)",
|
|
14544
|
+
{
|
|
14545
|
+
ref: import_zod.z.string(),
|
|
14546
|
+
name: import_zod.z.string().optional()
|
|
14547
|
+
},
|
|
14548
|
+
async ({ ref, name }) => {
|
|
14549
|
+
orch.stopDev(ref, name);
|
|
14550
|
+
return { content: [{ type: "text", text: "ok" }] };
|
|
14551
|
+
}
|
|
14552
|
+
);
|
|
14553
|
+
server.tool(
|
|
14554
|
+
"run_setup",
|
|
14555
|
+
"Re-run workspace setup (Sideboard/Conductor settings or .cursor/worktrees.json)",
|
|
14556
|
+
{ ref: import_zod.z.string() },
|
|
14557
|
+
async ({ ref }) => {
|
|
14558
|
+
const result = await orch.runSetup(ref);
|
|
14559
|
+
return {
|
|
14560
|
+
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
14561
|
+
};
|
|
14562
|
+
}
|
|
14563
|
+
);
|
|
14564
|
+
server.tool(
|
|
14565
|
+
"add_workspace",
|
|
14566
|
+
"Register a git repo as a Sideboard workspace",
|
|
14567
|
+
{ repoPath: import_zod.z.string() },
|
|
14568
|
+
async ({ repoPath }) => {
|
|
14569
|
+
const ws = await orch.addWorkspace(repoPath);
|
|
14570
|
+
return { content: [{ type: "text", text: JSON.stringify(ws) }] };
|
|
14571
|
+
}
|
|
14572
|
+
);
|
|
14573
|
+
server.tool(
|
|
14574
|
+
"remove_workspace",
|
|
14575
|
+
"Unregister a Sideboard workspace (does not archive threads)",
|
|
14576
|
+
{ repoPath: import_zod.z.string() },
|
|
14577
|
+
async ({ repoPath }) => {
|
|
14578
|
+
orch.removeWorkspace(repoPath);
|
|
14579
|
+
return { content: [{ type: "text", text: "ok" }] };
|
|
14580
|
+
}
|
|
14581
|
+
);
|
|
14582
|
+
server.tool(
|
|
14583
|
+
"fanout",
|
|
14584
|
+
"Best-of-n: create one thread per agent with the same prompt (parallel attempts)",
|
|
14585
|
+
{
|
|
14586
|
+
prompt: import_zod.z.string(),
|
|
14587
|
+
agents: import_zod.z.array(import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"])),
|
|
14588
|
+
repoPath: import_zod.z.string(),
|
|
14589
|
+
sourceType: import_zod.z.enum(["branch", "pr", "ticket"]).optional(),
|
|
14590
|
+
sourceRef: import_zod.z.string().optional(),
|
|
14591
|
+
title: import_zod.z.string().optional()
|
|
14592
|
+
},
|
|
14593
|
+
async (args) => {
|
|
14594
|
+
const threads = await orch.bestOfN(args);
|
|
14595
|
+
return {
|
|
14596
|
+
content: [
|
|
14597
|
+
{
|
|
14598
|
+
type: "text",
|
|
14599
|
+
text: JSON.stringify(
|
|
14600
|
+
threads.map((t) => ({
|
|
14601
|
+
id: t.id,
|
|
14602
|
+
agent: t.agent,
|
|
14603
|
+
branchName: t.branchName,
|
|
14604
|
+
worktreePath: t.worktreePath
|
|
14605
|
+
})),
|
|
14606
|
+
null,
|
|
14607
|
+
2
|
|
14608
|
+
)
|
|
14609
|
+
}
|
|
14610
|
+
]
|
|
14611
|
+
};
|
|
14612
|
+
}
|
|
14613
|
+
);
|
|
14614
|
+
server.tool(
|
|
14615
|
+
"list_branches",
|
|
14616
|
+
"List git branches in a registered workspace. Pass repoPath from list_workspaces (unmerged into the default branch by default \u2014 for create_thread sourceType=branch).",
|
|
14617
|
+
{
|
|
14618
|
+
repoPath: import_zod.z.string(),
|
|
14619
|
+
unmergedOnly: import_zod.z.boolean().optional()
|
|
14620
|
+
},
|
|
14621
|
+
async ({ repoPath, unmergedOnly }) => {
|
|
14622
|
+
const root = await resolveRepoRoot(repoPath);
|
|
14623
|
+
const branches = await listBranches(root, {
|
|
14624
|
+
unmergedOnly: unmergedOnly !== false
|
|
14062
14625
|
});
|
|
14063
14626
|
return {
|
|
14064
14627
|
content: [
|
|
14065
14628
|
{
|
|
14066
14629
|
type: "text",
|
|
14067
|
-
text:
|
|
14068
|
-
id: thread.id,
|
|
14069
|
-
title: thread.title,
|
|
14070
|
-
status: thread.status,
|
|
14071
|
-
agent: thread.agent,
|
|
14072
|
-
model: thread.model,
|
|
14073
|
-
branchName: thread.branchName,
|
|
14074
|
-
worktreePath: thread.worktreePath,
|
|
14075
|
-
fromThreadId: source?.id ?? ref,
|
|
14076
|
-
link: `sideboard://thread/${thread.id}`
|
|
14077
|
-
})
|
|
14630
|
+
text: branches.map((b) => `${b.current ? "*" : " "} ${b.name}`).join("\n")
|
|
14078
14631
|
}
|
|
14079
14632
|
]
|
|
14080
14633
|
};
|
|
14081
|
-
} catch (err) {
|
|
14082
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
14083
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
14084
14634
|
}
|
|
14085
|
-
|
|
14086
|
-
|
|
14087
|
-
|
|
14088
|
-
|
|
14089
|
-
|
|
14090
|
-
|
|
14091
|
-
|
|
14092
|
-
|
|
14093
|
-
|
|
14094
|
-
|
|
14095
|
-
|
|
14096
|
-
|
|
14097
|
-
|
|
14098
|
-
|
|
14099
|
-
|
|
14100
|
-
|
|
14101
|
-
|
|
14102
|
-
|
|
14103
|
-
|
|
14104
|
-
|
|
14105
|
-
|
|
14106
|
-
|
|
14107
|
-
|
|
14108
|
-
|
|
14109
|
-
|
|
14110
|
-
|
|
14111
|
-
|
|
14635
|
+
);
|
|
14636
|
+
server.tool(
|
|
14637
|
+
"list_prs",
|
|
14638
|
+
"List open GitHub PRs for a registered workspace. Pass repoPath from list_workspaces (uses gh against that repo remote). Then create_thread with sourceType=pr.",
|
|
14639
|
+
{ repoPath: import_zod.z.string() },
|
|
14640
|
+
async ({ repoPath }) => {
|
|
14641
|
+
const root = await resolveRepoRoot(repoPath);
|
|
14642
|
+
const prs = await listPrs(root);
|
|
14643
|
+
return {
|
|
14644
|
+
content: [
|
|
14645
|
+
{
|
|
14646
|
+
type: "text",
|
|
14647
|
+
text: prs.map(
|
|
14648
|
+
(p) => `#${p.number} ${p.title} (${p.headRefName})${p.isCrossRepository ? " [fork]" : ""}`
|
|
14649
|
+
).join("\n")
|
|
14650
|
+
}
|
|
14651
|
+
]
|
|
14652
|
+
};
|
|
14653
|
+
}
|
|
14654
|
+
);
|
|
14655
|
+
server.tool(
|
|
14656
|
+
"get_pr_stack",
|
|
14657
|
+
"Load the GitHub PR stack for a thread worktree (`gh stack view --json`). Returns null JSON when the branch is not stacked. Prefer this before mergePr on stacked PRs.",
|
|
14658
|
+
{ ref: import_zod.z.string() },
|
|
14659
|
+
async ({ ref }) => {
|
|
14660
|
+
const stack = await orch.getPrStack(ref);
|
|
14661
|
+
return {
|
|
14662
|
+
content: [{ type: "text", text: JSON.stringify(stack, null, 2) }]
|
|
14663
|
+
};
|
|
14664
|
+
}
|
|
14665
|
+
);
|
|
14666
|
+
server.tool(
|
|
14667
|
+
"open_pr_stack_layers",
|
|
14668
|
+
"Materialize one worktree+thread per stack layer (or a single 1-based layer). Pass a thread ref already on the stack.",
|
|
14669
|
+
{
|
|
14670
|
+
ref: import_zod.z.string(),
|
|
14671
|
+
layer: import_zod.z.number().int().positive().optional()
|
|
14672
|
+
},
|
|
14673
|
+
async ({ ref, layer }) => {
|
|
14674
|
+
const result = await orch.openPrStackLayers(ref, { layer });
|
|
14675
|
+
return {
|
|
14676
|
+
content: [
|
|
14677
|
+
{
|
|
14678
|
+
type: "text",
|
|
14679
|
+
text: JSON.stringify(
|
|
14680
|
+
{
|
|
14681
|
+
stackNumber: result.stack.stackNumber,
|
|
14682
|
+
trunk: result.stack.trunk,
|
|
14683
|
+
threads: result.threads.map((t) => ({
|
|
14684
|
+
id: t.id,
|
|
14685
|
+
title: t.title,
|
|
14686
|
+
branchName: t.branchName,
|
|
14687
|
+
stackLayer: t.stackLayer,
|
|
14688
|
+
worktreePath: t.worktreePath,
|
|
14689
|
+
prUrl: t.prUrl,
|
|
14690
|
+
link: `sideboard://thread/${t.id}`
|
|
14691
|
+
}))
|
|
14692
|
+
},
|
|
14693
|
+
null,
|
|
14694
|
+
2
|
|
14695
|
+
)
|
|
14696
|
+
}
|
|
14697
|
+
]
|
|
14698
|
+
};
|
|
14699
|
+
}
|
|
14700
|
+
);
|
|
14701
|
+
server.tool(
|
|
14702
|
+
"add_stack_layer",
|
|
14703
|
+
"Add a branch on top of the current stack (`gh stack add`) and open a worktree+thread for it.",
|
|
14704
|
+
{
|
|
14705
|
+
ref: import_zod.z.string(),
|
|
14706
|
+
branchName: import_zod.z.string(),
|
|
14707
|
+
title: import_zod.z.string().optional()
|
|
14708
|
+
},
|
|
14709
|
+
async ({ ref, branchName, title }) => {
|
|
14710
|
+
const result = await orch.addStackLayer(ref, branchName, { title });
|
|
14711
|
+
return {
|
|
14712
|
+
content: [
|
|
14713
|
+
{
|
|
14714
|
+
type: "text",
|
|
14715
|
+
text: JSON.stringify(
|
|
14716
|
+
{
|
|
14717
|
+
id: result.thread.id,
|
|
14718
|
+
title: result.thread.title,
|
|
14719
|
+
branchName: result.thread.branchName,
|
|
14720
|
+
stackLayer: result.thread.stackLayer,
|
|
14721
|
+
worktreePath: result.thread.worktreePath,
|
|
14722
|
+
link: `sideboard://thread/${result.thread.id}`
|
|
14723
|
+
},
|
|
14724
|
+
null,
|
|
14725
|
+
2
|
|
14726
|
+
)
|
|
14727
|
+
}
|
|
14728
|
+
]
|
|
14729
|
+
};
|
|
14730
|
+
}
|
|
14731
|
+
);
|
|
14732
|
+
server.tool(
|
|
14733
|
+
"create_pr_stack",
|
|
14734
|
+
"Create a new GitHub PR stack with one Sideboard worktree per layer (bottom\u2192top branch names). Requires `gh extension install github/gh-stack`.",
|
|
14735
|
+
{
|
|
14736
|
+
repoPath: import_zod.z.string(),
|
|
14737
|
+
branches: import_zod.z.array(import_zod.z.string()).min(1),
|
|
14738
|
+
agent: import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]),
|
|
14739
|
+
base: import_zod.z.string().optional(),
|
|
14740
|
+
title: import_zod.z.string().optional()
|
|
14741
|
+
},
|
|
14742
|
+
async (args) => {
|
|
14743
|
+
const result = await orch.createPrStack({
|
|
14744
|
+
repoPath: args.repoPath,
|
|
14745
|
+
branches: args.branches,
|
|
14746
|
+
agent: args.agent,
|
|
14747
|
+
base: args.base,
|
|
14748
|
+
title: args.title
|
|
14112
14749
|
});
|
|
14113
14750
|
return {
|
|
14114
14751
|
content: [
|
|
14115
14752
|
{
|
|
14116
14753
|
type: "text",
|
|
14117
|
-
text: JSON.stringify(
|
|
14118
|
-
|
|
14119
|
-
|
|
14120
|
-
|
|
14121
|
-
|
|
14122
|
-
|
|
14123
|
-
|
|
14124
|
-
|
|
14125
|
-
|
|
14126
|
-
|
|
14127
|
-
|
|
14754
|
+
text: JSON.stringify(
|
|
14755
|
+
{
|
|
14756
|
+
stackNumber: result.stack.stackNumber,
|
|
14757
|
+
trunk: result.stack.trunk,
|
|
14758
|
+
threads: result.threads.map((t) => ({
|
|
14759
|
+
id: t.id,
|
|
14760
|
+
title: t.title,
|
|
14761
|
+
branchName: t.branchName,
|
|
14762
|
+
stackLayer: t.stackLayer,
|
|
14763
|
+
worktreePath: t.worktreePath,
|
|
14764
|
+
link: `sideboard://thread/${t.id}`
|
|
14765
|
+
}))
|
|
14766
|
+
},
|
|
14767
|
+
null,
|
|
14768
|
+
2
|
|
14769
|
+
)
|
|
14128
14770
|
}
|
|
14129
14771
|
]
|
|
14130
14772
|
};
|
|
14131
|
-
} catch (err) {
|
|
14132
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
14133
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
14134
14773
|
}
|
|
14135
|
-
|
|
14136
|
-
|
|
14137
|
-
|
|
14138
|
-
|
|
14139
|
-
|
|
14140
|
-
|
|
14141
|
-
|
|
14142
|
-
|
|
14143
|
-
|
|
14144
|
-
|
|
14145
|
-
|
|
14146
|
-
|
|
14147
|
-
|
|
14148
|
-
|
|
14149
|
-
|
|
14150
|
-
|
|
14151
|
-
|
|
14152
|
-
|
|
14153
|
-
|
|
14154
|
-
|
|
14155
|
-
|
|
14156
|
-
|
|
14157
|
-
|
|
14158
|
-
|
|
14159
|
-
}
|
|
14160
|
-
);
|
|
14161
|
-
server.tool(
|
|
14162
|
-
"list_run_scripts",
|
|
14163
|
-
"List named run scripts available for a thread",
|
|
14164
|
-
{ ref: import_zod.z.string() },
|
|
14165
|
-
async ({ ref }) => {
|
|
14166
|
-
const scripts = orch.listThreadRunScripts(ref);
|
|
14167
|
-
const active = orch.getActiveRuns(ref);
|
|
14168
|
-
return {
|
|
14169
|
-
content: [
|
|
14170
|
-
{
|
|
14171
|
-
type: "text",
|
|
14172
|
-
text: JSON.stringify({ scripts, active }, null, 2)
|
|
14173
|
-
}
|
|
14174
|
-
]
|
|
14175
|
-
};
|
|
14176
|
-
}
|
|
14177
|
-
);
|
|
14178
|
-
server.tool(
|
|
14179
|
-
"stop_dev_script",
|
|
14180
|
-
"Stop a running script for a thread (all scripts if name omitted)",
|
|
14181
|
-
{
|
|
14182
|
-
ref: import_zod.z.string(),
|
|
14183
|
-
name: import_zod.z.string().optional()
|
|
14184
|
-
},
|
|
14185
|
-
async ({ ref, name }) => {
|
|
14186
|
-
orch.stopDev(ref, name);
|
|
14187
|
-
return { content: [{ type: "text", text: "ok" }] };
|
|
14188
|
-
}
|
|
14189
|
-
);
|
|
14190
|
-
server.tool(
|
|
14191
|
-
"run_setup",
|
|
14192
|
-
"Re-run workspace setup (Sideboard/Conductor settings or .cursor/worktrees.json)",
|
|
14193
|
-
{ ref: import_zod.z.string() },
|
|
14194
|
-
async ({ ref }) => {
|
|
14195
|
-
const result = await orch.runSetup(ref);
|
|
14196
|
-
return {
|
|
14197
|
-
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
14198
|
-
};
|
|
14199
|
-
}
|
|
14200
|
-
);
|
|
14201
|
-
server.tool(
|
|
14202
|
-
"add_workspace",
|
|
14203
|
-
"Register a git repo as a Sideboard workspace",
|
|
14204
|
-
{ repoPath: import_zod.z.string() },
|
|
14205
|
-
async ({ repoPath }) => {
|
|
14206
|
-
const ws = await orch.addWorkspace(repoPath);
|
|
14207
|
-
return { content: [{ type: "text", text: JSON.stringify(ws) }] };
|
|
14208
|
-
}
|
|
14209
|
-
);
|
|
14210
|
-
server.tool(
|
|
14211
|
-
"remove_workspace",
|
|
14212
|
-
"Unregister a Sideboard workspace (does not archive threads)",
|
|
14213
|
-
{ repoPath: import_zod.z.string() },
|
|
14214
|
-
async ({ repoPath }) => {
|
|
14215
|
-
orch.removeWorkspace(repoPath);
|
|
14216
|
-
return { content: [{ type: "text", text: "ok" }] };
|
|
14217
|
-
}
|
|
14218
|
-
);
|
|
14219
|
-
server.tool(
|
|
14220
|
-
"fanout",
|
|
14221
|
-
"Best-of-n: create one thread per agent with the same prompt (parallel attempts)",
|
|
14222
|
-
{
|
|
14223
|
-
prompt: import_zod.z.string(),
|
|
14224
|
-
agents: import_zod.z.array(import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"])),
|
|
14225
|
-
repoPath: import_zod.z.string(),
|
|
14226
|
-
sourceType: import_zod.z.enum(["branch", "pr", "ticket"]).optional(),
|
|
14227
|
-
sourceRef: import_zod.z.string().optional(),
|
|
14228
|
-
title: import_zod.z.string().optional()
|
|
14229
|
-
},
|
|
14230
|
-
async (args) => {
|
|
14231
|
-
const threads = await orch.bestOfN(args);
|
|
14232
|
-
return {
|
|
14233
|
-
content: [
|
|
14234
|
-
{
|
|
14235
|
-
type: "text",
|
|
14236
|
-
text: JSON.stringify(
|
|
14237
|
-
threads.map((t) => ({
|
|
14238
|
-
id: t.id,
|
|
14239
|
-
agent: t.agent,
|
|
14240
|
-
branchName: t.branchName,
|
|
14241
|
-
worktreePath: t.worktreePath
|
|
14242
|
-
})),
|
|
14243
|
-
null,
|
|
14244
|
-
2
|
|
14245
|
-
)
|
|
14246
|
-
}
|
|
14247
|
-
]
|
|
14248
|
-
};
|
|
14249
|
-
}
|
|
14250
|
-
);
|
|
14251
|
-
server.tool(
|
|
14252
|
-
"list_branches",
|
|
14253
|
-
"List git branches in a registered workspace. Pass repoPath from list_workspaces (unmerged into the default branch by default \u2014 for create_thread sourceType=branch).",
|
|
14254
|
-
{
|
|
14255
|
-
repoPath: import_zod.z.string(),
|
|
14256
|
-
unmergedOnly: import_zod.z.boolean().optional()
|
|
14257
|
-
},
|
|
14258
|
-
async ({ repoPath, unmergedOnly }) => {
|
|
14259
|
-
const root = await resolveRepoRoot(repoPath);
|
|
14260
|
-
const branches = await listBranches(root, {
|
|
14261
|
-
unmergedOnly: unmergedOnly !== false
|
|
14262
|
-
});
|
|
14263
|
-
return {
|
|
14264
|
-
content: [
|
|
14265
|
-
{
|
|
14266
|
-
type: "text",
|
|
14267
|
-
text: branches.map((b) => `${b.current ? "*" : " "} ${b.name}`).join("\n")
|
|
14268
|
-
}
|
|
14269
|
-
]
|
|
14270
|
-
};
|
|
14271
|
-
}
|
|
14272
|
-
);
|
|
14273
|
-
server.tool(
|
|
14274
|
-
"list_prs",
|
|
14275
|
-
"List open GitHub PRs for a registered workspace. Pass repoPath from list_workspaces (uses gh against that repo remote). Then create_thread with sourceType=pr.",
|
|
14276
|
-
{ repoPath: import_zod.z.string() },
|
|
14277
|
-
async ({ repoPath }) => {
|
|
14278
|
-
const root = await resolveRepoRoot(repoPath);
|
|
14279
|
-
const prs = await listPrs(root);
|
|
14280
|
-
return {
|
|
14281
|
-
content: [
|
|
14282
|
-
{
|
|
14283
|
-
type: "text",
|
|
14284
|
-
text: prs.map(
|
|
14285
|
-
(p) => `#${p.number} ${p.title} (${p.headRefName})${p.isCrossRepository ? " [fork]" : ""}`
|
|
14286
|
-
).join("\n")
|
|
14287
|
-
}
|
|
14288
|
-
]
|
|
14289
|
-
};
|
|
14290
|
-
}
|
|
14291
|
-
);
|
|
14292
|
-
server.tool(
|
|
14293
|
-
"get_pr_stack",
|
|
14294
|
-
"Load the GitHub PR stack for a thread worktree (`gh stack view --json`). Returns null JSON when the branch is not stacked. Prefer this before mergePr on stacked PRs.",
|
|
14295
|
-
{ ref: import_zod.z.string() },
|
|
14296
|
-
async ({ ref }) => {
|
|
14297
|
-
const stack = await orch.getPrStack(ref);
|
|
14298
|
-
return {
|
|
14299
|
-
content: [{ type: "text", text: JSON.stringify(stack, null, 2) }]
|
|
14300
|
-
};
|
|
14301
|
-
}
|
|
14302
|
-
);
|
|
14303
|
-
server.tool(
|
|
14304
|
-
"open_pr_stack_layers",
|
|
14305
|
-
"Materialize one worktree+thread per stack layer (or a single 1-based layer). Pass a thread ref already on the stack.",
|
|
14306
|
-
{
|
|
14307
|
-
ref: import_zod.z.string(),
|
|
14308
|
-
layer: import_zod.z.number().int().positive().optional()
|
|
14309
|
-
},
|
|
14310
|
-
async ({ ref, layer }) => {
|
|
14311
|
-
const result = await orch.openPrStackLayers(ref, { layer });
|
|
14312
|
-
return {
|
|
14313
|
-
content: [
|
|
14314
|
-
{
|
|
14315
|
-
type: "text",
|
|
14316
|
-
text: JSON.stringify(
|
|
14317
|
-
{
|
|
14318
|
-
stackNumber: result.stack.stackNumber,
|
|
14319
|
-
trunk: result.stack.trunk,
|
|
14320
|
-
threads: result.threads.map((t) => ({
|
|
14321
|
-
id: t.id,
|
|
14322
|
-
title: t.title,
|
|
14323
|
-
branchName: t.branchName,
|
|
14324
|
-
stackLayer: t.stackLayer,
|
|
14325
|
-
worktreePath: t.worktreePath,
|
|
14326
|
-
prUrl: t.prUrl,
|
|
14327
|
-
link: `sideboard://thread/${t.id}`
|
|
14328
|
-
}))
|
|
14329
|
-
},
|
|
14330
|
-
null,
|
|
14331
|
-
2
|
|
14332
|
-
)
|
|
14333
|
-
}
|
|
14334
|
-
]
|
|
14335
|
-
};
|
|
14336
|
-
}
|
|
14337
|
-
);
|
|
14338
|
-
server.tool(
|
|
14339
|
-
"add_stack_layer",
|
|
14340
|
-
"Add a branch on top of the current stack (`gh stack add`) and open a worktree+thread for it.",
|
|
14341
|
-
{
|
|
14342
|
-
ref: import_zod.z.string(),
|
|
14343
|
-
branchName: import_zod.z.string(),
|
|
14344
|
-
title: import_zod.z.string().optional()
|
|
14345
|
-
},
|
|
14346
|
-
async ({ ref, branchName, title }) => {
|
|
14347
|
-
const result = await orch.addStackLayer(ref, branchName, { title });
|
|
14348
|
-
return {
|
|
14349
|
-
content: [
|
|
14350
|
-
{
|
|
14351
|
-
type: "text",
|
|
14352
|
-
text: JSON.stringify(
|
|
14353
|
-
{
|
|
14354
|
-
id: result.thread.id,
|
|
14355
|
-
title: result.thread.title,
|
|
14356
|
-
branchName: result.thread.branchName,
|
|
14357
|
-
stackLayer: result.thread.stackLayer,
|
|
14358
|
-
worktreePath: result.thread.worktreePath,
|
|
14359
|
-
link: `sideboard://thread/${result.thread.id}`
|
|
14360
|
-
},
|
|
14361
|
-
null,
|
|
14362
|
-
2
|
|
14363
|
-
)
|
|
14364
|
-
}
|
|
14365
|
-
]
|
|
14366
|
-
};
|
|
14367
|
-
}
|
|
14368
|
-
);
|
|
14369
|
-
server.tool(
|
|
14370
|
-
"create_pr_stack",
|
|
14371
|
-
"Create a new GitHub PR stack with one Sideboard worktree per layer (bottom\u2192top branch names). Requires `gh extension install github/gh-stack`.",
|
|
14372
|
-
{
|
|
14373
|
-
repoPath: import_zod.z.string(),
|
|
14374
|
-
branches: import_zod.z.array(import_zod.z.string()).min(1),
|
|
14375
|
-
agent: import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]),
|
|
14376
|
-
base: import_zod.z.string().optional(),
|
|
14377
|
-
title: import_zod.z.string().optional()
|
|
14378
|
-
},
|
|
14379
|
-
async (args) => {
|
|
14380
|
-
const result = await orch.createPrStack({
|
|
14381
|
-
repoPath: args.repoPath,
|
|
14382
|
-
branches: args.branches,
|
|
14383
|
-
agent: args.agent,
|
|
14384
|
-
base: args.base,
|
|
14385
|
-
title: args.title
|
|
14386
|
-
});
|
|
14387
|
-
return {
|
|
14388
|
-
content: [
|
|
14389
|
-
{
|
|
14390
|
-
type: "text",
|
|
14391
|
-
text: JSON.stringify(
|
|
14392
|
-
{
|
|
14393
|
-
stackNumber: result.stack.stackNumber,
|
|
14394
|
-
trunk: result.stack.trunk,
|
|
14395
|
-
threads: result.threads.map((t) => ({
|
|
14396
|
-
id: t.id,
|
|
14397
|
-
title: t.title,
|
|
14398
|
-
branchName: t.branchName,
|
|
14399
|
-
stackLayer: t.stackLayer,
|
|
14400
|
-
worktreePath: t.worktreePath,
|
|
14401
|
-
link: `sideboard://thread/${t.id}`
|
|
14402
|
-
}))
|
|
14403
|
-
},
|
|
14404
|
-
null,
|
|
14405
|
-
2
|
|
14406
|
-
)
|
|
14407
|
-
}
|
|
14408
|
-
]
|
|
14409
|
-
};
|
|
14410
|
-
}
|
|
14411
|
-
);
|
|
14412
|
-
server.tool(
|
|
14413
|
-
"list_issues",
|
|
14414
|
-
"List issues from Sideboard Account connections (Linear API or GitHub Issues; Linear\u2192GitHub fallback when Linear is not connected). Pass repoPath from list_workspaces \u2014 GitHub Issues are scoped to that repo. Then create_thread with sourceType=ticket.",
|
|
14415
|
-
{ repoPath: import_zod.z.string() },
|
|
14416
|
-
async ({ repoPath }) => {
|
|
14417
|
-
const root = await resolveRepoRoot(repoPath);
|
|
14418
|
-
const result = await listIssues(root);
|
|
14419
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
14420
|
-
}
|
|
14421
|
-
);
|
|
14422
|
-
server.tool(
|
|
14423
|
-
"list_linear_issues",
|
|
14424
|
-
"Deprecated: prefer list_issues. Lists assigned Linear issues via the chosen agent MCP connector",
|
|
14425
|
-
{
|
|
14426
|
-
agent: import_zod.z.enum(["claude", "codex", "opencode"]),
|
|
14427
|
-
repoPath: import_zod.z.string()
|
|
14428
|
-
},
|
|
14429
|
-
async ({ agent, repoPath }) => {
|
|
14430
|
-
const issues = await listLinearIssues(agent, repoPath);
|
|
14431
|
-
return { content: [{ type: "text", text: JSON.stringify(issues, null, 2) }] };
|
|
14432
|
-
}
|
|
14433
|
-
);
|
|
14774
|
+
);
|
|
14775
|
+
server.tool(
|
|
14776
|
+
"list_issues",
|
|
14777
|
+
"List issues from Sideboard Account connections (Linear API or GitHub Issues; Linear\u2192GitHub fallback when Linear is not connected). Pass repoPath from list_workspaces \u2014 GitHub Issues are scoped to that repo. Then create_thread with sourceType=ticket.",
|
|
14778
|
+
{ repoPath: import_zod.z.string() },
|
|
14779
|
+
async ({ repoPath }) => {
|
|
14780
|
+
const root = await resolveRepoRoot(repoPath);
|
|
14781
|
+
const result = await listIssues(root);
|
|
14782
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
14783
|
+
}
|
|
14784
|
+
);
|
|
14785
|
+
server.tool(
|
|
14786
|
+
"list_linear_issues",
|
|
14787
|
+
"Deprecated: prefer list_issues. Lists assigned Linear issues via the chosen agent MCP connector",
|
|
14788
|
+
{
|
|
14789
|
+
agent: import_zod.z.enum(["claude", "codex", "opencode"]),
|
|
14790
|
+
repoPath: import_zod.z.string()
|
|
14791
|
+
},
|
|
14792
|
+
async ({ agent, repoPath }) => {
|
|
14793
|
+
const issues = await listLinearIssues(agent, repoPath);
|
|
14794
|
+
return { content: [{ type: "text", text: JSON.stringify(issues, null, 2) }] };
|
|
14795
|
+
}
|
|
14796
|
+
);
|
|
14797
|
+
}
|
|
14434
14798
|
const transport = new import_stdio.StdioServerTransport();
|
|
14435
14799
|
await server.connect(transport);
|
|
14436
14800
|
}
|
|
14437
14801
|
|
|
14438
14802
|
// src/index.ts
|
|
14803
|
+
init_profile();
|
|
14439
14804
|
init_config();
|
|
14440
14805
|
|
|
14441
14806
|
// src/brightsy/api.ts
|
|
@@ -14812,6 +15177,7 @@ init_injected_mcp();
|
|
|
14812
15177
|
REVIEW_REQUEST_PREFILL,
|
|
14813
15178
|
SIDEBOARD_FORCE_STOP,
|
|
14814
15179
|
SIDEBOARD_MCP_ALLOWED_TOOLS,
|
|
15180
|
+
SIDEBOARD_MCP_PROFILE_ENV,
|
|
14815
15181
|
THINKING_EFFORTS,
|
|
14816
15182
|
addPrStackLayer,
|
|
14817
15183
|
addStackLayerFromThread,
|
|
@@ -14843,6 +15209,7 @@ init_injected_mcp();
|
|
|
14843
15209
|
brightsyCloudConnectAgent,
|
|
14844
15210
|
brightsyCloudConnectEnabled,
|
|
14845
15211
|
brightsyConfigPath,
|
|
15212
|
+
brightsyInjectWorktreeMcpEnabled,
|
|
14846
15213
|
brightsyMcpAllowedTools,
|
|
14847
15214
|
brightsyMcpServerName,
|
|
14848
15215
|
buildCachedUserContent,
|
|
@@ -14894,7 +15261,9 @@ init_injected_mcp();
|
|
|
14894
15261
|
detectLocalMergeConflicts,
|
|
14895
15262
|
disconnectBrightsyTeam,
|
|
14896
15263
|
discoverSkills,
|
|
15264
|
+
dropCachedPrefixOnResume,
|
|
14897
15265
|
encodeBrightsyTarget,
|
|
15266
|
+
enrichPathWithNpmGlobalBin,
|
|
14898
15267
|
enrichWorkspacesWithGithub,
|
|
14899
15268
|
ensureAgentPath,
|
|
14900
15269
|
ensureCloudCoordinator,
|
|
@@ -14932,6 +15301,7 @@ init_injected_mcp();
|
|
|
14932
15301
|
formatTranscriptMarkdown,
|
|
14933
15302
|
formatWorkspaceInventory,
|
|
14934
15303
|
formatWorktreeDirective,
|
|
15304
|
+
formatWorktreeReminder,
|
|
14935
15305
|
getAdapter,
|
|
14936
15306
|
getAgentSetupInfo,
|
|
14937
15307
|
getBrightsySession,
|
|
@@ -15058,7 +15428,10 @@ init_injected_mcp();
|
|
|
15058
15428
|
pastedTextStats,
|
|
15059
15429
|
permissionMode,
|
|
15060
15430
|
planFileAbs,
|
|
15431
|
+
posixShellSingleQuote,
|
|
15432
|
+
prepareTerminalCommand,
|
|
15061
15433
|
previewLand,
|
|
15434
|
+
promptMentionsBrightsy,
|
|
15062
15435
|
pushBranch,
|
|
15063
15436
|
readExistingReviewRequestFile,
|
|
15064
15437
|
readPlanFile,
|
|
@@ -15074,7 +15447,9 @@ init_injected_mcp();
|
|
|
15074
15447
|
requestReview,
|
|
15075
15448
|
requireAgent,
|
|
15076
15449
|
resetGhStackDetectCache,
|
|
15450
|
+
resolveAgentExecutable,
|
|
15077
15451
|
resolveClaudeExecutable,
|
|
15452
|
+
resolveCommandBinarySync,
|
|
15078
15453
|
resolveConductorCursorAgentId,
|
|
15079
15454
|
resolveCursorModelId,
|
|
15080
15455
|
resolveDefaultBranch,
|
|
@@ -15083,6 +15458,7 @@ init_injected_mcp();
|
|
|
15083
15458
|
resolveFilesToCopy,
|
|
15084
15459
|
resolveGhAuthToken,
|
|
15085
15460
|
resolveGithubRepoSlug,
|
|
15461
|
+
resolveLoginCommand,
|
|
15086
15462
|
resolveNewThreadOptions,
|
|
15087
15463
|
resolvePlanMarkdown,
|
|
15088
15464
|
resolvePrSelector,
|
|
@@ -15104,9 +15480,11 @@ init_injected_mcp();
|
|
|
15104
15480
|
settingsSourceLabel,
|
|
15105
15481
|
shouldAttachPastedText,
|
|
15106
15482
|
shouldCompactContext,
|
|
15483
|
+
shouldInjectBrightsyMcp,
|
|
15107
15484
|
shouldRefreshReviewRequestTemplate,
|
|
15108
15485
|
shouldRunWorktreeCleanup,
|
|
15109
15486
|
sideboardHomeDir,
|
|
15487
|
+
sideboardMcpProfile,
|
|
15110
15488
|
sideboardReposDir,
|
|
15111
15489
|
sideboardWorkspacesDir,
|
|
15112
15490
|
slugify,
|
|
@@ -15134,6 +15512,7 @@ init_injected_mcp();
|
|
|
15134
15512
|
threadDisplayLabel,
|
|
15135
15513
|
threadFilePath,
|
|
15136
15514
|
threadLockPath,
|
|
15515
|
+
threadRequestsBrightsyMcp,
|
|
15137
15516
|
threadsDir,
|
|
15138
15517
|
threadsSharingWorktree,
|
|
15139
15518
|
toolDescription,
|
|
@@ -15141,14 +15520,18 @@ init_injected_mcp();
|
|
|
15141
15520
|
toolFilePath,
|
|
15142
15521
|
totalTokens,
|
|
15143
15522
|
updateAdvancedSettings,
|
|
15523
|
+
updateAgentExecutable,
|
|
15144
15524
|
updateAppEnvironment,
|
|
15145
15525
|
updateBrightsySettings,
|
|
15146
15526
|
updateClaudeSettings,
|
|
15527
|
+
updateCodexSettings,
|
|
15147
15528
|
updateDefaultsSettings,
|
|
15148
15529
|
updateIntegrationsSettings,
|
|
15530
|
+
updateOpencodeSettings,
|
|
15149
15531
|
updateThread,
|
|
15150
15532
|
validateLinearApiKey,
|
|
15151
15533
|
withAgentInstructions,
|
|
15534
|
+
withExportedPath,
|
|
15152
15535
|
withThreadLock,
|
|
15153
15536
|
workspaceSettingsSourceLabel,
|
|
15154
15537
|
worktreeCleanupSettings,
|