fix: plugin duplicate route registration + prestart.sh Python instead of psql + SMTP in docker-compose
Check Cross-Plugin Imports / check (push) Has been cancelled

This commit is contained in:
Agent Zero
2026-07-29 12:48:25 +02:00
parent de53bcff25
commit fd1a170f31
3 changed files with 49 additions and 10 deletions
+9
View File
@@ -615,6 +615,15 @@ class PluginRegistry:
routers = plugin.get_routes()
mounted_routes: list[Any] = []
for router in routers:
# Check if routes from this router are already registered (P1.2 fix)
# This prevents duplicate route registration when plugins are
# statically registered in main.py AND dynamically activated
existing_paths = {getattr(r, 'path', None) for r in self._app.router.routes}
router_paths = {getattr(r, 'path', None) for r in router.routes}
if router_paths & existing_paths:
# Routes already registered — skip to avoid duplicates
logger.debug("Plugin '%s' routes already registered, skipping", name)
continue
# Snapshot existing route object IDs before inclusion
existing_ids = {id(r) for r in self._app.router.routes}
self._app.include_router(router)
+14
View File
@@ -88,6 +88,13 @@ services:
LOG_LEVEL: ${LOG_LEVEL:-INFO}
SESSION_COOKIE_SECURE: ${SESSION_COOKIE_SECURE:-true}
STORAGE_PATH: ${STORAGE_PATH:-/data/storage}
# SMTP for password reset and notifications
SMTP_HOST: ${SMTP_HOST:-}
SMTP_PORT: ${SMTP_PORT:-587}
SMTP_USER: ${SMTP_USER:-}
SMTP_PASSWORD: ${SMTP_PASSWORD:-}
SMTP_FROM: ${SMTP_FROM:-no-reply@localhost}
SMTP_TLS: ${SMTP_TLS:-true}
BCRYPT_ROUNDS: ${BCRYPT_ROUNDS:-12}
# S3 Storage (optional — if STORAGE_BACKEND=s3)
STORAGE_BACKEND: ${STORAGE_BACKEND:-local}
@@ -134,6 +141,13 @@ services:
LOG_LEVEL: ${LOG_LEVEL:-INFO}
SESSION_COOKIE_SECURE: ${SESSION_COOKIE_SECURE:-true}
STORAGE_PATH: ${STORAGE_PATH:-/data/storage}
# SMTP for password reset and notifications
SMTP_HOST: ${SMTP_HOST:-}
SMTP_PORT: ${SMTP_PORT:-587}
SMTP_USER: ${SMTP_USER:-}
SMTP_PASSWORD: ${SMTP_PASSWORD:-}
SMTP_FROM: ${SMTP_FROM:-no-reply@localhost}
SMTP_TLS: ${SMTP_TLS:-true}
STORAGE_BACKEND: ${STORAGE_BACKEND:-local}
S3_ENDPOINT: ${S3_ENDPOINT:-}
S3_BUCKET: ${S3_BUCKET:-}
Executable → Regular
+26 -10
View File
@@ -30,16 +30,32 @@ echo "[prestart] DB migrations completed successfully."
# Set crm_runtime password if RUNTIME_DB_PASSWORD is set
if [ -n "$RUNTIME_DB_PASSWORD" ]; then
echo "[prestart] Setting crm_runtime password..."
# Parse the migration DB URL to get psql connection params
PGHOST=postgres
PGUSER="${POSTGRES_USER:-crm_user}"
PGDATABASE="${POSTGRES_DB:-crm_db}"
PGPASSWORD="$POSTGRES_PASSWORD"
export PGHOST PGUSER PGDATABASE PGPASSWORD
psql -c "ALTER ROLE crm_runtime WITH LOGIN PASSWORD '${RUNTIME_DB_PASSWORD}' NOSUPERUSER NOBYPASSRLS;" 2>/dev/null || \
echo "[prestart] WARNING: Could not set crm_runtime password (role may not exist yet)"
unset PGPASSWORD
echo "[prestart] crm_runtime password set."
python3 -c "
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
async def set_password():
db_url = os.environ.get('MIGRATION_DATABASE_URL', os.environ.get('DATABASE_URL', ''))
if not db_url:
print('[prestart] WARNING: No DB URL for password setup')
return
engine = create_async_engine(db_url)
pwd = os.environ.get('RUNTIME_DB_PASSWORD', '')
try:
async with engine.begin() as conn:
await conn.execute(text(
f\"ALTER ROLE crm_runtime WITH LOGIN PASSWORD '{pwd}' NOSUPERUSER NOBYPASSRLS\"
))
print('[prestart] crm_runtime password set.')
except Exception as e:
print(f'[prestart] WARNING: Could not set crm_runtime password: {e}')
finally:
await engine.dispose()
asyncio.run(set_password())
"
fi
echo "[prestart] Starting uvicorn on 0.0.0.0:8000 (workers=1)..."