Skip to content

Commit 3473b86

Browse files
authored
Merge pull request #92 from CartoDB/upstream-sync/v1.81.9-stable
🔄 Upstream Sync: LiteLLM v1.81.9-stable
2 parents be7f073 + 4a2426e commit 3473b86

1,079 files changed

Lines changed: 65187 additions & 29097 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.circleci/config.yml

Lines changed: 122 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,7 +1255,15 @@ jobs:
12551255
ls
12561256
# Add --timeout to kill hanging tests after 120s (2 min)
12571257
# Add --durations=20 to show 20 slowest tests for debugging
1258-
python -m pytest -vv tests/llm_translation --cov=litellm --cov-report=xml -v --junitxml=test-results/junit.xml --durations=20 -n 4 --timeout=120 --timeout_method=thread
1258+
# Subdirectories with dedicated jobs (maintain this list as new jobs are added)
1259+
IGNORE_DIRS=(
1260+
"tests/llm_translation/realtime"
1261+
)
1262+
IGNORE_ARGS=""
1263+
for dir in "${IGNORE_DIRS[@]}"; do
1264+
IGNORE_ARGS="$IGNORE_ARGS --ignore=$dir"
1265+
done
1266+
python -m pytest -vv tests/llm_translation $IGNORE_ARGS --cov=litellm --cov-report=xml -v --junitxml=test-results/junit.xml --durations=20 -n 4 --timeout=120 --timeout_method=thread
12591267
no_output_timeout: 120m
12601268
- run:
12611269
name: Rename the coverage files
@@ -1271,6 +1279,54 @@ jobs:
12711279
paths:
12721280
- llm_translation_coverage.xml
12731281
- llm_translation_coverage
1282+
realtime_translation_testing:
1283+
docker:
1284+
- image: cimg/python:3.11
1285+
auth:
1286+
username: ${DOCKERHUB_USERNAME}
1287+
password: ${DOCKERHUB_PASSWORD}
1288+
working_directory: ~/project
1289+
1290+
steps:
1291+
- checkout
1292+
- setup_google_dns
1293+
- run:
1294+
name: Install Dependencies
1295+
command: |
1296+
python -m pip install --upgrade pip
1297+
python -m pip install -r requirements.txt
1298+
pip install "pytest==7.3.1"
1299+
pip install "pytest-retry==1.6.3"
1300+
pip install "pytest-cov==5.0.0"
1301+
pip install "pytest-asyncio==0.21.1"
1302+
pip install "respx==0.22.0"
1303+
pip install "pytest-xdist==3.6.1"
1304+
pip install "pytest-timeout==2.2.0"
1305+
pip install "websockets"
1306+
# Run pytest and generate JUnit XML report
1307+
- run:
1308+
name: Run realtime tests
1309+
command: |
1310+
pwd
1311+
ls
1312+
# Add --timeout to kill hanging tests after 120s (2 min)
1313+
# Add --durations=20 to show 20 slowest tests for debugging
1314+
python -m pytest -vv tests/llm_translation/realtime --cov=litellm --cov-report=xml -v --junitxml=test-results/junit.xml --durations=20 -n 4 --timeout=120 --timeout_method=thread
1315+
no_output_timeout: 120m
1316+
- run:
1317+
name: Rename the coverage files
1318+
command: |
1319+
mv coverage.xml realtime_translation_coverage.xml
1320+
mv .coverage realtime_translation_coverage
1321+
1322+
# Store test results
1323+
- store_test_results:
1324+
path: test-results
1325+
- persist_to_workspace:
1326+
root: .
1327+
paths:
1328+
- realtime_translation_coverage.xml
1329+
- realtime_translation_coverage
12741330
mcp_testing:
12751331
docker:
12761332
- image: cimg/python:3.11
@@ -1316,6 +1372,51 @@ jobs:
13161372
paths:
13171373
- mcp_coverage.xml
13181374
- mcp_coverage
1375+
agent_testing:
1376+
docker:
1377+
- image: cimg/python:3.11
1378+
auth:
1379+
username: ${DOCKERHUB_USERNAME}
1380+
password: ${DOCKERHUB_PASSWORD}
1381+
working_directory: ~/project
1382+
1383+
steps:
1384+
- checkout
1385+
- setup_google_dns
1386+
- run:
1387+
name: Install Dependencies
1388+
command: |
1389+
python -m pip install --upgrade pip
1390+
python -m pip install -r requirements.txt
1391+
pip install "pytest==7.3.1"
1392+
pip install "pytest-retry==1.6.3"
1393+
pip install "pytest-cov==5.0.0"
1394+
pip install "pytest-asyncio==0.21.1"
1395+
pip install "respx==0.22.0"
1396+
pip install "pydantic==2.11.0"
1397+
pip install "a2a-sdk"
1398+
# Run pytest and generate JUnit XML report
1399+
- run:
1400+
name: Run tests
1401+
command: |
1402+
pwd
1403+
ls
1404+
python -m pytest -vv tests/agent_tests --ignore=tests/agent_tests/local_only_agent_tests --cov=litellm --cov-report=xml -x -s -v --junitxml=test-results/junit.xml --durations=5
1405+
no_output_timeout: 120m
1406+
- run:
1407+
name: Rename the coverage files
1408+
command: |
1409+
mv coverage.xml agent_coverage.xml
1410+
mv .coverage agent_coverage
1411+
1412+
# Store test results
1413+
- store_test_results:
1414+
path: test-results
1415+
- persist_to_workspace:
1416+
root: .
1417+
paths:
1418+
- agent_coverage.xml
1419+
- agent_coverage
13191420
guardrails_testing:
13201421
docker:
13211422
- image: cimg/python:3.11
@@ -3532,7 +3633,7 @@ jobs:
35323633
python -m venv venv
35333634
. venv/bin/activate
35343635
pip install coverage
3535-
coverage combine llm_translation_coverage llm_responses_api_coverage ocr_coverage search_coverage mcp_coverage logging_coverage audio_coverage litellm_router_coverage litellm_router_unit_coverage local_testing_part1_coverage local_testing_part2_coverage litellm_assistants_api_coverage auth_ui_unit_tests_coverage langfuse_coverage caching_coverage litellm_proxy_unit_tests_part1_coverage litellm_proxy_unit_tests_part2_coverage image_gen_coverage pass_through_unit_tests_coverage batches_coverage litellm_security_tests_coverage guardrails_coverage litellm_mapped_tests_coverage
3636+
coverage combine llm_translation_coverage realtime_translation_coverage llm_responses_api_coverage ocr_coverage search_coverage mcp_coverage logging_coverage audio_coverage litellm_router_coverage litellm_router_unit_coverage local_testing_part1_coverage local_testing_part2_coverage litellm_assistants_api_coverage auth_ui_unit_tests_coverage langfuse_coverage caching_coverage litellm_proxy_unit_tests_part1_coverage litellm_proxy_unit_tests_part2_coverage image_gen_coverage pass_through_unit_tests_coverage batches_coverage litellm_security_tests_coverage guardrails_coverage litellm_mapped_tests_coverage
35363637
coverage xml
35373638
- codecov/upload:
35383639
file: ./coverage.xml
@@ -3754,6 +3855,9 @@ jobs:
37543855
37553856
cd ui/litellm-dashboard
37563857
3858+
# Remove node_modules and package-lock to ensure clean install (fixes dependency resolution issues)
3859+
rm -rf node_modules package-lock.json
3860+
37573861
# Install dependencies first
37583862
npm install
37593863
@@ -4193,12 +4297,24 @@ workflows:
41934297
only:
41944298
- main
41954299
- /litellm_.*/
4300+
- realtime_translation_testing:
4301+
filters:
4302+
branches:
4303+
only:
4304+
- main
4305+
- /litellm_.*/
41964306
- mcp_testing:
41974307
filters:
41984308
branches:
41994309
only:
42004310
- main
42014311
- /litellm_.*/
4312+
- agent_testing:
4313+
filters:
4314+
branches:
4315+
only:
4316+
- main
4317+
- /litellm_.*/
42024318
- guardrails_testing:
42034319
filters:
42044320
branches:
@@ -4304,7 +4420,9 @@ workflows:
43044420
- upload-coverage:
43054421
requires:
43064422
- llm_translation_testing
4423+
- realtime_translation_testing
43074424
- mcp_testing
4425+
- agent_testing
43084426
- google_generate_content_endpoint_testing
43094427
- guardrails_testing
43104428
- llm_responses_api_testing
@@ -4381,7 +4499,9 @@ workflows:
43814499
- e2e_openai_endpoints
43824500
- test_bad_database_url
43834501
- llm_translation_testing
4502+
- realtime_translation_testing
43844503
- mcp_testing
4504+
- agent_testing
43854505
- google_generate_content_endpoint_testing
43864506
- llm_responses_api_testing
43874507
- ocr_testing

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ LiteLLM is a unified interface for 100+ LLM providers with two main components:
9090
- Pydantic v2 for data validation
9191
- Async/await patterns throughout
9292
- Type hints required for all public APIs
93+
- **Avoid imports within methods** — place all imports at the top of the file (module-level). Inline imports inside functions/methods make dependencies harder to trace and hurt readability. The only exception is avoiding circular imports where absolutely necessary.
9394

9495
### Testing Strategy
9596
- Unit tests in `tests/test_litellm/`

Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ ARG LITELLM_BUILD_IMAGE=cgr.dev/chainguard/wolfi-base
33

44
# Runtime image
55
ARG LITELLM_RUNTIME_IMAGE=cgr.dev/chainguard/wolfi-base
6+
67
# Builder stage
78
FROM $LITELLM_BUILD_IMAGE AS builder
89

@@ -62,6 +63,10 @@ COPY --from=builder /wheels/ /wheels/
6263
# Install the built wheel using pip; again using a wildcard if it's the only file
6364
RUN pip install *.whl /wheels/* --no-index --find-links=/wheels/ && rm -f *.whl && rm -rf /wheels
6465

66+
# Replace the nodejs-wheel-binaries bundled node with the system node (fixes CVE-2025-55130)
67+
RUN NODEJS_WHEEL_NODE=$(find /usr/lib -path "*/nodejs_wheel/bin/node" 2>/dev/null) && \
68+
if [ -n "$NODEJS_WHEEL_NODE" ]; then cp /usr/bin/node "$NODEJS_WHEEL_NODE"; fi
69+
6570
# Remove test files and keys from dependencies
6671
RUN find /usr/lib -type f -path "*/tornado/test/*" -delete && \
6772
find /usr/lib -type d -path "*/tornado/test" -delete

Makefile

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
# LiteLLM Makefile
22
# Simple Makefile for running tests and basic development tasks
33

4-
.PHONY: help test test-unit test-integration test-unit-helm lint format install-dev install-proxy-dev install-test-deps install-helm-unittest check-circular-imports check-import-safety
4+
.PHONY: help test test-unit test-integration test-unit-helm \
5+
info lint lint-dev format \
6+
install-dev install-proxy-dev install-test-deps \
7+
install-helm-unittest check-circular-imports check-import-safety
58

69
# Default target
710
help:
@@ -25,6 +28,13 @@ help:
2528
@echo " make test-integration - Run integration tests"
2629
@echo " make test-unit-helm - Run helm unit tests"
2730

31+
# Keep PIP simple for edge cases:
32+
PIP := $(shell command -v pip > /dev/null 2>&1 && echo "pip" || echo "python3 -m pip")
33+
34+
# Show info
35+
info:
36+
@echo "PIP: $(PIP)"
37+
2838
# Installation targets
2939
install-dev:
3040
poetry install --with dev
@@ -34,19 +44,19 @@ install-proxy-dev:
3444

3545
# CI-compatible installations (matches GitHub workflows exactly)
3646
install-dev-ci:
37-
pip install openai==2.8.0
47+
$(PIP) install openai==2.8.0
3848
poetry install --with dev
39-
pip install openai==2.8.0
49+
$(PIP) install openai==2.8.0
4050

4151
install-proxy-dev-ci:
4252
poetry install --with dev,proxy-dev --extras proxy
43-
pip install openai==2.8.0
53+
$(PIP) install openai==2.8.0
4454

4555
install-test-deps: install-proxy-dev
46-
poetry run pip install "pytest-retry==1.6.3"
47-
poetry run pip install pytest-xdist
48-
poetry run pip install openapi-core
49-
cd enterprise && poetry run pip install -e . && cd ..
56+
poetry run $(PIP) install "pytest-retry==1.6.3"
57+
poetry run $(PIP) install pytest-xdist
58+
poetry run $(PIP) install openapi-core
59+
cd enterprise && poetry run $(PIP) install -e . && cd ..
5060

5161
install-helm-unittest:
5262
helm plugin install https://github.com/helm-unittest/helm-unittest --version v0.4.4 || echo "ignore error if plugin exists"
@@ -62,8 +72,40 @@ format-check: install-dev
6272
lint-ruff: install-dev
6373
cd litellm && poetry run ruff check . && cd ..
6474

75+
# faster linter for developing ...
76+
# inspiration from:
77+
# https://github.com/astral-sh/ruff/discussions/10977
78+
# https://github.com/astral-sh/ruff/discussions/4049
79+
lint-format-changed: install-dev
80+
@git diff origin/main --unified=0 --no-color -- '*.py' | \
81+
perl -ne '\
82+
if (/^diff --git a\/(.*) b\//) { $$file = $$1; } \
83+
if (/^@@ .* \+(\d+)(?:,(\d+))? @@/) { \
84+
$$start = $$1; $$count = $$2 || 1; $$end = $$start + $$count - 1; \
85+
print "$$file:$$start:1-$$end:999\n"; \
86+
}' | \
87+
while read range; do \
88+
file="$${range%%:*}"; \
89+
lines="$${range#*:}"; \
90+
echo "Formatting $$file (lines $$lines)"; \
91+
poetry run ruff format --range "$$lines" "$$file"; \
92+
done
93+
94+
lint-ruff-dev: install-dev
95+
@tmpfile=$$(mktemp /tmp/ruff-dev.XXXXXX) && \
96+
cd litellm && \
97+
(poetry run ruff check . --output-format=pylint || true) > "$$tmpfile" && \
98+
poetry run diff-quality --violations=pylint "$$tmpfile" --compare-branch=origin/main && \
99+
cd .. ; \
100+
rm -f "$$tmpfile"
101+
102+
lint-ruff-FULL-dev: install-dev
103+
@files=$$(git diff --name-only origin/main -- '*.py'); \
104+
if [ -n "$$files" ]; then echo "$$files" | xargs poetry run ruff check; \
105+
else echo "No changed .py files to check."; fi
106+
65107
lint-mypy: install-dev
66-
poetry run pip install types-requests types-setuptools types-redis types-PyYAML
108+
poetry run $(PIP) install types-requests types-setuptools types-redis types-PyYAML
67109
cd litellm && poetry run mypy . --ignore-missing-imports && cd ..
68110

69111
lint-black: format-check
@@ -72,11 +114,14 @@ check-circular-imports: install-dev
72114
cd litellm && poetry run python ../tests/documentation_tests/test_circular_imports.py && cd ..
73115

74116
check-import-safety: install-dev
75-
poetry run python -c "from litellm import *" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1)
117+
@poetry run python -c "from litellm import *; print('[from litellm import *] OK! no issues!');" || (echo '🚨 import failed, this means you introduced unprotected imports! 🚨'; exit 1)
76118

77119
# Combined linting (matches test-linting.yml workflow)
78120
lint: format-check lint-ruff lint-mypy check-circular-imports check-import-safety
79121

122+
# Faster linting for local development (only checks changed code)
123+
lint-dev: lint-format-changed lint-mypy check-circular-imports check-import-safety
124+
80125
# Testing targets
81126
test:
82127
poetry run pytest tests/

ci_cd/security_scans.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,11 @@ run_grype_scans() {
154154
"CVE-2025-15367" # No fix available yet
155155
"CVE-2025-12781" # No fix available yet
156156
"CVE-2025-11468" # No fix available yet
157+
"CVE-2026-1299" # Python 3.13 email module header injection - not applicable, LiteLLM doesn't use BytesGenerator for email serialization
158+
"GHSA-7h2j-956f-4vf2" # @isaacs/brace-expansion ReDoS - npm tooling dependency, not used in application runtime
159+
"GHSA-hx9q-6w63-j58v" # orjson deep recursion - no fix available yet
160+
"GHSA-8qq5-rm4j-mr97" # node-tar symlink poisoning - npm tooling dependency, tar CLI not exposed in application code
161+
"GHSA-29xp-372q-xqph" # node-tar race condition - npm tooling dependency, tar CLI not exposed in application code
157162
)
158163

159164
# Build JSON array of allowlisted CVE IDs for jq

0 commit comments

Comments
 (0)