"""Anthropic 协议路由。""" from __future__ import annotations import json from collections.abc import AsyncIterator from typing import Any from fastapi import APIRouter, Depends, Request from fastapi.responses import JSONResponse, StreamingResponse from core.api.auth import require_api_key from core.api.chat_handler import ChatHandler from core.api.routes import get_chat_handler, resolve_request_model, check_pro_model_access from core.protocol.anthropic import AnthropicProtocolAdapter from core.protocol.service import CanonicalChatService def create_anthropic_router() -> APIRouter: router = APIRouter(dependencies=[Depends(require_api_key)]) adapter = AnthropicProtocolAdapter() @router.post("/anthropic/{provider}/v1/messages") async def messages( provider: str, request: Request, handler: ChatHandler = Depends(get_chat_handler), ) -> Any: return await _messages(provider, request, handler) @router.post("/{provider}/v1/messages") async def messages_legacy( provider: str, request: Request, handler: ChatHandler = Depends(get_chat_handler), ) -> Any: return await _messages(provider, request, handler) async def _messages( provider: str, request: Request, handler: ChatHandler, ) -> Any: raw_body = await request.json() try: canonical_req = resolve_request_model( provider, adapter.parse_request(provider, raw_body), ) except Exception as exc: status, payload = adapter.render_error(exc) return JSONResponse(status_code=status, content=payload) pro_err = check_pro_model_access(request, provider, canonical_req.model) if pro_err is not None: return pro_err service = CanonicalChatService(handler) if canonical_req.stream: async def sse_stream() -> AsyncIterator[str]: try: async for event in adapter.render_stream( canonical_req, service.stream_raw(canonical_req), ): yield event except Exception as exc: status, payload = adapter.render_error(exc) del status yield ( "event: error\n" f"data: {json.dumps(payload, ensure_ascii=False)}\n\n" ) return StreamingResponse( sse_stream(), media_type="text/event-stream", headers={ "Cache-Control": "no-cache", "Connection": "keep-alive", "X-Accel-Buffering": "no", }, ) try: raw_events = await service.collect_raw(canonical_req) return adapter.render_non_stream(canonical_req, raw_events) except Exception as exc: status, payload = adapter.render_error(exc) return JSONResponse(status_code=status, content=payload) return router