CI / lint / typecheck / import-linter / tests / secrets (push) Canceled after 0s
- agent: ag_conversation/ag_message 表(迁移0007),上下文组装注入最近报告画像摘要 (report.profile.latest_profile_summary 经 apps 层闭包注入,同层不互调),历史带最近 AGENT_HISTORY_TURNS=10 轮;POST/GET /agent/conversations 与消息历史接口 - agent 修复:ChatRequest.conversation_id 改 str(雪花ID超2^53,JS Number丢精度); _build_context 挪进 reserve commit 后同一 try,异常走 refund 兜底 - report: rp_feedback(维度反馈 upsert,认同率/修正率 SQL 可算,T-P3-21 最小版—— L1 记忆未建,不回写结论)+ rp_reservation(预约留资幂等,T-P3-22,预约率口径 行数/full_report.card_view 去重曝光,门槛≥8%),迁移0008 - 测试:全量 606 passed;ruff/mypy/lint-imports 全绿;E2E 真实 deepseek-v4-flash 验证 画像注入与历史携带
103 lines
2.8 KiB
Python
103 lines
2.8 KiB
Python
"""FastAPI application factory (架构文档 §3.1 L3 API 层).
|
|
|
|
The API layer only orchestrates: auth, validation, idempotency, quota,
|
|
unified response, OpenAPI. Business rules live in ``packages/<domain>``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import AsyncIterator
|
|
from contextlib import asynccontextmanager
|
|
|
|
from fastapi import FastAPI
|
|
|
|
from apps.api.deps import build_llm_gateway
|
|
from apps.api.routers import (
|
|
agent,
|
|
auth,
|
|
auth_sms,
|
|
events,
|
|
health,
|
|
kb,
|
|
quota,
|
|
reports,
|
|
reservations,
|
|
tasks,
|
|
uploads,
|
|
)
|
|
from packages.shared.config import Settings, get_settings
|
|
from packages.shared.db import dispose_engine
|
|
from packages.shared.handlers import install_exception_handlers
|
|
from packages.shared.logging import configure_logging, get_logger
|
|
from packages.shared.middleware import RequestContextMiddleware, install_version_alias
|
|
from packages.shared.observability import setup_tracing
|
|
from packages.shared.redis_client import close_redis
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
|
settings: Settings = get_settings()
|
|
app.state.llm_gateway = build_llm_gateway(settings)
|
|
logger.info(
|
|
"api_started",
|
|
env=settings.app_env,
|
|
api_prefix=settings.api_prefix,
|
|
llm_primary=settings.llm_primary_provider,
|
|
llm_model=settings.deepseek_model,
|
|
)
|
|
try:
|
|
yield
|
|
finally:
|
|
await app.state.llm_gateway.aclose()
|
|
await close_redis()
|
|
await dispose_engine()
|
|
logger.info("api_stopped")
|
|
|
|
|
|
def create_app(settings: Settings | None = None) -> FastAPI:
|
|
cfg = settings or get_settings()
|
|
configure_logging(
|
|
level=cfg.log_level, json_output=cfg.log_json, extra_redact_keys=cfg.extra_redact_keys
|
|
)
|
|
|
|
app = FastAPI(
|
|
title="美搭 backend",
|
|
version="0.1.0",
|
|
description=(
|
|
"AI 穿搭美学助手服务端。统一响应见架构文档 §9.2;"
|
|
"所有业务接口在 " + cfg.api_prefix + " 之下(/v1 为等价别名)。"
|
|
),
|
|
openapi_url=f"{cfg.api_prefix}/openapi.json",
|
|
docs_url=f"{cfg.api_prefix}/docs" if cfg.is_local else None,
|
|
redoc_url=None,
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
install_version_alias(app, cfg.api_prefix)
|
|
app.add_middleware(RequestContextMiddleware)
|
|
install_exception_handlers(app)
|
|
setup_tracing(app, cfg)
|
|
|
|
app.include_router(health.router)
|
|
routers = (
|
|
auth.router,
|
|
auth_sms.router,
|
|
agent.router,
|
|
quota.router,
|
|
tasks.router,
|
|
events.router,
|
|
uploads.router,
|
|
kb.router,
|
|
reports.router,
|
|
reservations.router,
|
|
)
|
|
for router in routers:
|
|
app.include_router(router, prefix=cfg.api_prefix)
|
|
|
|
return app
|
|
|
|
|
|
app = create_app()
|