Commit graph

39118 commits

Author SHA1 Message Date
Ryan Crabbe
0ccdc91dc5
ci(mutation): scope to whole management_endpoints folder, drop temp push trigger
Final scope before merge:
- paths_to_mutate / tests_dir broadened from one file to the entire
  management_endpoints source/test folders
- Trigger is now `workflow_dispatch` only — the temporary push: block
  used during workflow iteration is removed
- timeout-minutes bumped from 60 to 350 (just under the GH-hosted job
  cap of 360); whole-folder mutation against ~15 files / ~7.5k LOC can
  take a few hours
- Artifact path for the trampoline files glob-expanded to cover all
  files under mutants/litellm/proxy/management_endpoints/
2026-05-11 18:05:25 +00:00
Ryan Crabbe
c1a316c284
feat(mutation report): full Meta ACH-style rendering with MUTANT delimiters
For each surviving mutant, parse the mutmut sandbox trampoline file and
render the mutated function as it appears in the source — with the
differing lines wrapped in `# MUTANT START` / `# MUTANT END` comments,
matching the format from Meta's ACH paper (arXiv 2501.12862, Table 1).
Renames the function header back to its original name so the agent sees
the function as it would appear in the file. Falls back to the unified
diff if the trampoline lookup fails.

Handles replace, insert, and delete diff ops; uses difflib's
SequenceMatcher to find the differing line ranges.

The unified diff is preserved in a collapsible <details> block as
secondary context.
2026-05-11 18:05:25 +00:00
Ryan Crabbe
5289bd9ebe
fix(mutation report): correctly parse function names with leading underscores
mutmut's mutant-name prefix is x_ (single underscore), so a function
named _foo produces mutants x__foo__mutmut_N. The previous regex
\.x__(.+)__mutmut_ ate the function's leading underscore as part of
the prefix. Changed to \.x_(.+)__mutmut_ so leading underscores are
preserved in the captured function name; verified for normal, leading-
underscore, and dunder-method names.
2026-05-11 18:05:25 +00:00
Ryan Crabbe
c2098389b2
ci(mutation): generate ACH-style report with embedded function bodies
Replaces the inline bash markdown generation with a Python script that:
- Groups survivors by function (one section per function, function body
  shown once per section, surviving mutants nested as subsections)
- Embeds each enclosing function's source via Python AST (so the agent
  has full context, not just a 3-line `mutmut show` diff)
- Inlines the existing test file(s) listed in [tool.mutmut].tests_dir
- Writes an ACH-style task description at the bottom following the
  prompt template from arXiv 2501.12862

Output goes to mutation-report.md (artifact) and the head of the file
is appended to $GITHUB_STEP_SUMMARY for at-a-glance visibility.
2026-05-11 18:05:25 +00:00
Ryan Crabbe
c6725587d5
ci(mutation): document intended manual weekly cadence in trigger comment 2026-05-11 18:05:25 +00:00
Ryan Crabbe
238126165f
ci(mutation): emit per-survivor diffs to run-page summary + artifact
The previous artifact only contained `mutmut results` text (which in
mutmut 3.x lists survivor names but not the actual mutations). Adds:

- `mutmut export-cicd-stats` to produce mutmut-cicd-stats.json with the
  killed/survived/total scoreboard.
- `mutmut show <name>` per surviving mutant to capture each mutation as
  a unified diff.
- A `mutmut-report.md` that combines summary + run-progress tail +
  per-survivor diffs, written to both the artifact and
  $GITHUB_STEP_SUMMARY (visible on the run page, no download needed).
- Corrected artifact paths: stats files live under mutants/, not the
  project root.
- The trampolined source file from the sandbox so survivors can be
  inspected even outside `mutmut show`.
2026-05-11 18:05:25 +00:00
Ryan Crabbe
3bd003c254
ci(mutation): uninstall pytest-retry before mutmut runs
`-p no:retry` (and similar names) didn't match pytest-retry's
entry-point name, so the plugin still loaded and crashed during
mutmut's "Running clean tests" phase. Uninstalling the package is
surgical and doesn't depend on guessing the entry-point name.
2026-05-11 18:05:25 +00:00
Ryan Crabbe
2462681c62
ci(mutation): disable rerun and xdist plugins for mutmut runs
mutmut's in-process pytest.main() call hits
`INTERNALERROR: no option named 'filtered_exceptions'` from
pytest-retry's pytest_configure hook. Reruns are also wrong for
mutation testing — a "failed" mutant test that gets retried would
mask which mutants are killed vs. survive. Disable retry,
rerunfailures, and xdist via pytest_add_cli_args in [tool.mutmut].
2026-05-11 18:05:25 +00:00
Ryan Crabbe
94e491b554
ci: add manually-triggered mutation testing smoke workflow
Adds a workflow_dispatch-only GitHub Actions workflow that runs mutmut
against a single source/test pair (router_settings_endpoints) to validate
the tooling end-to-end before scaling.

The workflow reinstalls litellm non-editable so the mutants/ sandbox is
not shadowed by the editable .pth on sys.path, and sets PYTHONPATH so
the trampolined sandbox copy wins over site-packages.

mutmut itself is pulled in via uv run --with so it does not appear in
uv.lock or affect the shared dev environment.

Includes a temporary push: trigger scoped to this branch so we can
iterate before the workflow file lands on the default branch — to be
removed before merging (workflow_dispatch only requires the file on the
default branch to surface the manual trigger button).
2026-05-11 18:05:25 +00:00
ishaan-berri
12e59c8798
Fix internal tag usage scoping (#27315)
* Scope internal tag usage to own keys

Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>

* Add internal tag usage unowned key regression test

Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>

* Handle empty internal tag usage scopes safely

Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>

* Add tag activity database guard

Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>

---------

Co-authored-by: oss-agent-shin <279349115+oss-agent-shin@users.noreply.github.com>
Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>
2026-05-11 10:44:50 -07:00
Sameer Kankute
5e016f9f74
fix(responses): normalize chat tool_choice for completions→responses bridge (#27634)
* fix(responses): map chat tool_choice to Responses API when bridging from completions

OpenAI /v1/responses rejects tool_choice.function. Normalize forced-function
choice from chat shape to {type, name} in LiteLLMResponsesTransformationHandler.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(responses): strip tool_choice.function when top-level name is set

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 10:24:34 -07:00
Sameer Kankute
4c1d91d96f
fix(anthropic): inject dummy tool without modify_params (#27620)
Anthropic rejects tool_use/tool_result when tools is omitted. Always map
and attach the dummy tool in transform_request so CLIs work without
litellm.modify_params.

- Add unit test for transform_request dummy tool with modify_params off
- Adjust parallel function calling integration expectations: Bedrock
  Converse still requires modify_params for this path

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 09:50:16 -07:00
Sameer Kankute
9bc90f6d1b
chore: remove accidental .evidence screenshot from repo (#27633)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 08:57:59 -07:00
Sameer Kankute
aa587bd9d3
Merge pull request #27549 from BerriAI/shin_agent_oss_staging_05_09_2026
[litellm-agent] Staging → litellm_internal_staging (5/9/2026)
2026-05-11 11:58:26 +05:30
Sameer Kankute
9ed99037d2
Merge pull request #27422 from BerriAI/shin_agent_oss_staging_05_07_2026
[litellm-agent] Staging → litellm_internal_staging (5/7/2026)
2026-05-11 11:58:05 +05:30
Sameer Kankute
055bdc3507
fix(auth): harden JWT routing wildcard iss and merge list team_id claims
Reject fnmatch wildcards on non-scope claims when the claim string contains
whitespace so malformed iss values cannot match patterns like trusted.*.

Merge every entry when team_id_jwt_field resolves to a list instead of
keeping only the first element.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 11:35:56 +05:30
Sameer Kankute
083d87a396
Merge branch 'litellm_internal_staging' into shin_agent_oss_staging_05_09_2026 2026-05-11 11:35:00 +05:30
Sameer Kankute
c7e6bcc48f
Merge pull request #27256 from BerriAI/litellm_agent_oss_staging_05_06_2026
[litellm-agent] Staging → litellm_internal_staging (5/6/2026)
2026-05-11 11:01:45 +05:30
Sameer Kankute
99218c6fa0
Fix deprecated model test
Some checks failed
Unit Tests: Caching (Redis) / caching-redis (push) Has been cancelled
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
Unit Tests: Proxy DB Operations / auth-checks (push) Has been cancelled
Unit Tests: Proxy DB Operations / budgets (push) Has been cancelled
Unit Tests: Proxy DB Operations / custom-logging (push) Has been cancelled
Unit Tests: Proxy DB Operations / db-and-spend (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-runtime (push) Has been cancelled
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Has been cancelled
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Has been cancelled
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Has been cancelled
Unit Tests: Proxy DB Operations / key-generation (push) Has been cancelled
Unit Tests: Proxy DB Operations / logging-misc (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-server-core (push) Has been cancelled
Unit Tests: Proxy DB Operations / schema-migration (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-utils (push) Has been cancelled
2026-05-11 09:49:47 +05:30
Sameer Kankute
ce17e9490f
Merge branch 'litellm_internal_staging' into litellm_agent_oss_staging_05_06_2026 2026-05-11 09:07:08 +05:30
ryan-crabbe-berri
0af33fbe70
fix(ui): omit allowed_routes from key edit save when unchanged (#27553)
Some checks failed
Unit Tests: Caching (Redis) / caching-redis (push) Has been cancelled
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
Unit Tests: Proxy DB Operations / auth-checks (push) Has been cancelled
Unit Tests: Proxy DB Operations / budgets (push) Has been cancelled
Unit Tests: Proxy DB Operations / custom-logging (push) Has been cancelled
Unit Tests: Proxy DB Operations / db-and-spend (push) Has been cancelled
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Has been cancelled
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Has been cancelled
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Has been cancelled
Unit Tests: Proxy DB Operations / key-generation (push) Has been cancelled
Unit Tests: Proxy DB Operations / logging-misc (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-runtime (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-server-core (push) Has been cancelled
Unit Tests: Proxy DB Operations / schema-migration (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-utils (push) Has been cancelled
* fix(ui): omit allowed_routes from key edit save when unchanged

When a team admin opens Edit Settings on a key with key_type=AI APIs and
saves without changing anything, the UI re-sends the existing allowed_routes
value, which the backend's _check_allowed_routes_caller_permission gate
rejects for non-proxy-admins (LIT-2681).

Strip allowed_routes from the patch in handleSubmit when it deep-equals the
original keyData.allowed_routes. The backend treats absence as "leave alone,"
so no-op saves now succeed for non-admins. Admins explicitly editing the
field still send the new value.

* fix(ui): order-insensitive allowed_routes diff + cover null-original case

Address Greptile review:

- Switch the "is allowed_routes unchanged" check to a Set-based comparison so
  a server-side reorder of the array doesn't register as a user edit and
  re-trigger LIT-2681.
- Add two regression tests: (1) keyData.allowed_routes is null and the form
  is untouched — patch should strip the field; (2) server returned routes in
  a different order than the user originally entered — patch should still
  recognize the value as unchanged.

* chore(ui): strip ticket refs and tighten comments in key edit fix

- Remove internal-tracker references from in-code comments
- Tighten the WHY comment in handleSubmit to two lines
- Drop redundant test-block comments — test names already describe the case

* fix(ui): annotate Set<string> generic in allowed_routes diff to fix tsc
2026-05-09 19:01:58 -07:00
oss-agent-shin
9f68d2bb77
Fix: tag budget reset must drop stale management-cache entry (#27568)
Squash-merged by litellm-agent from oss-agent-shin's PR.
2026-05-10 00:18:55 +00:00
Michael-RZ-Berri
02edaef50c
fix: reset org and tag budgets (#27326)
* reset org budgets

* reset tag budgets

---------

Co-authored-by: Michael Riad Zaky <michaelr@Mac.localdomain>
2026-05-09 19:15:32 -04:00
Shivam Rawat
c7739c9ed5
feat: add ability to auth to azure with token (#27556)
Squash-merged by litellm-agent from shivamrawat1's PR.
2026-05-09 22:34:09 +00:00
Michael-RZ-Berri
b888177ea6
fix: reset proxy budget when initial reset duration is null then updated (#27488)
Co-authored-by: Michael Riad Zaky <michaelr@Mac.localdomain>
2026-05-09 18:33:36 -04:00
ishaan-berri
d67dfca1e1
Fix proxy auth status code tests (#27555)
* Fix proxy auth status code tests

Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>

* Update user model access status expectation

Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>

---------

Co-authored-by: oss-agent-shin <279349115+oss-agent-shin@users.noreply.github.com>
Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>
2026-05-09 14:47:48 -07:00
yuneng-jiang
936ada20fa
Merge pull request #27552 from BerriAI/litellm_/charming-sammet-8d77c3
build(packaging): raise jinja2 floor to 3.1.6
2026-05-09 13:59:11 -07:00
Yassin Kortam
fa5eae8bc9
chore: remove legacy deployment artifacts and litellm-js packages (#27541)
- Remove litellm-js/proxy and litellm-js/spend-logs TypeScript packages that provided Cloudflare Worker proxy and Node.js spend logging services, as these are no longer maintained
- Remove deprecated Docker variants (Dockerfile.alpine, Dockerfile.dev, Dockerfile.custom_ui, Dockerfile.health_check, Dockerfile.ghcr_base) that have been superseded by the primary Dockerfile
- Remove legacy Kubernetes manifests (kub.yaml, service.yaml) from deploy/kubernetes in favor of the Helm chart
- Remove stale index.yaml Helm chart index pinned to an old version (v1.43.18)
- Remove dev_config.yaml development configuration file that contained hardcoded credentials and example endpoints
- Clean up ~3,500 lines of unused code and configuration to reduce repository maintenance burden

Co-authored-by: Yassin Kortam <yassinkortam@g.ucla.edu>
2026-05-09 20:51:34 +00:00
Yuneng Jiang
8686001b3b
build(packaging): raise jinja2 floor to 3.1.6
Our `uv.lock` already resolves jinja2 to 3.1.6, so Docker / CI installs
get that version. The `pyproject.toml` floor was lagging at 3.1.0,
which means downstream consumers using `--resolution=lowest-direct` or
older constraint files can land on 3.1.0-3.1.5 instead of the version
we actually test against.

Aligns the declared floor with the resolved version so external
installers see the same baseline our test matrix exercises.

`uv lock` diff is metadata-only (no resolved-version drift).
2026-05-09 13:50:22 -07:00
Tai An
80445299b8
fix(proxy): coerce non-str x-litellm-* header values to avoid httpx TypeError (#27458) (#27504)
Squash-merged by litellm-agent from Anai-Guo's PR.
2026-05-09 20:32:31 +00:00
Rick
b799f94080
fix(ui): remove blank leading entry from access group model dropdown (#27521)
Squash-merged by litellm-agent from Bytechoreographer's PR.
2026-05-09 20:30:36 +00:00
Kris Xia
d1d2400862
fix(router): register model info under responses/-stripped variant (#27531)
Squash-merged by litellm-agent from krisxia0506's PR.
2026-05-09 20:30:18 +00:00
Tai An
f8b078b749
fix(bedrock/messages): preserve compact_20260112 context_management on /v1/messages (#27534)
Squash-merged by litellm-agent from Anai-Guo's PR.
2026-05-09 20:26:37 +00:00
Tai An
0f908e6885
fix(proxy): resolve provider from deployment for multi-provider defaultconfig (#27516) (#27517)
Squash-merged by litellm-agent from Anai-Guo's PR.
2026-05-09 20:23:15 +00:00
Noah Nistler
2b4beae29a
Fix/shared health check polling (#26434)
Squash-merged by litellm-agent from noahnistler's PR.
2026-05-09 20:14:40 +00:00
Shivam Rawat
3d1127a72d
Merge pull request #27441 from BerriAI/litellm_remove_tool_call_from_guardrails
feat(guardrails): optional skip tool message in unified guardrail inputs
2026-05-09 13:05:41 -07:00
Michael-RZ-Berri
b834817785
[Feat] Add endpoint for bulk key updates for team (#26468)
Squash-merged by litellm-agent from Michael-RZ-Berri's PR.
2026-05-09 19:32:16 +00:00
milan-berri
9380940ced
fix(mcp): forward extra_headers for OpenAPI MCP tools (#27383)
* fix(mcp): forward extra_headers for OpenAPI MCP tools

OpenAPI-generated tools only applied static closure headers and BYOK
Authorization via ContextVar. Copy MCPServer.extra_headers from the
incoming MCP request into _request_extra_headers (set in server.py before
local tool dispatch), merge in openapi_to_mcp_generator via a small helper.

OAuth2 M2M: do not forward caller Authorization from raw_headers (same rule
as _prepare_mcp_server_headers for managed MCP).

Adds TestRequestExtraHeaders and clarifies mcp_server_manager registration
comment.

Fixes #26794

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor(mcp): access has_client_credentials on MCPServer directly

Greptile: getattr default was redundant; property exists on MCPServer and
mcp_server is non-None inside the extra_headers forwarding block.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
2026-05-09 15:10:54 -04:00
yuneng-jiang
96f23c2e6f
Merge pull request #27537 from BerriAI/litellm_/hardcore-goldstine-baabae
fix(ui-tests): add Typography to antd mock in create_key_button test
2026-05-09 10:56:25 -07:00
yuneng-jiang
e01c8a7b1a
Merge pull request #27509 from BerriAI/litellm_/elegant-franklin-038d44
fix(proxy): bound budget reservation per request instead of pinning to headroom
2026-05-09 10:24:55 -07:00
Yuneng Jiang
7057d53862
fix(ui-tests): add Typography to antd mock in create_key_button test
The antd mock omits Typography, which caused all 15 tests in
create_key_button.test.tsx to fail with "No 'Typography' export is
defined on the 'antd' mock" after #27218 switched the key-type
dropdown labels to Typography.Text / Typography.Paragraph.

Add Typography (with .Text, .Paragraph, .Title subcomponents) to the
mock so the dropdown renders in the test environment.
2026-05-09 10:13:00 -07:00
yuneng-jiang
f69521a4b9
Merge pull request #27323 from BerriAI/litellm_realtimePrometheusMetrics
fix(realtime): add /openai/v1/realtime to routes for logging
2026-05-09 10:11:21 -07:00
yuneng-jiang
53323566d5
Merge pull request #27334 from BerriAI/litellm_fix_model_max_budget_redis_flush
fix(proxy): flush virtual-key model_max budget spend to Redis after success logging
2026-05-09 09:50:10 -07:00
ryan-crabbe-berri
0f11b3e187
[UI] Rename "Default" key type to "Full Access" and reorder dropdown (#27218)
The Create New Key dialog had a "Default" key-type option that was
misleading: it was not the actual default selection (AI APIs is), and it
grants access to all routes — broader than the description implied.

Rename the option to "Full Access" with an accurate description, and
reorder the dropdown to AI APIs → Management → Full Access. Switch the
inner labels to antd Typography for consistency with the rest of the UI.

UI-only change; the underlying enum value ("default") is unchanged so
the API contract is preserved.
2026-05-09 09:36:49 -07:00
Yuneng Jiang
963cb4694d
fix(proxy): gate image-gen reservation strictly on model mode
The previous detection treated any model with input_cost_per_image
or output_cost_per_image as image generation. Several chat and
embedding models carry those fields to price multimodal vision input,
not generated images:

- gemini-3.1-pro-preview (mode=chat) has output_cost_per_image=0.00012
  alongside input/output token pricing.
- azure/gpt-realtime-* (mode=chat) has input_cost_per_image=5e-6.
- amazon.titan-embed-image-v1 (mode=embedding) has
  input_cost_per_image=6e-5.

For these models the image-gen branch fired first and reserved a
fraction of a cent per request, short-circuiting the token-priced
path entirely. Long Gemini chats reserved 1 × $0.00012 instead of
the true token cost.

Gate strictly on mode in {"image_generation", "image_edit"}. All 197
real image_generation entries and all 31 image_edit entries
(Flux Kontext, Stability inpaint/outpaint, etc.) carry the right mode,
so the field-presence fallback was unnecessary.

Adds regression tests for the chat-model-with-image-cost-field case
and for image_edit reservation.
2026-05-09 09:16:27 -07:00
Yuneng Jiang
0d551ac4f0
fix(proxy): reserve per-image cost for image-generation requests
Image-generation routes (dall-e-3, flux, etc.) have no per-token output
cost so they fell through to the no-reservation read-time-only path.
Concurrent image requests against a depleted budget could all pass
common_checks (counter exactly at max_budget passes the strict-`>`
gate) and reach the provider before reconciliation caught up.

Add per-image reservation in _estimate_request_max_cost_for_model:
when the model has a per-image cost field, reserve `n × cost_per_image`
upfront. The atomic counter increment serializes concurrent admissions,
so the second request sees the post-first-reservation counter and
raises BudgetExceededError instead of silently leaking through.

Both `output_cost_per_image` and `input_cost_per_image` are honored —
naming is inconsistent across providers (OpenAI dall-e-3 uses
input_cost_per_image, aiml/dall-e-3 uses output_cost_per_image for
the same per-generated-image price).

Per-pixel pricing (DALL-E 2 size variants) and TTS/STT routes still
fall through to read-time enforcement; those are follow-ups.
2026-05-08 21:08:55 -07:00
Yuneng Jiang
4901ecc6b8
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/elegant-franklin-038d44 2026-05-08 21:08:21 -07:00
Yassin Kortam
b5d3a5fc85
feat: add read-replica routing for Prisma DB via DATABASE_URL_READ_REPLICA (#27493)
Some checks are pending
Unit Tests: Caching (Redis) / caching-redis (push) Waiting to run
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Waiting to run
Unit Tests: Proxy DB Operations / auth-checks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / budgets (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / custom-logging (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / db-and-spend (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / key-generation (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / logging-misc (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-runtime (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-server-core (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / schema-migration (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-utils (push) Blocked by required conditions
Unit Tests: Security / security (push) Waiting to run
- Introduce RoutingPrismaWrapper that transparently routes read operations (find_*, count, group_by, query_raw, query_first) to a reader endpoint while writes remain on the writer, enabling Aurora-style reader/writer endpoint splits
- Add IAMEndpoint dataclass and parse_iam_endpoint_from_url() to capture static connection fields from a reader URL so only the IAM token needs to rotate, avoiding the need for separate DATABASE_HOST_READ_REPLICA/etc. env vars
- Enhance PrismaWrapper with per-instance knobs (db_url_env_var, iam_endpoint, recreate_uses_datasource, log_prefix) so writer and reader wrappers are independent: the reader writes its fresh URL to DATABASE_URL_READ_REPLICA and passes datasource override to Prisma since Prisma only auto-reads DATABASE_URL
- Fix deadlock in PrismaWrapper.__getattr__: when called from inside a running event loop, schedule the token refresh as a background task instead of blocking with run_coroutine_threadsafe + future.result(), which would deadlock the loop thread waiting for a coroutine that needs the loop to run
- Fix botocore crash when DATABASE_PORT is unset by defaulting to "5432" in both proxy_cli.py and PrismaWrapper.get_rds_iam_token(); passing None caused botocore to embed the literal string "None" in the presigned URL
- Implement graceful reader degradation: reader connect/recreate failures are non-fatal; wrapper sets _reader_unavailable=True and silently routes reads to the writer to keep the proxy serving traffic during transient reader outages
- Add PrismaClient.writer_db property so the reconnect smoke-test always validates the writer engine specifically; query_raw on the routing wrapper would route to the reader and not verify the newly-recreated writer
- Expose DATABASE_URL_READ_REPLICA in Helm chart (values.yaml + deployment.yaml) via both plain value and secret key reference, and document the field in docker-compose.yml
- Add 887-line test suite covering routing logic, IAM token refresh paths, reader degradation scenarios, datasource override behavior, and the deadlock regression

Co-authored-by: Yassin Kortam <yassinkortam@g.ucla.edu>
2026-05-08 21:05:50 -07:00
Yuneng Jiang
adc41ade8c
fix(proxy): bound budget reservation per request instead of pinning to remaining headroom
reserve_budget_for_request fell back to reserving the entire remaining
team/key/user headroom whenever a request omitted max_tokens, which
pinned the spend counter at max_budget for the duration of the
in-flight request and false-positive-blocked every concurrent or
back-to-back request until the success callback reconciled. Surfaced
as an integration-test team being budget-blocked at its $2000 cap
while DB spend was $0.144.

Switch the missing-max_tokens path to a fixed default of 16384 output
tokens (mirrors parallel_request_limiter_v3's DEFAULT_MAX_TOKENS_ESTIMATE
precedent), and clamp explicit max_tokens at the model's
max_output_tokens for reservation accounting only. The outbound request
body is unchanged, so providers see whatever the caller actually sent;
only the local integer used to compute reservation cost is bounded.
This also prevents a hostile max_tokens=999999999 from inflating one
request's reservation up to the entire team headroom.

For Opus 4.7 (output $25/M, max_output 128K) on a $2000 budget the
worst-case per-request reservation drops from "everything left" to
$3.20, raising admittable concurrency from 1 to ~625.
2026-05-08 20:18:31 -07:00
yuneng-jiang
0bcff0214a
Merge pull request #27502 from BerriAI/litellm_/trusting-hoover-2bbbc8
fix(proxy): point /metrics 401 at the opt-out flag
2026-05-08 18:31:04 -07:00