@jeffusion/bungee-core 5.3.2 → 5.4.1
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.
- package/dist/main.js +86 -22
- package/dist/plugins/ai-transformer/index.js.map +2 -2
- package/dist/plugins/anthropic-request-sanitizer/index.js.map +2 -2
- package/dist/plugins/anthropic-tool-name-transformer/index.js.map +2 -2
- package/dist/plugins/chatgpt-oauth/index.js.map +2 -2
- package/dist/plugins/deepseek-reasoning-fix/index.js.map +2 -2
- package/dist/plugins/model-mapping/index.js.map +2 -2
- package/dist/plugins/openai-messages-to-chat/index.js.map +2 -2
- package/dist/plugins/signature-repair/index.js.map +2 -2
- package/dist/plugins/token-stats/control.js +29 -10
- package/dist/plugins/token-stats/control.js.map +6 -5
- package/dist/plugins/token-stats/index.js +12 -4
- package/dist/plugins/token-stats/index.js.map +6 -5
- package/dist/plugins/token-stats/manifest.json +24 -4
- package/dist/plugins/token-stats/ui/TokenStatsMetric.svelte +31 -9
- package/dist/plugins/token-stats/ui/TokenStatsPage.svelte +29 -41
- package/dist/plugins/token-stats/ui/UsageTimeChart.svelte +132 -70
- package/dist/plugins/token-stats/ui/labels.ts +22 -4
- package/dist/plugins/token-stats/ui/overview-trends.ts +33 -0
- package/dist/plugins/token-stats/ui/stats-resource.ts +5 -2
- package/dist/plugins/token-stats/ui/stats.ts +3 -2
- package/package.json +2 -2
|
@@ -1681,6 +1681,11 @@ var PROVIDER_ADAPTERS = {
|
|
|
1681
1681
|
anthropic: createAnthropicAdapter(),
|
|
1682
1682
|
gemini: createGeminiAdapter()
|
|
1683
1683
|
};
|
|
1684
|
+
// packages/core/src/token-stats-window.ts
|
|
1685
|
+
var HOUR = 3600000;
|
|
1686
|
+
var TOKEN_STATS_RETENTION_MS = 31 * 24 * HOUR;
|
|
1687
|
+
var TOKEN_STATS_RANGES = ["1h", "12h", "24h", "1d", "7d", "30d", "day", "week", "month"];
|
|
1688
|
+
|
|
1684
1689
|
// plugins/token-stats/server/repository.ts
|
|
1685
1690
|
class TokenStatsRepositoryError extends Error {
|
|
1686
1691
|
constructor(message) {
|
|
@@ -1796,23 +1801,26 @@ class TokenStatsRepository {
|
|
|
1796
1801
|
scheduleDrain();
|
|
1797
1802
|
return true;
|
|
1798
1803
|
}
|
|
1799
|
-
async query(range, groupBy, asOfMs = Date.now()) {
|
|
1800
|
-
if (range
|
|
1804
|
+
async query(range, groupBy, asOfMs = Date.now(), timeZone) {
|
|
1805
|
+
if (!TOKEN_STATS_RANGES.includes(range))
|
|
1801
1806
|
throw new TokenStatsRepositoryError("invalid token-stats range");
|
|
1802
1807
|
if (groupBy !== "model" && groupBy !== "time") {
|
|
1803
1808
|
throw new TokenStatsRepositoryError("invalid token-stats groupBy");
|
|
1804
1809
|
}
|
|
1805
1810
|
if (!Number.isSafeInteger(asOfMs) || asOfMs < 0)
|
|
1806
1811
|
throw new TokenStatsRepositoryError("invalid token-stats asOfMs");
|
|
1807
|
-
const snapshot = await this.metering.queryWindowSnapshot({ asOfMs, range, groupBy });
|
|
1812
|
+
const snapshot = await this.metering.queryWindowSnapshot({ asOfMs, range, groupBy, timeZone });
|
|
1808
1813
|
const total = metricsToDto(snapshot.all);
|
|
1809
1814
|
const { inputTokens, outputTokens, ...summary } = total;
|
|
1810
1815
|
return {
|
|
1811
1816
|
groupBy,
|
|
1817
|
+
asOfMs,
|
|
1812
1818
|
...summary,
|
|
1813
1819
|
totalInputTokens: inputTokens,
|
|
1814
1820
|
totalOutputTokens: outputTokens,
|
|
1815
1821
|
...snapshot.bucketMs === undefined ? {} : { bucketMs: snapshot.bucketMs },
|
|
1822
|
+
...snapshot.bucketStarts === undefined ? {} : { bucketStarts: snapshot.bucketStarts },
|
|
1823
|
+
...snapshot.bucketEndMs === undefined ? {} : { bucketEndMs: snapshot.bucketEndMs },
|
|
1816
1824
|
data: snapshot.data.map((row) => ({
|
|
1817
1825
|
dimension: row.dimension,
|
|
1818
1826
|
...row.bucketStartMs === undefined ? {} : { bucketStartMs: row.bucketStartMs },
|
|
@@ -2115,7 +2123,7 @@ class PriceCatalogManager {
|
|
|
2115
2123
|
|
|
2116
2124
|
// plugins/token-stats/server/control.ts
|
|
2117
2125
|
var MAX_RESPONSE_BYTES = 256 * 1024;
|
|
2118
|
-
var
|
|
2126
|
+
var MAX_PAGE_STATS_RESPONSE_BYTES = 4 * 1024 * 1024;
|
|
2119
2127
|
var VALID_GROUP_BY = ["model", "time"];
|
|
2120
2128
|
|
|
2121
2129
|
class ControlError extends Error {
|
|
@@ -2126,9 +2134,9 @@ class ControlError extends Error {
|
|
|
2126
2134
|
this.name = "TokenStatsControlError";
|
|
2127
2135
|
}
|
|
2128
2136
|
}
|
|
2129
|
-
function jsonResponse(value, status = 200) {
|
|
2137
|
+
function jsonResponse(value, status = 200, maxBytes = MAX_RESPONSE_BYTES) {
|
|
2130
2138
|
const body = JSON.stringify(value);
|
|
2131
|
-
if (new TextEncoder().encode(body).byteLength >
|
|
2139
|
+
if (new TextEncoder().encode(body).byteLength > maxBytes) {
|
|
2132
2140
|
return new Response(JSON.stringify({ error: "response_limit" }), {
|
|
2133
2141
|
status: 500,
|
|
2134
2142
|
headers: { "content-type": "application/json; charset=utf-8" }
|
|
@@ -2267,14 +2275,25 @@ class TokenStatsControl {
|
|
|
2267
2275
|
const url = new URL(context.request.url);
|
|
2268
2276
|
const rawRange = url.searchParams.get("range");
|
|
2269
2277
|
const rawGroupBy = url.searchParams.get("groupBy");
|
|
2270
|
-
|
|
2278
|
+
const timeZone = url.searchParams.get("timeZone") ?? undefined;
|
|
2279
|
+
if (url.searchParams.getAll("range").length > 1 || url.searchParams.getAll("groupBy").length > 1 || url.searchParams.getAll("timeZone").length > 1 || rawRange !== null && !TOKEN_STATS_RANGES.includes(rawRange) || rawGroupBy !== null && !VALID_GROUP_BY.includes(rawGroupBy)) {
|
|
2271
2280
|
throw new ControlError("invalid_input");
|
|
2272
2281
|
}
|
|
2282
|
+
if (timeZone !== undefined) {
|
|
2283
|
+
try {
|
|
2284
|
+
if (!timeZone || timeZone.length > 100)
|
|
2285
|
+
throw new Error("invalid time zone");
|
|
2286
|
+
new Intl.DateTimeFormat("en-US", { timeZone });
|
|
2287
|
+
} catch {
|
|
2288
|
+
throw new ControlError("invalid_input");
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2273
2291
|
const range = rawRange ?? "24h";
|
|
2274
2292
|
const groupBy = rawGroupBy ?? "model";
|
|
2275
|
-
const payload = await abortable(this.repository.query(range, groupBy), context.requestSignal, context.signal);
|
|
2293
|
+
const payload = await abortable(this.repository.query(range, groupBy, Date.now(), timeZone), context.requestSignal, context.signal);
|
|
2276
2294
|
this.assertAlive(context.requestSignal);
|
|
2277
|
-
|
|
2295
|
+
const maxBytes = ["1h", "12h", "24h"].includes(range) ? MAX_RESPONSE_BYTES : MAX_PAGE_STATS_RESPONSE_BYTES;
|
|
2296
|
+
return jsonResponse(payload, 200, maxBytes);
|
|
2278
2297
|
})
|
|
2279
2298
|
}, {
|
|
2280
2299
|
path: "/pricing",
|
|
@@ -2330,4 +2349,4 @@ export {
|
|
|
2330
2349
|
control_default as default
|
|
2331
2350
|
};
|
|
2332
2351
|
|
|
2333
|
-
//# debugId=
|
|
2352
|
+
//# debugId=CC440B77E27EEC3464756E2164756E21
|