@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
@@ -4,21 +4,24 @@ import {
4
4
  ensureCliTeamTracked,
5
5
  ensureConnectedBrightsyTeamTokens
6
6
  } from "./chunk-S5CJUIPY.js";
7
+ import {
8
+ listAssignedLinearIssues
9
+ } from "./chunk-TMCK5TLA.js";
7
10
  import {
8
11
  looksLikeConversationSummary,
9
12
  looksLikeSkillBody,
10
13
  skillCommandFromBody,
11
14
  withEventParentId
12
- } from "./chunk-QIC2JXHW.js";
15
+ } from "./chunk-OOXRMTU6.js";
13
16
  import {
14
17
  isOrchestratorThread
15
- } from "./chunk-JE3JLHMO.js";
18
+ } from "./chunk-FWVUGLBG.js";
16
19
  import {
17
20
  codexUnattendedGitConfigArgs,
18
21
  mergeAgentGitAuthEnv,
19
22
  resolveAgentGitAuthEnv,
20
23
  resolveCodexGitWritableRoots
21
- } from "./chunk-FUFNMUNR.js";
24
+ } from "./chunk-KECHK3ZT.js";
22
25
  import {
23
26
  loadBrightsyConfig
24
27
  } from "./chunk-RSA47QYR.js";
@@ -45,13 +48,13 @@ import {
45
48
  packagedMcpStdioPath,
46
49
  parseCursorRunnerLine,
47
50
  resolveNodeLaunch
48
- } from "./chunk-ZHGMRBSC.js";
51
+ } from "./chunk-NURZOXGN.js";
49
52
  import {
50
53
  extractJsonErrorMessage,
51
54
  formatUnknownDetail,
52
55
  looksLikeAgentFailureMessage,
53
56
  looksLikeBrightsyEmptyCompletion
54
- } from "./chunk-5XNT6BCG.js";
57
+ } from "./chunk-OPXEJJBM.js";
55
58
  import {
56
59
  githubAgentAuthReady,
57
60
  run
@@ -66,7 +69,7 @@ import {
66
69
  PILOT_TOOL_DESCRIPTIONS,
67
70
  PILOT_TOOL_NAMES,
68
71
  agentRpcConnectFromMetadata
69
- } from "./chunk-YDUHLWI5.js";
72
+ } from "./chunk-SUZOPJZC.js";
70
73
  import {
71
74
  claudeChromeEnabled,
72
75
  fromInclusiveInputUsage,
@@ -74,9 +77,10 @@ import {
74
77
  isLinearConnected,
75
78
  isPosthogConnected,
76
79
  loadAppSettings,
80
+ requestOccupancy,
77
81
  resolveAgentExecutable,
78
82
  resolveClaudeExecutable
79
- } from "./chunk-EJ66LEKH.js";
83
+ } from "./chunk-QPSKQP6E.js";
80
84
  import {
81
85
  isElectronLikeCommand,
82
86
  unwrapStrippedElectronLaunch
@@ -514,6 +518,7 @@ var brightsyAdapter = {
514
518
 
515
519
  // src/agents/claude.ts
516
520
  import { existsSync as existsSync7 } from "fs";
521
+ import { dirname as dirname4 } from "path";
517
522
 
518
523
  // src/agents/claude-mcp-status.ts
519
524
  var SIDEBOARD_CONNECTOR_SERVICES = [
@@ -630,7 +635,7 @@ function isNotableMcpInitStatus(server, sideboardOk, coverage) {
630
635
 
631
636
  // src/mcp-ui/host.ts
632
637
  import { createHash } from "crypto";
633
- import { homedir as homedir4 } from "os";
638
+ import { homedir as homedir5 } from "os";
634
639
 
635
640
  // src/agents/orch-mcp-isolation.ts
636
641
  import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
@@ -987,20 +992,20 @@ function readJson(path) {
987
992
  }
988
993
 
989
994
  // src/agents/orch-mcp-isolation.ts
990
- import { homedir as homedir3 } from "os";
991
- import { join as join4 } from "path";
995
+ import { homedir as homedir4 } from "os";
996
+ import { join as join5 } from "path";
992
997
  import { parse as parseToml } from "smol-toml";
993
998
 
994
999
  // src/agents/user-mcp-config.ts
995
- import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
996
- import { homedir as homedir2 } from "os";
997
- import { dirname as dirname2, join as join3 } from "path";
1000
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
1001
+ import { homedir as homedir3 } from "os";
1002
+ import { dirname as dirname2, join as join4 } from "path";
998
1003
 
999
1004
  // src/agents/injected-mcp.ts
1000
- import { existsSync as existsSync3, mkdtempSync, writeFileSync } from "fs";
1005
+ import { existsSync as existsSync3, mkdtempSync, writeFileSync as writeFileSync2 } from "fs";
1001
1006
  import { createRequire } from "module";
1002
1007
  import { tmpdir } from "os";
1003
- import { dirname, join as join2 } from "path";
1008
+ import { dirname, join as join3 } from "path";
1004
1009
  import { fileURLToPath } from "url";
1005
1010
 
1006
1011
  // src/mcp/profile.ts
@@ -1095,6 +1100,44 @@ function sideboardMcpProfile(env = process.env) {
1095
1100
  return env[SIDEBOARD_MCP_PROFILE_ENV]?.trim().toLowerCase() === "worktree" ? "worktree" : "orchestration";
1096
1101
  }
1097
1102
 
1103
+ // src/agents/codex-mcp-profile.ts
1104
+ import { randomBytes } from "crypto";
1105
+ import { mkdirSync, writeFileSync } from "fs";
1106
+ import { homedir as homedir2 } from "os";
1107
+ import { join as join2 } from "path";
1108
+ function isCodexSecretEnvKey(key) {
1109
+ return /token|secret|password|credential|oauth|api_key|_key$/i.test(key);
1110
+ }
1111
+ function tomlBasicString(value) {
1112
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r")}"`;
1113
+ }
1114
+ function secretEnv(env) {
1115
+ if (!env) return void 0;
1116
+ const out = { ...env };
1117
+ delete out.ELECTRON_RUN_AS_NODE;
1118
+ return Object.keys(out).length > 0 ? out : void 0;
1119
+ }
1120
+ function writeCodexMcpSecretProfile(servers) {
1121
+ const blocks = [];
1122
+ for (const s of servers) {
1123
+ const env = secretEnv(s.env);
1124
+ if (!env) continue;
1125
+ const secrets = Object.entries(env).filter(([key]) => isCodexSecretEnvKey(key));
1126
+ if (secrets.length === 0) continue;
1127
+ const lines = [`[mcp_servers.${s.name}.env]`];
1128
+ for (const [key, value] of secrets) lines.push(`${key} = ${tomlBasicString(value)}`);
1129
+ blocks.push(lines.join("\n"));
1130
+ }
1131
+ if (blocks.length === 0) return null;
1132
+ const home = process.env.CODEX_HOME?.trim() || join2(homedir2(), ".codex");
1133
+ mkdirSync(home, { recursive: true, mode: 448 });
1134
+ const profile = `sideboard-${randomBytes(8).toString("hex")}`;
1135
+ const file = join2(home, `${profile}.config.toml`);
1136
+ writeFileSync(file, `${blocks.join("\n\n")}
1137
+ `, { mode: 384 });
1138
+ return { profile, file };
1139
+ }
1140
+
1098
1141
  // src/agents/injected-mcp.ts
1099
1142
  var SIDEBOARD_MCP_ALLOWED_TOOLS = [
1100
1143
  "mcp__sideboard",
@@ -1234,7 +1277,7 @@ function corePackageDir() {
1234
1277
  } catch {
1235
1278
  }
1236
1279
  try {
1237
- const req = createRequire(join2(process.cwd(), "package.json"));
1280
+ const req = createRequire(join3(process.cwd(), "package.json"));
1238
1281
  return dirname(req.resolve("@sideboard-ai/core"));
1239
1282
  } catch {
1240
1283
  return process.cwd();
@@ -1248,13 +1291,13 @@ function findSideboardMcpJsEntry() {
1248
1291
  let dir = corePackageDir();
1249
1292
  for (let i = 0; i < 10; i++) {
1250
1293
  const candidates = [
1251
- join2(dir, "mcp/run-stdio.js"),
1252
- join2(dir, "mcp/run-stdio.cjs"),
1253
- join2(dir, "dist/mcp/run-stdio.js"),
1254
- join2(dir, "dist/mcp/run-stdio.cjs"),
1255
- join2(dir, "packages/core/dist/mcp/run-stdio.js"),
1256
- join2(dir, "packages/cli/dist/index.js"),
1257
- join2(dir, "cli/dist/index.js")
1294
+ join3(dir, "mcp/run-stdio.js"),
1295
+ join3(dir, "mcp/run-stdio.cjs"),
1296
+ join3(dir, "dist/mcp/run-stdio.js"),
1297
+ join3(dir, "dist/mcp/run-stdio.cjs"),
1298
+ join3(dir, "packages/core/dist/mcp/run-stdio.js"),
1299
+ join3(dir, "packages/cli/dist/index.js"),
1300
+ join3(dir, "cli/dist/index.js")
1258
1301
  ];
1259
1302
  for (const p of candidates) {
1260
1303
  if (existsSync3(p) && !isAsarPath(p)) return p;
@@ -1362,6 +1405,7 @@ function toCodexMcpConfigArgs(servers) {
1362
1405
  const env = mcpSpawnEnv(s.env);
1363
1406
  if (env) {
1364
1407
  for (const [key, value] of Object.entries(env)) {
1408
+ if (isCodexSecretEnvKey(key)) continue;
1365
1409
  args.push("-c", `${prefix}.env.${key}=${JSON.stringify(value)}`);
1366
1410
  }
1367
1411
  }
@@ -1420,9 +1464,9 @@ function mcpServersRecord(servers, extraServers) {
1420
1464
  function writeMcpServersConfig(servers, extraServers) {
1421
1465
  const mcpServers = mcpServersRecord(servers, extraServers);
1422
1466
  if (Object.keys(mcpServers).length === 0) return null;
1423
- const dir = mkdtempSync(join2(tmpdir(), "sideboard-mcp-"));
1424
- const cfgPath = join2(dir, "mcp.json");
1425
- writeFileSync(cfgPath, JSON.stringify({ mcpServers }, null, 2));
1467
+ const dir = mkdtempSync(join3(tmpdir(), "sideboard-mcp-"));
1468
+ const cfgPath = join3(dir, "mcp.json");
1469
+ writeFileSync2(cfgPath, JSON.stringify({ mcpServers }, null, 2), { mode: 384 });
1426
1470
  return cfgPath;
1427
1471
  }
1428
1472
  async function writeInjectedMcpConfig(opts) {
@@ -1431,10 +1475,10 @@ async function writeInjectedMcpConfig(opts) {
1431
1475
 
1432
1476
  // src/agents/user-mcp-config.ts
1433
1477
  function userCursorMcpConfigPath() {
1434
- return join3(homedir2(), ".cursor", "mcp.json");
1478
+ return join4(homedir3(), ".cursor", "mcp.json");
1435
1479
  }
1436
1480
  function userClaudeMcpConfigPath() {
1437
- return join3(homedir2(), ".claude.json");
1481
+ return join4(homedir3(), ".claude.json");
1438
1482
  }
1439
1483
  function asObject(value) {
1440
1484
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
@@ -1469,8 +1513,8 @@ function writeMergedMcpServersJson(configPath, sideboard) {
1469
1513
  }
1470
1514
  }
1471
1515
  const next = mergeSideboardIntoMcpServersJson(existing, sideboard);
1472
- mkdirSync(dirname2(configPath), { recursive: true });
1473
- writeFileSync2(configPath, `${JSON.stringify(next, null, 2)}
1516
+ mkdirSync2(dirname2(configPath), { recursive: true });
1517
+ writeFileSync3(configPath, `${JSON.stringify(next, null, 2)}
1474
1518
  `);
1475
1519
  }
1476
1520
  function launchFromResolved(server) {
@@ -1529,13 +1573,19 @@ function readText(path) {
1529
1573
  return "";
1530
1574
  }
1531
1575
  }
1532
- function userCodexConfigPaths(home = homedir3()) {
1533
- return [join4(home, ".codex", "config.toml"), join4(home, ".config", "codex", "config.toml")];
1576
+ function userCodexConfigPaths(home = homedir4()) {
1577
+ const paths = [
1578
+ join5(home, ".codex", "config.toml"),
1579
+ join5(home, ".config", "codex", "config.toml")
1580
+ ];
1581
+ const codexHome = process.env.CODEX_HOME?.trim();
1582
+ if (codexHome) paths.unshift(join5(codexHome, "config.toml"));
1583
+ return paths;
1534
1584
  }
1535
- function userOpencodeConfigPaths(home = homedir3()) {
1585
+ function userOpencodeConfigPaths(home = homedir4()) {
1536
1586
  return [
1537
- join4(home, ".config", "opencode", "opencode.json"),
1538
- join4(home, ".config", "opencode", "opencode.jsonc")
1587
+ join5(home, ".config", "opencode", "opencode.json"),
1588
+ join5(home, ".config", "opencode", "opencode.jsonc")
1539
1589
  ];
1540
1590
  }
1541
1591
  function userMcpNamesToDisable(opts) {
@@ -1554,7 +1604,7 @@ function userMcpNamesToDisable(opts) {
1554
1604
  }
1555
1605
  return out;
1556
1606
  }
1557
- function listUserCodexMcpNames(home = homedir3()) {
1607
+ function listUserCodexMcpNames(home = homedir4()) {
1558
1608
  const names = [];
1559
1609
  for (const path of userCodexConfigPaths(home)) {
1560
1610
  if (!existsSync5(path)) continue;
@@ -1562,7 +1612,7 @@ function listUserCodexMcpNames(home = homedir3()) {
1562
1612
  }
1563
1613
  return names;
1564
1614
  }
1565
- function listUserOpencodeMcpNames(home = homedir3()) {
1615
+ function listUserOpencodeMcpNames(home = homedir4()) {
1566
1616
  const names = [];
1567
1617
  for (const path of userOpencodeConfigPaths(home)) {
1568
1618
  if (!existsSync5(path)) continue;
@@ -1570,12 +1620,12 @@ function listUserOpencodeMcpNames(home = homedir3()) {
1570
1620
  }
1571
1621
  return names;
1572
1622
  }
1573
- function userClaudeMcpConfigObject(home = homedir3()) {
1574
- const claudePath = home === homedir3() ? userClaudeMcpConfigPath() : join4(home, ".claude.json");
1623
+ function userClaudeMcpConfigObject(home = homedir4()) {
1624
+ const claudePath = home === homedir4() ? userClaudeMcpConfigPath() : join5(home, ".claude.json");
1575
1625
  if (!existsSync5(claudePath)) return {};
1576
1626
  return asObject2(asObject2(readJsonObject(claudePath)).mcpServers);
1577
1627
  }
1578
- function listUserClaudeMcpServerEntries(home = homedir3(), projectDirs) {
1628
+ function listUserClaudeMcpServerEntries(home = homedir4(), projectDirs) {
1579
1629
  const out = {};
1580
1630
  for (const [name, entry] of Object.entries(
1581
1631
  listEnabledClaudePluginMcpServers({ home, projectDirs })
@@ -1613,7 +1663,7 @@ function toCodexUnattendedAppsArgs() {
1613
1663
  }
1614
1664
 
1615
1665
  // src/mcp-ui/proxy-http.ts
1616
- import { randomBytes, randomUUID } from "crypto";
1666
+ import { randomBytes as randomBytes2, randomUUID } from "crypto";
1617
1667
  import { createServer } from "http";
1618
1668
  import { Server as Server2 } from "@modelcontextprotocol/sdk/server/index.js";
1619
1669
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
@@ -1710,7 +1760,7 @@ function listedTool(tool) {
1710
1760
 
1711
1761
  // src/mcp-ui/proxy-http.ts
1712
1762
  async function listenMcpUiProxy(opts) {
1713
- const token = randomBytes(24).toString("hex");
1763
+ const token = randomBytes2(24).toString("hex");
1714
1764
  const transports = /* @__PURE__ */ new Map();
1715
1765
  const httpServer = createServer((req, res) => {
1716
1766
  void handle(req, res);
@@ -2083,7 +2133,7 @@ var singleton;
2083
2133
  function getMcpUiHost() {
2084
2134
  if (!singleton) {
2085
2135
  singleton = new McpUiHost({
2086
- entries: (projectDirs) => listUserClaudeMcpServerEntries(homedir4(), projectDirs)
2136
+ entries: (projectDirs) => listUserClaudeMcpServerEntries(homedir5(), projectDirs)
2087
2137
  });
2088
2138
  }
2089
2139
  return singleton;
@@ -2091,7 +2141,7 @@ function getMcpUiHost() {
2091
2141
  async function proxyClaudeUserMcp(orchestrator, projectDirs) {
2092
2142
  if (orchestrator) return {};
2093
2143
  const dirs = projectDirs.filter((d) => typeof d === "string" && d.length > 0);
2094
- return getMcpUiHost().proxyEntries(listUserClaudeMcpServerEntries(homedir4(), dirs), dirs);
2144
+ return getMcpUiHost().proxyEntries(listUserClaudeMcpServerEntries(homedir5(), dirs), dirs);
2095
2145
  }
2096
2146
  function closeMcpUiHost() {
2097
2147
  const host = singleton;
@@ -2110,16 +2160,6 @@ function planModeTurnInstruction(planMode) {
2110
2160
  return planMode ? PLAN_MODE_INSTRUCTION : PLAN_MODE_OFF_INSTRUCTION;
2111
2161
  }
2112
2162
  function permissionMode(thread) {
2113
- if (thread.sourceType === "orchestration") {
2114
- return {
2115
- claude: "acceptEdits",
2116
- opencodePermission: JSON.stringify({
2117
- edit: "allow",
2118
- bash: { "*": "allow", "rm -rf *": "deny" }
2119
- }),
2120
- codexSandbox: "danger-full-access"
2121
- };
2122
- }
2123
2163
  if (thread.planMode) {
2124
2164
  return {
2125
2165
  claude: "plan",
@@ -2131,6 +2171,18 @@ function permissionMode(thread) {
2131
2171
  codexSandbox: "read-only"
2132
2172
  };
2133
2173
  }
2174
+ if (thread.sourceType === "orchestration") {
2175
+ return {
2176
+ claude: "acceptEdits",
2177
+ // Unattended coordinators cannot answer permission prompts. Explicit
2178
+ // allows override the user's OpenCode denies for this process only.
2179
+ opencodePermission: JSON.stringify({
2180
+ edit: "allow",
2181
+ bash: { "*": "allow" }
2182
+ }),
2183
+ codexSandbox: "danger-full-access"
2184
+ };
2185
+ }
2134
2186
  if (thread.autonomy === "full") {
2135
2187
  return {
2136
2188
  claude: "bypassPermissions",
@@ -2140,10 +2192,7 @@ function permissionMode(thread) {
2140
2192
  }
2141
2193
  return {
2142
2194
  claude: "acceptEdits",
2143
- opencodePermission: JSON.stringify({
2144
- edit: "allow",
2145
- bash: { "*": "allow", "rm -rf *": "deny" }
2146
- }),
2195
+ opencodePermission: JSON.stringify({}),
2147
2196
  codexSandbox: "workspace-write"
2148
2197
  };
2149
2198
  }
@@ -2164,7 +2213,7 @@ function agentRpcChildEnv(rpc, cwd) {
2164
2213
  // src/agents/claude-host.ts
2165
2214
  import { existsSync as existsSync6 } from "fs";
2166
2215
  import { createRequire as createRequire2 } from "module";
2167
- import { dirname as dirname3, join as join5 } from "path";
2216
+ import { dirname as dirname3, join as join6 } from "path";
2168
2217
  import { fileURLToPath as fileURLToPath2 } from "url";
2169
2218
  function claudePilotSdkAllowedTools() {
2170
2219
  return PILOT_TOOL_NAMES.map(
@@ -2192,17 +2241,17 @@ function entryDir() {
2192
2241
  function claudeRunnerPath() {
2193
2242
  const packagedDir = packagedCursorRuntimeDir();
2194
2243
  if (packagedDir) {
2195
- const packaged = join5(packagedDir, "core-dist", "agents", "claude-runner.js");
2244
+ const packaged = join6(packagedDir, "core-dist", "agents", "claude-runner.js");
2196
2245
  if (existsSync6(packaged)) return packaged;
2197
2246
  }
2198
2247
  const root = entryDir();
2199
2248
  const candidates = [
2200
- join5(root, "agents", "claude-runner.js"),
2201
- join5(root, "agents", "claude-runner.cjs"),
2202
- join5(root, "dist", "agents", "claude-runner.js"),
2203
- join5(root, "dist", "agents", "claude-runner.cjs"),
2204
- join5(root, "claude-runner.ts"),
2205
- join5(root, "src", "agents", "claude-runner.ts")
2249
+ join6(root, "agents", "claude-runner.js"),
2250
+ join6(root, "agents", "claude-runner.cjs"),
2251
+ join6(root, "dist", "agents", "claude-runner.js"),
2252
+ join6(root, "dist", "agents", "claude-runner.cjs"),
2253
+ join6(root, "claude-runner.ts"),
2254
+ join6(root, "src", "agents", "claude-runner.ts")
2206
2255
  ];
2207
2256
  for (const candidate of candidates) {
2208
2257
  if (existsSync6(candidate)) return candidate;
@@ -2281,7 +2330,8 @@ function sessionCostUsdFromClaudeResult(obj) {
2281
2330
  function claudeResultErrorDetail(obj) {
2282
2331
  const isError = Boolean(obj.is_error) || typeof obj.subtype === "string" && /^error/i.test(obj.subtype);
2283
2332
  const fromResult = typeof obj.result === "string" ? obj.result.trim() : "";
2284
- if (fromResult && (isError || looksLikeAgentFailureMessage(fromResult))) {
2333
+ const shortFailure = fromResult.length > 0 && fromResult.length <= 300 && !fromResult.includes("\n") && looksLikeAgentFailureMessage(fromResult);
2334
+ if (fromResult && (isError || shortFailure)) {
2285
2335
  return fromResult;
2286
2336
  }
2287
2337
  if (!isError) return null;
@@ -2528,7 +2578,7 @@ function eventsFromClaudeSystem(obj) {
2528
2578
  data: `Context compressed${trigger}`,
2529
2579
  replace: true
2530
2580
  };
2531
- if (meta.postTokens != null && meta.postTokens > 0) {
2581
+ if (meta.postTokens != null && meta.postTokens > 0 && !parentId) {
2532
2582
  return [
2533
2583
  thinking,
2534
2584
  {
@@ -2609,7 +2659,7 @@ var claudeAdapter = {
2609
2659
  );
2610
2660
  }
2611
2661
  const mode = permissionMode(thread);
2612
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-RHEO55B4.js");
2662
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-UIEXAG2B.js");
2613
2663
  const isOrchestrator = isOrchestratorThread2(thread);
2614
2664
  const rpc = worktreeAgentRpc(isOrchestrator);
2615
2665
  const injectedServers = await buildInjectedMcpServers({
@@ -2709,6 +2759,7 @@ var claudeAdapter = {
2709
2759
  cwd: thread.worktreePath,
2710
2760
  stdin: useStdin ? `${promptText}
2711
2761
  ` : void 0,
2762
+ ...mcpConfigPath ? { cleanupDirs: [dirname4(mcpConfigPath)] } : {},
2712
2763
  // Nested Task/Agent thinking+text in stream-json (Claude Code 2.1.211+).
2713
2764
  // Raise the -p background-agent wait so long TaskOutput polls are not
2714
2765
  // abandoned at Claude Code’s 10-minute default.
@@ -2738,9 +2789,17 @@ var claudeAdapter = {
2738
2789
  Array.isArray(message?.content) ? message.content : void 0,
2739
2790
  parentId
2740
2791
  );
2741
- if (obj.type === "assistant") {
2792
+ if (obj.type === "assistant" && !parentId) {
2742
2793
  const usage = usageFromClaude(message?.usage);
2743
- if (usage) events.push({ type: "usage", data: usage, scope: "request" });
2794
+ const messageId = message && typeof message.id === "string" ? message.id : void 0;
2795
+ if (usage) {
2796
+ events.push({
2797
+ type: "usage",
2798
+ data: usage,
2799
+ scope: "request",
2800
+ ...messageId ? { messageId } : {}
2801
+ });
2802
+ }
2744
2803
  }
2745
2804
  if (events.length === 0) return null;
2746
2805
  return events.length === 1 ? events[0] : events;
@@ -2827,56 +2886,47 @@ var claudeAdapter = {
2827
2886
  return { file: claude, args, cwd: thread.worktreePath };
2828
2887
  },
2829
2888
  async listLinearIssues(_repoPath) {
2830
- const claude = resolveClaudeExecutable();
2831
- const prompt = "List my assigned Linear issues as JSON array only, no markdown. Each item: id, identifier, title, url, labels (string[]).";
2832
- const { stdout, exitCode } = await run(
2833
- claude,
2834
- [
2835
- "-p",
2836
- prompt,
2837
- "--output-format",
2838
- "json",
2839
- "--permission-mode",
2840
- "bypassPermissions",
2841
- "--allowedTools",
2842
- "mcp__linear__*"
2843
- ],
2844
- { reject: false }
2845
- );
2846
- if (exitCode !== 0) return [];
2847
- return parseIssuesJson(stdout);
2889
+ const { listAssignedLinearIssues: listAssignedLinearIssues2 } = await import("./linear-list-A37WLUBO.js");
2890
+ return listAssignedLinearIssues2();
2848
2891
  }
2849
2892
  };
2850
- function parseIssuesJson(raw) {
2851
- const text = raw.trim();
2852
- const candidates = [text];
2853
- const match = text.match(/\[[\s\S]*\]/);
2854
- if (match) candidates.push(match[0]);
2855
- for (const c of candidates) {
2856
- try {
2857
- const parsed = JSON.parse(c);
2858
- if (Array.isArray(parsed)) {
2859
- return parsed.map((item) => ({
2860
- id: String(item.id ?? item.identifier ?? ""),
2861
- identifier: String(item.identifier ?? item.id ?? ""),
2862
- title: String(item.title ?? ""),
2863
- url: String(item.url ?? ""),
2864
- labels: Array.isArray(item.labels) ? item.labels.map(String) : []
2865
- }));
2866
- }
2867
- if (parsed && typeof parsed === "object" && typeof parsed.result === "string") {
2868
- return parseIssuesJson(parsed.result);
2869
- }
2870
- } catch {
2893
+
2894
+ // src/agents/codex.ts
2895
+ import { existsSync as existsSync8, statSync } from "fs";
2896
+ import { homedir as homedir6 } from "os";
2897
+ import { join as join7 } from "path";
2898
+
2899
+ // src/agents/codex-items.ts
2900
+ function eventsFromCodexItem(eventType, item) {
2901
+ const itemType = item.type ?? item.item_type;
2902
+ if (itemType === "reasoning" && typeof item.text === "string" && item.text) {
2903
+ return { type: "thinking", data: item.text };
2904
+ }
2905
+ if (itemType !== "file_change" || !item.id) return null;
2906
+ const changes = Array.isArray(item.changes) ? item.changes : [];
2907
+ const paths = changes.map((change) => typeof change?.path === "string" ? change.path : "").filter(Boolean);
2908
+ const added = changes.some((change) => change?.kind === "add");
2909
+ const events = [
2910
+ {
2911
+ type: "tool_use",
2912
+ id: item.id,
2913
+ name: added ? "Write" : "Edit",
2914
+ input: paths.length ? { paths } : void 0
2871
2915
  }
2916
+ ];
2917
+ const finished = eventType === "item.completed" || item.status === "completed" || item.status === "failed";
2918
+ if (finished) {
2919
+ events.push({
2920
+ type: "tool_result",
2921
+ id: item.id,
2922
+ content: paths.join("\n") || void 0,
2923
+ isError: item.status === "failed"
2924
+ });
2872
2925
  }
2873
- return [];
2926
+ return events.length === 1 ? events[0] : events;
2874
2927
  }
2875
2928
 
2876
2929
  // src/agents/codex.ts
2877
- import { existsSync as existsSync8, readFileSync as readFileSync4, statSync } from "fs";
2878
- import { homedir as homedir5 } from "os";
2879
- import { join as join6 } from "path";
2880
2930
  var CODEX_PROMPT_ARG_MAX = 2e5;
2881
2931
  var FALLBACK_CODEX_MODELS = [
2882
2932
  { id: "gpt-5.6-sol", displayName: "GPT-5.6 Sol" },
@@ -2921,25 +2971,19 @@ async function listCodexModels() {
2921
2971
  return cachedCodexModels?.models ?? FALLBACK_CODEX_MODELS;
2922
2972
  }
2923
2973
  }
2924
- function usageFromCodex(usage) {
2974
+ function usageFromCodex(usage, asContext = false) {
2925
2975
  if (!usage) return null;
2926
- return fromInclusiveInputUsage({
2976
+ const mapped = fromInclusiveInputUsage({
2927
2977
  inputTokens: Number(usage.input_tokens ?? 0),
2928
2978
  outputTokens: Number(usage.output_tokens ?? 0),
2929
2979
  cachedInputTokens: Number(usage.cached_input_tokens ?? 0)
2930
2980
  });
2981
+ if (!mapped || !asContext) return mapped;
2982
+ const occ = requestOccupancy(mapped);
2983
+ return occ > 0 ? { ...mapped, lastRequestTokens: occ } : mapped;
2931
2984
  }
2932
- function codexConfigHasNetworkAccess() {
2933
- const candidates = [
2934
- join6(homedir5(), ".codex", "config.toml"),
2935
- join6(homedir5(), ".config", "codex", "config.toml")
2936
- ];
2937
- for (const path of candidates) {
2938
- if (!existsSync8(path)) continue;
2939
- const text = readFileSync4(path, "utf8");
2940
- if (/network_access\s*=\s*true/.test(text)) return true;
2941
- }
2942
- return false;
2985
+ function codexHomeDir() {
2986
+ return process.env.CODEX_HOME?.trim() || join7(homedir6(), ".codex");
2943
2987
  }
2944
2988
  function unwrapCodexMcpResult(result) {
2945
2989
  if (result == null) return void 0;
@@ -2968,7 +3012,7 @@ function asRecord3(value) {
2968
3012
  return void 0;
2969
3013
  }
2970
3014
  function codexLooksAuthenticated() {
2971
- const authPath = join6(homedir5(), ".codex", "auth.json");
3015
+ const authPath = join7(codexHomeDir(), "auth.json");
2972
3016
  if (!existsSync8(authPath)) return false;
2973
3017
  try {
2974
3018
  return statSync(authPath).size > 2;
@@ -3007,18 +3051,13 @@ var codexAdapter = {
3007
3051
  const authenticated = codexLooksAuthenticated();
3008
3052
  const linearMcp = false;
3009
3053
  const warnings = [];
3010
- if (!codexConfigHasNetworkAccess()) {
3011
- warnings.push(
3012
- "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."
3013
- );
3014
- }
3015
3054
  return {
3016
3055
  agent: "codex",
3017
3056
  installed: true,
3018
3057
  authenticated,
3019
3058
  linearMcp,
3020
3059
  warnings,
3021
- reason: authenticated ? void 0 : "Codex auth not found \u2014 run `codex login` (expected ~/.codex/auth.json)"
3060
+ reason: authenticated ? void 0 : `Codex auth not found \u2014 run \`codex login\` (expected ${join7(codexHomeDir(), "auth.json")})`
3022
3061
  };
3023
3062
  },
3024
3063
  async buildTurn(thread, input) {
@@ -3043,6 +3082,12 @@ var codexAdapter = {
3043
3082
  threadId: thread.id
3044
3083
  });
3045
3084
  const isolatePlugins = isOrchestrator || Boolean(thread.isolateCodexPlugins) || Boolean(normalizeTurnInput(input).isolateCodexPlugins);
3085
+ const gitEnv = await resolveAgentGitAuthEnv(process.env, {
3086
+ cwd: thread.worktreePath
3087
+ });
3088
+ const writableRoots = mode.codexSandbox === "workspace-write" ? await resolveCodexGitWritableRoots(thread.worktreePath) : [];
3089
+ const secretProfile = writeCodexMcpSecretProfile(injected);
3090
+ const effort = thread.effort?.trim() ?? "";
3046
3091
  const mcpOverrides = [
3047
3092
  // Worktree first try keeps plugins (Claude connectors). Coordinators
3048
3093
  // isolate. After a fatal plugin MCP, the orchestrator retries with
@@ -3059,6 +3104,7 @@ var codexAdapter = {
3059
3104
  const execOpts = [
3060
3105
  // Global orchestration cwd is not a git repo; without this Codex ≥0.147
3061
3106
  // refuses to start ("Not inside a trusted directory").
3107
+ ...secretProfile ? ["-p", secretProfile.profile] : [],
3062
3108
  "--skip-git-repo-check",
3063
3109
  "--cd",
3064
3110
  thread.worktreePath,
@@ -3068,14 +3114,16 @@ var codexAdapter = {
3068
3114
  // `codex exec` rejects `--ask-for-approval` (global-only on newer CLIs).
3069
3115
  "-c",
3070
3116
  'approval_policy="never"',
3071
- // Seatbelt cannot use the login Keychain; inherit GH_CONFIG_DIR / GIT_CONFIG_*.
3072
- // Default policy also strips *TOKEN*. Linked worktrees need the main
3073
- // repo `.git` (+ `.git/worktrees/<name>`) as writable_roots so git commit
3074
- // can create index.lock.
3117
+ // Seatbelt cannot use the login Keychain. inherit=all keeps GH_CONFIG_DIR
3118
+ // and GIT_CONFIG_*. Default excludes still strip *TOKEN*/*SECRET*/*KEY*;
3119
+ // GIT_CONFIG_KEY_n is re-set because it matches *KEY*. Linked worktrees
3120
+ // need the main repo `.git` as writable_roots so git commit can lock.
3075
3121
  ...codexUnattendedGitConfigArgs(mode.codexSandbox, {
3076
- writableRoots: mode.codexSandbox === "workspace-write" ? await resolveCodexGitWritableRoots(thread.worktreePath) : []
3122
+ writableRoots,
3123
+ preserveEnv: gitEnv
3077
3124
  }),
3078
3125
  ...model ? ["--model", model] : [],
3126
+ ...effort ? ["-c", `model_reasoning_effort=${JSON.stringify(effort)}`] : [],
3079
3127
  ...mcpOverrides
3080
3128
  ];
3081
3129
  const args = sessionId ? ["exec", ...execOpts, "resume", sessionId, promptArg] : ["exec", ...execOpts, promptArg];
@@ -3084,7 +3132,8 @@ var codexAdapter = {
3084
3132
  args,
3085
3133
  cwd: thread.worktreePath,
3086
3134
  stdin: useStdin ? `${prompt}
3087
- ` : void 0
3135
+ ` : void 0,
3136
+ ...secretProfile ? { cleanupDirs: [secretProfile.file] } : {}
3088
3137
  };
3089
3138
  },
3090
3139
  parseEvent(line) {
@@ -3105,8 +3154,10 @@ var codexAdapter = {
3105
3154
  if (typeof obj.item === "object" && obj.item !== null) {
3106
3155
  const item = obj.item;
3107
3156
  const itemType = item.type ?? item.item_type;
3157
+ const mapped = eventsFromCodexItem(type, item);
3158
+ if (mapped) return mapped;
3108
3159
  if (itemType === "error") {
3109
- const detail = item.message?.trim() || extractJsonErrorMessage(obj) || "Codex item error";
3160
+ const detail = (typeof item.message === "string" ? item.message.trim() : "") || extractJsonErrorMessage(obj) || "Codex item error";
3110
3161
  return { type: "stderr", data: detail };
3111
3162
  }
3112
3163
  if (itemType === "agent_message" && item.text) {
@@ -3135,14 +3186,14 @@ var codexAdapter = {
3135
3186
  const events = [
3136
3187
  { type: "tool_use", id: item.id, name: "Bash", input }
3137
3188
  ];
3138
- const finished = type === "item.completed" || item.status === "completed" || item.status === "failed";
3189
+ const finished = type === "item.completed" || item.status === "completed" || item.status === "failed" || item.status === "declined";
3139
3190
  const output = typeof item.aggregated_output === "string" && item.aggregated_output ? item.aggregated_output : void 0;
3140
3191
  if (finished) {
3141
3192
  events.push({
3142
3193
  type: "tool_result",
3143
3194
  id: item.id,
3144
3195
  content: output,
3145
- isError: item.status === "failed"
3196
+ isError: item.status === "failed" || item.status === "declined"
3146
3197
  });
3147
3198
  } else if (output) {
3148
3199
  events.push({
@@ -3185,7 +3236,7 @@ var codexAdapter = {
3185
3236
  return events.length === 1 ? events[0] : events;
3186
3237
  }
3187
3238
  if (item.status === "failed") {
3188
- const detail = item.message?.trim() || extractJsonErrorMessage(item) || `Codex ${itemType ?? "item"} failed`;
3239
+ const detail = (typeof item.message === "string" ? item.message.trim() : "") || extractJsonErrorMessage(item) || `Codex ${itemType ?? "item"} failed`;
3189
3240
  return { type: "stderr", data: detail };
3190
3241
  }
3191
3242
  }
@@ -3194,7 +3245,8 @@ var codexAdapter = {
3194
3245
  return { type: "session_id", data: sid };
3195
3246
  }
3196
3247
  if (type === "turn.completed" || type === "turn_completed") {
3197
- const usage = usageFromCodex(obj.usage);
3248
+ const payload = obj;
3249
+ const usage = payload.last_token_usage ? usageFromCodex(payload.last_token_usage, true) : usageFromCodex(payload.usage);
3198
3250
  return usage ? { type: "usage", data: usage, scope: "turn" } : null;
3199
3251
  }
3200
3252
  if (typeof obj.content === "string" && obj.content.trim()) {
@@ -3217,7 +3269,7 @@ var codexAdapter = {
3217
3269
  if (sessionId) {
3218
3270
  return {
3219
3271
  file: codex,
3220
- args: ["exec", "--cd", thread.worktreePath, "resume", sessionId],
3272
+ args: ["resume", sessionId],
3221
3273
  cwd: thread.worktreePath
3222
3274
  };
3223
3275
  }
@@ -3228,36 +3280,14 @@ var codexAdapter = {
3228
3280
  };
3229
3281
  },
3230
3282
  async listLinearIssues(_repoPath) {
3231
- const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
3232
- const { stdout, exitCode } = await run(
3233
- resolveAgentExecutable("codex"),
3234
- [
3235
- "exec",
3236
- "--json",
3237
- "--sandbox",
3238
- "read-only",
3239
- "-c",
3240
- 'approval_policy="never"',
3241
- prompt
3242
- ],
3243
- { reject: false }
3244
- );
3245
- if (exitCode !== 0) return [];
3246
- const match = stdout.match(/\[[\s\S]*\]/);
3247
- if (!match) return [];
3248
- try {
3249
- const parsed = JSON.parse(match[0]);
3250
- return Array.isArray(parsed) ? parsed : [];
3251
- } catch {
3252
- return [];
3253
- }
3283
+ return listAssignedLinearIssues();
3254
3284
  }
3255
3285
  };
3256
3286
 
3257
3287
  // src/agents/cursor.ts
3258
3288
  import { existsSync as existsSync9 } from "fs";
3259
3289
  import { createRequire as createRequire3 } from "module";
3260
- import { dirname as dirname4, join as join7 } from "path";
3290
+ import { dirname as dirname5, join as join8 } from "path";
3261
3291
  import { fileURLToPath as fileURLToPath3 } from "url";
3262
3292
  var FALLBACK_CURSOR_MODELS = [
3263
3293
  { id: "default", displayName: "Auto" },
@@ -3309,11 +3339,11 @@ function entryDir2() {
3309
3339
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
3310
3340
  if (cjsDir) return cjsDir;
3311
3341
  try {
3312
- return dirname4(fileURLToPath3(import.meta.url));
3342
+ return dirname5(fileURLToPath3(import.meta.url));
3313
3343
  } catch {
3314
3344
  try {
3315
3345
  const req = createRequire3(process.cwd() + "/");
3316
- return dirname4(req.resolve("@sideboard-ai/core"));
3346
+ return dirname5(req.resolve("@sideboard-ai/core"));
3317
3347
  } catch {
3318
3348
  return process.cwd();
3319
3349
  }
@@ -3324,14 +3354,14 @@ function cursorRunnerPath() {
3324
3354
  if (packaged) return packaged;
3325
3355
  const root = entryDir2();
3326
3356
  const candidates = [
3327
- join7(root, "agents", "cursor-runner.js"),
3328
- join7(root, "agents", "cursor-runner.cjs"),
3357
+ join8(root, "agents", "cursor-runner.js"),
3358
+ join8(root, "agents", "cursor-runner.cjs"),
3329
3359
  // If somehow resolved from package root instead of dist/
3330
- join7(root, "dist", "agents", "cursor-runner.js"),
3331
- join7(root, "dist", "agents", "cursor-runner.cjs"),
3360
+ join8(root, "dist", "agents", "cursor-runner.js"),
3361
+ join8(root, "dist", "agents", "cursor-runner.cjs"),
3332
3362
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
3333
- join7(root, "cursor-runner.ts"),
3334
- join7(root, "src", "agents", "cursor-runner.ts")
3363
+ join8(root, "cursor-runner.ts"),
3364
+ join8(root, "src", "agents", "cursor-runner.ts")
3335
3365
  ];
3336
3366
  for (const candidate of candidates) {
3337
3367
  if (existsSync9(candidate)) return candidate;
@@ -3372,6 +3402,7 @@ var cursorAdapter = {
3372
3402
  },
3373
3403
  async buildTurn(thread, input) {
3374
3404
  const agentId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
3405
+ const fullPrompt = flattenTurnInput(input);
3375
3406
  const prompt = flattenTurnInput(dropCachedPrefixOnResume(input, agentId));
3376
3407
  const apiKey = resolveCursorApiKey() || void 0;
3377
3408
  const isOrchestrator = isOrchestratorThread(thread);
@@ -3388,6 +3419,7 @@ var cursorAdapter = {
3388
3419
  const mcpServers = toCursorMcpServers(injected);
3389
3420
  const req = {
3390
3421
  prompt,
3422
+ ...fullPrompt !== prompt ? { freshPrompt: fullPrompt } : {},
3391
3423
  cwd: thread.worktreePath,
3392
3424
  threadId: thread.id,
3393
3425
  agentId,
@@ -3414,8 +3446,9 @@ var cursorAdapter = {
3414
3446
  stdin: JSON.stringify(req),
3415
3447
  env: {
3416
3448
  ...launch.env,
3417
- ...cursorRipgrepEnv({ startFile: runner }),
3418
- ...apiKey ? { CURSOR_API_KEY: apiKey } : {}
3449
+ ...cursorRipgrepEnv({ startFile: runner })
3450
+ // API key stays on the stdin request. Do not copy it into the child env,
3451
+ // where `ps` and crash dumps can see it. The runner reads `req.apiKey`.
3419
3452
  }
3420
3453
  };
3421
3454
  },
@@ -3437,14 +3470,17 @@ var cursorAdapter = {
3437
3470
  };
3438
3471
 
3439
3472
  // src/agents/opencode.ts
3440
- import { existsSync as existsSync10 } from "fs";
3473
+ import { existsSync as existsSync11 } from "fs";
3474
+
3475
+ // src/agent-rpc/opencode-host.ts
3476
+ import { pathToFileURL } from "url";
3441
3477
 
3442
3478
  // src/agent-rpc/opencode-hook.ts
3443
- import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
3444
- import { join as join8 } from "path";
3479
+ import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync, writeFileSync as writeFileSync4 } from "fs";
3480
+ import { join as join9 } from "path";
3445
3481
  var OPENCODE_PLUGIN_SOURCE = `import { tool } from "@opencode-ai/plugin"
3446
3482
 
3447
- const URL = process.env[${JSON.stringify(AGENT_RPC_URL_ENV)}] || ""
3483
+ const RPC_URL = process.env[${JSON.stringify(AGENT_RPC_URL_ENV)}] || ""
3448
3484
  const TOKEN = process.env[${JSON.stringify(AGENT_RPC_TOKEN_ENV)}] || ""
3449
3485
  const CWD = process.env[${JSON.stringify(AGENT_RPC_CWD_ENV)}] || ""
3450
3486
 
@@ -3457,24 +3493,29 @@ function jsonError(err) {
3457
3493
  }
3458
3494
 
3459
3495
  function socketUrl() {
3460
- const u = new URL(URL)
3496
+ const u = new URL(RPC_URL)
3461
3497
  u.searchParams.set(${JSON.stringify(AGENT_RPC_TOKEN_QUERY)}, TOKEN)
3462
3498
  return u.toString()
3463
3499
  }
3464
3500
 
3465
3501
  function call(method, params) {
3466
- if (!URL || !TOKEN) {
3502
+ if (!RPC_URL || !TOKEN) {
3467
3503
  return Promise.resolve(jsonError(new Error("Agent RPC runtime is not running")))
3468
3504
  }
3505
+ const timeoutMs = method === "job.wait" ? 130000 : 30000
3469
3506
  return new Promise((resolve) => {
3470
3507
  let settled = false
3508
+ let ws
3509
+ let timer
3471
3510
  const done = (value) => {
3472
3511
  if (settled) return
3473
3512
  settled = true
3513
+ clearTimeout(timer)
3474
3514
  try { ws.close() } catch {}
3475
3515
  resolve(value)
3476
3516
  }
3477
- const ws = new WebSocket(socketUrl())
3517
+ timer = setTimeout(() => done(jsonError(new Error("Agent RPC timed out"))), timeoutMs)
3518
+ ws = new WebSocket(socketUrl())
3478
3519
  const id = Date.now()
3479
3520
  ws.addEventListener("open", () => {
3480
3521
  ws.send(JSON.stringify({ jsonrpc: "2.0", id, method, params, authToken: TOKEN }))
@@ -3546,12 +3587,19 @@ export const SideboardRpc = async (ctx) => {
3546
3587
  }
3547
3588
  `;
3548
3589
  function writeOpencodeRpcPlugin() {
3549
- const configDir = join8(appDataDir(), "agent-rpc", "opencode");
3550
- const pluginDir = join8(configDir, "plugins");
3551
- mkdirSync2(pluginDir, { recursive: true });
3552
- const pluginFile = join8(pluginDir, "sideboard-rpc.js");
3553
- writeFileSync3(pluginFile, OPENCODE_PLUGIN_SOURCE);
3554
- return { configDir, pluginFile };
3590
+ const pluginDir = join9(appDataDir(), "agent-rpc", "opencode");
3591
+ mkdirSync3(pluginDir, { recursive: true });
3592
+ const pluginFile = join9(pluginDir, "sideboard-rpc.js");
3593
+ if (existsSync10(pluginFile)) {
3594
+ try {
3595
+ if (readFileSync4(pluginFile, "utf8") === OPENCODE_PLUGIN_SOURCE) return pluginFile;
3596
+ } catch {
3597
+ }
3598
+ }
3599
+ const tmp = `${pluginFile}.${process.pid}.tmp`;
3600
+ writeFileSync4(tmp, OPENCODE_PLUGIN_SOURCE);
3601
+ renameSync(tmp, pluginFile);
3602
+ return pluginFile;
3555
3603
  }
3556
3604
 
3557
3605
  // src/agent-rpc/opencode-host.ts
@@ -3574,10 +3622,9 @@ async function buildOpencodeHostEnv(thread) {
3574
3622
  const config = injected.length > 0 || disableNames.length > 0 ? JSON.parse(toOpencodeMcpConfigContent(injected, { disableNames })) : {};
3575
3623
  const env = {};
3576
3624
  if (rpc) {
3577
- const { configDir, pluginFile } = writeOpencodeRpcPlugin();
3578
- env.OPENCODE_CONFIG_DIR = configDir;
3625
+ const pluginFile = writeOpencodeRpcPlugin();
3579
3626
  Object.assign(env, agentRpcChildEnv(rpc, thread.worktreePath));
3580
- config.plugin = [pluginFile];
3627
+ config.plugin = [pathToFileURL(pluginFile).href];
3581
3628
  }
3582
3629
  if (Object.keys(config).length > 0) {
3583
3630
  env.OPENCODE_CONFIG_CONTENT = JSON.stringify(config);
@@ -3644,7 +3691,7 @@ async function listOpencodeModels() {
3644
3691
  if (opencode === "opencode") {
3645
3692
  const which = await run("which", ["opencode"], { reject: false });
3646
3693
  if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
3647
- } else if (!existsSync10(opencode)) {
3694
+ } else if (!existsSync11(opencode)) {
3648
3695
  return FALLBACK_OPENCODE_MODELS;
3649
3696
  }
3650
3697
  const listed = await run(opencode, ["models"], { reject: false });
@@ -3679,7 +3726,7 @@ var opencodeAdapter = {
3679
3726
  async detect() {
3680
3727
  const opencode = resolveAgentExecutable("opencode");
3681
3728
  if (opencode !== "opencode") {
3682
- if (!existsSync10(opencode)) {
3729
+ if (!existsSync11(opencode)) {
3683
3730
  return {
3684
3731
  agent: "opencode",
3685
3732
  installed: false,
@@ -3733,6 +3780,11 @@ var opencodeAdapter = {
3733
3780
  if (model) {
3734
3781
  args.push("--model", model);
3735
3782
  }
3783
+ args.push("--thinking");
3784
+ const variant = thread.effort?.trim() ?? "";
3785
+ if (variant && /^(minimal|low|medium|high|max|xhigh)$/i.test(variant)) {
3786
+ args.push("--variant", variant);
3787
+ }
3736
3788
  const hostEnv = await buildOpencodeHostEnv(thread);
3737
3789
  return {
3738
3790
  file: resolveAgentExecutable("opencode"),
@@ -3765,6 +3817,10 @@ var opencodeAdapter = {
3765
3817
  const text = obj.part?.text ?? obj.text;
3766
3818
  if (text) return { type: "stdout", data: text };
3767
3819
  }
3820
+ if (obj.type === "reasoning" || obj.type === "thinking") {
3821
+ const text = obj.part?.text ?? obj.text;
3822
+ if (typeof text === "string" && text) return { type: "thinking", data: text };
3823
+ }
3768
3824
  if (obj.type === "tool_use") {
3769
3825
  const part = obj.part;
3770
3826
  const name = part?.tool ?? part?.name ?? obj.tool ?? obj.name ?? "tool";
@@ -3880,11 +3936,14 @@ var opencodeAdapter = {
3880
3936
  const listed = await run(
3881
3937
  resolveAgentExecutable("opencode"),
3882
3938
  ["session", "list", "--format", "json"],
3883
- { cwd: worktreePath, reject: false }
3939
+ { cwd: worktreePath, reject: false, timeoutMs: 8e3 }
3884
3940
  );
3885
- if (listed.exitCode === 0 && listed.stdout.trim()) {
3941
+ if (listed.exitCode === 0) {
3942
+ const raw = listed.stdout.trim();
3943
+ if (!raw) return null;
3886
3944
  try {
3887
- const sessions = JSON.parse(listed.stdout);
3945
+ const sessions = JSON.parse(raw);
3946
+ if (Array.isArray(sessions) && sessions.length === 0) return null;
3888
3947
  if (Array.isArray(sessions) && sessions.length > 0) {
3889
3948
  const norm = (p) => p.replace(/\/+$/, "");
3890
3949
  const wt = norm(worktreePath);
@@ -3918,34 +3977,8 @@ var opencodeAdapter = {
3918
3977
  };
3919
3978
  },
3920
3979
  async listLinearIssues(_repoPath) {
3921
- const prompt = "List my assigned Linear issues as JSON array only: id, identifier, title, url, labels.";
3922
- const { stdout, exitCode } = await run(
3923
- resolveAgentExecutable("opencode"),
3924
- ["run", prompt, "--format", "json"],
3925
- {
3926
- reject: false,
3927
- env: { OPENCODE_PERMISSION: JSON.stringify({ "*": "allow" }) }
3928
- }
3929
- );
3930
- if (exitCode !== 0) return [];
3931
- const texts = [];
3932
- for (const line of stdout.split("\n")) {
3933
- try {
3934
- const obj = JSON.parse(line);
3935
- if (obj.type === "text") {
3936
- texts.push(obj.part?.text ?? obj.text ?? "");
3937
- }
3938
- } catch {
3939
- }
3940
- }
3941
- const joined = texts.join("");
3942
- const match = joined.match(/\[[\s\S]*\]/);
3943
- if (!match) return [];
3944
- try {
3945
- return JSON.parse(match[0]);
3946
- } catch {
3947
- return [];
3948
- }
3980
+ const { listAssignedLinearIssues: listAssignedLinearIssues2 } = await import("./linear-list-A37WLUBO.js");
3981
+ return listAssignedLinearIssues2();
3949
3982
  }
3950
3983
  };
3951
3984
 
@@ -4344,9 +4377,9 @@ function formatClaudeUsageOverLimitWait(windows, now = /* @__PURE__ */ new Date(
4344
4377
  }
4345
4378
 
4346
4379
  // src/agents/claude-usage-client.ts
4347
- import { existsSync as existsSync11, readFileSync as readFileSync5 } from "fs";
4348
- import { homedir as homedir6 } from "os";
4349
- import { join as join9 } from "path";
4380
+ import { existsSync as existsSync12, readFileSync as readFileSync5 } from "fs";
4381
+ import { homedir as homedir7 } from "os";
4382
+ import { join as join10 } from "path";
4350
4383
  var CLAUDE_OAUTH_USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
4351
4384
  var CLAUDE_USAGE_TTL_MS = 9e4;
4352
4385
  var CLAUDE_USAGE_ERROR_TTL_MS = 5 * 6e4;
@@ -4386,12 +4419,12 @@ function accessTokenFromCredentialsJson(raw) {
4386
4419
  }
4387
4420
  }
4388
4421
  function claudeCredentialsPath(configDir) {
4389
- const root = configDir?.trim() || process.env.CLAUDE_CONFIG_DIR?.trim() || join9(homedir6(), ".claude");
4390
- return join9(root, ".credentials.json");
4422
+ const root = configDir?.trim() || process.env.CLAUDE_CONFIG_DIR?.trim() || join10(homedir7(), ".claude");
4423
+ return join10(root, ".credentials.json");
4391
4424
  }
4392
4425
  async function readFileAccessToken(configDir) {
4393
4426
  const path = claudeCredentialsPath(configDir);
4394
- if (!existsSync11(path)) return null;
4427
+ if (!existsSync12(path)) return null;
4395
4428
  try {
4396
4429
  return accessTokenFromCredentialsJson(readFileSync5(path, "utf8"));
4397
4430
  } catch {