@sideboard-ai/core 0.1.45 → 0.1.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/cursor-runner.cjs +11 -4
- package/dist/agents/cursor-runner.js +11 -4
- package/dist/{agents-JSHCAZUZ.js → agents-3P4N6KHC.js} +12 -2
- package/dist/agents-LUB3Q773.js +82 -0
- package/dist/app-settings-7XVDQJ7F.js +80 -0
- package/dist/{app-settings-LYGVDGZY.js → app-settings-LZP632KI.js} +1 -1
- package/dist/{chunk-U3EQKJHA.js → chunk-3NAS4MWH.js} +1 -1
- package/dist/{chunk-ZNSM2DDD.js → chunk-5WYEJ3F3.js} +6 -2
- package/dist/chunk-7MV3RXSC.js +277 -0
- package/dist/chunk-DF5VQQKA.js +191 -0
- package/dist/chunk-E35APBHV.js +269 -0
- package/dist/chunk-EOYDCKQC.js +172 -0
- package/dist/chunk-GI7E5733.js +30 -0
- package/dist/chunk-GZXBYHJC.js +148 -0
- package/dist/chunk-HBJSHRY2.js +494 -0
- package/dist/chunk-ISY4EGF6.js +77 -0
- package/dist/chunk-KGZBYWZ3.js +23 -0
- package/dist/chunk-RQI4TOXK.js +2232 -0
- package/dist/chunk-S2LL5HA4.js +33 -0
- package/dist/{chunk-ANZ566Z5.js → chunk-SS34TVSY.js} +66 -7
- package/dist/{chunk-WYY3J7GR.js → chunk-T5QQVXK3.js} +6 -3
- package/dist/chunk-V4JRXYYU.js +122 -0
- package/dist/{chunk-6NAPN2N5.js → chunk-ZQCQIWIP.js} +1 -1
- package/dist/chunk-ZVV5EEQN.js +1892 -0
- package/dist/connected-teams-UBXHZGO4.js +24 -0
- package/dist/{coordinator-prompt-2XFYG3C5.js → coordinator-prompt-SPGDT7J5.js} +1 -1
- package/dist/coordinator-prompt-VG4BZ5JL.js +25 -0
- package/dist/cursor-recover-NNK7JPQM.js +44 -0
- package/dist/{global-workspace-YFOQUGWD.js → global-workspace-KSR3E63K.js} +3 -2
- package/dist/global-workspace-OJF4ENH4.js +40 -0
- package/dist/index.cjs +377 -30
- package/dist/index.d.cts +70 -11
- package/dist/index.d.ts +70 -11
- package/dist/index.js +5779 -193
- package/dist/mcp/run-stdio.cjs +331 -32
- package/dist/mcp/run-stdio.js +5618 -14
- package/dist/paths-2OFB7UJG.js +28 -0
- package/dist/run-HMRSRG3U.js +12 -0
- package/dist/thread-store-XICUWFNM.js +32 -0
- package/dist/title-4WAKWZRF.js +27 -0
- package/dist/workspaces-OZE7LRDO.js +24 -0
- package/dist/{workspaces-TIKLNDW3.js → workspaces-UJX7JIGH.js} +4 -3
- package/dist/worktree-XG5PCLZY.js +94 -0
- package/package.json +2 -2
- package/dist/chunk-I6QGZOOS.js +0 -5667
package/dist/index.cjs
CHANGED
|
@@ -528,7 +528,7 @@ function normalizeAdvanced(raw) {
|
|
|
528
528
|
if (source.orchestrationQuotaOnLimit === "switch_agent" || source.orchestrationQuotaOnLimit === "wait_reset") {
|
|
529
529
|
out.orchestrationQuotaOnLimit = source.orchestrationQuotaOnLimit;
|
|
530
530
|
}
|
|
531
|
-
if (typeof source.orchestrationQuotaFallbackAgent === "string" && DEFAULT_AGENTS.has(source.orchestrationQuotaFallbackAgent)) {
|
|
531
|
+
if (typeof source.orchestrationQuotaFallbackAgent === "string" && DEFAULT_AGENTS.has(source.orchestrationQuotaFallbackAgent) && source.orchestrationQuotaFallbackAgent !== "brightsy") {
|
|
532
532
|
out.orchestrationQuotaFallbackAgent = source.orchestrationQuotaFallbackAgent;
|
|
533
533
|
}
|
|
534
534
|
return out;
|
|
@@ -768,7 +768,7 @@ function updateAdvancedSettings(patch) {
|
|
|
768
768
|
if (patch.orchestrationQuotaOnLimit === "switch_agent" || patch.orchestrationQuotaOnLimit === "wait_reset") {
|
|
769
769
|
advanced.orchestrationQuotaOnLimit = patch.orchestrationQuotaOnLimit;
|
|
770
770
|
}
|
|
771
|
-
if (typeof patch.orchestrationQuotaFallbackAgent === "string" && DEFAULT_AGENTS.has(patch.orchestrationQuotaFallbackAgent)) {
|
|
771
|
+
if (typeof patch.orchestrationQuotaFallbackAgent === "string" && DEFAULT_AGENTS.has(patch.orchestrationQuotaFallbackAgent) && patch.orchestrationQuotaFallbackAgent !== "brightsy") {
|
|
772
772
|
advanced.orchestrationQuotaFallbackAgent = patch.orchestrationQuotaFallbackAgent;
|
|
773
773
|
}
|
|
774
774
|
return saveAppSettings({ ...current, advanced });
|
|
@@ -796,7 +796,10 @@ function orchestrationQuotaOnLimit(settings = loadAppSettings()) {
|
|
|
796
796
|
}
|
|
797
797
|
function orchestrationQuotaFallbackAgent(settings = loadAppSettings()) {
|
|
798
798
|
const preferred = settings.advanced.orchestrationQuotaFallbackAgent;
|
|
799
|
-
|
|
799
|
+
if (preferred && DEFAULT_AGENTS.has(preferred) && preferred !== "brightsy") {
|
|
800
|
+
return preferred;
|
|
801
|
+
}
|
|
802
|
+
return "cursor";
|
|
800
803
|
}
|
|
801
804
|
function maxConcurrentAgents(settings = loadAppSettings()) {
|
|
802
805
|
const n = settings.advanced.maxConcurrent;
|
|
@@ -1075,6 +1078,36 @@ var init_cloud_connect_constants = __esm({
|
|
|
1075
1078
|
}
|
|
1076
1079
|
});
|
|
1077
1080
|
|
|
1081
|
+
// src/agents/orchestrator-capable.ts
|
|
1082
|
+
function isOrchestratorCapableAgent(agent) {
|
|
1083
|
+
return Boolean(
|
|
1084
|
+
agent && ORCHESTRATOR_AGENT_KINDS.includes(agent)
|
|
1085
|
+
);
|
|
1086
|
+
}
|
|
1087
|
+
function assertOrchestratorCapableAgent(agent, context = "orchestration") {
|
|
1088
|
+
if (!isOrchestratorCapableAgent(agent)) {
|
|
1089
|
+
throw new Error(
|
|
1090
|
+
`${agent} cannot run ${context} \u2014 it does not support Sideboard MCP. Use Claude, Cursor, Codex, or OpenCode.`
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
return agent;
|
|
1094
|
+
}
|
|
1095
|
+
function coerceOrchestratorAgent(agent, fallback = "claude") {
|
|
1096
|
+
return isOrchestratorCapableAgent(agent) ? agent : fallback;
|
|
1097
|
+
}
|
|
1098
|
+
var ORCHESTRATOR_AGENT_KINDS;
|
|
1099
|
+
var init_orchestrator_capable = __esm({
|
|
1100
|
+
"src/agents/orchestrator-capable.ts"() {
|
|
1101
|
+
"use strict";
|
|
1102
|
+
ORCHESTRATOR_AGENT_KINDS = [
|
|
1103
|
+
"claude",
|
|
1104
|
+
"codex",
|
|
1105
|
+
"opencode",
|
|
1106
|
+
"cursor"
|
|
1107
|
+
];
|
|
1108
|
+
}
|
|
1109
|
+
});
|
|
1110
|
+
|
|
1078
1111
|
// src/git/team-meta.ts
|
|
1079
1112
|
var SOCCER_TEAM_META;
|
|
1080
1113
|
var init_team_meta = __esm({
|
|
@@ -3224,7 +3257,7 @@ var init_coordinator_prompt = __esm({
|
|
|
3224
3257
|
"- list_run_scripts / run_dev_script / stop_dev_script \u2014 start/stop named run scripts",
|
|
3225
3258
|
"Inspect / review / PRs:",
|
|
3226
3259
|
"- get_diff \u2014 compact diff summary",
|
|
3227
|
-
|
|
3260
|
+
'- request_review \u2014 open a Review chat tab on a worktree thread (attaches .sideboard/review.md when present, else local guidelines; sends "Review."); then wait_for_turn / get_turn_result on the returned id',
|
|
3228
3261
|
"- Ask the worktree agent via send_to_thread to open a draft PR with `gh pr create --draft -R <origin-owner/name>` (workspace `github:` slug / that worktree's origin \u2014 never upstream). Do not open PRs from the orchestrator yourself.",
|
|
3229
3262
|
"Human-only (do not attempt): merge, ready-for-review land, purge_thread.",
|
|
3230
3263
|
"Thread links in replies: when mentioning a chat/thread for the user, include a markdown link `[Title](sideboard://thread/<id>)` using the full id (or the link field from create_thread / list_threads). Sideboard renders these as clickable opens.",
|
|
@@ -3312,6 +3345,7 @@ function createGlobalChat(opts) {
|
|
|
3312
3345
|
const explicit = opts.title?.trim();
|
|
3313
3346
|
const title = explicit && explicit !== CLOUD_ORCHESTRATOR_GOAL ? explicit : allocateTeamName(takenTeamSlugsForOrchestration()).name;
|
|
3314
3347
|
const sourceRef = opts.sourceRef?.trim() || (isCloud ? CLOUD_ORCHESTRATOR_GOAL : title);
|
|
3348
|
+
const agent = assertOrchestratorCapableAgent(opts.agent);
|
|
3315
3349
|
const thread = createEmptyThread({
|
|
3316
3350
|
title,
|
|
3317
3351
|
// Stick nicknames the same way chat tabs do (avoid later sync overwrites).
|
|
@@ -3321,7 +3355,7 @@ function createGlobalChat(opts) {
|
|
|
3321
3355
|
branchName: "global",
|
|
3322
3356
|
worktreePath: globalAgentCwd(),
|
|
3323
3357
|
repoPath: GLOBAL_WORKSPACE_ID,
|
|
3324
|
-
agent
|
|
3358
|
+
agent,
|
|
3325
3359
|
autonomy: opts.autonomy ?? "default",
|
|
3326
3360
|
model: opts.model ?? null,
|
|
3327
3361
|
effort: opts.effort ?? "high",
|
|
@@ -3383,6 +3417,7 @@ var init_global_workspace = __esm({
|
|
|
3383
3417
|
"src/store/global-workspace.ts"() {
|
|
3384
3418
|
"use strict";
|
|
3385
3419
|
init_cloud_connect_constants();
|
|
3420
|
+
init_orchestrator_capable();
|
|
3386
3421
|
init_teams();
|
|
3387
3422
|
init_coordinator_prompt();
|
|
3388
3423
|
init_paths();
|
|
@@ -4538,6 +4573,45 @@ async function buildInjectedMcpServers(opts) {
|
|
|
4538
4573
|
}
|
|
4539
4574
|
return servers;
|
|
4540
4575
|
}
|
|
4576
|
+
function toCursorMcpServers(servers) {
|
|
4577
|
+
const out = {};
|
|
4578
|
+
for (const s of servers) {
|
|
4579
|
+
out[s.name] = {
|
|
4580
|
+
command: s.command,
|
|
4581
|
+
...s.args ? { args: s.args } : {},
|
|
4582
|
+
...s.env ? { env: s.env } : {}
|
|
4583
|
+
};
|
|
4584
|
+
}
|
|
4585
|
+
return out;
|
|
4586
|
+
}
|
|
4587
|
+
function toCodexMcpConfigArgs(servers) {
|
|
4588
|
+
const args = [];
|
|
4589
|
+
for (const s of servers) {
|
|
4590
|
+
const prefix = `mcp_servers.${s.name}`;
|
|
4591
|
+
args.push("-c", `${prefix}.command=${JSON.stringify(s.command)}`);
|
|
4592
|
+
if (s.args?.length) {
|
|
4593
|
+
args.push("-c", `${prefix}.args=${JSON.stringify(s.args)}`);
|
|
4594
|
+
}
|
|
4595
|
+
if (s.env) {
|
|
4596
|
+
for (const [key, value] of Object.entries(s.env)) {
|
|
4597
|
+
args.push("-c", `${prefix}.env.${key}=${JSON.stringify(value)}`);
|
|
4598
|
+
}
|
|
4599
|
+
}
|
|
4600
|
+
}
|
|
4601
|
+
return args;
|
|
4602
|
+
}
|
|
4603
|
+
function toOpencodeMcpConfigContent(servers) {
|
|
4604
|
+
const mcp = {};
|
|
4605
|
+
for (const s of servers) {
|
|
4606
|
+
mcp[s.name] = {
|
|
4607
|
+
type: "local",
|
|
4608
|
+
command: [s.command, ...s.args ?? []],
|
|
4609
|
+
enabled: true,
|
|
4610
|
+
...s.env && Object.keys(s.env).length > 0 ? { environment: s.env } : {}
|
|
4611
|
+
};
|
|
4612
|
+
}
|
|
4613
|
+
return JSON.stringify({ mcp });
|
|
4614
|
+
}
|
|
4541
4615
|
function writeMcpServersConfig(servers) {
|
|
4542
4616
|
if (servers.length === 0) return null;
|
|
4543
4617
|
const mcpServers = {};
|
|
@@ -5045,6 +5119,7 @@ var init_codex = __esm({
|
|
|
5045
5119
|
import_node_path12 = require("path");
|
|
5046
5120
|
init_run();
|
|
5047
5121
|
init_error_detail();
|
|
5122
|
+
init_injected_mcp();
|
|
5048
5123
|
init_turn_input();
|
|
5049
5124
|
init_types();
|
|
5050
5125
|
CODEX_PROMPT_ARG_MAX = 2e5;
|
|
@@ -5103,6 +5178,11 @@ var init_codex = __esm({
|
|
|
5103
5178
|
}
|
|
5104
5179
|
const mode = permissionMode(thread);
|
|
5105
5180
|
const model = thread.model?.trim();
|
|
5181
|
+
const injected = await buildInjectedMcpServers({
|
|
5182
|
+
includeSideboard: true,
|
|
5183
|
+
includeBrightsy: isBrightsyConnected()
|
|
5184
|
+
});
|
|
5185
|
+
const mcpOverrides = toCodexMcpConfigArgs(injected);
|
|
5106
5186
|
const args = [
|
|
5107
5187
|
"exec",
|
|
5108
5188
|
...sessionId ? ["resume", sessionId] : [],
|
|
@@ -5114,7 +5194,8 @@ var init_codex = __esm({
|
|
|
5114
5194
|
mode.codexSandbox,
|
|
5115
5195
|
"--ask-for-approval",
|
|
5116
5196
|
"never",
|
|
5117
|
-
...model ? ["--model", model] : []
|
|
5197
|
+
...model ? ["--model", model] : [],
|
|
5198
|
+
...mcpOverrides
|
|
5118
5199
|
];
|
|
5119
5200
|
return {
|
|
5120
5201
|
file: "codex",
|
|
@@ -5399,6 +5480,7 @@ var init_cursor = __esm({
|
|
|
5399
5480
|
init_run();
|
|
5400
5481
|
init_app_settings();
|
|
5401
5482
|
init_cursor_events();
|
|
5483
|
+
init_injected_mcp();
|
|
5402
5484
|
init_node_launch();
|
|
5403
5485
|
init_turn_input();
|
|
5404
5486
|
init_cursor_events();
|
|
@@ -5449,6 +5531,11 @@ var init_cursor = __esm({
|
|
|
5449
5531
|
const prompt = flattenTurnInput(input);
|
|
5450
5532
|
const agentId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
5451
5533
|
const apiKey = resolveCursorApiKey() || void 0;
|
|
5534
|
+
const injected = await buildInjectedMcpServers({
|
|
5535
|
+
includeSideboard: true,
|
|
5536
|
+
includeBrightsy: isBrightsyConnected()
|
|
5537
|
+
});
|
|
5538
|
+
const mcpServers = toCursorMcpServers(injected);
|
|
5452
5539
|
const req = {
|
|
5453
5540
|
prompt,
|
|
5454
5541
|
cwd: thread.worktreePath,
|
|
@@ -5457,7 +5544,8 @@ var init_cursor = __esm({
|
|
|
5457
5544
|
effort: thread.effort,
|
|
5458
5545
|
fast: thread.fast,
|
|
5459
5546
|
planMode: thread.planMode,
|
|
5460
|
-
apiKey
|
|
5547
|
+
apiKey,
|
|
5548
|
+
...Object.keys(mcpServers).length > 0 ? { mcpServers } : {}
|
|
5461
5549
|
};
|
|
5462
5550
|
const runner = cursorRunnerPath();
|
|
5463
5551
|
const isTs = runner.endsWith(".ts");
|
|
@@ -5551,6 +5639,7 @@ var init_opencode = __esm({
|
|
|
5551
5639
|
"use strict";
|
|
5552
5640
|
init_run();
|
|
5553
5641
|
init_error_detail();
|
|
5642
|
+
init_injected_mcp();
|
|
5554
5643
|
init_turn_input();
|
|
5555
5644
|
init_types();
|
|
5556
5645
|
FALLBACK_OPENCODE_MODELS = [
|
|
@@ -5611,6 +5700,11 @@ var init_opencode = __esm({
|
|
|
5611
5700
|
if (model) {
|
|
5612
5701
|
args.push("--model", model);
|
|
5613
5702
|
}
|
|
5703
|
+
const injected = await buildInjectedMcpServers({
|
|
5704
|
+
includeSideboard: true,
|
|
5705
|
+
includeBrightsy: isBrightsyConnected()
|
|
5706
|
+
});
|
|
5707
|
+
const mcpContent = injected.length > 0 ? toOpencodeMcpConfigContent(injected) : null;
|
|
5614
5708
|
return {
|
|
5615
5709
|
file: "opencode",
|
|
5616
5710
|
args,
|
|
@@ -5619,7 +5713,8 @@ var init_opencode = __esm({
|
|
|
5619
5713
|
// message is given (see resolveRunInput in opencode's run.ts).
|
|
5620
5714
|
stdin: prompt,
|
|
5621
5715
|
env: {
|
|
5622
|
-
OPENCODE_PERMISSION: mode.opencodePermission
|
|
5716
|
+
OPENCODE_PERMISSION: mode.opencodePermission,
|
|
5717
|
+
...mcpContent ? { OPENCODE_CONFIG_CONTENT: mcpContent } : {}
|
|
5623
5718
|
}
|
|
5624
5719
|
};
|
|
5625
5720
|
},
|
|
@@ -5915,7 +6010,10 @@ function zonedWallTimeToUtc(day, hour, minute, timeZone) {
|
|
|
5915
6010
|
}
|
|
5916
6011
|
}
|
|
5917
6012
|
function resolveQuotaFallbackAgent(current, preferred) {
|
|
5918
|
-
const ordered =
|
|
6013
|
+
const ordered = [
|
|
6014
|
+
...preferred && preferred !== "brightsy" ? [preferred] : [],
|
|
6015
|
+
...FALLBACK_ORDER.filter((a) => a !== preferred)
|
|
6016
|
+
];
|
|
5919
6017
|
return ordered.find((a) => a !== current) ?? (current === "cursor" ? "codex" : "cursor");
|
|
5920
6018
|
}
|
|
5921
6019
|
var FALLBACK_ORDER;
|
|
@@ -5926,7 +6024,6 @@ var init_session_quota = __esm({
|
|
|
5926
6024
|
"cursor",
|
|
5927
6025
|
"codex",
|
|
5928
6026
|
"opencode",
|
|
5929
|
-
"brightsy",
|
|
5930
6027
|
"claude"
|
|
5931
6028
|
];
|
|
5932
6029
|
}
|
|
@@ -6113,11 +6210,14 @@ var init_install = __esm({
|
|
|
6113
6210
|
var agents_exports = {};
|
|
6114
6211
|
__export(agents_exports, {
|
|
6115
6212
|
CLAUDE_MODEL_CATALOG: () => CLAUDE_MODEL_CATALOG,
|
|
6213
|
+
ORCHESTRATOR_AGENT_KINDS: () => ORCHESTRATOR_AGENT_KINDS,
|
|
6116
6214
|
PLAN_MODE_INSTRUCTION: () => PLAN_MODE_INSTRUCTION,
|
|
6117
6215
|
allAdapters: () => allAdapters,
|
|
6216
|
+
assertOrchestratorCapableAgent: () => assertOrchestratorCapableAgent,
|
|
6118
6217
|
brightsyAdapter: () => brightsyAdapter,
|
|
6119
6218
|
claudeAdapter: () => claudeAdapter,
|
|
6120
6219
|
codexAdapter: () => codexAdapter,
|
|
6220
|
+
coerceOrchestratorAgent: () => coerceOrchestratorAgent,
|
|
6121
6221
|
cursorAdapter: () => cursorAdapter,
|
|
6122
6222
|
cursorSdkMessageToEvents: () => cursorSdkMessageToEvents,
|
|
6123
6223
|
decodeBrightsyTarget: () => decodeBrightsyTarget,
|
|
@@ -6127,6 +6227,7 @@ __export(agents_exports, {
|
|
|
6127
6227
|
getAgentSetupInfo: () => getAgentSetupInfo,
|
|
6128
6228
|
installAgent: () => installAgent,
|
|
6129
6229
|
isCursorAutoModel: () => isCursorAutoModel,
|
|
6230
|
+
isOrchestratorCapableAgent: () => isOrchestratorCapableAgent,
|
|
6130
6231
|
isSessionQuotaLimit: () => isSessionQuotaLimit,
|
|
6131
6232
|
listAgentSetupInfo: () => listAgentSetupInfo,
|
|
6132
6233
|
listBrightsyChatTargets: () => listBrightsyChatTargets,
|
|
@@ -6169,6 +6270,7 @@ var init_agents = __esm({
|
|
|
6169
6270
|
init_opencode();
|
|
6170
6271
|
init_list_models();
|
|
6171
6272
|
init_session_quota();
|
|
6273
|
+
init_orchestrator_capable();
|
|
6172
6274
|
init_path();
|
|
6173
6275
|
init_install();
|
|
6174
6276
|
adapters = {
|
|
@@ -6278,10 +6380,13 @@ __export(index_exports, {
|
|
|
6278
6380
|
GLOBAL_WORKSPACE_ID: () => GLOBAL_WORKSPACE_ID,
|
|
6279
6381
|
HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
|
|
6280
6382
|
MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS: () => MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS,
|
|
6383
|
+
ORCHESTRATOR_AGENT_KINDS: () => ORCHESTRATOR_AGENT_KINDS,
|
|
6281
6384
|
Orchestrator: () => Orchestrator,
|
|
6282
6385
|
PASTE_ATTACH_MIN_CHARS: () => PASTE_ATTACH_MIN_CHARS,
|
|
6283
6386
|
PASTE_ATTACH_MIN_LINES: () => PASTE_ATTACH_MIN_LINES,
|
|
6284
6387
|
PLAN_MODE_INSTRUCTION: () => PLAN_MODE_INSTRUCTION,
|
|
6388
|
+
REPO_REVIEW_NAME: () => REPO_REVIEW_NAME,
|
|
6389
|
+
REPO_REVIEW_PATH: () => REPO_REVIEW_PATH,
|
|
6285
6390
|
REVIEW_REQUEST_NAME: () => REVIEW_REQUEST_NAME,
|
|
6286
6391
|
REVIEW_REQUEST_PATH: () => REVIEW_REQUEST_PATH,
|
|
6287
6392
|
REVIEW_REQUEST_PREFILL: () => REVIEW_REQUEST_PREFILL,
|
|
@@ -6302,6 +6407,7 @@ __export(index_exports, {
|
|
|
6302
6407
|
applyAppEnvironment: () => applyAppEnvironment,
|
|
6303
6408
|
applyCompaction: () => applyCompaction,
|
|
6304
6409
|
applyThreadIntoMain: () => applyThreadIntoMain,
|
|
6410
|
+
assertOrchestratorCapableAgent: () => assertOrchestratorCapableAgent,
|
|
6305
6411
|
attachmentFromAbsolutePath: () => attachmentFromAbsolutePath,
|
|
6306
6412
|
attachmentsFromBuffers: () => attachmentsFromBuffers,
|
|
6307
6413
|
attachmentsFromWorktreePaths: () => attachmentsFromWorktreePaths,
|
|
@@ -6334,6 +6440,7 @@ __export(index_exports, {
|
|
|
6334
6440
|
cleanupOrphanWorktrees: () => cleanupOrphanWorktrees,
|
|
6335
6441
|
cloneRepoIntoSideboard: () => cloneRepoIntoSideboard,
|
|
6336
6442
|
codexAdapter: () => codexAdapter,
|
|
6443
|
+
coerceOrchestratorAgent: () => coerceOrchestratorAgent,
|
|
6337
6444
|
collectTakenTeamSlugs: () => collectTakenTeamSlugs,
|
|
6338
6445
|
commitAll: () => commitAll,
|
|
6339
6446
|
conductorDbPath: () => conductorDbPath,
|
|
@@ -6365,6 +6472,7 @@ __export(index_exports, {
|
|
|
6365
6472
|
ensureCloudCoordinator: () => ensureCloudCoordinator,
|
|
6366
6473
|
ensureGhPreferOrigin: () => ensureGhPreferOrigin,
|
|
6367
6474
|
ensureGlobalCoordinatorCwd: () => ensureGlobalCoordinatorCwd,
|
|
6475
|
+
ensureReviewRequestFile: () => ensureReviewRequestFile,
|
|
6368
6476
|
ensureWorkspace: () => ensureWorkspace,
|
|
6369
6477
|
estimateMessageChars: () => estimateMessageChars,
|
|
6370
6478
|
estimateThreadChars: () => estimateThreadChars,
|
|
@@ -6438,6 +6546,7 @@ __export(index_exports, {
|
|
|
6438
6546
|
isGlobalThread: () => isGlobalThread,
|
|
6439
6547
|
isImageFilePath: () => isImageFilePath,
|
|
6440
6548
|
isLinearConnected: () => isLinearConnected,
|
|
6549
|
+
isOrchestratorCapableAgent: () => isOrchestratorCapableAgent,
|
|
6441
6550
|
isOrchestratorThread: () => isOrchestratorThread,
|
|
6442
6551
|
isPidAlive: () => isPidAlive,
|
|
6443
6552
|
isPlaceholderBranch: () => isPlaceholderBranch,
|
|
@@ -6527,6 +6636,7 @@ __export(index_exports, {
|
|
|
6527
6636
|
resolvePrSelector: () => resolvePrSelector,
|
|
6528
6637
|
resolveQuotaFallbackAgent: () => resolveQuotaFallbackAgent,
|
|
6529
6638
|
resolveRepoRoot: () => resolveRepoRoot,
|
|
6639
|
+
resolveReviewGuidelines: () => resolveReviewGuidelines,
|
|
6530
6640
|
resolveThreadDefaults: () => resolveThreadDefaults,
|
|
6531
6641
|
resolveThreadEffort: () => resolveThreadEffort,
|
|
6532
6642
|
resolveWorktreeStartPoint: () => resolveWorktreeStartPoint,
|
|
@@ -6542,6 +6652,7 @@ __export(index_exports, {
|
|
|
6542
6652
|
settingsSourceLabel: () => settingsSourceLabel,
|
|
6543
6653
|
shouldAttachPastedText: () => shouldAttachPastedText,
|
|
6544
6654
|
shouldCompactContext: () => shouldCompactContext,
|
|
6655
|
+
shouldRefreshReviewRequestTemplate: () => shouldRefreshReviewRequestTemplate,
|
|
6545
6656
|
shouldRunWorktreeCleanup: () => shouldRunWorktreeCleanup,
|
|
6546
6657
|
sideboardHomeDir: () => sideboardHomeDir,
|
|
6547
6658
|
sideboardReposDir: () => sideboardReposDir,
|
|
@@ -6790,6 +6901,7 @@ init_app_settings();
|
|
|
6790
6901
|
init_global_workspace();
|
|
6791
6902
|
init_brightsy();
|
|
6792
6903
|
init_agents();
|
|
6904
|
+
init_orchestrator_capable();
|
|
6793
6905
|
|
|
6794
6906
|
// src/agents/message-parts.ts
|
|
6795
6907
|
function asRecord(input) {
|
|
@@ -7034,6 +7146,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
7034
7146
|
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
|
|
7035
7147
|
ensureGlobalCoordinatorCwd2();
|
|
7036
7148
|
}
|
|
7149
|
+
if (isOrchestratorThread(thread)) {
|
|
7150
|
+
assertOrchestratorCapableAgent(thread.agent);
|
|
7151
|
+
}
|
|
7037
7152
|
const adapter = getAdapter(thread.agent);
|
|
7038
7153
|
const cmd = await adapter.buildTurn(thread, input);
|
|
7039
7154
|
if (cmd.cwd !== thread.worktreePath) {
|
|
@@ -9326,6 +9441,7 @@ var import_node_crypto4 = require("crypto");
|
|
|
9326
9441
|
init_teams();
|
|
9327
9442
|
init_worktree_labels();
|
|
9328
9443
|
init_global_workspace();
|
|
9444
|
+
init_orchestrator_capable();
|
|
9329
9445
|
init_thread_store();
|
|
9330
9446
|
init_worktree_labels();
|
|
9331
9447
|
function sameWorktreePath(a, b) {
|
|
@@ -9389,6 +9505,10 @@ function createChatTab(input) {
|
|
|
9389
9505
|
const binding = worktreeBindingFrom(from);
|
|
9390
9506
|
const explicitTitle = input.title?.trim();
|
|
9391
9507
|
const title = explicitTitle || allocateTeamName(takenTeamSlugsForChatTab(binding.worktreePath)).name;
|
|
9508
|
+
const nextAgent = input.agent ?? from.agent;
|
|
9509
|
+
if (isOrchestratorThread(from) || binding.sourceType === "orchestration") {
|
|
9510
|
+
assertOrchestratorCapableAgent(nextAgent);
|
|
9511
|
+
}
|
|
9392
9512
|
const thread = createEmptyThread({
|
|
9393
9513
|
title,
|
|
9394
9514
|
// Chat-tab nicknames (soccer team or explicit) must stick. Post-turn
|
|
@@ -9396,7 +9516,7 @@ function createChatTab(input) {
|
|
|
9396
9516
|
// shared worktree folder name (e.g. fork "Arsenal" → "Monaco").
|
|
9397
9517
|
userSetTitle: true,
|
|
9398
9518
|
...binding,
|
|
9399
|
-
agent:
|
|
9519
|
+
agent: nextAgent,
|
|
9400
9520
|
model: input.model !== void 0 ? input.model : input.agent && input.agent !== from.agent ? null : from.model,
|
|
9401
9521
|
effort: input.effort !== void 0 ? input.effort : from.effort,
|
|
9402
9522
|
fast: input.fast !== void 0 ? Boolean(input.fast) : from.fast,
|
|
@@ -9999,6 +10119,7 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
9999
10119
|
|
|
10000
10120
|
// src/orchestrator/orchestrator.ts
|
|
10001
10121
|
init_thread_store();
|
|
10122
|
+
init_orchestrator_capable();
|
|
10002
10123
|
|
|
10003
10124
|
// src/review/request-review.ts
|
|
10004
10125
|
var import_node_crypto5 = require("crypto");
|
|
@@ -10006,22 +10127,149 @@ var import_node_fs24 = require("fs");
|
|
|
10006
10127
|
var import_node_path23 = require("path");
|
|
10007
10128
|
init_global_workspace();
|
|
10008
10129
|
init_thread_store();
|
|
10130
|
+
|
|
10131
|
+
// src/review/review-request-template.ts
|
|
10132
|
+
var REVIEW_REQUEST_TEMPLATE = `# Review guidelines:
|
|
10133
|
+
|
|
10134
|
+
You are reviewing a proposed code change so a human can decide whether it is **ready to merge / land**. Findings matter, but the primary deliverable is a clear readiness recommendation \u2014 not a laundry list of style notes.
|
|
10135
|
+
|
|
10136
|
+
## Required outcome
|
|
10137
|
+
|
|
10138
|
+
Start your reply with a **Recommendation** section using exactly one of:
|
|
10139
|
+
|
|
10140
|
+
- **Approve** \u2014 ready to merge as-is (or with only trivial nits the author can ignore).
|
|
10141
|
+
- **Approve with nits** \u2014 ready to merge; list only optional polish that should not block.
|
|
10142
|
+
- **Request changes** \u2014 not ready; blocking issues must be fixed first.
|
|
10143
|
+
- **Needs more information** \u2014 cannot judge readiness yet (missing context, incomplete diff, unclear intent).
|
|
10144
|
+
|
|
10145
|
+
In 1\u20133 sentences, say **why** \u2014 grounded in correctness, risk, test coverage, and scope \u2014 not vibes. If you request changes, name the blockers explicitly.
|
|
10146
|
+
|
|
10147
|
+
People running this review are asking \u201Ccan we ship this?\u201D Treat that as the question you answer first.
|
|
10148
|
+
|
|
10149
|
+
## Findings
|
|
10150
|
+
|
|
10151
|
+
Below are guidelines for determining whether an issue is worth flagging to the original author.
|
|
10152
|
+
|
|
10153
|
+
These are not the final word. More specific guidelines elsewhere (developer message, user message, a file, etc.) override these.
|
|
10154
|
+
|
|
10155
|
+
Flag something as a bug / blocking finding only when:
|
|
10156
|
+
|
|
10157
|
+
1. It meaningfully impacts the accuracy, performance, security, or maintainability of the code.
|
|
10158
|
+
2. The bug is discrete and actionable (not a vague codebase-wide complaint or a bundle of unrelated issues).
|
|
10159
|
+
3. Fixing it does not demand rigor absent from the rest of the codebase.
|
|
10160
|
+
4. The issue was introduced by this change (do not flag pre-existing bugs unless they are newly exposed by this PR).
|
|
10161
|
+
5. The author would likely fix it if made aware.
|
|
10162
|
+
6. It does not rely on unstated assumptions about the codebase or author intent.
|
|
10163
|
+
7. Speculative breakage is not enough \u2014 identify the other code that is provably affected.
|
|
10164
|
+
8. It is clearly not just an intentional change by the author.
|
|
10165
|
+
|
|
10166
|
+
When flagging an issue, include a short accompanying comment:
|
|
10167
|
+
|
|
10168
|
+
1. Clear about why it is a problem.
|
|
10169
|
+
2. Severity must match reality \u2014 do not inflate.
|
|
10170
|
+
3. Brief: at most one paragraph; avoid unnecessary line breaks in prose.
|
|
10171
|
+
4. No code chunks longer than 3 lines; wrap code in inline ticks or a fenced block.
|
|
10172
|
+
5. Call out scenarios / environments / inputs needed to hit the bug when severity depends on them.
|
|
10173
|
+
6. Matter-of-fact tone \u2014 helpful assistant, not accusatory or effusive.
|
|
10174
|
+
7. Skimmable on first read.
|
|
10175
|
+
8. No empty flattery (\u201CGreat job\u2026\u201D, \u201CThanks for\u2026\u201D).
|
|
10176
|
+
|
|
10177
|
+
HOW MANY FINDINGS TO RETURN:
|
|
10178
|
+
|
|
10179
|
+
List every finding the author would fix if they knew about it. If nothing qualifies, say so and still give the Recommendation. Do not stop at the first finding.
|
|
10180
|
+
|
|
10181
|
+
GUIDELINES:
|
|
10182
|
+
|
|
10183
|
+
- Ignore trivial style unless it obscures meaning or violates documented standards.
|
|
10184
|
+
- One comment per distinct issue (or a short multi-line range if needed).
|
|
10185
|
+
- Use \`\`\`suggestion blocks ONLY for concrete replacement code (minimal lines; no commentary inside the block).
|
|
10186
|
+
- In every \`\`\`suggestion block, preserve the exact leading whitespace of the replaced lines (spaces vs tabs, number of spaces).
|
|
10187
|
+
- Do NOT introduce or remove outer indentation levels unless that is the actual fix.
|
|
10188
|
+
- Separate **blocking** findings from **nits**. Only blocking findings should drive Request changes.
|
|
10189
|
+
|
|
10190
|
+
The report appears in chat (and can become Sideboard diff comments). Avoid unnecessary location chatter in the body; keep line ranges as short as possible (prefer \u22645\u201310 lines).
|
|
10191
|
+
|
|
10192
|
+
## Getting the diff
|
|
10193
|
+
|
|
10194
|
+
Use Sideboard's diff for this thread's worktree. Prefer the \`get_diff\` MCP tool (pass this thread's ref) for a compact summary, then read specific files with Read/Glob as needed. In the Sideboard desktop app, the Changes panel shows the same worktree diff.
|
|
10195
|
+
|
|
10196
|
+
If the user asks you to address or read line comments they added in the Changes / file diff UI, those arrive as \`diff-comment\` attachments on the next turn \u2014 follow them precisely.
|
|
10197
|
+
|
|
10198
|
+
## Fallback: if you don't have access to the Sideboard diff tool
|
|
10199
|
+
|
|
10200
|
+
If you don't have access to \`get_diff\`, use the following git commands to get the diff:
|
|
10201
|
+
|
|
10202
|
+
\`\`\`bash
|
|
10203
|
+
# Get the merge base between this branch and the target
|
|
10204
|
+
MERGE_BASE=$(git merge-base origin/main HEAD)
|
|
10205
|
+
|
|
10206
|
+
# Get the committed diff against the merge base
|
|
10207
|
+
git diff $MERGE_BASE HEAD
|
|
10208
|
+
|
|
10209
|
+
# Get any uncommitted changes (staged and unstaged)
|
|
10210
|
+
git diff HEAD
|
|
10211
|
+
\`\`\`
|
|
10212
|
+
|
|
10213
|
+
Review the combination of both outputs: the first shows all committed changes on this branch relative to the target, and the second shows any uncommitted work in progress.
|
|
10214
|
+
|
|
10215
|
+
No need to mention in your report whether or not you used one of the fallback strategies; it's usually irrelevant.
|
|
10216
|
+
|
|
10217
|
+
## Output format
|
|
10218
|
+
|
|
10219
|
+
**1. Recommendation first** (required), then **2. Findings** (may be empty).
|
|
10220
|
+
|
|
10221
|
+
Only report ONE finding per unique issue.
|
|
10222
|
+
|
|
10223
|
+
<example>
|
|
10224
|
+
## Recommendation
|
|
10225
|
+
|
|
10226
|
+
**Request changes** \u2014 The empty-input crash on load will break first-run users; fix that before merge. The unused helper is a nit and can wait.
|
|
10227
|
+
|
|
10228
|
+
## Findings
|
|
10229
|
+
|
|
10230
|
+
### **#1 Empty input causes crash** (blocking)
|
|
10231
|
+
|
|
10232
|
+
If the input field is empty when the page loads, the app will crash.
|
|
10233
|
+
|
|
10234
|
+
File: src/client/frontends/desktop/ui/Input.tsx
|
|
10235
|
+
|
|
10236
|
+
### **#2 Dead code** (nit)
|
|
10237
|
+
|
|
10238
|
+
The getUserData function is now unused. It should be deleted.
|
|
10239
|
+
|
|
10240
|
+
File: src/client/frontends/desktop/core/UserData.ts
|
|
10241
|
+
</example>
|
|
10242
|
+
|
|
10243
|
+
<example>
|
|
10244
|
+
## Recommendation
|
|
10245
|
+
|
|
10246
|
+
**Approve** \u2014 Diff is scoped, behavior looks correct, and there are no blocking issues. Safe to merge.
|
|
10247
|
+
</example>
|
|
10248
|
+
`;
|
|
10249
|
+
|
|
10250
|
+
// src/review/request-review.ts
|
|
10251
|
+
var REPO_REVIEW_PATH = ".sideboard/review.md";
|
|
10252
|
+
var REPO_REVIEW_NAME = "review.md";
|
|
10009
10253
|
var REVIEW_REQUEST_PATH = ".sideboard/attachments/Review request.md";
|
|
10010
10254
|
var REVIEW_REQUEST_NAME = "Review request.md";
|
|
10011
|
-
var REVIEW_REQUEST_PREFILL =
|
|
10012
|
-
|
|
10013
|
-
|
|
10014
|
-
|
|
10015
|
-
|
|
10016
|
-
|
|
10017
|
-
|
|
10018
|
-
|
|
10019
|
-
|
|
10020
|
-
|
|
10021
|
-
|
|
10255
|
+
var REVIEW_REQUEST_PREFILL = "Review.";
|
|
10256
|
+
var ATTACHMENTS_GITIGNORE2 = `# Sideboard review / composer attachments (local only)
|
|
10257
|
+
*
|
|
10258
|
+
!.gitignore
|
|
10259
|
+
`;
|
|
10260
|
+
var LEGACY_REVIEW_TEMPLATE_MARKERS = [
|
|
10261
|
+
"You are acting as a reviewer for a proposed code change made by another engineer.",
|
|
10262
|
+
"HOW MANY FINDINGS TO RETURN:"
|
|
10263
|
+
];
|
|
10264
|
+
function shouldRefreshReviewRequestTemplate(content) {
|
|
10265
|
+
const trimmed = content.trim();
|
|
10266
|
+
if (!trimmed) return true;
|
|
10267
|
+
if (/##\s*Recommendation|ready to merge|Approve with nits|Request changes/i.test(trimmed)) {
|
|
10268
|
+
return false;
|
|
10269
|
+
}
|
|
10270
|
+
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
10022
10271
|
}
|
|
10023
|
-
function
|
|
10024
|
-
const abs = (0, import_node_path23.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
10272
|
+
function readTextIfPresent(abs) {
|
|
10025
10273
|
if (!(0, import_node_fs24.existsSync)(abs)) return null;
|
|
10026
10274
|
try {
|
|
10027
10275
|
const content = (0, import_node_fs24.readFileSync)(abs, "utf8");
|
|
@@ -10030,6 +10278,87 @@ function readExistingReviewRequestFile(worktreePath) {
|
|
|
10030
10278
|
return null;
|
|
10031
10279
|
}
|
|
10032
10280
|
}
|
|
10281
|
+
function ensureAttachmentsGitignore(worktreePath) {
|
|
10282
|
+
const gitignoreAbs = (0, import_node_path23.join)(worktreePath, ".sideboard", "attachments", ".gitignore");
|
|
10283
|
+
if ((0, import_node_fs24.existsSync)(gitignoreAbs)) return;
|
|
10284
|
+
(0, import_node_fs24.mkdirSync)((0, import_node_path23.dirname)(gitignoreAbs), { recursive: true });
|
|
10285
|
+
(0, import_node_fs24.writeFileSync)(gitignoreAbs, ATTACHMENTS_GITIGNORE2, "utf8");
|
|
10286
|
+
}
|
|
10287
|
+
function resolveReviewGuidelines(worktreePath) {
|
|
10288
|
+
const repoAbs = (0, import_node_path23.join)(worktreePath, REPO_REVIEW_PATH);
|
|
10289
|
+
const repoContent = readTextIfPresent(repoAbs);
|
|
10290
|
+
if (repoContent) {
|
|
10291
|
+
return {
|
|
10292
|
+
path: REPO_REVIEW_PATH,
|
|
10293
|
+
name: REPO_REVIEW_NAME,
|
|
10294
|
+
content: repoContent,
|
|
10295
|
+
source: "repo"
|
|
10296
|
+
};
|
|
10297
|
+
}
|
|
10298
|
+
const localAbs = (0, import_node_path23.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
10299
|
+
const localContent = readTextIfPresent(localAbs);
|
|
10300
|
+
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
10301
|
+
return {
|
|
10302
|
+
path: REVIEW_REQUEST_PATH,
|
|
10303
|
+
name: REVIEW_REQUEST_NAME,
|
|
10304
|
+
content: localContent,
|
|
10305
|
+
source: "local"
|
|
10306
|
+
};
|
|
10307
|
+
}
|
|
10308
|
+
ensureAttachmentsGitignore(worktreePath);
|
|
10309
|
+
(0, import_node_fs24.mkdirSync)((0, import_node_path23.dirname)(localAbs), { recursive: true });
|
|
10310
|
+
(0, import_node_fs24.writeFileSync)(localAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
|
|
10311
|
+
return {
|
|
10312
|
+
path: REVIEW_REQUEST_PATH,
|
|
10313
|
+
name: REVIEW_REQUEST_NAME,
|
|
10314
|
+
content: REVIEW_REQUEST_TEMPLATE,
|
|
10315
|
+
source: "stock"
|
|
10316
|
+
};
|
|
10317
|
+
}
|
|
10318
|
+
function ensureReviewRequestFile(worktreePath) {
|
|
10319
|
+
const repoAbs = (0, import_node_path23.join)(worktreePath, REPO_REVIEW_PATH);
|
|
10320
|
+
const repoContent = readTextIfPresent(repoAbs);
|
|
10321
|
+
if (repoContent) {
|
|
10322
|
+
return {
|
|
10323
|
+
path: REPO_REVIEW_PATH,
|
|
10324
|
+
name: REPO_REVIEW_NAME,
|
|
10325
|
+
content: repoContent,
|
|
10326
|
+
source: "repo"
|
|
10327
|
+
};
|
|
10328
|
+
}
|
|
10329
|
+
const localAbs = (0, import_node_path23.join)(worktreePath, REVIEW_REQUEST_PATH);
|
|
10330
|
+
const localContent = readTextIfPresent(localAbs);
|
|
10331
|
+
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
10332
|
+
return {
|
|
10333
|
+
path: REVIEW_REQUEST_PATH,
|
|
10334
|
+
name: REVIEW_REQUEST_NAME,
|
|
10335
|
+
content: localContent,
|
|
10336
|
+
source: "local"
|
|
10337
|
+
};
|
|
10338
|
+
}
|
|
10339
|
+
(0, import_node_fs24.mkdirSync)((0, import_node_path23.dirname)(repoAbs), { recursive: true });
|
|
10340
|
+
(0, import_node_fs24.writeFileSync)(repoAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
|
|
10341
|
+
return {
|
|
10342
|
+
path: REPO_REVIEW_PATH,
|
|
10343
|
+
name: REPO_REVIEW_NAME,
|
|
10344
|
+
content: REVIEW_REQUEST_TEMPLATE,
|
|
10345
|
+
source: "repo"
|
|
10346
|
+
};
|
|
10347
|
+
}
|
|
10348
|
+
function buildReviewRequestAttachment(content, opts) {
|
|
10349
|
+
const path = opts?.path ?? REVIEW_REQUEST_PATH;
|
|
10350
|
+
const name = opts?.name ?? (path === REPO_REVIEW_PATH ? REPO_REVIEW_NAME : REVIEW_REQUEST_NAME);
|
|
10351
|
+
return {
|
|
10352
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
10353
|
+
name,
|
|
10354
|
+
kind: "file",
|
|
10355
|
+
path,
|
|
10356
|
+
content
|
|
10357
|
+
};
|
|
10358
|
+
}
|
|
10359
|
+
function readExistingReviewRequestFile(worktreePath) {
|
|
10360
|
+
return readTextIfPresent((0, import_node_path23.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path23.join)(worktreePath, REVIEW_REQUEST_PATH));
|
|
10361
|
+
}
|
|
10033
10362
|
async function requestReview(threadRef, send) {
|
|
10034
10363
|
const from = findThreadByRef(threadRef);
|
|
10035
10364
|
if (!from) throw new Error(`Thread not found: ${threadRef}`);
|
|
@@ -10041,12 +10370,16 @@ async function requestReview(threadRef, send) {
|
|
|
10041
10370
|
if (from.status === "archived") {
|
|
10042
10371
|
throw new Error(`Thread is archived: ${from.id}`);
|
|
10043
10372
|
}
|
|
10044
|
-
const
|
|
10045
|
-
const attachments = existing ? [buildReviewRequestAttachment(existing)] : [];
|
|
10373
|
+
const guidelines = resolveReviewGuidelines(from.worktreePath);
|
|
10046
10374
|
const tab = createChatTab({
|
|
10047
10375
|
fromThreadId: from.id,
|
|
10048
10376
|
title: "Review",
|
|
10049
|
-
attachments
|
|
10377
|
+
attachments: [
|
|
10378
|
+
buildReviewRequestAttachment(guidelines.content, {
|
|
10379
|
+
path: guidelines.path,
|
|
10380
|
+
name: guidelines.name
|
|
10381
|
+
})
|
|
10382
|
+
]
|
|
10050
10383
|
});
|
|
10051
10384
|
const started = await send(tab.id, REVIEW_REQUEST_PREFILL);
|
|
10052
10385
|
return { tab: started, from };
|
|
@@ -10626,9 +10959,11 @@ var Orchestrator = class {
|
|
|
10626
10959
|
this.emit({ type: "error", threadId, message: `context compact failed: ${message}` });
|
|
10627
10960
|
thread = this.requireThread(threadId);
|
|
10628
10961
|
}
|
|
10962
|
+
const sentAttachments = thread.attachments.length > 0 ? [...thread.attachments] : void 0;
|
|
10629
10963
|
appendMessage(threadId, {
|
|
10630
10964
|
role: "user",
|
|
10631
10965
|
text: prompt,
|
|
10966
|
+
...sentAttachments ? { attachments: sentAttachments } : {},
|
|
10632
10967
|
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
10633
10968
|
});
|
|
10634
10969
|
thread = this.requireThread(threadId);
|
|
@@ -10636,7 +10971,7 @@ var Orchestrator = class {
|
|
|
10636
10971
|
thread.worktreePath,
|
|
10637
10972
|
prompt,
|
|
10638
10973
|
{
|
|
10639
|
-
attachments: thread.attachments
|
|
10974
|
+
attachments: sentAttachments ?? thread.attachments
|
|
10640
10975
|
}
|
|
10641
10976
|
);
|
|
10642
10977
|
const orchestrationReminder = isOrchestratorThread(thread) ? coordinatorTurnReminder({
|
|
@@ -11320,6 +11655,9 @@ var Orchestrator = class {
|
|
|
11320
11655
|
`Cannot switch agent provider mid-chat (${thread.agent} \u2192 ${patch.agent}). Start a new chat tab instead.`
|
|
11321
11656
|
);
|
|
11322
11657
|
}
|
|
11658
|
+
if (isOrchestratorThread(thread)) {
|
|
11659
|
+
assertOrchestratorCapableAgent(patch.agent);
|
|
11660
|
+
}
|
|
11323
11661
|
next.agent = patch.agent;
|
|
11324
11662
|
if (patch.agent !== "claude" && patch.model === void 0) next.model = null;
|
|
11325
11663
|
next.sessionId = null;
|
|
@@ -11937,7 +12275,7 @@ async function startMcpServer() {
|
|
|
11937
12275
|
);
|
|
11938
12276
|
server.tool(
|
|
11939
12277
|
"request_review",
|
|
11940
|
-
|
|
12278
|
+
'Start a merge-readiness Review on a worktree agent thread (same as the desktop Review button). Opens a new Review chat tab, attaches .sideboard/review.md when present (else local Review request.md / stock template), and sends "Review." Expect Approve / Approve with nits / Request changes / Needs more information. Pass a worktree thread ref \u2014 not the orchestrator. Then wait_for_turn / get_turn_result on the returned review tab id.',
|
|
11941
12279
|
{ ref: import_zod.z.string().describe("Worktree thread id/ref to review") },
|
|
11942
12280
|
async ({ ref }) => {
|
|
11943
12281
|
try {
|
|
@@ -12029,7 +12367,7 @@ async function startMcpServer() {
|
|
|
12029
12367
|
);
|
|
12030
12368
|
server.tool(
|
|
12031
12369
|
"fork_chat",
|
|
12032
|
-
"Fork a chat into a NEW tab on the SAME workspace: worktree agent \u2192 same worktree tab; Global orchestration chat \u2192 new orchestration chat (same synthetic home). Seeds a transcript; optional agent override. Leave model unset for Auto unless you have a reason. Remote coordinators use this to continue an orchestration chat on another agent after session limits. Then send_to_thread / wait_for_turn on the returned id. Use fork_worktree only for worktree agents that need a new git worktree.",
|
|
12370
|
+
"Fork a chat into a NEW tab on the SAME workspace: worktree agent \u2192 same worktree tab; Global orchestration chat \u2192 new orchestration chat (same synthetic home). Seeds a transcript; optional agent override. Leave model unset for Auto unless you have a reason. Orchestration forks require an MCP-capable agent (claude, cursor, codex, opencode \u2014 not brightsy). Remote coordinators use this to continue an orchestration chat on another agent after session limits. Then send_to_thread / wait_for_turn on the returned id. Use fork_worktree only for worktree agents that need a new git worktree.",
|
|
12033
12371
|
{
|
|
12034
12372
|
ref: import_zod.z.string().describe("Thread id/ref to fork (worktree agent or orchestration chat)"),
|
|
12035
12373
|
through_index: import_zod.z.number().optional().describe("Inclusive message index to include in the transcript (default: all)"),
|
|
@@ -12617,10 +12955,13 @@ init_injected_mcp();
|
|
|
12617
12955
|
GLOBAL_WORKSPACE_ID,
|
|
12618
12956
|
HARNESS_ENV_KEYS,
|
|
12619
12957
|
MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS,
|
|
12958
|
+
ORCHESTRATOR_AGENT_KINDS,
|
|
12620
12959
|
Orchestrator,
|
|
12621
12960
|
PASTE_ATTACH_MIN_CHARS,
|
|
12622
12961
|
PASTE_ATTACH_MIN_LINES,
|
|
12623
12962
|
PLAN_MODE_INSTRUCTION,
|
|
12963
|
+
REPO_REVIEW_NAME,
|
|
12964
|
+
REPO_REVIEW_PATH,
|
|
12624
12965
|
REVIEW_REQUEST_NAME,
|
|
12625
12966
|
REVIEW_REQUEST_PATH,
|
|
12626
12967
|
REVIEW_REQUEST_PREFILL,
|
|
@@ -12641,6 +12982,7 @@ init_injected_mcp();
|
|
|
12641
12982
|
applyAppEnvironment,
|
|
12642
12983
|
applyCompaction,
|
|
12643
12984
|
applyThreadIntoMain,
|
|
12985
|
+
assertOrchestratorCapableAgent,
|
|
12644
12986
|
attachmentFromAbsolutePath,
|
|
12645
12987
|
attachmentsFromBuffers,
|
|
12646
12988
|
attachmentsFromWorktreePaths,
|
|
@@ -12673,6 +13015,7 @@ init_injected_mcp();
|
|
|
12673
13015
|
cleanupOrphanWorktrees,
|
|
12674
13016
|
cloneRepoIntoSideboard,
|
|
12675
13017
|
codexAdapter,
|
|
13018
|
+
coerceOrchestratorAgent,
|
|
12676
13019
|
collectTakenTeamSlugs,
|
|
12677
13020
|
commitAll,
|
|
12678
13021
|
conductorDbPath,
|
|
@@ -12704,6 +13047,7 @@ init_injected_mcp();
|
|
|
12704
13047
|
ensureCloudCoordinator,
|
|
12705
13048
|
ensureGhPreferOrigin,
|
|
12706
13049
|
ensureGlobalCoordinatorCwd,
|
|
13050
|
+
ensureReviewRequestFile,
|
|
12707
13051
|
ensureWorkspace,
|
|
12708
13052
|
estimateMessageChars,
|
|
12709
13053
|
estimateThreadChars,
|
|
@@ -12777,6 +13121,7 @@ init_injected_mcp();
|
|
|
12777
13121
|
isGlobalThread,
|
|
12778
13122
|
isImageFilePath,
|
|
12779
13123
|
isLinearConnected,
|
|
13124
|
+
isOrchestratorCapableAgent,
|
|
12780
13125
|
isOrchestratorThread,
|
|
12781
13126
|
isPidAlive,
|
|
12782
13127
|
isPlaceholderBranch,
|
|
@@ -12866,6 +13211,7 @@ init_injected_mcp();
|
|
|
12866
13211
|
resolvePrSelector,
|
|
12867
13212
|
resolveQuotaFallbackAgent,
|
|
12868
13213
|
resolveRepoRoot,
|
|
13214
|
+
resolveReviewGuidelines,
|
|
12869
13215
|
resolveThreadDefaults,
|
|
12870
13216
|
resolveThreadEffort,
|
|
12871
13217
|
resolveWorktreeStartPoint,
|
|
@@ -12881,6 +13227,7 @@ init_injected_mcp();
|
|
|
12881
13227
|
settingsSourceLabel,
|
|
12882
13228
|
shouldAttachPastedText,
|
|
12883
13229
|
shouldCompactContext,
|
|
13230
|
+
shouldRefreshReviewRequestTemplate,
|
|
12884
13231
|
shouldRunWorktreeCleanup,
|
|
12885
13232
|
sideboardHomeDir,
|
|
12886
13233
|
sideboardReposDir,
|