@sideboard-ai/core 0.1.62 → 0.1.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agents-QLSFIQAO.js → agents-EWFD765A.js} +23 -7
- package/dist/{agents-KF3J3C53.js → agents-MD7SCFYX.js} +23 -7
- package/dist/{app-settings-LTSFG7QJ.js → app-settings-GJVZGU3M.js} +13 -3
- package/dist/{app-settings-HK4KAM4R.js → app-settings-ONKMFSEJ.js} +13 -3
- package/dist/{chunk-RIWUU7FO.js → chunk-5AG5BUQN.js} +61 -3
- package/dist/{chunk-27MAWNKY.js → chunk-AKPEXIKK.js} +2 -2
- package/dist/{chunk-2MCNURQV.js → chunk-BBEH2CJE.js} +264 -93
- package/dist/{chunk-DDN3UF4R.js → chunk-BPOTVI5J.js} +115 -3
- package/dist/{chunk-2FEA4LDA.js → chunk-DNPP7QMK.js} +31 -6
- package/dist/{chunk-MBAL5FE6.js → chunk-DZYMNW2A.js} +4 -4
- package/dist/{chunk-JB2H7E7V.js → chunk-EVD4KNKR.js} +1 -1
- package/dist/{chunk-A6FOKNOU.js → chunk-HTOTTJJX.js} +2 -2
- package/dist/{chunk-3KKNTHUC.js → chunk-I2KGRAXC.js} +1 -1
- package/dist/{chunk-ZF5YJCXO.js → chunk-IFAU2DEY.js} +269 -93
- package/dist/{chunk-NVU7EC2E.js → chunk-LRBRQFBU.js} +2 -2
- package/dist/{chunk-6CUJQKTJ.js → chunk-MHR4OGZ4.js} +115 -3
- package/dist/{chunk-46KMKHSD.js → chunk-PESJDZTB.js} +2 -2
- package/dist/{chunk-UGXSSBFJ.js → chunk-R7GUDEPY.js} +1 -1
- package/dist/{chunk-73AT5K4A.js → chunk-TXQ6K2GR.js} +61 -3
- package/dist/{chunk-DXTGDXO2.js → chunk-YTNLOJPK.js} +31 -6
- package/dist/{connected-teams-RSL4VB3X.js → connected-teams-CHXO5FFA.js} +2 -2
- package/dist/{connected-teams-MKIYKOYA.js → connected-teams-GJTESSTX.js} +2 -2
- package/dist/{coordinator-prompt-LKG3SHMI.js → coordinator-prompt-E5UGSJES.js} +4 -4
- package/dist/{coordinator-prompt-N2R6FGZK.js → coordinator-prompt-ILSULI7C.js} +4 -4
- package/dist/{global-workspace-LALWQWRJ.js → global-workspace-44UG64NA.js} +5 -6
- package/dist/{global-workspace-YOAUQCMA.js → global-workspace-5PM5LA6E.js} +5 -6
- package/dist/index.cjs +1308 -925
- package/dist/index.d.cts +92 -1
- package/dist/index.d.ts +92 -1
- package/dist/index.js +746 -715
- package/dist/mcp/run-stdio.cjs +1267 -976
- package/dist/mcp/run-stdio.js +691 -748
- package/dist/{run-HZTBWGQR.js → run-74S2NZWB.js} +1 -1
- package/dist/{run-GPSVV5OH.js → run-JLN5JK7Q.js} +1 -1
- package/dist/{workspaces-VCAIHVIE.js → workspaces-OVBCSS5Y.js} +6 -7
- package/dist/{workspaces-E75POJXP.js → workspaces-RXFXQRRF.js} +6 -7
- package/dist/{worktree-MV4WRW6G.js → worktree-K2JB53R5.js} +2 -2
- package/dist/{worktree-LZEGVQSN.js → worktree-S2N63FLV.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-GI7E5733.js +0 -30
- package/dist/chunk-S2LL5HA4.js +0 -33
|
@@ -6,20 +6,29 @@ import {
|
|
|
6
6
|
ensureCliTeamTracked,
|
|
7
7
|
ensureConnectedBrightsyTeamTokens,
|
|
8
8
|
loadBrightsyConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-EVD4KNKR.js";
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
isOrchestratorThread
|
|
12
|
+
} from "./chunk-DNPP7QMK.js";
|
|
13
|
+
import {
|
|
14
|
+
enrichPathWithNpmGlobalBin,
|
|
15
|
+
resolveCommandBinarySync,
|
|
16
|
+
run,
|
|
17
|
+
withExportedPath
|
|
18
|
+
} from "./chunk-5AG5BUQN.js";
|
|
14
19
|
import {
|
|
15
20
|
claudeChromeEnabled,
|
|
16
21
|
loadAppSettings,
|
|
22
|
+
resolveAgentExecutable,
|
|
17
23
|
resolveClaudeExecutable
|
|
18
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-BPOTVI5J.js";
|
|
19
25
|
import {
|
|
20
26
|
appDataDir
|
|
21
27
|
} from "./chunk-7MV3RXSC.js";
|
|
22
28
|
|
|
29
|
+
// src/agents/brightsy.ts
|
|
30
|
+
import { existsSync } from "fs";
|
|
31
|
+
|
|
23
32
|
// src/agents/brightsy-targets.ts
|
|
24
33
|
function encodeBrightsyTarget(type, id, accountId) {
|
|
25
34
|
if (accountId) return `team:${accountId}:${type}:${id}`;
|
|
@@ -176,6 +185,11 @@ function normalizeTurnInput(input) {
|
|
|
176
185
|
if (typeof input === "string") return { prompt: input };
|
|
177
186
|
return { prompt: input.prompt, cachedPrefix: input.cachedPrefix?.trim() || void 0 };
|
|
178
187
|
}
|
|
188
|
+
function dropCachedPrefixOnResume(input, sessionId) {
|
|
189
|
+
const turn = normalizeTurnInput(input);
|
|
190
|
+
if (sessionId) return { prompt: turn.prompt };
|
|
191
|
+
return turn;
|
|
192
|
+
}
|
|
179
193
|
function flattenTurnInput(input) {
|
|
180
194
|
const { cachedPrefix, prompt } = normalizeTurnInput(input);
|
|
181
195
|
if (!cachedPrefix) return prompt;
|
|
@@ -315,9 +329,13 @@ async function fetchTeamChatTargets(team) {
|
|
|
315
329
|
};
|
|
316
330
|
}
|
|
317
331
|
async function listBrightsyChatTargetsViaCli() {
|
|
318
|
-
const listed = await run(
|
|
319
|
-
|
|
320
|
-
|
|
332
|
+
const listed = await run(
|
|
333
|
+
resolveAgentExecutable("brightsy"),
|
|
334
|
+
["chat", "--list-targets", "--json"],
|
|
335
|
+
{
|
|
336
|
+
reject: false
|
|
337
|
+
}
|
|
338
|
+
);
|
|
321
339
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
322
340
|
throw new Error(
|
|
323
341
|
listed.stderr.trim() || "Failed to list Brightsy chat targets \u2014 is `brightsy` installed and logged in?"
|
|
@@ -404,18 +422,32 @@ async function syncCliForTarget(accountId) {
|
|
|
404
422
|
var brightsyAdapter = {
|
|
405
423
|
kind: "brightsy",
|
|
406
424
|
async detect() {
|
|
407
|
-
const
|
|
408
|
-
if (
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
425
|
+
const brightsy = resolveAgentExecutable("brightsy");
|
|
426
|
+
if (brightsy !== "brightsy") {
|
|
427
|
+
if (!existsSync(brightsy)) {
|
|
428
|
+
return {
|
|
429
|
+
agent: "brightsy",
|
|
430
|
+
installed: false,
|
|
431
|
+
authenticated: false,
|
|
432
|
+
linearMcp: false,
|
|
433
|
+
warnings: [],
|
|
434
|
+
reason: `Brightsy executable not found: ${brightsy}`
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
} else {
|
|
438
|
+
const which = await run("which", ["brightsy"], { reject: false });
|
|
439
|
+
if (which.exitCode !== 0) {
|
|
440
|
+
return {
|
|
441
|
+
agent: "brightsy",
|
|
442
|
+
installed: false,
|
|
443
|
+
authenticated: false,
|
|
444
|
+
linearMcp: false,
|
|
445
|
+
warnings: [],
|
|
446
|
+
reason: "brightsy CLI not found on PATH \u2014 npm i -g @brightsy/cli"
|
|
447
|
+
};
|
|
448
|
+
}
|
|
417
449
|
}
|
|
418
|
-
const who = await run(
|
|
450
|
+
const who = await run(brightsy, ["whoami"], { reject: false });
|
|
419
451
|
const authenticated = who.exitCode === 0 && /logged in as/i.test(who.stdout);
|
|
420
452
|
return {
|
|
421
453
|
agent: "brightsy",
|
|
@@ -440,7 +472,7 @@ var brightsyAdapter = {
|
|
|
440
472
|
target.id
|
|
441
473
|
];
|
|
442
474
|
return {
|
|
443
|
-
file: "brightsy",
|
|
475
|
+
file: resolveAgentExecutable("brightsy"),
|
|
444
476
|
args,
|
|
445
477
|
cwd: thread.worktreePath,
|
|
446
478
|
// Piped stdin becomes the message body (avoids ARG_MAX for long seeds).
|
|
@@ -457,12 +489,16 @@ var brightsyAdapter = {
|
|
|
457
489
|
const target = decodeBrightsyTarget(thread.model);
|
|
458
490
|
await syncCliForTarget(target.accountId);
|
|
459
491
|
const args = target.type === "model" ? ["chat", "--model", target.id] : ["chat", "--agent", target.id];
|
|
460
|
-
return {
|
|
492
|
+
return {
|
|
493
|
+
file: resolveAgentExecutable("brightsy"),
|
|
494
|
+
args,
|
|
495
|
+
cwd: thread.worktreePath
|
|
496
|
+
};
|
|
461
497
|
}
|
|
462
498
|
};
|
|
463
499
|
|
|
464
500
|
// src/agents/claude.ts
|
|
465
|
-
import { existsSync as
|
|
501
|
+
import { existsSync as existsSync3 } from "fs";
|
|
466
502
|
|
|
467
503
|
// src/agents/claude-mcp.ts
|
|
468
504
|
function parseMcpList(text) {
|
|
@@ -499,12 +535,18 @@ function mcpAllowTools(servers) {
|
|
|
499
535
|
}
|
|
500
536
|
|
|
501
537
|
// src/agents/injected-mcp.ts
|
|
502
|
-
import { existsSync, mkdtempSync, writeFileSync } from "fs";
|
|
538
|
+
import { existsSync as existsSync2, mkdtempSync, writeFileSync } from "fs";
|
|
503
539
|
import { createRequire } from "module";
|
|
504
540
|
import { tmpdir } from "os";
|
|
505
541
|
import { dirname, join } from "path";
|
|
506
542
|
import { fileURLToPath } from "url";
|
|
507
543
|
|
|
544
|
+
// src/mcp/profile.ts
|
|
545
|
+
var SIDEBOARD_MCP_PROFILE_ENV = "SIDEBOARD_MCP_PROFILE";
|
|
546
|
+
function sideboardMcpProfile(env = process.env) {
|
|
547
|
+
return env[SIDEBOARD_MCP_PROFILE_ENV]?.trim().toLowerCase() === "worktree" ? "worktree" : "orchestration";
|
|
548
|
+
}
|
|
549
|
+
|
|
508
550
|
// src/agents/node-launch.ts
|
|
509
551
|
function isAsarPath(filePath) {
|
|
510
552
|
return /\.asar([/\\]|$)/.test(filePath);
|
|
@@ -558,6 +600,39 @@ function isBrightsyConnected() {
|
|
|
558
600
|
return false;
|
|
559
601
|
}
|
|
560
602
|
}
|
|
603
|
+
var BRIGHTSY_WORD = /(?<![a-z0-9_-])brightsy(?![a-z0-9_-])/i;
|
|
604
|
+
function promptMentionsBrightsy(text) {
|
|
605
|
+
return BRIGHTSY_WORD.test(text ?? "");
|
|
606
|
+
}
|
|
607
|
+
function isBrightsyMcpToolName(name) {
|
|
608
|
+
const n = name.toLowerCase();
|
|
609
|
+
return n === "brightsy" || n.startsWith("mcp__brightsy") || n.startsWith("brightsy_");
|
|
610
|
+
}
|
|
611
|
+
function toolInputUsesBrightsyDatasource(input) {
|
|
612
|
+
const ds = input?.datasource;
|
|
613
|
+
return typeof ds === "string" && ds.toLowerCase() === "brightsy";
|
|
614
|
+
}
|
|
615
|
+
function messageUsedBrightsyMcp(msg) {
|
|
616
|
+
if (msg.role === "user" && promptMentionsBrightsy(msg.text)) return true;
|
|
617
|
+
for (const part of msg.parts ?? []) {
|
|
618
|
+
if (part.type !== "tool") continue;
|
|
619
|
+
if (isBrightsyMcpToolName(part.name)) return true;
|
|
620
|
+
if (/present_(schema|files)$/i.test(part.name) && toolInputUsesBrightsyDatasource(part.input)) {
|
|
621
|
+
return true;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
return false;
|
|
625
|
+
}
|
|
626
|
+
function threadRequestsBrightsyMcp(thread) {
|
|
627
|
+
return (thread?.messages ?? []).some(messageUsedBrightsyMcp);
|
|
628
|
+
}
|
|
629
|
+
function shouldInjectBrightsyMcp(thread, opts) {
|
|
630
|
+
if (!(opts?.connected ?? isBrightsyConnected())) return false;
|
|
631
|
+
if (opts?.orchestrator) return true;
|
|
632
|
+
const alwaysOn = opts?.alwaysOnWorktree ?? Boolean(loadAppSettings().brightsy?.injectWorktreeMcp);
|
|
633
|
+
if (alwaysOn) return true;
|
|
634
|
+
return threadRequestsBrightsyMcp(thread);
|
|
635
|
+
}
|
|
561
636
|
function mcpLaunch(cmd, name, env) {
|
|
562
637
|
if (cmd === "brightsy-mcp") {
|
|
563
638
|
return { name, command: "brightsy-mcp", ...env ? { env } : {} };
|
|
@@ -603,7 +678,7 @@ function corePackageDir() {
|
|
|
603
678
|
}
|
|
604
679
|
function findSideboardMcpJsEntry() {
|
|
605
680
|
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
606
|
-
if (override &&
|
|
681
|
+
if (override && existsSync2(override)) return override;
|
|
607
682
|
let dir = corePackageDir();
|
|
608
683
|
for (let i = 0; i < 10; i++) {
|
|
609
684
|
const candidates = [
|
|
@@ -616,7 +691,7 @@ function findSideboardMcpJsEntry() {
|
|
|
616
691
|
join(dir, "cli/dist/index.js")
|
|
617
692
|
];
|
|
618
693
|
for (const p of candidates) {
|
|
619
|
-
if (
|
|
694
|
+
if (existsSync2(p)) return p;
|
|
620
695
|
}
|
|
621
696
|
const parent = dirname(dir);
|
|
622
697
|
if (parent === dir) break;
|
|
@@ -647,11 +722,13 @@ async function buildInjectedMcpServers(opts) {
|
|
|
647
722
|
const servers = [];
|
|
648
723
|
if (opts.includeSideboard) {
|
|
649
724
|
const sideboard = await resolveSideboardMcpServer();
|
|
725
|
+
const orchId = opts.orchestratorThreadId?.trim();
|
|
726
|
+
const profile = orchId ? "orchestration" : "worktree";
|
|
650
727
|
sideboard.env = {
|
|
651
728
|
...sideboard.env ?? {},
|
|
652
|
-
SIDEBOARD_APP_DATA: appDataDir()
|
|
729
|
+
SIDEBOARD_APP_DATA: appDataDir(),
|
|
730
|
+
[SIDEBOARD_MCP_PROFILE_ENV]: profile
|
|
653
731
|
};
|
|
654
|
-
const orchId = opts.orchestratorThreadId?.trim();
|
|
655
732
|
if (orchId) {
|
|
656
733
|
sideboard.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID = orchId;
|
|
657
734
|
}
|
|
@@ -873,7 +950,7 @@ var claudeAdapter = {
|
|
|
873
950
|
async detect() {
|
|
874
951
|
const claude = resolveClaudeExecutable();
|
|
875
952
|
if (claude !== "claude") {
|
|
876
|
-
if (!
|
|
953
|
+
if (!existsSync3(claude)) {
|
|
877
954
|
return {
|
|
878
955
|
agent: "claude",
|
|
879
956
|
installed: false,
|
|
@@ -912,9 +989,8 @@ var claudeAdapter = {
|
|
|
912
989
|
},
|
|
913
990
|
async buildTurn(thread, input) {
|
|
914
991
|
const claude = resolveClaudeExecutable();
|
|
915
|
-
const turn = normalizeTurnInput(input);
|
|
916
992
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
917
|
-
const effective = sessionId
|
|
993
|
+
const effective = dropCachedPrefixOnResume(input, sessionId);
|
|
918
994
|
const promptText = flattenTurnInput(effective);
|
|
919
995
|
const useStdin = promptText.length > CLAUDE_PROMPT_ARG_MAX;
|
|
920
996
|
if (process.env.SIDEBOARD_DEBUG_CLAUDE_TURN === "1") {
|
|
@@ -923,11 +999,13 @@ var claudeAdapter = {
|
|
|
923
999
|
);
|
|
924
1000
|
}
|
|
925
1001
|
const mode = permissionMode(thread);
|
|
926
|
-
const { isOrchestratorThread } = await import("./global-workspace-
|
|
927
|
-
const isOrchestrator =
|
|
1002
|
+
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-5PM5LA6E.js");
|
|
1003
|
+
const isOrchestrator = isOrchestratorThread2(thread);
|
|
928
1004
|
const injectedServers = await buildInjectedMcpServers({
|
|
929
1005
|
includeSideboard: true,
|
|
930
|
-
includeBrightsy:
|
|
1006
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
1007
|
+
orchestrator: isOrchestrator
|
|
1008
|
+
}),
|
|
931
1009
|
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
932
1010
|
});
|
|
933
1011
|
const injectedBrightsyNames = injectedServers.filter((s) => s.name === "brightsy" || s.name.startsWith("brightsy_")).map((s) => s.name);
|
|
@@ -1119,7 +1197,7 @@ function parseIssuesJson(raw) {
|
|
|
1119
1197
|
}
|
|
1120
1198
|
|
|
1121
1199
|
// src/agents/codex.ts
|
|
1122
|
-
import { existsSync as
|
|
1200
|
+
import { existsSync as existsSync4, readFileSync, statSync } from "fs";
|
|
1123
1201
|
import { homedir } from "os";
|
|
1124
1202
|
import { join as join2 } from "path";
|
|
1125
1203
|
var CODEX_PROMPT_ARG_MAX = 2e5;
|
|
@@ -1137,9 +1215,14 @@ async function listCodexModels() {
|
|
|
1137
1215
|
if (cachedCodexModels && now - cachedCodexModels.at < CODEX_MODEL_CACHE_MS) {
|
|
1138
1216
|
return cachedCodexModels.models;
|
|
1139
1217
|
}
|
|
1140
|
-
const
|
|
1141
|
-
if (
|
|
1142
|
-
|
|
1218
|
+
const codex = resolveAgentExecutable("codex");
|
|
1219
|
+
if (codex === "codex") {
|
|
1220
|
+
const which = await run("which", ["codex"], { reject: false });
|
|
1221
|
+
if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
|
|
1222
|
+
} else if (!existsSync4(codex)) {
|
|
1223
|
+
return FALLBACK_CODEX_MODELS;
|
|
1224
|
+
}
|
|
1225
|
+
const listed = await run(codex, ["debug", "models"], { reject: false });
|
|
1143
1226
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
1144
1227
|
return cachedCodexModels?.models ?? FALLBACK_CODEX_MODELS;
|
|
1145
1228
|
}
|
|
@@ -1178,7 +1261,7 @@ function codexConfigHasNetworkAccess() {
|
|
|
1178
1261
|
join2(homedir(), ".config", "codex", "config.toml")
|
|
1179
1262
|
];
|
|
1180
1263
|
for (const path of candidates) {
|
|
1181
|
-
if (!
|
|
1264
|
+
if (!existsSync4(path)) continue;
|
|
1182
1265
|
const text = readFileSync(path, "utf8");
|
|
1183
1266
|
if (/network_access\s*=\s*true/.test(text)) return true;
|
|
1184
1267
|
}
|
|
@@ -1212,7 +1295,7 @@ function asRecord(value) {
|
|
|
1212
1295
|
}
|
|
1213
1296
|
function codexLooksAuthenticated() {
|
|
1214
1297
|
const authPath = join2(homedir(), ".codex", "auth.json");
|
|
1215
|
-
if (!
|
|
1298
|
+
if (!existsSync4(authPath)) return false;
|
|
1216
1299
|
try {
|
|
1217
1300
|
return statSync(authPath).size > 2;
|
|
1218
1301
|
} catch {
|
|
@@ -1222,16 +1305,30 @@ function codexLooksAuthenticated() {
|
|
|
1222
1305
|
var codexAdapter = {
|
|
1223
1306
|
kind: "codex",
|
|
1224
1307
|
async detect() {
|
|
1225
|
-
const
|
|
1226
|
-
if (
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1308
|
+
const codex = resolveAgentExecutable("codex");
|
|
1309
|
+
if (codex !== "codex") {
|
|
1310
|
+
if (!existsSync4(codex)) {
|
|
1311
|
+
return {
|
|
1312
|
+
agent: "codex",
|
|
1313
|
+
installed: false,
|
|
1314
|
+
authenticated: false,
|
|
1315
|
+
linearMcp: false,
|
|
1316
|
+
warnings: [],
|
|
1317
|
+
reason: `Codex executable not found: ${codex}`
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
} else {
|
|
1321
|
+
const which = await run("which", ["codex"], { reject: false, timeoutMs: 3e3 });
|
|
1322
|
+
if (which.exitCode !== 0) {
|
|
1323
|
+
return {
|
|
1324
|
+
agent: "codex",
|
|
1325
|
+
installed: false,
|
|
1326
|
+
authenticated: false,
|
|
1327
|
+
linearMcp: false,
|
|
1328
|
+
warnings: [],
|
|
1329
|
+
reason: "codex CLI not found on PATH"
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1235
1332
|
}
|
|
1236
1333
|
const authenticated = codexLooksAuthenticated();
|
|
1237
1334
|
const linearMcp = false;
|
|
@@ -1251,22 +1348,24 @@ var codexAdapter = {
|
|
|
1251
1348
|
};
|
|
1252
1349
|
},
|
|
1253
1350
|
async buildTurn(thread, input) {
|
|
1254
|
-
const prompt = flattenTurnInput(input);
|
|
1255
1351
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
1352
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, sessionId));
|
|
1256
1353
|
const useStdin = prompt.length > CODEX_PROMPT_ARG_MAX;
|
|
1257
1354
|
const promptArg = useStdin ? "-" : prompt;
|
|
1258
1355
|
if (process.env.SIDEBOARD_DEBUG_CODEX_TURN === "1") {
|
|
1259
|
-
const { cachedPrefix } = normalizeTurnInput(input);
|
|
1260
1356
|
console.error(
|
|
1261
|
-
`[sideboard/codex] promptChars=${prompt.length} resumed=${Boolean(sessionId)} stdin=${useStdin} hasPrefix=${
|
|
1357
|
+
`[sideboard/codex] promptChars=${prompt.length} resumed=${Boolean(sessionId)} stdin=${useStdin} hasPrefix=${prompt.includes("Current request:")}`
|
|
1262
1358
|
);
|
|
1263
1359
|
}
|
|
1264
1360
|
const mode = permissionMode(thread);
|
|
1265
1361
|
const model = thread.model?.trim();
|
|
1362
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
1266
1363
|
const injected = await buildInjectedMcpServers({
|
|
1267
1364
|
includeSideboard: true,
|
|
1268
|
-
includeBrightsy:
|
|
1269
|
-
|
|
1365
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
1366
|
+
orchestrator: isOrchestrator
|
|
1367
|
+
}),
|
|
1368
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
1270
1369
|
});
|
|
1271
1370
|
const mcpOverrides = toCodexMcpConfigArgs(injected);
|
|
1272
1371
|
const execOpts = [
|
|
@@ -1286,7 +1385,7 @@ var codexAdapter = {
|
|
|
1286
1385
|
];
|
|
1287
1386
|
const args = sessionId ? ["exec", ...execOpts, "resume", sessionId, promptArg] : ["exec", ...execOpts, promptArg];
|
|
1288
1387
|
return {
|
|
1289
|
-
file: "codex",
|
|
1388
|
+
file: resolveAgentExecutable("codex"),
|
|
1290
1389
|
args,
|
|
1291
1390
|
cwd: thread.worktreePath,
|
|
1292
1391
|
stdin: useStdin ? `${prompt}
|
|
@@ -1382,16 +1481,17 @@ var codexAdapter = {
|
|
|
1382
1481
|
return cached;
|
|
1383
1482
|
},
|
|
1384
1483
|
async buildAttach(thread) {
|
|
1484
|
+
const codex = resolveAgentExecutable("codex");
|
|
1385
1485
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
1386
1486
|
if (sessionId) {
|
|
1387
1487
|
return {
|
|
1388
|
-
file:
|
|
1488
|
+
file: codex,
|
|
1389
1489
|
args: ["exec", "--cd", thread.worktreePath, "resume", sessionId],
|
|
1390
1490
|
cwd: thread.worktreePath
|
|
1391
1491
|
};
|
|
1392
1492
|
}
|
|
1393
1493
|
return {
|
|
1394
|
-
file:
|
|
1494
|
+
file: codex,
|
|
1395
1495
|
args: ["--cd", thread.worktreePath],
|
|
1396
1496
|
cwd: thread.worktreePath
|
|
1397
1497
|
};
|
|
@@ -1399,7 +1499,7 @@ var codexAdapter = {
|
|
|
1399
1499
|
async listLinearIssues(_repoPath) {
|
|
1400
1500
|
const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
|
|
1401
1501
|
const { stdout, exitCode } = await run(
|
|
1402
|
-
"codex",
|
|
1502
|
+
resolveAgentExecutable("codex"),
|
|
1403
1503
|
[
|
|
1404
1504
|
"exec",
|
|
1405
1505
|
"--json",
|
|
@@ -1424,7 +1524,7 @@ var codexAdapter = {
|
|
|
1424
1524
|
};
|
|
1425
1525
|
|
|
1426
1526
|
// src/agents/cursor.ts
|
|
1427
|
-
import { existsSync as
|
|
1527
|
+
import { existsSync as existsSync5 } from "fs";
|
|
1428
1528
|
import { createRequire as createRequire2 } from "module";
|
|
1429
1529
|
import { dirname as dirname2, join as join3 } from "path";
|
|
1430
1530
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
@@ -1668,7 +1768,7 @@ function cursorRunnerPath() {
|
|
|
1668
1768
|
join3(root, "src", "agents", "cursor-runner.ts")
|
|
1669
1769
|
];
|
|
1670
1770
|
for (const candidate of candidates) {
|
|
1671
|
-
if (
|
|
1771
|
+
if (existsSync5(candidate)) return candidate;
|
|
1672
1772
|
}
|
|
1673
1773
|
return candidates[0];
|
|
1674
1774
|
}
|
|
@@ -1695,13 +1795,16 @@ var cursorAdapter = {
|
|
|
1695
1795
|
};
|
|
1696
1796
|
},
|
|
1697
1797
|
async buildTurn(thread, input) {
|
|
1698
|
-
const prompt = flattenTurnInput(input);
|
|
1699
1798
|
const agentId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
1799
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, agentId));
|
|
1700
1800
|
const apiKey = resolveCursorApiKey() || void 0;
|
|
1801
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
1701
1802
|
const injected = await buildInjectedMcpServers({
|
|
1702
1803
|
includeSideboard: true,
|
|
1703
|
-
includeBrightsy:
|
|
1704
|
-
|
|
1804
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
1805
|
+
orchestrator: isOrchestrator
|
|
1806
|
+
}),
|
|
1807
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
1705
1808
|
});
|
|
1706
1809
|
const mcpServers = toCursorMcpServers(injected);
|
|
1707
1810
|
const req = {
|
|
@@ -1747,6 +1850,7 @@ var cursorAdapter = {
|
|
|
1747
1850
|
};
|
|
1748
1851
|
|
|
1749
1852
|
// src/agents/opencode.ts
|
|
1853
|
+
import { existsSync as existsSync6 } from "fs";
|
|
1750
1854
|
var FALLBACK_OPENCODE_MODELS = [
|
|
1751
1855
|
{ id: "opencode/big-pickle", displayName: "opencode \xB7 big-pickle" },
|
|
1752
1856
|
{
|
|
@@ -1783,9 +1887,14 @@ async function listOpencodeModels() {
|
|
|
1783
1887
|
if (cachedOpencodeModels && now - cachedOpencodeModels.at < OPENCODE_MODEL_CACHE_MS) {
|
|
1784
1888
|
return cachedOpencodeModels.models;
|
|
1785
1889
|
}
|
|
1786
|
-
const
|
|
1787
|
-
if (
|
|
1788
|
-
|
|
1890
|
+
const opencode = resolveAgentExecutable("opencode");
|
|
1891
|
+
if (opencode === "opencode") {
|
|
1892
|
+
const which = await run("which", ["opencode"], { reject: false });
|
|
1893
|
+
if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
|
|
1894
|
+
} else if (!existsSync6(opencode)) {
|
|
1895
|
+
return FALLBACK_OPENCODE_MODELS;
|
|
1896
|
+
}
|
|
1897
|
+
const listed = await run(opencode, ["models"], { reject: false });
|
|
1789
1898
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
1790
1899
|
return cachedOpencodeModels?.models ?? FALLBACK_OPENCODE_MODELS;
|
|
1791
1900
|
}
|
|
@@ -1815,20 +1924,34 @@ function usageFromOpencode(tokens) {
|
|
|
1815
1924
|
var opencodeAdapter = {
|
|
1816
1925
|
kind: "opencode",
|
|
1817
1926
|
async detect() {
|
|
1818
|
-
const
|
|
1819
|
-
if (
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1927
|
+
const opencode = resolveAgentExecutable("opencode");
|
|
1928
|
+
if (opencode !== "opencode") {
|
|
1929
|
+
if (!existsSync6(opencode)) {
|
|
1930
|
+
return {
|
|
1931
|
+
agent: "opencode",
|
|
1932
|
+
installed: false,
|
|
1933
|
+
authenticated: false,
|
|
1934
|
+
linearMcp: false,
|
|
1935
|
+
warnings: [],
|
|
1936
|
+
reason: `OpenCode executable not found: ${opencode}`
|
|
1937
|
+
};
|
|
1938
|
+
}
|
|
1939
|
+
} else {
|
|
1940
|
+
const which = await run("which", ["opencode"], { reject: false });
|
|
1941
|
+
if (which.exitCode !== 0) {
|
|
1942
|
+
return {
|
|
1943
|
+
agent: "opencode",
|
|
1944
|
+
installed: false,
|
|
1945
|
+
authenticated: false,
|
|
1946
|
+
linearMcp: false,
|
|
1947
|
+
warnings: [],
|
|
1948
|
+
reason: "opencode CLI not found on PATH"
|
|
1949
|
+
};
|
|
1950
|
+
}
|
|
1828
1951
|
}
|
|
1829
|
-
const auth = await run(
|
|
1952
|
+
const auth = await run(opencode, ["auth", "list"], { reject: false });
|
|
1830
1953
|
const authenticated = auth.exitCode === 0 && auth.stdout.trim().length > 0;
|
|
1831
|
-
const mcp = await run(
|
|
1954
|
+
const mcp = await run(opencode, ["mcp", "list"], { reject: false });
|
|
1832
1955
|
const linearMcp = /linear/i.test(mcp.stdout + mcp.stderr);
|
|
1833
1956
|
return {
|
|
1834
1957
|
agent: "opencode",
|
|
@@ -1840,8 +1963,8 @@ var opencodeAdapter = {
|
|
|
1840
1963
|
};
|
|
1841
1964
|
},
|
|
1842
1965
|
async buildTurn(thread, input) {
|
|
1843
|
-
const prompt = flattenTurnInput(input);
|
|
1844
1966
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
1967
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, sessionId));
|
|
1845
1968
|
const mode = permissionMode(thread);
|
|
1846
1969
|
const model = thread.model?.trim();
|
|
1847
1970
|
const args = [
|
|
@@ -1857,14 +1980,17 @@ var opencodeAdapter = {
|
|
|
1857
1980
|
if (model) {
|
|
1858
1981
|
args.push("--model", model);
|
|
1859
1982
|
}
|
|
1983
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
1860
1984
|
const injected = await buildInjectedMcpServers({
|
|
1861
1985
|
includeSideboard: true,
|
|
1862
|
-
includeBrightsy:
|
|
1863
|
-
|
|
1986
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
1987
|
+
orchestrator: isOrchestrator
|
|
1988
|
+
}),
|
|
1989
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
1864
1990
|
});
|
|
1865
1991
|
const mcpContent = injected.length > 0 ? toOpencodeMcpConfigContent(injected) : null;
|
|
1866
1992
|
return {
|
|
1867
|
-
file: "opencode",
|
|
1993
|
+
file: resolveAgentExecutable("opencode"),
|
|
1868
1994
|
args,
|
|
1869
1995
|
cwd: thread.worktreePath,
|
|
1870
1996
|
// `opencode run` treats non-TTY stdin as the message body when no positional
|
|
@@ -1940,7 +2066,7 @@ var opencodeAdapter = {
|
|
|
1940
2066
|
async resolveSessionId(worktreePath, cached) {
|
|
1941
2067
|
const cachedId = cached?.trim() || null;
|
|
1942
2068
|
const listed = await run(
|
|
1943
|
-
"opencode",
|
|
2069
|
+
resolveAgentExecutable("opencode"),
|
|
1944
2070
|
["session", "list", "--format", "json"],
|
|
1945
2071
|
{ cwd: worktreePath, reject: false }
|
|
1946
2072
|
);
|
|
@@ -1971,7 +2097,7 @@ var opencodeAdapter = {
|
|
|
1971
2097
|
const args = ["--dir", thread.worktreePath];
|
|
1972
2098
|
if (sessionId) args.push("--session", sessionId);
|
|
1973
2099
|
return {
|
|
1974
|
-
file: "opencode",
|
|
2100
|
+
file: resolveAgentExecutable("opencode"),
|
|
1975
2101
|
args,
|
|
1976
2102
|
cwd: thread.worktreePath,
|
|
1977
2103
|
env: {
|
|
@@ -1982,7 +2108,7 @@ var opencodeAdapter = {
|
|
|
1982
2108
|
async listLinearIssues(_repoPath) {
|
|
1983
2109
|
const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
|
|
1984
2110
|
const { stdout, exitCode } = await run(
|
|
1985
|
-
"opencode",
|
|
2111
|
+
resolveAgentExecutable("opencode"),
|
|
1986
2112
|
["run", prompt, "--format", "json"],
|
|
1987
2113
|
{
|
|
1988
2114
|
reject: false,
|
|
@@ -2237,15 +2363,48 @@ var SETUP = {
|
|
|
2237
2363
|
npmPackage: "@brightsy/cli"
|
|
2238
2364
|
}
|
|
2239
2365
|
};
|
|
2366
|
+
var CLI_BIN = {
|
|
2367
|
+
claude: "claude",
|
|
2368
|
+
codex: "codex",
|
|
2369
|
+
opencode: "opencode",
|
|
2370
|
+
brightsy: "brightsy"
|
|
2371
|
+
};
|
|
2240
2372
|
function getAgentSetupInfo(agent) {
|
|
2241
2373
|
return SETUP[agent];
|
|
2242
2374
|
}
|
|
2243
2375
|
function listAgentSetupInfo() {
|
|
2244
2376
|
return Object.values(SETUP);
|
|
2245
2377
|
}
|
|
2246
|
-
|
|
2247
|
-
|
|
2378
|
+
var CLI_LOGIN_AGENTS = /* @__PURE__ */ new Set([
|
|
2379
|
+
"claude",
|
|
2380
|
+
"codex",
|
|
2381
|
+
"opencode",
|
|
2382
|
+
"brightsy"
|
|
2383
|
+
]);
|
|
2384
|
+
function resolveLoginCommand(agent) {
|
|
2385
|
+
const info = getAgentSetupInfo(agent);
|
|
2386
|
+
if (!info.loginCommand) return null;
|
|
2387
|
+
if (!CLI_LOGIN_AGENTS.has(agent)) return info.loginCommand;
|
|
2388
|
+
const exe = resolveAgentExecutable(agent);
|
|
2389
|
+
return info.loginCommand.replace(/^\S+/, exe);
|
|
2390
|
+
}
|
|
2391
|
+
async function prepareTerminalCommand(command) {
|
|
2392
|
+
enrichPathWithNpmGlobalBin();
|
|
2248
2393
|
const trimmed = command.trim();
|
|
2394
|
+
if (!trimmed) return trimmed;
|
|
2395
|
+
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
2396
|
+
const match = /^(\S+)(\s[\s\S]*)?$/.exec(trimmed);
|
|
2397
|
+
const bin = match?.[1];
|
|
2398
|
+
let whichPath = null;
|
|
2399
|
+
if (bin && !bin.includes("/") && !bin.includes("\\")) {
|
|
2400
|
+
const which = await run("which", [bin], { reject: false, timeoutMs: 3e3 });
|
|
2401
|
+
whichPath = which.exitCode === 0 ? which.stdout.trim() : null;
|
|
2402
|
+
}
|
|
2403
|
+
const resolved = resolveCommandBinarySync(trimmed, whichPath);
|
|
2404
|
+
return withExportedPath(resolved, process.env.PATH ?? "");
|
|
2405
|
+
}
|
|
2406
|
+
async function openInSystemTerminal(command) {
|
|
2407
|
+
const trimmed = (await prepareTerminalCommand(command)).trim();
|
|
2249
2408
|
if (!trimmed) throw new Error("Command is empty");
|
|
2250
2409
|
if (process.platform === "darwin") {
|
|
2251
2410
|
const escaped = trimmed.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
@@ -2306,7 +2465,7 @@ async function installAgent(agent) {
|
|
|
2306
2465
|
message: `Opened Terminal to run: ${info.installCommand}`
|
|
2307
2466
|
};
|
|
2308
2467
|
}
|
|
2309
|
-
|
|
2468
|
+
enrichPathWithNpmGlobalBin();
|
|
2310
2469
|
const result = await run("npm", ["install", "-g", info.npmPackage], { reject: false });
|
|
2311
2470
|
const ok = result.exitCode === 0;
|
|
2312
2471
|
if (!ok) {
|
|
@@ -2332,29 +2491,38 @@ async function installAgent(agent) {
|
|
|
2332
2491
|
};
|
|
2333
2492
|
}
|
|
2334
2493
|
}
|
|
2494
|
+
enrichPathWithNpmGlobalBin();
|
|
2495
|
+
const cliBin = agent === "cursor" ? null : CLI_BIN[agent];
|
|
2496
|
+
let binPath = null;
|
|
2497
|
+
if (cliBin) {
|
|
2498
|
+
const which = await run("which", [cliBin], { reject: false, timeoutMs: 3e3 });
|
|
2499
|
+
binPath = which.exitCode === 0 ? which.stdout.trim().split(/\r?\n/).find(Boolean) ?? null : null;
|
|
2500
|
+
}
|
|
2335
2501
|
return {
|
|
2336
2502
|
ok: true,
|
|
2337
2503
|
command: info.installCommand,
|
|
2338
2504
|
exitCode: 0,
|
|
2339
2505
|
stdout: result.stdout,
|
|
2340
2506
|
stderr: result.stderr,
|
|
2341
|
-
message: `Installed ${info.npmPackage}`
|
|
2507
|
+
message: binPath ? `Installed ${info.npmPackage} \u2192 ${binPath}` : `Installed ${info.npmPackage} (CLI not yet on PATH \u2014 Log in still exports Electron\u2019s PATH into Terminal)`
|
|
2342
2508
|
};
|
|
2343
2509
|
}
|
|
2344
2510
|
async function loginAgent(agent) {
|
|
2345
2511
|
const info = getAgentSetupInfo(agent);
|
|
2346
|
-
|
|
2512
|
+
const loginCommand = resolveLoginCommand(agent);
|
|
2513
|
+
if (!loginCommand) {
|
|
2347
2514
|
return {
|
|
2348
2515
|
ok: true,
|
|
2349
2516
|
message: info.kind === "bundled-sdk" || info.kind === "api-key" ? info.summary : `No login command for ${agent}`
|
|
2350
2517
|
};
|
|
2351
2518
|
}
|
|
2352
|
-
await
|
|
2519
|
+
const prepared = await prepareTerminalCommand(loginCommand);
|
|
2520
|
+
await openInSystemTerminal(prepared);
|
|
2353
2521
|
return {
|
|
2354
2522
|
ok: true,
|
|
2355
2523
|
openedTerminal: true,
|
|
2356
|
-
command:
|
|
2357
|
-
message: `Opened Terminal to run: ${
|
|
2524
|
+
command: prepared,
|
|
2525
|
+
message: `Opened Terminal to run: ${prepared}`
|
|
2358
2526
|
};
|
|
2359
2527
|
}
|
|
2360
2528
|
|
|
@@ -2386,6 +2554,7 @@ export {
|
|
|
2386
2554
|
parseBrightsyCliLine,
|
|
2387
2555
|
listBrightsyChatTargets,
|
|
2388
2556
|
brightsyAdapter,
|
|
2557
|
+
sideboardMcpProfile,
|
|
2389
2558
|
PLAN_MODE_INSTRUCTION,
|
|
2390
2559
|
permissionMode,
|
|
2391
2560
|
claudeAdapter,
|
|
@@ -2406,6 +2575,8 @@ export {
|
|
|
2406
2575
|
resolveQuotaFallbackAgent,
|
|
2407
2576
|
getAgentSetupInfo,
|
|
2408
2577
|
listAgentSetupInfo,
|
|
2578
|
+
resolveLoginCommand,
|
|
2579
|
+
prepareTerminalCommand,
|
|
2409
2580
|
openInSystemTerminal,
|
|
2410
2581
|
installAgent,
|
|
2411
2582
|
loginAgent,
|