* test(ui): cover the authorization MCP auth type in create and edit forms
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(ui): expose the authorization MCP auth type in create and edit forms
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>
* fix(proxy): build proxy-only failure logs from an allowlist and ignore request-time GCS credentials
* fix(proxy): drop caller metadata from proxy-only failure logs
metadata and litellm_metadata leave the proxy-only failure-log allowlist, so a rejected request can no longer point its failure log at its own Langsmith or Langfuse host through nested metadata.
* fix(proxy): keep allowlisted metadata in proxy-only failure logs
* test(proxy): isolate proxy-only failure log metadata tests
* fix(logging): ignore non-list request tags when building the logging payload
A guardrail-rejected request with metadata tags set to a non-list value crashed
the standard logging payload, so its spend row lost model attribution.
* fix(proxy): keep router attribution and drop unauthenticated tags in proxy-only failure logs
A request rejected before routing now logs the configured deployment and model group even when its metadata or litellm_metadata carries its own values. Requests rejected at auth no longer write caller tags into failure logs and tag spend.
* fix(proxy): always strip client guardrail info and mirror failure attribution into litellm_metadata
allow_client_pricing_override no longer keeps a caller-supplied standard_logging_guardrail_information on the chat or pass-through paths, since its guardrail_cost is billed. Proxy-only failure logs now also carry key and team attribution in litellm_metadata.
* refactor(proxy): keep the proxy-only failure-log fixes inside the type gates
Types the picked helpers so basedpyright and the type-discipline gate stay at main's counts. No runtime change.
* fix(proxy): keep the WS frame guardrail-info strip and string interaction tags as sent
The guardrail-info key left the pricing strip list, so the Responses WS frame guard now drops it by name. get_request_tags no longer raises on string tags, so background interaction polling checks for them before keeping them as sent.
---------
Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
* fix(bedrock): set gpt-6.1-terra max_input_tokens to the 1,050,000 Bedrock card context window
* fix(bedrock): set gpt-5.x and gpt-6 max_input_tokens to the card context window minus max output
* fix(bedrock): add Mantle token_count_model to bedrock_mantle claude-opus-5-5 rows
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
---------
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: kerry <kerry@berri.ai>
* test(proxy): cover enterprise spend permission errors on key and user creation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(proxy): return 403 naming the Enterprise licence for get_spend_routes without a licence
Co-authored-by: er-s-an <92594860+er-s-an@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(proxy): narrow parsed permissions before checking spend access
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(ci): allow full-history database checkout to finish
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: er-s-an <92594860+er-s-an@users.noreply.github.com>
* test(logging): cover extra spend tag header casing
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(logging): match spend tag headers case-insensitively
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>
* feat(proxy): refuse migrations that existing rows would make fail, before the first one runs
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(migrations): start the serving-proxy preflight case from a database without the api_key index
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(proxy): type the preflight count rows without casts
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* style(proxy): ruff format the db preflight flag
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* style(proxy-extras): keep the extras files at their existing formatting
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor(proxy-extras): type the ledger query and the reader pid so the type gate holds
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(proxy): declare the preflight report type where the extras package may be absent
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(proxy): suppress the optional-extras unknown on the preflight report variables
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(proxy): suppress the optional-extras unknown on the preflight import
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(proxy): return a typed preflight report when the extras package is unknown
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* style(proxy): sort the preflight import block
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(proxy): mark the preflight report binding Final
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(proxy): size the whole btree entry in the row check and name the flag for what it does
The index check now lays out each row's entry the way index_form_tuple does (tuple header, null bitmap, every indexed column at its alignment, rounded to 8) and compares it with BTMaxItemSize for the server's block_size, so a key that passes octet_length > 2704 but still fails the (api_key, startTime) index is caught. --db_preflight becomes --check_migrations_against_existing_data, db_preflight.py becomes migration_data_checks.py and the timeout env var LITELLM_MIGRATION_DATA_CHECK_TIMEOUT
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>
* feat(bedrock): price native guardrailConfig trace usage into spend and x-litellm-response-cost
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(integration): bill native Bedrock guardrail trace usage on chat, responses and pass-through
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(streaming): record the Bedrock guardrail trace of a streamed metadata chunk on the logging object
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(bedrock): apply guardrailConfig on /v1/messages and price its trace, record the stream trace on both builder paths, redact the native guardrail_response
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor(bedrock): validate the guardrail trace with one pydantic model
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(bedrock): record the native guardrail entry when litellm_params metadata is None
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(bedrock): import the renamed messages invoke transformation module
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(bedrock): skip native guardrail billing on cache hits and redact the trace with message logging off
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(bedrock): walk the guardrail trace iteratively when redacting it
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor(bedrock): record the native guardrail trace where the Bedrock response is parsed
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(bedrock): type the native guardrail trace fixtures and locals
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>
* refactor(mcp): drop the experimental label from the MCP server and client paths
Move litellm/proxy/_experimental/mcp_server to litellm/proxy/mcp_server and litellm/experimental_mcp_client to litellm/mcp_client, with the mirrored tests moved under tests/unit/proxy/mcp_server and tests/unit/mcp_client. Both old packages stay as shims that warn with DeprecationWarning, re-export the new package's public names and alias every submodule in sys.modules so deep imports keep resolving to the same objects. The OpenAPI docs gate now puts the merge base's enterprise package on PYTHONPATH so its base counts do not mix the checked-out enterprise code with the base litellm tree
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* ci(mcp): keep tests/unit/proxy/_experimental as a sharded root for the shim tests
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(mcp): alias namespace subpackages and bind attributes in the deprecated MCP shims
pkgutil.walk_packages skipped mcp_server/auth because it has no __init__.py, so old imports of litellm.proxy._experimental.mcp_server.auth.* failed, and sys.modules entries alone left litellm.experimental_mcp_client.tools unreachable as an attribute. Walk the package on disk and setattr each alias on its old parent.
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>
* fix(langfuse_otel): derive trace-level name, input, output and tags on the generation span
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(langfuse_otel): keep every reasoning summary in the derived observation output
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(langfuse_otel): leave joined traces untouched by derived trace fields
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(langfuse_otel): restore preset cache key fallback and type the derived-field helpers
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(langfuse_otel): keep trace tags off joined traces entirely
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(langfuse_otel): tolerate out-of-band upstream requests and add sink outage chaos cell
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(integration): build the langfuse rig config without mutating the loaded yaml
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor(langfuse_otel): flatten output items with itertools.chain to satisfy LIT014 budget
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(langfuse_otel): type the _RecordingSpan and _emitted unit helpers
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(langfuse_otel): keep joined-trace tags, mask trace io, leave v2 trace io to the root
Joined traces (existing_trace_id) keep the caller tags they carried before,
and only the derived trace fields are skipped for them. mask_input and
mask_output now redact the derived trace input and output, matching the
vanilla Langfuse callback. The v2 mapper derives the trace name only,
because the root observation already carries the trace input and output
there. Uses the public preset cache key helper, moves imports to module
top, restores the original formatting of the unit test file, and adds
integration cells for the v2 llm_only scope and SDK sync/async calls.
* fix(langfuse_otel): split string caller tags the way Langfuse reads them
A caller tags value given as a comma list or a JSON array string (body
metadata.tags or the langfuse_tags header) used to reach Langfuse raw,
where ingestion split it into separate tags. Merging it with the derived
tags kept it as one tag, so parse it the same way before the merge
* test(otel): expect langfuse.trace.name on the v2 langfuse_otel generation span
* fix(langfuse_otel): read string mask flags the way the classic callback does
The langfuse_mask_input / langfuse_mask_output headers arrive as strings,
so "false" redacted the derived trace io. Parse them with str_to_bool and
fall back to truthiness, as the classic langfuse callback does
* fix(langfuse_otel): derive trace fields only on traces litellm starts
A litellm span that joins a trace an app or caller started (inbound
traceparent, the app's active span, a caller-provided parent span) no
longer gets a derived trace name, input, output or tags, like a request
joining an existing_trace_id. Langfuse applies the later-starting span's
trace update, so the derived values overwrote the app's own trace name
and io.
OTel v2 derives the name on the request root only when it has no parent,
and the generation span keeps main's caller-only trace name.
* test(langfuse_otel): keep main's OTel v2 generation key set in the arize family cell
The OTel v2 generation span no longer carries a derived langfuse.trace.name,
so the pinned key set goes back to main's.
* fix(langfuse_otel): name the OTel v2 request root once, from the request's own call
The v2 Langfuse logger re-derived langfuse.trace.name on the request root
for every LLM call in the request. A post_call llm_as_a_judge guardrail's
judge call replaced the caller's trace_name on the root with
litellm-acompletion, and with another v2 callback (otel, arize_phoenix)
listed before langfuse_otel that vendor's root span gained
langfuse.trace.name on every request.
The derived name now fills only an unnamed root this logger's provider
started, and never comes from a call litellm makes for its own features.
A caller trace_name still names the root on every call, as on main.
* fix(langfuse_otel): keep the derived trace fields from pushing other attributes off a full span
The derived trace name, tags, input and output were written after the OpenInference attributes with no room
check, so a span near the SDK's attribute limit (about 34 tools at the default 128) evicted keys main
exported, such as openinference.span.kind, metadata and llm.model_name, and raised the dropped count.
They are now written last and only into the room the limit leaves next to the error attributes a failed
call adds, so a full span exports what it would without them.
* test(langfuse_otel): give the full-span cells' derived request a caller trace id, as the joined one's traceparent does
* chore(langfuse_otel): drop the docstrings and comments the house rule disallows and type the new tests' parameters
* test(langfuse_otel): set the span attribute limit the full-span tests run at and keep Final locals out of the app-trace loop
---------
Co-authored-by: yucheng <yucheng@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: yucheng-berri <293926326+yucheng-berri@users.noreply.github.com>
* refactor(anthropic): rename llms/anthropic/pass_through to llms/anthropic/messages
Move the unified /v1/messages code out of a directory called pass_through, since it is not the
passthrough feature. The inner messages sub-package becomes native, and the Vertex AI partner
model experimental_pass_through package becomes messages. The old packages stay as import shims
that warn once and alias every submodule in sys.modules, so old deep imports still resolve
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor(anthropic): keep Final variables out of loops in the rename shim
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(anthropic): match the warning text in the rename shim test
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor(anthropic): resolve old pass_through imports lazily through a meta path finder
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor(anthropic): mark the alias loader spec restore for the type discipline gate
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* style(anthropic): format the renamed package shim
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* style(anthropic): keep the rebind-ok marker on the spec restore line
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor(anthropic): carry the new package search path on alias specs
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(anthropic): declare the shim test locals Final
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>
* feat(decisions): support LM Studio decision models
Co-Authored-By: Codex <noreply@openai.com>
* fix(ci): resolve OSV dependency findings
Upgrade the extension MSAL dependency and document expiring exceptions for unused Windows filelock APIs while Python 3.10 remains supported.
Co-Authored-By: Codex <noreply@openai.com>
* Clean up ignored vulnerabilities in osv-scanner.tomlchore: remove unrelated dependency and scanner changes
Removed ignored vulnerabilities related to Windows issues and Python version compatibility.
* chore: remove unrelated dependency and scanner changes
* chore: remove unrelated dependency and scanner changes
---------
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: ishaan-j-berri <ishaan.j@berri.ai>
gpt_5_transformation.py becomes gpt_reasoning_transformation.py (OpenAI and Azure),
the Bedrock anthropic_claude3_transformation.py files become anthropic_claude_transformation.py,
anthropic_claude2_transformation.py becomes anthropic_legacy_text_completions_transformation.py,
and vertex_ai_partner_models/llama3 becomes vertex_ai_partner_models/llama. Class and symbol
names are unchanged.
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(rust): add circuit-breaker crate and guard redis-client with it
* fix(circuit-breaker): ignore stale probe drops
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(refuseless): add provider and model pricing
* feat(refuseless): expose provider in Add Model catalog
* test(refuseless): verify model input trimming after upstream fix
* fix(refuseless): exclude unavailable free model from catalogs
* feat(abliteration): add model pricing and capabilities
* feat(abliteration): expose provider in Add Model catalog
* chore(abliteration): keep provider entries independent of other additions
* fix(abliteration): correct reasoning capabilities and verify input trimming
* fix(prometheus): count provider-side 401s in LLM failure and deployment metrics
The invalid virtual key skip no longer applies to an error the LLM provider
returned while the deployment was called with its own credential, so a 401
for a bad deployment credential increments litellm_llm_api_failed_requests_metric,
litellm_deployment_failure_responses and litellm_deployment_total_requests and
marks litellm_deployment_state as a partial outage again. Proxy-gate rejections
and a failing credential that belongs to the caller (a rejected per-user
credential, an api_key sent with the request, a per-user GitHub Copilot
session) keep the skip
* fix(prometheus): keep a caller's own Anthropic OAuth token failure out of the deployment metrics
A provider 401 on an Anthropic OAuth token the caller forwarded through the proxy is the caller's credential
failing, so it stays out of the deployment failure and outage series like a caller-supplied api_key. Adds
integration cells for an Anthropic deployment's own key, the forwarded caller OAuth token and a direct SDK
call that brings its own key
* test(prometheus): pin how a caller's own key or Authorization header on a deployment is counted
An SDK Router call that passes its own api_key is counted against the one-off deployment the router builds for that key, so the operator deployment keeps only its own failure. A provider 401 on an Authorization header the caller sends through the proxy counts against the deployment, as on v1.80.12
* fix(prometheus): keep caller-sent provider credentials and token-exchange 401s out of deployment metrics
A caller can send its own provider credential in the request body, such as
azure_ad_token, azure_scope, the Azure Entra app fields, watsonx token,
gigachat_access_token, OCI keys, AWS keys or Vertex credentials, at the top
level or inside extra_body. A provider 401 on that credential is the caller's
failure, so it stays out of the shared deployment's failure, request,
LLM-failed and state series, as on main. A token-exchange deployment trades the
caller's identity token on every call, so its 401s stay out as well, matching
the router cooldown.
* test(prometheus): Final locals, precise helper types and one for per comprehension in the new test helpers
* test(prometheus): pin that a provider 401 at a caller-sent api_base counts against its one-off deployment
* fix(prometheus): keep a provider 401 on caller-sent headers out of deployment metrics
A caller can override the deployment's credential with headers it sends in the
request body: headers or provider_specific_header, or an Authorization, api-key,
x-api-key, x-goog-api-key or Ocp-Apim-Subscription-Key entry in extra_headers.
A provider 401 on such a request is the caller's failure, so it stays out of the
shared deployment's failure, request, LLM-failed and state series, as on main.
* fix(prometheus): skip a provider 401 only when the caller's headers carry a credential
The proxy now records headers, extra_headers or provider_specific_header in
credential_fields only when they name a provider credential header
(Authorization, api-key, x-api-key, x-goog-api-key, Ocp-Apim-Subscription-Key),
the same way api_key is recorded. A caller that sends a plain header such as a
trace id still has a provider 401 on the deployment's own key counted against
the deployment.
* fix(prometheus): stamp credential_fields after the proxy forwards the caller's headers
A provider credential header the proxy forwards from the caller's HTTP request
(forward_llm_provider_auth_headers + forward_client_headers_to_llm_api) lands in
data["headers"] after proxy_server_request is built, so the stamp missed it and a
401 on that caller credential was counted against the deployment. Compute the
stamp after the header forwarding steps and pin both forwarded cases.
* fix(prometheus): skip a provider 401 when the caller sends any header or an OpenAI organization
The proxy now records headers, extra_headers or provider_specific_header in
credential_fields whenever the caller sends or the proxy forwards any header
there, and records organization when the caller sends one in the body or as a
forwarded OpenAI-Organization header. A forwarded header can be a gateway key
such as x-portkey-api-key or an OpenAI-Project id, and a wrong organization
gets a 401 from OpenAI, so these 401s stay out of the deployment metrics as on
main instead of marking a healthy deployment as a partial outage.
* fix(prometheus): ignore the user information the proxy adds when stamping caller headers
With add_user_information_to_llm_headers on and header forwarding enabled, the
proxy adds x-litellm-user_api_key_* headers to the forwarded headers. Those
carry the proxy's own key and user details, not the caller's, so they no longer
make a request look caller-scoped, and a provider 401 on the deployment's own
key on such a request is counted.
* fix(prometheus): skip a 401 raised before the provider is called or at the caller's own endpoint
A deployment with no key of its own fails with LiteLLM's local "Missing
Anthropic API Key" 401 before any provider call, and a caller who sends
aws_bedrock_runtime_endpoint (or another provider endpoint field) can get a
401 from their own gateway. Both were counted against the shared deployment
and marked it as a partial outage, where main skipped every 401.
Count a 401 only once the provider was called (api_call_start_time is set),
and treat caller-sent provider endpoint fields like caller credential fields.
* fix(prometheus): count the deployment's own 401 on requests that carry only anthropic-version or anthropic-beta
The Anthropic SDK sends anthropic-version on every request, and the proxy copies
anthropic-version and anthropic-beta into provider_specific_header for Anthropic,
Bedrock and Vertex. Both were treated as caller headers, so a 401 on an Anthropic
deployment's own key from any Anthropic SDK client stayed out of the deployment
metrics.
These two headers only pick the API version and beta features. Anthropic answers
a bad anthropic-version or an unknown anthropic-beta with a 400, never a 401, so
they cannot turn the deployment's own key into a 401 and no longer mark the
request as carrying a caller header.
* test(prometheus): read and write the owned proxy's own database in the expired-key and MCP cells
Since #47213 an owned proxy boots on a private database, so the expired-key update and the MCP guardrail row read now go through the gateway's database_url instead of the worker's.
* fix(prometheus): keep credential_fields as main stamps it and give Prometheus its own caller_credential_fields
credential_fields tells the Rust OCR bridge which stripped body fields the
caller sent. Repurposing it for the Prometheus caller-credential check changed
its value (organization and extra_headers added, anthropic-version-only
headers dropped). Restore main's stamp unchanged and stamp the Prometheus
classification under caller_credential_fields, which only Prometheus reads.
* fix(prometheus): skip a provider 401 on a stored credential the caller picks by litellm_credential_name
A request body litellm_credential_name swaps the deployment's stored
credential for one the caller chose, so a 401 on it is the caller's, not the
deployment's. Treat it like the other caller credential fields so it no longer
marks a healthy shared deployment as a partial outage.
---------
Co-authored-by: yucheng-berri <293926326+yucheng-berri@users.noreply.github.com>
* fix(ui): show the budget period date range instead of "cycle" on team member spend
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(ui): derive the budget period start in UTC before showing it in local time
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(ui): keep clock times on sub-day budget periods and restore the total spend lower bound wording
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
---------
Co-authored-by: joshua <joshua@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(router): track every router for price data reloads so DB-only deployments keep custom pricing
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(router): register the router for reload replay only once model_list exists, and type the regression test
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
---------
Co-authored-by: joshua <joshua@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(team): keep the team reset schedule when a temp budget increase is set on a member inheriting the team default
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(integration): expect the temp-only member row to carry the team default cap
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
---------
Co-authored-by: joshua <joshua@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(router): serve a team's wildcard deployment before a proxy-wide wildcard
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(router): keep the wildcard precedence helpers free of partially typed locals
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(router): call each pattern router once in the wildcard precedence helpers
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test(ptu): a team's wildcard reservation serves beside a proxy-wide catch-all
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
---------
Co-authored-by: joshua <joshua@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(ui): budget period tooltip on key, team, user and org spend tiles
Adds a shared BudgetPeriodTooltip to the four detail-view spend tiles showing the current budget period, max budget, reset interval and spend so far, and makes organization create schedule budget_reset_at and organization info return it
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(ui): give the budget period tooltip trigger its own aria label
The default SimpleTooltip trigger shares the question-circle label with InheritedBudgetHint, which broke the key budget display tests that count that icon
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(ui): match the proxy's budget window rules in the period tooltip
30d and Nmo now span calendar months like get_budget_window_start, the arithmetic runs in UTC so a viewer's DST change cannot shift the start, the hourly/daily/weekly/monthly aliases the proxy accepts are normalized before parsing, and spend without a duration reads as lifetime spend
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
---------
Co-authored-by: joshua <joshua@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>