@sideboard-ai/core 0.1.125 → 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-GKY2GR2J.js → chunk-DLM5LSQW.js} +481 -35
- 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-ED27HCPV.js → chunk-T7KJQJAX.js} +493 -35
- 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 +1203 -157
- package/dist/index.d.cts +233 -10
- package/dist/index.d.ts +233 -10
- package/dist/index.js +668 -120
- package/dist/mcp/run-stdio.cjs +1051 -136
- package/dist/mcp/run-stdio.js +552 -112
- package/dist/{orchestrator-FZYM7I42.js → orchestrator-3JLPPTCF.js} +8 -8
- package/dist/{orchestrator-HN3LYHFN.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,6 +52,8 @@ import {
|
|
|
46
52
|
createPrStack,
|
|
47
53
|
createSchedule,
|
|
48
54
|
createThread,
|
|
55
|
+
dedupeBoardIssues,
|
|
56
|
+
dedupeBoardPrs,
|
|
49
57
|
defaultScheduleName,
|
|
50
58
|
deleteSchedule,
|
|
51
59
|
desktopHostPidPath,
|
|
@@ -58,6 +66,10 @@ import {
|
|
|
58
66
|
estimateThreadChars,
|
|
59
67
|
expandComposerPrompt,
|
|
60
68
|
extractiveSummary,
|
|
69
|
+
findBoardIssue,
|
|
70
|
+
findBoardPin,
|
|
71
|
+
findBoardPr,
|
|
72
|
+
findLiveThreadForCreate,
|
|
61
73
|
findOrphanWorktrees,
|
|
62
74
|
findThreadForStackLayer,
|
|
63
75
|
fireSchedule,
|
|
@@ -87,6 +99,7 @@ import {
|
|
|
87
99
|
getSchedule,
|
|
88
100
|
getSlackReplyTarget,
|
|
89
101
|
getSlackWorkspace,
|
|
102
|
+
groupHomeBoardWorktrees,
|
|
90
103
|
hasEnabledSchedules,
|
|
91
104
|
importConductorWorkspace,
|
|
92
105
|
importConductorWorkspaceAsync,
|
|
@@ -95,11 +108,13 @@ import {
|
|
|
95
108
|
inspectGitWorktree,
|
|
96
109
|
isCowboyThread,
|
|
97
110
|
isDesktopHostAlive,
|
|
111
|
+
isHomeBoardThread,
|
|
98
112
|
isImageFilePath,
|
|
99
113
|
isPidAlive,
|
|
100
114
|
isPrimaryCheckoutThread,
|
|
101
115
|
isSlackExternalReplyPrompt,
|
|
102
116
|
isThisProcessDesktopHost,
|
|
117
|
+
issueNeedsWorkspacePick,
|
|
103
118
|
lastRequestOccupancy,
|
|
104
119
|
listBranchCommits,
|
|
105
120
|
listConductorWorkspaces,
|
|
@@ -158,6 +173,7 @@ import {
|
|
|
158
173
|
startDevServer,
|
|
159
174
|
startOrchestration,
|
|
160
175
|
summarizeConversation,
|
|
176
|
+
syncBoardPins,
|
|
161
177
|
takenTeamSlugsForChatTab,
|
|
162
178
|
thisProcessShouldDrainAgentQueues,
|
|
163
179
|
threadsSharingWorktree,
|
|
@@ -165,10 +181,11 @@ import {
|
|
|
165
181
|
upsertSlackWorkspace,
|
|
166
182
|
waitForPidExit,
|
|
167
183
|
withAgentInstructions,
|
|
184
|
+
worktreeBoardStatus,
|
|
168
185
|
worktreeCleanupSettings,
|
|
169
186
|
wrapReviewSkillMarkdown,
|
|
170
187
|
writeWorktreeFile
|
|
171
|
-
} from "./chunk-
|
|
188
|
+
} from "./chunk-T7KJQJAX.js";
|
|
172
189
|
import {
|
|
173
190
|
BRIGHTSY_MCP_ALLOWED_TOOLS,
|
|
174
191
|
CLAUDE_MODEL_CATALOG,
|
|
@@ -247,7 +264,7 @@ import {
|
|
|
247
264
|
withEventParentId,
|
|
248
265
|
withEventsParentId,
|
|
249
266
|
writeInjectedMcpConfig
|
|
250
|
-
} from "./chunk-
|
|
267
|
+
} from "./chunk-NV73AO7Q.js";
|
|
251
268
|
import {
|
|
252
269
|
brightsyConfigPath,
|
|
253
270
|
brightsyMcpServerName,
|
|
@@ -266,7 +283,7 @@ import {
|
|
|
266
283
|
listWorkspaces,
|
|
267
284
|
removeWorkspace,
|
|
268
285
|
syncWorkspacesFromThreads
|
|
269
|
-
} from "./chunk-
|
|
286
|
+
} from "./chunk-VE22NWBD.js";
|
|
270
287
|
import {
|
|
271
288
|
CLOUD_COORDINATOR_BUSY_REPLY,
|
|
272
289
|
CLOUD_COORDINATOR_STOPPED_REPLY,
|
|
@@ -294,7 +311,7 @@ import {
|
|
|
294
311
|
parseForceStopMessage,
|
|
295
312
|
slackCoordinatorSourceRef,
|
|
296
313
|
takenTeamSlugsForOrchestration
|
|
297
|
-
} from "./chunk-
|
|
314
|
+
} from "./chunk-HULESWLI.js";
|
|
298
315
|
import {
|
|
299
316
|
COORDINATOR_TOOL_PLAYBOOK,
|
|
300
317
|
SLACK_REPLY_FORMATTING,
|
|
@@ -303,7 +320,7 @@ import {
|
|
|
303
320
|
enrichWorkspacesWithGithub,
|
|
304
321
|
ensureGlobalCoordinatorCwd,
|
|
305
322
|
formatWorkspaceInventory
|
|
306
|
-
} from "./chunk-
|
|
323
|
+
} from "./chunk-HZPO3SSZ.js";
|
|
307
324
|
import {
|
|
308
325
|
LEGACY_PLAN_FILE_REL,
|
|
309
326
|
PLAN_FILE_NAME,
|
|
@@ -340,6 +357,7 @@ import {
|
|
|
340
357
|
appendIndexedGitConfig,
|
|
341
358
|
applyGithubGitAuthEnv,
|
|
342
359
|
branchDisplayLabel,
|
|
360
|
+
canonicalizeRepoPath,
|
|
343
361
|
checkoutPrStackLayer,
|
|
344
362
|
codexSandboxWritableRootsArgs,
|
|
345
363
|
codexUnattendedGitConfigArgs,
|
|
@@ -412,7 +430,7 @@ import {
|
|
|
412
430
|
worktreeDisplayLabel,
|
|
413
431
|
worktreeDisplayLabelForGroup,
|
|
414
432
|
worktreeNameFromPath
|
|
415
|
-
} from "./chunk-
|
|
433
|
+
} from "./chunk-UDQI3N47.js";
|
|
416
434
|
import {
|
|
417
435
|
ATTACHMENTS_DIR,
|
|
418
436
|
LEGACY_ATTACHMENTS_DIR,
|
|
@@ -422,6 +440,7 @@ import {
|
|
|
422
440
|
import {
|
|
423
441
|
GITHUB_GIT_AUTH_MODES,
|
|
424
442
|
HARNESS_ENV_KEYS,
|
|
443
|
+
ISSUE_SOURCE_LABELS,
|
|
425
444
|
appSettingsPath,
|
|
426
445
|
applyAppEnvironment,
|
|
427
446
|
autoArchiveOnMergeEnabled,
|
|
@@ -451,7 +470,9 @@ import {
|
|
|
451
470
|
getIssueSource,
|
|
452
471
|
getLinearApiKey,
|
|
453
472
|
harnessEnvKey,
|
|
473
|
+
isIssueSourceConnected,
|
|
454
474
|
isLinearConnected,
|
|
475
|
+
issueSourceLabel,
|
|
455
476
|
loadAppSettings,
|
|
456
477
|
maxConcurrentAgents,
|
|
457
478
|
orchestrationQuotaFallbackAgent,
|
|
@@ -481,7 +502,7 @@ import {
|
|
|
481
502
|
updateDefaultsSettings,
|
|
482
503
|
updateIntegrationsSettings,
|
|
483
504
|
updateOpencodeSettings
|
|
484
|
-
} from "./chunk-
|
|
505
|
+
} from "./chunk-HUYEU4GS.js";
|
|
485
506
|
import {
|
|
486
507
|
stripNestedElectronEnv
|
|
487
508
|
} from "./chunk-4TR3HZFT.js";
|
|
@@ -500,7 +521,7 @@ import {
|
|
|
500
521
|
updateThread,
|
|
501
522
|
withThreadLock,
|
|
502
523
|
writeThread
|
|
503
|
-
} from "./chunk-
|
|
524
|
+
} from "./chunk-HLJUNJBF.js";
|
|
504
525
|
import {
|
|
505
526
|
THINKING_EFFORTS,
|
|
506
527
|
isThinkingEffort,
|
|
@@ -909,10 +930,13 @@ var ISSUE_FIELDS = `
|
|
|
909
930
|
assignee { id name }
|
|
910
931
|
team { id key name states { nodes { id name type } } }
|
|
911
932
|
labels { nodes { name } }
|
|
933
|
+
cycle { id name number startsAt endsAt completedAt }
|
|
912
934
|
`;
|
|
913
935
|
var ASSIGNED_ISSUES_QUERY = `
|
|
914
936
|
query SideboardAssignedIssues($first: Int!) {
|
|
915
937
|
viewer {
|
|
938
|
+
id
|
|
939
|
+
name
|
|
916
940
|
assignedIssues(
|
|
917
941
|
first: $first
|
|
918
942
|
orderBy: updatedAt
|
|
@@ -1015,6 +1039,25 @@ function mapState(node) {
|
|
|
1015
1039
|
type: String(node.type ?? "")
|
|
1016
1040
|
};
|
|
1017
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
|
+
}
|
|
1018
1061
|
function mapIssue(node) {
|
|
1019
1062
|
const team = node.team;
|
|
1020
1063
|
return {
|
|
@@ -1032,7 +1075,8 @@ function mapIssue(node) {
|
|
|
1032
1075
|
name: String(team.name ?? ""),
|
|
1033
1076
|
states: (team.states?.nodes ?? []).map((s) => mapState(s)).filter((s) => Boolean(s))
|
|
1034
1077
|
} : void 0,
|
|
1035
|
-
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)
|
|
1036
1080
|
};
|
|
1037
1081
|
}
|
|
1038
1082
|
function toIssueInfo(issue) {
|
|
@@ -1042,7 +1086,11 @@ function toIssueInfo(issue) {
|
|
|
1042
1086
|
title: issue.title,
|
|
1043
1087
|
url: issue.url,
|
|
1044
1088
|
labels: issue.labels,
|
|
1045
|
-
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
|
|
1046
1094
|
};
|
|
1047
1095
|
}
|
|
1048
1096
|
function mapTeam(node) {
|
|
@@ -1084,10 +1132,21 @@ function normalizePriority(priority) {
|
|
|
1084
1132
|
}
|
|
1085
1133
|
return priority;
|
|
1086
1134
|
}
|
|
1087
|
-
async function
|
|
1088
|
-
const first = Math.max(1, Math.min(
|
|
1135
|
+
async function listLinearAssignedIssues(opts) {
|
|
1136
|
+
const first = Math.max(1, Math.min(250, opts?.limit ?? 200));
|
|
1089
1137
|
const json = await linearGraphql(ASSIGNED_ISSUES_QUERY, { first }, opts);
|
|
1090
|
-
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;
|
|
1091
1150
|
}
|
|
1092
1151
|
async function listLinearTeams(opts) {
|
|
1093
1152
|
const json = await linearGraphql(TEAMS_QUERY, void 0, opts);
|
|
@@ -1206,13 +1265,13 @@ async function validateLinearApiKey(apiKey) {
|
|
|
1206
1265
|
|
|
1207
1266
|
// src/integrations/issues.ts
|
|
1208
1267
|
async function listGitHubIssues(repoPath, opts) {
|
|
1209
|
-
const limit = Math.max(1, Math.min(
|
|
1268
|
+
const limit = Math.max(1, Math.min(1e3, opts?.limit ?? 200));
|
|
1210
1269
|
const slug = await resolveGithubRepoSlug(repoPath);
|
|
1211
1270
|
const args = [
|
|
1212
1271
|
"issue",
|
|
1213
1272
|
"list",
|
|
1214
1273
|
"--json",
|
|
1215
|
-
"number,title,url,labels",
|
|
1274
|
+
"number,title,url,labels,assignees",
|
|
1216
1275
|
"--limit",
|
|
1217
1276
|
String(limit),
|
|
1218
1277
|
"--state",
|
|
@@ -1235,27 +1294,55 @@ async function listGitHubIssues(repoPath, opts) {
|
|
|
1235
1294
|
const labels = (item.labels ?? []).map(
|
|
1236
1295
|
(l) => typeof l === "string" ? l : String(l?.name ?? "")
|
|
1237
1296
|
).filter(Boolean);
|
|
1297
|
+
const assignees = (item.assignees ?? []).map((a) => typeof a === "string" ? a : String(a?.login ?? "")).map((login) => login.trim()).filter(Boolean);
|
|
1238
1298
|
return {
|
|
1239
1299
|
id: Number.isFinite(number) ? `gh-${number}` : identifier,
|
|
1240
1300
|
identifier,
|
|
1241
1301
|
title: String(item.title ?? ""),
|
|
1242
1302
|
url: String(item.url ?? ""),
|
|
1243
1303
|
labels,
|
|
1244
|
-
provider: "github"
|
|
1304
|
+
provider: "github",
|
|
1305
|
+
assignee: assignees[0],
|
|
1306
|
+
assignees
|
|
1245
1307
|
};
|
|
1246
1308
|
});
|
|
1247
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
|
+
}
|
|
1248
1317
|
async function listIssues(repoPath) {
|
|
1249
1318
|
const settings = loadAppSettings();
|
|
1250
1319
|
const preferredSource = settings.integrations.issueSource ?? "github";
|
|
1251
1320
|
const linearConnected = isLinearConnected(settings);
|
|
1252
1321
|
const source = resolveEffectiveIssueSource(settings);
|
|
1253
1322
|
if (source === "linear") {
|
|
1254
|
-
const
|
|
1255
|
-
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
|
+
};
|
|
1256
1334
|
}
|
|
1257
|
-
const issues = await
|
|
1258
|
-
|
|
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
|
+
};
|
|
1259
1346
|
}
|
|
1260
1347
|
|
|
1261
1348
|
// src/composer/diff-comment.ts
|
|
@@ -1343,6 +1430,12 @@ function buildPastedTextAttachment(text4, opts) {
|
|
|
1343
1430
|
}
|
|
1344
1431
|
|
|
1345
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
|
+
}
|
|
1346
1439
|
function asRecord(v) {
|
|
1347
1440
|
return v != null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
1348
1441
|
}
|
|
@@ -1400,12 +1493,22 @@ function extractPendingPlanQuestions(parts) {
|
|
|
1400
1493
|
if (!questions.length) continue;
|
|
1401
1494
|
return {
|
|
1402
1495
|
id: p.id || `ask-${i}`,
|
|
1496
|
+
signature: planQuestionsSignature(questions),
|
|
1403
1497
|
questions,
|
|
1404
1498
|
source: p.name || "ask_user"
|
|
1405
1499
|
};
|
|
1406
1500
|
}
|
|
1407
1501
|
return null;
|
|
1408
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
|
+
}
|
|
1409
1512
|
function formatPlanQuestionAnswers(questions, answers) {
|
|
1410
1513
|
const lines = ["Answers to your questions:"];
|
|
1411
1514
|
for (let i = 0; i < questions.length; i++) {
|
|
@@ -1444,6 +1547,7 @@ function formatPlanQuestionsForChat(questions) {
|
|
|
1444
1547
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
1445
1548
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1446
1549
|
import { z as z4 } from "zod";
|
|
1550
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
1447
1551
|
import { basename } from "path";
|
|
1448
1552
|
|
|
1449
1553
|
// src/mcp/archive-guard.ts
|
|
@@ -2226,6 +2330,283 @@ function registerScheduleTools(server) {
|
|
|
2226
2330
|
);
|
|
2227
2331
|
}
|
|
2228
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
|
+
|
|
2229
2610
|
// src/mcp/server.ts
|
|
2230
2611
|
var MAX_ORCH_THREADS = 5;
|
|
2231
2612
|
var CREATE_THREAD_TIMEOUT_MS = 9e4;
|
|
@@ -2246,6 +2627,93 @@ function withTimeout(promise, ms, label) {
|
|
|
2246
2627
|
);
|
|
2247
2628
|
});
|
|
2248
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
|
+
}
|
|
2249
2717
|
async function startMcpServer() {
|
|
2250
2718
|
const orch = getOrchestrator();
|
|
2251
2719
|
try {
|
|
@@ -2257,7 +2725,7 @@ async function startMcpServer() {
|
|
|
2257
2725
|
);
|
|
2258
2726
|
}
|
|
2259
2727
|
try {
|
|
2260
|
-
const { maxConcurrentAgents: maxConcurrentAgents2 } = await import("./app-settings-
|
|
2728
|
+
const { maxConcurrentAgents: maxConcurrentAgents2 } = await import("./app-settings-6RPALX4J.js");
|
|
2261
2729
|
orch.setMaxConcurrent(maxConcurrentAgents2());
|
|
2262
2730
|
} catch {
|
|
2263
2731
|
}
|
|
@@ -2277,7 +2745,7 @@ async function startMcpServer() {
|
|
|
2277
2745
|
if (!worktreeProfile) {
|
|
2278
2746
|
server.tool(
|
|
2279
2747
|
"list_workspaces",
|
|
2280
|
-
"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.",
|
|
2281
2749
|
{},
|
|
2282
2750
|
async () => {
|
|
2283
2751
|
const workspaces = orch.listWorkspaces();
|
|
@@ -2311,6 +2779,51 @@ async function startMcpServer() {
|
|
|
2311
2779
|
};
|
|
2312
2780
|
}
|
|
2313
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
|
+
);
|
|
2314
2827
|
server.tool(
|
|
2315
2828
|
"get_thread",
|
|
2316
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.",
|
|
@@ -2480,7 +2993,7 @@ async function startMcpServer() {
|
|
|
2480
2993
|
registerLinearTools(server);
|
|
2481
2994
|
registerScheduleTools(server);
|
|
2482
2995
|
const { getCaffeinateHold: getCaffeinateHold2, setCaffeinateHold: setCaffeinateHold2 } = await import("./caffeinate-hold-X3JNPR42.js");
|
|
2483
|
-
const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await import("./app-settings-
|
|
2996
|
+
const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await import("./app-settings-6RPALX4J.js");
|
|
2484
2997
|
const accountDefaults = resolveThreadDefaults2();
|
|
2485
2998
|
const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
|
|
2486
2999
|
server.tool(
|
|
@@ -2523,7 +3036,7 @@ async function startMcpServer() {
|
|
|
2523
3036
|
);
|
|
2524
3037
|
server.tool(
|
|
2525
3038
|
"create_thread",
|
|
2526
|
-
`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.`,
|
|
2527
3040
|
{
|
|
2528
3041
|
sourceType: z4.enum(["branch", "pr", "ticket"]),
|
|
2529
3042
|
sourceRef: z4.string(),
|
|
@@ -2541,104 +3054,118 @@ async function startMcpServer() {
|
|
|
2541
3054
|
)
|
|
2542
3055
|
},
|
|
2543
3056
|
async (args) => {
|
|
2544
|
-
const
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
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
|
-
let agentArg = args.agent;
|
|
2577
|
-
let agentCoercedFrom;
|
|
2578
|
-
const resolvedProbe = resolveNewThreadOptions2({ agent: agentArg }).agent;
|
|
2579
|
-
if (resolvedProbe === "codex") {
|
|
2580
|
-
agentCoercedFrom = agentArg ?? "codex";
|
|
2581
|
-
const accountAgent = resolveNewThreadOptions2({}).agent;
|
|
2582
|
-
agentArg = accountAgent !== "codex" ? accountAgent : "cursor";
|
|
2583
|
-
}
|
|
2584
|
-
const opts = resolveNewThreadOptions2({
|
|
2585
|
-
agent: agentArg,
|
|
2586
|
-
model: args.model
|
|
2587
|
-
});
|
|
2588
|
-
try {
|
|
2589
|
-
const thread = await withTimeout(
|
|
2590
|
-
orch.createThread({
|
|
2591
|
-
sourceType: args.sourceType,
|
|
2592
|
-
sourceRef: args.sourceRef,
|
|
2593
|
-
agent: opts.agent,
|
|
2594
|
-
model: opts.model,
|
|
2595
|
-
effort: opts.effort,
|
|
2596
|
-
fast: opts.fast,
|
|
2597
|
-
repoPath: args.repoPath,
|
|
2598
|
-
title: args.title,
|
|
2599
|
-
parentThreadId: parentId || null,
|
|
2600
|
-
cowboy: args.cowboy || void 0
|
|
2601
|
-
}),
|
|
2602
|
-
CREATE_THREAD_TIMEOUT_MS,
|
|
2603
|
-
"create_thread"
|
|
2604
|
-
);
|
|
2605
|
-
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) {
|
|
2606
3088
|
return {
|
|
2607
3089
|
content: [
|
|
2608
3090
|
{
|
|
2609
3091
|
type: "text",
|
|
2610
3092
|
text: JSON.stringify({
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
model: thread.model,
|
|
2617
|
-
status: thread.status,
|
|
2618
|
-
cowboy: Boolean(thread.cowboy),
|
|
2619
|
-
link: `sideboard://thread/${thread.id}`,
|
|
2620
|
-
parentThreadId: thread.parentThreadId,
|
|
2621
|
-
...agentCoercedFrom ? {
|
|
2622
|
-
agentCoercedFrom,
|
|
2623
|
-
note: `Avoid nested Codex under a Codex orchestrator \u2014 used Account default agent=${thread.agent}`
|
|
2624
|
-
} : {},
|
|
2625
|
-
...parentCorrectedFrom ? { parentCorrectedFrom, parentNote } : {}
|
|
3093
|
+
alreadyStarted: true,
|
|
3094
|
+
id: existing.id,
|
|
3095
|
+
title: existing.title,
|
|
3096
|
+
status: existing.status,
|
|
3097
|
+
link: `sideboard://thread/${existing.id}`
|
|
2626
3098
|
})
|
|
2627
3099
|
}
|
|
2628
3100
|
]
|
|
2629
3101
|
};
|
|
2630
|
-
}
|
|
2631
|
-
|
|
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
|
+
);
|
|
2632
3118
|
return {
|
|
2633
|
-
content: [
|
|
2634
|
-
|
|
2635
|
-
type: "text",
|
|
2636
|
-
text: `create_thread failed: ${message}`
|
|
2637
|
-
}
|
|
2638
|
-
],
|
|
2639
|
-
isError: true
|
|
3119
|
+
content: [{ type: "text", text: result2.text }],
|
|
3120
|
+
...result2.ok ? {} : { isError: true }
|
|
2640
3121
|
};
|
|
2641
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
|
+
};
|
|
2642
3169
|
}
|
|
2643
3170
|
);
|
|
2644
3171
|
server.tool(
|
|
@@ -3285,7 +3812,7 @@ async function startMcpServer() {
|
|
|
3285
3812
|
);
|
|
3286
3813
|
server.tool(
|
|
3287
3814
|
"list_issues",
|
|
3288
|
-
"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.",
|
|
3289
3816
|
{ repoPath: z4.string() },
|
|
3290
3817
|
async ({ repoPath }) => {
|
|
3291
3818
|
const root = await resolveRepoRoot(repoPath);
|
|
@@ -3627,14 +4154,14 @@ async function runCloudConnect(opts) {
|
|
|
3627
4154
|
}
|
|
3628
4155
|
|
|
3629
4156
|
// src/agents/user-mcp-config.ts
|
|
3630
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
4157
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
3631
4158
|
import { homedir } from "os";
|
|
3632
|
-
import { dirname, join } from "path";
|
|
4159
|
+
import { dirname, join as join3 } from "path";
|
|
3633
4160
|
function userCursorMcpConfigPath() {
|
|
3634
|
-
return
|
|
4161
|
+
return join3(homedir(), ".cursor", "mcp.json");
|
|
3635
4162
|
}
|
|
3636
4163
|
function userClaudeMcpConfigPath() {
|
|
3637
|
-
return
|
|
4164
|
+
return join3(homedir(), ".claude.json");
|
|
3638
4165
|
}
|
|
3639
4166
|
function asObject(value) {
|
|
3640
4167
|
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
@@ -3661,16 +4188,16 @@ function mergeSideboardIntoMcpServersJson(existing, sideboard) {
|
|
|
3661
4188
|
}
|
|
3662
4189
|
function writeMergedMcpServersJson(configPath, sideboard) {
|
|
3663
4190
|
let existing = {};
|
|
3664
|
-
if (
|
|
4191
|
+
if (existsSync3(configPath)) {
|
|
3665
4192
|
try {
|
|
3666
|
-
existing = JSON.parse(
|
|
4193
|
+
existing = JSON.parse(readFileSync3(configPath, "utf8"));
|
|
3667
4194
|
} catch {
|
|
3668
4195
|
existing = {};
|
|
3669
4196
|
}
|
|
3670
4197
|
}
|
|
3671
4198
|
const next = mergeSideboardIntoMcpServersJson(existing, sideboard);
|
|
3672
|
-
|
|
3673
|
-
|
|
4199
|
+
mkdirSync3(dirname(configPath), { recursive: true });
|
|
4200
|
+
writeFileSync3(configPath, `${JSON.stringify(next, null, 2)}
|
|
3674
4201
|
`);
|
|
3675
4202
|
}
|
|
3676
4203
|
function launchFromResolved(server) {
|
|
@@ -3688,7 +4215,7 @@ async function registerPackagedUserMcpClients() {
|
|
|
3688
4215
|
const cursor = userCursorMcpConfigPath();
|
|
3689
4216
|
writeMergedMcpServersJson(cursor, launch);
|
|
3690
4217
|
const claude = userClaudeMcpConfigPath();
|
|
3691
|
-
if (
|
|
4218
|
+
if (existsSync3(claude)) {
|
|
3692
4219
|
writeMergedMcpServersJson(claude, launch);
|
|
3693
4220
|
return { cursor, claude };
|
|
3694
4221
|
}
|
|
@@ -5617,6 +6144,8 @@ export {
|
|
|
5617
6144
|
GITHUB_GIT_AUTH_MODES,
|
|
5618
6145
|
GLOBAL_WORKSPACE_ID,
|
|
5619
6146
|
HARNESS_ENV_KEYS,
|
|
6147
|
+
HOME_BOARD_CACHE_TTL_MS,
|
|
6148
|
+
ISSUE_SOURCE_LABELS,
|
|
5620
6149
|
LEGACY_ATTACHMENTS_DIR,
|
|
5621
6150
|
LEGACY_PLAN_FILE_REL,
|
|
5622
6151
|
LEGACY_REVIEW_REQUEST_PATH,
|
|
@@ -5658,6 +6187,7 @@ export {
|
|
|
5658
6187
|
THINKING_EFFORTS,
|
|
5659
6188
|
WORKTREE_MCP_TOOLS,
|
|
5660
6189
|
ackSlackInboundSeen,
|
|
6190
|
+
addBoardPin,
|
|
5661
6191
|
addPrStackLayer,
|
|
5662
6192
|
addStackLayerFromThread,
|
|
5663
6193
|
addWorkspace,
|
|
@@ -5711,15 +6241,19 @@ export {
|
|
|
5711
6241
|
caffeinateWhileRunningEnabled,
|
|
5712
6242
|
caffeinateWhileSchedulesEnabled,
|
|
5713
6243
|
caffeinateWhileSlackListenEnabled,
|
|
6244
|
+
canonicalizeRepoPath,
|
|
5714
6245
|
captureLoginEnv,
|
|
5715
6246
|
captureTurnBaseline,
|
|
5716
6247
|
checkoutPrStackLayer,
|
|
5717
6248
|
childEnvWithAppSettings,
|
|
5718
6249
|
claimDesktopHost,
|
|
6250
|
+
classifyWorktreeColumn,
|
|
5719
6251
|
claudeAdapter,
|
|
5720
6252
|
claudeChromeEnabled,
|
|
5721
6253
|
claudeUserSettingsPath,
|
|
5722
6254
|
cleanupOrphanWorktrees,
|
|
6255
|
+
clearBoardPins,
|
|
6256
|
+
clearHomeBoardCache,
|
|
5723
6257
|
cloneRepoIntoSideboard,
|
|
5724
6258
|
codexAdapter,
|
|
5725
6259
|
codexSandboxWritableRootsArgs,
|
|
@@ -5792,6 +6326,7 @@ export {
|
|
|
5792
6326
|
finalizeParts,
|
|
5793
6327
|
findConventionSetup,
|
|
5794
6328
|
findInvalidCacheControlTtlOrder,
|
|
6329
|
+
findLiveThreadForCreate,
|
|
5795
6330
|
findOrphanWorktrees,
|
|
5796
6331
|
findSlackCoordinator,
|
|
5797
6332
|
findThreadByRef,
|
|
@@ -5843,6 +6378,7 @@ export {
|
|
|
5843
6378
|
getGitHubStatus,
|
|
5844
6379
|
getGithubGitAuthMode,
|
|
5845
6380
|
getGithubPat,
|
|
6381
|
+
getHomeBoardInputs,
|
|
5846
6382
|
getIssueSource,
|
|
5847
6383
|
getLinearApiKey,
|
|
5848
6384
|
getLinearAuthToken,
|
|
@@ -5865,6 +6401,7 @@ export {
|
|
|
5865
6401
|
git,
|
|
5866
6402
|
githubAgentGitEnv,
|
|
5867
6403
|
globalAgentCwd,
|
|
6404
|
+
groupHomeBoardWorktrees,
|
|
5868
6405
|
handleSlackInbound,
|
|
5869
6406
|
harnessEnvKey,
|
|
5870
6407
|
hasBakedLinearOAuth,
|
|
@@ -5898,9 +6435,11 @@ export {
|
|
|
5898
6435
|
isGhRateLimitError,
|
|
5899
6436
|
isGlobalRepoPath,
|
|
5900
6437
|
isGlobalThread,
|
|
6438
|
+
isHomeBoardThread,
|
|
5901
6439
|
isImageFilePath,
|
|
5902
6440
|
isInPrStack,
|
|
5903
6441
|
isInboundForThisDesktop,
|
|
6442
|
+
isIssueSourceConnected,
|
|
5904
6443
|
isLinearConnected,
|
|
5905
6444
|
isLinearOAuthCancelled,
|
|
5906
6445
|
isOrchestratorCapableAgent,
|
|
@@ -5923,12 +6462,16 @@ export {
|
|
|
5923
6462
|
isThreadCaffeinated,
|
|
5924
6463
|
isThreadRecordFile,
|
|
5925
6464
|
isWorkspaceScratchPath,
|
|
6465
|
+
issueSourceLabel,
|
|
5926
6466
|
lastRequestOccupancy,
|
|
6467
|
+
latestPendingPlanQuestions,
|
|
5927
6468
|
linearAuthorizationHeader,
|
|
6469
|
+
linearCycleIsActive,
|
|
5928
6470
|
linearGraphql,
|
|
5929
6471
|
linearOAuthAuthorizeUrl,
|
|
5930
6472
|
linearOAuthCredentials,
|
|
5931
6473
|
listAgentSetupInfo,
|
|
6474
|
+
listBoardPins,
|
|
5932
6475
|
listBranchCommits,
|
|
5933
6476
|
listBranches,
|
|
5934
6477
|
listBrightsyAccounts,
|
|
@@ -5940,6 +6483,7 @@ export {
|
|
|
5940
6483
|
listGitHubIssues,
|
|
5941
6484
|
listGlobalThreads,
|
|
5942
6485
|
listIssues,
|
|
6486
|
+
listLinearAssignedIssues,
|
|
5943
6487
|
listLinearIssues,
|
|
5944
6488
|
listLinearIssuesDirect,
|
|
5945
6489
|
listLinearTeams,
|
|
@@ -5959,6 +6503,7 @@ export {
|
|
|
5959
6503
|
loadAppSettings,
|
|
5960
6504
|
loadBrightsyConfig,
|
|
5961
6505
|
loadConductorSettings,
|
|
6506
|
+
loadHomeBoardInputs,
|
|
5962
6507
|
loadRepoSettings,
|
|
5963
6508
|
loadWorkspaceSettings,
|
|
5964
6509
|
locksDir,
|
|
@@ -6007,6 +6552,7 @@ export {
|
|
|
6007
6552
|
permissionMode,
|
|
6008
6553
|
persistVaultKeyInKeychain,
|
|
6009
6554
|
planFileAbs,
|
|
6555
|
+
planQuestionsSignature,
|
|
6010
6556
|
pollSlackOutboundWatches,
|
|
6011
6557
|
posixShellSingleQuote,
|
|
6012
6558
|
preferredCursorCostCents,
|
|
@@ -6028,6 +6574,7 @@ export {
|
|
|
6028
6574
|
registerPackagedUserMcpClients,
|
|
6029
6575
|
releaseCaffeinateHoldForThread,
|
|
6030
6576
|
releaseDesktopHost,
|
|
6577
|
+
removeBoardPin,
|
|
6031
6578
|
removeWorkspace,
|
|
6032
6579
|
removeWorktree,
|
|
6033
6580
|
repoSlug,
|
|
@@ -6174,6 +6721,7 @@ export {
|
|
|
6174
6721
|
withMaxOldSpaceSize,
|
|
6175
6722
|
withThreadLock,
|
|
6176
6723
|
workspaceSettingsSourceLabel,
|
|
6724
|
+
worktreeBoardStatus,
|
|
6177
6725
|
worktreeCleanupSettings,
|
|
6178
6726
|
worktreeDisplayLabel,
|
|
6179
6727
|
worktreeDisplayLabelForGroup,
|