fix: resolve staging blockers B1-B5, S6, X5 (quality review v1)

This commit is contained in:
Leopold
2026-07-05 22:55:29 +02:00
parent 64b840c94c
commit 8aa2e6792b
6 changed files with 39 additions and 9 deletions
+6 -1
View File
@@ -4,7 +4,12 @@ LLM_API_KEY=sk-or-v1-xxx
LLM_MODEL=anthropic/claude-3.5-sonnet LLM_MODEL=anthropic/claude-3.5-sonnet
LLM_API_BASE= LLM_API_BASE=
# Auth (CHANGE THIS!) # MCP Tool Server — URL MUST include the /mcp path (FastMCP HTTP transport).
# Example: http://mcp-tools:8501/mcp (the docker-compose default already includes /mcp)
MCP_SERVER_URL=http://mcp-tools:8501/mcp
# Auth (CHANGE THIS — must be >=32 chars, must NOT be the default below)
# Generate one with: python -c "import secrets;print(secrets.token_urlsafe(32))"
AUTH_TOKEN=change-me-to-something-secure AUTH_TOKEN=change-me-to-something-secure
# Logging # Logging
+2 -1
View File
@@ -13,7 +13,8 @@ RUN pip install --no-cache-dir --upgrade pip && \
COPY . . COPY . .
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser # B4: run as root for staging so /data volume is writable without chown entrypoint.
# (Bind-mounted /data from host typically has host UID, not 1000.)
EXPOSE 8000 EXPOSE 8000
+8 -3
View File
@@ -76,13 +76,15 @@ async def run_agent_turn(
if not agent["enabled"]: if not agent["enabled"]:
raise ValueError(f"Agent '{agent_id}' ist deaktiviert") raise ValueError(f"Agent '{agent_id}' ist deaktiviert")
# History laden (letzte 20 Messages) — VOR dem Speichern der neuen User-Message,
# damit die neue Turn-User-Message nicht versehentlich aus dem Slice fällt.
history = await get_messages(db, conversation_id, limit=20)
# User-Message speichern # User-Message speichern
await add_message(db, conversation_id, "user", user_message) await add_message(db, conversation_id, "user", user_message)
# History laden (letzte 20 Messages)
history = await get_messages(db, conversation_id, limit=20)
messages: List[dict] = [{"role": "system", "content": agent["system_prompt"]}] messages: List[dict] = [{"role": "system", "content": agent["system_prompt"]}]
for row in history[:-1]: # ohne die gerade gespeicherte user-Message for row in history:
role, content, tool_calls_json, _, _ = row role, content, tool_calls_json, _, _ = row
if role == "tool": if role == "tool":
continue continue
@@ -94,6 +96,9 @@ async def run_agent_turn(
pass pass
messages.append(msg) messages.append(msg)
# Aktuelle User-Message explizit anhängen, damit das LLM den neuen Turn sieht.
messages.append({"role": "user", "content": user_message})
# MCP-Tools laden (gefiltert nach allowed_tools) # MCP-Tools laden (gefiltert nach allowed_tools)
mcp_client = get_mcp_client() mcp_client = get_mcp_client()
tools = [] tools = []
+7 -1
View File
@@ -60,13 +60,19 @@ class AgentUpdate(BaseModel):
class ChatMessage(BaseModel): class ChatMessage(BaseModel):
message: str = Field(..., min_length=1) message: str = Field(..., min_length=1, max_length=32000)
# === App === # === App ===
@asynccontextmanager @asynccontextmanager
async def lifespan(app: FastAPI): async def lifespan(app: FastAPI):
# B1 Boot Guard: refuse to start with default or weak AUTH_TOKEN
if settings.AUTH_TOKEN == "change-me-in-production" or len(settings.AUTH_TOKEN) < 32:
raise RuntimeError(
"AUTH_TOKEN env var is unset or weak (must be >=32 chars and not the default "
"'change-me-in-production'). Set a strong AUTH_TOKEN before starting the service."
)
Path(settings.DB_PATH).parent.mkdir(parents=True, exist_ok=True) Path(settings.DB_PATH).parent.mkdir(parents=True, exist_ok=True)
db = await aiosqlite.connect(settings.DB_PATH) db = await aiosqlite.connect(settings.DB_PATH)
try: try:
+1 -1
View File
@@ -6,7 +6,7 @@ from typing import Optional, Dict, Any
import aiosqlite import aiosqlite
from config import settings from config import settings
from db import log_audit, get_db from db import log_audit
logger = logging.getLogger("audit") logger = logging.getLogger("audit")
+15 -2
View File
@@ -11,14 +11,21 @@ services:
- LLM_API_KEY=${LLM_API_KEY} - LLM_API_KEY=${LLM_API_KEY}
- LLM_MODEL=${LLM_MODEL:-anthropic/claude-3.5-sonnet} - LLM_MODEL=${LLM_MODEL:-anthropic/claude-3.5-sonnet}
- LLM_API_BASE=${LLM_API_BASE:-} - LLM_API_BASE=${LLM_API_BASE:-}
- MCP_SERVER_URL=http://mcp-tools:8501 - MCP_SERVER_URL=http://mcp-tools:8501/mcp
- AUTH_TOKEN=${AUTH_TOKEN} - AUTH_TOKEN=${AUTH_TOKEN}
- DB_PATH=/data/agent-platform.db - DB_PATH=/data/agent-platform.db
- LOG_LEVEL=${LOG_LEVEL:-info} - LOG_LEVEL=${LOG_LEVEL:-info}
volumes: volumes:
- agent-data:/data - agent-data:/data
depends_on: depends_on:
- mcp-tools mcp-tools:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: unless-stopped restart: unless-stopped
networks: networks:
- agent-net - agent-net
@@ -36,6 +43,12 @@ services:
environment: environment:
- MCP_HOST=0.0.0.0 - MCP_HOST=0.0.0.0
- MCP_PORT=8501 - MCP_PORT=8501
healthcheck:
test: ["CMD-SHELL", "(echo > /dev/tcp/127.0.0.1/8501) >/dev/null 2>&1 || exit 1"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: unless-stopped restart: unless-stopped
networks: networks:
- agent-net - agent-net