feat: add POST /api/diagnose and GET/PATCH /api/settings endpoints

This commit is contained in:
pyr0ball 2026-05-11 09:10:58 -07:00
parent b786eee49c
commit 5fe0fdd022

View file

@ -39,8 +39,10 @@ from app.services.search import (
stats_summary as _stats, stats_summary as _stats,
format_results, format_results,
) )
from app.services.diagnose import diagnose as _diagnose
DB_PATH = Path(os.environ.get("TURNSTONE_DB", Path(__file__).parent.parent / "data" / "turnstone.db")) DB_PATH = Path(os.environ.get("TURNSTONE_DB", Path(__file__).parent.parent / "data" / "turnstone.db"))
PREFS_PATH = DB_PATH.parent / "preferences.json"
DIST_DIR = Path(__file__).parent.parent / "web" / "dist" DIST_DIR = Path(__file__).parent.parent / "web" / "dist"
SOURCE_HOST = os.environ.get("TURNSTONE_SOURCE_HOST", "unknown") SOURCE_HOST = os.environ.get("TURNSTONE_SOURCE_HOST", "unknown")
BUNDLE_ENDPOINT = os.environ.get("TURNSTONE_BUNDLE_ENDPOINT", "") BUNDLE_ENDPOINT = os.environ.get("TURNSTONE_BUNDLE_ENDPOINT", "")
@ -50,7 +52,7 @@ app = FastAPI(title="Turnstone API", version="0.1.0", docs_url="/turnstone/docs"
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,
allow_origins=["*"], allow_origins=["*"],
allow_methods=["GET", "POST", "DELETE"], allow_methods=["GET", "POST", "DELETE", "PATCH"],
allow_headers=["*"], allow_headers=["*"],
) )
@ -60,6 +62,29 @@ def _startup() -> None:
ensure_schema(DB_PATH) ensure_schema(DB_PATH)
def _load_prefs() -> dict[str, str]:
if PREFS_PATH.exists():
try:
return json.loads(PREFS_PATH.read_text())
except (json.JSONDecodeError, OSError):
pass
return {"entry_point_style": "topbar"}
def _save_prefs(data: dict[str, str]) -> None:
PREFS_PATH.write_text(json.dumps(data))
class DiagnoseRequest(BaseModel):
query: str
since: str | None = None
until: str | None = None
class SettingsBody(BaseModel):
entry_point_style: str
class IncidentCreate(BaseModel): class IncidentCreate(BaseModel):
label: str label: str
issue_type: str = "" issue_type: str = ""
@ -167,6 +192,38 @@ def diagnose(
} }
@router.post("/api/diagnose")
def diagnose_post(body: DiagnoseRequest) -> dict:
if not body.query.strip():
return {
"summary": {
"total": 0, "window_start": None, "window_end": None,
"time_detected": False, "by_severity": {}, "by_source": {},
},
"entries": [],
}
result = _diagnose(DB_PATH, query=body.query, since=body.since, until=body.until)
return {
"summary": result["summary"],
"entries": [dataclasses.asdict(r) for r in result["entries"]],
}
@router.get("/api/settings")
def get_settings() -> dict:
return _load_prefs()
@router.patch("/api/settings")
def patch_settings(body: SettingsBody) -> dict:
if body.entry_point_style not in ("topbar", "fab"):
raise HTTPException(status_code=422, detail="entry_point_style must be 'topbar' or 'fab'")
prefs = _load_prefs()
prefs["entry_point_style"] = body.entry_point_style
_save_prefs(prefs)
return prefs
@router.get("/api/sources") @router.get("/api/sources")
def list_sources() -> dict: def list_sources() -> dict:
return {"sources": _list_sources(DB_PATH)} return {"sources": _list_sources(DB_PATH)}