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