106 lines
3.1 KiB
Python
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
|