feat: Add plugins — catalogue on/off à effet réel (v7.58.0, phase 8/8)
- app/services/plugins.py + migration 35 : table plugins (slug, name,
description, enabled) pré-remplie avec 3 modules câblés — web-tools,
web-clipper, automations ; ligne absente = activé (défaut sûr)
- automations OFF → dépendance FastAPI posée à l'include_router dans main.py
(aucun router touché) → toutes les routes /workspace/automations* refusées +
garde de tick du scheduler en arrière-plan
- web-clipper OFF → GET /extensions et tout /api/v2/web-clipper/* refusés
- web-tools OFF → web_search et fetch_url retirés du schéma ET de execute()
via ToolRegistry._all() : le LLM ne les voit plus
- UI rendue côté serveur : global Jinja plugin_enabled(slug) — nav
« Extensions » / « Automations » en {% if %} (absentes du DOM), sections
conditionnées en x-show dans settings.html
- menu + : l'entrée « Add plugins » devient vivante (fini disabled:true) —
liste des 3 plugins avec bascule, GET/PATCH /api/agent/plugins[/slug]
(slug inconnu → 404, 401 sans session)
- tests : tests/test_v758_plugins.py (10 tests) — routes refusées (302 hors
/api, 404 JSON pour /api*), outils retirés, nav disparue, persistance,
câblage ; assertions disabled:true == 0 dans les tests des phases 1/3/4/5/7
- livraison : VERSION + app/main = 7.58.0, OpenAPI 525 chemins, CHANGELOG,
ROADMAP phase 8 cochée (menu + complet), avenant phase 8 (docs)
This commit is contained in:
+18
-1
@@ -17,7 +17,7 @@ from fastapi.responses import JSONResponse, RedirectResponse, StreamingResponse
|
||||
from app.auth.session import get_current_user
|
||||
from app.config import settings
|
||||
from app.db import get_conn
|
||||
from app.services import connectors, oauth_connectors, skill_gallery
|
||||
from app.services import connectors, oauth_connectors, plugins, skill_gallery
|
||||
from app.services.agent_engine import AgentEngine, undo_action
|
||||
from app.services.llm_client import PROVIDER_MODELS, PROVIDERS, LLMClient
|
||||
from app.services.llm_config import (
|
||||
@@ -647,6 +647,23 @@ def list_connectors_route(request: Request):
|
||||
return {"connectors": connectors.list_connectors(user_id)}
|
||||
|
||||
|
||||
@router.get("/plugins")
|
||||
def list_plugins_route(request: Request):
|
||||
"""Catalogue des plugins de l'instance (menu + → « Add plugins »)."""
|
||||
_current_user_id(request)
|
||||
return {"plugins": plugins.list_plugins()}
|
||||
|
||||
|
||||
@router.patch("/plugins/{slug}")
|
||||
def set_plugin_route(request: Request, slug: str, body: dict = Body(default={})):
|
||||
"""Bascule un plugin : l'effet est réel (routes/UI/outils), pas un drapeau."""
|
||||
_current_user_id(request)
|
||||
try:
|
||||
return plugins.set_enabled(slug, bool(body.get("enabled")))
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
|
||||
|
||||
@router.post("/connectors")
|
||||
def create_connectors_route(request: Request, body: dict = Body(default={})):
|
||||
"""Ajoute un connecteur personnalisé — l'URL est validée (garde SSRF)."""
|
||||
|
||||
Reference in New Issue
Block a user