@sideboard-ai/core 0.1.216 → 0.1.218
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/{abletime-QGGYL2G4.js → abletime-BF253OZT.js} +5 -4
- package/dist/{abletime-GDZLZRMY.js → abletime-D6773P33.js} +5 -5
- package/dist/{abletime-oauth-F335TWKY.js → abletime-oauth-H4672PRH.js} +4 -3
- package/dist/{abletime-oauth-3X3BAPTF.js → abletime-oauth-KQPVVBKA.js} +4 -4
- package/dist/{abletime-rest-PLJVY3H3.js → abletime-rest-DAFPXZ7H.js} +4 -4
- package/dist/{abletime-rest-LAGTPAJL.js → abletime-rest-OPEVV3XC.js} +4 -3
- package/dist/agents/cursor-runner.js +5 -5
- package/dist/{agents-WBDDLRBY.js → agents-NWJ7DFJD.js} +8 -7
- package/dist/{agents-HETHRRZJ.js → agents-YABJUV3V.js} +9 -9
- package/dist/{app-settings-XCRNCEEE.js → app-settings-5RQMQKSB.js} +2 -1
- package/dist/{app-settings-2TN3WLZV.js → app-settings-V2BBCX2H.js} +2 -2
- package/dist/{chunk-MN6YUD4O.js → chunk-3NWUHXU3.js} +3 -3
- package/dist/{chunk-G4TANQC3.js → chunk-646I442S.js} +5 -5
- package/dist/{chunk-FNQNJOHY.js → chunk-ABOBTSO6.js} +4 -1
- package/dist/{chunk-YVE4PXCJ.js → chunk-CLI5DVU4.js} +2 -2
- package/dist/{chunk-7MTVRNP4.js → chunk-FSIJGLSV.js} +1173 -1186
- package/dist/{chunk-LS6TSOCE.js → chunk-HSYE5ID6.js} +5 -5
- package/dist/{chunk-UFHNSFAS.js → chunk-HVUVQXZ2.js} +5 -1
- package/dist/{chunk-SALM35KD.js → chunk-IILG7DPX.js} +5 -5
- package/dist/{chunk-D2IKXMF3.js → chunk-JWBPSD7Q.js} +453 -289
- package/dist/{chunk-NI243N27.js → chunk-KTZESHYH.js} +15 -7
- package/dist/{chunk-KFD2OXCE.js → chunk-MW57SKKR.js} +19 -6
- package/dist/{chunk-XYKVRRC2.js → chunk-NFWPDEN4.js} +15 -7
- package/dist/{chunk-FNGXKY5W.js → chunk-OPYBLX4V.js} +19 -6
- package/dist/{chunk-QQKDGPUI.js → chunk-PO4M4JAJ.js} +1 -1
- package/dist/{chunk-2M5B7YNY.js → chunk-RRW2XWAY.js} +2 -2
- package/dist/{chunk-REZRGCKV.js → chunk-SOGGKYFV.js} +3 -3
- package/dist/{chunk-C32SBNA3.js → chunk-SRFFIFW6.js} +457 -294
- package/dist/{chunk-3OHR73VK.js → chunk-SVXIJ2IC.js} +1 -1
- package/dist/{chunk-SYFVUF2C.js → chunk-SZJZEFTY.js} +1 -1
- package/dist/{chunk-42IULNIY.js → chunk-THLVCXLF.js} +3 -3
- package/dist/{chunk-JZHRZ3DR.js → chunk-TQBUXKIB.js} +5 -5
- package/dist/chunk-WWUABK6B.js +56 -0
- package/dist/{chunk-DFTVZEZY.js → chunk-XRHTRXZN.js} +1051 -1050
- package/dist/{chunk-BTC2D6LS.js → chunk-Y5JES2VV.js} +3 -51
- package/dist/{connected-teams-WK47ATT7.js → connected-teams-LX5DLL2I.js} +3 -2
- package/dist/{connected-teams-PU4AMFNA.js → connected-teams-PQETXUWV.js} +3 -2
- package/dist/{coordinator-prompt-FQX6ALAI.js → coordinator-prompt-5V7GEPBG.js} +6 -6
- package/dist/{coordinator-prompt-LE2GQZ2X.js → coordinator-prompt-J4QSNTKE.js} +6 -5
- package/dist/{global-workspace-6P236KKG.js → global-workspace-4TEMLESD.js} +6 -6
- package/dist/{global-workspace-KT3FRHZL.js → global-workspace-XPTFHMKL.js} +6 -5
- package/dist/index.cjs +1027 -821
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +22 -18
- package/dist/mcp/run-stdio.cjs +1838 -1651
- package/dist/mcp/run-stdio.js +16 -14
- package/dist/{orchestrator-WVZPTHBV.js → orchestrator-HKW3VLGX.js} +10 -10
- package/dist/{orchestrator-MI7A5DQZ.js → orchestrator-SWRTYFHX.js} +9 -8
- package/dist/{run-EBWL2Q4N.js → run-QDZCTP4Y.js} +2 -1
- package/dist/{run-CAGKZLHA.js → run-UEQM4JMZ.js} +2 -1
- package/dist/{workspaces-KM7KTLVO.js → workspaces-2HQP654Q.js} +6 -5
- package/dist/{workspaces-R5LJCJRB.js → workspaces-BCBBMMXB.js} +6 -6
- package/dist/{worktree-MDMTCAHX.js → worktree-7V67XTEO.js} +5 -5
- package/dist/{worktree-VXRI7LYM.js → worktree-I573UOPD.js} +5 -4
- package/dist/{worktree-exclude-N5X5I422.js → worktree-exclude-K7QK4RI5.js} +3 -2
- package/dist/{worktree-exclude-X54WSOXM.js → worktree-exclude-L32WEBX6.js} +3 -2
- package/package.json +1 -1
- package/dist/{chunk-L5CIEBLR.js → chunk-EWHJNJHV.js} +3 -3
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
isOrchestratorThread
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-MW57SKKR.js";
|
|
6
6
|
import {
|
|
7
7
|
applyConnectedTeamToCli,
|
|
8
8
|
brightsyMcpServerName,
|
|
9
9
|
ensureCliTeamTracked,
|
|
10
10
|
ensureConnectedBrightsyTeamTokens
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-SVXIJ2IC.js";
|
|
12
12
|
import {
|
|
13
13
|
loadBrightsyConfig
|
|
14
14
|
} from "./chunk-Y4MIXGPA.js";
|
|
@@ -20,29 +20,31 @@ import {
|
|
|
20
20
|
mergeAgentGitAuthEnv,
|
|
21
21
|
resolveAgentGitAuthEnv,
|
|
22
22
|
resolveCodexGitWritableRoots
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-NFWPDEN4.js";
|
|
24
24
|
import {
|
|
25
25
|
enrichPathWithNpmGlobalBin,
|
|
26
26
|
isConductorBundledCli,
|
|
27
27
|
resolveCommandBinarySync,
|
|
28
28
|
run,
|
|
29
29
|
withExportedPath
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-ABOBTSO6.js";
|
|
31
31
|
import {
|
|
32
32
|
claudeChromeEnabled,
|
|
33
33
|
fromInclusiveInputUsage,
|
|
34
34
|
isAbleTimeConnected,
|
|
35
|
-
isElectronLikeCommand,
|
|
36
35
|
isLinearConnected,
|
|
37
36
|
loadAppSettings,
|
|
38
37
|
resolveAgentExecutable,
|
|
39
|
-
resolveClaudeExecutable
|
|
40
|
-
|
|
41
|
-
wrapElectronAsNodeLaunch
|
|
42
|
-
} from "./chunk-BTC2D6LS.js";
|
|
38
|
+
resolveClaudeExecutable
|
|
39
|
+
} from "./chunk-Y5JES2VV.js";
|
|
43
40
|
import {
|
|
44
41
|
appDataDir
|
|
45
42
|
} from "./chunk-EQNRWDLN.js";
|
|
43
|
+
import {
|
|
44
|
+
isElectronLikeCommand,
|
|
45
|
+
unwrapStrippedElectronLaunch,
|
|
46
|
+
wrapElectronAsNodeLaunch
|
|
47
|
+
} from "./chunk-WWUABK6B.js";
|
|
46
48
|
|
|
47
49
|
// src/agents/brightsy.ts
|
|
48
50
|
import { existsSync } from "fs";
|
|
@@ -800,27 +802,9 @@ var brightsyAdapter = {
|
|
|
800
802
|
};
|
|
801
803
|
|
|
802
804
|
// src/agents/claude.ts
|
|
803
|
-
import { existsSync as
|
|
805
|
+
import { existsSync as existsSync8 } from "fs";
|
|
804
806
|
|
|
805
807
|
// src/agents/claude-mcp.ts
|
|
806
|
-
function parseMcpList(text) {
|
|
807
|
-
const servers = [];
|
|
808
|
-
const seen = /* @__PURE__ */ new Set();
|
|
809
|
-
for (const raw of text.split("\n")) {
|
|
810
|
-
const line = raw.trim();
|
|
811
|
-
if (!line || /^Checking MCP/i.test(line)) continue;
|
|
812
|
-
const m = line.match(/^(.+?):\s+\S+/);
|
|
813
|
-
if (!m) continue;
|
|
814
|
-
const name = m[1].trim();
|
|
815
|
-
if (!name || seen.has(name)) continue;
|
|
816
|
-
const needsAuth = /Needs authentication/i.test(line);
|
|
817
|
-
const connected = !needsAuth && /Connected/i.test(line);
|
|
818
|
-
if (!needsAuth && !connected) continue;
|
|
819
|
-
seen.add(name);
|
|
820
|
-
servers.push({ name, connected, needsAuth });
|
|
821
|
-
}
|
|
822
|
-
return servers;
|
|
823
|
-
}
|
|
824
808
|
function sanitizeMcpServerName(name) {
|
|
825
809
|
return name.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
826
810
|
}
|
|
@@ -835,1169 +819,1291 @@ function mcpAllowTools(servers) {
|
|
|
835
819
|
}
|
|
836
820
|
return out;
|
|
837
821
|
}
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
return input;
|
|
843
|
-
}
|
|
844
|
-
return void 0;
|
|
822
|
+
function mcpAllowToolsFromNames(names) {
|
|
823
|
+
return mcpAllowTools(
|
|
824
|
+
[...names].map((name) => name.trim()).filter(Boolean).map((name) => ({ name, connected: true, needsAuth: false }))
|
|
825
|
+
);
|
|
845
826
|
}
|
|
846
|
-
|
|
847
|
-
|
|
827
|
+
|
|
828
|
+
// src/agents/orch-mcp-isolation.ts
|
|
829
|
+
import { existsSync as existsSync7, readFileSync as readFileSync3 } from "fs";
|
|
830
|
+
import { homedir as homedir3 } from "os";
|
|
831
|
+
import { join as join6 } from "path";
|
|
832
|
+
import { parse as parseToml } from "smol-toml";
|
|
833
|
+
|
|
834
|
+
// src/agents/user-mcp-config.ts
|
|
835
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
836
|
+
import { homedir as homedir2 } from "os";
|
|
837
|
+
import { dirname as dirname3, join as join5 } from "path";
|
|
838
|
+
|
|
839
|
+
// src/agents/injected-mcp.ts
|
|
840
|
+
import { existsSync as existsSync5, mkdtempSync, writeFileSync as writeFileSync2 } from "fs";
|
|
841
|
+
import { createRequire } from "module";
|
|
842
|
+
import { tmpdir } from "os";
|
|
843
|
+
import { dirname as dirname2, join as join4 } from "path";
|
|
844
|
+
import { fileURLToPath } from "url";
|
|
845
|
+
|
|
846
|
+
// src/mcp/profile.ts
|
|
847
|
+
var SIDEBOARD_MCP_PROFILE_ENV = "SIDEBOARD_MCP_PROFILE";
|
|
848
|
+
function sideboardMcpProfile(env = process.env) {
|
|
849
|
+
return env[SIDEBOARD_MCP_PROFILE_ENV]?.trim().toLowerCase() === "worktree" ? "worktree" : "orchestration";
|
|
848
850
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
851
|
+
|
|
852
|
+
// src/agents/node-launch.ts
|
|
853
|
+
import { existsSync as existsSync4, readdirSync, realpathSync } from "fs";
|
|
854
|
+
import { homedir } from "os";
|
|
855
|
+
import { join as join3 } from "path";
|
|
856
|
+
|
|
857
|
+
// src/http/system-ca.ts
|
|
858
|
+
import { spawnSync } from "child_process";
|
|
859
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync, statSync, writeFileSync } from "fs";
|
|
860
|
+
import { dirname, join } from "path";
|
|
861
|
+
import tls from "tls";
|
|
862
|
+
var NODE_USE_SYSTEM_CA = "NODE_USE_SYSTEM_CA";
|
|
863
|
+
var NODE_EXTRA_CA_CERTS = "NODE_EXTRA_CA_CERTS";
|
|
864
|
+
var BUNDLE_NAME = "system-ca.pem";
|
|
865
|
+
var BUNDLE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
866
|
+
var LINUX_CA_FILES = [
|
|
867
|
+
"/etc/ssl/certs/ca-certificates.crt",
|
|
868
|
+
"/etc/pki/tls/certs/ca-bundle.crt",
|
|
869
|
+
"/etc/ssl/ca-bundle.pem",
|
|
870
|
+
"/etc/ssl/cert.pem"
|
|
871
|
+
];
|
|
872
|
+
var PEM_CERT_RE = /-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g;
|
|
873
|
+
function splitPemCertificates(pem) {
|
|
874
|
+
return pem.match(PEM_CERT_RE) ?? [];
|
|
854
875
|
}
|
|
855
|
-
function
|
|
856
|
-
if (!input) return void 0;
|
|
857
|
-
const command = str(input.command) ?? str(input.cmd);
|
|
858
|
-
if (command) return clipChatLine(command);
|
|
859
|
-
const pattern = str(input.pattern) ?? str(input.glob) ?? str(input.glob_pattern);
|
|
860
|
-
const isSearch = /grep|glob|search|ripgrep|findfiles|semsearch/i.test(name);
|
|
861
|
-
if (isSearch && pattern) {
|
|
862
|
-
return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
|
|
863
|
-
}
|
|
864
|
-
const path = str(input.file_path) ?? str(input.path) ?? str(input.filePath) ?? str(input.filename);
|
|
865
|
-
if (path) return path;
|
|
866
|
-
if (pattern) return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
|
|
867
|
-
const query = str(input.query) ?? str(input.prompt);
|
|
868
|
-
if (query) return query.length > 80 ? `${query.slice(0, 77)}\u2026` : query;
|
|
876
|
+
function readExistingFile(path) {
|
|
869
877
|
try {
|
|
870
|
-
|
|
871
|
-
return raw.length > 80 ? `${raw.slice(0, 77)}\u2026` : raw;
|
|
878
|
+
return existsSync2(path) ? readFileSync(path, "utf8") : "";
|
|
872
879
|
} catch {
|
|
873
|
-
return
|
|
880
|
+
return "";
|
|
874
881
|
}
|
|
875
882
|
}
|
|
876
|
-
function
|
|
877
|
-
const
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
}
|
|
882
|
-
if (
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
883
|
+
function darwinKeychainPem(spawn) {
|
|
884
|
+
const result = spawn("/usr/bin/security", ["find-certificate", "-a", "-p"], {
|
|
885
|
+
encoding: "utf8",
|
|
886
|
+
maxBuffer: 32 * 1024 * 1024,
|
|
887
|
+
timeout: 15e3
|
|
888
|
+
});
|
|
889
|
+
if (result.status !== 0) return "";
|
|
890
|
+
return typeof result.stdout === "string" ? result.stdout : "";
|
|
891
|
+
}
|
|
892
|
+
function linuxSystemCaPem() {
|
|
893
|
+
for (const path of LINUX_CA_FILES) {
|
|
894
|
+
const pem = readExistingFile(path);
|
|
895
|
+
if (splitPemCertificates(pem).length > 0) return pem;
|
|
887
896
|
}
|
|
888
|
-
|
|
889
|
-
|
|
897
|
+
return "";
|
|
898
|
+
}
|
|
899
|
+
function collectSystemCaPem(io = {}) {
|
|
900
|
+
const platform = io.platform ?? process.platform;
|
|
901
|
+
if (platform === "darwin") {
|
|
902
|
+
return darwinKeychainPem(io.spawn ?? spawnSync);
|
|
890
903
|
}
|
|
891
|
-
if (
|
|
892
|
-
return
|
|
904
|
+
if (platform === "linux") {
|
|
905
|
+
return linuxSystemCaPem();
|
|
893
906
|
}
|
|
894
|
-
|
|
895
|
-
|
|
907
|
+
return "";
|
|
908
|
+
}
|
|
909
|
+
function systemCaBundlePath(io = {}) {
|
|
910
|
+
return join((io.appData ?? appDataDir)(), BUNDLE_NAME);
|
|
911
|
+
}
|
|
912
|
+
function bundleIsFresh(path, now) {
|
|
913
|
+
try {
|
|
914
|
+
if (!existsSync2(path)) return false;
|
|
915
|
+
if (splitPemCertificates(readFileSync(path, "utf8")).length === 0) return false;
|
|
916
|
+
return now - statSync(path).mtimeMs < BUNDLE_MAX_AGE_MS;
|
|
917
|
+
} catch {
|
|
918
|
+
return false;
|
|
896
919
|
}
|
|
897
|
-
|
|
898
|
-
|
|
920
|
+
}
|
|
921
|
+
function materializeSystemCaBundle(io = {}) {
|
|
922
|
+
const inherited = process.env.NODE_EXTRA_CA_CERTS?.trim();
|
|
923
|
+
if (inherited && splitPemCertificates(readExistingFile(inherited)).length > 0) {
|
|
924
|
+
return inherited;
|
|
899
925
|
}
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
const
|
|
903
|
-
|
|
904
|
-
if (/^spawn_agent$/i.test(name)) {
|
|
905
|
-
return str(input?.prompt) ?? desc ?? "Subagent";
|
|
906
|
-
}
|
|
907
|
-
if (/connectedAgentRequest/i.test(name)) {
|
|
908
|
-
return str(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
|
|
926
|
+
const platform = io.platform ?? process.platform;
|
|
927
|
+
if (platform === "linux") {
|
|
928
|
+
for (const path of LINUX_CA_FILES) {
|
|
929
|
+
if (splitPemCertificates(readExistingFile(path)).length > 0) return path;
|
|
909
930
|
}
|
|
910
|
-
if (desc && kind) return `${kind}: ${desc}${subagentLiveSuffix(input)}`;
|
|
911
|
-
if (desc) return `${desc}${subagentLiveSuffix(input)}`;
|
|
912
|
-
return `Subagent${subagentLiveSuffix(input)}`;
|
|
913
|
-
}
|
|
914
|
-
if (/^(create|update)_artifact$/i.test(name.replace(/^mcp__[^_]+__/, ""))) {
|
|
915
|
-
return str(input?.title) ? `Artifact ${str(input?.title)}` : "Artifact";
|
|
916
|
-
}
|
|
917
|
-
if (!input) return n;
|
|
918
|
-
if (/bash|shell|terminal/i.test(name) && str(input.command)) {
|
|
919
|
-
const cmd = str(input.command);
|
|
920
|
-
if (/git\s+fetch/i.test(cmd)) return "Fetch latest from origin and check status";
|
|
921
|
-
if (/git\s+status/i.test(cmd)) return "Check git status";
|
|
922
|
-
if (/git\s+log/i.test(cmd)) return "Inspect recent commits";
|
|
923
|
-
if (/git\s+branch/i.test(cmd)) return "List branches";
|
|
924
|
-
if (/grep|rg\b/i.test(cmd)) return "Search repository";
|
|
925
|
-
return "Run shell command";
|
|
926
|
-
}
|
|
927
|
-
if (/edit|write|apply/i.test(name)) {
|
|
928
|
-
const path = str(input.file_path) ?? str(input.path);
|
|
929
|
-
return path ? `Edit ${path.split("/").pop()}` : "Edit file";
|
|
930
|
-
}
|
|
931
|
-
if (/read/i.test(name)) {
|
|
932
|
-
const path = str(input.file_path) ?? str(input.path);
|
|
933
|
-
return path ? `Read ${path.split("/").pop()}` : "Read file";
|
|
934
|
-
}
|
|
935
|
-
if (/grep/i.test(name)) return "Search files";
|
|
936
|
-
if (/glob/i.test(name)) return "Find files";
|
|
937
|
-
const compact = n.replace(/[_-]/g, "");
|
|
938
|
-
if (/^taskoutput$/i.test(compact)) {
|
|
939
|
-
return str(input.task_id) ? `Wait for ${str(input.task_id)}` : "Wait for background task";
|
|
940
931
|
}
|
|
941
|
-
|
|
942
|
-
|
|
932
|
+
const dest = systemCaBundlePath(io);
|
|
933
|
+
const now = (io.now ?? Date.now)();
|
|
934
|
+
if (bundleIsFresh(dest, now)) return dest;
|
|
935
|
+
const pem = collectSystemCaPem(io);
|
|
936
|
+
if (splitPemCertificates(pem).length === 0) {
|
|
937
|
+
return existsSync2(dest) && splitPemCertificates(readExistingFile(dest)).length > 0 ? dest : void 0;
|
|
943
938
|
}
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
939
|
+
try {
|
|
940
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
941
|
+
writeFileSync(dest, pem.endsWith("\n") ? pem : `${pem}
|
|
942
|
+
`, { mode: 384 });
|
|
943
|
+
return dest;
|
|
944
|
+
} catch {
|
|
945
|
+
return void 0;
|
|
947
946
|
}
|
|
948
|
-
return n;
|
|
949
947
|
}
|
|
950
|
-
function
|
|
951
|
-
if (!
|
|
952
|
-
|
|
953
|
-
const status = str(input.live_status);
|
|
954
|
-
if (status && !/^runn(ing)?$|^working$/i.test(status)) bits.push(status);
|
|
955
|
-
if (typeof input.live_tool_uses === "number") bits.push(`${input.live_tool_uses} tools`);
|
|
956
|
-
if (typeof input.live_duration_ms === "number") {
|
|
957
|
-
bits.push(`${Math.max(0, Math.round(Number(input.live_duration_ms) / 1e3))}s`);
|
|
948
|
+
function applySystemCaEnv(env) {
|
|
949
|
+
if (!String(env[NODE_USE_SYSTEM_CA] ?? "").trim()) {
|
|
950
|
+
env[NODE_USE_SYSTEM_CA] = "1";
|
|
958
951
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
}
|
|
963
|
-
function isSubagentToolName(name) {
|
|
964
|
-
const n = (name ?? "").trim();
|
|
965
|
-
if (/^(task|agent|spawn_agent)$/i.test(n)) return true;
|
|
966
|
-
return /connectedAgentRequest/i.test(n);
|
|
967
|
-
}
|
|
968
|
-
function isInternalAgentStatusText(text) {
|
|
969
|
-
const t = text.trim();
|
|
970
|
-
if (!t) return false;
|
|
971
|
-
if (/waiting for gate to pass/i.test(t)) return true;
|
|
972
|
-
if (/^agent is running\b/i.test(t) && t.length < 160) return true;
|
|
973
|
-
return false;
|
|
952
|
+
if (String(env[NODE_EXTRA_CA_CERTS] ?? "").trim()) return;
|
|
953
|
+
const inherited = process.env.NODE_EXTRA_CA_CERTS?.trim();
|
|
954
|
+
if (inherited) env[NODE_EXTRA_CA_CERTS] = inherited;
|
|
974
955
|
}
|
|
975
|
-
function
|
|
976
|
-
const
|
|
977
|
-
|
|
956
|
+
function extraCertsFromBundle() {
|
|
957
|
+
const path = process.env.NODE_EXTRA_CA_CERTS?.trim();
|
|
958
|
+
if (path) return splitPemCertificates(readExistingFile(path));
|
|
959
|
+
const dest = systemCaBundlePath();
|
|
960
|
+
return splitPemCertificates(readExistingFile(dest));
|
|
978
961
|
}
|
|
979
|
-
function
|
|
980
|
-
|
|
981
|
-
const
|
|
982
|
-
if (
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
962
|
+
function trustSystemCertificates(io = {}) {
|
|
963
|
+
try {
|
|
964
|
+
const api = tls;
|
|
965
|
+
if (typeof api.getCACertificates !== "function" || typeof api.setDefaultCACertificates !== "function") {
|
|
966
|
+
return false;
|
|
967
|
+
}
|
|
968
|
+
const current = api.getCACertificates("default");
|
|
969
|
+
const system = api.getCACertificates("system");
|
|
970
|
+
let extra = extraCertsFromBundle();
|
|
971
|
+
if (system.length === 0 && extra.length === 0) {
|
|
972
|
+
extra = splitPemCertificates(collectSystemCaPem(io));
|
|
973
|
+
}
|
|
974
|
+
if (system.length === 0 && extra.length === 0) return false;
|
|
975
|
+
api.setDefaultCACertificates([...current, ...system, ...extra]);
|
|
976
|
+
return true;
|
|
977
|
+
} catch {
|
|
978
|
+
return false;
|
|
979
|
+
}
|
|
988
980
|
}
|
|
989
|
-
|
|
990
|
-
|
|
981
|
+
|
|
982
|
+
// src/agents/packaged-runtime.ts
|
|
983
|
+
import { existsSync as existsSync3 } from "fs";
|
|
984
|
+
import { join as join2 } from "path";
|
|
985
|
+
function electronResourcesPath() {
|
|
986
|
+
const resources = process.resourcesPath;
|
|
987
|
+
if (typeof resources !== "string" || !resources) return null;
|
|
988
|
+
return resources;
|
|
991
989
|
}
|
|
992
|
-
function
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
(t) => t.status === "running" && !t.parentId && isSubagentToolName(t.name)
|
|
999
|
-
);
|
|
1000
|
-
const runningNested = [...tools].reverse().find((t) => t.status === "running" && t.parentId && !isPollWrapperToolName(t.name));
|
|
1001
|
-
const runningTop = [...tools].reverse().find(
|
|
1002
|
-
(t) => t.status === "running" && !t.parentId && !isPollWrapperToolName(t.name) && !isSubagentToolName(t.name)
|
|
1003
|
-
);
|
|
1004
|
-
const runningPoll = [...tools].reverse().find((t) => t.status === "running" && isPollWrapperToolName(t.name));
|
|
1005
|
-
const thinking = lastTextPart(parts, "thinking");
|
|
1006
|
-
const text = lastTextPart(parts, "text");
|
|
1007
|
-
if (runningSubs.length > 0) {
|
|
1008
|
-
const heads = runningSubs.map(toolLabel);
|
|
1009
|
-
const head = runningSubs.length === 1 ? heads[0] : `${runningSubs.length} subagents \xB7 ${heads.slice(0, 2).join(" \xB7 ")}`;
|
|
1010
|
-
if (runningNested) return `${head} \xB7 ${toolLabel(runningNested)}`;
|
|
1011
|
-
return head;
|
|
1012
|
-
}
|
|
1013
|
-
if (runningTop) return toolLabel(runningTop);
|
|
1014
|
-
if (runningPoll) return toolLabel(runningPoll);
|
|
1015
|
-
if (thinking) return thinking.length > 96 ? `\u2026${thinking.slice(-96)}` : thinking;
|
|
1016
|
-
if (text) return "Writing reply\u2026";
|
|
1017
|
-
const last = [...tools].reverse().find((t) => !isPollWrapperToolName(t.name)) ?? tools.at(-1);
|
|
1018
|
-
if (last) {
|
|
1019
|
-
const label = toolLabel(last);
|
|
1020
|
-
return last.status === "running" ? label : `Finished ${label}`;
|
|
1021
|
-
}
|
|
1022
|
-
return "Working\u2026";
|
|
990
|
+
function packagedCursorRuntimeDir() {
|
|
991
|
+
const resources = electronResourcesPath();
|
|
992
|
+
if (!resources) return null;
|
|
993
|
+
const dir = join2(resources, "cursor-runtime");
|
|
994
|
+
if (!existsSync3(join2(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
|
|
995
|
+
return dir;
|
|
1023
996
|
}
|
|
1024
|
-
function
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
}
|
|
1028
|
-
return void 0;
|
|
997
|
+
function packagedCursorRunnerPath() {
|
|
998
|
+
const dir = packagedCursorRuntimeDir();
|
|
999
|
+
return dir ? join2(dir, "core-dist", "agents", "cursor-runner.js") : null;
|
|
1029
1000
|
}
|
|
1030
|
-
function
|
|
1031
|
-
|
|
1001
|
+
function packagedMcpDir() {
|
|
1002
|
+
const resources = electronResourcesPath();
|
|
1003
|
+
if (!resources) return null;
|
|
1004
|
+
const dir = join2(resources, "sideboard-mcp");
|
|
1005
|
+
if (!existsSync3(join2(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
|
|
1006
|
+
return dir;
|
|
1032
1007
|
}
|
|
1033
|
-
function
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
return { ...event, parentId: event.parentId ?? parentId };
|
|
1037
|
-
}
|
|
1038
|
-
return event;
|
|
1008
|
+
function packagedMcpStdioPath() {
|
|
1009
|
+
const dir = packagedMcpDir();
|
|
1010
|
+
return dir ? join2(dir, "core-dist", "mcp", "run-stdio.js") : null;
|
|
1039
1011
|
}
|
|
1040
|
-
function
|
|
1041
|
-
|
|
1042
|
-
|
|
1012
|
+
function packagedBundledNodePath() {
|
|
1013
|
+
const resources = electronResourcesPath();
|
|
1014
|
+
if (!resources) return null;
|
|
1015
|
+
const bin = join2(resources, "node", "bin", "node");
|
|
1016
|
+
if (!existsSync3(bin)) return null;
|
|
1017
|
+
return bin;
|
|
1043
1018
|
}
|
|
1044
|
-
function
|
|
1045
|
-
|
|
1046
|
-
|
|
1019
|
+
function packagedCursorRipgrepCandidate(platformPkg, binName) {
|
|
1020
|
+
const dir = packagedCursorRuntimeDir();
|
|
1021
|
+
if (!dir) return null;
|
|
1022
|
+
return join2(dir, "node_modules", platformPkg, "bin", binName);
|
|
1047
1023
|
}
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1024
|
+
|
|
1025
|
+
// src/agents/node-launch.ts
|
|
1026
|
+
var AGENT_RUNNER_MAX_OLD_SPACE_MB = 8192;
|
|
1027
|
+
var MAX_OLD_SPACE_FLAG = /(?:^|\s)(--max[-_]old[-_]space[-_]size)(?:[= ](\d+))?(?=\s|$)/;
|
|
1028
|
+
function withMaxOldSpaceSize(nodeOptions, heapMb) {
|
|
1029
|
+
const existing = (nodeOptions ?? "").trim();
|
|
1030
|
+
const match = MAX_OLD_SPACE_FLAG.exec(existing);
|
|
1031
|
+
if (match) {
|
|
1032
|
+
const current = match[2] ? Number(match[2]) : 0;
|
|
1033
|
+
if (Number.isFinite(current) && current >= heapMb) return existing;
|
|
1034
|
+
return existing.replace(MAX_OLD_SPACE_FLAG, ` --max-old-space-size=${heapMb}`).trim();
|
|
1057
1035
|
}
|
|
1058
|
-
return {}
|
|
1036
|
+
return existing ? `${existing} --max-old-space-size=${heapMb}` : `--max-old-space-size=${heapMb}`;
|
|
1059
1037
|
}
|
|
1060
|
-
function
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
return {
|
|
1065
|
-
additions: Number(paired[1]),
|
|
1066
|
-
deletions: Number(paired[2])
|
|
1067
|
-
};
|
|
1068
|
-
}
|
|
1069
|
-
const verbose = result.match(
|
|
1070
|
-
/(\d+)\s+insertions?(?:,\s*(\d+)\s+deletions?)?/i
|
|
1038
|
+
function applyAgentRunnerHeapEnv(env) {
|
|
1039
|
+
env.NODE_OPTIONS = withMaxOldSpaceSize(
|
|
1040
|
+
env.NODE_OPTIONS,
|
|
1041
|
+
AGENT_RUNNER_MAX_OLD_SPACE_MB
|
|
1071
1042
|
);
|
|
1072
|
-
|
|
1073
|
-
return {
|
|
1074
|
-
additions: Number(verbose[1]),
|
|
1075
|
-
deletions: verbose[2] != null ? Number(verbose[2]) : void 0
|
|
1076
|
-
};
|
|
1077
|
-
}
|
|
1078
|
-
return {};
|
|
1043
|
+
applySystemCaEnv(env);
|
|
1079
1044
|
}
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
return marker + text.slice(text.length - Math.max(1, max - marker.length));
|
|
1045
|
+
function envWithAgentHeap(env) {
|
|
1046
|
+
const next = { ...env };
|
|
1047
|
+
applyAgentRunnerHeapEnv(next);
|
|
1048
|
+
return next;
|
|
1085
1049
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
if (text.length <= max) return text;
|
|
1090
|
-
const marker = "\u2026(truncated)\n";
|
|
1091
|
-
return marker + text.slice(text.length - Math.max(1, max - marker.length));
|
|
1050
|
+
function isAsarPath(filePath) {
|
|
1051
|
+
if (/\.asar\.unpacked([/\\]|$)/.test(filePath)) return false;
|
|
1052
|
+
return /\.asar([/\\]|$)/.test(filePath);
|
|
1092
1053
|
}
|
|
1093
|
-
function
|
|
1094
|
-
if (
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1054
|
+
function unpackedAsarPath(filePath) {
|
|
1055
|
+
if (!isAsarPath(filePath)) return null;
|
|
1056
|
+
const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
|
|
1057
|
+
if (unpacked === filePath) return null;
|
|
1058
|
+
return existsSync4(unpacked) ? unpacked : null;
|
|
1059
|
+
}
|
|
1060
|
+
function nodeReadableScriptPath(scriptPath) {
|
|
1061
|
+
return unpackedAsarPath(scriptPath) ?? scriptPath;
|
|
1062
|
+
}
|
|
1063
|
+
var PREFERRED_LTS_MAJORS = [24, 22];
|
|
1064
|
+
function parseNodeMajor(version) {
|
|
1065
|
+
const match = /^v?(\d+)/.exec(version.trim());
|
|
1066
|
+
if (!match) return null;
|
|
1067
|
+
const major = Number(match[1]);
|
|
1068
|
+
return Number.isInteger(major) ? major : null;
|
|
1069
|
+
}
|
|
1070
|
+
function scoreNodeForAgentRuntime(candidate) {
|
|
1071
|
+
const major = parseNodeMajor(candidate.version);
|
|
1072
|
+
if (major == null) return Number.NEGATIVE_INFINITY;
|
|
1073
|
+
if (major < 22) return major - 100;
|
|
1074
|
+
const posix = candidate.path.replace(/\\/g, "/");
|
|
1075
|
+
let score = 0;
|
|
1076
|
+
if (major % 2 === 0) {
|
|
1077
|
+
score += 1e3 + major * 10;
|
|
1078
|
+
} else {
|
|
1079
|
+
score += major;
|
|
1104
1080
|
}
|
|
1105
|
-
if (
|
|
1106
|
-
|
|
1081
|
+
if (/\/Cellar\/node\/\d/.test(posix) && !/\/Cellar\/node@\d+/.test(posix)) {
|
|
1082
|
+
score -= 50;
|
|
1107
1083
|
}
|
|
1108
|
-
return
|
|
1109
|
-
}
|
|
1110
|
-
function withPartTimes(next, prev) {
|
|
1111
|
-
const now = Date.now();
|
|
1112
|
-
const startedAt = prev && typeof prev.startedAt === "number" ? prev.startedAt : now;
|
|
1113
|
-
return { ...next, startedAt, updatedAt: now };
|
|
1084
|
+
return score;
|
|
1114
1085
|
}
|
|
1115
|
-
function
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
const
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
{
|
|
1124
|
-
type: "text",
|
|
1125
|
-
text: last.text + data,
|
|
1126
|
-
...event.parentId ? { parentId: event.parentId } : {}
|
|
1127
|
-
},
|
|
1128
|
-
last
|
|
1129
|
-
);
|
|
1130
|
-
} else {
|
|
1131
|
-
next.push(
|
|
1132
|
-
withPartTimes({
|
|
1133
|
-
type: "text",
|
|
1134
|
-
text: data,
|
|
1135
|
-
...event.parentId ? { parentId: event.parentId } : {}
|
|
1136
|
-
})
|
|
1137
|
-
);
|
|
1086
|
+
function pickPreferredNode(candidates) {
|
|
1087
|
+
let best = null;
|
|
1088
|
+
let bestScore = Number.NEGATIVE_INFINITY;
|
|
1089
|
+
for (const candidate of candidates) {
|
|
1090
|
+
const score = scoreNodeForAgentRuntime(candidate);
|
|
1091
|
+
if (score > bestScore) {
|
|
1092
|
+
bestScore = score;
|
|
1093
|
+
best = candidate;
|
|
1138
1094
|
}
|
|
1139
|
-
return next;
|
|
1140
1095
|
}
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
next[i] = withPartTimes(
|
|
1150
|
-
{
|
|
1151
|
-
type: "thinking",
|
|
1152
|
-
text: clipThinkingForStore(data),
|
|
1153
|
-
...event.parentId ? { parentId: event.parentId } : {}
|
|
1154
|
-
},
|
|
1155
|
-
prev
|
|
1156
|
-
);
|
|
1157
|
-
return next;
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
next.push(
|
|
1161
|
-
withPartTimes({
|
|
1162
|
-
type: "thinking",
|
|
1163
|
-
text: clipThinkingForStore(data),
|
|
1164
|
-
...event.parentId ? { parentId: event.parentId } : {}
|
|
1165
|
-
})
|
|
1166
|
-
);
|
|
1167
|
-
return next;
|
|
1168
|
-
}
|
|
1169
|
-
const last = next[next.length - 1];
|
|
1170
|
-
if (last?.type === "thinking" && sameParentId(last.parentId, event.parentId)) {
|
|
1171
|
-
next[next.length - 1] = withPartTimes(
|
|
1172
|
-
{
|
|
1173
|
-
type: "thinking",
|
|
1174
|
-
text: clipThinkingForStore(last.text + data),
|
|
1175
|
-
...event.parentId ? { parentId: event.parentId } : {}
|
|
1176
|
-
},
|
|
1177
|
-
last
|
|
1178
|
-
);
|
|
1179
|
-
} else {
|
|
1180
|
-
next.push(
|
|
1181
|
-
withPartTimes({
|
|
1182
|
-
type: "thinking",
|
|
1183
|
-
text: clipThinkingForStore(data),
|
|
1184
|
-
...event.parentId ? { parentId: event.parentId } : {}
|
|
1185
|
-
})
|
|
1186
|
-
);
|
|
1187
|
-
}
|
|
1188
|
-
return next;
|
|
1096
|
+
return best;
|
|
1097
|
+
}
|
|
1098
|
+
function versionDirNodeBins(root, toBin) {
|
|
1099
|
+
if (!existsSync4(root)) return [];
|
|
1100
|
+
try {
|
|
1101
|
+
return readdirSync(root).map(toBin);
|
|
1102
|
+
} catch {
|
|
1103
|
+
return [];
|
|
1189
1104
|
}
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1105
|
+
}
|
|
1106
|
+
function defaultNodeBinCandidates(home = homedir()) {
|
|
1107
|
+
const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
|
|
1108
|
+
(prefix) => PREFERRED_LTS_MAJORS.map((major) => join3(prefix, "opt", `node@${major}`, "bin", "node"))
|
|
1109
|
+
);
|
|
1110
|
+
return [
|
|
1111
|
+
...kegs,
|
|
1112
|
+
"/opt/homebrew/bin/node",
|
|
1113
|
+
"/usr/local/bin/node",
|
|
1114
|
+
join3(home, ".local/share/fnm/aliases/default/bin/node"),
|
|
1115
|
+
join3(home, ".nvm/current/bin/node"),
|
|
1116
|
+
join3(home, ".volta/bin/node"),
|
|
1117
|
+
join3(home, ".asdf/shims/node"),
|
|
1118
|
+
join3(home, ".local/share/mise/shims/node"),
|
|
1119
|
+
...versionDirNodeBins(
|
|
1120
|
+
join3(home, ".nvm", "versions", "node"),
|
|
1121
|
+
(name) => join3(home, ".nvm", "versions", "node", name, "bin", "node")
|
|
1122
|
+
),
|
|
1123
|
+
...versionDirNodeBins(
|
|
1124
|
+
join3(home, ".local/share/fnm", "node-versions"),
|
|
1125
|
+
(name) => join3(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
|
|
1126
|
+
),
|
|
1127
|
+
...versionDirNodeBins(
|
|
1128
|
+
join3(home, ".volta", "tools", "image", "node"),
|
|
1129
|
+
(name) => join3(home, ".volta", "tools", "image", "node", name, "bin", "node")
|
|
1130
|
+
)
|
|
1131
|
+
];
|
|
1132
|
+
}
|
|
1133
|
+
function uniqueExistingNodeBins(paths) {
|
|
1134
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1135
|
+
const out = [];
|
|
1136
|
+
for (const raw of paths) {
|
|
1137
|
+
const p = raw.trim();
|
|
1138
|
+
if (!p || !existsSync4(p) || isElectronLikeCommand(p)) continue;
|
|
1139
|
+
let key = p;
|
|
1140
|
+
try {
|
|
1141
|
+
key = realpathSync(p);
|
|
1142
|
+
} catch {
|
|
1143
|
+
continue;
|
|
1217
1144
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
type: "tool",
|
|
1222
|
-
id: event.id,
|
|
1223
|
-
name: event.name,
|
|
1224
|
-
input,
|
|
1225
|
-
description: toolDescription(event.name, input),
|
|
1226
|
-
detail: toolDetail(event.name, input),
|
|
1227
|
-
status: "running",
|
|
1228
|
-
filePath: toolFilePath(input),
|
|
1229
|
-
...event.parentId ? { parentId: event.parentId } : {},
|
|
1230
|
-
...diff
|
|
1231
|
-
})
|
|
1232
|
-
];
|
|
1145
|
+
if (seen.has(key)) continue;
|
|
1146
|
+
seen.add(key);
|
|
1147
|
+
out.push(p);
|
|
1233
1148
|
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
withPartTimes({
|
|
1242
|
-
type: "tool",
|
|
1243
|
-
id: event.id,
|
|
1244
|
-
name: "tool",
|
|
1245
|
-
description: "tool",
|
|
1246
|
-
status: event.isError ? "error" : "running",
|
|
1247
|
-
result: clipToolResultForStore(event.content),
|
|
1248
|
-
...event.parentId ? { parentId: event.parentId } : {}
|
|
1249
|
-
})
|
|
1250
|
-
];
|
|
1251
|
-
}
|
|
1252
|
-
return parts.map((p, i) => {
|
|
1253
|
-
if (i !== existing || p.type !== "tool") return p;
|
|
1254
|
-
if (p.status === "done" || p.status === "error") return p;
|
|
1255
|
-
return withPartTimes(
|
|
1256
|
-
{
|
|
1257
|
-
...p,
|
|
1258
|
-
result: clipToolResultForStore(event.content) ?? p.result
|
|
1259
|
-
},
|
|
1260
|
-
p
|
|
1261
|
-
);
|
|
1262
|
-
});
|
|
1263
|
-
}
|
|
1264
|
-
if (existing < 0) {
|
|
1265
|
-
return [
|
|
1266
|
-
...parts,
|
|
1267
|
-
withPartTimes({
|
|
1268
|
-
type: "tool",
|
|
1269
|
-
id: event.id,
|
|
1270
|
-
name: "tool",
|
|
1271
|
-
description: "tool",
|
|
1272
|
-
status: event.isError ? "error" : "done",
|
|
1273
|
-
result: clipToolResultForStore(event.content),
|
|
1274
|
-
...event.parentId ? { parentId: event.parentId } : {},
|
|
1275
|
-
...fromResult.additions != null ? { additions: fromResult.additions } : {},
|
|
1276
|
-
...fromResult.deletions != null ? { deletions: fromResult.deletions } : {}
|
|
1277
|
-
})
|
|
1278
|
-
];
|
|
1279
|
-
}
|
|
1280
|
-
return parts.map((p, i) => {
|
|
1281
|
-
if (i !== existing || p.type !== "tool") return p;
|
|
1282
|
-
return withPartTimes(
|
|
1283
|
-
{
|
|
1284
|
-
...p,
|
|
1285
|
-
status: event.isError ? "error" : "done",
|
|
1286
|
-
result: clipToolResultForStore(event.content),
|
|
1287
|
-
...fromResult.additions != null ? { additions: fromResult.additions } : {},
|
|
1288
|
-
...fromResult.deletions != null ? { deletions: fromResult.deletions } : {}
|
|
1289
|
-
},
|
|
1290
|
-
p
|
|
1291
|
-
);
|
|
1292
|
-
});
|
|
1149
|
+
return out;
|
|
1150
|
+
}
|
|
1151
|
+
async function whichAllNode() {
|
|
1152
|
+
if (process.platform === "win32") {
|
|
1153
|
+
const located = await run("where", ["node"], { reject: false, timeoutMs: 5e3 });
|
|
1154
|
+
if (located.exitCode !== 0) return [];
|
|
1155
|
+
return located.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
1293
1156
|
}
|
|
1294
|
-
|
|
1157
|
+
const all = await run("which", ["-a", "node"], { reject: false, timeoutMs: 5e3 });
|
|
1158
|
+
if (all.exitCode === 0 && all.stdout.trim()) {
|
|
1159
|
+
return all.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
1160
|
+
}
|
|
1161
|
+
const single = await run("which", ["node"], { reject: false, timeoutMs: 5e3 });
|
|
1162
|
+
if (single.exitCode !== 0 || !single.stdout.trim()) return [];
|
|
1163
|
+
return [single.stdout.trim()];
|
|
1295
1164
|
}
|
|
1296
|
-
function
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1165
|
+
async function probeNodeVersion(bin) {
|
|
1166
|
+
const probed = await run(bin, ["-v"], { reject: false, timeoutMs: 4e3 });
|
|
1167
|
+
if (probed.exitCode !== 0) return null;
|
|
1168
|
+
const version = probed.stdout.trim().split(/\r?\n/).find(Boolean);
|
|
1169
|
+
return version || null;
|
|
1300
1170
|
}
|
|
1301
|
-
function
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1171
|
+
async function findSystemNode() {
|
|
1172
|
+
const fromPath = await whichAllNode();
|
|
1173
|
+
const bins = uniqueExistingNodeBins([...fromPath, ...defaultNodeBinCandidates()]);
|
|
1174
|
+
if (bins.length === 0) return null;
|
|
1175
|
+
const probed = await Promise.all(
|
|
1176
|
+
bins.map(async (path) => {
|
|
1177
|
+
const version = await probeNodeVersion(path);
|
|
1178
|
+
return version ? { path, version } : null;
|
|
1179
|
+
})
|
|
1307
1180
|
);
|
|
1308
|
-
|
|
1309
|
-
return out.trim();
|
|
1310
|
-
}
|
|
1311
|
-
function isBrightsyNdjsonLine(line) {
|
|
1312
|
-
const t = line.trim();
|
|
1313
|
-
if (!t.startsWith("{")) return false;
|
|
1314
|
-
return /"type"\s*:\s*"(tool_use|tool_result|tool|thinking|usage|done|error|text)"/.test(t);
|
|
1181
|
+
return pickPreferredNode(probed.filter((c) => c != null));
|
|
1315
1182
|
}
|
|
1316
|
-
function
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1183
|
+
function applyNodeLaunch(launch, args) {
|
|
1184
|
+
const readableArgs = args.map(nodeReadableScriptPath);
|
|
1185
|
+
if (!launch.env.ELECTRON_RUN_AS_NODE) {
|
|
1186
|
+
return {
|
|
1187
|
+
file: launch.file,
|
|
1188
|
+
args: readableArgs,
|
|
1189
|
+
env: envWithAgentHeap(launch.env)
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
const wrapped = wrapElectronAsNodeLaunch(launch.file, readableArgs);
|
|
1193
|
+
if (process.platform === "win32") {
|
|
1194
|
+
return {
|
|
1195
|
+
file: wrapped.file,
|
|
1196
|
+
args: wrapped.args,
|
|
1197
|
+
env: envWithAgentHeap(launch.env)
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
const env = envWithAgentHeap(launch.env);
|
|
1201
|
+
delete env.ELECTRON_RUN_AS_NODE;
|
|
1202
|
+
return { file: wrapped.file, args: wrapped.args, env };
|
|
1320
1203
|
}
|
|
1321
|
-
function
|
|
1322
|
-
|
|
1323
|
-
|
|
1204
|
+
async function resolveNodeLaunch(scriptPath) {
|
|
1205
|
+
const script = nodeReadableScriptPath(scriptPath);
|
|
1206
|
+
if (!isAsarPath(script)) {
|
|
1207
|
+
const bundled = packagedBundledNodePath();
|
|
1208
|
+
if (bundled && !isElectronLikeCommand(bundled)) {
|
|
1209
|
+
return { file: bundled, env: {} };
|
|
1210
|
+
}
|
|
1211
|
+
const node = await findSystemNode();
|
|
1212
|
+
if (node) {
|
|
1213
|
+
return { file: node.path, env: {}, nodeVersion: node.version };
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
return {
|
|
1217
|
+
file: process.execPath,
|
|
1218
|
+
env: { ELECTRON_RUN_AS_NODE: "1" }
|
|
1219
|
+
};
|
|
1324
1220
|
}
|
|
1325
1221
|
|
|
1326
1222
|
// src/agents/injected-mcp.ts
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
import { dirname as dirname2, join as join4 } from "path";
|
|
1331
|
-
import { fileURLToPath } from "url";
|
|
1332
|
-
|
|
1333
|
-
// src/mcp/profile.ts
|
|
1334
|
-
var SIDEBOARD_MCP_PROFILE_ENV = "SIDEBOARD_MCP_PROFILE";
|
|
1335
|
-
function sideboardMcpProfile(env = process.env) {
|
|
1336
|
-
return env[SIDEBOARD_MCP_PROFILE_ENV]?.trim().toLowerCase() === "worktree" ? "worktree" : "orchestration";
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
// src/agents/node-launch.ts
|
|
1340
|
-
import { existsSync as existsSync4, readdirSync, realpathSync } from "fs";
|
|
1341
|
-
import { homedir } from "os";
|
|
1342
|
-
import { join as join3 } from "path";
|
|
1343
|
-
|
|
1344
|
-
// src/http/system-ca.ts
|
|
1345
|
-
import { spawnSync } from "child_process";
|
|
1346
|
-
import { existsSync as existsSync2, mkdirSync, readFileSync, statSync, writeFileSync } from "fs";
|
|
1347
|
-
import { dirname, join } from "path";
|
|
1348
|
-
import tls from "tls";
|
|
1349
|
-
var NODE_USE_SYSTEM_CA = "NODE_USE_SYSTEM_CA";
|
|
1350
|
-
var NODE_EXTRA_CA_CERTS = "NODE_EXTRA_CA_CERTS";
|
|
1351
|
-
var BUNDLE_NAME = "system-ca.pem";
|
|
1352
|
-
var BUNDLE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
1353
|
-
var LINUX_CA_FILES = [
|
|
1354
|
-
"/etc/ssl/certs/ca-certificates.crt",
|
|
1355
|
-
"/etc/pki/tls/certs/ca-bundle.crt",
|
|
1356
|
-
"/etc/ssl/ca-bundle.pem",
|
|
1357
|
-
"/etc/ssl/cert.pem"
|
|
1223
|
+
var SIDEBOARD_MCP_ALLOWED_TOOLS = [
|
|
1224
|
+
"mcp__sideboard",
|
|
1225
|
+
"mcp__sideboard__*"
|
|
1358
1226
|
];
|
|
1359
|
-
var
|
|
1360
|
-
|
|
1361
|
-
|
|
1227
|
+
var SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS = [
|
|
1228
|
+
"mcp__sideboard__present_artifact",
|
|
1229
|
+
"mcp__sideboard__present_schema",
|
|
1230
|
+
"mcp__sideboard__present_files",
|
|
1231
|
+
"mcp__sideboard__ask_user",
|
|
1232
|
+
"mcp__sideboard__present_plan",
|
|
1233
|
+
"mcp__sideboard__wait_for_job",
|
|
1234
|
+
"mcp__sideboard__stop_job",
|
|
1235
|
+
"mcp__sideboard__get_viewer_context",
|
|
1236
|
+
"mcp__sideboard__update_viewer_context"
|
|
1237
|
+
];
|
|
1238
|
+
var SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS = ["mcp__sideboard__github_*"];
|
|
1239
|
+
var SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS = ["mcp__sideboard__linear_*"];
|
|
1240
|
+
var SIDEBOARD_ABLETIME_MCP_ALLOWED_TOOLS = ["mcp__sideboard__abletime_*"];
|
|
1241
|
+
function sideboardWorktreeAllowedTools(opts) {
|
|
1242
|
+
const out = [...SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS];
|
|
1243
|
+
if (opts?.github !== false) out.push(...SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS);
|
|
1244
|
+
if (opts?.linear) out.push(...SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS);
|
|
1245
|
+
if (opts?.abletime) out.push(...SIDEBOARD_ABLETIME_MCP_ALLOWED_TOOLS);
|
|
1246
|
+
return out;
|
|
1362
1247
|
}
|
|
1363
|
-
|
|
1248
|
+
var brightsyMcpCommandCache = null;
|
|
1249
|
+
async function resolveBrightsyMcpCommand() {
|
|
1250
|
+
const now = Date.now();
|
|
1251
|
+
if (brightsyMcpCommandCache && now - brightsyMcpCommandCache.at < 6e4 && brightsyMcpCommandCache.command) {
|
|
1252
|
+
return brightsyMcpCommandCache.command;
|
|
1253
|
+
}
|
|
1254
|
+
const which = await run("which", ["brightsy-mcp"], { reject: false });
|
|
1255
|
+
const command = which.exitCode === 0 && which.stdout.trim() ? "brightsy-mcp" : "npx";
|
|
1256
|
+
brightsyMcpCommandCache = { at: now, command };
|
|
1257
|
+
return command;
|
|
1258
|
+
}
|
|
1259
|
+
function isBrightsyConnected() {
|
|
1364
1260
|
try {
|
|
1365
|
-
|
|
1261
|
+
loadBrightsyConfig();
|
|
1262
|
+
return true;
|
|
1366
1263
|
} catch {
|
|
1367
|
-
return
|
|
1264
|
+
return false;
|
|
1368
1265
|
}
|
|
1369
1266
|
}
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
maxBuffer: 32 * 1024 * 1024,
|
|
1374
|
-
timeout: 15e3
|
|
1375
|
-
});
|
|
1376
|
-
if (result.status !== 0) return "";
|
|
1377
|
-
return typeof result.stdout === "string" ? result.stdout : "";
|
|
1267
|
+
var BRIGHTSY_WORD = /(?<![a-z0-9_-])brightsy(?![a-z0-9_-])/i;
|
|
1268
|
+
function promptMentionsBrightsy(text) {
|
|
1269
|
+
return BRIGHTSY_WORD.test(text ?? "");
|
|
1378
1270
|
}
|
|
1379
|
-
function
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
if (splitPemCertificates(pem).length > 0) return pem;
|
|
1383
|
-
}
|
|
1384
|
-
return "";
|
|
1271
|
+
function isBrightsyMcpToolName(name) {
|
|
1272
|
+
const n = name.toLowerCase();
|
|
1273
|
+
return n === "brightsy" || n.startsWith("mcp__brightsy") || n.startsWith("brightsy_");
|
|
1385
1274
|
}
|
|
1386
|
-
function
|
|
1387
|
-
const
|
|
1388
|
-
|
|
1389
|
-
|
|
1275
|
+
function toolInputUsesBrightsyDatasource(input) {
|
|
1276
|
+
const ds = input?.datasource;
|
|
1277
|
+
return typeof ds === "string" && ds.toLowerCase() === "brightsy";
|
|
1278
|
+
}
|
|
1279
|
+
function messageUsedBrightsyMcp(msg) {
|
|
1280
|
+
if (msg.role === "user" && promptMentionsBrightsy(msg.text)) return true;
|
|
1281
|
+
for (const part of msg.parts ?? []) {
|
|
1282
|
+
if (part.type !== "tool") continue;
|
|
1283
|
+
if (isBrightsyMcpToolName(part.name)) return true;
|
|
1284
|
+
if (/present_(schema|files)$/i.test(part.name) && toolInputUsesBrightsyDatasource(part.input)) {
|
|
1285
|
+
return true;
|
|
1286
|
+
}
|
|
1390
1287
|
}
|
|
1391
|
-
|
|
1392
|
-
|
|
1288
|
+
return false;
|
|
1289
|
+
}
|
|
1290
|
+
function threadRequestsBrightsyMcp(thread) {
|
|
1291
|
+
return (thread?.messages ?? []).some(messageUsedBrightsyMcp);
|
|
1292
|
+
}
|
|
1293
|
+
function shouldInjectBrightsyMcp(thread, opts) {
|
|
1294
|
+
if (!(opts?.connected ?? isBrightsyConnected())) return false;
|
|
1295
|
+
if (opts?.orchestrator) return true;
|
|
1296
|
+
const alwaysOn = opts?.alwaysOnWorktree ?? Boolean(loadAppSettings().brightsy?.injectWorktreeMcp);
|
|
1297
|
+
if (alwaysOn) return true;
|
|
1298
|
+
return threadRequestsBrightsyMcp(thread);
|
|
1299
|
+
}
|
|
1300
|
+
function mcpLaunch(cmd, name, env) {
|
|
1301
|
+
if (cmd === "brightsy-mcp") {
|
|
1302
|
+
return { name, command: "brightsy-mcp", ...env ? { env } : {} };
|
|
1393
1303
|
}
|
|
1394
|
-
return
|
|
1304
|
+
return {
|
|
1305
|
+
name,
|
|
1306
|
+
command: "npx",
|
|
1307
|
+
args: ["-y", "@brightsy/mcp-server"],
|
|
1308
|
+
...env ? { env } : {}
|
|
1309
|
+
};
|
|
1395
1310
|
}
|
|
1396
|
-
function
|
|
1397
|
-
|
|
1311
|
+
function teamEnv(team) {
|
|
1312
|
+
const endpoint = (team.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
1313
|
+
return {
|
|
1314
|
+
BRIGHTSY_API_TOKEN: team.access_token,
|
|
1315
|
+
...team.refresh_token ? { BRIGHTSY_REFRESH_TOKEN: team.refresh_token } : {},
|
|
1316
|
+
BRIGHTSY_ACCOUNT_ID: team.id,
|
|
1317
|
+
BRIGHTSY_API_URL: endpoint
|
|
1318
|
+
};
|
|
1398
1319
|
}
|
|
1399
|
-
function
|
|
1320
|
+
function brightsyMcpAllowedTools(serverNames) {
|
|
1321
|
+
const out = [];
|
|
1322
|
+
for (const name of serverNames) {
|
|
1323
|
+
out.push(`mcp__${name}`, `mcp__${name}__*`);
|
|
1324
|
+
}
|
|
1325
|
+
return out;
|
|
1326
|
+
}
|
|
1327
|
+
function corePackageDir() {
|
|
1328
|
+
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
1329
|
+
if (cjsDir) return cjsDir;
|
|
1400
1330
|
try {
|
|
1401
|
-
|
|
1402
|
-
if (
|
|
1403
|
-
|
|
1331
|
+
const url = import.meta.url;
|
|
1332
|
+
if (typeof url === "string" && url.length > 0) {
|
|
1333
|
+
return dirname2(fileURLToPath(url));
|
|
1334
|
+
}
|
|
1404
1335
|
} catch {
|
|
1405
|
-
return false;
|
|
1406
1336
|
}
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
return
|
|
1337
|
+
try {
|
|
1338
|
+
const req = createRequire(join4(process.cwd(), "package.json"));
|
|
1339
|
+
return dirname2(req.resolve("@sideboard-ai/core"));
|
|
1340
|
+
} catch {
|
|
1341
|
+
return process.cwd();
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
function findSideboardMcpJsEntry() {
|
|
1345
|
+
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
1346
|
+
if (override && existsSync5(override)) return override;
|
|
1347
|
+
const packaged = packagedMcpStdioPath();
|
|
1348
|
+
if (packaged) return packaged;
|
|
1349
|
+
let dir = corePackageDir();
|
|
1350
|
+
for (let i = 0; i < 10; i++) {
|
|
1351
|
+
const candidates = [
|
|
1352
|
+
join4(dir, "mcp/run-stdio.js"),
|
|
1353
|
+
join4(dir, "mcp/run-stdio.cjs"),
|
|
1354
|
+
join4(dir, "dist/mcp/run-stdio.js"),
|
|
1355
|
+
join4(dir, "dist/mcp/run-stdio.cjs"),
|
|
1356
|
+
join4(dir, "packages/core/dist/mcp/run-stdio.js"),
|
|
1357
|
+
join4(dir, "packages/cli/dist/index.js"),
|
|
1358
|
+
join4(dir, "cli/dist/index.js")
|
|
1359
|
+
];
|
|
1360
|
+
for (const p of candidates) {
|
|
1361
|
+
if (existsSync5(p) && !isAsarPath(p)) return p;
|
|
1362
|
+
}
|
|
1363
|
+
const parent = dirname2(dir);
|
|
1364
|
+
if (parent === dir) break;
|
|
1365
|
+
dir = parent;
|
|
1366
|
+
}
|
|
1367
|
+
return null;
|
|
1368
|
+
}
|
|
1369
|
+
async function resolveSideboardMcpServer() {
|
|
1370
|
+
const entry = findSideboardMcpJsEntry();
|
|
1371
|
+
if (entry) {
|
|
1372
|
+
const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
|
|
1373
|
+
const scriptArgs = isCli ? [entry, "mcp"] : [entry];
|
|
1374
|
+
const launch = applyNodeLaunch(await resolveNodeLaunch(entry), scriptArgs);
|
|
1375
|
+
if (launch.file !== "/bin/sh" && !isElectronLikeCommand(launch.file)) {
|
|
1376
|
+
return {
|
|
1377
|
+
name: "sideboard",
|
|
1378
|
+
command: launch.file,
|
|
1379
|
+
args: launch.args,
|
|
1380
|
+
...Object.keys(launch.env).length > 0 ? { env: launch.env } : {}
|
|
1381
|
+
};
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
const which = await run("which", ["sideboard"], { reject: false });
|
|
1385
|
+
if (which.exitCode === 0 && which.stdout.trim()) {
|
|
1386
|
+
return { name: "sideboard", command: which.stdout.trim(), args: ["mcp"] };
|
|
1412
1387
|
}
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1388
|
+
return { name: "sideboard", command: "sideboard", args: ["mcp"] };
|
|
1389
|
+
}
|
|
1390
|
+
async function buildInjectedMcpServers(opts) {
|
|
1391
|
+
const servers = [];
|
|
1392
|
+
if (opts.includeSideboard) {
|
|
1393
|
+
const sideboard = await resolveSideboardMcpServer();
|
|
1394
|
+
const orchId = opts.orchestratorThreadId?.trim();
|
|
1395
|
+
const profile = orchId ? "orchestration" : "worktree";
|
|
1396
|
+
sideboard.env = {
|
|
1397
|
+
...sideboard.env ?? {},
|
|
1398
|
+
SIDEBOARD_APP_DATA: appDataDir(),
|
|
1399
|
+
[SIDEBOARD_MCP_PROFILE_ENV]: profile
|
|
1400
|
+
};
|
|
1401
|
+
if (orchId) {
|
|
1402
|
+
sideboard.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID = orchId;
|
|
1417
1403
|
}
|
|
1404
|
+
try {
|
|
1405
|
+
mergeAgentGitAuthEnv(
|
|
1406
|
+
sideboard.env,
|
|
1407
|
+
await resolveAgentGitAuthEnv(sideboard.env)
|
|
1408
|
+
);
|
|
1409
|
+
} catch {
|
|
1410
|
+
}
|
|
1411
|
+
applyAgentRunnerHeapEnv(sideboard.env);
|
|
1412
|
+
servers.push(sideboard);
|
|
1418
1413
|
}
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1414
|
+
if (opts.includeBrightsy && isBrightsyConnected()) {
|
|
1415
|
+
const cmd = await resolveBrightsyMcpCommand();
|
|
1416
|
+
const teams = await ensureConnectedBrightsyTeamTokens();
|
|
1417
|
+
if (teams.length > 0) {
|
|
1418
|
+
const used = /* @__PURE__ */ new Set();
|
|
1419
|
+
for (const team of teams) {
|
|
1420
|
+
let name = brightsyMcpServerName(team.slug);
|
|
1421
|
+
if (used.has(name)) name = `${name}_${team.id.slice(0, 8)}`;
|
|
1422
|
+
used.add(name);
|
|
1423
|
+
servers.push(mcpLaunch(cmd, name, teamEnv(team)));
|
|
1424
|
+
}
|
|
1425
|
+
} else {
|
|
1426
|
+
servers.push(mcpLaunch(cmd, "brightsy"));
|
|
1427
|
+
}
|
|
1433
1428
|
}
|
|
1429
|
+
return servers;
|
|
1434
1430
|
}
|
|
1435
|
-
function
|
|
1436
|
-
if (
|
|
1437
|
-
|
|
1431
|
+
function cursorSafeMcpLaunch(command, args) {
|
|
1432
|
+
if (process.platform === "win32") {
|
|
1433
|
+
return args && args.length > 0 ? { command, args } : { command };
|
|
1438
1434
|
}
|
|
1439
|
-
|
|
1440
|
-
const
|
|
1441
|
-
|
|
1435
|
+
const unwrapped = unwrapStrippedElectronLaunch(command, args);
|
|
1436
|
+
const file = unwrapped?.file ?? command;
|
|
1437
|
+
const fileArgs = unwrapped?.args ?? args ?? [];
|
|
1438
|
+
return fileArgs.length > 0 ? { command: file, args: fileArgs } : { command: file };
|
|
1442
1439
|
}
|
|
1443
|
-
function
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1440
|
+
function mcpSpawnEnv(env) {
|
|
1441
|
+
if (!env) return void 0;
|
|
1442
|
+
const out = { ...env };
|
|
1443
|
+
delete out.ELECTRON_RUN_AS_NODE;
|
|
1444
|
+
delete out.ELECTRON_RUN_AS_NODE;
|
|
1445
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
1448
1446
|
}
|
|
1449
|
-
function
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1447
|
+
function toCursorMcpServers(servers) {
|
|
1448
|
+
const out = {};
|
|
1449
|
+
for (const s of servers) {
|
|
1450
|
+
const env = mcpSpawnEnv(s.env);
|
|
1451
|
+
const launch = cursorSafeMcpLaunch(s.command, s.args);
|
|
1452
|
+
out[s.name] = {
|
|
1453
|
+
type: "stdio",
|
|
1454
|
+
command: launch.command,
|
|
1455
|
+
...launch.args && launch.args.length > 0 ? { args: launch.args } : {},
|
|
1456
|
+
...env ? { env } : {}
|
|
1457
|
+
};
|
|
1458
|
+
}
|
|
1459
|
+
return out;
|
|
1460
|
+
}
|
|
1461
|
+
function toCodexMcpConfigArgs(servers) {
|
|
1462
|
+
const args = [];
|
|
1463
|
+
for (const s of servers) {
|
|
1464
|
+
const prefix = `mcp_servers.${s.name}`;
|
|
1465
|
+
args.push("-c", `${prefix}.command=${JSON.stringify(s.command)}`);
|
|
1466
|
+
if (s.args?.length) {
|
|
1467
|
+
args.push("-c", `${prefix}.args=${JSON.stringify(s.args)}`);
|
|
1454
1468
|
}
|
|
1455
|
-
const
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1469
|
+
const env = mcpSpawnEnv(s.env);
|
|
1470
|
+
if (env) {
|
|
1471
|
+
for (const [key, value] of Object.entries(env)) {
|
|
1472
|
+
args.push("-c", `${prefix}.env.${key}=${JSON.stringify(value)}`);
|
|
1473
|
+
}
|
|
1460
1474
|
}
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
} catch {
|
|
1465
|
-
return false;
|
|
1475
|
+
args.push("-c", `${prefix}.default_tools_approval_mode=${JSON.stringify("approve")}`);
|
|
1476
|
+
args.push("-c", `${prefix}.tool_timeout_sec=300`);
|
|
1477
|
+
args.push("-c", `${prefix}.startup_timeout_sec=30`);
|
|
1466
1478
|
}
|
|
1479
|
+
return args;
|
|
1467
1480
|
}
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1478
|
-
const resources = electronResourcesPath();
|
|
1479
|
-
if (!resources) return null;
|
|
1480
|
-
const dir = join2(resources, "cursor-runtime");
|
|
1481
|
-
if (!existsSync3(join2(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
|
|
1482
|
-
return dir;
|
|
1483
|
-
}
|
|
1484
|
-
function packagedCursorRunnerPath() {
|
|
1485
|
-
const dir = packagedCursorRuntimeDir();
|
|
1486
|
-
return dir ? join2(dir, "core-dist", "agents", "cursor-runner.js") : null;
|
|
1487
|
-
}
|
|
1488
|
-
function packagedMcpDir() {
|
|
1489
|
-
const resources = electronResourcesPath();
|
|
1490
|
-
if (!resources) return null;
|
|
1491
|
-
const dir = join2(resources, "sideboard-mcp");
|
|
1492
|
-
if (!existsSync3(join2(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
|
|
1493
|
-
return dir;
|
|
1494
|
-
}
|
|
1495
|
-
function packagedMcpStdioPath() {
|
|
1496
|
-
const dir = packagedMcpDir();
|
|
1497
|
-
return dir ? join2(dir, "core-dist", "mcp", "run-stdio.js") : null;
|
|
1498
|
-
}
|
|
1499
|
-
function packagedBundledNodePath() {
|
|
1500
|
-
const resources = electronResourcesPath();
|
|
1501
|
-
if (!resources) return null;
|
|
1502
|
-
const bin = join2(resources, "node", "bin", "node");
|
|
1503
|
-
if (!existsSync3(bin)) return null;
|
|
1504
|
-
return bin;
|
|
1505
|
-
}
|
|
1506
|
-
function packagedCursorRipgrepCandidate(platformPkg, binName) {
|
|
1507
|
-
const dir = packagedCursorRuntimeDir();
|
|
1508
|
-
if (!dir) return null;
|
|
1509
|
-
return join2(dir, "node_modules", platformPkg, "bin", binName);
|
|
1510
|
-
}
|
|
1511
|
-
|
|
1512
|
-
// src/agents/node-launch.ts
|
|
1513
|
-
var AGENT_RUNNER_MAX_OLD_SPACE_MB = 8192;
|
|
1514
|
-
var MAX_OLD_SPACE_FLAG = /(?:^|\s)(--max[-_]old[-_]space[-_]size)(?:[= ](\d+))?(?=\s|$)/;
|
|
1515
|
-
function withMaxOldSpaceSize(nodeOptions, heapMb) {
|
|
1516
|
-
const existing = (nodeOptions ?? "").trim();
|
|
1517
|
-
const match = MAX_OLD_SPACE_FLAG.exec(existing);
|
|
1518
|
-
if (match) {
|
|
1519
|
-
const current = match[2] ? Number(match[2]) : 0;
|
|
1520
|
-
if (Number.isFinite(current) && current >= heapMb) return existing;
|
|
1521
|
-
return existing.replace(MAX_OLD_SPACE_FLAG, ` --max-old-space-size=${heapMb}`).trim();
|
|
1481
|
+
function toOpencodeMcpConfigContent(servers, opts) {
|
|
1482
|
+
const mcp = {};
|
|
1483
|
+
for (const s of servers) {
|
|
1484
|
+
const env = mcpSpawnEnv(s.env);
|
|
1485
|
+
mcp[s.name] = {
|
|
1486
|
+
type: "local",
|
|
1487
|
+
command: [s.command, ...s.args ?? []],
|
|
1488
|
+
enabled: true,
|
|
1489
|
+
...env ? { environment: env } : {}
|
|
1490
|
+
};
|
|
1522
1491
|
}
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
);
|
|
1530
|
-
applySystemCaEnv(env);
|
|
1531
|
-
}
|
|
1532
|
-
function envWithAgentHeap(env) {
|
|
1533
|
-
const next = { ...env };
|
|
1534
|
-
applyAgentRunnerHeapEnv(next);
|
|
1535
|
-
return next;
|
|
1492
|
+
for (const name of opts?.disableNames ?? []) {
|
|
1493
|
+
const key = name.trim();
|
|
1494
|
+
if (!key || mcp[key]?.enabled === true) continue;
|
|
1495
|
+
mcp[key] = { ...mcp[key], enabled: false };
|
|
1496
|
+
}
|
|
1497
|
+
return JSON.stringify({ mcp });
|
|
1536
1498
|
}
|
|
1537
|
-
function
|
|
1538
|
-
if (
|
|
1539
|
-
|
|
1499
|
+
function writeMcpServersConfig(servers) {
|
|
1500
|
+
if (servers.length === 0) return null;
|
|
1501
|
+
const mcpServers = {};
|
|
1502
|
+
for (const s of servers) {
|
|
1503
|
+
const env = mcpSpawnEnv(s.env);
|
|
1504
|
+
mcpServers[s.name] = {
|
|
1505
|
+
command: s.command,
|
|
1506
|
+
...s.args ? { args: s.args } : {},
|
|
1507
|
+
...env ? { env } : {}
|
|
1508
|
+
};
|
|
1509
|
+
}
|
|
1510
|
+
const dir = mkdtempSync(join4(tmpdir(), "sideboard-mcp-"));
|
|
1511
|
+
const cfgPath = join4(dir, "mcp.json");
|
|
1512
|
+
writeFileSync2(cfgPath, JSON.stringify({ mcpServers }, null, 2));
|
|
1513
|
+
return cfgPath;
|
|
1540
1514
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
return existsSync4(unpacked) ? unpacked : null;
|
|
1515
|
+
|
|
1516
|
+
// src/agents/user-mcp-config.ts
|
|
1517
|
+
function userClaudeMcpConfigPath() {
|
|
1518
|
+
return join5(homedir2(), ".claude.json");
|
|
1546
1519
|
}
|
|
1547
|
-
|
|
1548
|
-
|
|
1520
|
+
|
|
1521
|
+
// src/agents/orch-mcp-isolation.ts
|
|
1522
|
+
function isInjectedOrchMcpName(name) {
|
|
1523
|
+
const n = name.trim().toLowerCase();
|
|
1524
|
+
return n === "sideboard" || n === "brightsy" || n.startsWith("brightsy_");
|
|
1549
1525
|
}
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
if (!match) return null;
|
|
1554
|
-
const major = Number(match[1]);
|
|
1555
|
-
return Number.isInteger(major) ? major : null;
|
|
1526
|
+
function asObject(value) {
|
|
1527
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
1528
|
+
return value;
|
|
1556
1529
|
}
|
|
1557
|
-
function
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
score += major;
|
|
1567
|
-
}
|
|
1568
|
-
if (/\/Cellar\/node\/\d/.test(posix) && !/\/Cellar\/node@\d+/.test(posix)) {
|
|
1569
|
-
score -= 50;
|
|
1530
|
+
function listMcpNamesFromJsonMap(raw, key) {
|
|
1531
|
+
return Object.keys(asObject(asObject(raw)[key])).filter((n) => n.trim());
|
|
1532
|
+
}
|
|
1533
|
+
function listMcpNamesFromCodexToml(text) {
|
|
1534
|
+
try {
|
|
1535
|
+
const parsed = parseToml(text);
|
|
1536
|
+
return Object.keys(asObject(parsed.mcp_servers)).filter((n) => n.trim());
|
|
1537
|
+
} catch {
|
|
1538
|
+
return [];
|
|
1570
1539
|
}
|
|
1571
|
-
return score;
|
|
1572
1540
|
}
|
|
1573
|
-
function
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
if (score > bestScore) {
|
|
1579
|
-
bestScore = score;
|
|
1580
|
-
best = candidate;
|
|
1581
|
-
}
|
|
1541
|
+
function readJsonObject(path) {
|
|
1542
|
+
try {
|
|
1543
|
+
return JSON.parse(readFileSync3(path, "utf8"));
|
|
1544
|
+
} catch {
|
|
1545
|
+
return {};
|
|
1582
1546
|
}
|
|
1583
|
-
return best;
|
|
1584
1547
|
}
|
|
1585
|
-
function
|
|
1586
|
-
if (!existsSync4(root)) return [];
|
|
1548
|
+
function readText(path) {
|
|
1587
1549
|
try {
|
|
1588
|
-
return
|
|
1550
|
+
return readFileSync3(path, "utf8");
|
|
1589
1551
|
} catch {
|
|
1590
|
-
return
|
|
1552
|
+
return "";
|
|
1591
1553
|
}
|
|
1592
1554
|
}
|
|
1593
|
-
function
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1555
|
+
function userCodexConfigPaths(home = homedir3()) {
|
|
1556
|
+
return [join6(home, ".codex", "config.toml"), join6(home, ".config", "codex", "config.toml")];
|
|
1557
|
+
}
|
|
1558
|
+
function userOpencodeConfigPaths(home = homedir3()) {
|
|
1597
1559
|
return [
|
|
1598
|
-
|
|
1599
|
-
"
|
|
1600
|
-
"/usr/local/bin/node",
|
|
1601
|
-
join3(home, ".local/share/fnm/aliases/default/bin/node"),
|
|
1602
|
-
join3(home, ".nvm/current/bin/node"),
|
|
1603
|
-
join3(home, ".volta/bin/node"),
|
|
1604
|
-
join3(home, ".asdf/shims/node"),
|
|
1605
|
-
join3(home, ".local/share/mise/shims/node"),
|
|
1606
|
-
...versionDirNodeBins(
|
|
1607
|
-
join3(home, ".nvm", "versions", "node"),
|
|
1608
|
-
(name) => join3(home, ".nvm", "versions", "node", name, "bin", "node")
|
|
1609
|
-
),
|
|
1610
|
-
...versionDirNodeBins(
|
|
1611
|
-
join3(home, ".local/share/fnm", "node-versions"),
|
|
1612
|
-
(name) => join3(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
|
|
1613
|
-
),
|
|
1614
|
-
...versionDirNodeBins(
|
|
1615
|
-
join3(home, ".volta", "tools", "image", "node"),
|
|
1616
|
-
(name) => join3(home, ".volta", "tools", "image", "node", name, "bin", "node")
|
|
1617
|
-
)
|
|
1560
|
+
join6(home, ".config", "opencode", "opencode.json"),
|
|
1561
|
+
join6(home, ".config", "opencode", "opencode.jsonc")
|
|
1618
1562
|
];
|
|
1619
1563
|
}
|
|
1620
|
-
function
|
|
1621
|
-
const
|
|
1564
|
+
function userMcpNamesToDisable(opts) {
|
|
1565
|
+
const keep = new Set(
|
|
1566
|
+
[...opts.injectedNames ?? []].map((n) => n.trim().toLowerCase()).filter(Boolean)
|
|
1567
|
+
);
|
|
1622
1568
|
const out = [];
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
} catch {
|
|
1630
|
-
continue;
|
|
1631
|
-
}
|
|
1632
|
-
if (seen.has(key)) continue;
|
|
1569
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1570
|
+
for (const raw of opts.names) {
|
|
1571
|
+
const name = raw.trim();
|
|
1572
|
+
if (!name) continue;
|
|
1573
|
+
const key = name.toLowerCase();
|
|
1574
|
+
if (seen.has(key) || keep.has(key) || isInjectedOrchMcpName(name)) continue;
|
|
1633
1575
|
seen.add(key);
|
|
1634
|
-
out.push(
|
|
1576
|
+
out.push(name);
|
|
1635
1577
|
}
|
|
1636
1578
|
return out;
|
|
1637
1579
|
}
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
if (
|
|
1642
|
-
|
|
1580
|
+
function listUserCodexMcpNames(home = homedir3()) {
|
|
1581
|
+
const names = [];
|
|
1582
|
+
for (const path of userCodexConfigPaths(home)) {
|
|
1583
|
+
if (!existsSync7(path)) continue;
|
|
1584
|
+
names.push(...listMcpNamesFromCodexToml(readText(path)));
|
|
1643
1585
|
}
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1586
|
+
return names;
|
|
1587
|
+
}
|
|
1588
|
+
function listUserOpencodeMcpNames(home = homedir3()) {
|
|
1589
|
+
const names = [];
|
|
1590
|
+
for (const path of userOpencodeConfigPaths(home)) {
|
|
1591
|
+
if (!existsSync7(path)) continue;
|
|
1592
|
+
names.push(...listMcpNamesFromJsonMap(readJsonObject(path), "mcp"));
|
|
1593
|
+
}
|
|
1594
|
+
return names;
|
|
1595
|
+
}
|
|
1596
|
+
function listUserClaudeMcpNames(home = homedir3()) {
|
|
1597
|
+
const claudePath = home === homedir3() ? userClaudeMcpConfigPath() : join6(home, ".claude.json");
|
|
1598
|
+
if (!existsSync7(claudePath)) return [];
|
|
1599
|
+
return listMcpNamesFromJsonMap(readJsonObject(claudePath), "mcpServers");
|
|
1600
|
+
}
|
|
1601
|
+
function toCodexDisableUserMcpArgs(names) {
|
|
1602
|
+
const args = [];
|
|
1603
|
+
for (const name of names) {
|
|
1604
|
+
if (!/^[A-Za-z0-9_-]+$/.test(name)) continue;
|
|
1605
|
+
args.push("-c", `mcp_servers.${name}.enabled=false`);
|
|
1606
|
+
}
|
|
1607
|
+
return args;
|
|
1608
|
+
}
|
|
1609
|
+
function toCodexUnattendedAppsArgs() {
|
|
1610
|
+
return [
|
|
1611
|
+
"-c",
|
|
1612
|
+
"features.apps=false",
|
|
1613
|
+
"-c",
|
|
1614
|
+
"apps._default.enabled=false",
|
|
1615
|
+
"-c",
|
|
1616
|
+
"apps.posthog.enabled=false",
|
|
1617
|
+
"-c",
|
|
1618
|
+
"features.plugins=false"
|
|
1619
|
+
];
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
// src/agents/message-parts.ts
|
|
1623
|
+
function asRecord(input) {
|
|
1624
|
+
if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
1625
|
+
return input;
|
|
1626
|
+
}
|
|
1627
|
+
return void 0;
|
|
1628
|
+
}
|
|
1629
|
+
function str(v) {
|
|
1630
|
+
return typeof v === "string" && v.trim() ? v : void 0;
|
|
1631
|
+
}
|
|
1632
|
+
var CHAT_DETAIL_MAX = 72;
|
|
1633
|
+
function clipChatLine(value, max = CHAT_DETAIL_MAX) {
|
|
1634
|
+
const line = value.trim().split(/\r?\n/, 1)[0] ?? "";
|
|
1635
|
+
if (line.length <= max) return line;
|
|
1636
|
+
return `${line.slice(0, Math.max(1, max - 1))}\u2026`;
|
|
1637
|
+
}
|
|
1638
|
+
function toolDetail(name, input) {
|
|
1639
|
+
if (!input) return void 0;
|
|
1640
|
+
const command = str(input.command) ?? str(input.cmd);
|
|
1641
|
+
if (command) return clipChatLine(command);
|
|
1642
|
+
const pattern = str(input.pattern) ?? str(input.glob) ?? str(input.glob_pattern);
|
|
1643
|
+
const isSearch = /grep|glob|search|ripgrep|findfiles|semsearch/i.test(name);
|
|
1644
|
+
if (isSearch && pattern) {
|
|
1645
|
+
return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
|
|
1646
|
+
}
|
|
1647
|
+
const path = str(input.file_path) ?? str(input.path) ?? str(input.filePath) ?? str(input.filename);
|
|
1648
|
+
if (path) return path;
|
|
1649
|
+
if (pattern) return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
|
|
1650
|
+
const query = str(input.query) ?? str(input.prompt);
|
|
1651
|
+
if (query) return query.length > 80 ? `${query.slice(0, 77)}\u2026` : query;
|
|
1652
|
+
try {
|
|
1653
|
+
const raw = JSON.stringify(input);
|
|
1654
|
+
return raw.length > 80 ? `${raw.slice(0, 77)}\u2026` : raw;
|
|
1655
|
+
} catch {
|
|
1656
|
+
return name;
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
function toolDescription(name, input) {
|
|
1660
|
+
const n = name.replace(/^mcp__/, "").replace(/__/g, " \xB7 ");
|
|
1661
|
+
if (/^get_record_types$|recordTypes/i.test(name)) return "List record types";
|
|
1662
|
+
if (/connectedAgentRequest/i.test(name)) {
|
|
1663
|
+
return str(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
|
|
1664
|
+
}
|
|
1665
|
+
if (/present_artifact$/i.test(name)) {
|
|
1666
|
+
return str(input?.title) ? `Present ${str(input?.title)}` : "Present artifact";
|
|
1667
|
+
}
|
|
1668
|
+
if (/present_plan$/i.test(name)) {
|
|
1669
|
+
return str(input?.title) ? `Plan ${str(input?.title)}` : "Present plan";
|
|
1670
|
+
}
|
|
1671
|
+
if (/present_schema$/i.test(name)) {
|
|
1672
|
+
return str(input?.title) ? `Schema ${str(input?.title)}` : "Present schema";
|
|
1673
|
+
}
|
|
1674
|
+
if (/present_files$/i.test(name)) {
|
|
1675
|
+
return str(input?.title) ? `Files ${str(input?.title)}` : "Present files";
|
|
1676
|
+
}
|
|
1677
|
+
if (/wait_for_job$/i.test(name)) {
|
|
1678
|
+
return str(input?.id) ? `Wait for ${str(input?.id)}` : "Wait for job";
|
|
1679
|
+
}
|
|
1680
|
+
if (/stop_job$/i.test(name)) {
|
|
1681
|
+
return str(input?.id) ? `Stop ${str(input?.id)}` : "Stop job";
|
|
1682
|
+
}
|
|
1683
|
+
if (isSubagentToolName(name)) {
|
|
1684
|
+
const desc = str(input?.description);
|
|
1685
|
+
const sub = asRecord(input?.subagentType);
|
|
1686
|
+
const kind = str(sub?.name) ?? str(sub?.kind) ?? str(input?.subagent_type) ?? str(input?.subagentType);
|
|
1687
|
+
if (/^spawn_agent$/i.test(name)) {
|
|
1688
|
+
return str(input?.prompt) ?? desc ?? "Subagent";
|
|
1689
|
+
}
|
|
1690
|
+
if (/connectedAgentRequest/i.test(name)) {
|
|
1691
|
+
return str(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
|
|
1692
|
+
}
|
|
1693
|
+
if (desc && kind) return `${kind}: ${desc}${subagentLiveSuffix(input)}`;
|
|
1694
|
+
if (desc) return `${desc}${subagentLiveSuffix(input)}`;
|
|
1695
|
+
return `Subagent${subagentLiveSuffix(input)}`;
|
|
1696
|
+
}
|
|
1697
|
+
if (/^(create|update)_artifact$/i.test(name.replace(/^mcp__[^_]+__/, ""))) {
|
|
1698
|
+
return str(input?.title) ? `Artifact ${str(input?.title)}` : "Artifact";
|
|
1699
|
+
}
|
|
1700
|
+
if (!input) return n;
|
|
1701
|
+
if (/bash|shell|terminal/i.test(name) && str(input.command)) {
|
|
1702
|
+
const cmd = str(input.command);
|
|
1703
|
+
if (/git\s+fetch/i.test(cmd)) return "Fetch latest from origin and check status";
|
|
1704
|
+
if (/git\s+status/i.test(cmd)) return "Check git status";
|
|
1705
|
+
if (/git\s+log/i.test(cmd)) return "Inspect recent commits";
|
|
1706
|
+
if (/git\s+branch/i.test(cmd)) return "List branches";
|
|
1707
|
+
if (/grep|rg\b/i.test(cmd)) return "Search repository";
|
|
1708
|
+
return "Run shell command";
|
|
1709
|
+
}
|
|
1710
|
+
if (/edit|write|apply/i.test(name)) {
|
|
1711
|
+
const path = str(input.file_path) ?? str(input.path);
|
|
1712
|
+
return path ? `Edit ${path.split("/").pop()}` : "Edit file";
|
|
1713
|
+
}
|
|
1714
|
+
if (/read/i.test(name)) {
|
|
1715
|
+
const path = str(input.file_path) ?? str(input.path);
|
|
1716
|
+
return path ? `Read ${path.split("/").pop()}` : "Read file";
|
|
1717
|
+
}
|
|
1718
|
+
if (/grep/i.test(name)) return "Search files";
|
|
1719
|
+
if (/glob/i.test(name)) return "Find files";
|
|
1720
|
+
const compact = n.replace(/[_-]/g, "");
|
|
1721
|
+
if (/^taskoutput$/i.test(compact)) {
|
|
1722
|
+
return str(input.task_id) ? `Wait for ${str(input.task_id)}` : "Wait for background task";
|
|
1723
|
+
}
|
|
1724
|
+
if (/^taskstop$/i.test(compact)) {
|
|
1725
|
+
return str(input.task_id) ? `Stop ${str(input.task_id)}` : "Stop background task";
|
|
1726
|
+
}
|
|
1727
|
+
if (/^monitor$/i.test(compact)) {
|
|
1728
|
+
const command = str(input.command);
|
|
1729
|
+
return command ? `Watch ${command.length > 48 ? `${command.slice(0, 45)}\u2026` : command}` : "Watch command";
|
|
1730
|
+
}
|
|
1731
|
+
return n;
|
|
1732
|
+
}
|
|
1733
|
+
function subagentLiveSuffix(input) {
|
|
1734
|
+
if (!input) return "";
|
|
1735
|
+
const bits = [];
|
|
1736
|
+
const status = str(input.live_status);
|
|
1737
|
+
if (status && !/^runn(ing)?$|^working$/i.test(status)) bits.push(status);
|
|
1738
|
+
if (typeof input.live_tool_uses === "number") bits.push(`${input.live_tool_uses} tools`);
|
|
1739
|
+
if (typeof input.live_duration_ms === "number") {
|
|
1740
|
+
bits.push(`${Math.max(0, Math.round(Number(input.live_duration_ms) / 1e3))}s`);
|
|
1647
1741
|
}
|
|
1648
|
-
const
|
|
1649
|
-
if (
|
|
1650
|
-
return
|
|
1742
|
+
const last = str(input.live_last_tool);
|
|
1743
|
+
if (last) bits.push(last);
|
|
1744
|
+
return bits.length ? ` \xB7 ${bits.join(" \xB7 ")}` : "";
|
|
1651
1745
|
}
|
|
1652
|
-
|
|
1653
|
-
const
|
|
1654
|
-
if (
|
|
1655
|
-
|
|
1656
|
-
return version || null;
|
|
1746
|
+
function isSubagentToolName(name) {
|
|
1747
|
+
const n = (name ?? "").trim();
|
|
1748
|
+
if (/^(task|agent|spawn_agent)$/i.test(n)) return true;
|
|
1749
|
+
return /connectedAgentRequest/i.test(n);
|
|
1657
1750
|
}
|
|
1658
|
-
|
|
1659
|
-
const
|
|
1660
|
-
|
|
1661
|
-
if (
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
const version = await probeNodeVersion(path);
|
|
1665
|
-
return version ? { path, version } : null;
|
|
1666
|
-
})
|
|
1667
|
-
);
|
|
1668
|
-
return pickPreferredNode(probed.filter((c) => c != null));
|
|
1751
|
+
function isInternalAgentStatusText(text) {
|
|
1752
|
+
const t = text.trim();
|
|
1753
|
+
if (!t) return false;
|
|
1754
|
+
if (/waiting for gate to pass/i.test(t)) return true;
|
|
1755
|
+
if (/^agent is running\b/i.test(t) && t.length < 160) return true;
|
|
1756
|
+
return false;
|
|
1669
1757
|
}
|
|
1670
|
-
function
|
|
1671
|
-
const
|
|
1672
|
-
|
|
1673
|
-
return {
|
|
1674
|
-
file: launch.file,
|
|
1675
|
-
args: readableArgs,
|
|
1676
|
-
env: envWithAgentHeap(launch.env)
|
|
1677
|
-
};
|
|
1678
|
-
}
|
|
1679
|
-
const wrapped = wrapElectronAsNodeLaunch(launch.file, readableArgs);
|
|
1680
|
-
if (process.platform === "win32") {
|
|
1681
|
-
return {
|
|
1682
|
-
file: wrapped.file,
|
|
1683
|
-
args: wrapped.args,
|
|
1684
|
-
env: envWithAgentHeap(launch.env)
|
|
1685
|
-
};
|
|
1686
|
-
}
|
|
1687
|
-
const env = envWithAgentHeap(launch.env);
|
|
1688
|
-
delete env.ELECTRON_RUN_AS_NODE;
|
|
1689
|
-
return { file: wrapped.file, args: wrapped.args, env };
|
|
1758
|
+
function isPollWrapperToolName(name) {
|
|
1759
|
+
const n = (name ?? "").replace(/[_-]/g, "");
|
|
1760
|
+
return /^(taskoutput|taskstop|sleep)$/i.test(n);
|
|
1690
1761
|
}
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
const node = await findSystemNode();
|
|
1699
|
-
if (node) {
|
|
1700
|
-
return { file: node.path, env: {}, nodeVersion: node.version };
|
|
1701
|
-
}
|
|
1762
|
+
function lastTextPart(parts, type) {
|
|
1763
|
+
for (let i = parts.length - 1; i >= 0; i--) {
|
|
1764
|
+
const p = parts[i];
|
|
1765
|
+
if (p.type !== type) continue;
|
|
1766
|
+
const text = p.text.trim();
|
|
1767
|
+
if (!text || isInternalAgentStatusText(text)) continue;
|
|
1768
|
+
return text;
|
|
1702
1769
|
}
|
|
1703
|
-
return
|
|
1704
|
-
file: process.execPath,
|
|
1705
|
-
env: { ELECTRON_RUN_AS_NODE: "1" }
|
|
1706
|
-
};
|
|
1770
|
+
return "";
|
|
1707
1771
|
}
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
var SIDEBOARD_MCP_ALLOWED_TOOLS = [
|
|
1711
|
-
"mcp__sideboard",
|
|
1712
|
-
"mcp__sideboard__*"
|
|
1713
|
-
];
|
|
1714
|
-
var SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS = [
|
|
1715
|
-
"mcp__sideboard__present_artifact",
|
|
1716
|
-
"mcp__sideboard__present_schema",
|
|
1717
|
-
"mcp__sideboard__present_files",
|
|
1718
|
-
"mcp__sideboard__ask_user",
|
|
1719
|
-
"mcp__sideboard__present_plan",
|
|
1720
|
-
"mcp__sideboard__wait_for_job",
|
|
1721
|
-
"mcp__sideboard__stop_job",
|
|
1722
|
-
"mcp__sideboard__get_viewer_context",
|
|
1723
|
-
"mcp__sideboard__update_viewer_context"
|
|
1724
|
-
];
|
|
1725
|
-
var SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS = ["mcp__sideboard__github_*"];
|
|
1726
|
-
var SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS = ["mcp__sideboard__linear_*"];
|
|
1727
|
-
var SIDEBOARD_ABLETIME_MCP_ALLOWED_TOOLS = ["mcp__sideboard__abletime_*"];
|
|
1728
|
-
function sideboardWorktreeAllowedTools(opts) {
|
|
1729
|
-
const out = [...SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS];
|
|
1730
|
-
if (opts?.github !== false) out.push(...SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS);
|
|
1731
|
-
if (opts?.linear) out.push(...SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS);
|
|
1732
|
-
if (opts?.abletime) out.push(...SIDEBOARD_ABLETIME_MCP_ALLOWED_TOOLS);
|
|
1733
|
-
return out;
|
|
1772
|
+
function toolLabel(tool) {
|
|
1773
|
+
return tool.description || toolDescription(tool.name, tool.input) || tool.name;
|
|
1734
1774
|
}
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
if (brightsyMcpCommandCache && now - brightsyMcpCommandCache.at < 6e4 && brightsyMcpCommandCache.command) {
|
|
1739
|
-
return brightsyMcpCommandCache.command;
|
|
1775
|
+
function liveActivitySummary(parts, opts) {
|
|
1776
|
+
if (opts?.queued && parts.length === 0) {
|
|
1777
|
+
return "Queued \u2014 waiting for a slot";
|
|
1740
1778
|
}
|
|
1741
|
-
const
|
|
1742
|
-
const
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1779
|
+
const tools = parts.filter((p) => p.type === "tool");
|
|
1780
|
+
const runningSubs = tools.filter(
|
|
1781
|
+
(t) => t.status === "running" && !t.parentId && isSubagentToolName(t.name)
|
|
1782
|
+
);
|
|
1783
|
+
const runningNested = [...tools].reverse().find((t) => t.status === "running" && t.parentId && !isPollWrapperToolName(t.name));
|
|
1784
|
+
const runningTop = [...tools].reverse().find(
|
|
1785
|
+
(t) => t.status === "running" && !t.parentId && !isPollWrapperToolName(t.name) && !isSubagentToolName(t.name)
|
|
1786
|
+
);
|
|
1787
|
+
const runningPoll = [...tools].reverse().find((t) => t.status === "running" && isPollWrapperToolName(t.name));
|
|
1788
|
+
const thinking = lastTextPart(parts, "thinking");
|
|
1789
|
+
const text = lastTextPart(parts, "text");
|
|
1790
|
+
if (runningSubs.length > 0) {
|
|
1791
|
+
const heads = runningSubs.map(toolLabel);
|
|
1792
|
+
const head = runningSubs.length === 1 ? heads[0] : `${runningSubs.length} subagents \xB7 ${heads.slice(0, 2).join(" \xB7 ")}`;
|
|
1793
|
+
if (runningNested) return `${head} \xB7 ${toolLabel(runningNested)}`;
|
|
1794
|
+
return head;
|
|
1752
1795
|
}
|
|
1796
|
+
if (runningTop) return toolLabel(runningTop);
|
|
1797
|
+
if (runningPoll) return toolLabel(runningPoll);
|
|
1798
|
+
if (thinking) return thinking.length > 96 ? `\u2026${thinking.slice(-96)}` : thinking;
|
|
1799
|
+
if (text) return "Writing reply\u2026";
|
|
1800
|
+
const last = [...tools].reverse().find((t) => !isPollWrapperToolName(t.name)) ?? tools.at(-1);
|
|
1801
|
+
if (last) {
|
|
1802
|
+
const label = toolLabel(last);
|
|
1803
|
+
return last.status === "running" ? label : `Finished ${label}`;
|
|
1804
|
+
}
|
|
1805
|
+
return "Working\u2026";
|
|
1753
1806
|
}
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
}
|
|
1758
|
-
|
|
1759
|
-
const n = name.toLowerCase();
|
|
1760
|
-
return n === "brightsy" || n.startsWith("mcp__brightsy") || n.startsWith("brightsy_");
|
|
1807
|
+
function messagePartParentId(part) {
|
|
1808
|
+
if ("parentId" in part && typeof part.parentId === "string" && part.parentId.trim()) {
|
|
1809
|
+
return part.parentId;
|
|
1810
|
+
}
|
|
1811
|
+
return void 0;
|
|
1761
1812
|
}
|
|
1762
|
-
function
|
|
1763
|
-
|
|
1764
|
-
return typeof ds === "string" && ds.toLowerCase() === "brightsy";
|
|
1813
|
+
function sameParentId(a, b) {
|
|
1814
|
+
return (a ?? "") === (b ?? "");
|
|
1765
1815
|
}
|
|
1766
|
-
function
|
|
1767
|
-
if (
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
if (isBrightsyMcpToolName(part.name)) return true;
|
|
1771
|
-
if (/present_(schema|files)$/i.test(part.name) && toolInputUsesBrightsyDatasource(part.input)) {
|
|
1772
|
-
return true;
|
|
1773
|
-
}
|
|
1816
|
+
function withEventParentId(event, parentId) {
|
|
1817
|
+
if (!parentId) return event;
|
|
1818
|
+
if (event.type === "stdout" || event.type === "thinking" || event.type === "tool_use" || event.type === "tool_result") {
|
|
1819
|
+
return { ...event, parentId: event.parentId ?? parentId };
|
|
1774
1820
|
}
|
|
1775
|
-
return
|
|
1821
|
+
return event;
|
|
1776
1822
|
}
|
|
1777
|
-
function
|
|
1778
|
-
|
|
1823
|
+
function toolFilePath(input) {
|
|
1824
|
+
if (!input) return void 0;
|
|
1825
|
+
return str(input.file_path) ?? str(input.path) ?? str(input.filePath) ?? str(input.filename);
|
|
1779
1826
|
}
|
|
1780
|
-
function
|
|
1781
|
-
if (!
|
|
1782
|
-
|
|
1783
|
-
const alwaysOn = opts?.alwaysOnWorktree ?? Boolean(loadAppSettings().brightsy?.injectWorktreeMcp);
|
|
1784
|
-
if (alwaysOn) return true;
|
|
1785
|
-
return threadRequestsBrightsyMcp(thread);
|
|
1827
|
+
function countLines(text) {
|
|
1828
|
+
if (!text) return 0;
|
|
1829
|
+
return text.split("\n").length;
|
|
1786
1830
|
}
|
|
1787
|
-
function
|
|
1788
|
-
if (
|
|
1789
|
-
|
|
1831
|
+
function diffFromInput(input) {
|
|
1832
|
+
if (!input) return {};
|
|
1833
|
+
const oldS = str(input.old_string) ?? str(input.oldString);
|
|
1834
|
+
const newS = str(input.new_string) ?? str(input.newString) ?? str(input.content);
|
|
1835
|
+
if (oldS != null || newS != null) {
|
|
1836
|
+
return {
|
|
1837
|
+
additions: countLines(newS),
|
|
1838
|
+
deletions: countLines(oldS)
|
|
1839
|
+
};
|
|
1790
1840
|
}
|
|
1791
|
-
return {
|
|
1792
|
-
name,
|
|
1793
|
-
command: "npx",
|
|
1794
|
-
args: ["-y", "@brightsy/mcp-server"],
|
|
1795
|
-
...env ? { env } : {}
|
|
1796
|
-
};
|
|
1841
|
+
return {};
|
|
1797
1842
|
}
|
|
1798
|
-
function
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1843
|
+
function parseDiffStat(result) {
|
|
1844
|
+
if (!result) return {};
|
|
1845
|
+
const paired = result.match(/\+(\d+)\s+-(\d+)/);
|
|
1846
|
+
if (paired) {
|
|
1847
|
+
return {
|
|
1848
|
+
additions: Number(paired[1]),
|
|
1849
|
+
deletions: Number(paired[2])
|
|
1850
|
+
};
|
|
1851
|
+
}
|
|
1852
|
+
const verbose = result.match(
|
|
1853
|
+
/(\d+)\s+insertions?(?:,\s*(\d+)\s+deletions?)?/i
|
|
1854
|
+
);
|
|
1855
|
+
if (verbose) {
|
|
1856
|
+
return {
|
|
1857
|
+
additions: Number(verbose[1]),
|
|
1858
|
+
deletions: verbose[2] != null ? Number(verbose[2]) : void 0
|
|
1859
|
+
};
|
|
1860
|
+
}
|
|
1861
|
+
return {};
|
|
1862
|
+
}
|
|
1863
|
+
var THINKING_PART_MAX_CHARS = 64e3;
|
|
1864
|
+
function clipThinkingForStore(text, max = THINKING_PART_MAX_CHARS) {
|
|
1865
|
+
if (text.length <= max) return text;
|
|
1866
|
+
const marker = "\u2026(earlier thinking trimmed)\n";
|
|
1867
|
+
return marker + text.slice(text.length - Math.max(1, max - marker.length));
|
|
1868
|
+
}
|
|
1869
|
+
var STDOUT_EVENT_MAX_CHARS = 16e3;
|
|
1870
|
+
var STDERR_EVENT_MAX_CHARS = 4e3;
|
|
1871
|
+
function clipEventTail(text, max) {
|
|
1872
|
+
if (text.length <= max) return text;
|
|
1873
|
+
const marker = "\u2026(truncated)\n";
|
|
1874
|
+
return marker + text.slice(text.length - Math.max(1, max - marker.length));
|
|
1806
1875
|
}
|
|
1807
|
-
function
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1876
|
+
function clipAgentEventForPaint(event) {
|
|
1877
|
+
if (event.type === "tool_result" && event.content) {
|
|
1878
|
+
const content = clipToolResultForStore(event.content);
|
|
1879
|
+
if (content === event.content) return event;
|
|
1880
|
+
return { ...event, content };
|
|
1811
1881
|
}
|
|
1812
|
-
|
|
1813
|
-
}
|
|
1814
|
-
function corePackageDir() {
|
|
1815
|
-
const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
|
|
1816
|
-
if (cjsDir) return cjsDir;
|
|
1817
|
-
try {
|
|
1818
|
-
const url = import.meta.url;
|
|
1819
|
-
if (typeof url === "string" && url.length > 0) {
|
|
1820
|
-
return dirname2(fileURLToPath(url));
|
|
1821
|
-
}
|
|
1822
|
-
} catch {
|
|
1882
|
+
if (event.type === "thinking" && event.data.length > THINKING_PART_MAX_CHARS) {
|
|
1883
|
+
return { ...event, data: clipThinkingForStore(event.data) };
|
|
1823
1884
|
}
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
return
|
|
1885
|
+
if (event.type === "stdout" && event.data.length > STDOUT_EVENT_MAX_CHARS) {
|
|
1886
|
+
return { ...event, data: clipEventTail(event.data, STDOUT_EVENT_MAX_CHARS) };
|
|
1887
|
+
}
|
|
1888
|
+
if (event.type === "stderr" && event.data.length > STDERR_EVENT_MAX_CHARS) {
|
|
1889
|
+
return { ...event, data: clipEventTail(event.data, STDERR_EVENT_MAX_CHARS) };
|
|
1829
1890
|
}
|
|
1891
|
+
return event;
|
|
1830
1892
|
}
|
|
1831
|
-
function
|
|
1832
|
-
const
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
const
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1893
|
+
function withPartTimes(next, prev) {
|
|
1894
|
+
const now = Date.now();
|
|
1895
|
+
const startedAt = prev && typeof prev.startedAt === "number" ? prev.startedAt : now;
|
|
1896
|
+
return { ...next, startedAt, updatedAt: now };
|
|
1897
|
+
}
|
|
1898
|
+
function applyAgentEvent(parts, event) {
|
|
1899
|
+
if (event.type === "stdout") {
|
|
1900
|
+
const data = event.data;
|
|
1901
|
+
if (!data) return parts;
|
|
1902
|
+
const next = [...parts];
|
|
1903
|
+
const last = next[next.length - 1];
|
|
1904
|
+
if (last?.type === "text" && sameParentId(last.parentId, event.parentId)) {
|
|
1905
|
+
next[next.length - 1] = withPartTimes(
|
|
1906
|
+
{
|
|
1907
|
+
type: "text",
|
|
1908
|
+
text: last.text + data,
|
|
1909
|
+
...event.parentId ? { parentId: event.parentId } : {}
|
|
1910
|
+
},
|
|
1911
|
+
last
|
|
1912
|
+
);
|
|
1913
|
+
} else {
|
|
1914
|
+
next.push(
|
|
1915
|
+
withPartTimes({
|
|
1916
|
+
type: "text",
|
|
1917
|
+
text: data,
|
|
1918
|
+
...event.parentId ? { parentId: event.parentId } : {}
|
|
1919
|
+
})
|
|
1920
|
+
);
|
|
1849
1921
|
}
|
|
1850
|
-
|
|
1851
|
-
if (parent === dir) break;
|
|
1852
|
-
dir = parent;
|
|
1922
|
+
return next;
|
|
1853
1923
|
}
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1924
|
+
if (event.type === "thinking") {
|
|
1925
|
+
const data = event.data;
|
|
1926
|
+
if (!data) return parts;
|
|
1927
|
+
const next = [...parts];
|
|
1928
|
+
if (event.replace) {
|
|
1929
|
+
for (let i = next.length - 1; i >= 0; i--) {
|
|
1930
|
+
const prev = next[i];
|
|
1931
|
+
if (prev?.type === "thinking" && sameParentId(prev.parentId, event.parentId)) {
|
|
1932
|
+
next[i] = withPartTimes(
|
|
1933
|
+
{
|
|
1934
|
+
type: "thinking",
|
|
1935
|
+
text: clipThinkingForStore(data),
|
|
1936
|
+
...event.parentId ? { parentId: event.parentId } : {}
|
|
1937
|
+
},
|
|
1938
|
+
prev
|
|
1939
|
+
);
|
|
1940
|
+
return next;
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
next.push(
|
|
1944
|
+
withPartTimes({
|
|
1945
|
+
type: "thinking",
|
|
1946
|
+
text: clipThinkingForStore(data),
|
|
1947
|
+
...event.parentId ? { parentId: event.parentId } : {}
|
|
1948
|
+
})
|
|
1949
|
+
);
|
|
1950
|
+
return next;
|
|
1951
|
+
}
|
|
1952
|
+
const last = next[next.length - 1];
|
|
1953
|
+
if (last?.type === "thinking" && sameParentId(last.parentId, event.parentId)) {
|
|
1954
|
+
next[next.length - 1] = withPartTimes(
|
|
1955
|
+
{
|
|
1956
|
+
type: "thinking",
|
|
1957
|
+
text: clipThinkingForStore(last.text + data),
|
|
1958
|
+
...event.parentId ? { parentId: event.parentId } : {}
|
|
1959
|
+
},
|
|
1960
|
+
last
|
|
1961
|
+
);
|
|
1962
|
+
} else {
|
|
1963
|
+
next.push(
|
|
1964
|
+
withPartTimes({
|
|
1965
|
+
type: "thinking",
|
|
1966
|
+
text: clipThinkingForStore(data),
|
|
1967
|
+
...event.parentId ? { parentId: event.parentId } : {}
|
|
1968
|
+
})
|
|
1969
|
+
);
|
|
1869
1970
|
}
|
|
1971
|
+
return next;
|
|
1870
1972
|
}
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1973
|
+
if (event.type === "tool_use") {
|
|
1974
|
+
const input = asRecord(event.input);
|
|
1975
|
+
const diff = diffFromInput(input);
|
|
1976
|
+
const existing = parts.findIndex((p) => p.type === "tool" && p.id === event.id);
|
|
1977
|
+
if (existing >= 0) {
|
|
1978
|
+
const prev = parts[existing];
|
|
1979
|
+
const next = [...parts];
|
|
1980
|
+
const mergedInput = {
|
|
1981
|
+
...prev.input ?? {},
|
|
1982
|
+
...input ?? {}
|
|
1983
|
+
};
|
|
1984
|
+
const mergedRecord = Object.keys(mergedInput).length > 0 ? mergedInput : void 0;
|
|
1985
|
+
next[existing] = withPartTimes(
|
|
1986
|
+
{
|
|
1987
|
+
...prev,
|
|
1988
|
+
name: event.name || prev.name,
|
|
1989
|
+
input: mergedRecord,
|
|
1990
|
+
description: toolDescription(event.name || prev.name, mergedRecord),
|
|
1991
|
+
detail: toolDetail(event.name || prev.name, mergedRecord) ?? prev.detail,
|
|
1992
|
+
filePath: toolFilePath(mergedRecord) ?? prev.filePath,
|
|
1993
|
+
additions: diff.additions ?? prev.additions,
|
|
1994
|
+
deletions: diff.deletions ?? prev.deletions,
|
|
1995
|
+
parentId: event.parentId ?? prev.parentId
|
|
1996
|
+
},
|
|
1997
|
+
prev
|
|
1998
|
+
);
|
|
1999
|
+
return next;
|
|
2000
|
+
}
|
|
2001
|
+
return [
|
|
2002
|
+
...parts,
|
|
2003
|
+
withPartTimes({
|
|
2004
|
+
type: "tool",
|
|
2005
|
+
id: event.id,
|
|
2006
|
+
name: event.name,
|
|
2007
|
+
input,
|
|
2008
|
+
description: toolDescription(event.name, input),
|
|
2009
|
+
detail: toolDetail(event.name, input),
|
|
2010
|
+
status: "running",
|
|
2011
|
+
filePath: toolFilePath(input),
|
|
2012
|
+
...event.parentId ? { parentId: event.parentId } : {},
|
|
2013
|
+
...diff
|
|
2014
|
+
})
|
|
2015
|
+
];
|
|
1874
2016
|
}
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
2017
|
+
if (event.type === "tool_result") {
|
|
2018
|
+
const existing = parts.findIndex((p) => p.type === "tool" && p.id === event.id);
|
|
2019
|
+
const fromResult = parseDiffStat(event.content);
|
|
2020
|
+
if (event.partial) {
|
|
2021
|
+
if (existing < 0) {
|
|
2022
|
+
return [
|
|
2023
|
+
...parts,
|
|
2024
|
+
withPartTimes({
|
|
2025
|
+
type: "tool",
|
|
2026
|
+
id: event.id,
|
|
2027
|
+
name: "tool",
|
|
2028
|
+
description: "tool",
|
|
2029
|
+
status: event.isError ? "error" : "running",
|
|
2030
|
+
result: clipToolResultForStore(event.content),
|
|
2031
|
+
...event.parentId ? { parentId: event.parentId } : {}
|
|
2032
|
+
})
|
|
2033
|
+
];
|
|
2034
|
+
}
|
|
2035
|
+
return parts.map((p, i) => {
|
|
2036
|
+
if (i !== existing || p.type !== "tool") return p;
|
|
2037
|
+
if (p.status === "done" || p.status === "error") return p;
|
|
2038
|
+
return withPartTimes(
|
|
2039
|
+
{
|
|
2040
|
+
...p,
|
|
2041
|
+
result: clipToolResultForStore(event.content) ?? p.result
|
|
2042
|
+
},
|
|
2043
|
+
p
|
|
2044
|
+
);
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
2047
|
+
if (existing < 0) {
|
|
2048
|
+
return [
|
|
2049
|
+
...parts,
|
|
2050
|
+
withPartTimes({
|
|
2051
|
+
type: "tool",
|
|
2052
|
+
id: event.id,
|
|
2053
|
+
name: "tool",
|
|
2054
|
+
description: "tool",
|
|
2055
|
+
status: event.isError ? "error" : "done",
|
|
2056
|
+
result: clipToolResultForStore(event.content),
|
|
2057
|
+
...event.parentId ? { parentId: event.parentId } : {},
|
|
2058
|
+
...fromResult.additions != null ? { additions: fromResult.additions } : {},
|
|
2059
|
+
...fromResult.deletions != null ? { deletions: fromResult.deletions } : {}
|
|
2060
|
+
})
|
|
2061
|
+
];
|
|
1890
2062
|
}
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
2063
|
+
return parts.map((p, i) => {
|
|
2064
|
+
if (i !== existing || p.type !== "tool") return p;
|
|
2065
|
+
return withPartTimes(
|
|
2066
|
+
{
|
|
2067
|
+
...p,
|
|
2068
|
+
status: event.isError ? "error" : "done",
|
|
2069
|
+
result: clipToolResultForStore(event.content),
|
|
2070
|
+
...fromResult.additions != null ? { additions: fromResult.additions } : {},
|
|
2071
|
+
...fromResult.deletions != null ? { deletions: fromResult.deletions } : {}
|
|
2072
|
+
},
|
|
2073
|
+
p
|
|
1895
2074
|
);
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
applyAgentRunnerHeapEnv(sideboard.env);
|
|
1899
|
-
servers.push(sideboard);
|
|
1900
|
-
}
|
|
1901
|
-
if (opts.includeBrightsy && isBrightsyConnected()) {
|
|
1902
|
-
const cmd = await resolveBrightsyMcpCommand();
|
|
1903
|
-
const teams = await ensureConnectedBrightsyTeamTokens();
|
|
1904
|
-
if (teams.length > 0) {
|
|
1905
|
-
const used = /* @__PURE__ */ new Set();
|
|
1906
|
-
for (const team of teams) {
|
|
1907
|
-
let name = brightsyMcpServerName(team.slug);
|
|
1908
|
-
if (used.has(name)) name = `${name}_${team.id.slice(0, 8)}`;
|
|
1909
|
-
used.add(name);
|
|
1910
|
-
servers.push(mcpLaunch(cmd, name, teamEnv(team)));
|
|
1911
|
-
}
|
|
1912
|
-
} else {
|
|
1913
|
-
servers.push(mcpLaunch(cmd, "brightsy"));
|
|
1914
|
-
}
|
|
1915
|
-
}
|
|
1916
|
-
return servers;
|
|
1917
|
-
}
|
|
1918
|
-
function cursorSafeMcpLaunch(command, args) {
|
|
1919
|
-
if (process.platform === "win32") {
|
|
1920
|
-
return args && args.length > 0 ? { command, args } : { command };
|
|
2075
|
+
});
|
|
1921
2076
|
}
|
|
1922
|
-
|
|
1923
|
-
const file = unwrapped?.file ?? command;
|
|
1924
|
-
const fileArgs = unwrapped?.args ?? args ?? [];
|
|
1925
|
-
return fileArgs.length > 0 ? { command: file, args: fileArgs } : { command: file };
|
|
2077
|
+
return parts;
|
|
1926
2078
|
}
|
|
1927
|
-
function
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
delete out.ELECTRON_RUN_AS_NODE;
|
|
1932
|
-
return Object.keys(out).length > 0 ? out : void 0;
|
|
2079
|
+
function partsToAssistantText(parts) {
|
|
2080
|
+
return parts.filter(
|
|
2081
|
+
(p) => p.type === "text" && !messagePartParentId(p)
|
|
2082
|
+
).map((p) => p.text).join("").trim();
|
|
1933
2083
|
}
|
|
1934
|
-
function
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
...env ? { env } : {}
|
|
1944
|
-
};
|
|
1945
|
-
}
|
|
1946
|
-
return out;
|
|
2084
|
+
function stripBrightsyNdjsonNoise(text) {
|
|
2085
|
+
if (!text || !text.includes('"type"')) return text;
|
|
2086
|
+
let out = text;
|
|
2087
|
+
out = out.replace(
|
|
2088
|
+
/\{"type":"(?:tool_use|tool_result|tool|thinking|usage|done|error)"[\s\S]*?\}\s*(?=\{"type":"|$|(?=[A-Za-z*#]))/g,
|
|
2089
|
+
""
|
|
2090
|
+
);
|
|
2091
|
+
out = out.replace(/\{"type":"(?:tool_use|tool_result|tool)"[\s\S]*$/g, "");
|
|
2092
|
+
return out.trim();
|
|
1947
2093
|
}
|
|
1948
|
-
function
|
|
1949
|
-
const
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
args.push("-c", `${prefix}.command=${JSON.stringify(s.command)}`);
|
|
1953
|
-
if (s.args?.length) {
|
|
1954
|
-
args.push("-c", `${prefix}.args=${JSON.stringify(s.args)}`);
|
|
1955
|
-
}
|
|
1956
|
-
const env = mcpSpawnEnv(s.env);
|
|
1957
|
-
if (env) {
|
|
1958
|
-
for (const [key, value] of Object.entries(env)) {
|
|
1959
|
-
args.push("-c", `${prefix}.env.${key}=${JSON.stringify(value)}`);
|
|
1960
|
-
}
|
|
1961
|
-
}
|
|
1962
|
-
args.push("-c", `${prefix}.default_tools_approval_mode=${JSON.stringify("approve")}`);
|
|
1963
|
-
args.push("-c", `${prefix}.tool_timeout_sec=300`);
|
|
1964
|
-
args.push("-c", `${prefix}.startup_timeout_sec=30`);
|
|
1965
|
-
}
|
|
1966
|
-
return args;
|
|
2094
|
+
function isBrightsyNdjsonLine(line) {
|
|
2095
|
+
const t = line.trim();
|
|
2096
|
+
if (!t.startsWith("{")) return false;
|
|
2097
|
+
return /"type"\s*:\s*"(tool_use|tool_result|tool|thinking|usage|done|error|text)"/.test(t);
|
|
1967
2098
|
}
|
|
1968
|
-
function
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
mcp[s.name] = {
|
|
1973
|
-
type: "local",
|
|
1974
|
-
command: [s.command, ...s.args ?? []],
|
|
1975
|
-
enabled: true,
|
|
1976
|
-
...env ? { environment: env } : {}
|
|
1977
|
-
};
|
|
1978
|
-
}
|
|
1979
|
-
for (const name of opts?.disableNames ?? []) {
|
|
1980
|
-
const key = name.trim();
|
|
1981
|
-
if (!key || mcp[key]?.enabled === true) continue;
|
|
1982
|
-
mcp[key] = { ...mcp[key], enabled: false };
|
|
1983
|
-
}
|
|
1984
|
-
return JSON.stringify({ mcp });
|
|
2099
|
+
function finalizeParts(parts) {
|
|
2100
|
+
return parts.map(
|
|
2101
|
+
(p) => p.type === "tool" && p.status === "running" ? { ...p, status: "done" } : p
|
|
2102
|
+
);
|
|
1985
2103
|
}
|
|
1986
|
-
function
|
|
1987
|
-
if (
|
|
1988
|
-
|
|
1989
|
-
for (const s of servers) {
|
|
1990
|
-
const env = mcpSpawnEnv(s.env);
|
|
1991
|
-
mcpServers[s.name] = {
|
|
1992
|
-
command: s.command,
|
|
1993
|
-
...s.args ? { args: s.args } : {},
|
|
1994
|
-
...env ? { env } : {}
|
|
1995
|
-
};
|
|
1996
|
-
}
|
|
1997
|
-
const dir = mkdtempSync(join4(tmpdir(), "sideboard-mcp-"));
|
|
1998
|
-
const cfgPath = join4(dir, "mcp.json");
|
|
1999
|
-
writeFileSync2(cfgPath, JSON.stringify({ mcpServers }, null, 2));
|
|
2000
|
-
return cfgPath;
|
|
2104
|
+
function normalizeParseResult(parsed) {
|
|
2105
|
+
if (!parsed) return [];
|
|
2106
|
+
return Array.isArray(parsed) ? parsed : [parsed];
|
|
2001
2107
|
}
|
|
2002
2108
|
|
|
2003
2109
|
// src/agents/types.ts
|
|
@@ -2061,24 +2167,15 @@ var BASE_ALLOWED_TOOLS = [
|
|
|
2061
2167
|
"Skill"
|
|
2062
2168
|
];
|
|
2063
2169
|
var CLAUDE_PRINT_BG_WAIT_CEILING_MS = 72e5;
|
|
2170
|
+
function isLocalDevAppDataDir(dir = process.env.SIDEBOARD_APP_DATA) {
|
|
2171
|
+
return /[/\\]\.sideboard[/\\]dev-app-data(?:[/\\]|$)/.test(dir ?? "");
|
|
2172
|
+
}
|
|
2064
2173
|
var CLAUDE_CHROME_ALLOWED_TOOLS = [
|
|
2065
2174
|
"mcp__claude-in-chrome",
|
|
2066
2175
|
"mcp__claude-in-chrome__*",
|
|
2067
2176
|
"Skill(claude-in-chrome)"
|
|
2068
2177
|
];
|
|
2069
2178
|
var CLAUDE_PROMPT_ARG_MAX = 2e5;
|
|
2070
|
-
var mcpListCache = null;
|
|
2071
|
-
async function loadMcpServers() {
|
|
2072
|
-
if (mcpListCache && Date.now() - mcpListCache.at < 3e4) {
|
|
2073
|
-
return mcpListCache.servers;
|
|
2074
|
-
}
|
|
2075
|
-
const claude = resolveClaudeExecutable();
|
|
2076
|
-
const mcpText = await run(claude, ["mcp", "list"], { reject: false });
|
|
2077
|
-
const servers = parseMcpList(`${mcpText.stdout}
|
|
2078
|
-
${mcpText.stderr}`);
|
|
2079
|
-
mcpListCache = { at: Date.now(), servers };
|
|
2080
|
-
return servers;
|
|
2081
|
-
}
|
|
2082
2179
|
function usageFromClaude(usage) {
|
|
2083
2180
|
if (!usage) return null;
|
|
2084
2181
|
const inputTokens = Number(usage.input_tokens ?? 0);
|
|
@@ -2365,7 +2462,7 @@ var claudeAdapter = {
|
|
|
2365
2462
|
async detect() {
|
|
2366
2463
|
const claude = resolveClaudeExecutable();
|
|
2367
2464
|
if (claude !== "claude") {
|
|
2368
|
-
if (!
|
|
2465
|
+
if (!existsSync8(claude)) {
|
|
2369
2466
|
return {
|
|
2370
2467
|
agent: "claude",
|
|
2371
2468
|
installed: false,
|
|
@@ -2414,7 +2511,7 @@ var claudeAdapter = {
|
|
|
2414
2511
|
);
|
|
2415
2512
|
}
|
|
2416
2513
|
const mode = permissionMode(thread);
|
|
2417
|
-
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-
|
|
2514
|
+
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-XPTFHMKL.js");
|
|
2418
2515
|
const isOrchestrator = isOrchestratorThread2(thread);
|
|
2419
2516
|
const injectedServers = await buildInjectedMcpServers({
|
|
2420
2517
|
includeSideboard: true,
|
|
@@ -2433,10 +2530,9 @@ var claudeAdapter = {
|
|
|
2433
2530
|
...brightsyMcpAllowedTools(injectedBrightsyNames)
|
|
2434
2531
|
];
|
|
2435
2532
|
} else {
|
|
2436
|
-
const servers = await loadMcpServers();
|
|
2437
2533
|
allowedTools = [
|
|
2438
2534
|
...BASE_ALLOWED_TOOLS,
|
|
2439
|
-
...
|
|
2535
|
+
...mcpAllowToolsFromNames(userMcpNamesToDisable({ names: listUserClaudeMcpNames() })),
|
|
2440
2536
|
...sideboardWorktreeAllowedTools({
|
|
2441
2537
|
github: true,
|
|
2442
2538
|
linear: isLinearConnected(),
|
|
@@ -2464,9 +2560,7 @@ var claudeAdapter = {
|
|
|
2464
2560
|
const mcpConfigPath = writeMcpServersConfig(injectedServers);
|
|
2465
2561
|
if (mcpConfigPath) {
|
|
2466
2562
|
args.push("--mcp-config", mcpConfigPath);
|
|
2467
|
-
|
|
2468
|
-
args.push("--strict-mcp-config");
|
|
2469
|
-
}
|
|
2563
|
+
args.push("--strict-mcp-config");
|
|
2470
2564
|
}
|
|
2471
2565
|
if (chromeOn) {
|
|
2472
2566
|
args.push("--chrome");
|
|
@@ -2498,8 +2592,10 @@ var claudeAdapter = {
|
|
|
2498
2592
|
CLAUDE_CODE_FORWARD_SUBAGENT_TEXT: "1",
|
|
2499
2593
|
CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS: process.env.CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS ?? String(CLAUDE_PRINT_BG_WAIT_CEILING_MS),
|
|
2500
2594
|
// `--strict-mcp-config` still fetches claude.ai connectors on some CLI
|
|
2501
|
-
// builds (anthropics/claude-code#60252). Coordinators
|
|
2502
|
-
|
|
2595
|
+
// builds (anthropics/claude-code#60252). Coordinators never need them.
|
|
2596
|
+
// Local `pnpm dev` also disables them: those HTTP connectors hang the
|
|
2597
|
+
// first worktree turn when Electron's cwd is this Sideboard repo.
|
|
2598
|
+
...isOrchestrator || isLocalDevAppDataDir() ? { ENABLE_CLAUDEAI_MCP_SERVERS: "false" } : {}
|
|
2503
2599
|
}
|
|
2504
2600
|
};
|
|
2505
2601
|
},
|
|
@@ -2650,115 +2746,6 @@ function parseIssuesJson(raw) {
|
|
|
2650
2746
|
import { existsSync as existsSync9, readFileSync as readFileSync4, statSync as statSync2 } from "fs";
|
|
2651
2747
|
import { homedir as homedir4 } from "os";
|
|
2652
2748
|
import { join as join7 } from "path";
|
|
2653
|
-
|
|
2654
|
-
// src/agents/orch-mcp-isolation.ts
|
|
2655
|
-
import { existsSync as existsSync8, readFileSync as readFileSync3 } from "fs";
|
|
2656
|
-
import { homedir as homedir3 } from "os";
|
|
2657
|
-
import { join as join6 } from "path";
|
|
2658
|
-
import { parse as parseToml } from "smol-toml";
|
|
2659
|
-
|
|
2660
|
-
// src/agents/user-mcp-config.ts
|
|
2661
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
2662
|
-
import { homedir as homedir2 } from "os";
|
|
2663
|
-
import { dirname as dirname3, join as join5 } from "path";
|
|
2664
|
-
|
|
2665
|
-
// src/agents/orch-mcp-isolation.ts
|
|
2666
|
-
function isInjectedOrchMcpName(name) {
|
|
2667
|
-
const n = name.trim().toLowerCase();
|
|
2668
|
-
return n === "sideboard" || n === "brightsy" || n.startsWith("brightsy_");
|
|
2669
|
-
}
|
|
2670
|
-
function asObject(value) {
|
|
2671
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
2672
|
-
return value;
|
|
2673
|
-
}
|
|
2674
|
-
function listMcpNamesFromJsonMap(raw, key) {
|
|
2675
|
-
return Object.keys(asObject(asObject(raw)[key])).filter((n) => n.trim());
|
|
2676
|
-
}
|
|
2677
|
-
function listMcpNamesFromCodexToml(text) {
|
|
2678
|
-
try {
|
|
2679
|
-
const parsed = parseToml(text);
|
|
2680
|
-
return Object.keys(asObject(parsed.mcp_servers)).filter((n) => n.trim());
|
|
2681
|
-
} catch {
|
|
2682
|
-
return [];
|
|
2683
|
-
}
|
|
2684
|
-
}
|
|
2685
|
-
function readJsonObject(path) {
|
|
2686
|
-
try {
|
|
2687
|
-
return JSON.parse(readFileSync3(path, "utf8"));
|
|
2688
|
-
} catch {
|
|
2689
|
-
return {};
|
|
2690
|
-
}
|
|
2691
|
-
}
|
|
2692
|
-
function readText(path) {
|
|
2693
|
-
try {
|
|
2694
|
-
return readFileSync3(path, "utf8");
|
|
2695
|
-
} catch {
|
|
2696
|
-
return "";
|
|
2697
|
-
}
|
|
2698
|
-
}
|
|
2699
|
-
function userCodexConfigPaths(home = homedir3()) {
|
|
2700
|
-
return [join6(home, ".codex", "config.toml"), join6(home, ".config", "codex", "config.toml")];
|
|
2701
|
-
}
|
|
2702
|
-
function userOpencodeConfigPaths(home = homedir3()) {
|
|
2703
|
-
return [
|
|
2704
|
-
join6(home, ".config", "opencode", "opencode.json"),
|
|
2705
|
-
join6(home, ".config", "opencode", "opencode.jsonc")
|
|
2706
|
-
];
|
|
2707
|
-
}
|
|
2708
|
-
function userMcpNamesToDisable(opts) {
|
|
2709
|
-
const keep = new Set(
|
|
2710
|
-
[...opts.injectedNames ?? []].map((n) => n.trim().toLowerCase()).filter(Boolean)
|
|
2711
|
-
);
|
|
2712
|
-
const out = [];
|
|
2713
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2714
|
-
for (const raw of opts.names) {
|
|
2715
|
-
const name = raw.trim();
|
|
2716
|
-
if (!name) continue;
|
|
2717
|
-
const key = name.toLowerCase();
|
|
2718
|
-
if (seen.has(key) || keep.has(key) || isInjectedOrchMcpName(name)) continue;
|
|
2719
|
-
seen.add(key);
|
|
2720
|
-
out.push(name);
|
|
2721
|
-
}
|
|
2722
|
-
return out;
|
|
2723
|
-
}
|
|
2724
|
-
function listUserCodexMcpNames(home = homedir3()) {
|
|
2725
|
-
const names = [];
|
|
2726
|
-
for (const path of userCodexConfigPaths(home)) {
|
|
2727
|
-
if (!existsSync8(path)) continue;
|
|
2728
|
-
names.push(...listMcpNamesFromCodexToml(readText(path)));
|
|
2729
|
-
}
|
|
2730
|
-
return names;
|
|
2731
|
-
}
|
|
2732
|
-
function listUserOpencodeMcpNames(home = homedir3()) {
|
|
2733
|
-
const names = [];
|
|
2734
|
-
for (const path of userOpencodeConfigPaths(home)) {
|
|
2735
|
-
if (!existsSync8(path)) continue;
|
|
2736
|
-
names.push(...listMcpNamesFromJsonMap(readJsonObject(path), "mcp"));
|
|
2737
|
-
}
|
|
2738
|
-
return names;
|
|
2739
|
-
}
|
|
2740
|
-
function toCodexDisableUserMcpArgs(names) {
|
|
2741
|
-
const args = [];
|
|
2742
|
-
for (const name of names) {
|
|
2743
|
-
if (!/^[A-Za-z0-9_-]+$/.test(name)) continue;
|
|
2744
|
-
args.push("-c", `mcp_servers.${name}.enabled=false`);
|
|
2745
|
-
}
|
|
2746
|
-
return args;
|
|
2747
|
-
}
|
|
2748
|
-
function toCodexUnattendedAppsArgs() {
|
|
2749
|
-
return [
|
|
2750
|
-
"-c",
|
|
2751
|
-
"features.apps=false",
|
|
2752
|
-
"-c",
|
|
2753
|
-
"apps._default.enabled=false",
|
|
2754
|
-
"-c",
|
|
2755
|
-
"apps.posthog.enabled=false",
|
|
2756
|
-
"-c",
|
|
2757
|
-
"features.plugins=false"
|
|
2758
|
-
];
|
|
2759
|
-
}
|
|
2760
|
-
|
|
2761
|
-
// src/agents/codex.ts
|
|
2762
2749
|
var CODEX_PROMPT_ARG_MAX = 2e5;
|
|
2763
2750
|
var FALLBACK_CODEX_MODELS = [
|
|
2764
2751
|
{ id: "gpt-5.6-sol", displayName: "GPT-5.6 Sol" },
|
|
@@ -4755,6 +4742,9 @@ export {
|
|
|
4755
4742
|
adjustBrightsyTurnExit,
|
|
4756
4743
|
listBrightsyChatTargets,
|
|
4757
4744
|
brightsyAdapter,
|
|
4745
|
+
sideboardMcpProfile,
|
|
4746
|
+
packagedMcpDir,
|
|
4747
|
+
applyAgentRunnerHeapEnv,
|
|
4758
4748
|
toolDescription,
|
|
4759
4749
|
isInternalAgentStatusText,
|
|
4760
4750
|
isPollWrapperToolName,
|
|
@@ -4766,9 +4756,6 @@ export {
|
|
|
4766
4756
|
isBrightsyNdjsonLine,
|
|
4767
4757
|
finalizeParts,
|
|
4768
4758
|
normalizeParseResult,
|
|
4769
|
-
sideboardMcpProfile,
|
|
4770
|
-
packagedMcpDir,
|
|
4771
|
-
applyAgentRunnerHeapEnv,
|
|
4772
4759
|
PLAN_MODE_INSTRUCTION,
|
|
4773
4760
|
permissionMode,
|
|
4774
4761
|
mcpStatusThinkingFromClaudeInit,
|