@omnicross/core 0.1.4 → 0.1.6

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 (204) hide show
  1. package/dist/ApiConverter.cjs +2 -2
  2. package/dist/ApiConverter.js +1 -1
  3. package/dist/{CompletionService-DdWaAxq0.d.ts → CompletionService-C3BX0Ovy.d.ts} +4 -3
  4. package/dist/{CompletionService-D3a47vdU.d.cts → CompletionService-kNA17cfI.d.cts} +4 -3
  5. package/dist/auth/GeminiCodeAssistProjectResolver.cjs +7 -5
  6. package/dist/auth/GeminiCodeAssistProjectResolver.js +5 -3
  7. package/dist/{chunk-HRRYG2AX.js → chunk-23S5OPIO.js} +10 -1
  8. package/dist/chunk-25GXJCEZ.cjs +40 -0
  9. package/dist/chunk-2JYRIADS.js +40 -0
  10. package/dist/chunk-3Z5BQZFM.cjs +52 -0
  11. package/dist/{chunk-4VAVYUZS.cjs → chunk-4VLRHHFE.cjs} +82 -40
  12. package/dist/{chunk-VACWOIRE.cjs → chunk-4VZX5F4T.cjs} +39 -15
  13. package/dist/{chunk-FTQ7IQUC.js → chunk-6CL5HTPQ.js} +52 -10
  14. package/dist/chunk-6QQG7YG3.cjs +153 -0
  15. package/dist/{chunk-SU2GCLAC.cjs → chunk-6VUQPOV3.cjs} +359 -60
  16. package/dist/chunk-7AK7B36B.cjs +44 -0
  17. package/dist/{chunk-5ZQBEOMD.js → chunk-AT7B7SOZ.js} +25 -2
  18. package/dist/{chunk-IK3KE3AU.js → chunk-DE2SRBFZ.js} +1 -1
  19. package/dist/chunk-DLXZEZWO.cjs +285 -0
  20. package/dist/{chunk-UHGVBFU3.js → chunk-EBLFCNPY.js} +38 -14
  21. package/dist/chunk-EJLH6NFT.cjs +166 -0
  22. package/dist/chunk-HVBBDBS3.cjs +350 -0
  23. package/dist/{chunk-7Y47UCF2.js → chunk-IFXJ2BG7.js} +5 -38
  24. package/dist/{chunk-46ZIFWYG.cjs → chunk-IIRPUVPH.cjs} +7 -1
  25. package/dist/{chunk-YGXJGRFI.cjs → chunk-KBM2W6UY.cjs} +111 -24
  26. package/dist/{chunk-OCEUVQHW.cjs → chunk-KCVJWJST.cjs} +73 -3
  27. package/dist/chunk-LB6EBS6Y.js +69 -0
  28. package/dist/{chunk-C7PSERMH.js → chunk-LVUCAWMK.js} +1 -1
  29. package/dist/chunk-MKF46GNZ.js +350 -0
  30. package/dist/{chunk-HYN75H6G.cjs → chunk-MUHWHQVM.cjs} +1 -1
  31. package/dist/{chunk-Z7Y2NPHY.js → chunk-N5T4M4GU.js} +1 -1
  32. package/dist/{chunk-TIER4SUC.js → chunk-OEWZUX4G.js} +346 -47
  33. package/dist/chunk-OF3BECU2.cjs +69 -0
  34. package/dist/{chunk-RSJ3TWJQ.cjs → chunk-OKMJLEXX.cjs} +5 -5
  35. package/dist/chunk-OPRS4IQZ.js +153 -0
  36. package/dist/{chunk-XK5CIRMQ.js → chunk-SIZQQD6T.js} +72 -2
  37. package/dist/{chunk-DKPXN34V.cjs → chunk-SQYVORNP.cjs} +1334 -510
  38. package/dist/chunk-SYQF7OIR.js +52 -0
  39. package/dist/{chunk-S4WBV25P.js → chunk-TOVPMMHM.js} +111 -24
  40. package/dist/{chunk-QYTT6GE3.js → chunk-UDCC7EMR.js} +1093 -269
  41. package/dist/{chunk-E3UCVHLP.cjs → chunk-UNWKG6EI.cjs} +5 -38
  42. package/dist/{chunk-ZLX3KGXX.js → chunk-UX7VWA46.js} +135 -23
  43. package/dist/{chunk-7YN22L2H.cjs → chunk-V4TXMEJS.cjs} +5 -5
  44. package/dist/chunk-VRFBB5DB.js +44 -0
  45. package/dist/chunk-WB6PH56J.js +166 -0
  46. package/dist/{chunk-G2UTNSGU.js → chunk-WNKWAEUR.js} +7 -1
  47. package/dist/{chunk-SUEGJ75D.cjs → chunk-WYTEQ4Q5.cjs} +25 -2
  48. package/dist/{chunk-5ENKBSWO.js → chunk-YJVHCHQX.js} +42 -6
  49. package/dist/{chunk-VQY5W4YW.cjs → chunk-YK57NMIF.cjs} +44 -8
  50. package/dist/{chunk-KFI44N2R.cjs → chunk-YNJNTCSQ.cjs} +10 -1
  51. package/dist/completion/ApiKeyPoolService.cjs +12 -0
  52. package/dist/completion/ApiKeyPoolService.d.cts +6 -0
  53. package/dist/completion/ApiKeyPoolService.d.ts +6 -0
  54. package/dist/completion/ApiKeyPoolService.js +12 -0
  55. package/dist/completion/CompletionService.cjs +27 -24
  56. package/dist/completion/CompletionService.d.cts +2 -1
  57. package/dist/completion/CompletionService.d.ts +2 -1
  58. package/dist/completion/CompletionService.js +26 -23
  59. package/dist/completion.cjs +27 -24
  60. package/dist/completion.d.cts +2 -1
  61. package/dist/completion.d.ts +2 -1
  62. package/dist/completion.js +26 -23
  63. package/dist/index.cjs +53 -29
  64. package/dist/index.d.cts +8 -8
  65. package/dist/index.d.ts +8 -8
  66. package/dist/index.js +56 -32
  67. package/dist/{keyPolicy-Cp0FntZl.d.cts → keyPolicy-zdWTu3CQ.d.cts} +1 -1
  68. package/dist/{keyPolicy-Cp0FntZl.d.ts → keyPolicy-zdWTu3CQ.d.ts} +1 -1
  69. package/dist/outbound-api/auditCapture.cjs +2 -2
  70. package/dist/outbound-api/auditCapture.d.cts +5 -3
  71. package/dist/outbound-api/auditCapture.d.ts +5 -3
  72. package/dist/outbound-api/auditCapture.js +1 -1
  73. package/dist/outbound-api/quotaWarn.d.cts +1 -1
  74. package/dist/outbound-api/quotaWarn.d.ts +1 -1
  75. package/dist/outbound-api/routeResolver.cjs +2 -2
  76. package/dist/outbound-api/routeResolver.d.cts +4 -3
  77. package/dist/outbound-api/routeResolver.d.ts +4 -3
  78. package/dist/outbound-api/routeResolver.js +1 -1
  79. package/dist/outbound-api/subscriptionRegistryPort.d.cts +1 -0
  80. package/dist/outbound-api/subscriptionRegistryPort.d.ts +1 -0
  81. package/dist/outbound-api/types.d.cts +3 -2
  82. package/dist/outbound-api/types.d.ts +3 -2
  83. package/dist/outbound-api.cjs +49 -25
  84. package/dist/outbound-api.d.cts +127 -85
  85. package/dist/outbound-api.d.ts +127 -85
  86. package/dist/outbound-api.js +52 -28
  87. package/dist/pipeline/AccountAllowanceScheduling.cjs +15 -0
  88. package/dist/pipeline/AccountAllowanceScheduling.d.cts +90 -0
  89. package/dist/pipeline/AccountAllowanceScheduling.d.ts +90 -0
  90. package/dist/pipeline/AccountAllowanceScheduling.js +15 -0
  91. package/dist/pipeline/AccountAllowanceStore.cjs +20 -0
  92. package/dist/pipeline/AccountAllowanceStore.d.cts +77 -0
  93. package/dist/pipeline/AccountAllowanceStore.d.ts +77 -0
  94. package/dist/pipeline/AccountAllowanceStore.js +20 -0
  95. package/dist/pipeline/AuthSource.d.cts +11 -2
  96. package/dist/pipeline/AuthSource.d.ts +11 -2
  97. package/dist/pipeline/BoundAccountSelectionError.cjs +10 -0
  98. package/dist/pipeline/BoundAccountSelectionError.d.cts +28 -0
  99. package/dist/pipeline/BoundAccountSelectionError.d.ts +28 -0
  100. package/dist/pipeline/BoundAccountSelectionError.js +10 -0
  101. package/dist/pipeline/LlmConfigProviderAuth.d.cts +1 -0
  102. package/dist/pipeline/LlmConfigProviderAuth.d.ts +1 -0
  103. package/dist/pipeline/SubscriptionAccountHealth.cjs +4 -2
  104. package/dist/pipeline/SubscriptionAccountHealth.d.cts +34 -6
  105. package/dist/pipeline/SubscriptionAccountHealth.d.ts +34 -6
  106. package/dist/pipeline/SubscriptionAccountHealth.js +3 -1
  107. package/dist/pipeline/SubscriptionAuthSource.cjs +5 -2
  108. package/dist/pipeline/SubscriptionAuthSource.d.cts +1 -0
  109. package/dist/pipeline/SubscriptionAuthSource.d.ts +1 -0
  110. package/dist/pipeline/SubscriptionAuthSource.js +4 -1
  111. package/dist/pipeline/SubscriptionAuthStrategy.d.cts +8 -3
  112. package/dist/pipeline/SubscriptionAuthStrategy.d.ts +8 -3
  113. package/dist/pipeline/executeProviderCall.cjs +2 -2
  114. package/dist/pipeline/executeProviderCall.d.cts +8 -3
  115. package/dist/pipeline/executeProviderCall.d.ts +8 -3
  116. package/dist/pipeline/executeProviderCall.js +1 -1
  117. package/dist/pipeline/resolveProviderChain.d.cts +2 -3
  118. package/dist/pipeline/resolveProviderChain.d.ts +2 -3
  119. package/dist/pipeline/resolveSubscriptionChain.d.cts +1 -0
  120. package/dist/pipeline/resolveSubscriptionChain.d.ts +1 -0
  121. package/dist/pipeline/upstreamFetch.cjs +4 -2
  122. package/dist/pipeline/upstreamFetch.d.cts +6 -0
  123. package/dist/pipeline/upstreamFetch.d.ts +6 -0
  124. package/dist/pipeline/upstreamFetch.js +3 -1
  125. package/dist/pipeline/upstreamTrace.cjs +14 -0
  126. package/dist/pipeline/upstreamTrace.d.cts +85 -0
  127. package/dist/pipeline/upstreamTrace.d.ts +85 -0
  128. package/dist/pipeline/upstreamTrace.js +14 -0
  129. package/dist/ports/pricing-store.d.cts +4 -3
  130. package/dist/ports/pricing-store.d.ts +4 -3
  131. package/dist/ports.d.cts +4 -3
  132. package/dist/ports.d.ts +4 -3
  133. package/dist/provider-proxy/ProviderProxy.cjs +27 -24
  134. package/dist/provider-proxy/ProviderProxy.d.cts +1 -0
  135. package/dist/provider-proxy/ProviderProxy.d.ts +1 -0
  136. package/dist/provider-proxy/ProviderProxy.js +26 -23
  137. package/dist/provider-proxy/ingress/providerProxyShared.cjs +31 -24
  138. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +50 -5
  139. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +50 -5
  140. package/dist/provider-proxy/ingress/providerProxyShared.js +30 -23
  141. package/dist/provider-proxy/matchText.cjs +4 -2
  142. package/dist/provider-proxy/matchText.d.cts +41 -6
  143. package/dist/provider-proxy/matchText.d.ts +41 -6
  144. package/dist/provider-proxy/matchText.js +3 -1
  145. package/dist/provider-proxy/types.d.cts +30 -2
  146. package/dist/provider-proxy/types.d.ts +30 -2
  147. package/dist/provider-proxy.cjs +27 -24
  148. package/dist/provider-proxy.d.cts +1 -0
  149. package/dist/provider-proxy.d.ts +1 -0
  150. package/dist/provider-proxy.js +26 -23
  151. package/dist/{routeResolver-C4T7yClx.d.ts → routeResolver-CHTv_Bs5.d.ts} +1 -1
  152. package/dist/{routeResolver-CB3tvJKy.d.cts → routeResolver-kepxnfcC.d.cts} +1 -1
  153. package/dist/transformer/TransformerChainExecutor.cjs +2 -2
  154. package/dist/transformer/TransformerChainExecutor.js +1 -1
  155. package/dist/transformer/transformers/AnthropicTransformer.cjs +2 -2
  156. package/dist/transformer/transformers/AnthropicTransformer.js +1 -1
  157. package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +3 -3
  158. package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +2 -2
  159. package/dist/transformer/transformers/GeminiTransformer.cjs +3 -3
  160. package/dist/transformer/transformers/GeminiTransformer.js +2 -2
  161. package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +2 -2
  162. package/dist/transformer/transformers/OpenAIResponseTransformer.d.cts +1 -1
  163. package/dist/transformer/transformers/OpenAIResponseTransformer.d.ts +1 -1
  164. package/dist/transformer/transformers/OpenAIResponseTransformer.js +1 -1
  165. package/dist/transformer/transformers/OpenAITransformer.cjs +6 -0
  166. package/dist/transformer/transformers/OpenAITransformer.d.cts +68 -0
  167. package/dist/transformer/transformers/OpenAITransformer.d.ts +68 -0
  168. package/dist/transformer/transformers/OpenAITransformer.js +6 -0
  169. package/dist/transformer/transformers.cjs +8 -14
  170. package/dist/transformer/transformers.d.cts +12 -48
  171. package/dist/transformer/transformers.d.ts +12 -48
  172. package/dist/transformer/transformers.js +11 -17
  173. package/dist/transformer/types.d.cts +17 -0
  174. package/dist/transformer/types.d.ts +17 -0
  175. package/dist/transformer.cjs +11 -12
  176. package/dist/transformer.d.cts +1 -2
  177. package/dist/transformer.d.ts +1 -2
  178. package/dist/transformer.js +11 -12
  179. package/dist/{types-B8Arpxn0.d.cts → types-H3wGZSOo.d.cts} +134 -7
  180. package/dist/{types-lgPYQuZS.d.ts → types-hsoKrVQS.d.ts} +134 -7
  181. package/dist/usage/pricing-engine.cjs +2 -2
  182. package/dist/usage/pricing-engine.d.cts +9 -1
  183. package/dist/usage/pricing-engine.d.ts +9 -1
  184. package/dist/usage/pricing-engine.js +1 -1
  185. package/dist/usage.cjs +2 -2
  186. package/dist/usage.js +1 -1
  187. package/package.json +1 -1
  188. package/dist/chunk-C72S6TTV.cjs +0 -49
  189. package/dist/chunk-DWKQZ2SK.cjs +0 -254
  190. package/dist/chunk-IAXWICZU.js +0 -69
  191. package/dist/chunk-QWBWGODS.cjs +0 -69
  192. package/dist/chunk-RGTR7CIO.cjs +0 -235
  193. package/dist/chunk-VPBAUQ2M.js +0 -235
  194. package/dist/chunk-YMFAJFQT.cjs +0 -173
  195. package/dist/chunk-Z7LUNECE.js +0 -49
  196. package/dist/chunk-ZJZAOKI7.js +0 -254
  197. package/dist/transformer/transformers/OpenCodeGoTransformer.cjs +0 -6
  198. package/dist/transformer/transformers/OpenCodeGoTransformer.d.cts +0 -51
  199. package/dist/transformer/transformers/OpenCodeGoTransformer.d.ts +0 -51
  200. package/dist/transformer/transformers/OpenCodeGoTransformer.js +0 -6
  201. package/dist/transformer/transformers/ReasoningTransformer.cjs +0 -6
  202. package/dist/transformer/transformers/ReasoningTransformer.d.cts +0 -47
  203. package/dist/transformer/transformers/ReasoningTransformer.d.ts +0 -47
  204. package/dist/transformer/transformers/ReasoningTransformer.js +0 -6
@@ -1,21 +1,30 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13;
2
2
 
3
+
4
+
5
+ var _chunkEJLH6NFTcjs = require('./chunk-EJLH6NFT.cjs');
6
+
7
+
3
8
  var _chunkHQP3K7PUcjs = require('./chunk-HQP3K7PU.cjs');
4
9
 
5
10
 
6
- var _chunk4VAVYUZScjs = require('./chunk-4VAVYUZS.cjs');
11
+ var _chunkIIRPUVPHcjs = require('./chunk-IIRPUVPH.cjs');
7
12
 
8
13
 
9
- var _chunk7YN22L2Hcjs = require('./chunk-7YN22L2H.cjs');
14
+ var _chunkGBHYAGX3cjs = require('./chunk-GBHYAGX3.cjs');
10
15
 
11
16
 
12
- var _chunkSU2GCLACcjs = require('./chunk-SU2GCLAC.cjs');
17
+ var _chunkV4TXMEJScjs = require('./chunk-V4TXMEJS.cjs');
13
18
 
14
19
 
15
- var _chunk46ZIFWYGcjs = require('./chunk-46ZIFWYG.cjs');
20
+ var _chunk6VUQPOV3cjs = require('./chunk-6VUQPOV3.cjs');
16
21
 
17
22
 
18
- var _chunkGBHYAGX3cjs = require('./chunk-GBHYAGX3.cjs');
23
+
24
+ var _chunk4VLRHHFEcjs = require('./chunk-4VLRHHFE.cjs');
25
+
26
+
27
+ var _chunkR3HK6R4Bcjs = require('./chunk-R3HK6R4B.cjs');
19
28
 
20
29
 
21
30
  var _chunkRPII3E6Zcjs = require('./chunk-RPII3E6Z.cjs');
@@ -25,37 +34,37 @@ var _chunkRPII3E6Zcjs = require('./chunk-RPII3E6Z.cjs');
25
34
  var _chunk6RPZADX3cjs = require('./chunk-6RPZADX3.cjs');
26
35
 
27
36
 
37
+ var _chunkNYUNU75Acjs = require('./chunk-NYUNU75A.cjs');
28
38
 
29
- var _chunkQWBWGODScjs = require('./chunk-QWBWGODS.cjs');
30
39
 
31
40
 
32
- var _chunkUIBD2YY5cjs = require('./chunk-UIBD2YY5.cjs');
41
+ var _chunkYK57NMIFcjs = require('./chunk-YK57NMIF.cjs');
33
42
 
34
43
 
35
- var _chunkR3HK6R4Bcjs = require('./chunk-R3HK6R4B.cjs');
44
+ var _chunkYNJNTCSQcjs = require('./chunk-YNJNTCSQ.cjs');
36
45
 
37
46
 
38
- var _chunkHYN75H6Gcjs = require('./chunk-HYN75H6G.cjs');
47
+ var _chunkSVNDB62Dcjs = require('./chunk-SVNDB62D.cjs');
39
48
 
40
49
 
50
+ var _chunkUIBD2YY5cjs = require('./chunk-UIBD2YY5.cjs');
41
51
 
42
- var _chunkQ27JY5RGcjs = require('./chunk-Q27JY5RG.cjs');
43
52
 
53
+ var _chunk6QQG7YG3cjs = require('./chunk-6QQG7YG3.cjs');
44
54
 
45
- var _chunkQXD4MV2Xcjs = require('./chunk-QXD4MV2X.cjs');
46
55
 
47
56
 
48
- var _chunkNYUNU75Acjs = require('./chunk-NYUNU75A.cjs');
57
+ var _chunk25GXJCEZcjs = require('./chunk-25GXJCEZ.cjs');
49
58
 
50
59
 
60
+ var _chunkMUHWHQVMcjs = require('./chunk-MUHWHQVM.cjs');
51
61
 
52
- var _chunkVQY5W4YWcjs = require('./chunk-VQY5W4YW.cjs');
53
62
 
54
63
 
55
- var _chunkKFI44N2Rcjs = require('./chunk-KFI44N2R.cjs');
64
+ var _chunkQ27JY5RGcjs = require('./chunk-Q27JY5RG.cjs');
56
65
 
57
66
 
58
- var _chunkSVNDB62Dcjs = require('./chunk-SVNDB62D.cjs');
67
+ var _chunkQXD4MV2Xcjs = require('./chunk-QXD4MV2X.cjs');
59
68
 
60
69
 
61
70
  var _chunkAPYG5QD7cjs = require('./chunk-APYG5QD7.cjs');
@@ -72,7 +81,8 @@ var _chunk4YINUUKQcjs = require('./chunk-4YINUUKQ.cjs');
72
81
 
73
82
 
74
83
 
75
- var _chunkVACWOIREcjs = require('./chunk-VACWOIRE.cjs');
84
+
85
+ var _chunk4VZX5F4Tcjs = require('./chunk-4VZX5F4T.cjs');
76
86
 
77
87
 
78
88
 
@@ -80,14 +90,14 @@ var _chunkVACWOIREcjs = require('./chunk-VACWOIRE.cjs');
80
90
  var _chunkA2YMUCBTcjs = require('./chunk-A2YMUCBT.cjs');
81
91
 
82
92
 
83
- var _chunkE3UCVHLPcjs = require('./chunk-E3UCVHLP.cjs');
93
+ var _chunkUNWKG6EIcjs = require('./chunk-UNWKG6EI.cjs');
84
94
 
85
95
 
86
96
 
87
- var _chunkSUEGJ75Dcjs = require('./chunk-SUEGJ75D.cjs');
97
+ var _chunkWYTEQ4Q5cjs = require('./chunk-WYTEQ4Q5.cjs');
88
98
 
89
99
 
90
- var _chunkOCEUVQHWcjs = require('./chunk-OCEUVQHW.cjs');
100
+ var _chunkKCVJWJSTcjs = require('./chunk-KCVJWJST.cjs');
91
101
 
92
102
 
93
103
  var _chunkJMJBSACDcjs = require('./chunk-JMJBSACD.cjs');
@@ -486,48 +496,61 @@ function readAnthropicUsage(usage) {
486
496
  reasoningTokens: 0
487
497
  };
488
498
  }
499
+ function emitAnthropicUsageRecord(recorder, rawUsage, attribution) {
500
+ const tapped = readAnthropicUsage(rawUsage);
501
+ if (!tapped) return;
502
+ recorder.record({
503
+ messageId: null,
504
+ parentMessageId: null,
505
+ sessionId: attribution.sessionId,
506
+ providerId: attribution.providerId,
507
+ model: attribution.model,
508
+ apiKeyId: attribution.apiKeyId,
509
+ auditResponse: attribution.auditResponse,
510
+ engineOrigin: "codex-ingress",
511
+ usage: tapped,
512
+ rawUsage
513
+ });
514
+ }
489
515
  function recordAnthropicNonStreamUsage(recorder, bodyText, attribution) {
490
516
  try {
491
517
  const parsed = JSON.parse(bodyText);
492
- const tapped = readAnthropicUsage(parsed.usage);
493
- if (!tapped) return;
494
- recorder.record({
495
- messageId: null,
496
- parentMessageId: null,
497
- sessionId: attribution.sessionId,
498
- providerId: attribution.providerId,
499
- model: attribution.model,
500
- apiKeyId: attribution.apiKeyId,
501
- engineOrigin: "codex-ingress",
502
- usage: tapped,
503
- rawUsage: parsed.usage,
504
- auditResponse: attribution.auditResponse
505
- });
518
+ emitAnthropicUsageRecord(
519
+ recorder,
520
+ parsed.usage,
521
+ attribution
522
+ );
506
523
  } catch (e4) {
507
524
  }
508
525
  }
526
+ function recordAnthropicStreamUsage(recorder, rawUsage, attribution) {
527
+ try {
528
+ emitAnthropicUsageRecord(recorder, rawUsage, attribution);
529
+ } catch (e5) {
530
+ }
531
+ }
509
532
 
510
533
  // src/provider-proxy/ingress/providerProxyShared.ts
511
534
  var sharedExecutor = null;
512
535
  function getSharedExecutor() {
513
536
  if (!sharedExecutor) {
514
- sharedExecutor = new (0, _chunk46ZIFWYGcjs.TransformerChainExecutor)();
537
+ sharedExecutor = new (0, _chunkIIRPUVPHcjs.TransformerChainExecutor)();
515
538
  }
516
539
  return sharedExecutor;
517
540
  }
518
541
  var sharedResponses = null;
519
542
  function getResponsesEndpointTransformer() {
520
- if (!sharedResponses) sharedResponses = new (0, _chunkSU2GCLACcjs.OpenAIResponseTransformer)();
543
+ if (!sharedResponses) sharedResponses = new (0, _chunk6VUQPOV3cjs.OpenAIResponseTransformer)();
521
544
  return sharedResponses;
522
545
  }
523
546
  var sharedAnthropic = null;
524
547
  function getAnthropicEndpointTransformer() {
525
- if (!sharedAnthropic) sharedAnthropic = new (0, _chunk4VAVYUZScjs.AnthropicTransformer)();
548
+ if (!sharedAnthropic) sharedAnthropic = new (0, _chunk4VLRHHFEcjs.AnthropicTransformer)();
526
549
  return sharedAnthropic;
527
550
  }
528
551
  var sharedGemini = null;
529
552
  function getGeminiEndpointTransformer() {
530
- if (!sharedGemini) sharedGemini = new (0, _chunk7YN22L2Hcjs.GeminiTransformer)();
553
+ if (!sharedGemini) sharedGemini = new (0, _chunkV4TXMEJScjs.GeminiTransformer)();
531
554
  return sharedGemini;
532
555
  }
533
556
  function readBody(req) {
@@ -553,7 +576,7 @@ function rewriteJsonModel(bodyText, rewriteModel) {
553
576
  changed = true;
554
577
  }
555
578
  return changed ? JSON.stringify(obj) : bodyText;
556
- } catch (e5) {
579
+ } catch (e6) {
557
580
  return bodyText;
558
581
  }
559
582
  }
@@ -586,11 +609,22 @@ function rewriteSseLine(line, rewriteModel) {
586
609
  }
587
610
  if (!changed) return line;
588
611
  return `data:${leadingSpace}${JSON.stringify(obj)}${newline}`;
589
- } catch (e6) {
612
+ } catch (e7) {
590
613
  return line;
591
614
  }
592
615
  }
593
- async function relayStreamWithModelRewrite(res, body, rewriteModel) {
616
+ function tapSseDataLine(line, onEvent) {
617
+ const leadingStripped = line.replace(/^\s+/, "");
618
+ if (!leadingStripped.startsWith("data:")) return;
619
+ const payload = leadingStripped.slice(5).trim();
620
+ if (!payload || payload === "[DONE]") return;
621
+ try {
622
+ onEvent(JSON.parse(payload));
623
+ } catch (e8) {
624
+ }
625
+ }
626
+ async function relaySseBody(res, body, options) {
627
+ const { rewriteModel, onSseEvent } = options;
594
628
  const reader = body.getReader();
595
629
  const decoder = new TextDecoder();
596
630
  let buffer = "";
@@ -604,21 +638,26 @@ async function relayStreamWithModelRewrite(res, body, rewriteModel) {
604
638
  while ((nlIndex = buffer.indexOf("\n")) !== -1) {
605
639
  const linePart = buffer.slice(0, nlIndex + 1);
606
640
  buffer = buffer.slice(nlIndex + 1);
607
- out += rewriteSseLine(linePart, rewriteModel);
641
+ if (onSseEvent) tapSseDataLine(linePart, onSseEvent);
642
+ out += rewriteModel ? rewriteSseLine(linePart, rewriteModel) : linePart;
608
643
  }
609
644
  if (out) res.write(out);
610
645
  }
611
646
  const tail = buffer + decoder.decode();
612
- if (tail) res.write(rewriteSseLine(tail, rewriteModel));
647
+ if (tail) {
648
+ if (onSseEvent) tapSseDataLine(tail, onSseEvent);
649
+ res.write(rewriteModel ? rewriteSseLine(tail, rewriteModel) : tail);
650
+ }
613
651
  } finally {
614
652
  reader.releaseLock();
615
653
  res.end();
616
654
  }
617
655
  }
618
- async function relayResponse(res, providerResponse, isStream, rewriteModel) {
656
+ async function relayResponse(res, providerResponse, isStream, rewriteModel, usageTap) {
619
657
  const contentType = _nullishCoalesce(providerResponse.headers.get("Content-Type"), () => ( ""));
620
658
  const status = providerResponse.status && providerResponse.status >= 100 ? providerResponse.status : 200;
621
- if (isStream || contentType.includes("text/event-stream")) {
659
+ const upstreamIsSse = contentType.includes("text/event-stream");
660
+ if (upstreamIsSse || isStream && status < 400) {
622
661
  res.writeHead(status, {
623
662
  "Content-Type": "text/event-stream",
624
663
  "Cache-Control": "no-cache",
@@ -628,8 +667,16 @@ async function relayResponse(res, providerResponse, isStream, rewriteModel) {
628
667
  res.end();
629
668
  return null;
630
669
  }
631
- if (rewriteModel) {
632
- await relayStreamWithModelRewrite(res, providerResponse.body, rewriteModel);
670
+ if (rewriteModel || usageTap) {
671
+ let capturedUsage = null;
672
+ await relaySseBody(res, providerResponse.body, {
673
+ rewriteModel,
674
+ onSseEvent: usageTap ? (event) => {
675
+ const raw = usageTap.extractUsage(event);
676
+ if (raw) capturedUsage = raw;
677
+ } : void 0
678
+ });
679
+ if (capturedUsage) usageTap.onUsage(capturedUsage);
633
680
  return null;
634
681
  }
635
682
  const reader = providerResponse.body.getReader();
@@ -651,11 +698,121 @@ async function relayResponse(res, providerResponse, isStream, rewriteModel) {
651
698
  res.end(clientText);
652
699
  return bodyText;
653
700
  }
701
+ async function aggregateAnthropicSseToJsonBody(response, rewriteModel) {
702
+ const text = await response.text();
703
+ const message = {
704
+ type: "message",
705
+ role: "assistant",
706
+ content: [],
707
+ stop_reason: null,
708
+ stop_sequence: null,
709
+ usage: {}
710
+ };
711
+ const blocks = /* @__PURE__ */ new Map();
712
+ for (const raw of text.split("\n")) {
713
+ const line = raw.trim();
714
+ if (!line.startsWith("data:")) continue;
715
+ const payload = line.slice(5).trim();
716
+ if (!payload || payload === "[DONE]") continue;
717
+ let ev;
718
+ try {
719
+ ev = JSON.parse(payload);
720
+ } catch (e9) {
721
+ continue;
722
+ }
723
+ switch (ev["type"]) {
724
+ case "message_start": {
725
+ const m = _nullishCoalesce(ev["message"], () => ( {}));
726
+ if (typeof m["id"] === "string") message["id"] = m["id"];
727
+ if (typeof m["model"] === "string") message["model"] = m["model"];
728
+ if (m["usage"]) message["usage"] = { ...m["usage"] };
729
+ break;
730
+ }
731
+ case "content_block_start": {
732
+ const idx = Number(ev["index"]);
733
+ const cb = _nullishCoalesce(ev["content_block"], () => ( {}));
734
+ blocks.set(idx, {
735
+ type: typeof cb["type"] === "string" ? cb["type"] : "text",
736
+ text: typeof cb["text"] === "string" ? cb["text"] : "",
737
+ id: typeof cb["id"] === "string" ? cb["id"] : void 0,
738
+ name: typeof cb["name"] === "string" ? cb["name"] : void 0,
739
+ inputJson: ""
740
+ });
741
+ break;
742
+ }
743
+ case "content_block_delta": {
744
+ const b = blocks.get(Number(ev["index"]));
745
+ if (!b) break;
746
+ const d = _nullishCoalesce(ev["delta"], () => ( {}));
747
+ if (d["type"] === "text_delta" && typeof d["text"] === "string") b.text += d["text"];
748
+ else if (d["type"] === "input_json_delta" && typeof d["partial_json"] === "string")
749
+ b.inputJson += d["partial_json"];
750
+ else if (d["type"] === "thinking_delta" && typeof d["thinking"] === "string")
751
+ b.text += d["thinking"];
752
+ else if (d["type"] === "signature_delta" && typeof d["signature"] === "string")
753
+ b.signature = (b.signature || "") + d["signature"];
754
+ break;
755
+ }
756
+ case "message_delta": {
757
+ const d = _nullishCoalesce(ev["delta"], () => ( {}));
758
+ if (d["stop_reason"] !== void 0) message["stop_reason"] = d["stop_reason"];
759
+ if (d["stop_sequence"] !== void 0) message["stop_sequence"] = d["stop_sequence"];
760
+ if (ev["usage"])
761
+ message["usage"] = { ...message["usage"], ...ev["usage"] };
762
+ break;
763
+ }
764
+ default:
765
+ break;
766
+ }
767
+ }
768
+ message["content"] = [...blocks.keys()].sort((a, b) => a - b).map((idx) => {
769
+ const blk = blocks.get(idx);
770
+ if (!blk) return void 0;
771
+ if (blk.type === "tool_use") {
772
+ let input = {};
773
+ try {
774
+ input = blk.inputJson ? JSON.parse(blk.inputJson) : {};
775
+ } catch (e10) {
776
+ input = {};
777
+ }
778
+ return { type: "tool_use", id: _nullishCoalesce(blk.id, () => ( "")), name: _nullishCoalesce(blk.name, () => ( "")), input };
779
+ }
780
+ if (blk.type === "thinking") {
781
+ const out = { type: "thinking", thinking: blk.text };
782
+ if (blk.signature) out.signature = blk.signature;
783
+ return out;
784
+ }
785
+ return { type: blk.type || "text", text: blk.text };
786
+ }).filter((b) => b !== void 0);
787
+ if (rewriteModel) message["model"] = rewriteModel;
788
+ return JSON.stringify(message);
789
+ }
654
790
  function writeError(res, status, message) {
655
791
  if (res.headersSent) return;
656
792
  res.writeHead(status, { "Content-Type": "application/json" });
657
793
  res.end(JSON.stringify({ error: { type: "provider_proxy_error", message } }));
658
794
  }
795
+ function writeBoundAccountError(res, error) {
796
+ if (res.headersSent) return;
797
+ const headers = { "Content-Type": "application/json" };
798
+ if (error.status === 429 && error.resumeAt) {
799
+ const resumeMs = Date.parse(error.resumeAt);
800
+ if (Number.isFinite(resumeMs)) {
801
+ headers["Retry-After"] = String(Math.max(1, Math.ceil((resumeMs - Date.now()) / 1e3)));
802
+ }
803
+ }
804
+ res.writeHead(error.status, headers);
805
+ res.end(
806
+ JSON.stringify({
807
+ error: {
808
+ type: "provider_proxy_error",
809
+ code: error.code,
810
+ reason: error.reason,
811
+ message: _chunk25GXJCEZcjs.boundAccountSelectionMessage.call(void 0, error.reason)
812
+ }
813
+ })
814
+ );
815
+ }
659
816
  function resolveApiKey(apiKey) {
660
817
  if (!apiKey) return "";
661
818
  if (apiKey.startsWith("$")) {
@@ -663,7 +820,12 @@ function resolveApiKey(apiKey) {
663
820
  }
664
821
  return apiKey;
665
822
  }
666
- async function resolvePoolBoundKey(deps, providerId, provider, sessionId) {
823
+ async function resolvePoolBoundKey(deps, providerId, provider, sessionId, preferredKeyId, boundKeyFallbackPolicy) {
824
+ if (preferredKeyId) {
825
+ const preferred = await _optionalChain([deps, 'access', _8 => _8.apiKeyPool, 'optionalAccess', _9 => _9.getKeyById, 'call', _10 => _10(providerId, preferredKeyId, sessionId)]);
826
+ if (preferred) return preferred;
827
+ if (boundKeyFallbackPolicy !== "pool") return "";
828
+ }
667
829
  if (deps.apiKeyPool && sessionId) {
668
830
  const poolKey = await deps.apiKeyPool.getKeyForSession(providerId, sessionId);
669
831
  if (poolKey) return poolKey;
@@ -686,7 +848,7 @@ async function buildSubscriptionPlan(res, route, deps, anthropicBody, routeModel
686
848
  resolvedModel = mapped.resolvedModel;
687
849
  scenario = mapped.scenario;
688
850
  }
689
- const sessionKey = _chunkQWBWGODScjs.deriveSubscriptionSessionKey.call(void 0, anthropicBody);
851
+ const sessionKey = _chunkEJLH6NFTcjs.deriveSubscriptionSessionKey.call(void 0, anthropicBody);
690
852
  const plan = buildSubscriptionIterationPlan(profile, route, deps, resolvedModel, isStream, scenario, sessionKey);
691
853
  if (!plan) {
692
854
  writeError(res, 502, "Subscription profile is missing resolveUpstreamUrl");
@@ -695,11 +857,11 @@ async function buildSubscriptionPlan(res, route, deps, anthropicBody, routeModel
695
857
  return plan;
696
858
  }
697
859
  function buildSubscriptionIterationPlan(profile, route, deps, resolvedModel, isStream, scenario, sessionKey) {
698
- const upstreamUrl = _optionalChain([profile, 'access', _8 => _8.resolveUpstreamUrl, 'optionalCall', _9 => _9(resolvedModel, route.subscriptionConfig)]);
860
+ const upstreamUrl = _optionalChain([profile, 'access', _11 => _11.resolveUpstreamUrl, 'optionalCall', _12 => _12(resolvedModel, route.subscriptionConfig)]);
699
861
  if (!upstreamUrl) return null;
700
- const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkKFI44N2Rcjs.SubscriptionAuthSource)(profile)));
862
+ const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkYNJNTCSQcjs.SubscriptionAuthSource)(profile)));
701
863
  const sameFormat = profile.mode === "pass-through" || upstreamUrl.endsWith("/v1/messages");
702
- const overrideNames = _optionalChain([profile, 'access', _10 => _10.resolveProviderTransformerNames, 'optionalCall', _11 => _11(
864
+ const overrideNames = _optionalChain([profile, 'access', _13 => _13.resolveProviderTransformerNames, 'optionalCall', _14 => _14(
703
865
  resolvedModel,
704
866
  route.subscriptionConfig
705
867
  )]);
@@ -718,6 +880,8 @@ function buildSubscriptionIterationPlan(profile, route, deps, resolvedModel, isS
718
880
  return {
719
881
  auth,
720
882
  preferredAccountId: route.preferredAccountId,
883
+ preferredAccountGroup: route.preferredAccountGroup,
884
+ boundAccountFallbackPolicy: route.boundAccountFallbackPolicy,
721
885
  chain,
722
886
  transformerProvider,
723
887
  resolvedModel,
@@ -762,7 +926,7 @@ function buildSubscriptionRequestSummary(anthropicBody) {
762
926
  estimatedInputTokens: Math.ceil(totalChars / 4),
763
927
  // Single source of truth (shared with the dispatcher builder) so both
764
928
  // ingress paths yield identical `matchText` for the same body.
765
- matchText: _chunkQWBWGODScjs.collectMatchText.call(void 0, anthropicBody)
929
+ matchText: _chunkEJLH6NFTcjs.collectMatchText.call(void 0, anthropicBody)
766
930
  };
767
931
  }
768
932
  function collectText(value) {
@@ -792,13 +956,15 @@ async function runPipeline(anthropicBody, plan, reportSelection) {
792
956
  model: resolvedModel,
793
957
  sessionKey: plan.sessionKey,
794
958
  preferredAccountId: plan.preferredAccountId,
959
+ preferredAccountGroup: plan.preferredAccountGroup,
960
+ boundAccountFallbackPolicy: plan.boundAccountFallbackPolicy,
795
961
  reportSelection: (accountId, isActive) => {
796
962
  proxyAccountId = accountId;
797
- _optionalChain([reportSelection, 'optionalCall', _12 => _12(accountId, isActive)]);
963
+ _optionalChain([reportSelection, 'optionalCall', _15 => _15(accountId, isActive)]);
798
964
  }
799
965
  });
800
966
  let rawStatus = null;
801
- const { response } = await _chunkHYN75H6Gcjs.executeProviderCall.call(void 0, {
967
+ const { response } = await _chunkMUHWHQVMcjs.executeProviderCall.call(void 0, {
802
968
  executor,
803
969
  request: anthropicBody,
804
970
  provider: transformerProvider,
@@ -816,7 +982,7 @@ async function runPipeline(anthropicBody, plan, reportSelection) {
816
982
  },
817
983
  fetchFn: (url, headers, body) => {
818
984
  console.info(`[ProviderProxy:anthropic] -> ${url} model=${resolvedModel} stream=${isStream}`);
819
- return _chunkOCEUVQHWcjs.fetchUpstream.call(void 0,
985
+ return _chunkKCVJWJSTcjs.fetchUpstream.call(void 0,
820
986
  url,
821
987
  { method: "POST", headers, body: JSON.stringify(body) },
822
988
  { providerId: proxyProviderId(plan), accountId: proxyAccountId }
@@ -838,10 +1004,12 @@ async function runSubscriptionSameFormatFetch(rawBody, plan, reportSelection, op
838
1004
  model: plan.resolvedModel,
839
1005
  sessionKey: plan.sessionKey,
840
1006
  preferredAccountId: plan.preferredAccountId,
1007
+ preferredAccountGroup: plan.preferredAccountGroup,
1008
+ boundAccountFallbackPolicy: plan.boundAccountFallbackPolicy,
841
1009
  reportSelection: (accountId, isActive, remapped) => {
842
1010
  proxyAccountId = accountId;
843
1011
  remappedModel = remapped;
844
- _optionalChain([reportSelection, 'optionalCall', _13 => _13(accountId, isActive, remapped)]);
1012
+ _optionalChain([reportSelection, 'optionalCall', _16 => _16(accountId, isActive, remapped)]);
845
1013
  }
846
1014
  });
847
1015
  if (plan.isSubscription && plan.transformerProvider.name === "claude") {
@@ -859,7 +1027,7 @@ async function runSubscriptionSameFormatFetch(rawBody, plan, reportSelection, op
859
1027
  console.info(
860
1028
  `[ProviderProxy:anthropic] (subscription same-format) -> ${plan.upstreamUrl} model=${outboundModel} stream=${plan.isStream}`
861
1029
  );
862
- const response = await _chunkOCEUVQHWcjs.fetchUpstream.call(void 0,
1030
+ const response = await _chunkKCVJWJSTcjs.fetchUpstream.call(void 0,
863
1031
  plan.upstreamUrl,
864
1032
  { method: "POST", headers, body: outboundBody },
865
1033
  { providerId: proxyProviderId(plan), accountId: proxyAccountId }
@@ -875,7 +1043,7 @@ function rewriteBodyModel(rawBody, model) {
875
1043
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return rawBody;
876
1044
  parsed.model = model;
877
1045
  return JSON.stringify(parsed);
878
- } catch (e7) {
1046
+ } catch (e11) {
879
1047
  return rawBody;
880
1048
  }
881
1049
  }
@@ -888,7 +1056,7 @@ async function runSubscriptionAttemptWith401Retry(anthropicBody, relayBody, plan
888
1056
  const first = await runOnce();
889
1057
  let result = first;
890
1058
  if (first.rawStatus === 401) {
891
- const refreshed = await _optionalChain([plan, 'access', _14 => _14.auth, 'access', _15 => _15.onUnauthorized, 'optionalCall', _16 => _16(plan.sessionKey)]);
1059
+ const refreshed = await _optionalChain([plan, 'access', _17 => _17.auth, 'access', _18 => _18.onUnauthorized, 'optionalCall', _19 => _19(plan.sessionKey)]);
892
1060
  if (refreshed) {
893
1061
  console.info("[ProviderProxy:anthropic] 401 \u2192 token refreshed; retrying once");
894
1062
  result = await runOnce();
@@ -903,7 +1071,7 @@ async function readBoundedBody(response, max = 2048) {
903
1071
  try {
904
1072
  const text = await response.clone().text();
905
1073
  return text.slice(0, max);
906
- } catch (e8) {
1074
+ } catch (e12) {
907
1075
  return void 0;
908
1076
  }
909
1077
  }
@@ -911,9 +1079,9 @@ async function markSubscriptionHealth(plan, selectedAccountId, result) {
911
1079
  if (!plan.isSubscription || selectedAccountId === void 0) return;
912
1080
  const providerId = plan.transformerProvider.name;
913
1081
  const status = result.rawStatus;
914
- const { resetHeaderSeconds, retryAfterSeconds } = _chunkVQY5W4YWcjs.resolveResetSeconds.call(void 0, providerId, result.response.headers);
1082
+ const { resetHeaderSeconds, retryAfterSeconds } = _chunkYK57NMIFcjs.resolveResetSeconds.call(void 0, providerId, result.response.headers);
915
1083
  const bodyText = status === 403 ? await readBoundedBody(result.response) : void 0;
916
- _chunkVQY5W4YWcjs.getSharedAccountHealth.call(void 0, ).recordUpstreamOutcome(providerId, selectedAccountId, {
1084
+ _chunkYK57NMIFcjs.getSharedAccountHealth.call(void 0, ).recordUpstreamOutcome(providerId, selectedAccountId, {
917
1085
  status,
918
1086
  resetHeaderSeconds,
919
1087
  retryAfterSeconds,
@@ -931,7 +1099,7 @@ function breakerOutcome(rawStatus) {
931
1099
  function recordBreakerOutcome(profile, modelId, rawStatus) {
932
1100
  const outcome = breakerOutcome(rawStatus);
933
1101
  if (outcome === "neutral") return;
934
- _optionalChain([profile, 'optionalAccess', _17 => _17.recordModelOutcome, 'optionalCall', _18 => _18(modelId, outcome === "success")]);
1102
+ _optionalChain([profile, 'optionalAccess', _20 => _20.recordModelOutcome, 'optionalCall', _21 => _21(modelId, outcome === "success")]);
935
1103
  }
936
1104
  async function runSubscriptionAttemptOutcome(anthropicBody, relayBody, plan, options = {}) {
937
1105
  try {
@@ -950,7 +1118,7 @@ function settleOutcome(outcome) {
950
1118
  async function runPipelineWithSubscriptionRetry(anthropicBody, rawBody, initialPlan, route, deps, options = {}) {
951
1119
  const profile = route.subscriptionProfile;
952
1120
  const scenario = initialPlan.scenario;
953
- if (!_optionalChain([profile, 'optionalAccess', _19 => _19.nextFallback]) || scenario === void 0) {
1121
+ if (!_optionalChain([profile, 'optionalAccess', _22 => _22.nextFallback]) || scenario === void 0) {
954
1122
  const loneOutcome = await runSubscriptionAttemptOutcome(anthropicBody, rawBody, initialPlan, options);
955
1123
  recordBreakerOutcome(profile, initialPlan.resolvedModel, outcomeStatus(loneOutcome));
956
1124
  return settleOutcome(loneOutcome);
@@ -1014,7 +1182,7 @@ async function handleAnthropicMessagesByo(res, rawBody, route, deps, options = {
1014
1182
  let anthropicBody;
1015
1183
  try {
1016
1184
  anthropicBody = JSON.parse(rawBody);
1017
- } catch (e9) {
1185
+ } catch (e13) {
1018
1186
  writeError(res, 400, "Invalid JSON in request body");
1019
1187
  return;
1020
1188
  }
@@ -1026,21 +1194,61 @@ async function handleAnthropicMessagesByo(res, rawBody, route, deps, options = {
1026
1194
  if (!plan) return;
1027
1195
  anthropicBody.model = plan.resolvedModel;
1028
1196
  const providerResponse = route.authMode === "subscription" ? await runPipelineWithSubscriptionRetry(anthropicBody, rawBody, plan, route, deps, options) : await runPipelineWithPoolReporting(anthropicBody, rawBody, plan, options);
1029
- const bodyText = await relayResponse(res, providerResponse.response, isStream, route.requestedModel);
1197
+ const upstreamResponse = providerResponse.response;
1198
+ const upstreamSse = (_nullishCoalesce(upstreamResponse.headers.get("content-type"), () => ( ""))).includes(
1199
+ "text/event-stream"
1200
+ );
1201
+ const usageAttribution = {
1202
+ sessionId: route.sessionId,
1203
+ providerId: _nullishCoalesce(route.providerId, () => ( "anthropic")),
1204
+ model: plan.resolvedModel,
1205
+ apiKeyId: _nullishCoalesce(route.apiKeyId, () => ( null)),
1206
+ // request-audit-log: correlate this request's tokens/cost to its audit record.
1207
+ auditResponse: res
1208
+ };
1209
+ const usageRecorder = deps.usageRecorder;
1210
+ let anthropicInputUsage;
1211
+ const usageTap = usageRecorder ? {
1212
+ extractUsage(event) {
1213
+ if (event["type"] === "message_start") {
1214
+ const msg = event["message"];
1215
+ const u = _optionalChain([msg, 'optionalAccess', _23 => _23["usage"]]);
1216
+ if (u) anthropicInputUsage = u;
1217
+ return null;
1218
+ }
1219
+ if (event["type"] === "message_delta") {
1220
+ const outputUsage = event["usage"];
1221
+ if (!outputUsage) return null;
1222
+ return { ...anthropicInputUsage, ...outputUsage };
1223
+ }
1224
+ return null;
1225
+ },
1226
+ onUsage(rawUsage) {
1227
+ recordAnthropicStreamUsage(usageRecorder, rawUsage, usageAttribution);
1228
+ }
1229
+ } : void 0;
1230
+ let bodyText;
1231
+ if (!isStream && upstreamSse) {
1232
+ bodyText = await aggregateAnthropicSseToJsonBody(upstreamResponse, route.requestedModel);
1233
+ res.writeHead(
1234
+ upstreamResponse.status && upstreamResponse.status >= 100 ? upstreamResponse.status : 200,
1235
+ { "Content-Type": "application/json" }
1236
+ );
1237
+ res.end(bodyText);
1238
+ } else {
1239
+ bodyText = await relayResponse(res, upstreamResponse, isStream, route.requestedModel, usageTap);
1240
+ }
1030
1241
  if (bodyText && deps.usageRecorder) {
1031
- recordAnthropicNonStreamUsage(deps.usageRecorder, bodyText, {
1032
- sessionId: route.sessionId,
1033
- providerId: _nullishCoalesce(route.providerId, () => ( "anthropic")),
1034
- model: plan.resolvedModel,
1035
- apiKeyId: _nullishCoalesce(route.apiKeyId, () => ( null)),
1036
- // request-audit-log: correlate this request's tokens/cost to its audit record.
1037
- auditResponse: res
1038
- });
1242
+ recordAnthropicNonStreamUsage(deps.usageRecorder, bodyText, usageAttribution);
1039
1243
  }
1040
1244
  } catch (err) {
1245
+ if (_chunk25GXJCEZcjs.isBoundAccountSelectionError.call(void 0, err)) {
1246
+ writeBoundAccountError(res, err);
1247
+ return;
1248
+ }
1041
1249
  const errMsg = _chunkSVNDB62Dcjs.serializeError.call(void 0, err);
1042
1250
  console.error("[ProviderProxy:anthropic] Pipeline error:", errMsg);
1043
- writeError(res, 502, errMsg);
1251
+ writeError(res, _chunk6QQG7YG3cjs.isAccountAllowanceExhaustedError.call(void 0, err) ? 429 : 502, errMsg);
1044
1252
  }
1045
1253
  }
1046
1254
  async function buildByoPlan(res, route, deps, resolvedModel, isStream) {
@@ -1054,7 +1262,14 @@ async function buildByoPlan(res, route, deps, resolvedModel, isStream) {
1054
1262
  writeError(res, 502, `Provider not found: ${providerId}`);
1055
1263
  return null;
1056
1264
  }
1057
- const apiKey = await resolvePoolBoundKey(deps, providerId, provider, route.sessionId);
1265
+ const apiKey = await resolvePoolBoundKey(
1266
+ deps,
1267
+ providerId,
1268
+ provider,
1269
+ route.sessionId,
1270
+ route.preferredKeyId,
1271
+ route.boundKeyFallbackPolicy
1272
+ );
1058
1273
  if (!apiKey) {
1059
1274
  writeError(res, 502, "API key not configured");
1060
1275
  return null;
@@ -1087,7 +1302,7 @@ async function buildByoPlan(res, route, deps, resolvedModel, isStream) {
1087
1302
  isSubscription: false,
1088
1303
  provider,
1089
1304
  apiKey,
1090
- extendedContextEnabled: _nullishCoalesce(_optionalChain([route, 'access', _20 => _20.anthropicSdkHints, 'optionalAccess', _21 => _21.extendedContext, 'optionalAccess', _22 => _22.enabled]), () => ( false))
1305
+ extendedContextEnabled: _nullishCoalesce(_optionalChain([route, 'access', _24 => _24.anthropicSdkHints, 'optionalAccess', _25 => _25.extendedContext, 'optionalAccess', _26 => _26.enabled]), () => ( false))
1091
1306
  };
1092
1307
  }
1093
1308
  async function runSameFormatFetch(bodyToSend, plan, options, keyOverride) {
@@ -1097,7 +1312,7 @@ async function runSameFormatFetch(bodyToSend, plan, options, keyOverride) {
1097
1312
  }
1098
1313
  const effectiveKey = _nullishCoalesce(_nullishCoalesce(keyOverride, () => ( apiKey)), () => ( ""));
1099
1314
  const headers = _chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, effectiveKey);
1100
- const callerBeta = _optionalChain([options, 'access', _23 => _23.callerAnthropicBeta, 'optionalAccess', _24 => _24.trim, 'call', _25 => _25()]);
1315
+ const callerBeta = _optionalChain([options, 'access', _27 => _27.callerAnthropicBeta, 'optionalAccess', _28 => _28.trim, 'call', _29 => _29()]);
1101
1316
  if (callerBeta) {
1102
1317
  const existing = _nullishCoalesce(headers["anthropic-beta"], () => ( headers["Anthropic-Beta"]));
1103
1318
  const parts = new Set(
@@ -1111,7 +1326,7 @@ async function runSameFormatFetch(bodyToSend, plan, options, keyOverride) {
1111
1326
  _chunkGBHYAGX3cjs.injectExtendedContextBeta.call(void 0, headers, resolvedModel, _nullishCoalesce(extendedContextEnabled, () => ( false)));
1112
1327
  const url = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: resolvedModel, stream: isStream });
1113
1328
  console.info(`[ProviderProxy:anthropic] (same-format) -> ${url} model=${resolvedModel} stream=${isStream}`);
1114
- const response = await _chunkOCEUVQHWcjs.fetchUpstream.call(void 0,
1329
+ const response = await _chunkKCVJWJSTcjs.fetchUpstream.call(void 0,
1115
1330
  url,
1116
1331
  { method: "POST", headers, body: bodyToSend },
1117
1332
  { providerId: "byo" }
@@ -1123,7 +1338,7 @@ function resolveSameFormatBody(anthropicBody, rawBody, plan) {
1123
1338
  try {
1124
1339
  const m = JSON.parse(rawBody).model;
1125
1340
  originalModel = typeof m === "string" ? m : void 0;
1126
- } catch (e10) {
1341
+ } catch (e14) {
1127
1342
  originalModel = void 0;
1128
1343
  }
1129
1344
  return plan.resolvedModel !== originalModel ? JSON.stringify(anthropicBody) : rawBody;
@@ -1132,8 +1347,8 @@ async function runPipelineWithPoolReporting(anthropicBody, rawBody, plan, option
1132
1347
  const sameFormatBody = plan.sameFormat ? resolveSameFormatBody(anthropicBody, rawBody, plan) : rawBody;
1133
1348
  const runOnce = (keyOverride) => plan.sameFormat ? runSameFormatFetch(sameFormatBody, plan, options, keyOverride) : runPipeline(anthropicBody, plan);
1134
1349
  const first = await runOnce();
1135
- const outcome = await _optionalChain([plan, 'access', _26 => _26.auth, 'access', _27 => _27.onResult, 'optionalCall', _28 => _28(first.rawStatus)]);
1136
- if (_optionalChain([outcome, 'optionalAccess', _29 => _29.rebound])) {
1350
+ const outcome = await _optionalChain([plan, 'access', _30 => _30.auth, 'access', _31 => _31.onResult, 'optionalCall', _32 => _32(first.rawStatus)]);
1351
+ if (_optionalChain([outcome, 'optionalAccess', _33 => _33.rebound])) {
1137
1352
  console.info(
1138
1353
  "[ProviderProxy:anthropic] pool re-bound key after status",
1139
1354
  first.rawStatus,
@@ -1167,11 +1382,31 @@ async function handleAnthropicMessagesRequest(req, res, route, deps) {
1167
1382
  writeError(res, 502, "Anthropic route is missing a providerId");
1168
1383
  return;
1169
1384
  }
1385
+ let delegatedApiKey = hints.apiKey;
1386
+ if (route.authMode === "byo" && route.providerId) {
1387
+ const provider = await deps.llmConfig.getProvider(route.providerId);
1388
+ if (!provider) {
1389
+ writeError(res, 502, `Provider not found: ${route.providerId}`);
1390
+ return;
1391
+ }
1392
+ delegatedApiKey = await resolvePoolBoundKey(
1393
+ deps,
1394
+ route.providerId,
1395
+ provider,
1396
+ route.sessionId,
1397
+ route.preferredKeyId,
1398
+ route.boundKeyFallbackPolicy
1399
+ );
1400
+ if (!delegatedApiKey) {
1401
+ writeError(res, 502, "API key not configured");
1402
+ return;
1403
+ }
1404
+ }
1170
1405
  const handler = handlerFactory({
1171
1406
  llmConfig: deps.llmConfig,
1172
1407
  providerId: _nullishCoalesce(route.providerId, () => ( "")),
1173
1408
  model: route.model,
1174
- apiKey: hints.apiKey,
1409
+ apiKey: delegatedApiKey,
1175
1410
  backgroundTaskModel: route.backgroundTaskModel,
1176
1411
  isOfficialProvider: hints.isOfficialProvider,
1177
1412
  thinkingLevel: hints.thinkingLevel,
@@ -1180,6 +1415,11 @@ async function handleAnthropicMessagesRequest(req, res, route, deps) {
1180
1415
  passThroughAuthToken: _nullishCoalesce(hints.passThroughAuthToken, () => ( null)),
1181
1416
  resolvePassThroughAuthToken: _nullishCoalesce(hints.resolvePassThroughAuthToken, () => ( null)),
1182
1417
  subscriptionProfile: _nullishCoalesce(hints.subscriptionProfile, () => ( null)),
1418
+ preferredAccountId: hints.preferredAccountId,
1419
+ preferredAccountGroup: hints.preferredAccountGroup,
1420
+ boundAccountFallbackPolicy: hints.boundAccountFallbackPolicy,
1421
+ preferredKeyId: route.preferredKeyId,
1422
+ boundKeyFallbackPolicy: route.boundKeyFallbackPolicy,
1183
1423
  maxConcurrency: hints.maxConcurrency,
1184
1424
  webSearchService: _nullishCoalesce(hints.webSearchService, () => ( null)),
1185
1425
  onRetry: hints.onRetry,
@@ -1206,24 +1446,37 @@ function readGeminiUsage(usage) {
1206
1446
  reasoningTokens
1207
1447
  };
1208
1448
  }
1449
+ function emitGeminiUsageRecord(recorder, rawUsageMetadata, attribution) {
1450
+ const tapped = readGeminiUsage(rawUsageMetadata);
1451
+ if (!tapped) return;
1452
+ recorder.record({
1453
+ messageId: null,
1454
+ parentMessageId: null,
1455
+ sessionId: attribution.sessionId,
1456
+ providerId: attribution.providerId,
1457
+ model: attribution.model,
1458
+ apiKeyId: attribution.apiKeyId,
1459
+ auditResponse: attribution.auditResponse,
1460
+ engineOrigin: "codex-ingress",
1461
+ usage: tapped,
1462
+ rawUsage: rawUsageMetadata
1463
+ });
1464
+ }
1209
1465
  function recordGeminiNonStreamUsage(recorder, bodyText, attribution) {
1210
1466
  try {
1211
1467
  const parsed = JSON.parse(bodyText);
1212
- const tapped = readGeminiUsage(parsed.usageMetadata);
1213
- if (!tapped) return;
1214
- recorder.record({
1215
- messageId: null,
1216
- parentMessageId: null,
1217
- sessionId: attribution.sessionId,
1218
- providerId: attribution.providerId,
1219
- model: attribution.model,
1220
- apiKeyId: attribution.apiKeyId,
1221
- auditResponse: attribution.auditResponse,
1222
- engineOrigin: "codex-ingress",
1223
- usage: tapped,
1224
- rawUsage: parsed.usageMetadata
1225
- });
1226
- } catch (e11) {
1468
+ emitGeminiUsageRecord(
1469
+ recorder,
1470
+ parsed.usageMetadata,
1471
+ attribution
1472
+ );
1473
+ } catch (e15) {
1474
+ }
1475
+ }
1476
+ function recordGeminiStreamUsage(recorder, rawUsageMetadata, attribution) {
1477
+ try {
1478
+ emitGeminiUsageRecord(recorder, rawUsageMetadata, attribution);
1479
+ } catch (e16) {
1227
1480
  }
1228
1481
  }
1229
1482
 
@@ -1232,14 +1485,14 @@ var GENERATE_CONTENT_ACTION = ":generateContent";
1232
1485
  var STREAM_GENERATE_CONTENT_ACTION = ":streamGenerateContent";
1233
1486
  function isGeminiGenerateContentRequest(method, url) {
1234
1487
  if (method !== "POST" || !url) return false;
1235
- const path = _nullishCoalesce(_optionalChain([url, 'access', _30 => _30.split, 'call', _31 => _31("?"), 'access', _32 => _32[0], 'optionalAccess', _33 => _33.replace, 'call', _34 => _34(/\/+$/, "")]), () => ( ""));
1488
+ const path = _nullishCoalesce(_optionalChain([url, 'access', _34 => _34.split, 'call', _35 => _35("?"), 'access', _36 => _36[0], 'optionalAccess', _37 => _37.replace, 'call', _38 => _38(/\/+$/, "")]), () => ( ""));
1236
1489
  const lastSegment = _nullishCoalesce(path.split("/").pop(), () => ( ""));
1237
1490
  return lastSegment.includes(STREAM_GENERATE_CONTENT_ACTION) || lastSegment.includes(GENERATE_CONTENT_ACTION);
1238
1491
  }
1239
1492
  function isGeminiStreamRequest(url) {
1240
1493
  if (!url) return false;
1241
1494
  const [path, query = ""] = url.split("?");
1242
- const lastSegment = _nullishCoalesce((_nullishCoalesce(_optionalChain([path, 'optionalAccess', _35 => _35.replace, 'call', _36 => _36(/\/+$/, "")]), () => ( ""))).split("/").pop(), () => ( ""));
1495
+ const lastSegment = _nullishCoalesce((_nullishCoalesce(_optionalChain([path, 'optionalAccess', _39 => _39.replace, 'call', _40 => _40(/\/+$/, "")]), () => ( ""))).split("/").pop(), () => ( ""));
1243
1496
  if (lastSegment.includes(STREAM_GENERATE_CONTENT_ACTION)) return true;
1244
1497
  return /(^|&)alt=sse(&|$)/.test(query);
1245
1498
  }
@@ -1247,7 +1500,7 @@ async function handleGeminiGenerateContentRequest(res, rawBody, url, route, deps
1247
1500
  let geminiBody;
1248
1501
  try {
1249
1502
  geminiBody = JSON.parse(rawBody);
1250
- } catch (e12) {
1503
+ } catch (e17) {
1251
1504
  writeError(res, 400, "Invalid JSON in request body");
1252
1505
  return;
1253
1506
  }
@@ -1263,16 +1516,32 @@ async function handleGeminiGenerateContentRequest(res, rawBody, url, route, deps
1263
1516
  const plan = await buildByoPlan2(res, route, deps, resolvedModel, isStream);
1264
1517
  if (!plan) return;
1265
1518
  const providerResponse = await runPipelineWithPoolReporting2(geminiBody, plan);
1266
- const bodyText = await relayResponse(res, providerResponse.response, isStream);
1519
+ const usageAttribution = {
1520
+ sessionId: route.sessionId,
1521
+ providerId: _nullishCoalesce(route.providerId, () => ( "gemini")),
1522
+ model: resolvedModel,
1523
+ apiKeyId: _nullishCoalesce(route.apiKeyId, () => ( null)),
1524
+ // request-audit-log: correlate this request's tokens/cost to its audit record.
1525
+ auditResponse: res
1526
+ };
1527
+ const usageRecorder = deps.usageRecorder;
1528
+ const usageTap = usageRecorder ? {
1529
+ extractUsage(event) {
1530
+ return _nullishCoalesce(event["usageMetadata"], () => ( null));
1531
+ },
1532
+ onUsage(rawUsage) {
1533
+ recordGeminiStreamUsage(usageRecorder, rawUsage, usageAttribution);
1534
+ }
1535
+ } : void 0;
1536
+ const bodyText = await relayResponse(
1537
+ res,
1538
+ providerResponse.response,
1539
+ isStream,
1540
+ void 0,
1541
+ usageTap
1542
+ );
1267
1543
  if (bodyText && deps.usageRecorder) {
1268
- recordGeminiNonStreamUsage(deps.usageRecorder, bodyText, {
1269
- sessionId: route.sessionId,
1270
- providerId: _nullishCoalesce(route.providerId, () => ( "gemini")),
1271
- model: resolvedModel,
1272
- apiKeyId: _nullishCoalesce(route.apiKeyId, () => ( null)),
1273
- // request-audit-log: correlate this request's tokens/cost to its audit record.
1274
- auditResponse: res
1275
- });
1544
+ recordGeminiNonStreamUsage(deps.usageRecorder, bodyText, usageAttribution);
1276
1545
  }
1277
1546
  } catch (err) {
1278
1547
  const errMsg = _chunkSVNDB62Dcjs.serializeError.call(void 0, err);
@@ -1291,7 +1560,14 @@ async function buildByoPlan2(res, route, deps, resolvedModel, isStream) {
1291
1560
  writeError(res, 502, `Provider not found: ${providerId}`);
1292
1561
  return null;
1293
1562
  }
1294
- const apiKey = await resolvePoolBoundKey(deps, providerId, provider, route.sessionId);
1563
+ const apiKey = await resolvePoolBoundKey(
1564
+ deps,
1565
+ providerId,
1566
+ provider,
1567
+ route.sessionId,
1568
+ route.preferredKeyId,
1569
+ route.boundKeyFallbackPolicy
1570
+ );
1295
1571
  if (!apiKey) {
1296
1572
  writeError(res, 502, "API key not configured");
1297
1573
  return null;
@@ -1328,7 +1604,7 @@ async function runPipeline2(geminiBody, plan) {
1328
1604
  const authHeaders = {};
1329
1605
  await auth.applyHeaders(authHeaders, { upstreamUrl, model: resolvedModel });
1330
1606
  let rawStatus = null;
1331
- const { response } = await _chunkHYN75H6Gcjs.executeProviderCall.call(void 0, {
1607
+ const { response } = await _chunkMUHWHQVMcjs.executeProviderCall.call(void 0, {
1332
1608
  executor,
1333
1609
  request: geminiBody,
1334
1610
  provider: transformerProvider,
@@ -1346,7 +1622,7 @@ async function runPipeline2(geminiBody, plan) {
1346
1622
  },
1347
1623
  fetchFn: (url, headers, body) => {
1348
1624
  console.log(`[ProviderProxy:gemini] -> ${url} model=${resolvedModel} stream=${isStream}`);
1349
- return _chunkOCEUVQHWcjs.fetchUpstream.call(void 0,
1625
+ return _chunkKCVJWJSTcjs.fetchUpstream.call(void 0,
1350
1626
  url,
1351
1627
  { method: "POST", headers, body: JSON.stringify(body) },
1352
1628
  { providerId: "byo" }
@@ -1361,8 +1637,8 @@ async function runPipeline2(geminiBody, plan) {
1361
1637
  }
1362
1638
  async function runPipelineWithPoolReporting2(geminiBody, plan) {
1363
1639
  const first = await runPipeline2(geminiBody, plan);
1364
- const outcome = await _optionalChain([plan, 'access', _37 => _37.auth, 'access', _38 => _38.onResult, 'optionalCall', _39 => _39(first.rawStatus)]);
1365
- if (_optionalChain([outcome, 'optionalAccess', _40 => _40.rebound])) {
1640
+ const outcome = await _optionalChain([plan, 'access', _41 => _41.auth, 'access', _42 => _42.onResult, 'optionalCall', _43 => _43(first.rawStatus)]);
1641
+ if (_optionalChain([outcome, 'optionalAccess', _44 => _44.rebound])) {
1366
1642
  console.log(
1367
1643
  "[ProviderProxy:gemini] pool re-bound key after status",
1368
1644
  first.rawStatus,
@@ -1391,31 +1667,44 @@ function readChatCompletionsUsage(usage) {
1391
1667
  reasoningTokens
1392
1668
  };
1393
1669
  }
1670
+ function emitChatCompletionsUsageRecord(recorder, rawUsage, attribution) {
1671
+ const tapped = readChatCompletionsUsage(rawUsage);
1672
+ if (!tapped) return;
1673
+ recorder.record({
1674
+ messageId: null,
1675
+ parentMessageId: null,
1676
+ sessionId: attribution.sessionId,
1677
+ providerId: attribution.providerId,
1678
+ model: attribution.model,
1679
+ apiKeyId: attribution.apiKeyId,
1680
+ auditResponse: attribution.auditResponse,
1681
+ engineOrigin: "codex-ingress",
1682
+ usage: tapped,
1683
+ rawUsage
1684
+ });
1685
+ }
1394
1686
  function recordChatCompletionsNonStreamUsage(recorder, bodyText, attribution) {
1395
1687
  try {
1396
1688
  const parsed = JSON.parse(bodyText);
1397
- const tapped = readChatCompletionsUsage(parsed.usage);
1398
- if (!tapped) return;
1399
- recorder.record({
1400
- messageId: null,
1401
- parentMessageId: null,
1402
- sessionId: attribution.sessionId,
1403
- providerId: attribution.providerId,
1404
- model: attribution.model,
1405
- apiKeyId: attribution.apiKeyId,
1406
- auditResponse: attribution.auditResponse,
1407
- engineOrigin: "codex-ingress",
1408
- usage: tapped,
1409
- rawUsage: parsed.usage
1410
- });
1411
- } catch (e13) {
1689
+ emitChatCompletionsUsageRecord(
1690
+ recorder,
1691
+ parsed.usage,
1692
+ attribution
1693
+ );
1694
+ } catch (e18) {
1695
+ }
1696
+ }
1697
+ function recordChatCompletionsStreamUsage(recorder, rawUsage, attribution) {
1698
+ try {
1699
+ emitChatCompletionsUsageRecord(recorder, rawUsage, attribution);
1700
+ } catch (e19) {
1412
1701
  }
1413
1702
  }
1414
1703
 
1415
1704
  // src/provider-proxy/ingress/openaiChatIngress.ts
1416
1705
  function isOpenAIChatRequest(method, url) {
1417
1706
  if (method !== "POST" || !url) return false;
1418
- const path = _nullishCoalesce(_optionalChain([url, 'access', _41 => _41.split, 'call', _42 => _42("?"), 'access', _43 => _43[0], 'optionalAccess', _44 => _44.replace, 'call', _45 => _45(/\/+$/, "")]), () => ( ""));
1707
+ const path = _nullishCoalesce(_optionalChain([url, 'access', _45 => _45.split, 'call', _46 => _46("?"), 'access', _47 => _47[0], 'optionalAccess', _48 => _48.replace, 'call', _49 => _49(/\/+$/, "")]), () => ( ""));
1419
1708
  return path.endsWith("/chat/completions");
1420
1709
  }
1421
1710
  var CHAT_BRIDGE_SUBSCRIPTION_PROVIDERS = /* @__PURE__ */ new Set(["claude"]);
@@ -1424,7 +1713,7 @@ async function handleOpenAIChatRequest(res, rawBody, route, deps) {
1424
1713
  let chatBody;
1425
1714
  try {
1426
1715
  chatBody = JSON.parse(rawBody);
1427
- } catch (e14) {
1716
+ } catch (e20) {
1428
1717
  writeError(res, 400, "Invalid JSON in request body");
1429
1718
  return;
1430
1719
  }
@@ -1435,21 +1724,41 @@ async function handleOpenAIChatRequest(res, rawBody, route, deps) {
1435
1724
  const plan = route.authMode === "subscription" ? await buildSubscriptionPlan2(res, route, deps, resolvedModel, isStream) : await buildByoPlan3(res, route, deps, resolvedModel, isStream);
1436
1725
  if (!plan) return;
1437
1726
  const providerResponse = plan.isSubscription ? await runPipelineWithSubscriptionRetry2(chatBody, plan) : await runPipelineWithPoolReporting3(chatBody, plan);
1438
- const bodyText = await relayResponse(res, providerResponse.response, isStream);
1727
+ const usageAttribution = {
1728
+ sessionId: route.sessionId,
1729
+ providerId: _nullishCoalesce(route.providerId, () => ( "openai")),
1730
+ model: resolvedModel,
1731
+ apiKeyId: _nullishCoalesce(route.apiKeyId, () => ( null)),
1732
+ // request-audit-log: correlate this request's tokens/cost to its audit record.
1733
+ auditResponse: res
1734
+ };
1735
+ const usageRecorder = deps.usageRecorder;
1736
+ const usageTap = usageRecorder ? {
1737
+ extractUsage(event) {
1738
+ return _nullishCoalesce(event["usage"], () => ( null));
1739
+ },
1740
+ onUsage(rawUsage) {
1741
+ recordChatCompletionsStreamUsage(usageRecorder, rawUsage, usageAttribution);
1742
+ }
1743
+ } : void 0;
1744
+ const bodyText = await relayResponse(
1745
+ res,
1746
+ providerResponse.response,
1747
+ isStream,
1748
+ void 0,
1749
+ usageTap
1750
+ );
1439
1751
  if (bodyText && deps.usageRecorder) {
1440
- recordChatCompletionsNonStreamUsage(deps.usageRecorder, bodyText, {
1441
- sessionId: route.sessionId,
1442
- providerId: _nullishCoalesce(route.providerId, () => ( "openai")),
1443
- model: resolvedModel,
1444
- apiKeyId: _nullishCoalesce(route.apiKeyId, () => ( null)),
1445
- // request-audit-log: correlate this request's tokens/cost to its audit record.
1446
- auditResponse: res
1447
- });
1752
+ recordChatCompletionsNonStreamUsage(deps.usageRecorder, bodyText, usageAttribution);
1448
1753
  }
1449
1754
  } catch (err) {
1755
+ if (_chunk25GXJCEZcjs.isBoundAccountSelectionError.call(void 0, err)) {
1756
+ writeBoundAccountError(res, err);
1757
+ return;
1758
+ }
1450
1759
  const errMsg = _chunkSVNDB62Dcjs.serializeError.call(void 0, err);
1451
1760
  console.error("[ProviderProxy:chat] Pipeline error:", errMsg);
1452
- writeError(res, 502, errMsg);
1761
+ writeError(res, _chunk6QQG7YG3cjs.isAccountAllowanceExhaustedError.call(void 0, err) ? 429 : 502, errMsg);
1453
1762
  }
1454
1763
  }
1455
1764
  async function buildByoPlan3(res, route, deps, resolvedModel, isStream) {
@@ -1463,7 +1772,14 @@ async function buildByoPlan3(res, route, deps, resolvedModel, isStream) {
1463
1772
  writeError(res, 502, `Provider not found: ${providerId}`);
1464
1773
  return null;
1465
1774
  }
1466
- const apiKey = await resolvePoolBoundKey(deps, providerId, provider, route.sessionId);
1775
+ const apiKey = await resolvePoolBoundKey(
1776
+ deps,
1777
+ providerId,
1778
+ provider,
1779
+ route.sessionId,
1780
+ route.preferredKeyId,
1781
+ route.boundKeyFallbackPolicy
1782
+ );
1467
1783
  if (!apiKey) {
1468
1784
  writeError(res, 502, "API key not configured");
1469
1785
  return null;
@@ -1510,12 +1826,12 @@ async function buildSubscriptionPlan2(res, route, deps, resolvedModel, isStream)
1510
1826
  );
1511
1827
  return null;
1512
1828
  }
1513
- const upstreamUrl = _optionalChain([profile, 'access', _46 => _46.resolveUpstreamUrl, 'optionalCall', _47 => _47(resolvedModel)]);
1829
+ const upstreamUrl = _optionalChain([profile, 'access', _50 => _50.resolveUpstreamUrl, 'optionalCall', _51 => _51(resolvedModel)]);
1514
1830
  if (!upstreamUrl) {
1515
1831
  writeError(res, 502, "Subscription profile is missing resolveUpstreamUrl");
1516
1832
  return null;
1517
1833
  }
1518
- const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkKFI44N2Rcjs.SubscriptionAuthSource)(profile)));
1834
+ const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkYNJNTCSQcjs.SubscriptionAuthSource)(profile)));
1519
1835
  const chain = _chunkNYUNU75Acjs.resolveSubscriptionChain.call(void 0,
1520
1836
  profile,
1521
1837
  deps.llmConfig.getTransformerService(),
@@ -1529,6 +1845,9 @@ async function buildSubscriptionPlan2(res, route, deps, resolvedModel, isStream)
1529
1845
  };
1530
1846
  return {
1531
1847
  auth,
1848
+ preferredAccountId: route.preferredAccountId,
1849
+ preferredAccountGroup: route.preferredAccountGroup,
1850
+ boundAccountFallbackPolicy: route.boundAccountFallbackPolicy,
1532
1851
  chain,
1533
1852
  transformerProvider,
1534
1853
  resolvedModel,
@@ -1547,12 +1866,15 @@ async function runPipeline3(chatBody, plan) {
1547
1866
  await auth.applyHeaders(authHeaders, {
1548
1867
  upstreamUrl,
1549
1868
  model: resolvedModel,
1869
+ preferredAccountId: plan.preferredAccountId,
1870
+ preferredAccountGroup: plan.preferredAccountGroup,
1871
+ boundAccountFallbackPolicy: plan.boundAccountFallbackPolicy,
1550
1872
  reportSelection: (accountId) => {
1551
1873
  proxyAccountId = accountId;
1552
1874
  }
1553
1875
  });
1554
1876
  let rawStatus = null;
1555
- const { response } = await _chunkHYN75H6Gcjs.executeProviderCall.call(void 0, {
1877
+ const { response } = await _chunkMUHWHQVMcjs.executeProviderCall.call(void 0, {
1556
1878
  executor,
1557
1879
  request: chatBody,
1558
1880
  provider: transformerProvider,
@@ -1569,7 +1891,7 @@ async function runPipeline3(chatBody, plan) {
1569
1891
  },
1570
1892
  fetchFn: (url, headers, body) => {
1571
1893
  console.log(`[ProviderProxy:chat] -> ${url} model=${resolvedModel} stream=${isStream}`);
1572
- return _chunkOCEUVQHWcjs.fetchUpstream.call(void 0,
1894
+ return _chunkKCVJWJSTcjs.fetchUpstream.call(void 0,
1573
1895
  url,
1574
1896
  { method: "POST", headers, body: JSON.stringify(body) },
1575
1897
  { providerId: plan.proxyProviderId, accountId: proxyAccountId }
@@ -1584,8 +1906,8 @@ async function runPipeline3(chatBody, plan) {
1584
1906
  }
1585
1907
  async function runPipelineWithPoolReporting3(chatBody, plan) {
1586
1908
  const first = await runPipeline3(chatBody, plan);
1587
- const outcome = await _optionalChain([plan, 'access', _48 => _48.auth, 'access', _49 => _49.onResult, 'optionalCall', _50 => _50(first.rawStatus)]);
1588
- if (_optionalChain([outcome, 'optionalAccess', _51 => _51.rebound])) {
1909
+ const outcome = await _optionalChain([plan, 'access', _52 => _52.auth, 'access', _53 => _53.onResult, 'optionalCall', _54 => _54(first.rawStatus)]);
1910
+ if (_optionalChain([outcome, 'optionalAccess', _55 => _55.rebound])) {
1589
1911
  console.log(
1590
1912
  "[ProviderProxy:chat] pool re-bound key after status",
1591
1913
  first.rawStatus,
@@ -1598,7 +1920,7 @@ async function runPipelineWithPoolReporting3(chatBody, plan) {
1598
1920
  async function runPipelineWithSubscriptionRetry2(chatBody, plan) {
1599
1921
  const first = await runPipeline3(chatBody, plan);
1600
1922
  if (first.rawStatus !== 401) return first;
1601
- const refreshed = await _optionalChain([plan, 'access', _52 => _52.auth, 'access', _53 => _53.onUnauthorized, 'optionalCall', _54 => _54()]);
1923
+ const refreshed = await _optionalChain([plan, 'access', _56 => _56.auth, 'access', _57 => _57.onUnauthorized, 'optionalCall', _58 => _58()]);
1602
1924
  if (!refreshed) {
1603
1925
  console.warn("[ProviderProxy:chat] 401 not recoverable (onUnauthorized returned false)");
1604
1926
  return first;
@@ -1625,63 +1947,107 @@ function readResponsesUsage(usage) {
1625
1947
  reasoningTokens
1626
1948
  };
1627
1949
  }
1950
+ function emitResponsesUsageRecord(recorder, rawUsage, attribution) {
1951
+ const tapped = readResponsesUsage(rawUsage);
1952
+ if (!tapped) return;
1953
+ recorder.record({
1954
+ messageId: null,
1955
+ parentMessageId: null,
1956
+ sessionId: attribution.sessionId,
1957
+ providerId: attribution.providerId,
1958
+ model: attribution.model,
1959
+ apiKeyId: attribution.apiKeyId,
1960
+ auditResponse: attribution.auditResponse,
1961
+ engineOrigin: "codex-ingress",
1962
+ usage: tapped,
1963
+ rawUsage
1964
+ });
1965
+ }
1628
1966
  function recordResponsesNonStreamUsage(recorder, bodyText, attribution) {
1629
1967
  try {
1630
1968
  const parsed = JSON.parse(bodyText);
1631
- const tapped = readResponsesUsage(parsed.usage);
1632
- if (!tapped) return;
1633
- recorder.record({
1634
- messageId: null,
1635
- parentMessageId: null,
1636
- sessionId: attribution.sessionId,
1637
- providerId: attribution.providerId,
1638
- model: attribution.model,
1639
- apiKeyId: attribution.apiKeyId,
1640
- auditResponse: attribution.auditResponse,
1641
- engineOrigin: "codex-ingress",
1642
- usage: tapped,
1643
- rawUsage: parsed.usage
1644
- });
1645
- } catch (e15) {
1969
+ emitResponsesUsageRecord(
1970
+ recorder,
1971
+ parsed.usage,
1972
+ attribution
1973
+ );
1974
+ } catch (e21) {
1975
+ }
1976
+ }
1977
+ function recordResponsesStreamUsage(recorder, rawUsage, attribution) {
1978
+ try {
1979
+ emitResponsesUsageRecord(recorder, rawUsage, attribution);
1980
+ } catch (e22) {
1646
1981
  }
1647
1982
  }
1648
1983
 
1649
1984
  // src/provider-proxy/ingress/openaiResponsesIngress.ts
1650
1985
  function isOpenAIResponsesRequest(method, url) {
1651
1986
  if (method !== "POST" || !url) return false;
1652
- const path = _nullishCoalesce(_optionalChain([url, 'access', _55 => _55.split, 'call', _56 => _56("?"), 'access', _57 => _57[0], 'optionalAccess', _58 => _58.replace, 'call', _59 => _59(/\/+$/, "")]), () => ( ""));
1987
+ const path = _nullishCoalesce(_optionalChain([url, 'access', _59 => _59.split, 'call', _60 => _60("?"), 'access', _61 => _61[0], 'optionalAccess', _62 => _62.replace, 'call', _63 => _63(/\/+$/, "")]), () => ( ""));
1653
1988
  return path.endsWith("/responses");
1654
1989
  }
1655
- async function handleOpenAIResponsesRequest(res, rawBody, route, deps) {
1990
+ async function handleOpenAIResponsesRequest(res, rawBody, route, deps, requestHeaders = {}) {
1656
1991
  let responsesBody;
1657
1992
  try {
1658
1993
  responsesBody = JSON.parse(rawBody);
1659
- } catch (e16) {
1994
+ } catch (e23) {
1660
1995
  writeError(res, 400, "Invalid JSON in request body");
1661
1996
  return;
1662
1997
  }
1663
1998
  const isStream = responsesBody.stream === true;
1999
+ const derivedSession = _chunkEJLH6NFTcjs.deriveGatewaySessionKey.call(void 0, responsesBody, requestHeaders, {
2000
+ endpoint: "responses",
2001
+ // A verified outbound key is the strongest route-local fallback. Resident
2002
+ // proxy callers without one still get a stable run/session bucket; the
2003
+ // final `anonymous` fallback is handled inside the shared utility.
2004
+ fallbackKey: _nullishCoalesce(_nullishCoalesce(route.apiKeyId, () => ( route.sessionId)), () => ( void 0))
2005
+ });
2006
+ const sessionKey = derivedSession.key;
1664
2007
  const resolvedModel = route.model;
1665
2008
  responsesBody.model = resolvedModel;
1666
2009
  try {
1667
- const plan = route.authMode === "subscription" ? await buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream) : await buildByoPlan4(res, route, deps, resolvedModel, isStream);
2010
+ const plan = route.authMode === "subscription" ? await buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream, sessionKey) : await buildByoPlan4(res, route, deps, resolvedModel, isStream);
1668
2011
  if (!plan) return;
1669
2012
  const providerResponse = route.authMode === "subscription" ? await runPipelineWithSubscriptionRetry3(responsesBody, plan) : await runPipelineWithPoolReporting4(responsesBody, plan);
1670
- const bodyText = await relayResponse(res, providerResponse.response, isStream, route.requestedModel);
2013
+ const usageAttribution = {
2014
+ sessionId: route.sessionId,
2015
+ providerId: _nullishCoalesce(route.providerId, () => ( "codex")),
2016
+ model: resolvedModel,
2017
+ apiKeyId: _nullishCoalesce(route.apiKeyId, () => ( null)),
2018
+ // request-audit-log: correlate this request's tokens/cost to its audit record.
2019
+ auditResponse: res
2020
+ };
2021
+ const usageRecorder = deps.usageRecorder;
2022
+ const usageTap = usageRecorder ? {
2023
+ extractUsage(event) {
2024
+ if (event["type"] !== "response.completed") return null;
2025
+ const response = event["response"];
2026
+ const usage = _optionalChain([response, 'optionalAccess', _64 => _64["usage"]]);
2027
+ return _nullishCoalesce(usage, () => ( null));
2028
+ },
2029
+ onUsage(rawUsage) {
2030
+ recordResponsesStreamUsage(usageRecorder, rawUsage, usageAttribution);
2031
+ }
2032
+ } : void 0;
2033
+ const bodyText = await relayResponse(
2034
+ res,
2035
+ providerResponse.response,
2036
+ isStream,
2037
+ route.requestedModel,
2038
+ usageTap
2039
+ );
1671
2040
  if (bodyText && deps.usageRecorder) {
1672
- recordResponsesNonStreamUsage(deps.usageRecorder, bodyText, {
1673
- sessionId: route.sessionId,
1674
- providerId: _nullishCoalesce(route.providerId, () => ( "codex")),
1675
- model: resolvedModel,
1676
- apiKeyId: _nullishCoalesce(route.apiKeyId, () => ( null)),
1677
- // request-audit-log: correlate this request's tokens/cost to its audit record.
1678
- auditResponse: res
1679
- });
2041
+ recordResponsesNonStreamUsage(deps.usageRecorder, bodyText, usageAttribution);
1680
2042
  }
1681
2043
  } catch (err) {
2044
+ if (_chunk25GXJCEZcjs.isBoundAccountSelectionError.call(void 0, err)) {
2045
+ writeBoundAccountError(res, err);
2046
+ return;
2047
+ }
1682
2048
  const errMsg = _chunkSVNDB62Dcjs.serializeError.call(void 0, err);
1683
2049
  console.error("[ProviderProxy:responses] Pipeline error:", errMsg);
1684
- writeError(res, 502, errMsg);
2050
+ writeError(res, _chunk6QQG7YG3cjs.isAccountAllowanceExhaustedError.call(void 0, err) ? 429 : 502, errMsg);
1685
2051
  }
1686
2052
  }
1687
2053
  async function buildByoPlan4(res, route, deps, resolvedModel, isStream) {
@@ -1695,7 +2061,14 @@ async function buildByoPlan4(res, route, deps, resolvedModel, isStream) {
1695
2061
  writeError(res, 502, `Provider not found: ${providerId}`);
1696
2062
  return null;
1697
2063
  }
1698
- const apiKey = await resolvePoolBoundKey(deps, providerId, provider, route.sessionId);
2064
+ const apiKey = await resolvePoolBoundKey(
2065
+ deps,
2066
+ providerId,
2067
+ provider,
2068
+ route.sessionId,
2069
+ route.preferredKeyId,
2070
+ route.boundKeyFallbackPolicy
2071
+ );
1699
2072
  if (!apiKey) {
1700
2073
  writeError(res, 502, "API key not configured");
1701
2074
  return null;
@@ -1726,18 +2099,18 @@ async function buildByoPlan4(res, route, deps, resolvedModel, isStream) {
1726
2099
  proxyProviderId: "byo"
1727
2100
  };
1728
2101
  }
1729
- async function buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream) {
2102
+ async function buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream, sessionKey) {
1730
2103
  const profile = route.subscriptionProfile;
1731
2104
  if (!profile) {
1732
2105
  writeError(res, 502, "Subscription mode requires a codex subscription profile");
1733
2106
  return null;
1734
2107
  }
1735
- const upstreamUrl = _optionalChain([profile, 'access', _60 => _60.resolveUpstreamUrl, 'optionalCall', _61 => _61(resolvedModel)]);
2108
+ const upstreamUrl = _optionalChain([profile, 'access', _65 => _65.resolveUpstreamUrl, 'optionalCall', _66 => _66(resolvedModel)]);
1736
2109
  if (!upstreamUrl) {
1737
2110
  writeError(res, 502, "Subscription profile is missing resolveUpstreamUrl");
1738
2111
  return null;
1739
2112
  }
1740
- const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkKFI44N2Rcjs.SubscriptionAuthSource)(profile)));
2113
+ const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkYNJNTCSQcjs.SubscriptionAuthSource)(profile)));
1741
2114
  const chain = _chunkNYUNU75Acjs.resolveSubscriptionChain.call(void 0,
1742
2115
  profile,
1743
2116
  deps.llmConfig.getTransformerService(),
@@ -1751,15 +2124,27 @@ async function buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream)
1751
2124
  };
1752
2125
  if (profile.authStrategy.providerId === "gemini") {
1753
2126
  try {
1754
- transformerProvider.geminiProject = await resolveGeminiCodeAssistProject(profile);
2127
+ transformerProvider.geminiProject = await resolveGeminiCodeAssistProject(profile, {
2128
+ sessionKey,
2129
+ preferredAccountId: route.preferredAccountId,
2130
+ preferredAccountGroup: route.preferredAccountGroup,
2131
+ boundAccountFallbackPolicy: route.boundAccountFallbackPolicy
2132
+ });
1755
2133
  } catch (err) {
2134
+ if (_chunk25GXJCEZcjs.isBoundAccountSelectionError.call(void 0, err)) {
2135
+ writeBoundAccountError(res, err);
2136
+ return null;
2137
+ }
1756
2138
  writeError(res, 502, _chunkSVNDB62Dcjs.serializeError.call(void 0, err));
1757
2139
  return null;
1758
2140
  }
1759
2141
  }
1760
2142
  return {
1761
2143
  auth,
2144
+ sessionKey,
1762
2145
  preferredAccountId: route.preferredAccountId,
2146
+ preferredAccountGroup: route.preferredAccountGroup,
2147
+ boundAccountFallbackPolicy: route.boundAccountFallbackPolicy,
1763
2148
  chain,
1764
2149
  transformerProvider,
1765
2150
  resolvedModel,
@@ -1772,9 +2157,9 @@ async function buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream)
1772
2157
  proxyProviderId: profile.authStrategy.providerId
1773
2158
  };
1774
2159
  }
1775
- async function resolveGeminiCodeAssistProject(profile) {
2160
+ async function resolveGeminiCodeAssistProject(profile, hints) {
1776
2161
  const probe = {};
1777
- await profile.authStrategy.applyHeaders(probe);
2162
+ await profile.authStrategy.applyHeaders(probe, hints);
1778
2163
  const bearer = _nullishCoalesce(_nullishCoalesce(probe.Authorization, () => ( probe.authorization)), () => ( ""));
1779
2164
  const accessToken = bearer.replace(/^Bearer\s+/i, "").trim();
1780
2165
  if (!accessToken) return void 0;
@@ -1785,19 +2170,22 @@ async function resolveGeminiCodeAssistProject(profile) {
1785
2170
  async function runPipeline4(responsesBody, plan) {
1786
2171
  const executor = getSharedExecutor();
1787
2172
  const endpointTransformer = getResponsesEndpointTransformer();
1788
- const { auth, chain, transformerProvider, resolvedModel, isStream, resolveUrl, upstreamUrl } = plan;
2173
+ const { auth, sessionKey, chain, transformerProvider, resolvedModel, isStream, resolveUrl, upstreamUrl } = plan;
1789
2174
  let proxyAccountId;
1790
2175
  const authHeaders = {};
1791
2176
  await auth.applyHeaders(authHeaders, {
1792
2177
  upstreamUrl,
1793
2178
  model: resolvedModel,
2179
+ sessionKey,
1794
2180
  preferredAccountId: plan.preferredAccountId,
2181
+ preferredAccountGroup: plan.preferredAccountGroup,
2182
+ boundAccountFallbackPolicy: plan.boundAccountFallbackPolicy,
1795
2183
  reportSelection: (accountId) => {
1796
2184
  proxyAccountId = accountId;
1797
2185
  }
1798
2186
  });
1799
2187
  let rawStatus = null;
1800
- const { response } = await _chunkHYN75H6Gcjs.executeProviderCall.call(void 0, {
2188
+ const { response } = await _chunkMUHWHQVMcjs.executeProviderCall.call(void 0, {
1801
2189
  executor,
1802
2190
  request: responsesBody,
1803
2191
  provider: transformerProvider,
@@ -1815,7 +2203,7 @@ async function runPipeline4(responsesBody, plan) {
1815
2203
  },
1816
2204
  fetchFn: (url, headers, body) => {
1817
2205
  console.log(`[ProviderProxy:responses] -> ${url} model=${resolvedModel} stream=${isStream}`);
1818
- return _chunkOCEUVQHWcjs.fetchUpstream.call(void 0,
2206
+ return _chunkKCVJWJSTcjs.fetchUpstream.call(void 0,
1819
2207
  url,
1820
2208
  { method: "POST", headers, body: JSON.stringify(body) },
1821
2209
  { providerId: plan.proxyProviderId, accountId: proxyAccountId }
@@ -1830,8 +2218,8 @@ async function runPipeline4(responsesBody, plan) {
1830
2218
  }
1831
2219
  async function runPipelineWithPoolReporting4(responsesBody, plan) {
1832
2220
  const first = await runPipeline4(responsesBody, plan);
1833
- const outcome = await _optionalChain([plan, 'access', _62 => _62.auth, 'access', _63 => _63.onResult, 'optionalCall', _64 => _64(first.rawStatus)]);
1834
- if (_optionalChain([outcome, 'optionalAccess', _65 => _65.rebound])) {
2221
+ const outcome = await _optionalChain([plan, 'access', _67 => _67.auth, 'access', _68 => _68.onResult, 'optionalCall', _69 => _69(first.rawStatus)]);
2222
+ if (_optionalChain([outcome, 'optionalAccess', _70 => _70.rebound])) {
1835
2223
  console.log(
1836
2224
  "[ProviderProxy:responses] pool re-bound key after status",
1837
2225
  first.rawStatus,
@@ -1844,7 +2232,7 @@ async function runPipelineWithPoolReporting4(responsesBody, plan) {
1844
2232
  async function runPipelineWithSubscriptionRetry3(responsesBody, plan) {
1845
2233
  const first = await runPipeline4(responsesBody, plan);
1846
2234
  if (first.rawStatus !== 401) return first;
1847
- const refreshed = await _optionalChain([plan, 'access', _66 => _66.auth, 'access', _67 => _67.onUnauthorized, 'optionalCall', _68 => _68()]);
2235
+ const refreshed = await _optionalChain([plan, 'access', _71 => _71.auth, 'access', _72 => _72.onUnauthorized, 'optionalCall', _73 => _73(plan.sessionKey)]);
1848
2236
  if (!refreshed) {
1849
2237
  console.warn("[ProviderProxy:responses] 401 not recoverable (onUnauthorized returned false)");
1850
2238
  return first;
@@ -1866,7 +2254,7 @@ function resolveRouteToken(req) {
1866
2254
  if (fromAuth) return fromAuth;
1867
2255
  const googKey = req.headers["x-goog-api-key"];
1868
2256
  const value = Array.isArray(googKey) ? googKey[0] : googKey;
1869
- return _optionalChain([value, 'optionalAccess', _69 => _69.trim, 'call', _70 => _70()]) || void 0;
2257
+ return _optionalChain([value, 'optionalAccess', _74 => _74.trim, 'call', _75 => _75()]) || void 0;
1870
2258
  }
1871
2259
  async function routeRequest(req, res, routes, deps) {
1872
2260
  const token = resolveRouteToken(req);
@@ -1883,7 +2271,7 @@ async function routeRequest(req, res, routes, deps) {
1883
2271
  }
1884
2272
  if (isOpenAIResponsesRequest(method, url)) {
1885
2273
  const rawBody = await readBody(req);
1886
- await handleOpenAIResponsesRequest(res, rawBody, route, deps);
2274
+ await handleOpenAIResponsesRequest(res, rawBody, route, deps, req.headers);
1887
2275
  return;
1888
2276
  }
1889
2277
  if (isOpenAIChatRequest(method, url)) {
@@ -2074,11 +2462,11 @@ var DEFAULT_ACCOUNT_HEALTH = {
2074
2462
  overloadCooldownMs: 10 * 6e4
2075
2463
  };
2076
2464
  function normalizeAccountHealth(raw) {
2077
- const ah = _optionalChain([raw, 'optionalAccess', _71 => _71.accountHealth]);
2465
+ const ah = _optionalChain([raw, 'optionalAccess', _76 => _76.accountHealth]);
2078
2466
  return {
2079
- overloadCooldownEnabled: _optionalChain([ah, 'optionalAccess', _72 => _72.overloadCooldownEnabled]) !== false,
2467
+ overloadCooldownEnabled: _optionalChain([ah, 'optionalAccess', _77 => _77.overloadCooldownEnabled]) !== false,
2080
2468
  overloadCooldownMs: clampNumber(
2081
- _optionalChain([ah, 'optionalAccess', _73 => _73.overloadCooldownMs]),
2469
+ _optionalChain([ah, 'optionalAccess', _78 => _78.overloadCooldownMs]),
2082
2470
  6e4,
2083
2471
  36e5,
2084
2472
  DEFAULT_ACCOUNT_HEALTH.overloadCooldownMs
@@ -2093,54 +2481,86 @@ var DEFAULT_ACCOUNT_PROBE = {
2093
2481
  historySize: 10,
2094
2482
  staggerMs: 500
2095
2483
  };
2484
+ var DEFAULT_ALLOWANCE_SCHEDULING = {
2485
+ enabled: false,
2486
+ demoteAtPercent: 80,
2487
+ pauseAtPercent: 98,
2488
+ priorityPenalty: 100
2489
+ };
2490
+ function normalizeAllowanceScheduling(raw) {
2491
+ const value = _optionalChain([raw, 'optionalAccess', _79 => _79.allowanceScheduling]);
2492
+ const demoteAtPercent = clampNumber(
2493
+ _optionalChain([value, 'optionalAccess', _80 => _80.demoteAtPercent]),
2494
+ 0,
2495
+ 100,
2496
+ DEFAULT_ALLOWANCE_SCHEDULING.demoteAtPercent
2497
+ );
2498
+ const requestedPause = clampNumber(
2499
+ _optionalChain([value, 'optionalAccess', _81 => _81.pauseAtPercent]),
2500
+ 0,
2501
+ 100,
2502
+ DEFAULT_ALLOWANCE_SCHEDULING.pauseAtPercent
2503
+ );
2504
+ return {
2505
+ enabled: _optionalChain([value, 'optionalAccess', _82 => _82.enabled]) === true,
2506
+ demoteAtPercent,
2507
+ pauseAtPercent: Math.max(demoteAtPercent, requestedPause),
2508
+ priorityPenalty: Math.trunc(clampNumber(
2509
+ _optionalChain([value, 'optionalAccess', _83 => _83.priorityPenalty]),
2510
+ 1,
2511
+ 1e3,
2512
+ DEFAULT_ALLOWANCE_SCHEDULING.priorityPenalty
2513
+ ))
2514
+ };
2515
+ }
2096
2516
  function normalizeAccountProbe(raw) {
2097
- const ap = _optionalChain([raw, 'optionalAccess', _74 => _74.accountProbe]);
2517
+ const ap = _optionalChain([raw, 'optionalAccess', _84 => _84.accountProbe]);
2098
2518
  return {
2099
- enabled: _optionalChain([ap, 'optionalAccess', _75 => _75.enabled]) === true,
2100
- intervalMs: clampNumber(_optionalChain([ap, 'optionalAccess', _76 => _76.intervalMs]), 6e4, 864e5, DEFAULT_ACCOUNT_PROBE.intervalMs),
2101
- onlyMultiAccount: _optionalChain([ap, 'optionalAccess', _77 => _77.onlyMultiAccount]) !== false,
2102
- timeoutMs: clampNumber(_optionalChain([ap, 'optionalAccess', _78 => _78.timeoutMs]), 1e3, 6e4, DEFAULT_ACCOUNT_PROBE.timeoutMs),
2519
+ enabled: _optionalChain([ap, 'optionalAccess', _85 => _85.enabled]) === true,
2520
+ intervalMs: clampNumber(_optionalChain([ap, 'optionalAccess', _86 => _86.intervalMs]), 6e4, 864e5, DEFAULT_ACCOUNT_PROBE.intervalMs),
2521
+ onlyMultiAccount: _optionalChain([ap, 'optionalAccess', _87 => _87.onlyMultiAccount]) !== false,
2522
+ timeoutMs: clampNumber(_optionalChain([ap, 'optionalAccess', _88 => _88.timeoutMs]), 1e3, 6e4, DEFAULT_ACCOUNT_PROBE.timeoutMs),
2103
2523
  historySize: Math.trunc(
2104
- clampNumber(_optionalChain([ap, 'optionalAccess', _79 => _79.historySize]), 1, 200, DEFAULT_ACCOUNT_PROBE.historySize)
2524
+ clampNumber(_optionalChain([ap, 'optionalAccess', _89 => _89.historySize]), 1, 200, DEFAULT_ACCOUNT_PROBE.historySize)
2105
2525
  ),
2106
- staggerMs: clampNumber(_optionalChain([ap, 'optionalAccess', _80 => _80.staggerMs]), 0, 6e4, DEFAULT_ACCOUNT_PROBE.staggerMs)
2526
+ staggerMs: clampNumber(_optionalChain([ap, 'optionalAccess', _90 => _90.staggerMs]), 0, 6e4, DEFAULT_ACCOUNT_PROBE.staggerMs)
2107
2527
  };
2108
2528
  }
2109
2529
  function normalizeAudit(raw) {
2110
- const a = _optionalChain([raw, 'optionalAccess', _81 => _81.audit]);
2530
+ const a = _optionalChain([raw, 'optionalAccess', _91 => _91.audit]);
2111
2531
  return {
2112
- enabled: _optionalChain([a, 'optionalAccess', _82 => _82.enabled]) === true,
2113
- captureBodies: _optionalChain([a, 'optionalAccess', _83 => _83.captureBodies]) === true,
2532
+ enabled: _optionalChain([a, 'optionalAccess', _92 => _92.enabled]) === true,
2533
+ captureBodies: _optionalChain([a, 'optionalAccess', _93 => _93.captureBodies]) === true,
2114
2534
  maxBodyBytes: Math.trunc(
2115
- clampNumber(_optionalChain([a, 'optionalAccess', _84 => _84.maxBodyBytes]), 256, 1048576, _audittypes.DEFAULT_AUDIT_CONFIG.maxBodyBytes)
2535
+ clampNumber(_optionalChain([a, 'optionalAccess', _94 => _94.maxBodyBytes]), 256, 1048576, _audittypes.DEFAULT_AUDIT_CONFIG.maxBodyBytes)
2116
2536
  ),
2117
2537
  retentionDays: Math.trunc(
2118
- clampNumber(_optionalChain([a, 'optionalAccess', _85 => _85.retentionDays]), 1, 365, _audittypes.DEFAULT_AUDIT_CONFIG.retentionDays)
2538
+ clampNumber(_optionalChain([a, 'optionalAccess', _95 => _95.retentionDays]), 1, 365, _audittypes.DEFAULT_AUDIT_CONFIG.retentionDays)
2119
2539
  ),
2120
- trustForwardedFor: _optionalChain([a, 'optionalAccess', _86 => _86.trustForwardedFor]) === true
2540
+ trustForwardedFor: _optionalChain([a, 'optionalAccess', _96 => _96.trustForwardedFor]) === true
2121
2541
  };
2122
2542
  }
2123
2543
  function normalizeBilling(raw) {
2124
- const b = _optionalChain([raw, 'optionalAccess', _87 => _87.billing]);
2544
+ const b = _optionalChain([raw, 'optionalAccess', _97 => _97.billing]);
2125
2545
  const config = {
2126
- enabled: _optionalChain([b, 'optionalAccess', _88 => _88.enabled]) === true,
2546
+ enabled: _optionalChain([b, 'optionalAccess', _98 => _98.enabled]) === true,
2127
2547
  maxRetryAgeMs: Math.trunc(
2128
- clampNumber(_optionalChain([b, 'optionalAccess', _89 => _89.maxRetryAgeMs]), 6e4, 2592e6, _billingtypes.DEFAULT_BILLING_CONFIG.maxRetryAgeMs)
2548
+ clampNumber(_optionalChain([b, 'optionalAccess', _99 => _99.maxRetryAgeMs]), 6e4, 2592e6, _billingtypes.DEFAULT_BILLING_CONFIG.maxRetryAgeMs)
2129
2549
  )
2130
2550
  };
2131
- if (typeof _optionalChain([b, 'optionalAccess', _90 => _90.endpoint]) === "string" && b.endpoint.trim()) config.endpoint = b.endpoint.trim();
2132
- if (typeof _optionalChain([b, 'optionalAccess', _91 => _91.secret]) === "string" && b.secret.length > 0) config.secret = b.secret;
2551
+ if (typeof _optionalChain([b, 'optionalAccess', _100 => _100.endpoint]) === "string" && b.endpoint.trim()) config.endpoint = b.endpoint.trim();
2552
+ if (typeof _optionalChain([b, 'optionalAccess', _101 => _101.secret]) === "string" && b.secret.length > 0) config.secret = b.secret;
2133
2553
  return config;
2134
2554
  }
2135
2555
  var DEFAULT_FINGERPRINT = { enabled: false };
2136
2556
  function normalizeFingerprint(raw) {
2137
- const f = _optionalChain([raw, 'optionalAccess', _92 => _92.fingerprint]);
2138
- const out = { enabled: _optionalChain([f, 'optionalAccess', _93 => _93.enabled]) === true };
2139
- if (typeof _optionalChain([f, 'optionalAccess', _94 => _94.ua]) === "string" && f.ua.trim().length > 0) out.ua = f.ua.trim();
2557
+ const f = _optionalChain([raw, 'optionalAccess', _102 => _102.fingerprint]);
2558
+ const out = { enabled: _optionalChain([f, 'optionalAccess', _103 => _103.enabled]) === true };
2559
+ if (typeof _optionalChain([f, 'optionalAccess', _104 => _104.ua]) === "string" && f.ua.trim().length > 0) out.ua = f.ua.trim();
2140
2560
  return out;
2141
2561
  }
2142
2562
  function normalizeVoucher(raw) {
2143
- return { enabled: _optionalChain([raw, 'optionalAccess', _95 => _95.voucher, 'optionalAccess', _96 => _96.enabled]) === true };
2563
+ return { enabled: _optionalChain([raw, 'optionalAccess', _105 => _105.voucher, 'optionalAccess', _106 => _106.enabled]) === true };
2144
2564
  }
2145
2565
  var PROXY_TYPES = ["http", "https", "socks5"];
2146
2566
  function normalizeProxyConfig(raw) {
@@ -2224,14 +2644,14 @@ function clampNumber(value, min, max, fallback) {
2224
2644
  return Math.min(max, Math.max(min, n));
2225
2645
  }
2226
2646
  function normalizeQueueSegments(raw) {
2227
- const umq = _optionalChain([raw, 'optionalAccess', _97 => _97.userMessageQueue]);
2228
- const cq = _optionalChain([raw, 'optionalAccess', _98 => _98.concurrencyQueue]);
2647
+ const umq = _optionalChain([raw, 'optionalAccess', _107 => _107.userMessageQueue]);
2648
+ const cq = _optionalChain([raw, 'optionalAccess', _108 => _108.concurrencyQueue]);
2229
2649
  return {
2230
2650
  userMessageQueue: {
2231
- enabled: _optionalChain([umq, 'optionalAccess', _99 => _99.enabled]) === true,
2232
- delayMs: clampNumber(_optionalChain([umq, 'optionalAccess', _100 => _100.delayMs]), 0, 1e4, DEFAULT_USER_MESSAGE_QUEUE.delayMs),
2651
+ enabled: _optionalChain([umq, 'optionalAccess', _109 => _109.enabled]) === true,
2652
+ delayMs: clampNumber(_optionalChain([umq, 'optionalAccess', _110 => _110.delayMs]), 0, 1e4, DEFAULT_USER_MESSAGE_QUEUE.delayMs),
2233
2653
  waitTimeoutMs: clampNumber(
2234
- _optionalChain([umq, 'optionalAccess', _101 => _101.waitTimeoutMs]),
2654
+ _optionalChain([umq, 'optionalAccess', _111 => _111.waitTimeoutMs]),
2235
2655
  1e3,
2236
2656
  3e5,
2237
2657
  DEFAULT_USER_MESSAGE_QUEUE.waitTimeoutMs
@@ -2239,14 +2659,14 @@ function normalizeQueueSegments(raw) {
2239
2659
  },
2240
2660
  concurrencyQueue: {
2241
2661
  maxQueueSizeFactor: clampNumber(
2242
- _optionalChain([cq, 'optionalAccess', _102 => _102.maxQueueSizeFactor]),
2662
+ _optionalChain([cq, 'optionalAccess', _112 => _112.maxQueueSizeFactor]),
2243
2663
  1,
2244
2664
  10,
2245
2665
  DEFAULT_CONCURRENCY_QUEUE.maxQueueSizeFactor
2246
2666
  ),
2247
- minQueueSize: clampNumber(_optionalChain([cq, 'optionalAccess', _103 => _103.minQueueSize]), 1, 100, DEFAULT_CONCURRENCY_QUEUE.minQueueSize),
2667
+ minQueueSize: clampNumber(_optionalChain([cq, 'optionalAccess', _113 => _113.minQueueSize]), 1, 100, DEFAULT_CONCURRENCY_QUEUE.minQueueSize),
2248
2668
  waitTimeoutMs: clampNumber(
2249
- _optionalChain([cq, 'optionalAccess', _104 => _104.waitTimeoutMs]),
2669
+ _optionalChain([cq, 'optionalAccess', _114 => _114.waitTimeoutMs]),
2250
2670
  1e3,
2251
2671
  3e5,
2252
2672
  DEFAULT_CONCURRENCY_QUEUE.waitTimeoutMs
@@ -2257,11 +2677,11 @@ function normalizeQueueSegments(raw) {
2257
2677
  var ALL_ENDPOINTS = ["chat", "responses", "messages", "gemini"];
2258
2678
  function blankModelMap(endpoint) {
2259
2679
  const modelMap = {};
2260
- for (const kind of _chunkVACWOIREcjs.modelKindsForEndpoint.call(void 0, endpoint)) modelMap[kind] = "";
2680
+ for (const kind of _chunk4VZX5F4Tcjs.modelKindsForEndpoint.call(void 0, endpoint)) modelMap[kind] = "";
2261
2681
  return modelMap;
2262
2682
  }
2263
2683
  function defaultEndpointConfig(endpoint) {
2264
- if (_chunkVACWOIREcjs.isKindMappedEndpoint.call(void 0, endpoint)) {
2684
+ if (_chunk4VZX5F4Tcjs.isKindMappedEndpoint.call(void 0, endpoint)) {
2265
2685
  return { endpoint, modelMap: blankModelMap(endpoint), useSubscription: false };
2266
2686
  }
2267
2687
  if (endpoint === "chat") {
@@ -2287,13 +2707,14 @@ function normalizePrefixTargets(raw) {
2287
2707
  function normalizeEndpointConfig(e) {
2288
2708
  const endpoint = e.endpoint;
2289
2709
  const useSubscription = e.useSubscription === true;
2290
- const boundAccountId = typeof e.boundAccountId === "string" && e.boundAccountId.trim() !== "" ? e.boundAccountId : void 0;
2710
+ const boundAccountId = typeof e.boundAccountId === "string" && e.boundAccountId.trim() !== "" ? e.boundAccountId.trim() : void 0;
2711
+ const boundAccountFallbackPolicy = boundAccountId ? e.boundAccountFallbackPolicy === "pool" ? "pool" : "strict" : void 0;
2291
2712
  const boundKeyId = typeof e.boundKeyId === "string" && e.boundKeyId.trim() !== "" ? e.boundKeyId : void 0;
2292
2713
  let config;
2293
- if (_chunkVACWOIREcjs.isKindMappedEndpoint.call(void 0, endpoint)) {
2714
+ if (_chunk4VZX5F4Tcjs.isKindMappedEndpoint.call(void 0, endpoint)) {
2294
2715
  const rawMap = e.modelMap && typeof e.modelMap === "object" ? e.modelMap : {};
2295
2716
  const modelMap = {};
2296
- for (const kind of _chunkVACWOIREcjs.modelKindsForEndpoint.call(void 0, endpoint)) {
2717
+ for (const kind of _chunk4VZX5F4Tcjs.modelKindsForEndpoint.call(void 0, endpoint)) {
2297
2718
  const v = rawMap[kind];
2298
2719
  modelMap[kind] = typeof v === "string" ? v : "";
2299
2720
  }
@@ -2317,21 +2738,186 @@ function normalizeEndpointConfig(e) {
2317
2738
  config.backgroundModelIds = e.backgroundModelIds;
2318
2739
  }
2319
2740
  }
2320
- if (boundAccountId) config.boundAccountId = boundAccountId;
2741
+ if (boundAccountId) {
2742
+ config.boundAccountId = boundAccountId;
2743
+ config.boundAccountFallbackPolicy = boundAccountFallbackPolicy;
2744
+ }
2321
2745
  if (boundKeyId) config.boundKeyId = boundKeyId;
2322
2746
  return config;
2323
2747
  }
2748
+ function normalizeBindingTarget(raw) {
2749
+ if (!raw || typeof raw !== "object") return null;
2750
+ const target = raw;
2751
+ const providerId = typeof target.providerId === "string" ? target.providerId.trim() : "";
2752
+ if (!providerId) return null;
2753
+ if (target.kind === "account") {
2754
+ const accountId = typeof target.accountId === "string" ? target.accountId.trim() : "";
2755
+ return accountId ? { kind: "account", providerId, accountId } : null;
2756
+ }
2757
+ if (target.kind === "account-group") {
2758
+ const group = typeof target.group === "string" ? target.group.trim() : "";
2759
+ return group ? { kind: "account-group", providerId, group } : null;
2760
+ }
2761
+ if (target.kind === "account-pool") return { kind: "account-pool", providerId };
2762
+ if (target.kind === "provider") {
2763
+ const keyId = typeof target.keyId === "string" ? target.keyId.trim() : "";
2764
+ return keyId ? { kind: "provider", providerId, keyId } : { kind: "provider", providerId };
2765
+ }
2766
+ return null;
2767
+ }
2768
+ function normalizeGatewayModelMappings(raw) {
2769
+ if (!Array.isArray(raw)) return [];
2770
+ const mappings = [];
2771
+ for (const entry of raw) {
2772
+ if (!entry || typeof entry !== "object") continue;
2773
+ const value = entry;
2774
+ const source = typeof value.source === "string" ? value.source.trim() : "";
2775
+ const target = typeof value.target === "string" ? value.target.trim() : "";
2776
+ if (!source || !target) continue;
2777
+ mappings.push({ source, target });
2778
+ }
2779
+ return mappings;
2780
+ }
2781
+ function hasConfiguredLegacyModels(config) {
2782
+ return Object.values(_nullishCoalesce(config.modelMap, () => ( {}))).some((value) => typeof value === "string" && value.trim()) || Boolean(_optionalChain([config, 'access', _115 => _115.models, 'optionalAccess', _116 => _116.some, 'call', _117 => _117((value) => typeof value === "string" && value.trim())])) || Boolean(_optionalChain([config, 'access', _118 => _118.defaultModel, 'optionalAccess', _119 => _119.trim, 'call', _120 => _120()])) || Boolean(_optionalChain([config, 'access', _121 => _121.backgroundModel, 'optionalAccess', _122 => _122.trim, 'call', _123 => _123()])) || Boolean(Object.values(_nullishCoalesce(config.prefixTargets, () => ( {}))).some((value) => _optionalChain([value, 'optionalAccess', _124 => _124.trim, 'call', _125 => _125()])));
2783
+ }
2784
+ function splitModelRef(ref) {
2785
+ if (typeof ref !== "string") return null;
2786
+ const idx = ref.indexOf(",");
2787
+ if (idx <= 0) return null;
2788
+ const providerId = ref.slice(0, idx).trim();
2789
+ const modelId = ref.slice(idx + 1).trim();
2790
+ return providerId && modelId ? { providerId, modelId } : null;
2791
+ }
2792
+ function legacyTarget(config, providerId) {
2793
+ if (config.useSubscription) {
2794
+ if (config.boundAccountId) {
2795
+ return { kind: "account", providerId, accountId: config.boundAccountId };
2796
+ }
2797
+ if (config.boundAccountGroup) {
2798
+ return { kind: "account-group", providerId, group: config.boundAccountGroup };
2799
+ }
2800
+ return { kind: "account-pool", providerId };
2801
+ }
2802
+ return config.boundKeyId ? { kind: "provider", providerId, keyId: config.boundKeyId } : { kind: "provider", providerId };
2803
+ }
2804
+ function legacyEndpointToBindings(config) {
2805
+ const fallback = config.boundAccountId && config.boundAccountFallbackPolicy === "strict" ? "fail" : "next";
2806
+ const byProvider = /* @__PURE__ */ new Map();
2807
+ const routeFor = (providerId) => {
2808
+ const existing = byProvider.get(providerId);
2809
+ if (existing) return existing;
2810
+ const created = {
2811
+ id: `legacy-${config.endpoint}-${providerId}`,
2812
+ name: `${config.endpoint} \xB7 ${providerId}`,
2813
+ enabled: true,
2814
+ keyScope: "all",
2815
+ endpoint: config.endpoint,
2816
+ target: legacyTarget(config, providerId),
2817
+ fallback,
2818
+ modelMode: "mapped"
2819
+ };
2820
+ byProvider.set(providerId, created);
2821
+ return created;
2822
+ };
2823
+ for (const [kind, ref] of Object.entries(_nullishCoalesce(config.modelMap, () => ( {})))) {
2824
+ const parsed = splitModelRef(ref);
2825
+ if (!parsed) continue;
2826
+ const route = routeFor(parsed.providerId);
2827
+ route.modelMap = { ...route.modelMap, [kind]: ref };
2828
+ }
2829
+ for (const ref of _nullishCoalesce(config.models, () => ( []))) {
2830
+ const parsed = splitModelRef(ref);
2831
+ if (!parsed) continue;
2832
+ const route = routeFor(parsed.providerId);
2833
+ route.models = [..._nullishCoalesce(route.models, () => ( [])), ref];
2834
+ }
2835
+ for (const [prefix, ref] of Object.entries(_nullishCoalesce(config.prefixTargets, () => ( {})))) {
2836
+ const parsed = splitModelRef(ref);
2837
+ if (!parsed) continue;
2838
+ const route = routeFor(parsed.providerId);
2839
+ route.dispatchMode = "prefix";
2840
+ route.prefixTargets = { ...route.prefixTargets, [prefix]: ref };
2841
+ }
2842
+ for (const [field, ref] of [
2843
+ ["defaultModel", config.defaultModel],
2844
+ ["backgroundModel", config.backgroundModel]
2845
+ ]) {
2846
+ const parsed = splitModelRef(ref);
2847
+ if (!parsed) continue;
2848
+ const route = routeFor(parsed.providerId);
2849
+ route[field] = ref;
2850
+ if (_optionalChain([config, 'access', _126 => _126.backgroundModelIds, 'optionalAccess', _127 => _127.length])) {
2851
+ route.backgroundModelIds = [...config.backgroundModelIds];
2852
+ }
2853
+ }
2854
+ return [...byProvider.values()];
2855
+ }
2856
+ function legacyEndpointsToBindings(endpoints) {
2857
+ return endpoints.filter((endpoint) => hasConfiguredLegacyModels(endpoint)).flatMap((endpoint) => legacyEndpointToBindings(endpoint));
2858
+ }
2859
+ function normalizeGatewayBindings(raw) {
2860
+ if (!Array.isArray(raw)) return [];
2861
+ const seen = /* @__PURE__ */ new Set();
2862
+ const bindings = [];
2863
+ for (const entry of raw) {
2864
+ if (!entry || typeof entry !== "object") continue;
2865
+ const value = entry;
2866
+ const id = typeof value.id === "string" ? value.id.trim() : "";
2867
+ const name = typeof value.name === "string" ? value.name.trim() : "";
2868
+ const endpoint = value.endpoint;
2869
+ const target = normalizeBindingTarget(value.target);
2870
+ if (!id || seen.has(id) || !name || !ALL_ENDPOINTS.includes(endpoint) || !target) continue;
2871
+ seen.add(id);
2872
+ const normalizedRoute = normalizeEndpointConfig({
2873
+ ...value,
2874
+ endpoint,
2875
+ useSubscription: target.kind !== "provider"
2876
+ });
2877
+ const apiKeyIds = Array.isArray(value.apiKeyIds) ? [...new Set(value.apiKeyIds.filter((key) => typeof key === "string" && key.trim() !== "").map((key) => key.trim()))] : [];
2878
+ const keyScope = value.keyScope === "selected" ? "selected" : value.keyScope === "all" ? "all" : apiKeyIds.length > 0 ? "selected" : "all";
2879
+ const modelMappings = normalizeGatewayModelMappings(value.modelMappings);
2880
+ const modelMode = value.modelMode === "passthrough" ? "passthrough" : value.modelMode === "mapped" ? "mapped" : modelMappings.length > 0 || hasConfiguredLegacyModels(normalizedRoute) ? "mapped" : "passthrough";
2881
+ const priority = typeof value.priority === "number" && Number.isFinite(value.priority) ? Math.max(0, Math.min(1e4, Math.round(value.priority))) : void 0;
2882
+ const binding = {
2883
+ id,
2884
+ name,
2885
+ enabled: value.enabled !== false,
2886
+ keyScope,
2887
+ endpoint,
2888
+ target,
2889
+ // Legacy `'global'` meant "yield to the removed global endpoint fallback";
2890
+ // it now yields to the next matching route, which is the same default.
2891
+ fallback: value.fallback === "fail" ? "fail" : "next",
2892
+ modelMode
2893
+ };
2894
+ if (apiKeyIds.length > 0) binding.apiKeyIds = apiKeyIds;
2895
+ if (modelMappings.length > 0) binding.modelMappings = modelMappings;
2896
+ if (priority !== void 0) binding.priority = priority;
2897
+ if (normalizedRoute.modelMap) binding.modelMap = normalizedRoute.modelMap;
2898
+ if (normalizedRoute.models) binding.models = normalizedRoute.models;
2899
+ if (normalizedRoute.dispatchMode) binding.dispatchMode = normalizedRoute.dispatchMode;
2900
+ if (normalizedRoute.prefixTargets) binding.prefixTargets = normalizedRoute.prefixTargets;
2901
+ if (normalizedRoute.defaultModel !== void 0) binding.defaultModel = normalizedRoute.defaultModel;
2902
+ if (normalizedRoute.backgroundModel !== void 0) binding.backgroundModel = normalizedRoute.backgroundModel;
2903
+ if (normalizedRoute.backgroundModelIds) binding.backgroundModelIds = normalizedRoute.backgroundModelIds;
2904
+ bindings.push(binding);
2905
+ }
2906
+ return bindings;
2907
+ }
2324
2908
  function defaultServerConfig() {
2325
2909
  const queues = normalizeQueueSegments(void 0);
2326
2910
  return {
2327
2911
  enabled: false,
2328
2912
  networkBinding: false,
2329
2913
  endpoints: ALL_ENDPOINTS.map(defaultEndpointConfig),
2914
+ bindings: [],
2330
2915
  port: DEFAULT_OUTBOUND_PORT,
2331
2916
  userMessageQueue: queues.userMessageQueue,
2332
2917
  concurrencyQueue: queues.concurrencyQueue,
2333
2918
  accountHealth: normalizeAccountHealth(void 0),
2334
2919
  accountProbe: normalizeAccountProbe(void 0),
2920
+ allowanceScheduling: normalizeAllowanceScheduling(void 0),
2335
2921
  audit: normalizeAudit(void 0),
2336
2922
  billing: normalizeBilling(void 0),
2337
2923
  fingerprint: normalizeFingerprint(void 0),
@@ -2348,17 +2934,20 @@ function normalizeServerConfig(raw) {
2348
2934
  }
2349
2935
  }
2350
2936
  const queues = normalizeQueueSegments(raw);
2937
+ const legacyEndpoints = ALL_ENDPOINTS.map((ep) => _nullishCoalesce(byEndpoint.get(ep), () => ( defaultEndpointConfig(ep))));
2938
+ const persistedBindings = normalizeGatewayBindings(raw.bindings);
2939
+ const bindings = persistedBindings.length > 0 ? persistedBindings : normalizeGatewayBindings(legacyEndpointsToBindings(legacyEndpoints));
2351
2940
  const config = {
2352
2941
  enabled: raw.enabled === true,
2353
2942
  networkBinding: raw.networkBinding === true,
2354
- endpoints: ALL_ENDPOINTS.map(
2355
- (ep) => _nullishCoalesce(byEndpoint.get(ep), () => ( defaultEndpointConfig(ep)))
2356
- ),
2943
+ endpoints: ALL_ENDPOINTS.map(defaultEndpointConfig),
2944
+ bindings,
2357
2945
  port: _nullishCoalesce(raw.port, () => ( base.port)),
2358
2946
  userMessageQueue: queues.userMessageQueue,
2359
2947
  concurrencyQueue: queues.concurrencyQueue,
2360
2948
  accountHealth: normalizeAccountHealth(raw),
2361
2949
  accountProbe: normalizeAccountProbe(raw),
2950
+ allowanceScheduling: normalizeAllowanceScheduling(raw),
2362
2951
  audit: normalizeAudit(raw),
2363
2952
  billing: normalizeBilling(raw),
2364
2953
  fingerprint: normalizeFingerprint(raw),
@@ -2384,11 +2973,13 @@ function mergeServerConfig(current, patch) {
2384
2973
  enabled: _nullishCoalesce(patch.enabled, () => ( current.enabled)),
2385
2974
  networkBinding: _nullishCoalesce(patch.networkBinding, () => ( current.networkBinding)),
2386
2975
  endpoints: _nullishCoalesce(patch.endpoints, () => ( current.endpoints)),
2976
+ bindings: _nullishCoalesce(patch.bindings, () => ( current.bindings)),
2387
2977
  port: _nullishCoalesce(patch.port, () => ( current.port)),
2388
2978
  userMessageQueue: _nullishCoalesce(patch.userMessageQueue, () => ( current.userMessageQueue)),
2389
2979
  concurrencyQueue: _nullishCoalesce(patch.concurrencyQueue, () => ( current.concurrencyQueue)),
2390
2980
  accountHealth: _nullishCoalesce(patch.accountHealth, () => ( current.accountHealth)),
2391
2981
  accountProbe: _nullishCoalesce(patch.accountProbe, () => ( current.accountProbe)),
2982
+ allowanceScheduling: _nullishCoalesce(patch.allowanceScheduling, () => ( current.allowanceScheduling)),
2392
2983
  audit: _nullishCoalesce(patch.audit, () => ( current.audit)),
2393
2984
  billing: _nullishCoalesce(patch.billing, () => ( current.billing)),
2394
2985
  // Proxy is layer-replaced (not deep-merged): a PUT carrying `proxy` swaps the
@@ -2406,6 +2997,167 @@ function mergeServerConfig(current, patch) {
2406
2997
  });
2407
2998
  }
2408
2999
 
3000
+ // src/outbound-api/gatewayBindingResolver.ts
3001
+ var MESSAGE_FALLBACK_KINDS = ["sonnet", "opus", "haiku", "fable"];
3002
+ function nonBlank(value) {
3003
+ return typeof value === "string" && value.trim() !== "";
3004
+ }
3005
+ function gatewayBindingAllowsKey(binding, apiKeyId) {
3006
+ const scope = _nullishCoalesce(binding.keyScope, () => ( (_optionalChain([binding, 'access', _128 => _128.apiKeyIds, 'optionalAccess', _129 => _129.length]) ? "selected" : "all")));
3007
+ return scope === "all" || Boolean(_optionalChain([binding, 'access', _130 => _130.apiKeyIds, 'optionalAccess', _131 => _131.includes, 'call', _132 => _132(apiKeyId)]));
3008
+ }
3009
+ function wildcardMatches(pattern, value) {
3010
+ const escaped = pattern.split("*").map((part) => part.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")).join(".*");
3011
+ return new RegExp(`^${escaped}$`, "iu").test(value);
3012
+ }
3013
+ function resolveGatewayModelMapping(mappings, requestedModel) {
3014
+ if (!nonBlank(requestedModel)) return void 0;
3015
+ const wanted = requestedModel.trim();
3016
+ const exact = (_nullishCoalesce(mappings, () => ( []))).find(
3017
+ (mapping) => nonBlank(mapping.source) && !mapping.source.includes("*") && mapping.source.trim().toLocaleLowerCase() === wanted.toLocaleLowerCase()
3018
+ );
3019
+ if (exact && nonBlank(exact.target)) return exact.target.trim();
3020
+ const wildcard = (_nullishCoalesce(mappings, () => ( []))).find(
3021
+ (mapping) => nonBlank(mapping.source) && mapping.source.includes("*") && wildcardMatches(mapping.source.trim(), wanted)
3022
+ );
3023
+ return wildcard && nonBlank(wildcard.target) ? wildcard.target.trim() : void 0;
3024
+ }
3025
+ function routeCanServe(binding, requestedModel, role) {
3026
+ if (binding.modelMode === "passthrough") return nonBlank(requestedModel);
3027
+ if (_optionalChain([binding, 'access', _133 => _133.modelMappings, 'optionalAccess', _134 => _134.length])) {
3028
+ return nonBlank(resolveGatewayModelMapping(binding.modelMappings, requestedModel));
3029
+ }
3030
+ if (_chunk4VZX5F4Tcjs.isKindMappedEndpoint.call(void 0, binding.endpoint)) {
3031
+ const map = _nullishCoalesce(binding.modelMap, () => ( {}));
3032
+ const kind = _chunk4VZX5F4Tcjs.detectModelKind.call(void 0, binding.endpoint, requestedModel);
3033
+ if (kind && nonBlank(map[kind])) return true;
3034
+ if (binding.endpoint === "messages") {
3035
+ return MESSAGE_FALLBACK_KINDS.some((candidate) => nonBlank(map[candidate]));
3036
+ }
3037
+ return nonBlank(map.codex);
3038
+ }
3039
+ if (binding.endpoint === "chat" && binding.dispatchMode === "prefix") {
3040
+ return _chunk4VZX5F4Tcjs.resolvePrefixTarget.call(void 0, binding.prefixTargets, requestedModel) !== null;
3041
+ }
3042
+ if (binding.endpoint === "chat") {
3043
+ if (!requestedModel) return false;
3044
+ const wanted = requestedModel.trim().toLowerCase();
3045
+ return (_nullishCoalesce(binding.models, () => ( []))).some((ref) => _optionalChain([modelIdOf, 'call', _135 => _135(ref), 'optionalAccess', _136 => _136.toLowerCase, 'call', _137 => _137()]) === wanted);
3046
+ }
3047
+ return role === "background" ? nonBlank(binding.backgroundModel) : nonBlank(binding.defaultModel);
3048
+ }
3049
+ function modelIdOf(ref) {
3050
+ if (!nonBlank(ref)) return void 0;
3051
+ const trimmed = ref.trim();
3052
+ const comma = trimmed.indexOf(",");
3053
+ const modelId = comma >= 0 ? trimmed.slice(comma + 1).trim() : trimmed;
3054
+ return modelId || void 0;
3055
+ }
3056
+ function targetProviderId(target) {
3057
+ return target.providerId.trim();
3058
+ }
3059
+ function targetRef(target, ref) {
3060
+ const modelId = _nullishCoalesce(modelIdOf(ref), () => ( ""));
3061
+ return modelId ? `${targetProviderId(target)},${modelId}` : "";
3062
+ }
3063
+ function targetRefs(target, refs) {
3064
+ return (_nullishCoalesce(refs, () => ( []))).map((ref) => targetRef(target, ref)).filter(nonBlank);
3065
+ }
3066
+ function targetPrefixRefs(target, refs) {
3067
+ if (!refs) return void 0;
3068
+ const mapped = {};
3069
+ for (const kind of ["claude", "gpt", "gemini"]) {
3070
+ const ref = targetRef(target, refs[kind]);
3071
+ if (ref) mapped[kind] = ref;
3072
+ }
3073
+ return mapped.claude || mapped.gpt || mapped.gemini ? mapped : void 0;
3074
+ }
3075
+ function applySingleModel(config, binding, targetModel) {
3076
+ const ref = targetRef(binding.target, targetModel);
3077
+ if (!ref) return;
3078
+ if (_chunk4VZX5F4Tcjs.isKindMappedEndpoint.call(void 0, binding.endpoint)) {
3079
+ config.modelMap = Object.fromEntries(
3080
+ _chunk4VZX5F4Tcjs.modelKindsForEndpoint.call(void 0, binding.endpoint).map((kind) => [kind, ref])
3081
+ );
3082
+ } else if (binding.endpoint === "chat") {
3083
+ config.models = [ref];
3084
+ config.dispatchMode = "list";
3085
+ } else {
3086
+ config.defaultModel = ref;
3087
+ config.backgroundModel = ref;
3088
+ }
3089
+ }
3090
+ function gatewayBindingToEndpointConfig(binding, requestedModel) {
3091
+ const target = binding.target;
3092
+ const config = {
3093
+ endpoint: binding.endpoint,
3094
+ useSubscription: target.kind !== "provider"
3095
+ };
3096
+ const usesGenericModelHandling = binding.modelMode === "passthrough" || Boolean(_optionalChain([binding, 'access', _138 => _138.modelMappings, 'optionalAccess', _139 => _139.length]));
3097
+ const dynamicModel = binding.modelMode === "passthrough" ? requestedModel : resolveGatewayModelMapping(binding.modelMappings, requestedModel);
3098
+ if (usesGenericModelHandling) {
3099
+ if (nonBlank(dynamicModel)) applySingleModel(config, binding, dynamicModel);
3100
+ } else if (_chunk4VZX5F4Tcjs.isKindMappedEndpoint.call(void 0, binding.endpoint)) {
3101
+ config.modelMap = Object.fromEntries(
3102
+ Object.entries(_nullishCoalesce(binding.modelMap, () => ( {}))).map(([kind, ref]) => [kind, targetRef(target, ref)])
3103
+ );
3104
+ } else if (binding.endpoint === "chat") {
3105
+ config.models = targetRefs(target, binding.models);
3106
+ if (binding.dispatchMode === "prefix") {
3107
+ config.dispatchMode = "prefix";
3108
+ config.prefixTargets = targetPrefixRefs(target, binding.prefixTargets);
3109
+ }
3110
+ } else {
3111
+ config.defaultModel = targetRef(target, binding.defaultModel);
3112
+ config.backgroundModel = targetRef(target, binding.backgroundModel);
3113
+ if (binding.backgroundModelIds) config.backgroundModelIds = [...binding.backgroundModelIds];
3114
+ }
3115
+ if (target.kind === "account") {
3116
+ config.boundAccountId = target.accountId;
3117
+ config.boundAccountFallbackPolicy = binding.fallback === "next" ? "pool" : "strict";
3118
+ } else if (target.kind === "account-group") {
3119
+ config.boundAccountGroup = target.group;
3120
+ config.boundAccountFallbackPolicy = binding.fallback === "next" ? "pool" : "strict";
3121
+ } else if (target.kind === "provider" && target.keyId) {
3122
+ config.boundKeyId = target.keyId;
3123
+ config.boundKeyFallbackPolicy = binding.fallback === "next" ? "pool" : "strict";
3124
+ }
3125
+ return config;
3126
+ }
3127
+ function candidateGatewayBindings(bindings, apiKeyId, endpoint) {
3128
+ const candidates = (_nullishCoalesce(bindings, () => ( []))).filter(
3129
+ (binding) => binding.enabled && binding.endpoint === endpoint && gatewayBindingAllowsKey(binding, apiKeyId)
3130
+ );
3131
+ const scopeOf = (binding) => _nullishCoalesce(binding.keyScope, () => ( (_optionalChain([binding, 'access', _140 => _140.apiKeyIds, 'optionalAccess', _141 => _141.length]) ? "selected" : "all")));
3132
+ const scoped = candidates.filter((binding) => scopeOf(binding) === "selected");
3133
+ const pool = scoped.length > 0 ? scoped : candidates.filter((binding) => scopeOf(binding) === "all");
3134
+ return pool.sort(
3135
+ (left, right) => (_nullishCoalesce(left.priority, () => ( 100))) - (_nullishCoalesce(right.priority, () => ( 100))) || left.id.localeCompare(right.id)
3136
+ );
3137
+ }
3138
+ function candidateBackgroundModelIds(bindings, apiKeyId, endpoint) {
3139
+ const ids = [
3140
+ ...new Set(
3141
+ candidateGatewayBindings(bindings, apiKeyId, endpoint).flatMap(
3142
+ (binding) => _nullishCoalesce(binding.backgroundModelIds, () => ( []))
3143
+ )
3144
+ )
3145
+ ];
3146
+ return ids.length > 0 ? ids : void 0;
3147
+ }
3148
+ function resolveGatewayBinding(input) {
3149
+ const candidates = candidateGatewayBindings(input.bindings, input.apiKeyId, input.endpoint);
3150
+ const binding = _nullishCoalesce(candidates.find(
3151
+ (candidate) => candidate.fallback === "fail" || routeCanServe(candidate, input.requestedModel, input.role)
3152
+ ), () => ( candidates[0]));
3153
+ if (!binding) return { source: "none" };
3154
+ return {
3155
+ source: "binding",
3156
+ binding,
3157
+ config: gatewayBindingToEndpointConfig(binding, input.requestedModel)
3158
+ };
3159
+ }
3160
+
2409
3161
  // src/outbound-api/outboundApiKeyAuth.ts
2410
3162
 
2411
3163
 
@@ -2498,6 +3250,27 @@ async function createNamedKey(db, name) {
2498
3250
  plaintextOnce: secret
2499
3251
  };
2500
3252
  }
3253
+ async function createIntegrationKey(db, name, allowedEndpoints = ["responses", "messages"]) {
3254
+ const secret = generateSecret();
3255
+ const id = newKeyId();
3256
+ const prefix = keyPrefix(secret);
3257
+ const row = await db.outboundApiKeysCreate({
3258
+ id,
3259
+ name,
3260
+ keyHash: hashKey(secret),
3261
+ keyPrefix: prefix,
3262
+ kind: "integration",
3263
+ allowedEndpoints: [...new Set(allowedEndpoints)],
3264
+ loopbackOnly: true
3265
+ });
3266
+ return {
3267
+ id: row.id,
3268
+ name: row.name,
3269
+ keyPrefix: row.keyPrefix,
3270
+ createdAt: row.createdAt,
3271
+ plaintextOnce: secret
3272
+ };
3273
+ }
2501
3274
  function extractCostLimits(row) {
2502
3275
  const limits = {};
2503
3276
  if (row.dailyCostLimitUsd != null) limits.dailyUsd = row.dailyCostLimitUsd;
@@ -2520,7 +3293,12 @@ function extractModelRestriction(row) {
2520
3293
  };
2521
3294
  }
2522
3295
  function toVerifiedKey(row) {
2523
- const key = { id: row.id };
3296
+ const key = {
3297
+ id: row.id,
3298
+ kind: row.kind,
3299
+ allowedEndpoints: row.allowedEndpoints,
3300
+ loopbackOnly: row.loopbackOnly
3301
+ };
2524
3302
  if (row.maxConcurrency !== void 0 && row.maxConcurrency !== null) {
2525
3303
  key.maxConcurrency = row.maxConcurrency;
2526
3304
  }
@@ -2740,8 +3518,8 @@ var OutboundRateLimiter = (_class8 = class {
2740
3518
  * recorded (no bucket growth).
2741
3519
  */
2742
3520
  check(apiKeyId, now = Date.now(), override) {
2743
- const maxRequests = _nullishCoalesce(_optionalChain([override, 'optionalAccess', _105 => _105.maxRequests]), () => ( this.maxRequests));
2744
- const windowMs = _nullishCoalesce(_optionalChain([override, 'optionalAccess', _106 => _106.windowMs]), () => ( this.windowMs));
3521
+ const maxRequests = _nullishCoalesce(_optionalChain([override, 'optionalAccess', _142 => _142.maxRequests]), () => ( this.maxRequests));
3522
+ const windowMs = _nullishCoalesce(_optionalChain([override, 'optionalAccess', _143 => _143.windowMs]), () => ( this.windowMs));
2745
3523
  if (maxRequests === 0) return { allowed: true, retryAfterSeconds: 0 };
2746
3524
  const cutoff = now - windowMs;
2747
3525
  const timestamps = (_nullishCoalesce(this.hits.get(apiKeyId), () => ( []))).filter((ts) => ts > cutoff);
@@ -2786,7 +3564,7 @@ function isUserMessageAnthropic(body) {
2786
3564
  if (typeof content === "string") return true;
2787
3565
  if (Array.isArray(content)) {
2788
3566
  const hasToolResult = content.some(
2789
- (block) => _optionalChain([asObject, 'call', _107 => _107(block), 'optionalAccess', _108 => _108["type"]]) === "tool_result"
3567
+ (block) => _optionalChain([asObject, 'call', _144 => _144(block), 'optionalAccess', _145 => _145["type"]]) === "tool_result"
2790
3568
  );
2791
3569
  return !hasToolResult;
2792
3570
  }
@@ -2815,7 +3593,7 @@ function isUserMessageGemini(body) {
2815
3593
  if (!lastContent || lastContent["role"] !== "user") return false;
2816
3594
  const parts = asArray(lastContent["parts"]);
2817
3595
  const hasFunctionResponse = parts.some(
2818
- (part) => _optionalChain([asObject, 'call', _109 => _109(part), 'optionalAccess', _110 => _110["functionResponse"]]) !== void 0
3596
+ (part) => _optionalChain([asObject, 'call', _146 => _146(part), 'optionalAccess', _147 => _147["functionResponse"]]) !== void 0
2819
3597
  );
2820
3598
  return !hasFunctionResponse;
2821
3599
  }
@@ -2989,14 +3767,14 @@ function newVoucherId() {
2989
3767
  }
2990
3768
  function computeVoucherGrant(voucher, currentKey, now) {
2991
3769
  if (voucher.type === "credit") {
2992
- const current = _nullishCoalesce(_optionalChain([currentKey, 'optionalAccess', _111 => _111.totalCostLimitUsd]), () => ( 0));
3770
+ const current = _nullishCoalesce(_optionalChain([currentKey, 'optionalAccess', _148 => _148.totalCostLimitUsd]), () => ( 0));
2993
3771
  let granted2 = current + (_nullishCoalesce(voucher.creditUsd, () => ( 0)));
2994
3772
  if (voucher.maxTotalCostLimitUsd != null) {
2995
3773
  granted2 = Math.min(granted2, voucher.maxTotalCostLimitUsd);
2996
3774
  }
2997
3775
  return { totalCostLimitUsd: granted2 };
2998
3776
  }
2999
- const currentExpiry = _nullishCoalesce(_optionalChain([currentKey, 'optionalAccess', _112 => _112.expiresAt]), () => ( now));
3777
+ const currentExpiry = _nullishCoalesce(_optionalChain([currentKey, 'optionalAccess', _149 => _149.expiresAt]), () => ( now));
3000
3778
  let granted = currentExpiry + (_nullishCoalesce(voucher.renewalDays, () => ( 0))) * DAY_MS2;
3001
3779
  if (voucher.maxExpiryDays != null) {
3002
3780
  granted = Math.min(granted, now + voucher.maxExpiryDays * DAY_MS2);
@@ -3027,7 +3805,7 @@ function toVoucherInfo(v) {
3027
3805
  // src/outbound-api/voucherRedeem.ts
3028
3806
  function isRedeemRequest(method, url) {
3029
3807
  if (method !== "POST" || !url) return false;
3030
- const path = _nullishCoalesce(_optionalChain([url, 'access', _113 => _113.split, 'call', _114 => _114("?"), 'access', _115 => _115[0], 'optionalAccess', _116 => _116.replace, 'call', _117 => _117(/\/+$/, "")]), () => ( ""));
3808
+ const path = _nullishCoalesce(_optionalChain([url, 'access', _150 => _150.split, 'call', _151 => _151("?"), 'access', _152 => _152[0], 'optionalAccess', _153 => _153.replace, 'call', _154 => _154(/\/+$/, "")]), () => ( ""));
3031
3809
  return path.endsWith("/redeem");
3032
3810
  }
3033
3811
  function writeErr(res, status, message, headers = {}) {
@@ -3057,8 +3835,8 @@ function grantToResult(type, granted) {
3057
3835
  function currentResult(type, keyRow) {
3058
3836
  const result = { type };
3059
3837
  if (type === "credit") {
3060
- if (_optionalChain([keyRow, 'optionalAccess', _118 => _118.totalCostLimitUsd]) != null) result.totalCostLimitUsd = keyRow.totalCostLimitUsd;
3061
- } else if (_optionalChain([keyRow, 'optionalAccess', _119 => _119.expiresAt]) != null) {
3838
+ if (_optionalChain([keyRow, 'optionalAccess', _155 => _155.totalCostLimitUsd]) != null) result.totalCostLimitUsd = keyRow.totalCostLimitUsd;
3839
+ } else if (_optionalChain([keyRow, 'optionalAccess', _156 => _156.expiresAt]) != null) {
3062
3840
  result.expiresAt = keyRow.expiresAt;
3063
3841
  }
3064
3842
  return result;
@@ -3096,7 +3874,7 @@ async function handleVoucherRedeem(req, res, deps, voucherEnabled, redeemLimiter
3096
3874
  let code;
3097
3875
  try {
3098
3876
  code = raw ? JSON.parse(raw)["code"] : void 0;
3099
- } catch (e17) {
3877
+ } catch (e24) {
3100
3878
  writeErr(res, 400, "Invalid JSON in request body");
3101
3879
  return;
3102
3880
  }
@@ -3145,7 +3923,7 @@ async function handleVoucherRedeem(req, res, deps, voucherEnabled, redeemLimiter
3145
3923
  const won = await voucherDb.voucherRedeemCas(voucher.id, verifiedKeyId, absolute, now);
3146
3924
  if (!won) {
3147
3925
  const after = await voucherDb.voucherGetByHash(codeHash);
3148
- if (_optionalChain([after, 'optionalAccess', _120 => _120.status]) === "redeemed" && after.redeemedByKeyId === verifiedKeyId) {
3926
+ if (_optionalChain([after, 'optionalAccess', _157 => _157.status]) === "redeemed" && after.redeemedByKeyId === verifiedKeyId) {
3149
3927
  return after.grantApplied === true ? { ok: true, result: currentResult(after.type, await deps.db.outboundApiKeysGetByHash(keyHash)) } : await applyFirstPass(after, recordedAbsolute(after));
3150
3928
  }
3151
3929
  return { ok: false, status: 409, message: "Code was already redeemed" };
@@ -3164,10 +3942,10 @@ function getFallbackRedeemLimiter() {
3164
3942
  fallbackRedeemLimiter ??= new OutboundRateLimiter({ maxRequests: 10, windowMs: 6e4 });
3165
3943
  return fallbackRedeemLimiter;
3166
3944
  }
3167
- function writeJsonError(res, status, message, headers = {}) {
3945
+ function writeJsonError(res, status, message, headers = {}, details = {}) {
3168
3946
  if (res.headersSent) return;
3169
3947
  res.writeHead(status, { "Content-Type": "application/json", ...headers });
3170
- res.end(JSON.stringify({ error: { type: "outbound_api_error", message } }));
3948
+ res.end(JSON.stringify({ error: { type: "outbound_api_error", message, ...details } }));
3171
3949
  }
3172
3950
  function writeCostLimitError(res, scope, limitUsd, spentUsd) {
3173
3951
  if (res.headersSent) return;
@@ -3206,14 +3984,19 @@ function extractPresentedKey(req) {
3206
3984
  }
3207
3985
  const xApiKey = req.headers["x-api-key"];
3208
3986
  const xApi = Array.isArray(xApiKey) ? xApiKey[0] : xApiKey;
3209
- if (_optionalChain([xApi, 'optionalAccess', _121 => _121.trim, 'call', _122 => _122()])) return xApi.trim();
3987
+ if (_optionalChain([xApi, 'optionalAccess', _158 => _158.trim, 'call', _159 => _159()])) return xApi.trim();
3210
3988
  const goog = req.headers["x-goog-api-key"];
3211
3989
  const g = Array.isArray(goog) ? goog[0] : goog;
3212
- return _optionalChain([g, 'optionalAccess', _123 => _123.trim, 'call', _124 => _124()]) || void 0;
3990
+ return _optionalChain([g, 'optionalAccess', _160 => _160.trim, 'call', _161 => _161()]) || void 0;
3991
+ }
3992
+ function isLoopbackPeer(address) {
3993
+ if (!address) return false;
3994
+ const normalized = address.toLowerCase().split("%")[0];
3995
+ return normalized === "::1" || normalized === "127.0.0.1" || normalized.startsWith("127.") || normalized.startsWith("::ffff:127.");
3213
3996
  }
3214
3997
  function selectEndpoint(method, url) {
3215
3998
  if (method !== "POST" || !url) return null;
3216
- const path = _nullishCoalesce(_optionalChain([url, 'access', _125 => _125.split, 'call', _126 => _126("?"), 'access', _127 => _127[0], 'optionalAccess', _128 => _128.replace, 'call', _129 => _129(/\/+$/, "")]), () => ( ""));
3999
+ const path = _nullishCoalesce(_optionalChain([url, 'access', _162 => _162.split, 'call', _163 => _163("?"), 'access', _164 => _164[0], 'optionalAccess', _165 => _165.replace, 'call', _166 => _166(/\/+$/, "")]), () => ( ""));
3217
4000
  if (path.endsWith("/chat/completions")) return "chat";
3218
4001
  if (path.endsWith("/responses")) return "responses";
3219
4002
  if (path.includes("/v1/messages")) return "messages";
@@ -3231,12 +4014,36 @@ function extractGeminiModelFromUrl(url) {
3231
4014
  }
3232
4015
  function isModelsListRequest(url) {
3233
4016
  if (!url) return false;
3234
- const path = _nullishCoalesce(_optionalChain([url, 'access', _130 => _130.split, 'call', _131 => _131("?"), 'access', _132 => _132[0], 'optionalAccess', _133 => _133.replace, 'call', _134 => _134(/\/+$/, "")]), () => ( ""));
4017
+ const path = _nullishCoalesce(_optionalChain([url, 'access', _167 => _167.split, 'call', _168 => _168("?"), 'access', _169 => _169[0], 'optionalAccess', _170 => _170.replace, 'call', _171 => _171(/\/+$/, "")]), () => ( ""));
3235
4018
  return path.endsWith("/models");
3236
4019
  }
3237
- function writeChatModelsList(res, config) {
3238
- const chat = config.endpoints.find((e) => e.endpoint === "chat");
3239
- const data = (_nullishCoalesce(_optionalChain([chat, 'optionalAccess', _135 => _135.models]), () => ( []))).map((ref) => _chunkVACWOIREcjs.parseModelRef.call(void 0, ref)).filter((p) => p !== null).map((p) => ({ id: p.modelId, object: "model", owned_by: "omnicross" }));
4020
+ function writeModelsList(res, config, apiKeyId, allowedEndpoints) {
4021
+ const refs = [];
4022
+ const endpointConfigs = [];
4023
+ for (const endpoint of ["chat", "responses", "messages", "gemini"]) {
4024
+ if (allowedEndpoints && !allowedEndpoints.includes(endpoint)) continue;
4025
+ endpointConfigs.push(
4026
+ ...candidateGatewayBindings(config.bindings, apiKeyId, endpoint).map(
4027
+ (binding) => gatewayBindingToEndpointConfig(binding)
4028
+ )
4029
+ );
4030
+ }
4031
+ for (const endpoint of endpointConfigs) {
4032
+ if (allowedEndpoints && !allowedEndpoints.includes(endpoint.endpoint)) continue;
4033
+ if (endpoint.endpoint === "chat") refs.push(..._nullishCoalesce(endpoint.models, () => ( [])));
4034
+ else if (endpoint.endpoint === "messages" || endpoint.endpoint === "responses") {
4035
+ refs.push(...Object.values(_nullishCoalesce(endpoint.modelMap, () => ( {}))));
4036
+ } else {
4037
+ if (endpoint.defaultModel) refs.push(endpoint.defaultModel);
4038
+ if (endpoint.backgroundModel) refs.push(endpoint.backgroundModel);
4039
+ }
4040
+ }
4041
+ const seen = /* @__PURE__ */ new Set();
4042
+ const data = refs.map((ref) => _chunk4VZX5F4Tcjs.parseModelRef.call(void 0, ref)).filter((p) => p !== null).filter((p) => {
4043
+ if (seen.has(p.modelId)) return false;
4044
+ seen.add(p.modelId);
4045
+ return true;
4046
+ }).map((p) => ({ id: p.modelId, object: "model", owned_by: "omnicross" }));
3240
4047
  res.writeHead(200, { "Content-Type": "application/json" });
3241
4048
  res.end(JSON.stringify({ object: "list", data }));
3242
4049
  }
@@ -3255,7 +4062,7 @@ function shimAuthHeader(req, routeToken) {
3255
4062
  }
3256
4063
  async function handleOutboundRequest(req, res, deps, config, rateLimiter, serialQueue, concurrencyGate, redeemLimiter, redeemMutex) {
3257
4064
  const now = Date.now();
3258
- const audit = _chunkE3UCVHLPcjs.beginAuditCapture.call(void 0, req, res, now);
4065
+ const audit = _chunkUNWKG6EIcjs.beginAuditCapture.call(void 0, req, res, now);
3259
4066
  const billing = _chunkAPYG5QD7cjs.beginBillingCapture.call(void 0, req, res, now);
3260
4067
  const presented = extractPresentedKey(req);
3261
4068
  const verification = await verifyKey(deps.db, presented, now);
@@ -3270,12 +4077,20 @@ async function handleOutboundRequest(req, res, deps, config, rateLimiter, serial
3270
4077
  const verified = verification.key;
3271
4078
  if (audit) audit.keyId = verified.id;
3272
4079
  if (billing) billing.keyId = verified.id;
4080
+ if (verified.loopbackOnly && !isLoopbackPeer(_optionalChain([req, 'access', _172 => _172.socket, 'optionalAccess', _173 => _173.remoteAddress]))) {
4081
+ writeJsonError(res, 403, "This integration key is restricted to loopback clients");
4082
+ return;
4083
+ }
3273
4084
  if (isRedeemRequest(req.method, req.url)) {
4085
+ if (verified.kind === "integration") {
4086
+ writeJsonError(res, 403, "Integration keys cannot redeem vouchers");
4087
+ return;
4088
+ }
3274
4089
  await handleVoucherRedeem(
3275
4090
  req,
3276
4091
  res,
3277
4092
  deps,
3278
- _optionalChain([config, 'access', _136 => _136.voucher, 'optionalAccess', _137 => _137.enabled]) === true,
4093
+ _optionalChain([config, 'access', _174 => _174.voucher, 'optionalAccess', _175 => _175.enabled]) === true,
3279
4094
  _nullishCoalesce(redeemLimiter, () => ( getFallbackRedeemLimiter())),
3280
4095
  verified.id,
3281
4096
  _nullishCoalesce(presented, () => ( "")),
@@ -3292,7 +4107,11 @@ async function handleOutboundRequest(req, res, deps, config, rateLimiter, serial
3292
4107
  return;
3293
4108
  }
3294
4109
  if (req.method === "GET" && isModelsListRequest(req.url)) {
3295
- writeChatModelsList(res, config);
4110
+ if (verified.allowedEndpoints && verified.allowedEndpoints.length === 0) {
4111
+ writeJsonError(res, 403, "API key is not allowed to access this endpoint");
4112
+ return;
4113
+ }
4114
+ writeModelsList(res, config, verified.id, verified.allowedEndpoints);
3296
4115
  return;
3297
4116
  }
3298
4117
  const endpoint = selectEndpoint(req.method, req.url);
@@ -3300,9 +4119,12 @@ async function handleOutboundRequest(req, res, deps, config, rateLimiter, serial
3300
4119
  writeJsonError(res, 404, `Unsupported: ${req.method} ${req.url}`);
3301
4120
  return;
3302
4121
  }
3303
- const endpointConfig = config.endpoints.find((e) => e.endpoint === endpoint);
3304
- if (!endpointConfig) {
3305
- writeJsonError(res, 503, `endpoint '${endpoint}' is not configured`);
4122
+ if (verified.allowedEndpoints && !verified.allowedEndpoints.includes(endpoint)) {
4123
+ writeJsonError(res, 403, "API key is not allowed to access this endpoint");
4124
+ return;
4125
+ }
4126
+ if (candidateGatewayBindings(config.bindings, verified.id, endpoint).length === 0) {
4127
+ writeJsonError(res, 503, `endpoint '${endpoint}' has no downstream route for this key`);
3306
4128
  return;
3307
4129
  }
3308
4130
  if (verified.costLimits && deps.keySpendTracker) {
@@ -3361,12 +4183,12 @@ async function handleOutboundRequest(req, res, deps, config, rateLimiter, serial
3361
4183
  res.once("close", release2);
3362
4184
  }
3363
4185
  try {
3364
- const ingressFormat = _chunkVACWOIREcjs.endpointToIngressFormat.call(void 0, endpoint);
4186
+ const ingressFormat = _chunk4VZX5F4Tcjs.endpointToIngressFormat.call(void 0, endpoint);
3365
4187
  const rawBody = await readBody3(req);
3366
4188
  let parsedBody = {};
3367
4189
  try {
3368
4190
  parsedBody = rawBody ? JSON.parse(rawBody) : {};
3369
- } catch (e18) {
4191
+ } catch (e25) {
3370
4192
  writeJsonError(res, 400, "Invalid JSON in request body");
3371
4193
  return;
3372
4194
  }
@@ -3375,23 +4197,40 @@ async function handleOutboundRequest(req, res, deps, config, rateLimiter, serial
3375
4197
  const urlModel = extractGeminiModelFromUrl(req.url);
3376
4198
  if (urlModel) parsedBody["model"] = urlModel;
3377
4199
  }
3378
- const sessionId = deps.proxyDeps.apiKeyPool ? `outbound:${verified.id}` : null;
3379
- const resolved = _chunkVACWOIREcjs.isKindMappedEndpoint.call(void 0, endpoint) || endpoint === "chat" ? await _chunkVACWOIREcjs.resolveRoute.call(void 0, {
3380
- config: endpointConfig,
4200
+ const requestedModel = _chunk4VZX5F4Tcjs.extractRequestedModel.call(void 0, ingressFormat, parsedBody);
4201
+ const role = _chunk4VZX5F4Tcjs.isKindMappedEndpoint.call(void 0, endpoint) || endpoint === "chat" ? void 0 : _chunk4VZX5F4Tcjs.detectRequestRole.call(void 0, ingressFormat, parsedBody, {
4202
+ // Role detection precedes the route pick (the pick consumes the
4203
+ // role), so the hint is the union across the candidate routes.
4204
+ backgroundModelIds: candidateBackgroundModelIds(config.bindings, verified.id, endpoint)
4205
+ });
4206
+ const bindingResolution = resolveGatewayBinding({
4207
+ bindings: config.bindings,
4208
+ apiKeyId: verified.id,
4209
+ endpoint,
4210
+ requestedModel,
4211
+ role
4212
+ });
4213
+ if (bindingResolution.source === "none") {
4214
+ writeJsonError(res, 503, `endpoint '${endpoint}' has no downstream route for this key`);
4215
+ return;
4216
+ }
4217
+ const effectiveEndpointConfig = bindingResolution.config;
4218
+ const bindingAffinitySuffix = `:${bindingResolution.binding.id}`;
4219
+ const sessionId = deps.proxyDeps.apiKeyPool ? `outbound:${verified.id}${bindingAffinitySuffix}` : null;
4220
+ const resolved = _chunk4VZX5F4Tcjs.isKindMappedEndpoint.call(void 0, endpoint) || endpoint === "chat" ? await _chunk4VZX5F4Tcjs.resolveRoute.call(void 0, {
4221
+ config: effectiveEndpointConfig,
3381
4222
  ingressFormat,
3382
4223
  llmConfig: deps.llmConfig,
3383
4224
  sessionId,
3384
4225
  // Capture the ORIGINAL requested id BEFORE any downstream swap; for
3385
4226
  // kind-mapped endpoints it selects the kind AND is stamped onto
3386
4227
  // `route.requestedModel`; for chat it is matched against the list.
3387
- requestedModel: _chunkVACWOIREcjs.extractRequestedModel.call(void 0, ingressFormat, parsedBody),
4228
+ requestedModel,
3388
4229
  // Attribution: stamp the verified named-key id onto the route.
3389
4230
  apiKeyId: verified.id
3390
- }) : await _chunkVACWOIREcjs.resolveRoute.call(void 0, {
3391
- config: endpointConfig,
3392
- role: _chunkVACWOIREcjs.detectRequestRole.call(void 0, ingressFormat, parsedBody, {
3393
- backgroundModelIds: endpointConfig.backgroundModelIds
3394
- }),
4231
+ }) : await _chunk4VZX5F4Tcjs.resolveRoute.call(void 0, {
4232
+ config: effectiveEndpointConfig,
4233
+ role,
3395
4234
  ingressFormat,
3396
4235
  llmConfig: deps.llmConfig,
3397
4236
  sessionId,
@@ -3420,7 +4259,7 @@ async function handleOutboundRequest(req, res, deps, config, rateLimiter, serial
3420
4259
  }
3421
4260
  let releaseSerial = null;
3422
4261
  const providerKey = resolved.route.providerId;
3423
- if (_optionalChain([config, 'access', _138 => _138.userMessageQueue, 'optionalAccess', _139 => _139.enabled]) && providerKey && isUserMessageRequest(endpoint, parsedBody)) {
4262
+ if (_optionalChain([config, 'access', _176 => _176.userMessageQueue, 'optionalAccess', _177 => _177.enabled]) && providerKey && isUserMessageRequest(endpoint, parsedBody)) {
3424
4263
  const umq = config.userMessageQueue;
3425
4264
  try {
3426
4265
  const serialSlot = await serialQueue.acquire(providerKey, {
@@ -3452,12 +4291,29 @@ async function handleOutboundRequest(req, res, deps, config, rateLimiter, serial
3452
4291
  const replay = makeReplayRequest(req, rawBody);
3453
4292
  await routeRequest(replay, res, routeMap, deps.proxyDeps);
3454
4293
  } catch (err) {
4294
+ if (_chunk25GXJCEZcjs.isBoundAccountSelectionError.call(void 0, err)) {
4295
+ const headers = {};
4296
+ if (err.status === 429 && err.resumeAt) {
4297
+ const resumeMs = Date.parse(err.resumeAt);
4298
+ if (Number.isFinite(resumeMs)) {
4299
+ headers["Retry-After"] = String(Math.max(1, Math.ceil((resumeMs - Date.now()) / 1e3)));
4300
+ }
4301
+ }
4302
+ writeJsonError(
4303
+ res,
4304
+ err.status,
4305
+ _chunk25GXJCEZcjs.boundAccountSelectionMessage.call(void 0, err.reason),
4306
+ headers,
4307
+ { code: err.code, reason: err.reason }
4308
+ );
4309
+ return;
4310
+ }
3455
4311
  const message = _chunkSVNDB62Dcjs.serializeError.call(void 0, err);
3456
4312
  if (deps.logger) deps.logger.error("[OutboundApi] dispatch error:", message);
3457
4313
  else console.error("[OutboundApi] dispatch error:", message);
3458
4314
  _chunkUIBD2YY5cjs.emitWebhookEvent.call(void 0, { kind: "server.error", at: Date.now(), message });
3459
4315
  if (audit) audit.error = message;
3460
- writeJsonError(res, 502, message);
4316
+ writeJsonError(res, _chunk6QQG7YG3cjs.isAccountAllowanceExhaustedError.call(void 0, err) ? 429 : 502, message);
3461
4317
  } finally {
3462
4318
  routeMap.removeRoute(token);
3463
4319
  if (releaseSerial) releaseSerial();
@@ -3481,18 +4337,8 @@ function makeReplayRequest(req, rawBody) {
3481
4337
  var DEFAULT_OUTBOUND_PORT = 8765;
3482
4338
  var LOOPBACK_ADDR = "127.0.0.1";
3483
4339
  var LAN_ADDR = "0.0.0.0";
3484
- var OutboundApiConfigError = class extends Error {
3485
-
3486
- constructor(missing) {
3487
- super(
3488
- "Outbound API server cannot start: incomplete model-kind configuration \u2014 " + missing.map((m) => `${m.endpoint} missing [${m.missingKinds.join(", ")}]`).join("; ")
3489
- );
3490
- this.name = "OutboundApiConfigError";
3491
- this.missing = missing;
3492
- }
3493
- };
3494
4340
  var OutboundApiServer = (_class11 = class {
3495
- constructor(deps, onPortChange) {;_class11.prototype.__init12.call(this);_class11.prototype.__init13.call(this);_class11.prototype.__init14.call(this);_class11.prototype.__init15.call(this);_class11.prototype.__init16.call(this);_class11.prototype.__init17.call(this);_class11.prototype.__init18.call(this);_class11.prototype.__init19.call(this);_class11.prototype.__init20.call(this);
4341
+ constructor(deps, onPortChange) {;_class11.prototype.__init12.call(this);_class11.prototype.__init13.call(this);_class11.prototype.__init14.call(this);_class11.prototype.__init15.call(this);_class11.prototype.__init16.call(this);_class11.prototype.__init17.call(this);_class11.prototype.__init18.call(this);_class11.prototype.__init19.call(this);_class11.prototype.__init20.call(this);_class11.prototype.__init21.call(this);
3496
4342
  this.deps = deps;
3497
4343
  this.onPortChange = onPortChange;
3498
4344
  }
@@ -3502,25 +4348,26 @@ var OutboundApiServer = (_class11 = class {
3502
4348
  __init13() {this.boundPort = 0}
3503
4349
  __init14() {this.boundAddr = LOOPBACK_ADDR}
3504
4350
  __init15() {this.endpoints = []}
4351
+ __init16() {this.bindings = []}
3505
4352
 
3506
4353
 
3507
4354
 
3508
- __init16() {this.rateLimiter = new OutboundRateLimiter()}
4355
+ __init17() {this.rateLimiter = new OutboundRateLimiter()}
3509
4356
  /**
3510
4357
  * Redeem-attempt limiter (voucher-redemption #9, design D6) — a SEPARATE bucket
3511
4358
  * from the traffic `rateLimiter`, keyed by the authenticating key id, so
3512
4359
  * brute-forcing `CC_` codes is throttled (a handful/min) without touching the
3513
4360
  * per-key request rate. Conservative fixed defaults (10 / 60s).
3514
4361
  */
3515
- __init17() {this.redeemLimiter = new OutboundRateLimiter({ maxRequests: 10, windowMs: 6e4 })}
4362
+ __init18() {this.redeemLimiter = new OutboundRateLimiter({ maxRequests: 10, windowMs: 6e4 })}
3516
4363
  /**
3517
4364
  * Per-key redeem mutex (voucher-redemption #9, MJ1 fix). One instance for the
3518
4365
  * server's lifetime so concurrent redeem REQUESTS for the same key serialize
3519
4366
  * (relative grant increments accumulate instead of clobbering a snapshot).
3520
4367
  */
3521
- __init18() {this.redeemMutex = new KeyedMutex()}
3522
- __init19() {this.serialQueue = new UserMessageSerialQueue()}
3523
- __init20() {this.concurrencyGate = new OutboundConcurrencyGate()}
4368
+ __init19() {this.redeemMutex = new KeyedMutex()}
4369
+ __init20() {this.serialQueue = new UserMessageSerialQueue()}
4370
+ __init21() {this.concurrencyGate = new OutboundConcurrencyGate()}
3524
4371
  /**
3525
4372
  * Apply a config. Restarts the listener ONLY when the bind address or port
3526
4373
  * changes (or when toggling enabled); per-endpoint routing config is updated
@@ -3528,6 +4375,7 @@ var OutboundApiServer = (_class11 = class {
3528
4375
  */
3529
4376
  async applyConfig(input) {
3530
4377
  this.endpoints = input.endpoints;
4378
+ this.bindings = _nullishCoalesce(input.bindings, () => ( []));
3531
4379
  this.userMessageQueue = input.userMessageQueue;
3532
4380
  this.concurrencyQueue = input.concurrencyQueue;
3533
4381
  this.voucherConfig = input.voucher;
@@ -3537,16 +4385,6 @@ var OutboundApiServer = (_class11 = class {
3537
4385
  await this.stop();
3538
4386
  return;
3539
4387
  }
3540
- const missing = _chunkVACWOIREcjs.validateServerModelConfig.call(void 0, {
3541
- enabled: true,
3542
- networkBinding: input.networkBinding,
3543
- endpoints: input.endpoints,
3544
- port: input.port
3545
- });
3546
- if (missing.length > 0) {
3547
- await this.stop();
3548
- throw new OutboundApiConfigError(missing);
3549
- }
3550
4388
  const running = this.server !== null;
3551
4389
  const bindChanged = running && (this.boundAddr !== wantAddr || this.boundPort !== wantPort);
3552
4390
  if (running && !bindChanged) {
@@ -3561,7 +4399,7 @@ var OutboundApiServer = (_class11 = class {
3561
4399
  const actualPort = await this.listen(bindAddr, port);
3562
4400
  this.boundAddr = bindAddr;
3563
4401
  this.boundPort = actualPort;
3564
- if (actualPort !== port) _optionalChain([this, 'access', _140 => _140.onPortChange, 'optionalCall', _141 => _141(actualPort)]);
4402
+ if (actualPort !== port) _optionalChain([this, 'access', _178 => _178.onPortChange, 'optionalCall', _179 => _179(actualPort)]);
3565
4403
  this.logInfo(`[OutboundApiServer] Listening on ${bindAddr}:${actualPort}`);
3566
4404
  return actualPort;
3567
4405
  }
@@ -3595,6 +4433,7 @@ var OutboundApiServer = (_class11 = class {
3595
4433
  }
3596
4434
  /** Per-request handler. Auth is enforced on EVERY request (incl. loopback). */
3597
4435
  onRequest(req, res) {
4436
+ if (req.url) req.url = normalizeDoubledEndpointPath(req.url);
3598
4437
  if (this.deps.healthReportProvider && this.tryServeHealth(req, res)) return;
3599
4438
  handleOutboundRequest(
3600
4439
  req,
@@ -3602,6 +4441,7 @@ var OutboundApiServer = (_class11 = class {
3602
4441
  this.deps,
3603
4442
  {
3604
4443
  endpoints: this.endpoints,
4444
+ bindings: this.bindings,
3605
4445
  userMessageQueue: this.userMessageQueue,
3606
4446
  concurrencyQueue: this.concurrencyQueue,
3607
4447
  voucher: this.voucherConfig
@@ -3628,7 +4468,7 @@ var OutboundApiServer = (_class11 = class {
3628
4468
  const provider = this.deps.healthReportProvider;
3629
4469
  if (!provider) return false;
3630
4470
  if (req.method !== "GET" && req.method !== "HEAD") return false;
3631
- const path = _optionalChain([(_nullishCoalesce(req.url, () => ( "/"))), 'access', _142 => _142.split, 'call', _143 => _143("?"), 'access', _144 => _144[0], 'optionalAccess', _145 => _145.replace, 'call', _146 => _146(/\/+$/, "")]) || "/";
4471
+ const path = _optionalChain([(_nullishCoalesce(req.url, () => ( "/"))), 'access', _180 => _180.split, 'call', _181 => _181("?"), 'access', _182 => _182[0], 'optionalAccess', _183 => _183.replace, 'call', _184 => _184(/\/+$/, "")]) || "/";
3632
4472
  if (path !== "/health" && path !== "/healthz") return false;
3633
4473
  const report = provider();
3634
4474
  res.writeHead(_healthloggingtypes.healthHttpStatus.call(void 0, report.status), { "Content-Type": "application/json" });
@@ -3717,6 +4557,16 @@ function firstLanIPv4() {
3717
4557
  }
3718
4558
  return null;
3719
4559
  }
4560
+ function normalizeDoubledEndpointPath(url) {
4561
+ const queryIdx = url.indexOf("?");
4562
+ const path = queryIdx === -1 ? url : url.slice(0, queryIdx);
4563
+ const query = queryIdx === -1 ? "" : url.slice(queryIdx);
4564
+ const collapsed = path.replace(
4565
+ /^(.*?)(\/v1\/(?:messages|responses|chat\/completions))\2$/,
4566
+ "$1$2"
4567
+ );
4568
+ return collapsed + query;
4569
+ }
3720
4570
 
3721
4571
  // src/outbound-api/keySpendTracker.ts
3722
4572
  function startOfLocalDay(ts) {
@@ -3730,12 +4580,12 @@ function startOfLocalWeek(ts) {
3730
4580
  return day.getTime();
3731
4581
  }
3732
4582
  var KeySpendTracker = (_class12 = class {
3733
- constructor(seeder) {;_class12.prototype.__init21.call(this);
4583
+ constructor(seeder) {;_class12.prototype.__init22.call(this);
3734
4584
  this.seeder = seeder;
3735
4585
  }
3736
4586
 
3737
4587
  /** apiKeyId → live accumulated spend (seeded lazily). */
3738
- __init21() {this.spend = /* @__PURE__ */ new Map()}
4588
+ __init22() {this.spend = /* @__PURE__ */ new Map()}
3739
4589
  /**
3740
4590
  * Read the key's accumulated spend, seeding from the durable store on a cache
3741
4591
  * miss and rolling the daily/weekly windows on a hit.
@@ -3823,7 +4673,7 @@ async function callOpenAICompletion(provider, apiKey, options, logger) {
3823
4673
  model: options.model,
3824
4674
  messages: options.messages.map((m) => convertMessageToOpenAI(m)),
3825
4675
  // Only set max_tokens if explicitly provided, otherwise let API use its default
3826
- ...options.maxTokens ? { max_tokens: options.maxTokens } : {},
4676
+ ...options.maxTokens !== void 0 ? { max_tokens: options.maxTokens } : {},
3827
4677
  temperature: options.temperature,
3828
4678
  stream: false
3829
4679
  // For now, non-streaming only
@@ -3874,7 +4724,7 @@ async function callAnthropicCompletion(provider, apiKey, options, logger) {
3874
4724
  const nonSystemMessages = options.messages.filter((m) => m.role !== "system");
3875
4725
  const anthropicRequest2 = {
3876
4726
  model: options.model,
3877
- max_tokens: options.maxTokens || 16384,
4727
+ max_tokens: _nullishCoalesce(options.maxTokens, () => ( 16384)),
3878
4728
  temperature: options.temperature,
3879
4729
  ...systemMessages.length > 0 ? { system: systemMessages.map((m) => m.content).join("\n\n") } : {},
3880
4730
  messages: nonSystemMessages.map((m) => convertMessageToAnthropic(m)),
@@ -3896,14 +4746,14 @@ async function callAnthropicCompletion(provider, apiKey, options, logger) {
3896
4746
  };
3897
4747
  }
3898
4748
  const anthropicResponse2 = await response2.json();
3899
- const openaiResponse2 = _chunkSUEGJ75Dcjs.convertAnthropicToOpenAI.call(void 0, anthropicResponse2);
4749
+ const openaiResponse2 = _chunkWYTEQ4Q5cjs.convertAnthropicToOpenAI.call(void 0, anthropicResponse2);
3900
4750
  const choice2 = openaiResponse2.choices[0];
3901
4751
  return {
3902
4752
  success: true,
3903
4753
  message: {
3904
4754
  id: `assistant-${Date.now()}`,
3905
4755
  role: "assistant",
3906
- content: _optionalChain([choice2, 'access', _147 => _147.message, 'optionalAccess', _148 => _148.content]) || "",
4756
+ content: _optionalChain([choice2, 'access', _185 => _185.message, 'optionalAccess', _186 => _186.content]) || "",
3907
4757
  timestamp: Date.now()
3908
4758
  },
3909
4759
  usage: openaiResponse2.usage ? {
@@ -3920,14 +4770,14 @@ async function callAnthropicCompletion(provider, apiKey, options, logger) {
3920
4770
  content: m.content
3921
4771
  })),
3922
4772
  // Anthropic requires max_tokens; use 16384 default if not explicitly set
3923
- max_tokens: options.maxTokens || 16384,
4773
+ max_tokens: _nullishCoalesce(options.maxTokens, () => ( 16384)),
3924
4774
  temperature: options.temperature,
3925
4775
  stream: false
3926
4776
  };
3927
4777
  const config = {
3928
4778
  defaultModel: options.model
3929
4779
  };
3930
- const anthropicRequest = _chunkSUEGJ75Dcjs.convertOpenAIToAnthropic.call(void 0, openaiRequest, config);
4780
+ const anthropicRequest = _chunkWYTEQ4Q5cjs.convertOpenAIToAnthropic.call(void 0, openaiRequest, config);
3931
4781
  const apiUrl = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: options.model, stream: false });
3932
4782
  const headers = _chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey);
3933
4783
  logger.info("Calling Anthropic completion API", { url: apiUrl, model: options.model });
@@ -3944,7 +4794,7 @@ async function callAnthropicCompletion(provider, apiKey, options, logger) {
3944
4794
  };
3945
4795
  }
3946
4796
  const anthropicResponse = await response.json();
3947
- const openaiResponse = _chunkSUEGJ75Dcjs.convertAnthropicToOpenAI.call(void 0, anthropicResponse);
4797
+ const openaiResponse = _chunkWYTEQ4Q5cjs.convertAnthropicToOpenAI.call(void 0, anthropicResponse);
3948
4798
  const choice = openaiResponse.choices[0];
3949
4799
  return {
3950
4800
  success: true,
@@ -3975,7 +4825,7 @@ async function callGeminiCompletion(provider, apiKey, options, logger) {
3975
4825
  const request = {
3976
4826
  contents,
3977
4827
  generationConfig: {
3978
- ...options.maxTokens ? { maxOutputTokens: options.maxTokens } : {},
4828
+ ...options.maxTokens !== void 0 ? { maxOutputTokens: options.maxTokens } : {},
3979
4829
  ...options.temperature !== void 0 ? { temperature: options.temperature } : {}
3980
4830
  }
3981
4831
  };
@@ -4008,7 +4858,7 @@ async function callGeminiCompletion(provider, apiKey, options, logger) {
4008
4858
  const candidate = candidates[0];
4009
4859
  const content = candidate.content;
4010
4860
  let textContent = "";
4011
- if (_optionalChain([content, 'optionalAccess', _149 => _149.parts])) {
4861
+ if (_optionalChain([content, 'optionalAccess', _187 => _187.parts])) {
4012
4862
  for (const part of content.parts) {
4013
4863
  if (part.text) {
4014
4864
  textContent += part.text;
@@ -4044,7 +4894,7 @@ async function callOpenAIResponseCompletion(provider, apiKey, options, logger) {
4044
4894
  model: options.model,
4045
4895
  input,
4046
4896
  stream: false,
4047
- ...options.maxTokens ? { max_output_tokens: options.maxTokens } : {},
4897
+ ...options.maxTokens !== void 0 ? { max_output_tokens: options.maxTokens } : {},
4048
4898
  ...options.temperature !== void 0 ? { temperature: options.temperature } : {}
4049
4899
  };
4050
4900
  if (options.thinkLevel && options.thinkLevel !== "none") {
@@ -4109,7 +4959,7 @@ async function streamOpenAICompletion(provider, apiKey, options, messageId, call
4109
4959
  model: options.model,
4110
4960
  messages: options.messages.map((m) => convertMessageToOpenAI(m)),
4111
4961
  // Only set max_tokens if explicitly provided, otherwise let API use its default
4112
- ...options.maxTokens ? { max_tokens: options.maxTokens } : {},
4962
+ ...options.maxTokens !== void 0 ? { max_tokens: options.maxTokens } : {},
4113
4963
  temperature: options.temperature,
4114
4964
  stream: true
4115
4965
  };
@@ -4141,7 +4991,7 @@ async function streamOpenAICompletion(provider, apiKey, options, messageId, call
4141
4991
  });
4142
4992
  if (!response.ok) {
4143
4993
  const errorText = await response.text();
4144
- _optionalChain([callbacks, 'access', _150 => _150.onError, 'optionalCall', _151 => _151(`API error (${response.status}): ${errorText}`)]);
4994
+ _optionalChain([callbacks, 'access', _188 => _188.onError, 'optionalCall', _189 => _189(`API error (${response.status}): ${errorText}`)]);
4145
4995
  return;
4146
4996
  }
4147
4997
  const result = await _chunkHQP3K7PUcjs.streamSSEResponse.call(void 0, response, "openai", {
@@ -4151,7 +5001,7 @@ async function streamOpenAICompletion(provider, apiKey, options, messageId, call
4151
5001
  onVideo: callbacks.onVideo,
4152
5002
  onError: callbacks.onError
4153
5003
  });
4154
- _optionalChain([callbacks, 'access', _152 => _152.onDone, 'optionalCall', _153 => _153(
5004
+ _optionalChain([callbacks, 'access', _190 => _190.onDone, 'optionalCall', _191 => _191(
4155
5005
  {
4156
5006
  id: messageId,
4157
5007
  role: "assistant",
@@ -4168,7 +5018,7 @@ async function streamOpenAICompletion(provider, apiKey, options, messageId, call
4168
5018
  async function streamAnthropicCompletion(provider, apiKey, options, messageId, callbacks, logger) {
4169
5019
  const hasImages = options.messages.some((m) => m.images && m.images.length > 0);
4170
5020
  const MAX_TOKENS_FOR_THINKING = 16384;
4171
- let effectiveMaxTokens = options.maxTokens || 16384;
5021
+ let effectiveMaxTokens = _nullishCoalesce(options.maxTokens, () => ( 16384));
4172
5022
  const thinkingMaxTokens = options.thinkLevel && options.thinkLevel !== "none" ? Math.min(effectiveMaxTokens, MAX_TOKENS_FOR_THINKING) : effectiveMaxTokens;
4173
5023
  const thinkingConfig = options.thinkLevel && options.thinkLevel !== "none" ? _thinkingconfig.buildAnthropicThinking.call(void 0, options.model, options.thinkLevel, thinkingMaxTokens) : void 0;
4174
5024
  if (thinkingConfig) {
@@ -4209,7 +5059,7 @@ async function streamAnthropicCompletion(provider, apiKey, options, messageId, c
4209
5059
  temperature: thinkingConfig ? void 0 : options.temperature,
4210
5060
  stream: true
4211
5061
  };
4212
- anthropicRequest = _chunkSUEGJ75Dcjs.convertOpenAIToAnthropic.call(void 0, openaiRequest, config);
5062
+ anthropicRequest = _chunkWYTEQ4Q5cjs.convertOpenAIToAnthropic.call(void 0, openaiRequest, config);
4213
5063
  if (thinkingConfig) {
4214
5064
  anthropicRequest.thinking = thinkingConfig;
4215
5065
  delete anthropicRequest.temperature;
@@ -4223,7 +5073,7 @@ async function streamAnthropicCompletion(provider, apiKey, options, messageId, c
4223
5073
  logger.info("Streaming Anthropic completion request", {
4224
5074
  url: apiUrl,
4225
5075
  model: anthropicRequest.model,
4226
- messagesCount: _optionalChain([anthropicRequest, 'access', _154 => _154.messages, 'optionalAccess', _155 => _155.length]),
5076
+ messagesCount: _optionalChain([anthropicRequest, 'access', _192 => _192.messages, 'optionalAccess', _193 => _193.length]),
4227
5077
  max_tokens: anthropicRequest.max_tokens,
4228
5078
  temperature: anthropicRequest.temperature,
4229
5079
  stream: anthropicRequest.stream,
@@ -4240,7 +5090,7 @@ async function streamAnthropicCompletion(provider, apiKey, options, messageId, c
4240
5090
  if (!response.ok) {
4241
5091
  const errorText = await response.text();
4242
5092
  logger.error("Anthropic API error", void 0, { status: response.status, errorText });
4243
- _optionalChain([callbacks, 'access', _156 => _156.onError, 'optionalCall', _157 => _157(`API error (${response.status}): ${errorText}`)]);
5093
+ _optionalChain([callbacks, 'access', _194 => _194.onError, 'optionalCall', _195 => _195(`API error (${response.status}): ${errorText}`)]);
4244
5094
  return;
4245
5095
  }
4246
5096
  const result = await _chunkHQP3K7PUcjs.streamSSEResponse.call(void 0, response, "anthropic", {
@@ -4251,10 +5101,10 @@ async function streamAnthropicCompletion(provider, apiKey, options, messageId, c
4251
5101
  });
4252
5102
  logger.info("Anthropic stream complete", {
4253
5103
  contentLength: result.content.length,
4254
- reasoningLength: _optionalChain([result, 'access', _158 => _158.reasoning, 'optionalAccess', _159 => _159.length]) || 0,
5104
+ reasoningLength: _optionalChain([result, 'access', _196 => _196.reasoning, 'optionalAccess', _197 => _197.length]) || 0,
4255
5105
  blocksCount: result.blocks.length
4256
5106
  });
4257
- _optionalChain([callbacks, 'access', _160 => _160.onDone, 'optionalCall', _161 => _161(
5107
+ _optionalChain([callbacks, 'access', _198 => _198.onDone, 'optionalCall', _199 => _199(
4258
5108
  {
4259
5109
  id: messageId,
4260
5110
  role: "assistant",
@@ -4280,7 +5130,7 @@ async function streamGeminiCompletion(provider, apiKey, options, messageId, call
4280
5130
  const request = {
4281
5131
  contents,
4282
5132
  generationConfig: {
4283
- ...options.maxTokens ? { maxOutputTokens: options.maxTokens } : {},
5133
+ ...options.maxTokens !== void 0 ? { maxOutputTokens: options.maxTokens } : {},
4284
5134
  ...options.temperature !== void 0 ? { temperature: options.temperature } : {}
4285
5135
  }
4286
5136
  };
@@ -4310,7 +5160,7 @@ async function streamGeminiCompletion(provider, apiKey, options, messageId, call
4310
5160
  if (!response.ok) {
4311
5161
  const errorText = await response.text();
4312
5162
  logger.error("Gemini API error", void 0, { status: response.status, errorText });
4313
- _optionalChain([callbacks, 'access', _162 => _162.onError, 'optionalCall', _163 => _163(`API error (${response.status}): ${errorText}`)]);
5163
+ _optionalChain([callbacks, 'access', _200 => _200.onError, 'optionalCall', _201 => _201(`API error (${response.status}): ${errorText}`)]);
4314
5164
  return;
4315
5165
  }
4316
5166
  const result = await _chunkHQP3K7PUcjs.streamSSEResponse.call(void 0, response, "gemini", {
@@ -4319,7 +5169,7 @@ async function streamGeminiCompletion(provider, apiKey, options, messageId, call
4319
5169
  onError: callbacks.onError
4320
5170
  });
4321
5171
  logger.info("Gemini stream complete", { contentLength: result.content.length });
4322
- _optionalChain([callbacks, 'access', _164 => _164.onDone, 'optionalCall', _165 => _165(
5172
+ _optionalChain([callbacks, 'access', _202 => _202.onDone, 'optionalCall', _203 => _203(
4323
5173
  {
4324
5174
  id: messageId,
4325
5175
  role: "assistant",
@@ -4344,7 +5194,7 @@ async function streamOpenAIResponseCompletion(provider, apiKey, options, message
4344
5194
  model: options.model,
4345
5195
  input,
4346
5196
  stream: true,
4347
- ...options.maxTokens ? { max_output_tokens: options.maxTokens } : {},
5197
+ ...options.maxTokens !== void 0 ? { max_output_tokens: options.maxTokens } : {},
4348
5198
  ...options.temperature !== void 0 ? { temperature: options.temperature } : {}
4349
5199
  };
4350
5200
  if (options.thinkLevel && options.thinkLevel !== "none") {
@@ -4371,7 +5221,7 @@ async function streamOpenAIResponseCompletion(provider, apiKey, options, message
4371
5221
  });
4372
5222
  if (!response.ok) {
4373
5223
  const errorText = await response.text();
4374
- _optionalChain([callbacks, 'access', _166 => _166.onError, 'optionalCall', _167 => _167(`API error (${response.status}): ${errorText}`)]);
5224
+ _optionalChain([callbacks, 'access', _204 => _204.onError, 'optionalCall', _205 => _205(`API error (${response.status}): ${errorText}`)]);
4375
5225
  return;
4376
5226
  }
4377
5227
  const result = await _chunkHQP3K7PUcjs.streamSSEResponse.call(void 0, response, "openai-response", {
@@ -4380,7 +5230,7 @@ async function streamOpenAIResponseCompletion(provider, apiKey, options, message
4380
5230
  onError: callbacks.onError
4381
5231
  });
4382
5232
  logger.info("OpenAI Response API stream complete", { contentLength: result.content.length });
4383
- _optionalChain([callbacks, 'access', _168 => _168.onDone, 'optionalCall', _169 => _169(
5233
+ _optionalChain([callbacks, 'access', _206 => _206.onDone, 'optionalCall', _207 => _207(
4384
5234
  {
4385
5235
  id: messageId,
4386
5236
  role: "assistant",
@@ -4401,59 +5251,20 @@ async function streamOpenAIResponseCompletion(provider, apiKey, options, message
4401
5251
 
4402
5252
 
4403
5253
 
4404
- async function resolveEffectiveMaxTokens(llmConfig, getProvider, logger, providerId, modelId, sessionMaxTokens) {
5254
+ async function resolveEffectiveMaxTokens(llmConfig, _getProvider, logger, _providerId, _modelId, sessionMaxTokens) {
4405
5255
  if (sessionMaxTokens !== void 0 && sessionMaxTokens > 0) {
4406
5256
  logger.debug("Using session maxTokens", { sessionMaxTokens });
4407
5257
  return sessionMaxTokens;
4408
5258
  }
4409
5259
  try {
4410
5260
  const globalParams = await llmConfig.getGlobalModelParameters();
4411
- if (_optionalChain([globalParams, 'optionalAccess', _170 => _170.maxTokens, 'optionalAccess', _171 => _171.enabled]) && globalParams.maxTokens.value > 0) {
5261
+ if (_optionalChain([globalParams, 'optionalAccess', _208 => _208.maxTokens, 'optionalAccess', _209 => _209.enabled]) && globalParams.maxTokens.value > 0) {
4412
5262
  logger.debug("Using global maxTokens", { maxTokens: globalParams.maxTokens.value });
4413
5263
  return globalParams.maxTokens.value;
4414
5264
  }
4415
5265
  } catch (err) {
4416
5266
  logger.warn("Failed to get global params", err instanceof Error ? err : void 0);
4417
5267
  }
4418
- const MAX_TOKENS_CAP = 131072;
4419
- const provider = await getProvider(providerId);
4420
- if (provider) {
4421
- const modelConfig = _optionalChain([provider, 'access', _172 => _172.modelConfigs, 'optionalAccess', _173 => _173.find, 'call', _174 => _174((m) => m.id === modelId)]);
4422
- if (_optionalChain([modelConfig, 'optionalAccess', _175 => _175.maxTokens]) && modelConfig.maxTokens > 0) {
4423
- const cappedMaxTokens = Math.min(modelConfig.maxTokens, MAX_TOKENS_CAP);
4424
- logger.debug("Using model config maxTokens", {
4425
- maxTokens: modelConfig.maxTokens,
4426
- cappedMaxTokens
4427
- });
4428
- return cappedMaxTokens;
4429
- }
4430
- if (provider.modelGroups) {
4431
- for (const group of provider.modelGroups) {
4432
- const model = _optionalChain([group, 'access', _176 => _176.models, 'optionalAccess', _177 => _177.find, 'call', _178 => _178((m) => m.id === modelId)]);
4433
- if (_optionalChain([model, 'optionalAccess', _179 => _179.maxTokens]) && model.maxTokens > 0) {
4434
- const cappedMaxTokens = Math.min(model.maxTokens, MAX_TOKENS_CAP);
4435
- logger.debug("Using modelGroup model maxTokens", {
4436
- maxTokens: model.maxTokens,
4437
- cappedMaxTokens
4438
- });
4439
- return cappedMaxTokens;
4440
- }
4441
- }
4442
- }
4443
- }
4444
- try {
4445
- const discoveredMaxTokens = await llmConfig.getDiscoveredModelMaxTokens(providerId, modelId);
4446
- if (discoveredMaxTokens && discoveredMaxTokens > 0) {
4447
- const cappedMaxTokens = Math.min(discoveredMaxTokens, MAX_TOKENS_CAP);
4448
- logger.debug("Using discovered model maxTokens", {
4449
- discoveredMaxTokens,
4450
- cappedMaxTokens
4451
- });
4452
- return cappedMaxTokens;
4453
- }
4454
- } catch (err) {
4455
- logger.warn("Failed to get discovered model maxTokens", err instanceof Error ? err : void 0);
4456
- }
4457
5268
  logger.debug("No maxTokens configured, returning undefined");
4458
5269
  return void 0;
4459
5270
  }
@@ -4475,7 +5286,7 @@ async function resolveThinkingBudget(getProvider, logger, providerId, modelId, m
4475
5286
  }
4476
5287
  const thinkingBudget = _thinkingconfig.calculateThinkingBudget.call(void 0, modelId, thinkLevel, maxTokens);
4477
5288
  const provider = await getProvider(providerId);
4478
- const providerName = _optionalChain([provider, 'optionalAccess', _180 => _180.name, 'optionalAccess', _181 => _181.toLowerCase, 'call', _182 => _182()]) || "";
5289
+ const providerName = _optionalChain([provider, 'optionalAccess', _210 => _210.name, 'optionalAccess', _211 => _211.toLowerCase, 'call', _212 => _212()]) || "";
4479
5290
  const apiFormat = provider ? _chunkA2YMUCBTcjs.resolveApiFormat.call(void 0, provider) : "openai";
4480
5291
  if (apiFormat === "anthropic" || providerName === "anthropic" || providerName.includes("claude")) {
4481
5292
  const thinkingConfig = _thinkingconfig.buildAnthropicThinking.call(void 0, modelId, thinkLevel, maxTokens);
@@ -4512,7 +5323,7 @@ function logToolFormat(tools, logger) {
4512
5323
  tools: openaiTools.map((t) => t.function.name),
4513
5324
  firstTool: {
4514
5325
  name: firstTool.function.name,
4515
- description: _optionalChain([firstTool, 'access', _183 => _183.function, 'access', _184 => _184.description, 'optionalAccess', _185 => _185.slice, 'call', _186 => _186(0, 100)]),
5326
+ description: _optionalChain([firstTool, 'access', _213 => _213.function, 'access', _214 => _214.description, 'optionalAccess', _215 => _215.slice, 'call', _216 => _216(0, 100)]),
4516
5327
  parameters: firstTool.function.parameters
4517
5328
  }
4518
5329
  });
@@ -4523,7 +5334,7 @@ function logToolFormat(tools, logger) {
4523
5334
  tools: anthropicTools.map((t) => t.name),
4524
5335
  firstTool: {
4525
5336
  name: firstTool.name,
4526
- description: _optionalChain([firstTool, 'access', _187 => _187.description, 'optionalAccess', _188 => _188.slice, 'call', _189 => _189(0, 100)]),
5337
+ description: _optionalChain([firstTool, 'access', _217 => _217.description, 'optionalAccess', _218 => _218.slice, 'call', _219 => _219(0, 100)]),
4527
5338
  input_schema: firstTool.input_schema
4528
5339
  }
4529
5340
  });
@@ -4534,9 +5345,9 @@ function logToolFormat(tools, logger) {
4534
5345
  count: allDeclarations.length,
4535
5346
  tools: allDeclarations.map((t) => t.name),
4536
5347
  firstTool: {
4537
- name: _optionalChain([allDeclarations, 'access', _190 => _190[0], 'optionalAccess', _191 => _191.name]),
4538
- description: _optionalChain([allDeclarations, 'access', _192 => _192[0], 'optionalAccess', _193 => _193.description, 'optionalAccess', _194 => _194.slice, 'call', _195 => _195(0, 100)]),
4539
- parameters: _optionalChain([allDeclarations, 'access', _196 => _196[0], 'optionalAccess', _197 => _197.parameters])
5348
+ name: _optionalChain([allDeclarations, 'access', _220 => _220[0], 'optionalAccess', _221 => _221.name]),
5349
+ description: _optionalChain([allDeclarations, 'access', _222 => _222[0], 'optionalAccess', _223 => _223.description, 'optionalAccess', _224 => _224.slice, 'call', _225 => _225(0, 100)]),
5350
+ parameters: _optionalChain([allDeclarations, 'access', _226 => _226[0], 'optionalAccess', _227 => _227.parameters])
4540
5351
  }
4541
5352
  });
4542
5353
  }
@@ -4556,7 +5367,8 @@ function buildToolRequest(apiFormat, conversationMessages, actualModel, options,
4556
5367
  }
4557
5368
  requestBody = {
4558
5369
  contents,
4559
- tools: options.tools
5370
+ tools: options.tools,
5371
+ ...options.maxTokens !== void 0 ? { generationConfig: { maxOutputTokens: options.maxTokens } } : {}
4560
5372
  };
4561
5373
  url = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: actualModel, stream: true });
4562
5374
  } else if (apiFormat === "anthropic") {
@@ -4566,7 +5378,10 @@ function buildToolRequest(apiFormat, conversationMessages, actualModel, options,
4566
5378
  role: m.role,
4567
5379
  content: m.content
4568
5380
  })),
4569
- max_tokens: options.maxTokens || 4096,
5381
+ // Native Anthropic Messages requires this field. Resolve an absent
5382
+ // caller cap to the model's real ceiling rather than a small constant —
5383
+ // see `resolveAnthropicMaxTokens`.
5384
+ max_tokens: _chunk4VLRHHFEcjs.resolveAnthropicMaxTokens.call(void 0, actualModel, options.maxTokens),
4570
5385
  temperature: _nullishCoalesce(options.temperature, () => ( 0.7)),
4571
5386
  stream: true,
4572
5387
  tools: options.tools
@@ -4583,7 +5398,7 @@ function buildToolRequest(apiFormat, conversationMessages, actualModel, options,
4583
5398
  role: m.role,
4584
5399
  content: m.content
4585
5400
  })),
4586
- max_tokens: options.maxTokens || 4096,
5401
+ ...options.maxTokens !== void 0 ? { max_tokens: options.maxTokens } : {},
4587
5402
  temperature: _nullishCoalesce(options.temperature, () => ( 0.7)),
4588
5403
  stream: true,
4589
5404
  tools: options.tools
@@ -4595,7 +5410,7 @@ function buildToolRequest(apiFormat, conversationMessages, actualModel, options,
4595
5410
  function extractDeltaContent(rawJson, apiFormat) {
4596
5411
  const json = rawJson;
4597
5412
  if (apiFormat === "google") {
4598
- const parts = _optionalChain([json, 'access', _198 => _198.candidates, 'optionalAccess', _199 => _199[0], 'optionalAccess', _200 => _200.content, 'optionalAccess', _201 => _201.parts]) || [];
5413
+ const parts = _optionalChain([json, 'access', _228 => _228.candidates, 'optionalAccess', _229 => _229[0], 'optionalAccess', _230 => _230.content, 'optionalAccess', _231 => _231.parts]) || [];
4599
5414
  let text = "";
4600
5415
  for (const part of parts) {
4601
5416
  if (part.thought === true) continue;
@@ -4603,15 +5418,15 @@ function extractDeltaContent(rawJson, apiFormat) {
4603
5418
  }
4604
5419
  return text;
4605
5420
  } else if (apiFormat === "anthropic") {
4606
- return _optionalChain([json, 'access', _202 => _202.delta, 'optionalAccess', _203 => _203.text]) || "";
5421
+ return _optionalChain([json, 'access', _232 => _232.delta, 'optionalAccess', _233 => _233.text]) || "";
4607
5422
  } else {
4608
- return _optionalChain([json, 'access', _204 => _204.choices, 'optionalAccess', _205 => _205[0], 'optionalAccess', _206 => _206.delta, 'optionalAccess', _207 => _207.content]) || "";
5423
+ return _optionalChain([json, 'access', _234 => _234.choices, 'optionalAccess', _235 => _235[0], 'optionalAccess', _236 => _236.delta, 'optionalAccess', _237 => _237.content]) || "";
4609
5424
  }
4610
5425
  }
4611
5426
  function extractDeltaReasoning(rawJson, apiFormat) {
4612
5427
  const json = rawJson;
4613
5428
  if (apiFormat === "google") {
4614
- const parts = _optionalChain([json, 'access', _208 => _208.candidates, 'optionalAccess', _209 => _209[0], 'optionalAccess', _210 => _210.content, 'optionalAccess', _211 => _211.parts]) || [];
5429
+ const parts = _optionalChain([json, 'access', _238 => _238.candidates, 'optionalAccess', _239 => _239[0], 'optionalAccess', _240 => _240.content, 'optionalAccess', _241 => _241.parts]) || [];
4615
5430
  let reasoning = "";
4616
5431
  for (const part of parts) {
4617
5432
  if (part.thought === true && part.text) reasoning += part.text;
@@ -4620,14 +5435,14 @@ function extractDeltaReasoning(rawJson, apiFormat) {
4620
5435
  } else if (apiFormat === "anthropic") {
4621
5436
  return "";
4622
5437
  } else {
4623
- const delta = _optionalChain([json, 'access', _212 => _212.choices, 'optionalAccess', _213 => _213[0], 'optionalAccess', _214 => _214.delta]);
4624
- return (_optionalChain([delta, 'optionalAccess', _215 => _215.thinking, 'optionalAccess', _216 => _216.content]) || "") + (_optionalChain([delta, 'optionalAccess', _217 => _217.reasoning_content]) || "");
5438
+ const delta = _optionalChain([json, 'access', _242 => _242.choices, 'optionalAccess', _243 => _243[0], 'optionalAccess', _244 => _244.delta]);
5439
+ return (_optionalChain([delta, 'optionalAccess', _245 => _245.thinking, 'optionalAccess', _246 => _246.content]) || "") + (_optionalChain([delta, 'optionalAccess', _247 => _247.reasoning_content]) || "");
4625
5440
  }
4626
5441
  }
4627
5442
  function extractToolCalls(rawJson, apiFormat, toolCalls, callbacks, logger, pendingOpenAIToolCalls) {
4628
5443
  const json = rawJson;
4629
5444
  if (apiFormat === "google") {
4630
- const parts = _optionalChain([json, 'access', _218 => _218.candidates, 'optionalAccess', _219 => _219[0], 'optionalAccess', _220 => _220.content, 'optionalAccess', _221 => _221.parts]) || [];
5445
+ const parts = _optionalChain([json, 'access', _248 => _248.candidates, 'optionalAccess', _249 => _249[0], 'optionalAccess', _250 => _250.content, 'optionalAccess', _251 => _251.parts]) || [];
4631
5446
  for (const part of parts) {
4632
5447
  if (part.functionCall) {
4633
5448
  logger.info("Function call detected", { functionCall: part.functionCall });
@@ -4637,13 +5452,13 @@ function extractToolCalls(rawJson, apiFormat, toolCalls, callbacks, logger, pend
4637
5452
  args: part.functionCall.args || {}
4638
5453
  };
4639
5454
  toolCalls.push(toolCall);
4640
- _optionalChain([callbacks, 'access', _222 => _222.onToolCall, 'optionalCall', _223 => _223(toolCall)]);
5455
+ _optionalChain([callbacks, 'access', _252 => _252.onToolCall, 'optionalCall', _253 => _253(toolCall)]);
4641
5456
  logger.info("Tool called", { toolName: toolCall.name });
4642
5457
  }
4643
5458
  }
4644
5459
  } else if (apiFormat !== "anthropic") {
4645
- const delta = _optionalChain([json, 'access', _224 => _224.choices, 'optionalAccess', _225 => _225[0], 'optionalAccess', _226 => _226.delta]);
4646
- if (_optionalChain([delta, 'optionalAccess', _227 => _227.tool_calls]) && pendingOpenAIToolCalls) {
5460
+ const delta = _optionalChain([json, 'access', _254 => _254.choices, 'optionalAccess', _255 => _255[0], 'optionalAccess', _256 => _256.delta]);
5461
+ if (_optionalChain([delta, 'optionalAccess', _257 => _257.tool_calls]) && pendingOpenAIToolCalls) {
4647
5462
  for (const tc of delta.tool_calls) {
4648
5463
  const index = _nullishCoalesce(tc.index, () => ( 0));
4649
5464
  let pending = pendingOpenAIToolCalls.get(index);
@@ -4652,8 +5467,8 @@ function extractToolCalls(rawJson, apiFormat, toolCalls, callbacks, logger, pend
4652
5467
  pendingOpenAIToolCalls.set(index, pending);
4653
5468
  }
4654
5469
  if (tc.id) pending.id = tc.id;
4655
- if (_optionalChain([tc, 'access', _228 => _228.function, 'optionalAccess', _229 => _229.name])) pending.name += tc.function.name;
4656
- if (_optionalChain([tc, 'access', _230 => _230.function, 'optionalAccess', _231 => _231.arguments])) pending.arguments += tc.function.arguments;
5470
+ if (_optionalChain([tc, 'access', _258 => _258.function, 'optionalAccess', _259 => _259.name])) pending.name += tc.function.name;
5471
+ if (_optionalChain([tc, 'access', _260 => _260.function, 'optionalAccess', _261 => _261.arguments])) pending.arguments += tc.function.arguments;
4657
5472
  }
4658
5473
  }
4659
5474
  }
@@ -4668,7 +5483,7 @@ function finalizeOpenAIToolCalls(pendingOpenAIToolCalls, toolCalls, callbacks, l
4668
5483
  args: JSON.parse(pending.arguments || "{}")
4669
5484
  };
4670
5485
  toolCalls.push(toolCall);
4671
- _optionalChain([callbacks, 'access', _232 => _232.onToolCall, 'optionalCall', _233 => _233(toolCall)]);
5486
+ _optionalChain([callbacks, 'access', _262 => _262.onToolCall, 'optionalCall', _263 => _263(toolCall)]);
4672
5487
  logger.info("Tool called (OpenAI)", { toolName: toolCall.name, args: toolCall.args });
4673
5488
  } catch (e) {
4674
5489
  logger.error("Failed to parse OpenAI tool call arguments", e instanceof Error ? e : void 0, {
@@ -4682,38 +5497,38 @@ function finalizeOpenAIToolCalls(pendingOpenAIToolCalls, toolCalls, callbacks, l
4682
5497
  function parseStreamChunk(rawJson, apiFormat, callbacks, logger) {
4683
5498
  const json = rawJson;
4684
5499
  if (apiFormat === "google") {
4685
- const candidate = _optionalChain([json, 'access', _234 => _234.candidates, 'optionalAccess', _235 => _235[0]]);
5500
+ const candidate = _optionalChain([json, 'access', _264 => _264.candidates, 'optionalAccess', _265 => _265[0]]);
4686
5501
  if (!candidate) {
4687
5502
  logger.warn("No candidate found in Gemini response");
4688
5503
  return;
4689
5504
  }
4690
- const parts = _optionalChain([candidate, 'access', _236 => _236.content, 'optionalAccess', _237 => _237.parts]) || [];
5505
+ const parts = _optionalChain([candidate, 'access', _266 => _266.content, 'optionalAccess', _267 => _267.parts]) || [];
4691
5506
  for (const part of parts) {
4692
5507
  if (part.thought === true && part.text) {
4693
- _optionalChain([callbacks, 'access', _238 => _238.onReasoning, 'optionalCall', _239 => _239(part.text)]);
5508
+ _optionalChain([callbacks, 'access', _268 => _268.onReasoning, 'optionalCall', _269 => _269(part.text)]);
4694
5509
  continue;
4695
5510
  } else if (part.thoughtSignature && !part.thought) {
4696
5511
  logger.debug("Gemini returned thoughtSignature without thought content");
4697
5512
  }
4698
5513
  if (part.text) {
4699
- _optionalChain([callbacks, 'access', _240 => _240.onDelta, 'optionalCall', _241 => _241(part.text)]);
5514
+ _optionalChain([callbacks, 'access', _270 => _270.onDelta, 'optionalCall', _271 => _271(part.text)]);
4700
5515
  }
4701
5516
  }
4702
5517
  } else if (apiFormat === "anthropic") {
4703
5518
  const delta = json.delta;
4704
- if (_optionalChain([delta, 'optionalAccess', _242 => _242.text])) {
4705
- _optionalChain([callbacks, 'access', _243 => _243.onDelta, 'optionalCall', _244 => _244(delta.text)]);
5519
+ if (_optionalChain([delta, 'optionalAccess', _272 => _272.text])) {
5520
+ _optionalChain([callbacks, 'access', _273 => _273.onDelta, 'optionalCall', _274 => _274(delta.text)]);
4706
5521
  }
4707
5522
  } else {
4708
- const delta = _optionalChain([json, 'access', _245 => _245.choices, 'optionalAccess', _246 => _246[0], 'optionalAccess', _247 => _247.delta]);
4709
- if (_optionalChain([delta, 'optionalAccess', _248 => _248.content])) {
4710
- _optionalChain([callbacks, 'access', _249 => _249.onDelta, 'optionalCall', _250 => _250(delta.content)]);
5523
+ const delta = _optionalChain([json, 'access', _275 => _275.choices, 'optionalAccess', _276 => _276[0], 'optionalAccess', _277 => _277.delta]);
5524
+ if (_optionalChain([delta, 'optionalAccess', _278 => _278.content])) {
5525
+ _optionalChain([callbacks, 'access', _279 => _279.onDelta, 'optionalCall', _280 => _280(delta.content)]);
4711
5526
  }
4712
- if (_optionalChain([delta, 'optionalAccess', _251 => _251.thinking, 'optionalAccess', _252 => _252.content])) {
4713
- _optionalChain([callbacks, 'access', _253 => _253.onReasoning, 'optionalCall', _254 => _254(delta.thinking.content)]);
5527
+ if (_optionalChain([delta, 'optionalAccess', _281 => _281.thinking, 'optionalAccess', _282 => _282.content])) {
5528
+ _optionalChain([callbacks, 'access', _283 => _283.onReasoning, 'optionalCall', _284 => _284(delta.thinking.content)]);
4714
5529
  }
4715
- if (_optionalChain([delta, 'optionalAccess', _255 => _255.reasoning_content])) {
4716
- _optionalChain([callbacks, 'access', _256 => _256.onReasoning, 'optionalCall', _257 => _257(delta.reasoning_content)]);
5530
+ if (_optionalChain([delta, 'optionalAccess', _285 => _285.reasoning_content])) {
5531
+ _optionalChain([callbacks, 'access', _286 => _286.onReasoning, 'optionalCall', _287 => _287(delta.reasoning_content)]);
4717
5532
  }
4718
5533
  }
4719
5534
  }
@@ -4726,7 +5541,7 @@ function buildIterationBlocks(iteration, content, reasoning, blocks, callbacks)
4726
5541
  content: reasoning
4727
5542
  };
4728
5543
  blocks.push(thinkingBlock);
4729
- _optionalChain([callbacks, 'access', _258 => _258.onBlock, 'optionalCall', _259 => _259(thinkingBlock)]);
5544
+ _optionalChain([callbacks, 'access', _288 => _288.onBlock, 'optionalCall', _289 => _289(thinkingBlock)]);
4730
5545
  }
4731
5546
  if (content && content.trim()) {
4732
5547
  const textBlock = {
@@ -4735,7 +5550,7 @@ function buildIterationBlocks(iteration, content, reasoning, blocks, callbacks)
4735
5550
  content
4736
5551
  };
4737
5552
  blocks.push(textBlock);
4738
- _optionalChain([callbacks, 'access', _260 => _260.onBlock, 'optionalCall', _261 => _261(textBlock)]);
5553
+ _optionalChain([callbacks, 'access', _290 => _290.onBlock, 'optionalCall', _291 => _291(textBlock)]);
4739
5554
  }
4740
5555
  }
4741
5556
  async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbacks, logger, builtinExecutor) {
@@ -4750,7 +5565,7 @@ async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbac
4750
5565
  status: "running"
4751
5566
  };
4752
5567
  blocks.push(toolUseBlock);
4753
- _optionalChain([callbacks, 'access', _262 => _262.onBlock, 'optionalCall', _263 => _263(toolUseBlock)]);
5568
+ _optionalChain([callbacks, 'access', _292 => _292.onBlock, 'optionalCall', _293 => _293(toolUseBlock)]);
4754
5569
  try {
4755
5570
  logger.info("Executing tool", { toolName: toolCall.name });
4756
5571
  const mcpTool = mcpTools.find((t) => t.id === toolCall.name);
@@ -4773,8 +5588,8 @@ async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbac
4773
5588
  result = { isError: true, content: [{ type: "text", text: "MCP service not available" }] };
4774
5589
  }
4775
5590
  logger.info("Tool result received", { result });
4776
- _optionalChain([callbacks, 'access', _264 => _264.onToolResult, 'optionalCall', _265 => _265(toolCall.id, result)]);
4777
- const resultText = _optionalChain([result, 'access', _266 => _266.content, 'optionalAccess', _267 => _267[0], 'optionalAccess', _268 => _268.text]) || JSON.stringify(result);
5591
+ _optionalChain([callbacks, 'access', _294 => _294.onToolResult, 'optionalCall', _295 => _295(toolCall.id, result)]);
5592
+ const resultText = _optionalChain([result, 'access', _296 => _296.content, 'optionalAccess', _297 => _297[0], 'optionalAccess', _298 => _298.text]) || JSON.stringify(result);
4778
5593
  const toolResultBlock = {
4779
5594
  id: `${toolCall.id}_result`,
4780
5595
  type: "tool_result",
@@ -4784,11 +5599,11 @@ async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbac
4784
5599
  isError: result.isError
4785
5600
  };
4786
5601
  blocks.push(toolResultBlock);
4787
- _optionalChain([callbacks, 'access', _269 => _269.onBlock, 'optionalCall', _270 => _270(toolResultBlock)]);
5602
+ _optionalChain([callbacks, 'access', _299 => _299.onBlock, 'optionalCall', _300 => _300(toolResultBlock)]);
4788
5603
  const toolUseBlockRef = blocks.find((b) => b.id === `${toolCall.id}_use`);
4789
5604
  if (toolUseBlockRef && toolUseBlockRef.type === "tool_use") {
4790
5605
  toolUseBlockRef.status = result.isError ? "error" : "completed";
4791
- _optionalChain([callbacks, 'access', _271 => _271.onBlock, 'optionalCall', _272 => _272({ ...toolUseBlockRef })]);
5606
+ _optionalChain([callbacks, 'access', _301 => _301.onBlock, 'optionalCall', _302 => _302({ ...toolUseBlockRef })]);
4792
5607
  }
4793
5608
  toolResults.push({ toolCall, result });
4794
5609
  } catch (error) {
@@ -4798,7 +5613,7 @@ async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbac
4798
5613
  isError: true,
4799
5614
  content: [{ type: "text", text: `Error: ${errorMessage}` }]
4800
5615
  };
4801
- _optionalChain([callbacks, 'access', _273 => _273.onToolResult, 'optionalCall', _274 => _274(toolCall.id, errorResult)]);
5616
+ _optionalChain([callbacks, 'access', _303 => _303.onToolResult, 'optionalCall', _304 => _304(toolCall.id, errorResult)]);
4802
5617
  const errorToolResultBlock = {
4803
5618
  id: `${toolCall.id}_result`,
4804
5619
  type: "tool_result",
@@ -4808,11 +5623,11 @@ async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbac
4808
5623
  isError: true
4809
5624
  };
4810
5625
  blocks.push(errorToolResultBlock);
4811
- _optionalChain([callbacks, 'access', _275 => _275.onBlock, 'optionalCall', _276 => _276(errorToolResultBlock)]);
5626
+ _optionalChain([callbacks, 'access', _305 => _305.onBlock, 'optionalCall', _306 => _306(errorToolResultBlock)]);
4812
5627
  const errorToolUseBlockRef = blocks.find((b) => b.id === `${toolCall.id}_use`);
4813
5628
  if (errorToolUseBlockRef && errorToolUseBlockRef.type === "tool_use") {
4814
5629
  errorToolUseBlockRef.status = "error";
4815
- _optionalChain([callbacks, 'access', _277 => _277.onBlock, 'optionalCall', _278 => _278({ ...errorToolUseBlockRef })]);
5630
+ _optionalChain([callbacks, 'access', _307 => _307.onBlock, 'optionalCall', _308 => _308({ ...errorToolUseBlockRef })]);
4816
5631
  }
4817
5632
  toolResults.push({ toolCall, result: errorResult });
4818
5633
  }
@@ -4822,7 +5637,7 @@ async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbac
4822
5637
  function mapToolArguments(args, mcpTool, logger) {
4823
5638
  const mappedArgs = { ...args };
4824
5639
  const toolSchema = mcpTool.inputSchema;
4825
- if (_optionalChain([toolSchema, 'optionalAccess', _279 => _279.properties])) {
5640
+ if (_optionalChain([toolSchema, 'optionalAccess', _309 => _309.properties])) {
4826
5641
  const expectedParams = Object.keys(toolSchema.properties);
4827
5642
  const paramMappings = {
4828
5643
  "search_query": ["query", "q", "searchQuery", "search"],
@@ -4856,25 +5671,25 @@ async function streamWithTools(options, callbacks, mcpService, llmConfig, getPro
4856
5671
  options.providerId,
4857
5672
  options.model
4858
5673
  );
4859
- const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _280 => _280.actualProviderId]) || options.providerId;
4860
- const actualModel = _optionalChain([routedInfo, 'optionalAccess', _281 => _281.actualModelId]) || options.model;
5674
+ const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _310 => _310.actualProviderId]) || options.providerId;
5675
+ const actualModel = _optionalChain([routedInfo, 'optionalAccess', _311 => _311.actualModelId]) || options.model;
4861
5676
  const provider = await getProvider(actualProviderId);
4862
5677
  if (!provider) {
4863
- _optionalChain([callbacks, 'access', _282 => _282.onError, 'optionalCall', _283 => _283(`Provider not found: ${actualProviderId}`)]);
5678
+ _optionalChain([callbacks, 'access', _312 => _312.onError, 'optionalCall', _313 => _313(`Provider not found: ${actualProviderId}`)]);
4864
5679
  return;
4865
5680
  }
4866
5681
  if (!provider.enabled) {
4867
- _optionalChain([callbacks, 'access', _284 => _284.onError, 'optionalCall', _285 => _285(`Provider is disabled: ${provider.name}`)]);
5682
+ _optionalChain([callbacks, 'access', _314 => _314.onError, 'optionalCall', _315 => _315(`Provider is disabled: ${provider.name}`)]);
4868
5683
  return;
4869
5684
  }
4870
5685
  const { apiKey: effectiveKey } = _chunkA2YMUCBTcjs.resolveProviderEndpoint.call(void 0, provider);
4871
5686
  const apiKey = resolveApiKey2(effectiveKey);
4872
5687
  if (!apiKey) {
4873
- _optionalChain([callbacks, 'access', _286 => _286.onError, 'optionalCall', _287 => _287("API key not configured")]);
5688
+ _optionalChain([callbacks, 'access', _316 => _316.onError, 'optionalCall', _317 => _317("API key not configured")]);
4874
5689
  return;
4875
5690
  }
4876
5691
  const messageId = `msg_${Date.now()}_${Math.random().toString(36).slice(2)}`;
4877
- _optionalChain([callbacks, 'access', _288 => _288.onStart, 'optionalCall', _289 => _289(messageId)]);
5692
+ _optionalChain([callbacks, 'access', _318 => _318.onStart, 'optionalCall', _319 => _319(messageId)]);
4878
5693
  const globalParams = await llmConfig.getGlobalModelParameters();
4879
5694
  const MAX_ITERATIONS = _nullishCoalesce(globalParams.toolMaxTurns, () => ( 100));
4880
5695
  let iteration = 0;
@@ -4921,12 +5736,12 @@ async function streamWithTools(options, callbacks, mcpService, llmConfig, getPro
4921
5736
  });
4922
5737
  if (!response.ok) {
4923
5738
  const errorText = await response.text();
4924
- _optionalChain([callbacks, 'access', _290 => _290.onError, 'optionalCall', _291 => _291(`API error (${response.status}): ${errorText}`)]);
5739
+ _optionalChain([callbacks, 'access', _320 => _320.onError, 'optionalCall', _321 => _321(`API error (${response.status}): ${errorText}`)]);
4925
5740
  return;
4926
5741
  }
4927
- const reader = _optionalChain([response, 'access', _292 => _292.body, 'optionalAccess', _293 => _293.getReader, 'call', _294 => _294()]);
5742
+ const reader = _optionalChain([response, 'access', _322 => _322.body, 'optionalAccess', _323 => _323.getReader, 'call', _324 => _324()]);
4928
5743
  if (!reader) {
4929
- _optionalChain([callbacks, 'access', _295 => _295.onError, 'optionalCall', _296 => _296("No response body")]);
5744
+ _optionalChain([callbacks, 'access', _325 => _325.onError, 'optionalCall', _326 => _326("No response body")]);
4930
5745
  return;
4931
5746
  }
4932
5747
  const decoder = new TextDecoder();
@@ -4959,7 +5774,7 @@ async function streamWithTools(options, callbacks, mcpService, llmConfig, getPro
4959
5774
  logger.debug("Parsed JSON", { json });
4960
5775
  if (json.error) {
4961
5776
  logger.error("API Error", void 0, { error: json.error });
4962
- _optionalChain([callbacks, 'access', _297 => _297.onError, 'optionalCall', _298 => _298(`API Error: ${json.error.message || JSON.stringify(json.error)}`)]);
5777
+ _optionalChain([callbacks, 'access', _327 => _327.onError, 'optionalCall', _328 => _328(`API Error: ${json.error.message || JSON.stringify(json.error)}`)]);
4963
5778
  return;
4964
5779
  }
4965
5780
  parseStreamChunk(json, apiFormat, callbacks, logger);
@@ -4992,7 +5807,7 @@ async function streamWithTools(options, callbacks, mcpService, llmConfig, getPro
4992
5807
  toolCallsLength: toolCalls.length,
4993
5808
  executableToolCallsLength: executableToolCalls.length,
4994
5809
  hasMcpTools: !!options.mcpTools,
4995
- mcpToolsLength: _optionalChain([options, 'access', _299 => _299.mcpTools, 'optionalAccess', _300 => _300.length]),
5810
+ mcpToolsLength: _optionalChain([options, 'access', _329 => _329.mcpTools, 'optionalAccess', _330 => _330.length]),
4996
5811
  hasMcpService: !!mcpService
4997
5812
  });
4998
5813
  if (executableToolCalls.length > 0 && options.mcpTools && (mcpService || builtinExecutor)) {
@@ -5013,7 +5828,7 @@ async function streamWithTools(options, callbacks, mcpService, llmConfig, getPro
5013
5828
  builtinExecutor
5014
5829
  );
5015
5830
  const toolResultsText = toolResults.map(({ toolCall, result }) => {
5016
- const resultText = typeof result === "string" ? result : _optionalChain([result, 'access', _301 => _301.content, 'optionalAccess', _302 => _302[0], 'optionalAccess', _303 => _303.text]) || JSON.stringify(result);
5831
+ const resultText = typeof result === "string" ? result : _optionalChain([result, 'access', _331 => _331.content, 'optionalAccess', _332 => _332[0], 'optionalAccess', _333 => _333.text]) || JSON.stringify(result);
5017
5832
  return `Tool ${toolCall.name} result:
5018
5833
  ${resultText}`;
5019
5834
  }).join("\n\n");
@@ -5031,12 +5846,12 @@ ${resultText}`;
5031
5846
  }
5032
5847
  } catch (streamError) {
5033
5848
  logger.error("Stream processing error", streamError instanceof Error ? streamError : void 0);
5034
- _optionalChain([callbacks, 'access', _304 => _304.onError, 'optionalCall', _305 => _305(`Stream error: ${streamError instanceof Error ? streamError.message : "Unknown error"}`)]);
5849
+ _optionalChain([callbacks, 'access', _334 => _334.onError, 'optionalCall', _335 => _335(`Stream error: ${streamError instanceof Error ? streamError.message : "Unknown error"}`)]);
5035
5850
  return;
5036
5851
  }
5037
5852
  }
5038
5853
  logger.info("Sending final callback", { blocksCount: blocks.length });
5039
- _optionalChain([callbacks, 'access', _306 => _306.onDone, 'optionalCall', _307 => _307({
5854
+ _optionalChain([callbacks, 'access', _336 => _336.onDone, 'optionalCall', _337 => _337({
5040
5855
  id: messageId,
5041
5856
  role: "assistant",
5042
5857
  content: finalContent,
@@ -5047,7 +5862,7 @@ ${resultText}`;
5047
5862
  } catch (error) {
5048
5863
  logger.error("Error in streamWithTools", error instanceof Error ? error : void 0);
5049
5864
  const message = error instanceof Error ? error.message : "Unknown error";
5050
- _optionalChain([callbacks, 'access', _308 => _308.onError, 'optionalCall', _309 => _309(message)]);
5865
+ _optionalChain([callbacks, 'access', _338 => _338.onError, 'optionalCall', _339 => _339(message)]);
5051
5866
  }
5052
5867
  }
5053
5868
 
@@ -5073,21 +5888,33 @@ function readUsageFromOpenAIResponse(usage) {
5073
5888
  var sharedExecutor2 = null;
5074
5889
  function getSharedExecutor2() {
5075
5890
  if (!sharedExecutor2) {
5076
- sharedExecutor2 = new (0, _chunk46ZIFWYGcjs.TransformerChainExecutor)();
5891
+ sharedExecutor2 = new (0, _chunkIIRPUVPHcjs.TransformerChainExecutor)();
5077
5892
  }
5078
5893
  return sharedExecutor2;
5079
5894
  }
5080
5895
  async function resolveChainWithMain(llmConfig, providerId, model) {
5081
5896
  return _chunkQXD4MV2Xcjs.resolveProviderChain.call(void 0, llmConfig, providerId, model);
5082
5897
  }
5898
+ function buildUnifiedCompletionRequest(actualModel, options, stream) {
5899
+ return {
5900
+ model: actualModel,
5901
+ messages: options.messages.map((m) => ({
5902
+ role: m.role,
5903
+ content: m.content
5904
+ })),
5905
+ ...options.maxTokens !== void 0 ? { max_tokens: options.maxTokens } : {},
5906
+ temperature: options.temperature,
5907
+ stream
5908
+ };
5909
+ }
5083
5910
  async function completeWithTransformers(options, llmConfig, getProvider, resolveApiKey2, completeFallback, logger, recording) {
5084
5911
  try {
5085
5912
  const routedInfo = await llmConfig.resolveRoutedModel(
5086
5913
  options.providerId,
5087
5914
  options.model
5088
5915
  );
5089
- const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _310 => _310.actualProviderId]) || options.providerId;
5090
- const actualModel = _optionalChain([routedInfo, 'optionalAccess', _311 => _311.actualModelId]) || options.model;
5916
+ const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _340 => _340.actualProviderId]) || options.providerId;
5917
+ const actualModel = _optionalChain([routedInfo, 'optionalAccess', _341 => _341.actualModelId]) || options.model;
5091
5918
  const provider = await getProvider(actualProviderId);
5092
5919
  if (!provider) {
5093
5920
  return { success: false, error: `Provider not found: ${actualProviderId}` };
@@ -5108,16 +5935,11 @@ async function completeWithTransformers(options, llmConfig, getProvider, resolve
5108
5935
  if (!hasTransformers) {
5109
5936
  return completeFallback(options);
5110
5937
  }
5111
- const unifiedRequest = {
5112
- model: actualModel,
5113
- messages: options.messages.map((m) => ({
5114
- role: m.role,
5115
- content: m.content
5116
- })),
5117
- max_tokens: options.maxTokens || 4096,
5118
- temperature: options.temperature,
5119
- stream: _nullishCoalesce(options.stream, () => ( false))
5120
- };
5938
+ const unifiedRequest = buildUnifiedCompletionRequest(
5939
+ actualModel,
5940
+ options,
5941
+ _nullishCoalesce(options.stream, () => ( false))
5942
+ );
5121
5943
  const transformerProvider = {
5122
5944
  name: provider.name,
5123
5945
  baseUrl: provider.api_base_url,
@@ -5125,7 +5947,7 @@ async function completeWithTransformers(options, llmConfig, getProvider, resolve
5125
5947
  models: provider.models || []
5126
5948
  };
5127
5949
  const executor = getSharedExecutor2();
5128
- const { response } = await _chunkHYN75H6Gcjs.executeProviderCall.call(void 0, {
5950
+ const { response } = await _chunkMUHWHQVMcjs.executeProviderCall.call(void 0, {
5129
5951
  executor,
5130
5952
  request: unifiedRequest,
5131
5953
  provider: transformerProvider,
@@ -5168,18 +5990,18 @@ async function completeWithTransformers(options, llmConfig, getProvider, resolve
5168
5990
  { endpointTransformer: void 0 }
5169
5991
  );
5170
5992
  const data = await transformedResponse.json();
5171
- const choice = _optionalChain([data, 'access', _312 => _312.choices, 'optionalAccess', _313 => _313[0]]);
5993
+ const choice = _optionalChain([data, 'access', _342 => _342.choices, 'optionalAccess', _343 => _343[0]]);
5172
5994
  if (!choice) {
5173
5995
  return { success: false, error: "No choices in response" };
5174
5996
  }
5175
- const rawToolCalls = _optionalChain([choice, 'access', _314 => _314.message, 'optionalAccess', _315 => _315.tool_calls]);
5176
- const toolCalls = _optionalChain([rawToolCalls, 'optionalAccess', _316 => _316.map, 'call', _317 => _317((tc) => ({
5997
+ const rawToolCalls = _optionalChain([choice, 'access', _344 => _344.message, 'optionalAccess', _345 => _345.tool_calls]);
5998
+ const toolCalls = _optionalChain([rawToolCalls, 'optionalAccess', _346 => _346.map, 'call', _347 => _347((tc) => ({
5177
5999
  id: tc.id,
5178
6000
  name: tc.function.name,
5179
6001
  args: typeof tc.function.arguments === "string" ? JSON.parse(tc.function.arguments) : tc.function.arguments
5180
6002
  }))]);
5181
6003
  const tapped = readUsageFromOpenAIResponse(data.usage);
5182
- if (_optionalChain([recording, 'optionalAccess', _318 => _318.recorder]) && tapped) {
6004
+ if (_optionalChain([recording, 'optionalAccess', _348 => _348.recorder]) && tapped) {
5183
6005
  recording.recorder.record({
5184
6006
  messageId: _nullishCoalesce(options.messageId, () => ( null)),
5185
6007
  parentMessageId: _nullishCoalesce(options.parentMessageId, () => ( null)),
@@ -5197,9 +6019,9 @@ async function completeWithTransformers(options, llmConfig, getProvider, resolve
5197
6019
  message: {
5198
6020
  id: `msg_${Date.now()}`,
5199
6021
  role: "assistant",
5200
- content: _optionalChain([choice, 'access', _319 => _319.message, 'optionalAccess', _320 => _320.content]) || "",
6022
+ content: _optionalChain([choice, 'access', _349 => _349.message, 'optionalAccess', _350 => _350.content]) || "",
5201
6023
  timestamp: Date.now(),
5202
- thinking: data.reasoning_content || _optionalChain([choice, 'access', _321 => _321.message, 'optionalAccess', _322 => _322.thinking, 'optionalAccess', _323 => _323.content]) ? { content: data.reasoning_content || _optionalChain([choice, 'access', _324 => _324.message, 'optionalAccess', _325 => _325.thinking, 'optionalAccess', _326 => _326.content]) || "", signature: _optionalChain([choice, 'access', _327 => _327.message, 'optionalAccess', _328 => _328.thinking, 'optionalAccess', _329 => _329.signature]) } : void 0,
6024
+ thinking: data.reasoning_content || _optionalChain([choice, 'access', _351 => _351.message, 'optionalAccess', _352 => _352.thinking, 'optionalAccess', _353 => _353.content]) ? { content: data.reasoning_content || _optionalChain([choice, 'access', _354 => _354.message, 'optionalAccess', _355 => _355.thinking, 'optionalAccess', _356 => _356.content]) || "", signature: _optionalChain([choice, 'access', _357 => _357.message, 'optionalAccess', _358 => _358.thinking, 'optionalAccess', _359 => _359.signature]) } : void 0,
5203
6025
  toolCalls
5204
6026
  },
5205
6027
  usage: data.usage ? {
@@ -5220,21 +6042,21 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
5220
6042
  options.providerId,
5221
6043
  options.model
5222
6044
  );
5223
- const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _330 => _330.actualProviderId]) || options.providerId;
5224
- const actualModel = _optionalChain([routedInfo, 'optionalAccess', _331 => _331.actualModelId]) || options.model;
6045
+ const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _360 => _360.actualProviderId]) || options.providerId;
6046
+ const actualModel = _optionalChain([routedInfo, 'optionalAccess', _361 => _361.actualModelId]) || options.model;
5225
6047
  const provider = await getProvider(actualProviderId);
5226
6048
  if (!provider) {
5227
- _optionalChain([callbacks, 'access', _332 => _332.onError, 'optionalCall', _333 => _333(`Provider not found: ${actualProviderId}`)]);
6049
+ _optionalChain([callbacks, 'access', _362 => _362.onError, 'optionalCall', _363 => _363(`Provider not found: ${actualProviderId}`)]);
5228
6050
  return;
5229
6051
  }
5230
6052
  if (!provider.enabled) {
5231
- _optionalChain([callbacks, 'access', _334 => _334.onError, 'optionalCall', _335 => _335(`Provider is disabled: ${provider.name}`)]);
6053
+ _optionalChain([callbacks, 'access', _364 => _364.onError, 'optionalCall', _365 => _365(`Provider is disabled: ${provider.name}`)]);
5232
6054
  return;
5233
6055
  }
5234
6056
  const { apiKey: effectiveKey } = _chunkA2YMUCBTcjs.resolveProviderEndpoint.call(void 0, provider);
5235
6057
  const apiKey = resolveApiKey2(effectiveKey);
5236
6058
  if (!apiKey) {
5237
- _optionalChain([callbacks, 'access', _336 => _336.onError, 'optionalCall', _337 => _337("API key not configured")]);
6059
+ _optionalChain([callbacks, 'access', _366 => _366.onError, 'optionalCall', _367 => _367("API key not configured")]);
5238
6060
  return;
5239
6061
  }
5240
6062
  const { chain, hasTransformers } = await resolveChainWithMain(
@@ -5246,17 +6068,8 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
5246
6068
  return completeStreamFallback(options, callbacks);
5247
6069
  }
5248
6070
  const messageId = `msg_${Date.now()}`;
5249
- _optionalChain([callbacks, 'access', _338 => _338.onStart, 'optionalCall', _339 => _339(messageId)]);
5250
- const unifiedRequest = {
5251
- model: actualModel,
5252
- messages: options.messages.map((m) => ({
5253
- role: m.role,
5254
- content: m.content
5255
- })),
5256
- max_tokens: options.maxTokens || 4096,
5257
- temperature: options.temperature,
5258
- stream: true
5259
- };
6071
+ _optionalChain([callbacks, 'access', _368 => _368.onStart, 'optionalCall', _369 => _369(messageId)]);
6072
+ const unifiedRequest = buildUnifiedCompletionRequest(actualModel, options, true);
5260
6073
  const transformerProvider = {
5261
6074
  name: provider.name,
5262
6075
  baseUrl: provider.api_base_url,
@@ -5264,7 +6077,7 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
5264
6077
  models: provider.models || []
5265
6078
  };
5266
6079
  const executor = getSharedExecutor2();
5267
- const { response } = await _chunkHYN75H6Gcjs.executeProviderCall.call(void 0, {
6080
+ const { response } = await _chunkMUHWHQVMcjs.executeProviderCall.call(void 0, {
5268
6081
  executor,
5269
6082
  request: unifiedRequest,
5270
6083
  provider: transformerProvider,
@@ -5294,7 +6107,7 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
5294
6107
  });
5295
6108
  if (!response.ok) {
5296
6109
  const errorText = await response.text();
5297
- _optionalChain([callbacks, 'access', _340 => _340.onError, 'optionalCall', _341 => _341(`API error (${response.status}): ${errorText}`)]);
6110
+ _optionalChain([callbacks, 'access', _370 => _370.onError, 'optionalCall', _371 => _371(`API error (${response.status}): ${errorText}`)]);
5298
6111
  return;
5299
6112
  }
5300
6113
  const transformedResponse = await executor.executeResponseChain(
@@ -5304,9 +6117,9 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
5304
6117
  chain,
5305
6118
  { endpointTransformer: void 0 }
5306
6119
  );
5307
- const reader = _optionalChain([transformedResponse, 'access', _342 => _342.body, 'optionalAccess', _343 => _343.getReader, 'call', _344 => _344()]);
6120
+ const reader = _optionalChain([transformedResponse, 'access', _372 => _372.body, 'optionalAccess', _373 => _373.getReader, 'call', _374 => _374()]);
5308
6121
  if (!reader) {
5309
- _optionalChain([callbacks, 'access', _345 => _345.onError, 'optionalCall', _346 => _346("No response body")]);
6122
+ _optionalChain([callbacks, 'access', _375 => _375.onError, 'optionalCall', _376 => _376("No response body")]);
5310
6123
  return;
5311
6124
  }
5312
6125
  const decoder = new TextDecoder();
@@ -5324,22 +6137,22 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
5324
6137
  if (data === "[DONE]") continue;
5325
6138
  try {
5326
6139
  const json = JSON.parse(data);
5327
- const delta = _optionalChain([json, 'access', _347 => _347.choices, 'optionalAccess', _348 => _348[0], 'optionalAccess', _349 => _349.delta]);
5328
- if (_optionalChain([delta, 'optionalAccess', _350 => _350.content])) {
6140
+ const delta = _optionalChain([json, 'access', _377 => _377.choices, 'optionalAccess', _378 => _378[0], 'optionalAccess', _379 => _379.delta]);
6141
+ if (_optionalChain([delta, 'optionalAccess', _380 => _380.content])) {
5329
6142
  content += delta.content;
5330
- _optionalChain([callbacks, 'access', _351 => _351.onDelta, 'optionalCall', _352 => _352(delta.content)]);
6143
+ _optionalChain([callbacks, 'access', _381 => _381.onDelta, 'optionalCall', _382 => _382(delta.content)]);
5331
6144
  }
5332
- if (_optionalChain([delta, 'optionalAccess', _353 => _353.thinking, 'optionalAccess', _354 => _354.content])) {
6145
+ if (_optionalChain([delta, 'optionalAccess', _383 => _383.thinking, 'optionalAccess', _384 => _384.content])) {
5333
6146
  reasoning += delta.thinking.content;
5334
- _optionalChain([callbacks, 'access', _355 => _355.onReasoning, 'optionalCall', _356 => _356(delta.thinking.content)]);
6147
+ _optionalChain([callbacks, 'access', _385 => _385.onReasoning, 'optionalCall', _386 => _386(delta.thinking.content)]);
5335
6148
  }
5336
- if (_optionalChain([delta, 'optionalAccess', _357 => _357.reasoning_content])) {
6149
+ if (_optionalChain([delta, 'optionalAccess', _387 => _387.reasoning_content])) {
5337
6150
  reasoning += delta.reasoning_content;
5338
- _optionalChain([callbacks, 'access', _358 => _358.onReasoning, 'optionalCall', _359 => _359(delta.reasoning_content)]);
6151
+ _optionalChain([callbacks, 'access', _388 => _388.onReasoning, 'optionalCall', _389 => _389(delta.reasoning_content)]);
5339
6152
  }
5340
6153
  if (json.usage) {
5341
6154
  const tapped = readUsageFromOpenAIResponse(json.usage);
5342
- if (_optionalChain([recording, 'optionalAccess', _360 => _360.recorder]) && tapped) {
6155
+ if (_optionalChain([recording, 'optionalAccess', _390 => _390.recorder]) && tapped) {
5343
6156
  recording.recorder.record({
5344
6157
  messageId: _nullishCoalesce(options.messageId, () => ( null)),
5345
6158
  parentMessageId: _nullishCoalesce(options.parentMessageId, () => ( null)),
@@ -5352,7 +6165,7 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
5352
6165
  rawUsage: json.usage
5353
6166
  });
5354
6167
  }
5355
- _optionalChain([callbacks, 'access', _361 => _361.onDone, 'optionalCall', _362 => _362(
6168
+ _optionalChain([callbacks, 'access', _391 => _391.onDone, 'optionalCall', _392 => _392(
5356
6169
  {
5357
6170
  id: messageId,
5358
6171
  role: "assistant",
@@ -5373,7 +6186,7 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
5373
6186
  }
5374
6187
  }
5375
6188
  }
5376
- _optionalChain([callbacks, 'access', _363 => _363.onDone, 'optionalCall', _364 => _364({
6189
+ _optionalChain([callbacks, 'access', _393 => _393.onDone, 'optionalCall', _394 => _394({
5377
6190
  id: messageId,
5378
6191
  role: "assistant",
5379
6192
  content,
@@ -5385,13 +6198,13 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
5385
6198
  }
5386
6199
  } catch (error) {
5387
6200
  const message = error instanceof Error ? error.message : "Unknown error";
5388
- _optionalChain([callbacks, 'access', _365 => _365.onError, 'optionalCall', _366 => _366(message)]);
6201
+ _optionalChain([callbacks, 'access', _395 => _395.onError, 'optionalCall', _396 => _396(message)]);
5389
6202
  }
5390
6203
  }
5391
6204
 
5392
6205
  // src/completion/CompletionService.ts
5393
6206
  var CompletionService = (_class13 = class {
5394
- constructor(paths, llmConfig, logger) {;_class13.prototype.__init22.call(this);_class13.prototype.__init23.call(this);_class13.prototype.__init24.call(this);_class13.prototype.__init25.call(this);
6207
+ constructor(paths, llmConfig, logger) {;_class13.prototype.__init23.call(this);_class13.prototype.__init24.call(this);_class13.prototype.__init25.call(this);_class13.prototype.__init26.call(this);
5395
6208
  this.paths = paths;
5396
6209
  this.llmConfig = llmConfig;
5397
6210
  this.logger = logger;
@@ -5399,10 +6212,10 @@ var CompletionService = (_class13 = class {
5399
6212
 
5400
6213
 
5401
6214
 
5402
- __init22() {this.apiKeyPool = null}
5403
- __init23() {this.usageRecorder = null}
5404
- __init24() {this.usageEventSink = null}
5405
- __init25() {this.visionFallbackProvider = null}
6215
+ __init23() {this.apiKeyPool = null}
6216
+ __init24() {this.usageRecorder = null}
6217
+ __init25() {this.usageEventSink = null}
6218
+ __init26() {this.visionFallbackProvider = null}
5406
6219
  /**
5407
6220
  * Set the API key pool service for multi-key load balancing.
5408
6221
  * When set, keys are resolved via the pool instead of directly from the provider.
@@ -5452,8 +6265,8 @@ var CompletionService = (_class13 = class {
5452
6265
  options.providerId,
5453
6266
  options.model
5454
6267
  );
5455
- const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _367 => _367.actualProviderId]) || options.providerId;
5456
- const actualModel = _optionalChain([routedInfo, 'optionalAccess', _368 => _368.actualModelId]) || options.model;
6268
+ const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _397 => _397.actualProviderId]) || options.providerId;
6269
+ const actualModel = _optionalChain([routedInfo, 'optionalAccess', _398 => _398.actualModelId]) || options.model;
5457
6270
  const provider = await this.getProvider(actualProviderId);
5458
6271
  if (!provider) {
5459
6272
  return { success: false, error: `Provider not found: ${actualProviderId}` };
@@ -5486,7 +6299,7 @@ var CompletionService = (_class13 = class {
5486
6299
  this.apiKeyPool.reportSuccess(options.sessionId);
5487
6300
  }
5488
6301
  if (result.success && result.usage && options.sessionId) {
5489
- _optionalChain([this, 'access', _369 => _369.usageEventSink, 'optionalAccess', _370 => _370.emit, 'call', _371 => _371({
6302
+ _optionalChain([this, 'access', _399 => _399.usageEventSink, 'optionalAccess', _400 => _400.emit, 'call', _401 => _401({
5490
6303
  sessionId: options.sessionId,
5491
6304
  modelId: actualModel,
5492
6305
  usage: result.usage,
@@ -5515,8 +6328,8 @@ var CompletionService = (_class13 = class {
5515
6328
  options.model
5516
6329
  );
5517
6330
  this.logger.debug("Resolved routed model", { routedInfo });
5518
- const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _372 => _372.actualProviderId]) || options.providerId;
5519
- const actualModel = _optionalChain([routedInfo, 'optionalAccess', _373 => _373.actualModelId]) || options.model;
6331
+ const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _402 => _402.actualProviderId]) || options.providerId;
6332
+ const actualModel = _optionalChain([routedInfo, 'optionalAccess', _403 => _403.actualModelId]) || options.model;
5520
6333
  this.logger.debug("Resolved provider and model", { actualProviderId, actualModel });
5521
6334
  const provider = await this.getProvider(actualProviderId);
5522
6335
  this.logger.debug("Retrieved provider", provider ? {
@@ -5528,22 +6341,22 @@ var CompletionService = (_class13 = class {
5528
6341
  enabled: provider.enabled
5529
6342
  } : { error: "Provider not found" });
5530
6343
  if (!provider) {
5531
- _optionalChain([callbacks, 'access', _374 => _374.onError, 'optionalCall', _375 => _375(`Provider not found: ${actualProviderId}`)]);
6344
+ _optionalChain([callbacks, 'access', _404 => _404.onError, 'optionalCall', _405 => _405(`Provider not found: ${actualProviderId}`)]);
5532
6345
  return;
5533
6346
  }
5534
6347
  if (!provider.enabled) {
5535
- _optionalChain([callbacks, 'access', _376 => _376.onError, 'optionalCall', _377 => _377(`Provider is disabled: ${provider.name}`)]);
6348
+ _optionalChain([callbacks, 'access', _406 => _406.onError, 'optionalCall', _407 => _407(`Provider is disabled: ${provider.name}`)]);
5536
6349
  return;
5537
6350
  }
5538
6351
  const apiKey = await this.resolveApiKeyForRequest(provider, actualProviderId, options.sessionId);
5539
6352
  if (!apiKey) {
5540
- _optionalChain([callbacks, 'access', _378 => _378.onError, 'optionalCall', _379 => _379("API key not configured")]);
6353
+ _optionalChain([callbacks, 'access', _408 => _408.onError, 'optionalCall', _409 => _409("API key not configured")]);
5541
6354
  return;
5542
6355
  }
5543
6356
  const apiFormat = _chunkA2YMUCBTcjs.resolveApiFormat.call(void 0, provider);
5544
6357
  this.logger.info("Using API format for stream", { apiFormat });
5545
6358
  const messageId = `msg_${Date.now()}`;
5546
- _optionalChain([callbacks, 'access', _380 => _380.onStart, 'optionalCall', _381 => _381(messageId)]);
6359
+ _optionalChain([callbacks, 'access', _410 => _410.onStart, 'optionalCall', _411 => _411(messageId)]);
5547
6360
  const resolvedOptions = { ...options, model: actualModel };
5548
6361
  if (options.sessionId) {
5549
6362
  const sid = options.sessionId;
@@ -5552,14 +6365,14 @@ var CompletionService = (_class13 = class {
5552
6365
  ...callbacks,
5553
6366
  onDone: (message, usage, metrics) => {
5554
6367
  if (usage) {
5555
- _optionalChain([this, 'access', _382 => _382.usageEventSink, 'optionalAccess', _383 => _383.emit, 'call', _384 => _384({
6368
+ _optionalChain([this, 'access', _412 => _412.usageEventSink, 'optionalAccess', _413 => _413.emit, 'call', _414 => _414({
5556
6369
  sessionId: sid,
5557
6370
  modelId: actualModel,
5558
6371
  usage,
5559
6372
  engineOrigin: "completion"
5560
6373
  })]);
5561
6374
  }
5562
- _optionalChain([userOnDone, 'optionalCall', _385 => _385(message, usage, metrics)]);
6375
+ _optionalChain([userOnDone, 'optionalCall', _415 => _415(message, usage, metrics)]);
5563
6376
  }
5564
6377
  };
5565
6378
  }
@@ -5575,11 +6388,11 @@ var CompletionService = (_class13 = class {
5575
6388
  retryState.error = { status, message: error };
5576
6389
  return;
5577
6390
  }
5578
- _optionalChain([callbacks, 'access', _386 => _386.onError, 'optionalCall', _387 => _387(error)]);
6391
+ _optionalChain([callbacks, 'access', _416 => _416.onError, 'optionalCall', _417 => _417(error)]);
5579
6392
  },
5580
6393
  onDone: (message, usage, metrics) => {
5581
6394
  this.apiKeyPool.reportSuccess(options.sessionId);
5582
- _optionalChain([callbacks, 'access', _388 => _388.onDone, 'optionalCall', _389 => _389(message, usage, metrics)]);
6395
+ _optionalChain([callbacks, 'access', _418 => _418.onDone, 'optionalCall', _419 => _419(message, usage, metrics)]);
5583
6396
  }
5584
6397
  };
5585
6398
  await this.callStreamHandler(apiFormat, provider, apiKey, resolvedOptions, messageId, interceptCallbacks);
@@ -5600,7 +6413,7 @@ var CompletionService = (_class13 = class {
5600
6413
  // don't fire onStart again
5601
6414
  });
5602
6415
  } else {
5603
- _optionalChain([callbacks, 'access', _390 => _390.onError, 'optionalCall', _391 => _391(retryState.error.message)]);
6416
+ _optionalChain([callbacks, 'access', _420 => _420.onError, 'optionalCall', _421 => _421(retryState.error.message)]);
5604
6417
  }
5605
6418
  }
5606
6419
  } else {
@@ -5613,7 +6426,7 @@ var CompletionService = (_class13 = class {
5613
6426
  } catch (error) {
5614
6427
  const message = error instanceof Error ? error.message : "Unknown error";
5615
6428
  this.logger.error("Stream completion error", error instanceof Error ? error : void 0, { message });
5616
- _optionalChain([callbacks, 'access', _392 => _392.onError, 'optionalCall', _393 => _393(message)]);
6429
+ _optionalChain([callbacks, 'access', _422 => _422.onError, 'optionalCall', _423 => _423(message)]);
5617
6430
  }
5618
6431
  }
5619
6432
  /**
@@ -5653,7 +6466,7 @@ var CompletionService = (_class13 = class {
5653
6466
  return {
5654
6467
  success: true,
5655
6468
  message: "Connection successful",
5656
- response: _optionalChain([result, 'access', _394 => _394.message, 'optionalAccess', _395 => _395.content]) || "",
6469
+ response: _optionalChain([result, 'access', _424 => _424.message, 'optionalAccess', _425 => _425.content]) || "",
5657
6470
  model: modelId,
5658
6471
  durationMs
5659
6472
  };
@@ -5718,7 +6531,7 @@ ${description}`;
5718
6531
  * 3. Legacy single key from provider config
5719
6532
  */
5720
6533
  async resolveApiKeyForRequest(provider, providerId, sessionId) {
5721
- if (_optionalChain([provider, 'access', _396 => _396.codingPlan, 'optionalAccess', _397 => _397.enabled]) && provider.codingPlan.apiKey) {
6534
+ if (_optionalChain([provider, 'access', _426 => _426.codingPlan, 'optionalAccess', _427 => _427.enabled]) && provider.codingPlan.apiKey) {
5722
6535
  return this.resolveApiKey(provider.codingPlan.apiKey);
5723
6536
  }
5724
6537
  if (this.apiKeyPool) {
@@ -5791,9 +6604,10 @@ ${description}`;
5791
6604
  * Resolve effective max_tokens value with priority:
5792
6605
  * 1. Session settings (if provided)
5793
6606
  * 2. Global model parameters (if enabled)
5794
- * 3. Model's maxTokens from provider config
5795
- * 4. Discovered models cache (from API)
5796
- * 5. undefined - let API use its default
6607
+ * 3. undefined - let API use its default
6608
+ *
6609
+ * Provider and discovery maxTokens values are capability metadata, not
6610
+ * implicit per-request output limits.
5797
6611
  */
5798
6612
  async resolveEffectiveMaxTokens(providerId, modelId, sessionMaxTokens) {
5799
6613
  return resolveEffectiveMaxTokens(
@@ -5967,4 +6781,14 @@ ${description}`;
5967
6781
 
5968
6782
 
5969
6783
 
5970
- exports.CompletionService = CompletionService; exports.register = register; exports.emit = emit; exports.attach = attach; exports.release = release; exports.convertMessageToOpenAI = convertMessageToOpenAI; exports.convertMessageToAnthropic = convertMessageToAnthropic; exports.convertMessageToGemini = convertMessageToGemini; exports.getOpenRouterProviderConfig = getOpenRouterProviderConfig; exports.addOpenRouterProviderToRequest = addOpenRouterProviderToRequest; exports.DEFAULT_ROUTE_IDLE_MS = DEFAULT_ROUTE_IDLE_MS; exports.ProviderProxyRouteMap = ProviderProxyRouteMap; exports.getSharedExecutor = getSharedExecutor; exports.getResponsesEndpointTransformer = getResponsesEndpointTransformer; exports.getAnthropicEndpointTransformer = getAnthropicEndpointTransformer; exports.getGeminiEndpointTransformer = getGeminiEndpointTransformer; exports.readBody = readBody; exports.relayResponse = relayResponse; exports.writeError = writeError; exports.resolvePoolBoundKey = resolvePoolBoundKey; exports.extractRouteToken = extractRouteToken; exports.isLoopbackAddress = isLoopbackAddress; exports.ProviderProxy = ProviderProxy; exports.getProviderProxy = getProviderProxy; exports.__resetProviderProxyForTests = __resetProviderProxyForTests; exports.KeyedMutex = KeyedMutex; exports.OUTBOUND_API_SERVER_CONFIG_KEY = OUTBOUND_API_SERVER_CONFIG_KEY; exports.DEFAULT_USER_MESSAGE_QUEUE = DEFAULT_USER_MESSAGE_QUEUE; exports.DEFAULT_CONCURRENCY_QUEUE = DEFAULT_CONCURRENCY_QUEUE; exports.DEFAULT_ACCOUNT_PROBE = DEFAULT_ACCOUNT_PROBE; exports.normalizeAccountProbe = normalizeAccountProbe; exports.normalizeAudit = normalizeAudit; exports.normalizeBilling = normalizeBilling; exports.DEFAULT_FINGERPRINT = DEFAULT_FINGERPRINT; exports.normalizeFingerprint = normalizeFingerprint; exports.normalizeVoucher = normalizeVoucher; exports.normalizeProxyConfig = normalizeProxyConfig; exports.normalizeProxySegment = normalizeProxySegment; exports.normalizeWebhookDestination = normalizeWebhookDestination; exports.normalizeWebhookSegment = normalizeWebhookSegment; exports.normalizeQueueSegments = normalizeQueueSegments; exports.normalizePrefixTargets = normalizePrefixTargets; exports.defaultServerConfig = defaultServerConfig; exports.normalizeServerConfig = normalizeServerConfig; exports.loadServerConfig = loadServerConfig; exports.saveServerConfig = saveServerConfig; exports.mergeServerConfig = mergeServerConfig; exports.computeKeyExpiry = computeKeyExpiry; exports.checkKeyQuota = checkKeyQuota; exports.randomBase62 = randomBase62; exports.hashKey = hashKey; exports.createNamedKey = createNamedKey; exports.verifyKey = verifyKey; exports.verifyPresentedKey = verifyPresentedKey; exports.ConcurrencyQueueFullError = ConcurrencyQueueFullError; exports.ConcurrencyWaitTimeoutError = ConcurrencyWaitTimeoutError; exports.ConcurrencyWaitCancelledError = ConcurrencyWaitCancelledError; exports.isConcurrencyRejection = isConcurrencyRejection; exports.OutboundConcurrencyGate = OutboundConcurrencyGate; exports.OutboundRateLimiter = OutboundRateLimiter; exports.isUserMessageRequest = isUserMessageRequest; exports.SerialQueueTimeoutError = SerialQueueTimeoutError; exports.isSerialQueueTimeout = isSerialQueueTimeout; exports.UserMessageSerialQueue = UserMessageSerialQueue; exports.generateVoucherCode = generateVoucherCode; exports.hashVoucherCode = hashVoucherCode; exports.voucherCodePrefix = voucherCodePrefix; exports.newVoucherId = newVoucherId; exports.computeVoucherGrant = computeVoucherGrant; exports.toVoucherInfo = toVoucherInfo; exports.isRedeemRequest = isRedeemRequest; exports.handleVoucherRedeem = handleVoucherRedeem; exports.DEFAULT_OUTBOUND_PORT = DEFAULT_OUTBOUND_PORT; exports.OutboundApiConfigError = OutboundApiConfigError; exports.OutboundApiServer = OutboundApiServer; exports.formatUrls = formatUrls; exports.startOfLocalDay = startOfLocalDay; exports.startOfLocalWeek = startOfLocalWeek; exports.KeySpendTracker = KeySpendTracker; exports.getOutboundApiServer = getOutboundApiServer; exports.__resetOutboundApiServerForTests = __resetOutboundApiServerForTests;
6784
+
6785
+
6786
+
6787
+
6788
+
6789
+
6790
+
6791
+
6792
+
6793
+
6794
+ exports.CompletionService = CompletionService; exports.register = register; exports.emit = emit; exports.attach = attach; exports.release = release; exports.convertMessageToOpenAI = convertMessageToOpenAI; exports.convertMessageToAnthropic = convertMessageToAnthropic; exports.convertMessageToGemini = convertMessageToGemini; exports.getOpenRouterProviderConfig = getOpenRouterProviderConfig; exports.addOpenRouterProviderToRequest = addOpenRouterProviderToRequest; exports.DEFAULT_ROUTE_IDLE_MS = DEFAULT_ROUTE_IDLE_MS; exports.ProviderProxyRouteMap = ProviderProxyRouteMap; exports.getSharedExecutor = getSharedExecutor; exports.getResponsesEndpointTransformer = getResponsesEndpointTransformer; exports.getAnthropicEndpointTransformer = getAnthropicEndpointTransformer; exports.getGeminiEndpointTransformer = getGeminiEndpointTransformer; exports.readBody = readBody; exports.relayResponse = relayResponse; exports.aggregateAnthropicSseToJsonBody = aggregateAnthropicSseToJsonBody; exports.writeError = writeError; exports.writeBoundAccountError = writeBoundAccountError; exports.resolvePoolBoundKey = resolvePoolBoundKey; exports.extractRouteToken = extractRouteToken; exports.isLoopbackAddress = isLoopbackAddress; exports.ProviderProxy = ProviderProxy; exports.getProviderProxy = getProviderProxy; exports.__resetProviderProxyForTests = __resetProviderProxyForTests; exports.KeyedMutex = KeyedMutex; exports.OUTBOUND_API_SERVER_CONFIG_KEY = OUTBOUND_API_SERVER_CONFIG_KEY; exports.DEFAULT_USER_MESSAGE_QUEUE = DEFAULT_USER_MESSAGE_QUEUE; exports.DEFAULT_CONCURRENCY_QUEUE = DEFAULT_CONCURRENCY_QUEUE; exports.DEFAULT_ACCOUNT_PROBE = DEFAULT_ACCOUNT_PROBE; exports.DEFAULT_ALLOWANCE_SCHEDULING = DEFAULT_ALLOWANCE_SCHEDULING; exports.normalizeAllowanceScheduling = normalizeAllowanceScheduling; exports.normalizeAccountProbe = normalizeAccountProbe; exports.normalizeAudit = normalizeAudit; exports.normalizeBilling = normalizeBilling; exports.DEFAULT_FINGERPRINT = DEFAULT_FINGERPRINT; exports.normalizeFingerprint = normalizeFingerprint; exports.normalizeVoucher = normalizeVoucher; exports.normalizeProxyConfig = normalizeProxyConfig; exports.normalizeProxySegment = normalizeProxySegment; exports.normalizeWebhookDestination = normalizeWebhookDestination; exports.normalizeWebhookSegment = normalizeWebhookSegment; exports.normalizeQueueSegments = normalizeQueueSegments; exports.normalizePrefixTargets = normalizePrefixTargets; exports.legacyEndpointsToBindings = legacyEndpointsToBindings; exports.normalizeGatewayBindings = normalizeGatewayBindings; exports.defaultServerConfig = defaultServerConfig; exports.normalizeServerConfig = normalizeServerConfig; exports.loadServerConfig = loadServerConfig; exports.saveServerConfig = saveServerConfig; exports.mergeServerConfig = mergeServerConfig; exports.gatewayBindingToEndpointConfig = gatewayBindingToEndpointConfig; exports.candidateGatewayBindings = candidateGatewayBindings; exports.candidateBackgroundModelIds = candidateBackgroundModelIds; exports.resolveGatewayBinding = resolveGatewayBinding; exports.computeKeyExpiry = computeKeyExpiry; exports.checkKeyQuota = checkKeyQuota; exports.randomBase62 = randomBase62; exports.hashKey = hashKey; exports.createNamedKey = createNamedKey; exports.createIntegrationKey = createIntegrationKey; exports.verifyKey = verifyKey; exports.verifyPresentedKey = verifyPresentedKey; exports.ConcurrencyQueueFullError = ConcurrencyQueueFullError; exports.ConcurrencyWaitTimeoutError = ConcurrencyWaitTimeoutError; exports.ConcurrencyWaitCancelledError = ConcurrencyWaitCancelledError; exports.isConcurrencyRejection = isConcurrencyRejection; exports.OutboundConcurrencyGate = OutboundConcurrencyGate; exports.OutboundRateLimiter = OutboundRateLimiter; exports.isUserMessageRequest = isUserMessageRequest; exports.SerialQueueTimeoutError = SerialQueueTimeoutError; exports.isSerialQueueTimeout = isSerialQueueTimeout; exports.UserMessageSerialQueue = UserMessageSerialQueue; exports.generateVoucherCode = generateVoucherCode; exports.hashVoucherCode = hashVoucherCode; exports.voucherCodePrefix = voucherCodePrefix; exports.newVoucherId = newVoucherId; exports.computeVoucherGrant = computeVoucherGrant; exports.toVoucherInfo = toVoucherInfo; exports.isRedeemRequest = isRedeemRequest; exports.handleVoucherRedeem = handleVoucherRedeem; exports.DEFAULT_OUTBOUND_PORT = DEFAULT_OUTBOUND_PORT; exports.OutboundApiServer = OutboundApiServer; exports.formatUrls = formatUrls; exports.startOfLocalDay = startOfLocalDay; exports.startOfLocalWeek = startOfLocalWeek; exports.KeySpendTracker = KeySpendTracker; exports.getOutboundApiServer = getOutboundApiServer; exports.__resetOutboundApiServerForTests = __resetOutboundApiServerForTests;