@omnicross/core 0.1.2 → 0.1.4

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 (184) hide show
  1. package/LICENSE +21 -21
  2. package/NOTICE +57 -57
  3. package/README.md +15 -15
  4. package/dist/auth/GeminiCodeAssistProjectResolver.cjs +6 -1
  5. package/dist/auth/GeminiCodeAssistProjectResolver.js +6 -1
  6. package/dist/chunk-3QFXFCHG.js +33 -0
  7. package/dist/chunk-4IH4EL7M.cjs +9 -0
  8. package/dist/chunk-4YINUUKQ.cjs +33 -0
  9. package/dist/chunk-5ENKBSWO.js +311 -0
  10. package/dist/chunk-6RPZADX3.cjs +92 -0
  11. package/dist/chunk-7Y47UCF2.js +142 -0
  12. package/dist/chunk-AEOZIDEB.cjs +32 -0
  13. package/dist/chunk-APYG5QD7.cjs +50 -0
  14. package/dist/{chunk-MNYKI4CI.js → chunk-BPKCU575.js} +29 -0
  15. package/dist/{chunk-SN3YWBX7.cjs → chunk-DKPXN34V.cjs} +2108 -538
  16. package/dist/{chunk-4NBS6KPV.cjs → chunk-DQ5VAYZ6.cjs} +7 -8
  17. package/dist/chunk-E3UCVHLP.cjs +142 -0
  18. package/dist/chunk-FCR77GYM.cjs +33 -0
  19. package/dist/{chunk-74TMJA7Z.js → chunk-HRRYG2AX.js} +8 -4
  20. package/dist/chunk-HUZZZ3JL.js +32 -0
  21. package/dist/{chunk-KUU2RNG6.cjs → chunk-HYN75H6G.cjs} +3 -0
  22. package/dist/{chunk-QOCNX236.js → chunk-IAXWICZU.js} +24 -1
  23. package/dist/{chunk-JO5NLTLY.js → chunk-IK3KE3AU.js} +3 -0
  24. package/dist/{chunk-V5KPWNYX.cjs → chunk-JMJBSACD.cjs} +3 -3
  25. package/dist/chunk-K5NM7VAH.js +33 -0
  26. package/dist/{chunk-N3V2J5ZO.cjs → chunk-KFI44N2R.cjs} +8 -4
  27. package/dist/chunk-L74VDN4A.cjs +32 -0
  28. package/dist/chunk-OCEUVQHW.cjs +112 -0
  29. package/dist/chunk-OE6TDIWW.js +22 -0
  30. package/dist/chunk-OZFM4X3S.js +18 -0
  31. package/dist/{chunk-LKZJEL6E.cjs → chunk-Q27JY5RG.cjs} +6 -4
  32. package/dist/{chunk-SPVWWUHX.cjs → chunk-QWBWGODS.cjs} +24 -1
  33. package/dist/{chunk-2FEVTJWG.js → chunk-QYTT6GE3.js} +1929 -359
  34. package/dist/{chunk-UYPEN5XE.cjs → chunk-RGTR7CIO.cjs} +6 -6
  35. package/dist/chunk-RPII3E6Z.cjs +145 -0
  36. package/dist/{chunk-XBSYYZIY.cjs → chunk-SNYBEXLB.cjs} +31 -2
  37. package/dist/{chunk-2DCNB7DF.cjs → chunk-SU2GCLAC.cjs} +30 -10
  38. package/dist/{chunk-5HTVET6E.js → chunk-TIER4SUC.js} +24 -4
  39. package/dist/chunk-TKJMZBAH.js +32 -0
  40. package/dist/{chunk-ZSVQT3PW.js → chunk-UBWEBKRC.js} +5 -6
  41. package/dist/chunk-UHGVBFU3.js +385 -0
  42. package/dist/chunk-UIBD2YY5.cjs +22 -0
  43. package/dist/chunk-UNEFIWXI.cjs +32 -0
  44. package/dist/chunk-VACWOIRE.cjs +385 -0
  45. package/dist/{chunk-O466Y272.js → chunk-VPBAUQ2M.js} +7 -7
  46. package/dist/chunk-VQY5W4YW.cjs +311 -0
  47. package/dist/chunk-WLYIIEAF.js +50 -0
  48. package/dist/chunk-WNY4WMRF.js +32 -0
  49. package/dist/chunk-XEKD23J5.js +9 -0
  50. package/dist/chunk-XK5CIRMQ.js +112 -0
  51. package/dist/chunk-XSVNC2UD.cjs +18 -0
  52. package/dist/chunk-XTEI64OU.js +145 -0
  53. package/dist/chunk-XX6NQJMA.js +92 -0
  54. package/dist/{chunk-745DV5FL.js → chunk-Y7FO65VT.js} +3 -3
  55. package/dist/{chunk-PXUJF5HS.js → chunk-ZY6KU6P3.js} +4 -2
  56. package/dist/completion/CompletionService.cjs +30 -17
  57. package/dist/completion/CompletionService.js +29 -16
  58. package/dist/completion/NativeSearchInjector.cjs +3 -3
  59. package/dist/completion/NativeSearchInjector.js +2 -2
  60. package/dist/completion/openrouter-headers.cjs +3 -6
  61. package/dist/completion/openrouter-headers.d.cts +9 -12
  62. package/dist/completion/openrouter-headers.d.ts +9 -12
  63. package/dist/completion/openrouter-headers.js +2 -5
  64. package/dist/completion/openrouter-models.cjs +4 -3
  65. package/dist/completion/openrouter-models.js +2 -1
  66. package/dist/completion.cjs +30 -17
  67. package/dist/completion.js +29 -16
  68. package/dist/index.cjs +151 -20
  69. package/dist/index.d.cts +44 -10
  70. package/dist/index.d.ts +44 -10
  71. package/dist/index.js +160 -29
  72. package/dist/keyPolicy-Cp0FntZl.d.cts +90 -0
  73. package/dist/keyPolicy-Cp0FntZl.d.ts +90 -0
  74. package/dist/outbound-api/auditCapture.cjs +9 -0
  75. package/dist/outbound-api/auditCapture.d.cts +52 -0
  76. package/dist/outbound-api/auditCapture.d.ts +52 -0
  77. package/dist/outbound-api/auditCapture.js +9 -0
  78. package/dist/outbound-api/auditRedact.cjs +8 -0
  79. package/dist/outbound-api/auditRedact.d.cts +30 -0
  80. package/dist/outbound-api/auditRedact.d.ts +30 -0
  81. package/dist/outbound-api/auditRedact.js +8 -0
  82. package/dist/outbound-api/billingCapture.cjs +8 -0
  83. package/dist/outbound-api/billingCapture.d.cts +61 -0
  84. package/dist/outbound-api/billingCapture.d.ts +61 -0
  85. package/dist/outbound-api/billingCapture.js +8 -0
  86. package/dist/outbound-api/quotaWarn.cjs +12 -0
  87. package/dist/outbound-api/quotaWarn.d.cts +43 -0
  88. package/dist/outbound-api/quotaWarn.d.ts +43 -0
  89. package/dist/outbound-api/quotaWarn.js +12 -0
  90. package/dist/outbound-api/routeResolver.cjs +5 -2
  91. package/dist/outbound-api/routeResolver.d.cts +9 -2
  92. package/dist/outbound-api/routeResolver.d.ts +9 -2
  93. package/dist/outbound-api/routeResolver.js +4 -1
  94. package/dist/outbound-api/types.cjs +6 -1
  95. package/dist/outbound-api/types.d.cts +12 -144
  96. package/dist/outbound-api/types.d.ts +12 -144
  97. package/dist/outbound-api/types.js +6 -0
  98. package/dist/outbound-api.cjs +144 -17
  99. package/dist/outbound-api.d.cts +655 -25
  100. package/dist/outbound-api.d.ts +655 -25
  101. package/dist/outbound-api.js +148 -21
  102. package/dist/pipeline/AuthSource.d.cts +29 -1
  103. package/dist/pipeline/AuthSource.d.ts +29 -1
  104. package/dist/pipeline/LlmConfigProviderAuth.cjs +3 -3
  105. package/dist/pipeline/LlmConfigProviderAuth.js +2 -2
  106. package/dist/pipeline/SubscriptionAccountHealth.cjs +22 -0
  107. package/dist/pipeline/SubscriptionAccountHealth.d.cts +235 -0
  108. package/dist/pipeline/SubscriptionAccountHealth.d.ts +235 -0
  109. package/dist/pipeline/SubscriptionAccountHealth.js +22 -0
  110. package/dist/pipeline/SubscriptionAuthSource.cjs +2 -2
  111. package/dist/pipeline/SubscriptionAuthSource.d.cts +3 -2
  112. package/dist/pipeline/SubscriptionAuthSource.d.ts +3 -2
  113. package/dist/pipeline/SubscriptionAuthSource.js +1 -1
  114. package/dist/pipeline/SubscriptionAuthStrategy.d.cts +30 -1
  115. package/dist/pipeline/SubscriptionAuthStrategy.d.ts +30 -1
  116. package/dist/pipeline/auditSink.cjs +14 -0
  117. package/dist/pipeline/auditSink.d.cts +48 -0
  118. package/dist/pipeline/auditSink.d.ts +48 -0
  119. package/dist/pipeline/auditSink.js +14 -0
  120. package/dist/pipeline/auditUsageStash.cjs +10 -0
  121. package/dist/pipeline/auditUsageStash.d.cts +37 -0
  122. package/dist/pipeline/auditUsageStash.d.ts +37 -0
  123. package/dist/pipeline/auditUsageStash.js +10 -0
  124. package/dist/pipeline/billingEmit.cjs +14 -0
  125. package/dist/pipeline/billingEmit.d.cts +49 -0
  126. package/dist/pipeline/billingEmit.d.ts +49 -0
  127. package/dist/pipeline/billingEmit.js +14 -0
  128. package/dist/pipeline/executeProviderCall.cjs +2 -2
  129. package/dist/pipeline/executeProviderCall.js +1 -1
  130. package/dist/pipeline/upstreamFetch.cjs +14 -0
  131. package/dist/pipeline/upstreamFetch.d.cts +83 -0
  132. package/dist/pipeline/upstreamFetch.d.ts +83 -0
  133. package/dist/pipeline/upstreamFetch.js +14 -0
  134. package/dist/pipeline/webhookEmit.cjs +10 -0
  135. package/dist/pipeline/webhookEmit.d.cts +36 -0
  136. package/dist/pipeline/webhookEmit.d.ts +36 -0
  137. package/dist/pipeline/webhookEmit.js +10 -0
  138. package/dist/ports/usage-event-store.d.cts +26 -1
  139. package/dist/ports/usage-event-store.d.ts +26 -1
  140. package/dist/ports.d.cts +8 -1
  141. package/dist/ports.d.ts +8 -1
  142. package/dist/provider-proxy/ProviderProxy.cjs +30 -17
  143. package/dist/provider-proxy/ProviderProxy.js +29 -16
  144. package/dist/provider-proxy/identity/SubscriptionIdentityStore.cjs +15 -0
  145. package/dist/provider-proxy/identity/SubscriptionIdentityStore.d.cts +121 -0
  146. package/dist/provider-proxy/identity/SubscriptionIdentityStore.d.ts +121 -0
  147. package/dist/provider-proxy/identity/SubscriptionIdentityStore.js +15 -0
  148. package/dist/provider-proxy/identity/fingerprintHeaders.cjs +20 -0
  149. package/dist/provider-proxy/identity/fingerprintHeaders.d.cts +89 -0
  150. package/dist/provider-proxy/identity/fingerprintHeaders.d.ts +89 -0
  151. package/dist/provider-proxy/identity/fingerprintHeaders.js +20 -0
  152. package/dist/provider-proxy/ingress/providerProxyShared.cjs +30 -17
  153. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +11 -2
  154. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +11 -2
  155. package/dist/provider-proxy/ingress/providerProxyShared.js +29 -16
  156. package/dist/provider-proxy/matchText.cjs +4 -2
  157. package/dist/provider-proxy/matchText.d.cts +14 -1
  158. package/dist/provider-proxy/matchText.d.ts +14 -1
  159. package/dist/provider-proxy/matchText.js +3 -1
  160. package/dist/provider-proxy/types.d.cts +30 -0
  161. package/dist/provider-proxy/types.d.ts +30 -0
  162. package/dist/provider-proxy.cjs +30 -17
  163. package/dist/provider-proxy.js +29 -16
  164. package/dist/{routeResolver-HE-ZO0fO.d.ts → routeResolver-C4T7yClx.d.ts} +36 -10
  165. package/dist/{routeResolver-BrbK6ja9.d.cts → routeResolver-CB3tvJKy.d.cts} +36 -10
  166. package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +2 -2
  167. package/dist/transformer/transformers/OpenAIResponseTransformer.js +1 -1
  168. package/dist/transformer/transformers.cjs +7 -7
  169. package/dist/transformer/transformers.js +8 -8
  170. package/dist/transformer.cjs +9 -9
  171. package/dist/transformer.js +8 -8
  172. package/dist/types-B8Arpxn0.d.cts +754 -0
  173. package/dist/types-lgPYQuZS.d.ts +754 -0
  174. package/dist/usage/usage-recorder.cjs +3 -2
  175. package/dist/usage/usage-recorder.d.cts +19 -1
  176. package/dist/usage/usage-recorder.d.ts +19 -1
  177. package/dist/usage/usage-recorder.js +2 -1
  178. package/dist/usage.cjs +3 -2
  179. package/dist/usage.js +2 -1
  180. package/package.json +64 -62
  181. package/dist/chunk-3MEACFK3.js +0 -193
  182. package/dist/chunk-6VIXXLMX.cjs +0 -14
  183. package/dist/chunk-E3WHL7CO.js +0 -14
  184. package/dist/chunk-G2FUJNA2.cjs +0 -193
@@ -1,9 +1,15 @@
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;
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
- var _chunkSPVWWUHXcjs = require('./chunk-SPVWWUHX.cjs');
3
+ var _chunkHQP3K7PUcjs = require('./chunk-HQP3K7PU.cjs');
4
4
 
5
5
 
6
- var _chunkHQP3K7PUcjs = require('./chunk-HQP3K7PU.cjs');
6
+ var _chunk4VAVYUZScjs = require('./chunk-4VAVYUZS.cjs');
7
+
8
+
9
+ var _chunk7YN22L2Hcjs = require('./chunk-7YN22L2H.cjs');
10
+
11
+
12
+ var _chunkSU2GCLACcjs = require('./chunk-SU2GCLAC.cjs');
7
13
 
8
14
 
9
15
  var _chunk46ZIFWYGcjs = require('./chunk-46ZIFWYG.cjs');
@@ -12,23 +18,28 @@ var _chunk46ZIFWYGcjs = require('./chunk-46ZIFWYG.cjs');
12
18
  var _chunkGBHYAGX3cjs = require('./chunk-GBHYAGX3.cjs');
13
19
 
14
20
 
15
- var _chunk7YN22L2Hcjs = require('./chunk-7YN22L2H.cjs');
21
+ var _chunkRPII3E6Zcjs = require('./chunk-RPII3E6Z.cjs');
16
22
 
17
23
 
18
- var _chunk2DCNB7DFcjs = require('./chunk-2DCNB7DF.cjs');
19
24
 
25
+ var _chunk6RPZADX3cjs = require('./chunk-6RPZADX3.cjs');
20
26
 
21
- var _chunk4VAVYUZScjs = require('./chunk-4VAVYUZS.cjs');
27
+
28
+
29
+ var _chunkQWBWGODScjs = require('./chunk-QWBWGODS.cjs');
30
+
31
+
32
+ var _chunkUIBD2YY5cjs = require('./chunk-UIBD2YY5.cjs');
22
33
 
23
34
 
24
35
  var _chunkR3HK6R4Bcjs = require('./chunk-R3HK6R4B.cjs');
25
36
 
26
37
 
27
- var _chunkKUU2RNG6cjs = require('./chunk-KUU2RNG6.cjs');
38
+ var _chunkHYN75H6Gcjs = require('./chunk-HYN75H6G.cjs');
28
39
 
29
40
 
30
41
 
31
- var _chunkLKZJEL6Ecjs = require('./chunk-LKZJEL6E.cjs');
42
+ var _chunkQ27JY5RGcjs = require('./chunk-Q27JY5RG.cjs');
32
43
 
33
44
 
34
45
  var _chunkQXD4MV2Xcjs = require('./chunk-QXD4MV2X.cjs');
@@ -37,33 +48,57 @@ var _chunkQXD4MV2Xcjs = require('./chunk-QXD4MV2X.cjs');
37
48
  var _chunkNYUNU75Acjs = require('./chunk-NYUNU75A.cjs');
38
49
 
39
50
 
40
- var _chunkN3V2J5ZOcjs = require('./chunk-N3V2J5ZO.cjs');
51
+
52
+ var _chunkVQY5W4YWcjs = require('./chunk-VQY5W4YW.cjs');
53
+
54
+
55
+ var _chunkKFI44N2Rcjs = require('./chunk-KFI44N2R.cjs');
41
56
 
42
57
 
43
58
  var _chunkSVNDB62Dcjs = require('./chunk-SVNDB62D.cjs');
44
59
 
45
60
 
61
+ var _chunkAPYG5QD7cjs = require('./chunk-APYG5QD7.cjs');
62
+
63
+
64
+
65
+ var _chunk4YINUUKQcjs = require('./chunk-4YINUUKQ.cjs');
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+ var _chunkVACWOIREcjs = require('./chunk-VACWOIRE.cjs');
76
+
77
+
46
78
 
47
79
 
48
80
  var _chunkA2YMUCBTcjs = require('./chunk-A2YMUCBT.cjs');
49
81
 
50
82
 
51
- var _chunkG2FUJNA2cjs = require('./chunk-G2FUJNA2.cjs');
83
+ var _chunkE3UCVHLPcjs = require('./chunk-E3UCVHLP.cjs');
52
84
 
53
85
 
54
86
 
55
87
  var _chunkSUEGJ75Dcjs = require('./chunk-SUEGJ75D.cjs');
56
88
 
57
89
 
58
- var _chunkV5KPWNYXcjs = require('./chunk-V5KPWNYX.cjs');
59
-
90
+ var _chunkOCEUVQHWcjs = require('./chunk-OCEUVQHW.cjs');
60
91
 
61
92
 
62
- var _chunk6VIXXLMXcjs = require('./chunk-6VIXXLMX.cjs');
93
+ var _chunkJMJBSACDcjs = require('./chunk-JMJBSACD.cjs');
63
94
 
64
95
 
65
96
  var _chunkGMMT7RVNcjs = require('./chunk-GMMT7RVN.cjs');
66
97
 
98
+
99
+
100
+ var _chunkUNEFIWXIcjs = require('./chunk-UNEFIWXI.cjs');
101
+
67
102
  // src/completion/StreamEventBuffer.ts
68
103
  var TERMINAL_TYPES = /* @__PURE__ */ new Set(["done", "error", "abort"]);
69
104
  var QUEUE_CAP = 200;
@@ -325,7 +360,7 @@ function convertMessageToGemini(msg) {
325
360
 
326
361
  // src/completion/openrouter-utils.ts
327
362
  function getOpenRouterProviderConfig(provider, modelId) {
328
- if (!_chunk6VIXXLMXcjs.isOpenRouterProvider.call(void 0, provider)) {
363
+ if (!_chunkUNEFIWXIcjs.isOpenRouterProvider.call(void 0, provider)) {
329
364
  return void 0;
330
365
  }
331
366
  const modelConfig = _optionalChain([provider, 'access', _ => _.modelConfigs, 'optionalAccess', _2 => _2.find, 'call', _3 => _3((m) => m.id === modelId)]);
@@ -462,10 +497,11 @@ function recordAnthropicNonStreamUsage(recorder, bodyText, attribution) {
462
497
  sessionId: attribution.sessionId,
463
498
  providerId: attribution.providerId,
464
499
  model: attribution.model,
465
- apiKeyId: null,
500
+ apiKeyId: attribution.apiKeyId,
466
501
  engineOrigin: "codex-ingress",
467
502
  usage: tapped,
468
- rawUsage: parsed.usage
503
+ rawUsage: parsed.usage,
504
+ auditResponse: attribution.auditResponse
469
505
  });
470
506
  } catch (e4) {
471
507
  }
@@ -481,7 +517,7 @@ function getSharedExecutor() {
481
517
  }
482
518
  var sharedResponses = null;
483
519
  function getResponsesEndpointTransformer() {
484
- if (!sharedResponses) sharedResponses = new (0, _chunk2DCNB7DFcjs.OpenAIResponseTransformer)();
520
+ if (!sharedResponses) sharedResponses = new (0, _chunkSU2GCLACcjs.OpenAIResponseTransformer)();
485
521
  return sharedResponses;
486
522
  }
487
523
  var sharedAnthropic = null;
@@ -502,7 +538,84 @@ function readBody(req) {
502
538
  req.on("error", reject);
503
539
  });
504
540
  }
505
- async function relayResponse(res, providerResponse, isStream) {
541
+ function rewriteJsonModel(bodyText, rewriteModel) {
542
+ try {
543
+ const obj = JSON.parse(bodyText);
544
+ if (!obj || typeof obj !== "object") return bodyText;
545
+ let changed = false;
546
+ if (typeof obj.model === "string") {
547
+ obj.model = rewriteModel;
548
+ changed = true;
549
+ }
550
+ const nested = obj.response;
551
+ if (nested && typeof nested === "object" && typeof nested.model === "string") {
552
+ nested.model = rewriteModel;
553
+ changed = true;
554
+ }
555
+ return changed ? JSON.stringify(obj) : bodyText;
556
+ } catch (e5) {
557
+ return bodyText;
558
+ }
559
+ }
560
+ function rewriteSseLine(line, rewriteModel) {
561
+ if (!line.startsWith("data:") || !line.includes('"model"')) return line;
562
+ const nl = /\r?\n$/.exec(line);
563
+ const newline = nl ? nl[0] : "";
564
+ const withoutNl = newline ? line.slice(0, line.length - newline.length) : line;
565
+ const afterData = withoutNl.slice("data:".length);
566
+ const leadingSpace = afterData.startsWith(" ") ? " " : "";
567
+ const payload = afterData.slice(leadingSpace.length);
568
+ if (payload === "" || payload === "[DONE]") return line;
569
+ try {
570
+ const obj = JSON.parse(payload);
571
+ if (!obj || typeof obj !== "object") return line;
572
+ const type = typeof obj.type === "string" ? obj.type : "";
573
+ let changed = false;
574
+ if (type === "message_start") {
575
+ const message = obj.message;
576
+ if (message && typeof message === "object" && typeof message.model === "string") {
577
+ message.model = rewriteModel;
578
+ changed = true;
579
+ }
580
+ } else if (type === "response.created" || type === "response.in_progress" || type === "response.completed" || type === "response.failed" || type === "response.incomplete") {
581
+ const response = obj.response;
582
+ if (response && typeof response === "object" && typeof response.model === "string") {
583
+ response.model = rewriteModel;
584
+ changed = true;
585
+ }
586
+ }
587
+ if (!changed) return line;
588
+ return `data:${leadingSpace}${JSON.stringify(obj)}${newline}`;
589
+ } catch (e6) {
590
+ return line;
591
+ }
592
+ }
593
+ async function relayStreamWithModelRewrite(res, body, rewriteModel) {
594
+ const reader = body.getReader();
595
+ const decoder = new TextDecoder();
596
+ let buffer = "";
597
+ try {
598
+ for (; ; ) {
599
+ const { done, value } = await reader.read();
600
+ if (done) break;
601
+ buffer += decoder.decode(value, { stream: true });
602
+ let out = "";
603
+ let nlIndex;
604
+ while ((nlIndex = buffer.indexOf("\n")) !== -1) {
605
+ const linePart = buffer.slice(0, nlIndex + 1);
606
+ buffer = buffer.slice(nlIndex + 1);
607
+ out += rewriteSseLine(linePart, rewriteModel);
608
+ }
609
+ if (out) res.write(out);
610
+ }
611
+ const tail = buffer + decoder.decode();
612
+ if (tail) res.write(rewriteSseLine(tail, rewriteModel));
613
+ } finally {
614
+ reader.releaseLock();
615
+ res.end();
616
+ }
617
+ }
618
+ async function relayResponse(res, providerResponse, isStream, rewriteModel) {
506
619
  const contentType = _nullishCoalesce(providerResponse.headers.get("Content-Type"), () => ( ""));
507
620
  const status = providerResponse.status && providerResponse.status >= 100 ? providerResponse.status : 200;
508
621
  if (isStream || contentType.includes("text/event-stream")) {
@@ -515,6 +628,10 @@ async function relayResponse(res, providerResponse, isStream) {
515
628
  res.end();
516
629
  return null;
517
630
  }
631
+ if (rewriteModel) {
632
+ await relayStreamWithModelRewrite(res, providerResponse.body, rewriteModel);
633
+ return null;
634
+ }
518
635
  const reader = providerResponse.body.getReader();
519
636
  try {
520
637
  for (; ; ) {
@@ -529,8 +646,9 @@ async function relayResponse(res, providerResponse, isStream) {
529
646
  return null;
530
647
  }
531
648
  const bodyText = await providerResponse.text();
649
+ const clientText = rewriteModel ? rewriteJsonModel(bodyText, rewriteModel) : bodyText;
532
650
  res.writeHead(status, { "Content-Type": contentType.includes("json") ? contentType : "application/json" });
533
- res.end(bodyText);
651
+ res.end(clientText);
534
652
  return bodyText;
535
653
  }
536
654
  function writeError(res, status, message) {
@@ -568,17 +686,18 @@ async function buildSubscriptionPlan(res, route, deps, anthropicBody, routeModel
568
686
  resolvedModel = mapped.resolvedModel;
569
687
  scenario = mapped.scenario;
570
688
  }
571
- const plan = buildSubscriptionIterationPlan(profile, route, deps, resolvedModel, isStream, scenario);
689
+ const sessionKey = _chunkQWBWGODScjs.deriveSubscriptionSessionKey.call(void 0, anthropicBody);
690
+ const plan = buildSubscriptionIterationPlan(profile, route, deps, resolvedModel, isStream, scenario, sessionKey);
572
691
  if (!plan) {
573
692
  writeError(res, 502, "Subscription profile is missing resolveUpstreamUrl");
574
693
  return null;
575
694
  }
576
695
  return plan;
577
696
  }
578
- function buildSubscriptionIterationPlan(profile, route, deps, resolvedModel, isStream, scenario) {
697
+ function buildSubscriptionIterationPlan(profile, route, deps, resolvedModel, isStream, scenario, sessionKey) {
579
698
  const upstreamUrl = _optionalChain([profile, 'access', _8 => _8.resolveUpstreamUrl, 'optionalCall', _9 => _9(resolvedModel, route.subscriptionConfig)]);
580
699
  if (!upstreamUrl) return null;
581
- const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkN3V2J5ZOcjs.SubscriptionAuthSource)(profile)));
700
+ const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkKFI44N2Rcjs.SubscriptionAuthSource)(profile)));
582
701
  const sameFormat = profile.mode === "pass-through" || upstreamUrl.endsWith("/v1/messages");
583
702
  const overrideNames = _optionalChain([profile, 'access', _10 => _10.resolveProviderTransformerNames, 'optionalCall', _11 => _11(
584
703
  resolvedModel,
@@ -598,6 +717,7 @@ function buildSubscriptionIterationPlan(profile, route, deps, resolvedModel, isS
598
717
  };
599
718
  return {
600
719
  auth,
720
+ preferredAccountId: route.preferredAccountId,
601
721
  chain,
602
722
  transformerProvider,
603
723
  resolvedModel,
@@ -622,7 +742,8 @@ function buildSubscriptionIterationPlan(profile, route, deps, resolvedModel, isS
622
742
  upstreamUrl,
623
743
  sameFormat,
624
744
  isSubscription: true,
625
- scenario
745
+ scenario,
746
+ sessionKey
626
747
  };
627
748
  }
628
749
  function usesResponsesChain(names) {
@@ -641,7 +762,7 @@ function buildSubscriptionRequestSummary(anthropicBody) {
641
762
  estimatedInputTokens: Math.ceil(totalChars / 4),
642
763
  // Single source of truth (shared with the dispatcher builder) so both
643
764
  // ingress paths yield identical `matchText` for the same body.
644
- matchText: _chunkSPVWWUHXcjs.collectMatchText.call(void 0, anthropicBody)
765
+ matchText: _chunkQWBWGODScjs.collectMatchText.call(void 0, anthropicBody)
645
766
  };
646
767
  }
647
768
  function collectText(value) {
@@ -657,14 +778,27 @@ function collectText(value) {
657
778
  }
658
779
  return 0;
659
780
  }
660
- async function runPipeline(anthropicBody, plan) {
781
+ function proxyProviderId(plan) {
782
+ return plan.isSubscription ? plan.transformerProvider.name : "byo";
783
+ }
784
+ async function runPipeline(anthropicBody, plan, reportSelection) {
661
785
  const executor = getSharedExecutor();
662
786
  const endpointTransformer = getAnthropicEndpointTransformer();
663
787
  const { auth, chain, transformerProvider, resolvedModel, isStream, resolveUrl, upstreamUrl } = plan;
788
+ let proxyAccountId;
664
789
  const authHeaders = {};
665
- await auth.applyHeaders(authHeaders, { upstreamUrl, model: resolvedModel });
790
+ await auth.applyHeaders(authHeaders, {
791
+ upstreamUrl,
792
+ model: resolvedModel,
793
+ sessionKey: plan.sessionKey,
794
+ preferredAccountId: plan.preferredAccountId,
795
+ reportSelection: (accountId, isActive) => {
796
+ proxyAccountId = accountId;
797
+ _optionalChain([reportSelection, 'optionalCall', _12 => _12(accountId, isActive)]);
798
+ }
799
+ });
666
800
  let rawStatus = null;
667
- const { response } = await _chunkKUU2RNG6cjs.executeProviderCall.call(void 0, {
801
+ const { response } = await _chunkHYN75H6Gcjs.executeProviderCall.call(void 0, {
668
802
  executor,
669
803
  request: anthropicBody,
670
804
  provider: transformerProvider,
@@ -682,7 +816,11 @@ async function runPipeline(anthropicBody, plan) {
682
816
  },
683
817
  fetchFn: (url, headers, body) => {
684
818
  console.info(`[ProviderProxy:anthropic] -> ${url} model=${resolvedModel} stream=${isStream}`);
685
- return fetch(url, { method: "POST", headers, body: JSON.stringify(body) }).then((r) => {
819
+ return _chunkOCEUVQHWcjs.fetchUpstream.call(void 0,
820
+ url,
821
+ { method: "POST", headers, body: JSON.stringify(body) },
822
+ { providerId: proxyProviderId(plan), accountId: proxyAccountId }
823
+ ).then((r) => {
686
824
  rawStatus = r.status;
687
825
  return r;
688
826
  });
@@ -691,29 +829,96 @@ async function runPipeline(anthropicBody, plan) {
691
829
  });
692
830
  return { response, rawStatus };
693
831
  }
694
- async function runSubscriptionSameFormatFetch(rawBody, plan) {
832
+ async function runSubscriptionSameFormatFetch(rawBody, plan, reportSelection, options = {}) {
833
+ let proxyAccountId;
834
+ let remappedModel;
695
835
  const headers = { "content-type": "application/json" };
696
836
  await plan.auth.applyHeaders(headers, {
697
837
  upstreamUrl: plan.upstreamUrl,
698
- model: plan.resolvedModel
838
+ model: plan.resolvedModel,
839
+ sessionKey: plan.sessionKey,
840
+ preferredAccountId: plan.preferredAccountId,
841
+ reportSelection: (accountId, isActive, remapped) => {
842
+ proxyAccountId = accountId;
843
+ remappedModel = remapped;
844
+ _optionalChain([reportSelection, 'optionalCall', _13 => _13(accountId, isActive, remapped)]);
845
+ }
699
846
  });
847
+ if (plan.isSubscription && plan.transformerProvider.name === "claude") {
848
+ _chunk6RPZADX3cjs.applyFingerprint.call(void 0,
849
+ _chunkRPII3E6Zcjs.getSharedIdentityStore.call(void 0, ),
850
+ headers,
851
+ plan.transformerProvider.name,
852
+ proxyAccountId,
853
+ options.callerIdentity
854
+ );
855
+ }
856
+ const applyRemap = remappedModel !== void 0 && outboundRemapApplies(plan);
857
+ const outboundBody = applyRemap ? rewriteBodyModel(rawBody, remappedModel) : rawBody;
858
+ const outboundModel = applyRemap ? remappedModel : plan.resolvedModel;
700
859
  console.info(
701
- `[ProviderProxy:anthropic] (subscription same-format) -> ${plan.upstreamUrl} model=${plan.resolvedModel} stream=${plan.isStream}`
860
+ `[ProviderProxy:anthropic] (subscription same-format) -> ${plan.upstreamUrl} model=${outboundModel} stream=${plan.isStream}`
861
+ );
862
+ const response = await _chunkOCEUVQHWcjs.fetchUpstream.call(void 0,
863
+ plan.upstreamUrl,
864
+ { method: "POST", headers, body: outboundBody },
865
+ { providerId: proxyProviderId(plan), accountId: proxyAccountId }
702
866
  );
703
- const response = await fetch(plan.upstreamUrl, { method: "POST", headers, body: rawBody });
704
867
  return { response, rawStatus: response.status };
705
868
  }
706
- async function runSubscriptionAttemptWith401Retry(anthropicBody, relayBody, plan) {
707
- const runOnce = () => plan.sameFormat ? runSubscriptionSameFormatFetch(relayBody, plan) : runPipeline(anthropicBody, plan);
869
+ function outboundRemapApplies(plan) {
870
+ return plan.isSubscription && plan.transformerProvider.name === "claude";
871
+ }
872
+ function rewriteBodyModel(rawBody, model) {
873
+ try {
874
+ const parsed = JSON.parse(rawBody);
875
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return rawBody;
876
+ parsed.model = model;
877
+ return JSON.stringify(parsed);
878
+ } catch (e7) {
879
+ return rawBody;
880
+ }
881
+ }
882
+ async function runSubscriptionAttemptWith401Retry(anthropicBody, relayBody, plan, options = {}) {
883
+ let selectedAccountId;
884
+ const reportSelection = (accountId) => {
885
+ selectedAccountId = accountId;
886
+ };
887
+ const runOnce = () => plan.sameFormat ? runSubscriptionSameFormatFetch(relayBody, plan, reportSelection, options) : runPipeline(anthropicBody, plan, reportSelection);
708
888
  const first = await runOnce();
709
- if (first.rawStatus !== 401) return first;
710
- const refreshed = await _optionalChain([plan, 'access', _12 => _12.auth, 'access', _13 => _13.onUnauthorized, 'optionalCall', _14 => _14()]);
711
- if (!refreshed) {
712
- console.warn("[ProviderProxy:anthropic] 401 not recoverable (onUnauthorized returned false)");
713
- return first;
889
+ let result = first;
890
+ if (first.rawStatus === 401) {
891
+ const refreshed = await _optionalChain([plan, 'access', _14 => _14.auth, 'access', _15 => _15.onUnauthorized, 'optionalCall', _16 => _16(plan.sessionKey)]);
892
+ if (refreshed) {
893
+ console.info("[ProviderProxy:anthropic] 401 \u2192 token refreshed; retrying once");
894
+ result = await runOnce();
895
+ } else {
896
+ console.warn("[ProviderProxy:anthropic] 401 not recoverable (onUnauthorized returned false)");
897
+ }
714
898
  }
715
- console.info("[ProviderProxy:anthropic] 401 \u2192 token refreshed; retrying once");
716
- return runOnce();
899
+ await markSubscriptionHealth(plan, selectedAccountId, result);
900
+ return result;
901
+ }
902
+ async function readBoundedBody(response, max = 2048) {
903
+ try {
904
+ const text = await response.clone().text();
905
+ return text.slice(0, max);
906
+ } catch (e8) {
907
+ return void 0;
908
+ }
909
+ }
910
+ async function markSubscriptionHealth(plan, selectedAccountId, result) {
911
+ if (!plan.isSubscription || selectedAccountId === void 0) return;
912
+ const providerId = plan.transformerProvider.name;
913
+ const status = result.rawStatus;
914
+ const { resetHeaderSeconds, retryAfterSeconds } = _chunkVQY5W4YWcjs.resolveResetSeconds.call(void 0, providerId, result.response.headers);
915
+ const bodyText = status === 403 ? await readBoundedBody(result.response) : void 0;
916
+ _chunkVQY5W4YWcjs.getSharedAccountHealth.call(void 0, ).recordUpstreamOutcome(providerId, selectedAccountId, {
917
+ status,
918
+ resetHeaderSeconds,
919
+ retryAfterSeconds,
920
+ bodyText
921
+ });
717
922
  }
718
923
  function isFallbackEligibleStatus(rawStatus) {
719
924
  return rawStatus === null || rawStatus >= 500 || rawStatus === 429;
@@ -726,11 +931,11 @@ function breakerOutcome(rawStatus) {
726
931
  function recordBreakerOutcome(profile, modelId, rawStatus) {
727
932
  const outcome = breakerOutcome(rawStatus);
728
933
  if (outcome === "neutral") return;
729
- _optionalChain([profile, 'optionalAccess', _15 => _15.recordModelOutcome, 'optionalCall', _16 => _16(modelId, outcome === "success")]);
934
+ _optionalChain([profile, 'optionalAccess', _17 => _17.recordModelOutcome, 'optionalCall', _18 => _18(modelId, outcome === "success")]);
730
935
  }
731
- async function runSubscriptionAttemptOutcome(anthropicBody, relayBody, plan) {
936
+ async function runSubscriptionAttemptOutcome(anthropicBody, relayBody, plan, options = {}) {
732
937
  try {
733
- return { kind: "result", result: await runSubscriptionAttemptWith401Retry(anthropicBody, relayBody, plan) };
938
+ return { kind: "result", result: await runSubscriptionAttemptWith401Retry(anthropicBody, relayBody, plan, options) };
734
939
  } catch (error) {
735
940
  return { kind: "thrown", error };
736
941
  }
@@ -742,11 +947,11 @@ function settleOutcome(outcome) {
742
947
  if (outcome.kind === "thrown") throw outcome.error;
743
948
  return outcome.result;
744
949
  }
745
- async function runPipelineWithSubscriptionRetry(anthropicBody, rawBody, initialPlan, route, deps) {
950
+ async function runPipelineWithSubscriptionRetry(anthropicBody, rawBody, initialPlan, route, deps, options = {}) {
746
951
  const profile = route.subscriptionProfile;
747
952
  const scenario = initialPlan.scenario;
748
- if (!_optionalChain([profile, 'optionalAccess', _17 => _17.nextFallback]) || scenario === void 0) {
749
- const loneOutcome = await runSubscriptionAttemptOutcome(anthropicBody, rawBody, initialPlan);
953
+ if (!_optionalChain([profile, 'optionalAccess', _19 => _19.nextFallback]) || scenario === void 0) {
954
+ const loneOutcome = await runSubscriptionAttemptOutcome(anthropicBody, rawBody, initialPlan, options);
750
955
  recordBreakerOutcome(profile, initialPlan.resolvedModel, outcomeStatus(loneOutcome));
751
956
  return settleOutcome(loneOutcome);
752
957
  }
@@ -757,7 +962,7 @@ async function runPipelineWithSubscriptionRetry(anthropicBody, rawBody, initialP
757
962
  if (profile.allowModel && !profile.allowModel(initialPlan.resolvedModel)) {
758
963
  attempted.push(initialPlan.resolvedModel);
759
964
  const firstAdmitting = profile.nextFallback(scenario, attempted, route.subscriptionConfig);
760
- const gatedPlan = firstAdmitting ? buildSubscriptionIterationPlan(profile, route, deps, firstAdmitting.modelId, initialPlan.isStream, scenario) : null;
965
+ const gatedPlan = firstAdmitting ? buildSubscriptionIterationPlan(profile, route, deps, firstAdmitting.modelId, initialPlan.isStream, scenario, initialPlan.sessionKey) : null;
761
966
  if (firstAdmitting && gatedPlan) {
762
967
  console.warn(
763
968
  `[ProviderProxy:anthropic] subscription primary ${initialPlan.resolvedModel} circuit open -> first admitting fallback ${firstAdmitting.modelId}`
@@ -772,7 +977,7 @@ async function runPipelineWithSubscriptionRetry(anthropicBody, rawBody, initialP
772
977
  );
773
978
  }
774
979
  }
775
- let outcome = await runSubscriptionAttemptOutcome(firstBodyObj, firstRelayBody, plan);
980
+ let outcome = await runSubscriptionAttemptOutcome(firstBodyObj, firstRelayBody, plan, options);
776
981
  recordBreakerOutcome(profile, plan.resolvedModel, outcomeStatus(outcome));
777
982
  if (!attempted.includes(plan.resolvedModel)) attempted.push(plan.resolvedModel);
778
983
  while (attempted.length < MAX_FALLBACK_ATTEMPTS) {
@@ -785,7 +990,8 @@ async function runPipelineWithSubscriptionRetry(anthropicBody, rawBody, initialP
785
990
  deps,
786
991
  next.modelId,
787
992
  plan.isStream,
788
- scenario
993
+ scenario,
994
+ initialPlan.sessionKey
789
995
  );
790
996
  if (!nextPlan) return settleOutcome(outcome);
791
997
  const sinceLabel = outcome.kind === "thrown" ? "thrown error" : `status ${String(outcome.result.rawStatus)}`;
@@ -796,7 +1002,7 @@ async function runPipelineWithSubscriptionRetry(anthropicBody, rawBody, initialP
796
1002
  const fallbackRelayBody = nextPlan.sameFormat ? JSON.stringify(fallbackBodyObj) : rawBody;
797
1003
  plan = nextPlan;
798
1004
  attempted.push(next.modelId);
799
- outcome = await runSubscriptionAttemptOutcome(fallbackBodyObj, fallbackRelayBody, plan);
1005
+ outcome = await runSubscriptionAttemptOutcome(fallbackBodyObj, fallbackRelayBody, plan, options);
800
1006
  recordBreakerOutcome(profile, plan.resolvedModel, outcomeStatus(outcome));
801
1007
  }
802
1008
  return settleOutcome(outcome);
@@ -808,7 +1014,7 @@ async function handleAnthropicMessagesByo(res, rawBody, route, deps, options = {
808
1014
  let anthropicBody;
809
1015
  try {
810
1016
  anthropicBody = JSON.parse(rawBody);
811
- } catch (e5) {
1017
+ } catch (e9) {
812
1018
  writeError(res, 400, "Invalid JSON in request body");
813
1019
  return;
814
1020
  }
@@ -819,13 +1025,16 @@ async function handleAnthropicMessagesByo(res, rawBody, route, deps, options = {
819
1025
  const plan = route.authMode === "subscription" ? await buildSubscriptionPlan(res, route, deps, anthropicBody, resolvedModel, isStream) : await buildByoPlan(res, route, deps, resolvedModel, isStream);
820
1026
  if (!plan) return;
821
1027
  anthropicBody.model = plan.resolvedModel;
822
- const providerResponse = route.authMode === "subscription" ? await runPipelineWithSubscriptionRetry(anthropicBody, rawBody, plan, route, deps) : await runPipelineWithPoolReporting(anthropicBody, rawBody, plan, options);
823
- const bodyText = await relayResponse(res, providerResponse.response, isStream);
1028
+ 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);
824
1030
  if (bodyText && deps.usageRecorder) {
825
1031
  recordAnthropicNonStreamUsage(deps.usageRecorder, bodyText, {
826
1032
  sessionId: route.sessionId,
827
1033
  providerId: _nullishCoalesce(route.providerId, () => ( "anthropic")),
828
- model: plan.resolvedModel
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
829
1038
  });
830
1039
  }
831
1040
  } catch (err) {
@@ -850,7 +1059,7 @@ async function buildByoPlan(res, route, deps, resolvedModel, isStream) {
850
1059
  writeError(res, 502, "API key not configured");
851
1060
  return null;
852
1061
  }
853
- const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkLKZJEL6Ecjs.LlmConfigProviderAuth)({
1062
+ const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkQ27JY5RGcjs.LlmConfigProviderAuth)({
854
1063
  provider,
855
1064
  apiKey,
856
1065
  apiKeyPool: _nullishCoalesce(deps.apiKeyPool, () => ( null)),
@@ -878,17 +1087,17 @@ async function buildByoPlan(res, route, deps, resolvedModel, isStream) {
878
1087
  isSubscription: false,
879
1088
  provider,
880
1089
  apiKey,
881
- extendedContextEnabled: _nullishCoalesce(_optionalChain([route, 'access', _18 => _18.anthropicSdkHints, 'optionalAccess', _19 => _19.extendedContext, 'optionalAccess', _20 => _20.enabled]), () => ( false))
1090
+ extendedContextEnabled: _nullishCoalesce(_optionalChain([route, 'access', _20 => _20.anthropicSdkHints, 'optionalAccess', _21 => _21.extendedContext, 'optionalAccess', _22 => _22.enabled]), () => ( false))
882
1091
  };
883
1092
  }
884
- async function runSameFormatFetch(rawBody, plan, options, keyOverride) {
1093
+ async function runSameFormatFetch(bodyToSend, plan, options, keyOverride) {
885
1094
  const { provider, apiKey, resolvedModel, isStream, extendedContextEnabled } = plan;
886
1095
  if (!provider) {
887
1096
  throw new Error("[ProviderProxy:anthropic] same-format BYO path requires a provider row");
888
1097
  }
889
1098
  const effectiveKey = _nullishCoalesce(_nullishCoalesce(keyOverride, () => ( apiKey)), () => ( ""));
890
- const headers = _chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, effectiveKey);
891
- const callerBeta = _optionalChain([options, 'access', _21 => _21.callerAnthropicBeta, 'optionalAccess', _22 => _22.trim, 'call', _23 => _23()]);
1099
+ 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()]);
892
1101
  if (callerBeta) {
893
1102
  const existing = _nullishCoalesce(headers["anthropic-beta"], () => ( headers["Anthropic-Beta"]));
894
1103
  const parts = new Set(
@@ -902,14 +1111,29 @@ async function runSameFormatFetch(rawBody, plan, options, keyOverride) {
902
1111
  _chunkGBHYAGX3cjs.injectExtendedContextBeta.call(void 0, headers, resolvedModel, _nullishCoalesce(extendedContextEnabled, () => ( false)));
903
1112
  const url = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: resolvedModel, stream: isStream });
904
1113
  console.info(`[ProviderProxy:anthropic] (same-format) -> ${url} model=${resolvedModel} stream=${isStream}`);
905
- const response = await fetch(url, { method: "POST", headers, body: rawBody });
1114
+ const response = await _chunkOCEUVQHWcjs.fetchUpstream.call(void 0,
1115
+ url,
1116
+ { method: "POST", headers, body: bodyToSend },
1117
+ { providerId: "byo" }
1118
+ );
906
1119
  return { response, rawStatus: response.status };
907
1120
  }
1121
+ function resolveSameFormatBody(anthropicBody, rawBody, plan) {
1122
+ let originalModel;
1123
+ try {
1124
+ const m = JSON.parse(rawBody).model;
1125
+ originalModel = typeof m === "string" ? m : void 0;
1126
+ } catch (e10) {
1127
+ originalModel = void 0;
1128
+ }
1129
+ return plan.resolvedModel !== originalModel ? JSON.stringify(anthropicBody) : rawBody;
1130
+ }
908
1131
  async function runPipelineWithPoolReporting(anthropicBody, rawBody, plan, options) {
909
- const runOnce = (keyOverride) => plan.sameFormat ? runSameFormatFetch(rawBody, plan, options, keyOverride) : runPipeline(anthropicBody, plan);
1132
+ const sameFormatBody = plan.sameFormat ? resolveSameFormatBody(anthropicBody, rawBody, plan) : rawBody;
1133
+ const runOnce = (keyOverride) => plan.sameFormat ? runSameFormatFetch(sameFormatBody, plan, options, keyOverride) : runPipeline(anthropicBody, plan);
910
1134
  const first = await runOnce();
911
- const outcome = await _optionalChain([plan, 'access', _24 => _24.auth, 'access', _25 => _25.onResult, 'optionalCall', _26 => _26(first.rawStatus)]);
912
- if (_optionalChain([outcome, 'optionalAccess', _27 => _27.rebound])) {
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])) {
913
1137
  console.info(
914
1138
  "[ProviderProxy:anthropic] pool re-bound key after status",
915
1139
  first.rawStatus,
@@ -930,7 +1154,8 @@ async function handleAnthropicMessagesRequest(req, res, route, deps) {
930
1154
  const rawBody = await readBody(req);
931
1155
  const callerBetaRaw = req.headers["anthropic-beta"];
932
1156
  const callerAnthropicBeta = Array.isArray(callerBetaRaw) ? callerBetaRaw.join(",") : callerBetaRaw;
933
- await handleAnthropicMessagesByo(res, rawBody, route, deps, { callerAnthropicBeta });
1157
+ const callerIdentity = _chunk6RPZADX3cjs.captureCallerIdentity.call(void 0, _chunkRPII3E6Zcjs.getSharedIdentityStore.call(void 0, ), req.headers);
1158
+ await handleAnthropicMessagesByo(res, rawBody, route, deps, { callerAnthropicBeta, callerIdentity });
934
1159
  return;
935
1160
  }
936
1161
  const hints = route.anthropicSdkHints;
@@ -992,12 +1217,13 @@ function recordGeminiNonStreamUsage(recorder, bodyText, attribution) {
992
1217
  sessionId: attribution.sessionId,
993
1218
  providerId: attribution.providerId,
994
1219
  model: attribution.model,
995
- apiKeyId: null,
1220
+ apiKeyId: attribution.apiKeyId,
1221
+ auditResponse: attribution.auditResponse,
996
1222
  engineOrigin: "codex-ingress",
997
1223
  usage: tapped,
998
1224
  rawUsage: parsed.usageMetadata
999
1225
  });
1000
- } catch (e6) {
1226
+ } catch (e11) {
1001
1227
  }
1002
1228
  }
1003
1229
 
@@ -1006,14 +1232,14 @@ var GENERATE_CONTENT_ACTION = ":generateContent";
1006
1232
  var STREAM_GENERATE_CONTENT_ACTION = ":streamGenerateContent";
1007
1233
  function isGeminiGenerateContentRequest(method, url) {
1008
1234
  if (method !== "POST" || !url) return false;
1009
- const path = _nullishCoalesce(_optionalChain([url, 'access', _28 => _28.split, 'call', _29 => _29("?"), 'access', _30 => _30[0], 'optionalAccess', _31 => _31.replace, 'call', _32 => _32(/\/+$/, "")]), () => ( ""));
1235
+ const path = _nullishCoalesce(_optionalChain([url, 'access', _30 => _30.split, 'call', _31 => _31("?"), 'access', _32 => _32[0], 'optionalAccess', _33 => _33.replace, 'call', _34 => _34(/\/+$/, "")]), () => ( ""));
1010
1236
  const lastSegment = _nullishCoalesce(path.split("/").pop(), () => ( ""));
1011
1237
  return lastSegment.includes(STREAM_GENERATE_CONTENT_ACTION) || lastSegment.includes(GENERATE_CONTENT_ACTION);
1012
1238
  }
1013
1239
  function isGeminiStreamRequest(url) {
1014
1240
  if (!url) return false;
1015
1241
  const [path, query = ""] = url.split("?");
1016
- const lastSegment = _nullishCoalesce((_nullishCoalesce(_optionalChain([path, 'optionalAccess', _33 => _33.replace, 'call', _34 => _34(/\/+$/, "")]), () => ( ""))).split("/").pop(), () => ( ""));
1242
+ const lastSegment = _nullishCoalesce((_nullishCoalesce(_optionalChain([path, 'optionalAccess', _35 => _35.replace, 'call', _36 => _36(/\/+$/, "")]), () => ( ""))).split("/").pop(), () => ( ""));
1017
1243
  if (lastSegment.includes(STREAM_GENERATE_CONTENT_ACTION)) return true;
1018
1244
  return /(^|&)alt=sse(&|$)/.test(query);
1019
1245
  }
@@ -1021,7 +1247,7 @@ async function handleGeminiGenerateContentRequest(res, rawBody, url, route, deps
1021
1247
  let geminiBody;
1022
1248
  try {
1023
1249
  geminiBody = JSON.parse(rawBody);
1024
- } catch (e7) {
1250
+ } catch (e12) {
1025
1251
  writeError(res, 400, "Invalid JSON in request body");
1026
1252
  return;
1027
1253
  }
@@ -1042,7 +1268,10 @@ async function handleGeminiGenerateContentRequest(res, rawBody, url, route, deps
1042
1268
  recordGeminiNonStreamUsage(deps.usageRecorder, bodyText, {
1043
1269
  sessionId: route.sessionId,
1044
1270
  providerId: _nullishCoalesce(route.providerId, () => ( "gemini")),
1045
- model: resolvedModel
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
1046
1275
  });
1047
1276
  }
1048
1277
  } catch (err) {
@@ -1067,7 +1296,7 @@ async function buildByoPlan2(res, route, deps, resolvedModel, isStream) {
1067
1296
  writeError(res, 502, "API key not configured");
1068
1297
  return null;
1069
1298
  }
1070
- const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkLKZJEL6Ecjs.LlmConfigProviderAuth)({
1299
+ const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkQ27JY5RGcjs.LlmConfigProviderAuth)({
1071
1300
  provider,
1072
1301
  apiKey,
1073
1302
  apiKeyPool: _nullishCoalesce(deps.apiKeyPool, () => ( null)),
@@ -1099,7 +1328,7 @@ async function runPipeline2(geminiBody, plan) {
1099
1328
  const authHeaders = {};
1100
1329
  await auth.applyHeaders(authHeaders, { upstreamUrl, model: resolvedModel });
1101
1330
  let rawStatus = null;
1102
- const { response } = await _chunkKUU2RNG6cjs.executeProviderCall.call(void 0, {
1331
+ const { response } = await _chunkHYN75H6Gcjs.executeProviderCall.call(void 0, {
1103
1332
  executor,
1104
1333
  request: geminiBody,
1105
1334
  provider: transformerProvider,
@@ -1117,7 +1346,11 @@ async function runPipeline2(geminiBody, plan) {
1117
1346
  },
1118
1347
  fetchFn: (url, headers, body) => {
1119
1348
  console.log(`[ProviderProxy:gemini] -> ${url} model=${resolvedModel} stream=${isStream}`);
1120
- return fetch(url, { method: "POST", headers, body: JSON.stringify(body) }).then((r) => {
1349
+ return _chunkOCEUVQHWcjs.fetchUpstream.call(void 0,
1350
+ url,
1351
+ { method: "POST", headers, body: JSON.stringify(body) },
1352
+ { providerId: "byo" }
1353
+ ).then((r) => {
1121
1354
  rawStatus = r.status;
1122
1355
  return r;
1123
1356
  });
@@ -1128,8 +1361,8 @@ async function runPipeline2(geminiBody, plan) {
1128
1361
  }
1129
1362
  async function runPipelineWithPoolReporting2(geminiBody, plan) {
1130
1363
  const first = await runPipeline2(geminiBody, plan);
1131
- const outcome = await _optionalChain([plan, 'access', _35 => _35.auth, 'access', _36 => _36.onResult, 'optionalCall', _37 => _37(first.rawStatus)]);
1132
- if (_optionalChain([outcome, 'optionalAccess', _38 => _38.rebound])) {
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])) {
1133
1366
  console.log(
1134
1367
  "[ProviderProxy:gemini] pool re-bound key after status",
1135
1368
  first.rawStatus,
@@ -1169,46 +1402,48 @@ function recordChatCompletionsNonStreamUsage(recorder, bodyText, attribution) {
1169
1402
  sessionId: attribution.sessionId,
1170
1403
  providerId: attribution.providerId,
1171
1404
  model: attribution.model,
1172
- apiKeyId: null,
1405
+ apiKeyId: attribution.apiKeyId,
1406
+ auditResponse: attribution.auditResponse,
1173
1407
  engineOrigin: "codex-ingress",
1174
1408
  usage: tapped,
1175
1409
  rawUsage: parsed.usage
1176
1410
  });
1177
- } catch (e8) {
1411
+ } catch (e13) {
1178
1412
  }
1179
1413
  }
1180
1414
 
1181
1415
  // src/provider-proxy/ingress/openaiChatIngress.ts
1182
1416
  function isOpenAIChatRequest(method, url) {
1183
1417
  if (method !== "POST" || !url) return false;
1184
- const path = _nullishCoalesce(_optionalChain([url, 'access', _39 => _39.split, 'call', _40 => _40("?"), 'access', _41 => _41[0], 'optionalAccess', _42 => _42.replace, 'call', _43 => _43(/\/+$/, "")]), () => ( ""));
1418
+ const path = _nullishCoalesce(_optionalChain([url, 'access', _41 => _41.split, 'call', _42 => _42("?"), 'access', _43 => _43[0], 'optionalAccess', _44 => _44.replace, 'call', _45 => _45(/\/+$/, "")]), () => ( ""));
1185
1419
  return path.endsWith("/chat/completions");
1186
1420
  }
1421
+ var CHAT_BRIDGE_SUBSCRIPTION_PROVIDERS = /* @__PURE__ */ new Set(["claude"]);
1422
+ var IDENTITY_ENDPOINT_TRANSFORMER = { name: "identity-openai-chat" };
1187
1423
  async function handleOpenAIChatRequest(res, rawBody, route, deps) {
1188
1424
  let chatBody;
1189
1425
  try {
1190
1426
  chatBody = JSON.parse(rawBody);
1191
- } catch (e9) {
1427
+ } catch (e14) {
1192
1428
  writeError(res, 400, "Invalid JSON in request body");
1193
1429
  return;
1194
1430
  }
1195
- if (route.authMode === "subscription") {
1196
- writeError(res, 502, "OpenAI Chat Completions ingress does not support subscription auth");
1197
- return;
1198
- }
1199
1431
  const isStream = chatBody.stream === true;
1200
1432
  const resolvedModel = route.model;
1201
1433
  chatBody.model = resolvedModel;
1202
1434
  try {
1203
- const plan = await buildByoPlan3(res, route, deps, resolvedModel, isStream);
1435
+ const plan = route.authMode === "subscription" ? await buildSubscriptionPlan2(res, route, deps, resolvedModel, isStream) : await buildByoPlan3(res, route, deps, resolvedModel, isStream);
1204
1436
  if (!plan) return;
1205
- const providerResponse = await runPipelineWithPoolReporting3(chatBody, plan);
1437
+ const providerResponse = plan.isSubscription ? await runPipelineWithSubscriptionRetry2(chatBody, plan) : await runPipelineWithPoolReporting3(chatBody, plan);
1206
1438
  const bodyText = await relayResponse(res, providerResponse.response, isStream);
1207
1439
  if (bodyText && deps.usageRecorder) {
1208
1440
  recordChatCompletionsNonStreamUsage(deps.usageRecorder, bodyText, {
1209
1441
  sessionId: route.sessionId,
1210
1442
  providerId: _nullishCoalesce(route.providerId, () => ( "openai")),
1211
- model: resolvedModel
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
1212
1447
  });
1213
1448
  }
1214
1449
  } catch (err) {
@@ -1233,7 +1468,7 @@ async function buildByoPlan3(res, route, deps, resolvedModel, isStream) {
1233
1468
  writeError(res, 502, "API key not configured");
1234
1469
  return null;
1235
1470
  }
1236
- const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkLKZJEL6Ecjs.LlmConfigProviderAuth)({
1471
+ const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkQ27JY5RGcjs.LlmConfigProviderAuth)({
1237
1472
  provider,
1238
1473
  apiKey,
1239
1474
  apiKeyPool: _nullishCoalesce(deps.apiKeyPool, () => ( null)),
@@ -1255,16 +1490,69 @@ async function buildByoPlan3(res, route, deps, resolvedModel, isStream) {
1255
1490
  resolvedModel,
1256
1491
  isStream,
1257
1492
  resolveUrl: (config) => config.url instanceof URL ? config.url.toString() : byoUrl,
1258
- upstreamUrl: byoUrl
1493
+ upstreamUrl: byoUrl,
1494
+ proxyProviderId: "byo",
1495
+ isSubscription: false
1496
+ };
1497
+ }
1498
+ async function buildSubscriptionPlan2(res, route, deps, resolvedModel, isStream) {
1499
+ const profile = route.subscriptionProfile;
1500
+ if (!profile) {
1501
+ writeError(res, 502, "Subscription mode requires a subscription profile");
1502
+ return null;
1503
+ }
1504
+ const providerId = profile.authStrategy.providerId;
1505
+ if (!CHAT_BRIDGE_SUBSCRIPTION_PROVIDERS.has(providerId)) {
1506
+ writeError(
1507
+ res,
1508
+ 501,
1509
+ `the OpenAI-chat\u2192subscription bridge currently supports claude only; subscription provider '${providerId}' is not implemented on this endpoint yet (use the /v1/responses endpoint, a Claude subscription, or a BYO provider)`
1510
+ );
1511
+ return null;
1512
+ }
1513
+ const upstreamUrl = _optionalChain([profile, 'access', _46 => _46.resolveUpstreamUrl, 'optionalCall', _47 => _47(resolvedModel)]);
1514
+ if (!upstreamUrl) {
1515
+ writeError(res, 502, "Subscription profile is missing resolveUpstreamUrl");
1516
+ return null;
1517
+ }
1518
+ const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkKFI44N2Rcjs.SubscriptionAuthSource)(profile)));
1519
+ const chain = _chunkNYUNU75Acjs.resolveSubscriptionChain.call(void 0,
1520
+ profile,
1521
+ deps.llmConfig.getTransformerService(),
1522
+ IDENTITY_ENDPOINT_TRANSFORMER
1523
+ );
1524
+ const transformerProvider = {
1525
+ name: providerId,
1526
+ baseUrl: upstreamUrl,
1527
+ apiKey: "",
1528
+ models: [resolvedModel]
1529
+ };
1530
+ return {
1531
+ auth,
1532
+ chain,
1533
+ transformerProvider,
1534
+ resolvedModel,
1535
+ isStream,
1536
+ resolveUrl: (config) => config.url instanceof URL ? config.url.toString() : typeof config.url === "string" ? config.url : upstreamUrl,
1537
+ upstreamUrl,
1538
+ proxyProviderId: providerId,
1539
+ isSubscription: true
1259
1540
  };
1260
1541
  }
1261
1542
  async function runPipeline3(chatBody, plan) {
1262
1543
  const executor = getSharedExecutor();
1263
1544
  const { auth, chain, transformerProvider, resolvedModel, isStream, resolveUrl, upstreamUrl } = plan;
1545
+ let proxyAccountId;
1264
1546
  const authHeaders = {};
1265
- await auth.applyHeaders(authHeaders, { upstreamUrl, model: resolvedModel });
1547
+ await auth.applyHeaders(authHeaders, {
1548
+ upstreamUrl,
1549
+ model: resolvedModel,
1550
+ reportSelection: (accountId) => {
1551
+ proxyAccountId = accountId;
1552
+ }
1553
+ });
1266
1554
  let rawStatus = null;
1267
- const { response } = await _chunkKUU2RNG6cjs.executeProviderCall.call(void 0, {
1555
+ const { response } = await _chunkHYN75H6Gcjs.executeProviderCall.call(void 0, {
1268
1556
  executor,
1269
1557
  request: chatBody,
1270
1558
  provider: transformerProvider,
@@ -1281,7 +1569,11 @@ async function runPipeline3(chatBody, plan) {
1281
1569
  },
1282
1570
  fetchFn: (url, headers, body) => {
1283
1571
  console.log(`[ProviderProxy:chat] -> ${url} model=${resolvedModel} stream=${isStream}`);
1284
- return fetch(url, { method: "POST", headers, body: JSON.stringify(body) }).then((r) => {
1572
+ return _chunkOCEUVQHWcjs.fetchUpstream.call(void 0,
1573
+ url,
1574
+ { method: "POST", headers, body: JSON.stringify(body) },
1575
+ { providerId: plan.proxyProviderId, accountId: proxyAccountId }
1576
+ ).then((r) => {
1285
1577
  rawStatus = r.status;
1286
1578
  return r;
1287
1579
  });
@@ -1292,8 +1584,8 @@ async function runPipeline3(chatBody, plan) {
1292
1584
  }
1293
1585
  async function runPipelineWithPoolReporting3(chatBody, plan) {
1294
1586
  const first = await runPipeline3(chatBody, plan);
1295
- const outcome = await _optionalChain([plan, 'access', _44 => _44.auth, 'access', _45 => _45.onResult, 'optionalCall', _46 => _46(first.rawStatus)]);
1296
- if (_optionalChain([outcome, 'optionalAccess', _47 => _47.rebound])) {
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])) {
1297
1589
  console.log(
1298
1590
  "[ProviderProxy:chat] pool re-bound key after status",
1299
1591
  first.rawStatus,
@@ -1303,6 +1595,17 @@ async function runPipelineWithPoolReporting3(chatBody, plan) {
1303
1595
  }
1304
1596
  return first;
1305
1597
  }
1598
+ async function runPipelineWithSubscriptionRetry2(chatBody, plan) {
1599
+ const first = await runPipeline3(chatBody, plan);
1600
+ if (first.rawStatus !== 401) return first;
1601
+ const refreshed = await _optionalChain([plan, 'access', _52 => _52.auth, 'access', _53 => _53.onUnauthorized, 'optionalCall', _54 => _54()]);
1602
+ if (!refreshed) {
1603
+ console.warn("[ProviderProxy:chat] 401 not recoverable (onUnauthorized returned false)");
1604
+ return first;
1605
+ }
1606
+ console.log("[ProviderProxy:chat] 401 \u2192 token refreshed; retrying once");
1607
+ return runPipeline3(chatBody, plan);
1608
+ }
1306
1609
 
1307
1610
  // src/provider-proxy/usage/recordResponsesUsage.ts
1308
1611
  function readResponsesUsage(usage) {
@@ -1333,26 +1636,27 @@ function recordResponsesNonStreamUsage(recorder, bodyText, attribution) {
1333
1636
  sessionId: attribution.sessionId,
1334
1637
  providerId: attribution.providerId,
1335
1638
  model: attribution.model,
1336
- apiKeyId: null,
1639
+ apiKeyId: attribution.apiKeyId,
1640
+ auditResponse: attribution.auditResponse,
1337
1641
  engineOrigin: "codex-ingress",
1338
1642
  usage: tapped,
1339
1643
  rawUsage: parsed.usage
1340
1644
  });
1341
- } catch (e10) {
1645
+ } catch (e15) {
1342
1646
  }
1343
1647
  }
1344
1648
 
1345
1649
  // src/provider-proxy/ingress/openaiResponsesIngress.ts
1346
1650
  function isOpenAIResponsesRequest(method, url) {
1347
1651
  if (method !== "POST" || !url) return false;
1348
- const path = _nullishCoalesce(_optionalChain([url, 'access', _48 => _48.split, 'call', _49 => _49("?"), 'access', _50 => _50[0], 'optionalAccess', _51 => _51.replace, 'call', _52 => _52(/\/+$/, "")]), () => ( ""));
1652
+ const path = _nullishCoalesce(_optionalChain([url, 'access', _55 => _55.split, 'call', _56 => _56("?"), 'access', _57 => _57[0], 'optionalAccess', _58 => _58.replace, 'call', _59 => _59(/\/+$/, "")]), () => ( ""));
1349
1653
  return path.endsWith("/responses");
1350
1654
  }
1351
1655
  async function handleOpenAIResponsesRequest(res, rawBody, route, deps) {
1352
1656
  let responsesBody;
1353
1657
  try {
1354
1658
  responsesBody = JSON.parse(rawBody);
1355
- } catch (e11) {
1659
+ } catch (e16) {
1356
1660
  writeError(res, 400, "Invalid JSON in request body");
1357
1661
  return;
1358
1662
  }
@@ -1360,15 +1664,18 @@ async function handleOpenAIResponsesRequest(res, rawBody, route, deps) {
1360
1664
  const resolvedModel = route.model;
1361
1665
  responsesBody.model = resolvedModel;
1362
1666
  try {
1363
- const plan = route.authMode === "subscription" ? await buildSubscriptionPlan2(res, route, deps, resolvedModel, isStream) : await buildByoPlan4(res, route, deps, resolvedModel, isStream);
1667
+ const plan = route.authMode === "subscription" ? await buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream) : await buildByoPlan4(res, route, deps, resolvedModel, isStream);
1364
1668
  if (!plan) return;
1365
- const providerResponse = route.authMode === "subscription" ? await runPipelineWithSubscriptionRetry2(responsesBody, plan) : await runPipelineWithPoolReporting4(responsesBody, plan);
1366
- const bodyText = await relayResponse(res, providerResponse.response, isStream);
1669
+ const providerResponse = route.authMode === "subscription" ? await runPipelineWithSubscriptionRetry3(responsesBody, plan) : await runPipelineWithPoolReporting4(responsesBody, plan);
1670
+ const bodyText = await relayResponse(res, providerResponse.response, isStream, route.requestedModel);
1367
1671
  if (bodyText && deps.usageRecorder) {
1368
1672
  recordResponsesNonStreamUsage(deps.usageRecorder, bodyText, {
1369
1673
  sessionId: route.sessionId,
1370
1674
  providerId: _nullishCoalesce(route.providerId, () => ( "codex")),
1371
- model: resolvedModel
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
1372
1679
  });
1373
1680
  }
1374
1681
  } catch (err) {
@@ -1393,7 +1700,7 @@ async function buildByoPlan4(res, route, deps, resolvedModel, isStream) {
1393
1700
  writeError(res, 502, "API key not configured");
1394
1701
  return null;
1395
1702
  }
1396
- const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkLKZJEL6Ecjs.LlmConfigProviderAuth)({
1703
+ const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkQ27JY5RGcjs.LlmConfigProviderAuth)({
1397
1704
  provider,
1398
1705
  apiKey,
1399
1706
  apiKeyPool: _nullishCoalesce(deps.apiKeyPool, () => ( null)),
@@ -1415,21 +1722,22 @@ async function buildByoPlan4(res, route, deps, resolvedModel, isStream) {
1415
1722
  resolvedModel,
1416
1723
  isStream,
1417
1724
  resolveUrl: (config) => config.url instanceof URL ? config.url.toString() : byoUrl,
1418
- upstreamUrl: byoUrl
1725
+ upstreamUrl: byoUrl,
1726
+ proxyProviderId: "byo"
1419
1727
  };
1420
1728
  }
1421
- async function buildSubscriptionPlan2(res, route, deps, resolvedModel, isStream) {
1729
+ async function buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream) {
1422
1730
  const profile = route.subscriptionProfile;
1423
1731
  if (!profile) {
1424
1732
  writeError(res, 502, "Subscription mode requires a codex subscription profile");
1425
1733
  return null;
1426
1734
  }
1427
- const upstreamUrl = _optionalChain([profile, 'access', _53 => _53.resolveUpstreamUrl, 'optionalCall', _54 => _54(resolvedModel)]);
1735
+ const upstreamUrl = _optionalChain([profile, 'access', _60 => _60.resolveUpstreamUrl, 'optionalCall', _61 => _61(resolvedModel)]);
1428
1736
  if (!upstreamUrl) {
1429
1737
  writeError(res, 502, "Subscription profile is missing resolveUpstreamUrl");
1430
1738
  return null;
1431
1739
  }
1432
- const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkN3V2J5ZOcjs.SubscriptionAuthSource)(profile)));
1740
+ const auth = _nullishCoalesce(route.auth, () => ( new (0, _chunkKFI44N2Rcjs.SubscriptionAuthSource)(profile)));
1433
1741
  const chain = _chunkNYUNU75Acjs.resolveSubscriptionChain.call(void 0,
1434
1742
  profile,
1435
1743
  deps.llmConfig.getTransformerService(),
@@ -1451,6 +1759,7 @@ async function buildSubscriptionPlan2(res, route, deps, resolvedModel, isStream)
1451
1759
  }
1452
1760
  return {
1453
1761
  auth,
1762
+ preferredAccountId: route.preferredAccountId,
1454
1763
  chain,
1455
1764
  transformerProvider,
1456
1765
  resolvedModel,
@@ -1459,7 +1768,8 @@ async function buildSubscriptionPlan2(res, route, deps, resolvedModel, isStream)
1459
1768
  // stream vs non-stream colon-method URL in `config.url`); fall back to the
1460
1769
  // profile's `resolveUpstreamUrl` for non-Code-Assist subscriptions.
1461
1770
  resolveUrl: (config) => config.url instanceof URL ? config.url.toString() : typeof config.url === "string" ? config.url : upstreamUrl,
1462
- upstreamUrl
1771
+ upstreamUrl,
1772
+ proxyProviderId: profile.authStrategy.providerId
1463
1773
  };
1464
1774
  }
1465
1775
  async function resolveGeminiCodeAssistProject(profile) {
@@ -1476,10 +1786,18 @@ async function runPipeline4(responsesBody, plan) {
1476
1786
  const executor = getSharedExecutor();
1477
1787
  const endpointTransformer = getResponsesEndpointTransformer();
1478
1788
  const { auth, chain, transformerProvider, resolvedModel, isStream, resolveUrl, upstreamUrl } = plan;
1789
+ let proxyAccountId;
1479
1790
  const authHeaders = {};
1480
- await auth.applyHeaders(authHeaders, { upstreamUrl, model: resolvedModel });
1791
+ await auth.applyHeaders(authHeaders, {
1792
+ upstreamUrl,
1793
+ model: resolvedModel,
1794
+ preferredAccountId: plan.preferredAccountId,
1795
+ reportSelection: (accountId) => {
1796
+ proxyAccountId = accountId;
1797
+ }
1798
+ });
1481
1799
  let rawStatus = null;
1482
- const { response } = await _chunkKUU2RNG6cjs.executeProviderCall.call(void 0, {
1800
+ const { response } = await _chunkHYN75H6Gcjs.executeProviderCall.call(void 0, {
1483
1801
  executor,
1484
1802
  request: responsesBody,
1485
1803
  provider: transformerProvider,
@@ -1497,7 +1815,11 @@ async function runPipeline4(responsesBody, plan) {
1497
1815
  },
1498
1816
  fetchFn: (url, headers, body) => {
1499
1817
  console.log(`[ProviderProxy:responses] -> ${url} model=${resolvedModel} stream=${isStream}`);
1500
- return fetch(url, { method: "POST", headers, body: JSON.stringify(body) }).then((r) => {
1818
+ return _chunkOCEUVQHWcjs.fetchUpstream.call(void 0,
1819
+ url,
1820
+ { method: "POST", headers, body: JSON.stringify(body) },
1821
+ { providerId: plan.proxyProviderId, accountId: proxyAccountId }
1822
+ ).then((r) => {
1501
1823
  rawStatus = r.status;
1502
1824
  return r;
1503
1825
  });
@@ -1508,8 +1830,8 @@ async function runPipeline4(responsesBody, plan) {
1508
1830
  }
1509
1831
  async function runPipelineWithPoolReporting4(responsesBody, plan) {
1510
1832
  const first = await runPipeline4(responsesBody, plan);
1511
- const outcome = await _optionalChain([plan, 'access', _55 => _55.auth, 'access', _56 => _56.onResult, 'optionalCall', _57 => _57(first.rawStatus)]);
1512
- if (_optionalChain([outcome, 'optionalAccess', _58 => _58.rebound])) {
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])) {
1513
1835
  console.log(
1514
1836
  "[ProviderProxy:responses] pool re-bound key after status",
1515
1837
  first.rawStatus,
@@ -1519,10 +1841,10 @@ async function runPipelineWithPoolReporting4(responsesBody, plan) {
1519
1841
  }
1520
1842
  return first;
1521
1843
  }
1522
- async function runPipelineWithSubscriptionRetry2(responsesBody, plan) {
1844
+ async function runPipelineWithSubscriptionRetry3(responsesBody, plan) {
1523
1845
  const first = await runPipeline4(responsesBody, plan);
1524
1846
  if (first.rawStatus !== 401) return first;
1525
- const refreshed = await _optionalChain([plan, 'access', _59 => _59.auth, 'access', _60 => _60.onUnauthorized, 'optionalCall', _61 => _61()]);
1847
+ const refreshed = await _optionalChain([plan, 'access', _66 => _66.auth, 'access', _67 => _67.onUnauthorized, 'optionalCall', _68 => _68()]);
1526
1848
  if (!refreshed) {
1527
1849
  console.warn("[ProviderProxy:responses] 401 not recoverable (onUnauthorized returned false)");
1528
1850
  return first;
@@ -1544,7 +1866,7 @@ function resolveRouteToken(req) {
1544
1866
  if (fromAuth) return fromAuth;
1545
1867
  const googKey = req.headers["x-goog-api-key"];
1546
1868
  const value = Array.isArray(googKey) ? googKey[0] : googKey;
1547
- return _optionalChain([value, 'optionalAccess', _62 => _62.trim, 'call', _63 => _63()]) || void 0;
1869
+ return _optionalChain([value, 'optionalAccess', _69 => _69.trim, 'call', _70 => _70()]) || void 0;
1548
1870
  }
1549
1871
  async function routeRequest(req, res, routes, deps) {
1550
1872
  const token = resolveRouteToken(req);
@@ -1696,12 +2018,439 @@ function __resetProviderProxyForTests() {
1696
2018
  // src/outbound-api/OutboundApiServer.ts
1697
2019
 
1698
2020
  var _os = require('os');
2021
+ var _healthloggingtypes = require('@omnicross/contracts/health-logging-types');
2022
+
2023
+ // src/outbound-api/keyedMutex.ts
2024
+ var KeyedMutex = (_class3 = class {constructor() { _class3.prototype.__init4.call(this); }
2025
+ /** key → the tail of the pending-op chain (resolves when the last op frees). */
2026
+ __init4() {this.tails = /* @__PURE__ */ new Map()}
2027
+ /**
2028
+ * Run `fn` exclusively for `key`: it starts only after every previously
2029
+ * enqueued op for the SAME key has settled, and the next waiter starts only
2030
+ * after `fn` settles. Returns `fn`'s result (or rejection). Never lets one op's
2031
+ * failure wedge the queue (waiters proceed regardless).
2032
+ */
2033
+ async runExclusive(key, fn) {
2034
+ const prev = _nullishCoalesce(this.tails.get(key), () => ( Promise.resolve()));
2035
+ let release2;
2036
+ const gate = new Promise((resolve) => {
2037
+ release2 = resolve;
2038
+ });
2039
+ const chain = prev.then(() => gate);
2040
+ this.tails.set(key, chain);
2041
+ await prev.catch(() => void 0);
2042
+ try {
2043
+ return await fn();
2044
+ } finally {
2045
+ release2();
2046
+ if (this.tails.get(key) === chain) this.tails.delete(key);
2047
+ }
2048
+ }
2049
+ }, _class3);
1699
2050
 
1700
2051
  // src/outbound-api/outboundApiRouter.ts
1701
2052
  var _stream = require('stream');
1702
2053
 
2054
+ // src/outbound-api/apiServerConfig.ts
2055
+ var _audittypes = require('@omnicross/contracts/audit-types');
2056
+ var _billingtypes = require('@omnicross/contracts/billing-types');
2057
+
2058
+
2059
+
2060
+ var _webhooktypes = require('@omnicross/contracts/webhook-types');
2061
+ var OUTBOUND_API_SERVER_CONFIG_KEY = "outboundApiServer.config";
2062
+ var DEFAULT_USER_MESSAGE_QUEUE = {
2063
+ enabled: false,
2064
+ delayMs: 200,
2065
+ waitTimeoutMs: 6e4
2066
+ };
2067
+ var DEFAULT_CONCURRENCY_QUEUE = {
2068
+ maxQueueSizeFactor: 2,
2069
+ minQueueSize: 4,
2070
+ waitTimeoutMs: 6e4
2071
+ };
2072
+ var DEFAULT_ACCOUNT_HEALTH = {
2073
+ overloadCooldownEnabled: true,
2074
+ overloadCooldownMs: 10 * 6e4
2075
+ };
2076
+ function normalizeAccountHealth(raw) {
2077
+ const ah = _optionalChain([raw, 'optionalAccess', _71 => _71.accountHealth]);
2078
+ return {
2079
+ overloadCooldownEnabled: _optionalChain([ah, 'optionalAccess', _72 => _72.overloadCooldownEnabled]) !== false,
2080
+ overloadCooldownMs: clampNumber(
2081
+ _optionalChain([ah, 'optionalAccess', _73 => _73.overloadCooldownMs]),
2082
+ 6e4,
2083
+ 36e5,
2084
+ DEFAULT_ACCOUNT_HEALTH.overloadCooldownMs
2085
+ )
2086
+ };
2087
+ }
2088
+ var DEFAULT_ACCOUNT_PROBE = {
2089
+ enabled: false,
2090
+ intervalMs: 15 * 6e4,
2091
+ onlyMultiAccount: true,
2092
+ timeoutMs: 5e3,
2093
+ historySize: 10,
2094
+ staggerMs: 500
2095
+ };
2096
+ function normalizeAccountProbe(raw) {
2097
+ const ap = _optionalChain([raw, 'optionalAccess', _74 => _74.accountProbe]);
2098
+ 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),
2103
+ historySize: Math.trunc(
2104
+ clampNumber(_optionalChain([ap, 'optionalAccess', _79 => _79.historySize]), 1, 200, DEFAULT_ACCOUNT_PROBE.historySize)
2105
+ ),
2106
+ staggerMs: clampNumber(_optionalChain([ap, 'optionalAccess', _80 => _80.staggerMs]), 0, 6e4, DEFAULT_ACCOUNT_PROBE.staggerMs)
2107
+ };
2108
+ }
2109
+ function normalizeAudit(raw) {
2110
+ const a = _optionalChain([raw, 'optionalAccess', _81 => _81.audit]);
2111
+ return {
2112
+ enabled: _optionalChain([a, 'optionalAccess', _82 => _82.enabled]) === true,
2113
+ captureBodies: _optionalChain([a, 'optionalAccess', _83 => _83.captureBodies]) === true,
2114
+ maxBodyBytes: Math.trunc(
2115
+ clampNumber(_optionalChain([a, 'optionalAccess', _84 => _84.maxBodyBytes]), 256, 1048576, _audittypes.DEFAULT_AUDIT_CONFIG.maxBodyBytes)
2116
+ ),
2117
+ retentionDays: Math.trunc(
2118
+ clampNumber(_optionalChain([a, 'optionalAccess', _85 => _85.retentionDays]), 1, 365, _audittypes.DEFAULT_AUDIT_CONFIG.retentionDays)
2119
+ ),
2120
+ trustForwardedFor: _optionalChain([a, 'optionalAccess', _86 => _86.trustForwardedFor]) === true
2121
+ };
2122
+ }
2123
+ function normalizeBilling(raw) {
2124
+ const b = _optionalChain([raw, 'optionalAccess', _87 => _87.billing]);
2125
+ const config = {
2126
+ enabled: _optionalChain([b, 'optionalAccess', _88 => _88.enabled]) === true,
2127
+ maxRetryAgeMs: Math.trunc(
2128
+ clampNumber(_optionalChain([b, 'optionalAccess', _89 => _89.maxRetryAgeMs]), 6e4, 2592e6, _billingtypes.DEFAULT_BILLING_CONFIG.maxRetryAgeMs)
2129
+ )
2130
+ };
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;
2133
+ return config;
2134
+ }
2135
+ var DEFAULT_FINGERPRINT = { enabled: false };
2136
+ 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();
2140
+ return out;
2141
+ }
2142
+ function normalizeVoucher(raw) {
2143
+ return { enabled: _optionalChain([raw, 'optionalAccess', _95 => _95.voucher, 'optionalAccess', _96 => _96.enabled]) === true };
2144
+ }
2145
+ var PROXY_TYPES = ["http", "https", "socks5"];
2146
+ function normalizeProxyConfig(raw) {
2147
+ if (!raw || typeof raw !== "object") return void 0;
2148
+ const r = raw;
2149
+ if (typeof r["url"] === "string" && r["url"].trim().length > 0) {
2150
+ return { url: r["url"].trim() };
2151
+ }
2152
+ const type = r["type"];
2153
+ const host = r["host"];
2154
+ const port = r["port"];
2155
+ if (typeof type === "string" && PROXY_TYPES.includes(type) && typeof host === "string" && host.trim().length > 0 && typeof port === "number" && Number.isFinite(port) && port >= 1 && port <= 65535) {
2156
+ const out = {
2157
+ type,
2158
+ host: host.trim(),
2159
+ port: Math.trunc(port)
2160
+ };
2161
+ if (typeof r["username"] === "string" && r["username"].length > 0) out.username = r["username"];
2162
+ if (typeof r["password"] === "string" && r["password"].length > 0) out.password = r["password"];
2163
+ return out;
2164
+ }
2165
+ return void 0;
2166
+ }
2167
+ function normalizeProxySegment(raw) {
2168
+ if (!raw || typeof raw !== "object") return void 0;
2169
+ const r = raw;
2170
+ const out = {};
2171
+ const global = normalizeProxyConfig(r["global"]);
2172
+ if (global) out.global = global;
2173
+ if (r["byProvider"] && typeof r["byProvider"] === "object") {
2174
+ const byProvider = {};
2175
+ for (const [key, value] of Object.entries(r["byProvider"])) {
2176
+ if (!key.trim()) continue;
2177
+ const cfg = normalizeProxyConfig(value);
2178
+ if (cfg) byProvider[key] = cfg;
2179
+ }
2180
+ if (Object.keys(byProvider).length > 0) out.byProvider = byProvider;
2181
+ }
2182
+ return out.global || out.byProvider ? out : void 0;
2183
+ }
2184
+ function normalizeWebhookDestination(raw) {
2185
+ if (!raw || typeof raw !== "object") return void 0;
2186
+ const r = raw;
2187
+ const id = typeof r["id"] === "string" ? r["id"].trim() : "";
2188
+ const url = typeof r["url"] === "string" ? r["url"].trim() : "";
2189
+ const type = r["type"];
2190
+ if (!id || !url || typeof type !== "string" || !_webhooktypes.WEBHOOK_DESTINATION_TYPES.includes(type)) {
2191
+ return void 0;
2192
+ }
2193
+ const out = {
2194
+ id,
2195
+ type,
2196
+ url,
2197
+ enabled: r["enabled"] !== false
2198
+ };
2199
+ if (typeof r["secret"] === "string" && r["secret"].length > 0) out.secret = r["secret"];
2200
+ if (Array.isArray(r["events"])) {
2201
+ const events = r["events"].filter(
2202
+ (e) => typeof e === "string" && _webhooktypes.WEBHOOK_EVENT_KINDS.includes(e)
2203
+ );
2204
+ if (events.length > 0) out.events = events;
2205
+ }
2206
+ return out;
2207
+ }
2208
+ function normalizeWebhookSegment(raw) {
2209
+ if (!raw || typeof raw !== "object") return void 0;
2210
+ const r = raw;
2211
+ const destinations = [];
2212
+ if (Array.isArray(r["destinations"])) {
2213
+ for (const entry of r["destinations"]) {
2214
+ const d = normalizeWebhookDestination(entry);
2215
+ if (d) destinations.push(d);
2216
+ }
2217
+ }
2218
+ const enabled = r["enabled"] === true;
2219
+ if (!enabled && destinations.length === 0) return void 0;
2220
+ return { enabled, destinations };
2221
+ }
2222
+ function clampNumber(value, min, max, fallback) {
2223
+ const n = typeof value === "number" && Number.isFinite(value) ? value : fallback;
2224
+ return Math.min(max, Math.max(min, n));
2225
+ }
2226
+ function normalizeQueueSegments(raw) {
2227
+ const umq = _optionalChain([raw, 'optionalAccess', _97 => _97.userMessageQueue]);
2228
+ const cq = _optionalChain([raw, 'optionalAccess', _98 => _98.concurrencyQueue]);
2229
+ return {
2230
+ 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),
2233
+ waitTimeoutMs: clampNumber(
2234
+ _optionalChain([umq, 'optionalAccess', _101 => _101.waitTimeoutMs]),
2235
+ 1e3,
2236
+ 3e5,
2237
+ DEFAULT_USER_MESSAGE_QUEUE.waitTimeoutMs
2238
+ )
2239
+ },
2240
+ concurrencyQueue: {
2241
+ maxQueueSizeFactor: clampNumber(
2242
+ _optionalChain([cq, 'optionalAccess', _102 => _102.maxQueueSizeFactor]),
2243
+ 1,
2244
+ 10,
2245
+ DEFAULT_CONCURRENCY_QUEUE.maxQueueSizeFactor
2246
+ ),
2247
+ minQueueSize: clampNumber(_optionalChain([cq, 'optionalAccess', _103 => _103.minQueueSize]), 1, 100, DEFAULT_CONCURRENCY_QUEUE.minQueueSize),
2248
+ waitTimeoutMs: clampNumber(
2249
+ _optionalChain([cq, 'optionalAccess', _104 => _104.waitTimeoutMs]),
2250
+ 1e3,
2251
+ 3e5,
2252
+ DEFAULT_CONCURRENCY_QUEUE.waitTimeoutMs
2253
+ )
2254
+ }
2255
+ };
2256
+ }
2257
+ var ALL_ENDPOINTS = ["chat", "responses", "messages", "gemini"];
2258
+ function blankModelMap(endpoint) {
2259
+ const modelMap = {};
2260
+ for (const kind of _chunkVACWOIREcjs.modelKindsForEndpoint.call(void 0, endpoint)) modelMap[kind] = "";
2261
+ return modelMap;
2262
+ }
2263
+ function defaultEndpointConfig(endpoint) {
2264
+ if (_chunkVACWOIREcjs.isKindMappedEndpoint.call(void 0, endpoint)) {
2265
+ return { endpoint, modelMap: blankModelMap(endpoint), useSubscription: false };
2266
+ }
2267
+ if (endpoint === "chat") {
2268
+ return { endpoint, models: [], useSubscription: false };
2269
+ }
2270
+ return {
2271
+ endpoint,
2272
+ defaultModel: "",
2273
+ backgroundModel: "",
2274
+ useSubscription: false
2275
+ };
2276
+ }
2277
+ function normalizePrefixTargets(raw) {
2278
+ if (!raw || typeof raw !== "object") return void 0;
2279
+ const r = raw;
2280
+ const out = {};
2281
+ for (const key of ["claude", "gpt", "gemini"]) {
2282
+ const v = r[key];
2283
+ if (typeof v === "string" && v.trim() !== "") out[key] = v.trim();
2284
+ }
2285
+ return out.claude || out.gpt || out.gemini ? out : void 0;
2286
+ }
2287
+ function normalizeEndpointConfig(e) {
2288
+ const endpoint = e.endpoint;
2289
+ const useSubscription = e.useSubscription === true;
2290
+ const boundAccountId = typeof e.boundAccountId === "string" && e.boundAccountId.trim() !== "" ? e.boundAccountId : void 0;
2291
+ const boundKeyId = typeof e.boundKeyId === "string" && e.boundKeyId.trim() !== "" ? e.boundKeyId : void 0;
2292
+ let config;
2293
+ if (_chunkVACWOIREcjs.isKindMappedEndpoint.call(void 0, endpoint)) {
2294
+ const rawMap = e.modelMap && typeof e.modelMap === "object" ? e.modelMap : {};
2295
+ const modelMap = {};
2296
+ for (const kind of _chunkVACWOIREcjs.modelKindsForEndpoint.call(void 0, endpoint)) {
2297
+ const v = rawMap[kind];
2298
+ modelMap[kind] = typeof v === "string" ? v : "";
2299
+ }
2300
+ config = { endpoint, modelMap, useSubscription };
2301
+ } else if (endpoint === "chat") {
2302
+ const models = Array.isArray(e.models) ? e.models.filter((m) => typeof m === "string" && m.trim() !== "") : [];
2303
+ config = { endpoint, models, useSubscription };
2304
+ if (e.dispatchMode === "prefix") {
2305
+ config.dispatchMode = "prefix";
2306
+ const targets = normalizePrefixTargets(e.prefixTargets);
2307
+ if (targets) config.prefixTargets = targets;
2308
+ }
2309
+ } else {
2310
+ config = {
2311
+ endpoint,
2312
+ defaultModel: typeof e.defaultModel === "string" ? e.defaultModel : "",
2313
+ backgroundModel: typeof e.backgroundModel === "string" ? e.backgroundModel : "",
2314
+ useSubscription
2315
+ };
2316
+ if (Array.isArray(e.backgroundModelIds)) {
2317
+ config.backgroundModelIds = e.backgroundModelIds;
2318
+ }
2319
+ }
2320
+ if (boundAccountId) config.boundAccountId = boundAccountId;
2321
+ if (boundKeyId) config.boundKeyId = boundKeyId;
2322
+ return config;
2323
+ }
2324
+ function defaultServerConfig() {
2325
+ const queues = normalizeQueueSegments(void 0);
2326
+ return {
2327
+ enabled: false,
2328
+ networkBinding: false,
2329
+ endpoints: ALL_ENDPOINTS.map(defaultEndpointConfig),
2330
+ port: DEFAULT_OUTBOUND_PORT,
2331
+ userMessageQueue: queues.userMessageQueue,
2332
+ concurrencyQueue: queues.concurrencyQueue,
2333
+ accountHealth: normalizeAccountHealth(void 0),
2334
+ accountProbe: normalizeAccountProbe(void 0),
2335
+ audit: normalizeAudit(void 0),
2336
+ billing: normalizeBilling(void 0),
2337
+ fingerprint: normalizeFingerprint(void 0),
2338
+ voucher: normalizeVoucher(void 0)
2339
+ };
2340
+ }
2341
+ function normalizeServerConfig(raw) {
2342
+ const base = defaultServerConfig();
2343
+ if (!raw) return base;
2344
+ const byEndpoint = /* @__PURE__ */ new Map();
2345
+ for (const e of _nullishCoalesce(raw.endpoints, () => ( []))) {
2346
+ if (e && ALL_ENDPOINTS.includes(e.endpoint)) {
2347
+ byEndpoint.set(e.endpoint, normalizeEndpointConfig(e));
2348
+ }
2349
+ }
2350
+ const queues = normalizeQueueSegments(raw);
2351
+ const config = {
2352
+ enabled: raw.enabled === true,
2353
+ networkBinding: raw.networkBinding === true,
2354
+ endpoints: ALL_ENDPOINTS.map(
2355
+ (ep) => _nullishCoalesce(byEndpoint.get(ep), () => ( defaultEndpointConfig(ep)))
2356
+ ),
2357
+ port: _nullishCoalesce(raw.port, () => ( base.port)),
2358
+ userMessageQueue: queues.userMessageQueue,
2359
+ concurrencyQueue: queues.concurrencyQueue,
2360
+ accountHealth: normalizeAccountHealth(raw),
2361
+ accountProbe: normalizeAccountProbe(raw),
2362
+ audit: normalizeAudit(raw),
2363
+ billing: normalizeBilling(raw),
2364
+ fingerprint: normalizeFingerprint(raw),
2365
+ voucher: normalizeVoucher(raw)
2366
+ };
2367
+ const proxy = normalizeProxySegment(raw.proxy);
2368
+ if (proxy) config.proxy = proxy;
2369
+ const webhook = normalizeWebhookSegment(raw.webhook);
2370
+ if (webhook) config.webhook = webhook;
2371
+ return config;
2372
+ }
2373
+ async function loadServerConfig(store) {
2374
+ const raw = await store.get(
2375
+ OUTBOUND_API_SERVER_CONFIG_KEY
2376
+ );
2377
+ return normalizeServerConfig(raw);
2378
+ }
2379
+ async function saveServerConfig(store, config) {
2380
+ await store.set(OUTBOUND_API_SERVER_CONFIG_KEY, config);
2381
+ }
2382
+ function mergeServerConfig(current, patch) {
2383
+ return normalizeServerConfig({
2384
+ enabled: _nullishCoalesce(patch.enabled, () => ( current.enabled)),
2385
+ networkBinding: _nullishCoalesce(patch.networkBinding, () => ( current.networkBinding)),
2386
+ endpoints: _nullishCoalesce(patch.endpoints, () => ( current.endpoints)),
2387
+ port: _nullishCoalesce(patch.port, () => ( current.port)),
2388
+ userMessageQueue: _nullishCoalesce(patch.userMessageQueue, () => ( current.userMessageQueue)),
2389
+ concurrencyQueue: _nullishCoalesce(patch.concurrencyQueue, () => ( current.concurrencyQueue)),
2390
+ accountHealth: _nullishCoalesce(patch.accountHealth, () => ( current.accountHealth)),
2391
+ accountProbe: _nullishCoalesce(patch.accountProbe, () => ( current.accountProbe)),
2392
+ audit: _nullishCoalesce(patch.audit, () => ( current.audit)),
2393
+ billing: _nullishCoalesce(patch.billing, () => ( current.billing)),
2394
+ // Proxy is layer-replaced (not deep-merged): a PUT carrying `proxy` swaps the
2395
+ // whole segment; omitting it keeps the current one. `undefined` on both ⇒ absent.
2396
+ proxy: _nullishCoalesce(patch.proxy, () => ( current.proxy)),
2397
+ // Webhook is layer-replaced too (a PUT carrying `webhook` swaps the whole
2398
+ // segment; omitting it keeps the current one). `undefined` on both ⇒ absent.
2399
+ webhook: _nullishCoalesce(patch.webhook, () => ( current.webhook)),
2400
+ // Fingerprint is always-filled (normalizeFingerprint synthesizes a default);
2401
+ // a PUT carrying it replaces the segment, else the current one is kept.
2402
+ fingerprint: _nullishCoalesce(patch.fingerprint, () => ( current.fingerprint)),
2403
+ // Voucher is always-filled (normalizeVoucher synthesizes a default); a PUT
2404
+ // carrying it replaces the segment, else the current one is kept.
2405
+ voucher: _nullishCoalesce(patch.voucher, () => ( current.voucher))
2406
+ });
2407
+ }
2408
+
1703
2409
  // src/outbound-api/outboundApiKeyAuth.ts
1704
2410
 
2411
+
2412
+ // src/outbound-api/keyPolicy.ts
2413
+ var DAY_MS = 864e5;
2414
+ function computeKeyExpiry(row, now) {
2415
+ const mode = _nullishCoalesce(row.activationMode, () => ( "fixed"));
2416
+ if (mode === "activation") {
2417
+ if (row.activatedAt == null) return { expired: false, needsActivation: true };
2418
+ if (row.activationDays == null) return { expired: false };
2419
+ const effectiveExpiresAt = row.activatedAt + row.activationDays * DAY_MS;
2420
+ return { expired: now >= effectiveExpiresAt, effectiveExpiresAt };
2421
+ }
2422
+ if (row.expiresAt == null) return { expired: false };
2423
+ return { expired: now >= row.expiresAt, effectiveExpiresAt: row.expiresAt };
2424
+ }
2425
+ function checkKeyQuota(limits, spend) {
2426
+ if (!limits) return { allowed: true };
2427
+ if (limits.dailyUsd != null && spend.dailyUsd >= limits.dailyUsd) {
2428
+ return { allowed: false, scope: "daily", limitUsd: limits.dailyUsd, spentUsd: spend.dailyUsd };
2429
+ }
2430
+ if (limits.weeklyUsd != null && spend.weeklyUsd >= limits.weeklyUsd) {
2431
+ return { allowed: false, scope: "weekly", limitUsd: limits.weeklyUsd, spentUsd: spend.weeklyUsd };
2432
+ }
2433
+ if (limits.totalUsd != null && spend.totalUsd >= limits.totalUsd) {
2434
+ return { allowed: false, scope: "total", limitUsd: limits.totalUsd, spentUsd: spend.totalUsd };
2435
+ }
2436
+ return { allowed: true };
2437
+ }
2438
+ function canonicalModelId(value) {
2439
+ const idx = value.indexOf(",");
2440
+ const bare = idx >= 0 ? value.slice(idx + 1) : value;
2441
+ return bare.trim().toLowerCase();
2442
+ }
2443
+ function checkModelAllowed(restriction, resolvedModelId) {
2444
+ if (!restriction) return { allowed: true };
2445
+ const target = canonicalModelId(resolvedModelId);
2446
+ const listed = restriction.models.some((m) => canonicalModelId(m) === target);
2447
+ if (restriction.mode === "allowlist") {
2448
+ return listed ? { allowed: true } : { allowed: false, model: resolvedModelId };
2449
+ }
2450
+ return listed ? { allowed: false, model: resolvedModelId } : { allowed: true };
2451
+ }
2452
+
2453
+ // src/outbound-api/outboundApiKeyAuth.ts
1705
2454
  var SECRET_BYTES = 32;
1706
2455
  var PREFIX_LEN = 14;
1707
2456
  var KEY_PREFIX = "sk-omnicross-";
@@ -1749,143 +2498,706 @@ async function createNamedKey(db, name) {
1749
2498
  plaintextOnce: secret
1750
2499
  };
1751
2500
  }
1752
- async function verifyPresentedKey(db, presentedKey) {
1753
- if (!presentedKey) return null;
2501
+ function extractCostLimits(row) {
2502
+ const limits = {};
2503
+ if (row.dailyCostLimitUsd != null) limits.dailyUsd = row.dailyCostLimitUsd;
2504
+ if (row.totalCostLimitUsd != null) limits.totalUsd = row.totalCostLimitUsd;
2505
+ if (row.weeklyCostLimitUsd != null) limits.weeklyUsd = row.weeklyCostLimitUsd;
2506
+ return limits.dailyUsd != null || limits.totalUsd != null || limits.weeklyUsd != null ? limits : void 0;
2507
+ }
2508
+ function extractRateLimit(row) {
2509
+ if (row.rateLimitMaxRequests == null && row.rateLimitWindowMs == null) return void 0;
2510
+ const override = {};
2511
+ if (row.rateLimitMaxRequests != null) override.maxRequests = row.rateLimitMaxRequests;
2512
+ if (row.rateLimitWindowMs != null) override.windowMs = row.rateLimitWindowMs;
2513
+ return override;
2514
+ }
2515
+ function extractModelRestriction(row) {
2516
+ if (row.enableModelRestriction !== true) return void 0;
2517
+ return {
2518
+ mode: _nullishCoalesce(row.restrictionMode, () => ( "blacklist")),
2519
+ models: _nullishCoalesce(row.restrictedModels, () => ( []))
2520
+ };
2521
+ }
2522
+ function toVerifiedKey(row) {
2523
+ const key = { id: row.id };
2524
+ if (row.maxConcurrency !== void 0 && row.maxConcurrency !== null) {
2525
+ key.maxConcurrency = row.maxConcurrency;
2526
+ }
2527
+ const costLimits = extractCostLimits(row);
2528
+ if (costLimits) key.costLimits = costLimits;
2529
+ const rateLimit = extractRateLimit(row);
2530
+ if (rateLimit) key.rateLimit = rateLimit;
2531
+ const modelRestriction = extractModelRestriction(row);
2532
+ if (modelRestriction) key.modelRestriction = modelRestriction;
2533
+ return key;
2534
+ }
2535
+ async function verifyKey(db, presentedKey, now = Date.now()) {
2536
+ if (!presentedKey) return { status: "invalid" };
1754
2537
  const trimmed = presentedKey.trim();
1755
- if (!trimmed) return null;
2538
+ if (!trimmed) return { status: "invalid" };
1756
2539
  const row = await db.outboundApiKeysGetByHash(hashKey(trimmed));
1757
- if (!row) return null;
1758
- if (!row.enabled || row.revokedAt !== null) return null;
2540
+ if (!row) return { status: "invalid" };
2541
+ if (!row.enabled || row.revokedAt !== null) return { status: "invalid" };
2542
+ const expiry = computeKeyExpiry(row, now);
2543
+ if (expiry.expired) return { status: "expired" };
1759
2544
  void db.outboundApiKeysTouchLastUsed(row.id).catch(() => {
1760
2545
  });
1761
- return { id: row.id };
1762
- }
1763
-
1764
- // src/outbound-api/roleDetection.ts
1765
- var _canonicalmodels = require('@omnicross/contracts/canonical-models');
1766
- var BACKGROUND_TIER_TOKENS = /* @__PURE__ */ new Set([
1767
- "haiku",
1768
- "mini",
1769
- "flash",
1770
- "small",
1771
- "lite",
1772
- "nano",
1773
- "8b"
1774
- ]);
1775
- function modelTokens(normalizedId) {
1776
- return normalizedId.split(/[-._:/\s]+/).filter(Boolean);
1777
- }
1778
- function isBackgroundTierModel(rawModelId) {
1779
- if (!rawModelId) return false;
1780
- const tokens = modelTokens(_canonicalmodels.normalizeModelId.call(void 0, rawModelId));
1781
- return tokens.some((tok) => BACKGROUND_TIER_TOKENS.has(tok));
1782
- }
1783
- function extractRequestedModel(ingressFormat, body) {
1784
- const model = body["model"];
1785
- return typeof model === "string" && model ? model : void 0;
1786
- }
1787
- function anthropicHasVision(body) {
1788
- const messages = body["messages"];
1789
- if (!Array.isArray(messages)) return false;
1790
- for (const msg of messages) {
1791
- const content = _optionalChain([msg, 'optionalAccess', _64 => _64.content]);
1792
- if (!Array.isArray(content)) continue;
1793
- for (const part of content) {
1794
- if (_optionalChain([part, 'optionalAccess', _65 => _65.type]) === "image") return true;
1795
- }
2546
+ if (expiry.needsActivation) {
2547
+ void db.outboundApiKeysMarkActivated(row.id, now).catch(() => {
2548
+ });
1796
2549
  }
1797
- return false;
2550
+ return { status: "ok", key: toVerifiedKey(row) };
2551
+ }
2552
+ async function verifyPresentedKey(db, presentedKey) {
2553
+ const result = await verifyKey(db, presentedKey);
2554
+ return result.status === "ok" ? result.key : null;
1798
2555
  }
1799
- function openaiChatHasVision(body) {
1800
- const messages = body["messages"];
1801
- if (!Array.isArray(messages)) return false;
1802
- for (const msg of messages) {
1803
- const content = _optionalChain([msg, 'optionalAccess', _66 => _66.content]);
1804
- if (!Array.isArray(content)) continue;
1805
- for (const part of content) {
1806
- if (_optionalChain([part, 'optionalAccess', _67 => _67.type]) === "image_url") return true;
2556
+
2557
+ // src/outbound-api/outboundConcurrencyGate.ts
2558
+ var ConcurrencyQueueFullError = (_class4 = class extends Error {
2559
+ constructor(apiKeyId, maxQueueSize) {
2560
+ super(`concurrency queue full (max ${maxQueueSize}) for key '${apiKeyId}'`);_class4.prototype.__init5.call(this);;
2561
+ this.apiKeyId = apiKeyId;
2562
+ this.maxQueueSize = maxQueueSize;
2563
+ this.name = "ConcurrencyQueueFullError";
2564
+ }
2565
+
2566
+
2567
+ __init5() {this.code = "concurrency_queue_full"}
2568
+ }, _class4);
2569
+ var ConcurrencyWaitTimeoutError = (_class5 = class extends Error {
2570
+ constructor(apiKeyId, waitTimeoutMs) {
2571
+ super(`concurrency wait timed out after ${waitTimeoutMs}ms for key '${apiKeyId}'`);_class5.prototype.__init6.call(this);;
2572
+ this.apiKeyId = apiKeyId;
2573
+ this.waitTimeoutMs = waitTimeoutMs;
2574
+ this.name = "ConcurrencyWaitTimeoutError";
2575
+ }
2576
+
2577
+
2578
+ __init6() {this.code = "concurrency_wait_timeout"}
2579
+ }, _class5);
2580
+ var ConcurrencyWaitCancelledError = (_class6 = class extends Error {
2581
+ constructor(apiKeyId) {
2582
+ super(`concurrency wait cancelled for key '${apiKeyId}'`);_class6.prototype.__init7.call(this);;
2583
+ this.apiKeyId = apiKeyId;
2584
+ this.name = "ConcurrencyWaitCancelledError";
2585
+ }
2586
+
2587
+ __init7() {this.code = "concurrency_wait_cancelled"}
2588
+ }, _class6);
2589
+ function isConcurrencyRejection(err) {
2590
+ return err instanceof ConcurrencyQueueFullError || err instanceof ConcurrencyWaitTimeoutError || err instanceof ConcurrencyWaitCancelledError;
2591
+ }
2592
+ var OutboundConcurrencyGate = (_class7 = class {constructor() { _class7.prototype.__init8.call(this); }
2593
+ __init8() {this.states = /* @__PURE__ */ new Map()}
2594
+ ensure(apiKeyId) {
2595
+ let state = this.states.get(apiKeyId);
2596
+ if (!state) {
2597
+ state = { active: 0, waiters: [] };
2598
+ this.states.set(apiKeyId, state);
1807
2599
  }
2600
+ return state;
1808
2601
  }
1809
- return false;
1810
- }
1811
- function openaiResponsesHasVision(body) {
1812
- const input = body["input"];
1813
- if (!Array.isArray(input)) return false;
1814
- for (const item of input) {
1815
- const content = _optionalChain([item, 'optionalAccess', _68 => _68.content]);
1816
- if (Array.isArray(content)) {
1817
- for (const part of content) {
1818
- if (_optionalChain([part, 'optionalAccess', _69 => _69.type]) === "input_image") return true;
2602
+ /** Delete a key's state once it is fully idle (no active, no waiters). */
2603
+ gc(apiKeyId) {
2604
+ const state = this.states.get(apiKeyId);
2605
+ if (state && state.active === 0 && state.waiters.length === 0) {
2606
+ this.states.delete(apiKeyId);
2607
+ }
2608
+ }
2609
+ /**
2610
+ * Acquire a concurrency slot for `apiKeyId` under `limit`. Grants immediately
2611
+ * when `active < limit`; else enqueues FIFO while under the per-key queue cap;
2612
+ * else rejects queue-full. `limit <= 0` = unlimited (always granted).
2613
+ */
2614
+ acquire(apiKeyId, limit, options) {
2615
+ const state = this.ensure(apiKeyId);
2616
+ const cap = limit > 0 ? limit : Infinity;
2617
+ if (state.active < cap) {
2618
+ state.active += 1;
2619
+ const slot = this.makeSlot(apiKeyId);
2620
+ return { granted: Promise.resolve(slot), cancel: slot.cancel };
2621
+ }
2622
+ const maxQueueSize = Math.max(
2623
+ Number.isFinite(cap) ? cap * options.maxQueueSizeFactor : Infinity,
2624
+ options.minQueueSize
2625
+ );
2626
+ if (state.waiters.length >= maxQueueSize) {
2627
+ const err = new ConcurrencyQueueFullError(apiKeyId, maxQueueSize);
2628
+ return { granted: Promise.reject(err), cancel: () => {
2629
+ } };
2630
+ }
2631
+ let settled = false;
2632
+ let granted = false;
2633
+ let resolveGrant;
2634
+ let rejectGrant;
2635
+ const grantedPromise = new Promise((resolve, reject) => {
2636
+ resolveGrant = resolve;
2637
+ rejectGrant = reject;
2638
+ });
2639
+ const waiter = {
2640
+ cap,
2641
+ settled: false,
2642
+ timeoutHandle: null,
2643
+ grant: () => {
2644
+ if (settled) return;
2645
+ settled = true;
2646
+ granted = true;
2647
+ waiter.settled = true;
2648
+ if (waiter.timeoutHandle) clearTimeout(waiter.timeoutHandle);
2649
+ state.active += 1;
2650
+ resolveGrant(this.makeSlot(apiKeyId));
2651
+ },
2652
+ fail: (err) => {
2653
+ if (settled) return;
2654
+ settled = true;
2655
+ waiter.settled = true;
2656
+ if (waiter.timeoutHandle) clearTimeout(waiter.timeoutHandle);
2657
+ const idx = state.waiters.indexOf(waiter);
2658
+ if (idx >= 0) state.waiters.splice(idx, 1);
2659
+ rejectGrant(err);
2660
+ this.gc(apiKeyId);
1819
2661
  }
2662
+ };
2663
+ waiter.timeoutHandle = setTimeout(() => {
2664
+ waiter.fail(new ConcurrencyWaitTimeoutError(apiKeyId, options.waitTimeoutMs));
2665
+ }, options.waitTimeoutMs);
2666
+ state.waiters.push(waiter);
2667
+ const cancel = () => {
2668
+ if (settled || granted) return;
2669
+ waiter.fail(new ConcurrencyWaitCancelledError(apiKeyId));
2670
+ };
2671
+ return { granted: grantedPromise, cancel };
2672
+ }
2673
+ /** Build an idempotent granted slot (`release` decrements; `cancel` is a no-op). */
2674
+ makeSlot(apiKeyId) {
2675
+ let released = false;
2676
+ const release2 = () => {
2677
+ if (released) return;
2678
+ released = true;
2679
+ const state = this.states.get(apiKeyId);
2680
+ if (!state) return;
2681
+ state.active = Math.max(0, state.active - 1);
2682
+ this.dispatchNext(apiKeyId);
2683
+ this.gc(apiKeyId);
2684
+ };
2685
+ return { release: release2, cancel: () => {
2686
+ } };
2687
+ }
2688
+ /** After a release freed a slot, grant the FIFO head if it fits under its cap. */
2689
+ dispatchNext(apiKeyId) {
2690
+ const state = this.states.get(apiKeyId);
2691
+ if (!state || state.waiters.length === 0) return;
2692
+ const head = state.waiters[0];
2693
+ if (state.active < head.cap) {
2694
+ state.waiters.shift();
2695
+ head.grant();
1820
2696
  }
1821
- if (_optionalChain([item, 'optionalAccess', _70 => _70.type]) === "input_image") return true;
2697
+ }
2698
+ /** Snapshot for observability — only keys with active slots or waiters. */
2699
+ getStatus() {
2700
+ const out = [];
2701
+ for (const [apiKeyId, state] of this.states) {
2702
+ if (state.active > 0 || state.waiters.length > 0) {
2703
+ out.push({ apiKeyId, active: state.active, waiting: state.waiters.length });
2704
+ }
2705
+ }
2706
+ return out;
2707
+ }
2708
+ /** Drop all state + pending timers (tests / teardown). */
2709
+ reset() {
2710
+ for (const state of this.states.values()) {
2711
+ for (const w of state.waiters) {
2712
+ if (w.timeoutHandle) clearTimeout(w.timeoutHandle);
2713
+ }
2714
+ }
2715
+ this.states.clear();
2716
+ }
2717
+ }, _class7);
2718
+
2719
+ // src/outbound-api/outboundRateLimiter.ts
2720
+ var DEFAULT_WINDOW_MS = 6e4;
2721
+ var DEFAULT_MAX_REQUESTS = 60;
2722
+ var OutboundRateLimiter = (_class8 = class {
2723
+
2724
+
2725
+ /** apiKeyId → ascending request timestamps within the current window. */
2726
+ __init9() {this.hits = /* @__PURE__ */ new Map()}
2727
+ constructor(options = {}) {;_class8.prototype.__init9.call(this);
2728
+ this.windowMs = _nullishCoalesce(options.windowMs, () => ( DEFAULT_WINDOW_MS));
2729
+ this.maxRequests = _nullishCoalesce(options.maxRequests, () => ( DEFAULT_MAX_REQUESTS));
2730
+ }
2731
+ /**
2732
+ * Record a request for `apiKeyId` and decide whether it is allowed. Prunes
2733
+ * timestamps older than the window first; when allowed, the request's
2734
+ * timestamp is appended.
2735
+ *
2736
+ * `override` (outbound-key-policy) supplies a PER-KEY window/max for this
2737
+ * bucket, superseding the instance defaults for THAT key. Absent ⇒ the
2738
+ * instance default 60/60s (byte-identical to before this change). An effective
2739
+ * `maxRequests` of `0` means UNLIMITED — the request is allowed and NOT
2740
+ * recorded (no bucket growth).
2741
+ */
2742
+ 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));
2745
+ if (maxRequests === 0) return { allowed: true, retryAfterSeconds: 0 };
2746
+ const cutoff = now - windowMs;
2747
+ const timestamps = (_nullishCoalesce(this.hits.get(apiKeyId), () => ( []))).filter((ts) => ts > cutoff);
2748
+ if (timestamps.length >= maxRequests) {
2749
+ if (timestamps.length === 0) {
2750
+ this.hits.delete(apiKeyId);
2751
+ return { allowed: false, retryAfterSeconds: Math.max(1, Math.ceil(windowMs / 1e3)) };
2752
+ }
2753
+ const oldest = timestamps[0];
2754
+ const retryAfterMs = Math.max(0, oldest + windowMs - now);
2755
+ this.hits.set(apiKeyId, timestamps);
2756
+ return {
2757
+ allowed: false,
2758
+ retryAfterSeconds: Math.max(1, Math.ceil(retryAfterMs / 1e3))
2759
+ };
2760
+ }
2761
+ timestamps.push(now);
2762
+ this.hits.set(apiKeyId, timestamps);
2763
+ return { allowed: true, retryAfterSeconds: 0 };
2764
+ }
2765
+ /** Drop all recorded state (tests / teardown). */
2766
+ reset() {
2767
+ this.hits.clear();
2768
+ }
2769
+ }, _class8);
2770
+
2771
+ // src/outbound-api/userMessageDetection.ts
2772
+ function asArray(v) {
2773
+ return Array.isArray(v) ? v : [];
2774
+ }
2775
+ function asObject(v) {
2776
+ return v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
2777
+ }
2778
+ function last(arr) {
2779
+ return arr.length > 0 ? arr[arr.length - 1] : void 0;
2780
+ }
2781
+ function isUserMessageAnthropic(body) {
2782
+ const messages = asArray(body["messages"]);
2783
+ const lastMsg = asObject(last(messages));
2784
+ if (!lastMsg || lastMsg["role"] !== "user") return false;
2785
+ const content = lastMsg["content"];
2786
+ if (typeof content === "string") return true;
2787
+ if (Array.isArray(content)) {
2788
+ const hasToolResult = content.some(
2789
+ (block) => _optionalChain([asObject, 'call', _107 => _107(block), 'optionalAccess', _108 => _108["type"]]) === "tool_result"
2790
+ );
2791
+ return !hasToolResult;
1822
2792
  }
1823
2793
  return false;
1824
2794
  }
1825
- function geminiHasVision(body) {
1826
- const contents = body["contents"];
1827
- if (!Array.isArray(contents)) return false;
1828
- for (const content of contents) {
1829
- const parts = _optionalChain([content, 'optionalAccess', _71 => _71.parts]);
1830
- if (!Array.isArray(parts)) continue;
1831
- for (const part of parts) {
1832
- const p = part;
1833
- if (_optionalChain([p, 'optionalAccess', _72 => _72.inline_data]) || _optionalChain([p, 'optionalAccess', _73 => _73.inlineData]) || _optionalChain([p, 'optionalAccess', _74 => _74.file_data]) || _optionalChain([p, 'optionalAccess', _75 => _75.fileData])) return true;
1834
- }
2795
+ function isUserMessageResponses(body) {
2796
+ const input = body["input"];
2797
+ if (typeof input === "string") return input.length > 0;
2798
+ if (Array.isArray(input)) {
2799
+ const lastItem = asObject(last(input));
2800
+ if (!lastItem) return false;
2801
+ if (lastItem["type"] === "function_call_output") return false;
2802
+ return lastItem["role"] === "user";
1835
2803
  }
1836
2804
  return false;
1837
2805
  }
1838
- function hasVisionContent(ingressFormat, body) {
1839
- switch (ingressFormat) {
1840
- case "anthropic-messages":
1841
- return anthropicHasVision(body);
1842
- case "openai-chat":
1843
- return openaiChatHasVision(body);
1844
- case "openai-responses":
1845
- return openaiResponsesHasVision(body);
1846
- case "gemini-generatecontent":
1847
- return geminiHasVision(body);
2806
+ function isUserMessageChat(body) {
2807
+ const messages = asArray(body["messages"]);
2808
+ const lastMsg = asObject(last(messages));
2809
+ if (!lastMsg) return false;
2810
+ return lastMsg["role"] === "user";
2811
+ }
2812
+ function isUserMessageGemini(body) {
2813
+ const contents = asArray(body["contents"]);
2814
+ const lastContent = asObject(last(contents));
2815
+ if (!lastContent || lastContent["role"] !== "user") return false;
2816
+ const parts = asArray(lastContent["parts"]);
2817
+ const hasFunctionResponse = parts.some(
2818
+ (part) => _optionalChain([asObject, 'call', _109 => _109(part), 'optionalAccess', _110 => _110["functionResponse"]]) !== void 0
2819
+ );
2820
+ return !hasFunctionResponse;
2821
+ }
2822
+ function isUserMessageRequest(endpoint, parsedBody) {
2823
+ const body = asObject(parsedBody);
2824
+ if (!body) return false;
2825
+ switch (endpoint) {
2826
+ case "messages":
2827
+ return isUserMessageAnthropic(body);
2828
+ case "responses":
2829
+ return isUserMessageResponses(body);
2830
+ case "chat":
2831
+ return isUserMessageChat(body);
2832
+ case "gemini":
2833
+ return isUserMessageGemini(body);
1848
2834
  default:
1849
2835
  return false;
1850
2836
  }
1851
- }
1852
- function detectRequestRole(ingressFormat, body, options) {
1853
- if (hasVisionContent(ingressFormat, body)) return "vision";
1854
- const requestedModel = extractRequestedModel(ingressFormat, body);
1855
- if (requestedModel) {
1856
- const overrides = _optionalChain([options, 'optionalAccess', _76 => _76.backgroundModelIds]);
1857
- if (overrides && overrides.length > 0) {
1858
- const reqNorm = _canonicalmodels.normalizeModelId.call(void 0, requestedModel);
1859
- const inOverride = overrides.some((id) => {
1860
- if (!id) return false;
1861
- const candidate = id.includes(",") ? id.slice(id.indexOf(",") + 1) : id;
1862
- return _canonicalmodels.normalizeModelId.call(void 0, candidate) === reqNorm || candidate === requestedModel;
1863
- });
1864
- if (inOverride) return "background";
1865
- }
1866
- if (isBackgroundTierModel(requestedModel)) return "background";
2837
+ }
2838
+
2839
+ // src/outbound-api/userMessageSerialQueue.ts
2840
+ var SerialQueueTimeoutError = (_class9 = class extends Error {
2841
+ constructor(providerId, waitTimeoutMs) {
2842
+ super(`user-message serial queue wait timed out after ${waitTimeoutMs}ms for '${providerId}'`);_class9.prototype.__init10.call(this);;
2843
+ this.providerId = providerId;
2844
+ this.waitTimeoutMs = waitTimeoutMs;
2845
+ this.name = "SerialQueueTimeoutError";
2846
+ }
2847
+
2848
+
2849
+ __init10() {this.code = "serial_queue_timeout"}
2850
+ }, _class9);
2851
+ function isSerialQueueTimeout(err) {
2852
+ return err instanceof SerialQueueTimeoutError;
2853
+ }
2854
+ var UserMessageSerialQueue = (_class10 = class {constructor() { _class10.prototype.__init11.call(this); }
2855
+ __init11() {this.states = /* @__PURE__ */ new Map()}
2856
+ ensure(providerId) {
2857
+ let state = this.states.get(providerId);
2858
+ if (!state) {
2859
+ state = { holding: false, lastReleaseTs: null, waiters: [], dispatchHandle: null };
2860
+ this.states.set(providerId, state);
2861
+ }
2862
+ return state;
2863
+ }
2864
+ /**
2865
+ * Acquire the serial slot for `providerId`. Resolves immediately when the slot
2866
+ * is free, no one is queued, and the `delayMs` gap since the last release has
2867
+ * elapsed; otherwise enqueues FIFO and resolves in order (or rejects with a
2868
+ * {@link SerialQueueTimeoutError} after `waitTimeoutMs`).
2869
+ */
2870
+ acquire(providerId, options) {
2871
+ const { waitTimeoutMs, delayMs } = options;
2872
+ const now = _nullishCoalesce(options.now, () => ( Date.now()));
2873
+ const state = this.ensure(providerId);
2874
+ const spacingElapsed = state.lastReleaseTs === null || now - state.lastReleaseTs >= delayMs;
2875
+ if (!state.holding && state.waiters.length === 0 && spacingElapsed) {
2876
+ state.holding = true;
2877
+ return Promise.resolve(this.makeSlot(providerId));
2878
+ }
2879
+ return new Promise((resolve, reject) => {
2880
+ const waiter = {
2881
+ delayMs,
2882
+ resolve,
2883
+ reject,
2884
+ timeoutHandle: null,
2885
+ done: false
2886
+ };
2887
+ waiter.timeoutHandle = setTimeout(() => {
2888
+ if (waiter.done) return;
2889
+ waiter.done = true;
2890
+ const idx = state.waiters.indexOf(waiter);
2891
+ if (idx >= 0) state.waiters.splice(idx, 1);
2892
+ reject(new SerialQueueTimeoutError(providerId, waitTimeoutMs));
2893
+ }, waitTimeoutMs);
2894
+ state.waiters.push(waiter);
2895
+ this.maybeDispatch(providerId);
2896
+ });
2897
+ }
2898
+ /** Build an idempotent release for a granted slot. */
2899
+ makeSlot(providerId) {
2900
+ let released = false;
2901
+ return {
2902
+ release: () => {
2903
+ if (released) return;
2904
+ released = true;
2905
+ const state = this.states.get(providerId);
2906
+ if (!state) return;
2907
+ state.holding = false;
2908
+ state.lastReleaseTs = Date.now();
2909
+ this.maybeDispatch(providerId);
2910
+ }
2911
+ };
2912
+ }
2913
+ /**
2914
+ * Grant the head waiter when the slot is free and the head's `delayMs` gap has
2915
+ * elapsed; otherwise schedule a dispatch for the residual gap. No-op while the
2916
+ * slot is held (release re-invokes this) or the queue is empty.
2917
+ */
2918
+ maybeDispatch(providerId) {
2919
+ const state = this.states.get(providerId);
2920
+ if (!state || state.holding || state.waiters.length === 0) return;
2921
+ const head = state.waiters[0];
2922
+ const now = Date.now();
2923
+ const elapsed = state.lastReleaseTs === null ? Infinity : now - state.lastReleaseTs;
2924
+ const residual = Math.max(0, head.delayMs - elapsed);
2925
+ if (residual <= 0) {
2926
+ this.grantHead(providerId);
2927
+ return;
2928
+ }
2929
+ if (state.dispatchHandle !== null) return;
2930
+ state.dispatchHandle = setTimeout(() => {
2931
+ state.dispatchHandle = null;
2932
+ this.grantHead(providerId);
2933
+ }, residual);
2934
+ }
2935
+ /** Hand the slot to the FIFO head (if free and someone is waiting). */
2936
+ grantHead(providerId) {
2937
+ const state = this.states.get(providerId);
2938
+ if (!state || state.holding || state.waiters.length === 0) return;
2939
+ if (state.dispatchHandle !== null) {
2940
+ clearTimeout(state.dispatchHandle);
2941
+ state.dispatchHandle = null;
2942
+ }
2943
+ const head = state.waiters.shift();
2944
+ if (!head) return;
2945
+ if (head.timeoutHandle) clearTimeout(head.timeoutHandle);
2946
+ head.done = true;
2947
+ state.holding = true;
2948
+ head.resolve(this.makeSlot(providerId));
2949
+ }
2950
+ /** Snapshot for observability — only keys holding a slot or with waiters. */
2951
+ getStatus() {
2952
+ const out = [];
2953
+ for (const [providerId, state] of this.states) {
2954
+ if (state.holding || state.waiters.length > 0) {
2955
+ out.push({ providerId, holding: state.holding, waiting: state.waiters.length });
2956
+ }
2957
+ }
2958
+ return out;
2959
+ }
2960
+ /** Drop all state + pending timers (tests / teardown). */
2961
+ reset() {
2962
+ for (const state of this.states.values()) {
2963
+ if (state.dispatchHandle) clearTimeout(state.dispatchHandle);
2964
+ for (const w of state.waiters) {
2965
+ if (w.timeoutHandle) clearTimeout(w.timeoutHandle);
2966
+ }
2967
+ }
2968
+ this.states.clear();
2969
+ }
2970
+ }, _class10);
2971
+
2972
+ // src/outbound-api/voucher.ts
2973
+
2974
+ var CODE_ENTROPY_CHARS = 32;
2975
+ var CODE_PREFIX = "CC_";
2976
+ var DISPLAY_PREFIX_LEN = 8;
2977
+ var DAY_MS2 = 864e5;
2978
+ function generateVoucherCode() {
2979
+ return CODE_PREFIX + randomBase62(CODE_ENTROPY_CHARS);
2980
+ }
2981
+ function hashVoucherCode(code) {
2982
+ return _crypto.createHash.call(void 0, "sha256").update(code, "utf8").digest("hex");
2983
+ }
2984
+ function voucherCodePrefix(code) {
2985
+ return code.slice(0, DISPLAY_PREFIX_LEN);
2986
+ }
2987
+ function newVoucherId() {
2988
+ return `vch_${Date.now()}_${randomBase62(8)}`;
2989
+ }
2990
+ function computeVoucherGrant(voucher, currentKey, now) {
2991
+ if (voucher.type === "credit") {
2992
+ const current = _nullishCoalesce(_optionalChain([currentKey, 'optionalAccess', _111 => _111.totalCostLimitUsd]), () => ( 0));
2993
+ let granted2 = current + (_nullishCoalesce(voucher.creditUsd, () => ( 0)));
2994
+ if (voucher.maxTotalCostLimitUsd != null) {
2995
+ granted2 = Math.min(granted2, voucher.maxTotalCostLimitUsd);
2996
+ }
2997
+ return { totalCostLimitUsd: granted2 };
2998
+ }
2999
+ const currentExpiry = _nullishCoalesce(_optionalChain([currentKey, 'optionalAccess', _112 => _112.expiresAt]), () => ( now));
3000
+ let granted = currentExpiry + (_nullishCoalesce(voucher.renewalDays, () => ( 0))) * DAY_MS2;
3001
+ if (voucher.maxExpiryDays != null) {
3002
+ granted = Math.min(granted, now + voucher.maxExpiryDays * DAY_MS2);
3003
+ }
3004
+ return { expiresAt: granted };
3005
+ }
3006
+ function toVoucherInfo(v) {
3007
+ const info = {
3008
+ id: v.id,
3009
+ codePrefix: v.codePrefix,
3010
+ type: v.type,
3011
+ status: v.status,
3012
+ createdAt: v.createdAt
3013
+ };
3014
+ if (v.creditUsd != null) info.creditUsd = v.creditUsd;
3015
+ if (v.renewalDays != null) info.renewalDays = v.renewalDays;
3016
+ if (v.maxTotalCostLimitUsd != null) info.maxTotalCostLimitUsd = v.maxTotalCostLimitUsd;
3017
+ if (v.maxExpiryDays != null) info.maxExpiryDays = v.maxExpiryDays;
3018
+ if (v.redeemedAt != null) info.redeemedAt = v.redeemedAt;
3019
+ if (v.redeemedByKeyId != null) info.redeemedByKeyId = v.redeemedByKeyId;
3020
+ if (v.grantApplied != null) info.grantApplied = v.grantApplied;
3021
+ if (v.grantedTotalCostLimitUsd != null) info.grantedTotalCostLimitUsd = v.grantedTotalCostLimitUsd;
3022
+ if (v.grantedExpiresAt != null) info.grantedExpiresAt = v.grantedExpiresAt;
3023
+ if (v.revokedAt != null) info.revokedAt = v.revokedAt;
3024
+ return info;
3025
+ }
3026
+
3027
+ // src/outbound-api/voucherRedeem.ts
3028
+ function isRedeemRequest(method, url) {
3029
+ 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(/\/+$/, "")]), () => ( ""));
3031
+ return path.endsWith("/redeem");
3032
+ }
3033
+ function writeErr(res, status, message, headers = {}) {
3034
+ if (res.headersSent) return;
3035
+ res.writeHead(status, { "Content-Type": "application/json", ...headers });
3036
+ res.end(JSON.stringify({ error: { type: "voucher_error", message } }));
3037
+ }
3038
+ function writeResult(res, result) {
3039
+ if (res.headersSent) return;
3040
+ res.writeHead(200, { "Content-Type": "application/json" });
3041
+ res.end(JSON.stringify({ ok: true, ...result }));
3042
+ }
3043
+ function readBody2(req) {
3044
+ return new Promise((resolve, reject) => {
3045
+ const chunks = [];
3046
+ req.on("data", (c) => chunks.push(c));
3047
+ req.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
3048
+ req.on("error", reject);
3049
+ });
3050
+ }
3051
+ function grantToResult(type, granted) {
3052
+ const result = { type };
3053
+ if (granted.totalCostLimitUsd != null) result.totalCostLimitUsd = granted.totalCostLimitUsd;
3054
+ if (granted.expiresAt != null) result.expiresAt = granted.expiresAt;
3055
+ return result;
3056
+ }
3057
+ function currentResult(type, keyRow) {
3058
+ const result = { type };
3059
+ 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) {
3062
+ result.expiresAt = keyRow.expiresAt;
3063
+ }
3064
+ return result;
3065
+ }
3066
+ function recordedAbsolute(v) {
3067
+ const granted = {};
3068
+ if (v.grantedTotalCostLimitUsd != null) granted.totalCostLimitUsd = v.grantedTotalCostLimitUsd;
3069
+ if (v.grantedExpiresAt != null) granted.expiresAt = v.grantedExpiresAt;
3070
+ return granted;
3071
+ }
3072
+ function policyFrom(granted) {
3073
+ const policy = {};
3074
+ if (granted.totalCostLimitUsd != null) policy.totalCostLimitUsd = granted.totalCostLimitUsd;
3075
+ if (granted.expiresAt != null) policy.expiresAt = granted.expiresAt;
3076
+ return policy;
3077
+ }
3078
+ var NOT_REDEEMABLE = "Invalid or non-redeemable code";
3079
+ var fallbackMutex = null;
3080
+ function getFallbackMutex() {
3081
+ fallbackMutex ??= new KeyedMutex();
3082
+ return fallbackMutex;
3083
+ }
3084
+ async function handleVoucherRedeem(req, res, deps, voucherEnabled, redeemLimiter, verifiedKeyId, presentedKey, now, redeemMutex) {
3085
+ if (!voucherEnabled || !deps.voucherDb) {
3086
+ writeErr(res, 403, "Voucher redemption is not enabled");
3087
+ return;
3088
+ }
3089
+ const voucherDb = deps.voucherDb;
3090
+ const rl = redeemLimiter.check(verifiedKeyId, now);
3091
+ if (!rl.allowed) {
3092
+ writeErr(res, 429, "Too many redeem attempts", { "Retry-After": String(rl.retryAfterSeconds) });
3093
+ return;
3094
+ }
3095
+ const raw = await readBody2(req);
3096
+ let code;
3097
+ try {
3098
+ code = raw ? JSON.parse(raw)["code"] : void 0;
3099
+ } catch (e17) {
3100
+ writeErr(res, 400, "Invalid JSON in request body");
3101
+ return;
1867
3102
  }
1868
- return "default";
1869
- }
1870
- function endpointToIngressFormat(endpoint) {
1871
- switch (endpoint) {
1872
- case "chat":
1873
- return "openai-chat";
1874
- case "responses":
1875
- return "openai-responses";
1876
- case "messages":
1877
- return "anthropic-messages";
1878
- case "gemini":
1879
- return "gemini-generatecontent";
3103
+ if (typeof code !== "string" || !code.trim()) {
3104
+ writeErr(res, 400, "Missing redemption code");
3105
+ return;
1880
3106
  }
3107
+ const codeHash = hashVoucherCode(code.trim());
3108
+ const keyHash = hashKey(presentedKey.trim());
3109
+ const applyFirstPass = async (voucher, absolute) => {
3110
+ const ok = await deps.db.outboundApiKeysSetPolicy(verifiedKeyId, policyFrom(absolute));
3111
+ if (!ok) {
3112
+ await voucherDb.voucherRevertRedeem(voucher.id, verifiedKeyId);
3113
+ return { ok: false, status: 409, message: "Could not apply the grant \u2014 please retry" };
3114
+ }
3115
+ await voucherDb.voucherMarkGrantApplied(voucher.id);
3116
+ return { ok: true, result: grantToResult(voucher.type, absolute) };
3117
+ };
3118
+ const reconcileOne = async (voucher) => {
3119
+ const ok = await deps.db.outboundApiKeysSetPolicy(verifiedKeyId, policyFrom(recordedAbsolute(voucher)));
3120
+ if (ok) await voucherDb.voucherMarkGrantApplied(voucher.id);
3121
+ };
3122
+ const reconcileStranded = async () => {
3123
+ const all = await voucherDb.voucherList();
3124
+ const stranded = all.filter((v) => v.status === "redeemed" && v.grantApplied !== true && v.redeemedByKeyId === verifiedKeyId).sort((a, b) => (_nullishCoalesce(a.redeemedAt, () => ( 0))) - (_nullishCoalesce(b.redeemedAt, () => ( 0))));
3125
+ for (const v of stranded) await reconcileOne(v);
3126
+ };
3127
+ const runCritical = async () => {
3128
+ await reconcileStranded();
3129
+ const voucher = await voucherDb.voucherGetByHash(codeHash);
3130
+ if (!voucher || voucher.status === "revoked") {
3131
+ return { ok: false, status: 400, message: NOT_REDEEMABLE };
3132
+ }
3133
+ if (voucher.status === "redeemed") {
3134
+ if (voucher.redeemedByKeyId !== verifiedKeyId) {
3135
+ return { ok: false, status: 400, message: NOT_REDEEMABLE };
3136
+ }
3137
+ if (voucher.grantApplied === true) {
3138
+ const keyRow2 = await deps.db.outboundApiKeysGetByHash(keyHash);
3139
+ return { ok: true, result: currentResult(voucher.type, keyRow2) };
3140
+ }
3141
+ return await applyFirstPass(voucher, recordedAbsolute(voucher));
3142
+ }
3143
+ const keyRow = await deps.db.outboundApiKeysGetByHash(keyHash);
3144
+ const absolute = computeVoucherGrant(voucher, keyRow, now);
3145
+ const won = await voucherDb.voucherRedeemCas(voucher.id, verifiedKeyId, absolute, now);
3146
+ if (!won) {
3147
+ const after = await voucherDb.voucherGetByHash(codeHash);
3148
+ if (_optionalChain([after, 'optionalAccess', _120 => _120.status]) === "redeemed" && after.redeemedByKeyId === verifiedKeyId) {
3149
+ return after.grantApplied === true ? { ok: true, result: currentResult(after.type, await deps.db.outboundApiKeysGetByHash(keyHash)) } : await applyFirstPass(after, recordedAbsolute(after));
3150
+ }
3151
+ return { ok: false, status: 409, message: "Code was already redeemed" };
3152
+ }
3153
+ return await applyFirstPass(voucher, absolute);
3154
+ };
3155
+ const mutex = _nullishCoalesce(redeemMutex, () => ( getFallbackMutex()));
3156
+ const outcome = await mutex.runExclusive(verifiedKeyId, runCritical);
3157
+ if (outcome.ok) writeResult(res, outcome.result);
3158
+ else writeErr(res, outcome.status, outcome.message);
1881
3159
  }
1882
3160
 
1883
3161
  // src/outbound-api/outboundApiRouter.ts
3162
+ var fallbackRedeemLimiter = null;
3163
+ function getFallbackRedeemLimiter() {
3164
+ fallbackRedeemLimiter ??= new OutboundRateLimiter({ maxRequests: 10, windowMs: 6e4 });
3165
+ return fallbackRedeemLimiter;
3166
+ }
1884
3167
  function writeJsonError(res, status, message, headers = {}) {
1885
3168
  if (res.headersSent) return;
1886
3169
  res.writeHead(status, { "Content-Type": "application/json", ...headers });
1887
3170
  res.end(JSON.stringify({ error: { type: "outbound_api_error", message } }));
1888
3171
  }
3172
+ function writeCostLimitError(res, scope, limitUsd, spentUsd) {
3173
+ if (res.headersSent) return;
3174
+ res.writeHead(402, { "Content-Type": "application/json" });
3175
+ res.end(
3176
+ JSON.stringify({
3177
+ error: {
3178
+ type: "outbound_api_error",
3179
+ message: `Cost limit reached for this key (${scope}): $${spentUsd.toFixed(4)} of $${limitUsd.toFixed(4)}`
3180
+ },
3181
+ scope,
3182
+ limitUsd,
3183
+ spentUsd
3184
+ })
3185
+ );
3186
+ }
3187
+ function writeModelNotAllowedError(res, model, mode) {
3188
+ if (res.headersSent) return;
3189
+ res.writeHead(403, { "Content-Type": "application/json" });
3190
+ res.end(
3191
+ JSON.stringify({
3192
+ error: {
3193
+ type: "outbound_api_error",
3194
+ message: `Model '${model}' is not permitted for this key (${mode})`
3195
+ },
3196
+ model,
3197
+ mode
3198
+ })
3199
+ );
3200
+ }
1889
3201
  function extractPresentedKey(req) {
1890
3202
  const auth = req.headers["authorization"];
1891
3203
  if (typeof auth === "string" && auth.trim()) {
@@ -1894,14 +3206,14 @@ function extractPresentedKey(req) {
1894
3206
  }
1895
3207
  const xApiKey = req.headers["x-api-key"];
1896
3208
  const xApi = Array.isArray(xApiKey) ? xApiKey[0] : xApiKey;
1897
- if (_optionalChain([xApi, 'optionalAccess', _77 => _77.trim, 'call', _78 => _78()])) return xApi.trim();
3209
+ if (_optionalChain([xApi, 'optionalAccess', _121 => _121.trim, 'call', _122 => _122()])) return xApi.trim();
1898
3210
  const goog = req.headers["x-goog-api-key"];
1899
3211
  const g = Array.isArray(goog) ? goog[0] : goog;
1900
- return _optionalChain([g, 'optionalAccess', _79 => _79.trim, 'call', _80 => _80()]) || void 0;
3212
+ return _optionalChain([g, 'optionalAccess', _123 => _123.trim, 'call', _124 => _124()]) || void 0;
1901
3213
  }
1902
3214
  function selectEndpoint(method, url) {
1903
3215
  if (method !== "POST" || !url) return null;
1904
- const path = _nullishCoalesce(_optionalChain([url, 'access', _81 => _81.split, 'call', _82 => _82("?"), 'access', _83 => _83[0], 'optionalAccess', _84 => _84.replace, 'call', _85 => _85(/\/+$/, "")]), () => ( ""));
3216
+ const path = _nullishCoalesce(_optionalChain([url, 'access', _125 => _125.split, 'call', _126 => _126("?"), 'access', _127 => _127[0], 'optionalAccess', _128 => _128.replace, 'call', _129 => _129(/\/+$/, "")]), () => ( ""));
1905
3217
  if (path.endsWith("/chat/completions")) return "chat";
1906
3218
  if (path.endsWith("/responses")) return "responses";
1907
3219
  if (path.includes("/v1/messages")) return "messages";
@@ -1917,7 +3229,18 @@ function extractGeminiModelFromUrl(url) {
1917
3229
  const m = /\/models\/([^/:]+):(?:stream)?[gG]enerateContent$/.exec(path.replace(/\/+$/, ""));
1918
3230
  return m ? decodeURIComponent(m[1]) : void 0;
1919
3231
  }
1920
- function readBody2(req) {
3232
+ function isModelsListRequest(url) {
3233
+ 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(/\/+$/, "")]), () => ( ""));
3235
+ return path.endsWith("/models");
3236
+ }
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" }));
3240
+ res.writeHead(200, { "Content-Type": "application/json" });
3241
+ res.end(JSON.stringify({ object: "list", data }));
3242
+ }
3243
+ function readBody3(req) {
1921
3244
  return new Promise((resolve, reject) => {
1922
3245
  const chunks = [];
1923
3246
  req.on("data", (chunk) => chunks.push(chunk));
@@ -1930,20 +3253,48 @@ function shimAuthHeader(req, routeToken) {
1930
3253
  delete req.headers["x-goog-api-key"];
1931
3254
  delete req.headers["x-api-key"];
1932
3255
  }
1933
- async function handleOutboundRequest(req, res, deps, config, rateLimiter) {
3256
+ async function handleOutboundRequest(req, res, deps, config, rateLimiter, serialQueue, concurrencyGate, redeemLimiter, redeemMutex) {
3257
+ const now = Date.now();
3258
+ const audit = _chunkE3UCVHLPcjs.beginAuditCapture.call(void 0, req, res, now);
3259
+ const billing = _chunkAPYG5QD7cjs.beginBillingCapture.call(void 0, req, res, now);
1934
3260
  const presented = extractPresentedKey(req);
1935
- const verified = await verifyPresentedKey(deps.db, presented);
1936
- if (!verified) {
1937
- writeJsonError(res, 401, "Invalid or missing API key");
3261
+ const verification = await verifyKey(deps.db, presented, now);
3262
+ if (verification.status !== "ok") {
3263
+ writeJsonError(
3264
+ res,
3265
+ 401,
3266
+ verification.status === "expired" ? "API key has expired" : "Invalid or missing API key"
3267
+ );
3268
+ return;
3269
+ }
3270
+ const verified = verification.key;
3271
+ if (audit) audit.keyId = verified.id;
3272
+ if (billing) billing.keyId = verified.id;
3273
+ if (isRedeemRequest(req.method, req.url)) {
3274
+ await handleVoucherRedeem(
3275
+ req,
3276
+ res,
3277
+ deps,
3278
+ _optionalChain([config, 'access', _136 => _136.voucher, 'optionalAccess', _137 => _137.enabled]) === true,
3279
+ _nullishCoalesce(redeemLimiter, () => ( getFallbackRedeemLimiter())),
3280
+ verified.id,
3281
+ _nullishCoalesce(presented, () => ( "")),
3282
+ now,
3283
+ redeemMutex
3284
+ );
1938
3285
  return;
1939
3286
  }
1940
- const decision = rateLimiter.check(verified.id);
3287
+ const decision = rateLimiter.check(verified.id, now, verified.rateLimit);
1941
3288
  if (!decision.allowed) {
1942
3289
  writeJsonError(res, 429, "Rate limit exceeded", {
1943
3290
  "Retry-After": String(decision.retryAfterSeconds)
1944
3291
  });
1945
3292
  return;
1946
3293
  }
3294
+ if (req.method === "GET" && isModelsListRequest(req.url)) {
3295
+ writeChatModelsList(res, config);
3296
+ return;
3297
+ }
1947
3298
  const endpoint = selectEndpoint(req.method, req.url);
1948
3299
  if (!endpoint) {
1949
3300
  writeJsonError(res, 404, `Unsupported: ${req.method} ${req.url}`);
@@ -1954,53 +3305,165 @@ async function handleOutboundRequest(req, res, deps, config, rateLimiter) {
1954
3305
  writeJsonError(res, 503, `endpoint '${endpoint}' is not configured`);
1955
3306
  return;
1956
3307
  }
1957
- const ingressFormat = endpointToIngressFormat(endpoint);
1958
- const rawBody = await readBody2(req);
1959
- let parsedBody = {};
1960
- try {
1961
- parsedBody = rawBody ? JSON.parse(rawBody) : {};
1962
- } catch (e12) {
1963
- writeJsonError(res, 400, "Invalid JSON in request body");
1964
- return;
1965
- }
1966
- if (endpoint === "gemini" && typeof parsedBody["model"] !== "string") {
1967
- const urlModel = extractGeminiModelFromUrl(req.url);
1968
- if (urlModel) parsedBody["model"] = urlModel;
3308
+ if (verified.costLimits && deps.keySpendTracker) {
3309
+ const spend = await deps.keySpendTracker.getSpend(verified.id, now);
3310
+ const quota = checkKeyQuota(verified.costLimits, spend);
3311
+ if (!quota.allowed) {
3312
+ _chunkUIBD2YY5cjs.emitWebhookEvent.call(void 0, {
3313
+ kind: "key.quotaExceeded",
3314
+ at: now,
3315
+ keyId: verified.id,
3316
+ scope: quota.scope,
3317
+ limitUsd: quota.limitUsd,
3318
+ spentUsd: quota.spentUsd
3319
+ });
3320
+ writeCostLimitError(res, quota.scope, quota.limitUsd, quota.spentUsd);
3321
+ return;
3322
+ }
3323
+ for (const warn of _chunk4YINUUKQcjs.computeQuotaWarnings.call(void 0, verified.costLimits, spend)) {
3324
+ if (_chunk4YINUUKQcjs.markQuotaWarnedOnce.call(void 0, verified.id, warn.scope, warn.windowStart)) {
3325
+ _chunkUIBD2YY5cjs.emitWebhookEvent.call(void 0, {
3326
+ kind: "key.quotaWarning",
3327
+ at: now,
3328
+ keyId: verified.id,
3329
+ scope: warn.scope,
3330
+ limitUsd: warn.limitUsd,
3331
+ spentUsd: warn.spentUsd
3332
+ });
3333
+ }
3334
+ }
1969
3335
  }
1970
- const role = detectRequestRole(ingressFormat, parsedBody, {
1971
- backgroundModelIds: endpointConfig.backgroundModelIds
1972
- });
1973
- const resolved = await _chunkG2FUJNA2cjs.resolveRoute.call(void 0, {
1974
- config: endpointConfig,
1975
- role,
1976
- ingressFormat,
1977
- llmConfig: deps.llmConfig,
1978
- // pool-seam (omnicross-daemon-parity-poolseam, design D1/D2(a)): synthesize a
1979
- // STABLE per-verified-key sessionId so the BYO ingress can seed a pool session
1980
- // binding and 429/529/401/403 failover actually fires. Synthesize ONLY when
1981
- // the pool is wired — pool-null embedders/tests keep `route.sessionId === null`
1982
- // (byte-identical to pre-seam). The `outbound:` prefix is namespace-isolated
1983
- // from real chat-session ids; `verified.id` is a small operator-controlled set,
1984
- // so `sessionBindings` stays bounded (one binding per named key, not per
1985
- // request — `sessionBindings` has no TTL).
1986
- sessionId: deps.proxyDeps.apiKeyPool ? `outbound:${verified.id}` : null
1987
- });
1988
- if (!resolved.ok) {
1989
- writeJsonError(res, resolved.error.status, resolved.error.message);
1990
- return;
3336
+ const concurrencyLimit = verified.maxConcurrency;
3337
+ let releaseConcurrency = null;
3338
+ if (typeof concurrencyLimit === "number" && concurrencyLimit > 0) {
3339
+ const cq = _nullishCoalesce(config.concurrencyQueue, () => ( DEFAULT_CONCURRENCY_QUEUE));
3340
+ const acquisition = concurrencyGate.acquire(verified.id, concurrencyLimit, {
3341
+ maxQueueSizeFactor: cq.maxQueueSizeFactor,
3342
+ minQueueSize: cq.minQueueSize,
3343
+ waitTimeoutMs: cq.waitTimeoutMs
3344
+ });
3345
+ const cancelOnClose = () => acquisition.cancel();
3346
+ res.once("close", cancelOnClose);
3347
+ let slot;
3348
+ try {
3349
+ slot = await acquisition.granted;
3350
+ } catch (err) {
3351
+ res.removeListener("close", cancelOnClose);
3352
+ if (isConcurrencyRejection(err)) {
3353
+ writeJsonError(res, 429, "Concurrency limit exceeded", { "Retry-After": "5" });
3354
+ return;
3355
+ }
3356
+ throw err;
3357
+ }
3358
+ res.removeListener("close", cancelOnClose);
3359
+ const release2 = () => slot.release();
3360
+ releaseConcurrency = release2;
3361
+ res.once("close", release2);
1991
3362
  }
1992
- const routeMap = deps.providerProxy.getRouteMap();
1993
- const token = routeMap.addRoute(resolved.route);
1994
3363
  try {
1995
- shimAuthHeader(req, token);
1996
- const replay = makeReplayRequest(req, rawBody);
1997
- await routeRequest(replay, res, routeMap, deps.proxyDeps);
1998
- } catch (err) {
1999
- const message = _chunkSVNDB62Dcjs.serializeError.call(void 0, err);
2000
- console.error("[OutboundApi] dispatch error:", message);
2001
- writeJsonError(res, 502, message);
3364
+ const ingressFormat = _chunkVACWOIREcjs.endpointToIngressFormat.call(void 0, endpoint);
3365
+ const rawBody = await readBody3(req);
3366
+ let parsedBody = {};
3367
+ try {
3368
+ parsedBody = rawBody ? JSON.parse(rawBody) : {};
3369
+ } catch (e18) {
3370
+ writeJsonError(res, 400, "Invalid JSON in request body");
3371
+ return;
3372
+ }
3373
+ if (audit) audit.setRequestBody(rawBody);
3374
+ if (endpoint === "gemini" && typeof parsedBody["model"] !== "string") {
3375
+ const urlModel = extractGeminiModelFromUrl(req.url);
3376
+ if (urlModel) parsedBody["model"] = urlModel;
3377
+ }
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,
3381
+ ingressFormat,
3382
+ llmConfig: deps.llmConfig,
3383
+ sessionId,
3384
+ // Capture the ORIGINAL requested id BEFORE any downstream swap; for
3385
+ // kind-mapped endpoints it selects the kind AND is stamped onto
3386
+ // `route.requestedModel`; for chat it is matched against the list.
3387
+ requestedModel: _chunkVACWOIREcjs.extractRequestedModel.call(void 0, ingressFormat, parsedBody),
3388
+ // Attribution: stamp the verified named-key id onto the route.
3389
+ 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
+ }),
3395
+ ingressFormat,
3396
+ llmConfig: deps.llmConfig,
3397
+ sessionId,
3398
+ // Attribution: stamp the verified named-key id onto the route.
3399
+ apiKeyId: verified.id
3400
+ });
3401
+ if (!resolved.ok) {
3402
+ writeJsonError(res, resolved.error.status, resolved.error.message);
3403
+ return;
3404
+ }
3405
+ if (audit) {
3406
+ audit.model = resolved.route.model;
3407
+ audit.provider = resolved.route.providerId;
3408
+ }
3409
+ if (billing) {
3410
+ billing.model = resolved.route.model;
3411
+ billing.provider = resolved.route.providerId;
3412
+ billing.authMode = resolved.route.authMode;
3413
+ }
3414
+ if (verified.modelRestriction) {
3415
+ const modelDecision = checkModelAllowed(verified.modelRestriction, resolved.route.model);
3416
+ if (!modelDecision.allowed) {
3417
+ writeModelNotAllowedError(res, modelDecision.model, verified.modelRestriction.mode);
3418
+ return;
3419
+ }
3420
+ }
3421
+ let releaseSerial = null;
3422
+ const providerKey = resolved.route.providerId;
3423
+ if (_optionalChain([config, 'access', _138 => _138.userMessageQueue, 'optionalAccess', _139 => _139.enabled]) && providerKey && isUserMessageRequest(endpoint, parsedBody)) {
3424
+ const umq = config.userMessageQueue;
3425
+ try {
3426
+ const serialSlot = await serialQueue.acquire(providerKey, {
3427
+ waitTimeoutMs: umq.waitTimeoutMs,
3428
+ delayMs: umq.delayMs
3429
+ });
3430
+ releaseSerial = () => serialSlot.release();
3431
+ } catch (err) {
3432
+ if (isSerialQueueTimeout(err)) {
3433
+ writeJsonError(res, 503, "User-message serial queue wait timed out");
3434
+ return;
3435
+ }
3436
+ throw err;
3437
+ }
3438
+ }
3439
+ if (releaseSerial) {
3440
+ const original = res.writeHead.bind(res);
3441
+ const releaseOnce = releaseSerial;
3442
+ res.writeHead = ((...args) => {
3443
+ res.writeHead = original;
3444
+ releaseOnce();
3445
+ return original(...args);
3446
+ });
3447
+ }
3448
+ const routeMap = deps.providerProxy.getRouteMap();
3449
+ const token = routeMap.addRoute(resolved.route);
3450
+ try {
3451
+ shimAuthHeader(req, token);
3452
+ const replay = makeReplayRequest(req, rawBody);
3453
+ await routeRequest(replay, res, routeMap, deps.proxyDeps);
3454
+ } catch (err) {
3455
+ const message = _chunkSVNDB62Dcjs.serializeError.call(void 0, err);
3456
+ if (deps.logger) deps.logger.error("[OutboundApi] dispatch error:", message);
3457
+ else console.error("[OutboundApi] dispatch error:", message);
3458
+ _chunkUIBD2YY5cjs.emitWebhookEvent.call(void 0, { kind: "server.error", at: Date.now(), message });
3459
+ if (audit) audit.error = message;
3460
+ writeJsonError(res, 502, message);
3461
+ } finally {
3462
+ routeMap.removeRoute(token);
3463
+ if (releaseSerial) releaseSerial();
3464
+ }
2002
3465
  } finally {
2003
- routeMap.removeRoute(token);
3466
+ if (releaseConcurrency) releaseConcurrency();
2004
3467
  }
2005
3468
  }
2006
3469
  function makeReplayRequest(req, rawBody) {
@@ -2014,65 +3477,50 @@ function makeReplayRequest(req, rawBody) {
2014
3477
  return readable;
2015
3478
  }
2016
3479
 
2017
- // src/outbound-api/outboundRateLimiter.ts
2018
- var DEFAULT_WINDOW_MS = 6e4;
2019
- var DEFAULT_MAX_REQUESTS = 60;
2020
- var OutboundRateLimiter = (_class3 = class {
2021
-
2022
-
2023
- /** apiKeyId → ascending request timestamps within the current window. */
2024
- __init4() {this.hits = /* @__PURE__ */ new Map()}
2025
- constructor(options = {}) {;_class3.prototype.__init4.call(this);
2026
- this.windowMs = _nullishCoalesce(options.windowMs, () => ( DEFAULT_WINDOW_MS));
2027
- this.maxRequests = _nullishCoalesce(options.maxRequests, () => ( DEFAULT_MAX_REQUESTS));
2028
- }
2029
- /**
2030
- * Record a request for `apiKeyId` and decide whether it is allowed. Prunes
2031
- * timestamps older than the window first; when allowed, the request's
2032
- * timestamp is appended.
2033
- */
2034
- check(apiKeyId, now = Date.now()) {
2035
- const cutoff = now - this.windowMs;
2036
- const timestamps = (_nullishCoalesce(this.hits.get(apiKeyId), () => ( []))).filter((ts) => ts > cutoff);
2037
- if (timestamps.length >= this.maxRequests) {
2038
- if (timestamps.length === 0) {
2039
- this.hits.delete(apiKeyId);
2040
- return { allowed: false, retryAfterSeconds: Math.max(1, Math.ceil(this.windowMs / 1e3)) };
2041
- }
2042
- const oldest = timestamps[0];
2043
- const retryAfterMs = Math.max(0, oldest + this.windowMs - now);
2044
- this.hits.set(apiKeyId, timestamps);
2045
- return {
2046
- allowed: false,
2047
- retryAfterSeconds: Math.max(1, Math.ceil(retryAfterMs / 1e3))
2048
- };
2049
- }
2050
- timestamps.push(now);
2051
- this.hits.set(apiKeyId, timestamps);
2052
- return { allowed: true, retryAfterSeconds: 0 };
2053
- }
2054
- /** Drop all recorded state (tests / teardown). */
2055
- reset() {
2056
- this.hits.clear();
2057
- }
2058
- }, _class3);
2059
-
2060
3480
  // src/outbound-api/OutboundApiServer.ts
2061
3481
  var DEFAULT_OUTBOUND_PORT = 8765;
2062
3482
  var LOOPBACK_ADDR = "127.0.0.1";
2063
3483
  var LAN_ADDR = "0.0.0.0";
2064
- var OutboundApiServer = (_class4 = class {
2065
- constructor(deps, onPortChange) {;_class4.prototype.__init5.call(this);_class4.prototype.__init6.call(this);_class4.prototype.__init7.call(this);_class4.prototype.__init8.call(this);_class4.prototype.__init9.call(this);
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
+ 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);
2066
3496
  this.deps = deps;
2067
3497
  this.onPortChange = onPortChange;
2068
3498
  }
2069
3499
 
2070
3500
 
2071
- __init5() {this.server = null}
2072
- __init6() {this.boundPort = 0}
2073
- __init7() {this.boundAddr = LOOPBACK_ADDR}
2074
- __init8() {this.endpoints = []}
2075
- __init9() {this.rateLimiter = new OutboundRateLimiter()}
3501
+ __init12() {this.server = null}
3502
+ __init13() {this.boundPort = 0}
3503
+ __init14() {this.boundAddr = LOOPBACK_ADDR}
3504
+ __init15() {this.endpoints = []}
3505
+
3506
+
3507
+
3508
+ __init16() {this.rateLimiter = new OutboundRateLimiter()}
3509
+ /**
3510
+ * Redeem-attempt limiter (voucher-redemption #9, design D6) — a SEPARATE bucket
3511
+ * from the traffic `rateLimiter`, keyed by the authenticating key id, so
3512
+ * brute-forcing `CC_` codes is throttled (a handful/min) without touching the
3513
+ * per-key request rate. Conservative fixed defaults (10 / 60s).
3514
+ */
3515
+ __init17() {this.redeemLimiter = new OutboundRateLimiter({ maxRequests: 10, windowMs: 6e4 })}
3516
+ /**
3517
+ * Per-key redeem mutex (voucher-redemption #9, MJ1 fix). One instance for the
3518
+ * server's lifetime so concurrent redeem REQUESTS for the same key serialize
3519
+ * (relative grant increments accumulate instead of clobbering a snapshot).
3520
+ */
3521
+ __init18() {this.redeemMutex = new KeyedMutex()}
3522
+ __init19() {this.serialQueue = new UserMessageSerialQueue()}
3523
+ __init20() {this.concurrencyGate = new OutboundConcurrencyGate()}
2076
3524
  /**
2077
3525
  * Apply a config. Restarts the listener ONLY when the bind address or port
2078
3526
  * changes (or when toggling enabled); per-endpoint routing config is updated
@@ -2080,12 +3528,25 @@ var OutboundApiServer = (_class4 = class {
2080
3528
  */
2081
3529
  async applyConfig(input) {
2082
3530
  this.endpoints = input.endpoints;
3531
+ this.userMessageQueue = input.userMessageQueue;
3532
+ this.concurrencyQueue = input.concurrencyQueue;
3533
+ this.voucherConfig = input.voucher;
2083
3534
  const wantAddr = input.networkBinding ? LAN_ADDR : LOOPBACK_ADDR;
2084
3535
  const wantPort = _nullishCoalesce(input.port, () => ( DEFAULT_OUTBOUND_PORT));
2085
3536
  if (!input.enabled) {
2086
3537
  await this.stop();
2087
3538
  return;
2088
3539
  }
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
+ }
2089
3550
  const running = this.server !== null;
2090
3551
  const bindChanged = running && (this.boundAddr !== wantAddr || this.boundPort !== wantPort);
2091
3552
  if (running && !bindChanged) {
@@ -2100,8 +3561,8 @@ var OutboundApiServer = (_class4 = class {
2100
3561
  const actualPort = await this.listen(bindAddr, port);
2101
3562
  this.boundAddr = bindAddr;
2102
3563
  this.boundPort = actualPort;
2103
- if (actualPort !== port) _optionalChain([this, 'access', _86 => _86.onPortChange, 'optionalCall', _87 => _87(actualPort)]);
2104
- console.log(`[OutboundApiServer] Listening on ${bindAddr}:${actualPort}`);
3564
+ if (actualPort !== port) _optionalChain([this, 'access', _140 => _140.onPortChange, 'optionalCall', _141 => _141(actualPort)]);
3565
+ this.logInfo(`[OutboundApiServer] Listening on ${bindAddr}:${actualPort}`);
2105
3566
  return actualPort;
2106
3567
  }
2107
3568
  /** Bind once; on EADDRINUSE retry with an ephemeral port (port 0). */
@@ -2123,7 +3584,7 @@ var OutboundApiServer = (_class4 = class {
2123
3584
  const addr = server.address();
2124
3585
  if (addr && typeof addr === "object") {
2125
3586
  server.removeListener("error", onError);
2126
- server.on("error", (e) => console.error("[OutboundApiServer] server error", _chunkSVNDB62Dcjs.serializeError.call(void 0, e)));
3587
+ server.on("error", (e) => this.logError("[OutboundApiServer] server error", _chunkSVNDB62Dcjs.serializeError.call(void 0, e)));
2127
3588
  this.server = server;
2128
3589
  resolve(addr.port);
2129
3590
  } else {
@@ -2134,21 +3595,58 @@ var OutboundApiServer = (_class4 = class {
2134
3595
  }
2135
3596
  /** Per-request handler. Auth is enforced on EVERY request (incl. loopback). */
2136
3597
  onRequest(req, res) {
3598
+ if (this.deps.healthReportProvider && this.tryServeHealth(req, res)) return;
2137
3599
  handleOutboundRequest(
2138
3600
  req,
2139
3601
  res,
2140
3602
  this.deps,
2141
- { endpoints: this.endpoints },
2142
- this.rateLimiter
3603
+ {
3604
+ endpoints: this.endpoints,
3605
+ userMessageQueue: this.userMessageQueue,
3606
+ concurrencyQueue: this.concurrencyQueue,
3607
+ voucher: this.voucherConfig
3608
+ },
3609
+ this.rateLimiter,
3610
+ this.serialQueue,
3611
+ this.concurrencyGate,
3612
+ this.redeemLimiter,
3613
+ this.redeemMutex
2143
3614
  ).catch((err) => {
2144
3615
  const message = _chunkSVNDB62Dcjs.serializeError.call(void 0, err);
2145
- console.error("[OutboundApiServer] unhandled error:", message);
3616
+ this.logError("[OutboundApiServer] unhandled error:", message);
2146
3617
  if (!res.headersSent) {
2147
3618
  res.writeHead(500, { "Content-Type": "application/json" });
2148
3619
  res.end(JSON.stringify({ error: { type: "outbound_api_error", message } }));
2149
3620
  }
2150
3621
  });
2151
3622
  }
3623
+ /**
3624
+ * Serve `GET|HEAD /health` (+ `/healthz`) from the injected provider, returning
3625
+ * true when it handled the request. 200 when `ok`, else 503; secret-free body.
3626
+ */
3627
+ tryServeHealth(req, res) {
3628
+ const provider = this.deps.healthReportProvider;
3629
+ if (!provider) return false;
3630
+ 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(/\/+$/, "")]) || "/";
3632
+ if (path !== "/health" && path !== "/healthz") return false;
3633
+ const report = provider();
3634
+ res.writeHead(_healthloggingtypes.healthHttpStatus.call(void 0, report.status), { "Content-Type": "application/json" });
3635
+ res.end(req.method === "HEAD" ? void 0 : JSON.stringify(report));
3636
+ return true;
3637
+ }
3638
+ /** Route an info lifecycle line through the injected logger, else `console.log`
3639
+ * (byte-identical legacy fallback when no logger is wired). */
3640
+ logInfo(message) {
3641
+ if (this.deps.logger) this.deps.logger.info(message);
3642
+ else console.log(message);
3643
+ }
3644
+ /** Route an error lifecycle line through the injected logger, else `console.error`. */
3645
+ logError(message, detail) {
3646
+ if (this.deps.logger) this.deps.logger.error(message, detail);
3647
+ else if (detail === void 0) console.error(message);
3648
+ else console.error(message, detail);
3649
+ }
2152
3650
  /** Stop the listener and release the port. */
2153
3651
  async stop() {
2154
3652
  const server = this.server;
@@ -2157,7 +3655,7 @@ var OutboundApiServer = (_class4 = class {
2157
3655
  this.boundPort = 0;
2158
3656
  return new Promise((resolve) => {
2159
3657
  server.close(() => {
2160
- console.log("[OutboundApiServer] Stopped");
3658
+ this.logInfo("[OutboundApiServer] Stopped");
2161
3659
  resolve();
2162
3660
  });
2163
3661
  });
@@ -2189,7 +3687,18 @@ var OutboundApiServer = (_class4 = class {
2189
3687
  lanFormats: lanBase ? formatUrls(lanBase) : null
2190
3688
  };
2191
3689
  }
2192
- }, _class4);
3690
+ /**
3691
+ * Live queue-occupancy snapshot (only active entries). This getter's name +
3692
+ * shape are FROZEN — `omnicross-uqc-daemon` spreads it into its `/status`
3693
+ * response; the existing {@link getStatus} shape is deliberately NOT changed.
3694
+ */
3695
+ getQueueStatus() {
3696
+ return {
3697
+ serial: this.serialQueue.getStatus(),
3698
+ concurrency: this.concurrencyGate.getStatus()
3699
+ };
3700
+ }
3701
+ }, _class11);
2193
3702
  function formatUrls(base) {
2194
3703
  return {
2195
3704
  chat: `${base}/v1/chat/completions`,
@@ -2209,66 +3718,88 @@ function firstLanIPv4() {
2209
3718
  return null;
2210
3719
  }
2211
3720
 
2212
- // src/outbound-api/apiServerConfig.ts
2213
- var OUTBOUND_API_SERVER_CONFIG_KEY = "outboundApiServer.config";
2214
- var ALL_ENDPOINTS = ["chat", "responses", "messages", "gemini"];
2215
- function defaultEndpointConfig(endpoint) {
2216
- return {
2217
- endpoint,
2218
- defaultModel: "",
2219
- backgroundModel: "",
2220
- useSubscription: false
2221
- };
3721
+ // src/outbound-api/keySpendTracker.ts
3722
+ function startOfLocalDay(ts) {
3723
+ const d = new Date(ts);
3724
+ return new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
2222
3725
  }
2223
- function defaultServerConfig() {
2224
- return {
2225
- enabled: false,
2226
- networkBinding: false,
2227
- endpoints: ALL_ENDPOINTS.map(defaultEndpointConfig),
2228
- port: DEFAULT_OUTBOUND_PORT
2229
- };
3726
+ function startOfLocalWeek(ts) {
3727
+ const d = new Date(ts);
3728
+ const day = new Date(d.getFullYear(), d.getMonth(), d.getDate());
3729
+ day.setDate(day.getDate() - day.getDay());
3730
+ return day.getTime();
2230
3731
  }
2231
- function normalizeServerConfig(raw) {
2232
- const base = defaultServerConfig();
2233
- if (!raw) return base;
2234
- const byEndpoint = /* @__PURE__ */ new Map();
2235
- for (const e of _nullishCoalesce(raw.endpoints, () => ( []))) {
2236
- if (e && ALL_ENDPOINTS.includes(e.endpoint)) {
2237
- byEndpoint.set(e.endpoint, {
2238
- endpoint: e.endpoint,
2239
- defaultModel: _nullishCoalesce(e.defaultModel, () => ( "")),
2240
- backgroundModel: _nullishCoalesce(e.backgroundModel, () => ( "")),
2241
- visionModel: e.visionModel,
2242
- useSubscription: e.useSubscription === true,
2243
- backgroundModelIds: e.backgroundModelIds
2244
- });
3732
+ var KeySpendTracker = (_class12 = class {
3733
+ constructor(seeder) {;_class12.prototype.__init21.call(this);
3734
+ this.seeder = seeder;
3735
+ }
3736
+
3737
+ /** apiKeyId live accumulated spend (seeded lazily). */
3738
+ __init21() {this.spend = /* @__PURE__ */ new Map()}
3739
+ /**
3740
+ * Read the key's accumulated spend, seeding from the durable store on a cache
3741
+ * miss and rolling the daily/weekly windows on a hit.
3742
+ */
3743
+ async getSpend(apiKeyId, now) {
3744
+ const existing = this.spend.get(apiKeyId);
3745
+ if (existing) {
3746
+ rollWindows(existing, now);
3747
+ return existing;
2245
3748
  }
3749
+ const seeded = await this.seed(apiKeyId, now);
3750
+ const existingAfterSeed = this.spend.get(apiKeyId);
3751
+ if (existingAfterSeed) {
3752
+ rollWindows(existingAfterSeed, now);
3753
+ return existingAfterSeed;
3754
+ }
3755
+ this.spend.set(apiKeyId, seeded);
3756
+ return seeded;
3757
+ }
3758
+ /**
3759
+ * Increment the aggregate for one recorded request. No-op when the key has not
3760
+ * been seeded yet — a later `getSpend` will lazy-seed from the durable store,
3761
+ * which already includes this record, so it is neither lost nor double-counted.
3762
+ */
3763
+ add(apiKeyId, costUsd, now) {
3764
+ const s = this.spend.get(apiKeyId);
3765
+ if (!s) return;
3766
+ rollWindows(s, now);
3767
+ s.dailyUsd += costUsd;
3768
+ s.weeklyUsd += costUsd;
3769
+ s.totalUsd += costUsd;
3770
+ }
3771
+ /** Drop all cached spend (tests / teardown). */
3772
+ reset() {
3773
+ this.spend.clear();
3774
+ }
3775
+ /**
3776
+ * Derive a fresh spend snapshot for `apiKeyId` from the durable store in a
3777
+ * SINGLE scan (all three windows at once). `endTs` is EXCLUSIVE, so `now + 1`
3778
+ * includes a record stamped at exactly `now`.
3779
+ */
3780
+ async seed(apiKeyId, now) {
3781
+ const dailyWindowStart = startOfLocalDay(now);
3782
+ const weeklyWindowStart = startOfLocalWeek(now);
3783
+ const { totalUsd, dailyUsd, weeklyUsd } = await this.seeder.getSpendByKey({
3784
+ apiKeyId,
3785
+ dayStartTs: dailyWindowStart,
3786
+ weekStartTs: weeklyWindowStart,
3787
+ endTs: now + 1
3788
+ });
3789
+ return { dailyUsd, dailyWindowStart, weeklyUsd, weeklyWindowStart, totalUsd };
3790
+ }
3791
+ }, _class12);
3792
+ function rollWindows(s, now) {
3793
+ const day = startOfLocalDay(now);
3794
+ if (s.dailyWindowStart !== day) {
3795
+ s.dailyUsd = 0;
3796
+ s.dailyWindowStart = day;
3797
+ }
3798
+ const week = startOfLocalWeek(now);
3799
+ if (s.weeklyWindowStart !== week) {
3800
+ s.weeklyUsd = 0;
3801
+ s.weeklyWindowStart = week;
2246
3802
  }
2247
- return {
2248
- enabled: raw.enabled === true,
2249
- networkBinding: raw.networkBinding === true,
2250
- endpoints: ALL_ENDPOINTS.map(
2251
- (ep) => _nullishCoalesce(byEndpoint.get(ep), () => ( defaultEndpointConfig(ep)))
2252
- ),
2253
- port: _nullishCoalesce(raw.port, () => ( base.port))
2254
- };
2255
- }
2256
- async function loadServerConfig(store) {
2257
- const raw = await store.get(
2258
- OUTBOUND_API_SERVER_CONFIG_KEY
2259
- );
2260
- return normalizeServerConfig(raw);
2261
- }
2262
- async function saveServerConfig(store, config) {
2263
- await store.set(OUTBOUND_API_SERVER_CONFIG_KEY, config);
2264
- }
2265
- function mergeServerConfig(current, patch) {
2266
- return normalizeServerConfig({
2267
- enabled: _nullishCoalesce(patch.enabled, () => ( current.enabled)),
2268
- networkBinding: _nullishCoalesce(patch.networkBinding, () => ( current.networkBinding)),
2269
- endpoints: _nullishCoalesce(patch.endpoints, () => ( current.endpoints)),
2270
- port: _nullishCoalesce(patch.port, () => ( current.port))
2271
- });
2272
3803
  }
2273
3804
 
2274
3805
  // src/outbound-api/index.ts
@@ -2304,7 +3835,7 @@ async function callOpenAICompletion(provider, apiKey, options, logger) {
2304
3835
  }
2305
3836
  }
2306
3837
  const apiUrl = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: options.model, stream: false });
2307
- const headers = _chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, apiKey);
3838
+ const headers = _chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey);
2308
3839
  logger.info("Calling OpenAI completion API", { url: apiUrl, model: options.model });
2309
3840
  const response = await fetch(apiUrl, {
2310
3841
  method: "POST",
@@ -2350,7 +3881,7 @@ async function callAnthropicCompletion(provider, apiKey, options, logger) {
2350
3881
  stream: false
2351
3882
  };
2352
3883
  const apiUrl2 = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: options.model, stream: false });
2353
- const headers2 = _chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, apiKey);
3884
+ const headers2 = _chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey);
2354
3885
  logger.info("Calling Anthropic completion API with images", { url: apiUrl2, model: options.model });
2355
3886
  const response2 = await fetch(apiUrl2, {
2356
3887
  method: "POST",
@@ -2372,7 +3903,7 @@ async function callAnthropicCompletion(provider, apiKey, options, logger) {
2372
3903
  message: {
2373
3904
  id: `assistant-${Date.now()}`,
2374
3905
  role: "assistant",
2375
- content: _optionalChain([choice2, 'access', _88 => _88.message, 'optionalAccess', _89 => _89.content]) || "",
3906
+ content: _optionalChain([choice2, 'access', _147 => _147.message, 'optionalAccess', _148 => _148.content]) || "",
2376
3907
  timestamp: Date.now()
2377
3908
  },
2378
3909
  usage: openaiResponse2.usage ? {
@@ -2398,7 +3929,7 @@ async function callAnthropicCompletion(provider, apiKey, options, logger) {
2398
3929
  };
2399
3930
  const anthropicRequest = _chunkSUEGJ75Dcjs.convertOpenAIToAnthropic.call(void 0, openaiRequest, config);
2400
3931
  const apiUrl = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: options.model, stream: false });
2401
- const headers = _chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, apiKey);
3932
+ const headers = _chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey);
2402
3933
  logger.info("Calling Anthropic completion API", { url: apiUrl, model: options.model });
2403
3934
  const response = await fetch(apiUrl, {
2404
3935
  method: "POST",
@@ -2452,7 +3983,7 @@ async function callGeminiCompletion(provider, apiKey, options, logger) {
2452
3983
  request.systemInstruction = systemInstruction;
2453
3984
  }
2454
3985
  const apiUrl = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: options.model, stream: false });
2455
- const headers = _chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, apiKey);
3986
+ const headers = _chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey);
2456
3987
  logger.info("Calling Gemini completion API", { url: apiUrl, model: options.model });
2457
3988
  const response = await fetch(apiUrl, {
2458
3989
  method: "POST",
@@ -2477,7 +4008,7 @@ async function callGeminiCompletion(provider, apiKey, options, logger) {
2477
4008
  const candidate = candidates[0];
2478
4009
  const content = candidate.content;
2479
4010
  let textContent = "";
2480
- if (_optionalChain([content, 'optionalAccess', _90 => _90.parts])) {
4011
+ if (_optionalChain([content, 'optionalAccess', _149 => _149.parts])) {
2481
4012
  for (const part of content.parts) {
2482
4013
  if (part.text) {
2483
4014
  textContent += part.text;
@@ -2523,7 +4054,7 @@ async function callOpenAIResponseCompletion(provider, apiKey, options, logger) {
2523
4054
  }
2524
4055
  }
2525
4056
  const apiUrl = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: options.model, stream: false });
2526
- const headers = _chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, apiKey);
4057
+ const headers = _chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey);
2527
4058
  logger.info("Calling OpenAI Response API", { url: apiUrl, model: options.model });
2528
4059
  const response = await fetch(apiUrl, {
2529
4060
  method: "POST",
@@ -2589,9 +4120,9 @@ async function streamOpenAICompletion(provider, apiKey, options, messageId, call
2589
4120
  }
2590
4121
  }
2591
4122
  const apiUrl = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: options.model, stream: true });
2592
- const headers = _chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, apiKey);
4123
+ const headers = _chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey);
2593
4124
  if (options.nativeSearchAugmentation) {
2594
- _chunkV5KPWNYXcjs.applyAugmentation.call(void 0, request, options.nativeSearchAugmentation);
4125
+ _chunkJMJBSACDcjs.applyAugmentation.call(void 0, request, options.nativeSearchAugmentation);
2595
4126
  }
2596
4127
  logger.info("Streaming OpenAI completion request", {
2597
4128
  url: apiUrl,
@@ -2610,7 +4141,7 @@ async function streamOpenAICompletion(provider, apiKey, options, messageId, call
2610
4141
  });
2611
4142
  if (!response.ok) {
2612
4143
  const errorText = await response.text();
2613
- _optionalChain([callbacks, 'access', _91 => _91.onError, 'optionalCall', _92 => _92(`API error (${response.status}): ${errorText}`)]);
4144
+ _optionalChain([callbacks, 'access', _150 => _150.onError, 'optionalCall', _151 => _151(`API error (${response.status}): ${errorText}`)]);
2614
4145
  return;
2615
4146
  }
2616
4147
  const result = await _chunkHQP3K7PUcjs.streamSSEResponse.call(void 0, response, "openai", {
@@ -2620,7 +4151,7 @@ async function streamOpenAICompletion(provider, apiKey, options, messageId, call
2620
4151
  onVideo: callbacks.onVideo,
2621
4152
  onError: callbacks.onError
2622
4153
  });
2623
- _optionalChain([callbacks, 'access', _93 => _93.onDone, 'optionalCall', _94 => _94(
4154
+ _optionalChain([callbacks, 'access', _152 => _152.onDone, 'optionalCall', _153 => _153(
2624
4155
  {
2625
4156
  id: messageId,
2626
4157
  role: "assistant",
@@ -2685,14 +4216,14 @@ async function streamAnthropicCompletion(provider, apiKey, options, messageId, c
2685
4216
  }
2686
4217
  }
2687
4218
  const apiUrl = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: options.model, stream: true });
2688
- const headers = _chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, apiKey);
4219
+ const headers = _chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey);
2689
4220
  if (options.nativeSearchAugmentation) {
2690
- _chunkV5KPWNYXcjs.applyAugmentation.call(void 0, anthropicRequest, options.nativeSearchAugmentation);
4221
+ _chunkJMJBSACDcjs.applyAugmentation.call(void 0, anthropicRequest, options.nativeSearchAugmentation);
2691
4222
  }
2692
4223
  logger.info("Streaming Anthropic completion request", {
2693
4224
  url: apiUrl,
2694
4225
  model: anthropicRequest.model,
2695
- messagesCount: _optionalChain([anthropicRequest, 'access', _95 => _95.messages, 'optionalAccess', _96 => _96.length]),
4226
+ messagesCount: _optionalChain([anthropicRequest, 'access', _154 => _154.messages, 'optionalAccess', _155 => _155.length]),
2696
4227
  max_tokens: anthropicRequest.max_tokens,
2697
4228
  temperature: anthropicRequest.temperature,
2698
4229
  stream: anthropicRequest.stream,
@@ -2709,7 +4240,7 @@ async function streamAnthropicCompletion(provider, apiKey, options, messageId, c
2709
4240
  if (!response.ok) {
2710
4241
  const errorText = await response.text();
2711
4242
  logger.error("Anthropic API error", void 0, { status: response.status, errorText });
2712
- _optionalChain([callbacks, 'access', _97 => _97.onError, 'optionalCall', _98 => _98(`API error (${response.status}): ${errorText}`)]);
4243
+ _optionalChain([callbacks, 'access', _156 => _156.onError, 'optionalCall', _157 => _157(`API error (${response.status}): ${errorText}`)]);
2713
4244
  return;
2714
4245
  }
2715
4246
  const result = await _chunkHQP3K7PUcjs.streamSSEResponse.call(void 0, response, "anthropic", {
@@ -2720,10 +4251,10 @@ async function streamAnthropicCompletion(provider, apiKey, options, messageId, c
2720
4251
  });
2721
4252
  logger.info("Anthropic stream complete", {
2722
4253
  contentLength: result.content.length,
2723
- reasoningLength: _optionalChain([result, 'access', _99 => _99.reasoning, 'optionalAccess', _100 => _100.length]) || 0,
4254
+ reasoningLength: _optionalChain([result, 'access', _158 => _158.reasoning, 'optionalAccess', _159 => _159.length]) || 0,
2724
4255
  blocksCount: result.blocks.length
2725
4256
  });
2726
- _optionalChain([callbacks, 'access', _101 => _101.onDone, 'optionalCall', _102 => _102(
4257
+ _optionalChain([callbacks, 'access', _160 => _160.onDone, 'optionalCall', _161 => _161(
2727
4258
  {
2728
4259
  id: messageId,
2729
4260
  role: "assistant",
@@ -2757,9 +4288,9 @@ async function streamGeminiCompletion(provider, apiKey, options, messageId, call
2757
4288
  request.systemInstruction = systemInstruction;
2758
4289
  }
2759
4290
  const apiUrl = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: options.model, stream: true });
2760
- const headers = _chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, apiKey);
4291
+ const headers = _chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey);
2761
4292
  if (options.nativeSearchAugmentation) {
2762
- _chunkV5KPWNYXcjs.applyAugmentation.call(void 0, request, options.nativeSearchAugmentation);
4293
+ _chunkJMJBSACDcjs.applyAugmentation.call(void 0, request, options.nativeSearchAugmentation);
2763
4294
  }
2764
4295
  logger.info("Streaming Gemini completion request", {
2765
4296
  url: apiUrl,
@@ -2779,7 +4310,7 @@ async function streamGeminiCompletion(provider, apiKey, options, messageId, call
2779
4310
  if (!response.ok) {
2780
4311
  const errorText = await response.text();
2781
4312
  logger.error("Gemini API error", void 0, { status: response.status, errorText });
2782
- _optionalChain([callbacks, 'access', _103 => _103.onError, 'optionalCall', _104 => _104(`API error (${response.status}): ${errorText}`)]);
4313
+ _optionalChain([callbacks, 'access', _162 => _162.onError, 'optionalCall', _163 => _163(`API error (${response.status}): ${errorText}`)]);
2783
4314
  return;
2784
4315
  }
2785
4316
  const result = await _chunkHQP3K7PUcjs.streamSSEResponse.call(void 0, response, "gemini", {
@@ -2788,7 +4319,7 @@ async function streamGeminiCompletion(provider, apiKey, options, messageId, call
2788
4319
  onError: callbacks.onError
2789
4320
  });
2790
4321
  logger.info("Gemini stream complete", { contentLength: result.content.length });
2791
- _optionalChain([callbacks, 'access', _105 => _105.onDone, 'optionalCall', _106 => _106(
4322
+ _optionalChain([callbacks, 'access', _164 => _164.onDone, 'optionalCall', _165 => _165(
2792
4323
  {
2793
4324
  id: messageId,
2794
4325
  role: "assistant",
@@ -2823,7 +4354,7 @@ async function streamOpenAIResponseCompletion(provider, apiKey, options, message
2823
4354
  }
2824
4355
  }
2825
4356
  const apiUrl = _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: options.model, stream: true });
2826
- const headers = _chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, apiKey);
4357
+ const headers = _chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey);
2827
4358
  logger.info("Streaming OpenAI Response API request", {
2828
4359
  url: apiUrl,
2829
4360
  providerId: options.providerId,
@@ -2840,7 +4371,7 @@ async function streamOpenAIResponseCompletion(provider, apiKey, options, message
2840
4371
  });
2841
4372
  if (!response.ok) {
2842
4373
  const errorText = await response.text();
2843
- _optionalChain([callbacks, 'access', _107 => _107.onError, 'optionalCall', _108 => _108(`API error (${response.status}): ${errorText}`)]);
4374
+ _optionalChain([callbacks, 'access', _166 => _166.onError, 'optionalCall', _167 => _167(`API error (${response.status}): ${errorText}`)]);
2844
4375
  return;
2845
4376
  }
2846
4377
  const result = await _chunkHQP3K7PUcjs.streamSSEResponse.call(void 0, response, "openai-response", {
@@ -2849,7 +4380,7 @@ async function streamOpenAIResponseCompletion(provider, apiKey, options, message
2849
4380
  onError: callbacks.onError
2850
4381
  });
2851
4382
  logger.info("OpenAI Response API stream complete", { contentLength: result.content.length });
2852
- _optionalChain([callbacks, 'access', _109 => _109.onDone, 'optionalCall', _110 => _110(
4383
+ _optionalChain([callbacks, 'access', _168 => _168.onDone, 'optionalCall', _169 => _169(
2853
4384
  {
2854
4385
  id: messageId,
2855
4386
  role: "assistant",
@@ -2877,7 +4408,7 @@ async function resolveEffectiveMaxTokens(llmConfig, getProvider, logger, provide
2877
4408
  }
2878
4409
  try {
2879
4410
  const globalParams = await llmConfig.getGlobalModelParameters();
2880
- if (_optionalChain([globalParams, 'optionalAccess', _111 => _111.maxTokens, 'optionalAccess', _112 => _112.enabled]) && globalParams.maxTokens.value > 0) {
4411
+ if (_optionalChain([globalParams, 'optionalAccess', _170 => _170.maxTokens, 'optionalAccess', _171 => _171.enabled]) && globalParams.maxTokens.value > 0) {
2881
4412
  logger.debug("Using global maxTokens", { maxTokens: globalParams.maxTokens.value });
2882
4413
  return globalParams.maxTokens.value;
2883
4414
  }
@@ -2887,8 +4418,8 @@ async function resolveEffectiveMaxTokens(llmConfig, getProvider, logger, provide
2887
4418
  const MAX_TOKENS_CAP = 131072;
2888
4419
  const provider = await getProvider(providerId);
2889
4420
  if (provider) {
2890
- const modelConfig = _optionalChain([provider, 'access', _113 => _113.modelConfigs, 'optionalAccess', _114 => _114.find, 'call', _115 => _115((m) => m.id === modelId)]);
2891
- if (_optionalChain([modelConfig, 'optionalAccess', _116 => _116.maxTokens]) && modelConfig.maxTokens > 0) {
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) {
2892
4423
  const cappedMaxTokens = Math.min(modelConfig.maxTokens, MAX_TOKENS_CAP);
2893
4424
  logger.debug("Using model config maxTokens", {
2894
4425
  maxTokens: modelConfig.maxTokens,
@@ -2898,8 +4429,8 @@ async function resolveEffectiveMaxTokens(llmConfig, getProvider, logger, provide
2898
4429
  }
2899
4430
  if (provider.modelGroups) {
2900
4431
  for (const group of provider.modelGroups) {
2901
- const model = _optionalChain([group, 'access', _117 => _117.models, 'optionalAccess', _118 => _118.find, 'call', _119 => _119((m) => m.id === modelId)]);
2902
- if (_optionalChain([model, 'optionalAccess', _120 => _120.maxTokens]) && model.maxTokens > 0) {
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) {
2903
4434
  const cappedMaxTokens = Math.min(model.maxTokens, MAX_TOKENS_CAP);
2904
4435
  logger.debug("Using modelGroup model maxTokens", {
2905
4436
  maxTokens: model.maxTokens,
@@ -2944,7 +4475,7 @@ async function resolveThinkingBudget(getProvider, logger, providerId, modelId, m
2944
4475
  }
2945
4476
  const thinkingBudget = _thinkingconfig.calculateThinkingBudget.call(void 0, modelId, thinkLevel, maxTokens);
2946
4477
  const provider = await getProvider(providerId);
2947
- const providerName = _optionalChain([provider, 'optionalAccess', _121 => _121.name, 'optionalAccess', _122 => _122.toLowerCase, 'call', _123 => _123()]) || "";
4478
+ const providerName = _optionalChain([provider, 'optionalAccess', _180 => _180.name, 'optionalAccess', _181 => _181.toLowerCase, 'call', _182 => _182()]) || "";
2948
4479
  const apiFormat = provider ? _chunkA2YMUCBTcjs.resolveApiFormat.call(void 0, provider) : "openai";
2949
4480
  if (apiFormat === "anthropic" || providerName === "anthropic" || providerName.includes("claude")) {
2950
4481
  const thinkingConfig = _thinkingconfig.buildAnthropicThinking.call(void 0, modelId, thinkLevel, maxTokens);
@@ -2981,7 +4512,7 @@ function logToolFormat(tools, logger) {
2981
4512
  tools: openaiTools.map((t) => t.function.name),
2982
4513
  firstTool: {
2983
4514
  name: firstTool.function.name,
2984
- description: _optionalChain([firstTool, 'access', _124 => _124.function, 'access', _125 => _125.description, 'optionalAccess', _126 => _126.slice, 'call', _127 => _127(0, 100)]),
4515
+ description: _optionalChain([firstTool, 'access', _183 => _183.function, 'access', _184 => _184.description, 'optionalAccess', _185 => _185.slice, 'call', _186 => _186(0, 100)]),
2985
4516
  parameters: firstTool.function.parameters
2986
4517
  }
2987
4518
  });
@@ -2992,7 +4523,7 @@ function logToolFormat(tools, logger) {
2992
4523
  tools: anthropicTools.map((t) => t.name),
2993
4524
  firstTool: {
2994
4525
  name: firstTool.name,
2995
- description: _optionalChain([firstTool, 'access', _128 => _128.description, 'optionalAccess', _129 => _129.slice, 'call', _130 => _130(0, 100)]),
4526
+ description: _optionalChain([firstTool, 'access', _187 => _187.description, 'optionalAccess', _188 => _188.slice, 'call', _189 => _189(0, 100)]),
2996
4527
  input_schema: firstTool.input_schema
2997
4528
  }
2998
4529
  });
@@ -3003,9 +4534,9 @@ function logToolFormat(tools, logger) {
3003
4534
  count: allDeclarations.length,
3004
4535
  tools: allDeclarations.map((t) => t.name),
3005
4536
  firstTool: {
3006
- name: _optionalChain([allDeclarations, 'access', _131 => _131[0], 'optionalAccess', _132 => _132.name]),
3007
- description: _optionalChain([allDeclarations, 'access', _133 => _133[0], 'optionalAccess', _134 => _134.description, 'optionalAccess', _135 => _135.slice, 'call', _136 => _136(0, 100)]),
3008
- parameters: _optionalChain([allDeclarations, 'access', _137 => _137[0], 'optionalAccess', _138 => _138.parameters])
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])
3009
4540
  }
3010
4541
  });
3011
4542
  }
@@ -3064,7 +4595,7 @@ function buildToolRequest(apiFormat, conversationMessages, actualModel, options,
3064
4595
  function extractDeltaContent(rawJson, apiFormat) {
3065
4596
  const json = rawJson;
3066
4597
  if (apiFormat === "google") {
3067
- const parts = _optionalChain([json, 'access', _139 => _139.candidates, 'optionalAccess', _140 => _140[0], 'optionalAccess', _141 => _141.content, 'optionalAccess', _142 => _142.parts]) || [];
4598
+ const parts = _optionalChain([json, 'access', _198 => _198.candidates, 'optionalAccess', _199 => _199[0], 'optionalAccess', _200 => _200.content, 'optionalAccess', _201 => _201.parts]) || [];
3068
4599
  let text = "";
3069
4600
  for (const part of parts) {
3070
4601
  if (part.thought === true) continue;
@@ -3072,15 +4603,15 @@ function extractDeltaContent(rawJson, apiFormat) {
3072
4603
  }
3073
4604
  return text;
3074
4605
  } else if (apiFormat === "anthropic") {
3075
- return _optionalChain([json, 'access', _143 => _143.delta, 'optionalAccess', _144 => _144.text]) || "";
4606
+ return _optionalChain([json, 'access', _202 => _202.delta, 'optionalAccess', _203 => _203.text]) || "";
3076
4607
  } else {
3077
- return _optionalChain([json, 'access', _145 => _145.choices, 'optionalAccess', _146 => _146[0], 'optionalAccess', _147 => _147.delta, 'optionalAccess', _148 => _148.content]) || "";
4608
+ return _optionalChain([json, 'access', _204 => _204.choices, 'optionalAccess', _205 => _205[0], 'optionalAccess', _206 => _206.delta, 'optionalAccess', _207 => _207.content]) || "";
3078
4609
  }
3079
4610
  }
3080
4611
  function extractDeltaReasoning(rawJson, apiFormat) {
3081
4612
  const json = rawJson;
3082
4613
  if (apiFormat === "google") {
3083
- const parts = _optionalChain([json, 'access', _149 => _149.candidates, 'optionalAccess', _150 => _150[0], 'optionalAccess', _151 => _151.content, 'optionalAccess', _152 => _152.parts]) || [];
4614
+ const parts = _optionalChain([json, 'access', _208 => _208.candidates, 'optionalAccess', _209 => _209[0], 'optionalAccess', _210 => _210.content, 'optionalAccess', _211 => _211.parts]) || [];
3084
4615
  let reasoning = "";
3085
4616
  for (const part of parts) {
3086
4617
  if (part.thought === true && part.text) reasoning += part.text;
@@ -3089,14 +4620,14 @@ function extractDeltaReasoning(rawJson, apiFormat) {
3089
4620
  } else if (apiFormat === "anthropic") {
3090
4621
  return "";
3091
4622
  } else {
3092
- const delta = _optionalChain([json, 'access', _153 => _153.choices, 'optionalAccess', _154 => _154[0], 'optionalAccess', _155 => _155.delta]);
3093
- return (_optionalChain([delta, 'optionalAccess', _156 => _156.thinking, 'optionalAccess', _157 => _157.content]) || "") + (_optionalChain([delta, 'optionalAccess', _158 => _158.reasoning_content]) || "");
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]) || "");
3094
4625
  }
3095
4626
  }
3096
4627
  function extractToolCalls(rawJson, apiFormat, toolCalls, callbacks, logger, pendingOpenAIToolCalls) {
3097
4628
  const json = rawJson;
3098
4629
  if (apiFormat === "google") {
3099
- const parts = _optionalChain([json, 'access', _159 => _159.candidates, 'optionalAccess', _160 => _160[0], 'optionalAccess', _161 => _161.content, 'optionalAccess', _162 => _162.parts]) || [];
4630
+ const parts = _optionalChain([json, 'access', _218 => _218.candidates, 'optionalAccess', _219 => _219[0], 'optionalAccess', _220 => _220.content, 'optionalAccess', _221 => _221.parts]) || [];
3100
4631
  for (const part of parts) {
3101
4632
  if (part.functionCall) {
3102
4633
  logger.info("Function call detected", { functionCall: part.functionCall });
@@ -3106,13 +4637,13 @@ function extractToolCalls(rawJson, apiFormat, toolCalls, callbacks, logger, pend
3106
4637
  args: part.functionCall.args || {}
3107
4638
  };
3108
4639
  toolCalls.push(toolCall);
3109
- _optionalChain([callbacks, 'access', _163 => _163.onToolCall, 'optionalCall', _164 => _164(toolCall)]);
4640
+ _optionalChain([callbacks, 'access', _222 => _222.onToolCall, 'optionalCall', _223 => _223(toolCall)]);
3110
4641
  logger.info("Tool called", { toolName: toolCall.name });
3111
4642
  }
3112
4643
  }
3113
4644
  } else if (apiFormat !== "anthropic") {
3114
- const delta = _optionalChain([json, 'access', _165 => _165.choices, 'optionalAccess', _166 => _166[0], 'optionalAccess', _167 => _167.delta]);
3115
- if (_optionalChain([delta, 'optionalAccess', _168 => _168.tool_calls]) && pendingOpenAIToolCalls) {
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) {
3116
4647
  for (const tc of delta.tool_calls) {
3117
4648
  const index = _nullishCoalesce(tc.index, () => ( 0));
3118
4649
  let pending = pendingOpenAIToolCalls.get(index);
@@ -3121,8 +4652,8 @@ function extractToolCalls(rawJson, apiFormat, toolCalls, callbacks, logger, pend
3121
4652
  pendingOpenAIToolCalls.set(index, pending);
3122
4653
  }
3123
4654
  if (tc.id) pending.id = tc.id;
3124
- if (_optionalChain([tc, 'access', _169 => _169.function, 'optionalAccess', _170 => _170.name])) pending.name += tc.function.name;
3125
- if (_optionalChain([tc, 'access', _171 => _171.function, 'optionalAccess', _172 => _172.arguments])) pending.arguments += tc.function.arguments;
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;
3126
4657
  }
3127
4658
  }
3128
4659
  }
@@ -3137,7 +4668,7 @@ function finalizeOpenAIToolCalls(pendingOpenAIToolCalls, toolCalls, callbacks, l
3137
4668
  args: JSON.parse(pending.arguments || "{}")
3138
4669
  };
3139
4670
  toolCalls.push(toolCall);
3140
- _optionalChain([callbacks, 'access', _173 => _173.onToolCall, 'optionalCall', _174 => _174(toolCall)]);
4671
+ _optionalChain([callbacks, 'access', _232 => _232.onToolCall, 'optionalCall', _233 => _233(toolCall)]);
3141
4672
  logger.info("Tool called (OpenAI)", { toolName: toolCall.name, args: toolCall.args });
3142
4673
  } catch (e) {
3143
4674
  logger.error("Failed to parse OpenAI tool call arguments", e instanceof Error ? e : void 0, {
@@ -3151,38 +4682,38 @@ function finalizeOpenAIToolCalls(pendingOpenAIToolCalls, toolCalls, callbacks, l
3151
4682
  function parseStreamChunk(rawJson, apiFormat, callbacks, logger) {
3152
4683
  const json = rawJson;
3153
4684
  if (apiFormat === "google") {
3154
- const candidate = _optionalChain([json, 'access', _175 => _175.candidates, 'optionalAccess', _176 => _176[0]]);
4685
+ const candidate = _optionalChain([json, 'access', _234 => _234.candidates, 'optionalAccess', _235 => _235[0]]);
3155
4686
  if (!candidate) {
3156
4687
  logger.warn("No candidate found in Gemini response");
3157
4688
  return;
3158
4689
  }
3159
- const parts = _optionalChain([candidate, 'access', _177 => _177.content, 'optionalAccess', _178 => _178.parts]) || [];
4690
+ const parts = _optionalChain([candidate, 'access', _236 => _236.content, 'optionalAccess', _237 => _237.parts]) || [];
3160
4691
  for (const part of parts) {
3161
4692
  if (part.thought === true && part.text) {
3162
- _optionalChain([callbacks, 'access', _179 => _179.onReasoning, 'optionalCall', _180 => _180(part.text)]);
4693
+ _optionalChain([callbacks, 'access', _238 => _238.onReasoning, 'optionalCall', _239 => _239(part.text)]);
3163
4694
  continue;
3164
4695
  } else if (part.thoughtSignature && !part.thought) {
3165
4696
  logger.debug("Gemini returned thoughtSignature without thought content");
3166
4697
  }
3167
4698
  if (part.text) {
3168
- _optionalChain([callbacks, 'access', _181 => _181.onDelta, 'optionalCall', _182 => _182(part.text)]);
4699
+ _optionalChain([callbacks, 'access', _240 => _240.onDelta, 'optionalCall', _241 => _241(part.text)]);
3169
4700
  }
3170
4701
  }
3171
4702
  } else if (apiFormat === "anthropic") {
3172
4703
  const delta = json.delta;
3173
- if (_optionalChain([delta, 'optionalAccess', _183 => _183.text])) {
3174
- _optionalChain([callbacks, 'access', _184 => _184.onDelta, 'optionalCall', _185 => _185(delta.text)]);
4704
+ if (_optionalChain([delta, 'optionalAccess', _242 => _242.text])) {
4705
+ _optionalChain([callbacks, 'access', _243 => _243.onDelta, 'optionalCall', _244 => _244(delta.text)]);
3175
4706
  }
3176
4707
  } else {
3177
- const delta = _optionalChain([json, 'access', _186 => _186.choices, 'optionalAccess', _187 => _187[0], 'optionalAccess', _188 => _188.delta]);
3178
- if (_optionalChain([delta, 'optionalAccess', _189 => _189.content])) {
3179
- _optionalChain([callbacks, 'access', _190 => _190.onDelta, 'optionalCall', _191 => _191(delta.content)]);
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)]);
3180
4711
  }
3181
- if (_optionalChain([delta, 'optionalAccess', _192 => _192.thinking, 'optionalAccess', _193 => _193.content])) {
3182
- _optionalChain([callbacks, 'access', _194 => _194.onReasoning, 'optionalCall', _195 => _195(delta.thinking.content)]);
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)]);
3183
4714
  }
3184
- if (_optionalChain([delta, 'optionalAccess', _196 => _196.reasoning_content])) {
3185
- _optionalChain([callbacks, 'access', _197 => _197.onReasoning, 'optionalCall', _198 => _198(delta.reasoning_content)]);
4715
+ if (_optionalChain([delta, 'optionalAccess', _255 => _255.reasoning_content])) {
4716
+ _optionalChain([callbacks, 'access', _256 => _256.onReasoning, 'optionalCall', _257 => _257(delta.reasoning_content)]);
3186
4717
  }
3187
4718
  }
3188
4719
  }
@@ -3195,7 +4726,7 @@ function buildIterationBlocks(iteration, content, reasoning, blocks, callbacks)
3195
4726
  content: reasoning
3196
4727
  };
3197
4728
  blocks.push(thinkingBlock);
3198
- _optionalChain([callbacks, 'access', _199 => _199.onBlock, 'optionalCall', _200 => _200(thinkingBlock)]);
4729
+ _optionalChain([callbacks, 'access', _258 => _258.onBlock, 'optionalCall', _259 => _259(thinkingBlock)]);
3199
4730
  }
3200
4731
  if (content && content.trim()) {
3201
4732
  const textBlock = {
@@ -3204,7 +4735,7 @@ function buildIterationBlocks(iteration, content, reasoning, blocks, callbacks)
3204
4735
  content
3205
4736
  };
3206
4737
  blocks.push(textBlock);
3207
- _optionalChain([callbacks, 'access', _201 => _201.onBlock, 'optionalCall', _202 => _202(textBlock)]);
4738
+ _optionalChain([callbacks, 'access', _260 => _260.onBlock, 'optionalCall', _261 => _261(textBlock)]);
3208
4739
  }
3209
4740
  }
3210
4741
  async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbacks, logger, builtinExecutor) {
@@ -3219,7 +4750,7 @@ async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbac
3219
4750
  status: "running"
3220
4751
  };
3221
4752
  blocks.push(toolUseBlock);
3222
- _optionalChain([callbacks, 'access', _203 => _203.onBlock, 'optionalCall', _204 => _204(toolUseBlock)]);
4753
+ _optionalChain([callbacks, 'access', _262 => _262.onBlock, 'optionalCall', _263 => _263(toolUseBlock)]);
3223
4754
  try {
3224
4755
  logger.info("Executing tool", { toolName: toolCall.name });
3225
4756
  const mcpTool = mcpTools.find((t) => t.id === toolCall.name);
@@ -3242,8 +4773,8 @@ async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbac
3242
4773
  result = { isError: true, content: [{ type: "text", text: "MCP service not available" }] };
3243
4774
  }
3244
4775
  logger.info("Tool result received", { result });
3245
- _optionalChain([callbacks, 'access', _205 => _205.onToolResult, 'optionalCall', _206 => _206(toolCall.id, result)]);
3246
- const resultText = _optionalChain([result, 'access', _207 => _207.content, 'optionalAccess', _208 => _208[0], 'optionalAccess', _209 => _209.text]) || JSON.stringify(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);
3247
4778
  const toolResultBlock = {
3248
4779
  id: `${toolCall.id}_result`,
3249
4780
  type: "tool_result",
@@ -3253,11 +4784,11 @@ async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbac
3253
4784
  isError: result.isError
3254
4785
  };
3255
4786
  blocks.push(toolResultBlock);
3256
- _optionalChain([callbacks, 'access', _210 => _210.onBlock, 'optionalCall', _211 => _211(toolResultBlock)]);
4787
+ _optionalChain([callbacks, 'access', _269 => _269.onBlock, 'optionalCall', _270 => _270(toolResultBlock)]);
3257
4788
  const toolUseBlockRef = blocks.find((b) => b.id === `${toolCall.id}_use`);
3258
4789
  if (toolUseBlockRef && toolUseBlockRef.type === "tool_use") {
3259
4790
  toolUseBlockRef.status = result.isError ? "error" : "completed";
3260
- _optionalChain([callbacks, 'access', _212 => _212.onBlock, 'optionalCall', _213 => _213({ ...toolUseBlockRef })]);
4791
+ _optionalChain([callbacks, 'access', _271 => _271.onBlock, 'optionalCall', _272 => _272({ ...toolUseBlockRef })]);
3261
4792
  }
3262
4793
  toolResults.push({ toolCall, result });
3263
4794
  } catch (error) {
@@ -3267,7 +4798,7 @@ async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbac
3267
4798
  isError: true,
3268
4799
  content: [{ type: "text", text: `Error: ${errorMessage}` }]
3269
4800
  };
3270
- _optionalChain([callbacks, 'access', _214 => _214.onToolResult, 'optionalCall', _215 => _215(toolCall.id, errorResult)]);
4801
+ _optionalChain([callbacks, 'access', _273 => _273.onToolResult, 'optionalCall', _274 => _274(toolCall.id, errorResult)]);
3271
4802
  const errorToolResultBlock = {
3272
4803
  id: `${toolCall.id}_result`,
3273
4804
  type: "tool_result",
@@ -3277,11 +4808,11 @@ async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbac
3277
4808
  isError: true
3278
4809
  };
3279
4810
  blocks.push(errorToolResultBlock);
3280
- _optionalChain([callbacks, 'access', _216 => _216.onBlock, 'optionalCall', _217 => _217(errorToolResultBlock)]);
4811
+ _optionalChain([callbacks, 'access', _275 => _275.onBlock, 'optionalCall', _276 => _276(errorToolResultBlock)]);
3281
4812
  const errorToolUseBlockRef = blocks.find((b) => b.id === `${toolCall.id}_use`);
3282
4813
  if (errorToolUseBlockRef && errorToolUseBlockRef.type === "tool_use") {
3283
4814
  errorToolUseBlockRef.status = "error";
3284
- _optionalChain([callbacks, 'access', _218 => _218.onBlock, 'optionalCall', _219 => _219({ ...errorToolUseBlockRef })]);
4815
+ _optionalChain([callbacks, 'access', _277 => _277.onBlock, 'optionalCall', _278 => _278({ ...errorToolUseBlockRef })]);
3285
4816
  }
3286
4817
  toolResults.push({ toolCall, result: errorResult });
3287
4818
  }
@@ -3291,7 +4822,7 @@ async function executeToolCalls(toolCalls, mcpTools, mcpService, blocks, callbac
3291
4822
  function mapToolArguments(args, mcpTool, logger) {
3292
4823
  const mappedArgs = { ...args };
3293
4824
  const toolSchema = mcpTool.inputSchema;
3294
- if (_optionalChain([toolSchema, 'optionalAccess', _220 => _220.properties])) {
4825
+ if (_optionalChain([toolSchema, 'optionalAccess', _279 => _279.properties])) {
3295
4826
  const expectedParams = Object.keys(toolSchema.properties);
3296
4827
  const paramMappings = {
3297
4828
  "search_query": ["query", "q", "searchQuery", "search"],
@@ -3325,25 +4856,25 @@ async function streamWithTools(options, callbacks, mcpService, llmConfig, getPro
3325
4856
  options.providerId,
3326
4857
  options.model
3327
4858
  );
3328
- const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _221 => _221.actualProviderId]) || options.providerId;
3329
- const actualModel = _optionalChain([routedInfo, 'optionalAccess', _222 => _222.actualModelId]) || options.model;
4859
+ const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _280 => _280.actualProviderId]) || options.providerId;
4860
+ const actualModel = _optionalChain([routedInfo, 'optionalAccess', _281 => _281.actualModelId]) || options.model;
3330
4861
  const provider = await getProvider(actualProviderId);
3331
4862
  if (!provider) {
3332
- _optionalChain([callbacks, 'access', _223 => _223.onError, 'optionalCall', _224 => _224(`Provider not found: ${actualProviderId}`)]);
4863
+ _optionalChain([callbacks, 'access', _282 => _282.onError, 'optionalCall', _283 => _283(`Provider not found: ${actualProviderId}`)]);
3333
4864
  return;
3334
4865
  }
3335
4866
  if (!provider.enabled) {
3336
- _optionalChain([callbacks, 'access', _225 => _225.onError, 'optionalCall', _226 => _226(`Provider is disabled: ${provider.name}`)]);
4867
+ _optionalChain([callbacks, 'access', _284 => _284.onError, 'optionalCall', _285 => _285(`Provider is disabled: ${provider.name}`)]);
3337
4868
  return;
3338
4869
  }
3339
4870
  const { apiKey: effectiveKey } = _chunkA2YMUCBTcjs.resolveProviderEndpoint.call(void 0, provider);
3340
4871
  const apiKey = resolveApiKey2(effectiveKey);
3341
4872
  if (!apiKey) {
3342
- _optionalChain([callbacks, 'access', _227 => _227.onError, 'optionalCall', _228 => _228("API key not configured")]);
4873
+ _optionalChain([callbacks, 'access', _286 => _286.onError, 'optionalCall', _287 => _287("API key not configured")]);
3343
4874
  return;
3344
4875
  }
3345
4876
  const messageId = `msg_${Date.now()}_${Math.random().toString(36).slice(2)}`;
3346
- _optionalChain([callbacks, 'access', _229 => _229.onStart, 'optionalCall', _230 => _230(messageId)]);
4877
+ _optionalChain([callbacks, 'access', _288 => _288.onStart, 'optionalCall', _289 => _289(messageId)]);
3347
4878
  const globalParams = await llmConfig.getGlobalModelParameters();
3348
4879
  const MAX_ITERATIONS = _nullishCoalesce(globalParams.toolMaxTurns, () => ( 100));
3349
4880
  let iteration = 0;
@@ -3375,9 +4906,9 @@ async function streamWithTools(options, callbacks, mcpService, llmConfig, getPro
3375
4906
  provider
3376
4907
  );
3377
4908
  if (options.nativeSearchAugmentation) {
3378
- _chunkV5KPWNYXcjs.applyAugmentation.call(void 0, requestBody, options.nativeSearchAugmentation);
4909
+ _chunkJMJBSACDcjs.applyAugmentation.call(void 0, requestBody, options.nativeSearchAugmentation);
3379
4910
  }
3380
- const headers = _chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, apiKey);
4911
+ const headers = _chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey);
3381
4912
  logger.info("Sending tool call request", {
3382
4913
  url,
3383
4914
  headers,
@@ -3390,12 +4921,12 @@ async function streamWithTools(options, callbacks, mcpService, llmConfig, getPro
3390
4921
  });
3391
4922
  if (!response.ok) {
3392
4923
  const errorText = await response.text();
3393
- _optionalChain([callbacks, 'access', _231 => _231.onError, 'optionalCall', _232 => _232(`API error (${response.status}): ${errorText}`)]);
4924
+ _optionalChain([callbacks, 'access', _290 => _290.onError, 'optionalCall', _291 => _291(`API error (${response.status}): ${errorText}`)]);
3394
4925
  return;
3395
4926
  }
3396
- const reader = _optionalChain([response, 'access', _233 => _233.body, 'optionalAccess', _234 => _234.getReader, 'call', _235 => _235()]);
4927
+ const reader = _optionalChain([response, 'access', _292 => _292.body, 'optionalAccess', _293 => _293.getReader, 'call', _294 => _294()]);
3397
4928
  if (!reader) {
3398
- _optionalChain([callbacks, 'access', _236 => _236.onError, 'optionalCall', _237 => _237("No response body")]);
4929
+ _optionalChain([callbacks, 'access', _295 => _295.onError, 'optionalCall', _296 => _296("No response body")]);
3399
4930
  return;
3400
4931
  }
3401
4932
  const decoder = new TextDecoder();
@@ -3428,7 +4959,7 @@ async function streamWithTools(options, callbacks, mcpService, llmConfig, getPro
3428
4959
  logger.debug("Parsed JSON", { json });
3429
4960
  if (json.error) {
3430
4961
  logger.error("API Error", void 0, { error: json.error });
3431
- _optionalChain([callbacks, 'access', _238 => _238.onError, 'optionalCall', _239 => _239(`API Error: ${json.error.message || JSON.stringify(json.error)}`)]);
4962
+ _optionalChain([callbacks, 'access', _297 => _297.onError, 'optionalCall', _298 => _298(`API Error: ${json.error.message || JSON.stringify(json.error)}`)]);
3432
4963
  return;
3433
4964
  }
3434
4965
  parseStreamChunk(json, apiFormat, callbacks, logger);
@@ -3461,7 +4992,7 @@ async function streamWithTools(options, callbacks, mcpService, llmConfig, getPro
3461
4992
  toolCallsLength: toolCalls.length,
3462
4993
  executableToolCallsLength: executableToolCalls.length,
3463
4994
  hasMcpTools: !!options.mcpTools,
3464
- mcpToolsLength: _optionalChain([options, 'access', _240 => _240.mcpTools, 'optionalAccess', _241 => _241.length]),
4995
+ mcpToolsLength: _optionalChain([options, 'access', _299 => _299.mcpTools, 'optionalAccess', _300 => _300.length]),
3465
4996
  hasMcpService: !!mcpService
3466
4997
  });
3467
4998
  if (executableToolCalls.length > 0 && options.mcpTools && (mcpService || builtinExecutor)) {
@@ -3482,7 +5013,7 @@ async function streamWithTools(options, callbacks, mcpService, llmConfig, getPro
3482
5013
  builtinExecutor
3483
5014
  );
3484
5015
  const toolResultsText = toolResults.map(({ toolCall, result }) => {
3485
- const resultText = typeof result === "string" ? result : _optionalChain([result, 'access', _242 => _242.content, 'optionalAccess', _243 => _243[0], 'optionalAccess', _244 => _244.text]) || JSON.stringify(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);
3486
5017
  return `Tool ${toolCall.name} result:
3487
5018
  ${resultText}`;
3488
5019
  }).join("\n\n");
@@ -3500,12 +5031,12 @@ ${resultText}`;
3500
5031
  }
3501
5032
  } catch (streamError) {
3502
5033
  logger.error("Stream processing error", streamError instanceof Error ? streamError : void 0);
3503
- _optionalChain([callbacks, 'access', _245 => _245.onError, 'optionalCall', _246 => _246(`Stream error: ${streamError instanceof Error ? streamError.message : "Unknown error"}`)]);
5034
+ _optionalChain([callbacks, 'access', _304 => _304.onError, 'optionalCall', _305 => _305(`Stream error: ${streamError instanceof Error ? streamError.message : "Unknown error"}`)]);
3504
5035
  return;
3505
5036
  }
3506
5037
  }
3507
5038
  logger.info("Sending final callback", { blocksCount: blocks.length });
3508
- _optionalChain([callbacks, 'access', _247 => _247.onDone, 'optionalCall', _248 => _248({
5039
+ _optionalChain([callbacks, 'access', _306 => _306.onDone, 'optionalCall', _307 => _307({
3509
5040
  id: messageId,
3510
5041
  role: "assistant",
3511
5042
  content: finalContent,
@@ -3516,7 +5047,7 @@ ${resultText}`;
3516
5047
  } catch (error) {
3517
5048
  logger.error("Error in streamWithTools", error instanceof Error ? error : void 0);
3518
5049
  const message = error instanceof Error ? error.message : "Unknown error";
3519
- _optionalChain([callbacks, 'access', _249 => _249.onError, 'optionalCall', _250 => _250(message)]);
5050
+ _optionalChain([callbacks, 'access', _308 => _308.onError, 'optionalCall', _309 => _309(message)]);
3520
5051
  }
3521
5052
  }
3522
5053
 
@@ -3555,8 +5086,8 @@ async function completeWithTransformers(options, llmConfig, getProvider, resolve
3555
5086
  options.providerId,
3556
5087
  options.model
3557
5088
  );
3558
- const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _251 => _251.actualProviderId]) || options.providerId;
3559
- const actualModel = _optionalChain([routedInfo, 'optionalAccess', _252 => _252.actualModelId]) || options.model;
5089
+ const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _310 => _310.actualProviderId]) || options.providerId;
5090
+ const actualModel = _optionalChain([routedInfo, 'optionalAccess', _311 => _311.actualModelId]) || options.model;
3560
5091
  const provider = await getProvider(actualProviderId);
3561
5092
  if (!provider) {
3562
5093
  return { success: false, error: `Provider not found: ${actualProviderId}` };
@@ -3594,7 +5125,7 @@ async function completeWithTransformers(options, llmConfig, getProvider, resolve
3594
5125
  models: provider.models || []
3595
5126
  };
3596
5127
  const executor = getSharedExecutor2();
3597
- const { response } = await _chunkKUU2RNG6cjs.executeProviderCall.call(void 0, {
5128
+ const { response } = await _chunkHYN75H6Gcjs.executeProviderCall.call(void 0, {
3598
5129
  executor,
3599
5130
  request: unifiedRequest,
3600
5131
  provider: transformerProvider,
@@ -3603,9 +5134,9 @@ async function completeWithTransformers(options, llmConfig, getProvider, resolve
3603
5134
  extendedContext: options.useExtendedContext ? { enabled: true, model: actualModel } : void 0,
3604
5135
  resolveUrl: (config) => config.url instanceof URL ? config.url.toString() : _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: actualModel, stream: false }),
3605
5136
  buildHeaders: (config) => ({
3606
- ..._chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, apiKey),
5137
+ ..._chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey),
3607
5138
  ...config.headers,
3608
- ..._chunk6VIXXLMXcjs.isOpenRouterProvider.call(void 0, provider) ? _chunk6VIXXLMXcjs.OPENROUTER_APP_HEADERS : {}
5139
+ ..._chunkUNEFIWXIcjs.isOpenRouterProvider.call(void 0, provider) ? _chunkUNEFIWXIcjs.OPENROUTER_APP_HEADERS : {}
3609
5140
  }),
3610
5141
  // Add OpenRouter provider routing config if applicable
3611
5142
  prepareBody: (requestBody) => addOpenRouterProviderToRequest(
@@ -3637,18 +5168,18 @@ async function completeWithTransformers(options, llmConfig, getProvider, resolve
3637
5168
  { endpointTransformer: void 0 }
3638
5169
  );
3639
5170
  const data = await transformedResponse.json();
3640
- const choice = _optionalChain([data, 'access', _253 => _253.choices, 'optionalAccess', _254 => _254[0]]);
5171
+ const choice = _optionalChain([data, 'access', _312 => _312.choices, 'optionalAccess', _313 => _313[0]]);
3641
5172
  if (!choice) {
3642
5173
  return { success: false, error: "No choices in response" };
3643
5174
  }
3644
- const rawToolCalls = _optionalChain([choice, 'access', _255 => _255.message, 'optionalAccess', _256 => _256.tool_calls]);
3645
- const toolCalls = _optionalChain([rawToolCalls, 'optionalAccess', _257 => _257.map, 'call', _258 => _258((tc) => ({
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) => ({
3646
5177
  id: tc.id,
3647
5178
  name: tc.function.name,
3648
5179
  args: typeof tc.function.arguments === "string" ? JSON.parse(tc.function.arguments) : tc.function.arguments
3649
5180
  }))]);
3650
5181
  const tapped = readUsageFromOpenAIResponse(data.usage);
3651
- if (_optionalChain([recording, 'optionalAccess', _259 => _259.recorder]) && tapped) {
5182
+ if (_optionalChain([recording, 'optionalAccess', _318 => _318.recorder]) && tapped) {
3652
5183
  recording.recorder.record({
3653
5184
  messageId: _nullishCoalesce(options.messageId, () => ( null)),
3654
5185
  parentMessageId: _nullishCoalesce(options.parentMessageId, () => ( null)),
@@ -3666,9 +5197,9 @@ async function completeWithTransformers(options, llmConfig, getProvider, resolve
3666
5197
  message: {
3667
5198
  id: `msg_${Date.now()}`,
3668
5199
  role: "assistant",
3669
- content: _optionalChain([choice, 'access', _260 => _260.message, 'optionalAccess', _261 => _261.content]) || "",
5200
+ content: _optionalChain([choice, 'access', _319 => _319.message, 'optionalAccess', _320 => _320.content]) || "",
3670
5201
  timestamp: Date.now(),
3671
- thinking: data.reasoning_content || _optionalChain([choice, 'access', _262 => _262.message, 'optionalAccess', _263 => _263.thinking, 'optionalAccess', _264 => _264.content]) ? { content: data.reasoning_content || _optionalChain([choice, 'access', _265 => _265.message, 'optionalAccess', _266 => _266.thinking, 'optionalAccess', _267 => _267.content]) || "", signature: _optionalChain([choice, 'access', _268 => _268.message, 'optionalAccess', _269 => _269.thinking, 'optionalAccess', _270 => _270.signature]) } : void 0,
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,
3672
5203
  toolCalls
3673
5204
  },
3674
5205
  usage: data.usage ? {
@@ -3689,21 +5220,21 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
3689
5220
  options.providerId,
3690
5221
  options.model
3691
5222
  );
3692
- const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _271 => _271.actualProviderId]) || options.providerId;
3693
- const actualModel = _optionalChain([routedInfo, 'optionalAccess', _272 => _272.actualModelId]) || options.model;
5223
+ const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _330 => _330.actualProviderId]) || options.providerId;
5224
+ const actualModel = _optionalChain([routedInfo, 'optionalAccess', _331 => _331.actualModelId]) || options.model;
3694
5225
  const provider = await getProvider(actualProviderId);
3695
5226
  if (!provider) {
3696
- _optionalChain([callbacks, 'access', _273 => _273.onError, 'optionalCall', _274 => _274(`Provider not found: ${actualProviderId}`)]);
5227
+ _optionalChain([callbacks, 'access', _332 => _332.onError, 'optionalCall', _333 => _333(`Provider not found: ${actualProviderId}`)]);
3697
5228
  return;
3698
5229
  }
3699
5230
  if (!provider.enabled) {
3700
- _optionalChain([callbacks, 'access', _275 => _275.onError, 'optionalCall', _276 => _276(`Provider is disabled: ${provider.name}`)]);
5231
+ _optionalChain([callbacks, 'access', _334 => _334.onError, 'optionalCall', _335 => _335(`Provider is disabled: ${provider.name}`)]);
3701
5232
  return;
3702
5233
  }
3703
5234
  const { apiKey: effectiveKey } = _chunkA2YMUCBTcjs.resolveProviderEndpoint.call(void 0, provider);
3704
5235
  const apiKey = resolveApiKey2(effectiveKey);
3705
5236
  if (!apiKey) {
3706
- _optionalChain([callbacks, 'access', _277 => _277.onError, 'optionalCall', _278 => _278("API key not configured")]);
5237
+ _optionalChain([callbacks, 'access', _336 => _336.onError, 'optionalCall', _337 => _337("API key not configured")]);
3707
5238
  return;
3708
5239
  }
3709
5240
  const { chain, hasTransformers } = await resolveChainWithMain(
@@ -3715,7 +5246,7 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
3715
5246
  return completeStreamFallback(options, callbacks);
3716
5247
  }
3717
5248
  const messageId = `msg_${Date.now()}`;
3718
- _optionalChain([callbacks, 'access', _279 => _279.onStart, 'optionalCall', _280 => _280(messageId)]);
5249
+ _optionalChain([callbacks, 'access', _338 => _338.onStart, 'optionalCall', _339 => _339(messageId)]);
3719
5250
  const unifiedRequest = {
3720
5251
  model: actualModel,
3721
5252
  messages: options.messages.map((m) => ({
@@ -3733,7 +5264,7 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
3733
5264
  models: provider.models || []
3734
5265
  };
3735
5266
  const executor = getSharedExecutor2();
3736
- const { response } = await _chunkKUU2RNG6cjs.executeProviderCall.call(void 0, {
5267
+ const { response } = await _chunkHYN75H6Gcjs.executeProviderCall.call(void 0, {
3737
5268
  executor,
3738
5269
  request: unifiedRequest,
3739
5270
  provider: transformerProvider,
@@ -3742,9 +5273,9 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
3742
5273
  extendedContext: options.useExtendedContext ? { enabled: true, model: actualModel } : void 0,
3743
5274
  resolveUrl: (config) => config.url instanceof URL ? config.url.toString() : _chunkA2YMUCBTcjs.buildProviderApiUrl.call(void 0, provider, { model: actualModel, stream: true }),
3744
5275
  buildHeaders: (config) => ({
3745
- ..._chunkLKZJEL6Ecjs.getProviderHeaders.call(void 0, provider, apiKey),
5276
+ ..._chunkQ27JY5RGcjs.getProviderHeaders.call(void 0, provider, apiKey),
3746
5277
  ...config.headers,
3747
- ..._chunk6VIXXLMXcjs.isOpenRouterProvider.call(void 0, provider) ? _chunk6VIXXLMXcjs.OPENROUTER_APP_HEADERS : {}
5278
+ ..._chunkUNEFIWXIcjs.isOpenRouterProvider.call(void 0, provider) ? _chunkUNEFIWXIcjs.OPENROUTER_APP_HEADERS : {}
3748
5279
  }),
3749
5280
  // Add OpenRouter provider routing config if applicable
3750
5281
  prepareBody: (requestBody) => addOpenRouterProviderToRequest(
@@ -3763,7 +5294,7 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
3763
5294
  });
3764
5295
  if (!response.ok) {
3765
5296
  const errorText = await response.text();
3766
- _optionalChain([callbacks, 'access', _281 => _281.onError, 'optionalCall', _282 => _282(`API error (${response.status}): ${errorText}`)]);
5297
+ _optionalChain([callbacks, 'access', _340 => _340.onError, 'optionalCall', _341 => _341(`API error (${response.status}): ${errorText}`)]);
3767
5298
  return;
3768
5299
  }
3769
5300
  const transformedResponse = await executor.executeResponseChain(
@@ -3773,9 +5304,9 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
3773
5304
  chain,
3774
5305
  { endpointTransformer: void 0 }
3775
5306
  );
3776
- const reader = _optionalChain([transformedResponse, 'access', _283 => _283.body, 'optionalAccess', _284 => _284.getReader, 'call', _285 => _285()]);
5307
+ const reader = _optionalChain([transformedResponse, 'access', _342 => _342.body, 'optionalAccess', _343 => _343.getReader, 'call', _344 => _344()]);
3777
5308
  if (!reader) {
3778
- _optionalChain([callbacks, 'access', _286 => _286.onError, 'optionalCall', _287 => _287("No response body")]);
5309
+ _optionalChain([callbacks, 'access', _345 => _345.onError, 'optionalCall', _346 => _346("No response body")]);
3779
5310
  return;
3780
5311
  }
3781
5312
  const decoder = new TextDecoder();
@@ -3793,22 +5324,22 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
3793
5324
  if (data === "[DONE]") continue;
3794
5325
  try {
3795
5326
  const json = JSON.parse(data);
3796
- const delta = _optionalChain([json, 'access', _288 => _288.choices, 'optionalAccess', _289 => _289[0], 'optionalAccess', _290 => _290.delta]);
3797
- if (_optionalChain([delta, 'optionalAccess', _291 => _291.content])) {
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])) {
3798
5329
  content += delta.content;
3799
- _optionalChain([callbacks, 'access', _292 => _292.onDelta, 'optionalCall', _293 => _293(delta.content)]);
5330
+ _optionalChain([callbacks, 'access', _351 => _351.onDelta, 'optionalCall', _352 => _352(delta.content)]);
3800
5331
  }
3801
- if (_optionalChain([delta, 'optionalAccess', _294 => _294.thinking, 'optionalAccess', _295 => _295.content])) {
5332
+ if (_optionalChain([delta, 'optionalAccess', _353 => _353.thinking, 'optionalAccess', _354 => _354.content])) {
3802
5333
  reasoning += delta.thinking.content;
3803
- _optionalChain([callbacks, 'access', _296 => _296.onReasoning, 'optionalCall', _297 => _297(delta.thinking.content)]);
5334
+ _optionalChain([callbacks, 'access', _355 => _355.onReasoning, 'optionalCall', _356 => _356(delta.thinking.content)]);
3804
5335
  }
3805
- if (_optionalChain([delta, 'optionalAccess', _298 => _298.reasoning_content])) {
5336
+ if (_optionalChain([delta, 'optionalAccess', _357 => _357.reasoning_content])) {
3806
5337
  reasoning += delta.reasoning_content;
3807
- _optionalChain([callbacks, 'access', _299 => _299.onReasoning, 'optionalCall', _300 => _300(delta.reasoning_content)]);
5338
+ _optionalChain([callbacks, 'access', _358 => _358.onReasoning, 'optionalCall', _359 => _359(delta.reasoning_content)]);
3808
5339
  }
3809
5340
  if (json.usage) {
3810
5341
  const tapped = readUsageFromOpenAIResponse(json.usage);
3811
- if (_optionalChain([recording, 'optionalAccess', _301 => _301.recorder]) && tapped) {
5342
+ if (_optionalChain([recording, 'optionalAccess', _360 => _360.recorder]) && tapped) {
3812
5343
  recording.recorder.record({
3813
5344
  messageId: _nullishCoalesce(options.messageId, () => ( null)),
3814
5345
  parentMessageId: _nullishCoalesce(options.parentMessageId, () => ( null)),
@@ -3821,7 +5352,7 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
3821
5352
  rawUsage: json.usage
3822
5353
  });
3823
5354
  }
3824
- _optionalChain([callbacks, 'access', _302 => _302.onDone, 'optionalCall', _303 => _303(
5355
+ _optionalChain([callbacks, 'access', _361 => _361.onDone, 'optionalCall', _362 => _362(
3825
5356
  {
3826
5357
  id: messageId,
3827
5358
  role: "assistant",
@@ -3842,7 +5373,7 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
3842
5373
  }
3843
5374
  }
3844
5375
  }
3845
- _optionalChain([callbacks, 'access', _304 => _304.onDone, 'optionalCall', _305 => _305({
5376
+ _optionalChain([callbacks, 'access', _363 => _363.onDone, 'optionalCall', _364 => _364({
3846
5377
  id: messageId,
3847
5378
  role: "assistant",
3848
5379
  content,
@@ -3854,13 +5385,13 @@ async function completeStreamWithTransformers(options, callbacks, llmConfig, get
3854
5385
  }
3855
5386
  } catch (error) {
3856
5387
  const message = error instanceof Error ? error.message : "Unknown error";
3857
- _optionalChain([callbacks, 'access', _306 => _306.onError, 'optionalCall', _307 => _307(message)]);
5388
+ _optionalChain([callbacks, 'access', _365 => _365.onError, 'optionalCall', _366 => _366(message)]);
3858
5389
  }
3859
5390
  }
3860
5391
 
3861
5392
  // src/completion/CompletionService.ts
3862
- var CompletionService = (_class5 = class {
3863
- constructor(paths, llmConfig, logger) {;_class5.prototype.__init10.call(this);_class5.prototype.__init11.call(this);_class5.prototype.__init12.call(this);_class5.prototype.__init13.call(this);
5393
+ 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);
3864
5395
  this.paths = paths;
3865
5396
  this.llmConfig = llmConfig;
3866
5397
  this.logger = logger;
@@ -3868,10 +5399,10 @@ var CompletionService = (_class5 = class {
3868
5399
 
3869
5400
 
3870
5401
 
3871
- __init10() {this.apiKeyPool = null}
3872
- __init11() {this.usageRecorder = null}
3873
- __init12() {this.usageEventSink = null}
3874
- __init13() {this.visionFallbackProvider = null}
5402
+ __init22() {this.apiKeyPool = null}
5403
+ __init23() {this.usageRecorder = null}
5404
+ __init24() {this.usageEventSink = null}
5405
+ __init25() {this.visionFallbackProvider = null}
3875
5406
  /**
3876
5407
  * Set the API key pool service for multi-key load balancing.
3877
5408
  * When set, keys are resolved via the pool instead of directly from the provider.
@@ -3921,8 +5452,8 @@ var CompletionService = (_class5 = class {
3921
5452
  options.providerId,
3922
5453
  options.model
3923
5454
  );
3924
- const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _308 => _308.actualProviderId]) || options.providerId;
3925
- const actualModel = _optionalChain([routedInfo, 'optionalAccess', _309 => _309.actualModelId]) || options.model;
5455
+ const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _367 => _367.actualProviderId]) || options.providerId;
5456
+ const actualModel = _optionalChain([routedInfo, 'optionalAccess', _368 => _368.actualModelId]) || options.model;
3926
5457
  const provider = await this.getProvider(actualProviderId);
3927
5458
  if (!provider) {
3928
5459
  return { success: false, error: `Provider not found: ${actualProviderId}` };
@@ -3955,7 +5486,7 @@ var CompletionService = (_class5 = class {
3955
5486
  this.apiKeyPool.reportSuccess(options.sessionId);
3956
5487
  }
3957
5488
  if (result.success && result.usage && options.sessionId) {
3958
- _optionalChain([this, 'access', _310 => _310.usageEventSink, 'optionalAccess', _311 => _311.emit, 'call', _312 => _312({
5489
+ _optionalChain([this, 'access', _369 => _369.usageEventSink, 'optionalAccess', _370 => _370.emit, 'call', _371 => _371({
3959
5490
  sessionId: options.sessionId,
3960
5491
  modelId: actualModel,
3961
5492
  usage: result.usage,
@@ -3984,8 +5515,8 @@ var CompletionService = (_class5 = class {
3984
5515
  options.model
3985
5516
  );
3986
5517
  this.logger.debug("Resolved routed model", { routedInfo });
3987
- const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _313 => _313.actualProviderId]) || options.providerId;
3988
- const actualModel = _optionalChain([routedInfo, 'optionalAccess', _314 => _314.actualModelId]) || options.model;
5518
+ const actualProviderId = _optionalChain([routedInfo, 'optionalAccess', _372 => _372.actualProviderId]) || options.providerId;
5519
+ const actualModel = _optionalChain([routedInfo, 'optionalAccess', _373 => _373.actualModelId]) || options.model;
3989
5520
  this.logger.debug("Resolved provider and model", { actualProviderId, actualModel });
3990
5521
  const provider = await this.getProvider(actualProviderId);
3991
5522
  this.logger.debug("Retrieved provider", provider ? {
@@ -3997,22 +5528,22 @@ var CompletionService = (_class5 = class {
3997
5528
  enabled: provider.enabled
3998
5529
  } : { error: "Provider not found" });
3999
5530
  if (!provider) {
4000
- _optionalChain([callbacks, 'access', _315 => _315.onError, 'optionalCall', _316 => _316(`Provider not found: ${actualProviderId}`)]);
5531
+ _optionalChain([callbacks, 'access', _374 => _374.onError, 'optionalCall', _375 => _375(`Provider not found: ${actualProviderId}`)]);
4001
5532
  return;
4002
5533
  }
4003
5534
  if (!provider.enabled) {
4004
- _optionalChain([callbacks, 'access', _317 => _317.onError, 'optionalCall', _318 => _318(`Provider is disabled: ${provider.name}`)]);
5535
+ _optionalChain([callbacks, 'access', _376 => _376.onError, 'optionalCall', _377 => _377(`Provider is disabled: ${provider.name}`)]);
4005
5536
  return;
4006
5537
  }
4007
5538
  const apiKey = await this.resolveApiKeyForRequest(provider, actualProviderId, options.sessionId);
4008
5539
  if (!apiKey) {
4009
- _optionalChain([callbacks, 'access', _319 => _319.onError, 'optionalCall', _320 => _320("API key not configured")]);
5540
+ _optionalChain([callbacks, 'access', _378 => _378.onError, 'optionalCall', _379 => _379("API key not configured")]);
4010
5541
  return;
4011
5542
  }
4012
5543
  const apiFormat = _chunkA2YMUCBTcjs.resolveApiFormat.call(void 0, provider);
4013
5544
  this.logger.info("Using API format for stream", { apiFormat });
4014
5545
  const messageId = `msg_${Date.now()}`;
4015
- _optionalChain([callbacks, 'access', _321 => _321.onStart, 'optionalCall', _322 => _322(messageId)]);
5546
+ _optionalChain([callbacks, 'access', _380 => _380.onStart, 'optionalCall', _381 => _381(messageId)]);
4016
5547
  const resolvedOptions = { ...options, model: actualModel };
4017
5548
  if (options.sessionId) {
4018
5549
  const sid = options.sessionId;
@@ -4021,14 +5552,14 @@ var CompletionService = (_class5 = class {
4021
5552
  ...callbacks,
4022
5553
  onDone: (message, usage, metrics) => {
4023
5554
  if (usage) {
4024
- _optionalChain([this, 'access', _323 => _323.usageEventSink, 'optionalAccess', _324 => _324.emit, 'call', _325 => _325({
5555
+ _optionalChain([this, 'access', _382 => _382.usageEventSink, 'optionalAccess', _383 => _383.emit, 'call', _384 => _384({
4025
5556
  sessionId: sid,
4026
5557
  modelId: actualModel,
4027
5558
  usage,
4028
5559
  engineOrigin: "completion"
4029
5560
  })]);
4030
5561
  }
4031
- _optionalChain([userOnDone, 'optionalCall', _326 => _326(message, usage, metrics)]);
5562
+ _optionalChain([userOnDone, 'optionalCall', _385 => _385(message, usage, metrics)]);
4032
5563
  }
4033
5564
  };
4034
5565
  }
@@ -4044,11 +5575,11 @@ var CompletionService = (_class5 = class {
4044
5575
  retryState.error = { status, message: error };
4045
5576
  return;
4046
5577
  }
4047
- _optionalChain([callbacks, 'access', _327 => _327.onError, 'optionalCall', _328 => _328(error)]);
5578
+ _optionalChain([callbacks, 'access', _386 => _386.onError, 'optionalCall', _387 => _387(error)]);
4048
5579
  },
4049
5580
  onDone: (message, usage, metrics) => {
4050
5581
  this.apiKeyPool.reportSuccess(options.sessionId);
4051
- _optionalChain([callbacks, 'access', _329 => _329.onDone, 'optionalCall', _330 => _330(message, usage, metrics)]);
5582
+ _optionalChain([callbacks, 'access', _388 => _388.onDone, 'optionalCall', _389 => _389(message, usage, metrics)]);
4052
5583
  }
4053
5584
  };
4054
5585
  await this.callStreamHandler(apiFormat, provider, apiKey, resolvedOptions, messageId, interceptCallbacks);
@@ -4069,7 +5600,7 @@ var CompletionService = (_class5 = class {
4069
5600
  // don't fire onStart again
4070
5601
  });
4071
5602
  } else {
4072
- _optionalChain([callbacks, 'access', _331 => _331.onError, 'optionalCall', _332 => _332(retryState.error.message)]);
5603
+ _optionalChain([callbacks, 'access', _390 => _390.onError, 'optionalCall', _391 => _391(retryState.error.message)]);
4073
5604
  }
4074
5605
  }
4075
5606
  } else {
@@ -4082,7 +5613,7 @@ var CompletionService = (_class5 = class {
4082
5613
  } catch (error) {
4083
5614
  const message = error instanceof Error ? error.message : "Unknown error";
4084
5615
  this.logger.error("Stream completion error", error instanceof Error ? error : void 0, { message });
4085
- _optionalChain([callbacks, 'access', _333 => _333.onError, 'optionalCall', _334 => _334(message)]);
5616
+ _optionalChain([callbacks, 'access', _392 => _392.onError, 'optionalCall', _393 => _393(message)]);
4086
5617
  }
4087
5618
  }
4088
5619
  /**
@@ -4122,7 +5653,7 @@ var CompletionService = (_class5 = class {
4122
5653
  return {
4123
5654
  success: true,
4124
5655
  message: "Connection successful",
4125
- response: _optionalChain([result, 'access', _335 => _335.message, 'optionalAccess', _336 => _336.content]) || "",
5656
+ response: _optionalChain([result, 'access', _394 => _394.message, 'optionalAccess', _395 => _395.content]) || "",
4126
5657
  model: modelId,
4127
5658
  durationMs
4128
5659
  };
@@ -4187,7 +5718,7 @@ ${description}`;
4187
5718
  * 3. Legacy single key from provider config
4188
5719
  */
4189
5720
  async resolveApiKeyForRequest(provider, providerId, sessionId) {
4190
- if (_optionalChain([provider, 'access', _337 => _337.codingPlan, 'optionalAccess', _338 => _338.enabled]) && provider.codingPlan.apiKey) {
5721
+ if (_optionalChain([provider, 'access', _396 => _396.codingPlan, 'optionalAccess', _397 => _397.enabled]) && provider.codingPlan.apiKey) {
4191
5722
  return this.resolveApiKey(provider.codingPlan.apiKey);
4192
5723
  }
4193
5724
  if (this.apiKeyPool) {
@@ -4352,7 +5883,46 @@ ${description}`;
4352
5883
  builtinExecutor
4353
5884
  );
4354
5885
  }
4355
- }, _class5);
5886
+ }, _class13);
5887
+
5888
+
5889
+
5890
+
5891
+
5892
+
5893
+
5894
+
5895
+
5896
+
5897
+
5898
+
5899
+
5900
+
5901
+
5902
+
5903
+
5904
+
5905
+
5906
+
5907
+
5908
+
5909
+
5910
+
5911
+
5912
+
5913
+
5914
+
5915
+
5916
+
5917
+
5918
+
5919
+
5920
+
5921
+
5922
+
5923
+
5924
+
5925
+
4356
5926
 
4357
5927
 
4358
5928
 
@@ -4397,4 +5967,4 @@ ${description}`;
4397
5967
 
4398
5968
 
4399
5969
 
4400
- 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.hashKey = hashKey; exports.createNamedKey = createNamedKey; exports.verifyPresentedKey = verifyPresentedKey; exports.detectRequestRole = detectRequestRole; exports.endpointToIngressFormat = endpointToIngressFormat; exports.OutboundRateLimiter = OutboundRateLimiter; exports.DEFAULT_OUTBOUND_PORT = DEFAULT_OUTBOUND_PORT; exports.OutboundApiServer = OutboundApiServer; exports.formatUrls = formatUrls; exports.OUTBOUND_API_SERVER_CONFIG_KEY = OUTBOUND_API_SERVER_CONFIG_KEY; exports.defaultServerConfig = defaultServerConfig; exports.normalizeServerConfig = normalizeServerConfig; exports.loadServerConfig = loadServerConfig; exports.saveServerConfig = saveServerConfig; exports.mergeServerConfig = mergeServerConfig; exports.getOutboundApiServer = getOutboundApiServer; exports.__resetOutboundApiServerForTests = __resetOutboundApiServerForTests;
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;