@sideboard-ai/core 0.1.191 → 0.1.192
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/{agents-5OBZETUV.js → agents-T5VBB6X3.js} +2 -2
- package/dist/{agents-DTPVTDB5.js → agents-TXGQIK2E.js} +2 -2
- package/dist/{chunk-XXEIF2IL.js → chunk-7NSXGL6L.js} +3 -3
- package/dist/{chunk-GPSIZGEZ.js → chunk-FZ3G5TXM.js} +19 -12
- package/dist/{chunk-5RRAKGPK.js → chunk-NF6ENGHS.js} +20 -13
- package/dist/{chunk-OLDZXO53.js → chunk-TWSCTJCR.js} +2 -2
- package/dist/{chunk-VIODP5PT.js → chunk-VV7UT3E2.js} +3 -3
- package/dist/{chunk-GBWKMWUQ.js → chunk-WHD4JNTN.js} +2 -2
- package/dist/{coordinator-prompt-LWKOL3AZ.js → coordinator-prompt-PNUDN4DW.js} +1 -1
- package/dist/{coordinator-prompt-MSC44OOM.js → coordinator-prompt-S4HHFSLI.js} +1 -1
- package/dist/{global-workspace-6G5JJH2E.js → global-workspace-2BVCJUAL.js} +1 -1
- package/dist/{global-workspace-XATJTV3N.js → global-workspace-JTBBH2K5.js} +1 -1
- package/dist/index.cjs +64 -17
- package/dist/index.d.cts +9 -4
- package/dist/index.d.ts +9 -4
- package/dist/index.js +53 -13
- package/dist/mcp/run-stdio.cjs +62 -17
- package/dist/mcp/run-stdio.js +52 -13
- package/dist/{orchestrator-2X6LYBQI.js → orchestrator-4G76BOHH.js} +5 -3
- package/dist/{orchestrator-F3CXDBZB.js → orchestrator-LWEZ74RK.js} +5 -3
- package/dist/{workspaces-LMFCRXTT.js → workspaces-OY7D5RPU.js} +1 -1
- package/dist/{workspaces-FWKPWSXV.js → workspaces-ZYPME3YD.js} +1 -1
- package/package.json +1 -1
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -7973,8 +7973,8 @@ var init_coordinator_prompt = __esm({
|
|
|
7973
7973
|
"- start_board_card \u2014 same as create_thread for a ticket/PR/named branch (attaches issue text when resolvable). Then send_to_thread.",
|
|
7974
7974
|
"- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
|
|
7975
7975
|
"- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
|
|
7976
|
-
"- send_to_thread \u2014
|
|
7977
|
-
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or
|
|
7976
|
+
"- send_to_thread \u2014 steer a prompt (start/continue a chat turn; Settings \u2192 Follow-up, default steer: interrupt and start now). force_stop: true only to replace a wrong in-flight request and clear the inbox \u2014 never to check in, resume after a halt notice, or because wait_for_turn returned stillRunning (that interrupts the child mid-thought)",
|
|
7977
|
+
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send_to_thread a check-in (that steers / interrupts). Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. If stillRunning stays true across many waits with the same lastActivityAt, the child is stuck \u2014 tell the user; do not invent a gate. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
|
|
7978
7978
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
7979
7979
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
7980
7980
|
"Setup / run:",
|
|
@@ -7984,7 +7984,7 @@ var init_coordinator_prompt = __esm({
|
|
|
7984
7984
|
"- get_diff \u2014 compact diff summary",
|
|
7985
7985
|
"- get_pr_checks \u2014 snapshot of a worktree thread's PR checks (null = no PR). Use this to inspect status. If the user gave a goal, the worktree agent watches with `gh pr checks --watch` \u2014 do not poll for the human.",
|
|
7986
7986
|
'- request_review \u2014 open a Review chat tab on a worktree thread (attaches .claude/skills/review/SKILL.md when present, else .context/review.md copied from .sideboard/review.md / stock; sends "Review changes in this workspace."); then wait_for_turn (loop while stillRunning) / get_turn_result on the returned id. The review stays in that chat so they can read it and type next steps \u2014 do not tell the child to comment or update the PR or ticket.',
|
|
7987
|
-
"- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it
|
|
7987
|
+
"- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it steers 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. If the user gave a goal (Greptile 5/5, CI green), send_to_thread that goal so the worktree agent enters the watch-fix-push loop \u2014 do not tell the human to poll.",
|
|
7988
7988
|
'- Merge (`ask_git` action=merge / send_to_thread "Merge PR.") only when the user explicitly asked to merge that PR. Do not merge because the work looks done, CI is green, or a typical flow includes it.',
|
|
7989
7989
|
'- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Ready for review.", "Merge the remote branch (main) into your branch and resolve conflicts. Then, commit and push your changes.", "Merge PR." (draft PRs: `gh pr create --draft -R <origin-owner/name>` using the workspace `github:` slug \u2014 never upstream). Never run git/gh from this orchestration cwd, and never merge the PR yourself.',
|
|
7990
7990
|
"Process guides:",
|
|
@@ -14303,8 +14303,8 @@ var init_wait_for_turn = __esm({
|
|
|
14303
14303
|
"src/mcp/wait-for-turn.ts"() {
|
|
14304
14304
|
"use strict";
|
|
14305
14305
|
MCP_WAIT_FOR_TURN_MAX_MS = 45e3;
|
|
14306
|
-
MCP_WAIT_STILL_RUNNING_HINT = "Child is still working. Call wait_for_turn again. Do not
|
|
14307
|
-
MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u2014 it has not started yet. Call wait_for_turn again. Do not
|
|
14306
|
+
MCP_WAIT_STILL_RUNNING_HINT = "Child is still working. Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts) or assume a hang while progress is updating.";
|
|
14307
|
+
MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u2014 it has not started yet. Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts), force_stop, or assume it failed to start.";
|
|
14308
14308
|
MCP_WAIT_STOPPED_HINT = "Child was stopped before the turn finished. Do not treat this as success. send_to_thread to resume, or tell the user.";
|
|
14309
14309
|
MCP_WAIT_BROKEN_HINT = "Child worktree is broken (missing on disk). Tell the user \u2014 do not treat this as success.";
|
|
14310
14310
|
MCP_WAIT_ERROR_HINT = "Child turn failed. lastError/text is the failure \u2014 switch agent, tell the user, or retry. Do not treat empty text as success.";
|
|
@@ -19459,6 +19459,7 @@ __export(orchestrator_exports, {
|
|
|
19459
19459
|
Orchestrator: () => Orchestrator,
|
|
19460
19460
|
getOrchestrator: () => getOrchestrator,
|
|
19461
19461
|
isPidAlive: () => isPidAlive,
|
|
19462
|
+
resolveOrchChildFollowUp: () => resolveOrchChildFollowUp,
|
|
19462
19463
|
resolveSendFollowUp: () => resolveSendFollowUp,
|
|
19463
19464
|
startOrchestration: () => startOrchestration,
|
|
19464
19465
|
waitForPidExit: () => waitForPidExit
|
|
@@ -19489,6 +19490,10 @@ function resolveSendFollowUp(thread, requested) {
|
|
|
19489
19490
|
if (requested === "steer" || requested === "queue") return requested;
|
|
19490
19491
|
return isOrchestratorThread(thread) ? followUpBehavior() : "queue";
|
|
19491
19492
|
}
|
|
19493
|
+
function resolveOrchChildFollowUp(requested) {
|
|
19494
|
+
if (requested === "steer" || requested === "queue") return requested;
|
|
19495
|
+
return followUpBehavior();
|
|
19496
|
+
}
|
|
19492
19497
|
function writeLiveStatus(threadId, status, lastError) {
|
|
19493
19498
|
const latest = readThread(threadId);
|
|
19494
19499
|
if (!latest || latest.status === "archived") return latest;
|
|
@@ -21429,7 +21434,7 @@ var init_orchestrator = __esm({
|
|
|
21429
21434
|
/**
|
|
21430
21435
|
* Desktop git buttons + MCP `ask_git`.
|
|
21431
21436
|
* When the worktree is clean, push / open the PR here (HTTPS via `gh` if SSH
|
|
21432
|
-
* is missing). When dirty,
|
|
21437
|
+
* is missing). When dirty, steer the worktree agent to commit first.
|
|
21433
21438
|
*/
|
|
21434
21439
|
async askGit(threadRef, action) {
|
|
21435
21440
|
if (!AGENT_GIT_ACTIONS.includes(action)) {
|
|
@@ -21466,7 +21471,9 @@ var init_orchestrator = __esm({
|
|
|
21466
21471
|
} catch {
|
|
21467
21472
|
}
|
|
21468
21473
|
}
|
|
21469
|
-
return this.send(threadRef, agentGitPrompt(action, { prBase })
|
|
21474
|
+
return this.send(threadRef, agentGitPrompt(action, { prBase }), {
|
|
21475
|
+
followUp: resolveOrchChildFollowUp()
|
|
21476
|
+
});
|
|
21470
21477
|
}
|
|
21471
21478
|
/** Push origin (gh HTTPS fallback) and create/update the PR when requested. */
|
|
21472
21479
|
async pushAndMaybeOpenPr(thread, action) {
|
|
@@ -22054,7 +22061,7 @@ function parseProjectTitles(raw) {
|
|
|
22054
22061
|
}
|
|
22055
22062
|
async function listGitHubIssueProjects(number, cwd, repoArgs) {
|
|
22056
22063
|
const result = await gh(
|
|
22057
|
-
["issue", "view", String(number), ...repoArgs, "--json", "projectItems
|
|
22064
|
+
["issue", "view", String(number), ...repoArgs, "--json", "projectItems"],
|
|
22058
22065
|
cwd,
|
|
22059
22066
|
{ reject: false }
|
|
22060
22067
|
);
|
|
@@ -22443,6 +22450,16 @@ query SideboardLabels($first: Int!) {
|
|
|
22443
22450
|
}
|
|
22444
22451
|
}
|
|
22445
22452
|
`;
|
|
22453
|
+
var TEAM_LABELS_QUERY = `
|
|
22454
|
+
query SideboardTeamLabels($id: String!, $first: Int!, $after: String) {
|
|
22455
|
+
team(id: $id) {
|
|
22456
|
+
labels(first: $first, after: $after) {
|
|
22457
|
+
nodes { id name }
|
|
22458
|
+
pageInfo { hasNextPage endCursor }
|
|
22459
|
+
}
|
|
22460
|
+
}
|
|
22461
|
+
}
|
|
22462
|
+
`;
|
|
22446
22463
|
var PROJECTS_QUERY = `
|
|
22447
22464
|
query SideboardProjects($first: Int!, $filter: ProjectFilter) {
|
|
22448
22465
|
projects(first: $first, filter: $filter) {
|
|
@@ -22816,15 +22833,38 @@ function formatRelationList(relations) {
|
|
|
22816
22833
|
if (!relations.length) return "(none)";
|
|
22817
22834
|
return relations.map((r) => `${r.type} ${r.issue.identifier || r.issue.id}`).join(", ");
|
|
22818
22835
|
}
|
|
22819
|
-
|
|
22820
|
-
|
|
22821
|
-
return (json.issueLabels?.nodes ?? []).flatMap((node) => {
|
|
22836
|
+
function mapLabelNodes(nodes) {
|
|
22837
|
+
return (nodes ?? []).flatMap((node) => {
|
|
22822
22838
|
const id = String(node.id ?? "").trim();
|
|
22823
22839
|
const name = String(node.name ?? "").trim();
|
|
22824
22840
|
if (!id) return [];
|
|
22825
22841
|
return [{ id, name }];
|
|
22826
22842
|
});
|
|
22827
22843
|
}
|
|
22844
|
+
async function listLinearWorkspaceLabels(opts) {
|
|
22845
|
+
const json = await linearGraphql(LABELS_QUERY, { first: 250 }, opts);
|
|
22846
|
+
return mapLabelNodes(json.issueLabels?.nodes);
|
|
22847
|
+
}
|
|
22848
|
+
async function listLinearLabels(opts) {
|
|
22849
|
+
const teamId = opts?.teamId?.trim();
|
|
22850
|
+
if (teamId) {
|
|
22851
|
+
const out = [];
|
|
22852
|
+
let after;
|
|
22853
|
+
for (let page = 0; page < 4; page++) {
|
|
22854
|
+
const json = await linearGraphql(
|
|
22855
|
+
TEAM_LABELS_QUERY,
|
|
22856
|
+
after ? { id: teamId, first: 250, after } : { id: teamId, first: 250 },
|
|
22857
|
+
opts
|
|
22858
|
+
);
|
|
22859
|
+
const conn = json.team?.labels;
|
|
22860
|
+
out.push(...mapLabelNodes(conn?.nodes));
|
|
22861
|
+
if (!conn?.pageInfo?.hasNextPage || !conn.pageInfo.endCursor) break;
|
|
22862
|
+
after = conn.pageInfo.endCursor;
|
|
22863
|
+
}
|
|
22864
|
+
if (out.length) return out;
|
|
22865
|
+
}
|
|
22866
|
+
return listLinearWorkspaceLabels(opts);
|
|
22867
|
+
}
|
|
22828
22868
|
async function listLinearProjects(filter, opts) {
|
|
22829
22869
|
const json = await linearGraphql(PROJECTS_QUERY, { first: 50, filter: filter ?? {} }, opts);
|
|
22830
22870
|
return (json.projects?.nodes ?? []).flatMap((node) => {
|
|
@@ -23113,7 +23153,7 @@ async function updateLinearIssue(input, opts) {
|
|
|
23113
23153
|
}
|
|
23114
23154
|
const addRelations = input.relations?.length ? input.relations : void 0;
|
|
23115
23155
|
const removeRelations = input.removeRelations?.length ? input.removeRelations : void 0;
|
|
23116
|
-
const needsIssue = Boolean(input.state?.trim()) || input.cycle !== void 0 || Boolean(addRelations) || Boolean(removeRelations);
|
|
23156
|
+
const needsIssue = Boolean(input.state?.trim()) || input.cycle !== void 0 || input.labels !== void 0 || Boolean(addRelations) || Boolean(removeRelations);
|
|
23117
23157
|
const existing = needsIssue ? await getLinearIssue(issueId, opts) : void 0;
|
|
23118
23158
|
if (input.state?.trim()) {
|
|
23119
23159
|
const { teams } = await listLinearTeams(opts);
|
|
@@ -23148,7 +23188,10 @@ async function updateLinearIssue(input, opts) {
|
|
|
23148
23188
|
mutationInput.priority = normalizePriority(input.priority);
|
|
23149
23189
|
}
|
|
23150
23190
|
if (input.labels !== void 0) {
|
|
23151
|
-
mutationInput.labelIds = await resolveLinearLabelIds(input.labels,
|
|
23191
|
+
mutationInput.labelIds = await resolveLinearLabelIds(input.labels, {
|
|
23192
|
+
...opts,
|
|
23193
|
+
teamId: existing?.team?.id
|
|
23194
|
+
});
|
|
23152
23195
|
}
|
|
23153
23196
|
if (input.project !== void 0) {
|
|
23154
23197
|
mutationInput.projectId = await resolveLinearProjectId(input.project, opts);
|
|
@@ -26009,7 +26052,7 @@ async function startMcpServer() {
|
|
|
26009
26052
|
);
|
|
26010
26053
|
server.tool(
|
|
26011
26054
|
"send_to_thread",
|
|
26012
|
-
'
|
|
26055
|
+
'Steer a prompt on a worktree thread chat (Settings \u2192 Follow-up, default steer: interrupt and start now, skip the inbox). Use after create_thread to start or continue a conversation. For commit/push/PR, prefer ask_git (canonical desktop-button phrases). Send "Merge PR." / ask_git merge only when the user explicitly asked to merge. force_stop=true kills the in-flight turn and clears the queue before this prompt \u2014 only when the current request is wrong and must be replaced. Do not send_to_thread to check in, resume after a halt notice, or because wait_for_turn returned stillRunning; that interrupts the child mid-thought. Call wait_for_turn again instead.',
|
|
26013
26056
|
{
|
|
26014
26057
|
ref: import_zod9.z.string(),
|
|
26015
26058
|
prompt: import_zod9.z.string(),
|
|
@@ -26022,7 +26065,9 @@ async function startMcpServer() {
|
|
|
26022
26065
|
orch.stop(ref, { clearQueue: true, notifyParent: false });
|
|
26023
26066
|
}
|
|
26024
26067
|
}
|
|
26025
|
-
const thread = await orch.send(ref, prompt
|
|
26068
|
+
const thread = await orch.send(ref, prompt, {
|
|
26069
|
+
followUp: resolveOrchChildFollowUp()
|
|
26070
|
+
});
|
|
26026
26071
|
return mcpJson({
|
|
26027
26072
|
id: thread.id,
|
|
26028
26073
|
status: thread.status,
|
|
@@ -26033,7 +26078,7 @@ async function startMcpServer() {
|
|
|
26033
26078
|
);
|
|
26034
26079
|
server.tool(
|
|
26035
26080
|
"wait_for_turn",
|
|
26036
|
-
"Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. stillRunning is the source of truth \u2014 if false, the child is not working (do not say it is waiting for a gate). If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not
|
|
26081
|
+
"Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. stillRunning is the source of truth \u2014 if false, the child is not working (do not say it is waiting for a gate). If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts), force_stop, or assume a hang. On status error, lastError/text is the failure. On status stopped or broken, the child did not finish \u2014 resume with send_to_thread or tell the user; do not treat that as success. When finished, usage is the last agent turn\u2019s tokens + costUsd (when the provider reported cost).",
|
|
26037
26082
|
{
|
|
26038
26083
|
ref: import_zod9.z.string(),
|
|
26039
26084
|
timeoutMs: import_zod9.z.number().optional()
|
|
@@ -26190,7 +26235,7 @@ async function startMcpServer() {
|
|
|
26190
26235
|
);
|
|
26191
26236
|
server.tool(
|
|
26192
26237
|
"ask_git",
|
|
26193
|
-
"Commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty,
|
|
26238
|
+
"Commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty, steers the worktree agent to commit (Settings \u2192 Follow-up, default interrupt now); then wait_for_turn (loop while stillRunning). Do not start a checks loop on a plain push \u2014 only if the user gave a goal (Greptile 5/5, CI green). Pass a worktree thread ref (not the orchestrator). action=ready-for-review and action=merge only when the user explicitly asked (or clicked the desktop button). Do not run git or gh from the orchestration cwd. If this tool errors that the GraphQL/PR body is too long, the branch is already pushed \u2014 have the worktree agent retry `gh pr create --body-file` with a short description (GitHub limit 65,536 characters). Do not invent SSH/auth failures from that error.",
|
|
26194
26239
|
{
|
|
26195
26240
|
ref: import_zod9.z.string().describe("Worktree thread id/ref"),
|
|
26196
26241
|
action: import_zod9.z.enum(AGENT_GIT_ACTIONS).describe(
|
package/dist/mcp/run-stdio.js
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
readTurnLive,
|
|
31
31
|
recordSlackOutboundWatch,
|
|
32
32
|
requireSlackWorkspace,
|
|
33
|
+
resolveOrchChildFollowUp,
|
|
33
34
|
resolveScheduleThreadId,
|
|
34
35
|
slackApi,
|
|
35
36
|
slackTokenFor,
|
|
@@ -37,7 +38,7 @@ import {
|
|
|
37
38
|
syncBoardPins,
|
|
38
39
|
updateSchedule,
|
|
39
40
|
waitForDetachedJob
|
|
40
|
-
} from "../chunk-
|
|
41
|
+
} from "../chunk-FZ3G5TXM.js";
|
|
41
42
|
import {
|
|
42
43
|
applySystemCaEnv,
|
|
43
44
|
isCursorApiKeyConfigured,
|
|
@@ -46,7 +47,7 @@ import {
|
|
|
46
47
|
materializeSystemCaBundle,
|
|
47
48
|
sideboardMcpProfile,
|
|
48
49
|
trustSystemCertificates
|
|
49
|
-
} from "../chunk-
|
|
50
|
+
} from "../chunk-WHD4JNTN.js";
|
|
50
51
|
import "../chunk-HVIEYTUK.js";
|
|
51
52
|
import "../chunk-Y4MIXGPA.js";
|
|
52
53
|
import {
|
|
@@ -70,7 +71,7 @@ import {
|
|
|
70
71
|
GLOBAL_WORKSPACE_ID,
|
|
71
72
|
isCloudCoordinatorThread,
|
|
72
73
|
listWorkspaces
|
|
73
|
-
} from "../chunk-
|
|
74
|
+
} from "../chunk-7NSXGL6L.js";
|
|
74
75
|
import {
|
|
75
76
|
canonicalizeRepoPath,
|
|
76
77
|
formatGhLandError,
|
|
@@ -414,7 +415,7 @@ function parseProjectTitles(raw) {
|
|
|
414
415
|
}
|
|
415
416
|
async function listGitHubIssueProjects(number, cwd, repoArgs) {
|
|
416
417
|
const result = await gh(
|
|
417
|
-
["issue", "view", String(number), ...repoArgs, "--json", "projectItems
|
|
418
|
+
["issue", "view", String(number), ...repoArgs, "--json", "projectItems"],
|
|
418
419
|
cwd,
|
|
419
420
|
{ reject: false }
|
|
420
421
|
);
|
|
@@ -798,6 +799,16 @@ query SideboardLabels($first: Int!) {
|
|
|
798
799
|
}
|
|
799
800
|
}
|
|
800
801
|
`;
|
|
802
|
+
var TEAM_LABELS_QUERY = `
|
|
803
|
+
query SideboardTeamLabels($id: String!, $first: Int!, $after: String) {
|
|
804
|
+
team(id: $id) {
|
|
805
|
+
labels(first: $first, after: $after) {
|
|
806
|
+
nodes { id name }
|
|
807
|
+
pageInfo { hasNextPage endCursor }
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
`;
|
|
801
812
|
var PROJECTS_QUERY = `
|
|
802
813
|
query SideboardProjects($first: Int!, $filter: ProjectFilter) {
|
|
803
814
|
projects(first: $first, filter: $filter) {
|
|
@@ -1171,15 +1182,38 @@ function formatRelationList(relations) {
|
|
|
1171
1182
|
if (!relations.length) return "(none)";
|
|
1172
1183
|
return relations.map((r) => `${r.type} ${r.issue.identifier || r.issue.id}`).join(", ");
|
|
1173
1184
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
return (json.issueLabels?.nodes ?? []).flatMap((node) => {
|
|
1185
|
+
function mapLabelNodes(nodes) {
|
|
1186
|
+
return (nodes ?? []).flatMap((node) => {
|
|
1177
1187
|
const id = String(node.id ?? "").trim();
|
|
1178
1188
|
const name = String(node.name ?? "").trim();
|
|
1179
1189
|
if (!id) return [];
|
|
1180
1190
|
return [{ id, name }];
|
|
1181
1191
|
});
|
|
1182
1192
|
}
|
|
1193
|
+
async function listLinearWorkspaceLabels(opts) {
|
|
1194
|
+
const json = await linearGraphql(LABELS_QUERY, { first: 250 }, opts);
|
|
1195
|
+
return mapLabelNodes(json.issueLabels?.nodes);
|
|
1196
|
+
}
|
|
1197
|
+
async function listLinearLabels(opts) {
|
|
1198
|
+
const teamId = opts?.teamId?.trim();
|
|
1199
|
+
if (teamId) {
|
|
1200
|
+
const out = [];
|
|
1201
|
+
let after;
|
|
1202
|
+
for (let page = 0; page < 4; page++) {
|
|
1203
|
+
const json = await linearGraphql(
|
|
1204
|
+
TEAM_LABELS_QUERY,
|
|
1205
|
+
after ? { id: teamId, first: 250, after } : { id: teamId, first: 250 },
|
|
1206
|
+
opts
|
|
1207
|
+
);
|
|
1208
|
+
const conn = json.team?.labels;
|
|
1209
|
+
out.push(...mapLabelNodes(conn?.nodes));
|
|
1210
|
+
if (!conn?.pageInfo?.hasNextPage || !conn.pageInfo.endCursor) break;
|
|
1211
|
+
after = conn.pageInfo.endCursor;
|
|
1212
|
+
}
|
|
1213
|
+
if (out.length) return out;
|
|
1214
|
+
}
|
|
1215
|
+
return listLinearWorkspaceLabels(opts);
|
|
1216
|
+
}
|
|
1183
1217
|
async function listLinearProjects(filter, opts) {
|
|
1184
1218
|
const json = await linearGraphql(PROJECTS_QUERY, { first: 50, filter: filter ?? {} }, opts);
|
|
1185
1219
|
return (json.projects?.nodes ?? []).flatMap((node) => {
|
|
@@ -1468,7 +1502,7 @@ async function updateLinearIssue(input, opts) {
|
|
|
1468
1502
|
}
|
|
1469
1503
|
const addRelations = input.relations?.length ? input.relations : void 0;
|
|
1470
1504
|
const removeRelations = input.removeRelations?.length ? input.removeRelations : void 0;
|
|
1471
|
-
const needsIssue = Boolean(input.state?.trim()) || input.cycle !== void 0 || Boolean(addRelations) || Boolean(removeRelations);
|
|
1505
|
+
const needsIssue = Boolean(input.state?.trim()) || input.cycle !== void 0 || input.labels !== void 0 || Boolean(addRelations) || Boolean(removeRelations);
|
|
1472
1506
|
const existing = needsIssue ? await getLinearIssue(issueId, opts) : void 0;
|
|
1473
1507
|
if (input.state?.trim()) {
|
|
1474
1508
|
const { teams } = await listLinearTeams(opts);
|
|
@@ -1503,7 +1537,10 @@ async function updateLinearIssue(input, opts) {
|
|
|
1503
1537
|
mutationInput.priority = normalizePriority(input.priority);
|
|
1504
1538
|
}
|
|
1505
1539
|
if (input.labels !== void 0) {
|
|
1506
|
-
mutationInput.labelIds = await resolveLinearLabelIds(input.labels,
|
|
1540
|
+
mutationInput.labelIds = await resolveLinearLabelIds(input.labels, {
|
|
1541
|
+
...opts,
|
|
1542
|
+
teamId: existing?.team?.id
|
|
1543
|
+
});
|
|
1507
1544
|
}
|
|
1508
1545
|
if (input.project !== void 0) {
|
|
1509
1546
|
mutationInput.projectId = await resolveLinearProjectId(input.project, opts);
|
|
@@ -4315,7 +4352,7 @@ async function startMcpServer() {
|
|
|
4315
4352
|
);
|
|
4316
4353
|
server.tool(
|
|
4317
4354
|
"send_to_thread",
|
|
4318
|
-
'
|
|
4355
|
+
'Steer a prompt on a worktree thread chat (Settings \u2192 Follow-up, default steer: interrupt and start now, skip the inbox). Use after create_thread to start or continue a conversation. For commit/push/PR, prefer ask_git (canonical desktop-button phrases). Send "Merge PR." / ask_git merge only when the user explicitly asked to merge. force_stop=true kills the in-flight turn and clears the queue before this prompt \u2014 only when the current request is wrong and must be replaced. Do not send_to_thread to check in, resume after a halt notice, or because wait_for_turn returned stillRunning; that interrupts the child mid-thought. Call wait_for_turn again instead.',
|
|
4319
4356
|
{
|
|
4320
4357
|
ref: z9.string(),
|
|
4321
4358
|
prompt: z9.string(),
|
|
@@ -4328,7 +4365,9 @@ async function startMcpServer() {
|
|
|
4328
4365
|
orch.stop(ref, { clearQueue: true, notifyParent: false });
|
|
4329
4366
|
}
|
|
4330
4367
|
}
|
|
4331
|
-
const thread = await orch.send(ref, prompt
|
|
4368
|
+
const thread = await orch.send(ref, prompt, {
|
|
4369
|
+
followUp: resolveOrchChildFollowUp()
|
|
4370
|
+
});
|
|
4332
4371
|
return mcpJson({
|
|
4333
4372
|
id: thread.id,
|
|
4334
4373
|
status: thread.status,
|
|
@@ -4339,7 +4378,7 @@ async function startMcpServer() {
|
|
|
4339
4378
|
);
|
|
4340
4379
|
server.tool(
|
|
4341
4380
|
"wait_for_turn",
|
|
4342
|
-
"Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. stillRunning is the source of truth \u2014 if false, the child is not working (do not say it is waiting for a gate). If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not
|
|
4381
|
+
"Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. stillRunning is the source of truth \u2014 if false, the child is not working (do not say it is waiting for a gate). If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts), force_stop, or assume a hang. On status error, lastError/text is the failure. On status stopped or broken, the child did not finish \u2014 resume with send_to_thread or tell the user; do not treat that as success. When finished, usage is the last agent turn\u2019s tokens + costUsd (when the provider reported cost).",
|
|
4343
4382
|
{
|
|
4344
4383
|
ref: z9.string(),
|
|
4345
4384
|
timeoutMs: z9.number().optional()
|
|
@@ -4496,7 +4535,7 @@ async function startMcpServer() {
|
|
|
4496
4535
|
);
|
|
4497
4536
|
server.tool(
|
|
4498
4537
|
"ask_git",
|
|
4499
|
-
"Commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty,
|
|
4538
|
+
"Commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty, steers the worktree agent to commit (Settings \u2192 Follow-up, default interrupt now); then wait_for_turn (loop while stillRunning). Do not start a checks loop on a plain push \u2014 only if the user gave a goal (Greptile 5/5, CI green). Pass a worktree thread ref (not the orchestrator). action=ready-for-review and action=merge only when the user explicitly asked (or clicked the desktop button). Do not run git or gh from the orchestration cwd. If this tool errors that the GraphQL/PR body is too long, the branch is already pushed \u2014 have the worktree agent retry `gh pr create --body-file` with a short description (GitHub limit 65,536 characters). Do not invent SSH/auth failures from that error.",
|
|
4500
4539
|
{
|
|
4501
4540
|
ref: z9.string().describe("Worktree thread id/ref"),
|
|
4502
4541
|
action: z9.enum(AGENT_GIT_ACTIONS).describe(
|
|
@@ -5,17 +5,18 @@ import {
|
|
|
5
5
|
Orchestrator,
|
|
6
6
|
getOrchestrator,
|
|
7
7
|
isPidAlive,
|
|
8
|
+
resolveOrchChildFollowUp,
|
|
8
9
|
resolveSendFollowUp,
|
|
9
10
|
startOrchestration,
|
|
10
11
|
waitForPidExit
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-FZ3G5TXM.js";
|
|
13
|
+
import "./chunk-WHD4JNTN.js";
|
|
13
14
|
import "./chunk-HVIEYTUK.js";
|
|
14
15
|
import "./chunk-Y4MIXGPA.js";
|
|
15
16
|
import "./chunk-VKQGAWHY.js";
|
|
16
17
|
import "./chunk-JFOPOMK7.js";
|
|
17
18
|
import "./chunk-OCQPTUR7.js";
|
|
18
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-7NSXGL6L.js";
|
|
19
20
|
import "./chunk-XBLN52RZ.js";
|
|
20
21
|
import "./chunk-D6JWYJ4P.js";
|
|
21
22
|
import "./chunk-GOZ6T3AG.js";
|
|
@@ -30,6 +31,7 @@ export {
|
|
|
30
31
|
Orchestrator,
|
|
31
32
|
getOrchestrator,
|
|
32
33
|
isPidAlive,
|
|
34
|
+
resolveOrchChildFollowUp,
|
|
33
35
|
resolveSendFollowUp,
|
|
34
36
|
startOrchestration,
|
|
35
37
|
waitForPidExit
|
|
@@ -3,13 +3,14 @@ import {
|
|
|
3
3
|
Orchestrator,
|
|
4
4
|
getOrchestrator,
|
|
5
5
|
isPidAlive,
|
|
6
|
+
resolveOrchChildFollowUp,
|
|
6
7
|
resolveSendFollowUp,
|
|
7
8
|
startOrchestration,
|
|
8
9
|
waitForPidExit
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NF6ENGHS.js";
|
|
10
11
|
import "./chunk-DJU54RYW.js";
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-TWSCTJCR.js";
|
|
13
|
+
import "./chunk-VV7UT3E2.js";
|
|
13
14
|
import "./chunk-WXKXSZN4.js";
|
|
14
15
|
import "./chunk-6K64FJDD.js";
|
|
15
16
|
import "./chunk-IEEAVWAP.js";
|
|
@@ -31,6 +32,7 @@ export {
|
|
|
31
32
|
Orchestrator,
|
|
32
33
|
getOrchestrator,
|
|
33
34
|
isPidAlive,
|
|
35
|
+
resolveOrchChildFollowUp,
|
|
34
36
|
resolveSendFollowUp,
|
|
35
37
|
startOrchestration,
|
|
36
38
|
waitForPidExit
|