@sideboard-ai/core 0.1.89 → 0.1.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/cursor-runner.cjs +129 -14
- package/dist/agents/cursor-runner.js +4 -1
- package/dist/{agents-LMUFTGKF.js → agents-HBLA6FEV.js} +4 -4
- package/dist/{agents-ODBP7J6E.js → agents-WS5QV6LE.js} +5 -5
- package/dist/{chunk-WANQFU3S.js → chunk-6XBXVXX2.js} +2 -2
- package/dist/{chunk-7D27DD2X.js → chunk-CIRXAYWS.js} +260 -61
- package/dist/{chunk-B2KIO2SD.js → chunk-CLGO7TLO.js} +2 -2
- package/dist/{chunk-CBJSPTBG.js → chunk-GXSYI7FH.js} +206 -5
- package/dist/{chunk-RJLBSYUO.js → chunk-KWNUZ4LR.js} +46 -77
- package/dist/{chunk-UHTNJKZX.js → chunk-NR6APJLD.js} +2 -2
- package/dist/{chunk-6EZRSCIT.js → chunk-QKYO6BHB.js} +2 -2
- package/dist/{chunk-ZXYWWSHZ.js → chunk-R7BQBSDT.js} +254 -61
- package/dist/{chunk-JE75QW2I.js → chunk-WBX46OPD.js} +237 -96
- package/dist/{chunk-OB6IRIFV.js → chunk-XH2GS2LO.js} +2 -2
- package/dist/{chunk-VZ2L4AEJ.js → chunk-XUWDLRAE.js} +2 -2
- package/dist/{coordinator-prompt-UK5LYFN5.js → coordinator-prompt-AKEY4WSO.js} +2 -2
- package/dist/{coordinator-prompt-CI5SHONJ.js → coordinator-prompt-OQOOD5ET.js} +2 -2
- package/dist/{global-workspace-2YZ2V4I5.js → global-workspace-3GNPQCLE.js} +3 -3
- package/dist/{global-workspace-JQQLPJM5.js → global-workspace-M3OMVDDH.js} +3 -3
- package/dist/index.cjs +1021 -473
- package/dist/index.d.cts +91 -20
- package/dist/index.d.ts +91 -20
- package/dist/index.js +244 -59
- package/dist/mcp/run-stdio.cjs +816 -428
- package/dist/mcp/run-stdio.js +77 -40
- package/dist/{workspaces-YWCC3WV4.js → workspaces-ERZC7ULY.js} +4 -4
- package/dist/{workspaces-FDO5L4NI.js → workspaces-J4WG6UFR.js} +4 -4
- package/dist/{worktree-7YNSJ224.js → worktree-DA4BOV7G.js} +7 -1
- package/dist/{worktree-4555QBQ7.js → worktree-EO5QAGJU.js} +7 -1
- package/package.json +1 -1
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isElectronLikeCommand,
|
|
3
|
+
wrapElectronAsNodeLaunch
|
|
4
|
+
} from "./chunk-TLPJHLLM.js";
|
|
5
|
+
import {
|
|
6
|
+
run
|
|
7
|
+
} from "./chunk-LGXBYZZA.js";
|
|
8
|
+
|
|
1
9
|
// src/agents/error-detail.ts
|
|
2
10
|
function formatUnknownDetail(err) {
|
|
3
11
|
if (err == null) return "";
|
|
@@ -42,17 +50,27 @@ function extractJsonErrorMessage(obj) {
|
|
|
42
50
|
return null;
|
|
43
51
|
}
|
|
44
52
|
var NODE_VERSION_FOOTER = /^Node\.js v\d+/i;
|
|
53
|
+
function isPinnedStderrLine(line) {
|
|
54
|
+
if (/^\s*at\s/.test(line)) return false;
|
|
55
|
+
return /cannot find (?:package|module)|ERR_MODULE_NOT_FOUND|cursor startup failed:/i.test(
|
|
56
|
+
line
|
|
57
|
+
);
|
|
58
|
+
}
|
|
45
59
|
function pushTurnStderr(tail, line, maxLines = 12) {
|
|
46
60
|
const trimmed = line.trim();
|
|
47
61
|
if (!trimmed) return;
|
|
48
62
|
if (NODE_VERSION_FOOTER.test(trimmed)) return;
|
|
49
63
|
if (/^reconnecting\.\.\./i.test(trimmed)) return;
|
|
50
64
|
tail.push(trimmed);
|
|
51
|
-
while (tail.length > maxLines)
|
|
65
|
+
while (tail.length > maxLines) {
|
|
66
|
+
const dropIdx = tail.findIndex((l) => !isPinnedStderrLine(l));
|
|
67
|
+
if (dropIdx === -1) tail.shift();
|
|
68
|
+
else tail.splice(dropIdx, 1);
|
|
69
|
+
}
|
|
52
70
|
}
|
|
53
71
|
function looksLikeMinifiedJsDump(line) {
|
|
54
72
|
if (line.length < 200) return false;
|
|
55
|
-
return /yield Promise\.all/.test(line) || /\(0,[A-Za-z$]\.\w+\)/.test(line) || /CURSOR_RIPGREP_PATH/.test(line);
|
|
73
|
+
return /yield Promise\.all/.test(line) || /\(0,[A-Za-z$]\.\w+\)/.test(line) || /CURSOR_RIPGREP_PATH/.test(line) || /findFilesWithRipgrep/.test(line) || /@cursor\/sdk\/dist\//.test(line);
|
|
56
74
|
}
|
|
57
75
|
function looksLikeNestedElectronCrash(line) {
|
|
58
76
|
return /HasCustomHostObject|ElectronInitializeICUandStartNode/i.test(line);
|
|
@@ -69,7 +87,15 @@ function summarizeTurnStderr(tail, maxChars = 500) {
|
|
|
69
87
|
const cursorStartup = [...tail].reverse().find((line) => /cursor startup failed:/i.test(line));
|
|
70
88
|
if (cursorStartup) return clipStderr(cursorStartup, maxChars);
|
|
71
89
|
if (tail.some(looksLikeNestedElectronCrash)) return NESTED_ELECTRON_SUMMARY;
|
|
72
|
-
|
|
90
|
+
if (tail.some(
|
|
91
|
+
(line) => /\[resource_exhausted\]|resource_exhausted/i.test(line) || /findFilesWithRipgrep/.test(line)
|
|
92
|
+
)) {
|
|
93
|
+
return clipStderr(
|
|
94
|
+
"Cursor local file search failed (ripgrep / resource_exhausted). Wait a minute and retry; if it keeps happening, check Cursor usage.",
|
|
95
|
+
maxChars
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
const moduleMissing = [...tail].reverse().find((line) => /cannot find (?:package|module)/i.test(line));
|
|
73
99
|
if (moduleMissing) return clipStderr(moduleMissing, maxChars);
|
|
74
100
|
const useful = tail.filter((line) => !looksLikeMinifiedJsDump(line));
|
|
75
101
|
if (useful.length === 0 && tail.some(looksLikeMinifiedJsDump)) {
|
|
@@ -88,7 +114,7 @@ function looksLikeAgentFailureMessage(text) {
|
|
|
88
114
|
if (!lower) return false;
|
|
89
115
|
return /you've hit your|hit your (session|weekly|opus) limit|usage limit/.test(lower) || /credit balance is too low|out of credits|insufficient.?quota|quota.?exceeded/.test(lower) || /invalid user api key|invalid api key|not logged in|not authenticated|unauthorized/.test(
|
|
90
116
|
lower
|
|
91
|
-
) || /\b429\b|too many requests|rate.?limit/.test(lower) || /prompt is too long|context.*(too long|exceed)|conversation too long/.test(lower);
|
|
117
|
+
) || /\b429\b|too many requests|rate.?limit/.test(lower) || /prompt is too long|context.*(too long|exceed)|conversation too long/.test(lower) || /\[resource_exhausted\]|resource_exhausted/.test(lower) || /findFilesWithRipgrep/.test(text);
|
|
92
118
|
}
|
|
93
119
|
function fallbackTurnFailDetail(assistantText) {
|
|
94
120
|
const t = assistantText.trim();
|
|
@@ -110,6 +136,9 @@ function humanizeAgentFailDetail(detail) {
|
|
|
110
136
|
if (/\b429\b|rate.?limit|too many requests/.test(lower)) {
|
|
111
137
|
return `${raw} \u2014 wait a moment and retry.`;
|
|
112
138
|
}
|
|
139
|
+
if (/\[resource_exhausted\]|resource_exhausted|findfileswithripgrep/.test(lower)) {
|
|
140
|
+
return "Cursor local file search failed (ripgrep / resource_exhausted). Wait a minute and retry; if it keeps happening, check Cursor usage.";
|
|
141
|
+
}
|
|
113
142
|
if (/invalid user api key|invalid api key|not logged in|not authenticated|unauthorized|authentication|please run.*login|codex login|claude auth|cursor api/.test(
|
|
114
143
|
lower
|
|
115
144
|
)) {
|
|
@@ -312,6 +341,171 @@ function parseCursorRunnerLine(line) {
|
|
|
312
341
|
}
|
|
313
342
|
}
|
|
314
343
|
|
|
344
|
+
// src/agents/cursor-ripgrep.ts
|
|
345
|
+
import { existsSync as existsSync3 } from "fs";
|
|
346
|
+
import { createRequire } from "module";
|
|
347
|
+
import { dirname, isAbsolute, join as join3, parse, resolve as resolvePath } from "path";
|
|
348
|
+
import { fileURLToPath } from "url";
|
|
349
|
+
|
|
350
|
+
// src/agents/node-launch.ts
|
|
351
|
+
import { existsSync } from "fs";
|
|
352
|
+
import { homedir } from "os";
|
|
353
|
+
import { join } from "path";
|
|
354
|
+
function isAsarPath(filePath) {
|
|
355
|
+
if (/\.asar\.unpacked([/\\]|$)/.test(filePath)) return false;
|
|
356
|
+
return /\.asar([/\\]|$)/.test(filePath);
|
|
357
|
+
}
|
|
358
|
+
function unpackedAsarPath(filePath) {
|
|
359
|
+
if (!isAsarPath(filePath)) return null;
|
|
360
|
+
const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
|
|
361
|
+
if (unpacked === filePath) return null;
|
|
362
|
+
return existsSync(unpacked) ? unpacked : null;
|
|
363
|
+
}
|
|
364
|
+
function nodeReadableScriptPath(scriptPath) {
|
|
365
|
+
return unpackedAsarPath(scriptPath) ?? scriptPath;
|
|
366
|
+
}
|
|
367
|
+
var WELL_KNOWN_NODE_BINS = [
|
|
368
|
+
"/opt/homebrew/bin/node",
|
|
369
|
+
"/usr/local/bin/node"
|
|
370
|
+
];
|
|
371
|
+
async function findSystemNode() {
|
|
372
|
+
const whichNode = await run("which", ["node"], { reject: false });
|
|
373
|
+
const fromWhich = whichNode.exitCode === 0 && whichNode.stdout.trim() ? whichNode.stdout.trim() : "";
|
|
374
|
+
if (fromWhich && !isElectronLikeCommand(fromWhich)) return fromWhich;
|
|
375
|
+
const fallbacks = [
|
|
376
|
+
...WELL_KNOWN_NODE_BINS,
|
|
377
|
+
join(homedir(), ".local/share/fnm/aliases/default/bin/node"),
|
|
378
|
+
join(homedir(), ".nvm/current/bin/node")
|
|
379
|
+
];
|
|
380
|
+
for (const bin of fallbacks) {
|
|
381
|
+
if (existsSync(bin) && !isElectronLikeCommand(bin)) return bin;
|
|
382
|
+
}
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
function applyNodeLaunch(launch, args) {
|
|
386
|
+
const readableArgs = args.map(nodeReadableScriptPath);
|
|
387
|
+
if (!launch.env.ELECTRON_RUN_AS_NODE) {
|
|
388
|
+
return { file: launch.file, args: readableArgs, env: launch.env };
|
|
389
|
+
}
|
|
390
|
+
const wrapped = wrapElectronAsNodeLaunch(launch.file, readableArgs);
|
|
391
|
+
if (process.platform === "win32") {
|
|
392
|
+
return { file: wrapped.file, args: wrapped.args, env: launch.env };
|
|
393
|
+
}
|
|
394
|
+
const env = { ...launch.env };
|
|
395
|
+
delete env.ELECTRON_RUN_AS_NODE;
|
|
396
|
+
return { file: wrapped.file, args: wrapped.args, env };
|
|
397
|
+
}
|
|
398
|
+
async function resolveNodeLaunch(scriptPath) {
|
|
399
|
+
const script = nodeReadableScriptPath(scriptPath);
|
|
400
|
+
if (!isAsarPath(script)) {
|
|
401
|
+
const nodeBin = await findSystemNode();
|
|
402
|
+
if (nodeBin) {
|
|
403
|
+
return { file: nodeBin, env: {} };
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return {
|
|
407
|
+
file: process.execPath,
|
|
408
|
+
env: { ELECTRON_RUN_AS_NODE: "1" }
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// src/agents/packaged-runtime.ts
|
|
413
|
+
import { existsSync as existsSync2 } from "fs";
|
|
414
|
+
import { join as join2 } from "path";
|
|
415
|
+
function electronResourcesPath() {
|
|
416
|
+
const resources = process.resourcesPath;
|
|
417
|
+
if (typeof resources !== "string" || !resources) return null;
|
|
418
|
+
return resources;
|
|
419
|
+
}
|
|
420
|
+
function packagedCursorRuntimeDir() {
|
|
421
|
+
const resources = electronResourcesPath();
|
|
422
|
+
if (!resources) return null;
|
|
423
|
+
const dir = join2(resources, "cursor-runtime");
|
|
424
|
+
if (!existsSync2(join2(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
|
|
425
|
+
return dir;
|
|
426
|
+
}
|
|
427
|
+
function packagedCursorRunnerPath() {
|
|
428
|
+
const dir = packagedCursorRuntimeDir();
|
|
429
|
+
return dir ? join2(dir, "core-dist", "agents", "cursor-runner.js") : null;
|
|
430
|
+
}
|
|
431
|
+
function packagedMcpDir() {
|
|
432
|
+
const resources = electronResourcesPath();
|
|
433
|
+
if (!resources) return null;
|
|
434
|
+
const dir = join2(resources, "sideboard-mcp");
|
|
435
|
+
if (!existsSync2(join2(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
|
|
436
|
+
return dir;
|
|
437
|
+
}
|
|
438
|
+
function packagedMcpStdioPath() {
|
|
439
|
+
const dir = packagedMcpDir();
|
|
440
|
+
return dir ? join2(dir, "core-dist", "mcp", "run-stdio.js") : null;
|
|
441
|
+
}
|
|
442
|
+
function packagedCursorRipgrepCandidate(platformPkg, binName) {
|
|
443
|
+
const dir = packagedCursorRuntimeDir();
|
|
444
|
+
if (!dir) return null;
|
|
445
|
+
return join2(dir, "node_modules", platformPkg, "bin", binName);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// src/agents/cursor-ripgrep.ts
|
|
449
|
+
var RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
|
|
450
|
+
function rgBinaryName() {
|
|
451
|
+
return process.platform === "win32" ? "rg.exe" : "rg";
|
|
452
|
+
}
|
|
453
|
+
function platformRipgrepPackage() {
|
|
454
|
+
return `@cursor/sdk-${process.platform}-${process.arch}`;
|
|
455
|
+
}
|
|
456
|
+
function usableRipgrepPath(candidate) {
|
|
457
|
+
const raw = candidate?.trim();
|
|
458
|
+
if (!raw || !isAbsolute(raw)) return null;
|
|
459
|
+
const readable = nodeReadableScriptPath(raw);
|
|
460
|
+
if (!existsSync3(readable) || isAsarPath(readable)) return null;
|
|
461
|
+
return readable;
|
|
462
|
+
}
|
|
463
|
+
function walkForBundledRipgrep(startFile) {
|
|
464
|
+
if (!startFile) return null;
|
|
465
|
+
const pkg = platformRipgrepPackage();
|
|
466
|
+
const name = rgBinaryName();
|
|
467
|
+
let dir = dirname(resolvePath(startFile));
|
|
468
|
+
const root = parse(dir).root;
|
|
469
|
+
while (dir !== root) {
|
|
470
|
+
const hit = usableRipgrepPath(join3(dir, "node_modules", pkg, "bin", name));
|
|
471
|
+
if (hit) return hit;
|
|
472
|
+
const next = dirname(dir);
|
|
473
|
+
if (next === dir) break;
|
|
474
|
+
dir = next;
|
|
475
|
+
}
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
function requireResolveBundledRipgrep(fromFile) {
|
|
479
|
+
try {
|
|
480
|
+
const req = createRequire(fromFile);
|
|
481
|
+
const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
|
|
482
|
+
return usableRipgrepPath(join3(dirname(pkgJson), "bin", rgBinaryName()));
|
|
483
|
+
} catch {
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
function resolveCursorRipgrepPath(opts) {
|
|
488
|
+
const env = opts?.env ?? process.env;
|
|
489
|
+
const fromEnv = usableRipgrepPath(env[RIPGREP_ENV]);
|
|
490
|
+
if (fromEnv) return fromEnv;
|
|
491
|
+
const fromPackaged = usableRipgrepPath(
|
|
492
|
+
packagedCursorRipgrepCandidate(platformRipgrepPackage(), rgBinaryName())
|
|
493
|
+
);
|
|
494
|
+
if (fromPackaged) return fromPackaged;
|
|
495
|
+
const start = opts?.startFile?.trim() || process.argv[1] || fileURLToPath(import.meta.url);
|
|
496
|
+
return walkForBundledRipgrep(start) ?? requireResolveBundledRipgrep(start);
|
|
497
|
+
}
|
|
498
|
+
function cursorRipgrepEnv(opts) {
|
|
499
|
+
const path = resolveCursorRipgrepPath(opts);
|
|
500
|
+
return path ? { [RIPGREP_ENV]: path } : {};
|
|
501
|
+
}
|
|
502
|
+
function ensureCursorRipgrepPath(opts) {
|
|
503
|
+
const target = opts?.env ?? process.env;
|
|
504
|
+
const path = resolveCursorRipgrepPath({ env: target, startFile: opts?.startFile });
|
|
505
|
+
if (path) target[RIPGREP_ENV] = path;
|
|
506
|
+
return path;
|
|
507
|
+
}
|
|
508
|
+
|
|
315
509
|
export {
|
|
316
510
|
formatUnknownDetail,
|
|
317
511
|
extractJsonErrorMessage,
|
|
@@ -322,6 +516,13 @@ export {
|
|
|
322
516
|
fallbackTurnFailDetail,
|
|
323
517
|
humanizeAgentFailDetail,
|
|
324
518
|
formatTurnExitError,
|
|
519
|
+
isAsarPath,
|
|
520
|
+
applyNodeLaunch,
|
|
521
|
+
resolveNodeLaunch,
|
|
522
|
+
packagedCursorRunnerPath,
|
|
523
|
+
packagedMcpStdioPath,
|
|
325
524
|
cursorSdkMessageToEvents,
|
|
326
|
-
parseCursorRunnerLine
|
|
525
|
+
parseCursorRunnerLine,
|
|
526
|
+
cursorRipgrepEnv,
|
|
527
|
+
ensureCursorRipgrepPath
|
|
327
528
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isOrchestratorThread
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-CLGO7TLO.js";
|
|
4
4
|
import {
|
|
5
5
|
applyConnectedTeamToCli,
|
|
6
6
|
brightsyMcpServerName,
|
|
@@ -9,15 +9,23 @@ import {
|
|
|
9
9
|
loadBrightsyConfig
|
|
10
10
|
} from "./chunk-QSLE4VEM.js";
|
|
11
11
|
import {
|
|
12
|
+
applyNodeLaunch,
|
|
13
|
+
cursorRipgrepEnv,
|
|
12
14
|
extractJsonErrorMessage,
|
|
13
15
|
formatUnknownDetail,
|
|
16
|
+
isAsarPath,
|
|
14
17
|
looksLikeAgentFailureMessage,
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
packagedCursorRunnerPath,
|
|
19
|
+
packagedMcpStdioPath,
|
|
20
|
+
parseCursorRunnerLine,
|
|
21
|
+
resolveNodeLaunch
|
|
22
|
+
} from "./chunk-GXSYI7FH.js";
|
|
17
23
|
import {
|
|
18
24
|
codexUnattendedGitConfigArgs,
|
|
19
|
-
|
|
20
|
-
|
|
25
|
+
mergeAgentGitAuthEnv,
|
|
26
|
+
resolveAgentGitAuthEnv,
|
|
27
|
+
resolveCodexGitWritableRoots
|
|
28
|
+
} from "./chunk-CIRXAYWS.js";
|
|
21
29
|
import {
|
|
22
30
|
claudeChromeEnabled,
|
|
23
31
|
loadAppSettings,
|
|
@@ -26,8 +34,7 @@ import {
|
|
|
26
34
|
} from "./chunk-FT2SQOL4.js";
|
|
27
35
|
import {
|
|
28
36
|
isElectronLikeCommand,
|
|
29
|
-
unwrapStrippedElectronLaunch
|
|
30
|
-
wrapElectronAsNodeLaunch
|
|
37
|
+
unwrapStrippedElectronLaunch
|
|
31
38
|
} from "./chunk-TLPJHLLM.js";
|
|
32
39
|
import {
|
|
33
40
|
appDataDir
|
|
@@ -521,7 +528,7 @@ function mcpAuthWarnings(servers) {
|
|
|
521
528
|
}
|
|
522
529
|
|
|
523
530
|
// src/agents/injected-mcp.ts
|
|
524
|
-
import { existsSync as existsSync2,
|
|
531
|
+
import { existsSync as existsSync2, mkdtempSync, writeFileSync } from "fs";
|
|
525
532
|
import { createRequire } from "module";
|
|
526
533
|
import { tmpdir } from "os";
|
|
527
534
|
import { dirname, join } from "path";
|
|
@@ -533,40 +540,6 @@ function sideboardMcpProfile(env = process.env) {
|
|
|
533
540
|
return env[SIDEBOARD_MCP_PROFILE_ENV]?.trim().toLowerCase() === "worktree" ? "worktree" : "orchestration";
|
|
534
541
|
}
|
|
535
542
|
|
|
536
|
-
// src/agents/node-launch.ts
|
|
537
|
-
function isAsarPath(filePath) {
|
|
538
|
-
return /\.asar([/\\]|$)/.test(filePath);
|
|
539
|
-
}
|
|
540
|
-
function applyNodeLaunch(launch, args) {
|
|
541
|
-
if (!launch.env.ELECTRON_RUN_AS_NODE) {
|
|
542
|
-
return { file: launch.file, args, env: launch.env };
|
|
543
|
-
}
|
|
544
|
-
const wrapped = wrapElectronAsNodeLaunch(launch.file, args);
|
|
545
|
-
if (process.platform === "win32") {
|
|
546
|
-
return { file: wrapped.file, args: wrapped.args, env: launch.env };
|
|
547
|
-
}
|
|
548
|
-
const env = { ...launch.env };
|
|
549
|
-
delete env.ELECTRON_RUN_AS_NODE;
|
|
550
|
-
return { file: wrapped.file, args: wrapped.args, env };
|
|
551
|
-
}
|
|
552
|
-
async function resolveNodeLaunch(scriptPath) {
|
|
553
|
-
if (isAsarPath(scriptPath)) {
|
|
554
|
-
return {
|
|
555
|
-
file: process.execPath,
|
|
556
|
-
env: { ELECTRON_RUN_AS_NODE: "1" }
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
const whichNode = await run("which", ["node"], { reject: false });
|
|
560
|
-
const nodeBin = whichNode.exitCode === 0 && whichNode.stdout.trim() ? whichNode.stdout.trim() : null;
|
|
561
|
-
if (nodeBin) {
|
|
562
|
-
return { file: nodeBin, env: {} };
|
|
563
|
-
}
|
|
564
|
-
return {
|
|
565
|
-
file: process.execPath,
|
|
566
|
-
env: { ELECTRON_RUN_AS_NODE: "1" }
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
|
|
570
543
|
// src/agents/injected-mcp.ts
|
|
571
544
|
var SIDEBOARD_MCP_ALLOWED_TOOLS = [
|
|
572
545
|
"mcp__sideboard",
|
|
@@ -688,6 +661,8 @@ function corePackageDir() {
|
|
|
688
661
|
function findSideboardMcpJsEntry() {
|
|
689
662
|
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
690
663
|
if (override && existsSync2(override)) return override;
|
|
664
|
+
const packaged = packagedMcpStdioPath();
|
|
665
|
+
if (packaged) return packaged;
|
|
691
666
|
let dir = corePackageDir();
|
|
692
667
|
for (let i = 0; i < 10; i++) {
|
|
693
668
|
const candidates = [
|
|
@@ -700,7 +675,7 @@ function findSideboardMcpJsEntry() {
|
|
|
700
675
|
join(dir, "cli/dist/index.js")
|
|
701
676
|
];
|
|
702
677
|
for (const p of candidates) {
|
|
703
|
-
if (existsSync2(p)) return p;
|
|
678
|
+
if (existsSync2(p) && !isAsarPath(p)) return p;
|
|
704
679
|
}
|
|
705
680
|
const parent = dirname(dir);
|
|
706
681
|
if (parent === dir) break;
|
|
@@ -714,12 +689,14 @@ async function resolveSideboardMcpServer() {
|
|
|
714
689
|
const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
|
|
715
690
|
const scriptArgs = isCli ? [entry, "mcp"] : [entry];
|
|
716
691
|
const launch = applyNodeLaunch(await resolveNodeLaunch(entry), scriptArgs);
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
692
|
+
if (launch.file !== "/bin/sh" && !isElectronLikeCommand(launch.file)) {
|
|
693
|
+
return {
|
|
694
|
+
name: "sideboard",
|
|
695
|
+
command: launch.file,
|
|
696
|
+
args: launch.args,
|
|
697
|
+
...Object.keys(launch.env).length > 0 ? { env: launch.env } : {}
|
|
698
|
+
};
|
|
699
|
+
}
|
|
723
700
|
}
|
|
724
701
|
const which = await run("which", ["sideboard"], { reject: false });
|
|
725
702
|
if (which.exitCode === 0 && which.stdout.trim()) {
|
|
@@ -742,7 +719,10 @@ async function buildInjectedMcpServers(opts) {
|
|
|
742
719
|
sideboard.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID = orchId;
|
|
743
720
|
}
|
|
744
721
|
try {
|
|
745
|
-
|
|
722
|
+
mergeAgentGitAuthEnv(
|
|
723
|
+
sideboard.env,
|
|
724
|
+
await resolveAgentGitAuthEnv(sideboard.env)
|
|
725
|
+
);
|
|
746
726
|
} catch {
|
|
747
727
|
}
|
|
748
728
|
servers.push(sideboard);
|
|
@@ -764,9 +744,6 @@ async function buildInjectedMcpServers(opts) {
|
|
|
764
744
|
}
|
|
765
745
|
return servers;
|
|
766
746
|
}
|
|
767
|
-
function shSingleQuote(value) {
|
|
768
|
-
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
769
|
-
}
|
|
770
747
|
function cursorSafeMcpLaunch(command, args) {
|
|
771
748
|
if (process.platform === "win32") {
|
|
772
749
|
return args && args.length > 0 ? { command, args } : { command };
|
|
@@ -774,31 +751,13 @@ function cursorSafeMcpLaunch(command, args) {
|
|
|
774
751
|
const unwrapped = unwrapStrippedElectronLaunch(command, args);
|
|
775
752
|
const file = unwrapped?.file ?? command;
|
|
776
753
|
const fileArgs = unwrapped?.args ?? args ?? [];
|
|
777
|
-
|
|
778
|
-
return fileArgs.length > 0 ? { command: file, args: fileArgs } : { command: file };
|
|
779
|
-
}
|
|
780
|
-
const dir = join(appDataDir(), "mcp-launch");
|
|
781
|
-
mkdirSync(dir, { recursive: true });
|
|
782
|
-
const wrap = join(dir, "cursor-electron-as-node.sh");
|
|
783
|
-
const execLine = [file, ...fileArgs].map(shSingleQuote).join(" ");
|
|
784
|
-
writeFileSync(
|
|
785
|
-
wrap,
|
|
786
|
-
[
|
|
787
|
-
"#!/bin/sh",
|
|
788
|
-
"vars=`printenv | awk -F= '/^(ELECTRON_|CHROME_)/{print $1}'`",
|
|
789
|
-
'[ -n "$vars" ] && unset $vars',
|
|
790
|
-
"export ELECTRON_RUN_AS_NODE=1",
|
|
791
|
-
`exec ${execLine} "$@"`,
|
|
792
|
-
""
|
|
793
|
-
].join("\n"),
|
|
794
|
-
{ mode: 493 }
|
|
795
|
-
);
|
|
796
|
-
return { command: wrap };
|
|
754
|
+
return fileArgs.length > 0 ? { command: file, args: fileArgs } : { command: file };
|
|
797
755
|
}
|
|
798
756
|
function mcpSpawnEnv(env) {
|
|
799
757
|
if (!env) return void 0;
|
|
800
758
|
const out = { ...env };
|
|
801
759
|
delete out.ELECTRON_RUN_AS_NODE;
|
|
760
|
+
delete out.ELECTRON_RUN_AS_NODE;
|
|
802
761
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
803
762
|
}
|
|
804
763
|
function toCursorMcpServers(servers) {
|
|
@@ -807,6 +766,7 @@ function toCursorMcpServers(servers) {
|
|
|
807
766
|
const env = mcpSpawnEnv(s.env);
|
|
808
767
|
const launch = cursorSafeMcpLaunch(s.command, s.args);
|
|
809
768
|
out[s.name] = {
|
|
769
|
+
type: "stdio",
|
|
810
770
|
command: launch.command,
|
|
811
771
|
...launch.args && launch.args.length > 0 ? { args: launch.args } : {},
|
|
812
772
|
...env ? { env } : {}
|
|
@@ -868,7 +828,7 @@ async function writeInjectedMcpConfig(opts) {
|
|
|
868
828
|
}
|
|
869
829
|
|
|
870
830
|
// src/agents/types.ts
|
|
871
|
-
var PLAN_MODE_INSTRUCTION = "Plan mode is active and must remain active until the user turns Plan mode off in the UI (or Approves / Hands off the plan). Analyze the codebase, search and read files as needed, and produce or refine a clear implementation plan. Do not modify, create, or delete any project files except via Sideboard MCP present_plan (writes .context/attachments/plan.md). When you need a clarifying decision (approach forks, auth choice, scope): (1) first write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it) \u2014 do not leave the user staring at bare labels; (2) then call Sideboard MCP ask_user with the same options, including a description on every option. Sideboard shows questions in the composer and mirrors them in chat. After ask_user, wait for the user's next message with their answers before finalizing the plan. When the plan is ready for approval: (1) call present_plan with the full markdown plan (title + content) so Sideboard saves .context/attachments/plan.md and shows it in chat for Approve / Hand off / Copy; (2) Claude should also call ExitPlanMode after present_plan. Do not skip present_plan \u2014 the plan must be a markdown file, not only chat prose.";
|
|
831
|
+
var PLAN_MODE_INSTRUCTION = "Plan mode is active and must remain active until the user turns Plan mode off in the UI (or Approves / Hands off the plan). Analyze the codebase, search and read files as needed, and produce or refine a clear implementation plan. Do not modify, create, or delete any project files except via Sideboard MCP present_plan (writes .context/attachments/plan.md). When you need a clarifying decision (approach forks, auth choice, scope) \u2014 not greetings, check-ins, or an invented task menu: (1) first write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it) \u2014 do not leave the user staring at bare labels; (2) then call Sideboard MCP ask_user with the same options, including a description on every option. If one option is the obvious default, proceed without asking. Sideboard shows questions in the composer and mirrors them in chat. After ask_user, wait for the user's next message with their answers before finalizing the plan. When the plan is ready for approval: (1) call present_plan with the full markdown plan (title + content) so Sideboard saves .context/attachments/plan.md and shows it in chat for Approve / Hand off / Copy; (2) Claude should also call ExitPlanMode after present_plan. Do not skip present_plan \u2014 the plan must be a markdown file, not only chat prose.";
|
|
872
832
|
function permissionMode(thread) {
|
|
873
833
|
if (thread.sourceType === "orchestration") {
|
|
874
834
|
return {
|
|
@@ -1059,7 +1019,7 @@ var claudeAdapter = {
|
|
|
1059
1019
|
);
|
|
1060
1020
|
}
|
|
1061
1021
|
const mode = permissionMode(thread);
|
|
1062
|
-
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-
|
|
1022
|
+
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-M3OMVDDH.js");
|
|
1063
1023
|
const isOrchestrator = isOrchestratorThread2(thread);
|
|
1064
1024
|
const injectedServers = await buildInjectedMcpServers({
|
|
1065
1025
|
includeSideboard: true,
|
|
@@ -1441,8 +1401,13 @@ var codexAdapter = {
|
|
|
1441
1401
|
// `codex exec` rejects `--ask-for-approval` (global-only on newer CLIs).
|
|
1442
1402
|
"-c",
|
|
1443
1403
|
'approval_policy="never"',
|
|
1444
|
-
// Seatbelt cannot use the login Keychain;
|
|
1445
|
-
|
|
1404
|
+
// Seatbelt cannot use the login Keychain; inherit GH_CONFIG_DIR / GIT_CONFIG_*.
|
|
1405
|
+
// Default policy also strips *TOKEN*. Linked worktrees need the main
|
|
1406
|
+
// repo `.git` (+ `.git/worktrees/<name>`) as writable_roots so git commit
|
|
1407
|
+
// can create index.lock.
|
|
1408
|
+
...codexUnattendedGitConfigArgs(mode.codexSandbox, {
|
|
1409
|
+
writableRoots: mode.codexSandbox === "workspace-write" ? await resolveCodexGitWritableRoots(thread.worktreePath) : []
|
|
1410
|
+
}),
|
|
1446
1411
|
...model ? ["--model", model] : [],
|
|
1447
1412
|
...mcpOverrides
|
|
1448
1413
|
];
|
|
@@ -1648,6 +1613,8 @@ function entryDir() {
|
|
|
1648
1613
|
}
|
|
1649
1614
|
}
|
|
1650
1615
|
function cursorRunnerPath() {
|
|
1616
|
+
const packaged = packagedCursorRunnerPath();
|
|
1617
|
+
if (packaged) return packaged;
|
|
1651
1618
|
const root = entryDir();
|
|
1652
1619
|
const candidates = [
|
|
1653
1620
|
join3(root, "agents", "cursor-runner.js"),
|
|
@@ -1723,6 +1690,7 @@ var cursorAdapter = {
|
|
|
1723
1690
|
stdin: JSON.stringify(req),
|
|
1724
1691
|
env: {
|
|
1725
1692
|
...launch.env,
|
|
1693
|
+
...cursorRipgrepEnv({ startFile: runner }),
|
|
1726
1694
|
...apiKey ? { CURSOR_API_KEY: apiKey } : {}
|
|
1727
1695
|
}
|
|
1728
1696
|
};
|
|
@@ -2483,6 +2451,7 @@ export {
|
|
|
2483
2451
|
threadRequestsBrightsyMcp,
|
|
2484
2452
|
shouldInjectBrightsyMcp,
|
|
2485
2453
|
brightsyMcpAllowedTools,
|
|
2454
|
+
resolveSideboardMcpServer,
|
|
2486
2455
|
writeInjectedMcpConfig,
|
|
2487
2456
|
PLAN_MODE_INSTRUCTION,
|
|
2488
2457
|
permissionMode,
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
ensureGlobalCoordinatorCwd
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-XH2GS2LO.js";
|
|
6
6
|
import {
|
|
7
7
|
allocateTeamName,
|
|
8
8
|
takenSlugsFromThread,
|
|
9
9
|
teamSlugFromName
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-R7BQBSDT.js";
|
|
11
11
|
import {
|
|
12
12
|
createEmptyThread,
|
|
13
13
|
listThreads,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isGlobalRepoPath
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-CLGO7TLO.js";
|
|
4
4
|
import {
|
|
5
5
|
ensureGhPreferOrigin,
|
|
6
6
|
resolveRepoRoot
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-CIRXAYWS.js";
|
|
8
8
|
import {
|
|
9
9
|
appDataDir
|
|
10
10
|
} from "./chunk-B4R2VB2A.js";
|