@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
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
collectMatchText,
|
|
3
|
-
deriveGatewaySessionKey,
|
|
4
|
-
deriveSubscriptionSessionKey
|
|
5
|
-
} from "./chunk-WB6PH56J.js";
|
|
6
1
|
import {
|
|
7
2
|
streamSSEResponse
|
|
8
3
|
} from "./chunk-VVEHS2LI.js";
|
|
9
4
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
injectExtendedContextBeta
|
|
14
|
-
} from "./chunk-MZNPGW5Q.js";
|
|
5
|
+
AnthropicTransformer,
|
|
6
|
+
resolveAnthropicMaxTokens
|
|
7
|
+
} from "./chunk-PEGTIPB3.js";
|
|
15
8
|
import {
|
|
16
9
|
GeminiTransformer
|
|
17
10
|
} from "./chunk-LVUCAWMK.js";
|
|
18
11
|
import {
|
|
19
12
|
OpenAIResponseTransformer
|
|
20
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-32O35CIF.js";
|
|
21
14
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
} from "./chunk-6CL5HTPQ.js";
|
|
15
|
+
TransformerChainExecutor
|
|
16
|
+
} from "./chunk-WNKWAEUR.js";
|
|
25
17
|
import {
|
|
26
|
-
|
|
27
|
-
} from "./chunk-
|
|
18
|
+
injectExtendedContextBeta
|
|
19
|
+
} from "./chunk-MZNPGW5Q.js";
|
|
20
|
+
import {
|
|
21
|
+
DEFAULT_CODEX_CLI_HEADERS,
|
|
22
|
+
NEVER_FORWARD_HEADERS,
|
|
23
|
+
codexAcceptHeader,
|
|
24
|
+
extractCodexClientHeaders,
|
|
25
|
+
fillMissingHeaders,
|
|
26
|
+
flattenHeaderValue
|
|
27
|
+
} from "./chunk-XXFYLL7R.js";
|
|
28
28
|
import {
|
|
29
29
|
getSharedIdentityStore
|
|
30
30
|
} from "./chunk-XTEI64OU.js";
|
|
@@ -32,22 +32,36 @@ import {
|
|
|
32
32
|
applyFingerprint,
|
|
33
33
|
captureCallerIdentity
|
|
34
34
|
} from "./chunk-XX6NQJMA.js";
|
|
35
|
+
import {
|
|
36
|
+
collectMatchText,
|
|
37
|
+
deriveGatewaySessionKey,
|
|
38
|
+
deriveSubscriptionSessionKey
|
|
39
|
+
} from "./chunk-GFIZ6LQI.js";
|
|
40
|
+
import {
|
|
41
|
+
emitWebhookEvent
|
|
42
|
+
} from "./chunk-OE6TDIWW.js";
|
|
43
|
+
import {
|
|
44
|
+
getGeminiCodeAssistResolver
|
|
45
|
+
} from "./chunk-DRWHTIIZ.js";
|
|
46
|
+
import {
|
|
47
|
+
resolveProviderChain
|
|
48
|
+
} from "./chunk-JWC6APFQ.js";
|
|
35
49
|
import {
|
|
36
50
|
resolveSubscriptionChain
|
|
37
51
|
} from "./chunk-5ERIZW3D.js";
|
|
52
|
+
import {
|
|
53
|
+
getSharedOverloadCounter
|
|
54
|
+
} from "./chunk-PO3XB56Z.js";
|
|
38
55
|
import {
|
|
39
56
|
getSharedAccountHealth,
|
|
40
57
|
resolveResetSeconds
|
|
41
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-N7OOJI5V.js";
|
|
42
59
|
import {
|
|
43
60
|
SubscriptionAuthSource
|
|
44
61
|
} from "./chunk-23S5OPIO.js";
|
|
45
62
|
import {
|
|
46
63
|
serializeError
|
|
47
64
|
} from "./chunk-AVYJ4YBN.js";
|
|
48
|
-
import {
|
|
49
|
-
emitWebhookEvent
|
|
50
|
-
} from "./chunk-OE6TDIWW.js";
|
|
51
65
|
import {
|
|
52
66
|
isAccountAllowanceExhaustedError
|
|
53
67
|
} from "./chunk-OPRS4IQZ.js";
|
|
@@ -62,9 +76,6 @@ import {
|
|
|
62
76
|
LlmConfigProviderAuth,
|
|
63
77
|
getProviderHeaders
|
|
64
78
|
} from "./chunk-ZY6KU6P3.js";
|
|
65
|
-
import {
|
|
66
|
-
resolveProviderChain
|
|
67
|
-
} from "./chunk-JWC6APFQ.js";
|
|
68
79
|
import {
|
|
69
80
|
beginBillingCapture
|
|
70
81
|
} from "./chunk-WLYIIEAF.js";
|
|
@@ -90,14 +101,20 @@ import {
|
|
|
90
101
|
} from "./chunk-H5JUT3KV.js";
|
|
91
102
|
import {
|
|
92
103
|
beginAuditCapture
|
|
93
|
-
} from "./chunk-
|
|
104
|
+
} from "./chunk-7C7DET6S.js";
|
|
94
105
|
import {
|
|
95
106
|
convertAnthropicToOpenAI,
|
|
96
107
|
convertOpenAIToAnthropic
|
|
97
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-5NJLQ6T6.js";
|
|
98
109
|
import {
|
|
99
110
|
fetchUpstream
|
|
100
|
-
} from "./chunk-
|
|
111
|
+
} from "./chunk-RJ5ZGNI3.js";
|
|
112
|
+
import {
|
|
113
|
+
getSharedAccountAllowanceStore
|
|
114
|
+
} from "./chunk-MKF46GNZ.js";
|
|
115
|
+
import {
|
|
116
|
+
getSharedAccountRouteActivity
|
|
117
|
+
} from "./chunk-GL6XM527.js";
|
|
101
118
|
import {
|
|
102
119
|
applyAugmentation
|
|
103
120
|
} from "./chunk-Y7FO65VT.js";
|
|
@@ -479,6 +496,66 @@ var ProviderProxyRouteMap = class {
|
|
|
479
496
|
}
|
|
480
497
|
};
|
|
481
498
|
|
|
499
|
+
// src/provider-proxy/identity/claudeCodeHeaders.ts
|
|
500
|
+
var DEFAULT_ANTHROPIC_VERSION = "2023-06-01";
|
|
501
|
+
var OAUTH_BETA = "oauth-2025-04-20";
|
|
502
|
+
var CLAUDE_CODE_BETA = "claude-code-20250219";
|
|
503
|
+
var INTERLEAVED_THINKING_BETA = "interleaved-thinking-2025-05-14";
|
|
504
|
+
var TOOL_STREAMING_BETA = "fine-grained-tool-streaming-2025-05-14";
|
|
505
|
+
var DEFAULT_CLAUDE_CODE_HEADERS = Object.freeze({
|
|
506
|
+
"user-agent": "claude-cli/1.0.119 (external, cli)",
|
|
507
|
+
"x-app": "cli",
|
|
508
|
+
accept: "application/json",
|
|
509
|
+
"accept-language": "*",
|
|
510
|
+
"sec-fetch-mode": "cors",
|
|
511
|
+
"anthropic-dangerous-direct-browser-access": "true",
|
|
512
|
+
"x-stainless-lang": "js",
|
|
513
|
+
"x-stainless-package-version": "0.55.1",
|
|
514
|
+
"x-stainless-os": "Windows",
|
|
515
|
+
"x-stainless-arch": "x64",
|
|
516
|
+
"x-stainless-runtime": "node",
|
|
517
|
+
"x-stainless-runtime-version": "v20.19.2",
|
|
518
|
+
"x-stainless-retry-count": "0",
|
|
519
|
+
"x-stainless-timeout": "60"
|
|
520
|
+
});
|
|
521
|
+
var FORCED_ACCEPT_ENCODING = "identity";
|
|
522
|
+
var CLAUDE_FORWARD_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
523
|
+
"accept",
|
|
524
|
+
"accept-language",
|
|
525
|
+
"sec-fetch-mode",
|
|
526
|
+
"user-agent",
|
|
527
|
+
"x-app",
|
|
528
|
+
"anthropic-dangerous-direct-browser-access",
|
|
529
|
+
"anthropic-version"
|
|
530
|
+
]);
|
|
531
|
+
var STAINLESS_PREFIX = "x-stainless-";
|
|
532
|
+
function extractClaudeClientHeaders(reqHeaders) {
|
|
533
|
+
const out = {};
|
|
534
|
+
for (const [rawKey, rawVal] of Object.entries(reqHeaders)) {
|
|
535
|
+
const key = rawKey.toLowerCase();
|
|
536
|
+
if (NEVER_FORWARD_HEADERS.has(key)) continue;
|
|
537
|
+
if (!CLAUDE_FORWARD_ALLOWLIST.has(key) && !key.startsWith(STAINLESS_PREFIX)) continue;
|
|
538
|
+
const value = flattenHeaderValue(rawVal);
|
|
539
|
+
if (value !== void 0) out[key] = value;
|
|
540
|
+
}
|
|
541
|
+
return out;
|
|
542
|
+
}
|
|
543
|
+
function buildAnthropicBeta(model, callerBeta) {
|
|
544
|
+
const isHaiku = typeof model === "string" && model.toLowerCase().includes("haiku");
|
|
545
|
+
const baseline = isHaiku ? [OAUTH_BETA, INTERLEAVED_THINKING_BETA] : [CLAUDE_CODE_BETA, OAUTH_BETA, INTERLEAVED_THINKING_BETA, TOOL_STREAMING_BETA];
|
|
546
|
+
const seen = /* @__PURE__ */ new Set();
|
|
547
|
+
const out = [];
|
|
548
|
+
const add = (flag) => {
|
|
549
|
+
const trimmed = flag.trim();
|
|
550
|
+
if (!trimmed || seen.has(trimmed)) return;
|
|
551
|
+
seen.add(trimmed);
|
|
552
|
+
out.push(trimmed);
|
|
553
|
+
};
|
|
554
|
+
baseline.forEach(add);
|
|
555
|
+
if (callerBeta) callerBeta.split(",").forEach(add);
|
|
556
|
+
return out.join(",");
|
|
557
|
+
}
|
|
558
|
+
|
|
482
559
|
// src/provider-proxy/usage/recordAnthropicUsage.ts
|
|
483
560
|
function readAnthropicUsage(usage) {
|
|
484
561
|
if (!usage) return null;
|
|
@@ -653,7 +730,7 @@ async function relaySseBody(res, body, options) {
|
|
|
653
730
|
res.end();
|
|
654
731
|
}
|
|
655
732
|
}
|
|
656
|
-
async function relayResponse(res, providerResponse, isStream, rewriteModel, usageTap) {
|
|
733
|
+
async function relayResponse(res, providerResponse, isStream, rewriteModel, usageTap, onSseEvent) {
|
|
657
734
|
const contentType = providerResponse.headers.get("Content-Type") ?? "";
|
|
658
735
|
const status = providerResponse.status && providerResponse.status >= 100 ? providerResponse.status : 200;
|
|
659
736
|
const upstreamIsSse = contentType.includes("text/event-stream");
|
|
@@ -667,13 +744,16 @@ async function relayResponse(res, providerResponse, isStream, rewriteModel, usag
|
|
|
667
744
|
res.end();
|
|
668
745
|
return null;
|
|
669
746
|
}
|
|
670
|
-
if (rewriteModel || usageTap) {
|
|
747
|
+
if (rewriteModel || usageTap || onSseEvent) {
|
|
671
748
|
let capturedUsage = null;
|
|
672
749
|
await relaySseBody(res, providerResponse.body, {
|
|
673
750
|
rewriteModel,
|
|
674
|
-
onSseEvent: usageTap ? (event) => {
|
|
675
|
-
|
|
676
|
-
if (
|
|
751
|
+
onSseEvent: onSseEvent || usageTap ? (event) => {
|
|
752
|
+
onSseEvent?.(event);
|
|
753
|
+
if (usageTap) {
|
|
754
|
+
const raw = usageTap.extractUsage(event);
|
|
755
|
+
if (raw) capturedUsage = raw;
|
|
756
|
+
}
|
|
677
757
|
} : void 0
|
|
678
758
|
});
|
|
679
759
|
if (capturedUsage) usageTap.onUsage(capturedUsage);
|
|
@@ -985,7 +1065,16 @@ async function runPipeline(anthropicBody, plan, reportSelection) {
|
|
|
985
1065
|
return fetchUpstream(
|
|
986
1066
|
url,
|
|
987
1067
|
{ method: "POST", headers, body: JSON.stringify(body) },
|
|
988
|
-
{
|
|
1068
|
+
{
|
|
1069
|
+
providerId: proxyProviderId(plan),
|
|
1070
|
+
accountId: proxyAccountId,
|
|
1071
|
+
routeActivity: plan.isSubscription ? {
|
|
1072
|
+
endpoint: "messages",
|
|
1073
|
+
sessionKey: plan.sessionKey,
|
|
1074
|
+
sessionSource: plan.sessionKey ? "content-fingerprint" : "none",
|
|
1075
|
+
model: resolvedModel
|
|
1076
|
+
} : void 0
|
|
1077
|
+
}
|
|
989
1078
|
).then((r) => {
|
|
990
1079
|
rawStatus = r.status;
|
|
991
1080
|
return r;
|
|
@@ -1012,7 +1101,8 @@ async function runSubscriptionSameFormatFetch(rawBody, plan, reportSelection, op
|
|
|
1012
1101
|
reportSelection?.(accountId, isActive, remapped);
|
|
1013
1102
|
}
|
|
1014
1103
|
});
|
|
1015
|
-
|
|
1104
|
+
const isClaudeSubscription = plan.isSubscription && plan.transformerProvider.name === "claude";
|
|
1105
|
+
if (isClaudeSubscription) {
|
|
1016
1106
|
applyFingerprint(
|
|
1017
1107
|
getSharedIdentityStore(),
|
|
1018
1108
|
headers,
|
|
@@ -1021,16 +1111,36 @@ async function runSubscriptionSameFormatFetch(rawBody, plan, reportSelection, op
|
|
|
1021
1111
|
options.callerIdentity
|
|
1022
1112
|
);
|
|
1023
1113
|
}
|
|
1114
|
+
if (isClaudeSubscription) {
|
|
1115
|
+
fillMissingHeaders(headers, options.callerClientHeaders ?? {});
|
|
1116
|
+
fillMissingHeaders(headers, DEFAULT_CLAUDE_CODE_HEADERS);
|
|
1117
|
+
}
|
|
1118
|
+
fillMissingHeaders(headers, { "anthropic-version": DEFAULT_ANTHROPIC_VERSION });
|
|
1119
|
+
headers["accept-encoding"] = FORCED_ACCEPT_ENCODING;
|
|
1024
1120
|
const applyRemap = remappedModel !== void 0 && outboundRemapApplies(plan);
|
|
1025
1121
|
const outboundBody = applyRemap ? rewriteBodyModel(rawBody, remappedModel) : rawBody;
|
|
1026
1122
|
const outboundModel = applyRemap ? remappedModel : plan.resolvedModel;
|
|
1123
|
+
if (isClaudeSubscription) {
|
|
1124
|
+
headers["anthropic-beta"] = buildAnthropicBeta(outboundModel, options.callerAnthropicBeta);
|
|
1125
|
+
} else if (options.callerAnthropicBeta) {
|
|
1126
|
+
fillMissingHeaders(headers, { "anthropic-beta": options.callerAnthropicBeta });
|
|
1127
|
+
}
|
|
1027
1128
|
console.info(
|
|
1028
1129
|
`[ProviderProxy:anthropic] (subscription same-format) -> ${plan.upstreamUrl} model=${outboundModel} stream=${plan.isStream}`
|
|
1029
1130
|
);
|
|
1030
1131
|
const response = await fetchUpstream(
|
|
1031
1132
|
plan.upstreamUrl,
|
|
1032
1133
|
{ method: "POST", headers, body: outboundBody },
|
|
1033
|
-
{
|
|
1134
|
+
{
|
|
1135
|
+
providerId: proxyProviderId(plan),
|
|
1136
|
+
accountId: proxyAccountId,
|
|
1137
|
+
routeActivity: plan.isSubscription ? {
|
|
1138
|
+
endpoint: "messages",
|
|
1139
|
+
sessionKey: plan.sessionKey,
|
|
1140
|
+
sessionSource: plan.sessionKey ? "content-fingerprint" : "none",
|
|
1141
|
+
model: outboundModel
|
|
1142
|
+
} : void 0
|
|
1143
|
+
}
|
|
1034
1144
|
);
|
|
1035
1145
|
return { response, rawStatus: response.status };
|
|
1036
1146
|
}
|
|
@@ -1370,7 +1480,12 @@ async function handleAnthropicMessagesRequest(req, res, route, deps) {
|
|
|
1370
1480
|
const callerBetaRaw = req.headers["anthropic-beta"];
|
|
1371
1481
|
const callerAnthropicBeta = Array.isArray(callerBetaRaw) ? callerBetaRaw.join(",") : callerBetaRaw;
|
|
1372
1482
|
const callerIdentity = captureCallerIdentity(getSharedIdentityStore(), req.headers);
|
|
1373
|
-
|
|
1483
|
+
const callerClientHeaders = extractClaudeClientHeaders(req.headers);
|
|
1484
|
+
await handleAnthropicMessagesByo(res, rawBody, route, deps, {
|
|
1485
|
+
callerAnthropicBeta,
|
|
1486
|
+
callerIdentity,
|
|
1487
|
+
callerClientHeaders
|
|
1488
|
+
});
|
|
1374
1489
|
return;
|
|
1375
1490
|
}
|
|
1376
1491
|
const hints = route.anthropicSdkHints;
|
|
@@ -1957,6 +2072,8 @@ function emitResponsesUsageRecord(recorder, rawUsage, attribution) {
|
|
|
1957
2072
|
providerId: attribution.providerId,
|
|
1958
2073
|
model: attribution.model,
|
|
1959
2074
|
apiKeyId: attribution.apiKeyId,
|
|
2075
|
+
cacheKeySource: attribution.cacheKeySource,
|
|
2076
|
+
cacheKeyInjected: attribution.cacheKeyInjected,
|
|
1960
2077
|
auditResponse: attribution.auditResponse,
|
|
1961
2078
|
engineOrigin: "codex-ingress",
|
|
1962
2079
|
usage: tapped,
|
|
@@ -1981,12 +2098,72 @@ function recordResponsesStreamUsage(recorder, rawUsage, attribution) {
|
|
|
1981
2098
|
}
|
|
1982
2099
|
}
|
|
1983
2100
|
|
|
2101
|
+
// src/provider-proxy/ingress/codexUsageLimitDetection.ts
|
|
2102
|
+
var PROVIDER_ID = "codex";
|
|
2103
|
+
var DEFAULT_QUOTA_COOLDOWN_MS = 5 * 6e4;
|
|
2104
|
+
var QUOTA_EXHAUSTED_PERCENT = 90;
|
|
2105
|
+
function parseTryAgainDeadline(bodyText) {
|
|
2106
|
+
const match = bodyText.match(/try again (?:at|on)\s+(.+?)(?:[.\n]|$)/i);
|
|
2107
|
+
if (!match) return void 0;
|
|
2108
|
+
const cleaned = match[1].replace(/(\d+)(st|nd|rd|th)/giu, "$1").trim();
|
|
2109
|
+
const ms = Date.parse(cleaned);
|
|
2110
|
+
return Number.isFinite(ms) ? ms : void 0;
|
|
2111
|
+
}
|
|
2112
|
+
function deadlineFromAllowanceSnapshot(accountId, now) {
|
|
2113
|
+
const snapshot = getSharedAccountAllowanceStore().get(PROVIDER_ID, accountId, now);
|
|
2114
|
+
if (!snapshot) return void 0;
|
|
2115
|
+
const candidates = snapshot.windows.filter(
|
|
2116
|
+
(w) => typeof w.usedPercent === "number" && w.usedPercent >= QUOTA_EXHAUSTED_PERCENT && typeof w.resetsAt === "string"
|
|
2117
|
+
).map((w) => ({ ms: Date.parse(w.resetsAt), usedPercent: w.usedPercent })).filter((x) => Number.isFinite(x.ms) && x.ms > now).sort((a, b) => b.usedPercent - a.usedPercent);
|
|
2118
|
+
return candidates[0]?.ms;
|
|
2119
|
+
}
|
|
2120
|
+
function resolveCodexQuotaDeadline(accountId, bodyText, now = Date.now()) {
|
|
2121
|
+
const parsed = parseTryAgainDeadline(bodyText);
|
|
2122
|
+
const parsedDeadline = parsed !== void 0 && parsed > now ? parsed : void 0;
|
|
2123
|
+
return deadlineFromAllowanceSnapshot(accountId, now) ?? parsedDeadline ?? now + DEFAULT_QUOTA_COOLDOWN_MS;
|
|
2124
|
+
}
|
|
2125
|
+
function markCodexUsageLimitExhaustion(accountId, bodyText, now = Date.now()) {
|
|
2126
|
+
if (!accountId) return;
|
|
2127
|
+
const deadline = resolveCodexQuotaDeadline(accountId, bodyText, now);
|
|
2128
|
+
getSharedAccountHealth().markQuotaExhausted(PROVIDER_ID, accountId, deadline, now);
|
|
2129
|
+
}
|
|
2130
|
+
|
|
1984
2131
|
// src/provider-proxy/ingress/openaiResponsesIngress.ts
|
|
2132
|
+
var SERVER_OVERLOADED_CODES = /* @__PURE__ */ new Set(["server_is_overloaded", "slow_down"]);
|
|
2133
|
+
function isCodexServerOverloadEvent(event) {
|
|
2134
|
+
if (event["type"] !== "response.failed") return false;
|
|
2135
|
+
const error = event["response"]?.["error"];
|
|
2136
|
+
const code = error?.["code"];
|
|
2137
|
+
return typeof code === "string" && SERVER_OVERLOADED_CODES.has(code);
|
|
2138
|
+
}
|
|
1985
2139
|
function isOpenAIResponsesRequest(method, url) {
|
|
1986
2140
|
if (method !== "POST" || !url) return false;
|
|
1987
2141
|
const path = url.split("?")[0]?.replace(/\/+$/, "") ?? "";
|
|
1988
2142
|
return path.endsWith("/responses");
|
|
1989
2143
|
}
|
|
2144
|
+
var SAFE_INJECTED_CACHE_KEY_SOURCES = /* @__PURE__ */ new Set([
|
|
2145
|
+
"session-header",
|
|
2146
|
+
"thread-header",
|
|
2147
|
+
"body-session-id",
|
|
2148
|
+
"body-thread-id",
|
|
2149
|
+
"content-fingerprint"
|
|
2150
|
+
]);
|
|
2151
|
+
function isSafeInjectedCacheKeySource(source) {
|
|
2152
|
+
return SAFE_INJECTED_CACHE_KEY_SOURCES.has(source);
|
|
2153
|
+
}
|
|
2154
|
+
function ensureCodexPromptCacheKey(body, proxyProviderId2, derivedSession) {
|
|
2155
|
+
if (typeof body.prompt_cache_key === "string" && body.prompt_cache_key.trim()) {
|
|
2156
|
+
return { cacheKeySource: "client", cacheKeyInjected: false };
|
|
2157
|
+
}
|
|
2158
|
+
if (proxyProviderId2 !== "codex" || !isSafeInjectedCacheKeySource(derivedSession.source)) {
|
|
2159
|
+
return { cacheKeySource: "none", cacheKeyInjected: false };
|
|
2160
|
+
}
|
|
2161
|
+
body.prompt_cache_key = `omnicross:${derivedSession.source}:${derivedSession.key}`;
|
|
2162
|
+
return {
|
|
2163
|
+
cacheKeySource: derivedSession.source,
|
|
2164
|
+
cacheKeyInjected: true
|
|
2165
|
+
};
|
|
2166
|
+
}
|
|
1990
2167
|
async function handleOpenAIResponsesRequest(res, rawBody, route, deps, requestHeaders = {}) {
|
|
1991
2168
|
let responsesBody;
|
|
1992
2169
|
try {
|
|
@@ -2007,14 +2184,31 @@ async function handleOpenAIResponsesRequest(res, rawBody, route, deps, requestHe
|
|
|
2007
2184
|
const resolvedModel = route.model;
|
|
2008
2185
|
responsesBody.model = resolvedModel;
|
|
2009
2186
|
try {
|
|
2010
|
-
const plan = route.authMode === "subscription" ? await buildSubscriptionPlan3(
|
|
2187
|
+
const plan = route.authMode === "subscription" ? await buildSubscriptionPlan3(
|
|
2188
|
+
res,
|
|
2189
|
+
route,
|
|
2190
|
+
deps,
|
|
2191
|
+
resolvedModel,
|
|
2192
|
+
isStream,
|
|
2193
|
+
sessionKey,
|
|
2194
|
+
derivedSession.source,
|
|
2195
|
+
requestHeaders
|
|
2196
|
+
) : await buildByoPlan4(res, route, deps, resolvedModel, isStream);
|
|
2011
2197
|
if (!plan) return;
|
|
2012
|
-
const
|
|
2198
|
+
const cacheKeyAttribution = ensureCodexPromptCacheKey(
|
|
2199
|
+
responsesBody,
|
|
2200
|
+
plan.proxyProviderId,
|
|
2201
|
+
derivedSession
|
|
2202
|
+
);
|
|
2203
|
+
let providerResponse = route.authMode === "subscription" ? await runPipelineWithSubscriptionRetry3(responsesBody, plan) : await runPipelineWithPoolReporting4(responsesBody, plan);
|
|
2204
|
+
providerResponse = await retryAroundCodexUsageLimit(responsesBody, plan, providerResponse);
|
|
2013
2205
|
const usageAttribution = {
|
|
2014
2206
|
sessionId: route.sessionId,
|
|
2015
2207
|
providerId: route.providerId ?? "codex",
|
|
2016
2208
|
model: resolvedModel,
|
|
2017
2209
|
apiKeyId: route.apiKeyId ?? null,
|
|
2210
|
+
cacheKeySource: cacheKeyAttribution.cacheKeySource,
|
|
2211
|
+
cacheKeyInjected: cacheKeyAttribution.cacheKeyInjected,
|
|
2018
2212
|
// request-audit-log: correlate this request's tokens/cost to its audit record.
|
|
2019
2213
|
auditResponse: res
|
|
2020
2214
|
};
|
|
@@ -2030,12 +2224,33 @@ async function handleOpenAIResponsesRequest(res, rawBody, route, deps, requestHe
|
|
|
2030
2224
|
recordResponsesStreamUsage(usageRecorder, rawUsage, usageAttribution);
|
|
2031
2225
|
}
|
|
2032
2226
|
} : void 0;
|
|
2227
|
+
const overloadActivityId = providerResponse.activityRecordId;
|
|
2228
|
+
const overloadAccountId = providerResponse.accountId;
|
|
2229
|
+
const overloadProviderId = plan.proxyProviderId;
|
|
2230
|
+
let overloadRecorded = false;
|
|
2231
|
+
const overloadDetector = (event) => {
|
|
2232
|
+
if (overloadRecorded || !isCodexServerOverloadEvent(event)) return;
|
|
2233
|
+
overloadRecorded = true;
|
|
2234
|
+
if (overloadActivityId) {
|
|
2235
|
+
getSharedAccountRouteActivity().amend(overloadActivityId, {
|
|
2236
|
+
streamError: "server_overloaded"
|
|
2237
|
+
});
|
|
2238
|
+
}
|
|
2239
|
+
if (overloadAccountId) {
|
|
2240
|
+
getSharedOverloadCounter().recordOverload({
|
|
2241
|
+
providerId: overloadProviderId,
|
|
2242
|
+
accountId: overloadAccountId,
|
|
2243
|
+
endpoint: "responses"
|
|
2244
|
+
});
|
|
2245
|
+
}
|
|
2246
|
+
};
|
|
2033
2247
|
const bodyText = await relayResponse(
|
|
2034
2248
|
res,
|
|
2035
2249
|
providerResponse.response,
|
|
2036
2250
|
isStream,
|
|
2037
2251
|
route.requestedModel,
|
|
2038
|
-
usageTap
|
|
2252
|
+
usageTap,
|
|
2253
|
+
overloadDetector
|
|
2039
2254
|
);
|
|
2040
2255
|
if (bodyText && deps.usageRecorder) {
|
|
2041
2256
|
recordResponsesNonStreamUsage(deps.usageRecorder, bodyText, usageAttribution);
|
|
@@ -2099,7 +2314,7 @@ async function buildByoPlan4(res, route, deps, resolvedModel, isStream) {
|
|
|
2099
2314
|
proxyProviderId: "byo"
|
|
2100
2315
|
};
|
|
2101
2316
|
}
|
|
2102
|
-
async function buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream, sessionKey) {
|
|
2317
|
+
async function buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream, sessionKey, sessionSource, requestHeaders) {
|
|
2103
2318
|
const profile = route.subscriptionProfile;
|
|
2104
2319
|
if (!profile) {
|
|
2105
2320
|
writeError(res, 502, "Subscription mode requires a codex subscription profile");
|
|
@@ -2142,6 +2357,7 @@ async function buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream,
|
|
|
2142
2357
|
return {
|
|
2143
2358
|
auth,
|
|
2144
2359
|
sessionKey,
|
|
2360
|
+
sessionSource,
|
|
2145
2361
|
preferredAccountId: route.preferredAccountId,
|
|
2146
2362
|
preferredAccountGroup: route.preferredAccountGroup,
|
|
2147
2363
|
boundAccountFallbackPolicy: route.boundAccountFallbackPolicy,
|
|
@@ -2154,7 +2370,10 @@ async function buildSubscriptionPlan3(res, route, deps, resolvedModel, isStream,
|
|
|
2154
2370
|
// profile's `resolveUpstreamUrl` for non-Code-Assist subscriptions.
|
|
2155
2371
|
resolveUrl: (config) => config.url instanceof URL ? config.url.toString() : typeof config.url === "string" ? config.url : upstreamUrl,
|
|
2156
2372
|
upstreamUrl,
|
|
2157
|
-
proxyProviderId: profile.authStrategy.providerId
|
|
2373
|
+
proxyProviderId: profile.authStrategy.providerId,
|
|
2374
|
+
// Only the codex backend understands these; other subscription providers
|
|
2375
|
+
// (gemini Code Assist) share this relay and must not receive them.
|
|
2376
|
+
callerClientHeaders: profile.authStrategy.providerId === "codex" ? extractCodexClientHeaders(requestHeaders) : void 0
|
|
2158
2377
|
};
|
|
2159
2378
|
}
|
|
2160
2379
|
async function resolveGeminiCodeAssistProject(profile, hints) {
|
|
@@ -2172,6 +2391,7 @@ async function runPipeline4(responsesBody, plan) {
|
|
|
2172
2391
|
const endpointTransformer = getResponsesEndpointTransformer();
|
|
2173
2392
|
const { auth, sessionKey, chain, transformerProvider, resolvedModel, isStream, resolveUrl, upstreamUrl } = plan;
|
|
2174
2393
|
let proxyAccountId;
|
|
2394
|
+
let activityRecordId;
|
|
2175
2395
|
const authHeaders = {};
|
|
2176
2396
|
await auth.applyHeaders(authHeaders, {
|
|
2177
2397
|
upstreamUrl,
|
|
@@ -2199,6 +2419,11 @@ async function runPipeline4(responsesBody, plan) {
|
|
|
2199
2419
|
if (value !== void 0 && !(key in headers)) headers[key] = value;
|
|
2200
2420
|
}
|
|
2201
2421
|
}
|
|
2422
|
+
if (plan.proxyProviderId === "codex") {
|
|
2423
|
+
fillMissingHeaders(headers, plan.callerClientHeaders ?? {});
|
|
2424
|
+
fillMissingHeaders(headers, DEFAULT_CODEX_CLI_HEADERS);
|
|
2425
|
+
fillMissingHeaders(headers, { accept: codexAcceptHeader(isStream) });
|
|
2426
|
+
}
|
|
2202
2427
|
return headers;
|
|
2203
2428
|
},
|
|
2204
2429
|
fetchFn: (url, headers, body) => {
|
|
@@ -2206,7 +2431,19 @@ async function runPipeline4(responsesBody, plan) {
|
|
|
2206
2431
|
return fetchUpstream(
|
|
2207
2432
|
url,
|
|
2208
2433
|
{ method: "POST", headers, body: JSON.stringify(body) },
|
|
2209
|
-
{
|
|
2434
|
+
{
|
|
2435
|
+
providerId: plan.proxyProviderId,
|
|
2436
|
+
accountId: proxyAccountId,
|
|
2437
|
+
routeActivity: plan.proxyProviderId === "byo" ? void 0 : {
|
|
2438
|
+
endpoint: "responses",
|
|
2439
|
+
sessionKey,
|
|
2440
|
+
sessionSource: plan.sessionSource ?? "none",
|
|
2441
|
+
model: resolvedModel,
|
|
2442
|
+
onRecorded: (record) => {
|
|
2443
|
+
activityRecordId = record.id;
|
|
2444
|
+
}
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2210
2447
|
).then((r) => {
|
|
2211
2448
|
rawStatus = r.status;
|
|
2212
2449
|
return r;
|
|
@@ -2214,7 +2451,7 @@ async function runPipeline4(responsesBody, plan) {
|
|
|
2214
2451
|
},
|
|
2215
2452
|
runResponseChain: true
|
|
2216
2453
|
});
|
|
2217
|
-
return { response, rawStatus };
|
|
2454
|
+
return { response, rawStatus, accountId: proxyAccountId, activityRecordId };
|
|
2218
2455
|
}
|
|
2219
2456
|
async function runPipelineWithPoolReporting4(responsesBody, plan) {
|
|
2220
2457
|
const first = await runPipeline4(responsesBody, plan);
|
|
@@ -2240,6 +2477,22 @@ async function runPipelineWithSubscriptionRetry3(responsesBody, plan) {
|
|
|
2240
2477
|
console.log("[ProviderProxy:responses] 401 \u2192 token refreshed; retrying once");
|
|
2241
2478
|
return runPipeline4(responsesBody, plan);
|
|
2242
2479
|
}
|
|
2480
|
+
var MAX_QUOTA_RETRIES = 3;
|
|
2481
|
+
function isCodexAccountQuota429(plan, result) {
|
|
2482
|
+
return plan.proxyProviderId === "codex" && !!result.accountId && result.rawStatus === 429;
|
|
2483
|
+
}
|
|
2484
|
+
async function retryAroundCodexUsageLimit(responsesBody, plan, first, runAttempt = runPipelineWithSubscriptionRetry3) {
|
|
2485
|
+
if (!isCodexAccountQuota429(plan, first)) return first;
|
|
2486
|
+
let current = first;
|
|
2487
|
+
for (let attempt = 0; attempt < MAX_QUOTA_RETRIES; attempt++) {
|
|
2488
|
+
const errorBody = await current.response.text().catch(() => "");
|
|
2489
|
+
markCodexUsageLimitExhaustion(current.accountId, errorBody);
|
|
2490
|
+
const next = await runAttempt(responsesBody, plan);
|
|
2491
|
+
if (!isCodexAccountQuota429(plan, next)) return next;
|
|
2492
|
+
current = next;
|
|
2493
|
+
}
|
|
2494
|
+
return current;
|
|
2495
|
+
}
|
|
2243
2496
|
|
|
2244
2497
|
// src/provider-proxy/providerProxyRouter.ts
|
|
2245
2498
|
function extractRouteToken(authHeader) {
|
|
@@ -2531,15 +2784,20 @@ function normalizeAudit(raw) {
|
|
|
2531
2784
|
return {
|
|
2532
2785
|
enabled: a?.enabled === true,
|
|
2533
2786
|
captureBodies: a?.captureBodies === true,
|
|
2534
|
-
maxBodyBytes:
|
|
2535
|
-
clampNumber(a?.maxBodyBytes, 256, 1048576, DEFAULT_AUDIT_CONFIG.maxBodyBytes)
|
|
2536
|
-
),
|
|
2787
|
+
maxBodyBytes: normalizeMaxBodyBytes(a?.maxBodyBytes),
|
|
2537
2788
|
retentionDays: Math.trunc(
|
|
2538
2789
|
clampNumber(a?.retentionDays, 1, 365, DEFAULT_AUDIT_CONFIG.retentionDays)
|
|
2539
2790
|
),
|
|
2540
2791
|
trustForwardedFor: a?.trustForwardedFor === true
|
|
2541
2792
|
};
|
|
2542
2793
|
}
|
|
2794
|
+
function normalizeMaxBodyBytes(value) {
|
|
2795
|
+
if (value === -1) return -1;
|
|
2796
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
2797
|
+
return DEFAULT_AUDIT_CONFIG.maxBodyBytes;
|
|
2798
|
+
}
|
|
2799
|
+
return Math.trunc(Math.min(1048576, value));
|
|
2800
|
+
}
|
|
2543
2801
|
function normalizeBilling(raw) {
|
|
2544
2802
|
const b = raw?.billing;
|
|
2545
2803
|
const config = {
|
|
@@ -3240,7 +3498,8 @@ async function createNamedKey(db, name) {
|
|
|
3240
3498
|
id,
|
|
3241
3499
|
name,
|
|
3242
3500
|
keyHash: hashKey(secret),
|
|
3243
|
-
keyPrefix: prefix
|
|
3501
|
+
keyPrefix: prefix,
|
|
3502
|
+
plaintext: secret
|
|
3244
3503
|
});
|
|
3245
3504
|
return {
|
|
3246
3505
|
id: row.id,
|
|
@@ -3261,7 +3520,8 @@ async function createIntegrationKey(db, name, allowedEndpoints = ["responses", "
|
|
|
3261
3520
|
keyPrefix: prefix,
|
|
3262
3521
|
kind: "integration",
|
|
3263
3522
|
allowedEndpoints: [...new Set(allowedEndpoints)],
|
|
3264
|
-
loopbackOnly: true
|
|
3523
|
+
loopbackOnly: true,
|
|
3524
|
+
plaintext: secret
|
|
3265
3525
|
});
|
|
3266
3526
|
return {
|
|
3267
3527
|
id: row.id,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// src/transformer/transformers/utils/usage-mapping.ts
|
|
2
|
+
function num(obj, key) {
|
|
3
|
+
const v = obj?.[key];
|
|
4
|
+
return typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
5
|
+
}
|
|
6
|
+
function detailCachedTokens(obj, detailKey) {
|
|
7
|
+
const detail = obj?.[detailKey];
|
|
8
|
+
return num(detail, "cached_tokens");
|
|
9
|
+
}
|
|
10
|
+
function anthropicUsageToChatUsage(usage) {
|
|
11
|
+
if (!usage) return void 0;
|
|
12
|
+
const input = num(usage, "input_tokens");
|
|
13
|
+
const output = num(usage, "output_tokens");
|
|
14
|
+
const cacheRead = num(usage, "cache_read_input_tokens");
|
|
15
|
+
const cacheCreation = num(usage, "cache_creation_input_tokens");
|
|
16
|
+
const promptTokens = input + cacheRead + cacheCreation;
|
|
17
|
+
const out = {
|
|
18
|
+
prompt_tokens: promptTokens,
|
|
19
|
+
completion_tokens: output,
|
|
20
|
+
total_tokens: promptTokens + output
|
|
21
|
+
};
|
|
22
|
+
if (cacheRead > 0) {
|
|
23
|
+
out.prompt_tokens_details = { cached_tokens: cacheRead };
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
function chatUsageToResponsesUsage(usage) {
|
|
28
|
+
if (!usage) return void 0;
|
|
29
|
+
const prompt = num(usage, "prompt_tokens");
|
|
30
|
+
const completion = num(usage, "completion_tokens");
|
|
31
|
+
const out = {
|
|
32
|
+
input_tokens: prompt,
|
|
33
|
+
output_tokens: completion,
|
|
34
|
+
total_tokens: num(usage, "total_tokens") || prompt + completion
|
|
35
|
+
};
|
|
36
|
+
const cacheRead = detailCachedTokens(usage, "prompt_tokens_details");
|
|
37
|
+
if (cacheRead > 0) {
|
|
38
|
+
out.input_tokens_details = { cached_tokens: cacheRead };
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
function responsesUsageToChatUsage(usage) {
|
|
43
|
+
if (!usage) return void 0;
|
|
44
|
+
const input = num(usage, "input_tokens");
|
|
45
|
+
const output = num(usage, "output_tokens");
|
|
46
|
+
const out = {
|
|
47
|
+
prompt_tokens: input,
|
|
48
|
+
completion_tokens: output,
|
|
49
|
+
total_tokens: num(usage, "total_tokens") || input + output
|
|
50
|
+
};
|
|
51
|
+
const cacheRead = detailCachedTokens(usage, "input_tokens_details");
|
|
52
|
+
if (cacheRead > 0) {
|
|
53
|
+
out.prompt_tokens_details = { cached_tokens: cacheRead };
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
anthropicUsageToChatUsage,
|
|
60
|
+
chatUsageToResponsesUsage,
|
|
61
|
+
responsesUsageToChatUsage
|
|
62
|
+
};
|