2026-04-26 19:59:15 +08:00
|
|
|
|
import os
|
2025-10-23 14:08:08 +08:00
|
|
|
|
from contextlib import asynccontextmanager
|
|
|
|
|
|
|
|
|
|
|
|
from fastapi import FastAPI
|
2026-03-25 03:36:08 +08:00
|
|
|
|
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
|
2025-10-23 14:08:08 +08:00
|
|
|
|
|
2026-03-17 10:16:44 +08:00
|
|
|
|
from yuxi.services.task_service import tasker
|
2026-05-29 22:19:58 +08:00
|
|
|
|
from yuxi.agents.mcp.service import ensure_builtin_mcp_servers_in_db
|
|
|
|
|
|
from yuxi.models.providers.service import ensure_builtin_model_providers_in_db
|
2026-03-17 10:16:44 +08:00
|
|
|
|
from yuxi.services.run_queue_service import close_queue_clients, get_redis_client
|
|
|
|
|
|
from yuxi.storage.postgres.manager import pg_manager
|
|
|
|
|
|
from yuxi.knowledge import knowledge_base
|
|
|
|
|
|
from yuxi.utils import logger
|
2026-03-25 03:36:08 +08:00
|
|
|
|
from yuxi.agents.backends.sandbox import init_sandbox_provider, shutdown_sandbox_provider
|
2026-03-21 00:33:20 +08:00
|
|
|
|
from yuxi import get_version
|
2025-10-23 14:08:08 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@asynccontextmanager
|
|
|
|
|
|
async def lifespan(app: FastAPI):
|
|
|
|
|
|
"""FastAPI lifespan事件管理器"""
|
2026-01-21 15:15:52 +08:00
|
|
|
|
# 初始化数据库连接
|
|
|
|
|
|
try:
|
|
|
|
|
|
pg_manager.initialize()
|
2026-05-19 14:52:42 +08:00
|
|
|
|
await pg_manager.create_tables()
|
2026-02-22 17:42:37 +08:00
|
|
|
|
await pg_manager.ensure_business_schema()
|
2026-01-22 05:57:13 +08:00
|
|
|
|
await pg_manager.ensure_knowledge_schema()
|
2026-01-21 15:15:52 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"Failed to initialize database during startup: {e}")
|
|
|
|
|
|
|
2026-04-04 14:47:23 +08:00
|
|
|
|
# 确保内置 MCP 服务器定义存在于数据库
|
2026-01-22 01:15:01 +08:00
|
|
|
|
try:
|
2026-04-04 14:47:23 +08:00
|
|
|
|
await ensure_builtin_mcp_servers_in_db()
|
2026-01-22 01:15:01 +08:00
|
|
|
|
except Exception as e:
|
2026-04-04 14:47:23 +08:00
|
|
|
|
logger.error(f"Failed to ensure builtin MCP servers during startup: {e}")
|
2026-01-22 01:15:01 +08:00
|
|
|
|
|
2026-05-27 14:51:56 +08:00
|
|
|
|
try:
|
2026-05-29 22:19:58 +08:00
|
|
|
|
from yuxi.agents.skills.service import init_builtin_skills
|
2026-05-27 14:51:56 +08:00
|
|
|
|
|
|
|
|
|
|
async with pg_manager.get_async_session_context() as session:
|
|
|
|
|
|
await init_builtin_skills(session)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"Failed to initialize builtin skills during startup: {e}")
|
|
|
|
|
|
|
2026-05-24 00:45:52 +08:00
|
|
|
|
try:
|
|
|
|
|
|
from yuxi.repositories.agent_repository import AgentRepository
|
|
|
|
|
|
|
|
|
|
|
|
async with pg_manager.get_async_session_context() as session:
|
2026-06-02 20:08:27 +08:00
|
|
|
|
repository = AgentRepository(session)
|
|
|
|
|
|
await repository.ensure_default_agent()
|
|
|
|
|
|
await repository.ensure_web_search_subagent()
|
2026-05-24 00:45:52 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"Failed to ensure default agent during startup: {e}")
|
|
|
|
|
|
|
2026-04-25 23:58:01 +08:00
|
|
|
|
# 初始化内置模型供应商配置
|
|
|
|
|
|
try:
|
|
|
|
|
|
async with pg_manager.get_async_session_context() as session:
|
|
|
|
|
|
await ensure_builtin_model_providers_in_db(session)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"Failed to ensure builtin model providers during startup: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
# 初始化模型缓存(v2 模型选择使用)
|
|
|
|
|
|
try:
|
2026-05-29 22:19:58 +08:00
|
|
|
|
from yuxi.models.providers.cache import model_cache
|
|
|
|
|
|
from yuxi.models.providers.service import get_all_model_providers
|
2026-04-25 23:58:01 +08:00
|
|
|
|
|
|
|
|
|
|
async with pg_manager.get_async_session_context() as session:
|
|
|
|
|
|
providers = await get_all_model_providers(session)
|
|
|
|
|
|
model_cache.rebuild(providers)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"Failed to initialize model cache during startup: {e}")
|
|
|
|
|
|
|
2026-01-21 15:15:52 +08:00
|
|
|
|
# 初始化知识库管理器
|
2026-03-19 04:11:30 +08:00
|
|
|
|
if os.environ.get("LITE_MODE", "").lower() in ("true", "1"):
|
|
|
|
|
|
logger.info("LITE_MODE enabled, skipping knowledge base initialization")
|
|
|
|
|
|
else:
|
|
|
|
|
|
try:
|
|
|
|
|
|
await knowledge_base.initialize()
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"Failed to initialize knowledge base manager: {e}")
|
2026-01-21 15:15:52 +08:00
|
|
|
|
|
2026-02-25 16:26:09 +08:00
|
|
|
|
# 预热 Redis(run 队列)
|
|
|
|
|
|
try:
|
|
|
|
|
|
redis = await get_redis_client()
|
|
|
|
|
|
await redis.ping()
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.warning(f"Run queue redis unavailable on startup: {e}")
|
|
|
|
|
|
|
2026-03-25 03:36:08 +08:00
|
|
|
|
try:
|
|
|
|
|
|
init_sandbox_provider()
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error(f"Failed to initialize sandbox provider during startup: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
# =========================================================
|
|
|
|
|
|
# 2. 核心修复:在这里执行一次 setup(),建完表就拉倒
|
|
|
|
|
|
# =========================================================
|
|
|
|
|
|
checkpointer = AsyncPostgresSaver(pg_manager.langgraph_pool)
|
|
|
|
|
|
await checkpointer.setup()
|
|
|
|
|
|
print("LangGraph Checkpoint tables verified/created!")
|
|
|
|
|
|
|
2026-01-14 00:34:24 +08:00
|
|
|
|
await tasker.start()
|
2026-03-21 00:33:20 +08:00
|
|
|
|
logger.info(f"""
|
|
|
|
|
|
|
|
|
|
|
|
░██ ░██ ░██
|
|
|
|
|
|
░██ ░██
|
|
|
|
|
|
░██ ░██ ░██ ░██ ░██ ░██ ░██
|
|
|
|
|
|
░████ ░██ ░██ ░██ ░██ ░██
|
|
|
|
|
|
░██ ░██ ░██ ░█████ ░██
|
|
|
|
|
|
░██ ░██ ░███ ░██ ░██ ░██
|
|
|
|
|
|
░██ ░█████░██ ░██ ░██ ░██ v{get_version()}
|
|
|
|
|
|
|
|
|
|
|
|
""")
|
|
|
|
|
|
logger.info("Yuxi backend startup complete")
|
2025-10-23 14:08:08 +08:00
|
|
|
|
yield
|
|
|
|
|
|
await tasker.shutdown()
|
2026-03-25 03:36:08 +08:00
|
|
|
|
shutdown_sandbox_provider()
|
2026-02-25 16:26:09 +08:00
|
|
|
|
await close_queue_clients()
|
2026-01-21 15:15:52 +08:00
|
|
|
|
await pg_manager.close()
|