""" Plugin manifest and settings endpoints for doc-service. These are internal-only — they are called by the main backend's generic plugin proxy, never directly by the browser. No authentication is applied here because the backend enforces access control before forwarding the request. Endpoints: GET /plugin/manifest → static manifest with JSON Schema for settings GET /plugin/settings → current storage config values PATCH /plugin/settings → update storage config (partial update) """ from fastapi import APIRouter from pydantic import BaseModel from app.services.config_reader import get_storage_config, save_storage_config router = APIRouter() _MANIFEST: dict = { "id": "doc-service", "name": "Document Service", "icon": "file-text", "version": "1.0", "access": { "allow_superuser": True, "required_groups": ["doc-service-admin"], }, "settings_schema": { "type": "object", "title": "Storage & Watch", "properties": { "watch_enabled": { "type": "boolean", "title": "Enable file watching", "description": ( "Automatically ingest PDF files added to the mounted watch directory. " "Requires a service restart to take effect after toggling." ), }, "watch_path": { "type": "string", "title": "Watch path", "readOnly": True, "description": "Configured via Docker volume mount — edit docker-compose to change.", }, "ai_folder_suggestion": { "type": "boolean", "title": "AI folder suggestion", "description": ( "AI suggests a category for each ingested document. " "You must confirm the suggestion before it is applied." ), }, "ai_folder_default": { "type": "string", "title": "Default import category", "description": "Category assigned automatically when AI folder suggestion is disabled.", }, "ai_rename_suggestion": { "type": "boolean", "title": "AI rename suggestion", "description": ( "AI suggests a document title for each ingested file. " "You must confirm before it is applied." ), }, }, }, } class StorageSettingsUpdate(BaseModel): watch_enabled: bool | None = None ai_folder_suggestion: bool | None = None ai_folder_default: str | None = None ai_rename_suggestion: bool | None = None # watch_path is intentionally excluded — it cannot be changed via API @router.get("/manifest") async def get_manifest() -> dict: return _MANIFEST @router.get("/settings") async def get_settings() -> dict: return await get_storage_config() @router.patch("/settings") async def update_settings(body: StorageSettingsUpdate) -> dict: update = body.model_dump(exclude_none=True) if "ai_folder_default" in update: update["ai_folder_default"] = update["ai_folder_default"][:128].strip() or "imports" await save_storage_config(update) return await get_storage_config()