| """ |
| 系统状态 API 端点 |
| 提供 GET /api/system/status。 |
| """ |
|
|
| import os |
| import logging |
| from pathlib import Path |
|
|
| from fastapi import APIRouter |
|
|
| from app.config.settings import settings |
|
|
| logger = logging.getLogger(__name__) |
|
|
| router = APIRouter() |
|
|
|
|
| def _detect_huggingface_environment() -> dict: |
| """检测 HuggingFace 环境 |
| |
| 只输出非敏感摘要,不记录密钥或敏感环境变量。 |
| |
| Returns: |
| 包含 is_huggingface 和环境摘要的字典 |
| """ |
| |
| hf_indicators = [ |
| "SPACE_ID", |
| "SPACE_REPO_ID", |
| "SPACE_SDK", |
| "HF_HOME", |
| "HUGGINGFACE_HUB_TOKEN", |
| ] |
|
|
| detected_vars = [] |
| for var in hf_indicators: |
| if os.environ.get(var): |
| detected_vars.append(var) |
|
|
| is_huggingface = len(detected_vars) > 0 |
|
|
| return { |
| "is_huggingface": is_huggingface, |
| "detected_indicators": detected_vars, |
| "note": "HuggingFace 环境检测基于环境变量,不记录敏感值", |
| } |
|
|
|
|
| def _get_dependency_policy() -> dict: |
| """获取依赖策略 |
| |
| Returns: |
| 依赖策略描述 |
| """ |
| return { |
| "check_only": True, |
| "install_disabled": True, |
| "description": "只检查依赖是否满足,不执行安装操作", |
| "supported_operators": ["==", ">=", "<=", ">", "<"], |
| "limitations": "复杂依赖解析有限,覆盖常见 ==/>=/<= 和包缺失", |
| } |
|
|
|
|
| def _get_unsupported_actions() -> list: |
| """获取不支持的操作列表 |
| |
| Returns: |
| 不支持的操作描述列表 |
| """ |
| return [ |
| { |
| "action": "install", |
| "description": "页面不支持运行时安装插件", |
| "reason": "插件随部署注入", |
| }, |
| { |
| "action": "uninstall", |
| "description": "页面不支持卸载插件", |
| "reason": "插件随部署注入", |
| }, |
| { |
| "action": "restart", |
| "description": "页面不支持重启服务", |
| "reason": "HuggingFace Spaces 自动管理", |
| }, |
| { |
| "action": "validate_git", |
| "description": "页面不支持 Git 仓库校验", |
| "reason": "插件随部署注入", |
| }, |
| ] |
|
|
|
|
| def _get_deployment_instructions() -> dict: |
| """获取部署说明 |
| |
| Returns: |
| 部署说明 |
| """ |
| return { |
| "platform": "HuggingFace Spaces", |
| "plugin_injection": "插件通过部署时注入,不支持运行时安装", |
| "directory": str(settings.PLUGINS_DIR), |
| "state_file": str(settings.DATA_DIR / "plugin_state.json"), |
| "notes": [ |
| "插件目录在部署时创建", |
| "状态文件保存用户启停状态", |
| "HuggingFace 未启用持久存储时,状态文件可能随重建丢失", |
| ], |
| } |
|
|
|
|
| def _get_storage_summary() -> dict: |
| """获取存储摘要 |
| |
| Returns: |
| 存储风险和状态 |
| """ |
| data_dir = settings.DATA_DIR |
| state_file = data_dir / "plugin_state.json" |
|
|
| return { |
| "data_directory": str(data_dir), |
| "state_file_exists": state_file.exists(), |
| "persistent_storage_warning": "HuggingFace 未启用持久存储时,data/ 目录可能随 Space 重建丢失", |
| } |
|
|
|
|
| @router.get("/status") |
| async def get_system_status(): |
| """获取系统状态 |
| |
| Returns: |
| 包含环境、插件目录、依赖策略、部署说明、不支持动作、存储风险和 MCP 摘要的字典 |
| """ |
| |
| environment = _detect_huggingface_environment() |
|
|
| |
| try: |
| from app.plugins.manager import get_plugin_manager |
| manager = get_plugin_manager() |
| plugin_summary = manager.get_system_plugin_summary() |
| except Exception as e: |
| logger.warning(f"获取插件摘要失败: {e}") |
| plugin_summary = { |
| "total": 0, |
| "enabled": 0, |
| "disabled": 0, |
| "error": 0, |
| "plugin_directory": str(settings.PLUGINS_DIR), |
| } |
|
|
| |
| try: |
| from app.mcp.plugin_registry import get_plugin_registry |
| registry = get_plugin_registry() |
| mcp_status = registry.get_mcp_status() |
| mcp_summary = { |
| "total_tools": mcp_status["total_tools"], |
| "available_tools": mcp_status["available_tools"], |
| "unavailable_tools": mcp_status["unavailable_tools"], |
| } |
| except Exception as e: |
| logger.warning(f"获取 MCP 摘要失败: {e}") |
| mcp_summary = { |
| "total_tools": 0, |
| "available_tools": 0, |
| "unavailable_tools": 0, |
| } |
|
|
| return { |
| "environment": environment, |
| "plugin_directory": str(settings.PLUGINS_DIR), |
| "plugin_summary": plugin_summary, |
| "dependency_policy": _get_dependency_policy(), |
| "deployment_instructions": _get_deployment_instructions(), |
| "unsupported_actions": _get_unsupported_actions(), |
| "storage_summary": _get_storage_summary(), |
| "mcp_summary": mcp_summary, |
| } |
|
|