@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.
Files changed (131) hide show
  1. package/dist/ApiConverter.cjs +2 -2
  2. package/dist/ApiConverter.js +1 -1
  3. package/dist/auth/GeminiCodeAssistProjectResolver.cjs +4 -3
  4. package/dist/auth/GeminiCodeAssistProjectResolver.js +3 -2
  5. package/dist/{chunk-3Z5BQZFM.cjs → chunk-235MXAGX.cjs} +3 -1
  6. package/dist/{chunk-DLXZEZWO.cjs → chunk-2E42SAW3.cjs} +42 -4
  7. package/dist/{chunk-7AK7B36B.cjs → chunk-2Z4XM3H5.cjs} +6 -6
  8. package/dist/{chunk-OEWZUX4G.js → chunk-32O35CIF.js} +9 -20
  9. package/dist/chunk-3SCOLIPT.cjs +63 -0
  10. package/dist/{chunk-SYQF7OIR.js → chunk-3WD4HTR2.js} +2 -0
  11. package/dist/{chunk-SQYVORNP.cjs → chunk-4BB343BI.cjs} +527 -267
  12. package/dist/{chunk-AT7B7SOZ.js → chunk-5NJLQ6T6.js} +21 -10
  13. package/dist/chunk-5RSZYQJH.cjs +62 -0
  14. package/dist/{chunk-IFXJ2BG7.js → chunk-7C7DET6S.js} +51 -6
  15. package/dist/{chunk-UDCC7EMR.js → chunk-E3COOKUP.js} +307 -47
  16. package/dist/chunk-FU7EAR73.js +62 -0
  17. package/dist/{chunk-UX7VWA46.js → chunk-FXR6N3SR.js} +39 -1
  18. package/dist/{chunk-WYTEQ4Q5.cjs → chunk-GDIXXKF2.cjs} +21 -10
  19. package/dist/{chunk-WB6PH56J.js → chunk-GFIZ6LQI.js} +12 -8
  20. package/dist/chunk-GL6XM527.js +61 -0
  21. package/dist/{chunk-EJLH6NFT.cjs → chunk-J3QQ6JS5.cjs} +12 -8
  22. package/dist/{chunk-VRFBB5DB.js → chunk-MYYR3HZL.js} +4 -4
  23. package/dist/{chunk-YJVHCHQX.js → chunk-N7OOJI5V.js} +46 -2
  24. package/dist/chunk-NKVZ6Z3Y.cjs +61 -0
  25. package/dist/{chunk-SNYBEXLB.cjs → chunk-OJGQKHN5.cjs} +3 -1
  26. package/dist/chunk-OTZC4TNH.cjs +79 -0
  27. package/dist/{chunk-6VUQPOV3.cjs → chunk-OVQBNVSV.cjs} +10 -21
  28. package/dist/{chunk-4VLRHHFE.cjs → chunk-OXHNSZ53.cjs} +9 -11
  29. package/dist/{chunk-6CL5HTPQ.js → chunk-PEGTIPB3.js} +8 -10
  30. package/dist/chunk-PO3XB56Z.js +79 -0
  31. package/dist/{chunk-SIZQQD6T.js → chunk-RJ5ZGNI3.js} +42 -5
  32. package/dist/{chunk-KCVJWJST.cjs → chunk-RJUONLUQ.cjs} +47 -10
  33. package/dist/{chunk-BPKCU575.js → chunk-SOO562NM.js} +3 -1
  34. package/dist/{chunk-UNWKG6EI.cjs → chunk-XPIOJQS2.cjs} +51 -6
  35. package/dist/chunk-XXFYLL7R.js +63 -0
  36. package/dist/{chunk-YK57NMIF.cjs → chunk-YWL7YZWS.cjs} +47 -3
  37. package/dist/completion/CompletionService.cjs +23 -19
  38. package/dist/completion/CompletionService.d.cts +1 -0
  39. package/dist/completion/CompletionService.d.ts +1 -0
  40. package/dist/completion/CompletionService.js +22 -18
  41. package/dist/completion.cjs +23 -19
  42. package/dist/completion.d.cts +1 -0
  43. package/dist/completion.d.ts +1 -0
  44. package/dist/completion.js +22 -18
  45. package/dist/index.cjs +26 -22
  46. package/dist/index.d.cts +2 -2
  47. package/dist/index.d.ts +2 -2
  48. package/dist/index.js +26 -22
  49. package/dist/outbound-api/auditCapture.cjs +2 -2
  50. package/dist/outbound-api/auditCapture.d.cts +3 -4
  51. package/dist/outbound-api/auditCapture.d.ts +3 -4
  52. package/dist/outbound-api/auditCapture.js +1 -1
  53. package/dist/outbound-api/routeResolver.d.cts +3 -2
  54. package/dist/outbound-api/routeResolver.d.ts +3 -2
  55. package/dist/outbound-api/subscriptionRegistryPort.d.cts +1 -0
  56. package/dist/outbound-api/subscriptionRegistryPort.d.ts +1 -0
  57. package/dist/outbound-api/types.d.cts +2 -1
  58. package/dist/outbound-api/types.d.ts +2 -1
  59. package/dist/outbound-api.cjs +23 -19
  60. package/dist/outbound-api.d.cts +7 -5
  61. package/dist/outbound-api.d.ts +7 -5
  62. package/dist/outbound-api.js +22 -18
  63. package/dist/pipeline/AccountAllowanceScheduling.d.cts +2 -1
  64. package/dist/pipeline/AccountAllowanceScheduling.d.ts +2 -1
  65. package/dist/pipeline/AccountRouteActivity.cjs +10 -0
  66. package/dist/pipeline/AccountRouteActivity.d.cts +61 -0
  67. package/dist/pipeline/AccountRouteActivity.d.ts +61 -0
  68. package/dist/pipeline/AccountRouteActivity.js +10 -0
  69. package/dist/pipeline/ServerOverloadCounter.cjs +16 -0
  70. package/dist/pipeline/ServerOverloadCounter.d.cts +77 -0
  71. package/dist/pipeline/ServerOverloadCounter.d.ts +77 -0
  72. package/dist/pipeline/ServerOverloadCounter.js +16 -0
  73. package/dist/pipeline/SubscriptionAccountHealth.cjs +4 -2
  74. package/dist/pipeline/SubscriptionAccountHealth.d.cts +32 -3
  75. package/dist/pipeline/SubscriptionAccountHealth.d.ts +32 -3
  76. package/dist/pipeline/SubscriptionAccountHealth.js +3 -1
  77. package/dist/pipeline/upstreamFetch.cjs +4 -3
  78. package/dist/pipeline/upstreamFetch.d.cts +35 -6
  79. package/dist/pipeline/upstreamFetch.d.ts +35 -6
  80. package/dist/pipeline/upstreamFetch.js +3 -2
  81. package/dist/pipeline/upstreamTrace.cjs +4 -2
  82. package/dist/pipeline/upstreamTrace.d.cts +22 -8
  83. package/dist/pipeline/upstreamTrace.d.ts +22 -8
  84. package/dist/pipeline/upstreamTrace.js +3 -1
  85. package/dist/ports.d.cts +1 -1
  86. package/dist/ports.d.ts +1 -1
  87. package/dist/provider-proxy/ProviderProxy.cjs +23 -19
  88. package/dist/provider-proxy/ProviderProxy.d.cts +1 -0
  89. package/dist/provider-proxy/ProviderProxy.d.ts +1 -0
  90. package/dist/provider-proxy/ProviderProxy.js +22 -18
  91. package/dist/provider-proxy/identity/codexCliHeaders.cjs +10 -0
  92. package/dist/provider-proxy/identity/codexCliHeaders.d.cts +45 -0
  93. package/dist/provider-proxy/identity/codexCliHeaders.d.ts +45 -0
  94. package/dist/provider-proxy/identity/codexCliHeaders.js +10 -0
  95. package/dist/provider-proxy/ingress/providerProxyShared.cjs +23 -19
  96. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +11 -1
  97. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +11 -1
  98. package/dist/provider-proxy/ingress/providerProxyShared.js +22 -18
  99. package/dist/provider-proxy/matchText.cjs +2 -2
  100. package/dist/provider-proxy/matchText.d.cts +1 -3
  101. package/dist/provider-proxy/matchText.d.ts +1 -3
  102. package/dist/provider-proxy/matchText.js +1 -1
  103. package/dist/provider-proxy/types.d.cts +5 -0
  104. package/dist/provider-proxy/types.d.ts +5 -0
  105. package/dist/provider-proxy.cjs +23 -19
  106. package/dist/provider-proxy.d.cts +1 -0
  107. package/dist/provider-proxy.d.ts +1 -0
  108. package/dist/provider-proxy.js +22 -18
  109. package/dist/{routeResolver-CHTv_Bs5.d.ts → routeResolver-BxOfunbm.d.ts} +1 -1
  110. package/dist/{routeResolver-kepxnfcC.d.cts → routeResolver-D5OzD0iM.d.cts} +1 -1
  111. package/dist/transformer/transformers/AnthropicTransformer.cjs +3 -2
  112. package/dist/transformer/transformers/AnthropicTransformer.js +2 -1
  113. package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +3 -2
  114. package/dist/transformer/transformers/OpenAIResponseTransformer.js +2 -1
  115. package/dist/transformer/transformers.cjs +7 -6
  116. package/dist/transformer/transformers.js +6 -5
  117. package/dist/transformer.cjs +9 -8
  118. package/dist/transformer.js +8 -7
  119. package/dist/{types-hsoKrVQS.d.ts → types-CqZD77rS.d.ts} +39 -0
  120. package/dist/{types-H3wGZSOo.d.cts → types-gjJ5lJ5n.d.cts} +39 -0
  121. package/dist/usage/pricing-engine.cjs +2 -2
  122. package/dist/usage/pricing-engine.d.cts +20 -0
  123. package/dist/usage/pricing-engine.d.ts +20 -0
  124. package/dist/usage/pricing-engine.js +1 -1
  125. package/dist/usage/usage-recorder.cjs +2 -2
  126. package/dist/usage/usage-recorder.d.cts +5 -1
  127. package/dist/usage/usage-recorder.d.ts +5 -1
  128. package/dist/usage/usage-recorder.js +1 -1
  129. package/dist/usage.cjs +3 -3
  130. package/dist/usage.js +2 -2
  131. 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
- TransformerChainExecutor
11
- } from "./chunk-WNKWAEUR.js";
12
- import {
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-OEWZUX4G.js";
13
+ } from "./chunk-32O35CIF.js";
21
14
  import {
22
- AnthropicTransformer,
23
- resolveAnthropicMaxTokens
24
- } from "./chunk-6CL5HTPQ.js";
15
+ TransformerChainExecutor
16
+ } from "./chunk-WNKWAEUR.js";
25
17
  import {
26
- getGeminiCodeAssistResolver
27
- } from "./chunk-DRWHTIIZ.js";
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-YJVHCHQX.js";
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-IFXJ2BG7.js";
104
+ } from "./chunk-7C7DET6S.js";
94
105
  import {
95
106
  convertAnthropicToOpenAI,
96
107
  convertOpenAIToAnthropic
97
- } from "./chunk-AT7B7SOZ.js";
108
+ } from "./chunk-5NJLQ6T6.js";
98
109
  import {
99
110
  fetchUpstream
100
- } from "./chunk-SIZQQD6T.js";
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
- const raw = usageTap.extractUsage(event);
676
- if (raw) capturedUsage = raw;
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
- { providerId: proxyProviderId(plan), accountId: proxyAccountId }
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
- if (plan.isSubscription && plan.transformerProvider.name === "claude") {
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
- { providerId: proxyProviderId(plan), accountId: proxyAccountId }
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
- await handleAnthropicMessagesByo(res, rawBody, route, deps, { callerAnthropicBeta, callerIdentity });
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(res, route, deps, resolvedModel, isStream, sessionKey) : await buildByoPlan4(res, route, deps, resolvedModel, isStream);
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 providerResponse = route.authMode === "subscription" ? await runPipelineWithSubscriptionRetry3(responsesBody, plan) : await runPipelineWithPoolReporting4(responsesBody, plan);
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
- { providerId: plan.proxyProviderId, accountId: proxyAccountId }
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: Math.trunc(
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
+ };