nexus-agents 9.4.0 → 10.0.0

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 (153) hide show
  1. package/dist/{ast-rule-runner-5U6TE6YJ.js → ast-rule-runner-AAOBENF2.js} +3 -3
  2. package/dist/{child-mcp-config-IR7LRMIK.js → child-mcp-config-FRWGQIHP.js} +2 -2
  3. package/dist/{chunk-DG2UY5QU.js → chunk-2VD5OQQR.js} +2 -2
  4. package/dist/{chunk-FTUBCD52.js → chunk-52Q72CPP.js} +3 -3
  5. package/dist/{chunk-TQEXRC5C.js → chunk-BDAR2UPN.js} +57 -151
  6. package/dist/chunk-BDAR2UPN.js.map +1 -0
  7. package/dist/{chunk-Q7RFJSR5.js → chunk-BJLP4E6Q.js} +3 -3
  8. package/dist/{chunk-Q5F4OBOK.js → chunk-BK6Q3VQK.js} +6 -42
  9. package/dist/chunk-BK6Q3VQK.js.map +1 -0
  10. package/dist/{chunk-ETGNAHY3.js → chunk-CYROSFMW.js} +5 -5
  11. package/dist/{chunk-FWSAYHGV.js → chunk-EGUISJBB.js} +4 -4
  12. package/dist/{chunk-ONWH4UGD.js → chunk-HBJ3CVDB.js} +54 -25
  13. package/dist/{chunk-ONWH4UGD.js.map → chunk-HBJ3CVDB.js.map} +1 -1
  14. package/dist/{chunk-XJ65J3O5.js → chunk-HVZVVDFN.js} +10 -6
  15. package/dist/chunk-HVZVVDFN.js.map +1 -0
  16. package/dist/{chunk-2AW2VHMK.js → chunk-IRFKJ2KR.js} +2 -2
  17. package/dist/{chunk-HK4LBUYY.js → chunk-K6M2ZWX5.js} +2 -2
  18. package/dist/{chunk-RI4IXOZT.js → chunk-KPGWNBDA.js} +2 -2
  19. package/dist/{chunk-6WPXQTQY.js → chunk-L4P4A7Z2.js} +2 -2
  20. package/dist/{chunk-P7327767.js → chunk-M4IJ3H6M.js} +2 -2
  21. package/dist/{chunk-FKMBZ53Y.js → chunk-MCWIMVG2.js} +2 -2
  22. package/dist/{chunk-JNRDNE26.js → chunk-MYM2TPNL.js} +2 -2
  23. package/dist/{chunk-TMHCN5EY.js → chunk-NUXSGWDS.js} +5 -5
  24. package/dist/{chunk-ONYCBTOH.js → chunk-O3VPGING.js} +11 -15
  25. package/dist/chunk-O3VPGING.js.map +1 -0
  26. package/dist/{chunk-AFAM6GK3.js → chunk-O46IOND3.js} +7 -7
  27. package/dist/{chunk-DYTB2XW2.js → chunk-O5OUJ3PX.js} +5 -5
  28. package/dist/{chunk-VQGHQVD2.js → chunk-QPU7QKPT.js} +3 -3
  29. package/dist/{chunk-DEQRRCHK.js → chunk-RBFHY2LF.js} +2 -2
  30. package/dist/{chunk-H4ACPMJS.js → chunk-SCQ5YAYO.js} +4 -4
  31. package/dist/{chunk-LWLFWWA7.js → chunk-TQZSPGAZ.js} +3 -3
  32. package/dist/{chunk-LWLFWWA7.js.map → chunk-TQZSPGAZ.js.map} +1 -1
  33. package/dist/{chunk-ECJ52NSK.js → chunk-TYLE7Z2S.js} +5 -3
  34. package/dist/{chunk-ECJ52NSK.js.map → chunk-TYLE7Z2S.js.map} +1 -1
  35. package/dist/{chunk-TFQMVUWQ.js → chunk-V5FGXVSX.js} +5 -7
  36. package/dist/{chunk-TFQMVUWQ.js.map → chunk-V5FGXVSX.js.map} +1 -1
  37. package/dist/{chunk-2AN5NGCQ.js → chunk-VGCRYAEH.js} +4 -4
  38. package/dist/{chunk-AYBOQE2Y.js → chunk-VHOOJ4FG.js} +3 -3
  39. package/dist/{chunk-AYBOQE2Y.js.map → chunk-VHOOJ4FG.js.map} +1 -1
  40. package/dist/{chunk-II4XITQ6.js → chunk-W2XP4MEN.js} +14 -20
  41. package/dist/{chunk-II4XITQ6.js.map → chunk-W2XP4MEN.js.map} +1 -1
  42. package/dist/{chunk-6H4NUU7G.js → chunk-WCHN7B2Q.js} +6 -20
  43. package/dist/{chunk-6H4NUU7G.js.map → chunk-WCHN7B2Q.js.map} +1 -1
  44. package/dist/{chunk-7XJZTSHW.js → chunk-WI73OZAU.js} +22 -125
  45. package/dist/chunk-WI73OZAU.js.map +1 -0
  46. package/dist/{chunk-EPCR2GOE.js → chunk-XFTTKOHK.js} +2 -2
  47. package/dist/{chunk-C5WECFBR.js → chunk-XQMQGUJT.js} +5 -5
  48. package/dist/{chunk-PRX4ERTK.js → chunk-XSAUVC6D.js} +2 -2
  49. package/dist/{chunk-AI6LKFGU.js → chunk-XTL45OBN.js} +3 -3
  50. package/dist/{chunk-6Z3MAHAC.js → chunk-XYYXVJSO.js} +2 -2
  51. package/dist/{chunk-HESQ746B.js → chunk-YHY7GMAL.js} +2 -2
  52. package/dist/{cli-circuit-breaker-AZHN2TMH.js → cli-circuit-breaker-AM425BRL.js} +3 -3
  53. package/dist/{cli-readiness-H4JTTKKU.js → cli-readiness-LWOMHZ34.js} +7 -7
  54. package/dist/cli.d.ts +1 -1
  55. package/dist/cli.js +47 -49
  56. package/dist/cli.js.map +1 -1
  57. package/dist/{composite-router-WCTNVMSX.js → composite-router-VXQFXNET.js} +2 -2
  58. package/dist/{consensus-vote-RD3SME3K.js → consensus-vote-IUXJHSSQ.js} +19 -19
  59. package/dist/{consensus-vote-types-G7Lnj3B3.d.ts → consensus-vote-types-DexdhOdB.d.ts} +9 -15
  60. package/dist/{context-retriever-YM2PPNSY.js → context-retriever-GEQIPCVL.js} +8 -8
  61. package/dist/{doctor-deep-6P23G7PN.js → doctor-deep-DSOZGB5J.js} +3 -3
  62. package/dist/doctor-gateway-report-RJOSOHGA.js +21 -0
  63. package/dist/{doctor-live-MYXZCBSP.js → doctor-live-7LVRGOS5.js} +13 -13
  64. package/dist/{expert-bridge-CXHYMQRL.js → expert-bridge-5A4ADUBO.js} +4 -4
  65. package/dist/{factory-KH2MJQ5U.js → factory-4RZLP7QV.js} +5 -5
  66. package/dist/{factory-3Z46455N.js → factory-UBAUIA2M.js} +12 -12
  67. package/dist/{improvement-review-RAISKC3W.js → improvement-review-KBMTSFYT.js} +7 -7
  68. package/dist/index.d.ts +49 -562
  69. package/dist/index.js +35 -83
  70. package/dist/index.js.map +1 -1
  71. package/dist/{init-opencode-WXRTDPFP.js → init-opencode-WUN3CTBM.js} +6 -6
  72. package/dist/{issue-triage-KF47ZHU7.js → issue-triage-VKEHVHO4.js} +6 -6
  73. package/dist/{model-config-helpers-ZH2QAFVR.js → model-config-helpers-GYPIIXOP.js} +2 -2
  74. package/dist/{openai-compat-adapter-PQ3JKWPZ.js → openai-compat-adapter-GSDOJ7TQ.js} +6 -6
  75. package/dist/{outcome-store-adapter-NTYEZXLH.js → outcome-store-adapter-PXT7AL6T.js} +2 -2
  76. package/dist/{pr-reviewer-helpers-AQNGDRQT.js → pr-reviewer-helpers-GUUT7G43.js} +4 -4
  77. package/dist/{registry-command-6EHIJ3PJ.js → registry-command-4G3WGKS5.js} +2 -2
  78. package/dist/{repo-security-plan-AP3QEWJ5.js → repo-security-plan-QO6ACTPZ.js} +3 -3
  79. package/dist/{research-helpers-synthesize-XE3RMFQT.js → research-helpers-synthesize-MPEJHPYR.js} +4 -4
  80. package/dist/{routing-memory-PBZIE5NX.js → routing-memory-VHQDJ6XZ.js} +2 -2
  81. package/dist/{session-memory-6NUK6ZAG.js → session-memory-M3CQFFL6.js} +3 -3
  82. package/dist/{setup-config-KEPU4NTT.js → setup-config-VGEBCEKX.js} +3 -3
  83. package/dist/{setup-custom-api-XY455LVS.js → setup-custom-api-DX7CNYKT.js} +5 -5
  84. package/dist/{setup-custom-api-XY455LVS.js.map → setup-custom-api-DX7CNYKT.js.map} +1 -1
  85. package/dist/setup-data-dir-JQGH2JCH.js +36 -0
  86. package/dist/{tool-memory-MO2KOJJ7.js → tool-memory-7QUPGCWV.js} +5 -5
  87. package/dist/{unified-registry-JE22THXP.js → unified-registry-CLZK3H64.js} +13 -13
  88. package/dist/{weather-report-TQ6KM2F2.js → weather-report-OKMXF73V.js} +2 -2
  89. package/node_modules/@modelcontextprotocol/sdk/README.md +8 -2
  90. package/node_modules/@modelcontextprotocol/sdk/package.json +1 -1
  91. package/package.json +3 -2
  92. package/dist/chunk-7XJZTSHW.js.map +0 -1
  93. package/dist/chunk-ONYCBTOH.js.map +0 -1
  94. package/dist/chunk-Q5F4OBOK.js.map +0 -1
  95. package/dist/chunk-TQEXRC5C.js.map +0 -1
  96. package/dist/chunk-XJ65J3O5.js.map +0 -1
  97. package/dist/doctor-gateway-report-4TXHTWUM.js +0 -21
  98. package/dist/setup-data-dir-5MRGQD2G.js +0 -36
  99. /package/dist/{ast-rule-runner-5U6TE6YJ.js.map → ast-rule-runner-AAOBENF2.js.map} +0 -0
  100. /package/dist/{child-mcp-config-IR7LRMIK.js.map → child-mcp-config-FRWGQIHP.js.map} +0 -0
  101. /package/dist/{chunk-DG2UY5QU.js.map → chunk-2VD5OQQR.js.map} +0 -0
  102. /package/dist/{chunk-FTUBCD52.js.map → chunk-52Q72CPP.js.map} +0 -0
  103. /package/dist/{chunk-Q7RFJSR5.js.map → chunk-BJLP4E6Q.js.map} +0 -0
  104. /package/dist/{chunk-ETGNAHY3.js.map → chunk-CYROSFMW.js.map} +0 -0
  105. /package/dist/{chunk-FWSAYHGV.js.map → chunk-EGUISJBB.js.map} +0 -0
  106. /package/dist/{chunk-2AW2VHMK.js.map → chunk-IRFKJ2KR.js.map} +0 -0
  107. /package/dist/{chunk-HK4LBUYY.js.map → chunk-K6M2ZWX5.js.map} +0 -0
  108. /package/dist/{chunk-RI4IXOZT.js.map → chunk-KPGWNBDA.js.map} +0 -0
  109. /package/dist/{chunk-6WPXQTQY.js.map → chunk-L4P4A7Z2.js.map} +0 -0
  110. /package/dist/{chunk-P7327767.js.map → chunk-M4IJ3H6M.js.map} +0 -0
  111. /package/dist/{chunk-FKMBZ53Y.js.map → chunk-MCWIMVG2.js.map} +0 -0
  112. /package/dist/{chunk-JNRDNE26.js.map → chunk-MYM2TPNL.js.map} +0 -0
  113. /package/dist/{chunk-TMHCN5EY.js.map → chunk-NUXSGWDS.js.map} +0 -0
  114. /package/dist/{chunk-AFAM6GK3.js.map → chunk-O46IOND3.js.map} +0 -0
  115. /package/dist/{chunk-DYTB2XW2.js.map → chunk-O5OUJ3PX.js.map} +0 -0
  116. /package/dist/{chunk-VQGHQVD2.js.map → chunk-QPU7QKPT.js.map} +0 -0
  117. /package/dist/{chunk-DEQRRCHK.js.map → chunk-RBFHY2LF.js.map} +0 -0
  118. /package/dist/{chunk-H4ACPMJS.js.map → chunk-SCQ5YAYO.js.map} +0 -0
  119. /package/dist/{chunk-2AN5NGCQ.js.map → chunk-VGCRYAEH.js.map} +0 -0
  120. /package/dist/{chunk-EPCR2GOE.js.map → chunk-XFTTKOHK.js.map} +0 -0
  121. /package/dist/{chunk-C5WECFBR.js.map → chunk-XQMQGUJT.js.map} +0 -0
  122. /package/dist/{chunk-PRX4ERTK.js.map → chunk-XSAUVC6D.js.map} +0 -0
  123. /package/dist/{chunk-AI6LKFGU.js.map → chunk-XTL45OBN.js.map} +0 -0
  124. /package/dist/{chunk-6Z3MAHAC.js.map → chunk-XYYXVJSO.js.map} +0 -0
  125. /package/dist/{chunk-HESQ746B.js.map → chunk-YHY7GMAL.js.map} +0 -0
  126. /package/dist/{cli-circuit-breaker-AZHN2TMH.js.map → cli-circuit-breaker-AM425BRL.js.map} +0 -0
  127. /package/dist/{cli-readiness-H4JTTKKU.js.map → cli-readiness-LWOMHZ34.js.map} +0 -0
  128. /package/dist/{composite-router-WCTNVMSX.js.map → composite-router-VXQFXNET.js.map} +0 -0
  129. /package/dist/{consensus-vote-RD3SME3K.js.map → consensus-vote-IUXJHSSQ.js.map} +0 -0
  130. /package/dist/{context-retriever-YM2PPNSY.js.map → context-retriever-GEQIPCVL.js.map} +0 -0
  131. /package/dist/{doctor-deep-6P23G7PN.js.map → doctor-deep-DSOZGB5J.js.map} +0 -0
  132. /package/dist/{doctor-gateway-report-4TXHTWUM.js.map → doctor-gateway-report-RJOSOHGA.js.map} +0 -0
  133. /package/dist/{doctor-live-MYXZCBSP.js.map → doctor-live-7LVRGOS5.js.map} +0 -0
  134. /package/dist/{expert-bridge-CXHYMQRL.js.map → expert-bridge-5A4ADUBO.js.map} +0 -0
  135. /package/dist/{factory-3Z46455N.js.map → factory-4RZLP7QV.js.map} +0 -0
  136. /package/dist/{factory-KH2MJQ5U.js.map → factory-UBAUIA2M.js.map} +0 -0
  137. /package/dist/{improvement-review-RAISKC3W.js.map → improvement-review-KBMTSFYT.js.map} +0 -0
  138. /package/dist/{init-opencode-WXRTDPFP.js.map → init-opencode-WUN3CTBM.js.map} +0 -0
  139. /package/dist/{issue-triage-KF47ZHU7.js.map → issue-triage-VKEHVHO4.js.map} +0 -0
  140. /package/dist/{model-config-helpers-ZH2QAFVR.js.map → model-config-helpers-GYPIIXOP.js.map} +0 -0
  141. /package/dist/{openai-compat-adapter-PQ3JKWPZ.js.map → openai-compat-adapter-GSDOJ7TQ.js.map} +0 -0
  142. /package/dist/{outcome-store-adapter-NTYEZXLH.js.map → outcome-store-adapter-PXT7AL6T.js.map} +0 -0
  143. /package/dist/{pr-reviewer-helpers-AQNGDRQT.js.map → pr-reviewer-helpers-GUUT7G43.js.map} +0 -0
  144. /package/dist/{registry-command-6EHIJ3PJ.js.map → registry-command-4G3WGKS5.js.map} +0 -0
  145. /package/dist/{repo-security-plan-AP3QEWJ5.js.map → repo-security-plan-QO6ACTPZ.js.map} +0 -0
  146. /package/dist/{research-helpers-synthesize-XE3RMFQT.js.map → research-helpers-synthesize-MPEJHPYR.js.map} +0 -0
  147. /package/dist/{routing-memory-PBZIE5NX.js.map → routing-memory-VHQDJ6XZ.js.map} +0 -0
  148. /package/dist/{session-memory-6NUK6ZAG.js.map → session-memory-M3CQFFL6.js.map} +0 -0
  149. /package/dist/{setup-config-KEPU4NTT.js.map → setup-config-VGEBCEKX.js.map} +0 -0
  150. /package/dist/{setup-data-dir-5MRGQD2G.js.map → setup-data-dir-JQGH2JCH.js.map} +0 -0
  151. /package/dist/{tool-memory-MO2KOJJ7.js.map → tool-memory-7QUPGCWV.js.map} +0 -0
  152. /package/dist/{unified-registry-JE22THXP.js.map → unified-registry-CLZK3H64.js.map} +0 -0
  153. /package/dist/{weather-report-TQ6KM2F2.js.map → weather-report-OKMXF73V.js.map} +0 -0
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  ensureGatewayDiscovered,
3
3
  gatewayDiscoveryGeneration
4
- } from "./chunk-VQGHQVD2.js";
4
+ } from "./chunk-QPU7QKPT.js";
5
5
  import {
6
6
  createLogger,
7
7
  getTimeProvider,
8
8
  isRateLimitText,
9
9
  resolveCliSlot
10
- } from "./chunk-7XJZTSHW.js";
10
+ } from "./chunk-WI73OZAU.js";
11
11
 
12
12
  // src/pipeline/expert-access-mode.ts
13
13
  var logger = createLogger({ component: "expert-bridge" });
@@ -78,7 +78,7 @@ async function dispatchWithMcpConfig(router, content, expertType, start, options
78
78
  let config;
79
79
  if (requestedAccessModeOf(options) === "default") {
80
80
  try {
81
- const { generateMcpConfig } = await import("./child-mcp-config-IR7LRMIK.js");
81
+ const { generateMcpConfig } = await import("./child-mcp-config-FRWGQIHP.js");
82
82
  config = await generateMcpConfig();
83
83
  activeMcpConfigs.add(config);
84
84
  } catch (error) {
@@ -167,8 +167,8 @@ async function getRouter() {
167
167
  }
168
168
  if (cachedRouter !== null) return cachedRouter;
169
169
  routerInitPromise ??= (async () => {
170
- const { createAllAdapters } = await import("./factory-3Z46455N.js");
171
- const { createCompositeRouter } = await import("./composite-router-WCTNVMSX.js");
170
+ const { createAllAdapters } = await import("./factory-UBAUIA2M.js");
171
+ const { createCompositeRouter } = await import("./composite-router-VXQFXNET.js");
172
172
  const adapters = createAllAdapters();
173
173
  const superseded = generation !== routerGeneration;
174
174
  if (adapters.size === 0) {
@@ -179,7 +179,7 @@ async function getRouter() {
179
179
  if (superseded) return router;
180
180
  cachedRouter = router;
181
181
  try {
182
- const { createCliCircuitBreakerIntegration } = await import("./cli-circuit-breaker-AZHN2TMH.js");
182
+ const { createCliCircuitBreakerIntegration } = await import("./cli-circuit-breaker-AM425BRL.js");
183
183
  cachedCircuitBreaker = createCliCircuitBreakerIntegration([...adapters.values()]);
184
184
  } catch (error) {
185
185
  const msg = error instanceof Error ? error.message : String(error);
@@ -320,4 +320,4 @@ export {
320
320
  tokenSplitFromUsage,
321
321
  executeExpert
322
322
  };
323
- //# sourceMappingURL=chunk-AFAM6GK3.js.map
323
+ //# sourceMappingURL=chunk-O46IOND3.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  GitHubProvider,
3
3
  ScmError
4
- } from "./chunk-EPCR2GOE.js";
4
+ } from "./chunk-XFTTKOHK.js";
5
5
  import {
6
6
  ReputationCache,
7
7
  assessReputation,
@@ -9,10 +9,10 @@ import {
9
9
  resolveEnvMode,
10
10
  resolveReputationGatingMode,
11
11
  sanitizeInput
12
- } from "./chunk-JNRDNE26.js";
12
+ } from "./chunk-MYM2TPNL.js";
13
13
  import {
14
14
  hasToken
15
- } from "./chunk-RI4IXOZT.js";
15
+ } from "./chunk-KPGWNBDA.js";
16
16
  import {
17
17
  toContentTrustProvenanceRecord
18
18
  } from "./chunk-ZO6ZKR7L.js";
@@ -27,7 +27,7 @@ import {
27
27
  getErrorMessage,
28
28
  getTimeProvider,
29
29
  ok
30
- } from "./chunk-7XJZTSHW.js";
30
+ } from "./chunk-WI73OZAU.js";
31
31
  import {
32
32
  CLI_SUBPROCESS_TIMEOUTS
33
33
  } from "./chunk-4PN3UVZV.js";
@@ -2645,4 +2645,4 @@ export {
2645
2645
  IssueTriage,
2646
2646
  createIssueTriage
2647
2647
  };
2648
- //# sourceMappingURL=chunk-DYTB2XW2.js.map
2648
+ //# sourceMappingURL=chunk-O5OUJ3PX.js.map
@@ -7,7 +7,7 @@ import {
7
7
  logGatewaySlotMapping,
8
8
  resolveOwnerCli,
9
9
  setGatewaySlotCatalog
10
- } from "./chunk-7XJZTSHW.js";
10
+ } from "./chunk-WI73OZAU.js";
11
11
 
12
12
  // src/config/model-availability.ts
13
13
  var DEFAULT_TTL_MS = 6e4;
@@ -139,7 +139,7 @@ function discoverGatewayOnce(logger = defaultLogger) {
139
139
  }
140
140
  async function runProbe(logger) {
141
141
  try {
142
- const { buildOpenAICompatAdapters: build } = await import("./openai-compat-adapter-PQ3JKWPZ.js");
142
+ const { buildOpenAICompatAdapters: build } = await import("./openai-compat-adapter-GSDOJ7TQ.js");
143
143
  return await build(logger);
144
144
  } catch (error) {
145
145
  return err(new ConfigError(`Gateway discovery threw: ${getErrorMessage(error)}`));
@@ -269,4 +269,4 @@ export {
269
269
  setGatewayRediscovery,
270
270
  ensureGatewayDiscovered
271
271
  };
272
- //# sourceMappingURL=chunk-VQGHQVD2.js.map
272
+ //# sourceMappingURL=chunk-QPU7QKPT.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getRandomProvider,
3
3
  getTimeProvider
4
- } from "./chunk-7XJZTSHW.js";
4
+ } from "./chunk-WI73OZAU.js";
5
5
 
6
6
  // src/utils/id-utils.ts
7
7
  import { randomUUID } from "node:crypto";
@@ -24,4 +24,4 @@ export {
24
24
  generateHyphenId,
25
25
  generateUUID
26
26
  };
27
- //# sourceMappingURL=chunk-DEQRRCHK.js.map
27
+ //# sourceMappingURL=chunk-RBFHY2LF.js.map
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  GitHubProvider,
3
3
  ScmError
4
- } from "./chunk-EPCR2GOE.js";
4
+ } from "./chunk-XFTTKOHK.js";
5
5
  import {
6
6
  resolveToken
7
- } from "./chunk-RI4IXOZT.js";
7
+ } from "./chunk-KPGWNBDA.js";
8
8
  import {
9
9
  err,
10
10
  ok
11
- } from "./chunk-7XJZTSHW.js";
11
+ } from "./chunk-WI73OZAU.js";
12
12
 
13
13
  // src/scm/factory.ts
14
14
  async function createScmProvider(config) {
@@ -41,4 +41,4 @@ export {
41
41
  createScmProvider,
42
42
  createGitHubProvider
43
43
  };
44
- //# sourceMappingURL=chunk-H4ACPMJS.js.map
44
+ //# sourceMappingURL=chunk-SCQ5YAYO.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  getTimeProvider
3
- } from "./chunk-7XJZTSHW.js";
3
+ } from "./chunk-WI73OZAU.js";
4
4
 
5
5
  // src/version.ts
6
6
  import semver from "semver";
7
- var VERSION = true ? "9.4.0" : "dev";
7
+ var VERSION = true ? "10.0.0" : "dev";
8
8
  var NODE_ENGINE_RANGE = ">=24";
9
9
  function isNodeVersionSupported(version) {
10
10
  return semver.satisfies(version, NODE_ENGINE_RANGE);
@@ -106,4 +106,4 @@ export {
106
106
  contextForLogging,
107
107
  measuredTrustTier
108
108
  };
109
- //# sourceMappingURL=chunk-LWLFWWA7.js.map
109
+ //# sourceMappingURL=chunk-TQZSPGAZ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts","../src/mcp/middleware/request-context.ts"],"sourcesContent":["/**\n * nexus-agents - Version constant\n *\n * Injected at build time via tsup define from package.json.\n * Do NOT edit VERSION manually — it is replaced during build.\n */\n\nimport semver from 'semver';\n\ndeclare const __NEXUS_VERSION__: string;\n\nexport const VERSION: string = typeof __NEXUS_VERSION__ !== 'undefined' ? __NEXUS_VERSION__ : 'dev';\n\n/** Supported Node.js versions. Pinned to package.json by a regression test. */\nexport const NODE_ENGINE_RANGE = '>=24';\n\n/** Returns whether a Node.js version satisfies the package engine requirement. */\nexport function isNodeVersionSupported(version: string): boolean {\n return semver.satisfies(version, NODE_ENGINE_RANGE);\n}\n","/**\n * nexus-agents/mcp - Request Context Middleware\n *\n * Provides request ID generation and caller context tracking for MCP tools.\n * (Source: Issue #185 Phase 1 - Request context & PolicyFirewall integration)\n *\n * @module mcp/middleware/request-context\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { randomBytes } from 'node:crypto';\nimport { getTimeProvider } from '../../core/index.js';\nimport type { TrustTier } from '../../security/trust-types.js';\n\n/**\n * Authenticated user information.\n * (Source: Issue #739 - MCP authentication)\n */\nexport interface AuthenticatedUser {\n /** Unique user/client identifier */\n readonly id: string;\n /** Human-readable name (optional) */\n readonly name?: string;\n /** Granted permissions/scopes (optional) */\n readonly permissions?: readonly string[];\n}\n\n/**\n * Caller identification for audit trails.\n */\nexport interface CallerInfo {\n /** Client identifier (e.g., 'claude-cli', 'gemini-cli') */\n readonly clientId?: string;\n /** User agent string if available */\n readonly userAgent?: string;\n /** Session ID for request correlation */\n readonly sessionId?: string;\n /** IP address or transport identifier */\n readonly transport?: string;\n /** Whether the request is authenticated (Issue #739) */\n readonly authenticated?: boolean;\n /** Authenticated user information (Issue #739) */\n readonly authenticatedUser?: AuthenticatedUser;\n}\n\n/**\n * Request context for MCP tool invocations.\n * Immutable once created.\n */\nexport interface RequestContext {\n /** Unique request identifier (format: req_<16 hex chars>) */\n readonly requestId: string;\n /** Timestamp when request was received (ISO 8601, ET) */\n readonly timestamp: string;\n /** Tool being invoked */\n readonly toolName: string;\n /** Caller information for audit */\n readonly caller: CallerInfo;\n /**\n * Trust tier for this request (Issue #828).\n * Derived from caller authentication state:\n * - '1' = Authenticated + known client, or stdio (local-only)\n * - '2' = Authenticated via network\n * - '3' = Unauthenticated network request\n * - '4' = Request with detected injection patterns (set by sanitizer)\n */\n readonly trustTier: TrustTier;\n /** Trace ID for distributed tracing correlation */\n readonly traceId?: string;\n /** Parent span ID if part of a larger trace */\n readonly parentSpanId?: string;\n}\n\n/**\n * Options for creating a request context.\n */\nexport interface CreateContextOptions {\n /** Tool name being invoked */\n toolName: string;\n /** Optional caller information */\n caller?: CallerInfo;\n /** Optional explicit trust tier override (defaults to derived from caller) */\n trustTier?: TrustTier;\n /** Optional trace ID for correlation */\n traceId?: string;\n /** Optional parent span ID */\n parentSpanId?: string;\n /**\n * Reuse this request id instead of minting a new one (#4981).\n *\n * Lets a nested layer join an outer layer's request identity while still\n * deriving its OWN caller, trust tier and timestamp. Adopting the outer\n * context object wholesale would discard those, which for a handler\n * configured with `callerInfo` silently downgrades the trust tier and the\n * audit actor.\n */\n inheritRequestId?: string;\n}\n\n/**\n * Generates a cryptographically secure request ID.\n * Format: req_<16 hex characters>\n *\n * @returns Unique request identifier\n */\nexport function generateRequestId(): string {\n const bytes = randomBytes(8);\n return `req_${bytes.toString('hex')}`;\n}\n\n/**\n * Generates a session ID for request correlation.\n * Format: sess_<12 hex characters>\n *\n * @returns Unique session identifier\n */\nexport function generateSessionId(): string {\n const bytes = randomBytes(6);\n return `sess_${bytes.toString('hex')}`;\n}\n\n/**\n * Formats timestamp in ISO 8601 format with ET timezone.\n * (Source: CLAUDE.md - Time Authority section)\n */\nfunction formatTimestamp(): string {\n const now = new Date(getTimeProvider().now());\n const formatter = new Intl.DateTimeFormat('en-US', {\n timeZone: 'America/New_York',\n timeZoneName: 'shortOffset',\n });\n const parts = formatter.formatToParts(now);\n const offset = parts.find((p) => p.type === 'timeZoneName')?.value ?? '-05:00';\n const base = now.toLocaleString('sv-SE', {\n timeZone: 'America/New_York',\n hour12: false,\n });\n return base.replace(' ', 'T') + offset.replace('GMT', '');\n}\n\n/**\n * Derives trust tier from caller authentication state (Issue #828).\n *\n * - Authenticated + known CLI client (claude, gemini, codex) → Tier 1\n * - stdio transport (local-only, no network) → Tier 1\n * - Authenticated via network → Tier 2\n * - Unauthenticated → Tier 3\n */\nexport function deriveTrustTier(caller: CallerInfo): TrustTier {\n const knownClients = ['claude-cli', 'gemini-cli', 'codex-cli'];\n\n if (caller.transport === 'stdio') return '1';\n\n if (caller.authenticated === true) {\n if (caller.clientId !== undefined && knownClients.includes(caller.clientId)) {\n return '1';\n }\n return '2';\n }\n\n return '3';\n}\n\n/**\n * The MCP transports this server can identify (#6795). Only stdio ships in\n * this tree; a transport the server cannot identify is not recorded at all, so\n * its requests stay on the authentication branch of {@link deriveTrustTier}.\n */\nexport type McpServerTransport = 'stdio';\n\n/**\n * The transport the server connected, recorded by `connectTransport` (#6795).\n * Process-wide because an MCP server process connects one transport, and the\n * request context is built per call by middleware that never sees it.\n */\nlet serverTransport: McpServerTransport | undefined;\n\n/**\n * Record the transport the server is connected over, or `undefined` to clear\n * it (an unidentified transport, a failed connect, or test cleanup).\n */\nexport function recordServerTransport(transport: McpServerTransport | undefined): void {\n serverTransport = transport;\n}\n\n/**\n * The caller information the server itself measured for every request: the\n * transport it arrived over (#6795). Empty when no transport was recorded, which\n * {@link measuredTrustTier} reports as unmeasured rather than as a tier.\n */\nexport function serverCallerInfo(): CallerInfo {\n return serverTransport === undefined ? {} : { transport: serverTransport };\n}\n\n/**\n * Creates an immutable request context for an MCP tool invocation.\n *\n * @param options - Context creation options\n * @returns Immutable request context\n */\nexport function createRequestContext(options: CreateContextOptions): RequestContext {\n const caller = options.caller ?? {};\n const context: RequestContext = {\n requestId: options.inheritRequestId ?? generateRequestId(),\n timestamp: formatTimestamp(),\n toolName: options.toolName,\n caller,\n trustTier: options.trustTier ?? deriveTrustTier(caller),\n ...(options.traceId !== undefined && { traceId: options.traceId }),\n ...(options.parentSpanId !== undefined && { parentSpanId: options.parentSpanId }),\n };\n\n // Freeze to ensure immutability\n return Object.freeze(context);\n}\n\n/**\n * The request context for the call currently in flight (#4981).\n *\n * Exists because a tool call passes through two middleware implementations\n * that each used to mint their own `RequestContext`, producing two unlinked\n * `req_*` ids and two `Tool invocation started` pairs per call. Argument\n * threading cannot fix that: `createSecureHandler` returns a 1-arity function,\n * so the chain's arity dispatch drops `ctx`, and 1-arity intermediaries such\n * as the `withPrerequisite` wrappers sit between the layers on some tools.\n * An ambient channel survives both.\n *\n * This mirrors the AbortSignal and progress-context storages the chain already\n * uses, so it is the established idiom here rather than a new mechanism.\n */\nconst requestContextStorage = new AsyncLocalStorage<ContextHolder>();\n\n/**\n * The ambient context plus its liveness.\n *\n * AsyncLocalStorage keeps a store reachable from anything spawned inside the\n * scope, including work that OUTLIVES the call — a `setTimeout`, or the\n * detached body `runAsJob` fires from inside the secure handler. Without this\n * flag such work still reads the context of a request that already completed,\n * and a nested handler for the same tool would adopt a finished identity, then\n * log neither a start (suppressed) nor a completion (the chain already closed\n * its own pair).\n *\n * Identity is not liveness, so the adoption gate needs both.\n */\ninterface ContextHolder {\n readonly context: RequestContext;\n settled: boolean;\n}\n\n/**\n * Runs `fn` with `context` as the ambient request context, so any nested layer\n * can adopt it instead of minting a second one.\n */\nexport function runWithRequestContext<T>(\n context: RequestContext,\n fn: () => Promise<T>\n): Promise<T> {\n const holder: ContextHolder = { context, settled: false };\n return requestContextStorage.run(holder, () =>\n fn().finally(() => {\n holder.settled = true;\n })\n );\n}\n\n/**\n * The ambient request context, or `undefined` when nothing established one.\n *\n * `undefined` is a real answer, not a failure: a caller that composes a secure\n * handler without the middleware chain — every direct test of it does — has no\n * outer context to inherit, and must mint its own.\n */\nexport function getCurrentRequestContext(): RequestContext | undefined {\n const holder = requestContextStorage.getStore();\n if (holder === undefined || holder.settled) return undefined;\n return holder.context;\n}\n\n/**\n * Formats request context for logging.\n * Extracts essential fields for log context.\n *\n * @param ctx - Request context\n * @returns Log-friendly context object\n */\nexport function contextForLogging(ctx: RequestContext): Record<string, unknown> {\n return {\n requestId: ctx.requestId,\n toolName: ctx.toolName,\n trustTier: ctx.trustTier,\n ...(ctx.caller.clientId !== undefined && { clientId: ctx.caller.clientId }),\n ...(ctx.traceId !== undefined && { traceId: ctx.traceId }),\n };\n}\n\n/**\n * Type guard to check if a value is a valid RequestContext.\n */\nexport function isRequestContext(value: unknown): value is RequestContext {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const obj = value as Record<string, unknown>;\n return (\n typeof obj['requestId'] === 'string' &&\n obj['requestId'].startsWith('req_') &&\n typeof obj['timestamp'] === 'string' &&\n typeof obj['toolName'] === 'string' &&\n typeof obj['caller'] === 'object' &&\n typeof obj['trustTier'] === 'string' &&\n ['1', '2', '3', '4'].includes(obj['trustTier'])\n );\n}\n\n/**\n * The request's trust tier ONLY when it was actually derived from caller\n * information (#4733).\n *\n * `createRequestContext` falls back to `caller = {}`, and `deriveTrustTier({})`\n * returns `'3'` — so an absent caller is indistinguishable from a genuinely\n * untrusted one at the reading end. Since #6795 the middleware chain supplies\n * the transport the server connected ({@link serverCallerInfo}), so a stdio\n * server measures tier 1; a context built with no recorded transport and no\n * authentication fact is still that fallback.\n *\n * Returning `undefined` for the fallback lets a consumer record `unmeasured`\n * rather than a constant that reads as a measurement.\n *\n * NOTE this is caller AUTHENTICATION (transport / authenticated / clientId),\n * not content provenance. A trusted client can submit hostile content. Consumers\n * wanting provenance need a different signal — `classifyTrust` is the closest,\n * but it requires a GitHub actor and does not apply to a bare goal string.\n */\nexport function measuredTrustTier(context: RequestContext): string | undefined {\n // `caller` is always set by `createRequestContext` (to `{}` at minimum), but\n // a partially-constructed context can omit it — and an absent caller is the\n // same condition as an empty one: nothing was measured.\n const caller: unknown = context.caller;\n if (typeof caller !== 'object' || caller === null) return undefined;\n\n // Gate on the fields `deriveTrustTier` actually reads, not on \"the object has\n // any key at all\" (#4738 review). A caller carrying only `sessionId` or\n // `userAgent` feeds nothing into the derivation, so a non-empty check would\n // call the '3' fallback a measurement — reintroducing the constant this\n // function exists to prevent, in the function that prevents it.\n // `clientId` is NOT sufficient either: `deriveTrustTier` reads `clientId`\n // only INSIDE the `authenticated === true` branch, so\n // `{ clientId: 'claude-cli' }` returns the same '3' fallback as `{}`. (The\n // removed env-sniffing `extractCallerInfo` produced exactly that shape.)\n const info = caller as Partial<CallerInfo>;\n // `authenticated: false` counts: it is a measured fact (\"we checked, they\n // are not authenticated\"), which is different from the field being absent.\n const derivable = info.transport !== undefined || info.authenticated !== undefined;\n\n return derivable ? context.trustTier : undefined;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/version.ts","../src/mcp/middleware/request-context.ts"],"sourcesContent":["/**\n * nexus-agents - Version constant\n *\n * Injected at build time via tsup define from package.json.\n * Do NOT edit VERSION manually — it is replaced during build.\n */\n\nimport semver from 'semver';\n\ndeclare const __NEXUS_VERSION__: string;\n\nexport const VERSION: string = typeof __NEXUS_VERSION__ !== 'undefined' ? __NEXUS_VERSION__ : 'dev';\n\n/** Supported Node.js versions. Pinned to package.json by a regression test. */\nexport const NODE_ENGINE_RANGE = '>=24';\n\n/** Returns whether a Node.js version satisfies the package engine requirement. */\nexport function isNodeVersionSupported(version: string): boolean {\n return semver.satisfies(version, NODE_ENGINE_RANGE);\n}\n","/**\n * nexus-agents/mcp - Request Context Middleware\n *\n * Provides request ID generation and caller context tracking for MCP tools.\n * (Source: Issue #185 Phase 1 - Request context & PolicyFirewall integration)\n *\n * @module mcp/middleware/request-context\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { randomBytes } from 'node:crypto';\nimport { getTimeProvider } from '../../core/index.js';\nimport type { TrustTier } from '../../security/trust-types.js';\n\n/**\n * Authenticated user information.\n * (Source: Issue #739 - MCP authentication)\n */\nexport interface AuthenticatedUser {\n /** Unique user/client identifier */\n readonly id: string;\n /** Human-readable name (optional) */\n readonly name?: string;\n /** Granted permissions/scopes (optional) */\n readonly permissions?: readonly string[];\n}\n\n/**\n * Caller identification for audit trails.\n */\nexport interface CallerInfo {\n /** Client identifier (e.g., 'claude-cli', 'gemini-cli') */\n readonly clientId?: string;\n /** User agent string if available */\n readonly userAgent?: string;\n /** Session ID for request correlation */\n readonly sessionId?: string;\n /** IP address or transport identifier */\n readonly transport?: string;\n /** Whether the request is authenticated (Issue #739) */\n readonly authenticated?: boolean;\n /** Authenticated user information (Issue #739) */\n readonly authenticatedUser?: AuthenticatedUser;\n}\n\n/**\n * Request context for MCP tool invocations.\n * Immutable once created.\n */\nexport interface RequestContext {\n /** Unique request identifier (format: req_<16 hex chars>) */\n readonly requestId: string;\n /** Timestamp when request was received (ISO 8601, ET) */\n readonly timestamp: string;\n /** Tool being invoked */\n readonly toolName: string;\n /** Caller information for audit */\n readonly caller: CallerInfo;\n /**\n * Trust tier for this request (Issue #828).\n * Derived from caller authentication state:\n * - '1' = Authenticated + known client, or stdio (local-only)\n * - '2' = Authenticated via network\n * - '3' = Unauthenticated network request\n * - '4' = Request with detected injection patterns (set by sanitizer)\n */\n readonly trustTier: TrustTier;\n /** Trace ID for distributed tracing correlation */\n readonly traceId?: string;\n /** Parent span ID if part of a larger trace */\n readonly parentSpanId?: string;\n}\n\n/**\n * Options for creating a request context.\n */\nexport interface CreateContextOptions {\n /** Tool name being invoked */\n toolName: string;\n /** Optional caller information */\n caller?: CallerInfo;\n /** Optional explicit trust tier override (defaults to derived from caller) */\n trustTier?: TrustTier;\n /** Optional trace ID for correlation */\n traceId?: string;\n /** Optional parent span ID */\n parentSpanId?: string;\n /**\n * Reuse this request id instead of minting a new one (#4981).\n *\n * Lets a nested layer join an outer layer's request identity while still\n * deriving its OWN caller, trust tier and timestamp. Adopting the outer\n * context object wholesale would discard those, which for a handler\n * configured with `callerInfo` silently downgrades the trust tier and the\n * audit actor.\n */\n inheritRequestId?: string;\n}\n\n/**\n * Generates a cryptographically secure request ID.\n * Format: req_<16 hex characters>\n *\n * @returns Unique request identifier\n */\nexport function generateRequestId(): string {\n const bytes = randomBytes(8);\n return `req_${bytes.toString('hex')}`;\n}\n\n/**\n * Generates a session ID for request correlation.\n * Format: sess_<12 hex characters>\n *\n * @returns Unique session identifier\n */\nexport function generateSessionId(): string {\n const bytes = randomBytes(6);\n return `sess_${bytes.toString('hex')}`;\n}\n\n/**\n * Formats timestamp in ISO 8601 format with ET timezone.\n * (Source: CLAUDE.md - Time Authority section)\n */\nfunction formatTimestamp(): string {\n const now = new Date(getTimeProvider().now());\n const formatter = new Intl.DateTimeFormat('en-US', {\n timeZone: 'America/New_York',\n timeZoneName: 'shortOffset',\n });\n const parts = formatter.formatToParts(now);\n const offset = parts.find((p) => p.type === 'timeZoneName')?.value ?? '-05:00';\n const base = now.toLocaleString('sv-SE', {\n timeZone: 'America/New_York',\n hour12: false,\n });\n return base.replace(' ', 'T') + offset.replace('GMT', '');\n}\n\n/**\n * Derives trust tier from caller authentication state (Issue #828).\n *\n * - Authenticated + known CLI client (claude, gemini, codex) → Tier 1\n * - stdio transport (local-only, no network) → Tier 1\n * - Authenticated via network → Tier 2\n * - Unauthenticated → Tier 3\n */\nexport function deriveTrustTier(caller: CallerInfo): TrustTier {\n const knownClients = ['claude-cli', 'gemini-cli', 'codex-cli'];\n\n if (caller.transport === 'stdio') return '1';\n\n if (caller.authenticated === true) {\n if (caller.clientId !== undefined && knownClients.includes(caller.clientId)) {\n return '1';\n }\n return '2';\n }\n\n return '3';\n}\n\n/**\n * The MCP transports this server can identify (#6795). Only stdio ships in\n * this tree; a transport the server cannot identify is not recorded at all, so\n * its requests stay on the authentication branch of {@link deriveTrustTier}.\n */\nexport type McpServerTransport = 'stdio';\n\n/**\n * The transport the server connected, recorded by `connectTransport` (#6795).\n * Process-wide because an MCP server process connects one transport, and the\n * request context is built per call by middleware that never sees it.\n */\nlet serverTransport: McpServerTransport | undefined;\n\n/**\n * Record the transport the server is connected over, or `undefined` to clear\n * it (an unidentified transport, a failed connect, or test cleanup).\n */\nexport function recordServerTransport(transport: McpServerTransport | undefined): void {\n serverTransport = transport;\n}\n\n/**\n * The caller information the server itself measured for every request: the\n * transport it arrived over (#6795). Empty when no transport was recorded, which\n * {@link measuredTrustTier} reports as unmeasured rather than as a tier.\n */\nexport function serverCallerInfo(): CallerInfo {\n return serverTransport === undefined ? {} : { transport: serverTransport };\n}\n\n/**\n * Creates an immutable request context for an MCP tool invocation.\n *\n * @param options - Context creation options\n * @returns Immutable request context\n */\nexport function createRequestContext(options: CreateContextOptions): RequestContext {\n const caller = options.caller ?? {};\n const context: RequestContext = {\n requestId: options.inheritRequestId ?? generateRequestId(),\n timestamp: formatTimestamp(),\n toolName: options.toolName,\n caller,\n trustTier: options.trustTier ?? deriveTrustTier(caller),\n ...(options.traceId !== undefined && { traceId: options.traceId }),\n ...(options.parentSpanId !== undefined && { parentSpanId: options.parentSpanId }),\n };\n\n // Freeze to ensure immutability\n return Object.freeze(context);\n}\n\n/**\n * The request context for the call currently in flight (#4981).\n *\n * Exists because a tool call passes through two middleware implementations\n * that each used to mint their own `RequestContext`, producing two unlinked\n * `req_*` ids and two `Tool invocation started` pairs per call. Argument\n * threading cannot fix that: `createSecureHandler` returns a 1-arity function,\n * so the chain's arity dispatch drops `ctx`, and 1-arity intermediaries such\n * as the `withPrerequisite` wrappers sit between the layers on some tools.\n * An ambient channel survives both.\n *\n * This mirrors the AbortSignal and progress-context storages the chain already\n * uses, so it is the established idiom here rather than a new mechanism.\n */\nconst requestContextStorage = new AsyncLocalStorage<ContextHolder>();\n\n/**\n * The ambient context plus its liveness.\n *\n * AsyncLocalStorage keeps a store reachable from anything spawned inside the\n * scope, including work that OUTLIVES the call — a `setTimeout`, or the\n * detached body `runAsJob` fires from inside the secure handler. Without this\n * flag such work still reads the context of a request that already completed,\n * and a nested handler for the same tool would adopt a finished identity, then\n * log neither a start (suppressed) nor a completion (the chain already closed\n * its own pair).\n *\n * Identity is not liveness, so the adoption gate needs both.\n */\ninterface ContextHolder {\n readonly context: RequestContext;\n settled: boolean;\n}\n\n/**\n * Runs `fn` with `context` as the ambient request context, so any nested layer\n * can adopt it instead of minting a second one.\n */\nexport function runWithRequestContext<T>(\n context: RequestContext,\n fn: () => Promise<T>\n): Promise<T> {\n const holder: ContextHolder = { context, settled: false };\n return requestContextStorage.run(holder, () =>\n fn().finally(() => {\n holder.settled = true;\n })\n );\n}\n\n/**\n * The ambient request context, or `undefined` when nothing established one.\n *\n * `undefined` is a real answer, not a failure: a caller that composes a secure\n * handler without the middleware chain — every direct test of it does — has no\n * outer context to inherit, and must mint its own.\n */\nexport function getCurrentRequestContext(): RequestContext | undefined {\n const holder = requestContextStorage.getStore();\n if (holder === undefined || holder.settled) return undefined;\n return holder.context;\n}\n\n/**\n * Formats request context for logging.\n * Extracts essential fields for log context.\n *\n * @param ctx - Request context\n * @returns Log-friendly context object\n */\nexport function contextForLogging(ctx: RequestContext): Record<string, unknown> {\n return {\n requestId: ctx.requestId,\n toolName: ctx.toolName,\n trustTier: ctx.trustTier,\n ...(ctx.caller.clientId !== undefined && { clientId: ctx.caller.clientId }),\n ...(ctx.traceId !== undefined && { traceId: ctx.traceId }),\n };\n}\n\n/**\n * Type guard to check if a value is a valid RequestContext.\n */\nexport function isRequestContext(value: unknown): value is RequestContext {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n const obj = value as Record<string, unknown>;\n return (\n typeof obj['requestId'] === 'string' &&\n obj['requestId'].startsWith('req_') &&\n typeof obj['timestamp'] === 'string' &&\n typeof obj['toolName'] === 'string' &&\n typeof obj['caller'] === 'object' &&\n typeof obj['trustTier'] === 'string' &&\n ['1', '2', '3', '4'].includes(obj['trustTier'])\n );\n}\n\n/**\n * The request's trust tier ONLY when it was actually derived from caller\n * information (#4733).\n *\n * `createRequestContext` falls back to `caller = {}`, and `deriveTrustTier({})`\n * returns `'3'` — so an absent caller is indistinguishable from a genuinely\n * untrusted one at the reading end. Since #6795 the middleware chain supplies\n * the transport the server connected ({@link serverCallerInfo}), so a stdio\n * server measures tier 1; a context built with no recorded transport and no\n * authentication fact is still that fallback.\n *\n * Returning `undefined` for the fallback lets a consumer record `unmeasured`\n * rather than a constant that reads as a measurement.\n *\n * NOTE this is caller AUTHENTICATION (transport / authenticated / clientId),\n * not content provenance. A trusted client can submit hostile content. Consumers\n * wanting provenance need a different signal — `classifyTrust` is the closest,\n * but it requires a GitHub actor and does not apply to a bare goal string.\n */\nexport function measuredTrustTier(context: RequestContext): string | undefined {\n // `caller` is always set by `createRequestContext` (to `{}` at minimum), but\n // a partially-constructed context can omit it — and an absent caller is the\n // same condition as an empty one: nothing was measured.\n const caller: unknown = context.caller;\n if (typeof caller !== 'object' || caller === null) return undefined;\n\n // Gate on the fields `deriveTrustTier` actually reads, not on \"the object has\n // any key at all\" (#4738 review). A caller carrying only `sessionId` or\n // `userAgent` feeds nothing into the derivation, so a non-empty check would\n // call the '3' fallback a measurement — reintroducing the constant this\n // function exists to prevent, in the function that prevents it.\n // `clientId` is NOT sufficient either: `deriveTrustTier` reads `clientId`\n // only INSIDE the `authenticated === true` branch, so\n // `{ clientId: 'claude-cli' }` returns the same '3' fallback as `{}`. (The\n // removed env-sniffing `extractCallerInfo` produced exactly that shape.)\n const info = caller as Partial<CallerInfo>;\n // `authenticated: false` counts: it is a measured fact (\"we checked, they\n // are not authenticated\"), which is different from the field being absent.\n const derivable = info.transport !== undefined || info.authenticated !== undefined;\n\n return derivable ? context.trustTier : undefined;\n}\n"],"mappings":"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","names":[]}
@@ -87,8 +87,10 @@ var SecurityConfigSchema = z.object({
87
87
  auth: z.object({
88
88
  /** Enable authentication for network-exposed transports (default: true) */
89
89
  enabled: z.boolean().default(true),
90
- /** Authentication method (default: 'token') */
91
- method: z.enum(["token", "oauth2"]).default("token"),
90
+ /** Authentication method (only 'token' is supported) */
91
+ method: z.enum(["token"], {
92
+ error: (issue) => issue.input === "oauth2" ? "security.auth.method 'oauth2' was never implemented and is no longer accepted. Set security.auth.method to 'token' for bearer-token authentication (#5681)." : void 0
93
+ }).default("token"),
92
94
  /** Header name for bearer token (default: 'Authorization') */
93
95
  tokenHeader: z.string().default("Authorization"),
94
96
  /** Token file path (default: ~/.nexus-agents/auth/server-token) */
@@ -101,4 +103,4 @@ export {
101
103
  DEFAULT_TOOL_RATE_LIMITS,
102
104
  SecurityConfigSchema
103
105
  };
104
- //# sourceMappingURL=chunk-ECJ52NSK.js.map
106
+ //# sourceMappingURL=chunk-TYLE7Z2S.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config/schemas-security.ts"],"sourcesContent":["/**\n * nexus-agents/config - Security Configuration Schemas\n *\n * Schemas for security, policy, sandbox, timeout, and rate limiting.\n */\n\nimport { z } from 'zod';\n\n/**\n * The ONE default for `security.policy.defaultMode` (#6431). `DEFAULTS`,\n * `getPolicyValues`, the middleware `PolicyConfigSchema` and the policy\n * registry all read this constant; a second literal is how the config default\n * and the `?? 'read-only'` fallbacks drifted apart.\n *\n * `'read-write'` because the `deny-mutations-without-mode` rule fires on every\n * manifest-classified mutation tool under `'read-only'`, and nothing on the\n * MCP path sets the mode per call — so a `'read-only'` default would deny all\n * 20 mutation tools (the manifest's `readOnlyHint: false` entries) for every\n * operator the day enforcement defaults on (panel option A, 6-0).\n * `'read-only'` remains an operator opt-in lock, and `run { execute: true }`\n * is checked under it as the tool its selected strategy runs.\n */\nexport const DEFAULT_EXECUTION_MODE = 'read-write' as const;\n\n/**\n * Policy configuration schema.\n *\n * Controls authorization behavior for tool operations.\n * - defaultMode: the execution mode every MCP tool call is evaluated under.\n * `'read-write'` (default) allows manifest-classified mutation tools;\n * `'read-only'` is an operator lock that forbids every one of them — and\n * `run { execute: true }` as its selected strategy's tool — once the\n * firewall enforces (`NEXUS_MCP_POLICY_ENFORCE`), and is logged as a\n * would-be denial in warn mode.\n * - policyMode: Whether to enforce denials or just warn (for migration). Not\n * read for the effective firewall mode today — see\n * `stagePolicyFirewallForRollout` (#4888, #4988).\n *\n * (Source: OWASP ASVS 4.0, Authorization Controls)\n */\nexport const PolicyConfigSchema = z.object({\n /** Execution mode for tool operations (default: 'read-write'; 'read-only' is the opt-in lock, #6431) */\n defaultMode: z.enum(['read-only', 'read-write']).default(DEFAULT_EXECUTION_MODE),\n /** Policy enforcement mode (default: 'enforce') */\n policyMode: z.enum(['enforce', 'warn']).default('enforce'),\n});\n\nexport type PolicyConfig = z.infer<typeof PolicyConfigSchema>;\n\n/**\n * Sandbox configuration schema.\n *\n * Controls agent execution isolation.\n * - mode: 'none' (no isolation), 'policy' (allowlist enforcement), 'container' (Docker)\n * - fallbackToPolicy: Whether to fall back to policy mode if container unavailable\n *\n * (Source: Issue #175, ALIGNMENT_ROADMAP Phase 4)\n */\nexport const SandboxConfigSchema = z.object({\n /** Sandbox execution mode (default: 'policy') */\n mode: z.enum(['none', 'policy', 'container']).default('policy'),\n /** Fall back to policy mode if container mode unavailable (default: true) */\n fallbackToPolicy: z.boolean().default(true),\n /** Docker image to use in container mode (default: 'node:22-alpine') */\n dockerImage: z.string().optional(),\n /** Enable network access in container mode (default: false) */\n networkEnabled: z.boolean().default(false),\n});\n\nexport type SandboxConfig = z.infer<typeof SandboxConfigSchema>;\n\n/**\n * Timeout configuration schema.\n *\n * Controls timeout behavior for MCP operations to mitigate CVE-2026-0621.\n * - defaultTimeoutMs: Default timeout for operations\n * - maxTimeoutMs: Maximum allowed timeout\n * - enableLogging: Whether to log timeout events\n * - uriValidation: Whether to validate URIs against ReDoS patterns\n *\n * (Source: Issue #271, CVE-2026-0621 mitigation)\n */\nexport const TimeoutConfigSchema = z.object({\n /** Default timeout in milliseconds (default: 30000) */\n defaultTimeoutMs: z.number().positive().default(30000),\n /** Maximum timeout in milliseconds (default: 300000) */\n maxTimeoutMs: z.number().positive().default(300000),\n /** Whether to log timeout events (default: true) */\n enableLogging: z.boolean().default(true),\n /** Enable URI validation to prevent ReDoS (default: true) */\n uriValidation: z.boolean().default(true),\n /** Per-tool timeout overrides in milliseconds (Issue #657) */\n perToolTimeout: z.record(z.string(), z.number().positive().max(600000)).optional(),\n});\n\nexport type TimeoutConfig = z.infer<typeof TimeoutConfigSchema>;\n\n/**\n * Per-tool rate limit configuration.\n * Allows different limits for each tool category.\n *\n * (Source: Issue #274 Phase 2 - per-tool rate limits)\n */\nexport const ToolRateLimitSchema = z.object({\n /** Maximum tokens (burst capacity) */\n capacity: z.number().positive().default(10),\n /** Tokens refilled per interval */\n refillRate: z.number().positive().default(10),\n /** Refill interval in milliseconds (default: 60000 = 1 minute) */\n refillIntervalMs: z.number().positive().default(60000),\n});\n\nexport type ToolRateLimit = z.infer<typeof ToolRateLimitSchema>;\n\n/**\n * Default per-tool rate limits per Issue #274.\n */\nexport const DEFAULT_TOOL_RATE_LIMITS = {\n orchestrate: { capacity: 10, refillRate: 10, refillIntervalMs: 60000 },\n delegate: { capacity: 20, refillRate: 20, refillIntervalMs: 60000 },\n workflow: { capacity: 5, refillRate: 5, refillIntervalMs: 60000 },\n expert: { capacity: 30, refillRate: 30, refillIntervalMs: 60000 },\n} as const satisfies Record<string, ToolRateLimit>;\n\n/**\n * Tool categories for rate limiting.\n */\nexport type ToolCategory = keyof typeof DEFAULT_TOOL_RATE_LIMITS;\n\n/**\n * Security configuration schema.\n */\nexport const SecurityConfigSchema = z.object({\n allowedPaths: z.array(z.string()).default(['./']),\n blockedPatterns: z.array(z.string()).default([]),\n rateLimit: z\n .object({\n enabled: z.boolean().default(true),\n requestsPerMinute: z.number().positive().default(60),\n /** Per-tool rate limits (Issue #274 Phase 2) */\n perTool: z.record(z.string(), ToolRateLimitSchema).optional(),\n })\n .default(() => ({ enabled: true, requestsPerMinute: 60 })),\n secretsFile: z.string().optional(),\n /** Policy firewall configuration */\n policy: PolicyConfigSchema.optional(),\n /** Sandbox execution configuration (Issue #175) */\n sandbox: SandboxConfigSchema.optional(),\n /** Timeout configuration (Issue #271, CVE-2026-0621) */\n timeout: TimeoutConfigSchema.optional(),\n /** Tool allowlist — when set, only listed tools are registered (Issue #740) */\n toolAllowlist: z.array(z.string()).optional(),\n /**\n * Audit logging configuration (Issue #740 Phase 2).\n *\n * The block is optional and the inner defaults only apply when it is present:\n * a config with no `audit:` block is audit-OFF (`initializeAuditLogger`\n * returns null and startup warns). `config init` writes the block explicitly\n * so a generated config is on by default (#5632).\n */\n audit: z\n .object({\n /** Enable audit logging (default when the block is present: true) */\n enabled: z.boolean().default(true),\n /** Log directory (default: ~/.nexus-agents/audit) */\n logDir: z.string().optional(),\n /** Minimum severity to log (default: 'info') */\n minSeverity: z.enum(['info', 'warning', 'critical']).default('info'),\n /** Enable tamper-evident hash chain (default: true) */\n enableHashChain: z.boolean().default(true),\n /** Maximum log file size in bytes (default: 10MB) */\n maxFileSizeBytes: z\n .number()\n .positive()\n .default(10 * 1024 * 1024),\n /** Maximum number of log files to retain (default: 10) */\n maxFiles: z.number().positive().default(10),\n })\n .optional(),\n /** Authentication configuration (Issue #739) */\n auth: z\n .object({\n /** Enable authentication for network-exposed transports (default: true) */\n enabled: z.boolean().default(true),\n /** Authentication method (default: 'token') */\n method: z.enum(['token', 'oauth2']).default('token'),\n /** Header name for bearer token (default: 'Authorization') */\n tokenHeader: z.string().default('Authorization'),\n /** Token file path (default: ~/.nexus-agents/auth/server-token) */\n tokenFile: z.string().optional(),\n })\n .optional(),\n});\n\nexport type SecurityConfig = z.infer<typeof SecurityConfigSchema>;\n\n/**\n * Authentication configuration type.\n * (Source: Issue #739 - enable MCP authentication by default)\n */\nexport type AuthConfig = NonNullable<SecurityConfig['auth']>;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/config/schemas-security.ts"],"sourcesContent":["/**\n * nexus-agents/config - Security Configuration Schemas\n *\n * Schemas for security, policy, sandbox, timeout, and rate limiting.\n */\n\nimport { z } from 'zod';\n\n/**\n * The ONE default for `security.policy.defaultMode` (#6431). `DEFAULTS`,\n * `getPolicyValues`, the middleware `PolicyConfigSchema` and the policy\n * registry all read this constant; a second literal is how the config default\n * and the `?? 'read-only'` fallbacks drifted apart.\n *\n * `'read-write'` because the `deny-mutations-without-mode` rule fires on every\n * manifest-classified mutation tool under `'read-only'`, and nothing on the\n * MCP path sets the mode per call — so a `'read-only'` default would deny all\n * 20 mutation tools (the manifest's `readOnlyHint: false` entries) for every\n * operator the day enforcement defaults on (panel option A, 6-0).\n * `'read-only'` remains an operator opt-in lock, and `run { execute: true }`\n * is checked under it as the tool its selected strategy runs.\n */\nexport const DEFAULT_EXECUTION_MODE = 'read-write' as const;\n\n/**\n * Policy configuration schema.\n *\n * Controls authorization behavior for tool operations.\n * - defaultMode: the execution mode every MCP tool call is evaluated under.\n * `'read-write'` (default) allows manifest-classified mutation tools;\n * `'read-only'` is an operator lock that forbids every one of them — and\n * `run { execute: true }` as its selected strategy's tool — once the\n * firewall enforces (`NEXUS_MCP_POLICY_ENFORCE`), and is logged as a\n * would-be denial in warn mode.\n * - policyMode: Whether to enforce denials or just warn (for migration). Not\n * read for the effective firewall mode today — see\n * `stagePolicyFirewallForRollout` (#4888, #4988).\n *\n * (Source: OWASP ASVS 4.0, Authorization Controls)\n */\nexport const PolicyConfigSchema = z.object({\n /** Execution mode for tool operations (default: 'read-write'; 'read-only' is the opt-in lock, #6431) */\n defaultMode: z.enum(['read-only', 'read-write']).default(DEFAULT_EXECUTION_MODE),\n /** Policy enforcement mode (default: 'enforce') */\n policyMode: z.enum(['enforce', 'warn']).default('enforce'),\n});\n\nexport type PolicyConfig = z.infer<typeof PolicyConfigSchema>;\n\n/**\n * Sandbox configuration schema.\n *\n * Controls agent execution isolation.\n * - mode: 'none' (no isolation), 'policy' (allowlist enforcement), 'container' (Docker)\n * - fallbackToPolicy: Whether to fall back to policy mode if container unavailable\n *\n * (Source: Issue #175, ALIGNMENT_ROADMAP Phase 4)\n */\nexport const SandboxConfigSchema = z.object({\n /** Sandbox execution mode (default: 'policy') */\n mode: z.enum(['none', 'policy', 'container']).default('policy'),\n /** Fall back to policy mode if container mode unavailable (default: true) */\n fallbackToPolicy: z.boolean().default(true),\n /** Docker image to use in container mode (default: 'node:22-alpine') */\n dockerImage: z.string().optional(),\n /** Enable network access in container mode (default: false) */\n networkEnabled: z.boolean().default(false),\n});\n\nexport type SandboxConfig = z.infer<typeof SandboxConfigSchema>;\n\n/**\n * Timeout configuration schema.\n *\n * Controls timeout behavior for MCP operations to mitigate CVE-2026-0621.\n * - defaultTimeoutMs: Default timeout for operations\n * - maxTimeoutMs: Maximum allowed timeout\n * - enableLogging: Whether to log timeout events\n * - uriValidation: Whether to validate URIs against ReDoS patterns\n *\n * (Source: Issue #271, CVE-2026-0621 mitigation)\n */\nexport const TimeoutConfigSchema = z.object({\n /** Default timeout in milliseconds (default: 30000) */\n defaultTimeoutMs: z.number().positive().default(30000),\n /** Maximum timeout in milliseconds (default: 300000) */\n maxTimeoutMs: z.number().positive().default(300000),\n /** Whether to log timeout events (default: true) */\n enableLogging: z.boolean().default(true),\n /** Enable URI validation to prevent ReDoS (default: true) */\n uriValidation: z.boolean().default(true),\n /** Per-tool timeout overrides in milliseconds (Issue #657) */\n perToolTimeout: z.record(z.string(), z.number().positive().max(600000)).optional(),\n});\n\nexport type TimeoutConfig = z.infer<typeof TimeoutConfigSchema>;\n\n/**\n * Per-tool rate limit configuration.\n * Allows different limits for each tool category.\n *\n * (Source: Issue #274 Phase 2 - per-tool rate limits)\n */\nexport const ToolRateLimitSchema = z.object({\n /** Maximum tokens (burst capacity) */\n capacity: z.number().positive().default(10),\n /** Tokens refilled per interval */\n refillRate: z.number().positive().default(10),\n /** Refill interval in milliseconds (default: 60000 = 1 minute) */\n refillIntervalMs: z.number().positive().default(60000),\n});\n\nexport type ToolRateLimit = z.infer<typeof ToolRateLimitSchema>;\n\n/**\n * Default per-tool rate limits per Issue #274.\n */\nexport const DEFAULT_TOOL_RATE_LIMITS = {\n orchestrate: { capacity: 10, refillRate: 10, refillIntervalMs: 60000 },\n delegate: { capacity: 20, refillRate: 20, refillIntervalMs: 60000 },\n workflow: { capacity: 5, refillRate: 5, refillIntervalMs: 60000 },\n expert: { capacity: 30, refillRate: 30, refillIntervalMs: 60000 },\n} as const satisfies Record<string, ToolRateLimit>;\n\n/**\n * Tool categories for rate limiting.\n */\nexport type ToolCategory = keyof typeof DEFAULT_TOOL_RATE_LIMITS;\n\n/**\n * Security configuration schema.\n */\nexport const SecurityConfigSchema = z.object({\n allowedPaths: z.array(z.string()).default(['./']),\n blockedPatterns: z.array(z.string()).default([]),\n rateLimit: z\n .object({\n enabled: z.boolean().default(true),\n requestsPerMinute: z.number().positive().default(60),\n /** Per-tool rate limits (Issue #274 Phase 2) */\n perTool: z.record(z.string(), ToolRateLimitSchema).optional(),\n })\n .default(() => ({ enabled: true, requestsPerMinute: 60 })),\n secretsFile: z.string().optional(),\n /** Policy firewall configuration */\n policy: PolicyConfigSchema.optional(),\n /** Sandbox execution configuration (Issue #175) */\n sandbox: SandboxConfigSchema.optional(),\n /** Timeout configuration (Issue #271, CVE-2026-0621) */\n timeout: TimeoutConfigSchema.optional(),\n /** Tool allowlist — when set, only listed tools are registered (Issue #740) */\n toolAllowlist: z.array(z.string()).optional(),\n /**\n * Audit logging configuration (Issue #740 Phase 2).\n *\n * The block is optional and the inner defaults only apply when it is present:\n * a config with no `audit:` block is audit-OFF (`initializeAuditLogger`\n * returns null and startup warns). `config init` writes the block explicitly\n * so a generated config is on by default (#5632).\n */\n audit: z\n .object({\n /** Enable audit logging (default when the block is present: true) */\n enabled: z.boolean().default(true),\n /** Log directory (default: ~/.nexus-agents/audit) */\n logDir: z.string().optional(),\n /** Minimum severity to log (default: 'info') */\n minSeverity: z.enum(['info', 'warning', 'critical']).default('info'),\n /** Enable tamper-evident hash chain (default: true) */\n enableHashChain: z.boolean().default(true),\n /** Maximum log file size in bytes (default: 10MB) */\n maxFileSizeBytes: z\n .number()\n .positive()\n .default(10 * 1024 * 1024),\n /** Maximum number of log files to retain (default: 10) */\n maxFiles: z.number().positive().default(10),\n })\n .optional(),\n /** Authentication configuration (Issue #739) */\n auth: z\n .object({\n /** Enable authentication for network-exposed transports (default: true) */\n enabled: z.boolean().default(true),\n /** Authentication method (only 'token' is supported) */\n method: z\n .enum(['token'], {\n error: (issue) =>\n issue.input === 'oauth2'\n ? \"security.auth.method 'oauth2' was never implemented and is no longer accepted. \" +\n \"Set security.auth.method to 'token' for bearer-token authentication (#5681).\"\n : undefined,\n })\n .default('token'),\n /** Header name for bearer token (default: 'Authorization') */\n tokenHeader: z.string().default('Authorization'),\n /** Token file path (default: ~/.nexus-agents/auth/server-token) */\n tokenFile: z.string().optional(),\n })\n .optional(),\n});\n\nexport type SecurityConfig = z.infer<typeof SecurityConfigSchema>;\n\n/**\n * Authentication configuration type.\n * (Source: Issue #739 - enable MCP authentication by default)\n */\nexport type AuthConfig = NonNullable<SecurityConfig['auth']>;\n"],"mappings":"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","names":[]}
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  createAutoAdapter
3
- } from "./chunk-ONYCBTOH.js";
3
+ } from "./chunk-O3VPGING.js";
4
4
  import {
5
5
  ensureGatewayDiscovered,
6
6
  gatewayDiscoveryGeneration
7
- } from "./chunk-VQGHQVD2.js";
7
+ } from "./chunk-QPU7QKPT.js";
8
8
  import {
9
9
  getDefaultCliCircuitBreakerRegistry
10
- } from "./chunk-AYBOQE2Y.js";
10
+ } from "./chunk-VHOOJ4FG.js";
11
11
  import {
12
12
  CircularBuffer,
13
13
  ConfigError,
@@ -32,7 +32,7 @@ import {
32
32
  recordRateLimitEvent,
33
33
  toRateLimitError,
34
34
  warnIfGatewayCostUndeclared
35
- } from "./chunk-7XJZTSHW.js";
35
+ } from "./chunk-WI73OZAU.js";
36
36
  import {
37
37
  TASK_SPECIALIZATION_MATRIX,
38
38
  detectTaskCategory
@@ -946,8 +946,6 @@ var UnifiedAdapterRegistry = class {
946
946
  getSnapshot() {
947
947
  return {
948
948
  taskRouting: TASK_SPECIALIZATION_MATRIX.map((spec) => this.resolveRouting(spec)),
949
- /** @deprecated Use {@link RegistrySnapshot.cachedArms}; removed in 10.0, #6291. */
950
- cachedAdapters: [...this.cliAdapters.keys()].filter(isCliName),
951
949
  cachedArms: [...this.cliAdapters.keys()],
952
950
  availableModels: getInTreeCapabilitiesMatrix().models.length
953
951
  };
@@ -1056,4 +1054,4 @@ export {
1056
1054
  getGlobalRegistry,
1057
1055
  resetGlobalRegistry
1058
1056
  };
1059
- //# sourceMappingURL=chunk-TFQMVUWQ.js.map
1057
+ //# sourceMappingURL=chunk-V5FGXVSX.js.map