diff --git a/.github/workflows/test-linting.yml b/.github/workflows/test-linting.yml index 0a80a65cbe6..de7e1b68346 100644 --- a/.github/workflows/test-linting.yml +++ b/.github/workflows/test-linting.yml @@ -87,14 +87,9 @@ jobs: run: | uv run --no-sync python -c "import openai; print(f'OpenAI version: {openai.__version__}')" - - name: Run MyPy type checking - run: | - cd litellm - (uv run --no-sync mypy . || true) | uv run --no-sync python ../scripts/type_check_gate.py --tool mypy - - name: Run basedpyright type checking run: | - (uv run --no-sync basedpyright --outputjson || true) | uv run --no-sync python scripts/type_check_gate.py --tool basedpyright + (uv run --no-sync basedpyright --outputjson || true) | uv run --no-sync python scripts/type_check_gate.py - name: Check for circular imports run: | @@ -133,56 +128,6 @@ jobs: run: | python scripts/budget_ratchet_check.py --base "$BASE_SHA" - any-discipline: - # Separate job: the first run cold-builds litellm's type cache (~2 min, ~3 GB), - # so keep it off the main lint job's time budget. Subsequent runs reuse the - # cached .mypy_cache_any and only re-type-check the changed files. - runs-on: ubuntu-latest - timeout-minutes: 10 - - steps: - - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - # Check out the PR head, not the default refs/pull/N/merge: the merge ref - # folds in newer base commits, which the diff-based gates (ruff delta, - # Any-discipline) would otherwise blame on this branch. - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - clean: true - persist-credentials: false - - - name: Set up Python - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 - with: - python-version: "3.12" - - - name: Set up uv - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7 - with: - version: "0.10.9" - - - name: Install dependencies - run: | - uv sync --frozen - - # Keyed on deps + mypy config (which fix the type cache's validity), not on - # source content, so changed files always differ from the restored cache. - # The gate also defensively invalidates each target's cache entry, so - # correctness never depends on cache freshness -- this is purely for speed. - - name: Restore Any-gate type cache - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 - with: - path: .mypy_cache_any - key: any-mypy-cache-${{ runner.os }}-py3.12-${{ hashFiles('uv.lock', 'litellm/mypy.ini') }} - restore-keys: | - any-mypy-cache-${{ runner.os }}-py3.12- - - - name: Check Any discipline (per-file budget on changed files) - env: - BASE_SHA: ${{ github.event.pull_request.base.sha }} - run: | - uv run --no-sync python scripts/check_any_discipline.py --changed --base "$BASE_SHA" - secret-scan: runs-on: ubuntu-latest timeout-minutes: 5 diff --git a/.gitignore b/.gitignore index 54ae53bb2c9..fda3311fe02 100644 --- a/.gitignore +++ b/.gitignore @@ -74,8 +74,6 @@ tests/local_testing/log.txt .codegpt litellm/proxy/_new_new_secret_config.yaml litellm/proxy/custom_guardrail.py -**/.mypy_cache/ -**/.mypy_cache_any/ litellm/proxy/application.log tests/llm_translation/vertex_test_account.json tests/llm_translation/test_vertex_key.json diff --git a/CLAUDE.md b/CLAUDE.md index 95904ef8abd..2070b6fcdd6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -36,11 +36,9 @@ Don't hesitate to use values in .env to get needed API keys and other secrets, a Run tests, format your code, and lint your code before each commit -When you fix violations gated by `ruff-strict-budget.json`, `mypy-code-budget.json`, `basedpyright-code-budget.json`, or `any-discipline-budget.json`, run `make lint-budget-update` and commit the lowered baselines so the ceilings ratchet down instead of leaving stale headroom +When you fix violations gated by `ruff-strict-budget.json` or `basedpyright-code-budget.json`, run `make lint-budget-update` and commit the lowered baselines so the ceilings ratchet down instead of leaving stale headroom -If you're trying to create a new function that relies on untyped stuff, instead of adding more Any's and bringing it closer to the max, just validate it in the caller with Pydantic (a model or `TypeAdapter` that returns the typed thing or raises will do) and then pass the now typed variable in - -The Any-discipline gate (`make lint-any`, also a CI job) fails when a changed file under `litellm/` carries more `Any`-typed values than its grandfathered ceiling in `any-discipline-budget.json` (each file's captured count plus 50% headroom). It flags values whose inferred type *contains* `Any`, including the `X | Any` unions mypy/basedpyright accept. Editing a legacy file is fine as long as you don't push its `Any` count past the ceiling; a brand-new file must be `Any`-free. Fix a value by giving it a concrete type (if you're given untyped input, validate with Pydantic). Ideally `# any-ok: ` is never used; treat it as a last resort for a genuine typed/untyped boundary that Pydantic truly can't model +If you're trying to create a new function that relies on untyped stuff, instead of adding more Any's and pushing `reportAny` / `reportExplicitAny` closer to their basedpyright ceilings, just validate it in the caller with Pydantic (a model or `TypeAdapter` that returns the typed thing or raises will do) and then pass the now typed variable in If you get an LIT001 or LIT002 fail, refactor the code to follow functional programming best practices rather than introducing mutable data structures. For example, build values in one shot with comprehensions or generators wrapped in `tuple()` / `frozenset()` instead of seeding an empty `list`/`dict`/`set` and mutating it over time. Ideally `# mutable-ok` is never used; reach for it only as a genuine last resort when an immutable rewrite is truly impossible, and always pair it with a real reason diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9643a58742c..1080579d0fa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -154,8 +154,7 @@ Individual linting commands: ```bash make format-check # Check Black formatting make lint-ruff # Run Ruff linting -make lint-mypy # Run MyPy type checking -make lint-any # Gate changed files against their per-file Any budget +make lint-basedpyright # Run basedpyright type checking make check-circular-imports # Check for circular imports make check-import-safety # Check import safety ``` @@ -217,7 +216,7 @@ LiteLLM follows the [Google Python Style Guide](https://google.github.io/stylegu Our automated quality checks include: - **Black** for consistent code formatting - **Ruff** for linting and code quality -- **MyPy** for static type checking +- **basedpyright** for static type checking - **Circular import detection** - **Import safety validation** @@ -231,7 +230,7 @@ If `make lint` fails: 1. **Formatting issues**: Run `make format` to auto-fix 2. **Ruff issues**: Check the output and fix manually -3. **MyPy issues**: Add proper type hints +3. **basedpyright issues**: Add proper type hints 4. **Circular imports**: Refactor import dependencies 5. **Import safety**: Fix any unprotected imports @@ -246,7 +245,7 @@ If `make test-unit` fails: ### 3. Common Development Tips -- **Use type hints**: MyPy requires proper type annotations +- **Use type hints**: basedpyright requires proper type annotations - **Write descriptive commit messages**: Help reviewers understand your changes - **Keep PRs focused**: One feature/fix per PR - **Test edge cases**: Don't just test the happy path diff --git a/Makefile b/Makefile index 0a6d612e8b8..6183dff1556 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,8 @@ test-unit-integrations test-unit-core-utils test-unit-other test-unit-root \ test-proxy-unit-a test-proxy-unit-b test-integration test-unit-helm \ info lint lint-dev format \ - lint-mypy lint-mypy-budget-update lint-basedpyright lint-basedpyright-budget-update \ - lint-ruff-budget lint-any lint-ruff-budget-update lint-budget-update lint-any-budget-update \ + lint-basedpyright lint-basedpyright-budget-update \ + lint-ruff-budget lint-ruff-budget-update lint-budget-update \ install-dev install-proxy-dev install-test-deps install-hooks \ install-helm-unittest check-circular-imports check-import-safety @@ -22,18 +22,14 @@ help: @echo " make install-hooks - Install git hooks (Conventional Commits + Branches)" @echo " make format - Apply Black code formatting" @echo " make format-check - Check Black code formatting (matches CI)" - @echo " make lint - Run all linting (Ruff, MyPy, Black check, circular imports, import safety)" + @echo " make lint - Run all linting (Ruff, basedpyright, Black check, circular imports, import safety)" @echo " make lint-ruff - Run Ruff linting only" - @echo " make lint-mypy - Run MyPy (disallow_untyped_defs), gated by per-rule error counts" - @echo " make lint-mypy-budget-update - Re-capture the MyPy per-rule budget (ratchet)" @echo " make lint-basedpyright - Run basedpyright strict, gated by per-rule error counts" @echo " make lint-basedpyright-budget-update - Re-capture the basedpyright per-rule budget (ratchet)" @echo " make lint-black - Check Black formatting (matches CI)" @echo " make lint-ruff-budget - Gate the codebase total of each strict ruff rule against its ceiling" - @echo " make lint-any - Gate changed files under litellm/ against their per-file Any budget" @echo " make lint-ruff-budget-update - Re-capture per-rule baselines in ruff-strict-budget.json (ratchet)" - @echo " make lint-budget-update - Re-capture all four ratchet budgets (ruff + mypy + basedpyright + any)" - @echo " make lint-any-budget-update - Re-capture the per-file Any budget across the whole tree (ratchet)" + @echo " make lint-budget-update - Re-capture all ratchet budgets (ruff + basedpyright)" @echo " make check-circular-imports - Check for circular imports" @echo " make check-import-safety - Check import safety" @echo " make test - Run all tests" @@ -127,17 +123,11 @@ lint-ruff-FULL-dev: install-dev if [ -n "$$files" ]; then echo "$$files" | xargs $(UV_RUN) ruff check; \ else echo "No changed .py files to check."; fi -lint-mypy: install-dev - cd litellm && ($(UV_RUN) mypy . || true) | $(UV_RUN) python ../scripts/type_check_gate.py --tool mypy - -lint-mypy-budget-update: install-dev - cd litellm && ($(UV_RUN) mypy . || true) | $(UV_RUN) python ../scripts/type_check_gate.py --tool mypy --update - lint-basedpyright: install-dev - ($(UV_RUN) basedpyright --outputjson || true) | $(UV_RUN) python scripts/type_check_gate.py --tool basedpyright + ($(UV_RUN) basedpyright --outputjson || true) | $(UV_RUN) python scripts/type_check_gate.py lint-basedpyright-budget-update: install-dev - ($(UV_RUN) basedpyright --outputjson || true) | $(UV_RUN) python scripts/type_check_gate.py --tool basedpyright --update + ($(UV_RUN) basedpyright --outputjson || true) | $(UV_RUN) python scripts/type_check_gate.py --update lint-black: format-check @@ -147,14 +137,8 @@ lint-ruff-budget: install-dev lint-ruff-budget-update: install-dev $(UV_RUN) python scripts/ruff_strict_gate.py --update -# Ratchet all four budgets in one shot (ruff strict + mypy + basedpyright + any) -lint-budget-update: lint-ruff-budget-update lint-mypy-budget-update lint-basedpyright-budget-update lint-any-budget-update - -lint-any: install-dev - $(UV_RUN) python scripts/check_any_discipline.py --changed - -lint-any-budget-update: install-dev - $(UV_RUN) python scripts/check_any_discipline.py --update +# Ratchet all budgets in one shot (ruff strict + basedpyright) +lint-budget-update: lint-ruff-budget-update lint-basedpyright-budget-update check-circular-imports: install-dev cd litellm && $(UV_RUN) python ../tests/documentation_tests/test_circular_imports.py && cd .. @@ -163,10 +147,10 @@ check-import-safety: install-dev @$(UV_RUN) python -c "from litellm import *; print('[from litellm import *] OK! no issues!');" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1) # Combined linting (matches test-linting.yml workflow) -lint: format-check lint-ruff lint-mypy lint-basedpyright check-circular-imports check-import-safety lint-ruff-budget lint-any +lint: format-check lint-ruff lint-basedpyright check-circular-imports check-import-safety lint-ruff-budget # Faster linting for local development (only checks changed code) -lint-dev: lint-format-changed lint-mypy lint-any check-circular-imports check-import-safety +lint-dev: lint-format-changed check-circular-imports check-import-safety # Testing targets test: install-test-deps diff --git a/any-discipline-budget.json b/any-discipline-budget.json deleted file mode 100644 index d78b15e3653..00000000000 --- a/any-discipline-budget.json +++ /dev/null @@ -1,5974 +0,0 @@ -{ - "litellm/__init__.py": { - "baseline": 801, - "slack": 401 - }, - "litellm/_lazy_imports.py": { - "baseline": 55, - "slack": 28 - }, - "litellm/_logging.py": { - "baseline": 165, - "slack": 83 - }, - "litellm/_redis.py": { - "baseline": 416, - "slack": 208 - }, - "litellm/_redis_credential_provider.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/_service_logger.py": { - "baseline": 96, - "slack": 48 - }, - "litellm/_uuid.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/a2a_protocol/card_resolver.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/a2a_protocol/client.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/a2a_protocol/cost_calculator.py": { - "baseline": 26, - "slack": 13 - }, - "litellm/a2a_protocol/exception_mapping_utils.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/a2a_protocol/litellm_completion_bridge/handler.py": { - "baseline": 104, - "slack": 52 - }, - "litellm/a2a_protocol/litellm_completion_bridge/transformation.py": { - "baseline": 86, - "slack": 43 - }, - "litellm/a2a_protocol/main.py": { - "baseline": 209, - "slack": 105 - }, - "litellm/a2a_protocol/providers/bedrock_agentcore/config.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/a2a_protocol/providers/bedrock_agentcore/handler.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/a2a_protocol/providers/bedrock_agentcore/transformation.py": { - "baseline": 45, - "slack": 23 - }, - "litellm/a2a_protocol/providers/langflow/config.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/a2a_protocol/providers/pydantic_ai_agents/config.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/a2a_protocol/providers/pydantic_ai_agents/handler.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/a2a_protocol/providers/pydantic_ai_agents/transformation.py": { - "baseline": 142, - "slack": 71 - }, - "litellm/a2a_protocol/providers/watsonx_orchestrate/config.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/a2a_protocol/providers/watsonx_orchestrate/handler.py": { - "baseline": 118, - "slack": 59 - }, - "litellm/a2a_protocol/providers/watsonx_orchestrate/transformation.py": { - "baseline": 60, - "slack": 30 - }, - "litellm/a2a_protocol/streaming_iterator.py": { - "baseline": 57, - "slack": 29 - }, - "litellm/a2a_protocol/utils.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/anthropic_beta_headers_manager.py": { - "baseline": 77, - "slack": 39 - }, - "litellm/anthropic_interface/exceptions/exception_mapping_utils.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/anthropic_interface/exceptions/exceptions.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/anthropic_interface/messages/__init__.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/assistants/main.py": { - "baseline": 398, - "slack": 199 - }, - "litellm/assistants/utils.py": { - "baseline": 94, - "slack": 47 - }, - "litellm/batch_completion/main.py": { - "baseline": 178, - "slack": 89 - }, - "litellm/batches/batch_utils.py": { - "baseline": 129, - "slack": 65 - }, - "litellm/batches/main.py": { - "baseline": 240, - "slack": 120 - }, - "litellm/budget_manager.py": { - "baseline": 117, - "slack": 59 - }, - "litellm/caching/_internal_lru_cache.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/caching/azure_blob_cache.py": { - "baseline": 77, - "slack": 39 - }, - "litellm/caching/base_cache.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/caching/caching.py": { - "baseline": 378, - "slack": 189 - }, - "litellm/caching/caching_handler.py": { - "baseline": 337, - "slack": 169 - }, - "litellm/caching/disk_cache.py": { - "baseline": 75, - "slack": 38 - }, - "litellm/caching/dual_cache.py": { - "baseline": 192, - "slack": 96 - }, - "litellm/caching/gcs_cache.py": { - "baseline": 92, - "slack": 46 - }, - "litellm/caching/in_memory_cache.py": { - "baseline": 173, - "slack": 87 - }, - "litellm/caching/llm_caching_handler.py": { - "baseline": 32, - "slack": 16 - }, - "litellm/caching/qdrant_semantic_cache.py": { - "baseline": 359, - "slack": 180 - }, - "litellm/caching/redis_cache.py": { - "baseline": 588, - "slack": 294 - }, - "litellm/caching/redis_cluster_cache.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/caching/redis_semantic_cache.py": { - "baseline": 194, - "slack": 97 - }, - "litellm/caching/s3_cache.py": { - "baseline": 138, - "slack": 69 - }, - "litellm/completion_extras/litellm_responses_transformation/handler.py": { - "baseline": 187, - "slack": 94 - }, - "litellm/completion_extras/litellm_responses_transformation/transformation.py": { - "baseline": 562, - "slack": 281 - }, - "litellm/compression/compress.py": { - "baseline": 120, - "slack": 60 - }, - "litellm/compression/content_detection.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/compression/message_stubbing.py": { - "baseline": 50, - "slack": 25 - }, - "litellm/compression/retrieval_tool.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/compression/scoring/bm25.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/compression/scoring/embedding_scorer.py": { - "baseline": 31, - "slack": 16 - }, - "litellm/constants.py": { - "baseline": 40, - "slack": 20 - }, - "litellm/containers/endpoint_factory.py": { - "baseline": 85, - "slack": 43 - }, - "litellm/containers/main.py": { - "baseline": 278, - "slack": 139 - }, - "litellm/containers/utils.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/cost_calculator.py": { - "baseline": 428, - "slack": 214 - }, - "litellm/endpoints/speech/speech_to_completion_bridge/handler.py": { - "baseline": 59, - "slack": 30 - }, - "litellm/endpoints/speech/speech_to_completion_bridge/transformation.py": { - "baseline": 31, - "slack": 16 - }, - "litellm/evals/main.py": { - "baseline": 522, - "slack": 261 - }, - "litellm/exceptions.py": { - "baseline": 481, - "slack": 241 - }, - "litellm/experimental_mcp_client/client.py": { - "baseline": 174, - "slack": 87 - }, - "litellm/experimental_mcp_client/tools.py": { - "baseline": 47, - "slack": 24 - }, - "litellm/files/main.py": { - "baseline": 257, - "slack": 129 - }, - "litellm/files/streaming.py": { - "baseline": 47, - "slack": 24 - }, - "litellm/files/types.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/fine_tuning/main.py": { - "baseline": 167, - "slack": 84 - }, - "litellm/google_genai/adapters/handler.py": { - "baseline": 49, - "slack": 25 - }, - "litellm/google_genai/adapters/transformation.py": { - "baseline": 325, - "slack": 163 - }, - "litellm/google_genai/main.py": { - "baseline": 179, - "slack": 90 - }, - "litellm/google_genai/streaming_iterator.py": { - "baseline": 56, - "slack": 28 - }, - "litellm/images/main.py": { - "baseline": 326, - "slack": 163 - }, - "litellm/images/utils.py": { - "baseline": 28, - "slack": 14 - }, - "litellm/integrations/SlackAlerting/batching_handler.py": { - "baseline": 44, - "slack": 22 - }, - "litellm/integrations/SlackAlerting/hanging_request_check.py": { - "baseline": 48, - "slack": 24 - }, - "litellm/integrations/SlackAlerting/slack_alerting.py": { - "baseline": 644, - "slack": 322 - }, - "litellm/integrations/SlackAlerting/utils.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/integrations/additional_logging_utils.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/integrations/agentops/agentops.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/integrations/anthropic_cache_control_hook.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/integrations/argilla.py": { - "baseline": 204, - "slack": 102 - }, - "litellm/integrations/arize/__init__.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/integrations/arize/_utils.py": { - "baseline": 632, - "slack": 316 - }, - "litellm/integrations/arize/arize.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/integrations/arize/arize_phoenix.py": { - "baseline": 159, - "slack": 80 - }, - "litellm/integrations/arize/arize_phoenix_client.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/integrations/arize/arize_phoenix_prompt_manager.py": { - "baseline": 117, - "slack": 59 - }, - "litellm/integrations/athina.py": { - "baseline": 85, - "slack": 43 - }, - "litellm/integrations/azure_sentinel/azure_sentinel.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/integrations/azure_storage/azure_storage.py": { - "baseline": 148, - "slack": 74 - }, - "litellm/integrations/bitbucket/__init__.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/integrations/bitbucket/bitbucket_client.py": { - "baseline": 87, - "slack": 44 - }, - "litellm/integrations/bitbucket/bitbucket_prompt_manager.py": { - "baseline": 85, - "slack": 43 - }, - "litellm/integrations/braintrust_logging.py": { - "baseline": 318, - "slack": 159 - }, - "litellm/integrations/braintrust_mock_client.py": { - "baseline": 32, - "slack": 16 - }, - "litellm/integrations/cloudzero/cloudzero.py": { - "baseline": 200, - "slack": 100 - }, - "litellm/integrations/cloudzero/cz_resource_names.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/integrations/cloudzero/cz_stream_api.py": { - "baseline": 47, - "slack": 24 - }, - "litellm/integrations/cloudzero/database.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/integrations/cloudzero/transform.py": { - "baseline": 83, - "slack": 42 - }, - "litellm/integrations/compression_interception/handler.py": { - "baseline": 184, - "slack": 92 - }, - "litellm/integrations/custom_batch_logger.py": { - "baseline": 40, - "slack": 20 - }, - "litellm/integrations/custom_guardrail.py": { - "baseline": 304, - "slack": 152 - }, - "litellm/integrations/custom_logger.py": { - "baseline": 197, - "slack": 99 - }, - "litellm/integrations/custom_prompt_management.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/integrations/custom_sso_handler.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/integrations/datadog/datadog.py": { - "baseline": 266, - "slack": 133 - }, - "litellm/integrations/datadog/datadog_cost_management.py": { - "baseline": 79, - "slack": 40 - }, - "litellm/integrations/datadog/datadog_handler.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/integrations/datadog/datadog_llm_obs.py": { - "baseline": 314, - "slack": 157 - }, - "litellm/integrations/datadog/datadog_metrics.py": { - "baseline": 78, - "slack": 39 - }, - "litellm/integrations/datadog/datadog_mock_client.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/integrations/datadog/datadog_team_handler.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/integrations/deepeval/api.py": { - "baseline": 31, - "slack": 16 - }, - "litellm/integrations/deepeval/deepeval.py": { - "baseline": 131, - "slack": 66 - }, - "litellm/integrations/deepeval/types.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/integrations/dotprompt/__init__.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/integrations/dotprompt/dotprompt_manager.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/integrations/dotprompt/prompt_manager.py": { - "baseline": 77, - "slack": 39 - }, - "litellm/integrations/dynamodb.py": { - "baseline": 64, - "slack": 32 - }, - "litellm/integrations/email_alerting.py": { - "baseline": 33, - "slack": 17 - }, - "litellm/integrations/focus/database.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/integrations/focus/destinations/base.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/integrations/focus/destinations/factory.py": { - "baseline": 50, - "slack": 25 - }, - "litellm/integrations/focus/destinations/gcs_destination.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/integrations/focus/destinations/mavvrik_destination.py": { - "baseline": 49, - "slack": 25 - }, - "litellm/integrations/focus/destinations/s3_destination.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/integrations/focus/destinations/vantage_destination.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/integrations/focus/export_engine.py": { - "baseline": 47, - "slack": 24 - }, - "litellm/integrations/focus/focus_logger.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/integrations/focus/schema.py": { - "baseline": 76, - "slack": 38 - }, - "litellm/integrations/focus/serializers/csv.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/integrations/focus/serializers/parquet.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/integrations/focus/transformer.py": { - "baseline": 109, - "slack": 55 - }, - "litellm/integrations/galileo.py": { - "baseline": 381, - "slack": 191 - }, - "litellm/integrations/gcs_bucket/gcs_bucket.py": { - "baseline": 104, - "slack": 52 - }, - "litellm/integrations/gcs_bucket/gcs_bucket_base.py": { - "baseline": 48, - "slack": 24 - }, - "litellm/integrations/gcs_bucket/gcs_bucket_mock_client.py": { - "baseline": 60, - "slack": 30 - }, - "litellm/integrations/gcs_pubsub/pub_sub.py": { - "baseline": 56, - "slack": 28 - }, - "litellm/integrations/generic_api/generic_api_callback.py": { - "baseline": 198, - "slack": 99 - }, - "litellm/integrations/generic_prompt_management/generic_prompt_manager.py": { - "baseline": 51, - "slack": 26 - }, - "litellm/integrations/gitlab/__init__.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/integrations/gitlab/gitlab_client.py": { - "baseline": 97, - "slack": 49 - }, - "litellm/integrations/gitlab/gitlab_prompt_manager.py": { - "baseline": 137, - "slack": 69 - }, - "litellm/integrations/greenscale.py": { - "baseline": 71, - "slack": 36 - }, - "litellm/integrations/helicone.py": { - "baseline": 191, - "slack": 96 - }, - "litellm/integrations/helicone_mock_client.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/integrations/humanloop.py": { - "baseline": 47, - "slack": 24 - }, - "litellm/integrations/lago.py": { - "baseline": 123, - "slack": 62 - }, - "litellm/integrations/langfuse/langfuse.py": { - "baseline": 610, - "slack": 305 - }, - "litellm/integrations/langfuse/langfuse_handler.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/integrations/langfuse/langfuse_mock_client.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/integrations/langfuse/langfuse_otel.py": { - "baseline": 135, - "slack": 68 - }, - "litellm/integrations/langfuse/langfuse_otel_attributes.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/integrations/langfuse/langfuse_prompt_management.py": { - "baseline": 120, - "slack": 60 - }, - "litellm/integrations/langsmith.py": { - "baseline": 245, - "slack": 123 - }, - "litellm/integrations/langsmith_mock_client.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/integrations/langtrace.py": { - "baseline": 68, - "slack": 34 - }, - "litellm/integrations/levo/levo.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/integrations/litellm_agent/litellm_agent_model_resolver.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/integrations/literal_ai.py": { - "baseline": 281, - "slack": 141 - }, - "litellm/integrations/logfire_logger.py": { - "baseline": 88, - "slack": 44 - }, - "litellm/integrations/lunary.py": { - "baseline": 126, - "slack": 63 - }, - "litellm/integrations/mavvrik_focus/mavvrik_focus_logger.py": { - "baseline": 32, - "slack": 16 - }, - "litellm/integrations/mlflow.py": { - "baseline": 239, - "slack": 120 - }, - "litellm/integrations/mock_client_factory.py": { - "baseline": 88, - "slack": 44 - }, - "litellm/integrations/newrelic/newrelic.py": { - "baseline": 274, - "slack": 137 - }, - "litellm/integrations/openmeter.py": { - "baseline": 87, - "slack": 44 - }, - "litellm/integrations/opentelemetry.py": { - "baseline": 1474, - "slack": 737 - }, - "litellm/integrations/opentelemetry_utils/base_otel_llm_obs_attributes.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/integrations/opentelemetry_utils/gen_ai_semconv.py": { - "baseline": 64, - "slack": 32 - }, - "litellm/integrations/opik/opik.py": { - "baseline": 82, - "slack": 41 - }, - "litellm/integrations/opik/opik_payload_builder/api.py": { - "baseline": 53, - "slack": 27 - }, - "litellm/integrations/opik/opik_payload_builder/extractors.py": { - "baseline": 61, - "slack": 31 - }, - "litellm/integrations/opik/opik_payload_builder/payload_builders.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/integrations/opik/opik_payload_builder/types.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/integrations/opik/utils.py": { - "baseline": 76, - "slack": 38 - }, - "litellm/integrations/otel/logger.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/integrations/otel/mappers/genai.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/integrations/otel/mappers/langfuse.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/integrations/otel/mappers/langtrace.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/integrations/otel/mappers/openinference.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/integrations/otel/mappers/utils.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/integrations/otel/model/baggage.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/integrations/otel/model/config.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/integrations/otel/model/metadata.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/integrations/otel/model/payloads.py": { - "baseline": 67, - "slack": 34 - }, - "litellm/integrations/otel/model/spans.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/integrations/otel/model/utils.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/integrations/otel/mount.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/integrations/otel/plumbing/metrics.py": { - "baseline": 115, - "slack": 58 - }, - "litellm/integrations/otel/plumbing/providers.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/integrations/otel/plumbing/routing.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/integrations/otel/presets/agentops.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/integrations/otel/presets/arize.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/integrations/otel/presets/langfuse.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/integrations/otel/presets/langtrace.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/integrations/otel/presets/levo.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/integrations/otel/presets/phoenix.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/integrations/otel/presets/weave.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/integrations/otel/runtime.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/integrations/posthog.py": { - "baseline": 349, - "slack": 175 - }, - "litellm/integrations/posthog_mock_client.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/integrations/prometheus.py": { - "baseline": 1095, - "slack": 548 - }, - "litellm/integrations/prometheus_helpers/__init__.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/integrations/prometheus_helpers/bounded_prometheus_series_tracker.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/integrations/prometheus_helpers/prometheus_api.py": { - "baseline": 53, - "slack": 27 - }, - "litellm/integrations/prometheus_services.py": { - "baseline": 112, - "slack": 56 - }, - "litellm/integrations/prompt_layer.py": { - "baseline": 64, - "slack": 32 - }, - "litellm/integrations/prompt_management_base.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/integrations/rubrik.py": { - "baseline": 205, - "slack": 103 - }, - "litellm/integrations/s3.py": { - "baseline": 120, - "slack": 60 - }, - "litellm/integrations/s3_v2.py": { - "baseline": 242, - "slack": 121 - }, - "litellm/integrations/sqs.py": { - "baseline": 120, - "slack": 60 - }, - "litellm/integrations/supabase.py": { - "baseline": 79, - "slack": 40 - }, - "litellm/integrations/traceloop.py": { - "baseline": 130, - "slack": 65 - }, - "litellm/integrations/vantage/vantage_logger.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/integrations/vector_store_integrations/vector_store_pre_call_hook.py": { - "baseline": 75, - "slack": 38 - }, - "litellm/integrations/weave/weave_otel.py": { - "baseline": 108, - "slack": 54 - }, - "litellm/integrations/websearch_interception/handler.py": { - "baseline": 447, - "slack": 224 - }, - "litellm/integrations/websearch_interception/tools.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/integrations/websearch_interception/transformation.py": { - "baseline": 185, - "slack": 93 - }, - "litellm/integrations/weights_biases.py": { - "baseline": 107, - "slack": 54 - }, - "litellm/interactions/agents/http_handler.py": { - "baseline": 170, - "slack": 85 - }, - "litellm/interactions/agents/main.py": { - "baseline": 194, - "slack": 97 - }, - "litellm/interactions/http_handler.py": { - "baseline": 158, - "slack": 79 - }, - "litellm/interactions/litellm_responses_transformation/handler.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/interactions/litellm_responses_transformation/streaming_iterator.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/interactions/litellm_responses_transformation/transformation.py": { - "baseline": 131, - "slack": 66 - }, - "litellm/interactions/main.py": { - "baseline": 153, - "slack": 77 - }, - "litellm/interactions/streaming_iterator.py": { - "baseline": 48, - "slack": 24 - }, - "litellm/interactions/utils.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/litellm_core_utils/app_crypto.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/litellm_core_utils/asyncify.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/litellm_core_utils/audio_utils/utils.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/litellm_core_utils/cli_token_utils.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/litellm_core_utils/cloud_storage_security.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/litellm_core_utils/completion_timeout.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/litellm_core_utils/core_helpers.py": { - "baseline": 192, - "slack": 96 - }, - "litellm/litellm_core_utils/coroutine_checker.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/litellm_core_utils/credential_accessor.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/litellm_core_utils/custom_logger_registry.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/litellm_core_utils/dd_tracing.py": { - "baseline": 28, - "slack": 14 - }, - "litellm/litellm_core_utils/default_encoding.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/litellm_core_utils/dot_notation_indexing.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/litellm_core_utils/duration_parser.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/litellm_core_utils/exception_mapping_utils.py": { - "baseline": 2076, - "slack": 1038 - }, - "litellm/litellm_core_utils/fallback_utils.py": { - "baseline": 57, - "slack": 29 - }, - "litellm/litellm_core_utils/get_blog_posts.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/litellm_core_utils/get_litellm_params.py": { - "baseline": 45, - "slack": 23 - }, - "litellm/litellm_core_utils/get_llm_provider_logic.py": { - "baseline": 143, - "slack": 72 - }, - "litellm/litellm_core_utils/get_model_cost_map.py": { - "baseline": 47, - "slack": 24 - }, - "litellm/litellm_core_utils/get_provider_specific_headers.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/litellm_core_utils/get_supported_openai_params.py": { - "baseline": 67, - "slack": 34 - }, - "litellm/litellm_core_utils/health_check_helpers.py": { - "baseline": 73, - "slack": 37 - }, - "litellm/litellm_core_utils/health_check_utils.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/litellm_core_utils/initialize_dynamic_callback_params.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/litellm_core_utils/json_validation_rule.py": { - "baseline": 62, - "slack": 31 - }, - "litellm/litellm_core_utils/litellm_logging.py": { - "baseline": 2348, - "slack": 1174 - }, - "litellm/litellm_core_utils/llm_cost_calc/tool_call_cost_tracking.py": { - "baseline": 107, - "slack": 54 - }, - "litellm/litellm_core_utils/llm_cost_calc/usage_object_transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/litellm_core_utils/llm_cost_calc/utils.py": { - "baseline": 55, - "slack": 28 - }, - "litellm/litellm_core_utils/llm_request_utils.py": { - "baseline": 37, - "slack": 19 - }, - "litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py": { - "baseline": 336, - "slack": 168 - }, - "litellm/litellm_core_utils/llm_response_utils/get_api_base.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/litellm_core_utils/llm_response_utils/get_formatted_prompt.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/litellm_core_utils/llm_response_utils/get_headers.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/litellm_core_utils/llm_response_utils/response_metadata.py": { - "baseline": 80, - "slack": 40 - }, - "litellm/litellm_core_utils/logging_callback_manager.py": { - "baseline": 90, - "slack": 45 - }, - "litellm/litellm_core_utils/logging_utils.py": { - "baseline": 181, - "slack": 91 - }, - "litellm/litellm_core_utils/logging_worker.py": { - "baseline": 103, - "slack": 52 - }, - "litellm/litellm_core_utils/model_param_helper.py": { - "baseline": 41, - "slack": 21 - }, - "litellm/litellm_core_utils/model_response_utils.py": { - "baseline": 51, - "slack": 26 - }, - "litellm/litellm_core_utils/prompt_templates/common_utils.py": { - "baseline": 362, - "slack": 181 - }, - "litellm/litellm_core_utils/prompt_templates/factory.py": { - "baseline": 1452, - "slack": 726 - }, - "litellm/litellm_core_utils/prompt_templates/huggingface_template_handler.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/litellm_core_utils/prompt_templates/image_handling.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/litellm_core_utils/realtime_streaming.py": { - "baseline": 631, - "slack": 316 - }, - "litellm/litellm_core_utils/redact_messages.py": { - "baseline": 195, - "slack": 98 - }, - "litellm/litellm_core_utils/rules.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/litellm_core_utils/safe_json_dumps.py": { - "baseline": 64, - "slack": 32 - }, - "litellm/litellm_core_utils/safe_json_loads.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/litellm_core_utils/sensitive_data_masker.py": { - "baseline": 64, - "slack": 32 - }, - "litellm/litellm_core_utils/specialty_caches/dynamic_logging_cache.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/litellm_core_utils/streaming_chunk_builder_utils.py": { - "baseline": 313, - "slack": 157 - }, - "litellm/litellm_core_utils/streaming_handler.py": { - "baseline": 1020, - "slack": 510 - }, - "litellm/litellm_core_utils/token_counter.py": { - "baseline": 249, - "slack": 125 - }, - "litellm/litellm_core_utils/url_utils.py": { - "baseline": 46, - "slack": 23 - }, - "litellm/llms/__init__.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/llms/a2a/chat/guardrail_translation/handler.py": { - "baseline": 158, - "slack": 79 - }, - "litellm/llms/a2a/chat/streaming_iterator.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/llms/a2a/chat/transformation.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/llms/a2a/common_utils.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/llms/ai21/chat/transformation.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/llms/aiml/image_generation/cost_calculator.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/aiml/image_generation/transformation.py": { - "baseline": 61, - "slack": 31 - }, - "litellm/llms/aiohttp_openai/chat/transformation.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/llms/amazon_nova/chat/transformation.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/llms/anthropic/batches/handler.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/llms/anthropic/batches/transformation.py": { - "baseline": 55, - "slack": 28 - }, - "litellm/llms/anthropic/chat/guardrail_translation/handler.py": { - "baseline": 181, - "slack": 91 - }, - "litellm/llms/anthropic/chat/handler.py": { - "baseline": 390, - "slack": 195 - }, - "litellm/llms/anthropic/chat/transformation.py": { - "baseline": 770, - "slack": 385 - }, - "litellm/llms/anthropic/common_utils.py": { - "baseline": 278, - "slack": 139 - }, - "litellm/llms/anthropic/completion/transformation.py": { - "baseline": 86, - "slack": 43 - }, - "litellm/llms/anthropic/cost_calculation.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/llms/anthropic/count_tokens/handler.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/llms/anthropic/count_tokens/token_counter.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/llms/anthropic/count_tokens/transformation.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/llms/anthropic/experimental_pass_through/adapters/handler.py": { - "baseline": 228, - "slack": 114 - }, - "litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py": { - "baseline": 434, - "slack": 217 - }, - "litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py": { - "baseline": 328, - "slack": 164 - }, - "litellm/llms/anthropic/experimental_pass_through/context_management/dispatcher.py": { - "baseline": 57, - "slack": 29 - }, - "litellm/llms/anthropic/experimental_pass_through/context_management/editors/clear_tool_uses.py": { - "baseline": 100, - "slack": 50 - }, - "litellm/llms/anthropic/experimental_pass_through/context_management/editors/compact.py": { - "baseline": 420, - "slack": 210 - }, - "litellm/llms/anthropic/experimental_pass_through/context_management/placeholders.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/llms/anthropic/experimental_pass_through/context_management/result.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/anthropic/experimental_pass_through/messages/agentic_streaming_iterator.py": { - "baseline": 193, - "slack": 97 - }, - "litellm/llms/anthropic/experimental_pass_through/messages/fake_stream_iterator.py": { - "baseline": 78, - "slack": 39 - }, - "litellm/llms/anthropic/experimental_pass_through/messages/handler.py": { - "baseline": 148, - "slack": 74 - }, - "litellm/llms/anthropic/experimental_pass_through/messages/interceptors/advisor.py": { - "baseline": 150, - "slack": 75 - }, - "litellm/llms/anthropic/experimental_pass_through/messages/streaming_iterator.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/llms/anthropic/experimental_pass_through/messages/transformation.py": { - "baseline": 162, - "slack": 81 - }, - "litellm/llms/anthropic/experimental_pass_through/messages/utils.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/llms/anthropic/experimental_pass_through/responses_adapters/handler.py": { - "baseline": 96, - "slack": 48 - }, - "litellm/llms/anthropic/experimental_pass_through/responses_adapters/streaming_iterator.py": { - "baseline": 187, - "slack": 94 - }, - "litellm/llms/anthropic/experimental_pass_through/responses_adapters/transformation.py": { - "baseline": 250, - "slack": 125 - }, - "litellm/llms/anthropic/files/handler.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/llms/anthropic/files/transformation.py": { - "baseline": 47, - "slack": 24 - }, - "litellm/llms/anthropic/skills/transformation.py": { - "baseline": 40, - "slack": 20 - }, - "litellm/llms/apiserpent/search/defaults.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/llms/apiserpent/search/transformation.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/llms/aws_polly/text_to_speech/transformation.py": { - "baseline": 74, - "slack": 37 - }, - "litellm/llms/azure/assistants.py": { - "baseline": 114, - "slack": 57 - }, - "litellm/llms/azure/audio_transcription/transformation.py": { - "baseline": 37, - "slack": 19 - }, - "litellm/llms/azure/audio_transcriptions.py": { - "baseline": 47, - "slack": 24 - }, - "litellm/llms/azure/azure.py": { - "baseline": 459, - "slack": 230 - }, - "litellm/llms/azure/batches/handler.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/llms/azure/chat/gpt_5_transformation.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/llms/azure/chat/gpt_transformation.py": { - "baseline": 44, - "slack": 22 - }, - "litellm/llms/azure/chat/o_series_handler.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/llms/azure/chat/o_series_transformation.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/llms/azure/common_utils.py": { - "baseline": 221, - "slack": 111 - }, - "litellm/llms/azure/completion/handler.py": { - "baseline": 129, - "slack": 65 - }, - "litellm/llms/azure/completion/transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/azure/containers/transformation.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/llms/azure/exception_mapping.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/llms/azure/files/handler.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/llms/azure/fine_tuning/handler.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/llms/azure/image_edit/transformation.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/llms/azure/image_generation/http_utils.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/llms/azure/passthrough/transformation.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/llms/azure/realtime/handler.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/llms/azure/realtime/http_transformation.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/llms/azure/responses/o_series_transformation.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/llms/azure/responses/transformation.py": { - "baseline": 72, - "slack": 36 - }, - "litellm/llms/azure/text_to_speech/transformation.py": { - "baseline": 61, - "slack": 31 - }, - "litellm/llms/azure/vector_stores/transformation.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/llms/azure/videos/transformation.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/llms/azure_ai/agents/handler.py": { - "baseline": 293, - "slack": 147 - }, - "litellm/llms/azure_ai/agents/transformation.py": { - "baseline": 49, - "slack": 25 - }, - "litellm/llms/azure_ai/anthropic/count_tokens/handler.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/llms/azure_ai/anthropic/count_tokens/token_counter.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/llms/azure_ai/anthropic/count_tokens/transformation.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/llms/azure_ai/anthropic/handler.py": { - "baseline": 101, - "slack": 51 - }, - "litellm/llms/azure_ai/anthropic/messages_transformation.py": { - "baseline": 44, - "slack": 22 - }, - "litellm/llms/azure_ai/anthropic/transformation.py": { - "baseline": 39, - "slack": 20 - }, - "litellm/llms/azure_ai/azure_model_router/transformation.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/llms/azure_ai/chat/transformation.py": { - "baseline": 80, - "slack": 40 - }, - "litellm/llms/azure_ai/embed/cohere_transformation.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/llms/azure_ai/embed/handler.py": { - "baseline": 79, - "slack": 40 - }, - "litellm/llms/azure_ai/image_edit/flux2_transformation.py": { - "baseline": 26, - "slack": 13 - }, - "litellm/llms/azure_ai/image_edit/mai_transformation.py": { - "baseline": 47, - "slack": 24 - }, - "litellm/llms/azure_ai/image_edit/transformation.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/llms/azure_ai/image_generation/cost_calculator.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/azure_ai/image_generation/mai_transformation.py": { - "baseline": 88, - "slack": 44 - }, - "litellm/llms/azure_ai/ocr/document_intelligence/transformation.py": { - "baseline": 126, - "slack": 63 - }, - "litellm/llms/azure_ai/ocr/transformation.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/llms/azure_ai/rerank/transformation.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/llms/azure_ai/vector_stores/transformation.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/llms/base.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/llms/base_llm/agents/transformation.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/base_llm/anthropic_messages/transformation.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/llms/base_llm/audio_transcription/transformation.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/llms/base_llm/base_model_iterator.py": { - "baseline": 86, - "slack": 43 - }, - "litellm/llms/base_llm/base_utils.py": { - "baseline": 76, - "slack": 38 - }, - "litellm/llms/base_llm/batches/transformation.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/llms/base_llm/chat/transformation.py": { - "baseline": 63, - "slack": 32 - }, - "litellm/llms/base_llm/completion/transformation.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/base_llm/containers/transformation.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/llms/base_llm/embedding/transformation.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/base_llm/evals/transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/base_llm/files/azure_blob_storage_backend.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/llms/base_llm/files/transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/base_llm/google_genai/transformation.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/llms/base_llm/guardrail_translation/base_translation.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/llms/base_llm/guardrail_translation/utils.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/llms/base_llm/image_edit/transformation.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/llms/base_llm/image_generation/transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/base_llm/image_variations/transformation.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/base_llm/interactions/transformation.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/llms/base_llm/managed_resources/base_managed_resource.py": { - "baseline": 111, - "slack": 56 - }, - "litellm/llms/base_llm/managed_resources/isolation.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/llms/base_llm/managed_resources/utils.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/llms/base_llm/ocr/transformation.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/llms/base_llm/passthrough/transformation.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/llms/base_llm/realtime/http_transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/base_llm/realtime/transformation.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/base_llm/rerank/transformation.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/llms/base_llm/responses/transformation.py": { - "baseline": 28, - "slack": 14 - }, - "litellm/llms/base_llm/search/transformation.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/llms/base_llm/skills/transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/base_llm/text_to_speech/transformation.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/llms/base_llm/vector_store/transformation.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/llms/base_llm/vector_store_files/transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/base_llm/videos/transformation.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/llms/baseten/chat.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/llms/bedrock/base_aws_llm.py": { - "baseline": 341, - "slack": 171 - }, - "litellm/llms/bedrock/batches/handler.py": { - "baseline": 78, - "slack": 39 - }, - "litellm/llms/bedrock/batches/transformation.py": { - "baseline": 144, - "slack": 72 - }, - "litellm/llms/bedrock/chat/agentcore/transformation.py": { - "baseline": 195, - "slack": 98 - }, - "litellm/llms/bedrock/chat/converse_handler.py": { - "baseline": 152, - "slack": 76 - }, - "litellm/llms/bedrock/chat/converse_transformation.py": { - "baseline": 527, - "slack": 264 - }, - "litellm/llms/bedrock/chat/invoke_agent/transformation.py": { - "baseline": 65, - "slack": 33 - }, - "litellm/llms/bedrock/chat/invoke_handler.py": { - "baseline": 634, - "slack": 317 - }, - "litellm/llms/bedrock/chat/invoke_transformations/amazon_ai21_transformation.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/llms/bedrock/chat/invoke_transformations/amazon_cohere_transformation.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/llms/bedrock/chat/invoke_transformations/amazon_deepseek_transformation.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/llms/bedrock/chat/invoke_transformations/amazon_llama_transformation.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/llms/bedrock/chat/invoke_transformations/amazon_mistral_transformation.py": { - "baseline": 45, - "slack": 23 - }, - "litellm/llms/bedrock/chat/invoke_transformations/amazon_moonshot_transformation.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/llms/bedrock/chat/invoke_transformations/amazon_nova_transformation.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/llms/bedrock/chat/invoke_transformations/amazon_openai_transformation.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/llms/bedrock/chat/invoke_transformations/amazon_qwen2_transformation.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/llms/bedrock/chat/invoke_transformations/amazon_qwen3_transformation.py": { - "baseline": 72, - "slack": 36 - }, - "litellm/llms/bedrock/chat/invoke_transformations/amazon_titan_transformation.py": { - "baseline": 46, - "slack": 23 - }, - "litellm/llms/bedrock/chat/invoke_transformations/amazon_twelvelabs_pegasus_transformation.py": { - "baseline": 102, - "slack": 51 - }, - "litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude2_transformation.py": { - "baseline": 39, - "slack": 20 - }, - "litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py": { - "baseline": 139, - "slack": 70 - }, - "litellm/llms/bedrock/chat/invoke_transformations/base_invoke_transformation.py": { - "baseline": 192, - "slack": 96 - }, - "litellm/llms/bedrock/chat/mantle/transformation.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/llms/bedrock/claude_platform/common_utils.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/llms/bedrock/claude_platform/messages_transformation.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/llms/bedrock/claude_platform/transformation.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/llms/bedrock/common_utils.py": { - "baseline": 279, - "slack": 140 - }, - "litellm/llms/bedrock/count_tokens/bedrock_token_counter.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/llms/bedrock/count_tokens/handler.py": { - "baseline": 31, - "slack": 16 - }, - "litellm/llms/bedrock/count_tokens/transformation.py": { - "baseline": 106, - "slack": 53 - }, - "litellm/llms/bedrock/embed/amazon_nova_transformation.py": { - "baseline": 96, - "slack": 48 - }, - "litellm/llms/bedrock/embed/amazon_titan_g1_transformation.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/llms/bedrock/embed/amazon_titan_multimodal_transformation.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/llms/bedrock/embed/amazon_titan_v2_transformation.py": { - "baseline": 46, - "slack": 23 - }, - "litellm/llms/bedrock/embed/cohere_transformation.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/llms/bedrock/embed/embedding.py": { - "baseline": 225, - "slack": 113 - }, - "litellm/llms/bedrock/embed/twelvelabs_marengo_transformation.py": { - "baseline": 57, - "slack": 29 - }, - "litellm/llms/bedrock/files/handler.py": { - "baseline": 33, - "slack": 17 - }, - "litellm/llms/bedrock/files/transformation.py": { - "baseline": 218, - "slack": 109 - }, - "litellm/llms/bedrock/image_edit/amazon_nova_canvas_image_edit_transformation.py": { - "baseline": 156, - "slack": 78 - }, - "litellm/llms/bedrock/image_edit/handler.py": { - "baseline": 56, - "slack": 28 - }, - "litellm/llms/bedrock/image_edit/stability_transformation.py": { - "baseline": 87, - "slack": 44 - }, - "litellm/llms/bedrock/image_generation/amazon_nova_canvas_transformation.py": { - "baseline": 79, - "slack": 40 - }, - "litellm/llms/bedrock/image_generation/amazon_stability1_transformation.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/llms/bedrock/image_generation/amazon_stability3_transformation.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/llms/bedrock/image_generation/amazon_titan_transformation.py": { - "baseline": 64, - "slack": 32 - }, - "litellm/llms/bedrock/image_generation/cost_calculator.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/bedrock/image_generation/image_handler.py": { - "baseline": 59, - "slack": 30 - }, - "litellm/llms/bedrock/messages/invoke_transformations/anthropic_claude3_transformation.py": { - "baseline": 237, - "slack": 119 - }, - "litellm/llms/bedrock/messages/mantle_transformation.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/llms/bedrock/passthrough/guardrail_translation/handler.py": { - "baseline": 337, - "slack": 169 - }, - "litellm/llms/bedrock/passthrough/transformation.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/llms/bedrock/realtime/handler.py": { - "baseline": 58, - "slack": 29 - }, - "litellm/llms/bedrock/realtime/transformation.py": { - "baseline": 293, - "slack": 147 - }, - "litellm/llms/bedrock/rerank/handler.py": { - "baseline": 40, - "slack": 20 - }, - "litellm/llms/bedrock/rerank/transformation.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/llms/bedrock/vector_stores/transformation.py": { - "baseline": 123, - "slack": 62 - }, - "litellm/llms/bedrock_mantle/chat/transformation.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/llms/bedrock_mantle/responses/transformation.py": { - "baseline": 63, - "slack": 32 - }, - "litellm/llms/black_forest_labs/image_edit/handler.py": { - "baseline": 126, - "slack": 63 - }, - "litellm/llms/black_forest_labs/image_edit/transformation.py": { - "baseline": 45, - "slack": 23 - }, - "litellm/llms/black_forest_labs/image_generation/handler.py": { - "baseline": 130, - "slack": 65 - }, - "litellm/llms/black_forest_labs/image_generation/transformation.py": { - "baseline": 49, - "slack": 25 - }, - "litellm/llms/brave/search/transformation.py": { - "baseline": 71, - "slack": 36 - }, - "litellm/llms/bytez/chat/transformation.py": { - "baseline": 128, - "slack": 64 - }, - "litellm/llms/cerebras/chat.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/llms/chatgpt/authenticator.py": { - "baseline": 107, - "slack": 54 - }, - "litellm/llms/chatgpt/chat/streaming_utils.py": { - "baseline": 40, - "slack": 20 - }, - "litellm/llms/chatgpt/chat/transformation.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/llms/chatgpt/common_utils.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/llms/chatgpt/responses/transformation.py": { - "baseline": 105, - "slack": 53 - }, - "litellm/llms/clarifai/chat/transformation.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/llms/cloudflare/chat/transformation.py": { - "baseline": 63, - "slack": 32 - }, - "litellm/llms/codestral/completion/handler.py": { - "baseline": 128, - "slack": 64 - }, - "litellm/llms/codestral/completion/transformation.py": { - "baseline": 49, - "slack": 25 - }, - "litellm/llms/cohere/chat/transformation.py": { - "baseline": 113, - "slack": 57 - }, - "litellm/llms/cohere/chat/v2_transformation.py": { - "baseline": 97, - "slack": 49 - }, - "litellm/llms/cohere/common_utils.py": { - "baseline": 165, - "slack": 83 - }, - "litellm/llms/cohere/embed/handler.py": { - "baseline": 71, - "slack": 36 - }, - "litellm/llms/cohere/embed/transformation.py": { - "baseline": 56, - "slack": 28 - }, - "litellm/llms/cohere/embed/v1_transformation.py": { - "baseline": 52, - "slack": 26 - }, - "litellm/llms/cohere/rerank/guardrail_translation/handler.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/llms/cohere/rerank/transformation.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/llms/cohere/rerank_v2/transformation.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/llms/cometapi/chat/transformation.py": { - "baseline": 38, - "slack": 19 - }, - "litellm/llms/cometapi/embed/transformation.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/llms/cometapi/image_generation/cost_calculator.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/cometapi/image_generation/transformation.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/llms/compactifai/chat/transformation.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/llms/custom_httpx/aiohttp_handler.py": { - "baseline": 187, - "slack": 94 - }, - "litellm/llms/custom_httpx/aiohttp_transport.py": { - "baseline": 40, - "slack": 20 - }, - "litellm/llms/custom_httpx/async_client_cleanup.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/llms/custom_httpx/container_handler.py": { - "baseline": 169, - "slack": 85 - }, - "litellm/llms/custom_httpx/http_handler.py": { - "baseline": 339, - "slack": 170 - }, - "litellm/llms/custom_httpx/httpx_handler.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/llms/custom_httpx/llm_http_handler.py": { - "baseline": 3900, - "slack": 1950 - }, - "litellm/llms/custom_httpx/mock_transport.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/llms/custom_llm.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/llms/dashscope/chat/transformation.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/dashscope/common_utils.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/dashscope/cost_calculator.py": { - "baseline": 49, - "slack": 25 - }, - "litellm/llms/dashscope/embed/transformation.py": { - "baseline": 44, - "slack": 22 - }, - "litellm/llms/dashscope/image_generation/transformation.py": { - "baseline": 48, - "slack": 24 - }, - "litellm/llms/dashscope/rerank/transformation.py": { - "baseline": 60, - "slack": 30 - }, - "litellm/llms/databricks/chat/transformation.py": { - "baseline": 168, - "slack": 84 - }, - "litellm/llms/databricks/common_utils.py": { - "baseline": 58, - "slack": 29 - }, - "litellm/llms/databricks/cost_calculator.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/llms/databricks/embed/handler.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/llms/databricks/embed/transformation.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/llms/databricks/responses/transformation.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/llms/databricks/streaming_utils.py": { - "baseline": 75, - "slack": 38 - }, - "litellm/llms/dataforseo/search/transformation.py": { - "baseline": 52, - "slack": 26 - }, - "litellm/llms/deepgram/audio_transcription/transformation.py": { - "baseline": 62, - "slack": 31 - }, - "litellm/llms/deepinfra/chat/transformation.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/llms/deepinfra/rerank/transformation.py": { - "baseline": 68, - "slack": 34 - }, - "litellm/llms/deepseek/chat/transformation.py": { - "baseline": 51, - "slack": 26 - }, - "litellm/llms/deepseek/messages/transformation.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/llms/deprecated_providers/aleph_alpha.py": { - "baseline": 102, - "slack": 51 - }, - "litellm/llms/deprecated_providers/palm.py": { - "baseline": 75, - "slack": 38 - }, - "litellm/llms/docker_model_runner/chat/transformation.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/llms/duckduckgo/search/transformation.py": { - "baseline": 67, - "slack": 34 - }, - "litellm/llms/elevenlabs/audio_transcription/transformation.py": { - "baseline": 44, - "slack": 22 - }, - "litellm/llms/elevenlabs/text_to_speech/transformation.py": { - "baseline": 94, - "slack": 47 - }, - "litellm/llms/exa_ai/search/transformation.py": { - "baseline": 40, - "slack": 20 - }, - "litellm/llms/fal_ai/cost_calculator.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/fal_ai/image_generation/bria_transformation.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/llms/fal_ai/image_generation/bytedance_transformation.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/llms/fal_ai/image_generation/flux_pro_v11_transformation.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/llms/fal_ai/image_generation/flux_pro_v11_ultra_transformation.py": { - "baseline": 39, - "slack": 20 - }, - "litellm/llms/fal_ai/image_generation/flux_schnell_transformation.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/llms/fal_ai/image_generation/ideogram_v3_transformation.py": { - "baseline": 41, - "slack": 21 - }, - "litellm/llms/fal_ai/image_generation/imagen4_transformation.py": { - "baseline": 32, - "slack": 16 - }, - "litellm/llms/fal_ai/image_generation/nano_banana_transformation.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/llms/fal_ai/image_generation/recraft_v3_transformation.py": { - "baseline": 32, - "slack": 16 - }, - "litellm/llms/fal_ai/image_generation/stable_diffusion_transformation.py": { - "baseline": 41, - "slack": 21 - }, - "litellm/llms/fal_ai/image_generation/transformation.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/llms/fastcrw/search/transformation.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/llms/featherless_ai/chat/transformation.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/llms/firecrawl/search/transformation.py": { - "baseline": 55, - "slack": 28 - }, - "litellm/llms/fireworks_ai/chat/transformation.py": { - "baseline": 124, - "slack": 62 - }, - "litellm/llms/fireworks_ai/common_utils.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/llms/fireworks_ai/completion/transformation.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/llms/fireworks_ai/cost_calculator.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/llms/fireworks_ai/embed/fireworks_ai_transformation.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/llms/fireworks_ai/rerank/transformation.py": { - "baseline": 52, - "slack": 26 - }, - "litellm/llms/gemini/agents/transformation.py": { - "baseline": 58, - "slack": 29 - }, - "litellm/llms/gemini/chat/transformation.py": { - "baseline": 26, - "slack": 13 - }, - "litellm/llms/gemini/common_utils.py": { - "baseline": 158, - "slack": 79 - }, - "litellm/llms/gemini/count_tokens/handler.py": { - "baseline": 37, - "slack": 19 - }, - "litellm/llms/gemini/files/transformation.py": { - "baseline": 40, - "slack": 20 - }, - "litellm/llms/gemini/google_genai/transformation.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/llms/gemini/image_edit/cost_calculator.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/gemini/image_edit/transformation.py": { - "baseline": 44, - "slack": 22 - }, - "litellm/llms/gemini/image_generation/cost_calculator.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/gemini/image_generation/transformation.py": { - "baseline": 52, - "slack": 26 - }, - "litellm/llms/gemini/image_usage_transformation.py": { - "baseline": 31, - "slack": 16 - }, - "litellm/llms/gemini/interactions/transformation.py": { - "baseline": 92, - "slack": 46 - }, - "litellm/llms/gemini/realtime/transformation.py": { - "baseline": 324, - "slack": 162 - }, - "litellm/llms/gemini/vector_stores/transformation.py": { - "baseline": 97, - "slack": 49 - }, - "litellm/llms/gemini/videos/transformation.py": { - "baseline": 77, - "slack": 39 - }, - "litellm/llms/gigachat/authenticator.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/llms/gigachat/chat/streaming.py": { - "baseline": 32, - "slack": 16 - }, - "litellm/llms/gigachat/chat/transformation.py": { - "baseline": 157, - "slack": 79 - }, - "litellm/llms/gigachat/embedding/transformation.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/llms/gigachat/file_handler.py": { - "baseline": 47, - "slack": 24 - }, - "litellm/llms/github_copilot/authenticator.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/llms/github_copilot/chat/transformation.py": { - "baseline": 87, - "slack": 44 - }, - "litellm/llms/github_copilot/common_utils.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/llms/github_copilot/embedding/transformation.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/llms/github_copilot/responses/transformation.py": { - "baseline": 70, - "slack": 35 - }, - "litellm/llms/google_pse/search/transformation.py": { - "baseline": 61, - "slack": 31 - }, - "litellm/llms/gradient_ai/chat/transformation.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/llms/groq/chat/handler.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/llms/groq/chat/transformation.py": { - "baseline": 55, - "slack": 28 - }, - "litellm/llms/groq/stt/transformation.py": { - "baseline": 31, - "slack": 16 - }, - "litellm/llms/heroku/chat/transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/hosted_vllm/chat/transformation.py": { - "baseline": 80, - "slack": 40 - }, - "litellm/llms/hosted_vllm/embedding/transformation.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/llms/hosted_vllm/rerank/transformation.py": { - "baseline": 40, - "slack": 20 - }, - "litellm/llms/hosted_vllm/responses/transformation.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/llms/hosted_vllm/transcriptions/transformation.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/llms/huggingface/chat/transformation.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/llms/huggingface/common_utils.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/llms/huggingface/embedding/handler.py": { - "baseline": 157, - "slack": 79 - }, - "litellm/llms/huggingface/embedding/transformation.py": { - "baseline": 224, - "slack": 112 - }, - "litellm/llms/huggingface/rerank/transformation.py": { - "baseline": 70, - "slack": 35 - }, - "litellm/llms/hyperbolic/chat/transformation.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/inception/chat/transformation.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/inception/completion/transformation.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/llms/infinity/common_utils.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/infinity/embedding/transformation.py": { - "baseline": 28, - "slack": 14 - }, - "litellm/llms/infinity/rerank/transformation.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/llms/jina_ai/common_utils.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/llms/jina_ai/embedding/transformation.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/llms/jina_ai/rerank/transformation.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/llms/langflow/a2a.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/llms/langflow/chat/transformation.py": { - "baseline": 67, - "slack": 34 - }, - "litellm/llms/langgraph/chat/sse_iterator.py": { - "baseline": 49, - "slack": 25 - }, - "litellm/llms/langgraph/chat/transformation.py": { - "baseline": 103, - "slack": 52 - }, - "litellm/llms/lemonade/chat/transformation.py": { - "baseline": 66, - "slack": 33 - }, - "litellm/llms/linkup/search/transformation.py": { - "baseline": 43, - "slack": 22 - }, - "litellm/llms/litellm_proxy/chat/transformation.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/llms/litellm_proxy/image_edit/transformation.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/llms/litellm_proxy/image_generation/transformation.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/llms/litellm_proxy/skills/code_execution.py": { - "baseline": 111, - "slack": 56 - }, - "litellm/llms/litellm_proxy/skills/handler.py": { - "baseline": 67, - "slack": 34 - }, - "litellm/llms/litellm_proxy/skills/prompt_injection.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/llms/litellm_proxy/skills/sandbox_executor.py": { - "baseline": 60, - "slack": 30 - }, - "litellm/llms/litellm_proxy/skills/transformation.py": { - "baseline": 57, - "slack": 29 - }, - "litellm/llms/lm_studio/chat/transformation.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/llms/lm_studio/embed/transformation.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/llms/manus/files/transformation.py": { - "baseline": 68, - "slack": 34 - }, - "litellm/llms/manus/responses/transformation.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/llms/maritalk.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/llms/meta_llama/chat/transformation.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/llms/milvus/vector_stores/transformation.py": { - "baseline": 67, - "slack": 34 - }, - "litellm/llms/minimax/chat/transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/minimax/text_to_speech/transformation.py": { - "baseline": 112, - "slack": 56 - }, - "litellm/llms/mistral/audio_transcription/transformation.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/llms/mistral/chat/transformation.py": { - "baseline": 183, - "slack": 92 - }, - "litellm/llms/mistral/ocr/guardrail_translation/handler.py": { - "baseline": 39, - "slack": 20 - }, - "litellm/llms/mistral/ocr/transformation.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/llms/modelscope/chat/transformation.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/llms/modelscope/image_generation/transformation.py": { - "baseline": 33, - "slack": 17 - }, - "litellm/llms/moonshot/chat/transformation.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/llms/morph/chat/transformation.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/nebius/chat/transformation.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/llms/nlp_cloud/chat/handler.py": { - "baseline": 55, - "slack": 28 - }, - "litellm/llms/nlp_cloud/chat/transformation.py": { - "baseline": 57, - "slack": 29 - }, - "litellm/llms/nlp_cloud/common_utils.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/novita/chat/transformation.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/llms/nscale/chat/transformation.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/nvidia_nim/chat/transformation.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/llms/nvidia_nim/embed.py": { - "baseline": 39, - "slack": 20 - }, - "litellm/llms/nvidia_nim/rerank/ranking_transformation.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/llms/nvidia_nim/rerank/transformation.py": { - "baseline": 58, - "slack": 29 - }, - "litellm/llms/nvidia_riva/audio_transcription/audio_utils.py": { - "baseline": 89, - "slack": 45 - }, - "litellm/llms/nvidia_riva/audio_transcription/handler.py": { - "baseline": 142, - "slack": 71 - }, - "litellm/llms/nvidia_riva/audio_transcription/transformation.py": { - "baseline": 83, - "slack": 42 - }, - "litellm/llms/nvidia_riva/common_utils.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/llms/oci/chat/cohere.py": { - "baseline": 80, - "slack": 40 - }, - "litellm/llms/oci/chat/generic.py": { - "baseline": 58, - "slack": 29 - }, - "litellm/llms/oci/chat/transformation.py": { - "baseline": 159, - "slack": 80 - }, - "litellm/llms/oci/common_utils.py": { - "baseline": 221, - "slack": 111 - }, - "litellm/llms/oci/embed/transformation.py": { - "baseline": 45, - "slack": 23 - }, - "litellm/llms/ollama/chat/transformation.py": { - "baseline": 173, - "slack": 87 - }, - "litellm/llms/ollama/common_utils.py": { - "baseline": 68, - "slack": 34 - }, - "litellm/llms/ollama/completion/handler.py": { - "baseline": 41, - "slack": 21 - }, - "litellm/llms/ollama/completion/transformation.py": { - "baseline": 143, - "slack": 72 - }, - "litellm/llms/oobabooga/chat/oobabooga.py": { - "baseline": 59, - "slack": 30 - }, - "litellm/llms/oobabooga/chat/transformation.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/llms/oobabooga/common_utils.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/openai/chat/gpt_5_transformation.py": { - "baseline": 51, - "slack": 26 - }, - "litellm/llms/openai/chat/gpt_audio_transformation.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/llms/openai/chat/gpt_transformation.py": { - "baseline": 132, - "slack": 66 - }, - "litellm/llms/openai/chat/guardrail_translation/handler.py": { - "baseline": 196, - "slack": 98 - }, - "litellm/llms/openai/chat/o_series_transformation.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/llms/openai/common_utils.py": { - "baseline": 46, - "slack": 23 - }, - "litellm/llms/openai/completion/guardrail_translation/handler.py": { - "baseline": 43, - "slack": 22 - }, - "litellm/llms/openai/completion/handler.py": { - "baseline": 140, - "slack": 70 - }, - "litellm/llms/openai/completion/transformation.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/llms/openai/completion/utils.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/llms/openai/containers/transformation.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/llms/openai/cost_calculation.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/llms/openai/embeddings/guardrail_translation/handler.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/llms/openai/evals/transformation.py": { - "baseline": 73, - "slack": 37 - }, - "litellm/llms/openai/fine_tuning/handler.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/llms/openai/image_edit/dalle2_transformation.py": { - "baseline": 46, - "slack": 23 - }, - "litellm/llms/openai/image_edit/transformation.py": { - "baseline": 63, - "slack": 32 - }, - "litellm/llms/openai/image_generation/cost_calculator.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/llms/openai/image_generation/dall_e_2_transformation.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/llms/openai/image_generation/dall_e_3_transformation.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/llms/openai/image_generation/gpt_transformation.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/llms/openai/image_generation/guardrail_translation/handler.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/llms/openai/image_variations/handler.py": { - "baseline": 69, - "slack": 35 - }, - "litellm/llms/openai/image_variations/transformation.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/llms/openai/openai.py": { - "baseline": 664, - "slack": 332 - }, - "litellm/llms/openai/realtime/handler.py": { - "baseline": 31, - "slack": 16 - }, - "litellm/llms/openai/realtime/http_transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/openai/responses/count_tokens/handler.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/llms/openai/responses/count_tokens/token_counter.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/llms/openai/responses/count_tokens/transformation.py": { - "baseline": 85, - "slack": 43 - }, - "litellm/llms/openai/responses/guardrail_translation/handler.py": { - "baseline": 256, - "slack": 128 - }, - "litellm/llms/openai/responses/transformation.py": { - "baseline": 126, - "slack": 63 - }, - "litellm/llms/openai/speech/guardrail_translation/handler.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/llms/openai/transcriptions/gpt_transformation.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/llms/openai/transcriptions/guardrail_translation/handler.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/llms/openai/transcriptions/handler.py": { - "baseline": 74, - "slack": 37 - }, - "litellm/llms/openai/transcriptions/whisper_transformation.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/llms/openai/vector_store_files/transformation.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/llms/openai/vector_stores/transformation.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/llms/openai/videos/transformation.py": { - "baseline": 154, - "slack": 77 - }, - "litellm/llms/openai_like/chat/handler.py": { - "baseline": 113, - "slack": 57 - }, - "litellm/llms/openai_like/chat/transformation.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/llms/openai_like/common_utils.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/llms/openai_like/dynamic_config.py": { - "baseline": 73, - "slack": 37 - }, - "litellm/llms/openai_like/embedding/handler.py": { - "baseline": 56, - "slack": 28 - }, - "litellm/llms/openai_like/json_loader.py": { - "baseline": 46, - "slack": 23 - }, - "litellm/llms/openai_like/responses/transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/openrouter/chat/transformation.py": { - "baseline": 88, - "slack": 44 - }, - "litellm/llms/openrouter/embedding/transformation.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/llms/openrouter/image_edit/transformation.py": { - "baseline": 93, - "slack": 47 - }, - "litellm/llms/openrouter/image_generation/transformation.py": { - "baseline": 81, - "slack": 41 - }, - "litellm/llms/openrouter/responses/transformation.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/llms/ovhcloud/audio_transcription/transformation.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/llms/ovhcloud/chat/transformation.py": { - "baseline": 38, - "slack": 19 - }, - "litellm/llms/ovhcloud/embedding/transformation.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/llms/parallel_ai/search/transformation.py": { - "baseline": 55, - "slack": 28 - }, - "litellm/llms/pass_through/guardrail_translation/handler.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/llms/perplexity/chat/transformation.py": { - "baseline": 59, - "slack": 30 - }, - "litellm/llms/perplexity/cost_calculator.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/llms/perplexity/embedding/transformation.py": { - "baseline": 47, - "slack": 24 - }, - "litellm/llms/perplexity/responses/transformation.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/llms/perplexity/search/transformation.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/llms/petals/common_utils.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/petals/completion/handler.py": { - "baseline": 49, - "slack": 25 - }, - "litellm/llms/petals/completion/transformation.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/llms/pg_vector/vector_stores/transformation.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/llms/predibase/chat/handler.py": { - "baseline": 98, - "slack": 49 - }, - "litellm/llms/predibase/chat/transformation.py": { - "baseline": 116, - "slack": 58 - }, - "litellm/llms/predibase/common_utils.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/ragflow/chat/transformation.py": { - "baseline": 43, - "slack": 22 - }, - "litellm/llms/ragflow/vector_stores/transformation.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/llms/recraft/cost_calculator.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/recraft/image_edit/transformation.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/llms/recraft/image_generation/transformation.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/llms/reducto/common.py": { - "baseline": 46, - "slack": 23 - }, - "litellm/llms/reducto/ocr/transformation.py": { - "baseline": 53, - "slack": 27 - }, - "litellm/llms/replicate/chat/handler.py": { - "baseline": 139, - "slack": 70 - }, - "litellm/llms/replicate/chat/transformation.py": { - "baseline": 76, - "slack": 38 - }, - "litellm/llms/replicate/common_utils.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/runwayml/cost_calculator.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/runwayml/image_generation/transformation.py": { - "baseline": 80, - "slack": 40 - }, - "litellm/llms/runwayml/text_to_speech/transformation.py": { - "baseline": 116, - "slack": 58 - }, - "litellm/llms/runwayml/videos/transformation.py": { - "baseline": 125, - "slack": 63 - }, - "litellm/llms/s3_vectors/vector_stores/transformation.py": { - "baseline": 71, - "slack": 36 - }, - "litellm/llms/sagemaker/chat/handler.py": { - "baseline": 81, - "slack": 41 - }, - "litellm/llms/sagemaker/chat/transformation.py": { - "baseline": 33, - "slack": 17 - }, - "litellm/llms/sagemaker/common_utils.py": { - "baseline": 62, - "slack": 31 - }, - "litellm/llms/sagemaker/completion/handler.py": { - "baseline": 301, - "slack": 151 - }, - "litellm/llms/sagemaker/completion/transformation.py": { - "baseline": 95, - "slack": 48 - }, - "litellm/llms/sagemaker/embedding/cohere_transformation.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/llms/sagemaker/embedding/transformation.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/llms/sagemaker/nova/transformation.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/llms/sambanova/chat.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/llms/sambanova/common_utils.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/llms/sambanova/embedding/transformation.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/llms/sap/chat/handler.py": { - "baseline": 100, - "slack": 50 - }, - "litellm/llms/sap/chat/models.py": { - "baseline": 95, - "slack": 48 - }, - "litellm/llms/sap/chat/transformation.py": { - "baseline": 182, - "slack": 91 - }, - "litellm/llms/sap/credentials.py": { - "baseline": 61, - "slack": 31 - }, - "litellm/llms/sap/embed/transformation.py": { - "baseline": 82, - "slack": 41 - }, - "litellm/llms/scaleway/audio_transcription/transformation.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/llms/searchapi/search/transformation.py": { - "baseline": 58, - "slack": 29 - }, - "litellm/llms/searxng/search/transformation.py": { - "baseline": 43, - "slack": 22 - }, - "litellm/llms/serper/search/transformation.py": { - "baseline": 37, - "slack": 19 - }, - "litellm/llms/snowflake/chat/transformation.py": { - "baseline": 244, - "slack": 122 - }, - "litellm/llms/snowflake/common_utils.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/llms/snowflake/embedding/transformation.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/llms/snowflake/utils.py": { - "baseline": 26, - "slack": 13 - }, - "litellm/llms/soniox/audio_transcription/handler.py": { - "baseline": 196, - "slack": 98 - }, - "litellm/llms/soniox/audio_transcription/transformation.py": { - "baseline": 107, - "slack": 54 - }, - "litellm/llms/soniox/common_utils.py": { - "baseline": 68, - "slack": 34 - }, - "litellm/llms/stability/image_edit/transformations.py": { - "baseline": 59, - "slack": 30 - }, - "litellm/llms/stability/image_generation/transformation.py": { - "baseline": 41, - "slack": 21 - }, - "litellm/llms/tavily/search/transformation.py": { - "baseline": 38, - "slack": 19 - }, - "litellm/llms/together_ai/chat.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/llms/together_ai/completion/transformation.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/llms/together_ai/cost_calculator.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/llms/together_ai/rerank/handler.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/llms/together_ai/rerank/transformation.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/llms/topaz/common_utils.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/topaz/image_variations/transformation.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/llms/triton/common_utils.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/triton/completion/transformation.py": { - "baseline": 71, - "slack": 36 - }, - "litellm/llms/triton/embedding/transformation.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/llms/v0/chat/transformation.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/vercel_ai_gateway/chat/transformation.py": { - "baseline": 28, - "slack": 14 - }, - "litellm/llms/vercel_ai_gateway/embedding/transformation.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/llms/vertex_ai/agent_engine/sse_iterator.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/llms/vertex_ai/agent_engine/transformation.py": { - "baseline": 71, - "slack": 36 - }, - "litellm/llms/vertex_ai/aws_credentials_supplier.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/llms/vertex_ai/batches/handler.py": { - "baseline": 118, - "slack": 59 - }, - "litellm/llms/vertex_ai/batches/transformation.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/llms/vertex_ai/common_utils.py": { - "baseline": 493, - "slack": 247 - }, - "litellm/llms/vertex_ai/context_caching/transformation.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/llms/vertex_ai/context_caching/vertex_ai_context_caching.py": { - "baseline": 85, - "slack": 43 - }, - "litellm/llms/vertex_ai/cost_calculator.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/llms/vertex_ai/count_tokens/handler.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/llms/vertex_ai/files/handler.py": { - "baseline": 28, - "slack": 14 - }, - "litellm/llms/vertex_ai/files/transformation.py": { - "baseline": 177, - "slack": 89 - }, - "litellm/llms/vertex_ai/fine_tuning/handler.py": { - "baseline": 56, - "slack": 28 - }, - "litellm/llms/vertex_ai/gemini/transformation.py": { - "baseline": 311, - "slack": 156 - }, - "litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py": { - "baseline": 912, - "slack": 456 - }, - "litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_handler.py": { - "baseline": 82, - "slack": 41 - }, - "litellm/llms/vertex_ai/gemini_embeddings/batch_embed_content_transformation.py": { - "baseline": 32, - "slack": 16 - }, - "litellm/llms/vertex_ai/google_genai/transformation.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/llms/vertex_ai/image_edit/cost_calculator.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/vertex_ai/image_edit/vertex_gemini_transformation.py": { - "baseline": 70, - "slack": 35 - }, - "litellm/llms/vertex_ai/image_edit/vertex_imagen_transformation.py": { - "baseline": 85, - "slack": 43 - }, - "litellm/llms/vertex_ai/image_generation/image_generation_handler.py": { - "baseline": 71, - "slack": 36 - }, - "litellm/llms/vertex_ai/image_generation/vertex_gemini_transformation.py": { - "baseline": 118, - "slack": 59 - }, - "litellm/llms/vertex_ai/image_generation/vertex_imagen_transformation.py": { - "baseline": 50, - "slack": 25 - }, - "litellm/llms/vertex_ai/multimodal_embeddings/embedding_handler.py": { - "baseline": 50, - "slack": 25 - }, - "litellm/llms/vertex_ai/multimodal_embeddings/transformation.py": { - "baseline": 39, - "slack": 20 - }, - "litellm/llms/vertex_ai/ocr/deepseek_transformation.py": { - "baseline": 66, - "slack": 33 - }, - "litellm/llms/vertex_ai/ocr/transformation.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/llms/vertex_ai/rag_engine/ingestion.py": { - "baseline": 58, - "slack": 29 - }, - "litellm/llms/vertex_ai/rag_engine/transformation.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/llms/vertex_ai/realtime/transformation.py": { - "baseline": 44, - "slack": 22 - }, - "litellm/llms/vertex_ai/rerank/transformation.py": { - "baseline": 66, - "slack": 33 - }, - "litellm/llms/vertex_ai/text_to_speech/text_to_speech_handler.py": { - "baseline": 48, - "slack": 24 - }, - "litellm/llms/vertex_ai/text_to_speech/transformation.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/llms/vertex_ai/vector_stores/rag_api/transformation.py": { - "baseline": 81, - "slack": 41 - }, - "litellm/llms/vertex_ai/vector_stores/search_api/transformation.py": { - "baseline": 88, - "slack": 44 - }, - "litellm/llms/vertex_ai/vertex_ai_aws_wif.py": { - "baseline": 31, - "slack": 16 - }, - "litellm/llms/vertex_ai/vertex_ai_non_gemini.py": { - "baseline": 319, - "slack": 160 - }, - "litellm/llms/vertex_ai/vertex_ai_partner_models/ai21/transformation.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/experimental_pass_through/transformation.py": { - "baseline": 38, - "slack": 19 - }, - "litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/output_params_utils.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/llms/vertex_ai/vertex_ai_partner_models/anthropic/transformation.py": { - "baseline": 55, - "slack": 28 - }, - "litellm/llms/vertex_ai/vertex_ai_partner_models/count_tokens/handler.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/llms/vertex_ai/vertex_ai_partner_models/gpt_oss/transformation.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/llms/vertex_ai/vertex_ai_partner_models/llama3/transformation.py": { - "baseline": 65, - "slack": 33 - }, - "litellm/llms/vertex_ai/vertex_ai_partner_models/main.py": { - "baseline": 81, - "slack": 41 - }, - "litellm/llms/vertex_ai/vertex_embeddings/bge.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/llms/vertex_ai/vertex_embeddings/embedding_handler.py": { - "baseline": 46, - "slack": 23 - }, - "litellm/llms/vertex_ai/vertex_embeddings/transformation.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/llms/vertex_ai/vertex_embeddings/types.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/llms/vertex_ai/vertex_gemma_models/main.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/llms/vertex_ai/vertex_gemma_models/transformation.py": { - "baseline": 86, - "slack": 43 - }, - "litellm/llms/vertex_ai/vertex_llm_base.py": { - "baseline": 305, - "slack": 153 - }, - "litellm/llms/vertex_ai/vertex_model_garden/main.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/llms/vertex_ai/videos/transformation.py": { - "baseline": 164, - "slack": 82 - }, - "litellm/llms/vllm/common_utils.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/llms/vllm/completion/handler.py": { - "baseline": 75, - "slack": 38 - }, - "litellm/llms/vllm/passthrough/transformation.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/llms/volcengine/chat/transformation.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/llms/volcengine/common_utils.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/llms/volcengine/embedding/transformation.py": { - "baseline": 40, - "slack": 20 - }, - "litellm/llms/volcengine/responses/transformation.py": { - "baseline": 200, - "slack": 100 - }, - "litellm/llms/voyage/embedding/transformation.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/llms/voyage/embedding/transformation_contextual.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/llms/voyage/embedding/transformation_multimodal.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/llms/voyage/rerank/transformation.py": { - "baseline": 38, - "slack": 19 - }, - "litellm/llms/wandb/chat/transformation.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/llms/watsonx/audio_transcription/transformation.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/llms/watsonx/chat/handler.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/llms/watsonx/chat/transformation.py": { - "baseline": 43, - "slack": 22 - }, - "litellm/llms/watsonx/common_utils.py": { - "baseline": 101, - "slack": 51 - }, - "litellm/llms/watsonx/completion/transformation.py": { - "baseline": 117, - "slack": 59 - }, - "litellm/llms/watsonx/embed/transformation.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/llms/watsonx/passthrough/transformation.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/llms/watsonx/rerank/transformation.py": { - "baseline": 89, - "slack": 45 - }, - "litellm/llms/xai/chat/transformation.py": { - "baseline": 105, - "slack": 53 - }, - "litellm/llms/xai/common_utils.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/llms/xai/cost_calculator.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/llms/xai/oauth.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/llms/xai/realtime/handler.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/llms/xai/responses/transformation.py": { - "baseline": 70, - "slack": 35 - }, - "litellm/llms/xinference/image_generation/transformation.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/llms/you_com/search/transformation.py": { - "baseline": 49, - "slack": 25 - }, - "litellm/main.py": { - "baseline": 3138, - "slack": 1569 - }, - "litellm/models/access_group.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/models/base.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/models/budget.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/models/config.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/models/credentials.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/models/end_user.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/models/managed_files.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/models/mcp_server.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/models/model.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/models/object_permission.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/models/organization.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/models/organization_membership.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/models/project.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/models/skills.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/models/spend_logs.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/models/tag.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/models/team.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/models/team_membership.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/models/user.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/models/verification_token.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/ocr/main.py": { - "baseline": 80, - "slack": 40 - }, - "litellm/passthrough/main.py": { - "baseline": 100, - "slack": 50 - }, - "litellm/passthrough/timeout_utils.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/passthrough/utils.py": { - "baseline": 41, - "slack": 21 - }, - "litellm/proxy/_experimental/mcp_server/auth/token_exchange.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py": { - "baseline": 175, - "slack": 88 - }, - "litellm/proxy/_experimental/mcp_server/byok_oauth_endpoints.py": { - "baseline": 58, - "slack": 29 - }, - "litellm/proxy/_experimental/mcp_server/cost_calculator.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/proxy/_experimental/mcp_server/db.py": { - "baseline": 428, - "slack": 214 - }, - "litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py": { - "baseline": 193, - "slack": 97 - }, - "litellm/proxy/_experimental/mcp_server/elicitation_handler.py": { - "baseline": 57, - "slack": 29 - }, - "litellm/proxy/_experimental/mcp_server/guardrail_translation/handler.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/proxy/_experimental/mcp_server/mcp_debug.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/proxy/_experimental/mcp_server/mcp_server_manager.py": { - "baseline": 877, - "slack": 439 - }, - "litellm/proxy/_experimental/mcp_server/oauth2_token_cache.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/proxy/_experimental/mcp_server/oauth_utils.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/proxy/_experimental/mcp_server/openapi_to_mcp_generator.py": { - "baseline": 213, - "slack": 107 - }, - "litellm/proxy/_experimental/mcp_server/rest_endpoints.py": { - "baseline": 288, - "slack": 144 - }, - "litellm/proxy/_experimental/mcp_server/sampling_handler.py": { - "baseline": 541, - "slack": 271 - }, - "litellm/proxy/_experimental/mcp_server/semantic_tool_filter.py": { - "baseline": 98, - "slack": 49 - }, - "litellm/proxy/_experimental/mcp_server/server.py": { - "baseline": 971, - "slack": 486 - }, - "litellm/proxy/_experimental/mcp_server/sse_transport.py": { - "baseline": 61, - "slack": 31 - }, - "litellm/proxy/_experimental/mcp_server/tool_registry.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/proxy/_experimental/mcp_server/toolset_db.py": { - "baseline": 46, - "slack": 23 - }, - "litellm/proxy/_experimental/mcp_server/ui_session_utils.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/proxy/_experimental/mcp_server/utils.py": { - "baseline": 99, - "slack": 50 - }, - "litellm/proxy/_lazy_features.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/proxy/_lazy_openapi_snapshot.py": { - "baseline": 72, - "slack": 36 - }, - "litellm/proxy/_logging.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/proxy/_types.py": { - "baseline": 848, - "slack": 424 - }, - "litellm/proxy/a2a/agent_card.py": { - "baseline": 51, - "slack": 26 - }, - "litellm/proxy/a2a/discovery.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/proxy/a2a/endpoints.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/proxy/agent_endpoints/a2a_endpoints.py": { - "baseline": 333, - "slack": 167 - }, - "litellm/proxy/agent_endpoints/a2a_routing.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/proxy/agent_endpoints/agent_registry.py": { - "baseline": 143, - "slack": 72 - }, - "litellm/proxy/agent_endpoints/auth/agent_permission_handler.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/proxy/agent_endpoints/databricks_oauth.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/proxy/agent_endpoints/endpoints.py": { - "baseline": 222, - "slack": 111 - }, - "litellm/proxy/agent_endpoints/model_list_helpers.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/proxy/analytics_endpoints/analytics_endpoints.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/proxy/anthropic_endpoints/claude_code_endpoints/claude_code_marketplace.py": { - "baseline": 225, - "slack": 113 - }, - "litellm/proxy/anthropic_endpoints/endpoints.py": { - "baseline": 77, - "slack": 39 - }, - "litellm/proxy/anthropic_endpoints/skills_endpoints.py": { - "baseline": 106, - "slack": 53 - }, - "litellm/proxy/auth/auth_checks.py": { - "baseline": 654, - "slack": 327 - }, - "litellm/proxy/auth/auth_checks_organization.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/proxy/auth/auth_exception_handler.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/proxy/auth/auth_utils.py": { - "baseline": 276, - "slack": 138 - }, - "litellm/proxy/auth/handle_jwt.py": { - "baseline": 378, - "slack": 189 - }, - "litellm/proxy/auth/ip_address_utils.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/proxy/auth/litellm_license.py": { - "baseline": 63, - "slack": 32 - }, - "litellm/proxy/auth/login_utils.py": { - "baseline": 40, - "slack": 20 - }, - "litellm/proxy/auth/model_checks.py": { - "baseline": 52, - "slack": 26 - }, - "litellm/proxy/auth/oauth2_check.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/proxy/auth/oauth2_proxy_hook.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/proxy/auth/rds_iam_token.py": { - "baseline": 45, - "slack": 23 - }, - "litellm/proxy/auth/route_checks.py": { - "baseline": 67, - "slack": 34 - }, - "litellm/proxy/auth/trusted_proxy_utils.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/proxy/auth/user_api_key_auth.py": { - "baseline": 590, - "slack": 295 - }, - "litellm/proxy/batches_endpoints/endpoints.py": { - "baseline": 344, - "slack": 172 - }, - "litellm/proxy/caching_routes.py": { - "baseline": 105, - "slack": 53 - }, - "litellm/proxy/client/chat.py": { - "baseline": 31, - "slack": 16 - }, - "litellm/proxy/client/cli/commands/agents.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/proxy/client/cli/commands/auth.py": { - "baseline": 236, - "slack": 118 - }, - "litellm/proxy/client/cli/commands/chat.py": { - "baseline": 101, - "slack": 51 - }, - "litellm/proxy/client/cli/commands/credentials.py": { - "baseline": 39, - "slack": 20 - }, - "litellm/proxy/client/cli/commands/http.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/proxy/client/cli/commands/keys.py": { - "baseline": 100, - "slack": 50 - }, - "litellm/proxy/client/cli/commands/models.py": { - "baseline": 151, - "slack": 76 - }, - "litellm/proxy/client/cli/commands/teams.py": { - "baseline": 66, - "slack": 33 - }, - "litellm/proxy/client/cli/commands/users.py": { - "baseline": 41, - "slack": 21 - }, - "litellm/proxy/client/cli/interface.py": { - "baseline": 95, - "slack": 48 - }, - "litellm/proxy/client/cli/main.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/proxy/client/credentials.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/proxy/client/health.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/proxy/client/http_client.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/proxy/client/keys.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/proxy/client/model_groups.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/proxy/client/models.py": { - "baseline": 33, - "slack": 17 - }, - "litellm/proxy/client/teams.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/proxy/client/users.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/proxy/common_request_processing.py": { - "baseline": 753, - "slack": 377 - }, - "litellm/proxy/common_utils/admin_ui_utils.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/proxy/common_utils/banner.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/proxy/common_utils/cache_coordinator.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/proxy/common_utils/cache_pydantic_utils.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/proxy/common_utils/callback_utils.py": { - "baseline": 255, - "slack": 128 - }, - "litellm/proxy/common_utils/custom_openapi_spec.py": { - "baseline": 119, - "slack": 60 - }, - "litellm/proxy/common_utils/debug_utils.py": { - "baseline": 366, - "slack": 183 - }, - "litellm/proxy/common_utils/encrypt_decrypt_utils.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/proxy/common_utils/expired_ui_session_key_cleanup_manager.py": { - "baseline": 39, - "slack": 20 - }, - "litellm/proxy/common_utils/get_routes.py": { - "baseline": 45, - "slack": 23 - }, - "litellm/proxy/common_utils/http_parsing_utils.py": { - "baseline": 177, - "slack": 89 - }, - "litellm/proxy/common_utils/key_rotation_manager.py": { - "baseline": 66, - "slack": 33 - }, - "litellm/proxy/common_utils/load_config_utils.py": { - "baseline": 62, - "slack": 31 - }, - "litellm/proxy/common_utils/openai_endpoint_utils.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/proxy/common_utils/openapi_schema_compat.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/proxy/common_utils/performance_utils.py": { - "baseline": 60, - "slack": 30 - }, - "litellm/proxy/common_utils/proxy_rate_limit_error.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/proxy/common_utils/proxy_state.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/proxy/common_utils/rbac_utils.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/proxy/common_utils/reset_budget_job.py": { - "baseline": 539, - "slack": 270 - }, - "litellm/proxy/common_utils/swagger_utils.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/proxy/common_utils/timezone_utils.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/proxy/common_utils/user_api_key_cache.py": { - "baseline": 50, - "slack": 25 - }, - "litellm/proxy/compliance_checks.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/proxy/config_management_endpoints/pass_through_endpoints.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/proxy/container_endpoints/endpoints.py": { - "baseline": 85, - "slack": 43 - }, - "litellm/proxy/container_endpoints/handler_factory.py": { - "baseline": 120, - "slack": 60 - }, - "litellm/proxy/container_endpoints/ownership.py": { - "baseline": 167, - "slack": 84 - }, - "litellm/proxy/credential_endpoints/endpoints.py": { - "baseline": 118, - "slack": 59 - }, - "litellm/proxy/custom_hooks/custom_ui_sso_hook.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/proxy/custom_prompt_management.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/proxy/custom_sso.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/proxy/db/check_migration.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/proxy/db/create_views.py": { - "baseline": 43, - "slack": 22 - }, - "litellm/proxy/db/db_spend_update_writer.py": { - "baseline": 347, - "slack": 174 - }, - "litellm/proxy/db/db_transaction_queue/base_update_queue.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/proxy/db/db_transaction_queue/daily_spend_update_queue.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/proxy/db/db_transaction_queue/pod_lock_manager.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/proxy/db/db_transaction_queue/redis_update_buffer.py": { - "baseline": 140, - "slack": 70 - }, - "litellm/proxy/db/db_transaction_queue/spend_log_cleanup.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/proxy/db/db_transaction_queue/spend_logs_partition_manager.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/proxy/db/db_transaction_queue/spend_update_queue.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/proxy/db/db_url_settings.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/proxy/db/dynamo_db.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/proxy/db/exception_handler.py": { - "baseline": 39, - "slack": 20 - }, - "litellm/proxy/db/log_db_metrics.py": { - "baseline": 51, - "slack": 26 - }, - "litellm/proxy/db/prisma_client.py": { - "baseline": 51, - "slack": 26 - }, - "litellm/proxy/db/routing_prisma_wrapper.py": { - "baseline": 46, - "slack": 23 - }, - "litellm/proxy/db/spend_counter_reseed.py": { - "baseline": 65, - "slack": 33 - }, - "litellm/proxy/db/spend_log_tool_index.py": { - "baseline": 83, - "slack": 42 - }, - "litellm/proxy/db/tool_registry_writer.py": { - "baseline": 145, - "slack": 73 - }, - "litellm/proxy/discovery_endpoints/ui_discovery_endpoints.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/proxy/example_config_yaml/custom_auth.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/proxy/example_config_yaml/custom_callbacks.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/proxy/example_config_yaml/custom_callbacks1.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/proxy/example_config_yaml/custom_guardrail.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/proxy/example_config_yaml/custom_handler.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/proxy/example_config_yaml/pipeline_test_guardrails.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/proxy/fine_tuning_endpoints/endpoints.py": { - "baseline": 222, - "slack": 111 - }, - "litellm/proxy/google_endpoints/agents_endpoints.py": { - "baseline": 158, - "slack": 79 - }, - "litellm/proxy/google_endpoints/endpoints.py": { - "baseline": 131, - "slack": 66 - }, - "litellm/proxy/guardrails/_content_utils.py": { - "baseline": 118, - "slack": 59 - }, - "litellm/proxy/guardrails/guardrail_endpoints.py": { - "baseline": 610, - "slack": 305 - }, - "litellm/proxy/guardrails/guardrail_helpers.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/proxy/guardrails/guardrail_hooks/aim/aim.py": { - "baseline": 139, - "slack": 70 - }, - "litellm/proxy/guardrails/guardrail_hooks/akto/akto.py": { - "baseline": 127, - "slack": 64 - }, - "litellm/proxy/guardrails/guardrail_hooks/aporia_ai/aporia_ai.py": { - "baseline": 66, - "slack": 33 - }, - "litellm/proxy/guardrails/guardrail_hooks/azure/base.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/proxy/guardrails/guardrail_hooks/azure/prompt_shield.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/proxy/guardrails/guardrail_hooks/azure/text_moderation.py": { - "baseline": 33, - "slack": 17 - }, - "litellm/proxy/guardrails/guardrail_hooks/bedrock_guardrails.py": { - "baseline": 271, - "slack": 136 - }, - "litellm/proxy/guardrails/guardrail_hooks/block_code_execution/block_code_execution.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/proxy/guardrails/guardrail_hooks/cato_networks/cato_networks.py": { - "baseline": 402, - "slack": 201 - }, - "litellm/proxy/guardrails/guardrail_hooks/cisco_ai_defense/cisco_ai_defense.py": { - "baseline": 756, - "slack": 378 - }, - "litellm/proxy/guardrails/guardrail_hooks/cisco_ai_defense/cisco_ai_defense_mcp.py": { - "baseline": 324, - "slack": 162 - }, - "litellm/proxy/guardrails/guardrail_hooks/crowdstrike_aidr/crowdstrike_aidr.py": { - "baseline": 104, - "slack": 52 - }, - "litellm/proxy/guardrails/guardrail_hooks/custom_code/custom_code_guardrail.py": { - "baseline": 68, - "slack": 34 - }, - "litellm/proxy/guardrails/guardrail_hooks/custom_code/primitives.py": { - "baseline": 102, - "slack": 51 - }, - "litellm/proxy/guardrails/guardrail_hooks/custom_code/sandbox.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/proxy/guardrails/guardrail_hooks/custom_guardrail.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/proxy/guardrails/guardrail_hooks/dynamoai/dynamoai.py": { - "baseline": 83, - "slack": 42 - }, - "litellm/proxy/guardrails/guardrail_hooks/enkryptai/enkryptai.py": { - "baseline": 79, - "slack": 40 - }, - "litellm/proxy/guardrails/guardrail_hooks/generic_guardrail_api/generic_guardrail_api.py": { - "baseline": 107, - "slack": 54 - }, - "litellm/proxy/guardrails/guardrail_hooks/grayswan/__init__.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/proxy/guardrails/guardrail_hooks/grayswan/grayswan.py": { - "baseline": 154, - "slack": 77 - }, - "litellm/proxy/guardrails/guardrail_hooks/guardrails_ai/guardrails_ai.py": { - "baseline": 59, - "slack": 30 - }, - "litellm/proxy/guardrails/guardrail_hooks/hiddenlayer/hiddenlayer.py": { - "baseline": 194, - "slack": 97 - }, - "litellm/proxy/guardrails/guardrail_hooks/ibm_guardrails/ibm_detector.py": { - "baseline": 66, - "slack": 33 - }, - "litellm/proxy/guardrails/guardrail_hooks/javelin/javelin.py": { - "baseline": 57, - "slack": 29 - }, - "litellm/proxy/guardrails/guardrail_hooks/lakera_ai.py": { - "baseline": 92, - "slack": 46 - }, - "litellm/proxy/guardrails/guardrail_hooks/lakera_ai_v2.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/proxy/guardrails/guardrail_hooks/lasso/__init__.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/proxy/guardrails/guardrail_hooks/lasso/lasso.py": { - "baseline": 373, - "slack": 187 - }, - "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/competitor_intent/airline.py": { - "baseline": 56, - "slack": 28 - }, - "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/competitor_intent/base.py": { - "baseline": 33, - "slack": 17 - }, - "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py": { - "baseline": 275, - "slack": 138 - }, - "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/guardrail_benchmarks/test_eval.py": { - "baseline": 194, - "slack": 97 - }, - "litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/patterns.py": { - "baseline": 61, - "slack": 31 - }, - "litellm/proxy/guardrails/guardrail_hooks/llm_as_a_judge/__init__.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/proxy/guardrails/guardrail_hooks/mcp_end_user_permission/mcp_end_user_permission.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/proxy/guardrails/guardrail_hooks/mcp_jwt_signer/mcp_jwt_signer.py": { - "baseline": 202, - "slack": 101 - }, - "litellm/proxy/guardrails/guardrail_hooks/mcp_security/mcp_security_guardrail.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/proxy/guardrails/guardrail_hooks/microsoft_purview/base.py": { - "baseline": 160, - "slack": 80 - }, - "litellm/proxy/guardrails/guardrail_hooks/microsoft_purview/purview_dlp.py": { - "baseline": 131, - "slack": 66 - }, - "litellm/proxy/guardrails/guardrail_hooks/model_armor/model_armor.py": { - "baseline": 196, - "slack": 98 - }, - "litellm/proxy/guardrails/guardrail_hooks/noma/noma.py": { - "baseline": 202, - "slack": 101 - }, - "litellm/proxy/guardrails/guardrail_hooks/noma/noma_v2.py": { - "baseline": 69, - "slack": 35 - }, - "litellm/proxy/guardrails/guardrail_hooks/onyx/onyx.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/proxy/guardrails/guardrail_hooks/openai/moderations.py": { - "baseline": 48, - "slack": 24 - }, - "litellm/proxy/guardrails/guardrail_hooks/ovalix/ovalix.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/proxy/guardrails/guardrail_hooks/pangea/pangea.py": { - "baseline": 83, - "slack": 42 - }, - "litellm/proxy/guardrails/guardrail_hooks/panw_prisma_airs/__init__.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/proxy/guardrails/guardrail_hooks/panw_prisma_airs/panw_prisma_airs.py": { - "baseline": 656, - "slack": 328 - }, - "litellm/proxy/guardrails/guardrail_hooks/pillar/pillar.py": { - "baseline": 181, - "slack": 91 - }, - "litellm/proxy/guardrails/guardrail_hooks/presidio.py": { - "baseline": 462, - "slack": 231 - }, - "litellm/proxy/guardrails/guardrail_hooks/prompt_security/prompt_security.py": { - "baseline": 259, - "slack": 130 - }, - "litellm/proxy/guardrails/guardrail_hooks/promptguard/promptguard.py": { - "baseline": 41, - "slack": 21 - }, - "litellm/proxy/guardrails/guardrail_hooks/qohash/qohash.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/proxy/guardrails/guardrail_hooks/qualifire/qualifire.py": { - "baseline": 127, - "slack": 64 - }, - "litellm/proxy/guardrails/guardrail_hooks/semantic_guard/route_loader.py": { - "baseline": 40, - "slack": 20 - }, - "litellm/proxy/guardrails/guardrail_hooks/semantic_guard/semantic_guard.py": { - "baseline": 70, - "slack": 35 - }, - "litellm/proxy/guardrails/guardrail_hooks/tool_permission.py": { - "baseline": 210, - "slack": 105 - }, - "litellm/proxy/guardrails/guardrail_hooks/tool_policy/tool_policy_guardrail.py": { - "baseline": 73, - "slack": 37 - }, - "litellm/proxy/guardrails/guardrail_hooks/unified_guardrail/unified_guardrail.py": { - "baseline": 144, - "slack": 72 - }, - "litellm/proxy/guardrails/guardrail_hooks/vigil_guard/vigil_guard.py": { - "baseline": 118, - "slack": 59 - }, - "litellm/proxy/guardrails/guardrail_hooks/xecguard/xecguard.py": { - "baseline": 221, - "slack": 111 - }, - "litellm/proxy/guardrails/guardrail_hooks/zscaler_ai_guard/zscaler_ai_guard.py": { - "baseline": 194, - "slack": 97 - }, - "litellm/proxy/guardrails/guardrail_initializers.py": { - "baseline": 77, - "slack": 39 - }, - "litellm/proxy/guardrails/guardrail_registry.py": { - "baseline": 228, - "slack": 114 - }, - "litellm/proxy/guardrails/init_guardrails.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/proxy/guardrails/tool_name_extraction.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/proxy/guardrails/usage_endpoints.py": { - "baseline": 454, - "slack": 227 - }, - "litellm/proxy/guardrails/usage_tracking.py": { - "baseline": 85, - "slack": 43 - }, - "litellm/proxy/health_check.py": { - "baseline": 302, - "slack": 151 - }, - "litellm/proxy/health_check_utils/shared_health_check_manager.py": { - "baseline": 85, - "slack": 43 - }, - "litellm/proxy/health_endpoints/_health_endpoints.py": { - "baseline": 686, - "slack": 343 - }, - "litellm/proxy/hooks/azure_content_safety.py": { - "baseline": 86, - "slack": 43 - }, - "litellm/proxy/hooks/batch_rate_limiter.py": { - "baseline": 111, - "slack": 56 - }, - "litellm/proxy/hooks/batch_redis_get.py": { - "baseline": 50, - "slack": 25 - }, - "litellm/proxy/hooks/cache_control_check.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/proxy/hooks/dynamic_rate_limiter.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/proxy/hooks/dynamic_rate_limiter_v3.py": { - "baseline": 112, - "slack": 56 - }, - "litellm/proxy/hooks/key_management_event_hooks.py": { - "baseline": 114, - "slack": 57 - }, - "litellm/proxy/hooks/litellm_skills/main.py": { - "baseline": 389, - "slack": 195 - }, - "litellm/proxy/hooks/max_budget_limiter.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/proxy/hooks/max_budget_per_session_limiter.py": { - "baseline": 73, - "slack": 37 - }, - "litellm/proxy/hooks/max_iterations_limiter.py": { - "baseline": 37, - "slack": 19 - }, - "litellm/proxy/hooks/mcp_semantic_filter/hook.py": { - "baseline": 105, - "slack": 53 - }, - "litellm/proxy/hooks/model_max_budget_limiter.py": { - "baseline": 115, - "slack": 58 - }, - "litellm/proxy/hooks/parallel_request_limiter.py": { - "baseline": 417, - "slack": 209 - }, - "litellm/proxy/hooks/parallel_request_limiter_v3.py": { - "baseline": 630, - "slack": 315 - }, - "litellm/proxy/hooks/prompt_injection_detection.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/proxy/hooks/proxy_track_cost_callback.py": { - "baseline": 204, - "slack": 102 - }, - "litellm/proxy/hooks/rate_limiter_utils.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/proxy/hooks/responses_id_security.py": { - "baseline": 57, - "slack": 29 - }, - "litellm/proxy/hooks/sensitive_data_routing.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/proxy/hooks/user_management_event_hooks.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/proxy/image_endpoints/endpoints.py": { - "baseline": 125, - "slack": 63 - }, - "litellm/proxy/lambda.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/proxy/litellm_pre_call_utils.py": { - "baseline": 912, - "slack": 456 - }, - "litellm/proxy/management_endpoints/access_group_endpoints.py": { - "baseline": 277, - "slack": 139 - }, - "litellm/proxy/management_endpoints/budget_management_endpoints.py": { - "baseline": 70, - "slack": 35 - }, - "litellm/proxy/management_endpoints/cache_settings_endpoints.py": { - "baseline": 154, - "slack": 77 - }, - "litellm/proxy/management_endpoints/callback_management_endpoints.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/proxy/management_endpoints/common_daily_activity.py": { - "baseline": 446, - "slack": 223 - }, - "litellm/proxy/management_endpoints/common_utils.py": { - "baseline": 147, - "slack": 74 - }, - "litellm/proxy/management_endpoints/compliance_endpoints.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/proxy/management_endpoints/config_override_endpoints.py": { - "baseline": 165, - "slack": 83 - }, - "litellm/proxy/management_endpoints/cost_tracking_settings.py": { - "baseline": 104, - "slack": 52 - }, - "litellm/proxy/management_endpoints/customer_endpoints.py": { - "baseline": 198, - "slack": 99 - }, - "litellm/proxy/management_endpoints/fallback_management_endpoints.py": { - "baseline": 50, - "slack": 25 - }, - "litellm/proxy/management_endpoints/internal_user_endpoints.py": { - "baseline": 720, - "slack": 360 - }, - "litellm/proxy/management_endpoints/jwt_key_mapping_endpoints.py": { - "baseline": 83, - "slack": 42 - }, - "litellm/proxy/management_endpoints/key_management_endpoints.py": { - "baseline": 1565, - "slack": 783 - }, - "litellm/proxy/management_endpoints/mcp_management_endpoints.py": { - "baseline": 625, - "slack": 313 - }, - "litellm/proxy/management_endpoints/model_access_group_management_endpoints.py": { - "baseline": 163, - "slack": 82 - }, - "litellm/proxy/management_endpoints/model_management_endpoints.py": { - "baseline": 389, - "slack": 195 - }, - "litellm/proxy/management_endpoints/organization_endpoints.py": { - "baseline": 322, - "slack": 161 - }, - "litellm/proxy/management_endpoints/policy_endpoints/ai_policy_suggester.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/proxy/management_endpoints/policy_endpoints/endpoints.py": { - "baseline": 286, - "slack": 143 - }, - "litellm/proxy/management_endpoints/router_settings_endpoints.py": { - "baseline": 37, - "slack": 19 - }, - "litellm/proxy/management_endpoints/scim/scim_transformations.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/proxy/management_endpoints/scim/scim_v2.py": { - "baseline": 640, - "slack": 320 - }, - "litellm/proxy/management_endpoints/sso/custom_microsoft_sso.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/proxy/management_endpoints/sso_helper_utils.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/proxy/management_endpoints/tag_management_endpoints.py": { - "baseline": 207, - "slack": 104 - }, - "litellm/proxy/management_endpoints/team_callback_endpoints.py": { - "baseline": 127, - "slack": 64 - }, - "litellm/proxy/management_endpoints/team_endpoints.py": { - "baseline": 1236, - "slack": 618 - }, - "litellm/proxy/management_endpoints/tool_management_endpoints.py": { - "baseline": 172, - "slack": 86 - }, - "litellm/proxy/management_endpoints/types.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/proxy/management_endpoints/ui_sso.py": { - "baseline": 1009, - "slack": 505 - }, - "litellm/proxy/management_endpoints/usage_endpoints/ai_usage_chat.py": { - "baseline": 163, - "slack": 82 - }, - "litellm/proxy/management_endpoints/usage_endpoints/endpoints.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/proxy/management_endpoints/user_agent_analytics_endpoints.py": { - "baseline": 176, - "slack": 88 - }, - "litellm/proxy/management_endpoints/workflow_management_endpoints.py": { - "baseline": 147, - "slack": 74 - }, - "litellm/proxy/management_helpers/audit_logs.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/proxy/management_helpers/object_permission_utils.py": { - "baseline": 145, - "slack": 73 - }, - "litellm/proxy/management_helpers/team_member_permission_checks.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/proxy/management_helpers/user_invitation.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/proxy/management_helpers/utils.py": { - "baseline": 277, - "slack": 139 - }, - "litellm/proxy/mcp_tools.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/proxy/memory/memory_endpoints.py": { - "baseline": 178, - "slack": 89 - }, - "litellm/proxy/middleware/in_flight_requests_middleware.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/proxy/middleware/prometheus_auth_middleware.py": { - "baseline": 26, - "slack": 13 - }, - "litellm/proxy/middleware/request_size_limit_middleware.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/proxy/ocr_endpoints/endpoints.py": { - "baseline": 50, - "slack": 25 - }, - "litellm/proxy/openai_evals_endpoints/endpoints.py": { - "baseline": 265, - "slack": 133 - }, - "litellm/proxy/openai_files_endpoints/common_utils.py": { - "baseline": 206, - "slack": 103 - }, - "litellm/proxy/openai_files_endpoints/file_content_streaming_handler.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/proxy/openai_files_endpoints/files_endpoints.py": { - "baseline": 427, - "slack": 214 - }, - "litellm/proxy/openai_files_endpoints/storage_backend_service.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/proxy/pass_through_endpoints/jsonpath_extractor.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/proxy/pass_through_endpoints/llm_passthrough_endpoints.py": { - "baseline": 375, - "slack": 188 - }, - "litellm/proxy/pass_through_endpoints/llm_provider_handlers/anthropic_passthrough_logging_handler.py": { - "baseline": 164, - "slack": 82 - }, - "litellm/proxy/pass_through_endpoints/llm_provider_handlers/assembly_passthrough_logging_handler.py": { - "baseline": 45, - "slack": 23 - }, - "litellm/proxy/pass_through_endpoints/llm_provider_handlers/base_passthrough_logging_handler.py": { - "baseline": 32, - "slack": 16 - }, - "litellm/proxy/pass_through_endpoints/llm_provider_handlers/cohere_passthrough_logging_handler.py": { - "baseline": 39, - "slack": 20 - }, - "litellm/proxy/pass_through_endpoints/llm_provider_handlers/cursor_passthrough_logging_handler.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/proxy/pass_through_endpoints/llm_provider_handlers/gemini_passthrough_logging_handler.py": { - "baseline": 43, - "slack": 22 - }, - "litellm/proxy/pass_through_endpoints/llm_provider_handlers/openai_passthrough_logging_handler.py": { - "baseline": 114, - "slack": 57 - }, - "litellm/proxy/pass_through_endpoints/llm_provider_handlers/vertex_ai_live_passthrough_logging_handler.py": { - "baseline": 141, - "slack": 71 - }, - "litellm/proxy/pass_through_endpoints/llm_provider_handlers/vertex_passthrough_logging_handler.py": { - "baseline": 163, - "slack": 82 - }, - "litellm/proxy/pass_through_endpoints/managed_id_codec.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/proxy/pass_through_endpoints/managed_id_rewriter.py": { - "baseline": 312, - "slack": 156 - }, - "litellm/proxy/pass_through_endpoints/pass_through_endpoints.py": { - "baseline": 937, - "slack": 469 - }, - "litellm/proxy/pass_through_endpoints/passthrough_endpoint_router.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/proxy/pass_through_endpoints/passthrough_guardrails.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/proxy/pass_through_endpoints/streaming_handler.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/proxy/pass_through_endpoints/success_handler.py": { - "baseline": 113, - "slack": 57 - }, - "litellm/proxy/policy_engine/attachment_registry.py": { - "baseline": 83, - "slack": 42 - }, - "litellm/proxy/policy_engine/init_policies.py": { - "baseline": 71, - "slack": 36 - }, - "litellm/proxy/policy_engine/pipeline_executor.py": { - "baseline": 55, - "slack": 28 - }, - "litellm/proxy/policy_engine/policy_endpoints.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/proxy/policy_engine/policy_registry.py": { - "baseline": 257, - "slack": 129 - }, - "litellm/proxy/policy_engine/policy_resolve_endpoints.py": { - "baseline": 187, - "slack": 94 - }, - "litellm/proxy/policy_engine/policy_validator.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/proxy/post_call_rules.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/proxy/prisma_migration.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/proxy/prometheus_cleanup.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/proxy/prompts/init_prompts.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/proxy/prompts/prompt_endpoints.py": { - "baseline": 181, - "slack": 91 - }, - "litellm/proxy/prompts/prompt_registry.py": { - "baseline": 70, - "slack": 35 - }, - "litellm/proxy/proxy_cli.py": { - "baseline": 308, - "slack": 154 - }, - "litellm/proxy/proxy_server.py": { - "baseline": 5145, - "slack": 2573 - }, - "litellm/proxy/public_endpoints/public_endpoints.py": { - "baseline": 165, - "slack": 83 - }, - "litellm/proxy/rag_endpoints/endpoints.py": { - "baseline": 249, - "slack": 125 - }, - "litellm/proxy/realtime_endpoints/endpoints.py": { - "baseline": 243, - "slack": 122 - }, - "litellm/proxy/rerank_endpoints/endpoints.py": { - "baseline": 53, - "slack": 27 - }, - "litellm/proxy/response_api_endpoints/endpoints.py": { - "baseline": 322, - "slack": 161 - }, - "litellm/proxy/response_polling/background_streaming.py": { - "baseline": 162, - "slack": 81 - }, - "litellm/proxy/response_polling/polling_handler.py": { - "baseline": 82, - "slack": 41 - }, - "litellm/proxy/route_llm_request.py": { - "baseline": 138, - "slack": 69 - }, - "litellm/proxy/search_endpoints/endpoints.py": { - "baseline": 59, - "slack": 30 - }, - "litellm/proxy/search_endpoints/search_tool_management.py": { - "baseline": 95, - "slack": 48 - }, - "litellm/proxy/search_endpoints/search_tool_registry.py": { - "baseline": 53, - "slack": 27 - }, - "litellm/proxy/shutdown/graceful_shutdown_manager.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/proxy/spend_tracking/budget_reservation.py": { - "baseline": 245, - "slack": 123 - }, - "litellm/proxy/spend_tracking/cloudzero_endpoints.py": { - "baseline": 121, - "slack": 61 - }, - "litellm/proxy/spend_tracking/cold_storage_handler.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/proxy/spend_tracking/spend_log_error_logger.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/proxy/spend_tracking/spend_management_endpoints.py": { - "baseline": 980, - "slack": 490 - }, - "litellm/proxy/spend_tracking/spend_tracking_utils.py": { - "baseline": 274, - "slack": 137 - }, - "litellm/proxy/spend_tracking/vantage_endpoints.py": { - "baseline": 177, - "slack": 89 - }, - "litellm/proxy/types_utils/utils.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py": { - "baseline": 481, - "slack": 241 - }, - "litellm/proxy/utils.py": { - "baseline": 1731, - "slack": 866 - }, - "litellm/proxy/vector_store_endpoints/endpoints.py": { - "baseline": 163, - "slack": 82 - }, - "litellm/proxy/vector_store_endpoints/management_endpoints.py": { - "baseline": 248, - "slack": 124 - }, - "litellm/proxy/vector_store_endpoints/utils.py": { - "baseline": 37, - "slack": 19 - }, - "litellm/proxy/vector_store_files_endpoints/endpoints.py": { - "baseline": 292, - "slack": 146 - }, - "litellm/proxy/vertex_ai_endpoints/langfuse_endpoints.py": { - "baseline": 38, - "slack": 19 - }, - "litellm/proxy/video_endpoints/endpoints.py": { - "baseline": 238, - "slack": 119 - }, - "litellm/proxy/video_endpoints/utils.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/proxy_auth/credentials.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/rag/__init__.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/rag/ingestion/base_ingestion.py": { - "baseline": 64, - "slack": 32 - }, - "litellm/rag/ingestion/bedrock_ingestion.py": { - "baseline": 273, - "slack": 137 - }, - "litellm/rag/ingestion/file_parsers/pdf_parser.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/rag/ingestion/gemini_ingestion.py": { - "baseline": 64, - "slack": 32 - }, - "litellm/rag/ingestion/openai_ingestion.py": { - "baseline": 31, - "slack": 16 - }, - "litellm/rag/ingestion/s3_vectors_ingestion.py": { - "baseline": 252, - "slack": 126 - }, - "litellm/rag/ingestion/vertex_ai_ingestion.py": { - "baseline": 134, - "slack": 67 - }, - "litellm/rag/main.py": { - "baseline": 108, - "slack": 54 - }, - "litellm/rag/rag_query.py": { - "baseline": 51, - "slack": 26 - }, - "litellm/realtime_api/main.py": { - "baseline": 165, - "slack": 83 - }, - "litellm/repositories/base_repository.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/repositories/budget_repository.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/repositories/config_repository.py": { - "baseline": 94, - "slack": 47 - }, - "litellm/repositories/credentials_repository.py": { - "baseline": 28, - "slack": 14 - }, - "litellm/repositories/model_repository.py": { - "baseline": 77, - "slack": 39 - }, - "litellm/repositories/object_permission_repository.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/repositories/organization_repository.py": { - "baseline": 28, - "slack": 14 - }, - "litellm/repositories/project_repository.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/repositories/table_repositories.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/repositories/team_repository.py": { - "baseline": 163, - "slack": 82 - }, - "litellm/repositories/user_repository.py": { - "baseline": 81, - "slack": 41 - }, - "litellm/repositories/verification_token_repository.py": { - "baseline": 116, - "slack": 58 - }, - "litellm/rerank_api/main.py": { - "baseline": 129, - "slack": 65 - }, - "litellm/rerank_api/rerank_utils.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/responses/file_search/emulated_handler.py": { - "baseline": 280, - "slack": 140 - }, - "litellm/responses/litellm_completion_transformation/handler.py": { - "baseline": 28, - "slack": 14 - }, - "litellm/responses/litellm_completion_transformation/session_handler.py": { - "baseline": 43, - "slack": 22 - }, - "litellm/responses/litellm_completion_transformation/streaming_iterator.py": { - "baseline": 152, - "slack": 76 - }, - "litellm/responses/litellm_completion_transformation/transformation.py": { - "baseline": 555, - "slack": 278 - }, - "litellm/responses/main.py": { - "baseline": 567, - "slack": 284 - }, - "litellm/responses/mcp/chat_completions_handler.py": { - "baseline": 367, - "slack": 184 - }, - "litellm/responses/mcp/litellm_proxy_mcp_handler.py": { - "baseline": 454, - "slack": 227 - }, - "litellm/responses/mcp/mcp_streaming_iterator.py": { - "baseline": 202, - "slack": 101 - }, - "litellm/responses/sse_output_recovery.py": { - "baseline": 48, - "slack": 24 - }, - "litellm/responses/streaming_iterator.py": { - "baseline": 990, - "slack": 495 - }, - "litellm/responses/utils.py": { - "baseline": 295, - "slack": 148 - }, - "litellm/router.py": { - "baseline": 4343, - "slack": 2172 - }, - "litellm/router_strategy/adaptive_router/adaptive_router.py": { - "baseline": 48, - "slack": 24 - }, - "litellm/router_strategy/adaptive_router/bandit.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/router_strategy/adaptive_router/hooks.py": { - "baseline": 143, - "slack": 72 - }, - "litellm/router_strategy/adaptive_router/signals.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/router_strategy/adaptive_router/update_queue.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/router_strategy/auto_router/auto_router.py": { - "baseline": 44, - "slack": 22 - }, - "litellm/router_strategy/auto_router/litellm_encoder.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/router_strategy/base_routing_strategy.py": { - "baseline": 114, - "slack": 57 - }, - "litellm/router_strategy/budget_limiter.py": { - "baseline": 347, - "slack": 174 - }, - "litellm/router_strategy/complexity_router/complexity_router.py": { - "baseline": 59, - "slack": 30 - }, - "litellm/router_strategy/complexity_router/evals/eval_complexity_router.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/router_strategy/least_busy.py": { - "baseline": 155, - "slack": 78 - }, - "litellm/router_strategy/lowest_cost.py": { - "baseline": 211, - "slack": 106 - }, - "litellm/router_strategy/lowest_latency.py": { - "baseline": 404, - "slack": 202 - }, - "litellm/router_strategy/lowest_tpm_rpm.py": { - "baseline": 168, - "slack": 84 - }, - "litellm/router_strategy/lowest_tpm_rpm_v2.py": { - "baseline": 351, - "slack": 176 - }, - "litellm/router_strategy/quality_router/config.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/router_strategy/quality_router/quality_router.py": { - "baseline": 76, - "slack": 38 - }, - "litellm/router_strategy/simple_shuffle.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/router_strategy/tag_based_routing.py": { - "baseline": 80, - "slack": 40 - }, - "litellm/router_utils/add_retry_fallback_headers.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/router_utils/batch_utils.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/router_utils/client_initalization_utils.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/router_utils/clientside_credential_handler.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/router_utils/common_utils.py": { - "baseline": 63, - "slack": 32 - }, - "litellm/router_utils/cooldown_cache.py": { - "baseline": 42, - "slack": 21 - }, - "litellm/router_utils/cooldown_callbacks.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/router_utils/cooldown_handlers.py": { - "baseline": 26, - "slack": 13 - }, - "litellm/router_utils/fallback_event_handlers.py": { - "baseline": 56, - "slack": 28 - }, - "litellm/router_utils/get_retry_from_policy.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/router_utils/handle_error.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/router_utils/health_state_cache.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/router_utils/pattern_match_deployments.py": { - "baseline": 41, - "slack": 21 - }, - "litellm/router_utils/pre_call_checks/deployment_affinity_check.py": { - "baseline": 112, - "slack": 56 - }, - "litellm/router_utils/pre_call_checks/encrypted_content_affinity_check.py": { - "baseline": 86, - "slack": 43 - }, - "litellm/router_utils/pre_call_checks/model_rate_limit_check.py": { - "baseline": 134, - "slack": 67 - }, - "litellm/router_utils/pre_call_checks/prompt_caching_deployment_check.py": { - "baseline": 35, - "slack": 18 - }, - "litellm/router_utils/pre_call_checks/responses_api_deployment_check.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/router_utils/prompt_caching_cache.py": { - "baseline": 44, - "slack": 22 - }, - "litellm/router_utils/router_callbacks/track_deployment_metrics.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/router_utils/search_api_router.py": { - "baseline": 61, - "slack": 31 - }, - "litellm/scheduler.py": { - "baseline": 54, - "slack": 27 - }, - "litellm/search/cost_calculator.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/search/main.py": { - "baseline": 57, - "slack": 29 - }, - "litellm/secret_managers/aws_secret_manager.py": { - "baseline": 28, - "slack": 14 - }, - "litellm/secret_managers/aws_secret_manager_v2.py": { - "baseline": 132, - "slack": 66 - }, - "litellm/secret_managers/base_secret_manager.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/secret_managers/custom_secret_manager_loader.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/secret_managers/cyberark_secret_manager.py": { - "baseline": 84, - "slack": 42 - }, - "litellm/secret_managers/get_azure_ad_token_provider.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/secret_managers/google_kms.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/secret_managers/google_secret_manager.py": { - "baseline": 18, - "slack": 9 - }, - "litellm/secret_managers/hashicorp_secret_manager.py": { - "baseline": 220, - "slack": 110 - }, - "litellm/secret_managers/main.py": { - "baseline": 37, - "slack": 19 - }, - "litellm/secret_managers/secret_manager_handler.py": { - "baseline": 45, - "slack": 23 - }, - "litellm/setup_wizard.py": { - "baseline": 109, - "slack": 55 - }, - "litellm/skills/main.py": { - "baseline": 215, - "slack": 108 - }, - "litellm/timeout.py": { - "baseline": 70, - "slack": 35 - }, - "litellm/types/access_group.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/types/adapter.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/types/agents.py": { - "baseline": 117, - "slack": 59 - }, - "litellm/types/caching.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/types/completion.py": { - "baseline": 33, - "slack": 17 - }, - "litellm/types/compression.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/types/containers/main.py": { - "baseline": 96, - "slack": 48 - }, - "litellm/types/embedding.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/types/files.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/types/google_genai/main.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/types/guardrails.py": { - "baseline": 81, - "slack": 41 - }, - "litellm/types/images/main.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/types/integrations/anthropic_cache_control_hook.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/types/integrations/argilla.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/types/integrations/arize.py": { - "baseline": 4, - "slack": 2 - }, - "litellm/types/integrations/arize_phoenix.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/types/integrations/base_health_check.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/types/integrations/compression_interception.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/types/integrations/custom_logger.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/types/integrations/datadog.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/types/integrations/datadog_cost_management.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/types/integrations/datadog_llm_obs.py": { - "baseline": 39, - "slack": 20 - }, - "litellm/types/integrations/datadog_metrics.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/types/integrations/gcs_bucket.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/types/integrations/langfuse.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/types/integrations/langfuse_otel.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/types/integrations/langsmith.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/types/integrations/pagerduty.py": { - "baseline": 31, - "slack": 16 - }, - "litellm/types/integrations/posthog.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/types/integrations/prometheus.py": { - "baseline": 60, - "slack": 30 - }, - "litellm/types/integrations/rag/bedrock_knowledgebase.py": { - "baseline": 47, - "slack": 24 - }, - "litellm/types/integrations/s3_v2.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/types/integrations/slack_alerting.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/types/integrations/websearch_interception.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/types/interactions/generated.py": { - "baseline": 77, - "slack": 39 - }, - "litellm/types/litellm_core_utils/streaming_chunk_builder_utils.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/types/llms/aiml.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/types/llms/anthropic.py": { - "baseline": 258, - "slack": 129 - }, - "litellm/types/llms/anthropic_messages/anthropic_response.py": { - "baseline": 26, - "slack": 13 - }, - "litellm/types/llms/anthropic_skills.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/types/llms/azure_ai.py": { - "baseline": 7, - "slack": 4 - }, - "litellm/types/llms/base.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/types/llms/bedrock.py": { - "baseline": 402, - "slack": 201 - }, - "litellm/types/llms/bedrock_agentcore.py": { - "baseline": 28, - "slack": 14 - }, - "litellm/types/llms/bedrock_invoke_agents.py": { - "baseline": 46, - "slack": 23 - }, - "litellm/types/llms/cohere.py": { - "baseline": 46, - "slack": 23 - }, - "litellm/types/llms/custom_http.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/types/llms/custom_llm.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/types/llms/databricks.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/types/llms/gemini.py": { - "baseline": 64, - "slack": 32 - }, - "litellm/types/llms/langgraph.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/types/llms/mistral.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/types/llms/oci.py": { - "baseline": 62, - "slack": 31 - }, - "litellm/types/llms/ollama.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/types/llms/openai.py": { - "baseline": 750, - "slack": 375 - }, - "litellm/types/llms/openai_evals.py": { - "baseline": 68, - "slack": 34 - }, - "litellm/types/llms/openrouter.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/types/llms/recraft.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/types/llms/rerank.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/types/llms/stability.py": { - "baseline": 60, - "slack": 30 - }, - "litellm/types/llms/vertex_ai.py": { - "baseline": 347, - "slack": 174 - }, - "litellm/types/llms/vertex_ai_text_to_speech.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/types/llms/watsonx.py": { - "baseline": 14, - "slack": 7 - }, - "litellm/types/llms/xai.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/types/management_endpoints/cache_settings_endpoints.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/types/management_endpoints/router_settings_endpoints.py": { - "baseline": 23, - "slack": 12 - }, - "litellm/types/mcp.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/types/mcp_server/mcp_server_manager.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/types/mcp_server/mcp_toolset.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/types/mcp_server/tool_registry.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/types/memory_management.py": { - "baseline": 9, - "slack": 5 - }, - "litellm/types/passthrough_endpoints/pass_through_endpoints.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/types/prompts/init_prompts.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/types/proxy/claude_code_endpoints.py": { - "baseline": 25, - "slack": 13 - }, - "litellm/types/proxy/cloudzero_endpoints.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/types/proxy/compliance_endpoints.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/types/proxy/control_plane_endpoints.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/types/proxy/discovery_endpoints/ui_discovery_endpoints.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/azure/azure_prompt_shield.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/azure/azure_text_moderation.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/base.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/bedrock_guardrails.py": { - "baseline": 60, - "slack": 30 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/block_code_execution.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/cisco_ai_defense.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/dynamoai.py": { - "baseline": 31, - "slack": 16 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/enkryptai.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/generic_guardrail_api.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/ibm/ibm_detector.py": { - "baseline": 15, - "slack": 8 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/javelin.py": { - "baseline": 34, - "slack": 17 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/lakera_ai_v2.py": { - "baseline": 24, - "slack": 12 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/litellm_content_filter.py": { - "baseline": 36, - "slack": 18 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/presidio.py": { - "baseline": 10, - "slack": 5 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/tool_permission.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/types/proxy/guardrails/guardrail_hooks/xecguard.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/types/proxy/litellm_pre_call_utils.py": { - "baseline": 2, - "slack": 1 - }, - "litellm/types/proxy/management_endpoints/common_daily_activity.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/types/proxy/management_endpoints/config_overrides.py": { - "baseline": 3, - "slack": 2 - }, - "litellm/types/proxy/management_endpoints/internal_user_endpoints.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/types/proxy/management_endpoints/key_management_endpoints.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/types/proxy/management_endpoints/model_management_endpoints.py": { - "baseline": 11, - "slack": 6 - }, - "litellm/types/proxy/management_endpoints/scim_v2.py": { - "baseline": 45, - "slack": 23 - }, - "litellm/types/proxy/management_endpoints/team_endpoints.py": { - "baseline": 20, - "slack": 10 - }, - "litellm/types/proxy/management_endpoints/ui_sso.py": { - "baseline": 16, - "slack": 8 - }, - "litellm/types/proxy/policy_engine/pipeline_types.py": { - "baseline": 8, - "slack": 4 - }, - "litellm/types/proxy/policy_engine/policy_types.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/types/proxy/policy_engine/resolver_types.py": { - "baseline": 30, - "slack": 15 - }, - "litellm/types/proxy/policy_engine/validation_types.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/types/proxy/prompt_endpoints.py": { - "baseline": 1, - "slack": 1 - }, - "litellm/types/proxy/public_endpoints/public_endpoints.py": { - "baseline": 22, - "slack": 11 - }, - "litellm/types/proxy/ui_sso.py": { - "baseline": 12, - "slack": 6 - }, - "litellm/types/proxy/vantage_endpoints.py": { - "baseline": 6, - "slack": 3 - }, - "litellm/types/rag.py": { - "baseline": 78, - "slack": 39 - }, - "litellm/types/realtime.py": { - "baseline": 28, - "slack": 14 - }, - "litellm/types/rerank.py": { - "baseline": 29, - "slack": 15 - }, - "litellm/types/responses/main.py": { - "baseline": 49, - "slack": 25 - }, - "litellm/types/router.py": { - "baseline": 194, - "slack": 97 - }, - "litellm/types/search.py": { - "baseline": 21, - "slack": 11 - }, - "litellm/types/services.py": { - "baseline": 13, - "slack": 7 - }, - "litellm/types/tag_management.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/types/tool_management.py": { - "baseline": 27, - "slack": 14 - }, - "litellm/types/utils.py": { - "baseline": 1085, - "slack": 543 - }, - "litellm/types/vector_store_files.py": { - "baseline": 38, - "slack": 19 - }, - "litellm/types/vector_stores.py": { - "baseline": 118, - "slack": 59 - }, - "litellm/types/videos/main.py": { - "baseline": 59, - "slack": 30 - }, - "litellm/types/videos/utils.py": { - "baseline": 5, - "slack": 3 - }, - "litellm/utils.py": { - "baseline": 3367, - "slack": 1684 - }, - "litellm/vector_store_files/main.py": { - "baseline": 244, - "slack": 122 - }, - "litellm/vector_store_files/utils.py": { - "baseline": 17, - "slack": 9 - }, - "litellm/vector_stores/main.py": { - "baseline": 268, - "slack": 134 - }, - "litellm/vector_stores/utils.py": { - "baseline": 19, - "slack": 10 - }, - "litellm/vector_stores/vector_store_registry.py": { - "baseline": 94, - "slack": 47 - }, - "litellm/videos/main.py": { - "baseline": 513, - "slack": 257 - }, - "litellm/videos/utils.py": { - "baseline": 54, - "slack": 27 - } -} diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index 7ece944fd0e..d241c501797 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -5455,21 +5455,19 @@ class StandardLoggingPayloadSetup: error_information = StandardLoggingPayloadSetup.get_error_information( original_exception=original_exception, ) - if not metadata.get("client_disconnected"): # any-ok: untyped metadata + if not metadata.get("client_disconnected"): return error_information, error_str - client_disconnect_error = metadata.get( # any-ok: untyped metadata - "error_information" - ) - if isinstance(client_disconnect_error, dict): # any-ok: untyped metadata + client_disconnect_error = metadata.get("error_information") + if isinstance(client_disconnect_error, dict): error_information = cast( StandardLoggingPayloadErrorInformation, - client_disconnect_error, # any-ok: untyped metadata + client_disconnect_error, ) else: error_information = cast( StandardLoggingPayloadErrorInformation, - { # any-ok: untyped metadata + { "error_code": "499", "error_message": "Client disconnected the request", "error_class": "ClientDisconnected", @@ -5808,7 +5806,7 @@ def get_standard_logging_object_payload( error_information, error_str = ( StandardLoggingPayloadSetup.get_error_information_for_logging_payload( - metadata=metadata, # any-ok: untyped metadata + metadata=metadata, original_exception=original_exception, error_str=error_str, ) diff --git a/litellm/llms/anthropic/chat/transformation.py b/litellm/llms/anthropic/chat/transformation.py index 2e18d15a5ce..c24c990f356 100644 --- a/litellm/llms/anthropic/chat/transformation.py +++ b/litellm/llms/anthropic/chat/transformation.py @@ -2215,7 +2215,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): inference_geo = _usage["inference_geo"] service_tier = cast( str | None, - _usage.get("service_tier"), # any-ok: untyped usage dict + _usage.get("service_tier"), ) iterations: Optional[List[Any]] = _usage.get("iterations") diff --git a/litellm/llms/hosted_vllm/chat/transformation.py b/litellm/llms/hosted_vllm/chat/transformation.py index 40906e83a9d..7c42e6a9a00 100644 --- a/litellm/llms/hosted_vllm/chat/transformation.py +++ b/litellm/llms/hosted_vllm/chat/transformation.py @@ -205,53 +205,40 @@ class HostedVLLMChatConfig(OpenAIGPTConfig): tool_calls: list[ChatCompletionAssistantToolCall] = [] content_blocks: list[object] = [] has_structured_content = False - for c in existing_content: # any-ok: untyped content - if ( - isinstance(c, dict) # any-ok: untyped content - and c.get("type") == "text" # any-ok: untyped content - ): - text_parts.append( # any-ok: untyped content - c.get("text", "") # any-ok: untyped content - ) - content_blocks.append(c) # any-ok: untyped content - elif ( - isinstance(c, dict) # any-ok: untyped content - and c.get("type") == "tool_use" # any-ok: untyped content - ): - tool_input = c.get("input", {}) # any-ok: untyped content + for c in existing_content: + if isinstance(c, dict) and c.get("type") == "text": + text_parts.append(c.get("text", "")) + content_blocks.append(c) + elif isinstance(c, dict) and c.get("type") == "tool_use": + tool_input = c.get("input", {}) tool_calls.append( ChatCompletionAssistantToolCall( - id=c.get("id"), # any-ok: untyped content + id=c.get("id"), type="function", function=ChatCompletionToolCallFunctionChunk( - name=c.get("name"), # any-ok: untyped content + name=c.get("name"), arguments=( tool_input if isinstance( - tool_input, # any-ok: untyped content - str, # any-ok: untyped content - ) - else json.dumps( - tool_input # any-ok: untyped content + tool_input, + str, ) + else json.dumps(tool_input) ), ), ) ) else: - content_blocks.append(c) # any-ok: untyped content + content_blocks.append(c) has_structured_content = True if tool_calls: existing_tool_calls = message.get("tool_calls") if isinstance(existing_tool_calls, list): existing_tool_call_ids = { - tool_call.get("id") # any-ok: untyped content + tool_call.get("id") for tool_call in existing_tool_calls - if isinstance( - tool_call, dict - ) # any-ok: untyped content - and tool_call.get("id") - is not None # any-ok: untyped content + if isinstance(tool_call, dict) + and tool_call.get("id") is not None } new_tool_calls = [ tool_call @@ -264,7 +251,7 @@ class HostedVLLMChatConfig(OpenAIGPTConfig): ) else: message["tool_calls"] = tool_calls - content_str = "\n".join(text_parts) # any-ok: untyped content + content_str = "\n".join(text_parts) new_content = ( content_blocks if has_structured_content else content_str ) diff --git a/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py b/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py index a2634ffaa40..c171538b9c0 100644 --- a/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py +++ b/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py @@ -2844,7 +2844,7 @@ async def make_call( sync_stream=False, logging_obj=logging_obj, response_headers=response.headers, - response=response, # any-ok: untyped stream + response=response, ) # LOGGING logging_obj.post_call( @@ -2888,7 +2888,7 @@ def make_sync_call( sync_stream=True, logging_obj=logging_obj, response_headers=response.headers, - response=response, # any-ok: untyped stream + response=response, ) # LOGGING @@ -3661,16 +3661,14 @@ class ModelResponseIterator: raise RuntimeError(f"Error parsing chunk: {e},\nReceived chunk: {chunk}") async def aclose(self) -> None: - iterator = getattr( # any-ok: untyped stream + iterator = getattr( self, "async_response_iterator", - self.streaming_response, # any-ok: untyped stream + self.streaming_response, ) - if iterator is not None and hasattr( # any-ok: untyped stream - iterator, "aclose" # any-ok: untyped stream - ): + if iterator is not None and hasattr(iterator, "aclose"): try: - await iterator.aclose() # any-ok: untyped stream + await iterator.aclose() except Exception as e: # noqa: BLE001 verbose_logger.debug( "ModelResponseIterator.aclose: error closing iterator: %s", e @@ -3684,14 +3682,10 @@ class ModelResponseIterator: ) def close(self) -> None: - iterator = getattr( # any-ok: untyped stream - self, "response_iterator", self.streaming_response # any-ok: untyped stream - ) - if iterator is not None and hasattr( # any-ok: untyped stream - iterator, "close" # any-ok: untyped stream - ): + iterator = getattr(self, "response_iterator", self.streaming_response) + if iterator is not None and hasattr(iterator, "close"): try: - iterator.close() # any-ok: untyped stream + iterator.close() except Exception as e: # noqa: BLE001 verbose_logger.debug( "ModelResponseIterator.close: error closing iterator: %s", e diff --git a/litellm/mypy.ini b/litellm/mypy.ini deleted file mode 100644 index b65e11bab42..00000000000 --- a/litellm/mypy.ini +++ /dev/null @@ -1,22 +0,0 @@ -[mypy] -warn_return_any = True -ignore_missing_imports = True -disallow_untyped_defs = True -mypy_path = litellm/stubs -namespace_packages = True -disable_error_code = - annotation-unchecked, - import-untyped - -[mypy-litellm.*] -ignore_missing_imports = False - -[mypy-google.*] -ignore_missing_imports = True - -[mypy-cryptography.hazmat.bindings._rust.x509] -ignore_errors = True - -[mypy-fastuuid.*] -ignore_missing_imports = True -ignore_errors = True \ No newline at end of file diff --git a/litellm/proxy/common_request_processing.py b/litellm/proxy/common_request_processing.py index 7cccae6e761..2a0e8402f17 100644 --- a/litellm/proxy/common_request_processing.py +++ b/litellm/proxy/common_request_processing.py @@ -110,46 +110,32 @@ async def _record_streaming_client_disconnect_if_needed( if not disconnected: return False - logging_obj = request_data.get("litellm_logging_obj") # any-ok: untyped request - if logging_obj is not None: # any-ok: untyped request - litellm_params = ( - logging_obj.model_call_details.setdefault( # any-ok: untyped request - "litellm_params", {} - ) - ) + logging_obj = request_data.get("litellm_logging_obj") + if logging_obj is not None: + litellm_params = logging_obj.model_call_details.setdefault("litellm_params", {}) + _apply_client_disconnect_metadata(litellm_params.setdefault("metadata", {})) _apply_client_disconnect_metadata( - litellm_params.setdefault("metadata", {}) # any-ok: untyped request - ) - _apply_client_disconnect_metadata( - logging_obj.model_call_details.setdefault( # any-ok: untyped request - "metadata", {} - ) + logging_obj.model_call_details.setdefault("metadata", {}) ) - _apply_client_disconnect_metadata( - request_data.setdefault("metadata", {}) # any-ok: untyped request - ) - litellm_params = request_data.setdefault( # any-ok: untyped request - "litellm_params", {} # any-ok: untyped request - ) - _apply_client_disconnect_metadata( - litellm_params.setdefault("metadata", {}) # any-ok: untyped request - ) + _apply_client_disconnect_metadata(request_data.setdefault("metadata", {})) + litellm_params = request_data.setdefault("litellm_params", {}) + _apply_client_disconnect_metadata(litellm_params.setdefault("metadata", {})) verbose_proxy_logger.debug( "Recorded streaming client disconnect with error_code=499 for litellm_call_id=%s", - request_data.get("litellm_call_id"), # any-ok: untyped request + request_data.get("litellm_call_id"), ) return True async def _cancel_pending_gather_tasks(tasks: list["asyncio.Task[Any]"]) -> None: - pending_tasks = [task for task in tasks if not task.done()] # any-ok: untyped task - for task in pending_tasks: # any-ok: untyped task - task.cancel() # any-ok: untyped task - for task in pending_tasks: # any-ok: untyped task + pending_tasks = [task for task in tasks if not task.done()] + for task in pending_tasks: + task.cancel() + for task in pending_tasks: try: - await task # any-ok: untyped request + await task except (asyncio.CancelledError, Exception): # noqa: BLE001 pass @@ -1401,24 +1387,22 @@ class ProxyBaseLLMRequestProcessing: user_model=user_model, user_api_key_dict=user_api_key_dict, ) - llm_call_task = asyncio.create_task(llm_call) # any-ok: untyped task - tasks.append(llm_call_task) # any-ok: untyped task + llm_call_task = asyncio.create_task(llm_call) + tasks.append(llm_call_task) llm_responses = asyncio.gather( *tasks ) # run the moderation check in parallel to the actual llm api call try: - if general_settings.get( # any-ok: untyped request - "cancel_on_disconnect", False - ): - responses = await _await_llm_call_cancelling_on_disconnect( # any-ok: untyped request - request, llm_responses # any-ok: untyped task + if general_settings.get("cancel_on_disconnect", False): + responses = await _await_llm_call_cancelling_on_disconnect( + request, llm_responses ) else: - responses = await llm_responses # any-ok: untyped request + responses = await llm_responses finally: - await _cancel_pending_gather_tasks(tasks) # any-ok: untyped task + await _cancel_pending_gather_tasks(tasks) response = responses[1] @@ -2477,18 +2461,16 @@ class ProxyBaseLLMRequestProcessing: recorded_client_disconnect = ( await _record_streaming_client_disconnect_if_needed( request, - request_data, # any-ok: untyped request - client_disconnected, # any-ok: untyped request + request_data, + client_disconnected, ) ) if recorded_client_disconnect: - ProxyLogging._fire_deferred_stream_logging( - request_data # any-ok: untyped request - ) + ProxyLogging._fire_deferred_stream_logging(request_data) - if hasattr(response, "aclose"): # any-ok: untyped request + if hasattr(response, "aclose"): try: - await response.aclose() # any-ok: untyped request + await response.aclose() except BaseException as e: # noqa: BLE001 verbose_proxy_logger.debug( "async_streaming_data_generator: error closing response stream: %s", @@ -2624,8 +2606,8 @@ class ProxyBaseLLMRequestProcessing: finally: await ProxyBaseLLMRequestProcessing._finalize_streaming_generator_cleanup( request=request, - request_data=request_data, # any-ok: untyped request - response=response, # any-ok: untyped request + request_data=request_data, + response=response, stream_completed=stream_completed, client_disconnected=client_disconnected, ) diff --git a/litellm/proxy/discovery_endpoints/ui_discovery_endpoints.py b/litellm/proxy/discovery_endpoints/ui_discovery_endpoints.py index 726e71e307c..0e7e67aa37f 100644 --- a/litellm/proxy/discovery_endpoints/ui_discovery_endpoints.py +++ b/litellm/proxy/discovery_endpoints/ui_discovery_endpoints.py @@ -25,15 +25,9 @@ async def get_ui_config(): or general_settings.get("auto_redirect_ui_login_to_sso", False) is True ) admin_ui_disabled = os.getenv("DISABLE_ADMIN_UI", "false").lower() == "true" - hide_default_credentials_hint = bool( # any-ok: untyped settings - os.getenv( # any-ok: untyped settings - "LITELLM_HIDE_DEFAULT_CREDENTIALS_HINT", "false" - ).lower() - == "true" - or general_settings.get( # any-ok: untyped settings - "hide_default_credentials_hint", False - ) - is True + hide_default_credentials_hint = bool( + os.getenv("LITELLM_HIDE_DEFAULT_CREDENTIALS_HINT", "false").lower() == "true" + or general_settings.get("hide_default_credentials_hint", False) is True ) sso_configured = _has_user_setup_sso() @@ -48,7 +42,7 @@ async def get_ui_config(): auto_redirect_to_sso=sso_configured and auto_redirect_ui_login_to_sso, admin_ui_disabled=admin_ui_disabled, sso_configured=sso_configured, - hide_default_credentials_hint=hide_default_credentials_hint, # any-ok: untyped settings + hide_default_credentials_hint=hide_default_credentials_hint, is_control_plane=is_control_plane, workers=proxy_config.worker_registry if is_control_plane else [], ) diff --git a/litellm/proxy/google_endpoints/endpoints.py b/litellm/proxy/google_endpoints/endpoints.py index 4234c433f22..6427835c250 100644 --- a/litellm/proxy/google_endpoints/endpoints.py +++ b/litellm/proxy/google_endpoints/endpoints.py @@ -107,7 +107,7 @@ async def google_stream_generate_content( data["stream"] = True # google-genai SDK (?alt=sse) must not receive OpenAI's data: [DONE] terminator. data["_litellm_skip_openai_stream_done"] = True - data["_litellm_raw_sse_stream"] = True # any-ok: untyped request + data["_litellm_raw_sse_stream"] = True processor = ProxyBaseLLMRequestProcessing(data=data) try: diff --git a/litellm/proxy/guardrails/guardrail_hooks/presidio.py b/litellm/proxy/guardrails/guardrail_hooks/presidio.py index 5efb5966262..a8afe4efe2a 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/presidio.py +++ b/litellm/proxy/guardrails/guardrail_hooks/presidio.py @@ -747,12 +747,12 @@ class _OPTIONAL_PresidioPIIMasking(CustomGuardrail): # to the model would carry anonymization tokens and the response would echo them. if ( self.should_run_guardrail( - data=data, # any-ok: untyped request - event_type=GuardrailEventHooks.pre_call, # any-ok: untyped request + data=data, + event_type=GuardrailEventHooks.pre_call, ) is not True ): - return data # any-ok: untyped request + return data try: content_safety = data.get("content_safety", None) diff --git a/litellm/proxy/management_endpoints/key_management_endpoints.py b/litellm/proxy/management_endpoints/key_management_endpoints.py index 6e567a428e4..d6ecc59f263 100644 --- a/litellm/proxy/management_endpoints/key_management_endpoints.py +++ b/litellm/proxy/management_endpoints/key_management_endpoints.py @@ -3239,10 +3239,8 @@ async def _get_model_max_budget_current_spend( f"{VIRTUAL_KEY_SPEND_CACHE_KEY_PREFIX}:" f"{api_key_hash}:{model}:{budget_config.budget_duration}" ) - current_spend: float | None = ( - await user_api_key_cache.async_get_cache( # any-ok: untyped dump - key=virtual_key_model_spend_cache_key, - ) + current_spend: float | None = await user_api_key_cache.async_get_cache( + key=virtual_key_model_spend_cache_key, ) if current_spend is None: model_without_prefix = model.split("/")[-1] if "/" in model else model @@ -3250,13 +3248,11 @@ async def _get_model_max_budget_current_spend( f"{VIRTUAL_KEY_SPEND_CACHE_KEY_PREFIX}:" f"{api_key_hash}:{model_without_prefix}:{budget_config.budget_duration}" ) - current_spend = ( - await user_api_key_cache.async_get_cache( # any-ok: untyped dump - key=virtual_key_model_spend_cache_key, - ) + current_spend = await user_api_key_cache.async_get_cache( + key=virtual_key_model_spend_cache_key, ) try: - return float(current_spend or 0.0) # any-ok: untyped dump + return float(current_spend or 0.0) except (TypeError, ValueError): return 0.0 @@ -3365,27 +3361,17 @@ async def info_key_fn_v2( k_dict = k.model_dump() except Exception: k_dict = k.dict() - k_token_hash = k_dict.pop("token", None) # any-ok: untyped dump + k_token_hash = k_dict.pop("token", None) - model_max_budget = ( - k_dict.get("model_max_budget") or {} # any-ok: untyped dump - ) - budget_table = ( - k_dict.get("litellm_budget_table") or {} # any-ok: untyped dump - ) - if not model_max_budget and isinstance( # any-ok: untyped dump - budget_table, dict # any-ok: untyped dump - ): - model_max_budget = ( - budget_table.get("model_max_budget") or {} # any-ok: untyped dump - ) - if model_max_budget and k_token_hash: # any-ok: untyped dump - k_dict["model_max_budget_usage"] = ( # any-ok: untyped dump - await _build_model_max_budget_usage( # any-ok: untyped dump - api_key_hash=k_token_hash, # any-ok: untyped dump - model_max_budget=model_max_budget, # any-ok: untyped dump - user_api_key_cache=user_api_key_cache, - ) + model_max_budget = k_dict.get("model_max_budget") or {} + budget_table = k_dict.get("litellm_budget_table") or {} + if not model_max_budget and isinstance(budget_table, dict): + model_max_budget = budget_table.get("model_max_budget") or {} + if model_max_budget and k_token_hash: + k_dict["model_max_budget_usage"] = await _build_model_max_budget_usage( + api_key_hash=k_token_hash, + model_max_budget=model_max_budget, + user_api_key_cache=user_api_key_cache, ) filtered_key_info.append(k_dict) @@ -3470,27 +3456,17 @@ async def info_key_fn( except Exception: # if using pydantic v1 key_info = key_info.dict() - key_token_hash = key_info.pop("token") # any-ok: untyped dump + key_token_hash = key_info.pop("token") - model_max_budget = ( - key_info.get("model_max_budget") or {} # any-ok: untyped dump - ) - budget_table = ( - key_info.get("litellm_budget_table") or {} # any-ok: untyped dump - ) - if not model_max_budget and isinstance( # any-ok: untyped dump - budget_table, dict # any-ok: untyped dump - ): - model_max_budget = ( - budget_table.get("model_max_budget") or {} # any-ok: untyped dump - ) - if model_max_budget and key_token_hash: # any-ok: untyped dump - key_info["model_max_budget_usage"] = ( # any-ok: untyped dump - await _build_model_max_budget_usage( # any-ok: untyped dump - api_key_hash=key_token_hash, # any-ok: untyped dump - model_max_budget=model_max_budget, # any-ok: untyped dump - user_api_key_cache=user_api_key_cache, - ) + model_max_budget = key_info.get("model_max_budget") or {} + budget_table = key_info.get("litellm_budget_table") or {} + if not model_max_budget and isinstance(budget_table, dict): + model_max_budget = budget_table.get("model_max_budget") or {} + if model_max_budget and key_token_hash: + key_info["model_max_budget_usage"] = await _build_model_max_budget_usage( + api_key_hash=key_token_hash, + model_max_budget=model_max_budget, + user_api_key_cache=user_api_key_cache, ) # Attach object_permission if object_permission_id is set diff --git a/litellm/proxy/management_endpoints/ui_sso.py b/litellm/proxy/management_endpoints/ui_sso.py index 91a5c109acf..427c87e0f44 100644 --- a/litellm/proxy/management_endpoints/ui_sso.py +++ b/litellm/proxy/management_endpoints/ui_sso.py @@ -194,11 +194,7 @@ def _is_valid_cli_sso_user_code(user_code: str | None) -> bool: def _cli_sso_verification_uri_complete_enabled() -> bool: from litellm.proxy.proxy_server import general_settings - return bool( - general_settings.get( # any-ok: operator opt-in read from the untyped general_settings dict - "allow_cli_sso_verification_uri_complete", False - ) - ) + return bool(general_settings.get("allow_cli_sso_verification_uri_complete", False)) def _cli_sso_start_response_body( diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 8de369efbde..7e9d2688894 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -896,7 +896,7 @@ async def proxy_startup_event(app: FastAPI): if transaction_buffer_redis_cache is None: transaction_buffer_redis_cache = ( ProxyStartupEvent._get_transaction_buffer_redis_cache( - general_settings=general_settings # any-ok: untyped stream + general_settings=general_settings ) ) @@ -7082,9 +7082,7 @@ async def async_data_generator( # happened to ship a streaming-iterator override (the default). needs_iterator_wrap = proxy_logging_obj.needs_iterator_wrap() needs_per_chunk_hook = proxy_logging_obj.needs_per_chunk_streaming_hook() - is_raw_sse_stream = bool( - request_data.get("_litellm_raw_sse_stream") # any-ok: untyped stream - ) + is_raw_sse_stream = bool(request_data.get("_litellm_raw_sse_stream")) raw_sse_buffer = "" if needs_iterator_wrap: @@ -7123,26 +7121,26 @@ async def async_data_generator( frame, raw_sse_buffer = _pop_complete_sse_frame(raw_sse_buffer) if frame is None: break - yield frame # any-ok: untyped stream + yield frame if len(raw_sse_buffer) > _MAX_RAW_SSE_BUFFER_CHARS: raise ValueError( "Raw SSE stream exceeded maximum buffered size without a frame delimiter" ) continue if chunk.startswith(("data:", "event:", ":")): - yield ( # any-ok: untyped stream + yield ( chunk if chunk.endswith(_SSE_FRAME_DELIMITERS) else chunk + "\n\n" ) continue - elif isinstance(chunk, str) and is_raw_sse_stream: # any-ok: untyped stream + elif isinstance(chunk, str) and is_raw_sse_stream: raw_sse_buffer += chunk while True: frame, raw_sse_buffer = _pop_complete_sse_frame(raw_sse_buffer) if frame is None: break - yield frame # any-ok: untyped stream + yield frame if len(raw_sse_buffer) > _MAX_RAW_SSE_BUFFER_CHARS: raise ValueError( "Raw SSE stream exceeded maximum buffered size without a frame delimiter" @@ -7165,7 +7163,7 @@ async def async_data_generator( ProxyLogging._fire_deferred_stream_logging(request_data) if raw_sse_buffer: - yield ( # any-ok: untyped stream + yield ( raw_sse_buffer if raw_sse_buffer.endswith(_SSE_FRAME_DELIMITERS) else raw_sse_buffer + "\n\n" @@ -7231,8 +7229,8 @@ async def async_data_generator( await ProxyBaseLLMRequestProcessing._finalize_streaming_generator_cleanup( request=request, - request_data=request_data, # any-ok: untyped stream - response=response, # any-ok: untyped stream + request_data=request_data, + response=response, stream_completed=stream_completed, client_disconnected=client_disconnected, ) @@ -7353,10 +7351,8 @@ class ProxyStartupEvent: from litellm._redis import _redis_kwargs_from_environment from litellm.secret_managers.main import str_to_bool - _use_redis_transaction_buffer: bool | str | None = ( - general_settings.get( # any-ok: untyped stream - "use_redis_transaction_buffer", False - ) + _use_redis_transaction_buffer: bool | str | None = general_settings.get( + "use_redis_transaction_buffer", False ) if isinstance(_use_redis_transaction_buffer, str): _use_redis_transaction_buffer = str_to_bool(_use_redis_transaction_buffer) @@ -7364,14 +7360,11 @@ class ProxyStartupEvent: if not _use_redis_transaction_buffer: return None - redis_env_kwargs = _redis_kwargs_from_environment() # any-ok: untyped stream - if ( - "host" not in redis_env_kwargs # any-ok: untyped stream - and "url" not in redis_env_kwargs # any-ok: untyped stream - ): + redis_env_kwargs = _redis_kwargs_from_environment() + if "host" not in redis_env_kwargs and "url" not in redis_env_kwargs: return None - return RedisCache(**redis_env_kwargs) # any-ok: untyped stream + return RedisCache(**redis_env_kwargs) @classmethod async def _initialize_semantic_tool_filter( diff --git a/litellm/router_utils/fallback_event_handlers.py b/litellm/router_utils/fallback_event_handlers.py index bc01a894e1d..eb756e3cf8b 100644 --- a/litellm/router_utils/fallback_event_handlers.py +++ b/litellm/router_utils/fallback_event_handlers.py @@ -244,16 +244,12 @@ def _check_non_standard_fallback_format(fallbacks: Optional[List[Any]]) -> bool: if all(isinstance(item, str) for item in fallbacks): return True elif all(isinstance(item, dict) for item in fallbacks): - for item in fallbacks: # any-ok: untyped config - for ( - key - ) in ( - LiteLLMParamsTypedDict.__annotations__.keys() # any-ok: untyped config - ): - if key in item: # any-ok: untyped config + for item in fallbacks: + for key in LiteLLMParamsTypedDict.__annotations__.keys(): + if key in item: # If the value is a list, it's likely a standard fallback model group mapping # (e.g. {"model": ["backup"]}) rather than a parameter override. - if not isinstance(item[key], list): # any-ok: untyped config + if not isinstance(item[key], list): return True return False diff --git a/litellm/secret_managers/aws_secret_manager_v2.py b/litellm/secret_managers/aws_secret_manager_v2.py index 299217f14b2..ef3c821caf1 100644 --- a/litellm/secret_managers/aws_secret_manager_v2.py +++ b/litellm/secret_managers/aws_secret_manager_v2.py @@ -321,13 +321,13 @@ class AWSSecretsManagerV2(BaseAWSLLM, BaseSecretManager): ) try: - response = await async_client.post( # any-ok: untyped httpx + response = await async_client.post( url=endpoint_url, - headers=headers, # any-ok: untyped httpx - data=body.decode("utf-8"), # any-ok: untyped httpx + headers=headers, + data=body.decode("utf-8"), ) - response.raise_for_status() # any-ok: untyped httpx - create_response = response.json() # any-ok: untyped httpx + response.raise_for_status() + create_response = response.json() except httpx.HTTPStatusError as err: raise ValueError(f"HTTP error occurred: {err.response.text}") except httpx.TimeoutException: @@ -338,7 +338,7 @@ class AWSSecretsManagerV2(BaseAWSLLM, BaseSecretManager): await self.async_replicate_secret( secret_name=secret_name, replica_regions=self.replica_regions, - optional_params=optional_params, # any-ok: untyped httpx + optional_params=optional_params, timeout=timeout, ) verbose_logger.debug( @@ -354,7 +354,7 @@ class AWSSecretsManagerV2(BaseAWSLLM, BaseSecretManager): str(replication_err), ) - return create_response # any-ok: untyped httpx + return create_response async def async_replicate_secret( self, @@ -392,7 +392,7 @@ class AWSSecretsManagerV2(BaseAWSLLM, BaseSecretManager): "AddReplicaRegions": [{"Region": r} for r in replica_regions], } - endpoint_url, headers, body = self._prepare_request( # any-ok: untyped httpx + endpoint_url, headers, body = self._prepare_request( action="ReplicateSecretToRegions", secret_name=secret_name, optional_params=optional_params, @@ -401,7 +401,7 @@ class AWSSecretsManagerV2(BaseAWSLLM, BaseSecretManager): async_client = get_async_httpx_client( llm_provider=httpxSpecialProvider.SecretManager, - params={"timeout": timeout}, # any-ok: untyped httpx + params={"timeout": timeout}, ) try: diff --git a/litellm/utils.py b/litellm/utils.py index 30b5691a140..916260cab5a 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -6043,13 +6043,13 @@ def _get_model_info_helper( cache_read_input_token_cost_above_200k_tokens=_model_info.get( "cache_read_input_token_cost_above_200k_tokens", None ), - cache_read_input_token_cost_above_200k_tokens_priority=_model_info.get( # any-ok: untyped cost map + cache_read_input_token_cost_above_200k_tokens_priority=_model_info.get( "cache_read_input_token_cost_above_200k_tokens_priority", None ), cache_read_input_token_cost_above_272k_tokens=_model_info.get( "cache_read_input_token_cost_above_272k_tokens", None ), - cache_read_input_token_cost_above_272k_tokens_priority=_model_info.get( # any-ok: untyped cost map + cache_read_input_token_cost_above_272k_tokens_priority=_model_info.get( "cache_read_input_token_cost_above_272k_tokens_priority", None ), cache_read_input_token_cost_above_512k_tokens=_model_info.get( @@ -6073,13 +6073,13 @@ def _get_model_info_helper( input_cost_per_token_above_200k_tokens=_model_info.get( "input_cost_per_token_above_200k_tokens", None ), - input_cost_per_token_above_200k_tokens_priority=_model_info.get( # any-ok: untyped cost map + input_cost_per_token_above_200k_tokens_priority=_model_info.get( "input_cost_per_token_above_200k_tokens_priority", None ), input_cost_per_token_above_272k_tokens=_model_info.get( "input_cost_per_token_above_272k_tokens", None ), - input_cost_per_token_above_272k_tokens_priority=_model_info.get( # any-ok: untyped cost map + input_cost_per_token_above_272k_tokens_priority=_model_info.get( "input_cost_per_token_above_272k_tokens_priority", None ), input_cost_per_token_above_512k_tokens=_model_info.get( @@ -6137,13 +6137,13 @@ def _get_model_info_helper( output_cost_per_token_above_200k_tokens=_model_info.get( "output_cost_per_token_above_200k_tokens", None ), - output_cost_per_token_above_200k_tokens_priority=_model_info.get( # any-ok: untyped cost map + output_cost_per_token_above_200k_tokens_priority=_model_info.get( "output_cost_per_token_above_200k_tokens_priority", None ), output_cost_per_token_above_272k_tokens=_model_info.get( "output_cost_per_token_above_272k_tokens", None ), - output_cost_per_token_above_272k_tokens_priority=_model_info.get( # any-ok: untyped cost map + output_cost_per_token_above_272k_tokens_priority=_model_info.get( "output_cost_per_token_above_272k_tokens_priority", None ), output_cost_per_token_above_512k_tokens=_model_info.get( diff --git a/mypy-code-budget.json b/mypy-code-budget.json deleted file mode 100644 index 2cae0d661e9..00000000000 --- a/mypy-code-budget.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "import-not-found": { - "baseline": 8, - "slack": 3 - }, - "no-any-return": { - "baseline": 902, - "slack": 10 - }, - "no-untyped-def": { - "baseline": 4888, - "slack": 10 - }, - "valid-type": { - "baseline": 1, - "slack": 3 - } -} diff --git a/pyproject.toml b/pyproject.toml index 8b1386aaf87..8ee2840b573 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -148,7 +148,6 @@ dev = [ "diff-cover==9.7.2", "flake8==7.3.0", "black==26.3.1", - "mypy==1.19.0", "basedpyright==1.39.7", "pytest==9.0.3", "pytest-mock==3.15.1", @@ -261,8 +260,6 @@ source-exclude = [ "litellm/proxy/enterprise", "**/__pycache__", "**/__pycache__/**", - "**/.mypy_cache", - "**/.mypy_cache/**", "**/.pytest_cache", "**/.pytest_cache/**", "**/.ruff_cache", @@ -278,9 +275,6 @@ version_files = [ "pyproject.toml:^version", ] -[tool.mypy] -plugins = "pydantic.mypy" - [tool.pytest.ini_options] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "session" diff --git a/scripts/budget_ratchet_check.py b/scripts/budget_ratchet_check.py index 6406b0d888e..861d65489e8 100644 --- a/scripts/budget_ratchet_check.py +++ b/scripts/budget_ratchet_check.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 """Non-gating ratchet guard: budget ceilings may only fall, never rise. -Every `*-budget.json` file (ruff-strict, type-discipline, mypy-code, basedpyright-code, -any-discipline) is a one-way ratchet: each rule's ceiling is `baseline + slack`, and the whole point is +Every `*-budget.json` file (ruff-strict, type-discipline, basedpyright-code) is a +one-way ratchet: each rule's ceiling is `baseline + slack`, and the whole point is to drive that number DOWN over time. This check compares every budget file against its own content at the merge-base with the target branch and fails (exits 1, red) if: @@ -12,12 +12,6 @@ its own content at the merge-base with the target branch and fails (exits 1, red New rules and lowered/equal ceilings are fine. -The any-discipline budget is keyed by file rather than rule: its gate treats an -absent file as ceiling 0 (the file must be Any-free), so an entry vanishing means -that file was cleaned to zero -- a tightening, and exactly the cleanup this -ratchet exists to encourage. Such a budget is therefore exempt from the -dropped-entry rule (a raised ceiling is still caught). - This is deliberately NOT a gating check. It should turn the run red so that a loosening is impossible to miss in review, but it must stay OUT of the branch-protection required-checks list: a justified bump (e.g. banning a new API, @@ -44,17 +38,9 @@ DEFAULT_BASE = "origin/litellm_internal_staging" DEFAULT_BUDGETS: tuple[str, ...] = ( "ruff-strict-budget.json", "type-discipline-budget.json", - "mypy-code-budget.json", "basedpyright-code-budget.json", - "any-discipline-budget.json", ) -# File-keyed budgets whose gate treats an absent entry as ceiling 0 (the file -# must stay clean). Dropping an entry there is a tightening, not the "untracked, -# now unbounded" loosening a vanished rule is for the rule-keyed budgets, so a -# dropped entry must not read as a regression. -ZERO_FLOOR_BUDGETS: frozenset[str] = frozenset({"any-discipline-budget.json"}) - class Regression(NamedTuple): budget: str @@ -112,15 +98,17 @@ def regressions_for(rel: str, base: dict | None, head: dict | None) -> list[Regr base_caps = _caps(base) head_caps = _caps(head) - drop_floors_to_zero = rel in ZERO_FLOOR_BUDGETS - out: list[Regression] = [] - for rule, base_cap in sorted(base_caps.items()): - if rule not in head_caps: - if not drop_floors_to_zero: - out.append(Regression(rel, rule, f"rule dropped (ceiling {base_cap} -> removed)")) - elif head_caps[rule] > base_cap: - out.append(Regression(rel, rule, f"ceiling raised {base_cap} -> {head_caps[rule]}")) - return out + return [ + Regression( + rel, + rule, + f"rule dropped (ceiling {base_cap} -> removed)" + if rule not in head_caps + else f"ceiling raised {base_cap} -> {head_caps[rule]}", + ) + for rule, base_cap in sorted(base_caps.items()) + if rule not in head_caps or head_caps[rule] > base_cap + ] def main() -> int: diff --git a/scripts/check_any_discipline.py b/scripts/check_any_discipline.py deleted file mode 100644 index 5b8c83e63e0..00000000000 --- a/scripts/check_any_discipline.py +++ /dev/null @@ -1,778 +0,0 @@ -#!/usr/bin/env python3 -"""Any-discipline gate: fail when a changed file exceeds its `Any` budget. - -Where ruff, `mypy --strict`, and even basedpyright's `reportAny` stop short, this -catches the case that actually bites: a *union* hiding an `Any`. For example -`re.Match.group()` -> `str | Any`, `json.loads()` -> `Any`, and bare `list`/`dict` --> `list[Any]`/`dict[..., Any]`. Any value whose inferred type *contains* `Any` -(recursively, through unions / generics / tuples) is reported. - -Scope: changed files, per-file budget -------------------------------------- -litellm carries a large amount of pre-existing `Any` (a single legacy file can -have >100 findings). Rather than force every touched line clean (the original -changed-lines rule, which tripped on merely *editing* a legacy `X | Any` line), -this gate grandfathers each file: `any-discipline-budget.json` records every -file's current count of Any-typed values, and a file fails only when its count -exceeds `baseline + slack`, where `slack` is 50% headroom (rounded up). New or -unbudgeted files have baseline 0, so they stay airtight. - -Only *changed* files (vs the merge-base with `--base`) are re-type-checked -- an -unchanged file's count can't move from edits this branch didn't make -- so the -per-PR cost equals re-checking just those files, exactly like the original -changed-lines gate. The whole-tree scan needed to (re)capture the budget -(~2 min, ~3 GB) runs only under `--update`. - -The budget is a one-way ratchet (the same `{baseline, slack}` shape as the -ruff / mypy / basedpyright budgets) guarded by `scripts/budget_ratchet_check.py`: -a file's ceiling may fall but never rise. Drive a file's count down and rerun -`--update` (`make lint-any-budget-update`) to lock in the lower ceiling. - -How it works ------------- -It loads `litellm/mypy.ini` (the same config `make lint-mypy` uses, so findings -match what developers already see), builds the changed files with mypy asking for -its exported expression->type map, and walks each file's AST applying a recursive -"contains Any" predicate -- the test `mypy --disallow-any-expr` uses internally -but applies inconsistently (python/mypy#12856). - -mypy only re-exports types for modules it re-type-checks, so for each target we -invalidate just its cached hash (deps stay warm) to force a fast re-check against -a persisted incremental cache (.mypy_cache_any). - -Rules ------ -Codes share the `LIT***` namespace with `scripts/check_type_discipline.py` (PR -#30500), which owns LIT001/002/003/004/006/007/008. This gate claims the rest: -LIT009 A value expression's inferred type is, or contains, `Any`. Budgeted - per file (a file fails when its count exceeds `baseline + slack`). - Suppress an individual line with `# any-ok: `. -LIT005 An `# any-ok` suppression without a reason (the shared - suppression-needs-a-reason code, same as `# cast-ok` / `# guard-ok`). -LIT000 Setup failure: mypy could not build, or a target file could not be read. - -`Any`s produced purely by an already-reported error, and the special-form / -implementation-artifact internal `Any`s, are ignored. A bound method *reference* -whose signature mentions `Any` is not flagged -- only the value its call produces. - -Usage ------ - # gate mode (CI / pre-push): per-file Any budget on changed files - uv run --no-sync python scripts/check_any_discipline.py --changed --base origin/litellm_internal_staging - - # re-capture the per-file budget across the whole tree (ratchet) - uv run --no-sync python scripts/check_any_discipline.py --update - - # whole-file spot-check (no budget, no line filter), paths relative to repo root - uv run --no-sync python scripts/check_any_discipline.py litellm/budget_manager.py - -Exit code 1 if a file is over budget (or a hard rule trips), 2 on a setup error. -""" - -from __future__ import annotations - -import argparse -import json -import os -import re -import subprocess -import sys -import tokenize -from collections.abc import Callable, Iterable, Sequence -from pathlib import Path -from typing import NamedTuple - -try: - from mypy import build - from mypy.config_parser import parse_config_file - from mypy.find_sources import create_source_list - from mypy.fscache import FileSystemCache - from mypy.modulefinder import BuildSource - from mypy.nodes import AssignmentStmt, Expression, NameExpr, Node, TempNode - from mypy.options import Options - from mypy.types import ( - AnyType, - CallableType, - Instance, - Overloaded, - TupleType, - Type, - TypeOfAny, - UnionType, - get_proper_type, - ) -except ImportError: # pragma: no cover - environment guard - sys.stderr.write( - "check_any_discipline: mypy is not importable in this interpreter.\n" - "Run it through the project environment, e.g.\n" - " uv run --no-sync python scripts/check_any_discipline.py --changed\n" - ) - raise SystemExit(2) - - -REPO_ROOT = Path(__file__).resolve().parent.parent -LITELLM_DIR = REPO_ROOT / "litellm" -MYPY_INI = LITELLM_DIR / "mypy.ini" -CACHE_DIR = REPO_ROOT / ".mypy_cache_any" -PY_TAG = f"{sys.version_info.major}.{sys.version_info.minor}" -DEFAULT_BASE = "origin/litellm_internal_staging" -BUDGET_PATH = REPO_ROOT / "any-discipline-budget.json" - -MIN_REASON_LEN = 3 -ANY_OK_RE = re.compile(r"#\s*any-ok(?::\s*(?P.*))?") -_HUNK_RE = re.compile(r"^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@") - -# Files allowed to surface `Any` (the typed/untyped boundary). A finding is -# skipped if any fragment below is a substring of the file's posix path. Keep -# this tight -- prefer a line-level `# any-ok: ` over a blanket exemption. -BOUNDARY_PATHS: frozenset[str] = frozenset() - -# `Any` kinds that are not actionable: produced by an already-reported error, or -# an internal placeholder that never corresponds to a concrete runtime value. -# NOTE: `special_form` is deliberately NOT here. In mypy 1.19 the `Any` in -# typeshed unions like `re.Match.group() -> str | Any` is tagged `special_form`, -# and that union is the headline case this gate exists to catch. -_HARMLESS_ANY = frozenset( - kind - for kind in ( - TypeOfAny.from_error, - getattr(TypeOfAny, "implementation_artifact", None), - ) - if kind is not None -) - -# AST attributes that point OUTSIDE the syntactic subtree (a RefExpr's resolved -# definition, a node's TypeInfo). Skipping exactly these two makes a generic -# child-walk equivalent to mypy's TraverserVisitor -- validated to the node -# against ExtendedTraverserVisitor across the full grammar (see commit notes). -_NON_SYNTACTIC_ATTRS = frozenset({"node", "info"}) - -# Awaitable / coroutine / generator instances carry synthetic `Any` in their -# send (and, for coroutines, yield) protocol slots: `async def f() -> float` -# produces `Coroutine[Any, Any, float]`, so the bare call expression `f()` would -# be flagged even though the awaited value is a clean `float`. Only the args that -# hold a value the caller observes (the awaited result, the yielded item) are -# meaningful; a real `Any` there -- e.g. a coroutine that returns `Any` -- is -# still caught because that index is still checked. -_SYNTHETIC_SEND_YIELD_VALUE_ARGS: dict[str, tuple[int, ...]] = { - "typing.Coroutine": (2,), - "typing.Generator": (0, 2), - "typing.AsyncGenerator": (0,), -} - - -class Violation(NamedTuple): - path: Path - line: int - col: int - code: str - message: str - - def render(self) -> str: - return f"{self.path}:{self.line}:{self.col}: {self.code} {self.message}" - - -# --------------------------------------------------------------------------- # -# The "contains Any" predicate -# --------------------------------------------------------------------------- # - - -# Recursive type aliases (e.g. a JSON-like `T = Union[..., list[T], dict[str, T]]`) -# make `get_proper_type` yield a fresh object at every unfold, so an id()-based -# cycle guard never trips and a naive recursion overflows the stack. We walk -# iteratively and cap the depth: a real `Any` lives at shallow depth in the -# alias's definition, so a deep alias that has not produced one by `_MAX_DEPTH` -# never will. (The changed-lines gate never hit this; a whole-tree scan does.) -_MAX_DEPTH = 100 - - -def contains_any(t: Type) -> bool: - """True if a *value* of type ``t`` carries `Any` anywhere meaningful.""" - seen: set[int] = set() - stack: list[tuple[Type, int]] = [(t, 0)] - while stack: - cur, depth = stack.pop() - if depth > _MAX_DEPTH: - continue - p = get_proper_type(cur) - if id(p) in seen: - continue - seen.add(id(p)) - - # A function/method *reference* whose signature mentions Any is not itself - # an unsafe value -- only its eventual call result is. Don't recurse in. - if isinstance(p, (CallableType, Overloaded)): - continue - if isinstance(p, AnyType): - if p.type_of_any not in _HARMLESS_ANY: - return True - continue - if isinstance(p, UnionType): - stack.extend((item, depth + 1) for item in p.items) - elif isinstance(p, Instance): - value_arg_indices = _SYNTHETIC_SEND_YIELD_VALUE_ARGS.get(p.type.fullname) - if value_arg_indices is None: - stack.extend((arg, depth + 1) for arg in p.args) - else: - stack.extend( - (p.args[index], depth + 1) - for index in value_arg_indices - if index < len(p.args) - ) - elif isinstance(p, TupleType): - stack.extend((item, depth + 1) for item in p.items) - return False - - -# --------------------------------------------------------------------------- # -# Generic, leak-free AST walk (works under a mypyc-compiled mypy, which forbids -# subclassing TraverserVisitor) -# --------------------------------------------------------------------------- # - - -def _walk_file(tree: Node) -> tuple[list[Expression], set[int]]: - """Return (every Expression in `tree`, ids of simple assignment-target names). - - The walk follows only syntactic children (every attribute except the two - non-syntactic back-references), so it never escapes the module. Simple - ``x = `` name targets are collected separately so we don't double-report - the assigned name as an echo of an Any rvalue. - """ - exprs: list[Expression] = [] - skip_lvalues: set[int] = set() - stack: list[object] = [tree] - seen: set[int] = set() - while stack: - n = stack.pop() - if isinstance(n, Node): - if id(n) in seen: - continue - seen.add(id(n)) - if isinstance(n, Expression): - exprs.append(n) - if isinstance(n, AssignmentStmt): - for lvalue in n.lvalues: - if isinstance(lvalue, NameExpr): - skip_lvalues.add(id(lvalue)) - for name in dir(n): - if name.startswith("__") or name in _NON_SYNTACTIC_ATTRS: - continue - try: - val = getattr(n, name) - except Exception: - continue - if callable(val): - continue - if isinstance(val, (Node, list, tuple)): - stack.append(val) - elif isinstance(n, (list, tuple)): - stack.extend(n) - return exprs, skip_lvalues - - -def find_any_in_tree(tree: Node, idmap: dict[int, Type]) -> list[tuple[int, int, str]]: - exprs, skip_lvalues = _walk_file(tree) - findings: list[tuple[int, int, str]] = [] - for expr in exprs: - # A TempNode is mypy's synthetic placeholder for a position with no real - # expression -- e.g. the rvalue of an annotation-only `field: T` in a - # TypedDict / class body, whose `special_form` `Any` is not a value the - # author wrote. It never corresponds to a runtime value, so skip it. - if id(expr) in skip_lvalues or isinstance(expr, TempNode): - continue - t = idmap.get(id(expr)) - if t is not None and contains_any(t): - findings.append((expr.line, expr.column, str(get_proper_type(t)))) - - out: list[tuple[int, int, str]] = [] - seen_pos: set[tuple[int, int]] = set() - for line, col, typ in sorted(findings): - if line < 1 or (line, col) in seen_pos: - continue - seen_pos.add((line, col)) - out.append((line, col, typ)) - return out - - -# --------------------------------------------------------------------------- # -# Comment scanning (LIT005 + any-ok suppression) -# --------------------------------------------------------------------------- # - - -def _reason_ok(reason: str | None) -> bool: - return reason is not None and len(reason.strip()) >= MIN_REASON_LEN - - -def scan_any_ok( - path: Path, source: str -) -> tuple[frozenset[int], tuple[Violation, ...]]: - """Return (lines with a valid any-ok suppression, LIT005 violations).""" - try: - tokens = tokenize.generate_tokens( - iter(source.splitlines(keepends=True)).__next__ - ) - comments = tuple( - (t.start[0], t.string) for t in tokens if t.type == tokenize.COMMENT - ) - except tokenize.TokenError: - return frozenset(), () - - ok_lines: set[int] = set() - violations: list[Violation] = [] - for line, text in comments: - m = ANY_OK_RE.search(text) - if m is None: - continue - if _reason_ok(m.group("reason")): - ok_lines.add(line) - else: - violations.append( - Violation( - path, - line, - 0, - "LIT005", - "any-ok requires a reason: `# any-ok: `", - ) - ) - return frozenset(ok_lines), tuple(violations) - - -# --------------------------------------------------------------------------- # -# mypy build (parity with `make lint-mypy`) + forced target re-check -# --------------------------------------------------------------------------- # - - -def _build_options() -> Options: - opts = Options() - if MYPY_INI.exists(): - parse_config_file(opts, lambda: None, str(MYPY_INI), sys.stdout, sys.stderr) - opts.export_types = True - opts.preserve_asts = True - opts.incremental = True - opts.cache_dir = str(CACHE_DIR) - opts.show_traceback = False - return opts - - -def _meta_path(module: str) -> Path: - return CACHE_DIR / PY_TAG / (module.replace(".", os.sep) + ".meta.json") - - -def _force_recheck(sources: Sequence[BuildSource]) -> None: - """Invalidate each target's cached entry so mypy re-type-checks (and thus - re-exports types + preserves the AST for) exactly these modules, while their - dependencies stay warm. A missing entry is a cold build for that module. - - mypy trusts a cache entry whenever the source mtime matches the cached one - (it never re-hashes on that fast path), so we must break BOTH: zero the - cached mtime to force a re-hash, and corrupt the cached hash so the re-hash - mismatches and the module is treated as changed.""" - for src in sources: - if not src.module: - continue - meta = _meta_path(src.module) - if not meta.exists(): - continue - try: - data = json.loads(meta.read_text()) - data["hash"] = "0" * 40 - data["mtime"] = 0 - meta.write_text(json.dumps(data)) - except (OSError, ValueError): - continue - - -def check_files(rel_paths: Sequence[str]) -> tuple[Violation, ...]: - """`rel_paths` are relative to the litellm package dir (the build cwd).""" - prev_cwd = Path.cwd() - os.chdir(LITELLM_DIR) - try: - opts = _build_options() - fscache = FileSystemCache() - sources = create_source_list(list(rel_paths), opts, fscache) - _force_recheck(sources) - try: - res = build.build(sources, options=opts, fscache=fscache) - except build.CompileError as exc: - joined = "; ".join(exc.messages[:3]) or "blocking error" - return ( - Violation( - Path(rel_paths[0]), - 0, - 0, - "LIT000", - f"mypy could not build: {joined}", - ), - ) - idmap = {id(expr): t for expr, t in res.types.items()} - # Resolve trees to absolute source paths while cwd is the build dir, since - # mypy stores the paths it was given (relative to this cwd). - trees: dict[str, Node] = {} - for state in res.graph.values(): - if state.path and state.tree is not None: - trees[os.path.realpath(state.path)] = state.tree - finally: - os.chdir(prev_cwd) - - out: list[Violation] = [] - for rel in rel_paths: - abs_path = (LITELLM_DIR / rel).resolve() - report_path = abs_path.relative_to(REPO_ROOT) - if _is_boundary(report_path): - continue - try: - source = abs_path.read_text(encoding="utf-8") - except (OSError, UnicodeDecodeError) as exc: - out.append( - Violation(report_path, 0, 0, "LIT000", f"could not read file: {exc}") - ) - continue - - ok_lines, ok_violations = scan_any_ok(report_path, source) - out.extend(ok_violations) - tree = trees.get(os.path.realpath(abs_path)) - if tree is None: - continue - for line, col, typ in find_any_in_tree(tree, idmap): - if line in ok_lines: - continue - out.append( - Violation( - report_path, - line, - col, - "LIT009", - f"value type contains Any -> {typ}", - ) - ) - return tuple(out) - - -# --------------------------------------------------------------------------- # -# File selection (changed-only, changed-lines) + driver -# --------------------------------------------------------------------------- # - - -class _AllLines: - """Sentinel: a wholly new / untracked file -- every line is in scope. - - A distinct object, not None, so that `line_map.get(path)` returning None for - a path absent from the map is never mistaken for "whole file in scope".""" - - -# A changed file's in-scope lines: a specific set, or every line. -LineScope = set[int] | _AllLines -ALL_LINES = _AllLines() - - -def _is_boundary(path: Path) -> bool: - posix = path.as_posix() - return any(frag in posix for frag in BOUNDARY_PATHS) - - -def _git(*args: str) -> list[str]: - result = subprocess.run( - ["git", "-C", str(REPO_ROOT), *args], - capture_output=True, - text=True, - check=True, - ) - return result.stdout.splitlines() - - -def _parse_added_lines(diff_text: str) -> dict[str, set[int]]: - """Map repo-relative path -> set of new-file line numbers the diff adds/edits.""" - changed: dict[str, set[int]] = {} - path: str | None = None - for line in diff_text.splitlines(): - if line.startswith("+++ b/"): - path = line[6:] - elif path and (m := _HUNK_RE.match(line)): - start = int(m.group(1)) - count = int(m.group(2)) if m.group(2) is not None else 1 - if count: - changed.setdefault(path, set()).update(range(start, start + count)) - return changed - - -def changed_line_map(base: str) -> dict[str, LineScope] | None: - """Repo-relative `.py` path under litellm/ -> changed line numbers (or - ALL_LINES for untracked files). Compares the working tree to the merge-base - with `base`, so it covers committed-on-branch + unstaged edits. None if git - is unavailable / not a repo.""" - try: - merge_base = _git("merge-base", base, "HEAD") - point = merge_base[0].strip() if merge_base else base - diff = "\n".join( - _git( - "diff", - "--unified=0", - "--no-color", - "--diff-filter=d", - point, - "--", - "litellm", - ) - ) - untracked = _git("ls-files", "--others", "--exclude-standard", "--", "litellm") - except (subprocess.CalledProcessError, FileNotFoundError): - return None - - out: dict[str, LineScope] = {} - for name, lines in _parse_added_lines(diff).items(): - if name.endswith(".py") and (REPO_ROOT / name).exists(): - out[name] = lines - for name in untracked: - if name.endswith(".py") and (REPO_ROOT / name).exists(): - out[name] = ALL_LINES - return out - - -def _to_litellm_relative(paths: Iterable[Path]) -> list[str]: - rels: list[str] = [] - for p in sorted(paths): - try: - rels.append(p.resolve().relative_to(LITELLM_DIR).as_posix()) - except ValueError: - continue - return rels - - -def _in_scope(v: Violation, line_map: dict[str, LineScope] | None) -> bool: - """A finding survives if line filtering is off (explicit paths), it's a build - error, or its line is one the diff added/edited.""" - if line_map is None or v.code == "LIT000": - return True - lines = line_map.get(v.path.as_posix()) - return lines is ALL_LINES or (isinstance(lines, set) and v.line in lines) - - -# --------------------------------------------------------------------------- # -# Per-file Any budget (one-way ratchet, 50% headroom; ratchet-checked) -# --------------------------------------------------------------------------- # - - -def _slack_for(baseline: int) -> int: - """50% headroom, rounded up so even a 1-Any file gets a little room.""" - return (baseline + 1) // 2 - - -def _ceiling(spec: dict[str, int]) -> int: - """A file's ceiling: ``baseline + slack`` (0 for an absent/empty entry).""" - return int(spec.get("baseline", 0)) + int(spec.get("slack", 0)) - - -def load_budget() -> dict[str, dict[str, int]]: - """Read ``any-discipline-budget.json`` ({path: {baseline, slack}}); {} if absent.""" - if not BUDGET_PATH.exists(): - return {} - try: - data = json.loads(BUDGET_PATH.read_text()) - except (OSError, ValueError): - return {} - return data if isinstance(data, dict) else {} - - -def save_budget(counts: dict[str, int]) -> None: - """Write a fresh budget from per-file counts, with 50% headroom each. - - Files with zero Any are omitted: an absent entry means baseline 0, so a - file's first Any always trips the gate until it is deliberately baselined.""" - budget = { - path: {"baseline": n, "slack": _slack_for(n)} - for path, n in counts.items() - if n > 0 - } - BUDGET_PATH.write_text(json.dumps(budget, indent=2, sort_keys=True) + "\n") - - -def lit009_counts(violations: Iterable[Violation]) -> dict[str, int]: - """Count LIT009 (Any-typed value) findings per repo-relative file path.""" - counts: dict[str, int] = {} - for v in violations: - if v.code == "LIT009": - key = v.path.as_posix() - counts[key] = counts.get(key, 0) + 1 - return counts - - -def all_litellm_py_files() -> list[str] | None: - """Every tracked ``.py`` under litellm/, as litellm-package-relative paths; - None if git is unavailable / not a repo (mirrors ``changed_line_map``).""" - try: - tracked = _git("ls-files", "--", "litellm") - except (subprocess.CalledProcessError, FileNotFoundError): - return None - return _to_litellm_relative( - REPO_ROOT / name for name in tracked if name.endswith(".py") - ) - - -def update_budget( - list_files: Callable[[], list[str] | None] = all_litellm_py_files, -) -> int: - """Whole-tree scan: recapture every file's Any count into the budget.""" - rel_paths = list_files() - if rel_paths is None: - print( - "check_any_discipline: not a git repository; cannot capture the budget", - file=sys.stderr, - ) - return 2 - if not rel_paths: - print("check_any_discipline: no litellm/*.py files found", file=sys.stderr) - return 2 - violations = check_files(rel_paths) - build_errors = [v for v in violations if v.code == "LIT000"] - if build_errors: - for v in build_errors: - print(v.render(), file=sys.stderr) - print( - "FAIL: mypy could not build the tree; budget left unchanged.", - file=sys.stderr, - ) - return 2 - counts = lit009_counts(violations) - save_budget(counts) - print( - f"Wrote {BUDGET_PATH.name}: " - f"{sum(1 for n in counts.values() if n > 0)} file(s), " - f"{sum(counts.values())} Any-typed value(s) baselined (50% headroom each)." - ) - return 0 - - -def _report_over_budget( - path: str, - count: int, - spec: dict[str, int] | None, - lit009: list[Violation], - line_map: dict[str, LineScope], -) -> None: - """Print one over-budget file plus the Any findings on its changed lines.""" - ceiling = _ceiling(spec or {}) - if spec: - why = f"baseline {spec['baseline']} + 50% slack {spec['slack']} = ceiling {ceiling}" - else: - why = "no budget entry -> baseline 0 (a new/unbudgeted file must be Any-free)" - print(f"{path}: {count} Any-typed value(s) total, over budget ({why})") - # Surface the findings on changed lines first: the ones this branch most - # likely just added, and the cheapest path back under the ceiling. - scope = line_map.get(path) - for v in sorted(lit009): - if scope is ALL_LINES or (isinstance(scope, set) and v.line in scope): - print(f" changed-line Any {v.line}:{v.col} {v.message}") - - -def run_gate(base: str) -> int: - """Gate changed files under litellm/ against the committed per-file budget.""" - line_map = changed_line_map(base) - if line_map is None: - print( - "check_any_discipline: not a git repository; nothing to check", - file=sys.stderr, - ) - return 0 - rel_paths = _to_litellm_relative((REPO_ROOT / name).resolve() for name in line_map) - if not rel_paths: - print("OK: no changed Python files under litellm/ to check") - return 0 - - violations = check_files(rel_paths) - budget = load_budget() - - # Hard rules, independent of the budget: a build/read failure (always), and a - # reasonless `# any-ok` on a line this branch touched. - hard = sorted( - v - for v in violations - if v.code == "LIT000" or (v.code == "LIT005" and _in_scope(v, line_map)) - ) - - # Per-file Any budget: a changed file fails when its total Any count exceeds - # its ceiling. Unchanged files keep their committed baseline (never re-scanned). - counts = lit009_counts(violations) - lit009_by_file: dict[str, list[Violation]] = {} - for v in violations: - if v.code == "LIT009": - lit009_by_file.setdefault(v.path.as_posix(), []).append(v) - over_budget = [ - (path, count) - for path, count in sorted(counts.items()) - if count > _ceiling(budget.get(path, {})) - ] - - if not hard and not over_budget: - print( - f"OK: {len(rel_paths)} changed file(s) under litellm/ are within their Any budget" - ) - return 0 - - for v in hard: - print(v.render()) - for path, count in over_budget: - _report_over_budget( - path, count, budget.get(path), lit009_by_file.get(path, []), line_map - ) - - print( - f"\nFAIL: {len(hard)} hard violation(s), {len(over_budget)} file(s) over their Any budget.\n" - "Give the new values concrete types (validate untyped input with Pydantic) to get back\n" - "under the file's ceiling, or annotate a genuine boundary line `# any-ok: `.\n" - "Re-baseline with `make lint-any-budget-update` only to lock in a reduction.", - file=sys.stderr, - ) - return 1 - - -def spot_check(rel_paths: Sequence[str]) -> int: - """Explicit-paths mode: report every finding in the files (no budget).""" - violations = sorted(check_files(rel_paths)) - for v in violations: - print(v.render()) - if violations: - print(f"\nFAIL: {len(violations)} Any-discipline finding(s).", file=sys.stderr) - return 1 - print(f"OK: {len(rel_paths)} file(s) have no Any-typed values") - return 0 - - -def main(argv: Sequence[str]) -> int: - parser = argparse.ArgumentParser( - description="Any-discipline gate (changed files, per-file Any budget)." - ) - parser.add_argument( - "paths", - nargs="*", - help="explicit files (repo-root relative); whole-file spot-check, no budget", - ) - parser.add_argument( - "--changed", - action="store_true", - help="gate changed files under litellm/ vs --base against the per-file budget", - ) - parser.add_argument( - "--update", - action="store_true", - help="recapture the whole-tree per-file budget (any-discipline-budget.json)", - ) - parser.add_argument("--base", default=os.environ.get("ANY_GATE_BASE", DEFAULT_BASE)) - args = parser.parse_args(list(argv)) - - if args.update: - return update_budget() - if args.changed: - return run_gate(args.base) - if args.paths: - rel_paths = _to_litellm_relative((REPO_ROOT / p).resolve() for p in args.paths) - if not rel_paths: - print("check_any_discipline: no litellm/*.py paths given", file=sys.stderr) - return 2 - return spot_check(rel_paths) - parser.error("pass --changed, --update, or explicit file paths") - return 2 - - -if __name__ == "__main__": - raise SystemExit(main(sys.argv[1:])) diff --git a/scripts/check_type_discipline.py b/scripts/check_type_discipline.py index d83a1a7512f..6e152541863 100644 --- a/scripts/check_type_discipline.py +++ b/scripts/check_type_discipline.py @@ -25,10 +25,8 @@ LIT003 noqa suppression without rule codes or without a reason. Required shape: `# noqa: TID251 # ` LIT004 type/pyright/mypy ignore without bracketed codes or without a reason. Required shape: `# pyright: ignore[reportArgumentType] # ` -LIT005 A `# mutable-ok` / `# cast-ok` / `# guard-ok` / `# kwargs-ok` / `# any-ok` - suppression without a reason. (`any-ok` belongs to check_any_discipline.py; - it is enumerated here so the reason requirement holds even when only this - stdlib checker runs.) +LIT005 A `# mutable-ok` / `# cast-ok` / `# guard-ok` / `# kwargs-ok` + suppression without a reason. LIT006 `cast(...)` call. typing.cast is an unchecked assertion (the moral equivalent of TypeScript's `as`); it lies to the type checker with zero runtime guarantee. Validate into a concrete frozen type at the boundary instead. @@ -41,9 +39,8 @@ LIT008 `**kwargs` parameter. The keyword contract is erased and everything it c syntax. Declare explicit keyword params, or accept one frozen payload. `*args`, by contrast, is fine when typed (it's just a tuple). Suppress: `# kwargs-ok: `. -LIT000 and LIT009 are the sibling Any gate's (check_any_discipline.py, #30379): a mypy -build/read failure and an Any-typed value. They share this LIT namespace but are emitted -by that checker, not this one. +LIT000 Setup failure: a target file could not be read, or contains a syntax error. + Reported as a violation rather than crashing the run. Usage ----- @@ -105,17 +102,13 @@ MUTABLE_OK_RE = re.compile(r"#\s*mutable-ok(?::\s*(?P.*))?") CAST_OK_RE = re.compile(r"#\s*cast-ok(?::\s*(?P.*))?") GUARD_OK_RE = re.compile(r"#\s*guard-ok(?::\s*(?P.*))?") KWARGS_OK_RE = re.compile(r"#\s*kwargs-ok(?::\s*(?P.*))?") -ANY_OK_RE = re.compile(r"#\s*any-ok(?::\s*(?P.*))?") -# Suppression tokens that must each carry a reason (LIT005). `any-ok` is owned by -# check_any_discipline.py but listed here so the reason requirement is enforced even -# when only this stdlib checker runs. +# Suppression tokens that must each carry a reason (LIT005). OK_SUPPRESSIONS: tuple[tuple[str, re.Pattern[str]], ...] = ( ("mutable-ok", MUTABLE_OK_RE), ("cast-ok", CAST_OK_RE), ("guard-ok", GUARD_OK_RE), ("kwargs-ok", KWARGS_OK_RE), - ("any-ok", ANY_OK_RE), ) diff --git a/scripts/type_check_gate.py b/scripts/type_check_gate.py index 5ff485f0b0f..0f9a44703f9 100644 --- a/scripts/type_check_gate.py +++ b/scripts/type_check_gate.py @@ -1,47 +1,38 @@ #!/usr/bin/env python3 -"""Per-rule count gate for mypy and basedpyright. +"""Per-rule count gate for basedpyright. -Each tool's output is reduced to a count of errors per *rule* (mypy error codes -like ``arg-type``, basedpyright rules like ``reportAny``) and checked against a -committed budget of the form ``{rule: {baseline, slack}}``, the same shape as +basedpyright's ``--outputjson`` is reduced to a count of errors per *rule* +(``reportAny``, ``reportArgumentType``, ...) and checked against a committed +budget of the form ``{rule: {baseline, slack}}``, the same shape as ``ruff-strict-budget.json``. A rule fails when its codebase-wide total exceeds ``baseline + slack``. Counts ignore file, line, and column, so a violation moving anywhere in the tree is invisible; only the per-rule total moves the needle. Unlike ``ruff_strict_gate.py`` this does *not* re-run the tool on the merge base -to compute a delta: a second mypy/basedpyright pass is minutes and gigabytes, -whereas ruff is milliseconds. The committed budget is the baseline instead -- -exactly how the previous per-file gate worked -- so keep it fresh with -``--update`` (ratchet), which re-captures every rule's count from the current -tree while preserving each rule's slack. Tool output is read from stdin, so the -caller decides how to invoke the tool (and from which cwd). +to compute a delta: a second basedpyright pass is minutes and gigabytes, whereas +ruff is milliseconds. The committed budget is the baseline instead -- exactly +how the previous per-file gate worked -- so keep it fresh with ``--update`` +(ratchet), which re-captures every rule's count from the current tree while +preserving each rule's slack. Tool output is read from stdin, so the caller +decides how to invoke basedpyright (and from which cwd). -mypy is parsed from its text output (one error per line, the rule code in a -trailing ``[bracket]``). basedpyright is parsed from ``--outputjson``: its text -diagnostics routinely wrap across lines, leaving the ``(reportRule)`` on a -continuation line away from the ``- error:`` marker, so line parsing -mis-attributes ~60% of errors -- the JSON carries an unambiguous ``rule`` field. +``--outputjson`` is used rather than text diagnostics because the latter wrap +across lines, leaving the ``(reportRule)`` on a continuation line away from the +``- error:`` marker, so line parsing mis-attributes ~60% of errors -- the JSON +carries an unambiguous ``rule`` field. """ import argparse import json -import re import sys from collections import Counter from pathlib import Path -from typing import Iterable, Mapping, NamedTuple +from typing import Mapping, NamedTuple REPO_ROOT = Path(__file__).resolve().parent.parent -# mypy: one error per line, e.g. `path:12: error: msg [arg-type]`. ERROR_LINE -# recognizes the line; MYPY_CODE pulls the trailing [code]. Kept separate so an -# error emitted without a code is still counted (under UNCODED), never dropped. -MYPY_ERROR = re.compile(r"^(?P.+?):\d+: error:") -MYPY_CODE = re.compile(r"\[(?P[a-z][a-z0-9-]*)\]\s*$") - -# Bucket for an error whose rule code we couldn't read (a mypy error with no -# code, or a basedpyright diagnostic with no `rule`). Counted so it's gated. +# Bucket for a basedpyright diagnostic with no `rule`. Counted so it's gated. UNCODED = "" # Ceiling for a rule that shows up at HEAD but isn't in the budget at all -- a @@ -72,20 +63,6 @@ def _to_repo_relative(raw: str) -> str | None: return None -def count_mypy(lines: Iterable[str]) -> dict[str, int]: - """Count in-repo mypy errors per rule code from text output. Errors for - files outside the repo (third-party stubs) are ignored, as before.""" - counts: Counter[str] = Counter() - for raw in lines: - line = raw.rstrip("\n") - match = MYPY_ERROR.match(line) - if match is None or _to_repo_relative(match.group("file")) is None: - continue - code = MYPY_CODE.search(line) - counts[code.group("code") if code else UNCODED] += 1 - return dict(counts) - - def count_basedpyright(payload: str) -> dict[str, int]: """Count in-repo basedpyright errors per rule from `--outputjson`. Warnings and information are ignored; only `severity == "error"` is gated.""" @@ -108,12 +85,6 @@ def count_basedpyright(payload: str) -> dict[str, int]: return dict(counts) -def count_errors(stdin_text: str, tool: str) -> dict[str, int]: - if tool == "basedpyright": - return count_basedpyright(stdin_text) - return count_mypy(stdin_text.splitlines()) - - def evaluate( counts: Mapping[str, int], budget: Mapping[str, Mapping[str, int]] ) -> list[Breach]: @@ -136,13 +107,11 @@ def is_vacuous_run( return not counts and any(spec["baseline"] for spec in budget.values()) -def budget_path(tool: str) -> Path: - return REPO_ROOT / f"{tool}-code-budget.json" +BUDGET_PATH = REPO_ROOT / "basedpyright-code-budget.json" -def cmd_update(tool: str, counts: Mapping[str, int]) -> None: - path = budget_path(tool) - existing = json.loads(path.read_text()) if path.exists() else {} +def cmd_update(counts: Mapping[str, int]) -> None: + existing = json.loads(BUDGET_PATH.read_text()) if BUDGET_PATH.exists() else {} budget = { code: { "baseline": count, @@ -152,18 +121,18 @@ def cmd_update(tool: str, counts: Mapping[str, int]) -> None: } for code, count in sorted(counts.items()) } - path.write_text(json.dumps(budget, indent=2, sort_keys=True) + "\n") + BUDGET_PATH.write_text(json.dumps(budget, indent=2, sort_keys=True) + "\n") print( - f"Re-captured {tool} per-rule budget: {len(budget)} rules, {sum(counts.values())} errors total" + f"Re-captured basedpyright per-rule budget: {len(budget)} rules, {sum(counts.values())} errors total" ) -def cmd_check(tool: str, counts: Mapping[str, int]) -> None: - budget = json.loads(budget_path(tool).read_text()) +def cmd_check(counts: Mapping[str, int]) -> None: + budget = json.loads(BUDGET_PATH.read_text()) if is_vacuous_run(counts, budget): expected = sum(spec["baseline"] for spec in budget.values()) print( - f"FAIL: {tool} produced no errors, but {budget_path(tool).name} expects " + f"FAIL: basedpyright produced no errors, but {BUDGET_PATH.name} expects " f"~{expected}. The type checker almost certainly crashed or emitted " f"nothing; refusing to certify a vacuous run." ) @@ -171,25 +140,24 @@ def cmd_check(tool: str, counts: Mapping[str, int]) -> None: breaches = evaluate(counts, budget) if not breaches: print( - f"OK: every rule is within its {tool} ceiling ({sum(counts.values())} errors total)" + f"OK: every rule is within its basedpyright ceiling ({sum(counts.values())} errors total)" ) return - print(f"FAIL: {tool} errors exceed the per-rule ceiling:") + print("FAIL: basedpyright errors exceed the per-rule ceiling:") for breach in breaches: print(f" {breach.code}: {breach.total} errors over cap {breach.cap}") print( - f"Resolve the new errors, or run 'make lint-{tool}-budget-update' if the ceiling should move." + "Resolve the new errors, or run 'make lint-basedpyright-budget-update' if the ceiling should move." ) raise SystemExit(1) def main() -> None: parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument("--tool", choices=("mypy", "basedpyright"), required=True) parser.add_argument("--update", action="store_true") args = parser.parse_args() - counts = count_errors(sys.stdin.read(), args.tool) - cmd_update(args.tool, counts) if args.update else cmd_check(args.tool, counts) + counts = count_basedpyright(sys.stdin.read()) + cmd_update(counts) if args.update else cmd_check(counts) if __name__ == "__main__": diff --git a/tests/test_litellm/test_budget_ratchet_check.py b/tests/test_litellm/test_budget_ratchet_check.py index 8c4150fd36b..9f19944fdba 100644 --- a/tests/test_litellm/test_budget_ratchet_check.py +++ b/tests/test_litellm/test_budget_ratchet_check.py @@ -48,24 +48,7 @@ def test_dropped_rule_is_a_regression(): def test_new_rule_in_head_is_clean(): - assert ratchet.regressions_for("b.json", {}, {"LIT009": _spec_of(5, 0)}) == [] - - -def test_dropped_file_in_the_any_budget_is_not_a_regression(): - # any-discipline is file-keyed: an absent file means ceiling 0, so cleaning a - # file to zero (which drops its entry on --update) is a tightening, never the - # loosening a dropped rule is for the rule-keyed budgets. - base = {"litellm/x.py": _spec_of(10, 5)} - assert ratchet.regressions_for("any-discipline-budget.json", base, {}) == [] - - -def test_raised_ceiling_in_the_any_budget_is_still_a_regression(): - base = {"litellm/x.py": _spec_of(10, 5)} # ceiling 15 - regs = ratchet.regressions_for( - "any-discipline-budget.json", base, {"litellm/x.py": _spec_of(20, 10)} # ceiling 30 - ) - assert [r.rule for r in regs] == ["litellm/x.py"] - assert "15 -> 30" in regs[0].detail + assert ratchet.regressions_for("b.json", {}, {"new-rule": _spec_of(5, 0)}) == [] def test_deleted_budget_file_is_a_regression(): diff --git a/tests/test_litellm/test_check_any_discipline.py b/tests/test_litellm/test_check_any_discipline.py deleted file mode 100644 index 40385664691..00000000000 --- a/tests/test_litellm/test_check_any_discipline.py +++ /dev/null @@ -1,90 +0,0 @@ -import importlib.util -from pathlib import Path - -_MODULE_PATH = ( - Path(__file__).resolve().parents[2] / "scripts" / "check_any_discipline.py" -) -_spec = importlib.util.spec_from_file_location("check_any_discipline", _MODULE_PATH) -mod = importlib.util.module_from_spec(_spec) -_spec.loader.exec_module(mod) - -Violation = mod.Violation - - -def _v(path="litellm/x.py", line=10, code="LIT009"): - return Violation(Path(path), line, 0, code, "Any-typed value") - - -def test_violation_on_a_changed_line_is_in_scope(): - assert mod._in_scope(_v(line=10), {"litellm/x.py": {10, 11}}) is True - - -def test_violation_on_an_unchanged_line_of_a_changed_file_is_out_of_scope(): - assert mod._in_scope(_v(line=99), {"litellm/x.py": {10, 11}}) is False - - -def test_whole_new_file_puts_every_line_in_scope(): - assert mod._in_scope(_v(line=99999), {"litellm/x.py": mod.ALL_LINES}) is True - - -def test_file_absent_from_line_map_is_out_of_scope(): - # Regression: ALL_LINES is a distinct sentinel, so a path missing from the map - # (line_map.get -> None) is NOT mistaken for "whole file in scope". - assert mod._in_scope(_v(path="litellm/other.py"), {"litellm/x.py": {1}}) is False - - -def test_no_line_map_means_no_line_filtering(): - assert mod._in_scope(_v(line=12345), None) is True - - -def test_build_error_is_always_in_scope(): - assert mod._in_scope(_v(code="LIT000", line=1), {"litellm/x.py": {2}}) is True - - -# --- per-file Any budget ------------------------------------------------------ - - -def test_slack_is_50_percent_rounded_up(): - assert mod._slack_for(0) == 0 - assert mod._slack_for(1) == 1 # ceil(0.5): even a 1-Any file gets a little room - assert mod._slack_for(3) == 2 # ceil(1.5) - assert mod._slack_for(20) == 10 - assert mod._slack_for(5145) == 2573 - - -def test_ceiling_is_baseline_plus_slack(): - assert mod._ceiling({"baseline": 20, "slack": 10}) == 30 - assert mod._ceiling({}) == 0 # an absent/empty entry means a zero ceiling - - -def test_lit009_counts_groups_by_file_and_ignores_other_codes(): - violations = [ - _v(path="litellm/a.py", line=1, code="LIT009"), - _v(path="litellm/a.py", line=2, code="LIT009"), - _v(path="litellm/a.py", line=3, code="LIT005"), # suppression hygiene, not an Any - _v(path="litellm/b.py", line=1, code="LIT009"), - _v(path="litellm/c.py", line=0, code="LIT000"), # build error, not an Any - ] - assert mod.lit009_counts(violations) == {"litellm/a.py": 2, "litellm/b.py": 1} - - -def test_save_budget_omits_zero_count_files_and_round_trips(monkeypatch, tmp_path): - monkeypatch.setattr(mod, "BUDGET_PATH", tmp_path / "any-discipline-budget.json") - mod.save_budget({"litellm/a.py": 20, "litellm/b.py": 0, "litellm/c.py": 1}) - loaded = mod.load_budget() - assert loaded == { - "litellm/a.py": {"baseline": 20, "slack": 10}, - "litellm/c.py": {"baseline": 1, "slack": 1}, - } - assert "litellm/b.py" not in loaded # zero-Any files are never baselined - - -def test_load_budget_missing_file_is_empty(monkeypatch, tmp_path): - monkeypatch.setattr(mod, "BUDGET_PATH", tmp_path / "nope.json") - assert mod.load_budget() == {} - - -def test_update_budget_reports_setup_error_when_git_is_unavailable(): - # all_litellm_py_files returns None when git can't list files; --update must - # surface a clean setup error (exit 2), not crash with a raw traceback. - assert mod.update_budget(list_files=lambda: None) == 2 diff --git a/tests/test_litellm/test_type_check_gate.py b/tests/test_litellm/test_type_check_gate.py index eb01bd3b93e..18374c5db4b 100644 --- a/tests/test_litellm/test_type_check_gate.py +++ b/tests/test_litellm/test_type_check_gate.py @@ -10,22 +10,6 @@ _spec.loader.exec_module(gate) ROOT = gate.REPO_ROOT -def test_mypy_counts_per_code_ignoring_lines_notes_and_summary(): - text = "\n".join( - [ - f"{ROOT}/litellm/utils.py:10: error: missing annotation [no-untyped-def]", - f"{ROOT}/litellm/utils.py:9999: error: missing annotation [no-untyped-def]", - f"{ROOT}/litellm/main.py:5: error: Returning Any [no-any-return]", - f"{ROOT}/litellm/main.py:5: note: see here", - "Found 3 errors in 2 files (checked 100 source files)", - ] - ) - assert gate.count_errors(text, "mypy") == { - "no-untyped-def": 2, - "no-any-return": 1, - } - - def _bpr(file, severity, rule): diag = {"file": str(file), "severity": severity, "message": "msg"} if rule is not None: @@ -46,7 +30,7 @@ def test_basedpyright_counts_per_rule_from_json_not_warnings(): ] } ) - assert gate.count_errors(payload, "basedpyright") == { + assert gate.count_basedpyright(payload) == { "reportUnknownVariableType": 2, "reportArgumentType": 1, } @@ -56,17 +40,10 @@ def test_basedpyright_error_without_a_rule_is_bucketed(): payload = json.dumps( {"generalDiagnostics": [_bpr(f"{ROOT}/litellm/x.py", "error", None)]} ) - assert gate.count_errors(payload, "basedpyright") == {gate.UNCODED: 1} - - -def test_mypy_error_without_a_code_is_bucketed_so_it_is_still_gated(): - text = f"{ROOT}/litellm/x.py:1: error: something broke with no code" - assert gate.count_errors(text, "mypy") == {gate.UNCODED: 1} + assert gate.count_basedpyright(payload) == {gate.UNCODED: 1} def test_paths_outside_repo_are_skipped(): - text = "/tmp/elsewhere.py:1: error: missing annotation [no-untyped-def]" - assert gate.count_errors(text, "mypy") == {} payload = json.dumps( { "generalDiagnostics": [ @@ -74,7 +51,7 @@ def test_paths_outside_repo_are_skipped(): ] } ) - assert gate.count_errors(payload, "basedpyright") == {} + assert gate.count_basedpyright(payload) == {} def test_at_or_under_ceiling_passes(): @@ -124,10 +101,10 @@ def test_malformed_basedpyright_json_exits_loudly_not_as_zero_errors(): import pytest with pytest.raises(SystemExit): - gate.count_errors("startup warning\n{not json", "basedpyright") + gate.count_basedpyright("startup warning\n{not json") def test_empty_basedpyright_payload_counts_zero(): # Empty (not malformed) output parses to zero; the vacuous-run guard, not the # parser, is what rejects an empty run. - assert gate.count_errors("", "basedpyright") == {} + assert gate.count_basedpyright("") == {} diff --git a/uv.lock b/uv.lock index bc796e6ed07..5339b56df7f 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-06-11T06:56:06.940919973Z" +exclude-newer = "2026-06-14T15:53:04.946308996Z" exclude-newer-span = "P3D" [manifest] @@ -3231,65 +3231,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8c/7e/e7394eeb49a41cc514b3eb49020223666cbf40d86f5721c2f07871e6d84a/legacy_cgi-2.6.4-py3-none-any.whl", hash = "sha256:7e235ce58bf1e25d1fc9b2d299015e4e2cd37305eccafec1e6bac3fc04b878cd", size = 20035, upload-time = "2025-10-27T05:20:04.289Z" }, ] -[[package]] -name = "librt" -version = "0.11.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/40/08/9e7f6b5d2b5bed6ad055cdd5925f192bb403a51280f86b56554d9d0699a2/librt-0.11.0.tar.gz", hash = "sha256:075dc3ef4458a278e0195cbf6ac9d38808d9b906c5a6c7f7f79c3888276a3fb1", size = 200139, upload-time = "2026-05-10T18:17:25.138Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/10/37fd9e9ba96cb0bd742dfb20fc3d082e54bdbec759d7300df927f360ef07/librt-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6e94ebfcfa2d5e9926d6c3b9aa4617ffc42a845b4321fb84021b872358c82a0f", size = 141706, upload-time = "2026-05-10T18:15:16.129Z" }, - { url = "https://files.pythonhosted.org/packages/cf/72/1b1466f358e4a0b728051f69bc27e67b432c6eaa2e05b88db49d3785ae0d/librt-0.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ae627397a2f351560440d872d6f7c8dbb4072e57868e7b2fc5b8b430fe489d45", size = 142605, upload-time = "2026-05-10T18:15:18.148Z" }, - { url = "https://files.pythonhosted.org/packages/ca/85/ed26dd2f6bc9a0baf48306433e579e8d354d70b2bcb78134ed950a5d0e1e/librt-0.11.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc329359321b67d24efdf4bc69012b0597001649544db662c001db5a0184794c", size = 476555, upload-time = "2026-05-10T18:15:19.569Z" }, - { url = "https://files.pythonhosted.org/packages/66/fe/11891191c0e0a3fd617724e891f6e67a71a7658974a892b9a9a97fdb2977/librt-0.11.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:7e82e642ab0f7608ce2fe53d76ca2280a9ee33a1b06556142c7c6fe80a86fc33", size = 468434, upload-time = "2026-05-10T18:15:20.87Z" }, - { url = "https://files.pythonhosted.org/packages/6f/50/5ec949d7f9ce1a07af903aa3e13abb98b717923bdead6e719b2f824ccc07/librt-0.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88145c15c67731d54283d135b03244028c750cc9edc334a96a4f5950ebdb2884", size = 496918, upload-time = "2026-05-10T18:15:22.616Z" }, - { url = "https://files.pythonhosted.org/packages/ea/c4/177336c7524e34875a38bf668e88b193a6723a4eb4045d07f74df6e1506c/librt-0.11.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9d36a51b3d93320b686588e27123f4995804dbf1bce81df78c02fc3c6eea9280", size = 490334, upload-time = "2026-05-10T18:15:24.2Z" }, - { url = "https://files.pythonhosted.org/packages/13/1f/da3112f7569eda3b49f9a2629bae1fe059812b6085df16c885f6454dff49/librt-0.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3ac06a2a8b246327f11e186a53a100a4d5c7ed52346367e5ec751d51586c", size = 511287, upload-time = "2026-05-10T18:15:26.226Z" }, - { url = "https://files.pythonhosted.org/packages/fa/94/03fec301522e172d105581431223be56b27594ff46440ebfbb658a3735d5/librt-0.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:461bbceede621f1ffb8839755f8663e886087ee7af16294cab7fb4d782c62eeb", size = 517202, upload-time = "2026-05-10T18:15:27.965Z" }, - { url = "https://files.pythonhosted.org/packages/b7/6e/339f6e5a7b413ce014f1917a756dae630fe59cc99f34153205b1cb540901/librt-0.11.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0cad8a4d6a8ff03c9b76f9414caccd78e7cfbc8a2e12fa334d8e1d9932753783", size = 497517, upload-time = "2026-05-10T18:15:29.614Z" }, - { url = "https://files.pythonhosted.org/packages/cd/43/acdd5ce317cb46e8253ca9bfbdb8b12e68a24d745949336a7f3d5fb79ba0/librt-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f37aa505b3cf60701562eddb32df74b12a9e380c207fd8b06dd157a943ac7ea0", size = 538878, upload-time = "2026-05-10T18:15:30.928Z" }, - { url = "https://files.pythonhosted.org/packages/29/b5/7a25bb12e3172839f647f196b3e988318b7bb1ca7501732a225c4dce2ec0/librt-0.11.0-cp310-cp310-win32.whl", hash = "sha256:94663a21534637f0e787ec2a2a756022df6e5b7b2335a5cdd7d8e33d68a2af89", size = 100070, upload-time = "2026-05-10T18:15:32.551Z" }, - { url = "https://files.pythonhosted.org/packages/c6/0d/ebbcf4d77999c02c937b05d2b90ff4cd4dcc7e9a365ba132329ac1fe7a0f/librt-0.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:dec7db73758c2b54953fd8b7fe348c45188fe26b39ee18446196edd08453a5d4", size = 117918, upload-time = "2026-05-10T18:15:33.678Z" }, - { url = "https://files.pythonhosted.org/packages/fe/87/2bf31fe17587b29e3f93ec31421e2b1e1c3e349b8bf6c7c313dbad1d5340/librt-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:93d95bd45b7d58343d8b90d904450a545144eec19a002511163426f8ab1fae29", size = 141092, upload-time = "2026-05-10T18:15:34.795Z" }, - { url = "https://files.pythonhosted.org/packages/cf/08/5c5bf772920b7ebac6e32bc91a643e0ab3870199c0b542356d3baa83970a/librt-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ee278c769a713638cdacd4c0436d72156e75df3ebc0166ab2b9dc43acc386c9", size = 142035, upload-time = "2026-05-10T18:15:36.242Z" }, - { url = "https://files.pythonhosted.org/packages/06/20/662a03d254e5b000d838e8b345d83303ddb768c080fd488e40634c0fa66b/librt-0.11.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f230cb1cbc9faaa616f9a678f530ebcf186e414b6bcbd88b960e4ba1b92428d5", size = 475022, upload-time = "2026-05-10T18:15:37.56Z" }, - { url = "https://files.pythonhosted.org/packages/de/f3/aa81523e45184c6ec23dc7f63263362ec55f80a09d424c012359ecbe7e35/librt-0.11.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5d63c855d86938d9de93e265c9bd8c705b51ec494de5738340ee93767a686e4b", size = 467273, upload-time = "2026-05-10T18:15:39.182Z" }, - { url = "https://files.pythonhosted.org/packages/6b/6f/59c74b560ca8853834d5501d589c8a2519f4184f273a085ffd0f37a1cc47/librt-0.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f028be9e96a08d31df3479ac80d99be374d17f3b78e4796b3fd3c913d4e89", size = 497083, upload-time = "2026-05-10T18:15:40.634Z" }, - { url = "https://files.pythonhosted.org/packages/fe/7b/5aa4d2c9600a719401160bf7055417df0b2a47439b9d88286ce45e56b65f/librt-0.11.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:258d73a0aa66a055e65b2e4d1b8cdb23b9d132c5bb915d9547d804fcaed116cc", size = 489139, upload-time = "2026-05-10T18:15:41.934Z" }, - { url = "https://files.pythonhosted.org/packages/d6/31/9143803d7da6856a69153785768c4936864430eec0fd9461c3ea527d9922/librt-0.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0827efe7854718f04aaddf6496e96960a956e676fe1d0f04eb41511fd8ad06d5", size = 508442, upload-time = "2026-05-10T18:15:43.206Z" }, - { url = "https://files.pythonhosted.org/packages/2f/5a/bce08184488426bda4ccc2c4964ac048c8f68ae89bd7120082eef4233cfd/librt-0.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7753e57d6e12d019c0d8786f1c09c709f4c3fcc57c3887b24e36e6c06ec938b7", size = 514230, upload-time = "2026-05-10T18:15:44.761Z" }, - { url = "https://files.pythonhosted.org/packages/89/8c/bb5e213d254b7505a0e658da199d8ab719086632ce09eef311ab27976523/librt-0.11.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:11bd19822431cc21af9f27374e7ae2e58103c7d98bda823536a6c47f6bb2bb3d", size = 494231, upload-time = "2026-05-10T18:15:46.308Z" }, - { url = "https://files.pythonhosted.org/packages/9d/fb/541cdad5b1ab1300398c74c4c9a497b88e5074c21b1244c8f49731d3a284/librt-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:22bdf239b219d3993761a148ffa134b19e52e9989c84f845d5d7b71d70a17412", size = 537585, upload-time = "2026-05-10T18:15:47.629Z" }, - { url = "https://files.pythonhosted.org/packages/8f/f2/464bb69295c320cb06bddb4f14a4ec67934ee14b2bffb12b19fb7ab287ba/librt-0.11.0-cp311-cp311-win32.whl", hash = "sha256:46c60b61e308eb535fbd6fa622b1ee1bb2815691c1ad9c98bf7b84952ec3bc8d", size = 100509, upload-time = "2026-05-10T18:15:49.157Z" }, - { url = "https://files.pythonhosted.org/packages/6d/e7/a17ee1788f9e4fbf548c19f4afa07c92089b9e24fef6cb2410863781ef4c/librt-0.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:902e546ff044f579ff1c953ff5fce97b636fe9e3943996b2177710c6ef076f73", size = 118628, upload-time = "2026-05-10T18:15:50.345Z" }, - { url = "https://files.pythonhosted.org/packages/cc/c7/6c766214f9f9903bcfcfbef97d807af8d8f5aa3502d247858ab17582d212/librt-0.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:65ac3bc20f78aa0ee5ae84baa68917f89fef4af63e941084dd019a0d0e749f0c", size = 103122, upload-time = "2026-05-10T18:15:52.068Z" }, - { url = "https://files.pythonhosted.org/packages/8b/d0/07c77e067f0838949b43bd89232c29d72efebb9d2801a9750184eb706b71/librt-0.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b87504f1690a23b9a2cca841191a04f83895d4fc2dd04df91d82b1a04ca2ad46", size = 144147, upload-time = "2026-05-10T18:15:53.227Z" }, - { url = "https://files.pythonhosted.org/packages/7a/24/8493538fa4f62f982686398a5b8f68008138a75086abdea19ade64bf4255/librt-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40071fc5fe0ce8daa6de616702314a01e1250711682b0523d6ab8d4525910cb3", size = 143614, upload-time = "2026-05-10T18:15:54.657Z" }, - { url = "https://files.pythonhosted.org/packages/ff/1e/f8bad050810d9171f34a1648ed910e56814c2ba61639f2bd53c6377ae24b/librt-0.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:137e79445c896a0ea7b265f52d23954e05b64222ee1af69e2cb34219067cbb67", size = 485538, upload-time = "2026-05-10T18:15:56.117Z" }, - { url = "https://files.pythonhosted.org/packages/c0/fe/3594ebfbaf03084ba4b120c9ba5c3183fd938a48725e9bbe6ff0a5159ad8/librt-0.11.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:cca6644054e78746d8d4ef238681f9c34ff8b584fe6b988ecebb8db3b15e622a", size = 479623, upload-time = "2026-05-10T18:15:57.544Z" }, - { url = "https://files.pythonhosted.org/packages/b0/da/5d1876984b3746c85dbd219dbfcb73c85f54ee263fd32e5b2a632ec14571/librt-0.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5b0eea49f5562861ee8d757a32ef7d559c1d35be2aaaa1ec28941d74c9ffc8a", size = 513082, upload-time = "2026-05-10T18:15:58.805Z" }, - { url = "https://files.pythonhosted.org/packages/19/6e/55bdf5d5ca00c3e18430690bf2c953d8d3ffd3c337418173d33dec985dc9/librt-0.11.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0d1029d7e1ae1a7e647ed6fb5df8c4ce2dffefb7a9f5fd1376a4554d96dac09f", size = 508105, upload-time = "2026-05-10T18:16:00.2Z" }, - { url = "https://files.pythonhosted.org/packages/07/10/f1f23a7c595ee90ece4d35c851e5d104b1311a887ed1b4ac4c35bbd13da8/librt-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bc3ce6b33c5828d9e80592011a5c584cb2ce86edbc4088405f70da47dc1d1b3b", size = 522268, upload-time = "2026-05-10T18:16:01.708Z" }, - { url = "https://files.pythonhosted.org/packages/b6/02/5720f5697a7f54b78b3aefbe20df3a48cedcff1276618c4aa481177942ed/librt-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:936c5995f3514a42111f20099397d8177c79b4d7e70961e396c6f5a0a3566766", size = 527348, upload-time = "2026-05-10T18:16:03.496Z" }, - { url = "https://files.pythonhosted.org/packages/50/db/b4a47c6f91db4ff76348a0b3dd0cc65e090a078b765a810a62ff9434c3d3/librt-0.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9bc0ca6ad9381cbe8e4aa6e5726e4c80c78115a6e9723c599ed1d73e092bc49d", size = 516294, upload-time = "2026-05-10T18:16:05.173Z" }, - { url = "https://files.pythonhosted.org/packages/9e/58/9384b2f4eb1ed1d273d40948a7c5c4b2360213b402ef3be4641c06299f9c/librt-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:070aa8c26c0a74774317a72df8851facc7f0f012a5b406557ac56992d92e1ec8", size = 553608, upload-time = "2026-05-10T18:16:06.839Z" }, - { url = "https://files.pythonhosted.org/packages/21/7b/5aa8848a7c6a9278c79375146da1812e695754ceec5f005e6043461a7315/librt-0.11.0-cp312-cp312-win32.whl", hash = "sha256:6bf14feb84b05ae945277395451998c89c54d0def4070eb5c08de544930b245a", size = 101879, upload-time = "2026-05-10T18:16:08.103Z" }, - { url = "https://files.pythonhosted.org/packages/37/33/8a745436944947575b584231750a41417de1a38cf6a2e9251d1065651c09/librt-0.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:75672f0bc524ede266287d532d7923dbce94c7514ad07627bac3d0c6d92cc4d9", size = 119831, upload-time = "2026-05-10T18:16:09.174Z" }, - { url = "https://files.pythonhosted.org/packages/59/67/a6739ac96e28b7855808bdb0370e250606104a859750d209e5a0716fe7ab/librt-0.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c", size = 103470, upload-time = "2026-05-10T18:16:10.369Z" }, - { url = "https://files.pythonhosted.org/packages/82/61/e59168d4d0bf2bf90f4f0caf7a001bfc60254c3af4586013b04dc3ef517b/librt-0.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:78dc31f7fdfe9c9d0eb0e8f42d139db230e826415bbcabd9f0e9faaaee909894", size = 144119, upload-time = "2026-05-10T18:16:11.771Z" }, - { url = "https://files.pythonhosted.org/packages/61/fd/caa1d60b12f7dd79ccea23054e06eeaebe266a5f52c40a6b651069200ce5/librt-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fa475675db22290c3158e1d42326d0f5a65f04f44a0e68c3630a25b53560fb9c", size = 143565, upload-time = "2026-05-10T18:16:13.334Z" }, - { url = "https://files.pythonhosted.org/packages/b8/a9/dc744f5c2b4978d48db970be29f22716d3413d28b14ad99740817315cf2c/librt-0.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:621db29691044bdeda22e789e482e1b0f3a985d90e3426c9c6d17606416205ea", size = 485395, upload-time = "2026-05-10T18:16:14.729Z" }, - { url = "https://files.pythonhosted.org/packages/8f/21/7f8e97a1e4dae952a5a95948f6f8507a173bc1e669f54340bba6ca1ca31b/librt-0.11.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a9010e2ed5b3a9e158c5fd966b3ab7e834bb3d3aacc8f66c91dd4b57a3799230", size = 479383, upload-time = "2026-05-10T18:16:16.321Z" }, - { url = "https://files.pythonhosted.org/packages/a6/6d/d8ee9c114bebf2c50e29ec2aa940826fccb62a645c3e4c18760987d0e16d/librt-0.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c39513d8b7477a2e1ed8c43fc21c524e8d5a0f8d4e8b7b074dbdbe7820a08e2", size = 513010, upload-time = "2026-05-10T18:16:17.647Z" }, - { url = "https://files.pythonhosted.org/packages/f0/43/0b5708af2bd30a46400e72ba6bdaa8f066f15fb9a688527e34220e8d6c06/librt-0.11.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7aef3cf1d5af86e770ab04bfd993dfc4ae8b8c17f66fb77dd4a7d50de7bbb1a3", size = 508433, upload-time = "2026-05-10T18:16:19.309Z" }, - { url = "https://files.pythonhosted.org/packages/4a/50/356187247d09013490481033183b3532b58acf8028bcb34b2b56a375c9b2/librt-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:557183ddc36babe46b27dd60facbd5adb4492181a5be887587d57cda6e092f21", size = 522595, upload-time = "2026-05-10T18:16:20.642Z" }, - { url = "https://files.pythonhosted.org/packages/40/e7/c6ac4240899c7f3248079d5a9900debe0dadb3fdeaf856684c987105ba47/librt-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83d3e1f72bd42f6c5c0b7daec530c3f829bd02db42c70b8ddf0c2d90a2459930", size = 527255, upload-time = "2026-05-10T18:16:22.352Z" }, - { url = "https://files.pythonhosted.org/packages/eb/b5/a81322dbeedeeaf9c1ee6f001734d28a09d8383ac9e6779bc24bbd0743c6/librt-0.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4ce1f21fbe589bc1afd7872dece84fb0e1144f794a288e58a10d2c54a55c43be", size = 516847, upload-time = "2026-05-10T18:16:23.627Z" }, - { url = "https://files.pythonhosted.org/packages/ae/66/6e6323787d592b55204a42595ff1102da5115601b53a7e9ddebc889a6da5/librt-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b09f7044ea2b64c9da42fd3d335666518cfd1c6e8a182c95da73d0214b41e", size = 553920, upload-time = "2026-05-10T18:16:25.025Z" }, - { url = "https://files.pythonhosted.org/packages/9c/21/623f8ca230857102066d9ca8c6c1734995908c4d0d1bee7bb2ef0021cb33/librt-0.11.0-cp313-cp313-win32.whl", hash = "sha256:78fddc31cd4d3caa897ad5d31f856b1faadc9474021ad6cb182b9018793e254e", size = 101898, upload-time = "2026-05-10T18:16:26.649Z" }, - { url = "https://files.pythonhosted.org/packages/b3/1d/b4ebd44dd723f768469007515cb92251e0ae286c94c140f374801140fa74/librt-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ca8aa88751a775870b764e93bad5135385f563cb8dcee399abf034ea4d3cb47", size = 119812, upload-time = "2026-05-10T18:16:27.859Z" }, - { url = "https://files.pythonhosted.org/packages/3b/e4/b2f4ca7965ca373b491cdb4bc25cdb30c1649ca81a8782056a83850292a9/librt-0.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:96f044bb325fd9cf1a723015638c219e9143f0dfbc0ca54c565df2b7fc748b44", size = 103448, upload-time = "2026-05-10T18:16:29.066Z" }, -] - [[package]] name = "litellm" version = "1.89.0" @@ -3441,7 +3382,6 @@ dev = [ { name = "fastapi-offline" }, { name = "flake8" }, { name = "langfuse" }, - { name = "mypy" }, { name = "openapi-core" }, { name = "opentelemetry-api" }, { name = "opentelemetry-exporter-otlp" }, @@ -3609,7 +3549,6 @@ dev = [ { name = "fastapi-offline", specifier = "==1.7.6" }, { name = "flake8", specifier = "==7.3.0" }, { name = "langfuse", specifier = "==2.59.7" }, - { name = "mypy", specifier = "==1.19.0" }, { name = "openapi-core", marker = "python_full_version < '3.14'", specifier = "==0.22.0" }, { name = "opentelemetry-api", specifier = "==1.28.0" }, { name = "opentelemetry-exporter-otlp", specifier = "==1.28.0" }, @@ -4224,46 +4163,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" }, ] -[[package]] -name = "mypy" -version = "1.19.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "librt" }, - { name = "mypy-extensions" }, - { name = "pathspec" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f9/b5/b58cdc25fadd424552804bf410855d52324183112aa004f0732c5f6324cf/mypy-1.19.0.tar.gz", hash = "sha256:f6b874ca77f733222641e5c46e4711648c4037ea13646fd0cdc814c2eaec2528", size = 3579025, upload-time = "2025-11-28T15:49:01.26Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/98/8f/55fb488c2b7dabd76e3f30c10f7ab0f6190c1fcbc3e97b1e588ec625bbe2/mypy-1.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6148ede033982a8c5ca1143de34c71836a09f105068aaa8b7d5edab2b053e6c8", size = 13093239, upload-time = "2025-11-28T15:45:11.342Z" }, - { url = "https://files.pythonhosted.org/packages/72/1b/278beea978456c56b3262266274f335c3ba5ff2c8108b3b31bec1ffa4c1d/mypy-1.19.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a9ac09e52bb0f7fb912f5d2a783345c72441a08ef56ce3e17c1752af36340a39", size = 12156128, upload-time = "2025-11-28T15:46:02.566Z" }, - { url = "https://files.pythonhosted.org/packages/21/f8/e06f951902e136ff74fd7a4dc4ef9d884faeb2f8eb9c49461235714f079f/mypy-1.19.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f7254c15ab3f8ed68f8e8f5cbe88757848df793e31c36aaa4d4f9783fd08ab", size = 12753508, upload-time = "2025-11-28T15:44:47.538Z" }, - { url = "https://files.pythonhosted.org/packages/67/5a/d035c534ad86e09cee274d53cf0fd769c0b29ca6ed5b32e205be3c06878c/mypy-1.19.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318ba74f75899b0e78b847d8c50821e4c9637c79d9a59680fc1259f29338cb3e", size = 13507553, upload-time = "2025-11-28T15:44:39.26Z" }, - { url = "https://files.pythonhosted.org/packages/6a/17/c4a5498e00071ef29e483a01558b285d086825b61cf1fb2629fbdd019d94/mypy-1.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cf7d84f497f78b682edd407f14a7b6e1a2212b433eedb054e2081380b7395aa3", size = 13792898, upload-time = "2025-11-28T15:44:31.102Z" }, - { url = "https://files.pythonhosted.org/packages/67/f6/bb542422b3ee4399ae1cdc463300d2d91515ab834c6233f2fd1d52fa21e0/mypy-1.19.0-cp310-cp310-win_amd64.whl", hash = "sha256:c3385246593ac2b97f155a0e9639be906e73534630f663747c71908dfbf26134", size = 10048835, upload-time = "2025-11-28T15:48:15.744Z" }, - { url = "https://files.pythonhosted.org/packages/0f/d2/010fb171ae5ac4a01cc34fbacd7544531e5ace95c35ca166dd8fd1b901d0/mypy-1.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a31e4c28e8ddb042c84c5e977e28a21195d086aaffaf08b016b78e19c9ef8106", size = 13010563, upload-time = "2025-11-28T15:48:23.975Z" }, - { url = "https://files.pythonhosted.org/packages/41/6b/63f095c9f1ce584fdeb595d663d49e0980c735a1d2004720ccec252c5d47/mypy-1.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34ec1ac66d31644f194b7c163d7f8b8434f1b49719d403a5d26c87fff7e913f7", size = 12077037, upload-time = "2025-11-28T15:47:51.582Z" }, - { url = "https://files.pythonhosted.org/packages/d7/83/6cb93d289038d809023ec20eb0b48bbb1d80af40511fa077da78af6ff7c7/mypy-1.19.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb64b0ba5980466a0f3f9990d1c582bcab8db12e29815ecb57f1408d99b4bff7", size = 12680255, upload-time = "2025-11-28T15:46:57.628Z" }, - { url = "https://files.pythonhosted.org/packages/99/db/d217815705987d2cbace2edd9100926196d6f85bcb9b5af05058d6e3c8ad/mypy-1.19.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:120cffe120cca5c23c03c77f84abc0c14c5d2e03736f6c312480020082f1994b", size = 13421472, upload-time = "2025-11-28T15:47:59.655Z" }, - { url = "https://files.pythonhosted.org/packages/4e/51/d2beaca7c497944b07594f3f8aad8d2f0e8fc53677059848ae5d6f4d193e/mypy-1.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7a500ab5c444268a70565e374fc803972bfd1f09545b13418a5174e29883dab7", size = 13651823, upload-time = "2025-11-28T15:45:29.318Z" }, - { url = "https://files.pythonhosted.org/packages/aa/d1/7883dcf7644db3b69490f37b51029e0870aac4a7ad34d09ceae709a3df44/mypy-1.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:c14a98bc63fd867530e8ec82f217dae29d0550c86e70debc9667fff1ec83284e", size = 10049077, upload-time = "2025-11-28T15:45:39.818Z" }, - { url = "https://files.pythonhosted.org/packages/11/7e/1afa8fb188b876abeaa14460dc4983f909aaacaa4bf5718c00b2c7e0b3d5/mypy-1.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0fb3115cb8fa7c5f887c8a8d81ccdcb94cff334684980d847e5a62e926910e1d", size = 13207728, upload-time = "2025-11-28T15:46:26.463Z" }, - { url = "https://files.pythonhosted.org/packages/b2/13/f103d04962bcbefb1644f5ccb235998b32c337d6c13145ea390b9da47f3e/mypy-1.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3e19e3b897562276bb331074d64c076dbdd3e79213f36eed4e592272dabd760", size = 12202945, upload-time = "2025-11-28T15:48:49.143Z" }, - { url = "https://files.pythonhosted.org/packages/e4/93/a86a5608f74a22284a8ccea8592f6e270b61f95b8588951110ad797c2ddd/mypy-1.19.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9d491295825182fba01b6ffe2c6fe4e5a49dbf4e2bb4d1217b6ced3b4797bc6", size = 12718673, upload-time = "2025-11-28T15:47:37.193Z" }, - { url = "https://files.pythonhosted.org/packages/3d/58/cf08fff9ced0423b858f2a7495001fda28dc058136818ee9dffc31534ea9/mypy-1.19.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6016c52ab209919b46169651b362068f632efcd5eb8ef9d1735f6f86da7853b2", size = 13608336, upload-time = "2025-11-28T15:48:32.625Z" }, - { url = "https://files.pythonhosted.org/packages/64/ed/9c509105c5a6d4b73bb08733102a3ea62c25bc02c51bca85e3134bf912d3/mypy-1.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f188dcf16483b3e59f9278c4ed939ec0254aa8a60e8fc100648d9ab5ee95a431", size = 13833174, upload-time = "2025-11-28T15:45:48.091Z" }, - { url = "https://files.pythonhosted.org/packages/cd/71/01939b66e35c6f8cb3e6fdf0b657f0fd24de2f8ba5e523625c8e72328208/mypy-1.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:0e3c3d1e1d62e678c339e7ade72746a9e0325de42cd2cccc51616c7b2ed1a018", size = 10112208, upload-time = "2025-11-28T15:46:41.702Z" }, - { url = "https://files.pythonhosted.org/packages/cb/0d/a1357e6bb49e37ce26fcf7e3cc55679ce9f4ebee0cd8b6ee3a0e301a9210/mypy-1.19.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7686ed65dbabd24d20066f3115018d2dce030d8fa9db01aa9f0a59b6813e9f9e", size = 13191993, upload-time = "2025-11-28T15:47:22.336Z" }, - { url = "https://files.pythonhosted.org/packages/5d/75/8e5d492a879ec4490e6ba664b5154e48c46c85b5ac9785792a5ec6a4d58f/mypy-1.19.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fd4a985b2e32f23bead72e2fb4bbe5d6aceee176be471243bd831d5b2644672d", size = 12174411, upload-time = "2025-11-28T15:44:55.492Z" }, - { url = "https://files.pythonhosted.org/packages/71/31/ad5dcee9bfe226e8eaba777e9d9d251c292650130f0450a280aec3485370/mypy-1.19.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fc51a5b864f73a3a182584b1ac75c404396a17eced54341629d8bdcb644a5bba", size = 12727751, upload-time = "2025-11-28T15:44:14.169Z" }, - { url = "https://files.pythonhosted.org/packages/77/06/b6b8994ce07405f6039701f4b66e9d23f499d0b41c6dd46ec28f96d57ec3/mypy-1.19.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:37af5166f9475872034b56c5efdcf65ee25394e9e1d172907b84577120714364", size = 13593323, upload-time = "2025-11-28T15:46:34.699Z" }, - { url = "https://files.pythonhosted.org/packages/68/b1/126e274484cccdf099a8e328d4fda1c7bdb98a5e888fa6010b00e1bbf330/mypy-1.19.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:510c014b722308c9bd377993bcbf9a07d7e0692e5fa8fc70e639c1eb19fc6bee", size = 13818032, upload-time = "2025-11-28T15:46:18.286Z" }, - { url = "https://files.pythonhosted.org/packages/f8/56/53a8f70f562dfc466c766469133a8a4909f6c0012d83993143f2a9d48d2d/mypy-1.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:cabbee74f29aa9cd3b444ec2f1e4fa5a9d0d746ce7567a6a609e224429781f53", size = 10120644, upload-time = "2025-11-28T15:47:43.99Z" }, - { url = "https://files.pythonhosted.org/packages/09/0e/fe228ed5aeab470c6f4eb82481837fadb642a5aa95cc8215fd2214822c10/mypy-1.19.0-py3-none-any.whl", hash = "sha256:0c01c99d626380752e527d5ce8e69ffbba2046eb8a060db0329690849cf9b6f9", size = 2469714, upload-time = "2025-11-28T15:45:33.22Z" }, -] - [[package]] name = "mypy-extensions" version = "1.1.0"