@sideboard-ai/core 0.1.81 → 0.1.84
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 +106 -53
- package/dist/agents/cursor-runner.js +96 -55
- package/dist/{agents-UQ7D6U6L.js → agents-JFXM66QA.js} +7 -6
- package/dist/{agents-EBKJ55PN.js → agents-OPTHS4IX.js} +5 -5
- package/dist/{app-settings-6IOQYGBK.js → app-settings-K6RFCRF6.js} +2 -1
- package/dist/{app-settings-NILNWNNQ.js → app-settings-PEXK5VEX.js} +1 -1
- package/dist/chunk-5KLC2MWZ.js +40 -0
- package/dist/{chunk-XKNBSYA7.js → chunk-AY53MPDE.js} +39 -1
- package/dist/{chunk-4AVU4QXO.js → chunk-BBQ6HXKS.js} +67 -17
- package/dist/{chunk-SEOICVGB.js → chunk-CBJSPTBG.js} +30 -6
- package/dist/{chunk-FUUVPN4A.js → chunk-CKBIQ54F.js} +78 -49
- package/dist/{chunk-IFPN6TER.js → chunk-I3FRXL7J.js} +4 -1
- package/dist/{chunk-CQBQWX73.js → chunk-JPHG2KCC.js} +8 -3
- package/dist/{chunk-4HJK57XU.js → chunk-NW7MEJHO.js} +8 -3
- package/dist/{chunk-K553XK7M.js → chunk-ODZ2ZOA4.js} +2 -2
- package/dist/{chunk-6F2TQFJE.js → chunk-OIEFHOP7.js} +3 -3
- package/dist/{chunk-XNECBC6T.js → chunk-R753UFSX.js} +39 -11
- package/dist/{chunk-TDJ43HUD.js → chunk-UN3LVQB2.js} +2 -2
- package/dist/{chunk-P5VDPGAN.js → chunk-WJ5TINR6.js} +3 -3
- package/dist/{chunk-YVVXWWCC.js → chunk-XW47PL6A.js} +81 -49
- package/dist/{coordinator-prompt-NYNEFKIV.js → coordinator-prompt-DOIOSLUN.js} +3 -3
- package/dist/{coordinator-prompt-JQF72JKX.js → coordinator-prompt-RCTIIZ6C.js} +4 -3
- package/dist/{global-workspace-NUMUJRWG.js → global-workspace-33BIG7KK.js} +4 -4
- package/dist/{global-workspace-DZM4ZFGU.js → global-workspace-73OAKD3C.js} +5 -4
- package/dist/index.cjs +235 -88
- package/dist/index.d.cts +36 -9
- package/dist/index.d.ts +36 -9
- package/dist/index.js +69 -45
- package/dist/mcp/run-stdio.cjs +233 -88
- package/dist/mcp/run-stdio.js +60 -43
- package/dist/{workspaces-QLRCOXAY.js → workspaces-SRITISKA.js} +6 -5
- package/dist/{workspaces-SUU2GO3A.js → workspaces-WDLY34MX.js} +5 -5
- package/dist/{worktree-5VLLFI5W.js → worktree-SGZVAWOQ.js} +3 -2
- package/dist/{worktree-UNSOCYZU.js → worktree-TUAO74SI.js} +2 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -385,6 +385,41 @@ var init_paths = __esm({
|
|
|
385
385
|
}
|
|
386
386
|
});
|
|
387
387
|
|
|
388
|
+
// src/hook/nested-electron-env.ts
|
|
389
|
+
function isNestedElectronEnvKey(key) {
|
|
390
|
+
return NESTED_ELECTRON_ENV_PREFIXES.some((prefix) => key.startsWith(prefix));
|
|
391
|
+
}
|
|
392
|
+
function stripNestedElectronEnv(env) {
|
|
393
|
+
const out = { ...env };
|
|
394
|
+
for (const key of Object.keys(out)) {
|
|
395
|
+
if (isNestedElectronEnvKey(key)) delete out[key];
|
|
396
|
+
}
|
|
397
|
+
return out;
|
|
398
|
+
}
|
|
399
|
+
function wrapElectronAsNodeLaunch(file, args) {
|
|
400
|
+
if (process.platform === "win32") return { file, args };
|
|
401
|
+
return {
|
|
402
|
+
file: "/bin/sh",
|
|
403
|
+
args: ["-c", STRIP_NESTED_ELECTRON_THEN_EXEC, "sh", file, ...args]
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
function isStrippedElectronLaunch(command, args) {
|
|
407
|
+
return command === "/bin/sh" && Boolean(args?.[1]?.includes("ELECTRON_RUN_AS_NODE") && args[1].includes("unset"));
|
|
408
|
+
}
|
|
409
|
+
var NESTED_ELECTRON_ENV_PREFIXES, STRIP_NESTED_ELECTRON_THEN_EXEC;
|
|
410
|
+
var init_nested_electron_env = __esm({
|
|
411
|
+
"src/hook/nested-electron-env.ts"() {
|
|
412
|
+
"use strict";
|
|
413
|
+
NESTED_ELECTRON_ENV_PREFIXES = ["ELECTRON_", "CHROME_"];
|
|
414
|
+
STRIP_NESTED_ELECTRON_THEN_EXEC = [
|
|
415
|
+
"vars=`printenv | awk -F= '/^(ELECTRON_|CHROME_)/{print $1}'`",
|
|
416
|
+
'[ -n "$vars" ] && unset $vars',
|
|
417
|
+
"export ELECTRON_RUN_AS_NODE=1",
|
|
418
|
+
'exec "$@"'
|
|
419
|
+
].join("; ");
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
|
|
388
423
|
// src/store/private-file.ts
|
|
389
424
|
function writePrivateFile(path2, contents) {
|
|
390
425
|
(0, import_node_fs3.mkdirSync)((0, import_node_path4.dirname)(path2), { recursive: true });
|
|
@@ -1499,7 +1534,7 @@ function applyAppEnvironment(target = process.env, settings = loadAppSettings())
|
|
|
1499
1534
|
}
|
|
1500
1535
|
function childEnvWithAppSettings(extra) {
|
|
1501
1536
|
const settings = loadAppSettings();
|
|
1502
|
-
const env = { ...process.env };
|
|
1537
|
+
const env = stripNestedElectronEnv({ ...process.env });
|
|
1503
1538
|
applyAppEnvironment(env, settings);
|
|
1504
1539
|
if (extra) {
|
|
1505
1540
|
for (const [k, v] of Object.entries(extra)) {
|
|
@@ -1520,6 +1555,7 @@ var init_app_settings = __esm({
|
|
|
1520
1555
|
import_node_os3 = require("os");
|
|
1521
1556
|
import_node_path6 = require("path");
|
|
1522
1557
|
init_thinking_effort();
|
|
1558
|
+
init_nested_electron_env();
|
|
1523
1559
|
init_paths();
|
|
1524
1560
|
init_private_file();
|
|
1525
1561
|
init_secret_vault();
|
|
@@ -2852,11 +2888,25 @@ function formatGhLandError(raw, opts) {
|
|
|
2852
2888
|
}
|
|
2853
2889
|
return detail || "Failed to create or update pull request";
|
|
2854
2890
|
}
|
|
2891
|
+
function isPrNotMergeableError(text3) {
|
|
2892
|
+
return /not mergeable|cannot be cleanly created|cannot merge cleanly|Merge conflict|\bCONFLICTING\b|must be (updated|rebased)|branch is out of date|needs? to be (updated|rebased)|Resolve conflicts or update the branch/i.test(
|
|
2893
|
+
text3
|
|
2894
|
+
);
|
|
2895
|
+
}
|
|
2896
|
+
function formatMergePrError(raw) {
|
|
2897
|
+
const trimmed = raw.trim();
|
|
2898
|
+
if (!trimmed) return "gh pr merge failed";
|
|
2899
|
+
if (isPrNotMergeableError(trimmed)) {
|
|
2900
|
+
return "This pull request cannot merge cleanly into the base branch. Resolve conflicts or update the branch, then retry.";
|
|
2901
|
+
}
|
|
2902
|
+
return extractGhErrorDetail(trimmed) || trimmed;
|
|
2903
|
+
}
|
|
2855
2904
|
function formatIpcInvokeError(err) {
|
|
2856
2905
|
let msg = err instanceof Error ? err.message : String(err);
|
|
2857
2906
|
msg = msg.replace(/^Error invoking remote method '[^']+':\s*/i, "");
|
|
2858
2907
|
msg = msg.replace(/^ExecaError:\s*/i, "");
|
|
2859
2908
|
msg = msg.replace(/^Error:\s*/i, "");
|
|
2909
|
+
if (isPrNotMergeableError(msg)) return formatMergePrError(msg);
|
|
2860
2910
|
return formatGhLandError(msg);
|
|
2861
2911
|
}
|
|
2862
2912
|
var init_gh_errors = __esm({
|
|
@@ -3839,6 +3889,41 @@ ${result.stderr}`;
|
|
|
3839
3889
|
].slice(0, 20) : [];
|
|
3840
3890
|
return { conflicting, base: baseName, files };
|
|
3841
3891
|
}
|
|
3892
|
+
async function probeLocalMergeGate(cwd, gate) {
|
|
3893
|
+
const mergeable = (gate?.mergeable ?? "").toUpperCase();
|
|
3894
|
+
const mergeState = (gate?.mergeStateStatus ?? "").toUpperCase();
|
|
3895
|
+
const alreadyConflicting = mergeable === "CONFLICTING" || mergeState === "DIRTY";
|
|
3896
|
+
const inQueue = gate ? prIsInMergeQueue(gate) : false;
|
|
3897
|
+
if (alreadyConflicting || inQueue) return { gate, files: [] };
|
|
3898
|
+
try {
|
|
3899
|
+
const local = await detectLocalMergeConflicts(cwd, gate?.baseRefName ?? null);
|
|
3900
|
+
if (local.conflicting) {
|
|
3901
|
+
return {
|
|
3902
|
+
gate: {
|
|
3903
|
+
mergeable: "CONFLICTING",
|
|
3904
|
+
mergeStateStatus: "DIRTY",
|
|
3905
|
+
reviewDecision: gate?.reviewDecision ?? null,
|
|
3906
|
+
baseRefName: local.base,
|
|
3907
|
+
url: gate?.url ?? null,
|
|
3908
|
+
isInMergeQueue: false
|
|
3909
|
+
},
|
|
3910
|
+
files: local.files
|
|
3911
|
+
};
|
|
3912
|
+
}
|
|
3913
|
+
if (gate && (mergeable === "UNKNOWN" || mergeState === "UNKNOWN")) {
|
|
3914
|
+
return {
|
|
3915
|
+
gate: {
|
|
3916
|
+
...gate,
|
|
3917
|
+
mergeable: gate.mergeable === "UNKNOWN" ? "MERGEABLE" : gate.mergeable,
|
|
3918
|
+
mergeStateStatus: gate.mergeStateStatus === "UNKNOWN" ? "CLEAN" : gate.mergeStateStatus
|
|
3919
|
+
},
|
|
3920
|
+
files: []
|
|
3921
|
+
};
|
|
3922
|
+
}
|
|
3923
|
+
} catch {
|
|
3924
|
+
}
|
|
3925
|
+
return { gate, files: [] };
|
|
3926
|
+
}
|
|
3842
3927
|
async function getPrChecks(cwd, selector) {
|
|
3843
3928
|
const slug = await resolveGithubRepoSlug(cwd);
|
|
3844
3929
|
const args = [
|
|
@@ -3874,47 +3959,9 @@ async function getPrChecks(cwd, selector) {
|
|
|
3874
3959
|
}
|
|
3875
3960
|
}
|
|
3876
3961
|
let gate = await fetchPrMergeGate(cwd, selector, slug);
|
|
3877
|
-
const
|
|
3878
|
-
|
|
3879
|
-
const
|
|
3880
|
-
const inQueue = gate ? prIsInMergeQueue(gate) : false;
|
|
3881
|
-
const needsLocalProbe = !alreadyConflicting && !inQueue;
|
|
3882
|
-
if (needsLocalProbe) {
|
|
3883
|
-
try {
|
|
3884
|
-
const local = await detectLocalMergeConflicts(cwd, gate?.baseRefName ?? null);
|
|
3885
|
-
if (local.conflicting) {
|
|
3886
|
-
const fileHint = local.files.length > 0 ? ` Conflicting paths: ${local.files.slice(0, 8).join(", ")}${local.files.length > 8 ? "\u2026" : ""}.` : "";
|
|
3887
|
-
gate = {
|
|
3888
|
-
mergeable: "CONFLICTING",
|
|
3889
|
-
mergeStateStatus: "DIRTY",
|
|
3890
|
-
reviewDecision: gate?.reviewDecision ?? null,
|
|
3891
|
-
baseRefName: local.base,
|
|
3892
|
-
url: gate?.url ?? null,
|
|
3893
|
-
isInMergeQueue: false
|
|
3894
|
-
};
|
|
3895
|
-
const ciFailed2 = ciChecks.some((c) => c.bucket === "fail");
|
|
3896
|
-
const review2 = (gate.reviewDecision ?? "").toUpperCase();
|
|
3897
|
-
const hasReviewRow2 = review2 === "CHANGES_REQUESTED" || review2 === "REVIEW_REQUIRED";
|
|
3898
|
-
const gateRows2 = buildMergeGateChecks(gate, {
|
|
3899
|
-
suppressGenericBlocked: ciFailed2 || hasReviewRow2
|
|
3900
|
-
}).map(
|
|
3901
|
-
(row) => row.kind === "mergeability" && row.name === "Merge conflicts" ? {
|
|
3902
|
-
...row,
|
|
3903
|
-
description: `${row.description ?? ""}${fileHint}`.trim()
|
|
3904
|
-
} : row
|
|
3905
|
-
);
|
|
3906
|
-
return [...gateRows2, ...ciChecks];
|
|
3907
|
-
}
|
|
3908
|
-
if (gate && (mergeable === "UNKNOWN" || mergeState === "UNKNOWN")) {
|
|
3909
|
-
gate = {
|
|
3910
|
-
...gate,
|
|
3911
|
-
mergeable: gate.mergeable === "UNKNOWN" ? "MERGEABLE" : gate.mergeable,
|
|
3912
|
-
mergeStateStatus: gate.mergeStateStatus === "UNKNOWN" ? "CLEAN" : gate.mergeStateStatus
|
|
3913
|
-
};
|
|
3914
|
-
}
|
|
3915
|
-
} catch {
|
|
3916
|
-
}
|
|
3917
|
-
}
|
|
3962
|
+
const probed = await probeLocalMergeGate(cwd, gate);
|
|
3963
|
+
gate = probed.gate;
|
|
3964
|
+
const fileHint = probed.files.length > 0 ? ` Conflicting paths: ${probed.files.slice(0, 8).join(", ")}${probed.files.length > 8 ? "\u2026" : ""}.` : "";
|
|
3918
3965
|
if (!gate) {
|
|
3919
3966
|
return ciChecks;
|
|
3920
3967
|
}
|
|
@@ -3924,7 +3971,12 @@ async function getPrChecks(cwd, selector) {
|
|
|
3924
3971
|
const gateRows = buildMergeGateChecks(gate, {
|
|
3925
3972
|
// Avoid duplicating "blocked" when CI failures or review rows already explain it.
|
|
3926
3973
|
suppressGenericBlocked: ciFailed || hasReviewRow
|
|
3927
|
-
})
|
|
3974
|
+
}).map(
|
|
3975
|
+
(row) => fileHint && row.kind === "mergeability" && row.name === "Merge conflicts" ? {
|
|
3976
|
+
...row,
|
|
3977
|
+
description: `${row.description ?? ""}${fileHint}`.trim()
|
|
3978
|
+
} : row
|
|
3979
|
+
);
|
|
3928
3980
|
return [...gateRows, ...ciChecks];
|
|
3929
3981
|
}
|
|
3930
3982
|
async function getPrMeta(cwd, selector) {
|
|
@@ -3934,7 +3986,7 @@ async function getPrMeta(cwd, selector) {
|
|
|
3934
3986
|
"view",
|
|
3935
3987
|
selector,
|
|
3936
3988
|
"--json",
|
|
3937
|
-
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus"
|
|
3989
|
+
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus,mergeable"
|
|
3938
3990
|
];
|
|
3939
3991
|
if (slug) viewArgs.push("--repo", slug);
|
|
3940
3992
|
let { stdout, exitCode, stderr } = await gh(viewArgs, cwd, { reject: false });
|
|
@@ -3944,7 +3996,7 @@ async function getPrMeta(cwd, selector) {
|
|
|
3944
3996
|
"view",
|
|
3945
3997
|
selector,
|
|
3946
3998
|
"--json",
|
|
3947
|
-
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus"
|
|
3999
|
+
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus,mergeable"
|
|
3948
4000
|
];
|
|
3949
4001
|
if (slug) retry.push("--repo", slug);
|
|
3950
4002
|
({ stdout, exitCode, stderr } = await gh(retry, cwd, { reject: false }));
|
|
@@ -3955,16 +4007,28 @@ async function getPrMeta(cwd, selector) {
|
|
|
3955
4007
|
}
|
|
3956
4008
|
try {
|
|
3957
4009
|
const view = JSON.parse(stdout);
|
|
4010
|
+
const gate = {
|
|
4011
|
+
mergeable: typeof view.mergeable === "string" && view.mergeable ? view.mergeable : null,
|
|
4012
|
+
mergeStateStatus: typeof view.mergeStateStatus === "string" && view.mergeStateStatus ? view.mergeStateStatus : null,
|
|
4013
|
+
reviewDecision: typeof view.reviewDecision === "string" && view.reviewDecision ? view.reviewDecision : null,
|
|
4014
|
+
baseRefName: String(view.baseRefName ?? ""),
|
|
4015
|
+
url: String(view.url ?? ""),
|
|
4016
|
+
isInMergeQueue: parseInMergeQueue(view)
|
|
4017
|
+
};
|
|
4018
|
+
const probed = await probeLocalMergeGate(cwd, gate);
|
|
4019
|
+
const resolved = probed.gate ?? gate;
|
|
3958
4020
|
return {
|
|
3959
4021
|
number: Number(view.number),
|
|
3960
4022
|
title: String(view.title ?? ""),
|
|
3961
4023
|
url: String(view.url ?? ""),
|
|
3962
4024
|
state: String(view.state ?? ""),
|
|
3963
4025
|
isDraft: Boolean(view.isDraft),
|
|
3964
|
-
reviewDecision:
|
|
3965
|
-
baseRefName: String(view.baseRefName ?? ""),
|
|
4026
|
+
reviewDecision: resolved.reviewDecision,
|
|
4027
|
+
baseRefName: resolved.baseRefName || String(view.baseRefName ?? ""),
|
|
3966
4028
|
headRefName: String(view.headRefName ?? ""),
|
|
3967
|
-
isInMergeQueue:
|
|
4029
|
+
isInMergeQueue: Boolean(resolved.isInMergeQueue),
|
|
4030
|
+
mergeable: resolved.mergeable,
|
|
4031
|
+
mergeStateStatus: resolved.mergeStateStatus
|
|
3968
4032
|
};
|
|
3969
4033
|
} catch {
|
|
3970
4034
|
return null;
|
|
@@ -4432,7 +4496,9 @@ async function mergePr(cwd, selector, opts) {
|
|
|
4432
4496
|
if (slug) args.push("--repo", slug);
|
|
4433
4497
|
const { exitCode, stderr, stdout } = await gh(args, cwd, { reject: false });
|
|
4434
4498
|
if (exitCode !== 0) {
|
|
4435
|
-
throw new Error(
|
|
4499
|
+
throw new Error(
|
|
4500
|
+
formatMergePrError(stderr.trim() || stdout.trim() || "gh pr merge failed")
|
|
4501
|
+
);
|
|
4436
4502
|
}
|
|
4437
4503
|
const after = await gh(viewArgs, cwd, { reject: false });
|
|
4438
4504
|
if (after.exitCode === 0 && after.stdout.trim()) {
|
|
@@ -4769,6 +4835,7 @@ var init_coordinator_prompt = __esm({
|
|
|
4769
4835
|
"- get_pr_stack / open_pr_stack_layers / add_stack_layer / create_pr_stack \u2014 GitHub stacked PRs (`gh stack`); one worktree per layer",
|
|
4770
4836
|
"- list_models \u2014 only when you need a specific model (rare); otherwise omit model so Account defaults apply",
|
|
4771
4837
|
"- list_threads / get_thread \u2014 fleet status (what is going on)",
|
|
4838
|
+
"- ask_user \u2014 multiple-choice questions in the composer (any mode, not only Plan). Explain options in chat first, include a description on every option, then wait for answers.",
|
|
4772
4839
|
"- set_caffeinate \u2014 keep this Mac awake across turns (macOS caffeinate). Turn on for Slack / away-from-keyboard work. Turn OFF when the user says they are done, wrapping up, going to sleep, or no longer need the machine awake. Closing this chat also releases it.",
|
|
4773
4840
|
"Workspaces:",
|
|
4774
4841
|
"- add_workspace / remove_workspace \u2014 register or unregister a git repo",
|
|
@@ -4788,7 +4855,11 @@ var init_coordinator_prompt = __esm({
|
|
|
4788
4855
|
'- 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',
|
|
4789
4856
|
"- ask_git \u2014 commit & push, open a draft PR, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn. Prefer this over paraphrasing.",
|
|
4790
4857
|
'- Merge (`ask_git` action=merge / send_to_thread "Merge PR.") only when the user explicitly asked to merge that PR. Do not merge because the work looks done, CI is green, or a typical flow includes it.',
|
|
4791
|
-
'- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "
|
|
4858
|
+
'- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Merge the remote branch (main) into your branch and resolve conflicts. Then, commit and push your changes.", "Merge PR." (draft PRs: `gh pr create --draft -R <origin-owner/name>` using the workspace `github:` slug \u2014 never upstream). Never run git/gh from this orchestration cwd, and never merge the PR yourself.',
|
|
4859
|
+
"Process guides:",
|
|
4860
|
+
"- Recurring multi-item / fan-out: if the child worktree has `.claude/skills/graph-engineering/SKILL.md`, tell the worker to follow it (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch three threads.",
|
|
4861
|
+
"- Recurring shapes: have the worktree agent write `.claude/skills/<kebab-name>/SKILL.md` (commit it) so later threads and native Claude Code / attach see it. Do not use `.sideboard/skills` for new guides. Codex/OpenCode: one line in AGENTS.md pointing at that file.",
|
|
4862
|
+
"- One-offs: no guide. Same miss across threads: edit the skill or `.sideboard/review.md`, then rerun the batch \u2014 do not patch three threads.",
|
|
4792
4863
|
"Human-only (do not attempt): ready-for-review land (confirm_land), purge_thread.",
|
|
4793
4864
|
"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.",
|
|
4794
4865
|
"Bash / Read / etc: allowed for (1) inspecting target worktrees / registered repo paths from MCP, and (2) greenfield setup under ~/sideboard/repos (git clone, gh repo create, git init+remote). Never git init/clone *inside* this synthetic home cwd \u2014 emptiness here is expected, not a bug."
|
|
@@ -5620,20 +5691,36 @@ function pushTurnStderr(tail, line, maxLines = 12) {
|
|
|
5620
5691
|
tail.push(trimmed);
|
|
5621
5692
|
while (tail.length > maxLines) tail.shift();
|
|
5622
5693
|
}
|
|
5694
|
+
function looksLikeMinifiedJsDump(line) {
|
|
5695
|
+
if (line.length < 200) return false;
|
|
5696
|
+
return /yield Promise\.all/.test(line) || /\(0,[A-Za-z$]\.\w+\)/.test(line) || /CURSOR_RIPGREP_PATH/.test(line);
|
|
5697
|
+
}
|
|
5698
|
+
function looksLikeNestedElectronCrash(line) {
|
|
5699
|
+
return /HasCustomHostObject|ElectronInitializeICUandStartNode/i.test(line);
|
|
5700
|
+
}
|
|
5701
|
+
function clipStderr(text3, maxChars) {
|
|
5702
|
+
const trimmed = text3.trim();
|
|
5703
|
+
if (trimmed.length <= maxChars) return trimmed;
|
|
5704
|
+
return trimmed.slice(0, maxChars);
|
|
5705
|
+
}
|
|
5623
5706
|
function summarizeTurnStderr(tail, maxChars = 500) {
|
|
5624
5707
|
if (tail.length === 0) return "";
|
|
5708
|
+
const cursorStartup = [...tail].reverse().find((line) => /cursor startup failed:/i.test(line));
|
|
5709
|
+
if (cursorStartup) return clipStderr(cursorStartup, maxChars);
|
|
5710
|
+
if (tail.some(looksLikeNestedElectronCrash)) return NESTED_ELECTRON_SUMMARY;
|
|
5625
5711
|
const moduleMissing = [...tail].reverse().find((line) => /cannot find module/i.test(line));
|
|
5626
|
-
if (moduleMissing)
|
|
5627
|
-
|
|
5712
|
+
if (moduleMissing) return clipStderr(moduleMissing, maxChars);
|
|
5713
|
+
const useful = tail.filter((line) => !looksLikeMinifiedJsDump(line));
|
|
5714
|
+
if (useful.length === 0 && tail.some(looksLikeMinifiedJsDump)) {
|
|
5715
|
+
return MINIFIED_DUMP_SUMMARY;
|
|
5628
5716
|
}
|
|
5629
|
-
const joined = tail.slice(-6).join("\n").trim();
|
|
5630
|
-
|
|
5631
|
-
return joined.slice(joined.length - maxChars);
|
|
5717
|
+
const joined = (useful.length ? useful : tail).slice(-6).join("\n").trim();
|
|
5718
|
+
return clipStderr(joined, maxChars);
|
|
5632
5719
|
}
|
|
5633
5720
|
function looksLikeInvalidAgentSession(text3) {
|
|
5634
5721
|
const lower = text3.trim().toLowerCase();
|
|
5635
5722
|
if (!lower) return false;
|
|
5636
|
-
return /session not found/.test(lower) || /no conversation found/.test(lower) || /conversation .+ not found/.test(lower) || /thread .+ not found/.test(lower) || /unknown session/.test(lower) || /invalid session/.test(lower) || /session .+ (missing|expired|deleted|gone)/.test(lower) || /cannot resume/.test(lower) || /failed to (load|resume|open) session/.test(lower);
|
|
5723
|
+
return /session not found/.test(lower) || /no conversation found/.test(lower) || /conversation .+ not found/.test(lower) || /thread .+ not found/.test(lower) || /unknown session/.test(lower) || /invalid session/.test(lower) || /session .+ (missing|expired|deleted|gone)/.test(lower) || /cannot resume/.test(lower) || /failed to (load|resume|open) session/.test(lower) || /corrupt local agent checkpoint/.test(lower) || /missing root blob/.test(lower) || /\bagent\b.{0,120}\bnot found\b/.test(lower);
|
|
5637
5724
|
}
|
|
5638
5725
|
function looksLikeAgentFailureMessage(text3) {
|
|
5639
5726
|
const lower = text3.trim().toLowerCase();
|
|
@@ -5673,6 +5760,12 @@ function humanizeAgentFailDetail(detail) {
|
|
|
5673
5760
|
if (/context.*(too long|exceed)|prompt is too long|conversation too long/.test(lower)) {
|
|
5674
5761
|
return `${raw} \u2014 start a new chat or compact context, then retry.`;
|
|
5675
5762
|
}
|
|
5763
|
+
if (/hascustomhostobject|electroninitializeicuandstartnode|nested chromium/i.test(lower)) {
|
|
5764
|
+
return `${raw} \u2014 retry the turn; if it keeps failing, pick another agent.`;
|
|
5765
|
+
}
|
|
5766
|
+
if (/corrupt local agent checkpoint|missing root blob|truncated crash dump/.test(lower)) {
|
|
5767
|
+
return `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
|
|
5768
|
+
}
|
|
5676
5769
|
return raw;
|
|
5677
5770
|
}
|
|
5678
5771
|
function formatTurnExitError(exitCode, stderrSummary) {
|
|
@@ -5688,11 +5781,13 @@ function formatTurnExitError(exitCode, stderrSummary) {
|
|
|
5688
5781
|
if (looksLikeAgentFailureMessage(raw)) return detail;
|
|
5689
5782
|
return `exit ${code}: ${detail}`;
|
|
5690
5783
|
}
|
|
5691
|
-
var NODE_VERSION_FOOTER;
|
|
5784
|
+
var NODE_VERSION_FOOTER, NESTED_ELECTRON_SUMMARY, MINIFIED_DUMP_SUMMARY;
|
|
5692
5785
|
var init_error_detail = __esm({
|
|
5693
5786
|
"src/agents/error-detail.ts"() {
|
|
5694
5787
|
"use strict";
|
|
5695
5788
|
NODE_VERSION_FOOTER = /^Node\.js v\d+/i;
|
|
5789
|
+
NESTED_ELECTRON_SUMMARY = "Cursor local agent crashed at Electron startup (nested Chromium / HasCustomHostObject)";
|
|
5790
|
+
MINIFIED_DUMP_SUMMARY = "Cursor local agent crashed during startup (truncated crash dump)";
|
|
5696
5791
|
}
|
|
5697
5792
|
});
|
|
5698
5793
|
|
|
@@ -6136,6 +6231,18 @@ var init_profile = __esm({
|
|
|
6136
6231
|
function isAsarPath(filePath) {
|
|
6137
6232
|
return /\.asar([/\\]|$)/.test(filePath);
|
|
6138
6233
|
}
|
|
6234
|
+
function applyNodeLaunch(launch, args) {
|
|
6235
|
+
if (!launch.env.ELECTRON_RUN_AS_NODE) {
|
|
6236
|
+
return { file: launch.file, args, env: launch.env };
|
|
6237
|
+
}
|
|
6238
|
+
const wrapped = wrapElectronAsNodeLaunch(launch.file, args);
|
|
6239
|
+
if (process.platform === "win32") {
|
|
6240
|
+
return { file: wrapped.file, args: wrapped.args, env: launch.env };
|
|
6241
|
+
}
|
|
6242
|
+
const env = { ...launch.env };
|
|
6243
|
+
delete env.ELECTRON_RUN_AS_NODE;
|
|
6244
|
+
return { file: wrapped.file, args: wrapped.args, env };
|
|
6245
|
+
}
|
|
6139
6246
|
async function resolveNodeLaunch(scriptPath) {
|
|
6140
6247
|
if (isAsarPath(scriptPath)) {
|
|
6141
6248
|
return {
|
|
@@ -6156,6 +6263,7 @@ async function resolveNodeLaunch(scriptPath) {
|
|
|
6156
6263
|
var init_node_launch = __esm({
|
|
6157
6264
|
"src/agents/node-launch.ts"() {
|
|
6158
6265
|
"use strict";
|
|
6266
|
+
init_nested_electron_env();
|
|
6159
6267
|
init_run();
|
|
6160
6268
|
}
|
|
6161
6269
|
});
|
|
@@ -6282,11 +6390,11 @@ async function resolveSideboardMcpServer() {
|
|
|
6282
6390
|
if (entry) {
|
|
6283
6391
|
const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
|
|
6284
6392
|
const scriptArgs = isCli ? [entry, "mcp"] : [entry];
|
|
6285
|
-
const launch = await resolveNodeLaunch(entry);
|
|
6393
|
+
const launch = applyNodeLaunch(await resolveNodeLaunch(entry), scriptArgs);
|
|
6286
6394
|
return {
|
|
6287
6395
|
name: "sideboard",
|
|
6288
6396
|
command: launch.file,
|
|
6289
|
-
args:
|
|
6397
|
+
args: launch.args,
|
|
6290
6398
|
...Object.keys(launch.env).length > 0 ? { env: launch.env } : {}
|
|
6291
6399
|
};
|
|
6292
6400
|
}
|
|
@@ -6332,10 +6440,19 @@ async function buildInjectedMcpServers(opts) {
|
|
|
6332
6440
|
function toCursorMcpServers(servers) {
|
|
6333
6441
|
const out = {};
|
|
6334
6442
|
for (const s of servers) {
|
|
6443
|
+
const env = s.env ? { ...s.env } : void 0;
|
|
6444
|
+
if (env) delete env.ELECTRON_RUN_AS_NODE;
|
|
6445
|
+
let command = s.command;
|
|
6446
|
+
let args = s.args;
|
|
6447
|
+
if (process.platform !== "win32" && !isStrippedElectronLaunch(command, args)) {
|
|
6448
|
+
const wrapped = wrapElectronAsNodeLaunch(command, args ?? []);
|
|
6449
|
+
command = wrapped.file;
|
|
6450
|
+
args = wrapped.args;
|
|
6451
|
+
}
|
|
6335
6452
|
out[s.name] = {
|
|
6336
|
-
command
|
|
6337
|
-
...
|
|
6338
|
-
...
|
|
6453
|
+
command,
|
|
6454
|
+
...args && args.length > 0 ? { args } : {},
|
|
6455
|
+
...env && Object.keys(env).length > 0 ? { env } : {}
|
|
6339
6456
|
};
|
|
6340
6457
|
}
|
|
6341
6458
|
return out;
|
|
@@ -6405,6 +6522,7 @@ var init_injected_mcp = __esm({
|
|
|
6405
6522
|
init_app_settings();
|
|
6406
6523
|
init_paths();
|
|
6407
6524
|
init_node_launch();
|
|
6525
|
+
init_nested_electron_env();
|
|
6408
6526
|
import_meta = {};
|
|
6409
6527
|
SIDEBOARD_MCP_ALLOWED_TOOLS = [
|
|
6410
6528
|
"mcp__sideboard",
|
|
@@ -7498,10 +7616,13 @@ var init_cursor = __esm({
|
|
|
7498
7616
|
};
|
|
7499
7617
|
const runner = cursorRunnerPath();
|
|
7500
7618
|
const isTs = runner.endsWith(".ts");
|
|
7501
|
-
const launch =
|
|
7619
|
+
const launch = applyNodeLaunch(
|
|
7620
|
+
await resolveNodeLaunch(runner),
|
|
7621
|
+
isTs ? ["--import", "tsx", runner] : [runner]
|
|
7622
|
+
);
|
|
7502
7623
|
return {
|
|
7503
7624
|
file: launch.file,
|
|
7504
|
-
args:
|
|
7625
|
+
args: launch.args,
|
|
7505
7626
|
cwd: thread.worktreePath,
|
|
7506
7627
|
stdin: JSON.stringify(req),
|
|
7507
7628
|
env: {
|
|
@@ -8575,6 +8696,7 @@ __export(index_exports, {
|
|
|
8575
8696
|
REVIEW_REQUEST_NAME: () => REVIEW_REQUEST_NAME,
|
|
8576
8697
|
REVIEW_REQUEST_PATH: () => REVIEW_REQUEST_PATH,
|
|
8577
8698
|
REVIEW_REQUEST_PREFILL: () => REVIEW_REQUEST_PREFILL,
|
|
8699
|
+
REVIEW_REQUEST_TEMPLATE: () => REVIEW_REQUEST_TEMPLATE,
|
|
8578
8700
|
SIDEBOARD_FORCE_STOP: () => SIDEBOARD_FORCE_STOP,
|
|
8579
8701
|
SIDEBOARD_MCP_ALLOWED_TOOLS: () => SIDEBOARD_MCP_ALLOWED_TOOLS,
|
|
8580
8702
|
SIDEBOARD_MCP_PROFILE_ENV: () => SIDEBOARD_MCP_PROFILE_ENV,
|
|
@@ -8723,9 +8845,11 @@ __export(index_exports, {
|
|
|
8723
8845
|
formatGhLandError: () => formatGhLandError,
|
|
8724
8846
|
formatGitAuthModeDirective: () => formatGitAuthModeDirective,
|
|
8725
8847
|
formatIpcInvokeError: () => formatIpcInvokeError,
|
|
8848
|
+
formatMergePrError: () => formatMergePrError,
|
|
8726
8849
|
formatMessagesAsTranscript: () => formatMessagesAsTranscript,
|
|
8727
8850
|
formatPlanQuestionAnswers: () => formatPlanQuestionAnswers,
|
|
8728
8851
|
formatPlanQuestionsForChat: () => formatPlanQuestionsForChat,
|
|
8852
|
+
formatProcessGuideDirective: () => formatProcessGuideDirective,
|
|
8729
8853
|
formatRateLimitResetHint: () => formatRateLimitResetHint,
|
|
8730
8854
|
formatRenameBranchDirective: () => formatRenameBranchDirective,
|
|
8731
8855
|
formatSlackExternalReplyPrompt: () => formatSlackExternalReplyPrompt,
|
|
@@ -8733,6 +8857,7 @@ __export(index_exports, {
|
|
|
8733
8857
|
formatSlackRepliesForTurn: () => formatSlackRepliesForTurn,
|
|
8734
8858
|
formatSlackSignedReply: () => formatSlackSignedReply,
|
|
8735
8859
|
formatTranscriptMarkdown: () => formatTranscriptMarkdown,
|
|
8860
|
+
formatUiReminder: () => formatUiReminder,
|
|
8736
8861
|
formatWorkspaceInventory: () => formatWorkspaceInventory,
|
|
8737
8862
|
formatWorktreeDirective: () => formatWorktreeDirective,
|
|
8738
8863
|
formatWorktreeReminder: () => formatWorktreeReminder,
|
|
@@ -8807,6 +8932,7 @@ __export(index_exports, {
|
|
|
8807
8932
|
isOrchestratorThread: () => isOrchestratorThread,
|
|
8808
8933
|
isPidAlive: () => isPidAlive,
|
|
8809
8934
|
isPlaceholderBranch: () => isPlaceholderBranch,
|
|
8935
|
+
isPrNotMergeableError: () => isPrNotMergeableError,
|
|
8810
8936
|
isPresentPlanToolName: () => isPresentPlanToolName,
|
|
8811
8937
|
isSessionQuotaLimit: () => isSessionQuotaLimit,
|
|
8812
8938
|
isSideboardScratchPath: () => isSideboardScratchPath,
|
|
@@ -9073,7 +9199,8 @@ function agentGitPrompt(action, opts) {
|
|
|
9073
9199
|
return "Commit, push, and open a PR in the browser.";
|
|
9074
9200
|
case "resolve-conflicts": {
|
|
9075
9201
|
const base = opts?.prBase?.trim().replace(/^refs\/heads\//, "");
|
|
9076
|
-
|
|
9202
|
+
const named = base ? ` (${base})` : "";
|
|
9203
|
+
return `Merge the remote branch${named} into your branch and resolve conflicts. Then, commit and push your changes.`;
|
|
9077
9204
|
}
|
|
9078
9205
|
case "merge":
|
|
9079
9206
|
return "Merge PR.";
|
|
@@ -10249,7 +10376,7 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
10249
10376
|
'- "Fix CI: <name>." \u2192 investigate that failing check, fix it, commit, and push.'
|
|
10250
10377
|
);
|
|
10251
10378
|
lines.push(
|
|
10252
|
-
'- "
|
|
10379
|
+
'- "Merge the remote branch (<base>) into your branch and resolve conflicts. Then, commit and push your changes." \u2192 fetch the PR base, merge it into this branch, resolve conflicts carefully, commit, and push until the PR is mergeable.'
|
|
10253
10380
|
);
|
|
10254
10381
|
lines.push(
|
|
10255
10382
|
'- "Address review comments." \u2192 read PR review feedback, make the requested changes, commit, and push.'
|
|
@@ -10257,11 +10384,22 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
10257
10384
|
lines.push(
|
|
10258
10385
|
'- "Merge PR." \u2192 merge this thread\'s open pull request on GitHub (this phrase is the explicit ask). If `gh stack view` shows a stack, use `gh stack merge`; otherwise `gh pr merge` (respect repo defaults / squash vs merge). Do not force-push main/master or merge locally into the main checkout.'
|
|
10259
10386
|
);
|
|
10387
|
+
lines.push("");
|
|
10388
|
+
lines.push(formatProcessGuideDirective());
|
|
10260
10389
|
return lines.join("\n");
|
|
10261
10390
|
}
|
|
10262
10391
|
function formatWorktreeReminder() {
|
|
10263
10392
|
return "Sideboard worktree: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout.";
|
|
10264
10393
|
}
|
|
10394
|
+
function formatProcessGuideDirective() {
|
|
10395
|
+
return [
|
|
10396
|
+
"Process guides (recurring work only):",
|
|
10397
|
+
"- If `.claude/skills/graph-engineering/SKILL.md` exists, follow it (`/graph-engineering`) for migrations, ports, batch fixes, and other fan-out. Judge first; state on disk; grow the rulebook; do not patch around it.",
|
|
10398
|
+
"- If this same shape of work will happen again, write `.claude/skills/<kebab-name>/SKILL.md` in this worktree (Claude Code project skill). Sideboard `/name`, Claude Code, and `attach` all load that path. Do not leave the method only in chat.",
|
|
10399
|
+
"- Do not write new skills under `.sideboard/skills` \u2014 native agents do not scan it. Point Codex/OpenCode at the file from `AGENTS.md`. Optional: symlink `.cursor/skills/<name>` to the Claude skill.",
|
|
10400
|
+
"- Skip a guide for a one-off. If a matching skill exists, follow it. Same miss twice \u2192 edit the skill (or `.sideboard/review.md`), do not patch around it."
|
|
10401
|
+
].join("\n");
|
|
10402
|
+
}
|
|
10265
10403
|
function formatArtifactDirective() {
|
|
10266
10404
|
return [
|
|
10267
10405
|
"Sideboard side column (desktop UI):",
|
|
@@ -10279,9 +10417,22 @@ function formatArtifactDirective() {
|
|
|
10279
10417
|
"Files / media browser (CMS file manager column):",
|
|
10280
10418
|
"4) Call Sideboard MCP `present_files` with optional title, path, and datasource (brightsy|memory).",
|
|
10281
10419
|
" Opens the Files column for browse/upload/pick. Do NOT say a file manager UI is missing.",
|
|
10282
|
-
"
|
|
10420
|
+
"Multiple-choice questions (any mode \u2014 not only Plan):",
|
|
10421
|
+
"5) Call Sideboard MCP `ask_user` when the user should pick from predefined options (approach forks, requirements, which API). First write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it). Include a description on every option. After calling, stop and wait for their next message with answers. Do not ask multiple-choice questions as plain chat bullets \u2014 use ask_user so Sideboard shows the composer picker.",
|
|
10422
|
+
"Never say artifacts, CMS UI, or the Files column are unavailable. Prefer present_schema for list/edit/publish; present_files for storage UI; html fences for standalone pages; ask_user for predefined-option questions."
|
|
10283
10423
|
].join("\n");
|
|
10284
10424
|
}
|
|
10425
|
+
function formatUiReminder() {
|
|
10426
|
+
return [
|
|
10427
|
+
"Sideboard side column (important):",
|
|
10428
|
+
"There is no claude.ai Artifact tool here \u2014 that is normal.",
|
|
10429
|
+
"HTML/SVG/markdown: ```html fence or MCP present_artifact.",
|
|
10430
|
+
"CMS forms/tables: MCP present_schema (Brightsy resource_id or inline schema+schemaUi).",
|
|
10431
|
+
"Files column: MCP present_files (brightsy account storage or memory).",
|
|
10432
|
+
"Do not say artifacts/CMS UI are unavailable.",
|
|
10433
|
+
"Multiple-choice questions: MCP ask_user (composer picker, any mode). Explain options in chat first, then wait for answers."
|
|
10434
|
+
].join(" ");
|
|
10435
|
+
}
|
|
10285
10436
|
var FILES_BY_AGENT = {
|
|
10286
10437
|
claude: [
|
|
10287
10438
|
"CLAUDE.md",
|
|
@@ -10395,6 +10546,8 @@ var import_node_path18 = require("path");
|
|
|
10395
10546
|
var import_execa3 = require("execa");
|
|
10396
10547
|
var import_node_readline2 = require("readline");
|
|
10397
10548
|
init_settings();
|
|
10549
|
+
init_nested_electron_env();
|
|
10550
|
+
init_nested_electron_env();
|
|
10398
10551
|
var PORT_RANGE_SIZE = 10;
|
|
10399
10552
|
function matchSimpleGlob(pattern, name) {
|
|
10400
10553
|
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
@@ -10478,16 +10631,6 @@ async function captureLoginEnv() {
|
|
|
10478
10631
|
cachedLoginEnv = { ...process.env };
|
|
10479
10632
|
return { ...cachedLoginEnv };
|
|
10480
10633
|
}
|
|
10481
|
-
var NESTED_ELECTRON_ENV_PREFIXES = ["ELECTRON_", "CHROME_"];
|
|
10482
|
-
function stripNestedElectronEnv(env) {
|
|
10483
|
-
const out = { ...env };
|
|
10484
|
-
for (const key of Object.keys(out)) {
|
|
10485
|
-
if (NESTED_ELECTRON_ENV_PREFIXES.some((prefix) => key.startsWith(prefix))) {
|
|
10486
|
-
delete out[key];
|
|
10487
|
-
}
|
|
10488
|
-
}
|
|
10489
|
-
return out;
|
|
10490
|
-
}
|
|
10491
10634
|
function buildWorkspaceScriptEnv(opts, baseEnv) {
|
|
10492
10635
|
const env = stripNestedElectronEnv({
|
|
10493
10636
|
...baseEnv ?? process.env
|
|
@@ -14278,6 +14421,10 @@ File: src/client/frontends/desktop/core/UserData.ts
|
|
|
14278
14421
|
|
|
14279
14422
|
**Approve** \u2014 Diff is scoped, behavior looks correct, and there are no blocking issues. Safe to merge.
|
|
14280
14423
|
</example>
|
|
14424
|
+
|
|
14425
|
+
## Growing the rules
|
|
14426
|
+
|
|
14427
|
+
If a blocking issue is a missing or ambiguous repo rule that will recur, say so and propose one sentence for \`.sideboard/review.md\` or a \`.claude/skills/<name>/SKILL.md\`. Do not only patch this diff when the same miss will happen again. New skills go under \`.claude/skills\` (Claude Code / attach) \u2014 not \`.sideboard/skills\`.
|
|
14281
14428
|
`;
|
|
14282
14429
|
|
|
14283
14430
|
// src/review/request-review.ts
|
|
@@ -15078,14 +15225,7 @@ var Orchestrator = class {
|
|
|
15078
15225
|
SLACK_REPLY_FORMATTING
|
|
15079
15226
|
].join("\n") : null
|
|
15080
15227
|
].filter(Boolean).join("\n") : null;
|
|
15081
|
-
const artifactReminder = thread.agent !== "brightsy" ?
|
|
15082
|
-
"Sideboard side column (important):",
|
|
15083
|
-
"There is no claude.ai Artifact tool here \u2014 that is normal.",
|
|
15084
|
-
"HTML/SVG/markdown: ```html fence or MCP present_artifact.",
|
|
15085
|
-
"CMS forms/tables: MCP present_schema (Brightsy resource_id or inline schema+schemaUi).",
|
|
15086
|
-
"Files column: MCP present_files (brightsy account storage or memory).",
|
|
15087
|
-
"Do not say artifacts/CMS UI are unavailable."
|
|
15088
|
-
].join(" ") : null;
|
|
15228
|
+
const artifactReminder = thread.agent !== "brightsy" ? formatUiReminder() : null;
|
|
15089
15229
|
const worktreeReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatWorktreeReminder() : null;
|
|
15090
15230
|
const slackReplyContext = formatSlackRepliesForTurn(
|
|
15091
15231
|
pendingSlackExternalReplies(thread.messages)
|
|
@@ -15224,7 +15364,7 @@ var Orchestrator = class {
|
|
|
15224
15364
|
}
|
|
15225
15365
|
let lastStderr = summarizeTurnStderr(stderrTail);
|
|
15226
15366
|
let detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
15227
|
-
if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) && looksLikeInvalidAgentSession(detail) && this.requireThread(threadId).sessionId && this.requireThread(threadId).agent !== "
|
|
15367
|
+
if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) && looksLikeInvalidAgentSession(detail) && this.requireThread(threadId).sessionId && this.requireThread(threadId).agent !== "brightsy") {
|
|
15228
15368
|
updateThread(threadId, { sessionId: null });
|
|
15229
15369
|
pushTurnStderr(
|
|
15230
15370
|
stderrTail,
|
|
@@ -15779,7 +15919,9 @@ var Orchestrator = class {
|
|
|
15779
15919
|
reviewDecision: null,
|
|
15780
15920
|
baseRefName: "",
|
|
15781
15921
|
headRefName: "",
|
|
15782
|
-
isInMergeQueue: false
|
|
15922
|
+
isInMergeQueue: false,
|
|
15923
|
+
mergeable: null,
|
|
15924
|
+
mergeStateStatus: null
|
|
15783
15925
|
};
|
|
15784
15926
|
await this.persistPrMetaAndMaybeArchive(thread, metaLike);
|
|
15785
15927
|
return { url: metaLike.url, state };
|
|
@@ -17141,7 +17283,7 @@ async function startMcpServer() {
|
|
|
17141
17283
|
);
|
|
17142
17284
|
server.tool(
|
|
17143
17285
|
"ask_user",
|
|
17144
|
-
"Ask the user clarifying multiple-choice questions in Sideboard\u2019s composer (
|
|
17286
|
+
"Ask the user clarifying multiple-choice questions in Sideboard\u2019s composer (any mode \u2014 not only Plan). Before calling, write a short chat message explaining the decision and what each option means. Include a description on every option. Use when the user should pick from predefined options (approach forks, requirements, which API) \u2014 not for \u201Cis the plan ready?\u201D. After calling, stop and wait for their next message with answers.",
|
|
17145
17287
|
{
|
|
17146
17288
|
questions: import_zod3.z.array(
|
|
17147
17289
|
import_zod3.z.object({
|
|
@@ -20018,6 +20160,7 @@ async function startSlackRelayServer(opts) {
|
|
|
20018
20160
|
REVIEW_REQUEST_NAME,
|
|
20019
20161
|
REVIEW_REQUEST_PATH,
|
|
20020
20162
|
REVIEW_REQUEST_PREFILL,
|
|
20163
|
+
REVIEW_REQUEST_TEMPLATE,
|
|
20021
20164
|
SIDEBOARD_FORCE_STOP,
|
|
20022
20165
|
SIDEBOARD_MCP_ALLOWED_TOOLS,
|
|
20023
20166
|
SIDEBOARD_MCP_PROFILE_ENV,
|
|
@@ -20166,9 +20309,11 @@ async function startSlackRelayServer(opts) {
|
|
|
20166
20309
|
formatGhLandError,
|
|
20167
20310
|
formatGitAuthModeDirective,
|
|
20168
20311
|
formatIpcInvokeError,
|
|
20312
|
+
formatMergePrError,
|
|
20169
20313
|
formatMessagesAsTranscript,
|
|
20170
20314
|
formatPlanQuestionAnswers,
|
|
20171
20315
|
formatPlanQuestionsForChat,
|
|
20316
|
+
formatProcessGuideDirective,
|
|
20172
20317
|
formatRateLimitResetHint,
|
|
20173
20318
|
formatRenameBranchDirective,
|
|
20174
20319
|
formatSlackExternalReplyPrompt,
|
|
@@ -20176,6 +20321,7 @@ async function startSlackRelayServer(opts) {
|
|
|
20176
20321
|
formatSlackRepliesForTurn,
|
|
20177
20322
|
formatSlackSignedReply,
|
|
20178
20323
|
formatTranscriptMarkdown,
|
|
20324
|
+
formatUiReminder,
|
|
20179
20325
|
formatWorkspaceInventory,
|
|
20180
20326
|
formatWorktreeDirective,
|
|
20181
20327
|
formatWorktreeReminder,
|
|
@@ -20250,6 +20396,7 @@ async function startSlackRelayServer(opts) {
|
|
|
20250
20396
|
isOrchestratorThread,
|
|
20251
20397
|
isPidAlive,
|
|
20252
20398
|
isPlaceholderBranch,
|
|
20399
|
+
isPrNotMergeableError,
|
|
20253
20400
|
isPresentPlanToolName,
|
|
20254
20401
|
isSessionQuotaLimit,
|
|
20255
20402
|
isSideboardScratchPath,
|