Commit graph

48449 commits

Author SHA1 Message Date
Joshua Valluru
da61fa3564 fix(mcp): preserve existing relay discovery identifiers 2026-09-11 17:11:42 -07:00
Joshua Valluru
17863fa5cf fix(mcp): match per-server OAuth metadata issuers 2026-09-11 17:05:35 -07:00
yucheng-berri
e4706fa409
fix(hide-secrets): restore credential coverage lost to the 4.5 entropy limit (#40190)
* fix(hide-secrets): restore credential coverage lost to the 4.5 entropy limit

Shannon entropy is bounded by log2(length), so the 4.5 limit #39879 shipped
cannot score any value shorter than 23 characters, and it catches a random
32-character base64 credential only about two thirds of the time. A line like
REDIS_PASSWORD=aB3dE6gH9jK2mN5p therefore reaches the provider in the clear.

Add a keyword plugin that yields the credential-shaped value assigned to a
credential-named key, reusing detect_secrets' own maintained denylist so
camelCase, snake_case and SCREAMING_CASE all work with no local word list, and
re-run the assignment-quoting transform detect_secrets skips once its first
pass has matched.

The entropy limits are untouched, so #39879's false-positive fix still holds.

* fix(hide-secrets): read the assignments in a prompt that is mostly prose

configparser aborts the whole parse on the first line it cannot read, so a
message like "Here is my config, can you review it?" followed by
REDIS_PASSWORD=... lost every assignment to that one prose line. Hand the
parser only the lines it can read, dedent the assignments inside a pasted
config, and keep each key distinct by line number so a config naming api_key
once per model keeps every value instead of only the last.

* fix(hide-secrets): drop the plugin docstrings and pin the block-scalar shapes

* fix(hide-secrets): keep a comment or an indented header from closing an open value

* fix(hide-secrets): drop the explanatory comments from the new scan helpers

* fix(hide-secrets): accept punctuation in a credential value

The value filter only allowed the URL-safe Base64 alphabet, so a password
such as hunter2!brahms or p@ssw0rd!2026 passed through unredacted while
the upstream keyword plugin had already matched it. The filter now rejects
only whitespace and brackets, which keeps function calls, subscripts and
sentences out while letting symbol-heavy passwords through.

* fix(hide-secrets): redact every credential on a line and skip timestamps and plain urls

replaces the inherited first-match scan with finditer over every keyword
match, drops iso 8601 timestamps and userinfo-free urls from credential
values, and threads the parser's open-option state through
itertools.accumulate instead of rebinding it

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

* fix(hide-secrets): scan the first token of an assignment and ignore surrounding punctuation

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

* refactor(hide-secrets): drop the unreachable configparser error fallback

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

* fix(hide-secrets): keep prose after a credential key out of the keyword detector

A bare value followed by ordinary words (secret_sauce: Worcestershire sauce)
is prose, so the synthetic assignment is only built when the value stands
alone or is followed by a shell operator, comment, or another assignment

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

* fix(hide-secrets): scan the first token of shell-style assignments regardless of what follows

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

* fix(hide-secrets): keep spaced assignments in scope when shell text follows the value

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

* test(hide-secrets): drop docstrings that restate the test names

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

* fix(hide-secrets): stop reading a comparison operator as a trailing assignment

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

* fix(hide-secrets): keep dashed flags as assignment trailers

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-09-11 16:49:48 -07:00
devin-ai-integration[bot]
359b7a8489
feat(rust): count tiktoken cl100k_base admission tokens in Rust (#40777)
* feat(rust): count tiktoken cl100k_base admission tokens in Rust

The Rust admission token counter only had the Anthropic tokenizer, so every
other model (OpenAI gpt-4 family, Azure, Gemini, Bedrock non-Claude, Mistral)
tokenized with tiktoken on the Python inference worker.

Add an exact cl100k_base counter to litellm-token-counter: the vendored rank
file (base64 token / rank lines, the bytes Python's tiktoken uses) is parsed
into a byte-level BPE model and the cl100k split pattern is a handwritten
scanner over the shared Unicode classes, so no regex engine runs per request.
Both tokenizers share the message, tool and reply-priming accounting.

The PyO3 TokenCounter gains a from_cl100k_ranks constructor; Python reads the
rank file and passes it in, the way claude_json_str already works. The bridge
selects the counter through the same predicates litellm.token_counter uses
(huggingface_tokenizer_kind, openai_tokenizer_encoding), declines o200k_base,
downloaded HuggingFace and custom tokenizers to Python, and budget reservation
counts once per distinct tokenizer a request names.

The legacy gpt-3.5-turbo-0301 message accounting (4 per message, -1 per name)
stays in Python: the selector declines it through the predicate token_counter
itself uses.

* feat(rust): count tiktoken o200k_base admission tokens in Rust (#40794)

Add a handwritten o200k_base split scanner and TokenCounter::from_o200k_ranks
next to the cl100k_base counter, sharing MergeRanks and the request
accounting. The Python bridge selects it when openai_tokenizer_encoding
names o200k_base, so gpt-4o, gpt-4.1, gpt-5, o1/o3/o4 and chatgpt-4o
requests stop tokenizing on the Python worker under LITELLM_RUST=true

Co-authored-by: yassin <yassin@berri.ai>

---------

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 23:47:05 +00:00
devin-ai-integration[bot]
d78861bb29
fix(guardrails): stop logging the request payload as guardrail_response on pre_call hooks (#39699)
* fix(guardrails): stop logging the request payload as guardrail_response on pre_call hooks

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

* fix(guardrails): snapshot pre_call request before the hook so in-place edits log as mask

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

* fix(guardrails): log non-mapping pre_call hook results as mask instead of raising

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

* fix(guardrails): treat legacy functions and tool_choice edits as mask in pre_call logging

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

* fix(guardrails): log a pre_call rejection string as is instead of "mask"

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

---------

Co-authored-by: shivam <shivam@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: yucheng <yucheng@berri.ai>
2026-09-11 16:44:56 -07:00
ryan-crabbe-berri
4e9d414603
Merge pull request #40748 from BerriAI/litellm_fix_gemini_reasoning_effort_400
fix(vertex_ai): return 400 for invalid reasoning_effort instead of 500
2026-09-11 16:31:16 -07:00
yujonglee
83ab0113f0
feat(ocr): add Vertex DeepSeek adapter and remove legacy OCR pipeline (#40509)
* feat(ocr): add Vertex DeepSeek adapter

* fix(ocr): restore stacked CI coverage

* style(ocr): apply workspace rustfmt

* fix(ocr): deduplicate stacked gateway error mapping

* test(ocr): keep response format checks at dispatch

* fix(ocr): initialize gateway input provenance

* refactor(ocr): preserve DeepSeek extra params

* refactor(ocr): align Vertex DeepSeek preparation

* fix(gateway): drop removed OCR credential error variant

* fix(ocr): fail closed for deferred hooks and Vertex destinations

* fix(ocr): preserve DeepSeek credential provenance
2026-09-11 16:22:57 -07:00
yujonglee
b8928170e9
feat(ocr): add Vertex Mistral adapter (#40507)
* feat(ocr): add Vertex Mistral adapter

* test(ocr): validate Vertex credentials at adapter boundary

* refactor(ocr): preserve Vertex Mistral extra params

* refactor(ocr): align Vertex authentication lifecycle

* refactor(ocr): keep Vertex preparation behind bridge

* fix(ocr): protect Vertex credential destinations

* fix(auth): restrict request Vertex token endpoints
2026-09-11 16:22:56 -07:00
yujonglee
0dd5e6e289
feat(ocr): add Reducto legacy and v3 adapters (#40535)
* feat(ocr): add Reducto adapters

* fix(ocr): decline missing Reducto credentials

* fix(ocr): map Reducto credentials in gateway errors

* test(ocr): keep Reducto coverage at SDK boundary

* test(ocr): remove stale gateway Reducto cases

* fix(ocr): stop retaining Reducto responses by default

* refactor(ocr): preserve Reducto extra params

* refactor(ocr): adopt request preparation contract

* fix(ocr): preserve provider model passthrough

* fix(ocr): reject unknown Reducto models

* fix(ocr): preserve Reducto provider options
2026-09-11 16:22:56 -07:00
yujonglee
b544f2244b
feat(ocr): add Azure Document Intelligence adapter (#40534)
* feat(ocr): add Azure Document Intelligence

* fix(ocr): decline missing Document Intelligence credentials

* fix(ocr): map Document Intelligence credentials

* test(ocr): expose Azure transport to adapter tests

* fix(ocr): preserve native responses through Rust bridge

* feat(core): add URL query pair completion

* fix(ocr): declare Document Intelligence native responses

* fix(auth): preserve Azure credential provenance in OCR adapters

* refactor(ocr): use shared native response handling

* refactor(ocr): preserve Document Intelligence extra params

* refactor(ocr): adopt request preparation contract

* refactor(ocr): keep native response handling behind bridge

* fix(ocr): prevent credential-bearing polling redirects

* fix(ocr): update Azure auth imports

* fix(ocr): bound Document Intelligence polling rate

* fix(ocr): preserve proxy credential provenance

* test(ocr): assert native bridge format support
2026-09-11 16:22:55 -07:00
yujonglee
5e23db8e03
feat(ocr): add Azure Mistral adapter with native authentication (#40502)
* feat(ocr): move Azure credential resolution to Rust

* fix(auth): keep shared primitives warning-free

* fix(auth): preserve missing key provider errors

* fix(auth): enforce Azure input provenance

* fix(ocr): preserve proxy credential provenance
2026-09-11 16:22:55 -07:00
ryan-crabbe-berri
d70e64d973
Merge pull request #40644 from BerriAI/litellm_logs_last_page_jump
fix(ui): jump straight to the last Request Logs page instead of advancing one page
2026-09-11 16:17:56 -07:00
yuneng-jiang
22c60ef9e7
Merge pull request #40786 from BerriAI/litellm_responses-smoke-test
Some checks failed
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Waiting to run
Unit Tests: Proxy DB Operations / auth-checks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / budgets (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / custom-logging (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / db-and-spend (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / key-generation (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / logging-misc (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-runtime (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-server-core (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-utils (push) Blocked by required conditions
Unit Tests / misc (push) Waiting to run
Unit Tests / caching-local (push) Waiting to run
Unit Tests / core-utils (push) Waiting to run
Unit Tests / enterprise-package (push) Waiting to run
Unit Tests / enterprise-routing (push) Waiting to run
Unit Tests / integrations (push) Waiting to run
Unit Tests / All Other Providers (push) Waiting to run
Unit Tests / Vertex AI (push) Waiting to run
Unit Tests / proxy-auth (push) Waiting to run
Unit Tests / proxy-endpoints (push) Waiting to run
Unit Tests / proxy-extras (push) Waiting to run
Unit Tests / proxy-infra (push) Waiting to run
Unit Tests / proxy-server (push) Waiting to run
Unit Tests / responses-caching-types (push) Waiting to run
GitHub Actions Security Analysis / zizmor (push) Waiting to run
Terraform Modules / fmt, validate, test (aws) (push) Has been cancelled
Terraform Modules / fmt, validate, test (gcp) (push) Has been cancelled
test(responses): fix stale Anthropic smoke request
2026-09-11 15:10:59 -07:00
ryan-crabbe-berri
06fe2691c3 fix(proxy): count when a grouped log page starts past the last one
An out-of-range cursorless page returns nothing, and reading its total off the
offset reported more sessions than exist (page 4 of 100 sessions at page size 50
claimed 150). Only a page that holds rows, or the first page, ends the list;
anything past it falls back to the bounded count.

Claude-Session: https://claude.ai/code/session_01ESi9JwaXDww1vP3Qsrr4Mz
2026-09-11 14:59:18 -07:00
ryan-crabbe-berri
4bcd60e72b perf(proxy): total a short grouped log page from the page itself
A cursorless page that comes back without its lookahead row is the end of the
list, so the total is offset + len(page) and the bounded grouped COUNT over the
whole spend-log table is skipped. First pages on small deployments and every
offset last page now cost one query less.

Moves the count into _count_grouped_sessions and reworks the query-optimization
test that asserted the count always runs second onto a full page, where it does.

Claude-Session: https://claude.ai/code/session_01ESi9JwaXDww1vP3Qsrr4Mz
2026-09-11 14:51:05 -07:00
Mateo Wang
f90b5cad8a
Merge pull request #40740 from BerriAI/litellm_bedrock_openai_xhigh_flags
fix(cost-map): bedrock reasoning effort flags, registry audit fixes for vertex/openai/together/openrouter, absorb cerebras and inception rows
2026-09-11 14:41:18 -07:00
devin-ai-integration[bot]
c64e746b71
fix(content_filter): log only scan time as streaming post_call guardrail duration (#40760)
The streaming iterator hook timed the whole provider stream and logged that as the
guardrail duration, so PrometheusLogger added LLM generation time to
litellm_overhead_with_guardrails_latency_metric. The hook now accumulates the time
spent inside _filter_single_text per chunk and logs that sum, keeping start_time and
end_time as the wall-clock window.

Resolves LIT-7589

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 14:34:21 -07:00
ryan-crabbe-berri
cb434742c6 fix(proxy): end the cursorless grouped log page at the capped total
A page size that does not divide SPEND_LOGS_PAGINATION_COUNT_CAP left the last
page starting inside the capped window and reading past it, so the rows
disagreed with the total reported next to them. The page limit now stops at the
end of that window, and has_more plus next_session_cursor still hand back a
cursor for walking further.

Claude-Session: https://claude.ai/code/session_01ESi9JwaXDww1vP3Qsrr4Mz
2026-09-11 14:27:36 -07:00
devin-ai-integration[bot]
a426dc43cb
fix(policy_engine): run global policy pipelines before scoped ones (#39697)
* fix(policy_engine): run global policy pipelines before scoped ones

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

* fix(policy_engine): rank duplicate attachments by broadest scope

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

* fix(policy_engine): rank combined-scope attachments below single-scope ones

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

---------

Co-authored-by: shivam <shivam@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 14:20:10 -07:00
ryan-crabbe-berri
4295bf823a fix(proxy): bound the cursorless grouped log page offset
A page starting at or past SPEND_LOGS_PAGINATION_COUNT_CAP lies outside the
total the client is given, so it now returns no rows without running the page
query and the grouped top-N sort bound stays capped.

Rewrites the offset test to page a fake session store instead of asserting on
the generated SQL, and covers the last page inside the cap next to the first
page past it.

Claude-Session: https://claude.ai/code/session_01ESi9JwaXDww1vP3Qsrr4Mz
2026-09-11 14:16:43 -07:00
yuneng-jiang
d51a7af655
fix(search): propagate GET provider HTTP errors (#40779) 2026-09-11 14:07:32 -07:00
Yuneng Jiang
4423876857
test(responses): fix stale Anthropic smoke request 2026-09-11 13:56:27 -07:00
mateo-berri
71f45683d7 fix(cost-map): keep minimal withheld on Bedrock gpt-5.4 and gpt-5.5
LiteLLM sends the Bedrock Mantle GPT rows through Bedrock's Responses endpoint, which refuses minimal on gpt-5.4 and gpt-5.5 like every other Bedrock GPT row. The earlier commit measured the raw chat endpoint, which accepts it, and dropped the flag by mistake. The ladder test now matches what the proxy path returns
2026-09-11 13:46:28 -07:00
mateo-berri
dbc57c13d4 fix(cost-map): match Bedrock GPT effort flags to what Bedrock accepts
Live calls to Bedrock Mantle and Converse on 2026-09-11: the gpt-5.6 luna, sol, and terra rows and gpt-6-astra return 200 on reasoning_effort=max, gpt-6-astra returns 400 on none, and Mantle gpt-5.4 and gpt-5.5 return 200 on minimal. The commercial Bedrock rows now carry exactly those flags, and the schema test asserts the measured ladder per row instead of a blanket mirror of the direct OpenAI rows
2026-09-11 13:37:50 -07:00
devin-ai-integration[bot]
09b694894d
fix(datadog_llm_obs): keep tool call and result structure under redaction and emit tool output tokens (#40666)
* fix(datadog_llm_obs): keep tool call and result structure under redaction and emit tool output tokens

Under datadog_llm_observability_params.turn_off_message_logging the span kept only one role plus "redacted-by-litellm" per message, so Datadog showed Tool Call 0, Tool Result 0 and no tool output token data. The shared CustomLogger hook collapsed the messages before the callback ran, and the Datadog redaction then dropped tool_calls and tool_results.

The Datadog callback now opts out of the shared message collapse (redacts_messages_itself) and redacts its own normalized messages, keeping roles, tool names, ids and types while replacing content, arguments and results. Tool result tokens are counted with litellm.token_counter before redaction and shipped as the tool_output_tokens metric. Other callbacks keep the inherited behavior.

Resolves LIT-7545

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

* fix(datadog_llm_obs): drop explanatory docstrings from the redaction change

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

* chore(ui): regenerate schema.d.ts for the classifier descriptions changed in #40655

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

---------

Co-authored-by: yucheng <yucheng@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 13:12:14 -07:00
yujonglee
ae6a4a2f2a
feat(ocr): add Azure Mistral adapter and document fetching (#40533)
* feat(ocr): add Azure Mistral adapter and document fetching

* fix(ocr): decline missing Azure credentials

* fix(ocr): map Azure credentials in gateway errors

* refactor(ocr): preserve Azure Mistral extra params

* refactor(ocr): adopt request preparation contract
2026-09-11 13:03:06 -07:00
mateo
02279bc992 test(cost-map): gpt-5.5-pro has no published cached input rate
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 19:59:23 +00:00
devin-ai-integration[bot]
e073cd3aeb
fix(mcp): write failure spend log for guardrail-blocked /mcp-rest/tools/call (#40555)
* fix(mcp): write failure spend log for guardrail-blocked /mcp-rest/tools/call

call_tool_rest_api only translated exceptions to HTTP responses, so a pre_mcp_call
guardrail block never reached failure_handler / async_failure_handler /
post_call_failure_hook and no LiteLLM_SpendLogs failure row was written. Extract
the failure logging from call_mcp_tool into _fire_mcp_tool_call_failure_logging
and run it in the REST route for anything raised between
common_processing_pre_call_logic and execute_mcp_tool

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

* fix(mcp): keep the original REST tool error when failure logging raises

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

* fix(mcp): log virtual mcp_tool_call failures and keep REST success latency scoped to tool execution

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

---------

Co-authored-by: yucheng <yucheng@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 12:54:03 -07:00
tin-berri
f22f9bc461
feat(auto-router): show routed model and savings in Claude Code and Codex (#40330) 2026-09-11 12:52:42 -07:00
mateo
e3130a87bc test(cost-map): type the monkeypatch fixture in cerebras and inception registry tests
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 19:50:27 +00:00
mateo
4ffd4ecc83 fix(model_prices): absorb cerebras/inception PRs, fix vertex/openai/together/openrouter pricing
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 19:37:45 +00:00
yujonglee
89f1f9567d
refactor(ocr): route native requests through core (#40532)
* refactor(ocr): route native Mistral through core

* fix(ocr): preserve Azure API base resolution

* chore(ocr): document bridge boundary casts

* fix(ocr): keep Azure environment resolution in Rust

* fix(ocr): centralize native execution and isolate request logging

* refactor(ocr): narrow native migration to bridge routing

---------

Co-authored-by: Stack Plan <stack-plan@example.invalid>
2026-09-11 12:37:19 -07:00
yuneng-jiang
83616c0e09
Merge pull request #40754 from BerriAI/litellm_ui_e2e_propagation
test(e2e): wait for serving propagation in UI journeys
2026-09-11 12:33:48 -07:00
ryan-crabbe-berri
e790b450b7
Merge pull request #40554 from haydster7/fix/team-alias-model-metadata
fix(proxy): retain metadata when retrieving public team aliases
2026-09-11 12:29:46 -07:00
devin-ai-integration[bot]
3e23eae248
fix(proxy): keep call_type and request start time on failed-request spend logs (#40558)
* fix(proxy): keep call_type and request start time on failed-request spend logs

post_call_failure_hook pops litellm_logging_obj before the failure callbacks
run, so the spend row built from request_data had a blank call_type and used
datetime.now() as the start time. A guardrail-blocked MCP tool call therefore
showed up in the Logs page as an LLM row with no call type and a 0s duration.
Lift call_type and start_time off the logging object alongside the fields
already lifted, and have the DB failure hook prefer the lifted start time.

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

* test(proxy): inject the spend writer into _ProxyDBLogger instead of patching a module global

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

---------

Co-authored-by: yucheng <yucheng@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 12:22:18 -07:00
mateo
7b25c6a29e Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_bedrock_openai_xhigh_flags 2026-09-11 19:02:54 +00:00
devin-ai-integration[bot]
95b438013a
fix(router): fall back from unhealthy auto-router tier (#40757)
* fix(router): fall back from unhealthy auto-router tier

Co-Authored-By: Claude Code <noreply@anthropic.com>
(cherry picked from commit 00c7fd8376)

* fix(router): treat budget and tag exhaustion as a no-capacity verdict

The eligibility probe only read typed router errors as "nothing here can
serve this". Provider and deployment budget exhaustion, and tag routing
with no matching deployment, report it as a bare ValueError carrying a
RouterErrors marker, so the probe read a spent tier as live, skipped the
peer and default recovery, and failed the request.

---------

Co-authored-by: Tin Chi Lo <tin@berri.ai>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-09-11 11:51:55 -07:00
Mateo Wang
1dc0e363b0
fix(proxy): authorize every Responses API id, not only the ones the proxy issued (#39548)
* fix(proxy): authorize every Responses API id, not only the ones the proxy issued

The ownership check on the Responses API only ran when the id arrived in the
proxy's own encrypted format. An id in any other shape skipped the check and
was forwarded upstream, so a key that did not own the response could retrieve,
cancel, delete, or chain off it.

Every addressed id now goes through one authorization step shared by retrieve,
cancel, delete, list-input-items, and create's previous_response_id. An id the
proxy did not issue is refused with 403 unless the deployment opts in with
general_settings.allow_unmanaged_response_ids, has responses id security
disabled, has no signing key configured, or the caller is a proxy admin.

* fix(proxy): re-authorize the retained responses id instead of trusting it
2026-09-11 11:47:05 -07:00
Mateo Wang
2c78e28c24
Merge pull request #39523 from BerriAI/litellm_fix_ai_gateway_image_build
fix(ai-gateway): build the release image again and cover it in CI
2026-09-11 11:46:49 -07:00
Mateo Wang
5c821828ea
Merge pull request #39516 from BerriAI/litellm_vector_store_surface_retrieval_failure
fix(vector-stores): surface retrieval failures to the API caller
2026-09-11 11:46:42 -07:00
Mateo Wang
0fe9de8550
Merge pull request #39507 from BerriAI/litellm_fix_oci_streaming_chunk_ids
fix(oci): pin one response id per streamed completion, skip the [DONE] sentinel
2026-09-11 11:46:35 -07:00
joshua-berri
6882f057b4
Merge pull request #40440 from BerriAI/litellm_mcp_upstream_error_log_detail
fix(mcp): log upstream request method, body and response on tool-list and OAuth2 token failures
2026-09-11 11:24:42 -07:00
Joshua Valluru
aef8888c0b ci: remove MCP tests from Python 3.10 import smoke 2026-09-11 11:02:38 -07:00
joshua-berri
3f81ba3d30
Merge pull request #40679 from BerriAI/litellm_fix_mcp_oauth_registration_7498
fix(mcp): explain refused OAuth registration and bound discovery retries
2026-09-11 10:51:31 -07:00
Yuneng Jiang
b01d12154d
test(e2e): budget model health setup and propagation waits 2026-09-11 10:39:49 -07:00
Yuneng Jiang
057d333d10
test(e2e): observe model propagation without pre-running health checks 2026-09-11 10:29:10 -07:00
Yuneng Jiang
5ddd839432
test(e2e): wait for serving propagation in UI journeys 2026-09-11 10:25:43 -07:00
Anmol Jaiswal
dfab4794ec
docs(router): name both affinity TTL knobs in the _claim_pin docstring (#40663)
The docstring cited session_affinity_ttl_seconds as the keepalive bound,
but the Router-level knob feeding ttl_seconds is
deployment_affinity_ttl_seconds; session_affinity_ttl_seconds is the
separate per-request PreRoutingHookResponse override. Anyone grepping
the docstring's name to shrink the Router default finds only the
override. Name both, scoped correctly.
2026-09-11 10:22:32 -07:00
devin-ai-integration[bot]
9316b4194a
perf(proxy): register liveness and core inference routes first (#40687)
Starlette scans the route table in registration order, so a request pays one
regex match per route registered ahead of its own. The proxy registers several
hundred routes and left the liveness probe near position 280 and the lazy
loaded /v1/messages at the very end. Move /health/liveliness, /health/liveness,
/v1/chat/completions, /chat/completions and /v1/messages to the front of the
route table after startup registration and again after a lazy router loads.

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 17:10:38 +00:00
ryan-crabbe-berri
f72b117b21 fix(vertex_ai): return 400 for invalid reasoning_effort instead of 500
Both reasoning_effort mappers ended their if/elif chain in a bare ValueError.
exception_type() has no branch for ValueError, so it fell through to the shared
APIConnectionError fallback and the proxy answered a malformed client request
with a retryable HTTP 500 carrying no hint of the accepted values.

Raise UnsupportedParamsError (400) instead, listing the supported set, matching
what the Anthropic and Bedrock transforms already do and what this same file
already does at its five other param-validation sites.

This also covers 'xhigh' and 'max', which are members of litellm's own
REASONING_EFFORT literal but have no Gemini mapping, so callers bridging from
OpenAI-shaped code were hitting the 500 without typing anything wrong.

Fixes #40474

Claude-Session: https://claude.ai/code/session_01XT1qsbjLwnhiN5sQ2hNUxr
2026-09-11 10:00:35 -07:00