@sideboard-ai/core 0.1.168 → 0.1.170
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-BMS53RIZ.js → abletime-ESVTHTFH.js} +2 -2
- package/dist/{abletime-AGF54TNA.js → abletime-IC2V7CNB.js} +2 -2
- package/dist/{agents-TSO4MB3X.js → agents-GOBVOXFG.js} +9 -9
- package/dist/{agents-KWJXZAHB.js → agents-ZCIMZHXZ.js} +9 -9
- package/dist/{app-settings-BRLZQA7N.js → app-settings-LF3TS7XS.js} +5 -1
- package/dist/{app-settings-JJQDWPEK.js → app-settings-VMOTQORT.js} +5 -1
- package/dist/{chunk-74TWOSQP.js → chunk-3C4B52TS.js} +78 -42
- package/dist/{chunk-CVZ4KXVP.js → chunk-7IUO67CW.js} +122 -2
- package/dist/{chunk-HSGSQA42.js → chunk-DHPZW2EA.js} +8 -34
- package/dist/{chunk-KJFFQAMA.js → chunk-DKLGWRWC.js} +1 -1
- package/dist/{chunk-NYMFNUT5.js → chunk-GQHVICNT.js} +194 -147
- package/dist/{chunk-ILXKJ4ZD.js → chunk-NB7TEKCF.js} +1 -1
- package/dist/{chunk-RS756MKF.js → chunk-P2VCMIZU.js} +8 -34
- package/dist/{chunk-UIR4VDYA.js → chunk-SAZIRJR4.js} +30 -10
- package/dist/{chunk-UVLPL2FJ.js → chunk-TEI72FYD.js} +198 -216
- package/dist/{chunk-3A54S244.js → chunk-UDEWGTP6.js} +29 -10
- package/dist/{chunk-TW5A2HFY.js → chunk-Y7DJA3UW.js} +78 -42
- package/dist/{chunk-LTXS26K5.js → chunk-YMF5WCIA.js} +122 -2
- package/dist/{coordinator-prompt-75N74HAO.js → coordinator-prompt-JTDCEU74.js} +3 -3
- package/dist/{coordinator-prompt-Y372QRFE.js → coordinator-prompt-RRUU2OYO.js} +3 -3
- package/dist/{global-workspace-JNNFVSP7.js → global-workspace-4SI3CRRT.js} +3 -3
- package/dist/{global-workspace-TPE4LKVM.js → global-workspace-ZF6EJAM3.js} +3 -3
- package/dist/index.cjs +421 -278
- package/dist/index.d.cts +135 -37
- package/dist/index.d.ts +135 -37
- package/dist/index.js +33 -19
- package/dist/mcp/run-stdio.cjs +401 -207
- package/dist/mcp/run-stdio.js +8 -8
- package/dist/{orchestrator-XG3QCMOS.js → orchestrator-LE6L6MJC.js} +5 -5
- package/dist/{orchestrator-IIME6KXQ.js → orchestrator-UZSFTDKA.js} +5 -5
- package/dist/{workspaces-2IGQNFPL.js → workspaces-A7C3WA54.js} +3 -3
- package/dist/{workspaces-BWZSDSGG.js → workspaces-NOC2MWQV.js} +3 -3
- package/dist/{worktree-7X7XNSYL.js → worktree-GXO2VDQF.js} +12 -4
- package/dist/{worktree-5BFEK6PF.js → worktree-PODE23PD.js} +12 -4
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -530,6 +530,36 @@ var init_paths = __esm({
|
|
|
530
530
|
}
|
|
531
531
|
});
|
|
532
532
|
|
|
533
|
+
// src/agents/orchestrator-capable.ts
|
|
534
|
+
function isOrchestratorCapableAgent(agent) {
|
|
535
|
+
return Boolean(
|
|
536
|
+
agent && ORCHESTRATOR_AGENT_KINDS.includes(agent)
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
function assertOrchestratorCapableAgent(agent, context = "orchestration") {
|
|
540
|
+
if (!isOrchestratorCapableAgent(agent)) {
|
|
541
|
+
throw new Error(
|
|
542
|
+
`${agent} cannot run ${context} \u2014 it does not support Sideboard MCP. Use Claude, Cursor, Codex, or OpenCode.`
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
return agent;
|
|
546
|
+
}
|
|
547
|
+
function coerceOrchestratorAgent(agent, fallback = "claude") {
|
|
548
|
+
return isOrchestratorCapableAgent(agent) ? agent : fallback;
|
|
549
|
+
}
|
|
550
|
+
var ORCHESTRATOR_AGENT_KINDS;
|
|
551
|
+
var init_orchestrator_capable = __esm({
|
|
552
|
+
"src/agents/orchestrator-capable.ts"() {
|
|
553
|
+
"use strict";
|
|
554
|
+
ORCHESTRATOR_AGENT_KINDS = [
|
|
555
|
+
"claude",
|
|
556
|
+
"codex",
|
|
557
|
+
"opencode",
|
|
558
|
+
"cursor"
|
|
559
|
+
];
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
|
|
533
563
|
// src/hook/nested-electron-env.ts
|
|
534
564
|
function isNestedElectronEnvKey(key) {
|
|
535
565
|
return NESTED_ELECTRON_ENV_PREFIXES.some((prefix) => key.startsWith(prefix));
|
|
@@ -1008,7 +1038,9 @@ __export(app_settings_exports, {
|
|
|
1008
1038
|
resolveAgentExecutable: () => resolveAgentExecutable,
|
|
1009
1039
|
resolveClaudeExecutable: () => resolveClaudeExecutable,
|
|
1010
1040
|
resolveEffectiveIssueSource: () => resolveEffectiveIssueSource,
|
|
1041
|
+
resolveNewOrchestratorOptions: () => resolveNewOrchestratorOptions,
|
|
1011
1042
|
resolveNewThreadOptions: () => resolveNewThreadOptions,
|
|
1043
|
+
resolveOrchestratorDefaults: () => resolveOrchestratorDefaults,
|
|
1012
1044
|
resolveThreadDefaults: () => resolveThreadDefaults,
|
|
1013
1045
|
resolveViewerProfile: () => resolveViewerProfile,
|
|
1014
1046
|
resolveViewerProfileForRepo: () => resolveViewerProfileForRepo,
|
|
@@ -1270,6 +1302,25 @@ function normalizeIntegrations(raw) {
|
|
|
1270
1302
|
}
|
|
1271
1303
|
return out;
|
|
1272
1304
|
}
|
|
1305
|
+
function normalizeOrchestratorDefaults(raw) {
|
|
1306
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
1307
|
+
const source = raw;
|
|
1308
|
+
const out = {};
|
|
1309
|
+
if (typeof source.agent === "string" && isOrchestratorCapableAgent(source.agent)) {
|
|
1310
|
+
out.agent = source.agent;
|
|
1311
|
+
}
|
|
1312
|
+
if (typeof source.model === "string") {
|
|
1313
|
+
const model = source.model.trim();
|
|
1314
|
+
if (model) out.model = model;
|
|
1315
|
+
}
|
|
1316
|
+
if (normalizeThinkingEffort(source.effort)) {
|
|
1317
|
+
out.effort = normalizeThinkingEffort(source.effort);
|
|
1318
|
+
}
|
|
1319
|
+
if (typeof source.fast === "boolean") {
|
|
1320
|
+
out.fast = source.fast;
|
|
1321
|
+
}
|
|
1322
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
1323
|
+
}
|
|
1273
1324
|
function normalizeDefaults(raw) {
|
|
1274
1325
|
if (!raw || typeof raw !== "object") return {};
|
|
1275
1326
|
const source = raw;
|
|
@@ -1289,6 +1340,8 @@ function normalizeDefaults(raw) {
|
|
|
1289
1340
|
}
|
|
1290
1341
|
const notes = foldLegacyRolesIntoNotes(source.roles, source.role, source.notes);
|
|
1291
1342
|
if (notes) out.notes = notes;
|
|
1343
|
+
const orchestrator = normalizeOrchestratorDefaults(source.orchestrator);
|
|
1344
|
+
if (orchestrator) out.orchestrator = orchestrator;
|
|
1292
1345
|
return out;
|
|
1293
1346
|
}
|
|
1294
1347
|
function profileRepoKey(path2) {
|
|
@@ -1832,6 +1885,39 @@ function updateIntegrationsSettings(patch) {
|
|
|
1832
1885
|
}
|
|
1833
1886
|
return saveAppSettings({ ...current, integrations });
|
|
1834
1887
|
}
|
|
1888
|
+
function applyOrchestratorDefaultsPatch(current, patch) {
|
|
1889
|
+
const next = { ...current };
|
|
1890
|
+
if ("agent" in patch) {
|
|
1891
|
+
if (patch.agent == null) {
|
|
1892
|
+
delete next.agent;
|
|
1893
|
+
} else if (isOrchestratorCapableAgent(patch.agent)) {
|
|
1894
|
+
next.agent = patch.agent;
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
if ("model" in patch) {
|
|
1898
|
+
if (patch.model == null || patch.model.trim() === "") {
|
|
1899
|
+
delete next.model;
|
|
1900
|
+
} else {
|
|
1901
|
+
next.model = patch.model.trim();
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
if ("effort" in patch) {
|
|
1905
|
+
if (patch.effort == null) {
|
|
1906
|
+
delete next.effort;
|
|
1907
|
+
} else {
|
|
1908
|
+
const effort = normalizeThinkingEffort(patch.effort);
|
|
1909
|
+
if (effort) next.effort = effort;
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
if ("fast" in patch) {
|
|
1913
|
+
if (patch.fast == null) {
|
|
1914
|
+
delete next.fast;
|
|
1915
|
+
} else {
|
|
1916
|
+
next.fast = Boolean(patch.fast);
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
return Object.keys(next).length > 0 ? next : void 0;
|
|
1920
|
+
}
|
|
1835
1921
|
function updateDefaultsSettings(patch) {
|
|
1836
1922
|
const current = loadAppSettings();
|
|
1837
1923
|
const defaults = { ...current.defaults };
|
|
@@ -1869,6 +1955,18 @@ function updateDefaultsSettings(patch) {
|
|
|
1869
1955
|
if (!notes) delete defaults.notes;
|
|
1870
1956
|
else defaults.notes = notes;
|
|
1871
1957
|
}
|
|
1958
|
+
if ("orchestrator" in patch) {
|
|
1959
|
+
if (patch.orchestrator == null) {
|
|
1960
|
+
delete defaults.orchestrator;
|
|
1961
|
+
} else {
|
|
1962
|
+
const orchestrator = applyOrchestratorDefaultsPatch(
|
|
1963
|
+
defaults.orchestrator,
|
|
1964
|
+
patch.orchestrator
|
|
1965
|
+
);
|
|
1966
|
+
if (orchestrator) defaults.orchestrator = orchestrator;
|
|
1967
|
+
else delete defaults.orchestrator;
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1872
1970
|
delete defaults.roles;
|
|
1873
1971
|
delete defaults.role;
|
|
1874
1972
|
return saveAppSettings({ ...current, defaults });
|
|
@@ -1974,8 +2072,22 @@ function resolveThreadDefaults(settings = loadAppSettings()) {
|
|
|
1974
2072
|
fast: getDefaultFast(settings)
|
|
1975
2073
|
};
|
|
1976
2074
|
}
|
|
1977
|
-
function
|
|
1978
|
-
const
|
|
2075
|
+
function resolveOrchestratorDefaults(settings = loadAppSettings()) {
|
|
2076
|
+
const account = resolveThreadDefaults(settings);
|
|
2077
|
+
const orch = settings.defaults.orchestrator;
|
|
2078
|
+
const agent = coerceOrchestratorAgent(orch?.agent ?? account.agent);
|
|
2079
|
+
let model = orch ? orch.model?.trim() || null : account.model;
|
|
2080
|
+
if (model && agent !== "cursor" && /^(default|auto)$/i.test(model.trim())) {
|
|
2081
|
+
model = null;
|
|
2082
|
+
}
|
|
2083
|
+
return {
|
|
2084
|
+
agent,
|
|
2085
|
+
model,
|
|
2086
|
+
effort: orch?.effort ?? account.effort,
|
|
2087
|
+
fast: orch?.fast ?? account.fast
|
|
2088
|
+
};
|
|
2089
|
+
}
|
|
2090
|
+
function mergeThreadOptionOverrides(defaults, overrides) {
|
|
1979
2091
|
const effort = overrides.effort === void 0 || overrides.effort === null ? defaults.effort : normalizeThinkingEffort(overrides.effort) ?? defaults.effort;
|
|
1980
2092
|
const agent = overrides.agent ?? defaults.agent;
|
|
1981
2093
|
let model = overrides.model === void 0 ? defaults.model : overrides.model?.trim() || null;
|
|
@@ -1989,6 +2101,12 @@ function resolveNewThreadOptions(overrides = {}, settings = loadAppSettings()) {
|
|
|
1989
2101
|
fast: overrides.fast === void 0 || overrides.fast === null ? defaults.fast : Boolean(overrides.fast)
|
|
1990
2102
|
};
|
|
1991
2103
|
}
|
|
2104
|
+
function resolveNewThreadOptions(overrides = {}, settings = loadAppSettings()) {
|
|
2105
|
+
return mergeThreadOptionOverrides(resolveThreadDefaults(settings), overrides);
|
|
2106
|
+
}
|
|
2107
|
+
function resolveNewOrchestratorOptions(overrides = {}, settings = loadAppSettings()) {
|
|
2108
|
+
return mergeThreadOptionOverrides(resolveOrchestratorDefaults(settings), overrides);
|
|
2109
|
+
}
|
|
1992
2110
|
function isLinearConnected(settings = loadAppSettings()) {
|
|
1993
2111
|
return hasLinearCredentials(settings.integrations);
|
|
1994
2112
|
}
|
|
@@ -2110,6 +2228,10 @@ function brightsyInjectWorktreeMcpEnabled(settings = loadAppSettings()) {
|
|
|
2110
2228
|
}
|
|
2111
2229
|
function brightsyCloudConnectAgent(settings = loadAppSettings()) {
|
|
2112
2230
|
const fallback = settings.brightsy.cloudConnectAgent && CLOUD_CONNECT_AGENTS.has(settings.brightsy.cloudConnectAgent) ? settings.brightsy.cloudConnectAgent : "claude";
|
|
2231
|
+
const orchAgent = settings.defaults.orchestrator?.agent;
|
|
2232
|
+
if (orchAgent && CLOUD_CONNECT_AGENTS.has(orchAgent)) {
|
|
2233
|
+
return orchAgent;
|
|
2234
|
+
}
|
|
2113
2235
|
const preferred = getDefaultAgent(settings);
|
|
2114
2236
|
if (CLOUD_CONNECT_AGENTS.has(preferred)) {
|
|
2115
2237
|
return preferred;
|
|
@@ -2320,6 +2442,7 @@ var init_app_settings = __esm({
|
|
|
2320
2442
|
import_node_fs7 = require("fs");
|
|
2321
2443
|
import_node_os3 = require("os");
|
|
2322
2444
|
import_node_path8 = require("path");
|
|
2445
|
+
init_orchestrator_capable();
|
|
2323
2446
|
init_thinking_effort();
|
|
2324
2447
|
init_nested_electron_env();
|
|
2325
2448
|
init_account_profile();
|
|
@@ -2895,36 +3018,6 @@ var init_setup_log = __esm({
|
|
|
2895
3018
|
}
|
|
2896
3019
|
});
|
|
2897
3020
|
|
|
2898
|
-
// src/agents/orchestrator-capable.ts
|
|
2899
|
-
function isOrchestratorCapableAgent(agent) {
|
|
2900
|
-
return Boolean(
|
|
2901
|
-
agent && ORCHESTRATOR_AGENT_KINDS.includes(agent)
|
|
2902
|
-
);
|
|
2903
|
-
}
|
|
2904
|
-
function assertOrchestratorCapableAgent(agent, context = "orchestration") {
|
|
2905
|
-
if (!isOrchestratorCapableAgent(agent)) {
|
|
2906
|
-
throw new Error(
|
|
2907
|
-
`${agent} cannot run ${context} \u2014 it does not support Sideboard MCP. Use Claude, Cursor, Codex, or OpenCode.`
|
|
2908
|
-
);
|
|
2909
|
-
}
|
|
2910
|
-
return agent;
|
|
2911
|
-
}
|
|
2912
|
-
function coerceOrchestratorAgent(agent, fallback = "claude") {
|
|
2913
|
-
return isOrchestratorCapableAgent(agent) ? agent : fallback;
|
|
2914
|
-
}
|
|
2915
|
-
var ORCHESTRATOR_AGENT_KINDS;
|
|
2916
|
-
var init_orchestrator_capable = __esm({
|
|
2917
|
-
"src/agents/orchestrator-capable.ts"() {
|
|
2918
|
-
"use strict";
|
|
2919
|
-
ORCHESTRATOR_AGENT_KINDS = [
|
|
2920
|
-
"claude",
|
|
2921
|
-
"codex",
|
|
2922
|
-
"opencode",
|
|
2923
|
-
"cursor"
|
|
2924
|
-
];
|
|
2925
|
-
}
|
|
2926
|
-
});
|
|
2927
|
-
|
|
2928
3021
|
// src/store/schedules.ts
|
|
2929
3022
|
function schedulesPath() {
|
|
2930
3023
|
return (0, import_node_path12.join)(appDataDir(), "schedules.json");
|
|
@@ -3930,8 +4023,10 @@ function lookupSoccerTeam(titleOrSlug) {
|
|
|
3930
4023
|
}
|
|
3931
4024
|
function teamNameFromSlug(slug) {
|
|
3932
4025
|
const normalized = slug.toLowerCase().replace(/^thread\//, "");
|
|
3933
|
-
const
|
|
3934
|
-
const
|
|
4026
|
+
const withoutTicket = normalized.replace(/^[a-z]{2,8}-\d{1,6}-/, "").replace(/^\d{1,8}-/, "");
|
|
4027
|
+
const lookup = withoutTicket || normalized;
|
|
4028
|
+
const suffixMatch = lookup.match(/^(.+)-(\d+)$/);
|
|
4029
|
+
const base = suffixMatch?.[1] ?? lookup;
|
|
3935
4030
|
const suffix = suffixMatch?.[2];
|
|
3936
4031
|
const team = FAMOUS_SOCCER_TEAM_SEEDS.find((t) => t.slug === base);
|
|
3937
4032
|
if (team) return suffix ? `${team.name} ${suffix}` : team.name;
|
|
@@ -4352,6 +4447,25 @@ function worktreeNameFromPath(worktreePath) {
|
|
|
4352
4447
|
const parts = normalized.split("/");
|
|
4353
4448
|
return parts[parts.length - 1] || worktreePath;
|
|
4354
4449
|
}
|
|
4450
|
+
function ticketSlugForBranch(sourceRef) {
|
|
4451
|
+
const raw = sourceRef.trim();
|
|
4452
|
+
if (!raw) return null;
|
|
4453
|
+
const linear = raw.match(/\b([A-Za-z]{2,8}-\d{1,6})\b/);
|
|
4454
|
+
if (linear) return linear[1].toLowerCase();
|
|
4455
|
+
const hashed = raw.match(/^#(\d{1,8})$/);
|
|
4456
|
+
if (hashed) return hashed[1];
|
|
4457
|
+
const digits = raw.match(/^(\d{1,8})$/);
|
|
4458
|
+
if (digits) return digits[1];
|
|
4459
|
+
const slug = raw.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
4460
|
+
return slug || null;
|
|
4461
|
+
}
|
|
4462
|
+
function worktreeSlugForTicket(ticketRef, teamSlug) {
|
|
4463
|
+
const ticket = ticketSlugForBranch(ticketRef);
|
|
4464
|
+
const team = teamSlug.trim().replace(/^thread\//, "");
|
|
4465
|
+
if (!ticket) return team;
|
|
4466
|
+
if (!team) return ticket;
|
|
4467
|
+
return `${ticket}-${team}`;
|
|
4468
|
+
}
|
|
4355
4469
|
function isPlaceholderBranch(branchName, worktreePath) {
|
|
4356
4470
|
const branch = branchName.trim();
|
|
4357
4471
|
if (!branch || branch === "HEAD") return true;
|
|
@@ -5828,6 +5942,7 @@ var init_stack = __esm({
|
|
|
5828
5942
|
var worktree_exports = {};
|
|
5829
5943
|
__export(worktree_exports, {
|
|
5830
5944
|
FAMOUS_SOCCER_TEAMS: () => FAMOUS_SOCCER_TEAMS,
|
|
5945
|
+
PR_DETAILS_JSON_FIELDS: () => PR_DETAILS_JSON_FIELDS,
|
|
5831
5946
|
allocateTeamName: () => allocateTeamName,
|
|
5832
5947
|
allocateTeamSlug: () => allocateTeamSlug,
|
|
5833
5948
|
branchDisplayLabel: () => branchDisplayLabel,
|
|
@@ -5866,6 +5981,7 @@ __export(worktree_exports, {
|
|
|
5866
5981
|
originFetchBranch: () => originFetchBranch,
|
|
5867
5982
|
originGhRepoEnv: () => originGhRepoEnv,
|
|
5868
5983
|
parseGithubSlugFromRemoteUrl: () => parseGithubSlugFromRemoteUrl,
|
|
5984
|
+
parsePrDetailsView: () => parsePrDetailsView,
|
|
5869
5985
|
pushBranch: () => pushBranch,
|
|
5870
5986
|
removeWorktree: () => removeWorktree,
|
|
5871
5987
|
resolveDefaultBranch: () => resolveDefaultBranch,
|
|
@@ -5878,9 +5994,11 @@ __export(worktree_exports, {
|
|
|
5878
5994
|
slugify: () => slugify,
|
|
5879
5995
|
suggestSlug: () => suggestSlug,
|
|
5880
5996
|
threadDisplayLabel: () => threadDisplayLabel,
|
|
5997
|
+
ticketSlugForBranch: () => ticketSlugForBranch,
|
|
5881
5998
|
worktreeDisplayLabel: () => worktreeDisplayLabel,
|
|
5882
5999
|
worktreeDisplayLabelForGroup: () => worktreeDisplayLabelForGroup,
|
|
5883
|
-
worktreeNameFromPath: () => worktreeNameFromPath
|
|
6000
|
+
worktreeNameFromPath: () => worktreeNameFromPath,
|
|
6001
|
+
worktreeSlugForTicket: () => worktreeSlugForTicket
|
|
5884
6002
|
});
|
|
5885
6003
|
async function lookupGithubGraphqlReset(cwd) {
|
|
5886
6004
|
const result = await gh(["api", "rate_limit"], cwd, { reject: false });
|
|
@@ -6441,48 +6559,15 @@ async function getPrMeta(cwd, selector) {
|
|
|
6441
6559
|
return null;
|
|
6442
6560
|
}
|
|
6443
6561
|
}
|
|
6444
|
-
|
|
6445
|
-
const slug = await resolveGithubRepoSlug(cwd);
|
|
6446
|
-
const viewArgs = [
|
|
6447
|
-
"pr",
|
|
6448
|
-
"view",
|
|
6449
|
-
selector,
|
|
6450
|
-
"--json",
|
|
6451
|
-
[
|
|
6452
|
-
"number",
|
|
6453
|
-
"title",
|
|
6454
|
-
"body",
|
|
6455
|
-
"url",
|
|
6456
|
-
"state",
|
|
6457
|
-
"isDraft",
|
|
6458
|
-
"reviewDecision",
|
|
6459
|
-
"author",
|
|
6460
|
-
"baseRefName",
|
|
6461
|
-
"headRefName",
|
|
6462
|
-
"additions",
|
|
6463
|
-
"deletions",
|
|
6464
|
-
"changedFiles",
|
|
6465
|
-
"comments",
|
|
6466
|
-
"reviews"
|
|
6467
|
-
].join(",")
|
|
6468
|
-
];
|
|
6469
|
-
if (slug) viewArgs.push("--repo", slug);
|
|
6470
|
-
const { stdout, exitCode, stderr } = await gh(viewArgs, cwd, { reject: false });
|
|
6471
|
-
if (exitCode !== 0 || !stdout.trim()) {
|
|
6472
|
-
if (stderr.trim()) {
|
|
6473
|
-
if (/no pull requests found/i.test(stderr)) return null;
|
|
6474
|
-
}
|
|
6475
|
-
return null;
|
|
6476
|
-
}
|
|
6477
|
-
let view;
|
|
6478
|
-
try {
|
|
6479
|
-
view = JSON.parse(stdout);
|
|
6480
|
-
} catch {
|
|
6481
|
-
throw new Error(stderr.trim() || "gh pr view returned invalid JSON");
|
|
6482
|
-
}
|
|
6562
|
+
function parsePrDetailsView(view) {
|
|
6483
6563
|
const author = view.author ?? {};
|
|
6484
6564
|
const comments = Array.isArray(view.comments) ? view.comments : [];
|
|
6485
6565
|
const reviews = Array.isArray(view.reviews) ? view.reviews : [];
|
|
6566
|
+
const requested = {
|
|
6567
|
+
ids: reviewerIdentities(view.reviewRequests),
|
|
6568
|
+
users: humanReviewerLogins(view.reviewRequests),
|
|
6569
|
+
teams: teamReviewerSlugs(view.reviewRequests)
|
|
6570
|
+
};
|
|
6486
6571
|
return {
|
|
6487
6572
|
number: Number(view.number),
|
|
6488
6573
|
title: String(view.title ?? ""),
|
|
@@ -6518,10 +6603,34 @@ async function getPrDetails(cwd, selector) {
|
|
|
6518
6603
|
submittedAt: normalizeGhTime(row.submittedAt)
|
|
6519
6604
|
};
|
|
6520
6605
|
}),
|
|
6606
|
+
assignees: reviewerIdentities(view.assignees),
|
|
6607
|
+
labels: labelNames(view.labels),
|
|
6608
|
+
reviewRequests: requested.ids,
|
|
6609
|
+
reviewers: requested.users,
|
|
6610
|
+
teams: requested.teams,
|
|
6521
6611
|
// CI lives in Checks tab via getPrChecks — nesting burned GraphQL points.
|
|
6522
6612
|
checks: []
|
|
6523
6613
|
};
|
|
6524
6614
|
}
|
|
6615
|
+
async function getPrDetails(cwd, selector) {
|
|
6616
|
+
const slug = await resolveGithubRepoSlug(cwd);
|
|
6617
|
+
const viewArgs = ["pr", "view", selector, "--json", PR_DETAILS_JSON_FIELDS];
|
|
6618
|
+
if (slug) viewArgs.push("--repo", slug);
|
|
6619
|
+
const { stdout, exitCode, stderr } = await gh(viewArgs, cwd, { reject: false });
|
|
6620
|
+
if (exitCode !== 0 || !stdout.trim()) {
|
|
6621
|
+
if (stderr.trim()) {
|
|
6622
|
+
if (/no pull requests found/i.test(stderr)) return null;
|
|
6623
|
+
}
|
|
6624
|
+
return null;
|
|
6625
|
+
}
|
|
6626
|
+
let view;
|
|
6627
|
+
try {
|
|
6628
|
+
view = JSON.parse(stdout);
|
|
6629
|
+
} catch {
|
|
6630
|
+
throw new Error(stderr.trim() || "gh pr view returned invalid JSON");
|
|
6631
|
+
}
|
|
6632
|
+
return parsePrDetailsView(view);
|
|
6633
|
+
}
|
|
6525
6634
|
async function fetchPrHead(repoPath, number, localBranch) {
|
|
6526
6635
|
const slug = await resolveGithubRepoSlug(repoPath);
|
|
6527
6636
|
const refspec = `+pull/${number}/head:${localBranch}`;
|
|
@@ -7232,7 +7341,7 @@ function allocateTeamSlug(repoPath) {
|
|
|
7232
7341
|
}
|
|
7233
7342
|
throw new Error("No available soccer team worktree directories left");
|
|
7234
7343
|
}
|
|
7235
|
-
var import_node_crypto6, import_node_fs18, import_node_os6, import_node_path20;
|
|
7344
|
+
var import_node_crypto6, import_node_fs18, import_node_os6, import_node_path20, PR_DETAILS_JSON_FIELDS;
|
|
7236
7345
|
var init_worktree = __esm({
|
|
7237
7346
|
"src/git/worktree.ts"() {
|
|
7238
7347
|
"use strict";
|
|
@@ -7254,9 +7363,30 @@ var init_worktree = __esm({
|
|
|
7254
7363
|
init_pr_gates();
|
|
7255
7364
|
init_stack();
|
|
7256
7365
|
init_teams();
|
|
7366
|
+
init_worktree_labels();
|
|
7257
7367
|
init_git_auth_mode();
|
|
7258
7368
|
init_workspace_scratch();
|
|
7259
7369
|
init_worktree_labels();
|
|
7370
|
+
PR_DETAILS_JSON_FIELDS = [
|
|
7371
|
+
"number",
|
|
7372
|
+
"title",
|
|
7373
|
+
"body",
|
|
7374
|
+
"url",
|
|
7375
|
+
"state",
|
|
7376
|
+
"isDraft",
|
|
7377
|
+
"reviewDecision",
|
|
7378
|
+
"author",
|
|
7379
|
+
"baseRefName",
|
|
7380
|
+
"headRefName",
|
|
7381
|
+
"additions",
|
|
7382
|
+
"deletions",
|
|
7383
|
+
"changedFiles",
|
|
7384
|
+
"comments",
|
|
7385
|
+
"reviews",
|
|
7386
|
+
"assignees",
|
|
7387
|
+
"labels",
|
|
7388
|
+
"reviewRequests"
|
|
7389
|
+
].join(",");
|
|
7260
7390
|
}
|
|
7261
7391
|
});
|
|
7262
7392
|
|
|
@@ -7724,7 +7854,7 @@ function createGlobalChat(opts) {
|
|
|
7724
7854
|
const explicit = opts.title?.trim();
|
|
7725
7855
|
const title = explicit && explicit !== CLOUD_ORCHESTRATOR_GOAL ? explicit : allocateTeamName(takenTeamSlugsForOrchestration()).name;
|
|
7726
7856
|
const sourceRef = opts.sourceRef?.trim() || (isCloud ? CLOUD_ORCHESTRATOR_GOAL : title);
|
|
7727
|
-
const resolved =
|
|
7857
|
+
const resolved = resolveNewOrchestratorOptions({
|
|
7728
7858
|
agent: opts.agent,
|
|
7729
7859
|
model: opts.model,
|
|
7730
7860
|
effort: opts.effort,
|
|
@@ -7800,7 +7930,7 @@ function findSlackCoordinator(teamId, userId) {
|
|
|
7800
7930
|
);
|
|
7801
7931
|
}
|
|
7802
7932
|
function ensureSlackCoordinator(teamId, userId, agent, opts) {
|
|
7803
|
-
const defaults =
|
|
7933
|
+
const defaults = resolveOrchestratorDefaults();
|
|
7804
7934
|
const desired = assertOrchestratorCapableAgent(agent);
|
|
7805
7935
|
const ref = slackCoordinatorSourceRef(teamId, userId);
|
|
7806
7936
|
if (!opts?.forceNew) {
|
|
@@ -7835,7 +7965,7 @@ function ensureSlackCoordinator(teamId, userId, agent, opts) {
|
|
|
7835
7965
|
});
|
|
7836
7966
|
}
|
|
7837
7967
|
function ensureCloudCoordinator(agent) {
|
|
7838
|
-
const defaults =
|
|
7968
|
+
const defaults = resolveOrchestratorDefaults();
|
|
7839
7969
|
const desired = assertOrchestratorCapableAgent(agent);
|
|
7840
7970
|
const existing = findCloudCoordinator();
|
|
7841
7971
|
if (existing) {
|
|
@@ -9304,22 +9434,38 @@ var init_brightsy_targets = __esm({
|
|
|
9304
9434
|
// src/agents/turn-input.ts
|
|
9305
9435
|
function normalizeTurnInput(input) {
|
|
9306
9436
|
if (typeof input === "string") return { prompt: input };
|
|
9307
|
-
return {
|
|
9437
|
+
return {
|
|
9438
|
+
prompt: input.prompt,
|
|
9439
|
+
cachedPrefix: input.cachedPrefix?.trim() || void 0,
|
|
9440
|
+
systemPrompt: input.systemPrompt?.trim() || void 0
|
|
9441
|
+
};
|
|
9308
9442
|
}
|
|
9309
9443
|
function dropCachedPrefixOnResume(input, sessionId) {
|
|
9310
9444
|
const turn = normalizeTurnInput(input);
|
|
9311
|
-
if (sessionId)
|
|
9445
|
+
if (sessionId) {
|
|
9446
|
+
return turn.systemPrompt ? { prompt: turn.prompt, systemPrompt: turn.systemPrompt } : { prompt: turn.prompt };
|
|
9447
|
+
}
|
|
9312
9448
|
return turn;
|
|
9313
9449
|
}
|
|
9314
9450
|
function flattenTurnInput(input) {
|
|
9315
|
-
const { cachedPrefix, prompt } = normalizeTurnInput(input);
|
|
9316
|
-
if (
|
|
9317
|
-
return `${cachedPrefix}
|
|
9451
|
+
const { cachedPrefix, prompt, systemPrompt } = normalizeTurnInput(input);
|
|
9452
|
+
if (cachedPrefix) return `${cachedPrefix}
|
|
9318
9453
|
|
|
9319
9454
|
---
|
|
9320
9455
|
|
|
9321
9456
|
Current request:
|
|
9322
9457
|
${prompt}`;
|
|
9458
|
+
if (systemPrompt) return `${systemPrompt}
|
|
9459
|
+
|
|
9460
|
+
${prompt}`;
|
|
9461
|
+
return prompt;
|
|
9462
|
+
}
|
|
9463
|
+
function splitTurnInputForSystemPrompt(input) {
|
|
9464
|
+
const turn = normalizeTurnInput(input);
|
|
9465
|
+
return {
|
|
9466
|
+
promptText: flattenTurnInput({ cachedPrefix: turn.cachedPrefix, prompt: turn.prompt }),
|
|
9467
|
+
systemPrompt: turn.systemPrompt
|
|
9468
|
+
};
|
|
9323
9469
|
}
|
|
9324
9470
|
function buildCachedUserContent(input) {
|
|
9325
9471
|
return [{ type: "text", text: flattenTurnInput(input) }];
|
|
@@ -11359,7 +11505,7 @@ var init_claude = __esm({
|
|
|
11359
11505
|
const claude = resolveClaudeExecutable();
|
|
11360
11506
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
11361
11507
|
const effective = dropCachedPrefixOnResume(input, sessionId);
|
|
11362
|
-
const promptText =
|
|
11508
|
+
const { promptText, systemPrompt } = splitTurnInputForSystemPrompt(effective);
|
|
11363
11509
|
const useStdin = promptText.length > CLAUDE_PROMPT_ARG_MAX;
|
|
11364
11510
|
if (process.env.SIDEBOARD_DEBUG_CLAUDE_TURN === "1") {
|
|
11365
11511
|
console.error(
|
|
@@ -11411,6 +11557,9 @@ var init_claude = __esm({
|
|
|
11411
11557
|
"--permission-mode",
|
|
11412
11558
|
mode.claude
|
|
11413
11559
|
];
|
|
11560
|
+
if (systemPrompt) {
|
|
11561
|
+
args.push("--append-system-prompt", systemPrompt);
|
|
11562
|
+
}
|
|
11414
11563
|
const mcpConfigPath = writeMcpServersConfig(injectedServers);
|
|
11415
11564
|
if (mcpConfigPath) {
|
|
11416
11565
|
args.push("--mcp-config", mcpConfigPath);
|
|
@@ -13832,7 +13981,50 @@ function agentGitPrompt(action, opts) {
|
|
|
13832
13981
|
return "Merge PR.";
|
|
13833
13982
|
}
|
|
13834
13983
|
}
|
|
13835
|
-
|
|
13984
|
+
function gitActionExpansion(action, base) {
|
|
13985
|
+
switch (action) {
|
|
13986
|
+
case "commit-push":
|
|
13987
|
+
return "Commit any uncommitted work with a purpose-stating message, then push to origin (`git push -u origin HEAD`; this updates an existing PR when one is linked). Do not start a checks loop unless a goal was given.";
|
|
13988
|
+
case "create-draft":
|
|
13989
|
+
return "Commit, push, then create a draft PR with `gh pr create --draft -R <origin-owner/name>` (title/body from the change purpose). Update the existing PR instead if one is linked.";
|
|
13990
|
+
case "create-web":
|
|
13991
|
+
return "Commit, push, then `gh pr create --web -R <origin-owner/name>`.";
|
|
13992
|
+
case "resolve-conflicts":
|
|
13993
|
+
return `Fetch the PR base${base ? ` (\`${base}\`)` : ""}, merge it into this branch, resolve conflicts carefully, then commit and push until the PR is mergeable.`;
|
|
13994
|
+
case "merge":
|
|
13995
|
+
return "This phrase is the explicit ask to merge this thread's open pull request on GitHub. If `gh stack view` shows a stack, use `gh stack merge`; otherwise `gh pr merge` (respect repo defaults / squash vs merge). Do not force-push main/master or merge locally into the main checkout.";
|
|
13996
|
+
}
|
|
13997
|
+
}
|
|
13998
|
+
function expandCanonicalGitRequest(prompt) {
|
|
13999
|
+
const trimmed = prompt.trim();
|
|
14000
|
+
let action = null;
|
|
14001
|
+
let base = null;
|
|
14002
|
+
for (const candidate of AGENT_GIT_ACTIONS) {
|
|
14003
|
+
if (candidate === "resolve-conflicts") continue;
|
|
14004
|
+
if (agentGitPrompt(candidate) === trimmed) {
|
|
14005
|
+
action = candidate;
|
|
14006
|
+
break;
|
|
14007
|
+
}
|
|
14008
|
+
}
|
|
14009
|
+
if (!action) {
|
|
14010
|
+
const m = RESOLVE_CONFLICTS_RE.exec(trimmed);
|
|
14011
|
+
if (m) {
|
|
14012
|
+
action = "resolve-conflicts";
|
|
14013
|
+
base = m[1] ?? null;
|
|
14014
|
+
}
|
|
14015
|
+
}
|
|
14016
|
+
let expansion = action ? gitActionExpansion(action, base) : null;
|
|
14017
|
+
if (!expansion && trimmed === "Address review comments.") {
|
|
14018
|
+
expansion = "Read the PR review feedback (`gh pr view --comments`, `gh api` review comments), make the requested changes, commit, and push.";
|
|
14019
|
+
} else if (!expansion && FIX_CI_RE.test(trimmed)) {
|
|
14020
|
+
expansion = "Investigate that failing check (`gh pr checks`, `gh run view --log-failed`), fix it, commit, and push. Loop only if a goal to keep going until it passes was given.";
|
|
14021
|
+
}
|
|
14022
|
+
if (!expansion) return prompt;
|
|
14023
|
+
return `${trimmed}
|
|
14024
|
+
|
|
14025
|
+
(Sideboard git request \u2014 do not ask for clarification: ${expansion})`;
|
|
14026
|
+
}
|
|
14027
|
+
var AGENT_GIT_ACTIONS, RESOLVE_CONFLICTS_RE, FIX_CI_RE;
|
|
13836
14028
|
var init_agent_git_actions = __esm({
|
|
13837
14029
|
"src/git/agent-git-actions.ts"() {
|
|
13838
14030
|
"use strict";
|
|
@@ -13843,6 +14035,8 @@ var init_agent_git_actions = __esm({
|
|
|
13843
14035
|
"resolve-conflicts",
|
|
13844
14036
|
"merge"
|
|
13845
14037
|
];
|
|
14038
|
+
RESOLVE_CONFLICTS_RE = /^Merge the remote branch(?: \(([^)]+)\))? into your branch and resolve conflicts\. Then, commit and push your changes\.$/;
|
|
14039
|
+
FIX_CI_RE = /^Fix CI: .+\.$/;
|
|
13846
14040
|
}
|
|
13847
14041
|
});
|
|
13848
14042
|
|
|
@@ -14100,47 +14294,82 @@ function formatToolPart(t, detail) {
|
|
|
14100
14294
|
}
|
|
14101
14295
|
function formatMessagesAsTranscript(messages, opts) {
|
|
14102
14296
|
const tools = opts?.tools ?? "full";
|
|
14103
|
-
const
|
|
14104
|
-
|
|
14105
|
-
|
|
14106
|
-
|
|
14107
|
-
|
|
14108
|
-
|
|
14109
|
-
|
|
14110
|
-
|
|
14111
|
-
|
|
14112
|
-
|
|
14113
|
-
|
|
14114
|
-
}
|
|
14115
|
-
const bits = [];
|
|
14116
|
-
if (m.text?.trim()) {
|
|
14117
|
-
bits.push(`### Agent
|
|
14297
|
+
const thinking = opts?.thinking ?? true;
|
|
14298
|
+
return messages.map((m) => formatMessageBlock(m, { tools, thinking })).join("\n\n");
|
|
14299
|
+
}
|
|
14300
|
+
function formatMessageBlock(m, opts) {
|
|
14301
|
+
if (m.role === "summary") return `## Prior summary
|
|
14302
|
+
${m.text}`;
|
|
14303
|
+
if (m.role === "user") return `### User
|
|
14304
|
+
${m.text}`;
|
|
14305
|
+
const bits = [];
|
|
14306
|
+
if (m.text?.trim()) {
|
|
14307
|
+
bits.push(`### Agent
|
|
14118
14308
|
${m.text}`);
|
|
14119
|
-
|
|
14120
|
-
|
|
14121
|
-
|
|
14122
|
-
|
|
14123
|
-
for (const th of
|
|
14309
|
+
} else {
|
|
14310
|
+
bits.push("### Agent");
|
|
14311
|
+
}
|
|
14312
|
+
if (opts.thinking) {
|
|
14313
|
+
for (const th of m.parts ?? []) {
|
|
14124
14314
|
if (th.type !== "thinking" || !th.text.trim()) continue;
|
|
14125
14315
|
bits.push("Thinking:");
|
|
14126
14316
|
bits.push(th.text);
|
|
14127
14317
|
}
|
|
14128
|
-
|
|
14129
|
-
|
|
14130
|
-
)
|
|
14131
|
-
|
|
14132
|
-
|
|
14133
|
-
|
|
14134
|
-
|
|
14135
|
-
|
|
14318
|
+
}
|
|
14319
|
+
const toolParts = (m.parts ?? []).filter(
|
|
14320
|
+
(p) => p.type === "tool"
|
|
14321
|
+
);
|
|
14322
|
+
if (opts.tools !== "none" && toolParts.length > 0) {
|
|
14323
|
+
if (opts.tools === "summary") bits.push("Tools:");
|
|
14324
|
+
for (const t of toolParts) {
|
|
14325
|
+
bits.push(formatToolPart(t, opts.tools));
|
|
14136
14326
|
}
|
|
14137
|
-
blocks.push(bits.join("\n"));
|
|
14138
14327
|
}
|
|
14139
|
-
return
|
|
14328
|
+
return bits.join("\n");
|
|
14140
14329
|
}
|
|
14141
14330
|
function buildSessionSeed(messages, opts) {
|
|
14142
14331
|
if (messages.length === 0) return null;
|
|
14143
|
-
const
|
|
14332
|
+
const tools = opts?.tools ?? "full";
|
|
14333
|
+
const fullCount = opts?.fullToolMessages ?? SEED_FULL_TOOL_MESSAGES;
|
|
14334
|
+
const maxChars = opts?.maxChars ?? SEED_MAX_CHARS;
|
|
14335
|
+
const olderTools = tools === "none" ? "none" : "summary";
|
|
14336
|
+
const fullFrom = Math.max(0, messages.length - fullCount);
|
|
14337
|
+
const blocks = messages.map(
|
|
14338
|
+
(m, i) => formatMessageBlock(m, {
|
|
14339
|
+
tools: i >= fullFrom ? tools : olderTools,
|
|
14340
|
+
thinking: false
|
|
14341
|
+
})
|
|
14342
|
+
);
|
|
14343
|
+
const keep = new Array(blocks.length).fill(false);
|
|
14344
|
+
let used = 0;
|
|
14345
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
14346
|
+
if (messages[i].role === "summary") {
|
|
14347
|
+
keep[i] = true;
|
|
14348
|
+
used += blocks[i].length + 2;
|
|
14349
|
+
}
|
|
14350
|
+
}
|
|
14351
|
+
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
14352
|
+
if (keep[i]) continue;
|
|
14353
|
+
const next = used + blocks[i].length + 2;
|
|
14354
|
+
if (next > maxChars && used > 0) break;
|
|
14355
|
+
keep[i] = true;
|
|
14356
|
+
used = next;
|
|
14357
|
+
}
|
|
14358
|
+
const dropped = keep.filter((k) => !k).length;
|
|
14359
|
+
const kept = [];
|
|
14360
|
+
let markerPlaced = false;
|
|
14361
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
14362
|
+
if (!keep[i]) continue;
|
|
14363
|
+
if (dropped > 0 && !markerPlaced && messages[i].role !== "summary") {
|
|
14364
|
+
kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
|
|
14365
|
+
markerPlaced = true;
|
|
14366
|
+
}
|
|
14367
|
+
kept.push(blocks[i]);
|
|
14368
|
+
}
|
|
14369
|
+
if (dropped > 0 && !markerPlaced) {
|
|
14370
|
+
kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
|
|
14371
|
+
}
|
|
14372
|
+
const body = kept.join("\n\n");
|
|
14144
14373
|
if (!body.trim()) return null;
|
|
14145
14374
|
return [
|
|
14146
14375
|
"Sideboard conversation context (restored after compaction or a new session):",
|
|
@@ -14198,7 +14427,7 @@ function messagesSinceLastBrightsyContextSummary(messages) {
|
|
|
14198
14427
|
function buildBrightsySessionSeed(messages) {
|
|
14199
14428
|
const match = findLastBrightsyContextSummary(messages);
|
|
14200
14429
|
const tail = match ? messages.slice(match.index + 1) : messages;
|
|
14201
|
-
const body = formatMessagesAsTranscript(tail, { tools: "none" });
|
|
14430
|
+
const body = formatMessagesAsTranscript(tail, { tools: "none", thinking: false });
|
|
14202
14431
|
if (!match && !body.trim()) return null;
|
|
14203
14432
|
const blocks = [
|
|
14204
14433
|
"Sideboard conversation context (restored after compaction or a new session):",
|
|
@@ -14265,7 +14494,7 @@ async function maybeCompactContext(thread, thresholds = {}, summarize = summariz
|
|
|
14265
14494
|
olderCount: older.length
|
|
14266
14495
|
};
|
|
14267
14496
|
}
|
|
14268
|
-
var CONTEXT_COMPACT_CHARS, CONTEXT_KEEP_RECENT_CHARS, CONTEXT_KEEP_RECENT_MESSAGES, CONTEXT_MIN_MESSAGES, SESSION_RESET_OCCUPANCY_TOKENS, BRIGHTSY_SUMMARIZE_CONTEXT_TOOL;
|
|
14497
|
+
var CONTEXT_COMPACT_CHARS, CONTEXT_KEEP_RECENT_CHARS, CONTEXT_KEEP_RECENT_MESSAGES, CONTEXT_MIN_MESSAGES, SESSION_RESET_OCCUPANCY_TOKENS, SEED_MAX_CHARS, SEED_FULL_TOOL_MESSAGES, BRIGHTSY_SUMMARIZE_CONTEXT_TOOL;
|
|
14269
14498
|
var init_context_compact = __esm({
|
|
14270
14499
|
"src/composer/context-compact.ts"() {
|
|
14271
14500
|
"use strict";
|
|
@@ -14278,6 +14507,8 @@ var init_context_compact = __esm({
|
|
|
14278
14507
|
CONTEXT_KEEP_RECENT_MESSAGES = 12;
|
|
14279
14508
|
CONTEXT_MIN_MESSAGES = 10;
|
|
14280
14509
|
SESSION_RESET_OCCUPANCY_TOKENS = 75e4;
|
|
14510
|
+
SEED_MAX_CHARS = 6e4;
|
|
14511
|
+
SEED_FULL_TOOL_MESSAGES = 6;
|
|
14281
14512
|
BRIGHTSY_SUMMARIZE_CONTEXT_TOOL = "summarize_context";
|
|
14282
14513
|
}
|
|
14283
14514
|
});
|
|
@@ -17000,10 +17231,11 @@ async function createThread(input, _onSetupLine) {
|
|
|
17000
17231
|
throw new Error("Use adoptThread() for adopt sources");
|
|
17001
17232
|
}
|
|
17002
17233
|
const team = allocateTeamSlug(repoPath);
|
|
17234
|
+
const slug = sourceType === "ticket" ? worktreeSlugForTicket(persistedSourceRef, team.slug) : team.slug;
|
|
17003
17235
|
const { branchName, worktreePath } = await createThreadWorktree({
|
|
17004
17236
|
repoPath,
|
|
17005
17237
|
sourceRef,
|
|
17006
|
-
slug
|
|
17238
|
+
slug
|
|
17007
17239
|
});
|
|
17008
17240
|
copyConfiguredFiles(repoPath, worktreePath);
|
|
17009
17241
|
const explicitTitle = title?.trim();
|
|
@@ -19301,12 +19533,17 @@ function normPath3(p) {
|
|
|
19301
19533
|
function formatRenameBranchDirective(thread, opts) {
|
|
19302
19534
|
if (!isPlaceholderBranch(thread.branchName, thread.worktreePath)) return null;
|
|
19303
19535
|
const dir = worktreeNameFromPath(thread.worktreePath);
|
|
19536
|
+
const ticket = thread.sourceType === "ticket" ? ticketSlugForBranch(thread.sourceRef ?? "") : null;
|
|
19537
|
+
const example = ticket ? `\`feat/${ticket}-dark-mode\` or \`fix/${ticket}-panel-width\`` : "`fix/panel-width` or `feat/dark-mode`";
|
|
19304
19538
|
const lines = [
|
|
19305
19539
|
"Branch naming (do this early in the turn):",
|
|
19306
|
-
`- Current branch \`${thread.branchName}\` is a temporary placeholder. The worktree folder \`${dir}\` is a stable
|
|
19307
|
-
|
|
19540
|
+
`- Current branch \`${thread.branchName}\` is a temporary placeholder. The worktree folder \`${dir}\` is a stable nickname \u2014 do not rename or leave that directory.`,
|
|
19541
|
+
`- Rename the git branch to a short kebab-case name that describes this task (what you are changing), e.g. ${example}:`,
|
|
19308
19542
|
" `git branch -m <new-name>`",
|
|
19309
19543
|
"- Prefer Conventional Commits style prefixes when they fit (`fix/`, `feat/`, `chore/`, `docs/`).",
|
|
19544
|
+
...ticket ? [
|
|
19545
|
+
`- Keep ticket \`${ticket}\` in the new branch name so the issue stays findable.`
|
|
19546
|
+
] : [],
|
|
19310
19547
|
"- Never push this placeholder to main/master."
|
|
19311
19548
|
];
|
|
19312
19549
|
const custom = opts?.customPrompt?.trim();
|
|
@@ -19340,67 +19577,37 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
19340
19577
|
lines.push(
|
|
19341
19578
|
"- Always use this worktree's `origin` remote (`git remote get-url origin` from this cwd). Never push to or open PRs against `upstream` (template remotes)."
|
|
19342
19579
|
);
|
|
19343
|
-
lines.push(
|
|
19344
|
-
"- Push with `git push -u origin HEAD` (or the current branch name). Do not `git push upstream`."
|
|
19345
|
-
);
|
|
19346
|
-
lines.push("");
|
|
19347
19580
|
lines.push(formatGitAuthModeDirective(opts?.gitAuthMode ?? "auto"));
|
|
19348
19581
|
lines.push(
|
|
19349
|
-
"-
|
|
19350
|
-
);
|
|
19351
|
-
lines.push(
|
|
19352
|
-
"- Prefer a concise imperative title (Conventional Commits style when it fits: feat:/fix:/chore:/docs:). Body should summarize intent, key changes, and test notes."
|
|
19582
|
+
"- PR title/body and commit messages state what the change does and why (inspect the diff/commits and the user request) \u2014 never the worktree nickname or placeholder branch. Concise imperative title (Conventional Commits when it fits: feat:/fix:/chore:/docs:); body = intent, key changes, test notes."
|
|
19353
19583
|
);
|
|
19354
19584
|
lines.push(
|
|
19355
|
-
"-
|
|
19585
|
+
"- Stay on this thread branch. Never push to main/master or merge locally into the main checkout. Merge the PR only when this turn is a Merge PR request or the user explicitly asked \u2014 via GitHub from this worktree (`gh pr merge` / `gh stack merge`)."
|
|
19356
19586
|
);
|
|
19357
19587
|
if (thread.prUrl) {
|
|
19358
19588
|
lines.push(
|
|
19359
19589
|
`- A PR already exists (${thread.prUrl}). Update it (push + edit title/body if the purpose drifted) instead of opening a duplicate.`
|
|
19360
19590
|
);
|
|
19361
|
-
} else if (opts?.githubSlug) {
|
|
19362
|
-
lines.push(
|
|
19363
|
-
`- Prefer a draft PR first: \`gh pr create --draft -R ${opts.githubSlug}\` (or update via \`gh pr edit -R ${opts.githubSlug}\`) once the change set is coherent. Always pass \`-R ${opts.githubSlug}\` (this worktree's origin). Bare \`gh pr create\` may target upstream instead of origin on dual-remote checkouts. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name. If GitHub rejects the GraphQL body as too long, retry with a short \`--body-file\` (limit 65,536 characters) \u2014 do not paste a changelog or diff into \`--body\`.`
|
|
19364
|
-
);
|
|
19365
19591
|
} else {
|
|
19592
|
+
const slug = opts?.githubSlug ?? "<origin-owner/name>";
|
|
19593
|
+
const resolve = opts?.githubSlug ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
|
|
19366
19594
|
lines.push(
|
|
19367
|
-
|
|
19595
|
+
`- Prefer a draft PR first: \`gh pr create --draft -R ${slug}\` (update via \`gh pr edit -R ${slug}\`). Always pass \`-R\` \u2014 bare \`gh pr create\` may target upstream on dual-remote checkouts.${resolve} Mark ready for review only when asked. If GitHub rejects the body as too long, retry with a short \`--body-file\` \u2014 do not paste a changelog or diff into \`--body\`.`
|
|
19368
19596
|
);
|
|
19369
19597
|
}
|
|
19370
|
-
lines.push("");
|
|
19371
|
-
lines.push(
|
|
19372
|
-
"Short git requests from the Sideboard UI are complete instructions \u2014 expand them using the rules above without asking for clarification:"
|
|
19373
|
-
);
|
|
19374
|
-
lines.push(
|
|
19375
|
-
'- "Commit and push." \u2192 commit any uncommitted work with a purpose-stating message, then push to origin (updates an existing PR if one is linked). Do not start a checks loop unless they gave a goal.'
|
|
19376
|
-
);
|
|
19377
|
-
lines.push(
|
|
19378
|
-
'- "Commit, push, and open a draft PR." \u2192 commit, push, then create a draft PR with `gh pr create --draft -R \u2026` (title/body from the change purpose).'
|
|
19379
|
-
);
|
|
19380
|
-
lines.push(
|
|
19381
|
-
'- "Commit, push, and open a PR in the browser." \u2192 commit, push, then `gh pr create --web -R \u2026`.'
|
|
19382
|
-
);
|
|
19383
19598
|
lines.push(
|
|
19384
|
-
'- "
|
|
19599
|
+
'- Sideboard git buttons send short phrases ("Commit and push.", "Merge PR.", \u2026) with their meaning attached \u2014 act on them without asking for clarification. If the user gives a goal (Greptile 5/5, CI green, until checks pass), you get the watch-fix-push playbook with that request.'
|
|
19385
19600
|
);
|
|
19386
|
-
lines.push(
|
|
19387
|
-
'- "Merge the remote branch (<base>) into your branch and resolve conflicts. Then, commit and push your changes." \u2192 fetch the PR base, merge it into this branch, resolve conflicts carefully, commit, and push until the PR is mergeable.'
|
|
19388
|
-
);
|
|
19389
|
-
lines.push(
|
|
19390
|
-
'- "Address review comments." \u2192 read PR review feedback, make the requested changes, commit, and push.'
|
|
19391
|
-
);
|
|
19392
|
-
lines.push(
|
|
19393
|
-
'- "Merge PR." \u2192 merge this thread\'s open pull request on GitHub (this phrase is the explicit ask). If `gh stack view` shows a stack, use `gh stack merge`; otherwise `gh pr merge` (respect repo defaults / squash vs merge). Do not force-push main/master or merge locally into the main checkout.'
|
|
19394
|
-
);
|
|
19395
|
-
lines.push("");
|
|
19396
|
-
lines.push(formatPrGateDirective());
|
|
19397
19601
|
lines.push("");
|
|
19398
|
-
lines.push(formatProcessGuideDirective());
|
|
19602
|
+
lines.push(formatProcessGuideDirective({ worktreePath: thread.worktreePath }));
|
|
19399
19603
|
return lines.join("\n");
|
|
19400
19604
|
}
|
|
19401
19605
|
function formatWorktreeReminder() {
|
|
19402
19606
|
return "Sideboard worktree: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout. If a goal is given (Greptile 5/5, CI green), watch-fix-push until it lands \u2014 do not watch after every push.";
|
|
19403
19607
|
}
|
|
19608
|
+
function mentionsPrGoal(prompt) {
|
|
19609
|
+
return PR_GOAL_RE.test(prompt);
|
|
19610
|
+
}
|
|
19404
19611
|
function issueTicketFromThread(thread, preferredSource = "github") {
|
|
19405
19612
|
if (thread?.sourceType !== "ticket") return null;
|
|
19406
19613
|
const ref = thread.sourceRef?.trim() ?? "";
|
|
@@ -19489,29 +19696,27 @@ function formatPrGateDirective() {
|
|
|
19489
19696
|
"- Greptile 5/5: wait for the greptile check; read the latest `N/5` from the PR body or Greptile\u2019s most recently *updated* issue comment; also fetch unresolved review comments / the \u201CPrompt to fix all with AI\u201D block. Done = **5/5 and zero unresolved Greptile comments**. If Greptile is idle, comment `@greptile review`. Cap about 5 iterations, then report leftovers. Do not merge unless asked."
|
|
19490
19697
|
].join("\n");
|
|
19491
19698
|
}
|
|
19492
|
-
function formatProcessGuideDirective() {
|
|
19699
|
+
function formatProcessGuideDirective(opts) {
|
|
19700
|
+
const worktree = opts?.worktreePath?.trim();
|
|
19701
|
+
const hasGraphSkill = !!worktree && (0, import_node_fs48.existsSync)((0, import_node_path45.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
|
|
19702
|
+
const hasReviewSkill = !!worktree && (0, import_node_fs48.existsSync)((0, import_node_path45.join)(worktree, ".claude/skills/review/SKILL.md"));
|
|
19493
19703
|
return [
|
|
19494
19704
|
"Process guides (recurring work only):",
|
|
19495
|
-
"-
|
|
19496
|
-
"- If `.claude/skills
|
|
19497
|
-
"-
|
|
19498
|
-
"- Merge-readiness notes: if `.claude/skills/review/SKILL.md` already exists, edit it. Otherwise write them to `.context/review.md` (copied from `.sideboard/review.md` when that file exists). Do not create a review skill.",
|
|
19499
|
-
"- Do not write new skills under `.sideboard/skills/` (that folder only \u2014 other `.sideboard/` files such as settings.toml are fine). Point Codex/OpenCode at the Claude skill from `AGENTS.md`. Optional: symlink `.cursor/skills/<name>` to the Claude skill.",
|
|
19705
|
+
hasGraphSkill ? "- Migrations, ports, batch fixes, and other fan-out: follow `.claude/skills/graph-engineering/SKILL.md` (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch around it." : null,
|
|
19706
|
+
"- If this same shape of work will happen again, write `.claude/skills/<kebab-name>/SKILL.md` in this worktree (Claude Code project skill; Sideboard `/name`, Claude Code, and `attach` all load it). Not under `.sideboard/skills/`. Point Codex/OpenCode at it from `AGENTS.md`.",
|
|
19707
|
+
hasReviewSkill ? "- Merge-readiness notes go in `.claude/skills/review/SKILL.md` (edit it; do not create another review skill)." : "- Merge-readiness notes go in `.context/review.md` (copied from `.sideboard/review.md` when that file exists). Do not create a review skill.",
|
|
19500
19708
|
"- Skip a guide for a one-off. If a matching skill exists, follow it. Same miss twice \u2192 edit the skill, do not patch around it."
|
|
19501
|
-
].join("\n");
|
|
19709
|
+
].filter(Boolean).join("\n");
|
|
19502
19710
|
}
|
|
19503
19711
|
function formatLongRunningDirective(opts) {
|
|
19504
19712
|
const invoke = formatDetachedJobInvoke(opts?.scriptPath);
|
|
19505
19713
|
return [
|
|
19506
|
-
"Long-running jobs (mandatory when a command may run more than ~30s):",
|
|
19507
|
-
"A Sideboard worktree turn SIGTERMs the agent shell (and its process group) when the user sends another message or the turn is interrupted
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
"-
|
|
19511
|
-
|
|
19512
|
-
`- If it is hanging, producing no useful output, or doing the wrong thing: MCP \`stop_job\` (same id, optional reason) or \`${invoke} stop <id>\`. Do not loop forever. Do not stop a pack/test/deploy that is clearly making progress.`,
|
|
19513
|
-
"- Do not end the turn with \u201CI\u2019ll let you know when it\u2019s done.\u201D Stay in the loop until stillRunning is false (or you stopped it).",
|
|
19514
|
-
"- ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
|
|
19714
|
+
"Long-running jobs (mandatory when a command may run more than ~30s \u2014 pack, test, deploy, `gh pr checks --watch`):",
|
|
19715
|
+
"A Sideboard worktree turn SIGTERMs the agent shell (and its process group) when the user sends another message or the turn is interrupted; `block_until_ms: 0` is not enough. Detach instead, and never ask the human to poll.",
|
|
19716
|
+
`- Start once: \`${invoke} start <id> -- <command> [args...]\` (cwd = this worktree; same tool as \`scripts/detached-job.cjs\` when the worktree has it). If JSON says already-running, do not start again.`,
|
|
19717
|
+
"- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running`, then loop Sideboard MCP `wait_for_job` (returns in ~45s). stillRunning \u2192 present the same id with `content=delta` only \u2192 wait again. Shell fallback: the same helper with `wait <id>`.",
|
|
19718
|
+
"- Hanging, no useful output, or the wrong thing \u2192 `stop_job` (or the helper with `stop <id>`). Do not stop a pack/test/deploy that is clearly making progress.",
|
|
19719
|
+
"- Stay in the loop until stillRunning is false (or you stopped it). ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
|
|
19515
19720
|
"State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
|
|
19516
19721
|
].join("\n");
|
|
19517
19722
|
}
|
|
@@ -19521,84 +19726,17 @@ function formatLongRunningReminder(opts) {
|
|
|
19521
19726
|
}
|
|
19522
19727
|
function formatArtifactDirective() {
|
|
19523
19728
|
return [
|
|
19524
|
-
"Sideboard side column (desktop UI)
|
|
19525
|
-
"
|
|
19526
|
-
"
|
|
19527
|
-
"
|
|
19528
|
-
"
|
|
19529
|
-
"```html",
|
|
19530
|
-
"<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
|
|
19531
|
-
"```",
|
|
19532
|
-
"2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown|react|log), and content \u2014 not both a fence and this tool for the same body.",
|
|
19533
|
-
" type=log is append-only: same `artifact_id`, `content` = new lines only (plus optional status/phase). Do not resend the full log or wrap it in HTML.",
|
|
19534
|
-
"CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
|
|
19535
|
-
"3) Call Sideboard MCP `present_schema` when the user needs to filter, edit, publish, or persist rows \u2014 including after you already showed a markdown table, if they then ask for an editable table. If they only need to read the data, a markdown table is enough. When you do call it, pass title, mode (table|form), and either:",
|
|
19536
|
-
" - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
|
|
19537
|
-
" - datasource=inline + resource: { id, title, schema, schemaUi } and optional records/record.",
|
|
19538
|
-
"Files / media browser (CMS file manager column):",
|
|
19539
|
-
"4) Call Sideboard MCP `present_files` with optional title, path, and datasource (brightsy|memory).",
|
|
19540
|
-
" Opens the Files column for browse/upload/pick. Do NOT say a file manager UI is missing.",
|
|
19541
|
-
"Multiple-choice questions:",
|
|
19542
|
-
"5) Call Sideboard MCP `ask_user` only when work is blocked on choosing among a few concrete options (approach forks, which API, auth vs cookies). First write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it). Include a description on every option. After calling, stop and wait for their next message with answers. If you are asking a real multiple-choice, use ask_user rather than chat bullets so Sideboard shows the composer picker.",
|
|
19543
|
-
"Do not call ask_user for greetings, check-ins, \u201Chello\u201D, open-ended how-can-I-help, or to invent a menu of possible next tasks \u2014 reply in chat. If one option is the obvious default, proceed without asking.",
|
|
19544
|
-
"Never say artifacts, CMS UI, or the Files column are unavailable. present_schema is for interactive list/edit/publish (use it when they ask to edit, even if chat already had a markdown table); present_files for storage UI; html fences for standalone pages; ask_user only for those blocked predefined-option questions."
|
|
19729
|
+
"Sideboard side column (desktop UI) \u2014 Sideboard MCP tools present_artifact, present_schema, present_files, ask_user (see their descriptions). claude.ai\u2019s \u201CArtifact\u201D tool does not exist here; never say artifacts, the CMS UI, or the Files column are unavailable.",
|
|
19730
|
+
"- Standalone documents: a fenced block tagged `html` (preferred), `svg`, or `markdown` containing the FULL document opens the side column by itself. Use that or present_artifact \u2014 never both for the same body.",
|
|
19731
|
+
"- present_artifact type=log appends: same artifact_id, content = new lines only (plus status/phase). Do not resend the full log or wrap it in HTML.",
|
|
19732
|
+
"- Data: a markdown table is enough to read. Call present_schema only when the user needs to filter/edit/publish/persist rows \u2014 including when they ask for an editable table after you already showed markdown. Never re-present rows you already wrote just to display them.",
|
|
19733
|
+
"- ask_user only when work is blocked on a few concrete options (approach fork, which API, auth vs cookies): first a short chat message explaining the decision and each option, then the call (description on every option), then stop and wait. Not for greetings, check-ins, or an invented menu of next tasks \u2014 reply in chat. If one option is the obvious default, proceed."
|
|
19545
19734
|
].join("\n");
|
|
19546
19735
|
}
|
|
19547
19736
|
function formatUiReminder() {
|
|
19548
19737
|
return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
|
|
19549
19738
|
}
|
|
19550
|
-
|
|
19551
|
-
const candidates = FILES_BY_AGENT[agent] ?? FILES_BY_AGENT.claude;
|
|
19552
|
-
const seenPaths = /* @__PURE__ */ new Set();
|
|
19553
|
-
const seenBodies = /* @__PURE__ */ new Set();
|
|
19554
|
-
const out = [];
|
|
19555
|
-
for (const rel of candidates) {
|
|
19556
|
-
if (seenPaths.has(rel)) continue;
|
|
19557
|
-
const abs = (0, import_node_path45.join)(worktreePath, rel);
|
|
19558
|
-
if (!(0, import_node_fs48.existsSync)(abs)) continue;
|
|
19559
|
-
try {
|
|
19560
|
-
if (!(0, import_node_fs48.statSync)(abs).isFile()) continue;
|
|
19561
|
-
let content = (0, import_node_fs48.readFileSync)(abs, "utf8");
|
|
19562
|
-
if (!content.trim()) continue;
|
|
19563
|
-
if (content.length > MAX_CHARS_PER_FILE) {
|
|
19564
|
-
content = `${content.slice(0, MAX_CHARS_PER_FILE)}
|
|
19565
|
-
|
|
19566
|
-
\u2026(truncated)`;
|
|
19567
|
-
}
|
|
19568
|
-
const body = content.trim().replace(/\r\n/g, "\n");
|
|
19569
|
-
if (seenBodies.has(body)) continue;
|
|
19570
|
-
seenPaths.add(rel);
|
|
19571
|
-
seenBodies.add(body);
|
|
19572
|
-
out.push({ relativePath: rel, content });
|
|
19573
|
-
} catch {
|
|
19574
|
-
}
|
|
19575
|
-
}
|
|
19576
|
-
return out;
|
|
19577
|
-
}
|
|
19578
|
-
function formatAgentInstructions(files) {
|
|
19579
|
-
if (files.length === 0) return null;
|
|
19580
|
-
const parts = [
|
|
19581
|
-
"Project agent instructions (from the worktree \u2014 follow these):",
|
|
19582
|
-
""
|
|
19583
|
-
];
|
|
19584
|
-
for (const f of files) {
|
|
19585
|
-
parts.push(`## ${f.relativePath}`);
|
|
19586
|
-
parts.push("");
|
|
19587
|
-
parts.push(f.content.trim());
|
|
19588
|
-
parts.push("");
|
|
19589
|
-
parts.push("---");
|
|
19590
|
-
parts.push("");
|
|
19591
|
-
}
|
|
19592
|
-
return parts.join("\n").trimEnd();
|
|
19593
|
-
}
|
|
19594
|
-
function withAgentInstructions(prompt, files) {
|
|
19595
|
-
const prefix = formatAgentInstructions(files);
|
|
19596
|
-
if (!prefix) return prompt;
|
|
19597
|
-
return `${prefix}
|
|
19598
|
-
|
|
19599
|
-
${prompt}`;
|
|
19600
|
-
}
|
|
19601
|
-
var import_node_fs48, import_node_path45, GITHUB_TICKET_REF, KEYED_TICKET_REF, FILES_BY_AGENT, MAX_CHARS_PER_FILE;
|
|
19739
|
+
var import_node_fs48, import_node_path45, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
|
|
19602
19740
|
var init_instructions = __esm({
|
|
19603
19741
|
"src/agents/instructions.ts"() {
|
|
19604
19742
|
"use strict";
|
|
@@ -19607,22 +19745,9 @@ var init_instructions = __esm({
|
|
|
19607
19745
|
init_git_auth_mode();
|
|
19608
19746
|
init_worktree_labels();
|
|
19609
19747
|
init_detached_job_path();
|
|
19748
|
+
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;
|
|
19610
19749
|
GITHUB_TICKET_REF = /^(?:#?\d+|gh-\d+)$/i;
|
|
19611
19750
|
KEYED_TICKET_REF = /^(?:[A-Z][A-Z0-9]{0,9}-\d+|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i;
|
|
19612
|
-
FILES_BY_AGENT = {
|
|
19613
|
-
claude: [
|
|
19614
|
-
"CLAUDE.md",
|
|
19615
|
-
".claude/CLAUDE.md",
|
|
19616
|
-
"CLAUDE.local.md",
|
|
19617
|
-
"AGENTS.md",
|
|
19618
|
-
"AGENT.md"
|
|
19619
|
-
],
|
|
19620
|
-
codex: ["AGENTS.md", "AGENT.md", ".codex/AGENTS.md", "CLAUDE.md"],
|
|
19621
|
-
opencode: ["AGENTS.md", "AGENT.md", "OPENCODE.md", "CLAUDE.md"],
|
|
19622
|
-
brightsy: ["AGENTS.md", "AGENT.md", "CLAUDE.md"],
|
|
19623
|
-
cursor: ["AGENTS.md", "AGENT.md", ".cursor/rules", "CLAUDE.md"]
|
|
19624
|
-
};
|
|
19625
|
-
MAX_CHARS_PER_FILE = 48e3;
|
|
19626
19751
|
}
|
|
19627
19752
|
});
|
|
19628
19753
|
|
|
@@ -21019,17 +21144,21 @@ var init_orchestrator = __esm({
|
|
|
21019
21144
|
const slackReplyContext = formatSlackRepliesForTurn(
|
|
21020
21145
|
pendingSlackExternalReplies(thread.messages)
|
|
21021
21146
|
);
|
|
21022
|
-
const
|
|
21023
|
-
thread.planMode ? PLAN_MODE_INSTRUCTION : null,
|
|
21024
|
-
orchestrationReminder,
|
|
21147
|
+
const turnReminders = [
|
|
21025
21148
|
worktreeReminder,
|
|
21026
21149
|
optionalServicesReminder,
|
|
21027
21150
|
issueToolsReminder,
|
|
21028
21151
|
viewerContextReminder,
|
|
21029
21152
|
artifactReminder,
|
|
21030
|
-
longRunningReminder
|
|
21153
|
+
longRunningReminder
|
|
21154
|
+
].filter(Boolean).join("\n\n") || void 0;
|
|
21155
|
+
const prGateDirective = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && mentionsPrGoal(expandedPrompt) ? formatPrGateDirective() : null;
|
|
21156
|
+
const agentPrompt = [
|
|
21157
|
+
thread.planMode ? PLAN_MODE_INSTRUCTION : null,
|
|
21158
|
+
orchestrationReminder,
|
|
21159
|
+
prGateDirective,
|
|
21031
21160
|
slackReplyContext,
|
|
21032
|
-
expandedPrompt
|
|
21161
|
+
expandCanonicalGitRequest(expandedPrompt)
|
|
21033
21162
|
].filter(Boolean).join("\n\n");
|
|
21034
21163
|
if (thread.attachments.length > 0) {
|
|
21035
21164
|
updateThread(threadId, { attachments: [] });
|
|
@@ -21119,7 +21248,7 @@ var init_orchestrator = __esm({
|
|
|
21119
21248
|
const stderrTail = [];
|
|
21120
21249
|
const handle = await spawnAgentTurn(
|
|
21121
21250
|
fresh,
|
|
21122
|
-
{ cachedPrefix, prompt: agentPrompt },
|
|
21251
|
+
{ cachedPrefix, prompt: agentPrompt, systemPrompt: turnReminders },
|
|
21123
21252
|
(event) => {
|
|
21124
21253
|
this.emit({ type: "turn_output", threadId, event });
|
|
21125
21254
|
noteTurnLiveEvent(threadId, event);
|
|
@@ -21228,7 +21357,7 @@ var init_orchestrator = __esm({
|
|
|
21228
21357
|
].filter(Boolean).join("\n\n---\n\n");
|
|
21229
21358
|
const retryHandle = await spawnAgentTurn(
|
|
21230
21359
|
retryThread,
|
|
21231
|
-
{ cachedPrefix: retryPrefix, prompt: agentPrompt },
|
|
21360
|
+
{ cachedPrefix: retryPrefix, prompt: agentPrompt, systemPrompt: turnReminders },
|
|
21232
21361
|
(event) => {
|
|
21233
21362
|
this.emit({ type: "turn_output", threadId, event });
|
|
21234
21363
|
if (event.type === "session_id") {
|
|
@@ -22415,7 +22544,7 @@ async function defaultDeps() {
|
|
|
22415
22544
|
}
|
|
22416
22545
|
function pickAgent(schedule) {
|
|
22417
22546
|
if (schedule.agent) return schedule.agent;
|
|
22418
|
-
return coerceOrchestratorAgent(
|
|
22547
|
+
return coerceOrchestratorAgent(resolveOrchestratorDefaults().agent);
|
|
22419
22548
|
}
|
|
22420
22549
|
async function fireSchedule(id) {
|
|
22421
22550
|
const schedule = getSchedule(id);
|
|
@@ -22587,6 +22716,7 @@ __export(index_exports, {
|
|
|
22587
22716
|
PLAN_MODE_INSTRUCTION: () => PLAN_MODE_INSTRUCTION,
|
|
22588
22717
|
PLAN_QUESTION_ANSWERS_PREFIX: () => PLAN_QUESTION_ANSWERS_PREFIX,
|
|
22589
22718
|
PROFILE_NOTES_MAX: () => PROFILE_NOTES_MAX,
|
|
22719
|
+
PR_DETAILS_JSON_FIELDS: () => PR_DETAILS_JSON_FIELDS,
|
|
22590
22720
|
REPO_REVIEW_NAME: () => REPO_REVIEW_NAME,
|
|
22591
22721
|
REPO_REVIEW_PATH: () => REPO_REVIEW_PATH,
|
|
22592
22722
|
REVIEW_REQUEST_NAME: () => REVIEW_REQUEST_NAME,
|
|
@@ -22595,6 +22725,8 @@ __export(index_exports, {
|
|
|
22595
22725
|
REVIEW_REQUEST_TEMPLATE: () => REVIEW_REQUEST_TEMPLATE,
|
|
22596
22726
|
REVIEW_SKILL_NAME: () => REVIEW_SKILL_NAME,
|
|
22597
22727
|
REVIEW_SKILL_PATH: () => REVIEW_SKILL_PATH,
|
|
22728
|
+
SEED_FULL_TOOL_MESSAGES: () => SEED_FULL_TOOL_MESSAGES,
|
|
22729
|
+
SEED_MAX_CHARS: () => SEED_MAX_CHARS,
|
|
22598
22730
|
SESSION_RESET_OCCUPANCY_TOKENS: () => SESSION_RESET_OCCUPANCY_TOKENS,
|
|
22599
22731
|
SIDEBOARD_FORCE_STOP: () => SIDEBOARD_FORCE_STOP,
|
|
22600
22732
|
SIDEBOARD_MCP_ALLOWED_TOOLS: () => SIDEBOARD_MCP_ALLOWED_TOOLS,
|
|
@@ -22802,7 +22934,6 @@ __export(index_exports, {
|
|
|
22802
22934
|
forkMessageSlice: () => forkMessageSlice,
|
|
22803
22935
|
forkThreadWorktree: () => forkThreadWorktree,
|
|
22804
22936
|
formatAccountProfilePlaybookLine: () => formatAccountProfilePlaybookLine,
|
|
22805
|
-
formatAgentInstructions: () => formatAgentInstructions,
|
|
22806
22937
|
formatArtifactDirective: () => formatArtifactDirective,
|
|
22807
22938
|
formatBrightsyFetchError: () => formatBrightsyFetchError,
|
|
22808
22939
|
formatDetachedJobInvoke: () => formatDetachedJobInvoke,
|
|
@@ -23007,7 +23138,6 @@ __export(index_exports, {
|
|
|
23007
23138
|
listWorktreeFiles: () => listWorktreeFiles,
|
|
23008
23139
|
listWorktrees: () => listWorktrees,
|
|
23009
23140
|
liveActivitySummary: () => liveActivitySummary,
|
|
23010
|
-
loadAgentInstructions: () => loadAgentInstructions,
|
|
23011
23141
|
loadAppSettings: () => loadAppSettings,
|
|
23012
23142
|
loadBrightsyConfig: () => loadBrightsyConfig,
|
|
23013
23143
|
loadConductorSettings: () => loadConductorSettings,
|
|
@@ -23024,6 +23154,7 @@ __export(index_exports, {
|
|
|
23024
23154
|
mcpAllowTools: () => mcpAllowTools,
|
|
23025
23155
|
mcpAuthWarnings: () => mcpAuthWarnings,
|
|
23026
23156
|
mcpStatusThinkingFromClaudeInit: () => mcpStatusThinkingFromClaudeInit,
|
|
23157
|
+
mentionsPrGoal: () => mentionsPrGoal,
|
|
23027
23158
|
mergeAgentGitAuthEnv: () => mergeAgentGitAuthEnv,
|
|
23028
23159
|
mergePr: () => mergePr,
|
|
23029
23160
|
mergePrStack: () => mergePrStack,
|
|
@@ -23064,6 +23195,7 @@ __export(index_exports, {
|
|
|
23064
23195
|
parseGithubSlugFromRemoteUrl: () => parseGithubSlugFromRemoteUrl,
|
|
23065
23196
|
parseMcpList: () => parseMcpList,
|
|
23066
23197
|
parsePlanQuestionsInput: () => parsePlanQuestionsInput,
|
|
23198
|
+
parsePrDetailsView: () => parsePrDetailsView,
|
|
23067
23199
|
parseSessionQuotaResetAt: () => parseSessionQuotaResetAt,
|
|
23068
23200
|
parseSlackRelayClientMessage: () => parseSlackRelayClientMessage,
|
|
23069
23201
|
parseSlackRelayServerMessage: () => parseSlackRelayServerMessage,
|
|
@@ -23131,7 +23263,9 @@ __export(index_exports, {
|
|
|
23131
23263
|
resolveLinearState: () => resolveLinearState,
|
|
23132
23264
|
resolveLinearTeam: () => resolveLinearTeam,
|
|
23133
23265
|
resolveLoginCommand: () => resolveLoginCommand,
|
|
23266
|
+
resolveNewOrchestratorOptions: () => resolveNewOrchestratorOptions,
|
|
23134
23267
|
resolveNewThreadOptions: () => resolveNewThreadOptions,
|
|
23268
|
+
resolveOrchestratorDefaults: () => resolveOrchestratorDefaults,
|
|
23135
23269
|
resolvePlanMarkdown: () => resolvePlanMarkdown,
|
|
23136
23270
|
resolvePrSelector: () => resolvePrSelector,
|
|
23137
23271
|
resolvePrSelectors: () => resolvePrSelectors,
|
|
@@ -23194,6 +23328,7 @@ __export(index_exports, {
|
|
|
23194
23328
|
slugify: () => slugify,
|
|
23195
23329
|
spawnAgentTurn: () => spawnAgentTurn,
|
|
23196
23330
|
splitForCompaction: () => splitForCompaction,
|
|
23331
|
+
splitTurnInputForSystemPrompt: () => splitTurnInputForSystemPrompt,
|
|
23197
23332
|
stackAgentDefaultsFrom: () => stackAgentDefaultsFrom,
|
|
23198
23333
|
stackIdFrom: () => stackIdFrom,
|
|
23199
23334
|
stackMergeReadiness: () => stackMergeReadiness,
|
|
@@ -23228,6 +23363,7 @@ __export(index_exports, {
|
|
|
23228
23363
|
threadRequestsBrightsyMcp: () => threadRequestsBrightsyMcp,
|
|
23229
23364
|
threadsDir: () => threadsDir,
|
|
23230
23365
|
threadsSharingWorktree: () => threadsSharingWorktree,
|
|
23366
|
+
ticketSlugForBranch: () => ticketSlugForBranch,
|
|
23231
23367
|
toAbleTimeIssueInfo: () => toAbleTimeIssueInfo,
|
|
23232
23368
|
toGitHubIssueInfo: () => toGitHubIssueInfo,
|
|
23233
23369
|
toPublicAppSettings: () => toPublicAppSettings,
|
|
@@ -23262,7 +23398,6 @@ __export(index_exports, {
|
|
|
23262
23398
|
waitForPidExit: () => waitForPidExit,
|
|
23263
23399
|
warmGithubAgentAuth: () => warmGithubAgentAuth,
|
|
23264
23400
|
whichOnPath: () => whichOnPath,
|
|
23265
|
-
withAgentInstructions: () => withAgentInstructions,
|
|
23266
23401
|
withEventParentId: () => withEventParentId,
|
|
23267
23402
|
withEventsParentId: () => withEventsParentId,
|
|
23268
23403
|
withExportedPath: () => withExportedPath,
|
|
@@ -23274,6 +23409,7 @@ __export(index_exports, {
|
|
|
23274
23409
|
worktreeDisplayLabel: () => worktreeDisplayLabel,
|
|
23275
23410
|
worktreeDisplayLabelForGroup: () => worktreeDisplayLabelForGroup,
|
|
23276
23411
|
worktreeNameFromPath: () => worktreeNameFromPath,
|
|
23412
|
+
worktreeSlugForTicket: () => worktreeSlugForTicket,
|
|
23277
23413
|
worktreesRoot: () => worktreesRoot,
|
|
23278
23414
|
wrapReviewSkillMarkdown: () => wrapReviewSkillMarkdown,
|
|
23279
23415
|
writeInjectedMcpConfig: () => writeInjectedMcpConfig,
|
|
@@ -30309,6 +30445,7 @@ init_outbound_watch();
|
|
|
30309
30445
|
PLAN_MODE_INSTRUCTION,
|
|
30310
30446
|
PLAN_QUESTION_ANSWERS_PREFIX,
|
|
30311
30447
|
PROFILE_NOTES_MAX,
|
|
30448
|
+
PR_DETAILS_JSON_FIELDS,
|
|
30312
30449
|
REPO_REVIEW_NAME,
|
|
30313
30450
|
REPO_REVIEW_PATH,
|
|
30314
30451
|
REVIEW_REQUEST_NAME,
|
|
@@ -30317,6 +30454,8 @@ init_outbound_watch();
|
|
|
30317
30454
|
REVIEW_REQUEST_TEMPLATE,
|
|
30318
30455
|
REVIEW_SKILL_NAME,
|
|
30319
30456
|
REVIEW_SKILL_PATH,
|
|
30457
|
+
SEED_FULL_TOOL_MESSAGES,
|
|
30458
|
+
SEED_MAX_CHARS,
|
|
30320
30459
|
SESSION_RESET_OCCUPANCY_TOKENS,
|
|
30321
30460
|
SIDEBOARD_FORCE_STOP,
|
|
30322
30461
|
SIDEBOARD_MCP_ALLOWED_TOOLS,
|
|
@@ -30524,7 +30663,6 @@ init_outbound_watch();
|
|
|
30524
30663
|
forkMessageSlice,
|
|
30525
30664
|
forkThreadWorktree,
|
|
30526
30665
|
formatAccountProfilePlaybookLine,
|
|
30527
|
-
formatAgentInstructions,
|
|
30528
30666
|
formatArtifactDirective,
|
|
30529
30667
|
formatBrightsyFetchError,
|
|
30530
30668
|
formatDetachedJobInvoke,
|
|
@@ -30729,7 +30867,6 @@ init_outbound_watch();
|
|
|
30729
30867
|
listWorktreeFiles,
|
|
30730
30868
|
listWorktrees,
|
|
30731
30869
|
liveActivitySummary,
|
|
30732
|
-
loadAgentInstructions,
|
|
30733
30870
|
loadAppSettings,
|
|
30734
30871
|
loadBrightsyConfig,
|
|
30735
30872
|
loadConductorSettings,
|
|
@@ -30746,6 +30883,7 @@ init_outbound_watch();
|
|
|
30746
30883
|
mcpAllowTools,
|
|
30747
30884
|
mcpAuthWarnings,
|
|
30748
30885
|
mcpStatusThinkingFromClaudeInit,
|
|
30886
|
+
mentionsPrGoal,
|
|
30749
30887
|
mergeAgentGitAuthEnv,
|
|
30750
30888
|
mergePr,
|
|
30751
30889
|
mergePrStack,
|
|
@@ -30786,6 +30924,7 @@ init_outbound_watch();
|
|
|
30786
30924
|
parseGithubSlugFromRemoteUrl,
|
|
30787
30925
|
parseMcpList,
|
|
30788
30926
|
parsePlanQuestionsInput,
|
|
30927
|
+
parsePrDetailsView,
|
|
30789
30928
|
parseSessionQuotaResetAt,
|
|
30790
30929
|
parseSlackRelayClientMessage,
|
|
30791
30930
|
parseSlackRelayServerMessage,
|
|
@@ -30853,7 +30992,9 @@ init_outbound_watch();
|
|
|
30853
30992
|
resolveLinearState,
|
|
30854
30993
|
resolveLinearTeam,
|
|
30855
30994
|
resolveLoginCommand,
|
|
30995
|
+
resolveNewOrchestratorOptions,
|
|
30856
30996
|
resolveNewThreadOptions,
|
|
30997
|
+
resolveOrchestratorDefaults,
|
|
30857
30998
|
resolvePlanMarkdown,
|
|
30858
30999
|
resolvePrSelector,
|
|
30859
31000
|
resolvePrSelectors,
|
|
@@ -30916,6 +31057,7 @@ init_outbound_watch();
|
|
|
30916
31057
|
slugify,
|
|
30917
31058
|
spawnAgentTurn,
|
|
30918
31059
|
splitForCompaction,
|
|
31060
|
+
splitTurnInputForSystemPrompt,
|
|
30919
31061
|
stackAgentDefaultsFrom,
|
|
30920
31062
|
stackIdFrom,
|
|
30921
31063
|
stackMergeReadiness,
|
|
@@ -30950,6 +31092,7 @@ init_outbound_watch();
|
|
|
30950
31092
|
threadRequestsBrightsyMcp,
|
|
30951
31093
|
threadsDir,
|
|
30952
31094
|
threadsSharingWorktree,
|
|
31095
|
+
ticketSlugForBranch,
|
|
30953
31096
|
toAbleTimeIssueInfo,
|
|
30954
31097
|
toGitHubIssueInfo,
|
|
30955
31098
|
toPublicAppSettings,
|
|
@@ -30984,7 +31127,6 @@ init_outbound_watch();
|
|
|
30984
31127
|
waitForPidExit,
|
|
30985
31128
|
warmGithubAgentAuth,
|
|
30986
31129
|
whichOnPath,
|
|
30987
|
-
withAgentInstructions,
|
|
30988
31130
|
withEventParentId,
|
|
30989
31131
|
withEventsParentId,
|
|
30990
31132
|
withExportedPath,
|
|
@@ -30996,6 +31138,7 @@ init_outbound_watch();
|
|
|
30996
31138
|
worktreeDisplayLabel,
|
|
30997
31139
|
worktreeDisplayLabelForGroup,
|
|
30998
31140
|
worktreeNameFromPath,
|
|
31141
|
+
worktreeSlugForTicket,
|
|
30999
31142
|
worktreesRoot,
|
|
31000
31143
|
wrapReviewSkillMarkdown,
|
|
31001
31144
|
writeInjectedMcpConfig,
|