@sideboard-ai/core 0.1.57 → 0.1.59
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-2YYWW723.js → agents-B2723EOF.js} +4 -4
- package/dist/{agents-AQFEFKBL.js → agents-EADRAAPG.js} +4 -4
- package/dist/{app-settings-2LQNRTBE.js → app-settings-TBHTJWLQ.js} +1 -1
- package/dist/{app-settings-73DI4B6T.js → app-settings-YBNZ4XSR.js} +1 -1
- package/dist/{chunk-5DMYULLC.js → chunk-2P2UK7E7.js} +2 -2
- package/dist/{chunk-7LNGIP3X.js → chunk-73AT5K4A.js} +15 -3
- package/dist/{chunk-DIOF73S2.js → chunk-75QR74KM.js} +7 -2
- package/dist/{chunk-EBWEKG52.js → chunk-CHGOMFTA.js} +3 -3
- package/dist/{chunk-C4BCC5X5.js → chunk-FGNBTFRD.js} +7 -2
- package/dist/{chunk-H6GGDLYS.js → chunk-JB2H7E7V.js} +1 -1
- package/dist/{chunk-BXJ76RHF.js → chunk-MBAL5FE6.js} +4 -4
- package/dist/{chunk-XOU6HNQJ.js → chunk-MFGGIRUA.js} +39 -13
- package/dist/{chunk-S42XDFKF.js → chunk-MLAST5BB.js} +3 -3
- package/dist/{chunk-C3J4GDW4.js → chunk-MX7UH5AT.js} +76 -60
- package/dist/{chunk-DQJ5D42H.js → chunk-NTYRBRE7.js} +44 -13
- package/dist/{chunk-DZFH2KLT.js → chunk-P7EQUFB6.js} +39 -13
- package/dist/{chunk-V2DUTUNC.js → chunk-QJBC4BRK.js} +2 -2
- package/dist/{chunk-ZNM4MAN4.js → chunk-RIWUU7FO.js} +15 -3
- package/dist/{chunk-UA5NDAHL.js → chunk-XWPKLRB3.js} +44 -13
- package/dist/{chunk-7F454EE2.js → chunk-ZXDOI6IH.js} +76 -53
- package/dist/{connected-teams-ONC4666A.js → connected-teams-MKIYKOYA.js} +2 -2
- package/dist/{connected-teams-2ANNZCP5.js → connected-teams-RSL4VB3X.js} +2 -2
- package/dist/{coordinator-prompt-RBKUNRPR.js → coordinator-prompt-4P23VVFC.js} +4 -4
- package/dist/{coordinator-prompt-ICF36NUQ.js → coordinator-prompt-LNWHZ64D.js} +4 -4
- package/dist/{global-workspace-667XLBW6.js → global-workspace-BHT4XUAA.js} +5 -5
- package/dist/{global-workspace-S7VLWPWG.js → global-workspace-TMMAVRVW.js} +5 -5
- package/dist/index.cjs +303 -115
- package/dist/index.d.cts +15 -6
- package/dist/index.d.ts +15 -6
- package/dist/index.js +157 -64
- package/dist/mcp/run-stdio.cjs +303 -126
- package/dist/mcp/run-stdio.js +156 -68
- package/dist/{run-ZJKYHXGN.js → run-GPSVV5OH.js} +1 -1
- package/dist/{run-H3IMNOYN.js → run-HZTBWGQR.js} +1 -1
- package/dist/{workspaces-FPJJXXAE.js → workspaces-3GO3EDQG.js} +6 -6
- package/dist/{workspaces-LYIDE2VR.js → workspaces-GFPGDGCS.js} +6 -6
- package/dist/{worktree-5KEQWSAF.js → worktree-3L2G6PCM.js} +2 -2
- package/dist/{worktree-RWGL7FUV.js → worktree-GBLHEFHR.js} +2 -2
- package/package.json +1 -1
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -1554,7 +1554,8 @@ async function run(file, args, opts) {
|
|
|
1554
1554
|
const result = await (0, import_execa.execa)(file, args, {
|
|
1555
1555
|
cwd: opts?.cwd,
|
|
1556
1556
|
env: { ...process.env, ...opts?.env },
|
|
1557
|
-
reject: opts?.reject ?? true
|
|
1557
|
+
reject: opts?.reject ?? true,
|
|
1558
|
+
...opts?.timeoutMs != null ? { timeout: opts.timeoutMs } : {}
|
|
1558
1559
|
});
|
|
1559
1560
|
return {
|
|
1560
1561
|
stdout: result.stdout ?? "",
|
|
@@ -1584,11 +1585,22 @@ async function git(args, cwd, opts) {
|
|
|
1584
1585
|
return run("git", [...prefix, ...args], {
|
|
1585
1586
|
cwd,
|
|
1586
1587
|
reject: opts?.reject,
|
|
1587
|
-
|
|
1588
|
+
timeoutMs: opts?.timeoutMs,
|
|
1589
|
+
// Never block forever on a credential/SSH prompt inside MCP / Electron.
|
|
1590
|
+
env: {
|
|
1591
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
1592
|
+
GIT_ASKPASS: process.env.GIT_ASKPASS || "echo",
|
|
1593
|
+
GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND || "ssh -o BatchMode=yes -o ConnectTimeout=15",
|
|
1594
|
+
...opts?.env
|
|
1595
|
+
}
|
|
1588
1596
|
});
|
|
1589
1597
|
}
|
|
1590
1598
|
async function gh(args, cwd, opts) {
|
|
1591
|
-
return run("gh", args, {
|
|
1599
|
+
return run("gh", args, {
|
|
1600
|
+
cwd,
|
|
1601
|
+
reject: opts?.reject,
|
|
1602
|
+
timeoutMs: opts?.timeoutMs
|
|
1603
|
+
});
|
|
1592
1604
|
}
|
|
1593
1605
|
async function resolveGhAuthToken(cwd) {
|
|
1594
1606
|
const result = await gh(["auth", "token"], cwd, { reject: false });
|
|
@@ -2029,12 +2041,16 @@ async function ensureGhPreferOrigin(cwd) {
|
|
|
2029
2041
|
const hasAlt = Boolean(await slugFromGitRemote(cwd, "upstream")) || Boolean(await slugFromGitRemote(cwd, "github"));
|
|
2030
2042
|
if (!hasAlt) return;
|
|
2031
2043
|
const view = await gh(["repo", "set-default", "--view"], cwd, {
|
|
2032
|
-
reject: false
|
|
2044
|
+
reject: false,
|
|
2045
|
+
timeoutMs: 15e3
|
|
2033
2046
|
});
|
|
2034
2047
|
const current = `${view.stdout}
|
|
2035
2048
|
${view.stderr}`;
|
|
2036
2049
|
if (view.exitCode === 0 && current.includes(originSlug)) return;
|
|
2037
|
-
await gh(["repo", "set-default", "origin"], cwd, {
|
|
2050
|
+
await gh(["repo", "set-default", "origin"], cwd, {
|
|
2051
|
+
reject: false,
|
|
2052
|
+
timeoutMs: 15e3
|
|
2053
|
+
});
|
|
2038
2054
|
}
|
|
2039
2055
|
async function originGhRepoEnv(cwd) {
|
|
2040
2056
|
await ensureGhPreferOrigin(cwd);
|
|
@@ -2580,20 +2596,42 @@ async function createThreadWorktree(opts) {
|
|
|
2580
2596
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
2581
2597
|
}
|
|
2582
2598
|
await ensureGhPreferOrigin(opts.repoPath);
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
await
|
|
2586
|
-
|
|
2599
|
+
let startPoint = null;
|
|
2600
|
+
try {
|
|
2601
|
+
startPoint = await resolveWorktreeStartPoint(opts.repoPath, opts.sourceRef);
|
|
2602
|
+
} catch {
|
|
2603
|
+
startPoint = null;
|
|
2604
|
+
}
|
|
2605
|
+
if (!isLocalPrFetchBranch(opts.sourceRef)) {
|
|
2606
|
+
const fetchTimeoutMs = startPoint ? 12e3 : 45e3;
|
|
2607
|
+
await git(["fetch", "origin", "--prune"], opts.repoPath, {
|
|
2608
|
+
reject: false,
|
|
2609
|
+
timeoutMs: fetchTimeoutMs
|
|
2587
2610
|
});
|
|
2611
|
+
if (!opts.sourceRef.startsWith("origin/") && !opts.sourceRef.startsWith("refs/")) {
|
|
2612
|
+
await git(["fetch", "origin", opts.sourceRef], opts.repoPath, {
|
|
2613
|
+
reject: false,
|
|
2614
|
+
timeoutMs: fetchTimeoutMs
|
|
2615
|
+
});
|
|
2616
|
+
}
|
|
2617
|
+
try {
|
|
2618
|
+
startPoint = await resolveWorktreeStartPoint(
|
|
2619
|
+
opts.repoPath,
|
|
2620
|
+
opts.sourceRef
|
|
2621
|
+
);
|
|
2622
|
+
} catch (err) {
|
|
2623
|
+
if (!startPoint) throw err;
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
if (!startPoint) {
|
|
2627
|
+
throw new Error(
|
|
2628
|
+
`Invalid git reference: ${opts.sourceRef} (and fetch did not resolve it)`
|
|
2629
|
+
);
|
|
2588
2630
|
}
|
|
2589
|
-
const startPoint = await resolveWorktreeStartPoint(
|
|
2590
|
-
opts.repoPath,
|
|
2591
|
-
opts.sourceRef
|
|
2592
|
-
);
|
|
2593
2631
|
const add = await git(
|
|
2594
2632
|
["worktree", "add", "-b", branchName, worktreePath, startPoint],
|
|
2595
2633
|
opts.repoPath,
|
|
2596
|
-
{ reject: false }
|
|
2634
|
+
{ reject: false, timeoutMs: 6e4 }
|
|
2597
2635
|
);
|
|
2598
2636
|
if (add.exitCode !== 0) {
|
|
2599
2637
|
const err = `${add.stderr}
|
|
@@ -2604,7 +2642,7 @@ ${add.stdout}`;
|
|
|
2604
2642
|
const retry = await git(
|
|
2605
2643
|
["worktree", "add", "-b", alt, worktreePath, startPoint],
|
|
2606
2644
|
opts.repoPath,
|
|
2607
|
-
{ reject: false }
|
|
2645
|
+
{ reject: false, timeoutMs: 6e4 }
|
|
2608
2646
|
);
|
|
2609
2647
|
if (retry.exitCode === 0) {
|
|
2610
2648
|
branchName = alt;
|
|
@@ -3270,9 +3308,14 @@ function resolveThreadDefaults(settings = loadAppSettings()) {
|
|
|
3270
3308
|
function resolveNewThreadOptions(overrides = {}, settings = loadAppSettings()) {
|
|
3271
3309
|
const defaults = resolveThreadDefaults(settings);
|
|
3272
3310
|
const effort = overrides.effort === void 0 || overrides.effort === null ? defaults.effort : normalizeThinkingEffort(overrides.effort) ?? defaults.effort;
|
|
3311
|
+
const agent = overrides.agent ?? defaults.agent;
|
|
3312
|
+
let model = overrides.model === void 0 ? defaults.model : overrides.model?.trim() || null;
|
|
3313
|
+
if (model && agent !== "cursor" && /^(default|auto)$/i.test(model.trim())) {
|
|
3314
|
+
model = null;
|
|
3315
|
+
}
|
|
3273
3316
|
return {
|
|
3274
|
-
agent
|
|
3275
|
-
model
|
|
3317
|
+
agent,
|
|
3318
|
+
model,
|
|
3276
3319
|
effort,
|
|
3277
3320
|
fast: overrides.fast === void 0 || overrides.fast === null ? defaults.fast : Boolean(overrides.fast)
|
|
3278
3321
|
};
|
|
@@ -3561,7 +3604,9 @@ function coordinatorTurnReminder(opts) {
|
|
|
3561
3604
|
"- You oversee Sideboard worktree agents. You are not yourself checked out in a project worktree.",
|
|
3562
3605
|
"- This cwd is a synthetic empty home (not a git repo). Emptiness here is expected \u2014 it is not a problem to fix.",
|
|
3563
3606
|
"- Registered workspaces / child threads are the fleet you manage via Sideboard MCP.",
|
|
3564
|
-
`-
|
|
3607
|
+
`- YOUR orchestration thread id is ${opts.parentId}`,
|
|
3608
|
+
`- Always pass parentThreadId="${opts.parentId}" on create_thread (never invent or reuse another uuid).`,
|
|
3609
|
+
`- Or omit parentThreadId \u2014 Sideboard MCP already binds children to ${opts.parentId}.`,
|
|
3565
3610
|
goal ? `- Goal / title: ${goal}` : null,
|
|
3566
3611
|
accountDefaultsPlaybookLine(),
|
|
3567
3612
|
`- For "what's going on": call list_threads (and list_workspaces if needed). Summarize fleet status \u2014 do not ls/git-status this synthetic home.`,
|
|
@@ -3570,10 +3615,33 @@ function coordinatorTurnReminder(opts) {
|
|
|
3570
3615
|
"- When naming threads for the user, link them as `[Title](sideboard://thread/<id>)`."
|
|
3571
3616
|
].filter(Boolean).join("\n");
|
|
3572
3617
|
}
|
|
3573
|
-
function ensureGlobalCoordinatorCwd() {
|
|
3618
|
+
function ensureGlobalCoordinatorCwd(opts) {
|
|
3574
3619
|
const dir = globalAgentCwd();
|
|
3575
|
-
|
|
3620
|
+
try {
|
|
3621
|
+
(0, import_node_fs6.mkdirSync)(dir, { recursive: true });
|
|
3622
|
+
} catch {
|
|
3623
|
+
return dir;
|
|
3624
|
+
}
|
|
3576
3625
|
const reposDir = sideboardReposDir();
|
|
3626
|
+
let orchId = opts?.orchestratorThreadId?.trim() || "";
|
|
3627
|
+
if (!orchId) {
|
|
3628
|
+
try {
|
|
3629
|
+
const existing = (0, import_node_fs6.readFileSync)((0, import_node_path7.join)(dir, "AGENTS.md"), "utf8");
|
|
3630
|
+
const m = existing.match(
|
|
3631
|
+
/YOUR orchestration thread id is `([0-9a-f-]{36})`/i
|
|
3632
|
+
);
|
|
3633
|
+
if (m?.[1]) orchId = m[1];
|
|
3634
|
+
} catch {
|
|
3635
|
+
}
|
|
3636
|
+
}
|
|
3637
|
+
const parentBlock = orchId ? [
|
|
3638
|
+
"",
|
|
3639
|
+
`## This chat's id`,
|
|
3640
|
+
"",
|
|
3641
|
+
`YOUR orchestration thread id is \`${orchId}\`.`,
|
|
3642
|
+
`On every create_thread, pass parentThreadId="${orchId}" \u2014 or omit parentThreadId (Sideboard binds it automatically).`,
|
|
3643
|
+
"Never invent a uuid and never reuse an id from an earlier conversation."
|
|
3644
|
+
] : [];
|
|
3577
3645
|
const body = [
|
|
3578
3646
|
"# Sideboard Orchestration",
|
|
3579
3647
|
"",
|
|
@@ -3583,6 +3651,7 @@ function ensureGlobalCoordinatorCwd() {
|
|
|
3583
3651
|
"Repos from `list_workspaces` and threads from `list_threads` are the fleet you orchestrate.",
|
|
3584
3652
|
'For status questions ("what\'s going on?"), use `list_threads` / `list_workspaces` \u2014 never diagnose this synthetic home as a broken worktree.',
|
|
3585
3653
|
"Bash is fine for inspecting **child worktree** / registered-repo paths, and for greenfield repo setup under the Sideboard repos directory \u2014 not for treating this home as the project.",
|
|
3654
|
+
...parentBlock,
|
|
3586
3655
|
"",
|
|
3587
3656
|
COORDINATOR_TOOL_PLAYBOOK,
|
|
3588
3657
|
"",
|
|
@@ -3590,16 +3659,21 @@ function ensureGlobalCoordinatorCwd() {
|
|
|
3590
3659
|
"",
|
|
3591
3660
|
coordinatorGreenfieldPlaybook(reposDir),
|
|
3592
3661
|
"",
|
|
3593
|
-
"When creating threads, pass `repoPath` from `list_workspaces` (or the path you just registered)
|
|
3662
|
+
"When creating threads, pass `repoPath` from `list_workspaces` (or the path you just registered).",
|
|
3663
|
+
orchId ? `Pass parentThreadId="${orchId}" (or omit it). Never invent another parentThreadId.` : "Pass `parentThreadId` for children (this chat's id from the turn reminder).",
|
|
3594
3664
|
"Omit `agent` / `model` on `create_thread` unless you have a reason to override Account defaults.",
|
|
3665
|
+
"Never pass `agent=codex` when you yourself are Codex \u2014 nested Codex deadlocks on shared ~/.codex locks. Omit agent (Account default) or use cursor/claude.",
|
|
3595
3666
|
"Typical flow (existing): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn.",
|
|
3596
3667
|
"Typical flow (new app): Bash create/clone under repos dir \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn \u2192 draft PR via worktree agent.",
|
|
3597
3668
|
"Always ask worktree agents to open draft PRs (`send_to_thread` + `gh pr create --draft -R <origin>`); never open PRs from the orchestrator."
|
|
3598
3669
|
].join("\n");
|
|
3599
|
-
|
|
3670
|
+
try {
|
|
3671
|
+
(0, import_node_fs6.writeFileSync)((0, import_node_path7.join)(dir, "CLAUDE.md"), `${body}
|
|
3600
3672
|
`, "utf8");
|
|
3601
|
-
|
|
3673
|
+
(0, import_node_fs6.writeFileSync)((0, import_node_path7.join)(dir, "AGENTS.md"), `${body}
|
|
3602
3674
|
`, "utf8");
|
|
3675
|
+
} catch {
|
|
3676
|
+
}
|
|
3603
3677
|
return dir;
|
|
3604
3678
|
}
|
|
3605
3679
|
function coordinatorSystemPrompt(opts) {
|
|
@@ -3619,12 +3693,12 @@ function coordinatorSystemPrompt(opts) {
|
|
|
3619
3693
|
COORDINATOR_TOOL_PLAYBOOK,
|
|
3620
3694
|
accountDefaultsPlaybookLine(),
|
|
3621
3695
|
coordinatorGreenfieldPlaybook(reposDir),
|
|
3622
|
-
"When creating threads, pass the correct repoPath for the target workspace
|
|
3696
|
+
"When creating threads, pass the correct repoPath for the target workspace.",
|
|
3697
|
+
`YOUR orchestration thread id is ${opts.parentId} \u2014 pass parentThreadId="${opts.parentId}" on create_thread, or omit parentThreadId (Sideboard binds it). Never invent a uuid.`,
|
|
3623
3698
|
"Omit agent/model on create_thread unless you need to override Account defaults.",
|
|
3624
3699
|
"Typical flow (existing): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn \u2192 send_to_thread (ask for `gh pr create --draft -R <origin-owner/name>` using the workspace github slug) \u2192 wait_for_turn. Never target upstream. Never open PRs from the orchestrator.",
|
|
3625
3700
|
"Typical flow (new app): Bash under repos dir (clone or gh repo create) \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 draft PR via worktree agent.",
|
|
3626
3701
|
`Goal: ${opts.goal}`,
|
|
3627
|
-
`Parent thread id (pass as parentThreadId when creating children): ${opts.parentId}`,
|
|
3628
3702
|
"Registered workspaces:",
|
|
3629
3703
|
formatWorkspaceInventory(opts.workspaces)
|
|
3630
3704
|
].join("\n");
|
|
@@ -3650,7 +3724,7 @@ var init_coordinator_prompt = __esm({
|
|
|
3650
3724
|
"Workspaces:",
|
|
3651
3725
|
"- add_workspace / remove_workspace \u2014 register or unregister a git repo",
|
|
3652
3726
|
"Worktree threads (chats):",
|
|
3653
|
-
"- create_thread \u2014 create a worktree + chat from branch | pr | ticket; pass repoPath + parentThreadId; omit agent and model to use Sideboard Account defaults (Settings \u2192 Default agent, model & effort)",
|
|
3727
|
+
"- create_thread \u2014 create a worktree + chat from branch | pr | ticket; pass repoPath + parentThreadId; omit agent and model to use Sideboard Account defaults (Settings \u2192 Default agent, model & effort). If you are Codex, do not set agent=codex (nested Codex deadlocks)",
|
|
3654
3728
|
"- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
|
|
3655
3729
|
"- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
|
|
3656
3730
|
"- send_to_thread \u2014 queue a prompt (start/continue a chat turn); pass force_stop: true to interrupt mid-turn / clear stale queued prompts before replacing with a new request",
|
|
@@ -3662,7 +3736,7 @@ var init_coordinator_prompt = __esm({
|
|
|
3662
3736
|
"- list_run_scripts / run_dev_script / stop_dev_script \u2014 start/stop named run scripts",
|
|
3663
3737
|
"Inspect / review / PRs:",
|
|
3664
3738
|
"- get_diff \u2014 compact diff summary",
|
|
3665
|
-
'- 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',
|
|
3739
|
+
'- request_review \u2014 open a Review chat tab on a worktree thread (attaches .sideboard/review.md when present, else local guidelines; sends "Review changes in this workspace."); then wait_for_turn / get_turn_result on the returned id',
|
|
3666
3740
|
"- 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.",
|
|
3667
3741
|
"Human-only (do not attempt): merge, ready-for-review land, purge_thread.",
|
|
3668
3742
|
"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.",
|
|
@@ -4410,13 +4484,6 @@ function mcpAllowTools(servers) {
|
|
|
4410
4484
|
}
|
|
4411
4485
|
return out;
|
|
4412
4486
|
}
|
|
4413
|
-
function mcpAuthWarnings(servers) {
|
|
4414
|
-
const needing = servers.filter((s) => s.needsAuth).map((s) => s.name);
|
|
4415
|
-
if (needing.length === 0) return [];
|
|
4416
|
-
return [
|
|
4417
|
-
`MCP needs login: ${needing.join(", ")}. Run: claude mcp login "<name>"`
|
|
4418
|
-
];
|
|
4419
|
-
}
|
|
4420
4487
|
var init_claude_mcp = __esm({
|
|
4421
4488
|
"src/agents/claude-mcp.ts"() {
|
|
4422
4489
|
"use strict";
|
|
@@ -4558,7 +4625,16 @@ async function resolveSideboardMcpServer() {
|
|
|
4558
4625
|
async function buildInjectedMcpServers(opts) {
|
|
4559
4626
|
const servers = [];
|
|
4560
4627
|
if (opts.includeSideboard) {
|
|
4561
|
-
|
|
4628
|
+
const sideboard = await resolveSideboardMcpServer();
|
|
4629
|
+
sideboard.env = {
|
|
4630
|
+
...sideboard.env ?? {},
|
|
4631
|
+
SIDEBOARD_APP_DATA: appDataDir()
|
|
4632
|
+
};
|
|
4633
|
+
const orchId = opts.orchestratorThreadId?.trim();
|
|
4634
|
+
if (orchId) {
|
|
4635
|
+
sideboard.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID = orchId;
|
|
4636
|
+
}
|
|
4637
|
+
servers.push(sideboard);
|
|
4562
4638
|
}
|
|
4563
4639
|
if (opts.includeBrightsy && isBrightsyConnected()) {
|
|
4564
4640
|
const cmd = await resolveBrightsyMcpCommand();
|
|
@@ -4602,6 +4678,8 @@ function toCodexMcpConfigArgs(servers) {
|
|
|
4602
4678
|
}
|
|
4603
4679
|
}
|
|
4604
4680
|
args.push("-c", `${prefix}.default_tools_approval_mode=${JSON.stringify("approve")}`);
|
|
4681
|
+
args.push("-c", `${prefix}.tool_timeout_sec=300`);
|
|
4682
|
+
args.push("-c", `${prefix}.startup_timeout_sec=30`);
|
|
4605
4683
|
}
|
|
4606
4684
|
return args;
|
|
4607
4685
|
}
|
|
@@ -4644,6 +4722,7 @@ var init_injected_mcp = __esm({
|
|
|
4644
4722
|
init_run();
|
|
4645
4723
|
init_config();
|
|
4646
4724
|
init_connected_teams();
|
|
4725
|
+
init_paths();
|
|
4647
4726
|
init_node_launch();
|
|
4648
4727
|
import_meta = {};
|
|
4649
4728
|
SIDEBOARD_MCP_ALLOWED_TOOLS = [
|
|
@@ -4663,6 +4742,16 @@ var init_injected_mcp = __esm({
|
|
|
4663
4742
|
|
|
4664
4743
|
// src/agents/types.ts
|
|
4665
4744
|
function permissionMode(thread) {
|
|
4745
|
+
if (thread.sourceType === "orchestration") {
|
|
4746
|
+
return {
|
|
4747
|
+
claude: "acceptEdits",
|
|
4748
|
+
opencodePermission: JSON.stringify({
|
|
4749
|
+
edit: "allow",
|
|
4750
|
+
bash: { "*": "allow", "rm -rf *": "deny" }
|
|
4751
|
+
}),
|
|
4752
|
+
codexSandbox: "danger-full-access"
|
|
4753
|
+
};
|
|
4754
|
+
}
|
|
4666
4755
|
if (thread.planMode) {
|
|
4667
4756
|
return {
|
|
4668
4757
|
claude: "plan",
|
|
@@ -4858,18 +4947,17 @@ var init_claude = __esm({
|
|
|
4858
4947
|
};
|
|
4859
4948
|
}
|
|
4860
4949
|
}
|
|
4861
|
-
const auth = await run(claude, ["auth", "status"], {
|
|
4950
|
+
const auth = await run(claude, ["auth", "status"], {
|
|
4951
|
+
reject: false,
|
|
4952
|
+
timeoutMs: 5e3
|
|
4953
|
+
});
|
|
4862
4954
|
const authenticated = auth.exitCode === 0;
|
|
4863
|
-
const servers = await loadMcpServers();
|
|
4864
|
-
const linearMcp = servers.some(
|
|
4865
|
-
(s) => s.connected && /linear/i.test(s.name)
|
|
4866
|
-
);
|
|
4867
4955
|
return {
|
|
4868
4956
|
agent: "claude",
|
|
4869
4957
|
installed: true,
|
|
4870
4958
|
authenticated,
|
|
4871
|
-
linearMcp,
|
|
4872
|
-
warnings:
|
|
4959
|
+
linearMcp: false,
|
|
4960
|
+
warnings: [],
|
|
4873
4961
|
reason: authenticated ? void 0 : "claude auth status failed \u2014 run `claude auth login`"
|
|
4874
4962
|
};
|
|
4875
4963
|
},
|
|
@@ -4890,7 +4978,8 @@ var init_claude = __esm({
|
|
|
4890
4978
|
const isOrchestrator = isOrchestratorThread2(thread);
|
|
4891
4979
|
const injectedServers = await buildInjectedMcpServers({
|
|
4892
4980
|
includeSideboard: true,
|
|
4893
|
-
includeBrightsy: isBrightsyConnected()
|
|
4981
|
+
includeBrightsy: isBrightsyConnected(),
|
|
4982
|
+
orchestratorThreadId: isOrchestrator ? thread.id : null
|
|
4894
4983
|
});
|
|
4895
4984
|
const injectedBrightsyNames = injectedServers.filter((s) => s.name === "brightsy" || s.name.startsWith("brightsy_")).map((s) => s.name);
|
|
4896
4985
|
const chromeOn = claudeChromeEnabled();
|
|
@@ -5136,6 +5225,15 @@ function asRecord(value) {
|
|
|
5136
5225
|
}
|
|
5137
5226
|
return void 0;
|
|
5138
5227
|
}
|
|
5228
|
+
function codexLooksAuthenticated() {
|
|
5229
|
+
const authPath = (0, import_node_path11.join)((0, import_node_os7.homedir)(), ".codex", "auth.json");
|
|
5230
|
+
if (!(0, import_node_fs11.existsSync)(authPath)) return false;
|
|
5231
|
+
try {
|
|
5232
|
+
return (0, import_node_fs11.statSync)(authPath).size > 2;
|
|
5233
|
+
} catch {
|
|
5234
|
+
return false;
|
|
5235
|
+
}
|
|
5236
|
+
}
|
|
5139
5237
|
var import_node_fs11, import_node_os7, import_node_path11, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
|
|
5140
5238
|
var init_codex = __esm({
|
|
5141
5239
|
"src/agents/codex.ts"() {
|
|
@@ -5161,7 +5259,7 @@ var init_codex = __esm({
|
|
|
5161
5259
|
codexAdapter = {
|
|
5162
5260
|
kind: "codex",
|
|
5163
5261
|
async detect() {
|
|
5164
|
-
const which = await run("which", ["codex"], { reject: false });
|
|
5262
|
+
const which = await run("which", ["codex"], { reject: false, timeoutMs: 3e3 });
|
|
5165
5263
|
if (which.exitCode !== 0) {
|
|
5166
5264
|
return {
|
|
5167
5265
|
agent: "codex",
|
|
@@ -5172,10 +5270,8 @@ var init_codex = __esm({
|
|
|
5172
5270
|
reason: "codex CLI not found on PATH"
|
|
5173
5271
|
};
|
|
5174
5272
|
}
|
|
5175
|
-
const
|
|
5176
|
-
const
|
|
5177
|
-
const mcp = await run("codex", ["mcp", "list", "--json"], { reject: false });
|
|
5178
|
-
const linearMcp = /linear/i.test(mcp.stdout + mcp.stderr);
|
|
5273
|
+
const authenticated = codexLooksAuthenticated();
|
|
5274
|
+
const linearMcp = false;
|
|
5179
5275
|
const warnings = [];
|
|
5180
5276
|
if (!codexConfigHasNetworkAccess()) {
|
|
5181
5277
|
warnings.push(
|
|
@@ -5188,7 +5284,7 @@ var init_codex = __esm({
|
|
|
5188
5284
|
authenticated,
|
|
5189
5285
|
linearMcp,
|
|
5190
5286
|
warnings,
|
|
5191
|
-
reason: authenticated ? void 0 : "
|
|
5287
|
+
reason: authenticated ? void 0 : "Codex auth not found \u2014 run `codex login` (expected ~/.codex/auth.json)"
|
|
5192
5288
|
};
|
|
5193
5289
|
},
|
|
5194
5290
|
async buildTurn(thread, input) {
|
|
@@ -5206,23 +5302,26 @@ var init_codex = __esm({
|
|
|
5206
5302
|
const model = thread.model?.trim();
|
|
5207
5303
|
const injected = await buildInjectedMcpServers({
|
|
5208
5304
|
includeSideboard: true,
|
|
5209
|
-
includeBrightsy: isBrightsyConnected()
|
|
5305
|
+
includeBrightsy: isBrightsyConnected(),
|
|
5306
|
+
orchestratorThreadId: thread.sourceType === "orchestration" ? thread.id : null
|
|
5210
5307
|
});
|
|
5211
5308
|
const mcpOverrides = toCodexMcpConfigArgs(injected);
|
|
5212
|
-
const
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5309
|
+
const execOpts = [
|
|
5310
|
+
// Global orchestration cwd is not a git repo; without this Codex ≥0.147
|
|
5311
|
+
// refuses to start ("Not inside a trusted directory").
|
|
5312
|
+
"--skip-git-repo-check",
|
|
5216
5313
|
"--cd",
|
|
5217
5314
|
thread.worktreePath,
|
|
5218
5315
|
"--json",
|
|
5219
5316
|
"--sandbox",
|
|
5220
5317
|
mode.codexSandbox,
|
|
5221
|
-
|
|
5222
|
-
"
|
|
5318
|
+
// `codex exec` rejects `--ask-for-approval` (global-only on newer CLIs).
|
|
5319
|
+
"-c",
|
|
5320
|
+
'approval_policy="never"',
|
|
5223
5321
|
...model ? ["--model", model] : [],
|
|
5224
5322
|
...mcpOverrides
|
|
5225
5323
|
];
|
|
5324
|
+
const args = sessionId ? ["exec", ...execOpts, "resume", sessionId, promptArg] : ["exec", ...execOpts, promptArg];
|
|
5226
5325
|
return {
|
|
5227
5326
|
file: "codex",
|
|
5228
5327
|
args,
|
|
@@ -5324,7 +5423,7 @@ var init_codex = __esm({
|
|
|
5324
5423
|
if (sessionId) {
|
|
5325
5424
|
return {
|
|
5326
5425
|
file: "codex",
|
|
5327
|
-
args: ["exec", "
|
|
5426
|
+
args: ["exec", "--cd", thread.worktreePath, "resume", sessionId],
|
|
5328
5427
|
cwd: thread.worktreePath
|
|
5329
5428
|
};
|
|
5330
5429
|
}
|
|
@@ -5340,12 +5439,12 @@ var init_codex = __esm({
|
|
|
5340
5439
|
"codex",
|
|
5341
5440
|
[
|
|
5342
5441
|
"exec",
|
|
5343
|
-
prompt,
|
|
5344
5442
|
"--json",
|
|
5345
5443
|
"--sandbox",
|
|
5346
5444
|
"read-only",
|
|
5347
|
-
"
|
|
5348
|
-
"never"
|
|
5445
|
+
"-c",
|
|
5446
|
+
'approval_policy="never"',
|
|
5447
|
+
prompt
|
|
5349
5448
|
],
|
|
5350
5449
|
{ reject: false }
|
|
5351
5450
|
);
|
|
@@ -5642,26 +5741,13 @@ var init_cursor = __esm({
|
|
|
5642
5741
|
reason: "CURSOR_API_KEY not set \u2014 add it in Settings \u2192 Agents \u2192 Cursor, or Settings \u2192 Environment"
|
|
5643
5742
|
};
|
|
5644
5743
|
}
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
warnings: []
|
|
5653
|
-
};
|
|
5654
|
-
} catch (err) {
|
|
5655
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
5656
|
-
return {
|
|
5657
|
-
agent: "cursor",
|
|
5658
|
-
installed: true,
|
|
5659
|
-
authenticated: false,
|
|
5660
|
-
linearMcp: false,
|
|
5661
|
-
warnings: [],
|
|
5662
|
-
reason: `Cursor API auth failed: ${message}`
|
|
5663
|
-
};
|
|
5664
|
-
}
|
|
5744
|
+
return {
|
|
5745
|
+
agent: "cursor",
|
|
5746
|
+
installed: true,
|
|
5747
|
+
authenticated: true,
|
|
5748
|
+
linearMcp: false,
|
|
5749
|
+
warnings: []
|
|
5750
|
+
};
|
|
5665
5751
|
},
|
|
5666
5752
|
async buildTurn(thread, input) {
|
|
5667
5753
|
const prompt = flattenTurnInput(input);
|
|
@@ -5669,7 +5755,8 @@ var init_cursor = __esm({
|
|
|
5669
5755
|
const apiKey = resolveCursorApiKey() || void 0;
|
|
5670
5756
|
const injected = await buildInjectedMcpServers({
|
|
5671
5757
|
includeSideboard: true,
|
|
5672
|
-
includeBrightsy: isBrightsyConnected()
|
|
5758
|
+
includeBrightsy: isBrightsyConnected(),
|
|
5759
|
+
orchestratorThreadId: thread.sourceType === "orchestration" ? thread.id : null
|
|
5673
5760
|
});
|
|
5674
5761
|
const mcpServers = toCursorMcpServers(injected);
|
|
5675
5762
|
const req = {
|
|
@@ -5838,7 +5925,8 @@ var init_opencode = __esm({
|
|
|
5838
5925
|
}
|
|
5839
5926
|
const injected = await buildInjectedMcpServers({
|
|
5840
5927
|
includeSideboard: true,
|
|
5841
|
-
includeBrightsy: isBrightsyConnected()
|
|
5928
|
+
includeBrightsy: isBrightsyConnected(),
|
|
5929
|
+
orchestratorThreadId: thread.sourceType === "orchestration" ? thread.id : null
|
|
5842
5930
|
});
|
|
5843
5931
|
const mcpContent = injected.length > 0 ? toOpencodeMcpConfigContent(injected) : null;
|
|
5844
5932
|
return {
|
|
@@ -6993,7 +7081,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
6993
7081
|
const { isGlobalThread: isGlobalThread2 } = await Promise.resolve().then(() => (init_global_workspace(), global_workspace_exports));
|
|
6994
7082
|
if (isGlobalThread2(thread)) {
|
|
6995
7083
|
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
|
|
6996
|
-
ensureGlobalCoordinatorCwd2(
|
|
7084
|
+
ensureGlobalCoordinatorCwd2(
|
|
7085
|
+
isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
|
|
7086
|
+
);
|
|
6997
7087
|
}
|
|
6998
7088
|
if (isOrchestratorThread(thread)) {
|
|
6999
7089
|
assertOrchestratorCapableAgent(thread.agent);
|
|
@@ -7709,13 +7799,21 @@ var import_node_fs18 = require("fs");
|
|
|
7709
7799
|
|
|
7710
7800
|
// src/detect/detect.ts
|
|
7711
7801
|
init_agents();
|
|
7712
|
-
|
|
7713
|
-
ensureAgentPath();
|
|
7714
|
-
return Promise.all(allAdapters().map((a) => a.detect()));
|
|
7715
|
-
}
|
|
7802
|
+
var REQUIRE_AGENT_TIMEOUT_MS = 8e3;
|
|
7716
7803
|
async function requireAgent(agent, opts) {
|
|
7717
|
-
|
|
7718
|
-
|
|
7804
|
+
ensureAgentPath();
|
|
7805
|
+
const status = await Promise.race([
|
|
7806
|
+
getAdapter(agent).detect(),
|
|
7807
|
+
new Promise((_, reject) => {
|
|
7808
|
+
setTimeout(() => {
|
|
7809
|
+
reject(
|
|
7810
|
+
new Error(
|
|
7811
|
+
`${agent} detect timed out after ${REQUIRE_AGENT_TIMEOUT_MS / 1e3}s`
|
|
7812
|
+
)
|
|
7813
|
+
);
|
|
7814
|
+
}, REQUIRE_AGENT_TIMEOUT_MS);
|
|
7815
|
+
})
|
|
7816
|
+
]);
|
|
7719
7817
|
if (!status.installed || !status.authenticated) {
|
|
7720
7818
|
throw new Error(status.reason ?? `${agent} is not available`);
|
|
7721
7819
|
}
|
|
@@ -8333,7 +8431,7 @@ var REPO_REVIEW_NAME = "review.md";
|
|
|
8333
8431
|
var REVIEW_REQUEST_PATH = `${ATTACHMENTS_DIR}/Review request.md`;
|
|
8334
8432
|
var LEGACY_REVIEW_REQUEST_PATH = `${LEGACY_ATTACHMENTS_DIR}/Review request.md`;
|
|
8335
8433
|
var REVIEW_REQUEST_NAME = "Review request.md";
|
|
8336
|
-
var REVIEW_REQUEST_PREFILL = "Review.";
|
|
8434
|
+
var REVIEW_REQUEST_PREFILL = "Review changes in this workspace.";
|
|
8337
8435
|
var LEGACY_REVIEW_TEMPLATE_MARKERS = [
|
|
8338
8436
|
"You are acting as a reviewer for a proposed code change made by another engineer.",
|
|
8339
8437
|
"HOW MANY FINDINGS TO RETURN:"
|
|
@@ -11029,7 +11127,9 @@ var Orchestrator = class {
|
|
|
11029
11127
|
}
|
|
11030
11128
|
let coordinatorDirective = null;
|
|
11031
11129
|
if (isOrchestration) {
|
|
11032
|
-
if (isGlobalThread(fresh))
|
|
11130
|
+
if (isGlobalThread(fresh)) {
|
|
11131
|
+
ensureGlobalCoordinatorCwd({ orchestratorThreadId: fresh.id });
|
|
11132
|
+
}
|
|
11033
11133
|
if (!fresh.sessionId) {
|
|
11034
11134
|
const inventory = await enrichWorkspacesWithGithub(this.listWorkspaces());
|
|
11035
11135
|
coordinatorDirective = coordinatorSystemPrompt({
|
|
@@ -12111,6 +12211,24 @@ function mcpArchiveBlockedReason(thread) {
|
|
|
12111
12211
|
|
|
12112
12212
|
// src/mcp/server.ts
|
|
12113
12213
|
var MAX_ORCH_THREADS = 5;
|
|
12214
|
+
var CREATE_THREAD_TIMEOUT_MS = 9e4;
|
|
12215
|
+
function withTimeout(promise, ms, label) {
|
|
12216
|
+
return new Promise((resolve, reject) => {
|
|
12217
|
+
const timer = setTimeout(() => {
|
|
12218
|
+
reject(new Error(`${label} timed out after ${Math.round(ms / 1e3)}s`));
|
|
12219
|
+
}, ms);
|
|
12220
|
+
promise.then(
|
|
12221
|
+
(value) => {
|
|
12222
|
+
clearTimeout(timer);
|
|
12223
|
+
resolve(value);
|
|
12224
|
+
},
|
|
12225
|
+
(err) => {
|
|
12226
|
+
clearTimeout(timer);
|
|
12227
|
+
reject(err);
|
|
12228
|
+
}
|
|
12229
|
+
);
|
|
12230
|
+
});
|
|
12231
|
+
}
|
|
12114
12232
|
async function startMcpServer() {
|
|
12115
12233
|
const orch = getOrchestrator();
|
|
12116
12234
|
try {
|
|
@@ -12118,7 +12236,14 @@ async function startMcpServer() {
|
|
|
12118
12236
|
orch.setMaxConcurrent(maxConcurrentAgents2());
|
|
12119
12237
|
} catch {
|
|
12120
12238
|
}
|
|
12121
|
-
|
|
12239
|
+
try {
|
|
12240
|
+
await orch.reconcile(void 0, { reclaimStaleTurns: false, drainQueues: false });
|
|
12241
|
+
} catch (err) {
|
|
12242
|
+
console.error(
|
|
12243
|
+
"[sideboard-mcp] reconcile on boot failed (continuing):",
|
|
12244
|
+
err instanceof Error ? err.message : err
|
|
12245
|
+
);
|
|
12246
|
+
}
|
|
12122
12247
|
const server = new import_mcp.McpServer({
|
|
12123
12248
|
name: "sideboard",
|
|
12124
12249
|
version: "0.1.0"
|
|
@@ -12323,7 +12448,7 @@ async function startMcpServer() {
|
|
|
12323
12448
|
const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
|
|
12324
12449
|
server.tool(
|
|
12325
12450
|
"create_thread",
|
|
12326
|
-
`Create a new worktree thread (chat) from branch, pr, or ticket. Pass repoPath from list_workspaces
|
|
12451
|
+
`Create a new worktree thread (chat) from branch, pr, or ticket. Pass repoPath from list_workspaces. From an orchestration chat, omit parentThreadId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Prefer omitting agent/model so Sideboard applies ${accountDefaultsHint}. Then use send_to_thread to chat.`,
|
|
12327
12452
|
{
|
|
12328
12453
|
sourceType: import_zod.z.enum(["branch", "pr", "ticket"]),
|
|
12329
12454
|
sourceRef: import_zod.z.string(),
|
|
@@ -12333,11 +12458,31 @@ async function startMcpServer() {
|
|
|
12333
12458
|
),
|
|
12334
12459
|
repoPath: import_zod.z.string(),
|
|
12335
12460
|
title: import_zod.z.string().optional(),
|
|
12336
|
-
parentThreadId: import_zod.z.string().optional()
|
|
12461
|
+
parentThreadId: import_zod.z.string().optional().describe(
|
|
12462
|
+
"Orchestration: omit (preferred) or pass YOUR chat id from the turn reminder / AGENTS.md. Do not invent uuids."
|
|
12463
|
+
)
|
|
12337
12464
|
},
|
|
12338
12465
|
async (args) => {
|
|
12339
|
-
|
|
12340
|
-
|
|
12466
|
+
const envParentId = process.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID?.trim() || "";
|
|
12467
|
+
let parentId = args.parentThreadId?.trim() || "";
|
|
12468
|
+
let parent = parentId ? orch.getThread(parentId) : null;
|
|
12469
|
+
let parentCorrectedFrom;
|
|
12470
|
+
if (envParentId) {
|
|
12471
|
+
const envParent = orch.getThread(envParentId);
|
|
12472
|
+
if (envParent) {
|
|
12473
|
+
if (parentId && parentId !== envParentId) parentCorrectedFrom = parentId;
|
|
12474
|
+
else if (!parentId) parentCorrectedFrom = void 0;
|
|
12475
|
+
parentId = envParentId;
|
|
12476
|
+
parent = envParent;
|
|
12477
|
+
}
|
|
12478
|
+
}
|
|
12479
|
+
if (parentId && !parent) {
|
|
12480
|
+
parentCorrectedFrom = parentId;
|
|
12481
|
+
parentId = "";
|
|
12482
|
+
parent = null;
|
|
12483
|
+
}
|
|
12484
|
+
if (parentId) {
|
|
12485
|
+
const children = orch.getThreads(true).filter((t) => t.parentThreadId === parentId);
|
|
12341
12486
|
if (children.length >= MAX_ORCH_THREADS) {
|
|
12342
12487
|
return {
|
|
12343
12488
|
content: [
|
|
@@ -12350,38 +12495,70 @@ async function startMcpServer() {
|
|
|
12350
12495
|
};
|
|
12351
12496
|
}
|
|
12352
12497
|
}
|
|
12498
|
+
let agentArg = args.agent;
|
|
12499
|
+
let agentCoercedFrom;
|
|
12500
|
+
const resolvedProbe = resolveNewThreadOptions2({ agent: agentArg }).agent;
|
|
12501
|
+
if (resolvedProbe === "codex") {
|
|
12502
|
+
agentCoercedFrom = agentArg ?? "codex";
|
|
12503
|
+
const accountAgent = resolveNewThreadOptions2({}).agent;
|
|
12504
|
+
agentArg = accountAgent !== "codex" ? accountAgent : "cursor";
|
|
12505
|
+
}
|
|
12353
12506
|
const opts = resolveNewThreadOptions2({
|
|
12354
|
-
agent:
|
|
12507
|
+
agent: agentArg,
|
|
12355
12508
|
model: args.model
|
|
12356
12509
|
});
|
|
12357
|
-
|
|
12358
|
-
|
|
12359
|
-
|
|
12360
|
-
|
|
12361
|
-
|
|
12362
|
-
|
|
12363
|
-
|
|
12364
|
-
|
|
12365
|
-
|
|
12366
|
-
|
|
12367
|
-
|
|
12368
|
-
|
|
12369
|
-
|
|
12370
|
-
|
|
12371
|
-
|
|
12372
|
-
|
|
12373
|
-
|
|
12374
|
-
|
|
12375
|
-
|
|
12376
|
-
|
|
12377
|
-
|
|
12378
|
-
|
|
12379
|
-
|
|
12380
|
-
|
|
12381
|
-
|
|
12382
|
-
|
|
12383
|
-
|
|
12384
|
-
|
|
12510
|
+
try {
|
|
12511
|
+
const thread = await withTimeout(
|
|
12512
|
+
orch.createThread({
|
|
12513
|
+
sourceType: args.sourceType,
|
|
12514
|
+
sourceRef: args.sourceRef,
|
|
12515
|
+
agent: opts.agent,
|
|
12516
|
+
model: opts.model,
|
|
12517
|
+
effort: opts.effort,
|
|
12518
|
+
fast: opts.fast,
|
|
12519
|
+
repoPath: args.repoPath,
|
|
12520
|
+
title: args.title,
|
|
12521
|
+
parentThreadId: parentId || null
|
|
12522
|
+
}),
|
|
12523
|
+
CREATE_THREAD_TIMEOUT_MS,
|
|
12524
|
+
"create_thread"
|
|
12525
|
+
);
|
|
12526
|
+
const parentNote = parentCorrectedFrom ? parentId ? `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; nested under ${parentId}` : `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; created without parent` : void 0;
|
|
12527
|
+
return {
|
|
12528
|
+
content: [
|
|
12529
|
+
{
|
|
12530
|
+
type: "text",
|
|
12531
|
+
text: JSON.stringify({
|
|
12532
|
+
id: thread.id,
|
|
12533
|
+
title: thread.title,
|
|
12534
|
+
branchName: thread.branchName,
|
|
12535
|
+
worktreePath: thread.worktreePath,
|
|
12536
|
+
agent: thread.agent,
|
|
12537
|
+
model: thread.model,
|
|
12538
|
+
status: thread.status,
|
|
12539
|
+
link: `sideboard://thread/${thread.id}`,
|
|
12540
|
+
parentThreadId: thread.parentThreadId,
|
|
12541
|
+
...agentCoercedFrom ? {
|
|
12542
|
+
agentCoercedFrom,
|
|
12543
|
+
note: `Avoid nested Codex under a Codex orchestrator \u2014 used Account default agent=${thread.agent}`
|
|
12544
|
+
} : {},
|
|
12545
|
+
...parentCorrectedFrom ? { parentCorrectedFrom, parentNote } : {}
|
|
12546
|
+
})
|
|
12547
|
+
}
|
|
12548
|
+
]
|
|
12549
|
+
};
|
|
12550
|
+
} catch (err) {
|
|
12551
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
12552
|
+
return {
|
|
12553
|
+
content: [
|
|
12554
|
+
{
|
|
12555
|
+
type: "text",
|
|
12556
|
+
text: `create_thread failed: ${message}`
|
|
12557
|
+
}
|
|
12558
|
+
],
|
|
12559
|
+
isError: true
|
|
12560
|
+
};
|
|
12561
|
+
}
|
|
12385
12562
|
}
|
|
12386
12563
|
);
|
|
12387
12564
|
server.tool(
|
|
@@ -12562,7 +12739,7 @@ async function startMcpServer() {
|
|
|
12562
12739
|
);
|
|
12563
12740
|
server.tool(
|
|
12564
12741
|
"request_review",
|
|
12565
|
-
'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.',
|
|
12742
|
+
'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 changes in this workspace." 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.',
|
|
12566
12743
|
{ ref: import_zod.z.string().describe("Worktree thread id/ref to review") },
|
|
12567
12744
|
async ({ ref }) => {
|
|
12568
12745
|
try {
|