@sideboard-ai/core 0.1.203 → 0.1.204

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 (42) hide show
  1. package/dist/{abletime-JFGZBDHH.js → abletime-S3UHQZVW.js} +3 -3
  2. package/dist/{abletime-SISJEPJ3.js → abletime-TONBQP4O.js} +3 -3
  3. package/dist/{abletime-oauth-7TD5Z2QV.js → abletime-oauth-AVCEO2DY.js} +54 -5
  4. package/dist/{abletime-oauth-OSQYFB3E.js → abletime-oauth-SD4SZY5U.js} +14 -2
  5. package/dist/{abletime-rest-QPJTDLKX.js → abletime-rest-6ODSXV7G.js} +2 -2
  6. package/dist/{abletime-rest-ZJGWYALM.js → abletime-rest-J2OBB4VA.js} +2 -2
  7. package/dist/agents/cursor-runner.js +1 -1
  8. package/dist/{agents-ZMWL43SP.js → agents-67K4BQFJ.js} +3 -3
  9. package/dist/{agents-3755WYQM.js → agents-BVOJNHV6.js} +4 -4
  10. package/dist/{chunk-6VEIKW5C.js → chunk-3K257PCS.js} +6 -3
  11. package/dist/{chunk-LCU6GBZP.js → chunk-5SMS6QTO.js} +1 -1
  12. package/dist/{chunk-MHPINQKY.js → chunk-6Q7DFVDQ.js} +54 -5
  13. package/dist/{chunk-3PYH2RLA.js → chunk-CYLDJWRK.js} +6 -3
  14. package/dist/{chunk-FZ6IBUKY.js → chunk-FO2NTJ7L.js} +3 -3
  15. package/dist/{chunk-2DVCCLII.js → chunk-FO45DMJ5.js} +60 -60
  16. package/dist/{chunk-CQ5R3VPP.js → chunk-KZ7PI7FE.js} +18 -0
  17. package/dist/{chunk-FZYYEMET.js → chunk-QAVWH2RQ.js} +3 -3
  18. package/dist/{chunk-QSEF2YVQ.js → chunk-QUW5D62C.js} +33 -19
  19. package/dist/{chunk-PJHFNFXA.js → chunk-SGUVAK66.js} +27 -8
  20. package/dist/{chunk-TZNJKZ2A.js → chunk-ULZLWQBS.js} +58 -58
  21. package/dist/{chunk-TNDUTGDV.js → chunk-VIPA75ZA.js} +1 -1
  22. package/dist/{chunk-BFEBFGCS.js → chunk-W6VM36YO.js} +30 -8
  23. package/dist/{chunk-X2TFUFIS.js → chunk-WF33LOP4.js} +43 -5
  24. package/dist/{chunk-CMGRV36E.js → chunk-WVATAIF4.js} +33 -19
  25. package/dist/{chunk-5IXJTUST.js → chunk-YOSTWSNC.js} +26 -6
  26. package/dist/{coordinator-prompt-U4PEZDAW.js → coordinator-prompt-NPT555BO.js} +2 -2
  27. package/dist/{coordinator-prompt-2B2JA2IE.js → coordinator-prompt-WEPXXLLX.js} +2 -2
  28. package/dist/{global-workspace-JPJ3FKKY.js → global-workspace-2I2T7FL5.js} +2 -2
  29. package/dist/{global-workspace-PU7ZS3LS.js → global-workspace-NSILADOM.js} +2 -2
  30. package/dist/index.cjs +237 -83
  31. package/dist/index.d.cts +33 -11
  32. package/dist/index.d.ts +33 -11
  33. package/dist/index.js +39 -9
  34. package/dist/mcp/run-stdio.cjs +192 -78
  35. package/dist/mcp/run-stdio.js +7 -7
  36. package/dist/{orchestrator-3A6KUTNI.js → orchestrator-CMAVNELS.js} +5 -5
  37. package/dist/{orchestrator-Q33M24ZJ.js → orchestrator-I7GFXLHF.js} +4 -4
  38. package/dist/{workspaces-IMG7ZRUQ.js → workspaces-BOC6M7BW.js} +2 -2
  39. package/dist/{workspaces-U6P6DB44.js → workspaces-RFGZBUAR.js} +2 -2
  40. package/dist/{worktree-JSCDJPBU.js → worktree-G3ZLM4DC.js} +3 -1
  41. package/dist/{worktree-FL3UIUKQ.js → worktree-WSUQMMK4.js} +3 -1
  42. package/package.json +1 -1
@@ -1792,6 +1792,9 @@ function humanizeAgentFailDetail(detail) {
1792
1792
  if (/\[resource_exhausted\]|resource_exhausted|findfileswithripgrep/.test(lower)) {
1793
1793
  return "Cursor local file search failed (ripgrep / resource_exhausted). Wait a minute and retry; if it keeps happening, check Cursor usage.";
1794
1794
  }
1795
+ if (looksLikeCodexMcpError(raw)) {
1796
+ return `${raw} \u2014 skip that vendor MCP and continue (PostHog: Settings \u2192 Connectors + HTTP API).`;
1797
+ }
1795
1798
  if (/invalid user api key|invalid api key|not logged in|not authenticated|unauthorized|authentication|please run.*login|codex login|claude auth|cursor api/.test(
1796
1799
  lower
1797
1800
  )) {
@@ -1849,9 +1852,24 @@ function turnFailChatText(opts) {
1849
1852
 
1850
1853
  ${fail6}`;
1851
1854
  }
1855
+ function looksLikeCodexMcpError(text7) {
1856
+ const t = text7.trim().toLowerCase();
1857
+ if (!t) return false;
1858
+ if (/authrequired|authorization required/.test(t) && /mcp|posthog|rmcp|connector|plugin/.test(t)) {
1859
+ return true;
1860
+ }
1861
+ if (/\bposthog\b/.test(t) && /mcp|oauth|auth|unauthorized|401|plugin|app/.test(t)) {
1862
+ return true;
1863
+ }
1864
+ if (/\brmcp\b/.test(t) && /fatal|quit|transport|error|died|kill|auth/.test(t)) {
1865
+ return true;
1866
+ }
1867
+ return /mcp[_ -]?(server|tool|error|transport|client)/.test(t) && /fail|error|timeout|disconnect|auth|unauthorized/.test(t);
1868
+ }
1852
1869
  function shouldFeedErrorBackToAgent(opts) {
1853
1870
  const detail = opts.detail.trim();
1854
1871
  const chat = (opts.assistantText ?? "").trim();
1872
+ if (looksLikeCodexMcpError(detail)) return true;
1855
1873
  if (looksLikeAgentFailureMessage(detail) || looksLikeAgentFailureMessage(chat)) {
1856
1874
  return false;
1857
1875
  }
@@ -6069,6 +6087,7 @@ __export(worktree_exports, {
6069
6087
  canonicalizeRepoPath: () => canonicalizeRepoPath,
6070
6088
  collectTakenTeamSlugs: () => collectTakenTeamSlugs,
6071
6089
  commitAll: () => commitAll,
6090
+ connectedPrSelectors: () => connectedPrSelectors,
6072
6091
  countUnpushedVsOrigin: () => countUnpushedVsOrigin,
6073
6092
  createExistingBranchWorktree: () => createExistingBranchWorktree,
6074
6093
  createOrUpdatePr: () => createOrUpdatePr,
@@ -6402,26 +6421,21 @@ function resolvePrSelectors(thread) {
6402
6421
  function resolvePrSelector(thread) {
6403
6422
  return resolvePrSelectors(thread)[0] ?? null;
6404
6423
  }
6424
+ function connectedPrSelectors(thread, currentHeadPrUrl) {
6425
+ const out = [];
6426
+ const push = (value) => {
6427
+ const v = value?.trim();
6428
+ if (!v || out.includes(v)) return;
6429
+ out.push(v);
6430
+ };
6431
+ push(currentHeadPrUrl);
6432
+ for (const selector of resolvePrSelectors(thread)) push(selector);
6433
+ return out;
6434
+ }
6405
6435
  async function getPrForHeadBranch(repoPath, branch) {
6406
6436
  const head = normalizeGitBranchName(branch);
6407
6437
  if (!head || isDefaultishSourceRef(head)) return null;
6408
6438
  const slug = await resolveGithubRepoSlug(repoPath);
6409
- const viewArgs = [
6410
- "pr",
6411
- "view",
6412
- head,
6413
- "--json",
6414
- "number,title,headRefName,url,isCrossRepository,author"
6415
- ];
6416
- if (slug) viewArgs.push("--repo", slug);
6417
- const viewed = await gh(viewArgs, repoPath, { reject: false });
6418
- if (viewed.exitCode === 0 && viewed.stdout.trim()) {
6419
- try {
6420
- return JSON.parse(viewed.stdout);
6421
- } catch {
6422
- return null;
6423
- }
6424
- }
6425
6439
  const listHead = slug ? ghHeadRef(slug, head) : head;
6426
6440
  const listArgs = [
6427
6441
  "pr",
@@ -6437,10 +6451,28 @@ async function getPrForHeadBranch(repoPath, branch) {
6437
6451
  ];
6438
6452
  if (slug) listArgs.push("--repo", slug);
6439
6453
  const listed = await gh(listArgs, repoPath, { reject: false });
6440
- if (listed.exitCode !== 0 || !listed.stdout.trim()) return null;
6454
+ if (listed.exitCode === 0 && listed.stdout.trim()) {
6455
+ try {
6456
+ const rows = JSON.parse(listed.stdout);
6457
+ if (rows[0]) return rows[0];
6458
+ } catch {
6459
+ }
6460
+ }
6461
+ const viewArgs = [
6462
+ "pr",
6463
+ "view",
6464
+ head,
6465
+ "--json",
6466
+ "number,title,headRefName,url,isCrossRepository,author,state"
6467
+ ];
6468
+ if (slug) viewArgs.push("--repo", slug);
6469
+ const viewed = await gh(viewArgs, repoPath, { reject: false });
6470
+ if (viewed.exitCode !== 0 || !viewed.stdout.trim()) return null;
6441
6471
  try {
6442
- const rows = JSON.parse(listed.stdout);
6443
- return rows[0] ?? null;
6472
+ const info = JSON.parse(viewed.stdout);
6473
+ const state = (info.state ?? "OPEN").trim().toUpperCase();
6474
+ if (state !== "OPEN") return null;
6475
+ return info;
6444
6476
  } catch {
6445
6477
  return null;
6446
6478
  }
@@ -11023,7 +11055,18 @@ function toCodexDisableUserMcpArgs(names) {
11023
11055
  return args;
11024
11056
  }
11025
11057
  function toCodexUnattendedAppsArgs() {
11026
- return ["-c", "features.apps=false", "-c", "apps._default.enabled=false"];
11058
+ return [
11059
+ "-c",
11060
+ "features.apps=false",
11061
+ "-c",
11062
+ "apps._default.enabled=false",
11063
+ "-c",
11064
+ "apps.posthog.enabled=false",
11065
+ "-c",
11066
+ "features.plugins=false",
11067
+ "-c",
11068
+ "mcp_servers.posthog.enabled=false"
11069
+ ];
11027
11070
  }
11028
11071
  var import_node_fs28, import_node_os11, import_node_path29, import_smol_toml2;
11029
11072
  var init_orch_mcp_isolation = __esm({
@@ -12733,6 +12776,33 @@ var init_agent_git_actions = __esm({
12733
12776
  function normalizePrState(state) {
12734
12777
  return (state ?? "").trim().toUpperCase();
12735
12778
  }
12779
+ function sameLoginList(a, b) {
12780
+ const left = [...a ?? []].map((s) => s.trim().toLowerCase()).filter(Boolean).sort();
12781
+ const right = [...b ?? []].map((s) => s.trim().toLowerCase()).filter(Boolean).sort();
12782
+ return left.length === right.length && left.every((login, i) => login === right[i]);
12783
+ }
12784
+ function threadPrMetaPatch(thread, meta) {
12785
+ const prevState = normalizePrState(thread.prState);
12786
+ const nextState = normalizePrState(meta.state);
12787
+ const patch = {};
12788
+ if (meta.url && meta.url !== thread.prUrl) patch.prUrl = meta.url;
12789
+ if (meta.title && meta.title !== thread.prTitle) patch.prTitle = meta.title;
12790
+ if (nextState && nextState !== prevState) patch.prState = nextState;
12791
+ const nextDraft = Boolean(meta.isDraft) && nextState !== "MERGED" && nextState !== "CLOSED";
12792
+ if (nextDraft !== Boolean(thread.prIsDraft)) patch.prIsDraft = nextDraft;
12793
+ const nextAuthor = meta.authorLogin?.trim() || "";
12794
+ if (nextAuthor && nextAuthor !== (thread.prAuthorLogin ?? "").trim()) {
12795
+ patch.prAuthorLogin = nextAuthor;
12796
+ }
12797
+ const nextReviewers = meta.reviewerLogins ?? [];
12798
+ if (!sameLoginList(nextReviewers, thread.prReviewerLogins)) {
12799
+ patch.prReviewerLogins = nextReviewers;
12800
+ }
12801
+ if (thread.skipAutoArchiveOnMerge && nextState && nextState !== "MERGED" && nextState !== "CLOSED") {
12802
+ patch.skipAutoArchiveOnMerge = false;
12803
+ }
12804
+ return patch;
12805
+ }
12736
12806
  function shouldAutoArchiveOnPrMerge(opts) {
12737
12807
  if (!opts.autoArchiveEnabled) return false;
12738
12808
  if (opts.isGlobal) return false;
@@ -15411,21 +15481,67 @@ var init_home_board = __esm({
15411
15481
  // src/integrations/abletime-oauth.ts
15412
15482
  var abletime_oauth_exports = {};
15413
15483
  __export(abletime_oauth_exports, {
15484
+ ABLETIME_OAUTH_CALLBACK_PATH: () => ABLETIME_OAUTH_CALLBACK_PATH,
15414
15485
  ABLETIME_OAUTH_CANCELLED: () => ABLETIME_OAUTH_CANCELLED,
15486
+ ABLETIME_OAUTH_LOCAL_CALLBACK: () => ABLETIME_OAUTH_LOCAL_CALLBACK,
15415
15487
  ABLETIME_OAUTH_PORT: () => ABLETIME_OAUTH_PORT,
15416
15488
  ABLETIME_OAUTH_REDIRECT: () => ABLETIME_OAUTH_REDIRECT,
15417
15489
  ABLETIME_OAUTH_RESOURCE: () => ABLETIME_OAUTH_RESOURCE,
15418
15490
  AbleTimeOAuthCancelledError: () => AbleTimeOAuthCancelledError,
15419
15491
  BAKED_ABLETIME_OAUTH_CLIENT_ID: () => BAKED_ABLETIME_OAUTH_CLIENT_ID,
15420
15492
  ableTimeOAuthAuthorizeUrl: () => ableTimeOAuthAuthorizeUrl,
15493
+ ableTimeOAuthBouncePage: () => ableTimeOAuthBouncePage,
15421
15494
  ableTimeOAuthClientId: () => ableTimeOAuthClientId,
15495
+ ableTimeOAuthLocalBounceUrl: () => ableTimeOAuthLocalBounceUrl,
15496
+ ableTimeOAuthRedirectUri: () => ableTimeOAuthRedirectUri,
15422
15497
  ableTimeOAuthResource: () => ableTimeOAuthResource,
15423
15498
  createAbleTimePkce: () => createAbleTimePkce,
15424
15499
  ensureAbleTimeAccessToken: () => ensureAbleTimeAccessToken,
15425
15500
  hasBakedAbleTimeOAuth: () => hasBakedAbleTimeOAuth,
15426
15501
  isAbleTimeOAuthCancelled: () => isAbleTimeOAuthCancelled,
15502
+ parseAbleTimeOAuthCallbackUrl: () => parseAbleTimeOAuthCallbackUrl,
15427
15503
  startAbleTimeOAuth: () => startAbleTimeOAuth
15428
15504
  });
15505
+ function ableTimeOAuthRedirectUri() {
15506
+ return process.env.SIDEBOARD_ABLETIME_OAUTH_REDIRECT?.trim() || ABLETIME_OAUTH_REDIRECT;
15507
+ }
15508
+ function parseAbleTimeOAuthCallbackUrl(reqUrl) {
15509
+ let url;
15510
+ try {
15511
+ url = new URL(reqUrl, ABLETIME_OAUTH_REDIRECT);
15512
+ } catch {
15513
+ return null;
15514
+ }
15515
+ if (url.pathname !== ABLETIME_OAUTH_CALLBACK_PATH) return null;
15516
+ return url;
15517
+ }
15518
+ function ableTimeOAuthLocalBounceUrl(reqUrl) {
15519
+ const url = parseAbleTimeOAuthCallbackUrl(reqUrl);
15520
+ if (!url) return null;
15521
+ const dest = new URL(ABLETIME_OAUTH_LOCAL_CALLBACK);
15522
+ for (const key of BOUNCE_QUERY_KEYS) {
15523
+ const value = url.searchParams.get(key);
15524
+ if (value) dest.searchParams.set(key, value);
15525
+ }
15526
+ return dest.toString();
15527
+ }
15528
+ function escapeHtml(value) {
15529
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
15530
+ }
15531
+ function ableTimeOAuthBouncePage(localUrl) {
15532
+ const safe = escapeHtml(localUrl);
15533
+ return `<!doctype html><html><head><meta charset="utf-8">
15534
+ <meta http-equiv="refresh" content="0;url=${safe}">
15535
+ <title>Returning to Sideboard</title>
15536
+ <script>location.replace(${JSON.stringify(localUrl)})</script>
15537
+ <style>body{font-family:ui-sans-serif,system-ui,sans-serif;padding:48px 24px;max-width:36rem;margin:0 auto;color:#1a1a1a}
15538
+ h1{font-size:1.25rem}p{line-height:1.5;color:#444}a{color:#0f7ed4}</style>
15539
+ </head><body>
15540
+ <h1>Returning to Sideboard</h1>
15541
+ <p>AbleTime authorized. Opening the app\u2026</p>
15542
+ <p><a href="${safe}">Open Sideboard</a> if it does not appear.</p>
15543
+ </body></html>`;
15544
+ }
15429
15545
  function hasBakedAbleTimeOAuth() {
15430
15546
  return Boolean(BAKED_ABLETIME_OAUTH_CLIENT_ID.trim());
15431
15547
  }
@@ -15445,7 +15561,7 @@ function ableTimeOAuthAuthorizeUrl(clientId, state, codeChallenge, host) {
15445
15561
  const params = new URLSearchParams({
15446
15562
  response_type: "code",
15447
15563
  client_id: clientId,
15448
- redirect_uri: ABLETIME_OAUTH_REDIRECT,
15564
+ redirect_uri: ableTimeOAuthRedirectUri(),
15449
15565
  code_challenge: codeChallenge,
15450
15566
  code_challenge_method: "S256",
15451
15567
  state,
@@ -15617,7 +15733,7 @@ async function startAbleTimeOAuth(opts) {
15617
15733
  const body = new URLSearchParams({
15618
15734
  grant_type: "authorization_code",
15619
15735
  code,
15620
- redirect_uri: ABLETIME_OAUTH_REDIRECT,
15736
+ redirect_uri: ableTimeOAuthRedirectUri(),
15621
15737
  client_id: clientId,
15622
15738
  code_verifier: pkce.verifier,
15623
15739
  resource: ableTimeOAuthResource(host)
@@ -15639,7 +15755,7 @@ async function startAbleTimeOAuth(opts) {
15639
15755
  return loadAppSettings();
15640
15756
  }
15641
15757
  }
15642
- var import_node_crypto9, import_node_http, ABLETIME_OAUTH_PORT, ABLETIME_OAUTH_REDIRECT, BAKED_ABLETIME_OAUTH_CLIENT_ID, ABLETIME_OAUTH_RESOURCE, REFRESH_SKEW_MS2, refreshInFlight, ABLETIME_OAUTH_CANCELLED, AbleTimeOAuthCancelledError;
15758
+ var import_node_crypto9, import_node_http, ABLETIME_OAUTH_CALLBACK_PATH, ABLETIME_OAUTH_PORT, ABLETIME_OAUTH_LOCAL_CALLBACK, ABLETIME_OAUTH_REDIRECT, BOUNCE_QUERY_KEYS, BAKED_ABLETIME_OAUTH_CLIENT_ID, ABLETIME_OAUTH_RESOURCE, REFRESH_SKEW_MS2, refreshInFlight, ABLETIME_OAUTH_CANCELLED, AbleTimeOAuthCancelledError;
15643
15759
  var init_abletime_oauth = __esm({
15644
15760
  "src/integrations/abletime-oauth.ts"() {
15645
15761
  "use strict";
@@ -15648,8 +15764,11 @@ var init_abletime_oauth = __esm({
15648
15764
  init_fetch();
15649
15765
  init_app_settings();
15650
15766
  init_abletime_mcp();
15767
+ ABLETIME_OAUTH_CALLBACK_PATH = "/oauth/abletime/callback";
15651
15768
  ABLETIME_OAUTH_PORT = 19849;
15652
- ABLETIME_OAUTH_REDIRECT = `http://127.0.0.1:${ABLETIME_OAUTH_PORT}/callback`;
15769
+ ABLETIME_OAUTH_LOCAL_CALLBACK = `http://127.0.0.1:${ABLETIME_OAUTH_PORT}/callback`;
15770
+ ABLETIME_OAUTH_REDIRECT = `https://www.sideboard.cloud${ABLETIME_OAUTH_CALLBACK_PATH}`;
15771
+ BOUNCE_QUERY_KEYS = ["code", "state", "error", "error_description"];
15653
15772
  BAKED_ABLETIME_OAUTH_CLIENT_ID = "https://www.sideboard.cloud/oauth/abletime-client.json";
15654
15773
  ABLETIME_OAUTH_RESOURCE = `${DEFAULT_ABLETIME_HOST}/api/public/v2/mcp`;
15655
15774
  REFRESH_SKEW_MS2 = 5 * 6e4;
@@ -15903,8 +16022,11 @@ function firstStringArg(args, keys) {
15903
16022
  }
15904
16023
  async function callAbleTimeRestTool(name, args = {}, opts) {
15905
16024
  const token = normalizeAbleTimeCredential(opts?.token ?? getAbleTimeAccessToken() ?? "");
15906
- if (ableTimeCredentialKind(token) !== "org") {
15907
- throw new Error("AbleTime REST transport is for organization API keys (atk_\u2026)");
16025
+ if (!token) {
16026
+ throw new Error("AbleTime is not connected \u2014 paste an API key or connect via browser");
16027
+ }
16028
+ if (ableTimeCredentialKind(token) === "pat") {
16029
+ throw new Error("AbleTime REST transport is for organization keys and OAuth tokens, not apt_\u2026");
15908
16030
  }
15909
16031
  const requestOpts = { ...opts, token };
15910
16032
  switch (name) {
@@ -16064,11 +16186,25 @@ function normalizeAbleTimeCredential(raw) {
16064
16186
  return raw.trim().replace(/^bearer\s+/i, "").trim();
16065
16187
  }
16066
16188
  function ableTimeCredentialKind(raw) {
16067
- const token = normalizeAbleTimeCredential(raw).toLowerCase();
16068
- if (token.startsWith(ABLETIME_PAT_PREFIX)) return "pat";
16069
- if (token.startsWith(ABLETIME_ORG_KEY_PREFIX)) return "org";
16189
+ const token = normalizeAbleTimeCredential(raw);
16190
+ const lower = token.toLowerCase();
16191
+ if (lower.startsWith(ABLETIME_PAT_PREFIX)) return "pat";
16192
+ if (lower.startsWith(ABLETIME_ORG_KEY_PREFIX)) return "org";
16193
+ if (lower.startsWith(ABLETIME_OAUTH_TOKEN_PREFIX) || token.startsWith("eyJ")) return "oauth";
16070
16194
  return "unknown";
16071
16195
  }
16196
+ function ableTimeUsesRest(raw) {
16197
+ const token = normalizeAbleTimeCredential(raw);
16198
+ const kind = ableTimeCredentialKind(token);
16199
+ if (kind === "org") return true;
16200
+ if (kind === "oauth") return token.startsWith("eyJ");
16201
+ return kind === "unknown";
16202
+ }
16203
+ function isAbleTimeRejectedCredential(message) {
16204
+ return /INTEGRATION_KEY_INVALID|INTEGRATION_KEY_MISSING|INTEGRATION_PAT_REQUIRED|\b401\b/i.test(
16205
+ message
16206
+ );
16207
+ }
16072
16208
  function assertAbleTimeMcpCredential(raw) {
16073
16209
  const token = normalizeAbleTimeCredential(raw);
16074
16210
  if (!token) {
@@ -16230,7 +16366,7 @@ async function callAbleTimeTool(name, args = {}, opts) {
16230
16366
  throw new Error("AbleTime is not connected \u2014 paste a personal access token in Account settings");
16231
16367
  }
16232
16368
  const rawToken = opts?.token ?? await Promise.resolve().then(() => (init_abletime_oauth(), abletime_oauth_exports)).then((m) => m.ensureAbleTimeAccessToken());
16233
- if (rawToken && ableTimeCredentialKind(rawToken) === "org") {
16369
+ if (rawToken && ableTimeUsesRest(rawToken)) {
16234
16370
  const { callAbleTimeRestTool: callAbleTimeRestTool2 } = await Promise.resolve().then(() => (init_abletime_rest(), abletime_rest_exports));
16235
16371
  return callAbleTimeRestTool2(name, args, { ...opts, token: rawToken });
16236
16372
  }
@@ -16246,10 +16382,14 @@ async function callAbleTimeTool(name, args = {}, opts) {
16246
16382
  await initializeIfNeeded(requestOpts);
16247
16383
  return await call();
16248
16384
  }
16385
+ if (rawToken && ableTimeUsesRest(rawToken) && isAbleTimeRejectedCredential(message)) {
16386
+ const { callAbleTimeRestTool: callAbleTimeRestTool2 } = await Promise.resolve().then(() => (init_abletime_rest(), abletime_rest_exports));
16387
+ return callAbleTimeRestTool2(name, args, { ...opts, token: rawToken });
16388
+ }
16249
16389
  throw err instanceof Error ? new Error(rewriteAbleTimeError(err.message)) : err;
16250
16390
  }
16251
16391
  }
16252
- var DEFAULT_ABLETIME_HOST, ABLETIME_MCP_PATH, ABLETIME_MCP_PM_PATH, MCP_PROTOCOL_VERSION, ABLETIME_PM_TOOL_NAMES, ABLETIME_PAT_PREFIX, ABLETIME_ORG_KEY_PREFIX, ORG_KEY_HINT, REJECTED_CREDENTIAL_HINT, REWRITE_APPLIED;
16392
+ var DEFAULT_ABLETIME_HOST, ABLETIME_MCP_PATH, ABLETIME_MCP_PM_PATH, MCP_PROTOCOL_VERSION, ABLETIME_PM_TOOL_NAMES, ABLETIME_PAT_PREFIX, ABLETIME_ORG_KEY_PREFIX, ABLETIME_OAUTH_TOKEN_PREFIX, ORG_KEY_HINT, REJECTED_CREDENTIAL_HINT, REWRITE_APPLIED;
16253
16393
  var init_abletime_mcp = __esm({
16254
16394
  "src/integrations/abletime-mcp.ts"() {
16255
16395
  "use strict";
@@ -16273,8 +16413,9 @@ var init_abletime_mcp = __esm({
16273
16413
  ];
16274
16414
  ABLETIME_PAT_PREFIX = "apt_";
16275
16415
  ABLETIME_ORG_KEY_PREFIX = "atk_";
16416
+ ABLETIME_OAUTH_TOKEN_PREFIX = "acn_";
16276
16417
  ORG_KEY_HINT = "AbleTime MCP needs a personal access token (apt_\u2026) from Edit Profile \u2192 API Access, not an organization API key (atk_\u2026) from Settings \u2192 Integrations \u2192 API Keys.";
16277
- REJECTED_CREDENTIAL_HINT = "AbleTime rejected this credential (unknown, revoked, or expired). Use a personal access token (apt_\u2026) from Edit Profile \u2192 API Access \u2014 organization API keys (atk_\u2026) cannot call MCP. Tokens are shown once; rotating replaces the previous one.";
16418
+ REJECTED_CREDENTIAL_HINT = "AbleTime rejected this credential (unknown, revoked, or expired). Reconnect via browser, or paste a personal access token (apt_\u2026) from Edit Profile \u2192 API Access. Organization API keys (atk_\u2026) use REST, not MCP.";
16278
16419
  REWRITE_APPLIED = /— Enable Agent access \(MCP\)|— AbleTime MCP needs a personal access token|— AbleTime plan does not include API access|— AbleTime rejected this credential/;
16279
16420
  }
16280
16421
  });
@@ -16456,7 +16597,7 @@ function isOpenTask(task) {
16456
16597
  async function getAbleTimeOrientation(opts) {
16457
16598
  const raw = await callAbleTimeTool("orientation", {}, opts);
16458
16599
  const record = asRecord6(raw);
16459
- const viewerRec = firstRecord(record, ["viewer", "user", "actor", "me", "person"]) ?? record;
16600
+ const viewerRec = firstRecord(record, ["viewer", "principal", "user", "actor", "me", "person"]) ?? record;
16460
16601
  const viewer = {
16461
16602
  id: firstString(viewerRec, ["id", "user_id"]) || void 0,
16462
16603
  name: firstString(viewerRec, ["name", "display_name", "full_name"]) || firstString(record, ["name"]) || void 0
@@ -20474,11 +20615,6 @@ function isPidAlive(pid) {
20474
20615
  return false;
20475
20616
  }
20476
20617
  }
20477
- function sameLoginList(a, b) {
20478
- const left = [...a ?? []].map((s) => s.trim().toLowerCase()).filter(Boolean).sort();
20479
- const right = [...b ?? []].map((s) => s.trim().toLowerCase()).filter(Boolean).sort();
20480
- return left.length === right.length && left.every((login, i) => login === right[i]);
20481
- }
20482
20618
  async function waitForPidExit(pid, timeoutMs) {
20483
20619
  const start = Date.now();
20484
20620
  while (isPidAlive(pid)) {
@@ -22317,12 +22453,18 @@ var init_orchestrator = __esm({
22317
22453
  /** Resolve PR selectors and optionally persist `prUrl` when found. */
22318
22454
  async withPrSelector(threadRef) {
22319
22455
  const thread = this.requireThread(threadRef);
22320
- const selectors = resolvePrSelectors(thread);
22321
22456
  const cwd = thread.worktreePath;
22322
22457
  if (!cwd?.trim()) {
22323
22458
  throw new Error(`Thread ${threadRef} has no worktreePath`);
22324
22459
  }
22325
- return { thread, selectors, cwd };
22460
+ let headUrl = null;
22461
+ try {
22462
+ const head = await getPrForHeadBranch(cwd, thread.branchName);
22463
+ headUrl = head?.url?.trim() || null;
22464
+ } catch {
22465
+ headUrl = null;
22466
+ }
22467
+ return { thread, selectors: connectedPrSelectors(thread, headUrl), cwd };
22326
22468
  }
22327
22469
  async getPrChecks(threadRef) {
22328
22470
  const { selectors, cwd } = await this.withPrSelector(threadRef);
@@ -22350,29 +22492,16 @@ var init_orchestrator = __esm({
22350
22492
  async persistPrMetaAndMaybeArchive(thread, meta) {
22351
22493
  const prevState = normalizePrState(thread.prState);
22352
22494
  const nextState = normalizePrState(meta.state);
22353
- const patch = {};
22354
- if (meta.url && meta.url !== thread.prUrl) patch.prUrl = meta.url;
22355
- if (meta.title && meta.title !== thread.prTitle) patch.prTitle = meta.title;
22356
- if (nextState && nextState !== prevState) patch.prState = nextState;
22357
- const nextDraft = Boolean(meta.isDraft) && nextState !== "MERGED" && nextState !== "CLOSED";
22358
- if (nextDraft !== Boolean(thread.prIsDraft)) patch.prIsDraft = nextDraft;
22359
- const nextAuthor = meta.authorLogin?.trim() || "";
22360
- if (nextAuthor && nextAuthor !== (thread.prAuthorLogin ?? "").trim()) {
22361
- patch.prAuthorLogin = nextAuthor;
22362
- }
22363
- const nextReviewers = meta.reviewerLogins ?? [];
22364
- if (!sameLoginList(nextReviewers, thread.prReviewerLogins)) {
22365
- patch.prReviewerLogins = nextReviewers;
22495
+ const siblings = threadsSharingWorktree(thread.worktreePath);
22496
+ const targets = siblings.length > 0 ? siblings : [thread];
22497
+ for (const t of targets) {
22498
+ const patch = threadPrMetaPatch(t, meta);
22499
+ if (Object.keys(patch).length === 0) continue;
22500
+ updateThread(t.id, patch);
22366
22501
  }
22367
- if (thread.skipAutoArchiveOnMerge && nextState && nextState !== "MERGED" && nextState !== "CLOSED") {
22368
- patch.skipAutoArchiveOnMerge = false;
22369
- }
22370
- if (Object.keys(patch).length > 0) {
22371
- updateThread(thread.id, patch);
22372
- const latest2 = this.requireThread(thread.id);
22373
- if (!latest2.userSetTitle && meta.title && latest2.title !== meta.title) {
22374
- updateThread(thread.id, { title: meta.title });
22375
- }
22502
+ const titled = this.requireThread(thread.id);
22503
+ if (!titled.userSetTitle && meta.title && titled.title !== meta.title) {
22504
+ updateThread(thread.id, { title: meta.title });
22376
22505
  }
22377
22506
  const { autoArchiveOnMergeEnabled: autoArchiveOnMergeEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
22378
22507
  const latest = this.requireThread(thread.id);
@@ -22386,22 +22515,7 @@ var init_orchestrator = __esm({
22386
22515
  })) {
22387
22516
  return;
22388
22517
  }
22389
- const siblings = threadsSharingWorktree(latest.worktreePath);
22390
- for (const t of siblings) {
22391
- const sibPatch = { prState: "MERGED", prIsDraft: false };
22392
- if (meta.url && meta.url !== t.prUrl) sibPatch.prUrl = meta.url;
22393
- if (meta.title && meta.title !== t.prTitle) sibPatch.prTitle = meta.title;
22394
- const sibAuthor = meta.authorLogin?.trim() || "";
22395
- if (sibAuthor && sibAuthor !== (t.prAuthorLogin ?? "").trim()) {
22396
- sibPatch.prAuthorLogin = sibAuthor;
22397
- }
22398
- const sibReviewers = meta.reviewerLogins ?? [];
22399
- if (!sameLoginList(sibReviewers, t.prReviewerLogins)) {
22400
- sibPatch.prReviewerLogins = sibReviewers;
22401
- }
22402
- if (Object.keys(sibPatch).length > 0) updateThread(t.id, sibPatch);
22403
- }
22404
- for (const t of siblings) {
22518
+ for (const t of threadsSharingWorktree(latest.worktreePath)) {
22405
22519
  if (this.requireThread(t.id).status === "archived") continue;
22406
22520
  await this.archive(t.id);
22407
22521
  }
@@ -11,7 +11,7 @@ import {
11
11
  searchAbleTimeTasks,
12
12
  toAbleTimeIssueInfo,
13
13
  updateAbleTimeTask
14
- } from "../chunk-FZ6IBUKY.js";
14
+ } from "../chunk-FO2NTJ7L.js";
15
15
  import {
16
16
  AGENT_GIT_ACTIONS,
17
17
  BOARD_COLUMN_DEFS,
@@ -50,7 +50,7 @@ import {
50
50
  syncBoardPins,
51
51
  updateSchedule,
52
52
  waitForDetachedJob
53
- } from "../chunk-TZNJKZ2A.js";
53
+ } from "../chunk-ULZLWQBS.js";
54
54
  import "../chunk-JFOPOMK7.js";
55
55
  import "../chunk-YWI3IBP2.js";
56
56
  import {
@@ -61,16 +61,16 @@ import {
61
61
  materializeSystemCaBundle,
62
62
  sideboardMcpProfile,
63
63
  trustSystemCertificates
64
- } from "../chunk-X2TFUFIS.js";
64
+ } from "../chunk-WF33LOP4.js";
65
65
  import {
66
66
  GLOBAL_WORKSPACE_ID,
67
67
  isCloudCoordinatorThread,
68
68
  listWorkspaces
69
- } from "../chunk-LCU6GBZP.js";
69
+ } from "../chunk-5SMS6QTO.js";
70
70
  import "../chunk-3OHR73VK.js";
71
71
  import "../chunk-Y4MIXGPA.js";
72
- import "../chunk-6VEIKW5C.js";
73
- import "../chunk-PJHFNFXA.js";
72
+ import "../chunk-3K257PCS.js";
73
+ import "../chunk-SGUVAK66.js";
74
74
  import {
75
75
  httpFetch
76
76
  } from "../chunk-VKQGAWHY.js";
@@ -84,7 +84,7 @@ import {
84
84
  resolveListPrsOptions,
85
85
  resolveRepoRoot,
86
86
  warmGithubAgentAuth
87
- } from "../chunk-QSEF2YVQ.js";
87
+ } from "../chunk-QUW5D62C.js";
88
88
  import "../chunk-D6JWYJ4P.js";
89
89
  import "../chunk-INNLWYXW.js";
90
90
  import "../chunk-SYFVUF2C.js";
@@ -7,18 +7,18 @@ import {
7
7
  resolveSendFollowUp,
8
8
  startOrchestration,
9
9
  waitForPidExit
10
- } from "./chunk-2DVCCLII.js";
10
+ } from "./chunk-FO45DMJ5.js";
11
11
  import "./chunk-DJU54RYW.js";
12
- import "./chunk-5IXJTUST.js";
13
- import "./chunk-TNDUTGDV.js";
14
- import "./chunk-CMGRV36E.js";
12
+ import "./chunk-YOSTWSNC.js";
13
+ import "./chunk-VIPA75ZA.js";
14
+ import "./chunk-WVATAIF4.js";
15
15
  import "./chunk-6K64FJDD.js";
16
16
  import "./chunk-QQKDGPUI.js";
17
17
  import "./chunk-SALM35KD.js";
18
18
  import "./chunk-AN3THU7F.js";
19
19
  import "./chunk-N7WZ6NIN.js";
20
20
  import "./chunk-AXQ4ZWHK.js";
21
- import "./chunk-CQ5R3VPP.js";
21
+ import "./chunk-KZ7PI7FE.js";
22
22
  import "./chunk-QFBBUFD4.js";
23
23
  import "./chunk-4TR3HZFT.js";
24
24
  import "./chunk-WDRMZKVB.js";
@@ -9,15 +9,15 @@ import {
9
9
  resolveSendFollowUp,
10
10
  startOrchestration,
11
11
  waitForPidExit
12
- } from "./chunk-TZNJKZ2A.js";
12
+ } from "./chunk-ULZLWQBS.js";
13
13
  import "./chunk-JFOPOMK7.js";
14
14
  import "./chunk-YWI3IBP2.js";
15
- import "./chunk-X2TFUFIS.js";
16
- import "./chunk-LCU6GBZP.js";
15
+ import "./chunk-WF33LOP4.js";
16
+ import "./chunk-5SMS6QTO.js";
17
17
  import "./chunk-3OHR73VK.js";
18
18
  import "./chunk-Y4MIXGPA.js";
19
19
  import "./chunk-VKQGAWHY.js";
20
- import "./chunk-QSEF2YVQ.js";
20
+ import "./chunk-QUW5D62C.js";
21
21
  import "./chunk-D6JWYJ4P.js";
22
22
  import "./chunk-INNLWYXW.js";
23
23
  import "./chunk-SYFVUF2C.js";
@@ -4,8 +4,8 @@ import {
4
4
  listWorkspaces,
5
5
  removeWorkspace,
6
6
  syncWorkspacesFromThreads
7
- } from "./chunk-TNDUTGDV.js";
8
- import "./chunk-CMGRV36E.js";
7
+ } from "./chunk-VIPA75ZA.js";
8
+ import "./chunk-WVATAIF4.js";
9
9
  import "./chunk-6K64FJDD.js";
10
10
  import "./chunk-QQKDGPUI.js";
11
11
  import "./chunk-QFBBUFD4.js";
@@ -6,8 +6,8 @@ import {
6
6
  listWorkspaces,
7
7
  removeWorkspace,
8
8
  syncWorkspacesFromThreads
9
- } from "./chunk-LCU6GBZP.js";
10
- import "./chunk-QSEF2YVQ.js";
9
+ } from "./chunk-5SMS6QTO.js";
10
+ import "./chunk-QUW5D62C.js";
11
11
  import "./chunk-D6JWYJ4P.js";
12
12
  import "./chunk-INNLWYXW.js";
13
13
  import "./chunk-SYFVUF2C.js";
@@ -7,6 +7,7 @@ import {
7
7
  canonicalizeRepoPath,
8
8
  collectTakenTeamSlugs,
9
9
  commitAll,
10
+ connectedPrSelectors,
10
11
  countUnpushedVsOrigin,
11
12
  createExistingBranchWorktree,
12
13
  createOrUpdatePr,
@@ -57,7 +58,7 @@ import {
57
58
  worktreeDisplayLabelForGroup,
58
59
  worktreeNameFromPath,
59
60
  worktreeSlugForTicket
60
- } from "./chunk-CMGRV36E.js";
61
+ } from "./chunk-WVATAIF4.js";
61
62
  import "./chunk-6K64FJDD.js";
62
63
  import "./chunk-QQKDGPUI.js";
63
64
  import "./chunk-QFBBUFD4.js";
@@ -77,6 +78,7 @@ export {
77
78
  canonicalizeRepoPath,
78
79
  collectTakenTeamSlugs,
79
80
  commitAll,
81
+ connectedPrSelectors,
80
82
  countUnpushedVsOrigin,
81
83
  createExistingBranchWorktree,
82
84
  createOrUpdatePr,
@@ -9,6 +9,7 @@ import {
9
9
  canonicalizeRepoPath,
10
10
  collectTakenTeamSlugs,
11
11
  commitAll,
12
+ connectedPrSelectors,
12
13
  countUnpushedVsOrigin,
13
14
  createExistingBranchWorktree,
14
15
  createOrUpdatePr,
@@ -59,7 +60,7 @@ import {
59
60
  worktreeDisplayLabelForGroup,
60
61
  worktreeNameFromPath,
61
62
  worktreeSlugForTicket
62
- } from "./chunk-QSEF2YVQ.js";
63
+ } from "./chunk-QUW5D62C.js";
63
64
  import "./chunk-D6JWYJ4P.js";
64
65
  import "./chunk-INNLWYXW.js";
65
66
  import "./chunk-SYFVUF2C.js";
@@ -78,6 +79,7 @@ export {
78
79
  canonicalizeRepoPath,
79
80
  collectTakenTeamSlugs,
80
81
  commitAll,
82
+ connectedPrSelectors,
81
83
  countUnpushedVsOrigin,
82
84
  createExistingBranchWorktree,
83
85
  createOrUpdatePr,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sideboard-ai/core",
3
- "version": "0.1.203",
3
+ "version": "0.1.204",
4
4
  "description": "Sideboard core — orchestration, agents, git worktrees, MCP server",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",