+
Spend is bucketed by UTC day
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/autoRouterBenchmarks.test.ts b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/autoRouterBenchmarks.test.ts
index 201a71ae4be..57c059b5524 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/autoRouterBenchmarks.test.ts
+++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/autoRouterBenchmarks.test.ts
@@ -131,12 +131,25 @@ describe("bucketRows", () => {
});
describe("expiredMissShare", () => {
- it("recomputes the expired share from the miss counts", () => {
- expect(expiredMissShare(cache())).toBeCloseTo((100 * 19) / 70);
+ it("computes the expired share over every measured turn, not just return-to-tier misses", () => {
+ expect(expiredMissShare(cache())).toBeCloseTo((100 * 19) / 818);
});
- it("is absent when every return turn hit", () => {
- expect(expiredMissShare(cache({ return_to_tier: { turns: 10, hits: 10, hit_rate_pct: 100 } }))).toBeNull();
+ it("is zero, not absent, when every return turn hit", () => {
+ expect(
+ expiredMissShare(cache({ return_to_tier: { turns: 10, hits: 10, hit_rate_pct: 100 }, return_misses_expired: 0 })),
+ ).toBe(0);
+ });
+
+ it("is absent only when no turns were measured at all", () => {
+ const empty = { turns: 0, hits: 0, hit_rate_pct: 0 };
+ const nothingMeasured = {
+ same_model: empty,
+ first_visit: empty,
+ return_to_tier: empty,
+ return_misses_expired: 0,
+ };
+ expect(expiredMissShare(cache(nothingMeasured))).toBeNull();
});
});
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/autoRouterBenchmarks.ts b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/autoRouterBenchmarks.ts
index 8b6a4fa4105..00793548278 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/autoRouterBenchmarks.ts
+++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/autoRouterBenchmarks.ts
@@ -91,9 +91,9 @@ export const bucketRows = (cache: AutoRouterCacheStats): BucketRow[] => {
};
export const expiredMissShare = (cache: AutoRouterCacheStats): number | null => {
- const misses = cache.return_to_tier.turns - cache.return_to_tier.hits;
- if (misses <= 0) return null;
- return (100 * cache.return_misses_expired) / misses;
+ const total = bucketTurnsTotal(cache);
+ if (total <= 0) return null;
+ return (100 * cache.return_misses_expired) / total;
};
export const pctLabel = (value: number, digits: number = 1): string => `${value.toFixed(digits)}%`;
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/useDailyActivityRange.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/useDailyActivityRange.test.tsx
index 9fd27d80c37..e26a3629e8c 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/useDailyActivityRange.test.tsx
+++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/useDailyActivityRange.test.tsx
@@ -22,13 +22,13 @@ describe("useDailyActivityRange", () => {
it("queries every user's activity for an admin", () => {
renderHook(() => useDailyActivityRange("test-token", "u1", "proxy_admin"));
- expect(argsOfLastCall()).toEqual(["test-token", expect.any(Date), expect.any(Date), null]);
+ expect(argsOfLastCall()).toEqual(["test-token", expect.any(Date), expect.any(Date), null, true]);
});
it("scopes the query to the caller for a non-admin", () => {
renderHook(() => useDailyActivityRange("test-token", "u1", "internal_user"));
- expect(argsOfLastCall()).toEqual(["test-token", expect.any(Date), expect.any(Date), "u1"]);
+ expect(argsOfLastCall()).toEqual(["test-token", expect.any(Date), expect.any(Date), "u1", true]);
});
it("stays disabled until an access token is available", () => {
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/useDailyActivityRange.ts b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/useDailyActivityRange.ts
index 1c3f706726e..3a2a38c5955 100644
--- a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/useDailyActivityRange.ts
+++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/useDailyActivityRange.ts
@@ -35,7 +35,7 @@ export const useDailyActivityRange = (
const { data, loading, isFetchingMore } = usePaginatedDailyActivity({
fetchFn: userDailyActivityCall,
- args: [accessToken, startTime, endTime, effectiveUserId],
+ args: [accessToken, startTime, endTime, effectiveUserId, true],
enabled: !!accessToken && !!startTime && !!endTime,
});
diff --git a/ui/litellm-dashboard/src/components/networking.tsx b/ui/litellm-dashboard/src/components/networking.tsx
index 03106528a80..17a5ca37990 100644
--- a/ui/litellm-dashboard/src/components/networking.tsx
+++ b/ui/litellm-dashboard/src/components/networking.tsx
@@ -1388,6 +1388,7 @@ export const userDailyActivityCall = async (
endTime: Date,
page: number = 1,
userId: string | null = null,
+ includeCurrentUtcDay: boolean = false,
) => {
/**
* Get daily user activity on proxy
@@ -1400,6 +1401,7 @@ export const userDailyActivityCall = async (
page,
extraQueryParams: {
user_id: userId,
+ include_current_utc_day: includeCurrentUtcDay ? "true" : undefined,
},
});
};
diff --git a/ui/litellm-dashboard/src/lib/http/schema.d.ts b/ui/litellm-dashboard/src/lib/http/schema.d.ts
index 65434407f74..752572f9863 100644
--- a/ui/litellm-dashboard/src/lib/http/schema.d.ts
+++ b/ui/litellm-dashboard/src/lib/http/schema.d.ts
@@ -26716,6 +26716,8 @@ export interface components {
auto_router_max_input_chars?: number | null;
/** Aws Access Key Id */
aws_access_key_id?: string | null;
+ /** Aws Batch Role Arn */
+ aws_batch_role_arn?: string | null;
/** Aws Bedrock Project Id */
aws_bedrock_project_id?: string | null;
/** Aws Bedrock Runtime Endpoint */
@@ -26895,6 +26897,10 @@ export interface components {
output_cost_per_pixel?: number | null;
/** Output Cost Per Reasoning Token */
output_cost_per_reasoning_token?: number | null;
+ /** Output Cost Per Reasoning Token Flex */
+ output_cost_per_reasoning_token_flex?: number | null;
+ /** Output Cost Per Reasoning Token Priority */
+ output_cost_per_reasoning_token_priority?: number | null;
/** Output Cost Per Second */
output_cost_per_second?: number | null;
/** Output Cost Per Second 1080P */
@@ -26945,6 +26951,8 @@ export interface components {
s3_bucket_name?: string | null;
/** S3 Encryption Key Id */
s3_encryption_key_id?: string | null;
+ /** S3 Region Name */
+ s3_region_name?: string | null;
/** Search Context Cost Per Query */
search_context_cost_per_query?: {
[key: string]: unknown;
@@ -31560,6 +31568,26 @@ export interface components {
/** Review Notes */
review_notes?: string | null;
};
+ /**
+ * ReminderMarkerPair
+ * @description One open/close delimiter pair a harness wraps injected context in.
+ *
+ * Normalizing here rather than at the scan is what makes matching case-insensitive: markers reach
+ * the scan already lowered, so it lowercases only the haystack and never the needles. Stripping
+ * keeps YAML indentation whitespace from becoming part of the delimiter.
+ */
+ ReminderMarkerPair: {
+ /**
+ * Close
+ * @description Closing delimiter, e.g. ''
+ */
+ close: string;
+ /**
+ * Open
+ * @description Opening delimiter, e.g. '
'
+ */
+ open: string;
+ };
/**
* RequestComplexityRouterConfig
* @description The part of a complexity-router config a request can carry.
@@ -31672,12 +31700,9 @@ export interface components {
reasoning_keywords?: string[] | null;
/**
* Reminder Markers
- * @description Override the (open, close) marker pair used to recognize and strip harness-injected reminder blocks before classification. Defaults to Claude Code's convention, ('', ''), when unset. Matching is case-insensitive.
+ * @description Override the delimiter pairs used to recognize and strip harness-injected reminder blocks before classification. A harness that wraps injected context differently per agent type (main, subagent, cron) lists every pair it emits. Replaces, rather than adds to, the built-in default of ('', ''), so a harness that also emits that pair lists it too. Matching is case-insensitive.
*/
- reminder_markers?: [
- string,
- string
- ] | null;
+ reminder_markers?: components["schemas"]["ReminderMarkerPair"][] | null;
/**
* Return Raw Model Name
* @description Return the resolved raw model name in the response model field instead of the client-requested complexity-router alias
@@ -35295,6 +35320,8 @@ export interface components {
auto_router_max_input_chars?: number | null;
/** Aws Access Key Id */
aws_access_key_id?: string | null;
+ /** Aws Batch Role Arn */
+ aws_batch_role_arn?: string | null;
/** Aws Bedrock Project Id */
aws_bedrock_project_id?: string | null;
/** Aws Bedrock Runtime Endpoint */
@@ -35474,6 +35501,10 @@ export interface components {
output_cost_per_pixel?: number | null;
/** Output Cost Per Reasoning Token */
output_cost_per_reasoning_token?: number | null;
+ /** Output Cost Per Reasoning Token Flex */
+ output_cost_per_reasoning_token_flex?: number | null;
+ /** Output Cost Per Reasoning Token Priority */
+ output_cost_per_reasoning_token_priority?: number | null;
/** Output Cost Per Second */
output_cost_per_second?: number | null;
/** Output Cost Per Second 1080P */
@@ -35524,6 +35555,8 @@ export interface components {
s3_bucket_name?: string | null;
/** S3 Encryption Key Id */
s3_encryption_key_id?: string | null;
+ /** S3 Region Name */
+ s3_region_name?: string | null;
/** Search Context Cost Per Query */
search_context_cost_per_query?: {
[key: string]: unknown;
@@ -53858,6 +53891,8 @@ export interface operations {
page_size?: number;
/** @description Timezone offset in minutes from UTC (e.g., 480 for PST). Matches JavaScript's Date.getTimezoneOffset() convention. */
timezone?: number | null;
+ /** @description When the range ends on the caller's current local day, extend it to today's UTC bucket so spend written after the caller's local midnight (in UTC terms) is included. Requires the timezone parameter. Historical ranges are never extended. */
+ include_current_utc_day?: boolean;
};
header?: never;
path?: never;