@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.
@@ -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 !== "1h" && range !== "12h" && range !== "24h")
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 VALID_RANGES = ["1h", "12h", "24h"];
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 > MAX_RESPONSE_BYTES) {
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
- if (url.searchParams.getAll("range").length > 1 || url.searchParams.getAll("groupBy").length > 1 || rawRange !== null && !VALID_RANGES.includes(rawRange) || rawGroupBy !== null && !VALID_GROUP_BY.includes(rawGroupBy)) {
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
- return jsonResponse(payload);
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=C36CBFA86B22DB2D64756E2164756E21
2352
+ //# debugId=CC440B77E27EEC3464756E2164756E21