@sideboard-ai/core 0.1.284 → 0.1.285

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-WLDBJJUI.js → abletime-4CH2IOX5.js} +4 -4
  2. package/dist/{abletime-X64E3GUJ.js → abletime-I4RODUKT.js} +4 -4
  3. package/dist/{abletime-oauth-AXR676W5.js → abletime-oauth-7OZZ3ABX.js} +3 -3
  4. package/dist/{abletime-oauth-UWOCEICP.js → abletime-oauth-C2HN2Q6F.js} +3 -3
  5. package/dist/{abletime-rest-S4XWEXV2.js → abletime-rest-E4LBRFLM.js} +3 -3
  6. package/dist/{abletime-rest-LPUDJUEP.js → abletime-rest-WFI2HWBU.js} +3 -3
  7. package/dist/agents/cursor-runner.cjs +48 -11
  8. package/dist/agents/cursor-runner.js +48 -11
  9. package/dist/{agents-PM5ICSO3.js → agents-FKMYAKFD.js} +4 -4
  10. package/dist/{agents-6U2RQK7P.js → agents-ITNCZ6CA.js} +4 -4
  11. package/dist/chunk-2GPQZZLY.js +59 -0
  12. package/dist/{chunk-OEJQK7CY.js → chunk-2K723QZH.js} +3 -3
  13. package/dist/{chunk-ROPGQRPU.js → chunk-33KDPEK4.js} +1 -1
  14. package/dist/{chunk-I6HSGKMZ.js → chunk-5T4YWFLD.js} +2 -2
  15. package/dist/{chunk-U7HAVAGJ.js → chunk-6CVVNAIU.js} +2 -2
  16. package/dist/{chunk-TQRSVE7D.js → chunk-7IAMHN2N.js} +1 -1
  17. package/dist/{chunk-WQ4M2L44.js → chunk-C6NVTLZK.js} +5 -5
  18. package/dist/{chunk-VA55JG2I.js → chunk-DEJALWKM.js} +5 -5
  19. package/dist/{chunk-XTPQEZZA.js → chunk-IJMUYHPT.js} +3 -3
  20. package/dist/chunk-JAT3JFOS.js +61 -0
  21. package/dist/{chunk-DGPROCE5.js → chunk-LS4FFCPL.js} +3 -3
  22. package/dist/{chunk-P2BSMNHB.js → chunk-PXMLMBMI.js} +1 -1
  23. package/dist/{chunk-BS3QLVPL.js → chunk-TMM4FEZ5.js} +3 -3
  24. package/dist/{chunk-BSN6DJ4L.js → chunk-TXHZJESB.js} +3 -3
  25. package/dist/{chunk-GWFVCCJZ.js → chunk-VGNLMGBK.js} +6 -6
  26. package/dist/{chunk-PY4UCMRI.js → chunk-VQEARG5H.js} +5 -5
  27. package/dist/{chunk-COQLZNKQ.js → chunk-XSPOJFTV.js} +3 -3
  28. package/dist/{connected-teams-JIUOSZ6C.js → connected-teams-AB7ZHJVO.js} +3 -3
  29. package/dist/{connected-teams-RU6VATCM.js → connected-teams-BJ6PMIST.js} +3 -3
  30. package/dist/index.cjs +209 -112
  31. package/dist/index.d.cts +9 -2
  32. package/dist/index.d.ts +9 -2
  33. package/dist/index.js +171 -96
  34. package/dist/mcp/run-stdio.cjs +36 -17
  35. package/dist/mcp/run-stdio.js +8 -8
  36. package/dist/{oauth-S3M7B475.js → oauth-DP4ZV2M2.js} +2 -2
  37. package/dist/{oauth-K6CWZEQO.js → oauth-WCUZ6Z5G.js} +2 -2
  38. package/dist/{orchestrator-6YVY6T5I.js → orchestrator-F7KXYDQW.js} +5 -5
  39. package/dist/{orchestrator-CRBIW2RG.js → orchestrator-VUIRO6NC.js} +5 -5
  40. package/package.json +1 -1
  41. package/dist/chunk-N7WZ6NIN.js +0 -41
  42. package/dist/chunk-VKQGAWHY.js +0 -40
package/dist/index.js CHANGED
@@ -198,7 +198,7 @@ import {
198
198
  worktreeBoardStatus,
199
199
  worktreeCleanupSettings,
200
200
  writeWorktreeFile
201
- } from "./chunk-WQ4M2L44.js";
201
+ } from "./chunk-C6NVTLZK.js";
202
202
  import {
203
203
  BASE_ALLOWED_TOOLS,
204
204
  BRIGHTSY_MCP_ALLOWED_TOOLS,
@@ -288,7 +288,7 @@ import {
288
288
  whichOnPath,
289
289
  worktreeMcpToolNames,
290
290
  writeInjectedMcpConfig
291
- } from "./chunk-COQLZNKQ.js";
291
+ } from "./chunk-XSPOJFTV.js";
292
292
  import {
293
293
  brightsyMcpServerName,
294
294
  connectBrightsyTeam,
@@ -298,7 +298,7 @@ import {
298
298
  listBrightsyAccounts,
299
299
  listConnectedBrightsyTeams,
300
300
  switchBrightsyAccount
301
- } from "./chunk-GWFVCCJZ.js";
301
+ } from "./chunk-VGNLMGBK.js";
302
302
  import {
303
303
  BRIGHTSY_SUMMARIZE_CONTEXT_TOOL,
304
304
  CHARS_PER_CONTEXT_TOKEN,
@@ -481,7 +481,7 @@ import {
481
481
  parseAbleTimeOAuthCallbackUrl,
482
482
  resolveAbleTimeOAuthHost,
483
483
  startAbleTimeOAuth
484
- } from "./chunk-XTPQEZZA.js";
484
+ } from "./chunk-IJMUYHPT.js";
485
485
  import {
486
486
  ableTimeDependencyTarget,
487
487
  commentAbleTimeTask,
@@ -506,8 +506,8 @@ import {
506
506
  toAbleTimeIssueInfo,
507
507
  updateAbleTimeTask,
508
508
  verifyAbleTimeConnection
509
- } from "./chunk-DGPROCE5.js";
510
- import "./chunk-U7HAVAGJ.js";
509
+ } from "./chunk-LS4FFCPL.js";
510
+ import "./chunk-6CVVNAIU.js";
511
511
  import {
512
512
  ABLETIME_MCP_PATH,
513
513
  ABLETIME_MCP_PM_PATH,
@@ -528,7 +528,7 @@ import {
528
528
  normalizeAbleTimeCredential,
529
529
  normalizeAbleTimeHost,
530
530
  rewriteAbleTimeError
531
- } from "./chunk-VA55JG2I.js";
531
+ } from "./chunk-DEJALWKM.js";
532
532
  import {
533
533
  LEGACY_PLAN_FILE_REL,
534
534
  PLAN_FILE_NAME,
@@ -728,12 +728,13 @@ import {
728
728
  refreshBrightsyAccessToken,
729
729
  registerBrightsyOAuthClient,
730
730
  saveBrightsyConfig
731
- } from "./chunk-ROPGQRPU.js";
731
+ } from "./chunk-33KDPEK4.js";
732
732
  import {
733
+ currentHttpFetch,
733
734
  formatFetchError,
734
735
  httpFetch,
735
736
  setHttpFetchImpl
736
- } from "./chunk-N7WZ6NIN.js";
737
+ } from "./chunk-JAT3JFOS.js";
737
738
  import {
738
739
  clipMcpToolResult
739
740
  } from "./chunk-S2OOM7AU.js";
@@ -5015,7 +5016,7 @@ async function handleJobStop(params, _ctx) {
5015
5016
  return stopDetachedJob(jobCwd(rec), id, reason ? { reason } : void 0);
5016
5017
  }
5017
5018
  async function defaultTurnWait(ref, timeoutMs) {
5018
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-6YVY6T5I.js");
5019
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-F7KXYDQW.js");
5019
5020
  const orch = getOrchestrator2();
5020
5021
  const thread = await orch.waitForTurn(ref, timeoutMs, {
5021
5022
  resolveIfStillRunning: true
@@ -10113,7 +10114,7 @@ function deliverPhoneTurn(opts, chatId) {
10113
10114
  });
10114
10115
  }
10115
10116
 
10116
- // src/remote/listen.ts
10117
+ // src/remote/phone-turn.ts
10117
10118
  function formatRemotePrompt(text5) {
10118
10119
  return `Phone
10119
10120
 
@@ -10122,6 +10123,29 @@ ${text5.trim()}`;
10122
10123
  function isRemoteStopCommand(text5) {
10123
10124
  return text5.trim().toLowerCase() === "stop";
10124
10125
  }
10126
+ function phoneFollowUpQueues(status) {
10127
+ return followUpBehavior() === "queue" && (status === "running" || status === "queued");
10128
+ }
10129
+ var PHONE_TURN_MS = 14 * 60 * 1e3;
10130
+ function delay(ms) {
10131
+ return new Promise((resolve) => setTimeout(resolve, ms));
10132
+ }
10133
+ async function waitForPhoneTurn(threadId, stillCurrent) {
10134
+ const deadline = Date.now() + PHONE_TURN_MS;
10135
+ while (stillCurrent() && Date.now() < deadline) {
10136
+ const thread2 = readPhoneThread(threadId) ?? readThread(threadId);
10137
+ if (!thread2) return;
10138
+ if (thread2.status === "stopped" && thread2.queue.length > 0) {
10139
+ await delay(40);
10140
+ continue;
10141
+ }
10142
+ break;
10143
+ }
10144
+ if (!stillCurrent()) return;
10145
+ const thread = readPhoneThread(threadId) ?? readThread(threadId);
10146
+ if (!thread || thread.status !== "running" && thread.status !== "queued") return;
10147
+ await getOrchestrator().waitForTurn(threadId, Math.max(1, deadline - Date.now()));
10148
+ }
10125
10149
  var handleChain2 = Promise.resolve();
10126
10150
  var inboundGeneration = 0;
10127
10151
  function enqueue(fn) {
@@ -10145,6 +10169,77 @@ function interruptRemoteCoordinator(deviceId, log = () => void 0) {
10145
10169
  return false;
10146
10170
  }
10147
10171
  }
10172
+ function runCoordinatorPrompt(opts, body, generation) {
10173
+ const current = () => generation === inboundGeneration;
10174
+ return (async () => {
10175
+ if (!current()) return;
10176
+ const agent = coerceOrchestratorAgent(opts.agent ?? resolveOrchestratorDefaults().agent);
10177
+ if (!body) return;
10178
+ if (isRemoteStopCommand(body)) {
10179
+ if (!current()) return;
10180
+ opts.onOutbound({ type: "assistant", text: REMOTE_STOPPED_REPLY });
10181
+ return;
10182
+ }
10183
+ let thread = ensureRemoteCoordinator(opts.deviceId, agent);
10184
+ thread = readThread(thread.id) ?? thread;
10185
+ const followUp = followUpBehavior();
10186
+ const orch = getOrchestrator();
10187
+ try {
10188
+ await orch.send(thread.id, formatRemotePrompt(body), { followUp });
10189
+ if (!current()) return;
10190
+ await waitForPhoneTurn(thread.id, current);
10191
+ } catch (err) {
10192
+ if (!current()) return;
10193
+ const message = err instanceof Error ? err.message : String(err);
10194
+ opts.onOutbound({ type: "assistant", text: `Sideboard failed: ${message}` });
10195
+ return;
10196
+ }
10197
+ if (!current()) return;
10198
+ thread = readThread(thread.id) ?? thread;
10199
+ if (thread.status === "stopped") return;
10200
+ const result = orch.getTurnResult(thread.id);
10201
+ const pending = extractPendingPlanQuestions(
10202
+ [...thread.messages].reverse().find((m) => m.role === "agent")?.parts
10203
+ );
10204
+ if (result.taskState === "input-required" && pending) {
10205
+ opts.onOutbound({
10206
+ type: "ask_user",
10207
+ text: result.text.trim(),
10208
+ questions: pending.questions.map((q) => ({
10209
+ question: q.question,
10210
+ options: q.options.map(
10211
+ (o) => o.description ? { label: o.label, description: o.description } : { label: o.label }
10212
+ )
10213
+ }))
10214
+ });
10215
+ return;
10216
+ }
10217
+ const reply = outboundReplyFromTurn(result, {
10218
+ inputRequired: "Sideboard is waiting for an answer.",
10219
+ canceled: REMOTE_STOPPED_REPLY,
10220
+ completedEmpty: () => "",
10221
+ failed: (detail) => detail ? `Sideboard failed: ${detail}` : "Sideboard failed before producing a result."
10222
+ });
10223
+ if (reply.trim()) opts.onOutbound({ type: "assistant", text: reply.trim() });
10224
+ })();
10225
+ }
10226
+ function beginCoordinatorPrompt(body, opts) {
10227
+ const live = body ? findRemoteCoordinator(opts.deviceId) : null;
10228
+ const fresh = live ? readThread(live.id) ?? live : null;
10229
+ if (body && !isRemoteStopCommand(body) && phoneFollowUpQueues(fresh?.status)) {
10230
+ const generation2 = inboundGeneration;
10231
+ enqueue(() => runCoordinatorPrompt(opts, body, generation2));
10232
+ return;
10233
+ }
10234
+ const generation = ++inboundGeneration;
10235
+ if (body && isRemoteStopCommand(body)) {
10236
+ interruptRemoteCoordinator(opts.deviceId, opts.onLog ?? (() => void 0));
10237
+ }
10238
+ const task = runCoordinatorPrompt(opts, body, generation);
10239
+ enqueue(() => task);
10240
+ }
10241
+
10242
+ // src/remote/listen.ts
10148
10243
  function emitOpened(opts, opened) {
10149
10244
  setPhoneOpenChat(opened.chat.id);
10150
10245
  emitControl(opts, { op: "opened", ...opened });
@@ -10414,23 +10509,27 @@ function handlePhoneControl(cmd, opts) {
10414
10509
  return;
10415
10510
  }
10416
10511
  const chatId = cmd.chatId;
10512
+ const existing = readPhoneThread(chatId);
10513
+ if (phoneFollowUpQueues(existing?.status)) {
10514
+ deliverPhoneTurn(opts, chatId);
10515
+ const generation2 = chatGeneration.get(chatId) ?? bumpChat(chatId);
10516
+ enqueueChat(chatId, () => runPhonePrompt(opts, cmd, chatId, generation2));
10517
+ return;
10518
+ }
10417
10519
  const generation = bumpChat(chatId);
10418
10520
  phoneTurnGen.set(chatId, generation);
10419
- interruptChat(chatId, log);
10420
- enqueueChat(chatId, async () => {
10421
- if (chatGeneration.get(chatId) !== generation) return;
10521
+ const task = runPhonePrompt(opts, cmd, chatId, generation);
10522
+ enqueueChat(chatId, () => task);
10523
+ }
10524
+ function runPhonePrompt(opts, cmd, chatId, generation) {
10525
+ const current = () => chatGeneration.get(chatId) === generation;
10526
+ return (async () => {
10527
+ if (!current()) return;
10422
10528
  const thread = readPhoneThread(chatId);
10423
10529
  if (!thread) {
10424
10530
  emitControl(opts, { op: "error", chatId, message: "That agent is not on this Mac." });
10425
10531
  return;
10426
10532
  }
10427
- if (thread.status === "running" || thread.status === "queued") {
10428
- try {
10429
- getOrchestrator().stop(thread.id, { clearQueue: true });
10430
- } catch {
10431
- }
10432
- }
10433
- if (chatGeneration.get(chatId) !== generation) return;
10434
10533
  const stopStream = watchPhoneStream(opts, chatId, thread.id, generation);
10435
10534
  try {
10436
10535
  try {
@@ -10438,14 +10537,19 @@ function handlePhoneControl(cmd, opts) {
10438
10537
  } catch (err) {
10439
10538
  emitControl(opts, { op: "error", chatId, message: phoneError(err) });
10440
10539
  }
10540
+ if (!current()) return;
10441
10541
  const live = readPhoneThread(thread.id) ?? thread;
10542
+ const followUp = followUpBehavior();
10442
10543
  const staged = stagePhoneTurnFiles(live.worktreePath, cmd);
10443
10544
  const text5 = cmd.text.trim() || (staged.length ? "See the attached files." : "");
10444
- const formatted = formatRemotePrompt(text5);
10445
- await getOrchestrator().send(thread.id, formatted, { attachments: staged });
10446
- await getOrchestrator().waitForTurn(thread.id, 14 * 60 * 1e3);
10545
+ await getOrchestrator().send(thread.id, formatRemotePrompt(text5), {
10546
+ attachments: staged,
10547
+ followUp
10548
+ });
10549
+ if (!current()) return;
10550
+ await waitForPhoneTurn(thread.id, current);
10447
10551
  } catch (err) {
10448
- if (chatGeneration.get(chatId) !== generation) return;
10552
+ if (!current()) return;
10449
10553
  const message = err instanceof Error ? err.message : String(err);
10450
10554
  emitControl(opts, { op: "error", chatId, message: `Sideboard failed: ${message}` });
10451
10555
  return;
@@ -10453,12 +10557,11 @@ function handlePhoneControl(cmd, opts) {
10453
10557
  stopStream();
10454
10558
  finishPhoneTurn(chatId, generation);
10455
10559
  }
10456
- if (chatGeneration.get(chatId) !== generation) return;
10560
+ if (!current()) return;
10457
10561
  emitChatTurn(opts, chatId, thread.id);
10458
- });
10562
+ })();
10459
10563
  }
10460
10564
  function handleRemoteInbound(text5, opts) {
10461
- const log = opts.onLog ?? (() => void 0);
10462
10565
  const body = text5.trim();
10463
10566
  const control = takePhoneControl(body);
10464
10567
  if (control) {
@@ -10469,64 +10572,7 @@ function handleRemoteInbound(text5, opts) {
10469
10572
  handlePhoneControl(control, opts);
10470
10573
  return;
10471
10574
  }
10472
- const generation = ++inboundGeneration;
10473
- if (body) interruptRemoteCoordinator(opts.deviceId, log);
10474
- enqueue(async () => {
10475
- if (generation !== inboundGeneration) return;
10476
- const agent = coerceOrchestratorAgent(opts.agent ?? resolveOrchestratorDefaults().agent);
10477
- if (!body) return;
10478
- if (isRemoteStopCommand(body)) {
10479
- if (generation !== inboundGeneration) return;
10480
- opts.onOutbound({ type: "assistant", text: REMOTE_STOPPED_REPLY });
10481
- return;
10482
- }
10483
- let thread = ensureRemoteCoordinator(opts.deviceId, agent);
10484
- const fresh = readThread(thread.id) ?? thread;
10485
- if (fresh.status === "running" || fresh.status === "queued") {
10486
- try {
10487
- getOrchestrator().stop(fresh.id, { clearQueue: true });
10488
- } catch {
10489
- }
10490
- }
10491
- if (generation !== inboundGeneration) return;
10492
- const orch = getOrchestrator();
10493
- try {
10494
- await orch.send(thread.id, formatRemotePrompt(body));
10495
- await orch.waitForTurn(thread.id, 14 * 60 * 1e3);
10496
- } catch (err) {
10497
- if (generation !== inboundGeneration) return;
10498
- const message = err instanceof Error ? err.message : String(err);
10499
- opts.onOutbound({ type: "assistant", text: `Sideboard failed: ${message}` });
10500
- return;
10501
- }
10502
- if (generation !== inboundGeneration) return;
10503
- thread = readThread(thread.id) ?? thread;
10504
- if (thread.status === "stopped") return;
10505
- const result = orch.getTurnResult(thread.id);
10506
- const pending = extractPendingPlanQuestions(
10507
- [...thread.messages].reverse().find((m) => m.role === "agent")?.parts
10508
- );
10509
- if (result.taskState === "input-required" && pending) {
10510
- opts.onOutbound({
10511
- type: "ask_user",
10512
- text: result.text.trim(),
10513
- questions: pending.questions.map((q) => ({
10514
- question: q.question,
10515
- options: q.options.map(
10516
- (o) => o.description ? { label: o.label, description: o.description } : { label: o.label }
10517
- )
10518
- }))
10519
- });
10520
- return;
10521
- }
10522
- const reply = outboundReplyFromTurn(result, {
10523
- inputRequired: "Sideboard is waiting for an answer.",
10524
- canceled: REMOTE_STOPPED_REPLY,
10525
- completedEmpty: () => "",
10526
- failed: (detail) => detail ? `Sideboard failed: ${detail}` : "Sideboard failed before producing a result."
10527
- });
10528
- if (reply.trim()) opts.onOutbound({ type: "assistant", text: reply.trim() });
10529
- });
10575
+ beginCoordinatorPrompt(body, opts);
10530
10576
  }
10531
10577
 
10532
10578
  // src/remote/phone-board-sync.ts
@@ -11463,15 +11509,43 @@ function sleep2(ms, signal) {
11463
11509
  signal?.addEventListener("abort", onAbort, { once: true });
11464
11510
  });
11465
11511
  }
11512
+ var RELAY_TLS_HINT = " \u2014 the TLS certificate was rejected. A work proxy often does this when Sideboard is not allowlisted, or when the app does not trust the corporate CA.";
11513
+ var RELAY_NETWORK_HINT = " Sideboard could not reach the relay. On a work computer this is often a VPN, a proxy, or an allowlist that does not include Sideboard.";
11514
+ var RELAY_NETWORK_RE = /fetch failed|Failed to fetch|ENOTFOUND|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EHOSTUNREACH|ENETUNREACH|EAI_AGAIN|EPERM|UND_ERR_|ERR_CONNECTION|ERR_NETWORK|ERR_PROXY|ERR_TUNNEL|ERR_INTERNET|ERR_BLOCKED|ERR_NAME_NOT_RESOLVED|ERR_ADDRESS_UNREACHABLE|ERR_CERT|CERT_|UNABLE_TO_GET_ISSUER|SELF_SIGNED/i;
11515
+ function relayFetchError(err, url) {
11516
+ const formatted = formatFetchError(err, url, { tlsHint: RELAY_TLS_HINT });
11517
+ if (formatted.includes(RELAY_TLS_HINT) || !RELAY_NETWORK_RE.test(formatted)) {
11518
+ return new Error(formatted);
11519
+ }
11520
+ return new Error(`${formatted}${RELAY_NETWORK_HINT}`);
11521
+ }
11522
+ async function relayFetch(fetchImpl, url, init) {
11523
+ const fn = fetchImpl ?? currentHttpFetch();
11524
+ try {
11525
+ return await fn(url, init);
11526
+ } catch (err) {
11527
+ throw relayFetchError(err, url);
11528
+ }
11529
+ }
11530
+ async function readJson2(res, url) {
11531
+ try {
11532
+ return await res.json();
11533
+ } catch {
11534
+ const kind = (res.headers.get("content-type") ?? "").includes("html") ? "an HTML page" : "a non-JSON body";
11535
+ throw new Error(
11536
+ `Relay sign-in returned HTTP ${res.status} with ${kind} (${url}). A work proxy or allowlist often answers with a block page instead of the relay.`
11537
+ );
11538
+ }
11539
+ }
11466
11540
  async function startRemoteAccountLogin(opts) {
11467
11541
  if (opts.signal?.aborted) throw new RemoteAccountLoginCancelled();
11468
11542
  const origin = (opts.origin ?? remoteAccountHttpOrigin()).replace(/\/+$/, "");
11469
- const fetchImpl = opts.fetchImpl ?? fetch;
11470
11543
  const state = randomBytes7(16).toString("hex");
11471
11544
  const timeoutMs = opts.timeoutMs ?? 5 * 6e4;
11472
11545
  const pollIntervalMs = opts.pollIntervalMs ?? 400;
11473
11546
  const linkToken = opts.linkToken?.trim() ?? "";
11474
- const started = await fetchImpl(`${origin}${REMOTE_LOGIN_PATH}`, {
11547
+ const startUrl = `${origin}${REMOTE_LOGIN_PATH}`;
11548
+ const started = await relayFetch(opts.fetchImpl, startUrl, {
11475
11549
  method: "POST",
11476
11550
  headers: { "Content-Type": "application/json" },
11477
11551
  body: JSON.stringify({
@@ -11480,9 +11554,9 @@ async function startRemoteAccountLogin(opts) {
11480
11554
  ...linkToken ? { accountToken: linkToken } : {}
11481
11555
  })
11482
11556
  });
11483
- const startBody = await started.json();
11557
+ const startBody = await readJson2(started, startUrl);
11484
11558
  if (!started.ok || !startBody.url) {
11485
- throw new Error(startBody.error || "Could not start sign-in.");
11559
+ throw new Error(startBody.error || `Could not start sign-in (HTTP ${started.status}).`);
11486
11560
  }
11487
11561
  await Promise.resolve(opts.openUrl?.(startBody.url));
11488
11562
  const deadline = Date.now() + timeoutMs;
@@ -11491,9 +11565,11 @@ async function startRemoteAccountLogin(opts) {
11491
11565
  if (opts.signal?.aborted) throw new RemoteAccountLoginCancelled();
11492
11566
  let res;
11493
11567
  try {
11494
- res = await fetchImpl(resultUrl);
11495
- } catch {
11496
- if (opts.signal?.aborted) throw new RemoteAccountLoginCancelled();
11568
+ res = await relayFetch(opts.fetchImpl, resultUrl);
11569
+ } catch (err) {
11570
+ if (opts.signal?.aborted || isRemoteAccountLoginCancelled(err)) {
11571
+ throw new RemoteAccountLoginCancelled();
11572
+ }
11497
11573
  await sleep2(pollIntervalMs, opts.signal);
11498
11574
  continue;
11499
11575
  }
@@ -11518,8 +11594,7 @@ async function startRemoteAccountLogin(opts) {
11518
11594
  }
11519
11595
  async function disconnectRemoteAccount(opts) {
11520
11596
  const origin = (opts.origin ?? remoteAccountHttpOrigin()).replace(/\/+$/, "");
11521
- const fetchImpl = opts.fetchImpl ?? fetch;
11522
- await fetchImpl(`${origin}${REMOTE_LOGOUT_PATH}`, {
11597
+ await relayFetch(opts.fetchImpl, `${origin}${REMOTE_LOGOUT_PATH}`, {
11523
11598
  method: "POST",
11524
11599
  headers: { "Content-Type": "application/json" },
11525
11600
  body: JSON.stringify({ accountToken: opts.accountToken })
@@ -12411,7 +12486,7 @@ async function continueSourceThread(threadId, prompt) {
12411
12486
  await continueOnReply(threadId, prompt);
12412
12487
  return;
12413
12488
  }
12414
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-6YVY6T5I.js");
12489
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-F7KXYDQW.js");
12415
12490
  await getOrchestrator2().send(threadId, prompt);
12416
12491
  } catch {
12417
12492
  }
@@ -10254,30 +10254,49 @@ var init_accounts = __esm({
10254
10254
  });
10255
10255
 
10256
10256
  // src/http/fetch.ts
10257
- function tlsIssuerHint(code, message) {
10258
- const text7 = `${code ?? ""} ${message}`;
10259
- return TLS_ISSUER_RE.test(text7) ? TLS_ISSUER_HINT : "";
10257
+ function isTlsIssuerFailure(code, message) {
10258
+ return TLS_ISSUER_RE.test(`${code ?? ""} ${message}`);
10260
10259
  }
10261
- function formatFetchError(err, url) {
10262
- if (!(err instanceof Error)) return `${String(err)} (${url})`;
10263
- const cause = err.cause;
10264
- let detail = "";
10265
- let hint = tlsIssuerHint(void 0, err.message);
10260
+ function describeCause(cause, depth = 0) {
10261
+ if (depth > 5 || cause == null) return null;
10262
+ if (cause instanceof AggregateError) {
10263
+ for (const item of cause.errors) {
10264
+ const found = describeCause(item, depth + 1);
10265
+ if (found && (found.code || found.message)) return found;
10266
+ }
10267
+ return cause.message ? { message: cause.message } : null;
10268
+ }
10266
10269
  if (cause instanceof Error) {
10267
10270
  const code = typeof cause.code === "string" ? cause.code : void 0;
10268
- detail = code ? ` [${code}: ${cause.message}]` : ` [${cause.message}]`;
10269
- hint = tlsIssuerHint(code, `${err.message} ${cause.message}`) || hint;
10270
- } else if (cause != null) {
10271
- detail = ` [${String(cause)}]`;
10272
- hint = tlsIssuerHint(void 0, String(cause)) || hint;
10273
- }
10274
- return `${err.message}${detail} (${url})${hint}`;
10271
+ const nested = describeCause(cause.cause, depth + 1);
10272
+ if ((!cause.message || cause.message === "fetch failed") && nested) return nested;
10273
+ if (cause.message || code) return { code, message: cause.message };
10274
+ return nested;
10275
+ }
10276
+ return { message: String(cause) };
10277
+ }
10278
+ function causeSuffix(detail) {
10279
+ if (!detail) return "";
10280
+ if (detail.code && detail.message) return ` [${detail.code}: ${detail.message}]`;
10281
+ if (detail.code) return ` [${detail.code}]`;
10282
+ if (detail.message) return ` [${detail.message}]`;
10283
+ return "";
10284
+ }
10285
+ function formatFetchError(err, url, opts) {
10286
+ if (!(err instanceof Error)) return `${String(err)} (${url})`;
10287
+ const detail = describeCause(err.cause);
10288
+ const hintSource = `${err.message} ${detail?.code ?? ""} ${detail?.message ?? ""}`;
10289
+ const tls2 = isTlsIssuerFailure(detail?.code, hintSource);
10290
+ const hint = tls2 ? opts?.tlsHint ?? TLS_ISSUER_HINT : "";
10291
+ return `${err.message}${causeSuffix(detail)} (${url})${hint}`;
10292
+ }
10293
+ function currentHttpFetch() {
10294
+ return injected ?? globalThis.fetch.bind(globalThis);
10275
10295
  }
10276
10296
  async function httpFetch(input, init) {
10277
10297
  const url = typeof input === "string" ? input : input.href;
10278
- const fn = injected ?? globalThis.fetch.bind(globalThis);
10279
10298
  try {
10280
- return await fn(url, init);
10299
+ return await currentHttpFetch()(url, init);
10281
10300
  } catch (err) {
10282
10301
  throw new Error(formatFetchError(err, url));
10283
10302
  }
@@ -18,9 +18,9 @@ import {
18
18
  searchAbleTimeTasks,
19
19
  toAbleTimeIssueInfo,
20
20
  updateAbleTimeTask
21
- } from "../chunk-BS3QLVPL.js";
22
- import "../chunk-I6HSGKMZ.js";
23
- import "../chunk-PY4UCMRI.js";
21
+ } from "../chunk-TMM4FEZ5.js";
22
+ import "../chunk-5T4YWFLD.js";
23
+ import "../chunk-VQEARG5H.js";
24
24
  import {
25
25
  AGENT_GIT_ACTIONS,
26
26
  BOARD_COLUMN_DEFS,
@@ -71,7 +71,7 @@ import {
71
71
  syncBoardPins,
72
72
  updateSchedule,
73
73
  workspaceTagTargetRef
74
- } from "../chunk-OEJQK7CY.js";
74
+ } from "../chunk-2K723QZH.js";
75
75
  import "../chunk-LX5R5JOR.js";
76
76
  import {
77
77
  PRESENT_PLAN_REQUIRES_PLAN_MODE,
@@ -90,12 +90,12 @@ import {
90
90
  sideboardMcpProfile,
91
91
  trustSystemCertificates,
92
92
  worktreeMcpToolNames
93
- } from "../chunk-BSN6DJ4L.js";
94
- import "../chunk-TQRSVE7D.js";
95
- import "../chunk-P2BSMNHB.js";
93
+ } from "../chunk-TXHZJESB.js";
94
+ import "../chunk-7IAMHN2N.js";
95
+ import "../chunk-PXMLMBMI.js";
96
96
  import {
97
97
  httpFetch
98
- } from "../chunk-VKQGAWHY.js";
98
+ } from "../chunk-2GPQZZLY.js";
99
99
  import {
100
100
  mcpWaitForJobTimeoutMs,
101
101
  mcpWaitForTurnTimeoutMs,
@@ -7,8 +7,8 @@ import {
7
7
  normalizeBrightsyEndpoint,
8
8
  refreshBrightsyAccessToken,
9
9
  registerBrightsyOAuthClient
10
- } from "./chunk-ROPGQRPU.js";
11
- import "./chunk-N7WZ6NIN.js";
10
+ } from "./chunk-33KDPEK4.js";
11
+ import "./chunk-JAT3JFOS.js";
12
12
  export {
13
13
  BRIGHTSY_OAUTH_CLIENT_ID,
14
14
  BRIGHTSY_OAUTH_REDIRECT,
@@ -9,8 +9,8 @@ import {
9
9
  normalizeBrightsyEndpoint,
10
10
  refreshBrightsyAccessToken,
11
11
  registerBrightsyOAuthClient
12
- } from "./chunk-P2BSMNHB.js";
13
- import "./chunk-VKQGAWHY.js";
12
+ } from "./chunk-PXMLMBMI.js";
13
+ import "./chunk-2GPQZZLY.js";
14
14
  export {
15
15
  BRIGHTSY_OAUTH_CLIENT_ID,
16
16
  BRIGHTSY_OAUTH_REDIRECT,
@@ -9,9 +9,9 @@ import {
9
9
  resolveSendFollowUp,
10
10
  startOrchestration,
11
11
  waitForPidExit
12
- } from "./chunk-WQ4M2L44.js";
13
- import "./chunk-COQLZNKQ.js";
14
- import "./chunk-GWFVCCJZ.js";
12
+ } from "./chunk-C6NVTLZK.js";
13
+ import "./chunk-XSPOJFTV.js";
14
+ import "./chunk-VGNLMGBK.js";
15
15
  import "./chunk-BMUVNTT4.js";
16
16
  import "./chunk-XSDCLM3F.js";
17
17
  import "./chunk-7H655NEW.js";
@@ -20,8 +20,8 @@ import "./chunk-WY2IAB7J.js";
20
20
  import "./chunk-K5XSTHHP.js";
21
21
  import "./chunk-N5UGX3JL.js";
22
22
  import "./chunk-2P4XKWV2.js";
23
- import "./chunk-ROPGQRPU.js";
24
- import "./chunk-N7WZ6NIN.js";
23
+ import "./chunk-33KDPEK4.js";
24
+ import "./chunk-JAT3JFOS.js";
25
25
  import "./chunk-AXQ4ZWHK.js";
26
26
  import "./chunk-VOIWX5HA.js";
27
27
  import "./chunk-U6QDXT4K.js";
@@ -11,14 +11,14 @@ import {
11
11
  resolveSendFollowUp,
12
12
  startOrchestration,
13
13
  waitForPidExit
14
- } from "./chunk-OEJQK7CY.js";
14
+ } from "./chunk-2K723QZH.js";
15
15
  import "./chunk-LX5R5JOR.js";
16
16
  import "./chunk-4GK32AYX.js";
17
17
  import "./chunk-5DZUWGKV.js";
18
- import "./chunk-BSN6DJ4L.js";
19
- import "./chunk-TQRSVE7D.js";
20
- import "./chunk-P2BSMNHB.js";
21
- import "./chunk-VKQGAWHY.js";
18
+ import "./chunk-TXHZJESB.js";
19
+ import "./chunk-7IAMHN2N.js";
20
+ import "./chunk-PXMLMBMI.js";
21
+ import "./chunk-2GPQZZLY.js";
22
22
  import "./chunk-LMWPVC5L.js";
23
23
  import "./chunk-5QOLFOAX.js";
24
24
  import "./chunk-2SJXQ4UX.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sideboard-ai/core",
3
- "version": "0.1.284",
3
+ "version": "0.1.285",
4
4
  "description": "Sideboard core — orchestration, agents, git worktrees, MCP server",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -1,41 +0,0 @@
1
- // src/http/fetch.ts
2
- var injected = null;
3
- function setHttpFetchImpl(fetchImpl) {
4
- injected = fetchImpl;
5
- }
6
- var TLS_ISSUER_RE = /UNABLE_TO_GET_ISSUER_CERT|UNABLE_TO_VERIFY_LEAF_SIGNATURE|SELF_SIGNED_CERT_IN_CHAIN/i;
7
- var TLS_ISSUER_HINT = " \u2014 Node rejected the TLS certificate (corporate VPN/proxy CA). Desktop Linear can still work; reconnecting the API key will not fix this.";
8
- function tlsIssuerHint(code, message) {
9
- const text = `${code ?? ""} ${message}`;
10
- return TLS_ISSUER_RE.test(text) ? TLS_ISSUER_HINT : "";
11
- }
12
- function formatFetchError(err, url) {
13
- if (!(err instanceof Error)) return `${String(err)} (${url})`;
14
- const cause = err.cause;
15
- let detail = "";
16
- let hint = tlsIssuerHint(void 0, err.message);
17
- if (cause instanceof Error) {
18
- const code = typeof cause.code === "string" ? cause.code : void 0;
19
- detail = code ? ` [${code}: ${cause.message}]` : ` [${cause.message}]`;
20
- hint = tlsIssuerHint(code, `${err.message} ${cause.message}`) || hint;
21
- } else if (cause != null) {
22
- detail = ` [${String(cause)}]`;
23
- hint = tlsIssuerHint(void 0, String(cause)) || hint;
24
- }
25
- return `${err.message}${detail} (${url})${hint}`;
26
- }
27
- async function httpFetch(input, init) {
28
- const url = typeof input === "string" ? input : input.href;
29
- const fn = injected ?? globalThis.fetch.bind(globalThis);
30
- try {
31
- return await fn(url, init);
32
- } catch (err) {
33
- throw new Error(formatFetchError(err, url));
34
- }
35
- }
36
-
37
- export {
38
- setHttpFetchImpl,
39
- formatFetchError,
40
- httpFetch
41
- };