@omnicross/core 0.1.1 → 0.1.2

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 (210) hide show
  1. package/dist/ApiConverter.cjs +3 -778
  2. package/dist/ApiConverter.js +12 -751
  3. package/dist/{CompletionService-DtOF_War.d.cts → CompletionService-D3a47vdU.d.cts} +2 -1
  4. package/dist/{CompletionService-7fCmKAP3.d.ts → CompletionService-DdWaAxq0.d.ts} +2 -1
  5. package/dist/auth/GeminiCodeAssistProjectResolver.cjs +27 -60
  6. package/dist/auth/GeminiCodeAssistProjectResolver.js +5 -9
  7. package/dist/builtin-web-fetch-77JZUZGM.cjs +100 -0
  8. package/dist/builtin-web-fetch-IGLBX2XY.js +100 -0
  9. package/dist/chunk-2DCNB7DF.cjs +514 -0
  10. package/dist/chunk-2FEVTJWG.js +4400 -0
  11. package/dist/chunk-3MEACFK3.js +193 -0
  12. package/dist/chunk-3OPYJG76.cjs +266 -0
  13. package/dist/chunk-46RLHI7D.js +0 -0
  14. package/dist/chunk-46ZIFWYG.cjs +277 -0
  15. package/dist/chunk-4NBS6KPV.cjs +43 -0
  16. package/dist/chunk-4VAVYUZS.cjs +991 -0
  17. package/dist/chunk-5ERIZW3D.js +44 -0
  18. package/dist/chunk-5HTVET6E.js +514 -0
  19. package/dist/chunk-5ZQBEOMD.js +764 -0
  20. package/dist/chunk-6VIXXLMX.cjs +14 -0
  21. package/dist/chunk-745DV5FL.js +147 -0
  22. package/dist/chunk-74TMJA7Z.js +53 -0
  23. package/dist/chunk-7VU7V2E4.js +0 -0
  24. package/dist/chunk-7YN22L2H.cjs +87 -0
  25. package/dist/chunk-A2YMUCBT.cjs +105 -0
  26. package/dist/chunk-AQ5TNQB7.js +13 -0
  27. package/dist/chunk-AVYJ4YBN.js +58 -0
  28. package/dist/chunk-C72S6TTV.cjs +49 -0
  29. package/dist/chunk-C7PSERMH.js +87 -0
  30. package/dist/chunk-CDHS2QDC.js +179 -0
  31. package/dist/chunk-DK4A7DLE.js +266 -0
  32. package/dist/chunk-DRWHTIIZ.js +13 -0
  33. package/dist/chunk-DWKQZ2SK.cjs +254 -0
  34. package/dist/chunk-E3WHL7CO.js +14 -0
  35. package/dist/chunk-EYZYXJTJ.cjs +1 -0
  36. package/dist/chunk-FMOBD2OQ.js +39 -0
  37. package/dist/chunk-FTQ7IQUC.js +991 -0
  38. package/dist/chunk-FZ46M34D.cjs +1 -0
  39. package/dist/chunk-G2FUJNA2.cjs +193 -0
  40. package/dist/chunk-G2UTNSGU.js +277 -0
  41. package/dist/chunk-GBHYAGX3.cjs +26 -0
  42. package/dist/chunk-GMMT7RVN.cjs +39 -0
  43. package/dist/chunk-H5JUT3KV.js +105 -0
  44. package/dist/chunk-HQP3K7PU.cjs +431 -0
  45. package/dist/chunk-JO5NLTLY.js +46 -0
  46. package/dist/chunk-JWC6APFQ.js +23 -0
  47. package/dist/chunk-KUU2RNG6.cjs +46 -0
  48. package/dist/chunk-LKZJEL6E.cjs +124 -0
  49. package/dist/chunk-MNYKI4CI.js +94 -0
  50. package/dist/chunk-MZNPGW5Q.js +26 -0
  51. package/dist/chunk-N3V2J5ZO.cjs +53 -0
  52. package/dist/chunk-NYUNU75A.cjs +44 -0
  53. package/dist/chunk-NZYN7C3P.cjs +179 -0
  54. package/dist/chunk-O466Y272.js +235 -0
  55. package/dist/chunk-PXUJF5HS.js +124 -0
  56. package/dist/chunk-QBZJ7P2T.cjs +13 -0
  57. package/dist/chunk-QOCNX236.js +46 -0
  58. package/dist/chunk-QXD4MV2X.cjs +23 -0
  59. package/dist/chunk-R3HK6R4B.cjs +13 -0
  60. package/dist/chunk-RSJ3TWJQ.cjs +186 -0
  61. package/dist/chunk-S4WBV25P.js +913 -0
  62. package/dist/chunk-SN3YWBX7.cjs +4400 -0
  63. package/dist/chunk-SPVWWUHX.cjs +46 -0
  64. package/dist/chunk-SUEGJ75D.cjs +764 -0
  65. package/dist/chunk-SVNDB62D.cjs +58 -0
  66. package/dist/chunk-UYPEN5XE.cjs +235 -0
  67. package/dist/chunk-V5KPWNYX.cjs +147 -0
  68. package/dist/chunk-VVEHS2LI.js +431 -0
  69. package/dist/chunk-XBSYYZIY.cjs +94 -0
  70. package/dist/chunk-YGXJGRFI.cjs +913 -0
  71. package/dist/chunk-YMFAJFQT.cjs +173 -0
  72. package/dist/chunk-Z7LUNECE.js +49 -0
  73. package/dist/chunk-Z7Y2NPHY.js +186 -0
  74. package/dist/chunk-ZJZAOKI7.js +254 -0
  75. package/dist/chunk-ZLX3KGXX.js +173 -0
  76. package/dist/chunk-ZSVQT3PW.js +43 -0
  77. package/dist/completion/ApiKeyPoolService.cjs +23 -48
  78. package/dist/completion/ApiKeyPoolService.d.cts +150 -2
  79. package/dist/completion/ApiKeyPoolService.d.ts +150 -2
  80. package/dist/completion/BuiltinToolExecutor.cjs +9 -324
  81. package/dist/completion/BuiltinToolExecutor.js +6 -290
  82. package/dist/completion/CompletionService.cjs +38 -3487
  83. package/dist/completion/CompletionService.d.cts +3 -2
  84. package/dist/completion/CompletionService.d.ts +3 -2
  85. package/dist/completion/CompletionService.js +34 -3457
  86. package/dist/completion/NativeSearchInjector.cjs +8 -192
  87. package/dist/completion/NativeSearchInjector.js +7 -162
  88. package/dist/completion/ProviderSearchInjector.cjs +12 -39
  89. package/dist/completion/native-search-types.cjs +13 -66
  90. package/dist/completion/native-search-types.js +7 -31
  91. package/dist/completion/openrouter-headers.cjs +15 -71
  92. package/dist/completion/openrouter-headers.js +8 -34
  93. package/dist/completion/openrouter-models.cjs +10 -67
  94. package/dist/completion/openrouter-models.js +4 -34
  95. package/dist/completion/types.cjs +1 -18
  96. package/dist/completion/url-builder.cjs +24 -138
  97. package/dist/completion/url-builder.js +12 -92
  98. package/dist/completion.cjs +55 -3989
  99. package/dist/completion.d.cts +3 -2
  100. package/dist/completion.d.ts +3 -2
  101. package/dist/completion.js +63 -3953
  102. package/dist/index.cjs +197 -10429
  103. package/dist/index.d.cts +9 -2
  104. package/dist/index.d.ts +9 -2
  105. package/dist/index.js +125 -10268
  106. package/dist/logger-4GvQNzhE.d.cts +22 -0
  107. package/dist/logger-4GvQNzhE.d.ts +22 -0
  108. package/dist/outbound-api/routeResolver.cjs +7 -217
  109. package/dist/outbound-api/routeResolver.d.cts +2 -1
  110. package/dist/outbound-api/routeResolver.d.ts +2 -1
  111. package/dist/outbound-api/routeResolver.js +6 -187
  112. package/dist/outbound-api/subscriptionRegistryPort.cjs +7 -37
  113. package/dist/outbound-api/subscriptionRegistryPort.d.cts +2 -1
  114. package/dist/outbound-api/subscriptionRegistryPort.d.ts +2 -1
  115. package/dist/outbound-api/subscriptionRegistryPort.js +4 -8
  116. package/dist/outbound-api/types.cjs +1 -18
  117. package/dist/outbound-api/types.d.cts +2 -1
  118. package/dist/outbound-api/types.d.ts +2 -1
  119. package/dist/outbound-api.cjs +35 -5221
  120. package/dist/outbound-api.d.cts +2 -1
  121. package/dist/outbound-api.d.ts +2 -1
  122. package/dist/outbound-api.js +54 -5194
  123. package/dist/pipeline/AuthSource.cjs +1 -18
  124. package/dist/pipeline/LlmConfigProviderAuth.cjs +5 -166
  125. package/dist/pipeline/LlmConfigProviderAuth.d.cts +2 -1
  126. package/dist/pipeline/LlmConfigProviderAuth.d.ts +2 -1
  127. package/dist/pipeline/LlmConfigProviderAuth.js +5 -139
  128. package/dist/pipeline/SubscriptionAuthSource.cjs +6 -128
  129. package/dist/pipeline/SubscriptionAuthSource.js +5 -99
  130. package/dist/pipeline/SubscriptionAuthStrategy.cjs +1 -18
  131. package/dist/pipeline/executeProviderCall.cjs +5 -69
  132. package/dist/pipeline/executeProviderCall.js +3 -42
  133. package/dist/pipeline/resolveProviderChain.cjs +5 -46
  134. package/dist/pipeline/resolveProviderChain.js +3 -19
  135. package/dist/pipeline/resolveSubscriptionChain.cjs +5 -67
  136. package/dist/pipeline/resolveSubscriptionChain.js +3 -40
  137. package/dist/ports/gemini-code-assist-resolver.cjs +7 -37
  138. package/dist/ports/gemini-code-assist-resolver.js +4 -8
  139. package/dist/ports/pricing-store.cjs +1 -0
  140. package/dist/ports/pricing-store.d.cts +50 -0
  141. package/dist/ports/pricing-store.d.ts +50 -0
  142. package/dist/ports/pricing-store.js +0 -0
  143. package/dist/ports/provider-config-source.cjs +1 -18
  144. package/dist/ports/usage-event-store.cjs +1 -0
  145. package/dist/ports/usage-event-store.d.cts +29 -0
  146. package/dist/ports/usage-event-store.d.ts +29 -0
  147. package/dist/ports/usage-event-store.js +0 -0
  148. package/dist/ports/web-search-backend.cjs +1 -18
  149. package/dist/ports.cjs +1 -18
  150. package/dist/ports.d.cts +6 -1
  151. package/dist/ports.d.ts +6 -1
  152. package/dist/provider-proxy/ProviderProxy.cjs +40 -4643
  153. package/dist/provider-proxy/ProviderProxy.d.cts +2 -1
  154. package/dist/provider-proxy/ProviderProxy.d.ts +2 -1
  155. package/dist/provider-proxy/ProviderProxy.js +35 -4613
  156. package/dist/provider-proxy/ingress/providerProxyShared.cjs +35 -2941
  157. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +2 -1
  158. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +2 -1
  159. package/dist/provider-proxy/ingress/providerProxyShared.js +41 -2914
  160. package/dist/provider-proxy/matchText.cjs +11 -72
  161. package/dist/provider-proxy/matchText.js +6 -39
  162. package/dist/provider-proxy/types.cjs +1 -18
  163. package/dist/provider-proxy/types.d.cts +2 -1
  164. package/dist/provider-proxy/types.d.ts +2 -1
  165. package/dist/provider-proxy.cjs +35 -4655
  166. package/dist/provider-proxy.d.cts +2 -1
  167. package/dist/provider-proxy.d.ts +2 -1
  168. package/dist/provider-proxy.js +39 -4628
  169. package/dist/serializeError.cjs +5 -81
  170. package/dist/serializeError.js +3 -54
  171. package/dist/sse-parser.cjs +7 -455
  172. package/dist/sse-parser.js +4 -426
  173. package/dist/transformer/TransformerChainExecutor.cjs +4 -318
  174. package/dist/transformer/TransformerChainExecutor.js +4 -291
  175. package/dist/transformer/TransformerService.cjs +5 -289
  176. package/dist/transformer/TransformerService.js +3 -262
  177. package/dist/transformer/anthropicBetaInject.cjs +7 -50
  178. package/dist/transformer/anthropicBetaInject.js +4 -21
  179. package/dist/transformer/transformers/AnthropicTransformer.cjs +3 -1014
  180. package/dist/transformer/transformers/AnthropicTransformer.js +3 -987
  181. package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +4 -1106
  182. package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +7 -1079
  183. package/dist/transformer/transformers/GeminiTransformer.cjs +4 -1010
  184. package/dist/transformer/transformers/GeminiTransformer.js +4 -983
  185. package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +3 -535
  186. package/dist/transformer/transformers/OpenAIResponseTransformer.js +3 -510
  187. package/dist/transformer/transformers/OpenCodeGoTransformer.cjs +5 -72
  188. package/dist/transformer/transformers/OpenCodeGoTransformer.js +3 -45
  189. package/dist/transformer/transformers/ReasoningTransformer.cjs +3 -270
  190. package/dist/transformer/transformers/ReasoningTransformer.js +2 -249
  191. package/dist/transformer/transformers.cjs +10 -3177
  192. package/dist/transformer/transformers.js +23 -3158
  193. package/dist/transformer/types.cjs +1 -18
  194. package/dist/transformer.cjs +13 -3726
  195. package/dist/transformer.js +17 -3706
  196. package/dist/usage/pricing-engine.cjs +6 -0
  197. package/dist/usage/pricing-engine.d.cts +83 -0
  198. package/dist/usage/pricing-engine.d.ts +83 -0
  199. package/dist/usage/pricing-engine.js +6 -0
  200. package/dist/usage/usage-recorder.cjs +6 -0
  201. package/dist/usage/usage-recorder.d.cts +73 -0
  202. package/dist/usage/usage-recorder.d.ts +73 -0
  203. package/dist/usage/usage-recorder.js +6 -0
  204. package/dist/usage.cjs +11 -0
  205. package/dist/usage.d.cts +8 -0
  206. package/dist/usage.d.ts +8 -0
  207. package/dist/usage.js +11 -0
  208. package/package.json +1 -1
  209. package/dist/ApiKeyPoolService-BmMkau07.d.cts +0 -170
  210. package/dist/ApiKeyPoolService-BmMkau07.d.ts +0 -170
@@ -0,0 +1,6 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+ var _chunkYMFAJFQTcjs = require('../chunk-YMFAJFQT.cjs');
4
+
5
+
6
+ exports.PricingEngine = _chunkYMFAJFQTcjs.PricingEngine;
@@ -0,0 +1,83 @@
1
+ import { PricingEntry, PricingEntryInput, PricingFetchResult, PricingConflictDecision, PricingResolution } from '@omnicross/contracts/pricing-types';
2
+ import { UsageTokens } from '@omnicross/contracts/usage-types';
3
+ import { L as Logger } from '../logger-4GvQNzhE.cjs';
4
+ import { PricingStore } from '../ports/pricing-store.cjs';
5
+
6
+ /**
7
+ * PricingEngine — manages model pricing and computes per-event cost.
8
+ *
9
+ * Persistence goes through the injected `PricingStore` port. Sources of
10
+ * pricing rows:
11
+ * - 'builtin' — bundled fallback prices, seeded by the host
12
+ * - 'litellm' — refreshed on user demand from LiteLLM's public JSON
13
+ * - 'user' — hand-edited; protected from auto-overwrite
14
+ *
15
+ * @module usage/pricing-engine
16
+ */
17
+
18
+ /** Output of `calculateCost`. */
19
+ interface CostCalculation {
20
+ costUsd: number;
21
+ /**
22
+ * Difference between hypothetical-no-cache cost (charging cacheReadTokens at
23
+ * the full input price) and the actual cost (charging at the cache_read price).
24
+ * Always ≥ 0.
25
+ */
26
+ costSavedByCacheUsd: number;
27
+ }
28
+ /** Optional knobs (mostly for tests). */
29
+ interface PricingEngineOptions {
30
+ /** Override the pricing-source JSON URL — useful for testing. */
31
+ sourceUrl?: string;
32
+ /** Override `fetch` — useful for testing. */
33
+ fetchImpl?: typeof fetch;
34
+ }
35
+ declare class PricingEngine {
36
+ private store;
37
+ private logger;
38
+ private options;
39
+ private cache;
40
+ /**
41
+ * Secondary index keyed by modelId alone. Used as a fallback when no exact
42
+ * (providerId, modelId) match exists — usage may be recorded under a
43
+ * runtime provider alias while pricing rows use the canonical provider id,
44
+ * so matching by model name lets the price still resolve. First
45
+ * non-wildcard entry per model wins.
46
+ */
47
+ private cacheByModel;
48
+ private cacheLoaded;
49
+ constructor(store: PricingStore, logger: Logger, options?: PricingEngineOptions);
50
+ /** Lazy-load and cache the full pricing table. */
51
+ private ensureCache;
52
+ /** Force a cache refresh — call after any write. */
53
+ invalidateCache(): Promise<void>;
54
+ getAll(): Promise<PricingEntry[]>;
55
+ /**
56
+ * Look up a price for (provider, model). Resolution order:
57
+ * 1. exact (providerId, modelId)
58
+ * 2. wildcard provider ('*', modelId)
59
+ * 3. model name alone (any provider) — tolerates a runtime-alias vs
60
+ * canonical provider-id mismatch for the same model.
61
+ */
62
+ getEntry(providerId: string, modelId: string): Promise<PricingEntry | null>;
63
+ /**
64
+ * Compute the cost (and cache savings) for a single response.
65
+ *
66
+ * Cost formula (USD):
67
+ * cost = (input * inputPrice
68
+ * + output * outputPrice
69
+ * + cacheRead * (cacheReadPrice ?? inputPrice)
70
+ * + cacheWrite * (cacheWritePrice ?? inputPrice)
71
+ * ) / 1e6
72
+ *
73
+ * Cache savings:
74
+ * savings = cacheRead * (inputPrice - cacheReadPrice) / 1e6
75
+ * — clamped at 0 if cacheReadPrice is null or ≥ inputPrice.
76
+ */
77
+ calculateCost(providerId: string, modelId: string, usage: UsageTokens): Promise<CostCalculation>;
78
+ upsertManual(input: PricingEntryInput): Promise<PricingEntry>;
79
+ fetchLatestFromSource(): Promise<PricingFetchResult>;
80
+ resolveConflicts(decisions: PricingConflictDecision[], pendingIncoming: Map<string, PricingEntryInput>): Promise<PricingResolution>;
81
+ }
82
+
83
+ export { type CostCalculation, PricingEngine, type PricingEngineOptions };
@@ -0,0 +1,83 @@
1
+ import { PricingEntry, PricingEntryInput, PricingFetchResult, PricingConflictDecision, PricingResolution } from '@omnicross/contracts/pricing-types';
2
+ import { UsageTokens } from '@omnicross/contracts/usage-types';
3
+ import { L as Logger } from '../logger-4GvQNzhE.js';
4
+ import { PricingStore } from '../ports/pricing-store.js';
5
+
6
+ /**
7
+ * PricingEngine — manages model pricing and computes per-event cost.
8
+ *
9
+ * Persistence goes through the injected `PricingStore` port. Sources of
10
+ * pricing rows:
11
+ * - 'builtin' — bundled fallback prices, seeded by the host
12
+ * - 'litellm' — refreshed on user demand from LiteLLM's public JSON
13
+ * - 'user' — hand-edited; protected from auto-overwrite
14
+ *
15
+ * @module usage/pricing-engine
16
+ */
17
+
18
+ /** Output of `calculateCost`. */
19
+ interface CostCalculation {
20
+ costUsd: number;
21
+ /**
22
+ * Difference between hypothetical-no-cache cost (charging cacheReadTokens at
23
+ * the full input price) and the actual cost (charging at the cache_read price).
24
+ * Always ≥ 0.
25
+ */
26
+ costSavedByCacheUsd: number;
27
+ }
28
+ /** Optional knobs (mostly for tests). */
29
+ interface PricingEngineOptions {
30
+ /** Override the pricing-source JSON URL — useful for testing. */
31
+ sourceUrl?: string;
32
+ /** Override `fetch` — useful for testing. */
33
+ fetchImpl?: typeof fetch;
34
+ }
35
+ declare class PricingEngine {
36
+ private store;
37
+ private logger;
38
+ private options;
39
+ private cache;
40
+ /**
41
+ * Secondary index keyed by modelId alone. Used as a fallback when no exact
42
+ * (providerId, modelId) match exists — usage may be recorded under a
43
+ * runtime provider alias while pricing rows use the canonical provider id,
44
+ * so matching by model name lets the price still resolve. First
45
+ * non-wildcard entry per model wins.
46
+ */
47
+ private cacheByModel;
48
+ private cacheLoaded;
49
+ constructor(store: PricingStore, logger: Logger, options?: PricingEngineOptions);
50
+ /** Lazy-load and cache the full pricing table. */
51
+ private ensureCache;
52
+ /** Force a cache refresh — call after any write. */
53
+ invalidateCache(): Promise<void>;
54
+ getAll(): Promise<PricingEntry[]>;
55
+ /**
56
+ * Look up a price for (provider, model). Resolution order:
57
+ * 1. exact (providerId, modelId)
58
+ * 2. wildcard provider ('*', modelId)
59
+ * 3. model name alone (any provider) — tolerates a runtime-alias vs
60
+ * canonical provider-id mismatch for the same model.
61
+ */
62
+ getEntry(providerId: string, modelId: string): Promise<PricingEntry | null>;
63
+ /**
64
+ * Compute the cost (and cache savings) for a single response.
65
+ *
66
+ * Cost formula (USD):
67
+ * cost = (input * inputPrice
68
+ * + output * outputPrice
69
+ * + cacheRead * (cacheReadPrice ?? inputPrice)
70
+ * + cacheWrite * (cacheWritePrice ?? inputPrice)
71
+ * ) / 1e6
72
+ *
73
+ * Cache savings:
74
+ * savings = cacheRead * (inputPrice - cacheReadPrice) / 1e6
75
+ * — clamped at 0 if cacheReadPrice is null or ≥ inputPrice.
76
+ */
77
+ calculateCost(providerId: string, modelId: string, usage: UsageTokens): Promise<CostCalculation>;
78
+ upsertManual(input: PricingEntryInput): Promise<PricingEntry>;
79
+ fetchLatestFromSource(): Promise<PricingFetchResult>;
80
+ resolveConflicts(decisions: PricingConflictDecision[], pendingIncoming: Map<string, PricingEntryInput>): Promise<PricingResolution>;
81
+ }
82
+
83
+ export { type CostCalculation, PricingEngine, type PricingEngineOptions };
@@ -0,0 +1,6 @@
1
+ import {
2
+ PricingEngine
3
+ } from "../chunk-ZLX3KGXX.js";
4
+ export {
5
+ PricingEngine
6
+ };
@@ -0,0 +1,6 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+ var _chunkXBSYYZIYcjs = require('../chunk-XBSYYZIY.cjs');
4
+
5
+
6
+ exports.UsageRecorder = _chunkXBSYYZIYcjs.UsageRecorder;
@@ -0,0 +1,73 @@
1
+ import { PricingEngine } from './pricing-engine.cjs';
2
+ import { UsageDateRange, UsageTotals, ModelUsageRow, ApiKeyUsageRow, MessageUsageRow, SessionCacheStats } from '@omnicross/contracts/usage-stats-types';
3
+ import { UsageEngineOrigin, UsageTokens } from '@omnicross/contracts/usage-types';
4
+ import { L as Logger } from '../logger-4GvQNzhE.cjs';
5
+ import { UsageEventStore } from '../ports/usage-event-store.cjs';
6
+ import '@omnicross/contracts/pricing-types';
7
+ import '../ports/pricing-store.cjs';
8
+
9
+ /**
10
+ * UsageRecorder — funnels every captured LLM-request event through cost
11
+ * calculation and persists it via the injected `UsageEventStore`.
12
+ *
13
+ * Capture taps call `record()` synchronously with the parsed usage data. The
14
+ * store insert is enqueued via an injectable deferral function (default: a
15
+ * zero-delay timer; Node hosts may inject `setImmediate`) so the response path
16
+ * is never blocked on disk I/O.
17
+ *
18
+ * @module usage/usage-recorder
19
+ */
20
+
21
+ /** Subset of fields the caller MUST provide. Recorder fills cost (store fills ts). */
22
+ interface UsageRecordInput {
23
+ messageId?: string | null;
24
+ parentMessageId?: string | null;
25
+ sessionId?: string | null;
26
+ providerId: string;
27
+ model: string;
28
+ apiKeyId?: string | null;
29
+ engineOrigin: UsageEngineOrigin;
30
+ usage: UsageTokens;
31
+ /** Optional raw provider usage block — kept verbatim for forensics. */
32
+ rawUsage?: unknown;
33
+ /** Host run-correlation id. Optional / additive. */
34
+ runId?: string | null;
35
+ /** Host event-correlation id for this call. Optional / additive. */
36
+ eventId?: string | null;
37
+ }
38
+ /** Optional knobs (mostly for hosts/tests). */
39
+ interface UsageRecorderOptions {
40
+ /**
41
+ * Deferral function used by `record()` to schedule the async persist off
42
+ * the caller's path. Defaults to a zero-delay timer; Node hosts may inject
43
+ * `setImmediate` to preserve their exact scheduling.
44
+ */
45
+ defer?: (fn: () => void) => void;
46
+ }
47
+ declare class UsageRecorder {
48
+ private store;
49
+ private pricing;
50
+ private logger;
51
+ private defer;
52
+ constructor(store: UsageEventStore, pricing: PricingEngine, logger: Logger, options?: UsageRecorderOptions);
53
+ /**
54
+ * Record one LLM request. Returns immediately — the actual store insert is
55
+ * deferred so the caller's response path is unblocked.
56
+ *
57
+ * Errors during the insert are logged but never thrown.
58
+ */
59
+ record(input: UsageRecordInput): void;
60
+ /**
61
+ * Same as `record()` but awaitable — preferred in tests so they can assert
62
+ * after the row exists.
63
+ */
64
+ recordAsync(input: UsageRecordInput): Promise<string | null>;
65
+ getTotals(range: UsageDateRange): Promise<UsageTotals>;
66
+ getByModel(range: UsageDateRange): Promise<ModelUsageRow[]>;
67
+ getByApiKey(range: UsageDateRange): Promise<ApiKeyUsageRow[]>;
68
+ getMessagesForSession(sessionId: string): Promise<MessageUsageRow[]>;
69
+ /** Cumulative cache hit/miss stats for one session. */
70
+ getSessionCacheStats(sessionId: string): Promise<SessionCacheStats>;
71
+ }
72
+
73
+ export { type UsageRecordInput, UsageRecorder, type UsageRecorderOptions };
@@ -0,0 +1,73 @@
1
+ import { PricingEngine } from './pricing-engine.js';
2
+ import { UsageDateRange, UsageTotals, ModelUsageRow, ApiKeyUsageRow, MessageUsageRow, SessionCacheStats } from '@omnicross/contracts/usage-stats-types';
3
+ import { UsageEngineOrigin, UsageTokens } from '@omnicross/contracts/usage-types';
4
+ import { L as Logger } from '../logger-4GvQNzhE.js';
5
+ import { UsageEventStore } from '../ports/usage-event-store.js';
6
+ import '@omnicross/contracts/pricing-types';
7
+ import '../ports/pricing-store.js';
8
+
9
+ /**
10
+ * UsageRecorder — funnels every captured LLM-request event through cost
11
+ * calculation and persists it via the injected `UsageEventStore`.
12
+ *
13
+ * Capture taps call `record()` synchronously with the parsed usage data. The
14
+ * store insert is enqueued via an injectable deferral function (default: a
15
+ * zero-delay timer; Node hosts may inject `setImmediate`) so the response path
16
+ * is never blocked on disk I/O.
17
+ *
18
+ * @module usage/usage-recorder
19
+ */
20
+
21
+ /** Subset of fields the caller MUST provide. Recorder fills cost (store fills ts). */
22
+ interface UsageRecordInput {
23
+ messageId?: string | null;
24
+ parentMessageId?: string | null;
25
+ sessionId?: string | null;
26
+ providerId: string;
27
+ model: string;
28
+ apiKeyId?: string | null;
29
+ engineOrigin: UsageEngineOrigin;
30
+ usage: UsageTokens;
31
+ /** Optional raw provider usage block — kept verbatim for forensics. */
32
+ rawUsage?: unknown;
33
+ /** Host run-correlation id. Optional / additive. */
34
+ runId?: string | null;
35
+ /** Host event-correlation id for this call. Optional / additive. */
36
+ eventId?: string | null;
37
+ }
38
+ /** Optional knobs (mostly for hosts/tests). */
39
+ interface UsageRecorderOptions {
40
+ /**
41
+ * Deferral function used by `record()` to schedule the async persist off
42
+ * the caller's path. Defaults to a zero-delay timer; Node hosts may inject
43
+ * `setImmediate` to preserve their exact scheduling.
44
+ */
45
+ defer?: (fn: () => void) => void;
46
+ }
47
+ declare class UsageRecorder {
48
+ private store;
49
+ private pricing;
50
+ private logger;
51
+ private defer;
52
+ constructor(store: UsageEventStore, pricing: PricingEngine, logger: Logger, options?: UsageRecorderOptions);
53
+ /**
54
+ * Record one LLM request. Returns immediately — the actual store insert is
55
+ * deferred so the caller's response path is unblocked.
56
+ *
57
+ * Errors during the insert are logged but never thrown.
58
+ */
59
+ record(input: UsageRecordInput): void;
60
+ /**
61
+ * Same as `record()` but awaitable — preferred in tests so they can assert
62
+ * after the row exists.
63
+ */
64
+ recordAsync(input: UsageRecordInput): Promise<string | null>;
65
+ getTotals(range: UsageDateRange): Promise<UsageTotals>;
66
+ getByModel(range: UsageDateRange): Promise<ModelUsageRow[]>;
67
+ getByApiKey(range: UsageDateRange): Promise<ApiKeyUsageRow[]>;
68
+ getMessagesForSession(sessionId: string): Promise<MessageUsageRow[]>;
69
+ /** Cumulative cache hit/miss stats for one session. */
70
+ getSessionCacheStats(sessionId: string): Promise<SessionCacheStats>;
71
+ }
72
+
73
+ export { type UsageRecordInput, UsageRecorder, type UsageRecorderOptions };
@@ -0,0 +1,6 @@
1
+ import {
2
+ UsageRecorder
3
+ } from "../chunk-MNYKI4CI.js";
4
+ export {
5
+ UsageRecorder
6
+ };
package/dist/usage.cjs ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});require('./chunk-EYZYXJTJ.cjs');
2
+
3
+
4
+ var _chunkYMFAJFQTcjs = require('./chunk-YMFAJFQT.cjs');
5
+
6
+
7
+ var _chunkXBSYYZIYcjs = require('./chunk-XBSYYZIY.cjs');
8
+
9
+
10
+
11
+ exports.PricingEngine = _chunkYMFAJFQTcjs.PricingEngine; exports.UsageRecorder = _chunkXBSYYZIYcjs.UsageRecorder;
@@ -0,0 +1,8 @@
1
+ export { CostCalculation, PricingEngine, PricingEngineOptions } from './usage/pricing-engine.cjs';
2
+ export { UsageRecordInput, UsageRecorder, UsageRecorderOptions } from './usage/usage-recorder.cjs';
3
+ import '@omnicross/contracts/pricing-types';
4
+ import '@omnicross/contracts/usage-types';
5
+ import './logger-4GvQNzhE.cjs';
6
+ import './ports/pricing-store.cjs';
7
+ import '@omnicross/contracts/usage-stats-types';
8
+ import './ports/usage-event-store.cjs';
@@ -0,0 +1,8 @@
1
+ export { CostCalculation, PricingEngine, PricingEngineOptions } from './usage/pricing-engine.js';
2
+ export { UsageRecordInput, UsageRecorder, UsageRecorderOptions } from './usage/usage-recorder.js';
3
+ import '@omnicross/contracts/pricing-types';
4
+ import '@omnicross/contracts/usage-types';
5
+ import './logger-4GvQNzhE.js';
6
+ import './ports/pricing-store.js';
7
+ import '@omnicross/contracts/usage-stats-types';
8
+ import './ports/usage-event-store.js';
package/dist/usage.js ADDED
@@ -0,0 +1,11 @@
1
+ import "./chunk-7VU7V2E4.js";
2
+ import {
3
+ PricingEngine
4
+ } from "./chunk-ZLX3KGXX.js";
5
+ import {
6
+ UsageRecorder
7
+ } from "./chunk-MNYKI4CI.js";
8
+ export {
9
+ PricingEngine,
10
+ UsageRecorder
11
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnicross/core",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
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,170 +0,0 @@
1
- import { ApiKeyEntry } from '@omnicross/contracts/llm-config';
2
-
3
- /**
4
- * `Logger` — core-owned port for the structured logger the serving core uses.
5
- *
6
- * The serving core MUST depend on THIS interface, never on the concrete host
7
- * `LoggerService` class as a type. The host (`LoggerService`) already exposes a
8
- * superset of this surface, so it is passed directly with NO adapter.
9
- *
10
- * `error` uses the WIDEST signature `(message, error?, meta?)` so every core
11
- * call site — `error(msg)`, `error(msg, errInstance)`, `error(msg, err, meta)` —
12
- * stays assignable (design Q2). `info`/`warn`/`debug` take an optional `meta`
13
- * bag matching the host's `Record<string, unknown> | Error | object`.
14
- *
15
- * @module ports/logger
16
- */
17
- interface Logger {
18
- info(message: string, meta?: Record<string, unknown> | Error | object): void;
19
- warn(message: string, meta?: Record<string, unknown> | Error | object): void;
20
- error(message: string, error?: unknown, meta?: Record<string, unknown> | object): void;
21
- debug(message: string, meta?: Record<string, unknown> | Error | object): void;
22
- }
23
-
24
- /**
25
- * ApiKeyPoolService - Multi-API-key load balancing with session affinity
26
- *
27
- * Manages a pool of API keys per provider, selecting keys via weighted
28
- * round-robin and maintaining session-level key affinity to preserve
29
- * prompt cache across requests within the same session.
30
- */
31
-
32
- /** Live health snapshot for a single key currently in cooldown. */
33
- interface KeyHealthEntry {
34
- /** Epoch-ms when the cooldown expires */
35
- until: number;
36
- /** Number of consecutive errors */
37
- errors: number;
38
- /** HTTP status that triggered the most recent cooldown */
39
- lastStatus: number | null;
40
- }
41
- /** Provider-scoped map of keyId → live cooldown health (cooling keys only). */
42
- type KeyHealthMap = Record<string, KeyHealthEntry>;
43
- /** Function type for loading API keys from the database */
44
- type ApiKeysLoader = (providerId: string) => Promise<ApiKeyEntry[]>;
45
- /** Function type for disabling a key in the database (on auth failure) */
46
- type ApiKeyDisabler = (keyId: string) => Promise<boolean>;
47
- /**
48
- * Function type for auto-disabling a key in the database on auth failure,
49
- * persisting the offending status + timestamp so the client UI can surface
50
- * a per-key health indicator. Preferred over {@link ApiKeyDisabler} when set.
51
- */
52
- type ApiKeyAutoDisabler = (keyId: string, status: number, at: number) => Promise<void>;
53
- /** Function type for resolving environment variable references in API keys */
54
- type ApiKeyResolver = (rawKey: string) => string;
55
- declare class ApiKeyPoolService {
56
- private loadKeys;
57
- private resolveKey;
58
- private logger;
59
- private disableKey?;
60
- private markAutoDisabled?;
61
- /** Session 鈫?key binding (session affinity) */
62
- private sessionBindings;
63
- /** Provider 鈫?round-robin index */
64
- private rrIndex;
65
- /** Provider 鈫?cached key list */
66
- private keyCache;
67
- /** Key ID 鈫?cooldown state */
68
- private cooldowns;
69
- /** Cleanup interval handle */
70
- private cleanupTimer;
71
- private readonly DEFAULT_COOLDOWN_MS;
72
- private readonly MAX_COOLDOWN_MS;
73
- private readonly COOLDOWN_MULTIPLIER;
74
- constructor(loadKeys: ApiKeysLoader, resolveKey: ApiKeyResolver, logger: Logger, disableKey?: ApiKeyDisabler | undefined, markAutoDisabled?: ApiKeyAutoDisabler | undefined);
75
- /**
76
- * Get the API key for a session. Implements session affinity.
77
- *
78
- * First call for a session binds it to a key via weighted round-robin.
79
- * Subsequent calls return the same key (preserves prompt cache).
80
- *
81
- * @returns Resolved API key string, or empty string if no keys available
82
- */
83
- /**
84
- * Read which key id is currently bound to the given session, if any.
85
- * Returns null when the session has not yet been bound (first call hasn't
86
- * happened) or when the binding is for a different provider.
87
- *
88
- * Used by the usage-recorder attribution path: after `getKeyForSession`
89
- * completes the caller looks up the keyId so the recorded usage
90
- * row can attribute spend to a specific pool key.
91
- */
92
- getKeyIdForSession(providerId: string, sessionId: string): string | null;
93
- getKeyForSession(providerId: string, sessionId: string): Promise<string>;
94
- /**
95
- * Get a key without session affinity (for one-shot calls like testConnection).
96
- *
97
- * @returns Resolved API key string, or empty string if no keys available
98
- */
99
- getKey(providerId: string): Promise<string>;
100
- /**
101
- * Report an error for the current session's key.
102
- *
103
- * - 429/529 (rate limit / overload): puts key in cooldown with exponential backoff
104
- * - 401/403 (auth failure): permanently disables the key in the database
105
- *
106
- * In both cases, re-binds the session to a different key if available.
107
- *
108
- * @param statusCode HTTP status code
109
- * @returns New resolved API key if re-binding succeeded, null if no keys available
110
- */
111
- reportError(providerId: string, sessionId: string, statusCode: number): Promise<string | null>;
112
- /**
113
- * Report a successful request — resets cooldown counter for the session's key.
114
- */
115
- reportSuccess(sessionId: string): void;
116
- /**
117
- * Release session binding (call when session ends or is deleted).
118
- */
119
- releaseSession(sessionId: string): void;
120
- /**
121
- * Invalidate the key cache. Call after CRUD operations on API keys.
122
- */
123
- invalidateCache(providerId?: string): void;
124
- /**
125
- * Check if a provider has any keys in the pool.
126
- */
127
- hasKeys(providerId: string): Promise<boolean>;
128
- /**
129
- * Get the live (in-memory) rate-limit cooldown health for a provider's keys.
130
- *
131
- * Returns ONLY keys that are currently cooling down (cooldown `until` is in
132
- * the future). A key absent from the returned map is not cooling. This is a
133
- * pure read of the in-memory cooldown map — auth-failure auto-disable state
134
- * is persisted on the key row itself (getApiKeys) and is NOT included here.
135
- */
136
- getKeyHealth(providerId: string): Promise<KeyHealthMap>;
137
- /**
138
- * Dispose of the service (stop cleanup timer).
139
- */
140
- dispose(): void;
141
- /**
142
- * Handle auth failure (401/403): disable the key in DB permanently.
143
- */
144
- private handleAuthFailure;
145
- /**
146
- * Apply cooldown with exponential backoff for rate-limit errors (429/529).
147
- */
148
- private applyCooldown;
149
- /**
150
- * Get all keys for a provider (with caching).
151
- */
152
- private getAllKeys;
153
- /**
154
- * Get available keys: enabled AND not in cooldown.
155
- */
156
- private getAvailableKeys;
157
- /**
158
- * Weighted round-robin selection.
159
- *
160
- * Each key's weight determines how many "slots" it occupies in the rotation.
161
- * The round-robin index advances by 1 on each call per provider.
162
- */
163
- private selectWeightedRoundRobin;
164
- /**
165
- * Clean up expired cooldowns.
166
- */
167
- private cleanupExpiredCooldowns;
168
- }
169
-
170
- export { ApiKeyPoolService as A, type KeyHealthEntry as K, type Logger as L, type ApiKeyAutoDisabler as a, type ApiKeyDisabler as b, type ApiKeyResolver as c, type ApiKeysLoader as d, type KeyHealthMap as e };