@omnicross/core 0.1.5 → 0.1.7

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 (231) 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 +8 -6
  6. package/dist/auth/GeminiCodeAssistProjectResolver.js +6 -4
  7. package/dist/{chunk-3Z5BQZFM.cjs → chunk-235MXAGX.cjs} +3 -1
  8. package/dist/{chunk-HRRYG2AX.js → chunk-23S5OPIO.js} +10 -1
  9. package/dist/chunk-25GXJCEZ.cjs +40 -0
  10. package/dist/chunk-2E42SAW3.cjs +323 -0
  11. package/dist/chunk-2JYRIADS.js +40 -0
  12. package/dist/chunk-2Z4XM3H5.cjs +44 -0
  13. package/dist/{chunk-BODMAL6G.js → chunk-32O35CIF.js} +271 -91
  14. package/dist/chunk-3SCOLIPT.cjs +63 -0
  15. package/dist/{chunk-SYQF7OIR.js → chunk-3WD4HTR2.js} +2 -0
  16. package/dist/{chunk-CGKLE6IW.cjs → chunk-4BB343BI.cjs} +1489 -520
  17. package/dist/{chunk-VACWOIRE.cjs → chunk-4VZX5F4T.cjs} +39 -15
  18. package/dist/{chunk-5ZQBEOMD.js → chunk-5NJLQ6T6.js} +46 -12
  19. package/dist/chunk-5RSZYQJH.cjs +62 -0
  20. package/dist/chunk-6QQG7YG3.cjs +153 -0
  21. package/dist/{chunk-IFXJ2BG7.js → chunk-7C7DET6S.js} +51 -6
  22. package/dist/{chunk-IK3KE3AU.js → chunk-DE2SRBFZ.js} +1 -1
  23. package/dist/{chunk-FH2P4OCD.js → chunk-E3COOKUP.js} +1240 -271
  24. package/dist/{chunk-UHGVBFU3.js → chunk-EBLFCNPY.js} +38 -14
  25. package/dist/chunk-FU7EAR73.js +62 -0
  26. package/dist/chunk-FXR6N3SR.js +323 -0
  27. package/dist/{chunk-SUEGJ75D.cjs → chunk-GDIXXKF2.cjs} +46 -12
  28. package/dist/chunk-GFIZ6LQI.js +170 -0
  29. package/dist/chunk-GL6XM527.js +61 -0
  30. package/dist/chunk-HVBBDBS3.cjs +350 -0
  31. package/dist/{chunk-46ZIFWYG.cjs → chunk-IIRPUVPH.cjs} +7 -1
  32. package/dist/chunk-J3QQ6JS5.cjs +170 -0
  33. package/dist/{chunk-JWVTXXPX.cjs → chunk-KBM2W6UY.cjs} +8 -4
  34. package/dist/chunk-LB6EBS6Y.js +69 -0
  35. package/dist/{chunk-IWQAX3CS.js → chunk-LVUCAWMK.js} +1 -1
  36. package/dist/chunk-MKF46GNZ.js +350 -0
  37. package/dist/{chunk-HYN75H6G.cjs → chunk-MUHWHQVM.cjs} +1 -1
  38. package/dist/chunk-MYYR3HZL.js +44 -0
  39. package/dist/{chunk-MFZ5437A.js → chunk-N5T4M4GU.js} +1 -1
  40. package/dist/{chunk-5ENKBSWO.js → chunk-N7OOJI5V.js} +88 -8
  41. package/dist/chunk-NKVZ6Z3Y.cjs +61 -0
  42. package/dist/chunk-OF3BECU2.cjs +69 -0
  43. package/dist/{chunk-SNYBEXLB.cjs → chunk-OJGQKHN5.cjs} +3 -1
  44. package/dist/{chunk-DDMRUL76.cjs → chunk-OKMJLEXX.cjs} +5 -5
  45. package/dist/chunk-OPRS4IQZ.js +153 -0
  46. package/dist/chunk-OTZC4TNH.cjs +79 -0
  47. package/dist/{chunk-3Q6Z6JTO.cjs → chunk-OVQBNVSV.cjs} +287 -107
  48. package/dist/{chunk-4XMYPW46.cjs → chunk-OXHNSZ53.cjs} +84 -44
  49. package/dist/{chunk-C6OV7GCC.js → chunk-PEGTIPB3.js} +52 -12
  50. package/dist/chunk-PO3XB56Z.js +79 -0
  51. package/dist/{chunk-D3TDKWRP.js → chunk-RJ5ZGNI3.js} +54 -5
  52. package/dist/{chunk-PG7PS2NN.cjs → chunk-RJUONLUQ.cjs} +59 -10
  53. package/dist/{chunk-BPKCU575.js → chunk-SOO562NM.js} +3 -1
  54. package/dist/{chunk-6QZGDLL4.js → chunk-TOVPMMHM.js} +5 -1
  55. package/dist/{chunk-K52THW2C.cjs → chunk-V4TXMEJS.cjs} +5 -5
  56. package/dist/{chunk-G2UTNSGU.js → chunk-WNKWAEUR.js} +7 -1
  57. package/dist/{chunk-UNWKG6EI.cjs → chunk-XPIOJQS2.cjs} +51 -6
  58. package/dist/chunk-XXFYLL7R.js +63 -0
  59. package/dist/{chunk-KFI44N2R.cjs → chunk-YNJNTCSQ.cjs} +10 -1
  60. package/dist/{chunk-VQY5W4YW.cjs → chunk-YWL7YZWS.cjs} +90 -10
  61. package/dist/completion/ApiKeyPoolService.cjs +12 -0
  62. package/dist/completion/ApiKeyPoolService.d.cts +6 -0
  63. package/dist/completion/ApiKeyPoolService.d.ts +6 -0
  64. package/dist/completion/ApiKeyPoolService.js +12 -0
  65. package/dist/completion/CompletionService.cjs +30 -24
  66. package/dist/completion/CompletionService.d.cts +3 -1
  67. package/dist/completion/CompletionService.d.ts +3 -1
  68. package/dist/completion/CompletionService.js +29 -23
  69. package/dist/completion.cjs +32 -26
  70. package/dist/completion.d.cts +3 -1
  71. package/dist/completion.d.ts +3 -1
  72. package/dist/completion.js +31 -25
  73. package/dist/index.cjs +56 -29
  74. package/dist/index.d.cts +8 -8
  75. package/dist/index.d.ts +8 -8
  76. package/dist/index.js +61 -34
  77. package/dist/{keyPolicy-Cp0FntZl.d.cts → keyPolicy-zdWTu3CQ.d.cts} +1 -1
  78. package/dist/{keyPolicy-Cp0FntZl.d.ts → keyPolicy-zdWTu3CQ.d.ts} +1 -1
  79. package/dist/outbound-api/auditCapture.cjs +2 -2
  80. package/dist/outbound-api/auditCapture.d.cts +3 -4
  81. package/dist/outbound-api/auditCapture.d.ts +3 -4
  82. package/dist/outbound-api/auditCapture.js +1 -1
  83. package/dist/outbound-api/quotaWarn.d.cts +1 -1
  84. package/dist/outbound-api/quotaWarn.d.ts +1 -1
  85. package/dist/outbound-api/routeResolver.cjs +2 -2
  86. package/dist/outbound-api/routeResolver.d.cts +5 -3
  87. package/dist/outbound-api/routeResolver.d.ts +5 -3
  88. package/dist/outbound-api/routeResolver.js +1 -1
  89. package/dist/outbound-api/subscriptionRegistryPort.d.cts +2 -0
  90. package/dist/outbound-api/subscriptionRegistryPort.d.ts +2 -0
  91. package/dist/outbound-api/types.d.cts +4 -2
  92. package/dist/outbound-api/types.d.ts +4 -2
  93. package/dist/outbound-api.cjs +52 -25
  94. package/dist/outbound-api.d.cts +131 -87
  95. package/dist/outbound-api.d.ts +131 -87
  96. package/dist/outbound-api.js +55 -28
  97. package/dist/pipeline/AccountAllowanceScheduling.cjs +15 -0
  98. package/dist/pipeline/AccountAllowanceScheduling.d.cts +91 -0
  99. package/dist/pipeline/AccountAllowanceScheduling.d.ts +91 -0
  100. package/dist/pipeline/AccountAllowanceScheduling.js +15 -0
  101. package/dist/pipeline/AccountAllowanceStore.cjs +20 -0
  102. package/dist/pipeline/AccountAllowanceStore.d.cts +77 -0
  103. package/dist/pipeline/AccountAllowanceStore.d.ts +77 -0
  104. package/dist/pipeline/AccountAllowanceStore.js +20 -0
  105. package/dist/pipeline/AccountRouteActivity.cjs +10 -0
  106. package/dist/pipeline/AccountRouteActivity.d.cts +61 -0
  107. package/dist/pipeline/AccountRouteActivity.d.ts +61 -0
  108. package/dist/pipeline/AccountRouteActivity.js +10 -0
  109. package/dist/pipeline/AuthSource.d.cts +11 -2
  110. package/dist/pipeline/AuthSource.d.ts +11 -2
  111. package/dist/pipeline/BoundAccountSelectionError.cjs +10 -0
  112. package/dist/pipeline/BoundAccountSelectionError.d.cts +28 -0
  113. package/dist/pipeline/BoundAccountSelectionError.d.ts +28 -0
  114. package/dist/pipeline/BoundAccountSelectionError.js +10 -0
  115. package/dist/pipeline/LlmConfigProviderAuth.d.cts +1 -0
  116. package/dist/pipeline/LlmConfigProviderAuth.d.ts +1 -0
  117. package/dist/pipeline/ServerOverloadCounter.cjs +16 -0
  118. package/dist/pipeline/ServerOverloadCounter.d.cts +77 -0
  119. package/dist/pipeline/ServerOverloadCounter.d.ts +77 -0
  120. package/dist/pipeline/ServerOverloadCounter.js +16 -0
  121. package/dist/pipeline/SubscriptionAccountHealth.cjs +6 -2
  122. package/dist/pipeline/SubscriptionAccountHealth.d.cts +65 -8
  123. package/dist/pipeline/SubscriptionAccountHealth.d.ts +65 -8
  124. package/dist/pipeline/SubscriptionAccountHealth.js +5 -1
  125. package/dist/pipeline/SubscriptionAuthSource.cjs +5 -2
  126. package/dist/pipeline/SubscriptionAuthSource.d.cts +1 -0
  127. package/dist/pipeline/SubscriptionAuthSource.d.ts +1 -0
  128. package/dist/pipeline/SubscriptionAuthSource.js +4 -1
  129. package/dist/pipeline/SubscriptionAuthStrategy.d.cts +8 -3
  130. package/dist/pipeline/SubscriptionAuthStrategy.d.ts +8 -3
  131. package/dist/pipeline/executeProviderCall.cjs +2 -2
  132. package/dist/pipeline/executeProviderCall.d.cts +8 -3
  133. package/dist/pipeline/executeProviderCall.d.ts +8 -3
  134. package/dist/pipeline/executeProviderCall.js +1 -1
  135. package/dist/pipeline/resolveProviderChain.d.cts +2 -3
  136. package/dist/pipeline/resolveProviderChain.d.ts +2 -3
  137. package/dist/pipeline/resolveSubscriptionChain.d.cts +1 -0
  138. package/dist/pipeline/resolveSubscriptionChain.d.ts +1 -0
  139. package/dist/pipeline/upstreamFetch.cjs +5 -3
  140. package/dist/pipeline/upstreamFetch.d.cts +35 -6
  141. package/dist/pipeline/upstreamFetch.d.ts +35 -6
  142. package/dist/pipeline/upstreamFetch.js +4 -2
  143. package/dist/pipeline/upstreamTrace.cjs +4 -2
  144. package/dist/pipeline/upstreamTrace.d.cts +22 -8
  145. package/dist/pipeline/upstreamTrace.d.ts +22 -8
  146. package/dist/pipeline/upstreamTrace.js +3 -1
  147. package/dist/ports/pricing-store.d.cts +4 -3
  148. package/dist/ports/pricing-store.d.ts +4 -3
  149. package/dist/ports.d.cts +4 -3
  150. package/dist/ports.d.ts +4 -3
  151. package/dist/provider-proxy/ProviderProxy.cjs +30 -24
  152. package/dist/provider-proxy/ProviderProxy.d.cts +2 -0
  153. package/dist/provider-proxy/ProviderProxy.d.ts +2 -0
  154. package/dist/provider-proxy/ProviderProxy.js +29 -23
  155. package/dist/provider-proxy/identity/codexCliHeaders.cjs +10 -0
  156. package/dist/provider-proxy/identity/codexCliHeaders.d.cts +45 -0
  157. package/dist/provider-proxy/identity/codexCliHeaders.d.ts +45 -0
  158. package/dist/provider-proxy/identity/codexCliHeaders.js +10 -0
  159. package/dist/provider-proxy/ingress/providerProxyShared.cjs +32 -24
  160. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +44 -5
  161. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +44 -5
  162. package/dist/provider-proxy/ingress/providerProxyShared.js +31 -23
  163. package/dist/provider-proxy/matchText.cjs +4 -2
  164. package/dist/provider-proxy/matchText.d.cts +39 -6
  165. package/dist/provider-proxy/matchText.d.ts +39 -6
  166. package/dist/provider-proxy/matchText.js +3 -1
  167. package/dist/provider-proxy/types.d.cts +35 -2
  168. package/dist/provider-proxy/types.d.ts +35 -2
  169. package/dist/provider-proxy.cjs +30 -24
  170. package/dist/provider-proxy.d.cts +2 -0
  171. package/dist/provider-proxy.d.ts +2 -0
  172. package/dist/provider-proxy.js +29 -23
  173. package/dist/{routeResolver-C4T7yClx.d.ts → routeResolver-BxOfunbm.d.ts} +1 -1
  174. package/dist/{routeResolver-CB3tvJKy.d.cts → routeResolver-D5OzD0iM.d.cts} +1 -1
  175. package/dist/transformer/TransformerChainExecutor.cjs +2 -2
  176. package/dist/transformer/TransformerChainExecutor.js +1 -1
  177. package/dist/transformer/transformers/AnthropicTransformer.cjs +3 -2
  178. package/dist/transformer/transformers/AnthropicTransformer.js +2 -1
  179. package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +3 -3
  180. package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +2 -2
  181. package/dist/transformer/transformers/GeminiTransformer.cjs +3 -3
  182. package/dist/transformer/transformers/GeminiTransformer.js +2 -2
  183. package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +3 -2
  184. package/dist/transformer/transformers/OpenAIResponseTransformer.d.cts +1 -1
  185. package/dist/transformer/transformers/OpenAIResponseTransformer.d.ts +1 -1
  186. package/dist/transformer/transformers/OpenAIResponseTransformer.js +2 -1
  187. package/dist/transformer/transformers/OpenAITransformer.cjs +6 -0
  188. package/dist/transformer/transformers/OpenAITransformer.d.cts +68 -0
  189. package/dist/transformer/transformers/OpenAITransformer.d.ts +68 -0
  190. package/dist/transformer/transformers/OpenAITransformer.js +6 -0
  191. package/dist/transformer/transformers.cjs +9 -14
  192. package/dist/transformer/transformers.d.cts +12 -48
  193. package/dist/transformer/transformers.d.ts +12 -48
  194. package/dist/transformer/transformers.js +11 -16
  195. package/dist/transformer/types.d.cts +17 -0
  196. package/dist/transformer/types.d.ts +17 -0
  197. package/dist/transformer.cjs +12 -12
  198. package/dist/transformer.d.cts +1 -2
  199. package/dist/transformer.d.ts +1 -2
  200. package/dist/transformer.js +12 -12
  201. package/dist/{types-lgPYQuZS.d.ts → types-CqZD77rS.d.ts} +173 -7
  202. package/dist/{types-B8Arpxn0.d.cts → types-gjJ5lJ5n.d.cts} +173 -7
  203. package/dist/usage/pricing-engine.cjs +2 -2
  204. package/dist/usage/pricing-engine.d.cts +29 -1
  205. package/dist/usage/pricing-engine.d.ts +29 -1
  206. package/dist/usage/pricing-engine.js +1 -1
  207. package/dist/usage/usage-recorder.cjs +2 -2
  208. package/dist/usage/usage-recorder.d.cts +5 -1
  209. package/dist/usage/usage-recorder.d.ts +5 -1
  210. package/dist/usage/usage-recorder.js +1 -1
  211. package/dist/usage.cjs +3 -3
  212. package/dist/usage.js +2 -2
  213. package/package.json +1 -1
  214. package/dist/chunk-7FEBOPJO.cjs +0 -50
  215. package/dist/chunk-DWKQZ2SK.cjs +0 -254
  216. package/dist/chunk-IAXWICZU.js +0 -69
  217. package/dist/chunk-IB3FDI4O.js +0 -50
  218. package/dist/chunk-OQWKZCXP.js +0 -242
  219. package/dist/chunk-QWBWGODS.cjs +0 -69
  220. package/dist/chunk-YMFAJFQT.cjs +0 -173
  221. package/dist/chunk-ZCIQ3L3R.cjs +0 -242
  222. package/dist/chunk-ZJZAOKI7.js +0 -254
  223. package/dist/chunk-ZLX3KGXX.js +0 -173
  224. package/dist/transformer/transformers/OpenCodeGoTransformer.cjs +0 -6
  225. package/dist/transformer/transformers/OpenCodeGoTransformer.d.cts +0 -51
  226. package/dist/transformer/transformers/OpenCodeGoTransformer.d.ts +0 -51
  227. package/dist/transformer/transformers/OpenCodeGoTransformer.js +0 -6
  228. package/dist/transformer/transformers/ReasoningTransformer.cjs +0 -6
  229. package/dist/transformer/transformers/ReasoningTransformer.d.cts +0 -47
  230. package/dist/transformer/transformers/ReasoningTransformer.d.ts +0 -47
  231. package/dist/transformer/transformers/ReasoningTransformer.js +0 -6
@@ -2,7 +2,14 @@
2
2
 
3
3
 
4
4
 
5
- var _chunk3Z5BQZFMcjs = require('./chunk-3Z5BQZFM.cjs');
5
+
6
+ var _chunk235MXAGXcjs = require('./chunk-235MXAGX.cjs');
7
+
8
+
9
+ var _chunkHVBBDBS3cjs = require('./chunk-HVBBDBS3.cjs');
10
+
11
+
12
+ var _chunkNKVZ6Z3Ycjs = require('./chunk-NKVZ6Z3Y.cjs');
6
13
 
7
14
  // src/pipeline/upstreamFetch.ts
8
15
  var _undici = require('undici');
@@ -102,23 +109,63 @@ function resolveUpstreamDispatcher(ctx) {
102
109
  function fetchUpstream(url, init, ctx) {
103
110
  const dispatcher = resolveUpstreamDispatcher({ ..._nullishCoalesce(ctx, () => ( {})), url });
104
111
  const doFetch = dispatcher ? () => fetch(url, { ...init, dispatcher }) : () => fetch(url, init);
105
- const tracePath = _chunk3Z5BQZFMcjs.getUpstreamTracePath.call(void 0, );
106
- if (!tracePath || !_optionalChain([ctx, 'optionalAccess', _3 => _3.providerId])) return doFetch();
112
+ const doFetchWithAllowanceTap = () => doFetch().then((response) => {
113
+ if (_optionalChain([ctx, 'optionalAccess', _3 => _3.providerId]) === "codex" && ctx.accountId) {
114
+ try {
115
+ _chunkHVBBDBS3cjs.getSharedAccountAllowanceStore.call(void 0, ).recordCodexHeaders(ctx.accountId, response.headers);
116
+ } catch (e4) {
117
+ }
118
+ }
119
+ return response;
120
+ });
121
+ const activity = _optionalChain([ctx, 'optionalAccess', _4 => _4.routeActivity]);
122
+ const activityStartedAt = activity && _optionalChain([ctx, 'optionalAccess', _5 => _5.providerId]) && ctx.accountId ? Date.now() : 0;
123
+ const recordActivity = (status) => {
124
+ if (!activity || !_optionalChain([ctx, 'optionalAccess', _6 => _6.providerId]) || !ctx.accountId) return;
125
+ const record = _chunkNKVZ6Z3Ycjs.getSharedAccountRouteActivity.call(void 0, ).record({
126
+ providerId: ctx.providerId,
127
+ accountId: ctx.accountId,
128
+ endpoint: activity.endpoint,
129
+ sessionKey: activity.sessionKey,
130
+ sessionSource: activity.sessionSource,
131
+ model: activity.model,
132
+ status,
133
+ durationMs: Math.max(0, Date.now() - activityStartedAt),
134
+ ts: activityStartedAt
135
+ });
136
+ try {
137
+ _optionalChain([activity, 'access', _7 => _7.onRecorded, 'optionalCall', _8 => _8(record)]);
138
+ } catch (e5) {
139
+ }
140
+ };
141
+ const doFetchWithActivity = () => doFetchWithAllowanceTap().then(
142
+ (response) => {
143
+ recordActivity(response.status);
144
+ return response;
145
+ },
146
+ (error) => {
147
+ recordActivity(0);
148
+ throw error;
149
+ }
150
+ );
151
+ const tracePath = _chunk235MXAGXcjs.getUpstreamTracePath.call(void 0, );
152
+ if (!tracePath || !_optionalChain([ctx, 'optionalAccess', _9 => _9.providerId])) return doFetchWithActivity();
107
153
  const startedAt = Date.now();
108
154
  const method = typeof init.method === "string" ? init.method : "GET";
109
- const requestHeaders = _chunk3Z5BQZFMcjs.redactHeaders.call(void 0,
155
+ const requestHeaders = _chunk235MXAGXcjs.redactHeaders.call(void 0,
110
156
  init.headers
111
157
  );
112
- const requestBody = typeof init.body === "string" ? init.body : null;
158
+ const redactBodies = ctx.redactBodies === true;
159
+ const requestBody = redactBodies ? _chunk235MXAGXcjs.REDACTED_BODY : typeof init.body === "string" ? init.body : null;
113
160
  const providerId = ctx.providerId;
114
161
  const accountId = ctx.accountId;
115
- return doFetch().then((res) => {
162
+ return doFetchWithActivity().then((res) => {
116
163
  const clone = res.clone();
117
164
  const status = res.status;
118
165
  const statusText = res.statusText;
119
- const responseHeaders = _chunk3Z5BQZFMcjs.redactHeaders.call(void 0, res.headers);
166
+ const responseHeaders = _chunk235MXAGXcjs.redactHeaders.call(void 0, res.headers);
120
167
  void clone.text().then((body) => {
121
- _chunk3Z5BQZFMcjs.writeUpstreamTrace.call(void 0, {
168
+ _chunk235MXAGXcjs.writeUpstreamTrace.call(void 0, {
122
169
  ts: startedAt,
123
170
  durationMs: Date.now() - startedAt,
124
171
  providerId,
@@ -130,7 +177,9 @@ function fetchUpstream(url, init, ctx) {
130
177
  status,
131
178
  statusText,
132
179
  responseHeaders,
133
- responseBody: body,
180
+ // The byte count stays REAL even when redacted — it is a useful
181
+ // diagnostic and reveals nothing about the token itself.
182
+ responseBody: redactBodies ? _chunk235MXAGXcjs.REDACTED_BODY : body,
134
183
  responseBytes: Buffer.byteLength(body, "utf8")
135
184
  });
136
185
  }).catch(() => {
@@ -138,7 +187,7 @@ function fetchUpstream(url, init, ctx) {
138
187
  return res;
139
188
  }).catch((err) => {
140
189
  const msg = err instanceof Error ? err.message : String(err);
141
- _chunk3Z5BQZFMcjs.writeUpstreamTrace.call(void 0, {
190
+ _chunk235MXAGXcjs.writeUpstreamTrace.call(void 0, {
142
191
  ts: startedAt,
143
192
  durationMs: Date.now() - startedAt,
144
193
  providerId,
@@ -78,7 +78,9 @@ var UsageRecorder = class {
78
78
  costSavedByCacheUsd,
79
79
  rawUsage: input.rawUsage != null ? safeStringify(input.rawUsage) : null,
80
80
  runId: input.runId ?? null,
81
- eventId: input.eventId ?? null
81
+ eventId: input.eventId ?? null,
82
+ ...input.cacheKeySource !== void 0 ? { cacheKeySource: input.cacheKeySource } : {},
83
+ ...input.cacheKeyInjected !== void 0 ? { cacheKeyInjected: input.cacheKeyInjected } : {}
82
84
  };
83
85
  try {
84
86
  return await this.store.insert(row);
@@ -792,6 +792,9 @@ function buildRequestBody(request) {
792
792
  }
793
793
  });
794
794
  const generationConfig = {};
795
+ if (request.max_tokens !== void 0) {
796
+ generationConfig.maxOutputTokens = request.max_tokens;
797
+ }
795
798
  if (request.reasoning?.effort && request.reasoning.effort !== "none") {
796
799
  generationConfig.thinkingConfig = {
797
800
  includeThoughts: true
@@ -843,7 +846,8 @@ function transformRequestOut(request) {
843
846
  const contents = request.contents;
844
847
  const tools = request.tools;
845
848
  const model = request.model;
846
- const maxTokens = request.max_tokens;
849
+ const generationConfig = request.generationConfig;
850
+ const maxTokens = generationConfig?.maxOutputTokens ?? request.max_tokens;
847
851
  const temperature = request.temperature;
848
852
  const stream = request.stream;
849
853
  const toolChoice = request.tool_choice;
@@ -3,7 +3,7 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkJWVTXXPXcjs = require('./chunk-JWVTXXPX.cjs');
6
+ var _chunkKBM2W6UYcjs = require('./chunk-KBM2W6UY.cjs');
7
7
 
8
8
  // src/transformer/transformers/GeminiTransformer.ts
9
9
  var GeminiTransformer = (_class = class {
@@ -44,7 +44,7 @@ var GeminiTransformer = (_class = class {
44
44
  * Also builds the correct URL for the Gemini API
45
45
  */
46
46
  async transformRequestIn(request, provider, _context) {
47
- const body = _chunkJWVTXXPXcjs.buildRequestBody.call(void 0, request);
47
+ const body = _chunkKBM2W6UYcjs.buildRequestBody.call(void 0, request);
48
48
  const action = request.stream ? "streamGenerateContent?alt=sse" : "generateContent";
49
49
  const url = new URL(`./${request.model}:${action}`, provider.baseUrl);
50
50
  const headers = {};
@@ -65,20 +65,20 @@ var GeminiTransformer = (_class = class {
65
65
  * (For requests coming into the Gemini endpoint)
66
66
  */
67
67
  async transformRequestOut(request, _context) {
68
- return _chunkJWVTXXPXcjs.transformRequestOut.call(void 0, request);
68
+ return _chunkKBM2W6UYcjs.transformRequestOut.call(void 0, request);
69
69
  }
70
70
  /**
71
71
  * Transform Gemini response to OpenAI-compatible format
72
72
  */
73
73
  async transformResponseOut(response, _context) {
74
- return _chunkJWVTXXPXcjs.transformResponseOut.call(void 0, response, this.name, this.logger);
74
+ return _chunkKBM2W6UYcjs.transformResponseOut.call(void 0, response, this.name, this.logger);
75
75
  }
76
76
  /**
77
77
  * Transform OpenAI-compatible response back to Gemini format
78
78
  * (For endpoint mode — returning Gemini-format responses to the client)
79
79
  */
80
80
  async transformResponseIn(response, _context) {
81
- return _chunkJWVTXXPXcjs.transformResponseIn.call(void 0, response, this.logger);
81
+ return _chunkKBM2W6UYcjs.transformResponseIn.call(void 0, response, this.logger);
82
82
  }
83
83
  }, _class.__initStatic(), _class);
84
84
 
@@ -134,7 +134,13 @@ var TransformerChainExecutor = class {
134
134
  const { endpointTransformer } = options;
135
135
  const context = {
136
136
  logger: this.logger,
137
- providerName: provider.name
137
+ providerName: provider.name,
138
+ // The unified REQUEST this response answers. Response encoders need it to
139
+ // restore request-scoped protocol state that the chat wire cannot carry —
140
+ // e.g. which codex tools were declared `custom` (see
141
+ // `UnifiedChatRequestMeta.codexTools`), which decides whether a tool call
142
+ // is encoded back as a `function_call` or a `custom_tool_call` item.
143
+ req: request
138
144
  };
139
145
  let finalResponse = response;
140
146
  const bypass = this.shouldBypassTransformers(chain, endpointTransformer, request);
@@ -11,6 +11,29 @@ var _chunkXSVNC2UDcjs = require('./chunk-XSVNC2UD.cjs');
11
11
 
12
12
  // src/outbound-api/auditCapture.ts
13
13
  var _crypto = require('crypto');
14
+ function completeUtf8PrefixLength(buf) {
15
+ if (buf.length === 0) return 0;
16
+ let leadIndex = buf.length - 1;
17
+ while (leadIndex >= 0 && (buf[leadIndex] & 192) === 128) leadIndex -= 1;
18
+ if (leadIndex < 0) return 0;
19
+ const lead = buf[leadIndex];
20
+ let expectedLength = 1;
21
+ if ((lead & 224) === 192) expectedLength = 2;
22
+ else if ((lead & 240) === 224) expectedLength = 3;
23
+ else if ((lead & 248) === 240) expectedLength = 4;
24
+ return buf.length - leadIndex < expectedLength ? leadIndex : buf.length;
25
+ }
26
+ function truncateToBytes(text, maxBytes) {
27
+ if (maxBytes < 0) return text;
28
+ const buf = Buffer.from(text, "utf8");
29
+ if (buf.length <= maxBytes) return text;
30
+ const head = buf.subarray(0, maxBytes);
31
+ return head.subarray(0, completeUtf8PrefixLength(head)).toString("utf8");
32
+ }
33
+ function decodeCapturedBody(body, truncated) {
34
+ if (!truncated) return body.toString("utf8");
35
+ return body.subarray(0, completeUtf8PrefixLength(body)).toString("utf8");
36
+ }
14
37
  function resolveClientIp(req, trustForwardedFor) {
15
38
  if (trustForwardedFor) {
16
39
  const xff = req.headers["x-forwarded-for"];
@@ -25,18 +48,39 @@ function resolveClientIp(req, trustForwardedFor) {
25
48
  function beginAuditCapture(req, res, now) {
26
49
  const config = _chunkAEOZIDEBcjs.getAuditCaptureConfig.call(void 0, );
27
50
  if (!config) return null;
28
- let rawRequestBody;
51
+ let requestBody;
29
52
  const responseChunks = [];
53
+ let responseBytes = 0;
54
+ let responseTruncated = false;
30
55
  let finished = false;
31
56
  const ctx = {
32
57
  setRequestBody(raw) {
33
- if (config.captureBodies) rawRequestBody = raw;
58
+ if (config.captureBodies) {
59
+ requestBody = truncateToBytes(_chunkFCR77GYMcjs.redactAuditText.call(void 0, raw), config.maxBodyBytes);
60
+ }
34
61
  }
35
62
  };
36
63
  if (config.captureBodies) {
37
64
  installResponseCapture(res, {
38
65
  push(chunk) {
66
+ if (config.maxBodyBytes < 0) {
67
+ responseChunks.push(chunk);
68
+ responseBytes += chunk.length;
69
+ return;
70
+ }
71
+ const remaining = config.maxBodyBytes - responseBytes;
72
+ if (remaining <= 0) {
73
+ responseTruncated = true;
74
+ return;
75
+ }
76
+ if (chunk.length > remaining) {
77
+ responseChunks.push(chunk.subarray(0, remaining));
78
+ responseBytes += remaining;
79
+ responseTruncated = true;
80
+ return;
81
+ }
39
82
  responseChunks.push(chunk);
83
+ responseBytes += chunk.length;
40
84
  }
41
85
  });
42
86
  }
@@ -69,12 +113,13 @@ function beginAuditCapture(req, res, now) {
69
113
  }
70
114
  if (ctx.error) record.error = _chunkFCR77GYMcjs.redactAuditText.call(void 0, ctx.error);
71
115
  if (config.captureBodies) {
72
- if (rawRequestBody != null && rawRequestBody.length > 0) {
73
- record.requestBody = _chunkFCR77GYMcjs.redactAuditText.call(void 0, rawRequestBody);
116
+ if (requestBody != null && requestBody.length > 0) {
117
+ record.requestBody = requestBody;
74
118
  }
75
119
  if (responseChunks.length > 0) {
76
- const body = Buffer.concat(responseChunks).toString("utf8");
77
- record.responseBody = _chunkFCR77GYMcjs.redactAuditText.call(void 0, body);
120
+ const captured = Buffer.concat(responseChunks, responseBytes);
121
+ const body = decodeCapturedBody(captured, responseTruncated);
122
+ record.responseBody = truncateToBytes(_chunkFCR77GYMcjs.redactAuditText.call(void 0, body), config.maxBodyBytes);
78
123
  }
79
124
  }
80
125
  _chunkAEOZIDEBcjs.recordAudit.call(void 0, record);
@@ -0,0 +1,63 @@
1
+ // src/provider-proxy/identity/headerMerge.ts
2
+ function fillMissingHeaders(headers, source) {
3
+ const present = new Set(Object.keys(headers).map((k) => k.toLowerCase()));
4
+ for (const [key, value] of Object.entries(source)) {
5
+ const lower = key.toLowerCase();
6
+ if (present.has(lower)) continue;
7
+ headers[lower] = value;
8
+ present.add(lower);
9
+ }
10
+ }
11
+ function flattenHeaderValue(raw) {
12
+ if (raw === void 0) return void 0;
13
+ const value = Array.isArray(raw) ? raw.filter((v) => typeof v === "string").join(", ") : raw;
14
+ return typeof value === "string" && value.length > 0 ? value : void 0;
15
+ }
16
+ var NEVER_FORWARD_HEADERS = /* @__PURE__ */ new Set([
17
+ "authorization",
18
+ "x-api-key",
19
+ "cookie",
20
+ "proxy-authorization",
21
+ "host",
22
+ "connection",
23
+ "content-length",
24
+ "content-type",
25
+ "accept-encoding"
26
+ ]);
27
+
28
+ // src/provider-proxy/identity/codexCliHeaders.ts
29
+ var DEFAULT_CODEX_CLI_HEADERS = Object.freeze({
30
+ originator: "codex_cli_rs",
31
+ "user-agent": "codex_cli_rs/0.144.5",
32
+ version: "0.144.5"
33
+ });
34
+ var CODEX_FORWARD_ALLOWLIST = /* @__PURE__ */ new Set([
35
+ "version",
36
+ "openai-beta",
37
+ "session_id",
38
+ "originator",
39
+ "user-agent"
40
+ ]);
41
+ function extractCodexClientHeaders(reqHeaders) {
42
+ const out = {};
43
+ for (const [rawKey, rawVal] of Object.entries(reqHeaders)) {
44
+ const key = rawKey.toLowerCase();
45
+ if (NEVER_FORWARD_HEADERS.has(key)) continue;
46
+ if (!CODEX_FORWARD_ALLOWLIST.has(key)) continue;
47
+ const value = flattenHeaderValue(rawVal);
48
+ if (value !== void 0) out[key] = value;
49
+ }
50
+ return out;
51
+ }
52
+ function codexAcceptHeader(isStream) {
53
+ return isStream ? "text/event-stream" : "application/json";
54
+ }
55
+
56
+ export {
57
+ fillMissingHeaders,
58
+ flattenHeaderValue,
59
+ NEVER_FORWARD_HEADERS,
60
+ DEFAULT_CODEX_CLI_HEADERS,
61
+ extractCodexClientHeaders,
62
+ codexAcceptHeader
63
+ };
@@ -2,6 +2,12 @@
2
2
 
3
3
  var _chunkSVNDB62Dcjs = require('./chunk-SVNDB62D.cjs');
4
4
 
5
+
6
+ var _chunk6QQG7YG3cjs = require('./chunk-6QQG7YG3.cjs');
7
+
8
+
9
+ var _chunk25GXJCEZcjs = require('./chunk-25GXJCEZ.cjs');
10
+
5
11
  // src/pipeline/SubscriptionAuthSource.ts
6
12
  function stripAuthHeaders(headers) {
7
13
  delete headers.authorization;
@@ -34,9 +40,12 @@ var SubscriptionAuthSource = class {
34
40
  resolvedModel: hints.model,
35
41
  sessionKey: hints.sessionKey,
36
42
  reportSelection: hints.reportSelection,
37
- preferredAccountId: hints.preferredAccountId
43
+ preferredAccountId: hints.preferredAccountId,
44
+ preferredAccountGroup: hints.preferredAccountGroup,
45
+ boundAccountFallbackPolicy: hints.boundAccountFallbackPolicy
38
46
  });
39
47
  } catch (err) {
48
+ if (_chunk6QQG7YG3cjs.isAccountAllowanceExhaustedError.call(void 0, err) || _chunk25GXJCEZcjs.isBoundAccountSelectionError.call(void 0, err)) throw err;
40
49
  console.warn("[SubscriptionAuthSource] authStrategy.applyHeaders threw:", _chunkSVNDB62Dcjs.serializeError.call(void 0, err));
41
50
  }
42
51
  }
@@ -3,10 +3,12 @@ var OVERLOAD_TTL_MS = 10 * 6e4;
3
3
  var OVERLOAD_ENABLED_DEFAULT = true;
4
4
  var AUTH_ERROR_TTL_MS = 30 * 6e4;
5
5
  var SERVER_ERROR_TTL_MS = 5 * 6e4;
6
+ var MAX_QUOTA_COOLDOWN_MS = 7 * 24 * 60 * 6e4;
6
7
  var BAN_BODY_MARKERS = [
7
8
  "this organization has been disabled",
8
9
  "oauth authentication is currently not allowed"
9
10
  ];
11
+ var ACCOUNT_HEALTH_DIAGNOSTIC_LIMIT = 200;
10
12
  function readHeader(headers, name) {
11
13
  if (typeof headers.get === "function") {
12
14
  return headers.get(name);
@@ -37,19 +39,20 @@ function isBanBody(bodyText) {
37
39
  return BAN_BODY_MARKERS.some((marker) => lower.includes(marker));
38
40
  }
39
41
  function isRecordEmpty(record) {
40
- return record.rateLimitEndAt === void 0 && record.overloadUntil === void 0 && record.tempUnavailableUntil === void 0 && !record.blocked;
42
+ return record.rateLimitEndAt === void 0 && record.overloadUntil === void 0 && record.tempUnavailableUntil === void 0 && record.quotaExhaustedUntil === void 0 && !record.blocked;
41
43
  }
42
44
  var KEY_SEP = "\0";
43
45
  var SubscriptionAccountHealth = (_class = class {
44
46
  __init() {this.records = /* @__PURE__ */ new Map()}
45
47
  __init2() {this.listeners = /* @__PURE__ */ new Set()}
46
48
  __init3() {this.anomalyListeners = /* @__PURE__ */ new Set()}
49
+ __init4() {this.diagnostics = []}
47
50
 
48
51
 
49
52
 
50
53
 
51
54
 
52
- constructor(opts = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);
55
+ constructor(opts = {}) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);
53
56
  this.now = _nullishCoalesce(opts.now, () => ( Date.now));
54
57
  this.overloadEnabled = _nullishCoalesce(opts.overloadEnabled, () => ( OVERLOAD_ENABLED_DEFAULT));
55
58
  this.overloadTtlMs = _nullishCoalesce(opts.overloadTtlMs, () => ( OVERLOAD_TTL_MS));
@@ -71,8 +74,8 @@ var SubscriptionAccountHealth = (_class = class {
71
74
  }
72
75
  /**
73
76
  * Whether an account may be scheduled RIGHT NOW. `blocked` → false; any timer
74
- * still in the future → false. Expired timers are lazily deleted on read (CRS
75
- * lazy-clear parity) so an elapsed cooldown restores the account WITHOUT a
77
+ * still in the future → false. Expired timers are lazily deleted on read so
78
+ * an elapsed cooldown restores the account WITHOUT a
76
79
  * timer — but the recovery SIGNAL is the sweeper's job (`sweepRecoveries`), so
77
80
  * this read never emits (correctness is independent of the tick).
78
81
  */
@@ -86,7 +89,7 @@ var SubscriptionAccountHealth = (_class = class {
86
89
  return !active;
87
90
  }
88
91
  /**
89
- * The single marking entry point (design D3). Faithful to CRS status semantics:
92
+ * The single marking entry point (design D3):
90
93
  * - 429 + authoritative reset → `rateLimitEndAt`; a non-claude 429 may use
91
94
  * `retryAfterSeconds`; a bare 429 (no resolvable reset) is NOT marked;
92
95
  * - 529 → `overloadUntil` (gated by `overloadEnabled`);
@@ -141,9 +144,54 @@ var SubscriptionAccountHealth = (_class = class {
141
144
  }
142
145
  if (isRecordEmpty(record)) this.records.delete(key);
143
146
  else this.records.set(key, record);
144
- if (recovered) this.emit({ providerId, accountId, at: now, kind: "rateLimitRecovery" });
147
+ if (recovered) {
148
+ const recovery = {
149
+ providerId,
150
+ accountId,
151
+ at: now,
152
+ kind: "rateLimitRecovery"
153
+ };
154
+ this.recordDiagnostic({ kind: "health-recovery", providerId, accountId, at: now });
155
+ this.emit(recovery);
156
+ }
145
157
  if (anomalyState && !wasUnhealthyBefore) {
146
- this.emitAnomaly({ providerId, accountId, at: now, state: anomalyState });
158
+ const anomaly = { providerId, accountId, at: now, state: anomalyState };
159
+ this.recordDiagnostic({ kind: "health-anomaly", ...anomaly });
160
+ this.emitAnomaly(anomaly);
161
+ }
162
+ }
163
+ /**
164
+ * Mark an account quota/usage-exhausted until `untilEpochMs` (the Codex weekly
165
+ * usage-limit wall). Unlike the status-driven timers set by
166
+ * {@link recordUpstreamOutcome}, this mark is NOT cleared by a 2xx: in-flight
167
+ * sessions on the same account keep succeeding after the window is exhausted,
168
+ * so a traffic-driven clear would re-strand every NEW session onto this
169
+ * account. It excludes the account from NEW-session selection until the
170
+ * deadline elapses (existing sessions are unaffected — they already hold their
171
+ * token). Self-heals lazily on read and via {@link sweepRecoveries}.
172
+ * `untilEpochMs` is clamped to {@link MAX_QUOTA_COOLDOWN_MS}; an already-elapsed
173
+ * deadline is a no-op. Emits a `quota_exhausted` anomaly on the healthy→
174
+ * unhealthy edge.
175
+ */
176
+ markQuotaExhausted(providerId, accountId, untilEpochMs, now = this.now()) {
177
+ if (!Number.isFinite(untilEpochMs)) return;
178
+ const clamped = Math.min(untilEpochMs, now + MAX_QUOTA_COOLDOWN_MS);
179
+ if (clamped <= now) return;
180
+ const key = this.key(providerId, accountId);
181
+ const preExisting = this.records.get(key);
182
+ const record = _nullishCoalesce(preExisting, () => ( {}));
183
+ const wasUnhealthyBefore = preExisting ? this.isUnhealthyAt(preExisting, now) : false;
184
+ record.quotaExhaustedUntil = clamped;
185
+ this.records.set(key, record);
186
+ if (!wasUnhealthyBefore) {
187
+ const anomaly = {
188
+ providerId,
189
+ accountId,
190
+ at: now,
191
+ state: "quota_exhausted"
192
+ };
193
+ this.recordDiagnostic({ kind: "health-anomaly", ...anomaly });
194
+ this.emitAnomaly(anomaly);
147
195
  }
148
196
  }
149
197
  /** Whether a record is unhealthy at `now`: blocked, or any timer still future. */
@@ -152,6 +200,7 @@ var SubscriptionAccountHealth = (_class = class {
152
200
  if (record.rateLimitEndAt !== void 0 && now < record.rateLimitEndAt) return true;
153
201
  if (record.overloadUntil !== void 0 && now < record.overloadUntil) return true;
154
202
  if (record.tempUnavailableUntil !== void 0 && now < record.tempUnavailableUntil) return true;
203
+ if (record.quotaExhaustedUntil !== void 0 && now < record.quotaExhaustedUntil) return true;
155
204
  return false;
156
205
  }
157
206
  /**
@@ -188,7 +237,7 @@ var SubscriptionAccountHealth = (_class = class {
188
237
  const recovered = [];
189
238
  for (const [key, record] of this.records) {
190
239
  if (record.blocked) continue;
191
- const hadTimer = record.rateLimitEndAt !== void 0 || record.overloadUntil !== void 0 || record.tempUnavailableUntil !== void 0;
240
+ const hadTimer = record.rateLimitEndAt !== void 0 || record.overloadUntil !== void 0 || record.tempUnavailableUntil !== void 0 || record.quotaExhaustedUntil !== void 0;
192
241
  const active = this.clearExpired(record, now);
193
242
  if (hadTimer && !active && isRecordEmpty(record)) {
194
243
  const [pid, aid] = this.parseKey(key);
@@ -196,7 +245,15 @@ var SubscriptionAccountHealth = (_class = class {
196
245
  this.records.delete(key);
197
246
  }
198
247
  }
199
- for (const event of recovered) this.emit(event);
248
+ for (const event of recovered) {
249
+ this.recordDiagnostic({
250
+ kind: "health-recovery",
251
+ providerId: event.providerId,
252
+ accountId: event.accountId,
253
+ at: event.at
254
+ });
255
+ this.emit(event);
256
+ }
200
257
  return recovered;
201
258
  }
202
259
  /** Admin-facing coarse status + cooldown-until for one account (secret-free). */
@@ -204,6 +261,9 @@ var SubscriptionAccountHealth = (_class = class {
204
261
  const record = this.records.get(this.key(providerId, accountId));
205
262
  if (!record) return { state: "healthy" };
206
263
  if (record.blocked) return { state: "blocked" };
264
+ if (record.quotaExhaustedUntil !== void 0 && now < record.quotaExhaustedUntil) {
265
+ return { state: "quota_exhausted", cooldownUntil: record.quotaExhaustedUntil };
266
+ }
207
267
  if (record.rateLimitEndAt !== void 0 && now < record.rateLimitEndAt) {
208
268
  return { state: "rate_limited", cooldownUntil: record.rateLimitEndAt };
209
269
  }
@@ -215,6 +275,14 @@ var SubscriptionAccountHealth = (_class = class {
215
275
  }
216
276
  return { state: "healthy" };
217
277
  }
278
+ /** Return newest-first, bounded, secret-free health edge diagnostics. */
279
+ getDiagnostics(filter = {}) {
280
+ const requested = typeof filter.limit === "number" && Number.isFinite(filter.limit) ? Math.trunc(filter.limit) : ACCOUNT_HEALTH_DIAGNOSTIC_LIMIT;
281
+ const limit = Math.min(ACCOUNT_HEALTH_DIAGNOSTIC_LIMIT, Math.max(1, requested));
282
+ return this.diagnostics.filter(
283
+ (event) => (!filter.providerId || event.providerId === filter.providerId) && (!filter.accountId || event.accountId === filter.accountId)
284
+ ).slice(-limit).reverse().map((event) => ({ ...event }));
285
+ }
218
286
  /**
219
287
  * Register a recovery listener (the OQ3 seam #5 webhooks + #8 health-cron
220
288
  * consume). Returns an unsubscribe function. Two edges fire it:
@@ -257,6 +325,12 @@ var SubscriptionAccountHealth = (_class = class {
257
325
  }
258
326
  }
259
327
  }
328
+ recordDiagnostic(event) {
329
+ this.diagnostics.push({ ...event });
330
+ if (this.diagnostics.length > ACCOUNT_HEALTH_DIAGNOSTIC_LIMIT) {
331
+ this.diagnostics.splice(0, this.diagnostics.length - ACCOUNT_HEALTH_DIAGNOSTIC_LIMIT);
332
+ }
333
+ }
260
334
  /**
261
335
  * Delete every EXPIRED timer field on the record in place; return whether any
262
336
  * timer is STILL active (in the future). `blocked` is not a timer and is left
@@ -276,6 +350,10 @@ var SubscriptionAccountHealth = (_class = class {
276
350
  if (now >= record.tempUnavailableUntil) delete record.tempUnavailableUntil;
277
351
  else active = true;
278
352
  }
353
+ if (record.quotaExhaustedUntil !== void 0) {
354
+ if (now >= record.quotaExhaustedUntil) delete record.quotaExhaustedUntil;
355
+ else active = true;
356
+ }
279
357
  return active;
280
358
  }
281
359
  key(providerId, accountId) {
@@ -308,4 +386,6 @@ function __resetSharedAccountHealthForTests() {
308
386
 
309
387
 
310
388
 
311
- exports.OVERLOAD_TTL_MS = OVERLOAD_TTL_MS; exports.OVERLOAD_ENABLED_DEFAULT = OVERLOAD_ENABLED_DEFAULT; exports.AUTH_ERROR_TTL_MS = AUTH_ERROR_TTL_MS; exports.SERVER_ERROR_TTL_MS = SERVER_ERROR_TTL_MS; exports.resolveResetSeconds = resolveResetSeconds; exports.SubscriptionAccountHealth = SubscriptionAccountHealth; exports.getSharedAccountHealth = getSharedAccountHealth; exports.setSharedAccountHealth = setSharedAccountHealth; exports.__resetSharedAccountHealthForTests = __resetSharedAccountHealthForTests;
389
+
390
+
391
+ exports.OVERLOAD_TTL_MS = OVERLOAD_TTL_MS; exports.OVERLOAD_ENABLED_DEFAULT = OVERLOAD_ENABLED_DEFAULT; exports.AUTH_ERROR_TTL_MS = AUTH_ERROR_TTL_MS; exports.SERVER_ERROR_TTL_MS = SERVER_ERROR_TTL_MS; exports.MAX_QUOTA_COOLDOWN_MS = MAX_QUOTA_COOLDOWN_MS; exports.ACCOUNT_HEALTH_DIAGNOSTIC_LIMIT = ACCOUNT_HEALTH_DIAGNOSTIC_LIMIT; exports.resolveResetSeconds = resolveResetSeconds; exports.SubscriptionAccountHealth = SubscriptionAccountHealth; exports.getSharedAccountHealth = getSharedAccountHealth; exports.setSharedAccountHealth = setSharedAccountHealth; exports.__resetSharedAccountHealthForTests = __resetSharedAccountHealthForTests;
@@ -80,6 +80,18 @@ var ApiKeyPoolService = (_class = class {
80
80
  });
81
81
  return this.resolveKey(selected.apiKey);
82
82
  }
83
+ /**
84
+ * Bind a session to one explicit provider key. Returns an empty string when
85
+ * the key is unknown, disabled, or cooling so the caller can apply its strict
86
+ * versus pool fallback policy without exposing key material.
87
+ */
88
+ async getKeyById(providerId, keyId, sessionId) {
89
+ const keys = await this.getAvailableKeys(providerId);
90
+ const selected = keys.find((key) => key.id === keyId);
91
+ if (!selected) return "";
92
+ if (sessionId) this.sessionBindings.set(sessionId, { keyId: selected.id, providerId });
93
+ return this.resolveKey(selected.apiKey);
94
+ }
83
95
  /**
84
96
  * Get a key without session affinity (for one-shot calls like testConnection).
85
97
  *
@@ -71,6 +71,12 @@ declare class ApiKeyPoolService {
71
71
  */
72
72
  getKeyIdForSession(providerId: string, sessionId: string): string | null;
73
73
  getKeyForSession(providerId: string, sessionId: string): Promise<string>;
74
+ /**
75
+ * Bind a session to one explicit provider key. Returns an empty string when
76
+ * the key is unknown, disabled, or cooling so the caller can apply its strict
77
+ * versus pool fallback policy without exposing key material.
78
+ */
79
+ getKeyById(providerId: string, keyId: string, sessionId?: string | null): Promise<string>;
74
80
  /**
75
81
  * Get a key without session affinity (for one-shot calls like testConnection).
76
82
  *
@@ -71,6 +71,12 @@ declare class ApiKeyPoolService {
71
71
  */
72
72
  getKeyIdForSession(providerId: string, sessionId: string): string | null;
73
73
  getKeyForSession(providerId: string, sessionId: string): Promise<string>;
74
+ /**
75
+ * Bind a session to one explicit provider key. Returns an empty string when
76
+ * the key is unknown, disabled, or cooling so the caller can apply its strict
77
+ * versus pool fallback policy without exposing key material.
78
+ */
79
+ getKeyById(providerId: string, keyId: string, sessionId?: string | null): Promise<string>;
74
80
  /**
75
81
  * Get a key without session affinity (for one-shot calls like testConnection).
76
82
  *
@@ -80,6 +80,18 @@ var ApiKeyPoolService = class {
80
80
  });
81
81
  return this.resolveKey(selected.apiKey);
82
82
  }
83
+ /**
84
+ * Bind a session to one explicit provider key. Returns an empty string when
85
+ * the key is unknown, disabled, or cooling so the caller can apply its strict
86
+ * versus pool fallback policy without exposing key material.
87
+ */
88
+ async getKeyById(providerId, keyId, sessionId) {
89
+ const keys = await this.getAvailableKeys(providerId);
90
+ const selected = keys.find((key) => key.id === keyId);
91
+ if (!selected) return "";
92
+ if (sessionId) this.sessionBindings.set(sessionId, { keyId: selected.id, providerId });
93
+ return this.resolveKey(selected.apiKey);
94
+ }
83
95
  /**
84
96
  * Get a key without session affinity (for one-shot calls like testConnection).
85
97
  *