Files
bxh/app/api/question_traces.py

106 lines
3.1 KiB
Python

"""STEP 02 — Question Traces endpoints."""
from fastapi import APIRouter, Depends, HTTPException
from app.auth import CurrentUser
from app.config import settings
from app.contracts import QuestionTraceCreate, QuestionTraceBatch
from app.db import (
create_question_trace,
list_question_traces,
get_question_trace,
update_question_trace,
)
from app.project_context import ProjectContext, get_project_context
router = APIRouter()
@router.post("/question-traces")
async def _create(
body: QuestionTraceCreate,
context: ProjectContext = Depends(get_project_context),
_user: CurrentUser = None,
):
data = body.model_dump()
data.setdefault("tenant_id", context.tenant_id)
data.setdefault("project_id", context.project_id)
return await create_question_trace(data)
@router.post("/question-traces/batch")
async def _batch(
body: QuestionTraceBatch,
context: ProjectContext = Depends(get_project_context),
_user: CurrentUser = None,
):
results = []
for q in body.questions:
data = q.model_dump()
data.setdefault("tenant_id", context.tenant_id)
data.setdefault("project_id", context.project_id)
results.append(await create_question_trace(data))
return {"count": len(results), "traces": results}
@router.post("/question-traces/simulate")
async def _simulate(
context: ProjectContext = Depends(get_project_context),
_user: CurrentUser = None,
):
"""Create traces from enabled sim questions, audit them in the background."""
from app.db import list_simulation_questions, create_audit_run
from app.agents.auditor import schedule_audit
tenant = context.tenant_id
project = context.project_id
sim_questions = await list_simulation_questions(tenant, project)
enabled = [q for q in sim_questions if q.get("enabled")]
created = []
for sq in enabled:
trace = await create_question_trace({
"tenant_id": tenant,
"project_id": project,
"source": "simulated",
"origin": "panel",
"question_text": sq["question_text"],
"scenario_tags": sq.get("scenario_tags", []),
})
created.append(trace)
trace_ids = [t["id"] for t in created]
if not trace_ids:
return {"created": 0, "run_id": None, "total": 0}
run_id = await create_audit_run("simulate", len(trace_ids))
schedule_audit(trace_ids, run_id)
return {"created": len(created), "run_id": run_id, "total": len(trace_ids)}
@router.get("/question-traces")
async def _list(
source: str | None = None,
suggested_action: str | None = None,
limit: int = 50,
offset: int = 0,
context: ProjectContext = Depends(get_project_context),
_user: CurrentUser = None,
):
return await list_question_traces(
context.tenant_id,
context.project_id,
source,
suggested_action,
limit,
offset,
)
@router.get("/question-traces/{trace_id}")
async def _get(trace_id: int, _user: CurrentUser = None):
trace = await get_question_trace(trace_id)
if not trace:
raise HTTPException(404, "Question trace not found")
return trace