Skip to content

refactor(ui): drive cache settings form from a typed frontend schema - #31939

Merged
yuneng-berri merged 5 commits into
litellm_internal_stagingfrom
litellm_/affectionate-mcnulty-7eaafc
Jul 2, 2026
Merged

refactor(ui): drive cache settings form from a typed frontend schema#31939
yuneng-berri merged 5 commits into
litellm_internal_stagingfrom
litellm_/affectionate-mcnulty-7eaafc

Conversation

@yuneng-berri

@yuneng-berri yuneng-berri commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Relevant issues

Linear ticket

LIT-3996 (UI cache config deficiencies)

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have requested a Greptile review by commenting @greptileai and received a Confidence Score of at least 4/5 before requesting a maintainer review

Screenshots / Proof of Fix

This is a UI-only refactor, so verification is in the browser against a proxy with STORE_MODEL_IN_DB='True' and a database connected

  1. Go to http://localhost:4000/ui/?page=caching and open the Cache Settings tab
  2. Confirm the Connection Settings section shows Redis URL, Host, Port, Database Index, Password, Username
  3. Switch Redis Type to Cluster, Sentinel, then Semantic and confirm the type-specific section appears (Startup Nodes; Sentinel Nodes / Service Name / Sentinel Password; Similarity Threshold / Embedding Model)
  4. Clear Port, type 99999, and click Save Changes; confirm an inline error "Port must be an integer between 1 and 65535" shows and nothing is saved
  5. Switch to Cluster, type not json into Startup Nodes, and click Save Changes; confirm an inline "Must be valid JSON" error shows and nothing is saved
  6. Set a valid Host and Port, click Test Connection, then Save Changes, and confirm the values persist after a reload

Type

🧹 Refactoring

Changes

The Cache Settings form used to be generated dynamically from field metadata the backend shipped in GET /cache/settings, and it read the submitted values back out of the DOM with document.querySelector. For a form whose shape only changes when a developer edits code, that loses type safety and makes client-side validation hard

This moves the field definitions into a typed frontend module (cacheSettingsFields.ts) that mirrors the backend CACHE_SETTINGS_FIELDS, including the recently added url and db fields. Each field declares its name, label, type, default, help text, the redis type it applies to, its section, and optional antd validation rules. The form is now an antd Form with controlled state; cacheSettingsUtils.ts builds the initial values and the save payload as pure, typed functions, so the document.querySelector value-gathering is gone

The save and test payloads sent to POST /cache/settings and POST /cache/settings/test are unchanged, and current values are still populated from GET /cache/settings. Per-field validation lives on each field's rules, so an invalid value blocks submit and surfaces inline before and on save; that is the clean slot where the upcoming Redis URL validation will go

This is a frontend-only change. The url and db backend handling (field definitions plus url-precedence resolution) rides along with the sibling backend work; nothing here touches the backend. The fields value in the GET /cache/settings response is no longer consumed by the UI, but it is left in place since removing it is a separate backend change

CacheFieldRenderer and CacheFieldGroup (and their tests) are replaced by CacheFormField and CacheFieldSection. Tests cover the fields rendered per redis type, inline validation blocking submit, and the exact save payload shape

image image

The Cache Settings form was dynamically generated from field metadata
shipped by the backend, and read its values back out of the DOM with
document.querySelector. That loses type safety and makes client-side
validation awkward, which is a poor fit for a form whose shape only
changes when a developer edits code.

Move the field definitions (name, label, type, default, help text, which
redis type they apply to, section, and validation rules) into a typed
frontend module and render them through antd Form with controlled state.
The GET /cache/settings endpoint is still used to populate current values,
and the save/test payload shape sent to POST /cache/settings and
/cache/settings/test is unchanged. Per-field validation now lives on each
field's antd rules, so an inline error can surface before and on submit;
this is where the upcoming Redis URL validation will slot in.

The backend's fields output in GET /cache/settings is no longer consumed
by the UI, but is left in place since removing it is a separate backend
change.
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR replaces the dynamically-generated, DOM-querying cache settings form with a typed frontend schema (cacheSettingsFields.ts) that mirrors the backend field list, and wires it into a proper antd Form with controlled state and per-field validation rules.

  • Schema-driven form: CACHE_FIELDS defines every field's name, type, section, applicable redis type, and antd validation rules; buildInitialValues / buildCachePayload are pure typed functions that replace the document.querySelector gathering loop.
  • Inline validation: Port, database index, list fields (startup nodes, sentinel nodes), and numeric fields each declare their own rules array so invalid input is caught and surfaced inline before a save or test connection is attempted, and the old silent-drop path on JSON parse failure is now blocked by jsonListRule.
  • Deleted components: CacheFieldRenderer and CacheFieldGroup (and their tests) are removed and replaced by CacheFormField and CacheFieldSection, which consume the typed schema directly instead of receiving any-typed field objects from the API.

Confidence Score: 5/5

Frontend-only refactor that is safe to merge; the save and test payloads sent to the backend are unchanged and the new typed schema is well-tested.

The change removes all document.querySelector value gathering and replaces it with a typed antd Form. Every field now has explicit validation rules, the two list fields that were previously silently dropping invalid JSON now block submission with inline errors, and the utility functions are covered by pure unit tests plus an integration test suite. No backend contracts are changed.

No files require special attention.

Important Files Changed

Filename Overview
ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/cacheSettingsFields.ts New typed field registry for all cache settings; includes port, db, cluster, sentinel, and semantic fields with appropriate validation rules.
ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/cacheSettingsUtils.ts Replaces DOM-querying form value gathering with pure typed functions; boolean fields always emit false rather than undefined, which is tested and intentional.
ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/index.tsx Main component migrated to antd Form with controlled state; validate() follows standard antd pattern of catching ValidateErrorEntity to surface inline errors while blocking submission.
ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/CacheFormField.tsx New field renderer that consumes CacheField type; correctly sets valuePropName="checked" for Switch controls and delegates validation rules from the field schema.
ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/CacheFieldSection.tsx Thin layout wrapper that renders nothing when a section has no visible fields; Tailwind class strings are hardcoded literals so purge is safe.
ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/index.test.tsx New integration tests covering per-type field visibility, inline validation blocking submit, and save payload shape; replaces the deleted CacheFieldRenderer and CacheFieldGroup tests.
ui/litellm-dashboard/src/app/(dashboard)/caching/components/cache_settings/cacheSettingsUtils.test.ts Unit tests for fieldsForSection, buildInitialValues, and buildCachePayload; confirms list field invalid JSON is silently omitted at the utility level (guarded upstream by jsonListRule).

Reviews (2): Last reviewed commit: "fix(ui): validate numeric cache fields a..." | Re-trigger Greptile

sentinel_nodes and redis_startup_nodes had no validation rule, so
malformed JSON passed validateFields, was caught while building the save
payload, and the field was silently omitted; the user's cluster/sentinel
config was discarded with no feedback. Add a jsonListRule (same shape as
portRule) to both list fields so an invalid value surfaces inline and
blocks save.
…he error

The Startup Nodes and Sentinel Nodes help text showed Python-style
single-quoted examples (e.g. [{'host': '127.0.0.1', 'port': '7001'}]),
which the JSON validator correctly rejects, so pasting the example we
display failed. Switch both examples to valid JSON with double quotes and
change the parse-error message to "Must be a valid JSON array (use double
quotes)" so the hint points at the fix. Also add a regression test
asserting a numeric field (Database Index) is included in the save payload.
Numeric fields (Database Index, TTL, Max Connections, Similarity
Threshold) rendered as antd InputNumber, which silently coerces
non-numeric input to empty. Because the fields are optional, an invalid
entry like a full connection URL pasted into Database Index passed
validation and was silently dropped from the save payload.

Render numeric fields as text inputs with a validation rule (non-negative
integer for Database Index and Max Connections, number for TTL and
Similarity Threshold), mirroring how Port already works, so invalid input
is preserved, flagged inline, and blocks submit instead of vanishing. The
save payload still coerces these to real numbers. Adds a regression test
for a non-numeric value entered into a numeric field.
@yuneng-berri

Copy link
Copy Markdown
Contributor Author

@greptile

@yuneng-berri
yuneng-berri enabled auto-merge (squash) July 2, 2026 21:00
@yuneng-berri
yuneng-berri merged commit bea8c93 into litellm_internal_staging Jul 2, 2026
122 checks passed
@yuneng-berri
yuneng-berri deleted the litellm_/affectionate-mcnulty-7eaafc branch July 2, 2026 21:09
type: "string",
section: "connection",
helpText:
"Full Redis/Valkey connection URL (e.g. redis://:password@host:6379/1). When set, it takes precedence over Host, Port, Password, and Database Index.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium: Redis URL credentials are exposed

This new field explicitly supports embedding the Redis password in the URL, but /cache/settings only redacts password and sentinel_password before returning current_values. A read-only admin can fetch this endpoint and recover the Redis credential from current_values.url; treat url as sensitive end-to-end by redacting or stripping userinfo in the backend response, and avoid rendering credential-bearing URLs as a normal text field.

@veria-ai

veria-ai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

PR overview

This pull request refactors the LiteLLM dashboard cache settings UI so the form is driven by a typed frontend schema. The touched cache settings field definitions include support for configuring Redis connection fields, including URL-based configuration.

One security issue remains open: Redis credentials can be embedded in the cache URL and then returned through the cache settings endpoint without being redacted. This allows a read-only admin to recover the Redis credential from the rendered or fetched current settings. No issues have been addressed yet, so the PR still needs a backend redaction change and safer UI handling for credential-bearing URLs.

Open issues (1)

Fixed/addressed: 0 · PR risk: 7/10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants