@sideboard-ai/core 0.1.191 → 0.1.193
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/{abletime-JFMBCSIQ.js → abletime-QHKWGTBY.js} +4 -3
- package/dist/{abletime-53T7G667.js → abletime-UX53JTIH.js} +4 -3
- package/dist/agents/cursor-runner.js +4 -4
- package/dist/{agents-DTPVTDB5.js → agents-MN4GSQTL.js} +19 -17
- package/dist/{agents-5OBZETUV.js → agents-OK5VD25T.js} +10 -8
- package/dist/{app-settings-663VQWUV.js → app-settings-LO7UFHQ6.js} +5 -2
- package/dist/{app-settings-74HBAAH7.js → app-settings-QYLNKRK4.js} +5 -2
- package/dist/branch-prefix-7F37FIPX.js +10 -0
- package/dist/branch-prefix-EVW2KHGQ.js +12 -0
- package/dist/{caffeinate-hold-SK2QISPE.js → caffeinate-hold-22VFDPSO.js} +2 -2
- package/dist/{caffeinate-hold-DBKMRZZO.js → caffeinate-hold-OK4JJ5PP.js} +2 -2
- package/dist/{chunk-GPSIZGEZ.js → chunk-3DX2T2KR.js} +181 -172
- package/dist/{chunk-HVIEYTUK.js → chunk-3OHR73VK.js} +1 -1
- package/dist/{chunk-VIODP5PT.js → chunk-4OVCJPVI.js} +13 -11
- package/dist/{chunk-UBQIELFS.js → chunk-4QJRH5DL.js} +1 -1
- package/dist/{chunk-AO35MGOE.js → chunk-4TYXWPAJ.js} +1 -1
- package/dist/chunk-64QSHOKV.js +869 -0
- package/dist/{chunk-FY64F2ZQ.js → chunk-7AJ7OZZF.js} +4 -4
- package/dist/{chunk-WLPXZFRE.js → chunk-7J72QJOM.js} +1 -1
- package/dist/chunk-7SNJMKD6.js +20 -0
- package/dist/{chunk-WXKXSZN4.js → chunk-BIKCWYRP.js} +16 -873
- package/dist/{chunk-J7LQVLFQ.js → chunk-BWRS6GAS.js} +19 -1
- package/dist/{chunk-GOZ6T3AG.js → chunk-CJFBSQIB.js} +1 -1
- package/dist/{chunk-GBWKMWUQ.js → chunk-EBPBGQ4P.js} +13 -13
- package/dist/{chunk-JTJHOYCU.js → chunk-EQNRWDLN.js} +10 -4
- package/dist/{chunk-5RRAKGPK.js → chunk-EQXXGOMD.js} +192 -182
- package/dist/{chunk-XXEIF2IL.js → chunk-HIX2VDRE.js} +13 -11
- package/dist/chunk-ILWQT2UN.js +55 -0
- package/dist/chunk-JTWKGOFI.js +23 -0
- package/dist/{chunk-TCQAFTSV.js → chunk-KJBYIIJU.js} +1 -1
- package/dist/{chunk-OKZFTOM2.js → chunk-KORE4WOF.js} +19 -1
- package/dist/{chunk-OLDZXO53.js → chunk-MQC2VA5U.js} +14 -14
- package/dist/{chunk-4M2AK3O5.js → chunk-O4BMPY5Y.js} +1 -1
- package/dist/chunk-PBEPPXMY.js +57 -0
- package/dist/{chunk-IEEAVWAP.js → chunk-PE337IM2.js} +7 -7
- package/dist/chunk-RCWHL4TK.js +866 -0
- package/dist/{chunk-EFVFB2AH.js → chunk-WFUDY6PC.js} +12 -5
- package/dist/{chunk-XBLN52RZ.js → chunk-XPKKCFRT.js} +9 -866
- package/dist/{chunk-OCQPTUR7.js → chunk-YWI3IBP2.js} +1 -1
- package/dist/{connected-teams-WOYCH7FR.js → connected-teams-PU4AMFNA.js} +2 -2
- package/dist/{connected-teams-ON2KIKQX.js → connected-teams-SYQQGCXD.js} +2 -2
- package/dist/{coordinator-prompt-LWKOL3AZ.js → coordinator-prompt-GXJIPWNA.js} +7 -5
- package/dist/{coordinator-prompt-MSC44OOM.js → coordinator-prompt-WB65HIZ3.js} +9 -7
- package/dist/{cursor-recover-NDMLLNYX.js → cursor-recover-DTQAUDGO.js} +2 -2
- package/dist/{cursor-recover-L5MD6MBO.js → cursor-recover-TXVTLAMA.js} +1 -1
- package/dist/github-DWROJOB7.js +11 -0
- package/dist/github-IIF7AQNO.js +9 -0
- package/dist/{global-workspace-6G5JJH2E.js → global-workspace-BZ6V6TEX.js} +7 -5
- package/dist/{global-workspace-XATJTV3N.js → global-workspace-MMK5UFUZ.js} +9 -7
- package/dist/index.cjs +332 -205
- package/dist/index.d.cts +53 -9
- package/dist/index.d.ts +53 -9
- package/dist/index.js +147 -136
- package/dist/mcp/run-stdio.cjs +316 -201
- package/dist/mcp/run-stdio.js +84 -85
- package/dist/{orchestrator-F3CXDBZB.js → orchestrator-4KI6VIFG.js} +16 -12
- package/dist/{orchestrator-2X6LYBQI.js → orchestrator-SFOT6Q6F.js} +15 -11
- package/dist/{paths-RRCLNSJB.js → paths-C2VERLAE.js} +1 -1
- package/dist/{paths-53TLA7VQ.js → paths-LOXCISLX.js} +1 -1
- package/dist/{thread-store-ZL6GDIDP.js → thread-store-CO77HV2K.js} +2 -2
- package/dist/{thread-store-RXXNSRVO.js → thread-store-M4B52FUS.js} +2 -2
- package/dist/{workspaces-LMFCRXTT.js → workspaces-ACMZMKPD.js} +7 -5
- package/dist/{workspaces-FWKPWSXV.js → workspaces-KPJS7GLY.js} +9 -7
- package/dist/{worktree-7LOSSD7G.js → worktree-6IEVF3GN.js} +15 -12
- package/dist/{worktree-LPWTX2NA.js → worktree-UW6DNBIE.js} +20 -17
- package/dist/worktree-labels-3XDS6O3U.js +22 -0
- package/dist/worktree-labels-PEDOJBMD.js +24 -0
- package/package.json +1 -1
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -269,9 +269,12 @@ function parseSettingsFile(path, source) {
|
|
|
269
269
|
const prompts = {
|
|
270
270
|
renameBranch: typeof promptsRaw.rename_branch === "string" ? promptsRaw.rename_branch : void 0,
|
|
271
271
|
createPr: typeof promptsRaw.create_pr === "string" ? promptsRaw.create_pr : void 0,
|
|
272
|
-
general: typeof promptsRaw.general === "string" ? promptsRaw.general : void 0
|
|
272
|
+
general: typeof promptsRaw.general === "string" ? promptsRaw.general : void 0,
|
|
273
|
+
resolveMergeConflicts: typeof promptsRaw.resolve_merge_conflicts === "string" ? promptsRaw.resolve_merge_conflicts : void 0
|
|
273
274
|
};
|
|
274
|
-
const hasPrompts = Boolean(
|
|
275
|
+
const hasPrompts = Boolean(
|
|
276
|
+
prompts.renameBranch || prompts.createPr || prompts.general || prompts.resolveMergeConflicts
|
|
277
|
+
);
|
|
275
278
|
return {
|
|
276
279
|
source,
|
|
277
280
|
setup,
|
|
@@ -297,9 +300,12 @@ function mergeSettings(base, overlay) {
|
|
|
297
300
|
const prompts = {
|
|
298
301
|
renameBranch: overlay.prompts?.renameBranch ?? base.prompts?.renameBranch,
|
|
299
302
|
createPr: overlay.prompts?.createPr ?? base.prompts?.createPr,
|
|
300
|
-
general: overlay.prompts?.general ?? base.prompts?.general
|
|
303
|
+
general: overlay.prompts?.general ?? base.prompts?.general,
|
|
304
|
+
resolveMergeConflicts: overlay.prompts?.resolveMergeConflicts ?? base.prompts?.resolveMergeConflicts
|
|
301
305
|
};
|
|
302
|
-
const hasPrompts = Boolean(
|
|
306
|
+
const hasPrompts = Boolean(
|
|
307
|
+
prompts.renameBranch || prompts.createPr || prompts.general || prompts.resolveMergeConflicts
|
|
308
|
+
);
|
|
303
309
|
return {
|
|
304
310
|
source: overlay.source,
|
|
305
311
|
setup: overlay.setup ?? base.setup,
|
|
@@ -2980,6 +2986,18 @@ var init_teams = __esm({
|
|
|
2980
2986
|
});
|
|
2981
2987
|
|
|
2982
2988
|
// src/git/worktree-labels.ts
|
|
2989
|
+
var worktree_labels_exports = {};
|
|
2990
|
+
__export(worktree_labels_exports, {
|
|
2991
|
+
branchDisplayLabel: () => branchDisplayLabel,
|
|
2992
|
+
isPlaceholderBranch: () => isPlaceholderBranch,
|
|
2993
|
+
normalizeWorktreePath: () => normalizeWorktreePath,
|
|
2994
|
+
threadDisplayLabel: () => threadDisplayLabel,
|
|
2995
|
+
ticketSlugForBranch: () => ticketSlugForBranch,
|
|
2996
|
+
worktreeDisplayLabel: () => worktreeDisplayLabel,
|
|
2997
|
+
worktreeDisplayLabelForGroup: () => worktreeDisplayLabelForGroup,
|
|
2998
|
+
worktreeNameFromPath: () => worktreeNameFromPath,
|
|
2999
|
+
worktreeSlugForTicket: () => worktreeSlugForTicket
|
|
3000
|
+
});
|
|
2983
3001
|
function normalizeWorktreePath(worktreePath) {
|
|
2984
3002
|
const trimmed = (worktreePath ?? "").replace(/\/+$/, "") || "/";
|
|
2985
3003
|
const absolute = trimmed.startsWith("/");
|
|
@@ -3434,6 +3452,32 @@ var init_secret_vault = __esm({
|
|
|
3434
3452
|
}
|
|
3435
3453
|
});
|
|
3436
3454
|
|
|
3455
|
+
// src/git/branch-prefix.ts
|
|
3456
|
+
var branch_prefix_exports = {};
|
|
3457
|
+
__export(branch_prefix_exports, {
|
|
3458
|
+
examplePrefixedBranch: () => examplePrefixedBranch,
|
|
3459
|
+
resolveGitBranchPrefix: () => resolveGitBranchPrefix,
|
|
3460
|
+
sanitizeGitBranchPrefix: () => sanitizeGitBranchPrefix
|
|
3461
|
+
});
|
|
3462
|
+
function sanitizeGitBranchPrefix(raw) {
|
|
3463
|
+
const first = (raw ?? "").trim().replace(/^\/+|\/+$/g, "").split("/")[0] ?? "";
|
|
3464
|
+
const slug = first.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 39);
|
|
3465
|
+
return slug || null;
|
|
3466
|
+
}
|
|
3467
|
+
function resolveGitBranchPrefix(opts) {
|
|
3468
|
+
return sanitizeGitBranchPrefix(opts.setting) ?? sanitizeGitBranchPrefix(opts.githubLogin);
|
|
3469
|
+
}
|
|
3470
|
+
function examplePrefixedBranch(prefix, ticket) {
|
|
3471
|
+
const head = sanitizeGitBranchPrefix(prefix);
|
|
3472
|
+
const slug = ticket?.trim() ? `${ticket.trim()}-eng-fix-thing` : "bb-1234-eng-fix-thing";
|
|
3473
|
+
return head ? `${head}/${slug}` : slug;
|
|
3474
|
+
}
|
|
3475
|
+
var init_branch_prefix = __esm({
|
|
3476
|
+
"src/git/branch-prefix.ts"() {
|
|
3477
|
+
"use strict";
|
|
3478
|
+
}
|
|
3479
|
+
});
|
|
3480
|
+
|
|
3437
3481
|
// src/store/issue-source-labels.ts
|
|
3438
3482
|
function issueSourceLabel(source) {
|
|
3439
3483
|
if (source && source in ISSUE_SOURCE_LABELS) {
|
|
@@ -3502,6 +3546,7 @@ __export(app_settings_exports, {
|
|
|
3502
3546
|
getGithubPat: () => getGithubPat,
|
|
3503
3547
|
getIssueSource: () => getIssueSource,
|
|
3504
3548
|
getLinearApiKey: () => getLinearApiKey,
|
|
3549
|
+
gitBranchPrefixSetting: () => gitBranchPrefixSetting,
|
|
3505
3550
|
harnessEnvKey: () => harnessEnvKey,
|
|
3506
3551
|
isAbleTimeConnected: () => isAbleTimeConnected,
|
|
3507
3552
|
isIssueSourceConnected: () => isIssueSourceConnected,
|
|
@@ -3877,6 +3922,10 @@ function normalizeAdvanced(raw) {
|
|
|
3877
3922
|
if (typeof source.autoRenameBranch === "boolean") {
|
|
3878
3923
|
out.autoRenameBranch = source.autoRenameBranch;
|
|
3879
3924
|
}
|
|
3925
|
+
if (typeof source.branchPrefix === "string") {
|
|
3926
|
+
const prefix = sanitizeGitBranchPrefix(source.branchPrefix);
|
|
3927
|
+
if (prefix) out.branchPrefix = prefix;
|
|
3928
|
+
}
|
|
3880
3929
|
if (typeof source.autoRunAfterSetup === "boolean") {
|
|
3881
3930
|
out.autoRunAfterSetup = source.autoRunAfterSetup;
|
|
3882
3931
|
}
|
|
@@ -4730,6 +4779,13 @@ function updateAdvancedSettings(patch) {
|
|
|
4730
4779
|
if (typeof patch.autoRenameBranch === "boolean") {
|
|
4731
4780
|
advanced.autoRenameBranch = patch.autoRenameBranch;
|
|
4732
4781
|
}
|
|
4782
|
+
if (patch.branchPrefix === null || patch.branchPrefix === "") {
|
|
4783
|
+
delete advanced.branchPrefix;
|
|
4784
|
+
} else if (typeof patch.branchPrefix === "string") {
|
|
4785
|
+
const prefix = sanitizeGitBranchPrefix(patch.branchPrefix);
|
|
4786
|
+
if (prefix) advanced.branchPrefix = prefix;
|
|
4787
|
+
else delete advanced.branchPrefix;
|
|
4788
|
+
}
|
|
4733
4789
|
if (typeof patch.autoRunAfterSetup === "boolean") {
|
|
4734
4790
|
advanced.autoRunAfterSetup = patch.autoRunAfterSetup;
|
|
4735
4791
|
}
|
|
@@ -4790,6 +4846,9 @@ function updateAdvancedSettings(patch) {
|
|
|
4790
4846
|
function autoRenameBranchEnabled(settings = loadAppSettings()) {
|
|
4791
4847
|
return settings.advanced.autoRenameBranch !== false;
|
|
4792
4848
|
}
|
|
4849
|
+
function gitBranchPrefixSetting(settings = loadAppSettings()) {
|
|
4850
|
+
return sanitizeGitBranchPrefix(settings.advanced.branchPrefix);
|
|
4851
|
+
}
|
|
4793
4852
|
function autoRunAfterSetupEnabled(settings = loadAppSettings()) {
|
|
4794
4853
|
return Boolean(settings.advanced.autoRunAfterSetup);
|
|
4795
4854
|
}
|
|
@@ -4935,6 +4994,7 @@ var init_app_settings = __esm({
|
|
|
4935
4994
|
init_paths();
|
|
4936
4995
|
init_private_file();
|
|
4937
4996
|
init_secret_vault();
|
|
4997
|
+
init_branch_prefix();
|
|
4938
4998
|
init_issue_source_labels();
|
|
4939
4999
|
init_account_profile();
|
|
4940
5000
|
HARNESS_ENV_KEYS = {
|
|
@@ -7973,8 +8033,8 @@ var init_coordinator_prompt = __esm({
|
|
|
7973
8033
|
"- start_board_card \u2014 same as create_thread for a ticket/PR/named branch (attaches issue text when resolvable). Then send_to_thread.",
|
|
7974
8034
|
"- 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.",
|
|
7975
8035
|
"- 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.",
|
|
7976
|
-
"- send_to_thread \u2014
|
|
7977
|
-
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or
|
|
8036
|
+
"- send_to_thread \u2014 steer a prompt (start/continue a chat turn; Settings \u2192 Follow-up, default steer: interrupt and start now). force_stop: true only to replace a wrong in-flight request and clear the inbox \u2014 never to check in, resume after a halt notice, or because wait_for_turn returned stillRunning (that interrupts the child mid-thought)",
|
|
8037
|
+
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send_to_thread a check-in (that steers / interrupts). Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. If stillRunning stays true across many waits with the same lastActivityAt, the child is stuck \u2014 tell the user; do not invent a gate. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
|
|
7978
8038
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
7979
8039
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
7980
8040
|
"Setup / run:",
|
|
@@ -7984,7 +8044,7 @@ var init_coordinator_prompt = __esm({
|
|
|
7984
8044
|
"- get_diff \u2014 compact diff summary",
|
|
7985
8045
|
"- get_pr_checks \u2014 snapshot of a worktree thread's PR checks (null = no PR). Use this to inspect status. If the user gave a goal, the worktree agent watches with `gh pr checks --watch` \u2014 do not poll for the human.",
|
|
7986
8046
|
'- request_review \u2014 open a Review chat tab on a worktree thread (attaches .claude/skills/review/SKILL.md when present, else .context/review.md copied from .sideboard/review.md / stock; sends "Review changes in this workspace."); then wait_for_turn (loop while stillRunning) / get_turn_result on the returned id. The review stays in that chat so they can read it and type next steps \u2014 do not tell the child to comment or update the PR or ticket.',
|
|
7987
|
-
"- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge
|
|
8047
|
+
"- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge \u2014 same prompts as the desktop git buttons (Resolve, Create PR, \u2026). Always steers the worktree agent; then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If the user gave a goal (Greptile 5/5, CI green), send_to_thread that goal so the worktree agent enters the watch-fix-push loop \u2014 do not tell the human to poll.",
|
|
7988
8048
|
'- 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.',
|
|
7989
8049
|
'- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Ready for review.", "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.',
|
|
7990
8050
|
"Process guides:",
|
|
@@ -12431,87 +12491,6 @@ var init_spawn = __esm({
|
|
|
12431
12491
|
}
|
|
12432
12492
|
});
|
|
12433
12493
|
|
|
12434
|
-
// src/land/pr-metadata.ts
|
|
12435
|
-
function looksGeneric(title) {
|
|
12436
|
-
const t = title.trim();
|
|
12437
|
-
if (!t) return true;
|
|
12438
|
-
if (t.length < 4) return true;
|
|
12439
|
-
if (GENERIC_TITLE_RE.test(t)) return true;
|
|
12440
|
-
if (!/[\s:/\-_]/.test(t) && t.length <= 24) return true;
|
|
12441
|
-
return false;
|
|
12442
|
-
}
|
|
12443
|
-
function truncateTitle(title, max = 72) {
|
|
12444
|
-
const t = title.trim().replace(/\s+/g, " ");
|
|
12445
|
-
if (t.length <= max) return t;
|
|
12446
|
-
return `${t.slice(0, max - 1).trimEnd()}\u2026`;
|
|
12447
|
-
}
|
|
12448
|
-
function titleFromPaths(paths) {
|
|
12449
|
-
if (paths.length === 0) return null;
|
|
12450
|
-
const top = paths.slice(0, 3).map((p) => p.replace(/\/$/, ""));
|
|
12451
|
-
if (paths.length === 1) return truncateTitle(`Update ${top[0]}`);
|
|
12452
|
-
if (paths.length <= 3) return truncateTitle(`Update ${top.join(", ")}`);
|
|
12453
|
-
return truncateTitle(`Update ${top[0]} and ${paths.length - 1} more files`);
|
|
12454
|
-
}
|
|
12455
|
-
async function suggestPrMetadata(worktreePath, opts) {
|
|
12456
|
-
const [{ stdout: logOut }, { stdout: nameStatus }, { stdout: statOut }] = await Promise.all([
|
|
12457
|
-
git(["log", "--format=%s", `${opts.base}..HEAD`], worktreePath, {
|
|
12458
|
-
reject: false
|
|
12459
|
-
}),
|
|
12460
|
-
git(["diff", "--name-only", `${opts.base}...HEAD`], worktreePath, {
|
|
12461
|
-
reject: false
|
|
12462
|
-
}),
|
|
12463
|
-
git(["diff", "--stat", `${opts.base}...HEAD`], worktreePath, {
|
|
12464
|
-
reject: false
|
|
12465
|
-
})
|
|
12466
|
-
]);
|
|
12467
|
-
const { stdout: dirtyNames } = await git(["diff", "--name-only", "HEAD"], worktreePath, {
|
|
12468
|
-
reject: false
|
|
12469
|
-
});
|
|
12470
|
-
const { stdout: untracked } = await git(
|
|
12471
|
-
["ls-files", "--others", "--exclude-standard"],
|
|
12472
|
-
worktreePath,
|
|
12473
|
-
{ reject: false }
|
|
12474
|
-
);
|
|
12475
|
-
const subjects = logOut.split("\n").map((s) => s.trim()).filter(Boolean);
|
|
12476
|
-
const paths = [
|
|
12477
|
-
...new Set(
|
|
12478
|
-
[...nameStatus.split("\n"), ...dirtyNames.split("\n"), ...untracked.split("\n")].map((p) => p.trim()).filter(Boolean)
|
|
12479
|
-
)
|
|
12480
|
-
].sort((a, b) => a.localeCompare(b));
|
|
12481
|
-
const meaningfulSubjects = subjects.filter((s) => !looksGeneric(s));
|
|
12482
|
-
const fallback = opts.fallbackTitle?.trim() || null;
|
|
12483
|
-
const fallbackOk = fallback && !looksGeneric(fallback) ? fallback : null;
|
|
12484
|
-
const title = truncateTitle(
|
|
12485
|
-
meaningfulSubjects[0] ?? fallbackOk ?? titleFromPaths(paths) ?? "Sideboard changes"
|
|
12486
|
-
);
|
|
12487
|
-
const commitMessage = meaningfulSubjects[0] ?? fallbackOk ?? titleFromPaths(paths) ?? `sideboard: ${title}`;
|
|
12488
|
-
const summaryLines = meaningfulSubjects.length > 0 ? meaningfulSubjects.slice(0, 12).map((s) => `- ${s}`) : paths.slice(0, 20).map((p) => `- \`${p}\``);
|
|
12489
|
-
const bodyParts = [
|
|
12490
|
-
"## Summary",
|
|
12491
|
-
summaryLines.length > 0 ? summaryLines.join("\n") : "- Changes landed via Sideboard.",
|
|
12492
|
-
""
|
|
12493
|
-
];
|
|
12494
|
-
if (statOut.trim()) {
|
|
12495
|
-
bodyParts.push("## Diff", "```", statOut.trim(), "```", "");
|
|
12496
|
-
}
|
|
12497
|
-
if (opts.sourceLabel) {
|
|
12498
|
-
bodyParts.push(`_Landed via Sideboard from ${opts.sourceLabel}_`);
|
|
12499
|
-
}
|
|
12500
|
-
return {
|
|
12501
|
-
title,
|
|
12502
|
-
body: bodyParts.join("\n").trim() + "\n",
|
|
12503
|
-
commitMessage: truncateTitle(commitMessage, 72)
|
|
12504
|
-
};
|
|
12505
|
-
}
|
|
12506
|
-
var GENERIC_TITLE_RE;
|
|
12507
|
-
var init_pr_metadata = __esm({
|
|
12508
|
-
"src/land/pr-metadata.ts"() {
|
|
12509
|
-
"use strict";
|
|
12510
|
-
init_run();
|
|
12511
|
-
GENERIC_TITLE_RE = /^(sideboard:|thread\/|wip\b|tmp\b|update\b|changes?\b|misc\b|stuff\b)/i;
|
|
12512
|
-
}
|
|
12513
|
-
});
|
|
12514
|
-
|
|
12515
12494
|
// src/git/agent-git-actions.ts
|
|
12516
12495
|
function agentGitPrompt(action, opts) {
|
|
12517
12496
|
switch (action) {
|
|
@@ -12532,6 +12511,19 @@ function agentGitPrompt(action, opts) {
|
|
|
12532
12511
|
return "Merge PR.";
|
|
12533
12512
|
}
|
|
12534
12513
|
}
|
|
12514
|
+
function resolveSidebarGitPrompt(action, opts) {
|
|
12515
|
+
if (action === "create-pr" || action === "create-draft" || action === "create-web") {
|
|
12516
|
+
const custom = opts?.createPr?.trim();
|
|
12517
|
+
if (custom) return custom;
|
|
12518
|
+
return agentGitPrompt(action === "create-pr" ? "create-draft" : action);
|
|
12519
|
+
}
|
|
12520
|
+
if (action === "resolve-conflicts") {
|
|
12521
|
+
const custom = opts?.resolveMergeConflicts?.trim();
|
|
12522
|
+
if (custom) return custom;
|
|
12523
|
+
return agentGitPrompt("resolve-conflicts", opts);
|
|
12524
|
+
}
|
|
12525
|
+
return agentGitPrompt(action, opts);
|
|
12526
|
+
}
|
|
12535
12527
|
function gitActionExpansion(action, base) {
|
|
12536
12528
|
switch (action) {
|
|
12537
12529
|
case "commit-push":
|
|
@@ -14303,8 +14295,8 @@ var init_wait_for_turn = __esm({
|
|
|
14303
14295
|
"src/mcp/wait-for-turn.ts"() {
|
|
14304
14296
|
"use strict";
|
|
14305
14297
|
MCP_WAIT_FOR_TURN_MAX_MS = 45e3;
|
|
14306
|
-
MCP_WAIT_STILL_RUNNING_HINT = "Child is still working. Call wait_for_turn again. Do not
|
|
14307
|
-
MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u2014 it has not started yet. Call wait_for_turn again. Do not
|
|
14298
|
+
MCP_WAIT_STILL_RUNNING_HINT = "Child is still working. Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts) or assume a hang while progress is updating.";
|
|
14299
|
+
MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u2014 it has not started yet. Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts), force_stop, or assume it failed to start.";
|
|
14308
14300
|
MCP_WAIT_STOPPED_HINT = "Child was stopped before the turn finished. Do not treat this as success. send_to_thread to resume, or tell the user.";
|
|
14309
14301
|
MCP_WAIT_BROKEN_HINT = "Child worktree is broken (missing on disk). Tell the user \u2014 do not treat this as success.";
|
|
14310
14302
|
MCP_WAIT_ERROR_HINT = "Child turn failed. lastError/text is the failure \u2014 switch agent, tell the user, or retry. Do not treat empty text as success.";
|
|
@@ -17785,6 +17777,87 @@ var init_diff = __esm({
|
|
|
17785
17777
|
}
|
|
17786
17778
|
});
|
|
17787
17779
|
|
|
17780
|
+
// src/land/pr-metadata.ts
|
|
17781
|
+
function looksGeneric(title) {
|
|
17782
|
+
const t = title.trim();
|
|
17783
|
+
if (!t) return true;
|
|
17784
|
+
if (t.length < 4) return true;
|
|
17785
|
+
if (GENERIC_TITLE_RE.test(t)) return true;
|
|
17786
|
+
if (!/[\s:/\-_]/.test(t) && t.length <= 24) return true;
|
|
17787
|
+
return false;
|
|
17788
|
+
}
|
|
17789
|
+
function truncateTitle(title, max = 72) {
|
|
17790
|
+
const t = title.trim().replace(/\s+/g, " ");
|
|
17791
|
+
if (t.length <= max) return t;
|
|
17792
|
+
return `${t.slice(0, max - 1).trimEnd()}\u2026`;
|
|
17793
|
+
}
|
|
17794
|
+
function titleFromPaths(paths) {
|
|
17795
|
+
if (paths.length === 0) return null;
|
|
17796
|
+
const top = paths.slice(0, 3).map((p) => p.replace(/\/$/, ""));
|
|
17797
|
+
if (paths.length === 1) return truncateTitle(`Update ${top[0]}`);
|
|
17798
|
+
if (paths.length <= 3) return truncateTitle(`Update ${top.join(", ")}`);
|
|
17799
|
+
return truncateTitle(`Update ${top[0]} and ${paths.length - 1} more files`);
|
|
17800
|
+
}
|
|
17801
|
+
async function suggestPrMetadata(worktreePath, opts) {
|
|
17802
|
+
const [{ stdout: logOut }, { stdout: nameStatus }, { stdout: statOut }] = await Promise.all([
|
|
17803
|
+
git(["log", "--format=%s", `${opts.base}..HEAD`], worktreePath, {
|
|
17804
|
+
reject: false
|
|
17805
|
+
}),
|
|
17806
|
+
git(["diff", "--name-only", `${opts.base}...HEAD`], worktreePath, {
|
|
17807
|
+
reject: false
|
|
17808
|
+
}),
|
|
17809
|
+
git(["diff", "--stat", `${opts.base}...HEAD`], worktreePath, {
|
|
17810
|
+
reject: false
|
|
17811
|
+
})
|
|
17812
|
+
]);
|
|
17813
|
+
const { stdout: dirtyNames } = await git(["diff", "--name-only", "HEAD"], worktreePath, {
|
|
17814
|
+
reject: false
|
|
17815
|
+
});
|
|
17816
|
+
const { stdout: untracked } = await git(
|
|
17817
|
+
["ls-files", "--others", "--exclude-standard"],
|
|
17818
|
+
worktreePath,
|
|
17819
|
+
{ reject: false }
|
|
17820
|
+
);
|
|
17821
|
+
const subjects = logOut.split("\n").map((s) => s.trim()).filter(Boolean);
|
|
17822
|
+
const paths = [
|
|
17823
|
+
...new Set(
|
|
17824
|
+
[...nameStatus.split("\n"), ...dirtyNames.split("\n"), ...untracked.split("\n")].map((p) => p.trim()).filter(Boolean)
|
|
17825
|
+
)
|
|
17826
|
+
].sort((a, b) => a.localeCompare(b));
|
|
17827
|
+
const meaningfulSubjects = subjects.filter((s) => !looksGeneric(s));
|
|
17828
|
+
const fallback = opts.fallbackTitle?.trim() || null;
|
|
17829
|
+
const fallbackOk = fallback && !looksGeneric(fallback) ? fallback : null;
|
|
17830
|
+
const title = truncateTitle(
|
|
17831
|
+
meaningfulSubjects[0] ?? fallbackOk ?? titleFromPaths(paths) ?? "Sideboard changes"
|
|
17832
|
+
);
|
|
17833
|
+
const commitMessage = meaningfulSubjects[0] ?? fallbackOk ?? titleFromPaths(paths) ?? `sideboard: ${title}`;
|
|
17834
|
+
const summaryLines = meaningfulSubjects.length > 0 ? meaningfulSubjects.slice(0, 12).map((s) => `- ${s}`) : paths.slice(0, 20).map((p) => `- \`${p}\``);
|
|
17835
|
+
const bodyParts = [
|
|
17836
|
+
"## Summary",
|
|
17837
|
+
summaryLines.length > 0 ? summaryLines.join("\n") : "- Changes landed via Sideboard.",
|
|
17838
|
+
""
|
|
17839
|
+
];
|
|
17840
|
+
if (statOut.trim()) {
|
|
17841
|
+
bodyParts.push("## Diff", "```", statOut.trim(), "```", "");
|
|
17842
|
+
}
|
|
17843
|
+
if (opts.sourceLabel) {
|
|
17844
|
+
bodyParts.push(`_Landed via Sideboard from ${opts.sourceLabel}_`);
|
|
17845
|
+
}
|
|
17846
|
+
return {
|
|
17847
|
+
title,
|
|
17848
|
+
body: bodyParts.join("\n").trim() + "\n",
|
|
17849
|
+
commitMessage: truncateTitle(commitMessage, 72)
|
|
17850
|
+
};
|
|
17851
|
+
}
|
|
17852
|
+
var GENERIC_TITLE_RE;
|
|
17853
|
+
var init_pr_metadata = __esm({
|
|
17854
|
+
"src/land/pr-metadata.ts"() {
|
|
17855
|
+
"use strict";
|
|
17856
|
+
init_run();
|
|
17857
|
+
GENERIC_TITLE_RE = /^(sideboard:|thread\/|wip\b|tmp\b|update\b|changes?\b|misc\b|stuff\b)/i;
|
|
17858
|
+
}
|
|
17859
|
+
});
|
|
17860
|
+
|
|
17788
17861
|
// src/land/land.ts
|
|
17789
17862
|
async function previewLand(thread) {
|
|
17790
17863
|
if (thread.sourceIsFork) {
|
|
@@ -18315,13 +18388,14 @@ function formatRenameBranchDirective(thread, opts) {
|
|
|
18315
18388
|
if (!isPlaceholderBranch(thread.branchName, thread.worktreePath)) return null;
|
|
18316
18389
|
const dir = worktreeNameFromPath(thread.worktreePath);
|
|
18317
18390
|
const ticket = thread.sourceType === "ticket" ? ticketSlugForBranch(thread.sourceRef ?? "") : null;
|
|
18318
|
-
const
|
|
18391
|
+
const prefix = sanitizeGitBranchPrefix(opts?.branchPrefix);
|
|
18392
|
+
const example = examplePrefixedBranch(prefix, ticket);
|
|
18393
|
+
const shape = prefix ? `\`${prefix}/<ticket-or-task>-<short-kebab-description>\`` : "`<ticket-or-task>-<short-kebab-description>`";
|
|
18319
18394
|
const lines = [
|
|
18320
18395
|
"Branch naming (do this early in the turn):",
|
|
18321
18396
|
`- Current branch \`${thread.branchName}\` is a temporary placeholder. The worktree folder \`${dir}\` is a stable nickname \u2014 do not rename or leave that directory.`,
|
|
18322
|
-
`- Rename the git branch to
|
|
18397
|
+
`- Rename the git branch to ${shape}, e.g. \`${example}\`:`,
|
|
18323
18398
|
" `git branch -m <new-name>`",
|
|
18324
|
-
"- Prefer Conventional Commits style prefixes when they fit (`fix/`, `feat/`, `chore/`, `docs/`).",
|
|
18325
18399
|
...ticket ? [
|
|
18326
18400
|
`- Keep ticket \`${ticket}\` in the new branch name so the issue stays findable.`
|
|
18327
18401
|
] : [],
|
|
@@ -18505,6 +18579,7 @@ var init_instructions = __esm({
|
|
|
18505
18579
|
import_node_fs48 = require("fs");
|
|
18506
18580
|
import_node_path45 = require("path");
|
|
18507
18581
|
init_git_auth_mode();
|
|
18582
|
+
init_branch_prefix();
|
|
18508
18583
|
init_worktree_labels();
|
|
18509
18584
|
init_detached_job_path();
|
|
18510
18585
|
PR_GOAL_RE = /greptile|\bci\b.*\b(green|pass)|checks?\s+(pass|green)|until\s+.*\b(pass|green|merge|clean)|\bfix ci\b|watch[- ]fix[- ]push/i;
|
|
@@ -19337,6 +19412,64 @@ var init_schedule_runner = __esm({
|
|
|
19337
19412
|
}
|
|
19338
19413
|
});
|
|
19339
19414
|
|
|
19415
|
+
// src/integrations/github.ts
|
|
19416
|
+
var github_exports = {};
|
|
19417
|
+
__export(github_exports, {
|
|
19418
|
+
getGitHubStatus: () => getGitHubStatus,
|
|
19419
|
+
refreshGitHubAuth: () => refreshGitHubAuth
|
|
19420
|
+
});
|
|
19421
|
+
async function getGitHubStatus() {
|
|
19422
|
+
const which = await run("which", ["gh"], { reject: false });
|
|
19423
|
+
if (which.exitCode !== 0 || !which.stdout.trim()) {
|
|
19424
|
+
return {
|
|
19425
|
+
connected: false,
|
|
19426
|
+
login: null,
|
|
19427
|
+
hosts: [],
|
|
19428
|
+
reason: "gh CLI not found on PATH"
|
|
19429
|
+
};
|
|
19430
|
+
}
|
|
19431
|
+
const loginResult = await run(
|
|
19432
|
+
"gh",
|
|
19433
|
+
["api", "user", "--jq", ".login"],
|
|
19434
|
+
{ reject: false }
|
|
19435
|
+
);
|
|
19436
|
+
if (loginResult.exitCode === 0 && loginResult.stdout.trim()) {
|
|
19437
|
+
return {
|
|
19438
|
+
connected: true,
|
|
19439
|
+
login: loginResult.stdout.trim(),
|
|
19440
|
+
hosts: ["github.com"],
|
|
19441
|
+
reason: null
|
|
19442
|
+
};
|
|
19443
|
+
}
|
|
19444
|
+
const status = await run("gh", ["auth", "status"], { reject: false });
|
|
19445
|
+
const text7 = `${status.stdout}
|
|
19446
|
+
${status.stderr}`;
|
|
19447
|
+
const loginMatch = text7.match(/Logged in to ([^\s]+) account (\S+)/i) ?? text7.match(/Logged in to ([^\s]+) as (\S+)/i);
|
|
19448
|
+
if (loginMatch) {
|
|
19449
|
+
return {
|
|
19450
|
+
connected: true,
|
|
19451
|
+
login: loginMatch[2].replace(/['"]/g, ""),
|
|
19452
|
+
hosts: [loginMatch[1]],
|
|
19453
|
+
reason: null
|
|
19454
|
+
};
|
|
19455
|
+
}
|
|
19456
|
+
return {
|
|
19457
|
+
connected: false,
|
|
19458
|
+
login: null,
|
|
19459
|
+
hosts: [],
|
|
19460
|
+
reason: status.stderr.trim() || status.stdout.trim() || "Not logged in to GitHub (run: gh auth login)"
|
|
19461
|
+
};
|
|
19462
|
+
}
|
|
19463
|
+
async function refreshGitHubAuth() {
|
|
19464
|
+
return getGitHubStatus();
|
|
19465
|
+
}
|
|
19466
|
+
var init_github = __esm({
|
|
19467
|
+
"src/integrations/github.ts"() {
|
|
19468
|
+
"use strict";
|
|
19469
|
+
init_run();
|
|
19470
|
+
}
|
|
19471
|
+
});
|
|
19472
|
+
|
|
19340
19473
|
// src/agents/cursor-store.ts
|
|
19341
19474
|
function cursorSdkStoreDir(threadId) {
|
|
19342
19475
|
const root = (0, import_node_path49.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
|
|
@@ -19459,6 +19592,7 @@ __export(orchestrator_exports, {
|
|
|
19459
19592
|
Orchestrator: () => Orchestrator,
|
|
19460
19593
|
getOrchestrator: () => getOrchestrator,
|
|
19461
19594
|
isPidAlive: () => isPidAlive,
|
|
19595
|
+
resolveOrchChildFollowUp: () => resolveOrchChildFollowUp,
|
|
19462
19596
|
resolveSendFollowUp: () => resolveSendFollowUp,
|
|
19463
19597
|
startOrchestration: () => startOrchestration,
|
|
19464
19598
|
waitForPidExit: () => waitForPidExit
|
|
@@ -19489,6 +19623,10 @@ function resolveSendFollowUp(thread, requested) {
|
|
|
19489
19623
|
if (requested === "steer" || requested === "queue") return requested;
|
|
19490
19624
|
return isOrchestratorThread(thread) ? followUpBehavior() : "queue";
|
|
19491
19625
|
}
|
|
19626
|
+
function resolveOrchChildFollowUp(requested) {
|
|
19627
|
+
if (requested === "steer" || requested === "queue") return requested;
|
|
19628
|
+
return followUpBehavior();
|
|
19629
|
+
}
|
|
19492
19630
|
function writeLiveStatus(threadId, status, lastError) {
|
|
19493
19631
|
const latest = readThread(threadId);
|
|
19494
19632
|
if (!latest || latest.status === "archived") return latest;
|
|
@@ -19571,7 +19709,6 @@ var init_orchestrator = __esm({
|
|
|
19571
19709
|
init_spawn();
|
|
19572
19710
|
init_agents();
|
|
19573
19711
|
init_worktree();
|
|
19574
|
-
init_pr_metadata();
|
|
19575
19712
|
init_stack();
|
|
19576
19713
|
init_agent_git_actions();
|
|
19577
19714
|
init_pr_merge_archive();
|
|
@@ -20359,7 +20496,7 @@ var init_orchestrator = __esm({
|
|
|
20359
20496
|
}
|
|
20360
20497
|
const isBrightsy = fresh.agent === "brightsy";
|
|
20361
20498
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
20362
|
-
const { autoRenameBranchEnabled: autoRenameBranchEnabled2, getGithubGitAuthMode: getGithubGitAuthMode2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
20499
|
+
const { autoRenameBranchEnabled: autoRenameBranchEnabled2, getGithubGitAuthMode: getGithubGitAuthMode2, gitBranchPrefixSetting: gitBranchPrefixSetting2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
20363
20500
|
const gitAuthMode = getGithubGitAuthMode2();
|
|
20364
20501
|
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
20365
20502
|
githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
|
|
@@ -20395,9 +20532,26 @@ var init_orchestrator = __esm({
|
|
|
20395
20532
|
}
|
|
20396
20533
|
}
|
|
20397
20534
|
const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
|
|
20398
|
-
|
|
20399
|
-
|
|
20400
|
-
|
|
20535
|
+
let renameBranchDirective = null;
|
|
20536
|
+
if (!isBrightsy && !isOrchestration && autoRenameBranchEnabled2()) {
|
|
20537
|
+
const { isPlaceholderBranch: isPlaceholderBranch2 } = await Promise.resolve().then(() => (init_worktree_labels(), worktree_labels_exports));
|
|
20538
|
+
let githubLogin = null;
|
|
20539
|
+
if (isPlaceholderBranch2(fresh.branchName, fresh.worktreePath) && !gitBranchPrefixSetting2()) {
|
|
20540
|
+
try {
|
|
20541
|
+
const { getGitHubStatus: getGitHubStatus2 } = await Promise.resolve().then(() => (init_github(), github_exports));
|
|
20542
|
+
githubLogin = (await getGitHubStatus2()).login;
|
|
20543
|
+
} catch {
|
|
20544
|
+
}
|
|
20545
|
+
}
|
|
20546
|
+
const { resolveGitBranchPrefix: resolveGitBranchPrefix2 } = await Promise.resolve().then(() => (init_branch_prefix(), branch_prefix_exports));
|
|
20547
|
+
renameBranchDirective = formatRenameBranchDirective(fresh, {
|
|
20548
|
+
customPrompt: settings?.prompts?.renameBranch,
|
|
20549
|
+
branchPrefix: resolveGitBranchPrefix2({
|
|
20550
|
+
setting: gitBranchPrefixSetting2(),
|
|
20551
|
+
githubLogin
|
|
20552
|
+
})
|
|
20553
|
+
});
|
|
20554
|
+
}
|
|
20401
20555
|
let seed = null;
|
|
20402
20556
|
if (!fresh.sessionId) {
|
|
20403
20557
|
const prior = fresh.messages.slice(0, -1);
|
|
@@ -21427,9 +21581,9 @@ var init_orchestrator = __esm({
|
|
|
21427
21581
|
return tab;
|
|
21428
21582
|
}
|
|
21429
21583
|
/**
|
|
21430
|
-
* Desktop git buttons + MCP `ask_git`.
|
|
21431
|
-
*
|
|
21432
|
-
*
|
|
21584
|
+
* Desktop git buttons + MCP `ask_git`. Always queues the worktree agent
|
|
21585
|
+
* with the action prompt (same path as Resolve). Repository `[prompts]`
|
|
21586
|
+
* overrides apply when set.
|
|
21433
21587
|
*/
|
|
21434
21588
|
async askGit(threadRef, action) {
|
|
21435
21589
|
if (!AGENT_GIT_ACTIONS.includes(action)) {
|
|
@@ -21447,17 +21601,6 @@ var init_orchestrator = __esm({
|
|
|
21447
21601
|
"No pull request linked. Ask the worktree agent to open a draft PR first (ask_git create-draft)."
|
|
21448
21602
|
);
|
|
21449
21603
|
}
|
|
21450
|
-
if ((action === "commit-push" || action === "create-draft" || action === "create-web") && thread.worktreePath?.trim() && !await isDirty(thread.worktreePath)) {
|
|
21451
|
-
try {
|
|
21452
|
-
await this.pushAndMaybeOpenPr(thread, action);
|
|
21453
|
-
} catch (err) {
|
|
21454
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
21455
|
-
updateThread(thread.id, { lastError: message });
|
|
21456
|
-
this.emit({ type: "error", threadId: thread.id, message });
|
|
21457
|
-
throw err;
|
|
21458
|
-
}
|
|
21459
|
-
return this.requireThread(threadRef);
|
|
21460
|
-
}
|
|
21461
21604
|
let prBase;
|
|
21462
21605
|
if (action === "resolve-conflicts") {
|
|
21463
21606
|
try {
|
|
@@ -21466,40 +21609,18 @@ var init_orchestrator = __esm({
|
|
|
21466
21609
|
} catch {
|
|
21467
21610
|
}
|
|
21468
21611
|
}
|
|
21469
|
-
|
|
21470
|
-
|
|
21471
|
-
|
|
21472
|
-
|
|
21473
|
-
|
|
21474
|
-
|
|
21475
|
-
|
|
21476
|
-
|
|
21477
|
-
|
|
21478
|
-
|
|
21479
|
-
|
|
21480
|
-
|
|
21481
|
-
});
|
|
21482
|
-
const url = await createOrUpdatePr(cwd, {
|
|
21483
|
-
title: meta.title,
|
|
21484
|
-
body: meta.body,
|
|
21485
|
-
base,
|
|
21486
|
-
head: branch,
|
|
21487
|
-
draft: action === "create-draft",
|
|
21488
|
-
web: action === "create-web"
|
|
21489
|
-
});
|
|
21490
|
-
if (!url) return;
|
|
21491
|
-
const patch = {
|
|
21492
|
-
prUrl: url,
|
|
21493
|
-
prTitle: meta.title,
|
|
21494
|
-
prIsDraft: action === "create-draft"
|
|
21495
|
-
};
|
|
21496
|
-
try {
|
|
21497
|
-
const fetched = await getPrMeta(cwd, url);
|
|
21498
|
-
if (fetched?.title) patch.prTitle = fetched.title;
|
|
21499
|
-
if (fetched) patch.prIsDraft = Boolean(fetched.isDraft);
|
|
21500
|
-
} catch {
|
|
21501
|
-
}
|
|
21502
|
-
updateThread(thread.id, patch);
|
|
21612
|
+
const settings = loadWorkspaceSettings(thread.worktreePath, thread.repoPath);
|
|
21613
|
+
return this.send(
|
|
21614
|
+
threadRef,
|
|
21615
|
+
resolveSidebarGitPrompt(action, {
|
|
21616
|
+
prBase,
|
|
21617
|
+
createPr: settings?.prompts?.createPr,
|
|
21618
|
+
resolveMergeConflicts: settings?.prompts?.resolveMergeConflicts
|
|
21619
|
+
}),
|
|
21620
|
+
{
|
|
21621
|
+
followUp: resolveOrchChildFollowUp()
|
|
21622
|
+
}
|
|
21623
|
+
);
|
|
21503
21624
|
}
|
|
21504
21625
|
setThreadOptions(threadRef, patch) {
|
|
21505
21626
|
const thread = this.requireThread(threadRef);
|
|
@@ -22054,7 +22175,7 @@ function parseProjectTitles(raw) {
|
|
|
22054
22175
|
}
|
|
22055
22176
|
async function listGitHubIssueProjects(number, cwd, repoArgs) {
|
|
22056
22177
|
const result = await gh(
|
|
22057
|
-
["issue", "view", String(number), ...repoArgs, "--json", "projectItems
|
|
22178
|
+
["issue", "view", String(number), ...repoArgs, "--json", "projectItems"],
|
|
22058
22179
|
cwd,
|
|
22059
22180
|
{ reject: false }
|
|
22060
22181
|
);
|
|
@@ -22443,6 +22564,16 @@ query SideboardLabels($first: Int!) {
|
|
|
22443
22564
|
}
|
|
22444
22565
|
}
|
|
22445
22566
|
`;
|
|
22567
|
+
var TEAM_LABELS_QUERY = `
|
|
22568
|
+
query SideboardTeamLabels($id: String!, $first: Int!, $after: String) {
|
|
22569
|
+
team(id: $id) {
|
|
22570
|
+
labels(first: $first, after: $after) {
|
|
22571
|
+
nodes { id name }
|
|
22572
|
+
pageInfo { hasNextPage endCursor }
|
|
22573
|
+
}
|
|
22574
|
+
}
|
|
22575
|
+
}
|
|
22576
|
+
`;
|
|
22446
22577
|
var PROJECTS_QUERY = `
|
|
22447
22578
|
query SideboardProjects($first: Int!, $filter: ProjectFilter) {
|
|
22448
22579
|
projects(first: $first, filter: $filter) {
|
|
@@ -22816,15 +22947,38 @@ function formatRelationList(relations) {
|
|
|
22816
22947
|
if (!relations.length) return "(none)";
|
|
22817
22948
|
return relations.map((r) => `${r.type} ${r.issue.identifier || r.issue.id}`).join(", ");
|
|
22818
22949
|
}
|
|
22819
|
-
|
|
22820
|
-
|
|
22821
|
-
return (json.issueLabels?.nodes ?? []).flatMap((node) => {
|
|
22950
|
+
function mapLabelNodes(nodes) {
|
|
22951
|
+
return (nodes ?? []).flatMap((node) => {
|
|
22822
22952
|
const id = String(node.id ?? "").trim();
|
|
22823
22953
|
const name = String(node.name ?? "").trim();
|
|
22824
22954
|
if (!id) return [];
|
|
22825
22955
|
return [{ id, name }];
|
|
22826
22956
|
});
|
|
22827
22957
|
}
|
|
22958
|
+
async function listLinearWorkspaceLabels(opts) {
|
|
22959
|
+
const json = await linearGraphql(LABELS_QUERY, { first: 250 }, opts);
|
|
22960
|
+
return mapLabelNodes(json.issueLabels?.nodes);
|
|
22961
|
+
}
|
|
22962
|
+
async function listLinearLabels(opts) {
|
|
22963
|
+
const teamId = opts?.teamId?.trim();
|
|
22964
|
+
if (teamId) {
|
|
22965
|
+
const out = [];
|
|
22966
|
+
let after;
|
|
22967
|
+
for (let page = 0; page < 4; page++) {
|
|
22968
|
+
const json = await linearGraphql(
|
|
22969
|
+
TEAM_LABELS_QUERY,
|
|
22970
|
+
after ? { id: teamId, first: 250, after } : { id: teamId, first: 250 },
|
|
22971
|
+
opts
|
|
22972
|
+
);
|
|
22973
|
+
const conn = json.team?.labels;
|
|
22974
|
+
out.push(...mapLabelNodes(conn?.nodes));
|
|
22975
|
+
if (!conn?.pageInfo?.hasNextPage || !conn.pageInfo.endCursor) break;
|
|
22976
|
+
after = conn.pageInfo.endCursor;
|
|
22977
|
+
}
|
|
22978
|
+
if (out.length) return out;
|
|
22979
|
+
}
|
|
22980
|
+
return listLinearWorkspaceLabels(opts);
|
|
22981
|
+
}
|
|
22828
22982
|
async function listLinearProjects(filter, opts) {
|
|
22829
22983
|
const json = await linearGraphql(PROJECTS_QUERY, { first: 50, filter: filter ?? {} }, opts);
|
|
22830
22984
|
return (json.projects?.nodes ?? []).flatMap((node) => {
|
|
@@ -23113,7 +23267,7 @@ async function updateLinearIssue(input, opts) {
|
|
|
23113
23267
|
}
|
|
23114
23268
|
const addRelations = input.relations?.length ? input.relations : void 0;
|
|
23115
23269
|
const removeRelations = input.removeRelations?.length ? input.removeRelations : void 0;
|
|
23116
|
-
const needsIssue = Boolean(input.state?.trim()) || input.cycle !== void 0 || Boolean(addRelations) || Boolean(removeRelations);
|
|
23270
|
+
const needsIssue = Boolean(input.state?.trim()) || input.cycle !== void 0 || input.labels !== void 0 || Boolean(addRelations) || Boolean(removeRelations);
|
|
23117
23271
|
const existing = needsIssue ? await getLinearIssue(issueId, opts) : void 0;
|
|
23118
23272
|
if (input.state?.trim()) {
|
|
23119
23273
|
const { teams } = await listLinearTeams(opts);
|
|
@@ -23148,7 +23302,10 @@ async function updateLinearIssue(input, opts) {
|
|
|
23148
23302
|
mutationInput.priority = normalizePriority(input.priority);
|
|
23149
23303
|
}
|
|
23150
23304
|
if (input.labels !== void 0) {
|
|
23151
|
-
mutationInput.labelIds = await resolveLinearLabelIds(input.labels,
|
|
23305
|
+
mutationInput.labelIds = await resolveLinearLabelIds(input.labels, {
|
|
23306
|
+
...opts,
|
|
23307
|
+
teamId: existing?.team?.id
|
|
23308
|
+
});
|
|
23152
23309
|
}
|
|
23153
23310
|
if (input.project !== void 0) {
|
|
23154
23311
|
mutationInput.projectId = await resolveLinearProjectId(input.project, opts);
|
|
@@ -25330,51 +25487,7 @@ async function getHomeBoardInputs(workspaces, opts) {
|
|
|
25330
25487
|
|
|
25331
25488
|
// src/mcp/server.ts
|
|
25332
25489
|
init_home_board();
|
|
25333
|
-
|
|
25334
|
-
// src/integrations/github.ts
|
|
25335
|
-
init_run();
|
|
25336
|
-
async function getGitHubStatus() {
|
|
25337
|
-
const which = await run("which", ["gh"], { reject: false });
|
|
25338
|
-
if (which.exitCode !== 0 || !which.stdout.trim()) {
|
|
25339
|
-
return {
|
|
25340
|
-
connected: false,
|
|
25341
|
-
login: null,
|
|
25342
|
-
hosts: [],
|
|
25343
|
-
reason: "gh CLI not found on PATH"
|
|
25344
|
-
};
|
|
25345
|
-
}
|
|
25346
|
-
const loginResult = await run(
|
|
25347
|
-
"gh",
|
|
25348
|
-
["api", "user", "--jq", ".login"],
|
|
25349
|
-
{ reject: false }
|
|
25350
|
-
);
|
|
25351
|
-
if (loginResult.exitCode === 0 && loginResult.stdout.trim()) {
|
|
25352
|
-
return {
|
|
25353
|
-
connected: true,
|
|
25354
|
-
login: loginResult.stdout.trim(),
|
|
25355
|
-
hosts: ["github.com"],
|
|
25356
|
-
reason: null
|
|
25357
|
-
};
|
|
25358
|
-
}
|
|
25359
|
-
const status = await run("gh", ["auth", "status"], { reject: false });
|
|
25360
|
-
const text7 = `${status.stdout}
|
|
25361
|
-
${status.stderr}`;
|
|
25362
|
-
const loginMatch = text7.match(/Logged in to ([^\s]+) account (\S+)/i) ?? text7.match(/Logged in to ([^\s]+) as (\S+)/i);
|
|
25363
|
-
if (loginMatch) {
|
|
25364
|
-
return {
|
|
25365
|
-
connected: true,
|
|
25366
|
-
login: loginMatch[2].replace(/['"]/g, ""),
|
|
25367
|
-
hosts: [loginMatch[1]],
|
|
25368
|
-
reason: null
|
|
25369
|
-
};
|
|
25370
|
-
}
|
|
25371
|
-
return {
|
|
25372
|
-
connected: false,
|
|
25373
|
-
login: null,
|
|
25374
|
-
hosts: [],
|
|
25375
|
-
reason: status.stderr.trim() || status.stdout.trim() || "Not logged in to GitHub (run: gh auth login)"
|
|
25376
|
-
};
|
|
25377
|
-
}
|
|
25490
|
+
init_github();
|
|
25378
25491
|
|
|
25379
25492
|
// src/mcp/create-thread-agent.ts
|
|
25380
25493
|
init_cursor();
|
|
@@ -26009,7 +26122,7 @@ async function startMcpServer() {
|
|
|
26009
26122
|
);
|
|
26010
26123
|
server.tool(
|
|
26011
26124
|
"send_to_thread",
|
|
26012
|
-
'
|
|
26125
|
+
'Steer a prompt on a worktree thread chat (Settings \u2192 Follow-up, default steer: interrupt and start now, skip the inbox). Use after create_thread to start or continue a conversation. For commit/push/PR, prefer ask_git (canonical desktop-button phrases). Send "Merge PR." / ask_git merge only when the user explicitly asked to merge. force_stop=true kills the in-flight turn and clears the queue before this prompt \u2014 only when the current request is wrong and must be replaced. Do not send_to_thread to check in, resume after a halt notice, or because wait_for_turn returned stillRunning; that interrupts the child mid-thought. Call wait_for_turn again instead.',
|
|
26013
26126
|
{
|
|
26014
26127
|
ref: import_zod9.z.string(),
|
|
26015
26128
|
prompt: import_zod9.z.string(),
|
|
@@ -26022,7 +26135,9 @@ async function startMcpServer() {
|
|
|
26022
26135
|
orch.stop(ref, { clearQueue: true, notifyParent: false });
|
|
26023
26136
|
}
|
|
26024
26137
|
}
|
|
26025
|
-
const thread = await orch.send(ref, prompt
|
|
26138
|
+
const thread = await orch.send(ref, prompt, {
|
|
26139
|
+
followUp: resolveOrchChildFollowUp()
|
|
26140
|
+
});
|
|
26026
26141
|
return mcpJson({
|
|
26027
26142
|
id: thread.id,
|
|
26028
26143
|
status: thread.status,
|
|
@@ -26033,7 +26148,7 @@ async function startMcpServer() {
|
|
|
26033
26148
|
);
|
|
26034
26149
|
server.tool(
|
|
26035
26150
|
"wait_for_turn",
|
|
26036
|
-
"Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. stillRunning is the source of truth \u2014 if false, the child is not working (do not say it is waiting for a gate). If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not
|
|
26151
|
+
"Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. stillRunning is the source of truth \u2014 if false, the child is not working (do not say it is waiting for a gate). If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts), force_stop, or assume a hang. On status error, lastError/text is the failure. On status stopped or broken, the child did not finish \u2014 resume with send_to_thread or tell the user; do not treat that as success. When finished, usage is the last agent turn\u2019s tokens + costUsd (when the provider reported cost).",
|
|
26037
26152
|
{
|
|
26038
26153
|
ref: import_zod9.z.string(),
|
|
26039
26154
|
timeoutMs: import_zod9.z.number().optional()
|
|
@@ -26190,7 +26305,7 @@ async function startMcpServer() {
|
|
|
26190
26305
|
);
|
|
26191
26306
|
server.tool(
|
|
26192
26307
|
"ask_git",
|
|
26193
|
-
"Commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge \u2014 same
|
|
26308
|
+
"Commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge \u2014 same prompts as the desktop git buttons (including Resolve). Always steers the worktree agent; does not push or open the PR locally. Then wait_for_turn (loop while stillRunning). Do not start a checks loop on a plain push \u2014 only if the user gave a goal (Greptile 5/5, CI green). Pass a worktree thread ref (not the orchestrator). action=ready-for-review and action=merge only when the user explicitly asked (or clicked the desktop button). Do not run git or gh from the orchestration cwd.",
|
|
26194
26309
|
{
|
|
26195
26310
|
ref: import_zod9.z.string().describe("Worktree thread id/ref"),
|
|
26196
26311
|
action: import_zod9.z.enum(AGENT_GIT_ACTIONS).describe(
|