mindnet/app/routers/ingest.py
2025-12-11 08:18:41 +01:00

106 lines
3.3 KiB
Python

"""
app/routers/ingest.py
API-Endpunkte für WP-11 (Discovery & Persistence).
Robustified for Frontend Integration.
"""
import os
import time
import logging
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from typing import Optional, List, Dict, Any
from app.core.ingestion import IngestionService
from app.services.discovery import DiscoveryService
# Logger für Backend-Debugging aktivieren
logger = logging.getLogger("uvicorn.error")
router = APIRouter()
# --- DTOs (Data Transfer Objects) ---
class AnalyzeRequest(BaseModel):
text: str
type: str = "concept"
class SaveRequest(BaseModel):
markdown_content: str
filename: Optional[str] = None
folder: str = "00_Inbox" # Standard-Ordner
class SaveResponse(BaseModel):
status: str
file_path: str
note_id: str
stats: Dict[str, Any]
# --- Services ---
discovery_service = DiscoveryService()
@router.post("/analyze")
async def analyze_draft(req: AnalyzeRequest):
"""
WP-11 Intelligence: Liefert Link-Vorschläge basierend auf Text und Typ.
"""
try:
# Prio 2: Intelligence Service aufrufen
result = await discovery_service.analyze_draft(req.text, req.type)
return result
except Exception as e:
logger.error(f"Analyze failed: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Analysis failed: {str(e)}")
@router.post("/save", response_model=SaveResponse)
async def save_note(req: SaveRequest):
"""
WP-11 Persistence: Speichert Markdown physisch und indiziert es sofort.
"""
try:
# 1. Vault Root sicher ermitteln
vault_root = os.getenv("MINDNET_VAULT_ROOT", "./vault")
# Absolute Pfade auflösen, um CWD-Probleme zu vermeiden
abs_vault_root = os.path.abspath(vault_root)
if not os.path.exists(abs_vault_root):
error_msg = f"Vault root not found at: {abs_vault_root}. Check MINDNET_VAULT_ROOT in .env"
logger.error(error_msg)
raise HTTPException(status_code=500, detail=error_msg)
# 2. Filename Fallback
final_filename = req.filename
if not final_filename:
final_filename = f"draft_{int(time.time())}.md"
# 3. Ingestion Service aufrufen
ingest_service = IngestionService()
logger.info(f"Attempting to save {final_filename} to {req.folder} in {abs_vault_root}")
result = ingest_service.create_from_text(
markdown_content=req.markdown_content,
filename=final_filename,
vault_root=abs_vault_root,
folder=req.folder
)
# Fehler vom Service abfangen
if result.get("status") == "error":
raise HTTPException(status_code=500, detail=result.get("error"))
return SaveResponse(
status="success",
file_path=result["path"],
note_id=result.get("note_id", "unknown"),
stats={
"chunks": result.get("chunks_count", 0),
"edges": result.get("edges_count", 0)
}
)
except HTTPException as he:
raise he
except Exception as e:
logger.error(f"Save failed: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Save failed: {str(e)}")