@sideboard-ai/core 0.1.79 → 0.1.83

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 (34) hide show
  1. package/dist/agents/cursor-runner.cjs +18 -0
  2. package/dist/agents/cursor-runner.js +4 -0
  3. package/dist/{agents-EWPHOM6Y.js → agents-3YPUZME7.js} +6 -5
  4. package/dist/{agents-GRAPUXWW.js → agents-4KRD46KG.js} +5 -5
  5. package/dist/{app-settings-NILNWNNQ.js → app-settings-GVSOIJLZ.js} +1 -1
  6. package/dist/{app-settings-6IOQYGBK.js → app-settings-MQXL7OUF.js} +2 -1
  7. package/dist/{chunk-6T2SKGCS.js → chunk-DJFGX4RT.js} +3 -3
  8. package/dist/{chunk-HCGEFU3J.js → chunk-E2MIA7DO.js} +13 -14
  9. package/dist/{chunk-HSLQXL6M.js → chunk-ERJS3ZDP.js} +13 -14
  10. package/dist/{chunk-YVVXWWCC.js → chunk-GD2FM6FN.js} +81 -49
  11. package/dist/{chunk-FUUVPN4A.js → chunk-HBBXS2FR.js} +78 -49
  12. package/dist/chunk-IZ7RPF54.js +36 -0
  13. package/dist/{chunk-P33ZQ7ZC.js → chunk-JMRJ4F5B.js} +70 -25
  14. package/dist/{chunk-SHCR6RPU.js → chunk-JW6YFPQE.js} +83 -24
  15. package/dist/{chunk-PW5YHHP3.js → chunk-LVTNWH7B.js} +2 -2
  16. package/dist/{chunk-5LXWTU3J.js → chunk-NXXT5SE3.js} +3 -3
  17. package/dist/{chunk-5VTWBI3I.js → chunk-RS54WYYH.js} +2 -2
  18. package/dist/{chunk-XKNBSYA7.js → chunk-UHGN4KCL.js} +35 -1
  19. package/dist/{chunk-IFPN6TER.js → chunk-YO3CYL6B.js} +4 -1
  20. package/dist/{coordinator-prompt-2OVON2LQ.js → coordinator-prompt-46JE4NQR.js} +4 -3
  21. package/dist/{coordinator-prompt-K2R34A5T.js → coordinator-prompt-6ICA54JR.js} +3 -3
  22. package/dist/{global-workspace-VG44RZUH.js → global-workspace-GSLCEB5E.js} +5 -4
  23. package/dist/{global-workspace-RI367AM6.js → global-workspace-OBRWUPZG.js} +4 -4
  24. package/dist/index.cjs +268 -151
  25. package/dist/index.d.cts +52 -11
  26. package/dist/index.d.ts +52 -11
  27. package/dist/index.js +87 -87
  28. package/dist/mcp/run-stdio.cjs +249 -141
  29. package/dist/mcp/run-stdio.js +66 -76
  30. package/dist/{workspaces-TYPJNUSM.js → workspaces-7B3PTEF4.js} +6 -5
  31. package/dist/{workspaces-BQWQEZWE.js → workspaces-RJIWQB6J.js} +5 -5
  32. package/dist/{worktree-5VLLFI5W.js → worktree-HSN5LWY6.js} +3 -2
  33. package/dist/{worktree-UNSOCYZU.js → worktree-U3UIID2K.js} +2 -2
  34. package/package.json +1 -1
@@ -14,7 +14,7 @@ import {
14
14
  import {
15
15
  getGithubGitAuthMode,
16
16
  getGithubPat
17
- } from "./chunk-XKNBSYA7.js";
17
+ } from "./chunk-UHGN4KCL.js";
18
18
  import {
19
19
  worktreesRoot
20
20
  } from "./chunk-7MV3RXSC.js";
@@ -884,6 +884,19 @@ function formatGhLandError(raw, opts) {
884
884
  }
885
885
  return detail || "Failed to create or update pull request";
886
886
  }
887
+ function isPrNotMergeableError(text) {
888
+ return /not mergeable|cannot be cleanly created|cannot merge cleanly|Merge conflict|\bCONFLICTING\b|must be (updated|rebased)|branch is out of date|needs? to be (updated|rebased)|Resolve conflicts or update the branch/i.test(
889
+ text
890
+ );
891
+ }
892
+ function formatMergePrError(raw) {
893
+ const trimmed = raw.trim();
894
+ if (!trimmed) return "gh pr merge failed";
895
+ if (isPrNotMergeableError(trimmed)) {
896
+ return "This pull request cannot merge cleanly into the base branch. Resolve conflicts or update the branch, then retry.";
897
+ }
898
+ return extractGhErrorDetail(trimmed) || trimmed;
899
+ }
887
900
 
888
901
  // src/git/git-auth-mode.ts
889
902
  var HTTPS_REWRITE = [
@@ -1566,6 +1579,41 @@ ${result.stderr}`;
1566
1579
  ].slice(0, 20) : [];
1567
1580
  return { conflicting, base: baseName, files };
1568
1581
  }
1582
+ async function probeLocalMergeGate(cwd, gate) {
1583
+ const mergeable = (gate?.mergeable ?? "").toUpperCase();
1584
+ const mergeState = (gate?.mergeStateStatus ?? "").toUpperCase();
1585
+ const alreadyConflicting = mergeable === "CONFLICTING" || mergeState === "DIRTY";
1586
+ const inQueue = gate ? prIsInMergeQueue(gate) : false;
1587
+ if (alreadyConflicting || inQueue) return { gate, files: [] };
1588
+ try {
1589
+ const local = await detectLocalMergeConflicts(cwd, gate?.baseRefName ?? null);
1590
+ if (local.conflicting) {
1591
+ return {
1592
+ gate: {
1593
+ mergeable: "CONFLICTING",
1594
+ mergeStateStatus: "DIRTY",
1595
+ reviewDecision: gate?.reviewDecision ?? null,
1596
+ baseRefName: local.base,
1597
+ url: gate?.url ?? null,
1598
+ isInMergeQueue: false
1599
+ },
1600
+ files: local.files
1601
+ };
1602
+ }
1603
+ if (gate && (mergeable === "UNKNOWN" || mergeState === "UNKNOWN")) {
1604
+ return {
1605
+ gate: {
1606
+ ...gate,
1607
+ mergeable: gate.mergeable === "UNKNOWN" ? "MERGEABLE" : gate.mergeable,
1608
+ mergeStateStatus: gate.mergeStateStatus === "UNKNOWN" ? "CLEAN" : gate.mergeStateStatus
1609
+ },
1610
+ files: []
1611
+ };
1612
+ }
1613
+ } catch {
1614
+ }
1615
+ return { gate, files: [] };
1616
+ }
1569
1617
  async function getPrChecks(cwd, selector) {
1570
1618
  const slug = await resolveGithubRepoSlug(cwd);
1571
1619
  const args = [
@@ -1601,47 +1649,9 @@ async function getPrChecks(cwd, selector) {
1601
1649
  }
1602
1650
  }
1603
1651
  let gate = await fetchPrMergeGate(cwd, selector, slug);
1604
- const mergeable = (gate?.mergeable ?? "").toUpperCase();
1605
- const mergeState = (gate?.mergeStateStatus ?? "").toUpperCase();
1606
- const alreadyConflicting = mergeable === "CONFLICTING" || mergeState === "DIRTY";
1607
- const inQueue = gate ? prIsInMergeQueue(gate) : false;
1608
- const needsLocalProbe = !alreadyConflicting && !inQueue;
1609
- if (needsLocalProbe) {
1610
- try {
1611
- const local = await detectLocalMergeConflicts(cwd, gate?.baseRefName ?? null);
1612
- if (local.conflicting) {
1613
- const fileHint = local.files.length > 0 ? ` Conflicting paths: ${local.files.slice(0, 8).join(", ")}${local.files.length > 8 ? "\u2026" : ""}.` : "";
1614
- gate = {
1615
- mergeable: "CONFLICTING",
1616
- mergeStateStatus: "DIRTY",
1617
- reviewDecision: gate?.reviewDecision ?? null,
1618
- baseRefName: local.base,
1619
- url: gate?.url ?? null,
1620
- isInMergeQueue: false
1621
- };
1622
- const ciFailed2 = ciChecks.some((c) => c.bucket === "fail");
1623
- const review2 = (gate.reviewDecision ?? "").toUpperCase();
1624
- const hasReviewRow2 = review2 === "CHANGES_REQUESTED" || review2 === "REVIEW_REQUIRED";
1625
- const gateRows2 = buildMergeGateChecks(gate, {
1626
- suppressGenericBlocked: ciFailed2 || hasReviewRow2
1627
- }).map(
1628
- (row) => row.kind === "mergeability" && row.name === "Merge conflicts" ? {
1629
- ...row,
1630
- description: `${row.description ?? ""}${fileHint}`.trim()
1631
- } : row
1632
- );
1633
- return [...gateRows2, ...ciChecks];
1634
- }
1635
- if (gate && (mergeable === "UNKNOWN" || mergeState === "UNKNOWN")) {
1636
- gate = {
1637
- ...gate,
1638
- mergeable: gate.mergeable === "UNKNOWN" ? "MERGEABLE" : gate.mergeable,
1639
- mergeStateStatus: gate.mergeStateStatus === "UNKNOWN" ? "CLEAN" : gate.mergeStateStatus
1640
- };
1641
- }
1642
- } catch {
1643
- }
1644
- }
1652
+ const probed = await probeLocalMergeGate(cwd, gate);
1653
+ gate = probed.gate;
1654
+ const fileHint = probed.files.length > 0 ? ` Conflicting paths: ${probed.files.slice(0, 8).join(", ")}${probed.files.length > 8 ? "\u2026" : ""}.` : "";
1645
1655
  if (!gate) {
1646
1656
  return ciChecks;
1647
1657
  }
@@ -1651,7 +1661,12 @@ async function getPrChecks(cwd, selector) {
1651
1661
  const gateRows = buildMergeGateChecks(gate, {
1652
1662
  // Avoid duplicating "blocked" when CI failures or review rows already explain it.
1653
1663
  suppressGenericBlocked: ciFailed || hasReviewRow
1654
- });
1664
+ }).map(
1665
+ (row) => fileHint && row.kind === "mergeability" && row.name === "Merge conflicts" ? {
1666
+ ...row,
1667
+ description: `${row.description ?? ""}${fileHint}`.trim()
1668
+ } : row
1669
+ );
1655
1670
  return [...gateRows, ...ciChecks];
1656
1671
  }
1657
1672
  async function getPrMeta(cwd, selector) {
@@ -1661,7 +1676,7 @@ async function getPrMeta(cwd, selector) {
1661
1676
  "view",
1662
1677
  selector,
1663
1678
  "--json",
1664
- "number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus"
1679
+ "number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus,mergeable"
1665
1680
  ];
1666
1681
  if (slug) viewArgs.push("--repo", slug);
1667
1682
  let { stdout, exitCode, stderr } = await gh(viewArgs, cwd, { reject: false });
@@ -1671,7 +1686,7 @@ async function getPrMeta(cwd, selector) {
1671
1686
  "view",
1672
1687
  selector,
1673
1688
  "--json",
1674
- "number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus"
1689
+ "number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus,mergeable"
1675
1690
  ];
1676
1691
  if (slug) retry.push("--repo", slug);
1677
1692
  ({ stdout, exitCode, stderr } = await gh(retry, cwd, { reject: false }));
@@ -1682,16 +1697,28 @@ async function getPrMeta(cwd, selector) {
1682
1697
  }
1683
1698
  try {
1684
1699
  const view = JSON.parse(stdout);
1700
+ const gate = {
1701
+ mergeable: typeof view.mergeable === "string" && view.mergeable ? view.mergeable : null,
1702
+ mergeStateStatus: typeof view.mergeStateStatus === "string" && view.mergeStateStatus ? view.mergeStateStatus : null,
1703
+ reviewDecision: typeof view.reviewDecision === "string" && view.reviewDecision ? view.reviewDecision : null,
1704
+ baseRefName: String(view.baseRefName ?? ""),
1705
+ url: String(view.url ?? ""),
1706
+ isInMergeQueue: parseInMergeQueue(view)
1707
+ };
1708
+ const probed = await probeLocalMergeGate(cwd, gate);
1709
+ const resolved = probed.gate ?? gate;
1685
1710
  return {
1686
1711
  number: Number(view.number),
1687
1712
  title: String(view.title ?? ""),
1688
1713
  url: String(view.url ?? ""),
1689
1714
  state: String(view.state ?? ""),
1690
1715
  isDraft: Boolean(view.isDraft),
1691
- reviewDecision: typeof view.reviewDecision === "string" && view.reviewDecision ? view.reviewDecision : null,
1692
- baseRefName: String(view.baseRefName ?? ""),
1716
+ reviewDecision: resolved.reviewDecision,
1717
+ baseRefName: resolved.baseRefName || String(view.baseRefName ?? ""),
1693
1718
  headRefName: String(view.headRefName ?? ""),
1694
- isInMergeQueue: parseInMergeQueue(view)
1719
+ isInMergeQueue: Boolean(resolved.isInMergeQueue),
1720
+ mergeable: resolved.mergeable,
1721
+ mergeStateStatus: resolved.mergeStateStatus
1695
1722
  };
1696
1723
  } catch {
1697
1724
  return null;
@@ -2159,7 +2186,9 @@ async function mergePr(cwd, selector, opts) {
2159
2186
  if (slug) args.push("--repo", slug);
2160
2187
  const { exitCode, stderr, stdout } = await gh(args, cwd, { reject: false });
2161
2188
  if (exitCode !== 0) {
2162
- throw new Error(stderr.trim() || stdout.trim() || "gh pr merge failed");
2189
+ throw new Error(
2190
+ formatMergePrError(stderr.trim() || stdout.trim() || "gh pr merge failed")
2191
+ );
2163
2192
  }
2164
2193
  const after = await gh(viewArgs, cwd, { reject: false });
2165
2194
  if (after.exitCode === 0 && after.stdout.trim()) {
@@ -0,0 +1,36 @@
1
+ // src/hook/nested-electron-env.ts
2
+ var NESTED_ELECTRON_ENV_PREFIXES = ["ELECTRON_", "CHROME_"];
3
+ function isNestedElectronEnvKey(key) {
4
+ return NESTED_ELECTRON_ENV_PREFIXES.some((prefix) => key.startsWith(prefix));
5
+ }
6
+ function stripNestedElectronEnv(env) {
7
+ const out = { ...env };
8
+ for (const key of Object.keys(out)) {
9
+ if (isNestedElectronEnvKey(key)) delete out[key];
10
+ }
11
+ return out;
12
+ }
13
+ function dropNestedElectronEnvFromProcess(env = process.env) {
14
+ for (const key of Object.keys(env)) {
15
+ if (isNestedElectronEnvKey(key)) delete env[key];
16
+ }
17
+ }
18
+ var STRIP_NESTED_ELECTRON_THEN_EXEC = [
19
+ "vars=`printenv | awk -F= '/^(ELECTRON_|CHROME_)/{print $1}'`",
20
+ '[ -n "$vars" ] && unset $vars',
21
+ "export ELECTRON_RUN_AS_NODE=1",
22
+ 'exec "$@"'
23
+ ].join("; ");
24
+ function wrapElectronAsNodeLaunch(file, args) {
25
+ if (process.platform === "win32") return { file, args };
26
+ return {
27
+ file: "/bin/sh",
28
+ args: ["-c", STRIP_NESTED_ELECTRON_THEN_EXEC, "sh", file, ...args]
29
+ };
30
+ }
31
+
32
+ export {
33
+ stripNestedElectronEnv,
34
+ dropNestedElectronEnvFromProcess,
35
+ wrapElectronAsNodeLaunch
36
+ };
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-VROPG6QF.js";
10
10
  import {
11
11
  isOrchestratorThread
12
- } from "./chunk-6T2SKGCS.js";
12
+ } from "./chunk-DJFGX4RT.js";
13
13
  import {
14
14
  enrichPathWithNpmGlobalBin,
15
15
  isConductorBundledCli,
@@ -21,8 +21,9 @@ import {
21
21
  claudeChromeEnabled,
22
22
  loadAppSettings,
23
23
  resolveAgentExecutable,
24
- resolveClaudeExecutable
25
- } from "./chunk-XKNBSYA7.js";
24
+ resolveClaudeExecutable,
25
+ wrapElectronAsNodeLaunch
26
+ } from "./chunk-UHGN4KCL.js";
26
27
  import {
27
28
  appDataDir
28
29
  } from "./chunk-7MV3RXSC.js";
@@ -30,6 +31,46 @@ import {
30
31
  // src/agents/brightsy.ts
31
32
  import { existsSync } from "fs";
32
33
 
34
+ // src/agents/usage.ts
35
+ function sumOptional(a, b) {
36
+ if (a == null && b == null) return void 0;
37
+ return (a ?? 0) + (b ?? 0);
38
+ }
39
+ function fromInclusiveInputUsage(opts) {
40
+ const totalInput = Number(opts.inputTokens) || 0;
41
+ const outputTokens = Number(opts.outputTokens) || 0;
42
+ const cached = Number(opts.cachedInputTokens) || 0;
43
+ if (!totalInput && !outputTokens) return null;
44
+ const cacheReadTokens = cached > 0 ? Math.min(cached, totalInput) : 0;
45
+ return {
46
+ inputTokens: Math.max(0, totalInput - cacheReadTokens),
47
+ outputTokens,
48
+ cacheReadTokens: cacheReadTokens || void 0
49
+ };
50
+ }
51
+ function requestOccupancy(u) {
52
+ return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
53
+ }
54
+ function mergeUsage(a, b) {
55
+ return {
56
+ inputTokens: (a?.inputTokens ?? 0) + b.inputTokens,
57
+ outputTokens: (a?.outputTokens ?? 0) + b.outputTokens,
58
+ cacheReadTokens: sumOptional(a?.cacheReadTokens, b.cacheReadTokens),
59
+ cacheWriteTokens: sumOptional(a?.cacheWriteTokens, b.cacheWriteTokens),
60
+ lastRequestTokens: b.lastRequestTokens ?? a?.lastRequestTokens
61
+ };
62
+ }
63
+ function applyTurnUsage(current, incoming, scope = "request") {
64
+ if (scope === "turn") {
65
+ return {
66
+ ...incoming,
67
+ lastRequestTokens: current?.lastRequestTokens ?? requestOccupancy(incoming)
68
+ };
69
+ }
70
+ const merged = mergeUsage(current, incoming);
71
+ return { ...merged, lastRequestTokens: requestOccupancy(incoming) };
72
+ }
73
+
33
74
  // src/agents/brightsy-targets.ts
34
75
  function encodeBrightsyTarget(type, id, accountId) {
35
76
  if (accountId) return `team:${accountId}:${type}:${id}`;
@@ -205,15 +246,11 @@ ${prompt}`;
205
246
  // src/agents/brightsy.ts
206
247
  function usageFromBrightsy(usage) {
207
248
  if (!usage) return null;
208
- const inputTokens = Number(usage.prompt_tokens ?? 0);
209
- const outputTokens = Number(usage.completion_tokens ?? 0);
210
- if (!inputTokens && !outputTokens) return null;
211
- const cached = Number(usage.prompt_tokens_details?.cached_tokens ?? 0);
212
- return {
213
- inputTokens,
214
- outputTokens,
215
- cacheReadTokens: cached || void 0
216
- };
249
+ return fromInclusiveInputUsage({
250
+ inputTokens: Number(usage.prompt_tokens ?? 0),
251
+ outputTokens: Number(usage.completion_tokens ?? 0),
252
+ cachedInputTokens: Number(usage.prompt_tokens_details?.cached_tokens ?? 0)
253
+ });
217
254
  }
218
255
  function parseBrightsyCliLine(line) {
219
256
  const trimmed = line.trim();
@@ -552,6 +589,13 @@ function sideboardMcpProfile(env = process.env) {
552
589
  function isAsarPath(filePath) {
553
590
  return /\.asar([/\\]|$)/.test(filePath);
554
591
  }
592
+ function applyNodeLaunch(launch, args) {
593
+ if (!launch.env.ELECTRON_RUN_AS_NODE) {
594
+ return { file: launch.file, args, env: launch.env };
595
+ }
596
+ const wrapped = wrapElectronAsNodeLaunch(launch.file, args);
597
+ return { file: wrapped.file, args: wrapped.args, env: launch.env };
598
+ }
555
599
  async function resolveNodeLaunch(scriptPath) {
556
600
  if (isAsarPath(scriptPath)) {
557
601
  return {
@@ -712,11 +756,11 @@ async function resolveSideboardMcpServer() {
712
756
  if (entry) {
713
757
  const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
714
758
  const scriptArgs = isCli ? [entry, "mcp"] : [entry];
715
- const launch = await resolveNodeLaunch(entry);
759
+ const launch = applyNodeLaunch(await resolveNodeLaunch(entry), scriptArgs);
716
760
  return {
717
761
  name: "sideboard",
718
762
  command: launch.file,
719
- args: scriptArgs,
763
+ args: launch.args,
720
764
  ...Object.keys(launch.env).length > 0 ? { env: launch.env } : {}
721
765
  };
722
766
  }
@@ -1009,7 +1053,7 @@ var claudeAdapter = {
1009
1053
  );
1010
1054
  }
1011
1055
  const mode = permissionMode(thread);
1012
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-RI367AM6.js");
1056
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-OBRWUPZG.js");
1013
1057
  const isOrchestrator = isOrchestratorThread2(thread);
1014
1058
  const injectedServers = await buildInjectedMcpServers({
1015
1059
  includeSideboard: true,
@@ -1260,14 +1304,11 @@ async function listCodexModels() {
1260
1304
  }
1261
1305
  function usageFromCodex(usage) {
1262
1306
  if (!usage) return null;
1263
- const inputTokens = Number(usage.input_tokens ?? 0);
1264
- const outputTokens = Number(usage.output_tokens ?? 0) + Number(usage.reasoning_output_tokens ?? 0);
1265
- if (!inputTokens && !outputTokens) return null;
1266
- return {
1267
- inputTokens,
1268
- outputTokens,
1269
- cacheReadTokens: usage.cached_input_tokens ? Number(usage.cached_input_tokens) : void 0
1270
- };
1307
+ return fromInclusiveInputUsage({
1308
+ inputTokens: Number(usage.input_tokens ?? 0),
1309
+ outputTokens: Number(usage.output_tokens ?? 0),
1310
+ cachedInputTokens: Number(usage.cached_input_tokens ?? 0)
1311
+ });
1271
1312
  }
1272
1313
  function codexConfigHasNetworkAccess() {
1273
1314
  const candidates = [
@@ -1834,10 +1875,13 @@ var cursorAdapter = {
1834
1875
  };
1835
1876
  const runner = cursorRunnerPath();
1836
1877
  const isTs = runner.endsWith(".ts");
1837
- const launch = await resolveNodeLaunch(runner);
1878
+ const launch = applyNodeLaunch(
1879
+ await resolveNodeLaunch(runner),
1880
+ isTs ? ["--import", "tsx", runner] : [runner]
1881
+ );
1838
1882
  return {
1839
1883
  file: launch.file,
1840
- args: isTs ? ["--import", "tsx", runner] : [runner],
1884
+ args: launch.args,
1841
1885
  cwd: thread.worktreePath,
1842
1886
  stdin: JSON.stringify(req),
1843
1887
  env: {
@@ -2577,6 +2621,7 @@ export {
2577
2621
  fallbackTurnFailDetail,
2578
2622
  humanizeAgentFailDetail,
2579
2623
  formatTurnExitError,
2624
+ applyTurnUsage,
2580
2625
  encodeBrightsyTarget,
2581
2626
  decodeBrightsyTarget,
2582
2627
  parseBrightsyCliLine,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isOrchestratorThread
3
- } from "./chunk-5LXWTU3J.js";
3
+ } from "./chunk-NXXT5SE3.js";
4
4
  import {
5
5
  applyConnectedTeamToCli,
6
6
  brightsyMcpServerName,
@@ -19,7 +19,10 @@ import {
19
19
  loadAppSettings,
20
20
  resolveAgentExecutable,
21
21
  resolveClaudeExecutable
22
- } from "./chunk-IFPN6TER.js";
22
+ } from "./chunk-YO3CYL6B.js";
23
+ import {
24
+ wrapElectronAsNodeLaunch
25
+ } from "./chunk-IZ7RPF54.js";
23
26
  import {
24
27
  appDataDir
25
28
  } from "./chunk-M37RITA6.js";
@@ -34,6 +37,53 @@ import {
34
37
  // src/agents/brightsy.ts
35
38
  import { existsSync } from "fs";
36
39
 
40
+ // src/agents/usage.ts
41
+ function sumOptional(a, b) {
42
+ if (a == null && b == null) return void 0;
43
+ return (a ?? 0) + (b ?? 0);
44
+ }
45
+ function fromInclusiveInputUsage(opts) {
46
+ const totalInput = Number(opts.inputTokens) || 0;
47
+ const outputTokens = Number(opts.outputTokens) || 0;
48
+ const cached = Number(opts.cachedInputTokens) || 0;
49
+ if (!totalInput && !outputTokens) return null;
50
+ const cacheReadTokens = cached > 0 ? Math.min(cached, totalInput) : 0;
51
+ return {
52
+ inputTokens: Math.max(0, totalInput - cacheReadTokens),
53
+ outputTokens,
54
+ cacheReadTokens: cacheReadTokens || void 0
55
+ };
56
+ }
57
+ function requestOccupancy(u) {
58
+ return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
59
+ }
60
+ function mergeUsage(a, b) {
61
+ return {
62
+ inputTokens: (a?.inputTokens ?? 0) + b.inputTokens,
63
+ outputTokens: (a?.outputTokens ?? 0) + b.outputTokens,
64
+ cacheReadTokens: sumOptional(a?.cacheReadTokens, b.cacheReadTokens),
65
+ cacheWriteTokens: sumOptional(a?.cacheWriteTokens, b.cacheWriteTokens),
66
+ lastRequestTokens: b.lastRequestTokens ?? a?.lastRequestTokens
67
+ };
68
+ }
69
+ function applyTurnUsage(current, incoming, scope = "request") {
70
+ if (scope === "turn") {
71
+ return {
72
+ ...incoming,
73
+ lastRequestTokens: current?.lastRequestTokens ?? requestOccupancy(incoming)
74
+ };
75
+ }
76
+ const merged = mergeUsage(current, incoming);
77
+ return { ...merged, lastRequestTokens: requestOccupancy(incoming) };
78
+ }
79
+ function totalTokens(u) {
80
+ return u.inputTokens + u.outputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
81
+ }
82
+ function contextTokens(u) {
83
+ if (u.lastRequestTokens != null && u.lastRequestTokens > 0) return u.lastRequestTokens;
84
+ return requestOccupancy(u);
85
+ }
86
+
37
87
  // src/agents/brightsy-targets.ts
38
88
  function encodeBrightsyTarget(type, id, accountId) {
39
89
  if (accountId) return `team:${accountId}:${type}:${id}`;
@@ -131,15 +181,11 @@ var MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS = 4;
131
181
  // src/agents/brightsy.ts
132
182
  function usageFromBrightsy(usage) {
133
183
  if (!usage) return null;
134
- const inputTokens = Number(usage.prompt_tokens ?? 0);
135
- const outputTokens = Number(usage.completion_tokens ?? 0);
136
- if (!inputTokens && !outputTokens) return null;
137
- const cached = Number(usage.prompt_tokens_details?.cached_tokens ?? 0);
138
- return {
139
- inputTokens,
140
- outputTokens,
141
- cacheReadTokens: cached || void 0
142
- };
184
+ return fromInclusiveInputUsage({
185
+ inputTokens: Number(usage.prompt_tokens ?? 0),
186
+ outputTokens: Number(usage.completion_tokens ?? 0),
187
+ cachedInputTokens: Number(usage.prompt_tokens_details?.cached_tokens ?? 0)
188
+ });
143
189
  }
144
190
  function parseBrightsyCliLine(line) {
145
191
  const trimmed = line.trim();
@@ -485,6 +531,13 @@ function sideboardMcpProfile(env = process.env) {
485
531
  function isAsarPath(filePath) {
486
532
  return /\.asar([/\\]|$)/.test(filePath);
487
533
  }
534
+ function applyNodeLaunch(launch, args) {
535
+ if (!launch.env.ELECTRON_RUN_AS_NODE) {
536
+ return { file: launch.file, args, env: launch.env };
537
+ }
538
+ const wrapped = wrapElectronAsNodeLaunch(launch.file, args);
539
+ return { file: wrapped.file, args: wrapped.args, env: launch.env };
540
+ }
488
541
  async function resolveNodeLaunch(scriptPath) {
489
542
  if (isAsarPath(scriptPath)) {
490
543
  return {
@@ -649,11 +702,11 @@ async function resolveSideboardMcpServer() {
649
702
  if (entry) {
650
703
  const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
651
704
  const scriptArgs = isCli ? [entry, "mcp"] : [entry];
652
- const launch = await resolveNodeLaunch(entry);
705
+ const launch = applyNodeLaunch(await resolveNodeLaunch(entry), scriptArgs);
653
706
  return {
654
707
  name: "sideboard",
655
708
  command: launch.file,
656
- args: scriptArgs,
709
+ args: launch.args,
657
710
  ...Object.keys(launch.env).length > 0 ? { env: launch.env } : {}
658
711
  };
659
712
  }
@@ -949,7 +1002,7 @@ var claudeAdapter = {
949
1002
  );
950
1003
  }
951
1004
  const mode = permissionMode(thread);
952
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-VG44RZUH.js");
1005
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-GSLCEB5E.js");
953
1006
  const isOrchestrator = isOrchestratorThread2(thread);
954
1007
  const injectedServers = await buildInjectedMcpServers({
955
1008
  includeSideboard: true,
@@ -1200,14 +1253,11 @@ async function listCodexModels() {
1200
1253
  }
1201
1254
  function usageFromCodex(usage) {
1202
1255
  if (!usage) return null;
1203
- const inputTokens = Number(usage.input_tokens ?? 0);
1204
- const outputTokens = Number(usage.output_tokens ?? 0) + Number(usage.reasoning_output_tokens ?? 0);
1205
- if (!inputTokens && !outputTokens) return null;
1206
- return {
1207
- inputTokens,
1208
- outputTokens,
1209
- cacheReadTokens: usage.cached_input_tokens ? Number(usage.cached_input_tokens) : void 0
1210
- };
1256
+ return fromInclusiveInputUsage({
1257
+ inputTokens: Number(usage.input_tokens ?? 0),
1258
+ outputTokens: Number(usage.output_tokens ?? 0),
1259
+ cachedInputTokens: Number(usage.cached_input_tokens ?? 0)
1260
+ });
1211
1261
  }
1212
1262
  function codexConfigHasNetworkAccess() {
1213
1263
  const candidates = [
@@ -1603,10 +1653,13 @@ var cursorAdapter = {
1603
1653
  };
1604
1654
  const runner = cursorRunnerPath();
1605
1655
  const isTs = runner.endsWith(".ts");
1606
- const launch = await resolveNodeLaunch(runner);
1656
+ const launch = applyNodeLaunch(
1657
+ await resolveNodeLaunch(runner),
1658
+ isTs ? ["--import", "tsx", runner] : [runner]
1659
+ );
1607
1660
  return {
1608
1661
  file: launch.file,
1609
- args: isTs ? ["--import", "tsx", runner] : [runner],
1662
+ args: launch.args,
1610
1663
  cwd: thread.worktreePath,
1611
1664
  stdin: JSON.stringify(req),
1612
1665
  env: {
@@ -2339,6 +2392,12 @@ function allAdapters() {
2339
2392
  }
2340
2393
 
2341
2394
  export {
2395
+ fromInclusiveInputUsage,
2396
+ requestOccupancy,
2397
+ mergeUsage,
2398
+ applyTurnUsage,
2399
+ totalTokens,
2400
+ contextTokens,
2342
2401
  encodeBrightsyTarget,
2343
2402
  decodeBrightsyTarget,
2344
2403
  normalizeTurnInput,
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  isGlobalRepoPath
3
- } from "./chunk-5LXWTU3J.js";
3
+ } from "./chunk-NXXT5SE3.js";
4
4
  import {
5
5
  ensureGhPreferOrigin,
6
6
  resolveRepoRoot
7
- } from "./chunk-YVVXWWCC.js";
7
+ } from "./chunk-GD2FM6FN.js";
8
8
  import {
9
9
  appDataDir
10
10
  } from "./chunk-M37RITA6.js";
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  ensureGlobalCoordinatorCwd
3
- } from "./chunk-HCGEFU3J.js";
3
+ } from "./chunk-E2MIA7DO.js";
4
4
  import {
5
5
  allocateTeamName,
6
6
  takenSlugsFromThread,
7
7
  teamSlugFromName
8
- } from "./chunk-YVVXWWCC.js";
8
+ } from "./chunk-GD2FM6FN.js";
9
9
  import {
10
10
  resolveNewThreadOptions,
11
11
  resolveThreadDefaults
12
- } from "./chunk-IFPN6TER.js";
12
+ } from "./chunk-YO3CYL6B.js";
13
13
  import {
14
14
  createEmptyThread,
15
15
  listThreads,
@@ -2,11 +2,11 @@
2
2
 
3
3
  import {
4
4
  isGlobalRepoPath
5
- } from "./chunk-6T2SKGCS.js";
5
+ } from "./chunk-DJFGX4RT.js";
6
6
  import {
7
7
  ensureGhPreferOrigin,
8
8
  resolveRepoRoot
9
- } from "./chunk-FUUVPN4A.js";
9
+ } from "./chunk-HBBXS2FR.js";
10
10
  import {
11
11
  appDataDir
12
12
  } from "./chunk-7MV3RXSC.js";
@@ -17,6 +17,37 @@ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
17
17
  import { homedir, hostname } from "os";
18
18
  import { join as join2 } from "path";
19
19
 
20
+ // src/hook/nested-electron-env.ts
21
+ var NESTED_ELECTRON_ENV_PREFIXES = ["ELECTRON_", "CHROME_"];
22
+ function isNestedElectronEnvKey(key) {
23
+ return NESTED_ELECTRON_ENV_PREFIXES.some((prefix) => key.startsWith(prefix));
24
+ }
25
+ function stripNestedElectronEnv(env) {
26
+ const out = { ...env };
27
+ for (const key of Object.keys(out)) {
28
+ if (isNestedElectronEnvKey(key)) delete out[key];
29
+ }
30
+ return out;
31
+ }
32
+ function dropNestedElectronEnvFromProcess(env = process.env) {
33
+ for (const key of Object.keys(env)) {
34
+ if (isNestedElectronEnvKey(key)) delete env[key];
35
+ }
36
+ }
37
+ var STRIP_NESTED_ELECTRON_THEN_EXEC = [
38
+ "vars=`printenv | awk -F= '/^(ELECTRON_|CHROME_)/{print $1}'`",
39
+ '[ -n "$vars" ] && unset $vars',
40
+ "export ELECTRON_RUN_AS_NODE=1",
41
+ 'exec "$@"'
42
+ ].join("; ");
43
+ function wrapElectronAsNodeLaunch(file, args) {
44
+ if (process.platform === "win32") return { file, args };
45
+ return {
46
+ file: "/bin/sh",
47
+ args: ["-c", STRIP_NESTED_ELECTRON_THEN_EXEC, "sh", file, ...args]
48
+ };
49
+ }
50
+
20
51
  // src/store/secret-vault.ts
21
52
  import { join } from "path";
22
53
 
@@ -1062,7 +1093,7 @@ function applyAppEnvironment(target = process.env, settings = loadAppSettings())
1062
1093
  }
1063
1094
  function childEnvWithAppSettings(extra) {
1064
1095
  const settings = loadAppSettings();
1065
- const env = { ...process.env };
1096
+ const env = stripNestedElectronEnv({ ...process.env });
1066
1097
  applyAppEnvironment(env, settings);
1067
1098
  if (extra) {
1068
1099
  for (const [k, v] of Object.entries(extra)) {
@@ -1076,6 +1107,9 @@ function harnessEnvKey(harness) {
1076
1107
  }
1077
1108
 
1078
1109
  export {
1110
+ stripNestedElectronEnv,
1111
+ dropNestedElectronEnvFromProcess,
1112
+ wrapElectronAsNodeLaunch,
1079
1113
  resolveVaultKey,
1080
1114
  readSecureJson,
1081
1115
  writeSecureJson,