Commit graph

37031 commits

Author SHA1 Message Date
Jason Cook
4ff0de18ef fix(health): pass responses-mode `input` as a list
When ``/health/test_connection`` hits a ``mode: responses`` model, the
handler called ``litellm.aresponses(input=prompt or 'test')`` — a bare
string. OpenAI's public Responses API is tolerant of either shape, but
the ChatGPT/Codex backend enforces a list and returns
``{"detail": "Input must be a list"}``, so the "Test Connection" button
on the models list page failed against ChatGPT OAuth models even though
normal inference worked fine.

Wrap the fallback in a list (``input or [prompt or 'test']``) so both
backends are happy. The calling site in ``main.ahealth_check`` already
forwards ``input=['test from litellm']`` for this mode, so the common
path flows through unchanged.

Regression test mocks ``litellm.aresponses`` and asserts the handler
passes a list for both the ``input=[...]`` and prompt-only cases.
2026-04-23 15:02:35 -04:00
Jason Cook
f2653df86b fix(oauth): don't eager-resolve tokens during add_deployment cycles
``get_llm_provider_logic.py`` instantiates ``ChatGPTConfig`` /
``GithubCopilotConfig`` and calls ``_get_openai_compatible_provider_info``
at every ``add_deployment`` cycle during proxy startup (30s tick when
``STORE_MODEL_IN_DB=True``). The old code eagerly called
``get_access_token()`` / ``get_api_key()`` through the filesystem
authenticator at that point. With no tokens on disk this falls through
to ``_login_device_code()``, which prints a device prompt to stdout and
polls the IdP for up to 15 minutes — blocking startup and (for OAuth
credentials stored in the DB) duplicating work that ``validate_environment``
is about to do correctly at request time.

Resolution is now a pure metadata pass: pick an ``api_base``, let the
``oauth:<name>`` marker pass through untouched. Actual token resolution
still happens at request time via ``resolve_authenticator`` inside
``validate_environment``, which is where we have the full
``litellm_params`` anyway.

Tests updated to assert ``get_access_token`` / ``get_api_key`` are NOT
called during resolution, and that the ``oauth:`` marker passes through.
2026-04-23 14:58:20 -04:00
Jason Cook
2d70e7ba82 fix(chatgpt): fold response.output_item.done events into SSE parse
Reported symptom from a working OAuth request to
``chatgpt.com/backend-api/codex/responses``:

  APIConnectionError: ChatgptException - Unknown items in responses
  API response: []

The ChatGPT / Codex backend ships the response body as SSE. Each
output item arrives in its own ``response.output_item.done`` event,
and the terminal ``response.completed`` frame carries an empty
``response.output`` array — it is effectively a "we're done" signal
rather than the carrier for the items.

The existing parser only read ``response.output`` off the completed
frame, so it handed the downstream chat-completions translator a
``ResponsesAPIResponse`` with ``output=[]``, which blew up on
``_convert_response_output_to_choices``.

Fix: accumulate items from ``response.output_item.done`` during the
loop and, when ``response.completed`` arrives with an empty output,
substitute the accumulated list. The canonical OpenAI shape (items
already populated on ``response.completed``) still works — we only
fill in when the completed frame itself is empty.

Extracted the SSE loop into ``_parse_codex_sse_response`` to keep
``transform_response_api_response`` under the PLR0915 threshold.

Added a regression test that reproduces the Codex wire shape: one
``output_item.done`` event followed by a ``response.completed`` with
``output=[]``. 174 tests pass; Black + Ruff clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 13:24:50 -04:00
Jason Cook
503df1478e fix(chatgpt): DBAuthenticator must never fall through to _login_device_code
Reported symptom: Test Model fails immediately with

  GetLLMProvider Exception - Failed to request device code:
  Client error '403 Forbidden' for url
  'https://auth.openai.com/api/accounts/deviceauth/usercode'

No 15-minute hang this time — it comes back instantly.

Root cause: the ChatGPT ``DBAuthenticator`` inherited
``get_access_token`` from the filesystem ``Authenticator``, whose last
line is:

    tokens = self._login_device_code()

That's the right fall-through for the CLI (no tokens on disk → start a
new login). In the proxy's DB-backed context it is catastrophic: the
server tries to initiate an unattended device-code request, OpenAI
returns 403 on the ``usercode`` endpoint (no browser to walk through
consent), and the admin sees the cryptic error above.

Copilot's ``DBAuthenticator`` already overrides ``get_access_token``
and raises ``GetAccessTokenError`` cleanly — this commit mirrors that
in the ChatGPT side:

 - If no credential is loaded in ``litellm.credential_list``, raise a
   401 pointing the admin at STORE_MODEL_IN_DB and the UI sign-in.
 - If the token is expired and refresh fails, raise a 401 quoting the
   IdP's refresh error.
 - Never call ``_login_device_code`` from the proxy path.

Added regression tests that mock ``_login_device_code`` and assert it
is never called across the three failure modes above (missing
credential, happy path, refresh-error). 173 tests pass; Black + Ruff
clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 12:09:42 -04:00
Jason Cook
cef21a087d fix(oauth): route every remaining self.authenticator call through resolve_authenticator
Audit of every ``self.authenticator.*`` call-site across both providers
turned up two more paths that would skip the ``oauth:`` dispatch:

- ``github_copilot/embedding/transformation.py`` — the embedding
  ``validate_environment`` and ``get_complete_url`` both call the
  filesystem authenticator directly. Same failure mode as the chat
  transformation before the previous fix: a request with
  ``api_key: oauth:<name>`` would hit the filesystem authenticator, find
  no tokens on disk, and block the server thread on the 15-minute
  device-code poll. Now goes through ``resolve_authenticator`` too.
- ``chatgpt/responses/transformation.py::get_complete_url`` — called
  separately from ``validate_environment``. Lower severity (the env-
  based ``get_api_base`` just returns the constant fallback when no
  auth file is present, so it works in practice) but still a direct
  call that ought to share the same dispatch.

After this commit, ``grep -rn 'self\.authenticator\.' litellm/llms/
{chatgpt,github_copilot}/`` returns zero matches — every auth access
goes through ``resolve_authenticator``.

170 tests pass (same count; the chat regression test already covers
this family of bug — no new test was worth adding here).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 12:02:22 -04:00
Jason Cook
581b3e9692 fix(chatgpt): route the chat transformation through DBAuthenticator too
Reported symptom: "Test model" in the UI hangs indefinitely, a new
device code appears in the proxy logs, and the whole UI is frozen.

Root cause: the ChatGPT **chat** transformation still used the
filesystem-only ``Authenticator`` unconditionally. When the UI's
``/health/test_connection`` runs in the default ``mode="chat"``:

  UI → /health/test_connection (sync wait)
    → litellm.ahealth_check(mode="chat")
      → litellm.acompletion(...)
        → ChatGPTConfig._get_openai_compatible_provider_info(api_key="oauth:X")
          → self.authenticator.get_access_token()  # filesystem authenticator
            → _login_device_code()  # no tokens on disk → prints a new
                                    # device code and polls for up to 15
                                    # minutes, blocking the request

``ChatGPTResponsesAPIConfig`` already had the ``resolve_authenticator``
dispatch (the PR's original scope), so the responses-mode path was
fine. The chat path was overlooked.

Fix:

- Apply ``resolve_authenticator`` to both call-sites in
  ``ChatGPTConfig`` (``_get_openai_compatible_provider_info`` and
  ``validate_environment``). When ``api_key`` carries the ``oauth:``
  prefix, both methods now reach for the DB-backed authenticator and
  the stored credential — no device-code prompt, no 15-minute hang.

- Extend ``resolve_authenticator`` to the 3-arg shape
  ``(api_key, litellm_params, fallback)`` so it matches the Copilot
  resolver and covers the chat call-site that has ``api_key`` but not
  ``litellm_params``. Updated the single existing call-site in
  ``responses/transformation.py`` and the existing unit tests.

- Add a regression test asserting that ``ChatGPTConfig`` never calls
  the filesystem authenticator when ``api_key`` is ``oauth:<name>``
  (fs_auth is a MagicMock that raises on any attribute access).

170 tests pass; Black + Ruff clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 11:57:32 -04:00
Jason Cook
9167f9725b feat(oauth): refuse /start when STORE_MODEL_IN_DB is not set
Without STORE_MODEL_IN_DB=True the proxy still writes OAuth credentials
to LiteLLM_CredentialsTable, but ``proxy_config.get_credentials`` — the
DB → ``litellm.credential_list`` reload run at startup — lives inside
``if store_model_in_db is True:`` in proxy_server.py. Result: silent
data loss on restart and request-time ``api_key: oauth:<name>`` failures
because the name is no longer in the in-memory cache.

Gate the /start endpoints (both ChatGPT and Copilot) behind
``get_secret_bool("STORE_MODEL_IN_DB", False)``. Admins get a clear 400
up front instead of sitting through the 15-minute device-code poll only
to discover the flow silently doesn't persist.

Tests: setenv STORE_MODEL_IN_DB=True in the autouse fixture so the
success-path tests don't each have to opt in, plus one new test per
provider asserting 400 + message when the env var is absent. 167 cases
pass locally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 11:48:02 -04:00
Jason Cook
392400fe28 docs: call out STORE_MODEL_IN_DB=True requirement for OAuth credentials
The DB → litellm.credential_list reload that makes OAuth credentials
survive a proxy restart lives inside the same ``if store_model_in_db
is True:`` block in proxy_server.py as the model-deployment scheduler.
Without the env var the write succeeds but nothing reads it back on
startup — credentials appear to vanish, and any model with
``api_key: oauth:<name>`` fails at request time.

This was caught during deployment testing. Not a new requirement
introduced by this PR (the same block gates the standard Add Model UI
flow), but easy to miss if you're only thinking about OAuth. Added a
prominent note to the CLAUDE.md OAuth section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 11:44:41 -04:00
Jason Cook
9d0466ba6d feat(ui): oauth_credential_select field type for Add Model form
Previously the ChatGPT (OAuth) provider in the Add Model form rendered
a plain text input for ``api_key`` and expected the admin to type the
``oauth:<credential_name>`` marker by hand — easy to typo, and
discoverability depended on reading the tooltip.

Add a new ``field_type: "oauth_credential_select"`` that
``provider_specific_fields.tsx`` renders as an antd Select populated
from ``useCredentials()``, filtered to OAuth-backed credentials
(``credential_info.type`` in ``{chatgpt_oauth, copilot_oauth}``).
Picking a row stores ``oauth:<credential_name>`` as the form value, so
the downstream request path is unchanged.

Wire-up:

- ``ProviderCredentialField`` Literal (Python) and
  ``ProviderCredentialFieldMetadata`` union (TypeScript) both extended
  with the new type.
- ``provider_create_fields.json`` for ``ChatGPT`` updated to use it.
- Empty-state: if no OAuth credentials exist yet, the dropdown shows a
  "No OAuth credentials found" hint pointing at Credentials → Add
  Credential.

No change to Copilot's entry — Copilot's existing ``api_key``/``api_base``
text fields stay, since that provider still supports plain PAT auth
alongside OAuth. Admins who want the OAuth flow for Copilot can still
type ``oauth:<name>`` into the ``api_key`` field manually; the dropdown
will cover that too in a follow-up if you want symmetry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 11:21:02 -04:00
Jason Cook
a5225003a3 feat(chatgpt): list ChatGPT (OAuth) in the Add Model provider dropdown
The Add Model form reads its provider list from
``/public/providers/fields`` (served from
``public_endpoints/provider_create_fields.json``), not from the
frontend ``Providers`` enum directly. Add a ChatGPT entry there with a
single required ``api_key`` field pre-filled with ``oauth:`` so the
admin's workflow is:

1. Credentials → Add Credential → ChatGPT (OAuth) → sign in → credential
   named ``my-chatgpt``
2. Add Model → provider: ChatGPT (OAuth) → model name → api_key field
   shows ``oauth:`` placeholder + tooltip explaining the convention →
   admin types ``oauth:my-chatgpt`` → save

At request time the ChatGPT responses transformation recognises the
``oauth:`` prefix and routes through ``DBAuthenticator`` for the stored
credential. Copilot was already in the JSON so its Add Model flow
already works.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 11:14:23 -04:00
Jason Cook
b22f988248 fix(oauth): jsonify_object() for Prisma Json columns in persist_credential_to_db
Reported error after the cross-loop fix:

  Tokens obtained but DB persist failed: Unable to match input value to
  any allowed input type for the field. Parse errors: [...
  ``credential_values`` should be of any of the following types:
  ``JsonNullValueInput``, ``Json`` ...]

Prisma's Json columns ingest pre-serialized JSON *strings*, not raw
Python dicts. The ``/credentials`` endpoint wraps the payload with
``jsonify_object(...)`` (in ``litellm/proxy/utils.py``) which does
``json.dumps`` per nested-dict field. My persist helper was skipping
that step and passing raw dicts — Prisma's binding layer then couldn't
match them to the ``Json`` type.

Route the ``credential_values`` + ``credential_info`` dicts through
``jsonify_object`` before the upsert. Same fix in both ChatGPT and
Copilot ``db_authenticator.py``. Tests updated to assert the serialized
string form (``json.loads(kwargs[...]["credential_values"])``).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:58:46 -04:00
Jason Cook
c3932e06d4 fix(oauth): run the OAuth worker on the proxy's main asyncio loop
Reported error during device-code login:

  Tokens obtained but DB persist failed: <asyncio.locks.Event object at
  0x... [unset]> is bound to a different event loop

Root cause: the background worker was a ``threading.Thread`` that ran
``asyncio.run(persist_credential_to_db(item))``. That creates a fresh
event loop in the worker thread, but ``prisma_client``'s internal
asyncio primitives (locks, futures) are bound to the proxy's main loop.
Awaiting a prisma call from the worker loop hits the cross-loop error.

Fix:

- Refactor the background flow from a thread to an asyncio task
  (``asyncio.create_task``) scheduled on the proxy's main loop. Blocking
  IO in the flow (device-code poll, token exchange) runs in
  ``loop.run_in_executor``. The DB persist step (``await
  persist_credential_to_db(item)``) now naturally shares a loop with
  prisma_client. Same treatment for both ChatGPT and Copilot endpoints.

- For the DBAuthenticator refresh path (called from sync
  ``validate_environment`` during a request, same cross-loop risk), add
  ``_register_proxy_main_loop`` + ``_schedule_db_persist`` now prefers
  ``asyncio.run_coroutine_threadsafe`` onto the registered loop.
  ``/chatgpt/oauth/start`` and ``/copilot/oauth/start`` register the loop
  on invocation (guaranteed to be the proxy's main loop). Falls back to
  the old thread + ``asyncio.run`` path only when no loop is registered
  (CLI / tests, where prisma_client is ``None`` anyway).

Tests updated: ``TestBackgroundWorker`` now drives the async task
directly via ``await _run_device_code_flow_async(...)``. The
``test_creates_session_and_spawns_worker`` test stubs the task to a
no-op instead of patching ``threading.Thread``.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:48:59 -04:00
Jason Cook
4f798c0d23 fix(ui): wire ChatGPT into provider_map + providerLogoMap
The enum entry ``Providers.ChatGPT = "ChatGPT (OAuth)"`` was added but
the corresponding ``provider_map["ChatGPT"]`` and
``providerLogoMap[Providers.ChatGPT]`` entries were missing. The
dropdown option still renders, but:

 - without ``provider_map[key]``, ``custom_llm_provider`` resolves to
   ``undefined`` on submit (harmless for the OAuth path — we never hit
   that submit branch — but still inconsistent with every other
   provider), and
 - without ``providerLogoMap`` the Option icon falls through to the
   "first-letter div" fallback, which reads as a visual glitch.

Add both. Reuses ``openai_small.svg`` since ChatGPT is an OpenAI product.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 10:24:26 -04:00
Jason Cook
c3d29a1ded test(ui): add vitest coverage for the 3 new OAuth login components
CONTRIBUTING.md requires corresponding tests for new UI components.
Adds:

- OAuthDeviceLoginButton.test.tsx (6 cases) — Sign-in button disabled
  state, startCall invocation, user-code + verification-URL rendering,
  onSuccess callback on poll success, error-state rendering on poll
  failure, and cancel flow.
- ChatGPTLoginButton.test.tsx (1 case) — renders with the ChatGPT label.
- CopilotLoginButton.test.tsx (1 case) — renders with the GitHub Copilot
  label.

Real timers throughout; polling tests wait up to 10s for the 3s-interval
first poll to fire. 20/20 local tests pass across my new + adjacent
existing UI test files; ``npm run build`` succeeds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 11:31:52 -04:00
Jason Cook
d663094202 docs(db_authenticator): explain the inline imports in persist_credential_to_db
Greptile flagged the inline proxy imports as an acknowledged P2 style
nit. Documenting the two real reasons they're inline so the next reader
doesn't 'fix' them into a module-level import and break things.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:58:40 -04:00
Jason Cook
796e51713b fix(oauth): address Greptile P2 findings on #25923
- Drop the redundant decorator-level ``dependencies=[Depends(user_api_key_auth)]``
  on all 8 OAuth endpoints (4 each in chatgpt/copilot). The same dependency
  is already injected as a parameter, which runs it and binds the result —
  FastAPI's dependency cache makes the decorator-level duplicate a no-op at
  runtime, just visual noise.
- Finish the @tremor/react → antd migration in ``credentials.tsx``: rename
  the ``AntdButton`` alias to ``Button`` and remove the ``Button`` entry
  from the @tremor/react import, so the top-level "Add Credential" button
  also goes through antd. No rendered changes (antd Button's children +
  onClick API matches what that call site already used).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:53:22 -04:00
Jason Cook
98741dff72 feat(chatgpt, github_copilot): OAuth sign-in + token refresh in proxy UI
Add "Sign in with ChatGPT" and "Sign in with GitHub Copilot" device-code
OAuth flows to the Add Credential modal. Tokens persist as encrypted JSON
in LiteLLM_CredentialsTable and are picked up at request time when a
model's api_key is set to "oauth:<credential_name>"; a DBAuthenticator
subclass reads from the in-memory credential cache (sync) and writes
refreshed tokens back via a fire-and-forget worker thread.

Per-row Refresh button rotates tokens on demand — ChatGPT via the IdP's
refresh_token grant, Copilot by re-deriving the short-lived API key from
the stored GitHub access token.

Also ships a litellm-chatgpt-login CLI with an optional PKCE+loopback
flow alongside the existing device-code path for local sign-in outside
the UI.

Provider-specific surface lives in new files under
litellm/llms/{chatgpt,github_copilot}/db_authenticator.py and
litellm/proxy/{chatgpt,copilot}_oauth_endpoints/. Shared-file delta is
~275 lines across 10 pre-existing files, the bulk being a pure append
at the end of networking.tsx.

Dispatch convention + operational caveats documented in the new
"ChatGPT / Copilot OAuth Credentials" section of CLAUDE.md.

Security:
 - /chatgpt/oauth/* and /copilot/oauth/* endpoints require PROXY_ADMIN
   (view-only admins excluded from write paths)
 - session_id query params are Query(...) annotated
 - session-cap check + slot reservation are atomic; reserved slot is
   cleaned up on device-code failure
 - PKCE loopback callback html.escape()s the IdP's error_description
   before rendering

Tests: 165 cases covering DBAuthenticator read/write, config dispatch,
endpoint admin-only, 429 cap, slot cleanup, background-worker success /
auth-failure / DB-persist-failure paths, PKCE helpers + XSS regression,
CLI broad-exception + KeyboardInterrupt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:30:10 -04:00
Sameer Kankute
b8f7d61400
Merge pull request #25589 from BerriAI/litellm_oss_staging_04_11_2026
Litellm oss staging 04 11 2026
2026-04-14 23:34:25 +05:30
Sameer Kankute
b1c77d22f0
Merge pull request #25192 from BerriAI/litellm_oss_staging_04_04_2026
litellm_staging_04_04_2026
2026-04-14 23:33:16 +05:30
ishaan-berri
4a71583951
Merge pull request #25348 from BerriAI/litellm_gemini-veo-video-resolution-pricing2
feat(gemini): Veo Lite pricing, video resolution usage and tiered cost
2026-04-14 10:23:22 -07:00
ishaan-berri
e2fc7d64e8
Merge pull request #25396 from BerriAI/litellm_bedrock-normalize-custom-tool-schema
feat(bedrock): normalize custom tool JSON schema for Invoke and Converse
2026-04-14 10:21:15 -07:00
Sameer Kankute
69bf2bfb9a
Fix tests 2026-04-14 21:18:23 +05:30
Sameer Kankute
a0e61a9d49
Fix code qa 2026-04-14 21:01:39 +05:30
Sameer Kankute
ee40da58a2
Merge branch 'main' into litellm_oss_staging_04_11_2026 2026-04-14 20:54:12 +05:30
Sameer Kankute
ffb87dcac9
Fix failing test and code qa + lint 2026-04-14 20:53:17 +05:30
Sameer Kankute
ef94f5fc4d
Fix budget reset test 2026-04-14 20:50:42 +05:30
Sameer Kankute
f6e526c5be
Fix bulk update tests 2026-04-14 20:46:21 +05:30
Sameer Kankute
3d567c34dd
Merge pull request #25698 from BerriAI/revert-25395-fix/25388-embedding-encoding-format
Revert "fix(embedding): omit null encoding_format for openai requests"
2026-04-14 20:37:35 +05:30
Sameer Kankute
e6771feace
Revert "fix(embedding): omit null encoding_format for openai requests (#25395)"
This reverts commit e3d160f158.
2026-04-14 20:36:28 +05:30
Sameer Kankute
972e42c7fd
Merge branch 'main' into litellm_oss_staging_04_04_2026 2026-04-14 20:23:06 +05:30
yuneng-jiang
e64d98f725
Merge pull request #25590 from BerriAI/litellm_add_model_e2e_tests
[Test] UI - Models: Add E2E tests for Add Model flow
2026-04-13 19:03:39 -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
8427534f13
Merge pull request #25647 from BerriAI/litellm_yj_apr_11
Some checks are pending
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
CodSpeed Benchmarks / benchmarks (push) Waiting to run
Helm unit test / unit-test (push) Waiting to run
Read Version from pyproject.toml / read-version (push) Waiting to run
Scorecard supply-chain security / Scorecard analysis (push) Waiting to run
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) Waiting to run
Unit Tests: Proxy DB Operations / proxy-db (key-generation, tests/proxy_unit_tests/test_key_generate_prisma.py, 30, 0) (push) Waiting to run
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, 30, 8) (push) Waiting to run
Unit Tests: Security / security (push) Waiting to run
GitHub Actions Security Analysis / zizmor (push) Waiting to run
[Infra] Merge dev branch with main
2026-04-13 17:28:38 -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-berri
c08fb82cae
Merge pull request #25657 from BerriAI/litellm_chore-e2e-tests
chore: remove deprecated tests/ui_e2e_tests/ suite
2026-04-13 16:51:22 -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
ishaan-berri
548225ef31
Merge pull request #25586 from BerriAI/litellm_ishaan_april11
Litellm ishaan april11
2026-04-13 14:55:50 -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
ishaan-berri
6e6ed4fa66
Merge pull request #25452 from mubashir1osmani/readme
docs: week 2 checklist
2026-04-13 13:23:48 -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
Yuneng Jiang
df75e79615
raise ValueError on os.environ/ references in request-supplied callback params
Previously these were silently dropped with a verbose warning, which
could break observability integrations without surfacing a clear error.
Now raises ValueError with remediation steps (configure server-side
or pass the resolved value) so callers get immediate, actionable feedback.
2026-04-13 12:00:25 -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