@omnicross/core 0.1.2 → 0.1.3
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.
- package/dist/auth/GeminiCodeAssistProjectResolver.cjs +6 -1
- package/dist/auth/GeminiCodeAssistProjectResolver.js +6 -1
- package/dist/{chunk-SN3YWBX7.cjs → chunk-2FMI2B6V.cjs} +2329 -533
- package/dist/{chunk-XBSYYZIY.cjs → chunk-3QOSDDNI.cjs} +39 -3
- package/dist/{chunk-2FEVTJWG.js → chunk-4DECIFU7.js} +2162 -366
- package/dist/chunk-4IH4EL7M.cjs +9 -0
- package/dist/chunk-5ENKBSWO.js +311 -0
- package/dist/chunk-6RPZADX3.cjs +92 -0
- package/dist/chunk-AEOZIDEB.cjs +32 -0
- package/dist/chunk-BO4RFWBR.js +89 -0
- package/dist/{chunk-MNYKI4CI.js → chunk-CWM2ZDU5.js} +36 -0
- package/dist/chunk-CZHZGRU7.js +383 -0
- package/dist/{chunk-4NBS6KPV.cjs → chunk-DQ5VAYZ6.cjs} +7 -8
- package/dist/chunk-HUZZZ3JL.js +32 -0
- package/dist/{chunk-QOCNX236.js → chunk-IAXWICZU.js} +24 -1
- package/dist/{chunk-V5KPWNYX.cjs → chunk-JMJBSACD.cjs} +3 -3
- package/dist/chunk-L74VDN4A.cjs +32 -0
- package/dist/{chunk-74TMJA7Z.js → chunk-N5QFKSDO.js} +7 -4
- package/dist/{chunk-LKZJEL6E.cjs → chunk-Q27JY5RG.cjs} +6 -4
- package/dist/{chunk-SPVWWUHX.cjs → chunk-QWBWGODS.cjs} +24 -1
- package/dist/chunk-RPII3E6Z.cjs +145 -0
- package/dist/chunk-S6JGLF3G.cjs +89 -0
- package/dist/chunk-SVXC36MU.cjs +383 -0
- package/dist/chunk-TKJMZBAH.js +32 -0
- package/dist/{chunk-ZSVQT3PW.js → chunk-UBWEBKRC.js} +5 -6
- package/dist/chunk-UNEFIWXI.cjs +32 -0
- package/dist/chunk-VQY5W4YW.cjs +311 -0
- package/dist/chunk-WNY4WMRF.js +32 -0
- package/dist/chunk-XEKD23J5.js +9 -0
- package/dist/chunk-XTEI64OU.js +145 -0
- package/dist/chunk-XX6NQJMA.js +92 -0
- package/dist/{chunk-N3V2J5ZO.cjs → chunk-Y6OM7EV7.cjs} +7 -4
- package/dist/{chunk-745DV5FL.js → chunk-Y7FO65VT.js} +3 -3
- package/dist/{chunk-PXUJF5HS.js → chunk-ZY6KU6P3.js} +4 -2
- package/dist/completion/CompletionService.cjs +22 -15
- package/dist/completion/CompletionService.js +21 -14
- package/dist/completion/NativeSearchInjector.cjs +3 -3
- package/dist/completion/NativeSearchInjector.js +2 -2
- package/dist/completion/openrouter-headers.cjs +3 -6
- package/dist/completion/openrouter-headers.d.cts +9 -12
- package/dist/completion/openrouter-headers.d.ts +9 -12
- package/dist/completion/openrouter-headers.js +2 -5
- package/dist/completion/openrouter-models.cjs +4 -3
- package/dist/completion/openrouter-models.js +2 -1
- package/dist/completion.cjs +22 -15
- package/dist/completion.js +21 -14
- package/dist/index.cjs +139 -17
- package/dist/index.d.cts +40 -10
- package/dist/index.d.ts +40 -10
- package/dist/index.js +146 -24
- package/dist/outbound-api/routeResolver.cjs +5 -2
- package/dist/outbound-api/routeResolver.d.cts +8 -2
- package/dist/outbound-api/routeResolver.d.ts +8 -2
- package/dist/outbound-api/routeResolver.js +4 -1
- package/dist/outbound-api/types.cjs +6 -1
- package/dist/outbound-api/types.d.cts +11 -144
- package/dist/outbound-api/types.d.ts +11 -144
- package/dist/outbound-api/types.js +6 -0
- package/dist/outbound-api.cjs +133 -15
- package/dist/outbound-api.d.cts +786 -25
- package/dist/outbound-api.d.ts +786 -25
- package/dist/outbound-api.js +137 -19
- package/dist/pipeline/AuthSource.d.cts +23 -1
- package/dist/pipeline/AuthSource.d.ts +23 -1
- package/dist/pipeline/LlmConfigProviderAuth.cjs +3 -3
- package/dist/pipeline/LlmConfigProviderAuth.js +2 -2
- package/dist/pipeline/SubscriptionAccountHealth.cjs +22 -0
- package/dist/pipeline/SubscriptionAccountHealth.d.cts +235 -0
- package/dist/pipeline/SubscriptionAccountHealth.d.ts +235 -0
- package/dist/pipeline/SubscriptionAccountHealth.js +22 -0
- package/dist/pipeline/SubscriptionAuthSource.cjs +2 -2
- package/dist/pipeline/SubscriptionAuthSource.d.cts +3 -2
- package/dist/pipeline/SubscriptionAuthSource.d.ts +3 -2
- package/dist/pipeline/SubscriptionAuthSource.js +1 -1
- package/dist/pipeline/SubscriptionAuthStrategy.d.cts +24 -1
- package/dist/pipeline/SubscriptionAuthStrategy.d.ts +24 -1
- package/dist/pipeline/auditSink.cjs +14 -0
- package/dist/pipeline/auditSink.d.cts +48 -0
- package/dist/pipeline/auditSink.d.ts +48 -0
- package/dist/pipeline/auditSink.js +14 -0
- package/dist/pipeline/billingEmit.cjs +14 -0
- package/dist/pipeline/billingEmit.d.cts +49 -0
- package/dist/pipeline/billingEmit.d.ts +49 -0
- package/dist/pipeline/billingEmit.js +14 -0
- package/dist/ports/usage-event-store.d.cts +26 -1
- package/dist/ports/usage-event-store.d.ts +26 -1
- package/dist/ports.d.cts +7 -1
- package/dist/ports.d.ts +7 -1
- package/dist/provider-proxy/ProviderProxy.cjs +22 -15
- package/dist/provider-proxy/ProviderProxy.js +21 -14
- package/dist/provider-proxy/identity/SubscriptionIdentityStore.cjs +15 -0
- package/dist/provider-proxy/identity/SubscriptionIdentityStore.d.cts +121 -0
- package/dist/provider-proxy/identity/SubscriptionIdentityStore.d.ts +121 -0
- package/dist/provider-proxy/identity/SubscriptionIdentityStore.js +15 -0
- package/dist/provider-proxy/identity/fingerprintHeaders.cjs +20 -0
- package/dist/provider-proxy/identity/fingerprintHeaders.d.cts +89 -0
- package/dist/provider-proxy/identity/fingerprintHeaders.d.ts +89 -0
- package/dist/provider-proxy/identity/fingerprintHeaders.js +20 -0
- package/dist/provider-proxy/ingress/providerProxyShared.cjs +22 -15
- package/dist/provider-proxy/ingress/providerProxyShared.d.cts +11 -2
- package/dist/provider-proxy/ingress/providerProxyShared.d.ts +11 -2
- package/dist/provider-proxy/ingress/providerProxyShared.js +21 -14
- package/dist/provider-proxy/matchText.cjs +4 -2
- package/dist/provider-proxy/matchText.d.cts +14 -1
- package/dist/provider-proxy/matchText.d.ts +14 -1
- package/dist/provider-proxy/matchText.js +3 -1
- package/dist/provider-proxy/types.d.cts +23 -0
- package/dist/provider-proxy/types.d.ts +23 -0
- package/dist/provider-proxy.cjs +22 -15
- package/dist/provider-proxy.js +21 -14
- package/dist/{routeResolver-HE-ZO0fO.d.ts → routeResolver-B1NglTfe.d.ts} +36 -10
- package/dist/{routeResolver-BrbK6ja9.d.cts → routeResolver-CbG5uBgm.d.cts} +36 -10
- package/dist/transformer/transformers.cjs +7 -7
- package/dist/transformer/transformers.js +7 -7
- package/dist/transformer.cjs +5 -5
- package/dist/transformer.js +4 -4
- package/dist/types-6OUY_xfA.d.ts +830 -0
- package/dist/types-aBFFXoBz.d.cts +830 -0
- package/dist/usage/usage-recorder.cjs +2 -2
- package/dist/usage/usage-recorder.d.cts +19 -1
- package/dist/usage/usage-recorder.d.ts +19 -1
- package/dist/usage/usage-recorder.js +1 -1
- package/dist/usage.cjs +2 -2
- package/dist/usage.js +1 -1
- package/package.json +4 -2
- package/dist/chunk-3MEACFK3.js +0 -193
- package/dist/chunk-6VIXXLMX.cjs +0 -14
- package/dist/chunk-E3WHL7CO.js +0 -14
- package/dist/chunk-G2FUJNA2.cjs +0 -193
- package/dist/{chunk-UYPEN5XE.cjs → chunk-FFALUUZZ.cjs} +5 -5
- package/dist/{chunk-O466Y272.js → chunk-MQNDWYPN.js} +6 -6
package/dist/outbound-api.js
CHANGED
|
@@ -1,79 +1,197 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AUDIT_REDACTED,
|
|
3
|
+
ConcurrencyQueueFullError,
|
|
4
|
+
ConcurrencyWaitCancelledError,
|
|
5
|
+
ConcurrencyWaitTimeoutError,
|
|
6
|
+
DEFAULT_ACCOUNT_PROBE,
|
|
7
|
+
DEFAULT_CONCURRENCY_QUEUE,
|
|
8
|
+
DEFAULT_FINGERPRINT,
|
|
2
9
|
DEFAULT_OUTBOUND_PORT,
|
|
10
|
+
DEFAULT_USER_MESSAGE_QUEUE,
|
|
11
|
+
KeySpendTracker,
|
|
12
|
+
KeyedMutex,
|
|
3
13
|
OUTBOUND_API_SERVER_CONFIG_KEY,
|
|
14
|
+
OutboundApiConfigError,
|
|
4
15
|
OutboundApiServer,
|
|
16
|
+
OutboundConcurrencyGate,
|
|
5
17
|
OutboundRateLimiter,
|
|
18
|
+
SerialQueueTimeoutError,
|
|
19
|
+
UserMessageSerialQueue,
|
|
6
20
|
__resetOutboundApiServerForTests,
|
|
21
|
+
beginAuditCapture,
|
|
22
|
+
beginBillingCapture,
|
|
23
|
+
checkKeyQuota,
|
|
24
|
+
computeKeyExpiry,
|
|
25
|
+
computeVoucherGrant,
|
|
7
26
|
createNamedKey,
|
|
8
27
|
defaultServerConfig,
|
|
9
|
-
detectRequestRole,
|
|
10
|
-
endpointToIngressFormat,
|
|
11
28
|
formatUrls,
|
|
29
|
+
generateVoucherCode,
|
|
12
30
|
getOutboundApiServer,
|
|
31
|
+
handleVoucherRedeem,
|
|
13
32
|
hashKey,
|
|
33
|
+
hashVoucherCode,
|
|
34
|
+
isConcurrencyRejection,
|
|
35
|
+
isRedeemRequest,
|
|
36
|
+
isSerialQueueTimeout,
|
|
37
|
+
isUserMessageRequest,
|
|
14
38
|
loadServerConfig,
|
|
15
39
|
mergeServerConfig,
|
|
40
|
+
newVoucherId,
|
|
41
|
+
normalizeAccountProbe,
|
|
42
|
+
normalizeAudit,
|
|
43
|
+
normalizeBilling,
|
|
44
|
+
normalizeFingerprint,
|
|
45
|
+
normalizePrefixTargets,
|
|
46
|
+
normalizeProxyConfig,
|
|
47
|
+
normalizeProxySegment,
|
|
48
|
+
normalizeQueueSegments,
|
|
16
49
|
normalizeServerConfig,
|
|
50
|
+
normalizeVoucher,
|
|
51
|
+
normalizeWebhookDestination,
|
|
52
|
+
normalizeWebhookSegment,
|
|
53
|
+
randomBase62,
|
|
54
|
+
redactAuditText,
|
|
17
55
|
saveServerConfig,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
56
|
+
startOfLocalDay,
|
|
57
|
+
startOfLocalWeek,
|
|
58
|
+
toVoucherInfo,
|
|
59
|
+
verifyKey,
|
|
60
|
+
verifyPresentedKey,
|
|
61
|
+
voucherCodePrefix
|
|
62
|
+
} from "./chunk-4DECIFU7.js";
|
|
21
63
|
import "./chunk-VVEHS2LI.js";
|
|
22
64
|
import "./chunk-46RLHI7D.js";
|
|
23
65
|
import "./chunk-G2UTNSGU.js";
|
|
24
|
-
import "./chunk-MZNPGW5Q.js";
|
|
25
66
|
import "./chunk-DK4A7DLE.js";
|
|
26
|
-
import "./chunk-
|
|
27
|
-
import "./chunk-C7PSERMH.js";
|
|
28
|
-
import "./chunk-5HTVET6E.js";
|
|
67
|
+
import "./chunk-MQNDWYPN.js";
|
|
29
68
|
import "./chunk-Z7LUNECE.js";
|
|
30
69
|
import "./chunk-ZJZAOKI7.js";
|
|
31
70
|
import "./chunk-FTQ7IQUC.js";
|
|
71
|
+
import "./chunk-C7PSERMH.js";
|
|
72
|
+
import "./chunk-5HTVET6E.js";
|
|
32
73
|
import "./chunk-7VU7V2E4.js";
|
|
33
74
|
import "./chunk-ZLX3KGXX.js";
|
|
34
|
-
import "./chunk-
|
|
75
|
+
import "./chunk-CWM2ZDU5.js";
|
|
76
|
+
import "./chunk-MZNPGW5Q.js";
|
|
77
|
+
import "./chunk-XTEI64OU.js";
|
|
78
|
+
import "./chunk-XX6NQJMA.js";
|
|
79
|
+
import "./chunk-IAXWICZU.js";
|
|
80
|
+
import "./chunk-5ERIZW3D.js";
|
|
81
|
+
import "./chunk-5ENKBSWO.js";
|
|
82
|
+
import "./chunk-N5QFKSDO.js";
|
|
83
|
+
import "./chunk-AVYJ4YBN.js";
|
|
35
84
|
import "./chunk-DRWHTIIZ.js";
|
|
85
|
+
import "./chunk-WNY4WMRF.js";
|
|
86
|
+
import "./chunk-TKJMZBAH.js";
|
|
36
87
|
import "./chunk-JO5NLTLY.js";
|
|
37
|
-
import "./chunk-
|
|
88
|
+
import "./chunk-ZY6KU6P3.js";
|
|
38
89
|
import "./chunk-JWC6APFQ.js";
|
|
39
|
-
import "./chunk-5ERIZW3D.js";
|
|
40
|
-
import "./chunk-74TMJA7Z.js";
|
|
41
|
-
import "./chunk-AVYJ4YBN.js";
|
|
42
90
|
import "./chunk-H5JUT3KV.js";
|
|
43
91
|
import {
|
|
44
92
|
SUBSCRIPTION_PROVIDER_IDS,
|
|
93
|
+
classifyModelPrefix,
|
|
94
|
+
detectModelKind,
|
|
95
|
+
detectRequestRole,
|
|
45
96
|
endpointSupportsSubscription,
|
|
97
|
+
endpointToIngressFormat,
|
|
98
|
+
isKindMappedEndpoint,
|
|
46
99
|
isSubscriptionProviderId,
|
|
47
|
-
|
|
48
|
-
|
|
100
|
+
modelKindsForEndpoint,
|
|
101
|
+
parseModelRef,
|
|
102
|
+
pickModelRefFromList,
|
|
103
|
+
resolvePrefixTarget,
|
|
104
|
+
resolveRoute,
|
|
105
|
+
validateEndpointModelConfig,
|
|
106
|
+
validateServerModelConfig
|
|
107
|
+
} from "./chunk-CZHZGRU7.js";
|
|
49
108
|
import "./chunk-AQ5TNQB7.js";
|
|
109
|
+
import {
|
|
110
|
+
ENDPOINT_MODEL_KINDS
|
|
111
|
+
} from "./chunk-XEKD23J5.js";
|
|
50
112
|
import "./chunk-5ZQBEOMD.js";
|
|
113
|
+
import "./chunk-BO4RFWBR.js";
|
|
51
114
|
import "./chunk-Z7Y2NPHY.js";
|
|
52
115
|
import "./chunk-S4WBV25P.js";
|
|
53
116
|
import "./chunk-CDHS2QDC.js";
|
|
54
|
-
import "./chunk-
|
|
55
|
-
import "./chunk-E3WHL7CO.js";
|
|
117
|
+
import "./chunk-Y7FO65VT.js";
|
|
56
118
|
import "./chunk-FMOBD2OQ.js";
|
|
119
|
+
import "./chunk-HUZZZ3JL.js";
|
|
57
120
|
export {
|
|
121
|
+
AUDIT_REDACTED,
|
|
122
|
+
ConcurrencyQueueFullError,
|
|
123
|
+
ConcurrencyWaitCancelledError,
|
|
124
|
+
ConcurrencyWaitTimeoutError,
|
|
125
|
+
DEFAULT_ACCOUNT_PROBE,
|
|
126
|
+
DEFAULT_CONCURRENCY_QUEUE,
|
|
127
|
+
DEFAULT_FINGERPRINT,
|
|
58
128
|
DEFAULT_OUTBOUND_PORT,
|
|
129
|
+
DEFAULT_USER_MESSAGE_QUEUE,
|
|
130
|
+
ENDPOINT_MODEL_KINDS,
|
|
131
|
+
KeySpendTracker,
|
|
132
|
+
KeyedMutex,
|
|
59
133
|
OUTBOUND_API_SERVER_CONFIG_KEY,
|
|
134
|
+
OutboundApiConfigError,
|
|
60
135
|
OutboundApiServer,
|
|
136
|
+
OutboundConcurrencyGate,
|
|
61
137
|
OutboundRateLimiter,
|
|
62
138
|
SUBSCRIPTION_PROVIDER_IDS,
|
|
139
|
+
SerialQueueTimeoutError,
|
|
140
|
+
UserMessageSerialQueue,
|
|
63
141
|
__resetOutboundApiServerForTests,
|
|
142
|
+
beginAuditCapture,
|
|
143
|
+
beginBillingCapture,
|
|
144
|
+
checkKeyQuota,
|
|
145
|
+
classifyModelPrefix,
|
|
146
|
+
computeKeyExpiry,
|
|
147
|
+
computeVoucherGrant,
|
|
64
148
|
createNamedKey,
|
|
65
149
|
defaultServerConfig,
|
|
150
|
+
detectModelKind,
|
|
66
151
|
detectRequestRole,
|
|
67
152
|
endpointSupportsSubscription,
|
|
68
153
|
endpointToIngressFormat,
|
|
69
154
|
formatUrls,
|
|
155
|
+
generateVoucherCode,
|
|
70
156
|
getOutboundApiServer,
|
|
157
|
+
handleVoucherRedeem,
|
|
71
158
|
hashKey,
|
|
159
|
+
hashVoucherCode,
|
|
160
|
+
isConcurrencyRejection,
|
|
161
|
+
isKindMappedEndpoint,
|
|
162
|
+
isRedeemRequest,
|
|
163
|
+
isSerialQueueTimeout,
|
|
72
164
|
isSubscriptionProviderId,
|
|
165
|
+
isUserMessageRequest,
|
|
73
166
|
loadServerConfig,
|
|
74
167
|
mergeServerConfig,
|
|
168
|
+
modelKindsForEndpoint,
|
|
169
|
+
newVoucherId,
|
|
170
|
+
normalizeAccountProbe,
|
|
171
|
+
normalizeAudit,
|
|
172
|
+
normalizeBilling,
|
|
173
|
+
normalizeFingerprint,
|
|
174
|
+
normalizePrefixTargets,
|
|
175
|
+
normalizeProxyConfig,
|
|
176
|
+
normalizeProxySegment,
|
|
177
|
+
normalizeQueueSegments,
|
|
75
178
|
normalizeServerConfig,
|
|
179
|
+
normalizeVoucher,
|
|
180
|
+
normalizeWebhookDestination,
|
|
181
|
+
normalizeWebhookSegment,
|
|
182
|
+
parseModelRef,
|
|
183
|
+
pickModelRefFromList,
|
|
184
|
+
randomBase62,
|
|
185
|
+
redactAuditText,
|
|
186
|
+
resolvePrefixTarget,
|
|
76
187
|
resolveRoute,
|
|
77
188
|
saveServerConfig,
|
|
78
|
-
|
|
189
|
+
startOfLocalDay,
|
|
190
|
+
startOfLocalWeek,
|
|
191
|
+
toVoucherInfo,
|
|
192
|
+
validateEndpointModelConfig,
|
|
193
|
+
validateServerModelConfig,
|
|
194
|
+
verifyKey,
|
|
195
|
+
verifyPresentedKey,
|
|
196
|
+
voucherCodePrefix
|
|
79
197
|
};
|
|
@@ -34,6 +34,24 @@ 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;
|
|
37
55
|
}
|
|
38
56
|
/**
|
|
39
57
|
* Result of {@link AuthSource.onResult}.
|
|
@@ -74,8 +92,12 @@ interface AuthSource {
|
|
|
74
92
|
* Called when the upstream returns 401. Return `true` to ask the caller to
|
|
75
93
|
* retry once with freshly-applied headers; `false` to surface the 401.
|
|
76
94
|
* Optional — sources without a refresh notion omit it.
|
|
95
|
+
*
|
|
96
|
+
* The OPTIONAL `sessionKey` (subscription-account-scheduling, D7) lets a
|
|
97
|
+
* subscription source refresh the account the request was actually served by;
|
|
98
|
+
* BYO sources ignore it.
|
|
77
99
|
*/
|
|
78
|
-
onUnauthorized?(): Promise<boolean>;
|
|
100
|
+
onUnauthorized?(sessionKey?: string): Promise<boolean>;
|
|
79
101
|
/**
|
|
80
102
|
* Resolve the upstream URL the request should target, when the credential
|
|
81
103
|
* dictates it (e.g. a subscription profile's per-model endpoint). Returns
|
|
@@ -34,6 +34,24 @@ 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;
|
|
37
55
|
}
|
|
38
56
|
/**
|
|
39
57
|
* Result of {@link AuthSource.onResult}.
|
|
@@ -74,8 +92,12 @@ interface AuthSource {
|
|
|
74
92
|
* Called when the upstream returns 401. Return `true` to ask the caller to
|
|
75
93
|
* retry once with freshly-applied headers; `false` to surface the 401.
|
|
76
94
|
* Optional — sources without a refresh notion omit it.
|
|
95
|
+
*
|
|
96
|
+
* The OPTIONAL `sessionKey` (subscription-account-scheduling, D7) lets a
|
|
97
|
+
* subscription source refresh the account the request was actually served by;
|
|
98
|
+
* BYO sources ignore it.
|
|
77
99
|
*/
|
|
78
|
-
onUnauthorized?(): Promise<boolean>;
|
|
100
|
+
onUnauthorized?(sessionKey?: string): Promise<boolean>;
|
|
79
101
|
/**
|
|
80
102
|
* Resolve the upstream URL the request should target, when the credential
|
|
81
103
|
* 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
|
|
3
|
+
var _chunkQ27JY5RGcjs = require('../chunk-Q27JY5RG.cjs');
|
|
4
4
|
require('../chunk-A2YMUCBT.cjs');
|
|
5
|
-
require('../chunk-
|
|
5
|
+
require('../chunk-UNEFIWXI.cjs');
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
exports.LlmConfigProviderAuth =
|
|
8
|
+
exports.LlmConfigProviderAuth = _chunkQ27JY5RGcjs.LlmConfigProviderAuth;
|
|
@@ -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 };
|