""" Review Task API Routes 审核任务API路由 - 提供过程中审核和生成后审核的管理接口 """ from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks from typing import List, Optional import asyncio from app.models.review_task import ( ReviewTask, ReviewMode, ReviewAction, ProcessReviewRequest, UserReviewActionRequest, PostCreationReviewRequest, PostCreationReviewResult, ReviewTaskStatus ) from app.core.review.review_task_manager import ( ReviewTaskManager, get_review_task_manager, StreamReviewHelper ) from app.db.repositories import project_repo, episode_repo from app.models.project import SeriesProject, Episode from app.utils.logger import get_logger logger = get_logger(__name__) router = APIRouter(prefix="/review-task", tags=["审核任务"]) # ============================================ # 依赖注入 # ============================================ async def get_task_manager() -> ReviewTaskManager: """获取审核任务管理器""" return get_review_task_manager() async def get_stream_helper(project_id: str) -> StreamReviewHelper: """获取流式审核助手""" task_manager = get_review_task_manager() return StreamReviewHelper(project_id, task_manager) # ============================================ # 过程中审核 API # ============================================ @router.post("/process") async def create_process_review_task( request: ProcessReviewRequest, task_manager: ReviewTaskManager = Depends(get_task_manager) ): """ 创建过程中审核任务 由Agent在流式输出过程中调用,推送审核任务到前端。 前端通过WebSocket接收通知并等待用户确认。 """ try: # 创建审核任务 task = await task_manager.create_process_review_task(request) # 通过WebSocket推送到前端 from app.api.v1.websocket import manager await manager.send_to_project(request.project_id, { "type": "review_task_created", "data": { "task_id": task.id, "mode": task.mode.value, "issue_type": task.issue_type, "issue_description": task.issue_description, "severity": task.severity, "location": task.location.dict(), "available_actions": [action.value for action in task.available_actions], "suggestion": task.suggestion, "trigger_source": task.trigger_source.value, "created_at": task.created_at.isoformat() } }) logger.info(f"过程中审核任务已创建并推送: {task.id}") return { "success": True, "task_id": task.id, "message": "审核任务已创建" } except Exception as e: logger.error(f"创建过程中审核任务失败: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"创建审核任务失败: {str(e)}" ) @router.post("/process/{task_id}/action") async def handle_process_review_action( task_id: str, request: UserReviewActionRequest, task_manager: ReviewTaskManager = Depends(get_task_manager) ): """ 处理用户对过程中审核任务的响应 Args: task_id: 任务ID request: 用户操作请求 Returns: 处理结果 """ try: # 处理用户操作 task = await task_manager.handle_user_review_action(request) # 通过WebSocket通知前端任务已完成 from app.api.v1.websocket import manager await manager.send_to_project(task.project_id or "unknown", { "type": "review_task_completed", "data": { "task_id": task_id, "status": task.status.value, "user_response": task.user_response, "completed_at": task.completed_at.isoformat() if task.completed_at else None } }) logger.info(f"用户操作已处理: {task_id}, 操作: {request.action.value}") return { "success": True, "task_id": task_id, "status": task.status.value, "message": "操作已处理" } except ValueError as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=str(e) ) except Exception as e: logger.error(f"处理用户操作失败: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"处理失败: {str(e)}" ) @router.get("/process/pending/{project_id}") async def get_pending_process_tasks( project_id: str, task_manager: ReviewTaskManager = Depends(get_task_manager) ) -> List[ReviewTask]: """ 获取项目所有待处理的过程审核任务 Args: project_id: 项目ID Returns: List[ReviewTask]: 待处理任务列表 """ return task_manager.get_pending_process_tasks(project_id) # ============================================ # 生成后审核 API # ============================================ @router.post("/post-creation") async def execute_post_creation_review( request: PostCreationReviewRequest, task_manager: ReviewTaskManager = Depends(get_task_manager), background_tasks: BackgroundTasks = None ): """ 执行生成后审核 根据用户配置的规则/Skill进行自动检查,根据阈值报告问题。 Args: request: 生成后审核请求 background_tasks: FastAPI后台任务管理器 Returns: PostCreationReviewResult: 审核结果 """ # 获取项目 project = await project_repo.get(request.project_id) if not project: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"项目不存在: {request.project_id}" ) # 获取剧集 episodes = await episode_repo.list_by_project(request.project_id) episode = next((ep for ep in episodes if ep.id == request.episode_id), None) if not episode: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"剧集不存在: {request.episode_id}" ) try: # 获取审核配置 from app.models.review import ReviewConfig raw_config = getattr(project, 'reviewConfig', None) if isinstance(raw_config, dict): config = ReviewConfig(**raw_config) elif raw_config is None: config = ReviewConfig() else: config = raw_config # 确保dimension_settings是dict if not hasattr(config, 'dimension_settings') or not isinstance(config.dimension_settings, dict): config.dimension_settings = {} # 执行审核 result = await task_manager.execute_post_creation_review( request=request, project_config=config ) # 更新剧集审核结果 from app.models.review import ReviewResult review_result = ReviewResult( id=f"review_{episode.id}", episode_id=episode.id, episode_number=episode.number, project_id=project.id, overall_score=result.overall_score or 75.0, passed=result.passed, passed_dimensions=0, total_dimensions=1, dimension_scores=[], issues=[], issue_count=result.task_count, high_severity_count=sum(1 for t in result.tasks if t.severity == "high"), medium_severity_count=sum(1 for t in result.tasks if t.severity == "medium"), low_severity_count=sum(1 for t in result.tasks if t.severity == "low") ) # 保存审核结果到剧集 await episode_repo.update(episode.id, { "reviewResult": review_result.dict() }) # 通过WebSocket推送审核结果 from app.api.v1.websocket import manager await manager.send_to_project(request.project_id, { "type": "post_creation_review_completed", "data": { "episode_id": episode.id, "episode_number": episode.number, "overall_score": result.overall_score, "passed": result.passed, "task_count": result.task_count, "tasks": [ { "id": task.id, "issue_type": task.issue_type, "issue_description": task.issue_description, "severity": task.severity, "location": task.location.dict(), "available_actions": [action.value for action in task.available_actions], "status": task.status.value, "suggestion": task.suggestion } for task in result.tasks ] } }) logger.info(f"生成后审核完成: {episode.id}, 分数: {result.overall_score}") return result except Exception as e: logger.error(f"生成后审核失败: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"审核失败: {str(e)}" ) @router.post("/post-creation/{task_id}/action") async def handle_post_creation_task_action( task_id: str, request: UserReviewActionRequest, task_manager: ReviewTaskManager = Depends(get_task_manager) ): """ 处理用户对生成后审核任务的响应 Args: task_id: 任务ID request: 用户操作请求 Returns: 处理结果 """ try: # 处理用户操作 task = await task_manager.handle_user_review_action(request) # 如果修改了内容,更新剧集内容 if request.action == ReviewAction.MODIFY and request.modified_content: # 获取剧集 episodes = await episode_repo.list_by_project(task.project_id or "") episode = next((ep for ep in episodes if ep.id == task.episode_id), None) if episode: # 更新内容 await episode_repo.update(episode.id, { "content": request.modified_content }) # 通过WebSocket通知内容已更新 from app.api.v1.websocket import manager await manager.send_to_project(task.project_id or "", { "type": "episode_content_updated", "data": { "episode_id": episode.id, "episode_number": episode.number } }) # 通过WebSocket通知任务已完成 from app.api.v1.websocket import manager await manager.send_to_project(task.project_id or "", { "type": "review_task_completed", "data": { "task_id": task_id, "status": task.status.value, "user_response": task.user_response, "completed_at": task.completed_at.isoformat() if task.completed_at else None } }) logger.info(f"生成后审核任务已处理: {task_id}, 操作: {request.action.value}") return { "success": True, "task_id": task_id, "status": task.status.value, "message": "操作已处理" } except ValueError as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=str(e) ) except Exception as e: logger.error(f"处理生成后审核任务操作失败: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"处理失败: {str(e)}" ) # ============================================ # Agent流式审核辅助 API # ============================================ @router.post("/agent/push") async def agent_push_review_task( project_id: str, issue_type: str, issue_description: str, severity: str = "medium", skill_id: Optional[str] = None, suggestion: Optional[str] = None, task_manager: ReviewTaskManager = Depends(get_task_manager) ): """ Agent推送审核任务(简化版) 由Agent在流式输出过程中调用,推送审核任务。 Args: project_id: 项目ID issue_type: 问题类型 issue_description: 问题描述 severity: 严重程度 skill_id: 使用的Skill ID suggestion: 修改建议 Returns: 创建的任务ID """ try: from app.models.review_task import ReviewTaskLocation task = await task_manager.create_process_review_task( ProcessReviewRequest( project_id=project_id, issue_type=issue_type, issue_description=issue_description, severity=severity, location=ReviewTaskLocation(), trigger_source="agent_auto", skill_id=skill_id, suggestion=suggestion ) ) return { "success": True, "task_id": task.id, "message": "审核任务已推送" } except Exception as e: logger.error(f"Agent推送审核任务失败: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"推送审核任务失败: {str(e)}" )