@sideboard-ai/core 0.1.149 → 0.1.150
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-QEVAE67D.js → abletime-223A3LY6.js} +2 -2
- package/dist/{abletime-DI55AJX3.js → abletime-CLC5UJC2.js} +2 -2
- package/dist/agents/cursor-runner.cjs +40 -35
- package/dist/agents/cursor-runner.js +2 -2
- package/dist/{agents-HSVQ2Z6Y.js → agents-KKXGTEV6.js} +10 -9
- package/dist/{agents-V4MTDWXS.js → agents-YWBQXOA2.js} +10 -9
- package/dist/{app-settings-WJDCJFSY.js → app-settings-3CHCNIMD.js} +5 -1
- package/dist/{app-settings-ZCN632OJ.js → app-settings-J3JBCUOT.js} +5 -1
- package/dist/{chunk-I77RYPOH.js → chunk-4XNSGDXE.js} +12 -0
- package/dist/{chunk-KBWND62T.js → chunk-7F4XE6UG.js} +5 -5
- package/dist/{chunk-R4JP32P5.js → chunk-AF6O55PJ.js} +4 -4
- package/dist/{chunk-BOD5V52W.js → chunk-B7XK37WZ.js} +1 -1
- package/dist/{chunk-BGQBELGJ.js → chunk-CZD4NRDZ.js} +12 -0
- package/dist/{chunk-ZVYLEF72.js → chunk-DMRIZR6M.js} +6 -6
- package/dist/{chunk-TZWO7J4W.js → chunk-DXCNW2JF.js} +113 -52
- package/dist/{chunk-KPIYENTF.js → chunk-FNQNJOHY.js} +89 -5
- package/dist/{chunk-ED4UPEJX.js → chunk-G7SIQFBQ.js} +1 -1
- package/dist/{chunk-3QRGCKYL.js → chunk-HAS5EPBS.js} +2 -2
- package/dist/{chunk-LAFA56WD.js → chunk-HEII7W3Q.js} +1 -1
- package/dist/{chunk-EGDRPA4B.js → chunk-NOTANBYC.js} +6 -6
- package/dist/{chunk-JDYKQ6OI.js → chunk-NUPITVRF.js} +134 -73
- package/dist/{chunk-QTUESPAW.js → chunk-PTOSP4AH.js} +1 -1
- package/dist/{chunk-Q62SDB53.js → chunk-QGJHIJHV.js} +2 -2
- package/dist/{chunk-PTI5H3RK.js → chunk-SDN4ZYQH.js} +24 -13
- package/dist/{chunk-DVM4ID64.js → chunk-UFHNSFAS.js} +89 -5
- package/dist/{chunk-N3VNOFXQ.js → chunk-VO4SPEBS.js} +4 -4
- package/dist/chunk-VSFGPWCQ.js +62 -0
- package/dist/{chunk-N5PM7HGQ.js → chunk-W6N6GQME.js} +1 -1
- package/dist/{chunk-FKOIHGKV.js → chunk-WHU7YGWP.js} +1 -1
- package/dist/{chunk-VZJVKQHH.js → chunk-WLV7TRMR.js} +1 -1
- package/dist/chunk-Y4NAPW5I.js +60 -0
- package/dist/{chunk-B3SJXYIJ.js → chunk-Y7YBWWIG.js} +1 -1
- package/dist/{chunk-Q5DHVMXB.js → chunk-YGGBJY5A.js} +18 -7
- package/dist/{chunk-JTPDWTWJ.js → chunk-Z2PVJKMN.js} +137 -114
- package/dist/{chunk-YP3CSOZ6.js → chunk-ZGFYFVJF.js} +142 -114
- package/dist/{connected-teams-IJUJQ7R6.js → connected-teams-I2WZZZFA.js} +2 -2
- package/dist/{connected-teams-4A2AXDNN.js → connected-teams-XO766HB4.js} +2 -2
- package/dist/{coordinator-prompt-ZWBMAIWA.js → coordinator-prompt-NYR5TPBD.js} +6 -5
- package/dist/{coordinator-prompt-5GXGBGEZ.js → coordinator-prompt-UCQJTFA7.js} +6 -5
- package/dist/{global-workspace-2SIPM4PW.js → global-workspace-4QHDAD2D.js} +7 -6
- package/dist/{global-workspace-OJRXWXEA.js → global-workspace-4SENNWBU.js} +7 -6
- package/dist/index.cjs +998 -574
- package/dist/index.d.cts +91 -10
- package/dist/index.d.ts +91 -10
- package/dist/index.js +268 -93
- package/dist/mcp/run-stdio.cjs +976 -579
- package/dist/mcp/run-stdio.js +196 -43
- package/dist/{orchestrator-6TXQWBXN.js → orchestrator-GZE4X3XV.js} +14 -11
- package/dist/{orchestrator-Z2O5OVJA.js → orchestrator-QSBRWME5.js} +16 -13
- package/dist/{plan-file-6O7G4VPQ.js → plan-file-5S5TUNAW.js} +2 -2
- package/dist/{plan-file-PHVKUAEE.js → plan-file-IBSU2PVW.js} +2 -2
- package/dist/{run-XQKGHQZ2.js → run-CAGKZLHA.js} +1 -1
- package/dist/{run-USF6FRKV.js → run-EBWL2Q4N.js} +1 -1
- package/dist/{workspaces-UUJNOO4T.js → workspaces-7S7QKCUE.js} +8 -7
- package/dist/{workspaces-3NUUZTQK.js → workspaces-RDUSB6FD.js} +8 -7
- package/dist/{worktree-RZRJNHYL.js → worktree-63AGPPLO.js} +5 -4
- package/dist/{worktree-UCWWTVLS.js → worktree-JIZ3QMZX.js} +5 -4
- package/dist/worktree-exclude-6MQWGWV5.js +11 -0
- package/dist/worktree-exclude-TV6EV6BS.js +9 -0
- package/package.json +1 -1
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
formatTurnExitError,
|
|
13
13
|
getAdapter,
|
|
14
14
|
isBrightsyNdjsonLine,
|
|
15
|
+
isInternalAgentStatusText,
|
|
15
16
|
isPollWrapperToolName,
|
|
16
17
|
isSessionQuotaLimit,
|
|
17
18
|
liveActivitySummary,
|
|
@@ -32,21 +33,13 @@ import {
|
|
|
32
33
|
summarizeTurnStderr,
|
|
33
34
|
toolDescription,
|
|
34
35
|
turnFailChatText
|
|
35
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-YGGBJY5A.js";
|
|
36
37
|
import {
|
|
37
38
|
addWorkspace,
|
|
38
39
|
ensureWorkspace,
|
|
39
40
|
removeWorkspace,
|
|
40
41
|
syncWorkspacesFromThreads
|
|
41
|
-
} from "./chunk-
|
|
42
|
-
import {
|
|
43
|
-
extractPresentedPlan,
|
|
44
|
-
readPlanFile,
|
|
45
|
-
writePlanFile
|
|
46
|
-
} from "./chunk-N5PM7HGQ.js";
|
|
47
|
-
import {
|
|
48
|
-
releaseCaffeinateHoldForThread
|
|
49
|
-
} from "./chunk-KLBOWJ74.js";
|
|
42
|
+
} from "./chunk-QGJHIJHV.js";
|
|
50
43
|
import {
|
|
51
44
|
assertOrchestratorCapableAgent,
|
|
52
45
|
attachmentsFromWorktreePaths,
|
|
@@ -63,14 +56,22 @@ import {
|
|
|
63
56
|
persistPendingFileAttachments,
|
|
64
57
|
stageAbsolutePathsAsAttachments,
|
|
65
58
|
stageBuffersAsAttachments
|
|
66
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-VO4SPEBS.js";
|
|
60
|
+
import {
|
|
61
|
+
extractPresentedPlan,
|
|
62
|
+
readPlanFile,
|
|
63
|
+
writePlanFile
|
|
64
|
+
} from "./chunk-W6N6GQME.js";
|
|
65
|
+
import {
|
|
66
|
+
releaseCaffeinateHoldForThread
|
|
67
|
+
} from "./chunk-KLBOWJ74.js";
|
|
67
68
|
import {
|
|
68
69
|
SLACK_REPLY_FORMATTING,
|
|
69
70
|
coordinatorSystemPrompt,
|
|
70
71
|
coordinatorTurnReminder,
|
|
71
72
|
enrichWorkspacesWithGithub,
|
|
72
73
|
ensureGlobalCoordinatorCwd
|
|
73
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-DMRIZR6M.js";
|
|
74
75
|
import {
|
|
75
76
|
addPrStackLayer,
|
|
76
77
|
allocateTeamName,
|
|
@@ -118,11 +119,11 @@ import {
|
|
|
118
119
|
withRepoGitLock,
|
|
119
120
|
worktreeDisplayLabelForGroup,
|
|
120
121
|
worktreeNameFromPath
|
|
121
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-Z2PVJKMN.js";
|
|
122
123
|
import {
|
|
123
124
|
ATTACHMENTS_DIR,
|
|
124
125
|
LEGACY_ATTACHMENTS_DIR
|
|
125
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-Y7YBWWIG.js";
|
|
126
127
|
import {
|
|
127
128
|
appendMessage,
|
|
128
129
|
createEmptyThread,
|
|
@@ -135,6 +136,9 @@ import {
|
|
|
135
136
|
withThreadLock,
|
|
136
137
|
writeThread
|
|
137
138
|
} from "./chunk-EUXOHTUK.js";
|
|
139
|
+
import {
|
|
140
|
+
ensureWorktreeSideboardIgnored
|
|
141
|
+
} from "./chunk-VSFGPWCQ.js";
|
|
138
142
|
import {
|
|
139
143
|
clearStaleIndexLocks,
|
|
140
144
|
enrichPathWithNpmGlobalBin,
|
|
@@ -142,7 +146,7 @@ import {
|
|
|
142
146
|
git,
|
|
143
147
|
resolveGitDirsForLockRecovery,
|
|
144
148
|
run
|
|
145
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-FNQNJOHY.js";
|
|
146
150
|
import {
|
|
147
151
|
childEnvWithAppSettings,
|
|
148
152
|
getIssueSource,
|
|
@@ -158,7 +162,7 @@ import {
|
|
|
158
162
|
stripNestedElectronEnv,
|
|
159
163
|
updateAdvancedSettings,
|
|
160
164
|
writeSecureJson
|
|
161
|
-
} from "./chunk-
|
|
165
|
+
} from "./chunk-CZD4NRDZ.js";
|
|
162
166
|
import {
|
|
163
167
|
writePrivateFile
|
|
164
168
|
} from "./chunk-NSTQ6QKD.js";
|
|
@@ -391,7 +395,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
391
395
|
await continueOnReply(threadId, prompt);
|
|
392
396
|
return;
|
|
393
397
|
}
|
|
394
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
398
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-GZE4X3XV.js");
|
|
395
399
|
await getOrchestrator2().send(threadId, prompt);
|
|
396
400
|
} catch {
|
|
397
401
|
}
|
|
@@ -732,9 +736,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
732
736
|
`Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
|
|
733
737
|
);
|
|
734
738
|
}
|
|
735
|
-
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-
|
|
739
|
+
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-4QHDAD2D.js");
|
|
736
740
|
if (isGlobalThread2(thread)) {
|
|
737
|
-
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-
|
|
741
|
+
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-UCQJTFA7.js");
|
|
738
742
|
ensureGlobalCoordinatorCwd2(
|
|
739
743
|
isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
|
|
740
744
|
);
|
|
@@ -1966,6 +1970,7 @@ async function runConventionSetup(repoPath, worktreePath, onLine, opts) {
|
|
|
1966
1970
|
};
|
|
1967
1971
|
}
|
|
1968
1972
|
async function runWorkspaceSetup(repoPath, worktreePath, onLine, opts) {
|
|
1973
|
+
await ensureWorktreeSideboardIgnored(worktreePath);
|
|
1969
1974
|
const reviewSkill = ensureReviewSkillFile(worktreePath);
|
|
1970
1975
|
if (reviewSkill.wrote) {
|
|
1971
1976
|
onLine?.(
|
|
@@ -2874,7 +2879,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2874
2879
|
});
|
|
2875
2880
|
await requireAgent(resolved.agent);
|
|
2876
2881
|
if (input.cowboy) {
|
|
2877
|
-
const { cowboyModeEnabled } = await import("./app-settings-
|
|
2882
|
+
const { cowboyModeEnabled } = await import("./app-settings-J3JBCUOT.js");
|
|
2878
2883
|
if (!cowboyModeEnabled()) {
|
|
2879
2884
|
throw new Error(
|
|
2880
2885
|
"Cowboy mode is off. Enable it in Settings \u2192 Advanced."
|
|
@@ -2932,7 +2937,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2932
2937
|
let sourceIsFork = false;
|
|
2933
2938
|
if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
|
|
2934
2939
|
if (isAbleTimeConnected() && getIssueSource() === "abletime") {
|
|
2935
|
-
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-
|
|
2940
|
+
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-CLC5UJC2.js");
|
|
2936
2941
|
const task = await ensureAbleTimeTask({
|
|
2937
2942
|
title: title?.trim() || "Untitled work",
|
|
2938
2943
|
description: input.prompt?.trim() || void 0
|
|
@@ -3005,7 +3010,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3005
3010
|
return readThread(thread.id) ?? thread;
|
|
3006
3011
|
}
|
|
3007
3012
|
async function listLinearIssues(agent, repoPath) {
|
|
3008
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
3013
|
+
const { getAdapter: getAdapter2 } = await import("./agents-YWBQXOA2.js");
|
|
3009
3014
|
await requireAgent(agent, { requireLinear: true });
|
|
3010
3015
|
const adapter = getAdapter2(agent);
|
|
3011
3016
|
if (!adapter.listLinearIssues) {
|
|
@@ -3397,7 +3402,7 @@ async function adoptThread(input) {
|
|
|
3397
3402
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
3398
3403
|
}
|
|
3399
3404
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
3400
|
-
const { stdout: branch } = await import("./run-
|
|
3405
|
+
const { stdout: branch } = await import("./run-EBWL2Q4N.js").then(
|
|
3401
3406
|
({ git: git2 }) => git2(["rev-parse", "--abbrev-ref", "HEAD"], input.worktreePath)
|
|
3402
3407
|
);
|
|
3403
3408
|
const thread = createEmptyThread({
|
|
@@ -3412,8 +3417,10 @@ async function adoptThread(input) {
|
|
|
3412
3417
|
messages: input.messages ?? []
|
|
3413
3418
|
});
|
|
3414
3419
|
writeThread(thread);
|
|
3415
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
3420
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-7S7QKCUE.js");
|
|
3416
3421
|
await ensureWorkspace2(repoPath);
|
|
3422
|
+
const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-6MQWGWV5.js");
|
|
3423
|
+
await ensureWorktreeSideboardIgnored2(input.worktreePath);
|
|
3417
3424
|
return thread;
|
|
3418
3425
|
}
|
|
3419
3426
|
function listConductorWorkspaces() {
|
|
@@ -4709,7 +4716,7 @@ async function confirmLand(thread, opts) {
|
|
|
4709
4716
|
if (preview.dirty) {
|
|
4710
4717
|
committed = await commitAll(thread.worktreePath, meta.commitMessage);
|
|
4711
4718
|
}
|
|
4712
|
-
const { git: git2 } = await import("./run-
|
|
4719
|
+
const { git: git2 } = await import("./run-EBWL2Q4N.js");
|
|
4713
4720
|
const { stdout: headOut } = await git2(
|
|
4714
4721
|
["rev-parse", "--abbrev-ref", "HEAD"],
|
|
4715
4722
|
thread.worktreePath,
|
|
@@ -5162,11 +5169,11 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
5162
5169
|
);
|
|
5163
5170
|
} else if (opts?.githubSlug) {
|
|
5164
5171
|
lines.push(
|
|
5165
|
-
`- 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
|
|
5172
|
+
`- 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\`.`
|
|
5166
5173
|
);
|
|
5167
5174
|
} else {
|
|
5168
5175
|
lines.push(
|
|
5169
|
-
"- Prefer a draft PR first: `gh pr create --draft -R <origin-owner/name>` (or update via `gh pr edit -R \u2026`) once the change set is coherent. Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree \u2014 never from `upstream`. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name."
|
|
5176
|
+
"- Prefer a draft PR first: `gh pr create --draft -R <origin-owner/name>` (or update via `gh pr edit -R \u2026`) once the change set is coherent. Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree \u2014 never from `upstream`. 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`."
|
|
5170
5177
|
);
|
|
5171
5178
|
}
|
|
5172
5179
|
lines.push("");
|
|
@@ -5611,7 +5618,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
5611
5618
|
${prompt}`;
|
|
5612
5619
|
}
|
|
5613
5620
|
async function defaultDeps() {
|
|
5614
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
5621
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-GZE4X3XV.js");
|
|
5615
5622
|
const orch = getOrchestrator2();
|
|
5616
5623
|
return {
|
|
5617
5624
|
findThread: (id) => findThreadByRef(id),
|
|
@@ -5715,6 +5722,7 @@ function armSchedules() {
|
|
|
5715
5722
|
}
|
|
5716
5723
|
|
|
5717
5724
|
// src/orchestrator/orchestrator.ts
|
|
5725
|
+
var LIVE_TURN_SPAWN_GRACE_MS = 15e3;
|
|
5718
5726
|
function isPidAlive(pid) {
|
|
5719
5727
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
5720
5728
|
try {
|
|
@@ -5793,6 +5801,39 @@ var Orchestrator = class {
|
|
|
5793
5801
|
if (typeof pid === "number" && pid > 0 && isPidAlive(pid)) return false;
|
|
5794
5802
|
return true;
|
|
5795
5803
|
}
|
|
5804
|
+
/**
|
|
5805
|
+
* Whether a child is actually turning — not leftover disk `running` after
|
|
5806
|
+
* the process died. Coordinators were telling users “Agent is running.
|
|
5807
|
+
* Waiting for gate to pass” from stale stillRunning.
|
|
5808
|
+
*/
|
|
5809
|
+
threadLooksLive(thread) {
|
|
5810
|
+
if (thread.status === "queued") {
|
|
5811
|
+
if (this.draining.has(thread.id) || this.startingTurns.has(thread.id)) return true;
|
|
5812
|
+
return thread.queue.length > 0;
|
|
5813
|
+
}
|
|
5814
|
+
if (thread.status !== "running") return false;
|
|
5815
|
+
if (this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id)) return true;
|
|
5816
|
+
const pid = thread.agentPid;
|
|
5817
|
+
if (typeof pid === "number" && pid > 0 && isPidAlive(pid)) return true;
|
|
5818
|
+
const updated = Date.parse(thread.updatedAt ?? "");
|
|
5819
|
+
if (Number.isFinite(updated) && Date.now() - updated < LIVE_TURN_SPAWN_GRACE_MS) return true;
|
|
5820
|
+
return false;
|
|
5821
|
+
}
|
|
5822
|
+
/** Desktop-only: persist idle/stopped when MCP would otherwise keep reporting live. */
|
|
5823
|
+
healStaleReportedActivity(thread) {
|
|
5824
|
+
if (!thisProcessShouldDrainAgentQueues()) return thread;
|
|
5825
|
+
if (this.threadLooksLive(thread)) return thread;
|
|
5826
|
+
if (thread.status === "running") {
|
|
5827
|
+
this.healStaleRunningTurns();
|
|
5828
|
+
return readThread(thread.id) ?? thread;
|
|
5829
|
+
}
|
|
5830
|
+
if (thread.status === "queued" && thread.queue.length === 0 && !this.activeTurns.has(thread.id) && !this.startingTurns.has(thread.id) && !this.draining.has(thread.id)) {
|
|
5831
|
+
setStatus(thread.id, "idle");
|
|
5832
|
+
this.emit({ type: "status_changed", threadId: thread.id, status: "idle" });
|
|
5833
|
+
return readThread(thread.id) ?? thread;
|
|
5834
|
+
}
|
|
5835
|
+
return thread;
|
|
5836
|
+
}
|
|
5796
5837
|
async reconcile(repoPath, opts) {
|
|
5797
5838
|
const reclaimStaleTurns = opts?.reclaimStaleTurns === true;
|
|
5798
5839
|
const drainQueues = opts?.drainQueues !== false;
|
|
@@ -5836,7 +5877,7 @@ var Orchestrator = class {
|
|
|
5836
5877
|
orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
|
|
5837
5878
|
});
|
|
5838
5879
|
}
|
|
5839
|
-
const { autoCleanupOrphansEnabled } = await import("./app-settings-
|
|
5880
|
+
const { autoCleanupOrphansEnabled } = await import("./app-settings-J3JBCUOT.js");
|
|
5840
5881
|
if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
|
|
5841
5882
|
await cleanupOrphanWorktrees({ repoPaths });
|
|
5842
5883
|
}
|
|
@@ -6076,7 +6117,7 @@ var Orchestrator = class {
|
|
|
6076
6117
|
}
|
|
6077
6118
|
await setup;
|
|
6078
6119
|
if (skipSetup) return;
|
|
6079
|
-
const { autoRunAfterSetupEnabled } = await import("./app-settings-
|
|
6120
|
+
const { autoRunAfterSetupEnabled } = await import("./app-settings-J3JBCUOT.js");
|
|
6080
6121
|
if (autoRunAfterSetupEnabled()) {
|
|
6081
6122
|
try {
|
|
6082
6123
|
await this.startDev(threadId);
|
|
@@ -6127,12 +6168,14 @@ var Orchestrator = class {
|
|
|
6127
6168
|
this.emit({ type: "status_changed", threadId: thread.id, status: thread.status });
|
|
6128
6169
|
return thread;
|
|
6129
6170
|
}
|
|
6130
|
-
async send(threadRef, prompt) {
|
|
6171
|
+
async send(threadRef, prompt, opts) {
|
|
6131
6172
|
const thread = this.requireThread(threadRef);
|
|
6132
6173
|
if (thread.status === "archived") {
|
|
6133
6174
|
throw new Error(`Thread is archived: ${thread.id}`);
|
|
6134
6175
|
}
|
|
6135
|
-
|
|
6176
|
+
const followUp = opts?.followUp === "steer" ? "steer" : "queue";
|
|
6177
|
+
let shouldSteer = false;
|
|
6178
|
+
const sent = await withThreadLock(thread.id, async () => {
|
|
6136
6179
|
const current = this.requireThread(thread.id);
|
|
6137
6180
|
if (current.status === "archived") {
|
|
6138
6181
|
throw new Error(`Thread is archived: ${thread.id}`);
|
|
@@ -6141,6 +6184,7 @@ var Orchestrator = class {
|
|
|
6141
6184
|
this.crashContinued.delete(thread.id);
|
|
6142
6185
|
this.haltDrain.delete(thread.id);
|
|
6143
6186
|
const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id) || current.status === "running";
|
|
6187
|
+
shouldSteer = followUp === "steer" && (inFlight || current.queue.length > 0);
|
|
6144
6188
|
const patch = { queue };
|
|
6145
6189
|
if (!inFlight) patch.status = "queued";
|
|
6146
6190
|
const pid = current.agentPid;
|
|
@@ -6152,16 +6196,20 @@ var Orchestrator = class {
|
|
|
6152
6196
|
if (!inFlight) {
|
|
6153
6197
|
this.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
|
|
6154
6198
|
}
|
|
6155
|
-
if (thisProcessShouldDrainAgentQueues()) {
|
|
6199
|
+
if (thisProcessShouldDrainAgentQueues() && !shouldSteer) {
|
|
6156
6200
|
void this.drainQueue(thread.id);
|
|
6157
6201
|
}
|
|
6158
6202
|
return this.requireThread(thread.id);
|
|
6159
6203
|
});
|
|
6204
|
+
if (shouldSteer && sent.queue.length > 0) {
|
|
6205
|
+
return this.sendQueuedMessageNow(sent.id, sent.queue.length - 1);
|
|
6206
|
+
}
|
|
6207
|
+
return sent;
|
|
6160
6208
|
}
|
|
6161
|
-
async fanOut(threadRefs, prompt) {
|
|
6209
|
+
async fanOut(threadRefs, prompt, opts) {
|
|
6162
6210
|
const results = [];
|
|
6163
6211
|
for (const ref of threadRefs) {
|
|
6164
|
-
results.push(await this.send(ref, prompt));
|
|
6212
|
+
results.push(await this.send(ref, prompt, opts));
|
|
6165
6213
|
}
|
|
6166
6214
|
return results;
|
|
6167
6215
|
}
|
|
@@ -6377,7 +6425,7 @@ var Orchestrator = class {
|
|
|
6377
6425
|
}
|
|
6378
6426
|
const isBrightsy = fresh.agent === "brightsy";
|
|
6379
6427
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
6380
|
-
const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-
|
|
6428
|
+
const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-J3JBCUOT.js");
|
|
6381
6429
|
const gitAuthMode = getGithubGitAuthMode();
|
|
6382
6430
|
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
6383
6431
|
githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
|
|
@@ -6965,8 +7013,8 @@ var Orchestrator = class {
|
|
|
6965
7013
|
return created;
|
|
6966
7014
|
}
|
|
6967
7015
|
async waitForTurn(threadRef, timeoutMs = 6e5, opts) {
|
|
6968
|
-
const thread = this.requireThread(threadRef);
|
|
6969
|
-
if (!
|
|
7016
|
+
const thread = this.healStaleReportedActivity(this.requireThread(threadRef));
|
|
7017
|
+
if (!this.threadLooksLive(thread)) {
|
|
6970
7018
|
return thread;
|
|
6971
7019
|
}
|
|
6972
7020
|
const start = Date.now();
|
|
@@ -7003,12 +7051,13 @@ var Orchestrator = class {
|
|
|
7003
7051
|
}
|
|
7004
7052
|
});
|
|
7005
7053
|
timer = setInterval(() => {
|
|
7006
|
-
const
|
|
7007
|
-
if (!
|
|
7054
|
+
const raw = readThread(thread.id);
|
|
7055
|
+
if (!raw) {
|
|
7008
7056
|
finish(() => reject(new Error(`Thread not found: ${thread.id}`)));
|
|
7009
7057
|
return;
|
|
7010
7058
|
}
|
|
7011
|
-
|
|
7059
|
+
const current = this.healStaleReportedActivity(raw);
|
|
7060
|
+
if (!this.threadLooksLive(current)) {
|
|
7012
7061
|
finish(() => resolve(current));
|
|
7013
7062
|
return;
|
|
7014
7063
|
}
|
|
@@ -7031,20 +7080,22 @@ var Orchestrator = class {
|
|
|
7031
7080
|
};
|
|
7032
7081
|
}
|
|
7033
7082
|
getTurnResult(threadRef) {
|
|
7034
|
-
const thread = this.requireThread(threadRef);
|
|
7083
|
+
const thread = this.healStaleReportedActivity(this.requireThread(threadRef));
|
|
7035
7084
|
const lastAgent = [...thread.messages].reverse().find((m) => m.role === "agent");
|
|
7036
7085
|
const lastError = thread.lastError ?? null;
|
|
7037
|
-
const
|
|
7038
|
-
const
|
|
7086
|
+
const rawText = (lastAgent?.text ?? "").trim();
|
|
7087
|
+
const text = (rawText && !isInternalAgentStatusText(rawText) ? rawText : "") || (thread.status === "error" || thread.status === "stopped" || thread.status === "broken" ? lastError ?? "" : "");
|
|
7088
|
+
const stillRunning = this.threadLooksLive(thread);
|
|
7039
7089
|
const live = stillRunning ? readTurnLive(thread.id) : null;
|
|
7040
|
-
const
|
|
7090
|
+
const liveSummary = live?.summary && !isInternalAgentStatusText(live.summary) ? live.summary : null;
|
|
7091
|
+
const queuedHint = stillRunning && thread.status === "queued" && !liveSummary ? "Queued \u2014 waiting for a concurrency slot" : null;
|
|
7041
7092
|
return {
|
|
7042
7093
|
text,
|
|
7043
7094
|
status: thread.status,
|
|
7044
7095
|
sessionId: thread.sessionId,
|
|
7045
7096
|
lastError,
|
|
7046
7097
|
stillRunning,
|
|
7047
|
-
progress:
|
|
7098
|
+
progress: liveSummary ?? queuedHint,
|
|
7048
7099
|
lastActivityAt: live?.updatedAt ?? null,
|
|
7049
7100
|
usage: lastAgent?.usage ?? null
|
|
7050
7101
|
};
|
|
@@ -7237,7 +7288,7 @@ var Orchestrator = class {
|
|
|
7237
7288
|
updateThread(thread.id, { title: meta.title });
|
|
7238
7289
|
}
|
|
7239
7290
|
}
|
|
7240
|
-
const { autoArchiveOnMergeEnabled } = await import("./app-settings-
|
|
7291
|
+
const { autoArchiveOnMergeEnabled } = await import("./app-settings-J3JBCUOT.js");
|
|
7241
7292
|
const latest = this.requireThread(thread.id);
|
|
7242
7293
|
if (!shouldAutoArchiveOnPrMerge({
|
|
7243
7294
|
previousPrState: prevState || null,
|
|
@@ -7392,7 +7443,14 @@ var Orchestrator = class {
|
|
|
7392
7443
|
);
|
|
7393
7444
|
}
|
|
7394
7445
|
if ((action === "commit-push" || action === "create-draft" || action === "create-web") && thread.worktreePath?.trim() && !await isDirty(thread.worktreePath)) {
|
|
7395
|
-
|
|
7446
|
+
try {
|
|
7447
|
+
await this.pushAndMaybeOpenPr(thread, action);
|
|
7448
|
+
} catch (err) {
|
|
7449
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
7450
|
+
updateThread(thread.id, { lastError: message });
|
|
7451
|
+
this.emit({ type: "error", threadId: thread.id, message });
|
|
7452
|
+
throw err;
|
|
7453
|
+
}
|
|
7396
7454
|
return this.requireThread(threadRef);
|
|
7397
7455
|
}
|
|
7398
7456
|
let prBase;
|
|
@@ -7547,7 +7605,7 @@ var Orchestrator = class {
|
|
|
7547
7605
|
this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
|
|
7548
7606
|
if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
|
|
7549
7607
|
try {
|
|
7550
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
7608
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-7S7QKCUE.js");
|
|
7551
7609
|
await ensureWorkspace2(thread.repoPath);
|
|
7552
7610
|
} catch {
|
|
7553
7611
|
}
|
|
@@ -7574,7 +7632,7 @@ var Orchestrator = class {
|
|
|
7574
7632
|
await runArchiveScript(thread.repoPath, thread.worktreePath);
|
|
7575
7633
|
} catch {
|
|
7576
7634
|
}
|
|
7577
|
-
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-
|
|
7635
|
+
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-J3JBCUOT.js");
|
|
7578
7636
|
const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
|
|
7579
7637
|
await removeWorktree(thread.repoPath, thread.worktreePath, {
|
|
7580
7638
|
deleteBranch: deleteBranch ? thread.branchName : void 0
|
|
@@ -7601,12 +7659,14 @@ var Orchestrator = class {
|
|
|
7601
7659
|
`Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
|
|
7602
7660
|
);
|
|
7603
7661
|
}
|
|
7604
|
-
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-
|
|
7662
|
+
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-JIZ3QMZX.js");
|
|
7605
7663
|
const slug = thread.worktreePath.split("/").pop();
|
|
7606
7664
|
const dest = thread.worktreePath;
|
|
7607
7665
|
await withRepoGitLock(thread.repoPath, async () => {
|
|
7608
7666
|
await git(["worktree", "add", dest, thread.branchName], thread.repoPath);
|
|
7609
7667
|
});
|
|
7668
|
+
const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-6MQWGWV5.js");
|
|
7669
|
+
await ensureWorktreeSideboardIgnored2(dest);
|
|
7610
7670
|
void createThreadWorktree2;
|
|
7611
7671
|
void slug;
|
|
7612
7672
|
}
|
|
@@ -7709,7 +7769,7 @@ async function startOrchestration(opts) {
|
|
|
7709
7769
|
sourceRef: "default",
|
|
7710
7770
|
...createOpts
|
|
7711
7771
|
}).catch(async () => {
|
|
7712
|
-
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-
|
|
7772
|
+
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-JIZ3QMZX.js");
|
|
7713
7773
|
const repo = await resolveRepoRoot2(repoPath);
|
|
7714
7774
|
const def = await resolveDefaultBranch2(repo);
|
|
7715
7775
|
return orch.createThread({
|
|
@@ -7761,6 +7821,7 @@ export {
|
|
|
7761
7821
|
updateSchedule,
|
|
7762
7822
|
deleteSchedule,
|
|
7763
7823
|
fireSchedule,
|
|
7824
|
+
LIVE_TURN_SPAWN_GRACE_MS,
|
|
7764
7825
|
isPidAlive,
|
|
7765
7826
|
waitForPidExit,
|
|
7766
7827
|
Orchestrator,
|
|
@@ -99,17 +99,93 @@ function withExportedPath(command, pathValue) {
|
|
|
99
99
|
return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
// src/git/github-agent-auth.ts
|
|
103
|
+
import { chmodSync, existsSync as existsSync2, mkdirSync, writeFileSync } from "fs";
|
|
104
|
+
import { homedir as homedir2 } from "os";
|
|
105
|
+
import { dirname, join as join2 } from "path";
|
|
106
|
+
function githubAgentAuthDir() {
|
|
107
|
+
const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
|
|
108
|
+
if (override) return override;
|
|
109
|
+
return join2(homedir2(), ".sideboard-git-auth");
|
|
110
|
+
}
|
|
111
|
+
function githubCredentialStorePath() {
|
|
112
|
+
return join2(githubAgentAuthDir(), "git-credentials");
|
|
113
|
+
}
|
|
114
|
+
function githubGhConfigDir() {
|
|
115
|
+
return join2(githubAgentAuthDir(), "gh");
|
|
116
|
+
}
|
|
117
|
+
function writePrivateFile(file, body) {
|
|
118
|
+
mkdirSync(dirname(file), { recursive: true, mode: 448 });
|
|
119
|
+
try {
|
|
120
|
+
chmodSync(dirname(file), 448);
|
|
121
|
+
} catch {
|
|
122
|
+
}
|
|
123
|
+
writeFileSync(file, body, { encoding: "utf8", mode: 384 });
|
|
124
|
+
try {
|
|
125
|
+
chmodSync(file, 384);
|
|
126
|
+
} catch {
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function gitCredentialStoreContents(token) {
|
|
130
|
+
return `https://x-access-token:${encodeURIComponent(token)}@github.com
|
|
131
|
+
`;
|
|
132
|
+
}
|
|
133
|
+
function ghHostsYml(token, user = "x-access-token") {
|
|
134
|
+
const u = user.replace(/[^A-Za-z0-9._-]/g, "") || "x-access-token";
|
|
135
|
+
return [
|
|
136
|
+
"github.com:",
|
|
137
|
+
" git_protocol: https",
|
|
138
|
+
` user: ${u}`,
|
|
139
|
+
` oauth_token: ${token}`,
|
|
140
|
+
" users:",
|
|
141
|
+
` ${u}:`,
|
|
142
|
+
` oauth_token: ${token}`,
|
|
143
|
+
""
|
|
144
|
+
].join("\n");
|
|
145
|
+
}
|
|
146
|
+
function materializeGithubAgentAuth(token, user) {
|
|
147
|
+
const trimmed = token.trim();
|
|
148
|
+
if (!trimmed) return;
|
|
149
|
+
const root = githubAgentAuthDir();
|
|
150
|
+
mkdirSync(root, { recursive: true, mode: 448 });
|
|
151
|
+
try {
|
|
152
|
+
chmodSync(root, 448);
|
|
153
|
+
} catch {
|
|
154
|
+
}
|
|
155
|
+
writePrivateFile(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
|
|
156
|
+
const ghDir = githubGhConfigDir();
|
|
157
|
+
mkdirSync(ghDir, { recursive: true, mode: 448 });
|
|
158
|
+
writePrivateFile(join2(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
|
|
159
|
+
writePrivateFile(join2(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
|
|
160
|
+
}
|
|
161
|
+
function githubAgentAuthReady() {
|
|
162
|
+
return existsSync2(githubCredentialStorePath()) && existsSync2(join2(githubGhConfigDir(), "hosts.yml"));
|
|
163
|
+
}
|
|
164
|
+
function githubCredentialHelperGitConfig() {
|
|
165
|
+
const file = githubCredentialStorePath();
|
|
166
|
+
return [
|
|
167
|
+
{ key: "credential.helper", value: "" },
|
|
168
|
+
{ key: "credential.helper", value: `store --file=${file}` }
|
|
169
|
+
];
|
|
170
|
+
}
|
|
171
|
+
function githubGhConfigEnv() {
|
|
172
|
+
return {
|
|
173
|
+
GH_CONFIG_DIR: githubGhConfigDir(),
|
|
174
|
+
GH_PROMPT_DISABLED: "1"
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
102
178
|
// src/git/stale-lock.ts
|
|
103
|
-
import { existsSync as
|
|
104
|
-
import { join as
|
|
179
|
+
import { existsSync as existsSync3, statSync, unlinkSync } from "fs";
|
|
180
|
+
import { join as join3 } from "path";
|
|
105
181
|
var STALE_INDEX_LOCK_MS = 2e4;
|
|
106
182
|
function isIndexLockError(text) {
|
|
107
183
|
return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text);
|
|
108
184
|
}
|
|
109
185
|
function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
|
|
110
|
-
const lockPath =
|
|
186
|
+
const lockPath = join3(gitDir, "index.lock");
|
|
111
187
|
try {
|
|
112
|
-
if (!
|
|
188
|
+
if (!existsSync3(lockPath)) return null;
|
|
113
189
|
if (now - statSync(lockPath).mtimeMs < maxAgeMs) return null;
|
|
114
190
|
unlinkSync(lockPath);
|
|
115
191
|
return lockPath;
|
|
@@ -211,7 +287,10 @@ async function gh(args, cwd, opts) {
|
|
|
211
287
|
timeoutMs: opts?.timeoutMs,
|
|
212
288
|
env: {
|
|
213
289
|
GH_PROMPT_DISABLED: "1",
|
|
214
|
-
GIT_TERMINAL_PROMPT: "0"
|
|
290
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
291
|
+
// Isolated hosts.yml uses git_protocol: https so `gh pr create` does not
|
|
292
|
+
// shell out over SSH when Settings → Git is SSH (ask_git in Electron).
|
|
293
|
+
...githubAgentAuthReady() ? githubGhConfigEnv() : {}
|
|
215
294
|
}
|
|
216
295
|
});
|
|
217
296
|
}
|
|
@@ -230,6 +309,11 @@ export {
|
|
|
230
309
|
posixShellSingleQuote,
|
|
231
310
|
resolveCommandBinarySync,
|
|
232
311
|
withExportedPath,
|
|
312
|
+
githubAgentAuthDir,
|
|
313
|
+
materializeGithubAgentAuth,
|
|
314
|
+
githubAgentAuthReady,
|
|
315
|
+
githubCredentialHelperGitConfig,
|
|
316
|
+
githubGhConfigEnv,
|
|
233
317
|
clearStaleIndexLocks,
|
|
234
318
|
run,
|
|
235
319
|
resolveGitDirsForLockRecovery,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isGlobalRepoPath
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AF6O55PJ.js";
|
|
4
4
|
import {
|
|
5
5
|
ensureGhPreferOrigin,
|
|
6
6
|
resolveRepoRoot
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZGFYFVJF.js";
|
|
8
8
|
import {
|
|
9
9
|
appDataDir
|
|
10
10
|
} from "./chunk-QZQEXME2.js";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveGithubRepoSlug
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZGFYFVJF.js";
|
|
4
4
|
import {
|
|
5
5
|
resolveThreadDefaults
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4XNSGDXE.js";
|
|
7
7
|
import {
|
|
8
8
|
globalAgentCwd,
|
|
9
9
|
sideboardReposDir
|
|
@@ -45,8 +45,8 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
45
45
|
"Discover:",
|
|
46
46
|
"- list_workspaces \u2014 registered repos (path + github slug when known)",
|
|
47
47
|
"- list_board \u2014 Home Kanban of worktrees (New / Draft / Review / Merged; one card per checkout). Path to merge: no PR \u2192 draft PR \u2192 open PR \u2192 merged. Archive removes the card to Settings \u2192 History. Queued/running are activity on the card, not columns. Orchestration chats are not on the board. Filters: query, repoPath, kind, column, limit.",
|
|
48
|
-
"- list_branches / list_prs / list_issues \u2014 pass repoPath from list_workspaces (issues: Linear, AbleTime MCP, or GitHub Issues)",
|
|
49
|
-
"- linear_list_teams / linear_get_issue / linear_create_issue / linear_update_issue / linear_comment \u2014 Linear Account connection; call linear_list_teams for team key and workflow states; pass ENG-123 or uuid. linear_get_issue returns comments, relations, parent/children, and the rest of the issue metadata. If mutations fail with a scope error, Disconnect and Connect Linear in Account settings.",
|
|
48
|
+
"- list_branches / list_prs / list_issues \u2014 pass repoPath from list_workspaces (issues: Linear, AbleTime MCP, or GitHub Issues). list_issues accepts query and assignee (me / unassigned / all / user id) so Linear is not limited to tickets assigned to you.",
|
|
49
|
+
"- linear_list_teams / linear_search_issues / linear_get_issue / linear_create_issue / linear_update_issue / linear_comment \u2014 Linear Account connection; call linear_list_teams for team key and workflow states; pass ENG-123 or uuid. linear_search_issues finds unassigned and other people's open issues (assignee=unassigned|all|me|user). linear_get_issue returns comments, relations, parent/children, and the rest of the issue metadata. If mutations fail with a scope error, Disconnect and Connect Linear in Account settings.",
|
|
50
50
|
"- abletime_orientation / abletime_list_projects / abletime_list_tasks / abletime_search_tasks / abletime_get_task / abletime_create_task / abletime_ensure_task \u2014 AbleTime Account personal access token (hosted MCP). Call orientation first. If work has no task yet, abletime_ensure_task creates one to track against (or create_thread from the default branch does that automatically when AbleTime is the preferred issue source).",
|
|
51
51
|
"- list_teams / slack_list_channels / slack_list_users / slack_search / slack_read / slack_post / slack_replies \u2014 Slack workspaces from Settings \u2192 Remote; pass team_id from list_teams",
|
|
52
52
|
"- Optional connectors (Vercel, Supabase, PostHog, Sentry) in Settings \u2192 Connectors inject tokens into worktree agent env when connected. Prefer official CLIs (`vercel`, `supabase`, `sentry-cli`) with those env vars. PostHog has no first-class CLI \u2014 use the HTTP API (`POSTHOG_PERSONAL_API_KEY`). If a CLI is missing, the user can Install CLI on that row (not auto-installed on Connect). Do not add vendor MCPs or ask the user to paste tokens again. Git (`gh`) stays Settings \u2192 Git; issue tracking stays Settings \u2192 Issues; Slack stays Settings \u2192 Remote (Sideboard MCP).",
|
|
@@ -65,7 +65,7 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
65
65
|
"- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
|
|
66
66
|
"- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
|
|
67
67
|
"- send_to_thread \u2014 queue a prompt (start/continue a chat turn). force_stop: true only to replace a wrong in-flight request \u2014 never to check in, resume after a halt notice, or because wait_for_turn returned stillRunning (that kills the child mid-thought)",
|
|
68
|
-
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
|
|
68
|
+
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. If stillRunning stays true across many waits with the same lastActivityAt, the child is stuck \u2014 tell the user; do not invent a gate. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
|
|
69
69
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
70
70
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
71
71
|
"Setup / run:",
|
|
@@ -74,7 +74,7 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
74
74
|
"Inspect / review / PRs:",
|
|
75
75
|
"- get_diff \u2014 compact diff summary",
|
|
76
76
|
'- request_review \u2014 open a Review chat tab on a worktree thread (attaches .claude/skills/review/SKILL.md when present, else seeds that skill / local guidelines; sends "Review changes in this workspace."); then wait_for_turn (loop while stillRunning) / get_turn_result on the returned id',
|
|
77
|
-
"- ask_git \u2014 commit & push, open a draft PR, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing.",
|
|
77
|
+
"- ask_git \u2014 commit & push, open a draft PR, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error.",
|
|
78
78
|
'- Merge (`ask_git` action=merge / send_to_thread "Merge PR.") only when the user explicitly asked to merge that PR. Do not merge because the work looks done, CI is green, or a typical flow includes it.',
|
|
79
79
|
'- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Merge the remote branch (main) into your branch and resolve conflicts. Then, commit and push your changes.", "Merge PR." (draft PRs: `gh pr create --draft -R <origin-owner/name>` using the workspace `github:` slug \u2014 never upstream). Never run git/gh from this orchestration cwd, and never merge the PR yourself.',
|
|
80
80
|
"Process guides:",
|