nexus-agents 10.2.0 → 11.0.1

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 (187) hide show
  1. package/README.md +4 -1
  2. package/dist/{ast-rule-runner-RI7ZJ4ZI.js → ast-rule-runner-RL6XHXJB.js} +5 -5
  3. package/dist/{child-mcp-config-73BX4OTR.js → child-mcp-config-ADRNVJJB.js} +5 -5
  4. package/dist/{chunk-TDUXUVUU.js → chunk-3LE73MVE.js} +2 -2
  5. package/dist/{chunk-FNHVTDHZ.js → chunk-63YC42C2.js} +3 -3
  6. package/dist/{chunk-U37AITDA.js → chunk-6JMULY2R.js} +2 -2
  7. package/dist/{chunk-LP5ISXKM.js → chunk-6Y55UUWK.js} +5 -5
  8. package/dist/{chunk-QM5W3T3O.js → chunk-A7XALVN3.js} +2 -2
  9. package/dist/{chunk-JGY5HMWI.js → chunk-AX5DBV3M.js} +2 -2
  10. package/dist/{chunk-VLOPXV47.js → chunk-BHH3PKI6.js} +7 -7
  11. package/dist/{chunk-TW6PJYTP.js → chunk-C73VZSC5.js} +1 -1
  12. package/dist/chunk-C73VZSC5.js.map +1 -0
  13. package/dist/{chunk-LWOX65CP.js → chunk-CH6IBWXH.js} +31 -31
  14. package/dist/chunk-CH6IBWXH.js.map +1 -0
  15. package/dist/{chunk-RIYFVDYN.js → chunk-CSDGNGAG.js} +2 -2
  16. package/dist/{chunk-WD4DENPC.js → chunk-CXRZQ4NH.js} +3 -3
  17. package/dist/{chunk-SS53PZO6.js → chunk-DYV7XS26.js} +5 -5
  18. package/dist/{chunk-WKFPKPEM.js → chunk-EBOAFTOG.js} +458 -134
  19. package/dist/chunk-EBOAFTOG.js.map +1 -0
  20. package/dist/chunk-FMIALWCD.js +1046 -0
  21. package/dist/chunk-FMIALWCD.js.map +1 -0
  22. package/dist/{chunk-GAX75XCV.js → chunk-G2OI3KA4.js} +2 -2
  23. package/dist/{chunk-QG3VDSWD.js → chunk-GU2HV6KI.js} +3 -3
  24. package/dist/{chunk-2TA6KTRF.js → chunk-HBEZ2J4F.js} +16 -18
  25. package/dist/{chunk-2TA6KTRF.js.map → chunk-HBEZ2J4F.js.map} +1 -1
  26. package/dist/{chunk-QRC3QLUQ.js → chunk-HL3EHBKJ.js} +1086 -14
  27. package/dist/chunk-HL3EHBKJ.js.map +1 -0
  28. package/dist/{chunk-3UWT434E.js → chunk-I2THTVA4.js} +17 -10
  29. package/dist/chunk-I2THTVA4.js.map +1 -0
  30. package/dist/{chunk-OMSKBBL7.js → chunk-JKLXFENK.js} +18 -19
  31. package/dist/chunk-JKLXFENK.js.map +1 -0
  32. package/dist/{chunk-2DYCHHWW.js → chunk-KSSPY5KX.js} +4 -4
  33. package/dist/{chunk-23QA6GQD.js → chunk-LAUBKK25.js} +7 -7
  34. package/dist/{chunk-7EV3QAKO.js → chunk-MTB5BXYJ.js} +2 -2
  35. package/dist/{chunk-XSAUVC6D.js → chunk-NLFCAEEK.js} +2 -2
  36. package/dist/{chunk-PXYSAG5B.js → chunk-NVE262E3.js} +2 -2
  37. package/dist/{chunk-V26YQQK4.js → chunk-NY7IMAG5.js} +2 -2
  38. package/dist/{chunk-KLSNDPU6.js → chunk-NZA7EIZO.js} +17 -32
  39. package/dist/chunk-NZA7EIZO.js.map +1 -0
  40. package/dist/{chunk-XDUTAUK3.js → chunk-OKMSQJQJ.js} +75 -61
  41. package/dist/chunk-OKMSQJQJ.js.map +1 -0
  42. package/dist/{chunk-KASBBKAQ.js → chunk-OYAHRYFI.js} +54 -54
  43. package/dist/chunk-OYAHRYFI.js.map +1 -0
  44. package/dist/{chunk-GX5ZHZR2.js → chunk-PYAR3CVN.js} +7 -7
  45. package/dist/{chunk-EJ5EBTAV.js → chunk-QKWZZM2D.js} +2 -2
  46. package/dist/{chunk-FWQSOPBA.js → chunk-RR2Y2HVZ.js} +6 -6
  47. package/dist/{chunk-UE7A2XHM.js → chunk-RUHKJC3X.js} +2 -2
  48. package/dist/{chunk-D6E3LJGP.js → chunk-S4QYN2AV.js} +4 -4
  49. package/dist/{chunk-J44RKRGQ.js → chunk-TW4R2Q55.js} +4 -4
  50. package/dist/{chunk-QS5HGPCN.js → chunk-TWQEUAUG.js} +2 -2
  51. package/dist/{chunk-JPFRRNRR.js → chunk-U7HL7FGS.js} +2 -2
  52. package/dist/{chunk-JUUGLXSN.js → chunk-WAPGSEIM.js} +5 -5
  53. package/dist/{chunk-LXYT2P2Y.js → chunk-WILZPMEM.js} +3 -3
  54. package/dist/{chunk-4JJI34RV.js → chunk-WTMLF7QR.js} +3 -3
  55. package/dist/{chunk-SX2XWCGA.js → chunk-YIZ25Y4C.js} +22 -7
  56. package/dist/chunk-YIZ25Y4C.js.map +1 -0
  57. package/dist/{cli-auth-probe-A7ANEHJ7.js → cli-auth-probe-GUK3NXW3.js} +2 -2
  58. package/dist/{cli-circuit-breaker-62YOQQT3.js → cli-circuit-breaker-CDJKHR7R.js} +5 -5
  59. package/dist/{cli-readiness-O6EOQV4L.js → cli-readiness-7I5BYWLA.js} +9 -9
  60. package/dist/cli-server-gateway-626TKNQJ.js +34 -0
  61. package/dist/cli.d.ts +1 -1
  62. package/dist/cli.js +81 -1216
  63. package/dist/cli.js.map +1 -1
  64. package/dist/{codebase-search-VMKI7FW4.js → codebase-search-YVO7BC33.js} +2 -2
  65. package/dist/{composite-router-YPZ3D5Y6.js → composite-router-YWSL4Y62.js} +4 -4
  66. package/dist/{consensus-vote-RNQQUBXO.js → consensus-vote-IRD5B3SC.js} +21 -22
  67. package/dist/{consensus-vote-types-DexdhOdB.d.ts → consensus-vote-types-C8RWaoxp.d.ts} +9 -8
  68. package/dist/{context-retriever-HVPLM6DH.js → context-retriever-CBOMGQAP.js} +11 -11
  69. package/dist/{doctor-deep-UZQTD65D.js → doctor-deep-2N3BHH6I.js} +5 -5
  70. package/dist/doctor-gateway-report-MRPZ7S34.js +20 -0
  71. package/dist/{doctor-live-QFLT5SDB.js → doctor-live-JBXIFI7A.js} +18 -16
  72. package/dist/doctor-live-JBXIFI7A.js.map +1 -0
  73. package/dist/{expert-bridge-O3UZXLGB.js → expert-bridge-TOMOJTMC.js} +6 -6
  74. package/dist/factory-H6IIGGFG.js +31 -0
  75. package/dist/factory-OLT24RLU.js +17 -0
  76. package/dist/{improvement-review-7IABFAU3.js → improvement-review-GFIINOQR.js} +8 -8
  77. package/dist/index.d.ts +69 -77
  78. package/dist/index.js +66 -57
  79. package/dist/index.js.map +1 -1
  80. package/dist/{init-opencode-RYPBCM4P.js → init-opencode-HXXKEIQF.js} +7 -7
  81. package/dist/issue-triage-ENNKQYKQ.js +20 -0
  82. package/dist/{learning-persistence-FB4U5AX2.js → learning-persistence-X24OOBYY.js} +3 -3
  83. package/dist/{model-config-helpers-QNV3KD2W.js → model-config-helpers-QFWX2QAO.js} +4 -4
  84. package/dist/{openai-compat-adapter-GPZDIR3D.js → openai-compat-adapter-N5WWPBGN.js} +7 -7
  85. package/dist/{outcome-store-adapter-WRONSTUD.js → outcome-store-adapter-Y6MS4JJK.js} +4 -4
  86. package/dist/{pr-reviewer-helpers-7SMNNDFJ.js → pr-reviewer-helpers-I6XFNU74.js} +6 -6
  87. package/dist/{registry-command-U7K6HIBK.js → registry-command-W7UHEQ6D.js} +4 -4
  88. package/dist/{repo-security-plan-LFWLVEL2.js → repo-security-plan-MENT6MS6.js} +5 -5
  89. package/dist/research-helpers-synthesize-BX4W3OA7.js +16 -0
  90. package/dist/{routing-memory-OCIVXKOU.js → routing-memory-7VHOAFNA.js} +4 -4
  91. package/dist/{session-memory-4LMEWO3X.js → session-memory-3EYP3GNQ.js} +5 -5
  92. package/dist/setup-config-VN2IOJ7S.js +13 -0
  93. package/dist/{setup-custom-api-QEPUCHOX.js → setup-custom-api-U3IGIJI7.js} +6 -6
  94. package/dist/setup-data-dir-UWOXXYFS.js +34 -0
  95. package/dist/{tool-memory-EFGFXF65.js → tool-memory-YYFE4EXT.js} +8 -8
  96. package/dist/{tool-memory-registry-adapters-FO6JVQSX.js → tool-memory-registry-adapters-IIORYBCC.js} +3 -3
  97. package/dist/unified-registry-IEPJHJHO.js +35 -0
  98. package/dist/{weather-report-PMYQ3WBW.js → weather-report-PJZFHSB7.js} +4 -4
  99. package/dist/weather-report-PJZFHSB7.js.map +1 -0
  100. package/node_modules/express-rate-limit/dist/index.cjs +9 -7
  101. package/node_modules/express-rate-limit/dist/index.mjs +9 -7
  102. package/node_modules/express-rate-limit/package.json +9 -9
  103. package/package.json +1 -1
  104. package/dist/chunk-3UWT434E.js.map +0 -1
  105. package/dist/chunk-KASBBKAQ.js.map +0 -1
  106. package/dist/chunk-KLSNDPU6.js.map +0 -1
  107. package/dist/chunk-LWOX65CP.js.map +0 -1
  108. package/dist/chunk-OMSKBBL7.js.map +0 -1
  109. package/dist/chunk-QRC3QLUQ.js.map +0 -1
  110. package/dist/chunk-SX2XWCGA.js.map +0 -1
  111. package/dist/chunk-TW6PJYTP.js.map +0 -1
  112. package/dist/chunk-UZJ6IPJR.js +0 -1057
  113. package/dist/chunk-UZJ6IPJR.js.map +0 -1
  114. package/dist/chunk-WKFPKPEM.js.map +0 -1
  115. package/dist/chunk-XDUTAUK3.js.map +0 -1
  116. package/dist/doctor-gateway-report-LRBPPJD4.js +0 -20
  117. package/dist/doctor-live-QFLT5SDB.js.map +0 -1
  118. package/dist/factory-KCKQQAEH.js +0 -31
  119. package/dist/factory-LUKUIB6C.js +0 -17
  120. package/dist/issue-triage-YBVJVAUU.js +0 -20
  121. package/dist/research-helpers-synthesize-X6MVAAKT.js +0 -16
  122. package/dist/setup-config-YNNNR4AE.js +0 -13
  123. package/dist/setup-data-dir-XM5DWH7R.js +0 -35
  124. package/dist/unified-registry-KLNC24HA.js +0 -36
  125. /package/dist/{ast-rule-runner-RI7ZJ4ZI.js.map → ast-rule-runner-RL6XHXJB.js.map} +0 -0
  126. /package/dist/{child-mcp-config-73BX4OTR.js.map → child-mcp-config-ADRNVJJB.js.map} +0 -0
  127. /package/dist/{chunk-TDUXUVUU.js.map → chunk-3LE73MVE.js.map} +0 -0
  128. /package/dist/{chunk-FNHVTDHZ.js.map → chunk-63YC42C2.js.map} +0 -0
  129. /package/dist/{chunk-U37AITDA.js.map → chunk-6JMULY2R.js.map} +0 -0
  130. /package/dist/{chunk-LP5ISXKM.js.map → chunk-6Y55UUWK.js.map} +0 -0
  131. /package/dist/{chunk-QM5W3T3O.js.map → chunk-A7XALVN3.js.map} +0 -0
  132. /package/dist/{chunk-JGY5HMWI.js.map → chunk-AX5DBV3M.js.map} +0 -0
  133. /package/dist/{chunk-VLOPXV47.js.map → chunk-BHH3PKI6.js.map} +0 -0
  134. /package/dist/{chunk-RIYFVDYN.js.map → chunk-CSDGNGAG.js.map} +0 -0
  135. /package/dist/{chunk-WD4DENPC.js.map → chunk-CXRZQ4NH.js.map} +0 -0
  136. /package/dist/{chunk-SS53PZO6.js.map → chunk-DYV7XS26.js.map} +0 -0
  137. /package/dist/{chunk-GAX75XCV.js.map → chunk-G2OI3KA4.js.map} +0 -0
  138. /package/dist/{chunk-QG3VDSWD.js.map → chunk-GU2HV6KI.js.map} +0 -0
  139. /package/dist/{chunk-2DYCHHWW.js.map → chunk-KSSPY5KX.js.map} +0 -0
  140. /package/dist/{chunk-23QA6GQD.js.map → chunk-LAUBKK25.js.map} +0 -0
  141. /package/dist/{chunk-7EV3QAKO.js.map → chunk-MTB5BXYJ.js.map} +0 -0
  142. /package/dist/{chunk-XSAUVC6D.js.map → chunk-NLFCAEEK.js.map} +0 -0
  143. /package/dist/{chunk-PXYSAG5B.js.map → chunk-NVE262E3.js.map} +0 -0
  144. /package/dist/{chunk-V26YQQK4.js.map → chunk-NY7IMAG5.js.map} +0 -0
  145. /package/dist/{chunk-GX5ZHZR2.js.map → chunk-PYAR3CVN.js.map} +0 -0
  146. /package/dist/{chunk-EJ5EBTAV.js.map → chunk-QKWZZM2D.js.map} +0 -0
  147. /package/dist/{chunk-FWQSOPBA.js.map → chunk-RR2Y2HVZ.js.map} +0 -0
  148. /package/dist/{chunk-UE7A2XHM.js.map → chunk-RUHKJC3X.js.map} +0 -0
  149. /package/dist/{chunk-D6E3LJGP.js.map → chunk-S4QYN2AV.js.map} +0 -0
  150. /package/dist/{chunk-J44RKRGQ.js.map → chunk-TW4R2Q55.js.map} +0 -0
  151. /package/dist/{chunk-QS5HGPCN.js.map → chunk-TWQEUAUG.js.map} +0 -0
  152. /package/dist/{chunk-JPFRRNRR.js.map → chunk-U7HL7FGS.js.map} +0 -0
  153. /package/dist/{chunk-JUUGLXSN.js.map → chunk-WAPGSEIM.js.map} +0 -0
  154. /package/dist/{chunk-LXYT2P2Y.js.map → chunk-WILZPMEM.js.map} +0 -0
  155. /package/dist/{chunk-4JJI34RV.js.map → chunk-WTMLF7QR.js.map} +0 -0
  156. /package/dist/{cli-auth-probe-A7ANEHJ7.js.map → cli-auth-probe-GUK3NXW3.js.map} +0 -0
  157. /package/dist/{cli-circuit-breaker-62YOQQT3.js.map → cli-circuit-breaker-CDJKHR7R.js.map} +0 -0
  158. /package/dist/{cli-readiness-O6EOQV4L.js.map → cli-readiness-7I5BYWLA.js.map} +0 -0
  159. /package/dist/{codebase-search-VMKI7FW4.js.map → cli-server-gateway-626TKNQJ.js.map} +0 -0
  160. /package/dist/{composite-router-YPZ3D5Y6.js.map → codebase-search-YVO7BC33.js.map} +0 -0
  161. /package/dist/{consensus-vote-RNQQUBXO.js.map → composite-router-YWSL4Y62.js.map} +0 -0
  162. /package/dist/{context-retriever-HVPLM6DH.js.map → consensus-vote-IRD5B3SC.js.map} +0 -0
  163. /package/dist/{doctor-deep-UZQTD65D.js.map → context-retriever-CBOMGQAP.js.map} +0 -0
  164. /package/dist/{doctor-gateway-report-LRBPPJD4.js.map → doctor-deep-2N3BHH6I.js.map} +0 -0
  165. /package/dist/{expert-bridge-O3UZXLGB.js.map → doctor-gateway-report-MRPZ7S34.js.map} +0 -0
  166. /package/dist/{factory-KCKQQAEH.js.map → expert-bridge-TOMOJTMC.js.map} +0 -0
  167. /package/dist/{factory-LUKUIB6C.js.map → factory-H6IIGGFG.js.map} +0 -0
  168. /package/dist/{improvement-review-7IABFAU3.js.map → factory-OLT24RLU.js.map} +0 -0
  169. /package/dist/{issue-triage-YBVJVAUU.js.map → improvement-review-GFIINOQR.js.map} +0 -0
  170. /package/dist/{init-opencode-RYPBCM4P.js.map → init-opencode-HXXKEIQF.js.map} +0 -0
  171. /package/dist/{learning-persistence-FB4U5AX2.js.map → issue-triage-ENNKQYKQ.js.map} +0 -0
  172. /package/dist/{model-config-helpers-QNV3KD2W.js.map → learning-persistence-X24OOBYY.js.map} +0 -0
  173. /package/dist/{openai-compat-adapter-GPZDIR3D.js.map → model-config-helpers-QFWX2QAO.js.map} +0 -0
  174. /package/dist/{pr-reviewer-helpers-7SMNNDFJ.js.map → openai-compat-adapter-N5WWPBGN.js.map} +0 -0
  175. /package/dist/{outcome-store-adapter-WRONSTUD.js.map → outcome-store-adapter-Y6MS4JJK.js.map} +0 -0
  176. /package/dist/{repo-security-plan-LFWLVEL2.js.map → pr-reviewer-helpers-I6XFNU74.js.map} +0 -0
  177. /package/dist/{registry-command-U7K6HIBK.js.map → registry-command-W7UHEQ6D.js.map} +0 -0
  178. /package/dist/{research-helpers-synthesize-X6MVAAKT.js.map → repo-security-plan-MENT6MS6.js.map} +0 -0
  179. /package/dist/{routing-memory-OCIVXKOU.js.map → research-helpers-synthesize-BX4W3OA7.js.map} +0 -0
  180. /package/dist/{session-memory-4LMEWO3X.js.map → routing-memory-7VHOAFNA.js.map} +0 -0
  181. /package/dist/{setup-config-YNNNR4AE.js.map → session-memory-3EYP3GNQ.js.map} +0 -0
  182. /package/dist/{setup-data-dir-XM5DWH7R.js.map → setup-config-VN2IOJ7S.js.map} +0 -0
  183. /package/dist/{setup-custom-api-QEPUCHOX.js.map → setup-custom-api-U3IGIJI7.js.map} +0 -0
  184. /package/dist/{tool-memory-EFGFXF65.js.map → setup-data-dir-UWOXXYFS.js.map} +0 -0
  185. /package/dist/{tool-memory-registry-adapters-FO6JVQSX.js.map → tool-memory-YYFE4EXT.js.map} +0 -0
  186. /package/dist/{unified-registry-KLNC24HA.js.map → tool-memory-registry-adapters-IIORYBCC.js.map} +0 -0
  187. /package/dist/{weather-report-PMYQ3WBW.js.map → unified-registry-IEPJHJHO.js.map} +0 -0
@@ -7,13 +7,13 @@ import {
7
7
  getModelSelectionShadowFile,
8
8
  isPersistenceEnabled,
9
9
  isStrategyDistillationEnabled
10
- } from "./chunk-UE7A2XHM.js";
10
+ } from "./chunk-RUHKJC3X.js";
11
11
  import {
12
12
  findRepoRoot,
13
13
  getNexusDataDir,
14
14
  nexusDataPath,
15
15
  parseBoolEnv
16
- } from "./chunk-LWOX65CP.js";
16
+ } from "./chunk-CH6IBWXH.js";
17
17
  import {
18
18
  CLI_NAMES,
19
19
  CliNameSchema,
@@ -2182,13 +2182,13 @@ function lookupCanonicalPricing(model) {
2182
2182
  const entry2 = registry.getEntry(matched.id);
2183
2183
  return {
2184
2184
  pricing: toPricing(matched.pricing),
2185
- source: entry2.pricing === void 0 ? "in-tree" : entry2.source
2185
+ source: entry2.pricing === void 0 ? "in-tree" : pricingSourceOf(entry2)
2186
2186
  };
2187
2187
  }
2188
2188
  const entry = registry.getEntry(model);
2189
2189
  return {
2190
2190
  pricing: toPricing(entry.pricing),
2191
- source: registry.getEntry(entry.resolvedFrom ?? entry.id).source
2191
+ source: pricingSourceOf(registry.getEntry(entry.resolvedFrom ?? entry.id))
2192
2192
  };
2193
2193
  }
2194
2194
  function calculateCost(model, inputTokens, outputTokens) {
@@ -4928,9 +4928,14 @@ function routingArmDisplaySlot(armId) {
4928
4928
  case "api:custom-openai":
4929
4929
  return "opencode";
4930
4930
  default:
4931
- return armId.startsWith("api:") ? UNKNOWN_ENDPOINT_ARM_DISPLAY_SLOT : armId;
4931
+ return armId;
4932
4932
  }
4933
4933
  }
4934
+ function routingArmCliSlot(armId) {
4935
+ if (isCliName(armId)) return armId;
4936
+ const parsed = ApiArmIdSchema.safeParse(armId);
4937
+ return parsed.success ? routingArmDisplaySlot(parsed.data) : void 0;
4938
+ }
4934
4939
  var API_ENDPOINT_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;
4935
4940
  var EndpointArmIdSchema = z3.templateLiteral([
4936
4941
  "api:",
@@ -4941,7 +4946,7 @@ function isEndpointArmId(value) {
4941
4946
  }
4942
4947
  var UNKNOWN_ENDPOINT_ARM_DISPLAY_SLOT = "opencode";
4943
4948
  function observedArmDisplaySlot(armId) {
4944
- return routingArmDisplaySlot(armId);
4949
+ return routingArmCliSlot(armId) ?? UNKNOWN_ENDPOINT_ARM_DISPLAY_SLOT;
4945
4950
  }
4946
4951
 
4947
4952
  // src/cli-adapters/types-capability.ts
@@ -4974,6 +4979,9 @@ var CLI_VERSION_REQUIREMENTS = {
4974
4979
  var DEFAULT_CAPABILITIES = buildCliCapabilityProfiles();
4975
4980
 
4976
4981
  // src/learning/routing-decision-mappers.ts
4982
+ function recordedArm(armId) {
4983
+ return routingArmCliSlot(armId) ?? armId;
4984
+ }
4977
4985
  function mapFeedbackRoutingDecision(decision, context) {
4978
4986
  return {
4979
4987
  id: context.id,
@@ -4982,9 +4990,9 @@ function mapFeedbackRoutingDecision(decision, context) {
4982
4990
  routerType: context.routerType,
4983
4991
  routerTypeMeasured: context.routerTypeMeasured,
4984
4992
  query: context.query ?? "",
4985
- selectedModel: routingArmDisplaySlot(decision.cliName),
4993
+ selectedModel: recordedArm(decision.cliName),
4986
4994
  confidence: decision.confidence,
4987
- selectedTier: decision.preferenceTier
4995
+ selectedTier: routingArmCliSlot(decision.cliName) === void 0 ? void 0 : decision.preferenceTier
4988
4996
  };
4989
4997
  }
4990
4998
  function mapObserverRoutingDecision(decision, context) {
@@ -4992,10 +5000,10 @@ function mapObserverRoutingDecision(decision, context) {
4992
5000
  timestamp: context.timestamp,
4993
5001
  taskId: context.taskId,
4994
5002
  taskDescription: context.query.length > 100 ? context.query.substring(0, 100) + "..." : context.query,
4995
- selectedCli: routingArmDisplaySlot(decision.cliName),
5003
+ selectedCli: recordedArm(decision.cliName),
4996
5004
  confidence: decision.confidence,
4997
5005
  reason: decision.reason,
4998
- alternatives: decision.alternatives.map(routingArmDisplaySlot),
5006
+ alternatives: decision.alternatives.map(recordedArm),
4999
5007
  stagesExecuted: decision.stagesExecuted,
5000
5008
  decisionTimeMs: decision.decisionTimeMs,
5001
5009
  withinBudget: decision.withinBudget,
@@ -5011,8 +5019,8 @@ function mapStoredRoutingDecision(decision, context) {
5011
5019
  timestamp: context.timestamp,
5012
5020
  routerType: context.routerType,
5013
5021
  routerTypeMeasured: context.routerTypeMeasured,
5014
- selectedModel: routingArmDisplaySlot(decision.cliName),
5015
- alternativeModels: decision.alternatives.map(routingArmDisplaySlot),
5022
+ selectedModel: recordedArm(decision.cliName),
5023
+ alternativeModels: decision.alternatives.map(recordedArm),
5016
5024
  confidence: decision.confidence,
5017
5025
  reason: decision.reason,
5018
5026
  taskProfile: {
@@ -5803,7 +5811,7 @@ function computeCostDetail(modelId, inputTokens, outputTokens) {
5803
5811
  return {
5804
5812
  costUsd: roundToMicroUsd(costUsd),
5805
5813
  priced: true,
5806
- ...getDefaultRegistry().getEntry(entry.resolvedFrom ?? entry.id).source === "manifest" ? { declared: true } : {},
5814
+ ...pricingSourceOf(getDefaultRegistry().getEntry(entry.resolvedFrom ?? entry.id)) === "manifest" ? { declared: true } : {},
5807
5815
  resolvedId,
5808
5816
  ...provenance,
5809
5817
  ...entry.pricingProvenance !== void 0 ? { pricingProvenance: entry.pricingProvenance } : {}
@@ -6060,7 +6068,7 @@ function adapterReadiness(adapter, options) {
6060
6068
  const ceiling = resolveClassGuardMs("interactive");
6061
6069
  const requested = options.timeoutMs ?? ceiling;
6062
6070
  const timeoutMs = Number.isFinite(requested) && requested > 0 ? Math.min(requested, ceiling) : ceiling;
6063
- const flight = import("./cli-readiness-O6EOQV4L.js").then(({ probeServes }) => probeServes(adapter, timeoutMs)).finally(() => readinessFlights.delete(adapter));
6071
+ const flight = import("./cli-readiness-7I5BYWLA.js").then(({ probeServes }) => probeServes(adapter, timeoutMs)).finally(() => readinessFlights.delete(adapter));
6064
6072
  readinessFlights.set(adapter, flight);
6065
6073
  return flight;
6066
6074
  }
@@ -6070,7 +6078,7 @@ async function servesListedModel(adapter, modelId, cli) {
6070
6078
  const models = await adapter.listModels();
6071
6079
  if (models.length === 0) return "unknown";
6072
6080
  const requestedKey = canonicalModelKey(modelId);
6073
- const findCanonicalModel2 = cli === "codex" ? (await import("./model-config-helpers-QNV3KD2W.js")).findCanonicalModel : void 0;
6081
+ const findCanonicalModel2 = cli === "codex" ? (await import("./model-config-helpers-QFWX2QAO.js")).findCanonicalModel : void 0;
6074
6082
  const requestedEntry = requestedKey === null ? findCanonicalModel2?.("codex", modelId) : void 0;
6075
6083
  const listed = models.some((model) => {
6076
6084
  const listedEntry = findCanonicalModel2?.("codex", model.id);
@@ -6715,6 +6723,9 @@ var DEFAULT_REQUEST_LIMITS = {
6715
6723
  };
6716
6724
  var RATE_LIMIT_WINDOW_MS = 6e4;
6717
6725
  function getDefaultConfig(cli) {
6726
+ if (!isCliName(cli)) {
6727
+ return { tokenLimit: Infinity, requestLimit: Infinity, windowMs: RATE_LIMIT_WINDOW_MS };
6728
+ }
6718
6729
  const envPrefix = `NEXUS_${cli.toUpperCase()}`;
6719
6730
  const tokenEnv = process.env[`${envPrefix}_TOKEN_LIMIT`];
6720
6731
  const requestEnv = process.env[`${envPrefix}_REQUEST_LIMIT`];
@@ -7364,6 +7375,237 @@ function mapModelErrorToCategory(error) {
7364
7375
  }
7365
7376
  }
7366
7377
 
7378
+ // src/adapters/sdk/gateway-catalog.ts
7379
+ var catalogs = /* @__PURE__ */ new Map();
7380
+ var owners = /* @__PURE__ */ new Map();
7381
+ function retainGatewayCatalog(arm, owner) {
7382
+ let retained = owners.get(arm);
7383
+ if (retained === void 0) {
7384
+ retained = /* @__PURE__ */ new Set();
7385
+ owners.set(arm, retained);
7386
+ }
7387
+ retained.add(owner);
7388
+ }
7389
+ function releaseGatewayCatalog(arm, owner) {
7390
+ const retained = owners.get(arm);
7391
+ if (retained?.delete(owner) !== true) return;
7392
+ if (retained.size > 0) return;
7393
+ owners.delete(arm);
7394
+ clearGatewayCatalog(arm);
7395
+ }
7396
+ function setGatewayCatalog(arm, modelIds) {
7397
+ if (modelIds.length === 0) {
7398
+ throw new Error(
7399
+ `Gateway catalogue for ${arm} is empty; an arm with no model is not registrable`
7400
+ );
7401
+ }
7402
+ catalogs.set(arm, [...modelIds]);
7403
+ }
7404
+ function getGatewayCatalog(arm) {
7405
+ return catalogs.get(arm);
7406
+ }
7407
+ function clearGatewayCatalog(arm) {
7408
+ catalogs.delete(arm);
7409
+ }
7410
+
7411
+ // src/adapters/gateway-arm-adapter.ts
7412
+ function createGatewayArmAdapter(armId, models, deps) {
7413
+ if (models.length === 0) {
7414
+ throw new ConfigError(`Gateway arm ${armId} has no models; nothing to register`);
7415
+ }
7416
+ return new GatewayArmAdapter(armId, models, deps);
7417
+ }
7418
+ function ownsGatewayCircuitAdmission(adapter, armId, registry) {
7419
+ return adapter instanceof GatewayArmAdapter && adapter.gatewayArm === armId && adapter.getCircuitBreakerRegistry() === registry;
7420
+ }
7421
+ var GatewayArmAdapter = class {
7422
+ constructor(armId, models, deps) {
7423
+ this.armId = armId;
7424
+ this.models = models;
7425
+ this.deps = deps;
7426
+ retainGatewayCatalog(armId, this);
7427
+ }
7428
+ armId;
7429
+ models;
7430
+ deps;
7431
+ selectedAt = /* @__PURE__ */ new Date();
7432
+ resolvedDelegate;
7433
+ /**
7434
+ * The gateway-arm marker (#4392 step 4, `isGatewayModelAdapter`): a
7435
+ * telemetry writer that is handed this wrapper prices its calls by the
7436
+ * arm's `NEXUS_GATEWAY_COST` declaration, never the delegate's list price.
7437
+ */
7438
+ get gatewayArm() {
7439
+ return this.armId;
7440
+ }
7441
+ // --- IModelAdapter (forwarded to the delegate) ---
7442
+ get providerId() {
7443
+ return this.requireDelegate().providerId;
7444
+ }
7445
+ get modelId() {
7446
+ return this.requireDelegate().modelId;
7447
+ }
7448
+ get capabilities() {
7449
+ return this.requireDelegate().capabilities;
7450
+ }
7451
+ /**
7452
+ * Both halves of the breaker contract, as `base-adapter.ts` records them
7453
+ * for the CLI slots on the same shared registry. The success half matters
7454
+ * (#6403 review): in the closed state `recordSuccess` zeroes the failure
7455
+ * count, which is what makes the threshold mean CONSECUTIVE failures, and
7456
+ * in half-open it is what closes the circuit again. Without it a long-lived
7457
+ * process counted scattered blips for its whole lifetime and, once open,
7458
+ * sat half-open forever with any single error re-opening it.
7459
+ */
7460
+ async complete(request) {
7461
+ const resolved = this.resolveDelegate();
7462
+ if (!resolved.ok) {
7463
+ return err(new ModelError(resolved.error.message, { code: ErrorCode.MODEL_UNAVAILABLE }));
7464
+ }
7465
+ const delegate = resolved.value;
7466
+ const breaker = this.deps.circuitBreakerRegistry.getArmBreaker(this.armId);
7467
+ const admission = breaker.canExecute();
7468
+ if (!admission.ok) {
7469
+ return err(
7470
+ new ModelError(admission.error.message, {
7471
+ code: ErrorCode.MODEL_UNAVAILABLE,
7472
+ cause: admission.error,
7473
+ retryable: false
7474
+ })
7475
+ );
7476
+ }
7477
+ const result = await delegate.complete(request);
7478
+ if (result.ok) {
7479
+ breaker.recordSuccess();
7480
+ } else if (isCallerCancelled(result.error)) {
7481
+ breaker.releaseHalfOpenProbe();
7482
+ } else {
7483
+ this.recordFailure(result.error, delegate.providerId);
7484
+ }
7485
+ return result;
7486
+ }
7487
+ stream(request) {
7488
+ return this.requireDelegate().stream(request);
7489
+ }
7490
+ countTokens(text) {
7491
+ return this.requireDelegate().countTokens(text);
7492
+ }
7493
+ validateConfig() {
7494
+ const resolved = this.resolveDelegate();
7495
+ return resolved.ok ? resolved.value.validateConfig() : resolved;
7496
+ }
7497
+ /** The whole catalogue, not the delegate alone — that is what the arm fronts. */
7498
+ listModels() {
7499
+ return Promise.resolve(this.models.map((m) => ({ id: m.modelId })));
7500
+ }
7501
+ // --- IResilientAdapter ---
7502
+ /**
7503
+ * `source: 'api'` always; `degraded` while the arm's breaker is open. There
7504
+ * is no `unavailable`: the arm exists only once discovery succeeded.
7505
+ */
7506
+ getHealth() {
7507
+ return {
7508
+ source: "api",
7509
+ state: this.deps.circuitBreakerRegistry.isArmOpen(this.armId) ? "degraded" : "healthy",
7510
+ selectedAt: this.selectedAt,
7511
+ failoverCount: 0
7512
+ };
7513
+ }
7514
+ /** Nothing to re-detect: the catalogue is fixed at registration. */
7515
+ refresh() {
7516
+ return Promise.resolve();
7517
+ }
7518
+ /** A gateway arm has no CLI to prefer; said at debug so a caller can see it was ignored. */
7519
+ setPreferredCli(cli) {
7520
+ this.deps.logger.debug("setPreferredCli ignored on a gateway arm", { arm: this.armId, cli });
7521
+ }
7522
+ /** The arm never fails over, so the callback is never invoked. */
7523
+ onFailover() {
7524
+ return () => void 0;
7525
+ }
7526
+ getCircuitBreakerRegistry() {
7527
+ return this.deps.circuitBreakerRegistry;
7528
+ }
7529
+ /**
7530
+ * No listeners or timers are held; the breaker outlives the arm on purpose
7531
+ * (a re-registered gateway keeps its failure history). The shared catalogue
7532
+ * stays while any registry owns a live wrapper for this endpoint. Repeated
7533
+ * disposal is harmless, and a wrapper retained before replacement prevents
7534
+ * disposal of the earlier wrapper from clearing the endpoint's metadata.
7535
+ */
7536
+ dispose() {
7537
+ releaseGatewayCatalog(this.armId, this);
7538
+ }
7539
+ // --- Private ---
7540
+ /** Resolve lazily after bootstrap, and pin a successful default to this arm. */
7541
+ resolveDelegate() {
7542
+ if (this.resolvedDelegate !== void 0) return ok(this.resolvedDelegate);
7543
+ const resolved = resolveGatewayDefault(process.env, this.deps.logger);
7544
+ if (resolved.kind !== "resolved") {
7545
+ return err(new ConfigError(`Gateway arm ${this.armId} has no chat default`));
7546
+ }
7547
+ const delegate = this.models.find((model) => model === resolved.adapter);
7548
+ if (delegate === void 0) {
7549
+ return err(new ConfigError(`Gateway default does not belong to arm ${this.armId}`));
7550
+ }
7551
+ this.resolvedDelegate = delegate;
7552
+ return ok(delegate);
7553
+ }
7554
+ /** Metadata and streaming interfaces cannot carry a Result error. */
7555
+ requireDelegate() {
7556
+ const resolved = this.resolveDelegate();
7557
+ if (!resolved.ok) throw resolved.error;
7558
+ return resolved.value;
7559
+ }
7560
+ /**
7561
+ * `ResilientAdapter.recordBreakerFailure`, keyed on the ARM (#3423, #5359):
7562
+ * a transient rate limit is recorded by the telemetry branch and exempt from
7563
+ * the breaker (it would double-count, and open a breaker on a condition that
7564
+ * clears within the minute); a DURABLE capacity cap is counted even though it
7565
+ * is rate-limit-shaped, because it never clears; everything else counts.
7566
+ * Every rate-limit-shaped failure, durable or not, is a telemetry event.
7567
+ */
7568
+ recordFailure(error, provider) {
7569
+ const breaker = this.deps.circuitBreakerRegistry.getArmBreaker(this.armId);
7570
+ const category = mapModelErrorToCategory(error);
7571
+ const rateLimitLike = category === "rate_limit" || isRateLimitLikeError(error);
7572
+ if (rateLimitLike) this.recordRateLimit(error, provider);
7573
+ if (isDurableCapacityError(error)) {
7574
+ breaker.recordFailure(category);
7575
+ this.deps.logger.warn("Durable capacity cap recorded to gateway arm breaker", {
7576
+ arm: this.armId,
7577
+ provider,
7578
+ category
7579
+ });
7580
+ return;
7581
+ }
7582
+ if (rateLimitLike) {
7583
+ breaker.releaseHalfOpenProbe();
7584
+ return;
7585
+ }
7586
+ breaker.recordFailure(category);
7587
+ this.deps.logger.warn("Gateway arm failure recorded to circuit breaker", {
7588
+ arm: this.armId,
7589
+ provider,
7590
+ category
7591
+ });
7592
+ }
7593
+ /** The telemetry branch of `ResilientAdapter.complete`, for the exempted case. */
7594
+ recordRateLimit(error, provider) {
7595
+ const rlError = toRateLimitError(error, provider);
7596
+ recordRateLimitEvent({
7597
+ provider,
7598
+ timestamp: getTimeProvider().now(),
7599
+ retryAfterMs: rlError.retryAfterMs
7600
+ });
7601
+ this.deps.logger.warn("Rate limit detected on gateway arm", {
7602
+ arm: this.armId,
7603
+ provider,
7604
+ retryAfterMs: rlError.retryAfterMs
7605
+ });
7606
+ }
7607
+ };
7608
+
7367
7609
  // src/cli-adapters/model-to-cli-adapter.ts
7368
7610
  var DEFAULT_CONTEXT_WINDOW = FALLBACK_CONTEXT_WINDOW;
7369
7611
  var NEUTRAL_CAPABILITIES = {
@@ -7403,16 +7645,26 @@ var ModelToCliAdapter = class {
7403
7645
  * Per-instance, so one arm's exhaustion never speaks for another's.
7404
7646
  */
7405
7647
  capacityTracker;
7648
+ /** Exact admission ownership; other API adapters still need the integration's gate. */
7649
+ ownsCircuitAdmission(registry) {
7650
+ return ownsGatewayCircuitAdmission(this.modelAdapter, this.name, registry);
7651
+ }
7406
7652
  constructor(modelAdapter, config) {
7407
7653
  this.modelAdapter = modelAdapter;
7408
7654
  this.name = config.name;
7409
- this.capabilities = config.capabilities ?? NEUTRAL_CAPABILITIES;
7655
+ const entry = routingArmCliSlot(config.name) === void 0 ? getDefaultRegistry().getEntry(modelAdapter.modelId) : void 0;
7656
+ this.capabilities = config.capabilities ?? {
7657
+ ...NEUTRAL_CAPABILITIES,
7658
+ ...entry?.qualityScores,
7659
+ contextWindow: entry?.contextWindow ?? DEFAULT_CONTEXT_WINDOW
7660
+ };
7410
7661
  this.capacityTracker = createCapacityTracker(config.name);
7411
7662
  }
7412
7663
  /** Build a single-turn CompletionRequest from a CliTask. */
7413
7664
  toCompletionRequest(task, options) {
7414
7665
  const request = {
7415
- messages: [{ role: "user", content: task.content }]
7666
+ messages: [{ role: "user", content: task.content }],
7667
+ ...options?.signal !== void 0 ? { signal: options.signal } : {}
7416
7668
  };
7417
7669
  if (task.systemPrompt !== void 0) {
7418
7670
  request.systemPrompt = task.systemPrompt;
@@ -7501,7 +7753,7 @@ var ModelToCliAdapter = class {
7501
7753
  }
7502
7754
  async execute(task, options) {
7503
7755
  const gatewayArm = this.gatewayArmField().gatewayArm;
7504
- const breaker = gatewayArm !== void 0 && this.modelAdapter.providerId === `cli-${this.name}` ? (await import("./cli-circuit-breaker-62YOQQT3.js")).getDefaultCliCircuitBreakerRegistry().getArmBreaker(breakerKeys.forArm({ name: this.name, gatewayArm })) : void 0;
7756
+ const breaker = gatewayArm !== void 0 && this.modelAdapter.providerId === `cli-${this.name}` ? (await import("./cli-circuit-breaker-CDJKHR7R.js")).getDefaultCliCircuitBreakerRegistry().getArmBreaker(breakerKeys.forArm({ name: this.name, gatewayArm })) : void 0;
7505
7757
  const result = await this.modelAdapter.complete(this.toCompletionRequest(task, options));
7506
7758
  if (!result.ok) {
7507
7759
  const cliError = this.toCliError(result.error);
@@ -7576,7 +7828,7 @@ var ModelToCliAdapter = class {
7576
7828
  return {
7577
7829
  id: this.modelAdapter.modelId,
7578
7830
  name: this.modelAdapter.modelId,
7579
- contextWindow: DEFAULT_CONTEXT_WINDOW
7831
+ contextWindow: routingArmCliSlot(this.name) === void 0 ? this.capabilities.contextWindow : DEFAULT_CONTEXT_WINDOW
7580
7832
  };
7581
7833
  }
7582
7834
  /** Delegate to the model adapter's listModels surface when present (#2529). */
@@ -7630,6 +7882,11 @@ var GatewaySlotArm = class {
7630
7882
  arm: typeof arm === "string" && isEndpointArmId(arm) ? arm : void 0
7631
7883
  };
7632
7884
  }
7885
+ /** Endpoint this slot may serve, including an undecided CLI-or-gateway target. */
7886
+ get gatewayEndpoint() {
7887
+ const arm = this.deps.gatewayModel.gatewayArm;
7888
+ return typeof arm === "string" && isEndpointArmId(arm) ? arm : void 0;
7889
+ }
7633
7890
  /** The CLI's subprocess adapter; undefined when its binary is not on PATH. */
7634
7891
  get cliBinaryAdapter() {
7635
7892
  return this.deps.cliAdapter;
@@ -7726,6 +7983,9 @@ var GatewaySlotArm = class {
7726
7983
  await this.gatewayAdapter.dispose();
7727
7984
  }
7728
7985
  };
7986
+ function gatewaySlotEndpointOf(adapter) {
7987
+ return adapter instanceof GatewaySlotArm ? adapter.gatewayEndpoint : void 0;
7988
+ }
7729
7989
  function gatewayServedSlotOf(adapter) {
7730
7990
  return adapter instanceof GatewaySlotArm ? adapter.gatewayServedSlot : void 0;
7731
7991
  }
@@ -7769,23 +8029,6 @@ function buildGatewaySlotRouterArm(cli, createCli, isAvailable, logger16) {
7769
8029
  });
7770
8030
  }
7771
8031
 
7772
- // src/adapters/sdk/gateway-catalog.ts
7773
- var catalogs = /* @__PURE__ */ new Map();
7774
- function setGatewayCatalog(arm, modelIds) {
7775
- if (modelIds.length === 0) {
7776
- throw new Error(
7777
- `Gateway catalogue for ${arm} is empty; an arm with no model is not registrable`
7778
- );
7779
- }
7780
- catalogs.set(arm, [...modelIds]);
7781
- }
7782
- function getGatewayCatalog(arm) {
7783
- return catalogs.get(arm);
7784
- }
7785
- function clearGatewayCatalog(arm) {
7786
- catalogs.delete(arm);
7787
- }
7788
-
7789
8032
  // src/cli-adapters/budget-arm-cost.ts
7790
8033
  function estimateRegistryCostUsd(slot, inputTokens, outputTokens) {
7791
8034
  const pricing = getModelPricing(getDefaultModelForCli(slot));
@@ -7947,8 +8190,9 @@ var DEFAULT_OPTIONS = {
7947
8190
  // #4196: per-task-class cost ceilings default OFF (no ceiling configured).
7948
8191
  taskClassCostCeilings: {}
7949
8192
  };
7950
- function latencyOf(slot) {
7951
- return DEFAULT_COST_MODELS[slot]?.avgLatencyMs;
8193
+ function latencyOf(arm) {
8194
+ const slot = routingArmCliSlot(arm);
8195
+ return slot === void 0 ? void 0 : DEFAULT_COST_MODELS[slot]?.avgLatencyMs;
7952
8196
  }
7953
8197
  var BudgetRouter = class {
7954
8198
  adapters;
@@ -8064,7 +8308,7 @@ var BudgetRouter = class {
8064
8308
  const adapter = selected === null ? null : selected.adapter;
8065
8309
  const armCostUsd = selected === null ? void 0 : budgetCostOfArm(selected, estimatedInputTokens, estimatedOutputTokens);
8066
8310
  const estimatedCostUsd = armCostUsd ?? 0;
8067
- const estimatedLatencyMs = selected === null ? void 0 : latencyOf(routingArmDisplaySlot(selected.arm));
8311
+ const estimatedLatencyMs = selected === null ? void 0 : latencyOf(selected.arm);
8068
8312
  const currentBudget = this.getSessionBudget();
8069
8313
  const withinBudget = armCostUsd !== void 0 && this.checkConstraints(budget, estimatedTokens, estimatedCostUsd);
8070
8314
  const warnings = generateBudgetWarnings(
@@ -8245,8 +8489,8 @@ var BudgetRouter = class {
8245
8489
  }
8246
8490
  selectAdapterWithinBudget(budget, estimatedTokens) {
8247
8491
  const sortedAdapters = [...this.adapters].sort((a, b) => {
8248
- const capA = DEFAULT_CAPABILITIES[routingArmDisplaySlot(a[0])];
8249
- const capB = DEFAULT_CAPABILITIES[routingArmDisplaySlot(b[0])];
8492
+ const capA = this.capabilitiesOf(a[0], a[1]);
8493
+ const capB = this.capabilitiesOf(b[0], b[1]);
8250
8494
  return capB.cost - capA.cost;
8251
8495
  });
8252
8496
  const unpricedArms = [];
@@ -8259,19 +8503,25 @@ var BudgetRouter = class {
8259
8503
  unpricedArms.push({ arm, reason });
8260
8504
  continue;
8261
8505
  }
8262
- if (this.admitsCandidate(budget, estimatedTokens, routingArmDisplaySlot(arm), estimatedCost)) {
8506
+ if (this.admitsCandidate(budget, estimatedTokens, { arm, adapter }, estimatedCost)) {
8263
8507
  return { selected: { arm, adapter }, unpricedArms };
8264
8508
  }
8265
8509
  }
8266
8510
  return { selected: null, unpricedArms };
8267
8511
  }
8512
+ /** Slot profiles apply only to vendor arms; endpoints supply their own profile. */
8513
+ capabilitiesOf(arm, adapter) {
8514
+ const slot = routingArmCliSlot(arm);
8515
+ return slot === void 0 ? adapter.capabilities : DEFAULT_CAPABILITIES[slot];
8516
+ }
8268
8517
  /** The four per-candidate admission checks of `selectAdapterWithinBudget`. */
8269
- admitsCandidate(budget, estimatedTokens, slot, estimatedCost) {
8270
- const caps = DEFAULT_CAPABILITIES[slot];
8518
+ admitsCandidate(budget, estimatedTokens, target, estimatedCost) {
8519
+ const caps = this.capabilitiesOf(target.arm, target.adapter);
8271
8520
  const withinTokenBudget = budget.maxTokens === void 0 || estimatedTokens <= budget.maxTokens;
8272
8521
  const withinCostBudget = budget.maxCostUsd === void 0 || estimatedCost <= budget.maxCostUsd;
8273
8522
  const withinContextWindow = estimatedTokens <= caps.contextWindow;
8274
- const withinLatencyBudget = budget.maxLatencyMs === void 0 || latencyOf(slot) === void 0 || latencyOf(slot) <= budget.maxLatencyMs;
8523
+ const latency = latencyOf(target.arm);
8524
+ const withinLatencyBudget = budget.maxLatencyMs === void 0 || latency === void 0 || latency <= budget.maxLatencyMs;
8275
8525
  return withinTokenBudget && withinCostBudget && withinContextWindow && withinLatencyBudget;
8276
8526
  }
8277
8527
  checkConstraints(budget, estimatedTokens, estimatedCostUsd) {
@@ -8473,6 +8723,15 @@ function generateReasoning(best, ranked, savings) {
8473
8723
  }
8474
8724
  return parts.join(". ");
8475
8725
  }
8726
+ function adjustProfileForTask(profile, taskProfile) {
8727
+ if (taskProfile.taskType === "architecture" || taskProfile.reasoningComplexity > 7) {
8728
+ return { ...profile, qualityScore: Math.min(profile.qualityScore * 1.2, 10) };
8729
+ }
8730
+ if (taskProfile.taskType === "bulk_operations" || taskProfile.contextRequired < 1e3) {
8731
+ return { ...profile, averageLatencyMs: profile.averageLatencyMs * 0.8 };
8732
+ }
8733
+ return profile;
8734
+ }
8476
8735
 
8477
8736
  // src/cli-adapters/topsis-router.ts
8478
8737
  var WEIGHT_SUM_TOLERANCE = 0.01;
@@ -13498,8 +13757,8 @@ function getOutcomeStore() {
13498
13757
  async function attachOutcomeStoreToRegistry(store) {
13499
13758
  try {
13500
13759
  const { getMemoryRegistry } = await import("./dist-RRRU2OKU.js");
13501
- const { OutcomeStoreAdapter } = await import("./outcome-store-adapter-WRONSTUD.js");
13502
- const { ensureSharedMemoryRegistry } = await import("./tool-memory-registry-adapters-FO6JVQSX.js");
13760
+ const { OutcomeStoreAdapter } = await import("./outcome-store-adapter-Y6MS4JJK.js");
13761
+ const { ensureSharedMemoryRegistry } = await import("./tool-memory-registry-adapters-IIORYBCC.js");
13503
13762
  ensureSharedMemoryRegistry();
13504
13763
  getMemoryRegistry().attach("outcomes", new OutcomeStoreAdapter(store));
13505
13764
  } catch {
@@ -13706,9 +13965,10 @@ function getPipelineEventBus() {
13706
13965
  var PRIMARY_REWARD = 0.85;
13707
13966
  var SECONDARY_REWARD = 0.6;
13708
13967
  var OTHER_REWARD = 0.35;
13968
+ var ENDPOINT_REWARD = 0.5;
13709
13969
  var SYNTHETIC_MARKER = "synthetic:warm-up";
13710
13970
  var CLI_NAMES2 = ["claude", "gemini", "codex", "opencode"];
13711
- function generateSyntheticPriors() {
13971
+ function generateSyntheticPriors(armNames = []) {
13712
13972
  const totals = /* @__PURE__ */ new Map();
13713
13973
  for (const cli of CLI_NAMES2) {
13714
13974
  totals.set(cli, 0);
@@ -13730,6 +13990,11 @@ function generateSyntheticPriors() {
13730
13990
  for (const [cli, total] of totals) {
13731
13991
  priors.set(cli, total / count);
13732
13992
  }
13993
+ for (const arm of armNames.filter(
13994
+ (name) => isEndpointArmId(name) && routingArmCliSlot(name) === void 0
13995
+ )) {
13996
+ priors.set(arm, ENDPOINT_REWARD);
13997
+ }
13733
13998
  return priors;
13734
13999
  }
13735
14000
  function buildSyntheticOutcomes(timestamp) {
@@ -13803,7 +14068,7 @@ function warmStartBandit(bandit, logger16, options = {}) {
13803
14068
  });
13804
14069
  }
13805
14070
  }
13806
- bandit.seedPriors(generateSyntheticPriors(), replayed === 0 ? 3 : 1);
14071
+ bandit.seedPriors(generateSyntheticPriors(bandit.getArmNames()), replayed === 0 ? 3 : 1);
13807
14072
  if (replayed === 0) {
13808
14073
  fallbackUsed = true;
13809
14074
  const fallback = options.persist === false ? memoryFallback() : persistedFallback(logger16);
@@ -13874,15 +14139,6 @@ function budgetUtilizationForTask(task, budgetRouter, rawConstraints) {
13874
14139
  }
13875
14140
 
13876
14141
  // src/cli-adapters/composite-router-helpers.ts
13877
- function adjustProfileForTask(profile, taskProfile) {
13878
- if (taskProfile.taskType === "architecture" || taskProfile.reasoningComplexity > 7) {
13879
- return { ...profile, qualityScore: Math.min(profile.qualityScore * 1.2, 10) };
13880
- }
13881
- if (taskProfile.taskType === "bulk_operations" || taskProfile.contextRequired < 1e3) {
13882
- return { ...profile, averageLatencyMs: profile.averageLatencyMs * 0.8 };
13883
- }
13884
- return profile;
13885
- }
13886
14142
  function taskProfileToBanditContext(profile, budgetUtilization) {
13887
14143
  return {
13888
14144
  taskComplexity: profile.reasoningComplexity / 10,
@@ -13930,7 +14186,10 @@ function filterByPreferenceTier(candidates, tier) {
13930
14186
  const strongModels = deriveStrongClis();
13931
14187
  const weakModels = deriveWeakClis();
13932
14188
  const preferred = tier === "strong" ? strongModels : weakModels;
13933
- const filtered = candidates.filter((c) => preferred.includes(routingArmDisplaySlot(c)));
14189
+ const filtered = candidates.filter((c) => {
14190
+ const slot = routingArmCliSlot(c);
14191
+ return slot === void 0 || preferred.includes(slot);
14192
+ });
13934
14193
  return filtered.length > 0 ? filtered : candidates;
13935
14194
  }
13936
14195
  function cliTaskToTask(cliTask) {
@@ -14001,7 +14260,7 @@ function adjustProfileWithStageScores(profiles, stageScores) {
14001
14260
  });
14002
14261
  }
14003
14262
  function buildAdjustedProfiles(taskProfile, candidates, options) {
14004
- const candidateSlots = new Set(candidates.map(routingArmDisplaySlot));
14263
+ const candidateSlots = new Set(candidates.map(routingArmCliSlot));
14005
14264
  const profiles = DEFAULT_MODEL_PROFILES.filter((p) => candidateSlots.has(p.cliName));
14006
14265
  let adjusted = profiles.map((p) => adjustProfileForTask(p, taskProfile));
14007
14266
  if (options?.stageScores !== void 0 && options.stageScores.size > 0) {
@@ -14024,15 +14283,17 @@ function applyTopsisRanking(taskProfile, candidates, topsisRouter, options) {
14024
14283
  taskProfile.reasoningComplexity
14025
14284
  );
14026
14285
  const adjustedProfiles = buildAdjustedProfiles(taskProfile, candidates, options);
14286
+ if (adjustedProfiles.length === 0) return { ranking: candidates, topScore: 1 };
14027
14287
  const result = router.selectModel({ profiles: adjustedProfiles });
14028
- const scoreMap = new Map(result.scores.map((s) => [s.cliName, s.closenessScore]));
14029
- const scoreOf = (arm) => scoreMap.get(routingArmDisplaySlot(arm)) ?? 0;
14288
+ const scoreOf = (arm) => result.scores.find((score) => score.cliName === routingArmCliSlot(arm))?.closenessScore ?? 0;
14030
14289
  const ranking = [...candidates].sort((a, b) => scoreOf(b) - scoreOf(a));
14031
14290
  const topArm = ranking[0];
14032
14291
  const topScore = topArm !== void 0 ? scoreOf(topArm) : 1;
14033
- const scoresByArm = new Map(candidates.map((arm) => [arm, scoreOf(arm)]));
14292
+ const scoresByArm = new Map(
14293
+ candidates.filter((arm) => routingArmCliSlot(arm) !== void 0).map((arm) => [arm, scoreOf(arm)])
14294
+ );
14034
14295
  const threshold = topScore * (1 - TOPSIS_TOLERANCE_BAND_PERCENT);
14035
- const toleranceBandSize = ranking.filter((c) => scoreOf(c) >= threshold).length;
14296
+ const toleranceBandSize = [...scoresByArm.values()].filter((score) => score >= threshold).length;
14036
14297
  return { ranking, topScore, toleranceBandSize, scoresByArm };
14037
14298
  }
14038
14299
  function defaultPreferenceStageResult(candidates) {
@@ -14052,8 +14313,8 @@ function defaultZeroRouterStageResult(candidates) {
14052
14313
  function filterByDifficultyTier(candidates, tier) {
14053
14314
  const preferred = deriveTierToClis()[tier];
14054
14315
  const sortedCandidates = [...candidates].sort((a, b) => {
14055
- const aIndex = preferred.indexOf(routingArmDisplaySlot(a));
14056
- const bIndex = preferred.indexOf(routingArmDisplaySlot(b));
14316
+ const aIndex = preferred.findIndex((slot) => slot === routingArmCliSlot(a));
14317
+ const bIndex = preferred.findIndex((slot) => slot === routingArmCliSlot(b));
14057
14318
  const aPos = aIndex === -1 ? preferred.length : aIndex;
14058
14319
  const bPos = bIndex === -1 ? preferred.length : bIndex;
14059
14320
  return aPos - bPos;
@@ -14064,7 +14325,9 @@ function applyZeroRouterFilter(task, candidates, zeroRouter) {
14064
14325
  if (zeroRouter === void 0 || candidates.length === 0) {
14065
14326
  return defaultZeroRouterStageResult(candidates);
14066
14327
  }
14067
- const decision = zeroRouter.routeByDifficulty(task, candidates.map(routingArmDisplaySlot));
14328
+ const slots = candidates.map(routingArmCliSlot).filter((slot) => slot !== void 0);
14329
+ if (slots.length === 0) return defaultZeroRouterStageResult(candidates);
14330
+ const decision = zeroRouter.routeByDifficulty(task, slots);
14068
14331
  const difficultyEstimate = decision.difficulty;
14069
14332
  const difficultyTier = decision.tier;
14070
14333
  const filteredCandidates = filterByDifficultyTier(candidates, difficultyTier);
@@ -14099,7 +14362,7 @@ function buildDecisionFields(ctx) {
14099
14362
  const alternatives = ctx.topsisRanking.filter((c) => c !== ctx.selectedCli);
14100
14363
  if (ctx.topsisScoresByArm === void 0) return { confidence, reason, alternatives };
14101
14364
  const alternativeScores = new Map(
14102
- alternatives.map((arm) => [arm, ctx.topsisScoresByArm?.get(arm) ?? 0])
14365
+ alternatives.filter((arm) => ctx.topsisScoresByArm?.has(arm) === true).map((arm) => [arm, ctx.topsisScoresByArm?.get(arm) ?? 0])
14103
14366
  );
14104
14367
  return { confidence, reason, alternatives, alternativeScores };
14105
14368
  }
@@ -17697,7 +17960,10 @@ function buildWeatherCostSection(cfg, deps, includePipelineJoins = false) {
17697
17960
  }
17698
17961
 
17699
17962
  // src/mcp/tools/weather-report-arms.ts
17700
- var ROUTED_ARMS = [...CLI_NAMES, ...ApiArmIdSchema.options];
17963
+ var ROUTED_ARMS = [
17964
+ ...CLI_NAMES,
17965
+ ...ApiArmIdSchema.options
17966
+ ];
17701
17967
  var SLOT_ARMS = new Map(
17702
17968
  CLI_NAMES.map((slot) => [
17703
17969
  slot,
@@ -18275,11 +18541,21 @@ function getFallbackChainForCategory(category, bucketType, registry = DEFAULT_FA
18275
18541
 
18276
18542
  // src/cli-adapters/composite-router-scoring-stages.ts
18277
18543
  function armsToSlots(candidates) {
18278
- return [...new Set(candidates.map(routingArmDisplaySlot))];
18544
+ return [
18545
+ ...new Set(
18546
+ candidates.flatMap((arm) => {
18547
+ const slot = routingArmCliSlot(arm);
18548
+ return slot === void 0 ? [] : [slot];
18549
+ })
18550
+ )
18551
+ ];
18279
18552
  }
18280
18553
  function keepArmsForSlots(candidates, survivingSlots) {
18281
18554
  const slotSet = new Set(survivingSlots);
18282
- return candidates.filter((arm) => slotSet.has(routingArmDisplaySlot(arm)));
18555
+ return candidates.filter((arm) => {
18556
+ const slot = routingArmCliSlot(arm);
18557
+ return slot === void 0 || slotSet.has(slot);
18558
+ });
18283
18559
  }
18284
18560
  var DEFAULT_COMPLEXITY = "moderate";
18285
18561
  function extractComplexityFromSignals(signals) {
@@ -18371,7 +18647,14 @@ async function runQualityConstraintStage(candidates, stagesExecuted, deps) {
18371
18647
  if (!deps.config.enableQualityConstraint || deps.qualityConstraintStage === void 0) {
18372
18648
  return { eligible: candidates, filtered: /* @__PURE__ */ new Map(), usedFallback: false };
18373
18649
  }
18374
- const ctx = createRoutingContext("", armsToSlots(candidates));
18650
+ const slots = armsToSlots(candidates);
18651
+ if (candidates.some((arm) => routingArmCliSlot(arm) === void 0)) {
18652
+ stagesExecuted.push("quality-constraint:endpoint-unmeasured");
18653
+ }
18654
+ if (slots.length === 0) {
18655
+ return { eligible: candidates, filtered: /* @__PURE__ */ new Map(), usedFallback: false };
18656
+ }
18657
+ const ctx = createRoutingContext("", slots);
18375
18658
  const result = await deps.qualityConstraintStage.route(ctx);
18376
18659
  stagesExecuted.push("quality-constraint");
18377
18660
  if (!result.ok) {
@@ -18478,7 +18761,7 @@ function runZeroRouterStage(task, candidates, stagesExecuted, deps) {
18478
18761
  return result;
18479
18762
  }
18480
18763
  function runTopsisStage(taskProfile, candidates, stagesExecuted, deps, options) {
18481
- if (!deps.config.enableTopsisRanking || deps.topsisRouter === void 0) {
18764
+ if (!deps.config.enableTopsisRanking || deps.topsisRouter === void 0 || armsToSlots(candidates).length === 0) {
18482
18765
  return { ranking: candidates, score: void 0 };
18483
18766
  }
18484
18767
  const topsisOptions = {
@@ -18536,10 +18819,10 @@ function runLatencyStage(candidates, stagesExecuted, deps) {
18536
18819
  }
18537
18820
  const scores = deps.latencyTracker.getScores(armsToSlots(candidates));
18538
18821
  stagesExecuted.push("latency-scoring");
18539
- const scoreOf = (arm) => scores.find((s) => s.cli === routingArmDisplaySlot(arm))?.score ?? 0;
18822
+ const scoreOf = (arm) => scores.find((s) => s.cli === routingArmCliSlot(arm))?.score ?? 0;
18540
18823
  const sortedCandidates = [...candidates].sort((a, b) => scoreOf(b) - scoreOf(a));
18541
18824
  const topArm = sortedCandidates[0];
18542
- const topScore = topArm !== void 0 ? scores.find((s) => s.cli === routingArmDisplaySlot(topArm))?.score : void 0;
18825
+ const topScore = topArm !== void 0 ? scores.find((s) => s.cli === routingArmCliSlot(topArm))?.score : void 0;
18543
18826
  deps.logger.debug("Latency scoring applied", {
18544
18827
  scores: scores.map((s) => ({
18545
18828
  cli: s.cli,
@@ -18647,6 +18930,7 @@ function getPerformanceDataForCategory(taskContent) {
18647
18930
  const summary = getOutcomeStore().summarize({ category: match.category });
18648
18931
  const result = /* @__PURE__ */ new Map();
18649
18932
  for (const [cli, stats] of summary.byCli) {
18933
+ if (!isCliName(cli)) continue;
18650
18934
  result.set(cli, {
18651
18935
  successRate: stats.successRate,
18652
18936
  sampleCount: stats.count
@@ -18754,9 +19038,18 @@ function applyCategoryOverride(task, candidates, stagesExecuted) {
18754
19038
  if (match === null) return ok(candidates);
18755
19039
  const override = CATEGORY_CHAIN_OVERRIDES[match.category];
18756
19040
  if (override === void 0) return ok(candidates);
19041
+ if (!isCategoryFailClosed(match.category) && candidates.some((arm) => routingArmCliSlot(arm) === void 0)) {
19042
+ stagesExecuted.push("category-override:endpoint-unmeasured");
19043
+ }
18757
19044
  const overrideSet = new Set(override);
18758
- const orderIndex = (arm) => override.indexOf(routingArmDisplaySlot(arm));
18759
- const filtered = candidates.filter((arm) => overrideSet.has(routingArmDisplaySlot(arm))).sort((a, b) => orderIndex(a) - orderIndex(b));
19045
+ const orderIndex = (arm) => {
19046
+ const slot = routingArmCliSlot(arm);
19047
+ return slot === void 0 ? override.length : override.indexOf(slot);
19048
+ };
19049
+ const filtered = candidates.filter((arm) => {
19050
+ const slot = routingArmCliSlot(arm);
19051
+ return slot === void 0 ? !isCategoryFailClosed(match.category) : overrideSet.has(slot);
19052
+ }).sort((a, b) => orderIndex(a) - orderIndex(b));
18760
19053
  if (filtered.length === 0) {
18761
19054
  if (isCategoryFailClosed(match.category)) {
18762
19055
  stagesExecuted.push("category-override:fail-closed");
@@ -18779,8 +19072,9 @@ function applyCategoryOverride(task, candidates, stagesExecuted) {
18779
19072
  return ok(filtered);
18780
19073
  }
18781
19074
  function applyLinUCBFloorOverride(linucbCli, topsisRanking, opts) {
18782
- if (opts.perfData === void 0) return linucbCli;
18783
- const cliPerf = opts.perfData.get(routingArmDisplaySlot(linucbCli));
19075
+ const slot = routingArmCliSlot(linucbCli);
19076
+ if (opts.perfData === void 0 || slot === void 0) return linucbCli;
19077
+ const cliPerf = opts.perfData.get(slot);
18784
19078
  if (cliPerf === void 0 || cliPerf.sampleCount < 20 || cliPerf.successRate >= 0.5) {
18785
19079
  return linucbCli;
18786
19080
  }
@@ -18878,11 +19172,13 @@ function buildPipelineResult(p) {
18878
19172
  preferenceScore: p.prefResult.preferenceScore,
18879
19173
  preferenceTier: p.prefResult.preferenceTier,
18880
19174
  topsisRanking: p.topsisResult.ranking,
18881
- topsisScore: p.topsisResult.score,
19175
+ // An endpoint did not participate in TOPSIS; do not report a CLI score.
19176
+ topsisScore: routingArmCliSlot(p.selectedCli) === void 0 ? void 0 : p.topsisResult.score,
18882
19177
  topsisScoresByArm: p.topsisResult.scoresByArm,
18883
19178
  selectedCli: p.selectedCli,
18884
19179
  ucbScore: p.linucbResult.ucbScore,
18885
- latencyScore: p.latencyResult.latencyScore,
19180
+ // Endpoint latency is unmeasured; the stage's best CLI score is not its own.
19181
+ latencyScore: routingArmCliSlot(p.selectedCli) === void 0 ? void 0 : p.latencyResult.latencyScore,
18886
19182
  memoryRecommendation: p.memoryResult.recommendation,
18887
19183
  memoryConfidence: p.memoryResult.memoryConfidence,
18888
19184
  ...stageScores.size > 0 ? { stageScores } : {},
@@ -19181,8 +19477,8 @@ function buildDefaultModelSources(adapters, opts = {}) {
19181
19477
  }
19182
19478
  for (const [key, adapter] of adapters) {
19183
19479
  if (hasListModels(adapter)) {
19184
- const slot = routingArmDisplaySlot(key);
19185
- sources.push(adapterSource(slot, adapter));
19480
+ const sourceName = routingArmCliSlot(key) ?? key;
19481
+ sources.push(adapterSource(sourceName, adapter));
19186
19482
  }
19187
19483
  }
19188
19484
  return sources;
@@ -19437,12 +19733,10 @@ var PendingRoutingOutcomes = class {
19437
19733
  try {
19438
19734
  if (!isRouteModelShadowEnabled() || decision.difficultyTier === void 0) return void 0;
19439
19735
  if (task.model !== void 0) return void 0;
19736
+ const slot = routingArmCliSlot(decision.cliName);
19737
+ if (slot === void 0) return void 0;
19440
19738
  logModelSelectionReadinessOnce(this.logger);
19441
- const comparison = computeModelSelectionShadow(
19442
- routingArmDisplaySlot(decision.cliName),
19443
- decision.difficultyTier,
19444
- decision.model
19445
- );
19739
+ const comparison = computeModelSelectionShadow(slot, decision.difficultyTier, decision.model);
19446
19740
  this.logger.debug("Model-selection shadow computed (#4197)", {
19447
19741
  cli: comparison.cli,
19448
19742
  tier: comparison.tier,
@@ -19536,12 +19830,14 @@ function recordZeroRouterOutcome(task, success, qualityScore, deps, attribution)
19536
19830
  return;
19537
19831
  }
19538
19832
  const { difficulty, selectedCli } = attribution;
19833
+ const slot = routingArmCliSlot(selectedCli);
19834
+ if (slot === void 0) return;
19539
19835
  const outcome = buildDifficultyOutcome(
19540
19836
  task.content,
19541
19837
  difficulty,
19542
19838
  // Difficulty calibration is slot-level; collapse an api:* arm to its
19543
19839
  // display slot here (the bandit retains the distinct arm). (#3422)
19544
- routingArmDisplaySlot(selectedCli),
19840
+ slot,
19545
19841
  success,
19546
19842
  qualityScore
19547
19843
  );
@@ -19575,8 +19871,8 @@ function getCachedCliSuccessRate(cli) {
19575
19871
  function rewardSuccessRate(arm) {
19576
19872
  const own = getCachedCliSuccessRate(arm);
19577
19873
  if (own !== void 0) return own;
19578
- const slot = routingArmDisplaySlot(arm);
19579
- return slot === arm ? void 0 : getCachedCliSuccessRate(slot);
19874
+ const slot = routingArmCliSlot(arm);
19875
+ return slot === void 0 || slot === arm ? void 0 : getCachedCliSuccessRate(slot);
19580
19876
  }
19581
19877
  function computeQualityReward(cli, success, durationMs) {
19582
19878
  if (!success) return 0.1;
@@ -19603,12 +19899,16 @@ function computeQualityReward(cli, success, durationMs) {
19603
19899
  // src/cli-adapters/composite-router-metrics.ts
19604
19900
  function recordDecisionToMetrics(decision, traceId, deps) {
19605
19901
  if (deps.metricsCollector === void 0) return;
19606
- const selectedModel = routingArmDisplaySlot(decision.cliName);
19902
+ const selectedModel = routingArmCliSlot(decision.cliName);
19903
+ if (selectedModel === void 0) return;
19607
19904
  deps.metricsCollector.recordDecision({
19608
19905
  timestamp: getTimeProvider().nowIso(),
19609
19906
  traceId,
19610
19907
  selectedModel,
19611
- alternativeModels: decision.alternatives.map(routingArmDisplaySlot),
19908
+ alternativeModels: decision.alternatives.flatMap((arm) => {
19909
+ const slot = routingArmCliSlot(arm);
19910
+ return slot === void 0 ? [] : [slot];
19911
+ }),
19612
19912
  isExploration: decision.ucbScore !== void 0 && decision.ucbScore > 0.5,
19613
19913
  taskType: decision.taskProfile.taskType,
19614
19914
  contextTokens: decision.taskProfile.contextRequired,
@@ -19836,9 +20136,8 @@ var CompositeRouter = class _CompositeRouter {
19836
20136
  type: "routing.decision",
19837
20137
  timestamp: getTimeProvider().now(),
19838
20138
  taskId: taskDescription.slice(0, 100),
19839
- // Trace attribution is slot-level; collapse the api:* arm (#3422) so this
19840
- // sink matches every other telemetry sink (the bandit keeps the arm).
19841
- selectedModel: routingArmDisplaySlot(decision.cliName),
20139
+ // Built-in vendor arms retain slot display; endpoints retain their own identity.
20140
+ selectedModel: routingArmCliSlot(decision.cliName) ?? decision.cliName,
19842
20141
  reasoning: decision.reason,
19843
20142
  decisionPath: decision.stagesExecuted
19844
20143
  });
@@ -19874,7 +20173,7 @@ var CompositeRouter = class _CompositeRouter {
19874
20173
  */
19875
20174
  async consultUnifiedContext(task) {
19876
20175
  try {
19877
- const { getContextForTask, inferTaskCategory } = await import("./context-retriever-HVPLM6DH.js");
20176
+ const { getContextForTask, inferTaskCategory } = await import("./context-retriever-CBOMGQAP.js");
19878
20177
  const ctx = await getContextForTask({
19879
20178
  task: task.content,
19880
20179
  category: inferTaskCategory(task.content),
@@ -19936,8 +20235,10 @@ var CompositeRouter = class _CompositeRouter {
19936
20235
  const durationMs = getTimeProvider().now() - startTime;
19937
20236
  const success = executeResult.ok;
19938
20237
  this.autoRecordFeedback(decision, task, success, durationMs);
20238
+ const routedSlot = routingArmCliSlot(decision.cliName);
19939
20239
  const routed = {
19940
- routedCli: routingArmDisplaySlot(decision.cliName),
20240
+ // A gateway endpoint has no routed CLI; routedArm carries its identity.
20241
+ ...routedSlot !== void 0 && { routedCli: routedSlot },
19941
20242
  routedArm: decision.cliName,
19942
20243
  routedDurationMs: armDurationMs
19943
20244
  };
@@ -19946,10 +20247,17 @@ var CompositeRouter = class _CompositeRouter {
19946
20247
  }
19947
20248
  autoRecordFeedback(decision, task, success, durationMs) {
19948
20249
  const arm = decision.cliName;
19949
- const slot = routingArmDisplaySlot(arm);
20250
+ const slot = routingArmCliSlot(arm);
19950
20251
  const reward = computeQualityReward(arm, success, durationMs);
19951
20252
  this.recordOutcome(arm, task, reward, success);
19952
20253
  this.recordExecutedDifficultyOutcome(decision, task, success);
20254
+ this.logger.debug("Auto-recorded feedback", {
20255
+ cli: arm,
20256
+ success,
20257
+ durationMs,
20258
+ reward
20259
+ });
20260
+ if (slot === void 0) return;
19953
20261
  if (this.latencyTracker !== void 0) {
19954
20262
  this.latencyTracker.record(slot, durationMs, success);
19955
20263
  }
@@ -19977,12 +20285,6 @@ var CompositeRouter = class _CompositeRouter {
19977
20285
  { metricsCollector: this.metricsCollector, logger: this.logger }
19978
20286
  );
19979
20287
  }
19980
- this.logger.debug("Auto-recorded feedback", {
19981
- cli: arm,
19982
- success,
19983
- durationMs,
19984
- reward
19985
- });
19986
20288
  }
19987
20289
  /** Task type inference keywords. */
19988
20290
  static TASK_TYPE_KEYWORDS = [
@@ -20065,9 +20367,10 @@ var CompositeRouter = class _CompositeRouter {
20065
20367
  return this.cliNames;
20066
20368
  }
20067
20369
  const sourcesWithModels = new Set(all.map((m) => m.source));
20068
- const filtered = this.cliNames.filter(
20069
- (name) => sourcesWithModels.has(routingArmDisplaySlot(name))
20070
- );
20370
+ const filtered = this.cliNames.filter((name) => {
20371
+ const slot = routingArmCliSlot(name);
20372
+ return slot === void 0 || sourcesWithModels.has(slot);
20373
+ });
20071
20374
  if (filtered.length === 0) {
20072
20375
  this.logger.info(
20073
20376
  "AvailableModelsCache filtered out all CLIs; falling back to all (possible stale/misconfigured cache)",
@@ -20139,7 +20442,8 @@ var CompositeRouter = class _CompositeRouter {
20139
20442
  decisionTimeMs,
20140
20443
  billingMode: this.config.billingMode
20141
20444
  });
20142
- const model = isRouteModelSelectionEnabled() && params.difficultyTier !== void 0 ? resolveModelForTier(routingArmDisplaySlot(params.selectedCli), params.difficultyTier) : void 0;
20445
+ const modelSlot = routingArmCliSlot(params.selectedCli);
20446
+ const model = isRouteModelSelectionEnabled() && params.difficultyTier !== void 0 && modelSlot !== void 0 ? resolveModelForTier(modelSlot, params.difficultyTier) : void 0;
20143
20447
  return ok({
20144
20448
  adapter: selectedAdapter,
20145
20449
  cliName: params.selectedCli,
@@ -20163,7 +20467,8 @@ var CompositeRouter = class _CompositeRouter {
20163
20467
  }
20164
20468
  updateStats(selectedCli, decisionTimeMs) {
20165
20469
  this.totalDecisions++;
20166
- this.decisionsPerCli[routingArmDisplaySlot(selectedCli)]++;
20470
+ const slot = routingArmCliSlot(selectedCli);
20471
+ if (slot !== void 0) this.decisionsPerCli[slot]++;
20167
20472
  this.totalDecisionTimeMs += decisionTimeMs;
20168
20473
  }
20169
20474
  /**
@@ -20191,9 +20496,10 @@ var CompositeRouter = class _CompositeRouter {
20191
20496
  }
20192
20497
  recordOutcome(cliName, task, reward, success) {
20193
20498
  recordBanditOutcome(cliName, task, reward, this.getOutcomeDependencies());
20194
- if (this.config.enableStrategyDistillation && this.distilledRuleStage !== void 0 && success !== void 0) {
20499
+ const slot = routingArmCliSlot(cliName);
20500
+ if (this.config.enableStrategyDistillation && this.distilledRuleStage !== void 0 && success !== void 0 && slot !== void 0) {
20195
20501
  this.distilledRuleStage.recordOutcome({
20196
- selectedCli: routingArmDisplaySlot(cliName),
20502
+ selectedCli: slot,
20197
20503
  task: task.content,
20198
20504
  success
20199
20505
  });
@@ -20456,10 +20762,7 @@ function loadManifestOverlay(options) {
20456
20762
  return mergeOverlays(user, operator);
20457
20763
  }
20458
20764
  function mergeOverlays(lower, higher) {
20459
- const byId = /* @__PURE__ */ new Map();
20460
- for (const entry of lower.entries) byId.set(entry.id, entry);
20461
- for (const entry of higher.entries) byId.set(entry.id, entry);
20462
- const entries = [...byId.values()];
20765
+ const entries = [...lower.entries, ...higher.entries];
20463
20766
  const merged = {
20464
20767
  entries,
20465
20768
  rejections: [...lower.rejections, ...higher.rejections],
@@ -20760,6 +21063,10 @@ function loadGeneratedRegistryEntries(options) {
20760
21063
  }
20761
21064
 
20762
21065
  // src/config/model-registry.ts
21066
+ var pricingSources = /* @__PURE__ */ new WeakMap();
21067
+ function pricingSourceOf(entry) {
21068
+ return (entry.pricing === void 0 ? void 0 : pricingSources.get(entry.pricing)) ?? entry.source;
21069
+ }
20763
21070
  var ModelRegistry = class {
20764
21071
  byId = /* @__PURE__ */ new Map();
20765
21072
  byAlias = /* @__PURE__ */ new Map();
@@ -20875,9 +21182,22 @@ var ModelRegistry = class {
20875
21182
  }
20876
21183
  loadEntries(entries) {
20877
21184
  for (const entry of entries) {
20878
- this.byId.set(entry.id, entry);
20879
- if (entry.aliases !== void 0) {
20880
- for (const alias of entry.aliases) {
21185
+ const merged = { ...entry };
21186
+ if (entry.pricing === void 0) {
21187
+ const lower = this.byId.get(entry.id);
21188
+ if (lower?.pricing !== void 0) {
21189
+ merged.pricing = lower.pricing;
21190
+ if (lower.pricingProvenance !== void 0) {
21191
+ merged.pricingProvenance = lower.pricingProvenance;
21192
+ }
21193
+ }
21194
+ } else {
21195
+ merged.pricing = { ...entry.pricing };
21196
+ pricingSources.set(merged.pricing, entry.source);
21197
+ }
21198
+ this.byId.set(entry.id, merged);
21199
+ if (merged.aliases !== void 0) {
21200
+ for (const alias of merged.aliases) {
20881
21201
  this.byAlias.set(alias, entry.id);
20882
21202
  if (alias !== entry.id) this.byId.delete(alias);
20883
21203
  }
@@ -20956,7 +21276,7 @@ function setDefaultRegistry(registry) {
20956
21276
  }
20957
21277
  async function reloadDefaultRegistry() {
20958
21278
  globalRegistry = buildDefaultRegistry();
20959
- const { resetGlobalRegistry } = await import("./unified-registry-KLNC24HA.js");
21279
+ const { resetGlobalRegistry } = await import("./unified-registry-IEPJHJHO.js");
20960
21280
  resetGlobalRegistry();
20961
21281
  return globalRegistry;
20962
21282
  }
@@ -20978,12 +21298,12 @@ var VENDOR_TO_CLI_SLOT = {
20978
21298
  };
20979
21299
  function ownerOfEntry(entry) {
20980
21300
  if (isCliName2(entry.cliName)) return entry.cliName;
20981
- const owners = /* @__PURE__ */ new Set();
21301
+ const owners2 = /* @__PURE__ */ new Set();
20982
21302
  for (const key of [entry.id, ...entry.aliases ?? []]) {
20983
21303
  const owner = inTreeOwner(key);
20984
- if (owner !== void 0) owners.add(owner);
21304
+ if (owner !== void 0) owners2.add(owner);
20985
21305
  }
20986
- return owners.size === 1 ? [...owners][0] : void 0;
21306
+ return owners2.size === 1 ? [...owners2][0] : void 0;
20987
21307
  }
20988
21308
  function slotOfEntry(entry) {
20989
21309
  return ownerOfEntry(entry) ?? VENDOR_TO_CLI_SLOT[entry.vendor] ?? "opencode";
@@ -21310,7 +21630,7 @@ export {
21310
21630
  isCliName,
21311
21631
  ApiArmIdSchema,
21312
21632
  apiArmId,
21313
- routingArmDisplaySlot,
21633
+ routingArmCliSlot,
21314
21634
  isEndpointArmId,
21315
21635
  CLI_VERSION_REQUIREMENTS,
21316
21636
  DEFAULT_CAPABILITIES,
@@ -21413,20 +21733,17 @@ export {
21413
21733
  CircuitBreakerRegistry,
21414
21734
  mapCliErrorToCategory,
21415
21735
  mapModelErrorToCategory,
21736
+ setGatewayCatalog,
21737
+ createGatewayArmAdapter,
21738
+ ModelToCliAdapter,
21416
21739
  createModelToCliAdapter,
21740
+ gatewaySlotEndpointOf,
21417
21741
  gatewayServedSlotOf,
21418
21742
  cliBinaryAdapterOf,
21419
21743
  resolveGatewayServedSlot,
21420
21744
  decideSlotServing,
21421
21745
  isDisabledSlotUnserved,
21422
21746
  buildGatewaySlotRouterArm,
21423
- createOpenRouterModelsSource,
21424
- isDynamicModelsEnabled,
21425
- buildDefaultModelSources,
21426
- resolveOwnerCli,
21427
- resolveCliSlot,
21428
- getTokenEstimator,
21429
- estimateTokens,
21430
21747
  computeTokenCost,
21431
21748
  priceBasisOf,
21432
21749
  recordUsageEvent,
@@ -21437,12 +21754,19 @@ export {
21437
21754
  gatewayEndpointRejection,
21438
21755
  gatewayCostStatus,
21439
21756
  resolveGatewayCostDeclaration,
21757
+ gatewayCostGap,
21440
21758
  describeGatewayCostDeclaration,
21441
21759
  warnIfGatewayCostUndeclared,
21442
- setGatewayCatalog,
21443
- clearGatewayCatalog,
21760
+ budgetCostOfArm,
21444
21761
  gatewayCostDetail,
21445
21762
  servedCostDetail,
21763
+ createOpenRouterModelsSource,
21764
+ isDynamicModelsEnabled,
21765
+ buildDefaultModelSources,
21766
+ resolveOwnerCli,
21767
+ resolveCliSlot,
21768
+ getTokenEstimator,
21769
+ estimateTokens,
21446
21770
  ModelRegistry,
21447
21771
  getDefaultRegistry,
21448
21772
  setDefaultRegistry,
@@ -21623,4 +21947,4 @@ export {
21623
21947
  AgentCapability,
21624
21948
  OrchestratorError
21625
21949
  };
21626
- //# sourceMappingURL=chunk-WKFPKPEM.js.map
21950
+ //# sourceMappingURL=chunk-EBOAFTOG.js.map