@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,79 +1,206 @@
1
1
  import {
2
+ ConcurrencyQueueFullError,
3
+ ConcurrencyWaitCancelledError,
4
+ ConcurrencyWaitTimeoutError,
5
+ DEFAULT_ACCOUNT_PROBE,
6
+ DEFAULT_CONCURRENCY_QUEUE,
7
+ DEFAULT_FINGERPRINT,
2
8
  DEFAULT_OUTBOUND_PORT,
9
+ DEFAULT_USER_MESSAGE_QUEUE,
10
+ KeySpendTracker,
11
+ KeyedMutex,
3
12
  OUTBOUND_API_SERVER_CONFIG_KEY,
13
+ OutboundApiConfigError,
4
14
  OutboundApiServer,
15
+ OutboundConcurrencyGate,
5
16
  OutboundRateLimiter,
17
+ SerialQueueTimeoutError,
18
+ UserMessageSerialQueue,
6
19
  __resetOutboundApiServerForTests,
20
+ checkKeyQuota,
21
+ computeKeyExpiry,
22
+ computeVoucherGrant,
7
23
  createNamedKey,
8
24
  defaultServerConfig,
9
- detectRequestRole,
10
- endpointToIngressFormat,
11
25
  formatUrls,
26
+ generateVoucherCode,
12
27
  getOutboundApiServer,
28
+ handleVoucherRedeem,
13
29
  hashKey,
30
+ hashVoucherCode,
31
+ isConcurrencyRejection,
32
+ isRedeemRequest,
33
+ isSerialQueueTimeout,
34
+ isUserMessageRequest,
14
35
  loadServerConfig,
15
36
  mergeServerConfig,
37
+ newVoucherId,
38
+ normalizeAccountProbe,
39
+ normalizeAudit,
40
+ normalizeBilling,
41
+ normalizeFingerprint,
42
+ normalizePrefixTargets,
43
+ normalizeProxyConfig,
44
+ normalizeProxySegment,
45
+ normalizeQueueSegments,
16
46
  normalizeServerConfig,
47
+ normalizeVoucher,
48
+ normalizeWebhookDestination,
49
+ normalizeWebhookSegment,
50
+ randomBase62,
17
51
  saveServerConfig,
18
- verifyPresentedKey
19
- } from "./chunk-2FEVTJWG.js";
20
- import "./chunk-QOCNX236.js";
52
+ startOfLocalDay,
53
+ startOfLocalWeek,
54
+ toVoucherInfo,
55
+ verifyKey,
56
+ verifyPresentedKey,
57
+ voucherCodePrefix
58
+ } from "./chunk-QYTT6GE3.js";
21
59
  import "./chunk-VVEHS2LI.js";
22
60
  import "./chunk-46RLHI7D.js";
23
- import "./chunk-G2UTNSGU.js";
24
- import "./chunk-MZNPGW5Q.js";
25
61
  import "./chunk-DK4A7DLE.js";
26
- import "./chunk-O466Y272.js";
27
- import "./chunk-C7PSERMH.js";
28
- import "./chunk-5HTVET6E.js";
29
- import "./chunk-Z7LUNECE.js";
62
+ import "./chunk-VPBAUQ2M.js";
30
63
  import "./chunk-ZJZAOKI7.js";
31
64
  import "./chunk-FTQ7IQUC.js";
65
+ import "./chunk-C7PSERMH.js";
66
+ import "./chunk-TIER4SUC.js";
67
+ import "./chunk-Z7LUNECE.js";
32
68
  import "./chunk-7VU7V2E4.js";
33
69
  import "./chunk-ZLX3KGXX.js";
34
- import "./chunk-MNYKI4CI.js";
70
+ import "./chunk-BPKCU575.js";
71
+ import "./chunk-G2UTNSGU.js";
72
+ import "./chunk-MZNPGW5Q.js";
73
+ import "./chunk-XTEI64OU.js";
74
+ import "./chunk-XX6NQJMA.js";
75
+ import "./chunk-IAXWICZU.js";
76
+ import "./chunk-OE6TDIWW.js";
35
77
  import "./chunk-DRWHTIIZ.js";
36
- import "./chunk-JO5NLTLY.js";
37
- import "./chunk-PXUJF5HS.js";
78
+ import "./chunk-IK3KE3AU.js";
79
+ import "./chunk-ZY6KU6P3.js";
38
80
  import "./chunk-JWC6APFQ.js";
39
81
  import "./chunk-5ERIZW3D.js";
40
- import "./chunk-74TMJA7Z.js";
82
+ import "./chunk-5ENKBSWO.js";
83
+ import "./chunk-HRRYG2AX.js";
41
84
  import "./chunk-AVYJ4YBN.js";
42
- import "./chunk-H5JUT3KV.js";
85
+ import {
86
+ beginBillingCapture
87
+ } from "./chunk-WLYIIEAF.js";
88
+ import "./chunk-TKJMZBAH.js";
89
+ import "./chunk-3QFXFCHG.js";
43
90
  import {
44
91
  SUBSCRIPTION_PROVIDER_IDS,
92
+ classifyModelPrefix,
93
+ detectModelKind,
94
+ detectRequestRole,
45
95
  endpointSupportsSubscription,
96
+ endpointToIngressFormat,
97
+ isKindMappedEndpoint,
46
98
  isSubscriptionProviderId,
47
- resolveRoute
48
- } from "./chunk-3MEACFK3.js";
99
+ modelKindsForEndpoint,
100
+ parseModelRef,
101
+ pickModelRefFromList,
102
+ resolvePrefixTarget,
103
+ resolveRoute,
104
+ validateEndpointModelConfig,
105
+ validateServerModelConfig
106
+ } from "./chunk-UHGVBFU3.js";
49
107
  import "./chunk-AQ5TNQB7.js";
108
+ import {
109
+ ENDPOINT_MODEL_KINDS
110
+ } from "./chunk-XEKD23J5.js";
111
+ import "./chunk-H5JUT3KV.js";
112
+ import {
113
+ beginAuditCapture
114
+ } from "./chunk-7Y47UCF2.js";
115
+ import {
116
+ AUDIT_REDACTED,
117
+ redactAuditText
118
+ } from "./chunk-K5NM7VAH.js";
119
+ import "./chunk-WNY4WMRF.js";
120
+ import "./chunk-OZFM4X3S.js";
50
121
  import "./chunk-5ZQBEOMD.js";
51
122
  import "./chunk-Z7Y2NPHY.js";
52
123
  import "./chunk-S4WBV25P.js";
124
+ import "./chunk-XK5CIRMQ.js";
53
125
  import "./chunk-CDHS2QDC.js";
54
- import "./chunk-745DV5FL.js";
55
- import "./chunk-E3WHL7CO.js";
126
+ import "./chunk-Y7FO65VT.js";
56
127
  import "./chunk-FMOBD2OQ.js";
128
+ import "./chunk-HUZZZ3JL.js";
57
129
  export {
130
+ AUDIT_REDACTED,
131
+ ConcurrencyQueueFullError,
132
+ ConcurrencyWaitCancelledError,
133
+ ConcurrencyWaitTimeoutError,
134
+ DEFAULT_ACCOUNT_PROBE,
135
+ DEFAULT_CONCURRENCY_QUEUE,
136
+ DEFAULT_FINGERPRINT,
58
137
  DEFAULT_OUTBOUND_PORT,
138
+ DEFAULT_USER_MESSAGE_QUEUE,
139
+ ENDPOINT_MODEL_KINDS,
140
+ KeySpendTracker,
141
+ KeyedMutex,
59
142
  OUTBOUND_API_SERVER_CONFIG_KEY,
143
+ OutboundApiConfigError,
60
144
  OutboundApiServer,
145
+ OutboundConcurrencyGate,
61
146
  OutboundRateLimiter,
62
147
  SUBSCRIPTION_PROVIDER_IDS,
148
+ SerialQueueTimeoutError,
149
+ UserMessageSerialQueue,
63
150
  __resetOutboundApiServerForTests,
151
+ beginAuditCapture,
152
+ beginBillingCapture,
153
+ checkKeyQuota,
154
+ classifyModelPrefix,
155
+ computeKeyExpiry,
156
+ computeVoucherGrant,
64
157
  createNamedKey,
65
158
  defaultServerConfig,
159
+ detectModelKind,
66
160
  detectRequestRole,
67
161
  endpointSupportsSubscription,
68
162
  endpointToIngressFormat,
69
163
  formatUrls,
164
+ generateVoucherCode,
70
165
  getOutboundApiServer,
166
+ handleVoucherRedeem,
71
167
  hashKey,
168
+ hashVoucherCode,
169
+ isConcurrencyRejection,
170
+ isKindMappedEndpoint,
171
+ isRedeemRequest,
172
+ isSerialQueueTimeout,
72
173
  isSubscriptionProviderId,
174
+ isUserMessageRequest,
73
175
  loadServerConfig,
74
176
  mergeServerConfig,
177
+ modelKindsForEndpoint,
178
+ newVoucherId,
179
+ normalizeAccountProbe,
180
+ normalizeAudit,
181
+ normalizeBilling,
182
+ normalizeFingerprint,
183
+ normalizePrefixTargets,
184
+ normalizeProxyConfig,
185
+ normalizeProxySegment,
186
+ normalizeQueueSegments,
75
187
  normalizeServerConfig,
188
+ normalizeVoucher,
189
+ normalizeWebhookDestination,
190
+ normalizeWebhookSegment,
191
+ parseModelRef,
192
+ pickModelRefFromList,
193
+ randomBase62,
194
+ redactAuditText,
195
+ resolvePrefixTarget,
76
196
  resolveRoute,
77
197
  saveServerConfig,
78
- verifyPresentedKey
198
+ startOfLocalDay,
199
+ startOfLocalWeek,
200
+ toVoucherInfo,
201
+ validateEndpointModelConfig,
202
+ validateServerModelConfig,
203
+ verifyKey,
204
+ verifyPresentedKey,
205
+ voucherCodePrefix
79
206
  };
@@ -34,6 +34,30 @@ interface AuthApplyHints {
34
34
  upstreamUrl: string;
35
35
  /** Resolved model id for the request. */
36
36
  model: string;
37
+ /**
38
+ * OPTIONAL stable per-conversation session key (subscription-account-scheduling,
39
+ * D5) — mapped through to the subscription strategy's sticky account affinity.
40
+ * BYO auth sources ignore it.
41
+ */
42
+ sessionKey?: string;
43
+ /**
44
+ * OPTIONAL per-request selection callback (subscription-account-health, D5;
45
+ * subscription-account-model-map, D3). A subscription strategy invokes it with
46
+ * the EFFECTIVE account id it resolved (the selected non-active id, or the active
47
+ * id on the null/≤1 path) so the relay can mark that account's health against the
48
+ * upstream outcome. The OPTIONAL 3rd `remappedModel` carries the selected
49
+ * account's ACTUAL upstream model when its `supportedModels` object remaps the
50
+ * request model — the relay rewrites the outbound `body.model` to it on the
51
+ * pass-through / same-format path (absent ⇒ forward verbatim). Fresh per request
52
+ * (no cross-request race). BYO auth sources ignore it.
53
+ */
54
+ reportSelection?: (accountId: string, isActive: boolean, remappedModel?: string) => void;
55
+ /**
56
+ * OPTIONAL preferred subscription account id (provider/subscription duality).
57
+ * When set and schedulable the account picker resolves it directly; absent or
58
+ * unschedulable ⇒ pool auto-schedule. BYO auth sources ignore it.
59
+ */
60
+ preferredAccountId?: string;
37
61
  }
38
62
  /**
39
63
  * Result of {@link AuthSource.onResult}.
@@ -74,8 +98,12 @@ interface AuthSource {
74
98
  * Called when the upstream returns 401. Return `true` to ask the caller to
75
99
  * retry once with freshly-applied headers; `false` to surface the 401.
76
100
  * Optional — sources without a refresh notion omit it.
101
+ *
102
+ * The OPTIONAL `sessionKey` (subscription-account-scheduling, D7) lets a
103
+ * subscription source refresh the account the request was actually served by;
104
+ * BYO sources ignore it.
77
105
  */
78
- onUnauthorized?(): Promise<boolean>;
106
+ onUnauthorized?(sessionKey?: string): Promise<boolean>;
79
107
  /**
80
108
  * Resolve the upstream URL the request should target, when the credential
81
109
  * dictates it (e.g. a subscription profile's per-model endpoint). Returns
@@ -34,6 +34,30 @@ interface AuthApplyHints {
34
34
  upstreamUrl: string;
35
35
  /** Resolved model id for the request. */
36
36
  model: string;
37
+ /**
38
+ * OPTIONAL stable per-conversation session key (subscription-account-scheduling,
39
+ * D5) — mapped through to the subscription strategy's sticky account affinity.
40
+ * BYO auth sources ignore it.
41
+ */
42
+ sessionKey?: string;
43
+ /**
44
+ * OPTIONAL per-request selection callback (subscription-account-health, D5;
45
+ * subscription-account-model-map, D3). A subscription strategy invokes it with
46
+ * the EFFECTIVE account id it resolved (the selected non-active id, or the active
47
+ * id on the null/≤1 path) so the relay can mark that account's health against the
48
+ * upstream outcome. The OPTIONAL 3rd `remappedModel` carries the selected
49
+ * account's ACTUAL upstream model when its `supportedModels` object remaps the
50
+ * request model — the relay rewrites the outbound `body.model` to it on the
51
+ * pass-through / same-format path (absent ⇒ forward verbatim). Fresh per request
52
+ * (no cross-request race). BYO auth sources ignore it.
53
+ */
54
+ reportSelection?: (accountId: string, isActive: boolean, remappedModel?: string) => void;
55
+ /**
56
+ * OPTIONAL preferred subscription account id (provider/subscription duality).
57
+ * When set and schedulable the account picker resolves it directly; absent or
58
+ * unschedulable ⇒ pool auto-schedule. BYO auth sources ignore it.
59
+ */
60
+ preferredAccountId?: string;
37
61
  }
38
62
  /**
39
63
  * Result of {@link AuthSource.onResult}.
@@ -74,8 +98,12 @@ interface AuthSource {
74
98
  * Called when the upstream returns 401. Return `true` to ask the caller to
75
99
  * retry once with freshly-applied headers; `false` to surface the 401.
76
100
  * Optional — sources without a refresh notion omit it.
101
+ *
102
+ * The OPTIONAL `sessionKey` (subscription-account-scheduling, D7) lets a
103
+ * subscription source refresh the account the request was actually served by;
104
+ * BYO sources ignore it.
77
105
  */
78
- onUnauthorized?(): Promise<boolean>;
106
+ onUnauthorized?(sessionKey?: string): Promise<boolean>;
79
107
  /**
80
108
  * Resolve the upstream URL the request should target, when the credential
81
109
  * dictates it (e.g. a subscription profile's per-model endpoint). Returns
@@ -1,8 +1,8 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkLKZJEL6Ecjs = require('../chunk-LKZJEL6E.cjs');
3
+ var _chunkQ27JY5RGcjs = require('../chunk-Q27JY5RG.cjs');
4
4
  require('../chunk-A2YMUCBT.cjs');
5
- require('../chunk-6VIXXLMX.cjs');
5
+ require('../chunk-UNEFIWXI.cjs');
6
6
 
7
7
 
8
- exports.LlmConfigProviderAuth = _chunkLKZJEL6Ecjs.LlmConfigProviderAuth;
8
+ exports.LlmConfigProviderAuth = _chunkQ27JY5RGcjs.LlmConfigProviderAuth;
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  LlmConfigProviderAuth
3
- } from "../chunk-PXUJF5HS.js";
3
+ } from "../chunk-ZY6KU6P3.js";
4
4
  import "../chunk-H5JUT3KV.js";
5
- import "../chunk-E3WHL7CO.js";
5
+ import "../chunk-HUZZZ3JL.js";
6
6
  export {
7
7
  LlmConfigProviderAuth
8
8
  };
@@ -0,0 +1,22 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+ var _chunkVQY5W4YWcjs = require('../chunk-VQY5W4YW.cjs');
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+ exports.AUTH_ERROR_TTL_MS = _chunkVQY5W4YWcjs.AUTH_ERROR_TTL_MS; exports.OVERLOAD_ENABLED_DEFAULT = _chunkVQY5W4YWcjs.OVERLOAD_ENABLED_DEFAULT; exports.OVERLOAD_TTL_MS = _chunkVQY5W4YWcjs.OVERLOAD_TTL_MS; exports.SERVER_ERROR_TTL_MS = _chunkVQY5W4YWcjs.SERVER_ERROR_TTL_MS; exports.SubscriptionAccountHealth = _chunkVQY5W4YWcjs.SubscriptionAccountHealth; exports.__resetSharedAccountHealthForTests = _chunkVQY5W4YWcjs.__resetSharedAccountHealthForTests; exports.getSharedAccountHealth = _chunkVQY5W4YWcjs.getSharedAccountHealth; exports.resolveResetSeconds = _chunkVQY5W4YWcjs.resolveResetSeconds; exports.setSharedAccountHealth = _chunkVQY5W4YWcjs.setSharedAccountHealth;
@@ -0,0 +1,235 @@
1
+ /**
2
+ * SubscriptionAccountHealth — the in-memory account health state machine
3
+ * (subscription-account-health, design D1/D2/D3/D6).
4
+ *
5
+ * Shaped like the existing per-model `CircuitBreaker` (`opencodego/CircuitBreaker`):
6
+ * an in-memory `Map`, an injectable `now` clock, and NO external deps / NO
7
+ * persistence. It is keyed by an opaque `providerId + '\0' + accountId` string —
8
+ * core never learns "account" semantics, exactly as the breaker keys by opaque
9
+ * `modelId`. It is hosted in `@omnicross/core` because all three consumers reach
10
+ * it in the allowed dependency direction:
11
+ * - the subscriptions strategies COMPUTE `schedulable` (`isSchedulable`) + mark
12
+ * a final-401;
13
+ * - the core `/v1/messages` relay MARKS 429/529/403/5xx from the upstream
14
+ * response (`recordUpstreamOutcome`);
15
+ * - the daemon `AccountHealthSweeper` drives proactive recovery
16
+ * (`sweepRecoveries` + `onRecovered`).
17
+ *
18
+ * It carries NO secrets — only statuses + epoch-ms timers — so the secret-free
19
+ * discipline is untouched. Health is IN-MEMORY (cleared on restart): the worst
20
+ * case after a restart is one request hitting a still-cooling account and getting
21
+ * the upstream's authoritative 429 (which re-marks it). Nothing is written to
22
+ * `tokens.json`.
23
+ *
24
+ * @module pipeline/SubscriptionAccountHealth
25
+ */
26
+ /** Default 529 overload cooldown (LEAD OQ1: ON by default, bounded 10 min). */
27
+ declare const OVERLOAD_TTL_MS: number;
28
+ /** 529 overload cooldown enabled by default (LEAD OQ1). */
29
+ declare const OVERLOAD_ENABLED_DEFAULT = true;
30
+ /** Transient cooldown for a final-401 / plain-403 (CRS auth_error 1800s). */
31
+ declare const AUTH_ERROR_TTL_MS: number;
32
+ /** Transient cooldown for a 5xx / thrown network failure (CRS server_error 300s). */
33
+ declare const SERVER_ERROR_TTL_MS: number;
34
+ /** Per-account health record (all timers are epoch ms). Absent fields ⇒ healthy. */
35
+ interface HealthRecord {
36
+ /** From a 429 authoritative reset header — rate-limited until this instant. */
37
+ rateLimitEndAt?: number;
38
+ /** From a 529 overload — in overload cooldown until this instant. */
39
+ overloadUntil?: number;
40
+ /** From a final-401 / plain-403 / 5xx / thrown — transient cooldown until this. */
41
+ tempUnavailableUntil?: number;
42
+ /** From a 403-ban — permanent, self-heal never clears it. */
43
+ blocked?: boolean;
44
+ }
45
+ /** The coarse health state surfaced to the admin accounts view (secret-free). */
46
+ type AccountHealthState = 'healthy' | 'rate_limited' | 'overloaded' | 'transient' | 'blocked';
47
+ /** Admin-facing status projection for one account. */
48
+ interface AccountHealthStatus {
49
+ state: AccountHealthState;
50
+ /** Epoch ms the current cooldown elapses (absent for healthy / blocked). */
51
+ cooldownUntil?: number;
52
+ }
53
+ /**
54
+ * The recovery signal emitted when an account transitions unhealthy → schedulable.
55
+ * FROZEN here (subscription-account-health OQ3) as the stable seam #5 (webhooks)
56
+ * and #8 (health-cron) CONSUME — they must not re-derive health.
57
+ */
58
+ interface AccountRecoveryEvent {
59
+ /** Opaque provider id ('claude' | 'codex' | 'gemini' | 'opencodego'). */
60
+ providerId: string;
61
+ /** The recovered account id. */
62
+ accountId: string;
63
+ /** Epoch ms of the recovery observation. */
64
+ at: number;
65
+ /** Discriminator so consumers can widen this to an anomaly union later. */
66
+ kind: 'rateLimitRecovery';
67
+ }
68
+ /** A recovery listener (fire-and-forget; the emitter never awaits it). */
69
+ type AccountRecoveryListener = (event: AccountRecoveryEvent) => void;
70
+ /** The coarse anomaly state an account transitioned into (secret-free). */
71
+ type AccountAnomalyState = 'blocked' | 'unauthorized' | 'rate_limited' | 'overloaded';
72
+ /**
73
+ * The anomaly signal emitted when a HEALTHY account transitions to unhealthy —
74
+ * the additive union #5 (webhooks) consumes, which this tracker's frozen `kind`
75
+ * discriminator (on {@link AccountRecoveryEvent}) explicitly anticipated. ADDITIVE:
76
+ * it fires ONLY on the healthy→unhealthy EDGE (de-duped) and changes NOTHING about
77
+ * the existing marking / recovery behavior. A #8 probe failure flows through the
78
+ * same `recordUpstreamOutcome` path, so anomaly covers it for free.
79
+ */
80
+ interface AccountAnomalyEvent {
81
+ /** Opaque provider id ('claude' | 'codex' | 'gemini' | 'opencodego'). */
82
+ providerId: string;
83
+ /** The account id that became unhealthy. */
84
+ accountId: string;
85
+ /** Epoch ms of the transition. */
86
+ at: number;
87
+ /** The coarse state the account entered (mapped from the marking). */
88
+ state: AccountAnomalyState;
89
+ }
90
+ /** An anomaly listener (fire-and-forget; the emitter never awaits it). */
91
+ type AccountAnomalyListener = (event: AccountAnomalyEvent) => void;
92
+ /** The inputs one upstream attempt contributes to health marking (design D3). */
93
+ interface RecordUpstreamOutcomeInput {
94
+ /** The final HTTP status, or `null` for a thrown / network failure. */
95
+ status: number | null;
96
+ /** Parsed authoritative reset (epoch SECONDS) — `anthropic-ratelimit-unified-reset`. */
97
+ resetHeaderSeconds?: number | null;
98
+ /** Parsed `retry-after` DELTA seconds (non-claude fallback, OQ2). */
99
+ retryAfterSeconds?: number | null;
100
+ /** Bounded response body text for the 403-ban sniff (only read on a 403). */
101
+ bodyText?: string;
102
+ /** Injectable clock (default the tracker's `now`). */
103
+ now?: number;
104
+ }
105
+ /** Constructor knobs (all default to the exported constants). */
106
+ interface SubscriptionAccountHealthOptions {
107
+ /** Injectable clock (ms). Default `Date.now`. */
108
+ now?: () => number;
109
+ /** Whether a 529 places the account in overload cooldown (LEAD OQ1: ON). */
110
+ overloadEnabled?: boolean;
111
+ /** The 529 overload cooldown duration (ms). */
112
+ overloadTtlMs?: number;
113
+ /** The final-401 / plain-403 transient cooldown (ms). */
114
+ authErrorTtlMs?: number;
115
+ /** The 5xx / thrown transient cooldown (ms). */
116
+ serverErrorTtlMs?: number;
117
+ }
118
+ /** Minimal structural read over a `Headers` OR a plain header record. */
119
+ type HeadersLike = {
120
+ get(name: string): string | null;
121
+ } | Record<string, string | undefined>;
122
+ /**
123
+ * Resolve the 429 cooldown drivers per provider (OQ2 seam) — a single pure
124
+ * function. claude is STRICT (only the authoritative
125
+ * `anthropic-ratelimit-unified-reset`, epoch seconds; a bare 429 stays unmarked);
126
+ * codex / gemini / opencodego additionally accept `retry-after` (delta seconds)
127
+ * and a provider-specific reset header as the cooldown driver.
128
+ */
129
+ declare function resolveResetSeconds(providerId: string, headers: HeadersLike): {
130
+ resetHeaderSeconds: number | null;
131
+ retryAfterSeconds: number | null;
132
+ };
133
+ declare class SubscriptionAccountHealth {
134
+ private readonly records;
135
+ private readonly listeners;
136
+ private readonly anomalyListeners;
137
+ private readonly now;
138
+ private overloadEnabled;
139
+ private overloadTtlMs;
140
+ private authErrorTtlMs;
141
+ private serverErrorTtlMs;
142
+ constructor(opts?: SubscriptionAccountHealthOptions);
143
+ /**
144
+ * Re-apply cooldown config to the LIVE shared instance (subscription-account-
145
+ * health, LEAD OQ1). `buildDaemon` is synchronous so it cannot await the
146
+ * persisted server config; the async `start.ts` path loads it and applies the
147
+ * `accountHealth` segment here — every strategy/relay/sweeper that already
148
+ * captured this instance picks the new values up. Only defined fields override.
149
+ */
150
+ configure(opts: Pick<SubscriptionAccountHealthOptions, 'overloadEnabled' | 'overloadTtlMs' | 'authErrorTtlMs' | 'serverErrorTtlMs'>): void;
151
+ /**
152
+ * Whether an account may be scheduled RIGHT NOW. `blocked` → false; any timer
153
+ * still in the future → false. Expired timers are lazily deleted on read (CRS
154
+ * lazy-clear parity) so an elapsed cooldown restores the account WITHOUT a
155
+ * timer — but the recovery SIGNAL is the sweeper's job (`sweepRecoveries`), so
156
+ * this read never emits (correctness is independent of the tick).
157
+ */
158
+ isSchedulable(providerId: string, accountId: string, now?: number): boolean;
159
+ /**
160
+ * The single marking entry point (design D3). Faithful to CRS status semantics:
161
+ * - 429 + authoritative reset → `rateLimitEndAt`; a non-claude 429 may use
162
+ * `retryAfterSeconds`; a bare 429 (no resolvable reset) is NOT marked;
163
+ * - 529 → `overloadUntil` (gated by `overloadEnabled`);
164
+ * - 403-ban body → `blocked` (permanent); plain 403 → transient;
165
+ * - final-401 → transient; 5xx / thrown(null) → transient;
166
+ * - non-429 4xx → NEUTRAL (never marked);
167
+ * - 2xx → clear rate-limit + transient state (keep `blocked`).
168
+ */
169
+ recordUpstreamOutcome(providerId: string, accountId: string, input: RecordUpstreamOutcomeInput): void;
170
+ /** Whether a record is unhealthy at `now`: blocked, or any timer still future. */
171
+ private isUnhealthyAt;
172
+ /**
173
+ * Clear ONLY the auth/transient unavailability mark (`tempUnavailableUntil`) —
174
+ * the narrow healing a background PROBE is allowed to do (subscription-account-
175
+ * probe #8, review M1). A probe 2xx from the lightweight `GET /v1/models` attests
176
+ * the TOKEN works (so a final-401 / plain-403 / 5xx transient may be healed), but
177
+ * it does NOT prove the traffic endpoint's rate-limit / overload has recovered —
178
+ * so it MUST NOT touch `rateLimitEndAt` / `overloadUntil` (those clear only on the
179
+ * upstream's authoritative reset, or a REAL-traffic 2xx). `blocked` (a ban) is
180
+ * never cleared here. Distinct from `recordUpstreamOutcome`'s 2xx path, which is
181
+ * UNCHANGED and still clears rate + transient together because it IS traffic.
182
+ * Returns whether a transient mark was actually cleared. Does NOT emit a recovery
183
+ * signal (a probe is internal maintenance; the account is schedulable-on-read).
184
+ */
185
+ clearTransientMark(providerId: string, accountId: string): boolean;
186
+ /**
187
+ * Proactively surface accounts that transitioned unhealthy → schedulable since
188
+ * the last sweep (design D6). Clears their expired timers, emits a recovery
189
+ * signal for each through `onRecovered`, and returns the list. A `blocked`
190
+ * account never recovers here. Correctness does NOT depend on this running —
191
+ * `isSchedulable` already restores an elapsed cooldown lazily; this adds the
192
+ * proactive signal (#5/#8) + lets the daemon nudge a token refresh.
193
+ */
194
+ sweepRecoveries(now?: number): AccountRecoveryEvent[];
195
+ /** Admin-facing coarse status + cooldown-until for one account (secret-free). */
196
+ getStatus(providerId: string, accountId: string, now?: number): AccountHealthStatus;
197
+ /**
198
+ * Register a recovery listener (the OQ3 seam #5 webhooks + #8 health-cron
199
+ * consume). Returns an unsubscribe function. Two edges fire it:
200
+ * - TRAFFIC-DRIVEN: a `recordUpstreamOutcome` 2xx that clears an unhealthy
201
+ * account (guaranteed — the sweep would miss it, as the 2xx deletes the
202
+ * record first); and
203
+ * - PURE-IDLE: `sweepRecoveries` when an idle account's cooldown elapsed with
204
+ * no traffic (best-effort, on the 60s tick).
205
+ * A lazy `isSchedulable` read that heals an account does NOT emit (a request is
206
+ * already using it) — so consumers never double-count a recovery.
207
+ */
208
+ onRecovered(listener: AccountRecoveryListener): () => void;
209
+ private emit;
210
+ /**
211
+ * Register an anomaly listener (the ADDITIVE seam #5 webhooks consumes; the
212
+ * frozen `kind` discriminator on {@link AccountRecoveryEvent} anticipated it).
213
+ * Fires ONLY on the healthy→unhealthy EDGE inside `recordUpstreamOutcome`
214
+ * (de-duped: an already-unhealthy account escalating does NOT re-fire). Returns
215
+ * an unsubscribe function. Existing marking/recovery behavior is UNCHANGED.
216
+ */
217
+ onAnomaly(listener: AccountAnomalyListener): () => void;
218
+ private emitAnomaly;
219
+ /**
220
+ * Delete every EXPIRED timer field on the record in place; return whether any
221
+ * timer is STILL active (in the future). `blocked` is not a timer and is left
222
+ * untouched here (only an explicit reset / restart clears a ban).
223
+ */
224
+ private clearExpired;
225
+ private key;
226
+ private parseKey;
227
+ }
228
+ /** The shared tracker; lazily constructs a default-config instance on first use. */
229
+ declare function getSharedAccountHealth(): SubscriptionAccountHealth;
230
+ /** Install a config-tuned tracker at bootstrap (idempotent; last write wins). */
231
+ declare function setSharedAccountHealth(instance: SubscriptionAccountHealth): void;
232
+ /** Reset the shared singleton (tests / teardown only). */
233
+ declare function __resetSharedAccountHealthForTests(): void;
234
+
235
+ export { AUTH_ERROR_TTL_MS, type AccountAnomalyEvent, type AccountAnomalyListener, type AccountAnomalyState, type AccountHealthState, type AccountHealthStatus, type AccountRecoveryEvent, type AccountRecoveryListener, type HeadersLike, type HealthRecord, OVERLOAD_ENABLED_DEFAULT, OVERLOAD_TTL_MS, type RecordUpstreamOutcomeInput, SERVER_ERROR_TTL_MS, SubscriptionAccountHealth, type SubscriptionAccountHealthOptions, __resetSharedAccountHealthForTests, getSharedAccountHealth, resolveResetSeconds, setSharedAccountHealth };