Add eval harness (#62 P4), status frames (#96), and agentic runs (#63).
CI / test (pull_request) Successful in 11s
Unit Tests / test (pull_request) Successful in 10s

Ship the Phase 4 accuracy eval suite with a manual Gitea workflow, emit
versioned WS status frames during grounded chat, and introduce opt-in
agent infrastructure (Redis/Celery, AgentRun/Step, tools, orchestrator)
gated by ALLOW_AGENTIC_TASKS so default chat behaviour stays unchanged.
This commit is contained in:
2026-08-04 06:07:26 -05:00
parent e1e086a474
commit 9c0b648db3
46 changed files with 4669 additions and 117 deletions
+96
View File
@@ -0,0 +1,96 @@
"""REST API for AgentRun rehydration + cancel (#63)."""
from __future__ import annotations
from django.utils import timezone
from rest_framework import serializers, status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from chat_backend.models import AgentRun, AgentStep
class AgentStepSerializer(serializers.ModelSerializer):
class Meta:
model = AgentStep
fields = (
"id",
"index",
"parent_step",
"title",
"status",
"is_subagent",
"tool_name",
"tool_input",
"tool_output",
"error",
"started_at",
"completed_at",
"created",
)
class AgentRunSerializer(serializers.ModelSerializer):
steps = AgentStepSerializer(many=True, read_only=True)
class Meta:
model = AgentRun
fields = (
"id",
"conversation",
"goal",
"title",
"status",
"plan",
"result",
"error",
"model_orchestrator",
"model_subagent",
"tool_call_count",
"iteration_count",
"cancel_requested",
"started_at",
"completed_at",
"created",
"steps",
)
class AgentRunListView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
qs = (
AgentRun.objects.filter(user=request.user)
.prefetch_related("steps")
.order_by("-created")[:50]
)
return Response(AgentRunSerializer(qs, many=True).data)
class AgentRunDetailView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request, run_id: int):
try:
run = AgentRun.objects.prefetch_related("steps").get(
pk=run_id, user=request.user
)
except AgentRun.DoesNotExist:
return Response({"detail": "Not found."}, status=status.HTTP_404_NOT_FOUND)
return Response(AgentRunSerializer(run).data)
class AgentRunCancelView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, run_id: int):
try:
run = AgentRun.objects.get(pk=run_id, user=request.user)
except AgentRun.DoesNotExist:
return Response({"detail": "Not found."}, status=status.HTTP_404_NOT_FOUND)
if run.is_terminal:
return Response(AgentRunSerializer(run).data)
run.mark_cancelled()
return Response(AgentRunSerializer(run).data)