04bdccf189
Task 5-3-01: api/defense.py — POST /v1/defense/start (DefenseRecord + first examiner
question persisted + voice descriptor + trace_complete disclosure — the defense does
NOT gate on completeness, the grader does per G-4), POST /{id}/answer ({text} or
multipart audio -> STT via VoiceProvider; follow-up question; per-turn latency
stt_ms/llm_ms/tts_ms), GET /{id}/audio/{turn_id} (streaming TTS WAV), POST /{id}/finish
(DefenseVerdict via D-020 + A-109 integrity signals: long pauses computed from turn
metadata at PAUSE_THRESHOLD_MS=15s), GET /{id} (ordered transcript + signals + status).
Lifespan wires DefenseStore + voice provider + ExaminerAgent. python-multipart dep for
audio parsing.
11 endpoint tests green (full loop mock voice + mock LLM; long-pause signal; 404s; 422
no-body; audio streaming). Suite 378 green; ruff clean.
---ci---
phase: 5
milestone: v0.3
status: execute
requirements: {covered: [REQ-3-006], partial: []}
---/ci---
80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
"""FastAPI dependencies — provider, settings, sessions, agents via app.state (DI)."""
|
|
|
|
from fastapi import Request
|
|
|
|
from ..agents.examiner import ExaminerAgent
|
|
from ..agents.registry import AgentRegistry
|
|
from ..agents.session import SessionStore
|
|
from ..config import Settings
|
|
from ..grading.engine import GradingEngine
|
|
from ..grading.store import GradeStore
|
|
from ..llm.base import LLMProvider
|
|
from ..sandbox.manager import SandboxManager
|
|
from ..sandbox.workdir import SandboxDir
|
|
from ..telemetry.ingest import TraceIntegrityMap
|
|
from ..telemetry.store import TraceStore
|
|
from ..variants.generator import VariantGenerator
|
|
from ..variants.store import VariantStore
|
|
from ..voice.base import VoiceProvider
|
|
from ..voice.defense_store import DefenseStore
|
|
|
|
|
|
def get_settings(request: Request) -> Settings:
|
|
return request.app.state.settings
|
|
|
|
|
|
def get_provider(request: Request) -> LLMProvider:
|
|
return request.app.state.provider
|
|
|
|
|
|
def get_session_store(request: Request) -> SessionStore:
|
|
return request.app.state.session_store
|
|
|
|
|
|
def get_agent_registry(request: Request) -> AgentRegistry:
|
|
return request.app.state.agent_registry
|
|
|
|
|
|
def get_sandbox_manager(request: Request) -> SandboxManager:
|
|
return request.app.state.sandbox_manager
|
|
|
|
|
|
def get_sandbox_test_layout(request: Request) -> SandboxDir | None:
|
|
"""Optional test seam (app.state.sandbox_test_layout); always None in prod."""
|
|
return getattr(request.app.state, "sandbox_test_layout", None)
|
|
|
|
|
|
def get_trace_store(request: Request) -> TraceStore:
|
|
return request.app.state.trace_store
|
|
|
|
|
|
def get_trace_integrity(request: Request) -> TraceIntegrityMap:
|
|
return request.app.state.trace_integrity
|
|
|
|
|
|
def get_grade_store(request: Request) -> GradeStore:
|
|
return request.app.state.grade_store
|
|
|
|
|
|
def get_grading_engine(request: Request) -> GradingEngine:
|
|
return request.app.state.grading_engine
|
|
|
|
|
|
def get_variant_generator(request: Request) -> VariantGenerator:
|
|
return request.app.state.variant_generator
|
|
|
|
|
|
def get_variant_store(request: Request) -> VariantStore:
|
|
return request.app.state.variant_store
|
|
|
|
def get_voice_store(request: Request) -> DefenseStore:
|
|
return request.app.state.defense_store
|
|
|
|
|
|
def get_voice_provider(request: Request) -> VoiceProvider:
|
|
return request.app.state.voice_provider
|
|
|
|
|
|
def get_examiner(request: Request) -> ExaminerAgent:
|
|
return request.app.state.examiner_agent
|