diff --git a/litellm/proxy/_lazy_openapi_snapshot.json b/litellm/proxy/_lazy_openapi_snapshot.json index 6be003927d6..972c831073f 100644 --- a/litellm/proxy/_lazy_openapi_snapshot.json +++ b/litellm/proxy/_lazy_openapi_snapshot.json @@ -27417,7 +27417,7 @@ }, "/v1/tool/spend": { "get": { - "description": "Spend attributed to each tool over a date range, for the Cost Optimization dashboard.\n\nJoins ``LiteLLM_SpendLogToolIndex`` (which tool names ran on which request) to\n``LiteLLM_SpendLogs`` (what the request cost). A request that used multiple tools\ncounts its full spend toward each of those tools, so per-tool numbers are\nattributions. ``total_spend`` is the deduplicated spend of every request that\ncalled at least one tool in the window, so it never double counts.\n\nThe window is capped at the most recent 30 days ending at ``end_date``: a wider\nrequested range is clamped, and the response's ``start_date`` reflects the\neffective window actually served.", + "description": "Spend attributed to each tool over a date range, for the Cost Optimization dashboard.\n\nJoins ``LiteLLM_SpendLogToolIndex`` (which tool names ran on which request) to\n``LiteLLM_SpendLogs`` (what the request cost). A request that used multiple tools\ncounts its full spend toward each of those tools, so per-tool numbers are\nattributions. ``total_spend`` is the deduplicated spend of every request that\ncalled at least one tool in the window, so it never double counts.\n\n``start_date`` is clamped to at most 30 days before ``end_date`` (serving up to\n31 calendar dates inclusive, the same width as the endpoint's default window):\na wider requested range is clamped, and the response's ``start_date`` reflects\nthe effective window actually served.", "operationId": "get_tool_spend_v1_tool_spend_get", "parameters": [ { diff --git a/litellm/proxy/management_endpoints/tool_management_endpoints.py b/litellm/proxy/management_endpoints/tool_management_endpoints.py index 6d9748332bc..3f528c8c489 100644 --- a/litellm/proxy/management_endpoints/tool_management_endpoints.py +++ b/litellm/proxy/management_endpoints/tool_management_endpoints.py @@ -211,9 +211,10 @@ async def get_tool_spend( attributions. ``total_spend`` is the deduplicated spend of every request that called at least one tool in the window, so it never double counts. - The window is capped at the most recent 30 days ending at ``end_date``: a wider - requested range is clamped, and the response's ``start_date`` reflects the - effective window actually served. + ``start_date`` is clamped to at most 30 days before ``end_date`` (serving up to + 31 calendar dates inclusive, the same width as the endpoint's default window): + a wider requested range is clamped, and the response's ``start_date`` reflects + the effective window actually served. """ from litellm.proxy.proxy_server import prisma_client diff --git a/tests/test_litellm/proxy/management_endpoints/test_tool_management_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_tool_management_endpoints.py index f420eed6a33..150499dfbf1 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_tool_management_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_tool_management_endpoints.py @@ -203,7 +203,10 @@ class TestToolManagementEndpoints: assert tuple(call.args[1:]) == expected_binds assert resp.json()["end_date"] == "2026-07-02" - def test_tool_spend_window_clamped_to_most_recent_30_days(self): + def test_tool_spend_start_clamped_to_30_days_before_end(self): + # Clamped floor is end_date minus 30 days, serving up to 31 calendar dates + # inclusive: deliberately the same width as the endpoint's default window, + # so the dashboard's default range never triggers the clamp. prisma = MagicMock() prisma.db.query_raw = AsyncMock(return_value=[]) with patch("litellm.proxy.proxy_server.prisma_client", prisma): diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/UsageTab.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/UsageTab.test.tsx index 27c79c8a9ce..ab1cd146adc 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/UsageTab.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/UsageTab.test.tsx @@ -148,7 +148,7 @@ describe("UsageTab", () => { }; const { findByText } = renderWith([day("2026-07-12", {})], toolSpend); - expect(await findByText(/most recent 30 days of the selected range/)).toBeInTheDocument(); + expect(await findByText(/capped at 30 days before the end of the selected range/)).toBeInTheDocument(); }); it("shows no cap note when the served window matches the request", async () => { @@ -162,6 +162,6 @@ describe("UsageTab", () => { const { findAllByTestId, queryByText } = renderWith([day("2026-07-12", {})], toolSpend); await findAllByTestId("bar-chart"); - expect(queryByText(/most recent 30 days of the selected range/)).not.toBeInTheDocument(); + expect(queryByText(/capped at 30 days before the end of the selected range/)).not.toBeInTheDocument(); }); }); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/UsageTab.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/UsageTab.tsx index a069c80a201..6e2da4456d3 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/UsageTab.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/UsageTab.tsx @@ -214,7 +214,8 @@ const UsageTab: React.FC = ({ accessToken, activity }) => {

{toolSpendWindowClamped && (

- Tool spend is limited to the most recent 30 days of the selected range (since {toolSpend?.start_date}). + Tool spend is capped at 30 days before the end of the selected range; showing spend since{" "} + {toolSpend?.start_date}.

)} diff --git a/ui/litellm-dashboard/src/lib/http/schema.d.ts b/ui/litellm-dashboard/src/lib/http/schema.d.ts index e420da55e77..c1141db7852 100644 --- a/ui/litellm-dashboard/src/lib/http/schema.d.ts +++ b/ui/litellm-dashboard/src/lib/http/schema.d.ts @@ -17977,9 +17977,10 @@ export interface paths { * attributions. ``total_spend`` is the deduplicated spend of every request that * called at least one tool in the window, so it never double counts. * - * The window is capped at the most recent 30 days ending at ``end_date``: a wider - * requested range is clamped, and the response's ``start_date`` reflects the - * effective window actually served. + * ``start_date`` is clamped to at most 30 days before ``end_date`` (serving up to + * 31 calendar dates inclusive, the same width as the endpoint's default window): + * a wider requested range is clamped, and the response's ``start_date`` reflects + * the effective window actually served. */ get: operations["get_tool_spend_v1_tool_spend_get"]; put?: never;