Commit graph

732 commits

Author SHA1 Message Date
Kerry Lu
0eff31ae4e
fix(gemini): bill context cache creation tokens from cachedContents responses (#46144)
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-13 03:18:50 +00:00
Kerry Lu
24bbf8f0e1
fix(cost): bill azure_ai claude web searches under deployment-owned pricing ids (#46135)
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-12 19:40:53 -07:00
devin-ai-integration[bot]
7265b0e889
fix(bedrock): bill the regional row for inference-profile ARNs that embed a cross-region prefix (#46128)
* fix(bedrock): bill the regional row for inference-profile ARNs that embed a cross-region prefix

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

* test(bedrock): keep the ARN regional-row regression tests to the touched lines

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>
2026-10-12 18:56:43 -07:00
devin-ai-integration[bot]
bfb4f4b2c3
fix(databricks): accept service_tier on requests and carry the served tier on responses (#46111)
* fix(databricks): accept service_tier on requests and carry the served tier on responses

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

* fix(databricks): mark the in-place service_tier store as rebind-ok

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

* style(databricks): wrap the service_tier store to the line limit

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

* fix(databricks): keep the rebind-ok suppression on the service_tier line

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

* fix(databricks): only set service_tier on responses when the upstream returned one

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

* fix(databricks): name the B010 suppression on the service_tier setattr

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

* fix(databricks): shorten the service_tier suppression to the line limit

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

* fix(responses): read service_tier from the Responses request only

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>
2026-10-12 18:22:10 -07:00
devin-ai-integration[bot]
f97d3df6de
fix(cost): bill custom priced deployments at their own rates over the upstream x-litellm-response-cost header (#46120)
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-13 00:58:03 +00:00
devin-ai-integration[bot]
5338edb7e3
fix(cost): bill azure_ai claude web searches per server_tool_use request (#46114)
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-13 00:42:46 +00:00
yujonglee
05cf428761
feat(rust): settle EdenAI Messages reported cost (#45698)
* feat(edenai): settle native Messages reported cost

* test(rust): add live EdenAI Messages contract cases

* refactor(rust): settle call cost once as an ExecutionFacts variant

The route now decides Cost (Reported, CacheHit or Deferred) from the
result source and the provider's reported figure. The legacy callback
adapter only projects a Reported amount onto provider_reported_cost and
no longer writes response_cost, which the Python calculator derives

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(rust): keep EdenAI wire shaping independent of Invoke

* style(rust): format cost settlement imports

* fix(rust): trust provider costs without bypassing configured pricing

* fix(rust): clear untrusted response costs before spend settlement

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-12 17:39:08 -07:00
devin-ai-integration[bot]
c2bc5aecff
fix(cost_calculator): apply the anthropic fast multiplier to cache cost breakdown (#46112)
* fix(cost_calculator): apply the anthropic fast multiplier to cache cost breakdown

Anthropic fast mode billed totals at provider_specific_entry.fast while the
spend log cost_breakdown kept cache_read_cost and cache_creation_cost at 1x.
Move the speed lookup into a shared helper, multiply it into the billed token
rates used by get_token_type_cost_breakdown, and have the Anthropic calculator
read the same helper so totals and breakdown cannot drift apart.

Production change carried from #44074.

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

* fix(cost_calculator): narrow the provider entry instead of defaulting to a dict literal

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>
2026-10-12 17:38:08 -07:00
devin-ai-integration[bot]
b6df3d7fe5
fix(responses): number bridged chat tool calls 0, 1 and pin the remaining bridge shapes (#46109)
* test(responses): pin bridged commentary plus final answer as one chat choice

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

* test(responses): pin reasoning, two-message and two-tool-call bridge shapes

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

* fix(responses): number bridged chat tool calls 0, 1 instead of all 0

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>
2026-10-12 17:35:30 -07:00
devin-ai-integration[bot]
aa52927216
feat(proxy): let personal keys inherit model access from the owner's current teams (#43692) 2026-10-13 00:17:35 +00:00
Delweng
b24b68e576
fix(gemini): price tool-use prompt tokens as input (#46021)
* test(gemini): tool-use prompt tokens must be priced as input

Signed-off-by: Delweng <delweng@gmail.com>

* fix(gemini): price tool-use prompt tokens as input

toolUsePromptTokenCount was folded into usage.prompt_tokens but left out
of prompt_tokens_details.text_tokens, and generic_cost_per_token bills
input from text_tokens, so URL context / code execution / File Search
tool tokens were counted but never charged. Search-grounded responses
keep adding zero via the grounding-aware billable count, and
promptTokensDetails absent still leaves text_tokens None so billing
falls back to the full prompt_tokens

Signed-off-by: Delweng <delweng@gmail.com>

---------

Signed-off-by: Delweng <delweng@gmail.com>
2026-10-12 17:01:48 -07:00
devin-ai-integration[bot]
4b7b8efd4c
fix(responses): fold bridged Responses output into one chat choice (#46099)
* fix(responses): fold bridged Responses output into one chat choice

A Chat Completions request bridged to /responses got one choice per
Responses message item, so a reply shaped [message, message,
function_call] put the tool call on choices[1] and clients reading
only choices[0] never saw it. Fold every message text, annotation,
reasoning item and tool call into choices[0]

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

* fix(responses): drop mutable annotations and the extra cast in the choice fold

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

* fix(responses): remove a cast-ok marker that suppressed nothing

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

* fix(responses): join folded message texts with a newline

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

* revert(responses): join folded message texts with no separator so stream and non-stream match

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>
2026-10-12 16:33:50 -07:00
moyai-devin-berriai[bot]
0c04d0bdb7
fix(guardrails): honor decision model streaming buffering (#46086)
Co-authored-by: moyai-devin-berriai[bot] <336287033+moyai-devin-berriai[bot]@users.noreply.github.com>
2026-10-12 16:28:22 -07:00
mrinal-berri
231721f20a
feat(otel): let a team or key excluded_services override the global setting for its OTel v2 destination (#45880)
* feat(otel): let a team or key excluded_services override the global setting for its OTel v2 destination

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

* style: ruff format otel excluded_services changes

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

* test: use raw regex for excluded_services match

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

* fix(otel): reject non-string destination callback vars

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

* fix(otel): harden destination callback var validation

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

* fix(otel): compare parsed values in callback var conflict check

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-10-12 19:25:52 -04:00
yucheng-berri
02b5a395d8
feat(zscaler_ai_guard): send the request user to AI Guard (#46094)
* Add user field to AI Guard execute-policy payload for dashboard attribution

Send the top-level OpenAI request `user` field in the execute-policy
JSON payload so AI Guard can surface usernames on its dashboard. This is
independent of the existing user_api_key_* headers which remain unchanged.

The upstream guardrail framework already passes the original request_data
(containing the `user` field) through to response-path guardrail calls,
so this works for both IN and OUT directions including streaming.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Apply suggestion from @greptile-apps[bot]

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Add type annotations and tests for user field in execute-policy payload

- Add Final annotation to user_for_payload
- Add str | None type to user parameter in make_zscaler_ai_guard_api_call
- Add 3 tests: user included when present, omitted when absent,
  and user in/out of JSON body sent to AI Guard

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test(zscaler_ai_guard): inject the http client in user field tests

Pass an AsyncHTTPHandler into ZscalerAIGuard so the user field tests read the
real execute-policy body off a MockTransport instead of patching class methods,
and drop the comments that restated the lookup

* fix(zscaler_ai_guard): forward only non-empty string users

Read the request user through a typed helper and type the execute-policy call
params so basedpyright stays under the merge-base count, and skip non-string
values the vendor rejects with a 500

* test(zscaler_ai_guard): drop the test-only http_client

Run the user field tests against an in-process aiohttp server through api_base
so the guardrail keeps its original constructor

---------

Co-authored-by: Syamala Keerthana Chegu <schegu@zscaler.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: yucheng-berri <293926326+yucheng-berri@users.noreply.github.com>
2026-10-12 16:13:22 -07:00
devin-ai-integration[bot]
ebc8e56aec
fix(proxy): enforce the personal max_budget on proxy-admin JWTs (#43070)
* fix(proxy): keep the personal budget on a proxy-admin user object

A token carrying the proxy_admin role (JWT admin scope, SSO) replaced the fetched LiteLLM_UserTable row with a bare admin object, so max_budget never reached common_checks and admins spent past their personal budget on /chat/completions. Keep the row and force only user_role.

Co-authored-by: L4XB <lukas.buck@e-mail.de>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(e2e): budget denial for a proxy-admin JWT is the 422 ExceededBudget response

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

* fix(proxy): carry only the personal budget onto a forced proxy-admin user object

Keeping the whole DB row also carried its models list, so a proxy admin
whose row had no-default-models or a restricted list got 403 on personal
requests. Build the admin object as before and copy max_budget and
user_email across. The built-in admin identity (the master key and the UI
username/password login) keeps ignoring its row's budget.

* test(proxy): pin the contrast case in the admin model-list and admin-name budget tests

Each test now also shows the same cached row refusing a non-exempt token, so the
pass case cannot go green on a row the gate never read.

* test(e2e): drive the personal-budget case with a proxy_admin user row and a plain JWT

The Buildkite stack keeps the default admin_allowed_routes, so an admin-scope JWT
gets 403 on /chat/completions before any budget check and the case could never
pass there. A plain token whose sub resolves to a proxy_admin row goes through the
same forced-admin rebuild. Drop the stage-mirror admin_allowed_routes edit, which
the deployed stack never read.

* ci: rerun e2e after an unrelated Gemini streaming spend-row timeout

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: L4XB <lukas.buck@e-mail.de>
Co-authored-by: yucheng-berri <293926326+yucheng-berri@users.noreply.github.com>
2026-10-12 16:04:12 -07:00
devin-ai-integration[bot]
4fae3c64bb
feat(sagemaker)!: inference components and OpenAI-compatible embeddings (#44985)
* feat(sagemaker): inference components and OpenAI-compatible embeddings

Send model_id on a SageMaker embedding deployment as the invoke call's
InferenceComponentName, sync and async, and keep it out of the request body.
Add the sagemaker/openai/<endpoint> route, which sends the OpenAI embeddings
request shape ({"input": [...]} plus extra_body fields) and reads
data[].embedding and usage from the response for containers that serve the
OpenAI embeddings API. Plain sagemaker/<endpoint> deployments keep the
Hugging Face shape

* refactor(sagemaker): type validate_environment messages and cover base64 embeddings

* fix(sagemaker): name model_id in inference component errors and reject a non-string model_id on embeddings

* fix(sagemaker): fall back to the error text when SageMaker sends a null message

A ClientError whose Error.Message is null (SageMaker's InternalFailure shape) reached the
inference component hint as None and crashed with a TypeError; the message now falls back
to the error's own text on the chat and embedding paths

* test(sagemaker): audit matrix for inference-component embeddings

* fix(sagemaker): read the error status and text through one shape-checked helper

botocore's ConnectionClosedError carries response=None, so the except blocks that
read e.response.get(...) crashed with an AttributeError and the proxy answered 400
"Invalid request format" for a dropped connection. client_error_details validates
the botocore error shape with pydantic and falls back to 500 plus the error's own
text for any other shape (a missing response, an httpx Response, a plain exception).

* fix(sagemaker): drop the inference component hint from chat and derive the SDK wire expectation from the request

The chat except blocks never see SageMaker's text: HTTPHandler.post raises from
raise_for_status before the handler's own SagemakerError line, so the hint check ran
on httpx's generic "Client error '400 Bad Request' for url" line and could not match on
any chat path. The hint now names litellm.embedding only and the chat blocks keep the
status and text they had, without the dead check. The two OpenAI SDK wire tests pinned
the SDK's default encoding_format; they now expect whatever the SDK sent.

* refactor(sagemaker): meet main's per-rule lint and type ceilings

Main started gating every lint rule on its merge-base count and added LIT015
(frozen pydantic models) after this branch was cut, so the merge with main
pushed LIT001, LIT011, LIT015, BLE001 and reportArgumentType past their
ceilings. The response models are frozen with tuple fields, the OpenAI
embedding response is built with model_copy instead of writing into the
caller's object, the invoke_endpoint arguments are a TypedDict, and
optional_params and extra_body are validated into Mapping[str, object] before
they are read

* refactor(sagemaker): pick the embedding config in one place and stop pinning upstream error text

The openai/, Voyage and Cohere checks lived in both get_model_config and
get_supported_openai_params, so they now share one lookup. Tests compare error
messages against the error's own text, or against botocore's and json's own
wording, instead of copying that wording, and assert whole messages where the
text is ours

* fix(caching): key direct calls on model_id so inference components don't share cached embeddings

* test(sagemaker): name the fake-boto3 SDK test class for what it covers

* test(sagemaker): kill and stop chaos workers through the owned-proxy harness

---------

Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-10-12 22:25:52 +00:00
Yassin Kortam
1b89c2af1a
fix(proxy): refuse /fallback writes to a fallbacks list set in config.yaml (#45860)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-12 15:01:45 -07:00
devin-ai-integration[bot]
4f16aaa32c
feat(cost): support provider/model-pattern keys in cost_discount_config (#43335)
cost_discount_config keys may now be <provider>/<model-pattern> with fnmatch globs, so a discount can target a subset of a provider's models. An exact pattern beats a glob, the glob with the longest literal wins, and the bare provider key is the fallback. PATCH /config/cost_discount_config validates the provider half only, and the admin UI cost tracking page gains a Model pattern field and a Models column

Resolves LIT-8465

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-12 14:59:18 -07:00
ryan-crabbe-berri
c2d0726a08
fix(anthropic): carry cache_control to prompt_cache_breakpoint on the /v1/messages to Responses bridge (#46082)
A caller hitting /v1/messages with a cache_control mark and an OpenAI
gpt-5.6 or newer deployment behind it lost the mark when the request was
rebuilt as a Responses request, so OpenAI never cached at the boundary the
caller chose. The bridge now rewrites each marked system, user and
tool_result block to prompt_cache_breakpoint on the same block when the
deployment reads breakpoints, keeps the system prompt as a developer
message so its mark survives, and still strips the mark for deployments
that do not read it

The hook's gate becomes public so the bridge and the hook share one
answer for which deployments read breakpoints, and the one-block swap
lives next to the existing breakpoint helper in prompt_templates
2026-10-12 14:57:22 -07:00
devin-ai-integration[bot]
ca4169d20a
feat(providers): add CoralBricks as a native provider (#44700)
* feat(providers): add CoralBricks as a native provider

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

* test(coralbricks): harden cost map consistency tests

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

* test(coralbricks): type cost helpers, read cost maps from disk, cover streaming spend

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

* test(coralbricks): drop Final on loop-rebound names

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

* test(coralbricks): add the provider audit cells, the Add Model browser cell and the README row

* test(coralbricks): derive UI spend from model info, type browser rows, always release held upstream

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

* test(coralbricks): release held upstream before the wire server joins its threads

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

* test(coralbricks): number forwarded chats with itertools.count instead of a mutable list

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

* fix(coralbricks): drop retired glm-5.3-flash-fp4 and test against deepseek-v4.1-flash-fast-fp4

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

* test(coralbricks): pin retries, await the respawned worker, read the UI rate from the catalog

The retry cells now set num_retries on the deployment, since the CI rig posts
router_settings.num_retries 0 after readiness and the router default of 2 no
longer applies there. The SIGKILL chaos cell waits for the respawned worker's
startup before the owned proxy is stopped and derives its timeout from the
harness budget. The Add Model spec waits for the catalog the form loads, reads
the expected rate from it, and finds the deployment through /v1/model/info,
which does not paginate

* fix(coralbricks): price the current model names and the new DeepSeek input rate

CoralBricks renamed glm-5.3-fp4 to glm-5.3-fast and deepseek-v4.1-flash-fast-fp4
to deepseek-v4.1-flash-fast (the fp4 names stay as deprecated aliases), and cut
DeepSeek V4.1 Flash input from $0.30 to $0.01 per 1M on 2026-10-08. Rates read
from https://www.coralbricks.ai/api/public/models on 2026-10-10; a live cache
write billed 6014 tokens at 9e-08 each, so the cache-write rate stays input
plus cacheWritePerM.

The test config builders now build new dicts instead of editing the parsed
YAML, and the cost-map test locals carry Final.

* fix(coralbricks): keep pricing for the deprecated fp4 slugs CoralBricks still serves

* fix(coralbricks): list the catalog rows for wildcard deployments and derive the test's input limit from the row

* fix(coralbricks): price the deprecated glm-5.3 and deepseek-v4.1-flash slugs

---------

Co-authored-by: Mubashir Osmani <mubashir@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-10-12 21:56:59 +00:00
mayank-affirm
56a1e94a31
fix(bedrock_mantle): map the OpenAI-shaped context overflow envelope too (#41747)
* feat(dd_span_tagger): emit litellm_user_email span tag for JWT-authenticated requests

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

* refactor(dd_span_tagger): use dotted litellm.user_email tag for consistency

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

* feat(model_hub): surface model_info.description in model group info and Model Hub UI

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

* refactor(router): aggregate model group description without in-place mutation

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

* fix(health): skip background health check DB writes when the latest-row read fails

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

* fix(bedrock_mantle): map the OpenAI-shaped context overflow envelope too

Mantle reports context overflow in two envelopes. #37862 covered the
structured `validation_error` one carrying token counts
("prompt tokens (N) exceed model maximum (M)"). Mantle also returns the
OpenAI-shaped body:

    {"error":{"code":"context_length_exceeded","message":"Your input
     exceeds the context window of this model. ...","param":"input",
     "type":"invalid_request_error"}}

That passes the existing `invalid_request_error` gate but matches neither
the token-count pattern nor `is_error_str_context_window_exceeded`'s
substring list, so it fell through to a generic BadRequestError. Clients
such as Claude Code only reactive-compact on a recognised overflow
phrase, so an overflowing request surfaced as an ordinary error with no
recovery.

Return the same normalised "prompt is too long: ..." message for this
envelope when it carries no counts, keeping the numeric wording when the
provider supplies them.

* fix(bedrock_mantle): map the streamed context overflow and keep its 400 on /v1/messages streams

* fix(anthropic_adapter): keep only the context overflow's 400 on streamed /v1/messages so other provider 4xx still fall back

* test(anthropic_adapter): wrap a parametrize line over the 120 char limit

* test(integration): audit Bedrock Mantle context overflow mapping across routes, clients, and fallbacks

* test(integration): move the streamed /v1/messages overflow spend row into a BUG-skipped test

* test(integration): keep every chaos cell in the burst and skip only the missing spend row

* fix(bedrock_mantle): answer 400 on an in-stream context overflow

The Mantle overflow mapper built its ContextWindowExceededError on the
original exception's response, so an overflow that Mantle reports inside
a 200 stream (the chat-mode token-count envelope, which the OpenAI chunk
parser wraps as a 500) kept that 500 and the streamed /v1/messages route
answered HTTP 500 api_error instead of 400 invalid_request_error. The
mapper now builds the error on a 400 response that keeps the original
headers and request, and the mapping test covers an in-stream 500 and 503.

The integration suites pin the streamed /v1/messages overflow to the
pre-content 400 route under a retry budget and to the message_start plus
invalid_request_error event without one, drop the chaos carve-out that
expected no spend row, and give the fallbacks file a timeout mark sized to
the proxy's graceful stop.

* fix(bedrock_mantle): keep the provider's 400 body and match the overflow code only as error.code

---------

Co-authored-by: milan <milan@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: ryan-crabbe-berri <ryan@berri.ai>
Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-10-12 21:50:22 +00:00
devin-ai-integration[bot]
7dc7f101d9
feat(decisions): bill decisions and systemone from _decisions cost map fields (#45904)
* feat(decisions): bill decisions and systemone from <provider>/decisions/<model> cost map rows

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

* feat(decisions): mark decisions pricing rows with mode decisions

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

* fix(ui): sync generated API types for decisions mode

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

* fix(decisions): update pricing expectations in proxy tests

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

* test(decisions): price classifier calls from decision rows

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

* fix(health): drop redundant evaluation handler after main merge

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

* test(decisions): inject pricing row for deployed classifier

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

* refactor(decisions): ship the decisions pricing lookup without cost map rows

Restore both cost maps to main. Tests inject their own
<provider>/decisions/<model> rows. The Add Model dropdown hides those
pricing keys and offers mode decisions instead of evaluation.

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

* test(ui): expect the Decisions mode option in the Add Model form

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

* feat(decisions): bill decisions and systemone from _decisions cost map fields

Replace the provider/decisions/model pricing rows with <field>_decisions
fields on the model's own row. cost_per_token overlays them for the
decisions, adecisions, systemone and asystemone call types and prices
through generic_cost_per_token; chat, responses and batch keep the plain
fields. gpt-6-luna gains its Decisions rates (input 1e-07, output 0,
cached and cache-write input 1e-07, 2x above 272k tokens).

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

* fix(decisions): satisfy type gate, schema sync and test_utils schema for _decisions fields

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

* test(decisions): import cost_calculator module to keep basedpyright unknown-variable count flat

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

* fix(decisions): drop stray fireworks import from __init__ and annotate test cost rows for the type gate

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

* test(integration): cover gpt-6-luna decisions and systemone above the 272k tier

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

* refactor(decisions): keep the decisions pricing block clear of main's stale azure comment

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

* chore(cost_calculator): drop stale azure models doc comment

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

---------

Co-authored-by: kerry <kerry@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-12 14:31:12 -07:00
joshua-berri
932a0d6151
fix(mcp)!: preserve scopes during managed OAuth reauthorization (#45886)
* fix(mcp): preserve scopes during managed OAuth reauthorization

* fix(mcp): relay scope challenges before streaming responses

* fix(mcp): bind aggregate OAuth step-up scopes to upstream consent

* fix(mcp): describe gateway access accurately before final consent

* fix(mcp): preserve standalone client optional dependencies

* fix(mcp): retain explicit empty grants during native refresh

* fix(mcp): preserve empty grants through credential persistence

* test(mcp): run scope regressions in OAuth CI shard

---------

Co-authored-by: Joshua Valluru <326636767+joshua-berri@users.noreply.github.com>
2026-10-12 17:10:05 -04:00
jesus-berri
fead47fa7b
fix(proxy): skip failure rows for expired Admin UI session keys on dashboard info routes (#45881)
* fix(proxy): skip failure rows for expired Admin UI session keys on dashboard info routes

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

* test(proxy): mark DB-boundary write assertion as test-quality-ok

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-10-12 13:56:05 -07:00
moyai-devin-berriai[bot]
a86ad9ebf8
feat(decisions): support Clef-omni audio and video (#45811)
* feat(decisions): support Clef-omni audio and video

* fix(decisions): accept Clef-omni media types with parameters and cover the proxy routes

The clip patterns now mirror Cloudflare's input schema, so a data URL or
content_type carrying parameters like audio/webm;codecs=opus is accepted.
The four proxy routes get media tests of their own, the backup cost map
is synced with the new Clef-omni rows, and the docs page moves to the
docs repo as a follow-up.

* fix(decisions): refuse parameterized media-type data URLs and refresh the OpenAPI snapshot

Cloudflare answers 422 to a data URL whose media type carries parameters even though its schema only requires the data:audio/ prefix, so LiteLLM now refuses those with a 400 before the call. The object form keeps passing parameters through, which Cloudflare accepts. The lazy OpenAPI snapshot and the dashboard API types are regenerated for the new audio and videos fields

* fix(decisions): gate media by cost-map flags, treat null clips as none, drop unsupported clips before validation

* fix(decisions): keep the SDK's positional order and gate media flags on evaluation-mode models

* fix(decisions): gate media on both decisions model modes and move the audit cells onto the harness helpers

* test(decisions): cover the Fireworks System One router in the media refusal cells

---------

Co-authored-by: moyai-devin-berriai[bot] <336287033+moyai-devin-berriai[bot]@users.noreply.github.com>
Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-10-12 20:29:49 +00:00
Sukhdeep
87478c7b6d
fix(gemini): do not inject temperature for Gemini 3+ models when omitted (#45107)
* fix(gemini): do not inject temperature for Gemini 3+ models when omitted

map_openai_params added temperature=1.0 to every Gemini 3+ request that did not set one, on both the gemini and vertex_ai routes. Google is deprecating temperature, top_p and top_k for Gemini 3+ and says upcoming models will reject them, so this default turns a request that never set temperature into one that will fail

An omitted temperature now falls back to Google's own default, which their docs give as 1.0 for all Gemini 3 models. Explicit temperature, top_p and top_k are still forwarded

Fixes #38663

* test(gemini): annotate sampling regression tests

* test(gemini): drop the injected temperature from Gemini translation cases

The nine Gemini base cases for chat completions, responses and messages send no temperature, so the provider request no longer carries the removed 1.0 default. Each new body was sent to the real Gemini API for gemini-3.5-flash, gemini-3.8-flash and gemini-3.1-pro-preview and returned 200, and the stored provider responses are unchanged

* test(gemini): drop the default-temperature wording from the thinking level test docstring

* test(gemini): cover omitted and explicit sampling on both Gemini routes

---------

Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-10-12 20:26:49 +00:00
devin-ai-integration[bot]
19327a606e
feat(vertex_ai): add semantic-ranker rerank pricing to the cost map (#46061)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-12 12:40:27 -07:00
devin-ai-integration[bot]
fe33d85e66
feat(model_prices): add meta/muse-wonder-1.0 (#46072)
* feat(model_prices): add meta/muse-wonder-1.0

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

* fix(model_prices): mark muse-wonder-1.0 as not supporting reasoning_effort none

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

---------

Co-authored-by: kerry <kerry@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-12 19:36:52 +00:00
devin-ai-integration[bot]
249add6f0d
refactor(bedrock): rename is_claude_4_5_on_bedrock to supports_bedrock_prompt_cache_ttl (#46058)
Co-authored-by: kerry <kerry@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-12 18:34:33 +00:00
devin-ai-integration[bot]
088184c24b
feat(fireworks_ai): add Decisions support for accounts/fireworks/routers/rune on /v1/systemone and /v1/decisions (#46057)
* feat(fireworks_ai): add Decisions support for accounts/fireworks/routers/rune on /v1/systemone and /v1/decisions

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

* chore(fireworks_ai): point the rune cost row at the public Fireworks docs

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

* test(decisions): patch litellm.callbacks with monkeypatch in the Fireworks cached-cost test

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

---------

Co-authored-by: kerry <kerry@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-12 11:18:59 -07:00
mrinal-berri
f516668f96
fix(managed_files): enforce input file ownership on batch and fine-tuning create (#45855)
* test(managed_files): pin ownership checks on batch and fine-tuning create

Tenant B can create a batch or fine-tuning job from tenant A's managed
file id today. These fail on main for acreate_batch input_file_id and
acreate_fine_tuning_job training_file and validation_file

* fix(managed_files): check input file ownership on batch and fine-tuning create

Batch create and fine-tuning create only mapped the managed input file to
provider ids and never checked who owned it, so any key with access to the
model could build a batch or job on another tenant's file and then own the
outputs. Both now run check_file_ids_access like chat and responses do,
which 403s a non-owner and 404s a managed id with no ownership row.
Fine-tuning also checks validation_file, which was never looked at

* test(batches): pin that a pre-call ownership denial stops every batch create branch

LIT-4797 noted an endpoint-level check missed the load-balanced branch
because it dispatches first. The ownership check lives in the pre-call
hook, which runs before branch selection, so a 403 there must keep both
the load-balanced and unified-file branches from reaching the router

* test(integration): pin managed-file ownership on batch and fine-tuning create

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

* fix(managed_files): check ownership before the batch rate limiter reads the input file and keep key-owned resources across key regenerate

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-10-12 13:58:25 -04:00
devin-ai-integration[bot]
02feb67c20
test(integration): cut CircleCI proxy boot time with concurrent worker stacks and single-worker test proxies (#46037)
* test(integration): build worker stacks concurrently and record proxy boot phases

The controller built every xdist worker's database, Redis, upstream and gateway
proxy one after another before any test ran, about 95 s per extensions shard,
and since every multi-worker suite is now isolated the same serial wait hits
mcp, security and cost too. The stacks now start on a thread pool bounded by
the CPU count. Each stack reads its endpoints and results directory from an
explicit environment instead of a patched os.environ, every stack that started
is registered for cleanup, and a failure in one stops the others before the
error is raised

Owned proxy startup.json now records the wall-clock spawn time, the worker
count and when the Prisma CLI child ran, when the port started accepting and
when the first worker answered readiness, and exit.json records when the stop
started and ended, so the boot time can be split and overlapping gateway boots
can be seen in the artifacts

* test(integration): boot one uvicorn worker where a test does not assert cross-worker behaviour

A 2-worker owned proxy takes about twice as long to become ready as a 1-worker
one, because the uvicorn parent imports the app and each spawned worker imports
it again. The passthrough upstream error visibility cases, the single-request
S3 dedupe cases and the single-request spend log payload cases send one or two
requests and assert on the response, the proxy log and the spend row, none of
which depends on a second worker, so they now boot the default single worker

Cases that do rely on two workers keep them, the concurrent S3 burst through a
sink outage, previous_response_id replay, response cache hits, the concurrent
spend bursts and upstream stop and recovery

* test(observability): settle OTel excluded-services traces by a quiet period instead of a full window

_trace_spans slept through its whole 15 or 30 s window on every call even when
the trace had long stopped growing. It now polls and returns once the trace
has spans and has not gained one for five tenant export intervals, and the
module pins the tenant batch exporter's schedule delay to 1 s so that bound is
set by the test rather than by the SDK default. Absence checks still run only
after the trace stopped growing, and against a build that leaks postgres spans
to the tenant they still fail

These cases also boot one uvicorn worker now. None of them asserts anything
about a second worker

---------

Co-authored-by: Yuneng Jiang <yuneng@berri.ai>
2026-10-12 09:48:42 -07:00
devin-ai-integration[bot]
7efce7f8e0
test(integration): give chaos and timing tests a harness API and gate raw signals (#46031)
* test(integration): give chaos and timing tests a harness API and gate raw signals

Chaos tests killed and suspended proxy workers with raw os.kill and psutil
calls and bounded elapsed time with fixed literals, so they raced the uvicorn
worker healthcheck and failed on slow CI boxes

OwnedProxy now offers kill_worker and replacing_worker, which return only once
a replacement answers readiness with its own pid, and suspended, which is
refused unless the proxy was launched with a lenient worker healthcheck.
timing.py bounds durations against a measured control or the injected delay.
run.py measures the proxy import time once and derives readiness deadlines and
the per-test timeout from it, writing boot-calibration.json

check_test_quality.py adds TQ010 (raw process signals) and TQ011 (elapsed time
asserted under a numeric literal) for tests/integration outside _support, and
every call site is migrated so both report zero with no suppressions

* test(integration): steer the assistants wire burst onto both workers

The mixed-status burst assumed the OS would spread 48 connections across both workers and failed when one worker took them all. Each half is now sent while the other worker is suspended, and the test asserts an exact 24 and 24 split

* test(integration): restore product-enforced timing bounds lost in the migration

Some TQ011 migrations dropped or loosened a bound whose time is the behaviour
under test. The websocket session cap only kept its floor, so a cap closing at
300 s would have passed, and several timeouts were bounded by the injected stall
instead of the configured product value

assert_enforced_within bounds an elapsed time by the configured value plus
explicit slack, with an optional floor. The websocket cap, the MCP validation
timeout, the guardrail litellm_params timeout, the prisma command timeouts, the
baseline projection lock timeout and the key metadata statement timeout use it.
The device code refusal keeps its 15 s margin, and the langfuse retried prompt
fetch is now bounded by a cold fetch of a steady prompt as well as by the
ignored retry-after

* fix(tests): wait for the supervisor to reap killed workers and fix real-kill migrations

The lenient worker healthcheck was the whole case budget, so uvicorn's supervisor sat
in a ping on the killed worker for up to that long before respawning it. It now uses
the graceful stop budget, and a worker kill returns only after the victim is reaped,
so pooled connections no longer race the dead worker's socket.

Several tests on main picked the multiprocessing resource tracker as their victim and
never killed a worker. Now that they kill a real one, presidio counts streams cut by
the death, delete_model waits for the config reload that removes a deleted model from
a replacement worker, and the wedged coordination Redis test kills before the wedge
and waits for every parked publish to fail before resuming Redis.

The redis cluster test imports the harness through the tests package so it collects
in the unit job, and the per-model fallback rig exposes the owned proxy it now needs.

* test(observability): only require S3 deliveries the killed worker could not have buffered

A real SIGKILL drops the victim's unflushed batch, so requests it already answered can't be expected to land. The test now requires every request served after the replacement to land, some of the surviving worker's burst share to land, and nothing unsent to land

---------

Co-authored-by: Yuneng Jiang <yuneng@berri.ai>
2026-10-12 05:27:33 -07:00
devin-ai-integration[bot]
e16d456291
test(integration): isolate every multi-worker integration suite by default (#46027)
* test(integration): isolate every multi-worker integration suite by default

Per-worker database, Redis, upstream and proxy were opt-in for management,
accounting, providers and extensions. mcp, security and cost ran 4 to 8
xdist workers against one shared proxy, database and Redis, and those suites
hold most of the integration flakes CircleCI records. Every run with more than
one worker now builds a private stack per worker, run_integration.sh no longer
starts or exports the shared proxy, upstream, database or Redis in that mode,
and each worker's scripted upstream runs in its own process instead of a
thread in the pytest controller.

Worker gateways get what the shared proxy used to provide: a peer for
management and mcp, the scripted cost map for cost, stdio MCP servers, and
coverage for mcp. mcp coverage now measures lines through sys.monitoring,
because branch measurement on CPython 3.12 uses the trace function and that
made a covered proxy take about 4x as long to become ready, which is why the
shared mcp proxy kept missing its 90 s readiness wait. Routing parity
snapshots now also read the worker databases, since its cost and mcp runs use
several workers. The security per-worker fixture is redundant and removed

* test(integration): give the nested probe root the files a worker gateway needs

Two worker probes now run isolated, so the nested controller boots a real per-worker upstream and proxy from the probe root. That upstream imports the fake OpenAI server and the cost map modules, and the proxy reads proxy_config.yaml, none of which the probe copied. The nested run also drops INTEGRATION_COVERAGE_FILE so it never writes into an outer coverage file

* test(integration): budget nested multi-worker runs for their worker stack boots

A nested run.py database run with more than one worker now boots a private database, Redis, upstream and proxy per worker, one after another, before any case runs. The fixed 60 s subprocess timeout left no room for that, so the 2 worker probes sat at 57-60 s on CircleCI. The subprocess budget is now the old 60 s plus 30 s per worker stack, and the outer pytest timeout keeps its previous 30 s of slack on top. 30 s is the slowest worker proxy readiness recorded in startup.json on the integration-cost job of workflow e09b108b (21.6-30.3 s on 4 CPUs, 2026-10-12)

---------

Co-authored-by: Yuneng Jiang <yuneng@berri.ai>
2026-10-12 03:46:06 -07:00
devin-ai-integration[bot]
4fd0051346
ci: move redis-compat and MCP unit suites from CircleCI to GitHub Actions (#46026)
The redis-compat matrix and mcp-integration ran unit tests on five large
CircleCI machines per integration run. redis-compat now runs as a redis-py
matrix in the unit workflow with the same pinned redis-server 7.2.16 binary,
no reruns, and the redis-compat Codecov flag on the 5.3.1 leg. The MCP unit
directories not already claimed by mcp-elicitation and mcp-oauth run in a new
mcp-server shard whose report is also uploaded under the mcp-integration flag.

The Windows release wheel job installs Python from a checksum-verified
python.org installer with a bounded wait instead of Chocolatey, helm chart
testing waits on the rollout instead of sleeping, and roi-database no longer
checks out the repository twice.

Co-authored-by: Yuneng Jiang <yuneng@berri.ai>
2026-10-12 02:24:31 -07:00
devin-ai-integration[bot]
102619d47a
test: migrate proxy security, schema migration and MCP legacy tests (#45937)
Some checks are pending
unit / key-generation (push) Blocked by required conditions
unit / logging-misc (push) Blocked by required conditions
unit / assert-shard-coverage (push) Waiting to run
unit / llms-openai-meta (push) Blocked by required conditions
unit / llms-providers (push) Blocked by required conditions
unit / llms-vertex-ai (push) Blocked by required conditions
unit / ui-unit (push) Waiting to run
unit / docs (push) Waiting to run
unit / OpenAI 3.25.0 compatibility (push) Waiting to run
unit / coverage (push) Blocked by required conditions
unit / jwt-and-keys (push) Blocked by required conditions
unit / mcp-oauth (push) Blocked by required conditions
unit / proxy-runtime (push) Blocked by required conditions
unit / rust-bridge (push) Waiting to run
unit / enterprise-managed-files (push) Blocked by required conditions
unit / proxy-server (push) Blocked by required conditions
unit / lens-python-310 (push) Blocked by required conditions
unit / caching-local (push) Blocked by required conditions
unit / core-utils (push) Blocked by required conditions
unit / endpoints (push) Blocked by required conditions
unit / enterprise-package (push) Blocked by required conditions
unit / enterprise-repositories-secrets (push) Blocked by required conditions
unit / integrations (push) Blocked by required conditions
unit / llms-anthropic (push) Blocked by required conditions
unit / llms-bedrock (push) Blocked by required conditions
unit / helm (push) Waiting to run
unit / OpenAI 2.20.0 compatibility (push) Waiting to run
unit / OpenAI 3.0.0 compatibility (push) Waiting to run
unit / unit passed (push) Blocked by required conditions
GitHub Actions Security Analysis / zizmor (push) Waiting to run
* test: migrate proxy security, schema migration and MCP legacy tests

* test: run the MCP proxy e2e upstream under the SDK1 peer in integration-mcp

* test: warm the baseline store before timing the locked projection

* test(e2e): hold the stack exclusively while the semantic filter flag is flipped

* test(mcp): scope the in-process proxy e2e fixtures to their module

The session-scoped autouse fixture deleted DATABASE_URL and overrode LITELLM_MASTER_KEY for the rest of the worker, which broke every later test in the integration mcp suite

* test(e2e): assert the semantic filter keeps listed tools instead of a ranking

Which Datadog tool an OpenAI embedding ranks first is not something litellm owns, so the test now checks that the kept tools are a non-empty subset of the key's listing within top_k

* test(mcp): keep the in-process proxy e2e tests on one worker

loadgroup spread the file's tests across workers and interleaved them with other files, so the module-scoped in-process proxy was torn down and restarted between tests and requests timed out

* test(mcp): name the upstream requests that carried the wrong token

The bare all() assertion hid which request broke the forwarded token, which made an intermittent CircleCI failure undiagnosable

---------

Co-authored-by: yuneng <yuneng@berri.ai>
2026-10-11 16:17:24 -07:00
yujonglee
dff8131f14
refactor(rust_bridge): route Python state reads through host modules (#45689)
* refactor(rust_bridge): group the Python modules Rust imports by name under rust_bridge/host

Rust reads Python-owned state (legacy callback registries, model capabilities) through
modules it imports by path. Put them in one folder with an AGENTS.md that states the
contract, and update the module path constants on the Rust side.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* refactor(rust_bridge): route Python state reads through host accessors

* docs(rust_bridge): point test_support at the moved host contract test

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

* refactor(rust_bridge): move secret manager, transport and timeout accessors under host

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

* chore(greptile): register rust_bridge/host AGENTS.md in files.json

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

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-11 14:10:16 -07:00
devin-ai-integration[bot]
c0ca4a51f7
fix(bedrock_mantle): send max_completion_tokens for gpt-5.6 and gpt-6 chat completions (#43982)
GPT reasoning-series models (gpt-5.x, gpt-6) on Bedrock Mantle chat completions now send max_completion_tokens, carrying a deployment or client max_tokens over with its value. Every other Mantle chat model keeps sending max_tokens.
2026-10-11 18:28:48 +00:00
devin-ai-integration[bot]
780c504e00
test: migrate tests/proxy_behavior into integration and unit tiers (#45939)
* test: migrate tests/proxy_behavior into integration and unit tiers (partial)

* test(integration): run settings-dependent management tests on an owned proxy

* test(integration): assert stored values in the rewritten management rows

* test(integration): pin sibling team allocations against the org guaranteed throughput cap

* test(integration): keep Prisma clients out of the shared integration conftest import path

---------

Co-authored-by: yuneng <yuneng@berri.ai>
2026-10-11 08:28:42 -07:00
devin-ai-integration[bot]
21cfa0eacd
ci: run every CircleCI check from the integration workflow (#45938)
* ci: run every CircleCI check from the integration workflow

* test(ci): keep the startup test CircleCI-owned

* test(ui): find reset log rows by request id so concurrent workers cannot page them out

* test(ui): retry the key budget window spec until the draft refresh fix lands

* ci(ui): set Playwright workers and retries on the CircleCI command only

The shared playwright.config.ts also drives the Buildkite UI suite, where 3 workers
ran out of memory on one of two runs. Buildkite keeps main's 1 worker and 2 retries

---------

Co-authored-by: yuneng <yuneng@berri.ai>
2026-10-11 07:39:16 -07:00
devin-ai-integration[bot]
a7a3a6b375
test: migrate legacy unit dirs and unrun folders into tests/unit, tests/integration and tests/e2e (#45940)
* test: migrate legacy unit dirs and unrun folders into tests/unit, tests/integration and tests/e2e

* test: fix disk cache collection, ungate saturation check, drop RSS memory tests

* test: assert one delivered log per completion in Datadog and LangSmith checks

* test: drop SDK-direct e2e copies and align cost-map path filter cases

---------

Co-authored-by: yuneng <yuneng@berri.ai>
2026-10-11 06:24:57 -07:00
devin-ai-integration[bot]
2a01fe6e5c
fix(home): serve the bundled whats_new.json by default so a build shows only its own launches (#45934)
* fix(home): serve the bundled whats_new.json by default so a release shows only its own launches

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 4dd96800e8)

* style: annotate whats_new_url with str | None

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit d1ae7ea085)

* test(home): pin whats_new_url to the env var and regenerate the dashboard API types

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 4bfec53865)

* test(public_endpoints): prove the /public/whats_new route serves the bundled list when no URL is configured

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

* test(public_endpoints): drop the unused os import

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

* test(home): pin whats_new_url to the env var so a baked-in default URL fails the suite

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

* style(tests): sort the import blocks ruff flagged in test_public_endpoints

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

* test(home): let the route test read the real whats_new_url default so a baked-in URL fails it

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

---------

Co-authored-by: mateo <mateo@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-11 02:01:56 -07:00
devin-ai-integration[bot]
3090f4b23e
fix(ci): isolate integration workers and repair test fixtures (#45863)
* test(integration): wait for customer spend rows and use owned OpenRouter cost

* ci: isolate integration workers and clean up resources after crashes

* docs: describe isolated extensions workers and shard census

* fix(ci): restore integration service and fixture guarantees

* fix(integration): preserve replay IDs and native route fixtures

* fix(tests): scope integration harness imports to each unit case

* fix(ci): preserve fixtures and wait for owned workers

* fix(ci): isolate nested runs and telemetry cases

* fix(ci): make worker readiness and fault tests deterministic

* chore(ci): drop MCP fixture repair already covered by main

* chore(ci): keep the local catalog fix from main

---------

Co-authored-by: yuneng <yuneng@berri.ai>
2026-10-11 01:56:02 -07:00
devin-ai-integration[bot]
e0398455d0
test: migrate tests/llm_translation into unit, integration and e2e tiers (#45759)
* test: migrate selected llm translation contracts

* test: migrate anthropic completion translation tests

* test: migrate bedrock and cohere translation tests

* test: tighten bedrock translation migration

* test: migrate azure and openai model translation tests

* test: migrate openai and small-provider translation tests

* test: migrate gemini and vertex translation tests

* test: migrate optional params and rerank translation tests

* test: migrate huggingface, json and openrouter translation tests

* test: fix openrouter integration expectations

* test: migrate databricks, xai, cometapi and fireworks translation tests

* test: migrate ovhcloud, prompt and small provider translation tests

* test: split reasoning effort grid into unit and e2e

* test: migrate router and realtime guardrail translation tests

* test: migrate google interactions translation tests

* test: migrate a2a, evals, skills and hosted vllm translation tests

* test: remove remaining llm translation suite

* test: tighten migrated llm translation unit tests and land missing rows

Restores rows the first pass dropped or weakened (bedrock agentcore and openwebui thinking stream, anthropic prefix, citations and tool_choice, azure agents handler, huggingface bare api_base, optional params num_retries, alternating roles, rerank response type), replaces truthiness and call-count checks with whole-value assertions, and moves tests to the mirror file of the code they cover

* test: move cohere, databricks, fireworks and gemini rows to mirror files over mocked HTTP

Restores three TestCohereV2Transform methods the first pass nested out of collection, replaces direct transform calls with respx-backed completion calls, and drops the databricks and fireworks files that sat outside their mirror paths

* test: close lost-intent gaps found in review of the llm translation migration

Points the hosted-mock guard at the triton test's new integration path, restores exact rerank result assertions for infinity, drops the reasoning e2e fallback that passed for any multi-line answer, and adds the mixtral invoke system prompt variants, eval deletion, and async pdf url download that the legacy suite exercised

* test: assert provider acceptance in the reasoning effort e2e

The live half of the split grid proves each route accepts reasoning_effort. claude-fable-5-1 on the direct route answers without surfacing reasoning content, so a reasoning-presence check either fails on head or needs a fallback that passes for any answer. Wire shape stays covered by the unit grid

* test: cover async and stream-end paths the legacy translation suite exercised

Adds async variants for bedrock converse file and thinking content, bedrock embedding timeout and region resolution, interaction stream termination and success logging, xai reasoning token folding, and bytes chunks with a prefix before data:. Also scopes the vertex safety settings global in test_vertex_safety_settings with monkeypatch so it stops leaking into gemini request bodies on the same worker

* test: type the new llm translation e2e calls and mark moved fixture dirs as packages

* test: name the reasoning effort e2e models as module constants

* test: assert reasoning content, register the new gemini coverage ids and give the guardrail config e2e a unique name

* test: block the prompt the shared guardrail denies and drop the reasoning presence check

* test: drop the duplicate litellm import left by the main sync

---------

Co-authored-by: yuneng <yuneng@berri.ai>
2026-10-11 07:58:53 +00:00
devin-ai-integration[bot]
1dbde0845e
test: migrate SDK and proxy-booting legacy CircleCI tests to their tiers (#45758)
* test: move guardrails, image, audio, batches, search legacy tests to unit

* test: restore the custom guardrail and remaining chunk 1 unit rows

* test: move the ocr matrix to e2e

* test: drop comments from moved tests and fix vertex ocr credentials

* test: move litellm utils and unified google legacy tests to their tiers

* test: move logging callback and pass-through unit legacy tests to their tiers

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

* test: move store_model_in_db legacy tests and start the admin ui migration

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

* test: finish the proxy job rows and drop their CircleCI jobs

Moves the remaining multi-instance, openai endpoint, otel, pass-through and
top-level proxy tests into tests/integration with scripted upstreams, rewrites
the weak replacements to assert the outbound wire and exact responses, and
removes the build_and_test job group this PR owns from CircleCI

* test: tighten the key generation and error log assertions, rename migrated unit files to their mapped names

* test: shard the pagerduty unit tests and record the rust harness file on the coverage allowlist

* test: drive the SSO sign-in tests through a scripted IdP and isolate the cost center stand-in

* test: type the e2e beta header, prompt cache and secret manager values

* test: assert the missing model error message on the OpenAI routes

* test: drop the deleted otel base class import and restore mcp redaction and exact langfuse usage checks

* test: make the langfuse fixture directory a package for the layout check

* test: restore collected no-match cases, real langfuse and gcs payload checks, and gate the aws secret lane

* test: keep the ocr e2e pdf fixture next to the test

* test: put meta below covers on the streaming tool search e2e

* test: run the OCR matrix against a scripted upstream and fix two runner-only e2e failures

* test: count only OCR calls in the OCR matrix recorder

* test: pin OCR parse bodies and billed cost, group new e2e cases into classes

* ci: restore the python image anchor dropped in the main sync

---------

Co-authored-by: yuneng <yuneng@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-11 00:17:21 -07:00
devin-ai-integration[bot]
ca0ff24726
fix(databricks): call the ai_decide AI Function route for decisions and the auto-router (#45722)
* fix(databricks): call the ai_decide AI Function route for decisions and the auto-router

Databricks serves ai_decide at POST <host>/api/2.0/ai-functions/ai-decide, not
on a serving endpoint's /invocations route. The decisions provider and the
auto-router classifier now accept only the ai_decide model, post to that route
without a model field, unwrap the response envelope, and map a noul answer's
probability to the System One noul field.

* test(databricks): bound the megabyte model name test by scaling, not wall time

* test(databricks): assert the whole OpenAI-format decision and floor the liveliness bound

* test(decisions): move the Databricks OpenAI-format wire row to the ai_decide route

* fix(databricks): keep serving endpoint decisions beside the ai_decide route

* test(databricks): assert the whole classifier request body in the test routing case

* test(databricks): correct System One spend call type

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

---------

Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
Co-authored-by: mateo <mateo@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-10 23:58:16 -07:00
devin-ai-integration[bot]
5390199d63
test: model the team membership lookup in MCP DCR admission fixtures and assert decisions call types per route (#45917)
Co-authored-by: mateo <mateo@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-10 22:08:01 -07:00
joshua-berri
2ab80ba4fa
feat(ui): streamline auto-router setup with deployed decision models (#45913)
* refactor(ui): simplify Jev auto-router creation

* refactor(ui): polish auto-router classifier presentation

* refactor(ui): clarify auto-router configuration sections

* refactor(ui): align router templates and optional settings

* feat(router): support deployed decision classifiers

* refactor(ui): select onboarded decision models

* style(ui): remove divider before router advanced settings

* test(ui): cover decision deployment catalog selection

* fix(router): tighten decision adapter types and regression checks

* fix(ui): preserve deployed decision model editing

* test(ui): use supported decision picker query options

* style(ui): format decision model selection regression

* test(router): verify deployed classifier cost and provider accounting

---------

Co-authored-by: Joshua Valluru <326636767+joshua-berri@users.noreply.github.com>
2026-10-10 20:49:59 -07:00
devin-ai-integration[bot]
55c89977d7
feat(ui): load Home page What's new launches from /public/whats_new at runtime (#45912)
Some checks failed
unit / caching-local (push) Blocked by required conditions
unit / core-utils (push) Blocked by required conditions
unit / endpoints (push) Blocked by required conditions
unit / enterprise-package (push) Blocked by required conditions
unit / enterprise-repositories-secrets (push) Blocked by required conditions
unit / integrations (push) Blocked by required conditions
unit / llms-bedrock (push) Blocked by required conditions
unit / llms-openai-meta (push) Blocked by required conditions
unit / llms-providers (push) Blocked by required conditions
unit / llms-vertex-ai (push) Blocked by required conditions
unit / lens-python-310 (push) Blocked by required conditions
unit / llms-anthropic (push) Blocked by required conditions
unit / proxy-auth (push) Blocked by required conditions
unit / proxy-endpoints (push) Blocked by required conditions
unit / proxy-extras (push) Blocked by required conditions
unit / proxy-feature-endpoints (push) Blocked by required conditions
unit / proxy-hooks-client (push) Blocked by required conditions
unit / proxy-infra (push) Blocked by required conditions
unit / ui-unit (push) Waiting to run
unit / docs (push) Waiting to run
unit / helm (push) Waiting to run
unit / OpenAI 2.20.0 compatibility (push) Waiting to run
unit / OpenAI 3.0.0 compatibility (push) Waiting to run
unit / OpenAI 3.25.0 compatibility (push) Waiting to run
GitHub Actions Security Analysis / zizmor (push) Waiting to run
unit / mcp-elicitation (push) Blocked by required conditions
unit / coverage (push) Blocked by required conditions
unit / unit passed (push) Blocked by required conditions
Terraform Provider / gofmt, vet, build, test (push) Has been cancelled
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Has been cancelled
* feat(ui): load the Home page What's new launches from /public/whats_new at runtime

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

* feat(ui): show the three newest What's new launches

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

* build: ship whats_new.json in the wheel

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

---------

Co-authored-by: kerry <kerry@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-10 19:42:18 -07:00