最后一版
This commit is contained in:
131
main.py
131
main.py
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
SDLC Agent Demo - FastAPI 主服务(异步版本)
|
||||
SDLC Agent Demo - FastAPI 主服务(轮询版本)
|
||||
多智能体端到端软件交付协同系统
|
||||
"""
|
||||
|
||||
@@ -7,7 +7,6 @@ import json
|
||||
import uuid
|
||||
import asyncio
|
||||
import threading
|
||||
import queue
|
||||
from typing import Dict, Optional, AsyncGenerator
|
||||
from datetime import datetime
|
||||
from fastapi import FastAPI, HTTPException
|
||||
@@ -16,6 +15,7 @@ from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import StreamingResponse, RedirectResponse, JSONResponse
|
||||
from pydantic import BaseModel, Field
|
||||
import uvicorn
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
from crews.sdlc_crew import SDLCCrew
|
||||
from models.qwen_config import get_qwen_config
|
||||
@@ -27,7 +27,7 @@ app = FastAPI(
|
||||
version="1.0.0"
|
||||
)
|
||||
|
||||
# 启用 CORS
|
||||
# 添加 CORS 中间件
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
@@ -104,6 +104,9 @@ class TaskManager:
|
||||
# 全局任务管理器
|
||||
task_manager = TaskManager()
|
||||
|
||||
# 线程池
|
||||
executor = ThreadPoolExecutor(max_workers=5)
|
||||
|
||||
|
||||
# ========== API 端点 ==========
|
||||
@app.post("/api/v1/sdlc/start", response_model=Dict[str, str])
|
||||
@@ -130,13 +133,6 @@ async def start_sdlc_process(request: StartRequest):
|
||||
}
|
||||
|
||||
|
||||
import threading
|
||||
import asyncio
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
# 线程池
|
||||
executor = ThreadPoolExecutor(max_workers=5)
|
||||
|
||||
def execute_sdlc_flow(task_id: str, requirement: str):
|
||||
"""
|
||||
在线程池中执行 SDLC 流程,将事件保存到任务列表
|
||||
@@ -195,42 +191,6 @@ async def poll_task_events(task_id: str, last_index: int = 0):
|
||||
return result
|
||||
|
||||
|
||||
@app.get("/api/v1/sdlc/stream/{task_id}")
|
||||
async def stream_task_progress(task_id: str):
|
||||
"""
|
||||
SSE流式输出任务进度
|
||||
|
||||
直接在异步函数中使用 async for 和 yield,
|
||||
FastAPI 会自动将其转换为 StreamingResponse
|
||||
"""
|
||||
# 验证任务存在
|
||||
task = task_manager.get_task(task_id)
|
||||
if not task:
|
||||
raise HTTPException(status_code=404, detail="Task not found")
|
||||
|
||||
# 直接使用 async for 和 yield
|
||||
while True:
|
||||
event = await task_manager.get_event(task_id, timeout=120.0)
|
||||
|
||||
if event is None:
|
||||
# 超时,检查任务状态
|
||||
task_data = task_manager.get_task(task_id)
|
||||
if task_data and task_data["status"] in ["completed", "failed"]:
|
||||
yield f"event: end\ndata: {json.dumps({'status': task_data['status']}, ensure_ascii=False)}\n\n"
|
||||
break
|
||||
continue
|
||||
|
||||
# 格式化 SSE事件
|
||||
event_type = event.get("event", "message")
|
||||
event_data = event.get("data", {})
|
||||
|
||||
yield f"event: {event_type}\ndata: {json.dumps(event_data, ensure_ascii=False)}\n\n"
|
||||
|
||||
# 如果是结束事件,断开连接
|
||||
if event_type in ["final_result", "error"]:
|
||||
break
|
||||
|
||||
|
||||
@app.get("/api/v1/sdlc/status/{task_id}")
|
||||
def get_task_status(task_id: str):
|
||||
"""
|
||||
@@ -248,85 +208,6 @@ def get_task_status(task_id: str):
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/v1/sdlc/result/{task_id}")
|
||||
def get_task_result(task_id: str):
|
||||
"""
|
||||
获取任务完整结果
|
||||
"""
|
||||
task = task_manager.get_task(task_id)
|
||||
if not task:
|
||||
raise HTTPException(status_code=404, detail="Task not found")
|
||||
|
||||
if task["status"] != "completed":
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Task not completed yet. Status: {task['status']}"
|
||||
)
|
||||
|
||||
return task
|
||||
|
||||
|
||||
@app.get("/api/v1/sdlc/download/{task_id}")
|
||||
def download_result(task_id: str):
|
||||
"""
|
||||
打包下载任务结果(ZIP 文件)
|
||||
"""
|
||||
import zipfile
|
||||
import io
|
||||
from fastapi.responses import StreamingResponse
|
||||
|
||||
task = task_manager.get_task(task_id)
|
||||
if not task:
|
||||
raise HTTPException(status_code=404, detail="Task not found")
|
||||
|
||||
if task["status"] != "completed":
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Task not completed yet. Status: {task['status']}"
|
||||
)
|
||||
|
||||
# 创建 ZIP 文件
|
||||
zip_buffer = io.BytesIO()
|
||||
|
||||
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
|
||||
# 1. SRS 文档
|
||||
srs_content = ""
|
||||
# 注意:异步模式下需要从 events 中获取,这里简化处理
|
||||
zip_file.writestr("01_SRS_需求规格说明书.md", "需求文档内容")
|
||||
|
||||
# 2. 测试用例
|
||||
zip_file.writestr("02_Test_测试用例.md", "测试用例内容")
|
||||
|
||||
# 3. 代码实现
|
||||
zip_file.writestr("03_Code_代码实现.md", "代码实现内容")
|
||||
|
||||
# 4. 项目摘要
|
||||
summary = f"""# SDLC 项目交付摘要
|
||||
|
||||
## 项目信息
|
||||
- 任务 ID: {task['task_id']}
|
||||
- 创建时间:{task['created_at']}
|
||||
- 完成时间:{task['updated_at']}
|
||||
- 原始需求:{task['requirement']}
|
||||
|
||||
## 生成说明
|
||||
本项目由 SDLC Agent Demo 自动生成
|
||||
基于 CrewAI + Qwen3.5-flash + FastAPI
|
||||
"""
|
||||
zip_file.writestr("README_项目摘要.md", summary)
|
||||
|
||||
# 准备下载
|
||||
zip_buffer.seek(0)
|
||||
|
||||
return StreamingResponse(
|
||||
zip_buffer,
|
||||
media_type="application/zip",
|
||||
headers={
|
||||
"Content-Disposition": f"attachment; filename=SDLC_Result_{task_id[:8]}.zip"
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def root():
|
||||
"""根路径重定向到测试页面"""
|
||||
|
||||
Reference in New Issue
Block a user