@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/mcp/run-stdio.cjs
CHANGED
|
@@ -2382,8 +2382,10 @@ function lookupSoccerTeam(titleOrSlug) {
|
|
|
2382
2382
|
}
|
|
2383
2383
|
function teamNameFromSlug(slug) {
|
|
2384
2384
|
const normalized = slug.toLowerCase().replace(/^thread\//, "");
|
|
2385
|
-
const
|
|
2386
|
-
const
|
|
2385
|
+
const withoutTicket = normalized.replace(/^[a-z]{2,8}-\d{1,6}-/, "").replace(/^\d{1,8}-/, "");
|
|
2386
|
+
const lookup = withoutTicket || normalized;
|
|
2387
|
+
const suffixMatch = lookup.match(/^(.+)-(\d+)$/);
|
|
2388
|
+
const base = suffixMatch?.[1] ?? lookup;
|
|
2387
2389
|
const suffix = suffixMatch?.[2];
|
|
2388
2390
|
const team = FAMOUS_SOCCER_TEAM_SEEDS.find((t) => t.slug === base);
|
|
2389
2391
|
if (team) return suffix ? `${team.name} ${suffix}` : team.name;
|
|
@@ -2804,6 +2806,25 @@ function worktreeNameFromPath(worktreePath) {
|
|
|
2804
2806
|
const parts = normalized.split("/");
|
|
2805
2807
|
return parts[parts.length - 1] || worktreePath;
|
|
2806
2808
|
}
|
|
2809
|
+
function ticketSlugForBranch(sourceRef) {
|
|
2810
|
+
const raw = sourceRef.trim();
|
|
2811
|
+
if (!raw) return null;
|
|
2812
|
+
const linear = raw.match(/\b([A-Za-z]{2,8}-\d{1,6})\b/);
|
|
2813
|
+
if (linear) return linear[1].toLowerCase();
|
|
2814
|
+
const hashed = raw.match(/^#(\d{1,8})$/);
|
|
2815
|
+
if (hashed) return hashed[1];
|
|
2816
|
+
const digits = raw.match(/^(\d{1,8})$/);
|
|
2817
|
+
if (digits) return digits[1];
|
|
2818
|
+
const slug = raw.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
2819
|
+
return slug || null;
|
|
2820
|
+
}
|
|
2821
|
+
function worktreeSlugForTicket(ticketRef, teamSlug) {
|
|
2822
|
+
const ticket = ticketSlugForBranch(ticketRef);
|
|
2823
|
+
const team = teamSlug.trim().replace(/^thread\//, "");
|
|
2824
|
+
if (!ticket) return team;
|
|
2825
|
+
if (!team) return ticket;
|
|
2826
|
+
return `${ticket}-${team}`;
|
|
2827
|
+
}
|
|
2807
2828
|
function isPlaceholderBranch(branchName, worktreePath) {
|
|
2808
2829
|
const branch = branchName.trim();
|
|
2809
2830
|
if (!branch || branch === "HEAD") return true;
|
|
@@ -3008,6 +3029,36 @@ var init_worktree_exclude = __esm({
|
|
|
3008
3029
|
}
|
|
3009
3030
|
});
|
|
3010
3031
|
|
|
3032
|
+
// src/agents/orchestrator-capable.ts
|
|
3033
|
+
function isOrchestratorCapableAgent(agent) {
|
|
3034
|
+
return Boolean(
|
|
3035
|
+
agent && ORCHESTRATOR_AGENT_KINDS.includes(agent)
|
|
3036
|
+
);
|
|
3037
|
+
}
|
|
3038
|
+
function assertOrchestratorCapableAgent(agent, context = "orchestration") {
|
|
3039
|
+
if (!isOrchestratorCapableAgent(agent)) {
|
|
3040
|
+
throw new Error(
|
|
3041
|
+
`${agent} cannot run ${context} \u2014 it does not support Sideboard MCP. Use Claude, Cursor, Codex, or OpenCode.`
|
|
3042
|
+
);
|
|
3043
|
+
}
|
|
3044
|
+
return agent;
|
|
3045
|
+
}
|
|
3046
|
+
function coerceOrchestratorAgent(agent, fallback = "claude") {
|
|
3047
|
+
return isOrchestratorCapableAgent(agent) ? agent : fallback;
|
|
3048
|
+
}
|
|
3049
|
+
var ORCHESTRATOR_AGENT_KINDS;
|
|
3050
|
+
var init_orchestrator_capable = __esm({
|
|
3051
|
+
"src/agents/orchestrator-capable.ts"() {
|
|
3052
|
+
"use strict";
|
|
3053
|
+
ORCHESTRATOR_AGENT_KINDS = [
|
|
3054
|
+
"claude",
|
|
3055
|
+
"codex",
|
|
3056
|
+
"opencode",
|
|
3057
|
+
"cursor"
|
|
3058
|
+
];
|
|
3059
|
+
}
|
|
3060
|
+
});
|
|
3061
|
+
|
|
3011
3062
|
// src/store/account-profile.ts
|
|
3012
3063
|
function legacyRoleLabel(role) {
|
|
3013
3064
|
const known = LEGACY_ROLE_LABELS[role];
|
|
@@ -3273,7 +3324,9 @@ __export(app_settings_exports, {
|
|
|
3273
3324
|
resolveAgentExecutable: () => resolveAgentExecutable,
|
|
3274
3325
|
resolveClaudeExecutable: () => resolveClaudeExecutable,
|
|
3275
3326
|
resolveEffectiveIssueSource: () => resolveEffectiveIssueSource,
|
|
3327
|
+
resolveNewOrchestratorOptions: () => resolveNewOrchestratorOptions,
|
|
3276
3328
|
resolveNewThreadOptions: () => resolveNewThreadOptions,
|
|
3329
|
+
resolveOrchestratorDefaults: () => resolveOrchestratorDefaults,
|
|
3277
3330
|
resolveThreadDefaults: () => resolveThreadDefaults,
|
|
3278
3331
|
resolveViewerProfile: () => resolveViewerProfile,
|
|
3279
3332
|
resolveViewerProfileForRepo: () => resolveViewerProfileForRepo,
|
|
@@ -3535,6 +3588,25 @@ function normalizeIntegrations(raw) {
|
|
|
3535
3588
|
}
|
|
3536
3589
|
return out;
|
|
3537
3590
|
}
|
|
3591
|
+
function normalizeOrchestratorDefaults(raw) {
|
|
3592
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
3593
|
+
const source = raw;
|
|
3594
|
+
const out = {};
|
|
3595
|
+
if (typeof source.agent === "string" && isOrchestratorCapableAgent(source.agent)) {
|
|
3596
|
+
out.agent = source.agent;
|
|
3597
|
+
}
|
|
3598
|
+
if (typeof source.model === "string") {
|
|
3599
|
+
const model = source.model.trim();
|
|
3600
|
+
if (model) out.model = model;
|
|
3601
|
+
}
|
|
3602
|
+
if (normalizeThinkingEffort(source.effort)) {
|
|
3603
|
+
out.effort = normalizeThinkingEffort(source.effort);
|
|
3604
|
+
}
|
|
3605
|
+
if (typeof source.fast === "boolean") {
|
|
3606
|
+
out.fast = source.fast;
|
|
3607
|
+
}
|
|
3608
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
3609
|
+
}
|
|
3538
3610
|
function normalizeDefaults(raw) {
|
|
3539
3611
|
if (!raw || typeof raw !== "object") return {};
|
|
3540
3612
|
const source = raw;
|
|
@@ -3554,6 +3626,8 @@ function normalizeDefaults(raw) {
|
|
|
3554
3626
|
}
|
|
3555
3627
|
const notes = foldLegacyRolesIntoNotes(source.roles, source.role, source.notes);
|
|
3556
3628
|
if (notes) out.notes = notes;
|
|
3629
|
+
const orchestrator = normalizeOrchestratorDefaults(source.orchestrator);
|
|
3630
|
+
if (orchestrator) out.orchestrator = orchestrator;
|
|
3557
3631
|
return out;
|
|
3558
3632
|
}
|
|
3559
3633
|
function profileRepoKey(path) {
|
|
@@ -4097,6 +4171,39 @@ function updateIntegrationsSettings(patch) {
|
|
|
4097
4171
|
}
|
|
4098
4172
|
return saveAppSettings({ ...current, integrations });
|
|
4099
4173
|
}
|
|
4174
|
+
function applyOrchestratorDefaultsPatch(current, patch) {
|
|
4175
|
+
const next = { ...current };
|
|
4176
|
+
if ("agent" in patch) {
|
|
4177
|
+
if (patch.agent == null) {
|
|
4178
|
+
delete next.agent;
|
|
4179
|
+
} else if (isOrchestratorCapableAgent(patch.agent)) {
|
|
4180
|
+
next.agent = patch.agent;
|
|
4181
|
+
}
|
|
4182
|
+
}
|
|
4183
|
+
if ("model" in patch) {
|
|
4184
|
+
if (patch.model == null || patch.model.trim() === "") {
|
|
4185
|
+
delete next.model;
|
|
4186
|
+
} else {
|
|
4187
|
+
next.model = patch.model.trim();
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
if ("effort" in patch) {
|
|
4191
|
+
if (patch.effort == null) {
|
|
4192
|
+
delete next.effort;
|
|
4193
|
+
} else {
|
|
4194
|
+
const effort = normalizeThinkingEffort(patch.effort);
|
|
4195
|
+
if (effort) next.effort = effort;
|
|
4196
|
+
}
|
|
4197
|
+
}
|
|
4198
|
+
if ("fast" in patch) {
|
|
4199
|
+
if (patch.fast == null) {
|
|
4200
|
+
delete next.fast;
|
|
4201
|
+
} else {
|
|
4202
|
+
next.fast = Boolean(patch.fast);
|
|
4203
|
+
}
|
|
4204
|
+
}
|
|
4205
|
+
return Object.keys(next).length > 0 ? next : void 0;
|
|
4206
|
+
}
|
|
4100
4207
|
function updateDefaultsSettings(patch) {
|
|
4101
4208
|
const current = loadAppSettings();
|
|
4102
4209
|
const defaults = { ...current.defaults };
|
|
@@ -4134,6 +4241,18 @@ function updateDefaultsSettings(patch) {
|
|
|
4134
4241
|
if (!notes) delete defaults.notes;
|
|
4135
4242
|
else defaults.notes = notes;
|
|
4136
4243
|
}
|
|
4244
|
+
if ("orchestrator" in patch) {
|
|
4245
|
+
if (patch.orchestrator == null) {
|
|
4246
|
+
delete defaults.orchestrator;
|
|
4247
|
+
} else {
|
|
4248
|
+
const orchestrator = applyOrchestratorDefaultsPatch(
|
|
4249
|
+
defaults.orchestrator,
|
|
4250
|
+
patch.orchestrator
|
|
4251
|
+
);
|
|
4252
|
+
if (orchestrator) defaults.orchestrator = orchestrator;
|
|
4253
|
+
else delete defaults.orchestrator;
|
|
4254
|
+
}
|
|
4255
|
+
}
|
|
4137
4256
|
delete defaults.roles;
|
|
4138
4257
|
delete defaults.role;
|
|
4139
4258
|
return saveAppSettings({ ...current, defaults });
|
|
@@ -4239,8 +4358,22 @@ function resolveThreadDefaults(settings = loadAppSettings()) {
|
|
|
4239
4358
|
fast: getDefaultFast(settings)
|
|
4240
4359
|
};
|
|
4241
4360
|
}
|
|
4242
|
-
function
|
|
4243
|
-
const
|
|
4361
|
+
function resolveOrchestratorDefaults(settings = loadAppSettings()) {
|
|
4362
|
+
const account = resolveThreadDefaults(settings);
|
|
4363
|
+
const orch = settings.defaults.orchestrator;
|
|
4364
|
+
const agent = coerceOrchestratorAgent(orch?.agent ?? account.agent);
|
|
4365
|
+
let model = orch ? orch.model?.trim() || null : account.model;
|
|
4366
|
+
if (model && agent !== "cursor" && /^(default|auto)$/i.test(model.trim())) {
|
|
4367
|
+
model = null;
|
|
4368
|
+
}
|
|
4369
|
+
return {
|
|
4370
|
+
agent,
|
|
4371
|
+
model,
|
|
4372
|
+
effort: orch?.effort ?? account.effort,
|
|
4373
|
+
fast: orch?.fast ?? account.fast
|
|
4374
|
+
};
|
|
4375
|
+
}
|
|
4376
|
+
function mergeThreadOptionOverrides(defaults, overrides) {
|
|
4244
4377
|
const effort = overrides.effort === void 0 || overrides.effort === null ? defaults.effort : normalizeThinkingEffort(overrides.effort) ?? defaults.effort;
|
|
4245
4378
|
const agent = overrides.agent ?? defaults.agent;
|
|
4246
4379
|
let model = overrides.model === void 0 ? defaults.model : overrides.model?.trim() || null;
|
|
@@ -4254,6 +4387,12 @@ function resolveNewThreadOptions(overrides = {}, settings = loadAppSettings()) {
|
|
|
4254
4387
|
fast: overrides.fast === void 0 || overrides.fast === null ? defaults.fast : Boolean(overrides.fast)
|
|
4255
4388
|
};
|
|
4256
4389
|
}
|
|
4390
|
+
function resolveNewThreadOptions(overrides = {}, settings = loadAppSettings()) {
|
|
4391
|
+
return mergeThreadOptionOverrides(resolveThreadDefaults(settings), overrides);
|
|
4392
|
+
}
|
|
4393
|
+
function resolveNewOrchestratorOptions(overrides = {}, settings = loadAppSettings()) {
|
|
4394
|
+
return mergeThreadOptionOverrides(resolveOrchestratorDefaults(settings), overrides);
|
|
4395
|
+
}
|
|
4257
4396
|
function isLinearConnected(settings = loadAppSettings()) {
|
|
4258
4397
|
return hasLinearCredentials(settings.integrations);
|
|
4259
4398
|
}
|
|
@@ -4375,6 +4514,10 @@ function brightsyInjectWorktreeMcpEnabled(settings = loadAppSettings()) {
|
|
|
4375
4514
|
}
|
|
4376
4515
|
function brightsyCloudConnectAgent(settings = loadAppSettings()) {
|
|
4377
4516
|
const fallback = settings.brightsy.cloudConnectAgent && CLOUD_CONNECT_AGENTS.has(settings.brightsy.cloudConnectAgent) ? settings.brightsy.cloudConnectAgent : "claude";
|
|
4517
|
+
const orchAgent = settings.defaults.orchestrator?.agent;
|
|
4518
|
+
if (orchAgent && CLOUD_CONNECT_AGENTS.has(orchAgent)) {
|
|
4519
|
+
return orchAgent;
|
|
4520
|
+
}
|
|
4378
4521
|
const preferred = getDefaultAgent(settings);
|
|
4379
4522
|
if (CLOUD_CONNECT_AGENTS.has(preferred)) {
|
|
4380
4523
|
return preferred;
|
|
@@ -4585,6 +4728,7 @@ var init_app_settings = __esm({
|
|
|
4585
4728
|
import_node_fs14 = require("fs");
|
|
4586
4729
|
import_node_os5 = require("os");
|
|
4587
4730
|
import_node_path16 = require("path");
|
|
4731
|
+
init_orchestrator_capable();
|
|
4588
4732
|
init_thinking_effort();
|
|
4589
4733
|
init_nested_electron_env();
|
|
4590
4734
|
init_account_profile();
|
|
@@ -5563,6 +5707,7 @@ var init_workspace_scratch = __esm({
|
|
|
5563
5707
|
var worktree_exports = {};
|
|
5564
5708
|
__export(worktree_exports, {
|
|
5565
5709
|
FAMOUS_SOCCER_TEAMS: () => FAMOUS_SOCCER_TEAMS,
|
|
5710
|
+
PR_DETAILS_JSON_FIELDS: () => PR_DETAILS_JSON_FIELDS,
|
|
5566
5711
|
allocateTeamName: () => allocateTeamName,
|
|
5567
5712
|
allocateTeamSlug: () => allocateTeamSlug,
|
|
5568
5713
|
branchDisplayLabel: () => branchDisplayLabel,
|
|
@@ -5601,6 +5746,7 @@ __export(worktree_exports, {
|
|
|
5601
5746
|
originFetchBranch: () => originFetchBranch,
|
|
5602
5747
|
originGhRepoEnv: () => originGhRepoEnv,
|
|
5603
5748
|
parseGithubSlugFromRemoteUrl: () => parseGithubSlugFromRemoteUrl,
|
|
5749
|
+
parsePrDetailsView: () => parsePrDetailsView,
|
|
5604
5750
|
pushBranch: () => pushBranch,
|
|
5605
5751
|
removeWorktree: () => removeWorktree,
|
|
5606
5752
|
resolveDefaultBranch: () => resolveDefaultBranch,
|
|
@@ -5613,9 +5759,11 @@ __export(worktree_exports, {
|
|
|
5613
5759
|
slugify: () => slugify,
|
|
5614
5760
|
suggestSlug: () => suggestSlug,
|
|
5615
5761
|
threadDisplayLabel: () => threadDisplayLabel,
|
|
5762
|
+
ticketSlugForBranch: () => ticketSlugForBranch,
|
|
5616
5763
|
worktreeDisplayLabel: () => worktreeDisplayLabel,
|
|
5617
5764
|
worktreeDisplayLabelForGroup: () => worktreeDisplayLabelForGroup,
|
|
5618
|
-
worktreeNameFromPath: () => worktreeNameFromPath
|
|
5765
|
+
worktreeNameFromPath: () => worktreeNameFromPath,
|
|
5766
|
+
worktreeSlugForTicket: () => worktreeSlugForTicket
|
|
5619
5767
|
});
|
|
5620
5768
|
async function lookupGithubGraphqlReset(cwd) {
|
|
5621
5769
|
const result = await gh(["api", "rate_limit"], cwd, { reject: false });
|
|
@@ -6176,48 +6324,15 @@ async function getPrMeta(cwd, selector) {
|
|
|
6176
6324
|
return null;
|
|
6177
6325
|
}
|
|
6178
6326
|
}
|
|
6179
|
-
|
|
6180
|
-
const slug = await resolveGithubRepoSlug(cwd);
|
|
6181
|
-
const viewArgs = [
|
|
6182
|
-
"pr",
|
|
6183
|
-
"view",
|
|
6184
|
-
selector,
|
|
6185
|
-
"--json",
|
|
6186
|
-
[
|
|
6187
|
-
"number",
|
|
6188
|
-
"title",
|
|
6189
|
-
"body",
|
|
6190
|
-
"url",
|
|
6191
|
-
"state",
|
|
6192
|
-
"isDraft",
|
|
6193
|
-
"reviewDecision",
|
|
6194
|
-
"author",
|
|
6195
|
-
"baseRefName",
|
|
6196
|
-
"headRefName",
|
|
6197
|
-
"additions",
|
|
6198
|
-
"deletions",
|
|
6199
|
-
"changedFiles",
|
|
6200
|
-
"comments",
|
|
6201
|
-
"reviews"
|
|
6202
|
-
].join(",")
|
|
6203
|
-
];
|
|
6204
|
-
if (slug) viewArgs.push("--repo", slug);
|
|
6205
|
-
const { stdout, exitCode, stderr } = await gh(viewArgs, cwd, { reject: false });
|
|
6206
|
-
if (exitCode !== 0 || !stdout.trim()) {
|
|
6207
|
-
if (stderr.trim()) {
|
|
6208
|
-
if (/no pull requests found/i.test(stderr)) return null;
|
|
6209
|
-
}
|
|
6210
|
-
return null;
|
|
6211
|
-
}
|
|
6212
|
-
let view;
|
|
6213
|
-
try {
|
|
6214
|
-
view = JSON.parse(stdout);
|
|
6215
|
-
} catch {
|
|
6216
|
-
throw new Error(stderr.trim() || "gh pr view returned invalid JSON");
|
|
6217
|
-
}
|
|
6327
|
+
function parsePrDetailsView(view) {
|
|
6218
6328
|
const author = view.author ?? {};
|
|
6219
6329
|
const comments = Array.isArray(view.comments) ? view.comments : [];
|
|
6220
6330
|
const reviews = Array.isArray(view.reviews) ? view.reviews : [];
|
|
6331
|
+
const requested = {
|
|
6332
|
+
ids: reviewerIdentities(view.reviewRequests),
|
|
6333
|
+
users: humanReviewerLogins(view.reviewRequests),
|
|
6334
|
+
teams: teamReviewerSlugs(view.reviewRequests)
|
|
6335
|
+
};
|
|
6221
6336
|
return {
|
|
6222
6337
|
number: Number(view.number),
|
|
6223
6338
|
title: String(view.title ?? ""),
|
|
@@ -6253,10 +6368,34 @@ async function getPrDetails(cwd, selector) {
|
|
|
6253
6368
|
submittedAt: normalizeGhTime(row.submittedAt)
|
|
6254
6369
|
};
|
|
6255
6370
|
}),
|
|
6371
|
+
assignees: reviewerIdentities(view.assignees),
|
|
6372
|
+
labels: labelNames(view.labels),
|
|
6373
|
+
reviewRequests: requested.ids,
|
|
6374
|
+
reviewers: requested.users,
|
|
6375
|
+
teams: requested.teams,
|
|
6256
6376
|
// CI lives in Checks tab via getPrChecks — nesting burned GraphQL points.
|
|
6257
6377
|
checks: []
|
|
6258
6378
|
};
|
|
6259
6379
|
}
|
|
6380
|
+
async function getPrDetails(cwd, selector) {
|
|
6381
|
+
const slug = await resolveGithubRepoSlug(cwd);
|
|
6382
|
+
const viewArgs = ["pr", "view", selector, "--json", PR_DETAILS_JSON_FIELDS];
|
|
6383
|
+
if (slug) viewArgs.push("--repo", slug);
|
|
6384
|
+
const { stdout, exitCode, stderr } = await gh(viewArgs, cwd, { reject: false });
|
|
6385
|
+
if (exitCode !== 0 || !stdout.trim()) {
|
|
6386
|
+
if (stderr.trim()) {
|
|
6387
|
+
if (/no pull requests found/i.test(stderr)) return null;
|
|
6388
|
+
}
|
|
6389
|
+
return null;
|
|
6390
|
+
}
|
|
6391
|
+
let view;
|
|
6392
|
+
try {
|
|
6393
|
+
view = JSON.parse(stdout);
|
|
6394
|
+
} catch {
|
|
6395
|
+
throw new Error(stderr.trim() || "gh pr view returned invalid JSON");
|
|
6396
|
+
}
|
|
6397
|
+
return parsePrDetailsView(view);
|
|
6398
|
+
}
|
|
6260
6399
|
async function fetchPrHead(repoPath, number, localBranch) {
|
|
6261
6400
|
const slug = await resolveGithubRepoSlug(repoPath);
|
|
6262
6401
|
const refspec = `+pull/${number}/head:${localBranch}`;
|
|
@@ -6967,7 +7106,7 @@ function allocateTeamSlug(repoPath) {
|
|
|
6967
7106
|
}
|
|
6968
7107
|
throw new Error("No available soccer team worktree directories left");
|
|
6969
7108
|
}
|
|
6970
|
-
var import_node_crypto4, import_node_fs15, import_node_os6, import_node_path18;
|
|
7109
|
+
var import_node_crypto4, import_node_fs15, import_node_os6, import_node_path18, PR_DETAILS_JSON_FIELDS;
|
|
6971
7110
|
var init_worktree = __esm({
|
|
6972
7111
|
"src/git/worktree.ts"() {
|
|
6973
7112
|
"use strict";
|
|
@@ -6989,9 +7128,30 @@ var init_worktree = __esm({
|
|
|
6989
7128
|
init_pr_gates();
|
|
6990
7129
|
init_stack();
|
|
6991
7130
|
init_teams();
|
|
7131
|
+
init_worktree_labels();
|
|
6992
7132
|
init_git_auth_mode();
|
|
6993
7133
|
init_workspace_scratch();
|
|
6994
7134
|
init_worktree_labels();
|
|
7135
|
+
PR_DETAILS_JSON_FIELDS = [
|
|
7136
|
+
"number",
|
|
7137
|
+
"title",
|
|
7138
|
+
"body",
|
|
7139
|
+
"url",
|
|
7140
|
+
"state",
|
|
7141
|
+
"isDraft",
|
|
7142
|
+
"reviewDecision",
|
|
7143
|
+
"author",
|
|
7144
|
+
"baseRefName",
|
|
7145
|
+
"headRefName",
|
|
7146
|
+
"additions",
|
|
7147
|
+
"deletions",
|
|
7148
|
+
"changedFiles",
|
|
7149
|
+
"comments",
|
|
7150
|
+
"reviews",
|
|
7151
|
+
"assignees",
|
|
7152
|
+
"labels",
|
|
7153
|
+
"reviewRequests"
|
|
7154
|
+
].join(",");
|
|
6995
7155
|
}
|
|
6996
7156
|
});
|
|
6997
7157
|
|
|
@@ -7257,36 +7417,6 @@ var init_stage_files = __esm({
|
|
|
7257
7417
|
}
|
|
7258
7418
|
});
|
|
7259
7419
|
|
|
7260
|
-
// src/agents/orchestrator-capable.ts
|
|
7261
|
-
function isOrchestratorCapableAgent(agent) {
|
|
7262
|
-
return Boolean(
|
|
7263
|
-
agent && ORCHESTRATOR_AGENT_KINDS.includes(agent)
|
|
7264
|
-
);
|
|
7265
|
-
}
|
|
7266
|
-
function assertOrchestratorCapableAgent(agent, context = "orchestration") {
|
|
7267
|
-
if (!isOrchestratorCapableAgent(agent)) {
|
|
7268
|
-
throw new Error(
|
|
7269
|
-
`${agent} cannot run ${context} \u2014 it does not support Sideboard MCP. Use Claude, Cursor, Codex, or OpenCode.`
|
|
7270
|
-
);
|
|
7271
|
-
}
|
|
7272
|
-
return agent;
|
|
7273
|
-
}
|
|
7274
|
-
function coerceOrchestratorAgent(agent, fallback = "claude") {
|
|
7275
|
-
return isOrchestratorCapableAgent(agent) ? agent : fallback;
|
|
7276
|
-
}
|
|
7277
|
-
var ORCHESTRATOR_AGENT_KINDS;
|
|
7278
|
-
var init_orchestrator_capable = __esm({
|
|
7279
|
-
"src/agents/orchestrator-capable.ts"() {
|
|
7280
|
-
"use strict";
|
|
7281
|
-
ORCHESTRATOR_AGENT_KINDS = [
|
|
7282
|
-
"claude",
|
|
7283
|
-
"codex",
|
|
7284
|
-
"opencode",
|
|
7285
|
-
"cursor"
|
|
7286
|
-
];
|
|
7287
|
-
}
|
|
7288
|
-
});
|
|
7289
|
-
|
|
7290
7420
|
// src/store/workspaces.ts
|
|
7291
7421
|
var workspaces_exports = {};
|
|
7292
7422
|
__export(workspaces_exports, {
|
|
@@ -7751,7 +7881,7 @@ function createGlobalChat(opts) {
|
|
|
7751
7881
|
const explicit = opts.title?.trim();
|
|
7752
7882
|
const title = explicit && explicit !== CLOUD_ORCHESTRATOR_GOAL ? explicit : allocateTeamName(takenTeamSlugsForOrchestration()).name;
|
|
7753
7883
|
const sourceRef = opts.sourceRef?.trim() || (isCloud ? CLOUD_ORCHESTRATOR_GOAL : title);
|
|
7754
|
-
const resolved =
|
|
7884
|
+
const resolved = resolveNewOrchestratorOptions({
|
|
7755
7885
|
agent: opts.agent,
|
|
7756
7886
|
model: opts.model,
|
|
7757
7887
|
effort: opts.effort,
|
|
@@ -7827,7 +7957,7 @@ function findSlackCoordinator(teamId, userId) {
|
|
|
7827
7957
|
);
|
|
7828
7958
|
}
|
|
7829
7959
|
function ensureSlackCoordinator(teamId, userId, agent, opts) {
|
|
7830
|
-
const defaults =
|
|
7960
|
+
const defaults = resolveOrchestratorDefaults();
|
|
7831
7961
|
const desired = assertOrchestratorCapableAgent(agent);
|
|
7832
7962
|
const ref = slackCoordinatorSourceRef(teamId, userId);
|
|
7833
7963
|
if (!opts?.forceNew) {
|
|
@@ -7862,7 +7992,7 @@ function ensureSlackCoordinator(teamId, userId, agent, opts) {
|
|
|
7862
7992
|
});
|
|
7863
7993
|
}
|
|
7864
7994
|
function ensureCloudCoordinator(agent) {
|
|
7865
|
-
const defaults =
|
|
7995
|
+
const defaults = resolveOrchestratorDefaults();
|
|
7866
7996
|
const desired = assertOrchestratorCapableAgent(agent);
|
|
7867
7997
|
const existing = findCloudCoordinator();
|
|
7868
7998
|
if (existing) {
|
|
@@ -8315,22 +8445,38 @@ var init_brightsy_targets = __esm({
|
|
|
8315
8445
|
// src/agents/turn-input.ts
|
|
8316
8446
|
function normalizeTurnInput(input) {
|
|
8317
8447
|
if (typeof input === "string") return { prompt: input };
|
|
8318
|
-
return {
|
|
8448
|
+
return {
|
|
8449
|
+
prompt: input.prompt,
|
|
8450
|
+
cachedPrefix: input.cachedPrefix?.trim() || void 0,
|
|
8451
|
+
systemPrompt: input.systemPrompt?.trim() || void 0
|
|
8452
|
+
};
|
|
8319
8453
|
}
|
|
8320
8454
|
function dropCachedPrefixOnResume(input, sessionId) {
|
|
8321
8455
|
const turn = normalizeTurnInput(input);
|
|
8322
|
-
if (sessionId)
|
|
8456
|
+
if (sessionId) {
|
|
8457
|
+
return turn.systemPrompt ? { prompt: turn.prompt, systemPrompt: turn.systemPrompt } : { prompt: turn.prompt };
|
|
8458
|
+
}
|
|
8323
8459
|
return turn;
|
|
8324
8460
|
}
|
|
8325
8461
|
function flattenTurnInput(input) {
|
|
8326
|
-
const { cachedPrefix, prompt } = normalizeTurnInput(input);
|
|
8327
|
-
if (
|
|
8328
|
-
return `${cachedPrefix}
|
|
8462
|
+
const { cachedPrefix, prompt, systemPrompt } = normalizeTurnInput(input);
|
|
8463
|
+
if (cachedPrefix) return `${cachedPrefix}
|
|
8329
8464
|
|
|
8330
8465
|
---
|
|
8331
8466
|
|
|
8332
8467
|
Current request:
|
|
8333
8468
|
${prompt}`;
|
|
8469
|
+
if (systemPrompt) return `${systemPrompt}
|
|
8470
|
+
|
|
8471
|
+
${prompt}`;
|
|
8472
|
+
return prompt;
|
|
8473
|
+
}
|
|
8474
|
+
function splitTurnInputForSystemPrompt(input) {
|
|
8475
|
+
const turn = normalizeTurnInput(input);
|
|
8476
|
+
return {
|
|
8477
|
+
promptText: flattenTurnInput({ cachedPrefix: turn.cachedPrefix, prompt: turn.prompt }),
|
|
8478
|
+
systemPrompt: turn.systemPrompt
|
|
8479
|
+
};
|
|
8334
8480
|
}
|
|
8335
8481
|
var init_turn_input = __esm({
|
|
8336
8482
|
"src/agents/turn-input.ts"() {
|
|
@@ -10164,7 +10310,7 @@ var init_claude = __esm({
|
|
|
10164
10310
|
const claude = resolveClaudeExecutable();
|
|
10165
10311
|
const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
10166
10312
|
const effective = dropCachedPrefixOnResume(input, sessionId);
|
|
10167
|
-
const promptText =
|
|
10313
|
+
const { promptText, systemPrompt } = splitTurnInputForSystemPrompt(effective);
|
|
10168
10314
|
const useStdin = promptText.length > CLAUDE_PROMPT_ARG_MAX;
|
|
10169
10315
|
if (process.env.SIDEBOARD_DEBUG_CLAUDE_TURN === "1") {
|
|
10170
10316
|
console.error(
|
|
@@ -10216,6 +10362,9 @@ var init_claude = __esm({
|
|
|
10216
10362
|
"--permission-mode",
|
|
10217
10363
|
mode.claude
|
|
10218
10364
|
];
|
|
10365
|
+
if (systemPrompt) {
|
|
10366
|
+
args.push("--append-system-prompt", systemPrompt);
|
|
10367
|
+
}
|
|
10219
10368
|
const mcpConfigPath = writeMcpServersConfig(injectedServers);
|
|
10220
10369
|
if (mcpConfigPath) {
|
|
10221
10370
|
args.push("--mcp-config", mcpConfigPath);
|
|
@@ -12092,7 +12241,50 @@ function agentGitPrompt(action, opts) {
|
|
|
12092
12241
|
return "Merge PR.";
|
|
12093
12242
|
}
|
|
12094
12243
|
}
|
|
12095
|
-
|
|
12244
|
+
function gitActionExpansion(action, base) {
|
|
12245
|
+
switch (action) {
|
|
12246
|
+
case "commit-push":
|
|
12247
|
+
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.";
|
|
12248
|
+
case "create-draft":
|
|
12249
|
+
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.";
|
|
12250
|
+
case "create-web":
|
|
12251
|
+
return "Commit, push, then `gh pr create --web -R <origin-owner/name>`.";
|
|
12252
|
+
case "resolve-conflicts":
|
|
12253
|
+
return `Fetch the PR base${base ? ` (\`${base}\`)` : ""}, merge it into this branch, resolve conflicts carefully, then commit and push until the PR is mergeable.`;
|
|
12254
|
+
case "merge":
|
|
12255
|
+
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.";
|
|
12256
|
+
}
|
|
12257
|
+
}
|
|
12258
|
+
function expandCanonicalGitRequest(prompt) {
|
|
12259
|
+
const trimmed = prompt.trim();
|
|
12260
|
+
let action = null;
|
|
12261
|
+
let base = null;
|
|
12262
|
+
for (const candidate of AGENT_GIT_ACTIONS) {
|
|
12263
|
+
if (candidate === "resolve-conflicts") continue;
|
|
12264
|
+
if (agentGitPrompt(candidate) === trimmed) {
|
|
12265
|
+
action = candidate;
|
|
12266
|
+
break;
|
|
12267
|
+
}
|
|
12268
|
+
}
|
|
12269
|
+
if (!action) {
|
|
12270
|
+
const m = RESOLVE_CONFLICTS_RE.exec(trimmed);
|
|
12271
|
+
if (m) {
|
|
12272
|
+
action = "resolve-conflicts";
|
|
12273
|
+
base = m[1] ?? null;
|
|
12274
|
+
}
|
|
12275
|
+
}
|
|
12276
|
+
let expansion = action ? gitActionExpansion(action, base) : null;
|
|
12277
|
+
if (!expansion && trimmed === "Address review comments.") {
|
|
12278
|
+
expansion = "Read the PR review feedback (`gh pr view --comments`, `gh api` review comments), make the requested changes, commit, and push.";
|
|
12279
|
+
} else if (!expansion && FIX_CI_RE.test(trimmed)) {
|
|
12280
|
+
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.";
|
|
12281
|
+
}
|
|
12282
|
+
if (!expansion) return prompt;
|
|
12283
|
+
return `${trimmed}
|
|
12284
|
+
|
|
12285
|
+
(Sideboard git request \u2014 do not ask for clarification: ${expansion})`;
|
|
12286
|
+
}
|
|
12287
|
+
var AGENT_GIT_ACTIONS, RESOLVE_CONFLICTS_RE, FIX_CI_RE;
|
|
12096
12288
|
var init_agent_git_actions = __esm({
|
|
12097
12289
|
"src/git/agent-git-actions.ts"() {
|
|
12098
12290
|
"use strict";
|
|
@@ -12103,6 +12295,8 @@ var init_agent_git_actions = __esm({
|
|
|
12103
12295
|
"resolve-conflicts",
|
|
12104
12296
|
"merge"
|
|
12105
12297
|
];
|
|
12298
|
+
RESOLVE_CONFLICTS_RE = /^Merge the remote branch(?: \(([^)]+)\))? into your branch and resolve conflicts\. Then, commit and push your changes\.$/;
|
|
12299
|
+
FIX_CI_RE = /^Fix CI: .+\.$/;
|
|
12106
12300
|
}
|
|
12107
12301
|
});
|
|
12108
12302
|
|
|
@@ -12340,47 +12534,82 @@ function formatToolPart(t, detail) {
|
|
|
12340
12534
|
}
|
|
12341
12535
|
function formatMessagesAsTranscript(messages, opts) {
|
|
12342
12536
|
const tools = opts?.tools ?? "full";
|
|
12343
|
-
const
|
|
12344
|
-
|
|
12345
|
-
|
|
12346
|
-
|
|
12347
|
-
|
|
12348
|
-
|
|
12349
|
-
|
|
12350
|
-
|
|
12351
|
-
|
|
12352
|
-
|
|
12353
|
-
|
|
12354
|
-
}
|
|
12355
|
-
const bits = [];
|
|
12356
|
-
if (m.text?.trim()) {
|
|
12357
|
-
bits.push(`### Agent
|
|
12537
|
+
const thinking = opts?.thinking ?? true;
|
|
12538
|
+
return messages.map((m) => formatMessageBlock(m, { tools, thinking })).join("\n\n");
|
|
12539
|
+
}
|
|
12540
|
+
function formatMessageBlock(m, opts) {
|
|
12541
|
+
if (m.role === "summary") return `## Prior summary
|
|
12542
|
+
${m.text}`;
|
|
12543
|
+
if (m.role === "user") return `### User
|
|
12544
|
+
${m.text}`;
|
|
12545
|
+
const bits = [];
|
|
12546
|
+
if (m.text?.trim()) {
|
|
12547
|
+
bits.push(`### Agent
|
|
12358
12548
|
${m.text}`);
|
|
12359
|
-
|
|
12360
|
-
|
|
12361
|
-
|
|
12362
|
-
|
|
12363
|
-
for (const th of
|
|
12549
|
+
} else {
|
|
12550
|
+
bits.push("### Agent");
|
|
12551
|
+
}
|
|
12552
|
+
if (opts.thinking) {
|
|
12553
|
+
for (const th of m.parts ?? []) {
|
|
12364
12554
|
if (th.type !== "thinking" || !th.text.trim()) continue;
|
|
12365
12555
|
bits.push("Thinking:");
|
|
12366
12556
|
bits.push(th.text);
|
|
12367
12557
|
}
|
|
12368
|
-
|
|
12369
|
-
|
|
12370
|
-
)
|
|
12371
|
-
|
|
12372
|
-
|
|
12373
|
-
|
|
12374
|
-
|
|
12375
|
-
|
|
12558
|
+
}
|
|
12559
|
+
const toolParts = (m.parts ?? []).filter(
|
|
12560
|
+
(p) => p.type === "tool"
|
|
12561
|
+
);
|
|
12562
|
+
if (opts.tools !== "none" && toolParts.length > 0) {
|
|
12563
|
+
if (opts.tools === "summary") bits.push("Tools:");
|
|
12564
|
+
for (const t of toolParts) {
|
|
12565
|
+
bits.push(formatToolPart(t, opts.tools));
|
|
12376
12566
|
}
|
|
12377
|
-
blocks.push(bits.join("\n"));
|
|
12378
12567
|
}
|
|
12379
|
-
return
|
|
12568
|
+
return bits.join("\n");
|
|
12380
12569
|
}
|
|
12381
12570
|
function buildSessionSeed(messages, opts) {
|
|
12382
12571
|
if (messages.length === 0) return null;
|
|
12383
|
-
const
|
|
12572
|
+
const tools = opts?.tools ?? "full";
|
|
12573
|
+
const fullCount = opts?.fullToolMessages ?? SEED_FULL_TOOL_MESSAGES;
|
|
12574
|
+
const maxChars = opts?.maxChars ?? SEED_MAX_CHARS;
|
|
12575
|
+
const olderTools = tools === "none" ? "none" : "summary";
|
|
12576
|
+
const fullFrom = Math.max(0, messages.length - fullCount);
|
|
12577
|
+
const blocks = messages.map(
|
|
12578
|
+
(m, i) => formatMessageBlock(m, {
|
|
12579
|
+
tools: i >= fullFrom ? tools : olderTools,
|
|
12580
|
+
thinking: false
|
|
12581
|
+
})
|
|
12582
|
+
);
|
|
12583
|
+
const keep = new Array(blocks.length).fill(false);
|
|
12584
|
+
let used = 0;
|
|
12585
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
12586
|
+
if (messages[i].role === "summary") {
|
|
12587
|
+
keep[i] = true;
|
|
12588
|
+
used += blocks[i].length + 2;
|
|
12589
|
+
}
|
|
12590
|
+
}
|
|
12591
|
+
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
12592
|
+
if (keep[i]) continue;
|
|
12593
|
+
const next = used + blocks[i].length + 2;
|
|
12594
|
+
if (next > maxChars && used > 0) break;
|
|
12595
|
+
keep[i] = true;
|
|
12596
|
+
used = next;
|
|
12597
|
+
}
|
|
12598
|
+
const dropped = keep.filter((k) => !k).length;
|
|
12599
|
+
const kept = [];
|
|
12600
|
+
let markerPlaced = false;
|
|
12601
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
12602
|
+
if (!keep[i]) continue;
|
|
12603
|
+
if (dropped > 0 && !markerPlaced && messages[i].role !== "summary") {
|
|
12604
|
+
kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
|
|
12605
|
+
markerPlaced = true;
|
|
12606
|
+
}
|
|
12607
|
+
kept.push(blocks[i]);
|
|
12608
|
+
}
|
|
12609
|
+
if (dropped > 0 && !markerPlaced) {
|
|
12610
|
+
kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
|
|
12611
|
+
}
|
|
12612
|
+
const body = kept.join("\n\n");
|
|
12384
12613
|
if (!body.trim()) return null;
|
|
12385
12614
|
return [
|
|
12386
12615
|
"Sideboard conversation context (restored after compaction or a new session):",
|
|
@@ -12433,7 +12662,7 @@ function findLastBrightsyContextSummary(messages) {
|
|
|
12433
12662
|
function buildBrightsySessionSeed(messages) {
|
|
12434
12663
|
const match = findLastBrightsyContextSummary(messages);
|
|
12435
12664
|
const tail = match ? messages.slice(match.index + 1) : messages;
|
|
12436
|
-
const body = formatMessagesAsTranscript(tail, { tools: "none" });
|
|
12665
|
+
const body = formatMessagesAsTranscript(tail, { tools: "none", thinking: false });
|
|
12437
12666
|
if (!match && !body.trim()) return null;
|
|
12438
12667
|
const blocks = [
|
|
12439
12668
|
"Sideboard conversation context (restored after compaction or a new session):",
|
|
@@ -12500,7 +12729,7 @@ async function maybeCompactContext(thread, thresholds = {}, summarize = summariz
|
|
|
12500
12729
|
olderCount: older.length
|
|
12501
12730
|
};
|
|
12502
12731
|
}
|
|
12503
|
-
var CONTEXT_COMPACT_CHARS, CONTEXT_KEEP_RECENT_CHARS, CONTEXT_KEEP_RECENT_MESSAGES, CONTEXT_MIN_MESSAGES, SESSION_RESET_OCCUPANCY_TOKENS, BRIGHTSY_SUMMARIZE_CONTEXT_TOOL;
|
|
12732
|
+
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;
|
|
12504
12733
|
var init_context_compact = __esm({
|
|
12505
12734
|
"src/composer/context-compact.ts"() {
|
|
12506
12735
|
"use strict";
|
|
@@ -12513,6 +12742,8 @@ var init_context_compact = __esm({
|
|
|
12513
12742
|
CONTEXT_KEEP_RECENT_MESSAGES = 12;
|
|
12514
12743
|
CONTEXT_MIN_MESSAGES = 10;
|
|
12515
12744
|
SESSION_RESET_OCCUPANCY_TOKENS = 75e4;
|
|
12745
|
+
SEED_MAX_CHARS = 6e4;
|
|
12746
|
+
SEED_FULL_TOOL_MESSAGES = 6;
|
|
12516
12747
|
BRIGHTSY_SUMMARIZE_CONTEXT_TOOL = "summarize_context";
|
|
12517
12748
|
}
|
|
12518
12749
|
});
|
|
@@ -15310,10 +15541,11 @@ async function createThread(input, _onSetupLine) {
|
|
|
15310
15541
|
throw new Error("Use adoptThread() for adopt sources");
|
|
15311
15542
|
}
|
|
15312
15543
|
const team = allocateTeamSlug(repoPath);
|
|
15544
|
+
const slug = sourceType === "ticket" ? worktreeSlugForTicket(persistedSourceRef, team.slug) : team.slug;
|
|
15313
15545
|
const { branchName, worktreePath } = await createThreadWorktree({
|
|
15314
15546
|
repoPath,
|
|
15315
15547
|
sourceRef,
|
|
15316
|
-
slug
|
|
15548
|
+
slug
|
|
15317
15549
|
});
|
|
15318
15550
|
copyConfiguredFiles(repoPath, worktreePath);
|
|
15319
15551
|
const explicitTitle = title?.trim();
|
|
@@ -17586,12 +17818,17 @@ function normPath3(p) {
|
|
|
17586
17818
|
function formatRenameBranchDirective(thread, opts) {
|
|
17587
17819
|
if (!isPlaceholderBranch(thread.branchName, thread.worktreePath)) return null;
|
|
17588
17820
|
const dir = worktreeNameFromPath(thread.worktreePath);
|
|
17821
|
+
const ticket = thread.sourceType === "ticket" ? ticketSlugForBranch(thread.sourceRef ?? "") : null;
|
|
17822
|
+
const example = ticket ? `\`feat/${ticket}-dark-mode\` or \`fix/${ticket}-panel-width\`` : "`fix/panel-width` or `feat/dark-mode`";
|
|
17589
17823
|
const lines = [
|
|
17590
17824
|
"Branch naming (do this early in the turn):",
|
|
17591
|
-
`- Current branch \`${thread.branchName}\` is a temporary placeholder. The worktree folder \`${dir}\` is a stable
|
|
17592
|
-
|
|
17825
|
+
`- Current branch \`${thread.branchName}\` is a temporary placeholder. The worktree folder \`${dir}\` is a stable nickname \u2014 do not rename or leave that directory.`,
|
|
17826
|
+
`- Rename the git branch to a short kebab-case name that describes this task (what you are changing), e.g. ${example}:`,
|
|
17593
17827
|
" `git branch -m <new-name>`",
|
|
17594
17828
|
"- Prefer Conventional Commits style prefixes when they fit (`fix/`, `feat/`, `chore/`, `docs/`).",
|
|
17829
|
+
...ticket ? [
|
|
17830
|
+
`- Keep ticket \`${ticket}\` in the new branch name so the issue stays findable.`
|
|
17831
|
+
] : [],
|
|
17595
17832
|
"- Never push this placeholder to main/master."
|
|
17596
17833
|
];
|
|
17597
17834
|
const custom = opts?.customPrompt?.trim();
|
|
@@ -17625,67 +17862,37 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
17625
17862
|
lines.push(
|
|
17626
17863
|
"- 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)."
|
|
17627
17864
|
);
|
|
17628
|
-
lines.push(
|
|
17629
|
-
"- Push with `git push -u origin HEAD` (or the current branch name). Do not `git push upstream`."
|
|
17630
|
-
);
|
|
17631
|
-
lines.push("");
|
|
17632
17865
|
lines.push(formatGitAuthModeDirective(opts?.gitAuthMode ?? "auto"));
|
|
17633
17866
|
lines.push(
|
|
17634
|
-
"-
|
|
17867
|
+
"- 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."
|
|
17635
17868
|
);
|
|
17636
17869
|
lines.push(
|
|
17637
|
-
"-
|
|
17638
|
-
);
|
|
17639
|
-
lines.push(
|
|
17640
|
-
"- Commit with messages that state the purpose of the change (same standard as the PR). Stay on this thread branch. Never push directly to main/master or merge locally into the main checkout. Do not merge the PR unless this turn is a Merge PR request or the user explicitly asked. When merging, use GitHub from this worktree (`gh pr merge` / `gh stack merge`)."
|
|
17870
|
+
"- 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`)."
|
|
17641
17871
|
);
|
|
17642
17872
|
if (thread.prUrl) {
|
|
17643
17873
|
lines.push(
|
|
17644
17874
|
`- A PR already exists (${thread.prUrl}). Update it (push + edit title/body if the purpose drifted) instead of opening a duplicate.`
|
|
17645
17875
|
);
|
|
17646
|
-
} else if (opts?.githubSlug) {
|
|
17647
|
-
lines.push(
|
|
17648
|
-
`- 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\`.`
|
|
17649
|
-
);
|
|
17650
17876
|
} else {
|
|
17877
|
+
const slug = opts?.githubSlug ?? "<origin-owner/name>";
|
|
17878
|
+
const resolve = opts?.githubSlug ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
|
|
17651
17879
|
lines.push(
|
|
17652
|
-
|
|
17880
|
+
`- 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\`.`
|
|
17653
17881
|
);
|
|
17654
17882
|
}
|
|
17655
|
-
lines.push("");
|
|
17656
|
-
lines.push(
|
|
17657
|
-
"Short git requests from the Sideboard UI are complete instructions \u2014 expand them using the rules above without asking for clarification:"
|
|
17658
|
-
);
|
|
17659
|
-
lines.push(
|
|
17660
|
-
'- "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.'
|
|
17661
|
-
);
|
|
17662
|
-
lines.push(
|
|
17663
|
-
'- "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).'
|
|
17664
|
-
);
|
|
17665
|
-
lines.push(
|
|
17666
|
-
'- "Commit, push, and open a PR in the browser." \u2192 commit, push, then `gh pr create --web -R \u2026`.'
|
|
17667
|
-
);
|
|
17668
|
-
lines.push(
|
|
17669
|
-
'- "Fix CI: <name>." \u2192 investigate that failing check, fix it, commit, and push. Loop only if they gave a goal to keep going until it passes.'
|
|
17670
|
-
);
|
|
17671
|
-
lines.push(
|
|
17672
|
-
'- "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.'
|
|
17673
|
-
);
|
|
17674
17883
|
lines.push(
|
|
17675
|
-
'- "
|
|
17676
|
-
);
|
|
17677
|
-
lines.push(
|
|
17678
|
-
'- "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.'
|
|
17884
|
+
'- 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.'
|
|
17679
17885
|
);
|
|
17680
17886
|
lines.push("");
|
|
17681
|
-
lines.push(
|
|
17682
|
-
lines.push("");
|
|
17683
|
-
lines.push(formatProcessGuideDirective());
|
|
17887
|
+
lines.push(formatProcessGuideDirective({ worktreePath: thread.worktreePath }));
|
|
17684
17888
|
return lines.join("\n");
|
|
17685
17889
|
}
|
|
17686
17890
|
function formatWorktreeReminder() {
|
|
17687
17891
|
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.";
|
|
17688
17892
|
}
|
|
17893
|
+
function mentionsPrGoal(prompt) {
|
|
17894
|
+
return PR_GOAL_RE.test(prompt);
|
|
17895
|
+
}
|
|
17689
17896
|
function issueTicketFromThread(thread, preferredSource = "github") {
|
|
17690
17897
|
if (thread?.sourceType !== "ticket") return null;
|
|
17691
17898
|
const ref = thread.sourceRef?.trim() ?? "";
|
|
@@ -17752,29 +17959,27 @@ function formatPrGateDirective() {
|
|
|
17752
17959
|
"- 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."
|
|
17753
17960
|
].join("\n");
|
|
17754
17961
|
}
|
|
17755
|
-
function formatProcessGuideDirective() {
|
|
17962
|
+
function formatProcessGuideDirective(opts) {
|
|
17963
|
+
const worktree = opts?.worktreePath?.trim();
|
|
17964
|
+
const hasGraphSkill = !!worktree && (0, import_node_fs46.existsSync)((0, import_node_path43.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
|
|
17965
|
+
const hasReviewSkill = !!worktree && (0, import_node_fs46.existsSync)((0, import_node_path43.join)(worktree, ".claude/skills/review/SKILL.md"));
|
|
17756
17966
|
return [
|
|
17757
17967
|
"Process guides (recurring work only):",
|
|
17758
|
-
"-
|
|
17759
|
-
"- If `.claude/skills
|
|
17760
|
-
"-
|
|
17761
|
-
"- 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.",
|
|
17762
|
-
"- 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.",
|
|
17968
|
+
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,
|
|
17969
|
+
"- 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`.",
|
|
17970
|
+
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.",
|
|
17763
17971
|
"- 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."
|
|
17764
|
-
].join("\n");
|
|
17972
|
+
].filter(Boolean).join("\n");
|
|
17765
17973
|
}
|
|
17766
17974
|
function formatLongRunningDirective(opts) {
|
|
17767
17975
|
const invoke = formatDetachedJobInvoke(opts?.scriptPath);
|
|
17768
17976
|
return [
|
|
17769
|
-
"Long-running jobs (mandatory when a command may run more than ~30s):",
|
|
17770
|
-
"A Sideboard worktree turn SIGTERMs the agent shell (and its process group) when the user sends another message or the turn is interrupted
|
|
17771
|
-
|
|
17772
|
-
|
|
17773
|
-
"-
|
|
17774
|
-
|
|
17775
|
-
`- 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.`,
|
|
17776
|
-
"- 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).",
|
|
17777
|
-
"- ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
|
|
17977
|
+
"Long-running jobs (mandatory when a command may run more than ~30s \u2014 pack, test, deploy, `gh pr checks --watch`):",
|
|
17978
|
+
"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.",
|
|
17979
|
+
`- 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.`,
|
|
17980
|
+
"- 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>`.",
|
|
17981
|
+
"- 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.",
|
|
17982
|
+
"- 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.",
|
|
17778
17983
|
"State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
|
|
17779
17984
|
].join("\n");
|
|
17780
17985
|
}
|
|
@@ -17784,33 +17989,17 @@ function formatLongRunningReminder(opts) {
|
|
|
17784
17989
|
}
|
|
17785
17990
|
function formatArtifactDirective() {
|
|
17786
17991
|
return [
|
|
17787
|
-
"Sideboard side column (desktop UI)
|
|
17788
|
-
"
|
|
17789
|
-
"
|
|
17790
|
-
"
|
|
17791
|
-
"
|
|
17792
|
-
"```html",
|
|
17793
|
-
"<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
|
|
17794
|
-
"```",
|
|
17795
|
-
"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.",
|
|
17796
|
-
" 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.",
|
|
17797
|
-
"CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
|
|
17798
|
-
"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:",
|
|
17799
|
-
" - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
|
|
17800
|
-
" - datasource=inline + resource: { id, title, schema, schemaUi } and optional records/record.",
|
|
17801
|
-
"Files / media browser (CMS file manager column):",
|
|
17802
|
-
"4) Call Sideboard MCP `present_files` with optional title, path, and datasource (brightsy|memory).",
|
|
17803
|
-
" Opens the Files column for browse/upload/pick. Do NOT say a file manager UI is missing.",
|
|
17804
|
-
"Multiple-choice questions:",
|
|
17805
|
-
"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.",
|
|
17806
|
-
"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.",
|
|
17807
|
-
"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."
|
|
17992
|
+
"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.",
|
|
17993
|
+
"- 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.",
|
|
17994
|
+
"- 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.",
|
|
17995
|
+
"- 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.",
|
|
17996
|
+
"- 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."
|
|
17808
17997
|
].join("\n");
|
|
17809
17998
|
}
|
|
17810
17999
|
function formatUiReminder() {
|
|
17811
18000
|
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.";
|
|
17812
18001
|
}
|
|
17813
|
-
var import_node_fs46, import_node_path43, GITHUB_TICKET_REF, KEYED_TICKET_REF;
|
|
18002
|
+
var import_node_fs46, import_node_path43, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
|
|
17814
18003
|
var init_instructions = __esm({
|
|
17815
18004
|
"src/agents/instructions.ts"() {
|
|
17816
18005
|
"use strict";
|
|
@@ -17819,6 +18008,7 @@ var init_instructions = __esm({
|
|
|
17819
18008
|
init_git_auth_mode();
|
|
17820
18009
|
init_worktree_labels();
|
|
17821
18010
|
init_detached_job_path();
|
|
18011
|
+
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;
|
|
17822
18012
|
GITHUB_TICKET_REF = /^(?:#?\d+|gh-\d+)$/i;
|
|
17823
18013
|
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;
|
|
17824
18014
|
}
|
|
@@ -18507,7 +18697,7 @@ async function defaultDeps() {
|
|
|
18507
18697
|
}
|
|
18508
18698
|
function pickAgent(schedule) {
|
|
18509
18699
|
if (schedule.agent) return schedule.agent;
|
|
18510
|
-
return coerceOrchestratorAgent(
|
|
18700
|
+
return coerceOrchestratorAgent(resolveOrchestratorDefaults().agent);
|
|
18511
18701
|
}
|
|
18512
18702
|
async function fireSchedule(id) {
|
|
18513
18703
|
const schedule = getSchedule(id);
|
|
@@ -19587,17 +19777,21 @@ var init_orchestrator = __esm({
|
|
|
19587
19777
|
const slackReplyContext = formatSlackRepliesForTurn(
|
|
19588
19778
|
pendingSlackExternalReplies(thread.messages)
|
|
19589
19779
|
);
|
|
19590
|
-
const
|
|
19591
|
-
thread.planMode ? PLAN_MODE_INSTRUCTION : null,
|
|
19592
|
-
orchestrationReminder,
|
|
19780
|
+
const turnReminders = [
|
|
19593
19781
|
worktreeReminder,
|
|
19594
19782
|
optionalServicesReminder,
|
|
19595
19783
|
issueToolsReminder,
|
|
19596
19784
|
viewerContextReminder,
|
|
19597
19785
|
artifactReminder,
|
|
19598
|
-
longRunningReminder
|
|
19786
|
+
longRunningReminder
|
|
19787
|
+
].filter(Boolean).join("\n\n") || void 0;
|
|
19788
|
+
const prGateDirective = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && mentionsPrGoal(expandedPrompt) ? formatPrGateDirective() : null;
|
|
19789
|
+
const agentPrompt = [
|
|
19790
|
+
thread.planMode ? PLAN_MODE_INSTRUCTION : null,
|
|
19791
|
+
orchestrationReminder,
|
|
19792
|
+
prGateDirective,
|
|
19599
19793
|
slackReplyContext,
|
|
19600
|
-
expandedPrompt
|
|
19794
|
+
expandCanonicalGitRequest(expandedPrompt)
|
|
19601
19795
|
].filter(Boolean).join("\n\n");
|
|
19602
19796
|
if (thread.attachments.length > 0) {
|
|
19603
19797
|
updateThread(threadId, { attachments: [] });
|
|
@@ -19687,7 +19881,7 @@ var init_orchestrator = __esm({
|
|
|
19687
19881
|
const stderrTail = [];
|
|
19688
19882
|
const handle = await spawnAgentTurn(
|
|
19689
19883
|
fresh,
|
|
19690
|
-
{ cachedPrefix, prompt: agentPrompt },
|
|
19884
|
+
{ cachedPrefix, prompt: agentPrompt, systemPrompt: turnReminders },
|
|
19691
19885
|
(event) => {
|
|
19692
19886
|
this.emit({ type: "turn_output", threadId, event });
|
|
19693
19887
|
noteTurnLiveEvent(threadId, event);
|
|
@@ -19796,7 +19990,7 @@ var init_orchestrator = __esm({
|
|
|
19796
19990
|
].filter(Boolean).join("\n\n---\n\n");
|
|
19797
19991
|
const retryHandle = await spawnAgentTurn(
|
|
19798
19992
|
retryThread,
|
|
19799
|
-
{ cachedPrefix: retryPrefix, prompt: agentPrompt },
|
|
19993
|
+
{ cachedPrefix: retryPrefix, prompt: agentPrompt, systemPrompt: turnReminders },
|
|
19800
19994
|
(event) => {
|
|
19801
19995
|
this.emit({ type: "turn_output", threadId, event });
|
|
19802
19996
|
if (event.type === "session_id") {
|