@omnicross/core 0.1.8 → 0.1.10

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 (113) hide show
  1. package/dist/auth/GeminiCodeAssistProjectResolver.cjs +5 -3
  2. package/dist/auth/GeminiCodeAssistProjectResolver.js +4 -2
  3. package/dist/{chunk-N5T4M4GU.js → chunk-2UTGX6FM.js} +2 -2
  4. package/dist/{chunk-32O35CIF.js → chunk-45FHEOKW.js} +22 -7
  5. package/dist/{chunk-LVUCAWMK.js → chunk-55FMGZ3L.js} +13 -5
  6. package/dist/{chunk-OF3BECU2.cjs → chunk-56QD3YW6.cjs} +18 -5
  7. package/dist/{chunk-V4TXMEJS.cjs → chunk-5LNYGCIW.cjs} +15 -7
  8. package/dist/{chunk-EPN67EGP.cjs → chunk-5UK3KLE2.cjs} +9 -1
  9. package/dist/chunk-6D4W22P4.js +150 -0
  10. package/dist/chunk-77USGNRW.cjs +37 -0
  11. package/dist/chunk-AOFWNWLT.cjs +203 -0
  12. package/dist/{chunk-UAPBLNN2.js → chunk-AQDON6MB.js} +8 -0
  13. package/dist/{chunk-LB6EBS6Y.js → chunk-CCVRRJOX.js} +17 -4
  14. package/dist/{chunk-OVQBNVSV.cjs → chunk-CMVXX7ON.cjs} +42 -27
  15. package/dist/{chunk-QYC54PMG.js → chunk-FEBAQI5A.js} +255 -92
  16. package/dist/{chunk-7C7DET6S.js → chunk-GXEZ2R3E.js} +156 -1
  17. package/dist/{chunk-PEGTIPB3.js → chunk-HKB656B4.js} +37 -43
  18. package/dist/chunk-N2EIM2XJ.js +203 -0
  19. package/dist/{chunk-MYYR3HZL.js → chunk-NGYOO5TO.js} +5 -5
  20. package/dist/{chunk-OKMJLEXX.cjs → chunk-OC6DOOFX.cjs} +5 -5
  21. package/dist/{chunk-2Z4XM3H5.cjs → chunk-P7EM6BND.cjs} +10 -10
  22. package/dist/chunk-QUSEZNYS.cjs +150 -0
  23. package/dist/{chunk-KBM2W6UY.cjs → chunk-RICPANBY.cjs} +41 -24
  24. package/dist/{chunk-TOVPMMHM.js → chunk-S3DYFEBE.js} +37 -20
  25. package/dist/{chunk-26K6T2YS.cjs → chunk-TIT74RIL.cjs} +407 -244
  26. package/dist/{chunk-XPIOJQS2.cjs → chunk-UWDW6PN3.cjs} +159 -4
  27. package/dist/chunk-WYVGULTQ.js +37 -0
  28. package/dist/{chunk-OXHNSZ53.cjs → chunk-ZQQUD66M.cjs} +54 -60
  29. package/dist/completion/CompletionService.cjs +15 -13
  30. package/dist/completion/CompletionService.js +14 -12
  31. package/dist/completion.cjs +15 -13
  32. package/dist/completion.js +14 -12
  33. package/dist/index.cjs +15 -13
  34. package/dist/index.d.cts +2 -2
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.js +14 -12
  37. package/dist/outbound-api/auditCapture.cjs +2 -2
  38. package/dist/outbound-api/auditCapture.d.cts +6 -0
  39. package/dist/outbound-api/auditCapture.d.ts +6 -0
  40. package/dist/outbound-api/auditCapture.js +1 -1
  41. package/dist/outbound-api/routeResolver.d.cts +1 -1
  42. package/dist/outbound-api/routeResolver.d.ts +1 -1
  43. package/dist/outbound-api/types.d.cts +1 -1
  44. package/dist/outbound-api/types.d.ts +1 -1
  45. package/dist/outbound-api.cjs +15 -13
  46. package/dist/outbound-api.d.cts +3 -2
  47. package/dist/outbound-api.d.ts +3 -2
  48. package/dist/outbound-api.js +14 -12
  49. package/dist/pipeline/AccountAllowanceScheduling.d.cts +1 -1
  50. package/dist/pipeline/AccountAllowanceScheduling.d.ts +1 -1
  51. package/dist/pipeline/executeProviderCall.d.cts +2 -0
  52. package/dist/pipeline/executeProviderCall.d.ts +2 -0
  53. package/dist/pipeline/resolveProviderChain.d.cts +1 -0
  54. package/dist/pipeline/resolveProviderChain.d.ts +1 -0
  55. package/dist/pipeline/resolveSubscriptionChain.d.cts +2 -0
  56. package/dist/pipeline/resolveSubscriptionChain.d.ts +2 -0
  57. package/dist/ports/provider-config-source.d.cts +1 -0
  58. package/dist/ports/provider-config-source.d.ts +1 -0
  59. package/dist/ports.d.cts +1 -1
  60. package/dist/ports.d.ts +1 -1
  61. package/dist/provider-proxy/ProviderProxy.cjs +15 -13
  62. package/dist/provider-proxy/ProviderProxy.js +14 -12
  63. package/dist/provider-proxy/ingress/providerProxyShared.cjs +15 -13
  64. package/dist/provider-proxy/ingress/providerProxyShared.js +14 -12
  65. package/dist/provider-proxy.cjs +15 -13
  66. package/dist/provider-proxy.js +14 -12
  67. package/dist/transformer/TransformerChainExecutor.d.cts +2 -0
  68. package/dist/transformer/TransformerChainExecutor.d.ts +2 -0
  69. package/dist/transformer/TransformerService.d.cts +2 -0
  70. package/dist/transformer/TransformerService.d.ts +2 -0
  71. package/dist/transformer/transformers/AnthropicTransformer.cjs +4 -2
  72. package/dist/transformer/transformers/AnthropicTransformer.d.cts +7 -2
  73. package/dist/transformer/transformers/AnthropicTransformer.d.ts +7 -2
  74. package/dist/transformer/transformers/AnthropicTransformer.js +3 -1
  75. package/dist/transformer/transformers/GeminiCodeAssistTransformer.cjs +5 -3
  76. package/dist/transformer/transformers/GeminiCodeAssistTransformer.d.cts +2 -0
  77. package/dist/transformer/transformers/GeminiCodeAssistTransformer.d.ts +2 -0
  78. package/dist/transformer/transformers/GeminiCodeAssistTransformer.js +4 -2
  79. package/dist/transformer/transformers/GeminiTransformer.cjs +5 -3
  80. package/dist/transformer/transformers/GeminiTransformer.d.cts +4 -2
  81. package/dist/transformer/transformers/GeminiTransformer.d.ts +4 -2
  82. package/dist/transformer/transformers/GeminiTransformer.js +4 -2
  83. package/dist/transformer/transformers/OpenAIResponseTransformer.cjs +3 -2
  84. package/dist/transformer/transformers/OpenAIResponseTransformer.d.cts +4 -2
  85. package/dist/transformer/transformers/OpenAIResponseTransformer.d.ts +4 -2
  86. package/dist/transformer/transformers/OpenAIResponseTransformer.js +2 -1
  87. package/dist/transformer/transformers/OpenAITransformer.cjs +3 -2
  88. package/dist/transformer/transformers/OpenAITransformer.d.cts +3 -1
  89. package/dist/transformer/transformers/OpenAITransformer.d.ts +3 -1
  90. package/dist/transformer/transformers/OpenAITransformer.js +2 -1
  91. package/dist/transformer/transformers.cjs +10 -8
  92. package/dist/transformer/transformers.d.cts +2 -0
  93. package/dist/transformer/transformers.d.ts +2 -0
  94. package/dist/transformer/transformers.js +9 -7
  95. package/dist/transformer/types.d.cts +16 -5
  96. package/dist/transformer/types.d.ts +16 -5
  97. package/dist/transformer.cjs +28 -9
  98. package/dist/transformer.d.cts +76 -1
  99. package/dist/transformer.d.ts +76 -1
  100. package/dist/transformer.js +28 -9
  101. package/dist/usage/usage-recorder.cjs +2 -2
  102. package/dist/usage/usage-recorder.d.cts +12 -2
  103. package/dist/usage/usage-recorder.d.ts +12 -2
  104. package/dist/usage/usage-recorder.js +1 -1
  105. package/dist/usage.cjs +20 -3
  106. package/dist/usage.d.cts +149 -0
  107. package/dist/usage.d.ts +149 -0
  108. package/dist/usage.js +20 -3
  109. package/package.json +2 -2
  110. package/dist/chunk-7VU7V2E4.js +0 -0
  111. package/dist/chunk-FZ46M34D.cjs +0 -1
  112. /package/dist/{chunk-EYZYXJTJ.cjs → chunk-QVOB2DNX.cjs} +0 -0
  113. /package/dist/{chunk-46RLHI7D.js → chunk-WTQMX2Q6.js} +0 -0
@@ -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 _chunkQUSEZNYScjs = require('./chunk-QUSEZNYS.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 = _chunkQUSEZNYScjs.THROUGHPUT_BUCKET_COUNT; exports.THROUGHPUT_RETENTION_MS = _chunkQUSEZNYScjs.THROUGHPUT_RETENTION_MS; exports.THROUGHPUT_SAMPLE_LIMIT = _chunkQUSEZNYScjs.THROUGHPUT_SAMPLE_LIMIT; exports.THROUGHPUT_WINDOWS_MS = _chunkQUSEZNYScjs.THROUGHPUT_WINDOWS_MS; exports.UsageRecorder = _chunk5UK3KLE2cjs.UsageRecorder; exports.UsageThroughputTracker = _chunkQUSEZNYScjs.UsageThroughputTracker; exports.__resetSharedUsageThroughputTrackerForTests = _chunkQUSEZNYScjs.__resetSharedUsageThroughputTrackerForTests; exports.getSharedUsageThroughputTracker = _chunkQUSEZNYScjs.getSharedUsageThroughputTracker; exports.setSharedUsageThroughputTracker = _chunkQUSEZNYScjs.setSharedUsageThroughputTracker;
package/dist/usage.d.cts CHANGED
@@ -6,3 +6,152 @@ 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
+ /** The headline TPM: `totalTokens` per minute over `windowMs`. */
86
+ tokensPerMinute: number;
87
+ inputTokensPerMinute: number;
88
+ outputTokensPerMinute: number;
89
+ costUsdPerMinute: number;
90
+ /**
91
+ * False when the sample cap evicted events that fall inside this window, so
92
+ * every figure above is a LOWER BOUND rather than an exact count.
93
+ */
94
+ complete: boolean;
95
+ }
96
+ /** One fixed-width bucket of the trend series. */
97
+ interface UsageThroughputBucket {
98
+ /** Epoch-ms of the bucket's (grid-aligned) start. */
99
+ startTs: number;
100
+ requests: number;
101
+ tokens: number;
102
+ }
103
+ /** The `GET /admin/api/usage/throughput` payload. */
104
+ interface UsageThroughputSnapshot {
105
+ /** Always true here; the UI's fallback shape uses `false` for older daemons. */
106
+ available: true;
107
+ collectedAt: number;
108
+ /** Epoch-ms this tracker began observing (effectively the daemon's start). */
109
+ startedAt: number;
110
+ retentionMs: number;
111
+ /** Width of one `buckets` entry, in ms. */
112
+ bucketMs: number;
113
+ /** One row per {@link THROUGHPUT_WINDOWS_MS} entry, shortest window first. */
114
+ windows: UsageThroughputWindow[];
115
+ /**
116
+ * Oldest to newest, exactly {@link THROUGHPUT_BUCKET_COUNT} entries covering
117
+ * `retentionMs` on a `bucketMs` grid. Empty buckets are present and zeroed;
118
+ * the final bucket is still in progress. Grid alignment (rather than
119
+ * "now minus retention") keeps boundaries stable between polls so a sparkline
120
+ * does not shimmer.
121
+ */
122
+ buckets: UsageThroughputBucket[];
123
+ }
124
+ declare class UsageThroughputTracker {
125
+ private samples;
126
+ /** Index of the oldest live sample; slots before it are consumed. */
127
+ private head;
128
+ private readonly startedAt;
129
+ /** Newest ts dropped by the sample CAP (not by retention). Null when none. */
130
+ private evictedThroughTs;
131
+ constructor(now?: number);
132
+ /** Record one served request. O(1) amortised; never touches disk. */
133
+ record(input: UsageThroughputInput, now?: number): void;
134
+ /** Aggregate every reported window plus the shared trend series. */
135
+ snapshot(now?: number): UsageThroughputSnapshot;
136
+ /** Drop all samples (tests / teardown). `startedAt` is unchanged. */
137
+ clear(): void;
138
+ /**
139
+ * Drop samples past the retention horizon, then enforce the sample cap.
140
+ *
141
+ * Retention pruning uses the CALLER's `now`, which is never later than a
142
+ * subsequent snapshot's `now`, so it can only ever keep MORE than the widest
143
+ * window needs — it can never shave data off the 15-minute window.
144
+ */
145
+ private prune;
146
+ private window;
147
+ private buckets;
148
+ }
149
+ declare function getSharedUsageThroughputTracker(): UsageThroughputTracker;
150
+ /**
151
+ * TEST SEAM — swap the singleton (e.g. with a fixed-clock instance). Mirrors the
152
+ * `setShared…`/`__reset…ForTests` discipline of the sibling in-memory stores.
153
+ */
154
+ declare function setSharedUsageThroughputTracker(instance: UsageThroughputTracker): void;
155
+ declare function __resetSharedUsageThroughputTrackerForTests(): void;
156
+
157
+ 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 };
package/dist/usage.d.ts CHANGED
@@ -6,3 +6,152 @@ import './logger-4GvQNzhE.js';
6
6
  import './ports/pricing-store.js';
7
7
  import '@omnicross/contracts/usage-stats-types';
8
8
  import './ports/usage-event-store.js';
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
+ /** The headline TPM: `totalTokens` per minute over `windowMs`. */
86
+ tokensPerMinute: number;
87
+ inputTokensPerMinute: number;
88
+ outputTokensPerMinute: number;
89
+ costUsdPerMinute: number;
90
+ /**
91
+ * False when the sample cap evicted events that fall inside this window, so
92
+ * every figure above is a LOWER BOUND rather than an exact count.
93
+ */
94
+ complete: boolean;
95
+ }
96
+ /** One fixed-width bucket of the trend series. */
97
+ interface UsageThroughputBucket {
98
+ /** Epoch-ms of the bucket's (grid-aligned) start. */
99
+ startTs: number;
100
+ requests: number;
101
+ tokens: number;
102
+ }
103
+ /** The `GET /admin/api/usage/throughput` payload. */
104
+ interface UsageThroughputSnapshot {
105
+ /** Always true here; the UI's fallback shape uses `false` for older daemons. */
106
+ available: true;
107
+ collectedAt: number;
108
+ /** Epoch-ms this tracker began observing (effectively the daemon's start). */
109
+ startedAt: number;
110
+ retentionMs: number;
111
+ /** Width of one `buckets` entry, in ms. */
112
+ bucketMs: number;
113
+ /** One row per {@link THROUGHPUT_WINDOWS_MS} entry, shortest window first. */
114
+ windows: UsageThroughputWindow[];
115
+ /**
116
+ * Oldest to newest, exactly {@link THROUGHPUT_BUCKET_COUNT} entries covering
117
+ * `retentionMs` on a `bucketMs` grid. Empty buckets are present and zeroed;
118
+ * the final bucket is still in progress. Grid alignment (rather than
119
+ * "now minus retention") keeps boundaries stable between polls so a sparkline
120
+ * does not shimmer.
121
+ */
122
+ buckets: UsageThroughputBucket[];
123
+ }
124
+ declare class UsageThroughputTracker {
125
+ private samples;
126
+ /** Index of the oldest live sample; slots before it are consumed. */
127
+ private head;
128
+ private readonly startedAt;
129
+ /** Newest ts dropped by the sample CAP (not by retention). Null when none. */
130
+ private evictedThroughTs;
131
+ constructor(now?: number);
132
+ /** Record one served request. O(1) amortised; never touches disk. */
133
+ record(input: UsageThroughputInput, now?: number): void;
134
+ /** Aggregate every reported window plus the shared trend series. */
135
+ snapshot(now?: number): UsageThroughputSnapshot;
136
+ /** Drop all samples (tests / teardown). `startedAt` is unchanged. */
137
+ clear(): void;
138
+ /**
139
+ * Drop samples past the retention horizon, then enforce the sample cap.
140
+ *
141
+ * Retention pruning uses the CALLER's `now`, which is never later than a
142
+ * subsequent snapshot's `now`, so it can only ever keep MORE than the widest
143
+ * window needs — it can never shave data off the 15-minute window.
144
+ */
145
+ private prune;
146
+ private window;
147
+ private buckets;
148
+ }
149
+ declare function getSharedUsageThroughputTracker(): UsageThroughputTracker;
150
+ /**
151
+ * TEST SEAM — swap the singleton (e.g. with a fixed-clock instance). Mirrors the
152
+ * `setShared…`/`__reset…ForTests` discipline of the sibling in-memory stores.
153
+ */
154
+ declare function setSharedUsageThroughputTracker(instance: UsageThroughputTracker): void;
155
+ declare function __resetSharedUsageThroughputTrackerForTests(): void;
156
+
157
+ 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 };
package/dist/usage.js CHANGED
@@ -1,12 +1,29 @@
1
- import "./chunk-7VU7V2E4.js";
1
+ import {
2
+ THROUGHPUT_BUCKET_COUNT,
3
+ THROUGHPUT_RETENTION_MS,
4
+ THROUGHPUT_SAMPLE_LIMIT,
5
+ THROUGHPUT_WINDOWS_MS,
6
+ UsageThroughputTracker,
7
+ __resetSharedUsageThroughputTrackerForTests,
8
+ getSharedUsageThroughputTracker,
9
+ setSharedUsageThroughputTracker
10
+ } from "./chunk-6D4W22P4.js";
2
11
  import {
3
12
  PricingEngine
4
13
  } from "./chunk-FXR6N3SR.js";
5
14
  import {
6
15
  UsageRecorder
7
- } from "./chunk-UAPBLNN2.js";
16
+ } from "./chunk-AQDON6MB.js";
8
17
  import "./chunk-OZFM4X3S.js";
9
18
  export {
10
19
  PricingEngine,
11
- UsageRecorder
20
+ THROUGHPUT_BUCKET_COUNT,
21
+ THROUGHPUT_RETENTION_MS,
22
+ THROUGHPUT_SAMPLE_LIMIT,
23
+ THROUGHPUT_WINDOWS_MS,
24
+ UsageRecorder,
25
+ UsageThroughputTracker,
26
+ __resetSharedUsageThroughputTrackerForTests,
27
+ getSharedUsageThroughputTracker,
28
+ setSharedUsageThroughputTracker
12
29
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@omnicross/core",
3
- "version": "0.1.8",
4
- "description": "Omnicross LLM serving core 鈥?provider dispatch, completion pipeline, transformers, and the provider proxy.",
3
+ "version": "0.1.10",
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)",
7
7
  "homepage": "https://github.com/Dumoedss/omnicross#readme",
File without changes
@@ -1 +0,0 @@
1
- "use strict";
File without changes
File without changes