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