@omnicross/core 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/dist/ApiConverter.cjs +2 -2
  2. package/dist/ApiConverter.js +1 -1
  3. package/dist/{CompletionService-DdWaAxq0.d.ts → CompletionService-C3BX0Ovy.d.ts} +4 -3
  4. package/dist/{CompletionService-D3a47vdU.d.cts → CompletionService-kNA17cfI.d.cts} +4 -3
  5. package/dist/auth/GeminiCodeAssistProjectResolver.cjs +8 -6
  6. package/dist/auth/GeminiCodeAssistProjectResolver.js +6 -4
  7. package/dist/{chunk-3Z5BQZFM.cjs → chunk-235MXAGX.cjs} +3 -1
  8. package/dist/{chunk-HRRYG2AX.js → chunk-23S5OPIO.js} +10 -1
  9. package/dist/chunk-25GXJCEZ.cjs +40 -0
  10. package/dist/chunk-2E42SAW3.cjs +323 -0
  11. package/dist/chunk-2JYRIADS.js +40 -0
  12. package/dist/chunk-2Z4XM3H5.cjs +44 -0
  13. package/dist/{chunk-BODMAL6G.js → chunk-32O35CIF.js} +271 -91
  14. package/dist/chunk-3SCOLIPT.cjs +63 -0
  15. package/dist/{chunk-SYQF7OIR.js → chunk-3WD4HTR2.js} +2 -0
  16. package/dist/{chunk-CGKLE6IW.cjs → chunk-4BB343BI.cjs} +1489 -520
  17. package/dist/{chunk-VACWOIRE.cjs → chunk-4VZX5F4T.cjs} +39 -15
  18. package/dist/{chunk-5ZQBEOMD.js → chunk-5NJLQ6T6.js} +46 -12
  19. package/dist/chunk-5RSZYQJH.cjs +62 -0
  20. package/dist/chunk-6QQG7YG3.cjs +153 -0
  21. package/dist/{chunk-IFXJ2BG7.js → chunk-7C7DET6S.js} +51 -6
  22. package/dist/{chunk-IK3KE3AU.js → chunk-DE2SRBFZ.js} +1 -1
  23. package/dist/{chunk-FH2P4OCD.js → chunk-E3COOKUP.js} +1240 -271
  24. package/dist/{chunk-UHGVBFU3.js → chunk-EBLFCNPY.js} +38 -14
  25. package/dist/chunk-FU7EAR73.js +62 -0
  26. package/dist/chunk-FXR6N3SR.js +323 -0
  27. package/dist/{chunk-SUEGJ75D.cjs → chunk-GDIXXKF2.cjs} +46 -12
  28. package/dist/chunk-GFIZ6LQI.js +170 -0
  29. package/dist/chunk-GL6XM527.js +61 -0
  30. package/dist/chunk-HVBBDBS3.cjs +350 -0
  31. package/dist/{chunk-46ZIFWYG.cjs → chunk-IIRPUVPH.cjs} +7 -1
  32. package/dist/chunk-J3QQ6JS5.cjs +170 -0
  33. package/dist/{chunk-JWVTXXPX.cjs → chunk-KBM2W6UY.cjs} +8 -4
  34. package/dist/chunk-LB6EBS6Y.js +69 -0
  35. package/dist/{chunk-IWQAX3CS.js → chunk-LVUCAWMK.js} +1 -1
  36. package/dist/chunk-MKF46GNZ.js +350 -0
  37. package/dist/{chunk-HYN75H6G.cjs → chunk-MUHWHQVM.cjs} +1 -1
  38. package/dist/chunk-MYYR3HZL.js +44 -0
  39. package/dist/{chunk-MFZ5437A.js → chunk-N5T4M4GU.js} +1 -1
  40. package/dist/{chunk-5ENKBSWO.js → chunk-N7OOJI5V.js} +88 -8
  41. package/dist/chunk-NKVZ6Z3Y.cjs +61 -0
  42. package/dist/chunk-OF3BECU2.cjs +69 -0
  43. package/dist/{chunk-SNYBEXLB.cjs → chunk-OJGQKHN5.cjs} +3 -1
  44. package/dist/{chunk-DDMRUL76.cjs → chunk-OKMJLEXX.cjs} +5 -5
  45. package/dist/chunk-OPRS4IQZ.js +153 -0
  46. package/dist/chunk-OTZC4TNH.cjs +79 -0
  47. package/dist/{chunk-3Q6Z6JTO.cjs → chunk-OVQBNVSV.cjs} +287 -107
  48. package/dist/{chunk-4XMYPW46.cjs → chunk-OXHNSZ53.cjs} +84 -44
  49. package/dist/{chunk-C6OV7GCC.js → chunk-PEGTIPB3.js} +52 -12
  50. package/dist/chunk-PO3XB56Z.js +79 -0
  51. package/dist/{chunk-D3TDKWRP.js → chunk-RJ5ZGNI3.js} +54 -5
  52. package/dist/{chunk-PG7PS2NN.cjs → chunk-RJUONLUQ.cjs} +59 -10
  53. package/dist/{chunk-BPKCU575.js → chunk-SOO562NM.js} +3 -1
  54. package/dist/{chunk-6QZGDLL4.js → chunk-TOVPMMHM.js} +5 -1
  55. package/dist/{chunk-K52THW2C.cjs → chunk-V4TXMEJS.cjs} +5 -5
  56. package/dist/{chunk-G2UTNSGU.js → chunk-WNKWAEUR.js} +7 -1
  57. package/dist/{chunk-UNWKG6EI.cjs → chunk-XPIOJQS2.cjs} +51 -6
  58. package/dist/chunk-XXFYLL7R.js +63 -0
  59. package/dist/{chunk-KFI44N2R.cjs → chunk-YNJNTCSQ.cjs} +10 -1
  60. package/dist/{chunk-VQY5W4YW.cjs → chunk-YWL7YZWS.cjs} +90 -10
  61. package/dist/completion/ApiKeyPoolService.cjs +12 -0
  62. package/dist/completion/ApiKeyPoolService.d.cts +6 -0
  63. package/dist/completion/ApiKeyPoolService.d.ts +6 -0
  64. package/dist/completion/ApiKeyPoolService.js +12 -0
  65. package/dist/completion/CompletionService.cjs +30 -24
  66. package/dist/completion/CompletionService.d.cts +3 -1
  67. package/dist/completion/CompletionService.d.ts +3 -1
  68. package/dist/completion/CompletionService.js +29 -23
  69. package/dist/completion.cjs +32 -26
  70. package/dist/completion.d.cts +3 -1
  71. package/dist/completion.d.ts +3 -1
  72. package/dist/completion.js +31 -25
  73. package/dist/index.cjs +56 -29
  74. package/dist/index.d.cts +8 -8
  75. package/dist/index.d.ts +8 -8
  76. package/dist/index.js +61 -34
  77. package/dist/{keyPolicy-Cp0FntZl.d.cts → keyPolicy-zdWTu3CQ.d.cts} +1 -1
  78. package/dist/{keyPolicy-Cp0FntZl.d.ts → keyPolicy-zdWTu3CQ.d.ts} +1 -1
  79. package/dist/outbound-api/auditCapture.cjs +2 -2
  80. package/dist/outbound-api/auditCapture.d.cts +3 -4
  81. package/dist/outbound-api/auditCapture.d.ts +3 -4
  82. package/dist/outbound-api/auditCapture.js +1 -1
  83. package/dist/outbound-api/quotaWarn.d.cts +1 -1
  84. package/dist/outbound-api/quotaWarn.d.ts +1 -1
  85. package/dist/outbound-api/routeResolver.cjs +2 -2
  86. package/dist/outbound-api/routeResolver.d.cts +5 -3
  87. package/dist/outbound-api/routeResolver.d.ts +5 -3
  88. package/dist/outbound-api/routeResolver.js +1 -1
  89. package/dist/outbound-api/subscriptionRegistryPort.d.cts +2 -0
  90. package/dist/outbound-api/subscriptionRegistryPort.d.ts +2 -0
  91. package/dist/outbound-api/types.d.cts +4 -2
  92. package/dist/outbound-api/types.d.ts +4 -2
  93. package/dist/outbound-api.cjs +52 -25
  94. package/dist/outbound-api.d.cts +131 -87
  95. package/dist/outbound-api.d.ts +131 -87
  96. package/dist/outbound-api.js +55 -28
  97. package/dist/pipeline/AccountAllowanceScheduling.cjs +15 -0
  98. package/dist/pipeline/AccountAllowanceScheduling.d.cts +91 -0
  99. package/dist/pipeline/AccountAllowanceScheduling.d.ts +91 -0
  100. package/dist/pipeline/AccountAllowanceScheduling.js +15 -0
  101. package/dist/pipeline/AccountAllowanceStore.cjs +20 -0
  102. package/dist/pipeline/AccountAllowanceStore.d.cts +77 -0
  103. package/dist/pipeline/AccountAllowanceStore.d.ts +77 -0
  104. package/dist/pipeline/AccountAllowanceStore.js +20 -0
  105. package/dist/pipeline/AccountRouteActivity.cjs +10 -0
  106. package/dist/pipeline/AccountRouteActivity.d.cts +61 -0
  107. package/dist/pipeline/AccountRouteActivity.d.ts +61 -0
  108. package/dist/pipeline/AccountRouteActivity.js +10 -0
  109. package/dist/pipeline/AuthSource.d.cts +11 -2
  110. package/dist/pipeline/AuthSource.d.ts +11 -2
  111. package/dist/pipeline/BoundAccountSelectionError.cjs +10 -0
  112. package/dist/pipeline/BoundAccountSelectionError.d.cts +28 -0
  113. package/dist/pipeline/BoundAccountSelectionError.d.ts +28 -0
  114. package/dist/pipeline/BoundAccountSelectionError.js +10 -0
  115. package/dist/pipeline/LlmConfigProviderAuth.d.cts +1 -0
  116. package/dist/pipeline/LlmConfigProviderAuth.d.ts +1 -0
  117. package/dist/pipeline/ServerOverloadCounter.cjs +16 -0
  118. package/dist/pipeline/ServerOverloadCounter.d.cts +77 -0
  119. package/dist/pipeline/ServerOverloadCounter.d.ts +77 -0
  120. package/dist/pipeline/ServerOverloadCounter.js +16 -0
  121. package/dist/pipeline/SubscriptionAccountHealth.cjs +6 -2
  122. package/dist/pipeline/SubscriptionAccountHealth.d.cts +65 -8
  123. package/dist/pipeline/SubscriptionAccountHealth.d.ts +65 -8
  124. package/dist/pipeline/SubscriptionAccountHealth.js +5 -1
  125. package/dist/pipeline/SubscriptionAuthSource.cjs +5 -2
  126. package/dist/pipeline/SubscriptionAuthSource.d.cts +1 -0
  127. package/dist/pipeline/SubscriptionAuthSource.d.ts +1 -0
  128. package/dist/pipeline/SubscriptionAuthSource.js +4 -1
  129. package/dist/pipeline/SubscriptionAuthStrategy.d.cts +8 -3
  130. package/dist/pipeline/SubscriptionAuthStrategy.d.ts +8 -3
  131. package/dist/pipeline/executeProviderCall.cjs +2 -2
  132. package/dist/pipeline/executeProviderCall.d.cts +8 -3
  133. package/dist/pipeline/executeProviderCall.d.ts +8 -3
  134. package/dist/pipeline/executeProviderCall.js +1 -1
  135. package/dist/pipeline/resolveProviderChain.d.cts +2 -3
  136. package/dist/pipeline/resolveProviderChain.d.ts +2 -3
  137. package/dist/pipeline/resolveSubscriptionChain.d.cts +1 -0
  138. package/dist/pipeline/resolveSubscriptionChain.d.ts +1 -0
  139. package/dist/pipeline/upstreamFetch.cjs +5 -3
  140. package/dist/pipeline/upstreamFetch.d.cts +35 -6
  141. package/dist/pipeline/upstreamFetch.d.ts +35 -6
  142. package/dist/pipeline/upstreamFetch.js +4 -2
  143. package/dist/pipeline/upstreamTrace.cjs +4 -2
  144. package/dist/pipeline/upstreamTrace.d.cts +22 -8
  145. package/dist/pipeline/upstreamTrace.d.ts +22 -8
  146. package/dist/pipeline/upstreamTrace.js +3 -1
  147. package/dist/ports/pricing-store.d.cts +4 -3
  148. package/dist/ports/pricing-store.d.ts +4 -3
  149. package/dist/ports.d.cts +4 -3
  150. package/dist/ports.d.ts +4 -3
  151. package/dist/provider-proxy/ProviderProxy.cjs +30 -24
  152. package/dist/provider-proxy/ProviderProxy.d.cts +2 -0
  153. package/dist/provider-proxy/ProviderProxy.d.ts +2 -0
  154. package/dist/provider-proxy/ProviderProxy.js +29 -23
  155. package/dist/provider-proxy/identity/codexCliHeaders.cjs +10 -0
  156. package/dist/provider-proxy/identity/codexCliHeaders.d.cts +45 -0
  157. package/dist/provider-proxy/identity/codexCliHeaders.d.ts +45 -0
  158. package/dist/provider-proxy/identity/codexCliHeaders.js +10 -0
  159. package/dist/provider-proxy/ingress/providerProxyShared.cjs +32 -24
  160. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +44 -5
  161. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +44 -5
  162. package/dist/provider-proxy/ingress/providerProxyShared.js +31 -23
  163. package/dist/provider-proxy/matchText.cjs +4 -2
  164. package/dist/provider-proxy/matchText.d.cts +39 -6
  165. package/dist/provider-proxy/matchText.d.ts +39 -6
  166. package/dist/provider-proxy/matchText.js +3 -1
  167. package/dist/provider-proxy/types.d.cts +35 -2
  168. package/dist/provider-proxy/types.d.ts +35 -2
  169. package/dist/provider-proxy.cjs +30 -24
  170. package/dist/provider-proxy.d.cts +2 -0
  171. package/dist/provider-proxy.d.ts +2 -0
  172. package/dist/provider-proxy.js +29 -23
  173. package/dist/{routeResolver-C4T7yClx.d.ts → routeResolver-BxOfunbm.d.ts} +1 -1
  174. package/dist/{routeResolver-CB3tvJKy.d.cts → routeResolver-D5OzD0iM.d.cts} +1 -1
  175. package/dist/transformer/TransformerChainExecutor.cjs +2 -2
  176. package/dist/transformer/TransformerChainExecutor.js +1 -1
  177. package/dist/transformer/transformers/AnthropicTransformer.cjs +3 -2
  178. package/dist/transformer/transformers/AnthropicTransformer.js +2 -1
  179. package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +3 -3
  180. package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +2 -2
  181. package/dist/transformer/transformers/GeminiTransformer.cjs +3 -3
  182. package/dist/transformer/transformers/GeminiTransformer.js +2 -2
  183. package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +3 -2
  184. package/dist/transformer/transformers/OpenAIResponseTransformer.d.cts +1 -1
  185. package/dist/transformer/transformers/OpenAIResponseTransformer.d.ts +1 -1
  186. package/dist/transformer/transformers/OpenAIResponseTransformer.js +2 -1
  187. package/dist/transformer/transformers/OpenAITransformer.cjs +6 -0
  188. package/dist/transformer/transformers/OpenAITransformer.d.cts +68 -0
  189. package/dist/transformer/transformers/OpenAITransformer.d.ts +68 -0
  190. package/dist/transformer/transformers/OpenAITransformer.js +6 -0
  191. package/dist/transformer/transformers.cjs +9 -14
  192. package/dist/transformer/transformers.d.cts +12 -48
  193. package/dist/transformer/transformers.d.ts +12 -48
  194. package/dist/transformer/transformers.js +11 -16
  195. package/dist/transformer/types.d.cts +17 -0
  196. package/dist/transformer/types.d.ts +17 -0
  197. package/dist/transformer.cjs +12 -12
  198. package/dist/transformer.d.cts +1 -2
  199. package/dist/transformer.d.ts +1 -2
  200. package/dist/transformer.js +12 -12
  201. package/dist/{types-lgPYQuZS.d.ts → types-CqZD77rS.d.ts} +173 -7
  202. package/dist/{types-B8Arpxn0.d.cts → types-gjJ5lJ5n.d.cts} +173 -7
  203. package/dist/usage/pricing-engine.cjs +2 -2
  204. package/dist/usage/pricing-engine.d.cts +29 -1
  205. package/dist/usage/pricing-engine.d.ts +29 -1
  206. package/dist/usage/pricing-engine.js +1 -1
  207. package/dist/usage/usage-recorder.cjs +2 -2
  208. package/dist/usage/usage-recorder.d.cts +5 -1
  209. package/dist/usage/usage-recorder.d.ts +5 -1
  210. package/dist/usage/usage-recorder.js +1 -1
  211. package/dist/usage.cjs +3 -3
  212. package/dist/usage.js +2 -2
  213. package/package.json +1 -1
  214. package/dist/chunk-7FEBOPJO.cjs +0 -50
  215. package/dist/chunk-DWKQZ2SK.cjs +0 -254
  216. package/dist/chunk-IAXWICZU.js +0 -69
  217. package/dist/chunk-IB3FDI4O.js +0 -50
  218. package/dist/chunk-OQWKZCXP.js +0 -242
  219. package/dist/chunk-QWBWGODS.cjs +0 -69
  220. package/dist/chunk-YMFAJFQT.cjs +0 -173
  221. package/dist/chunk-ZCIQ3L3R.cjs +0 -242
  222. package/dist/chunk-ZJZAOKI7.js +0 -254
  223. package/dist/chunk-ZLX3KGXX.js +0 -173
  224. package/dist/transformer/transformers/OpenCodeGoTransformer.cjs +0 -6
  225. package/dist/transformer/transformers/OpenCodeGoTransformer.d.cts +0 -51
  226. package/dist/transformer/transformers/OpenCodeGoTransformer.d.ts +0 -51
  227. package/dist/transformer/transformers/OpenCodeGoTransformer.js +0 -6
  228. package/dist/transformer/transformers/ReasoningTransformer.cjs +0 -6
  229. package/dist/transformer/transformers/ReasoningTransformer.d.cts +0 -47
  230. package/dist/transformer/transformers/ReasoningTransformer.d.ts +0 -47
  231. package/dist/transformer/transformers/ReasoningTransformer.js +0 -6
@@ -9,7 +9,8 @@ import { PricingStore } from '../ports/pricing-store.js';
9
9
  * Persistence goes through the injected `PricingStore` port. Sources of
10
10
  * pricing rows:
11
11
  * - 'builtin' — bundled fallback prices, seeded by the host
12
- * - 'litellm' — refreshed on user demand from LiteLLM's public JSON
12
+ * - 'litellm' — primary catalog from LiteLLM's public JSON
13
+ * - 'openrouter' — supplemental OpenRouter route pricing
13
14
  * - 'user' — hand-edited; protected from auto-overwrite
14
15
  *
15
16
  * @module usage/pricing-engine
@@ -29,8 +30,12 @@ interface CostCalculation {
29
30
  interface PricingEngineOptions {
30
31
  /** Override the pricing-source JSON URL — useful for testing. */
31
32
  sourceUrl?: string;
33
+ /** Override the supplemental OpenRouter catalog URL. */
34
+ openRouterSourceUrl?: string;
32
35
  /** Override `fetch` — useful for testing. */
33
36
  fetchImpl?: typeof fetch;
37
+ /** Bound each remote source independently; both sources are fetched in parallel. */
38
+ fetchTimeoutMs?: number;
34
39
  }
35
40
  declare class PricingEngine {
36
41
  private store;
@@ -45,7 +50,18 @@ declare class PricingEngine {
45
50
  * non-wildcard entry per model wins.
46
51
  */
47
52
  private cacheByModel;
53
+ /**
54
+ * Last-resort fuzzy index: `[normalizedModelId, entry]` pairs over the same
55
+ * non-wildcard, non-openrouter rows as `cacheByModel`. Used when even the
56
+ * model-name fallback misses — e.g. usage recorded under a bare model id
57
+ * (`glm-5.2`) while the catalog only knows prefixed slugs
58
+ * (`cloudflare/@cf/zai-org/glm-5.2`). This is an ESTIMATE: the matched row
59
+ * may be an aggregate-route price rather than the direct-vendor rate.
60
+ */
61
+ private fuzzyEntries;
48
62
  private cacheLoaded;
63
+ /** Coalesce manual and background refreshes to prevent a catalog stampede. */
64
+ private refreshInFlight;
49
65
  constructor(store: PricingStore, logger: Logger, options?: PricingEngineOptions);
50
66
  /** Lazy-load and cache the full pricing table. */
51
67
  private ensureCache;
@@ -58,8 +74,19 @@ declare class PricingEngine {
58
74
  * 2. wildcard provider ('*', modelId)
59
75
  * 3. model name alone (any provider) — tolerates a runtime-alias vs
60
76
  * canonical provider-id mismatch for the same model.
77
+ * 4. normalized fuzzy match (last resort) — matches a bare id like
78
+ * `glm-5.2` against prefixed catalog slugs like
79
+ * `cloudflare/@cf/zai-org/glm-5.2`. ESTIMATE only: the matched row may
80
+ * be an aggregate-route price, not the direct-vendor rate.
61
81
  */
62
82
  getEntry(providerId: string, modelId: string): Promise<PricingEntry | null>;
83
+ /**
84
+ * Normalized substring match over the catalog's non-openrouter rows. Lowercases
85
+ * and strips all non-alphanumerics, then matches bidirectionally, preferring
86
+ * the shortest catalog key (tightest match) to reduce over-matching version
87
+ * variants. Returns null when nothing matches.
88
+ */
89
+ private fuzzyMatch;
63
90
  /**
64
91
  * Compute the cost (and cache savings) for a single response.
65
92
  *
@@ -77,6 +104,7 @@ declare class PricingEngine {
77
104
  calculateCost(providerId: string, modelId: string, usage: UsageTokens): Promise<CostCalculation>;
78
105
  upsertManual(input: PricingEntryInput): Promise<PricingEntry>;
79
106
  fetchLatestFromSource(): Promise<PricingFetchResult>;
107
+ private refreshSources;
80
108
  resolveConflicts(decisions: PricingConflictDecision[], pendingIncoming: Map<string, PricingEntryInput>): Promise<PricingResolution>;
81
109
  }
82
110
 
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PricingEngine
3
- } from "../chunk-ZLX3KGXX.js";
3
+ } from "../chunk-FXR6N3SR.js";
4
4
  export {
5
5
  PricingEngine
6
6
  };
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkSNYBEXLBcjs = require('../chunk-SNYBEXLB.cjs');
3
+ var _chunkOJGQKHN5cjs = require('../chunk-OJGQKHN5.cjs');
4
4
  require('../chunk-XSVNC2UD.cjs');
5
5
 
6
6
 
7
- exports.UsageRecorder = _chunkSNYBEXLBcjs.UsageRecorder;
7
+ exports.UsageRecorder = _chunkOJGQKHN5cjs.UsageRecorder;
@@ -1,5 +1,5 @@
1
1
  import { PricingEngine } from './pricing-engine.cjs';
2
- import { UsageDateRange, UsageTotals, ModelUsageRow, ApiKeyUsageRow, UsageTimeBucket, UsageTimeSeriesBucket, MessageUsageRow, SessionCacheStats } from '@omnicross/contracts/usage-stats-types';
2
+ import { UsageCacheKeySource, UsageDateRange, UsageTotals, ModelUsageRow, ApiKeyUsageRow, UsageTimeBucket, UsageTimeSeriesBucket, MessageUsageRow, SessionCacheStats } from '@omnicross/contracts/usage-stats-types';
3
3
  import { UsageEngineOrigin, UsageTokens } from '@omnicross/contracts/usage-types';
4
4
  import { L as Logger } from '../logger-4GvQNzhE.cjs';
5
5
  import { UsageEventStore } from '../ports/usage-event-store.cjs';
@@ -34,6 +34,10 @@ interface UsageRecordInput {
34
34
  runId?: string | null;
35
35
  /** Host event-correlation id for this call. Optional / additive. */
36
36
  eventId?: string | null;
37
+ /** Safe prompt-cache-key provenance; raw key material is never recorded. */
38
+ cacheKeySource?: UsageCacheKeySource;
39
+ /** Whether the gateway, rather than the client, attached the cache key. */
40
+ cacheKeyInjected?: boolean;
37
41
  /**
38
42
  * OPTIONAL per-request audit correlation key (request-audit-log). When the
39
43
  * OUTBOUND relay taps set this to the request's `http.ServerResponse`, the
@@ -1,5 +1,5 @@
1
1
  import { PricingEngine } from './pricing-engine.js';
2
- import { UsageDateRange, UsageTotals, ModelUsageRow, ApiKeyUsageRow, UsageTimeBucket, UsageTimeSeriesBucket, MessageUsageRow, SessionCacheStats } from '@omnicross/contracts/usage-stats-types';
2
+ import { UsageCacheKeySource, UsageDateRange, UsageTotals, ModelUsageRow, ApiKeyUsageRow, UsageTimeBucket, UsageTimeSeriesBucket, MessageUsageRow, SessionCacheStats } from '@omnicross/contracts/usage-stats-types';
3
3
  import { UsageEngineOrigin, UsageTokens } from '@omnicross/contracts/usage-types';
4
4
  import { L as Logger } from '../logger-4GvQNzhE.js';
5
5
  import { UsageEventStore } from '../ports/usage-event-store.js';
@@ -34,6 +34,10 @@ interface UsageRecordInput {
34
34
  runId?: string | null;
35
35
  /** Host event-correlation id for this call. Optional / additive. */
36
36
  eventId?: string | null;
37
+ /** Safe prompt-cache-key provenance; raw key material is never recorded. */
38
+ cacheKeySource?: UsageCacheKeySource;
39
+ /** Whether the gateway, rather than the client, attached the cache key. */
40
+ cacheKeyInjected?: boolean;
37
41
  /**
38
42
  * OPTIONAL per-request audit correlation key (request-audit-log). When the
39
43
  * OUTBOUND relay taps set this to the request's `http.ServerResponse`, the
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  UsageRecorder
3
- } from "../chunk-BPKCU575.js";
3
+ } from "../chunk-SOO562NM.js";
4
4
  import "../chunk-OZFM4X3S.js";
5
5
  export {
6
6
  UsageRecorder
package/dist/usage.cjs CHANGED
@@ -1,12 +1,12 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});require('./chunk-EYZYXJTJ.cjs');
2
2
 
3
3
 
4
- var _chunkYMFAJFQTcjs = require('./chunk-YMFAJFQT.cjs');
4
+ var _chunk2E42SAW3cjs = require('./chunk-2E42SAW3.cjs');
5
5
 
6
6
 
7
- var _chunkSNYBEXLBcjs = require('./chunk-SNYBEXLB.cjs');
7
+ var _chunkOJGQKHN5cjs = require('./chunk-OJGQKHN5.cjs');
8
8
  require('./chunk-XSVNC2UD.cjs');
9
9
 
10
10
 
11
11
 
12
- exports.PricingEngine = _chunkYMFAJFQTcjs.PricingEngine; exports.UsageRecorder = _chunkSNYBEXLBcjs.UsageRecorder;
12
+ exports.PricingEngine = _chunk2E42SAW3cjs.PricingEngine; exports.UsageRecorder = _chunkOJGQKHN5cjs.UsageRecorder;
package/dist/usage.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import "./chunk-7VU7V2E4.js";
2
2
  import {
3
3
  PricingEngine
4
- } from "./chunk-ZLX3KGXX.js";
4
+ } from "./chunk-FXR6N3SR.js";
5
5
  import {
6
6
  UsageRecorder
7
- } from "./chunk-BPKCU575.js";
7
+ } from "./chunk-SOO562NM.js";
8
8
  import "./chunk-OZFM4X3S.js";
9
9
  export {
10
10
  PricingEngine,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnicross/core",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Omnicross LLM serving core 鈥?provider dispatch, completion pipeline, transformers, and the provider proxy.",
5
5
  "license": "MIT",
6
6
  "author": "Sayo (https://github.com/Dumoedss)",
@@ -1,50 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;// src/transformer/transformers/OpenCodeGoTransformer.ts
2
- var OpenCodeGoTransformer = (_class = class {constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this); }
3
- static __initStatic() {this.TransformerName = "opencodego"}
4
- __init() {this.name = "opencodego"}
5
- __init2() {this.endPoint = "/v1/chat/completions"}
6
-
7
- async auth(request, _provider, _context) {
8
- return { body: request, config: { headers: {} } };
9
- }
10
- /**
11
- * Unified → OpenAI Chat Completions.
12
- * Unified IS chat completions shape; this is mostly stripping `meta` and
13
- * normalizing string-content single-block messages.
14
- */
15
- async transformRequestIn(request, _provider, _context) {
16
- const messages = request.messages.map((m) => {
17
- const content = m.content;
18
- const normalizedContent = Array.isArray(content) && content.length === 1 && _optionalChain([content, 'access', _ => _[0], 'optionalAccess', _2 => _2.type]) === "text" ? content[0].text : content;
19
- const out2 = { role: m.role, content: normalizedContent };
20
- if (m.tool_calls) out2.tool_calls = m.tool_calls;
21
- if (m.tool_call_id) out2.tool_call_id = m.tool_call_id;
22
- return out2;
23
- });
24
- const out = {
25
- model: request.model,
26
- messages,
27
- stream: request.stream
28
- };
29
- if (request.temperature !== void 0) out.temperature = request.temperature;
30
- if (request.max_tokens !== void 0) out.max_tokens = request.max_tokens;
31
- if (request.tools && request.tools.length > 0) out.tools = request.tools;
32
- if (request.tool_choice !== void 0) out.tool_choice = request.tool_choice;
33
- if (_optionalChain([request, 'access', _3 => _3.reasoning, 'optionalAccess', _4 => _4.effort]) && request.reasoning.effort !== "none") {
34
- out.reasoning_effort = request.reasoning.effort;
35
- }
36
- return out;
37
- }
38
- /**
39
- * OpenAI Chat Completions response → Unified.
40
- * The upstream's response shape already matches Unified — pass through.
41
- * The endpoint AnthropicTransformer re-encodes to Anthropic for the SDK.
42
- */
43
- async transformResponseOut(response, _context) {
44
- return response;
45
- }
46
- }, _class.__initStatic(), _class);
47
-
48
-
49
-
50
- exports.OpenCodeGoTransformer = OpenCodeGoTransformer;
@@ -1,254 +0,0 @@
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/ReasoningTransformer.ts
2
-
3
-
4
-
5
-
6
-
7
- var _thinkingconfig = require('@omnicross/contracts/thinking-config');
8
- var ReasoningTransformer = (_class = class {
9
- static __initStatic() {this.TransformerName = "reasoning"}
10
- __init() {this.name = "reasoning"}
11
-
12
-
13
- constructor(options) {;_class.prototype.__init.call(this);
14
- this.enabled = _optionalChain([options, 'optionalAccess', _ => _.enable]) !== false;
15
- }
16
- /**
17
- * Transform request: convert reasoning config to thinking parameters
18
- * Uses model-specific budget calculation based on effort level
19
- */
20
- async transformRequestIn(request, provider, _context) {
21
- const extendedRequest = request;
22
- const modelId = request.model;
23
- if (!this.enabled) {
24
- extendedRequest.thinking = {
25
- type: "disabled",
26
- budget_tokens: -1
27
- };
28
- extendedRequest.enable_thinking = false;
29
- return extendedRequest;
30
- }
31
- if (request.reasoning) {
32
- const effortLevel = request.reasoning.effort || "none";
33
- const userMaxTokens = request.reasoning.max_tokens || request.max_tokens;
34
- const calculatedBudget = _thinkingconfig.calculateThinkingBudget.call(void 0, modelId, effortLevel, userMaxTokens);
35
- const providerName = _optionalChain([provider, 'access', _2 => _2.name, 'optionalAccess', _3 => _3.toLowerCase, 'call', _4 => _4()]) || "";
36
- if (providerName === "anthropic" || providerName.includes("claude")) {
37
- const thinkingConfig = _thinkingconfig.buildAnthropicThinking.call(void 0, modelId, effortLevel, userMaxTokens);
38
- if (thinkingConfig) {
39
- extendedRequest.thinking = thinkingConfig;
40
- } else {
41
- extendedRequest.thinking = {
42
- type: "disabled"
43
- };
44
- }
45
- } else if (providerName === "openai" || modelId.match(/^o[134]/i)) {
46
- const reasoningEffort = _thinkingconfig.getOpenAIReasoningEffort.call(void 0, effortLevel);
47
- if (reasoningEffort) {
48
- extendedRequest.reasoning_effort = reasoningEffort;
49
- }
50
- extendedRequest.thinking = {
51
- type: effortLevel === "none" ? "disabled" : "enabled",
52
- budget_tokens: calculatedBudget
53
- };
54
- } else if (providerName === "deepseek" && _optionalChain([modelId, 'optionalAccess', _5 => _5.startsWith, 'call', _6 => _6("deepseek-v4")])) {
55
- extendedRequest.thinking = {
56
- type: effortLevel === "none" ? "disabled" : "enabled",
57
- budget_tokens: calculatedBudget
58
- };
59
- if (effortLevel !== "none") {
60
- extendedRequest.reasoning_effort = effortLevel === "high" ? "max" : "high";
61
- }
62
- } else if (providerName === "deepseek" || providerName === "qwen" || providerName === "alibaba") {
63
- const qwenConfig = _thinkingconfig.buildQwenThinkingConfig.call(void 0, effortLevel, userMaxTokens);
64
- extendedRequest.enable_thinking = qwenConfig.enable_thinking;
65
- if (qwenConfig.thinking_budget) {
66
- extendedRequest.thinking_budget = qwenConfig.thinking_budget;
67
- }
68
- extendedRequest.thinking = {
69
- type: qwenConfig.enable_thinking ? "enabled" : "disabled",
70
- budget_tokens: calculatedBudget
71
- };
72
- } else {
73
- extendedRequest.thinking = {
74
- type: effortLevel === "none" ? "disabled" : "enabled",
75
- budget_tokens: calculatedBudget
76
- };
77
- extendedRequest.enable_thinking = effortLevel !== "none";
78
- }
79
- _optionalChain([this, 'access', _7 => _7.logger, 'optionalAccess', _8 => _8.debug, 'call', _9 => _9(`[ReasoningTransformer] Model: ${modelId}, Effort: ${effortLevel}, Budget: ${calculatedBudget}`)]);
80
- }
81
- return extendedRequest;
82
- }
83
- /**
84
- * Transform response: convert reasoning_content to thinking blocks
85
- */
86
- async transformResponseOut(response, _context) {
87
- if (!this.enabled) return response;
88
- const contentType = _nullishCoalesce(response.headers.get("Content-Type"), () => ( ""));
89
- if (contentType.includes("application/json")) {
90
- return this.handleJsonResponse(response);
91
- } else if (contentType.includes("stream") || contentType.includes("text/event-stream")) {
92
- return this.handleStreamResponse(response);
93
- }
94
- return response;
95
- }
96
- /**
97
- * Handle JSON (non-streaming) response
98
- */
99
- async handleJsonResponse(response) {
100
- const jsonResponse = await response.json();
101
- if (_optionalChain([jsonResponse, 'access', _10 => _10.choices, 'optionalAccess', _11 => _11[0], 'optionalAccess', _12 => _12.message, 'optionalAccess', _13 => _13.reasoning_content])) {
102
- jsonResponse.thinking = {
103
- content: jsonResponse.choices[0].message.reasoning_content
104
- };
105
- delete jsonResponse.choices[0].message.reasoning_content;
106
- }
107
- return new Response(JSON.stringify(jsonResponse), {
108
- status: response.status,
109
- statusText: response.statusText,
110
- headers: response.headers
111
- });
112
- }
113
- /**
114
- * Handle streaming response - convert reasoning_content to thinking blocks
115
- */
116
- handleStreamResponse(response) {
117
- if (!response.body) {
118
- return response;
119
- }
120
- const decoder = new TextDecoder();
121
- const encoder = new TextEncoder();
122
- let reasoningContent = "";
123
- let isReasoningComplete = false;
124
- let buffer = "";
125
- const stream = new ReadableStream({
126
- start: async (controller) => {
127
- const reader = response.body.getReader();
128
- const processLine = (line) => {
129
- _optionalChain([this, 'access', _14 => _14.logger, 'optionalAccess', _15 => _15.debug, 'call', _16 => _16("Processing reasoning line:", line)]);
130
- if (line.startsWith("data: ") && line.trim() !== "data: [DONE]") {
131
- try {
132
- const data = JSON.parse(line.slice(6));
133
- if (_optionalChain([data, 'access', _17 => _17.choices, 'optionalAccess', _18 => _18[0], 'optionalAccess', _19 => _19.delta, 'optionalAccess', _20 => _20.reasoning_content])) {
134
- reasoningContent += data.choices[0].delta.reasoning_content;
135
- const thinkingChunk = {
136
- ...data,
137
- choices: [
138
- {
139
- ...data.choices[0],
140
- delta: {
141
- ...data.choices[0].delta,
142
- thinking: {
143
- content: data.choices[0].delta.reasoning_content
144
- }
145
- }
146
- }
147
- ]
148
- };
149
- delete thinkingChunk.choices[0].delta.reasoning_content;
150
- const thinkingLine = `data: ${JSON.stringify(thinkingChunk)}
151
-
152
- `;
153
- controller.enqueue(encoder.encode(thinkingLine));
154
- return;
155
- }
156
- if ((_optionalChain([data, 'access', _21 => _21.choices, 'optionalAccess', _22 => _22[0], 'optionalAccess', _23 => _23.delta, 'optionalAccess', _24 => _24.content]) || _optionalChain([data, 'access', _25 => _25.choices, 'optionalAccess', _26 => _26[0], 'optionalAccess', _27 => _27.delta, 'optionalAccess', _28 => _28.tool_calls])) && reasoningContent && !isReasoningComplete) {
157
- isReasoningComplete = true;
158
- const signature = Date.now().toString();
159
- const thinkingChunk = {
160
- ...data,
161
- choices: [
162
- {
163
- ...data.choices[0],
164
- delta: {
165
- ...data.choices[0].delta,
166
- content: null,
167
- thinking: {
168
- signature
169
- }
170
- }
171
- }
172
- ]
173
- };
174
- delete thinkingChunk.choices[0].delta.reasoning_content;
175
- const thinkingLine = `data: ${JSON.stringify(thinkingChunk)}
176
-
177
- `;
178
- controller.enqueue(encoder.encode(thinkingLine));
179
- }
180
- if (_optionalChain([data, 'access', _29 => _29.choices, 'optionalAccess', _30 => _30[0], 'optionalAccess', _31 => _31.delta, 'optionalAccess', _32 => _32.reasoning_content])) {
181
- delete data.choices[0].delta.reasoning_content;
182
- }
183
- if (_optionalChain([data, 'access', _33 => _33.choices, 'optionalAccess', _34 => _34[0], 'optionalAccess', _35 => _35.delta]) && Object.keys(data.choices[0].delta).length > 0) {
184
- if (isReasoningComplete) {
185
- data.choices[0].index++;
186
- }
187
- const modifiedLine = `data: ${JSON.stringify(data)}
188
-
189
- `;
190
- controller.enqueue(encoder.encode(modifiedLine));
191
- }
192
- } catch (_e) {
193
- controller.enqueue(encoder.encode(line + "\n"));
194
- }
195
- } else {
196
- controller.enqueue(encoder.encode(line + "\n"));
197
- }
198
- };
199
- try {
200
- while (true) {
201
- const { done, value } = await reader.read();
202
- if (done) {
203
- if (buffer.trim()) {
204
- const lines2 = buffer.split("\n");
205
- for (const line of lines2) {
206
- if (line.trim()) {
207
- controller.enqueue(encoder.encode(line + "\n"));
208
- }
209
- }
210
- }
211
- break;
212
- }
213
- const chunk = decoder.decode(value, { stream: true });
214
- buffer += chunk;
215
- const lines = buffer.split("\n");
216
- buffer = lines.pop() || "";
217
- for (const line of lines) {
218
- if (!line.trim()) continue;
219
- try {
220
- processLine(line);
221
- } catch (error) {
222
- _optionalChain([this, 'access', _36 => _36.logger, 'optionalAccess', _37 => _37.error, 'call', _38 => _38("Error processing reasoning stream line:", error)]);
223
- controller.enqueue(encoder.encode(line + "\n"));
224
- }
225
- }
226
- }
227
- } catch (error) {
228
- _optionalChain([this, 'access', _39 => _39.logger, 'optionalAccess', _40 => _40.error, 'call', _41 => _41("Reasoning stream error:", error)]);
229
- controller.error(error);
230
- } finally {
231
- try {
232
- reader.releaseLock();
233
- } catch (e) {
234
- _optionalChain([this, 'access', _42 => _42.logger, 'optionalAccess', _43 => _43.error, 'call', _44 => _44("Error releasing reader lock:", e)]);
235
- }
236
- controller.close();
237
- }
238
- }
239
- });
240
- return new Response(stream, {
241
- status: response.status,
242
- statusText: response.statusText,
243
- headers: new Headers({
244
- "Content-Type": "text/event-stream",
245
- "Cache-Control": "no-cache",
246
- Connection: "keep-alive"
247
- })
248
- });
249
- }
250
- }, _class.__initStatic(), _class);
251
-
252
-
253
-
254
- exports.ReasoningTransformer = ReasoningTransformer;
@@ -1,69 +0,0 @@
1
- // src/provider-proxy/matchText.ts
2
- var MATCH_TEXT_PER_MESSAGE_CAP = 8192;
3
- var MATCH_TEXT_RECENT_MESSAGES = 6;
4
- function flattenMatchText(value) {
5
- if (typeof value === "string") return value;
6
- if (Array.isArray(value)) {
7
- const parts = [];
8
- for (const item of value) {
9
- const text = flattenMatchText(item);
10
- if (text) parts.push(text);
11
- }
12
- return parts.join("\n");
13
- }
14
- if (value && typeof value === "object") {
15
- const obj = value;
16
- if (obj.type === "tool_result" && obj.content !== void 0) {
17
- return flattenMatchText(obj.content);
18
- }
19
- if (typeof obj.text === "string") return obj.text;
20
- }
21
- return "";
22
- }
23
- function collectMatchText(anthropicBody) {
24
- const messages = Array.isArray(anthropicBody.messages) ? anthropicBody.messages : [];
25
- const slices = [];
26
- const sys = flattenMatchText(anthropicBody.system).trim();
27
- if (sys) slices.push(sys.slice(0, MATCH_TEXT_PER_MESSAGE_CAP));
28
- const recent = [];
29
- for (let i = messages.length - 1; i >= 0 && recent.length < MATCH_TEXT_RECENT_MESSAGES; i--) {
30
- const message = messages[i];
31
- if (!message || typeof message !== "object") continue;
32
- const role = message.role;
33
- if (role !== "user" && role !== "system") continue;
34
- const text = flattenMatchText(message.content).trim();
35
- if (text) recent.push(text.slice(0, MATCH_TEXT_PER_MESSAGE_CAP));
36
- }
37
- for (let i = recent.length - 1; i >= 0; i--) slices.push(recent[i]);
38
- return slices;
39
- }
40
- function deriveSubscriptionSessionKey(anthropicBody) {
41
- const system = flattenMatchText(anthropicBody.system).trim().slice(0, MATCH_TEXT_PER_MESSAGE_CAP);
42
- const messages = Array.isArray(anthropicBody.messages) ? anthropicBody.messages : [];
43
- let firstUser = "";
44
- for (const message of messages) {
45
- if (message && typeof message === "object" && message.role === "user") {
46
- firstUser = flattenMatchText(message.content).trim().slice(0, MATCH_TEXT_PER_MESSAGE_CAP);
47
- break;
48
- }
49
- }
50
- const anchor = `${system}\0${firstUser}`;
51
- if (!system && !firstUser) return void 0;
52
- return fnv1a(anchor);
53
- }
54
- function fnv1a(str) {
55
- let h = 2166136261;
56
- for (let i = 0; i < str.length; i++) {
57
- h ^= str.charCodeAt(i);
58
- h = Math.imul(h, 16777619);
59
- }
60
- return (h >>> 0).toString(16).padStart(8, "0");
61
- }
62
-
63
- export {
64
- MATCH_TEXT_PER_MESSAGE_CAP,
65
- MATCH_TEXT_RECENT_MESSAGES,
66
- flattenMatchText,
67
- collectMatchText,
68
- deriveSubscriptionSessionKey
69
- };
@@ -1,50 +0,0 @@
1
- // src/transformer/transformers/OpenCodeGoTransformer.ts
2
- var OpenCodeGoTransformer = class {
3
- static TransformerName = "opencodego";
4
- name = "opencodego";
5
- endPoint = "/v1/chat/completions";
6
- logger;
7
- async auth(request, _provider, _context) {
8
- return { body: request, config: { headers: {} } };
9
- }
10
- /**
11
- * Unified → OpenAI Chat Completions.
12
- * Unified IS chat completions shape; this is mostly stripping `meta` and
13
- * normalizing string-content single-block messages.
14
- */
15
- async transformRequestIn(request, _provider, _context) {
16
- const messages = request.messages.map((m) => {
17
- const content = m.content;
18
- const normalizedContent = Array.isArray(content) && content.length === 1 && content[0]?.type === "text" ? content[0].text : content;
19
- const out2 = { role: m.role, content: normalizedContent };
20
- if (m.tool_calls) out2.tool_calls = m.tool_calls;
21
- if (m.tool_call_id) out2.tool_call_id = m.tool_call_id;
22
- return out2;
23
- });
24
- const out = {
25
- model: request.model,
26
- messages,
27
- stream: request.stream
28
- };
29
- if (request.temperature !== void 0) out.temperature = request.temperature;
30
- if (request.max_tokens !== void 0) out.max_tokens = request.max_tokens;
31
- if (request.tools && request.tools.length > 0) out.tools = request.tools;
32
- if (request.tool_choice !== void 0) out.tool_choice = request.tool_choice;
33
- if (request.reasoning?.effort && request.reasoning.effort !== "none") {
34
- out.reasoning_effort = request.reasoning.effort;
35
- }
36
- return out;
37
- }
38
- /**
39
- * OpenAI Chat Completions response → Unified.
40
- * The upstream's response shape already matches Unified — pass through.
41
- * The endpoint AnthropicTransformer re-encodes to Anthropic for the SDK.
42
- */
43
- async transformResponseOut(response, _context) {
44
- return response;
45
- }
46
- };
47
-
48
- export {
49
- OpenCodeGoTransformer
50
- };