This commit is contained in:
team3
2026-06-18 14:30:21 +02:00
parent d8932c90d6
commit 9c0f622e0c
30 changed files with 45808 additions and 217 deletions

View File

@@ -7,7 +7,7 @@ from fastapi import APIRouter, HTTPException
from fastapi.responses import FileResponse
from agents import provider_available
from config import PROJECTS_DIR, PROVIDERS
from config import PROJECTS_DIR, UNI_DIR, PROVIDERS
from database import (
create_guide, delete_guide, get_guide, list_guides,
create_topic, list_topics as db_list_topics, delete_topic,
@@ -16,7 +16,7 @@ from database import (
get_vertiefung, set_vertiefung, list_vertiefungen,
list_baustein_progress, set_baustein_score, set_baustein_streak, set_baustein_absolviert, set_baustein_verstanden, set_baustein_gemeistert, delete_baustein_daten,
)
from bausteine import generate_bausteine, cancel_bausteine, bausteine_status, active_bausteine, reset_bausteine
from bausteine import generate_bausteine, cancel_bausteine, bausteine_status, active_bausteine, reset_bausteine, lade_quelle, lade_uebersicht
from elements import generate_element, chat_with_guide, chat_with_element, check_element, style_element, refine_suggestion
from lernen import NOETIG, MASTERY, MEISTERN, baustein_chat, baustein_diskussion, baustein_element_anlegen, pruefung_bewertung, pruefung_bewertung_schnell, pruefung_frage, score_berechnen, streak_berechnen, vertiefung_generieren
from guide import generate_guide, guide_slot_dateien
@@ -31,6 +31,7 @@ from models import (
ElementUpdateRequest, ElementCheckRequest, ElementCheckResponse, ElementStyleResponse,
ElementRefineRequest, ElementRefineResponse,
ProgressUpdate, ProgressResponse, ProjectResponse, ProviderInfo,
FolderResponse, BausteineQuelleUpdate, BausteineQuelleResponse, BausteinUebersicht,
VertiefungRequest, VertiefungResponse,
BausteinChatRequest, BausteinChatResponse,
BausteinPruefungRequest, BausteinPruefungResponse, BausteinLernstandResponse,
@@ -113,6 +114,18 @@ async def remove_project(name: str):
return {"ok": True}
@router.get("/folders", response_model=list[FolderResponse])
async def list_folders(kind: str):
"""Ordner für die Quellen-Auswahl: kind=projekt → projects/, kind=uni → uni/."""
base = {"projekt": (PROJECTS_DIR, "projects"), "uni": (UNI_DIR, "uni")}.get(kind)
if base is None:
raise HTTPException(400, "kind muss 'projekt' oder 'uni' sein")
root, prefix = base
if not root.is_dir():
return []
return [{"name": e.name, "ort": f"{prefix}/{e.name}"} for e in sorted(root.iterdir()) if e.is_dir()]
# --- Bausteine ---
@router.get("/bausteine/status", response_model=BausteineStatusResponse)
@@ -161,6 +174,39 @@ async def remove_bausteine(topic: str):
return {"ok": True}
def _validate_quelle(typ: str, ort: str) -> None:
"""Quellen-Eingabe prüfen (gleiche Regeln wie beim Erstellen)."""
if typ in ("projekt", "uni"):
ordner = safe_ordner(ort)
if ordner is None or not ordner.is_dir():
raise HTTPException(400, "Ordner ungültig oder nicht gefunden (Pfad relativ zum Projekt-Root, kein ../).")
elif typ == "link":
if not ort.lower().startswith(("http://", "https://")):
raise HTTPException(400, "Link muss mit http:// oder https:// beginnen.")
@router.get("/bausteine/quelle", response_model=BausteineQuelleResponse)
async def get_bausteine_quelle(topic: str):
return lade_quelle(topic)
@router.put("/bausteine/quelle", response_model=BausteineQuelleResponse)
async def update_bausteine_quelle(req: BausteineQuelleUpdate):
"""Nur speichern — KEINE Neugenerierung. Quellen-/Spec-Wahl überschreiben."""
topic, typ, ort = req.topic.strip(), req.type, req.ort.strip()
_validate_quelle(typ, ort)
qp = quelle_path(topic)
qp.parent.mkdir(parents=True, exist_ok=True)
daten = {"type": typ, "ort": ort, "spec": req.spec.strip()}
atomic_write_json(qp, daten)
return daten
@router.get("/bausteine/uebersicht", response_model=list[BausteinUebersicht])
async def get_bausteine_uebersicht(topic: str):
return lade_uebersicht(topic)
# --- Baustein-Lernen: Vertiefung, Chat, Prüfung ---
async def _bester_text(topic: str, baustein: str) -> str | None: