@sideboard-ai/core 0.1.324 → 0.1.326

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-CU2UPMJF.js → abletime-RDHYSZL2.js} +5 -4
  2. package/dist/{abletime-5ZY3ZUUO.js → abletime-RYYFGKMU.js} +6 -5
  3. package/dist/{abletime-oauth-7EOSBEFM.js → abletime-oauth-OYGS2DAU.js} +3 -3
  4. package/dist/{abletime-oauth-4TTCR3CT.js → abletime-oauth-QR2QDVMK.js} +3 -3
  5. package/dist/{abletime-rest-KOKE7V4B.js → abletime-rest-BKYKNPTC.js} +3 -3
  6. package/dist/{abletime-rest-3TG4G7LW.js → abletime-rest-QDPTWNS4.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 +97 -32
  10. package/dist/agents/cursor-runner.js +74 -24
  11. package/dist/{agents-YK65UDLT.js → agents-HANWZNI6.js} +9 -8
  12. package/dist/{agents-LUSTCMDN.js → agents-QO7GKBYT.js} +12 -11
  13. package/dist/{app-settings-XIF4EC4K.js → app-settings-RXBH7KY4.js} +1 -1
  14. package/dist/{app-settings-I5HM5RMP.js → app-settings-TUVLZNDE.js} +1 -1
  15. package/dist/{chunk-7MQSYPAY.js → chunk-2EOLWHXH.js} +206 -188
  16. package/dist/{chunk-QOS4465Y.js → chunk-3Q4XNYHY.js} +1 -1
  17. package/dist/{chunk-RR4WCGNB.js → chunk-46FECFZU.js} +18 -15
  18. package/dist/{chunk-5GDJSFCT.js → chunk-4H5MWZ6J.js} +2 -2
  19. package/dist/{chunk-EQ52JR3Q.js → chunk-5MXLDDYF.js} +1 -1
  20. package/dist/{chunk-NCHOTN3C.js → chunk-5YCKATG6.js} +4 -3
  21. package/dist/{chunk-ROOZDDFA.js → chunk-75RPUXJS.js} +7 -8
  22. package/dist/{chunk-INBUV7HY.js → chunk-B244TJWC.js} +2 -2
  23. package/dist/{chunk-JH5SMVM5.js → chunk-BBNWKL4I.js} +268 -235
  24. package/dist/{chunk-ODH3XHMI.js → chunk-C7HUCBX7.js} +5 -5
  25. package/dist/{chunk-OIHRC2ZJ.js → chunk-D744HOI5.js} +25 -3
  26. package/dist/chunk-DBKHL7NC.js +214 -0
  27. package/dist/chunk-F6GE7V3Q.js +216 -0
  28. package/dist/{chunk-JE3JLHMO.js → chunk-FWVUGLBG.js} +3 -3
  29. package/dist/{chunk-DF5BM5OY.js → chunk-GP3RLZ6A.js} +207 -186
  30. package/dist/{chunk-FR3SAYUL.js → chunk-JM2TGOHP.js} +5 -5
  31. package/dist/{chunk-Y3WREIPQ.js → chunk-K7M7MIWL.js} +12 -210
  32. package/dist/{chunk-FUFNMUNR.js → chunk-KECHK3ZT.js} +7 -8
  33. package/dist/{chunk-EKU7FQVG.js → chunk-KXRF6RNL.js} +2 -2
  34. package/dist/chunk-LRHUBGEM.js +1259 -0
  35. package/dist/{chunk-MZIZTSR2.js → chunk-MAW7DIG7.js} +2 -2
  36. package/dist/{chunk-ZHGMRBSC.js → chunk-NURZOXGN.js} +4 -4
  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-7PVT73H6.js → chunk-PB6HW7SA.js} +12 -210
  41. package/dist/{chunk-B4CDSSRN.js → chunk-Q3FHTGIW.js} +2 -0
  42. package/dist/{chunk-7D5QIU3N.js → chunk-QG4CYRA3.js} +301 -268
  43. package/dist/{chunk-EJ66LEKH.js → chunk-QPSKQP6E.js} +24 -3
  44. package/dist/{chunk-Q3YJZPQI.js → chunk-RZVOX2MT.js} +3 -3
  45. package/dist/chunk-SO7G6O24.js +1445 -0
  46. package/dist/{chunk-YDUHLWI5.js → chunk-SUZOPJZC.js} +21 -7
  47. package/dist/chunk-TMCK5TLA.js +25 -0
  48. package/dist/chunk-W3ZLE4PO.js +77 -0
  49. package/dist/chunk-WUCAVIIP.js +28 -0
  50. package/dist/{chunk-BYUCNIXK.js → chunk-XLVLMQKN.js} +13 -9
  51. package/dist/{chunk-ZIRQZUZY.js → chunk-YGVGXQA7.js} +3 -3
  52. package/dist/{chunk-NXUN4U5P.js → chunk-YWQF7WAG.js} +2 -2
  53. package/dist/{chunk-IFWGG2M2.js → chunk-ZSHS46V5.js} +2 -0
  54. package/dist/{chunk-74OPNF7U.js → chunk-ZUAYA57W.js} +2 -2
  55. package/dist/{conductor-SPZOTC7W.js → conductor-4GVTHUUB.js} +7 -7
  56. package/dist/{conductor-JFABMXDA.js → conductor-TGWI6ETZ.js} +6 -6
  57. package/dist/{coordinator-prompt-K66RGNWK.js → coordinator-prompt-3E6SIDTM.js} +4 -4
  58. package/dist/{coordinator-prompt-Z6UFHFDH.js → coordinator-prompt-WEYJREV6.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-FPDZKUPF.js} +4 -4
  62. package/dist/{global-workspace-RHEO55B4.js → global-workspace-UIEXAG2B.js} +4 -4
  63. package/dist/index.cjs +21094 -20840
  64. package/dist/index.d.cts +36 -17
  65. package/dist/index.d.ts +36 -17
  66. package/dist/index.js +343 -1678
  67. package/dist/linear-6S7MK5YK.js +69 -0
  68. package/dist/linear-Z2T4KUAQ.js +67 -0
  69. package/dist/linear-list-A37WLUBO.js +6 -0
  70. package/dist/linear-list-Q4M7AZO2.js +8 -0
  71. package/dist/mcp/run-stdio.cjs +15903 -15640
  72. package/dist/mcp/run-stdio.js +67 -1247
  73. package/dist/{optional-cli-RMMS5L6F.js → optional-cli-AANBL4U5.js} +3 -3
  74. package/dist/{optional-cli-Y3Z3GIPZ.js → optional-cli-CA4LL322.js} +4 -4
  75. package/dist/{orchestrator-7VTAUY24.js → orchestrator-7FVDBE7Y.js} +15 -13
  76. package/dist/{orchestrator-2O6OJQLX.js → orchestrator-RQXRZW7Z.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-LEW4UP56.js} +4 -4
  80. package/dist/{workspaces-42E6AGXD.js → workspaces-QONNLHNR.js} +4 -4
  81. package/dist/{worktree-ZDA2UJ7C.js → worktree-6GIONDQO.js} +3 -3
  82. package/dist/{worktree-4NGXCCUO.js → worktree-KFEJAQ2H.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-YGVGXQA7.js";
28
16
  import {
29
17
  codexUnattendedGitConfigArgs,
30
18
  mergeAgentGitAuthEnv,
31
19
  resolveAgentGitAuthEnv,
32
20
  resolveCodexGitWritableRoots
33
- } from "./chunk-ROOZDDFA.js";
21
+ } from "./chunk-75RPUXJS.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-WUCAVIIP.js";
34
37
  import {
35
38
  githubAgentAuthReady,
36
39
  npmGlobalNodeModules,
@@ -43,9 +46,10 @@ import {
43
46
  isLinearConnected,
44
47
  isPosthogConnected,
45
48
  loadAppSettings,
49
+ requestOccupancy,
46
50
  resolveAgentExecutable,
47
51
  resolveClaudeExecutable
48
- } from "./chunk-OIHRC2ZJ.js";
52
+ } from "./chunk-D744HOI5.js";
49
53
  import {
50
54
  isElectronLikeCommand,
51
55
  unwrapStrippedElectronLaunch,
@@ -57,7 +61,7 @@ import {
57
61
  CLAUDE_POSTHOG_CONNECTOR_ALLOWED_TOOLS,
58
62
  CLAUDE_PRINT_BG_WAIT_CEILING_MS,
59
63
  mcpAllowToolsFromNames
60
- } from "./chunk-B4CDSSRN.js";
64
+ } from "./chunk-Q3FHTGIW.js";
61
65
  import {
62
66
  appDataDir
63
67
  } from "./chunk-WOU343SI.js";
@@ -448,6 +452,7 @@ var brightsyAdapter = {
448
452
 
449
453
  // src/agents/claude.ts
450
454
  import { existsSync as existsSync11 } from "fs";
455
+ import { dirname as dirname5 } from "path";
451
456
 
452
457
  // src/agents/claude-mcp-status.ts
453
458
  var SIDEBOARD_CONNECTOR_SERVICES = [
@@ -564,7 +569,7 @@ function isNotableMcpInitStatus(server, sideboardOk, coverage) {
564
569
 
565
570
  // src/mcp-ui/host.ts
566
571
  import { createHash } from "crypto";
567
- import { homedir as homedir5 } from "os";
572
+ import { homedir as homedir6 } from "os";
568
573
 
569
574
  // src/agents/orch-mcp-isolation.ts
570
575
  import { existsSync as existsSync8, readFileSync as readFileSync4 } from "fs";
@@ -921,20 +926,20 @@ function readJson(path) {
921
926
  }
922
927
 
923
928
  // src/agents/orch-mcp-isolation.ts
924
- import { homedir as homedir4 } from "os";
925
- import { join as join7 } from "path";
929
+ import { homedir as homedir5 } from "os";
930
+ import { join as join8 } from "path";
926
931
  import { parse as parseToml } from "smol-toml";
927
932
 
928
933
  // 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";
934
+ import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "fs";
935
+ import { homedir as homedir4 } from "os";
936
+ import { dirname as dirname3, join as join7 } from "path";
932
937
 
933
938
  // src/agents/injected-mcp.ts
934
- import { existsSync as existsSync6, mkdtempSync, writeFileSync as writeFileSync2 } from "fs";
939
+ import { existsSync as existsSync6, mkdtempSync, writeFileSync as writeFileSync3 } from "fs";
935
940
  import { createRequire } from "module";
936
941
  import { tmpdir } from "os";
937
- import { dirname as dirname2, join as join5 } from "path";
942
+ import { dirname as dirname2, join as join6 } from "path";
938
943
  import { fileURLToPath } from "url";
939
944
 
940
945
  // src/agent-rpc/protocol.ts
@@ -1401,6 +1406,44 @@ async function resolveNodeLaunch(scriptPath) {
1401
1406
  };
1402
1407
  }
1403
1408
 
1409
+ // src/agents/codex-mcp-profile.ts
1410
+ import { randomBytes } from "crypto";
1411
+ import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
1412
+ import { homedir as homedir3 } from "os";
1413
+ import { join as join5 } from "path";
1414
+ function isCodexSecretEnvKey(key) {
1415
+ return /token|secret|password|credential|oauth|api_key|_key$/i.test(key);
1416
+ }
1417
+ function tomlBasicString(value) {
1418
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r")}"`;
1419
+ }
1420
+ function secretEnv(env) {
1421
+ if (!env) return void 0;
1422
+ const out = { ...env };
1423
+ delete out.ELECTRON_RUN_AS_NODE;
1424
+ return Object.keys(out).length > 0 ? out : void 0;
1425
+ }
1426
+ function writeCodexMcpSecretProfile(servers) {
1427
+ const blocks = [];
1428
+ for (const s of servers) {
1429
+ const env = secretEnv(s.env);
1430
+ if (!env) continue;
1431
+ const secrets = Object.entries(env).filter(([key]) => isCodexSecretEnvKey(key));
1432
+ if (secrets.length === 0) continue;
1433
+ const lines = [`[mcp_servers.${s.name}.env]`];
1434
+ for (const [key, value] of secrets) lines.push(`${key} = ${tomlBasicString(value)}`);
1435
+ blocks.push(lines.join("\n"));
1436
+ }
1437
+ if (blocks.length === 0) return null;
1438
+ const home = process.env.CODEX_HOME?.trim() || join5(homedir3(), ".codex");
1439
+ mkdirSync2(home, { recursive: true, mode: 448 });
1440
+ const profile = `sideboard-${randomBytes(8).toString("hex")}`;
1441
+ const file = join5(home, `${profile}.config.toml`);
1442
+ writeFileSync2(file, `${blocks.join("\n\n")}
1443
+ `, { mode: 384 });
1444
+ return { profile, file };
1445
+ }
1446
+
1404
1447
  // src/agents/injected-mcp.ts
1405
1448
  var SIDEBOARD_MCP_ALLOWED_TOOLS = [
1406
1449
  "mcp__sideboard",
@@ -1536,7 +1579,7 @@ function corePackageDir() {
1536
1579
  } catch {
1537
1580
  }
1538
1581
  try {
1539
- const req = createRequire(join5(process.cwd(), "package.json"));
1582
+ const req = createRequire(join6(process.cwd(), "package.json"));
1540
1583
  return dirname2(req.resolve("@sideboard-ai/core"));
1541
1584
  } catch {
1542
1585
  return process.cwd();
@@ -1550,13 +1593,13 @@ function findSideboardMcpJsEntry() {
1550
1593
  let dir = corePackageDir();
1551
1594
  for (let i = 0; i < 10; i++) {
1552
1595
  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")
1596
+ join6(dir, "mcp/run-stdio.js"),
1597
+ join6(dir, "mcp/run-stdio.cjs"),
1598
+ join6(dir, "dist/mcp/run-stdio.js"),
1599
+ join6(dir, "dist/mcp/run-stdio.cjs"),
1600
+ join6(dir, "packages/core/dist/mcp/run-stdio.js"),
1601
+ join6(dir, "packages/cli/dist/index.js"),
1602
+ join6(dir, "cli/dist/index.js")
1560
1603
  ];
1561
1604
  for (const p of candidates) {
1562
1605
  if (existsSync6(p) && !isAsarPath(p)) return p;
@@ -1664,6 +1707,7 @@ function toCodexMcpConfigArgs(servers) {
1664
1707
  const env = mcpSpawnEnv(s.env);
1665
1708
  if (env) {
1666
1709
  for (const [key, value] of Object.entries(env)) {
1710
+ if (isCodexSecretEnvKey(key)) continue;
1667
1711
  args.push("-c", `${prefix}.env.${key}=${JSON.stringify(value)}`);
1668
1712
  }
1669
1713
  }
@@ -1722,15 +1766,15 @@ function mcpServersRecord(servers, extraServers) {
1722
1766
  function writeMcpServersConfig(servers, extraServers) {
1723
1767
  const mcpServers = mcpServersRecord(servers, extraServers);
1724
1768
  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));
1769
+ const dir = mkdtempSync(join6(tmpdir(), "sideboard-mcp-"));
1770
+ const cfgPath = join6(dir, "mcp.json");
1771
+ writeFileSync3(cfgPath, JSON.stringify({ mcpServers }, null, 2), { mode: 384 });
1728
1772
  return cfgPath;
1729
1773
  }
1730
1774
 
1731
1775
  // src/agents/user-mcp-config.ts
1732
1776
  function userClaudeMcpConfigPath() {
1733
- return join6(homedir3(), ".claude.json");
1777
+ return join7(homedir4(), ".claude.json");
1734
1778
  }
1735
1779
 
1736
1780
  // src/agents/orch-mcp-isolation.ts
@@ -1767,13 +1811,19 @@ function readText(path) {
1767
1811
  return "";
1768
1812
  }
1769
1813
  }
1770
- function userCodexConfigPaths(home = homedir4()) {
1771
- return [join7(home, ".codex", "config.toml"), join7(home, ".config", "codex", "config.toml")];
1814
+ function userCodexConfigPaths(home = homedir5()) {
1815
+ const paths = [
1816
+ join8(home, ".codex", "config.toml"),
1817
+ join8(home, ".config", "codex", "config.toml")
1818
+ ];
1819
+ const codexHome = process.env.CODEX_HOME?.trim();
1820
+ if (codexHome) paths.unshift(join8(codexHome, "config.toml"));
1821
+ return paths;
1772
1822
  }
1773
- function userOpencodeConfigPaths(home = homedir4()) {
1823
+ function userOpencodeConfigPaths(home = homedir5()) {
1774
1824
  return [
1775
- join7(home, ".config", "opencode", "opencode.json"),
1776
- join7(home, ".config", "opencode", "opencode.jsonc")
1825
+ join8(home, ".config", "opencode", "opencode.json"),
1826
+ join8(home, ".config", "opencode", "opencode.jsonc")
1777
1827
  ];
1778
1828
  }
1779
1829
  function userMcpNamesToDisable(opts) {
@@ -1792,7 +1842,7 @@ function userMcpNamesToDisable(opts) {
1792
1842
  }
1793
1843
  return out;
1794
1844
  }
1795
- function listUserCodexMcpNames(home = homedir4()) {
1845
+ function listUserCodexMcpNames(home = homedir5()) {
1796
1846
  const names = [];
1797
1847
  for (const path of userCodexConfigPaths(home)) {
1798
1848
  if (!existsSync8(path)) continue;
@@ -1800,7 +1850,7 @@ function listUserCodexMcpNames(home = homedir4()) {
1800
1850
  }
1801
1851
  return names;
1802
1852
  }
1803
- function listUserOpencodeMcpNames(home = homedir4()) {
1853
+ function listUserOpencodeMcpNames(home = homedir5()) {
1804
1854
  const names = [];
1805
1855
  for (const path of userOpencodeConfigPaths(home)) {
1806
1856
  if (!existsSync8(path)) continue;
@@ -1808,12 +1858,12 @@ function listUserOpencodeMcpNames(home = homedir4()) {
1808
1858
  }
1809
1859
  return names;
1810
1860
  }
1811
- function userClaudeMcpConfigObject(home = homedir4()) {
1812
- const claudePath = home === homedir4() ? userClaudeMcpConfigPath() : join7(home, ".claude.json");
1861
+ function userClaudeMcpConfigObject(home = homedir5()) {
1862
+ const claudePath = home === homedir5() ? userClaudeMcpConfigPath() : join8(home, ".claude.json");
1813
1863
  if (!existsSync8(claudePath)) return {};
1814
1864
  return asObject(asObject(readJsonObject(claudePath)).mcpServers);
1815
1865
  }
1816
- function listUserClaudeMcpServerEntries(home = homedir4(), projectDirs) {
1866
+ function listUserClaudeMcpServerEntries(home = homedir5(), projectDirs) {
1817
1867
  const out = {};
1818
1868
  for (const [name, entry] of Object.entries(
1819
1869
  listEnabledClaudePluginMcpServers({ home, projectDirs })
@@ -1851,7 +1901,7 @@ function toCodexUnattendedAppsArgs() {
1851
1901
  }
1852
1902
 
1853
1903
  // src/mcp-ui/proxy-http.ts
1854
- import { randomBytes, randomUUID } from "crypto";
1904
+ import { randomBytes as randomBytes2, randomUUID } from "crypto";
1855
1905
  import { createServer } from "http";
1856
1906
  import { Server as Server2 } from "@modelcontextprotocol/sdk/server/index.js";
1857
1907
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
@@ -1948,7 +1998,7 @@ function listedTool(tool) {
1948
1998
 
1949
1999
  // src/mcp-ui/proxy-http.ts
1950
2000
  async function listenMcpUiProxy(opts) {
1951
- const token = randomBytes(24).toString("hex");
2001
+ const token = randomBytes2(24).toString("hex");
1952
2002
  const transports = /* @__PURE__ */ new Map();
1953
2003
  const httpServer = createServer((req, res) => {
1954
2004
  void handle(req, res);
@@ -2321,7 +2371,7 @@ var singleton;
2321
2371
  function getMcpUiHost() {
2322
2372
  if (!singleton) {
2323
2373
  singleton = new McpUiHost({
2324
- entries: (projectDirs) => listUserClaudeMcpServerEntries(homedir5(), projectDirs)
2374
+ entries: (projectDirs) => listUserClaudeMcpServerEntries(homedir6(), projectDirs)
2325
2375
  });
2326
2376
  }
2327
2377
  return singleton;
@@ -2329,7 +2379,7 @@ function getMcpUiHost() {
2329
2379
  async function proxyClaudeUserMcp(orchestrator, projectDirs) {
2330
2380
  if (orchestrator) return {};
2331
2381
  const dirs = projectDirs.filter((d) => typeof d === "string" && d.length > 0);
2332
- return getMcpUiHost().proxyEntries(listUserClaudeMcpServerEntries(homedir5(), dirs), dirs);
2382
+ return getMcpUiHost().proxyEntries(listUserClaudeMcpServerEntries(homedir6(), dirs), dirs);
2333
2383
  }
2334
2384
  function dirsKeyFor(projectDirs) {
2335
2385
  if (!projectDirs?.length) return "";
@@ -2343,16 +2393,6 @@ function planModeTurnInstruction(planMode) {
2343
2393
  return planMode ? PLAN_MODE_INSTRUCTION : PLAN_MODE_OFF_INSTRUCTION;
2344
2394
  }
2345
2395
  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
2396
  if (thread.planMode) {
2357
2397
  return {
2358
2398
  claude: "plan",
@@ -2364,6 +2404,18 @@ function permissionMode(thread) {
2364
2404
  codexSandbox: "read-only"
2365
2405
  };
2366
2406
  }
2407
+ if (thread.sourceType === "orchestration") {
2408
+ return {
2409
+ claude: "acceptEdits",
2410
+ // Unattended coordinators cannot answer permission prompts. Explicit
2411
+ // allows override the user's OpenCode denies for this process only.
2412
+ opencodePermission: JSON.stringify({
2413
+ edit: "allow",
2414
+ bash: { "*": "allow" }
2415
+ }),
2416
+ codexSandbox: "danger-full-access"
2417
+ };
2418
+ }
2367
2419
  if (thread.autonomy === "full") {
2368
2420
  return {
2369
2421
  claude: "bypassPermissions",
@@ -2373,19 +2425,16 @@ function permissionMode(thread) {
2373
2425
  }
2374
2426
  return {
2375
2427
  claude: "acceptEdits",
2376
- opencodePermission: JSON.stringify({
2377
- edit: "allow",
2378
- bash: { "*": "allow", "rm -rf *": "deny" }
2379
- }),
2428
+ opencodePermission: JSON.stringify({}),
2380
2429
  codexSandbox: "workspace-write"
2381
2430
  };
2382
2431
  }
2383
2432
 
2384
2433
  // 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";
2434
+ import { existsSync as existsSync9, readFileSync as readFileSync5, unlinkSync, writeFileSync as writeFileSync5 } from "fs";
2435
+ import { join as join9 } from "path";
2387
2436
  function agentRuntimeMetadataPath() {
2388
- return join8(appDataDir(), "agent-runtime.json");
2437
+ return join9(appDataDir(), "agent-runtime.json");
2389
2438
  }
2390
2439
  function readAgentRuntimeMetadata() {
2391
2440
  try {
@@ -2454,7 +2503,7 @@ function agentRpcChildEnv(rpc, cwd) {
2454
2503
  // src/agents/claude-host.ts
2455
2504
  import { existsSync as existsSync10 } from "fs";
2456
2505
  import { createRequire as createRequire2 } from "module";
2457
- import { dirname as dirname4, join as join9 } from "path";
2506
+ import { dirname as dirname4, join as join10 } from "path";
2458
2507
  import { fileURLToPath as fileURLToPath2 } from "url";
2459
2508
 
2460
2509
  // src/agent-rpc/client.ts
@@ -2499,17 +2548,17 @@ function entryDir() {
2499
2548
  function claudeRunnerPath() {
2500
2549
  const packagedDir = packagedCursorRuntimeDir();
2501
2550
  if (packagedDir) {
2502
- const packaged = join9(packagedDir, "core-dist", "agents", "claude-runner.js");
2551
+ const packaged = join10(packagedDir, "core-dist", "agents", "claude-runner.js");
2503
2552
  if (existsSync10(packaged)) return packaged;
2504
2553
  }
2505
2554
  const root = entryDir();
2506
2555
  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")
2556
+ join10(root, "agents", "claude-runner.js"),
2557
+ join10(root, "agents", "claude-runner.cjs"),
2558
+ join10(root, "dist", "agents", "claude-runner.js"),
2559
+ join10(root, "dist", "agents", "claude-runner.cjs"),
2560
+ join10(root, "claude-runner.ts"),
2561
+ join10(root, "src", "agents", "claude-runner.ts")
2513
2562
  ];
2514
2563
  for (const candidate of candidates) {
2515
2564
  if (existsSync10(candidate)) return candidate;
@@ -2588,7 +2637,8 @@ function sessionCostUsdFromClaudeResult(obj) {
2588
2637
  function claudeResultErrorDetail(obj) {
2589
2638
  const isError = Boolean(obj.is_error) || typeof obj.subtype === "string" && /^error/i.test(obj.subtype);
2590
2639
  const fromResult = typeof obj.result === "string" ? obj.result.trim() : "";
2591
- if (fromResult && (isError || looksLikeAgentFailureMessage(fromResult))) {
2640
+ const shortFailure = fromResult.length > 0 && fromResult.length <= 300 && !fromResult.includes("\n") && looksLikeAgentFailureMessage(fromResult);
2641
+ if (fromResult && (isError || shortFailure)) {
2592
2642
  return fromResult;
2593
2643
  }
2594
2644
  if (!isError) return null;
@@ -2835,7 +2885,7 @@ function eventsFromClaudeSystem(obj) {
2835
2885
  data: `Context compressed${trigger}`,
2836
2886
  replace: true
2837
2887
  };
2838
- if (meta.postTokens != null && meta.postTokens > 0) {
2888
+ if (meta.postTokens != null && meta.postTokens > 0 && !parentId) {
2839
2889
  return [
2840
2890
  thinking,
2841
2891
  {
@@ -2916,7 +2966,7 @@ var claudeAdapter = {
2916
2966
  );
2917
2967
  }
2918
2968
  const mode = permissionMode(thread);
2919
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-A6UO6PJV.js");
2969
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-FPDZKUPF.js");
2920
2970
  const isOrchestrator = isOrchestratorThread2(thread);
2921
2971
  const rpc = worktreeAgentRpc(isOrchestrator);
2922
2972
  const injectedServers = await buildInjectedMcpServers({
@@ -3016,6 +3066,7 @@ var claudeAdapter = {
3016
3066
  cwd: thread.worktreePath,
3017
3067
  stdin: useStdin ? `${promptText}
3018
3068
  ` : void 0,
3069
+ ...mcpConfigPath ? { cleanupDirs: [dirname5(mcpConfigPath)] } : {},
3019
3070
  // Nested Task/Agent thinking+text in stream-json (Claude Code 2.1.211+).
3020
3071
  // Raise the -p background-agent wait so long TaskOutput polls are not
3021
3072
  // abandoned at Claude Code’s 10-minute default.
@@ -3045,9 +3096,17 @@ var claudeAdapter = {
3045
3096
  Array.isArray(message?.content) ? message.content : void 0,
3046
3097
  parentId
3047
3098
  );
3048
- if (obj.type === "assistant") {
3099
+ if (obj.type === "assistant" && !parentId) {
3049
3100
  const usage = usageFromClaude(message?.usage);
3050
- if (usage) events.push({ type: "usage", data: usage, scope: "request" });
3101
+ const messageId = message && typeof message.id === "string" ? message.id : void 0;
3102
+ if (usage) {
3103
+ events.push({
3104
+ type: "usage",
3105
+ data: usage,
3106
+ scope: "request",
3107
+ ...messageId ? { messageId } : {}
3108
+ });
3109
+ }
3051
3110
  }
3052
3111
  if (events.length === 0) return null;
3053
3112
  return events.length === 1 ? events[0] : events;
@@ -3134,56 +3193,47 @@ var claudeAdapter = {
3134
3193
  return { file: claude, args, cwd: thread.worktreePath };
3135
3194
  },
3136
3195
  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);
3196
+ const { listAssignedLinearIssues: listAssignedLinearIssues2 } = await import("./linear-list-Q4M7AZO2.js");
3197
+ return listAssignedLinearIssues2();
3155
3198
  }
3156
3199
  };
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 {
3200
+
3201
+ // src/agents/codex.ts
3202
+ import { existsSync as existsSync12, statSync as statSync2 } from "fs";
3203
+ import { homedir as homedir7 } from "os";
3204
+ import { join as join11 } from "path";
3205
+
3206
+ // src/agents/codex-items.ts
3207
+ function eventsFromCodexItem(eventType, item) {
3208
+ const itemType = item.type ?? item.item_type;
3209
+ if (itemType === "reasoning" && typeof item.text === "string" && item.text) {
3210
+ return { type: "thinking", data: item.text };
3211
+ }
3212
+ if (itemType !== "file_change" || !item.id) return null;
3213
+ const changes = Array.isArray(item.changes) ? item.changes : [];
3214
+ const paths = changes.map((change) => typeof change?.path === "string" ? change.path : "").filter(Boolean);
3215
+ const added = changes.some((change) => change?.kind === "add");
3216
+ const events = [
3217
+ {
3218
+ type: "tool_use",
3219
+ id: item.id,
3220
+ name: added ? "Write" : "Edit",
3221
+ input: paths.length ? { paths } : void 0
3178
3222
  }
3223
+ ];
3224
+ const finished = eventType === "item.completed" || item.status === "completed" || item.status === "failed";
3225
+ if (finished) {
3226
+ events.push({
3227
+ type: "tool_result",
3228
+ id: item.id,
3229
+ content: paths.join("\n") || void 0,
3230
+ isError: item.status === "failed"
3231
+ });
3179
3232
  }
3180
- return [];
3233
+ return events.length === 1 ? events[0] : events;
3181
3234
  }
3182
3235
 
3183
3236
  // 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
3237
  var CODEX_PROMPT_ARG_MAX = 2e5;
3188
3238
  var FALLBACK_CODEX_MODELS = [
3189
3239
  { id: "gpt-5.6-sol", displayName: "GPT-5.6 Sol" },
@@ -3228,25 +3278,19 @@ async function listCodexModels() {
3228
3278
  return cachedCodexModels?.models ?? FALLBACK_CODEX_MODELS;
3229
3279
  }
3230
3280
  }
3231
- function usageFromCodex(usage) {
3281
+ function usageFromCodex(usage, asContext = false) {
3232
3282
  if (!usage) return null;
3233
- return fromInclusiveInputUsage({
3283
+ const mapped = fromInclusiveInputUsage({
3234
3284
  inputTokens: Number(usage.input_tokens ?? 0),
3235
3285
  outputTokens: Number(usage.output_tokens ?? 0),
3236
3286
  cachedInputTokens: Number(usage.cached_input_tokens ?? 0)
3237
3287
  });
3288
+ if (!mapped || !asContext) return mapped;
3289
+ const occ = requestOccupancy(mapped);
3290
+ return occ > 0 ? { ...mapped, lastRequestTokens: occ } : mapped;
3238
3291
  }
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;
3292
+ function codexHomeDir() {
3293
+ return process.env.CODEX_HOME?.trim() || join11(homedir7(), ".codex");
3250
3294
  }
3251
3295
  function unwrapCodexMcpResult(result) {
3252
3296
  if (result == null) return void 0;
@@ -3275,7 +3319,7 @@ function asRecord3(value) {
3275
3319
  return void 0;
3276
3320
  }
3277
3321
  function codexLooksAuthenticated() {
3278
- const authPath = join10(homedir6(), ".codex", "auth.json");
3322
+ const authPath = join11(codexHomeDir(), "auth.json");
3279
3323
  if (!existsSync12(authPath)) return false;
3280
3324
  try {
3281
3325
  return statSync2(authPath).size > 2;
@@ -3314,18 +3358,13 @@ var codexAdapter = {
3314
3358
  const authenticated = codexLooksAuthenticated();
3315
3359
  const linearMcp = false;
3316
3360
  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
3361
  return {
3323
3362
  agent: "codex",
3324
3363
  installed: true,
3325
3364
  authenticated,
3326
3365
  linearMcp,
3327
3366
  warnings,
3328
- reason: authenticated ? void 0 : "Codex auth not found \u2014 run `codex login` (expected ~/.codex/auth.json)"
3367
+ reason: authenticated ? void 0 : `Codex auth not found \u2014 run \`codex login\` (expected ${join11(codexHomeDir(), "auth.json")})`
3329
3368
  };
3330
3369
  },
3331
3370
  async buildTurn(thread, input) {
@@ -3350,6 +3389,12 @@ var codexAdapter = {
3350
3389
  threadId: thread.id
3351
3390
  });
3352
3391
  const isolatePlugins = isOrchestrator || Boolean(thread.isolateCodexPlugins) || Boolean(normalizeTurnInput(input).isolateCodexPlugins);
3392
+ const gitEnv = await resolveAgentGitAuthEnv(process.env, {
3393
+ cwd: thread.worktreePath
3394
+ });
3395
+ const writableRoots = mode.codexSandbox === "workspace-write" ? await resolveCodexGitWritableRoots(thread.worktreePath) : [];
3396
+ const secretProfile = writeCodexMcpSecretProfile(injected);
3397
+ const effort = thread.effort?.trim() ?? "";
3353
3398
  const mcpOverrides = [
3354
3399
  // Worktree first try keeps plugins (Claude connectors). Coordinators
3355
3400
  // isolate. After a fatal plugin MCP, the orchestrator retries with
@@ -3366,6 +3411,7 @@ var codexAdapter = {
3366
3411
  const execOpts = [
3367
3412
  // Global orchestration cwd is not a git repo; without this Codex ≥0.147
3368
3413
  // refuses to start ("Not inside a trusted directory").
3414
+ ...secretProfile ? ["-p", secretProfile.profile] : [],
3369
3415
  "--skip-git-repo-check",
3370
3416
  "--cd",
3371
3417
  thread.worktreePath,
@@ -3375,14 +3421,16 @@ var codexAdapter = {
3375
3421
  // `codex exec` rejects `--ask-for-approval` (global-only on newer CLIs).
3376
3422
  "-c",
3377
3423
  '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.
3424
+ // Seatbelt cannot use the login Keychain. inherit=all keeps GH_CONFIG_DIR
3425
+ // and GIT_CONFIG_*. Default excludes still strip *TOKEN*/*SECRET*/*KEY*;
3426
+ // GIT_CONFIG_KEY_n is re-set because it matches *KEY*. Linked worktrees
3427
+ // need the main repo `.git` as writable_roots so git commit can lock.
3382
3428
  ...codexUnattendedGitConfigArgs(mode.codexSandbox, {
3383
- writableRoots: mode.codexSandbox === "workspace-write" ? await resolveCodexGitWritableRoots(thread.worktreePath) : []
3429
+ writableRoots,
3430
+ preserveEnv: gitEnv
3384
3431
  }),
3385
3432
  ...model ? ["--model", model] : [],
3433
+ ...effort ? ["-c", `model_reasoning_effort=${JSON.stringify(effort)}`] : [],
3386
3434
  ...mcpOverrides
3387
3435
  ];
3388
3436
  const args = sessionId ? ["exec", ...execOpts, "resume", sessionId, promptArg] : ["exec", ...execOpts, promptArg];
@@ -3391,7 +3439,8 @@ var codexAdapter = {
3391
3439
  args,
3392
3440
  cwd: thread.worktreePath,
3393
3441
  stdin: useStdin ? `${prompt}
3394
- ` : void 0
3442
+ ` : void 0,
3443
+ ...secretProfile ? { cleanupDirs: [secretProfile.file] } : {}
3395
3444
  };
3396
3445
  },
3397
3446
  parseEvent(line) {
@@ -3412,8 +3461,10 @@ var codexAdapter = {
3412
3461
  if (typeof obj.item === "object" && obj.item !== null) {
3413
3462
  const item = obj.item;
3414
3463
  const itemType = item.type ?? item.item_type;
3464
+ const mapped = eventsFromCodexItem(type, item);
3465
+ if (mapped) return mapped;
3415
3466
  if (itemType === "error") {
3416
- const detail = item.message?.trim() || extractJsonErrorMessage(obj) || "Codex item error";
3467
+ const detail = (typeof item.message === "string" ? item.message.trim() : "") || extractJsonErrorMessage(obj) || "Codex item error";
3417
3468
  return { type: "stderr", data: detail };
3418
3469
  }
3419
3470
  if (itemType === "agent_message" && item.text) {
@@ -3442,14 +3493,14 @@ var codexAdapter = {
3442
3493
  const events = [
3443
3494
  { type: "tool_use", id: item.id, name: "Bash", input }
3444
3495
  ];
3445
- const finished = type === "item.completed" || item.status === "completed" || item.status === "failed";
3496
+ const finished = type === "item.completed" || item.status === "completed" || item.status === "failed" || item.status === "declined";
3446
3497
  const output = typeof item.aggregated_output === "string" && item.aggregated_output ? item.aggregated_output : void 0;
3447
3498
  if (finished) {
3448
3499
  events.push({
3449
3500
  type: "tool_result",
3450
3501
  id: item.id,
3451
3502
  content: output,
3452
- isError: item.status === "failed"
3503
+ isError: item.status === "failed" || item.status === "declined"
3453
3504
  });
3454
3505
  } else if (output) {
3455
3506
  events.push({
@@ -3492,7 +3543,7 @@ var codexAdapter = {
3492
3543
  return events.length === 1 ? events[0] : events;
3493
3544
  }
3494
3545
  if (item.status === "failed") {
3495
- const detail = item.message?.trim() || extractJsonErrorMessage(item) || `Codex ${itemType ?? "item"} failed`;
3546
+ const detail = (typeof item.message === "string" ? item.message.trim() : "") || extractJsonErrorMessage(item) || `Codex ${itemType ?? "item"} failed`;
3496
3547
  return { type: "stderr", data: detail };
3497
3548
  }
3498
3549
  }
@@ -3501,7 +3552,8 @@ var codexAdapter = {
3501
3552
  return { type: "session_id", data: sid };
3502
3553
  }
3503
3554
  if (type === "turn.completed" || type === "turn_completed") {
3504
- const usage = usageFromCodex(obj.usage);
3555
+ const payload = obj;
3556
+ const usage = payload.last_token_usage ? usageFromCodex(payload.last_token_usage, true) : usageFromCodex(payload.usage);
3505
3557
  return usage ? { type: "usage", data: usage, scope: "turn" } : null;
3506
3558
  }
3507
3559
  if (typeof obj.content === "string" && obj.content.trim()) {
@@ -3524,7 +3576,7 @@ var codexAdapter = {
3524
3576
  if (sessionId) {
3525
3577
  return {
3526
3578
  file: codex,
3527
- args: ["exec", "--cd", thread.worktreePath, "resume", sessionId],
3579
+ args: ["resume", sessionId],
3528
3580
  cwd: thread.worktreePath
3529
3581
  };
3530
3582
  }
@@ -3535,56 +3587,34 @@ var codexAdapter = {
3535
3587
  };
3536
3588
  },
3537
3589
  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
- }
3590
+ return listAssignedLinearIssues();
3561
3591
  }
3562
3592
  };
3563
3593
 
3564
3594
  // src/agents/cursor.ts
3565
3595
  import { existsSync as existsSync15 } from "fs";
3566
3596
  import { createRequire as createRequire5 } from "module";
3567
- import { dirname as dirname7, join as join13 } from "path";
3597
+ import { dirname as dirname8, join as join14 } from "path";
3568
3598
  import { fileURLToPath as fileURLToPath4 } from "url";
3569
3599
 
3570
3600
  // src/agents/cursor-sdk-resolve.ts
3571
- import { existsSync as existsSync13, readFileSync as readFileSync7 } from "fs";
3601
+ import { existsSync as existsSync13, readFileSync as readFileSync6 } from "fs";
3572
3602
  import { createRequire as createRequire3 } from "module";
3573
- import { basename, dirname as dirname5, join as join11 } from "path";
3603
+ import { basename, dirname as dirname6, join as join12 } from "path";
3574
3604
  import { fileURLToPath as fileURLToPath3, pathToFileURL } from "url";
3575
3605
  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
3606
  function thisModuleFile() {
3577
3607
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
3578
- if (cjsDir) return join11(cjsDir, "cursor-sdk-resolve.js");
3608
+ if (cjsDir) return join12(cjsDir, "cursor-sdk-resolve.js");
3579
3609
  try {
3580
3610
  return fileURLToPath3(import.meta.url);
3581
3611
  } catch {
3582
- return join11(process.cwd(), "package.json");
3612
+ return join12(process.cwd(), "package.json");
3583
3613
  }
3584
3614
  }
3585
3615
  function packageRootLooksLikeSdk(dir) {
3586
3616
  try {
3587
- const raw = readFileSync7(join11(dir, "package.json"), "utf8");
3617
+ const raw = readFileSync6(join12(dir, "package.json"), "utf8");
3588
3618
  const pkg = JSON.parse(raw);
3589
3619
  return pkg.name === "@cursor/sdk" && existsSync13(dir);
3590
3620
  } catch {
@@ -3595,7 +3625,7 @@ function resolvedPackageRoot(fromFile) {
3595
3625
  try {
3596
3626
  const req = createRequire3(fromFile);
3597
3627
  const pkgJson = req.resolve("@cursor/sdk/package.json");
3598
- const root = dirname5(pkgJson);
3628
+ const root = dirname6(pkgJson);
3599
3629
  return packageRootLooksLikeSdk(root) ? root : null;
3600
3630
  } catch {
3601
3631
  return null;
@@ -3609,10 +3639,10 @@ function resolveCursorSdkRoot(opts) {
3609
3639
  }
3610
3640
  const globalNm = npmGlobalNodeModules(env);
3611
3641
  if (globalNm) {
3612
- const globalRoot = join11(globalNm, "@cursor/sdk");
3642
+ const globalRoot = join12(globalNm, "@cursor/sdk");
3613
3643
  if (packageRootLooksLikeSdk(globalRoot)) return globalRoot;
3614
3644
  }
3615
- const cwdPkg = join11(process.cwd(), "package.json");
3645
+ const cwdPkg = join12(process.cwd(), "package.json");
3616
3646
  return resolvedPackageRoot(thisModuleFile()) ?? resolvedPackageRoot(cwdPkg);
3617
3647
  }
3618
3648
  function isCursorSdkInstalled(opts) {
@@ -3628,12 +3658,12 @@ function exportTarget(value) {
3628
3658
  }
3629
3659
  function cursorSdkEsmEntry(root) {
3630
3660
  try {
3631
- const pkg = JSON.parse(readFileSync7(join11(root, "package.json"), "utf8"));
3661
+ const pkg = JSON.parse(readFileSync6(join12(root, "package.json"), "utf8"));
3632
3662
  const exp = pkg.exports;
3633
3663
  const dot = exp && typeof exp === "object" && !Array.isArray(exp) && "." in exp ? exp["."] : exp;
3634
3664
  const rel = exportTarget(dot) ?? (typeof pkg.module === "string" ? pkg.module : null);
3635
3665
  if (!rel) return null;
3636
- const entry = join11(root, rel);
3666
+ const entry = join12(root, rel);
3637
3667
  return existsSync13(entry) ? entry : null;
3638
3668
  } catch {
3639
3669
  return null;
@@ -3650,7 +3680,7 @@ async function importCursorSdk(opts) {
3650
3680
  try {
3651
3681
  let entry = cursorSdkEsmEntry(root);
3652
3682
  if (!entry) {
3653
- const req = createRequire3(join11(root, "package.json"));
3683
+ const req = createRequire3(join12(root, "package.json"));
3654
3684
  entry = req.resolve("@cursor/sdk");
3655
3685
  }
3656
3686
  return unwrapCursorSdkModule(await import(pathToFileURL(entry).href));
@@ -3662,8 +3692,8 @@ function cursorSdkPlatformRipgrepPackage() {
3662
3692
  return `@cursor/sdk-${process.platform}-${process.arch}`;
3663
3693
  }
3664
3694
  function nodeModulesDirForPackageRoot(packageRoot) {
3665
- const parent = dirname5(packageRoot);
3666
- return basename(parent).startsWith("@") ? dirname5(parent) : parent;
3695
+ const parent = dirname6(packageRoot);
3696
+ return basename(parent).startsWith("@") ? dirname6(parent) : parent;
3667
3697
  }
3668
3698
  function cursorSdkRipgrepCandidate(opts) {
3669
3699
  const root = resolveCursorSdkRoot(opts);
@@ -3671,9 +3701,9 @@ function cursorSdkRipgrepCandidate(opts) {
3671
3701
  const nm = nodeModulesDirForPackageRoot(root);
3672
3702
  const pkg = cursorSdkPlatformRipgrepPackage();
3673
3703
  const bin = process.platform === "win32" ? "rg.exe" : "rg";
3674
- const sibling = join11(nm, pkg, "bin", bin);
3704
+ const sibling = join12(nm, pkg, "bin", bin);
3675
3705
  if (existsSync13(sibling)) return sibling;
3676
- const nested = join11(root, "node_modules", pkg, "bin", bin);
3706
+ const nested = join12(root, "node_modules", pkg, "bin", bin);
3677
3707
  return existsSync13(nested) ? nested : null;
3678
3708
  }
3679
3709
 
@@ -3702,7 +3732,8 @@ function preferredCursorCostCents(cost) {
3702
3732
  }
3703
3733
  function turnCostUsdFromCursorUsage(before, after) {
3704
3734
  if (!after) return void 0;
3705
- const beforeIds = new Set((before?.runs ?? []).map((r) => r.runId));
3735
+ if (before == null) return void 0;
3736
+ const beforeIds = new Set((before.runs ?? []).map((r) => r.runId));
3706
3737
  const newRuns = (after.runs ?? []).filter((r) => !beforeIds.has(r.runId));
3707
3738
  let sum = 0;
3708
3739
  let any = false;
@@ -3714,7 +3745,6 @@ function turnCostUsdFromCursorUsage(before, after) {
3714
3745
  }
3715
3746
  }
3716
3747
  if (any) return sum / 100;
3717
- if (before == null) return void 0;
3718
3748
  const afterCents = preferredCursorCostCents(after.cost);
3719
3749
  if (afterCents == null) return void 0;
3720
3750
  const beforeCents = preferredCursorCostCents(before.cost) ?? 0;
@@ -3857,7 +3887,7 @@ function cursorSdkMessageToEvents(msg) {
3857
3887
  }
3858
3888
  if (msg.type === "usage") {
3859
3889
  const usage = usageFromCursor(msg.usage);
3860
- if (usage) return [{ type: "usage", data: usage, scope: "request" }];
3890
+ if (usage) return [{ type: "usage", data: usage, scope: "turn" }];
3861
3891
  }
3862
3892
  if (msg.type === "status" && msg.status === "ERROR") {
3863
3893
  const rawMessage = msg.message;
@@ -3891,7 +3921,7 @@ function parseCursorRunnerLine(line) {
3891
3921
  // src/agents/cursor-ripgrep.ts
3892
3922
  import { existsSync as existsSync14 } from "fs";
3893
3923
  import { createRequire as createRequire4 } from "module";
3894
- import { dirname as dirname6, isAbsolute as isAbsolute2, join as join12, parse, resolve as resolvePath } from "path";
3924
+ import { dirname as dirname7, isAbsolute as isAbsolute2, join as join13, parse, resolve as resolvePath } from "path";
3895
3925
  var RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
3896
3926
  function rgBinaryName() {
3897
3927
  return process.platform === "win32" ? "rg.exe" : "rg";
@@ -3910,12 +3940,12 @@ function walkForBundledRipgrep(startFile) {
3910
3940
  if (!startFile) return null;
3911
3941
  const pkg = platformRipgrepPackage();
3912
3942
  const name = rgBinaryName();
3913
- let dir = dirname6(resolvePath(startFile));
3943
+ let dir = dirname7(resolvePath(startFile));
3914
3944
  const root = parse(dir).root;
3915
3945
  while (dir !== root) {
3916
- const hit = usableRipgrepPath(join12(dir, "node_modules", pkg, "bin", name));
3946
+ const hit = usableRipgrepPath(join13(dir, "node_modules", pkg, "bin", name));
3917
3947
  if (hit) return hit;
3918
- const next = dirname6(dir);
3948
+ const next = dirname7(dir);
3919
3949
  if (next === dir) break;
3920
3950
  dir = next;
3921
3951
  }
@@ -3925,7 +3955,7 @@ function requireResolveBundledRipgrep(fromFile) {
3925
3955
  try {
3926
3956
  const req = createRequire4(fromFile);
3927
3957
  const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
3928
- return usableRipgrepPath(join12(dirname6(pkgJson), "bin", rgBinaryName()));
3958
+ return usableRipgrepPath(join13(dirname7(pkgJson), "bin", rgBinaryName()));
3929
3959
  } catch {
3930
3960
  return null;
3931
3961
  }
@@ -3999,11 +4029,11 @@ function entryDir2() {
3999
4029
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
4000
4030
  if (cjsDir) return cjsDir;
4001
4031
  try {
4002
- return dirname7(fileURLToPath4(import.meta.url));
4032
+ return dirname8(fileURLToPath4(import.meta.url));
4003
4033
  } catch {
4004
4034
  try {
4005
4035
  const req = createRequire5(process.cwd() + "/");
4006
- return dirname7(req.resolve("@sideboard-ai/core"));
4036
+ return dirname8(req.resolve("@sideboard-ai/core"));
4007
4037
  } catch {
4008
4038
  return process.cwd();
4009
4039
  }
@@ -4014,14 +4044,14 @@ function cursorRunnerPath() {
4014
4044
  if (packaged) return packaged;
4015
4045
  const root = entryDir2();
4016
4046
  const candidates = [
4017
- join13(root, "agents", "cursor-runner.js"),
4018
- join13(root, "agents", "cursor-runner.cjs"),
4047
+ join14(root, "agents", "cursor-runner.js"),
4048
+ join14(root, "agents", "cursor-runner.cjs"),
4019
4049
  // 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"),
4050
+ join14(root, "dist", "agents", "cursor-runner.js"),
4051
+ join14(root, "dist", "agents", "cursor-runner.cjs"),
4022
4052
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
4023
- join13(root, "cursor-runner.ts"),
4024
- join13(root, "src", "agents", "cursor-runner.ts")
4053
+ join14(root, "cursor-runner.ts"),
4054
+ join14(root, "src", "agents", "cursor-runner.ts")
4025
4055
  ];
4026
4056
  for (const candidate of candidates) {
4027
4057
  if (existsSync15(candidate)) return candidate;
@@ -4062,6 +4092,7 @@ var cursorAdapter = {
4062
4092
  },
4063
4093
  async buildTurn(thread, input) {
4064
4094
  const agentId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
4095
+ const fullPrompt = flattenTurnInput(input);
4065
4096
  const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, agentId));
4066
4097
  const apiKey = resolveCursorApiKey() || void 0;
4067
4098
  const isOrchestrator = isOrchestratorThread(thread);
@@ -4078,6 +4109,7 @@ var cursorAdapter = {
4078
4109
  const mcpServers = toCursorMcpServers(injected);
4079
4110
  const req = {
4080
4111
  prompt,
4112
+ ...fullPrompt !== prompt ? { freshPrompt: fullPrompt } : {},
4081
4113
  cwd: thread.worktreePath,
4082
4114
  threadId: thread.id,
4083
4115
  agentId,
@@ -4104,8 +4136,9 @@ var cursorAdapter = {
4104
4136
  stdin: JSON.stringify(req),
4105
4137
  env: {
4106
4138
  ...launch.env,
4107
- ...cursorRipgrepEnv({ startFile: runner }),
4108
- ...apiKey ? { CURSOR_API_KEY: apiKey } : {}
4139
+ ...cursorRipgrepEnv({ startFile: runner })
4140
+ // API key stays on the stdin request. Do not copy it into the child env,
4141
+ // where `ps` and crash dumps can see it. The runner reads `req.apiKey`.
4109
4142
  }
4110
4143
  };
4111
4144
  },
@@ -4127,14 +4160,17 @@ var cursorAdapter = {
4127
4160
  };
4128
4161
 
4129
4162
  // src/agents/opencode.ts
4130
- import { existsSync as existsSync16 } from "fs";
4163
+ import { existsSync as existsSync17 } from "fs";
4164
+
4165
+ // src/agent-rpc/opencode-host.ts
4166
+ import { pathToFileURL as pathToFileURL2 } from "url";
4131
4167
 
4132
4168
  // src/agent-rpc/opencode-hook.ts
4133
- import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync5 } from "fs";
4134
- import { join as join14 } from "path";
4169
+ import { existsSync as existsSync16, mkdirSync as mkdirSync4, readFileSync as readFileSync7, renameSync, writeFileSync as writeFileSync6 } from "fs";
4170
+ import { join as join15 } from "path";
4135
4171
  var OPENCODE_PLUGIN_SOURCE = `import { tool } from "@opencode-ai/plugin"
4136
4172
 
4137
- const URL = process.env[${JSON.stringify(AGENT_RPC_URL_ENV)}] || ""
4173
+ const RPC_URL = process.env[${JSON.stringify(AGENT_RPC_URL_ENV)}] || ""
4138
4174
  const TOKEN = process.env[${JSON.stringify(AGENT_RPC_TOKEN_ENV)}] || ""
4139
4175
  const CWD = process.env[${JSON.stringify(AGENT_RPC_CWD_ENV)}] || ""
4140
4176
 
@@ -4147,24 +4183,29 @@ function jsonError(err) {
4147
4183
  }
4148
4184
 
4149
4185
  function socketUrl() {
4150
- const u = new URL(URL)
4186
+ const u = new URL(RPC_URL)
4151
4187
  u.searchParams.set(${JSON.stringify(AGENT_RPC_TOKEN_QUERY)}, TOKEN)
4152
4188
  return u.toString()
4153
4189
  }
4154
4190
 
4155
4191
  function call(method, params) {
4156
- if (!URL || !TOKEN) {
4192
+ if (!RPC_URL || !TOKEN) {
4157
4193
  return Promise.resolve(jsonError(new Error("Agent RPC runtime is not running")))
4158
4194
  }
4195
+ const timeoutMs = method === "job.wait" ? 130000 : 30000
4159
4196
  return new Promise((resolve) => {
4160
4197
  let settled = false
4198
+ let ws
4199
+ let timer
4161
4200
  const done = (value) => {
4162
4201
  if (settled) return
4163
4202
  settled = true
4203
+ clearTimeout(timer)
4164
4204
  try { ws.close() } catch {}
4165
4205
  resolve(value)
4166
4206
  }
4167
- const ws = new WebSocket(socketUrl())
4207
+ timer = setTimeout(() => done(jsonError(new Error("Agent RPC timed out"))), timeoutMs)
4208
+ ws = new WebSocket(socketUrl())
4168
4209
  const id = Date.now()
4169
4210
  ws.addEventListener("open", () => {
4170
4211
  ws.send(JSON.stringify({ jsonrpc: "2.0", id, method, params, authToken: TOKEN }))
@@ -4236,12 +4277,19 @@ export const SideboardRpc = async (ctx) => {
4236
4277
  }
4237
4278
  `;
4238
4279
  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 };
4280
+ const pluginDir = join15(appDataDir(), "agent-rpc", "opencode");
4281
+ mkdirSync4(pluginDir, { recursive: true });
4282
+ const pluginFile = join15(pluginDir, "sideboard-rpc.js");
4283
+ if (existsSync16(pluginFile)) {
4284
+ try {
4285
+ if (readFileSync7(pluginFile, "utf8") === OPENCODE_PLUGIN_SOURCE) return pluginFile;
4286
+ } catch {
4287
+ }
4288
+ }
4289
+ const tmp = `${pluginFile}.${process.pid}.tmp`;
4290
+ writeFileSync6(tmp, OPENCODE_PLUGIN_SOURCE);
4291
+ renameSync(tmp, pluginFile);
4292
+ return pluginFile;
4245
4293
  }
4246
4294
 
4247
4295
  // src/agent-rpc/opencode-host.ts
@@ -4264,10 +4312,9 @@ async function buildOpencodeHostEnv(thread) {
4264
4312
  const config = injected.length > 0 || disableNames.length > 0 ? JSON.parse(toOpencodeMcpConfigContent(injected, { disableNames })) : {};
4265
4313
  const env = {};
4266
4314
  if (rpc) {
4267
- const { configDir, pluginFile } = writeOpencodeRpcPlugin();
4268
- env.OPENCODE_CONFIG_DIR = configDir;
4315
+ const pluginFile = writeOpencodeRpcPlugin();
4269
4316
  Object.assign(env, agentRpcChildEnv(rpc, thread.worktreePath));
4270
- config.plugin = [pluginFile];
4317
+ config.plugin = [pathToFileURL2(pluginFile).href];
4271
4318
  }
4272
4319
  if (Object.keys(config).length > 0) {
4273
4320
  env.OPENCODE_CONFIG_CONTENT = JSON.stringify(config);
@@ -4334,7 +4381,7 @@ async function listOpencodeModels() {
4334
4381
  if (opencode === "opencode") {
4335
4382
  const which = await run("which", ["opencode"], { reject: false });
4336
4383
  if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
4337
- } else if (!existsSync16(opencode)) {
4384
+ } else if (!existsSync17(opencode)) {
4338
4385
  return FALLBACK_OPENCODE_MODELS;
4339
4386
  }
4340
4387
  const listed = await run(opencode, ["models"], { reject: false });
@@ -4369,7 +4416,7 @@ var opencodeAdapter = {
4369
4416
  async detect() {
4370
4417
  const opencode = resolveAgentExecutable("opencode");
4371
4418
  if (opencode !== "opencode") {
4372
- if (!existsSync16(opencode)) {
4419
+ if (!existsSync17(opencode)) {
4373
4420
  return {
4374
4421
  agent: "opencode",
4375
4422
  installed: false,
@@ -4423,6 +4470,11 @@ var opencodeAdapter = {
4423
4470
  if (model) {
4424
4471
  args.push("--model", model);
4425
4472
  }
4473
+ args.push("--thinking");
4474
+ const variant = thread.effort?.trim() ?? "";
4475
+ if (variant && /^(minimal|low|medium|high|max|xhigh)$/i.test(variant)) {
4476
+ args.push("--variant", variant);
4477
+ }
4426
4478
  const hostEnv = await buildOpencodeHostEnv(thread);
4427
4479
  return {
4428
4480
  file: resolveAgentExecutable("opencode"),
@@ -4455,6 +4507,10 @@ var opencodeAdapter = {
4455
4507
  const text = obj.part?.text ?? obj.text;
4456
4508
  if (text) return { type: "stdout", data: text };
4457
4509
  }
4510
+ if (obj.type === "reasoning" || obj.type === "thinking") {
4511
+ const text = obj.part?.text ?? obj.text;
4512
+ if (typeof text === "string" && text) return { type: "thinking", data: text };
4513
+ }
4458
4514
  if (obj.type === "tool_use") {
4459
4515
  const part = obj.part;
4460
4516
  const name = part?.tool ?? part?.name ?? obj.tool ?? obj.name ?? "tool";
@@ -4570,11 +4626,14 @@ var opencodeAdapter = {
4570
4626
  const listed = await run(
4571
4627
  resolveAgentExecutable("opencode"),
4572
4628
  ["session", "list", "--format", "json"],
4573
- { cwd: worktreePath, reject: false }
4629
+ { cwd: worktreePath, reject: false, timeoutMs: 8e3 }
4574
4630
  );
4575
- if (listed.exitCode === 0 && listed.stdout.trim()) {
4631
+ if (listed.exitCode === 0) {
4632
+ const raw = listed.stdout.trim();
4633
+ if (!raw) return null;
4576
4634
  try {
4577
- const sessions = JSON.parse(listed.stdout);
4635
+ const sessions = JSON.parse(raw);
4636
+ if (Array.isArray(sessions) && sessions.length === 0) return null;
4578
4637
  if (Array.isArray(sessions) && sessions.length > 0) {
4579
4638
  const norm = (p) => p.replace(/\/+$/, "");
4580
4639
  const wt = norm(worktreePath);
@@ -4608,34 +4667,8 @@ var opencodeAdapter = {
4608
4667
  };
4609
4668
  },
4610
4669
  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
- }
4670
+ const { listAssignedLinearIssues: listAssignedLinearIssues2 } = await import("./linear-list-Q4M7AZO2.js");
4671
+ return listAssignedLinearIssues2();
4639
4672
  }
4640
4673
  };
4641
4674
 
@@ -5034,9 +5067,9 @@ function formatClaudeUsageOverLimitWait(windows, now = /* @__PURE__ */ new Date(
5034
5067
  }
5035
5068
 
5036
5069
  // 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";
5070
+ import { existsSync as existsSync18, readFileSync as readFileSync8 } from "fs";
5071
+ import { homedir as homedir8 } from "os";
5072
+ import { join as join16 } from "path";
5040
5073
  var CLAUDE_OAUTH_USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
5041
5074
  var CLAUDE_USAGE_TTL_MS = 9e4;
5042
5075
  var CLAUDE_USAGE_ERROR_TTL_MS = 5 * 6e4;
@@ -5076,12 +5109,12 @@ function accessTokenFromCredentialsJson(raw) {
5076
5109
  }
5077
5110
  }
5078
5111
  function claudeCredentialsPath(configDir) {
5079
- const root = configDir?.trim() || process.env.CLAUDE_CONFIG_DIR?.trim() || join15(homedir7(), ".claude");
5080
- return join15(root, ".credentials.json");
5112
+ const root = configDir?.trim() || process.env.CLAUDE_CONFIG_DIR?.trim() || join16(homedir8(), ".claude");
5113
+ return join16(root, ".credentials.json");
5081
5114
  }
5082
5115
  async function readFileAccessToken(configDir) {
5083
5116
  const path = claudeCredentialsPath(configDir);
5084
- if (!existsSync17(path)) return null;
5117
+ if (!existsSync18(path)) return null;
5085
5118
  try {
5086
5119
  return accessTokenFromCredentialsJson(readFileSync8(path, "utf8"));
5087
5120
  } catch {