@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
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isOrchestratorThread
|
|
3
|
+
} from "./chunk-YTNLOJPK.js";
|
|
1
4
|
import {
|
|
2
5
|
applyConnectedTeamToCli,
|
|
3
6
|
brightsyMcpServerName,
|
|
4
7
|
ensureCliTeamTracked,
|
|
5
8
|
ensureConnectedBrightsyTeamTokens,
|
|
6
9
|
loadBrightsyConfig
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-DZYMNW2A.js";
|
|
8
11
|
import {
|
|
9
12
|
extractJsonErrorMessage,
|
|
10
13
|
formatUnknownDetail,
|
|
@@ -14,15 +17,21 @@ import {
|
|
|
14
17
|
import {
|
|
15
18
|
claudeChromeEnabled,
|
|
16
19
|
loadAppSettings,
|
|
20
|
+
resolveAgentExecutable,
|
|
17
21
|
resolveClaudeExecutable
|
|
18
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-MHR4OGZ4.js";
|
|
19
23
|
import {
|
|
20
24
|
appDataDir
|
|
21
25
|
} from "./chunk-M37RITA6.js";
|
|
22
26
|
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
enrichPathWithNpmGlobalBin,
|
|
28
|
+
resolveCommandBinarySync,
|
|
29
|
+
run,
|
|
30
|
+
withExportedPath
|
|
31
|
+
} from "./chunk-TXQ6K2GR.js";
|
|
32
|
+
|
|
33
|
+
// src/agents/brightsy.ts
|
|
34
|
+
import { existsSync } from "fs";
|
|
26
35
|
|
|
27
36
|
// src/agents/brightsy-targets.ts
|
|
28
37
|
function encodeBrightsyTarget(type, id, accountId) {
|
|
@@ -59,6 +68,11 @@ function normalizeTurnInput(input) {
|
|
|
59
68
|
if (typeof input === "string") return { prompt: input };
|
|
60
69
|
return { prompt: input.prompt, cachedPrefix: input.cachedPrefix?.trim() || void 0 };
|
|
61
70
|
}
|
|
71
|
+
function dropCachedPrefixOnResume(input, sessionId) {
|
|
72
|
+
const turn = normalizeTurnInput(input);
|
|
73
|
+
if (sessionId) return { prompt: turn.prompt };
|
|
74
|
+
return turn;
|
|
75
|
+
}
|
|
62
76
|
function flattenTurnInput(input) {
|
|
63
77
|
const { cachedPrefix, prompt } = normalizeTurnInput(input);
|
|
64
78
|
if (!cachedPrefix) return prompt;
|
|
@@ -241,9 +255,13 @@ async function fetchTeamChatTargets(team) {
|
|
|
241
255
|
};
|
|
242
256
|
}
|
|
243
257
|
async function listBrightsyChatTargetsViaCli() {
|
|
244
|
-
const listed = await run(
|
|
245
|
-
|
|
246
|
-
|
|
258
|
+
const listed = await run(
|
|
259
|
+
resolveAgentExecutable("brightsy"),
|
|
260
|
+
["chat", "--list-targets", "--json"],
|
|
261
|
+
{
|
|
262
|
+
reject: false
|
|
263
|
+
}
|
|
264
|
+
);
|
|
247
265
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
248
266
|
throw new Error(
|
|
249
267
|
listed.stderr.trim() || "Failed to list Brightsy chat targets \u2014 is `brightsy` installed and logged in?"
|
|
@@ -330,18 +348,32 @@ async function syncCliForTarget(accountId) {
|
|
|
330
348
|
var brightsyAdapter = {
|
|
331
349
|
kind: "brightsy",
|
|
332
350
|
async detect() {
|
|
333
|
-
const
|
|
334
|
-
if (
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
351
|
+
const brightsy = resolveAgentExecutable("brightsy");
|
|
352
|
+
if (brightsy !== "brightsy") {
|
|
353
|
+
if (!existsSync(brightsy)) {
|
|
354
|
+
return {
|
|
355
|
+
agent: "brightsy",
|
|
356
|
+
installed: false,
|
|
357
|
+
authenticated: false,
|
|
358
|
+
linearMcp: false,
|
|
359
|
+
warnings: [],
|
|
360
|
+
reason: `Brightsy executable not found: ${brightsy}`
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
} else {
|
|
364
|
+
const which = await run("which", ["brightsy"], { reject: false });
|
|
365
|
+
if (which.exitCode !== 0) {
|
|
366
|
+
return {
|
|
367
|
+
agent: "brightsy",
|
|
368
|
+
installed: false,
|
|
369
|
+
authenticated: false,
|
|
370
|
+
linearMcp: false,
|
|
371
|
+
warnings: [],
|
|
372
|
+
reason: "brightsy CLI not found on PATH \u2014 npm i -g @brightsy/cli"
|
|
373
|
+
};
|
|
374
|
+
}
|
|
343
375
|
}
|
|
344
|
-
const who = await run(
|
|
376
|
+
const who = await run(brightsy, ["whoami"], { reject: false });
|
|
345
377
|
const authenticated = who.exitCode === 0 && /logged in as/i.test(who.stdout);
|
|
346
378
|
return {
|
|
347
379
|
agent: "brightsy",
|
|
@@ -366,7 +398,7 @@ var brightsyAdapter = {
|
|
|
366
398
|
target.id
|
|
367
399
|
];
|
|
368
400
|
return {
|
|
369
|
-
file: "brightsy",
|
|
401
|
+
file: resolveAgentExecutable("brightsy"),
|
|
370
402
|
args,
|
|
371
403
|
cwd: thread.worktreePath,
|
|
372
404
|
// Piped stdin becomes the message body (avoids ARG_MAX for long seeds).
|
|
@@ -383,12 +415,16 @@ var brightsyAdapter = {
|
|
|
383
415
|
const target = decodeBrightsyTarget(thread.model);
|
|
384
416
|
await syncCliForTarget(target.accountId);
|
|
385
417
|
const args = target.type === "model" ? ["chat", "--model", target.id] : ["chat", "--agent", target.id];
|
|
386
|
-
return {
|
|
418
|
+
return {
|
|
419
|
+
file: resolveAgentExecutable("brightsy"),
|
|
420
|
+
args,
|
|
421
|
+
cwd: thread.worktreePath
|
|
422
|
+
};
|
|
387
423
|
}
|
|
388
424
|
};
|
|
389
425
|
|
|
390
426
|
// src/agents/claude.ts
|
|
391
|
-
import { existsSync as
|
|
427
|
+
import { existsSync as existsSync3 } from "fs";
|
|
392
428
|
|
|
393
429
|
// src/agents/claude-mcp.ts
|
|
394
430
|
function parseMcpList(text) {
|
|
@@ -432,12 +468,18 @@ function mcpAuthWarnings(servers) {
|
|
|
432
468
|
}
|
|
433
469
|
|
|
434
470
|
// src/agents/injected-mcp.ts
|
|
435
|
-
import { existsSync, mkdtempSync, writeFileSync } from "fs";
|
|
471
|
+
import { existsSync as existsSync2, mkdtempSync, writeFileSync } from "fs";
|
|
436
472
|
import { createRequire } from "module";
|
|
437
473
|
import { tmpdir } from "os";
|
|
438
474
|
import { dirname, join } from "path";
|
|
439
475
|
import { fileURLToPath } from "url";
|
|
440
476
|
|
|
477
|
+
// src/mcp/profile.ts
|
|
478
|
+
var SIDEBOARD_MCP_PROFILE_ENV = "SIDEBOARD_MCP_PROFILE";
|
|
479
|
+
function sideboardMcpProfile(env = process.env) {
|
|
480
|
+
return env[SIDEBOARD_MCP_PROFILE_ENV]?.trim().toLowerCase() === "worktree" ? "worktree" : "orchestration";
|
|
481
|
+
}
|
|
482
|
+
|
|
441
483
|
// src/agents/node-launch.ts
|
|
442
484
|
function isAsarPath(filePath) {
|
|
443
485
|
return /\.asar([/\\]|$)/.test(filePath);
|
|
@@ -495,6 +537,39 @@ function isBrightsyConnected() {
|
|
|
495
537
|
return false;
|
|
496
538
|
}
|
|
497
539
|
}
|
|
540
|
+
var BRIGHTSY_WORD = /(?<![a-z0-9_-])brightsy(?![a-z0-9_-])/i;
|
|
541
|
+
function promptMentionsBrightsy(text) {
|
|
542
|
+
return BRIGHTSY_WORD.test(text ?? "");
|
|
543
|
+
}
|
|
544
|
+
function isBrightsyMcpToolName(name) {
|
|
545
|
+
const n = name.toLowerCase();
|
|
546
|
+
return n === "brightsy" || n.startsWith("mcp__brightsy") || n.startsWith("brightsy_");
|
|
547
|
+
}
|
|
548
|
+
function toolInputUsesBrightsyDatasource(input) {
|
|
549
|
+
const ds = input?.datasource;
|
|
550
|
+
return typeof ds === "string" && ds.toLowerCase() === "brightsy";
|
|
551
|
+
}
|
|
552
|
+
function messageUsedBrightsyMcp(msg) {
|
|
553
|
+
if (msg.role === "user" && promptMentionsBrightsy(msg.text)) return true;
|
|
554
|
+
for (const part of msg.parts ?? []) {
|
|
555
|
+
if (part.type !== "tool") continue;
|
|
556
|
+
if (isBrightsyMcpToolName(part.name)) return true;
|
|
557
|
+
if (/present_(schema|files)$/i.test(part.name) && toolInputUsesBrightsyDatasource(part.input)) {
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return false;
|
|
562
|
+
}
|
|
563
|
+
function threadRequestsBrightsyMcp(thread) {
|
|
564
|
+
return (thread?.messages ?? []).some(messageUsedBrightsyMcp);
|
|
565
|
+
}
|
|
566
|
+
function shouldInjectBrightsyMcp(thread, opts) {
|
|
567
|
+
if (!(opts?.connected ?? isBrightsyConnected())) return false;
|
|
568
|
+
if (opts?.orchestrator) return true;
|
|
569
|
+
const alwaysOn = opts?.alwaysOnWorktree ?? Boolean(loadAppSettings().brightsy?.injectWorktreeMcp);
|
|
570
|
+
if (alwaysOn) return true;
|
|
571
|
+
return threadRequestsBrightsyMcp(thread);
|
|
572
|
+
}
|
|
498
573
|
function mcpLaunch(cmd, name, env) {
|
|
499
574
|
if (cmd === "brightsy-mcp") {
|
|
500
575
|
return { name, command: "brightsy-mcp", ...env ? { env } : {} };
|
|
@@ -540,7 +615,7 @@ function corePackageDir() {
|
|
|
540
615
|
}
|
|
541
616
|
function findSideboardMcpJsEntry() {
|
|
542
617
|
const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
|
|
543
|
-
if (override &&
|
|
618
|
+
if (override && existsSync2(override)) return override;
|
|
544
619
|
let dir = corePackageDir();
|
|
545
620
|
for (let i = 0; i < 10; i++) {
|
|
546
621
|
const candidates = [
|
|
@@ -553,7 +628,7 @@ function findSideboardMcpJsEntry() {
|
|
|
553
628
|
join(dir, "cli/dist/index.js")
|
|
554
629
|
];
|
|
555
630
|
for (const p of candidates) {
|
|
556
|
-
if (
|
|
631
|
+
if (existsSync2(p)) return p;
|
|
557
632
|
}
|
|
558
633
|
const parent = dirname(dir);
|
|
559
634
|
if (parent === dir) break;
|
|
@@ -584,11 +659,13 @@ async function buildInjectedMcpServers(opts) {
|
|
|
584
659
|
const servers = [];
|
|
585
660
|
if (opts.includeSideboard) {
|
|
586
661
|
const sideboard = await resolveSideboardMcpServer();
|
|
662
|
+
const orchId = opts.orchestratorThreadId?.trim();
|
|
663
|
+
const profile = orchId ? "orchestration" : "worktree";
|
|
587
664
|
sideboard.env = {
|
|
588
665
|
...sideboard.env ?? {},
|
|
589
|
-
SIDEBOARD_APP_DATA: appDataDir()
|
|
666
|
+
SIDEBOARD_APP_DATA: appDataDir(),
|
|
667
|
+
[SIDEBOARD_MCP_PROFILE_ENV]: profile
|
|
590
668
|
};
|
|
591
|
-
const orchId = opts.orchestratorThreadId?.trim();
|
|
592
669
|
if (orchId) {
|
|
593
670
|
sideboard.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID = orchId;
|
|
594
671
|
}
|
|
@@ -813,7 +890,7 @@ var claudeAdapter = {
|
|
|
813
890
|
async detect() {
|
|
814
891
|
const claude = resolveClaudeExecutable();
|
|
815
892
|
if (claude !== "claude") {
|
|
816
|
-
if (!
|
|
893
|
+
if (!existsSync3(claude)) {
|
|
817
894
|
return {
|
|
818
895
|
agent: "claude",
|
|
819
896
|
installed: false,
|
|
@@ -852,9 +929,8 @@ var claudeAdapter = {
|
|
|
852
929
|
},
|
|
853
930
|
async buildTurn(thread, input) {
|
|
854
931
|
const claude = resolveClaudeExecutable();
|
|
855
|
-
const turn = normalizeTurnInput(input);
|
|
856
932
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
857
|
-
const effective = sessionId
|
|
933
|
+
const effective = dropCachedPrefixOnResume(input, sessionId);
|
|
858
934
|
const promptText = flattenTurnInput(effective);
|
|
859
935
|
const useStdin = promptText.length > CLAUDE_PROMPT_ARG_MAX;
|
|
860
936
|
if (process.env.SIDEBOARD_DEBUG_CLAUDE_TURN === "1") {
|
|
@@ -863,11 +939,13 @@ var claudeAdapter = {
|
|
|
863
939
|
);
|
|
864
940
|
}
|
|
865
941
|
const mode = permissionMode(thread);
|
|
866
|
-
const { isOrchestratorThread } = await import("./global-workspace-
|
|
867
|
-
const isOrchestrator =
|
|
942
|
+
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-44UG64NA.js");
|
|
943
|
+
const isOrchestrator = isOrchestratorThread2(thread);
|
|
868
944
|
const injectedServers = await buildInjectedMcpServers({
|
|
869
945
|
includeSideboard: true,
|
|
870
|
-
includeBrightsy:
|
|
946
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
947
|
+
orchestrator: isOrchestrator
|
|
948
|
+
}),
|
|
871
949
|
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
872
950
|
});
|
|
873
951
|
const injectedBrightsyNames = injectedServers.filter((s) => s.name === "brightsy" || s.name.startsWith("brightsy_")).map((s) => s.name);
|
|
@@ -1059,7 +1137,7 @@ function parseIssuesJson(raw) {
|
|
|
1059
1137
|
}
|
|
1060
1138
|
|
|
1061
1139
|
// src/agents/codex.ts
|
|
1062
|
-
import { existsSync as
|
|
1140
|
+
import { existsSync as existsSync4, readFileSync, statSync } from "fs";
|
|
1063
1141
|
import { homedir } from "os";
|
|
1064
1142
|
import { join as join2 } from "path";
|
|
1065
1143
|
var CODEX_PROMPT_ARG_MAX = 2e5;
|
|
@@ -1077,9 +1155,14 @@ async function listCodexModels() {
|
|
|
1077
1155
|
if (cachedCodexModels && now - cachedCodexModels.at < CODEX_MODEL_CACHE_MS) {
|
|
1078
1156
|
return cachedCodexModels.models;
|
|
1079
1157
|
}
|
|
1080
|
-
const
|
|
1081
|
-
if (
|
|
1082
|
-
|
|
1158
|
+
const codex = resolveAgentExecutable("codex");
|
|
1159
|
+
if (codex === "codex") {
|
|
1160
|
+
const which = await run("which", ["codex"], { reject: false });
|
|
1161
|
+
if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
|
|
1162
|
+
} else if (!existsSync4(codex)) {
|
|
1163
|
+
return FALLBACK_CODEX_MODELS;
|
|
1164
|
+
}
|
|
1165
|
+
const listed = await run(codex, ["debug", "models"], { reject: false });
|
|
1083
1166
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
1084
1167
|
return cachedCodexModels?.models ?? FALLBACK_CODEX_MODELS;
|
|
1085
1168
|
}
|
|
@@ -1118,7 +1201,7 @@ function codexConfigHasNetworkAccess() {
|
|
|
1118
1201
|
join2(homedir(), ".config", "codex", "config.toml")
|
|
1119
1202
|
];
|
|
1120
1203
|
for (const path of candidates) {
|
|
1121
|
-
if (!
|
|
1204
|
+
if (!existsSync4(path)) continue;
|
|
1122
1205
|
const text = readFileSync(path, "utf8");
|
|
1123
1206
|
if (/network_access\s*=\s*true/.test(text)) return true;
|
|
1124
1207
|
}
|
|
@@ -1152,7 +1235,7 @@ function asRecord(value) {
|
|
|
1152
1235
|
}
|
|
1153
1236
|
function codexLooksAuthenticated() {
|
|
1154
1237
|
const authPath = join2(homedir(), ".codex", "auth.json");
|
|
1155
|
-
if (!
|
|
1238
|
+
if (!existsSync4(authPath)) return false;
|
|
1156
1239
|
try {
|
|
1157
1240
|
return statSync(authPath).size > 2;
|
|
1158
1241
|
} catch {
|
|
@@ -1162,16 +1245,30 @@ function codexLooksAuthenticated() {
|
|
|
1162
1245
|
var codexAdapter = {
|
|
1163
1246
|
kind: "codex",
|
|
1164
1247
|
async detect() {
|
|
1165
|
-
const
|
|
1166
|
-
if (
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1248
|
+
const codex = resolveAgentExecutable("codex");
|
|
1249
|
+
if (codex !== "codex") {
|
|
1250
|
+
if (!existsSync4(codex)) {
|
|
1251
|
+
return {
|
|
1252
|
+
agent: "codex",
|
|
1253
|
+
installed: false,
|
|
1254
|
+
authenticated: false,
|
|
1255
|
+
linearMcp: false,
|
|
1256
|
+
warnings: [],
|
|
1257
|
+
reason: `Codex executable not found: ${codex}`
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1260
|
+
} else {
|
|
1261
|
+
const which = await run("which", ["codex"], { reject: false, timeoutMs: 3e3 });
|
|
1262
|
+
if (which.exitCode !== 0) {
|
|
1263
|
+
return {
|
|
1264
|
+
agent: "codex",
|
|
1265
|
+
installed: false,
|
|
1266
|
+
authenticated: false,
|
|
1267
|
+
linearMcp: false,
|
|
1268
|
+
warnings: [],
|
|
1269
|
+
reason: "codex CLI not found on PATH"
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1175
1272
|
}
|
|
1176
1273
|
const authenticated = codexLooksAuthenticated();
|
|
1177
1274
|
const linearMcp = false;
|
|
@@ -1191,22 +1288,24 @@ var codexAdapter = {
|
|
|
1191
1288
|
};
|
|
1192
1289
|
},
|
|
1193
1290
|
async buildTurn(thread, input) {
|
|
1194
|
-
const prompt = flattenTurnInput(input);
|
|
1195
1291
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
1292
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, sessionId));
|
|
1196
1293
|
const useStdin = prompt.length > CODEX_PROMPT_ARG_MAX;
|
|
1197
1294
|
const promptArg = useStdin ? "-" : prompt;
|
|
1198
1295
|
if (process.env.SIDEBOARD_DEBUG_CODEX_TURN === "1") {
|
|
1199
|
-
const { cachedPrefix } = normalizeTurnInput(input);
|
|
1200
1296
|
console.error(
|
|
1201
|
-
`[sideboard/codex] promptChars=${prompt.length} resumed=${Boolean(sessionId)} stdin=${useStdin} hasPrefix=${
|
|
1297
|
+
`[sideboard/codex] promptChars=${prompt.length} resumed=${Boolean(sessionId)} stdin=${useStdin} hasPrefix=${prompt.includes("Current request:")}`
|
|
1202
1298
|
);
|
|
1203
1299
|
}
|
|
1204
1300
|
const mode = permissionMode(thread);
|
|
1205
1301
|
const model = thread.model?.trim();
|
|
1302
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
1206
1303
|
const injected = await buildInjectedMcpServers({
|
|
1207
1304
|
includeSideboard: true,
|
|
1208
|
-
includeBrightsy:
|
|
1209
|
-
|
|
1305
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
1306
|
+
orchestrator: isOrchestrator
|
|
1307
|
+
}),
|
|
1308
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
1210
1309
|
});
|
|
1211
1310
|
const mcpOverrides = toCodexMcpConfigArgs(injected);
|
|
1212
1311
|
const execOpts = [
|
|
@@ -1226,7 +1325,7 @@ var codexAdapter = {
|
|
|
1226
1325
|
];
|
|
1227
1326
|
const args = sessionId ? ["exec", ...execOpts, "resume", sessionId, promptArg] : ["exec", ...execOpts, promptArg];
|
|
1228
1327
|
return {
|
|
1229
|
-
file: "codex",
|
|
1328
|
+
file: resolveAgentExecutable("codex"),
|
|
1230
1329
|
args,
|
|
1231
1330
|
cwd: thread.worktreePath,
|
|
1232
1331
|
stdin: useStdin ? `${prompt}
|
|
@@ -1322,16 +1421,17 @@ var codexAdapter = {
|
|
|
1322
1421
|
return cached;
|
|
1323
1422
|
},
|
|
1324
1423
|
async buildAttach(thread) {
|
|
1424
|
+
const codex = resolveAgentExecutable("codex");
|
|
1325
1425
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
1326
1426
|
if (sessionId) {
|
|
1327
1427
|
return {
|
|
1328
|
-
file:
|
|
1428
|
+
file: codex,
|
|
1329
1429
|
args: ["exec", "--cd", thread.worktreePath, "resume", sessionId],
|
|
1330
1430
|
cwd: thread.worktreePath
|
|
1331
1431
|
};
|
|
1332
1432
|
}
|
|
1333
1433
|
return {
|
|
1334
|
-
file:
|
|
1434
|
+
file: codex,
|
|
1335
1435
|
args: ["--cd", thread.worktreePath],
|
|
1336
1436
|
cwd: thread.worktreePath
|
|
1337
1437
|
};
|
|
@@ -1339,7 +1439,7 @@ var codexAdapter = {
|
|
|
1339
1439
|
async listLinearIssues(_repoPath) {
|
|
1340
1440
|
const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
|
|
1341
1441
|
const { stdout, exitCode } = await run(
|
|
1342
|
-
"codex",
|
|
1442
|
+
resolveAgentExecutable("codex"),
|
|
1343
1443
|
[
|
|
1344
1444
|
"exec",
|
|
1345
1445
|
"--json",
|
|
@@ -1364,7 +1464,7 @@ var codexAdapter = {
|
|
|
1364
1464
|
};
|
|
1365
1465
|
|
|
1366
1466
|
// src/agents/cursor.ts
|
|
1367
|
-
import { existsSync as
|
|
1467
|
+
import { existsSync as existsSync5 } from "fs";
|
|
1368
1468
|
import { createRequire as createRequire2 } from "module";
|
|
1369
1469
|
import { dirname as dirname2, join as join3 } from "path";
|
|
1370
1470
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
@@ -1437,7 +1537,7 @@ function cursorRunnerPath() {
|
|
|
1437
1537
|
join3(root, "src", "agents", "cursor-runner.ts")
|
|
1438
1538
|
];
|
|
1439
1539
|
for (const candidate of candidates) {
|
|
1440
|
-
if (
|
|
1540
|
+
if (existsSync5(candidate)) return candidate;
|
|
1441
1541
|
}
|
|
1442
1542
|
return candidates[0];
|
|
1443
1543
|
}
|
|
@@ -1464,13 +1564,16 @@ var cursorAdapter = {
|
|
|
1464
1564
|
};
|
|
1465
1565
|
},
|
|
1466
1566
|
async buildTurn(thread, input) {
|
|
1467
|
-
const prompt = flattenTurnInput(input);
|
|
1468
1567
|
const agentId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
1568
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, agentId));
|
|
1469
1569
|
const apiKey = resolveCursorApiKey() || void 0;
|
|
1570
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
1470
1571
|
const injected = await buildInjectedMcpServers({
|
|
1471
1572
|
includeSideboard: true,
|
|
1472
|
-
includeBrightsy:
|
|
1473
|
-
|
|
1573
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
1574
|
+
orchestrator: isOrchestrator
|
|
1575
|
+
}),
|
|
1576
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
1474
1577
|
});
|
|
1475
1578
|
const mcpServers = toCursorMcpServers(injected);
|
|
1476
1579
|
const req = {
|
|
@@ -1516,6 +1619,7 @@ var cursorAdapter = {
|
|
|
1516
1619
|
};
|
|
1517
1620
|
|
|
1518
1621
|
// src/agents/opencode.ts
|
|
1622
|
+
import { existsSync as existsSync6 } from "fs";
|
|
1519
1623
|
var FALLBACK_OPENCODE_MODELS = [
|
|
1520
1624
|
{ id: "opencode/big-pickle", displayName: "opencode \xB7 big-pickle" },
|
|
1521
1625
|
{
|
|
@@ -1552,9 +1656,14 @@ async function listOpencodeModels() {
|
|
|
1552
1656
|
if (cachedOpencodeModels && now - cachedOpencodeModels.at < OPENCODE_MODEL_CACHE_MS) {
|
|
1553
1657
|
return cachedOpencodeModels.models;
|
|
1554
1658
|
}
|
|
1555
|
-
const
|
|
1556
|
-
if (
|
|
1557
|
-
|
|
1659
|
+
const opencode = resolveAgentExecutable("opencode");
|
|
1660
|
+
if (opencode === "opencode") {
|
|
1661
|
+
const which = await run("which", ["opencode"], { reject: false });
|
|
1662
|
+
if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
|
|
1663
|
+
} else if (!existsSync6(opencode)) {
|
|
1664
|
+
return FALLBACK_OPENCODE_MODELS;
|
|
1665
|
+
}
|
|
1666
|
+
const listed = await run(opencode, ["models"], { reject: false });
|
|
1558
1667
|
if (listed.exitCode !== 0 || !listed.stdout.trim()) {
|
|
1559
1668
|
return cachedOpencodeModels?.models ?? FALLBACK_OPENCODE_MODELS;
|
|
1560
1669
|
}
|
|
@@ -1584,20 +1693,34 @@ function usageFromOpencode(tokens) {
|
|
|
1584
1693
|
var opencodeAdapter = {
|
|
1585
1694
|
kind: "opencode",
|
|
1586
1695
|
async detect() {
|
|
1587
|
-
const
|
|
1588
|
-
if (
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1696
|
+
const opencode = resolveAgentExecutable("opencode");
|
|
1697
|
+
if (opencode !== "opencode") {
|
|
1698
|
+
if (!existsSync6(opencode)) {
|
|
1699
|
+
return {
|
|
1700
|
+
agent: "opencode",
|
|
1701
|
+
installed: false,
|
|
1702
|
+
authenticated: false,
|
|
1703
|
+
linearMcp: false,
|
|
1704
|
+
warnings: [],
|
|
1705
|
+
reason: `OpenCode executable not found: ${opencode}`
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1708
|
+
} else {
|
|
1709
|
+
const which = await run("which", ["opencode"], { reject: false });
|
|
1710
|
+
if (which.exitCode !== 0) {
|
|
1711
|
+
return {
|
|
1712
|
+
agent: "opencode",
|
|
1713
|
+
installed: false,
|
|
1714
|
+
authenticated: false,
|
|
1715
|
+
linearMcp: false,
|
|
1716
|
+
warnings: [],
|
|
1717
|
+
reason: "opencode CLI not found on PATH"
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1597
1720
|
}
|
|
1598
|
-
const auth = await run(
|
|
1721
|
+
const auth = await run(opencode, ["auth", "list"], { reject: false });
|
|
1599
1722
|
const authenticated = auth.exitCode === 0 && auth.stdout.trim().length > 0;
|
|
1600
|
-
const mcp = await run(
|
|
1723
|
+
const mcp = await run(opencode, ["mcp", "list"], { reject: false });
|
|
1601
1724
|
const linearMcp = /linear/i.test(mcp.stdout + mcp.stderr);
|
|
1602
1725
|
return {
|
|
1603
1726
|
agent: "opencode",
|
|
@@ -1609,8 +1732,8 @@ var opencodeAdapter = {
|
|
|
1609
1732
|
};
|
|
1610
1733
|
},
|
|
1611
1734
|
async buildTurn(thread, input) {
|
|
1612
|
-
const prompt = flattenTurnInput(input);
|
|
1613
1735
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
1736
|
+
const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, sessionId));
|
|
1614
1737
|
const mode = permissionMode(thread);
|
|
1615
1738
|
const model = thread.model?.trim();
|
|
1616
1739
|
const args = [
|
|
@@ -1626,14 +1749,17 @@ var opencodeAdapter = {
|
|
|
1626
1749
|
if (model) {
|
|
1627
1750
|
args.push("--model", model);
|
|
1628
1751
|
}
|
|
1752
|
+
const isOrchestrator = isOrchestratorThread(thread);
|
|
1629
1753
|
const injected = await buildInjectedMcpServers({
|
|
1630
1754
|
includeSideboard: true,
|
|
1631
|
-
includeBrightsy:
|
|
1632
|
-
|
|
1755
|
+
includeBrightsy: shouldInjectBrightsyMcp(thread, {
|
|
1756
|
+
orchestrator: isOrchestrator
|
|
1757
|
+
}),
|
|
1758
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
1633
1759
|
});
|
|
1634
1760
|
const mcpContent = injected.length > 0 ? toOpencodeMcpConfigContent(injected) : null;
|
|
1635
1761
|
return {
|
|
1636
|
-
file: "opencode",
|
|
1762
|
+
file: resolveAgentExecutable("opencode"),
|
|
1637
1763
|
args,
|
|
1638
1764
|
cwd: thread.worktreePath,
|
|
1639
1765
|
// `opencode run` treats non-TTY stdin as the message body when no positional
|
|
@@ -1709,7 +1835,7 @@ var opencodeAdapter = {
|
|
|
1709
1835
|
async resolveSessionId(worktreePath, cached) {
|
|
1710
1836
|
const cachedId = cached?.trim() || null;
|
|
1711
1837
|
const listed = await run(
|
|
1712
|
-
"opencode",
|
|
1838
|
+
resolveAgentExecutable("opencode"),
|
|
1713
1839
|
["session", "list", "--format", "json"],
|
|
1714
1840
|
{ cwd: worktreePath, reject: false }
|
|
1715
1841
|
);
|
|
@@ -1740,7 +1866,7 @@ var opencodeAdapter = {
|
|
|
1740
1866
|
const args = ["--dir", thread.worktreePath];
|
|
1741
1867
|
if (sessionId) args.push("--session", sessionId);
|
|
1742
1868
|
return {
|
|
1743
|
-
file: "opencode",
|
|
1869
|
+
file: resolveAgentExecutable("opencode"),
|
|
1744
1870
|
args,
|
|
1745
1871
|
cwd: thread.worktreePath,
|
|
1746
1872
|
env: {
|
|
@@ -1751,7 +1877,7 @@ var opencodeAdapter = {
|
|
|
1751
1877
|
async listLinearIssues(_repoPath) {
|
|
1752
1878
|
const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
|
|
1753
1879
|
const { stdout, exitCode } = await run(
|
|
1754
|
-
"opencode",
|
|
1880
|
+
resolveAgentExecutable("opencode"),
|
|
1755
1881
|
["run", prompt, "--format", "json"],
|
|
1756
1882
|
{
|
|
1757
1883
|
reject: false,
|
|
@@ -2006,15 +2132,48 @@ var SETUP = {
|
|
|
2006
2132
|
npmPackage: "@brightsy/cli"
|
|
2007
2133
|
}
|
|
2008
2134
|
};
|
|
2135
|
+
var CLI_BIN = {
|
|
2136
|
+
claude: "claude",
|
|
2137
|
+
codex: "codex",
|
|
2138
|
+
opencode: "opencode",
|
|
2139
|
+
brightsy: "brightsy"
|
|
2140
|
+
};
|
|
2009
2141
|
function getAgentSetupInfo(agent) {
|
|
2010
2142
|
return SETUP[agent];
|
|
2011
2143
|
}
|
|
2012
2144
|
function listAgentSetupInfo() {
|
|
2013
2145
|
return Object.values(SETUP);
|
|
2014
2146
|
}
|
|
2015
|
-
|
|
2016
|
-
|
|
2147
|
+
var CLI_LOGIN_AGENTS = /* @__PURE__ */ new Set([
|
|
2148
|
+
"claude",
|
|
2149
|
+
"codex",
|
|
2150
|
+
"opencode",
|
|
2151
|
+
"brightsy"
|
|
2152
|
+
]);
|
|
2153
|
+
function resolveLoginCommand(agent) {
|
|
2154
|
+
const info = getAgentSetupInfo(agent);
|
|
2155
|
+
if (!info.loginCommand) return null;
|
|
2156
|
+
if (!CLI_LOGIN_AGENTS.has(agent)) return info.loginCommand;
|
|
2157
|
+
const exe = resolveAgentExecutable(agent);
|
|
2158
|
+
return info.loginCommand.replace(/^\S+/, exe);
|
|
2159
|
+
}
|
|
2160
|
+
async function prepareTerminalCommand(command) {
|
|
2161
|
+
enrichPathWithNpmGlobalBin();
|
|
2017
2162
|
const trimmed = command.trim();
|
|
2163
|
+
if (!trimmed) return trimmed;
|
|
2164
|
+
if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
|
|
2165
|
+
const match = /^(\S+)(\s[\s\S]*)?$/.exec(trimmed);
|
|
2166
|
+
const bin = match?.[1];
|
|
2167
|
+
let whichPath = null;
|
|
2168
|
+
if (bin && !bin.includes("/") && !bin.includes("\\")) {
|
|
2169
|
+
const which = await run("which", [bin], { reject: false, timeoutMs: 3e3 });
|
|
2170
|
+
whichPath = which.exitCode === 0 ? which.stdout.trim() : null;
|
|
2171
|
+
}
|
|
2172
|
+
const resolved = resolveCommandBinarySync(trimmed, whichPath);
|
|
2173
|
+
return withExportedPath(resolved, process.env.PATH ?? "");
|
|
2174
|
+
}
|
|
2175
|
+
async function openInSystemTerminal(command) {
|
|
2176
|
+
const trimmed = (await prepareTerminalCommand(command)).trim();
|
|
2018
2177
|
if (!trimmed) throw new Error("Command is empty");
|
|
2019
2178
|
if (process.platform === "darwin") {
|
|
2020
2179
|
const escaped = trimmed.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
@@ -2075,7 +2234,7 @@ async function installAgent(agent) {
|
|
|
2075
2234
|
message: `Opened Terminal to run: ${info.installCommand}`
|
|
2076
2235
|
};
|
|
2077
2236
|
}
|
|
2078
|
-
|
|
2237
|
+
enrichPathWithNpmGlobalBin();
|
|
2079
2238
|
const result = await run("npm", ["install", "-g", info.npmPackage], { reject: false });
|
|
2080
2239
|
const ok = result.exitCode === 0;
|
|
2081
2240
|
if (!ok) {
|
|
@@ -2101,29 +2260,38 @@ async function installAgent(agent) {
|
|
|
2101
2260
|
};
|
|
2102
2261
|
}
|
|
2103
2262
|
}
|
|
2263
|
+
enrichPathWithNpmGlobalBin();
|
|
2264
|
+
const cliBin = agent === "cursor" ? null : CLI_BIN[agent];
|
|
2265
|
+
let binPath = null;
|
|
2266
|
+
if (cliBin) {
|
|
2267
|
+
const which = await run("which", [cliBin], { reject: false, timeoutMs: 3e3 });
|
|
2268
|
+
binPath = which.exitCode === 0 ? which.stdout.trim().split(/\r?\n/).find(Boolean) ?? null : null;
|
|
2269
|
+
}
|
|
2104
2270
|
return {
|
|
2105
2271
|
ok: true,
|
|
2106
2272
|
command: info.installCommand,
|
|
2107
2273
|
exitCode: 0,
|
|
2108
2274
|
stdout: result.stdout,
|
|
2109
2275
|
stderr: result.stderr,
|
|
2110
|
-
message: `Installed ${info.npmPackage}`
|
|
2276
|
+
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)`
|
|
2111
2277
|
};
|
|
2112
2278
|
}
|
|
2113
2279
|
async function loginAgent(agent) {
|
|
2114
2280
|
const info = getAgentSetupInfo(agent);
|
|
2115
|
-
|
|
2281
|
+
const loginCommand = resolveLoginCommand(agent);
|
|
2282
|
+
if (!loginCommand) {
|
|
2116
2283
|
return {
|
|
2117
2284
|
ok: true,
|
|
2118
2285
|
message: info.kind === "bundled-sdk" || info.kind === "api-key" ? info.summary : `No login command for ${agent}`
|
|
2119
2286
|
};
|
|
2120
2287
|
}
|
|
2121
|
-
await
|
|
2288
|
+
const prepared = await prepareTerminalCommand(loginCommand);
|
|
2289
|
+
await openInSystemTerminal(prepared);
|
|
2122
2290
|
return {
|
|
2123
2291
|
ok: true,
|
|
2124
2292
|
openedTerminal: true,
|
|
2125
|
-
command:
|
|
2126
|
-
message: `Opened Terminal to run: ${
|
|
2293
|
+
command: prepared,
|
|
2294
|
+
message: `Opened Terminal to run: ${prepared}`
|
|
2127
2295
|
};
|
|
2128
2296
|
}
|
|
2129
2297
|
|
|
@@ -2146,6 +2314,7 @@ export {
|
|
|
2146
2314
|
encodeBrightsyTarget,
|
|
2147
2315
|
decodeBrightsyTarget,
|
|
2148
2316
|
normalizeTurnInput,
|
|
2317
|
+
dropCachedPrefixOnResume,
|
|
2149
2318
|
flattenTurnInput,
|
|
2150
2319
|
buildCachedUserContent,
|
|
2151
2320
|
buildClaudeStreamJsonUserMessage,
|
|
@@ -2159,9 +2328,14 @@ export {
|
|
|
2159
2328
|
sanitizeMcpServerName,
|
|
2160
2329
|
mcpAllowTools,
|
|
2161
2330
|
mcpAuthWarnings,
|
|
2331
|
+
SIDEBOARD_MCP_PROFILE_ENV,
|
|
2332
|
+
sideboardMcpProfile,
|
|
2162
2333
|
SIDEBOARD_MCP_ALLOWED_TOOLS,
|
|
2163
2334
|
BRIGHTSY_MCP_ALLOWED_TOOLS,
|
|
2164
2335
|
isBrightsyConnected,
|
|
2336
|
+
promptMentionsBrightsy,
|
|
2337
|
+
threadRequestsBrightsyMcp,
|
|
2338
|
+
shouldInjectBrightsyMcp,
|
|
2165
2339
|
brightsyMcpAllowedTools,
|
|
2166
2340
|
writeInjectedMcpConfig,
|
|
2167
2341
|
PLAN_MODE_INSTRUCTION,
|
|
@@ -2182,6 +2356,8 @@ export {
|
|
|
2182
2356
|
resolveQuotaFallbackAgent,
|
|
2183
2357
|
getAgentSetupInfo,
|
|
2184
2358
|
listAgentSetupInfo,
|
|
2359
|
+
resolveLoginCommand,
|
|
2360
|
+
prepareTerminalCommand,
|
|
2185
2361
|
openInSystemTerminal,
|
|
2186
2362
|
installAgent,
|
|
2187
2363
|
loginAgent,
|