diff --git a/apps/api/ww_api/routers/projects.py b/apps/api/ww_api/routers/projects.py index 30daa56..3258833 100644 --- a/apps/api/ww_api/routers/projects.py +++ b/apps/api/ww_api/routers/projects.py @@ -105,6 +105,13 @@ _ACCEPT_ERRORS: dict[int | str, dict[str, Any]] = { 409: {"model": ErrorEnvelope, "description": "存在未裁决冲突"}, 503: {"model": ErrorEnvelope, "description": "LLM 不可用"}, } +# SSE 端点:如实声明 200 的 media type 为 text/event-stream(否则 OpenAPI 误标 json)。 +_SSE_RESPONSE: dict[int | str, dict[str, Any]] = { + 200: { + "description": "SSE 事件流(`event: \\ndata: `,见 memory/contracts.md)", + "content": {"text/event-stream": {}}, + } +} ProjectRepoDep = Annotated[ProjectRepo, Depends(get_project_repo)] ChapterRepoDep = Annotated[ChapterRepo, Depends(get_chapter_repo)] @@ -256,7 +263,7 @@ def _encode_sse(event: SseEvent) -> str: return f"event: {event.event}\ndata: {payload}\n\n" -@router.post("/{project_id}/chapters/{chapter_no}/draft") +@router.post("/{project_id}/chapters/{chapter_no}/draft", responses=_SSE_RESPONSE) async def stream_draft( project_id: uuid.UUID, chapter_no: int, @@ -319,7 +326,7 @@ async def stream_draft( ) -@router.post("/{project_id}/chapters/{chapter_no}/rewrite") +@router.post("/{project_id}/chapters/{chapter_no}/rewrite", responses=_SSE_RESPONSE) async def stream_rewrite( project_id: uuid.UUID, chapter_no: int, @@ -532,7 +539,7 @@ async def _resolve_review_draft( return saved.content -@router.post("/{project_id}/chapters/{chapter_no}/review") +@router.post("/{project_id}/chapters/{chapter_no}/review", responses=_SSE_RESPONSE) async def review_chapter( project_id: uuid.UUID, chapter_no: int,