@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/index.cjs
CHANGED
|
@@ -274,9 +274,12 @@ function parseSettingsFile(path2, source) {
|
|
|
274
274
|
const prompts = {
|
|
275
275
|
renameBranch: typeof promptsRaw.rename_branch === "string" ? promptsRaw.rename_branch : void 0,
|
|
276
276
|
createPr: typeof promptsRaw.create_pr === "string" ? promptsRaw.create_pr : void 0,
|
|
277
|
-
general: typeof promptsRaw.general === "string" ? promptsRaw.general : void 0
|
|
277
|
+
general: typeof promptsRaw.general === "string" ? promptsRaw.general : void 0,
|
|
278
|
+
resolveMergeConflicts: typeof promptsRaw.resolve_merge_conflicts === "string" ? promptsRaw.resolve_merge_conflicts : void 0
|
|
278
279
|
};
|
|
279
|
-
const hasPrompts = Boolean(
|
|
280
|
+
const hasPrompts = Boolean(
|
|
281
|
+
prompts.renameBranch || prompts.createPr || prompts.general || prompts.resolveMergeConflicts
|
|
282
|
+
);
|
|
280
283
|
return {
|
|
281
284
|
source,
|
|
282
285
|
setup,
|
|
@@ -302,9 +305,12 @@ function mergeSettings(base, overlay) {
|
|
|
302
305
|
const prompts = {
|
|
303
306
|
renameBranch: overlay.prompts?.renameBranch ?? base.prompts?.renameBranch,
|
|
304
307
|
createPr: overlay.prompts?.createPr ?? base.prompts?.createPr,
|
|
305
|
-
general: overlay.prompts?.general ?? base.prompts?.general
|
|
308
|
+
general: overlay.prompts?.general ?? base.prompts?.general,
|
|
309
|
+
resolveMergeConflicts: overlay.prompts?.resolveMergeConflicts ?? base.prompts?.resolveMergeConflicts
|
|
306
310
|
};
|
|
307
|
-
const hasPrompts = Boolean(
|
|
311
|
+
const hasPrompts = Boolean(
|
|
312
|
+
prompts.renameBranch || prompts.createPr || prompts.general || prompts.resolveMergeConflicts
|
|
313
|
+
);
|
|
308
314
|
return {
|
|
309
315
|
source: overlay.source,
|
|
310
316
|
setup: overlay.setup ?? base.setup,
|
|
@@ -428,7 +434,8 @@ function getRepoSetupInfo(worktreePath, repoPath) {
|
|
|
428
434
|
return {
|
|
429
435
|
hasConfig: hasWorkspaceHook(worktreePath, repoPath) || cursor || Boolean(convention),
|
|
430
436
|
hasSetupScript,
|
|
431
|
-
configLabel
|
|
437
|
+
configLabel,
|
|
438
|
+
...settings?.prompts ? { prompts: settings.prompts } : {}
|
|
432
439
|
};
|
|
433
440
|
}
|
|
434
441
|
var import_node_fs3, import_node_os, import_node_path3, import_smol_toml;
|
|
@@ -955,6 +962,32 @@ var init_secret_vault = __esm({
|
|
|
955
962
|
}
|
|
956
963
|
});
|
|
957
964
|
|
|
965
|
+
// src/git/branch-prefix.ts
|
|
966
|
+
var branch_prefix_exports = {};
|
|
967
|
+
__export(branch_prefix_exports, {
|
|
968
|
+
examplePrefixedBranch: () => examplePrefixedBranch,
|
|
969
|
+
resolveGitBranchPrefix: () => resolveGitBranchPrefix,
|
|
970
|
+
sanitizeGitBranchPrefix: () => sanitizeGitBranchPrefix
|
|
971
|
+
});
|
|
972
|
+
function sanitizeGitBranchPrefix(raw) {
|
|
973
|
+
const first = (raw ?? "").trim().replace(/^\/+|\/+$/g, "").split("/")[0] ?? "";
|
|
974
|
+
const slug = first.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 39);
|
|
975
|
+
return slug || null;
|
|
976
|
+
}
|
|
977
|
+
function resolveGitBranchPrefix(opts) {
|
|
978
|
+
return sanitizeGitBranchPrefix(opts.setting) ?? sanitizeGitBranchPrefix(opts.githubLogin);
|
|
979
|
+
}
|
|
980
|
+
function examplePrefixedBranch(prefix, ticket) {
|
|
981
|
+
const head = sanitizeGitBranchPrefix(prefix);
|
|
982
|
+
const slug = ticket?.trim() ? `${ticket.trim()}-eng-fix-thing` : "bb-1234-eng-fix-thing";
|
|
983
|
+
return head ? `${head}/${slug}` : slug;
|
|
984
|
+
}
|
|
985
|
+
var init_branch_prefix = __esm({
|
|
986
|
+
"src/git/branch-prefix.ts"() {
|
|
987
|
+
"use strict";
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
|
|
958
991
|
// src/store/issue-source-labels.ts
|
|
959
992
|
function issueSourceLabel(source) {
|
|
960
993
|
if (source && source in ISSUE_SOURCE_LABELS) {
|
|
@@ -1023,6 +1056,7 @@ __export(app_settings_exports, {
|
|
|
1023
1056
|
getGithubPat: () => getGithubPat,
|
|
1024
1057
|
getIssueSource: () => getIssueSource,
|
|
1025
1058
|
getLinearApiKey: () => getLinearApiKey,
|
|
1059
|
+
gitBranchPrefixSetting: () => gitBranchPrefixSetting,
|
|
1026
1060
|
harnessEnvKey: () => harnessEnvKey,
|
|
1027
1061
|
isAbleTimeConnected: () => isAbleTimeConnected,
|
|
1028
1062
|
isIssueSourceConnected: () => isIssueSourceConnected,
|
|
@@ -1398,6 +1432,10 @@ function normalizeAdvanced(raw) {
|
|
|
1398
1432
|
if (typeof source.autoRenameBranch === "boolean") {
|
|
1399
1433
|
out.autoRenameBranch = source.autoRenameBranch;
|
|
1400
1434
|
}
|
|
1435
|
+
if (typeof source.branchPrefix === "string") {
|
|
1436
|
+
const prefix = sanitizeGitBranchPrefix(source.branchPrefix);
|
|
1437
|
+
if (prefix) out.branchPrefix = prefix;
|
|
1438
|
+
}
|
|
1401
1439
|
if (typeof source.autoRunAfterSetup === "boolean") {
|
|
1402
1440
|
out.autoRunAfterSetup = source.autoRunAfterSetup;
|
|
1403
1441
|
}
|
|
@@ -2251,6 +2289,13 @@ function updateAdvancedSettings(patch) {
|
|
|
2251
2289
|
if (typeof patch.autoRenameBranch === "boolean") {
|
|
2252
2290
|
advanced.autoRenameBranch = patch.autoRenameBranch;
|
|
2253
2291
|
}
|
|
2292
|
+
if (patch.branchPrefix === null || patch.branchPrefix === "") {
|
|
2293
|
+
delete advanced.branchPrefix;
|
|
2294
|
+
} else if (typeof patch.branchPrefix === "string") {
|
|
2295
|
+
const prefix = sanitizeGitBranchPrefix(patch.branchPrefix);
|
|
2296
|
+
if (prefix) advanced.branchPrefix = prefix;
|
|
2297
|
+
else delete advanced.branchPrefix;
|
|
2298
|
+
}
|
|
2254
2299
|
if (typeof patch.autoRunAfterSetup === "boolean") {
|
|
2255
2300
|
advanced.autoRunAfterSetup = patch.autoRunAfterSetup;
|
|
2256
2301
|
}
|
|
@@ -2311,6 +2356,9 @@ function updateAdvancedSettings(patch) {
|
|
|
2311
2356
|
function autoRenameBranchEnabled(settings = loadAppSettings()) {
|
|
2312
2357
|
return settings.advanced.autoRenameBranch !== false;
|
|
2313
2358
|
}
|
|
2359
|
+
function gitBranchPrefixSetting(settings = loadAppSettings()) {
|
|
2360
|
+
return sanitizeGitBranchPrefix(settings.advanced.branchPrefix);
|
|
2361
|
+
}
|
|
2314
2362
|
function autoRunAfterSetupEnabled(settings = loadAppSettings()) {
|
|
2315
2363
|
return Boolean(settings.advanced.autoRunAfterSetup);
|
|
2316
2364
|
}
|
|
@@ -2456,6 +2504,7 @@ var init_app_settings = __esm({
|
|
|
2456
2504
|
init_paths();
|
|
2457
2505
|
init_private_file();
|
|
2458
2506
|
init_secret_vault();
|
|
2507
|
+
init_branch_prefix();
|
|
2459
2508
|
init_issue_source_labels();
|
|
2460
2509
|
init_account_profile();
|
|
2461
2510
|
HARNESS_ENV_KEYS = {
|
|
@@ -4454,6 +4503,18 @@ var init_teams = __esm({
|
|
|
4454
4503
|
});
|
|
4455
4504
|
|
|
4456
4505
|
// src/git/worktree-labels.ts
|
|
4506
|
+
var worktree_labels_exports = {};
|
|
4507
|
+
__export(worktree_labels_exports, {
|
|
4508
|
+
branchDisplayLabel: () => branchDisplayLabel,
|
|
4509
|
+
isPlaceholderBranch: () => isPlaceholderBranch,
|
|
4510
|
+
normalizeWorktreePath: () => normalizeWorktreePath,
|
|
4511
|
+
threadDisplayLabel: () => threadDisplayLabel,
|
|
4512
|
+
ticketSlugForBranch: () => ticketSlugForBranch,
|
|
4513
|
+
worktreeDisplayLabel: () => worktreeDisplayLabel,
|
|
4514
|
+
worktreeDisplayLabelForGroup: () => worktreeDisplayLabelForGroup,
|
|
4515
|
+
worktreeNameFromPath: () => worktreeNameFromPath,
|
|
4516
|
+
worktreeSlugForTicket: () => worktreeSlugForTicket
|
|
4517
|
+
});
|
|
4457
4518
|
function normalizeWorktreePath(worktreePath) {
|
|
4458
4519
|
const trimmed = (worktreePath ?? "").replace(/\/+$/, "") || "/";
|
|
4459
4520
|
const absolute = trimmed.startsWith("/");
|
|
@@ -7772,8 +7833,8 @@ var init_coordinator_prompt = __esm({
|
|
|
7772
7833
|
"- start_board_card \u2014 same as create_thread for a ticket/PR/named branch (attaches issue text when resolvable). Then send_to_thread.",
|
|
7773
7834
|
"- 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.",
|
|
7774
7835
|
"- 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.",
|
|
7775
|
-
"- send_to_thread \u2014
|
|
7776
|
-
"- 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
|
|
7836
|
+
"- 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)",
|
|
7837
|
+
"- 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.",
|
|
7777
7838
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
7778
7839
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
7779
7840
|
"Setup / run:",
|
|
@@ -7783,7 +7844,7 @@ var init_coordinator_prompt = __esm({
|
|
|
7783
7844
|
"- get_diff \u2014 compact diff summary",
|
|
7784
7845
|
"- 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.",
|
|
7785
7846
|
'- 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.',
|
|
7786
|
-
"- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge
|
|
7847
|
+
"- 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.",
|
|
7787
7848
|
'- 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.',
|
|
7788
7849
|
'- 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.',
|
|
7789
7850
|
"Process guides:",
|
|
@@ -14176,87 +14237,6 @@ var init_spawn = __esm({
|
|
|
14176
14237
|
}
|
|
14177
14238
|
});
|
|
14178
14239
|
|
|
14179
|
-
// src/land/pr-metadata.ts
|
|
14180
|
-
function looksGeneric(title) {
|
|
14181
|
-
const t = title.trim();
|
|
14182
|
-
if (!t) return true;
|
|
14183
|
-
if (t.length < 4) return true;
|
|
14184
|
-
if (GENERIC_TITLE_RE.test(t)) return true;
|
|
14185
|
-
if (!/[\s:/\-_]/.test(t) && t.length <= 24) return true;
|
|
14186
|
-
return false;
|
|
14187
|
-
}
|
|
14188
|
-
function truncateTitle(title, max = 72) {
|
|
14189
|
-
const t = title.trim().replace(/\s+/g, " ");
|
|
14190
|
-
if (t.length <= max) return t;
|
|
14191
|
-
return `${t.slice(0, max - 1).trimEnd()}\u2026`;
|
|
14192
|
-
}
|
|
14193
|
-
function titleFromPaths(paths) {
|
|
14194
|
-
if (paths.length === 0) return null;
|
|
14195
|
-
const top = paths.slice(0, 3).map((p) => p.replace(/\/$/, ""));
|
|
14196
|
-
if (paths.length === 1) return truncateTitle(`Update ${top[0]}`);
|
|
14197
|
-
if (paths.length <= 3) return truncateTitle(`Update ${top.join(", ")}`);
|
|
14198
|
-
return truncateTitle(`Update ${top[0]} and ${paths.length - 1} more files`);
|
|
14199
|
-
}
|
|
14200
|
-
async function suggestPrMetadata(worktreePath, opts) {
|
|
14201
|
-
const [{ stdout: logOut }, { stdout: nameStatus }, { stdout: statOut }] = await Promise.all([
|
|
14202
|
-
git(["log", "--format=%s", `${opts.base}..HEAD`], worktreePath, {
|
|
14203
|
-
reject: false
|
|
14204
|
-
}),
|
|
14205
|
-
git(["diff", "--name-only", `${opts.base}...HEAD`], worktreePath, {
|
|
14206
|
-
reject: false
|
|
14207
|
-
}),
|
|
14208
|
-
git(["diff", "--stat", `${opts.base}...HEAD`], worktreePath, {
|
|
14209
|
-
reject: false
|
|
14210
|
-
})
|
|
14211
|
-
]);
|
|
14212
|
-
const { stdout: dirtyNames } = await git(["diff", "--name-only", "HEAD"], worktreePath, {
|
|
14213
|
-
reject: false
|
|
14214
|
-
});
|
|
14215
|
-
const { stdout: untracked } = await git(
|
|
14216
|
-
["ls-files", "--others", "--exclude-standard"],
|
|
14217
|
-
worktreePath,
|
|
14218
|
-
{ reject: false }
|
|
14219
|
-
);
|
|
14220
|
-
const subjects = logOut.split("\n").map((s) => s.trim()).filter(Boolean);
|
|
14221
|
-
const paths = [
|
|
14222
|
-
...new Set(
|
|
14223
|
-
[...nameStatus.split("\n"), ...dirtyNames.split("\n"), ...untracked.split("\n")].map((p) => p.trim()).filter(Boolean)
|
|
14224
|
-
)
|
|
14225
|
-
].sort((a, b) => a.localeCompare(b));
|
|
14226
|
-
const meaningfulSubjects = subjects.filter((s) => !looksGeneric(s));
|
|
14227
|
-
const fallback = opts.fallbackTitle?.trim() || null;
|
|
14228
|
-
const fallbackOk = fallback && !looksGeneric(fallback) ? fallback : null;
|
|
14229
|
-
const title = truncateTitle(
|
|
14230
|
-
meaningfulSubjects[0] ?? fallbackOk ?? titleFromPaths(paths) ?? "Sideboard changes"
|
|
14231
|
-
);
|
|
14232
|
-
const commitMessage = meaningfulSubjects[0] ?? fallbackOk ?? titleFromPaths(paths) ?? `sideboard: ${title}`;
|
|
14233
|
-
const summaryLines = meaningfulSubjects.length > 0 ? meaningfulSubjects.slice(0, 12).map((s) => `- ${s}`) : paths.slice(0, 20).map((p) => `- \`${p}\``);
|
|
14234
|
-
const bodyParts = [
|
|
14235
|
-
"## Summary",
|
|
14236
|
-
summaryLines.length > 0 ? summaryLines.join("\n") : "- Changes landed via Sideboard.",
|
|
14237
|
-
""
|
|
14238
|
-
];
|
|
14239
|
-
if (statOut.trim()) {
|
|
14240
|
-
bodyParts.push("## Diff", "```", statOut.trim(), "```", "");
|
|
14241
|
-
}
|
|
14242
|
-
if (opts.sourceLabel) {
|
|
14243
|
-
bodyParts.push(`_Landed via Sideboard from ${opts.sourceLabel}_`);
|
|
14244
|
-
}
|
|
14245
|
-
return {
|
|
14246
|
-
title,
|
|
14247
|
-
body: bodyParts.join("\n").trim() + "\n",
|
|
14248
|
-
commitMessage: truncateTitle(commitMessage, 72)
|
|
14249
|
-
};
|
|
14250
|
-
}
|
|
14251
|
-
var GENERIC_TITLE_RE;
|
|
14252
|
-
var init_pr_metadata = __esm({
|
|
14253
|
-
"src/land/pr-metadata.ts"() {
|
|
14254
|
-
"use strict";
|
|
14255
|
-
init_run();
|
|
14256
|
-
GENERIC_TITLE_RE = /^(sideboard:|thread\/|wip\b|tmp\b|update\b|changes?\b|misc\b|stuff\b)/i;
|
|
14257
|
-
}
|
|
14258
|
-
});
|
|
14259
|
-
|
|
14260
14240
|
// src/git/agent-git-actions.ts
|
|
14261
14241
|
function agentGitPrompt(action, opts) {
|
|
14262
14242
|
switch (action) {
|
|
@@ -14277,6 +14257,19 @@ function agentGitPrompt(action, opts) {
|
|
|
14277
14257
|
return "Merge PR.";
|
|
14278
14258
|
}
|
|
14279
14259
|
}
|
|
14260
|
+
function resolveSidebarGitPrompt(action, opts) {
|
|
14261
|
+
if (action === "create-pr" || action === "create-draft" || action === "create-web") {
|
|
14262
|
+
const custom = opts?.createPr?.trim();
|
|
14263
|
+
if (custom) return custom;
|
|
14264
|
+
return agentGitPrompt(action === "create-pr" ? "create-draft" : action);
|
|
14265
|
+
}
|
|
14266
|
+
if (action === "resolve-conflicts") {
|
|
14267
|
+
const custom = opts?.resolveMergeConflicts?.trim();
|
|
14268
|
+
if (custom) return custom;
|
|
14269
|
+
return agentGitPrompt("resolve-conflicts", opts);
|
|
14270
|
+
}
|
|
14271
|
+
return agentGitPrompt(action, opts);
|
|
14272
|
+
}
|
|
14280
14273
|
function gitActionExpansion(action, base) {
|
|
14281
14274
|
switch (action) {
|
|
14282
14275
|
case "commit-push":
|
|
@@ -15956,8 +15949,8 @@ var init_wait_for_turn = __esm({
|
|
|
15956
15949
|
"src/mcp/wait-for-turn.ts"() {
|
|
15957
15950
|
"use strict";
|
|
15958
15951
|
MCP_WAIT_FOR_TURN_MAX_MS = 45e3;
|
|
15959
|
-
MCP_WAIT_STILL_RUNNING_HINT = "Child is still working. Call wait_for_turn again. Do not
|
|
15960
|
-
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
|
|
15952
|
+
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.";
|
|
15953
|
+
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.";
|
|
15961
15954
|
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.";
|
|
15962
15955
|
MCP_WAIT_BROKEN_HINT = "Child worktree is broken (missing on disk). Tell the user \u2014 do not treat this as success.";
|
|
15963
15956
|
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.";
|
|
@@ -19505,6 +19498,87 @@ var init_diff = __esm({
|
|
|
19505
19498
|
}
|
|
19506
19499
|
});
|
|
19507
19500
|
|
|
19501
|
+
// src/land/pr-metadata.ts
|
|
19502
|
+
function looksGeneric(title) {
|
|
19503
|
+
const t = title.trim();
|
|
19504
|
+
if (!t) return true;
|
|
19505
|
+
if (t.length < 4) return true;
|
|
19506
|
+
if (GENERIC_TITLE_RE.test(t)) return true;
|
|
19507
|
+
if (!/[\s:/\-_]/.test(t) && t.length <= 24) return true;
|
|
19508
|
+
return false;
|
|
19509
|
+
}
|
|
19510
|
+
function truncateTitle(title, max = 72) {
|
|
19511
|
+
const t = title.trim().replace(/\s+/g, " ");
|
|
19512
|
+
if (t.length <= max) return t;
|
|
19513
|
+
return `${t.slice(0, max - 1).trimEnd()}\u2026`;
|
|
19514
|
+
}
|
|
19515
|
+
function titleFromPaths(paths) {
|
|
19516
|
+
if (paths.length === 0) return null;
|
|
19517
|
+
const top = paths.slice(0, 3).map((p) => p.replace(/\/$/, ""));
|
|
19518
|
+
if (paths.length === 1) return truncateTitle(`Update ${top[0]}`);
|
|
19519
|
+
if (paths.length <= 3) return truncateTitle(`Update ${top.join(", ")}`);
|
|
19520
|
+
return truncateTitle(`Update ${top[0]} and ${paths.length - 1} more files`);
|
|
19521
|
+
}
|
|
19522
|
+
async function suggestPrMetadata(worktreePath, opts) {
|
|
19523
|
+
const [{ stdout: logOut }, { stdout: nameStatus }, { stdout: statOut }] = await Promise.all([
|
|
19524
|
+
git(["log", "--format=%s", `${opts.base}..HEAD`], worktreePath, {
|
|
19525
|
+
reject: false
|
|
19526
|
+
}),
|
|
19527
|
+
git(["diff", "--name-only", `${opts.base}...HEAD`], worktreePath, {
|
|
19528
|
+
reject: false
|
|
19529
|
+
}),
|
|
19530
|
+
git(["diff", "--stat", `${opts.base}...HEAD`], worktreePath, {
|
|
19531
|
+
reject: false
|
|
19532
|
+
})
|
|
19533
|
+
]);
|
|
19534
|
+
const { stdout: dirtyNames } = await git(["diff", "--name-only", "HEAD"], worktreePath, {
|
|
19535
|
+
reject: false
|
|
19536
|
+
});
|
|
19537
|
+
const { stdout: untracked } = await git(
|
|
19538
|
+
["ls-files", "--others", "--exclude-standard"],
|
|
19539
|
+
worktreePath,
|
|
19540
|
+
{ reject: false }
|
|
19541
|
+
);
|
|
19542
|
+
const subjects = logOut.split("\n").map((s) => s.trim()).filter(Boolean);
|
|
19543
|
+
const paths = [
|
|
19544
|
+
...new Set(
|
|
19545
|
+
[...nameStatus.split("\n"), ...dirtyNames.split("\n"), ...untracked.split("\n")].map((p) => p.trim()).filter(Boolean)
|
|
19546
|
+
)
|
|
19547
|
+
].sort((a, b) => a.localeCompare(b));
|
|
19548
|
+
const meaningfulSubjects = subjects.filter((s) => !looksGeneric(s));
|
|
19549
|
+
const fallback = opts.fallbackTitle?.trim() || null;
|
|
19550
|
+
const fallbackOk = fallback && !looksGeneric(fallback) ? fallback : null;
|
|
19551
|
+
const title = truncateTitle(
|
|
19552
|
+
meaningfulSubjects[0] ?? fallbackOk ?? titleFromPaths(paths) ?? "Sideboard changes"
|
|
19553
|
+
);
|
|
19554
|
+
const commitMessage = meaningfulSubjects[0] ?? fallbackOk ?? titleFromPaths(paths) ?? `sideboard: ${title}`;
|
|
19555
|
+
const summaryLines = meaningfulSubjects.length > 0 ? meaningfulSubjects.slice(0, 12).map((s) => `- ${s}`) : paths.slice(0, 20).map((p) => `- \`${p}\``);
|
|
19556
|
+
const bodyParts = [
|
|
19557
|
+
"## Summary",
|
|
19558
|
+
summaryLines.length > 0 ? summaryLines.join("\n") : "- Changes landed via Sideboard.",
|
|
19559
|
+
""
|
|
19560
|
+
];
|
|
19561
|
+
if (statOut.trim()) {
|
|
19562
|
+
bodyParts.push("## Diff", "```", statOut.trim(), "```", "");
|
|
19563
|
+
}
|
|
19564
|
+
if (opts.sourceLabel) {
|
|
19565
|
+
bodyParts.push(`_Landed via Sideboard from ${opts.sourceLabel}_`);
|
|
19566
|
+
}
|
|
19567
|
+
return {
|
|
19568
|
+
title,
|
|
19569
|
+
body: bodyParts.join("\n").trim() + "\n",
|
|
19570
|
+
commitMessage: truncateTitle(commitMessage, 72)
|
|
19571
|
+
};
|
|
19572
|
+
}
|
|
19573
|
+
var GENERIC_TITLE_RE;
|
|
19574
|
+
var init_pr_metadata = __esm({
|
|
19575
|
+
"src/land/pr-metadata.ts"() {
|
|
19576
|
+
"use strict";
|
|
19577
|
+
init_run();
|
|
19578
|
+
GENERIC_TITLE_RE = /^(sideboard:|thread\/|wip\b|tmp\b|update\b|changes?\b|misc\b|stuff\b)/i;
|
|
19579
|
+
}
|
|
19580
|
+
});
|
|
19581
|
+
|
|
19508
19582
|
// src/land/land.ts
|
|
19509
19583
|
async function previewLand(thread) {
|
|
19510
19584
|
if (thread.sourceIsFork) {
|
|
@@ -20035,13 +20109,14 @@ function formatRenameBranchDirective(thread, opts) {
|
|
|
20035
20109
|
if (!isPlaceholderBranch(thread.branchName, thread.worktreePath)) return null;
|
|
20036
20110
|
const dir = worktreeNameFromPath(thread.worktreePath);
|
|
20037
20111
|
const ticket = thread.sourceType === "ticket" ? ticketSlugForBranch(thread.sourceRef ?? "") : null;
|
|
20038
|
-
const
|
|
20112
|
+
const prefix = sanitizeGitBranchPrefix(opts?.branchPrefix);
|
|
20113
|
+
const example = examplePrefixedBranch(prefix, ticket);
|
|
20114
|
+
const shape = prefix ? `\`${prefix}/<ticket-or-task>-<short-kebab-description>\`` : "`<ticket-or-task>-<short-kebab-description>`";
|
|
20039
20115
|
const lines = [
|
|
20040
20116
|
"Branch naming (do this early in the turn):",
|
|
20041
20117
|
`- Current branch \`${thread.branchName}\` is a temporary placeholder. The worktree folder \`${dir}\` is a stable nickname \u2014 do not rename or leave that directory.`,
|
|
20042
|
-
`- Rename the git branch to
|
|
20118
|
+
`- Rename the git branch to ${shape}, e.g. \`${example}\`:`,
|
|
20043
20119
|
" `git branch -m <new-name>`",
|
|
20044
|
-
"- Prefer Conventional Commits style prefixes when they fit (`fix/`, `feat/`, `chore/`, `docs/`).",
|
|
20045
20120
|
...ticket ? [
|
|
20046
20121
|
`- Keep ticket \`${ticket}\` in the new branch name so the issue stays findable.`
|
|
20047
20122
|
] : [],
|
|
@@ -20247,6 +20322,7 @@ var init_instructions = __esm({
|
|
|
20247
20322
|
import_node_fs50 = require("fs");
|
|
20248
20323
|
import_node_path47 = require("path");
|
|
20249
20324
|
init_git_auth_mode();
|
|
20325
|
+
init_branch_prefix();
|
|
20250
20326
|
init_worktree_labels();
|
|
20251
20327
|
init_detached_job_path();
|
|
20252
20328
|
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;
|
|
@@ -20709,6 +20785,64 @@ var init_sync_branch = __esm({
|
|
|
20709
20785
|
}
|
|
20710
20786
|
});
|
|
20711
20787
|
|
|
20788
|
+
// src/integrations/github.ts
|
|
20789
|
+
var github_exports = {};
|
|
20790
|
+
__export(github_exports, {
|
|
20791
|
+
getGitHubStatus: () => getGitHubStatus,
|
|
20792
|
+
refreshGitHubAuth: () => refreshGitHubAuth
|
|
20793
|
+
});
|
|
20794
|
+
async function getGitHubStatus() {
|
|
20795
|
+
const which = await run("which", ["gh"], { reject: false });
|
|
20796
|
+
if (which.exitCode !== 0 || !which.stdout.trim()) {
|
|
20797
|
+
return {
|
|
20798
|
+
connected: false,
|
|
20799
|
+
login: null,
|
|
20800
|
+
hosts: [],
|
|
20801
|
+
reason: "gh CLI not found on PATH"
|
|
20802
|
+
};
|
|
20803
|
+
}
|
|
20804
|
+
const loginResult = await run(
|
|
20805
|
+
"gh",
|
|
20806
|
+
["api", "user", "--jq", ".login"],
|
|
20807
|
+
{ reject: false }
|
|
20808
|
+
);
|
|
20809
|
+
if (loginResult.exitCode === 0 && loginResult.stdout.trim()) {
|
|
20810
|
+
return {
|
|
20811
|
+
connected: true,
|
|
20812
|
+
login: loginResult.stdout.trim(),
|
|
20813
|
+
hosts: ["github.com"],
|
|
20814
|
+
reason: null
|
|
20815
|
+
};
|
|
20816
|
+
}
|
|
20817
|
+
const status = await run("gh", ["auth", "status"], { reject: false });
|
|
20818
|
+
const text7 = `${status.stdout}
|
|
20819
|
+
${status.stderr}`;
|
|
20820
|
+
const loginMatch = text7.match(/Logged in to ([^\s]+) account (\S+)/i) ?? text7.match(/Logged in to ([^\s]+) as (\S+)/i);
|
|
20821
|
+
if (loginMatch) {
|
|
20822
|
+
return {
|
|
20823
|
+
connected: true,
|
|
20824
|
+
login: loginMatch[2].replace(/['"]/g, ""),
|
|
20825
|
+
hosts: [loginMatch[1]],
|
|
20826
|
+
reason: null
|
|
20827
|
+
};
|
|
20828
|
+
}
|
|
20829
|
+
return {
|
|
20830
|
+
connected: false,
|
|
20831
|
+
login: null,
|
|
20832
|
+
hosts: [],
|
|
20833
|
+
reason: status.stderr.trim() || status.stdout.trim() || "Not logged in to GitHub (run: gh auth login)"
|
|
20834
|
+
};
|
|
20835
|
+
}
|
|
20836
|
+
async function refreshGitHubAuth() {
|
|
20837
|
+
return getGitHubStatus();
|
|
20838
|
+
}
|
|
20839
|
+
var init_github = __esm({
|
|
20840
|
+
"src/integrations/github.ts"() {
|
|
20841
|
+
"use strict";
|
|
20842
|
+
init_run();
|
|
20843
|
+
}
|
|
20844
|
+
});
|
|
20845
|
+
|
|
20712
20846
|
// src/agents/cursor-store.ts
|
|
20713
20847
|
function cursorSdkStoreDir(threadId) {
|
|
20714
20848
|
const root = (0, import_node_path49.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
|
|
@@ -20831,6 +20965,7 @@ __export(orchestrator_exports, {
|
|
|
20831
20965
|
Orchestrator: () => Orchestrator,
|
|
20832
20966
|
getOrchestrator: () => getOrchestrator,
|
|
20833
20967
|
isPidAlive: () => isPidAlive,
|
|
20968
|
+
resolveOrchChildFollowUp: () => resolveOrchChildFollowUp,
|
|
20834
20969
|
resolveSendFollowUp: () => resolveSendFollowUp,
|
|
20835
20970
|
startOrchestration: () => startOrchestration,
|
|
20836
20971
|
waitForPidExit: () => waitForPidExit
|
|
@@ -20861,6 +20996,10 @@ function resolveSendFollowUp(thread, requested) {
|
|
|
20861
20996
|
if (requested === "steer" || requested === "queue") return requested;
|
|
20862
20997
|
return isOrchestratorThread(thread) ? followUpBehavior() : "queue";
|
|
20863
20998
|
}
|
|
20999
|
+
function resolveOrchChildFollowUp(requested) {
|
|
21000
|
+
if (requested === "steer" || requested === "queue") return requested;
|
|
21001
|
+
return followUpBehavior();
|
|
21002
|
+
}
|
|
20864
21003
|
function writeLiveStatus(threadId, status, lastError) {
|
|
20865
21004
|
const latest = readThread(threadId);
|
|
20866
21005
|
if (!latest || latest.status === "archived") return latest;
|
|
@@ -20943,7 +21082,6 @@ var init_orchestrator = __esm({
|
|
|
20943
21082
|
init_spawn();
|
|
20944
21083
|
init_agents();
|
|
20945
21084
|
init_worktree();
|
|
20946
|
-
init_pr_metadata();
|
|
20947
21085
|
init_stack();
|
|
20948
21086
|
init_agent_git_actions();
|
|
20949
21087
|
init_pr_merge_archive();
|
|
@@ -21731,7 +21869,7 @@ var init_orchestrator = __esm({
|
|
|
21731
21869
|
}
|
|
21732
21870
|
const isBrightsy = fresh.agent === "brightsy";
|
|
21733
21871
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
21734
|
-
const { autoRenameBranchEnabled: autoRenameBranchEnabled2, getGithubGitAuthMode: getGithubGitAuthMode2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
21872
|
+
const { autoRenameBranchEnabled: autoRenameBranchEnabled2, getGithubGitAuthMode: getGithubGitAuthMode2, gitBranchPrefixSetting: gitBranchPrefixSetting2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
|
|
21735
21873
|
const gitAuthMode = getGithubGitAuthMode2();
|
|
21736
21874
|
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
21737
21875
|
githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
|
|
@@ -21767,9 +21905,26 @@ var init_orchestrator = __esm({
|
|
|
21767
21905
|
}
|
|
21768
21906
|
}
|
|
21769
21907
|
const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
|
|
21770
|
-
|
|
21771
|
-
|
|
21772
|
-
|
|
21908
|
+
let renameBranchDirective = null;
|
|
21909
|
+
if (!isBrightsy && !isOrchestration && autoRenameBranchEnabled2()) {
|
|
21910
|
+
const { isPlaceholderBranch: isPlaceholderBranch2 } = await Promise.resolve().then(() => (init_worktree_labels(), worktree_labels_exports));
|
|
21911
|
+
let githubLogin = null;
|
|
21912
|
+
if (isPlaceholderBranch2(fresh.branchName, fresh.worktreePath) && !gitBranchPrefixSetting2()) {
|
|
21913
|
+
try {
|
|
21914
|
+
const { getGitHubStatus: getGitHubStatus2 } = await Promise.resolve().then(() => (init_github(), github_exports));
|
|
21915
|
+
githubLogin = (await getGitHubStatus2()).login;
|
|
21916
|
+
} catch {
|
|
21917
|
+
}
|
|
21918
|
+
}
|
|
21919
|
+
const { resolveGitBranchPrefix: resolveGitBranchPrefix2 } = await Promise.resolve().then(() => (init_branch_prefix(), branch_prefix_exports));
|
|
21920
|
+
renameBranchDirective = formatRenameBranchDirective(fresh, {
|
|
21921
|
+
customPrompt: settings?.prompts?.renameBranch,
|
|
21922
|
+
branchPrefix: resolveGitBranchPrefix2({
|
|
21923
|
+
setting: gitBranchPrefixSetting2(),
|
|
21924
|
+
githubLogin
|
|
21925
|
+
})
|
|
21926
|
+
});
|
|
21927
|
+
}
|
|
21773
21928
|
let seed = null;
|
|
21774
21929
|
if (!fresh.sessionId) {
|
|
21775
21930
|
const prior = fresh.messages.slice(0, -1);
|
|
@@ -22799,9 +22954,9 @@ var init_orchestrator = __esm({
|
|
|
22799
22954
|
return tab;
|
|
22800
22955
|
}
|
|
22801
22956
|
/**
|
|
22802
|
-
* Desktop git buttons + MCP `ask_git`.
|
|
22803
|
-
*
|
|
22804
|
-
*
|
|
22957
|
+
* Desktop git buttons + MCP `ask_git`. Always queues the worktree agent
|
|
22958
|
+
* with the action prompt (same path as Resolve). Repository `[prompts]`
|
|
22959
|
+
* overrides apply when set.
|
|
22805
22960
|
*/
|
|
22806
22961
|
async askGit(threadRef, action) {
|
|
22807
22962
|
if (!AGENT_GIT_ACTIONS.includes(action)) {
|
|
@@ -22819,17 +22974,6 @@ var init_orchestrator = __esm({
|
|
|
22819
22974
|
"No pull request linked. Ask the worktree agent to open a draft PR first (ask_git create-draft)."
|
|
22820
22975
|
);
|
|
22821
22976
|
}
|
|
22822
|
-
if ((action === "commit-push" || action === "create-draft" || action === "create-web") && thread.worktreePath?.trim() && !await isDirty(thread.worktreePath)) {
|
|
22823
|
-
try {
|
|
22824
|
-
await this.pushAndMaybeOpenPr(thread, action);
|
|
22825
|
-
} catch (err) {
|
|
22826
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
22827
|
-
updateThread(thread.id, { lastError: message });
|
|
22828
|
-
this.emit({ type: "error", threadId: thread.id, message });
|
|
22829
|
-
throw err;
|
|
22830
|
-
}
|
|
22831
|
-
return this.requireThread(threadRef);
|
|
22832
|
-
}
|
|
22833
22977
|
let prBase;
|
|
22834
22978
|
if (action === "resolve-conflicts") {
|
|
22835
22979
|
try {
|
|
@@ -22838,40 +22982,18 @@ var init_orchestrator = __esm({
|
|
|
22838
22982
|
} catch {
|
|
22839
22983
|
}
|
|
22840
22984
|
}
|
|
22841
|
-
|
|
22842
|
-
|
|
22843
|
-
|
|
22844
|
-
|
|
22845
|
-
|
|
22846
|
-
|
|
22847
|
-
|
|
22848
|
-
|
|
22849
|
-
|
|
22850
|
-
|
|
22851
|
-
|
|
22852
|
-
|
|
22853
|
-
});
|
|
22854
|
-
const url = await createOrUpdatePr(cwd, {
|
|
22855
|
-
title: meta.title,
|
|
22856
|
-
body: meta.body,
|
|
22857
|
-
base,
|
|
22858
|
-
head: branch,
|
|
22859
|
-
draft: action === "create-draft",
|
|
22860
|
-
web: action === "create-web"
|
|
22861
|
-
});
|
|
22862
|
-
if (!url) return;
|
|
22863
|
-
const patch = {
|
|
22864
|
-
prUrl: url,
|
|
22865
|
-
prTitle: meta.title,
|
|
22866
|
-
prIsDraft: action === "create-draft"
|
|
22867
|
-
};
|
|
22868
|
-
try {
|
|
22869
|
-
const fetched = await getPrMeta(cwd, url);
|
|
22870
|
-
if (fetched?.title) patch.prTitle = fetched.title;
|
|
22871
|
-
if (fetched) patch.prIsDraft = Boolean(fetched.isDraft);
|
|
22872
|
-
} catch {
|
|
22873
|
-
}
|
|
22874
|
-
updateThread(thread.id, patch);
|
|
22985
|
+
const settings = loadWorkspaceSettings(thread.worktreePath, thread.repoPath);
|
|
22986
|
+
return this.send(
|
|
22987
|
+
threadRef,
|
|
22988
|
+
resolveSidebarGitPrompt(action, {
|
|
22989
|
+
prBase,
|
|
22990
|
+
createPr: settings?.prompts?.createPr,
|
|
22991
|
+
resolveMergeConflicts: settings?.prompts?.resolveMergeConflicts
|
|
22992
|
+
}),
|
|
22993
|
+
{
|
|
22994
|
+
followUp: resolveOrchChildFollowUp()
|
|
22995
|
+
}
|
|
22996
|
+
);
|
|
22875
22997
|
}
|
|
22876
22998
|
setThreadOptions(threadRef, patch) {
|
|
22877
22999
|
const thread = this.requireThread(threadRef);
|
|
@@ -23487,6 +23609,7 @@ __export(index_exports, {
|
|
|
23487
23609
|
estimateMessageChars: () => estimateMessageChars,
|
|
23488
23610
|
estimateOccupancyTokens: () => estimateOccupancyTokens,
|
|
23489
23611
|
estimateThreadChars: () => estimateThreadChars,
|
|
23612
|
+
examplePrefixedBranch: () => examplePrefixedBranch,
|
|
23490
23613
|
expandComposerPrompt: () => expandComposerPrompt,
|
|
23491
23614
|
extractBrightsyContextSummary: () => extractBrightsyContextSummary,
|
|
23492
23615
|
extractGhErrorDetail: () => extractGhErrorDetail,
|
|
@@ -23599,6 +23722,7 @@ __export(index_exports, {
|
|
|
23599
23722
|
ghHeadRef: () => ghHeadRef,
|
|
23600
23723
|
ghRepoSelectArgs: () => ghRepoSelectArgs,
|
|
23601
23724
|
git: () => git,
|
|
23725
|
+
gitBranchPrefixSetting: () => gitBranchPrefixSetting,
|
|
23602
23726
|
githubAgentGitEnv: () => githubAgentGitEnv,
|
|
23603
23727
|
githubHttpsInsteadOfEntries: () => githubHttpsInsteadOfEntries,
|
|
23604
23728
|
githubRelationEditFlag: () => githubRelationEditFlag,
|
|
@@ -23847,6 +23971,7 @@ __export(index_exports, {
|
|
|
23847
23971
|
resolveEffectiveIssueSource: () => resolveEffectiveIssueSource,
|
|
23848
23972
|
resolveFilesToCopy: () => resolveFilesToCopy,
|
|
23849
23973
|
resolveGhAuthToken: () => resolveGhAuthToken,
|
|
23974
|
+
resolveGitBranchPrefix: () => resolveGitBranchPrefix,
|
|
23850
23975
|
resolveGitDirsForLockRecovery: () => resolveGitDirsForLockRecovery,
|
|
23851
23976
|
resolveGitHubIssueRepo: () => resolveGitHubIssueRepo,
|
|
23852
23977
|
resolveGithubAgentToken: () => resolveGithubAgentToken,
|
|
@@ -23859,6 +23984,7 @@ __export(index_exports, {
|
|
|
23859
23984
|
resolveLoginCommand: () => resolveLoginCommand,
|
|
23860
23985
|
resolveNewOrchestratorOptions: () => resolveNewOrchestratorOptions,
|
|
23861
23986
|
resolveNewThreadOptions: () => resolveNewThreadOptions,
|
|
23987
|
+
resolveOrchChildFollowUp: () => resolveOrchChildFollowUp,
|
|
23862
23988
|
resolveOrchestratorDefaults: () => resolveOrchestratorDefaults,
|
|
23863
23989
|
resolvePlanMarkdown: () => resolvePlanMarkdown,
|
|
23864
23990
|
resolvePrSelector: () => resolvePrSelector,
|
|
@@ -23868,6 +23994,7 @@ __export(index_exports, {
|
|
|
23868
23994
|
resolveReviewGuidelines: () => resolveReviewGuidelines,
|
|
23869
23995
|
resolveScheduleThreadId: () => resolveScheduleThreadId,
|
|
23870
23996
|
resolveSendFollowUp: () => resolveSendFollowUp,
|
|
23997
|
+
resolveSidebarGitPrompt: () => resolveSidebarGitPrompt,
|
|
23871
23998
|
resolveSlackListenMode: () => resolveSlackListenMode,
|
|
23872
23999
|
resolveThreadDefaults: () => resolveThreadDefaults,
|
|
23873
24000
|
resolveThreadEffort: () => resolveThreadEffort,
|
|
@@ -23887,6 +24014,7 @@ __export(index_exports, {
|
|
|
23887
24014
|
runSlackRelayClient: () => runSlackRelayClient,
|
|
23888
24015
|
runWorkspaceSetup: () => runWorkspaceSetup,
|
|
23889
24016
|
sameWorktreePath: () => sameWorktreePath,
|
|
24017
|
+
sanitizeGitBranchPrefix: () => sanitizeGitBranchPrefix,
|
|
23890
24018
|
sanitizeMcpServerName: () => sanitizeMcpServerName,
|
|
23891
24019
|
saveAbleTimeConnection: () => saveAbleTimeConnection,
|
|
23892
24020
|
saveAppSettings: () => saveAppSettings,
|
|
@@ -24032,55 +24160,9 @@ init_gh_errors();
|
|
|
24032
24160
|
init_git_auth_mode();
|
|
24033
24161
|
init_worktree();
|
|
24034
24162
|
init_stack();
|
|
24163
|
+
init_branch_prefix();
|
|
24035
24164
|
init_agent_git_actions();
|
|
24036
|
-
|
|
24037
|
-
// src/integrations/github.ts
|
|
24038
|
-
init_run();
|
|
24039
|
-
async function getGitHubStatus() {
|
|
24040
|
-
const which = await run("which", ["gh"], { reject: false });
|
|
24041
|
-
if (which.exitCode !== 0 || !which.stdout.trim()) {
|
|
24042
|
-
return {
|
|
24043
|
-
connected: false,
|
|
24044
|
-
login: null,
|
|
24045
|
-
hosts: [],
|
|
24046
|
-
reason: "gh CLI not found on PATH"
|
|
24047
|
-
};
|
|
24048
|
-
}
|
|
24049
|
-
const loginResult = await run(
|
|
24050
|
-
"gh",
|
|
24051
|
-
["api", "user", "--jq", ".login"],
|
|
24052
|
-
{ reject: false }
|
|
24053
|
-
);
|
|
24054
|
-
if (loginResult.exitCode === 0 && loginResult.stdout.trim()) {
|
|
24055
|
-
return {
|
|
24056
|
-
connected: true,
|
|
24057
|
-
login: loginResult.stdout.trim(),
|
|
24058
|
-
hosts: ["github.com"],
|
|
24059
|
-
reason: null
|
|
24060
|
-
};
|
|
24061
|
-
}
|
|
24062
|
-
const status = await run("gh", ["auth", "status"], { reject: false });
|
|
24063
|
-
const text7 = `${status.stdout}
|
|
24064
|
-
${status.stderr}`;
|
|
24065
|
-
const loginMatch = text7.match(/Logged in to ([^\s]+) account (\S+)/i) ?? text7.match(/Logged in to ([^\s]+) as (\S+)/i);
|
|
24066
|
-
if (loginMatch) {
|
|
24067
|
-
return {
|
|
24068
|
-
connected: true,
|
|
24069
|
-
login: loginMatch[2].replace(/['"]/g, ""),
|
|
24070
|
-
hosts: [loginMatch[1]],
|
|
24071
|
-
reason: null
|
|
24072
|
-
};
|
|
24073
|
-
}
|
|
24074
|
-
return {
|
|
24075
|
-
connected: false,
|
|
24076
|
-
login: null,
|
|
24077
|
-
hosts: [],
|
|
24078
|
-
reason: status.stderr.trim() || status.stdout.trim() || "Not logged in to GitHub (run: gh auth login)"
|
|
24079
|
-
};
|
|
24080
|
-
}
|
|
24081
|
-
async function refreshGitHubAuth() {
|
|
24082
|
-
return getGitHubStatus();
|
|
24083
|
-
}
|
|
24165
|
+
init_github();
|
|
24084
24166
|
|
|
24085
24167
|
// src/integrations/linear.ts
|
|
24086
24168
|
init_fetch();
|
|
@@ -24605,6 +24687,16 @@ query SideboardLabels($first: Int!) {
|
|
|
24605
24687
|
}
|
|
24606
24688
|
}
|
|
24607
24689
|
`;
|
|
24690
|
+
var TEAM_LABELS_QUERY = `
|
|
24691
|
+
query SideboardTeamLabels($id: String!, $first: Int!, $after: String) {
|
|
24692
|
+
team(id: $id) {
|
|
24693
|
+
labels(first: $first, after: $after) {
|
|
24694
|
+
nodes { id name }
|
|
24695
|
+
pageInfo { hasNextPage endCursor }
|
|
24696
|
+
}
|
|
24697
|
+
}
|
|
24698
|
+
}
|
|
24699
|
+
`;
|
|
24608
24700
|
var PROJECTS_QUERY = `
|
|
24609
24701
|
query SideboardProjects($first: Int!, $filter: ProjectFilter) {
|
|
24610
24702
|
projects(first: $first, filter: $filter) {
|
|
@@ -24978,15 +25070,38 @@ function formatRelationList(relations) {
|
|
|
24978
25070
|
if (!relations.length) return "(none)";
|
|
24979
25071
|
return relations.map((r) => `${r.type} ${r.issue.identifier || r.issue.id}`).join(", ");
|
|
24980
25072
|
}
|
|
24981
|
-
|
|
24982
|
-
|
|
24983
|
-
return (json.issueLabels?.nodes ?? []).flatMap((node) => {
|
|
25073
|
+
function mapLabelNodes(nodes) {
|
|
25074
|
+
return (nodes ?? []).flatMap((node) => {
|
|
24984
25075
|
const id = String(node.id ?? "").trim();
|
|
24985
25076
|
const name = String(node.name ?? "").trim();
|
|
24986
25077
|
if (!id) return [];
|
|
24987
25078
|
return [{ id, name }];
|
|
24988
25079
|
});
|
|
24989
25080
|
}
|
|
25081
|
+
async function listLinearWorkspaceLabels(opts) {
|
|
25082
|
+
const json = await linearGraphql(LABELS_QUERY, { first: 250 }, opts);
|
|
25083
|
+
return mapLabelNodes(json.issueLabels?.nodes);
|
|
25084
|
+
}
|
|
25085
|
+
async function listLinearLabels(opts) {
|
|
25086
|
+
const teamId = opts?.teamId?.trim();
|
|
25087
|
+
if (teamId) {
|
|
25088
|
+
const out = [];
|
|
25089
|
+
let after;
|
|
25090
|
+
for (let page = 0; page < 4; page++) {
|
|
25091
|
+
const json = await linearGraphql(
|
|
25092
|
+
TEAM_LABELS_QUERY,
|
|
25093
|
+
after ? { id: teamId, first: 250, after } : { id: teamId, first: 250 },
|
|
25094
|
+
opts
|
|
25095
|
+
);
|
|
25096
|
+
const conn = json.team?.labels;
|
|
25097
|
+
out.push(...mapLabelNodes(conn?.nodes));
|
|
25098
|
+
if (!conn?.pageInfo?.hasNextPage || !conn.pageInfo.endCursor) break;
|
|
25099
|
+
after = conn.pageInfo.endCursor;
|
|
25100
|
+
}
|
|
25101
|
+
if (out.length) return out;
|
|
25102
|
+
}
|
|
25103
|
+
return listLinearWorkspaceLabels(opts);
|
|
25104
|
+
}
|
|
24990
25105
|
async function listLinearProjects(filter, opts) {
|
|
24991
25106
|
const json = await linearGraphql(PROJECTS_QUERY, { first: 50, filter: filter ?? {} }, opts);
|
|
24992
25107
|
return (json.projects?.nodes ?? []).flatMap((node) => {
|
|
@@ -25281,7 +25396,7 @@ async function updateLinearIssue(input, opts) {
|
|
|
25281
25396
|
}
|
|
25282
25397
|
const addRelations = input.relations?.length ? input.relations : void 0;
|
|
25283
25398
|
const removeRelations = input.removeRelations?.length ? input.removeRelations : void 0;
|
|
25284
|
-
const needsIssue = Boolean(input.state?.trim()) || input.cycle !== void 0 || Boolean(addRelations) || Boolean(removeRelations);
|
|
25399
|
+
const needsIssue = Boolean(input.state?.trim()) || input.cycle !== void 0 || input.labels !== void 0 || Boolean(addRelations) || Boolean(removeRelations);
|
|
25285
25400
|
const existing = needsIssue ? await getLinearIssue(issueId, opts) : void 0;
|
|
25286
25401
|
if (input.state?.trim()) {
|
|
25287
25402
|
const { teams } = await listLinearTeams(opts);
|
|
@@ -25316,7 +25431,10 @@ async function updateLinearIssue(input, opts) {
|
|
|
25316
25431
|
mutationInput.priority = normalizePriority(input.priority);
|
|
25317
25432
|
}
|
|
25318
25433
|
if (input.labels !== void 0) {
|
|
25319
|
-
mutationInput.labelIds = await resolveLinearLabelIds(input.labels,
|
|
25434
|
+
mutationInput.labelIds = await resolveLinearLabelIds(input.labels, {
|
|
25435
|
+
...opts,
|
|
25436
|
+
teamId: existing?.team?.id
|
|
25437
|
+
});
|
|
25320
25438
|
}
|
|
25321
25439
|
if (input.project !== void 0) {
|
|
25322
25440
|
mutationInput.projectId = await resolveLinearProjectId(input.project, opts);
|
|
@@ -25622,7 +25740,7 @@ function parseProjectTitles(raw) {
|
|
|
25622
25740
|
}
|
|
25623
25741
|
async function listGitHubIssueProjects(number, cwd, repoArgs) {
|
|
25624
25742
|
const result = await gh(
|
|
25625
|
-
["issue", "view", String(number), ...repoArgs, "--json", "projectItems
|
|
25743
|
+
["issue", "view", String(number), ...repoArgs, "--json", "projectItems"],
|
|
25626
25744
|
cwd,
|
|
25627
25745
|
{ reject: false }
|
|
25628
25746
|
);
|
|
@@ -28322,6 +28440,7 @@ async function getHomeBoardInputs(workspaces, opts) {
|
|
|
28322
28440
|
|
|
28323
28441
|
// src/mcp/server.ts
|
|
28324
28442
|
init_home_board();
|
|
28443
|
+
init_github();
|
|
28325
28444
|
|
|
28326
28445
|
// src/mcp/create-thread-agent.ts
|
|
28327
28446
|
init_cursor();
|
|
@@ -28956,7 +29075,7 @@ async function startMcpServer() {
|
|
|
28956
29075
|
);
|
|
28957
29076
|
server.tool(
|
|
28958
29077
|
"send_to_thread",
|
|
28959
|
-
'
|
|
29078
|
+
'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.',
|
|
28960
29079
|
{
|
|
28961
29080
|
ref: import_zod9.z.string(),
|
|
28962
29081
|
prompt: import_zod9.z.string(),
|
|
@@ -28969,7 +29088,9 @@ async function startMcpServer() {
|
|
|
28969
29088
|
orch.stop(ref, { clearQueue: true, notifyParent: false });
|
|
28970
29089
|
}
|
|
28971
29090
|
}
|
|
28972
|
-
const thread = await orch.send(ref, prompt
|
|
29091
|
+
const thread = await orch.send(ref, prompt, {
|
|
29092
|
+
followUp: resolveOrchChildFollowUp()
|
|
29093
|
+
});
|
|
28973
29094
|
return mcpJson({
|
|
28974
29095
|
id: thread.id,
|
|
28975
29096
|
status: thread.status,
|
|
@@ -28980,7 +29101,7 @@ async function startMcpServer() {
|
|
|
28980
29101
|
);
|
|
28981
29102
|
server.tool(
|
|
28982
29103
|
"wait_for_turn",
|
|
28983
|
-
"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
|
|
29104
|
+
"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).",
|
|
28984
29105
|
{
|
|
28985
29106
|
ref: import_zod9.z.string(),
|
|
28986
29107
|
timeoutMs: import_zod9.z.number().optional()
|
|
@@ -29137,7 +29258,7 @@ async function startMcpServer() {
|
|
|
29137
29258
|
);
|
|
29138
29259
|
server.tool(
|
|
29139
29260
|
"ask_git",
|
|
29140
|
-
"Commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge \u2014 same
|
|
29261
|
+
"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.",
|
|
29141
29262
|
{
|
|
29142
29263
|
ref: import_zod9.z.string().describe("Worktree thread id/ref"),
|
|
29143
29264
|
action: import_zod9.z.enum(AGENT_GIT_ACTIONS).describe(
|
|
@@ -32058,6 +32179,7 @@ init_outbound_watch();
|
|
|
32058
32179
|
estimateMessageChars,
|
|
32059
32180
|
estimateOccupancyTokens,
|
|
32060
32181
|
estimateThreadChars,
|
|
32182
|
+
examplePrefixedBranch,
|
|
32061
32183
|
expandComposerPrompt,
|
|
32062
32184
|
extractBrightsyContextSummary,
|
|
32063
32185
|
extractGhErrorDetail,
|
|
@@ -32170,6 +32292,7 @@ init_outbound_watch();
|
|
|
32170
32292
|
ghHeadRef,
|
|
32171
32293
|
ghRepoSelectArgs,
|
|
32172
32294
|
git,
|
|
32295
|
+
gitBranchPrefixSetting,
|
|
32173
32296
|
githubAgentGitEnv,
|
|
32174
32297
|
githubHttpsInsteadOfEntries,
|
|
32175
32298
|
githubRelationEditFlag,
|
|
@@ -32418,6 +32541,7 @@ init_outbound_watch();
|
|
|
32418
32541
|
resolveEffectiveIssueSource,
|
|
32419
32542
|
resolveFilesToCopy,
|
|
32420
32543
|
resolveGhAuthToken,
|
|
32544
|
+
resolveGitBranchPrefix,
|
|
32421
32545
|
resolveGitDirsForLockRecovery,
|
|
32422
32546
|
resolveGitHubIssueRepo,
|
|
32423
32547
|
resolveGithubAgentToken,
|
|
@@ -32430,6 +32554,7 @@ init_outbound_watch();
|
|
|
32430
32554
|
resolveLoginCommand,
|
|
32431
32555
|
resolveNewOrchestratorOptions,
|
|
32432
32556
|
resolveNewThreadOptions,
|
|
32557
|
+
resolveOrchChildFollowUp,
|
|
32433
32558
|
resolveOrchestratorDefaults,
|
|
32434
32559
|
resolvePlanMarkdown,
|
|
32435
32560
|
resolvePrSelector,
|
|
@@ -32439,6 +32564,7 @@ init_outbound_watch();
|
|
|
32439
32564
|
resolveReviewGuidelines,
|
|
32440
32565
|
resolveScheduleThreadId,
|
|
32441
32566
|
resolveSendFollowUp,
|
|
32567
|
+
resolveSidebarGitPrompt,
|
|
32442
32568
|
resolveSlackListenMode,
|
|
32443
32569
|
resolveThreadDefaults,
|
|
32444
32570
|
resolveThreadEffort,
|
|
@@ -32458,6 +32584,7 @@ init_outbound_watch();
|
|
|
32458
32584
|
runSlackRelayClient,
|
|
32459
32585
|
runWorkspaceSetup,
|
|
32460
32586
|
sameWorktreePath,
|
|
32587
|
+
sanitizeGitBranchPrefix,
|
|
32461
32588
|
sanitizeMcpServerName,
|
|
32462
32589
|
saveAbleTimeConnection,
|
|
32463
32590
|
saveAppSettings,
|