Commit graph

48433 commits

Author SHA1 Message Date
Conduct AI
9b96b8f499 fix: real stub class in the missing-package fallback
Runtime regression in the previous simplification — the guardrail
registry iterates every registered class at load time and calls
get_supported_event_hooks(). Fallback of ConductGuardrail = None
crashed the whole registry with AttributeError, which cascaded into
unrelated guardrails' tests (noma_v2, repelloai, hide_secrets,
provider_specific_params, etc.).

Fallback now defines ConductGuardrail as a real subclass of
CustomGuardrail with the required class attrs (SUPPORTED_EVENT_HOOKS
+ get_supported_event_hooks). Matches the pattern the
guardrails_ai integration already uses in the same repo.
raise_if_missing_package still fires before instantiation so users
see the friendly pip install error.

All four budget gates re-verified locally against
upstream/litellm_internal_staging:
  ruff_strict_gate    OK
  test_quality_gate   OK
  type_discipline_gate OK
  type_check_gate     OK
2026-09-11 20:26:32 +00:00
Conduct AI
185b12c4aa refactor: shim becomes a pure alias, hooks now on plugin's ConductGuard
Plugin conduct-litellm-guard 0.2.3 ships SUPPORTED_EVENT_HOOKS +
get_supported_event_hooks on ConductGuard directly. The upstream
shim's subclass wrapper is now redundant — dropping it clears every
strict-rule budget gate (ruff-strict / test-quality /
type-discipline / basedpyright) in one pass.

Changes:
- conduct.py: subclass removed; ConductGuardrail is now an alias for
  the plugin's ConductGuard (no dynamic base class, no reassignment,
  no # type: ignore). raise_if_missing_package helper unchanged.
- test file: _IMPORT_ERROR → _import_error rename to satisfy
  reportConstantRedefinition (basedpyright treats SCREAMING_CASE as
  constant). Also drops unused sys import.
- Pin bumped to conduct-litellm-guard>=0.2.3 in the module docstring.

Verified all four LiteLLM gate scripts locally against
upstream/litellm_internal_staging:
  ruff_strict_gate    OK
  test_quality_gate   OK
  type_discipline_gate OK
  type_check_gate     OK
2026-09-11 20:26:31 +00:00
Conduct AI
33d974dd13 style: explicit assert on noop test (TQ001 zero-assert budget)
BerriAI/litellm CI's test-quality budget flagged
test_raise_if_missing_package_is_noop_when_present as a zero-assert
test (TQ001). Make the intent explicit: raise_if_missing_package()
must return None when the package IS installed.
2026-09-11 20:26:31 +00:00
Conduct AI
4b26d083cc style: satisfy type-discipline budget (LIT008, LIT009)
BerriAI/litellm CI's type-discipline budget check flagged the
subclass __init__ shim. Fixes:

- Drop the __init__ override entirely — the subclass now inherits
  __init__ from _BaseConductGuard (when the standalone package is
  installed) or from CustomGuardrail (fallback). Removes both the
  banned **kwargs (LIT008) and all four inert # type: ignore markers
  (LIT009 x 4).
- Move the missing-package check into a dedicated
  raise_if_missing_package() helper called by
  initialize_guardrail before construction. Preserves the
  cursor[bot] fix (silent-drop-on-import-failure) without needing
  a custom __init__.
- Fallback branch aliases _BaseConductGuard = CustomGuardrail
  directly, no type-ignore comment needed.
- Test updated to exercise the helper instead of the removed
  __init__ path; new companion test asserts the helper is a no-op
  when the package IS installed.

Local: ruff --select ANN,TID passes clean. ruff format applied.

Same behavioral surface — user-visible error message unchanged.
2026-09-11 20:26:31 +00:00
Conduct AI
16bb91a05a style: satisfy strict-rule budget (ANN201, ANN401, TID251)
BerriAI/litellm CI's ruff strict-rule budget check flagged four new
violations on the conduct shim. Fixes:

- __init__.py: add return type annotation on initialize_guardrail
  (ANN201)
- conduct.py: swap Any → object on __init__(*args, **kwargs) so the
  signature stays permissive without dynamically-typed Any (ANN401)
- conduct.py: drop the now-unused Any import (TID251)

Ruff --select ANN,TID passes locally.
2026-09-11 20:26:31 +00:00
Conduct AI
a506f82297 style: remove redundant noqa on re-exported GuardDecision
Ruff lint flagged this as unused because GuardDecision is re-exported
via __all__. Removing the noqa satisfies ruff without changing behavior.
2026-09-11 20:26:31 +00:00
Conduct AI
3c886cf3dc style: ruff format on the conduct guardrail shim + tests
Lint job on #38143 flagged three files as needing reformat. No
behavior change — just ruff-format's chosen line breaks and quoting.
2026-09-11 20:26:31 +00:00
Conduct AI
d8201bfd98 address review findings on #38143 (yucheng-berri, cursor, veria-ai, devin)
Rename fail_mode → unreachable_fallback (typed field)
─────────────────────────────────────────────────────
The shim was reading a free-form ``fail_mode`` field; a typo silently
defaulted the plugin to fail-open behavior. Switch to the typed
``LitellmParams.unreachable_fallback`` field so Pydantic validates the
value at config load. The plugin's constructor kwarg stays as
``fail_mode`` — the initializer maps the typed field onto it.
(yucheng-berri, devin-ai-integration)

Fix timeout default (was silently discarded)
────────────────────────────────────────────
``getattr(litellm_params, "timeout", 8.0)`` only applied the default
when the attribute was missing; ``LitellmParams.timeout`` always
exists and defaults to ``None``, so the intended 8-second budget was
never used. Change to ``getattr(..., None) or 8.0`` so ``None`` (and
``0``) fall through to the default.
(cursor[bot])

Move ImportError from module-load to __init__
─────────────────────────────────────────────
Raising ImportError at module load caused the guardrail-hook
auto-discovery loop to silently drop the registration when
``conduct-litellm-guard`` was missing. Users saw configs load with
no guardrail active and no error. Import lazily; raise the friendly
``pip install`` error at ``ConductGuardrail.__init__`` when
actionable.
(cursor[bot])

Advertise only supported event hooks
────────────────────────────────────
``during_call`` mode was advertised in the guardrail config but the
class never overrode ``async_moderation_hook`` — every request in that
mode silently bypassed policy. Override ``get_supported_event_hooks``
to return only ``pre_call`` so LiteLLM validates configs against
supported modes at load time. ``during_call`` / ``post_call`` support
lands with plugin 0.3.x once the underlying response-gate is wired
through ``guard_check_response``.
(veria-ai)

Text-completion + full-turn prompt scanning
───────────────────────────────────────────
Fixed in the standalone package: ``conduct-litellm-guard 0.2.2``
(BerriAI/litellm PR #38143 companion, shipping to PyPI shortly).
Pinned in the docstring here as the minimum supported version.
(veria-ai — text_completion bypass + 4KB truncation)

Tests
─────
  * ``test_only_pre_call_event_hook_advertised`` — regression for
    ``during_call`` silent-bypass finding
  * ``test_initialize_prefers_typed_unreachable_fallback`` — regression
    for typo silent-fail-open finding
  * ``test_initialize_applies_timeout_default_when_field_is_none`` —
    regression for silently-discarded 8.0 default
  * ``test_missing_standalone_package_raises_at_construction`` —
    regression for silent-drop-on-import-failure finding (previous
    module-load raise replaced with lazy import + init-time raise)
2026-09-11 20:26:31 +00:00
Sudhi Seshachala
116fc4220c test(conduct): cover initialize_guardrail to raise patch coverage
Codecov flagged the __init__.initialize_guardrail body as uncovered
(30% patch coverage on that file). Added a test that mocks
litellm.logging_callback_manager and calls initialize_guardrail with
a SimpleNamespace stand-in for LitellmParams — exercises the full
function body and confirms the callback is registered.
2026-09-11 20:26:31 +00:00
Sudhi Seshachala
fb653049be test(conduct): skip smoke tests when conduct-litellm-guard not installed
The wrapper module imports its runtime from the conduct-litellm-guard
PyPI package. When the package is not installed in the CI environment,
the smoke tests can't verify wiring (the import raises before any test
runs). Use pytest.importorskip so BerriAI's default CI env doesn't
fail on this integration, while environments that do install the
package (via 'pip install conduct-litellm-guard[dev]' or similar)
still get the smoke coverage.

Full behavioural test coverage lives in the conduct-litellm-guard
package's own CI.
2026-09-11 20:26:31 +00:00
Sudhi Seshachala
b3443ac429 refactor: slim upstream adapter — import from conduct-litellm-guard PyPI
The full adapter (response parser, session-ID chain, fail-mode logic,
HTTP client) lives in the conduct-litellm-guard package on PyPI. The
upstream tree hosts a thin re-export + the LiteLLM registration wiring.

Matches the Aporia / Lakera pattern — vendor SDK on PyPI, upstream
integration is a tiny adapter.

Benefits:
- Passes ruff-strict-budget and type-discipline-budget without new
  violations.
- Users get the same install experience as any other guardrail vendor:
    pip install conduct-litellm-guard
- Vendor keeps ownership of the parser + fail-mode semantics; upstream
  keeps a stable interface.

Tests slimmed to smoke coverage (imports work, class is a
CustomGuardrail, enum + registries wired, missing-package error path).
Full behavioural coverage stays in the PyPI package.

Local runs of both scripts/ruff_strict_gate.py and
scripts/type_discipline_gate.py against upstream/litellm_internal_staging:
both pass.
2026-09-11 20:26:31 +00:00
Sudhi Seshachala
4b01f5f4f1 chore: annotate **kwargs to satisfy ANN003 strict rule
Removing 'Any' in the prior commit left **kwargs untyped, which
tripped ANN003 (missing type annotation on **kwargs). Using 'object'
threads the strict-rule budget cleanly.
2026-09-11 20:26:31 +00:00
Sudhi Seshachala
d73458c0c7 chore: drop typing.Any to satisfy strict-rule budget
BerriAI's ruff strict-rule budget caps ANN401 (Any type annotation)
and TID251 (banned import) totals. Aligning with the CustomLogger
base signature (data: dict, cache: object, **kwargs untyped)
eliminates all Any uses in the module. Local tests still pass 15/15.
2026-09-11 20:26:31 +00:00
Sudhi Seshachala
14cd72a9e4 chore: fix ruff lint errors
- Remove unused TYPE_CHECKING import (F401).
- Un-quote self-forward-ref type annotation (UP037).
- Suppress BLE001 on transport-fallback broad-except (intentional).
2026-09-11 20:26:31 +00:00
Sudhi Seshachala
7dc00068d7 chore: ruff format for conduct guardrail
Fixes lint check on the upstream PR.
2026-09-11 20:26:31 +00:00
Sudhi Seshachala
7788ba1b6a feat(guardrails): add ConductGuard integration
Adds Conduct Guard as a first-class LiteLLM guardrail. Point any
LiteLLM proxy at Conduct and every LLM call routed through it is
policy-checked before the upstream request goes out — block, warn,
audit, or trigger a human-in-the-loop approval, with the same signed
configuration + hash-chained audit log Conduct exposes on its native
enforcement surfaces.

- litellm/types/guardrails.py: add CONDUCT to SupportedGuardrailIntegrations.
- litellm/proxy/guardrails/guardrail_hooks/conduct/__init__.py: registration
  via guardrail_initializer_registry and guardrail_class_registry, picked
  up by the auto-discovery in guardrail_registry.py.
- litellm/proxy/guardrails/guardrail_hooks/conduct/conduct.py: the adapter.
  CustomGuardrail subclass, async_pre_call_hook, response envelope parser
  for the five Conduct verdicts (ok / advisory / WARNING / BLOCKED /
  PENDING approval), fail-mode logic, session-ID resolution chain
  (litellm_metadata.trace_id → X-Conduct-Session-Id → hash fallback).
- tests/test_litellm/proxy/guardrails/test_conduct_guardrail.py: envelope
  parsing, pre-call allow/block/approval, config precedence, missing-token
  construction error.

```yaml
guardrails:
  - guardrail_name: conduct-guard
    litellm_params:
      guardrail: conduct
      mode: pre_call
      api_base: https://api.conductai.ai      # optional, default
      api_key: os.environ/CONDUCT_AGENT_TOKEN # cond_agt_* token
      fail_mode: fail_closed                   # or fail_open
      tool_name: llm_call                      # scoped tool_name
```

A standalone PyPI package `conduct-litellm-guard` shipped ahead of this
PR for teams pinned to older LiteLLM versions. Once this integration
merges, the standalone README will point at the native support as the
preferred path.

- PyPI: https://pypi.org/project/conduct-litellm-guard/
- Product: https://conductai.ai/guard

Contact: sudhi@b2bsphere.com
2026-09-11 20:26:31 +00: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
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
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
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
devin-ai-integration[bot]
db3338b206
feat(proxy): make the in-memory management cache capacity configurable (#40725)
* feat(proxy): make the in-memory management cache capacity configurable

Add general_settings.user_api_key_cache_max_size (positive int, default 200) to resize the
in-memory tier of the shared user_api_key_cache at startup and on DB config reloads, expose it
in the Admin UI general settings, and cover it with behavioral tests. Prior art: #34726

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

* fix(caching): resize the in-memory tier from DualCache so any cache instance honours the cap

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

* style(proxy): wrap the cache capacity field description to the 120 col limit

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

---------

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 09:55:30 -07:00
devin-ai-integration[bot]
de79310954
feat(secret_managers): support customer-managed KMS key for virtual keys stored in AWS Secrets Manager (#40475)
Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 09:54:08 -07:00
devin-ai-integration[bot]
47bba14336
fix(passthrough): parse Bedrock stream spend incrementally instead of buffering the whole response (#40724)
* fix(passthrough): parse Bedrock stream spend incrementally instead of buffering the whole response

Bedrock pass-through streaming kept every relayed chunk in memory until EOF and
then decoded, parsed and translated the whole stream again for spend logging.
Large or concurrent streams could exhaust proxy worker memory.

Sync and async passthrough wrappers now hand each chunk to a provider stream
collector as it is relayed. Bedrock decodes event-stream frames incrementally,
folds consecutive text deltas, and keeps only what stream_chunk_builder needs
for usage, tool calls and metadata. Text deltas are no longer retained in the
Bedrock and Anthropic stream decoders either. Providers without a collector
keep the previous raw-bytes behavior. Collector failures are isolated so spend
tracking can never interrupt the customer stream

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

* test(passthrough): assert the spend payload the collector builds instead of mock internals

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

* test(passthrough): type the Bedrock collector helpers by the collector protocol instead of asserting the class

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

---------

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 09:53:37 -07:00
devin-ai-integration[bot]
3df127b439
fix(proxy): give user-key objects their own in-memory cache partition (#40713)
Key objects share the 200-entry UserApiKeyCache in-memory store with teams,
end users, tags and memberships, so churn in those objects evicts hot keys
and forces a LiteLLM_VerificationToken lookup on the next request. Route
bare hashed-token keys to a dedicated InMemoryCache inside UserApiKeyCache
while keeping Redis, TTL, serialization and invalidation shared

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 09:52:09 -07:00
devin-ai-integration[bot]
729ea6b832
perf(proxy): lazy-load provider passthrough routes (#40691)
Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 09:48:53 -07:00
Joshua Valluru
3883a891f0 fix(mcp): redact compact credential field names 2026-09-11 08:10:19 -07:00
Joshua Valluru
5c190e69bf fix(mcp): preserve timeout fallback on Python 3.10 2026-09-11 08:00:39 -07:00
Mateo Wang
67cb34ceee
Merge pull request #40606 from BerriAI/litellm_registry_audit_2026_09_10b 2026-09-11 08:00:04 -07:00
Joshua Valluru
e8c411fb43 test(mcp): cover deeply nested credential inspection limits 2026-09-11 07:32:38 -07:00
Joshua Valluru
5b13dfcc59 fix(mcp): omit credential-bearing paths from failure logs 2026-09-11 07:27:10 -07:00
Joshua Valluru
0ee9e1e448 fix(mcp): redact reflected credentials and avoid import cycles 2026-09-11 07:20:48 -07:00
Joshua Valluru
40f01e2fa5 chore: merge current staging into MCP OAuth fix 2026-09-11 07:07:07 -07:00
Joshua Valluru
8d5a675878 fix(mcp): expire temporary OAuth discovery results 2026-09-11 07:02:11 -07:00