Commit graph

42960 commits

Author SHA1 Message Date
yuneng-jiang
2913ee811c
Merge pull request #36847 from BerriAI/litellm_/awesome-shirley-6a1a86
refactor(ui): migrate playground to shadcn
2026-08-13 18:30:48 -07:00
yuneng-jiang
6797327dc8
Merge pull request #36838 from BerriAI/litellm_/brave-hermann-3d77ac
refactor(ui): migrate guardrails-monitor to shadcn
2026-08-13 18:30:40 -07:00
yuneng-jiang
ce3a56dce6
Merge pull request #36834 from BerriAI/litellm_/compassionate-jones-9c0d5c
refactor(ui): migrate usage to shadcn
2026-08-13 18:30:30 -07:00
Yassin Kortam
8841cbc10f
fix(mcp): resolve admin OAuth sessions from any worker via DB-backed drafts (#36844)
The Admin UI's Authorize & Fetch Token flow stored its pending server in a
module-level dict, so /register, /authorize and /token only succeeded when
every leg happened to land on the process that served /session. On a proxy
with NUM_WORKERS greater than 1, or more than one replica, each click was an
independent draw and failed with a bare 404, which reads as intermittent.

Persist the pending server as a short-lived draft row instead, so any worker
resolves it. The in-memory cache is kept as the fallback for proxies with no
database configured, which keeps single-process deployments working as before.

A session runs under a caller-supplied id only when that id names a server
that really exists, which is the edit form re-authorizing a saved server.
Anything else gets a fresh id, so two concurrent sessions can never share one
draft and silently adopt each other's URL or client credentials. Drafts past
their lifetime are swept on each write so abandoned sessions do not
accumulate, and a lost create race adopts the winner rather than failing a
caller whose session is ready.

Drafts are excluded from listings and never enter the runtime registry. The
exclusion keeps rows whose approval status is NULL, which both short spellings
of the filter drop, silently hiding every server predating the approval
workflow.

Measured on a two-worker proxy against the live GitHub MCP server, 120
concurrent authorize calls per leg: staging 56/120 failures, this branch
0/120, staging again 65/120 as a positive control.
2026-08-13 18:03:12 -07:00
Yassin Kortam
3615cccfef
fix(team): sweep dangling team references and cache on team delete (#36819)
* fix(team): sweep dangling team references and cache on team delete

delete_team drove all of its cleanup off the team's members_with_roles roster, so any
user row referencing the team by another route kept a dangling team id forever and the
deleted team stayed visible on /user/info. Nothing swept LiteLLM_UserTable.teams or
LiteLLM_TeamMembership by team id, schema.prisma declares no relation between the
membership table and the team table so there is no cascade to fall back on, and the
cached team object was never invalidated on delete.

Adds a sweep that runs before the team rows are dropped: it strips the deleted ids from
every user row that still lists them and removes every membership row for those teams.
Adds _delete_cache_team_object in auth_checks and calls it per deleted team so the
team_id:{team_id} entry cannot outlive the team.

The sweep is targeted, not indiscriminate: only the deleted ids are removed and the
other teams on a user record are left intact.

* fix(team): fail member_add when the team is deleted under the row lock

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* docs(team): correct the post-delete sweep note for the member_add lock path

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-13 18:01:38 -07:00
Yassin Kortam
b344043eaf
fix(ui): stop a deselected MCP server keeping its grant on a virtual key (#36840)
* fix(ui): stop a deselected MCP server keeping its grant on a virtual key

The key editor sent `mcp_tool_permissions` unfiltered, and the MCP resolver
counts a server named only under `mcp_tool_permissions` as entitled, unioning
`tool_perm_servers` into `all_servers` at four sites in
`user_api_key_auth_mcp.py`. Deselecting a server, or removing the access group
that supplied it, therefore left a stale entry that kept the key reaching that
server with its old tool allowlist attached.

Reuse `extractMcpEntitlement`, which already landed for the internal-user
surface, so the key surface drops an entry only once the server is known and no
longer granted, and keeps it whenever a retained access group or toolset could
still supply it. The helper moves to a shared module so the key template does
not import a users page component.

Setting the map unconditionally is part of the same fix: the old
`Object.keys(...).length > 0` guard let the previous map ride through the
`object_permission` spread, which filtering to an empty map would otherwise hit
in exactly the case the fix is for.

* fix(ui): resolve retained MCP groups and toolsets per server when pruning tool permissions

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(ui): mock the MCP toolsets hook in the key update suite

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-13 18:00:42 -07:00
Yassin Kortam
e0f388cb5c
feat(ui): render request metrics on the /ui/chat surface (#36845)
/ui/chat never rendered a metrics bar. The Responses helper already parses
usage off the response.completed event, but the chat page passed positional
undefined where onTimingData, onUsageData and onTotalLatency sit, ChatMessage
had nowhere to hold them, and ChatMessages never rendered ResponseMetrics.

Thread the three callbacks through, persist the values on the assistant
message, and reuse the playground's ResponseMetrics to show latency, TTFT,
input/output/total tokens and cost. Also map the cost the proxy reports on the
streamed usage object, which only the chat-completions helper did before.
2026-08-13 17:31:13 -07:00
Emerson Gomes
4ea5749642
feat(azure-ai): add Grok 4.3 model metadata (#27932)
* Add Azure AI Grok 4.3 metadata

* Address Azure Grok 4.3 test feedback

* Drop empty tool choice in responses bridge

* style(azure-ai): update Grok metadata tests
2026-08-13 17:25:17 -07:00
Emerson Gomes
b85f557f30
fix: enable xhigh reasoning support for gpt-5.4-mini models (#26909)
* fix: sync gpt-5.4 reasoning capability flags

* fix(models): keep GPT-5.4 service tiers consistent
2026-08-13 17:24:58 -07:00
Emerson Gomes
603fe93758
feat(azure_ai): add Fireworks FW model pricing on Azure AI Foundry (#35613)
* feat(azure_ai): add Fireworks FW model pricing on Azure AI Foundry

* fix(azure_ai): drop incorrect FW-Kimi-K2.6-Code alias

* test(azure-ai): assert FW max token metadata

* feat(azure_ai): add Inkling and Nemotron 3 Ultra pricing
2026-08-13 17:24:38 -07:00
Yassin Kortam
04f5dedf69
feat(cli): make the hidden lite command list configurable (#36816)
* fix(cli): hide codex and opencode from the lite command listings

They stay registered and invokable, so existing `lite codex` users keep
working; they just no longer show up in `lite --help` or the interactive
shell's command list.

* feat(cli): make the hidden lite command list configurable

codex and opencode are supported, so hardcoding them as hidden was wrong. Let deployments curate their own listing with `lite config set hidden_commands codex,opencode` instead; nothing is hidden by default and hidden commands stay invokable.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-13 17:23:03 -07:00
tin-berri
83e890bdde
feat(ui): shadow evals tab beside auto-router usage (#36588) 2026-08-13 17:19:45 -07:00
Yassin Kortam
72ee0bb1c4
fix(cli): launch agents as a child process on Windows (#36822)
os.exec* has no process-replacement semantics on Windows, so `lite claude`
printed its routing line and returned to the prompt while Claude Code was left
detached without a usable console. Windows now spawns the agent, waits for it,
and exits with the child's status. Batch shims such as the npm-installed
claude.cmd go through cmd.exe because CreateProcess cannot run them directly,
and that command line is emitted verbatim with every token quoted so a spaced
path or an argument holding a shell metacharacter cannot be re-parsed by the
command processor. POSIX keeps using os.execvpe unchanged.
2026-08-13 17:06:25 -07:00
Yassin Kortam
56b08c19d6
fix(proxy/team): resolve member_delete cleanup by user id, not the addressed email (#36839)
/team/member_delete dropped the roster entry by matching user_email against
members_with_roles, then built its user-row lookup from that same raw email
instead of from the user_id the roster entry already carries. An email the user
row does not literally hold matched nothing, so the team id stayed in the user's
teams array and the team-membership row was left orphaned while the call still
returned 200.

/team/member_add resolves an email to a user case-insensitively but stores the
caller's casing on the roster, so inviting "Alice@Example.com" for a row holding
"alice@example.com" and removing by that same string is enough to reach it.

_cleanup_members_with_roles now returns the roster entries it removed, and both
the user-row update and the membership delete run against their user ids.
2026-08-13 17:00:52 -07:00
Yassin Kortam
ab2333b6c4
fix(auth): stop the team fallback from widening model access (#36837)
When get_team_object fails, the centralized auth gate rebuilds the team
from the token's own fields. A token whose team row was missing when the
key was read carries team_models=[] and team_blocked=False, and the
model-access check reads an empty model list as every model, so the
rebuilt team grants more than the real team ever did.

get_team_object reported a deleted team and a database that would not
answer as the same 404, so the fallback could not tell a definitive
answer from a degraded read. Raise a TeamNotFoundError subclass, still a
404 with the same detail so every other caller is unaffected, only when
the database answers and the row is absent.

A team that is provably gone now refuses, and no setting overrides that.
Otherwise the grant is merely unknown: a token carrying one may vouch,
since replaying a recorded grant cannot widen it, and a token carrying
none may not. allow_requests_on_db_unavailable still opts back out there,
and is only consulted once the failure is known to be a degraded read.
2026-08-13 16:59:58 -07:00
Yassin Kortam
b72dab8049
feat(ui): show provider prompt cache tokens in chat response metrics (#36827)
The chat metrics bar reported In/Out/Reasoning/Total/cost only, so a
playground user had no signal that provider prompt caching worked. The
cached-token counts were already visible in the Logs drawer, which meant
the answer to "does caching work here" lived on a different page.

Adds cacheReadTokens and cacheCreationTokens to TokenUsage and renders
them as two chips, reusing the prompt-cache tooltip wording already
introduced for the Logs drawer so both surfaces say the same thing.

A single helper, extractPromptCacheTokens, normalizes the three usage
shapes the playground consumes: Anthropic Messages
(cache_read_input_tokens / cache_creation_input_tokens), chat
completions (prompt_tokens_details) and the Responses API
(input_tokens_details). All three producers call it instead of parsing
per surface. Counts that are absent, zero or non-finite are dropped, so
providers without prompt caching render exactly what they render today.
2026-08-13 16:58:14 -07:00
Yassin Kortam
4bc27f1664
fix(auth): carry team grants in lite login session tokens (#36826)
CLI session tokens minted by /sso/cli/poll set team_id and team_alias but
never team_models or team_model_aliases, so the token carried a team with
none of that team's grants. /v1/models bails out to "unrestricted" when both
key_models and team_models are empty and listed the whole proxy, and team
model aliases never resolved because both can_team_access_model and the
pre-call rewrite read team_model_aliases off the token.

The team data was not close at hand: _fetch_cli_sso_team_details projected
full team rows down to team_id and team_alias before they reached the mint.
Widen that projection to include the team's models and its joined alias
table, and populate both fields at mint time.

Also stop writing the user's personal allowlist into the key models slot
when a team is bound, matching virtual-key semantics where a team-bound
credential is governed by the team grant.

Because an empty team grant is itself a real value meaning unrestricted, a
team whose grants cannot be resolved must not be minted as empty: that is
the same "unrestricted" bail-out this fix exists to close. The poll now
refuses to mint when the selected team has no complete cached detail.

That refusal is only safe because a login can no longer be pinned to a team
whose grants will never resolve. Deleting an organization drops its team
rows but leaves the memberships behind, so the login now offers only teams
whose rows still exist, and a lookup that fails outright fails the login
rather than caching a session that silently drops every team.
2026-08-13 16:56:47 -07:00
Yuneng Jiang
0ebbda92d7
style(ui): drop the playground migration's explanatory comments
The repository's comment policy keeps reasoning out of the source, so the
notes on the delete dialog, the tooltip wrapper, and the test query choices
move to the pull request instead.
2026-08-13 16:51:22 -07:00
Yuneng Jiang
615de5d922
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/awesome-shirley-6a1a86 2026-08-13 16:32:16 -07:00
Yuneng Jiang
1c7b49a5ed
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/brave-hermann-3d77ac 2026-08-13 16:21:21 -07:00
Yuneng Jiang
30b933dd5e
test(ui): drop the metric grid class assertion
The assertion pinned the Tailwind track string, which jsdom can never
evaluate: it does no layout, so the test could not fail for the reason
that matters, and its pattern accepted any minmax minimum, staying green
if that minimum changed enough to break the layout outright.

Only a viewport-resize browser test can observe this, which belongs in
tests/e2e/ui rather than a route's unit tests. The responsive behaviour
itself is unchanged; the widths it reproduces are recorded in b341a22339
2026-08-13 16:21:01 -07:00
Mateo Wang
373a0fc506
Merge pull request #36717 from BerriAI/litellm_add_muse_spark_1_2
feat(model_prices): add meta/muse-spark-1.2 and its contributor tier
2026-08-13 16:19:06 -07:00
Yuneng Jiang
9a26da90a4
refactor(ui): migrate playground to shadcn
Replaces antd and Tremor with shadcn primitives across the six route-owned,
form-free playground components: the compare view and its panel, message input
and unified selector, plus the realtime playground and the agent builder.

Markup only, no behaviour change. The characterisation tests added in the
previous commit are untouched here and stay green through the swap.

Adds ui/slider.tsx via the shadcn CLI and retires the six antd
no-restricted-imports suppressions the migration made obsolete.
2026-08-13 15:59:53 -07:00
Yuneng Jiang
b341a22339
fix(ui): keep the guardrails metric cards wrapping at narrow widths
The antd Row and Col the migration replaced never squeezed the summary
cards below their content width; they wrapped onto a second line instead.
Measured on a live dashboard, antd laid out five per row at 1280 and 1024,
then four plus one at 900 and three plus two at 820, never narrower than
about 126px. A fixed grid-cols-5 kept all five on one line and compressed
them to 86px at 820, so the metric values overflowed their cards.

An auto-fit track with a 7rem minimum reproduces antd's wrap points and
card widths exactly at all four measured viewports, and is identical at
1280, so the route's visual baseline is unchanged.

The added test fails against grid-cols-5 and passes against the track
2026-08-13 15:57:03 -07:00
Yuneng Jiang
923a49a6f8
test(ui): pin playground behaviour with library-agnostic queries
Rewrite the playground tests that reached for antd class names so they
locate controls by role, text, placeholder or lucide icon instead. Add
characterisation suites for AgentBuilderView and RealtimePlayground,
which had none, including tab state that must survive a round trip
through another tab.

Every assertion here passes against the current antd components.
2026-08-13 15:56:45 -07:00
Yuneng Jiang
5af59f3d53
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/brave-hermann-3d77ac 2026-08-13 15:30:24 -07:00
ryan-crabbe-berri
262ed530f8
fix(proxy): honor explicit null budget_duration on team and key create + clearable UI dropdowns (#36699)
* fix(proxy): honor explicit null budget_duration over default_team_params on /team/new

* fix(ui): clearable team budget reset with explicit Never resets option

* docs(proxy): align default_team_params docstrings with actual all-teams scope

* fix(proxy): honor explicit null budget_duration on /key/generate over configured defaults

* fix(proxy): keep upperbound_key_generate_params filling explicitly-null key params

* fix(proxy): restrict explicit-null default opt-out to budget_duration
2026-08-13 15:22:11 -07:00
Yuneng Jiang
355ef22257
refactor(ui): drop narration comments from the migrated usage components 2026-08-13 15:22:03 -07:00
Yuneng Jiang
7c9cd2b3df
refactor(ui): migrate guardrails-monitor to shadcn
Replaces the antd Button, Row, Col, Spin and Typography usage in
GuardrailsOverview with the shadcn button, a CSS grid and the house
loading wrapper, and swaps the ant-design icons for lucide equivalents
that the already-migrated GuardrailDetail sibling uses. The busy state
keeps the aria-busy attribute the antd Spin exposed, so the loading
contract is unchanged for assistive tech.

The route's other analyzer-listed file, GuardrailsMonitorView, keeps its
DateRangePickerValue type import because the shared AdvancedDatePicker
prop contract requires it, so there is nothing to migrate there.

Retires the file's now unused no-restricted-imports suppression
2026-08-13 15:21:54 -07:00
yuneng-jiang
0c1355d54a
Merge pull request #36824 from BerriAI/litellm_/concurrent-view-creation
fix(proxy): tolerate a concurrent creator when creating spend views
2026-08-13 15:20:11 -07:00
yuneng-jiang
69792a9529
Merge pull request #36823 from BerriAI/litellm_/e2e-access-control-allowlist
test(e2e): assert the model allow-list permits, not only denies
2026-08-13 15:17:52 -07:00
Yuneng Jiang
e448049163
style(proxy): satisfy ruff format in create_views 2026-08-13 15:04:43 -07:00
Yuneng Jiang
2d7581e32e
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/compassionate-jones-9c0d5c 2026-08-13 15:02:48 -07:00
Yuneng Jiang
b69177712e
refactor(ui): migrate usage to shadcn
Replaces antd and Tremor markup on the usage route with the installed shadcn
base-vega primitives. Behaviour is unchanged: the route's characterisation
tests were rewritten to role and text queries in the previous commit, proven
green against the antd components, and pass through this commit unedited.

Tremor tab panels stayed mounted once rendered, so every migrated TabsContent
and the collapsible model sections in activity_metrics carry keepMounted to
keep view-mode and expansion state alive across tab switches.
2026-08-13 15:02:40 -07:00
devin-ai-integration[bot]
87736a767c
feat(ui): highlight Auto Router in the navbar announcement (#36315)
* chore(ui): remove Agent Platform announcement bell from navbar

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* feat(ui): highlight Auto Router in the navbar announcement

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(ui): open Auto Router docs link in a new tab

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* Revert "fix(ui): open Auto Router docs link in a new tab"

This reverts commit 3be861bafe.

* chore(ui): title the navbar announcement LiteLLM Auto Router

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Mubashir Osmani <mubashir@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-13 21:57:14 +00:00
Yuneng Jiang
c5c98cf706
test(ui): characterise GuardrailsOverview before the shadcn migration
Covers the header and export action, all five summary metric cards, the
table toolbar heading, the evaluation settings modal wiring, the busy
state and the request failure message. Every assertion is role, title or
text based so it holds against both the antd markup and its shadcn
replacement, letting the migration commit land without editing this file
2026-08-13 14:56:58 -07:00
mateo
cbcc3715c6 Merge branch 'litellm_internal_staging' into litellm_add_muse_spark_1_2 2026-08-13 21:54:41 +00:00
Yuneng Jiang
570b34988b
refactor(proxy): type the race helper's db against a Protocol
create_view_tolerating_race took the module's _db = Any. It now takes a
Protocol naming the single operation it calls, so the contract is checkable
at its call sites without retyping the rest of the module.

Kept free of Any deliberately: an earlier version typed the Protocol's
parameters as Any and pushed create_views.py from 26 basedpyright errors to
30 by adding reportExplicitAny. This version measures identical to the
baseline on both create_views.py (26) and utils.py (1355).
2026-08-13 14:53:59 -07:00
Mateo Wang
a4ab511d0b
Merge pull request #36805 from BerriAI/litellm_grok_4_6
feat(xai): day-0 pricing for grok-4.6
2026-08-13 14:49:41 -07:00
Yuneng Jiang
726292720c
fix(proxy): guard every view creation, not just the first and last
Against a real Postgres the previous commit still died on MonthlyGlobalSpend:
only 2 of the 8 creation sites went through the tolerant helper, so the losing
replica re-raised on the first unguarded one and skipped the rest.

The regression test now makes every CREATE lose the race and asserts all 8 are
still attempted, which fails on the partial fix.
2026-08-13 14:41:59 -07:00
Yuneng Jiang
28032eb4c9
test(ui): decouple usage-route tests from antd and Tremor markup
Rewrites the usage route's library-coupled assertions to role and text
queries so they characterise behaviour rather than the widget library that
happens to render it. Every test here is green against the current antd and
Tremor components and is meant to survive a migration unedited.

Drops the wholesale vi.mock of antd, @ant-design/icons and @tremor/react in
UsagePageView, UsageViewSelect and activity_metrics, and drives the real
controls instead. Two of those mocks were hiding behaviour: activity_metrics
asserted panel order through a heading role that only existed because the
mock faked an h2, and the Tremor tab stubs flattened panel selection away
entirely.

Replaces DOM-shape lookups with anchors that do not move: a chart is found
from its own heading rather than a fixed wrapper depth, an active panel is
identified by the inactive markers both tab libraries set, and select options
are matched by text since antd's real options carry no option role.

Adds the missing characterisation test for team_multi_select, and covers the
mount contracts the route depends on: Tremor keeps every tab panel mounted,
and antd Collapse keeps a section mounted once it has been expanded, which is
what preserves the view-mode state a model section owns.
2026-08-13 14:23:26 -07:00
yuneng-jiang
fa498391a4
Merge pull request #36129 from BerriAI/litellm_playground_shadcn
feat(ui): migrate playground chat controls to shadcn
2026-08-13 14:21:38 -07:00
mubashir1osmani
2a7f5f270c Merge remote-tracking branch 'berri/litellm_internal_staging' into litellm_playground_shadcn
# Conflicts:
#	ui/litellm-dashboard/eslint-suppressions.json
2026-08-13 13:54:11 -07:00
Yuneng Jiang
77e64c5d40
fix(proxy): tolerate a concurrent creator when creating spend views
Every replica booting against the same fresh database sees each view as
absent and issues the CREATE. Postgres fails all but one with a
duplicate-object error, and that exception propagated out of
create_missing_views, so every view after the first was never created and
/global/spend* 500'd for the life of the deployment.

Losing that race reaches the desired end state, so treat it as success.
Genuine DDL errors still propagate.
2026-08-13 13:42:57 -07:00
yuneng-jiang
69b0296ca3
Merge pull request #36793 from BerriAI/litellm_shadcn_logs_drawer_header_0813
refactor(ui): migrate SectionHeader and ToolsSection to shadcn
2026-08-13 13:41:36 -07:00
Yuneng Jiang
ed01f7316b
test(e2e): assert the model allow-list permits, not only denies
Every case in TestAccessControl asserted that something was refused. A gateway
that denied the allow-listed model too would have passed all of them, so the
suite could not tell "denied correctly" from "broken outright".

Adds the positive half: a key allow-listed for gemini-2.5-flash can call it and
gets back a real completion rather than a 200-wrapped error.

Also tightens the unknown-model case. It accepted any valid JSON, so a bare
"{}" or even "null" satisfied it. It now requires the OpenAI-shaped error
envelope with a message a client can actually surface, parsed through a typed
model instead of json.loads.
2026-08-13 13:37:31 -07:00
Yuneng Jiang
1dc0ea3d11
Merge branch 'litellm_internal_staging' into litellm_shadcn_logs_drawer_header_0813 2026-08-13 13:33:00 -07:00
yuneng-jiang
160548d40b
Merge pull request #36739 from BerriAI/litellm_/quirky-mcnulty-e432c4
refactor(ui): migrate TruncatedValue and OutputCard to shadcn
2026-08-13 13:31:55 -07:00
Mateo Wang
c1310de342
Merge pull request #36763 from BerriAI/litellm_decrease_anys_fable7
refactor: replace Any with precise types across responses, proxy, and llms modules
2026-08-13 13:24:47 -07:00
Yuneng Jiang
9f947a7406
Merge branch 'litellm_internal_staging' into litellm_/quirky-mcnulty-e432c4 2026-08-13 13:23:51 -07:00