@sideboard-ai/core 0.1.62 → 0.1.67
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-KF3J3C53.js → agents-OTBZVTZO.js} +27 -7
- package/dist/{agents-QLSFIQAO.js → agents-TS3EI2YI.js} +27 -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-UGXSSBFJ.js → chunk-4BUCGNZS.js} +1 -1
- package/dist/chunk-4UIYN56C.js +173 -0
- package/dist/{chunk-NVU7EC2E.js → chunk-57WWNMFP.js} +2 -2
- package/dist/{chunk-A6FOKNOU.js → chunk-5HTTCYWA.js} +2 -2
- package/dist/{chunk-DXTGDXO2.js → chunk-7ZOQY4A7.js} +31 -6
- package/dist/{chunk-ZF5YJCXO.js → chunk-B4PRRKMA.js} +284 -93
- package/dist/{chunk-DDN3UF4R.js → chunk-BPOTVI5J.js} +115 -3
- package/dist/{chunk-MBAL5FE6.js → chunk-DB3I75FI.js} +4 -4
- package/dist/chunk-FGDJOJ2L.js +176 -0
- package/dist/{chunk-2FEA4LDA.js → chunk-JWZNK3CQ.js} +31 -6
- package/dist/{chunk-2MCNURQV.js → chunk-K7LM4CLD.js} +279 -93
- package/dist/{chunk-3KKNTHUC.js → chunk-LW5CMQGZ.js} +1 -1
- package/dist/{chunk-JB2H7E7V.js → chunk-M5V4QIWF.js} +1 -1
- package/dist/{chunk-6CUJQKTJ.js → chunk-MHR4OGZ4.js} +115 -3
- package/dist/{chunk-46KMKHSD.js → chunk-WAFIF22N.js} +2 -2
- package/dist/{chunk-27MAWNKY.js → chunk-ZRFAZVGL.js} +2 -2
- package/dist/{connected-teams-MKIYKOYA.js → connected-teams-OMDHTL6A.js} +2 -2
- package/dist/{connected-teams-RSL4VB3X.js → connected-teams-RUNMOCG5.js} +2 -2
- package/dist/{coordinator-prompt-N2R6FGZK.js → coordinator-prompt-3BSMKZL4.js} +4 -4
- package/dist/{coordinator-prompt-LKG3SHMI.js → coordinator-prompt-6HMTOX4G.js} +4 -4
- package/dist/{global-workspace-LALWQWRJ.js → global-workspace-QS7A23CB.js} +5 -6
- package/dist/{global-workspace-YOAUQCMA.js → global-workspace-YZ2NJVLL.js} +5 -6
- package/dist/index.cjs +1345 -933
- package/dist/index.d.cts +96 -1
- package/dist/index.d.ts +96 -1
- package/dist/index.js +750 -715
- package/dist/mcp/run-stdio.cjs +1293 -977
- package/dist/mcp/run-stdio.js +691 -748
- package/dist/{run-GPSVV5OH.js → run-JLD2Y52J.js} +1 -1
- package/dist/{run-HZTBWGQR.js → run-Y2MI3EVV.js} +1 -1
- package/dist/{workspaces-E75POJXP.js → workspaces-AIUYUXB7.js} +6 -7
- package/dist/{workspaces-VCAIHVIE.js → workspaces-EBFW7I7S.js} +6 -7
- package/dist/{worktree-MV4WRW6G.js → worktree-7NBPIVFZ.js} +2 -2
- package/dist/{worktree-LZEGVQSN.js → worktree-WMDJW2BL.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-73AT5K4A.js +0 -104
- package/dist/chunk-GI7E5733.js +0 -30
- package/dist/chunk-RIWUU7FO.js +0 -107
- 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,37 @@ 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
|
+
}
|
|
2166
|
+
function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os4.homedir)()) {
|
|
2167
|
+
return (0, import_node_path5.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
|
|
2168
|
+
}
|
|
2169
|
+
function isConductorBundledCli(filePath) {
|
|
2170
|
+
const p = (filePath ?? "").replace(/\\/g, "/");
|
|
2171
|
+
return p.includes("/com.conductor.app/bin/") || p.endsWith("/com.conductor.app/bin");
|
|
2172
|
+
}
|
|
2044
2173
|
function ensureAgentPath(env = process.env) {
|
|
2045
2174
|
const home = env.HOME || env.USERPROFILE || (0, import_node_os4.homedir)();
|
|
2046
2175
|
const current = env.PATH ?? "";
|
|
2047
2176
|
const parts = current.split(import_node_path5.delimiter).filter(Boolean);
|
|
2048
2177
|
const seen = new Set(parts);
|
|
2049
2178
|
const extras = [
|
|
2050
|
-
...EXTRA_BIN_DIRS.map((rel) =>
|
|
2179
|
+
...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path5.join)(home, rel)),
|
|
2051
2180
|
"/opt/homebrew/bin",
|
|
2052
|
-
"/usr/local/bin"
|
|
2181
|
+
"/usr/local/bin",
|
|
2182
|
+
// Keep after Homebrew/npm so a user-installed CLI still wins.
|
|
2183
|
+
conductorBundledBinDir(home)
|
|
2053
2184
|
];
|
|
2054
2185
|
for (const dir of extras.reverse()) {
|
|
2055
|
-
if (!dir || seen.has(dir)) continue;
|
|
2186
|
+
if (!dir || seen.has(dir) || !(0, import_node_fs5.existsSync)(dir)) continue;
|
|
2056
2187
|
parts.unshift(dir);
|
|
2057
2188
|
seen.add(dir);
|
|
2058
2189
|
}
|
|
@@ -2060,10 +2191,50 @@ function ensureAgentPath(env = process.env) {
|
|
|
2060
2191
|
env.PATH = next;
|
|
2061
2192
|
return next;
|
|
2062
2193
|
}
|
|
2063
|
-
|
|
2194
|
+
function enrichPathWithNpmGlobalBin(env = process.env) {
|
|
2195
|
+
ensureAgentPath(env);
|
|
2196
|
+
try {
|
|
2197
|
+
const prefix = (0, import_node_child_process.execFileSync)("npm", ["prefix", "-g"], {
|
|
2198
|
+
encoding: "utf8",
|
|
2199
|
+
env: { ...process.env, ...env },
|
|
2200
|
+
timeout: 8e3,
|
|
2201
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2202
|
+
}).trim().split(/\r?\n/).find(Boolean);
|
|
2203
|
+
if (prefix) {
|
|
2204
|
+
const binDir = process.platform === "win32" ? prefix : (0, import_node_path5.join)(prefix, "bin");
|
|
2205
|
+
prependPathDir(env, binDir);
|
|
2206
|
+
}
|
|
2207
|
+
} catch {
|
|
2208
|
+
}
|
|
2209
|
+
return env.PATH ?? "";
|
|
2210
|
+
}
|
|
2211
|
+
function posixShellSingleQuote(value) {
|
|
2212
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
2213
|
+
}
|
|
2214
|
+
function resolveCommandBinarySync(command, whichPath) {
|
|
2215
|
+
const trimmed = command.trim();
|
|
2216
|
+
if (!trimmed) return trimmed;
|
|
2217
|
+
const match = /^(\S+)(\s[\s\S]*)?$/.exec(trimmed);
|
|
2218
|
+
if (!match) return trimmed;
|
|
2219
|
+
const bin = match[1];
|
|
2220
|
+
const rest = match[2] ?? "";
|
|
2221
|
+
if (bin.includes("/") || bin.includes("\\")) return trimmed;
|
|
2222
|
+
const abs = whichPath?.trim().split(/\r?\n/).find(Boolean);
|
|
2223
|
+
if (!abs) return trimmed;
|
|
2224
|
+
return `${abs}${rest}`;
|
|
2225
|
+
}
|
|
2226
|
+
function withExportedPath(command, pathValue) {
|
|
2227
|
+
const trimmed = command.trim();
|
|
2228
|
+
if (!trimmed) return trimmed;
|
|
2229
|
+
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
2230
|
+
return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
|
|
2231
|
+
}
|
|
2232
|
+
var import_node_fs5, import_node_child_process, import_node_os4, import_node_path5, EXTRA_BIN_DIRS;
|
|
2064
2233
|
var init_path = __esm({
|
|
2065
2234
|
"src/agents/path.ts"() {
|
|
2066
2235
|
"use strict";
|
|
2236
|
+
import_node_fs5 = require("fs");
|
|
2237
|
+
import_node_child_process = require("child_process");
|
|
2067
2238
|
import_node_os4 = require("os");
|
|
2068
2239
|
import_node_path5 = require("path");
|
|
2069
2240
|
EXTRA_BIN_DIRS = [
|
|
@@ -2071,6 +2242,10 @@ var init_path = __esm({
|
|
|
2071
2242
|
".cargo/bin",
|
|
2072
2243
|
".nvm/current/bin",
|
|
2073
2244
|
".asdf/shims",
|
|
2245
|
+
".volta/bin",
|
|
2246
|
+
".npm-global/bin",
|
|
2247
|
+
// fnm default alias (common when shell init is skipped)
|
|
2248
|
+
".local/share/fnm/aliases/default/bin",
|
|
2074
2249
|
// pnpm / npm global bins (where `@brightsy/cli` typically lands)
|
|
2075
2250
|
"Library/pnpm",
|
|
2076
2251
|
".pnpm"
|
|
@@ -3158,7 +3333,7 @@ function isLocalPrFetchBranch(ref) {
|
|
|
3158
3333
|
async function createThreadWorktree(opts) {
|
|
3159
3334
|
let branchName = `thread/${opts.slug}`;
|
|
3160
3335
|
const worktreePath = (0, import_node_path6.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
3161
|
-
if ((0,
|
|
3336
|
+
if ((0, import_node_fs6.existsSync)(worktreePath)) {
|
|
3162
3337
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
3163
3338
|
}
|
|
3164
3339
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -3228,7 +3403,7 @@ async function createExistingBranchWorktree(opts) {
|
|
|
3228
3403
|
const branchName = opts.branchName.trim();
|
|
3229
3404
|
if (!branchName) throw new Error("branch name required");
|
|
3230
3405
|
const worktreePath = (0, import_node_path6.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
3231
|
-
if ((0,
|
|
3406
|
+
if ((0, import_node_fs6.existsSync)(worktreePath)) {
|
|
3232
3407
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
3233
3408
|
}
|
|
3234
3409
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -3489,9 +3664,9 @@ function sameRepoPath(a, b) {
|
|
|
3489
3664
|
}
|
|
3490
3665
|
function listLocalThreadBranchSlugs(repoPath) {
|
|
3491
3666
|
const refsDir = (0, import_node_path6.join)(repoPath, ".git", "refs", "heads", "thread");
|
|
3492
|
-
if (!(0,
|
|
3667
|
+
if (!(0, import_node_fs6.existsSync)(refsDir)) return [];
|
|
3493
3668
|
try {
|
|
3494
|
-
return (0,
|
|
3669
|
+
return (0, import_node_fs6.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
|
|
3495
3670
|
} catch {
|
|
3496
3671
|
return [];
|
|
3497
3672
|
}
|
|
@@ -3499,8 +3674,8 @@ function listLocalThreadBranchSlugs(repoPath) {
|
|
|
3499
3674
|
function collectTakenTeamSlugs(repoPath) {
|
|
3500
3675
|
const taken = /* @__PURE__ */ new Set();
|
|
3501
3676
|
const root = worktreesRoot(repoPath);
|
|
3502
|
-
if ((0,
|
|
3503
|
-
for (const entry of (0,
|
|
3677
|
+
if ((0, import_node_fs6.existsSync)(root)) {
|
|
3678
|
+
for (const entry of (0, import_node_fs6.readdirSync)(root, { withFileTypes: true })) {
|
|
3504
3679
|
if (entry.isDirectory() && entry.name !== ".DS_Store") {
|
|
3505
3680
|
taken.add(normalizeTakenSlug(entry.name));
|
|
3506
3681
|
}
|
|
@@ -3522,16 +3697,16 @@ function allocateTeamSlug(repoPath) {
|
|
|
3522
3697
|
for (let attempt = 0; attempt < 32; attempt++) {
|
|
3523
3698
|
const team = allocateTeamName(taken);
|
|
3524
3699
|
const path = (0, import_node_path6.join)(worktreesRoot(repoPath), team.slug);
|
|
3525
|
-
if (!(0,
|
|
3700
|
+
if (!(0, import_node_fs6.existsSync)(path)) return team;
|
|
3526
3701
|
taken.add(team.slug);
|
|
3527
3702
|
}
|
|
3528
3703
|
throw new Error("No available soccer team worktree directories left");
|
|
3529
3704
|
}
|
|
3530
|
-
var
|
|
3705
|
+
var import_node_fs6, import_node_path6;
|
|
3531
3706
|
var init_worktree = __esm({
|
|
3532
3707
|
"src/git/worktree.ts"() {
|
|
3533
3708
|
"use strict";
|
|
3534
|
-
|
|
3709
|
+
import_node_fs6 = require("fs");
|
|
3535
3710
|
import_node_path6 = require("path");
|
|
3536
3711
|
init_paths();
|
|
3537
3712
|
init_thread_store();
|
|
@@ -3611,7 +3786,7 @@ function coordinatorTurnReminder(opts) {
|
|
|
3611
3786
|
function ensureGlobalCoordinatorCwd(opts) {
|
|
3612
3787
|
const dir = globalAgentCwd();
|
|
3613
3788
|
try {
|
|
3614
|
-
(0,
|
|
3789
|
+
(0, import_node_fs7.mkdirSync)(dir, { recursive: true });
|
|
3615
3790
|
} catch {
|
|
3616
3791
|
return dir;
|
|
3617
3792
|
}
|
|
@@ -3619,7 +3794,7 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
3619
3794
|
let orchId = opts?.orchestratorThreadId?.trim() || "";
|
|
3620
3795
|
if (!orchId) {
|
|
3621
3796
|
try {
|
|
3622
|
-
const existing = (0,
|
|
3797
|
+
const existing = (0, import_node_fs7.readFileSync)((0, import_node_path7.join)(dir, "AGENTS.md"), "utf8");
|
|
3623
3798
|
const m = existing.match(
|
|
3624
3799
|
/YOUR orchestration thread id is `([0-9a-f-]{36})`/i
|
|
3625
3800
|
);
|
|
@@ -3661,9 +3836,9 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
3661
3836
|
"Always ask worktree agents to open draft PRs (`send_to_thread` + `gh pr create --draft -R <origin>`); never open PRs from the orchestrator."
|
|
3662
3837
|
].join("\n");
|
|
3663
3838
|
try {
|
|
3664
|
-
(0,
|
|
3839
|
+
(0, import_node_fs7.writeFileSync)((0, import_node_path7.join)(dir, "CLAUDE.md"), `${body}
|
|
3665
3840
|
`, "utf8");
|
|
3666
|
-
(0,
|
|
3841
|
+
(0, import_node_fs7.writeFileSync)((0, import_node_path7.join)(dir, "AGENTS.md"), `${body}
|
|
3667
3842
|
`, "utf8");
|
|
3668
3843
|
} catch {
|
|
3669
3844
|
}
|
|
@@ -3696,11 +3871,11 @@ function coordinatorSystemPrompt(opts) {
|
|
|
3696
3871
|
formatWorkspaceInventory(opts.workspaces)
|
|
3697
3872
|
].join("\n");
|
|
3698
3873
|
}
|
|
3699
|
-
var
|
|
3874
|
+
var import_node_fs7, import_node_path7, COORDINATOR_TOOL_PLAYBOOK;
|
|
3700
3875
|
var init_coordinator_prompt = __esm({
|
|
3701
3876
|
"src/orchestrator/coordinator-prompt.ts"() {
|
|
3702
3877
|
"use strict";
|
|
3703
|
-
|
|
3878
|
+
import_node_fs7 = require("fs");
|
|
3704
3879
|
import_node_path7 = require("path");
|
|
3705
3880
|
init_worktree();
|
|
3706
3881
|
init_app_settings();
|
|
@@ -3937,31 +4112,31 @@ function removedWorkspacesFile() {
|
|
|
3937
4112
|
}
|
|
3938
4113
|
function readAll() {
|
|
3939
4114
|
const path = workspacesFile();
|
|
3940
|
-
if (!(0,
|
|
4115
|
+
if (!(0, import_node_fs8.existsSync)(path)) return [];
|
|
3941
4116
|
try {
|
|
3942
|
-
const raw = JSON.parse((0,
|
|
4117
|
+
const raw = JSON.parse((0, import_node_fs8.readFileSync)(path, "utf8"));
|
|
3943
4118
|
return Array.isArray(raw) ? raw : [];
|
|
3944
4119
|
} catch {
|
|
3945
4120
|
return [];
|
|
3946
4121
|
}
|
|
3947
4122
|
}
|
|
3948
4123
|
function writeAll(list) {
|
|
3949
|
-
(0,
|
|
3950
|
-
(0,
|
|
4124
|
+
(0, import_node_fs8.mkdirSync)(appDataDir(), { recursive: true });
|
|
4125
|
+
(0, import_node_fs8.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
|
|
3951
4126
|
}
|
|
3952
4127
|
function readRemoved() {
|
|
3953
4128
|
const path = removedWorkspacesFile();
|
|
3954
|
-
if (!(0,
|
|
4129
|
+
if (!(0, import_node_fs8.existsSync)(path)) return /* @__PURE__ */ new Set();
|
|
3955
4130
|
try {
|
|
3956
|
-
const raw = JSON.parse((0,
|
|
4131
|
+
const raw = JSON.parse((0, import_node_fs8.readFileSync)(path, "utf8"));
|
|
3957
4132
|
return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
|
|
3958
4133
|
} catch {
|
|
3959
4134
|
return /* @__PURE__ */ new Set();
|
|
3960
4135
|
}
|
|
3961
4136
|
}
|
|
3962
4137
|
function writeRemoved(paths) {
|
|
3963
|
-
(0,
|
|
3964
|
-
(0,
|
|
4138
|
+
(0, import_node_fs8.mkdirSync)(appDataDir(), { recursive: true });
|
|
4139
|
+
(0, import_node_fs8.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
|
|
3965
4140
|
}
|
|
3966
4141
|
function rememberRemoved(repoPath) {
|
|
3967
4142
|
const next = readRemoved();
|
|
@@ -3984,7 +4159,7 @@ function listWorkspaces() {
|
|
|
3984
4159
|
async function addWorkspace(repoPath) {
|
|
3985
4160
|
const root = await resolveRepoRoot(repoPath);
|
|
3986
4161
|
if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
|
|
3987
|
-
if (!(0,
|
|
4162
|
+
if (!(0, import_node_fs8.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
|
|
3988
4163
|
forgetRemoved(root);
|
|
3989
4164
|
await ensureGhPreferOrigin(root);
|
|
3990
4165
|
const current = readAll();
|
|
@@ -4014,7 +4189,7 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
4014
4189
|
if (!path || path === "/" || isGlobalRepoPath(path) || byPath.has(path) || removed.has(path)) {
|
|
4015
4190
|
continue;
|
|
4016
4191
|
}
|
|
4017
|
-
if (!(0,
|
|
4192
|
+
if (!(0, import_node_fs8.existsSync)(path)) continue;
|
|
4018
4193
|
const ws = {
|
|
4019
4194
|
path,
|
|
4020
4195
|
name: (0, import_node_path8.basename)(path),
|
|
@@ -4027,11 +4202,11 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
4027
4202
|
if (dirty) writeAll(next);
|
|
4028
4203
|
return next.sort((a, b) => a.name.localeCompare(b.name));
|
|
4029
4204
|
}
|
|
4030
|
-
var
|
|
4205
|
+
var import_node_fs8, import_node_path8;
|
|
4031
4206
|
var init_workspaces = __esm({
|
|
4032
4207
|
"src/store/workspaces.ts"() {
|
|
4033
4208
|
"use strict";
|
|
4034
|
-
|
|
4209
|
+
import_node_fs8 = require("fs");
|
|
4035
4210
|
import_node_path8 = require("path");
|
|
4036
4211
|
init_paths();
|
|
4037
4212
|
init_global_workspace();
|
|
@@ -4045,26 +4220,26 @@ function brightsyConfigPath() {
|
|
|
4045
4220
|
}
|
|
4046
4221
|
function loadBrightsyConfig() {
|
|
4047
4222
|
const path = brightsyConfigPath();
|
|
4048
|
-
if (!(0,
|
|
4223
|
+
if (!(0, import_node_fs9.existsSync)(path)) {
|
|
4049
4224
|
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
4050
4225
|
}
|
|
4051
|
-
const raw = JSON.parse((0,
|
|
4226
|
+
const raw = JSON.parse((0, import_node_fs9.readFileSync)(path, "utf8"));
|
|
4052
4227
|
if (!raw.access_token || !raw.account_id) {
|
|
4053
4228
|
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
4054
4229
|
}
|
|
4055
4230
|
return raw;
|
|
4056
4231
|
}
|
|
4057
4232
|
function saveBrightsyConfig(cfg) {
|
|
4058
|
-
(0,
|
|
4233
|
+
(0, import_node_fs9.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
4059
4234
|
`, {
|
|
4060
4235
|
mode: 384
|
|
4061
4236
|
});
|
|
4062
4237
|
}
|
|
4063
|
-
var
|
|
4238
|
+
var import_node_fs9, import_node_os5, import_node_path9;
|
|
4064
4239
|
var init_config = __esm({
|
|
4065
4240
|
"src/brightsy/config.ts"() {
|
|
4066
4241
|
"use strict";
|
|
4067
|
-
|
|
4242
|
+
import_node_fs9 = require("fs");
|
|
4068
4243
|
import_node_os5 = require("os");
|
|
4069
4244
|
import_node_path9 = require("path");
|
|
4070
4245
|
}
|
|
@@ -4173,18 +4348,18 @@ function storePath() {
|
|
|
4173
4348
|
}
|
|
4174
4349
|
function readStore() {
|
|
4175
4350
|
const path = storePath();
|
|
4176
|
-
if (!(0,
|
|
4351
|
+
if (!(0, import_node_fs10.existsSync)(path)) return [];
|
|
4177
4352
|
try {
|
|
4178
|
-
const parsed = JSON.parse((0,
|
|
4353
|
+
const parsed = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf8"));
|
|
4179
4354
|
return Array.isArray(parsed.teams) ? parsed.teams : [];
|
|
4180
4355
|
} catch {
|
|
4181
4356
|
return [];
|
|
4182
4357
|
}
|
|
4183
4358
|
}
|
|
4184
4359
|
function writeStore(teams) {
|
|
4185
|
-
(0,
|
|
4360
|
+
(0, import_node_fs10.mkdirSync)(appDataDir(), { recursive: true });
|
|
4186
4361
|
const path = storePath();
|
|
4187
|
-
(0,
|
|
4362
|
+
(0, import_node_fs10.writeFileSync)(path, `${JSON.stringify({ teams }, null, 2)}
|
|
4188
4363
|
`, {
|
|
4189
4364
|
mode: 384
|
|
4190
4365
|
});
|
|
@@ -4346,11 +4521,11 @@ function brightsyMcpServerName(slug) {
|
|
|
4346
4521
|
const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
|
|
4347
4522
|
return `brightsy_${cleaned || "team"}`;
|
|
4348
4523
|
}
|
|
4349
|
-
var
|
|
4524
|
+
var import_node_fs10, import_node_path10;
|
|
4350
4525
|
var init_connected_teams = __esm({
|
|
4351
4526
|
"src/brightsy/connected-teams.ts"() {
|
|
4352
4527
|
"use strict";
|
|
4353
|
-
|
|
4528
|
+
import_node_fs10 = require("fs");
|
|
4354
4529
|
import_node_path10 = require("path");
|
|
4355
4530
|
init_paths();
|
|
4356
4531
|
init_accounts();
|
|
@@ -4525,6 +4700,11 @@ function normalizeTurnInput(input) {
|
|
|
4525
4700
|
if (typeof input === "string") return { prompt: input };
|
|
4526
4701
|
return { prompt: input.prompt, cachedPrefix: input.cachedPrefix?.trim() || void 0 };
|
|
4527
4702
|
}
|
|
4703
|
+
function dropCachedPrefixOnResume(input, sessionId) {
|
|
4704
|
+
const turn = normalizeTurnInput(input);
|
|
4705
|
+
if (sessionId) return { prompt: turn.prompt };
|
|
4706
|
+
return turn;
|
|
4707
|
+
}
|
|
4528
4708
|
function flattenTurnInput(input) {
|
|
4529
4709
|
const { cachedPrefix, prompt } = normalizeTurnInput(input);
|
|
4530
4710
|
if (!cachedPrefix) return prompt;
|
|
@@ -4713,9 +4893,13 @@ async function fetchTeamChatTargets(team) {
|
|
|
4713
4893
|
};
|
|
4714
4894
|
}
|
|
4715
4895
|
async function listBrightsyChatTargetsViaCli() {
|
|
4716
|
-
const listed = await run(
|
|
4717
|
-
|
|
4718
|
-
|
|
4896
|
+
const listed = await run(
|
|
4897
|
+
resolveAgentExecutable("brightsy"),
|
|
4898
|
+
["chat", "--list-targets", "--json"],
|
|
4899
|
+
{
|
|
4900
|
+
reject: false
|
|
4901
|
+
}
|
|
4902
|
+
);
|
|
4719
4903
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
4720
4904
|
throw new Error(
|
|
4721
4905
|
listed.stderr.trim() || "Failed to list Brightsy chat targets \u2014 is `brightsy` installed and logged in?"
|
|
@@ -4799,13 +4983,15 @@ async function syncCliForTarget(accountId) {
|
|
|
4799
4983
|
}
|
|
4800
4984
|
applyConnectedTeamToCli(team);
|
|
4801
4985
|
}
|
|
4802
|
-
var brightsyAdapter;
|
|
4986
|
+
var import_node_fs11, brightsyAdapter;
|
|
4803
4987
|
var init_brightsy = __esm({
|
|
4804
4988
|
"src/agents/brightsy.ts"() {
|
|
4805
4989
|
"use strict";
|
|
4990
|
+
import_node_fs11 = require("fs");
|
|
4806
4991
|
init_run();
|
|
4807
4992
|
init_connected_teams();
|
|
4808
4993
|
init_config();
|
|
4994
|
+
init_app_settings();
|
|
4809
4995
|
init_brightsy_targets();
|
|
4810
4996
|
init_error_detail();
|
|
4811
4997
|
init_turn_input();
|
|
@@ -4813,18 +4999,32 @@ var init_brightsy = __esm({
|
|
|
4813
4999
|
brightsyAdapter = {
|
|
4814
5000
|
kind: "brightsy",
|
|
4815
5001
|
async detect() {
|
|
4816
|
-
const
|
|
4817
|
-
if (
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
5002
|
+
const brightsy = resolveAgentExecutable("brightsy");
|
|
5003
|
+
if (brightsy !== "brightsy") {
|
|
5004
|
+
if (!(0, import_node_fs11.existsSync)(brightsy)) {
|
|
5005
|
+
return {
|
|
5006
|
+
agent: "brightsy",
|
|
5007
|
+
installed: false,
|
|
5008
|
+
authenticated: false,
|
|
5009
|
+
linearMcp: false,
|
|
5010
|
+
warnings: [],
|
|
5011
|
+
reason: `Brightsy executable not found: ${brightsy}`
|
|
5012
|
+
};
|
|
5013
|
+
}
|
|
5014
|
+
} else {
|
|
5015
|
+
const which = await run("which", ["brightsy"], { reject: false });
|
|
5016
|
+
if (which.exitCode !== 0) {
|
|
5017
|
+
return {
|
|
5018
|
+
agent: "brightsy",
|
|
5019
|
+
installed: false,
|
|
5020
|
+
authenticated: false,
|
|
5021
|
+
linearMcp: false,
|
|
5022
|
+
warnings: [],
|
|
5023
|
+
reason: "brightsy CLI not found on PATH \u2014 npm i -g @brightsy/cli"
|
|
5024
|
+
};
|
|
5025
|
+
}
|
|
4826
5026
|
}
|
|
4827
|
-
const who = await run(
|
|
5027
|
+
const who = await run(brightsy, ["whoami"], { reject: false });
|
|
4828
5028
|
const authenticated = who.exitCode === 0 && /logged in as/i.test(who.stdout);
|
|
4829
5029
|
return {
|
|
4830
5030
|
agent: "brightsy",
|
|
@@ -4849,7 +5049,7 @@ var init_brightsy = __esm({
|
|
|
4849
5049
|
target.id
|
|
4850
5050
|
];
|
|
4851
5051
|
return {
|
|
4852
|
-
file: "brightsy",
|
|
5052
|
+
file: resolveAgentExecutable("brightsy"),
|
|
4853
5053
|
args,
|
|
4854
5054
|
cwd: thread.worktreePath,
|
|
4855
5055
|
// Piped stdin becomes the message body (avoids ARG_MAX for long seeds).
|
|
@@ -4866,7 +5066,11 @@ var init_brightsy = __esm({
|
|
|
4866
5066
|
const target = decodeBrightsyTarget(thread.model);
|
|
4867
5067
|
await syncCliForTarget(target.accountId);
|
|
4868
5068
|
const args = target.type === "model" ? ["chat", "--model", target.id] : ["chat", "--agent", target.id];
|
|
4869
|
-
return {
|
|
5069
|
+
return {
|
|
5070
|
+
file: resolveAgentExecutable("brightsy"),
|
|
5071
|
+
args,
|
|
5072
|
+
cwd: thread.worktreePath
|
|
5073
|
+
};
|
|
4870
5074
|
}
|
|
4871
5075
|
};
|
|
4872
5076
|
}
|
|
@@ -4918,6 +5122,18 @@ var init_claude_mcp = __esm({
|
|
|
4918
5122
|
}
|
|
4919
5123
|
});
|
|
4920
5124
|
|
|
5125
|
+
// src/mcp/profile.ts
|
|
5126
|
+
function sideboardMcpProfile(env = process.env) {
|
|
5127
|
+
return env[SIDEBOARD_MCP_PROFILE_ENV]?.trim().toLowerCase() === "worktree" ? "worktree" : "orchestration";
|
|
5128
|
+
}
|
|
5129
|
+
var SIDEBOARD_MCP_PROFILE_ENV;
|
|
5130
|
+
var init_profile = __esm({
|
|
5131
|
+
"src/mcp/profile.ts"() {
|
|
5132
|
+
"use strict";
|
|
5133
|
+
SIDEBOARD_MCP_PROFILE_ENV = "SIDEBOARD_MCP_PROFILE";
|
|
5134
|
+
}
|
|
5135
|
+
});
|
|
5136
|
+
|
|
4921
5137
|
// src/agents/node-launch.ts
|
|
4922
5138
|
function isAsarPath(filePath) {
|
|
4923
5139
|
return /\.asar([/\\]|$)/.test(filePath);
|
|
@@ -4965,6 +5181,38 @@ function isBrightsyConnected() {
|
|
|
4965
5181
|
return false;
|
|
4966
5182
|
}
|
|
4967
5183
|
}
|
|
5184
|
+
function promptMentionsBrightsy(text) {
|
|
5185
|
+
return BRIGHTSY_WORD.test(text ?? "");
|
|
5186
|
+
}
|
|
5187
|
+
function isBrightsyMcpToolName(name) {
|
|
5188
|
+
const n = name.toLowerCase();
|
|
5189
|
+
return n === "brightsy" || n.startsWith("mcp__brightsy") || n.startsWith("brightsy_");
|
|
5190
|
+
}
|
|
5191
|
+
function toolInputUsesBrightsyDatasource(input) {
|
|
5192
|
+
const ds = input?.datasource;
|
|
5193
|
+
return typeof ds === "string" && ds.toLowerCase() === "brightsy";
|
|
5194
|
+
}
|
|
5195
|
+
function messageUsedBrightsyMcp(msg) {
|
|
5196
|
+
if (msg.role === "user" && promptMentionsBrightsy(msg.text)) return true;
|
|
5197
|
+
for (const part of msg.parts ?? []) {
|
|
5198
|
+
if (part.type !== "tool") continue;
|
|
5199
|
+
if (isBrightsyMcpToolName(part.name)) return true;
|
|
5200
|
+
if (/present_(schema|files)$/i.test(part.name) && toolInputUsesBrightsyDatasource(part.input)) {
|
|
5201
|
+
return true;
|
|
5202
|
+
}
|
|
5203
|
+
}
|
|
5204
|
+
return false;
|
|
5205
|
+
}
|
|
5206
|
+
function threadRequestsBrightsyMcp(thread) {
|
|
5207
|
+
return (thread?.messages ?? []).some(messageUsedBrightsyMcp);
|
|
5208
|
+
}
|
|
5209
|
+
function shouldInjectBrightsyMcp(thread, opts) {
|
|
5210
|
+
if (!(opts?.connected ?? isBrightsyConnected())) return false;
|
|
5211
|
+
if (opts?.orchestrator) return true;
|
|
5212
|
+
const alwaysOn = opts?.alwaysOnWorktree ?? Boolean(loadAppSettings().brightsy?.injectWorktreeMcp);
|
|
5213
|
+
if (alwaysOn) return true;
|
|
5214
|
+
return threadRequestsBrightsyMcp(thread);
|
|
5215
|
+
}
|
|
4968
5216
|
function mcpLaunch(cmd, name, env) {
|
|
4969
5217
|
if (cmd === "brightsy-mcp") {
|
|
4970
5218
|
return { name, command: "brightsy-mcp", ...env ? { env } : {} };
|
|
@@ -5010,7 +5258,7 @@ function corePackageDir() {
|
|
|
5010
5258
|
}
|
|
5011
5259
|
function findSideboardMcpJsEntry() {
|
|
5012
5260
|
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
5013
|
-
if (override && (0,
|
|
5261
|
+
if (override && (0, import_node_fs12.existsSync)(override)) return override;
|
|
5014
5262
|
let dir = corePackageDir();
|
|
5015
5263
|
for (let i = 0; i < 10; i++) {
|
|
5016
5264
|
const candidates = [
|
|
@@ -5023,7 +5271,7 @@ function findSideboardMcpJsEntry() {
|
|
|
5023
5271
|
(0, import_node_path11.join)(dir, "cli/dist/index.js")
|
|
5024
5272
|
];
|
|
5025
5273
|
for (const p of candidates) {
|
|
5026
|
-
if ((0,
|
|
5274
|
+
if ((0, import_node_fs12.existsSync)(p)) return p;
|
|
5027
5275
|
}
|
|
5028
5276
|
const parent = (0, import_node_path11.dirname)(dir);
|
|
5029
5277
|
if (parent === dir) break;
|
|
@@ -5054,11 +5302,13 @@ async function buildInjectedMcpServers(opts) {
|
|
|
5054
5302
|
const servers = [];
|
|
5055
5303
|
if (opts.includeSideboard) {
|
|
5056
5304
|
const sideboard = await resolveSideboardMcpServer();
|
|
5305
|
+
const orchId = opts.orchestratorThreadId?.trim();
|
|
5306
|
+
const profile = orchId ? "orchestration" : "worktree";
|
|
5057
5307
|
sideboard.env = {
|
|
5058
5308
|
...sideboard.env ?? {},
|
|
5059
|
-
SIDEBOARD_APP_DATA: appDataDir()
|
|
5309
|
+
SIDEBOARD_APP_DATA: appDataDir(),
|
|
5310
|
+
[SIDEBOARD_MCP_PROFILE_ENV]: profile
|
|
5060
5311
|
};
|
|
5061
|
-
const orchId = opts.orchestratorThreadId?.trim();
|
|
5062
5312
|
if (orchId) {
|
|
5063
5313
|
sideboard.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID = orchId;
|
|
5064
5314
|
}
|
|
@@ -5133,19 +5383,19 @@ function writeMcpServersConfig(servers) {
|
|
|
5133
5383
|
...s.env ? { env: s.env } : {}
|
|
5134
5384
|
};
|
|
5135
5385
|
}
|
|
5136
|
-
const dir = (0,
|
|
5386
|
+
const dir = (0, import_node_fs12.mkdtempSync)((0, import_node_path11.join)((0, import_node_os6.tmpdir)(), "sideboard-mcp-"));
|
|
5137
5387
|
const cfgPath = (0, import_node_path11.join)(dir, "mcp.json");
|
|
5138
|
-
(0,
|
|
5388
|
+
(0, import_node_fs12.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
|
|
5139
5389
|
return cfgPath;
|
|
5140
5390
|
}
|
|
5141
5391
|
async function writeInjectedMcpConfig(opts) {
|
|
5142
5392
|
return writeMcpServersConfig(await buildInjectedMcpServers(opts));
|
|
5143
5393
|
}
|
|
5144
|
-
var
|
|
5394
|
+
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
5395
|
var init_injected_mcp = __esm({
|
|
5146
5396
|
"src/agents/injected-mcp.ts"() {
|
|
5147
5397
|
"use strict";
|
|
5148
|
-
|
|
5398
|
+
import_node_fs12 = require("fs");
|
|
5149
5399
|
import_node_module = require("module");
|
|
5150
5400
|
import_node_os6 = require("os");
|
|
5151
5401
|
import_node_path11 = require("path");
|
|
@@ -5153,6 +5403,8 @@ var init_injected_mcp = __esm({
|
|
|
5153
5403
|
init_run();
|
|
5154
5404
|
init_config();
|
|
5155
5405
|
init_connected_teams();
|
|
5406
|
+
init_profile();
|
|
5407
|
+
init_app_settings();
|
|
5156
5408
|
init_paths();
|
|
5157
5409
|
init_node_launch();
|
|
5158
5410
|
import_meta = {};
|
|
@@ -5172,6 +5424,7 @@ var init_injected_mcp = __esm({
|
|
|
5172
5424
|
"mcp__brightsy__*"
|
|
5173
5425
|
];
|
|
5174
5426
|
brightsyMcpCommandCache = null;
|
|
5427
|
+
BRIGHTSY_WORD = /(?<![a-z0-9_-])brightsy(?![a-z0-9_-])/i;
|
|
5175
5428
|
}
|
|
5176
5429
|
});
|
|
5177
5430
|
|
|
@@ -5326,11 +5579,11 @@ function parseIssuesJson(raw) {
|
|
|
5326
5579
|
}
|
|
5327
5580
|
return [];
|
|
5328
5581
|
}
|
|
5329
|
-
var
|
|
5582
|
+
var import_node_fs13, BASE_ALLOWED_TOOLS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
|
|
5330
5583
|
var init_claude = __esm({
|
|
5331
5584
|
"src/agents/claude.ts"() {
|
|
5332
5585
|
"use strict";
|
|
5333
|
-
|
|
5586
|
+
import_node_fs13 = require("fs");
|
|
5334
5587
|
init_run();
|
|
5335
5588
|
init_app_settings();
|
|
5336
5589
|
init_claude_mcp();
|
|
@@ -5359,7 +5612,7 @@ var init_claude = __esm({
|
|
|
5359
5612
|
async detect() {
|
|
5360
5613
|
const claude = resolveClaudeExecutable();
|
|
5361
5614
|
if (claude !== "claude") {
|
|
5362
|
-
if (!(0,
|
|
5615
|
+
if (!(0, import_node_fs13.existsSync)(claude)) {
|
|
5363
5616
|
return {
|
|
5364
5617
|
agent: "claude",
|
|
5365
5618
|
installed: false,
|
|
@@ -5398,9 +5651,8 @@ var init_claude = __esm({
|
|
|
5398
5651
|
},
|
|
5399
5652
|
async buildTurn(thread, input) {
|
|
5400
5653
|
const claude = resolveClaudeExecutable();
|
|
5401
|
-
const turn = normalizeTurnInput(input);
|
|
5402
5654
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
5403
|
-
const effective = sessionId
|
|
5655
|
+
const effective = dropCachedPrefixOnResume(input, sessionId);
|
|
5404
5656
|
const promptText = flattenTurnInput(effective);
|
|
5405
5657
|
const useStdin = promptText.length > CLAUDE_PROMPT_ARG_MAX;
|
|
5406
5658
|
if (process.env.SIDEBOARD_DEBUG_CLAUDE_TURN === "1") {
|
|
@@ -5413,7 +5665,9 @@ var init_claude = __esm({
|
|
|
5413
5665
|
const isOrchestrator = isOrchestratorThread2(thread);
|
|
5414
5666
|
const injectedServers = await buildInjectedMcpServers({
|
|
5415
5667
|
includeSideboard: true,
|
|
5416
|
-
includeBrightsy:
|
|
5668
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
5669
|
+
orchestrator: isOrchestrator
|
|
5670
|
+
}),
|
|
5417
5671
|
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
5418
5672
|
});
|
|
5419
5673
|
const injectedBrightsyNames = injectedServers.filter((s) => s.name === "brightsy" || s.name.startsWith("brightsy_")).map((s) => s.name);
|
|
@@ -5587,9 +5841,14 @@ async function listCodexModels() {
|
|
|
5587
5841
|
if (cachedCodexModels && now - cachedCodexModels.at < CODEX_MODEL_CACHE_MS) {
|
|
5588
5842
|
return cachedCodexModels.models;
|
|
5589
5843
|
}
|
|
5590
|
-
const
|
|
5591
|
-
if (
|
|
5592
|
-
|
|
5844
|
+
const codex = resolveAgentExecutable("codex");
|
|
5845
|
+
if (codex === "codex") {
|
|
5846
|
+
const which = await run("which", ["codex"], { reject: false });
|
|
5847
|
+
if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
|
|
5848
|
+
} else if (!(0, import_node_fs14.existsSync)(codex)) {
|
|
5849
|
+
return FALLBACK_CODEX_MODELS;
|
|
5850
|
+
}
|
|
5851
|
+
const listed = await run(codex, ["debug", "models"], { reject: false });
|
|
5593
5852
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
5594
5853
|
return cachedCodexModels?.models ?? FALLBACK_CODEX_MODELS;
|
|
5595
5854
|
}
|
|
@@ -5628,8 +5887,8 @@ function codexConfigHasNetworkAccess() {
|
|
|
5628
5887
|
(0, import_node_path12.join)((0, import_node_os7.homedir)(), ".config", "codex", "config.toml")
|
|
5629
5888
|
];
|
|
5630
5889
|
for (const path of candidates) {
|
|
5631
|
-
if (!(0,
|
|
5632
|
-
const text = (0,
|
|
5890
|
+
if (!(0, import_node_fs14.existsSync)(path)) continue;
|
|
5891
|
+
const text = (0, import_node_fs14.readFileSync)(path, "utf8");
|
|
5633
5892
|
if (/network_access\s*=\s*true/.test(text)) return true;
|
|
5634
5893
|
}
|
|
5635
5894
|
return false;
|
|
@@ -5662,21 +5921,23 @@ function asRecord(value) {
|
|
|
5662
5921
|
}
|
|
5663
5922
|
function codexLooksAuthenticated() {
|
|
5664
5923
|
const authPath = (0, import_node_path12.join)((0, import_node_os7.homedir)(), ".codex", "auth.json");
|
|
5665
|
-
if (!(0,
|
|
5924
|
+
if (!(0, import_node_fs14.existsSync)(authPath)) return false;
|
|
5666
5925
|
try {
|
|
5667
|
-
return (0,
|
|
5926
|
+
return (0, import_node_fs14.statSync)(authPath).size > 2;
|
|
5668
5927
|
} catch {
|
|
5669
5928
|
return false;
|
|
5670
5929
|
}
|
|
5671
5930
|
}
|
|
5672
|
-
var
|
|
5931
|
+
var import_node_fs14, import_node_os7, import_node_path12, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
|
|
5673
5932
|
var init_codex = __esm({
|
|
5674
5933
|
"src/agents/codex.ts"() {
|
|
5675
5934
|
"use strict";
|
|
5676
|
-
|
|
5935
|
+
import_node_fs14 = require("fs");
|
|
5677
5936
|
import_node_os7 = require("os");
|
|
5678
5937
|
import_node_path12 = require("path");
|
|
5679
5938
|
init_run();
|
|
5939
|
+
init_app_settings();
|
|
5940
|
+
init_global_workspace();
|
|
5680
5941
|
init_error_detail();
|
|
5681
5942
|
init_injected_mcp();
|
|
5682
5943
|
init_turn_input();
|
|
@@ -5694,16 +5955,30 @@ var init_codex = __esm({
|
|
|
5694
5955
|
codexAdapter = {
|
|
5695
5956
|
kind: "codex",
|
|
5696
5957
|
async detect() {
|
|
5697
|
-
const
|
|
5698
|
-
if (
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5958
|
+
const codex = resolveAgentExecutable("codex");
|
|
5959
|
+
if (codex !== "codex") {
|
|
5960
|
+
if (!(0, import_node_fs14.existsSync)(codex)) {
|
|
5961
|
+
return {
|
|
5962
|
+
agent: "codex",
|
|
5963
|
+
installed: false,
|
|
5964
|
+
authenticated: false,
|
|
5965
|
+
linearMcp: false,
|
|
5966
|
+
warnings: [],
|
|
5967
|
+
reason: `Codex executable not found: ${codex}`
|
|
5968
|
+
};
|
|
5969
|
+
}
|
|
5970
|
+
} else {
|
|
5971
|
+
const which = await run("which", ["codex"], { reject: false, timeoutMs: 3e3 });
|
|
5972
|
+
if (which.exitCode !== 0) {
|
|
5973
|
+
return {
|
|
5974
|
+
agent: "codex",
|
|
5975
|
+
installed: false,
|
|
5976
|
+
authenticated: false,
|
|
5977
|
+
linearMcp: false,
|
|
5978
|
+
warnings: [],
|
|
5979
|
+
reason: "codex CLI not found on PATH"
|
|
5980
|
+
};
|
|
5981
|
+
}
|
|
5707
5982
|
}
|
|
5708
5983
|
const authenticated = codexLooksAuthenticated();
|
|
5709
5984
|
const linearMcp = false;
|
|
@@ -5723,22 +5998,24 @@ var init_codex = __esm({
|
|
|
5723
5998
|
};
|
|
5724
5999
|
},
|
|
5725
6000
|
async buildTurn(thread, input) {
|
|
5726
|
-
const prompt = flattenTurnInput(input);
|
|
5727
6001
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
6002
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, sessionId));
|
|
5728
6003
|
const useStdin = prompt.length > CODEX_PROMPT_ARG_MAX;
|
|
5729
6004
|
const promptArg = useStdin ? "-" : prompt;
|
|
5730
6005
|
if (process.env.SIDEBOARD_DEBUG_CODEX_TURN === "1") {
|
|
5731
|
-
const { cachedPrefix } = normalizeTurnInput(input);
|
|
5732
6006
|
console.error(
|
|
5733
|
-
`[sideboard/codex] promptChars=${prompt.length} resumed=${Boolean(sessionId)} stdin=${useStdin} hasPrefix=${
|
|
6007
|
+
`[sideboard/codex] promptChars=${prompt.length} resumed=${Boolean(sessionId)} stdin=${useStdin} hasPrefix=${prompt.includes("Current request:")}`
|
|
5734
6008
|
);
|
|
5735
6009
|
}
|
|
5736
6010
|
const mode = permissionMode(thread);
|
|
5737
6011
|
const model = thread.model?.trim();
|
|
6012
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
5738
6013
|
const injected = await buildInjectedMcpServers({
|
|
5739
6014
|
includeSideboard: true,
|
|
5740
|
-
includeBrightsy:
|
|
5741
|
-
|
|
6015
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
6016
|
+
orchestrator: isOrchestrator
|
|
6017
|
+
}),
|
|
6018
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
5742
6019
|
});
|
|
5743
6020
|
const mcpOverrides = toCodexMcpConfigArgs(injected);
|
|
5744
6021
|
const execOpts = [
|
|
@@ -5758,7 +6035,7 @@ var init_codex = __esm({
|
|
|
5758
6035
|
];
|
|
5759
6036
|
const args = sessionId ? ["exec", ...execOpts, "resume", sessionId, promptArg] : ["exec", ...execOpts, promptArg];
|
|
5760
6037
|
return {
|
|
5761
|
-
file: "codex",
|
|
6038
|
+
file: resolveAgentExecutable("codex"),
|
|
5762
6039
|
args,
|
|
5763
6040
|
cwd: thread.worktreePath,
|
|
5764
6041
|
stdin: useStdin ? `${prompt}
|
|
@@ -5854,16 +6131,17 @@ var init_codex = __esm({
|
|
|
5854
6131
|
return cached;
|
|
5855
6132
|
},
|
|
5856
6133
|
async buildAttach(thread) {
|
|
6134
|
+
const codex = resolveAgentExecutable("codex");
|
|
5857
6135
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
5858
6136
|
if (sessionId) {
|
|
5859
6137
|
return {
|
|
5860
|
-
file:
|
|
6138
|
+
file: codex,
|
|
5861
6139
|
args: ["exec", "--cd", thread.worktreePath, "resume", sessionId],
|
|
5862
6140
|
cwd: thread.worktreePath
|
|
5863
6141
|
};
|
|
5864
6142
|
}
|
|
5865
6143
|
return {
|
|
5866
|
-
file:
|
|
6144
|
+
file: codex,
|
|
5867
6145
|
args: ["--cd", thread.worktreePath],
|
|
5868
6146
|
cwd: thread.worktreePath
|
|
5869
6147
|
};
|
|
@@ -5871,7 +6149,7 @@ var init_codex = __esm({
|
|
|
5871
6149
|
async listLinearIssues(_repoPath) {
|
|
5872
6150
|
const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
|
|
5873
6151
|
const { stdout, exitCode } = await run(
|
|
5874
|
-
"codex",
|
|
6152
|
+
resolveAgentExecutable("codex"),
|
|
5875
6153
|
[
|
|
5876
6154
|
"exec",
|
|
5877
6155
|
"--json",
|
|
@@ -6134,21 +6412,22 @@ function cursorRunnerPath() {
|
|
|
6134
6412
|
(0, import_node_path13.join)(root, "src", "agents", "cursor-runner.ts")
|
|
6135
6413
|
];
|
|
6136
6414
|
for (const candidate of candidates) {
|
|
6137
|
-
if ((0,
|
|
6415
|
+
if ((0, import_node_fs15.existsSync)(candidate)) return candidate;
|
|
6138
6416
|
}
|
|
6139
6417
|
return candidates[0];
|
|
6140
6418
|
}
|
|
6141
|
-
var
|
|
6419
|
+
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
6420
|
var init_cursor = __esm({
|
|
6143
6421
|
"src/agents/cursor.ts"() {
|
|
6144
6422
|
"use strict";
|
|
6145
|
-
|
|
6423
|
+
import_node_fs15 = require("fs");
|
|
6146
6424
|
import_node_module2 = require("module");
|
|
6147
6425
|
import_node_path13 = require("path");
|
|
6148
6426
|
import_node_url2 = require("url");
|
|
6149
6427
|
import_sdk = require("@cursor/sdk");
|
|
6150
6428
|
init_run();
|
|
6151
6429
|
init_app_settings();
|
|
6430
|
+
init_global_workspace();
|
|
6152
6431
|
init_cursor_events();
|
|
6153
6432
|
init_injected_mcp();
|
|
6154
6433
|
init_node_launch();
|
|
@@ -6185,13 +6464,16 @@ var init_cursor = __esm({
|
|
|
6185
6464
|
};
|
|
6186
6465
|
},
|
|
6187
6466
|
async buildTurn(thread, input) {
|
|
6188
|
-
const prompt = flattenTurnInput(input);
|
|
6189
6467
|
const agentId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
6468
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, agentId));
|
|
6190
6469
|
const apiKey = resolveCursorApiKey() || void 0;
|
|
6470
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
6191
6471
|
const injected = await buildInjectedMcpServers({
|
|
6192
6472
|
includeSideboard: true,
|
|
6193
|
-
includeBrightsy:
|
|
6194
|
-
|
|
6473
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
6474
|
+
orchestrator: isOrchestrator
|
|
6475
|
+
}),
|
|
6476
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
6195
6477
|
});
|
|
6196
6478
|
const mcpServers = toCursorMcpServers(injected);
|
|
6197
6479
|
const req = {
|
|
@@ -6262,9 +6544,14 @@ async function listOpencodeModels() {
|
|
|
6262
6544
|
if (cachedOpencodeModels && now - cachedOpencodeModels.at < OPENCODE_MODEL_CACHE_MS) {
|
|
6263
6545
|
return cachedOpencodeModels.models;
|
|
6264
6546
|
}
|
|
6265
|
-
const
|
|
6266
|
-
if (
|
|
6267
|
-
|
|
6547
|
+
const opencode = resolveAgentExecutable("opencode");
|
|
6548
|
+
if (opencode === "opencode") {
|
|
6549
|
+
const which = await run("which", ["opencode"], { reject: false });
|
|
6550
|
+
if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
|
|
6551
|
+
} else if (!(0, import_node_fs16.existsSync)(opencode)) {
|
|
6552
|
+
return FALLBACK_OPENCODE_MODELS;
|
|
6553
|
+
}
|
|
6554
|
+
const listed = await run(opencode, ["models"], { reject: false });
|
|
6268
6555
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
6269
6556
|
return cachedOpencodeModels?.models ?? FALLBACK_OPENCODE_MODELS;
|
|
6270
6557
|
}
|
|
@@ -6291,11 +6578,14 @@ function usageFromOpencode(tokens) {
|
|
|
6291
6578
|
cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
|
|
6292
6579
|
};
|
|
6293
6580
|
}
|
|
6294
|
-
var FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
|
|
6581
|
+
var import_node_fs16, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
|
|
6295
6582
|
var init_opencode = __esm({
|
|
6296
6583
|
"src/agents/opencode.ts"() {
|
|
6297
6584
|
"use strict";
|
|
6585
|
+
import_node_fs16 = require("fs");
|
|
6298
6586
|
init_run();
|
|
6587
|
+
init_app_settings();
|
|
6588
|
+
init_global_workspace();
|
|
6299
6589
|
init_error_detail();
|
|
6300
6590
|
init_injected_mcp();
|
|
6301
6591
|
init_turn_input();
|
|
@@ -6316,20 +6606,34 @@ var init_opencode = __esm({
|
|
|
6316
6606
|
opencodeAdapter = {
|
|
6317
6607
|
kind: "opencode",
|
|
6318
6608
|
async detect() {
|
|
6319
|
-
const
|
|
6320
|
-
if (
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6609
|
+
const opencode = resolveAgentExecutable("opencode");
|
|
6610
|
+
if (opencode !== "opencode") {
|
|
6611
|
+
if (!(0, import_node_fs16.existsSync)(opencode)) {
|
|
6612
|
+
return {
|
|
6613
|
+
agent: "opencode",
|
|
6614
|
+
installed: false,
|
|
6615
|
+
authenticated: false,
|
|
6616
|
+
linearMcp: false,
|
|
6617
|
+
warnings: [],
|
|
6618
|
+
reason: `OpenCode executable not found: ${opencode}`
|
|
6619
|
+
};
|
|
6620
|
+
}
|
|
6621
|
+
} else {
|
|
6622
|
+
const which = await run("which", ["opencode"], { reject: false });
|
|
6623
|
+
if (which.exitCode !== 0) {
|
|
6624
|
+
return {
|
|
6625
|
+
agent: "opencode",
|
|
6626
|
+
installed: false,
|
|
6627
|
+
authenticated: false,
|
|
6628
|
+
linearMcp: false,
|
|
6629
|
+
warnings: [],
|
|
6630
|
+
reason: "opencode CLI not found on PATH"
|
|
6631
|
+
};
|
|
6632
|
+
}
|
|
6329
6633
|
}
|
|
6330
|
-
const auth = await run(
|
|
6634
|
+
const auth = await run(opencode, ["auth", "list"], { reject: false });
|
|
6331
6635
|
const authenticated = auth.exitCode === 0 && auth.stdout.trim().length > 0;
|
|
6332
|
-
const mcp = await run(
|
|
6636
|
+
const mcp = await run(opencode, ["mcp", "list"], { reject: false });
|
|
6333
6637
|
const linearMcp = /linear/i.test(mcp.stdout + mcp.stderr);
|
|
6334
6638
|
return {
|
|
6335
6639
|
agent: "opencode",
|
|
@@ -6341,8 +6645,8 @@ var init_opencode = __esm({
|
|
|
6341
6645
|
};
|
|
6342
6646
|
},
|
|
6343
6647
|
async buildTurn(thread, input) {
|
|
6344
|
-
const prompt = flattenTurnInput(input);
|
|
6345
6648
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
6649
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, sessionId));
|
|
6346
6650
|
const mode = permissionMode(thread);
|
|
6347
6651
|
const model = thread.model?.trim();
|
|
6348
6652
|
const args = [
|
|
@@ -6358,14 +6662,17 @@ var init_opencode = __esm({
|
|
|
6358
6662
|
if (model) {
|
|
6359
6663
|
args.push("--model", model);
|
|
6360
6664
|
}
|
|
6665
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
6361
6666
|
const injected = await buildInjectedMcpServers({
|
|
6362
6667
|
includeSideboard: true,
|
|
6363
|
-
includeBrightsy:
|
|
6364
|
-
|
|
6668
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
6669
|
+
orchestrator: isOrchestrator
|
|
6670
|
+
}),
|
|
6671
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
6365
6672
|
});
|
|
6366
6673
|
const mcpContent = injected.length > 0 ? toOpencodeMcpConfigContent(injected) : null;
|
|
6367
6674
|
return {
|
|
6368
|
-
file: "opencode",
|
|
6675
|
+
file: resolveAgentExecutable("opencode"),
|
|
6369
6676
|
args,
|
|
6370
6677
|
cwd: thread.worktreePath,
|
|
6371
6678
|
// `opencode run` treats non-TTY stdin as the message body when no positional
|
|
@@ -6441,7 +6748,7 @@ var init_opencode = __esm({
|
|
|
6441
6748
|
async resolveSessionId(worktreePath, cached) {
|
|
6442
6749
|
const cachedId = cached?.trim() || null;
|
|
6443
6750
|
const listed = await run(
|
|
6444
|
-
"opencode",
|
|
6751
|
+
resolveAgentExecutable("opencode"),
|
|
6445
6752
|
["session", "list", "--format", "json"],
|
|
6446
6753
|
{ cwd: worktreePath, reject: false }
|
|
6447
6754
|
);
|
|
@@ -6472,7 +6779,7 @@ var init_opencode = __esm({
|
|
|
6472
6779
|
const args = ["--dir", thread.worktreePath];
|
|
6473
6780
|
if (sessionId) args.push("--session", sessionId);
|
|
6474
6781
|
return {
|
|
6475
|
-
file: "opencode",
|
|
6782
|
+
file: resolveAgentExecutable("opencode"),
|
|
6476
6783
|
args,
|
|
6477
6784
|
cwd: thread.worktreePath,
|
|
6478
6785
|
env: {
|
|
@@ -6483,7 +6790,7 @@ var init_opencode = __esm({
|
|
|
6483
6790
|
async listLinearIssues(_repoPath) {
|
|
6484
6791
|
const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
|
|
6485
6792
|
const { stdout, exitCode } = await run(
|
|
6486
|
-
"opencode",
|
|
6793
|
+
resolveAgentExecutable("opencode"),
|
|
6487
6794
|
["run", prompt, "--format", "json"],
|
|
6488
6795
|
{
|
|
6489
6796
|
reject: false,
|
|
@@ -6716,9 +7023,30 @@ function getAgentSetupInfo(agent) {
|
|
|
6716
7023
|
function listAgentSetupInfo() {
|
|
6717
7024
|
return Object.values(SETUP);
|
|
6718
7025
|
}
|
|
6719
|
-
|
|
6720
|
-
|
|
7026
|
+
function resolveLoginCommand(agent) {
|
|
7027
|
+
const info = getAgentSetupInfo(agent);
|
|
7028
|
+
if (!info.loginCommand) return null;
|
|
7029
|
+
if (!CLI_LOGIN_AGENTS.has(agent)) return info.loginCommand;
|
|
7030
|
+
const exe = resolveAgentExecutable(agent);
|
|
7031
|
+
return info.loginCommand.replace(/^\S+/, exe);
|
|
7032
|
+
}
|
|
7033
|
+
async function prepareTerminalCommand(command) {
|
|
7034
|
+
enrichPathWithNpmGlobalBin();
|
|
6721
7035
|
const trimmed = command.trim();
|
|
7036
|
+
if (!trimmed) return trimmed;
|
|
7037
|
+
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
7038
|
+
const match = /^(\S+)(\s[\s\S]*)?$/.exec(trimmed);
|
|
7039
|
+
const bin = match?.[1];
|
|
7040
|
+
let whichPath = null;
|
|
7041
|
+
if (bin && !bin.includes("/") && !bin.includes("\\")) {
|
|
7042
|
+
const which = await run("which", [bin], { reject: false, timeoutMs: 3e3 });
|
|
7043
|
+
whichPath = which.exitCode === 0 ? which.stdout.trim() : null;
|
|
7044
|
+
}
|
|
7045
|
+
const resolved = resolveCommandBinarySync(trimmed, whichPath);
|
|
7046
|
+
return withExportedPath(resolved, process.env.PATH ?? "");
|
|
7047
|
+
}
|
|
7048
|
+
async function openInSystemTerminal(command) {
|
|
7049
|
+
const trimmed = (await prepareTerminalCommand(command)).trim();
|
|
6722
7050
|
if (!trimmed) throw new Error("Command is empty");
|
|
6723
7051
|
if (process.platform === "darwin") {
|
|
6724
7052
|
const escaped = trimmed.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
@@ -6759,6 +7087,11 @@ async function openInSystemTerminal(command) {
|
|
|
6759
7087
|
`No terminal found to run: ${trimmed}. Install gnome-terminal (or similar), or run the command manually.`
|
|
6760
7088
|
);
|
|
6761
7089
|
}
|
|
7090
|
+
async function whichCli(bin) {
|
|
7091
|
+
const which = await run("which", [bin], { reject: false, timeoutMs: 3e3 });
|
|
7092
|
+
if (which.exitCode !== 0) return null;
|
|
7093
|
+
return which.stdout.trim().split(/\r?\n/).find(Boolean) ?? null;
|
|
7094
|
+
}
|
|
6762
7095
|
async function installAgent(agent) {
|
|
6763
7096
|
const info = getAgentSetupInfo(agent);
|
|
6764
7097
|
if (info.kind === "bundled-sdk" || info.kind === "api-key") {
|
|
@@ -6779,7 +7112,18 @@ async function installAgent(agent) {
|
|
|
6779
7112
|
message: `Opened Terminal to run: ${info.installCommand}`
|
|
6780
7113
|
};
|
|
6781
7114
|
}
|
|
6782
|
-
|
|
7115
|
+
enrichPathWithNpmGlobalBin();
|
|
7116
|
+
const cliBin = agent === "cursor" ? null : CLI_BIN[agent];
|
|
7117
|
+
if (cliBin) {
|
|
7118
|
+
const existing = await whichCli(cliBin);
|
|
7119
|
+
if (existing) {
|
|
7120
|
+
return {
|
|
7121
|
+
ok: true,
|
|
7122
|
+
command: existing,
|
|
7123
|
+
message: isConductorBundledCli(existing) ? `Using Conductor\u2019s ${cliBin} at ${existing}. No extra install \u2014 Log in only if auth is missing.` : `Already on PATH: ${existing}`
|
|
7124
|
+
};
|
|
7125
|
+
}
|
|
7126
|
+
}
|
|
6783
7127
|
const result = await run("npm", ["install", "-g", info.npmPackage], { reject: false });
|
|
6784
7128
|
const ok = result.exitCode === 0;
|
|
6785
7129
|
if (!ok) {
|
|
@@ -6805,36 +7149,44 @@ async function installAgent(agent) {
|
|
|
6805
7149
|
};
|
|
6806
7150
|
}
|
|
6807
7151
|
}
|
|
7152
|
+
enrichPathWithNpmGlobalBin();
|
|
7153
|
+
let binPath = null;
|
|
7154
|
+
if (cliBin) {
|
|
7155
|
+
binPath = await whichCli(cliBin);
|
|
7156
|
+
}
|
|
6808
7157
|
return {
|
|
6809
7158
|
ok: true,
|
|
6810
7159
|
command: info.installCommand,
|
|
6811
7160
|
exitCode: 0,
|
|
6812
7161
|
stdout: result.stdout,
|
|
6813
7162
|
stderr: result.stderr,
|
|
6814
|
-
message: `Installed ${info.npmPackage}`
|
|
7163
|
+
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
7164
|
};
|
|
6816
7165
|
}
|
|
6817
7166
|
async function loginAgent(agent) {
|
|
6818
7167
|
const info = getAgentSetupInfo(agent);
|
|
6819
|
-
|
|
7168
|
+
const loginCommand = resolveLoginCommand(agent);
|
|
7169
|
+
if (!loginCommand) {
|
|
6820
7170
|
return {
|
|
6821
7171
|
ok: true,
|
|
6822
7172
|
message: info.kind === "bundled-sdk" || info.kind === "api-key" ? info.summary : `No login command for ${agent}`
|
|
6823
7173
|
};
|
|
6824
7174
|
}
|
|
6825
|
-
await
|
|
7175
|
+
const prepared = await prepareTerminalCommand(loginCommand);
|
|
7176
|
+
await openInSystemTerminal(prepared);
|
|
6826
7177
|
return {
|
|
6827
7178
|
ok: true,
|
|
6828
7179
|
openedTerminal: true,
|
|
6829
|
-
command:
|
|
6830
|
-
message: `Opened Terminal to run: ${
|
|
7180
|
+
command: prepared,
|
|
7181
|
+
message: `Opened Terminal to run: ${prepared}`
|
|
6831
7182
|
};
|
|
6832
7183
|
}
|
|
6833
|
-
var SETUP;
|
|
7184
|
+
var SETUP, CLI_BIN, CLI_LOGIN_AGENTS;
|
|
6834
7185
|
var init_install = __esm({
|
|
6835
7186
|
"src/agents/install.ts"() {
|
|
6836
7187
|
"use strict";
|
|
6837
7188
|
init_run();
|
|
7189
|
+
init_app_settings();
|
|
6838
7190
|
init_path();
|
|
6839
7191
|
SETUP = {
|
|
6840
7192
|
claude: {
|
|
@@ -6883,6 +7235,18 @@ var init_install = __esm({
|
|
|
6883
7235
|
npmPackage: "@brightsy/cli"
|
|
6884
7236
|
}
|
|
6885
7237
|
};
|
|
7238
|
+
CLI_BIN = {
|
|
7239
|
+
claude: "claude",
|
|
7240
|
+
codex: "codex",
|
|
7241
|
+
opencode: "opencode",
|
|
7242
|
+
brightsy: "brightsy"
|
|
7243
|
+
};
|
|
7244
|
+
CLI_LOGIN_AGENTS = /* @__PURE__ */ new Set([
|
|
7245
|
+
"claude",
|
|
7246
|
+
"codex",
|
|
7247
|
+
"opencode",
|
|
7248
|
+
"brightsy"
|
|
7249
|
+
]);
|
|
6886
7250
|
}
|
|
6887
7251
|
});
|
|
6888
7252
|
|
|
@@ -6898,14 +7262,17 @@ __export(agents_exports, {
|
|
|
6898
7262
|
claudeAdapter: () => claudeAdapter,
|
|
6899
7263
|
codexAdapter: () => codexAdapter,
|
|
6900
7264
|
coerceOrchestratorAgent: () => coerceOrchestratorAgent,
|
|
7265
|
+
conductorBundledBinDir: () => conductorBundledBinDir,
|
|
6901
7266
|
cursorAdapter: () => cursorAdapter,
|
|
6902
7267
|
cursorSdkMessageToEvents: () => cursorSdkMessageToEvents,
|
|
6903
7268
|
decodeBrightsyTarget: () => decodeBrightsyTarget,
|
|
6904
7269
|
encodeBrightsyTarget: () => encodeBrightsyTarget,
|
|
7270
|
+
enrichPathWithNpmGlobalBin: () => enrichPathWithNpmGlobalBin,
|
|
6905
7271
|
ensureAgentPath: () => ensureAgentPath,
|
|
6906
7272
|
getAdapter: () => getAdapter,
|
|
6907
7273
|
getAgentSetupInfo: () => getAgentSetupInfo,
|
|
6908
7274
|
installAgent: () => installAgent,
|
|
7275
|
+
isConductorBundledCli: () => isConductorBundledCli,
|
|
6909
7276
|
isCursorAutoModel: () => isCursorAutoModel,
|
|
6910
7277
|
isOrchestratorCapableAgent: () => isOrchestratorCapableAgent,
|
|
6911
7278
|
isSessionQuotaLimit: () => isSessionQuotaLimit,
|
|
@@ -6921,8 +7288,13 @@ __export(agents_exports, {
|
|
|
6921
7288
|
parseCursorRunnerLine: () => parseCursorRunnerLine,
|
|
6922
7289
|
parseSessionQuotaResetAt: () => parseSessionQuotaResetAt,
|
|
6923
7290
|
permissionMode: () => permissionMode,
|
|
7291
|
+
posixShellSingleQuote: () => posixShellSingleQuote,
|
|
7292
|
+
prepareTerminalCommand: () => prepareTerminalCommand,
|
|
7293
|
+
resolveCommandBinarySync: () => resolveCommandBinarySync,
|
|
6924
7294
|
resolveCursorModelId: () => resolveCursorModelId,
|
|
6925
|
-
|
|
7295
|
+
resolveLoginCommand: () => resolveLoginCommand,
|
|
7296
|
+
resolveQuotaFallbackAgent: () => resolveQuotaFallbackAgent,
|
|
7297
|
+
withExportedPath: () => withExportedPath
|
|
6926
7298
|
});
|
|
6927
7299
|
function getAdapter(kind) {
|
|
6928
7300
|
return adapters[kind];
|
|
@@ -7034,17 +7406,17 @@ __export(plan_file_exports, {
|
|
|
7034
7406
|
});
|
|
7035
7407
|
function ensureAttachmentsGitignore2(worktreePath) {
|
|
7036
7408
|
const gitignoreAbs = (0, import_node_path24.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
7037
|
-
if ((0,
|
|
7038
|
-
(0,
|
|
7039
|
-
(0,
|
|
7409
|
+
if ((0, import_node_fs29.existsSync)(gitignoreAbs)) return;
|
|
7410
|
+
(0, import_node_fs29.mkdirSync)((0, import_node_path24.dirname)(gitignoreAbs), { recursive: true });
|
|
7411
|
+
(0, import_node_fs29.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
7040
7412
|
}
|
|
7041
7413
|
function planFileAbs(worktreePath) {
|
|
7042
7414
|
return (0, import_node_path24.join)(worktreePath, PLAN_FILE_REL);
|
|
7043
7415
|
}
|
|
7044
7416
|
function readTextIfPresent2(abs) {
|
|
7045
|
-
if (!(0,
|
|
7417
|
+
if (!(0, import_node_fs29.existsSync)(abs)) return null;
|
|
7046
7418
|
try {
|
|
7047
|
-
const content = (0,
|
|
7419
|
+
const content = (0, import_node_fs29.readFileSync)(abs, "utf8");
|
|
7048
7420
|
return content.trim() ? content : null;
|
|
7049
7421
|
} catch {
|
|
7050
7422
|
return null;
|
|
@@ -7056,16 +7428,16 @@ function readPlanFile(worktreePath) {
|
|
|
7056
7428
|
function writePlanFile(worktreePath, content) {
|
|
7057
7429
|
ensureAttachmentsGitignore2(worktreePath);
|
|
7058
7430
|
const abs = planFileAbs(worktreePath);
|
|
7059
|
-
(0,
|
|
7431
|
+
(0, import_node_fs29.mkdirSync)((0, import_node_path24.dirname)(abs), { recursive: true });
|
|
7060
7432
|
const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
|
|
7061
|
-
(0,
|
|
7433
|
+
(0, import_node_fs29.writeFileSync)(abs, body, "utf8");
|
|
7062
7434
|
return PLAN_FILE_REL;
|
|
7063
7435
|
}
|
|
7064
|
-
var
|
|
7436
|
+
var import_node_fs29, import_node_path24;
|
|
7065
7437
|
var init_plan_file = __esm({
|
|
7066
7438
|
"src/plan/plan-file.ts"() {
|
|
7067
7439
|
"use strict";
|
|
7068
|
-
|
|
7440
|
+
import_node_fs29 = require("fs");
|
|
7069
7441
|
import_node_path24 = require("path");
|
|
7070
7442
|
init_workspace_scratch();
|
|
7071
7443
|
init_plan_present();
|
|
@@ -7082,9 +7454,9 @@ function recoverFinishedCursorRun(opts) {
|
|
|
7082
7454
|
const agentId = opts.agentId.trim();
|
|
7083
7455
|
if (!agentId) return null;
|
|
7084
7456
|
const runsPath = (0, import_node_path25.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
|
|
7085
|
-
if (!(0,
|
|
7457
|
+
if (!(0, import_node_fs30.existsSync)(runsPath)) return null;
|
|
7086
7458
|
try {
|
|
7087
|
-
const lines = (0,
|
|
7459
|
+
const lines = (0, import_node_fs30.readFileSync)(runsPath, "utf8").split("\n");
|
|
7088
7460
|
let best = null;
|
|
7089
7461
|
for (const line of lines) {
|
|
7090
7462
|
const trimmed = line.trim();
|
|
@@ -7110,11 +7482,11 @@ function recoverFinishedCursorRun(opts) {
|
|
|
7110
7482
|
return null;
|
|
7111
7483
|
}
|
|
7112
7484
|
}
|
|
7113
|
-
var
|
|
7485
|
+
var import_node_fs30, import_node_path25;
|
|
7114
7486
|
var init_cursor_recover = __esm({
|
|
7115
7487
|
"src/agents/cursor-recover.ts"() {
|
|
7116
7488
|
"use strict";
|
|
7117
|
-
|
|
7489
|
+
import_node_fs30 = require("fs");
|
|
7118
7490
|
import_node_path25 = require("path");
|
|
7119
7491
|
init_paths();
|
|
7120
7492
|
}
|
|
@@ -7188,6 +7560,7 @@ __export(index_exports, {
|
|
|
7188
7560
|
REVIEW_REQUEST_PREFILL: () => REVIEW_REQUEST_PREFILL,
|
|
7189
7561
|
SIDEBOARD_FORCE_STOP: () => SIDEBOARD_FORCE_STOP,
|
|
7190
7562
|
SIDEBOARD_MCP_ALLOWED_TOOLS: () => SIDEBOARD_MCP_ALLOWED_TOOLS,
|
|
7563
|
+
SIDEBOARD_MCP_PROFILE_ENV: () => SIDEBOARD_MCP_PROFILE_ENV,
|
|
7191
7564
|
THINKING_EFFORTS: () => THINKING_EFFORTS,
|
|
7192
7565
|
addPrStackLayer: () => addPrStackLayer,
|
|
7193
7566
|
addStackLayerFromThread: () => addStackLayerFromThread,
|
|
@@ -7219,6 +7592,7 @@ __export(index_exports, {
|
|
|
7219
7592
|
brightsyCloudConnectAgent: () => brightsyCloudConnectAgent,
|
|
7220
7593
|
brightsyCloudConnectEnabled: () => brightsyCloudConnectEnabled,
|
|
7221
7594
|
brightsyConfigPath: () => brightsyConfigPath,
|
|
7595
|
+
brightsyInjectWorktreeMcpEnabled: () => brightsyInjectWorktreeMcpEnabled,
|
|
7222
7596
|
brightsyMcpAllowedTools: () => brightsyMcpAllowedTools,
|
|
7223
7597
|
brightsyMcpServerName: () => brightsyMcpServerName,
|
|
7224
7598
|
buildCachedUserContent: () => buildCachedUserContent,
|
|
@@ -7244,6 +7618,7 @@ __export(index_exports, {
|
|
|
7244
7618
|
coerceOrchestratorAgent: () => coerceOrchestratorAgent,
|
|
7245
7619
|
collectTakenTeamSlugs: () => collectTakenTeamSlugs,
|
|
7246
7620
|
commitAll: () => commitAll,
|
|
7621
|
+
conductorBundledBinDir: () => conductorBundledBinDir,
|
|
7247
7622
|
conductorDbPath: () => conductorDbPath,
|
|
7248
7623
|
confirmLand: () => confirmLand,
|
|
7249
7624
|
connectBrightsyTeam: () => connectBrightsyTeam,
|
|
@@ -7270,7 +7645,9 @@ __export(index_exports, {
|
|
|
7270
7645
|
detectLocalMergeConflicts: () => detectLocalMergeConflicts,
|
|
7271
7646
|
disconnectBrightsyTeam: () => disconnectBrightsyTeam,
|
|
7272
7647
|
discoverSkills: () => discoverSkills,
|
|
7648
|
+
dropCachedPrefixOnResume: () => dropCachedPrefixOnResume,
|
|
7273
7649
|
encodeBrightsyTarget: () => encodeBrightsyTarget,
|
|
7650
|
+
enrichPathWithNpmGlobalBin: () => enrichPathWithNpmGlobalBin,
|
|
7274
7651
|
enrichWorkspacesWithGithub: () => enrichWorkspacesWithGithub,
|
|
7275
7652
|
ensureAgentPath: () => ensureAgentPath,
|
|
7276
7653
|
ensureCloudCoordinator: () => ensureCloudCoordinator,
|
|
@@ -7308,6 +7685,7 @@ __export(index_exports, {
|
|
|
7308
7685
|
formatTranscriptMarkdown: () => formatTranscriptMarkdown,
|
|
7309
7686
|
formatWorkspaceInventory: () => formatWorkspaceInventory,
|
|
7310
7687
|
formatWorktreeDirective: () => formatWorktreeDirective,
|
|
7688
|
+
formatWorktreeReminder: () => formatWorktreeReminder,
|
|
7311
7689
|
getAdapter: () => getAdapter,
|
|
7312
7690
|
getAgentSetupInfo: () => getAgentSetupInfo,
|
|
7313
7691
|
getBrightsySession: () => getBrightsySession,
|
|
@@ -7352,6 +7730,7 @@ __export(index_exports, {
|
|
|
7352
7730
|
isBrightsyConnected: () => isBrightsyConnected,
|
|
7353
7731
|
isBrightsyNdjsonLine: () => isBrightsyNdjsonLine,
|
|
7354
7732
|
isCloudCoordinatorThread: () => isCloudCoordinatorThread,
|
|
7733
|
+
isConductorBundledCli: () => isConductorBundledCli,
|
|
7355
7734
|
isCursorAutoModel: () => isCursorAutoModel,
|
|
7356
7735
|
isDirty: () => isDirty,
|
|
7357
7736
|
isGhRateLimitError: () => isGhRateLimitError,
|
|
@@ -7434,7 +7813,10 @@ __export(index_exports, {
|
|
|
7434
7813
|
pastedTextStats: () => pastedTextStats,
|
|
7435
7814
|
permissionMode: () => permissionMode,
|
|
7436
7815
|
planFileAbs: () => planFileAbs,
|
|
7816
|
+
posixShellSingleQuote: () => posixShellSingleQuote,
|
|
7817
|
+
prepareTerminalCommand: () => prepareTerminalCommand,
|
|
7437
7818
|
previewLand: () => previewLand,
|
|
7819
|
+
promptMentionsBrightsy: () => promptMentionsBrightsy,
|
|
7438
7820
|
pushBranch: () => pushBranch,
|
|
7439
7821
|
readExistingReviewRequestFile: () => readExistingReviewRequestFile,
|
|
7440
7822
|
readPlanFile: () => readPlanFile,
|
|
@@ -7450,7 +7832,9 @@ __export(index_exports, {
|
|
|
7450
7832
|
requestReview: () => requestReview,
|
|
7451
7833
|
requireAgent: () => requireAgent,
|
|
7452
7834
|
resetGhStackDetectCache: () => resetGhStackDetectCache,
|
|
7835
|
+
resolveAgentExecutable: () => resolveAgentExecutable,
|
|
7453
7836
|
resolveClaudeExecutable: () => resolveClaudeExecutable,
|
|
7837
|
+
resolveCommandBinarySync: () => resolveCommandBinarySync,
|
|
7454
7838
|
resolveConductorCursorAgentId: () => resolveConductorCursorAgentId,
|
|
7455
7839
|
resolveCursorModelId: () => resolveCursorModelId,
|
|
7456
7840
|
resolveDefaultBranch: () => resolveDefaultBranch,
|
|
@@ -7459,6 +7843,7 @@ __export(index_exports, {
|
|
|
7459
7843
|
resolveFilesToCopy: () => resolveFilesToCopy,
|
|
7460
7844
|
resolveGhAuthToken: () => resolveGhAuthToken,
|
|
7461
7845
|
resolveGithubRepoSlug: () => resolveGithubRepoSlug,
|
|
7846
|
+
resolveLoginCommand: () => resolveLoginCommand,
|
|
7462
7847
|
resolveNewThreadOptions: () => resolveNewThreadOptions,
|
|
7463
7848
|
resolvePlanMarkdown: () => resolvePlanMarkdown,
|
|
7464
7849
|
resolvePrSelector: () => resolvePrSelector,
|
|
@@ -7480,9 +7865,11 @@ __export(index_exports, {
|
|
|
7480
7865
|
settingsSourceLabel: () => settingsSourceLabel,
|
|
7481
7866
|
shouldAttachPastedText: () => shouldAttachPastedText,
|
|
7482
7867
|
shouldCompactContext: () => shouldCompactContext,
|
|
7868
|
+
shouldInjectBrightsyMcp: () => shouldInjectBrightsyMcp,
|
|
7483
7869
|
shouldRefreshReviewRequestTemplate: () => shouldRefreshReviewRequestTemplate,
|
|
7484
7870
|
shouldRunWorktreeCleanup: () => shouldRunWorktreeCleanup,
|
|
7485
7871
|
sideboardHomeDir: () => sideboardHomeDir,
|
|
7872
|
+
sideboardMcpProfile: () => sideboardMcpProfile,
|
|
7486
7873
|
sideboardReposDir: () => sideboardReposDir,
|
|
7487
7874
|
sideboardWorkspacesDir: () => sideboardWorkspacesDir,
|
|
7488
7875
|
slugify: () => slugify,
|
|
@@ -7510,6 +7897,7 @@ __export(index_exports, {
|
|
|
7510
7897
|
threadDisplayLabel: () => threadDisplayLabel,
|
|
7511
7898
|
threadFilePath: () => threadFilePath,
|
|
7512
7899
|
threadLockPath: () => threadLockPath,
|
|
7900
|
+
threadRequestsBrightsyMcp: () => threadRequestsBrightsyMcp,
|
|
7513
7901
|
threadsDir: () => threadsDir,
|
|
7514
7902
|
threadsSharingWorktree: () => threadsSharingWorktree,
|
|
7515
7903
|
toolDescription: () => toolDescription,
|
|
@@ -7517,14 +7905,18 @@ __export(index_exports, {
|
|
|
7517
7905
|
toolFilePath: () => toolFilePath,
|
|
7518
7906
|
totalTokens: () => totalTokens,
|
|
7519
7907
|
updateAdvancedSettings: () => updateAdvancedSettings,
|
|
7908
|
+
updateAgentExecutable: () => updateAgentExecutable,
|
|
7520
7909
|
updateAppEnvironment: () => updateAppEnvironment,
|
|
7521
7910
|
updateBrightsySettings: () => updateBrightsySettings,
|
|
7522
7911
|
updateClaudeSettings: () => updateClaudeSettings,
|
|
7912
|
+
updateCodexSettings: () => updateCodexSettings,
|
|
7523
7913
|
updateDefaultsSettings: () => updateDefaultsSettings,
|
|
7524
7914
|
updateIntegrationsSettings: () => updateIntegrationsSettings,
|
|
7915
|
+
updateOpencodeSettings: () => updateOpencodeSettings,
|
|
7525
7916
|
updateThread: () => updateThread,
|
|
7526
7917
|
validateLinearApiKey: () => validateLinearApiKey,
|
|
7527
7918
|
withAgentInstructions: () => withAgentInstructions,
|
|
7919
|
+
withExportedPath: () => withExportedPath,
|
|
7528
7920
|
withThreadLock: () => withThreadLock,
|
|
7529
7921
|
workspaceSettingsSourceLabel: () => workspaceSettingsSourceLabel,
|
|
7530
7922
|
worktreeCleanupSettings: () => worktreeCleanupSettings,
|
|
@@ -8101,7 +8493,7 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
8101
8493
|
init_claude_mcp();
|
|
8102
8494
|
|
|
8103
8495
|
// src/agents/instructions.ts
|
|
8104
|
-
var
|
|
8496
|
+
var import_node_fs17 = require("fs");
|
|
8105
8497
|
var import_node_path14 = require("path");
|
|
8106
8498
|
init_worktree_labels();
|
|
8107
8499
|
function normPath2(p) {
|
|
@@ -8201,6 +8593,9 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
8201
8593
|
);
|
|
8202
8594
|
return lines.join("\n");
|
|
8203
8595
|
}
|
|
8596
|
+
function formatWorktreeReminder() {
|
|
8597
|
+
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.";
|
|
8598
|
+
}
|
|
8204
8599
|
function formatArtifactDirective() {
|
|
8205
8600
|
return [
|
|
8206
8601
|
"Sideboard side column (desktop UI):",
|
|
@@ -8242,10 +8637,10 @@ function loadAgentInstructions(worktreePath, agent) {
|
|
|
8242
8637
|
for (const rel of candidates) {
|
|
8243
8638
|
if (seen.has(rel)) continue;
|
|
8244
8639
|
const abs = (0, import_node_path14.join)(worktreePath, rel);
|
|
8245
|
-
if (!(0,
|
|
8640
|
+
if (!(0, import_node_fs17.existsSync)(abs)) continue;
|
|
8246
8641
|
try {
|
|
8247
|
-
if (!(0,
|
|
8248
|
-
let content = (0,
|
|
8642
|
+
if (!(0, import_node_fs17.statSync)(abs).isFile()) continue;
|
|
8643
|
+
let content = (0, import_node_fs17.readFileSync)(abs, "utf8");
|
|
8249
8644
|
if (!content.trim()) continue;
|
|
8250
8645
|
if (content.length > MAX_CHARS_PER_FILE) {
|
|
8251
8646
|
content = `${content.slice(0, MAX_CHARS_PER_FILE)}
|
|
@@ -8290,11 +8685,13 @@ init_turn_input();
|
|
|
8290
8685
|
init_agents();
|
|
8291
8686
|
async function detectAgents() {
|
|
8292
8687
|
ensureAgentPath();
|
|
8688
|
+
enrichPathWithNpmGlobalBin();
|
|
8293
8689
|
return Promise.all(allAdapters().map((a) => a.detect()));
|
|
8294
8690
|
}
|
|
8295
8691
|
var REQUIRE_AGENT_TIMEOUT_MS = 8e3;
|
|
8296
8692
|
async function requireAgent(agent, opts) {
|
|
8297
8693
|
ensureAgentPath();
|
|
8694
|
+
enrichPathWithNpmGlobalBin();
|
|
8298
8695
|
const status = await Promise.race([
|
|
8299
8696
|
getAdapter(agent).detect(),
|
|
8300
8697
|
new Promise((_, reject) => {
|
|
@@ -8322,7 +8719,7 @@ async function requireAgent(agent, opts) {
|
|
|
8322
8719
|
init_settings();
|
|
8323
8720
|
|
|
8324
8721
|
// src/hook/conductor.ts
|
|
8325
|
-
var
|
|
8722
|
+
var import_node_fs18 = require("fs");
|
|
8326
8723
|
var import_node_net = require("net");
|
|
8327
8724
|
var import_node_path15 = require("path");
|
|
8328
8725
|
var import_execa3 = require("execa");
|
|
@@ -8335,8 +8732,8 @@ function matchSimpleGlob(pattern, name) {
|
|
|
8335
8732
|
}
|
|
8336
8733
|
function readWorktreeInclude(repoPath) {
|
|
8337
8734
|
const path = (0, import_node_path15.join)(repoPath, ".worktreeinclude");
|
|
8338
|
-
if (!(0,
|
|
8339
|
-
return (0,
|
|
8735
|
+
if (!(0, import_node_fs18.existsSync)(path)) return [];
|
|
8736
|
+
return (0, import_node_fs18.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
8340
8737
|
}
|
|
8341
8738
|
function resolveFilesToCopy(repoPath) {
|
|
8342
8739
|
const fromInclude = readWorktreeInclude(repoPath);
|
|
@@ -8346,7 +8743,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
8346
8743
|
if (settings?.fileIncludeGlobs?.length) {
|
|
8347
8744
|
const matched = [];
|
|
8348
8745
|
try {
|
|
8349
|
-
for (const entry of (0,
|
|
8746
|
+
for (const entry of (0, import_node_fs18.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
8350
8747
|
if (!entry.isFile()) continue;
|
|
8351
8748
|
for (const glob of settings.fileIncludeGlobs) {
|
|
8352
8749
|
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path15.basename)(glob), entry.name)) {
|
|
@@ -8361,7 +8758,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
8361
8758
|
}
|
|
8362
8759
|
const defaults = [];
|
|
8363
8760
|
try {
|
|
8364
|
-
for (const entry of (0,
|
|
8761
|
+
for (const entry of (0, import_node_fs18.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
8365
8762
|
if (entry.isFile() && entry.name.startsWith(".env")) {
|
|
8366
8763
|
defaults.push(entry.name);
|
|
8367
8764
|
}
|
|
@@ -8376,10 +8773,10 @@ function copyConfiguredFiles(repoPath, worktreePath) {
|
|
|
8376
8773
|
const copied = [];
|
|
8377
8774
|
for (const rel of patterns) {
|
|
8378
8775
|
const src = (0, import_node_path15.join)(repoPath, rel);
|
|
8379
|
-
if (!(0,
|
|
8776
|
+
if (!(0, import_node_fs18.existsSync)(src)) continue;
|
|
8380
8777
|
const dest = (0, import_node_path15.join)(worktreePath, rel);
|
|
8381
|
-
(0,
|
|
8382
|
-
(0,
|
|
8778
|
+
(0, import_node_fs18.mkdirSync)((0, import_node_path15.dirname)(dest), { recursive: true });
|
|
8779
|
+
(0, import_node_fs18.copyFileSync)(src, dest);
|
|
8383
8780
|
copied.push(rel);
|
|
8384
8781
|
}
|
|
8385
8782
|
return copied;
|
|
@@ -8632,15 +9029,15 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
|
8632
9029
|
}
|
|
8633
9030
|
|
|
8634
9031
|
// src/hook/cursor-worktrees.ts
|
|
8635
|
-
var
|
|
9032
|
+
var import_node_fs19 = require("fs");
|
|
8636
9033
|
var import_node_path16 = require("path");
|
|
8637
9034
|
var import_execa4 = require("execa");
|
|
8638
9035
|
var import_node_readline3 = require("readline");
|
|
8639
9036
|
function loadCursorWorktreesJson(rootPath) {
|
|
8640
9037
|
const path = (0, import_node_path16.join)(rootPath, ".cursor", "worktrees.json");
|
|
8641
|
-
if (!(0,
|
|
9038
|
+
if (!(0, import_node_fs19.existsSync)(path)) return null;
|
|
8642
9039
|
try {
|
|
8643
|
-
return JSON.parse((0,
|
|
9040
|
+
return JSON.parse((0, import_node_fs19.readFileSync)(path, "utf8"));
|
|
8644
9041
|
} catch {
|
|
8645
9042
|
return null;
|
|
8646
9043
|
}
|
|
@@ -8705,12 +9102,12 @@ function hasCursorWorktreeSetup(worktreePath, repoPath) {
|
|
|
8705
9102
|
}
|
|
8706
9103
|
|
|
8707
9104
|
// src/diff/diff.ts
|
|
8708
|
-
var
|
|
9105
|
+
var import_node_fs20 = require("fs");
|
|
8709
9106
|
var import_node_path17 = require("path");
|
|
8710
9107
|
init_run();
|
|
8711
9108
|
init_worktree();
|
|
8712
9109
|
async function inspectGitWorktree(worktreePath) {
|
|
8713
|
-
if (!worktreePath || !(0,
|
|
9110
|
+
if (!worktreePath || !(0, import_node_fs20.existsSync)(worktreePath)) return "missing_worktree";
|
|
8714
9111
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
8715
9112
|
reject: false
|
|
8716
9113
|
});
|
|
@@ -8718,7 +9115,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
8718
9115
|
return "ok";
|
|
8719
9116
|
}
|
|
8720
9117
|
async function initializeGitRepository(worktreePath) {
|
|
8721
|
-
if (!worktreePath || !(0,
|
|
9118
|
+
if (!worktreePath || !(0, import_node_fs20.existsSync)(worktreePath)) {
|
|
8722
9119
|
throw new Error("Worktree not found");
|
|
8723
9120
|
}
|
|
8724
9121
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -9156,7 +9553,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
9156
9553
|
assertSafeRelativePath(relativePath);
|
|
9157
9554
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
9158
9555
|
const abs = (0, import_node_path17.join)(worktreePath, relativePath);
|
|
9159
|
-
const st = (0,
|
|
9556
|
+
const st = (0, import_node_fs20.statSync)(abs);
|
|
9160
9557
|
if (!st.isFile()) {
|
|
9161
9558
|
throw new Error(`Not a file: ${relativePath}`);
|
|
9162
9559
|
}
|
|
@@ -9165,7 +9562,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
9165
9562
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
9166
9563
|
);
|
|
9167
9564
|
}
|
|
9168
|
-
const buf = (0,
|
|
9565
|
+
const buf = (0, import_node_fs20.readFileSync)(abs);
|
|
9169
9566
|
return {
|
|
9170
9567
|
path: relativePath,
|
|
9171
9568
|
contentBase64: buf.toString("base64"),
|
|
@@ -9176,11 +9573,11 @@ function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
|
9176
9573
|
assertSafeRelativePath(relativePath);
|
|
9177
9574
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
9178
9575
|
const abs = (0, import_node_path17.join)(worktreePath, relativePath);
|
|
9179
|
-
const st = (0,
|
|
9576
|
+
const st = (0, import_node_fs20.statSync)(abs);
|
|
9180
9577
|
if (!st.isFile()) {
|
|
9181
9578
|
throw new Error(`Not a file: ${relativePath}`);
|
|
9182
9579
|
}
|
|
9183
|
-
const buf = (0,
|
|
9580
|
+
const buf = (0, import_node_fs20.readFileSync)(abs);
|
|
9184
9581
|
if (isImageRelativePath(relativePath)) {
|
|
9185
9582
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
9186
9583
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -9224,8 +9621,8 @@ function assertSafeRelativePath(relativePath) {
|
|
|
9224
9621
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
9225
9622
|
assertSafeRelativePath(relativePath);
|
|
9226
9623
|
const abs = (0, import_node_path17.join)(worktreePath, relativePath);
|
|
9227
|
-
(0,
|
|
9228
|
-
(0,
|
|
9624
|
+
(0, import_node_fs20.mkdirSync)((0, import_node_path17.dirname)(abs), { recursive: true });
|
|
9625
|
+
(0, import_node_fs20.writeFileSync)(abs, content, "utf8");
|
|
9229
9626
|
return { path: relativePath };
|
|
9230
9627
|
}
|
|
9231
9628
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
@@ -9244,7 +9641,7 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
|
9244
9641
|
}
|
|
9245
9642
|
|
|
9246
9643
|
// src/skills/discover.ts
|
|
9247
|
-
var
|
|
9644
|
+
var import_node_fs21 = require("fs");
|
|
9248
9645
|
var import_node_os8 = require("os");
|
|
9249
9646
|
var import_node_path18 = require("path");
|
|
9250
9647
|
function toCommand(name) {
|
|
@@ -9278,7 +9675,7 @@ function parseFrontmatter(content) {
|
|
|
9278
9675
|
}
|
|
9279
9676
|
function readSkill(skillMd, source) {
|
|
9280
9677
|
try {
|
|
9281
|
-
const content = (0,
|
|
9678
|
+
const content = (0, import_node_fs21.readFileSync)(skillMd, "utf8");
|
|
9282
9679
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
9283
9680
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
9284
9681
|
const name = fmName || dirName;
|
|
@@ -9297,19 +9694,19 @@ function readSkill(skillMd, source) {
|
|
|
9297
9694
|
}
|
|
9298
9695
|
}
|
|
9299
9696
|
function scanSkillsDir(dir, source, out) {
|
|
9300
|
-
if (!(0,
|
|
9697
|
+
if (!(0, import_node_fs21.existsSync)(dir)) return;
|
|
9301
9698
|
let entries;
|
|
9302
9699
|
try {
|
|
9303
|
-
entries = (0,
|
|
9700
|
+
entries = (0, import_node_fs21.readdirSync)(dir);
|
|
9304
9701
|
} catch {
|
|
9305
9702
|
return;
|
|
9306
9703
|
}
|
|
9307
9704
|
for (const entry of entries) {
|
|
9308
9705
|
if (entry.startsWith(".")) continue;
|
|
9309
9706
|
const skillMd = (0, import_node_path18.join)(dir, entry, "SKILL.md");
|
|
9310
|
-
if (!(0,
|
|
9707
|
+
if (!(0, import_node_fs21.existsSync)(skillMd)) continue;
|
|
9311
9708
|
try {
|
|
9312
|
-
if (!(0,
|
|
9709
|
+
if (!(0, import_node_fs21.statSync)(skillMd).isFile()) continue;
|
|
9313
9710
|
} catch {
|
|
9314
9711
|
continue;
|
|
9315
9712
|
}
|
|
@@ -9318,12 +9715,12 @@ function scanSkillsDir(dir, source, out) {
|
|
|
9318
9715
|
}
|
|
9319
9716
|
}
|
|
9320
9717
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
9321
|
-
if (!(0,
|
|
9718
|
+
if (!(0, import_node_fs21.existsSync)(pluginsRoot)) return;
|
|
9322
9719
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
9323
9720
|
if (depth > 7) return;
|
|
9324
9721
|
let entries;
|
|
9325
9722
|
try {
|
|
9326
|
-
entries = (0,
|
|
9723
|
+
entries = (0, import_node_fs21.readdirSync)(dir);
|
|
9327
9724
|
} catch {
|
|
9328
9725
|
return;
|
|
9329
9726
|
}
|
|
@@ -9335,7 +9732,7 @@ function scanClaudePluginSkills(pluginsRoot, out) {
|
|
|
9335
9732
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
9336
9733
|
const full = (0, import_node_path18.join)(dir, entry);
|
|
9337
9734
|
try {
|
|
9338
|
-
if (!(0,
|
|
9735
|
+
if (!(0, import_node_fs21.statSync)(full).isDirectory()) continue;
|
|
9339
9736
|
} catch {
|
|
9340
9737
|
continue;
|
|
9341
9738
|
}
|
|
@@ -9375,7 +9772,7 @@ function discoverSkills(worktreePath) {
|
|
|
9375
9772
|
return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
|
|
9376
9773
|
}
|
|
9377
9774
|
function readSkillBody(skillPath, maxChars = 12e3) {
|
|
9378
|
-
const raw = (0,
|
|
9775
|
+
const raw = (0, import_node_fs21.readFileSync)(skillPath, "utf8");
|
|
9379
9776
|
if (raw.startsWith("---")) {
|
|
9380
9777
|
const end = raw.indexOf("\n---", 3);
|
|
9381
9778
|
if (end >= 0) {
|
|
@@ -9516,7 +9913,7 @@ function buildDiffCommentAttachment(input) {
|
|
|
9516
9913
|
}
|
|
9517
9914
|
|
|
9518
9915
|
// src/composer/stage-files.ts
|
|
9519
|
-
var
|
|
9916
|
+
var import_node_fs22 = require("fs");
|
|
9520
9917
|
var import_node_path19 = require("path");
|
|
9521
9918
|
var import_node_crypto2 = require("crypto");
|
|
9522
9919
|
init_workspace_scratch();
|
|
@@ -9554,21 +9951,21 @@ function imageMimeType(filePath) {
|
|
|
9554
9951
|
}
|
|
9555
9952
|
function ensureAttachmentsDir(worktreePath) {
|
|
9556
9953
|
const dir = (0, import_node_path19.join)(worktreePath, ATTACHMENTS_DIR);
|
|
9557
|
-
(0,
|
|
9954
|
+
(0, import_node_fs22.mkdirSync)(dir, { recursive: true });
|
|
9558
9955
|
const gi = (0, import_node_path19.join)(dir, ".gitignore");
|
|
9559
|
-
if (!(0,
|
|
9560
|
-
(0,
|
|
9956
|
+
if (!(0, import_node_fs22.existsSync)(gi)) {
|
|
9957
|
+
(0, import_node_fs22.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
9561
9958
|
}
|
|
9562
9959
|
return dir;
|
|
9563
9960
|
}
|
|
9564
9961
|
function uniqueAttachmentName(dir, originalName) {
|
|
9565
9962
|
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
9566
|
-
if (!(0,
|
|
9963
|
+
if (!(0, import_node_fs22.existsSync)((0, import_node_path19.join)(dir, safe))) return safe;
|
|
9567
9964
|
const ext = (0, import_node_path19.extname)(safe);
|
|
9568
9965
|
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
9569
9966
|
for (let i = 1; i < 1e4; i++) {
|
|
9570
9967
|
const candidate = `${stem}-${i}${ext}`;
|
|
9571
|
-
if (!(0,
|
|
9968
|
+
if (!(0, import_node_fs22.existsSync)((0, import_node_path19.join)(dir, candidate))) return candidate;
|
|
9572
9969
|
}
|
|
9573
9970
|
return `${stem}-${(0, import_node_crypto2.randomUUID)()}${ext}`;
|
|
9574
9971
|
}
|
|
@@ -9622,7 +10019,7 @@ function attachmentFromBuffer(name, buf, opts) {
|
|
|
9622
10019
|
function attachmentFromAbsolutePath(absolutePath) {
|
|
9623
10020
|
const name = (0, import_node_path19.basename)(absolutePath);
|
|
9624
10021
|
try {
|
|
9625
|
-
const st = (0,
|
|
10022
|
+
const st = (0, import_node_fs22.statSync)(absolutePath);
|
|
9626
10023
|
if (!st.isFile()) {
|
|
9627
10024
|
return {
|
|
9628
10025
|
id: (0, import_node_crypto2.randomUUID)(),
|
|
@@ -9631,7 +10028,7 @@ function attachmentFromAbsolutePath(absolutePath) {
|
|
|
9631
10028
|
content: `(not a file: ${absolutePath})`
|
|
9632
10029
|
};
|
|
9633
10030
|
}
|
|
9634
|
-
const buf = (0,
|
|
10031
|
+
const buf = (0, import_node_fs22.readFileSync)(absolutePath);
|
|
9635
10032
|
return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
|
|
9636
10033
|
} catch (err) {
|
|
9637
10034
|
return {
|
|
@@ -9649,13 +10046,13 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
|
9649
10046
|
for (const abs of absolutePaths) {
|
|
9650
10047
|
const originalName = (0, import_node_path19.basename)(abs);
|
|
9651
10048
|
try {
|
|
9652
|
-
const st = (0,
|
|
10049
|
+
const st = (0, import_node_fs22.statSync)(abs);
|
|
9653
10050
|
if (!st.isFile()) continue;
|
|
9654
10051
|
const name = uniqueAttachmentName(dir, originalName);
|
|
9655
10052
|
const destAbs = (0, import_node_path19.join)(dir, name);
|
|
9656
|
-
(0,
|
|
10053
|
+
(0, import_node_fs22.copyFileSync)(abs, destAbs);
|
|
9657
10054
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
9658
|
-
const buf = (0,
|
|
10055
|
+
const buf = (0, import_node_fs22.readFileSync)(destAbs);
|
|
9659
10056
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
9660
10057
|
} catch (err) {
|
|
9661
10058
|
out.push({
|
|
@@ -9678,7 +10075,7 @@ function stageBuffersAsAttachments(worktreePath, buffers) {
|
|
|
9678
10075
|
const buf = Buffer.from(item.dataBase64, "base64");
|
|
9679
10076
|
const name = uniqueAttachmentName(dir, originalName);
|
|
9680
10077
|
const destAbs = (0, import_node_path19.join)(dir, name);
|
|
9681
|
-
(0,
|
|
10078
|
+
(0, import_node_fs22.writeFileSync)(destAbs, buf);
|
|
9682
10079
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
9683
10080
|
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
9684
10081
|
} catch (err) {
|
|
@@ -9723,9 +10120,9 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
|
9723
10120
|
const name = (0, import_node_path19.basename)(rel);
|
|
9724
10121
|
try {
|
|
9725
10122
|
const abs = (0, import_node_path19.join)(worktreePath, rel);
|
|
9726
|
-
const st = (0,
|
|
10123
|
+
const st = (0, import_node_fs22.statSync)(abs);
|
|
9727
10124
|
if (!st.isFile()) continue;
|
|
9728
|
-
const buf = (0,
|
|
10125
|
+
const buf = (0, import_node_fs22.readFileSync)(abs);
|
|
9729
10126
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
9730
10127
|
} catch (err) {
|
|
9731
10128
|
out.push({
|
|
@@ -10213,7 +10610,7 @@ async function confirmLand(thread, opts) {
|
|
|
10213
10610
|
}
|
|
10214
10611
|
|
|
10215
10612
|
// src/threads/create.ts
|
|
10216
|
-
var
|
|
10613
|
+
var import_node_fs23 = require("fs");
|
|
10217
10614
|
init_worktree();
|
|
10218
10615
|
init_app_settings();
|
|
10219
10616
|
init_thread_store();
|
|
@@ -10227,7 +10624,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
10227
10624
|
});
|
|
10228
10625
|
await requireAgent(resolved.agent);
|
|
10229
10626
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
10230
|
-
if (!(0,
|
|
10627
|
+
if (!(0, import_node_fs23.existsSync)(repoPath)) {
|
|
10231
10628
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
10232
10629
|
}
|
|
10233
10630
|
let sourceRef = input.sourceRef;
|
|
@@ -10454,7 +10851,7 @@ async function forkThreadWorktree(input, onSetupLine) {
|
|
|
10454
10851
|
}
|
|
10455
10852
|
|
|
10456
10853
|
// src/threads/stack-layers.ts
|
|
10457
|
-
var
|
|
10854
|
+
var import_node_fs24 = require("fs");
|
|
10458
10855
|
init_run();
|
|
10459
10856
|
init_stack();
|
|
10460
10857
|
init_worktree();
|
|
@@ -10522,7 +10919,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
10522
10919
|
let createdWorktree = false;
|
|
10523
10920
|
const trees = await listWorktrees(repoPath);
|
|
10524
10921
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
10525
|
-
if (checkedOut?.path && (0,
|
|
10922
|
+
if (checkedOut?.path && (0, import_node_fs24.existsSync)(checkedOut.path)) {
|
|
10526
10923
|
if (input.reuseExistingWorktree !== false) {
|
|
10527
10924
|
worktreePath = checkedOut.path;
|
|
10528
10925
|
} else {
|
|
@@ -10664,7 +11061,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
10664
11061
|
async function createPrStack(input, onSetupLine) {
|
|
10665
11062
|
await requireAgent(input.agent);
|
|
10666
11063
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
10667
|
-
if (!(0,
|
|
11064
|
+
if (!(0, import_node_fs24.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
10668
11065
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
10669
11066
|
const status = await detectGhStack(repoPath);
|
|
10670
11067
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -10731,7 +11128,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
10731
11128
|
}
|
|
10732
11129
|
}
|
|
10733
11130
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
10734
|
-
if (!claimed.has(bootstrap.worktreePath) && (0,
|
|
11131
|
+
if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs24.existsSync)(bootstrap.worktreePath)) {
|
|
10735
11132
|
try {
|
|
10736
11133
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
10737
11134
|
deleteBranch: bootstrap.branchName
|
|
@@ -10753,8 +11150,8 @@ function stackAgentDefaultsFrom(input) {
|
|
|
10753
11150
|
}
|
|
10754
11151
|
|
|
10755
11152
|
// src/threads/adopt.ts
|
|
10756
|
-
var
|
|
10757
|
-
var
|
|
11153
|
+
var import_node_child_process2 = require("child_process");
|
|
11154
|
+
var import_node_fs25 = require("fs");
|
|
10758
11155
|
var import_node_os9 = require("os");
|
|
10759
11156
|
var import_node_path20 = require("path");
|
|
10760
11157
|
var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
@@ -10779,21 +11176,21 @@ function mapAgentType(raw) {
|
|
|
10779
11176
|
return null;
|
|
10780
11177
|
}
|
|
10781
11178
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
10782
|
-
if (!workspacePath || !(0,
|
|
11179
|
+
if (!workspacePath || !(0, import_node_fs25.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
10783
11180
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
10784
11181
|
let best = null;
|
|
10785
11182
|
let hashes;
|
|
10786
11183
|
try {
|
|
10787
|
-
hashes = (0,
|
|
11184
|
+
hashes = (0, import_node_fs25.readdirSync)(CURSOR_SDK_STORE);
|
|
10788
11185
|
} catch {
|
|
10789
11186
|
return null;
|
|
10790
11187
|
}
|
|
10791
11188
|
for (const hash of hashes) {
|
|
10792
11189
|
const agentsFile = (0, import_node_path20.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
10793
|
-
if (!(0,
|
|
11190
|
+
if (!(0, import_node_fs25.existsSync)(agentsFile)) continue;
|
|
10794
11191
|
let text;
|
|
10795
11192
|
try {
|
|
10796
|
-
text = (0,
|
|
11193
|
+
text = (0, import_node_fs25.readFileSync)(agentsFile, "utf8");
|
|
10797
11194
|
} catch {
|
|
10798
11195
|
continue;
|
|
10799
11196
|
}
|
|
@@ -10817,7 +11214,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
10817
11214
|
return best?.agentId ?? null;
|
|
10818
11215
|
}
|
|
10819
11216
|
async function adoptThread(input) {
|
|
10820
|
-
if (!(0,
|
|
11217
|
+
if (!(0, import_node_fs25.existsSync)(input.worktreePath)) {
|
|
10821
11218
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
10822
11219
|
}
|
|
10823
11220
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -10844,18 +11241,18 @@ function conductorDbPath() {
|
|
|
10844
11241
|
return CONDUCTOR_DB;
|
|
10845
11242
|
}
|
|
10846
11243
|
function listConductorWorkspaces() {
|
|
10847
|
-
if (!(0,
|
|
11244
|
+
if (!(0, import_node_fs25.existsSync)(CONDUCTOR_DB)) {
|
|
10848
11245
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
10849
11246
|
}
|
|
10850
|
-
const tmp = (0,
|
|
11247
|
+
const tmp = (0, import_node_fs25.mkdtempSync)((0, import_node_path20.join)((0, import_node_os9.tmpdir)(), "sideboard-conductor-"));
|
|
10851
11248
|
const snapshot = (0, import_node_path20.join)(tmp, "conductor.db");
|
|
10852
11249
|
try {
|
|
10853
|
-
(0,
|
|
11250
|
+
(0, import_node_fs25.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
10854
11251
|
for (const suffix of ["-wal", "-shm"]) {
|
|
10855
11252
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
10856
|
-
if ((0,
|
|
11253
|
+
if ((0, import_node_fs25.existsSync)(src)) {
|
|
10857
11254
|
try {
|
|
10858
|
-
(0,
|
|
11255
|
+
(0, import_node_fs25.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
10859
11256
|
} catch {
|
|
10860
11257
|
}
|
|
10861
11258
|
}
|
|
@@ -10931,22 +11328,22 @@ function listConductorWorkspaces() {
|
|
|
10931
11328
|
db.close();
|
|
10932
11329
|
}
|
|
10933
11330
|
} finally {
|
|
10934
|
-
(0,
|
|
11331
|
+
(0, import_node_fs25.rmSync)(tmp, { recursive: true, force: true });
|
|
10935
11332
|
}
|
|
10936
11333
|
}
|
|
10937
11334
|
function importConductorWorkspace(workspaceId) {
|
|
10938
|
-
if (!(0,
|
|
11335
|
+
if (!(0, import_node_fs25.existsSync)(CONDUCTOR_DB)) {
|
|
10939
11336
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
10940
11337
|
}
|
|
10941
|
-
const tmp = (0,
|
|
11338
|
+
const tmp = (0, import_node_fs25.mkdtempSync)((0, import_node_path20.join)((0, import_node_os9.tmpdir)(), "sideboard-conductor-"));
|
|
10942
11339
|
const snapshot = (0, import_node_path20.join)(tmp, "conductor.db");
|
|
10943
11340
|
try {
|
|
10944
|
-
(0,
|
|
11341
|
+
(0, import_node_fs25.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
10945
11342
|
for (const suffix of ["-wal", "-shm"]) {
|
|
10946
11343
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
10947
|
-
if ((0,
|
|
11344
|
+
if ((0, import_node_fs25.existsSync)(src)) {
|
|
10948
11345
|
try {
|
|
10949
|
-
(0,
|
|
11346
|
+
(0, import_node_fs25.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
10950
11347
|
} catch {
|
|
10951
11348
|
}
|
|
10952
11349
|
}
|
|
@@ -10964,7 +11361,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
10964
11361
|
).get(workspaceId);
|
|
10965
11362
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
10966
11363
|
const worktreePath = String(row.workspacePath);
|
|
10967
|
-
if (!(0,
|
|
11364
|
+
if (!(0, import_node_fs25.existsSync)(worktreePath)) {
|
|
10968
11365
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
10969
11366
|
}
|
|
10970
11367
|
let sessionId = null;
|
|
@@ -11004,7 +11401,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
11004
11401
|
}
|
|
11005
11402
|
let repoPath = worktreePath;
|
|
11006
11403
|
try {
|
|
11007
|
-
repoPath = (0,
|
|
11404
|
+
repoPath = (0, import_node_child_process2.execFileSync)("git", ["rev-parse", "--show-toplevel"], {
|
|
11008
11405
|
cwd: worktreePath,
|
|
11009
11406
|
encoding: "utf8"
|
|
11010
11407
|
}).trim();
|
|
@@ -11027,7 +11424,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
11027
11424
|
db.close();
|
|
11028
11425
|
}
|
|
11029
11426
|
} finally {
|
|
11030
|
-
(0,
|
|
11427
|
+
(0, import_node_fs25.rmSync)(tmp, { recursive: true, force: true });
|
|
11031
11428
|
}
|
|
11032
11429
|
}
|
|
11033
11430
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
@@ -11036,7 +11433,7 @@ async function importConductorWorkspaceAsync(workspaceId) {
|
|
|
11036
11433
|
|
|
11037
11434
|
// src/orchestrator/orchestrator.ts
|
|
11038
11435
|
var import_node_events = require("events");
|
|
11039
|
-
var
|
|
11436
|
+
var import_node_fs31 = require("fs");
|
|
11040
11437
|
init_error_detail();
|
|
11041
11438
|
init_agents();
|
|
11042
11439
|
init_worktree();
|
|
@@ -11057,7 +11454,7 @@ function shouldAutoArchiveOnPrMerge(opts) {
|
|
|
11057
11454
|
}
|
|
11058
11455
|
|
|
11059
11456
|
// src/git/orphan-cleanup.ts
|
|
11060
|
-
var
|
|
11457
|
+
var import_node_fs26 = require("fs");
|
|
11061
11458
|
var import_node_path21 = require("path");
|
|
11062
11459
|
init_worktree();
|
|
11063
11460
|
init_thread_store();
|
|
@@ -11073,9 +11470,9 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11073
11470
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
11074
11471
|
);
|
|
11075
11472
|
const homeRoot = sideboardWorkspacesDir();
|
|
11076
|
-
if ((0,
|
|
11473
|
+
if ((0, import_node_fs26.existsSync)(homeRoot)) {
|
|
11077
11474
|
try {
|
|
11078
|
-
for (const entry of (0,
|
|
11475
|
+
for (const entry of (0, import_node_fs26.readdirSync)(homeRoot, { withFileTypes: true })) {
|
|
11079
11476
|
if (!entry.isDirectory()) continue;
|
|
11080
11477
|
void entry;
|
|
11081
11478
|
}
|
|
@@ -11085,7 +11482,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11085
11482
|
const orphans = [];
|
|
11086
11483
|
const seen = /* @__PURE__ */ new Set();
|
|
11087
11484
|
for (const repoPath of repos) {
|
|
11088
|
-
if (!repoPath || !(0,
|
|
11485
|
+
if (!repoPath || !(0, import_node_fs26.existsSync)(repoPath)) continue;
|
|
11089
11486
|
try {
|
|
11090
11487
|
const wts = await listWorktrees(repoPath);
|
|
11091
11488
|
for (const wt of wts) {
|
|
@@ -11096,7 +11493,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11096
11493
|
seen.add(path);
|
|
11097
11494
|
let mtimeMs = 0;
|
|
11098
11495
|
try {
|
|
11099
|
-
mtimeMs = (0,
|
|
11496
|
+
mtimeMs = (0, import_node_fs26.statSync)(path).mtimeMs;
|
|
11100
11497
|
} catch {
|
|
11101
11498
|
mtimeMs = 0;
|
|
11102
11499
|
}
|
|
@@ -11106,16 +11503,16 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11106
11503
|
}
|
|
11107
11504
|
try {
|
|
11108
11505
|
const root = worktreesRoot(repoPath);
|
|
11109
|
-
if ((0,
|
|
11110
|
-
for (const entry of (0,
|
|
11506
|
+
if ((0, import_node_fs26.existsSync)(root)) {
|
|
11507
|
+
for (const entry of (0, import_node_fs26.readdirSync)(root, { withFileTypes: true })) {
|
|
11111
11508
|
if (!entry.isDirectory()) continue;
|
|
11112
11509
|
const path = (0, import_node_path21.join)(root, entry.name).replace(/\/$/, "");
|
|
11113
11510
|
if (known.has(path) || seen.has(path)) continue;
|
|
11114
|
-
if (!(0,
|
|
11511
|
+
if (!(0, import_node_fs26.existsSync)((0, import_node_path21.join)(path, ".git"))) continue;
|
|
11115
11512
|
seen.add(path);
|
|
11116
11513
|
let mtimeMs = 0;
|
|
11117
11514
|
try {
|
|
11118
|
-
mtimeMs = (0,
|
|
11515
|
+
mtimeMs = (0, import_node_fs26.statSync)(path).mtimeMs;
|
|
11119
11516
|
} catch {
|
|
11120
11517
|
mtimeMs = Date.now();
|
|
11121
11518
|
}
|
|
@@ -11261,7 +11658,7 @@ async function applyThreadIntoMain(thread, opts) {
|
|
|
11261
11658
|
}
|
|
11262
11659
|
|
|
11263
11660
|
// src/git/clone-repo.ts
|
|
11264
|
-
var
|
|
11661
|
+
var import_node_fs27 = require("fs");
|
|
11265
11662
|
var import_node_path22 = require("path");
|
|
11266
11663
|
var import_execa6 = require("execa");
|
|
11267
11664
|
init_paths();
|
|
@@ -11277,7 +11674,7 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
11277
11674
|
}
|
|
11278
11675
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
11279
11676
|
const dest = (0, import_node_path22.join)(sideboardReposDir(), name);
|
|
11280
|
-
if ((0,
|
|
11677
|
+
if ((0, import_node_fs27.existsSync)(dest)) {
|
|
11281
11678
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
11282
11679
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
11283
11680
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -11299,7 +11696,7 @@ init_orchestrator_capable();
|
|
|
11299
11696
|
|
|
11300
11697
|
// src/review/request-review.ts
|
|
11301
11698
|
var import_node_crypto5 = require("crypto");
|
|
11302
|
-
var
|
|
11699
|
+
var import_node_fs28 = require("fs");
|
|
11303
11700
|
var import_node_path23 = require("path");
|
|
11304
11701
|
init_global_workspace();
|
|
11305
11702
|
init_thread_store();
|
|
@@ -11444,9 +11841,9 @@ function shouldRefreshReviewRequestTemplate(content) {
|
|
|
11444
11841
|
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
11445
11842
|
}
|
|
11446
11843
|
function readTextIfPresent(abs) {
|
|
11447
|
-
if (!(0,
|
|
11844
|
+
if (!(0, import_node_fs28.existsSync)(abs)) return null;
|
|
11448
11845
|
try {
|
|
11449
|
-
const content = (0,
|
|
11846
|
+
const content = (0, import_node_fs28.readFileSync)(abs, "utf8");
|
|
11450
11847
|
return content.trim() ? content : null;
|
|
11451
11848
|
} catch {
|
|
11452
11849
|
return null;
|
|
@@ -11454,9 +11851,9 @@ function readTextIfPresent(abs) {
|
|
|
11454
11851
|
}
|
|
11455
11852
|
function ensureAttachmentsGitignore(worktreePath) {
|
|
11456
11853
|
const gitignoreAbs = (0, import_node_path23.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
11457
|
-
if ((0,
|
|
11458
|
-
(0,
|
|
11459
|
-
(0,
|
|
11854
|
+
if ((0, import_node_fs28.existsSync)(gitignoreAbs)) return;
|
|
11855
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path23.dirname)(gitignoreAbs), { recursive: true });
|
|
11856
|
+
(0, import_node_fs28.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
11460
11857
|
}
|
|
11461
11858
|
function resolveReviewGuidelines(worktreePath) {
|
|
11462
11859
|
const repoAbs = (0, import_node_path23.join)(worktreePath, REPO_REVIEW_PATH);
|
|
@@ -11490,8 +11887,8 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
11490
11887
|
};
|
|
11491
11888
|
}
|
|
11492
11889
|
ensureAttachmentsGitignore(worktreePath);
|
|
11493
|
-
(0,
|
|
11494
|
-
(0,
|
|
11890
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path23.dirname)(localAbs), { recursive: true });
|
|
11891
|
+
(0, import_node_fs28.writeFileSync)(localAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
|
|
11495
11892
|
return {
|
|
11496
11893
|
path: REVIEW_REQUEST_PATH,
|
|
11497
11894
|
name: REVIEW_REQUEST_NAME,
|
|
@@ -11513,7 +11910,7 @@ function ensureReviewRequestFile(worktreePath) {
|
|
|
11513
11910
|
const localAbs = (0, import_node_path23.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
11514
11911
|
const localContent = readTextIfPresent(localAbs) ?? readTextIfPresent((0, import_node_path23.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
|
|
11515
11912
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
11516
|
-
const path = (0,
|
|
11913
|
+
const path = (0, import_node_fs28.existsSync)(localAbs) ? REVIEW_REQUEST_PATH : LEGACY_REVIEW_REQUEST_PATH;
|
|
11517
11914
|
return {
|
|
11518
11915
|
path,
|
|
11519
11916
|
name: REVIEW_REQUEST_NAME,
|
|
@@ -11521,8 +11918,8 @@ function ensureReviewRequestFile(worktreePath) {
|
|
|
11521
11918
|
source: "local"
|
|
11522
11919
|
};
|
|
11523
11920
|
}
|
|
11524
|
-
(0,
|
|
11525
|
-
(0,
|
|
11921
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path23.dirname)(repoAbs), { recursive: true });
|
|
11922
|
+
(0, import_node_fs28.writeFileSync)(repoAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
|
|
11526
11923
|
return {
|
|
11527
11924
|
path: REPO_REVIEW_PATH,
|
|
11528
11925
|
name: REPO_REVIEW_NAME,
|
|
@@ -11802,7 +12199,7 @@ var Orchestrator = class {
|
|
|
11802
12199
|
}
|
|
11803
12200
|
continue;
|
|
11804
12201
|
}
|
|
11805
|
-
if (!(0,
|
|
12202
|
+
if (!(0, import_node_fs31.existsSync)(thread.worktreePath)) {
|
|
11806
12203
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
11807
12204
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
11808
12205
|
continue;
|
|
@@ -12219,13 +12616,14 @@ var Orchestrator = class {
|
|
|
12219
12616
|
"Files column: MCP present_files (brightsy account storage or memory).",
|
|
12220
12617
|
"Do not say artifacts/CMS UI are unavailable."
|
|
12221
12618
|
].join(" ") : null;
|
|
12619
|
+
const worktreeReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatWorktreeReminder() : null;
|
|
12222
12620
|
const agentPrompt = [
|
|
12223
12621
|
thread.planMode ? PLAN_MODE_INSTRUCTION : null,
|
|
12224
12622
|
orchestrationReminder,
|
|
12623
|
+
worktreeReminder,
|
|
12225
12624
|
artifactReminder,
|
|
12226
12625
|
expandedPrompt
|
|
12227
12626
|
].filter(Boolean).join("\n\n");
|
|
12228
|
-
const instructionFiles = loadAgentInstructions(thread.worktreePath, thread.agent);
|
|
12229
12627
|
if (thread.attachments.length > 0) {
|
|
12230
12628
|
updateThread(threadId, { attachments: [] });
|
|
12231
12629
|
}
|
|
@@ -12253,7 +12651,6 @@ var Orchestrator = class {
|
|
|
12253
12651
|
const renameBranchDirective = !isBrightsy && !isOrchestration && autoRenameBranchEnabled2() ? formatRenameBranchDirective(fresh, {
|
|
12254
12652
|
customPrompt: settings?.prompts?.renameBranch
|
|
12255
12653
|
}) : null;
|
|
12256
|
-
const instructions = fresh.agent === "claude" || isBrightsy ? null : formatAgentInstructions(instructionFiles);
|
|
12257
12654
|
let seed = null;
|
|
12258
12655
|
if (!fresh.sessionId) {
|
|
12259
12656
|
const prior = fresh.messages.slice(0, -1);
|
|
@@ -12274,12 +12671,12 @@ var Orchestrator = class {
|
|
|
12274
12671
|
});
|
|
12275
12672
|
}
|
|
12276
12673
|
}
|
|
12277
|
-
const cachedPrefix = [
|
|
12674
|
+
const cachedPrefix = fresh.sessionId ? "" : [
|
|
12278
12675
|
coordinatorDirective,
|
|
12279
12676
|
worktreeDirective,
|
|
12280
12677
|
artifactDirective,
|
|
12281
12678
|
renameBranchDirective,
|
|
12282
|
-
|
|
12679
|
+
seed
|
|
12283
12680
|
].filter(Boolean).join("\n\n---\n\n");
|
|
12284
12681
|
try {
|
|
12285
12682
|
const stderrTail = [];
|
|
@@ -12366,15 +12763,11 @@ var Orchestrator = class {
|
|
|
12366
12763
|
const retryThread = this.requireThread(threadId);
|
|
12367
12764
|
const prior = retryThread.messages.slice(0, -1);
|
|
12368
12765
|
const retrySeed = buildSessionSeed(prior);
|
|
12369
|
-
const retryInstructions = retryThread.agent === "claude" ? null : formatAgentInstructions(
|
|
12370
|
-
loadAgentInstructions(retryThread.worktreePath, retryThread.agent)
|
|
12371
|
-
);
|
|
12372
12766
|
const retryPrefix = [
|
|
12373
12767
|
coordinatorDirective,
|
|
12374
12768
|
worktreeDirective,
|
|
12375
12769
|
artifactDirective,
|
|
12376
12770
|
renameBranchDirective,
|
|
12377
|
-
retryInstructions,
|
|
12378
12771
|
retrySeed
|
|
12379
12772
|
].filter(Boolean).join("\n\n---\n\n");
|
|
12380
12773
|
const retryHandle = await spawnAgentTurn(
|
|
@@ -13209,7 +13602,7 @@ var Orchestrator = class {
|
|
|
13209
13602
|
this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
|
|
13210
13603
|
return restored2;
|
|
13211
13604
|
}
|
|
13212
|
-
if (!(0,
|
|
13605
|
+
if (!(0, import_node_fs31.existsSync)(thread.worktreePath)) {
|
|
13213
13606
|
const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
|
|
13214
13607
|
const { execa: execa7 } = await import("execa");
|
|
13215
13608
|
const slug = thread.worktreePath.split("/").pop();
|
|
@@ -13465,6 +13858,7 @@ function mcpArchiveBlockedReason(thread) {
|
|
|
13465
13858
|
}
|
|
13466
13859
|
|
|
13467
13860
|
// src/mcp/server.ts
|
|
13861
|
+
init_profile();
|
|
13468
13862
|
var MAX_ORCH_THREADS = 5;
|
|
13469
13863
|
var CREATE_THREAD_TIMEOUT_MS = 9e4;
|
|
13470
13864
|
function withTimeout(promise, ms, label) {
|
|
@@ -13578,14 +13972,13 @@ async function startMcpServer() {
|
|
|
13578
13972
|
),
|
|
13579
13973
|
artifact_id: import_zod.z.string().optional().describe("Stable id when updating the same artifact across turns")
|
|
13580
13974
|
},
|
|
13581
|
-
async ({ title, type,
|
|
13975
|
+
async ({ title, type, artifact_id }) => {
|
|
13582
13976
|
const id = artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
13583
13977
|
const payload = {
|
|
13584
13978
|
ok: true,
|
|
13585
13979
|
artifact_id: id,
|
|
13586
13980
|
title,
|
|
13587
13981
|
type,
|
|
13588
|
-
content,
|
|
13589
13982
|
message: "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
|
|
13590
13983
|
};
|
|
13591
13984
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
@@ -13638,7 +14031,6 @@ async function startMcpServer() {
|
|
|
13638
14031
|
ok: true,
|
|
13639
14032
|
path,
|
|
13640
14033
|
title: title?.trim() || "Plan",
|
|
13641
|
-
content,
|
|
13642
14034
|
message: "Plan saved to .context/attachments/plan.md and shown in Sideboard chat for approval."
|
|
13643
14035
|
};
|
|
13644
14036
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
@@ -13668,9 +14060,6 @@ async function startMcpServer() {
|
|
|
13668
14060
|
datasource: args.datasource ?? (args.resource ? "inline" : "brightsy"),
|
|
13669
14061
|
resource_id: args.resource_id,
|
|
13670
14062
|
record_id: args.record_id,
|
|
13671
|
-
resource: args.resource,
|
|
13672
|
-
record: args.record,
|
|
13673
|
-
records: args.records,
|
|
13674
14063
|
message: "Schema pane accepted. Sideboard desktop opens the CMS column beside chat."
|
|
13675
14064
|
};
|
|
13676
14065
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
@@ -13698,744 +14087,747 @@ async function startMcpServer() {
|
|
|
13698
14087
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
13699
14088
|
}
|
|
13700
14089
|
);
|
|
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
|
-
|
|
14090
|
+
if (sideboardMcpProfile() !== "worktree") {
|
|
14091
|
+
const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
14092
|
+
const accountDefaults = resolveThreadDefaults2();
|
|
14093
|
+
const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
|
|
14094
|
+
server.tool(
|
|
14095
|
+
"create_thread",
|
|
14096
|
+
`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.`,
|
|
14097
|
+
{
|
|
14098
|
+
sourceType: import_zod.z.enum(["branch", "pr", "ticket"]),
|
|
14099
|
+
sourceRef: import_zod.z.string(),
|
|
14100
|
+
agent: import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]).optional().describe(`Omit to use Account default agent (${accountDefaults.agent})`),
|
|
14101
|
+
model: import_zod.z.string().nullable().optional().describe(
|
|
14102
|
+
`Usually omit to use Account default model (${accountDefaults.model?.trim() || "Auto"}). Pass null only to force Auto / agent-default.`
|
|
14103
|
+
),
|
|
14104
|
+
repoPath: import_zod.z.string(),
|
|
14105
|
+
title: import_zod.z.string().optional(),
|
|
14106
|
+
parentThreadId: import_zod.z.string().optional().describe(
|
|
14107
|
+
"Orchestration: omit (preferred) or pass YOUR chat id from the turn reminder / AGENTS.md. Do not invent uuids."
|
|
14108
|
+
)
|
|
14109
|
+
},
|
|
14110
|
+
async (args) => {
|
|
14111
|
+
const envParentId = process.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID?.trim() || "";
|
|
14112
|
+
let parentId = args.parentThreadId?.trim() || "";
|
|
14113
|
+
let parent = parentId ? orch.getThread(parentId) : null;
|
|
14114
|
+
let parentCorrectedFrom;
|
|
14115
|
+
if (envParentId) {
|
|
14116
|
+
const envParent = orch.getThread(envParentId);
|
|
14117
|
+
if (envParent) {
|
|
14118
|
+
if (parentId && parentId !== envParentId) parentCorrectedFrom = parentId;
|
|
14119
|
+
else if (!parentId) parentCorrectedFrom = void 0;
|
|
14120
|
+
parentId = envParentId;
|
|
14121
|
+
parent = envParent;
|
|
14122
|
+
}
|
|
13732
14123
|
}
|
|
13733
|
-
|
|
13734
|
-
|
|
13735
|
-
|
|
13736
|
-
|
|
13737
|
-
|
|
13738
|
-
|
|
13739
|
-
|
|
13740
|
-
|
|
13741
|
-
|
|
13742
|
-
|
|
13743
|
-
|
|
13744
|
-
|
|
13745
|
-
|
|
13746
|
-
|
|
13747
|
-
|
|
13748
|
-
|
|
13749
|
-
|
|
14124
|
+
if (parentId && !parent) {
|
|
14125
|
+
parentCorrectedFrom = parentId;
|
|
14126
|
+
parentId = "";
|
|
14127
|
+
parent = null;
|
|
14128
|
+
}
|
|
14129
|
+
if (parentId) {
|
|
14130
|
+
const children = orch.getThreads(false).filter((t) => t.parentThreadId === parentId);
|
|
14131
|
+
if (children.length >= MAX_ORCH_THREADS) {
|
|
14132
|
+
return {
|
|
14133
|
+
content: [
|
|
14134
|
+
{
|
|
14135
|
+
type: "text",
|
|
14136
|
+
text: `Thread-creation cap (${MAX_ORCH_THREADS}) reached for this orchestration session`
|
|
14137
|
+
}
|
|
14138
|
+
],
|
|
14139
|
+
isError: true
|
|
14140
|
+
};
|
|
14141
|
+
}
|
|
14142
|
+
}
|
|
14143
|
+
let agentArg = args.agent;
|
|
14144
|
+
let agentCoercedFrom;
|
|
14145
|
+
const resolvedProbe = resolveNewThreadOptions2({ agent: agentArg }).agent;
|
|
14146
|
+
if (resolvedProbe === "codex") {
|
|
14147
|
+
agentCoercedFrom = agentArg ?? "codex";
|
|
14148
|
+
const accountAgent = resolveNewThreadOptions2({}).agent;
|
|
14149
|
+
agentArg = accountAgent !== "codex" ? accountAgent : "cursor";
|
|
14150
|
+
}
|
|
14151
|
+
const opts = resolveNewThreadOptions2({
|
|
14152
|
+
agent: agentArg,
|
|
14153
|
+
model: args.model
|
|
14154
|
+
});
|
|
14155
|
+
try {
|
|
14156
|
+
const thread = await withTimeout(
|
|
14157
|
+
orch.createThread({
|
|
14158
|
+
sourceType: args.sourceType,
|
|
14159
|
+
sourceRef: args.sourceRef,
|
|
14160
|
+
agent: opts.agent,
|
|
14161
|
+
model: opts.model,
|
|
14162
|
+
effort: opts.effort,
|
|
14163
|
+
fast: opts.fast,
|
|
14164
|
+
repoPath: args.repoPath,
|
|
14165
|
+
title: args.title,
|
|
14166
|
+
parentThreadId: parentId || null
|
|
14167
|
+
}),
|
|
14168
|
+
CREATE_THREAD_TIMEOUT_MS,
|
|
14169
|
+
"create_thread"
|
|
14170
|
+
);
|
|
14171
|
+
const parentNote = parentCorrectedFrom ? parentId ? `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; nested under ${parentId}` : `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; created without parent` : void 0;
|
|
14172
|
+
return {
|
|
14173
|
+
content: [
|
|
14174
|
+
{
|
|
14175
|
+
type: "text",
|
|
14176
|
+
text: JSON.stringify({
|
|
14177
|
+
id: thread.id,
|
|
14178
|
+
title: thread.title,
|
|
14179
|
+
branchName: thread.branchName,
|
|
14180
|
+
worktreePath: thread.worktreePath,
|
|
14181
|
+
agent: thread.agent,
|
|
14182
|
+
model: thread.model,
|
|
14183
|
+
status: thread.status,
|
|
14184
|
+
link: `sideboard://thread/${thread.id}`,
|
|
14185
|
+
parentThreadId: thread.parentThreadId,
|
|
14186
|
+
...agentCoercedFrom ? {
|
|
14187
|
+
agentCoercedFrom,
|
|
14188
|
+
note: `Avoid nested Codex under a Codex orchestrator \u2014 used Account default agent=${thread.agent}`
|
|
14189
|
+
} : {},
|
|
14190
|
+
...parentCorrectedFrom ? { parentCorrectedFrom, parentNote } : {}
|
|
14191
|
+
})
|
|
14192
|
+
}
|
|
14193
|
+
]
|
|
14194
|
+
};
|
|
14195
|
+
} catch (err) {
|
|
14196
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14197
|
+
return {
|
|
14198
|
+
content: [
|
|
14199
|
+
{
|
|
14200
|
+
type: "text",
|
|
14201
|
+
text: `create_thread failed: ${message}`
|
|
14202
|
+
}
|
|
14203
|
+
],
|
|
14204
|
+
isError: true
|
|
13750
14205
|
};
|
|
13751
14206
|
}
|
|
13752
14207
|
}
|
|
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;
|
|
14208
|
+
);
|
|
14209
|
+
server.tool(
|
|
14210
|
+
"send_to_thread",
|
|
14211
|
+
"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.",
|
|
14212
|
+
{
|
|
14213
|
+
ref: import_zod.z.string(),
|
|
14214
|
+
prompt: import_zod.z.string(),
|
|
14215
|
+
force_stop: import_zod.z.boolean().optional()
|
|
14216
|
+
},
|
|
14217
|
+
async ({ ref, prompt, force_stop }) => {
|
|
14218
|
+
if (force_stop) {
|
|
14219
|
+
const existing = orch.getThread(ref);
|
|
14220
|
+
if (existing) {
|
|
14221
|
+
orch.stop(ref, { clearQueue: true });
|
|
14222
|
+
}
|
|
14223
|
+
}
|
|
14224
|
+
const thread = await orch.send(ref, prompt);
|
|
13782
14225
|
return {
|
|
13783
14226
|
content: [
|
|
13784
14227
|
{
|
|
13785
14228
|
type: "text",
|
|
13786
14229
|
text: JSON.stringify({
|
|
13787
14230
|
id: thread.id,
|
|
13788
|
-
title: thread.title,
|
|
13789
|
-
branchName: thread.branchName,
|
|
13790
|
-
worktreePath: thread.worktreePath,
|
|
13791
|
-
agent: thread.agent,
|
|
13792
|
-
model: thread.model,
|
|
13793
14231
|
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 } : {}
|
|
14232
|
+
queueLength: thread.queue.length,
|
|
14233
|
+
forceStopped: Boolean(force_stop)
|
|
13801
14234
|
})
|
|
13802
14235
|
}
|
|
13803
14236
|
]
|
|
13804
14237
|
};
|
|
13805
|
-
}
|
|
13806
|
-
|
|
14238
|
+
}
|
|
14239
|
+
);
|
|
14240
|
+
server.tool(
|
|
14241
|
+
"wait_for_turn",
|
|
14242
|
+
"Block until the thread finishes its current/queued turn (avoids polling). Use after send_to_thread to read the agent reply.",
|
|
14243
|
+
{
|
|
14244
|
+
ref: import_zod.z.string(),
|
|
14245
|
+
timeoutMs: import_zod.z.number().optional()
|
|
14246
|
+
},
|
|
14247
|
+
async ({ ref, timeoutMs }) => {
|
|
14248
|
+
const thread = await orch.waitForTurn(ref, timeoutMs ?? 6e5);
|
|
14249
|
+
const result = orch.getTurnResult(thread.id);
|
|
13807
14250
|
return {
|
|
13808
14251
|
content: [
|
|
13809
14252
|
{
|
|
13810
14253
|
type: "text",
|
|
13811
|
-
text:
|
|
14254
|
+
text: JSON.stringify({
|
|
14255
|
+
id: thread.id,
|
|
14256
|
+
status: result.status,
|
|
14257
|
+
text: result.text
|
|
14258
|
+
})
|
|
13812
14259
|
}
|
|
13813
|
-
]
|
|
13814
|
-
isError: true
|
|
14260
|
+
]
|
|
13815
14261
|
};
|
|
13816
14262
|
}
|
|
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
|
-
}
|
|
14263
|
+
);
|
|
14264
|
+
server.tool(
|
|
14265
|
+
"get_turn_result",
|
|
14266
|
+
"Final assistant message only (not full transcript)",
|
|
14267
|
+
{ ref: import_zod.z.string() },
|
|
14268
|
+
async ({ ref }) => {
|
|
14269
|
+
const result = orch.getTurnResult(ref);
|
|
14270
|
+
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
13833
14271
|
}
|
|
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) {
|
|
14272
|
+
);
|
|
14273
|
+
server.tool(
|
|
14274
|
+
"stop_thread",
|
|
14275
|
+
"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.",
|
|
14276
|
+
{
|
|
14277
|
+
ref: import_zod.z.string(),
|
|
14278
|
+
force: import_zod.z.boolean().optional()
|
|
14279
|
+
},
|
|
14280
|
+
async ({ ref, force }) => {
|
|
14281
|
+
const t = orch.getThread(ref);
|
|
14282
|
+
if (!t) {
|
|
14283
|
+
return {
|
|
14284
|
+
content: [{ type: "text", text: `Thread not found: ${ref}` }],
|
|
14285
|
+
isError: true
|
|
14286
|
+
};
|
|
14287
|
+
}
|
|
14288
|
+
const clearQueue = force !== false;
|
|
14289
|
+
const hadQueued = t.queue.length > 0;
|
|
14290
|
+
const stopped = orch.stop(ref, { clearQueue });
|
|
13893
14291
|
return {
|
|
13894
|
-
content: [
|
|
13895
|
-
|
|
14292
|
+
content: [
|
|
14293
|
+
{
|
|
14294
|
+
type: "text",
|
|
14295
|
+
text: JSON.stringify({
|
|
14296
|
+
id: stopped.id,
|
|
14297
|
+
status: stopped.status,
|
|
14298
|
+
clearedQueue: clearQueue && hadQueued
|
|
14299
|
+
})
|
|
14300
|
+
}
|
|
14301
|
+
]
|
|
13896
14302
|
};
|
|
13897
14303
|
}
|
|
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) {
|
|
14304
|
+
);
|
|
14305
|
+
server.tool(
|
|
14306
|
+
"archive_thread",
|
|
14307
|
+
"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.",
|
|
14308
|
+
{ ref: import_zod.z.string() },
|
|
14309
|
+
async ({ ref }) => {
|
|
14310
|
+
const t = orch.getThread(ref);
|
|
14311
|
+
if (!t) {
|
|
14312
|
+
return {
|
|
14313
|
+
content: [{ type: "text", text: `Thread not found: ${ref}` }],
|
|
14314
|
+
isError: true
|
|
14315
|
+
};
|
|
14316
|
+
}
|
|
14317
|
+
const blocked = mcpArchiveBlockedReason(t);
|
|
14318
|
+
if (blocked) {
|
|
14319
|
+
return {
|
|
14320
|
+
content: [{ type: "text", text: blocked }],
|
|
14321
|
+
isError: true
|
|
14322
|
+
};
|
|
14323
|
+
}
|
|
14324
|
+
const archived = await orch.archive(ref);
|
|
13922
14325
|
return {
|
|
13923
|
-
content: [
|
|
13924
|
-
|
|
14326
|
+
content: [
|
|
14327
|
+
{
|
|
14328
|
+
type: "text",
|
|
14329
|
+
text: JSON.stringify({
|
|
14330
|
+
id: archived.id,
|
|
14331
|
+
status: archived.status
|
|
14332
|
+
})
|
|
14333
|
+
}
|
|
14334
|
+
]
|
|
13925
14335
|
};
|
|
13926
14336
|
}
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
14337
|
+
);
|
|
14338
|
+
server.tool(
|
|
14339
|
+
"restore_thread",
|
|
14340
|
+
"Restore an archived thread (recreates worktree from branch when needed)",
|
|
14341
|
+
{ ref: import_zod.z.string() },
|
|
14342
|
+
async ({ ref }) => {
|
|
14343
|
+
try {
|
|
14344
|
+
const restored = await orch.restore(ref);
|
|
14345
|
+
return {
|
|
14346
|
+
content: [
|
|
14347
|
+
{
|
|
14348
|
+
type: "text",
|
|
14349
|
+
text: JSON.stringify({
|
|
14350
|
+
id: restored.id,
|
|
14351
|
+
status: restored.status,
|
|
14352
|
+
worktreePath: restored.worktreePath
|
|
14353
|
+
})
|
|
14354
|
+
}
|
|
14355
|
+
]
|
|
14356
|
+
};
|
|
14357
|
+
} catch (err) {
|
|
14358
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14359
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14360
|
+
}
|
|
13933
14361
|
}
|
|
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);
|
|
14362
|
+
);
|
|
14363
|
+
server.tool(
|
|
14364
|
+
"get_diff",
|
|
14365
|
+
"Compact diff summary (capped hunks, paginated)",
|
|
14366
|
+
{
|
|
14367
|
+
ref: import_zod.z.string(),
|
|
14368
|
+
maxFiles: import_zod.z.number().optional()
|
|
14369
|
+
},
|
|
14370
|
+
async ({ ref, maxFiles }) => {
|
|
14371
|
+
const summary = await orch.diffSummary(ref);
|
|
13955
14372
|
return {
|
|
13956
14373
|
content: [
|
|
13957
14374
|
{
|
|
13958
14375
|
type: "text",
|
|
13959
14376
|
text: JSON.stringify({
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
worktreePath: restored.worktreePath
|
|
14377
|
+
...summary,
|
|
14378
|
+
files: summary.files.slice(0, maxFiles ?? 10)
|
|
13963
14379
|
})
|
|
13964
14380
|
}
|
|
13965
14381
|
]
|
|
13966
14382
|
};
|
|
13967
|
-
} catch (err) {
|
|
13968
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
13969
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
13970
14383
|
}
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
13974
|
-
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
13989
|
-
|
|
14384
|
+
);
|
|
14385
|
+
server.tool(
|
|
14386
|
+
"request_review",
|
|
14387
|
+
'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.',
|
|
14388
|
+
{ ref: import_zod.z.string().describe("Worktree thread id/ref to review") },
|
|
14389
|
+
async ({ ref }) => {
|
|
14390
|
+
try {
|
|
14391
|
+
const tab = await orch.requestReview(ref);
|
|
14392
|
+
const from = orch.getThread(ref);
|
|
14393
|
+
return {
|
|
14394
|
+
content: [
|
|
14395
|
+
{
|
|
14396
|
+
type: "text",
|
|
14397
|
+
text: JSON.stringify({
|
|
14398
|
+
id: tab.id,
|
|
14399
|
+
title: tab.title,
|
|
14400
|
+
status: tab.status,
|
|
14401
|
+
fromThreadId: from?.id ?? ref,
|
|
14402
|
+
link: `sideboard://thread/${tab.id}`
|
|
14403
|
+
})
|
|
14404
|
+
}
|
|
14405
|
+
]
|
|
14406
|
+
};
|
|
14407
|
+
} catch (err) {
|
|
14408
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14409
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14410
|
+
}
|
|
14411
|
+
}
|
|
14412
|
+
);
|
|
14413
|
+
const agentEnum = import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]);
|
|
14414
|
+
server.tool(
|
|
14415
|
+
"list_models",
|
|
14416
|
+
"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.",
|
|
14417
|
+
{
|
|
14418
|
+
agent: agentEnum.optional().describe("Limit to one agent; omit for all")
|
|
14419
|
+
},
|
|
14420
|
+
async ({ agent }) => {
|
|
14421
|
+
try {
|
|
14422
|
+
const catalogs = await listModelsForAgent(agent);
|
|
14423
|
+
return {
|
|
14424
|
+
content: [{ type: "text", text: JSON.stringify(catalogs, null, 2) }]
|
|
14425
|
+
};
|
|
14426
|
+
} catch (err) {
|
|
14427
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14428
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14429
|
+
}
|
|
14430
|
+
}
|
|
14431
|
+
);
|
|
14432
|
+
server.tool(
|
|
14433
|
+
"fork_worktree",
|
|
14434
|
+
"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.",
|
|
14435
|
+
{
|
|
14436
|
+
ref: import_zod.z.string().describe("Worktree thread id/ref to fork"),
|
|
14437
|
+
through_index: import_zod.z.number().optional().describe("Inclusive message index to include in the transcript (default: all)"),
|
|
14438
|
+
agent: agentEnum.optional().describe("Agent for the forked chat (default: same as source)"),
|
|
14439
|
+
model: import_zod.z.string().nullable().optional().describe("Usually omit (Auto). Only set from list_models when you need a specific model"),
|
|
14440
|
+
title: import_zod.z.string().optional()
|
|
14441
|
+
},
|
|
14442
|
+
async ({ ref, through_index, agent, model, title }) => {
|
|
14443
|
+
try {
|
|
14444
|
+
const source = orch.getThread(ref);
|
|
14445
|
+
if (source) await orch.reconcile(source.repoPath, { drainQueues: false });
|
|
14446
|
+
const thread = await orch.forkThreadWorktree({
|
|
14447
|
+
threadId: ref,
|
|
14448
|
+
throughIndex: through_index,
|
|
14449
|
+
agent,
|
|
14450
|
+
model,
|
|
14451
|
+
title
|
|
14452
|
+
});
|
|
14453
|
+
return {
|
|
14454
|
+
content: [
|
|
14455
|
+
{
|
|
14456
|
+
type: "text",
|
|
14457
|
+
text: JSON.stringify({
|
|
14458
|
+
id: thread.id,
|
|
14459
|
+
title: thread.title,
|
|
14460
|
+
status: thread.status,
|
|
14461
|
+
agent: thread.agent,
|
|
14462
|
+
model: thread.model,
|
|
14463
|
+
branchName: thread.branchName,
|
|
14464
|
+
worktreePath: thread.worktreePath,
|
|
14465
|
+
fromThreadId: source?.id ?? ref,
|
|
14466
|
+
link: `sideboard://thread/${thread.id}`
|
|
14467
|
+
})
|
|
14468
|
+
}
|
|
14469
|
+
]
|
|
14470
|
+
};
|
|
14471
|
+
} catch (err) {
|
|
14472
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14473
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14474
|
+
}
|
|
14475
|
+
}
|
|
14476
|
+
);
|
|
14477
|
+
server.tool(
|
|
14478
|
+
"fork_chat",
|
|
14479
|
+
"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.",
|
|
14480
|
+
{
|
|
14481
|
+
ref: import_zod.z.string().describe("Thread id/ref to fork (worktree agent or orchestration chat)"),
|
|
14482
|
+
through_index: import_zod.z.number().optional().describe("Inclusive message index to include in the transcript (default: all)"),
|
|
14483
|
+
agent: agentEnum.optional().describe("Agent for the forked chat (default: same as source)"),
|
|
14484
|
+
model: import_zod.z.string().nullable().optional().describe("Usually omit (Auto). Only set from list_models when you need a specific model"),
|
|
14485
|
+
title: import_zod.z.string().optional()
|
|
14486
|
+
},
|
|
14487
|
+
async ({ ref, through_index, agent, model, title }) => {
|
|
14488
|
+
try {
|
|
14489
|
+
const source = orch.getThread(ref);
|
|
14490
|
+
if (!source) {
|
|
14491
|
+
return {
|
|
14492
|
+
content: [{ type: "text", text: `Thread not found: ${ref}` }],
|
|
14493
|
+
isError: true
|
|
14494
|
+
};
|
|
13990
14495
|
}
|
|
13991
|
-
|
|
13992
|
-
|
|
13993
|
-
|
|
13994
|
-
|
|
13995
|
-
|
|
13996
|
-
|
|
13997
|
-
|
|
13998
|
-
|
|
13999
|
-
|
|
14000
|
-
|
|
14001
|
-
|
|
14002
|
-
|
|
14496
|
+
const tab = orch.forkChatTab({
|
|
14497
|
+
threadId: source.id,
|
|
14498
|
+
throughIndex: through_index,
|
|
14499
|
+
agent,
|
|
14500
|
+
model,
|
|
14501
|
+
title
|
|
14502
|
+
});
|
|
14503
|
+
return {
|
|
14504
|
+
content: [
|
|
14505
|
+
{
|
|
14506
|
+
type: "text",
|
|
14507
|
+
text: JSON.stringify({
|
|
14508
|
+
id: tab.id,
|
|
14509
|
+
title: tab.title,
|
|
14510
|
+
status: tab.status,
|
|
14511
|
+
agent: tab.agent,
|
|
14512
|
+
model: tab.model,
|
|
14513
|
+
sourceType: tab.sourceType,
|
|
14514
|
+
worktreePath: tab.worktreePath,
|
|
14515
|
+
fromThreadId: source.id,
|
|
14516
|
+
link: `sideboard://thread/${tab.id}`
|
|
14517
|
+
})
|
|
14518
|
+
}
|
|
14519
|
+
]
|
|
14520
|
+
};
|
|
14521
|
+
} catch (err) {
|
|
14522
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14523
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14524
|
+
}
|
|
14525
|
+
}
|
|
14526
|
+
);
|
|
14527
|
+
server.tool(
|
|
14528
|
+
"run_dev_script",
|
|
14529
|
+
"Start a .sideboard/.conductor run script for a thread (default script if name omitted); returns port",
|
|
14530
|
+
{
|
|
14531
|
+
ref: import_zod.z.string(),
|
|
14532
|
+
name: import_zod.z.string().optional()
|
|
14533
|
+
},
|
|
14534
|
+
async ({ ref, name }) => {
|
|
14535
|
+
const result = await orch.startDev(ref, name);
|
|
14003
14536
|
return {
|
|
14004
14537
|
content: [
|
|
14005
14538
|
{
|
|
14006
14539
|
type: "text",
|
|
14007
14540
|
text: JSON.stringify({
|
|
14008
|
-
|
|
14009
|
-
|
|
14010
|
-
|
|
14011
|
-
|
|
14012
|
-
link: `sideboard://thread/${tab.id}`
|
|
14541
|
+
port: result.port,
|
|
14542
|
+
scriptName: result.scriptName,
|
|
14543
|
+
ports: result.ports,
|
|
14544
|
+
url: `http://localhost:${result.port}`
|
|
14013
14545
|
})
|
|
14014
14546
|
}
|
|
14015
14547
|
]
|
|
14016
14548
|
};
|
|
14017
|
-
} catch (err) {
|
|
14018
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
14019
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
14020
14549
|
}
|
|
14021
|
-
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
|
|
14025
|
-
|
|
14026
|
-
|
|
14027
|
-
|
|
14028
|
-
|
|
14029
|
-
},
|
|
14030
|
-
async ({ agent }) => {
|
|
14031
|
-
try {
|
|
14032
|
-
const catalogs = await listModelsForAgent(agent);
|
|
14550
|
+
);
|
|
14551
|
+
server.tool(
|
|
14552
|
+
"list_run_scripts",
|
|
14553
|
+
"List named run scripts available for a thread",
|
|
14554
|
+
{ ref: import_zod.z.string() },
|
|
14555
|
+
async ({ ref }) => {
|
|
14556
|
+
const scripts = orch.listThreadRunScripts(ref);
|
|
14557
|
+
const active = orch.getActiveRuns(ref);
|
|
14033
14558
|
return {
|
|
14034
|
-
content: [
|
|
14559
|
+
content: [
|
|
14560
|
+
{
|
|
14561
|
+
type: "text",
|
|
14562
|
+
text: JSON.stringify({ scripts, active }, null, 2)
|
|
14563
|
+
}
|
|
14564
|
+
]
|
|
14035
14565
|
};
|
|
14036
|
-
} catch (err) {
|
|
14037
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
14038
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
14039
14566
|
}
|
|
14040
|
-
|
|
14041
|
-
|
|
14042
|
-
|
|
14043
|
-
|
|
14044
|
-
|
|
14045
|
-
|
|
14046
|
-
|
|
14047
|
-
|
|
14048
|
-
|
|
14049
|
-
|
|
14050
|
-
|
|
14051
|
-
|
|
14052
|
-
|
|
14053
|
-
|
|
14054
|
-
|
|
14055
|
-
|
|
14056
|
-
|
|
14057
|
-
|
|
14058
|
-
|
|
14059
|
-
|
|
14060
|
-
|
|
14061
|
-
|
|
14567
|
+
);
|
|
14568
|
+
server.tool(
|
|
14569
|
+
"stop_dev_script",
|
|
14570
|
+
"Stop a running script for a thread (all scripts if name omitted)",
|
|
14571
|
+
{
|
|
14572
|
+
ref: import_zod.z.string(),
|
|
14573
|
+
name: import_zod.z.string().optional()
|
|
14574
|
+
},
|
|
14575
|
+
async ({ ref, name }) => {
|
|
14576
|
+
orch.stopDev(ref, name);
|
|
14577
|
+
return { content: [{ type: "text", text: "ok" }] };
|
|
14578
|
+
}
|
|
14579
|
+
);
|
|
14580
|
+
server.tool(
|
|
14581
|
+
"run_setup",
|
|
14582
|
+
"Re-run workspace setup (Sideboard/Conductor settings or .cursor/worktrees.json)",
|
|
14583
|
+
{ ref: import_zod.z.string() },
|
|
14584
|
+
async ({ ref }) => {
|
|
14585
|
+
const result = await orch.runSetup(ref);
|
|
14586
|
+
return {
|
|
14587
|
+
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
14588
|
+
};
|
|
14589
|
+
}
|
|
14590
|
+
);
|
|
14591
|
+
server.tool(
|
|
14592
|
+
"add_workspace",
|
|
14593
|
+
"Register a git repo as a Sideboard workspace",
|
|
14594
|
+
{ repoPath: import_zod.z.string() },
|
|
14595
|
+
async ({ repoPath }) => {
|
|
14596
|
+
const ws = await orch.addWorkspace(repoPath);
|
|
14597
|
+
return { content: [{ type: "text", text: JSON.stringify(ws) }] };
|
|
14598
|
+
}
|
|
14599
|
+
);
|
|
14600
|
+
server.tool(
|
|
14601
|
+
"remove_workspace",
|
|
14602
|
+
"Unregister a Sideboard workspace (does not archive threads)",
|
|
14603
|
+
{ repoPath: import_zod.z.string() },
|
|
14604
|
+
async ({ repoPath }) => {
|
|
14605
|
+
orch.removeWorkspace(repoPath);
|
|
14606
|
+
return { content: [{ type: "text", text: "ok" }] };
|
|
14607
|
+
}
|
|
14608
|
+
);
|
|
14609
|
+
server.tool(
|
|
14610
|
+
"fanout",
|
|
14611
|
+
"Best-of-n: create one thread per agent with the same prompt (parallel attempts)",
|
|
14612
|
+
{
|
|
14613
|
+
prompt: import_zod.z.string(),
|
|
14614
|
+
agents: import_zod.z.array(import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"])),
|
|
14615
|
+
repoPath: import_zod.z.string(),
|
|
14616
|
+
sourceType: import_zod.z.enum(["branch", "pr", "ticket"]).optional(),
|
|
14617
|
+
sourceRef: import_zod.z.string().optional(),
|
|
14618
|
+
title: import_zod.z.string().optional()
|
|
14619
|
+
},
|
|
14620
|
+
async (args) => {
|
|
14621
|
+
const threads = await orch.bestOfN(args);
|
|
14622
|
+
return {
|
|
14623
|
+
content: [
|
|
14624
|
+
{
|
|
14625
|
+
type: "text",
|
|
14626
|
+
text: JSON.stringify(
|
|
14627
|
+
threads.map((t) => ({
|
|
14628
|
+
id: t.id,
|
|
14629
|
+
agent: t.agent,
|
|
14630
|
+
branchName: t.branchName,
|
|
14631
|
+
worktreePath: t.worktreePath
|
|
14632
|
+
})),
|
|
14633
|
+
null,
|
|
14634
|
+
2
|
|
14635
|
+
)
|
|
14636
|
+
}
|
|
14637
|
+
]
|
|
14638
|
+
};
|
|
14639
|
+
}
|
|
14640
|
+
);
|
|
14641
|
+
server.tool(
|
|
14642
|
+
"list_branches",
|
|
14643
|
+
"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).",
|
|
14644
|
+
{
|
|
14645
|
+
repoPath: import_zod.z.string(),
|
|
14646
|
+
unmergedOnly: import_zod.z.boolean().optional()
|
|
14647
|
+
},
|
|
14648
|
+
async ({ repoPath, unmergedOnly }) => {
|
|
14649
|
+
const root = await resolveRepoRoot(repoPath);
|
|
14650
|
+
const branches = await listBranches(root, {
|
|
14651
|
+
unmergedOnly: unmergedOnly !== false
|
|
14062
14652
|
});
|
|
14063
14653
|
return {
|
|
14064
14654
|
content: [
|
|
14065
14655
|
{
|
|
14066
14656
|
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
|
-
})
|
|
14657
|
+
text: branches.map((b) => `${b.current ? "*" : " "} ${b.name}`).join("\n")
|
|
14078
14658
|
}
|
|
14079
14659
|
]
|
|
14080
14660
|
};
|
|
14081
|
-
} catch (err) {
|
|
14082
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
14083
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
14084
14661
|
}
|
|
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
|
-
|
|
14662
|
+
);
|
|
14663
|
+
server.tool(
|
|
14664
|
+
"list_prs",
|
|
14665
|
+
"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.",
|
|
14666
|
+
{ repoPath: import_zod.z.string() },
|
|
14667
|
+
async ({ repoPath }) => {
|
|
14668
|
+
const root = await resolveRepoRoot(repoPath);
|
|
14669
|
+
const prs = await listPrs(root);
|
|
14670
|
+
return {
|
|
14671
|
+
content: [
|
|
14672
|
+
{
|
|
14673
|
+
type: "text",
|
|
14674
|
+
text: prs.map(
|
|
14675
|
+
(p) => `#${p.number} ${p.title} (${p.headRefName})${p.isCrossRepository ? " [fork]" : ""}`
|
|
14676
|
+
).join("\n")
|
|
14677
|
+
}
|
|
14678
|
+
]
|
|
14679
|
+
};
|
|
14680
|
+
}
|
|
14681
|
+
);
|
|
14682
|
+
server.tool(
|
|
14683
|
+
"get_pr_stack",
|
|
14684
|
+
"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.",
|
|
14685
|
+
{ ref: import_zod.z.string() },
|
|
14686
|
+
async ({ ref }) => {
|
|
14687
|
+
const stack = await orch.getPrStack(ref);
|
|
14688
|
+
return {
|
|
14689
|
+
content: [{ type: "text", text: JSON.stringify(stack, null, 2) }]
|
|
14690
|
+
};
|
|
14691
|
+
}
|
|
14692
|
+
);
|
|
14693
|
+
server.tool(
|
|
14694
|
+
"open_pr_stack_layers",
|
|
14695
|
+
"Materialize one worktree+thread per stack layer (or a single 1-based layer). Pass a thread ref already on the stack.",
|
|
14696
|
+
{
|
|
14697
|
+
ref: import_zod.z.string(),
|
|
14698
|
+
layer: import_zod.z.number().int().positive().optional()
|
|
14699
|
+
},
|
|
14700
|
+
async ({ ref, layer }) => {
|
|
14701
|
+
const result = await orch.openPrStackLayers(ref, { layer });
|
|
14702
|
+
return {
|
|
14703
|
+
content: [
|
|
14704
|
+
{
|
|
14705
|
+
type: "text",
|
|
14706
|
+
text: JSON.stringify(
|
|
14707
|
+
{
|
|
14708
|
+
stackNumber: result.stack.stackNumber,
|
|
14709
|
+
trunk: result.stack.trunk,
|
|
14710
|
+
threads: result.threads.map((t) => ({
|
|
14711
|
+
id: t.id,
|
|
14712
|
+
title: t.title,
|
|
14713
|
+
branchName: t.branchName,
|
|
14714
|
+
stackLayer: t.stackLayer,
|
|
14715
|
+
worktreePath: t.worktreePath,
|
|
14716
|
+
prUrl: t.prUrl,
|
|
14717
|
+
link: `sideboard://thread/${t.id}`
|
|
14718
|
+
}))
|
|
14719
|
+
},
|
|
14720
|
+
null,
|
|
14721
|
+
2
|
|
14722
|
+
)
|
|
14723
|
+
}
|
|
14724
|
+
]
|
|
14725
|
+
};
|
|
14726
|
+
}
|
|
14727
|
+
);
|
|
14728
|
+
server.tool(
|
|
14729
|
+
"add_stack_layer",
|
|
14730
|
+
"Add a branch on top of the current stack (`gh stack add`) and open a worktree+thread for it.",
|
|
14731
|
+
{
|
|
14732
|
+
ref: import_zod.z.string(),
|
|
14733
|
+
branchName: import_zod.z.string(),
|
|
14734
|
+
title: import_zod.z.string().optional()
|
|
14735
|
+
},
|
|
14736
|
+
async ({ ref, branchName, title }) => {
|
|
14737
|
+
const result = await orch.addStackLayer(ref, branchName, { title });
|
|
14738
|
+
return {
|
|
14739
|
+
content: [
|
|
14740
|
+
{
|
|
14741
|
+
type: "text",
|
|
14742
|
+
text: JSON.stringify(
|
|
14743
|
+
{
|
|
14744
|
+
id: result.thread.id,
|
|
14745
|
+
title: result.thread.title,
|
|
14746
|
+
branchName: result.thread.branchName,
|
|
14747
|
+
stackLayer: result.thread.stackLayer,
|
|
14748
|
+
worktreePath: result.thread.worktreePath,
|
|
14749
|
+
link: `sideboard://thread/${result.thread.id}`
|
|
14750
|
+
},
|
|
14751
|
+
null,
|
|
14752
|
+
2
|
|
14753
|
+
)
|
|
14754
|
+
}
|
|
14755
|
+
]
|
|
14756
|
+
};
|
|
14757
|
+
}
|
|
14758
|
+
);
|
|
14759
|
+
server.tool(
|
|
14760
|
+
"create_pr_stack",
|
|
14761
|
+
"Create a new GitHub PR stack with one Sideboard worktree per layer (bottom\u2192top branch names). Requires `gh extension install github/gh-stack`.",
|
|
14762
|
+
{
|
|
14763
|
+
repoPath: import_zod.z.string(),
|
|
14764
|
+
branches: import_zod.z.array(import_zod.z.string()).min(1),
|
|
14765
|
+
agent: import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]),
|
|
14766
|
+
base: import_zod.z.string().optional(),
|
|
14767
|
+
title: import_zod.z.string().optional()
|
|
14768
|
+
},
|
|
14769
|
+
async (args) => {
|
|
14770
|
+
const result = await orch.createPrStack({
|
|
14771
|
+
repoPath: args.repoPath,
|
|
14772
|
+
branches: args.branches,
|
|
14773
|
+
agent: args.agent,
|
|
14774
|
+
base: args.base,
|
|
14775
|
+
title: args.title
|
|
14112
14776
|
});
|
|
14113
14777
|
return {
|
|
14114
14778
|
content: [
|
|
14115
14779
|
{
|
|
14116
14780
|
type: "text",
|
|
14117
|
-
text: JSON.stringify(
|
|
14118
|
-
|
|
14119
|
-
|
|
14120
|
-
|
|
14121
|
-
|
|
14122
|
-
|
|
14123
|
-
|
|
14124
|
-
|
|
14125
|
-
|
|
14126
|
-
|
|
14127
|
-
|
|
14781
|
+
text: JSON.stringify(
|
|
14782
|
+
{
|
|
14783
|
+
stackNumber: result.stack.stackNumber,
|
|
14784
|
+
trunk: result.stack.trunk,
|
|
14785
|
+
threads: result.threads.map((t) => ({
|
|
14786
|
+
id: t.id,
|
|
14787
|
+
title: t.title,
|
|
14788
|
+
branchName: t.branchName,
|
|
14789
|
+
stackLayer: t.stackLayer,
|
|
14790
|
+
worktreePath: t.worktreePath,
|
|
14791
|
+
link: `sideboard://thread/${t.id}`
|
|
14792
|
+
}))
|
|
14793
|
+
},
|
|
14794
|
+
null,
|
|
14795
|
+
2
|
|
14796
|
+
)
|
|
14128
14797
|
}
|
|
14129
14798
|
]
|
|
14130
14799
|
};
|
|
14131
|
-
} catch (err) {
|
|
14132
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
14133
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
14134
14800
|
}
|
|
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
|
-
);
|
|
14801
|
+
);
|
|
14802
|
+
server.tool(
|
|
14803
|
+
"list_issues",
|
|
14804
|
+
"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.",
|
|
14805
|
+
{ repoPath: import_zod.z.string() },
|
|
14806
|
+
async ({ repoPath }) => {
|
|
14807
|
+
const root = await resolveRepoRoot(repoPath);
|
|
14808
|
+
const result = await listIssues(root);
|
|
14809
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
14810
|
+
}
|
|
14811
|
+
);
|
|
14812
|
+
server.tool(
|
|
14813
|
+
"list_linear_issues",
|
|
14814
|
+
"Deprecated: prefer list_issues. Lists assigned Linear issues via the chosen agent MCP connector",
|
|
14815
|
+
{
|
|
14816
|
+
agent: import_zod.z.enum(["claude", "codex", "opencode"]),
|
|
14817
|
+
repoPath: import_zod.z.string()
|
|
14818
|
+
},
|
|
14819
|
+
async ({ agent, repoPath }) => {
|
|
14820
|
+
const issues = await listLinearIssues(agent, repoPath);
|
|
14821
|
+
return { content: [{ type: "text", text: JSON.stringify(issues, null, 2) }] };
|
|
14822
|
+
}
|
|
14823
|
+
);
|
|
14824
|
+
}
|
|
14434
14825
|
const transport = new import_stdio.StdioServerTransport();
|
|
14435
14826
|
await server.connect(transport);
|
|
14436
14827
|
}
|
|
14437
14828
|
|
|
14438
14829
|
// src/index.ts
|
|
14830
|
+
init_profile();
|
|
14439
14831
|
init_config();
|
|
14440
14832
|
|
|
14441
14833
|
// src/brightsy/api.ts
|
|
@@ -14812,6 +15204,7 @@ init_injected_mcp();
|
|
|
14812
15204
|
REVIEW_REQUEST_PREFILL,
|
|
14813
15205
|
SIDEBOARD_FORCE_STOP,
|
|
14814
15206
|
SIDEBOARD_MCP_ALLOWED_TOOLS,
|
|
15207
|
+
SIDEBOARD_MCP_PROFILE_ENV,
|
|
14815
15208
|
THINKING_EFFORTS,
|
|
14816
15209
|
addPrStackLayer,
|
|
14817
15210
|
addStackLayerFromThread,
|
|
@@ -14843,6 +15236,7 @@ init_injected_mcp();
|
|
|
14843
15236
|
brightsyCloudConnectAgent,
|
|
14844
15237
|
brightsyCloudConnectEnabled,
|
|
14845
15238
|
brightsyConfigPath,
|
|
15239
|
+
brightsyInjectWorktreeMcpEnabled,
|
|
14846
15240
|
brightsyMcpAllowedTools,
|
|
14847
15241
|
brightsyMcpServerName,
|
|
14848
15242
|
buildCachedUserContent,
|
|
@@ -14868,6 +15262,7 @@ init_injected_mcp();
|
|
|
14868
15262
|
coerceOrchestratorAgent,
|
|
14869
15263
|
collectTakenTeamSlugs,
|
|
14870
15264
|
commitAll,
|
|
15265
|
+
conductorBundledBinDir,
|
|
14871
15266
|
conductorDbPath,
|
|
14872
15267
|
confirmLand,
|
|
14873
15268
|
connectBrightsyTeam,
|
|
@@ -14894,7 +15289,9 @@ init_injected_mcp();
|
|
|
14894
15289
|
detectLocalMergeConflicts,
|
|
14895
15290
|
disconnectBrightsyTeam,
|
|
14896
15291
|
discoverSkills,
|
|
15292
|
+
dropCachedPrefixOnResume,
|
|
14897
15293
|
encodeBrightsyTarget,
|
|
15294
|
+
enrichPathWithNpmGlobalBin,
|
|
14898
15295
|
enrichWorkspacesWithGithub,
|
|
14899
15296
|
ensureAgentPath,
|
|
14900
15297
|
ensureCloudCoordinator,
|
|
@@ -14932,6 +15329,7 @@ init_injected_mcp();
|
|
|
14932
15329
|
formatTranscriptMarkdown,
|
|
14933
15330
|
formatWorkspaceInventory,
|
|
14934
15331
|
formatWorktreeDirective,
|
|
15332
|
+
formatWorktreeReminder,
|
|
14935
15333
|
getAdapter,
|
|
14936
15334
|
getAgentSetupInfo,
|
|
14937
15335
|
getBrightsySession,
|
|
@@ -14976,6 +15374,7 @@ init_injected_mcp();
|
|
|
14976
15374
|
isBrightsyConnected,
|
|
14977
15375
|
isBrightsyNdjsonLine,
|
|
14978
15376
|
isCloudCoordinatorThread,
|
|
15377
|
+
isConductorBundledCli,
|
|
14979
15378
|
isCursorAutoModel,
|
|
14980
15379
|
isDirty,
|
|
14981
15380
|
isGhRateLimitError,
|
|
@@ -15058,7 +15457,10 @@ init_injected_mcp();
|
|
|
15058
15457
|
pastedTextStats,
|
|
15059
15458
|
permissionMode,
|
|
15060
15459
|
planFileAbs,
|
|
15460
|
+
posixShellSingleQuote,
|
|
15461
|
+
prepareTerminalCommand,
|
|
15061
15462
|
previewLand,
|
|
15463
|
+
promptMentionsBrightsy,
|
|
15062
15464
|
pushBranch,
|
|
15063
15465
|
readExistingReviewRequestFile,
|
|
15064
15466
|
readPlanFile,
|
|
@@ -15074,7 +15476,9 @@ init_injected_mcp();
|
|
|
15074
15476
|
requestReview,
|
|
15075
15477
|
requireAgent,
|
|
15076
15478
|
resetGhStackDetectCache,
|
|
15479
|
+
resolveAgentExecutable,
|
|
15077
15480
|
resolveClaudeExecutable,
|
|
15481
|
+
resolveCommandBinarySync,
|
|
15078
15482
|
resolveConductorCursorAgentId,
|
|
15079
15483
|
resolveCursorModelId,
|
|
15080
15484
|
resolveDefaultBranch,
|
|
@@ -15083,6 +15487,7 @@ init_injected_mcp();
|
|
|
15083
15487
|
resolveFilesToCopy,
|
|
15084
15488
|
resolveGhAuthToken,
|
|
15085
15489
|
resolveGithubRepoSlug,
|
|
15490
|
+
resolveLoginCommand,
|
|
15086
15491
|
resolveNewThreadOptions,
|
|
15087
15492
|
resolvePlanMarkdown,
|
|
15088
15493
|
resolvePrSelector,
|
|
@@ -15104,9 +15509,11 @@ init_injected_mcp();
|
|
|
15104
15509
|
settingsSourceLabel,
|
|
15105
15510
|
shouldAttachPastedText,
|
|
15106
15511
|
shouldCompactContext,
|
|
15512
|
+
shouldInjectBrightsyMcp,
|
|
15107
15513
|
shouldRefreshReviewRequestTemplate,
|
|
15108
15514
|
shouldRunWorktreeCleanup,
|
|
15109
15515
|
sideboardHomeDir,
|
|
15516
|
+
sideboardMcpProfile,
|
|
15110
15517
|
sideboardReposDir,
|
|
15111
15518
|
sideboardWorkspacesDir,
|
|
15112
15519
|
slugify,
|
|
@@ -15134,6 +15541,7 @@ init_injected_mcp();
|
|
|
15134
15541
|
threadDisplayLabel,
|
|
15135
15542
|
threadFilePath,
|
|
15136
15543
|
threadLockPath,
|
|
15544
|
+
threadRequestsBrightsyMcp,
|
|
15137
15545
|
threadsDir,
|
|
15138
15546
|
threadsSharingWorktree,
|
|
15139
15547
|
toolDescription,
|
|
@@ -15141,14 +15549,18 @@ init_injected_mcp();
|
|
|
15141
15549
|
toolFilePath,
|
|
15142
15550
|
totalTokens,
|
|
15143
15551
|
updateAdvancedSettings,
|
|
15552
|
+
updateAgentExecutable,
|
|
15144
15553
|
updateAppEnvironment,
|
|
15145
15554
|
updateBrightsySettings,
|
|
15146
15555
|
updateClaudeSettings,
|
|
15556
|
+
updateCodexSettings,
|
|
15147
15557
|
updateDefaultsSettings,
|
|
15148
15558
|
updateIntegrationsSettings,
|
|
15559
|
+
updateOpencodeSettings,
|
|
15149
15560
|
updateThread,
|
|
15150
15561
|
validateLinearApiKey,
|
|
15151
15562
|
withAgentInstructions,
|
|
15563
|
+
withExportedPath,
|
|
15152
15564
|
withThreadLock,
|
|
15153
15565
|
workspaceSettingsSourceLabel,
|
|
15154
15566
|
worktreeCleanupSettings,
|