Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
30ca2a3
Redis quick patch
jatorre Jul 16, 2025
8e5dd6f
ensure streaming chunk IDs use consistent encoding format
jatorre Jul 16, 2025
ebcaa26
fix(responses): ensure streaming chunk IDs use consistent encoding fo…
jatorre Jul 16, 2025
af6862a
fix(types): add explicit Optional[str] type annotation for model_id
jatorre Jul 16, 2025
53b2346
fix(types): handle None case for litellm_metadata access
jatorre Jul 16, 2025
582a263
test: add comprehensive tests for streaming ID consistency
jatorre Jul 16, 2025
4c84225
fix(lint): remove unused imports in transformation.py
jatorre Jul 16, 2025
6fa10e9
test: remove E2E tests from openai_endpoints_tests
jatorre Jul 16, 2025
95621e2
revert: remove streaming chunk ID encoding to original behavior
jatorre Jul 16, 2025
120c197
fix(responses): encode streaming final response IDs to match OpenAI b…
jatorre Jul 16, 2025
117dd8a
test: update unit test to match correct OpenAI-compatible behavior
jatorre Jul 16, 2025
762246a
Modify CI for Docker build
mateo-di Jul 28, 2025
ac7d257
Modify CI for Docker build
mateo-di Jul 28, 2025
68da968
Modify CI for Docker build
mateo-di Jul 28, 2025
911a97f
Add ghcr_carto_deploy and comment old litellm one
mateo-di Jul 28, 2025
e2874b4
optimize ghcr_carto_deploy
mateo-di Jul 28, 2025
81bb84c
optimize ghcr_carto_deploy
mateo-di Jul 28, 2025
9db2219
optimize ghcr_carto_deploy
mateo-di Jul 28, 2025
32a6bad
optimize ghcr_carto_deploy
mateo-di Jul 28, 2025
c04610d
Update ci behavior
mateo-di Jul 30, 2025
0354f20
Merge branch 'main' of https://github.com/jatorre/litellm
jatorre Aug 6, 2025
d951218
test: add comprehensive Responses API test suite
jatorre Aug 6, 2025
ab04eaa
Merge branch 'BerriAI:main' into main
mateo-di Aug 6, 2025
400d9a0
apply new dockerfile prisma solution to offline binaries download
mateo-di Aug 6, 2025
b7db96f
apply new dockerfile prisma solution to offline binaries download
mateo-di Aug 6, 2025
16f77e0
fix: Store Redis sessions for streaming Response API requests
jatorre Aug 7, 2025
ce3b79c
Merge remote-tracking branch 'jatorre/feature/streaming-id-consistenc…
mateo-di Aug 7, 2025
3b7f35e
Rollback non-root
mateo-di Aug 8, 2025
f517814
disable un-used workflows
mateo-di Aug 8, 2025
d67d4d1
Merge branch 'main' into chore/merge-streaming-id-consistency
mateo-di Aug 8, 2025
2b09182
Merge pull request #4 from CartoDB/chore/merge-streaming-id-consistency
mateo-di Aug 8, 2025
577904f
Revert "Merge remote-tracking branch 'jatorre/feature/streaming-id-co…
mateo-di Aug 11, 2025
f509a08
Merge pull request #5 from CartoDB/jatorre/fix/responses-api-redis-se…
mateo-di Aug 13, 2025
c6dd3c2
Configure scheduler with memory leak prevention settings
mateo-di Sep 2, 2025
0f19392
fix by Opus on the memray-1757425844.bin
mateo-di Sep 9, 2025
3ed99d0
Merge pull request #7 from CartoDB/feature/apscheduler-memory-leak-fixes
mateo-di Sep 25, 2025
df4d371
fix mcp_table server_name error
mateo-di Sep 26, 2025
b950752
fix mcp_table server_name error
mateo-di Sep 26, 2025
14647b7
remove arm64 from platforms
mateo-di Sep 29, 2025
e1a4da8
Add new migration to fix mcp server_name column missing error
mateo-di Sep 30, 2025
4ceb26d
Remove fixed litellm-proxy-extras package and use local
mateo-di Sep 30, 2025
7deaf6e
Remove dist commited folder
mateo-di Sep 30, 2025
3b1331e
Fix linting errors
mateo-di Sep 30, 2025
3532931
Merge pull request #11 from CartoDB/feature/fix-mcp-sql-migration-issue
mateo-di Sep 30, 2025
90b4155
Download prisma binaries on build time
mateo-di Sep 30, 2025
ea11a53
Add node as dependency for prisma
mateo-di Oct 1, 2025
2f8530d
Add node as dependency for prisma
mateo-di Oct 1, 2025
624becc
Fix duplicated migration + static prisma binaries
mateo-di Oct 2, 2025
37648d7
Create more robust / solid release method for fork
mateo-di Oct 2, 2025
a78840d
Fix prisma binaries error again
mateo-di Oct 2, 2025
8e608e8
Fix prisma binaries error again
mateo-di Oct 2, 2025
d2d1375
Fix prisma binaries error again
mateo-di Oct 2, 2025
828ead9
Set Prisma binaries directory
mateo-di Oct 2, 2025
649342a
Modify prisma-client in python to use the env
mateo-di Oct 2, 2025
ab673c9
New version with Modify prisma-client in python
mateo-di Oct 3, 2025
1078447
New version with Modify prisma-client in python
mateo-di Oct 3, 2025
37e96d8
change carto-workflows naming
mateo-di Oct 5, 2025
9b66311
change PRISMA_NODEENV_CACHE_DIR
mateo-di Oct 6, 2025
157bf45
Merge pull request #14 from CartoDB/feature/sc-509789/improve-litellm…
mateo-di Oct 6, 2025
b507b82
Updated docker/Dockerfile.non_root
mateo-di Oct 6, 2025
5c29e21
Update prisma binaries download approach
mateo-di Oct 6, 2025
6e13c75
Solve merge conflict
mateo-di Oct 6, 2025
2d12e24
Fix issue with dependencies in image build
mateo-di Oct 6, 2025
cdc3f3f
Fix issue with dependencies in image build
mateo-di Oct 6, 2025
4cdfeed
Fix issue with dependencies in image build
mateo-di Oct 6, 2025
5e6f214
Fix issue with dependencies in image build
mateo-di Oct 6, 2025
6c97a6c
Modify Utils
mateo-di Oct 7, 2025
f941488
Modify Utils
mateo-di Oct 7, 2025
aca7a78
fix: Use correct Prisma CLI path in offline mode
mateo-di Oct 7, 2025
45a37d5
fix: Correct Prisma CLI installation path in Docker build
mateo-di Oct 7, 2025
b2a56a2
refactor: Simplify Prisma configuration and reduce complexity
mateo-di Oct 7, 2025
98771e7
feat: Include create_views.py in base Docker image
mateo-di Oct 8, 2025
912d5f3
feat: Improve create_views.py error handling for containers
mateo-di Oct 8, 2025
8ea1bba
Merge pull request #13 from CartoDB/feature/sc-505348/re-review-outbo…
mateo-di Oct 9, 2025
5a15c18
feat: add Claude Code automated upstream sync
jatorre Oct 27, 2025
f6eb010
refactor: replace Claude Code sync with bash-based workflow
mateo-di Oct 27, 2025
63b9936
Add changes
mateo-di Oct 27, 2025
e6e381b
refactor: convert to pure bash workflow with correct branch strategy
mateo-di Oct 27, 2025
da1cdda
Fix indentation
mateo-di Oct 27, 2025
ec3c01c
Optional `labels` field in Vertex AI request
vvidovic Mar 12, 2025
5748d6d
Fix: Vertex AI Gemini labels field provider-aware filtering (#14563)
timelfrink Sep 15, 2025
60f9b2c
Merge pull request #23 from CartoDB/fix/cherry-pick-vertex-ai-labels
miguelangelmorenochacon Oct 28, 2025
ef367d2
Remove docs for the release process
mateo-di Oct 29, 2025
6dcceee
feat: add GitHub Actions output grouping and improve Slack notifications
mateo-di Oct 29, 2025
55706c1
fix: auto-resolve conflicts in main branch sync with upstream
mateo-di Oct 29, 2025
ab28f94
Add permissions
mateo-di Oct 29, 2025
20891b5
Revert PR-automerge approach + add Cartofante token
mateo-di Oct 30, 2025
683f8f8
add CARTOFANTE token in all steps
mateo-di Oct 30, 2025
7efd795
Merge pull request #22 from CartoDB/feature/claude-code-automated-sync-2
mateo-di Oct 30, 2025
9a75cea
Add suffix 'CARTO' in custom workflows
mateo-di Oct 30, 2025
542804e
refactor: decouple PR creation from upstream sync and improve merge s…
mateo-di Oct 30, 2025
4b313ae
fix: use git reset instead of merge for upstream sync
mateo-di Oct 30, 2025
72bbb1f
refactor: use merge-first strategy with reset fallback
mateo-di Oct 30, 2025
b5efffb
Add Claude conflict resolution workflow
mateo-di Oct 30, 2025
1a8520e
Improve Claude conflict resolution workflow
mateo-di Oct 30, 2025
10297aa
add actors
mateo-di Oct 30, 2025
08fad73
Fix workflow dispatch issue
mateo-di Oct 30, 2025
2ff496e
Fix workflow dispatch issue
mateo-di Oct 30, 2025
d26c233
Fix workflow dispatch capability
mateo-di Oct 31, 2025
a0a9daa
Fix workflow dispatch capability
mateo-di Oct 31, 2025
8089cce
Fix workflow dispatch capability
mateo-di Oct 31, 2025
4b092cb
Fix workflow dispatch capability
mateo-di Oct 31, 2025
3428dea
remove timeout from claude action
mateo-di Oct 31, 2025
712d674
Set max turns for claude to 250
mateo-di Oct 31, 2025
62e2b76
fix: resolve upstream sync conflicts for PR #24
github-actions[bot] Oct 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
571 changes: 474 additions & 97 deletions .circleci/config.yml

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions .circleci/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# used by CI/CD testing
openai==1.81.0
openai==1.100.1
python-dotenv
tiktoken
importlib_metadata
Expand All @@ -14,4 +14,5 @@ google-cloud-iam==2.19.1
fastapi-sso==0.16.0
uvloop==0.21.0
mcp==1.10.1 # for MCP server
semantic_router==0.1.10 # for auto-routing with litellm
semantic_router==0.1.10 # for auto-routing with litellm
fastuuid==0.12.0
11 changes: 8 additions & 3 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
// },

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "lts"
},
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},

// Configure tool-specific properties.
"customizations": {
Expand All @@ -30,7 +35,7 @@

// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [4000],

"containerEnv": {
"LITELLM_LOG": "DEBUG"
},
Expand All @@ -48,5 +53,5 @@
// "remoteUser": "litellm",

// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "pipx install poetry && poetry install -E extra_proxy -E proxy"
"postCreateCommand": "bash ./.devcontainer/post-create.sh"
}
17 changes: 17 additions & 0 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -e

echo "[post-create] Installing poetry via pip"
python -m pip install --upgrade pip
python -m pip install poetry

echo "[post-create] Installing Python dependencies (poetry)"
poetry install --with dev --extras proxy

echo "[post-create] Generating Prisma client"
poetry run prisma generate

echo "[post-create] Installing npm dependencies"
cd ui/litellm-dashboard && npm install --no-audit --no-fund

echo "[post-create] Done"
133 changes: 133 additions & 0 deletions .github/scripts/scan_keywords.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/usr/bin/env python3
import json
import os
import sys
import urllib.request
import urllib.error


def read_event_payload() -> dict:
event_path = os.environ.get("GITHUB_EVENT_PATH")
if not event_path or not os.path.exists(event_path):
return {}
with open(event_path, "r", encoding="utf-8") as f:
return json.load(f)


def get_issue_text(event: dict) -> tuple[str, str, int, str, str]:
issue = event.get("issue") or {}
title = (issue.get("title") or "").strip()
body = (issue.get("body") or "").strip()
number = issue.get("number") or 0
html_url = issue.get("html_url") or ""
author = ((issue.get("user") or {}).get("login") or "").strip()
return title, body, number, html_url, author


def detect_keywords(text: str, keywords: list[str]) -> list[str]:
lowered = text.lower()
matches = []
for keyword in keywords:
k = keyword.strip().lower()
if not k:
continue
if k in lowered:
matches.append(keyword.strip())
# Deduplicate while preserving order
seen = set()
unique_matches = []
for m in matches:
if m not in seen:
unique_matches.append(m)
seen.add(m)
return unique_matches


def send_webhook(webhook_url: str, payload: dict) -> None:
if not webhook_url:
return
data = json.dumps(payload).encode("utf-8")
req = urllib.request.Request(
webhook_url,
data=data,
headers={"Content-Type": "application/json"},
method="POST",
)
try:
with urllib.request.urlopen(req, timeout=10) as resp:
resp.read()
except urllib.error.HTTPError as e:
print(f"Webhook HTTP error: {e.code} {e.reason}", file=sys.stderr)
except urllib.error.URLError as e:
print(f"Webhook URL error: {e.reason}", file=sys.stderr)
except Exception as e:
print(f"Webhook unexpected error: {e}", file=sys.stderr)


def _excerpt(text: str, max_len: int = 400) -> str:
if not text:
return ""

# Keep original formatting
if len(text) <= max_len:
return text
return text[: max_len - 1] + "…"



def main() -> int:
event = read_event_payload()
if not event:
print("::warning::No event payload found; exiting without labeling.")
return 0

# Read issue details
title, body, number, html_url, author = get_issue_text(event)
combined_text = f"{title}\n\n{body}".strip()

# Keywords from env or defaults
keywords_env = os.environ.get("KEYWORDS", "")
default_keywords = ["azure", "openai", "bedrock", "vertexai", "vertex ai", "anthropic"]
keywords = [k.strip() for k in keywords_env.split(",")] if keywords_env else default_keywords

matches = detect_keywords(combined_text, keywords)
found = bool(matches)

# Emit outputs
github_output = os.environ.get("GITHUB_OUTPUT")
if github_output:
with open(github_output, "a", encoding="utf-8") as fh:
fh.write(f"found={'true' if found else 'false'}\n")
fh.write(f"matches={','.join(matches)}\n")

# Optional webhook notification
webhook_url = os.environ.get("PROVIDER_ISSUE_WEBHOOK_URL", "").strip()
if found and webhook_url:
repo_full = (event.get("repository") or {}).get("full_name", "")
title_part = f"*{title}*" if title else "New issue"
author_part = f" by @{author}" if author else ""
body_preview = _excerpt(body)
preview_block = f"\n{body_preview}" if body_preview else ""
payload = {
"text": (
f"New issue 🚨\n"
f"{title_part}\n\n{preview_block}\n"
f"<{html_url}|View issue>\n"
f"Author: {author}"
)
}
send_webhook(webhook_url, payload)

# Print a short log line for Actions UI
if found:
print(f"Detected provider keywords: {', '.join(matches)}")
else:
print("No provider keywords detected.")

return 0


if __name__ == "__main__":
raise SystemExit(main())


62 changes: 50 additions & 12 deletions .github/workflows/auto_update_price_and_context_window_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ def write_to_file(file_path, data):
# Print an error message if writing to file fails
print("Error updating JSON file:", e)

# Update the existing models and add the missing models
def transform_remote_data(data):
# Update the existing models and add the missing models for OpenRouter
def transform_openrouter_data(data):
transformed = {}
for row in data:
# Add the fields 'max_tokens' and 'input_cost_per_token'
Expand Down Expand Up @@ -81,6 +81,34 @@ def transform_remote_data(data):

return transformed

# Update the existing models and add the missing models for Vercel AI Gateway
def transform_vercel_ai_gateway_data(data):
transformed = {}
for row in data:
obj = {
"max_tokens": row["context_window"],
"input_cost_per_token": float(row["pricing"]["input"]),
"output_cost_per_token": float(row["pricing"]["output"]),
'max_output_tokens': row['max_tokens'],
'max_input_tokens': row["context_window"],
}

# Handle cache pricing if available
if "pricing" in row:
if "input_cache_read" in row["pricing"] and row["pricing"]["input_cache_read"] is not None:
obj['cache_read_input_token_cost'] = float(f"{float(row['pricing']['input_cache_read']):e}")

if "input_cache_write" in row["pricing"] and row["pricing"]["input_cache_write"] is not None:
obj['cache_creation_input_token_cost'] = float(f"{float(row['pricing']['input_cache_write']):e}")

mode = "embedding" if "embedding" in row["id"].lower() else "chat"

obj.update({"litellm_provider": "vercel_ai_gateway", "mode": mode})

transformed[f'vercel_ai_gateway/{row["id"]}'] = obj

return transformed


# Load local data from a specified file
def load_local_data(file_path):
Expand All @@ -100,22 +128,32 @@ def load_local_data(file_path):

def main():
local_file_path = "model_prices_and_context_window.json" # Path to the local data file
url = "https://openrouter.ai/api/v1/models" # URL to fetch remote data
openrouter_url = "https://openrouter.ai/api/v1/models" # URL to fetch OpenRouter data
vercel_ai_gateway_url = "https://ai-gateway.vercel.sh/v1/models" # URL to fetch Vercel AI Gateway data

# Load local data from file
local_data = load_local_data(local_file_path)
# Fetch remote data asynchronously
remote_data = asyncio.run(fetch_data(url))
# Transform the fetched remote data
remote_data = transform_remote_data(remote_data)

# If both local and remote data are available, synchronize and save
if local_data and remote_data:
sync_local_data_with_remote(local_data, remote_data)

# Fetch OpenRouter data
openrouter_data = asyncio.run(fetch_data(openrouter_url))
# Transform the fetched OpenRouter data
openrouter_data = transform_openrouter_data(openrouter_data)

# Fetch Vercel AI Gateway data
vercel_data = asyncio.run(fetch_data(vercel_ai_gateway_url))
# Transform the fetched Vercel AI Gateway data
vercel_data = transform_vercel_ai_gateway_data(vercel_data)

# Combine both datasets
all_remote_data = {**openrouter_data, **vercel_data}

# If both local and openrouter data are available, synchronize and save
if local_data and all_remote_data:
sync_local_data_with_remote(local_data, all_remote_data)
write_to_file(local_file_path, local_data)
else:
print("Failed to fetch model data from either local file or URL.")

# Entry point of the script
if __name__ == "__main__":
main()
main()
Loading