feat: add LiteLLM gateway scaffold and dashboard health probe
Deploy Dashboard (Dev) / deploy-dev (push) Successful in 2m11s
Deploy Dashboard (Dev) / deploy-dev (push) Successful in 2m11s
Introduce a localhost-only LiteLLM service template and expose a protected dashboard health endpoint for operational visibility, while adding cc-connect mobile bridge templates with conservative defaults. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -44,6 +44,9 @@ CORS_ORIGINS = os.environ.get("CORS_ORIGINS", "https://nas.jimmygan.com,https://
|
||||
# Chat Summary
|
||||
CHAT_SUMMARY_DB = os.environ.get("CHAT_SUMMARY_DB", "/app/data/chat-summarizer/chat_summary.db")
|
||||
|
||||
# LiteLLM
|
||||
LITELLM_URL = os.environ.get("LITELLM_URL", "http://127.0.0.1:4005")
|
||||
|
||||
# OpenClaw
|
||||
OPENCLAW_GATEWAY_TOKEN = os.environ.get("OPENCLAW_GATEWAY_TOKEN", "")
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from fastapi.responses import JSONResponse
|
||||
from slowapi import Limiter
|
||||
from slowapi.util import get_remote_address
|
||||
from slowapi.errors import RateLimitExceeded
|
||||
from routers import docker_router, gitea, files, terminal, system, auth, chat_summary, security, passkey, totp
|
||||
from routers import docker_router, gitea, files, terminal, system, auth, chat_summary, security, passkey, totp, litellm
|
||||
import auth as auth_module
|
||||
from rbac import require_page, require_write
|
||||
|
||||
@@ -179,6 +179,8 @@ app.include_router(files.router, prefix="/api/files",
|
||||
dependencies=[Depends(_inject_user), Depends(require_page("files")), Depends(require_write())])
|
||||
app.include_router(system.router, prefix="/api/system",
|
||||
dependencies=[Depends(_inject_user), Depends(require_page("dashboard"))])
|
||||
app.include_router(litellm.router, prefix="/api/litellm",
|
||||
dependencies=[Depends(_inject_user), Depends(require_page("dashboard"))])
|
||||
app.include_router(chat_summary.router, prefix="/api/chat-summary",
|
||||
dependencies=[Depends(_inject_user), Depends(require_page("chat-digest"))])
|
||||
app.include_router(security.router, prefix="/api/security",
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import time
|
||||
import httpx
|
||||
from fastapi import APIRouter
|
||||
from config import LITELLM_URL
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/health")
|
||||
async def litellm_health():
|
||||
timeout = httpx.Timeout(2.0)
|
||||
checks = ("/health", "/v1/models")
|
||||
|
||||
last_error = None
|
||||
async with httpx.AsyncClient(timeout=timeout) as client:
|
||||
for path in checks:
|
||||
url = f"{LITELLM_URL.rstrip('/')}{path}"
|
||||
started = time.perf_counter()
|
||||
try:
|
||||
response = await client.get(url)
|
||||
latency_ms = round((time.perf_counter() - started) * 1000, 1)
|
||||
if response.is_success:
|
||||
return {
|
||||
"ok": True,
|
||||
"status": "up",
|
||||
"latency_ms": latency_ms,
|
||||
"endpoint": path,
|
||||
"http_status": response.status_code,
|
||||
}
|
||||
last_error = f"{path} returned {response.status_code}"
|
||||
except Exception as exc:
|
||||
last_error = str(exc)
|
||||
|
||||
return {
|
||||
"ok": False,
|
||||
"status": "down",
|
||||
"latency_ms": None,
|
||||
"endpoint": None,
|
||||
"error": last_error or "health check failed",
|
||||
}
|
||||
Reference in New Issue
Block a user