118 lines
4.5 KiB
Python
118 lines
4.5 KiB
Python
import uuid
|
|
from fastapi import APIRouter, HTTPException
|
|
from pydantic import BaseModel
|
|
from typing import Optional
|
|
from app.models import SystemCreate, SystemRecord
|
|
from app.internal import firestore as fstore
|
|
|
|
router = APIRouter(prefix="/systems", tags=["systems"])
|
|
|
|
|
|
class VocabularyTermBody(BaseModel):
|
|
term: str
|
|
|
|
|
|
@router.get("")
|
|
async def list_systems():
|
|
return await fstore.collection_list("systems")
|
|
|
|
|
|
@router.get("/{system_id}")
|
|
async def get_system(system_id: str):
|
|
system = await fstore.doc_get("systems", system_id)
|
|
if not system:
|
|
raise HTTPException(404, f"System '{system_id}' not found.")
|
|
return system
|
|
|
|
|
|
@router.post("", status_code=201)
|
|
async def create_system(body: SystemCreate):
|
|
system_id = str(uuid.uuid4())
|
|
doc = SystemRecord(system_id=system_id, **body.model_dump())
|
|
await fstore.doc_set("systems", system_id, doc.model_dump(), merge=False)
|
|
return doc
|
|
|
|
|
|
@router.put("/{system_id}")
|
|
async def update_system(system_id: str, body: SystemCreate):
|
|
existing = await fstore.doc_get("systems", system_id)
|
|
if not existing:
|
|
raise HTTPException(404, f"System '{system_id}' not found.")
|
|
await fstore.doc_update("systems", system_id, body.model_dump())
|
|
return {**existing, **body.model_dump()}
|
|
|
|
|
|
@router.delete("/{system_id}", status_code=204)
|
|
async def delete_system(system_id: str):
|
|
existing = await fstore.doc_get("systems", system_id)
|
|
if not existing:
|
|
raise HTTPException(404, f"System '{system_id}' not found.")
|
|
await fstore.doc_delete("systems", system_id)
|
|
|
|
|
|
# ── Vocabulary endpoints ───────────────────────────────────────────────────────
|
|
|
|
@router.get("/{system_id}/vocabulary")
|
|
async def get_vocabulary(system_id: str):
|
|
"""Return approved vocabulary and pending induction suggestions."""
|
|
existing = await fstore.doc_get("systems", system_id)
|
|
if not existing:
|
|
raise HTTPException(404, f"System '{system_id}' not found.")
|
|
from app.internal.vocabulary_learner import get_vocabulary as _get
|
|
return await _get(system_id)
|
|
|
|
|
|
@router.post("/{system_id}/vocabulary/bootstrap", status_code=202)
|
|
async def bootstrap_vocabulary(system_id: str):
|
|
"""Trigger a one-shot GPT-4o bootstrap to seed the vocabulary from local knowledge."""
|
|
existing = await fstore.doc_get("systems", system_id)
|
|
if not existing:
|
|
raise HTTPException(404, f"System '{system_id}' not found.")
|
|
from app.internal.vocabulary_learner import bootstrap_system_vocabulary
|
|
terms = await bootstrap_system_vocabulary(system_id)
|
|
return {"added": len(terms), "terms": terms}
|
|
|
|
|
|
@router.post("/{system_id}/vocabulary/terms")
|
|
async def add_vocabulary_term(system_id: str, body: VocabularyTermBody):
|
|
"""Manually add a term to the approved vocabulary."""
|
|
existing = await fstore.doc_get("systems", system_id)
|
|
if not existing:
|
|
raise HTTPException(404, f"System '{system_id}' not found.")
|
|
from app.internal.vocabulary_learner import add_term
|
|
await add_term(system_id, body.term.strip())
|
|
return {"ok": True}
|
|
|
|
|
|
@router.delete("/{system_id}/vocabulary/terms")
|
|
async def remove_vocabulary_term(system_id: str, body: VocabularyTermBody):
|
|
"""Remove a term from the approved vocabulary."""
|
|
existing = await fstore.doc_get("systems", system_id)
|
|
if not existing:
|
|
raise HTTPException(404, f"System '{system_id}' not found.")
|
|
from app.internal.vocabulary_learner import remove_term
|
|
await remove_term(system_id, body.term)
|
|
return {"ok": True}
|
|
|
|
|
|
@router.post("/{system_id}/vocabulary/pending/approve")
|
|
async def approve_pending(system_id: str, body: VocabularyTermBody):
|
|
"""Move a pending induction suggestion into the approved vocabulary."""
|
|
existing = await fstore.doc_get("systems", system_id)
|
|
if not existing:
|
|
raise HTTPException(404, f"System '{system_id}' not found.")
|
|
from app.internal.vocabulary_learner import approve_pending_term
|
|
await approve_pending_term(system_id, body.term)
|
|
return {"ok": True}
|
|
|
|
|
|
@router.post("/{system_id}/vocabulary/pending/dismiss")
|
|
async def dismiss_pending(system_id: str, body: VocabularyTermBody):
|
|
"""Dismiss a pending induction suggestion without adding it."""
|
|
existing = await fstore.doc_get("systems", system_id)
|
|
if not existing:
|
|
raise HTTPException(404, f"System '{system_id}' not found.")
|
|
from app.internal.vocabulary_learner import dismiss_pending_term
|
|
await dismiss_pending_term(system_id, body.term)
|
|
return {"ok": True}
|