@sideboard-ai/core 0.1.177 → 0.1.179

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 (31) hide show
  1. package/dist/{agents-544IX5KA.js → agents-2UD26PUT.js} +4 -4
  2. package/dist/{agents-UENEQ6J2.js → agents-XPWZG3JU.js} +4 -4
  3. package/dist/{chunk-3ZFGZ7RT.js → chunk-7T5XKNOF.js} +2 -2
  4. package/dist/{chunk-LZQULFIT.js → chunk-GOZ6T3AG.js} +2 -0
  5. package/dist/{chunk-DVYRABZC.js → chunk-GVC4IVF5.js} +76 -16
  6. package/dist/{chunk-NIB6BTC6.js → chunk-IVJFEB3T.js} +3 -3
  7. package/dist/{chunk-DJUDDKXM.js → chunk-MZOZ6PIZ.js} +75 -15
  8. package/dist/{chunk-7UURXPKD.js → chunk-TCQAFTSV.js} +2 -0
  9. package/dist/{chunk-W44EKPIR.js → chunk-VUFJ5MAN.js} +3 -3
  10. package/dist/{chunk-7JIYKYLL.js → chunk-WXKXSZN4.js} +10 -7
  11. package/dist/{chunk-7O53GXTA.js → chunk-XBLN52RZ.js} +10 -7
  12. package/dist/{chunk-FJWQCZ74.js → chunk-XV3EFFZ6.js} +2 -2
  13. package/dist/{coordinator-prompt-PRM5ARWG.js → coordinator-prompt-3NRUXH3F.js} +3 -3
  14. package/dist/{coordinator-prompt-BE2FERYE.js → coordinator-prompt-GKH7Q7PK.js} +3 -3
  15. package/dist/{global-workspace-3HIWNQ3B.js → global-workspace-2FQU62S2.js} +3 -3
  16. package/dist/{global-workspace-J737XNUX.js → global-workspace-C2JMJXYV.js} +3 -3
  17. package/dist/index.cjs +82 -11
  18. package/dist/index.d.cts +16 -1
  19. package/dist/index.d.ts +16 -1
  20. package/dist/index.js +13 -7
  21. package/dist/mcp/run-stdio.cjs +127 -11
  22. package/dist/mcp/run-stdio.js +59 -8
  23. package/dist/{orchestrator-FTGAFZMK.js → orchestrator-HOMNNKMT.js} +5 -5
  24. package/dist/{orchestrator-XAJ3LREM.js → orchestrator-WNFMRRQP.js} +5 -5
  25. package/dist/{thread-store-KBFBHT5G.js → thread-store-RXXNSRVO.js} +1 -1
  26. package/dist/{thread-store-MVQU6HPJ.js → thread-store-ZL6GDIDP.js} +1 -1
  27. package/dist/{workspaces-ULHYXM4Y.js → workspaces-J3M3IPR3.js} +3 -3
  28. package/dist/{workspaces-DR4UNOQC.js → workspaces-YVZYX5H2.js} +3 -3
  29. package/dist/{worktree-LC4VRWDM.js → worktree-7LOSSD7G.js} +2 -2
  30. package/dist/{worktree-UTDBQXSS.js → worktree-LPWTX2NA.js} +2 -2
  31. package/package.json +1 -1
@@ -866,6 +866,8 @@ function createEmptyThread(partial) {
866
866
  prTitle: partial.prTitle ?? null,
867
867
  prState: partial.prState ?? null,
868
868
  prIsDraft: Boolean(partial.prIsDraft),
869
+ prAuthorLogin: partial.prAuthorLogin?.trim() || null,
870
+ prReviewerLogins: partial.prReviewerLogins ?? [],
869
871
  skipAutoArchiveOnMerge: partial.skipAutoArchiveOnMerge ?? false,
870
872
  cowboy: Boolean(partial.cowboy),
871
873
  stackId: partial.stackId ?? null,
@@ -6166,7 +6168,7 @@ async function getPr(repoPath, number) {
6166
6168
  "view",
6167
6169
  String(number),
6168
6170
  "--json",
6169
- "number,title,headRefName,url,isCrossRepository"
6171
+ "number,title,headRefName,url,isCrossRepository,author"
6170
6172
  ];
6171
6173
  if (slug) args.push("--repo", slug);
6172
6174
  const { stdout, exitCode } = await gh(args, repoPath, { reject: false });
@@ -6212,7 +6214,7 @@ async function getPrForHeadBranch(repoPath, branch) {
6212
6214
  "view",
6213
6215
  head,
6214
6216
  "--json",
6215
- "number,title,headRefName,url,isCrossRepository"
6217
+ "number,title,headRefName,url,isCrossRepository,author"
6216
6218
  ];
6217
6219
  if (slug) viewArgs.push("--repo", slug);
6218
6220
  const viewed = await gh(viewArgs, repoPath, { reject: false });
@@ -6230,7 +6232,7 @@ async function getPrForHeadBranch(repoPath, branch) {
6230
6232
  "--head",
6231
6233
  listHead,
6232
6234
  "--json",
6233
- "number,title,headRefName,url,isCrossRepository",
6235
+ "number,title,headRefName,url,isCrossRepository,author",
6234
6236
  "--limit",
6235
6237
  "1",
6236
6238
  "--state",
@@ -6432,7 +6434,7 @@ async function getPrMeta(cwd, selector) {
6432
6434
  "view",
6433
6435
  selector,
6434
6436
  "--json",
6435
- "number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus,mergeable"
6437
+ "number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus,mergeable,author,reviewRequests"
6436
6438
  ];
6437
6439
  if (slug) viewArgs.push("--repo", slug);
6438
6440
  let { stdout, exitCode, stderr } = await gh(viewArgs, cwd, { reject: false });
@@ -6442,7 +6444,7 @@ async function getPrMeta(cwd, selector) {
6442
6444
  "view",
6443
6445
  selector,
6444
6446
  "--json",
6445
- "number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus,mergeable"
6447
+ "number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus,mergeable,author,reviewRequests"
6446
6448
  ];
6447
6449
  if (slug) retry.push("--repo", slug);
6448
6450
  ({ stdout, exitCode, stderr } = await gh(retry, cwd, { reject: false }));
@@ -6463,6 +6465,7 @@ async function getPrMeta(cwd, selector) {
6463
6465
  };
6464
6466
  const probed = await probeLocalMergeGate(cwd, gate);
6465
6467
  const resolved = probed.gate ?? gate;
6468
+ const author = view.author ?? {};
6466
6469
  return {
6467
6470
  number: Number(view.number),
6468
6471
  title: String(view.title ?? ""),
@@ -6474,7 +6477,9 @@ async function getPrMeta(cwd, selector) {
6474
6477
  headRefName: String(view.headRefName ?? ""),
6475
6478
  isInMergeQueue: Boolean(resolved.isInMergeQueue),
6476
6479
  mergeable: resolved.mergeable,
6477
- mergeStateStatus: resolved.mergeStateStatus
6480
+ mergeStateStatus: resolved.mergeStateStatus,
6481
+ authorLogin: author.login?.trim() || null,
6482
+ reviewerLogins: humanReviewerLogins(view.reviewRequests)
6478
6483
  };
6479
6484
  } catch {
6480
6485
  return null;
@@ -13023,6 +13028,8 @@ function worktreeBindingFrom(from) {
13023
13028
  prTitle: from.prTitle,
13024
13029
  prState: from.prState,
13025
13030
  prIsDraft: from.prIsDraft,
13031
+ prAuthorLogin: from.prAuthorLogin,
13032
+ prReviewerLogins: from.prReviewerLogins,
13026
13033
  skipAutoArchiveOnMerge: from.skipAutoArchiveOnMerge,
13027
13034
  stackId: from.stackId,
13028
13035
  stackLayer: from.stackLayer,
@@ -14659,6 +14666,35 @@ function groupHomeBoardWorktrees(threads, sort = DEFAULT_WORKTREE_SORT, labelOf
14659
14666
  }
14660
14667
  return [...map.values()].map((list) => sortThreadsInWorktree(list)).sort((a, b) => compareWorktreeGroups(a, b, sort, labelOf));
14661
14668
  }
14669
+ function normalizeViewerLogin(login) {
14670
+ return (login ?? "").trim().toLowerCase();
14671
+ }
14672
+ function loginsInclude(logins, viewerLogin) {
14673
+ const me = normalizeViewerLogin(viewerLogin);
14674
+ if (!me) return false;
14675
+ return (logins ?? []).some((login) => normalizeViewerLogin(login) === me);
14676
+ }
14677
+ function classifyWorktreeOwnership(group, viewerLogin = "") {
14678
+ const me = normalizeViewerLogin(viewerLogin);
14679
+ if (group.some((t) => {
14680
+ const author = normalizeViewerLogin(t.prAuthorLogin);
14681
+ return Boolean(author && me && author === me);
14682
+ })) {
14683
+ return "mine";
14684
+ }
14685
+ const reviewing = group.some((t) => {
14686
+ const author = normalizeViewerLogin(t.prAuthorLogin);
14687
+ if (author && me && author !== me) return true;
14688
+ if (t.sourceType === "pr" && (!author || !me || author !== me)) return true;
14689
+ if (me && loginsInclude(t.prReviewerLogins, me)) return true;
14690
+ return false;
14691
+ });
14692
+ return reviewing ? "reviewing" : "mine";
14693
+ }
14694
+ function worktreeMatchesOwnership(group, filter, viewerLogin = "") {
14695
+ if (filter === "all") return true;
14696
+ return classifyWorktreeOwnership(group, viewerLogin) === filter;
14697
+ }
14662
14698
  function classifyWorktreeColumn(group) {
14663
14699
  if (group.some((t) => isMergedPrState(t.prUrl, t.prState))) return "done";
14664
14700
  if (group.some((t) => isOpenPrState(t.prUrl, t.prState) && !t.prIsDraft)) {
@@ -14977,6 +15013,8 @@ function assembleHomeBoard(input) {
14977
15013
  const tokens = tokenizeQuery(input.query ?? "");
14978
15014
  const repo = input.repoPath?.trim() ?? "";
14979
15015
  const kind = input.kind ?? "all";
15016
+ const ownership = input.ownership ?? DEFAULT_BOARD_OWNERSHIP;
15017
+ const viewerLogin = input.viewerLogin ?? "";
14980
15018
  const limit = Math.max(1, input.limit ?? BOARD_PAGE_SIZE);
14981
15019
  const wsName = input.workspaceName ?? (() => "");
14982
15020
  const live = input.threads.filter((t) => t.status !== "archived" && isHomeBoardThread(t));
@@ -15005,6 +15043,7 @@ function assembleHomeBoard(input) {
15005
15043
  };
15006
15044
  for (const group of groupHomeBoardWorktrees(live)) {
15007
15045
  if (!group.some((t) => threadMatchesKind(t, kind))) continue;
15046
+ if (!worktreeMatchesOwnership(group, ownership, viewerLogin)) continue;
15008
15047
  const col = classifyWorktreeColumn(group);
15009
15048
  if (col === "backlog") continue;
15010
15049
  const primary = group[0];
@@ -15034,7 +15073,7 @@ function assembleHomeBoard(input) {
15034
15073
  }
15035
15074
  return { columns, hidden, totals };
15036
15075
  }
15037
- var GLOBAL_WORKSPACE_ID2, BOARD_COLUMN_DEFS, HOME_BOARD_CACHE_TTL_MS, DEFAULT_WORKTREE_SORT, DEFAULTISH_BRANCH, BOARD_PAGE_SIZE, HOME_BOARD_AGENT_HINT;
15076
+ var GLOBAL_WORKSPACE_ID2, BOARD_COLUMN_DEFS, HOME_BOARD_CACHE_TTL_MS, DEFAULT_WORKTREE_SORT, DEFAULT_BOARD_OWNERSHIP, DEFAULTISH_BRANCH, BOARD_PAGE_SIZE, HOME_BOARD_AGENT_HINT;
15038
15077
  var init_home_board = __esm({
15039
15078
  "src/board/home-board.ts"() {
15040
15079
  "use strict";
@@ -15049,9 +15088,10 @@ var init_home_board = __esm({
15049
15088
  ];
15050
15089
  HOME_BOARD_CACHE_TTL_MS = 15 * 60 * 1e3;
15051
15090
  DEFAULT_WORKTREE_SORT = "created";
15091
+ DEFAULT_BOARD_OWNERSHIP = "all";
15052
15092
  DEFAULTISH_BRANCH = /^(main|master|develop|development|trunk|default|head)$/;
15053
15093
  BOARD_PAGE_SIZE = 40;
15054
- HOME_BOARD_AGENT_HINT = "Home is a Kanban of worktrees (one card per checkout; sibling chat tabs nest as inner cards). Do not create a second worktree for a ticket, PR, or named branch that already has a live checkout \u2014 create_thread / start_board_card return that thread (alreadyStarted). Creating from the default branch still opens a new isolated worktree. Columns are the path to merge: New (no PR) \u2192 Draft (draft PR) \u2192 Review (open PR) \u2192 Merged. Archive removes the card to Settings \u2192 History. Queued/running are activity on the card, not columns. Orchestration chats stay in the sidebar. Do not invent status.";
15094
+ HOME_BOARD_AGENT_HINT = "Home is a Kanban of worktrees (one card per checkout; sibling chat tabs nest as inner cards). Do not create a second worktree for a ticket, PR, or named branch that already has a live checkout \u2014 create_thread / start_board_card return that thread (alreadyStarted). Creating from the default branch still opens a new isolated worktree. Columns are the path to merge: New (no PR) \u2192 Draft (draft PR) \u2192 Review (open PR) \u2192 Merged. ownership=mine is PRs you authored (or WIP with no PR); ownership=reviewing is someone else's PR (or a review-requested checkout). Viewer login comes from gh, not a setting. Archive removes the card to Settings \u2192 History. Queued/running are activity on the card, not columns. Orchestration chats stay in the sidebar. Do not invent status.";
15055
15095
  }
15056
15096
  });
15057
15097
 
@@ -15738,6 +15778,7 @@ async function createThread(input, _onSetupLine) {
15738
15778
  }
15739
15779
  let prUrl = null;
15740
15780
  let prTitle = null;
15781
+ let prAuthorLogin2 = null;
15741
15782
  if (sourceType === "pr") {
15742
15783
  const num2 = Number(input.sourceRef.replace(/^#/, ""));
15743
15784
  if (!Number.isFinite(num2)) throw new Error(`Invalid PR number: ${input.sourceRef}`);
@@ -15753,6 +15794,7 @@ async function createThread(input, _onSetupLine) {
15753
15794
  if (reusedPr) return reusedPr;
15754
15795
  sourceIsFork = pr.isCrossRepository;
15755
15796
  prUrl = pr.url;
15797
+ prAuthorLogin2 = pr.author?.login?.trim() || null;
15756
15798
  const localFetchBranch = `sideboard-pr-${pr.number}`;
15757
15799
  await fetchPrHead(repoPath, pr.number, localFetchBranch);
15758
15800
  sourceRef = localFetchBranch;
@@ -15775,6 +15817,7 @@ async function createThread(input, _onSetupLine) {
15775
15817
  if (existing.url) {
15776
15818
  prUrl = existing.url;
15777
15819
  prTitle = existing.title;
15820
+ prAuthorLogin2 = existing.author?.login?.trim() || null;
15778
15821
  }
15779
15822
  }
15780
15823
  }
@@ -15809,7 +15852,8 @@ async function createThread(input, _onSetupLine) {
15809
15852
  parentThreadId: input.parentThreadId ?? null,
15810
15853
  status: "idle",
15811
15854
  prUrl,
15812
- prTitle
15855
+ prTitle,
15856
+ prAuthorLogin: prAuthorLogin2
15813
15857
  });
15814
15858
  writeThread(thread);
15815
15859
  await ensureWorkspace(repoPath);
@@ -19184,6 +19228,11 @@ function isPidAlive(pid) {
19184
19228
  return false;
19185
19229
  }
19186
19230
  }
19231
+ function sameLoginList(a, b) {
19232
+ const left = [...a ?? []].map((s) => s.trim().toLowerCase()).filter(Boolean).sort();
19233
+ const right = [...b ?? []].map((s) => s.trim().toLowerCase()).filter(Boolean).sort();
19234
+ return left.length === right.length && left.every((login, i) => login === right[i]);
19235
+ }
19187
19236
  async function waitForPidExit(pid, timeoutMs) {
19188
19237
  const start = Date.now();
19189
19238
  while (isPidAlive(pid)) {
@@ -20960,6 +21009,14 @@ var init_orchestrator = __esm({
20960
21009
  if (nextState && nextState !== prevState) patch.prState = nextState;
20961
21010
  const nextDraft = Boolean(meta.isDraft) && nextState !== "MERGED" && nextState !== "CLOSED";
20962
21011
  if (nextDraft !== Boolean(thread.prIsDraft)) patch.prIsDraft = nextDraft;
21012
+ const nextAuthor = meta.authorLogin?.trim() || "";
21013
+ if (nextAuthor && nextAuthor !== (thread.prAuthorLogin ?? "").trim()) {
21014
+ patch.prAuthorLogin = nextAuthor;
21015
+ }
21016
+ const nextReviewers = meta.reviewerLogins ?? [];
21017
+ if (!sameLoginList(nextReviewers, thread.prReviewerLogins)) {
21018
+ patch.prReviewerLogins = nextReviewers;
21019
+ }
20963
21020
  if (thread.skipAutoArchiveOnMerge && nextState && nextState !== "MERGED" && nextState !== "CLOSED") {
20964
21021
  patch.skipAutoArchiveOnMerge = false;
20965
21022
  }
@@ -20987,6 +21044,14 @@ var init_orchestrator = __esm({
20987
21044
  const sibPatch = { prState: "MERGED", prIsDraft: false };
20988
21045
  if (meta.url && meta.url !== t.prUrl) sibPatch.prUrl = meta.url;
20989
21046
  if (meta.title && meta.title !== t.prTitle) sibPatch.prTitle = meta.title;
21047
+ const sibAuthor = meta.authorLogin?.trim() || "";
21048
+ if (sibAuthor && sibAuthor !== (t.prAuthorLogin ?? "").trim()) {
21049
+ sibPatch.prAuthorLogin = sibAuthor;
21050
+ }
21051
+ const sibReviewers = meta.reviewerLogins ?? [];
21052
+ if (!sameLoginList(sibReviewers, t.prReviewerLogins)) {
21053
+ sibPatch.prReviewerLogins = sibReviewers;
21054
+ }
20990
21055
  if (Object.keys(sibPatch).length > 0) updateThread(t.id, sibPatch);
20991
21056
  }
20992
21057
  for (const t of siblings) {
@@ -24233,6 +24298,51 @@ async function getHomeBoardInputs(workspaces, opts) {
24233
24298
  // src/mcp/server.ts
24234
24299
  init_home_board();
24235
24300
 
24301
+ // src/integrations/github.ts
24302
+ init_run();
24303
+ async function getGitHubStatus() {
24304
+ const which = await run("which", ["gh"], { reject: false });
24305
+ if (which.exitCode !== 0 || !which.stdout.trim()) {
24306
+ return {
24307
+ connected: false,
24308
+ login: null,
24309
+ hosts: [],
24310
+ reason: "gh CLI not found on PATH"
24311
+ };
24312
+ }
24313
+ const loginResult = await run(
24314
+ "gh",
24315
+ ["api", "user", "--jq", ".login"],
24316
+ { reject: false }
24317
+ );
24318
+ if (loginResult.exitCode === 0 && loginResult.stdout.trim()) {
24319
+ return {
24320
+ connected: true,
24321
+ login: loginResult.stdout.trim(),
24322
+ hosts: ["github.com"],
24323
+ reason: null
24324
+ };
24325
+ }
24326
+ const status = await run("gh", ["auth", "status"], { reject: false });
24327
+ const text7 = `${status.stdout}
24328
+ ${status.stderr}`;
24329
+ const loginMatch = text7.match(/Logged in to ([^\s]+) account (\S+)/i) ?? text7.match(/Logged in to ([^\s]+) as (\S+)/i);
24330
+ if (loginMatch) {
24331
+ return {
24332
+ connected: true,
24333
+ login: loginMatch[2].replace(/['"]/g, ""),
24334
+ hosts: [loginMatch[1]],
24335
+ reason: null
24336
+ };
24337
+ }
24338
+ return {
24339
+ connected: false,
24340
+ login: null,
24341
+ hosts: [],
24342
+ reason: status.stderr.trim() || status.stdout.trim() || "Not logged in to GitHub (run: gh auth login)"
24343
+ };
24344
+ }
24345
+
24236
24346
  // src/mcp/create-thread-agent.ts
24237
24347
  init_cursor();
24238
24348
  function resolveOrchCreateThreadOptions(input) {
@@ -24462,25 +24572,31 @@ async function startMcpServer() {
24462
24572
  );
24463
24573
  server.tool(
24464
24574
  "list_board",
24465
- "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.",
24575
+ "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), ownership (mine = your PRs / WIP; reviewing = someone else's PR), 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.",
24466
24576
  {
24467
24577
  query: import_zod8.z.string().optional().describe("Case-insensitive token search across title, id, labels, repo"),
24468
24578
  repoPath: import_zod8.z.string().optional().describe("Limit to one workspace path from list_workspaces"),
24469
24579
  kind: import_zod8.z.enum(["all", "tickets", "prs", "branches", "threads"]).optional().describe("Filter by worktree source (default all)"),
24580
+ ownership: import_zod8.z.enum(["all", "mine", "reviewing"]).optional().describe(
24581
+ "Mine = PRs you authored or local WIP; reviewing = someone else's PR. Uses the gh login."
24582
+ ),
24470
24583
  column: import_zod8.z.enum(["new", "draft", "review", "done", "needs_you"]).optional().describe(
24471
24584
  "Return cards for this column only (totals still include the rest). needs_you is a legacy alias for new."
24472
24585
  ),
24473
24586
  limit: import_zod8.z.number().int().positive().optional().describe("Max cards per column (default 40). hidden counts the remainder.")
24474
24587
  },
24475
- async ({ query, repoPath, kind, column, limit }) => {
24588
+ async ({ query, repoPath, kind, ownership, column, limit }) => {
24476
24589
  const workspaces = orch.listWorkspaces();
24477
24590
  const all = orch.getThreads(true);
24478
24591
  const names = new Map(workspaces.map((w) => [w.path, w.name]));
24592
+ const github = await getGitHubStatus();
24479
24593
  const snap = assembleHomeBoard({
24480
24594
  threads: all.filter((t) => t.status !== "archived"),
24481
24595
  query,
24482
24596
  repoPath,
24483
24597
  kind: kind ?? "all",
24598
+ ownership: ownership ?? "all",
24599
+ viewerLogin: github.login ?? "",
24484
24600
  column: column === "needs_you" ? "new" : column,
24485
24601
  limit,
24486
24602
  workspaceName: (path) => names.get(path) ?? ""
@@ -37,7 +37,7 @@ import {
37
37
  syncBoardPins,
38
38
  updateSchedule,
39
39
  waitForDetachedJob
40
- } from "../chunk-DJUDDKXM.js";
40
+ } from "../chunk-MZOZ6PIZ.js";
41
41
  import {
42
42
  applySystemCaEnv,
43
43
  isCursorApiKeyConfigured,
@@ -46,7 +46,7 @@ import {
46
46
  materializeSystemCaBundle,
47
47
  sideboardMcpProfile,
48
48
  trustSystemCertificates
49
- } from "../chunk-W44EKPIR.js";
49
+ } from "../chunk-VUFJ5MAN.js";
50
50
  import "../chunk-HVIEYTUK.js";
51
51
  import "../chunk-Y4MIXGPA.js";
52
52
  import {
@@ -71,7 +71,7 @@ import {
71
71
  GLOBAL_WORKSPACE_ID,
72
72
  isCloudCoordinatorThread,
73
73
  listWorkspaces
74
- } from "../chunk-FJWQCZ74.js";
74
+ } from "../chunk-XV3EFFZ6.js";
75
75
  import {
76
76
  canonicalizeRepoPath,
77
77
  formatGhLandError,
@@ -82,12 +82,13 @@ import {
82
82
  resolveListPrsOptions,
83
83
  resolveRepoRoot,
84
84
  warmGithubAgentAuth
85
- } from "../chunk-7O53GXTA.js";
85
+ } from "../chunk-XBLN52RZ.js";
86
86
  import "../chunk-D6JWYJ4P.js";
87
- import "../chunk-LZQULFIT.js";
87
+ import "../chunk-GOZ6T3AG.js";
88
88
  import "../chunk-SYFVUF2C.js";
89
89
  import {
90
- gh
90
+ gh,
91
+ run
91
92
  } from "../chunk-FNQNJOHY.js";
92
93
  import {
93
94
  disconnectLinearConnection,
@@ -2867,6 +2868,50 @@ async function getHomeBoardInputs(workspaces, opts) {
2867
2868
  }
2868
2869
  }
2869
2870
 
2871
+ // src/integrations/github.ts
2872
+ async function getGitHubStatus() {
2873
+ const which = await run("which", ["gh"], { reject: false });
2874
+ if (which.exitCode !== 0 || !which.stdout.trim()) {
2875
+ return {
2876
+ connected: false,
2877
+ login: null,
2878
+ hosts: [],
2879
+ reason: "gh CLI not found on PATH"
2880
+ };
2881
+ }
2882
+ const loginResult = await run(
2883
+ "gh",
2884
+ ["api", "user", "--jq", ".login"],
2885
+ { reject: false }
2886
+ );
2887
+ if (loginResult.exitCode === 0 && loginResult.stdout.trim()) {
2888
+ return {
2889
+ connected: true,
2890
+ login: loginResult.stdout.trim(),
2891
+ hosts: ["github.com"],
2892
+ reason: null
2893
+ };
2894
+ }
2895
+ const status = await run("gh", ["auth", "status"], { reject: false });
2896
+ const text7 = `${status.stdout}
2897
+ ${status.stderr}`;
2898
+ const loginMatch = text7.match(/Logged in to ([^\s]+) account (\S+)/i) ?? text7.match(/Logged in to ([^\s]+) as (\S+)/i);
2899
+ if (loginMatch) {
2900
+ return {
2901
+ connected: true,
2902
+ login: loginMatch[2].replace(/['"]/g, ""),
2903
+ hosts: [loginMatch[1]],
2904
+ reason: null
2905
+ };
2906
+ }
2907
+ return {
2908
+ connected: false,
2909
+ login: null,
2910
+ hosts: [],
2911
+ reason: status.stderr.trim() || status.stdout.trim() || "Not logged in to GitHub (run: gh auth login)"
2912
+ };
2913
+ }
2914
+
2870
2915
  // src/mcp/create-thread-agent.ts
2871
2916
  function resolveOrchCreateThreadOptions(input) {
2872
2917
  const { resolveNewThreadOptions } = input;
@@ -3095,25 +3140,31 @@ async function startMcpServer() {
3095
3140
  );
3096
3141
  server.tool(
3097
3142
  "list_board",
3098
- "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.",
3143
+ "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), ownership (mine = your PRs / WIP; reviewing = someone else's PR), 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.",
3099
3144
  {
3100
3145
  query: z8.string().optional().describe("Case-insensitive token search across title, id, labels, repo"),
3101
3146
  repoPath: z8.string().optional().describe("Limit to one workspace path from list_workspaces"),
3102
3147
  kind: z8.enum(["all", "tickets", "prs", "branches", "threads"]).optional().describe("Filter by worktree source (default all)"),
3148
+ ownership: z8.enum(["all", "mine", "reviewing"]).optional().describe(
3149
+ "Mine = PRs you authored or local WIP; reviewing = someone else's PR. Uses the gh login."
3150
+ ),
3103
3151
  column: z8.enum(["new", "draft", "review", "done", "needs_you"]).optional().describe(
3104
3152
  "Return cards for this column only (totals still include the rest). needs_you is a legacy alias for new."
3105
3153
  ),
3106
3154
  limit: z8.number().int().positive().optional().describe("Max cards per column (default 40). hidden counts the remainder.")
3107
3155
  },
3108
- async ({ query, repoPath, kind, column, limit }) => {
3156
+ async ({ query, repoPath, kind, ownership, column, limit }) => {
3109
3157
  const workspaces = orch.listWorkspaces();
3110
3158
  const all = orch.getThreads(true);
3111
3159
  const names = new Map(workspaces.map((w) => [w.path, w.name]));
3160
+ const github = await getGitHubStatus();
3112
3161
  const snap = assembleHomeBoard({
3113
3162
  threads: all.filter((t) => t.status !== "archived"),
3114
3163
  query,
3115
3164
  repoPath,
3116
3165
  kind: kind ?? "all",
3166
+ ownership: ownership ?? "all",
3167
+ viewerLogin: github.login ?? "",
3117
3168
  column: column === "needs_you" ? "new" : column,
3118
3169
  limit,
3119
3170
  workspaceName: (path) => names.get(path) ?? ""
@@ -6,11 +6,11 @@ import {
6
6
  resolveSendFollowUp,
7
7
  startOrchestration,
8
8
  waitForPidExit
9
- } from "./chunk-DVYRABZC.js";
9
+ } from "./chunk-GVC4IVF5.js";
10
10
  import "./chunk-DJU54RYW.js";
11
- import "./chunk-NIB6BTC6.js";
12
- import "./chunk-3ZFGZ7RT.js";
13
- import "./chunk-7JIYKYLL.js";
11
+ import "./chunk-IVJFEB3T.js";
12
+ import "./chunk-7T5XKNOF.js";
13
+ import "./chunk-WXKXSZN4.js";
14
14
  import "./chunk-6K64FJDD.js";
15
15
  import "./chunk-IEEAVWAP.js";
16
16
  import "./chunk-AN3THU7F.js";
@@ -21,7 +21,7 @@ import "./chunk-J7LQVLFQ.js";
21
21
  import "./chunk-4TR3HZFT.js";
22
22
  import "./chunk-AO35MGOE.js";
23
23
  import "./chunk-JT7R45JB.js";
24
- import "./chunk-7UURXPKD.js";
24
+ import "./chunk-TCQAFTSV.js";
25
25
  import "./chunk-77WWLBCI.js";
26
26
  import "./chunk-EFVFB2AH.js";
27
27
  import "./chunk-QQKDGPUI.js";
@@ -8,17 +8,17 @@ import {
8
8
  resolveSendFollowUp,
9
9
  startOrchestration,
10
10
  waitForPidExit
11
- } from "./chunk-DJUDDKXM.js";
12
- import "./chunk-W44EKPIR.js";
11
+ } from "./chunk-MZOZ6PIZ.js";
12
+ import "./chunk-VUFJ5MAN.js";
13
13
  import "./chunk-HVIEYTUK.js";
14
14
  import "./chunk-Y4MIXGPA.js";
15
15
  import "./chunk-VKQGAWHY.js";
16
16
  import "./chunk-JFOPOMK7.js";
17
17
  import "./chunk-OCQPTUR7.js";
18
- import "./chunk-FJWQCZ74.js";
19
- import "./chunk-7O53GXTA.js";
18
+ import "./chunk-XV3EFFZ6.js";
19
+ import "./chunk-XBLN52RZ.js";
20
20
  import "./chunk-D6JWYJ4P.js";
21
- import "./chunk-LZQULFIT.js";
21
+ import "./chunk-GOZ6T3AG.js";
22
22
  import "./chunk-SYFVUF2C.js";
23
23
  import "./chunk-FNQNJOHY.js";
24
24
  import "./chunk-OKZFTOM2.js";
@@ -13,7 +13,7 @@ import {
13
13
  updateThread,
14
14
  withThreadLock,
15
15
  writeThread
16
- } from "./chunk-7UURXPKD.js";
16
+ } from "./chunk-TCQAFTSV.js";
17
17
  import "./chunk-77WWLBCI.js";
18
18
  import "./chunk-EFVFB2AH.js";
19
19
  export {
@@ -15,7 +15,7 @@ import {
15
15
  updateThread,
16
16
  withThreadLock,
17
17
  writeThread
18
- } from "./chunk-LZQULFIT.js";
18
+ } from "./chunk-GOZ6T3AG.js";
19
19
  import "./chunk-KGZBYWZ3.js";
20
20
  import "./chunk-JTJHOYCU.js";
21
21
  export {
@@ -4,13 +4,13 @@ import {
4
4
  listWorkspaces,
5
5
  removeWorkspace,
6
6
  syncWorkspacesFromThreads
7
- } from "./chunk-3ZFGZ7RT.js";
8
- import "./chunk-7JIYKYLL.js";
7
+ } from "./chunk-7T5XKNOF.js";
8
+ import "./chunk-WXKXSZN4.js";
9
9
  import "./chunk-6K64FJDD.js";
10
10
  import "./chunk-J7LQVLFQ.js";
11
11
  import "./chunk-4TR3HZFT.js";
12
12
  import "./chunk-JT7R45JB.js";
13
- import "./chunk-7UURXPKD.js";
13
+ import "./chunk-TCQAFTSV.js";
14
14
  import "./chunk-77WWLBCI.js";
15
15
  import "./chunk-EFVFB2AH.js";
16
16
  import "./chunk-QQKDGPUI.js";
@@ -6,10 +6,10 @@ import {
6
6
  listWorkspaces,
7
7
  removeWorkspace,
8
8
  syncWorkspacesFromThreads
9
- } from "./chunk-FJWQCZ74.js";
10
- import "./chunk-7O53GXTA.js";
9
+ } from "./chunk-XV3EFFZ6.js";
10
+ import "./chunk-XBLN52RZ.js";
11
11
  import "./chunk-D6JWYJ4P.js";
12
- import "./chunk-LZQULFIT.js";
12
+ import "./chunk-GOZ6T3AG.js";
13
13
  import "./chunk-SYFVUF2C.js";
14
14
  import "./chunk-FNQNJOHY.js";
15
15
  import "./chunk-OKZFTOM2.js";
@@ -59,9 +59,9 @@ import {
59
59
  worktreeDisplayLabelForGroup,
60
60
  worktreeNameFromPath,
61
61
  worktreeSlugForTicket
62
- } from "./chunk-7O53GXTA.js";
62
+ } from "./chunk-XBLN52RZ.js";
63
63
  import "./chunk-D6JWYJ4P.js";
64
- import "./chunk-LZQULFIT.js";
64
+ import "./chunk-GOZ6T3AG.js";
65
65
  import "./chunk-SYFVUF2C.js";
66
66
  import "./chunk-FNQNJOHY.js";
67
67
  import "./chunk-OKZFTOM2.js";
@@ -57,12 +57,12 @@ import {
57
57
  worktreeDisplayLabelForGroup,
58
58
  worktreeNameFromPath,
59
59
  worktreeSlugForTicket
60
- } from "./chunk-7JIYKYLL.js";
60
+ } from "./chunk-WXKXSZN4.js";
61
61
  import "./chunk-6K64FJDD.js";
62
62
  import "./chunk-J7LQVLFQ.js";
63
63
  import "./chunk-4TR3HZFT.js";
64
64
  import "./chunk-JT7R45JB.js";
65
- import "./chunk-7UURXPKD.js";
65
+ import "./chunk-TCQAFTSV.js";
66
66
  import "./chunk-77WWLBCI.js";
67
67
  import "./chunk-EFVFB2AH.js";
68
68
  import "./chunk-QQKDGPUI.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sideboard-ai/core",
3
- "version": "0.1.177",
3
+ "version": "0.1.179",
4
4
  "description": "Sideboard core — orchestration, agents, git worktrees, MCP server",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",