From dfc386aac270ccd369d2de9517540dc4506c0d7f Mon Sep 17 00:00:00 2001 From: joshhatfield Date: Thu, 7 May 2026 17:36:24 +1000 Subject: [PATCH] Fix always_include_stream_usage missing in UI --- litellm/proxy/_types.py | 4 ++ .../UISettings/UISettings.test.tsx | 34 ++++++++++ .../AdminSettings/UISettings/UISettings.tsx | 63 ++++++++++++++----- 3 files changed, 86 insertions(+), 15 deletions(-) diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index 2c976479798..156d0ffb6cf 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -2452,6 +2452,10 @@ class ConfigGeneralSettings(LiteLLMPydanticObjectBase): None, description="If True, forwards client headers (e.g. Authorization) to the LLM API. Required for Claude Code with Max subscription.", ) + always_include_stream_usage: Optional[bool] = Field( + None, + description="If True, automatically includes usage information in all streaming responses.", + ) mcp_required_fields: Optional[List[str]] = Field( None, description="List of MCP server fields that must be filled in for a submission to pass standards checks (e.g. ['description', 'source_url', 'alias']).", diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx index 639564bbd35..64b25f4dbc4 100644 --- a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx +++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.test.tsx @@ -41,12 +41,16 @@ const buildSettingsResponse = (overrides?: Partial>) => require_auth_for_public_ai_hub: { description: "Require authentication for public AI Hub", }, + always_include_stream_usage: { + description: "Always include stream usage", + }, }, }, values: { disable_model_add_for_internal_users: false, disable_team_admin_delete_team_user: false, require_auth_for_public_ai_hub: false, + always_include_stream_usage: false, }, }, isLoading: false, @@ -74,6 +78,7 @@ describe("UISettings", () => { expect(screen.getByRole("switch", { name: "Disable model add for internal users" })).toBeInTheDocument(); expect(screen.getByRole("switch", { name: "Disable team admin delete team user" })).toBeInTheDocument(); expect(screen.getByRole("switch", { name: "Require authentication for public AI Hub" })).toBeInTheDocument(); + expect(screen.getByRole("switch", { name: "Always include stream usage" })).toBeInTheDocument(); }); it("should toggle setting and call update", () => { @@ -162,4 +167,33 @@ describe("UISettings", () => { ); expect(NotificationManager.success).toHaveBeenCalledWith("UI settings updated successfully"); }); + + it("should toggle always include stream usage setting and call update", () => { + const mutateMock = vi.fn((_settings, options) => { + options?.onSuccess?.(); + }); + + mockUseUpdateUISettings.mockReturnValue({ + mutate: mutateMock, + isPending: false, + error: null, + }); + + render(); + + const toggle = screen.getByRole("switch", { name: "Always include stream usage" }); + + act(() => { + fireEvent.click(toggle); + }); + + expect(mutateMock).toHaveBeenCalledWith( + { always_include_stream_usage: true }, + expect.objectContaining({ + onSuccess: expect.any(Function), + onError: expect.any(Function), + }), + ); + expect(NotificationManager.success).toHaveBeenCalledWith("UI settings updated successfully"); + }); }); diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx index 51b9895e9c5..e013e9bc71c 100644 --- a/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx +++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/UISettings/UISettings.tsx @@ -17,6 +17,7 @@ export default function UISettings() { const disableTeamAdminDeleteProperty = schema?.properties?.disable_team_admin_delete_team_user; const requireAuthForPublicAIHubProperty = schema?.properties?.require_auth_for_public_ai_hub; const forwardClientHeadersProperty = schema?.properties?.forward_client_headers_to_llm_api; + const alwaysIncludeStreamUsageProperty = schema?.properties?.always_include_stream_usage; const forwardLLMProviderAuthHeadersProperty = schema?.properties?.forward_llm_provider_auth_headers; const enableProjectsUIProperty = schema?.properties?.enable_projects_ui; @@ -28,6 +29,7 @@ export default function UISettings() { const scopeUserSearchProperty = schema?.properties?.scope_user_search_to_org; const disableCustomApiKeysProperty = schema?.properties?.disable_custom_api_keys; const values = data?.values ?? {}; + const isAlwaysIncludeStreamUsage = Boolean(values.always_include_stream_usage); const isDisabledForInternalUsers = Boolean(values.disable_model_add_for_internal_users); const isDisabledTeamAdminDeleteTeamUser = Boolean(values.disable_team_admin_delete_team_user); const isAgentsDisabled = Boolean(values.disable_agents_for_internal_users); @@ -86,6 +88,20 @@ export default function UISettings() { ); }; + const handleToggleAlwaysIncludeStreamUsage = (checked: boolean) => { + updateSettings( + { always_include_stream_usage: checked }, + { + onSuccess: () => { + NotificationManager.success("UI settings updated successfully"); + }, + onError: (error) => { + NotificationManager.fromBackend(error); + }, + }, + ); + }; + const handleToggleForwardLLMProviderAuthHeaders = (checked: boolean) => { updateSettings( { forward_llm_provider_auth_headers: checked }, @@ -283,22 +299,39 @@ export default function UISettings() { - - - - Forward client headers to LLM API - - {forwardClientHeadersProperty?.description ?? - "Forwards client headers (Authorization, anthropic-beta, and x-* custom headers) to the upstream LLM. Enable for Claude Code with a Max subscription (forwards the OAuth token) or to pass custom/tracing headers through to the provider. Independent of the BYOK toggle — enable only the one(s) you need."} - + + + + Forward client headers to LLM API + + {forwardClientHeadersProperty?.description ?? + "Forwards client headers (Authorization, anthropic-beta, and x-* custom headers) to the upstream LLM. Enable for Claude Code with a Max subscription (forwards the OAuth token) or to pass custom/tracing headers through to the provider. Independent of the BYOK toggle — enable only the one(s) you need."} + + + + + + + + Always include stream usage + + {alwaysIncludeStreamUsageProperty?.description ?? + "If enabled, usage is included in stream responses."} + + -