@sideboard-ai/core 0.1.67 → 0.1.71
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-OTBZVTZO.js → agents-GB7XL2LI.js} +8 -7
- package/dist/{agents-TS3EI2YI.js → agents-TCAK3MXN.js} +8 -7
- package/dist/{app-settings-ONKMFSEJ.js → app-settings-3TLA2EJ7.js} +16 -1
- package/dist/{app-settings-GJVZGU3M.js → app-settings-P42Z3VOB.js} +16 -1
- package/dist/caffeinate-hold-BEJIYPJ7.js +107 -0
- package/dist/caffeinate-hold-KLC6SABD.js +14 -0
- package/dist/{chunk-WAFIF22N.js → chunk-3CY6WJ7O.js} +2 -2
- package/dist/{chunk-7ZOQY4A7.js → chunk-57ROTAFD.js} +62 -3
- package/dist/{chunk-57WWNMFP.js → chunk-7NCIHRAU.js} +22 -4
- package/dist/{chunk-FGDJOJ2L.js → chunk-AE5VBOFE.js} +1 -1
- package/dist/{chunk-DB3I75FI.js → chunk-BTL7EMGT.js} +4 -4
- package/dist/{chunk-4UIYN56C.js → chunk-D4DPQ552.js} +1 -1
- package/dist/{chunk-JWZNK3CQ.js → chunk-DGPUAZA4.js} +62 -3
- package/dist/{chunk-ZRFAZVGL.js → chunk-H2IXNFQ2.js} +22 -4
- package/dist/chunk-JAWEDVVA.js +106 -0
- package/dist/chunk-JT7R45JB.js +20 -0
- package/dist/{chunk-4BUCGNZS.js → chunk-MF2YMEGD.js} +83 -29
- package/dist/{chunk-K7LM4CLD.js → chunk-NG7S3OPX.js} +12 -6
- package/dist/chunk-NSTQ6QKD.js +23 -0
- package/dist/{chunk-LW5CMQGZ.js → chunk-OE7YBB5X.js} +83 -29
- package/dist/{chunk-BPOTVI5J.js → chunk-PTJJIQK7.js} +472 -18
- package/dist/{chunk-B4PRRKMA.js → chunk-S25IHL5H.js} +12 -6
- package/dist/{chunk-5HTTCYWA.js → chunk-UH57WVFP.js} +2 -2
- package/dist/{chunk-M5V4QIWF.js → chunk-VROPG6QF.js} +1 -1
- package/dist/{chunk-MHR4OGZ4.js → chunk-W7YOTDVO.js} +493 -18
- package/dist/{connected-teams-RUNMOCG5.js → connected-teams-35EIRJCP.js} +2 -2
- package/dist/{connected-teams-OMDHTL6A.js → connected-teams-ZRS53OAT.js} +2 -2
- package/dist/{coordinator-prompt-6HMTOX4G.js → coordinator-prompt-2J4PIMUF.js} +7 -4
- package/dist/{coordinator-prompt-3BSMKZL4.js → coordinator-prompt-QYYG2IBB.js} +7 -4
- package/dist/{global-workspace-YZ2NJVLL.js → global-workspace-KHIFQUUM.js} +12 -5
- package/dist/{global-workspace-QS7A23CB.js → global-workspace-SVRYNJZA.js} +12 -5
- package/dist/index.cjs +4805 -1262
- package/dist/index.d.cts +570 -22
- package/dist/index.d.ts +570 -22
- package/dist/index.js +3084 -340
- package/dist/mcp/run-stdio.cjs +2339 -617
- package/dist/mcp/run-stdio.js +1289 -290
- package/dist/{run-Y2MI3EVV.js → run-A4RHY7HH.js} +1 -1
- package/dist/{run-JLD2Y52J.js → run-V2WZUMJA.js} +1 -1
- package/dist/{workspaces-EBFW7I7S.js → workspaces-AHFTHVBT.js} +7 -6
- package/dist/{workspaces-AIUYUXB7.js → workspaces-SVQIEVIZ.js} +7 -6
- package/dist/{worktree-WMDJW2BL.js → worktree-KWXHMKRN.js} +2 -2
- package/dist/{worktree-7NBPIVFZ.js → worktree-VOCH3WS3.js} +2 -2
- package/package.json +3 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveThreadDefaults
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-W7YOTDVO.js";
|
|
4
4
|
import {
|
|
5
5
|
resolveGithubRepoSlug
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-MF2YMEGD.js";
|
|
7
7
|
import {
|
|
8
8
|
globalAgentCwd,
|
|
9
9
|
sideboardReposDir
|
|
@@ -45,9 +45,12 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
45
45
|
"Discover:",
|
|
46
46
|
"- list_workspaces \u2014 registered repos (path + github slug when known)",
|
|
47
47
|
"- list_branches / list_prs / list_issues \u2014 pass repoPath from list_workspaces (issues: Linear API or GitHub Issues)",
|
|
48
|
+
"- list_teams / slack_list_channels / slack_list_users / slack_search / slack_read / slack_post \u2014 Slack workspaces from Account settings; pass team_id from list_teams",
|
|
49
|
+
"- Slack notify (only when the user asks): list_teams \u2192 slack_list_users or slack_list_channels \u2192 slack_post with to=@user or #channel and optional github_url (PR, blob permalink, or review/issue comment). Do not notify proactively.",
|
|
48
50
|
"- get_pr_stack / open_pr_stack_layers / add_stack_layer / create_pr_stack \u2014 GitHub stacked PRs (`gh stack`); one worktree per layer",
|
|
49
51
|
"- list_models \u2014 only when you need a specific model (rare); otherwise omit model so Account defaults apply",
|
|
50
52
|
"- list_threads / get_thread \u2014 fleet status (what is going on)",
|
|
53
|
+
"- 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.",
|
|
51
54
|
"Workspaces:",
|
|
52
55
|
"- add_workspace / remove_workspace \u2014 register or unregister a git repo",
|
|
53
56
|
"Worktree threads (chats):",
|
|
@@ -69,6 +72,13 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
69
72
|
"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.",
|
|
70
73
|
"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."
|
|
71
74
|
].join("\n");
|
|
75
|
+
var SLACK_REPLY_FORMATTING = [
|
|
76
|
+
"Slack formatting (mandatory \u2014 your reply is posted verbatim to Slack):",
|
|
77
|
+
"- Use Slack mrkdwn, NOT GitHub/CommonMark markdown. Slack does not render `**bold**`, `# headings`, or `[label](url)`.",
|
|
78
|
+
"- Bold: *text* (single asterisks). Italic: _text_. Strikethrough: ~text~. Inline code: `code`.",
|
|
79
|
+
"- Links: <https://example.com|label> or bare URLs. Thread ids: plain `sideboard://thread/<id>` (no markdown link syntax).",
|
|
80
|
+
"- Prefer short paragraphs and *bold* section labels over markdown headings or bullet trees with `**`."
|
|
81
|
+
].join("\n");
|
|
72
82
|
function accountDefaultsPlaybookLine() {
|
|
73
83
|
const d = resolveThreadDefaults();
|
|
74
84
|
const model = d.model?.trim() || "Auto";
|
|
@@ -89,7 +99,8 @@ function coordinatorTurnReminder(opts) {
|
|
|
89
99
|
`- 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.`,
|
|
90
100
|
"- Existing repo: create_thread on a repoPath \u2192 send_to_thread \u2192 wait_for_turn.",
|
|
91
101
|
"- New repo: Bash (clone or gh repo create under ~/sideboard/repos/<name>) \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 draft PR.",
|
|
92
|
-
"- When naming threads for the user, link them as `[Title](sideboard://thread/<id>)`."
|
|
102
|
+
"- When naming threads for the user, link them as `[Title](sideboard://thread/<id>)`.",
|
|
103
|
+
"- If they will wait on Slack or leave the Mac, call set_caffeinate enabled=true. When they say they are done / wrapping up / going to sleep, call set_caffeinate enabled=false."
|
|
93
104
|
].filter(Boolean).join("\n");
|
|
94
105
|
}
|
|
95
106
|
function ensureGlobalCoordinatorCwd(opts) {
|
|
@@ -157,8 +168,14 @@ function coordinatorSystemPrompt(opts) {
|
|
|
157
168
|
const audience = opts.audience ?? "cloud";
|
|
158
169
|
const reposDir = sideboardReposDir();
|
|
159
170
|
const intro = audience === "cloud" ? [
|
|
160
|
-
"You are a Sideboard coordinator responding to a request from a Brightsy cloud agent (
|
|
171
|
+
"You are a Sideboard coordinator responding to a request from a Brightsy cloud agent (Discord, Teams, or other chat).",
|
|
161
172
|
"Your reply will be sent back to that cloud agent \u2014 be concise and actionable."
|
|
173
|
+
] : audience === "slack" ? [
|
|
174
|
+
"You are a Sideboard coordinator responding to a Slack DM or @mention via the Sideboard Slack app.",
|
|
175
|
+
"Your reply will be posted back in Slack \u2014 be concise and actionable.",
|
|
176
|
+
"Sideboard signs the Slack reply with this Mac's destination name (Personal / Work). Do not prefix that name yourself.",
|
|
177
|
+
"Call set_caffeinate enabled=true when they start a stretch of remote work so the Mac stays awake. Call set_caffeinate enabled=false when they say they are done, wrapping up, or going to sleep.",
|
|
178
|
+
SLACK_REPLY_FORMATTING
|
|
162
179
|
] : [
|
|
163
180
|
"You are a Sideboard orchestration agent: you oversee worktree agents across registered workspaces in the Sideboard app.",
|
|
164
181
|
"Stay concise and actionable; prefer Sideboard MCP for fleet status; use Bash for greenfield repo setup and inspecting target worktree paths."
|
|
@@ -186,6 +203,7 @@ export {
|
|
|
186
203
|
enrichWorkspacesWithGithub,
|
|
187
204
|
coordinatorGreenfieldPlaybook,
|
|
188
205
|
COORDINATOR_TOOL_PLAYBOOK,
|
|
206
|
+
SLACK_REPLY_FORMATTING,
|
|
189
207
|
coordinatorTurnReminder,
|
|
190
208
|
ensureGlobalCoordinatorCwd,
|
|
191
209
|
coordinatorSystemPrompt
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import {
|
|
2
|
+
writePrivateFile
|
|
3
|
+
} from "./chunk-JT7R45JB.js";
|
|
4
|
+
import {
|
|
5
|
+
appDataDir
|
|
6
|
+
} from "./chunk-M37RITA6.js";
|
|
7
|
+
|
|
8
|
+
// src/store/caffeinate-hold.ts
|
|
9
|
+
import { spawn } from "child_process";
|
|
10
|
+
import { existsSync, readFileSync, unlinkSync } from "fs";
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
var hooks = {};
|
|
13
|
+
function setCaffeinateHoldHooks(next) {
|
|
14
|
+
hooks = next;
|
|
15
|
+
}
|
|
16
|
+
function caffeinateHoldPath() {
|
|
17
|
+
return join(appDataDir(), "caffeinate-hold.json");
|
|
18
|
+
}
|
|
19
|
+
function processAlive(pid) {
|
|
20
|
+
if (hooks.processAlive) return hooks.processAlive(pid);
|
|
21
|
+
try {
|
|
22
|
+
process.kill(pid, 0);
|
|
23
|
+
return true;
|
|
24
|
+
} catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function killPid(pid) {
|
|
29
|
+
if (hooks.kill) {
|
|
30
|
+
hooks.kill(pid);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
process.kill(pid, "SIGTERM");
|
|
35
|
+
} catch {
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function readHold() {
|
|
39
|
+
const path = caffeinateHoldPath();
|
|
40
|
+
if (!existsSync(path)) return null;
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
43
|
+
if (typeof parsed?.pid === "number" && parsed.pid > 0) return parsed;
|
|
44
|
+
} catch {
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
function writeHold(pid) {
|
|
49
|
+
writePrivateFile(caffeinateHoldPath(), `${JSON.stringify({ pid })}
|
|
50
|
+
`);
|
|
51
|
+
}
|
|
52
|
+
function clearHold() {
|
|
53
|
+
try {
|
|
54
|
+
unlinkSync(caffeinateHoldPath());
|
|
55
|
+
} catch {
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function getCaffeinateHold() {
|
|
59
|
+
const platform = hooks.platform ?? process.platform;
|
|
60
|
+
const hold = readHold();
|
|
61
|
+
if (!hold) {
|
|
62
|
+
return { held: false, pid: null, running: false, platform };
|
|
63
|
+
}
|
|
64
|
+
const running = processAlive(hold.pid);
|
|
65
|
+
if (!running) {
|
|
66
|
+
clearHold();
|
|
67
|
+
return { held: false, pid: null, running: false, platform };
|
|
68
|
+
}
|
|
69
|
+
return { held: true, pid: hold.pid, running: true, platform };
|
|
70
|
+
}
|
|
71
|
+
function setCaffeinateHold(enabled) {
|
|
72
|
+
const platform = hooks.platform ?? process.platform;
|
|
73
|
+
const current = getCaffeinateHold();
|
|
74
|
+
if (!enabled) {
|
|
75
|
+
if (current.pid) killPid(current.pid);
|
|
76
|
+
clearHold();
|
|
77
|
+
return { held: false, pid: null, running: false, platform };
|
|
78
|
+
}
|
|
79
|
+
if (current.running && current.pid) return current;
|
|
80
|
+
if (platform !== "darwin") {
|
|
81
|
+
return { held: false, pid: null, running: false, platform };
|
|
82
|
+
}
|
|
83
|
+
const spawnImpl = hooks.spawn ?? spawn;
|
|
84
|
+
const child = spawnImpl("caffeinate", ["-dimsu"], {
|
|
85
|
+
detached: true,
|
|
86
|
+
stdio: "ignore"
|
|
87
|
+
});
|
|
88
|
+
const pid = child.pid;
|
|
89
|
+
if (!pid) {
|
|
90
|
+
try {
|
|
91
|
+
child.kill();
|
|
92
|
+
} catch {
|
|
93
|
+
}
|
|
94
|
+
return { held: false, pid: null, running: false, platform };
|
|
95
|
+
}
|
|
96
|
+
child.unref();
|
|
97
|
+
writeHold(pid);
|
|
98
|
+
return { held: true, pid, running: true, platform };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
setCaffeinateHoldHooks,
|
|
103
|
+
caffeinateHoldPath,
|
|
104
|
+
getCaffeinateHold,
|
|
105
|
+
setCaffeinateHold
|
|
106
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/store/private-file.ts
|
|
2
|
+
import { chmodSync, mkdirSync, writeFileSync } from "fs";
|
|
3
|
+
import { dirname } from "path";
|
|
4
|
+
var PRIVATE_FILE_MODE = 384;
|
|
5
|
+
function writePrivateFile(path, contents) {
|
|
6
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
7
|
+
writeFileSync(path, contents, { encoding: "utf8", mode: PRIVATE_FILE_MODE });
|
|
8
|
+
chmodOwnerOnly(path);
|
|
9
|
+
}
|
|
10
|
+
function chmodOwnerOnly(path) {
|
|
11
|
+
try {
|
|
12
|
+
chmodSync(path, PRIVATE_FILE_MODE);
|
|
13
|
+
} catch {
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
writePrivateFile,
|
|
19
|
+
chmodOwnerOnly
|
|
20
|
+
};
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
gh,
|
|
12
12
|
git,
|
|
13
13
|
resolveGhAuthToken
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-D4DPQ552.js";
|
|
15
15
|
|
|
16
16
|
// src/git/worktree.ts
|
|
17
17
|
import { existsSync, readdirSync } from "fs";
|
|
@@ -887,6 +887,10 @@ function formatIpcInvokeError(err) {
|
|
|
887
887
|
}
|
|
888
888
|
|
|
889
889
|
// src/git/pr-gates.ts
|
|
890
|
+
function prIsInMergeQueue(gate) {
|
|
891
|
+
if (gate.isInMergeQueue) return true;
|
|
892
|
+
return (gate.mergeStateStatus ?? "").toUpperCase() === "QUEUED";
|
|
893
|
+
}
|
|
890
894
|
function buildMergeGateChecks(gate, opts = {}) {
|
|
891
895
|
const rows = [];
|
|
892
896
|
const base = gate.baseRefName?.trim() || "the base branch";
|
|
@@ -896,7 +900,8 @@ function buildMergeGateChecks(gate, opts = {}) {
|
|
|
896
900
|
const review = (gate.reviewDecision ?? "").toUpperCase();
|
|
897
901
|
const suppressBlocked = opts.suppressGenericBlocked !== false;
|
|
898
902
|
const conflicting = mergeable === "CONFLICTING" || mergeState === "DIRTY";
|
|
899
|
-
|
|
903
|
+
const inQueue = prIsInMergeQueue(gate);
|
|
904
|
+
if (conflicting && !inQueue) {
|
|
900
905
|
rows.push({
|
|
901
906
|
name: "Merge conflicts",
|
|
902
907
|
state: mergeable === "CONFLICTING" ? "CONFLICTING" : mergeState || "DIRTY",
|
|
@@ -908,6 +913,18 @@ function buildMergeGateChecks(gate, opts = {}) {
|
|
|
908
913
|
workflow: "mergeability",
|
|
909
914
|
kind: "mergeability"
|
|
910
915
|
});
|
|
916
|
+
} else if (inQueue) {
|
|
917
|
+
rows.push({
|
|
918
|
+
name: "Merge queue",
|
|
919
|
+
state: "QUEUED",
|
|
920
|
+
bucket: "pending",
|
|
921
|
+
startedAt: null,
|
|
922
|
+
completedAt: null,
|
|
923
|
+
link,
|
|
924
|
+
description: `This pull request is in the GitHub merge queue for ${base}.`,
|
|
925
|
+
workflow: "mergeability",
|
|
926
|
+
kind: "mergeability"
|
|
927
|
+
});
|
|
911
928
|
} else if (mergeState === "BEHIND") {
|
|
912
929
|
rows.push({
|
|
913
930
|
name: "Branch behind",
|
|
@@ -1274,7 +1291,7 @@ async function originGhRepoEnv(cwd) {
|
|
|
1274
1291
|
const slug = await resolveGithubRepoSlug(cwd);
|
|
1275
1292
|
return slug ? { GH_REPO: slug } : {};
|
|
1276
1293
|
}
|
|
1277
|
-
async function resolveDefaultBranch(repoPath) {
|
|
1294
|
+
async function resolveDefaultBranch(repoPath, opts) {
|
|
1278
1295
|
const viaOrigin = await git(
|
|
1279
1296
|
["symbolic-ref", "refs/remotes/origin/HEAD"],
|
|
1280
1297
|
repoPath,
|
|
@@ -1283,22 +1300,24 @@ async function resolveDefaultBranch(repoPath) {
|
|
|
1283
1300
|
if (viaOrigin.exitCode === 0 && viaOrigin.stdout.trim()) {
|
|
1284
1301
|
return viaOrigin.stdout.trim().replace(/^refs\/remotes\/origin\//, "");
|
|
1285
1302
|
}
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1303
|
+
if (opts?.network !== false) {
|
|
1304
|
+
const slug = await resolveGithubRepoSlug(repoPath);
|
|
1305
|
+
const viaGh = await gh(
|
|
1306
|
+
[
|
|
1307
|
+
"repo",
|
|
1308
|
+
"view",
|
|
1309
|
+
...slug ? ["--repo", slug] : [],
|
|
1310
|
+
"--json",
|
|
1311
|
+
"defaultBranchRef",
|
|
1312
|
+
"--jq",
|
|
1313
|
+
".defaultBranchRef.name"
|
|
1314
|
+
],
|
|
1315
|
+
repoPath,
|
|
1316
|
+
{ reject: false, timeoutMs: 8e3 }
|
|
1317
|
+
);
|
|
1318
|
+
if (viaGh.exitCode === 0 && viaGh.stdout.trim()) {
|
|
1319
|
+
return viaGh.stdout.trim();
|
|
1320
|
+
}
|
|
1302
1321
|
}
|
|
1303
1322
|
for (const candidate of ["main", "master"]) {
|
|
1304
1323
|
const check = await git(
|
|
@@ -1439,10 +1458,21 @@ async function fetchPrMergeGate(cwd, selector, slug) {
|
|
|
1439
1458
|
"view",
|
|
1440
1459
|
selector,
|
|
1441
1460
|
"--json",
|
|
1442
|
-
"mergeable,mergeStateStatus,reviewDecision,baseRefName,url"
|
|
1461
|
+
"mergeable,mergeStateStatus,reviewDecision,baseRefName,url,isInMergeQueue"
|
|
1443
1462
|
];
|
|
1444
1463
|
if (slug) args.push("--repo", slug);
|
|
1445
|
-
|
|
1464
|
+
let { stdout, exitCode, stderr } = await gh(args, cwd, { reject: false });
|
|
1465
|
+
if (exitCode !== 0 && isUnknownJsonField(stderr, "isInMergeQueue")) {
|
|
1466
|
+
const retry = [
|
|
1467
|
+
"pr",
|
|
1468
|
+
"view",
|
|
1469
|
+
selector,
|
|
1470
|
+
"--json",
|
|
1471
|
+
"mergeable,mergeStateStatus,reviewDecision,baseRefName,url"
|
|
1472
|
+
];
|
|
1473
|
+
if (slug) retry.push("--repo", slug);
|
|
1474
|
+
({ stdout, exitCode, stderr } = await gh(retry, cwd, { reject: false }));
|
|
1475
|
+
}
|
|
1446
1476
|
if (exitCode !== 0 || !stdout.trim()) {
|
|
1447
1477
|
if (/no pull requests found/i.test(stderr)) return null;
|
|
1448
1478
|
return null;
|
|
@@ -1454,12 +1484,22 @@ async function fetchPrMergeGate(cwd, selector, slug) {
|
|
|
1454
1484
|
mergeStateStatus: typeof view.mergeStateStatus === "string" && view.mergeStateStatus ? view.mergeStateStatus : null,
|
|
1455
1485
|
reviewDecision: typeof view.reviewDecision === "string" && view.reviewDecision ? view.reviewDecision : null,
|
|
1456
1486
|
baseRefName: typeof view.baseRefName === "string" && view.baseRefName ? view.baseRefName : null,
|
|
1457
|
-
url: typeof view.url === "string" && view.url ? view.url : null
|
|
1487
|
+
url: typeof view.url === "string" && view.url ? view.url : null,
|
|
1488
|
+
isInMergeQueue: parseInMergeQueue(view)
|
|
1458
1489
|
};
|
|
1459
1490
|
} catch {
|
|
1460
1491
|
return null;
|
|
1461
1492
|
}
|
|
1462
1493
|
}
|
|
1494
|
+
function isUnknownJsonField(stderr, field) {
|
|
1495
|
+
return new RegExp(`unknown json field[^\\n]*${field}`, "i").test(stderr);
|
|
1496
|
+
}
|
|
1497
|
+
function parseInMergeQueue(view) {
|
|
1498
|
+
return prIsInMergeQueue({
|
|
1499
|
+
isInMergeQueue: view.isInMergeQueue === true,
|
|
1500
|
+
mergeStateStatus: typeof view.mergeStateStatus === "string" ? view.mergeStateStatus : null
|
|
1501
|
+
});
|
|
1502
|
+
}
|
|
1463
1503
|
async function detectLocalMergeConflicts(cwd, baseRefName) {
|
|
1464
1504
|
const baseName = (baseRefName?.trim() || await resolveDefaultBranch(cwd)).replace(
|
|
1465
1505
|
/^origin\//,
|
|
@@ -1520,7 +1560,8 @@ async function getPrChecks(cwd, selector) {
|
|
|
1520
1560
|
const mergeable = (gate?.mergeable ?? "").toUpperCase();
|
|
1521
1561
|
const mergeState = (gate?.mergeStateStatus ?? "").toUpperCase();
|
|
1522
1562
|
const alreadyConflicting = mergeable === "CONFLICTING" || mergeState === "DIRTY";
|
|
1523
|
-
const
|
|
1563
|
+
const inQueue = gate ? prIsInMergeQueue(gate) : false;
|
|
1564
|
+
const needsLocalProbe = !alreadyConflicting && !inQueue;
|
|
1524
1565
|
if (needsLocalProbe) {
|
|
1525
1566
|
try {
|
|
1526
1567
|
const local = await detectLocalMergeConflicts(cwd, gate?.baseRefName ?? null);
|
|
@@ -1531,7 +1572,8 @@ async function getPrChecks(cwd, selector) {
|
|
|
1531
1572
|
mergeStateStatus: "DIRTY",
|
|
1532
1573
|
reviewDecision: gate?.reviewDecision ?? null,
|
|
1533
1574
|
baseRefName: local.base,
|
|
1534
|
-
url: gate?.url ?? null
|
|
1575
|
+
url: gate?.url ?? null,
|
|
1576
|
+
isInMergeQueue: false
|
|
1535
1577
|
};
|
|
1536
1578
|
const ciFailed2 = ciChecks.some((c) => c.bucket === "fail");
|
|
1537
1579
|
const review2 = (gate.reviewDecision ?? "").toUpperCase();
|
|
@@ -1575,10 +1617,21 @@ async function getPrMeta(cwd, selector) {
|
|
|
1575
1617
|
"view",
|
|
1576
1618
|
selector,
|
|
1577
1619
|
"--json",
|
|
1578
|
-
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName"
|
|
1620
|
+
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus"
|
|
1579
1621
|
];
|
|
1580
1622
|
if (slug) viewArgs.push("--repo", slug);
|
|
1581
|
-
|
|
1623
|
+
let { stdout, exitCode, stderr } = await gh(viewArgs, cwd, { reject: false });
|
|
1624
|
+
if (exitCode !== 0 && isUnknownJsonField(stderr, "isInMergeQueue")) {
|
|
1625
|
+
const retry = [
|
|
1626
|
+
"pr",
|
|
1627
|
+
"view",
|
|
1628
|
+
selector,
|
|
1629
|
+
"--json",
|
|
1630
|
+
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus"
|
|
1631
|
+
];
|
|
1632
|
+
if (slug) retry.push("--repo", slug);
|
|
1633
|
+
({ stdout, exitCode, stderr } = await gh(retry, cwd, { reject: false }));
|
|
1634
|
+
}
|
|
1582
1635
|
if (exitCode !== 0 || !stdout.trim()) {
|
|
1583
1636
|
if (/no pull requests found/i.test(stderr)) return null;
|
|
1584
1637
|
return null;
|
|
@@ -1593,7 +1646,8 @@ async function getPrMeta(cwd, selector) {
|
|
|
1593
1646
|
isDraft: Boolean(view.isDraft),
|
|
1594
1647
|
reviewDecision: typeof view.reviewDecision === "string" && view.reviewDecision ? view.reviewDecision : null,
|
|
1595
1648
|
baseRefName: String(view.baseRefName ?? ""),
|
|
1596
|
-
headRefName: String(view.headRefName ?? "")
|
|
1649
|
+
headRefName: String(view.headRefName ?? ""),
|
|
1650
|
+
isInMergeQueue: parseInMergeQueue(view)
|
|
1597
1651
|
};
|
|
1598
1652
|
} catch {
|
|
1599
1653
|
return null;
|
|
@@ -1950,11 +2004,11 @@ async function listWorktrees(repoPath) {
|
|
|
1950
2004
|
return entries;
|
|
1951
2005
|
}
|
|
1952
2006
|
async function isDirty(worktreePath) {
|
|
1953
|
-
const { stdout } = await git(["status", "--porcelain"
|
|
2007
|
+
const { stdout } = await git(["status", "--porcelain"], worktreePath);
|
|
1954
2008
|
for (const line of stdout.split("\n")) {
|
|
1955
2009
|
if (!line.trim()) continue;
|
|
1956
2010
|
const rel = porcelainStatusPath(line);
|
|
1957
|
-
if (!rel || isSideboardScratchPath(rel)) continue;
|
|
2011
|
+
if (!rel || isSideboardScratchPath(rel) || rel === ".sideboard") continue;
|
|
1958
2012
|
return true;
|
|
1959
2013
|
}
|
|
1960
2014
|
return false;
|
|
@@ -6,23 +6,23 @@ import {
|
|
|
6
6
|
ensureCliTeamTracked,
|
|
7
7
|
ensureConnectedBrightsyTeamTokens,
|
|
8
8
|
loadBrightsyConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-VROPG6QF.js";
|
|
10
10
|
import {
|
|
11
11
|
isOrchestratorThread
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-DGPUAZA4.js";
|
|
13
13
|
import {
|
|
14
14
|
enrichPathWithNpmGlobalBin,
|
|
15
15
|
isConductorBundledCli,
|
|
16
16
|
resolveCommandBinarySync,
|
|
17
17
|
run,
|
|
18
18
|
withExportedPath
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-AE5VBOFE.js";
|
|
20
20
|
import {
|
|
21
21
|
claudeChromeEnabled,
|
|
22
22
|
loadAppSettings,
|
|
23
23
|
resolveAgentExecutable,
|
|
24
24
|
resolveClaudeExecutable
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-PTJJIQK7.js";
|
|
26
26
|
import {
|
|
27
27
|
appDataDir
|
|
28
28
|
} from "./chunk-7MV3RXSC.js";
|
|
@@ -580,7 +580,13 @@ var SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS = [
|
|
|
580
580
|
"mcp__sideboard__present_schema",
|
|
581
581
|
"mcp__sideboard__present_files",
|
|
582
582
|
"mcp__sideboard__ask_user",
|
|
583
|
-
"mcp__sideboard__present_plan"
|
|
583
|
+
"mcp__sideboard__present_plan",
|
|
584
|
+
"mcp__sideboard__list_teams",
|
|
585
|
+
"mcp__sideboard__slack_list_channels",
|
|
586
|
+
"mcp__sideboard__slack_list_users",
|
|
587
|
+
"mcp__sideboard__slack_search",
|
|
588
|
+
"mcp__sideboard__slack_read",
|
|
589
|
+
"mcp__sideboard__slack_post"
|
|
584
590
|
];
|
|
585
591
|
var brightsyMcpCommandCache = null;
|
|
586
592
|
async function resolveBrightsyMcpCommand() {
|
|
@@ -1000,7 +1006,7 @@ var claudeAdapter = {
|
|
|
1000
1006
|
);
|
|
1001
1007
|
}
|
|
1002
1008
|
const mode = permissionMode(thread);
|
|
1003
|
-
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-
|
|
1009
|
+
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-KHIFQUUM.js");
|
|
1004
1010
|
const isOrchestrator = isOrchestratorThread2(thread);
|
|
1005
1011
|
const injectedServers = await buildInjectedMcpServers({
|
|
1006
1012
|
includeSideboard: true,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
// src/store/private-file.ts
|
|
5
|
+
import { chmodSync, mkdirSync, writeFileSync } from "fs";
|
|
6
|
+
import { dirname } from "path";
|
|
7
|
+
var PRIVATE_FILE_MODE = 384;
|
|
8
|
+
function writePrivateFile(path, contents) {
|
|
9
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
10
|
+
writeFileSync(path, contents, { encoding: "utf8", mode: PRIVATE_FILE_MODE });
|
|
11
|
+
chmodOwnerOnly(path);
|
|
12
|
+
}
|
|
13
|
+
function chmodOwnerOnly(path) {
|
|
14
|
+
try {
|
|
15
|
+
chmodSync(path, PRIVATE_FILE_MODE);
|
|
16
|
+
} catch {
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
writePrivateFile,
|
|
22
|
+
chmodOwnerOnly
|
|
23
|
+
};
|