@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,4 +1,8 @@
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/transformer/transformers/AnthropicToolHandling.ts
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
+ var _chunk5RSZYQJHcjs = require('./chunk-5RSZYQJH.cjs');
4
+
5
+ // src/transformer/transformers/AnthropicToolHandling.ts
2
6
  function isServerSideTool(tool) {
3
7
  const type = String(tool.type || "");
4
8
  return type.startsWith("web_search_") || type.startsWith("code_execution_") || type.startsWith("text_editor_") || type.startsWith("memory_") || type.startsWith("web_fetch_") || type.startsWith("search_tool_");
@@ -261,11 +265,9 @@ ${formatted}`);
261
265
  message,
262
266
  finish_reason: stopReasonMapping[anthropicResponse.stop_reason] || "stop"
263
267
  }],
264
- usage: usage ? {
265
- prompt_tokens: usage.input_tokens || 0,
266
- completion_tokens: usage.output_tokens || 0,
267
- total_tokens: (usage.input_tokens || 0) + (usage.output_tokens || 0)
268
- } : void 0
268
+ // Preserve prompt-cache counts (cache-read → prompt_tokens_details.cached_tokens,
269
+ // cache-creation folded into prompt_tokens) instead of dropping them.
270
+ usage: _chunk5RSZYQJHcjs.anthropicUsageToChatUsage.call(void 0, usage)
269
271
  };
270
272
  }
271
273
  function convertOpenAIResponseToAnthropic(openaiResponse) {
@@ -619,11 +621,7 @@ ${formatted}` },
619
621
  }]
620
622
  };
621
623
  if (event.usage) {
622
- chunk.usage = {
623
- prompt_tokens: event.usage.input_tokens || 0,
624
- completion_tokens: event.usage.output_tokens || 0,
625
- total_tokens: (event.usage.input_tokens || 0) + (event.usage.output_tokens || 0)
626
- };
624
+ chunk.usage = _chunk5RSZYQJHcjs.anthropicUsageToChatUsage.call(void 0, event.usage);
627
625
  }
628
626
  safeEnqueue(`data: ${JSON.stringify(chunk)}
629
627
 
@@ -1,3 +1,7 @@
1
+ import {
2
+ anthropicUsageToChatUsage
3
+ } from "./chunk-FU7EAR73.js";
4
+
1
5
  // src/transformer/transformers/AnthropicToolHandling.ts
2
6
  function isServerSideTool(tool) {
3
7
  const type = String(tool.type || "");
@@ -261,11 +265,9 @@ ${formatted}`);
261
265
  message,
262
266
  finish_reason: stopReasonMapping[anthropicResponse.stop_reason] || "stop"
263
267
  }],
264
- usage: usage ? {
265
- prompt_tokens: usage.input_tokens || 0,
266
- completion_tokens: usage.output_tokens || 0,
267
- total_tokens: (usage.input_tokens || 0) + (usage.output_tokens || 0)
268
- } : void 0
268
+ // Preserve prompt-cache counts (cache-read → prompt_tokens_details.cached_tokens,
269
+ // cache-creation folded into prompt_tokens) instead of dropping them.
270
+ usage: anthropicUsageToChatUsage(usage)
269
271
  };
270
272
  }
271
273
  function convertOpenAIResponseToAnthropic(openaiResponse) {
@@ -619,11 +621,7 @@ ${formatted}` },
619
621
  }]
620
622
  };
621
623
  if (event.usage) {
622
- chunk.usage = {
623
- prompt_tokens: event.usage.input_tokens || 0,
624
- completion_tokens: event.usage.output_tokens || 0,
625
- total_tokens: (event.usage.input_tokens || 0) + (event.usage.output_tokens || 0)
626
- };
624
+ chunk.usage = anthropicUsageToChatUsage(event.usage);
627
625
  }
628
626
  safeEnqueue(`data: ${JSON.stringify(chunk)}
629
627
 
@@ -0,0 +1,79 @@
1
+ // 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 {
8
+ 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 = query.providerId?.trim();
43
+ const accountId = query.accountId?.trim();
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
+ };
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
+ export {
73
+ OVERLOAD_RECENT_LIMIT,
74
+ OVERLOAD_ENTRY_TTL_MS,
75
+ ServerOverloadCounterStore,
76
+ getSharedOverloadCounter,
77
+ setSharedOverloadCounter,
78
+ __resetSharedOverloadCounterForTests
79
+ };
@@ -1,11 +1,15 @@
1
1
  import {
2
+ REDACTED_BODY,
2
3
  getUpstreamTracePath,
3
4
  redactHeaders,
4
5
  writeUpstreamTrace
5
- } from "./chunk-SYQF7OIR.js";
6
+ } from "./chunk-3WD4HTR2.js";
6
7
  import {
7
8
  getSharedAccountAllowanceStore
8
9
  } from "./chunk-MKF46GNZ.js";
10
+ import {
11
+ getSharedAccountRouteActivity
12
+ } from "./chunk-GL6XM527.js";
9
13
 
10
14
  // src/pipeline/upstreamFetch.ts
11
15
  import { Agent, buildConnector, ProxyAgent } from "undici";
@@ -114,17 +118,48 @@ function fetchUpstream(url, init, ctx) {
114
118
  }
115
119
  return response;
116
120
  });
121
+ const activity = ctx?.routeActivity;
122
+ const activityStartedAt = activity && ctx?.providerId && ctx.accountId ? Date.now() : 0;
123
+ const recordActivity = (status) => {
124
+ if (!activity || !ctx?.providerId || !ctx.accountId) return;
125
+ const record = getSharedAccountRouteActivity().record({
126
+ providerId: ctx.providerId,
127
+ accountId: ctx.accountId,
128
+ endpoint: activity.endpoint,
129
+ sessionKey: activity.sessionKey,
130
+ sessionSource: activity.sessionSource,
131
+ model: activity.model,
132
+ status,
133
+ durationMs: Math.max(0, Date.now() - activityStartedAt),
134
+ ts: activityStartedAt
135
+ });
136
+ try {
137
+ activity.onRecorded?.(record);
138
+ } catch {
139
+ }
140
+ };
141
+ const doFetchWithActivity = () => doFetchWithAllowanceTap().then(
142
+ (response) => {
143
+ recordActivity(response.status);
144
+ return response;
145
+ },
146
+ (error) => {
147
+ recordActivity(0);
148
+ throw error;
149
+ }
150
+ );
117
151
  const tracePath = getUpstreamTracePath();
118
- if (!tracePath || !ctx?.providerId) return doFetchWithAllowanceTap();
152
+ if (!tracePath || !ctx?.providerId) return doFetchWithActivity();
119
153
  const startedAt = Date.now();
120
154
  const method = typeof init.method === "string" ? init.method : "GET";
121
155
  const requestHeaders = redactHeaders(
122
156
  init.headers
123
157
  );
124
- const requestBody = typeof init.body === "string" ? init.body : null;
158
+ const redactBodies = ctx.redactBodies === true;
159
+ const requestBody = redactBodies ? REDACTED_BODY : typeof init.body === "string" ? init.body : null;
125
160
  const providerId = ctx.providerId;
126
161
  const accountId = ctx.accountId;
127
- return doFetchWithAllowanceTap().then((res) => {
162
+ return doFetchWithActivity().then((res) => {
128
163
  const clone = res.clone();
129
164
  const status = res.status;
130
165
  const statusText = res.statusText;
@@ -142,7 +177,9 @@ function fetchUpstream(url, init, ctx) {
142
177
  status,
143
178
  statusText,
144
179
  responseHeaders,
145
- responseBody: body,
180
+ // The byte count stays REAL even when redacted — it is a useful
181
+ // diagnostic and reveals nothing about the token itself.
182
+ responseBody: redactBodies ? REDACTED_BODY : body,
146
183
  responseBytes: Buffer.byteLength(body, "utf8")
147
184
  });
148
185
  }).catch(() => {
@@ -2,11 +2,15 @@
2
2
 
3
3
 
4
4
 
5
- var _chunk3Z5BQZFMcjs = require('./chunk-3Z5BQZFM.cjs');
5
+
6
+ var _chunk235MXAGXcjs = require('./chunk-235MXAGX.cjs');
6
7
 
7
8
 
8
9
  var _chunkHVBBDBS3cjs = require('./chunk-HVBBDBS3.cjs');
9
10
 
11
+
12
+ var _chunkNKVZ6Z3Ycjs = require('./chunk-NKVZ6Z3Y.cjs');
13
+
10
14
  // src/pipeline/upstreamFetch.ts
11
15
  var _undici = require('undici');
12
16
  var _socks = require('socks');
@@ -114,23 +118,54 @@ function fetchUpstream(url, init, ctx) {
114
118
  }
115
119
  return response;
116
120
  });
117
- const tracePath = _chunk3Z5BQZFMcjs.getUpstreamTracePath.call(void 0, );
118
- if (!tracePath || !_optionalChain([ctx, 'optionalAccess', _4 => _4.providerId])) return doFetchWithAllowanceTap();
121
+ const activity = _optionalChain([ctx, 'optionalAccess', _4 => _4.routeActivity]);
122
+ const activityStartedAt = activity && _optionalChain([ctx, 'optionalAccess', _5 => _5.providerId]) && ctx.accountId ? Date.now() : 0;
123
+ const recordActivity = (status) => {
124
+ if (!activity || !_optionalChain([ctx, 'optionalAccess', _6 => _6.providerId]) || !ctx.accountId) return;
125
+ const record = _chunkNKVZ6Z3Ycjs.getSharedAccountRouteActivity.call(void 0, ).record({
126
+ providerId: ctx.providerId,
127
+ accountId: ctx.accountId,
128
+ endpoint: activity.endpoint,
129
+ sessionKey: activity.sessionKey,
130
+ sessionSource: activity.sessionSource,
131
+ model: activity.model,
132
+ status,
133
+ durationMs: Math.max(0, Date.now() - activityStartedAt),
134
+ ts: activityStartedAt
135
+ });
136
+ try {
137
+ _optionalChain([activity, 'access', _7 => _7.onRecorded, 'optionalCall', _8 => _8(record)]);
138
+ } catch (e5) {
139
+ }
140
+ };
141
+ const doFetchWithActivity = () => doFetchWithAllowanceTap().then(
142
+ (response) => {
143
+ recordActivity(response.status);
144
+ return response;
145
+ },
146
+ (error) => {
147
+ recordActivity(0);
148
+ throw error;
149
+ }
150
+ );
151
+ const tracePath = _chunk235MXAGXcjs.getUpstreamTracePath.call(void 0, );
152
+ if (!tracePath || !_optionalChain([ctx, 'optionalAccess', _9 => _9.providerId])) return doFetchWithActivity();
119
153
  const startedAt = Date.now();
120
154
  const method = typeof init.method === "string" ? init.method : "GET";
121
- const requestHeaders = _chunk3Z5BQZFMcjs.redactHeaders.call(void 0,
155
+ const requestHeaders = _chunk235MXAGXcjs.redactHeaders.call(void 0,
122
156
  init.headers
123
157
  );
124
- const requestBody = typeof init.body === "string" ? init.body : null;
158
+ const redactBodies = ctx.redactBodies === true;
159
+ const requestBody = redactBodies ? _chunk235MXAGXcjs.REDACTED_BODY : typeof init.body === "string" ? init.body : null;
125
160
  const providerId = ctx.providerId;
126
161
  const accountId = ctx.accountId;
127
- return doFetchWithAllowanceTap().then((res) => {
162
+ return doFetchWithActivity().then((res) => {
128
163
  const clone = res.clone();
129
164
  const status = res.status;
130
165
  const statusText = res.statusText;
131
- const responseHeaders = _chunk3Z5BQZFMcjs.redactHeaders.call(void 0, res.headers);
166
+ const responseHeaders = _chunk235MXAGXcjs.redactHeaders.call(void 0, res.headers);
132
167
  void clone.text().then((body) => {
133
- _chunk3Z5BQZFMcjs.writeUpstreamTrace.call(void 0, {
168
+ _chunk235MXAGXcjs.writeUpstreamTrace.call(void 0, {
134
169
  ts: startedAt,
135
170
  durationMs: Date.now() - startedAt,
136
171
  providerId,
@@ -142,7 +177,9 @@ function fetchUpstream(url, init, ctx) {
142
177
  status,
143
178
  statusText,
144
179
  responseHeaders,
145
- responseBody: body,
180
+ // The byte count stays REAL even when redacted — it is a useful
181
+ // diagnostic and reveals nothing about the token itself.
182
+ responseBody: redactBodies ? _chunk235MXAGXcjs.REDACTED_BODY : body,
146
183
  responseBytes: Buffer.byteLength(body, "utf8")
147
184
  });
148
185
  }).catch(() => {
@@ -150,7 +187,7 @@ function fetchUpstream(url, init, ctx) {
150
187
  return res;
151
188
  }).catch((err) => {
152
189
  const msg = err instanceof Error ? err.message : String(err);
153
- _chunk3Z5BQZFMcjs.writeUpstreamTrace.call(void 0, {
190
+ _chunk235MXAGXcjs.writeUpstreamTrace.call(void 0, {
154
191
  ts: startedAt,
155
192
  durationMs: Date.now() - startedAt,
156
193
  providerId,
@@ -78,7 +78,9 @@ var UsageRecorder = class {
78
78
  costSavedByCacheUsd,
79
79
  rawUsage: input.rawUsage != null ? safeStringify(input.rawUsage) : null,
80
80
  runId: input.runId ?? null,
81
- eventId: input.eventId ?? null
81
+ eventId: input.eventId ?? null,
82
+ ...input.cacheKeySource !== void 0 ? { cacheKeySource: input.cacheKeySource } : {},
83
+ ...input.cacheKeyInjected !== void 0 ? { cacheKeyInjected: input.cacheKeyInjected } : {}
82
84
  };
83
85
  try {
84
86
  return await this.store.insert(row);
@@ -11,6 +11,29 @@ var _chunkXSVNC2UDcjs = require('./chunk-XSVNC2UD.cjs');
11
11
 
12
12
  // src/outbound-api/auditCapture.ts
13
13
  var _crypto = require('crypto');
14
+ function completeUtf8PrefixLength(buf) {
15
+ if (buf.length === 0) return 0;
16
+ let leadIndex = buf.length - 1;
17
+ while (leadIndex >= 0 && (buf[leadIndex] & 192) === 128) leadIndex -= 1;
18
+ if (leadIndex < 0) return 0;
19
+ const lead = buf[leadIndex];
20
+ let expectedLength = 1;
21
+ if ((lead & 224) === 192) expectedLength = 2;
22
+ else if ((lead & 240) === 224) expectedLength = 3;
23
+ else if ((lead & 248) === 240) expectedLength = 4;
24
+ return buf.length - leadIndex < expectedLength ? leadIndex : buf.length;
25
+ }
26
+ function truncateToBytes(text, maxBytes) {
27
+ if (maxBytes < 0) return text;
28
+ const buf = Buffer.from(text, "utf8");
29
+ if (buf.length <= maxBytes) return text;
30
+ const head = buf.subarray(0, maxBytes);
31
+ return head.subarray(0, completeUtf8PrefixLength(head)).toString("utf8");
32
+ }
33
+ function decodeCapturedBody(body, truncated) {
34
+ if (!truncated) return body.toString("utf8");
35
+ return body.subarray(0, completeUtf8PrefixLength(body)).toString("utf8");
36
+ }
14
37
  function resolveClientIp(req, trustForwardedFor) {
15
38
  if (trustForwardedFor) {
16
39
  const xff = req.headers["x-forwarded-for"];
@@ -25,18 +48,39 @@ function resolveClientIp(req, trustForwardedFor) {
25
48
  function beginAuditCapture(req, res, now) {
26
49
  const config = _chunkAEOZIDEBcjs.getAuditCaptureConfig.call(void 0, );
27
50
  if (!config) return null;
28
- let rawRequestBody;
51
+ let requestBody;
29
52
  const responseChunks = [];
53
+ let responseBytes = 0;
54
+ let responseTruncated = false;
30
55
  let finished = false;
31
56
  const ctx = {
32
57
  setRequestBody(raw) {
33
- if (config.captureBodies) rawRequestBody = raw;
58
+ if (config.captureBodies) {
59
+ requestBody = truncateToBytes(_chunkFCR77GYMcjs.redactAuditText.call(void 0, raw), config.maxBodyBytes);
60
+ }
34
61
  }
35
62
  };
36
63
  if (config.captureBodies) {
37
64
  installResponseCapture(res, {
38
65
  push(chunk) {
66
+ if (config.maxBodyBytes < 0) {
67
+ responseChunks.push(chunk);
68
+ responseBytes += chunk.length;
69
+ return;
70
+ }
71
+ const remaining = config.maxBodyBytes - responseBytes;
72
+ if (remaining <= 0) {
73
+ responseTruncated = true;
74
+ return;
75
+ }
76
+ if (chunk.length > remaining) {
77
+ responseChunks.push(chunk.subarray(0, remaining));
78
+ responseBytes += remaining;
79
+ responseTruncated = true;
80
+ return;
81
+ }
39
82
  responseChunks.push(chunk);
83
+ responseBytes += chunk.length;
40
84
  }
41
85
  });
42
86
  }
@@ -69,12 +113,13 @@ function beginAuditCapture(req, res, now) {
69
113
  }
70
114
  if (ctx.error) record.error = _chunkFCR77GYMcjs.redactAuditText.call(void 0, ctx.error);
71
115
  if (config.captureBodies) {
72
- if (rawRequestBody != null && rawRequestBody.length > 0) {
73
- record.requestBody = _chunkFCR77GYMcjs.redactAuditText.call(void 0, rawRequestBody);
116
+ if (requestBody != null && requestBody.length > 0) {
117
+ record.requestBody = requestBody;
74
118
  }
75
119
  if (responseChunks.length > 0) {
76
- const body = Buffer.concat(responseChunks).toString("utf8");
77
- record.responseBody = _chunkFCR77GYMcjs.redactAuditText.call(void 0, body);
120
+ const captured = Buffer.concat(responseChunks, responseBytes);
121
+ const body = decodeCapturedBody(captured, responseTruncated);
122
+ record.responseBody = truncateToBytes(_chunkFCR77GYMcjs.redactAuditText.call(void 0, body), config.maxBodyBytes);
78
123
  }
79
124
  }
80
125
  _chunkAEOZIDEBcjs.recordAudit.call(void 0, record);
@@ -0,0 +1,63 @@
1
+ // src/provider-proxy/identity/headerMerge.ts
2
+ function fillMissingHeaders(headers, source) {
3
+ const present = new Set(Object.keys(headers).map((k) => k.toLowerCase()));
4
+ for (const [key, value] of Object.entries(source)) {
5
+ const lower = key.toLowerCase();
6
+ if (present.has(lower)) continue;
7
+ headers[lower] = value;
8
+ present.add(lower);
9
+ }
10
+ }
11
+ function flattenHeaderValue(raw) {
12
+ if (raw === void 0) return void 0;
13
+ const value = Array.isArray(raw) ? raw.filter((v) => typeof v === "string").join(", ") : raw;
14
+ return typeof value === "string" && value.length > 0 ? value : void 0;
15
+ }
16
+ var NEVER_FORWARD_HEADERS = /* @__PURE__ */ new Set([
17
+ "authorization",
18
+ "x-api-key",
19
+ "cookie",
20
+ "proxy-authorization",
21
+ "host",
22
+ "connection",
23
+ "content-length",
24
+ "content-type",
25
+ "accept-encoding"
26
+ ]);
27
+
28
+ // src/provider-proxy/identity/codexCliHeaders.ts
29
+ var DEFAULT_CODEX_CLI_HEADERS = Object.freeze({
30
+ originator: "codex_cli_rs",
31
+ "user-agent": "codex_cli_rs/0.144.5",
32
+ version: "0.144.5"
33
+ });
34
+ var CODEX_FORWARD_ALLOWLIST = /* @__PURE__ */ new Set([
35
+ "version",
36
+ "openai-beta",
37
+ "session_id",
38
+ "originator",
39
+ "user-agent"
40
+ ]);
41
+ function extractCodexClientHeaders(reqHeaders) {
42
+ const out = {};
43
+ for (const [rawKey, rawVal] of Object.entries(reqHeaders)) {
44
+ const key = rawKey.toLowerCase();
45
+ if (NEVER_FORWARD_HEADERS.has(key)) continue;
46
+ if (!CODEX_FORWARD_ALLOWLIST.has(key)) continue;
47
+ const value = flattenHeaderValue(rawVal);
48
+ if (value !== void 0) out[key] = value;
49
+ }
50
+ return out;
51
+ }
52
+ function codexAcceptHeader(isStream) {
53
+ return isStream ? "text/event-stream" : "application/json";
54
+ }
55
+
56
+ export {
57
+ fillMissingHeaders,
58
+ flattenHeaderValue,
59
+ NEVER_FORWARD_HEADERS,
60
+ DEFAULT_CODEX_CLI_HEADERS,
61
+ extractCodexClientHeaders,
62
+ codexAcceptHeader
63
+ };
@@ -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 = class {
@@ -159,12 +160,47 @@ var SubscriptionAccountHealth = (_class = 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 = _nullishCoalesce(preExisting, () => ( {}));
183
+ const wasUnhealthyBefore = preExisting ? this.isUnhealthyAt(preExisting, now) : false;
184
+ record.quotaExhaustedUntil = clamped;
185
+ this.records.set(key, record);
186
+ if (!wasUnhealthyBefore) {
187
+ const anomaly = {
188
+ providerId,
189
+ accountId,
190
+ at: now,
191
+ state: "quota_exhausted"
192
+ };
193
+ this.recordDiagnostic({ kind: "health-anomaly", ...anomaly });
194
+ this.emitAnomaly(anomaly);
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 = 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 = 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 = 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) {
@@ -344,4 +387,5 @@ function __resetSharedAccountHealthForTests() {
344
387
 
345
388
 
346
389
 
347
- exports.OVERLOAD_TTL_MS = OVERLOAD_TTL_MS; exports.OVERLOAD_ENABLED_DEFAULT = OVERLOAD_ENABLED_DEFAULT; exports.AUTH_ERROR_TTL_MS = AUTH_ERROR_TTL_MS; exports.SERVER_ERROR_TTL_MS = SERVER_ERROR_TTL_MS; exports.ACCOUNT_HEALTH_DIAGNOSTIC_LIMIT = ACCOUNT_HEALTH_DIAGNOSTIC_LIMIT; exports.resolveResetSeconds = resolveResetSeconds; exports.SubscriptionAccountHealth = SubscriptionAccountHealth; exports.getSharedAccountHealth = getSharedAccountHealth; exports.setSharedAccountHealth = setSharedAccountHealth; exports.__resetSharedAccountHealthForTests = __resetSharedAccountHealthForTests;
390
+
391
+ exports.OVERLOAD_TTL_MS = OVERLOAD_TTL_MS; exports.OVERLOAD_ENABLED_DEFAULT = OVERLOAD_ENABLED_DEFAULT; exports.AUTH_ERROR_TTL_MS = AUTH_ERROR_TTL_MS; exports.SERVER_ERROR_TTL_MS = SERVER_ERROR_TTL_MS; exports.MAX_QUOTA_COOLDOWN_MS = MAX_QUOTA_COOLDOWN_MS; exports.ACCOUNT_HEALTH_DIAGNOSTIC_LIMIT = ACCOUNT_HEALTH_DIAGNOSTIC_LIMIT; exports.resolveResetSeconds = resolveResetSeconds; exports.SubscriptionAccountHealth = SubscriptionAccountHealth; exports.getSharedAccountHealth = getSharedAccountHealth; exports.setSharedAccountHealth = setSharedAccountHealth; exports.__resetSharedAccountHealthForTests = __resetSharedAccountHealthForTests;