mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-17 01:49:15 +08:00
* refactor: migrate to fastapi * structure refactor * fix: pyright fix * refactor: improve error handling and public messages in plugin services * feat(api): refactor API client integration and enhance request handling - Updated API client configuration to use a dedicated HTTP client. - Introduced utility functions for generating options, queries, and form data for API requests. - Refactored multiple API methods to utilize the new utility functions for improved consistency and readability. - Renamed types for clarity and updated import statements accordingly. feat(docs): add script to update OpenAPI JSON from YAML spec - Created a Python script to convert OpenAPI YAML specification to JSON format. - The script supports customizable input and output paths. - Ensured the script handles directory creation for output paths and validates the YAML structure. * fix * feat(auth): implement rate limiting for v1 login endpoint and enhance request handling * Refactor dashboard API routers to use legacy_router for backward compatibility - Changed all instances of dashboard_router to legacy_router across multiple API modules including platform, plugins, providers, sessions, skills, stats, subagents, t2i, tools, updates, and asgi_runtime. - Updated route definitions to ensure existing endpoints remain functional under the new router structure. - Introduced support for Quart request context in asgi_runtime to enhance compatibility with existing Quart-based plugins. - Added a test case to validate the functionality of the new Quart request context handling in plugin extensions. * chore: remove cli test * fix: update dashboard tests for fastapi migration * chore: satisfy ruff checks * fix: update openapi api key scopes * fix: sync config scope chip selection * fix: restore quart dependency * docs: clarify quart plugin api compatibility * docs: update openapi scope documentation * fix: use singular skill openapi scope * fix: hide update service exception details * fix: address fastapi review comments * fix: address dashboard review findings * docs: revert unrelated package deployment changes * docs: update agent api generation guidance * feat: add plugin page web api helpers * docs: add plugin page bridge demo * fix: type plugin upload files * fix: stabilize plugin page uploads * fix: type plugin web request proxy * docs: remove plugin page docs example * fix: authenticate plugin page SSE bridge
98 lines
3.3 KiB
Python
98 lines
3.3 KiB
Python
from __future__ import annotations
|
|
|
|
import traceback
|
|
|
|
from astrbot.core import logger
|
|
from astrbot.core.agent.handoff import HandoffTool
|
|
from astrbot.core.core_lifecycle import AstrBotCoreLifecycle
|
|
|
|
|
|
class SubAgentServiceError(Exception):
|
|
pass
|
|
|
|
|
|
class SubAgentService:
|
|
def __init__(self, core_lifecycle: AstrBotCoreLifecycle) -> None:
|
|
self.core_lifecycle = core_lifecycle
|
|
|
|
def get_config(self) -> dict:
|
|
try:
|
|
config_data = self.core_lifecycle.astrbot_config.get(
|
|
"subagent_orchestrator"
|
|
)
|
|
return self._normalize_config(config_data)
|
|
except Exception as exc:
|
|
logger.error(traceback.format_exc())
|
|
raise SubAgentServiceError(f"获取 subagent 配置失败: {exc!s}") from exc
|
|
|
|
async def update_config(self, data: object) -> None:
|
|
try:
|
|
if not isinstance(data, dict):
|
|
raise SubAgentServiceError("配置必须为 JSON 对象")
|
|
|
|
config = self.core_lifecycle.astrbot_config
|
|
config["subagent_orchestrator"] = data
|
|
config.save_config()
|
|
|
|
orchestrator = getattr(self.core_lifecycle, "subagent_orchestrator", None)
|
|
if orchestrator is not None:
|
|
await orchestrator.reload_from_config(data)
|
|
except SubAgentServiceError:
|
|
raise
|
|
except Exception as exc:
|
|
logger.error(traceback.format_exc())
|
|
raise SubAgentServiceError(f"保存 subagent 配置失败: {exc!s}") from exc
|
|
|
|
def get_available_tools(self) -> list[dict]:
|
|
try:
|
|
tool_mgr = self.core_lifecycle.provider_manager.llm_tools
|
|
tools = []
|
|
for tool in tool_mgr.func_list:
|
|
if self._is_subagent_internal_tool(tool):
|
|
continue
|
|
tools.append(
|
|
{
|
|
"name": tool.name,
|
|
"description": tool.description,
|
|
"parameters": tool.parameters,
|
|
"active": tool.active,
|
|
"handler_module_path": tool.handler_module_path,
|
|
}
|
|
)
|
|
return tools
|
|
except Exception as exc:
|
|
logger.error(traceback.format_exc())
|
|
raise SubAgentServiceError(f"获取可用工具失败: {exc!s}") from exc
|
|
|
|
@staticmethod
|
|
def _normalize_config(data: object) -> dict:
|
|
if not isinstance(data, dict):
|
|
data = {
|
|
"main_enable": False,
|
|
"remove_main_duplicate_tools": False,
|
|
"agents": [],
|
|
}
|
|
|
|
if "main_enable" not in data and "enable" in data:
|
|
data["main_enable"] = bool(data.get("enable", False))
|
|
|
|
data.setdefault("main_enable", False)
|
|
data.setdefault("remove_main_duplicate_tools", False)
|
|
data.setdefault("agents", [])
|
|
|
|
agents = data.get("agents")
|
|
if isinstance(agents, list):
|
|
for agent in agents:
|
|
if isinstance(agent, dict):
|
|
agent.setdefault("provider_id", None)
|
|
agent.setdefault("persona_id", None)
|
|
|
|
return data
|
|
|
|
@staticmethod
|
|
def _is_subagent_internal_tool(tool) -> bool:
|
|
return (
|
|
isinstance(tool, HandoffTool)
|
|
or tool.handler_module_path == "core.subagent_orchestrator"
|
|
)
|