Enhance MCP development features and introduce skills management
- Added configuration options for requiring human approval before applying LLM-generated MCP patches. - Updated Docker setup to include skills directory. - Integrated skills management into the backend, allowing for procedural guides and skill matching. - Refactored database initialization to apply Alembic migrations. - Enhanced task approval process to handle MCP patch applications with optional approval. - Introduced new schemas for skills and updated existing APIs to support skills functionality. This commit lays the groundwork for improved agent capabilities and better management of MCP development processes.
This commit is contained in:
@@ -1,13 +1,18 @@
|
||||
"""Async SQLAlchemy engine, session factory, and Base model."""
|
||||
"""Database schema migrations via Alembic."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from collections.abc import AsyncGenerator
|
||||
from pathlib import Path
|
||||
|
||||
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
|
||||
from sqlalchemy.orm import DeclarativeBase
|
||||
|
||||
from app.config import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
engine = create_async_engine(settings.database_url, echo=False, pool_pre_ping=True)
|
||||
SessionLocal = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
||||
|
||||
@@ -21,45 +26,19 @@ async def get_db() -> AsyncGenerator[AsyncSession, None]:
|
||||
yield session
|
||||
|
||||
|
||||
async def init_db() -> None:
|
||||
"""Create tables and apply lightweight dev migrations."""
|
||||
from app import models # noqa: F401
|
||||
from sqlalchemy import text
|
||||
def _run_alembic_upgrade() -> None:
|
||||
from alembic import command
|
||||
from alembic.config import Config
|
||||
|
||||
async with engine.begin() as conn:
|
||||
await conn.run_sync(Base.metadata.create_all)
|
||||
# Dev migration: locations → vessels (rename legacy table/columns)
|
||||
await conn.execute(
|
||||
text(
|
||||
"""
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'locations')
|
||||
AND NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'vessels')
|
||||
THEN
|
||||
ALTER TABLE locations RENAME TO vessels;
|
||||
END IF;
|
||||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'devices' AND column_name = 'location_id')
|
||||
THEN
|
||||
ALTER TABLE devices RENAME COLUMN location_id TO vessel_id;
|
||||
END IF;
|
||||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'tasks' AND column_name = 'location_id')
|
||||
THEN
|
||||
ALTER TABLE tasks RENAME COLUMN location_id TO vessel_id;
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'devices' AND column_name = 'catalog_key')
|
||||
THEN
|
||||
ALTER TABLE devices ADD COLUMN catalog_key VARCHAR(64);
|
||||
END IF;
|
||||
END $$;
|
||||
"""
|
||||
)
|
||||
)
|
||||
# Indexes for hot query paths (idempotent; covers pre-existing DBs).
|
||||
for stmt in (
|
||||
"CREATE INDEX IF NOT EXISTS ix_tasks_vessel_id ON tasks (vessel_id)",
|
||||
"CREATE INDEX IF NOT EXISTS ix_task_events_task_id_id ON task_events (task_id, id)",
|
||||
"CREATE INDEX IF NOT EXISTS ix_approval_requests_task_status "
|
||||
"ON approval_requests (task_id, status)",
|
||||
):
|
||||
await conn.execute(text(stmt))
|
||||
ini = Path(__file__).resolve().parent.parent / "alembic.ini"
|
||||
cfg = Config(str(ini))
|
||||
command.upgrade(cfg, "head")
|
||||
|
||||
|
||||
async def init_db() -> None:
|
||||
"""Apply Alembic migrations to head."""
|
||||
try:
|
||||
await asyncio.to_thread(_run_alembic_upgrade)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.exception("Database migration failed")
|
||||
raise RuntimeError("Database migration failed") from exc
|
||||
|
||||
Reference in New Issue
Block a user