@sideboard-ai/core 0.1.61 → 0.1.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agents-B2723EOF.js → agents-EWFD765A.js} +23 -7
- package/dist/{agents-EADRAAPG.js → agents-MD7SCFYX.js} +23 -7
- package/dist/{app-settings-YBNZ4XSR.js → app-settings-GJVZGU3M.js} +15 -3
- package/dist/{app-settings-TBHTJWLQ.js → app-settings-ONKMFSEJ.js} +15 -3
- package/dist/{chunk-RIWUU7FO.js → chunk-5AG5BUQN.js} +61 -3
- package/dist/{chunk-HLEX5AQ6.js → chunk-7FD7COKE.js} +4 -0
- package/dist/{chunk-XWPKLRB3.js → chunk-AKPEXIKK.js} +2 -2
- package/dist/{chunk-MX7UH5AT.js → chunk-BBEH2CJE.js} +264 -93
- package/dist/{chunk-FGNBTFRD.js → chunk-BPOTVI5J.js} +125 -3
- package/dist/{chunk-CHGOMFTA.js → chunk-DNPP7QMK.js} +32 -7
- package/dist/{chunk-MBAL5FE6.js → chunk-DZYMNW2A.js} +4 -4
- package/dist/{chunk-JB2H7E7V.js → chunk-EVD4KNKR.js} +1 -1
- package/dist/{chunk-TSRXOSVD.js → chunk-FWJYLBO6.js} +4 -0
- package/dist/{chunk-QJBC4BRK.js → chunk-HTOTTJJX.js} +2 -2
- package/dist/{chunk-MFGGIRUA.js → chunk-I2KGRAXC.js} +2 -2
- package/dist/{chunk-ZXDOI6IH.js → chunk-IFAU2DEY.js} +269 -93
- package/dist/{chunk-NTYRBRE7.js → chunk-LRBRQFBU.js} +2 -2
- package/dist/{chunk-75QR74KM.js → chunk-MHR4OGZ4.js} +125 -3
- package/dist/{chunk-2P2UK7E7.js → chunk-PESJDZTB.js} +2 -2
- package/dist/{chunk-P7EQUFB6.js → chunk-R7GUDEPY.js} +2 -2
- package/dist/{chunk-73AT5K4A.js → chunk-TXQ6K2GR.js} +61 -3
- package/dist/{chunk-MLAST5BB.js → chunk-YTNLOJPK.js} +32 -7
- package/dist/{connected-teams-RSL4VB3X.js → connected-teams-CHXO5FFA.js} +2 -2
- package/dist/{connected-teams-MKIYKOYA.js → connected-teams-GJTESSTX.js} +2 -2
- package/dist/{coordinator-prompt-4P23VVFC.js → coordinator-prompt-E5UGSJES.js} +5 -5
- package/dist/{coordinator-prompt-LNWHZ64D.js → coordinator-prompt-ILSULI7C.js} +5 -5
- package/dist/{global-workspace-TMMAVRVW.js → global-workspace-44UG64NA.js} +6 -7
- package/dist/{global-workspace-BHT4XUAA.js → global-workspace-5PM5LA6E.js} +6 -7
- package/dist/index.cjs +1433 -944
- package/dist/index.d.cts +117 -2
- package/dist/index.d.ts +117 -2
- package/dist/index.js +859 -736
- package/dist/mcp/run-stdio.cjs +1388 -993
- package/dist/mcp/run-stdio.js +798 -765
- package/dist/{run-HZTBWGQR.js → run-74S2NZWB.js} +1 -1
- package/dist/{run-GPSVV5OH.js → run-JLN5JK7Q.js} +1 -1
- package/dist/{thread-store-GHOADGL2.js → thread-store-BUBR24YA.js} +1 -1
- package/dist/{thread-store-UJIGMI5J.js → thread-store-XTPFCJAI.js} +1 -1
- package/dist/{workspaces-3GO3EDQG.js → workspaces-OVBCSS5Y.js} +7 -8
- package/dist/{workspaces-GFPGDGCS.js → workspaces-RXFXQRRF.js} +7 -8
- package/dist/{worktree-GBLHEFHR.js → worktree-K2JB53R5.js} +3 -3
- package/dist/{worktree-3L2G6PCM.js → worktree-S2N63FLV.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-GI7E5733.js +0 -30
- package/dist/chunk-S2LL5HA4.js +0 -33
package/dist/index.cjs
CHANGED
|
@@ -391,11 +391,13 @@ __export(app_settings_exports, {
|
|
|
391
391
|
HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
|
|
392
392
|
appSettingsPath: () => appSettingsPath,
|
|
393
393
|
applyAppEnvironment: () => applyAppEnvironment,
|
|
394
|
+
autoArchiveOnMergeEnabled: () => autoArchiveOnMergeEnabled,
|
|
394
395
|
autoCleanupOrphansEnabled: () => autoCleanupOrphansEnabled,
|
|
395
396
|
autoRenameBranchEnabled: () => autoRenameBranchEnabled,
|
|
396
397
|
autoRunAfterSetupEnabled: () => autoRunAfterSetupEnabled,
|
|
397
398
|
brightsyCloudConnectAgent: () => brightsyCloudConnectAgent,
|
|
398
399
|
brightsyCloudConnectEnabled: () => brightsyCloudConnectEnabled,
|
|
400
|
+
brightsyInjectWorktreeMcpEnabled: () => brightsyInjectWorktreeMcpEnabled,
|
|
399
401
|
caffeinateWhileCloudConnectEnabled: () => caffeinateWhileCloudConnectEnabled,
|
|
400
402
|
caffeinateWhileRunningEnabled: () => caffeinateWhileRunningEnabled,
|
|
401
403
|
childEnvWithAppSettings: () => childEnvWithAppSettings,
|
|
@@ -414,17 +416,21 @@ __export(app_settings_exports, {
|
|
|
414
416
|
maxConcurrentAgents: () => maxConcurrentAgents,
|
|
415
417
|
orchestrationQuotaFallbackAgent: () => orchestrationQuotaFallbackAgent,
|
|
416
418
|
orchestrationQuotaOnLimit: () => orchestrationQuotaOnLimit,
|
|
419
|
+
resolveAgentExecutable: () => resolveAgentExecutable,
|
|
417
420
|
resolveClaudeExecutable: () => resolveClaudeExecutable,
|
|
418
421
|
resolveEffectiveIssueSource: () => resolveEffectiveIssueSource,
|
|
419
422
|
resolveNewThreadOptions: () => resolveNewThreadOptions,
|
|
420
423
|
resolveThreadDefaults: () => resolveThreadDefaults,
|
|
421
424
|
saveAppSettings: () => saveAppSettings,
|
|
422
425
|
updateAdvancedSettings: () => updateAdvancedSettings,
|
|
426
|
+
updateAgentExecutable: () => updateAgentExecutable,
|
|
423
427
|
updateAppEnvironment: () => updateAppEnvironment,
|
|
424
428
|
updateBrightsySettings: () => updateBrightsySettings,
|
|
425
429
|
updateClaudeSettings: () => updateClaudeSettings,
|
|
430
|
+
updateCodexSettings: () => updateCodexSettings,
|
|
426
431
|
updateDefaultsSettings: () => updateDefaultsSettings,
|
|
427
|
-
updateIntegrationsSettings: () => updateIntegrationsSettings
|
|
432
|
+
updateIntegrationsSettings: () => updateIntegrationsSettings,
|
|
433
|
+
updateOpencodeSettings: () => updateOpencodeSettings
|
|
428
434
|
});
|
|
429
435
|
function appSettingsPath() {
|
|
430
436
|
return (0, import_node_path4.join)(appDataDir(), "settings.json");
|
|
@@ -445,16 +451,33 @@ function normalizeClaude(raw) {
|
|
|
445
451
|
}
|
|
446
452
|
return out;
|
|
447
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
|
+
}
|
|
448
464
|
function normalizeBrightsy(raw) {
|
|
449
465
|
if (!raw || typeof raw !== "object") return {};
|
|
450
466
|
const source = raw;
|
|
451
467
|
const out = {};
|
|
468
|
+
if (typeof source.executablePath === "string") {
|
|
469
|
+
const path = source.executablePath.trim();
|
|
470
|
+
if (path) out.executablePath = path;
|
|
471
|
+
}
|
|
452
472
|
if (typeof source.cloudConnectEnabled === "boolean") {
|
|
453
473
|
out.cloudConnectEnabled = source.cloudConnectEnabled;
|
|
454
474
|
}
|
|
455
475
|
if (typeof source.cloudConnectAgent === "string" && CLOUD_CONNECT_AGENTS.has(source.cloudConnectAgent)) {
|
|
456
476
|
out.cloudConnectAgent = source.cloudConnectAgent;
|
|
457
477
|
}
|
|
478
|
+
if (typeof source.injectWorktreeMcp === "boolean") {
|
|
479
|
+
out.injectWorktreeMcp = source.injectWorktreeMcp;
|
|
480
|
+
}
|
|
458
481
|
return out;
|
|
459
482
|
}
|
|
460
483
|
function normalizeIntegrations(raw) {
|
|
@@ -508,6 +531,9 @@ function normalizeAdvanced(raw) {
|
|
|
508
531
|
if (typeof source.deleteBranchOnPurge === "boolean") {
|
|
509
532
|
out.deleteBranchOnPurge = source.deleteBranchOnPurge;
|
|
510
533
|
}
|
|
534
|
+
if (typeof source.autoArchiveOnMerge === "boolean") {
|
|
535
|
+
out.autoArchiveOnMerge = source.autoArchiveOnMerge;
|
|
536
|
+
}
|
|
511
537
|
if (typeof source.maxConcurrent === "number" && Number.isFinite(source.maxConcurrent)) {
|
|
512
538
|
out.maxConcurrent = Math.max(1, Math.min(32, Math.floor(source.maxConcurrent)));
|
|
513
539
|
}
|
|
@@ -537,6 +563,8 @@ function normalizeAdvanced(raw) {
|
|
|
537
563
|
function normalizeSettings(raw) {
|
|
538
564
|
const env = {};
|
|
539
565
|
let claude = {};
|
|
566
|
+
let codex = {};
|
|
567
|
+
let opencode = {};
|
|
540
568
|
let brightsy = {};
|
|
541
569
|
let integrations = {};
|
|
542
570
|
let defaults = {};
|
|
@@ -555,6 +583,12 @@ function normalizeSettings(raw) {
|
|
|
555
583
|
if ("claude" in raw) {
|
|
556
584
|
claude = normalizeClaude(raw.claude);
|
|
557
585
|
}
|
|
586
|
+
if ("codex" in raw) {
|
|
587
|
+
codex = normalizeCliExecutable(raw.codex);
|
|
588
|
+
}
|
|
589
|
+
if ("opencode" in raw) {
|
|
590
|
+
opencode = normalizeCliExecutable(raw.opencode);
|
|
591
|
+
}
|
|
558
592
|
if ("brightsy" in raw) {
|
|
559
593
|
brightsy = normalizeBrightsy(raw.brightsy);
|
|
560
594
|
}
|
|
@@ -570,7 +604,16 @@ function normalizeSettings(raw) {
|
|
|
570
604
|
advanced = normalizeAdvanced(raw.advanced);
|
|
571
605
|
}
|
|
572
606
|
}
|
|
573
|
-
return {
|
|
607
|
+
return {
|
|
608
|
+
environment: env,
|
|
609
|
+
claude,
|
|
610
|
+
codex,
|
|
611
|
+
opencode,
|
|
612
|
+
brightsy,
|
|
613
|
+
integrations,
|
|
614
|
+
defaults,
|
|
615
|
+
advanced
|
|
616
|
+
};
|
|
574
617
|
}
|
|
575
618
|
function loadAppSettings() {
|
|
576
619
|
const path = appSettingsPath();
|
|
@@ -623,6 +666,13 @@ function updateClaudeSettings(patch) {
|
|
|
623
666
|
function updateBrightsySettings(patch) {
|
|
624
667
|
const current = loadAppSettings();
|
|
625
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
|
+
}
|
|
626
676
|
if (typeof patch.cloudConnectEnabled === "boolean") {
|
|
627
677
|
brightsy.cloudConnectEnabled = patch.cloudConnectEnabled;
|
|
628
678
|
}
|
|
@@ -633,8 +683,35 @@ function updateBrightsySettings(patch) {
|
|
|
633
683
|
brightsy.cloudConnectAgent = patch.cloudConnectAgent;
|
|
634
684
|
}
|
|
635
685
|
}
|
|
686
|
+
if (typeof patch.injectWorktreeMcp === "boolean") {
|
|
687
|
+
brightsy.injectWorktreeMcp = patch.injectWorktreeMcp;
|
|
688
|
+
}
|
|
636
689
|
return saveAppSettings({ ...current, brightsy });
|
|
637
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
|
+
}
|
|
638
715
|
function updateIntegrationsSettings(patch) {
|
|
639
716
|
const current = loadAppSettings();
|
|
640
717
|
const integrations = { ...current.integrations };
|
|
@@ -742,6 +819,9 @@ function getLinearApiKey(settings = loadAppSettings()) {
|
|
|
742
819
|
function brightsyCloudConnectEnabled(settings = loadAppSettings()) {
|
|
743
820
|
return Boolean(settings.brightsy.cloudConnectEnabled);
|
|
744
821
|
}
|
|
822
|
+
function brightsyInjectWorktreeMcpEnabled(settings = loadAppSettings()) {
|
|
823
|
+
return Boolean(settings.brightsy.injectWorktreeMcp);
|
|
824
|
+
}
|
|
745
825
|
function brightsyCloudConnectAgent(settings = loadAppSettings()) {
|
|
746
826
|
const fallback = settings.brightsy.cloudConnectAgent && CLOUD_CONNECT_AGENTS.has(settings.brightsy.cloudConnectAgent) ? settings.brightsy.cloudConnectAgent : "claude";
|
|
747
827
|
const preferred = getDefaultAgent(settings);
|
|
@@ -768,6 +848,9 @@ function updateAdvancedSettings(patch) {
|
|
|
768
848
|
if (typeof patch.deleteBranchOnPurge === "boolean") {
|
|
769
849
|
advanced.deleteBranchOnPurge = patch.deleteBranchOnPurge;
|
|
770
850
|
}
|
|
851
|
+
if (typeof patch.autoArchiveOnMerge === "boolean") {
|
|
852
|
+
advanced.autoArchiveOnMerge = patch.autoArchiveOnMerge;
|
|
853
|
+
}
|
|
771
854
|
if (typeof patch.maxConcurrent === "number" && Number.isFinite(patch.maxConcurrent)) {
|
|
772
855
|
advanced.maxConcurrent = Math.max(1, Math.min(32, Math.floor(patch.maxConcurrent)));
|
|
773
856
|
}
|
|
@@ -809,6 +892,9 @@ function caffeinateWhileCloudConnectEnabled(settings = loadAppSettings()) {
|
|
|
809
892
|
function deleteBranchOnPurgeEnabled(settings = loadAppSettings()) {
|
|
810
893
|
return Boolean(settings.advanced.deleteBranchOnPurge);
|
|
811
894
|
}
|
|
895
|
+
function autoArchiveOnMergeEnabled(settings = loadAppSettings()) {
|
|
896
|
+
return Boolean(settings.advanced.autoArchiveOnMerge);
|
|
897
|
+
}
|
|
812
898
|
function autoCleanupOrphansEnabled(settings = loadAppSettings()) {
|
|
813
899
|
return Boolean(settings.advanced.autoCleanupOrphans);
|
|
814
900
|
}
|
|
@@ -830,8 +916,36 @@ function maxConcurrentAgents(settings = loadAppSettings()) {
|
|
|
830
916
|
return 3;
|
|
831
917
|
}
|
|
832
918
|
function resolveClaudeExecutable(settings = loadAppSettings()) {
|
|
833
|
-
|
|
834
|
-
|
|
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 });
|
|
835
949
|
}
|
|
836
950
|
function claudeChromeEnabled(settings = loadAppSettings()) {
|
|
837
951
|
return Boolean(settings.claude.chromeEnabled);
|
|
@@ -859,7 +973,7 @@ function childEnvWithAppSettings(extra) {
|
|
|
859
973
|
function harnessEnvKey(harness) {
|
|
860
974
|
return HARNESS_ENV_KEYS[harness];
|
|
861
975
|
}
|
|
862
|
-
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;
|
|
863
977
|
var init_app_settings = __esm({
|
|
864
978
|
"src/store/app-settings.ts"() {
|
|
865
979
|
"use strict";
|
|
@@ -892,11 +1006,19 @@ var init_app_settings = __esm({
|
|
|
892
1006
|
EMPTY_SETTINGS = {
|
|
893
1007
|
environment: {},
|
|
894
1008
|
claude: {},
|
|
1009
|
+
codex: {},
|
|
1010
|
+
opencode: {},
|
|
895
1011
|
brightsy: {},
|
|
896
1012
|
integrations: {},
|
|
897
1013
|
defaults: {},
|
|
898
1014
|
advanced: {}
|
|
899
1015
|
};
|
|
1016
|
+
DEFAULT_CLI_BIN = {
|
|
1017
|
+
claude: "claude",
|
|
1018
|
+
codex: "codex",
|
|
1019
|
+
opencode: "opencode",
|
|
1020
|
+
brightsy: "brightsy"
|
|
1021
|
+
};
|
|
900
1022
|
}
|
|
901
1023
|
});
|
|
902
1024
|
|
|
@@ -937,6 +1059,8 @@ function normalizeThread(raw) {
|
|
|
937
1059
|
agentPid: raw.agentPid ?? null,
|
|
938
1060
|
attachments: Array.isArray(raw.attachments) ? raw.attachments : [],
|
|
939
1061
|
prTitle: raw.prTitle ?? null,
|
|
1062
|
+
prState: raw.prState ?? null,
|
|
1063
|
+
skipAutoArchiveOnMerge: Boolean(raw.skipAutoArchiveOnMerge),
|
|
940
1064
|
stackId: raw.stackId ?? null,
|
|
941
1065
|
stackLayer: raw.stackLayer ?? null,
|
|
942
1066
|
userSetTitle: Boolean(raw.userSetTitle),
|
|
@@ -963,6 +1087,8 @@ function createEmptyThread(partial) {
|
|
|
963
1087
|
activeRuns: partial.activeRuns ?? [],
|
|
964
1088
|
prUrl: partial.prUrl ?? null,
|
|
965
1089
|
prTitle: partial.prTitle ?? null,
|
|
1090
|
+
prState: partial.prState ?? null,
|
|
1091
|
+
skipAutoArchiveOnMerge: partial.skipAutoArchiveOnMerge ?? false,
|
|
966
1092
|
stackId: partial.stackId ?? null,
|
|
967
1093
|
stackLayer: partial.stackLayer ?? null,
|
|
968
1094
|
userSetTitle: partial.userSetTitle ?? false,
|
|
@@ -2027,18 +2153,28 @@ var init_gh_errors = __esm({
|
|
|
2027
2153
|
});
|
|
2028
2154
|
|
|
2029
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
|
+
}
|
|
2030
2166
|
function ensureAgentPath(env = process.env) {
|
|
2031
2167
|
const home = env.HOME || env.USERPROFILE || (0, import_node_os4.homedir)();
|
|
2032
2168
|
const current = env.PATH ?? "";
|
|
2033
2169
|
const parts = current.split(import_node_path5.delimiter).filter(Boolean);
|
|
2034
2170
|
const seen = new Set(parts);
|
|
2035
2171
|
const extras = [
|
|
2036
|
-
...EXTRA_BIN_DIRS.map((rel) =>
|
|
2172
|
+
...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path5.join)(home, rel)),
|
|
2037
2173
|
"/opt/homebrew/bin",
|
|
2038
2174
|
"/usr/local/bin"
|
|
2039
2175
|
];
|
|
2040
2176
|
for (const dir of extras.reverse()) {
|
|
2041
|
-
if (!dir || seen.has(dir)) continue;
|
|
2177
|
+
if (!dir || seen.has(dir) || !(0, import_node_fs5.existsSync)(dir)) continue;
|
|
2042
2178
|
parts.unshift(dir);
|
|
2043
2179
|
seen.add(dir);
|
|
2044
2180
|
}
|
|
@@ -2046,10 +2182,50 @@ function ensureAgentPath(env = process.env) {
|
|
|
2046
2182
|
env.PATH = next;
|
|
2047
2183
|
return next;
|
|
2048
2184
|
}
|
|
2049
|
-
|
|
2185
|
+
function enrichPathWithNpmGlobalBin(env = process.env) {
|
|
2186
|
+
ensureAgentPath(env);
|
|
2187
|
+
try {
|
|
2188
|
+
const prefix = (0, import_node_child_process.execFileSync)("npm", ["prefix", "-g"], {
|
|
2189
|
+
encoding: "utf8",
|
|
2190
|
+
env: { ...process.env, ...env },
|
|
2191
|
+
timeout: 8e3,
|
|
2192
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
2193
|
+
}).trim().split(/\r?\n/).find(Boolean);
|
|
2194
|
+
if (prefix) {
|
|
2195
|
+
const binDir = process.platform === "win32" ? prefix : (0, import_node_path5.join)(prefix, "bin");
|
|
2196
|
+
prependPathDir(env, binDir);
|
|
2197
|
+
}
|
|
2198
|
+
} catch {
|
|
2199
|
+
}
|
|
2200
|
+
return env.PATH ?? "";
|
|
2201
|
+
}
|
|
2202
|
+
function posixShellSingleQuote(value) {
|
|
2203
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
2204
|
+
}
|
|
2205
|
+
function resolveCommandBinarySync(command, whichPath) {
|
|
2206
|
+
const trimmed = command.trim();
|
|
2207
|
+
if (!trimmed) return trimmed;
|
|
2208
|
+
const match = /^(\S+)(\s[\s\S]*)?$/.exec(trimmed);
|
|
2209
|
+
if (!match) return trimmed;
|
|
2210
|
+
const bin = match[1];
|
|
2211
|
+
const rest = match[2] ?? "";
|
|
2212
|
+
if (bin.includes("/") || bin.includes("\\")) return trimmed;
|
|
2213
|
+
const abs = whichPath?.trim().split(/\r?\n/).find(Boolean);
|
|
2214
|
+
if (!abs) return trimmed;
|
|
2215
|
+
return `${abs}${rest}`;
|
|
2216
|
+
}
|
|
2217
|
+
function withExportedPath(command, pathValue) {
|
|
2218
|
+
const trimmed = command.trim();
|
|
2219
|
+
if (!trimmed) return trimmed;
|
|
2220
|
+
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
2221
|
+
return `export PATH=${posixShellSingleQuote(pathValue)}; ${trimmed}`;
|
|
2222
|
+
}
|
|
2223
|
+
var import_node_fs5, import_node_child_process, import_node_os4, import_node_path5, EXTRA_BIN_DIRS;
|
|
2050
2224
|
var init_path = __esm({
|
|
2051
2225
|
"src/agents/path.ts"() {
|
|
2052
2226
|
"use strict";
|
|
2227
|
+
import_node_fs5 = require("fs");
|
|
2228
|
+
import_node_child_process = require("child_process");
|
|
2053
2229
|
import_node_os4 = require("os");
|
|
2054
2230
|
import_node_path5 = require("path");
|
|
2055
2231
|
EXTRA_BIN_DIRS = [
|
|
@@ -2057,6 +2233,10 @@ var init_path = __esm({
|
|
|
2057
2233
|
".cargo/bin",
|
|
2058
2234
|
".nvm/current/bin",
|
|
2059
2235
|
".asdf/shims",
|
|
2236
|
+
".volta/bin",
|
|
2237
|
+
".npm-global/bin",
|
|
2238
|
+
// fnm default alias (common when shell init is skipped)
|
|
2239
|
+
".local/share/fnm/aliases/default/bin",
|
|
2060
2240
|
// pnpm / npm global bins (where `@brightsy/cli` typically lands)
|
|
2061
2241
|
"Library/pnpm",
|
|
2062
2242
|
".pnpm"
|
|
@@ -3144,7 +3324,7 @@ function isLocalPrFetchBranch(ref) {
|
|
|
3144
3324
|
async function createThreadWorktree(opts) {
|
|
3145
3325
|
let branchName = `thread/${opts.slug}`;
|
|
3146
3326
|
const worktreePath = (0, import_node_path6.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
3147
|
-
if ((0,
|
|
3327
|
+
if ((0, import_node_fs6.existsSync)(worktreePath)) {
|
|
3148
3328
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
3149
3329
|
}
|
|
3150
3330
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -3214,7 +3394,7 @@ async function createExistingBranchWorktree(opts) {
|
|
|
3214
3394
|
const branchName = opts.branchName.trim();
|
|
3215
3395
|
if (!branchName) throw new Error("branch name required");
|
|
3216
3396
|
const worktreePath = (0, import_node_path6.join)(worktreesRoot(opts.repoPath), opts.slug);
|
|
3217
|
-
if ((0,
|
|
3397
|
+
if ((0, import_node_fs6.existsSync)(worktreePath)) {
|
|
3218
3398
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
3219
3399
|
}
|
|
3220
3400
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
@@ -3475,9 +3655,9 @@ function sameRepoPath(a, b) {
|
|
|
3475
3655
|
}
|
|
3476
3656
|
function listLocalThreadBranchSlugs(repoPath) {
|
|
3477
3657
|
const refsDir = (0, import_node_path6.join)(repoPath, ".git", "refs", "heads", "thread");
|
|
3478
|
-
if (!(0,
|
|
3658
|
+
if (!(0, import_node_fs6.existsSync)(refsDir)) return [];
|
|
3479
3659
|
try {
|
|
3480
|
-
return (0,
|
|
3660
|
+
return (0, import_node_fs6.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
|
|
3481
3661
|
} catch {
|
|
3482
3662
|
return [];
|
|
3483
3663
|
}
|
|
@@ -3485,8 +3665,8 @@ function listLocalThreadBranchSlugs(repoPath) {
|
|
|
3485
3665
|
function collectTakenTeamSlugs(repoPath) {
|
|
3486
3666
|
const taken = /* @__PURE__ */ new Set();
|
|
3487
3667
|
const root = worktreesRoot(repoPath);
|
|
3488
|
-
if ((0,
|
|
3489
|
-
for (const entry of (0,
|
|
3668
|
+
if ((0, import_node_fs6.existsSync)(root)) {
|
|
3669
|
+
for (const entry of (0, import_node_fs6.readdirSync)(root, { withFileTypes: true })) {
|
|
3490
3670
|
if (entry.isDirectory() && entry.name !== ".DS_Store") {
|
|
3491
3671
|
taken.add(normalizeTakenSlug(entry.name));
|
|
3492
3672
|
}
|
|
@@ -3508,16 +3688,16 @@ function allocateTeamSlug(repoPath) {
|
|
|
3508
3688
|
for (let attempt = 0; attempt < 32; attempt++) {
|
|
3509
3689
|
const team = allocateTeamName(taken);
|
|
3510
3690
|
const path = (0, import_node_path6.join)(worktreesRoot(repoPath), team.slug);
|
|
3511
|
-
if (!(0,
|
|
3691
|
+
if (!(0, import_node_fs6.existsSync)(path)) return team;
|
|
3512
3692
|
taken.add(team.slug);
|
|
3513
3693
|
}
|
|
3514
3694
|
throw new Error("No available soccer team worktree directories left");
|
|
3515
3695
|
}
|
|
3516
|
-
var
|
|
3696
|
+
var import_node_fs6, import_node_path6;
|
|
3517
3697
|
var init_worktree = __esm({
|
|
3518
3698
|
"src/git/worktree.ts"() {
|
|
3519
3699
|
"use strict";
|
|
3520
|
-
|
|
3700
|
+
import_node_fs6 = require("fs");
|
|
3521
3701
|
import_node_path6 = require("path");
|
|
3522
3702
|
init_paths();
|
|
3523
3703
|
init_thread_store();
|
|
@@ -3597,7 +3777,7 @@ function coordinatorTurnReminder(opts) {
|
|
|
3597
3777
|
function ensureGlobalCoordinatorCwd(opts) {
|
|
3598
3778
|
const dir = globalAgentCwd();
|
|
3599
3779
|
try {
|
|
3600
|
-
(0,
|
|
3780
|
+
(0, import_node_fs7.mkdirSync)(dir, { recursive: true });
|
|
3601
3781
|
} catch {
|
|
3602
3782
|
return dir;
|
|
3603
3783
|
}
|
|
@@ -3605,7 +3785,7 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
3605
3785
|
let orchId = opts?.orchestratorThreadId?.trim() || "";
|
|
3606
3786
|
if (!orchId) {
|
|
3607
3787
|
try {
|
|
3608
|
-
const existing = (0,
|
|
3788
|
+
const existing = (0, import_node_fs7.readFileSync)((0, import_node_path7.join)(dir, "AGENTS.md"), "utf8");
|
|
3609
3789
|
const m = existing.match(
|
|
3610
3790
|
/YOUR orchestration thread id is `([0-9a-f-]{36})`/i
|
|
3611
3791
|
);
|
|
@@ -3647,9 +3827,9 @@ function ensureGlobalCoordinatorCwd(opts) {
|
|
|
3647
3827
|
"Always ask worktree agents to open draft PRs (`send_to_thread` + `gh pr create --draft -R <origin>`); never open PRs from the orchestrator."
|
|
3648
3828
|
].join("\n");
|
|
3649
3829
|
try {
|
|
3650
|
-
(0,
|
|
3830
|
+
(0, import_node_fs7.writeFileSync)((0, import_node_path7.join)(dir, "CLAUDE.md"), `${body}
|
|
3651
3831
|
`, "utf8");
|
|
3652
|
-
(0,
|
|
3832
|
+
(0, import_node_fs7.writeFileSync)((0, import_node_path7.join)(dir, "AGENTS.md"), `${body}
|
|
3653
3833
|
`, "utf8");
|
|
3654
3834
|
} catch {
|
|
3655
3835
|
}
|
|
@@ -3682,11 +3862,11 @@ function coordinatorSystemPrompt(opts) {
|
|
|
3682
3862
|
formatWorkspaceInventory(opts.workspaces)
|
|
3683
3863
|
].join("\n");
|
|
3684
3864
|
}
|
|
3685
|
-
var
|
|
3865
|
+
var import_node_fs7, import_node_path7, COORDINATOR_TOOL_PLAYBOOK;
|
|
3686
3866
|
var init_coordinator_prompt = __esm({
|
|
3687
3867
|
"src/orchestrator/coordinator-prompt.ts"() {
|
|
3688
3868
|
"use strict";
|
|
3689
|
-
|
|
3869
|
+
import_node_fs7 = require("fs");
|
|
3690
3870
|
import_node_path7 = require("path");
|
|
3691
3871
|
init_worktree();
|
|
3692
3872
|
init_app_settings();
|
|
@@ -3923,31 +4103,31 @@ function removedWorkspacesFile() {
|
|
|
3923
4103
|
}
|
|
3924
4104
|
function readAll() {
|
|
3925
4105
|
const path = workspacesFile();
|
|
3926
|
-
if (!(0,
|
|
4106
|
+
if (!(0, import_node_fs8.existsSync)(path)) return [];
|
|
3927
4107
|
try {
|
|
3928
|
-
const raw = JSON.parse((0,
|
|
4108
|
+
const raw = JSON.parse((0, import_node_fs8.readFileSync)(path, "utf8"));
|
|
3929
4109
|
return Array.isArray(raw) ? raw : [];
|
|
3930
4110
|
} catch {
|
|
3931
4111
|
return [];
|
|
3932
4112
|
}
|
|
3933
4113
|
}
|
|
3934
4114
|
function writeAll(list) {
|
|
3935
|
-
(0,
|
|
3936
|
-
(0,
|
|
4115
|
+
(0, import_node_fs8.mkdirSync)(appDataDir(), { recursive: true });
|
|
4116
|
+
(0, import_node_fs8.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
|
|
3937
4117
|
}
|
|
3938
4118
|
function readRemoved() {
|
|
3939
4119
|
const path = removedWorkspacesFile();
|
|
3940
|
-
if (!(0,
|
|
4120
|
+
if (!(0, import_node_fs8.existsSync)(path)) return /* @__PURE__ */ new Set();
|
|
3941
4121
|
try {
|
|
3942
|
-
const raw = JSON.parse((0,
|
|
4122
|
+
const raw = JSON.parse((0, import_node_fs8.readFileSync)(path, "utf8"));
|
|
3943
4123
|
return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
|
|
3944
4124
|
} catch {
|
|
3945
4125
|
return /* @__PURE__ */ new Set();
|
|
3946
4126
|
}
|
|
3947
4127
|
}
|
|
3948
4128
|
function writeRemoved(paths) {
|
|
3949
|
-
(0,
|
|
3950
|
-
(0,
|
|
4129
|
+
(0, import_node_fs8.mkdirSync)(appDataDir(), { recursive: true });
|
|
4130
|
+
(0, import_node_fs8.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
|
|
3951
4131
|
}
|
|
3952
4132
|
function rememberRemoved(repoPath) {
|
|
3953
4133
|
const next = readRemoved();
|
|
@@ -3970,7 +4150,7 @@ function listWorkspaces() {
|
|
|
3970
4150
|
async function addWorkspace(repoPath) {
|
|
3971
4151
|
const root = await resolveRepoRoot(repoPath);
|
|
3972
4152
|
if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
|
|
3973
|
-
if (!(0,
|
|
4153
|
+
if (!(0, import_node_fs8.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
|
|
3974
4154
|
forgetRemoved(root);
|
|
3975
4155
|
await ensureGhPreferOrigin(root);
|
|
3976
4156
|
const current = readAll();
|
|
@@ -4000,7 +4180,7 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
4000
4180
|
if (!path || path === "/" || isGlobalRepoPath(path) || byPath.has(path) || removed.has(path)) {
|
|
4001
4181
|
continue;
|
|
4002
4182
|
}
|
|
4003
|
-
if (!(0,
|
|
4183
|
+
if (!(0, import_node_fs8.existsSync)(path)) continue;
|
|
4004
4184
|
const ws = {
|
|
4005
4185
|
path,
|
|
4006
4186
|
name: (0, import_node_path8.basename)(path),
|
|
@@ -4013,11 +4193,11 @@ function syncWorkspacesFromThreads(repoPaths) {
|
|
|
4013
4193
|
if (dirty) writeAll(next);
|
|
4014
4194
|
return next.sort((a, b) => a.name.localeCompare(b.name));
|
|
4015
4195
|
}
|
|
4016
|
-
var
|
|
4196
|
+
var import_node_fs8, import_node_path8;
|
|
4017
4197
|
var init_workspaces = __esm({
|
|
4018
4198
|
"src/store/workspaces.ts"() {
|
|
4019
4199
|
"use strict";
|
|
4020
|
-
|
|
4200
|
+
import_node_fs8 = require("fs");
|
|
4021
4201
|
import_node_path8 = require("path");
|
|
4022
4202
|
init_paths();
|
|
4023
4203
|
init_global_workspace();
|
|
@@ -4031,26 +4211,26 @@ function brightsyConfigPath() {
|
|
|
4031
4211
|
}
|
|
4032
4212
|
function loadBrightsyConfig() {
|
|
4033
4213
|
const path = brightsyConfigPath();
|
|
4034
|
-
if (!(0,
|
|
4214
|
+
if (!(0, import_node_fs9.existsSync)(path)) {
|
|
4035
4215
|
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
4036
4216
|
}
|
|
4037
|
-
const raw = JSON.parse((0,
|
|
4217
|
+
const raw = JSON.parse((0, import_node_fs9.readFileSync)(path, "utf8"));
|
|
4038
4218
|
if (!raw.access_token || !raw.account_id) {
|
|
4039
4219
|
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
4040
4220
|
}
|
|
4041
4221
|
return raw;
|
|
4042
4222
|
}
|
|
4043
4223
|
function saveBrightsyConfig(cfg) {
|
|
4044
|
-
(0,
|
|
4224
|
+
(0, import_node_fs9.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
4045
4225
|
`, {
|
|
4046
4226
|
mode: 384
|
|
4047
4227
|
});
|
|
4048
4228
|
}
|
|
4049
|
-
var
|
|
4229
|
+
var import_node_fs9, import_node_os5, import_node_path9;
|
|
4050
4230
|
var init_config = __esm({
|
|
4051
4231
|
"src/brightsy/config.ts"() {
|
|
4052
4232
|
"use strict";
|
|
4053
|
-
|
|
4233
|
+
import_node_fs9 = require("fs");
|
|
4054
4234
|
import_node_os5 = require("os");
|
|
4055
4235
|
import_node_path9 = require("path");
|
|
4056
4236
|
}
|
|
@@ -4159,18 +4339,18 @@ function storePath() {
|
|
|
4159
4339
|
}
|
|
4160
4340
|
function readStore() {
|
|
4161
4341
|
const path = storePath();
|
|
4162
|
-
if (!(0,
|
|
4342
|
+
if (!(0, import_node_fs10.existsSync)(path)) return [];
|
|
4163
4343
|
try {
|
|
4164
|
-
const parsed = JSON.parse((0,
|
|
4344
|
+
const parsed = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf8"));
|
|
4165
4345
|
return Array.isArray(parsed.teams) ? parsed.teams : [];
|
|
4166
4346
|
} catch {
|
|
4167
4347
|
return [];
|
|
4168
4348
|
}
|
|
4169
4349
|
}
|
|
4170
4350
|
function writeStore(teams) {
|
|
4171
|
-
(0,
|
|
4351
|
+
(0, import_node_fs10.mkdirSync)(appDataDir(), { recursive: true });
|
|
4172
4352
|
const path = storePath();
|
|
4173
|
-
(0,
|
|
4353
|
+
(0, import_node_fs10.writeFileSync)(path, `${JSON.stringify({ teams }, null, 2)}
|
|
4174
4354
|
`, {
|
|
4175
4355
|
mode: 384
|
|
4176
4356
|
});
|
|
@@ -4332,11 +4512,11 @@ function brightsyMcpServerName(slug) {
|
|
|
4332
4512
|
const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
|
|
4333
4513
|
return `brightsy_${cleaned || "team"}`;
|
|
4334
4514
|
}
|
|
4335
|
-
var
|
|
4515
|
+
var import_node_fs10, import_node_path10;
|
|
4336
4516
|
var init_connected_teams = __esm({
|
|
4337
4517
|
"src/brightsy/connected-teams.ts"() {
|
|
4338
4518
|
"use strict";
|
|
4339
|
-
|
|
4519
|
+
import_node_fs10 = require("fs");
|
|
4340
4520
|
import_node_path10 = require("path");
|
|
4341
4521
|
init_paths();
|
|
4342
4522
|
init_accounts();
|
|
@@ -4511,6 +4691,11 @@ function normalizeTurnInput(input) {
|
|
|
4511
4691
|
if (typeof input === "string") return { prompt: input };
|
|
4512
4692
|
return { prompt: input.prompt, cachedPrefix: input.cachedPrefix?.trim() || void 0 };
|
|
4513
4693
|
}
|
|
4694
|
+
function dropCachedPrefixOnResume(input, sessionId) {
|
|
4695
|
+
const turn = normalizeTurnInput(input);
|
|
4696
|
+
if (sessionId) return { prompt: turn.prompt };
|
|
4697
|
+
return turn;
|
|
4698
|
+
}
|
|
4514
4699
|
function flattenTurnInput(input) {
|
|
4515
4700
|
const { cachedPrefix, prompt } = normalizeTurnInput(input);
|
|
4516
4701
|
if (!cachedPrefix) return prompt;
|
|
@@ -4699,9 +4884,13 @@ async function fetchTeamChatTargets(team) {
|
|
|
4699
4884
|
};
|
|
4700
4885
|
}
|
|
4701
4886
|
async function listBrightsyChatTargetsViaCli() {
|
|
4702
|
-
const listed = await run(
|
|
4703
|
-
|
|
4704
|
-
|
|
4887
|
+
const listed = await run(
|
|
4888
|
+
resolveAgentExecutable("brightsy"),
|
|
4889
|
+
["chat", "--list-targets", "--json"],
|
|
4890
|
+
{
|
|
4891
|
+
reject: false
|
|
4892
|
+
}
|
|
4893
|
+
);
|
|
4705
4894
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
4706
4895
|
throw new Error(
|
|
4707
4896
|
listed.stderr.trim() || "Failed to list Brightsy chat targets \u2014 is `brightsy` installed and logged in?"
|
|
@@ -4785,13 +4974,15 @@ async function syncCliForTarget(accountId) {
|
|
|
4785
4974
|
}
|
|
4786
4975
|
applyConnectedTeamToCli(team);
|
|
4787
4976
|
}
|
|
4788
|
-
var brightsyAdapter;
|
|
4977
|
+
var import_node_fs11, brightsyAdapter;
|
|
4789
4978
|
var init_brightsy = __esm({
|
|
4790
4979
|
"src/agents/brightsy.ts"() {
|
|
4791
4980
|
"use strict";
|
|
4981
|
+
import_node_fs11 = require("fs");
|
|
4792
4982
|
init_run();
|
|
4793
4983
|
init_connected_teams();
|
|
4794
4984
|
init_config();
|
|
4985
|
+
init_app_settings();
|
|
4795
4986
|
init_brightsy_targets();
|
|
4796
4987
|
init_error_detail();
|
|
4797
4988
|
init_turn_input();
|
|
@@ -4799,18 +4990,32 @@ var init_brightsy = __esm({
|
|
|
4799
4990
|
brightsyAdapter = {
|
|
4800
4991
|
kind: "brightsy",
|
|
4801
4992
|
async detect() {
|
|
4802
|
-
const
|
|
4803
|
-
if (
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4993
|
+
const brightsy = resolveAgentExecutable("brightsy");
|
|
4994
|
+
if (brightsy !== "brightsy") {
|
|
4995
|
+
if (!(0, import_node_fs11.existsSync)(brightsy)) {
|
|
4996
|
+
return {
|
|
4997
|
+
agent: "brightsy",
|
|
4998
|
+
installed: false,
|
|
4999
|
+
authenticated: false,
|
|
5000
|
+
linearMcp: false,
|
|
5001
|
+
warnings: [],
|
|
5002
|
+
reason: `Brightsy executable not found: ${brightsy}`
|
|
5003
|
+
};
|
|
5004
|
+
}
|
|
5005
|
+
} else {
|
|
5006
|
+
const which = await run("which", ["brightsy"], { reject: false });
|
|
5007
|
+
if (which.exitCode !== 0) {
|
|
5008
|
+
return {
|
|
5009
|
+
agent: "brightsy",
|
|
5010
|
+
installed: false,
|
|
5011
|
+
authenticated: false,
|
|
5012
|
+
linearMcp: false,
|
|
5013
|
+
warnings: [],
|
|
5014
|
+
reason: "brightsy CLI not found on PATH \u2014 npm i -g @brightsy/cli"
|
|
5015
|
+
};
|
|
5016
|
+
}
|
|
4812
5017
|
}
|
|
4813
|
-
const who = await run(
|
|
5018
|
+
const who = await run(brightsy, ["whoami"], { reject: false });
|
|
4814
5019
|
const authenticated = who.exitCode === 0 && /logged in as/i.test(who.stdout);
|
|
4815
5020
|
return {
|
|
4816
5021
|
agent: "brightsy",
|
|
@@ -4835,7 +5040,7 @@ var init_brightsy = __esm({
|
|
|
4835
5040
|
target.id
|
|
4836
5041
|
];
|
|
4837
5042
|
return {
|
|
4838
|
-
file: "brightsy",
|
|
5043
|
+
file: resolveAgentExecutable("brightsy"),
|
|
4839
5044
|
args,
|
|
4840
5045
|
cwd: thread.worktreePath,
|
|
4841
5046
|
// Piped stdin becomes the message body (avoids ARG_MAX for long seeds).
|
|
@@ -4852,7 +5057,11 @@ var init_brightsy = __esm({
|
|
|
4852
5057
|
const target = decodeBrightsyTarget(thread.model);
|
|
4853
5058
|
await syncCliForTarget(target.accountId);
|
|
4854
5059
|
const args = target.type === "model" ? ["chat", "--model", target.id] : ["chat", "--agent", target.id];
|
|
4855
|
-
return {
|
|
5060
|
+
return {
|
|
5061
|
+
file: resolveAgentExecutable("brightsy"),
|
|
5062
|
+
args,
|
|
5063
|
+
cwd: thread.worktreePath
|
|
5064
|
+
};
|
|
4856
5065
|
}
|
|
4857
5066
|
};
|
|
4858
5067
|
}
|
|
@@ -4904,6 +5113,18 @@ var init_claude_mcp = __esm({
|
|
|
4904
5113
|
}
|
|
4905
5114
|
});
|
|
4906
5115
|
|
|
5116
|
+
// src/mcp/profile.ts
|
|
5117
|
+
function sideboardMcpProfile(env = process.env) {
|
|
5118
|
+
return env[SIDEBOARD_MCP_PROFILE_ENV]?.trim().toLowerCase() === "worktree" ? "worktree" : "orchestration";
|
|
5119
|
+
}
|
|
5120
|
+
var SIDEBOARD_MCP_PROFILE_ENV;
|
|
5121
|
+
var init_profile = __esm({
|
|
5122
|
+
"src/mcp/profile.ts"() {
|
|
5123
|
+
"use strict";
|
|
5124
|
+
SIDEBOARD_MCP_PROFILE_ENV = "SIDEBOARD_MCP_PROFILE";
|
|
5125
|
+
}
|
|
5126
|
+
});
|
|
5127
|
+
|
|
4907
5128
|
// src/agents/node-launch.ts
|
|
4908
5129
|
function isAsarPath(filePath) {
|
|
4909
5130
|
return /\.asar([/\\]|$)/.test(filePath);
|
|
@@ -4951,6 +5172,38 @@ function isBrightsyConnected() {
|
|
|
4951
5172
|
return false;
|
|
4952
5173
|
}
|
|
4953
5174
|
}
|
|
5175
|
+
function promptMentionsBrightsy(text) {
|
|
5176
|
+
return BRIGHTSY_WORD.test(text ?? "");
|
|
5177
|
+
}
|
|
5178
|
+
function isBrightsyMcpToolName(name) {
|
|
5179
|
+
const n = name.toLowerCase();
|
|
5180
|
+
return n === "brightsy" || n.startsWith("mcp__brightsy") || n.startsWith("brightsy_");
|
|
5181
|
+
}
|
|
5182
|
+
function toolInputUsesBrightsyDatasource(input) {
|
|
5183
|
+
const ds = input?.datasource;
|
|
5184
|
+
return typeof ds === "string" && ds.toLowerCase() === "brightsy";
|
|
5185
|
+
}
|
|
5186
|
+
function messageUsedBrightsyMcp(msg) {
|
|
5187
|
+
if (msg.role === "user" && promptMentionsBrightsy(msg.text)) return true;
|
|
5188
|
+
for (const part of msg.parts ?? []) {
|
|
5189
|
+
if (part.type !== "tool") continue;
|
|
5190
|
+
if (isBrightsyMcpToolName(part.name)) return true;
|
|
5191
|
+
if (/present_(schema|files)$/i.test(part.name) && toolInputUsesBrightsyDatasource(part.input)) {
|
|
5192
|
+
return true;
|
|
5193
|
+
}
|
|
5194
|
+
}
|
|
5195
|
+
return false;
|
|
5196
|
+
}
|
|
5197
|
+
function threadRequestsBrightsyMcp(thread) {
|
|
5198
|
+
return (thread?.messages ?? []).some(messageUsedBrightsyMcp);
|
|
5199
|
+
}
|
|
5200
|
+
function shouldInjectBrightsyMcp(thread, opts) {
|
|
5201
|
+
if (!(opts?.connected ?? isBrightsyConnected())) return false;
|
|
5202
|
+
if (opts?.orchestrator) return true;
|
|
5203
|
+
const alwaysOn = opts?.alwaysOnWorktree ?? Boolean(loadAppSettings().brightsy?.injectWorktreeMcp);
|
|
5204
|
+
if (alwaysOn) return true;
|
|
5205
|
+
return threadRequestsBrightsyMcp(thread);
|
|
5206
|
+
}
|
|
4954
5207
|
function mcpLaunch(cmd, name, env) {
|
|
4955
5208
|
if (cmd === "brightsy-mcp") {
|
|
4956
5209
|
return { name, command: "brightsy-mcp", ...env ? { env } : {} };
|
|
@@ -4996,7 +5249,7 @@ function corePackageDir() {
|
|
|
4996
5249
|
}
|
|
4997
5250
|
function findSideboardMcpJsEntry() {
|
|
4998
5251
|
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
4999
|
-
if (override && (0,
|
|
5252
|
+
if (override && (0, import_node_fs12.existsSync)(override)) return override;
|
|
5000
5253
|
let dir = corePackageDir();
|
|
5001
5254
|
for (let i = 0; i < 10; i++) {
|
|
5002
5255
|
const candidates = [
|
|
@@ -5009,7 +5262,7 @@ function findSideboardMcpJsEntry() {
|
|
|
5009
5262
|
(0, import_node_path11.join)(dir, "cli/dist/index.js")
|
|
5010
5263
|
];
|
|
5011
5264
|
for (const p of candidates) {
|
|
5012
|
-
if ((0,
|
|
5265
|
+
if ((0, import_node_fs12.existsSync)(p)) return p;
|
|
5013
5266
|
}
|
|
5014
5267
|
const parent = (0, import_node_path11.dirname)(dir);
|
|
5015
5268
|
if (parent === dir) break;
|
|
@@ -5040,11 +5293,13 @@ async function buildInjectedMcpServers(opts) {
|
|
|
5040
5293
|
const servers = [];
|
|
5041
5294
|
if (opts.includeSideboard) {
|
|
5042
5295
|
const sideboard = await resolveSideboardMcpServer();
|
|
5296
|
+
const orchId = opts.orchestratorThreadId?.trim();
|
|
5297
|
+
const profile = orchId ? "orchestration" : "worktree";
|
|
5043
5298
|
sideboard.env = {
|
|
5044
5299
|
...sideboard.env ?? {},
|
|
5045
|
-
SIDEBOARD_APP_DATA: appDataDir()
|
|
5300
|
+
SIDEBOARD_APP_DATA: appDataDir(),
|
|
5301
|
+
[SIDEBOARD_MCP_PROFILE_ENV]: profile
|
|
5046
5302
|
};
|
|
5047
|
-
const orchId = opts.orchestratorThreadId?.trim();
|
|
5048
5303
|
if (orchId) {
|
|
5049
5304
|
sideboard.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID = orchId;
|
|
5050
5305
|
}
|
|
@@ -5119,19 +5374,19 @@ function writeMcpServersConfig(servers) {
|
|
|
5119
5374
|
...s.env ? { env: s.env } : {}
|
|
5120
5375
|
};
|
|
5121
5376
|
}
|
|
5122
|
-
const dir = (0,
|
|
5377
|
+
const dir = (0, import_node_fs12.mkdtempSync)((0, import_node_path11.join)((0, import_node_os6.tmpdir)(), "sideboard-mcp-"));
|
|
5123
5378
|
const cfgPath = (0, import_node_path11.join)(dir, "mcp.json");
|
|
5124
|
-
(0,
|
|
5379
|
+
(0, import_node_fs12.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
|
|
5125
5380
|
return cfgPath;
|
|
5126
5381
|
}
|
|
5127
5382
|
async function writeInjectedMcpConfig(opts) {
|
|
5128
5383
|
return writeMcpServersConfig(await buildInjectedMcpServers(opts));
|
|
5129
5384
|
}
|
|
5130
|
-
var
|
|
5385
|
+
var import_node_fs12, import_node_module, import_node_os6, import_node_path11, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
|
|
5131
5386
|
var init_injected_mcp = __esm({
|
|
5132
5387
|
"src/agents/injected-mcp.ts"() {
|
|
5133
5388
|
"use strict";
|
|
5134
|
-
|
|
5389
|
+
import_node_fs12 = require("fs");
|
|
5135
5390
|
import_node_module = require("module");
|
|
5136
5391
|
import_node_os6 = require("os");
|
|
5137
5392
|
import_node_path11 = require("path");
|
|
@@ -5139,6 +5394,8 @@ var init_injected_mcp = __esm({
|
|
|
5139
5394
|
init_run();
|
|
5140
5395
|
init_config();
|
|
5141
5396
|
init_connected_teams();
|
|
5397
|
+
init_profile();
|
|
5398
|
+
init_app_settings();
|
|
5142
5399
|
init_paths();
|
|
5143
5400
|
init_node_launch();
|
|
5144
5401
|
import_meta = {};
|
|
@@ -5158,6 +5415,7 @@ var init_injected_mcp = __esm({
|
|
|
5158
5415
|
"mcp__brightsy__*"
|
|
5159
5416
|
];
|
|
5160
5417
|
brightsyMcpCommandCache = null;
|
|
5418
|
+
BRIGHTSY_WORD = /(?<![a-z0-9_-])brightsy(?![a-z0-9_-])/i;
|
|
5161
5419
|
}
|
|
5162
5420
|
});
|
|
5163
5421
|
|
|
@@ -5312,11 +5570,11 @@ function parseIssuesJson(raw) {
|
|
|
5312
5570
|
}
|
|
5313
5571
|
return [];
|
|
5314
5572
|
}
|
|
5315
|
-
var
|
|
5573
|
+
var import_node_fs13, BASE_ALLOWED_TOOLS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
|
|
5316
5574
|
var init_claude = __esm({
|
|
5317
5575
|
"src/agents/claude.ts"() {
|
|
5318
5576
|
"use strict";
|
|
5319
|
-
|
|
5577
|
+
import_node_fs13 = require("fs");
|
|
5320
5578
|
init_run();
|
|
5321
5579
|
init_app_settings();
|
|
5322
5580
|
init_claude_mcp();
|
|
@@ -5345,7 +5603,7 @@ var init_claude = __esm({
|
|
|
5345
5603
|
async detect() {
|
|
5346
5604
|
const claude = resolveClaudeExecutable();
|
|
5347
5605
|
if (claude !== "claude") {
|
|
5348
|
-
if (!(0,
|
|
5606
|
+
if (!(0, import_node_fs13.existsSync)(claude)) {
|
|
5349
5607
|
return {
|
|
5350
5608
|
agent: "claude",
|
|
5351
5609
|
installed: false,
|
|
@@ -5384,9 +5642,8 @@ var init_claude = __esm({
|
|
|
5384
5642
|
},
|
|
5385
5643
|
async buildTurn(thread, input) {
|
|
5386
5644
|
const claude = resolveClaudeExecutable();
|
|
5387
|
-
const turn = normalizeTurnInput(input);
|
|
5388
5645
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
5389
|
-
const effective = sessionId
|
|
5646
|
+
const effective = dropCachedPrefixOnResume(input, sessionId);
|
|
5390
5647
|
const promptText = flattenTurnInput(effective);
|
|
5391
5648
|
const useStdin = promptText.length > CLAUDE_PROMPT_ARG_MAX;
|
|
5392
5649
|
if (process.env.SIDEBOARD_DEBUG_CLAUDE_TURN === "1") {
|
|
@@ -5399,7 +5656,9 @@ var init_claude = __esm({
|
|
|
5399
5656
|
const isOrchestrator = isOrchestratorThread2(thread);
|
|
5400
5657
|
const injectedServers = await buildInjectedMcpServers({
|
|
5401
5658
|
includeSideboard: true,
|
|
5402
|
-
includeBrightsy:
|
|
5659
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
5660
|
+
orchestrator: isOrchestrator
|
|
5661
|
+
}),
|
|
5403
5662
|
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
5404
5663
|
});
|
|
5405
5664
|
const injectedBrightsyNames = injectedServers.filter((s) => s.name === "brightsy" || s.name.startsWith("brightsy_")).map((s) => s.name);
|
|
@@ -5573,9 +5832,14 @@ async function listCodexModels() {
|
|
|
5573
5832
|
if (cachedCodexModels && now - cachedCodexModels.at < CODEX_MODEL_CACHE_MS) {
|
|
5574
5833
|
return cachedCodexModels.models;
|
|
5575
5834
|
}
|
|
5576
|
-
const
|
|
5577
|
-
if (
|
|
5578
|
-
|
|
5835
|
+
const codex = resolveAgentExecutable("codex");
|
|
5836
|
+
if (codex === "codex") {
|
|
5837
|
+
const which = await run("which", ["codex"], { reject: false });
|
|
5838
|
+
if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
|
|
5839
|
+
} else if (!(0, import_node_fs14.existsSync)(codex)) {
|
|
5840
|
+
return FALLBACK_CODEX_MODELS;
|
|
5841
|
+
}
|
|
5842
|
+
const listed = await run(codex, ["debug", "models"], { reject: false });
|
|
5579
5843
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
5580
5844
|
return cachedCodexModels?.models ?? FALLBACK_CODEX_MODELS;
|
|
5581
5845
|
}
|
|
@@ -5614,8 +5878,8 @@ function codexConfigHasNetworkAccess() {
|
|
|
5614
5878
|
(0, import_node_path12.join)((0, import_node_os7.homedir)(), ".config", "codex", "config.toml")
|
|
5615
5879
|
];
|
|
5616
5880
|
for (const path of candidates) {
|
|
5617
|
-
if (!(0,
|
|
5618
|
-
const text = (0,
|
|
5881
|
+
if (!(0, import_node_fs14.existsSync)(path)) continue;
|
|
5882
|
+
const text = (0, import_node_fs14.readFileSync)(path, "utf8");
|
|
5619
5883
|
if (/network_access\s*=\s*true/.test(text)) return true;
|
|
5620
5884
|
}
|
|
5621
5885
|
return false;
|
|
@@ -5648,21 +5912,23 @@ function asRecord(value) {
|
|
|
5648
5912
|
}
|
|
5649
5913
|
function codexLooksAuthenticated() {
|
|
5650
5914
|
const authPath = (0, import_node_path12.join)((0, import_node_os7.homedir)(), ".codex", "auth.json");
|
|
5651
|
-
if (!(0,
|
|
5915
|
+
if (!(0, import_node_fs14.existsSync)(authPath)) return false;
|
|
5652
5916
|
try {
|
|
5653
|
-
return (0,
|
|
5917
|
+
return (0, import_node_fs14.statSync)(authPath).size > 2;
|
|
5654
5918
|
} catch {
|
|
5655
5919
|
return false;
|
|
5656
5920
|
}
|
|
5657
5921
|
}
|
|
5658
|
-
var
|
|
5922
|
+
var import_node_fs14, import_node_os7, import_node_path12, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
|
|
5659
5923
|
var init_codex = __esm({
|
|
5660
5924
|
"src/agents/codex.ts"() {
|
|
5661
5925
|
"use strict";
|
|
5662
|
-
|
|
5926
|
+
import_node_fs14 = require("fs");
|
|
5663
5927
|
import_node_os7 = require("os");
|
|
5664
5928
|
import_node_path12 = require("path");
|
|
5665
5929
|
init_run();
|
|
5930
|
+
init_app_settings();
|
|
5931
|
+
init_global_workspace();
|
|
5666
5932
|
init_error_detail();
|
|
5667
5933
|
init_injected_mcp();
|
|
5668
5934
|
init_turn_input();
|
|
@@ -5680,16 +5946,30 @@ var init_codex = __esm({
|
|
|
5680
5946
|
codexAdapter = {
|
|
5681
5947
|
kind: "codex",
|
|
5682
5948
|
async detect() {
|
|
5683
|
-
const
|
|
5684
|
-
if (
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5949
|
+
const codex = resolveAgentExecutable("codex");
|
|
5950
|
+
if (codex !== "codex") {
|
|
5951
|
+
if (!(0, import_node_fs14.existsSync)(codex)) {
|
|
5952
|
+
return {
|
|
5953
|
+
agent: "codex",
|
|
5954
|
+
installed: false,
|
|
5955
|
+
authenticated: false,
|
|
5956
|
+
linearMcp: false,
|
|
5957
|
+
warnings: [],
|
|
5958
|
+
reason: `Codex executable not found: ${codex}`
|
|
5959
|
+
};
|
|
5960
|
+
}
|
|
5961
|
+
} else {
|
|
5962
|
+
const which = await run("which", ["codex"], { reject: false, timeoutMs: 3e3 });
|
|
5963
|
+
if (which.exitCode !== 0) {
|
|
5964
|
+
return {
|
|
5965
|
+
agent: "codex",
|
|
5966
|
+
installed: false,
|
|
5967
|
+
authenticated: false,
|
|
5968
|
+
linearMcp: false,
|
|
5969
|
+
warnings: [],
|
|
5970
|
+
reason: "codex CLI not found on PATH"
|
|
5971
|
+
};
|
|
5972
|
+
}
|
|
5693
5973
|
}
|
|
5694
5974
|
const authenticated = codexLooksAuthenticated();
|
|
5695
5975
|
const linearMcp = false;
|
|
@@ -5709,22 +5989,24 @@ var init_codex = __esm({
|
|
|
5709
5989
|
};
|
|
5710
5990
|
},
|
|
5711
5991
|
async buildTurn(thread, input) {
|
|
5712
|
-
const prompt = flattenTurnInput(input);
|
|
5713
5992
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
5993
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, sessionId));
|
|
5714
5994
|
const useStdin = prompt.length > CODEX_PROMPT_ARG_MAX;
|
|
5715
5995
|
const promptArg = useStdin ? "-" : prompt;
|
|
5716
5996
|
if (process.env.SIDEBOARD_DEBUG_CODEX_TURN === "1") {
|
|
5717
|
-
const { cachedPrefix } = normalizeTurnInput(input);
|
|
5718
5997
|
console.error(
|
|
5719
|
-
`[sideboard/codex] promptChars=${prompt.length} resumed=${Boolean(sessionId)} stdin=${useStdin} hasPrefix=${
|
|
5998
|
+
`[sideboard/codex] promptChars=${prompt.length} resumed=${Boolean(sessionId)} stdin=${useStdin} hasPrefix=${prompt.includes("Current request:")}`
|
|
5720
5999
|
);
|
|
5721
6000
|
}
|
|
5722
6001
|
const mode = permissionMode(thread);
|
|
5723
6002
|
const model = thread.model?.trim();
|
|
6003
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
5724
6004
|
const injected = await buildInjectedMcpServers({
|
|
5725
6005
|
includeSideboard: true,
|
|
5726
|
-
includeBrightsy:
|
|
5727
|
-
|
|
6006
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
6007
|
+
orchestrator: isOrchestrator
|
|
6008
|
+
}),
|
|
6009
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
5728
6010
|
});
|
|
5729
6011
|
const mcpOverrides = toCodexMcpConfigArgs(injected);
|
|
5730
6012
|
const execOpts = [
|
|
@@ -5744,7 +6026,7 @@ var init_codex = __esm({
|
|
|
5744
6026
|
];
|
|
5745
6027
|
const args = sessionId ? ["exec", ...execOpts, "resume", sessionId, promptArg] : ["exec", ...execOpts, promptArg];
|
|
5746
6028
|
return {
|
|
5747
|
-
file: "codex",
|
|
6029
|
+
file: resolveAgentExecutable("codex"),
|
|
5748
6030
|
args,
|
|
5749
6031
|
cwd: thread.worktreePath,
|
|
5750
6032
|
stdin: useStdin ? `${prompt}
|
|
@@ -5840,16 +6122,17 @@ var init_codex = __esm({
|
|
|
5840
6122
|
return cached;
|
|
5841
6123
|
},
|
|
5842
6124
|
async buildAttach(thread) {
|
|
6125
|
+
const codex = resolveAgentExecutable("codex");
|
|
5843
6126
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
5844
6127
|
if (sessionId) {
|
|
5845
6128
|
return {
|
|
5846
|
-
file:
|
|
6129
|
+
file: codex,
|
|
5847
6130
|
args: ["exec", "--cd", thread.worktreePath, "resume", sessionId],
|
|
5848
6131
|
cwd: thread.worktreePath
|
|
5849
6132
|
};
|
|
5850
6133
|
}
|
|
5851
6134
|
return {
|
|
5852
|
-
file:
|
|
6135
|
+
file: codex,
|
|
5853
6136
|
args: ["--cd", thread.worktreePath],
|
|
5854
6137
|
cwd: thread.worktreePath
|
|
5855
6138
|
};
|
|
@@ -5857,7 +6140,7 @@ var init_codex = __esm({
|
|
|
5857
6140
|
async listLinearIssues(_repoPath) {
|
|
5858
6141
|
const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
|
|
5859
6142
|
const { stdout, exitCode } = await run(
|
|
5860
|
-
"codex",
|
|
6143
|
+
resolveAgentExecutable("codex"),
|
|
5861
6144
|
[
|
|
5862
6145
|
"exec",
|
|
5863
6146
|
"--json",
|
|
@@ -6120,21 +6403,22 @@ function cursorRunnerPath() {
|
|
|
6120
6403
|
(0, import_node_path13.join)(root, "src", "agents", "cursor-runner.ts")
|
|
6121
6404
|
];
|
|
6122
6405
|
for (const candidate of candidates) {
|
|
6123
|
-
if ((0,
|
|
6406
|
+
if ((0, import_node_fs15.existsSync)(candidate)) return candidate;
|
|
6124
6407
|
}
|
|
6125
6408
|
return candidates[0];
|
|
6126
6409
|
}
|
|
6127
|
-
var
|
|
6410
|
+
var import_node_fs15, import_node_module2, import_node_path13, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
|
|
6128
6411
|
var init_cursor = __esm({
|
|
6129
6412
|
"src/agents/cursor.ts"() {
|
|
6130
6413
|
"use strict";
|
|
6131
|
-
|
|
6414
|
+
import_node_fs15 = require("fs");
|
|
6132
6415
|
import_node_module2 = require("module");
|
|
6133
6416
|
import_node_path13 = require("path");
|
|
6134
6417
|
import_node_url2 = require("url");
|
|
6135
6418
|
import_sdk = require("@cursor/sdk");
|
|
6136
6419
|
init_run();
|
|
6137
6420
|
init_app_settings();
|
|
6421
|
+
init_global_workspace();
|
|
6138
6422
|
init_cursor_events();
|
|
6139
6423
|
init_injected_mcp();
|
|
6140
6424
|
init_node_launch();
|
|
@@ -6171,13 +6455,16 @@ var init_cursor = __esm({
|
|
|
6171
6455
|
};
|
|
6172
6456
|
},
|
|
6173
6457
|
async buildTurn(thread, input) {
|
|
6174
|
-
const prompt = flattenTurnInput(input);
|
|
6175
6458
|
const agentId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
6459
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, agentId));
|
|
6176
6460
|
const apiKey = resolveCursorApiKey() || void 0;
|
|
6461
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
6177
6462
|
const injected = await buildInjectedMcpServers({
|
|
6178
6463
|
includeSideboard: true,
|
|
6179
|
-
includeBrightsy:
|
|
6180
|
-
|
|
6464
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
6465
|
+
orchestrator: isOrchestrator
|
|
6466
|
+
}),
|
|
6467
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
6181
6468
|
});
|
|
6182
6469
|
const mcpServers = toCursorMcpServers(injected);
|
|
6183
6470
|
const req = {
|
|
@@ -6248,9 +6535,14 @@ async function listOpencodeModels() {
|
|
|
6248
6535
|
if (cachedOpencodeModels && now - cachedOpencodeModels.at < OPENCODE_MODEL_CACHE_MS) {
|
|
6249
6536
|
return cachedOpencodeModels.models;
|
|
6250
6537
|
}
|
|
6251
|
-
const
|
|
6252
|
-
if (
|
|
6253
|
-
|
|
6538
|
+
const opencode = resolveAgentExecutable("opencode");
|
|
6539
|
+
if (opencode === "opencode") {
|
|
6540
|
+
const which = await run("which", ["opencode"], { reject: false });
|
|
6541
|
+
if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
|
|
6542
|
+
} else if (!(0, import_node_fs16.existsSync)(opencode)) {
|
|
6543
|
+
return FALLBACK_OPENCODE_MODELS;
|
|
6544
|
+
}
|
|
6545
|
+
const listed = await run(opencode, ["models"], { reject: false });
|
|
6254
6546
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
6255
6547
|
return cachedOpencodeModels?.models ?? FALLBACK_OPENCODE_MODELS;
|
|
6256
6548
|
}
|
|
@@ -6277,11 +6569,14 @@ function usageFromOpencode(tokens) {
|
|
|
6277
6569
|
cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
|
|
6278
6570
|
};
|
|
6279
6571
|
}
|
|
6280
|
-
var FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
|
|
6572
|
+
var import_node_fs16, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
|
|
6281
6573
|
var init_opencode = __esm({
|
|
6282
6574
|
"src/agents/opencode.ts"() {
|
|
6283
6575
|
"use strict";
|
|
6576
|
+
import_node_fs16 = require("fs");
|
|
6284
6577
|
init_run();
|
|
6578
|
+
init_app_settings();
|
|
6579
|
+
init_global_workspace();
|
|
6285
6580
|
init_error_detail();
|
|
6286
6581
|
init_injected_mcp();
|
|
6287
6582
|
init_turn_input();
|
|
@@ -6302,20 +6597,34 @@ var init_opencode = __esm({
|
|
|
6302
6597
|
opencodeAdapter = {
|
|
6303
6598
|
kind: "opencode",
|
|
6304
6599
|
async detect() {
|
|
6305
|
-
const
|
|
6306
|
-
if (
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6600
|
+
const opencode = resolveAgentExecutable("opencode");
|
|
6601
|
+
if (opencode !== "opencode") {
|
|
6602
|
+
if (!(0, import_node_fs16.existsSync)(opencode)) {
|
|
6603
|
+
return {
|
|
6604
|
+
agent: "opencode",
|
|
6605
|
+
installed: false,
|
|
6606
|
+
authenticated: false,
|
|
6607
|
+
linearMcp: false,
|
|
6608
|
+
warnings: [],
|
|
6609
|
+
reason: `OpenCode executable not found: ${opencode}`
|
|
6610
|
+
};
|
|
6611
|
+
}
|
|
6612
|
+
} else {
|
|
6613
|
+
const which = await run("which", ["opencode"], { reject: false });
|
|
6614
|
+
if (which.exitCode !== 0) {
|
|
6615
|
+
return {
|
|
6616
|
+
agent: "opencode",
|
|
6617
|
+
installed: false,
|
|
6618
|
+
authenticated: false,
|
|
6619
|
+
linearMcp: false,
|
|
6620
|
+
warnings: [],
|
|
6621
|
+
reason: "opencode CLI not found on PATH"
|
|
6622
|
+
};
|
|
6623
|
+
}
|
|
6315
6624
|
}
|
|
6316
|
-
const auth = await run(
|
|
6625
|
+
const auth = await run(opencode, ["auth", "list"], { reject: false });
|
|
6317
6626
|
const authenticated = auth.exitCode === 0 && auth.stdout.trim().length > 0;
|
|
6318
|
-
const mcp = await run(
|
|
6627
|
+
const mcp = await run(opencode, ["mcp", "list"], { reject: false });
|
|
6319
6628
|
const linearMcp = /linear/i.test(mcp.stdout + mcp.stderr);
|
|
6320
6629
|
return {
|
|
6321
6630
|
agent: "opencode",
|
|
@@ -6327,8 +6636,8 @@ var init_opencode = __esm({
|
|
|
6327
6636
|
};
|
|
6328
6637
|
},
|
|
6329
6638
|
async buildTurn(thread, input) {
|
|
6330
|
-
const prompt = flattenTurnInput(input);
|
|
6331
6639
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
6640
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, sessionId));
|
|
6332
6641
|
const mode = permissionMode(thread);
|
|
6333
6642
|
const model = thread.model?.trim();
|
|
6334
6643
|
const args = [
|
|
@@ -6344,14 +6653,17 @@ var init_opencode = __esm({
|
|
|
6344
6653
|
if (model) {
|
|
6345
6654
|
args.push("--model", model);
|
|
6346
6655
|
}
|
|
6656
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
6347
6657
|
const injected = await buildInjectedMcpServers({
|
|
6348
6658
|
includeSideboard: true,
|
|
6349
|
-
includeBrightsy:
|
|
6350
|
-
|
|
6659
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
6660
|
+
orchestrator: isOrchestrator
|
|
6661
|
+
}),
|
|
6662
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
6351
6663
|
});
|
|
6352
6664
|
const mcpContent = injected.length > 0 ? toOpencodeMcpConfigContent(injected) : null;
|
|
6353
6665
|
return {
|
|
6354
|
-
file: "opencode",
|
|
6666
|
+
file: resolveAgentExecutable("opencode"),
|
|
6355
6667
|
args,
|
|
6356
6668
|
cwd: thread.worktreePath,
|
|
6357
6669
|
// `opencode run` treats non-TTY stdin as the message body when no positional
|
|
@@ -6427,7 +6739,7 @@ var init_opencode = __esm({
|
|
|
6427
6739
|
async resolveSessionId(worktreePath, cached) {
|
|
6428
6740
|
const cachedId = cached?.trim() || null;
|
|
6429
6741
|
const listed = await run(
|
|
6430
|
-
"opencode",
|
|
6742
|
+
resolveAgentExecutable("opencode"),
|
|
6431
6743
|
["session", "list", "--format", "json"],
|
|
6432
6744
|
{ cwd: worktreePath, reject: false }
|
|
6433
6745
|
);
|
|
@@ -6458,7 +6770,7 @@ var init_opencode = __esm({
|
|
|
6458
6770
|
const args = ["--dir", thread.worktreePath];
|
|
6459
6771
|
if (sessionId) args.push("--session", sessionId);
|
|
6460
6772
|
return {
|
|
6461
|
-
file: "opencode",
|
|
6773
|
+
file: resolveAgentExecutable("opencode"),
|
|
6462
6774
|
args,
|
|
6463
6775
|
cwd: thread.worktreePath,
|
|
6464
6776
|
env: {
|
|
@@ -6469,7 +6781,7 @@ var init_opencode = __esm({
|
|
|
6469
6781
|
async listLinearIssues(_repoPath) {
|
|
6470
6782
|
const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
|
|
6471
6783
|
const { stdout, exitCode } = await run(
|
|
6472
|
-
"opencode",
|
|
6784
|
+
resolveAgentExecutable("opencode"),
|
|
6473
6785
|
["run", prompt, "--format", "json"],
|
|
6474
6786
|
{
|
|
6475
6787
|
reject: false,
|
|
@@ -6702,9 +7014,30 @@ function getAgentSetupInfo(agent) {
|
|
|
6702
7014
|
function listAgentSetupInfo() {
|
|
6703
7015
|
return Object.values(SETUP);
|
|
6704
7016
|
}
|
|
6705
|
-
|
|
6706
|
-
|
|
7017
|
+
function resolveLoginCommand(agent) {
|
|
7018
|
+
const info = getAgentSetupInfo(agent);
|
|
7019
|
+
if (!info.loginCommand) return null;
|
|
7020
|
+
if (!CLI_LOGIN_AGENTS.has(agent)) return info.loginCommand;
|
|
7021
|
+
const exe = resolveAgentExecutable(agent);
|
|
7022
|
+
return info.loginCommand.replace(/^\S+/, exe);
|
|
7023
|
+
}
|
|
7024
|
+
async function prepareTerminalCommand(command) {
|
|
7025
|
+
enrichPathWithNpmGlobalBin();
|
|
6707
7026
|
const trimmed = command.trim();
|
|
7027
|
+
if (!trimmed) return trimmed;
|
|
7028
|
+
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
7029
|
+
const match = /^(\S+)(\s[\s\S]*)?$/.exec(trimmed);
|
|
7030
|
+
const bin = match?.[1];
|
|
7031
|
+
let whichPath = null;
|
|
7032
|
+
if (bin && !bin.includes("/") && !bin.includes("\\")) {
|
|
7033
|
+
const which = await run("which", [bin], { reject: false, timeoutMs: 3e3 });
|
|
7034
|
+
whichPath = which.exitCode === 0 ? which.stdout.trim() : null;
|
|
7035
|
+
}
|
|
7036
|
+
const resolved = resolveCommandBinarySync(trimmed, whichPath);
|
|
7037
|
+
return withExportedPath(resolved, process.env.PATH ?? "");
|
|
7038
|
+
}
|
|
7039
|
+
async function openInSystemTerminal(command) {
|
|
7040
|
+
const trimmed = (await prepareTerminalCommand(command)).trim();
|
|
6708
7041
|
if (!trimmed) throw new Error("Command is empty");
|
|
6709
7042
|
if (process.platform === "darwin") {
|
|
6710
7043
|
const escaped = trimmed.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
@@ -6765,7 +7098,7 @@ async function installAgent(agent) {
|
|
|
6765
7098
|
message: `Opened Terminal to run: ${info.installCommand}`
|
|
6766
7099
|
};
|
|
6767
7100
|
}
|
|
6768
|
-
|
|
7101
|
+
enrichPathWithNpmGlobalBin();
|
|
6769
7102
|
const result = await run("npm", ["install", "-g", info.npmPackage], { reject: false });
|
|
6770
7103
|
const ok = result.exitCode === 0;
|
|
6771
7104
|
if (!ok) {
|
|
@@ -6791,36 +7124,46 @@ async function installAgent(agent) {
|
|
|
6791
7124
|
};
|
|
6792
7125
|
}
|
|
6793
7126
|
}
|
|
7127
|
+
enrichPathWithNpmGlobalBin();
|
|
7128
|
+
const cliBin = agent === "cursor" ? null : CLI_BIN[agent];
|
|
7129
|
+
let binPath = null;
|
|
7130
|
+
if (cliBin) {
|
|
7131
|
+
const which = await run("which", [cliBin], { reject: false, timeoutMs: 3e3 });
|
|
7132
|
+
binPath = which.exitCode === 0 ? which.stdout.trim().split(/\r?\n/).find(Boolean) ?? null : null;
|
|
7133
|
+
}
|
|
6794
7134
|
return {
|
|
6795
7135
|
ok: true,
|
|
6796
7136
|
command: info.installCommand,
|
|
6797
7137
|
exitCode: 0,
|
|
6798
7138
|
stdout: result.stdout,
|
|
6799
7139
|
stderr: result.stderr,
|
|
6800
|
-
message: `Installed ${info.npmPackage}`
|
|
7140
|
+
message: binPath ? `Installed ${info.npmPackage} \u2192 ${binPath}` : `Installed ${info.npmPackage} (CLI not yet on PATH \u2014 Log in still exports Electron\u2019s PATH into Terminal)`
|
|
6801
7141
|
};
|
|
6802
7142
|
}
|
|
6803
7143
|
async function loginAgent(agent) {
|
|
6804
7144
|
const info = getAgentSetupInfo(agent);
|
|
6805
|
-
|
|
7145
|
+
const loginCommand = resolveLoginCommand(agent);
|
|
7146
|
+
if (!loginCommand) {
|
|
6806
7147
|
return {
|
|
6807
7148
|
ok: true,
|
|
6808
7149
|
message: info.kind === "bundled-sdk" || info.kind === "api-key" ? info.summary : `No login command for ${agent}`
|
|
6809
7150
|
};
|
|
6810
7151
|
}
|
|
6811
|
-
await
|
|
7152
|
+
const prepared = await prepareTerminalCommand(loginCommand);
|
|
7153
|
+
await openInSystemTerminal(prepared);
|
|
6812
7154
|
return {
|
|
6813
7155
|
ok: true,
|
|
6814
7156
|
openedTerminal: true,
|
|
6815
|
-
command:
|
|
6816
|
-
message: `Opened Terminal to run: ${
|
|
7157
|
+
command: prepared,
|
|
7158
|
+
message: `Opened Terminal to run: ${prepared}`
|
|
6817
7159
|
};
|
|
6818
7160
|
}
|
|
6819
|
-
var SETUP;
|
|
7161
|
+
var SETUP, CLI_BIN, CLI_LOGIN_AGENTS;
|
|
6820
7162
|
var init_install = __esm({
|
|
6821
7163
|
"src/agents/install.ts"() {
|
|
6822
7164
|
"use strict";
|
|
6823
7165
|
init_run();
|
|
7166
|
+
init_app_settings();
|
|
6824
7167
|
init_path();
|
|
6825
7168
|
SETUP = {
|
|
6826
7169
|
claude: {
|
|
@@ -6869,6 +7212,18 @@ var init_install = __esm({
|
|
|
6869
7212
|
npmPackage: "@brightsy/cli"
|
|
6870
7213
|
}
|
|
6871
7214
|
};
|
|
7215
|
+
CLI_BIN = {
|
|
7216
|
+
claude: "claude",
|
|
7217
|
+
codex: "codex",
|
|
7218
|
+
opencode: "opencode",
|
|
7219
|
+
brightsy: "brightsy"
|
|
7220
|
+
};
|
|
7221
|
+
CLI_LOGIN_AGENTS = /* @__PURE__ */ new Set([
|
|
7222
|
+
"claude",
|
|
7223
|
+
"codex",
|
|
7224
|
+
"opencode",
|
|
7225
|
+
"brightsy"
|
|
7226
|
+
]);
|
|
6872
7227
|
}
|
|
6873
7228
|
});
|
|
6874
7229
|
|
|
@@ -6888,6 +7243,7 @@ __export(agents_exports, {
|
|
|
6888
7243
|
cursorSdkMessageToEvents: () => cursorSdkMessageToEvents,
|
|
6889
7244
|
decodeBrightsyTarget: () => decodeBrightsyTarget,
|
|
6890
7245
|
encodeBrightsyTarget: () => encodeBrightsyTarget,
|
|
7246
|
+
enrichPathWithNpmGlobalBin: () => enrichPathWithNpmGlobalBin,
|
|
6891
7247
|
ensureAgentPath: () => ensureAgentPath,
|
|
6892
7248
|
getAdapter: () => getAdapter,
|
|
6893
7249
|
getAgentSetupInfo: () => getAgentSetupInfo,
|
|
@@ -6907,8 +7263,13 @@ __export(agents_exports, {
|
|
|
6907
7263
|
parseCursorRunnerLine: () => parseCursorRunnerLine,
|
|
6908
7264
|
parseSessionQuotaResetAt: () => parseSessionQuotaResetAt,
|
|
6909
7265
|
permissionMode: () => permissionMode,
|
|
7266
|
+
posixShellSingleQuote: () => posixShellSingleQuote,
|
|
7267
|
+
prepareTerminalCommand: () => prepareTerminalCommand,
|
|
7268
|
+
resolveCommandBinarySync: () => resolveCommandBinarySync,
|
|
6910
7269
|
resolveCursorModelId: () => resolveCursorModelId,
|
|
6911
|
-
|
|
7270
|
+
resolveLoginCommand: () => resolveLoginCommand,
|
|
7271
|
+
resolveQuotaFallbackAgent: () => resolveQuotaFallbackAgent,
|
|
7272
|
+
withExportedPath: () => withExportedPath
|
|
6912
7273
|
});
|
|
6913
7274
|
function getAdapter(kind) {
|
|
6914
7275
|
return adapters[kind];
|
|
@@ -7020,17 +7381,17 @@ __export(plan_file_exports, {
|
|
|
7020
7381
|
});
|
|
7021
7382
|
function ensureAttachmentsGitignore2(worktreePath) {
|
|
7022
7383
|
const gitignoreAbs = (0, import_node_path24.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
7023
|
-
if ((0,
|
|
7024
|
-
(0,
|
|
7025
|
-
(0,
|
|
7384
|
+
if ((0, import_node_fs29.existsSync)(gitignoreAbs)) return;
|
|
7385
|
+
(0, import_node_fs29.mkdirSync)((0, import_node_path24.dirname)(gitignoreAbs), { recursive: true });
|
|
7386
|
+
(0, import_node_fs29.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
7026
7387
|
}
|
|
7027
7388
|
function planFileAbs(worktreePath) {
|
|
7028
7389
|
return (0, import_node_path24.join)(worktreePath, PLAN_FILE_REL);
|
|
7029
7390
|
}
|
|
7030
7391
|
function readTextIfPresent2(abs) {
|
|
7031
|
-
if (!(0,
|
|
7392
|
+
if (!(0, import_node_fs29.existsSync)(abs)) return null;
|
|
7032
7393
|
try {
|
|
7033
|
-
const content = (0,
|
|
7394
|
+
const content = (0, import_node_fs29.readFileSync)(abs, "utf8");
|
|
7034
7395
|
return content.trim() ? content : null;
|
|
7035
7396
|
} catch {
|
|
7036
7397
|
return null;
|
|
@@ -7042,16 +7403,16 @@ function readPlanFile(worktreePath) {
|
|
|
7042
7403
|
function writePlanFile(worktreePath, content) {
|
|
7043
7404
|
ensureAttachmentsGitignore2(worktreePath);
|
|
7044
7405
|
const abs = planFileAbs(worktreePath);
|
|
7045
|
-
(0,
|
|
7406
|
+
(0, import_node_fs29.mkdirSync)((0, import_node_path24.dirname)(abs), { recursive: true });
|
|
7046
7407
|
const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
|
|
7047
|
-
(0,
|
|
7408
|
+
(0, import_node_fs29.writeFileSync)(abs, body, "utf8");
|
|
7048
7409
|
return PLAN_FILE_REL;
|
|
7049
7410
|
}
|
|
7050
|
-
var
|
|
7411
|
+
var import_node_fs29, import_node_path24;
|
|
7051
7412
|
var init_plan_file = __esm({
|
|
7052
7413
|
"src/plan/plan-file.ts"() {
|
|
7053
7414
|
"use strict";
|
|
7054
|
-
|
|
7415
|
+
import_node_fs29 = require("fs");
|
|
7055
7416
|
import_node_path24 = require("path");
|
|
7056
7417
|
init_workspace_scratch();
|
|
7057
7418
|
init_plan_present();
|
|
@@ -7068,9 +7429,9 @@ function recoverFinishedCursorRun(opts) {
|
|
|
7068
7429
|
const agentId = opts.agentId.trim();
|
|
7069
7430
|
if (!agentId) return null;
|
|
7070
7431
|
const runsPath = (0, import_node_path25.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
|
|
7071
|
-
if (!(0,
|
|
7432
|
+
if (!(0, import_node_fs30.existsSync)(runsPath)) return null;
|
|
7072
7433
|
try {
|
|
7073
|
-
const lines = (0,
|
|
7434
|
+
const lines = (0, import_node_fs30.readFileSync)(runsPath, "utf8").split("\n");
|
|
7074
7435
|
let best = null;
|
|
7075
7436
|
for (const line of lines) {
|
|
7076
7437
|
const trimmed = line.trim();
|
|
@@ -7096,11 +7457,11 @@ function recoverFinishedCursorRun(opts) {
|
|
|
7096
7457
|
return null;
|
|
7097
7458
|
}
|
|
7098
7459
|
}
|
|
7099
|
-
var
|
|
7460
|
+
var import_node_fs30, import_node_path25;
|
|
7100
7461
|
var init_cursor_recover = __esm({
|
|
7101
7462
|
"src/agents/cursor-recover.ts"() {
|
|
7102
7463
|
"use strict";
|
|
7103
|
-
|
|
7464
|
+
import_node_fs30 = require("fs");
|
|
7104
7465
|
import_node_path25 = require("path");
|
|
7105
7466
|
init_paths();
|
|
7106
7467
|
}
|
|
@@ -7174,6 +7535,7 @@ __export(index_exports, {
|
|
|
7174
7535
|
REVIEW_REQUEST_PREFILL: () => REVIEW_REQUEST_PREFILL,
|
|
7175
7536
|
SIDEBOARD_FORCE_STOP: () => SIDEBOARD_FORCE_STOP,
|
|
7176
7537
|
SIDEBOARD_MCP_ALLOWED_TOOLS: () => SIDEBOARD_MCP_ALLOWED_TOOLS,
|
|
7538
|
+
SIDEBOARD_MCP_PROFILE_ENV: () => SIDEBOARD_MCP_PROFILE_ENV,
|
|
7177
7539
|
THINKING_EFFORTS: () => THINKING_EFFORTS,
|
|
7178
7540
|
addPrStackLayer: () => addPrStackLayer,
|
|
7179
7541
|
addStackLayerFromThread: () => addStackLayerFromThread,
|
|
@@ -7196,6 +7558,7 @@ __export(index_exports, {
|
|
|
7196
7558
|
attachmentsFromBuffers: () => attachmentsFromBuffers,
|
|
7197
7559
|
attachmentsFromWorktreePaths: () => attachmentsFromWorktreePaths,
|
|
7198
7560
|
attachmentsGitignoreBody: () => attachmentsGitignoreBody,
|
|
7561
|
+
autoArchiveOnMergeEnabled: () => autoArchiveOnMergeEnabled,
|
|
7199
7562
|
autoCleanupOrphansEnabled: () => autoCleanupOrphansEnabled,
|
|
7200
7563
|
autoRenameBranchEnabled: () => autoRenameBranchEnabled,
|
|
7201
7564
|
autoRunAfterSetupEnabled: () => autoRunAfterSetupEnabled,
|
|
@@ -7204,6 +7567,7 @@ __export(index_exports, {
|
|
|
7204
7567
|
brightsyCloudConnectAgent: () => brightsyCloudConnectAgent,
|
|
7205
7568
|
brightsyCloudConnectEnabled: () => brightsyCloudConnectEnabled,
|
|
7206
7569
|
brightsyConfigPath: () => brightsyConfigPath,
|
|
7570
|
+
brightsyInjectWorktreeMcpEnabled: () => brightsyInjectWorktreeMcpEnabled,
|
|
7207
7571
|
brightsyMcpAllowedTools: () => brightsyMcpAllowedTools,
|
|
7208
7572
|
brightsyMcpServerName: () => brightsyMcpServerName,
|
|
7209
7573
|
buildCachedUserContent: () => buildCachedUserContent,
|
|
@@ -7255,7 +7619,9 @@ __export(index_exports, {
|
|
|
7255
7619
|
detectLocalMergeConflicts: () => detectLocalMergeConflicts,
|
|
7256
7620
|
disconnectBrightsyTeam: () => disconnectBrightsyTeam,
|
|
7257
7621
|
discoverSkills: () => discoverSkills,
|
|
7622
|
+
dropCachedPrefixOnResume: () => dropCachedPrefixOnResume,
|
|
7258
7623
|
encodeBrightsyTarget: () => encodeBrightsyTarget,
|
|
7624
|
+
enrichPathWithNpmGlobalBin: () => enrichPathWithNpmGlobalBin,
|
|
7259
7625
|
enrichWorkspacesWithGithub: () => enrichWorkspacesWithGithub,
|
|
7260
7626
|
ensureAgentPath: () => ensureAgentPath,
|
|
7261
7627
|
ensureCloudCoordinator: () => ensureCloudCoordinator,
|
|
@@ -7293,6 +7659,7 @@ __export(index_exports, {
|
|
|
7293
7659
|
formatTranscriptMarkdown: () => formatTranscriptMarkdown,
|
|
7294
7660
|
formatWorkspaceInventory: () => formatWorkspaceInventory,
|
|
7295
7661
|
formatWorktreeDirective: () => formatWorktreeDirective,
|
|
7662
|
+
formatWorktreeReminder: () => formatWorktreeReminder,
|
|
7296
7663
|
getAdapter: () => getAdapter,
|
|
7297
7664
|
getAgentSetupInfo: () => getAgentSetupInfo,
|
|
7298
7665
|
getBrightsySession: () => getBrightsySession,
|
|
@@ -7419,7 +7786,10 @@ __export(index_exports, {
|
|
|
7419
7786
|
pastedTextStats: () => pastedTextStats,
|
|
7420
7787
|
permissionMode: () => permissionMode,
|
|
7421
7788
|
planFileAbs: () => planFileAbs,
|
|
7789
|
+
posixShellSingleQuote: () => posixShellSingleQuote,
|
|
7790
|
+
prepareTerminalCommand: () => prepareTerminalCommand,
|
|
7422
7791
|
previewLand: () => previewLand,
|
|
7792
|
+
promptMentionsBrightsy: () => promptMentionsBrightsy,
|
|
7423
7793
|
pushBranch: () => pushBranch,
|
|
7424
7794
|
readExistingReviewRequestFile: () => readExistingReviewRequestFile,
|
|
7425
7795
|
readPlanFile: () => readPlanFile,
|
|
@@ -7435,7 +7805,9 @@ __export(index_exports, {
|
|
|
7435
7805
|
requestReview: () => requestReview,
|
|
7436
7806
|
requireAgent: () => requireAgent,
|
|
7437
7807
|
resetGhStackDetectCache: () => resetGhStackDetectCache,
|
|
7808
|
+
resolveAgentExecutable: () => resolveAgentExecutable,
|
|
7438
7809
|
resolveClaudeExecutable: () => resolveClaudeExecutable,
|
|
7810
|
+
resolveCommandBinarySync: () => resolveCommandBinarySync,
|
|
7439
7811
|
resolveConductorCursorAgentId: () => resolveConductorCursorAgentId,
|
|
7440
7812
|
resolveCursorModelId: () => resolveCursorModelId,
|
|
7441
7813
|
resolveDefaultBranch: () => resolveDefaultBranch,
|
|
@@ -7444,6 +7816,7 @@ __export(index_exports, {
|
|
|
7444
7816
|
resolveFilesToCopy: () => resolveFilesToCopy,
|
|
7445
7817
|
resolveGhAuthToken: () => resolveGhAuthToken,
|
|
7446
7818
|
resolveGithubRepoSlug: () => resolveGithubRepoSlug,
|
|
7819
|
+
resolveLoginCommand: () => resolveLoginCommand,
|
|
7447
7820
|
resolveNewThreadOptions: () => resolveNewThreadOptions,
|
|
7448
7821
|
resolvePlanMarkdown: () => resolvePlanMarkdown,
|
|
7449
7822
|
resolvePrSelector: () => resolvePrSelector,
|
|
@@ -7465,9 +7838,11 @@ __export(index_exports, {
|
|
|
7465
7838
|
settingsSourceLabel: () => settingsSourceLabel,
|
|
7466
7839
|
shouldAttachPastedText: () => shouldAttachPastedText,
|
|
7467
7840
|
shouldCompactContext: () => shouldCompactContext,
|
|
7841
|
+
shouldInjectBrightsyMcp: () => shouldInjectBrightsyMcp,
|
|
7468
7842
|
shouldRefreshReviewRequestTemplate: () => shouldRefreshReviewRequestTemplate,
|
|
7469
7843
|
shouldRunWorktreeCleanup: () => shouldRunWorktreeCleanup,
|
|
7470
7844
|
sideboardHomeDir: () => sideboardHomeDir,
|
|
7845
|
+
sideboardMcpProfile: () => sideboardMcpProfile,
|
|
7471
7846
|
sideboardReposDir: () => sideboardReposDir,
|
|
7472
7847
|
sideboardWorkspacesDir: () => sideboardWorkspacesDir,
|
|
7473
7848
|
slugify: () => slugify,
|
|
@@ -7495,6 +7870,7 @@ __export(index_exports, {
|
|
|
7495
7870
|
threadDisplayLabel: () => threadDisplayLabel,
|
|
7496
7871
|
threadFilePath: () => threadFilePath,
|
|
7497
7872
|
threadLockPath: () => threadLockPath,
|
|
7873
|
+
threadRequestsBrightsyMcp: () => threadRequestsBrightsyMcp,
|
|
7498
7874
|
threadsDir: () => threadsDir,
|
|
7499
7875
|
threadsSharingWorktree: () => threadsSharingWorktree,
|
|
7500
7876
|
toolDescription: () => toolDescription,
|
|
@@ -7502,14 +7878,18 @@ __export(index_exports, {
|
|
|
7502
7878
|
toolFilePath: () => toolFilePath,
|
|
7503
7879
|
totalTokens: () => totalTokens,
|
|
7504
7880
|
updateAdvancedSettings: () => updateAdvancedSettings,
|
|
7881
|
+
updateAgentExecutable: () => updateAgentExecutable,
|
|
7505
7882
|
updateAppEnvironment: () => updateAppEnvironment,
|
|
7506
7883
|
updateBrightsySettings: () => updateBrightsySettings,
|
|
7507
7884
|
updateClaudeSettings: () => updateClaudeSettings,
|
|
7885
|
+
updateCodexSettings: () => updateCodexSettings,
|
|
7508
7886
|
updateDefaultsSettings: () => updateDefaultsSettings,
|
|
7509
7887
|
updateIntegrationsSettings: () => updateIntegrationsSettings,
|
|
7888
|
+
updateOpencodeSettings: () => updateOpencodeSettings,
|
|
7510
7889
|
updateThread: () => updateThread,
|
|
7511
7890
|
validateLinearApiKey: () => validateLinearApiKey,
|
|
7512
7891
|
withAgentInstructions: () => withAgentInstructions,
|
|
7892
|
+
withExportedPath: () => withExportedPath,
|
|
7513
7893
|
withThreadLock: () => withThreadLock,
|
|
7514
7894
|
workspaceSettingsSourceLabel: () => workspaceSettingsSourceLabel,
|
|
7515
7895
|
worktreeCleanupSettings: () => worktreeCleanupSettings,
|
|
@@ -8086,7 +8466,7 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
8086
8466
|
init_claude_mcp();
|
|
8087
8467
|
|
|
8088
8468
|
// src/agents/instructions.ts
|
|
8089
|
-
var
|
|
8469
|
+
var import_node_fs17 = require("fs");
|
|
8090
8470
|
var import_node_path14 = require("path");
|
|
8091
8471
|
init_worktree_labels();
|
|
8092
8472
|
function normPath2(p) {
|
|
@@ -8186,6 +8566,9 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
8186
8566
|
);
|
|
8187
8567
|
return lines.join("\n");
|
|
8188
8568
|
}
|
|
8569
|
+
function formatWorktreeReminder() {
|
|
8570
|
+
return "Sideboard worktree: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout.";
|
|
8571
|
+
}
|
|
8189
8572
|
function formatArtifactDirective() {
|
|
8190
8573
|
return [
|
|
8191
8574
|
"Sideboard side column (desktop UI):",
|
|
@@ -8227,10 +8610,10 @@ function loadAgentInstructions(worktreePath, agent) {
|
|
|
8227
8610
|
for (const rel of candidates) {
|
|
8228
8611
|
if (seen.has(rel)) continue;
|
|
8229
8612
|
const abs = (0, import_node_path14.join)(worktreePath, rel);
|
|
8230
|
-
if (!(0,
|
|
8613
|
+
if (!(0, import_node_fs17.existsSync)(abs)) continue;
|
|
8231
8614
|
try {
|
|
8232
|
-
if (!(0,
|
|
8233
|
-
let content = (0,
|
|
8615
|
+
if (!(0, import_node_fs17.statSync)(abs).isFile()) continue;
|
|
8616
|
+
let content = (0, import_node_fs17.readFileSync)(abs, "utf8");
|
|
8234
8617
|
if (!content.trim()) continue;
|
|
8235
8618
|
if (content.length > MAX_CHARS_PER_FILE) {
|
|
8236
8619
|
content = `${content.slice(0, MAX_CHARS_PER_FILE)}
|
|
@@ -8275,11 +8658,13 @@ init_turn_input();
|
|
|
8275
8658
|
init_agents();
|
|
8276
8659
|
async function detectAgents() {
|
|
8277
8660
|
ensureAgentPath();
|
|
8661
|
+
enrichPathWithNpmGlobalBin();
|
|
8278
8662
|
return Promise.all(allAdapters().map((a) => a.detect()));
|
|
8279
8663
|
}
|
|
8280
8664
|
var REQUIRE_AGENT_TIMEOUT_MS = 8e3;
|
|
8281
8665
|
async function requireAgent(agent, opts) {
|
|
8282
8666
|
ensureAgentPath();
|
|
8667
|
+
enrichPathWithNpmGlobalBin();
|
|
8283
8668
|
const status = await Promise.race([
|
|
8284
8669
|
getAdapter(agent).detect(),
|
|
8285
8670
|
new Promise((_, reject) => {
|
|
@@ -8307,7 +8692,7 @@ async function requireAgent(agent, opts) {
|
|
|
8307
8692
|
init_settings();
|
|
8308
8693
|
|
|
8309
8694
|
// src/hook/conductor.ts
|
|
8310
|
-
var
|
|
8695
|
+
var import_node_fs18 = require("fs");
|
|
8311
8696
|
var import_node_net = require("net");
|
|
8312
8697
|
var import_node_path15 = require("path");
|
|
8313
8698
|
var import_execa3 = require("execa");
|
|
@@ -8320,8 +8705,8 @@ function matchSimpleGlob(pattern, name) {
|
|
|
8320
8705
|
}
|
|
8321
8706
|
function readWorktreeInclude(repoPath) {
|
|
8322
8707
|
const path = (0, import_node_path15.join)(repoPath, ".worktreeinclude");
|
|
8323
|
-
if (!(0,
|
|
8324
|
-
return (0,
|
|
8708
|
+
if (!(0, import_node_fs18.existsSync)(path)) return [];
|
|
8709
|
+
return (0, import_node_fs18.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
8325
8710
|
}
|
|
8326
8711
|
function resolveFilesToCopy(repoPath) {
|
|
8327
8712
|
const fromInclude = readWorktreeInclude(repoPath);
|
|
@@ -8331,7 +8716,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
8331
8716
|
if (settings?.fileIncludeGlobs?.length) {
|
|
8332
8717
|
const matched = [];
|
|
8333
8718
|
try {
|
|
8334
|
-
for (const entry of (0,
|
|
8719
|
+
for (const entry of (0, import_node_fs18.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
8335
8720
|
if (!entry.isFile()) continue;
|
|
8336
8721
|
for (const glob of settings.fileIncludeGlobs) {
|
|
8337
8722
|
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path15.basename)(glob), entry.name)) {
|
|
@@ -8346,7 +8731,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
8346
8731
|
}
|
|
8347
8732
|
const defaults = [];
|
|
8348
8733
|
try {
|
|
8349
|
-
for (const entry of (0,
|
|
8734
|
+
for (const entry of (0, import_node_fs18.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
8350
8735
|
if (entry.isFile() && entry.name.startsWith(".env")) {
|
|
8351
8736
|
defaults.push(entry.name);
|
|
8352
8737
|
}
|
|
@@ -8361,10 +8746,10 @@ function copyConfiguredFiles(repoPath, worktreePath) {
|
|
|
8361
8746
|
const copied = [];
|
|
8362
8747
|
for (const rel of patterns) {
|
|
8363
8748
|
const src = (0, import_node_path15.join)(repoPath, rel);
|
|
8364
|
-
if (!(0,
|
|
8749
|
+
if (!(0, import_node_fs18.existsSync)(src)) continue;
|
|
8365
8750
|
const dest = (0, import_node_path15.join)(worktreePath, rel);
|
|
8366
|
-
(0,
|
|
8367
|
-
(0,
|
|
8751
|
+
(0, import_node_fs18.mkdirSync)((0, import_node_path15.dirname)(dest), { recursive: true });
|
|
8752
|
+
(0, import_node_fs18.copyFileSync)(src, dest);
|
|
8368
8753
|
copied.push(rel);
|
|
8369
8754
|
}
|
|
8370
8755
|
return copied;
|
|
@@ -8617,15 +9002,15 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
|
8617
9002
|
}
|
|
8618
9003
|
|
|
8619
9004
|
// src/hook/cursor-worktrees.ts
|
|
8620
|
-
var
|
|
9005
|
+
var import_node_fs19 = require("fs");
|
|
8621
9006
|
var import_node_path16 = require("path");
|
|
8622
9007
|
var import_execa4 = require("execa");
|
|
8623
9008
|
var import_node_readline3 = require("readline");
|
|
8624
9009
|
function loadCursorWorktreesJson(rootPath) {
|
|
8625
9010
|
const path = (0, import_node_path16.join)(rootPath, ".cursor", "worktrees.json");
|
|
8626
|
-
if (!(0,
|
|
9011
|
+
if (!(0, import_node_fs19.existsSync)(path)) return null;
|
|
8627
9012
|
try {
|
|
8628
|
-
return JSON.parse((0,
|
|
9013
|
+
return JSON.parse((0, import_node_fs19.readFileSync)(path, "utf8"));
|
|
8629
9014
|
} catch {
|
|
8630
9015
|
return null;
|
|
8631
9016
|
}
|
|
@@ -8690,12 +9075,12 @@ function hasCursorWorktreeSetup(worktreePath, repoPath) {
|
|
|
8690
9075
|
}
|
|
8691
9076
|
|
|
8692
9077
|
// src/diff/diff.ts
|
|
8693
|
-
var
|
|
9078
|
+
var import_node_fs20 = require("fs");
|
|
8694
9079
|
var import_node_path17 = require("path");
|
|
8695
9080
|
init_run();
|
|
8696
9081
|
init_worktree();
|
|
8697
9082
|
async function inspectGitWorktree(worktreePath) {
|
|
8698
|
-
if (!worktreePath || !(0,
|
|
9083
|
+
if (!worktreePath || !(0, import_node_fs20.existsSync)(worktreePath)) return "missing_worktree";
|
|
8699
9084
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
8700
9085
|
reject: false
|
|
8701
9086
|
});
|
|
@@ -8703,7 +9088,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
8703
9088
|
return "ok";
|
|
8704
9089
|
}
|
|
8705
9090
|
async function initializeGitRepository(worktreePath) {
|
|
8706
|
-
if (!worktreePath || !(0,
|
|
9091
|
+
if (!worktreePath || !(0, import_node_fs20.existsSync)(worktreePath)) {
|
|
8707
9092
|
throw new Error("Worktree not found");
|
|
8708
9093
|
}
|
|
8709
9094
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -9141,7 +9526,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
9141
9526
|
assertSafeRelativePath(relativePath);
|
|
9142
9527
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
9143
9528
|
const abs = (0, import_node_path17.join)(worktreePath, relativePath);
|
|
9144
|
-
const st = (0,
|
|
9529
|
+
const st = (0, import_node_fs20.statSync)(abs);
|
|
9145
9530
|
if (!st.isFile()) {
|
|
9146
9531
|
throw new Error(`Not a file: ${relativePath}`);
|
|
9147
9532
|
}
|
|
@@ -9150,7 +9535,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
9150
9535
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
9151
9536
|
);
|
|
9152
9537
|
}
|
|
9153
|
-
const buf = (0,
|
|
9538
|
+
const buf = (0, import_node_fs20.readFileSync)(abs);
|
|
9154
9539
|
return {
|
|
9155
9540
|
path: relativePath,
|
|
9156
9541
|
contentBase64: buf.toString("base64"),
|
|
@@ -9161,11 +9546,11 @@ function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
|
9161
9546
|
assertSafeRelativePath(relativePath);
|
|
9162
9547
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
9163
9548
|
const abs = (0, import_node_path17.join)(worktreePath, relativePath);
|
|
9164
|
-
const st = (0,
|
|
9549
|
+
const st = (0, import_node_fs20.statSync)(abs);
|
|
9165
9550
|
if (!st.isFile()) {
|
|
9166
9551
|
throw new Error(`Not a file: ${relativePath}`);
|
|
9167
9552
|
}
|
|
9168
|
-
const buf = (0,
|
|
9553
|
+
const buf = (0, import_node_fs20.readFileSync)(abs);
|
|
9169
9554
|
if (isImageRelativePath(relativePath)) {
|
|
9170
9555
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
9171
9556
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -9209,8 +9594,8 @@ function assertSafeRelativePath(relativePath) {
|
|
|
9209
9594
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
9210
9595
|
assertSafeRelativePath(relativePath);
|
|
9211
9596
|
const abs = (0, import_node_path17.join)(worktreePath, relativePath);
|
|
9212
|
-
(0,
|
|
9213
|
-
(0,
|
|
9597
|
+
(0, import_node_fs20.mkdirSync)((0, import_node_path17.dirname)(abs), { recursive: true });
|
|
9598
|
+
(0, import_node_fs20.writeFileSync)(abs, content, "utf8");
|
|
9214
9599
|
return { path: relativePath };
|
|
9215
9600
|
}
|
|
9216
9601
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
@@ -9229,7 +9614,7 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
|
9229
9614
|
}
|
|
9230
9615
|
|
|
9231
9616
|
// src/skills/discover.ts
|
|
9232
|
-
var
|
|
9617
|
+
var import_node_fs21 = require("fs");
|
|
9233
9618
|
var import_node_os8 = require("os");
|
|
9234
9619
|
var import_node_path18 = require("path");
|
|
9235
9620
|
function toCommand(name) {
|
|
@@ -9263,7 +9648,7 @@ function parseFrontmatter(content) {
|
|
|
9263
9648
|
}
|
|
9264
9649
|
function readSkill(skillMd, source) {
|
|
9265
9650
|
try {
|
|
9266
|
-
const content = (0,
|
|
9651
|
+
const content = (0, import_node_fs21.readFileSync)(skillMd, "utf8");
|
|
9267
9652
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
9268
9653
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
9269
9654
|
const name = fmName || dirName;
|
|
@@ -9282,19 +9667,19 @@ function readSkill(skillMd, source) {
|
|
|
9282
9667
|
}
|
|
9283
9668
|
}
|
|
9284
9669
|
function scanSkillsDir(dir, source, out) {
|
|
9285
|
-
if (!(0,
|
|
9670
|
+
if (!(0, import_node_fs21.existsSync)(dir)) return;
|
|
9286
9671
|
let entries;
|
|
9287
9672
|
try {
|
|
9288
|
-
entries = (0,
|
|
9673
|
+
entries = (0, import_node_fs21.readdirSync)(dir);
|
|
9289
9674
|
} catch {
|
|
9290
9675
|
return;
|
|
9291
9676
|
}
|
|
9292
9677
|
for (const entry of entries) {
|
|
9293
9678
|
if (entry.startsWith(".")) continue;
|
|
9294
9679
|
const skillMd = (0, import_node_path18.join)(dir, entry, "SKILL.md");
|
|
9295
|
-
if (!(0,
|
|
9680
|
+
if (!(0, import_node_fs21.existsSync)(skillMd)) continue;
|
|
9296
9681
|
try {
|
|
9297
|
-
if (!(0,
|
|
9682
|
+
if (!(0, import_node_fs21.statSync)(skillMd).isFile()) continue;
|
|
9298
9683
|
} catch {
|
|
9299
9684
|
continue;
|
|
9300
9685
|
}
|
|
@@ -9303,12 +9688,12 @@ function scanSkillsDir(dir, source, out) {
|
|
|
9303
9688
|
}
|
|
9304
9689
|
}
|
|
9305
9690
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
9306
|
-
if (!(0,
|
|
9691
|
+
if (!(0, import_node_fs21.existsSync)(pluginsRoot)) return;
|
|
9307
9692
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
9308
9693
|
if (depth > 7) return;
|
|
9309
9694
|
let entries;
|
|
9310
9695
|
try {
|
|
9311
|
-
entries = (0,
|
|
9696
|
+
entries = (0, import_node_fs21.readdirSync)(dir);
|
|
9312
9697
|
} catch {
|
|
9313
9698
|
return;
|
|
9314
9699
|
}
|
|
@@ -9320,7 +9705,7 @@ function scanClaudePluginSkills(pluginsRoot, out) {
|
|
|
9320
9705
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
9321
9706
|
const full = (0, import_node_path18.join)(dir, entry);
|
|
9322
9707
|
try {
|
|
9323
|
-
if (!(0,
|
|
9708
|
+
if (!(0, import_node_fs21.statSync)(full).isDirectory()) continue;
|
|
9324
9709
|
} catch {
|
|
9325
9710
|
continue;
|
|
9326
9711
|
}
|
|
@@ -9360,7 +9745,7 @@ function discoverSkills(worktreePath) {
|
|
|
9360
9745
|
return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
|
|
9361
9746
|
}
|
|
9362
9747
|
function readSkillBody(skillPath, maxChars = 12e3) {
|
|
9363
|
-
const raw = (0,
|
|
9748
|
+
const raw = (0, import_node_fs21.readFileSync)(skillPath, "utf8");
|
|
9364
9749
|
if (raw.startsWith("---")) {
|
|
9365
9750
|
const end = raw.indexOf("\n---", 3);
|
|
9366
9751
|
if (end >= 0) {
|
|
@@ -9501,7 +9886,7 @@ function buildDiffCommentAttachment(input) {
|
|
|
9501
9886
|
}
|
|
9502
9887
|
|
|
9503
9888
|
// src/composer/stage-files.ts
|
|
9504
|
-
var
|
|
9889
|
+
var import_node_fs22 = require("fs");
|
|
9505
9890
|
var import_node_path19 = require("path");
|
|
9506
9891
|
var import_node_crypto2 = require("crypto");
|
|
9507
9892
|
init_workspace_scratch();
|
|
@@ -9539,21 +9924,21 @@ function imageMimeType(filePath) {
|
|
|
9539
9924
|
}
|
|
9540
9925
|
function ensureAttachmentsDir(worktreePath) {
|
|
9541
9926
|
const dir = (0, import_node_path19.join)(worktreePath, ATTACHMENTS_DIR);
|
|
9542
|
-
(0,
|
|
9927
|
+
(0, import_node_fs22.mkdirSync)(dir, { recursive: true });
|
|
9543
9928
|
const gi = (0, import_node_path19.join)(dir, ".gitignore");
|
|
9544
|
-
if (!(0,
|
|
9545
|
-
(0,
|
|
9929
|
+
if (!(0, import_node_fs22.existsSync)(gi)) {
|
|
9930
|
+
(0, import_node_fs22.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
|
|
9546
9931
|
}
|
|
9547
9932
|
return dir;
|
|
9548
9933
|
}
|
|
9549
9934
|
function uniqueAttachmentName(dir, originalName) {
|
|
9550
9935
|
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
9551
|
-
if (!(0,
|
|
9936
|
+
if (!(0, import_node_fs22.existsSync)((0, import_node_path19.join)(dir, safe))) return safe;
|
|
9552
9937
|
const ext = (0, import_node_path19.extname)(safe);
|
|
9553
9938
|
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
9554
9939
|
for (let i = 1; i < 1e4; i++) {
|
|
9555
9940
|
const candidate = `${stem}-${i}${ext}`;
|
|
9556
|
-
if (!(0,
|
|
9941
|
+
if (!(0, import_node_fs22.existsSync)((0, import_node_path19.join)(dir, candidate))) return candidate;
|
|
9557
9942
|
}
|
|
9558
9943
|
return `${stem}-${(0, import_node_crypto2.randomUUID)()}${ext}`;
|
|
9559
9944
|
}
|
|
@@ -9607,7 +9992,7 @@ function attachmentFromBuffer(name, buf, opts) {
|
|
|
9607
9992
|
function attachmentFromAbsolutePath(absolutePath) {
|
|
9608
9993
|
const name = (0, import_node_path19.basename)(absolutePath);
|
|
9609
9994
|
try {
|
|
9610
|
-
const st = (0,
|
|
9995
|
+
const st = (0, import_node_fs22.statSync)(absolutePath);
|
|
9611
9996
|
if (!st.isFile()) {
|
|
9612
9997
|
return {
|
|
9613
9998
|
id: (0, import_node_crypto2.randomUUID)(),
|
|
@@ -9616,7 +10001,7 @@ function attachmentFromAbsolutePath(absolutePath) {
|
|
|
9616
10001
|
content: `(not a file: ${absolutePath})`
|
|
9617
10002
|
};
|
|
9618
10003
|
}
|
|
9619
|
-
const buf = (0,
|
|
10004
|
+
const buf = (0, import_node_fs22.readFileSync)(absolutePath);
|
|
9620
10005
|
return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
|
|
9621
10006
|
} catch (err) {
|
|
9622
10007
|
return {
|
|
@@ -9634,13 +10019,13 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
|
9634
10019
|
for (const abs of absolutePaths) {
|
|
9635
10020
|
const originalName = (0, import_node_path19.basename)(abs);
|
|
9636
10021
|
try {
|
|
9637
|
-
const st = (0,
|
|
10022
|
+
const st = (0, import_node_fs22.statSync)(abs);
|
|
9638
10023
|
if (!st.isFile()) continue;
|
|
9639
10024
|
const name = uniqueAttachmentName(dir, originalName);
|
|
9640
10025
|
const destAbs = (0, import_node_path19.join)(dir, name);
|
|
9641
|
-
(0,
|
|
10026
|
+
(0, import_node_fs22.copyFileSync)(abs, destAbs);
|
|
9642
10027
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
9643
|
-
const buf = (0,
|
|
10028
|
+
const buf = (0, import_node_fs22.readFileSync)(destAbs);
|
|
9644
10029
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
9645
10030
|
} catch (err) {
|
|
9646
10031
|
out.push({
|
|
@@ -9663,7 +10048,7 @@ function stageBuffersAsAttachments(worktreePath, buffers) {
|
|
|
9663
10048
|
const buf = Buffer.from(item.dataBase64, "base64");
|
|
9664
10049
|
const name = uniqueAttachmentName(dir, originalName);
|
|
9665
10050
|
const destAbs = (0, import_node_path19.join)(dir, name);
|
|
9666
|
-
(0,
|
|
10051
|
+
(0, import_node_fs22.writeFileSync)(destAbs, buf);
|
|
9667
10052
|
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
9668
10053
|
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
9669
10054
|
} catch (err) {
|
|
@@ -9708,9 +10093,9 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
|
9708
10093
|
const name = (0, import_node_path19.basename)(rel);
|
|
9709
10094
|
try {
|
|
9710
10095
|
const abs = (0, import_node_path19.join)(worktreePath, rel);
|
|
9711
|
-
const st = (0,
|
|
10096
|
+
const st = (0, import_node_fs22.statSync)(abs);
|
|
9712
10097
|
if (!st.isFile()) continue;
|
|
9713
|
-
const buf = (0,
|
|
10098
|
+
const buf = (0, import_node_fs22.readFileSync)(abs);
|
|
9714
10099
|
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
9715
10100
|
} catch (err) {
|
|
9716
10101
|
out.push({
|
|
@@ -10198,7 +10583,7 @@ async function confirmLand(thread, opts) {
|
|
|
10198
10583
|
}
|
|
10199
10584
|
|
|
10200
10585
|
// src/threads/create.ts
|
|
10201
|
-
var
|
|
10586
|
+
var import_node_fs23 = require("fs");
|
|
10202
10587
|
init_worktree();
|
|
10203
10588
|
init_app_settings();
|
|
10204
10589
|
init_thread_store();
|
|
@@ -10212,7 +10597,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
10212
10597
|
});
|
|
10213
10598
|
await requireAgent(resolved.agent);
|
|
10214
10599
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
10215
|
-
if (!(0,
|
|
10600
|
+
if (!(0, import_node_fs23.existsSync)(repoPath)) {
|
|
10216
10601
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
10217
10602
|
}
|
|
10218
10603
|
let sourceRef = input.sourceRef;
|
|
@@ -10320,6 +10705,8 @@ function worktreeBindingFrom(from) {
|
|
|
10320
10705
|
parentThreadId: from.parentThreadId,
|
|
10321
10706
|
prUrl: from.prUrl,
|
|
10322
10707
|
prTitle: from.prTitle,
|
|
10708
|
+
prState: from.prState,
|
|
10709
|
+
skipAutoArchiveOnMerge: from.skipAutoArchiveOnMerge,
|
|
10323
10710
|
stackId: from.stackId,
|
|
10324
10711
|
stackLayer: from.stackLayer
|
|
10325
10712
|
};
|
|
@@ -10437,7 +10824,7 @@ async function forkThreadWorktree(input, onSetupLine) {
|
|
|
10437
10824
|
}
|
|
10438
10825
|
|
|
10439
10826
|
// src/threads/stack-layers.ts
|
|
10440
|
-
var
|
|
10827
|
+
var import_node_fs24 = require("fs");
|
|
10441
10828
|
init_run();
|
|
10442
10829
|
init_stack();
|
|
10443
10830
|
init_worktree();
|
|
@@ -10505,7 +10892,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
10505
10892
|
let createdWorktree = false;
|
|
10506
10893
|
const trees = await listWorktrees(repoPath);
|
|
10507
10894
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
10508
|
-
if (checkedOut?.path && (0,
|
|
10895
|
+
if (checkedOut?.path && (0, import_node_fs24.existsSync)(checkedOut.path)) {
|
|
10509
10896
|
if (input.reuseExistingWorktree !== false) {
|
|
10510
10897
|
worktreePath = checkedOut.path;
|
|
10511
10898
|
} else {
|
|
@@ -10647,7 +11034,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
10647
11034
|
async function createPrStack(input, onSetupLine) {
|
|
10648
11035
|
await requireAgent(input.agent);
|
|
10649
11036
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
10650
|
-
if (!(0,
|
|
11037
|
+
if (!(0, import_node_fs24.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
10651
11038
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
10652
11039
|
const status = await detectGhStack(repoPath);
|
|
10653
11040
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -10714,7 +11101,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
10714
11101
|
}
|
|
10715
11102
|
}
|
|
10716
11103
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
10717
|
-
if (!claimed.has(bootstrap.worktreePath) && (0,
|
|
11104
|
+
if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs24.existsSync)(bootstrap.worktreePath)) {
|
|
10718
11105
|
try {
|
|
10719
11106
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
10720
11107
|
deleteBranch: bootstrap.branchName
|
|
@@ -10736,8 +11123,8 @@ function stackAgentDefaultsFrom(input) {
|
|
|
10736
11123
|
}
|
|
10737
11124
|
|
|
10738
11125
|
// src/threads/adopt.ts
|
|
10739
|
-
var
|
|
10740
|
-
var
|
|
11126
|
+
var import_node_child_process2 = require("child_process");
|
|
11127
|
+
var import_node_fs25 = require("fs");
|
|
10741
11128
|
var import_node_os9 = require("os");
|
|
10742
11129
|
var import_node_path20 = require("path");
|
|
10743
11130
|
var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
@@ -10762,21 +11149,21 @@ function mapAgentType(raw) {
|
|
|
10762
11149
|
return null;
|
|
10763
11150
|
}
|
|
10764
11151
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
10765
|
-
if (!workspacePath || !(0,
|
|
11152
|
+
if (!workspacePath || !(0, import_node_fs25.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
10766
11153
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
10767
11154
|
let best = null;
|
|
10768
11155
|
let hashes;
|
|
10769
11156
|
try {
|
|
10770
|
-
hashes = (0,
|
|
11157
|
+
hashes = (0, import_node_fs25.readdirSync)(CURSOR_SDK_STORE);
|
|
10771
11158
|
} catch {
|
|
10772
11159
|
return null;
|
|
10773
11160
|
}
|
|
10774
11161
|
for (const hash of hashes) {
|
|
10775
11162
|
const agentsFile = (0, import_node_path20.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
10776
|
-
if (!(0,
|
|
11163
|
+
if (!(0, import_node_fs25.existsSync)(agentsFile)) continue;
|
|
10777
11164
|
let text;
|
|
10778
11165
|
try {
|
|
10779
|
-
text = (0,
|
|
11166
|
+
text = (0, import_node_fs25.readFileSync)(agentsFile, "utf8");
|
|
10780
11167
|
} catch {
|
|
10781
11168
|
continue;
|
|
10782
11169
|
}
|
|
@@ -10800,7 +11187,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
10800
11187
|
return best?.agentId ?? null;
|
|
10801
11188
|
}
|
|
10802
11189
|
async function adoptThread(input) {
|
|
10803
|
-
if (!(0,
|
|
11190
|
+
if (!(0, import_node_fs25.existsSync)(input.worktreePath)) {
|
|
10804
11191
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
10805
11192
|
}
|
|
10806
11193
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -10827,18 +11214,18 @@ function conductorDbPath() {
|
|
|
10827
11214
|
return CONDUCTOR_DB;
|
|
10828
11215
|
}
|
|
10829
11216
|
function listConductorWorkspaces() {
|
|
10830
|
-
if (!(0,
|
|
11217
|
+
if (!(0, import_node_fs25.existsSync)(CONDUCTOR_DB)) {
|
|
10831
11218
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
10832
11219
|
}
|
|
10833
|
-
const tmp = (0,
|
|
11220
|
+
const tmp = (0, import_node_fs25.mkdtempSync)((0, import_node_path20.join)((0, import_node_os9.tmpdir)(), "sideboard-conductor-"));
|
|
10834
11221
|
const snapshot = (0, import_node_path20.join)(tmp, "conductor.db");
|
|
10835
11222
|
try {
|
|
10836
|
-
(0,
|
|
11223
|
+
(0, import_node_fs25.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
10837
11224
|
for (const suffix of ["-wal", "-shm"]) {
|
|
10838
11225
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
10839
|
-
if ((0,
|
|
11226
|
+
if ((0, import_node_fs25.existsSync)(src)) {
|
|
10840
11227
|
try {
|
|
10841
|
-
(0,
|
|
11228
|
+
(0, import_node_fs25.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
10842
11229
|
} catch {
|
|
10843
11230
|
}
|
|
10844
11231
|
}
|
|
@@ -10914,22 +11301,22 @@ function listConductorWorkspaces() {
|
|
|
10914
11301
|
db.close();
|
|
10915
11302
|
}
|
|
10916
11303
|
} finally {
|
|
10917
|
-
(0,
|
|
11304
|
+
(0, import_node_fs25.rmSync)(tmp, { recursive: true, force: true });
|
|
10918
11305
|
}
|
|
10919
11306
|
}
|
|
10920
11307
|
function importConductorWorkspace(workspaceId) {
|
|
10921
|
-
if (!(0,
|
|
11308
|
+
if (!(0, import_node_fs25.existsSync)(CONDUCTOR_DB)) {
|
|
10922
11309
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
10923
11310
|
}
|
|
10924
|
-
const tmp = (0,
|
|
11311
|
+
const tmp = (0, import_node_fs25.mkdtempSync)((0, import_node_path20.join)((0, import_node_os9.tmpdir)(), "sideboard-conductor-"));
|
|
10925
11312
|
const snapshot = (0, import_node_path20.join)(tmp, "conductor.db");
|
|
10926
11313
|
try {
|
|
10927
|
-
(0,
|
|
11314
|
+
(0, import_node_fs25.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
10928
11315
|
for (const suffix of ["-wal", "-shm"]) {
|
|
10929
11316
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
10930
|
-
if ((0,
|
|
11317
|
+
if ((0, import_node_fs25.existsSync)(src)) {
|
|
10931
11318
|
try {
|
|
10932
|
-
(0,
|
|
11319
|
+
(0, import_node_fs25.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
10933
11320
|
} catch {
|
|
10934
11321
|
}
|
|
10935
11322
|
}
|
|
@@ -10947,7 +11334,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
10947
11334
|
).get(workspaceId);
|
|
10948
11335
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
10949
11336
|
const worktreePath = String(row.workspacePath);
|
|
10950
|
-
if (!(0,
|
|
11337
|
+
if (!(0, import_node_fs25.existsSync)(worktreePath)) {
|
|
10951
11338
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
10952
11339
|
}
|
|
10953
11340
|
let sessionId = null;
|
|
@@ -10987,7 +11374,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
10987
11374
|
}
|
|
10988
11375
|
let repoPath = worktreePath;
|
|
10989
11376
|
try {
|
|
10990
|
-
repoPath = (0,
|
|
11377
|
+
repoPath = (0, import_node_child_process2.execFileSync)("git", ["rev-parse", "--show-toplevel"], {
|
|
10991
11378
|
cwd: worktreePath,
|
|
10992
11379
|
encoding: "utf8"
|
|
10993
11380
|
}).trim();
|
|
@@ -11010,7 +11397,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
11010
11397
|
db.close();
|
|
11011
11398
|
}
|
|
11012
11399
|
} finally {
|
|
11013
|
-
(0,
|
|
11400
|
+
(0, import_node_fs25.rmSync)(tmp, { recursive: true, force: true });
|
|
11014
11401
|
}
|
|
11015
11402
|
}
|
|
11016
11403
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
@@ -11019,14 +11406,28 @@ async function importConductorWorkspaceAsync(workspaceId) {
|
|
|
11019
11406
|
|
|
11020
11407
|
// src/orchestrator/orchestrator.ts
|
|
11021
11408
|
var import_node_events = require("events");
|
|
11022
|
-
var
|
|
11409
|
+
var import_node_fs31 = require("fs");
|
|
11023
11410
|
init_error_detail();
|
|
11024
11411
|
init_agents();
|
|
11025
11412
|
init_worktree();
|
|
11026
11413
|
init_stack();
|
|
11027
11414
|
|
|
11415
|
+
// src/git/pr-merge-archive.ts
|
|
11416
|
+
function normalizePrState(state) {
|
|
11417
|
+
return (state ?? "").trim().toUpperCase();
|
|
11418
|
+
}
|
|
11419
|
+
function shouldAutoArchiveOnPrMerge(opts) {
|
|
11420
|
+
if (!opts.autoArchiveEnabled) return false;
|
|
11421
|
+
if (opts.isGlobal) return false;
|
|
11422
|
+
if (opts.skipAutoArchiveOnMerge) return false;
|
|
11423
|
+
if (opts.threadStatus === "archived") return false;
|
|
11424
|
+
const next = normalizePrState(opts.nextPrState);
|
|
11425
|
+
if (next !== "MERGED") return false;
|
|
11426
|
+
return normalizePrState(opts.previousPrState) !== "MERGED";
|
|
11427
|
+
}
|
|
11428
|
+
|
|
11028
11429
|
// src/git/orphan-cleanup.ts
|
|
11029
|
-
var
|
|
11430
|
+
var import_node_fs26 = require("fs");
|
|
11030
11431
|
var import_node_path21 = require("path");
|
|
11031
11432
|
init_worktree();
|
|
11032
11433
|
init_thread_store();
|
|
@@ -11042,9 +11443,9 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11042
11443
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
11043
11444
|
);
|
|
11044
11445
|
const homeRoot = sideboardWorkspacesDir();
|
|
11045
|
-
if ((0,
|
|
11446
|
+
if ((0, import_node_fs26.existsSync)(homeRoot)) {
|
|
11046
11447
|
try {
|
|
11047
|
-
for (const entry of (0,
|
|
11448
|
+
for (const entry of (0, import_node_fs26.readdirSync)(homeRoot, { withFileTypes: true })) {
|
|
11048
11449
|
if (!entry.isDirectory()) continue;
|
|
11049
11450
|
void entry;
|
|
11050
11451
|
}
|
|
@@ -11054,7 +11455,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11054
11455
|
const orphans = [];
|
|
11055
11456
|
const seen = /* @__PURE__ */ new Set();
|
|
11056
11457
|
for (const repoPath of repos) {
|
|
11057
|
-
if (!repoPath || !(0,
|
|
11458
|
+
if (!repoPath || !(0, import_node_fs26.existsSync)(repoPath)) continue;
|
|
11058
11459
|
try {
|
|
11059
11460
|
const wts = await listWorktrees(repoPath);
|
|
11060
11461
|
for (const wt of wts) {
|
|
@@ -11065,7 +11466,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11065
11466
|
seen.add(path);
|
|
11066
11467
|
let mtimeMs = 0;
|
|
11067
11468
|
try {
|
|
11068
|
-
mtimeMs = (0,
|
|
11469
|
+
mtimeMs = (0, import_node_fs26.statSync)(path).mtimeMs;
|
|
11069
11470
|
} catch {
|
|
11070
11471
|
mtimeMs = 0;
|
|
11071
11472
|
}
|
|
@@ -11075,16 +11476,16 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
11075
11476
|
}
|
|
11076
11477
|
try {
|
|
11077
11478
|
const root = worktreesRoot(repoPath);
|
|
11078
|
-
if ((0,
|
|
11079
|
-
for (const entry of (0,
|
|
11479
|
+
if ((0, import_node_fs26.existsSync)(root)) {
|
|
11480
|
+
for (const entry of (0, import_node_fs26.readdirSync)(root, { withFileTypes: true })) {
|
|
11080
11481
|
if (!entry.isDirectory()) continue;
|
|
11081
11482
|
const path = (0, import_node_path21.join)(root, entry.name).replace(/\/$/, "");
|
|
11082
11483
|
if (known.has(path) || seen.has(path)) continue;
|
|
11083
|
-
if (!(0,
|
|
11484
|
+
if (!(0, import_node_fs26.existsSync)((0, import_node_path21.join)(path, ".git"))) continue;
|
|
11084
11485
|
seen.add(path);
|
|
11085
11486
|
let mtimeMs = 0;
|
|
11086
11487
|
try {
|
|
11087
|
-
mtimeMs = (0,
|
|
11488
|
+
mtimeMs = (0, import_node_fs26.statSync)(path).mtimeMs;
|
|
11088
11489
|
} catch {
|
|
11089
11490
|
mtimeMs = Date.now();
|
|
11090
11491
|
}
|
|
@@ -11230,7 +11631,7 @@ async function applyThreadIntoMain(thread, opts) {
|
|
|
11230
11631
|
}
|
|
11231
11632
|
|
|
11232
11633
|
// src/git/clone-repo.ts
|
|
11233
|
-
var
|
|
11634
|
+
var import_node_fs27 = require("fs");
|
|
11234
11635
|
var import_node_path22 = require("path");
|
|
11235
11636
|
var import_execa6 = require("execa");
|
|
11236
11637
|
init_paths();
|
|
@@ -11246,7 +11647,7 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
11246
11647
|
}
|
|
11247
11648
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
11248
11649
|
const dest = (0, import_node_path22.join)(sideboardReposDir(), name);
|
|
11249
|
-
if ((0,
|
|
11650
|
+
if ((0, import_node_fs27.existsSync)(dest)) {
|
|
11250
11651
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
11251
11652
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
11252
11653
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -11268,7 +11669,7 @@ init_orchestrator_capable();
|
|
|
11268
11669
|
|
|
11269
11670
|
// src/review/request-review.ts
|
|
11270
11671
|
var import_node_crypto5 = require("crypto");
|
|
11271
|
-
var
|
|
11672
|
+
var import_node_fs28 = require("fs");
|
|
11272
11673
|
var import_node_path23 = require("path");
|
|
11273
11674
|
init_global_workspace();
|
|
11274
11675
|
init_thread_store();
|
|
@@ -11413,9 +11814,9 @@ function shouldRefreshReviewRequestTemplate(content) {
|
|
|
11413
11814
|
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
11414
11815
|
}
|
|
11415
11816
|
function readTextIfPresent(abs) {
|
|
11416
|
-
if (!(0,
|
|
11817
|
+
if (!(0, import_node_fs28.existsSync)(abs)) return null;
|
|
11417
11818
|
try {
|
|
11418
|
-
const content = (0,
|
|
11819
|
+
const content = (0, import_node_fs28.readFileSync)(abs, "utf8");
|
|
11419
11820
|
return content.trim() ? content : null;
|
|
11420
11821
|
} catch {
|
|
11421
11822
|
return null;
|
|
@@ -11423,9 +11824,9 @@ function readTextIfPresent(abs) {
|
|
|
11423
11824
|
}
|
|
11424
11825
|
function ensureAttachmentsGitignore(worktreePath) {
|
|
11425
11826
|
const gitignoreAbs = (0, import_node_path23.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
11426
|
-
if ((0,
|
|
11427
|
-
(0,
|
|
11428
|
-
(0,
|
|
11827
|
+
if ((0, import_node_fs28.existsSync)(gitignoreAbs)) return;
|
|
11828
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path23.dirname)(gitignoreAbs), { recursive: true });
|
|
11829
|
+
(0, import_node_fs28.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
11429
11830
|
}
|
|
11430
11831
|
function resolveReviewGuidelines(worktreePath) {
|
|
11431
11832
|
const repoAbs = (0, import_node_path23.join)(worktreePath, REPO_REVIEW_PATH);
|
|
@@ -11459,8 +11860,8 @@ function resolveReviewGuidelines(worktreePath) {
|
|
|
11459
11860
|
};
|
|
11460
11861
|
}
|
|
11461
11862
|
ensureAttachmentsGitignore(worktreePath);
|
|
11462
|
-
(0,
|
|
11463
|
-
(0,
|
|
11863
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path23.dirname)(localAbs), { recursive: true });
|
|
11864
|
+
(0, import_node_fs28.writeFileSync)(localAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
|
|
11464
11865
|
return {
|
|
11465
11866
|
path: REVIEW_REQUEST_PATH,
|
|
11466
11867
|
name: REVIEW_REQUEST_NAME,
|
|
@@ -11482,7 +11883,7 @@ function ensureReviewRequestFile(worktreePath) {
|
|
|
11482
11883
|
const localAbs = (0, import_node_path23.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
11483
11884
|
const localContent = readTextIfPresent(localAbs) ?? readTextIfPresent((0, import_node_path23.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
|
|
11484
11885
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
11485
|
-
const path = (0,
|
|
11886
|
+
const path = (0, import_node_fs28.existsSync)(localAbs) ? REVIEW_REQUEST_PATH : LEGACY_REVIEW_REQUEST_PATH;
|
|
11486
11887
|
return {
|
|
11487
11888
|
path,
|
|
11488
11889
|
name: REVIEW_REQUEST_NAME,
|
|
@@ -11490,8 +11891,8 @@ function ensureReviewRequestFile(worktreePath) {
|
|
|
11490
11891
|
source: "local"
|
|
11491
11892
|
};
|
|
11492
11893
|
}
|
|
11493
|
-
(0,
|
|
11494
|
-
(0,
|
|
11894
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path23.dirname)(repoAbs), { recursive: true });
|
|
11895
|
+
(0, import_node_fs28.writeFileSync)(repoAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
|
|
11495
11896
|
return {
|
|
11496
11897
|
path: REPO_REVIEW_PATH,
|
|
11497
11898
|
name: REPO_REVIEW_NAME,
|
|
@@ -11771,7 +12172,7 @@ var Orchestrator = class {
|
|
|
11771
12172
|
}
|
|
11772
12173
|
continue;
|
|
11773
12174
|
}
|
|
11774
|
-
if (!(0,
|
|
12175
|
+
if (!(0, import_node_fs31.existsSync)(thread.worktreePath)) {
|
|
11775
12176
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
11776
12177
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
11777
12178
|
continue;
|
|
@@ -12188,13 +12589,14 @@ var Orchestrator = class {
|
|
|
12188
12589
|
"Files column: MCP present_files (brightsy account storage or memory).",
|
|
12189
12590
|
"Do not say artifacts/CMS UI are unavailable."
|
|
12190
12591
|
].join(" ") : null;
|
|
12592
|
+
const worktreeReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatWorktreeReminder() : null;
|
|
12191
12593
|
const agentPrompt = [
|
|
12192
12594
|
thread.planMode ? PLAN_MODE_INSTRUCTION : null,
|
|
12193
12595
|
orchestrationReminder,
|
|
12596
|
+
worktreeReminder,
|
|
12194
12597
|
artifactReminder,
|
|
12195
12598
|
expandedPrompt
|
|
12196
12599
|
].filter(Boolean).join("\n\n");
|
|
12197
|
-
const instructionFiles = loadAgentInstructions(thread.worktreePath, thread.agent);
|
|
12198
12600
|
if (thread.attachments.length > 0) {
|
|
12199
12601
|
updateThread(threadId, { attachments: [] });
|
|
12200
12602
|
}
|
|
@@ -12222,7 +12624,6 @@ var Orchestrator = class {
|
|
|
12222
12624
|
const renameBranchDirective = !isBrightsy && !isOrchestration && autoRenameBranchEnabled2() ? formatRenameBranchDirective(fresh, {
|
|
12223
12625
|
customPrompt: settings?.prompts?.renameBranch
|
|
12224
12626
|
}) : null;
|
|
12225
|
-
const instructions = fresh.agent === "claude" || isBrightsy ? null : formatAgentInstructions(instructionFiles);
|
|
12226
12627
|
let seed = null;
|
|
12227
12628
|
if (!fresh.sessionId) {
|
|
12228
12629
|
const prior = fresh.messages.slice(0, -1);
|
|
@@ -12243,12 +12644,12 @@ var Orchestrator = class {
|
|
|
12243
12644
|
});
|
|
12244
12645
|
}
|
|
12245
12646
|
}
|
|
12246
|
-
const cachedPrefix = [
|
|
12647
|
+
const cachedPrefix = fresh.sessionId ? "" : [
|
|
12247
12648
|
coordinatorDirective,
|
|
12248
12649
|
worktreeDirective,
|
|
12249
12650
|
artifactDirective,
|
|
12250
12651
|
renameBranchDirective,
|
|
12251
|
-
|
|
12652
|
+
seed
|
|
12252
12653
|
].filter(Boolean).join("\n\n---\n\n");
|
|
12253
12654
|
try {
|
|
12254
12655
|
const stderrTail = [];
|
|
@@ -12335,15 +12736,11 @@ var Orchestrator = class {
|
|
|
12335
12736
|
const retryThread = this.requireThread(threadId);
|
|
12336
12737
|
const prior = retryThread.messages.slice(0, -1);
|
|
12337
12738
|
const retrySeed = buildSessionSeed(prior);
|
|
12338
|
-
const retryInstructions = retryThread.agent === "claude" ? null : formatAgentInstructions(
|
|
12339
|
-
loadAgentInstructions(retryThread.worktreePath, retryThread.agent)
|
|
12340
|
-
);
|
|
12341
12739
|
const retryPrefix = [
|
|
12342
12740
|
coordinatorDirective,
|
|
12343
12741
|
worktreeDirective,
|
|
12344
12742
|
artifactDirective,
|
|
12345
12743
|
renameBranchDirective,
|
|
12346
|
-
retryInstructions,
|
|
12347
12744
|
retrySeed
|
|
12348
12745
|
].filter(Boolean).join("\n\n---\n\n");
|
|
12349
12746
|
const retryHandle = await spawnAgentTurn(
|
|
@@ -12854,10 +13251,19 @@ var Orchestrator = class {
|
|
|
12854
13251
|
this.assertNotGlobal(thread, "Merge PR");
|
|
12855
13252
|
if (!selector) throw new Error("No pull request linked to this thread");
|
|
12856
13253
|
const result = await mergePr(cwd, selector);
|
|
12857
|
-
|
|
12858
|
-
|
|
12859
|
-
|
|
12860
|
-
|
|
13254
|
+
const state = normalizePrState(result.state) || "MERGED";
|
|
13255
|
+
const metaLike = {
|
|
13256
|
+
number: 0,
|
|
13257
|
+
title: thread.prTitle ?? thread.title,
|
|
13258
|
+
url: result.url || thread.prUrl || "",
|
|
13259
|
+
state,
|
|
13260
|
+
isDraft: false,
|
|
13261
|
+
reviewDecision: null,
|
|
13262
|
+
baseRefName: "",
|
|
13263
|
+
headRefName: ""
|
|
13264
|
+
};
|
|
13265
|
+
await this.persistPrMetaAndMaybeArchive(thread, metaLike);
|
|
13266
|
+
return { url: metaLike.url, state };
|
|
12861
13267
|
}
|
|
12862
13268
|
/** Resolve PR selector and optionally persist `prUrl` when found. */
|
|
12863
13269
|
async withPrSelector(threadRef) {
|
|
@@ -12879,19 +13285,55 @@ var Orchestrator = class {
|
|
|
12879
13285
|
if (!selector) return null;
|
|
12880
13286
|
const meta = await getPrMeta(cwd, selector);
|
|
12881
13287
|
if (meta) {
|
|
12882
|
-
|
|
12883
|
-
if (meta.url && meta.url !== thread.prUrl) patch.prUrl = meta.url;
|
|
12884
|
-
if (meta.title && meta.title !== thread.prTitle) patch.prTitle = meta.title;
|
|
12885
|
-
if (Object.keys(patch).length > 0) {
|
|
12886
|
-
updateThread(thread.id, patch);
|
|
12887
|
-
const latest = this.requireThread(thread.id);
|
|
12888
|
-
if (!latest.userSetTitle && meta.title && latest.title !== meta.title) {
|
|
12889
|
-
updateThread(thread.id, { title: meta.title });
|
|
12890
|
-
}
|
|
12891
|
-
}
|
|
13288
|
+
await this.persistPrMetaAndMaybeArchive(thread, meta);
|
|
12892
13289
|
}
|
|
12893
13290
|
return meta;
|
|
12894
13291
|
}
|
|
13292
|
+
/**
|
|
13293
|
+
* Persist PR URL/title/state and Conductor-style auto-archive when the PR
|
|
13294
|
+
* first becomes MERGED.
|
|
13295
|
+
*/
|
|
13296
|
+
async persistPrMetaAndMaybeArchive(thread, meta) {
|
|
13297
|
+
const prevState = normalizePrState(thread.prState);
|
|
13298
|
+
const nextState = normalizePrState(meta.state);
|
|
13299
|
+
const patch = {};
|
|
13300
|
+
if (meta.url && meta.url !== thread.prUrl) patch.prUrl = meta.url;
|
|
13301
|
+
if (meta.title && meta.title !== thread.prTitle) patch.prTitle = meta.title;
|
|
13302
|
+
if (nextState && nextState !== prevState) patch.prState = nextState;
|
|
13303
|
+
if (thread.skipAutoArchiveOnMerge && nextState && nextState !== "MERGED" && nextState !== "CLOSED") {
|
|
13304
|
+
patch.skipAutoArchiveOnMerge = false;
|
|
13305
|
+
}
|
|
13306
|
+
if (Object.keys(patch).length > 0) {
|
|
13307
|
+
updateThread(thread.id, patch);
|
|
13308
|
+
const latest2 = this.requireThread(thread.id);
|
|
13309
|
+
if (!latest2.userSetTitle && meta.title && latest2.title !== meta.title) {
|
|
13310
|
+
updateThread(thread.id, { title: meta.title });
|
|
13311
|
+
}
|
|
13312
|
+
}
|
|
13313
|
+
const { autoArchiveOnMergeEnabled: autoArchiveOnMergeEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
13314
|
+
const latest = this.requireThread(thread.id);
|
|
13315
|
+
if (!shouldAutoArchiveOnPrMerge({
|
|
13316
|
+
previousPrState: prevState || null,
|
|
13317
|
+
nextPrState: nextState,
|
|
13318
|
+
threadStatus: latest.status,
|
|
13319
|
+
skipAutoArchiveOnMerge: latest.skipAutoArchiveOnMerge,
|
|
13320
|
+
autoArchiveEnabled: autoArchiveOnMergeEnabled2(),
|
|
13321
|
+
isGlobal: isGlobalThread(latest)
|
|
13322
|
+
})) {
|
|
13323
|
+
return;
|
|
13324
|
+
}
|
|
13325
|
+
const siblings = threadsSharingWorktree(latest.worktreePath);
|
|
13326
|
+
for (const t of siblings) {
|
|
13327
|
+
const sibPatch = { prState: "MERGED" };
|
|
13328
|
+
if (meta.url && meta.url !== t.prUrl) sibPatch.prUrl = meta.url;
|
|
13329
|
+
if (meta.title && meta.title !== t.prTitle) sibPatch.prTitle = meta.title;
|
|
13330
|
+
if (Object.keys(sibPatch).length > 0) updateThread(t.id, sibPatch);
|
|
13331
|
+
}
|
|
13332
|
+
for (const t of siblings) {
|
|
13333
|
+
if (this.requireThread(t.id).status === "archived") continue;
|
|
13334
|
+
await this.archive(t.id);
|
|
13335
|
+
}
|
|
13336
|
+
}
|
|
12895
13337
|
async getPrStack(threadRef) {
|
|
12896
13338
|
const thread = this.requireThread(threadRef);
|
|
12897
13339
|
if (!thread.worktreePath?.trim()) return null;
|
|
@@ -13069,7 +13511,9 @@ var Orchestrator = class {
|
|
|
13069
13511
|
const thread = this.requireThread(threadRef);
|
|
13070
13512
|
this.stop(thread.id);
|
|
13071
13513
|
if (isGlobalThread(thread)) {
|
|
13072
|
-
|
|
13514
|
+
const archived2 = setStatus(thread.id, "archived");
|
|
13515
|
+
this.emit({ type: "status_changed", threadId: archived2.id, status: "archived" });
|
|
13516
|
+
return archived2;
|
|
13073
13517
|
}
|
|
13074
13518
|
const siblings = threadsSharingWorktree(thread.worktreePath).filter((t) => t.id !== thread.id);
|
|
13075
13519
|
if (siblings.length === 0) {
|
|
@@ -13087,6 +13531,7 @@ var Orchestrator = class {
|
|
|
13087
13531
|
await removeWorktree(thread.repoPath, thread.worktreePath);
|
|
13088
13532
|
}
|
|
13089
13533
|
const archived = setStatus(thread.id, "archived");
|
|
13534
|
+
this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
|
|
13090
13535
|
if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
|
|
13091
13536
|
try {
|
|
13092
13537
|
const { ensureWorkspace: ensureWorkspace2 } = await Promise.resolve().then(() => (init_workspaces(), workspaces_exports));
|
|
@@ -13126,9 +13571,11 @@ var Orchestrator = class {
|
|
|
13126
13571
|
if (isGlobalThread(thread)) {
|
|
13127
13572
|
const { globalAgentCwd: globalAgentCwd2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
13128
13573
|
updateThread(thread.id, { worktreePath: globalAgentCwd2() });
|
|
13129
|
-
|
|
13574
|
+
const restored2 = setStatus(thread.id, "idle");
|
|
13575
|
+
this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
|
|
13576
|
+
return restored2;
|
|
13130
13577
|
}
|
|
13131
|
-
if (!(0,
|
|
13578
|
+
if (!(0, import_node_fs31.existsSync)(thread.worktreePath)) {
|
|
13132
13579
|
const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
|
|
13133
13580
|
const { execa: execa7 } = await import("execa");
|
|
13134
13581
|
const slug = thread.worktreePath.split("/").pop();
|
|
@@ -13139,9 +13586,33 @@ var Orchestrator = class {
|
|
|
13139
13586
|
void createThreadWorktree2;
|
|
13140
13587
|
void slug;
|
|
13141
13588
|
}
|
|
13142
|
-
|
|
13143
|
-
|
|
13144
|
-
|
|
13589
|
+
const restorePatch = {};
|
|
13590
|
+
let alreadyMerged = normalizePrState(thread.prState) === "MERGED";
|
|
13591
|
+
if (!alreadyMerged && thread.prUrl?.trim() && thread.worktreePath?.trim()) {
|
|
13592
|
+
try {
|
|
13593
|
+
const selector = resolvePrSelector(thread);
|
|
13594
|
+
if (selector) {
|
|
13595
|
+
const meta = await getPrMeta(thread.worktreePath, selector);
|
|
13596
|
+
if (meta) {
|
|
13597
|
+
const state = normalizePrState(meta.state);
|
|
13598
|
+
if (meta.url && meta.url !== thread.prUrl) restorePatch.prUrl = meta.url;
|
|
13599
|
+
if (meta.title && meta.title !== thread.prTitle) restorePatch.prTitle = meta.title;
|
|
13600
|
+
if (state) restorePatch.prState = state;
|
|
13601
|
+
if (state === "MERGED") alreadyMerged = true;
|
|
13602
|
+
}
|
|
13603
|
+
}
|
|
13604
|
+
} catch {
|
|
13605
|
+
}
|
|
13606
|
+
}
|
|
13607
|
+
if (alreadyMerged) restorePatch.skipAutoArchiveOnMerge = true;
|
|
13608
|
+
if (Object.keys(restorePatch).length > 0) {
|
|
13609
|
+
updateThread(thread.id, restorePatch);
|
|
13610
|
+
}
|
|
13611
|
+
const restored = setStatus(thread.id, "idle");
|
|
13612
|
+
this.emit({ type: "status_changed", threadId: restored.id, status: restored.status });
|
|
13613
|
+
return restored;
|
|
13614
|
+
}
|
|
13615
|
+
async attachCommand(threadRef) {
|
|
13145
13616
|
const thread = this.requireThread(threadRef);
|
|
13146
13617
|
const adapter = getAdapter(thread.agent);
|
|
13147
13618
|
return adapter.buildAttach(thread);
|
|
@@ -13360,6 +13831,7 @@ function mcpArchiveBlockedReason(thread) {
|
|
|
13360
13831
|
}
|
|
13361
13832
|
|
|
13362
13833
|
// src/mcp/server.ts
|
|
13834
|
+
init_profile();
|
|
13363
13835
|
var MAX_ORCH_THREADS = 5;
|
|
13364
13836
|
var CREATE_THREAD_TIMEOUT_MS = 9e4;
|
|
13365
13837
|
function withTimeout(promise, ms, label) {
|
|
@@ -13473,14 +13945,13 @@ async function startMcpServer() {
|
|
|
13473
13945
|
),
|
|
13474
13946
|
artifact_id: import_zod.z.string().optional().describe("Stable id when updating the same artifact across turns")
|
|
13475
13947
|
},
|
|
13476
|
-
async ({ title, type,
|
|
13948
|
+
async ({ title, type, artifact_id }) => {
|
|
13477
13949
|
const id = artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
13478
13950
|
const payload = {
|
|
13479
13951
|
ok: true,
|
|
13480
13952
|
artifact_id: id,
|
|
13481
13953
|
title,
|
|
13482
13954
|
type,
|
|
13483
|
-
content,
|
|
13484
13955
|
message: "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
|
|
13485
13956
|
};
|
|
13486
13957
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
@@ -13533,7 +14004,6 @@ async function startMcpServer() {
|
|
|
13533
14004
|
ok: true,
|
|
13534
14005
|
path,
|
|
13535
14006
|
title: title?.trim() || "Plan",
|
|
13536
|
-
content,
|
|
13537
14007
|
message: "Plan saved to .context/attachments/plan.md and shown in Sideboard chat for approval."
|
|
13538
14008
|
};
|
|
13539
14009
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
@@ -13563,9 +14033,6 @@ async function startMcpServer() {
|
|
|
13563
14033
|
datasource: args.datasource ?? (args.resource ? "inline" : "brightsy"),
|
|
13564
14034
|
resource_id: args.resource_id,
|
|
13565
14035
|
record_id: args.record_id,
|
|
13566
|
-
resource: args.resource,
|
|
13567
|
-
record: args.record,
|
|
13568
|
-
records: args.records,
|
|
13569
14036
|
message: "Schema pane accepted. Sideboard desktop opens the CMS column beside chat."
|
|
13570
14037
|
};
|
|
13571
14038
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
@@ -13593,744 +14060,747 @@ async function startMcpServer() {
|
|
|
13593
14060
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
13594
14061
|
}
|
|
13595
14062
|
);
|
|
13596
|
-
|
|
13597
|
-
|
|
13598
|
-
|
|
13599
|
-
|
|
13600
|
-
|
|
13601
|
-
|
|
13602
|
-
|
|
13603
|
-
|
|
13604
|
-
|
|
13605
|
-
|
|
13606
|
-
|
|
13607
|
-
|
|
13608
|
-
|
|
13609
|
-
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13617
|
-
|
|
13618
|
-
|
|
13619
|
-
|
|
13620
|
-
|
|
13621
|
-
|
|
13622
|
-
|
|
13623
|
-
if (
|
|
13624
|
-
|
|
13625
|
-
|
|
13626
|
-
|
|
14063
|
+
if (sideboardMcpProfile() !== "worktree") {
|
|
14064
|
+
const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
14065
|
+
const accountDefaults = resolveThreadDefaults2();
|
|
14066
|
+
const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
|
|
14067
|
+
server.tool(
|
|
14068
|
+
"create_thread",
|
|
14069
|
+
`Create a new worktree thread (chat) from branch, pr, or ticket. Pass repoPath from list_workspaces. From an orchestration chat, omit parentThreadId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Prefer omitting agent/model so Sideboard applies ${accountDefaultsHint}. Then use send_to_thread to chat.`,
|
|
14070
|
+
{
|
|
14071
|
+
sourceType: import_zod.z.enum(["branch", "pr", "ticket"]),
|
|
14072
|
+
sourceRef: import_zod.z.string(),
|
|
14073
|
+
agent: import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]).optional().describe(`Omit to use Account default agent (${accountDefaults.agent})`),
|
|
14074
|
+
model: import_zod.z.string().nullable().optional().describe(
|
|
14075
|
+
`Usually omit to use Account default model (${accountDefaults.model?.trim() || "Auto"}). Pass null only to force Auto / agent-default.`
|
|
14076
|
+
),
|
|
14077
|
+
repoPath: import_zod.z.string(),
|
|
14078
|
+
title: import_zod.z.string().optional(),
|
|
14079
|
+
parentThreadId: import_zod.z.string().optional().describe(
|
|
14080
|
+
"Orchestration: omit (preferred) or pass YOUR chat id from the turn reminder / AGENTS.md. Do not invent uuids."
|
|
14081
|
+
)
|
|
14082
|
+
},
|
|
14083
|
+
async (args) => {
|
|
14084
|
+
const envParentId = process.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID?.trim() || "";
|
|
14085
|
+
let parentId = args.parentThreadId?.trim() || "";
|
|
14086
|
+
let parent = parentId ? orch.getThread(parentId) : null;
|
|
14087
|
+
let parentCorrectedFrom;
|
|
14088
|
+
if (envParentId) {
|
|
14089
|
+
const envParent = orch.getThread(envParentId);
|
|
14090
|
+
if (envParent) {
|
|
14091
|
+
if (parentId && parentId !== envParentId) parentCorrectedFrom = parentId;
|
|
14092
|
+
else if (!parentId) parentCorrectedFrom = void 0;
|
|
14093
|
+
parentId = envParentId;
|
|
14094
|
+
parent = envParent;
|
|
14095
|
+
}
|
|
13627
14096
|
}
|
|
13628
|
-
|
|
13629
|
-
|
|
13630
|
-
|
|
13631
|
-
|
|
13632
|
-
|
|
13633
|
-
|
|
13634
|
-
|
|
13635
|
-
|
|
13636
|
-
|
|
14097
|
+
if (parentId && !parent) {
|
|
14098
|
+
parentCorrectedFrom = parentId;
|
|
14099
|
+
parentId = "";
|
|
14100
|
+
parent = null;
|
|
14101
|
+
}
|
|
14102
|
+
if (parentId) {
|
|
14103
|
+
const children = orch.getThreads(false).filter((t) => t.parentThreadId === parentId);
|
|
14104
|
+
if (children.length >= MAX_ORCH_THREADS) {
|
|
14105
|
+
return {
|
|
14106
|
+
content: [
|
|
14107
|
+
{
|
|
14108
|
+
type: "text",
|
|
14109
|
+
text: `Thread-creation cap (${MAX_ORCH_THREADS}) reached for this orchestration session`
|
|
14110
|
+
}
|
|
14111
|
+
],
|
|
14112
|
+
isError: true
|
|
14113
|
+
};
|
|
14114
|
+
}
|
|
14115
|
+
}
|
|
14116
|
+
let agentArg = args.agent;
|
|
14117
|
+
let agentCoercedFrom;
|
|
14118
|
+
const resolvedProbe = resolveNewThreadOptions2({ agent: agentArg }).agent;
|
|
14119
|
+
if (resolvedProbe === "codex") {
|
|
14120
|
+
agentCoercedFrom = agentArg ?? "codex";
|
|
14121
|
+
const accountAgent = resolveNewThreadOptions2({}).agent;
|
|
14122
|
+
agentArg = accountAgent !== "codex" ? accountAgent : "cursor";
|
|
14123
|
+
}
|
|
14124
|
+
const opts = resolveNewThreadOptions2({
|
|
14125
|
+
agent: agentArg,
|
|
14126
|
+
model: args.model
|
|
14127
|
+
});
|
|
14128
|
+
try {
|
|
14129
|
+
const thread = await withTimeout(
|
|
14130
|
+
orch.createThread({
|
|
14131
|
+
sourceType: args.sourceType,
|
|
14132
|
+
sourceRef: args.sourceRef,
|
|
14133
|
+
agent: opts.agent,
|
|
14134
|
+
model: opts.model,
|
|
14135
|
+
effort: opts.effort,
|
|
14136
|
+
fast: opts.fast,
|
|
14137
|
+
repoPath: args.repoPath,
|
|
14138
|
+
title: args.title,
|
|
14139
|
+
parentThreadId: parentId || null
|
|
14140
|
+
}),
|
|
14141
|
+
CREATE_THREAD_TIMEOUT_MS,
|
|
14142
|
+
"create_thread"
|
|
14143
|
+
);
|
|
14144
|
+
const parentNote = parentCorrectedFrom ? parentId ? `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; nested under ${parentId}` : `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; created without parent` : void 0;
|
|
13637
14145
|
return {
|
|
13638
14146
|
content: [
|
|
13639
14147
|
{
|
|
13640
14148
|
type: "text",
|
|
13641
|
-
text:
|
|
14149
|
+
text: JSON.stringify({
|
|
14150
|
+
id: thread.id,
|
|
14151
|
+
title: thread.title,
|
|
14152
|
+
branchName: thread.branchName,
|
|
14153
|
+
worktreePath: thread.worktreePath,
|
|
14154
|
+
agent: thread.agent,
|
|
14155
|
+
model: thread.model,
|
|
14156
|
+
status: thread.status,
|
|
14157
|
+
link: `sideboard://thread/${thread.id}`,
|
|
14158
|
+
parentThreadId: thread.parentThreadId,
|
|
14159
|
+
...agentCoercedFrom ? {
|
|
14160
|
+
agentCoercedFrom,
|
|
14161
|
+
note: `Avoid nested Codex under a Codex orchestrator \u2014 used Account default agent=${thread.agent}`
|
|
14162
|
+
} : {},
|
|
14163
|
+
...parentCorrectedFrom ? { parentCorrectedFrom, parentNote } : {}
|
|
14164
|
+
})
|
|
14165
|
+
}
|
|
14166
|
+
]
|
|
14167
|
+
};
|
|
14168
|
+
} catch (err) {
|
|
14169
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14170
|
+
return {
|
|
14171
|
+
content: [
|
|
14172
|
+
{
|
|
14173
|
+
type: "text",
|
|
14174
|
+
text: `create_thread failed: ${message}`
|
|
13642
14175
|
}
|
|
13643
14176
|
],
|
|
13644
14177
|
isError: true
|
|
13645
14178
|
};
|
|
13646
14179
|
}
|
|
13647
14180
|
}
|
|
13648
|
-
|
|
13649
|
-
|
|
13650
|
-
|
|
13651
|
-
|
|
13652
|
-
|
|
13653
|
-
|
|
13654
|
-
|
|
13655
|
-
|
|
13656
|
-
|
|
13657
|
-
|
|
13658
|
-
|
|
13659
|
-
|
|
13660
|
-
|
|
13661
|
-
|
|
13662
|
-
|
|
13663
|
-
|
|
13664
|
-
|
|
13665
|
-
agent: opts.agent,
|
|
13666
|
-
model: opts.model,
|
|
13667
|
-
effort: opts.effort,
|
|
13668
|
-
fast: opts.fast,
|
|
13669
|
-
repoPath: args.repoPath,
|
|
13670
|
-
title: args.title,
|
|
13671
|
-
parentThreadId: parentId || null
|
|
13672
|
-
}),
|
|
13673
|
-
CREATE_THREAD_TIMEOUT_MS,
|
|
13674
|
-
"create_thread"
|
|
13675
|
-
);
|
|
13676
|
-
const parentNote = parentCorrectedFrom ? parentId ? `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; nested under ${parentId}` : `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; created without parent` : void 0;
|
|
14181
|
+
);
|
|
14182
|
+
server.tool(
|
|
14183
|
+
"send_to_thread",
|
|
14184
|
+
"Queue a prompt on a worktree thread chat (runs under concurrency cap). Use after create_thread to start or continue a conversation. Set force_stop=true to interrupt an in-flight/queued turn (kill + clear queue) before queueing this prompt \u2014 use when the thread is mid-turn or has stale queued prompts you need to replace.",
|
|
14185
|
+
{
|
|
14186
|
+
ref: import_zod.z.string(),
|
|
14187
|
+
prompt: import_zod.z.string(),
|
|
14188
|
+
force_stop: import_zod.z.boolean().optional()
|
|
14189
|
+
},
|
|
14190
|
+
async ({ ref, prompt, force_stop }) => {
|
|
14191
|
+
if (force_stop) {
|
|
14192
|
+
const existing = orch.getThread(ref);
|
|
14193
|
+
if (existing) {
|
|
14194
|
+
orch.stop(ref, { clearQueue: true });
|
|
14195
|
+
}
|
|
14196
|
+
}
|
|
14197
|
+
const thread = await orch.send(ref, prompt);
|
|
13677
14198
|
return {
|
|
13678
14199
|
content: [
|
|
13679
14200
|
{
|
|
13680
14201
|
type: "text",
|
|
13681
14202
|
text: JSON.stringify({
|
|
13682
14203
|
id: thread.id,
|
|
13683
|
-
title: thread.title,
|
|
13684
|
-
branchName: thread.branchName,
|
|
13685
|
-
worktreePath: thread.worktreePath,
|
|
13686
|
-
agent: thread.agent,
|
|
13687
|
-
model: thread.model,
|
|
13688
14204
|
status: thread.status,
|
|
13689
|
-
|
|
13690
|
-
|
|
13691
|
-
...agentCoercedFrom ? {
|
|
13692
|
-
agentCoercedFrom,
|
|
13693
|
-
note: `Avoid nested Codex under a Codex orchestrator \u2014 used Account default agent=${thread.agent}`
|
|
13694
|
-
} : {},
|
|
13695
|
-
...parentCorrectedFrom ? { parentCorrectedFrom, parentNote } : {}
|
|
14205
|
+
queueLength: thread.queue.length,
|
|
14206
|
+
forceStopped: Boolean(force_stop)
|
|
13696
14207
|
})
|
|
13697
14208
|
}
|
|
13698
14209
|
]
|
|
13699
14210
|
};
|
|
13700
|
-
}
|
|
13701
|
-
|
|
14211
|
+
}
|
|
14212
|
+
);
|
|
14213
|
+
server.tool(
|
|
14214
|
+
"wait_for_turn",
|
|
14215
|
+
"Block until the thread finishes its current/queued turn (avoids polling). Use after send_to_thread to read the agent reply.",
|
|
14216
|
+
{
|
|
14217
|
+
ref: import_zod.z.string(),
|
|
14218
|
+
timeoutMs: import_zod.z.number().optional()
|
|
14219
|
+
},
|
|
14220
|
+
async ({ ref, timeoutMs }) => {
|
|
14221
|
+
const thread = await orch.waitForTurn(ref, timeoutMs ?? 6e5);
|
|
14222
|
+
const result = orch.getTurnResult(thread.id);
|
|
13702
14223
|
return {
|
|
13703
14224
|
content: [
|
|
13704
14225
|
{
|
|
13705
14226
|
type: "text",
|
|
13706
|
-
text:
|
|
14227
|
+
text: JSON.stringify({
|
|
14228
|
+
id: thread.id,
|
|
14229
|
+
status: result.status,
|
|
14230
|
+
text: result.text
|
|
14231
|
+
})
|
|
13707
14232
|
}
|
|
13708
|
-
]
|
|
13709
|
-
isError: true
|
|
14233
|
+
]
|
|
13710
14234
|
};
|
|
13711
14235
|
}
|
|
13712
|
-
|
|
13713
|
-
|
|
13714
|
-
|
|
13715
|
-
|
|
13716
|
-
|
|
13717
|
-
|
|
13718
|
-
|
|
13719
|
-
|
|
13720
|
-
force_stop: import_zod.z.boolean().optional()
|
|
13721
|
-
},
|
|
13722
|
-
async ({ ref, prompt, force_stop }) => {
|
|
13723
|
-
if (force_stop) {
|
|
13724
|
-
const existing = orch.getThread(ref);
|
|
13725
|
-
if (existing) {
|
|
13726
|
-
orch.stop(ref, { clearQueue: true });
|
|
13727
|
-
}
|
|
14236
|
+
);
|
|
14237
|
+
server.tool(
|
|
14238
|
+
"get_turn_result",
|
|
14239
|
+
"Final assistant message only (not full transcript)",
|
|
14240
|
+
{ ref: import_zod.z.string() },
|
|
14241
|
+
async ({ ref }) => {
|
|
14242
|
+
const result = orch.getTurnResult(ref);
|
|
14243
|
+
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
13728
14244
|
}
|
|
13729
|
-
|
|
13730
|
-
|
|
13731
|
-
|
|
13732
|
-
|
|
13733
|
-
|
|
13734
|
-
|
|
13735
|
-
|
|
13736
|
-
|
|
13737
|
-
|
|
13738
|
-
|
|
13739
|
-
|
|
13740
|
-
|
|
13741
|
-
|
|
13742
|
-
|
|
13743
|
-
|
|
13744
|
-
|
|
13745
|
-
|
|
13746
|
-
|
|
13747
|
-
|
|
13748
|
-
{
|
|
13749
|
-
ref: import_zod.z.string(),
|
|
13750
|
-
timeoutMs: import_zod.z.number().optional()
|
|
13751
|
-
},
|
|
13752
|
-
async ({ ref, timeoutMs }) => {
|
|
13753
|
-
const thread = await orch.waitForTurn(ref, timeoutMs ?? 6e5);
|
|
13754
|
-
const result = orch.getTurnResult(thread.id);
|
|
13755
|
-
return {
|
|
13756
|
-
content: [
|
|
13757
|
-
{
|
|
13758
|
-
type: "text",
|
|
13759
|
-
text: JSON.stringify({
|
|
13760
|
-
id: thread.id,
|
|
13761
|
-
status: result.status,
|
|
13762
|
-
text: result.text
|
|
13763
|
-
})
|
|
13764
|
-
}
|
|
13765
|
-
]
|
|
13766
|
-
};
|
|
13767
|
-
}
|
|
13768
|
-
);
|
|
13769
|
-
server.tool(
|
|
13770
|
-
"get_turn_result",
|
|
13771
|
-
"Final assistant message only (not full transcript)",
|
|
13772
|
-
{ ref: import_zod.z.string() },
|
|
13773
|
-
async ({ ref }) => {
|
|
13774
|
-
const result = orch.getTurnResult(ref);
|
|
13775
|
-
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
13776
|
-
}
|
|
13777
|
-
);
|
|
13778
|
-
server.tool(
|
|
13779
|
-
"stop_thread",
|
|
13780
|
-
"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.",
|
|
13781
|
-
{
|
|
13782
|
-
ref: import_zod.z.string(),
|
|
13783
|
-
force: import_zod.z.boolean().optional()
|
|
13784
|
-
},
|
|
13785
|
-
async ({ ref, force }) => {
|
|
13786
|
-
const t = orch.getThread(ref);
|
|
13787
|
-
if (!t) {
|
|
14245
|
+
);
|
|
14246
|
+
server.tool(
|
|
14247
|
+
"stop_thread",
|
|
14248
|
+
"Force-stop a thread: kill any in-flight agent turn AND clear queued prompts so drainQueue cannot continue. Does not archive the worktree. Optional force defaults to true.",
|
|
14249
|
+
{
|
|
14250
|
+
ref: import_zod.z.string(),
|
|
14251
|
+
force: import_zod.z.boolean().optional()
|
|
14252
|
+
},
|
|
14253
|
+
async ({ ref, force }) => {
|
|
14254
|
+
const t = orch.getThread(ref);
|
|
14255
|
+
if (!t) {
|
|
14256
|
+
return {
|
|
14257
|
+
content: [{ type: "text", text: `Thread not found: ${ref}` }],
|
|
14258
|
+
isError: true
|
|
14259
|
+
};
|
|
14260
|
+
}
|
|
14261
|
+
const clearQueue = force !== false;
|
|
14262
|
+
const hadQueued = t.queue.length > 0;
|
|
14263
|
+
const stopped = orch.stop(ref, { clearQueue });
|
|
13788
14264
|
return {
|
|
13789
|
-
content: [
|
|
13790
|
-
|
|
14265
|
+
content: [
|
|
14266
|
+
{
|
|
14267
|
+
type: "text",
|
|
14268
|
+
text: JSON.stringify({
|
|
14269
|
+
id: stopped.id,
|
|
14270
|
+
status: stopped.status,
|
|
14271
|
+
clearedQueue: clearQueue && hadQueued
|
|
14272
|
+
})
|
|
14273
|
+
}
|
|
14274
|
+
]
|
|
13791
14275
|
};
|
|
13792
14276
|
}
|
|
13793
|
-
|
|
13794
|
-
|
|
13795
|
-
|
|
13796
|
-
|
|
13797
|
-
|
|
13798
|
-
|
|
13799
|
-
|
|
13800
|
-
|
|
13801
|
-
|
|
13802
|
-
|
|
13803
|
-
|
|
13804
|
-
|
|
13805
|
-
|
|
13806
|
-
|
|
13807
|
-
|
|
13808
|
-
|
|
13809
|
-
|
|
13810
|
-
|
|
13811
|
-
|
|
13812
|
-
|
|
13813
|
-
|
|
13814
|
-
async ({ ref }) => {
|
|
13815
|
-
const t = orch.getThread(ref);
|
|
13816
|
-
if (!t) {
|
|
14277
|
+
);
|
|
14278
|
+
server.tool(
|
|
14279
|
+
"archive_thread",
|
|
14280
|
+
"Archive a thread (stops agent/dev, runs archive script, removes worktree when last chat tab). Cannot archive the cloud coordinator \u2014 use the Sideboard UI for that.",
|
|
14281
|
+
{ ref: import_zod.z.string() },
|
|
14282
|
+
async ({ ref }) => {
|
|
14283
|
+
const t = orch.getThread(ref);
|
|
14284
|
+
if (!t) {
|
|
14285
|
+
return {
|
|
14286
|
+
content: [{ type: "text", text: `Thread not found: ${ref}` }],
|
|
14287
|
+
isError: true
|
|
14288
|
+
};
|
|
14289
|
+
}
|
|
14290
|
+
const blocked = mcpArchiveBlockedReason(t);
|
|
14291
|
+
if (blocked) {
|
|
14292
|
+
return {
|
|
14293
|
+
content: [{ type: "text", text: blocked }],
|
|
14294
|
+
isError: true
|
|
14295
|
+
};
|
|
14296
|
+
}
|
|
14297
|
+
const archived = await orch.archive(ref);
|
|
13817
14298
|
return {
|
|
13818
|
-
content: [
|
|
13819
|
-
|
|
14299
|
+
content: [
|
|
14300
|
+
{
|
|
14301
|
+
type: "text",
|
|
14302
|
+
text: JSON.stringify({
|
|
14303
|
+
id: archived.id,
|
|
14304
|
+
status: archived.status
|
|
14305
|
+
})
|
|
14306
|
+
}
|
|
14307
|
+
]
|
|
13820
14308
|
};
|
|
13821
14309
|
}
|
|
13822
|
-
|
|
13823
|
-
|
|
13824
|
-
|
|
13825
|
-
|
|
13826
|
-
|
|
13827
|
-
|
|
14310
|
+
);
|
|
14311
|
+
server.tool(
|
|
14312
|
+
"restore_thread",
|
|
14313
|
+
"Restore an archived thread (recreates worktree from branch when needed)",
|
|
14314
|
+
{ ref: import_zod.z.string() },
|
|
14315
|
+
async ({ ref }) => {
|
|
14316
|
+
try {
|
|
14317
|
+
const restored = await orch.restore(ref);
|
|
14318
|
+
return {
|
|
14319
|
+
content: [
|
|
14320
|
+
{
|
|
14321
|
+
type: "text",
|
|
14322
|
+
text: JSON.stringify({
|
|
14323
|
+
id: restored.id,
|
|
14324
|
+
status: restored.status,
|
|
14325
|
+
worktreePath: restored.worktreePath
|
|
14326
|
+
})
|
|
14327
|
+
}
|
|
14328
|
+
]
|
|
14329
|
+
};
|
|
14330
|
+
} catch (err) {
|
|
14331
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14332
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14333
|
+
}
|
|
13828
14334
|
}
|
|
13829
|
-
|
|
13830
|
-
|
|
13831
|
-
|
|
13832
|
-
|
|
13833
|
-
|
|
13834
|
-
|
|
13835
|
-
|
|
13836
|
-
|
|
13837
|
-
|
|
13838
|
-
|
|
13839
|
-
]
|
|
13840
|
-
};
|
|
13841
|
-
}
|
|
13842
|
-
);
|
|
13843
|
-
server.tool(
|
|
13844
|
-
"restore_thread",
|
|
13845
|
-
"Restore an archived thread (recreates worktree from branch when needed)",
|
|
13846
|
-
{ ref: import_zod.z.string() },
|
|
13847
|
-
async ({ ref }) => {
|
|
13848
|
-
try {
|
|
13849
|
-
const restored = await orch.restore(ref);
|
|
14335
|
+
);
|
|
14336
|
+
server.tool(
|
|
14337
|
+
"get_diff",
|
|
14338
|
+
"Compact diff summary (capped hunks, paginated)",
|
|
14339
|
+
{
|
|
14340
|
+
ref: import_zod.z.string(),
|
|
14341
|
+
maxFiles: import_zod.z.number().optional()
|
|
14342
|
+
},
|
|
14343
|
+
async ({ ref, maxFiles }) => {
|
|
14344
|
+
const summary = await orch.diffSummary(ref);
|
|
13850
14345
|
return {
|
|
13851
14346
|
content: [
|
|
13852
14347
|
{
|
|
13853
14348
|
type: "text",
|
|
13854
14349
|
text: JSON.stringify({
|
|
13855
|
-
|
|
13856
|
-
|
|
13857
|
-
worktreePath: restored.worktreePath
|
|
14350
|
+
...summary,
|
|
14351
|
+
files: summary.files.slice(0, maxFiles ?? 10)
|
|
13858
14352
|
})
|
|
13859
14353
|
}
|
|
13860
14354
|
]
|
|
13861
14355
|
};
|
|
13862
|
-
} catch (err) {
|
|
13863
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
13864
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
13865
14356
|
}
|
|
13866
|
-
|
|
13867
|
-
|
|
13868
|
-
|
|
13869
|
-
|
|
13870
|
-
|
|
13871
|
-
|
|
13872
|
-
|
|
13873
|
-
|
|
13874
|
-
|
|
13875
|
-
|
|
13876
|
-
|
|
13877
|
-
|
|
13878
|
-
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
|
|
13882
|
-
|
|
13883
|
-
|
|
13884
|
-
|
|
14357
|
+
);
|
|
14358
|
+
server.tool(
|
|
14359
|
+
"request_review",
|
|
14360
|
+
'Start a merge-readiness Review on a worktree agent thread (same as the desktop Review button). Opens a new Review chat tab, attaches .sideboard/review.md when present (else local Review request.md / stock template), and sends "Review changes in this workspace." Expect Approve / Approve with nits / Request changes / Needs more information. Pass a worktree thread ref \u2014 not the orchestrator. Then wait_for_turn / get_turn_result on the returned review tab id.',
|
|
14361
|
+
{ ref: import_zod.z.string().describe("Worktree thread id/ref to review") },
|
|
14362
|
+
async ({ ref }) => {
|
|
14363
|
+
try {
|
|
14364
|
+
const tab = await orch.requestReview(ref);
|
|
14365
|
+
const from = orch.getThread(ref);
|
|
14366
|
+
return {
|
|
14367
|
+
content: [
|
|
14368
|
+
{
|
|
14369
|
+
type: "text",
|
|
14370
|
+
text: JSON.stringify({
|
|
14371
|
+
id: tab.id,
|
|
14372
|
+
title: tab.title,
|
|
14373
|
+
status: tab.status,
|
|
14374
|
+
fromThreadId: from?.id ?? ref,
|
|
14375
|
+
link: `sideboard://thread/${tab.id}`
|
|
14376
|
+
})
|
|
14377
|
+
}
|
|
14378
|
+
]
|
|
14379
|
+
};
|
|
14380
|
+
} catch (err) {
|
|
14381
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14382
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14383
|
+
}
|
|
14384
|
+
}
|
|
14385
|
+
);
|
|
14386
|
+
const agentEnum = import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]);
|
|
14387
|
+
server.tool(
|
|
14388
|
+
"list_models",
|
|
14389
|
+
"List models for an agent. Prefer Auto: do not call this unless you have a reason to pin a specific model (user request, cost/latency, capability). Omit agent to list all.",
|
|
14390
|
+
{
|
|
14391
|
+
agent: agentEnum.optional().describe("Limit to one agent; omit for all")
|
|
14392
|
+
},
|
|
14393
|
+
async ({ agent }) => {
|
|
14394
|
+
try {
|
|
14395
|
+
const catalogs = await listModelsForAgent(agent);
|
|
14396
|
+
return {
|
|
14397
|
+
content: [{ type: "text", text: JSON.stringify(catalogs, null, 2) }]
|
|
14398
|
+
};
|
|
14399
|
+
} catch (err) {
|
|
14400
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14401
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14402
|
+
}
|
|
14403
|
+
}
|
|
14404
|
+
);
|
|
14405
|
+
server.tool(
|
|
14406
|
+
"fork_worktree",
|
|
14407
|
+
"Fork a worktree agent chat into a NEW git worktree + chat (desktop \u201CFork to new workspace\u201D). Seeds a transcript (through through_index, default all). Optional agent override. Leave model unset for Auto (default) \u2014 only pass model when you have a reason. Not for the orchestrator. Then send_to_thread / wait_for_turn on the returned id.",
|
|
14408
|
+
{
|
|
14409
|
+
ref: import_zod.z.string().describe("Worktree thread id/ref to fork"),
|
|
14410
|
+
through_index: import_zod.z.number().optional().describe("Inclusive message index to include in the transcript (default: all)"),
|
|
14411
|
+
agent: agentEnum.optional().describe("Agent for the forked chat (default: same as source)"),
|
|
14412
|
+
model: import_zod.z.string().nullable().optional().describe("Usually omit (Auto). Only set from list_models when you need a specific model"),
|
|
14413
|
+
title: import_zod.z.string().optional()
|
|
14414
|
+
},
|
|
14415
|
+
async ({ ref, through_index, agent, model, title }) => {
|
|
14416
|
+
try {
|
|
14417
|
+
const source = orch.getThread(ref);
|
|
14418
|
+
if (source) await orch.reconcile(source.repoPath, { drainQueues: false });
|
|
14419
|
+
const thread = await orch.forkThreadWorktree({
|
|
14420
|
+
threadId: ref,
|
|
14421
|
+
throughIndex: through_index,
|
|
14422
|
+
agent,
|
|
14423
|
+
model,
|
|
14424
|
+
title
|
|
14425
|
+
});
|
|
14426
|
+
return {
|
|
14427
|
+
content: [
|
|
14428
|
+
{
|
|
14429
|
+
type: "text",
|
|
14430
|
+
text: JSON.stringify({
|
|
14431
|
+
id: thread.id,
|
|
14432
|
+
title: thread.title,
|
|
14433
|
+
status: thread.status,
|
|
14434
|
+
agent: thread.agent,
|
|
14435
|
+
model: thread.model,
|
|
14436
|
+
branchName: thread.branchName,
|
|
14437
|
+
worktreePath: thread.worktreePath,
|
|
14438
|
+
fromThreadId: source?.id ?? ref,
|
|
14439
|
+
link: `sideboard://thread/${thread.id}`
|
|
14440
|
+
})
|
|
14441
|
+
}
|
|
14442
|
+
]
|
|
14443
|
+
};
|
|
14444
|
+
} catch (err) {
|
|
14445
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14446
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14447
|
+
}
|
|
14448
|
+
}
|
|
14449
|
+
);
|
|
14450
|
+
server.tool(
|
|
14451
|
+
"fork_chat",
|
|
14452
|
+
"Fork a chat into a NEW tab on the SAME workspace: worktree agent \u2192 same worktree tab; Global orchestration chat \u2192 new orchestration chat (same synthetic home). Seeds a transcript; optional agent override. Leave model unset for Auto unless you have a reason. Orchestration forks require an MCP-capable agent (claude, cursor, codex, opencode \u2014 not brightsy). Remote coordinators use this to continue an orchestration chat on another agent after session limits. Then send_to_thread / wait_for_turn on the returned id. Use fork_worktree only for worktree agents that need a new git worktree.",
|
|
14453
|
+
{
|
|
14454
|
+
ref: import_zod.z.string().describe("Thread id/ref to fork (worktree agent or orchestration chat)"),
|
|
14455
|
+
through_index: import_zod.z.number().optional().describe("Inclusive message index to include in the transcript (default: all)"),
|
|
14456
|
+
agent: agentEnum.optional().describe("Agent for the forked chat (default: same as source)"),
|
|
14457
|
+
model: import_zod.z.string().nullable().optional().describe("Usually omit (Auto). Only set from list_models when you need a specific model"),
|
|
14458
|
+
title: import_zod.z.string().optional()
|
|
14459
|
+
},
|
|
14460
|
+
async ({ ref, through_index, agent, model, title }) => {
|
|
14461
|
+
try {
|
|
14462
|
+
const source = orch.getThread(ref);
|
|
14463
|
+
if (!source) {
|
|
14464
|
+
return {
|
|
14465
|
+
content: [{ type: "text", text: `Thread not found: ${ref}` }],
|
|
14466
|
+
isError: true
|
|
14467
|
+
};
|
|
13885
14468
|
}
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
|
|
13889
|
-
|
|
13890
|
-
|
|
13891
|
-
|
|
13892
|
-
|
|
13893
|
-
|
|
13894
|
-
|
|
13895
|
-
|
|
13896
|
-
|
|
13897
|
-
|
|
14469
|
+
const tab = orch.forkChatTab({
|
|
14470
|
+
threadId: source.id,
|
|
14471
|
+
throughIndex: through_index,
|
|
14472
|
+
agent,
|
|
14473
|
+
model,
|
|
14474
|
+
title
|
|
14475
|
+
});
|
|
14476
|
+
return {
|
|
14477
|
+
content: [
|
|
14478
|
+
{
|
|
14479
|
+
type: "text",
|
|
14480
|
+
text: JSON.stringify({
|
|
14481
|
+
id: tab.id,
|
|
14482
|
+
title: tab.title,
|
|
14483
|
+
status: tab.status,
|
|
14484
|
+
agent: tab.agent,
|
|
14485
|
+
model: tab.model,
|
|
14486
|
+
sourceType: tab.sourceType,
|
|
14487
|
+
worktreePath: tab.worktreePath,
|
|
14488
|
+
fromThreadId: source.id,
|
|
14489
|
+
link: `sideboard://thread/${tab.id}`
|
|
14490
|
+
})
|
|
14491
|
+
}
|
|
14492
|
+
]
|
|
14493
|
+
};
|
|
14494
|
+
} catch (err) {
|
|
14495
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
14496
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
14497
|
+
}
|
|
14498
|
+
}
|
|
14499
|
+
);
|
|
14500
|
+
server.tool(
|
|
14501
|
+
"run_dev_script",
|
|
14502
|
+
"Start a .sideboard/.conductor run script for a thread (default script if name omitted); returns port",
|
|
14503
|
+
{
|
|
14504
|
+
ref: import_zod.z.string(),
|
|
14505
|
+
name: import_zod.z.string().optional()
|
|
14506
|
+
},
|
|
14507
|
+
async ({ ref, name }) => {
|
|
14508
|
+
const result = await orch.startDev(ref, name);
|
|
13898
14509
|
return {
|
|
13899
14510
|
content: [
|
|
13900
14511
|
{
|
|
13901
14512
|
type: "text",
|
|
13902
14513
|
text: JSON.stringify({
|
|
13903
|
-
|
|
13904
|
-
|
|
13905
|
-
|
|
13906
|
-
|
|
13907
|
-
link: `sideboard://thread/${tab.id}`
|
|
14514
|
+
port: result.port,
|
|
14515
|
+
scriptName: result.scriptName,
|
|
14516
|
+
ports: result.ports,
|
|
14517
|
+
url: `http://localhost:${result.port}`
|
|
13908
14518
|
})
|
|
13909
14519
|
}
|
|
13910
14520
|
]
|
|
13911
14521
|
};
|
|
13912
|
-
} catch (err) {
|
|
13913
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
13914
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
13915
14522
|
}
|
|
13916
|
-
|
|
13917
|
-
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
},
|
|
13925
|
-
async ({ agent }) => {
|
|
13926
|
-
try {
|
|
13927
|
-
const catalogs = await listModelsForAgent(agent);
|
|
14523
|
+
);
|
|
14524
|
+
server.tool(
|
|
14525
|
+
"list_run_scripts",
|
|
14526
|
+
"List named run scripts available for a thread",
|
|
14527
|
+
{ ref: import_zod.z.string() },
|
|
14528
|
+
async ({ ref }) => {
|
|
14529
|
+
const scripts = orch.listThreadRunScripts(ref);
|
|
14530
|
+
const active = orch.getActiveRuns(ref);
|
|
13928
14531
|
return {
|
|
13929
|
-
content: [
|
|
14532
|
+
content: [
|
|
14533
|
+
{
|
|
14534
|
+
type: "text",
|
|
14535
|
+
text: JSON.stringify({ scripts, active }, null, 2)
|
|
14536
|
+
}
|
|
14537
|
+
]
|
|
13930
14538
|
};
|
|
13931
|
-
} catch (err) {
|
|
13932
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
13933
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
13934
14539
|
}
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
14540
|
+
);
|
|
14541
|
+
server.tool(
|
|
14542
|
+
"stop_dev_script",
|
|
14543
|
+
"Stop a running script for a thread (all scripts if name omitted)",
|
|
14544
|
+
{
|
|
14545
|
+
ref: import_zod.z.string(),
|
|
14546
|
+
name: import_zod.z.string().optional()
|
|
14547
|
+
},
|
|
14548
|
+
async ({ ref, name }) => {
|
|
14549
|
+
orch.stopDev(ref, name);
|
|
14550
|
+
return { content: [{ type: "text", text: "ok" }] };
|
|
14551
|
+
}
|
|
14552
|
+
);
|
|
14553
|
+
server.tool(
|
|
14554
|
+
"run_setup",
|
|
14555
|
+
"Re-run workspace setup (Sideboard/Conductor settings or .cursor/worktrees.json)",
|
|
14556
|
+
{ ref: import_zod.z.string() },
|
|
14557
|
+
async ({ ref }) => {
|
|
14558
|
+
const result = await orch.runSetup(ref);
|
|
14559
|
+
return {
|
|
14560
|
+
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
14561
|
+
};
|
|
14562
|
+
}
|
|
14563
|
+
);
|
|
14564
|
+
server.tool(
|
|
14565
|
+
"add_workspace",
|
|
14566
|
+
"Register a git repo as a Sideboard workspace",
|
|
14567
|
+
{ repoPath: import_zod.z.string() },
|
|
14568
|
+
async ({ repoPath }) => {
|
|
14569
|
+
const ws = await orch.addWorkspace(repoPath);
|
|
14570
|
+
return { content: [{ type: "text", text: JSON.stringify(ws) }] };
|
|
14571
|
+
}
|
|
14572
|
+
);
|
|
14573
|
+
server.tool(
|
|
14574
|
+
"remove_workspace",
|
|
14575
|
+
"Unregister a Sideboard workspace (does not archive threads)",
|
|
14576
|
+
{ repoPath: import_zod.z.string() },
|
|
14577
|
+
async ({ repoPath }) => {
|
|
14578
|
+
orch.removeWorkspace(repoPath);
|
|
14579
|
+
return { content: [{ type: "text", text: "ok" }] };
|
|
14580
|
+
}
|
|
14581
|
+
);
|
|
14582
|
+
server.tool(
|
|
14583
|
+
"fanout",
|
|
14584
|
+
"Best-of-n: create one thread per agent with the same prompt (parallel attempts)",
|
|
14585
|
+
{
|
|
14586
|
+
prompt: import_zod.z.string(),
|
|
14587
|
+
agents: import_zod.z.array(import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"])),
|
|
14588
|
+
repoPath: import_zod.z.string(),
|
|
14589
|
+
sourceType: import_zod.z.enum(["branch", "pr", "ticket"]).optional(),
|
|
14590
|
+
sourceRef: import_zod.z.string().optional(),
|
|
14591
|
+
title: import_zod.z.string().optional()
|
|
14592
|
+
},
|
|
14593
|
+
async (args) => {
|
|
14594
|
+
const threads = await orch.bestOfN(args);
|
|
14595
|
+
return {
|
|
14596
|
+
content: [
|
|
14597
|
+
{
|
|
14598
|
+
type: "text",
|
|
14599
|
+
text: JSON.stringify(
|
|
14600
|
+
threads.map((t) => ({
|
|
14601
|
+
id: t.id,
|
|
14602
|
+
agent: t.agent,
|
|
14603
|
+
branchName: t.branchName,
|
|
14604
|
+
worktreePath: t.worktreePath
|
|
14605
|
+
})),
|
|
14606
|
+
null,
|
|
14607
|
+
2
|
|
14608
|
+
)
|
|
14609
|
+
}
|
|
14610
|
+
]
|
|
14611
|
+
};
|
|
14612
|
+
}
|
|
14613
|
+
);
|
|
14614
|
+
server.tool(
|
|
14615
|
+
"list_branches",
|
|
14616
|
+
"List git branches in a registered workspace. Pass repoPath from list_workspaces (unmerged into the default branch by default \u2014 for create_thread sourceType=branch).",
|
|
14617
|
+
{
|
|
14618
|
+
repoPath: import_zod.z.string(),
|
|
14619
|
+
unmergedOnly: import_zod.z.boolean().optional()
|
|
14620
|
+
},
|
|
14621
|
+
async ({ repoPath, unmergedOnly }) => {
|
|
14622
|
+
const root = await resolveRepoRoot(repoPath);
|
|
14623
|
+
const branches = await listBranches(root, {
|
|
14624
|
+
unmergedOnly: unmergedOnly !== false
|
|
13957
14625
|
});
|
|
13958
14626
|
return {
|
|
13959
14627
|
content: [
|
|
13960
14628
|
{
|
|
13961
14629
|
type: "text",
|
|
13962
|
-
text:
|
|
13963
|
-
id: thread.id,
|
|
13964
|
-
title: thread.title,
|
|
13965
|
-
status: thread.status,
|
|
13966
|
-
agent: thread.agent,
|
|
13967
|
-
model: thread.model,
|
|
13968
|
-
branchName: thread.branchName,
|
|
13969
|
-
worktreePath: thread.worktreePath,
|
|
13970
|
-
fromThreadId: source?.id ?? ref,
|
|
13971
|
-
link: `sideboard://thread/${thread.id}`
|
|
13972
|
-
})
|
|
14630
|
+
text: branches.map((b) => `${b.current ? "*" : " "} ${b.name}`).join("\n")
|
|
13973
14631
|
}
|
|
13974
14632
|
]
|
|
13975
14633
|
};
|
|
13976
|
-
} catch (err) {
|
|
13977
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
13978
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
13979
14634
|
}
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
|
|
13993
|
-
|
|
13994
|
-
|
|
13995
|
-
|
|
13996
|
-
|
|
13997
|
-
|
|
13998
|
-
|
|
13999
|
-
|
|
14000
|
-
|
|
14001
|
-
|
|
14002
|
-
|
|
14003
|
-
|
|
14004
|
-
|
|
14005
|
-
|
|
14006
|
-
|
|
14635
|
+
);
|
|
14636
|
+
server.tool(
|
|
14637
|
+
"list_prs",
|
|
14638
|
+
"List open GitHub PRs for a registered workspace. Pass repoPath from list_workspaces (uses gh against that repo remote). Then create_thread with sourceType=pr.",
|
|
14639
|
+
{ repoPath: import_zod.z.string() },
|
|
14640
|
+
async ({ repoPath }) => {
|
|
14641
|
+
const root = await resolveRepoRoot(repoPath);
|
|
14642
|
+
const prs = await listPrs(root);
|
|
14643
|
+
return {
|
|
14644
|
+
content: [
|
|
14645
|
+
{
|
|
14646
|
+
type: "text",
|
|
14647
|
+
text: prs.map(
|
|
14648
|
+
(p) => `#${p.number} ${p.title} (${p.headRefName})${p.isCrossRepository ? " [fork]" : ""}`
|
|
14649
|
+
).join("\n")
|
|
14650
|
+
}
|
|
14651
|
+
]
|
|
14652
|
+
};
|
|
14653
|
+
}
|
|
14654
|
+
);
|
|
14655
|
+
server.tool(
|
|
14656
|
+
"get_pr_stack",
|
|
14657
|
+
"Load the GitHub PR stack for a thread worktree (`gh stack view --json`). Returns null JSON when the branch is not stacked. Prefer this before mergePr on stacked PRs.",
|
|
14658
|
+
{ ref: import_zod.z.string() },
|
|
14659
|
+
async ({ ref }) => {
|
|
14660
|
+
const stack = await orch.getPrStack(ref);
|
|
14661
|
+
return {
|
|
14662
|
+
content: [{ type: "text", text: JSON.stringify(stack, null, 2) }]
|
|
14663
|
+
};
|
|
14664
|
+
}
|
|
14665
|
+
);
|
|
14666
|
+
server.tool(
|
|
14667
|
+
"open_pr_stack_layers",
|
|
14668
|
+
"Materialize one worktree+thread per stack layer (or a single 1-based layer). Pass a thread ref already on the stack.",
|
|
14669
|
+
{
|
|
14670
|
+
ref: import_zod.z.string(),
|
|
14671
|
+
layer: import_zod.z.number().int().positive().optional()
|
|
14672
|
+
},
|
|
14673
|
+
async ({ ref, layer }) => {
|
|
14674
|
+
const result = await orch.openPrStackLayers(ref, { layer });
|
|
14675
|
+
return {
|
|
14676
|
+
content: [
|
|
14677
|
+
{
|
|
14678
|
+
type: "text",
|
|
14679
|
+
text: JSON.stringify(
|
|
14680
|
+
{
|
|
14681
|
+
stackNumber: result.stack.stackNumber,
|
|
14682
|
+
trunk: result.stack.trunk,
|
|
14683
|
+
threads: result.threads.map((t) => ({
|
|
14684
|
+
id: t.id,
|
|
14685
|
+
title: t.title,
|
|
14686
|
+
branchName: t.branchName,
|
|
14687
|
+
stackLayer: t.stackLayer,
|
|
14688
|
+
worktreePath: t.worktreePath,
|
|
14689
|
+
prUrl: t.prUrl,
|
|
14690
|
+
link: `sideboard://thread/${t.id}`
|
|
14691
|
+
}))
|
|
14692
|
+
},
|
|
14693
|
+
null,
|
|
14694
|
+
2
|
|
14695
|
+
)
|
|
14696
|
+
}
|
|
14697
|
+
]
|
|
14698
|
+
};
|
|
14699
|
+
}
|
|
14700
|
+
);
|
|
14701
|
+
server.tool(
|
|
14702
|
+
"add_stack_layer",
|
|
14703
|
+
"Add a branch on top of the current stack (`gh stack add`) and open a worktree+thread for it.",
|
|
14704
|
+
{
|
|
14705
|
+
ref: import_zod.z.string(),
|
|
14706
|
+
branchName: import_zod.z.string(),
|
|
14707
|
+
title: import_zod.z.string().optional()
|
|
14708
|
+
},
|
|
14709
|
+
async ({ ref, branchName, title }) => {
|
|
14710
|
+
const result = await orch.addStackLayer(ref, branchName, { title });
|
|
14711
|
+
return {
|
|
14712
|
+
content: [
|
|
14713
|
+
{
|
|
14714
|
+
type: "text",
|
|
14715
|
+
text: JSON.stringify(
|
|
14716
|
+
{
|
|
14717
|
+
id: result.thread.id,
|
|
14718
|
+
title: result.thread.title,
|
|
14719
|
+
branchName: result.thread.branchName,
|
|
14720
|
+
stackLayer: result.thread.stackLayer,
|
|
14721
|
+
worktreePath: result.thread.worktreePath,
|
|
14722
|
+
link: `sideboard://thread/${result.thread.id}`
|
|
14723
|
+
},
|
|
14724
|
+
null,
|
|
14725
|
+
2
|
|
14726
|
+
)
|
|
14727
|
+
}
|
|
14728
|
+
]
|
|
14729
|
+
};
|
|
14730
|
+
}
|
|
14731
|
+
);
|
|
14732
|
+
server.tool(
|
|
14733
|
+
"create_pr_stack",
|
|
14734
|
+
"Create a new GitHub PR stack with one Sideboard worktree per layer (bottom\u2192top branch names). Requires `gh extension install github/gh-stack`.",
|
|
14735
|
+
{
|
|
14736
|
+
repoPath: import_zod.z.string(),
|
|
14737
|
+
branches: import_zod.z.array(import_zod.z.string()).min(1),
|
|
14738
|
+
agent: import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]),
|
|
14739
|
+
base: import_zod.z.string().optional(),
|
|
14740
|
+
title: import_zod.z.string().optional()
|
|
14741
|
+
},
|
|
14742
|
+
async (args) => {
|
|
14743
|
+
const result = await orch.createPrStack({
|
|
14744
|
+
repoPath: args.repoPath,
|
|
14745
|
+
branches: args.branches,
|
|
14746
|
+
agent: args.agent,
|
|
14747
|
+
base: args.base,
|
|
14748
|
+
title: args.title
|
|
14007
14749
|
});
|
|
14008
14750
|
return {
|
|
14009
14751
|
content: [
|
|
14010
14752
|
{
|
|
14011
14753
|
type: "text",
|
|
14012
|
-
text: JSON.stringify(
|
|
14013
|
-
|
|
14014
|
-
|
|
14015
|
-
|
|
14016
|
-
|
|
14017
|
-
|
|
14018
|
-
|
|
14019
|
-
|
|
14020
|
-
|
|
14021
|
-
|
|
14022
|
-
|
|
14754
|
+
text: JSON.stringify(
|
|
14755
|
+
{
|
|
14756
|
+
stackNumber: result.stack.stackNumber,
|
|
14757
|
+
trunk: result.stack.trunk,
|
|
14758
|
+
threads: result.threads.map((t) => ({
|
|
14759
|
+
id: t.id,
|
|
14760
|
+
title: t.title,
|
|
14761
|
+
branchName: t.branchName,
|
|
14762
|
+
stackLayer: t.stackLayer,
|
|
14763
|
+
worktreePath: t.worktreePath,
|
|
14764
|
+
link: `sideboard://thread/${t.id}`
|
|
14765
|
+
}))
|
|
14766
|
+
},
|
|
14767
|
+
null,
|
|
14768
|
+
2
|
|
14769
|
+
)
|
|
14023
14770
|
}
|
|
14024
14771
|
]
|
|
14025
14772
|
};
|
|
14026
|
-
} catch (err) {
|
|
14027
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
14028
|
-
return { content: [{ type: "text", text: message }], isError: true };
|
|
14029
14773
|
}
|
|
14030
|
-
|
|
14031
|
-
|
|
14032
|
-
|
|
14033
|
-
|
|
14034
|
-
|
|
14035
|
-
|
|
14036
|
-
|
|
14037
|
-
|
|
14038
|
-
|
|
14039
|
-
|
|
14040
|
-
|
|
14041
|
-
|
|
14042
|
-
|
|
14043
|
-
|
|
14044
|
-
|
|
14045
|
-
|
|
14046
|
-
|
|
14047
|
-
|
|
14048
|
-
|
|
14049
|
-
|
|
14050
|
-
|
|
14051
|
-
|
|
14052
|
-
|
|
14053
|
-
|
|
14054
|
-
}
|
|
14055
|
-
);
|
|
14056
|
-
server.tool(
|
|
14057
|
-
"list_run_scripts",
|
|
14058
|
-
"List named run scripts available for a thread",
|
|
14059
|
-
{ ref: import_zod.z.string() },
|
|
14060
|
-
async ({ ref }) => {
|
|
14061
|
-
const scripts = orch.listThreadRunScripts(ref);
|
|
14062
|
-
const active = orch.getActiveRuns(ref);
|
|
14063
|
-
return {
|
|
14064
|
-
content: [
|
|
14065
|
-
{
|
|
14066
|
-
type: "text",
|
|
14067
|
-
text: JSON.stringify({ scripts, active }, null, 2)
|
|
14068
|
-
}
|
|
14069
|
-
]
|
|
14070
|
-
};
|
|
14071
|
-
}
|
|
14072
|
-
);
|
|
14073
|
-
server.tool(
|
|
14074
|
-
"stop_dev_script",
|
|
14075
|
-
"Stop a running script for a thread (all scripts if name omitted)",
|
|
14076
|
-
{
|
|
14077
|
-
ref: import_zod.z.string(),
|
|
14078
|
-
name: import_zod.z.string().optional()
|
|
14079
|
-
},
|
|
14080
|
-
async ({ ref, name }) => {
|
|
14081
|
-
orch.stopDev(ref, name);
|
|
14082
|
-
return { content: [{ type: "text", text: "ok" }] };
|
|
14083
|
-
}
|
|
14084
|
-
);
|
|
14085
|
-
server.tool(
|
|
14086
|
-
"run_setup",
|
|
14087
|
-
"Re-run workspace setup (Sideboard/Conductor settings or .cursor/worktrees.json)",
|
|
14088
|
-
{ ref: import_zod.z.string() },
|
|
14089
|
-
async ({ ref }) => {
|
|
14090
|
-
const result = await orch.runSetup(ref);
|
|
14091
|
-
return {
|
|
14092
|
-
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
14093
|
-
};
|
|
14094
|
-
}
|
|
14095
|
-
);
|
|
14096
|
-
server.tool(
|
|
14097
|
-
"add_workspace",
|
|
14098
|
-
"Register a git repo as a Sideboard workspace",
|
|
14099
|
-
{ repoPath: import_zod.z.string() },
|
|
14100
|
-
async ({ repoPath }) => {
|
|
14101
|
-
const ws = await orch.addWorkspace(repoPath);
|
|
14102
|
-
return { content: [{ type: "text", text: JSON.stringify(ws) }] };
|
|
14103
|
-
}
|
|
14104
|
-
);
|
|
14105
|
-
server.tool(
|
|
14106
|
-
"remove_workspace",
|
|
14107
|
-
"Unregister a Sideboard workspace (does not archive threads)",
|
|
14108
|
-
{ repoPath: import_zod.z.string() },
|
|
14109
|
-
async ({ repoPath }) => {
|
|
14110
|
-
orch.removeWorkspace(repoPath);
|
|
14111
|
-
return { content: [{ type: "text", text: "ok" }] };
|
|
14112
|
-
}
|
|
14113
|
-
);
|
|
14114
|
-
server.tool(
|
|
14115
|
-
"fanout",
|
|
14116
|
-
"Best-of-n: create one thread per agent with the same prompt (parallel attempts)",
|
|
14117
|
-
{
|
|
14118
|
-
prompt: import_zod.z.string(),
|
|
14119
|
-
agents: import_zod.z.array(import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"])),
|
|
14120
|
-
repoPath: import_zod.z.string(),
|
|
14121
|
-
sourceType: import_zod.z.enum(["branch", "pr", "ticket"]).optional(),
|
|
14122
|
-
sourceRef: import_zod.z.string().optional(),
|
|
14123
|
-
title: import_zod.z.string().optional()
|
|
14124
|
-
},
|
|
14125
|
-
async (args) => {
|
|
14126
|
-
const threads = await orch.bestOfN(args);
|
|
14127
|
-
return {
|
|
14128
|
-
content: [
|
|
14129
|
-
{
|
|
14130
|
-
type: "text",
|
|
14131
|
-
text: JSON.stringify(
|
|
14132
|
-
threads.map((t) => ({
|
|
14133
|
-
id: t.id,
|
|
14134
|
-
agent: t.agent,
|
|
14135
|
-
branchName: t.branchName,
|
|
14136
|
-
worktreePath: t.worktreePath
|
|
14137
|
-
})),
|
|
14138
|
-
null,
|
|
14139
|
-
2
|
|
14140
|
-
)
|
|
14141
|
-
}
|
|
14142
|
-
]
|
|
14143
|
-
};
|
|
14144
|
-
}
|
|
14145
|
-
);
|
|
14146
|
-
server.tool(
|
|
14147
|
-
"list_branches",
|
|
14148
|
-
"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).",
|
|
14149
|
-
{
|
|
14150
|
-
repoPath: import_zod.z.string(),
|
|
14151
|
-
unmergedOnly: import_zod.z.boolean().optional()
|
|
14152
|
-
},
|
|
14153
|
-
async ({ repoPath, unmergedOnly }) => {
|
|
14154
|
-
const root = await resolveRepoRoot(repoPath);
|
|
14155
|
-
const branches = await listBranches(root, {
|
|
14156
|
-
unmergedOnly: unmergedOnly !== false
|
|
14157
|
-
});
|
|
14158
|
-
return {
|
|
14159
|
-
content: [
|
|
14160
|
-
{
|
|
14161
|
-
type: "text",
|
|
14162
|
-
text: branches.map((b) => `${b.current ? "*" : " "} ${b.name}`).join("\n")
|
|
14163
|
-
}
|
|
14164
|
-
]
|
|
14165
|
-
};
|
|
14166
|
-
}
|
|
14167
|
-
);
|
|
14168
|
-
server.tool(
|
|
14169
|
-
"list_prs",
|
|
14170
|
-
"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.",
|
|
14171
|
-
{ repoPath: import_zod.z.string() },
|
|
14172
|
-
async ({ repoPath }) => {
|
|
14173
|
-
const root = await resolveRepoRoot(repoPath);
|
|
14174
|
-
const prs = await listPrs(root);
|
|
14175
|
-
return {
|
|
14176
|
-
content: [
|
|
14177
|
-
{
|
|
14178
|
-
type: "text",
|
|
14179
|
-
text: prs.map(
|
|
14180
|
-
(p) => `#${p.number} ${p.title} (${p.headRefName})${p.isCrossRepository ? " [fork]" : ""}`
|
|
14181
|
-
).join("\n")
|
|
14182
|
-
}
|
|
14183
|
-
]
|
|
14184
|
-
};
|
|
14185
|
-
}
|
|
14186
|
-
);
|
|
14187
|
-
server.tool(
|
|
14188
|
-
"get_pr_stack",
|
|
14189
|
-
"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.",
|
|
14190
|
-
{ ref: import_zod.z.string() },
|
|
14191
|
-
async ({ ref }) => {
|
|
14192
|
-
const stack = await orch.getPrStack(ref);
|
|
14193
|
-
return {
|
|
14194
|
-
content: [{ type: "text", text: JSON.stringify(stack, null, 2) }]
|
|
14195
|
-
};
|
|
14196
|
-
}
|
|
14197
|
-
);
|
|
14198
|
-
server.tool(
|
|
14199
|
-
"open_pr_stack_layers",
|
|
14200
|
-
"Materialize one worktree+thread per stack layer (or a single 1-based layer). Pass a thread ref already on the stack.",
|
|
14201
|
-
{
|
|
14202
|
-
ref: import_zod.z.string(),
|
|
14203
|
-
layer: import_zod.z.number().int().positive().optional()
|
|
14204
|
-
},
|
|
14205
|
-
async ({ ref, layer }) => {
|
|
14206
|
-
const result = await orch.openPrStackLayers(ref, { layer });
|
|
14207
|
-
return {
|
|
14208
|
-
content: [
|
|
14209
|
-
{
|
|
14210
|
-
type: "text",
|
|
14211
|
-
text: JSON.stringify(
|
|
14212
|
-
{
|
|
14213
|
-
stackNumber: result.stack.stackNumber,
|
|
14214
|
-
trunk: result.stack.trunk,
|
|
14215
|
-
threads: result.threads.map((t) => ({
|
|
14216
|
-
id: t.id,
|
|
14217
|
-
title: t.title,
|
|
14218
|
-
branchName: t.branchName,
|
|
14219
|
-
stackLayer: t.stackLayer,
|
|
14220
|
-
worktreePath: t.worktreePath,
|
|
14221
|
-
prUrl: t.prUrl,
|
|
14222
|
-
link: `sideboard://thread/${t.id}`
|
|
14223
|
-
}))
|
|
14224
|
-
},
|
|
14225
|
-
null,
|
|
14226
|
-
2
|
|
14227
|
-
)
|
|
14228
|
-
}
|
|
14229
|
-
]
|
|
14230
|
-
};
|
|
14231
|
-
}
|
|
14232
|
-
);
|
|
14233
|
-
server.tool(
|
|
14234
|
-
"add_stack_layer",
|
|
14235
|
-
"Add a branch on top of the current stack (`gh stack add`) and open a worktree+thread for it.",
|
|
14236
|
-
{
|
|
14237
|
-
ref: import_zod.z.string(),
|
|
14238
|
-
branchName: import_zod.z.string(),
|
|
14239
|
-
title: import_zod.z.string().optional()
|
|
14240
|
-
},
|
|
14241
|
-
async ({ ref, branchName, title }) => {
|
|
14242
|
-
const result = await orch.addStackLayer(ref, branchName, { title });
|
|
14243
|
-
return {
|
|
14244
|
-
content: [
|
|
14245
|
-
{
|
|
14246
|
-
type: "text",
|
|
14247
|
-
text: JSON.stringify(
|
|
14248
|
-
{
|
|
14249
|
-
id: result.thread.id,
|
|
14250
|
-
title: result.thread.title,
|
|
14251
|
-
branchName: result.thread.branchName,
|
|
14252
|
-
stackLayer: result.thread.stackLayer,
|
|
14253
|
-
worktreePath: result.thread.worktreePath,
|
|
14254
|
-
link: `sideboard://thread/${result.thread.id}`
|
|
14255
|
-
},
|
|
14256
|
-
null,
|
|
14257
|
-
2
|
|
14258
|
-
)
|
|
14259
|
-
}
|
|
14260
|
-
]
|
|
14261
|
-
};
|
|
14262
|
-
}
|
|
14263
|
-
);
|
|
14264
|
-
server.tool(
|
|
14265
|
-
"create_pr_stack",
|
|
14266
|
-
"Create a new GitHub PR stack with one Sideboard worktree per layer (bottom\u2192top branch names). Requires `gh extension install github/gh-stack`.",
|
|
14267
|
-
{
|
|
14268
|
-
repoPath: import_zod.z.string(),
|
|
14269
|
-
branches: import_zod.z.array(import_zod.z.string()).min(1),
|
|
14270
|
-
agent: import_zod.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]),
|
|
14271
|
-
base: import_zod.z.string().optional(),
|
|
14272
|
-
title: import_zod.z.string().optional()
|
|
14273
|
-
},
|
|
14274
|
-
async (args) => {
|
|
14275
|
-
const result = await orch.createPrStack({
|
|
14276
|
-
repoPath: args.repoPath,
|
|
14277
|
-
branches: args.branches,
|
|
14278
|
-
agent: args.agent,
|
|
14279
|
-
base: args.base,
|
|
14280
|
-
title: args.title
|
|
14281
|
-
});
|
|
14282
|
-
return {
|
|
14283
|
-
content: [
|
|
14284
|
-
{
|
|
14285
|
-
type: "text",
|
|
14286
|
-
text: JSON.stringify(
|
|
14287
|
-
{
|
|
14288
|
-
stackNumber: result.stack.stackNumber,
|
|
14289
|
-
trunk: result.stack.trunk,
|
|
14290
|
-
threads: result.threads.map((t) => ({
|
|
14291
|
-
id: t.id,
|
|
14292
|
-
title: t.title,
|
|
14293
|
-
branchName: t.branchName,
|
|
14294
|
-
stackLayer: t.stackLayer,
|
|
14295
|
-
worktreePath: t.worktreePath,
|
|
14296
|
-
link: `sideboard://thread/${t.id}`
|
|
14297
|
-
}))
|
|
14298
|
-
},
|
|
14299
|
-
null,
|
|
14300
|
-
2
|
|
14301
|
-
)
|
|
14302
|
-
}
|
|
14303
|
-
]
|
|
14304
|
-
};
|
|
14305
|
-
}
|
|
14306
|
-
);
|
|
14307
|
-
server.tool(
|
|
14308
|
-
"list_issues",
|
|
14309
|
-
"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.",
|
|
14310
|
-
{ repoPath: import_zod.z.string() },
|
|
14311
|
-
async ({ repoPath }) => {
|
|
14312
|
-
const root = await resolveRepoRoot(repoPath);
|
|
14313
|
-
const result = await listIssues(root);
|
|
14314
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
14315
|
-
}
|
|
14316
|
-
);
|
|
14317
|
-
server.tool(
|
|
14318
|
-
"list_linear_issues",
|
|
14319
|
-
"Deprecated: prefer list_issues. Lists assigned Linear issues via the chosen agent MCP connector",
|
|
14320
|
-
{
|
|
14321
|
-
agent: import_zod.z.enum(["claude", "codex", "opencode"]),
|
|
14322
|
-
repoPath: import_zod.z.string()
|
|
14323
|
-
},
|
|
14324
|
-
async ({ agent, repoPath }) => {
|
|
14325
|
-
const issues = await listLinearIssues(agent, repoPath);
|
|
14326
|
-
return { content: [{ type: "text", text: JSON.stringify(issues, null, 2) }] };
|
|
14327
|
-
}
|
|
14328
|
-
);
|
|
14774
|
+
);
|
|
14775
|
+
server.tool(
|
|
14776
|
+
"list_issues",
|
|
14777
|
+
"List issues from Sideboard Account connections (Linear API or GitHub Issues; Linear\u2192GitHub fallback when Linear is not connected). Pass repoPath from list_workspaces \u2014 GitHub Issues are scoped to that repo. Then create_thread with sourceType=ticket.",
|
|
14778
|
+
{ repoPath: import_zod.z.string() },
|
|
14779
|
+
async ({ repoPath }) => {
|
|
14780
|
+
const root = await resolveRepoRoot(repoPath);
|
|
14781
|
+
const result = await listIssues(root);
|
|
14782
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
14783
|
+
}
|
|
14784
|
+
);
|
|
14785
|
+
server.tool(
|
|
14786
|
+
"list_linear_issues",
|
|
14787
|
+
"Deprecated: prefer list_issues. Lists assigned Linear issues via the chosen agent MCP connector",
|
|
14788
|
+
{
|
|
14789
|
+
agent: import_zod.z.enum(["claude", "codex", "opencode"]),
|
|
14790
|
+
repoPath: import_zod.z.string()
|
|
14791
|
+
},
|
|
14792
|
+
async ({ agent, repoPath }) => {
|
|
14793
|
+
const issues = await listLinearIssues(agent, repoPath);
|
|
14794
|
+
return { content: [{ type: "text", text: JSON.stringify(issues, null, 2) }] };
|
|
14795
|
+
}
|
|
14796
|
+
);
|
|
14797
|
+
}
|
|
14329
14798
|
const transport = new import_stdio.StdioServerTransport();
|
|
14330
14799
|
await server.connect(transport);
|
|
14331
14800
|
}
|
|
14332
14801
|
|
|
14333
14802
|
// src/index.ts
|
|
14803
|
+
init_profile();
|
|
14334
14804
|
init_config();
|
|
14335
14805
|
|
|
14336
14806
|
// src/brightsy/api.ts
|
|
@@ -14707,6 +15177,7 @@ init_injected_mcp();
|
|
|
14707
15177
|
REVIEW_REQUEST_PREFILL,
|
|
14708
15178
|
SIDEBOARD_FORCE_STOP,
|
|
14709
15179
|
SIDEBOARD_MCP_ALLOWED_TOOLS,
|
|
15180
|
+
SIDEBOARD_MCP_PROFILE_ENV,
|
|
14710
15181
|
THINKING_EFFORTS,
|
|
14711
15182
|
addPrStackLayer,
|
|
14712
15183
|
addStackLayerFromThread,
|
|
@@ -14729,6 +15200,7 @@ init_injected_mcp();
|
|
|
14729
15200
|
attachmentsFromBuffers,
|
|
14730
15201
|
attachmentsFromWorktreePaths,
|
|
14731
15202
|
attachmentsGitignoreBody,
|
|
15203
|
+
autoArchiveOnMergeEnabled,
|
|
14732
15204
|
autoCleanupOrphansEnabled,
|
|
14733
15205
|
autoRenameBranchEnabled,
|
|
14734
15206
|
autoRunAfterSetupEnabled,
|
|
@@ -14737,6 +15209,7 @@ init_injected_mcp();
|
|
|
14737
15209
|
brightsyCloudConnectAgent,
|
|
14738
15210
|
brightsyCloudConnectEnabled,
|
|
14739
15211
|
brightsyConfigPath,
|
|
15212
|
+
brightsyInjectWorktreeMcpEnabled,
|
|
14740
15213
|
brightsyMcpAllowedTools,
|
|
14741
15214
|
brightsyMcpServerName,
|
|
14742
15215
|
buildCachedUserContent,
|
|
@@ -14788,7 +15261,9 @@ init_injected_mcp();
|
|
|
14788
15261
|
detectLocalMergeConflicts,
|
|
14789
15262
|
disconnectBrightsyTeam,
|
|
14790
15263
|
discoverSkills,
|
|
15264
|
+
dropCachedPrefixOnResume,
|
|
14791
15265
|
encodeBrightsyTarget,
|
|
15266
|
+
enrichPathWithNpmGlobalBin,
|
|
14792
15267
|
enrichWorkspacesWithGithub,
|
|
14793
15268
|
ensureAgentPath,
|
|
14794
15269
|
ensureCloudCoordinator,
|
|
@@ -14826,6 +15301,7 @@ init_injected_mcp();
|
|
|
14826
15301
|
formatTranscriptMarkdown,
|
|
14827
15302
|
formatWorkspaceInventory,
|
|
14828
15303
|
formatWorktreeDirective,
|
|
15304
|
+
formatWorktreeReminder,
|
|
14829
15305
|
getAdapter,
|
|
14830
15306
|
getAgentSetupInfo,
|
|
14831
15307
|
getBrightsySession,
|
|
@@ -14952,7 +15428,10 @@ init_injected_mcp();
|
|
|
14952
15428
|
pastedTextStats,
|
|
14953
15429
|
permissionMode,
|
|
14954
15430
|
planFileAbs,
|
|
15431
|
+
posixShellSingleQuote,
|
|
15432
|
+
prepareTerminalCommand,
|
|
14955
15433
|
previewLand,
|
|
15434
|
+
promptMentionsBrightsy,
|
|
14956
15435
|
pushBranch,
|
|
14957
15436
|
readExistingReviewRequestFile,
|
|
14958
15437
|
readPlanFile,
|
|
@@ -14968,7 +15447,9 @@ init_injected_mcp();
|
|
|
14968
15447
|
requestReview,
|
|
14969
15448
|
requireAgent,
|
|
14970
15449
|
resetGhStackDetectCache,
|
|
15450
|
+
resolveAgentExecutable,
|
|
14971
15451
|
resolveClaudeExecutable,
|
|
15452
|
+
resolveCommandBinarySync,
|
|
14972
15453
|
resolveConductorCursorAgentId,
|
|
14973
15454
|
resolveCursorModelId,
|
|
14974
15455
|
resolveDefaultBranch,
|
|
@@ -14977,6 +15458,7 @@ init_injected_mcp();
|
|
|
14977
15458
|
resolveFilesToCopy,
|
|
14978
15459
|
resolveGhAuthToken,
|
|
14979
15460
|
resolveGithubRepoSlug,
|
|
15461
|
+
resolveLoginCommand,
|
|
14980
15462
|
resolveNewThreadOptions,
|
|
14981
15463
|
resolvePlanMarkdown,
|
|
14982
15464
|
resolvePrSelector,
|
|
@@ -14998,9 +15480,11 @@ init_injected_mcp();
|
|
|
14998
15480
|
settingsSourceLabel,
|
|
14999
15481
|
shouldAttachPastedText,
|
|
15000
15482
|
shouldCompactContext,
|
|
15483
|
+
shouldInjectBrightsyMcp,
|
|
15001
15484
|
shouldRefreshReviewRequestTemplate,
|
|
15002
15485
|
shouldRunWorktreeCleanup,
|
|
15003
15486
|
sideboardHomeDir,
|
|
15487
|
+
sideboardMcpProfile,
|
|
15004
15488
|
sideboardReposDir,
|
|
15005
15489
|
sideboardWorkspacesDir,
|
|
15006
15490
|
slugify,
|
|
@@ -15028,6 +15512,7 @@ init_injected_mcp();
|
|
|
15028
15512
|
threadDisplayLabel,
|
|
15029
15513
|
threadFilePath,
|
|
15030
15514
|
threadLockPath,
|
|
15515
|
+
threadRequestsBrightsyMcp,
|
|
15031
15516
|
threadsDir,
|
|
15032
15517
|
threadsSharingWorktree,
|
|
15033
15518
|
toolDescription,
|
|
@@ -15035,14 +15520,18 @@ init_injected_mcp();
|
|
|
15035
15520
|
toolFilePath,
|
|
15036
15521
|
totalTokens,
|
|
15037
15522
|
updateAdvancedSettings,
|
|
15523
|
+
updateAgentExecutable,
|
|
15038
15524
|
updateAppEnvironment,
|
|
15039
15525
|
updateBrightsySettings,
|
|
15040
15526
|
updateClaudeSettings,
|
|
15527
|
+
updateCodexSettings,
|
|
15041
15528
|
updateDefaultsSettings,
|
|
15042
15529
|
updateIntegrationsSettings,
|
|
15530
|
+
updateOpencodeSettings,
|
|
15043
15531
|
updateThread,
|
|
15044
15532
|
validateLinearApiKey,
|
|
15045
15533
|
withAgentInstructions,
|
|
15534
|
+
withExportedPath,
|
|
15046
15535
|
withThreadLock,
|
|
15047
15536
|
workspaceSettingsSourceLabel,
|
|
15048
15537
|
worktreeCleanupSettings,
|