Commit graph

4746 commits

Author SHA1 Message Date
Ryan Crabbe
f27bf8e711
fix(ui): pre-select backend default for boolean guardrail provider fields
Boolean fields in the auto-generated guardrail provider form (e.g. Noma
`use_v2`) rendered as empty Selects because the Form.Item only populated
`initialValue` for percentage fields, and the `defaultValue` passed to the
Select child was silently dropped by antd's controlled-component wrapper.
Users could not tell what the backend default was, and the visual ambiguity
made flags like `use_v2` look inoperative even though the save path worked.

Unify `initialValue` to fall back through `fieldValue → field.default_value →
(percentage ? 0.5 : undefined)`, and switch Select.Option values from
"true"/"false" strings to real booleans so the backend default flows through
without stringification.
2026-04-15 09:52:23 -07:00
Ryan Crabbe
17568e81f2
chore(ui): use antd Typography in GuardrailTestPlayground
- Replace plain text/heading tags with Typography.Text, Title, Paragraph
- Document Typography preference in CLAUDE.md UI guidelines
2026-04-15 08:45:11 -07:00
Sameer Kankute
277be4c50e
Add input + output tokens for anthropic message type 2026-04-15 21:08:34 +05:30
Yuneng Jiang
6426bc41f5
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_yj_apr14 2026-04-14 22:40:04 -07:00
Ryan Crabbe
b28b82c105
chore(ui): migrate GuardrailTestPlayground off @tremor/react to antd
Part of the ongoing migration away from @tremor/react per CLAUDE.md.
Swaps tremor Card/Title/Text/TextInput for antd Card/Input and plain
h2/h3/span/p tags with Tailwind. Drops the redundant Checkbox avatar in
the sidebar list since row clicks already toggle selection and the
blue-border + bg-blue-50 styling already signals selected state.
2026-04-14 21:46:13 -07:00
Ishaan Jaffer
e0a988e39a
feat(ui/log-details): pass rawInputTokens, cacheReadTokens, cacheCreationTokens to CostBreakdownViewer from SpendLogs 2026-04-14 18:29:12 -07:00
Ishaan Jaffer
0148effd6e
feat(ui/cost-breakdown): show separate Input / Cache Read / Cache Write line items in cost breakdown drawer 2026-04-14 18:29:12 -07:00
Ishaan Jaffer
6b1dc1156e
fix(ui/usage): subtract cache tokens from Input Tokens summary card to avoid double-counting 2026-04-14 18:29:12 -07:00
ryan-crabbe-berri
6d2b7b76ad
Merge pull request #25721 from BerriAI/litellm_fix-invite-user-default-role
fix: default invite user modal global role to least-privilege
2026-04-14 16:34:04 -07:00
Ryan Crabbe
a428ae7599
fix: default invite user modal global role to least-privilege
Pre-select "Internal User Viewer" in the Global Proxy Role dropdown
on both the standalone and embedded Invite User forms so admins don't
have to remember to pick a role, and the default lands on the least
privileged option rather than silently posting an undefined role.
2026-04-14 15:45:35 -07:00
Ryan Crabbe
bdaaa5c187
test(ui): add getCookie to cookieUtils mock in user_dashboard test
user_dashboard.tsx imports getCookie from @/utils/cookieUtils, but the
vi.mock factory in user_dashboard.test.tsx only exports clearTokenCookies.
Vitest throws `No "getCookie" export is defined on the "@/utils/cookieUtils"
mock`, breaking all three beforeunload-listener tests.

Add getCookie to the mock factory so it matches the current imports.
2026-04-14 15:18:10 -07:00
ryan-crabbe-berri
43efe76f17
Merge pull request #25716 from BerriAI/litellm_fix-logs-team-filter-state-bleed
fix: isolate logs team filter dropdown from root teams state bleed
2026-04-14 14:44:37 -07:00
ryan-crabbe-berri
ec4ce1cc4a
Merge pull request #25700 from BerriAI/litellm_fix-guardrail-bool-select-rendering
fix(ui): pre-select backend default for boolean guardrail provider fields
2026-04-14 14:31:28 -07:00
Ryan Crabbe
1beb8037d1
fix: isolate logs team filter dropdown from root teams state bleed
The Logs view's Team ID filter dropdown was reading `allTeams` from the
root `teams` state in page.tsx, which the Teams page search overwrites
with its filtered subset. Applying a team search on the Teams page made
filtered-out teams disappear from the Logs filter dropdown.

Swap the Team ID filter to use the existing `TeamDropdown` component via
a small `FilterTeamDropdown` wrapper that adapts it to the filter slot's
`FilterOptionCustomComponentProps` contract. The dropdown now drives its
own `useInfiniteTeams` query against `/v2/team/list` with server-side
search and an isolated react-query cache, unreachable from root state.

Rename the now-unused `hookAllTeams` destructure to `allTeams` so the
`KeyInfoView` passthrough receives the hook's unpolluted fetch instead
of the polluted prop, and drop the dead `allTeams` prop from
`SpendLogsTable` and both of its call sites.
2026-04-14 14:28:53 -07:00
Ryan Crabbe
6da4e0b901
fix(ui): pre-select backend default for boolean guardrail provider fields
Boolean fields in the auto-generated guardrail provider form (e.g. Noma
`use_v2`) rendered as empty Selects because the Form.Item only populated
`initialValue` for percentage fields, and the `defaultValue` passed to the
Select child was silently dropped by antd's controlled-component wrapper.
Users could not tell what the backend default was, and the visual ambiguity
made flags like `use_v2` look inoperative even though the save path worked.

Unify `initialValue` to fall back through `fieldValue → field.default_value →
(percentage ? 0.5 : undefined)`, and switch Select.Option values from
"true"/"false" strings to real booleans so the backend default flows through
without stringification.
2026-04-14 10:13:58 -07:00
Lucas Song
9c869732a5 fix(ui): remove unused useMutation import and add React import to test 2026-04-14 10:08:18 -07:00
Lucas Song
977245c30e fix(ui): rename test file to tsx and remove unused useMutation import 2026-04-14 10:08:07 -07:00
Lucas Song
ef774a1991 Merge remote-tracking branch 'origin/main' into fix-ui-policy-attachment-delete 2026-04-14 10:02:23 -07:00
Lucas Song
53828dda76 refactor: migrate policy attachment deletion to useMutation hook with tests 2026-04-14 09:54:41 -07:00
Sameer Kankute
972e42c7fd
Merge branch 'main' into litellm_oss_staging_04_04_2026 2026-04-14 20:23:06 +05:30
Yuneng Jiang
d3a1f63af2
[Refactor] Proxy: move projects management to enterprise package
Remove the /project/* management endpoints and the enable_projects_ui
admin-settings flag from the OSS litellm package. Project endpoints now
live under litellm_enterprise and are wired through the existing
enterprise router; OSS builds return 404 for every /project/* route.

The enable_projects_ui UI flag is registered back onto UISettings via a
small extension registry when the enterprise package is imported, so the
admin toggle and downstream key/sidebar gating continue to work in
enterprise builds. On OSS, explicit PATCH attempts with the flag return
403 with a clear enterprise-only message instead of being silently
dropped.

Pydantic request/response types (NewProjectRequest, UpdateProjectRequest,
DeleteProjectRequest, NewProjectResponse) stay in litellm/proxy/_types.py
because management_endpoints/common_utils.py and pydantic-shape tests
import them. LiteLLM_ProjectTable and all FK columns in schema.prisma
are unchanged.
2026-04-13 21:41:12 -07:00
Yuneng Jiang
9b74ff3ef7
remove unnecessary cleanup helper
The database is freshly seeded on every test run via seed.sql,
so per-test cleanup is not needed.
2026-04-13 17:29:49 -07:00
Yuneng Jiang
cce7163348
fix CI: replace data-testid selectors with text/role-based selectors
The data-testid attributes added to React components are not present
in the CI-built UI output. Switch to using getByRole and getByText
selectors which work with the rendered DOM regardless of build cache.
2026-04-13 17:29:49 -07:00
Yuneng Jiang
5e07c1cbc9
address greptile review feedback (greploop iteration 1)
Add cleanup helper to delete models created during tests, preventing
stale data accumulation across repeated test runs.
2026-04-13 17:29:49 -07:00
Yuneng Jiang
4f364a8138
[Test] UI - Models: Add E2E tests for Add Model flow
Add E2E tests covering:
- Test connection with bad credentials shows failure modal
- Adding a specific model and verifying it appears in All Models table
- Adding a wildcard route and verifying it appears in All Models table
- Verifying model dropdown shows provider-specific models (existing test updated)

Added data-testid attributes to UI components to support stable test selectors.

Tests verified passing 3/3 consecutive runs with zero flakiness.
2026-04-13 17:29:49 -07:00
yuneng-jiang
c25b4b2ce8
Merge pull request #25398 from BerriAI/litellm_team_settings_router
[Feature] UI - Teams: Allow Editing Router Settings After Team Creation
2026-04-13 17:27:15 -07:00
yuneng-jiang
a306092d47
Merge pull request #25463 from BerriAI/litellm_oss_staging_04_09_2026
Litellm oss staging 04 09 2026
2026-04-13 17:25:53 -07:00
ryan-crabbe-berri
87b6b5145f
Merge pull request #25658 from BerriAI/litellm_e2e-edit-team-model-test
test(e2e): add edit team model TPM/RPM limits test
2026-04-13 17:15:56 -07:00
Ryan Crabbe
152d6898ab
test(e2e): drop cleanup from edit team model test
Reviewer flagged that cleanup failures were silently swallowed and
suggested asserting `delete.ok()`. While thinking through the fix, the
actual question turned out to be "does the cleanup matter at all?" —
and the answer is no.

The e2e runner (`run_e2e.sh`) spins up a fresh postgres container per
invocation and tears it down at the end, so every local and CI run
starts with an empty DB. Playwright retries share the same DB but each
attempt creates a new model with a unique `Date.now()` name and only
queries its own model, so orphans from failed attempts never collide
with later attempts or other tests. Nothing else in the suite reads
the all-models table.

Keeping the cleanup would also turn every write test into an implicit
delete test, coupling responsibilities and inflating runtime — which
is probably why `teams.spec.ts` (create a team), `keys.spec.ts`
(update key limits), etc. all leave their entities in place. Matching
that convention, drop the try/finally block and the `createdModelId`
tracking. 12 lines removed, no behavior change.
2026-04-13 17:05:42 -07:00
Ryan Crabbe
44614c43c6
test(e2e): add edit team model TPM/RPM limits test
Covers the full write-path flow for team-scoped models on the Models +
Endpoints page: create via /model/new, click the row to open the detail
view, click Edit Settings, change TPM/RPM, click Save Changes, assert
the new values render back. Cleans up via /model/delete in finally so
reruns stay deterministic.

Requires store_model_in_db: true in the fixture general_settings so the
proxy accepts /model/new and /model/delete. No existing test in the
dashboard e2e suite reads the all-models table or hits the model CRUD
endpoints, so enabling the flag has no cross-test impact.
2026-04-13 16:27:39 -07:00
Ryan Crabbe
004964f421
chore: remove deprecated tests/ui_e2e_tests/ suite
The suite was superseded by ui/litellm-dashboard/e2e_tests/ on 2026-04-08
and is no longer referenced by CircleCI, docs, or Makefile targets. Drop
the directory wholesale and remove the orphaned e2e:psql npm script that
pointed at its runner.
2026-04-13 15:40:34 -07:00
ryan-crabbe-berri
65d9fadf45
Merge pull request #25575 from BerriAI/litellm_feat-per-guardrail-opt-out-for-global-guardrails
feat(guardrails): per-team opt-out for specific global guardrails
2026-04-13 13:31:23 -07:00
Ryan Crabbe
2d14e4a4ed
test(ui/team): fix guardrails overview test for new component
Updates the expected header text to "Guardrails Settings" to match
GuardrailSettingsView's rendering, and moves the mock guardrails
from team_info.guardrails (legacy top-level path that nothing
reads) to team_info.metadata.guardrails where the component
actually looks. Also tightens the assertion to verify the
individual guardrail names appear, not just the section header.
2026-04-13 12:20:30 -07:00
Ryan Crabbe
842523a918
chore(ui): use antd in GuardrailSettingsView and document the rule
Converts GuardrailSettingsView from @tremor/react (Badge, Text) to
antd (Tag, plain spans) as part of the Tremor migration. Also
captures the "no new Tremor imports" rule in CLAUDE.md and expands
the existing note in AGENTS.md with the specific antd equivalents
and the yellow→gold gotcha.
2026-04-13 11:49:39 -07:00
Ryan Crabbe
84d7816bc9
refactor(ui/team): extract GuardrailSettingsView and reuse across team views
Pulls the Global / Team-specific subsection rendering out of
TeamInfo.tsx into a shared GuardrailSettingsView component with
card and inline variants, used on both the team Overview tab
(inside the existing Tremor Card) and the Team Settings tab read
view. The Global subsection header now carries a GlobalOutlined
icon, and since the icon is load-bearing the edit-form chip
coloring is simplified to a single blue instead of green/blue.
2026-04-13 11:38:23 -07:00
Ryan Crabbe
1dcccfc1d1
feat(ui/team): show guardrails in team settings read view
The Team Settings tab's read view listed every team field except
guardrails. Adds a Guardrails entry after Status with the same
Global / Team-specific subsections used on the Overview tab, so
the kill switch state and per-section membership are visible
without entering edit mode.
2026-04-13 11:08:39 -07:00
Ryan Crabbe
6ae693b85c
refactor(ui/team): split team read view guardrails into Global and Team-specific sections
Replaces the flat guardrails list with two subsections under the
Guardrails card, so the global vs. team-specific distinction is
carried by the section headers instead of per-badge markers. The
kill-switch state now renders in place of the Global subsection as
"Bypassed for this team", and the separate "Disable Global
Guardrails" field with its confusing "Disabled - Global guardrails
active" badge is removed.
2026-04-13 10:57:10 -07:00
Ryan Crabbe
1f57292363
fix(ui/team): add GlobalOutlined icon to global guardrail markers
Addresses a11y feedback — global vs. non-global guardrails were
distinguished only by color (green vs. blue). Adds GlobalOutlined
next to global guardrails in (1) the selected-chip tagRender, (2)
the dropdown OptGroup label, and (3) the team info read view badge.
2026-04-13 10:55:09 -07:00
Sameer Kankute
fa605d85c0
Merge pull request #25616 from BerriAI/main
merge main
2026-04-13 08:43:43 +05:30
Yuneng Jiang
1857be43a7
Merge remote-tracking branch 'origin/main' into litellm_regen_key_modal_antd 2026-04-11 20:45:17 -07:00
Yuneng Jiang
7c6bd98fdf
fix: address PR review comments on RegenerateKeyModal
- Remove redundant useEffect cleanup that duplicated handleClose logic
- Remove unnecessary currentAccessToken state, use accessToken from hook directly
2026-04-11 18:01:02 -07:00
Ryan Crabbe
30c2357fe3
fix(ui/team): annotate effectiveGuardrails as string[] for strict typecheck
Some checks failed
Unit Tests: Proxy DB Operations / proxy-db (auth-checks, tests/proxy_unit_tests/test_auth_checks.py tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (key-generation, tests/proxy_unit_tests/test_key_generate_prisma.py, 30, 0) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (remaining, tests/proxy_unit_tests --ignore=tests/proxy_unit_tests/test_key_generate_prisma.py --ignore=tests/proxy_unit_tests/test_auth_checks.py --ignore=tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
The new effectiveGuardrails computation derived its element type from
`info.metadata?.guardrails`, which is implicitly typed `any[]`, so the
downstream `.map((name) => ...)` callback inferred `name` as implicit
`any` and broke the production typecheck.
2026-04-11 17:48:16 -07:00
Ryan Crabbe
3d72e2a6f3
fix(guardrails): address PR #25575 review feedback + sync kill switch with opt-out list
Renames the new per-guardrail opt-out field from `disabled_global_guardrails`
to `opted_out_global_guardrails` to eliminate the one-character collision with
the legacy `disable_global_guardrails` boolean kill switch. Adds a type guard
on the new gate so a misnamed bool can't crash the guardrail check. Filters
duplicates out of the team-edit guardrail display for legacy teams that have a
global name persisted in `metadata.guardrails` from before this PR. Drops the
unused `isGuardrailsLoading` and `guardrailsError` destructures left in
AddModelForm after the hook refactor.

Adds Python tests for the new gate behavior (root, litellm_metadata, metadata,
non-matching name, empty list, malformed bool value, opt-in coexistence) and
extends useGuardrails.test.ts to exercise the global / optional partition
logic that the rebuilt hook performs in its `select` transform.

Wires the legacy kill switch and the new opt-out list together in the team
edit form so they can never fall out of sync:

- Toggling the kill switch reactively updates the Guardrails Select via
  `onValuesChange` — switch on strips all globals from the selection, switch
  off re-adds them. Existing opt-in extras are preserved either way.
- When the switch is on, global options in the Select are individually
  disabled (greyed out) so the user can still manage opt-in guardrails but
  cannot accidentally re-enable a global the kill switch is bypassing.
- The save handler writes both fields together: `disable_global_guardrails`
  reflects the switch, and `opted_out_global_guardrails` is set to either
  every global (when the switch is on) or the user's explicit opt-outs.
- `effectiveGuardrails` for the form's initialValues honors the kill switch
  on legacy teams so the form opens in a state that matches what the runtime
  gate is actually doing — fixes the visual lie where chips appeared active
  while the switch was bypassing them.

The backend gate already reads the list as the primary path with the bool
as a fallback, so untouched legacy teams keep working until they get edited,
at which point they migrate naturally.
2026-04-11 17:48:16 -07:00
Ryan Crabbe
59f66af0f9
fix(ui/team): wait for useGuardrails to resolve before rendering edit form
The team edit form computed its `guardrails` initialValues from
`globalGuardrailNames`, which is empty until `useGuardrails` resolves.
Because Ant Design's `<Form initialValues>` is read once on mount, a
user who clicked Edit before the query resolved would see globals
missing from the Select and could save that stale state, silently
opting the team out of every global guardrail.

Gate the form on `!isGuardrailsLoading` so initialValues always sees
the resolved set.
2026-04-11 17:48:16 -07:00
Ryan Crabbe
f9639654fa
feat(ui/team): per-guardrail opt-out for global guardrails
Replace the team info page's tags-mode guardrails Select with a grouped
multi-select that splits guardrails into "Global" (default_on=true) and
"Other" sections. On submit, derive both metadata fields from the single
selection array:

  - metadata.guardrails: non-global opt-ins (additive)
  - metadata.disabled_global_guardrails: globals the team has opted out of

The legacy disable_global_guardrails kill-switch toggle stays alongside
the multiselect and remains semantically distinct: it kills all global
guardrails including any added in the future, while the new list lets
new globals auto-apply unless explicitly excluded.

Other changes:
  - Switch from a manual useEffect/useState guardrails fetch to the
    consolidated useGuardrails hook
  - Replace stale "Select existing guardrails or enter new ones" help
    text with a single tooltip on each section's info icon
  - Render selected chips with green/blue color coding via tagRender so
    global vs non-global is visible without opening the dropdown
  - Drop the redundant [Global] tag from inside the OptGroup options
    (the group label already conveys it)
  - Update the read-only display to show the effective set (globals not
    opted out + additive opt-ins) with [Global] suffix on globals
2026-04-11 17:48:16 -07:00
Ryan Crabbe
a9d64f8620
refactor(ui/guardrails): expose full data from useGuardrails hook
Extend useGuardrails to return the full guardrail objects plus derived
globalGuardrailNames / optionalGuardrailNames sets via React Query's
select option, instead of just an array of names. Update its existing
consumer (AddModelForm) to extract names from the new shape.

The previous shape was tailored to AddModelForm's single use case
(populate a Select with names). The team info per-guardrail opt-out
work needs default_on per guardrail to split globals from non-globals,
which the old shape couldn't provide. Consolidating into the existing
hook gives both consumers one source of truth and one React Query
cache entry instead of two parallel fetches.

- useGuardrails.ts: rewrite return type, derive global/optional sets
  in select(); preserve the existing query key and auth-gate semantics
- AddModelForm.tsx: extract names from data?.guardrails.map(...)
- AddModelForm.test.tsx: update mock to return the new shape (also
  fixes a pre-existing shape mismatch in the mock)
- useGuardrails.test.ts: update 3 assertions to read names via
  data?.guardrails.map(...) instead of asserting against the flat array
2026-04-11 17:48:16 -07:00
Yuneng Jiang
909247785e
Merge remote-tracking branch 'origin' into litellm_internal_staging_04_11_2026 2026-04-11 15:41:03 -07:00
yuneng-jiang
56e82451df
Merge pull request #25458 from BerriAI/litellm_team_members_logs
Team member permission /spend/logs for team-wide spend logs (UI + RBAC)
2026-04-11 13:55:00 -07:00
Ishaan Jaffer
d22a07a9ba
Merge remote-tracking branch 'origin/main' into ci-fix-april6-fixes 2026-04-11 12:04:14 -07:00
Sameer Kankute
c13be44e44
feat(guardrails): optional skip system message in unified guardrail inputs (#25481)
* feat(guardrails): optional skip system message in unified guardrail inputs

Made-with: Cursor

* feat(dashboard): skip_system_message_in_guardrail in guardrail UI

Add a tri-state control (inherit / yes / no) when creating or editing
guardrails so admins can set litellm_params.skip_system_message_in_guardrail
without YAML. Table edit merges existing litellm_params before PUT to avoid
wiping content-filter and other provider fields.

Document the dashboard flow in the guardrails quick start with a screenshot.

Made-with: Cursor

* fix(guardrails): type structured_messages as AllMessageValues for mypy

Use AllMessageValues in openai_messages_without_system and cast adapter
request messages so GenericGuardrailAPIInputs matches TypedDict.

Made-with: Cursor
2026-04-11 08:53:24 -07:00