""" 配置管理 API 提供系统配置、AI模型、Agent、设备等配置的管理接口 """ import logging from typing import List, Optional from fastapi import APIRouter, HTTPException, status from pydantic import BaseModel, Field import database from services.config_service import ConfigService logger = logging.getLogger(__name__) router = APIRouter() def get_config_service() -> ConfigService: """获取配置服务实例(每次请求时动态创建)""" if database.db is None: raise HTTPException( status_code=500, detail="数据库未初始化,请确保服务已正确启动" ) return ConfigService(database.db) # ==================== 数据模型 ==================== class AIModelResponse(BaseModel): """AI模型响应模型""" id: int model_name: str provider: str api_key: str api_base: str model_type: str = "chat" temperature: float = 0.7 max_tokens: int = 2048 is_default: bool = False is_active: bool = True class AIModelUpdate(BaseModel): """AI模型更新模型""" model_name: Optional[str] = None provider: Optional[str] = None api_key: Optional[str] = None api_base: Optional[str] = None model_type: Optional[str] = None temperature: Optional[float] = None max_tokens: Optional[int] = None is_default: Optional[bool] = None is_active: Optional[bool] = None class AIModelCreate(BaseModel): """AI模型创建模型""" model_name: str provider: str api_key: str api_base: str model_type: str = "chat" temperature: float = 0.7 max_tokens: int = 2048 is_default: bool = False is_active: bool = True class AgentResponse(BaseModel): """Agent响应模型""" id: int agent_code: str agent_name: str host: str = "localhost" port: int description: Optional[str] = None is_enabled: bool = True class AgentUpdate(BaseModel): """Agent更新模型""" agent_name: Optional[str] = None host: Optional[str] = None port: Optional[int] = None description: Optional[str] = None is_enabled: Optional[bool] = None class AgentPromptResponse(BaseModel): """Agent提示词响应模型""" agent_code: str prompt_text: str class AgentPromptUpdate(BaseModel): """Agent提示词更新模型""" prompt_text: str version: str = "v1.0" class DeviceResponse(BaseModel): """设备响应模型""" id: int device_code: str device_name: str device_type: str agent_code: str ip_address: Optional[str] = None token: Optional[str] = None model: Optional[str] = None extra_config: Optional[str] = None is_active: bool = True class DeviceUpdate(BaseModel): """设备更新模型""" device_name: Optional[str] = None ip_address: Optional[str] = None token: Optional[str] = None model: Optional[str] = None extra_config: Optional[str] = None is_active: Optional[bool] = None class DeviceCreate(BaseModel): """设备创建模型""" device_code: str device_name: str device_type: str agent_code: str ip_address: Optional[str] = None token: Optional[str] = None model: Optional[str] = None extra_config: Optional[str] = None is_active: bool = True class XiaomiAccountResponse(BaseModel): """小米账号响应模型""" id: int username: str password: str region: str = "cn" is_default: bool = True is_active: bool = True class XiaomiAccountUpdate(BaseModel): """小米账号更新模型""" username: Optional[str] = None password: Optional[str] = None region: Optional[str] = None is_default: Optional[bool] = None is_active: Optional[bool] = None class XiaomiAccountCreate(BaseModel): """小米账号创建模型""" username: str password: str region: str = "cn" is_default: bool = True is_active: bool = True class SystemConfigResponse(BaseModel): """系统配置响应模型""" id: int config_key: str config_value: str config_type: str category: str description: Optional[str] = None is_active: bool = True class SystemConfigUpdate(BaseModel): """系统配置更新模型""" config_value: str # ==================== AI 模型管理 ==================== @router.get("/ai-models", response_model=List[AIModelResponse]) async def get_ai_models(is_active: Optional[bool] = None): """获取AI模型配置列表""" try: config_service = get_config_service() models = config_service.get_ai_models(is_active) return models except Exception as e: logger.error(f"获取AI模型配置失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.get("/ai-models/default", response_model=AIModelResponse) async def get_default_ai_model(): """获取默认AI模型配置""" try: config_service = get_config_service() model = config_service.get_default_ai_model() if not model: raise HTTPException(status_code=404, detail="未找到默认AI模型") return model except HTTPException: raise except Exception as e: logger.error(f"获取默认AI模型失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.get("/ai-models/{model_id}", response_model=AIModelResponse) async def get_ai_model(model_id: int): """根据ID获取AI模型配置""" try: config_service = get_config_service() model = config_service.get_ai_model_by_id(model_id) if not model: raise HTTPException(status_code=404, detail="未找到该AI模型") return model except HTTPException: raise except Exception as e: logger.error(f"获取AI模型失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.put("/ai-models/{model_id}") async def update_ai_model(model_id: int, data: AIModelUpdate): """更新AI模型配置""" try: config_service = get_config_service() update_data = data.model_dump(exclude_unset=True) success = config_service.update_ai_model(model_id, update_data) if not success: raise HTTPException(status_code=404, detail="更新失败或未找到该模型") return {"message": "更新成功", "model_id": model_id} except HTTPException: raise except Exception as e: logger.error(f"更新AI模型失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.post("/ai-models", status_code=status.HTTP_201_CREATED) async def create_ai_model(data: AIModelCreate): """创建新的AI模型配置""" try: config_service = get_config_service() model_id = config_service.create_ai_model(data.model_dump()) return {"message": "创建成功", "model_id": model_id} except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) except Exception as e: logger.error(f"创建AI模型失败: {e}") raise HTTPException(status_code=500, detail=str(e)) # ==================== Agent 管理 ==================== @router.get("/agents", response_model=List[AgentResponse]) async def get_agents(is_enabled: Optional[bool] = None): """获取Agent配置列表""" try: config_service = get_config_service() agents = config_service.get_agents(is_enabled) return agents except Exception as e: logger.error(f"获取Agent配置失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.get("/agents/{agent_code}", response_model=AgentResponse) async def get_agent(agent_code: str): """根据代码获取Agent配置""" try: config_service = get_config_service() agent = config_service.get_agent_by_code(agent_code) if not agent: raise HTTPException(status_code=404, detail="未找到该Agent") return agent except HTTPException: raise except Exception as e: logger.error(f"获取Agent配置失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.put("/agents/{agent_id}") async def update_agent(agent_id: int, data: AgentUpdate): """更新Agent配置""" try: config_service = get_config_service() update_data = data.model_dump(exclude_unset=True) success = config_service.update_agent(agent_id, update_data) if not success: raise HTTPException(status_code=404, detail="更新失败或未找到该Agent") return {"message": "更新成功", "agent_id": agent_id} except HTTPException: raise except Exception as e: logger.error(f"更新Agent配置失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.get("/agents/{agent_code}/prompt", response_model=AgentPromptResponse) async def get_agent_prompt(agent_code: str): """获取Agent的系统提示词""" try: config_service = get_config_service() prompt = config_service.get_agent_prompt(agent_code) if not prompt: raise HTTPException(status_code=404, detail="未找到该Agent的提示词") return {"agent_code": agent_code, "prompt_text": prompt} except HTTPException: raise except Exception as e: logger.error(f"获取Agent提示词失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.put("/agents/{agent_code}/prompt") async def update_agent_prompt(agent_code: str, data: AgentPromptUpdate): """更新Agent的系统提示词""" try: config_service = get_config_service() success = config_service.update_agent_prompt( agent_code, data.prompt_text, data.version ) if not success: raise HTTPException(status_code=404, detail="更新失败") return {"message": "提示词更新成功", "agent_code": agent_code} except HTTPException: raise except Exception as e: logger.error(f"更新Agent提示词失败: {e}") raise HTTPException(status_code=500, detail=str(e)) # ==================== 设备管理 ==================== @router.get("/devices", response_model=List[DeviceResponse]) async def get_devices( device_type: Optional[str] = None, is_active: Optional[bool] = None ): """获取设备配置列表""" try: config_service = get_config_service() devices = config_service.get_devices(device_type, is_active) return devices except Exception as e: logger.error(f"获取设备配置失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.get("/devices/{device_code}", response_model=DeviceResponse) async def get_device(device_code: str): """根据代码获取设备配置""" try: config_service = get_config_service() device = config_service.get_device_by_code(device_code) if not device: raise HTTPException(status_code=404, detail="未找到该设备") return device except HTTPException: raise except Exception as e: logger.error(f"获取设备配置失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.put("/devices/{device_id}") async def update_device(device_id: int, data: DeviceUpdate): """更新设备配置""" try: config_service = get_config_service() update_data = data.model_dump(exclude_unset=True) success = config_service.update_device(device_id, update_data) if not success: raise HTTPException(status_code=404, detail="更新失败或未找到该设备") return {"message": "更新成功", "device_id": device_id} except HTTPException: raise except Exception as e: logger.error(f"更新设备配置失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.post("/devices", status_code=status.HTTP_201_CREATED) async def create_device(data: DeviceCreate): """创建新设备配置""" try: config_service = get_config_service() device_id = config_service.create_device(data.model_dump()) return {"message": "创建成功", "device_id": device_id} except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) except Exception as e: logger.error(f"创建设备配置失败: {e}") raise HTTPException(status_code=500, detail=str(e)) # ==================== 小米账号管理 ==================== @router.get("/xiaomi-accounts", response_model=List[XiaomiAccountResponse]) async def get_xiaomi_accounts(is_active: Optional[bool] = None): """获取小米账号配置列表""" try: config_service = get_config_service() accounts = config_service.get_xiaomi_accounts(is_active) return accounts except Exception as e: logger.error(f"获取小米账号配置失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.get("/xiaomi-accounts/default", response_model=XiaomiAccountResponse) async def get_default_xiaomi_account(): """获取默认小米账号""" try: config_service = get_config_service() account = config_service.get_default_xiaomi_account() if not account: raise HTTPException(status_code=404, detail="未找到默认小米账号") return account except HTTPException: raise except Exception as e: logger.error(f"获取默认小米账号失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.put("/xiaomi-accounts/{account_id}") async def update_xiaomi_account(account_id: int, data: XiaomiAccountUpdate): """更新小米账号配置""" try: config_service = get_config_service() update_data = data.model_dump(exclude_unset=True) success = config_service.update_xiaomi_account(account_id, update_data) if not success: raise HTTPException(status_code=404, detail="更新失败或未找到该账号") return {"message": "更新成功", "account_id": account_id} except HTTPException: raise except Exception as e: logger.error(f"更新小米账号失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.post("/xiaomi-accounts", status_code=status.HTTP_201_CREATED) async def create_xiaomi_account(data: XiaomiAccountCreate): """创建新小米账号""" try: config_service = get_config_service() account_id = config_service.create_xiaomi_account(data.model_dump()) return {"message": "创建成功", "account_id": account_id} except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) except Exception as e: logger.error(f"创建小米账号失败: {e}") raise HTTPException(status_code=500, detail=str(e)) # ==================== 系统配置管理 ==================== @router.get("/system-config", response_model=List[SystemConfigResponse]) async def get_system_configs(category: Optional[str] = None): """获取系统配置列表""" try: config_service = get_config_service() configs = config_service.get_system_configs(category) return configs except Exception as e: logger.error(f"获取系统配置失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.get("/system-config/{config_key}") async def get_system_config(config_key: str): """根据键获取系统配置值""" try: config_service = get_config_service() value = config_service.get_system_config(config_key) if value is None: raise HTTPException(status_code=404, detail="未找到该配置项") return {"config_key": config_key, "config_value": value} except HTTPException: raise except Exception as e: logger.error(f"获取系统配置失败: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.put("/system-config/{config_key}") async def update_system_config(config_key: str, data: SystemConfigUpdate): """更新系统配置""" try: config_service = get_config_service() success = config_service.update_system_config(config_key, data.config_value) if not success: raise HTTPException(status_code=404, detail="更新失败或未找到该配置项") return {"message": "更新成功", "config_key": config_key} except HTTPException: raise except Exception as e: logger.error(f"更新系统配置失败: {e}") raise HTTPException(status_code=500, detail=str(e))