@sideboard-ai/core 0.1.284 → 0.1.286

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 (54) 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-6U2RQK7P.js → agents-BHUXZ7XO.js} +5 -5
  10. package/dist/{agents-PM5ICSO3.js → agents-QNIFTZPN.js} +5 -5
  11. package/dist/chunk-2GPQZZLY.js +59 -0
  12. package/dist/{chunk-ROPGQRPU.js → chunk-33KDPEK4.js} +1 -1
  13. package/dist/{chunk-BSN6DJ4L.js → chunk-3H5U4QLD.js} +5 -5
  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-BMUVNTT4.js → chunk-ABOH7GBG.js} +2 -2
  18. package/dist/{chunk-OEJQK7CY.js → chunk-CBIUGGPI.js} +14 -13
  19. package/dist/{chunk-VA55JG2I.js → chunk-DEJALWKM.js} +5 -5
  20. package/dist/{chunk-LMWPVC5L.js → chunk-ETZPTOK7.js} +2 -2
  21. package/dist/{chunk-WQ4M2L44.js → chunk-HJNFK5SP.js} +16 -15
  22. package/dist/{chunk-XTPQEZZA.js → chunk-IJMUYHPT.js} +3 -3
  23. package/dist/chunk-JAT3JFOS.js +61 -0
  24. package/dist/{chunk-DGPROCE5.js → chunk-LS4FFCPL.js} +3 -3
  25. package/dist/{chunk-WY2IAB7J.js → chunk-MGJ7R7UX.js} +45 -1
  26. package/dist/{chunk-COQLZNKQ.js → chunk-PCNH74SF.js} +5 -5
  27. package/dist/{chunk-P2BSMNHB.js → chunk-PXMLMBMI.js} +1 -1
  28. package/dist/{chunk-BS3QLVPL.js → chunk-TMM4FEZ5.js} +3 -3
  29. package/dist/{chunk-2SJXQ4UX.js → chunk-ULSY2BJF.js} +45 -1
  30. package/dist/{chunk-GWFVCCJZ.js → chunk-VGNLMGBK.js} +6 -6
  31. package/dist/{chunk-PY4UCMRI.js → chunk-VQEARG5H.js} +5 -5
  32. package/dist/{conductor-MU3TYVCD.js → conductor-RBJYEF7L.js} +2 -2
  33. package/dist/{conductor-GBX6LSP2.js → conductor-WYOWFB7I.js} +2 -2
  34. package/dist/{connected-teams-JIUOSZ6C.js → connected-teams-AB7ZHJVO.js} +3 -3
  35. package/dist/{connected-teams-RU6VATCM.js → connected-teams-BJ6PMIST.js} +3 -3
  36. package/dist/{coordinator-prompt-SVVGU6AZ.js → coordinator-prompt-5DE3XBNT.js} +1 -1
  37. package/dist/{coordinator-prompt-4DJIHSE6.js → coordinator-prompt-R42WEL3T.js} +1 -1
  38. package/dist/{global-workspace-XON4YZXE.js → global-workspace-IPIEC6FM.js} +1 -1
  39. package/dist/{global-workspace-UPUDWIS6.js → global-workspace-NXMYLS34.js} +1 -1
  40. package/dist/index.cjs +300 -155
  41. package/dist/index.d.cts +16 -3
  42. package/dist/index.d.ts +16 -3
  43. package/dist/index.js +177 -98
  44. package/dist/mcp/run-stdio.cjs +121 -58
  45. package/dist/mcp/run-stdio.js +10 -10
  46. package/dist/{oauth-S3M7B475.js → oauth-DP4ZV2M2.js} +2 -2
  47. package/dist/{oauth-K6CWZEQO.js → oauth-WCUZ6Z5G.js} +2 -2
  48. package/dist/{orchestrator-6YVY6T5I.js → orchestrator-65QGA6BB.js} +7 -7
  49. package/dist/{orchestrator-CRBIW2RG.js → orchestrator-YEZV35G7.js} +7 -7
  50. package/dist/{workspaces-F76BWCSI.js → workspaces-5C5ESWPU.js} +5 -1
  51. package/dist/{workspaces-7AJ5RZ3P.js → workspaces-LIFFWK23.js} +5 -1
  52. package/package.json +1 -1
  53. package/dist/chunk-N7WZ6NIN.js +0 -41
  54. package/dist/chunk-VKQGAWHY.js +0 -40
package/dist/index.cjs CHANGED
@@ -11171,6 +11171,8 @@ var init_stage_files = __esm({
11171
11171
  var workspaces_exports = {};
11172
11172
  __export(workspaces_exports, {
11173
11173
  addWorkspace: () => addWorkspace,
11174
+ archiveRemovedWorkspaceChats: () => archiveRemovedWorkspaceChats,
11175
+ archivesWithRemovedWorkspace: () => archivesWithRemovedWorkspace,
11174
11176
  ensureWorkspace: () => ensureWorkspace,
11175
11177
  isRemovedWorkspace: () => isRemovedWorkspace,
11176
11178
  listWorkspaces: () => listWorkspaces,
@@ -11227,10 +11229,33 @@ function sameWorkspacePath(a, b) {
11227
11229
  if (primaryB && primaryB === left) return true;
11228
11230
  return false;
11229
11231
  }
11232
+ function pathIsInside(parent, child) {
11233
+ const root = parent.replace(/\/+$/, "");
11234
+ const path2 = child.replace(/\/+$/, "");
11235
+ if (!root || !path2) return false;
11236
+ return path2 === root || path2.startsWith(`${root}/`);
11237
+ }
11238
+ function defaultWorktreesRoot(repoPath) {
11239
+ const slug = (0, import_node_path27.basename)(repoPath.replace(/\/+$/, "")) || "repo";
11240
+ return (0, import_node_path27.join)((0, import_node_os9.homedir)(), "sideboard", "workspaces", slug);
11241
+ }
11242
+ function removedWorktreeCoversRepo(saved, repoPath) {
11243
+ if (!saved || !repoPath) return false;
11244
+ if (pathIsInside(defaultWorktreesRoot(repoPath), saved)) return true;
11245
+ try {
11246
+ const custom = loadRepoSettings(repoPath)?.worktreesRoot;
11247
+ if (custom && pathIsInside(custom, saved)) return true;
11248
+ } catch {
11249
+ }
11250
+ return false;
11251
+ }
11230
11252
  function removedMatches(saved, repoPath) {
11231
11253
  if (saved === repoPath || sameWorkspacePath(saved, repoPath)) return true;
11232
11254
  const primary = primaryCheckoutFromLinkedWorktree(repoPath);
11233
- return Boolean(primary && sameWorkspacePath(saved, primary));
11255
+ if (primary && (sameWorkspacePath(saved, primary) || removedWorktreeCoversRepo(saved, primary))) {
11256
+ return true;
11257
+ }
11258
+ return removedWorktreeCoversRepo(saved, repoPath);
11234
11259
  }
11235
11260
  function isRemovedWorkspace(repoPath) {
11236
11261
  if (!repoPath) return false;
@@ -11239,6 +11264,10 @@ function isRemovedWorkspace(repoPath) {
11239
11264
  }
11240
11265
  return false;
11241
11266
  }
11267
+ function archivesWithRemovedWorkspace(threadRepoPath, removedPath) {
11268
+ if (!threadRepoPath || isGlobalRepoPath(threadRepoPath)) return false;
11269
+ return isRemovedWorkspace(threadRepoPath) || sameWorkspacePath(threadRepoPath, removedPath);
11270
+ }
11242
11271
  function rememberRemoved(repoPath) {
11243
11272
  const next = readRemoved();
11244
11273
  const before = next.size;
@@ -11246,6 +11275,8 @@ function rememberRemoved(repoPath) {
11246
11275
  next.add(canon);
11247
11276
  const raw = repoPath.replace(/\/+$/, "");
11248
11277
  if (raw && raw !== canon) next.add(raw);
11278
+ const primary = primaryCheckoutFromLinkedWorktree(repoPath) ?? (canon !== repoPath ? primaryCheckoutFromLinkedWorktree(canon) : null);
11279
+ if (primary) next.add(primary);
11249
11280
  if (next.size !== before) writeRemoved(next);
11250
11281
  }
11251
11282
  function forgetRemoved(repoPath) {
@@ -11378,12 +11409,25 @@ function syncWorkspacesFromThreads(repoPaths) {
11378
11409
  if (dirty) writeAll2(next);
11379
11410
  return next.sort((a, b) => a.name.localeCompare(b.name));
11380
11411
  }
11381
- var import_node_fs24, import_node_path27;
11412
+ async function archiveRemovedWorkspaceChats(threads, archive) {
11413
+ const failures = [];
11414
+ for (const thread of threads) {
11415
+ try {
11416
+ await archive(thread.id);
11417
+ } catch (err) {
11418
+ failures.push(err instanceof Error ? err.message : String(err));
11419
+ }
11420
+ }
11421
+ if (failures.length > 0) throw new Error(failures.join("\n"));
11422
+ }
11423
+ var import_node_fs24, import_node_os9, import_node_path27;
11382
11424
  var init_workspaces = __esm({
11383
11425
  "src/store/workspaces.ts"() {
11384
11426
  "use strict";
11385
11427
  import_node_fs24 = require("fs");
11428
+ import_node_os9 = require("os");
11386
11429
  import_node_path27 = require("path");
11430
+ init_settings();
11387
11431
  init_paths();
11388
11432
  init_global_workspace();
11389
11433
  init_worktree();
@@ -11966,7 +12010,7 @@ var init_turn_trace = __esm({
11966
12010
  function brightsyConfigPath() {
11967
12011
  const override = process.env.BRIGHTSY_CONFIG?.trim();
11968
12012
  if (override) return override;
11969
- return (0, import_node_path30.join)((0, import_node_os9.homedir)(), ".brightsy", "config.json");
12013
+ return (0, import_node_path30.join)((0, import_node_os10.homedir)(), ".brightsy", "config.json");
11970
12014
  }
11971
12015
  function loadBrightsyConfig() {
11972
12016
  const path2 = brightsyConfigPath();
@@ -11985,12 +12029,12 @@ function saveBrightsyConfig(cfg) {
11985
12029
  mode: 384
11986
12030
  });
11987
12031
  }
11988
- var import_node_fs27, import_node_os9, import_node_path30;
12032
+ var import_node_fs27, import_node_os10, import_node_path30;
11989
12033
  var init_config = __esm({
11990
12034
  "src/brightsy/config.ts"() {
11991
12035
  "use strict";
11992
12036
  import_node_fs27 = require("fs");
11993
- import_node_os9 = require("os");
12037
+ import_node_os10 = require("os");
11994
12038
  import_node_path30 = require("path");
11995
12039
  }
11996
12040
  });
@@ -11999,30 +12043,49 @@ var init_config = __esm({
11999
12043
  function setHttpFetchImpl(fetchImpl) {
12000
12044
  injected = fetchImpl;
12001
12045
  }
12002
- function tlsIssuerHint(code, message) {
12003
- const text7 = `${code ?? ""} ${message}`;
12004
- return TLS_ISSUER_RE.test(text7) ? TLS_ISSUER_HINT : "";
12046
+ function isTlsIssuerFailure(code, message) {
12047
+ return TLS_ISSUER_RE.test(`${code ?? ""} ${message}`);
12005
12048
  }
12006
- function formatFetchError(err, url) {
12007
- if (!(err instanceof Error)) return `${String(err)} (${url})`;
12008
- const cause = err.cause;
12009
- let detail = "";
12010
- let hint = tlsIssuerHint(void 0, err.message);
12049
+ function describeCause(cause, depth = 0) {
12050
+ if (depth > 5 || cause == null) return null;
12051
+ if (cause instanceof AggregateError) {
12052
+ for (const item of cause.errors) {
12053
+ const found = describeCause(item, depth + 1);
12054
+ if (found && (found.code || found.message)) return found;
12055
+ }
12056
+ return cause.message ? { message: cause.message } : null;
12057
+ }
12011
12058
  if (cause instanceof Error) {
12012
12059
  const code = typeof cause.code === "string" ? cause.code : void 0;
12013
- detail = code ? ` [${code}: ${cause.message}]` : ` [${cause.message}]`;
12014
- hint = tlsIssuerHint(code, `${err.message} ${cause.message}`) || hint;
12015
- } else if (cause != null) {
12016
- detail = ` [${String(cause)}]`;
12017
- hint = tlsIssuerHint(void 0, String(cause)) || hint;
12018
- }
12019
- return `${err.message}${detail} (${url})${hint}`;
12060
+ const nested = describeCause(cause.cause, depth + 1);
12061
+ if ((!cause.message || cause.message === "fetch failed") && nested) return nested;
12062
+ if (cause.message || code) return { code, message: cause.message };
12063
+ return nested;
12064
+ }
12065
+ return { message: String(cause) };
12066
+ }
12067
+ function causeSuffix(detail) {
12068
+ if (!detail) return "";
12069
+ if (detail.code && detail.message) return ` [${detail.code}: ${detail.message}]`;
12070
+ if (detail.code) return ` [${detail.code}]`;
12071
+ if (detail.message) return ` [${detail.message}]`;
12072
+ return "";
12073
+ }
12074
+ function formatFetchError(err, url, opts) {
12075
+ if (!(err instanceof Error)) return `${String(err)} (${url})`;
12076
+ const detail = describeCause(err.cause);
12077
+ const hintSource = `${err.message} ${detail?.code ?? ""} ${detail?.message ?? ""}`;
12078
+ const tls2 = isTlsIssuerFailure(detail?.code, hintSource);
12079
+ const hint = tls2 ? opts?.tlsHint ?? TLS_ISSUER_HINT : "";
12080
+ return `${err.message}${causeSuffix(detail)} (${url})${hint}`;
12081
+ }
12082
+ function currentHttpFetch() {
12083
+ return injected ?? globalThis.fetch.bind(globalThis);
12020
12084
  }
12021
12085
  async function httpFetch(input, init) {
12022
12086
  const url = typeof input === "string" ? input : input.href;
12023
- const fn = injected ?? globalThis.fetch.bind(globalThis);
12024
12087
  try {
12025
- return await fn(url, init);
12088
+ return await currentHttpFetch()(url, init);
12026
12089
  } catch (err) {
12027
12090
  throw new Error(formatFetchError(err, url));
12028
12091
  }
@@ -13445,7 +13508,7 @@ function versionDirNodeBins(root, toBin) {
13445
13508
  return [];
13446
13509
  }
13447
13510
  }
13448
- function defaultNodeBinCandidates(home = (0, import_node_os10.homedir)()) {
13511
+ function defaultNodeBinCandidates(home = (0, import_node_os11.homedir)()) {
13449
13512
  const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
13450
13513
  (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path34.join)(prefix, "opt", `node@${major}`, "bin", "node"))
13451
13514
  );
@@ -13560,12 +13623,12 @@ async function resolveNodeLaunch(scriptPath) {
13560
13623
  env: { ELECTRON_RUN_AS_NODE: "1" }
13561
13624
  };
13562
13625
  }
13563
- var import_node_fs32, import_node_os10, import_node_path34, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
13626
+ var import_node_fs32, import_node_os11, import_node_path34, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
13564
13627
  var init_node_launch = __esm({
13565
13628
  "src/agents/node-launch.ts"() {
13566
13629
  "use strict";
13567
13630
  import_node_fs32 = require("fs");
13568
- import_node_os10 = require("os");
13631
+ import_node_os11 = require("os");
13569
13632
  import_node_path34 = require("path");
13570
13633
  init_nested_electron_env();
13571
13634
  init_system_ca();
@@ -13864,7 +13927,7 @@ function mcpServersRecord(servers, extraServers) {
13864
13927
  function writeMcpServersConfig(servers, extraServers) {
13865
13928
  const mcpServers = mcpServersRecord(servers, extraServers);
13866
13929
  if (Object.keys(mcpServers).length === 0) return null;
13867
- const dir = (0, import_node_fs33.mkdtempSync)((0, import_node_path35.join)((0, import_node_os11.tmpdir)(), "sideboard-mcp-"));
13930
+ const dir = (0, import_node_fs33.mkdtempSync)((0, import_node_path35.join)((0, import_node_os12.tmpdir)(), "sideboard-mcp-"));
13868
13931
  const cfgPath = (0, import_node_path35.join)(dir, "mcp.json");
13869
13932
  (0, import_node_fs33.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
13870
13933
  return cfgPath;
@@ -13872,13 +13935,13 @@ function writeMcpServersConfig(servers, extraServers) {
13872
13935
  async function writeInjectedMcpConfig(opts) {
13873
13936
  return writeMcpServersConfig(await buildInjectedMcpServers(opts));
13874
13937
  }
13875
- var import_node_fs33, import_node_module, import_node_os11, import_node_path35, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS, SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS, SIDEBOARD_ABLETIME_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
13938
+ var import_node_fs33, import_node_module, import_node_os12, import_node_path35, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS, SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS, SIDEBOARD_ABLETIME_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
13876
13939
  var init_injected_mcp = __esm({
13877
13940
  "src/agents/injected-mcp.ts"() {
13878
13941
  "use strict";
13879
13942
  import_node_fs33 = require("fs");
13880
13943
  import_node_module = require("module");
13881
- import_node_os11 = require("os");
13944
+ import_node_os12 = require("os");
13882
13945
  import_node_path35 = require("path");
13883
13946
  import_node_url = require("url");
13884
13947
  init_run();
@@ -13935,10 +13998,10 @@ var init_injected_mcp = __esm({
13935
13998
 
13936
13999
  // src/agents/user-mcp-config.ts
13937
14000
  function userCursorMcpConfigPath() {
13938
- return (0, import_node_path36.join)((0, import_node_os12.homedir)(), ".cursor", "mcp.json");
14001
+ return (0, import_node_path36.join)((0, import_node_os13.homedir)(), ".cursor", "mcp.json");
13939
14002
  }
13940
14003
  function userClaudeMcpConfigPath() {
13941
- return (0, import_node_path36.join)((0, import_node_os12.homedir)(), ".claude.json");
14004
+ return (0, import_node_path36.join)((0, import_node_os13.homedir)(), ".claude.json");
13942
14005
  }
13943
14006
  function asObject(value) {
13944
14007
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
@@ -13998,12 +14061,12 @@ async function registerPackagedUserMcpClients() {
13998
14061
  }
13999
14062
  return { cursor };
14000
14063
  }
14001
- var import_node_fs34, import_node_os12, import_node_path36;
14064
+ var import_node_fs34, import_node_os13, import_node_path36;
14002
14065
  var init_user_mcp_config = __esm({
14003
14066
  "src/agents/user-mcp-config.ts"() {
14004
14067
  "use strict";
14005
14068
  import_node_fs34 = require("fs");
14006
- import_node_os12 = require("os");
14069
+ import_node_os13 = require("os");
14007
14070
  import_node_path36 = require("path");
14008
14071
  init_paths();
14009
14072
  init_injected_mcp();
@@ -14044,10 +14107,10 @@ function readText(path2) {
14044
14107
  return "";
14045
14108
  }
14046
14109
  }
14047
- function userCodexConfigPaths(home = (0, import_node_os13.homedir)()) {
14110
+ function userCodexConfigPaths(home = (0, import_node_os14.homedir)()) {
14048
14111
  return [(0, import_node_path37.join)(home, ".codex", "config.toml"), (0, import_node_path37.join)(home, ".config", "codex", "config.toml")];
14049
14112
  }
14050
- function userOpencodeConfigPaths(home = (0, import_node_os13.homedir)()) {
14113
+ function userOpencodeConfigPaths(home = (0, import_node_os14.homedir)()) {
14051
14114
  return [
14052
14115
  (0, import_node_path37.join)(home, ".config", "opencode", "opencode.json"),
14053
14116
  (0, import_node_path37.join)(home, ".config", "opencode", "opencode.jsonc")
@@ -14069,7 +14132,7 @@ function userMcpNamesToDisable(opts) {
14069
14132
  }
14070
14133
  return out;
14071
14134
  }
14072
- function listUserCodexMcpNames(home = (0, import_node_os13.homedir)()) {
14135
+ function listUserCodexMcpNames(home = (0, import_node_os14.homedir)()) {
14073
14136
  const names = [];
14074
14137
  for (const path2 of userCodexConfigPaths(home)) {
14075
14138
  if (!(0, import_node_fs35.existsSync)(path2)) continue;
@@ -14077,7 +14140,7 @@ function listUserCodexMcpNames(home = (0, import_node_os13.homedir)()) {
14077
14140
  }
14078
14141
  return names;
14079
14142
  }
14080
- function listUserOpencodeMcpNames(home = (0, import_node_os13.homedir)()) {
14143
+ function listUserOpencodeMcpNames(home = (0, import_node_os14.homedir)()) {
14081
14144
  const names = [];
14082
14145
  for (const path2 of userOpencodeConfigPaths(home)) {
14083
14146
  if (!(0, import_node_fs35.existsSync)(path2)) continue;
@@ -14085,12 +14148,12 @@ function listUserOpencodeMcpNames(home = (0, import_node_os13.homedir)()) {
14085
14148
  }
14086
14149
  return names;
14087
14150
  }
14088
- function userClaudeMcpConfigObject(home = (0, import_node_os13.homedir)()) {
14089
- const claudePath = home === (0, import_node_os13.homedir)() ? userClaudeMcpConfigPath() : (0, import_node_path37.join)(home, ".claude.json");
14151
+ function userClaudeMcpConfigObject(home = (0, import_node_os14.homedir)()) {
14152
+ const claudePath = home === (0, import_node_os14.homedir)() ? userClaudeMcpConfigPath() : (0, import_node_path37.join)(home, ".claude.json");
14090
14153
  if (!(0, import_node_fs35.existsSync)(claudePath)) return {};
14091
14154
  return asObject2(asObject2(readJsonObject2(claudePath)).mcpServers);
14092
14155
  }
14093
- function listUserClaudeMcpServerEntries(home = (0, import_node_os13.homedir)()) {
14156
+ function listUserClaudeMcpServerEntries(home = (0, import_node_os14.homedir)()) {
14094
14157
  const out = {};
14095
14158
  for (const [rawName, value] of Object.entries(userClaudeMcpConfigObject(home))) {
14096
14159
  const name = rawName.trim();
@@ -14120,12 +14183,12 @@ function toCodexUnattendedAppsArgs() {
14120
14183
  "features.plugins=false"
14121
14184
  ];
14122
14185
  }
14123
- var import_node_fs35, import_node_os13, import_node_path37, import_smol_toml2;
14186
+ var import_node_fs35, import_node_os14, import_node_path37, import_smol_toml2;
14124
14187
  var init_orch_mcp_isolation = __esm({
14125
14188
  "src/agents/orch-mcp-isolation.ts"() {
14126
14189
  "use strict";
14127
14190
  import_node_fs35 = require("fs");
14128
- import_node_os13 = require("os");
14191
+ import_node_os14 = require("os");
14129
14192
  import_node_path37 = require("path");
14130
14193
  import_smol_toml2 = require("smol-toml");
14131
14194
  init_user_mcp_config();
@@ -14719,10 +14782,10 @@ function eventsFromClaudeSystem(obj) {
14719
14782
  if (subtype === "api_retry") {
14720
14783
  const attempt = obj.attempt;
14721
14784
  const max = obj.max_retries;
14722
- const delay2 = obj.retry_delay_ms;
14785
+ const delay3 = obj.retry_delay_ms;
14723
14786
  return {
14724
14787
  type: "thinking",
14725
- data: `API retry ${attempt ?? "?"}/${max ?? "?"}${typeof delay2 === "number" ? ` (wait ${delay2}ms)` : ""}`
14788
+ data: `API retry ${attempt ?? "?"}/${max ?? "?"}${typeof delay3 === "number" ? ` (wait ${delay3}ms)` : ""}`
14726
14789
  };
14727
14790
  }
14728
14791
  if (subtype === "status") {
@@ -15145,8 +15208,8 @@ function usageFromCodex(usage) {
15145
15208
  }
15146
15209
  function codexConfigHasNetworkAccess() {
15147
15210
  const candidates = [
15148
- (0, import_node_path40.join)((0, import_node_os14.homedir)(), ".codex", "config.toml"),
15149
- (0, import_node_path40.join)((0, import_node_os14.homedir)(), ".config", "codex", "config.toml")
15211
+ (0, import_node_path40.join)((0, import_node_os15.homedir)(), ".codex", "config.toml"),
15212
+ (0, import_node_path40.join)((0, import_node_os15.homedir)(), ".config", "codex", "config.toml")
15150
15213
  ];
15151
15214
  for (const path2 of candidates) {
15152
15215
  if (!(0, import_node_fs39.existsSync)(path2)) continue;
@@ -15182,7 +15245,7 @@ function asRecord3(value) {
15182
15245
  return void 0;
15183
15246
  }
15184
15247
  function codexLooksAuthenticated() {
15185
- const authPath = (0, import_node_path40.join)((0, import_node_os14.homedir)(), ".codex", "auth.json");
15248
+ const authPath = (0, import_node_path40.join)((0, import_node_os15.homedir)(), ".codex", "auth.json");
15186
15249
  if (!(0, import_node_fs39.existsSync)(authPath)) return false;
15187
15250
  try {
15188
15251
  return (0, import_node_fs39.statSync)(authPath).size > 2;
@@ -15190,12 +15253,12 @@ function codexLooksAuthenticated() {
15190
15253
  return false;
15191
15254
  }
15192
15255
  }
15193
- var import_node_fs39, import_node_os14, import_node_path40, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
15256
+ var import_node_fs39, import_node_os15, import_node_path40, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
15194
15257
  var init_codex = __esm({
15195
15258
  "src/agents/codex.ts"() {
15196
15259
  "use strict";
15197
15260
  import_node_fs39 = require("fs");
15198
- import_node_os14 = require("os");
15261
+ import_node_os15 = require("os");
15199
15262
  import_node_path40 = require("path");
15200
15263
  init_run();
15201
15264
  init_app_settings();
@@ -17091,7 +17154,7 @@ function accessTokenFromCredentialsJson(raw) {
17091
17154
  }
17092
17155
  }
17093
17156
  function claudeCredentialsPath(configDir) {
17094
- const root = configDir?.trim() || process.env.CLAUDE_CONFIG_DIR?.trim() || (0, import_node_path45.join)((0, import_node_os15.homedir)(), ".claude");
17157
+ const root = configDir?.trim() || process.env.CLAUDE_CONFIG_DIR?.trim() || (0, import_node_path45.join)((0, import_node_os16.homedir)(), ".claude");
17095
17158
  return (0, import_node_path45.join)(root, ".credentials.json");
17096
17159
  }
17097
17160
  async function readFileAccessToken(configDir) {
@@ -17209,12 +17272,12 @@ async function getClaudePlanUsage(opts = {}) {
17209
17272
  })();
17210
17273
  return inflight;
17211
17274
  }
17212
- var import_node_fs45, import_node_os15, import_node_path45, CLAUDE_OAUTH_USAGE_URL, CLAUDE_USAGE_TTL_MS, CLAUDE_USAGE_ERROR_TTL_MS, CLAUDE_USAGE_STALE_OK_MS, KEYCHAIN_SERVICES, cache, errorUntil, inflight, lastGood, claudeVersion, cacheDirKey;
17275
+ var import_node_fs45, import_node_os16, import_node_path45, CLAUDE_OAUTH_USAGE_URL, CLAUDE_USAGE_TTL_MS, CLAUDE_USAGE_ERROR_TTL_MS, CLAUDE_USAGE_STALE_OK_MS, KEYCHAIN_SERVICES, cache, errorUntil, inflight, lastGood, claudeVersion, cacheDirKey;
17213
17276
  var init_claude_usage_client = __esm({
17214
17277
  "src/agents/claude-usage-client.ts"() {
17215
17278
  "use strict";
17216
17279
  import_node_fs45 = require("fs");
17217
- import_node_os15 = require("os");
17280
+ import_node_os16 = require("os");
17218
17281
  import_node_path45 = require("path");
17219
17282
  init_run();
17220
17283
  init_fetch();
@@ -24049,7 +24112,7 @@ function listConductorWorkspaces() {
24049
24112
  if (!(0, import_node_fs57.existsSync)(CONDUCTOR_DB)) {
24050
24113
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
24051
24114
  }
24052
- const tmp = (0, import_node_fs57.mkdtempSync)((0, import_node_path55.join)((0, import_node_os16.tmpdir)(), "sideboard-conductor-"));
24115
+ const tmp = (0, import_node_fs57.mkdtempSync)((0, import_node_path55.join)((0, import_node_os17.tmpdir)(), "sideboard-conductor-"));
24053
24116
  const snapshot = (0, import_node_path55.join)(tmp, "conductor.db");
24054
24117
  try {
24055
24118
  (0, import_node_fs57.copyFileSync)(CONDUCTOR_DB, snapshot);
@@ -24140,7 +24203,7 @@ function importConductorWorkspace(workspaceId) {
24140
24203
  if (!(0, import_node_fs57.existsSync)(CONDUCTOR_DB)) {
24141
24204
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
24142
24205
  }
24143
- const tmp = (0, import_node_fs57.mkdtempSync)((0, import_node_path55.join)((0, import_node_os16.tmpdir)(), "sideboard-conductor-"));
24206
+ const tmp = (0, import_node_fs57.mkdtempSync)((0, import_node_path55.join)((0, import_node_os17.tmpdir)(), "sideboard-conductor-"));
24144
24207
  const snapshot = (0, import_node_path55.join)(tmp, "conductor.db");
24145
24208
  try {
24146
24209
  (0, import_node_fs57.copyFileSync)(CONDUCTOR_DB, snapshot);
@@ -24235,13 +24298,13 @@ function importConductorWorkspace(workspaceId) {
24235
24298
  async function importConductorWorkspaceAsync(workspaceId) {
24236
24299
  return importConductorWorkspace(workspaceId);
24237
24300
  }
24238
- var import_node_child_process6, import_node_fs57, import_node_os16, import_node_path55, import_node_module6, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
24301
+ var import_node_child_process6, import_node_fs57, import_node_os17, import_node_path55, import_node_module6, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
24239
24302
  var init_adopt = __esm({
24240
24303
  "src/threads/adopt.ts"() {
24241
24304
  "use strict";
24242
24305
  import_node_child_process6 = require("child_process");
24243
24306
  import_node_fs57 = require("fs");
24244
- import_node_os16 = require("os");
24307
+ import_node_os17 = require("os");
24245
24308
  import_node_path55 = require("path");
24246
24309
  import_node_module6 = require("module");
24247
24310
  init_worktree();
@@ -25803,7 +25866,7 @@ function scanClaudePluginSkills(pluginsRoot, out) {
25803
25866
  walk(pluginsRoot, 0, false);
25804
25867
  }
25805
25868
  function discoverSkills(worktreePath) {
25806
- const home = (0, import_node_os17.homedir)();
25869
+ const home = (0, import_node_os18.homedir)();
25807
25870
  const collected = [];
25808
25871
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
25809
25872
  scanSkillsDir((0, import_node_path58.join)(worktreePath, rel), "workspace", collected);
@@ -25856,12 +25919,12 @@ function readSkillBody(skillPath, maxChars = 12e3) {
25856
25919
 
25857
25920
  \u2026(truncated)` : raw;
25858
25921
  }
25859
- var import_node_fs61, import_node_os17, import_node_path58, BUNDLED_SKILL_PREFIX;
25922
+ var import_node_fs61, import_node_os18, import_node_path58, BUNDLED_SKILL_PREFIX;
25860
25923
  var init_discover = __esm({
25861
25924
  "src/skills/discover.ts"() {
25862
25925
  "use strict";
25863
25926
  import_node_fs61 = require("fs");
25864
- import_node_os17 = require("os");
25927
+ import_node_os18 = require("os");
25865
25928
  import_node_path58 = require("path");
25866
25929
  init_long_running();
25867
25930
  BUNDLED_SKILL_PREFIX = "bundled:";
@@ -27744,8 +27807,8 @@ var init_orchestrator = __esm({
27744
27807
  scheduleQuotaResume(threadId, resumeAt) {
27745
27808
  this.clearQuotaResumeTimer(threadId);
27746
27809
  updateThread(threadId, { quotaResumeAt: resumeAt.toISOString() });
27747
- const delay2 = Math.max(5e3, resumeAt.getTime() - Date.now());
27748
- const capped = Math.min(delay2, 2147483647);
27810
+ const delay3 = Math.max(5e3, resumeAt.getTime() - Date.now());
27811
+ const capped = Math.min(delay3, 2147483647);
27749
27812
  const timer = setTimeout(() => {
27750
27813
  this.quotaResumeTimers.delete(threadId);
27751
27814
  void this.resumeAfterQuotaWait(threadId);
@@ -28030,10 +28093,10 @@ var init_orchestrator = __esm({
28030
28093
  }
28031
28094
  async removeWorkspace(repoPath) {
28032
28095
  removeWorkspace(repoPath);
28033
- for (const thread of listThreads()) {
28034
- if (!sameWorkspacePath(thread.repoPath, repoPath)) continue;
28035
- await this.archive(thread.id).catch(() => void 0);
28036
- }
28096
+ await archiveRemovedWorkspaceChats(
28097
+ listThreads().filter((thread) => archivesWithRemovedWorkspace(thread.repoPath, repoPath)),
28098
+ (id) => this.archive(id)
28099
+ );
28037
28100
  }
28038
28101
  async adopt(input) {
28039
28102
  const thread = await adoptThread(input);
@@ -30186,14 +30249,14 @@ function armOne(schedule) {
30186
30249
  if (!schedule.enabled) return;
30187
30250
  const at = new Date(schedule.nextRunAt);
30188
30251
  if (Number.isNaN(at.getTime())) return;
30189
- const delay2 = Math.max(0, at.getTime() - Date.now());
30190
- if (delay2 <= 250) {
30252
+ const delay3 = Math.max(0, at.getTime() - Date.now());
30253
+ if (delay3 <= 250) {
30191
30254
  void fireSchedule(schedule.id).then(() => {
30192
30255
  if (isThisProcessDesktopHost()) armSchedules();
30193
30256
  });
30194
30257
  return;
30195
30258
  }
30196
- const capped = Math.min(delay2, SET_TIMEOUT_MAX);
30259
+ const capped = Math.min(delay3, SET_TIMEOUT_MAX);
30197
30260
  const timer = setTimeout(() => {
30198
30261
  timers.delete(schedule.id);
30199
30262
  const live = getSchedule(schedule.id);
@@ -30442,6 +30505,8 @@ __export(index_exports, {
30442
30505
  applyThreadIntoMain: () => applyThreadIntoMain,
30443
30506
  applyTurnUsage: () => applyTurnUsage,
30444
30507
  applyWorkspaceTags: () => applyWorkspaceTags,
30508
+ archiveRemovedWorkspaceChats: () => archiveRemovedWorkspaceChats,
30509
+ archivesWithRemovedWorkspace: () => archivesWithRemovedWorkspace,
30445
30510
  armSchedules: () => armSchedules,
30446
30511
  assertAbleTimeCredential: () => assertAbleTimeCredential,
30447
30512
  assertAbleTimeMcpCredential: () => assertAbleTimeMcpCredential,
@@ -39738,10 +39803,7 @@ var import_ws5 = require("ws");
39738
39803
  init_orchestrator_capable();
39739
39804
  init_stage_files();
39740
39805
  init_orchestrator();
39741
- init_ask_user();
39742
39806
  init_app_settings();
39743
- init_global_workspace();
39744
- init_thread_store();
39745
39807
  init_implied_first_prompt();
39746
39808
 
39747
39809
  // src/remote/phone-media.ts
@@ -40720,7 +40782,13 @@ function deliverPhoneTurn(opts, chatId) {
40720
40782
  });
40721
40783
  }
40722
40784
 
40723
- // src/remote/listen.ts
40785
+ // src/remote/phone-turn.ts
40786
+ init_orchestrator_capable();
40787
+ init_orchestrator();
40788
+ init_ask_user();
40789
+ init_app_settings();
40790
+ init_global_workspace();
40791
+ init_thread_store();
40724
40792
  function formatRemotePrompt(text7) {
40725
40793
  return `Phone
40726
40794
 
@@ -40729,6 +40797,29 @@ ${text7.trim()}`;
40729
40797
  function isRemoteStopCommand(text7) {
40730
40798
  return text7.trim().toLowerCase() === "stop";
40731
40799
  }
40800
+ function phoneFollowUpQueues(status) {
40801
+ return followUpBehavior() === "queue" && (status === "running" || status === "queued");
40802
+ }
40803
+ var PHONE_TURN_MS = 14 * 60 * 1e3;
40804
+ function delay2(ms) {
40805
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
40806
+ }
40807
+ async function waitForPhoneTurn(threadId, stillCurrent) {
40808
+ const deadline = Date.now() + PHONE_TURN_MS;
40809
+ while (stillCurrent() && Date.now() < deadline) {
40810
+ const thread2 = readPhoneThread(threadId) ?? readThread(threadId);
40811
+ if (!thread2) return;
40812
+ if (thread2.status === "stopped" && thread2.queue.length > 0) {
40813
+ await delay2(40);
40814
+ continue;
40815
+ }
40816
+ break;
40817
+ }
40818
+ if (!stillCurrent()) return;
40819
+ const thread = readPhoneThread(threadId) ?? readThread(threadId);
40820
+ if (!thread || thread.status !== "running" && thread.status !== "queued") return;
40821
+ await getOrchestrator().waitForTurn(threadId, Math.max(1, deadline - Date.now()));
40822
+ }
40732
40823
  var handleChain2 = Promise.resolve();
40733
40824
  var inboundGeneration = 0;
40734
40825
  function enqueue(fn) {
@@ -40752,6 +40843,77 @@ function interruptRemoteCoordinator(deviceId, log = () => void 0) {
40752
40843
  return false;
40753
40844
  }
40754
40845
  }
40846
+ function runCoordinatorPrompt(opts, body, generation) {
40847
+ const current = () => generation === inboundGeneration;
40848
+ return (async () => {
40849
+ if (!current()) return;
40850
+ const agent = coerceOrchestratorAgent(opts.agent ?? resolveOrchestratorDefaults().agent);
40851
+ if (!body) return;
40852
+ if (isRemoteStopCommand(body)) {
40853
+ if (!current()) return;
40854
+ opts.onOutbound({ type: "assistant", text: REMOTE_STOPPED_REPLY });
40855
+ return;
40856
+ }
40857
+ let thread = ensureRemoteCoordinator(opts.deviceId, agent);
40858
+ thread = readThread(thread.id) ?? thread;
40859
+ const followUp = followUpBehavior();
40860
+ const orch = getOrchestrator();
40861
+ try {
40862
+ await orch.send(thread.id, formatRemotePrompt(body), { followUp });
40863
+ if (!current()) return;
40864
+ await waitForPhoneTurn(thread.id, current);
40865
+ } catch (err) {
40866
+ if (!current()) return;
40867
+ const message = err instanceof Error ? err.message : String(err);
40868
+ opts.onOutbound({ type: "assistant", text: `Sideboard failed: ${message}` });
40869
+ return;
40870
+ }
40871
+ if (!current()) return;
40872
+ thread = readThread(thread.id) ?? thread;
40873
+ if (thread.status === "stopped") return;
40874
+ const result = orch.getTurnResult(thread.id);
40875
+ const pending = extractPendingPlanQuestions(
40876
+ [...thread.messages].reverse().find((m) => m.role === "agent")?.parts
40877
+ );
40878
+ if (result.taskState === "input-required" && pending) {
40879
+ opts.onOutbound({
40880
+ type: "ask_user",
40881
+ text: result.text.trim(),
40882
+ questions: pending.questions.map((q) => ({
40883
+ question: q.question,
40884
+ options: q.options.map(
40885
+ (o) => o.description ? { label: o.label, description: o.description } : { label: o.label }
40886
+ )
40887
+ }))
40888
+ });
40889
+ return;
40890
+ }
40891
+ const reply = outboundReplyFromTurn(result, {
40892
+ inputRequired: "Sideboard is waiting for an answer.",
40893
+ canceled: REMOTE_STOPPED_REPLY,
40894
+ completedEmpty: () => "",
40895
+ failed: (detail) => detail ? `Sideboard failed: ${detail}` : "Sideboard failed before producing a result."
40896
+ });
40897
+ if (reply.trim()) opts.onOutbound({ type: "assistant", text: reply.trim() });
40898
+ })();
40899
+ }
40900
+ function beginCoordinatorPrompt(body, opts) {
40901
+ const live = body ? findRemoteCoordinator(opts.deviceId) : null;
40902
+ const fresh = live ? readThread(live.id) ?? live : null;
40903
+ if (body && !isRemoteStopCommand(body) && phoneFollowUpQueues(fresh?.status)) {
40904
+ const generation2 = inboundGeneration;
40905
+ enqueue(() => runCoordinatorPrompt(opts, body, generation2));
40906
+ return;
40907
+ }
40908
+ const generation = ++inboundGeneration;
40909
+ if (body && isRemoteStopCommand(body)) {
40910
+ interruptRemoteCoordinator(opts.deviceId, opts.onLog ?? (() => void 0));
40911
+ }
40912
+ const task = runCoordinatorPrompt(opts, body, generation);
40913
+ enqueue(() => task);
40914
+ }
40915
+
40916
+ // src/remote/listen.ts
40755
40917
  function emitOpened(opts, opened) {
40756
40918
  setPhoneOpenChat(opened.chat.id);
40757
40919
  emitControl(opts, { op: "opened", ...opened });
@@ -41021,23 +41183,27 @@ function handlePhoneControl(cmd, opts) {
41021
41183
  return;
41022
41184
  }
41023
41185
  const chatId = cmd.chatId;
41186
+ const existing = readPhoneThread(chatId);
41187
+ if (phoneFollowUpQueues(existing?.status)) {
41188
+ deliverPhoneTurn(opts, chatId);
41189
+ const generation2 = chatGeneration.get(chatId) ?? bumpChat(chatId);
41190
+ enqueueChat(chatId, () => runPhonePrompt(opts, cmd, chatId, generation2));
41191
+ return;
41192
+ }
41024
41193
  const generation = bumpChat(chatId);
41025
41194
  phoneTurnGen.set(chatId, generation);
41026
- interruptChat(chatId, log);
41027
- enqueueChat(chatId, async () => {
41028
- if (chatGeneration.get(chatId) !== generation) return;
41195
+ const task = runPhonePrompt(opts, cmd, chatId, generation);
41196
+ enqueueChat(chatId, () => task);
41197
+ }
41198
+ function runPhonePrompt(opts, cmd, chatId, generation) {
41199
+ const current = () => chatGeneration.get(chatId) === generation;
41200
+ return (async () => {
41201
+ if (!current()) return;
41029
41202
  const thread = readPhoneThread(chatId);
41030
41203
  if (!thread) {
41031
41204
  emitControl(opts, { op: "error", chatId, message: "That agent is not on this Mac." });
41032
41205
  return;
41033
41206
  }
41034
- if (thread.status === "running" || thread.status === "queued") {
41035
- try {
41036
- getOrchestrator().stop(thread.id, { clearQueue: true });
41037
- } catch {
41038
- }
41039
- }
41040
- if (chatGeneration.get(chatId) !== generation) return;
41041
41207
  const stopStream = watchPhoneStream(opts, chatId, thread.id, generation);
41042
41208
  try {
41043
41209
  try {
@@ -41045,14 +41211,19 @@ function handlePhoneControl(cmd, opts) {
41045
41211
  } catch (err) {
41046
41212
  emitControl(opts, { op: "error", chatId, message: phoneError(err) });
41047
41213
  }
41214
+ if (!current()) return;
41048
41215
  const live = readPhoneThread(thread.id) ?? thread;
41216
+ const followUp = followUpBehavior();
41049
41217
  const staged = stagePhoneTurnFiles(live.worktreePath, cmd);
41050
41218
  const text7 = cmd.text.trim() || (staged.length ? "See the attached files." : "");
41051
- const formatted = formatRemotePrompt(text7);
41052
- await getOrchestrator().send(thread.id, formatted, { attachments: staged });
41053
- await getOrchestrator().waitForTurn(thread.id, 14 * 60 * 1e3);
41219
+ await getOrchestrator().send(thread.id, formatRemotePrompt(text7), {
41220
+ attachments: staged,
41221
+ followUp
41222
+ });
41223
+ if (!current()) return;
41224
+ await waitForPhoneTurn(thread.id, current);
41054
41225
  } catch (err) {
41055
- if (chatGeneration.get(chatId) !== generation) return;
41226
+ if (!current()) return;
41056
41227
  const message = err instanceof Error ? err.message : String(err);
41057
41228
  emitControl(opts, { op: "error", chatId, message: `Sideboard failed: ${message}` });
41058
41229
  return;
@@ -41060,12 +41231,11 @@ function handlePhoneControl(cmd, opts) {
41060
41231
  stopStream();
41061
41232
  finishPhoneTurn(chatId, generation);
41062
41233
  }
41063
- if (chatGeneration.get(chatId) !== generation) return;
41234
+ if (!current()) return;
41064
41235
  emitChatTurn(opts, chatId, thread.id);
41065
- });
41236
+ })();
41066
41237
  }
41067
41238
  function handleRemoteInbound(text7, opts) {
41068
- const log = opts.onLog ?? (() => void 0);
41069
41239
  const body = text7.trim();
41070
41240
  const control = takePhoneControl(body);
41071
41241
  if (control) {
@@ -41076,64 +41246,7 @@ function handleRemoteInbound(text7, opts) {
41076
41246
  handlePhoneControl(control, opts);
41077
41247
  return;
41078
41248
  }
41079
- const generation = ++inboundGeneration;
41080
- if (body) interruptRemoteCoordinator(opts.deviceId, log);
41081
- enqueue(async () => {
41082
- if (generation !== inboundGeneration) return;
41083
- const agent = coerceOrchestratorAgent(opts.agent ?? resolveOrchestratorDefaults().agent);
41084
- if (!body) return;
41085
- if (isRemoteStopCommand(body)) {
41086
- if (generation !== inboundGeneration) return;
41087
- opts.onOutbound({ type: "assistant", text: REMOTE_STOPPED_REPLY });
41088
- return;
41089
- }
41090
- let thread = ensureRemoteCoordinator(opts.deviceId, agent);
41091
- const fresh = readThread(thread.id) ?? thread;
41092
- if (fresh.status === "running" || fresh.status === "queued") {
41093
- try {
41094
- getOrchestrator().stop(fresh.id, { clearQueue: true });
41095
- } catch {
41096
- }
41097
- }
41098
- if (generation !== inboundGeneration) return;
41099
- const orch = getOrchestrator();
41100
- try {
41101
- await orch.send(thread.id, formatRemotePrompt(body));
41102
- await orch.waitForTurn(thread.id, 14 * 60 * 1e3);
41103
- } catch (err) {
41104
- if (generation !== inboundGeneration) return;
41105
- const message = err instanceof Error ? err.message : String(err);
41106
- opts.onOutbound({ type: "assistant", text: `Sideboard failed: ${message}` });
41107
- return;
41108
- }
41109
- if (generation !== inboundGeneration) return;
41110
- thread = readThread(thread.id) ?? thread;
41111
- if (thread.status === "stopped") return;
41112
- const result = orch.getTurnResult(thread.id);
41113
- const pending = extractPendingPlanQuestions(
41114
- [...thread.messages].reverse().find((m) => m.role === "agent")?.parts
41115
- );
41116
- if (result.taskState === "input-required" && pending) {
41117
- opts.onOutbound({
41118
- type: "ask_user",
41119
- text: result.text.trim(),
41120
- questions: pending.questions.map((q) => ({
41121
- question: q.question,
41122
- options: q.options.map(
41123
- (o) => o.description ? { label: o.label, description: o.description } : { label: o.label }
41124
- )
41125
- }))
41126
- });
41127
- return;
41128
- }
41129
- const reply = outboundReplyFromTurn(result, {
41130
- inputRequired: "Sideboard is waiting for an answer.",
41131
- canceled: REMOTE_STOPPED_REPLY,
41132
- completedEmpty: () => "",
41133
- failed: (detail) => detail ? `Sideboard failed: ${detail}` : "Sideboard failed before producing a result."
41134
- });
41135
- if (reply.trim()) opts.onOutbound({ type: "assistant", text: reply.trim() });
41136
- });
41249
+ beginCoordinatorPrompt(body, opts);
41137
41250
  }
41138
41251
 
41139
41252
  // src/remote/phone-board-sync.ts
@@ -41473,6 +41586,7 @@ function runRemoteHost(opts) {
41473
41586
 
41474
41587
  // src/relay/account-login.ts
41475
41588
  var import_node_crypto28 = require("crypto");
41589
+ init_fetch();
41476
41590
 
41477
41591
  // src/relay/accounts.ts
41478
41592
  var import_node_crypto27 = require("crypto");
@@ -42073,15 +42187,43 @@ function sleep2(ms, signal) {
42073
42187
  signal?.addEventListener("abort", onAbort, { once: true });
42074
42188
  });
42075
42189
  }
42190
+ 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.";
42191
+ 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.";
42192
+ 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;
42193
+ function relayFetchError(err, url) {
42194
+ const formatted = formatFetchError(err, url, { tlsHint: RELAY_TLS_HINT });
42195
+ if (formatted.includes(RELAY_TLS_HINT) || !RELAY_NETWORK_RE.test(formatted)) {
42196
+ return new Error(formatted);
42197
+ }
42198
+ return new Error(`${formatted}${RELAY_NETWORK_HINT}`);
42199
+ }
42200
+ async function relayFetch(fetchImpl, url, init) {
42201
+ const fn = fetchImpl ?? currentHttpFetch();
42202
+ try {
42203
+ return await fn(url, init);
42204
+ } catch (err) {
42205
+ throw relayFetchError(err, url);
42206
+ }
42207
+ }
42208
+ async function readJson3(res, url) {
42209
+ try {
42210
+ return await res.json();
42211
+ } catch {
42212
+ const kind = (res.headers.get("content-type") ?? "").includes("html") ? "an HTML page" : "a non-JSON body";
42213
+ throw new Error(
42214
+ `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.`
42215
+ );
42216
+ }
42217
+ }
42076
42218
  async function startRemoteAccountLogin(opts) {
42077
42219
  if (opts.signal?.aborted) throw new RemoteAccountLoginCancelled();
42078
42220
  const origin = (opts.origin ?? remoteAccountHttpOrigin()).replace(/\/+$/, "");
42079
- const fetchImpl = opts.fetchImpl ?? fetch;
42080
42221
  const state = (0, import_node_crypto28.randomBytes)(16).toString("hex");
42081
42222
  const timeoutMs = opts.timeoutMs ?? 5 * 6e4;
42082
42223
  const pollIntervalMs = opts.pollIntervalMs ?? 400;
42083
42224
  const linkToken = opts.linkToken?.trim() ?? "";
42084
- const started = await fetchImpl(`${origin}${REMOTE_LOGIN_PATH}`, {
42225
+ const startUrl = `${origin}${REMOTE_LOGIN_PATH}`;
42226
+ const started = await relayFetch(opts.fetchImpl, startUrl, {
42085
42227
  method: "POST",
42086
42228
  headers: { "Content-Type": "application/json" },
42087
42229
  body: JSON.stringify({
@@ -42090,9 +42232,9 @@ async function startRemoteAccountLogin(opts) {
42090
42232
  ...linkToken ? { accountToken: linkToken } : {}
42091
42233
  })
42092
42234
  });
42093
- const startBody = await started.json();
42235
+ const startBody = await readJson3(started, startUrl);
42094
42236
  if (!started.ok || !startBody.url) {
42095
- throw new Error(startBody.error || "Could not start sign-in.");
42237
+ throw new Error(startBody.error || `Could not start sign-in (HTTP ${started.status}).`);
42096
42238
  }
42097
42239
  await Promise.resolve(opts.openUrl?.(startBody.url));
42098
42240
  const deadline = Date.now() + timeoutMs;
@@ -42101,9 +42243,11 @@ async function startRemoteAccountLogin(opts) {
42101
42243
  if (opts.signal?.aborted) throw new RemoteAccountLoginCancelled();
42102
42244
  let res;
42103
42245
  try {
42104
- res = await fetchImpl(resultUrl);
42105
- } catch {
42106
- if (opts.signal?.aborted) throw new RemoteAccountLoginCancelled();
42246
+ res = await relayFetch(opts.fetchImpl, resultUrl);
42247
+ } catch (err) {
42248
+ if (opts.signal?.aborted || isRemoteAccountLoginCancelled(err)) {
42249
+ throw new RemoteAccountLoginCancelled();
42250
+ }
42107
42251
  await sleep2(pollIntervalMs, opts.signal);
42108
42252
  continue;
42109
42253
  }
@@ -42128,8 +42272,7 @@ async function startRemoteAccountLogin(opts) {
42128
42272
  }
42129
42273
  async function disconnectRemoteAccount(opts) {
42130
42274
  const origin = (opts.origin ?? remoteAccountHttpOrigin()).replace(/\/+$/, "");
42131
- const fetchImpl = opts.fetchImpl ?? fetch;
42132
- await fetchImpl(`${origin}${REMOTE_LOGOUT_PATH}`, {
42275
+ await relayFetch(opts.fetchImpl, `${origin}${REMOTE_LOGOUT_PATH}`, {
42133
42276
  method: "POST",
42134
42277
  headers: { "Content-Type": "application/json" },
42135
42278
  body: JSON.stringify({ accountToken: opts.accountToken })
@@ -43487,6 +43630,8 @@ async function pollSlackOutboundWatches(opts) {
43487
43630
  applyThreadIntoMain,
43488
43631
  applyTurnUsage,
43489
43632
  applyWorkspaceTags,
43633
+ archiveRemovedWorkspaceChats,
43634
+ archivesWithRemovedWorkspace,
43490
43635
  armSchedules,
43491
43636
  assertAbleTimeCredential,
43492
43637
  assertAbleTimeMcpCredential,