@omnicross/core 0.1.6 → 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/auth/GeminiCodeAssistProjectResolver.cjs +4 -3
- package/dist/auth/GeminiCodeAssistProjectResolver.js +3 -2
- package/dist/{chunk-3Z5BQZFM.cjs → chunk-235MXAGX.cjs} +3 -1
- package/dist/{chunk-DLXZEZWO.cjs → chunk-2E42SAW3.cjs} +42 -4
- package/dist/{chunk-7AK7B36B.cjs → chunk-2Z4XM3H5.cjs} +6 -6
- package/dist/{chunk-OEWZUX4G.js → chunk-32O35CIF.js} +9 -20
- package/dist/chunk-3SCOLIPT.cjs +63 -0
- package/dist/{chunk-SYQF7OIR.js → chunk-3WD4HTR2.js} +2 -0
- package/dist/{chunk-SQYVORNP.cjs → chunk-4BB343BI.cjs} +527 -267
- package/dist/{chunk-AT7B7SOZ.js → chunk-5NJLQ6T6.js} +21 -10
- package/dist/chunk-5RSZYQJH.cjs +62 -0
- package/dist/{chunk-IFXJ2BG7.js → chunk-7C7DET6S.js} +51 -6
- package/dist/{chunk-UDCC7EMR.js → chunk-E3COOKUP.js} +307 -47
- package/dist/chunk-FU7EAR73.js +62 -0
- package/dist/{chunk-UX7VWA46.js → chunk-FXR6N3SR.js} +39 -1
- package/dist/{chunk-WYTEQ4Q5.cjs → chunk-GDIXXKF2.cjs} +21 -10
- package/dist/{chunk-WB6PH56J.js → chunk-GFIZ6LQI.js} +12 -8
- package/dist/chunk-GL6XM527.js +61 -0
- package/dist/{chunk-EJLH6NFT.cjs → chunk-J3QQ6JS5.cjs} +12 -8
- package/dist/{chunk-VRFBB5DB.js → chunk-MYYR3HZL.js} +4 -4
- package/dist/{chunk-YJVHCHQX.js → chunk-N7OOJI5V.js} +46 -2
- package/dist/chunk-NKVZ6Z3Y.cjs +61 -0
- package/dist/{chunk-SNYBEXLB.cjs → chunk-OJGQKHN5.cjs} +3 -1
- package/dist/chunk-OTZC4TNH.cjs +79 -0
- package/dist/{chunk-6VUQPOV3.cjs → chunk-OVQBNVSV.cjs} +10 -21
- package/dist/{chunk-4VLRHHFE.cjs → chunk-OXHNSZ53.cjs} +9 -11
- package/dist/{chunk-6CL5HTPQ.js → chunk-PEGTIPB3.js} +8 -10
- package/dist/chunk-PO3XB56Z.js +79 -0
- package/dist/{chunk-SIZQQD6T.js → chunk-RJ5ZGNI3.js} +42 -5
- package/dist/{chunk-KCVJWJST.cjs → chunk-RJUONLUQ.cjs} +47 -10
- package/dist/{chunk-BPKCU575.js → chunk-SOO562NM.js} +3 -1
- package/dist/{chunk-UNWKG6EI.cjs → chunk-XPIOJQS2.cjs} +51 -6
- package/dist/chunk-XXFYLL7R.js +63 -0
- package/dist/{chunk-YK57NMIF.cjs → chunk-YWL7YZWS.cjs} +47 -3
- package/dist/completion/CompletionService.cjs +23 -19
- package/dist/completion/CompletionService.d.cts +1 -0
- package/dist/completion/CompletionService.d.ts +1 -0
- package/dist/completion/CompletionService.js +22 -18
- package/dist/completion.cjs +23 -19
- package/dist/completion.d.cts +1 -0
- package/dist/completion.d.ts +1 -0
- package/dist/completion.js +22 -18
- package/dist/index.cjs +26 -22
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +26 -22
- 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/routeResolver.d.cts +3 -2
- package/dist/outbound-api/routeResolver.d.ts +3 -2
- package/dist/outbound-api/subscriptionRegistryPort.d.cts +1 -0
- package/dist/outbound-api/subscriptionRegistryPort.d.ts +1 -0
- package/dist/outbound-api/types.d.cts +2 -1
- package/dist/outbound-api/types.d.ts +2 -1
- package/dist/outbound-api.cjs +23 -19
- package/dist/outbound-api.d.cts +7 -5
- package/dist/outbound-api.d.ts +7 -5
- package/dist/outbound-api.js +22 -18
- package/dist/pipeline/AccountAllowanceScheduling.d.cts +2 -1
- package/dist/pipeline/AccountAllowanceScheduling.d.ts +2 -1
- 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/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 +4 -2
- package/dist/pipeline/SubscriptionAccountHealth.d.cts +32 -3
- package/dist/pipeline/SubscriptionAccountHealth.d.ts +32 -3
- package/dist/pipeline/SubscriptionAccountHealth.js +3 -1
- package/dist/pipeline/upstreamFetch.cjs +4 -3
- package/dist/pipeline/upstreamFetch.d.cts +35 -6
- package/dist/pipeline/upstreamFetch.d.ts +35 -6
- package/dist/pipeline/upstreamFetch.js +3 -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.d.cts +1 -1
- package/dist/ports.d.ts +1 -1
- package/dist/provider-proxy/ProviderProxy.cjs +23 -19
- package/dist/provider-proxy/ProviderProxy.d.cts +1 -0
- package/dist/provider-proxy/ProviderProxy.d.ts +1 -0
- package/dist/provider-proxy/ProviderProxy.js +22 -18
- 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 +23 -19
- package/dist/provider-proxy/ingress/providerProxyShared.d.cts +11 -1
- package/dist/provider-proxy/ingress/providerProxyShared.d.ts +11 -1
- package/dist/provider-proxy/ingress/providerProxyShared.js +22 -18
- package/dist/provider-proxy/matchText.cjs +2 -2
- package/dist/provider-proxy/matchText.d.cts +1 -3
- package/dist/provider-proxy/matchText.d.ts +1 -3
- package/dist/provider-proxy/matchText.js +1 -1
- package/dist/provider-proxy/types.d.cts +5 -0
- package/dist/provider-proxy/types.d.ts +5 -0
- package/dist/provider-proxy.cjs +23 -19
- package/dist/provider-proxy.d.cts +1 -0
- package/dist/provider-proxy.d.ts +1 -0
- package/dist/provider-proxy.js +22 -18
- package/dist/{routeResolver-CHTv_Bs5.d.ts → routeResolver-BxOfunbm.d.ts} +1 -1
- package/dist/{routeResolver-kepxnfcC.d.cts → routeResolver-D5OzD0iM.d.cts} +1 -1
- package/dist/transformer/transformers/AnthropicTransformer.cjs +3 -2
- package/dist/transformer/transformers/AnthropicTransformer.js +2 -1
- package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +3 -2
- package/dist/transformer/transformers/OpenAIResponseTransformer.js +2 -1
- package/dist/transformer/transformers.cjs +7 -6
- package/dist/transformer/transformers.js +6 -5
- package/dist/transformer.cjs +9 -8
- package/dist/transformer.js +8 -7
- package/dist/{types-hsoKrVQS.d.ts → types-CqZD77rS.d.ts} +39 -0
- package/dist/{types-H3wGZSOo.d.cts → types-gjJ5lJ5n.d.cts} +39 -0
- package/dist/usage/pricing-engine.cjs +2 -2
- package/dist/usage/pricing-engine.d.cts +20 -0
- package/dist/usage/pricing-engine.d.ts +20 -0
- 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
|
@@ -21,6 +21,15 @@ var PricingEngine = class {
|
|
|
21
21
|
* non-wildcard entry per model wins.
|
|
22
22
|
*/
|
|
23
23
|
cacheByModel = /* @__PURE__ */ new Map();
|
|
24
|
+
/**
|
|
25
|
+
* Last-resort fuzzy index: `[normalizedModelId, entry]` pairs over the same
|
|
26
|
+
* non-wildcard, non-openrouter rows as `cacheByModel`. Used when even the
|
|
27
|
+
* model-name fallback misses — e.g. usage recorded under a bare model id
|
|
28
|
+
* (`glm-5.2`) while the catalog only knows prefixed slugs
|
|
29
|
+
* (`cloudflare/@cf/zai-org/glm-5.2`). This is an ESTIMATE: the matched row
|
|
30
|
+
* may be an aggregate-route price rather than the direct-vendor rate.
|
|
31
|
+
*/
|
|
32
|
+
fuzzyEntries = [];
|
|
24
33
|
cacheLoaded = false;
|
|
25
34
|
/** Coalesce manual and background refreshes to prevent a catalog stampede. */
|
|
26
35
|
refreshInFlight = null;
|
|
@@ -31,9 +40,11 @@ var PricingEngine = class {
|
|
|
31
40
|
const rows = await this.store.getAll();
|
|
32
41
|
this.cache = new Map(rows.map((r) => [keyOf(r.providerId, r.modelId), r]));
|
|
33
42
|
this.cacheByModel = /* @__PURE__ */ new Map();
|
|
43
|
+
this.fuzzyEntries = [];
|
|
34
44
|
for (const r of rows) {
|
|
35
45
|
if (r.providerId === "*" || r.providerId === "openrouter" || r.source === "openrouter") continue;
|
|
36
46
|
if (!this.cacheByModel.has(r.modelId)) this.cacheByModel.set(r.modelId, r);
|
|
47
|
+
this.fuzzyEntries.push([normalizeModelId(r.modelId), r]);
|
|
37
48
|
}
|
|
38
49
|
this.cacheLoaded = true;
|
|
39
50
|
}
|
|
@@ -53,10 +64,36 @@ var PricingEngine = class {
|
|
|
53
64
|
* 2. wildcard provider ('*', modelId)
|
|
54
65
|
* 3. model name alone (any provider) — tolerates a runtime-alias vs
|
|
55
66
|
* canonical provider-id mismatch for the same model.
|
|
67
|
+
* 4. normalized fuzzy match (last resort) — matches a bare id like
|
|
68
|
+
* `glm-5.2` against prefixed catalog slugs like
|
|
69
|
+
* `cloudflare/@cf/zai-org/glm-5.2`. ESTIMATE only: the matched row may
|
|
70
|
+
* be an aggregate-route price, not the direct-vendor rate.
|
|
56
71
|
*/
|
|
57
72
|
async getEntry(providerId, modelId) {
|
|
58
73
|
await this.ensureCache();
|
|
59
|
-
|
|
74
|
+
const exact = this.cache.get(keyOf(providerId, modelId)) ?? this.cache.get(keyOf("*", modelId)) ?? this.cacheByModel.get(modelId) ?? null;
|
|
75
|
+
if (exact) return exact;
|
|
76
|
+
return this.fuzzyMatch(modelId);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Normalized substring match over the catalog's non-openrouter rows. Lowercases
|
|
80
|
+
* and strips all non-alphanumerics, then matches bidirectionally, preferring
|
|
81
|
+
* the shortest catalog key (tightest match) to reduce over-matching version
|
|
82
|
+
* variants. Returns null when nothing matches.
|
|
83
|
+
*/
|
|
84
|
+
fuzzyMatch(modelId) {
|
|
85
|
+
const normQuery = normalizeModelId(modelId);
|
|
86
|
+
if (!normQuery) return null;
|
|
87
|
+
let best = null;
|
|
88
|
+
let bestLen = Infinity;
|
|
89
|
+
for (const [key, entry] of this.fuzzyEntries) {
|
|
90
|
+
if (!key || !key.includes(normQuery) && !normQuery.includes(key)) continue;
|
|
91
|
+
if (key.length < bestLen) {
|
|
92
|
+
best = entry;
|
|
93
|
+
bestLen = key.length;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return best;
|
|
60
97
|
}
|
|
61
98
|
// ===== Cost calculation =====
|
|
62
99
|
/**
|
|
@@ -187,6 +224,7 @@ var PricingEngine = class {
|
|
|
187
224
|
}
|
|
188
225
|
};
|
|
189
226
|
var keyOf = (providerId, modelId) => `${providerId}::${modelId}`;
|
|
227
|
+
var normalizeModelId = (modelId) => (modelId ?? "").toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
190
228
|
var PROVIDER_ALIASES = {
|
|
191
229
|
vertex_ai: "gemini",
|
|
192
230
|
google: "gemini",
|
|
@@ -81,6 +81,20 @@ function flattenToolResultContent(content) {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
// src/api-converter/anthropic-to-openai.ts
|
|
84
|
+
function anthropicUsageToChatUsage(usage) {
|
|
85
|
+
const input = usage.input_tokens || 0;
|
|
86
|
+
const output = usage.output_tokens || 0;
|
|
87
|
+
const cacheRead = usage.cache_read_input_tokens || 0;
|
|
88
|
+
const cacheCreation = usage.cache_creation_input_tokens || 0;
|
|
89
|
+
const promptTokens = input + cacheRead + cacheCreation;
|
|
90
|
+
const out = {
|
|
91
|
+
prompt_tokens: promptTokens,
|
|
92
|
+
completion_tokens: output,
|
|
93
|
+
total_tokens: promptTokens + output
|
|
94
|
+
};
|
|
95
|
+
if (cacheRead > 0) out.prompt_tokens_details = { cached_tokens: cacheRead };
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
84
98
|
function convertAnthropicToOpenAI(response) {
|
|
85
99
|
const content = [];
|
|
86
100
|
const toolCalls = [];
|
|
@@ -118,11 +132,7 @@ function convertAnthropicToOpenAI(response) {
|
|
|
118
132
|
finish_reason: finishReason
|
|
119
133
|
}
|
|
120
134
|
],
|
|
121
|
-
usage:
|
|
122
|
-
prompt_tokens: response.usage.input_tokens,
|
|
123
|
-
completion_tokens: response.usage.output_tokens,
|
|
124
|
-
total_tokens: response.usage.input_tokens + response.usage.output_tokens
|
|
125
|
-
}
|
|
135
|
+
usage: anthropicUsageToChatUsage(response.usage)
|
|
126
136
|
};
|
|
127
137
|
if (reasoningContent) {
|
|
128
138
|
result.reasoning_content = reasoningContent;
|
|
@@ -352,11 +362,12 @@ async function* convertAnthropicStreamToOpenAI(anthropicStream) {
|
|
|
352
362
|
delta: {},
|
|
353
363
|
finish_reason: finishReason
|
|
354
364
|
}],
|
|
355
|
-
usage: event.usage ? {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
365
|
+
usage: event.usage ? anthropicUsageToChatUsage({
|
|
366
|
+
input_tokens: event.usage.input_tokens || 0,
|
|
367
|
+
output_tokens: event.usage.output_tokens || 0,
|
|
368
|
+
cache_read_input_tokens: event.usage.cache_read_input_tokens,
|
|
369
|
+
cache_creation_input_tokens: event.usage.cache_creation_input_tokens
|
|
370
|
+
}) : void 0
|
|
360
371
|
})}
|
|
361
372
|
|
|
362
373
|
`;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/provider-proxy/matchText.ts
|
|
2
|
+
import { createHash } from "crypto";
|
|
2
3
|
var MATCH_TEXT_PER_MESSAGE_CAP = 8192;
|
|
3
4
|
var MATCH_TEXT_RECENT_MESSAGES = 6;
|
|
4
5
|
function flattenMatchText(value) {
|
|
@@ -55,39 +56,42 @@ var SESSION_ID_CAP = 1024;
|
|
|
55
56
|
function deriveGatewaySessionKey(body, headers = {}, options = {}) {
|
|
56
57
|
const sessionHeader = firstHeaderValue(headers, ["session-id", "session_id", "x-session-id"]);
|
|
57
58
|
if (sessionHeader) {
|
|
58
|
-
return { key:
|
|
59
|
+
return { key: stableSessionDigest(sessionHeader), source: "session-header" };
|
|
59
60
|
}
|
|
60
61
|
const threadHeader = firstHeaderValue(headers, ["thread-id", "thread_id", "x-thread-id"]);
|
|
61
62
|
if (threadHeader) {
|
|
62
|
-
return { key:
|
|
63
|
+
return { key: stableSessionDigest(threadHeader), source: "thread-header" };
|
|
63
64
|
}
|
|
64
65
|
const bodySessionId = scalarSessionValue(body.session_id);
|
|
65
66
|
if (bodySessionId) {
|
|
66
|
-
return { key:
|
|
67
|
+
return { key: stableSessionDigest(bodySessionId), source: "body-session-id" };
|
|
67
68
|
}
|
|
68
69
|
const bodyThreadId = scalarSessionValue(body.thread_id ?? body.threadId);
|
|
69
70
|
if (bodyThreadId) {
|
|
70
|
-
return { key:
|
|
71
|
+
return { key: stableSessionDigest(bodyThreadId), source: "body-thread-id" };
|
|
71
72
|
}
|
|
72
73
|
const conversationId = scalarSessionValue(body.conversation_id);
|
|
73
74
|
if (conversationId) {
|
|
74
|
-
return { key:
|
|
75
|
+
return { key: stableSessionDigest(conversationId), source: "body-session-id" };
|
|
75
76
|
}
|
|
76
77
|
const promptCacheKey = scalarSessionValue(body.prompt_cache_key);
|
|
77
78
|
if (promptCacheKey) {
|
|
78
|
-
return { key:
|
|
79
|
+
return { key: stableSessionDigest(promptCacheKey), source: "prompt-cache-key" };
|
|
79
80
|
}
|
|
80
81
|
const fingerprint = deriveResponsesContentFingerprint(body);
|
|
81
82
|
if (fingerprint) {
|
|
82
|
-
return { key:
|
|
83
|
+
return { key: stableSessionDigest(fingerprint), source: "content-fingerprint" };
|
|
83
84
|
}
|
|
84
85
|
const endpoint = options.endpoint?.trim() || "responses";
|
|
85
86
|
const fallback = options.fallbackKey?.trim() || "anonymous";
|
|
86
87
|
return {
|
|
87
|
-
key:
|
|
88
|
+
key: stableSessionDigest(`${endpoint}\0${fallback}`),
|
|
88
89
|
source: "api-key-fallback"
|
|
89
90
|
};
|
|
90
91
|
}
|
|
92
|
+
function stableSessionDigest(value) {
|
|
93
|
+
return createHash("sha256").update(value, "utf8").digest("hex").slice(0, 32);
|
|
94
|
+
}
|
|
91
95
|
function firstHeaderValue(headers, names) {
|
|
92
96
|
const byLower = /* @__PURE__ */ new Map();
|
|
93
97
|
for (const [name, value] of Object.entries(headers)) {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/pipeline/AccountRouteActivity.ts
|
|
2
|
+
var ACCOUNT_ROUTE_ACTIVITY_LIMIT = 300;
|
|
3
|
+
function boundedLimit(value) {
|
|
4
|
+
if (!Number.isFinite(value)) return 100;
|
|
5
|
+
return Math.max(1, Math.min(ACCOUNT_ROUTE_ACTIVITY_LIMIT, Math.trunc(value)));
|
|
6
|
+
}
|
|
7
|
+
var AccountRouteActivityStore = class {
|
|
8
|
+
records = [];
|
|
9
|
+
sequence = 0;
|
|
10
|
+
record(input) {
|
|
11
|
+
const ts = input.ts ?? Date.now();
|
|
12
|
+
const sessionKey = input.sessionKey?.trim() || void 0;
|
|
13
|
+
const previous = sessionKey ? this.records.find((record2) => record2.providerId === input.providerId && record2.endpoint === input.endpoint && record2.sessionKey === sessionKey) : void 0;
|
|
14
|
+
const affinity = !sessionKey ? "untracked" : !previous ? "new" : previous.accountId === input.accountId ? "sticky" : "switched";
|
|
15
|
+
const record = {
|
|
16
|
+
...input,
|
|
17
|
+
id: `${ts.toString(36)}-${(this.sequence++).toString(36)}`,
|
|
18
|
+
ts,
|
|
19
|
+
sessionKey,
|
|
20
|
+
affinity,
|
|
21
|
+
...affinity === "switched" && previous ? { previousAccountId: previous.accountId } : {}
|
|
22
|
+
};
|
|
23
|
+
this.records.unshift(record);
|
|
24
|
+
if (this.records.length > ACCOUNT_ROUTE_ACTIVITY_LIMIT) {
|
|
25
|
+
this.records.length = ACCOUNT_ROUTE_ACTIVITY_LIMIT;
|
|
26
|
+
}
|
|
27
|
+
return { ...record };
|
|
28
|
+
}
|
|
29
|
+
list(query = {}) {
|
|
30
|
+
const providerId = query.providerId?.trim();
|
|
31
|
+
const accountId = query.accountId?.trim();
|
|
32
|
+
const sessionKey = query.sessionKey?.trim();
|
|
33
|
+
return this.records.filter((record) => !providerId || record.providerId === providerId).filter((record) => !accountId || record.accountId === accountId).filter((record) => !sessionKey || record.sessionKey === sessionKey).slice(0, boundedLimit(query.limit)).map((record) => ({ ...record }));
|
|
34
|
+
}
|
|
35
|
+
clear() {
|
|
36
|
+
this.records.length = 0;
|
|
37
|
+
this.sequence = 0;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Backfill a field on an already-recorded entry. Used to annotate a record
|
|
41
|
+
* AFTER the upstream body streams — e.g. a `200` whose SSE body carries a
|
|
42
|
+
* `response.failed` overload event is only detectable mid-relay, long after
|
|
43
|
+
* `record()` stamped the 200 status. `patch` is intentionally narrow: only
|
|
44
|
+
* post-hoc-observable fields belong here, never the routing-decision fields.
|
|
45
|
+
* No-op when the id has already aged out of the bounded ring.
|
|
46
|
+
*/
|
|
47
|
+
amend(id, patch) {
|
|
48
|
+
const record = this.records.find((r) => r.id === id);
|
|
49
|
+
if (record) Object.assign(record, patch);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var sharedAccountRouteActivity = new AccountRouteActivityStore();
|
|
53
|
+
function getSharedAccountRouteActivity() {
|
|
54
|
+
return sharedAccountRouteActivity;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export {
|
|
58
|
+
ACCOUNT_ROUTE_ACTIVITY_LIMIT,
|
|
59
|
+
AccountRouteActivityStore,
|
|
60
|
+
getSharedAccountRouteActivity
|
|
61
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/provider-proxy/matchText.ts
|
|
2
|
+
var _crypto = require('crypto');
|
|
2
3
|
var MATCH_TEXT_PER_MESSAGE_CAP = 8192;
|
|
3
4
|
var MATCH_TEXT_RECENT_MESSAGES = 6;
|
|
4
5
|
function flattenMatchText(value) {
|
|
@@ -55,39 +56,42 @@ var SESSION_ID_CAP = 1024;
|
|
|
55
56
|
function deriveGatewaySessionKey(body, headers = {}, options = {}) {
|
|
56
57
|
const sessionHeader = firstHeaderValue(headers, ["session-id", "session_id", "x-session-id"]);
|
|
57
58
|
if (sessionHeader) {
|
|
58
|
-
return { key:
|
|
59
|
+
return { key: stableSessionDigest(sessionHeader), source: "session-header" };
|
|
59
60
|
}
|
|
60
61
|
const threadHeader = firstHeaderValue(headers, ["thread-id", "thread_id", "x-thread-id"]);
|
|
61
62
|
if (threadHeader) {
|
|
62
|
-
return { key:
|
|
63
|
+
return { key: stableSessionDigest(threadHeader), source: "thread-header" };
|
|
63
64
|
}
|
|
64
65
|
const bodySessionId = scalarSessionValue(body.session_id);
|
|
65
66
|
if (bodySessionId) {
|
|
66
|
-
return { key:
|
|
67
|
+
return { key: stableSessionDigest(bodySessionId), source: "body-session-id" };
|
|
67
68
|
}
|
|
68
69
|
const bodyThreadId = scalarSessionValue(_nullishCoalesce(body.thread_id, () => ( body.threadId)));
|
|
69
70
|
if (bodyThreadId) {
|
|
70
|
-
return { key:
|
|
71
|
+
return { key: stableSessionDigest(bodyThreadId), source: "body-thread-id" };
|
|
71
72
|
}
|
|
72
73
|
const conversationId = scalarSessionValue(body.conversation_id);
|
|
73
74
|
if (conversationId) {
|
|
74
|
-
return { key:
|
|
75
|
+
return { key: stableSessionDigest(conversationId), source: "body-session-id" };
|
|
75
76
|
}
|
|
76
77
|
const promptCacheKey = scalarSessionValue(body.prompt_cache_key);
|
|
77
78
|
if (promptCacheKey) {
|
|
78
|
-
return { key:
|
|
79
|
+
return { key: stableSessionDigest(promptCacheKey), source: "prompt-cache-key" };
|
|
79
80
|
}
|
|
80
81
|
const fingerprint = deriveResponsesContentFingerprint(body);
|
|
81
82
|
if (fingerprint) {
|
|
82
|
-
return { key:
|
|
83
|
+
return { key: stableSessionDigest(fingerprint), source: "content-fingerprint" };
|
|
83
84
|
}
|
|
84
85
|
const endpoint = _optionalChain([options, 'access', _ => _.endpoint, 'optionalAccess', _2 => _2.trim, 'call', _3 => _3()]) || "responses";
|
|
85
86
|
const fallback = _optionalChain([options, 'access', _4 => _4.fallbackKey, 'optionalAccess', _5 => _5.trim, 'call', _6 => _6()]) || "anonymous";
|
|
86
87
|
return {
|
|
87
|
-
key:
|
|
88
|
+
key: stableSessionDigest(`${endpoint}\0${fallback}`),
|
|
88
89
|
source: "api-key-fallback"
|
|
89
90
|
};
|
|
90
91
|
}
|
|
92
|
+
function stableSessionDigest(value) {
|
|
93
|
+
return _crypto.createHash.call(void 0, "sha256").update(value, "utf8").digest("hex").slice(0, 32);
|
|
94
|
+
}
|
|
91
95
|
function firstHeaderValue(headers, names) {
|
|
92
96
|
const byLower = /* @__PURE__ */ new Map();
|
|
93
97
|
for (const [name, value] of Object.entries(headers)) {
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AnthropicTransformer
|
|
3
|
+
} from "./chunk-PEGTIPB3.js";
|
|
1
4
|
import {
|
|
2
5
|
GeminiTransformer
|
|
3
6
|
} from "./chunk-LVUCAWMK.js";
|
|
4
7
|
import {
|
|
5
8
|
OpenAIResponseTransformer
|
|
6
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-32O35CIF.js";
|
|
7
10
|
import {
|
|
8
11
|
OpenAITransformer
|
|
9
12
|
} from "./chunk-LB6EBS6Y.js";
|
|
10
|
-
import {
|
|
11
|
-
AnthropicTransformer
|
|
12
|
-
} from "./chunk-6CL5HTPQ.js";
|
|
13
13
|
import {
|
|
14
14
|
GeminiCodeAssistTransformer
|
|
15
15
|
} from "./chunk-N5T4M4GU.js";
|
|
@@ -3,6 +3,7 @@ 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"
|
|
@@ -38,7 +39,7 @@ function isBanBody(bodyText) {
|
|
|
38
39
|
return BAN_BODY_MARKERS.some((marker) => lower.includes(marker));
|
|
39
40
|
}
|
|
40
41
|
function isRecordEmpty(record) {
|
|
41
|
-
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;
|
|
42
43
|
}
|
|
43
44
|
var KEY_SEP = "\0";
|
|
44
45
|
var SubscriptionAccountHealth = class {
|
|
@@ -159,12 +160,47 @@ var SubscriptionAccountHealth = class {
|
|
|
159
160
|
this.emitAnomaly(anomaly);
|
|
160
161
|
}
|
|
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 = 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);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
162
197
|
/** Whether a record is unhealthy at `now`: blocked, or any timer still future. */
|
|
163
198
|
isUnhealthyAt(record, now) {
|
|
164
199
|
if (record.blocked) return true;
|
|
165
200
|
if (record.rateLimitEndAt !== void 0 && now < record.rateLimitEndAt) return true;
|
|
166
201
|
if (record.overloadUntil !== void 0 && now < record.overloadUntil) return true;
|
|
167
202
|
if (record.tempUnavailableUntil !== void 0 && now < record.tempUnavailableUntil) return true;
|
|
203
|
+
if (record.quotaExhaustedUntil !== void 0 && now < record.quotaExhaustedUntil) return true;
|
|
168
204
|
return false;
|
|
169
205
|
}
|
|
170
206
|
/**
|
|
@@ -201,7 +237,7 @@ var SubscriptionAccountHealth = class {
|
|
|
201
237
|
const recovered = [];
|
|
202
238
|
for (const [key, record] of this.records) {
|
|
203
239
|
if (record.blocked) continue;
|
|
204
|
-
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;
|
|
205
241
|
const active = this.clearExpired(record, now);
|
|
206
242
|
if (hadTimer && !active && isRecordEmpty(record)) {
|
|
207
243
|
const [pid, aid] = this.parseKey(key);
|
|
@@ -225,6 +261,9 @@ var SubscriptionAccountHealth = class {
|
|
|
225
261
|
const record = this.records.get(this.key(providerId, accountId));
|
|
226
262
|
if (!record) return { state: "healthy" };
|
|
227
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
|
+
}
|
|
228
267
|
if (record.rateLimitEndAt !== void 0 && now < record.rateLimitEndAt) {
|
|
229
268
|
return { state: "rate_limited", cooldownUntil: record.rateLimitEndAt };
|
|
230
269
|
}
|
|
@@ -311,6 +350,10 @@ var SubscriptionAccountHealth = class {
|
|
|
311
350
|
if (now >= record.tempUnavailableUntil) delete record.tempUnavailableUntil;
|
|
312
351
|
else active = true;
|
|
313
352
|
}
|
|
353
|
+
if (record.quotaExhaustedUntil !== void 0) {
|
|
354
|
+
if (now >= record.quotaExhaustedUntil) delete record.quotaExhaustedUntil;
|
|
355
|
+
else active = true;
|
|
356
|
+
}
|
|
314
357
|
return active;
|
|
315
358
|
}
|
|
316
359
|
key(providerId, accountId) {
|
|
@@ -338,6 +381,7 @@ export {
|
|
|
338
381
|
OVERLOAD_ENABLED_DEFAULT,
|
|
339
382
|
AUTH_ERROR_TTL_MS,
|
|
340
383
|
SERVER_ERROR_TTL_MS,
|
|
384
|
+
MAX_QUOTA_COOLDOWN_MS,
|
|
341
385
|
ACCOUNT_HEALTH_DIAGNOSTIC_LIMIT,
|
|
342
386
|
resolveResetSeconds,
|
|
343
387
|
SubscriptionAccountHealth,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;// src/pipeline/AccountRouteActivity.ts
|
|
2
|
+
var ACCOUNT_ROUTE_ACTIVITY_LIMIT = 300;
|
|
3
|
+
function boundedLimit(value) {
|
|
4
|
+
if (!Number.isFinite(value)) return 100;
|
|
5
|
+
return Math.max(1, Math.min(ACCOUNT_ROUTE_ACTIVITY_LIMIT, Math.trunc(value)));
|
|
6
|
+
}
|
|
7
|
+
var AccountRouteActivityStore = (_class = class {constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this); }
|
|
8
|
+
__init() {this.records = []}
|
|
9
|
+
__init2() {this.sequence = 0}
|
|
10
|
+
record(input) {
|
|
11
|
+
const ts = _nullishCoalesce(input.ts, () => ( Date.now()));
|
|
12
|
+
const sessionKey = _optionalChain([input, 'access', _ => _.sessionKey, 'optionalAccess', _2 => _2.trim, 'call', _3 => _3()]) || void 0;
|
|
13
|
+
const previous = sessionKey ? this.records.find((record2) => record2.providerId === input.providerId && record2.endpoint === input.endpoint && record2.sessionKey === sessionKey) : void 0;
|
|
14
|
+
const affinity = !sessionKey ? "untracked" : !previous ? "new" : previous.accountId === input.accountId ? "sticky" : "switched";
|
|
15
|
+
const record = {
|
|
16
|
+
...input,
|
|
17
|
+
id: `${ts.toString(36)}-${(this.sequence++).toString(36)}`,
|
|
18
|
+
ts,
|
|
19
|
+
sessionKey,
|
|
20
|
+
affinity,
|
|
21
|
+
...affinity === "switched" && previous ? { previousAccountId: previous.accountId } : {}
|
|
22
|
+
};
|
|
23
|
+
this.records.unshift(record);
|
|
24
|
+
if (this.records.length > ACCOUNT_ROUTE_ACTIVITY_LIMIT) {
|
|
25
|
+
this.records.length = ACCOUNT_ROUTE_ACTIVITY_LIMIT;
|
|
26
|
+
}
|
|
27
|
+
return { ...record };
|
|
28
|
+
}
|
|
29
|
+
list(query = {}) {
|
|
30
|
+
const providerId = _optionalChain([query, 'access', _4 => _4.providerId, 'optionalAccess', _5 => _5.trim, 'call', _6 => _6()]);
|
|
31
|
+
const accountId = _optionalChain([query, 'access', _7 => _7.accountId, 'optionalAccess', _8 => _8.trim, 'call', _9 => _9()]);
|
|
32
|
+
const sessionKey = _optionalChain([query, 'access', _10 => _10.sessionKey, 'optionalAccess', _11 => _11.trim, 'call', _12 => _12()]);
|
|
33
|
+
return this.records.filter((record) => !providerId || record.providerId === providerId).filter((record) => !accountId || record.accountId === accountId).filter((record) => !sessionKey || record.sessionKey === sessionKey).slice(0, boundedLimit(query.limit)).map((record) => ({ ...record }));
|
|
34
|
+
}
|
|
35
|
+
clear() {
|
|
36
|
+
this.records.length = 0;
|
|
37
|
+
this.sequence = 0;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Backfill a field on an already-recorded entry. Used to annotate a record
|
|
41
|
+
* AFTER the upstream body streams — e.g. a `200` whose SSE body carries a
|
|
42
|
+
* `response.failed` overload event is only detectable mid-relay, long after
|
|
43
|
+
* `record()` stamped the 200 status. `patch` is intentionally narrow: only
|
|
44
|
+
* post-hoc-observable fields belong here, never the routing-decision fields.
|
|
45
|
+
* No-op when the id has already aged out of the bounded ring.
|
|
46
|
+
*/
|
|
47
|
+
amend(id, patch) {
|
|
48
|
+
const record = this.records.find((r) => r.id === id);
|
|
49
|
+
if (record) Object.assign(record, patch);
|
|
50
|
+
}
|
|
51
|
+
}, _class);
|
|
52
|
+
var sharedAccountRouteActivity = new AccountRouteActivityStore();
|
|
53
|
+
function getSharedAccountRouteActivity() {
|
|
54
|
+
return sharedAccountRouteActivity;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
exports.ACCOUNT_ROUTE_ACTIVITY_LIMIT = ACCOUNT_ROUTE_ACTIVITY_LIMIT; exports.AccountRouteActivityStore = AccountRouteActivityStore; exports.getSharedAccountRouteActivity = getSharedAccountRouteActivity;
|
|
@@ -78,7 +78,9 @@ var UsageRecorder = class {
|
|
|
78
78
|
costSavedByCacheUsd,
|
|
79
79
|
rawUsage: input.rawUsage != null ? safeStringify(input.rawUsage) : null,
|
|
80
80
|
runId: _nullishCoalesce(input.runId, () => ( null)),
|
|
81
|
-
eventId: _nullishCoalesce(input.eventId, () => ( null))
|
|
81
|
+
eventId: _nullishCoalesce(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);
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;// src/pipeline/ServerOverloadCounter.ts
|
|
2
|
+
var OVERLOAD_RECENT_LIMIT = 64;
|
|
3
|
+
var OVERLOAD_ENTRY_TTL_MS = 24 * 60 * 6e4;
|
|
4
|
+
function entryKey(providerId, accountId, endpoint) {
|
|
5
|
+
return `${providerId}\0${accountId}\0${endpoint}`;
|
|
6
|
+
}
|
|
7
|
+
var ServerOverloadCounterStore = (_class = class {constructor() { _class.prototype.__init.call(this); }
|
|
8
|
+
__init() {this.entries = /* @__PURE__ */ new Map()}
|
|
9
|
+
/**
|
|
10
|
+
* Record one overload event. Creates the entry on first sight, then bumps
|
|
11
|
+
* `count`, `lastTs`, and prepends the event to the bounded `recent` ring.
|
|
12
|
+
*/
|
|
13
|
+
recordOverload(input, now = Date.now()) {
|
|
14
|
+
const key = entryKey(input.providerId, input.accountId, input.endpoint);
|
|
15
|
+
const existing = this.entries.get(key);
|
|
16
|
+
if (existing) {
|
|
17
|
+
existing.count += 1;
|
|
18
|
+
existing.lastTs = now;
|
|
19
|
+
existing.recent.unshift(now);
|
|
20
|
+
if (existing.recent.length > OVERLOAD_RECENT_LIMIT) {
|
|
21
|
+
existing.recent.length = OVERLOAD_RECENT_LIMIT;
|
|
22
|
+
}
|
|
23
|
+
return { ...existing, recent: [...existing.recent] };
|
|
24
|
+
}
|
|
25
|
+
const entry = {
|
|
26
|
+
providerId: input.providerId,
|
|
27
|
+
accountId: input.accountId,
|
|
28
|
+
endpoint: input.endpoint,
|
|
29
|
+
count: 1,
|
|
30
|
+
firstTs: now,
|
|
31
|
+
lastTs: now,
|
|
32
|
+
recent: [now]
|
|
33
|
+
};
|
|
34
|
+
this.entries.set(key, entry);
|
|
35
|
+
return { ...entry, recent: [...entry.recent] };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Snapshot all (optionally filtered) entries, pruning stale ones first. Returns
|
|
39
|
+
* copies — callers (admin API → JSON) never see the live mutable entries.
|
|
40
|
+
*/
|
|
41
|
+
list(query = {}, now = Date.now()) {
|
|
42
|
+
const providerId = _optionalChain([query, 'access', _ => _.providerId, 'optionalAccess', _2 => _2.trim, 'call', _3 => _3()]);
|
|
43
|
+
const accountId = _optionalChain([query, 'access', _4 => _4.accountId, 'optionalAccess', _5 => _5.trim, 'call', _6 => _6()]);
|
|
44
|
+
const out = [];
|
|
45
|
+
for (const [key, entry] of this.entries) {
|
|
46
|
+
if (now - entry.lastTs > OVERLOAD_ENTRY_TTL_MS) {
|
|
47
|
+
this.entries.delete(key);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (providerId && entry.providerId !== providerId) continue;
|
|
51
|
+
if (accountId && entry.accountId !== accountId) continue;
|
|
52
|
+
out.push({ ...entry, recent: [...entry.recent] });
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
clear() {
|
|
57
|
+
this.entries.clear();
|
|
58
|
+
}
|
|
59
|
+
}, _class);
|
|
60
|
+
var sharedStore = null;
|
|
61
|
+
function getSharedOverloadCounter() {
|
|
62
|
+
if (!sharedStore) sharedStore = new ServerOverloadCounterStore();
|
|
63
|
+
return sharedStore;
|
|
64
|
+
}
|
|
65
|
+
function setSharedOverloadCounter(instance) {
|
|
66
|
+
sharedStore = instance;
|
|
67
|
+
}
|
|
68
|
+
function __resetSharedOverloadCounterForTests() {
|
|
69
|
+
sharedStore = null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
exports.OVERLOAD_RECENT_LIMIT = OVERLOAD_RECENT_LIMIT; exports.OVERLOAD_ENTRY_TTL_MS = OVERLOAD_ENTRY_TTL_MS; exports.ServerOverloadCounterStore = ServerOverloadCounterStore; exports.getSharedOverloadCounter = getSharedOverloadCounter; exports.setSharedOverloadCounter = setSharedOverloadCounter; exports.__resetSharedOverloadCounterForTests = __resetSharedOverloadCounterForTests;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunk5RSZYQJHcjs = require('./chunk-5RSZYQJH.cjs');
|
|
5
|
+
|
|
6
|
+
// src/transformer/transformers/OpenAIResponseTransformer.ts
|
|
2
7
|
var OpenAIResponseTransformer = (_class = class {constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this); }
|
|
3
8
|
static __initStatic() {this.TransformerName = "openai-response"}
|
|
4
9
|
__init() {this.name = "openai-response"}
|
|
@@ -433,11 +438,7 @@ function convertResponseApiJsonToOpenAI(data) {
|
|
|
433
438
|
finish_reason: toolCalls.length > 0 ? "tool_calls" : "stop"
|
|
434
439
|
}
|
|
435
440
|
],
|
|
436
|
-
usage:
|
|
437
|
-
prompt_tokens: usage.input_tokens || 0,
|
|
438
|
-
completion_tokens: usage.output_tokens || 0,
|
|
439
|
-
total_tokens: (usage.input_tokens || 0) + (usage.output_tokens || 0)
|
|
440
|
-
} : void 0
|
|
441
|
+
usage: _chunk5RSZYQJHcjs.responsesUsageToChatUsage.call(void 0, usage)
|
|
441
442
|
};
|
|
442
443
|
}
|
|
443
444
|
function convertOpenAIJsonToResponseApi(data, codexTools) {
|
|
@@ -475,11 +476,7 @@ function convertOpenAIJsonToResponseApi(data, codexTools) {
|
|
|
475
476
|
status: "completed",
|
|
476
477
|
model: data.model || "unknown",
|
|
477
478
|
output,
|
|
478
|
-
usage:
|
|
479
|
-
input_tokens: usage.prompt_tokens || 0,
|
|
480
|
-
output_tokens: usage.completion_tokens || 0,
|
|
481
|
-
total_tokens: usage.total_tokens || (usage.prompt_tokens || 0) + (usage.completion_tokens || 0)
|
|
482
|
-
} : void 0
|
|
479
|
+
usage: _chunk5RSZYQJHcjs.chatUsageToResponsesUsage.call(void 0, usage)
|
|
483
480
|
};
|
|
484
481
|
}
|
|
485
482
|
function convertResponseApiStreamToOpenAI(responseApiStream) {
|
|
@@ -589,11 +586,7 @@ function convertResponseApiStreamToOpenAI(responseApiStream) {
|
|
|
589
586
|
case "response.completed": {
|
|
590
587
|
const resp = event.response;
|
|
591
588
|
const respUsage = _optionalChain([resp, 'optionalAccess', _32 => _32.usage]);
|
|
592
|
-
const usage =
|
|
593
|
-
prompt_tokens: respUsage.input_tokens || 0,
|
|
594
|
-
completion_tokens: respUsage.output_tokens || 0,
|
|
595
|
-
total_tokens: (respUsage.input_tokens || 0) + (respUsage.output_tokens || 0)
|
|
596
|
-
} : void 0;
|
|
589
|
+
const usage = _chunk5RSZYQJHcjs.responsesUsageToChatUsage.call(void 0, respUsage);
|
|
597
590
|
emitChunk([{ index: 0, delta: {}, finish_reason: hasToolCalls ? "tool_calls" : "stop" }], usage);
|
|
598
591
|
safeEnqueue("data: [DONE]\n\n");
|
|
599
592
|
break;
|
|
@@ -801,11 +794,7 @@ function convertOpenAIStreamToResponseApi(openaiStream, codexTools) {
|
|
|
801
794
|
status: "completed",
|
|
802
795
|
model,
|
|
803
796
|
output,
|
|
804
|
-
usage: chunk.usage
|
|
805
|
-
input_tokens: chunk.usage.prompt_tokens || 0,
|
|
806
|
-
output_tokens: chunk.usage.completion_tokens || 0,
|
|
807
|
-
total_tokens: chunk.usage.total_tokens || 0
|
|
808
|
-
} : void 0
|
|
797
|
+
usage: _chunk5RSZYQJHcjs.chatUsageToResponsesUsage.call(void 0, chunk.usage)
|
|
809
798
|
}
|
|
810
799
|
});
|
|
811
800
|
}
|