Files
DEMO-AGENT/review_agent/views.py

112 lines
4.0 KiB
Python

from django.contrib.auth.decorators import login_required
from django.db.models import Count, Q
from django.http import HttpRequest, HttpResponse, JsonResponse, StreamingHttpResponse
from django.shortcuts import redirect, render
from django.views.decorators.http import require_http_methods
from .services import (
create_conversation,
get_conversation_for_user,
list_conversations,
send_message,
stream_message,
)
from .models import Conversation, FileAttachment, FileSummaryBatch
@login_required
@require_http_methods(["GET", "POST"])
def workspace(request: HttpRequest) -> HttpResponse:
"""Renders the review-agent workspace and handles conversation actions."""
if request.method == "POST":
action = request.POST.get("action")
conversation = get_conversation_for_user(request.user, request.POST.get("conversation_id"))
if action == "new_conversation":
conversation = create_conversation(request.user)
return redirect(f"/?conversation={conversation.pk}")
if action == "send_message":
content = (request.POST.get("prompt") or "").strip()
if not conversation:
conversation = create_conversation(request.user)
if content:
send_message(conversation, content)
return redirect(f"/?conversation={conversation.pk}")
search = (request.GET.get("q") or "").strip()
conversations = list_conversations(request.user, search)
current = get_conversation_for_user(request.user, request.GET.get("conversation"))
if current is None and conversations.exists():
current = conversations.first()
return render(
request,
"home.html",
{
"page_title": "审核智能体",
"search_query": search,
"conversations": conversations,
"current_conversation": current,
"messages": current.messages.all() if current else [],
"attachments": FileAttachment.objects.filter(conversation=current).order_by("original_name", "-version_no") if current else [],
"summary_batches": FileSummaryBatch.objects.filter(conversation=current).prefetch_related("node_runs").order_by("-created_at")[:5] if current else [],
},
)
@login_required
@require_http_methods(["GET"])
def attachment_manager(request: HttpRequest) -> HttpResponse:
conversations = (
Conversation.objects.filter(user=request.user)
.annotate(
attachment_count=Count(
"file_attachments",
filter=~Q(file_attachments__upload_status=FileAttachment.UploadStatus.DELETED),
)
)
.order_by("-updated_at", "-id")
)
selected = get_conversation_for_user(request.user, request.GET.get("conversation"))
attachments = (
FileAttachment.objects.filter(conversation=selected)
.order_by("original_name", "-version_no")
if selected
else []
)
return render(
request,
"attachment_manager.html",
{
"page_title": "附件管理",
"conversations": conversations,
"selected_conversation": selected,
"attachments": attachments,
},
)
@login_required
@require_http_methods(["POST"])
def stream_chat(request: HttpRequest) -> HttpResponse:
"""Streams one assistant reply so the UI can render incremental output."""
content = (request.POST.get("prompt") or "").strip()
if not content:
return JsonResponse({"error": "消息内容不能为空。"}, status=400)
conversation = get_conversation_for_user(request.user, request.POST.get("conversation_id"))
if not conversation:
conversation = create_conversation(request.user)
response = StreamingHttpResponse(
streaming_content=stream_message(conversation, content),
content_type="text/event-stream",
)
response["Cache-Control"] = "no-cache"
response["X-Accel-Buffering"] = "no"
return response