@sideboard-ai/core 0.1.324 → 0.1.325

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 (83) hide show
  1. package/dist/{abletime-5ZY3ZUUO.js → abletime-M7STTMZT.js} +6 -5
  2. package/dist/{abletime-CU2UPMJF.js → abletime-VL234MCP.js} +5 -4
  3. package/dist/{abletime-oauth-7EOSBEFM.js → abletime-oauth-LMMGMAPA.js} +3 -3
  4. package/dist/{abletime-oauth-4TTCR3CT.js → abletime-oauth-P4ZFBEAL.js} +3 -3
  5. package/dist/{abletime-rest-3TG4G7LW.js → abletime-rest-DLV7EIWS.js} +3 -3
  6. package/dist/{abletime-rest-KOKE7V4B.js → abletime-rest-GOI7HELR.js} +3 -3
  7. package/dist/agents/claude-runner.cjs +59 -22
  8. package/dist/agents/claude-runner.js +39 -16
  9. package/dist/agents/cursor-runner.cjs +96 -31
  10. package/dist/agents/cursor-runner.js +74 -24
  11. package/dist/{agents-YK65UDLT.js → agents-LDRM3BTY.js} +9 -8
  12. package/dist/{agents-LUSTCMDN.js → agents-MBIEAETM.js} +12 -11
  13. package/dist/{app-settings-I5HM5RMP.js → app-settings-E7DMMEKC.js} +1 -1
  14. package/dist/{app-settings-XIF4EC4K.js → app-settings-UQHUNOLV.js} +1 -1
  15. package/dist/{chunk-INBUV7HY.js → chunk-2UP3XD2D.js} +2 -2
  16. package/dist/{chunk-EQ52JR3Q.js → chunk-5MXLDDYF.js} +1 -1
  17. package/dist/{chunk-NCHOTN3C.js → chunk-5YCKATG6.js} +4 -3
  18. package/dist/{chunk-BYUCNIXK.js → chunk-7G27TB4M.js} +6 -6
  19. package/dist/chunk-7LUOLYFM.js +1445 -0
  20. package/dist/{chunk-Y3WREIPQ.js → chunk-A76MKMSF.js} +12 -210
  21. package/dist/{chunk-JE3JLHMO.js → chunk-APKUI4BP.js} +3 -3
  22. package/dist/{chunk-FR3SAYUL.js → chunk-AQEKPJWU.js} +5 -5
  23. package/dist/{chunk-QOS4465Y.js → chunk-BOFYI6LC.js} +1 -1
  24. package/dist/{chunk-FUFNMUNR.js → chunk-BTF3ATST.js} +7 -8
  25. package/dist/{chunk-OIHRC2ZJ.js → chunk-CI4M54LS.js} +22 -2
  26. package/dist/chunk-DBKHL7NC.js +214 -0
  27. package/dist/{chunk-ROOZDDFA.js → chunk-EO6ZFLG6.js} +7 -8
  28. package/dist/chunk-EZR6W4B3.js +1259 -0
  29. package/dist/{chunk-MZIZTSR2.js → chunk-F65JMKUR.js} +2 -2
  30. package/dist/chunk-F6GE7V3Q.js +216 -0
  31. package/dist/{chunk-7MQSYPAY.js → chunk-GNLKBS3U.js} +206 -188
  32. package/dist/{chunk-EKU7FQVG.js → chunk-H36GKGU2.js} +2 -2
  33. package/dist/{chunk-7D5QIU3N.js → chunk-HG6KS7OT.js} +294 -265
  34. package/dist/chunk-MBT6WDAB.js +28 -0
  35. package/dist/{chunk-JH5SMVM5.js → chunk-MFMDZAA6.js} +262 -233
  36. package/dist/{chunk-7PVT73H6.js → chunk-NWGINMEA.js} +12 -210
  37. package/dist/{chunk-QIC2JXHW.js → chunk-OOXRMTU6.js} +1 -1
  38. package/dist/{chunk-5XNT6BCG.js → chunk-OPXEJJBM.js} +1 -1
  39. package/dist/chunk-OYRN356W.js +80 -0
  40. package/dist/chunk-PPTJMBUY.js +25 -0
  41. package/dist/{chunk-B4CDSSRN.js → chunk-Q3FHTGIW.js} +2 -0
  42. package/dist/{chunk-EJ66LEKH.js → chunk-RZJTGBXY.js} +22 -2
  43. package/dist/{chunk-DF5BM5OY.js → chunk-SACHHTBJ.js} +207 -186
  44. package/dist/{chunk-5GDJSFCT.js → chunk-SK6NYGPD.js} +2 -2
  45. package/dist/{chunk-74OPNF7U.js → chunk-SQQBU7Z6.js} +2 -2
  46. package/dist/{chunk-Q3YJZPQI.js → chunk-SS6CYGLF.js} +3 -3
  47. package/dist/{chunk-YDUHLWI5.js → chunk-SUZOPJZC.js} +21 -7
  48. package/dist/{chunk-ZHGMRBSC.js → chunk-U5WO6MEB.js} +3 -3
  49. package/dist/{chunk-NXUN4U5P.js → chunk-VAFQS4D2.js} +2 -2
  50. package/dist/chunk-W3ZLE4PO.js +77 -0
  51. package/dist/{chunk-RR4WCGNB.js → chunk-WYEST76H.js} +7 -7
  52. package/dist/{chunk-ODH3XHMI.js → chunk-ZEUMWHOH.js} +5 -5
  53. package/dist/{chunk-ZIRQZUZY.js → chunk-ZHDXLDLA.js} +3 -3
  54. package/dist/{chunk-IFWGG2M2.js → chunk-ZSHS46V5.js} +2 -0
  55. package/dist/{conductor-JFABMXDA.js → conductor-D4KFZF54.js} +6 -6
  56. package/dist/{conductor-SPZOTC7W.js → conductor-KB7L7NQN.js} +7 -7
  57. package/dist/{coordinator-prompt-K66RGNWK.js → coordinator-prompt-OBXEC63K.js} +4 -4
  58. package/dist/{coordinator-prompt-Z6UFHFDH.js → coordinator-prompt-SUO4FRY3.js} +4 -4
  59. package/dist/{cursor-recover-TEBFKAZ4.js → cursor-recover-7F46PAJ5.js} +1 -1
  60. package/dist/{cursor-recover-OWPQUHFH.js → cursor-recover-BDIAZIE3.js} +1 -1
  61. package/dist/{global-workspace-A6UO6PJV.js → global-workspace-UHU2FXTY.js} +4 -4
  62. package/dist/{global-workspace-RHEO55B4.js → global-workspace-Z2SURNHA.js} +4 -4
  63. package/dist/index.cjs +21112 -20864
  64. package/dist/index.d.cts +25 -9
  65. package/dist/index.d.ts +25 -9
  66. package/dist/index.js +343 -1678
  67. package/dist/linear-HFUOUJ5H.js +67 -0
  68. package/dist/linear-SIHEBU3X.js +69 -0
  69. package/dist/linear-list-63I7QUC6.js +6 -0
  70. package/dist/linear-list-JFV3EES6.js +8 -0
  71. package/dist/mcp/run-stdio.cjs +15654 -15398
  72. package/dist/mcp/run-stdio.js +67 -1247
  73. package/dist/{optional-cli-RMMS5L6F.js → optional-cli-U2GUA2X6.js} +3 -3
  74. package/dist/{optional-cli-Y3Z3GIPZ.js → optional-cli-ULDP3O5S.js} +4 -4
  75. package/dist/{orchestrator-7VTAUY24.js → orchestrator-3H4KNGPN.js} +15 -13
  76. package/dist/{orchestrator-2O6OJQLX.js → orchestrator-6ROMEWBP.js} +14 -12
  77. package/dist/{thread-store-3F7GR64A.js → thread-store-4ZN3DS2W.js} +1 -1
  78. package/dist/{thread-store-JRSL4HQY.js → thread-store-IC4BQXDW.js} +1 -1
  79. package/dist/{workspaces-NRKEXOYR.js → workspaces-MG5JHRKW.js} +4 -4
  80. package/dist/{workspaces-42E6AGXD.js → workspaces-QJNKEGEM.js} +4 -4
  81. package/dist/{worktree-ZDA2UJ7C.js → worktree-KSJPTHGZ.js} +3 -3
  82. package/dist/{worktree-4NGXCCUO.js → worktree-MYJYUHZM.js} +3 -3
  83. package/package.json +1 -1
@@ -1,17 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import {
4
- applyConnectedTeamToCli,
5
- brightsyMcpServerName,
6
- ensureCliTeamTracked,
7
- ensureConnectedBrightsyTeamTokens
8
- } from "./chunk-6U6QRUHY.js";
9
- import {
10
- loadBrightsyConfig
11
- } from "./chunk-E63AM3PW.js";
12
- import {
13
- httpFetch
14
- } from "./chunk-2GPQZZLY.js";
15
3
  import {
16
4
  extractJsonErrorMessage,
17
5
  formatUnknownDetail,
@@ -21,16 +9,31 @@ import {
21
9
  looksLikeSkillBody,
22
10
  skillCommandFromBody,
23
11
  withEventParentId
24
- } from "./chunk-EQ52JR3Q.js";
12
+ } from "./chunk-5MXLDDYF.js";
25
13
  import {
26
14
  isOrchestratorThread
27
- } from "./chunk-ZIRQZUZY.js";
15
+ } from "./chunk-ZHDXLDLA.js";
28
16
  import {
29
17
  codexUnattendedGitConfigArgs,
30
18
  mergeAgentGitAuthEnv,
31
19
  resolveAgentGitAuthEnv,
32
20
  resolveCodexGitWritableRoots
33
- } from "./chunk-ROOZDDFA.js";
21
+ } from "./chunk-EO6ZFLG6.js";
22
+ import {
23
+ applyConnectedTeamToCli,
24
+ brightsyMcpServerName,
25
+ ensureCliTeamTracked,
26
+ ensureConnectedBrightsyTeamTokens
27
+ } from "./chunk-6U6QRUHY.js";
28
+ import {
29
+ loadBrightsyConfig
30
+ } from "./chunk-E63AM3PW.js";
31
+ import {
32
+ httpFetch
33
+ } from "./chunk-2GPQZZLY.js";
34
+ import {
35
+ listAssignedLinearIssues
36
+ } from "./chunk-MBT6WDAB.js";
34
37
  import {
35
38
  githubAgentAuthReady,
36
39
  npmGlobalNodeModules,
@@ -45,7 +48,7 @@ import {
45
48
  loadAppSettings,
46
49
  resolveAgentExecutable,
47
50
  resolveClaudeExecutable
48
- } from "./chunk-OIHRC2ZJ.js";
51
+ } from "./chunk-CI4M54LS.js";
49
52
  import {
50
53
  isElectronLikeCommand,
51
54
  unwrapStrippedElectronLaunch,
@@ -57,7 +60,7 @@ import {
57
60
  CLAUDE_POSTHOG_CONNECTOR_ALLOWED_TOOLS,
58
61
  CLAUDE_PRINT_BG_WAIT_CEILING_MS,
59
62
  mcpAllowToolsFromNames
60
- } from "./chunk-B4CDSSRN.js";
63
+ } from "./chunk-Q3FHTGIW.js";
61
64
  import {
62
65
  appDataDir
63
66
  } from "./chunk-WOU343SI.js";
@@ -448,6 +451,7 @@ var brightsyAdapter = {
448
451
 
449
452
  // src/agents/claude.ts
450
453
  import { existsSync as existsSync11 } from "fs";
454
+ import { dirname as dirname5 } from "path";
451
455
 
452
456
  // src/agents/claude-mcp-status.ts
453
457
  var SIDEBOARD_CONNECTOR_SERVICES = [
@@ -564,7 +568,7 @@ function isNotableMcpInitStatus(server, sideboardOk, coverage) {
564
568
 
565
569
  // src/mcp-ui/host.ts
566
570
  import { createHash } from "crypto";
567
- import { homedir as homedir5 } from "os";
571
+ import { homedir as homedir6 } from "os";
568
572
 
569
573
  // src/agents/orch-mcp-isolation.ts
570
574
  import { existsSync as existsSync8, readFileSync as readFileSync4 } from "fs";
@@ -921,20 +925,20 @@ function readJson(path) {
921
925
  }
922
926
 
923
927
  // src/agents/orch-mcp-isolation.ts
924
- import { homedir as homedir4 } from "os";
925
- import { join as join7 } from "path";
928
+ import { homedir as homedir5 } from "os";
929
+ import { join as join8 } from "path";
926
930
  import { parse as parseToml } from "smol-toml";
927
931
 
928
932
  // src/agents/user-mcp-config.ts
929
- import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
930
- import { homedir as homedir3 } from "os";
931
- import { dirname as dirname3, join as join6 } from "path";
933
+ import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "fs";
934
+ import { homedir as homedir4 } from "os";
935
+ import { dirname as dirname3, join as join7 } from "path";
932
936
 
933
937
  // src/agents/injected-mcp.ts
934
- import { existsSync as existsSync6, mkdtempSync, writeFileSync as writeFileSync2 } from "fs";
938
+ import { existsSync as existsSync6, mkdtempSync, writeFileSync as writeFileSync3 } from "fs";
935
939
  import { createRequire } from "module";
936
940
  import { tmpdir } from "os";
937
- import { dirname as dirname2, join as join5 } from "path";
941
+ import { dirname as dirname2, join as join6 } from "path";
938
942
  import { fileURLToPath } from "url";
939
943
 
940
944
  // src/agent-rpc/protocol.ts
@@ -1401,6 +1405,44 @@ async function resolveNodeLaunch(scriptPath) {
1401
1405
  };
1402
1406
  }
1403
1407
 
1408
+ // src/agents/codex-mcp-profile.ts
1409
+ import { randomBytes } from "crypto";
1410
+ import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
1411
+ import { homedir as homedir3 } from "os";
1412
+ import { join as join5 } from "path";
1413
+ function isCodexSecretEnvKey(key) {
1414
+ return /token|secret|password|credential|oauth|api_key|_key$/i.test(key);
1415
+ }
1416
+ function tomlBasicString(value) {
1417
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r")}"`;
1418
+ }
1419
+ function secretEnv(env) {
1420
+ if (!env) return void 0;
1421
+ const out = { ...env };
1422
+ delete out.ELECTRON_RUN_AS_NODE;
1423
+ return Object.keys(out).length > 0 ? out : void 0;
1424
+ }
1425
+ function writeCodexMcpSecretProfile(servers) {
1426
+ const blocks = [];
1427
+ for (const s of servers) {
1428
+ const env = secretEnv(s.env);
1429
+ if (!env) continue;
1430
+ const secrets = Object.entries(env).filter(([key]) => isCodexSecretEnvKey(key));
1431
+ if (secrets.length === 0) continue;
1432
+ const lines = [`[mcp_servers.${s.name}.env]`];
1433
+ for (const [key, value] of secrets) lines.push(`${key} = ${tomlBasicString(value)}`);
1434
+ blocks.push(lines.join("\n"));
1435
+ }
1436
+ if (blocks.length === 0) return null;
1437
+ const home = process.env.CODEX_HOME?.trim() || join5(homedir3(), ".codex");
1438
+ mkdirSync2(home, { recursive: true, mode: 448 });
1439
+ const profile = `sideboard-${randomBytes(8).toString("hex")}`;
1440
+ const file = join5(home, `${profile}.config.toml`);
1441
+ writeFileSync2(file, `${blocks.join("\n\n")}
1442
+ `, { mode: 384 });
1443
+ return { profile, file };
1444
+ }
1445
+
1404
1446
  // src/agents/injected-mcp.ts
1405
1447
  var SIDEBOARD_MCP_ALLOWED_TOOLS = [
1406
1448
  "mcp__sideboard",
@@ -1536,7 +1578,7 @@ function corePackageDir() {
1536
1578
  } catch {
1537
1579
  }
1538
1580
  try {
1539
- const req = createRequire(join5(process.cwd(), "package.json"));
1581
+ const req = createRequire(join6(process.cwd(), "package.json"));
1540
1582
  return dirname2(req.resolve("@sideboard-ai/core"));
1541
1583
  } catch {
1542
1584
  return process.cwd();
@@ -1550,13 +1592,13 @@ function findSideboardMcpJsEntry() {
1550
1592
  let dir = corePackageDir();
1551
1593
  for (let i = 0; i < 10; i++) {
1552
1594
  const candidates = [
1553
- join5(dir, "mcp/run-stdio.js"),
1554
- join5(dir, "mcp/run-stdio.cjs"),
1555
- join5(dir, "dist/mcp/run-stdio.js"),
1556
- join5(dir, "dist/mcp/run-stdio.cjs"),
1557
- join5(dir, "packages/core/dist/mcp/run-stdio.js"),
1558
- join5(dir, "packages/cli/dist/index.js"),
1559
- join5(dir, "cli/dist/index.js")
1595
+ join6(dir, "mcp/run-stdio.js"),
1596
+ join6(dir, "mcp/run-stdio.cjs"),
1597
+ join6(dir, "dist/mcp/run-stdio.js"),
1598
+ join6(dir, "dist/mcp/run-stdio.cjs"),
1599
+ join6(dir, "packages/core/dist/mcp/run-stdio.js"),
1600
+ join6(dir, "packages/cli/dist/index.js"),
1601
+ join6(dir, "cli/dist/index.js")
1560
1602
  ];
1561
1603
  for (const p of candidates) {
1562
1604
  if (existsSync6(p) && !isAsarPath(p)) return p;
@@ -1664,6 +1706,7 @@ function toCodexMcpConfigArgs(servers) {
1664
1706
  const env = mcpSpawnEnv(s.env);
1665
1707
  if (env) {
1666
1708
  for (const [key, value] of Object.entries(env)) {
1709
+ if (isCodexSecretEnvKey(key)) continue;
1667
1710
  args.push("-c", `${prefix}.env.${key}=${JSON.stringify(value)}`);
1668
1711
  }
1669
1712
  }
@@ -1722,15 +1765,15 @@ function mcpServersRecord(servers, extraServers) {
1722
1765
  function writeMcpServersConfig(servers, extraServers) {
1723
1766
  const mcpServers = mcpServersRecord(servers, extraServers);
1724
1767
  if (Object.keys(mcpServers).length === 0) return null;
1725
- const dir = mkdtempSync(join5(tmpdir(), "sideboard-mcp-"));
1726
- const cfgPath = join5(dir, "mcp.json");
1727
- writeFileSync2(cfgPath, JSON.stringify({ mcpServers }, null, 2));
1768
+ const dir = mkdtempSync(join6(tmpdir(), "sideboard-mcp-"));
1769
+ const cfgPath = join6(dir, "mcp.json");
1770
+ writeFileSync3(cfgPath, JSON.stringify({ mcpServers }, null, 2), { mode: 384 });
1728
1771
  return cfgPath;
1729
1772
  }
1730
1773
 
1731
1774
  // src/agents/user-mcp-config.ts
1732
1775
  function userClaudeMcpConfigPath() {
1733
- return join6(homedir3(), ".claude.json");
1776
+ return join7(homedir4(), ".claude.json");
1734
1777
  }
1735
1778
 
1736
1779
  // src/agents/orch-mcp-isolation.ts
@@ -1767,13 +1810,19 @@ function readText(path) {
1767
1810
  return "";
1768
1811
  }
1769
1812
  }
1770
- function userCodexConfigPaths(home = homedir4()) {
1771
- return [join7(home, ".codex", "config.toml"), join7(home, ".config", "codex", "config.toml")];
1813
+ function userCodexConfigPaths(home = homedir5()) {
1814
+ const paths = [
1815
+ join8(home, ".codex", "config.toml"),
1816
+ join8(home, ".config", "codex", "config.toml")
1817
+ ];
1818
+ const codexHome = process.env.CODEX_HOME?.trim();
1819
+ if (codexHome) paths.unshift(join8(codexHome, "config.toml"));
1820
+ return paths;
1772
1821
  }
1773
- function userOpencodeConfigPaths(home = homedir4()) {
1822
+ function userOpencodeConfigPaths(home = homedir5()) {
1774
1823
  return [
1775
- join7(home, ".config", "opencode", "opencode.json"),
1776
- join7(home, ".config", "opencode", "opencode.jsonc")
1824
+ join8(home, ".config", "opencode", "opencode.json"),
1825
+ join8(home, ".config", "opencode", "opencode.jsonc")
1777
1826
  ];
1778
1827
  }
1779
1828
  function userMcpNamesToDisable(opts) {
@@ -1792,7 +1841,7 @@ function userMcpNamesToDisable(opts) {
1792
1841
  }
1793
1842
  return out;
1794
1843
  }
1795
- function listUserCodexMcpNames(home = homedir4()) {
1844
+ function listUserCodexMcpNames(home = homedir5()) {
1796
1845
  const names = [];
1797
1846
  for (const path of userCodexConfigPaths(home)) {
1798
1847
  if (!existsSync8(path)) continue;
@@ -1800,7 +1849,7 @@ function listUserCodexMcpNames(home = homedir4()) {
1800
1849
  }
1801
1850
  return names;
1802
1851
  }
1803
- function listUserOpencodeMcpNames(home = homedir4()) {
1852
+ function listUserOpencodeMcpNames(home = homedir5()) {
1804
1853
  const names = [];
1805
1854
  for (const path of userOpencodeConfigPaths(home)) {
1806
1855
  if (!existsSync8(path)) continue;
@@ -1808,12 +1857,12 @@ function listUserOpencodeMcpNames(home = homedir4()) {
1808
1857
  }
1809
1858
  return names;
1810
1859
  }
1811
- function userClaudeMcpConfigObject(home = homedir4()) {
1812
- const claudePath = home === homedir4() ? userClaudeMcpConfigPath() : join7(home, ".claude.json");
1860
+ function userClaudeMcpConfigObject(home = homedir5()) {
1861
+ const claudePath = home === homedir5() ? userClaudeMcpConfigPath() : join8(home, ".claude.json");
1813
1862
  if (!existsSync8(claudePath)) return {};
1814
1863
  return asObject(asObject(readJsonObject(claudePath)).mcpServers);
1815
1864
  }
1816
- function listUserClaudeMcpServerEntries(home = homedir4(), projectDirs) {
1865
+ function listUserClaudeMcpServerEntries(home = homedir5(), projectDirs) {
1817
1866
  const out = {};
1818
1867
  for (const [name, entry] of Object.entries(
1819
1868
  listEnabledClaudePluginMcpServers({ home, projectDirs })
@@ -1851,7 +1900,7 @@ function toCodexUnattendedAppsArgs() {
1851
1900
  }
1852
1901
 
1853
1902
  // src/mcp-ui/proxy-http.ts
1854
- import { randomBytes, randomUUID } from "crypto";
1903
+ import { randomBytes as randomBytes2, randomUUID } from "crypto";
1855
1904
  import { createServer } from "http";
1856
1905
  import { Server as Server2 } from "@modelcontextprotocol/sdk/server/index.js";
1857
1906
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
@@ -1948,7 +1997,7 @@ function listedTool(tool) {
1948
1997
 
1949
1998
  // src/mcp-ui/proxy-http.ts
1950
1999
  async function listenMcpUiProxy(opts) {
1951
- const token = randomBytes(24).toString("hex");
2000
+ const token = randomBytes2(24).toString("hex");
1952
2001
  const transports = /* @__PURE__ */ new Map();
1953
2002
  const httpServer = createServer((req, res) => {
1954
2003
  void handle(req, res);
@@ -2321,7 +2370,7 @@ var singleton;
2321
2370
  function getMcpUiHost() {
2322
2371
  if (!singleton) {
2323
2372
  singleton = new McpUiHost({
2324
- entries: (projectDirs) => listUserClaudeMcpServerEntries(homedir5(), projectDirs)
2373
+ entries: (projectDirs) => listUserClaudeMcpServerEntries(homedir6(), projectDirs)
2325
2374
  });
2326
2375
  }
2327
2376
  return singleton;
@@ -2329,7 +2378,7 @@ function getMcpUiHost() {
2329
2378
  async function proxyClaudeUserMcp(orchestrator, projectDirs) {
2330
2379
  if (orchestrator) return {};
2331
2380
  const dirs = projectDirs.filter((d) => typeof d === "string" && d.length > 0);
2332
- return getMcpUiHost().proxyEntries(listUserClaudeMcpServerEntries(homedir5(), dirs), dirs);
2381
+ return getMcpUiHost().proxyEntries(listUserClaudeMcpServerEntries(homedir6(), dirs), dirs);
2333
2382
  }
2334
2383
  function dirsKeyFor(projectDirs) {
2335
2384
  if (!projectDirs?.length) return "";
@@ -2343,16 +2392,6 @@ function planModeTurnInstruction(planMode) {
2343
2392
  return planMode ? PLAN_MODE_INSTRUCTION : PLAN_MODE_OFF_INSTRUCTION;
2344
2393
  }
2345
2394
  function permissionMode(thread) {
2346
- if (thread.sourceType === "orchestration") {
2347
- return {
2348
- claude: "acceptEdits",
2349
- opencodePermission: JSON.stringify({
2350
- edit: "allow",
2351
- bash: { "*": "allow", "rm -rf *": "deny" }
2352
- }),
2353
- codexSandbox: "danger-full-access"
2354
- };
2355
- }
2356
2395
  if (thread.planMode) {
2357
2396
  return {
2358
2397
  claude: "plan",
@@ -2364,6 +2403,18 @@ function permissionMode(thread) {
2364
2403
  codexSandbox: "read-only"
2365
2404
  };
2366
2405
  }
2406
+ if (thread.sourceType === "orchestration") {
2407
+ return {
2408
+ claude: "acceptEdits",
2409
+ // Unattended coordinators cannot answer permission prompts. Explicit
2410
+ // allows override the user's OpenCode denies for this process only.
2411
+ opencodePermission: JSON.stringify({
2412
+ edit: "allow",
2413
+ bash: { "*": "allow" }
2414
+ }),
2415
+ codexSandbox: "danger-full-access"
2416
+ };
2417
+ }
2367
2418
  if (thread.autonomy === "full") {
2368
2419
  return {
2369
2420
  claude: "bypassPermissions",
@@ -2373,19 +2424,16 @@ function permissionMode(thread) {
2373
2424
  }
2374
2425
  return {
2375
2426
  claude: "acceptEdits",
2376
- opencodePermission: JSON.stringify({
2377
- edit: "allow",
2378
- bash: { "*": "allow", "rm -rf *": "deny" }
2379
- }),
2427
+ opencodePermission: JSON.stringify({}),
2380
2428
  codexSandbox: "workspace-write"
2381
2429
  };
2382
2430
  }
2383
2431
 
2384
2432
  // src/agent-rpc/metadata.ts
2385
- import { existsSync as existsSync9, readFileSync as readFileSync5, unlinkSync, writeFileSync as writeFileSync4 } from "fs";
2386
- import { join as join8 } from "path";
2433
+ import { existsSync as existsSync9, readFileSync as readFileSync5, unlinkSync, writeFileSync as writeFileSync5 } from "fs";
2434
+ import { join as join9 } from "path";
2387
2435
  function agentRuntimeMetadataPath() {
2388
- return join8(appDataDir(), "agent-runtime.json");
2436
+ return join9(appDataDir(), "agent-runtime.json");
2389
2437
  }
2390
2438
  function readAgentRuntimeMetadata() {
2391
2439
  try {
@@ -2454,7 +2502,7 @@ function agentRpcChildEnv(rpc, cwd) {
2454
2502
  // src/agents/claude-host.ts
2455
2503
  import { existsSync as existsSync10 } from "fs";
2456
2504
  import { createRequire as createRequire2 } from "module";
2457
- import { dirname as dirname4, join as join9 } from "path";
2505
+ import { dirname as dirname4, join as join10 } from "path";
2458
2506
  import { fileURLToPath as fileURLToPath2 } from "url";
2459
2507
 
2460
2508
  // src/agent-rpc/client.ts
@@ -2499,17 +2547,17 @@ function entryDir() {
2499
2547
  function claudeRunnerPath() {
2500
2548
  const packagedDir = packagedCursorRuntimeDir();
2501
2549
  if (packagedDir) {
2502
- const packaged = join9(packagedDir, "core-dist", "agents", "claude-runner.js");
2550
+ const packaged = join10(packagedDir, "core-dist", "agents", "claude-runner.js");
2503
2551
  if (existsSync10(packaged)) return packaged;
2504
2552
  }
2505
2553
  const root = entryDir();
2506
2554
  const candidates = [
2507
- join9(root, "agents", "claude-runner.js"),
2508
- join9(root, "agents", "claude-runner.cjs"),
2509
- join9(root, "dist", "agents", "claude-runner.js"),
2510
- join9(root, "dist", "agents", "claude-runner.cjs"),
2511
- join9(root, "claude-runner.ts"),
2512
- join9(root, "src", "agents", "claude-runner.ts")
2555
+ join10(root, "agents", "claude-runner.js"),
2556
+ join10(root, "agents", "claude-runner.cjs"),
2557
+ join10(root, "dist", "agents", "claude-runner.js"),
2558
+ join10(root, "dist", "agents", "claude-runner.cjs"),
2559
+ join10(root, "claude-runner.ts"),
2560
+ join10(root, "src", "agents", "claude-runner.ts")
2513
2561
  ];
2514
2562
  for (const candidate of candidates) {
2515
2563
  if (existsSync10(candidate)) return candidate;
@@ -2588,7 +2636,8 @@ function sessionCostUsdFromClaudeResult(obj) {
2588
2636
  function claudeResultErrorDetail(obj) {
2589
2637
  const isError = Boolean(obj.is_error) || typeof obj.subtype === "string" && /^error/i.test(obj.subtype);
2590
2638
  const fromResult = typeof obj.result === "string" ? obj.result.trim() : "";
2591
- if (fromResult && (isError || looksLikeAgentFailureMessage(fromResult))) {
2639
+ const shortFailure = fromResult.length > 0 && fromResult.length <= 300 && !fromResult.includes("\n") && looksLikeAgentFailureMessage(fromResult);
2640
+ if (fromResult && (isError || shortFailure)) {
2592
2641
  return fromResult;
2593
2642
  }
2594
2643
  if (!isError) return null;
@@ -2835,7 +2884,7 @@ function eventsFromClaudeSystem(obj) {
2835
2884
  data: `Context compressed${trigger}`,
2836
2885
  replace: true
2837
2886
  };
2838
- if (meta.postTokens != null && meta.postTokens > 0) {
2887
+ if (meta.postTokens != null && meta.postTokens > 0 && !parentId) {
2839
2888
  return [
2840
2889
  thinking,
2841
2890
  {
@@ -2916,7 +2965,7 @@ var claudeAdapter = {
2916
2965
  );
2917
2966
  }
2918
2967
  const mode = permissionMode(thread);
2919
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-A6UO6PJV.js");
2968
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-UHU2FXTY.js");
2920
2969
  const isOrchestrator = isOrchestratorThread2(thread);
2921
2970
  const rpc = worktreeAgentRpc(isOrchestrator);
2922
2971
  const injectedServers = await buildInjectedMcpServers({
@@ -3016,6 +3065,7 @@ var claudeAdapter = {
3016
3065
  cwd: thread.worktreePath,
3017
3066
  stdin: useStdin ? `${promptText}
3018
3067
  ` : void 0,
3068
+ ...mcpConfigPath ? { cleanupDirs: [dirname5(mcpConfigPath)] } : {},
3019
3069
  // Nested Task/Agent thinking+text in stream-json (Claude Code 2.1.211+).
3020
3070
  // Raise the -p background-agent wait so long TaskOutput polls are not
3021
3071
  // abandoned at Claude Code’s 10-minute default.
@@ -3045,9 +3095,17 @@ var claudeAdapter = {
3045
3095
  Array.isArray(message?.content) ? message.content : void 0,
3046
3096
  parentId
3047
3097
  );
3048
- if (obj.type === "assistant") {
3098
+ if (obj.type === "assistant" && !parentId) {
3049
3099
  const usage = usageFromClaude(message?.usage);
3050
- if (usage) events.push({ type: "usage", data: usage, scope: "request" });
3100
+ const messageId = message && typeof message.id === "string" ? message.id : void 0;
3101
+ if (usage) {
3102
+ events.push({
3103
+ type: "usage",
3104
+ data: usage,
3105
+ scope: "request",
3106
+ ...messageId ? { messageId } : {}
3107
+ });
3108
+ }
3051
3109
  }
3052
3110
  if (events.length === 0) return null;
3053
3111
  return events.length === 1 ? events[0] : events;
@@ -3134,56 +3192,47 @@ var claudeAdapter = {
3134
3192
  return { file: claude, args, cwd: thread.worktreePath };
3135
3193
  },
3136
3194
  async listLinearIssues(_repoPath) {
3137
- const claude = resolveClaudeExecutable();
3138
- const prompt = "List my assigned Linear issues as JSON array only, no markdown. Each item: id, identifier, title, url, labels (string[]).";
3139
- const { stdout, exitCode } = await run(
3140
- claude,
3141
- [
3142
- "-p",
3143
- prompt,
3144
- "--output-format",
3145
- "json",
3146
- "--permission-mode",
3147
- "bypassPermissions",
3148
- "--allowedTools",
3149
- "mcp__linear__*"
3150
- ],
3151
- { reject: false }
3152
- );
3153
- if (exitCode !== 0) return [];
3154
- return parseIssuesJson(stdout);
3195
+ const { listAssignedLinearIssues: listAssignedLinearIssues2 } = await import("./linear-list-JFV3EES6.js");
3196
+ return listAssignedLinearIssues2();
3155
3197
  }
3156
3198
  };
3157
- function parseIssuesJson(raw) {
3158
- const text = raw.trim();
3159
- const candidates = [text];
3160
- const match = text.match(/\[[\s\S]*\]/);
3161
- if (match) candidates.push(match[0]);
3162
- for (const c of candidates) {
3163
- try {
3164
- const parsed = JSON.parse(c);
3165
- if (Array.isArray(parsed)) {
3166
- return parsed.map((item) => ({
3167
- id: String(item.id ?? item.identifier ?? ""),
3168
- identifier: String(item.identifier ?? item.id ?? ""),
3169
- title: String(item.title ?? ""),
3170
- url: String(item.url ?? ""),
3171
- labels: Array.isArray(item.labels) ? item.labels.map(String) : []
3172
- }));
3173
- }
3174
- if (parsed && typeof parsed === "object" && typeof parsed.result === "string") {
3175
- return parseIssuesJson(parsed.result);
3176
- }
3177
- } catch {
3199
+
3200
+ // src/agents/codex.ts
3201
+ import { existsSync as existsSync12, statSync as statSync2 } from "fs";
3202
+ import { homedir as homedir7 } from "os";
3203
+ import { join as join11 } from "path";
3204
+
3205
+ // src/agents/codex-items.ts
3206
+ function eventsFromCodexItem(eventType, item) {
3207
+ const itemType = item.type ?? item.item_type;
3208
+ if (itemType === "reasoning" && typeof item.text === "string" && item.text) {
3209
+ return { type: "thinking", data: item.text };
3210
+ }
3211
+ if (itemType !== "file_change" || !item.id) return null;
3212
+ const changes = Array.isArray(item.changes) ? item.changes : [];
3213
+ const paths = changes.map((change) => typeof change?.path === "string" ? change.path : "").filter(Boolean);
3214
+ const added = changes.some((change) => change?.kind === "add");
3215
+ const events = [
3216
+ {
3217
+ type: "tool_use",
3218
+ id: item.id,
3219
+ name: added ? "Write" : "Edit",
3220
+ input: paths.length ? { paths } : void 0
3178
3221
  }
3222
+ ];
3223
+ const finished = eventType === "item.completed" || item.status === "completed" || item.status === "failed";
3224
+ if (finished) {
3225
+ events.push({
3226
+ type: "tool_result",
3227
+ id: item.id,
3228
+ content: paths.join("\n") || void 0,
3229
+ isError: item.status === "failed"
3230
+ });
3179
3231
  }
3180
- return [];
3232
+ return events.length === 1 ? events[0] : events;
3181
3233
  }
3182
3234
 
3183
3235
  // src/agents/codex.ts
3184
- import { existsSync as existsSync12, readFileSync as readFileSync6, statSync as statSync2 } from "fs";
3185
- import { homedir as homedir6 } from "os";
3186
- import { join as join10 } from "path";
3187
3236
  var CODEX_PROMPT_ARG_MAX = 2e5;
3188
3237
  var FALLBACK_CODEX_MODELS = [
3189
3238
  { id: "gpt-5.6-sol", displayName: "GPT-5.6 Sol" },
@@ -3236,17 +3285,8 @@ function usageFromCodex(usage) {
3236
3285
  cachedInputTokens: Number(usage.cached_input_tokens ?? 0)
3237
3286
  });
3238
3287
  }
3239
- function codexConfigHasNetworkAccess() {
3240
- const candidates = [
3241
- join10(homedir6(), ".codex", "config.toml"),
3242
- join10(homedir6(), ".config", "codex", "config.toml")
3243
- ];
3244
- for (const path of candidates) {
3245
- if (!existsSync12(path)) continue;
3246
- const text = readFileSync6(path, "utf8");
3247
- if (/network_access\s*=\s*true/.test(text)) return true;
3248
- }
3249
- return false;
3288
+ function codexHomeDir() {
3289
+ return process.env.CODEX_HOME?.trim() || join11(homedir7(), ".codex");
3250
3290
  }
3251
3291
  function unwrapCodexMcpResult(result) {
3252
3292
  if (result == null) return void 0;
@@ -3275,7 +3315,7 @@ function asRecord3(value) {
3275
3315
  return void 0;
3276
3316
  }
3277
3317
  function codexLooksAuthenticated() {
3278
- const authPath = join10(homedir6(), ".codex", "auth.json");
3318
+ const authPath = join11(codexHomeDir(), "auth.json");
3279
3319
  if (!existsSync12(authPath)) return false;
3280
3320
  try {
3281
3321
  return statSync2(authPath).size > 2;
@@ -3314,18 +3354,13 @@ var codexAdapter = {
3314
3354
  const authenticated = codexLooksAuthenticated();
3315
3355
  const linearMcp = false;
3316
3356
  const warnings = [];
3317
- if (!codexConfigHasNetworkAccess()) {
3318
- warnings.push(
3319
- "Codex workspace-write blocks network by default \u2014 set [sandbox_workspace_write] network_access = true in ~/.codex/config.toml if agents need npm install etc."
3320
- );
3321
- }
3322
3357
  return {
3323
3358
  agent: "codex",
3324
3359
  installed: true,
3325
3360
  authenticated,
3326
3361
  linearMcp,
3327
3362
  warnings,
3328
- reason: authenticated ? void 0 : "Codex auth not found \u2014 run `codex login` (expected ~/.codex/auth.json)"
3363
+ reason: authenticated ? void 0 : `Codex auth not found \u2014 run \`codex login\` (expected ${join11(codexHomeDir(), "auth.json")})`
3329
3364
  };
3330
3365
  },
3331
3366
  async buildTurn(thread, input) {
@@ -3350,6 +3385,12 @@ var codexAdapter = {
3350
3385
  threadId: thread.id
3351
3386
  });
3352
3387
  const isolatePlugins = isOrchestrator || Boolean(thread.isolateCodexPlugins) || Boolean(normalizeTurnInput(input).isolateCodexPlugins);
3388
+ const gitEnv = await resolveAgentGitAuthEnv(process.env, {
3389
+ cwd: thread.worktreePath
3390
+ });
3391
+ const writableRoots = mode.codexSandbox === "workspace-write" ? await resolveCodexGitWritableRoots(thread.worktreePath) : [];
3392
+ const secretProfile = writeCodexMcpSecretProfile(injected);
3393
+ const effort = thread.effort?.trim() ?? "";
3353
3394
  const mcpOverrides = [
3354
3395
  // Worktree first try keeps plugins (Claude connectors). Coordinators
3355
3396
  // isolate. After a fatal plugin MCP, the orchestrator retries with
@@ -3366,6 +3407,7 @@ var codexAdapter = {
3366
3407
  const execOpts = [
3367
3408
  // Global orchestration cwd is not a git repo; without this Codex ≥0.147
3368
3409
  // refuses to start ("Not inside a trusted directory").
3410
+ ...secretProfile ? ["-p", secretProfile.profile] : [],
3369
3411
  "--skip-git-repo-check",
3370
3412
  "--cd",
3371
3413
  thread.worktreePath,
@@ -3375,14 +3417,16 @@ var codexAdapter = {
3375
3417
  // `codex exec` rejects `--ask-for-approval` (global-only on newer CLIs).
3376
3418
  "-c",
3377
3419
  'approval_policy="never"',
3378
- // Seatbelt cannot use the login Keychain; inherit GH_CONFIG_DIR / GIT_CONFIG_*.
3379
- // Default policy also strips *TOKEN*. Linked worktrees need the main
3380
- // repo `.git` (+ `.git/worktrees/<name>`) as writable_roots so git commit
3381
- // can create index.lock.
3420
+ // Seatbelt cannot use the login Keychain. inherit=all keeps GH_CONFIG_DIR
3421
+ // and GIT_CONFIG_*. Default excludes still strip *TOKEN*/*SECRET*/*KEY*;
3422
+ // GIT_CONFIG_KEY_n is re-set because it matches *KEY*. Linked worktrees
3423
+ // need the main repo `.git` as writable_roots so git commit can lock.
3382
3424
  ...codexUnattendedGitConfigArgs(mode.codexSandbox, {
3383
- writableRoots: mode.codexSandbox === "workspace-write" ? await resolveCodexGitWritableRoots(thread.worktreePath) : []
3425
+ writableRoots,
3426
+ preserveEnv: gitEnv
3384
3427
  }),
3385
3428
  ...model ? ["--model", model] : [],
3429
+ ...effort ? ["-c", `model_reasoning_effort=${JSON.stringify(effort)}`] : [],
3386
3430
  ...mcpOverrides
3387
3431
  ];
3388
3432
  const args = sessionId ? ["exec", ...execOpts, "resume", sessionId, promptArg] : ["exec", ...execOpts, promptArg];
@@ -3391,7 +3435,8 @@ var codexAdapter = {
3391
3435
  args,
3392
3436
  cwd: thread.worktreePath,
3393
3437
  stdin: useStdin ? `${prompt}
3394
- ` : void 0
3438
+ ` : void 0,
3439
+ ...secretProfile ? { cleanupDirs: [secretProfile.file] } : {}
3395
3440
  };
3396
3441
  },
3397
3442
  parseEvent(line) {
@@ -3412,8 +3457,10 @@ var codexAdapter = {
3412
3457
  if (typeof obj.item === "object" && obj.item !== null) {
3413
3458
  const item = obj.item;
3414
3459
  const itemType = item.type ?? item.item_type;
3460
+ const mapped = eventsFromCodexItem(type, item);
3461
+ if (mapped) return mapped;
3415
3462
  if (itemType === "error") {
3416
- const detail = item.message?.trim() || extractJsonErrorMessage(obj) || "Codex item error";
3463
+ const detail = (typeof item.message === "string" ? item.message.trim() : "") || extractJsonErrorMessage(obj) || "Codex item error";
3417
3464
  return { type: "stderr", data: detail };
3418
3465
  }
3419
3466
  if (itemType === "agent_message" && item.text) {
@@ -3442,14 +3489,14 @@ var codexAdapter = {
3442
3489
  const events = [
3443
3490
  { type: "tool_use", id: item.id, name: "Bash", input }
3444
3491
  ];
3445
- const finished = type === "item.completed" || item.status === "completed" || item.status === "failed";
3492
+ const finished = type === "item.completed" || item.status === "completed" || item.status === "failed" || item.status === "declined";
3446
3493
  const output = typeof item.aggregated_output === "string" && item.aggregated_output ? item.aggregated_output : void 0;
3447
3494
  if (finished) {
3448
3495
  events.push({
3449
3496
  type: "tool_result",
3450
3497
  id: item.id,
3451
3498
  content: output,
3452
- isError: item.status === "failed"
3499
+ isError: item.status === "failed" || item.status === "declined"
3453
3500
  });
3454
3501
  } else if (output) {
3455
3502
  events.push({
@@ -3492,7 +3539,7 @@ var codexAdapter = {
3492
3539
  return events.length === 1 ? events[0] : events;
3493
3540
  }
3494
3541
  if (item.status === "failed") {
3495
- const detail = item.message?.trim() || extractJsonErrorMessage(item) || `Codex ${itemType ?? "item"} failed`;
3542
+ const detail = (typeof item.message === "string" ? item.message.trim() : "") || extractJsonErrorMessage(item) || `Codex ${itemType ?? "item"} failed`;
3496
3543
  return { type: "stderr", data: detail };
3497
3544
  }
3498
3545
  }
@@ -3501,7 +3548,8 @@ var codexAdapter = {
3501
3548
  return { type: "session_id", data: sid };
3502
3549
  }
3503
3550
  if (type === "turn.completed" || type === "turn_completed") {
3504
- const usage = usageFromCodex(obj.usage);
3551
+ const payload = obj;
3552
+ const usage = usageFromCodex(payload.last_token_usage ?? payload.usage);
3505
3553
  return usage ? { type: "usage", data: usage, scope: "turn" } : null;
3506
3554
  }
3507
3555
  if (typeof obj.content === "string" && obj.content.trim()) {
@@ -3524,7 +3572,7 @@ var codexAdapter = {
3524
3572
  if (sessionId) {
3525
3573
  return {
3526
3574
  file: codex,
3527
- args: ["exec", "--cd", thread.worktreePath, "resume", sessionId],
3575
+ args: ["resume", sessionId],
3528
3576
  cwd: thread.worktreePath
3529
3577
  };
3530
3578
  }
@@ -3535,56 +3583,34 @@ var codexAdapter = {
3535
3583
  };
3536
3584
  },
3537
3585
  async listLinearIssues(_repoPath) {
3538
- const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
3539
- const { stdout, exitCode } = await run(
3540
- resolveAgentExecutable("codex"),
3541
- [
3542
- "exec",
3543
- "--json",
3544
- "--sandbox",
3545
- "read-only",
3546
- "-c",
3547
- 'approval_policy="never"',
3548
- prompt
3549
- ],
3550
- { reject: false }
3551
- );
3552
- if (exitCode !== 0) return [];
3553
- const match = stdout.match(/\[[\s\S]*\]/);
3554
- if (!match) return [];
3555
- try {
3556
- const parsed = JSON.parse(match[0]);
3557
- return Array.isArray(parsed) ? parsed : [];
3558
- } catch {
3559
- return [];
3560
- }
3586
+ return listAssignedLinearIssues();
3561
3587
  }
3562
3588
  };
3563
3589
 
3564
3590
  // src/agents/cursor.ts
3565
3591
  import { existsSync as existsSync15 } from "fs";
3566
3592
  import { createRequire as createRequire5 } from "module";
3567
- import { dirname as dirname7, join as join13 } from "path";
3593
+ import { dirname as dirname8, join as join14 } from "path";
3568
3594
  import { fileURLToPath as fileURLToPath4 } from "url";
3569
3595
 
3570
3596
  // src/agents/cursor-sdk-resolve.ts
3571
- import { existsSync as existsSync13, readFileSync as readFileSync7 } from "fs";
3597
+ import { existsSync as existsSync13, readFileSync as readFileSync6 } from "fs";
3572
3598
  import { createRequire as createRequire3 } from "module";
3573
- import { basename, dirname as dirname5, join as join11 } from "path";
3599
+ import { basename, dirname as dirname6, join as join12 } from "path";
3574
3600
  import { fileURLToPath as fileURLToPath3, pathToFileURL } from "url";
3575
3601
  var CURSOR_SDK_INSTALL_HINT = "Cursor SDK is not installed. Settings \u2192 Agents \u2192 Cursor \u2192 Install (`npm i -g @cursor/sdk`). Sideboard does not ship the SDK \u2014 update it anytime without a new Sideboard build.";
3576
3602
  function thisModuleFile() {
3577
3603
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
3578
- if (cjsDir) return join11(cjsDir, "cursor-sdk-resolve.js");
3604
+ if (cjsDir) return join12(cjsDir, "cursor-sdk-resolve.js");
3579
3605
  try {
3580
3606
  return fileURLToPath3(import.meta.url);
3581
3607
  } catch {
3582
- return join11(process.cwd(), "package.json");
3608
+ return join12(process.cwd(), "package.json");
3583
3609
  }
3584
3610
  }
3585
3611
  function packageRootLooksLikeSdk(dir) {
3586
3612
  try {
3587
- const raw = readFileSync7(join11(dir, "package.json"), "utf8");
3613
+ const raw = readFileSync6(join12(dir, "package.json"), "utf8");
3588
3614
  const pkg = JSON.parse(raw);
3589
3615
  return pkg.name === "@cursor/sdk" && existsSync13(dir);
3590
3616
  } catch {
@@ -3595,7 +3621,7 @@ function resolvedPackageRoot(fromFile) {
3595
3621
  try {
3596
3622
  const req = createRequire3(fromFile);
3597
3623
  const pkgJson = req.resolve("@cursor/sdk/package.json");
3598
- const root = dirname5(pkgJson);
3624
+ const root = dirname6(pkgJson);
3599
3625
  return packageRootLooksLikeSdk(root) ? root : null;
3600
3626
  } catch {
3601
3627
  return null;
@@ -3609,10 +3635,10 @@ function resolveCursorSdkRoot(opts) {
3609
3635
  }
3610
3636
  const globalNm = npmGlobalNodeModules(env);
3611
3637
  if (globalNm) {
3612
- const globalRoot = join11(globalNm, "@cursor/sdk");
3638
+ const globalRoot = join12(globalNm, "@cursor/sdk");
3613
3639
  if (packageRootLooksLikeSdk(globalRoot)) return globalRoot;
3614
3640
  }
3615
- const cwdPkg = join11(process.cwd(), "package.json");
3641
+ const cwdPkg = join12(process.cwd(), "package.json");
3616
3642
  return resolvedPackageRoot(thisModuleFile()) ?? resolvedPackageRoot(cwdPkg);
3617
3643
  }
3618
3644
  function isCursorSdkInstalled(opts) {
@@ -3628,12 +3654,12 @@ function exportTarget(value) {
3628
3654
  }
3629
3655
  function cursorSdkEsmEntry(root) {
3630
3656
  try {
3631
- const pkg = JSON.parse(readFileSync7(join11(root, "package.json"), "utf8"));
3657
+ const pkg = JSON.parse(readFileSync6(join12(root, "package.json"), "utf8"));
3632
3658
  const exp = pkg.exports;
3633
3659
  const dot = exp && typeof exp === "object" && !Array.isArray(exp) && "." in exp ? exp["."] : exp;
3634
3660
  const rel = exportTarget(dot) ?? (typeof pkg.module === "string" ? pkg.module : null);
3635
3661
  if (!rel) return null;
3636
- const entry = join11(root, rel);
3662
+ const entry = join12(root, rel);
3637
3663
  return existsSync13(entry) ? entry : null;
3638
3664
  } catch {
3639
3665
  return null;
@@ -3650,7 +3676,7 @@ async function importCursorSdk(opts) {
3650
3676
  try {
3651
3677
  let entry = cursorSdkEsmEntry(root);
3652
3678
  if (!entry) {
3653
- const req = createRequire3(join11(root, "package.json"));
3679
+ const req = createRequire3(join12(root, "package.json"));
3654
3680
  entry = req.resolve("@cursor/sdk");
3655
3681
  }
3656
3682
  return unwrapCursorSdkModule(await import(pathToFileURL(entry).href));
@@ -3662,8 +3688,8 @@ function cursorSdkPlatformRipgrepPackage() {
3662
3688
  return `@cursor/sdk-${process.platform}-${process.arch}`;
3663
3689
  }
3664
3690
  function nodeModulesDirForPackageRoot(packageRoot) {
3665
- const parent = dirname5(packageRoot);
3666
- return basename(parent).startsWith("@") ? dirname5(parent) : parent;
3691
+ const parent = dirname6(packageRoot);
3692
+ return basename(parent).startsWith("@") ? dirname6(parent) : parent;
3667
3693
  }
3668
3694
  function cursorSdkRipgrepCandidate(opts) {
3669
3695
  const root = resolveCursorSdkRoot(opts);
@@ -3671,9 +3697,9 @@ function cursorSdkRipgrepCandidate(opts) {
3671
3697
  const nm = nodeModulesDirForPackageRoot(root);
3672
3698
  const pkg = cursorSdkPlatformRipgrepPackage();
3673
3699
  const bin = process.platform === "win32" ? "rg.exe" : "rg";
3674
- const sibling = join11(nm, pkg, "bin", bin);
3700
+ const sibling = join12(nm, pkg, "bin", bin);
3675
3701
  if (existsSync13(sibling)) return sibling;
3676
- const nested = join11(root, "node_modules", pkg, "bin", bin);
3702
+ const nested = join12(root, "node_modules", pkg, "bin", bin);
3677
3703
  return existsSync13(nested) ? nested : null;
3678
3704
  }
3679
3705
 
@@ -3702,7 +3728,8 @@ function preferredCursorCostCents(cost) {
3702
3728
  }
3703
3729
  function turnCostUsdFromCursorUsage(before, after) {
3704
3730
  if (!after) return void 0;
3705
- const beforeIds = new Set((before?.runs ?? []).map((r) => r.runId));
3731
+ if (before == null) return void 0;
3732
+ const beforeIds = new Set((before.runs ?? []).map((r) => r.runId));
3706
3733
  const newRuns = (after.runs ?? []).filter((r) => !beforeIds.has(r.runId));
3707
3734
  let sum = 0;
3708
3735
  let any = false;
@@ -3714,7 +3741,6 @@ function turnCostUsdFromCursorUsage(before, after) {
3714
3741
  }
3715
3742
  }
3716
3743
  if (any) return sum / 100;
3717
- if (before == null) return void 0;
3718
3744
  const afterCents = preferredCursorCostCents(after.cost);
3719
3745
  if (afterCents == null) return void 0;
3720
3746
  const beforeCents = preferredCursorCostCents(before.cost) ?? 0;
@@ -3891,7 +3917,7 @@ function parseCursorRunnerLine(line) {
3891
3917
  // src/agents/cursor-ripgrep.ts
3892
3918
  import { existsSync as existsSync14 } from "fs";
3893
3919
  import { createRequire as createRequire4 } from "module";
3894
- import { dirname as dirname6, isAbsolute as isAbsolute2, join as join12, parse, resolve as resolvePath } from "path";
3920
+ import { dirname as dirname7, isAbsolute as isAbsolute2, join as join13, parse, resolve as resolvePath } from "path";
3895
3921
  var RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
3896
3922
  function rgBinaryName() {
3897
3923
  return process.platform === "win32" ? "rg.exe" : "rg";
@@ -3910,12 +3936,12 @@ function walkForBundledRipgrep(startFile) {
3910
3936
  if (!startFile) return null;
3911
3937
  const pkg = platformRipgrepPackage();
3912
3938
  const name = rgBinaryName();
3913
- let dir = dirname6(resolvePath(startFile));
3939
+ let dir = dirname7(resolvePath(startFile));
3914
3940
  const root = parse(dir).root;
3915
3941
  while (dir !== root) {
3916
- const hit = usableRipgrepPath(join12(dir, "node_modules", pkg, "bin", name));
3942
+ const hit = usableRipgrepPath(join13(dir, "node_modules", pkg, "bin", name));
3917
3943
  if (hit) return hit;
3918
- const next = dirname6(dir);
3944
+ const next = dirname7(dir);
3919
3945
  if (next === dir) break;
3920
3946
  dir = next;
3921
3947
  }
@@ -3925,7 +3951,7 @@ function requireResolveBundledRipgrep(fromFile) {
3925
3951
  try {
3926
3952
  const req = createRequire4(fromFile);
3927
3953
  const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
3928
- return usableRipgrepPath(join12(dirname6(pkgJson), "bin", rgBinaryName()));
3954
+ return usableRipgrepPath(join13(dirname7(pkgJson), "bin", rgBinaryName()));
3929
3955
  } catch {
3930
3956
  return null;
3931
3957
  }
@@ -3999,11 +4025,11 @@ function entryDir2() {
3999
4025
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
4000
4026
  if (cjsDir) return cjsDir;
4001
4027
  try {
4002
- return dirname7(fileURLToPath4(import.meta.url));
4028
+ return dirname8(fileURLToPath4(import.meta.url));
4003
4029
  } catch {
4004
4030
  try {
4005
4031
  const req = createRequire5(process.cwd() + "/");
4006
- return dirname7(req.resolve("@sideboard-ai/core"));
4032
+ return dirname8(req.resolve("@sideboard-ai/core"));
4007
4033
  } catch {
4008
4034
  return process.cwd();
4009
4035
  }
@@ -4014,14 +4040,14 @@ function cursorRunnerPath() {
4014
4040
  if (packaged) return packaged;
4015
4041
  const root = entryDir2();
4016
4042
  const candidates = [
4017
- join13(root, "agents", "cursor-runner.js"),
4018
- join13(root, "agents", "cursor-runner.cjs"),
4043
+ join14(root, "agents", "cursor-runner.js"),
4044
+ join14(root, "agents", "cursor-runner.cjs"),
4019
4045
  // If somehow resolved from package root instead of dist/
4020
- join13(root, "dist", "agents", "cursor-runner.js"),
4021
- join13(root, "dist", "agents", "cursor-runner.cjs"),
4046
+ join14(root, "dist", "agents", "cursor-runner.js"),
4047
+ join14(root, "dist", "agents", "cursor-runner.cjs"),
4022
4048
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
4023
- join13(root, "cursor-runner.ts"),
4024
- join13(root, "src", "agents", "cursor-runner.ts")
4049
+ join14(root, "cursor-runner.ts"),
4050
+ join14(root, "src", "agents", "cursor-runner.ts")
4025
4051
  ];
4026
4052
  for (const candidate of candidates) {
4027
4053
  if (existsSync15(candidate)) return candidate;
@@ -4062,6 +4088,7 @@ var cursorAdapter = {
4062
4088
  },
4063
4089
  async buildTurn(thread, input) {
4064
4090
  const agentId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
4091
+ const fullPrompt = flattenTurnInput(input);
4065
4092
  const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, agentId));
4066
4093
  const apiKey = resolveCursorApiKey() || void 0;
4067
4094
  const isOrchestrator = isOrchestratorThread(thread);
@@ -4078,6 +4105,7 @@ var cursorAdapter = {
4078
4105
  const mcpServers = toCursorMcpServers(injected);
4079
4106
  const req = {
4080
4107
  prompt,
4108
+ ...fullPrompt !== prompt ? { freshPrompt: fullPrompt } : {},
4081
4109
  cwd: thread.worktreePath,
4082
4110
  threadId: thread.id,
4083
4111
  agentId,
@@ -4104,8 +4132,9 @@ var cursorAdapter = {
4104
4132
  stdin: JSON.stringify(req),
4105
4133
  env: {
4106
4134
  ...launch.env,
4107
- ...cursorRipgrepEnv({ startFile: runner }),
4108
- ...apiKey ? { CURSOR_API_KEY: apiKey } : {}
4135
+ ...cursorRipgrepEnv({ startFile: runner })
4136
+ // API key stays on the stdin request. Do not copy it into the child env,
4137
+ // where `ps` and crash dumps can see it. The runner reads `req.apiKey`.
4109
4138
  }
4110
4139
  };
4111
4140
  },
@@ -4127,14 +4156,17 @@ var cursorAdapter = {
4127
4156
  };
4128
4157
 
4129
4158
  // src/agents/opencode.ts
4130
- import { existsSync as existsSync16 } from "fs";
4159
+ import { existsSync as existsSync17 } from "fs";
4160
+
4161
+ // src/agent-rpc/opencode-host.ts
4162
+ import { pathToFileURL as pathToFileURL2 } from "url";
4131
4163
 
4132
4164
  // src/agent-rpc/opencode-hook.ts
4133
- import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync5 } from "fs";
4134
- import { join as join14 } from "path";
4165
+ import { existsSync as existsSync16, mkdirSync as mkdirSync4, readFileSync as readFileSync7, renameSync, writeFileSync as writeFileSync6 } from "fs";
4166
+ import { join as join15 } from "path";
4135
4167
  var OPENCODE_PLUGIN_SOURCE = `import { tool } from "@opencode-ai/plugin"
4136
4168
 
4137
- const URL = process.env[${JSON.stringify(AGENT_RPC_URL_ENV)}] || ""
4169
+ const RPC_URL = process.env[${JSON.stringify(AGENT_RPC_URL_ENV)}] || ""
4138
4170
  const TOKEN = process.env[${JSON.stringify(AGENT_RPC_TOKEN_ENV)}] || ""
4139
4171
  const CWD = process.env[${JSON.stringify(AGENT_RPC_CWD_ENV)}] || ""
4140
4172
 
@@ -4147,24 +4179,29 @@ function jsonError(err) {
4147
4179
  }
4148
4180
 
4149
4181
  function socketUrl() {
4150
- const u = new URL(URL)
4182
+ const u = new URL(RPC_URL)
4151
4183
  u.searchParams.set(${JSON.stringify(AGENT_RPC_TOKEN_QUERY)}, TOKEN)
4152
4184
  return u.toString()
4153
4185
  }
4154
4186
 
4155
4187
  function call(method, params) {
4156
- if (!URL || !TOKEN) {
4188
+ if (!RPC_URL || !TOKEN) {
4157
4189
  return Promise.resolve(jsonError(new Error("Agent RPC runtime is not running")))
4158
4190
  }
4191
+ const timeoutMs = method === "job.wait" ? 130000 : 30000
4159
4192
  return new Promise((resolve) => {
4160
4193
  let settled = false
4194
+ let ws
4195
+ let timer
4161
4196
  const done = (value) => {
4162
4197
  if (settled) return
4163
4198
  settled = true
4199
+ clearTimeout(timer)
4164
4200
  try { ws.close() } catch {}
4165
4201
  resolve(value)
4166
4202
  }
4167
- const ws = new WebSocket(socketUrl())
4203
+ timer = setTimeout(() => done(jsonError(new Error("Agent RPC timed out"))), timeoutMs)
4204
+ ws = new WebSocket(socketUrl())
4168
4205
  const id = Date.now()
4169
4206
  ws.addEventListener("open", () => {
4170
4207
  ws.send(JSON.stringify({ jsonrpc: "2.0", id, method, params, authToken: TOKEN }))
@@ -4236,12 +4273,19 @@ export const SideboardRpc = async (ctx) => {
4236
4273
  }
4237
4274
  `;
4238
4275
  function writeOpencodeRpcPlugin() {
4239
- const configDir = join14(appDataDir(), "agent-rpc", "opencode");
4240
- const pluginDir = join14(configDir, "plugins");
4241
- mkdirSync3(pluginDir, { recursive: true });
4242
- const pluginFile = join14(pluginDir, "sideboard-rpc.js");
4243
- writeFileSync5(pluginFile, OPENCODE_PLUGIN_SOURCE);
4244
- return { configDir, pluginFile };
4276
+ const pluginDir = join15(appDataDir(), "agent-rpc", "opencode");
4277
+ mkdirSync4(pluginDir, { recursive: true });
4278
+ const pluginFile = join15(pluginDir, "sideboard-rpc.js");
4279
+ if (existsSync16(pluginFile)) {
4280
+ try {
4281
+ if (readFileSync7(pluginFile, "utf8") === OPENCODE_PLUGIN_SOURCE) return pluginFile;
4282
+ } catch {
4283
+ }
4284
+ }
4285
+ const tmp = `${pluginFile}.${process.pid}.tmp`;
4286
+ writeFileSync6(tmp, OPENCODE_PLUGIN_SOURCE);
4287
+ renameSync(tmp, pluginFile);
4288
+ return pluginFile;
4245
4289
  }
4246
4290
 
4247
4291
  // src/agent-rpc/opencode-host.ts
@@ -4264,10 +4308,9 @@ async function buildOpencodeHostEnv(thread) {
4264
4308
  const config = injected.length > 0 || disableNames.length > 0 ? JSON.parse(toOpencodeMcpConfigContent(injected, { disableNames })) : {};
4265
4309
  const env = {};
4266
4310
  if (rpc) {
4267
- const { configDir, pluginFile } = writeOpencodeRpcPlugin();
4268
- env.OPENCODE_CONFIG_DIR = configDir;
4311
+ const pluginFile = writeOpencodeRpcPlugin();
4269
4312
  Object.assign(env, agentRpcChildEnv(rpc, thread.worktreePath));
4270
- config.plugin = [pluginFile];
4313
+ config.plugin = [pathToFileURL2(pluginFile).href];
4271
4314
  }
4272
4315
  if (Object.keys(config).length > 0) {
4273
4316
  env.OPENCODE_CONFIG_CONTENT = JSON.stringify(config);
@@ -4334,7 +4377,7 @@ async function listOpencodeModels() {
4334
4377
  if (opencode === "opencode") {
4335
4378
  const which = await run("which", ["opencode"], { reject: false });
4336
4379
  if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
4337
- } else if (!existsSync16(opencode)) {
4380
+ } else if (!existsSync17(opencode)) {
4338
4381
  return FALLBACK_OPENCODE_MODELS;
4339
4382
  }
4340
4383
  const listed = await run(opencode, ["models"], { reject: false });
@@ -4369,7 +4412,7 @@ var opencodeAdapter = {
4369
4412
  async detect() {
4370
4413
  const opencode = resolveAgentExecutable("opencode");
4371
4414
  if (opencode !== "opencode") {
4372
- if (!existsSync16(opencode)) {
4415
+ if (!existsSync17(opencode)) {
4373
4416
  return {
4374
4417
  agent: "opencode",
4375
4418
  installed: false,
@@ -4423,6 +4466,11 @@ var opencodeAdapter = {
4423
4466
  if (model) {
4424
4467
  args.push("--model", model);
4425
4468
  }
4469
+ args.push("--thinking");
4470
+ const variant = thread.effort?.trim() ?? "";
4471
+ if (variant && /^(minimal|low|medium|high|max|xhigh)$/i.test(variant)) {
4472
+ args.push("--variant", variant);
4473
+ }
4426
4474
  const hostEnv = await buildOpencodeHostEnv(thread);
4427
4475
  return {
4428
4476
  file: resolveAgentExecutable("opencode"),
@@ -4455,6 +4503,10 @@ var opencodeAdapter = {
4455
4503
  const text = obj.part?.text ?? obj.text;
4456
4504
  if (text) return { type: "stdout", data: text };
4457
4505
  }
4506
+ if (obj.type === "reasoning" || obj.type === "thinking") {
4507
+ const text = obj.part?.text ?? obj.text;
4508
+ if (typeof text === "string" && text) return { type: "thinking", data: text };
4509
+ }
4458
4510
  if (obj.type === "tool_use") {
4459
4511
  const part = obj.part;
4460
4512
  const name = part?.tool ?? part?.name ?? obj.tool ?? obj.name ?? "tool";
@@ -4570,11 +4622,14 @@ var opencodeAdapter = {
4570
4622
  const listed = await run(
4571
4623
  resolveAgentExecutable("opencode"),
4572
4624
  ["session", "list", "--format", "json"],
4573
- { cwd: worktreePath, reject: false }
4625
+ { cwd: worktreePath, reject: false, timeoutMs: 8e3 }
4574
4626
  );
4575
- if (listed.exitCode === 0 && listed.stdout.trim()) {
4627
+ if (listed.exitCode === 0) {
4628
+ const raw = listed.stdout.trim();
4629
+ if (!raw) return null;
4576
4630
  try {
4577
- const sessions = JSON.parse(listed.stdout);
4631
+ const sessions = JSON.parse(raw);
4632
+ if (Array.isArray(sessions) && sessions.length === 0) return null;
4578
4633
  if (Array.isArray(sessions) && sessions.length > 0) {
4579
4634
  const norm = (p) => p.replace(/\/+$/, "");
4580
4635
  const wt = norm(worktreePath);
@@ -4608,34 +4663,8 @@ var opencodeAdapter = {
4608
4663
  };
4609
4664
  },
4610
4665
  async listLinearIssues(_repoPath) {
4611
- const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
4612
- const { stdout, exitCode } = await run(
4613
- resolveAgentExecutable("opencode"),
4614
- ["run", prompt, "--format", "json"],
4615
- {
4616
- reject: false,
4617
- env: { OPENCODE_PERMISSION: JSON.stringify({ "*": "allow" }) }
4618
- }
4619
- );
4620
- if (exitCode !== 0) return [];
4621
- const texts = [];
4622
- for (const line of stdout.split("\n")) {
4623
- try {
4624
- const obj = JSON.parse(line);
4625
- if (obj.type === "text") {
4626
- texts.push(obj.part?.text ?? obj.text ?? "");
4627
- }
4628
- } catch {
4629
- }
4630
- }
4631
- const joined = texts.join("");
4632
- const match = joined.match(/\[[\s\S]*\]/);
4633
- if (!match) return [];
4634
- try {
4635
- return JSON.parse(match[0]);
4636
- } catch {
4637
- return [];
4638
- }
4666
+ const { listAssignedLinearIssues: listAssignedLinearIssues2 } = await import("./linear-list-JFV3EES6.js");
4667
+ return listAssignedLinearIssues2();
4639
4668
  }
4640
4669
  };
4641
4670
 
@@ -5034,9 +5063,9 @@ function formatClaudeUsageOverLimitWait(windows, now = /* @__PURE__ */ new Date(
5034
5063
  }
5035
5064
 
5036
5065
  // src/agents/claude-usage-client.ts
5037
- import { existsSync as existsSync17, readFileSync as readFileSync8 } from "fs";
5038
- import { homedir as homedir7 } from "os";
5039
- import { join as join15 } from "path";
5066
+ import { existsSync as existsSync18, readFileSync as readFileSync8 } from "fs";
5067
+ import { homedir as homedir8 } from "os";
5068
+ import { join as join16 } from "path";
5040
5069
  var CLAUDE_OAUTH_USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
5041
5070
  var CLAUDE_USAGE_TTL_MS = 9e4;
5042
5071
  var CLAUDE_USAGE_ERROR_TTL_MS = 5 * 6e4;
@@ -5076,12 +5105,12 @@ function accessTokenFromCredentialsJson(raw) {
5076
5105
  }
5077
5106
  }
5078
5107
  function claudeCredentialsPath(configDir) {
5079
- const root = configDir?.trim() || process.env.CLAUDE_CONFIG_DIR?.trim() || join15(homedir7(), ".claude");
5080
- return join15(root, ".credentials.json");
5108
+ const root = configDir?.trim() || process.env.CLAUDE_CONFIG_DIR?.trim() || join16(homedir8(), ".claude");
5109
+ return join16(root, ".credentials.json");
5081
5110
  }
5082
5111
  async function readFileAccessToken(configDir) {
5083
5112
  const path = claudeCredentialsPath(configDir);
5084
- if (!existsSync17(path)) return null;
5113
+ if (!existsSync18(path)) return null;
5085
5114
  try {
5086
5115
  return accessTokenFromCredentialsJson(readFileSync8(path, "utf8"));
5087
5116
  } catch {