@sideboard-ai/core 0.1.124 → 0.1.127
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-DPR2TDNF.js → agents-7BUQY2WX.js} +6 -6
- package/dist/{agents-DCXXLTXF.js → agents-X2I3RNCY.js} +6 -6
- package/dist/{app-settings-YFWV7MOG.js → app-settings-6RPALX4J.js} +7 -1
- package/dist/{app-settings-IKFWZDUK.js → app-settings-E7NEQY7D.js} +7 -1
- package/dist/{chunk-SDCPQL27.js → chunk-DLM5LSQW.js} +484 -93
- package/dist/{chunk-RG737OWT.js → chunk-G6X6UFJO.js} +2 -0
- package/dist/{chunk-HPAWHIZ3.js → chunk-HLJUNJBF.js} +2 -0
- package/dist/{chunk-OHEFHIG3.js → chunk-HRSBZIXS.js} +14 -6
- package/dist/{chunk-KWGP6RZM.js → chunk-HULESWLI.js} +4 -4
- package/dist/{chunk-FXQPY2KU.js → chunk-HUYEU4GS.js} +26 -4
- package/dist/{chunk-2X7I6MDW.js → chunk-HZPO3SSZ.js} +11 -8
- package/dist/{chunk-O43IRQ2Y.js → chunk-MNL4FSKY.js} +4 -4
- package/dist/{chunk-7Y3AYQWT.js → chunk-NV73AO7Q.js} +4 -4
- package/dist/{chunk-TRTWH6C2.js → chunk-RSFCB23A.js} +11 -8
- package/dist/{chunk-RBVVWBVB.js → chunk-SYLTXDRF.js} +2 -2
- package/dist/{chunk-MZDAEI3Y.js → chunk-T7KJQJAX.js} +496 -109
- package/dist/{chunk-UAVZ2JSO.js → chunk-UDQI3N47.js} +14 -6
- package/dist/{chunk-HZLE6LJJ.js → chunk-VE22NWBD.js} +2 -2
- package/dist/{chunk-JNAIKICO.js → chunk-ZMUOPTKZ.js} +4 -4
- package/dist/{chunk-BMIRX64H.js → chunk-ZND6XV6J.js} +26 -4
- package/dist/{coordinator-prompt-AZ3WRDNC.js → coordinator-prompt-MEEUOEF2.js} +4 -4
- package/dist/{coordinator-prompt-LEU62W25.js → coordinator-prompt-SPJSGAQS.js} +4 -4
- package/dist/{global-workspace-U5UOVXKQ.js → global-workspace-BMWP7YZC.js} +5 -5
- package/dist/{global-workspace-4YNYDMLQ.js → global-workspace-KNESLWKG.js} +5 -5
- package/dist/index.cjs +1208 -236
- package/dist/index.d.cts +303 -103
- package/dist/index.d.ts +303 -103
- package/dist/index.js +671 -129
- package/dist/mcp/run-stdio.cjs +1054 -194
- package/dist/mcp/run-stdio.js +554 -114
- package/dist/{orchestrator-VJQ5EWZZ.js → orchestrator-3JLPPTCF.js} +8 -8
- package/dist/{orchestrator-JS3EHI4E.js → orchestrator-6GUCE4LY.js} +8 -8
- package/dist/{thread-store-JR235AWK.js → thread-store-5MLYY35S.js} +1 -1
- package/dist/{thread-store-PMH3BMB6.js → thread-store-F6BCARQG.js} +1 -1
- package/dist/{workspaces-ICK433ZV.js → workspaces-HSYRYJYV.js} +6 -6
- package/dist/{workspaces-POWKTH2D.js → workspaces-O4QZOASB.js} +6 -6
- package/dist/{worktree-CMGBTVN4.js → worktree-ERHC7Q4F.js} +5 -3
- package/dist/{worktree-T57RD7BQ.js → worktree-JVGSLSLJ.js} +5 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AGENT_GIT_ACTIONS,
|
|
3
|
+
BOARD_COLUMN_DEFS,
|
|
3
4
|
CONTEXT_COMPACT_CHARS,
|
|
4
5
|
CONTEXT_KEEP_RECENT_CHARS,
|
|
5
6
|
CONTEXT_KEEP_RECENT_MESSAGES,
|
|
6
7
|
CONTEXT_MIN_MESSAGES,
|
|
8
|
+
HOME_BOARD_AGENT_HINT,
|
|
9
|
+
HOME_BOARD_CACHE_TTL_MS,
|
|
7
10
|
LEGACY_REVIEW_REQUEST_PATH,
|
|
8
11
|
Orchestrator,
|
|
9
12
|
REPO_REVIEW_NAME,
|
|
@@ -25,9 +28,11 @@ import {
|
|
|
25
28
|
applyPromptCacheTtlEnv,
|
|
26
29
|
applyThreadIntoMain,
|
|
27
30
|
armSchedules,
|
|
31
|
+
assembleHomeBoard,
|
|
28
32
|
attachmentFromAbsolutePath,
|
|
29
33
|
attachmentsFromBuffers,
|
|
30
34
|
attachmentsFromWorktreePaths,
|
|
35
|
+
boardPinIdentity,
|
|
31
36
|
buildForkTranscriptAttachment,
|
|
32
37
|
buildReviewRequestAttachment,
|
|
33
38
|
buildSessionSeed,
|
|
@@ -35,6 +40,7 @@ import {
|
|
|
35
40
|
captureLoginEnv,
|
|
36
41
|
captureTurnBaseline,
|
|
37
42
|
claimDesktopHost,
|
|
43
|
+
classifyWorktreeColumn,
|
|
38
44
|
cleanupOrphanWorktrees,
|
|
39
45
|
cloneRepoIntoSideboard,
|
|
40
46
|
computeNextRunAt,
|
|
@@ -46,19 +52,24 @@ import {
|
|
|
46
52
|
createPrStack,
|
|
47
53
|
createSchedule,
|
|
48
54
|
createThread,
|
|
55
|
+
dedupeBoardIssues,
|
|
56
|
+
dedupeBoardPrs,
|
|
49
57
|
defaultScheduleName,
|
|
50
58
|
deleteSchedule,
|
|
51
59
|
desktopHostPidPath,
|
|
52
60
|
detectAgents,
|
|
53
61
|
disconnectSlackWorkspace,
|
|
54
62
|
discoverSkills,
|
|
55
|
-
dismissSlackReplyBadge,
|
|
56
63
|
ensureReviewRequestFile,
|
|
57
64
|
ensureReviewSkillFile,
|
|
58
65
|
estimateMessageChars,
|
|
59
66
|
estimateThreadChars,
|
|
60
67
|
expandComposerPrompt,
|
|
61
68
|
extractiveSummary,
|
|
69
|
+
findBoardIssue,
|
|
70
|
+
findBoardPin,
|
|
71
|
+
findBoardPr,
|
|
72
|
+
findLiveThreadForCreate,
|
|
62
73
|
findOrphanWorktrees,
|
|
63
74
|
findThreadForStackLayer,
|
|
64
75
|
fireSchedule,
|
|
@@ -88,6 +99,7 @@ import {
|
|
|
88
99
|
getSchedule,
|
|
89
100
|
getSlackReplyTarget,
|
|
90
101
|
getSlackWorkspace,
|
|
102
|
+
groupHomeBoardWorktrees,
|
|
91
103
|
hasEnabledSchedules,
|
|
92
104
|
importConductorWorkspace,
|
|
93
105
|
importConductorWorkspaceAsync,
|
|
@@ -96,11 +108,13 @@ import {
|
|
|
96
108
|
inspectGitWorktree,
|
|
97
109
|
isCowboyThread,
|
|
98
110
|
isDesktopHostAlive,
|
|
111
|
+
isHomeBoardThread,
|
|
99
112
|
isImageFilePath,
|
|
100
113
|
isPidAlive,
|
|
101
114
|
isPrimaryCheckoutThread,
|
|
102
115
|
isSlackExternalReplyPrompt,
|
|
103
116
|
isThisProcessDesktopHost,
|
|
117
|
+
issueNeedsWorkspacePick,
|
|
104
118
|
lastRequestOccupancy,
|
|
105
119
|
listBranchCommits,
|
|
106
120
|
listConductorWorkspaces,
|
|
@@ -108,7 +122,6 @@ import {
|
|
|
108
122
|
listRunScripts,
|
|
109
123
|
listSchedules,
|
|
110
124
|
listSlackOutboundWatches,
|
|
111
|
-
listSlackReplyBadges,
|
|
112
125
|
listSlackWorkspaces,
|
|
113
126
|
listSlackWorkspacesRaw,
|
|
114
127
|
listWorktreeFiles,
|
|
@@ -118,7 +131,7 @@ import {
|
|
|
118
131
|
openStackLayer,
|
|
119
132
|
parseDurationMs,
|
|
120
133
|
pendingSlackExternalReplies,
|
|
121
|
-
|
|
134
|
+
pollSlackOutboundWatches,
|
|
122
135
|
previewLand,
|
|
123
136
|
readExistingReviewRequestFile,
|
|
124
137
|
readSkillBody,
|
|
@@ -128,7 +141,6 @@ import {
|
|
|
128
141
|
readWorktreeInclude,
|
|
129
142
|
recordScheduleRun,
|
|
130
143
|
recordSlackOutboundWatch,
|
|
131
|
-
refreshSlackReplyBadges,
|
|
132
144
|
releaseDesktopHost,
|
|
133
145
|
requestReview,
|
|
134
146
|
requireAgent,
|
|
@@ -161,6 +173,7 @@ import {
|
|
|
161
173
|
startDevServer,
|
|
162
174
|
startOrchestration,
|
|
163
175
|
summarizeConversation,
|
|
176
|
+
syncBoardPins,
|
|
164
177
|
takenTeamSlugsForChatTab,
|
|
165
178
|
thisProcessShouldDrainAgentQueues,
|
|
166
179
|
threadsSharingWorktree,
|
|
@@ -168,10 +181,11 @@ import {
|
|
|
168
181
|
upsertSlackWorkspace,
|
|
169
182
|
waitForPidExit,
|
|
170
183
|
withAgentInstructions,
|
|
184
|
+
worktreeBoardStatus,
|
|
171
185
|
worktreeCleanupSettings,
|
|
172
186
|
wrapReviewSkillMarkdown,
|
|
173
187
|
writeWorktreeFile
|
|
174
|
-
} from "./chunk-
|
|
188
|
+
} from "./chunk-T7KJQJAX.js";
|
|
175
189
|
import {
|
|
176
190
|
BRIGHTSY_MCP_ALLOWED_TOOLS,
|
|
177
191
|
CLAUDE_MODEL_CATALOG,
|
|
@@ -250,7 +264,7 @@ import {
|
|
|
250
264
|
withEventParentId,
|
|
251
265
|
withEventsParentId,
|
|
252
266
|
writeInjectedMcpConfig
|
|
253
|
-
} from "./chunk-
|
|
267
|
+
} from "./chunk-NV73AO7Q.js";
|
|
254
268
|
import {
|
|
255
269
|
brightsyConfigPath,
|
|
256
270
|
brightsyMcpServerName,
|
|
@@ -269,7 +283,7 @@ import {
|
|
|
269
283
|
listWorkspaces,
|
|
270
284
|
removeWorkspace,
|
|
271
285
|
syncWorkspacesFromThreads
|
|
272
|
-
} from "./chunk-
|
|
286
|
+
} from "./chunk-VE22NWBD.js";
|
|
273
287
|
import {
|
|
274
288
|
CLOUD_COORDINATOR_BUSY_REPLY,
|
|
275
289
|
CLOUD_COORDINATOR_STOPPED_REPLY,
|
|
@@ -297,7 +311,7 @@ import {
|
|
|
297
311
|
parseForceStopMessage,
|
|
298
312
|
slackCoordinatorSourceRef,
|
|
299
313
|
takenTeamSlugsForOrchestration
|
|
300
|
-
} from "./chunk-
|
|
314
|
+
} from "./chunk-HULESWLI.js";
|
|
301
315
|
import {
|
|
302
316
|
COORDINATOR_TOOL_PLAYBOOK,
|
|
303
317
|
SLACK_REPLY_FORMATTING,
|
|
@@ -306,7 +320,7 @@ import {
|
|
|
306
320
|
enrichWorkspacesWithGithub,
|
|
307
321
|
ensureGlobalCoordinatorCwd,
|
|
308
322
|
formatWorkspaceInventory
|
|
309
|
-
} from "./chunk-
|
|
323
|
+
} from "./chunk-HZPO3SSZ.js";
|
|
310
324
|
import {
|
|
311
325
|
LEGACY_PLAN_FILE_REL,
|
|
312
326
|
PLAN_FILE_NAME,
|
|
@@ -343,6 +357,7 @@ import {
|
|
|
343
357
|
appendIndexedGitConfig,
|
|
344
358
|
applyGithubGitAuthEnv,
|
|
345
359
|
branchDisplayLabel,
|
|
360
|
+
canonicalizeRepoPath,
|
|
346
361
|
checkoutPrStackLayer,
|
|
347
362
|
codexSandboxWritableRootsArgs,
|
|
348
363
|
codexUnattendedGitConfigArgs,
|
|
@@ -415,7 +430,7 @@ import {
|
|
|
415
430
|
worktreeDisplayLabel,
|
|
416
431
|
worktreeDisplayLabelForGroup,
|
|
417
432
|
worktreeNameFromPath
|
|
418
|
-
} from "./chunk-
|
|
433
|
+
} from "./chunk-UDQI3N47.js";
|
|
419
434
|
import {
|
|
420
435
|
ATTACHMENTS_DIR,
|
|
421
436
|
LEGACY_ATTACHMENTS_DIR,
|
|
@@ -425,6 +440,7 @@ import {
|
|
|
425
440
|
import {
|
|
426
441
|
GITHUB_GIT_AUTH_MODES,
|
|
427
442
|
HARNESS_ENV_KEYS,
|
|
443
|
+
ISSUE_SOURCE_LABELS,
|
|
428
444
|
appSettingsPath,
|
|
429
445
|
applyAppEnvironment,
|
|
430
446
|
autoArchiveOnMergeEnabled,
|
|
@@ -454,7 +470,9 @@ import {
|
|
|
454
470
|
getIssueSource,
|
|
455
471
|
getLinearApiKey,
|
|
456
472
|
harnessEnvKey,
|
|
473
|
+
isIssueSourceConnected,
|
|
457
474
|
isLinearConnected,
|
|
475
|
+
issueSourceLabel,
|
|
458
476
|
loadAppSettings,
|
|
459
477
|
maxConcurrentAgents,
|
|
460
478
|
orchestrationQuotaFallbackAgent,
|
|
@@ -484,7 +502,7 @@ import {
|
|
|
484
502
|
updateDefaultsSettings,
|
|
485
503
|
updateIntegrationsSettings,
|
|
486
504
|
updateOpencodeSettings
|
|
487
|
-
} from "./chunk-
|
|
505
|
+
} from "./chunk-HUYEU4GS.js";
|
|
488
506
|
import {
|
|
489
507
|
stripNestedElectronEnv
|
|
490
508
|
} from "./chunk-4TR3HZFT.js";
|
|
@@ -503,7 +521,7 @@ import {
|
|
|
503
521
|
updateThread,
|
|
504
522
|
withThreadLock,
|
|
505
523
|
writeThread
|
|
506
|
-
} from "./chunk-
|
|
524
|
+
} from "./chunk-HLJUNJBF.js";
|
|
507
525
|
import {
|
|
508
526
|
THINKING_EFFORTS,
|
|
509
527
|
isThinkingEffort,
|
|
@@ -912,10 +930,13 @@ var ISSUE_FIELDS = `
|
|
|
912
930
|
assignee { id name }
|
|
913
931
|
team { id key name states { nodes { id name type } } }
|
|
914
932
|
labels { nodes { name } }
|
|
933
|
+
cycle { id name number startsAt endsAt completedAt }
|
|
915
934
|
`;
|
|
916
935
|
var ASSIGNED_ISSUES_QUERY = `
|
|
917
936
|
query SideboardAssignedIssues($first: Int!) {
|
|
918
937
|
viewer {
|
|
938
|
+
id
|
|
939
|
+
name
|
|
919
940
|
assignedIssues(
|
|
920
941
|
first: $first
|
|
921
942
|
orderBy: updatedAt
|
|
@@ -1018,6 +1039,25 @@ function mapState(node) {
|
|
|
1018
1039
|
type: String(node.type ?? "")
|
|
1019
1040
|
};
|
|
1020
1041
|
}
|
|
1042
|
+
function linearCycleIsActive(cycle, now = Date.now()) {
|
|
1043
|
+
if (!cycle) return false;
|
|
1044
|
+
if (cycle.completedAt) return false;
|
|
1045
|
+
const start = cycle.startsAt ? Date.parse(cycle.startsAt) : Number.NaN;
|
|
1046
|
+
const end = cycle.endsAt ? Date.parse(cycle.endsAt) : Number.NaN;
|
|
1047
|
+
if (Number.isFinite(start) && now < start) return false;
|
|
1048
|
+
if (Number.isFinite(end) && now > end) return false;
|
|
1049
|
+
return true;
|
|
1050
|
+
}
|
|
1051
|
+
function mapCycle(node) {
|
|
1052
|
+
if (!node?.name && node?.number == null) return null;
|
|
1053
|
+
const name = String(node.name ?? (node.number != null ? `Cycle ${node.number}` : "")).trim();
|
|
1054
|
+
if (!name) return null;
|
|
1055
|
+
return {
|
|
1056
|
+
name,
|
|
1057
|
+
number: typeof node.number === "number" ? node.number : void 0,
|
|
1058
|
+
isActive: linearCycleIsActive(node)
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1021
1061
|
function mapIssue(node) {
|
|
1022
1062
|
const team = node.team;
|
|
1023
1063
|
return {
|
|
@@ -1035,7 +1075,8 @@ function mapIssue(node) {
|
|
|
1035
1075
|
name: String(team.name ?? ""),
|
|
1036
1076
|
states: (team.states?.nodes ?? []).map((s) => mapState(s)).filter((s) => Boolean(s))
|
|
1037
1077
|
} : void 0,
|
|
1038
|
-
labels: (node.labels?.nodes ?? []).map((l) => l.name).filter((n) => Boolean(n))
|
|
1078
|
+
labels: (node.labels?.nodes ?? []).map((l) => l.name).filter((n) => Boolean(n)),
|
|
1079
|
+
cycle: mapCycle(node.cycle)
|
|
1039
1080
|
};
|
|
1040
1081
|
}
|
|
1041
1082
|
function toIssueInfo(issue) {
|
|
@@ -1045,7 +1086,11 @@ function toIssueInfo(issue) {
|
|
|
1045
1086
|
title: issue.title,
|
|
1046
1087
|
url: issue.url,
|
|
1047
1088
|
labels: issue.labels,
|
|
1048
|
-
provider: "linear"
|
|
1089
|
+
provider: "linear",
|
|
1090
|
+
assignee: issue.assignee?.name,
|
|
1091
|
+
assignees: issue.assignee?.name ? [issue.assignee.name] : void 0,
|
|
1092
|
+
cycle: issue.cycle ?? null,
|
|
1093
|
+
teamKey: issue.team?.key || void 0
|
|
1049
1094
|
};
|
|
1050
1095
|
}
|
|
1051
1096
|
function mapTeam(node) {
|
|
@@ -1087,10 +1132,21 @@ function normalizePriority(priority) {
|
|
|
1087
1132
|
}
|
|
1088
1133
|
return priority;
|
|
1089
1134
|
}
|
|
1090
|
-
async function
|
|
1091
|
-
const first = Math.max(1, Math.min(
|
|
1135
|
+
async function listLinearAssignedIssues(opts) {
|
|
1136
|
+
const first = Math.max(1, Math.min(250, opts?.limit ?? 200));
|
|
1092
1137
|
const json = await linearGraphql(ASSIGNED_ISSUES_QUERY, { first }, opts);
|
|
1093
|
-
return
|
|
1138
|
+
return {
|
|
1139
|
+
viewer: {
|
|
1140
|
+
id: String(json.viewer?.id ?? ""),
|
|
1141
|
+
name: String(json.viewer?.name ?? "")
|
|
1142
|
+
},
|
|
1143
|
+
issues: (json.viewer?.assignedIssues?.nodes ?? []).map(
|
|
1144
|
+
(node) => toIssueInfo(mapIssue(node))
|
|
1145
|
+
)
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
async function listLinearIssuesDirect(opts) {
|
|
1149
|
+
return (await listLinearAssignedIssues(opts)).issues;
|
|
1094
1150
|
}
|
|
1095
1151
|
async function listLinearTeams(opts) {
|
|
1096
1152
|
const json = await linearGraphql(TEAMS_QUERY, void 0, opts);
|
|
@@ -1209,13 +1265,13 @@ async function validateLinearApiKey(apiKey) {
|
|
|
1209
1265
|
|
|
1210
1266
|
// src/integrations/issues.ts
|
|
1211
1267
|
async function listGitHubIssues(repoPath, opts) {
|
|
1212
|
-
const limit = Math.max(1, Math.min(
|
|
1268
|
+
const limit = Math.max(1, Math.min(1e3, opts?.limit ?? 200));
|
|
1213
1269
|
const slug = await resolveGithubRepoSlug(repoPath);
|
|
1214
1270
|
const args = [
|
|
1215
1271
|
"issue",
|
|
1216
1272
|
"list",
|
|
1217
1273
|
"--json",
|
|
1218
|
-
"number,title,url,labels",
|
|
1274
|
+
"number,title,url,labels,assignees",
|
|
1219
1275
|
"--limit",
|
|
1220
1276
|
String(limit),
|
|
1221
1277
|
"--state",
|
|
@@ -1238,27 +1294,55 @@ async function listGitHubIssues(repoPath, opts) {
|
|
|
1238
1294
|
const labels = (item.labels ?? []).map(
|
|
1239
1295
|
(l) => typeof l === "string" ? l : String(l?.name ?? "")
|
|
1240
1296
|
).filter(Boolean);
|
|
1297
|
+
const assignees = (item.assignees ?? []).map((a) => typeof a === "string" ? a : String(a?.login ?? "")).map((login) => login.trim()).filter(Boolean);
|
|
1241
1298
|
return {
|
|
1242
1299
|
id: Number.isFinite(number) ? `gh-${number}` : identifier,
|
|
1243
1300
|
identifier,
|
|
1244
1301
|
title: String(item.title ?? ""),
|
|
1245
1302
|
url: String(item.url ?? ""),
|
|
1246
1303
|
labels,
|
|
1247
|
-
provider: "github"
|
|
1304
|
+
provider: "github",
|
|
1305
|
+
assignee: assignees[0],
|
|
1306
|
+
assignees
|
|
1248
1307
|
};
|
|
1249
1308
|
});
|
|
1250
1309
|
}
|
|
1310
|
+
async function githubViewerLogin(repoPath) {
|
|
1311
|
+
const { stdout, exitCode } = await gh(["api", "user", "--jq", ".login"], repoPath, {
|
|
1312
|
+
reject: false
|
|
1313
|
+
});
|
|
1314
|
+
if (exitCode !== 0) return "";
|
|
1315
|
+
return stdout.trim();
|
|
1316
|
+
}
|
|
1251
1317
|
async function listIssues(repoPath) {
|
|
1252
1318
|
const settings = loadAppSettings();
|
|
1253
1319
|
const preferredSource = settings.integrations.issueSource ?? "github";
|
|
1254
1320
|
const linearConnected = isLinearConnected(settings);
|
|
1255
1321
|
const source = resolveEffectiveIssueSource(settings);
|
|
1256
1322
|
if (source === "linear") {
|
|
1257
|
-
const
|
|
1258
|
-
return {
|
|
1323
|
+
const listed = await listLinearAssignedIssues();
|
|
1324
|
+
return {
|
|
1325
|
+
source,
|
|
1326
|
+
preferredSource,
|
|
1327
|
+
linearConnected,
|
|
1328
|
+
issues: listed.issues,
|
|
1329
|
+
viewer: {
|
|
1330
|
+
login: listed.viewer.name,
|
|
1331
|
+
name: listed.viewer.name
|
|
1332
|
+
}
|
|
1333
|
+
};
|
|
1259
1334
|
}
|
|
1260
|
-
const issues = await
|
|
1261
|
-
|
|
1335
|
+
const [issues, login] = await Promise.all([
|
|
1336
|
+
listGitHubIssues(repoPath),
|
|
1337
|
+
githubViewerLogin(repoPath)
|
|
1338
|
+
]);
|
|
1339
|
+
return {
|
|
1340
|
+
source,
|
|
1341
|
+
preferredSource,
|
|
1342
|
+
linearConnected,
|
|
1343
|
+
issues,
|
|
1344
|
+
viewer: login ? { login } : void 0
|
|
1345
|
+
};
|
|
1262
1346
|
}
|
|
1263
1347
|
|
|
1264
1348
|
// src/composer/diff-comment.ts
|
|
@@ -1346,6 +1430,12 @@ function buildPastedTextAttachment(text4, opts) {
|
|
|
1346
1430
|
}
|
|
1347
1431
|
|
|
1348
1432
|
// src/plan/ask-user.ts
|
|
1433
|
+
function planQuestionsSignature(questions) {
|
|
1434
|
+
return questions.map((q) => {
|
|
1435
|
+
const opts = q.options.map((o) => o.label).join("");
|
|
1436
|
+
return `${q.question}${opts}`;
|
|
1437
|
+
}).join("");
|
|
1438
|
+
}
|
|
1349
1439
|
function asRecord(v) {
|
|
1350
1440
|
return v != null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
1351
1441
|
}
|
|
@@ -1403,12 +1493,22 @@ function extractPendingPlanQuestions(parts) {
|
|
|
1403
1493
|
if (!questions.length) continue;
|
|
1404
1494
|
return {
|
|
1405
1495
|
id: p.id || `ask-${i}`,
|
|
1496
|
+
signature: planQuestionsSignature(questions),
|
|
1406
1497
|
questions,
|
|
1407
1498
|
source: p.name || "ask_user"
|
|
1408
1499
|
};
|
|
1409
1500
|
}
|
|
1410
1501
|
return null;
|
|
1411
1502
|
}
|
|
1503
|
+
function latestPendingPlanQuestions(input) {
|
|
1504
|
+
if (input.userReplied) return null;
|
|
1505
|
+
const fromLive = extractPendingPlanQuestions(input.liveParts);
|
|
1506
|
+
if (fromLive) return fromLive;
|
|
1507
|
+
const last = input.messages[input.messages.length - 1];
|
|
1508
|
+
if (last?.role === "user") return null;
|
|
1509
|
+
if (last?.role === "agent") return extractPendingPlanQuestions(last.parts);
|
|
1510
|
+
return null;
|
|
1511
|
+
}
|
|
1412
1512
|
function formatPlanQuestionAnswers(questions, answers) {
|
|
1413
1513
|
const lines = ["Answers to your questions:"];
|
|
1414
1514
|
for (let i = 0; i < questions.length; i++) {
|
|
@@ -1447,6 +1547,7 @@ function formatPlanQuestionsForChat(questions) {
|
|
|
1447
1547
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
1448
1548
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1449
1549
|
import { z as z4 } from "zod";
|
|
1550
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
1450
1551
|
import { basename } from "path";
|
|
1451
1552
|
|
|
1452
1553
|
// src/mcp/archive-guard.ts
|
|
@@ -1941,7 +2042,7 @@ function registerSlackTools(server) {
|
|
|
1941
2042
|
},
|
|
1942
2043
|
async ({ team_id }) => {
|
|
1943
2044
|
try {
|
|
1944
|
-
await
|
|
2045
|
+
await pollSlackOutboundWatches({ force: true });
|
|
1945
2046
|
const team = team_id?.trim();
|
|
1946
2047
|
const watches = listSlackOutboundWatches().filter(
|
|
1947
2048
|
(w) => !team || w.teamId === team
|
|
@@ -2229,6 +2330,283 @@ function registerScheduleTools(server) {
|
|
|
2229
2330
|
);
|
|
2230
2331
|
}
|
|
2231
2332
|
|
|
2333
|
+
// src/board/load-home-board.ts
|
|
2334
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
2335
|
+
import { join as join2 } from "path";
|
|
2336
|
+
|
|
2337
|
+
// src/board/board-pins.ts
|
|
2338
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2339
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
2340
|
+
import { join } from "path";
|
|
2341
|
+
var FILE = "home-board-pins.json";
|
|
2342
|
+
var VERSION = 1;
|
|
2343
|
+
function pinsFile() {
|
|
2344
|
+
return join(appDataDir(), FILE);
|
|
2345
|
+
}
|
|
2346
|
+
function readDisk() {
|
|
2347
|
+
const path2 = pinsFile();
|
|
2348
|
+
if (!existsSync(path2)) return [];
|
|
2349
|
+
try {
|
|
2350
|
+
const raw = JSON.parse(readFileSync(path2, "utf8"));
|
|
2351
|
+
if (raw?.version !== VERSION || !Array.isArray(raw.items)) return [];
|
|
2352
|
+
return raw.items.filter((item) => item?.id && item.kind && item.ref);
|
|
2353
|
+
} catch {
|
|
2354
|
+
return [];
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
function writeDisk(items) {
|
|
2358
|
+
mkdirSync(appDataDir(), { recursive: true });
|
|
2359
|
+
writeFileSync(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
|
|
2360
|
+
}
|
|
2361
|
+
function listBoardPins() {
|
|
2362
|
+
return readDisk();
|
|
2363
|
+
}
|
|
2364
|
+
function addBoardPin(input) {
|
|
2365
|
+
const ref = input.ref.trim();
|
|
2366
|
+
if (!ref) throw new Error("Board item needs a ref");
|
|
2367
|
+
const pin = {
|
|
2368
|
+
id: randomUUID2(),
|
|
2369
|
+
kind: input.kind,
|
|
2370
|
+
ref,
|
|
2371
|
+
repoPath: input.repoPath.trim(),
|
|
2372
|
+
addedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2373
|
+
title: input.title?.trim() || ref,
|
|
2374
|
+
url: input.url,
|
|
2375
|
+
labels: input.labels,
|
|
2376
|
+
provider: input.provider,
|
|
2377
|
+
assignee: input.assignee,
|
|
2378
|
+
cycle: input.cycle,
|
|
2379
|
+
teamKey: input.teamKey,
|
|
2380
|
+
headRefName: input.headRefName,
|
|
2381
|
+
author: input.author,
|
|
2382
|
+
remoteState: "open",
|
|
2383
|
+
needsWorkspacePick: issueNeedsWorkspacePick(
|
|
2384
|
+
input.provider,
|
|
2385
|
+
input.workspaceCount ?? 1
|
|
2386
|
+
)
|
|
2387
|
+
};
|
|
2388
|
+
const items = listBoardPins();
|
|
2389
|
+
const identity = boardPinIdentity(pin);
|
|
2390
|
+
const existing = items.find((item) => boardPinIdentity(item) === identity);
|
|
2391
|
+
if (existing) {
|
|
2392
|
+
const merged = { ...existing, ...pin, id: existing.id, addedAt: existing.addedAt };
|
|
2393
|
+
writeDisk(items.map((item) => item.id === existing.id ? merged : item));
|
|
2394
|
+
return merged;
|
|
2395
|
+
}
|
|
2396
|
+
writeDisk([...items, pin]);
|
|
2397
|
+
return pin;
|
|
2398
|
+
}
|
|
2399
|
+
function removeBoardPin(id) {
|
|
2400
|
+
const items = listBoardPins();
|
|
2401
|
+
const next = items.filter((item) => item.id !== id);
|
|
2402
|
+
if (next.length === items.length) return false;
|
|
2403
|
+
writeDisk(next);
|
|
2404
|
+
return true;
|
|
2405
|
+
}
|
|
2406
|
+
function replaceBoardPins(items) {
|
|
2407
|
+
writeDisk(items);
|
|
2408
|
+
}
|
|
2409
|
+
function clearBoardPins() {
|
|
2410
|
+
try {
|
|
2411
|
+
unlinkSync(pinsFile());
|
|
2412
|
+
} catch {
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
// src/board/load-home-board.ts
|
|
2417
|
+
var CACHE_VERSION = 1;
|
|
2418
|
+
var memory = null;
|
|
2419
|
+
var inflight = null;
|
|
2420
|
+
function errText(err) {
|
|
2421
|
+
return err instanceof Error ? err.message : String(err);
|
|
2422
|
+
}
|
|
2423
|
+
function homeBoardWorkspaceKey(workspaces) {
|
|
2424
|
+
return workspaces.map((w) => w.path).filter(Boolean).sort().join("\n");
|
|
2425
|
+
}
|
|
2426
|
+
function cacheFile() {
|
|
2427
|
+
return join2(appDataDir(), "home-board-cache.json");
|
|
2428
|
+
}
|
|
2429
|
+
function emptyInputs() {
|
|
2430
|
+
return {
|
|
2431
|
+
issues: [],
|
|
2432
|
+
prs: [],
|
|
2433
|
+
issueSource: "github",
|
|
2434
|
+
viewerLogin: void 0,
|
|
2435
|
+
issueErrors: [],
|
|
2436
|
+
prErrors: []
|
|
2437
|
+
};
|
|
2438
|
+
}
|
|
2439
|
+
function asLoaded(entry, fromCache) {
|
|
2440
|
+
const pins = syncBoardPins(listBoardPins(), entry.inputs.issues, entry.inputs.prs);
|
|
2441
|
+
return { ...entry.inputs, fetchedAt: entry.fetchedAt, fromCache, pins };
|
|
2442
|
+
}
|
|
2443
|
+
function cacheStillFresh(entry, key, now) {
|
|
2444
|
+
return entry.workspaceKey === key && now - entry.fetchedAt < HOME_BOARD_CACHE_TTL_MS;
|
|
2445
|
+
}
|
|
2446
|
+
function shouldCacheHomeBoardInputs(inputs) {
|
|
2447
|
+
const issuesFailed = inputs.issues.length === 0 && inputs.issueErrors.length > 0;
|
|
2448
|
+
const prsFailed = inputs.prs.length === 0 && inputs.prErrors.length > 0;
|
|
2449
|
+
return !(issuesFailed && prsFailed);
|
|
2450
|
+
}
|
|
2451
|
+
function readDiskCache() {
|
|
2452
|
+
const path2 = cacheFile();
|
|
2453
|
+
if (!existsSync2(path2)) return null;
|
|
2454
|
+
try {
|
|
2455
|
+
const raw = JSON.parse(readFileSync2(path2, "utf8"));
|
|
2456
|
+
if (raw?.version !== CACHE_VERSION || typeof raw.fetchedAt !== "number") {
|
|
2457
|
+
return null;
|
|
2458
|
+
}
|
|
2459
|
+
if (!raw.inputs || !Array.isArray(raw.inputs.issues) || !Array.isArray(raw.inputs.prs)) {
|
|
2460
|
+
return null;
|
|
2461
|
+
}
|
|
2462
|
+
return raw;
|
|
2463
|
+
} catch {
|
|
2464
|
+
return null;
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
function writeDiskCache(entry) {
|
|
2468
|
+
try {
|
|
2469
|
+
mkdirSync2(appDataDir(), { recursive: true });
|
|
2470
|
+
writeFileSync2(cacheFile(), JSON.stringify(entry), "utf8");
|
|
2471
|
+
} catch {
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
function deleteDiskCache() {
|
|
2475
|
+
try {
|
|
2476
|
+
unlinkSync2(cacheFile());
|
|
2477
|
+
} catch {
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
function resetHomeBoardMemory() {
|
|
2481
|
+
memory = null;
|
|
2482
|
+
inflight = null;
|
|
2483
|
+
}
|
|
2484
|
+
function clearHomeBoardCache() {
|
|
2485
|
+
resetHomeBoardMemory();
|
|
2486
|
+
deleteDiskCache();
|
|
2487
|
+
}
|
|
2488
|
+
async function loadHomeBoardInputs(workspaces) {
|
|
2489
|
+
const paths = workspaces.map((w) => w.path).filter(Boolean);
|
|
2490
|
+
if (paths.length === 0) return emptyInputs();
|
|
2491
|
+
const issueErrors = [];
|
|
2492
|
+
const prErrors = [];
|
|
2493
|
+
let issueSource = "github";
|
|
2494
|
+
let viewerLogin;
|
|
2495
|
+
let issues = [];
|
|
2496
|
+
try {
|
|
2497
|
+
const first = await listIssues(paths[0]);
|
|
2498
|
+
issueSource = first.source;
|
|
2499
|
+
viewerLogin = first.viewer?.login || first.viewer?.name || void 0;
|
|
2500
|
+
if (first.source === "linear") {
|
|
2501
|
+
const repoPath = paths[0] ?? "";
|
|
2502
|
+
issues = first.issues.map((issue) => ({
|
|
2503
|
+
...issue,
|
|
2504
|
+
repoPath,
|
|
2505
|
+
needsWorkspacePick: issueNeedsWorkspacePick(
|
|
2506
|
+
issue.provider ?? first.source,
|
|
2507
|
+
paths.length
|
|
2508
|
+
)
|
|
2509
|
+
}));
|
|
2510
|
+
} else {
|
|
2511
|
+
const settled = await Promise.allSettled(
|
|
2512
|
+
paths.map(async (path2) => {
|
|
2513
|
+
const result = path2 === paths[0] ? first : await listIssues(path2);
|
|
2514
|
+
return result.issues.map((issue) => ({
|
|
2515
|
+
...issue,
|
|
2516
|
+
repoPath: path2,
|
|
2517
|
+
needsWorkspacePick: issueNeedsWorkspacePick(
|
|
2518
|
+
issue.provider ?? result.source,
|
|
2519
|
+
1
|
|
2520
|
+
)
|
|
2521
|
+
}));
|
|
2522
|
+
})
|
|
2523
|
+
);
|
|
2524
|
+
const collected = [];
|
|
2525
|
+
for (const item of settled) {
|
|
2526
|
+
if (item.status === "fulfilled") collected.push(...item.value);
|
|
2527
|
+
else issueErrors.push(errText(item.reason));
|
|
2528
|
+
}
|
|
2529
|
+
issues = collected;
|
|
2530
|
+
if (collected.length === 0 && issueErrors[0]) {
|
|
2531
|
+
throw new Error(issueErrors[0]);
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
issues = dedupeBoardIssues(issues);
|
|
2535
|
+
} catch (err) {
|
|
2536
|
+
issueErrors.push(errText(err));
|
|
2537
|
+
issues = [];
|
|
2538
|
+
}
|
|
2539
|
+
let prs = [];
|
|
2540
|
+
try {
|
|
2541
|
+
const settled = await Promise.allSettled(
|
|
2542
|
+
paths.map(async (path2) => {
|
|
2543
|
+
const list = await listPrs(path2);
|
|
2544
|
+
return list.map((pr) => ({ ...pr, repoPath: path2 }));
|
|
2545
|
+
})
|
|
2546
|
+
);
|
|
2547
|
+
const collected = [];
|
|
2548
|
+
for (const item of settled) {
|
|
2549
|
+
if (item.status === "fulfilled") collected.push(...item.value);
|
|
2550
|
+
else prErrors.push(errText(item.reason));
|
|
2551
|
+
}
|
|
2552
|
+
if (collected.length === 0 && prErrors[0]) {
|
|
2553
|
+
throw new Error(prErrors[0]);
|
|
2554
|
+
}
|
|
2555
|
+
prs = dedupeBoardPrs(collected);
|
|
2556
|
+
} catch (err) {
|
|
2557
|
+
prErrors.push(errText(err));
|
|
2558
|
+
prs = [];
|
|
2559
|
+
}
|
|
2560
|
+
return { issues, prs, issueSource, viewerLogin, issueErrors, prErrors };
|
|
2561
|
+
}
|
|
2562
|
+
async function getHomeBoardInputs(workspaces, opts) {
|
|
2563
|
+
const key = homeBoardWorkspaceKey(workspaces);
|
|
2564
|
+
const now = opts?.now ?? Date.now();
|
|
2565
|
+
if (!key) {
|
|
2566
|
+
return {
|
|
2567
|
+
...emptyInputs(),
|
|
2568
|
+
fetchedAt: now,
|
|
2569
|
+
fromCache: false,
|
|
2570
|
+
pins: listBoardPins()
|
|
2571
|
+
};
|
|
2572
|
+
}
|
|
2573
|
+
if (!opts?.refresh) {
|
|
2574
|
+
const disk = readDiskCache();
|
|
2575
|
+
const best = memory && disk ? disk.fetchedAt >= memory.fetchedAt ? disk : memory : memory ?? disk;
|
|
2576
|
+
if (best && cacheStillFresh(best, key, now)) {
|
|
2577
|
+
memory = best;
|
|
2578
|
+
return asLoaded(best, true);
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
if (inflight && inflight.key === key) {
|
|
2582
|
+
return inflight.promise;
|
|
2583
|
+
}
|
|
2584
|
+
const promise = (async () => {
|
|
2585
|
+
const inputs = await loadHomeBoardInputs(workspaces);
|
|
2586
|
+
const fetchedAt = opts?.now ?? Date.now();
|
|
2587
|
+
const pins = syncBoardPins(listBoardPins(), inputs.issues, inputs.prs);
|
|
2588
|
+
replaceBoardPins(pins);
|
|
2589
|
+
const loaded = { ...inputs, fetchedAt, fromCache: false, pins };
|
|
2590
|
+
if (shouldCacheHomeBoardInputs(inputs)) {
|
|
2591
|
+
const entry = {
|
|
2592
|
+
version: CACHE_VERSION,
|
|
2593
|
+
workspaceKey: key,
|
|
2594
|
+
fetchedAt,
|
|
2595
|
+
inputs
|
|
2596
|
+
};
|
|
2597
|
+
memory = entry;
|
|
2598
|
+
writeDiskCache(entry);
|
|
2599
|
+
}
|
|
2600
|
+
return loaded;
|
|
2601
|
+
})();
|
|
2602
|
+
inflight = { key, promise };
|
|
2603
|
+
try {
|
|
2604
|
+
return await promise;
|
|
2605
|
+
} finally {
|
|
2606
|
+
if (inflight?.promise === promise) inflight = null;
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2232
2610
|
// src/mcp/server.ts
|
|
2233
2611
|
var MAX_ORCH_THREADS = 5;
|
|
2234
2612
|
var CREATE_THREAD_TIMEOUT_MS = 9e4;
|
|
@@ -2249,6 +2627,93 @@ function withTimeout(promise, ms, label) {
|
|
|
2249
2627
|
);
|
|
2250
2628
|
});
|
|
2251
2629
|
}
|
|
2630
|
+
async function createOrchChildThread(orch, args, resolveNewThreadOptions2) {
|
|
2631
|
+
const envParentId = process.env.SIDEBOARD_ORCHESTRATOR_THREAD_ID?.trim() || "";
|
|
2632
|
+
let parentId = args.parentThreadId?.trim() || "";
|
|
2633
|
+
let parent = parentId ? orch.getThread(parentId) : null;
|
|
2634
|
+
let parentCorrectedFrom;
|
|
2635
|
+
if (envParentId) {
|
|
2636
|
+
const envParent = orch.getThread(envParentId);
|
|
2637
|
+
if (envParent) {
|
|
2638
|
+
if (parentId && parentId !== envParentId) parentCorrectedFrom = parentId;
|
|
2639
|
+
else if (!parentId) parentCorrectedFrom = void 0;
|
|
2640
|
+
parentId = envParentId;
|
|
2641
|
+
parent = envParent;
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
if (parentId && !parent) {
|
|
2645
|
+
parentCorrectedFrom = parentId;
|
|
2646
|
+
parentId = "";
|
|
2647
|
+
parent = null;
|
|
2648
|
+
}
|
|
2649
|
+
if (parentId) {
|
|
2650
|
+
const children = orch.getThreads(false).filter((t) => t.parentThreadId === parentId);
|
|
2651
|
+
if (children.length >= MAX_ORCH_THREADS) {
|
|
2652
|
+
return {
|
|
2653
|
+
ok: false,
|
|
2654
|
+
text: `Thread-creation cap (${MAX_ORCH_THREADS}) reached for this orchestration session`
|
|
2655
|
+
};
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
let agentArg = args.agent;
|
|
2659
|
+
let agentCoercedFrom;
|
|
2660
|
+
const resolvedProbe = resolveNewThreadOptions2({ agent: agentArg }).agent;
|
|
2661
|
+
if (resolvedProbe === "codex") {
|
|
2662
|
+
agentCoercedFrom = agentArg ?? "codex";
|
|
2663
|
+
const accountAgent = resolveNewThreadOptions2({}).agent;
|
|
2664
|
+
agentArg = accountAgent !== "codex" ? accountAgent : "cursor";
|
|
2665
|
+
}
|
|
2666
|
+
const opts = resolveNewThreadOptions2({
|
|
2667
|
+
agent: agentArg,
|
|
2668
|
+
model: args.model
|
|
2669
|
+
});
|
|
2670
|
+
try {
|
|
2671
|
+
const priorIds = new Set(orch.getThreads(false).map((t) => t.id));
|
|
2672
|
+
const thread = await withTimeout(
|
|
2673
|
+
orch.createThread({
|
|
2674
|
+
sourceType: args.sourceType,
|
|
2675
|
+
sourceRef: args.sourceRef,
|
|
2676
|
+
agent: opts.agent,
|
|
2677
|
+
model: opts.model,
|
|
2678
|
+
effort: opts.effort,
|
|
2679
|
+
fast: opts.fast,
|
|
2680
|
+
repoPath: args.repoPath,
|
|
2681
|
+
title: args.title,
|
|
2682
|
+
parentThreadId: parentId || null,
|
|
2683
|
+
cowboy: args.cowboy || void 0,
|
|
2684
|
+
attachments: args.attachments
|
|
2685
|
+
}),
|
|
2686
|
+
CREATE_THREAD_TIMEOUT_MS,
|
|
2687
|
+
"create_thread"
|
|
2688
|
+
);
|
|
2689
|
+
const alreadyStarted = priorIds.has(thread.id);
|
|
2690
|
+
const parentNote = parentCorrectedFrom ? parentId ? `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; nested under ${parentId}` : `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; created without parent` : void 0;
|
|
2691
|
+
return {
|
|
2692
|
+
ok: true,
|
|
2693
|
+
text: JSON.stringify({
|
|
2694
|
+
id: thread.id,
|
|
2695
|
+
title: thread.title,
|
|
2696
|
+
branchName: thread.branchName,
|
|
2697
|
+
worktreePath: thread.worktreePath,
|
|
2698
|
+
agent: thread.agent,
|
|
2699
|
+
model: thread.model,
|
|
2700
|
+
status: thread.status,
|
|
2701
|
+
cowboy: Boolean(thread.cowboy),
|
|
2702
|
+
link: `sideboard://thread/${thread.id}`,
|
|
2703
|
+
parentThreadId: thread.parentThreadId,
|
|
2704
|
+
...alreadyStarted ? { alreadyStarted: true } : {},
|
|
2705
|
+
...agentCoercedFrom ? {
|
|
2706
|
+
agentCoercedFrom,
|
|
2707
|
+
note: `Avoid nested Codex under a Codex orchestrator \u2014 used Account default agent=${thread.agent}`
|
|
2708
|
+
} : {},
|
|
2709
|
+
...parentCorrectedFrom ? { parentCorrectedFrom, parentNote } : {}
|
|
2710
|
+
})
|
|
2711
|
+
};
|
|
2712
|
+
} catch (err) {
|
|
2713
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2714
|
+
return { ok: false, text: `create_thread failed: ${message}` };
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2252
2717
|
async function startMcpServer() {
|
|
2253
2718
|
const orch = getOrchestrator();
|
|
2254
2719
|
try {
|
|
@@ -2260,7 +2725,7 @@ async function startMcpServer() {
|
|
|
2260
2725
|
);
|
|
2261
2726
|
}
|
|
2262
2727
|
try {
|
|
2263
|
-
const { maxConcurrentAgents: maxConcurrentAgents2 } = await import("./app-settings-
|
|
2728
|
+
const { maxConcurrentAgents: maxConcurrentAgents2 } = await import("./app-settings-6RPALX4J.js");
|
|
2264
2729
|
orch.setMaxConcurrent(maxConcurrentAgents2());
|
|
2265
2730
|
} catch {
|
|
2266
2731
|
}
|
|
@@ -2280,7 +2745,7 @@ async function startMcpServer() {
|
|
|
2280
2745
|
if (!worktreeProfile) {
|
|
2281
2746
|
server.tool(
|
|
2282
2747
|
"list_workspaces",
|
|
2283
|
-
"List registered Sideboard workspaces (repos). Each line is name, path, and github:owner/repo when resolvable \u2014 use path as repoPath for list_branches/list_prs/list_issues/create_thread.",
|
|
2748
|
+
"List registered Sideboard workspaces (repos). Each line is name, path, and github:owner/repo when resolvable \u2014 use path as repoPath for list_board/list_branches/list_prs/list_issues/create_thread.",
|
|
2284
2749
|
{},
|
|
2285
2750
|
async () => {
|
|
2286
2751
|
const workspaces = orch.listWorkspaces();
|
|
@@ -2314,6 +2779,51 @@ async function startMcpServer() {
|
|
|
2314
2779
|
};
|
|
2315
2780
|
}
|
|
2316
2781
|
);
|
|
2782
|
+
server.tool(
|
|
2783
|
+
"list_board",
|
|
2784
|
+
"Home Kanban of worktrees (New, Draft, Review, Merged) \u2014 one card per checkout; sibling chat tabs nest as inner cards. Same cards as desktop Home. 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 (ticket/PR/branch source), column, limit (default 40). create_thread adds a worktree (and a Home card), or returns the live one if that ticket/PR/named branch is already checked out.",
|
|
2785
|
+
{
|
|
2786
|
+
query: z4.string().optional().describe("Case-insensitive token search across title, id, labels, repo"),
|
|
2787
|
+
repoPath: z4.string().optional().describe("Limit to one workspace path from list_workspaces"),
|
|
2788
|
+
kind: z4.enum(["all", "tickets", "prs", "branches", "threads"]).optional().describe("Filter by worktree source (default all)"),
|
|
2789
|
+
column: z4.enum(["new", "draft", "review", "done", "needs_you"]).optional().describe(
|
|
2790
|
+
"Return cards for this column only (totals still include the rest). needs_you is a legacy alias for new."
|
|
2791
|
+
),
|
|
2792
|
+
limit: z4.number().int().positive().optional().describe("Max cards per column (default 40). hidden counts the remainder.")
|
|
2793
|
+
},
|
|
2794
|
+
async ({ query, repoPath, kind, column, limit }) => {
|
|
2795
|
+
const workspaces = orch.listWorkspaces();
|
|
2796
|
+
const all = orch.getThreads(true);
|
|
2797
|
+
const names = new Map(workspaces.map((w) => [w.path, w.name]));
|
|
2798
|
+
const snap = assembleHomeBoard({
|
|
2799
|
+
threads: all.filter((t) => t.status !== "archived"),
|
|
2800
|
+
query,
|
|
2801
|
+
repoPath,
|
|
2802
|
+
kind: kind ?? "all",
|
|
2803
|
+
column: column === "needs_you" ? "new" : column,
|
|
2804
|
+
limit,
|
|
2805
|
+
workspaceName: (path2) => names.get(path2) ?? ""
|
|
2806
|
+
});
|
|
2807
|
+
return {
|
|
2808
|
+
content: [
|
|
2809
|
+
{
|
|
2810
|
+
type: "text",
|
|
2811
|
+
text: JSON.stringify(
|
|
2812
|
+
{
|
|
2813
|
+
columns: snap.columns,
|
|
2814
|
+
hidden: snap.hidden,
|
|
2815
|
+
totals: snap.totals,
|
|
2816
|
+
columnDefs: BOARD_COLUMN_DEFS,
|
|
2817
|
+
hint: HOME_BOARD_AGENT_HINT
|
|
2818
|
+
},
|
|
2819
|
+
null,
|
|
2820
|
+
2
|
|
2821
|
+
)
|
|
2822
|
+
}
|
|
2823
|
+
]
|
|
2824
|
+
};
|
|
2825
|
+
}
|
|
2826
|
+
);
|
|
2317
2827
|
server.tool(
|
|
2318
2828
|
"get_thread",
|
|
2319
2829
|
"Get a compact thread summary by id/ref. While running, includes progress (last tool/thinking) and lastActivityAt. Includes usage (thread billed token + costUsd totals when providers reported cost) and lastTurnUsage.",
|
|
@@ -2483,7 +2993,7 @@ async function startMcpServer() {
|
|
|
2483
2993
|
registerLinearTools(server);
|
|
2484
2994
|
registerScheduleTools(server);
|
|
2485
2995
|
const { getCaffeinateHold: getCaffeinateHold2, setCaffeinateHold: setCaffeinateHold2 } = await import("./caffeinate-hold-X3JNPR42.js");
|
|
2486
|
-
const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await import("./app-settings-
|
|
2996
|
+
const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await import("./app-settings-6RPALX4J.js");
|
|
2487
2997
|
const accountDefaults = resolveThreadDefaults2();
|
|
2488
2998
|
const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
|
|
2489
2999
|
server.tool(
|
|
@@ -2526,7 +3036,7 @@ async function startMcpServer() {
|
|
|
2526
3036
|
);
|
|
2527
3037
|
server.tool(
|
|
2528
3038
|
"create_thread",
|
|
2529
|
-
`Create a
|
|
3039
|
+
`Create a worktree thread (chat) from branch, pr, or ticket. If a live worktree already matches that ticket, PR, or named branch, returns it (alreadyStarted=true) instead of a second checkout. Creating from the default branch still opens a new isolated worktree. Pass repoPath from list_workspaces. cowboy=true uses the project folder on the default branch (no isolated worktree; land is commit+push). From an orchestration chat, omit parentThreadId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Prefer omitting agent/model so Sideboard applies ${accountDefaultsHint}. Setup (settings.toml, .cursor/worktrees.json, or script/setup) runs in the background in parallel with the first turn (skipped for cowboy). Then use send_to_thread to chat.`,
|
|
2530
3040
|
{
|
|
2531
3041
|
sourceType: z4.enum(["branch", "pr", "ticket"]),
|
|
2532
3042
|
sourceRef: z4.string(),
|
|
@@ -2544,104 +3054,118 @@ async function startMcpServer() {
|
|
|
2544
3054
|
)
|
|
2545
3055
|
},
|
|
2546
3056
|
async (args) => {
|
|
2547
|
-
const
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
}
|
|
2579
|
-
let agentArg = args.agent;
|
|
2580
|
-
let agentCoercedFrom;
|
|
2581
|
-
const resolvedProbe = resolveNewThreadOptions2({ agent: agentArg }).agent;
|
|
2582
|
-
if (resolvedProbe === "codex") {
|
|
2583
|
-
agentCoercedFrom = agentArg ?? "codex";
|
|
2584
|
-
const accountAgent = resolveNewThreadOptions2({}).agent;
|
|
2585
|
-
agentArg = accountAgent !== "codex" ? accountAgent : "cursor";
|
|
2586
|
-
}
|
|
2587
|
-
const opts = resolveNewThreadOptions2({
|
|
2588
|
-
agent: agentArg,
|
|
2589
|
-
model: args.model
|
|
2590
|
-
});
|
|
2591
|
-
try {
|
|
2592
|
-
const thread = await withTimeout(
|
|
2593
|
-
orch.createThread({
|
|
2594
|
-
sourceType: args.sourceType,
|
|
2595
|
-
sourceRef: args.sourceRef,
|
|
2596
|
-
agent: opts.agent,
|
|
2597
|
-
model: opts.model,
|
|
2598
|
-
effort: opts.effort,
|
|
2599
|
-
fast: opts.fast,
|
|
2600
|
-
repoPath: args.repoPath,
|
|
2601
|
-
title: args.title,
|
|
2602
|
-
parentThreadId: parentId || null,
|
|
2603
|
-
cowboy: args.cowboy || void 0
|
|
2604
|
-
}),
|
|
2605
|
-
CREATE_THREAD_TIMEOUT_MS,
|
|
2606
|
-
"create_thread"
|
|
2607
|
-
);
|
|
2608
|
-
const parentNote = parentCorrectedFrom ? parentId ? `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; nested under ${parentId}` : `Ignored unknown/stale parentThreadId ${parentCorrectedFrom}; created without parent` : void 0;
|
|
3057
|
+
const result = await createOrchChildThread(orch, args, resolveNewThreadOptions2);
|
|
3058
|
+
return {
|
|
3059
|
+
content: [{ type: "text", text: result.text }],
|
|
3060
|
+
...result.ok ? {} : { isError: true }
|
|
3061
|
+
};
|
|
3062
|
+
}
|
|
3063
|
+
);
|
|
3064
|
+
server.tool(
|
|
3065
|
+
"start_board_card",
|
|
3066
|
+
"Same as create_thread for a ticket, PR, or named branch (attaches issue text when Sideboard can resolve it). Reuses the live worktree if one already matches. Then send_to_thread.",
|
|
3067
|
+
{
|
|
3068
|
+
kind: z4.enum(["ticket", "pr", "branch"]),
|
|
3069
|
+
ref: z4.string().describe("Ticket identifier (ENG-12), PR number (44), or branch name from list_board"),
|
|
3070
|
+
repoPath: z4.string().describe("Workspace path from list_workspaces / list_board"),
|
|
3071
|
+
title: z4.string().optional()
|
|
3072
|
+
},
|
|
3073
|
+
async ({ kind, ref, repoPath, title }) => {
|
|
3074
|
+
const root = await resolveRepoRoot(repoPath);
|
|
3075
|
+
const existing = findLiveThreadForCreate(
|
|
3076
|
+
{
|
|
3077
|
+
sourceType: kind,
|
|
3078
|
+
sourceRef: ref.trim(),
|
|
3079
|
+
repoPath: canonicalizeRepoPath(root),
|
|
3080
|
+
title: title?.trim()
|
|
3081
|
+
},
|
|
3082
|
+
orch.getThreads(false).map((t) => ({
|
|
3083
|
+
...t,
|
|
3084
|
+
repoPath: canonicalizeRepoPath(t.repoPath)
|
|
3085
|
+
}))
|
|
3086
|
+
);
|
|
3087
|
+
if (existing) {
|
|
2609
3088
|
return {
|
|
2610
3089
|
content: [
|
|
2611
3090
|
{
|
|
2612
3091
|
type: "text",
|
|
2613
3092
|
text: JSON.stringify({
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
model: thread.model,
|
|
2620
|
-
status: thread.status,
|
|
2621
|
-
cowboy: Boolean(thread.cowboy),
|
|
2622
|
-
link: `sideboard://thread/${thread.id}`,
|
|
2623
|
-
parentThreadId: thread.parentThreadId,
|
|
2624
|
-
...agentCoercedFrom ? {
|
|
2625
|
-
agentCoercedFrom,
|
|
2626
|
-
note: `Avoid nested Codex under a Codex orchestrator \u2014 used Account default agent=${thread.agent}`
|
|
2627
|
-
} : {},
|
|
2628
|
-
...parentCorrectedFrom ? { parentCorrectedFrom, parentNote } : {}
|
|
3093
|
+
alreadyStarted: true,
|
|
3094
|
+
id: existing.id,
|
|
3095
|
+
title: existing.title,
|
|
3096
|
+
status: existing.status,
|
|
3097
|
+
link: `sideboard://thread/${existing.id}`
|
|
2629
3098
|
})
|
|
2630
3099
|
}
|
|
2631
3100
|
]
|
|
2632
3101
|
};
|
|
2633
|
-
}
|
|
2634
|
-
|
|
3102
|
+
}
|
|
3103
|
+
const workspaces = orch.listWorkspaces();
|
|
3104
|
+
const loaded = await getHomeBoardInputs(workspaces);
|
|
3105
|
+
const pin = findBoardPin(loaded.pins, kind, ref, root);
|
|
3106
|
+
if (kind === "branch") {
|
|
3107
|
+
const sourceRef = pin?.ref === "default" ? "default" : pin?.ref ?? ref.trim();
|
|
3108
|
+
const result2 = await createOrchChildThread(
|
|
3109
|
+
orch,
|
|
3110
|
+
{
|
|
3111
|
+
sourceType: "branch",
|
|
3112
|
+
sourceRef,
|
|
3113
|
+
repoPath: root,
|
|
3114
|
+
title: title?.trim() || pin?.title || (sourceRef === "default" ? void 0 : sourceRef)
|
|
3115
|
+
},
|
|
3116
|
+
resolveNewThreadOptions2
|
|
3117
|
+
);
|
|
2635
3118
|
return {
|
|
2636
|
-
content: [
|
|
2637
|
-
|
|
2638
|
-
type: "text",
|
|
2639
|
-
text: `create_thread failed: ${message}`
|
|
2640
|
-
}
|
|
2641
|
-
],
|
|
2642
|
-
isError: true
|
|
3119
|
+
content: [{ type: "text", text: result2.text }],
|
|
3120
|
+
...result2.ok ? {} : { isError: true }
|
|
2643
3121
|
};
|
|
2644
3122
|
}
|
|
3123
|
+
if (kind === "ticket") {
|
|
3124
|
+
const issue = findBoardIssue(loaded.issues, ref, root);
|
|
3125
|
+
const ident = issue?.identifier ?? ref.trim();
|
|
3126
|
+
const attachments = issue ? [
|
|
3127
|
+
{
|
|
3128
|
+
id: randomUUID3(),
|
|
3129
|
+
name: issue.identifier,
|
|
3130
|
+
kind: "issue",
|
|
3131
|
+
content: [
|
|
3132
|
+
`Linked issue: ${issue.identifier} \u2014 ${issue.title}`,
|
|
3133
|
+
issue.url ? `URL: ${issue.url}` : null
|
|
3134
|
+
].filter(Boolean).join("\n")
|
|
3135
|
+
}
|
|
3136
|
+
] : void 0;
|
|
3137
|
+
const result2 = await createOrchChildThread(
|
|
3138
|
+
orch,
|
|
3139
|
+
{
|
|
3140
|
+
sourceType: "ticket",
|
|
3141
|
+
sourceRef: ident,
|
|
3142
|
+
repoPath: root,
|
|
3143
|
+
title: title?.trim() || issue?.title,
|
|
3144
|
+
attachments
|
|
3145
|
+
},
|
|
3146
|
+
resolveNewThreadOptions2
|
|
3147
|
+
);
|
|
3148
|
+
return {
|
|
3149
|
+
content: [{ type: "text", text: result2.text }],
|
|
3150
|
+
...result2.ok ? {} : { isError: true }
|
|
3151
|
+
};
|
|
3152
|
+
}
|
|
3153
|
+
const pr = findBoardPr(loaded.prs, ref, root);
|
|
3154
|
+
const number = pr ? String(pr.number) : ref.trim().replace(/^#/, "");
|
|
3155
|
+
const result = await createOrchChildThread(
|
|
3156
|
+
orch,
|
|
3157
|
+
{
|
|
3158
|
+
sourceType: "pr",
|
|
3159
|
+
sourceRef: number,
|
|
3160
|
+
repoPath: root,
|
|
3161
|
+
title: title?.trim() || pr?.title
|
|
3162
|
+
},
|
|
3163
|
+
resolveNewThreadOptions2
|
|
3164
|
+
);
|
|
3165
|
+
return {
|
|
3166
|
+
content: [{ type: "text", text: result.text }],
|
|
3167
|
+
...result.ok ? {} : { isError: true }
|
|
3168
|
+
};
|
|
2645
3169
|
}
|
|
2646
3170
|
);
|
|
2647
3171
|
server.tool(
|
|
@@ -3288,7 +3812,7 @@ async function startMcpServer() {
|
|
|
3288
3812
|
);
|
|
3289
3813
|
server.tool(
|
|
3290
3814
|
"list_issues",
|
|
3291
|
-
"List issues from Sideboard Account connections (Linear API or GitHub Issues; Linear\u2192GitHub fallback when Linear is not connected). Pass repoPath from list_workspaces \u2014 GitHub Issues are scoped to that repo. Then create_thread with sourceType=ticket.",
|
|
3815
|
+
"List issues from Sideboard Account connections (Linear API or GitHub Issues; Linear\u2192GitHub fallback when Linear is not connected). Linear returns issues assigned to you (includes cycle). Pass repoPath from list_workspaces \u2014 GitHub Issues are scoped to that repo. Prefer list_board for Home columns + current-cycle filter. Then create_thread with sourceType=ticket.",
|
|
3292
3816
|
{ repoPath: z4.string() },
|
|
3293
3817
|
async ({ repoPath }) => {
|
|
3294
3818
|
const root = await resolveRepoRoot(repoPath);
|
|
@@ -3630,14 +4154,14 @@ async function runCloudConnect(opts) {
|
|
|
3630
4154
|
}
|
|
3631
4155
|
|
|
3632
4156
|
// src/agents/user-mcp-config.ts
|
|
3633
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
4157
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
3634
4158
|
import { homedir } from "os";
|
|
3635
|
-
import { dirname, join } from "path";
|
|
4159
|
+
import { dirname, join as join3 } from "path";
|
|
3636
4160
|
function userCursorMcpConfigPath() {
|
|
3637
|
-
return
|
|
4161
|
+
return join3(homedir(), ".cursor", "mcp.json");
|
|
3638
4162
|
}
|
|
3639
4163
|
function userClaudeMcpConfigPath() {
|
|
3640
|
-
return
|
|
4164
|
+
return join3(homedir(), ".claude.json");
|
|
3641
4165
|
}
|
|
3642
4166
|
function asObject(value) {
|
|
3643
4167
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
@@ -3664,16 +4188,16 @@ function mergeSideboardIntoMcpServersJson(existing, sideboard) {
|
|
|
3664
4188
|
}
|
|
3665
4189
|
function writeMergedMcpServersJson(configPath, sideboard) {
|
|
3666
4190
|
let existing = {};
|
|
3667
|
-
if (
|
|
4191
|
+
if (existsSync3(configPath)) {
|
|
3668
4192
|
try {
|
|
3669
|
-
existing = JSON.parse(
|
|
4193
|
+
existing = JSON.parse(readFileSync3(configPath, "utf8"));
|
|
3670
4194
|
} catch {
|
|
3671
4195
|
existing = {};
|
|
3672
4196
|
}
|
|
3673
4197
|
}
|
|
3674
4198
|
const next = mergeSideboardIntoMcpServersJson(existing, sideboard);
|
|
3675
|
-
|
|
3676
|
-
|
|
4199
|
+
mkdirSync3(dirname(configPath), { recursive: true });
|
|
4200
|
+
writeFileSync3(configPath, `${JSON.stringify(next, null, 2)}
|
|
3677
4201
|
`);
|
|
3678
4202
|
}
|
|
3679
4203
|
function launchFromResolved(server) {
|
|
@@ -3691,7 +4215,7 @@ async function registerPackagedUserMcpClients() {
|
|
|
3691
4215
|
const cursor = userCursorMcpConfigPath();
|
|
3692
4216
|
writeMergedMcpServersJson(cursor, launch);
|
|
3693
4217
|
const claude = userClaudeMcpConfigPath();
|
|
3694
|
-
if (
|
|
4218
|
+
if (existsSync3(claude)) {
|
|
3695
4219
|
writeMergedMcpServersJson(claude, launch);
|
|
3696
4220
|
return { cursor, claude };
|
|
3697
4221
|
}
|
|
@@ -5620,6 +6144,8 @@ export {
|
|
|
5620
6144
|
GITHUB_GIT_AUTH_MODES,
|
|
5621
6145
|
GLOBAL_WORKSPACE_ID,
|
|
5622
6146
|
HARNESS_ENV_KEYS,
|
|
6147
|
+
HOME_BOARD_CACHE_TTL_MS,
|
|
6148
|
+
ISSUE_SOURCE_LABELS,
|
|
5623
6149
|
LEGACY_ATTACHMENTS_DIR,
|
|
5624
6150
|
LEGACY_PLAN_FILE_REL,
|
|
5625
6151
|
LEGACY_REVIEW_REQUEST_PATH,
|
|
@@ -5661,6 +6187,7 @@ export {
|
|
|
5661
6187
|
THINKING_EFFORTS,
|
|
5662
6188
|
WORKTREE_MCP_TOOLS,
|
|
5663
6189
|
ackSlackInboundSeen,
|
|
6190
|
+
addBoardPin,
|
|
5664
6191
|
addPrStackLayer,
|
|
5665
6192
|
addStackLayerFromThread,
|
|
5666
6193
|
addWorkspace,
|
|
@@ -5714,15 +6241,19 @@ export {
|
|
|
5714
6241
|
caffeinateWhileRunningEnabled,
|
|
5715
6242
|
caffeinateWhileSchedulesEnabled,
|
|
5716
6243
|
caffeinateWhileSlackListenEnabled,
|
|
6244
|
+
canonicalizeRepoPath,
|
|
5717
6245
|
captureLoginEnv,
|
|
5718
6246
|
captureTurnBaseline,
|
|
5719
6247
|
checkoutPrStackLayer,
|
|
5720
6248
|
childEnvWithAppSettings,
|
|
5721
6249
|
claimDesktopHost,
|
|
6250
|
+
classifyWorktreeColumn,
|
|
5722
6251
|
claudeAdapter,
|
|
5723
6252
|
claudeChromeEnabled,
|
|
5724
6253
|
claudeUserSettingsPath,
|
|
5725
6254
|
cleanupOrphanWorktrees,
|
|
6255
|
+
clearBoardPins,
|
|
6256
|
+
clearHomeBoardCache,
|
|
5726
6257
|
cloneRepoIntoSideboard,
|
|
5727
6258
|
codexAdapter,
|
|
5728
6259
|
codexSandboxWritableRootsArgs,
|
|
@@ -5771,7 +6302,6 @@ export {
|
|
|
5771
6302
|
disconnectLinearConnection,
|
|
5772
6303
|
disconnectSlackWorkspace,
|
|
5773
6304
|
discoverSkills,
|
|
5774
|
-
dismissSlackReplyBadge,
|
|
5775
6305
|
dropCachedPrefixOnResume,
|
|
5776
6306
|
encodeBrightsyTarget,
|
|
5777
6307
|
enrichPathWithNpmGlobalBin,
|
|
@@ -5796,6 +6326,7 @@ export {
|
|
|
5796
6326
|
finalizeParts,
|
|
5797
6327
|
findConventionSetup,
|
|
5798
6328
|
findInvalidCacheControlTtlOrder,
|
|
6329
|
+
findLiveThreadForCreate,
|
|
5799
6330
|
findOrphanWorktrees,
|
|
5800
6331
|
findSlackCoordinator,
|
|
5801
6332
|
findThreadByRef,
|
|
@@ -5847,6 +6378,7 @@ export {
|
|
|
5847
6378
|
getGitHubStatus,
|
|
5848
6379
|
getGithubGitAuthMode,
|
|
5849
6380
|
getGithubPat,
|
|
6381
|
+
getHomeBoardInputs,
|
|
5850
6382
|
getIssueSource,
|
|
5851
6383
|
getLinearApiKey,
|
|
5852
6384
|
getLinearAuthToken,
|
|
@@ -5869,6 +6401,7 @@ export {
|
|
|
5869
6401
|
git,
|
|
5870
6402
|
githubAgentGitEnv,
|
|
5871
6403
|
globalAgentCwd,
|
|
6404
|
+
groupHomeBoardWorktrees,
|
|
5872
6405
|
handleSlackInbound,
|
|
5873
6406
|
harnessEnvKey,
|
|
5874
6407
|
hasBakedLinearOAuth,
|
|
@@ -5902,9 +6435,11 @@ export {
|
|
|
5902
6435
|
isGhRateLimitError,
|
|
5903
6436
|
isGlobalRepoPath,
|
|
5904
6437
|
isGlobalThread,
|
|
6438
|
+
isHomeBoardThread,
|
|
5905
6439
|
isImageFilePath,
|
|
5906
6440
|
isInPrStack,
|
|
5907
6441
|
isInboundForThisDesktop,
|
|
6442
|
+
isIssueSourceConnected,
|
|
5908
6443
|
isLinearConnected,
|
|
5909
6444
|
isLinearOAuthCancelled,
|
|
5910
6445
|
isOrchestratorCapableAgent,
|
|
@@ -5927,12 +6462,16 @@ export {
|
|
|
5927
6462
|
isThreadCaffeinated,
|
|
5928
6463
|
isThreadRecordFile,
|
|
5929
6464
|
isWorkspaceScratchPath,
|
|
6465
|
+
issueSourceLabel,
|
|
5930
6466
|
lastRequestOccupancy,
|
|
6467
|
+
latestPendingPlanQuestions,
|
|
5931
6468
|
linearAuthorizationHeader,
|
|
6469
|
+
linearCycleIsActive,
|
|
5932
6470
|
linearGraphql,
|
|
5933
6471
|
linearOAuthAuthorizeUrl,
|
|
5934
6472
|
linearOAuthCredentials,
|
|
5935
6473
|
listAgentSetupInfo,
|
|
6474
|
+
listBoardPins,
|
|
5936
6475
|
listBranchCommits,
|
|
5937
6476
|
listBranches,
|
|
5938
6477
|
listBrightsyAccounts,
|
|
@@ -5944,6 +6483,7 @@ export {
|
|
|
5944
6483
|
listGitHubIssues,
|
|
5945
6484
|
listGlobalThreads,
|
|
5946
6485
|
listIssues,
|
|
6486
|
+
listLinearAssignedIssues,
|
|
5947
6487
|
listLinearIssues,
|
|
5948
6488
|
listLinearIssuesDirect,
|
|
5949
6489
|
listLinearTeams,
|
|
@@ -5953,7 +6493,6 @@ export {
|
|
|
5953
6493
|
listRunScripts,
|
|
5954
6494
|
listSchedules,
|
|
5955
6495
|
listSlackOutboundWatches,
|
|
5956
|
-
listSlackReplyBadges,
|
|
5957
6496
|
listSlackWorkspaces,
|
|
5958
6497
|
listThreads,
|
|
5959
6498
|
listWorkspaces,
|
|
@@ -5964,6 +6503,7 @@ export {
|
|
|
5964
6503
|
loadAppSettings,
|
|
5965
6504
|
loadBrightsyConfig,
|
|
5966
6505
|
loadConductorSettings,
|
|
6506
|
+
loadHomeBoardInputs,
|
|
5967
6507
|
loadRepoSettings,
|
|
5968
6508
|
loadWorkspaceSettings,
|
|
5969
6509
|
locksDir,
|
|
@@ -6009,10 +6549,11 @@ export {
|
|
|
6009
6549
|
partsToAssistantText,
|
|
6010
6550
|
pastedTextStats,
|
|
6011
6551
|
pendingSlackExternalReplies,
|
|
6012
|
-
permalinkForSlackReplyBadge,
|
|
6013
6552
|
permissionMode,
|
|
6014
6553
|
persistVaultKeyInKeychain,
|
|
6015
6554
|
planFileAbs,
|
|
6555
|
+
planQuestionsSignature,
|
|
6556
|
+
pollSlackOutboundWatches,
|
|
6016
6557
|
posixShellSingleQuote,
|
|
6017
6558
|
preferredCursorCostCents,
|
|
6018
6559
|
prepareTerminalCommand,
|
|
@@ -6030,10 +6571,10 @@ export {
|
|
|
6030
6571
|
recordScheduleRun,
|
|
6031
6572
|
recordSlackOutboundWatch,
|
|
6032
6573
|
refreshGitHubAuth,
|
|
6033
|
-
refreshSlackReplyBadges,
|
|
6034
6574
|
registerPackagedUserMcpClients,
|
|
6035
6575
|
releaseCaffeinateHoldForThread,
|
|
6036
6576
|
releaseDesktopHost,
|
|
6577
|
+
removeBoardPin,
|
|
6037
6578
|
removeWorkspace,
|
|
6038
6579
|
removeWorktree,
|
|
6039
6580
|
repoSlug,
|
|
@@ -6180,6 +6721,7 @@ export {
|
|
|
6180
6721
|
withMaxOldSpaceSize,
|
|
6181
6722
|
withThreadLock,
|
|
6182
6723
|
workspaceSettingsSourceLabel,
|
|
6724
|
+
worktreeBoardStatus,
|
|
6183
6725
|
worktreeCleanupSettings,
|
|
6184
6726
|
worktreeDisplayLabel,
|
|
6185
6727
|
worktreeDisplayLabelForGroup,
|