Merge branch 'dev' of https://github.com/MoFox-Studio/MoFox-Core into dev
This commit is contained in:
@@ -14,12 +14,13 @@ from __future__ import annotations
|
||||
import asyncio
|
||||
import importlib
|
||||
import multiprocessing as mp
|
||||
from typing import TYPE_CHECKING, Dict, Optional
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.plugin_system.base.base_adapter import BaseAdapter
|
||||
|
||||
from mofox_wire import ProcessCoreSinkServer
|
||||
|
||||
from src.common.logger import get_logger
|
||||
|
||||
logger = get_logger("adapter_manager")
|
||||
@@ -64,11 +65,11 @@ def _adapter_process_entry(
|
||||
):
|
||||
"""
|
||||
子进程适配器入口函数
|
||||
|
||||
|
||||
在子进程中运行,创建 ProcessCoreSink 与主进程通信
|
||||
"""
|
||||
import asyncio
|
||||
import contextlib
|
||||
|
||||
from mofox_wire import ProcessCoreSink
|
||||
|
||||
async def _run() -> None:
|
||||
@@ -77,14 +78,14 @@ def _adapter_process_entry(
|
||||
if plugin_info:
|
||||
plugin_cls = _load_class(plugin_info["module"], plugin_info["class"])
|
||||
plugin_instance = plugin_cls(plugin_info["plugin_dir"], plugin_info["metadata"])
|
||||
|
||||
|
||||
# 创建 ProcessCoreSink 用于与主进程通信
|
||||
core_sink = ProcessCoreSink(to_core_queue=incoming_queue, from_core_queue=outgoing_queue)
|
||||
|
||||
|
||||
# 创建并启动适配器
|
||||
adapter = adapter_cls(core_sink, plugin=plugin_instance)
|
||||
await adapter.start()
|
||||
|
||||
|
||||
try:
|
||||
while not getattr(core_sink, "_closed", False):
|
||||
await asyncio.sleep(0.2)
|
||||
@@ -101,7 +102,7 @@ def _adapter_process_entry(
|
||||
class AdapterProcess:
|
||||
"""
|
||||
适配器子进程封装:管理子进程的生命周期与通信桥接
|
||||
|
||||
|
||||
使用 CoreSinkManager 创建通信队列,自动维护与子进程的消息通道
|
||||
"""
|
||||
|
||||
@@ -132,13 +133,13 @@ class AdapterProcess:
|
||||
"""启动适配器子进程"""
|
||||
try:
|
||||
logger.info(f"启动适配器子进程: {self.adapter_name}")
|
||||
|
||||
|
||||
# 从 CoreSinkManager 获取通信队列
|
||||
from src.common.core_sink_manager import get_core_sink_manager
|
||||
|
||||
|
||||
manager = get_core_sink_manager()
|
||||
self._incoming_queue, self._outgoing_queue = manager.create_process_sink_queues(self.adapter_name)
|
||||
|
||||
|
||||
# 启动子进程
|
||||
self.process = self._ctx.Process(
|
||||
target=_adapter_process_entry,
|
||||
@@ -146,10 +147,10 @@ class AdapterProcess:
|
||||
name=f"{self.adapter_name}-proc",
|
||||
)
|
||||
self.process.start()
|
||||
|
||||
|
||||
logger.info(f"启动适配器子进程 {self.adapter_name} (PID: {self.process.pid})")
|
||||
return True
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"启动适配器子进程 {self.adapter_name} 失败: {e}")
|
||||
return False
|
||||
@@ -158,25 +159,25 @@ class AdapterProcess:
|
||||
"""停止适配器子进程"""
|
||||
if not self.process:
|
||||
return
|
||||
|
||||
|
||||
logger.info(f"停止适配器子进程: {self.adapter_name} (PID: {self.process.pid})")
|
||||
|
||||
|
||||
try:
|
||||
# 从 CoreSinkManager 移除通信队列
|
||||
from src.common.core_sink_manager import get_core_sink_manager
|
||||
|
||||
|
||||
manager = get_core_sink_manager()
|
||||
manager.remove_process_sink(self.adapter_name)
|
||||
|
||||
|
||||
# 等待子进程结束
|
||||
if self.process.is_alive():
|
||||
self.process.join(timeout=5.0)
|
||||
|
||||
|
||||
if self.process.is_alive():
|
||||
logger.warning(f"适配器 {self.adapter_name} 未能及时停止,强制终止中")
|
||||
self.process.terminate()
|
||||
self.process.join()
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"停止适配器子进程 {self.adapter_name} 时发生错误: {e}")
|
||||
finally:
|
||||
@@ -193,7 +194,7 @@ class AdapterProcess:
|
||||
class AdapterManager:
|
||||
"""
|
||||
适配器管理器
|
||||
|
||||
|
||||
负责管理所有注册的适配器,根据 run_in_subprocess 属性自动选择:
|
||||
- run_in_subprocess=True: 在子进程中运行,使用 ProcessCoreSink
|
||||
- run_in_subprocess=False: 在主进程中运行,使用 InProcessCoreSink
|
||||
@@ -201,9 +202,9 @@ class AdapterManager:
|
||||
|
||||
def __init__(self):
|
||||
# 注册信息:name -> (adapter class, plugin instance | None)
|
||||
self._adapter_defs: Dict[str, tuple[type[BaseAdapter], object | None]] = {}
|
||||
self._adapter_processes: Dict[str, AdapterProcess] = {}
|
||||
self._in_process_adapters: Dict[str, BaseAdapter] = {}
|
||||
self._adapter_defs: dict[str, tuple[type[BaseAdapter], object | None]] = {}
|
||||
self._adapter_processes: dict[str, AdapterProcess] = {}
|
||||
self._in_process_adapters: dict[str, BaseAdapter] = {}
|
||||
|
||||
def register_adapter(self, adapter_cls: type[BaseAdapter], plugin=None) -> None:
|
||||
"""
|
||||
@@ -213,15 +214,15 @@ class AdapterManager:
|
||||
adapter_cls: 适配器类
|
||||
plugin: 可选 Plugin 实例
|
||||
"""
|
||||
adapter_name = getattr(adapter_cls, 'adapter_name', adapter_cls.__name__)
|
||||
adapter_name = getattr(adapter_cls, "adapter_name", adapter_cls.__name__)
|
||||
|
||||
if adapter_name in self._adapter_defs:
|
||||
logger.warning(f"适配器 {adapter_name} 已注册,已覆盖")
|
||||
|
||||
self._adapter_defs[adapter_name] = (adapter_cls, plugin)
|
||||
adapter_version = getattr(adapter_cls, 'adapter_version', 'unknown')
|
||||
run_in_subprocess = getattr(adapter_cls, 'run_in_subprocess', False)
|
||||
|
||||
adapter_version = getattr(adapter_cls, "adapter_version", "unknown")
|
||||
run_in_subprocess = getattr(adapter_cls, "run_in_subprocess", False)
|
||||
|
||||
logger.info(
|
||||
f"注册适配器: {adapter_name} v{adapter_version} "
|
||||
f"(子进程: {'是' if run_in_subprocess else '否'})"
|
||||
@@ -230,7 +231,7 @@ class AdapterManager:
|
||||
async def start_adapter(self, adapter_name: str) -> bool:
|
||||
"""
|
||||
启动指定适配器
|
||||
|
||||
|
||||
根据适配器的 run_in_subprocess 属性自动选择:
|
||||
- True: 创建子进程,使用 ProcessCoreSink
|
||||
- False: 在当前进程,使用 InProcessCoreSink
|
||||
@@ -239,7 +240,7 @@ class AdapterManager:
|
||||
if not definition:
|
||||
logger.error(f"适配器 {adapter_name} 未注册")
|
||||
return False
|
||||
|
||||
|
||||
adapter_cls, plugin = definition
|
||||
run_in_subprocess = getattr(adapter_cls, "run_in_subprocess", False)
|
||||
|
||||
@@ -248,9 +249,9 @@ class AdapterManager:
|
||||
return await self._start_adapter_in_process(adapter_name, adapter_cls, plugin)
|
||||
|
||||
async def _start_adapter_subprocess(
|
||||
self,
|
||||
adapter_name: str,
|
||||
adapter_cls: type[BaseAdapter],
|
||||
self,
|
||||
adapter_name: str,
|
||||
adapter_cls: type[BaseAdapter],
|
||||
plugin
|
||||
) -> bool:
|
||||
"""在子进程中启动适配器(使用 ProcessCoreSink)"""
|
||||
@@ -263,24 +264,24 @@ class AdapterManager:
|
||||
return success
|
||||
|
||||
async def _start_adapter_in_process(
|
||||
self,
|
||||
adapter_name: str,
|
||||
adapter_cls: type[BaseAdapter],
|
||||
self,
|
||||
adapter_name: str,
|
||||
adapter_cls: type[BaseAdapter],
|
||||
plugin
|
||||
) -> bool:
|
||||
"""在当前进程中启动适配器(使用 InProcessCoreSink)"""
|
||||
try:
|
||||
# 从 CoreSinkManager 获取 InProcessCoreSink
|
||||
from src.common.core_sink_manager import get_core_sink_manager
|
||||
|
||||
|
||||
core_sink = get_core_sink_manager().get_in_process_sink()
|
||||
adapter = adapter_cls(core_sink, plugin=plugin) # type: ignore[call-arg]
|
||||
await adapter.start()
|
||||
|
||||
|
||||
self._in_process_adapters[adapter_name] = adapter
|
||||
logger.info(f"适配器 {adapter_name} 已在当前进程启动")
|
||||
return True
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"启动适配器 {adapter_name} 失败: {e}")
|
||||
return False
|
||||
@@ -288,7 +289,7 @@ class AdapterManager:
|
||||
async def stop_adapter(self, adapter_name: str) -> None:
|
||||
"""
|
||||
停止指定的适配器
|
||||
|
||||
|
||||
Args:
|
||||
adapter_name: 适配器名称
|
||||
"""
|
||||
@@ -327,20 +328,20 @@ class AdapterManager:
|
||||
|
||||
logger.info("所有适配器已停止")
|
||||
|
||||
def get_adapter(self, adapter_name: str) -> Optional[BaseAdapter]:
|
||||
def get_adapter(self, adapter_name: str) -> BaseAdapter | None:
|
||||
"""
|
||||
获取适配器实例
|
||||
|
||||
|
||||
Args:
|
||||
adapter_name: 适配器名称
|
||||
|
||||
|
||||
Returns:
|
||||
BaseAdapter | None: 适配器实例,如果不存在则返回 None
|
||||
"""
|
||||
# 只返回在主进程中运行的适配器
|
||||
return self._in_process_adapters.get(adapter_name)
|
||||
|
||||
def list_adapters(self) -> Dict[str, Dict[str, any]]:
|
||||
def list_adapters(self) -> dict[str, dict[str, any]]:
|
||||
"""列出适配器状态"""
|
||||
result = {}
|
||||
|
||||
@@ -371,7 +372,7 @@ class AdapterManager:
|
||||
|
||||
|
||||
# 全局单例
|
||||
_adapter_manager: Optional[AdapterManager] = None
|
||||
_adapter_manager: AdapterManager | None = None
|
||||
|
||||
|
||||
def get_adapter_manager() -> AdapterManager:
|
||||
|
||||
@@ -242,7 +242,7 @@ class EventManager:
|
||||
for event in self._events.values():
|
||||
# 创建订阅者列表的副本进行迭代,以安全地修改原始列表
|
||||
for subscriber in list(event.subscribers):
|
||||
if getattr(subscriber, 'handler_name', None) == handler_name:
|
||||
if getattr(subscriber, "handler_name", None) == handler_name:
|
||||
event.subscribers.remove(subscriber)
|
||||
logger.debug(f"事件处理器 {handler_name} 已从事件 {event.name} 取消订阅。")
|
||||
|
||||
|
||||
@@ -38,14 +38,14 @@ class PermissionManager(IPermissionManager):
|
||||
try:
|
||||
master_users_config = global_config.permission.master_users
|
||||
if not isinstance(master_users_config, list):
|
||||
logger.warning(f"配置文件中的 permission.master_users 不是一个列表,已跳过加载。")
|
||||
logger.warning("配置文件中的 permission.master_users 不是一个列表,已跳过加载。")
|
||||
self._master_users = set()
|
||||
return
|
||||
|
||||
self._master_users = set()
|
||||
for i, user_info in enumerate(master_users_config):
|
||||
if not isinstance(user_info, list) or len(user_info) != 2:
|
||||
logger.warning(f"Master用户配置项格式错误 (索引: {i}): {user_info},应为 [\"platform\", \"user_id\"]")
|
||||
logger.warning(f'Master用户配置项格式错误 (索引: {i}): {user_info},应为 ["platform", "user_id"]')
|
||||
continue
|
||||
|
||||
platform, user_id = user_info
|
||||
|
||||
@@ -33,9 +33,9 @@ class PluginManager:
|
||||
|
||||
self.loaded_plugins: dict[str, PluginBase] = {} # 已加载的插件类实例注册表,插件名 -> 插件类实例
|
||||
self.failed_plugins: dict[str, str] = {} # 记录加载失败的插件文件及其错误信息,插件名 -> 错误信息
|
||||
|
||||
|
||||
# 核心消息接收器(由主程序设置)
|
||||
self._core_sink: Optional[Any] = None
|
||||
self._core_sink: Any | None = None
|
||||
|
||||
# 确保插件目录存在
|
||||
self._ensure_plugin_directories()
|
||||
@@ -45,7 +45,7 @@ class PluginManager:
|
||||
|
||||
def set_core_sink(self, core_sink: Any) -> None:
|
||||
"""设置核心消息接收器
|
||||
|
||||
|
||||
Args:
|
||||
core_sink: 核心消息接收器实例(InProcessCoreSink)
|
||||
"""
|
||||
@@ -183,7 +183,7 @@ class PluginManager:
|
||||
|
||||
async def _register_adapter_components(self, plugin_name: str, plugin_instance: PluginBase) -> None:
|
||||
"""注册适配器组件
|
||||
|
||||
|
||||
Args:
|
||||
plugin_name: 插件名称
|
||||
plugin_instance: 插件实例
|
||||
@@ -192,36 +192,36 @@ class PluginManager:
|
||||
from src.plugin_system.base.component_types import AdapterInfo, ComponentType
|
||||
from src.plugin_system.core.adapter_manager import get_adapter_manager
|
||||
from src.plugin_system.core.component_registry import component_registry
|
||||
|
||||
|
||||
# 获取所有 ADAPTER 类型的组件
|
||||
plugin_info = plugin_instance.plugin_info
|
||||
adapter_components = [
|
||||
comp for comp in plugin_info.components
|
||||
comp for comp in plugin_info.components
|
||||
if comp.component_type == ComponentType.ADAPTER
|
||||
]
|
||||
|
||||
|
||||
if not adapter_components:
|
||||
return
|
||||
|
||||
|
||||
adapter_manager = get_adapter_manager()
|
||||
|
||||
|
||||
for comp_info in adapter_components:
|
||||
# 类型检查:确保是 AdapterInfo
|
||||
if not isinstance(comp_info, AdapterInfo):
|
||||
logger.warning(f"组件 {comp_info.name} 不是 AdapterInfo 类型")
|
||||
continue
|
||||
|
||||
|
||||
try:
|
||||
# 从组件注册表获取适配器类
|
||||
adapter_class = component_registry.get_component_class(
|
||||
comp_info.name,
|
||||
comp_info.name,
|
||||
ComponentType.ADAPTER
|
||||
)
|
||||
|
||||
|
||||
if not adapter_class:
|
||||
logger.warning(f"无法找到适配器组件类: {comp_info.name}")
|
||||
continue
|
||||
|
||||
|
||||
# 创建适配器实例,传入 core_sink 和 plugin
|
||||
# 注册到适配器管理器,由管理器统一在运行时创建实例
|
||||
adapter_manager.register_adapter(adapter_class, plugin_instance) # type: ignore
|
||||
@@ -229,13 +229,13 @@ class PluginManager:
|
||||
f"插件 '{plugin_name}' 注册了适配器组件: {comp_info.name} "
|
||||
f"(平台: {comp_info.platform})"
|
||||
)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"注册插件 '{plugin_name}' 的适配器组件 '{comp_info.name}' 时出错: {e}",
|
||||
exc_info=True
|
||||
)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"处理插件 '{plugin_name}' 的适配器组件时出错: {e}")
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ class ToolCallRecord:
|
||||
no_truncate_tools = {"web_search", "web_surfing", "knowledge_search"}
|
||||
should_truncate = self.tool_name not in no_truncate_tools
|
||||
max_length = 500 if should_truncate else 10000 # 联网搜索给更大的限制
|
||||
|
||||
|
||||
if isinstance(content, str):
|
||||
if len(content) > max_length:
|
||||
self.result_preview = content[:max_length] + "..."
|
||||
@@ -415,7 +415,6 @@ _STREAM_MANAGERS_MAX_SIZE = 100 # 最大保留数量
|
||||
|
||||
def _evict_old_stream_managers() -> None:
|
||||
"""内存优化:淘汰最久未使用的 stream manager"""
|
||||
import time
|
||||
|
||||
if len(_stream_managers) < _STREAM_MANAGERS_MAX_SIZE:
|
||||
return
|
||||
@@ -429,10 +428,8 @@ def _evict_old_stream_managers() -> None:
|
||||
|
||||
evicted = []
|
||||
for chat_id, _ in sorted_by_time[:evict_count]:
|
||||
if chat_id in _stream_managers:
|
||||
del _stream_managers[chat_id]
|
||||
if chat_id in _stream_managers_last_used:
|
||||
del _stream_managers_last_used[chat_id]
|
||||
_stream_managers.pop(chat_id, None)
|
||||
_stream_managers_last_used.pop(chat_id, None)
|
||||
evicted.append(chat_id)
|
||||
|
||||
if evicted:
|
||||
@@ -466,8 +463,6 @@ def cleanup_stream_manager(chat_id: str) -> None:
|
||||
Args:
|
||||
chat_id: 聊天ID
|
||||
"""
|
||||
if chat_id in _stream_managers:
|
||||
del _stream_managers[chat_id]
|
||||
if chat_id in _stream_managers_last_used:
|
||||
del _stream_managers_last_used[chat_id]
|
||||
_stream_managers.pop(chat_id, None)
|
||||
_stream_managers_last_used.pop(chat_id, None)
|
||||
logger.info(f"已清理聊天 {chat_id} 的工具历史记录管理器")
|
||||
|
||||
@@ -11,7 +11,6 @@ from src.llm_models.payload_content import ToolCall
|
||||
from src.llm_models.utils_model import LLMRequest
|
||||
from src.plugin_system.apis.tool_api import get_llm_available_tool_definitions, get_tool_instance
|
||||
from src.plugin_system.base.base_tool import BaseTool
|
||||
from src.plugin_system.core.global_announcement_manager import global_announcement_manager
|
||||
from src.plugin_system.core.stream_tool_history import ToolCallRecord, get_stream_tool_history_manager
|
||||
|
||||
logger = get_logger("tool_use")
|
||||
@@ -203,7 +202,7 @@ class ToolExecutor:
|
||||
logger.debug(f"{self.log_prefix}开始LLM工具调用分析")
|
||||
|
||||
# 调用LLM进行工具决策
|
||||
response, llm_extra_info = await self.llm_model.generate_response_async(
|
||||
_response, llm_extra_info = await self.llm_model.generate_response_async(
|
||||
prompt=prompt, tools=tools, raise_when_empty=False
|
||||
)
|
||||
|
||||
@@ -412,7 +411,7 @@ class ToolExecutor:
|
||||
for i, tool_call in enumerate(tool_calls)
|
||||
]
|
||||
|
||||
|
||||
|
||||
async def _execute_single_tool_with_timeout(self, tool_call: ToolCall, index: int) -> ToolExecutionResult:
|
||||
"""执行单个工具调用,支持超时控制
|
||||
|
||||
|
||||
Reference in New Issue
Block a user