import json import os from pathlib import Path from typing import Any, Dict, Optional from fastapi import HTTPException from utils.settings import NEW_API_BASE_URL GENERAL_AGENT_CONFIG_PATH = Path(os.getenv("GENERAL_AGENT_CONFIG_PATH", "config/general_agent.json")) def load_general_agent_config() -> Dict[str, Any]: if not GENERAL_AGENT_CONFIG_PATH.exists(): raise HTTPException(status_code=500, detail="General agent config not found") try: with GENERAL_AGENT_CONFIG_PATH.open("r", encoding="utf-8") as file: config = json.load(file) except json.JSONDecodeError as error: raise HTTPException(status_code=500, detail=f"Invalid general agent config: {error}") if not isinstance(config, dict): raise HTTPException(status_code=500, detail="General agent config must be an object") if not config.get("enabled", False): raise HTTPException(status_code=404, detail="General agent is disabled") required_fields = ["bot_id", "name", "model_id", "system_prompt"] missing_fields = [field for field in required_fields if not config.get(field)] if missing_fields: raise HTTPException(status_code=500, detail=f"General agent config missing fields: {', '.join(missing_fields)}") return config def get_general_agent_id() -> str: return str(load_general_agent_config()["bot_id"]) def is_general_agent_id(bot_id: Optional[str]) -> bool: if not bot_id: return False try: config = load_general_agent_config() except HTTPException: return False return str(bot_id) == str(config.get("bot_id")) def _as_list(value: Any, *, split_newlines: bool = False) -> list: if value is None: return [] if isinstance(value, list): return value if isinstance(value, str): separator = "\n" if split_newlines else "," return [item.strip() for item in value.split(separator) if item.strip()] return [] def get_general_agent_settings() -> Dict[str, Any]: config = load_general_agent_config() settings = dict(config) settings["suggestions"] = _as_list(settings.get("suggestions"), split_newlines=True) settings["dataset_ids"] = _as_list(settings.get("dataset_ids")) settings["skills"] = _as_list(settings.get("skills")) settings["shell_env"] = settings.get("shell_env") or {} settings["mcp_settings"] = settings.get("mcp_settings") or [] return settings def get_general_agent_runtime_config(user_identifier: Optional[str] = None) -> Dict[str, Any]: settings = get_general_agent_settings() model_id = settings.get("model_id", "") bot_id = settings.get("bot_id", "general-agent") # 按用户隔离工作目录:projects/robot/general-agent-{user} raw_user = user_identifier or "anonymous" safe_user = "".join(c if c.isalnum() or c in "-_" else "_" for c in raw_user) or "anonymous" project_dir_key = f"{bot_id}-{safe_user}" return { "name": settings.get("name", "通用智能体"), "model": model_id, "api_key": settings.get("api_key", ""), "model_server": settings.get("model_server") or (NEW_API_BASE_URL.rstrip("/") + "/v1" if NEW_API_BASE_URL else ""), "language": settings.get("language", "zh"), "dataset_ids": settings.get("dataset_ids", []), "system_prompt": settings.get("system_prompt", ""), "user_identifier": user_identifier, "enable_memori": settings.get("enable_memori", False), "tool_response": settings.get("tool_response", False), "enable_thinking": settings.get("enable_thinking", False), "skills": settings.get("skills", []), "description": settings.get("description", ""), "suggestions": settings.get("suggestions", []), "shell_env": settings.get("shell_env") or {}, "voice_speaker": settings.get("voice_speaker", ""), "voice_system_role": settings.get("voice_system_role", ""), "voice_speaking_style": settings.get("voice_speaking_style", ""), "mcp_settings": settings.get("mcp_settings", []), "project_dir_key": project_dir_key, }