AgentEvalTool/backend/agenteval/web/routers/scenarios.py
sinohqb 17aeba80dd v0.3-s4: 场景模板库 + WS 自动重连 + PageWrapper 复用
## 场景模板库(S4-1)
- scenarios/templates.py: 6 个内置模板
  - 单轮问答基础 / 多轮对话 / 动态 LLM 生成 / 安全合规检测 / JSON 接口校验 / 加权评分
  - 每个模板附带对应规则配置(含 v0.3 新规则)
- routers/scenarios.py: GET /api/scenarios/templates + GET /api/scenarios/templates/{id}
- api.ts: scenariosApi.listTemplates() / getTemplate()
- Scenarios.tsx: 「从模板新建」按钮 + 卡片式模板选择弹窗
  - 选择后预填名称/描述/标签/cases JSON/llm_config,直接进入编辑 Drawer

## WebSocket 自动重连(S4-2)
- useRunSession.ts: connectWs() 函数 + 指数退避重连
  - 异常断开(非 1000/clean)时自动重试,最多 5 次
  - 延迟:1s → 2s → 4s → 8s → 16s(上限 30s)
  - 超出重试次数后降级 REST 获取最终状态
  - reconnectTimerRef 在组件卸载时清理,无内存泄漏

## PageWrapper 复用(S4-3)
- PageWrapper.tsx: 升级 inline 模式匹配全高页面的 padding 页头样式
- Home / Targets / Scenarios: 用 PageWrapper inline+fullHeight 替换重复内联页头
- Home.tsx: 去掉 unused `colors` import

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-17 12:05:18 +08:00

61 lines
2.0 KiB
Python

"""API routes for evaluation scenarios."""
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import Session
from agenteval.models import Scenario
from agenteval.scenarios.templates import get_template, list_templates
from agenteval.storage.repository import ScenarioRepository
from agenteval.web.deps import get_db
router = APIRouter()
@router.get("/templates")
def list_scenario_templates() -> list[dict]:
"""Return built-in scenario templates (no auth required for discovery)."""
return list_templates()
@router.get("/templates/{template_id}")
def get_scenario_template(template_id: str) -> dict:
tpl = get_template(template_id)
if not tpl:
raise HTTPException(status_code=404, detail="template not found")
return tpl
@router.get("")
def list_scenarios(session: Session = Depends(get_db)) -> list[dict]:
return [s.model_dump() for s in ScenarioRepository(session).list_all()]
@router.post("")
def create_scenario(scenario: Scenario, session: Session = Depends(get_db)) -> dict:
created = ScenarioRepository(session).create(scenario)
return created.model_dump()
@router.get("/{scenario_id}")
def get_scenario(scenario_id: str, session: Session = Depends(get_db)) -> dict:
scenario = ScenarioRepository(session).get(scenario_id)
if not scenario:
raise HTTPException(status_code=404, detail="scenario not found")
return scenario.model_dump()
@router.put("/{scenario_id}")
def update_scenario(scenario_id: str, scenario: Scenario, session: Session = Depends(get_db)) -> dict:
scenario.id = scenario_id
updated = ScenarioRepository(session).update(scenario)
if not updated:
raise HTTPException(status_code=404, detail="scenario not found")
return updated.model_dump()
@router.delete("/{scenario_id}")
def delete_scenario(scenario_id: str, session: Session = Depends(get_db)) -> dict:
if not ScenarioRepository(session).delete(scenario_id):
raise HTTPException(status_code=404, detail="scenario not found")
return {"ok": True}