""" 低代码智能体平台 - FastAPI 主应用 """ import asyncio import logging from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.exceptions import RequestValidationError from sqlalchemy.exc import SQLAlchemyError from app.core.config import settings from app.core.error_handler import ( validation_exception_handler, api_exception_handler, sqlalchemy_exception_handler, general_exception_handler ) from app.core.exceptions import BaseAPIException from app.core.database import init_db # 配置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) app = FastAPI( title=settings.APP_NAME, version=settings.APP_VERSION, description=""" ## 低代码智能体平台 API 一个支持可视化工作流设计和智能Agent配置的低代码平台。 ### 主要功能 * **用户认证** - 用户注册、登录、JWT认证 * **工作流管理** - 工作流的创建、读取、更新、删除、执行 * **工作流版本管理** - 版本保存、版本列表、版本回滚 * **执行管理** - 工作流执行、执行记录查询、执行状态监控 * **执行日志** - 详细的执行日志记录和查询 * **数据源管理** - 多种数据源的连接和管理 * **WebSocket实时推送** - 执行状态实时更新 ### 认证方式 大部分API需要JWT认证。请先通过 `/api/v1/auth/login` 获取token,然后在请求头中添加: ``` Authorization: Bearer ``` ### API版本 当前API版本:v1 ### 文档 * **Swagger UI**: `/docs` - 交互式API文档 * **ReDoc**: `/redoc` - 可读性更好的API文档 """, docs_url="/docs", redoc_url="/redoc", openapi_tags=[ { "name": "auth", "description": "用户认证相关API,包括注册、登录、获取用户信息等。" }, { "name": "workflows", "description": "工作流管理API,包括工作流的CRUD操作、执行、版本管理等。" }, { "name": "executions", "description": "执行管理API,包括执行记录的创建、查询、状态获取等。" }, { "name": "execution-logs", "description": "执行日志API,包括日志查询、日志统计等。" }, { "name": "data-sources", "description": "数据源管理API,包括数据源的CRUD操作、连接测试、数据查询等。" }, { "name": "websocket", "description": "WebSocket API,用于实时推送执行状态。" } ] ) # CORS 配置 cors_origins = [origin.strip() for origin in settings.CORS_ORIGINS.split(",")] # 添加调试日志 logger.info(f"CORS允许的源: {cors_origins}") app.add_middleware( CORSMiddleware, allow_origins=cors_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], expose_headers=["*"], ) # 注册全局异常处理器 app.add_exception_handler(RequestValidationError, validation_exception_handler) app.add_exception_handler(BaseAPIException, api_exception_handler) app.add_exception_handler(SQLAlchemyError, sqlalchemy_exception_handler) app.add_exception_handler(Exception, general_exception_handler) # 请求日志中间件 @app.middleware("http") async def log_requests(request: Request, call_next): """记录请求日志""" import time start_time = time.time() # 记录请求 logger.info(f"{request.method} {request.url.path} - 客户端: {request.client.host if request.client else 'unknown'}") try: response = await call_next(request) process_time = time.time() - start_time # 记录响应 logger.info( f"{request.method} {request.url.path} - " f"状态码: {response.status_code} - " f"耗时: {process_time:.3f}s" ) return response except Exception as e: process_time = time.time() - start_time logger.error( f"{request.method} {request.url.path} - " f"异常: {str(e)} - " f"耗时: {process_time:.3f}s" ) raise @app.get("/") async def root(): """根路径""" return { "message": "欢迎使用低代码智能体平台 API", "version": settings.APP_VERSION, "docs": "/docs" } @app.get("/health") async def health_check(): """健康检查(含内置工具是否已注册,便于排查「可动手 Agent」)。""" from app.services.tool_registry import tool_registry names = tool_registry.builtin_tool_names() count = tool_registry.builtin_tool_count() file_agent_core = {"file_write", "file_read", "system_info"} subset_ok = file_agent_core.issubset(set(names)) expected_ok = count >= 10 tools_ready = expected_ok and subset_ok return { "status": "healthy", "checks": { "builtin_tools_ready": tools_ready, "builtin_tools_count_ok": expected_ok, "file_agent_core_ready": subset_ok, }, "builtin_tools": { "count": count, "names": names, "expected_min_count": 10, }, "notes": { "celery": "工作流/Agent 执行通常在 Celery Worker 中跑;Worker 日志中也应出现「内置工具就绪」且 count 应与 API 一致。若仅 API 有工具而 Worker 无,会出现 LLM 无法真正调用 file_write。", }, } # 应用启动时初始化数据库和工具 @app.on_event("startup") async def startup_event(): """应用启动事件""" try: logger.info("正在初始化数据库...") init_db() logger.info("数据库初始化完成") except Exception as e: logger.error(f"数据库初始化失败: {e}") # 不抛出异常,允许应用继续启动 # 注册内置工具(与 Celery Worker 共用 app.core.tools_bootstrap) try: from app.core.tools_bootstrap import ensure_builtin_tools_registered ensure_builtin_tools_registered() from app.services.tool_registry import tool_registry logger.info("内置工具注册完成(count=%s)", tool_registry.builtin_tool_count()) except Exception as e: logger.error(f"内置工具注册失败: {e}") # 不抛出异常,允许应用继续启动 # 加载自定义工具(从数据库同步到注册表) try: from app.core.database import SessionLocal db = SessionLocal() try: tool_registry.load_tools_from_db(db) logger.info("自定义工具加载完成(count=%s)", len(tool_registry._tool_schemas) - tool_registry.builtin_tool_count()) finally: db.close() except Exception as e: logger.error(f"自定义工具加载失败: {e}") # 启动飞书长连接(在主事件循环中运行) try: from app.services.feishu_ws_handler import start_ws_client asyncio.ensure_future(start_ws_client()) except Exception as e: logger.error(f"飞书长连接启动失败: {e}") # 启动橙子飞书长连接 try: from app.services.orange_ws_handler import start_ws_client as start_orange_ws asyncio.ensure_future(start_orange_ws()) except Exception as e: logger.error(f"橙子长连接启动失败: {e}") # 启动苏瑶飞书长连接 try: from app.services.suyao_ws_handler import start_ws_client as start_suyao_ws asyncio.ensure_future(start_suyao_ws()) except Exception as e: logger.error(f"苏瑶长连接启动失败: {e}") # 启动甜甜飞书长连接(苏瑶3号) try: from app.services.tiantian_ws_handler import start_ws_client as start_tiantian_ws asyncio.ensure_future(start_tiantian_ws()) except Exception as e: logger.error(f"甜甜长连接启动失败: {e}") # 启动灵犀飞书长连接(学习助手) try: from app.services.lingxi_ws_handler import start_ws_client as start_lingxi_ws asyncio.ensure_future(start_lingxi_ws()) except Exception as e: logger.error(f"灵犀长连接启动失败: {e}") # 注册路由 from app.api import auth, uploads, workflows, executions, websocket, execution_logs, data_sources, agents, platform_templates, model_configs, webhooks, template_market, batch_operations, collaboration, permissions, monitoring, alert_rules, node_test, node_templates, tools, agent_chat, agent_monitoring, knowledge_base, agent_schedules, notifications, feishu_bind app.include_router(auth.router) app.include_router(uploads.router) app.include_router(workflows.router) app.include_router(executions.router) app.include_router(websocket.router) app.include_router(execution_logs.router) app.include_router(data_sources.router) app.include_router(agents.router) app.include_router(platform_templates.router) app.include_router(model_configs.router) app.include_router(webhooks.router) app.include_router(template_market.router) app.include_router(batch_operations.router) app.include_router(collaboration.router) app.include_router(permissions.router) app.include_router(monitoring.router) app.include_router(alert_rules.router) app.include_router(node_test.router) app.include_router(node_templates.router) app.include_router(tools.router) app.include_router(agent_chat.router) app.include_router(agent_monitoring.router) app.include_router(knowledge_base.router) app.include_router(agent_schedules.router) app.include_router(notifications.router) app.include_router(feishu_bind.router) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)