@omnicross/core 0.1.9 → 0.2.0

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 (176) hide show
  1. package/LICENSE +21 -21
  2. package/NOTICE +57 -57
  3. package/README.md +22 -15
  4. package/dist/{CompletionService-kNA17cfI.d.cts → CompletionService-BiJqftc-.d.cts} +1 -1
  5. package/dist/{CompletionService-C3BX0Ovy.d.ts → CompletionService-NXN_Av5W.d.ts} +1 -1
  6. package/dist/{ProviderProxy-QdwNV6l1.d.cts → ProviderProxy-CgIcCVwk.d.cts} +1 -1
  7. package/dist/{ProviderProxy--ROec6VI.d.ts → ProviderProxy-DYoY5XoT.d.ts} +1 -1
  8. package/dist/auth/GeminiCodeAssistProjectResolver.cjs +6 -6
  9. package/dist/auth/GeminiCodeAssistProjectResolver.js +4 -4
  10. package/dist/chunk-32SRZFFP.cjs +153 -0
  11. package/dist/chunk-4JOU54M5.js +200 -0
  12. package/dist/{chunk-2UTGX6FM.js → chunk-4VVCXVB7.js} +1 -1
  13. package/dist/{chunk-EPN67EGP.cjs → chunk-5UK3KLE2.cjs} +9 -1
  14. package/dist/chunk-6DDYNS2B.cjs +384 -0
  15. package/dist/{chunk-HKB656B4.js → chunk-6OC3ORW6.js} +55 -287
  16. package/dist/chunk-6OKXH2TW.js +320 -0
  17. package/dist/{chunk-XELFM7KL.cjs → chunk-7B56AJBB.cjs} +6275 -2421
  18. package/dist/{chunk-YWL7YZWS.cjs → chunk-7LRTPNFL.cjs} +5 -0
  19. package/dist/{chunk-CCVRRJOX.js → chunk-7PIUVCKK.js} +9 -2
  20. package/dist/{chunk-IIRPUVPH.cjs → chunk-7ZHBN75N.cjs} +3 -1
  21. package/dist/{chunk-UAPBLNN2.js → chunk-AQDON6MB.js} +8 -0
  22. package/dist/{chunk-RJ5ZGNI3.js → chunk-CFSGYFOZ.js} +1 -1
  23. package/dist/chunk-CTKM773J.cjs +3919 -0
  24. package/dist/chunk-DEIUR2TH.js +3919 -0
  25. package/dist/{chunk-WNKWAEUR.js → chunk-EYGBM2VC.js} +3 -1
  26. package/dist/{chunk-NGYOO5TO.js → chunk-FJNKXOWE.js} +9 -9
  27. package/dist/chunk-FX325I5Q.cjs +320 -0
  28. package/dist/chunk-G4CZIUIB.cjs +200 -0
  29. package/dist/chunk-HCOQQAZE.cjs +123 -0
  30. package/dist/{chunk-55FMGZ3L.js → chunk-HN74IGEO.js} +1 -1
  31. package/dist/{chunk-ZY6KU6P3.js → chunk-HOMUGKHR.js} +8 -5
  32. package/dist/{chunk-AOFWNWLT.cjs → chunk-IUL4VWNU.cjs} +22 -1
  33. package/dist/{chunk-5LNYGCIW.cjs → chunk-KIQ2HA2A.cjs} +5 -5
  34. package/dist/{chunk-MUHWHQVM.cjs → chunk-KQBLZMP6.cjs} +4 -3
  35. package/dist/chunk-LFEH7CEO.js +384 -0
  36. package/dist/chunk-N76KU6F5.js +123 -0
  37. package/dist/{chunk-CMVXX7ON.cjs → chunk-NOITAVHA.cjs} +114 -58
  38. package/dist/{chunk-Q27JY5RG.cjs → chunk-OIKREZVQ.cjs} +7 -4
  39. package/dist/{chunk-RJUONLUQ.cjs → chunk-OST5RJOJ.cjs} +1 -1
  40. package/dist/chunk-QIIAMBTM.js +153 -0
  41. package/dist/{chunk-56QD3YW6.cjs → chunk-QWNUOR7F.cjs} +11 -4
  42. package/dist/{chunk-S3DYFEBE.js → chunk-R4VCO2CB.js} +10 -1
  43. package/dist/{chunk-ZQQUD66M.cjs → chunk-SQMAEDNE.cjs} +63 -295
  44. package/dist/{chunk-4VZX5F4T.cjs → chunk-T6NWPIYZ.cjs} +5 -2
  45. package/dist/{chunk-P7EM6BND.cjs → chunk-TVYA5JSQ.cjs} +10 -10
  46. package/dist/{chunk-EBLFCNPY.js → chunk-U47LQXPB.js} +5 -2
  47. package/dist/{chunk-N7OOJI5V.js → chunk-V2UKUTJ3.js} +5 -0
  48. package/dist/{chunk-45FHEOKW.js → chunk-V53ZEFXC.js} +92 -36
  49. package/dist/{chunk-OC6DOOFX.cjs → chunk-VXRTQZF2.cjs} +5 -5
  50. package/dist/{chunk-CQIJCPMF.js → chunk-WSJE42SG.js} +5149 -1295
  51. package/dist/{chunk-RICPANBY.cjs → chunk-WX2E2G7H.cjs} +13 -4
  52. package/dist/{chunk-DE2SRBFZ.js → chunk-X335TJNS.js} +4 -3
  53. package/dist/{chunk-N2EIM2XJ.js → chunk-ZLNHPUFA.js} +22 -1
  54. package/dist/completion/CompletionService.cjs +30 -27
  55. package/dist/completion/CompletionService.d.cts +3 -2
  56. package/dist/completion/CompletionService.d.ts +3 -2
  57. package/dist/completion/CompletionService.js +29 -26
  58. package/dist/completion.cjs +38 -35
  59. package/dist/completion.d.cts +3 -2
  60. package/dist/completion.d.ts +3 -2
  61. package/dist/completion.js +37 -34
  62. package/dist/image-generation.cjs +52 -0
  63. package/dist/image-generation.d.cts +93 -0
  64. package/dist/image-generation.d.ts +93 -0
  65. package/dist/image-generation.js +52 -0
  66. package/dist/index.cjs +126 -31
  67. package/dist/index.d.cts +11 -7
  68. package/dist/index.d.ts +11 -7
  69. package/dist/index.js +143 -48
  70. package/dist/openai-operation.cjs +18 -0
  71. package/dist/openai-operation.d.cts +19 -0
  72. package/dist/openai-operation.d.ts +19 -0
  73. package/dist/openai-operation.js +18 -0
  74. package/dist/outbound-api/auditCapture.cjs +3 -3
  75. package/dist/outbound-api/auditCapture.d.cts +19 -2
  76. package/dist/outbound-api/auditCapture.d.ts +19 -2
  77. package/dist/outbound-api/auditCapture.js +2 -2
  78. package/dist/outbound-api/auditRedact.cjs +2 -2
  79. package/dist/outbound-api/auditRedact.js +1 -1
  80. package/dist/outbound-api/routeResolver.cjs +2 -2
  81. package/dist/outbound-api/routeResolver.d.cts +7 -4
  82. package/dist/outbound-api/routeResolver.d.ts +7 -4
  83. package/dist/outbound-api/routeResolver.js +1 -1
  84. package/dist/outbound-api/subscriptionRegistryPort.d.cts +2 -1
  85. package/dist/outbound-api/subscriptionRegistryPort.d.ts +2 -1
  86. package/dist/outbound-api/types.d.cts +6 -3
  87. package/dist/outbound-api/types.d.ts +6 -3
  88. package/dist/outbound-api.cjs +49 -32
  89. package/dist/outbound-api.d.cts +97 -10
  90. package/dist/outbound-api.d.ts +97 -10
  91. package/dist/outbound-api.js +48 -31
  92. package/dist/pipeline/AccountAllowanceScheduling.d.cts +18 -15
  93. package/dist/pipeline/AccountAllowanceScheduling.d.ts +18 -15
  94. package/dist/pipeline/LlmConfigProviderAuth.cjs +3 -3
  95. package/dist/pipeline/LlmConfigProviderAuth.js +2 -2
  96. package/dist/pipeline/SubscriptionAccountHealth.cjs +2 -2
  97. package/dist/pipeline/SubscriptionAccountHealth.d.cts +7 -0
  98. package/dist/pipeline/SubscriptionAccountHealth.d.ts +7 -0
  99. package/dist/pipeline/SubscriptionAccountHealth.js +1 -1
  100. package/dist/pipeline/executeProviderCall.cjs +2 -2
  101. package/dist/pipeline/executeProviderCall.d.cts +11 -6
  102. package/dist/pipeline/executeProviderCall.d.ts +11 -6
  103. package/dist/pipeline/executeProviderCall.js +1 -1
  104. package/dist/pipeline/upstreamFetch.cjs +2 -2
  105. package/dist/pipeline/upstreamFetch.d.cts +5 -0
  106. package/dist/pipeline/upstreamFetch.d.ts +5 -0
  107. package/dist/pipeline/upstreamFetch.js +1 -1
  108. package/dist/ports.d.cts +6 -3
  109. package/dist/ports.d.ts +6 -3
  110. package/dist/provider-proxy/ProviderProxy.cjs +30 -27
  111. package/dist/provider-proxy/ProviderProxy.d.cts +3 -2
  112. package/dist/provider-proxy/ProviderProxy.d.ts +3 -2
  113. package/dist/provider-proxy/ProviderProxy.js +29 -26
  114. package/dist/provider-proxy/identity/codexCliHeaders.cjs +4 -2
  115. package/dist/provider-proxy/identity/codexCliHeaders.d.cts +26 -6
  116. package/dist/provider-proxy/identity/codexCliHeaders.d.ts +26 -6
  117. package/dist/provider-proxy/identity/codexCliHeaders.js +5 -3
  118. package/dist/provider-proxy/ingress/providerProxyShared.cjs +32 -27
  119. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +21 -8
  120. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +21 -8
  121. package/dist/provider-proxy/ingress/providerProxyShared.js +31 -26
  122. package/dist/provider-proxy/types.d.cts +14 -483
  123. package/dist/provider-proxy/types.d.ts +14 -483
  124. package/dist/provider-proxy.cjs +44 -27
  125. package/dist/provider-proxy.d.cts +30 -8
  126. package/dist/provider-proxy.d.ts +30 -8
  127. package/dist/provider-proxy.js +43 -26
  128. package/dist/{routeResolver-C0mkkZaM.d.ts → routeResolver-CTCcSHWu.d.ts} +4 -2
  129. package/dist/{routeResolver-CVFE8KKe.d.cts → routeResolver-rpKQLyDO.d.cts} +4 -2
  130. package/dist/transformer/TransformerChainExecutor.cjs +2 -2
  131. package/dist/transformer/TransformerChainExecutor.d.cts +2 -2
  132. package/dist/transformer/TransformerChainExecutor.d.ts +2 -2
  133. package/dist/transformer/TransformerChainExecutor.js +1 -1
  134. package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.cjs +16 -0
  135. package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.d.cts +53 -0
  136. package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.d.ts +53 -0
  137. package/dist/transformer/transformers/AnthropicOpenAIToAnthropicStream.js +16 -0
  138. package/dist/transformer/transformers/AnthropicTransformer.cjs +4 -3
  139. package/dist/transformer/transformers/AnthropicTransformer.js +3 -2
  140. package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +4 -4
  141. package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +3 -3
  142. package/dist/transformer/transformers/GeminiTransformer.cjs +4 -4
  143. package/dist/transformer/transformers/GeminiTransformer.js +3 -3
  144. package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +3 -3
  145. package/dist/transformer/transformers/OpenAIResponseTransformer.js +2 -2
  146. package/dist/transformer/transformers/OpenAITransformer.cjs +3 -3
  147. package/dist/transformer/transformers/OpenAITransformer.js +2 -2
  148. package/dist/transformer/transformers.cjs +10 -9
  149. package/dist/transformer/transformers.js +13 -12
  150. package/dist/transformer/types.d.cts +39 -4
  151. package/dist/transformer/types.d.ts +39 -4
  152. package/dist/transformer.cjs +14 -13
  153. package/dist/transformer.js +14 -13
  154. package/dist/{types-BB8pxk_3.d.ts → types-5T223WYQ.d.ts} +183 -23
  155. package/dist/types-Bd72H4SB.d.ts +196 -0
  156. package/dist/types-CVRge76p.d.ts +1115 -0
  157. package/dist/types-CbglB73l.d.cts +196 -0
  158. package/dist/types-DsHBBk3h.d.cts +1115 -0
  159. package/dist/{types-C2MwkLah.d.cts → types-jjU24eYG.d.cts} +183 -23
  160. package/dist/usage/usage-recorder.cjs +2 -2
  161. package/dist/usage/usage-recorder.d.cts +12 -2
  162. package/dist/usage/usage-recorder.d.ts +12 -2
  163. package/dist/usage/usage-recorder.js +1 -1
  164. package/dist/usage.cjs +20 -3
  165. package/dist/usage.d.cts +154 -0
  166. package/dist/usage.d.ts +154 -0
  167. package/dist/usage.js +20 -3
  168. package/package.json +69 -64
  169. package/dist/chunk-7C7DET6S.js +0 -154
  170. package/dist/chunk-7VU7V2E4.js +0 -0
  171. package/dist/chunk-EYZYXJTJ.cjs +0 -1
  172. package/dist/chunk-FCR77GYM.cjs +0 -33
  173. package/dist/chunk-K5NM7VAH.js +0 -33
  174. package/dist/chunk-XPIOJQS2.cjs +0 -154
  175. /package/dist/{chunk-XXFYLL7R.js → chunk-ECZ3ZE2C.js} +0 -0
  176. /package/dist/{chunk-3SCOLIPT.cjs → chunk-MXI2PWIC.cjs} +0 -0
@@ -1,3 +1,4 @@
1
+ import { e as ImageApiLimits } from './types-CbglB73l.cjs';
1
2
  import { ProxyConfig } from '@omnicross/contracts/account-tokens-types';
2
3
  import { AuditConfig } from '@omnicross/contracts/audit-types';
3
4
  import { BillingConfig } from '@omnicross/contracts/billing-types';
@@ -6,11 +7,49 @@ import { VoucherRecord, VoucherGrant, VoucherInfo, VoucherConfig } from '@omnicr
6
7
  import { WebhookConfig } from '@omnicross/contracts/webhook-types';
7
8
  import { L as Logger } from './logger-4GvQNzhE.cjs';
8
9
  import { ProviderConfigSource } from './ports/provider-config-source.cjs';
9
- import { P as ProviderProxy } from './ProviderProxy-QdwNV6l1.cjs';
10
- import { ProviderProxyDeps } from './provider-proxy/types.cjs';
10
+ import { P as ProviderProxy } from './ProviderProxy-CgIcCVwk.cjs';
11
+ import { W as ProviderProxyDeps } from './types-DsHBBk3h.cjs';
11
12
  import { BoundAccountFallbackPolicy } from './pipeline/BoundAccountSelectionError.cjs';
12
13
  import { c as KeySpend } from './keyPolicy-zdWTu3CQ.cjs';
13
14
 
15
+ /**
16
+ * anthropicCountTokens — the `POST /v1/messages/count_tokens` handler
17
+ * (`claude-api-routing-errors`, R2 passthrough+reject subset).
18
+ *
19
+ * Before this module, the substring `/v1/messages` match routed count_tokens
20
+ * into the FULL generation pipeline — every context-stats call burned a real
21
+ * upstream inference (BYO money, subscription 5h-window quota) and returned a
22
+ * Message JSON instead of `{"input_tokens":N}` (audit F-1, P0).
23
+ *
24
+ * Strategies (portfolio-locked default: `'auto'`):
25
+ * - **passthrough** (Anthropic-wire upstream — `plan.sameFormat`): strip the
26
+ * generation-only fields the count_tokens endpoint rejects (`stream`,
27
+ * `max_tokens`), rewrite `model` to the resolved upstream model, and POST to
28
+ * `<upstream>/v1/messages/count_tokens` via the SAME same-format fetches the
29
+ * generation path uses (credential injection, beta merge, claude header
30
+ * baseline all inherited). The response — success OR failure — relays
31
+ * verbatim with its real status (an Anthropic-wire error body already IS
32
+ * the official shape; wrapping it would violate the verbatim moat).
33
+ * - **estimate** (Change B; explicit config, or `auto` on a translation
34
+ * upstream): a PURE-LOCAL heuristic estimate (`anthropicCountEstimate.ts`)
35
+ * answered as `{"input_tokens":N}` with the `x-omnicross-count-estimate:
36
+ * true` marker header — zero upstream calls, never recorded as usage.
37
+ * - **reject** (explicit config, or `passthrough` degraded on a translation
38
+ * upstream): a clean Anthropic 404 `not_found_error` with ZERO upstream
39
+ * calls — Claude Code treats it as "endpoint absent" and falls back to its
40
+ * local usage estimation.
41
+ *
42
+ * A free endpoint: no usage recording, no concurrency gate (the outbound face
43
+ * bypasses its gate before dispatch), single attempt — no 401 refresh retry,
44
+ * no subscription health marking (a failed count_tokens must not cool an
45
+ * account that serves inference; the inference path drives those itself).
46
+ *
47
+ * @module provider-proxy/ingress/anthropicCountTokens
48
+ */
49
+
50
+ /** The operator-facing strategy config (§10 `anthropic.countTokens.mode`). */
51
+ type CountTokensMode = 'auto' | 'passthrough' | 'estimate' | 'reject';
52
+
14
53
  /**
15
54
  * keySpendTracker — a cheap in-memory per-key accumulated-spend cache
16
55
  * (`outbound-key-policy`, design D3).
@@ -201,23 +240,56 @@ interface VoucherDb {
201
240
  voucherList(): Promise<VoucherRecord[]>;
202
241
  }
203
242
 
204
- /**
205
- * Shared contract types for the outbound API server (`outbound-api-server`).
206
- *
207
- * The outbound server is a SEPARATE long-lived HTTP listener (distinct from the
208
- * resident loopback `ProviderProxy`) that authenticates external callers via
209
- * named API keys and routes their requests through the EXISTING `provider-proxy`
210
- * ingress parsers + transformer — there is exactly one conversion stack.
211
- *
212
- * These types are kept in their own module so the server, router, auth, rate
213
- * limiter, role detection, and route resolver can share shapes without circular
214
- * imports.
215
- *
216
- * @module outbound-api/types
217
- */
218
-
219
243
  /** The four endpoints, 1:1 with the four wire-format ingress parsers. */
220
244
  type OutboundEndpoint = 'chat' | 'responses' | 'messages' | 'gemini';
245
+ /** Named-key authorization vocabulary. Images is deliberately not a text route. */
246
+ type OutboundPermission = OutboundEndpoint | 'images';
247
+ interface ImagesServerConfig {
248
+ enabled: boolean;
249
+ provider: 'codex-subscription';
250
+ defaultModel: string;
251
+ modelAliases: Record<string, string>;
252
+ account: {
253
+ id?: string;
254
+ group?: string;
255
+ fallback: 'strict' | 'pool';
256
+ };
257
+ queue: {
258
+ maxConcurrentJobsPerAccount: number;
259
+ maxQueuedJobs: number;
260
+ queueTimeoutMs: number;
261
+ generationTimeoutMs: number;
262
+ };
263
+ temporary: {
264
+ maxActiveScopes: number;
265
+ maxTotalBytes: number;
266
+ maxTenantBytes: number;
267
+ staleAfterMs: number;
268
+ cleanupIntervalMs: number;
269
+ };
270
+ limits: ImageApiLimits;
271
+ references: {
272
+ ttlMs: number;
273
+ maxArtifactBytes: number;
274
+ maxTotalBytes: number;
275
+ maxTenantBytes: number;
276
+ maxEntries: number;
277
+ maxCalls: number;
278
+ maxResponses: number;
279
+ maxTombstones: number;
280
+ tombstoneTtlMs: number;
281
+ cleanupIntervalMs: number;
282
+ storageRoot?: string;
283
+ };
284
+ remote: {
285
+ enabled: boolean;
286
+ };
287
+ evidenceTtlMs: number;
288
+ }
289
+ /** Non-consuming, account-bound image model discovery injected by the daemon. */
290
+ interface ImageModelCatalogReader {
291
+ listAvailableModels(apiKeyId: string): Promise<readonly string[]>;
292
+ }
221
293
  /** A `"providerId,modelId"` model reference (mirrors `RouterConfig` vocab). */
222
294
  type ModelRef = string;
223
295
  /** The detected request role; precedence background > default. */
@@ -513,6 +585,69 @@ interface FingerprintConfig {
513
585
  /** Operator UA baseline for un-captured accounts (piece 4). Absent ⇒ none. */
514
586
  ua?: string;
515
587
  }
588
+ /**
589
+ * count_tokens strategy mode (§10 `anthropic.countTokens.mode`). ONE canonical
590
+ * union lives with the handler (`provider-proxy/ingress/anthropicCountTokens`);
591
+ * this alias re-exports it so the config-segment types and the runtime
592
+ * resolver can never drift apart (review B-M2).
593
+ */
594
+ type AnthropicCountTokensMode = CountTokensMode;
595
+ /** `GET /v1/models` response shape selector (§10 `anthropic.modelsShape`). */
596
+ type AnthropicModelsShape = 'auto' | 'anthropic' | 'openai';
597
+ /**
598
+ * Anthropic-protocol tuning segment (`claude-api-protocol-fidelity`, §10
599
+ * skeleton — count_tokens strategy/budget, /v1/models shape, synthetic-SSE
600
+ * heartbeat). Persisted + normalized like the other segments; read live per
601
+ * request (count_tokens/models) or hot-applied via the module setter
602
+ * (heartbeat). `proxyOauthUsage` / `apiHello` land in the follow-up change.
603
+ */
604
+ interface AnthropicConfigSegment {
605
+ /**
606
+ * `/v1/messages/count_tokens` strategy. `mode` absent ⇒ `'auto'`
607
+ * (Anthropic-wire upstream → passthrough; translation upstream → local
608
+ * estimate). `estimateBudgetMs` bounds the local estimator walk (default
609
+ * 2000; a pathological input degrades to a coarser estimate, never fails).
610
+ */
611
+ countTokens?: {
612
+ mode?: AnthropicCountTokensMode;
613
+ estimateBudgetMs?: number;
614
+ };
615
+ /**
616
+ * `GET /v1/models` response shape. `'auto'` (default): a key authorized for
617
+ * the messages endpoint gets the Anthropic list shape, everyone else keeps
618
+ * the OpenAI shape; `'anthropic'` / `'openai'` force one shape (escape
619
+ * hatch for dual-protocol consumers).
620
+ */
621
+ modelsShape?: AnthropicModelsShape;
622
+ /**
623
+ * Synthetic-SSE ping heartbeat interval (ms) for the TRANSLATION path only.
624
+ * Default 20000; ≤0 disables. Hot-applied at `applyConfig` — in-flight
625
+ * streams pick the new value at their next timer arm.
626
+ */
627
+ heartbeatIntervalMs?: number;
628
+ /**
629
+ * Translate-path PDF text extraction budget (`claude-api-transform-fidelity`,
630
+ * R7). `budgetMs` default 2000 — bounds the synchronous zero-dependency
631
+ * text-layer walk; over-budget documents 400 explicitly (never silently
632
+ * dropped, never unbounded work).
633
+ */
634
+ pdfTextExtraction?: {
635
+ budgetMs?: number;
636
+ };
637
+ /**
638
+ * Serve `GET /api/oauth/usage` on the outbound listener as a PURE-CACHE read
639
+ * of the shared Claude allowance store (R9). Default FALSE — off, the path
640
+ * keeps its current generic 404 byte-for-byte. When on, a messages-authorized
641
+ * key bound to a Claude subscription receives the api.anthropic.com usage
642
+ * wire shape; NO upstream call or refresh is ever triggered by the query.
643
+ */
644
+ proxyOauthUsage?: boolean;
645
+ /**
646
+ * Answer `HEAD /api/hello` with a bare 200 at the listener level (R10 —
647
+ * clients probe "can this endpoint be safely rejected"). Default TRUE.
648
+ */
649
+ apiHello?: boolean;
650
+ }
516
651
  /**
517
652
  * Layered upstream-proxy segment (upstream-proxy). Global + per-provider proxy
518
653
  * config for outbound EGRESS to upstreams (NOT the inbound listener). Resolved
@@ -627,6 +762,14 @@ interface OutboundApiServerConfig {
627
762
  * byte-identical zero regression, purely additive on the #4 key-policy.
628
763
  */
629
764
  voucher?: VoucherConfig;
765
+ /**
766
+ * Anthropic-protocol tuning segment (claude-api-protocol-fidelity, §10).
767
+ * Optional in the persisted shape; `normalizeServerConfig` always fills it
768
+ * with the frozen defaults (auto/auto/20000).
769
+ */
770
+ anthropic?: AnthropicConfigSegment;
771
+ /** Default-off Images serving policy; capability still requires fresh evidence. */
772
+ images?: ImagesServerConfig;
630
773
  }
631
774
  /** A live status snapshot the Settings tab renders. */
632
775
  interface OutboundApiServerStatus {
@@ -641,6 +784,15 @@ interface OutboundApiServerStatus {
641
784
  formats: OutboundFormatUrls | null;
642
785
  /** The four format endpoint URLs over the LAN (only when network binding on). */
643
786
  lanFormats: OutboundFormatUrls | null;
787
+ /** Additive Images endpoints; absent while Images is disabled. */
788
+ images?: {
789
+ generations: string;
790
+ edits: string;
791
+ } | null;
792
+ lanImages?: {
793
+ generations: string;
794
+ edits: string;
795
+ } | null;
644
796
  }
645
797
  /** The four format endpoint URLs for one base. */
646
798
  interface OutboundFormatUrls {
@@ -667,8 +819,10 @@ interface OutboundApiKeyInfo {
667
819
  revoked: boolean;
668
820
  /** Intended consumer. Existing rows default to a general client key. */
669
821
  kind?: 'client' | 'integration';
670
- /** Optional endpoint allow-list. Absent means every outbound endpoint. */
671
- allowedEndpoints?: OutboundEndpoint[];
822
+ /** Exact effective permission list; legacy absent rows project to text-only permissions. */
823
+ allowedEndpoints: OutboundPermission[];
824
+ /** True when the stored row omitted permissions and compatibility defaults were projected. */
825
+ legacyPermissions: boolean;
672
826
  /** When true the key is rejected unless the TCP peer is loopback. */
673
827
  loopbackOnly?: boolean;
674
828
  /**
@@ -746,6 +900,8 @@ interface OutboundApiKeyCreated {
746
900
  name: string;
747
901
  keyPrefix: string;
748
902
  createdAt: number;
903
+ /** Exact effective permission list assigned to the new key. */
904
+ allowedEndpoints: OutboundPermission[];
749
905
  plaintextOnce: string;
750
906
  }
751
907
  /**
@@ -773,8 +929,8 @@ interface OutboundKeyDbRow {
773
929
  revokedAt: number | null;
774
930
  /** Intended consumer. Existing rows without this field remain client keys. */
775
931
  kind?: 'client' | 'integration';
776
- /** Optional endpoint allow-list for least-privilege integration keys. */
777
- allowedEndpoints?: OutboundEndpoint[];
932
+ /** Persisted exact permission list. Absent is a legacy text-only row. */
933
+ allowedEndpoints?: OutboundPermission[];
778
934
  /** Restrict use to requests whose direct socket peer is loopback. */
779
935
  loopbackOnly?: boolean;
780
936
  /**
@@ -817,7 +973,7 @@ interface OutboundKeyDb {
817
973
  keyPrefix: string;
818
974
  createdAt?: number;
819
975
  kind?: 'client' | 'integration';
820
- allowedEndpoints?: OutboundEndpoint[];
976
+ allowedEndpoints?: OutboundPermission[];
821
977
  loopbackOnly?: boolean;
822
978
  /**
823
979
  * The generated plaintext secret. When the DB holds a `SecretBox` it
@@ -831,6 +987,8 @@ interface OutboundKeyDb {
831
987
  outboundApiKeysRevoke(id: string): Promise<boolean>;
832
988
  outboundApiKeysTouchLastUsed(id: string): Promise<boolean>;
833
989
  outboundApiKeysSetEnabled(id: string, enabled: boolean): Promise<boolean>;
990
+ /** Atomically replace the exact key permission list. */
991
+ outboundApiKeysSetPermissions(id: string, permissions: OutboundPermission[]): Promise<boolean>;
834
992
  /**
835
993
  * Set (or clear) a key's per-key concurrency ceiling. `null` clears the field
836
994
  * → unlimited (gate bypassed). Mirrors `outboundApiKeysSetEnabled`; returns
@@ -890,6 +1048,8 @@ interface OutboundApiDeps {
890
1048
  readonly providerProxy: ProviderProxy;
891
1049
  /** The proxy's app-session deps (reused verbatim for `routeRequest`). */
892
1050
  readonly proxyDeps: ProviderProxyDeps;
1051
+ /** Optional fail-closed Images catalog; absent means no image model is advertised. */
1052
+ readonly imageModelCatalog?: ImageModelCatalogReader;
893
1053
  /**
894
1054
  * OPTIONAL unauthenticated `/health` provider (daemon-health-endpoint, D1
895
1055
  * secondary mount). When wired (by the daemon bootstrap — core NEVER imports
@@ -917,4 +1077,4 @@ interface OutboundApiDeps {
917
1077
  readonly logger?: Logger;
918
1078
  }
919
1079
 
920
- export { type AccountProbeConfig as A, computeVoucherGrant as B, type ChatDispatchMode as C, generateVoucherCode as D, ENDPOINT_MODEL_KINDS as E, type FingerprintConfig as F, type GatewayBinding as G, hashVoucherCode as H, newVoucherId as I, startOfLocalDay as J, type KeySpendReader as K, startOfLocalWeek as L, type MessagesModelKind as M, toVoucherInfo as N, type OutboundKeyDb as O, voucherCodePrefix as P, type ModelRef as Q, type RequestRole as R, type AccountHealthConfig as S, type OutboundKeyModelRestrictionMode as T, type UserMessageQueueConfig as U, type VoucherCreateInput as V, type AllowanceSchedulingConfig as a, type ConcurrencyQueueConfig as b, type EndpointRoutingConfig as c, type GatewayBindingFallback as d, type GatewayBindingKeyScope as e, type GatewayBindingModelMode as f, type GatewayBindingTarget as g, type GatewayModelMapping as h, type KeySpendSeeder as i, KeySpendTracker as j, type KindMappedEndpoint as k, type ModelKind as l, type ModelPrefixTargets as m, type OutboundApiDeps as n, type OutboundApiKeyCreated as o, type OutboundApiKeyInfo as p, type OutboundApiServerConfig as q, type OutboundApiServerStatus as r, type OutboundEndpoint as s, type OutboundFormatUrls as t, type OutboundKeyActivationMode as u, type OutboundKeyDbRow as v, type OutboundKeyPolicy as w, type OutboundProxyConfig as x, type ResponsesModelKind as y, type VoucherDb as z };
1080
+ export { type OutboundKeyModelRestrictionMode as $, type AccountProbeConfig as A, type VoucherDb as B, type ChatDispatchMode as C, computeVoucherGrant as D, ENDPOINT_MODEL_KINDS as E, type FingerprintConfig as F, type GatewayBinding as G, generateVoucherCode as H, type ImagesServerConfig as I, hashVoucherCode as J, type KeySpendReader as K, newVoucherId as L, type MessagesModelKind as M, startOfLocalDay as N, type OutboundKeyDb as O, startOfLocalWeek as P, toVoucherInfo as Q, type RequestRole as R, voucherCodePrefix as S, type ModelRef as T, type UserMessageQueueConfig as U, type VoucherCreateInput as V, type AnthropicConfigSegment as W, type AccountHealthConfig as X, type AnthropicCountTokensMode as Y, type AnthropicModelsShape as Z, type ImageModelCatalogReader as _, type AllowanceSchedulingConfig as a, type ConcurrencyQueueConfig as b, type EndpointRoutingConfig as c, type GatewayBindingFallback as d, type GatewayBindingKeyScope as e, type GatewayBindingModelMode as f, type GatewayBindingTarget as g, type GatewayModelMapping as h, type KeySpendSeeder as i, KeySpendTracker as j, type KindMappedEndpoint as k, type ModelKind as l, type ModelPrefixTargets as m, type OutboundApiDeps as n, type OutboundApiKeyCreated as o, type OutboundApiKeyInfo as p, type OutboundApiServerConfig as q, type OutboundApiServerStatus as r, type OutboundEndpoint as s, type OutboundFormatUrls as t, type OutboundKeyActivationMode as u, type OutboundKeyDbRow as v, type OutboundKeyPolicy as w, type OutboundPermission as x, type OutboundProxyConfig as y, type ResponsesModelKind as z };
@@ -1,7 +1,7 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
2
 
3
- var _chunkEPN67EGPcjs = require('../chunk-EPN67EGP.cjs');
3
+ var _chunk5UK3KLE2cjs = require('../chunk-5UK3KLE2.cjs');
4
4
  require('../chunk-XSVNC2UD.cjs');
5
5
 
6
6
 
7
- exports.UsageRecorder = _chunkEPN67EGPcjs.UsageRecorder;
7
+ exports.UsageRecorder = _chunk5UK3KLE2cjs.UsageRecorder;
@@ -1,8 +1,8 @@
1
- import { PricingEngine } from './pricing-engine.cjs';
2
- import { UsageCacheKeySource, UsageDateRange, UsageTotals, ModelUsageRow, ApiKeyUsageRow, UsageTimeBucket, UsageTimeSeriesBucket, MessageUsageRow, SessionCacheStats } from '@omnicross/contracts/usage-stats-types';
1
+ import { UsageCacheKeySource, UsageEventInput, UsageDateRange, UsageTotals, ModelUsageRow, ApiKeyUsageRow, UsageTimeBucket, UsageTimeSeriesBucket, MessageUsageRow, SessionCacheStats } from '@omnicross/contracts/usage-stats-types';
3
2
  import { UsageEngineOrigin, UsageTokens } from '@omnicross/contracts/usage-types';
4
3
  import { L as Logger } from '../logger-4GvQNzhE.cjs';
5
4
  import { UsageEventStore } from '../ports/usage-event-store.cjs';
5
+ import { PricingEngine } from './pricing-engine.cjs';
6
6
  import '@omnicross/contracts/pricing-types';
7
7
  import '../ports/pricing-store.cjs';
8
8
 
@@ -69,6 +69,15 @@ interface UsageRecorderOptions {
69
69
  * Absent ⇒ no-op (byte-identical for hosts/tests that do not wire it).
70
70
  */
71
71
  onRecord?: (apiKeyId: string, costUsd: number, now: number) => void;
72
+ /**
73
+ * OPTIONAL per-request hook (live-throughput). Called synchronously with the
74
+ * FINISHED row, immediately before the store insert, for EVERY recorded
75
+ * request — attributed or not. Distinct from `onRecord`, which is gated on
76
+ * `apiKeyId` and carries only the cost: a rate metric must see subscription-
77
+ * account traffic too, and needs the token counts. Absent ⇒ no-op
78
+ * (byte-identical for hosts/tests that do not wire it).
79
+ */
80
+ onEvent?: (row: UsageEventInput, at: number) => void;
72
81
  }
73
82
  declare class UsageRecorder {
74
83
  private store;
@@ -76,6 +85,7 @@ declare class UsageRecorder {
76
85
  private logger;
77
86
  private defer;
78
87
  private onRecord?;
88
+ private onEvent?;
79
89
  constructor(store: UsageEventStore, pricing: PricingEngine, logger: Logger, options?: UsageRecorderOptions);
80
90
  /**
81
91
  * Record one LLM request. Returns immediately — the actual store insert is
@@ -1,8 +1,8 @@
1
- import { PricingEngine } from './pricing-engine.js';
2
- import { UsageCacheKeySource, UsageDateRange, UsageTotals, ModelUsageRow, ApiKeyUsageRow, UsageTimeBucket, UsageTimeSeriesBucket, MessageUsageRow, SessionCacheStats } from '@omnicross/contracts/usage-stats-types';
1
+ import { UsageCacheKeySource, UsageEventInput, UsageDateRange, UsageTotals, ModelUsageRow, ApiKeyUsageRow, UsageTimeBucket, UsageTimeSeriesBucket, MessageUsageRow, SessionCacheStats } from '@omnicross/contracts/usage-stats-types';
3
2
  import { UsageEngineOrigin, UsageTokens } from '@omnicross/contracts/usage-types';
4
3
  import { L as Logger } from '../logger-4GvQNzhE.js';
5
4
  import { UsageEventStore } from '../ports/usage-event-store.js';
5
+ import { PricingEngine } from './pricing-engine.js';
6
6
  import '@omnicross/contracts/pricing-types';
7
7
  import '../ports/pricing-store.js';
8
8
 
@@ -69,6 +69,15 @@ interface UsageRecorderOptions {
69
69
  * Absent ⇒ no-op (byte-identical for hosts/tests that do not wire it).
70
70
  */
71
71
  onRecord?: (apiKeyId: string, costUsd: number, now: number) => void;
72
+ /**
73
+ * OPTIONAL per-request hook (live-throughput). Called synchronously with the
74
+ * FINISHED row, immediately before the store insert, for EVERY recorded
75
+ * request — attributed or not. Distinct from `onRecord`, which is gated on
76
+ * `apiKeyId` and carries only the cost: a rate metric must see subscription-
77
+ * account traffic too, and needs the token counts. Absent ⇒ no-op
78
+ * (byte-identical for hosts/tests that do not wire it).
79
+ */
80
+ onEvent?: (row: UsageEventInput, at: number) => void;
72
81
  }
73
82
  declare class UsageRecorder {
74
83
  private store;
@@ -76,6 +85,7 @@ declare class UsageRecorder {
76
85
  private logger;
77
86
  private defer;
78
87
  private onRecord?;
88
+ private onEvent?;
79
89
  constructor(store: UsageEventStore, pricing: PricingEngine, logger: Logger, options?: UsageRecorderOptions);
80
90
  /**
81
91
  * Record one LLM request. Returns immediately — the actual store insert is
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  UsageRecorder
3
- } from "../chunk-UAPBLNN2.js";
3
+ } from "../chunk-AQDON6MB.js";
4
4
  import "../chunk-OZFM4X3S.js";
5
5
  export {
6
6
  UsageRecorder
package/dist/usage.cjs CHANGED
@@ -1,12 +1,29 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});require('./chunk-EYZYXJTJ.cjs');
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+ var _chunk32SRZFFPcjs = require('./chunk-32SRZFFP.cjs');
2
11
 
3
12
 
4
13
  var _chunk2E42SAW3cjs = require('./chunk-2E42SAW3.cjs');
5
14
 
6
15
 
7
- var _chunkEPN67EGPcjs = require('./chunk-EPN67EGP.cjs');
16
+ var _chunk5UK3KLE2cjs = require('./chunk-5UK3KLE2.cjs');
8
17
  require('./chunk-XSVNC2UD.cjs');
9
18
 
10
19
 
11
20
 
12
- exports.PricingEngine = _chunk2E42SAW3cjs.PricingEngine; exports.UsageRecorder = _chunkEPN67EGPcjs.UsageRecorder;
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+ exports.PricingEngine = _chunk2E42SAW3cjs.PricingEngine; exports.THROUGHPUT_BUCKET_COUNT = _chunk32SRZFFPcjs.THROUGHPUT_BUCKET_COUNT; exports.THROUGHPUT_RETENTION_MS = _chunk32SRZFFPcjs.THROUGHPUT_RETENTION_MS; exports.THROUGHPUT_SAMPLE_LIMIT = _chunk32SRZFFPcjs.THROUGHPUT_SAMPLE_LIMIT; exports.THROUGHPUT_WINDOWS_MS = _chunk32SRZFFPcjs.THROUGHPUT_WINDOWS_MS; exports.UsageRecorder = _chunk5UK3KLE2cjs.UsageRecorder; exports.UsageThroughputTracker = _chunk32SRZFFPcjs.UsageThroughputTracker; exports.__resetSharedUsageThroughputTrackerForTests = _chunk32SRZFFPcjs.__resetSharedUsageThroughputTrackerForTests; exports.getSharedUsageThroughputTracker = _chunk32SRZFFPcjs.getSharedUsageThroughputTracker; exports.setSharedUsageThroughputTracker = _chunk32SRZFFPcjs.setSharedUsageThroughputTracker;
package/dist/usage.d.cts CHANGED
@@ -6,3 +6,157 @@ import './logger-4GvQNzhE.cjs';
6
6
  import './ports/pricing-store.cjs';
7
7
  import '@omnicross/contracts/usage-stats-types';
8
8
  import './ports/usage-event-store.cjs';
9
+
10
+ /**
11
+ * throughputTracker — a bounded, in-memory sliding window of recently recorded
12
+ * usage events, answering "how fast is the gateway serving RIGHT NOW".
13
+ *
14
+ * WHY a dedicated in-memory store (not a `UsageEventStore` range query): the
15
+ * daemon's `JsonlUsageEventStore.getTotals()` reads and parses the ENTIRE
16
+ * `usage-events.jsonl` synchronously on every call (a deliberate simplification
17
+ * documented there). That is fine for an on-demand stats page, but a live rate
18
+ * widget polls every few seconds, and a periodic synchronous full-file scan
19
+ * would stall the same event loop that is relaying gateway requests. This
20
+ * tracker is fed O(1) per recorded request from `UsageRecorder`'s `onEvent`
21
+ * hook and read in O(samples-in-window) — it never touches disk.
22
+ *
23
+ * Shaped like `pipeline/ServerOverloadCounter`: process-local, cleared on
24
+ * restart, an injectable `now` clock, no external deps. It carries ONLY token
25
+ * counts, costs, and epoch timestamps — never a prompt, header, model secret,
26
+ * or key id — so no snapshot of it can leak one.
27
+ *
28
+ * TWO MEASUREMENT DECISIONS worth stating explicitly, because both are easy to
29
+ * get subtly wrong:
30
+ *
31
+ * 1. `totalTokens` deliberately EXCLUDES `reasoningTokens`. Providers report
32
+ * reasoning tokens as a SUBSET of the completion/output tokens, so adding
33
+ * them would double-count. They are still reported separately.
34
+ *
35
+ * 2. Rates always divide by the FULL requested window, never by "how long this
36
+ * process has been up". A daemon that was down served no traffic, so the
37
+ * honest rate over that wall-clock window really is lower; after a restart
38
+ * the number climbs back from zero on its own. `startedAt` is reported so a
39
+ * reader can say "this process started less than a window ago" without the
40
+ * rate itself being fudged.
41
+ *
42
+ * @module usage/throughputTracker
43
+ */
44
+ /** Longest window a snapshot can answer; also the sample-retention horizon. */
45
+ declare const THROUGHPUT_RETENTION_MS: number;
46
+ /**
47
+ * Hard memory ceiling on retained samples (~20k x a few dozen bytes). Reaching
48
+ * it means sustained >22 req/s for a full 15 minutes; past that the OLDEST
49
+ * samples are evicted and the affected windows report `complete: false` rather
50
+ * than quietly under-reporting.
51
+ */
52
+ declare const THROUGHPUT_SAMPLE_LIMIT = 20000;
53
+ /** Windows every snapshot reports, shortest first. The last must be <= retention. */
54
+ declare const THROUGHPUT_WINDOWS_MS: readonly [60000, 300000, 900000];
55
+ /** Trend-series resolution: 30 buckets across the retention horizon (30s each). */
56
+ declare const THROUGHPUT_BUCKET_COUNT = 30;
57
+ /**
58
+ * One recorded request's contribution. Structurally satisfied by the recorder's
59
+ * `UsageEventInput` row, so the daemon can forward it verbatim.
60
+ */
61
+ interface UsageThroughputInput {
62
+ inputTokens: number;
63
+ outputTokens: number;
64
+ cacheReadTokens: number;
65
+ cacheCreationTokens: number;
66
+ reasoningTokens: number;
67
+ costUsd: number;
68
+ /** Epoch-ms of the event. Omit to use the `now` argument. */
69
+ ts?: number;
70
+ }
71
+ /** Aggregates + rates for one trailing window. */
72
+ interface UsageThroughputWindow {
73
+ /** Trailing window this row covers, in ms. */
74
+ windowMs: number;
75
+ requests: number;
76
+ inputTokens: number;
77
+ outputTokens: number;
78
+ cacheReadTokens: number;
79
+ cacheCreationTokens: number;
80
+ reasoningTokens: number;
81
+ /** input + output + cacheRead + cacheCreation (reasoning is a subset of output). */
82
+ totalTokens: number;
83
+ costUsd: number;
84
+ requestsPerMinute: number;
85
+ /** `totalTokens` per minute over `windowMs`. */
86
+ tokensPerMinute: number;
87
+ inputTokensPerMinute: number;
88
+ outputTokensPerMinute: number;
89
+ /** cacheRead + cacheCreation per minute over `windowMs`. */
90
+ cacheTokensPerMinute: number;
91
+ costUsdPerMinute: number;
92
+ /**
93
+ * False when the sample cap evicted events that fall inside this window, so
94
+ * every figure above is a LOWER BOUND rather than an exact count.
95
+ */
96
+ complete: boolean;
97
+ }
98
+ /** One fixed-width bucket of the trend series. */
99
+ interface UsageThroughputBucket {
100
+ /** Epoch-ms of the bucket's (grid-aligned) start. */
101
+ startTs: number;
102
+ requests: number;
103
+ /** input + output + cacheRead + cacheCreation (same basis as `totalTokens`). */
104
+ tokens: number;
105
+ /** Output tokens alone, so a card headlining output can trend in step. */
106
+ outputTokens: number;
107
+ }
108
+ /** The `GET /admin/api/usage/throughput` payload. */
109
+ interface UsageThroughputSnapshot {
110
+ /** Always true here; the UI's fallback shape uses `false` for older daemons. */
111
+ available: true;
112
+ collectedAt: number;
113
+ /** Epoch-ms this tracker began observing (effectively the daemon's start). */
114
+ startedAt: number;
115
+ retentionMs: number;
116
+ /** Width of one `buckets` entry, in ms. */
117
+ bucketMs: number;
118
+ /** One row per {@link THROUGHPUT_WINDOWS_MS} entry, shortest window first. */
119
+ windows: UsageThroughputWindow[];
120
+ /**
121
+ * Oldest to newest, exactly {@link THROUGHPUT_BUCKET_COUNT} entries covering
122
+ * `retentionMs` on a `bucketMs` grid. Empty buckets are present and zeroed;
123
+ * the final bucket is still in progress. Grid alignment (rather than
124
+ * "now minus retention") keeps boundaries stable between polls so a sparkline
125
+ * does not shimmer.
126
+ */
127
+ buckets: UsageThroughputBucket[];
128
+ }
129
+ declare class UsageThroughputTracker {
130
+ private samples;
131
+ /** Index of the oldest live sample; slots before it are consumed. */
132
+ private head;
133
+ private readonly startedAt;
134
+ /** Newest ts dropped by the sample CAP (not by retention). Null when none. */
135
+ private evictedThroughTs;
136
+ constructor(now?: number);
137
+ /** Record one served request. O(1) amortised; never touches disk. */
138
+ record(input: UsageThroughputInput, now?: number): void;
139
+ /** Aggregate every reported window plus the shared trend series. */
140
+ snapshot(now?: number): UsageThroughputSnapshot;
141
+ /** Drop all samples (tests / teardown). `startedAt` is unchanged. */
142
+ clear(): void;
143
+ /**
144
+ * Drop samples past the retention horizon, then enforce the sample cap.
145
+ *
146
+ * Retention pruning uses the CALLER's `now`, which is never later than a
147
+ * subsequent snapshot's `now`, so it can only ever keep MORE than the widest
148
+ * window needs — it can never shave data off the 15-minute window.
149
+ */
150
+ private prune;
151
+ private window;
152
+ private buckets;
153
+ }
154
+ declare function getSharedUsageThroughputTracker(): UsageThroughputTracker;
155
+ /**
156
+ * TEST SEAM — swap the singleton (e.g. with a fixed-clock instance). Mirrors the
157
+ * `setShared…`/`__reset…ForTests` discipline of the sibling in-memory stores.
158
+ */
159
+ declare function setSharedUsageThroughputTracker(instance: UsageThroughputTracker): void;
160
+ declare function __resetSharedUsageThroughputTrackerForTests(): void;
161
+
162
+ export { THROUGHPUT_BUCKET_COUNT, THROUGHPUT_RETENTION_MS, THROUGHPUT_SAMPLE_LIMIT, THROUGHPUT_WINDOWS_MS, type UsageThroughputBucket, type UsageThroughputInput, type UsageThroughputSnapshot, UsageThroughputTracker, type UsageThroughputWindow, __resetSharedUsageThroughputTrackerForTests, getSharedUsageThroughputTracker, setSharedUsageThroughputTracker };