@sideboard-ai/core 0.1.149 → 0.1.150

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/{abletime-QEVAE67D.js → abletime-223A3LY6.js} +2 -2
  2. package/dist/{abletime-DI55AJX3.js → abletime-CLC5UJC2.js} +2 -2
  3. package/dist/agents/cursor-runner.cjs +40 -35
  4. package/dist/agents/cursor-runner.js +2 -2
  5. package/dist/{agents-HSVQ2Z6Y.js → agents-KKXGTEV6.js} +10 -9
  6. package/dist/{agents-V4MTDWXS.js → agents-YWBQXOA2.js} +10 -9
  7. package/dist/{app-settings-WJDCJFSY.js → app-settings-3CHCNIMD.js} +5 -1
  8. package/dist/{app-settings-ZCN632OJ.js → app-settings-J3JBCUOT.js} +5 -1
  9. package/dist/{chunk-I77RYPOH.js → chunk-4XNSGDXE.js} +12 -0
  10. package/dist/{chunk-KBWND62T.js → chunk-7F4XE6UG.js} +5 -5
  11. package/dist/{chunk-R4JP32P5.js → chunk-AF6O55PJ.js} +4 -4
  12. package/dist/{chunk-BOD5V52W.js → chunk-B7XK37WZ.js} +1 -1
  13. package/dist/{chunk-BGQBELGJ.js → chunk-CZD4NRDZ.js} +12 -0
  14. package/dist/{chunk-ZVYLEF72.js → chunk-DMRIZR6M.js} +6 -6
  15. package/dist/{chunk-TZWO7J4W.js → chunk-DXCNW2JF.js} +113 -52
  16. package/dist/{chunk-KPIYENTF.js → chunk-FNQNJOHY.js} +89 -5
  17. package/dist/{chunk-ED4UPEJX.js → chunk-G7SIQFBQ.js} +1 -1
  18. package/dist/{chunk-3QRGCKYL.js → chunk-HAS5EPBS.js} +2 -2
  19. package/dist/{chunk-LAFA56WD.js → chunk-HEII7W3Q.js} +1 -1
  20. package/dist/{chunk-EGDRPA4B.js → chunk-NOTANBYC.js} +6 -6
  21. package/dist/{chunk-JDYKQ6OI.js → chunk-NUPITVRF.js} +134 -73
  22. package/dist/{chunk-QTUESPAW.js → chunk-PTOSP4AH.js} +1 -1
  23. package/dist/{chunk-Q62SDB53.js → chunk-QGJHIJHV.js} +2 -2
  24. package/dist/{chunk-PTI5H3RK.js → chunk-SDN4ZYQH.js} +24 -13
  25. package/dist/{chunk-DVM4ID64.js → chunk-UFHNSFAS.js} +89 -5
  26. package/dist/{chunk-N3VNOFXQ.js → chunk-VO4SPEBS.js} +4 -4
  27. package/dist/chunk-VSFGPWCQ.js +62 -0
  28. package/dist/{chunk-N5PM7HGQ.js → chunk-W6N6GQME.js} +1 -1
  29. package/dist/{chunk-FKOIHGKV.js → chunk-WHU7YGWP.js} +1 -1
  30. package/dist/{chunk-VZJVKQHH.js → chunk-WLV7TRMR.js} +1 -1
  31. package/dist/chunk-Y4NAPW5I.js +60 -0
  32. package/dist/{chunk-B3SJXYIJ.js → chunk-Y7YBWWIG.js} +1 -1
  33. package/dist/{chunk-Q5DHVMXB.js → chunk-YGGBJY5A.js} +18 -7
  34. package/dist/{chunk-JTPDWTWJ.js → chunk-Z2PVJKMN.js} +137 -114
  35. package/dist/{chunk-YP3CSOZ6.js → chunk-ZGFYFVJF.js} +142 -114
  36. package/dist/{connected-teams-IJUJQ7R6.js → connected-teams-I2WZZZFA.js} +2 -2
  37. package/dist/{connected-teams-4A2AXDNN.js → connected-teams-XO766HB4.js} +2 -2
  38. package/dist/{coordinator-prompt-ZWBMAIWA.js → coordinator-prompt-NYR5TPBD.js} +6 -5
  39. package/dist/{coordinator-prompt-5GXGBGEZ.js → coordinator-prompt-UCQJTFA7.js} +6 -5
  40. package/dist/{global-workspace-2SIPM4PW.js → global-workspace-4QHDAD2D.js} +7 -6
  41. package/dist/{global-workspace-OJRXWXEA.js → global-workspace-4SENNWBU.js} +7 -6
  42. package/dist/index.cjs +998 -574
  43. package/dist/index.d.cts +91 -10
  44. package/dist/index.d.ts +91 -10
  45. package/dist/index.js +268 -93
  46. package/dist/mcp/run-stdio.cjs +976 -579
  47. package/dist/mcp/run-stdio.js +196 -43
  48. package/dist/{orchestrator-6TXQWBXN.js → orchestrator-GZE4X3XV.js} +14 -11
  49. package/dist/{orchestrator-Z2O5OVJA.js → orchestrator-QSBRWME5.js} +16 -13
  50. package/dist/{plan-file-6O7G4VPQ.js → plan-file-5S5TUNAW.js} +2 -2
  51. package/dist/{plan-file-PHVKUAEE.js → plan-file-IBSU2PVW.js} +2 -2
  52. package/dist/{run-XQKGHQZ2.js → run-CAGKZLHA.js} +1 -1
  53. package/dist/{run-USF6FRKV.js → run-EBWL2Q4N.js} +1 -1
  54. package/dist/{workspaces-UUJNOO4T.js → workspaces-7S7QKCUE.js} +8 -7
  55. package/dist/{workspaces-3NUUZTQK.js → workspaces-RDUSB6FD.js} +8 -7
  56. package/dist/{worktree-RZRJNHYL.js → worktree-63AGPPLO.js} +5 -4
  57. package/dist/{worktree-UCWWTVLS.js → worktree-JIZ3QMZX.js} +5 -4
  58. package/dist/worktree-exclude-6MQWGWV5.js +11 -0
  59. package/dist/worktree-exclude-TV6EV6BS.js +9 -0
  60. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  HOME_BOARD_AGENT_HINT,
14
14
  HOME_BOARD_CACHE_TTL_MS,
15
15
  LEGACY_REVIEW_REQUEST_PATH,
16
+ LIVE_TURN_SPAWN_GRACE_MS,
16
17
  LONG_RUNNING_SKILL_COMMAND,
17
18
  OPTIONAL_SERVICES,
18
19
  OPTIONAL_SERVICE_IDS,
@@ -212,7 +213,18 @@ import {
212
213
  worktreeCleanupSettings,
213
214
  wrapReviewSkillMarkdown,
214
215
  writeWorktreeFile
215
- } from "./chunk-JDYKQ6OI.js";
216
+ } from "./chunk-NUPITVRF.js";
217
+ import {
218
+ LEGACY_PLAN_FILE_REL,
219
+ PLAN_FILE_NAME,
220
+ PLAN_FILE_REL,
221
+ extractPresentedPlan,
222
+ isPresentPlanToolName,
223
+ planFileAbs,
224
+ readPlanFile,
225
+ resolvePlanMarkdown,
226
+ writePlanFile
227
+ } from "./chunk-PTOSP4AH.js";
216
228
  import {
217
229
  BRIGHTSY_MCP_ALLOWED_TOOLS,
218
230
  CLAUDE_MODEL_CATALOG,
@@ -247,6 +259,7 @@ import {
247
259
  isBrightsyConnected,
248
260
  isBrightsyNdjsonLine,
249
261
  isCursorAutoModel,
262
+ isInternalAgentStatusText,
250
263
  isPollWrapperToolName,
251
264
  isSessionQuotaLimit,
252
265
  isShellToolName,
@@ -294,7 +307,7 @@ import {
294
307
  withEventParentId,
295
308
  withEventsParentId,
296
309
  writeInjectedMcpConfig
297
- } from "./chunk-PTI5H3RK.js";
310
+ } from "./chunk-SDN4ZYQH.js";
298
311
  import {
299
312
  brightsyMcpServerName,
300
313
  connectBrightsyTeam,
@@ -304,7 +317,7 @@ import {
304
317
  listBrightsyAccounts,
305
318
  listConnectedBrightsyTeams,
306
319
  switchBrightsyAccount
307
- } from "./chunk-KBWND62T.js";
320
+ } from "./chunk-7F4XE6UG.js";
308
321
  import {
309
322
  brightsyAccessTokenNeedsRefresh,
310
323
  brightsyConfigPath,
@@ -319,7 +332,7 @@ import {
319
332
  listWorkspaces,
320
333
  removeWorkspace,
321
334
  syncWorkspacesFromThreads
322
- } from "./chunk-3QRGCKYL.js";
335
+ } from "./chunk-HAS5EPBS.js";
323
336
  import {
324
337
  CLOUD_COORDINATOR_BUSY_REPLY,
325
338
  CLOUD_COORDINATOR_STOPPED_REPLY,
@@ -354,7 +367,7 @@ import {
354
367
  stageAbsolutePathsAsAttachments,
355
368
  stageBuffersAsAttachments,
356
369
  takenTeamSlugsForOrchestration
357
- } from "./chunk-R4JP32P5.js";
370
+ } from "./chunk-AF6O55PJ.js";
358
371
  import {
359
372
  COORDINATOR_TOOL_PLAYBOOK,
360
373
  SLACK_REPLY_FORMATTING,
@@ -363,64 +376,11 @@ import {
363
376
  enrichWorkspacesWithGithub,
364
377
  ensureGlobalCoordinatorCwd,
365
378
  formatWorkspaceInventory
366
- } from "./chunk-EGDRPA4B.js";
367
- import {
368
- ABLETIME_MCP_PATH,
369
- DEFAULT_ABLETIME_HOST,
370
- abletimeMcpRequest,
371
- abletimeMcpUrl,
372
- callAbleTimeTool,
373
- createAbleTimeTask,
374
- ensureAbleTimeTask,
375
- getAbleTimeOrientation,
376
- getAbleTimeTask,
377
- issueAttachmentForAbleTimeTask,
378
- listAbleTimeAssignedIssues,
379
- listAbleTimeProjects,
380
- listAbleTimeTasks,
381
- mapAbleTimeTask,
382
- normalizeAbleTimeHost,
383
- rewriteAbleTimeError,
384
- searchAbleTimeTasks,
385
- taskUrl,
386
- toAbleTimeIssueInfo,
387
- verifyAbleTimeConnection
388
- } from "./chunk-VZJVKQHH.js";
389
- import {
390
- formatFetchError,
391
- httpFetch,
392
- setHttpFetchImpl
393
- } from "./chunk-ELBYOGVA.js";
394
- import {
395
- LEGACY_PLAN_FILE_REL,
396
- PLAN_FILE_NAME,
397
- PLAN_FILE_REL,
398
- extractPresentedPlan,
399
- isPresentPlanToolName,
400
- planFileAbs,
401
- readPlanFile,
402
- resolvePlanMarkdown,
403
- writePlanFile
404
- } from "./chunk-QTUESPAW.js";
405
- import "./chunk-AXQ4ZWHK.js";
406
- import {
407
- AGENT_RUNNER_MAX_OLD_SPACE_MB,
408
- applyAgentRunnerHeapEnv,
409
- cursorSdkMessageToEvents,
410
- parseCursorRunnerLine,
411
- preferredCursorCostCents,
412
- turnCostUsdFromCursorUsage,
413
- withMaxOldSpaceSize
414
- } from "./chunk-LAFA56WD.js";
415
- import {
416
- caffeinateHoldPath,
417
- getCaffeinateHold,
418
- isThreadCaffeinated,
419
- releaseCaffeinateHoldForThread,
420
- setCaffeinateHold
421
- } from "./chunk-DCOZABNT.js";
379
+ } from "./chunk-NOTANBYC.js";
422
380
  import {
423
381
  FAMOUS_SOCCER_TEAMS,
382
+ GITHUB_PR_BODY_MAX_CHARS,
383
+ GITHUB_PR_BODY_SAFE_CHARS,
424
384
  addPrStackLayer,
425
385
  allocateTeamName,
426
386
  allocateTeamSlug,
@@ -429,6 +389,7 @@ import {
429
389
  branchDisplayLabel,
430
390
  canonicalizeRepoPath,
431
391
  checkoutPrStackLayer,
392
+ clampGithubPrBody,
432
393
  codexSandboxWritableRootsArgs,
433
394
  codexUnattendedGitConfigArgs,
434
395
  collectTakenTeamSlugs,
@@ -459,9 +420,11 @@ import {
459
420
  ghHeadRef,
460
421
  ghRepoSelectArgs,
461
422
  githubAgentGitEnv,
423
+ githubHttpsInsteadOfEntries,
462
424
  initPrStack,
463
425
  isDefaultishSourceRef,
464
426
  isDirty,
427
+ isGhPrBodyTooLongError,
465
428
  isGhRateLimitError,
466
429
  isInPrStack,
467
430
  isPlaceholderBranch,
@@ -505,14 +468,52 @@ import {
505
468
  worktreeDisplayLabel,
506
469
  worktreeDisplayLabelForGroup,
507
470
  worktreeNameFromPath
508
- } from "./chunk-YP3CSOZ6.js";
471
+ } from "./chunk-ZGFYFVJF.js";
509
472
  import {
510
473
  ATTACHMENTS_DIR,
511
474
  LEGACY_ATTACHMENTS_DIR,
512
475
  attachmentsGitignoreBody,
513
476
  isWorkspaceScratchPath
514
- } from "./chunk-FKOIHGKV.js";
477
+ } from "./chunk-WHU7YGWP.js";
478
+ import {
479
+ ABLETIME_MCP_PATH,
480
+ DEFAULT_ABLETIME_HOST,
481
+ abletimeMcpRequest,
482
+ abletimeMcpUrl,
483
+ callAbleTimeTool,
484
+ createAbleTimeTask,
485
+ ensureAbleTimeTask,
486
+ getAbleTimeOrientation,
487
+ getAbleTimeTask,
488
+ issueAttachmentForAbleTimeTask,
489
+ listAbleTimeAssignedIssues,
490
+ listAbleTimeProjects,
491
+ listAbleTimeTasks,
492
+ mapAbleTimeTask,
493
+ normalizeAbleTimeHost,
494
+ rewriteAbleTimeError,
495
+ searchAbleTimeTasks,
496
+ taskUrl,
497
+ toAbleTimeIssueInfo,
498
+ verifyAbleTimeConnection
499
+ } from "./chunk-WLV7TRMR.js";
515
500
  import {
501
+ formatFetchError,
502
+ httpFetch,
503
+ setHttpFetchImpl
504
+ } from "./chunk-ELBYOGVA.js";
505
+ import "./chunk-AXQ4ZWHK.js";
506
+ import {
507
+ AGENT_RUNNER_MAX_OLD_SPACE_MB,
508
+ applyAgentRunnerHeapEnv,
509
+ cursorSdkMessageToEvents,
510
+ parseCursorRunnerLine,
511
+ preferredCursorCostCents,
512
+ turnCostUsdFromCursorUsage,
513
+ withMaxOldSpaceSize
514
+ } from "./chunk-HEII7W3Q.js";
515
+ import {
516
+ FOLLOW_UP_BEHAVIORS,
516
517
  GITHUB_GIT_AUTH_MODES,
517
518
  HARNESS_ENV_KEYS,
518
519
  ISSUE_SOURCE_LABELS,
@@ -538,6 +539,7 @@ import {
538
539
  disconnectLinearConnection,
539
540
  emptyPublicIntegrations,
540
541
  ensureSlackDeviceIdentity,
542
+ followUpBehavior,
541
543
  getAbleTimeAccessToken,
542
544
  getAbleTimeHost,
543
545
  getDefaultAgent,
@@ -583,10 +585,17 @@ import {
583
585
  updateDefaultsSettings,
584
586
  updateIntegrationsSettings,
585
587
  updateOpencodeSettings
586
- } from "./chunk-I77RYPOH.js";
588
+ } from "./chunk-4XNSGDXE.js";
587
589
  import {
588
590
  stripNestedElectronEnv
589
591
  } from "./chunk-4TR3HZFT.js";
592
+ import {
593
+ caffeinateHoldPath,
594
+ getCaffeinateHold,
595
+ isThreadCaffeinated,
596
+ releaseCaffeinateHoldForThread,
597
+ setCaffeinateHold
598
+ } from "./chunk-DCOZABNT.js";
590
599
  import "./chunk-JT7R45JB.js";
591
600
  import {
592
601
  appendMessage,
@@ -640,6 +649,7 @@ import {
640
649
  workspaceSettingsSourceLabel,
641
650
  worktreesRoot
642
651
  } from "./chunk-QZQEXME2.js";
652
+ import "./chunk-Y4NAPW5I.js";
643
653
  import {
644
654
  conductorBundledBinDir,
645
655
  enrichPathWithNpmGlobalBin,
@@ -653,7 +663,7 @@ import {
653
663
  resolveGitDirsForLockRecovery,
654
664
  run,
655
665
  withExportedPath
656
- } from "./chunk-DVM4ID64.js";
666
+ } from "./chunk-UFHNSFAS.js";
657
667
 
658
668
  // src/integrations/github.ts
659
669
  async function getGitHubStatus() {
@@ -1053,6 +1063,22 @@ query SideboardAssignedIssues($first: Int!) {
1053
1063
  }
1054
1064
  }
1055
1065
  `;
1066
+ var ISSUES_QUERY = `
1067
+ query SideboardIssues($first: Int!, $filter: IssueFilter) {
1068
+ viewer { id name }
1069
+ issues(first: $first, orderBy: updatedAt, filter: $filter) {
1070
+ nodes { ${LIST_ISSUE_FIELDS} }
1071
+ }
1072
+ }
1073
+ `;
1074
+ var SEARCH_ISSUES_QUERY = `
1075
+ query SideboardSearchIssues($term: String!, $first: Int!, $filter: IssueFilter) {
1076
+ viewer { id name }
1077
+ searchIssues(term: $term, first: $first, includeArchived: false, filter: $filter) {
1078
+ nodes { ${LIST_ISSUE_FIELDS} }
1079
+ }
1080
+ }
1081
+ `;
1056
1082
  var TEAMS_QUERY = `
1057
1083
  query SideboardTeams {
1058
1084
  viewer { id name }
@@ -1336,19 +1362,76 @@ function normalizePriority(priority) {
1336
1362
  }
1337
1363
  return priority;
1338
1364
  }
1339
- async function listLinearAssignedIssues(opts) {
1340
- const first = Math.max(1, Math.min(250, opts?.limit ?? 200));
1341
- const json = await linearGraphql(ASSIGNED_ISSUES_QUERY, { first }, opts);
1365
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1366
+ function assigneeFilterKey(assignee) {
1367
+ return (assignee ?? "").trim();
1368
+ }
1369
+ function buildLinearIssueFilter(input) {
1370
+ const filter = {
1371
+ state: { type: { nin: ["completed", "canceled"] } }
1372
+ };
1373
+ const raw = assigneeFilterKey(input?.assignee) || "me";
1374
+ const key = raw.toLowerCase();
1375
+ if (key === "all" || key === "*") return filter;
1376
+ if (key === "unassigned" || key === "none" || key === "null") {
1377
+ filter.assignee = { null: true };
1378
+ return filter;
1379
+ }
1380
+ if (key === "me" || key === "@me") {
1381
+ filter.assignee = { isMe: true };
1382
+ return filter;
1383
+ }
1384
+ if (UUID_RE.test(raw)) {
1385
+ filter.assignee = { id: { eq: raw } };
1386
+ return filter;
1387
+ }
1388
+ filter.assignee = { name: { eqIgnoreCase: raw } };
1389
+ return filter;
1390
+ }
1391
+ function isAssignedToMe(assignee) {
1392
+ const key = assignee.toLowerCase();
1393
+ return key === "me" || key === "@me";
1394
+ }
1395
+ function listedLinearIssues(json, nodes) {
1342
1396
  return {
1343
1397
  viewer: {
1344
1398
  id: String(json.viewer?.id ?? ""),
1345
1399
  name: String(json.viewer?.name ?? "")
1346
1400
  },
1347
- issues: (json.viewer?.assignedIssues?.nodes ?? []).map(
1348
- (node) => toIssueInfo(mapIssue(node))
1349
- )
1401
+ issues: (nodes ?? []).map((node) => toIssueInfo(mapIssue(node)))
1350
1402
  };
1351
1403
  }
1404
+ async function listLinearIssuesFiltered(opts) {
1405
+ const first = Math.max(1, Math.min(250, opts?.limit ?? 200));
1406
+ const query = opts?.query?.trim() ?? "";
1407
+ const assignee = assigneeFilterKey(opts?.assignee) || (query ? "all" : "me");
1408
+ const filter = buildLinearIssueFilter({ assignee });
1409
+ if (query) {
1410
+ const json2 = await linearGraphql(
1411
+ SEARCH_ISSUES_QUERY,
1412
+ { term: query, first, filter },
1413
+ opts
1414
+ );
1415
+ return listedLinearIssues(json2, json2.searchIssues?.nodes);
1416
+ }
1417
+ if (isAssignedToMe(assignee)) {
1418
+ const json2 = await linearGraphql(
1419
+ ASSIGNED_ISSUES_QUERY,
1420
+ { first },
1421
+ opts
1422
+ );
1423
+ return listedLinearIssues(json2, json2.viewer?.assignedIssues?.nodes);
1424
+ }
1425
+ const json = await linearGraphql(
1426
+ ISSUES_QUERY,
1427
+ { first, filter },
1428
+ opts
1429
+ );
1430
+ return listedLinearIssues(json, json.issues?.nodes);
1431
+ }
1432
+ async function listLinearAssignedIssues(opts) {
1433
+ return listLinearIssuesFiltered({ ...opts, assignee: "me" });
1434
+ }
1352
1435
  async function listLinearIssuesDirect(opts) {
1353
1436
  return (await listLinearAssignedIssues(opts)).issues;
1354
1437
  }
@@ -1468,6 +1551,22 @@ async function validateLinearApiKey(apiKey) {
1468
1551
  }
1469
1552
 
1470
1553
  // src/integrations/issues.ts
1554
+ function assigneeKey(assignee) {
1555
+ return (assignee ?? "").trim().toLowerCase();
1556
+ }
1557
+ function issueMatchesAssignee(issue, assignee, viewerName = "") {
1558
+ const key = assigneeKey(assignee);
1559
+ if (!key || key === "all" || key === "*") return true;
1560
+ const names = [...issue.assignees ?? [], issue.assignee ?? ""].map((name) => name.trim().toLowerCase()).filter(Boolean);
1561
+ if (key === "unassigned" || key === "none" || key === "null") {
1562
+ return names.length === 0;
1563
+ }
1564
+ if (key === "me" || key === "@me") {
1565
+ const me = viewerName.trim().toLowerCase();
1566
+ return Boolean(me && names.includes(me));
1567
+ }
1568
+ return names.includes(key);
1569
+ }
1471
1570
  async function listGitHubIssues(repoPath, opts) {
1472
1571
  const limit = Math.max(1, Math.min(1e3, opts?.limit ?? 200));
1473
1572
  const slug = await resolveGithubRepoSlug(repoPath);
@@ -1481,6 +1580,17 @@ async function listGitHubIssues(repoPath, opts) {
1481
1580
  "--state",
1482
1581
  "open"
1483
1582
  ];
1583
+ const query = opts?.query?.trim() ?? "";
1584
+ const assignee = opts?.assignee?.trim() ?? "";
1585
+ const key = assignee.toLowerCase();
1586
+ const searchParts = [];
1587
+ if (query) searchParts.push(query);
1588
+ if (key === "unassigned" || key === "none" || key === "null") {
1589
+ searchParts.push("no:assignee");
1590
+ } else if (key && key !== "all" && key !== "*") {
1591
+ args.push("--assignee", key === "me" || key === "@me" ? "@me" : assignee);
1592
+ }
1593
+ if (searchParts.length) args.push("--search", searchParts.join(" "));
1484
1594
  if (slug) args.push("--repo", slug);
1485
1595
  const { stdout, exitCode } = await gh(args, repoPath, { reject: false });
1486
1596
  if (exitCode !== 0 || !stdout.trim()) return [];
@@ -1518,14 +1628,20 @@ async function githubViewerLogin(repoPath) {
1518
1628
  if (exitCode !== 0) return "";
1519
1629
  return stdout.trim();
1520
1630
  }
1521
- async function listIssues(repoPath) {
1631
+ async function listIssues(repoPath, opts) {
1522
1632
  const settings = loadAppSettings();
1523
1633
  const preferredSource = settings.integrations.issueSource ?? "github";
1524
1634
  const linearConnected = isLinearConnected(settings);
1525
1635
  const abletimeConnected = isAbleTimeConnected(settings);
1526
1636
  const source = resolveEffectiveIssueSource(settings);
1637
+ const query = opts?.query?.trim() || void 0;
1638
+ const assignee = opts?.assignee?.trim() || void 0;
1527
1639
  if (source === "linear") {
1528
- const listed = await listLinearAssignedIssues();
1640
+ const listed = await listLinearIssuesFiltered({
1641
+ assignee,
1642
+ query,
1643
+ limit: opts?.limit
1644
+ });
1529
1645
  return {
1530
1646
  source,
1531
1647
  preferredSource,
@@ -1539,13 +1655,20 @@ async function listIssues(repoPath) {
1539
1655
  };
1540
1656
  }
1541
1657
  if (source === "abletime") {
1542
- const listed = await listAbleTimeAssignedIssues();
1658
+ const [listed, searched] = await Promise.all([
1659
+ listAbleTimeAssignedIssues(),
1660
+ query ? searchAbleTimeTasks(query) : Promise.resolve(null)
1661
+ ]);
1662
+ const viewerName = listed.viewer.name ?? listed.viewer.id ?? "";
1663
+ const issues2 = (searched ? searched.map(toAbleTimeIssueInfo) : listed.issues).filter(
1664
+ (issue) => issueMatchesAssignee(issue, assignee, viewerName)
1665
+ );
1543
1666
  return {
1544
1667
  source,
1545
1668
  preferredSource,
1546
1669
  linearConnected,
1547
1670
  abletimeConnected,
1548
- issues: listed.issues,
1671
+ issues: issues2,
1549
1672
  viewer: {
1550
1673
  login: listed.viewer.name,
1551
1674
  name: listed.viewer.name
@@ -1553,7 +1676,7 @@ async function listIssues(repoPath) {
1553
1676
  };
1554
1677
  }
1555
1678
  const [issues, login] = await Promise.all([
1556
- listGitHubIssues(repoPath),
1679
+ listGitHubIssues(repoPath, { assignee, query, limit: opts?.limit }),
1557
1680
  githubViewerLogin(repoPath)
1558
1681
  ]);
1559
1682
  return {
@@ -1939,7 +2062,7 @@ function lastMessagePreview(messages, max = 160) {
1939
2062
  if (!messages?.length) return null;
1940
2063
  for (let i = messages.length - 1; i >= 0; i--) {
1941
2064
  const text5 = messages[i]?.text?.trim();
1942
- if (!text5) continue;
2065
+ if (!text5 || isInternalAgentStatusText(text5)) continue;
1943
2066
  const flat = text5.replace(/\s+/g, " ");
1944
2067
  return flat.length > max ? `${flat.slice(0, max)}\u2026` : flat;
1945
2068
  }
@@ -2604,6 +2727,22 @@ function registerLinearTools(server) {
2604
2727
  }
2605
2728
  }
2606
2729
  );
2730
+ server.tool(
2731
+ "linear_search_issues",
2732
+ "Search or list open Linear issues. Not limited to the current user \u2014 pass assignee=unassigned for issues with no owner, assignee=all (default when query is set) for anyone including unassigned, assignee=me for yours, or a user id / name. Optional query uses Linear search (title, identifier, description).",
2733
+ {
2734
+ query: z3.string().optional().describe("Search text (identifier, title, description). Omit to list by assignee only."),
2735
+ assignee: z3.string().optional().describe("me, unassigned, all, a Linear user id, or a display name. Default: all when query is set, otherwise me."),
2736
+ limit: z3.number().int().positive().max(250).optional()
2737
+ },
2738
+ async ({ query, assignee, limit }) => {
2739
+ try {
2740
+ return text3(await listLinearIssuesFiltered({ query, assignee, limit }));
2741
+ } catch (err) {
2742
+ return fail3(err);
2743
+ }
2744
+ }
2745
+ );
2607
2746
  server.tool(
2608
2747
  "linear_get_issue",
2609
2748
  "Get a Linear issue by uuid or identifier (ENG-123). Returns description, comments, relations (blocks/blockedBy/related/duplicate), parent/children, project, cycle, labels, and other metadata.",
@@ -3229,7 +3368,7 @@ async function startMcpServer() {
3229
3368
  );
3230
3369
  }
3231
3370
  try {
3232
- const { maxConcurrentAgents: maxConcurrentAgents2 } = await import("./app-settings-WJDCJFSY.js");
3371
+ const { maxConcurrentAgents: maxConcurrentAgents2 } = await import("./app-settings-3CHCNIMD.js");
3233
3372
  orch.setMaxConcurrent(maxConcurrentAgents2());
3234
3373
  } catch {
3235
3374
  }
@@ -3274,12 +3413,12 @@ async function startMcpServer() {
3274
3413
  const threads = orch.getThreads(true);
3275
3414
  const lines = threads.map((t) => {
3276
3415
  const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : basename(t.repoPath) || t.repoPath;
3277
- const live = t.status === "running" || t.status === "queued" ? readTurnLive(t.id) : null;
3416
+ const live = orch.threadLooksLive(t) ? readTurnLive(t.id) : null;
3278
3417
  const parent = t.parentThreadId ? ` parent:${t.parentThreadId.slice(0, 8)}` : "";
3279
3418
  const preview = lastMessagePreview(t.messages, 80);
3280
3419
  const previewBit = preview ? ` ${preview}` : "";
3281
3420
  const err = t.lastError ? ` error:${t.lastError.replace(/\s+/g, " ").slice(0, 60)}` : "";
3282
- const progress = live?.summary ? ` ${live.summary}` : "";
3421
+ const progress = live?.summary && !isInternalAgentStatusText(live.summary) ? ` ${live.summary}` : "";
3283
3422
  return `${t.id.slice(0, 8)} ${t.status.padEnd(9)} ${t.agent.padEnd(8)} ${repo} ${t.sourceType}:${t.sourceRef} ${t.title}${parent}${previewBit}${err} sideboard://thread/${t.id}${t.devPort ? ` http://localhost:${t.devPort}` : ""}${progress}`;
3284
3423
  });
3285
3424
  return {
@@ -3341,7 +3480,9 @@ async function startMcpServer() {
3341
3480
  if (!t) {
3342
3481
  return { content: [{ type: "text", text: `Thread not found: ${ref}` }], isError: true };
3343
3482
  }
3344
- const live = t.status === "running" || t.status === "queued" ? readTurnLive(t.id) : null;
3483
+ const stillRunning = orch.threadLooksLive(t);
3484
+ const live = stillRunning ? readTurnLive(t.id) : null;
3485
+ const liveSummary = live?.summary && !isInternalAgentStatusText(live.summary) ? live.summary : null;
3345
3486
  const spend = orch.getThreadUsage(t.id);
3346
3487
  const summary = {
3347
3488
  id: t.id,
@@ -3361,8 +3502,8 @@ async function startMcpServer() {
3361
3502
  devPort: t.devPort,
3362
3503
  prUrl: t.prUrl,
3363
3504
  lastError: t.lastError ?? null,
3364
- stillRunning: t.status === "running" || t.status === "queued",
3365
- progress: live?.summary ?? (t.status === "queued" ? "Queued \u2014 waiting for a concurrency slot" : null),
3505
+ stillRunning,
3506
+ progress: liveSummary ?? (stillRunning && t.status === "queued" ? "Queued \u2014 waiting for a concurrency slot" : null),
3366
3507
  lastActivityAt: live?.updatedAt ?? null,
3367
3508
  usage: spend.usage,
3368
3509
  lastTurnUsage: spend.lastTurnUsage
@@ -3438,7 +3579,7 @@ async function startMcpServer() {
3438
3579
  thread_id: z5.string().optional().describe("Sideboard thread id when cwd is not the worktree")
3439
3580
  },
3440
3581
  async ({ title, content, thread_id }) => {
3441
- const { writePlanFile: writePlanFile2 } = await import("./plan-file-6O7G4VPQ.js");
3582
+ const { writePlanFile: writePlanFile2 } = await import("./plan-file-5S5TUNAW.js");
3442
3583
  let root = process.cwd();
3443
3584
  if (thread_id?.trim()) {
3444
3585
  const t = orch.getThread(thread_id.trim());
@@ -3511,7 +3652,7 @@ async function startMcpServer() {
3511
3652
  registerAbleTimeTools(server);
3512
3653
  registerScheduleTools(server);
3513
3654
  const { getCaffeinateHold: getCaffeinateHold2, setCaffeinateHold: setCaffeinateHold2 } = await import("./caffeinate-hold-X3JNPR42.js");
3514
- const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await import("./app-settings-WJDCJFSY.js");
3655
+ const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await import("./app-settings-3CHCNIMD.js");
3515
3656
  const accountDefaults = resolveThreadDefaults2();
3516
3657
  const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
3517
3658
  server.tool(
@@ -3719,7 +3860,7 @@ async function startMcpServer() {
3719
3860
  );
3720
3861
  server.tool(
3721
3862
  "wait_for_turn",
3722
- "Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not send a check-in prompt, force_stop, or assume a hang. On status error, lastError/text is the failure. On status stopped or broken, the child did not finish \u2014 resume with send_to_thread or tell the user; do not treat that as success. When finished, usage is the last agent turn\u2019s tokens + costUsd (when the provider reported cost).",
3863
+ "Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. stillRunning is the source of truth \u2014 if false, the child is not working (do not say it is waiting for a gate). If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not send a check-in prompt, force_stop, or assume a hang. On status error, lastError/text is the failure. On status stopped or broken, the child did not finish \u2014 resume with send_to_thread or tell the user; do not treat that as success. When finished, usage is the last agent turn\u2019s tokens + costUsd (when the provider reported cost).",
3723
3864
  {
3724
3865
  ref: z5.string(),
3725
3866
  timeoutMs: z5.number().optional()
@@ -3911,7 +4052,7 @@ async function startMcpServer() {
3911
4052
  );
3912
4053
  server.tool(
3913
4054
  "ask_git",
3914
- "Commit & push, open a draft PR, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` if SSH is missing). When dirty, queues the worktree agent to commit; then wait_for_turn (loop while stillRunning). Pass a worktree thread ref (not the orchestrator). action=merge only when the user explicitly asked to merge that PR. Do not run git or gh from the orchestration cwd.",
4055
+ "Commit & push, open a draft PR, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty, queues the worktree agent to commit; then wait_for_turn (loop while stillRunning). Pass a worktree thread ref (not the orchestrator). action=merge only when the user explicitly asked to merge that PR. Do not run git or gh from the orchestration cwd. If this tool errors that the GraphQL/PR body is too long, the branch is already pushed \u2014 have the worktree agent retry `gh pr create --body-file` with a short description (GitHub limit 65,536 characters). Do not invent SSH/auth failures from that error.",
3915
4056
  {
3916
4057
  ref: z5.string().describe("Worktree thread id/ref"),
3917
4058
  action: z5.enum(AGENT_GIT_ACTIONS).describe(
@@ -3936,8 +4077,26 @@ async function startMcpServer() {
3936
4077
  ]
3937
4078
  };
3938
4079
  } catch (err) {
3939
- const message = err instanceof Error ? err.message : String(err);
3940
- return { content: [{ type: "text", text: message }], isError: true };
4080
+ const raw = err instanceof Error ? err.message : String(err);
4081
+ const message = formatGhLandError(raw);
4082
+ return {
4083
+ content: [
4084
+ {
4085
+ type: "text",
4086
+ text: JSON.stringify(
4087
+ {
4088
+ error: true,
4089
+ action,
4090
+ lastError: message,
4091
+ hint: /body is too long/i.test(message) ? "Branch is already pushed. send_to_thread so the worktree agent runs gh pr create --draft -R <origin> --body-file <short.md>. Keep the description short." : void 0
4092
+ },
4093
+ null,
4094
+ 2
4095
+ )
4096
+ }
4097
+ ],
4098
+ isError: true
4099
+ };
3941
4100
  }
3942
4101
  }
3943
4102
  );
@@ -4332,11 +4491,15 @@ async function startMcpServer() {
4332
4491
  );
4333
4492
  server.tool(
4334
4493
  "list_issues",
4335
- "List issues from Sideboard Account connections (Linear, AbleTime MCP, or GitHub Issues; falls back to GitHub when the preferred tracker is not connected). Linear/AbleTime are account-wide; GitHub Issues are scoped to repoPath from list_workspaces. When AbleTime is the issue source and work has no ticket, call abletime_ensure_task (or create_thread from the default branch \u2014 Sideboard auto-creates a task to track against). Prefer list_board for Home columns. Then create_thread with sourceType=ticket.",
4336
- { repoPath: z5.string() },
4337
- async ({ repoPath }) => {
4494
+ "List or search issues from Sideboard Account connections (Linear, AbleTime MCP, or GitHub Issues; falls back to GitHub when the preferred tracker is not connected). Linear defaults to issues assigned to you; pass assignee=unassigned for no owner, assignee=all for everyone (including unassigned), or a user id / GitHub login. Optional query searches title/identifier. Linear/AbleTime are account-wide; GitHub Issues are scoped to repoPath from list_workspaces. Prefer linear_search_issues when Linear is connected and you need unassigned or other people's tickets. When AbleTime is the issue source and work has no ticket, call abletime_ensure_task (or create_thread from the default branch \u2014 Sideboard auto-creates a task to track against). Prefer list_board for Home columns. Then create_thread with sourceType=ticket.",
4495
+ {
4496
+ repoPath: z5.string(),
4497
+ query: z5.string().optional().describe("Search title, identifier, or description"),
4498
+ assignee: z5.string().optional().describe("me (Linear default), unassigned, all, a user id, or a GitHub login")
4499
+ },
4500
+ async ({ repoPath, query, assignee }) => {
4338
4501
  const root = await resolveRepoRoot(repoPath);
4339
- const result = await listIssues(root);
4502
+ const result = await listIssues(root, { query, assignee });
4340
4503
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
4341
4504
  }
4342
4505
  );
@@ -6656,7 +6819,10 @@ export {
6656
6819
  DEFAULT_ABLETIME_HOST,
6657
6820
  DEFAULT_WORKTREE_SORT,
6658
6821
  FAMOUS_SOCCER_TEAMS,
6822
+ FOLLOW_UP_BEHAVIORS,
6659
6823
  GITHUB_GIT_AUTH_MODES,
6824
+ GITHUB_PR_BODY_MAX_CHARS,
6825
+ GITHUB_PR_BODY_SAFE_CHARS,
6660
6826
  GLOBAL_WORKSPACE_ID,
6661
6827
  HARNESS_ENV_KEYS,
6662
6828
  HOME_BOARD_CACHE_TTL_MS,
@@ -6668,6 +6834,7 @@ export {
6668
6834
  LINEAR_OAUTH_PORT,
6669
6835
  LINEAR_OAUTH_REDIRECT,
6670
6836
  LINEAR_OAUTH_SCOPES,
6837
+ LIVE_TURN_SPAWN_GRACE_MS,
6671
6838
  LONG_RUNNING_SKILL_COMMAND,
6672
6839
  LinearOAuthCancelledError,
6673
6840
  MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS,
@@ -6757,6 +6924,7 @@ export {
6757
6924
  buildCodeRefAttachment,
6758
6925
  buildDiffCommentAttachment,
6759
6926
  buildForkTranscriptAttachment,
6927
+ buildLinearIssueFilter,
6760
6928
  buildPastedTextAttachment,
6761
6929
  buildPathRefAttachment,
6762
6930
  buildReviewRequestAttachment,
@@ -6774,6 +6942,7 @@ export {
6774
6942
  checkoutPrStackLayer,
6775
6943
  childEnvWithAppSettings,
6776
6944
  claimDesktopHost,
6945
+ clampGithubPrBody,
6777
6946
  classifyWorktreeColumn,
6778
6947
  claudeAdapter,
6779
6948
  claudeChromeEnabled,
@@ -6878,6 +7047,7 @@ export {
6878
7047
  fireSchedule,
6879
7048
  flattenTurnInput,
6880
7049
  flipLinearRelationType,
7050
+ followUpBehavior,
6881
7051
  forkChatTab,
6882
7052
  forkMessageSlice,
6883
7053
  forkThreadWorktree,
@@ -6956,6 +7126,7 @@ export {
6956
7126
  ghRepoSelectArgs,
6957
7127
  git,
6958
7128
  githubAgentGitEnv,
7129
+ githubHttpsInsteadOfEntries,
6959
7130
  globalAgentCwd,
6960
7131
  groupHomeBoardWorktrees,
6961
7132
  handleSlackInbound,
@@ -6992,6 +7163,7 @@ export {
6992
7163
  isDefaultishSourceRef,
6993
7164
  isDesktopHostAlive,
6994
7165
  isDirty,
7166
+ isGhPrBodyTooLongError,
6995
7167
  isGhRateLimitError,
6996
7168
  isGlobalRepoPath,
6997
7169
  isGlobalThread,
@@ -6999,6 +7171,7 @@ export {
6999
7171
  isImageFilePath,
7000
7172
  isInPrStack,
7001
7173
  isInboundForThisDesktop,
7174
+ isInternalAgentStatusText,
7002
7175
  isIssueSourceConnected,
7003
7176
  isLinearConnected,
7004
7177
  isLinearOAuthCancelled,
@@ -7025,6 +7198,7 @@ export {
7025
7198
  isThreadRecordFile,
7026
7199
  isWorkspaceScratchPath,
7027
7200
  issueAttachmentForAbleTimeTask,
7201
+ issueMatchesAssignee,
7028
7202
  issueSourceLabel,
7029
7203
  lastRequestOccupancy,
7030
7204
  latestPendingPlanQuestions,
@@ -7052,6 +7226,7 @@ export {
7052
7226
  listLinearAssignedIssues,
7053
7227
  listLinearIssues,
7054
7228
  listLinearIssuesDirect,
7229
+ listLinearIssuesFiltered,
7055
7230
  listLinearTeams,
7056
7231
  listModelsForAgent,
7057
7232
  listOpencodeModels,