The core now decides when an over-budget team member may fall back and walks
the router's fallback targets in order, skipping the requested model, through
its own TeamMemberStep and driver. The proxy handler only reads the targets
and vets each one, so _try_team_member_model_budget_fallback and its
per-model helper are gone
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The core now owns which models get checked, when an over-budget key may fall
back to its budget_fallbacks, and that the user check sees the rerouted model.
The virtual-key chain runs it inline, custom auth through check_model_budgets
and JWT through check_user_model_budgets, so the three paths share one walk.
A budget refusal is now a ModelBudgetExceeded denial that the proxy turns back
into the same BudgetExceededError
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The core now decides the soft budget alert, when per-model budgets run, the
team and project context load, the proxy budget alert and the missing-token
denial, so the builder only projects the grant. One projection serves both
the request builder and internal jobs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The key checks that ran first in validate_resolved_virtual_key now run in
the Python core, in the same order: blocked key, model access, deactivated
owner, budget exemption, team member budget, expiry, budget alerts and the
key's own max budget or throttle. Lookups, counters and alerts are effects
the proxy answers, and internal jobs run the same checks through
start_resolved_key.
The soft budget, per-model budgets and the team, project and global spend
lookups stay in _finish_virtual_key_auth for a later pass. The source-shape
tests now read the functions that replaced validate_resolved_virtual_key
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Python core now decides the whole virtual key resolution path. It asks
the proxy to resolve the end user, the presented key (preresolved, cached or
UI login), evict an expired cached admin key and load an uncached key from
the DB, each as a typed effect with its own continuation. It decides the
admin key expiry, master-key-only routes, the no-DB case and the sk- prefix
check itself, so the builder no longer has a legacy fallback.
The budget and team checks in validate_resolved_virtual_key still run after
Allow(VirtualKey) and move into the core in later passes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the AuthCore interface in litellm._auth and a Python core that decides
the no-master-key, missing key, malformed key, /user/auth and master key
cases. Everything else defers to the legacy builder. The builder projects
the outcome into UserAPIKeyAuth or the existing error contract, and the
end-user resolution it shared with the master key path is extracted.
A master key request no longer inherits end-user limits from an earlier
master key request, since the master key is no longer read back from the
key cache
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Key regeneration still called is_master_key with the old api_key/_master_key
keywords and raised TypeError. Also restores the str contract of get_api_key
and drops the duplicate hashlib imports left in proxy/utils.py.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move scheme stripping, key-source precedence, websocket key selection,
hash_token and is_master_key into litellm/_auth as the interface the Rust
auth port will mirror. Authorization schemes now match case-insensitively
like FastAPI's HTTPBearer. Pass-through endpoint keys join the precedence
table instead of a separate fallback, and the dead custom-header helper
plus the duplicated hash_token and is_master_key bodies are gone
* fix(zscaler_ai_guard): scan only the last user turn on requests
* fix(zscaler_ai_guard): keep scanning A2A requests and refuse scan_only_tool_results
* fix(zscaler_ai_guard): join the last user turn's text parts with spaces like before
* fix(zscaler_ai_guard): keep scanning tool results when scan_only_tool_results is set
* fix(zscaler_ai_guard): scan the latest user turn when assistant or tool messages follow it
* fix(zscaler_ai_guard): skip the scan when the latest user turn is only whitespace
A blank latest user turn was sent to Zscaler on its own, which answers
Content is empty, so the proxy returned 500 where main returned 200
---------
Co-authored-by: Arnav Maiti <amaiti@zscaler.com>
Moves the English left in the Aria assistant, the MCP tool permission
groups, the shared chat composer, the Beta badge, the user banner and
the metadata key fields onto react-i18next. English output is unchanged.
Text that Aria sends to the model (system prompt, tool descriptions,
tool results and usage chart payloads) stays English byte for byte.
Where the same string is also shown on screen, a display map keyed by
the operation name or by the chart's English value translates it at
render time, and the model copy is left alone.
Compliance framework and category names, the Compare endpoint labels, the
Decisions presets and schema messages, chat metrics, MCP events, reasoning
toggle, conversation date groups, model filters and the MCP boolean argument
labels now resolve through en.json. Ids, stored values and text sent to a
model are unchanged
Constants and option lists on the keys, teams, agents, budgets, cost
tracking, router settings and vector store pages now hold message keys,
and the code that renders them translates. Values, ids, sort keys and
payloads are unchanged, and lookups keyed by server values check
Object.hasOwn first
Five tests now resolve the expected English through i18n.t instead of
reading the constant directly
Moves the leftover English in the sidebar, page descriptions, account
menu, usage card and a handful of shared widgets into en.json. Option
lists and label maps now hold message keys and are translated where they
render, while every option value, id and stored setting stays the same
string. Lookups keyed by a server value check Object.hasOwn first
* refactor(ui): move remaining models text onto i18n
Moves the leftover English on the models pages, mostly labels and hints
held in constants, onto react-i18next. Constants now hold message keys and
the code that renders them translates. Where a string is both a value and
a label (tier names, health check sentinels), the English value stays for
comparisons, sorting and payloads, and a separate label key drives display.
Lookups keyed by server values check Object.hasOwn first.
* refactor(ui): translate the tier name in display name inputs
Logs and usage option lists, filter chip labels and label maps now hold
message keys that their readers translate at render time. Tile titles, the
"Claude (unspecified)" agent label and the endpoint chart categories stay
English ids and get display maps keyed by them. Lookups keyed by URL or
server values check Object.hasOwn first.
* fix(anthropic): report temperature/top_p as supported only when the model keeps them
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(vertex_ai): accept the generic unsupported-param message for Claude batch rows
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>