refactor: 优化插件处理逻辑,改进导入保护机制

This commit is contained in:
DrSmoothl
2026-03-24 11:51:15 +08:00
parent d5581a1a97
commit b8224bdb3c

View File

@@ -429,9 +429,9 @@ class PluginRunner:
component_name = str(comp_info.get("name", "") or "").strip() component_name = str(comp_info.get("name", "") or "").strip()
raw_metadata = comp_info.get("metadata", {}) raw_metadata = comp_info.get("metadata", {})
component_metadata = raw_metadata if isinstance(raw_metadata, dict) else {} component_metadata = raw_metadata if isinstance(raw_metadata, dict) else {}
handler_name = str(component_metadata.get("handler_name", component_name) or component_name).strip()
if component_name: if component_name:
handler_name = str(component_metadata.get("handler_name", component_name) or component_name).strip()
meta.component_handlers[component_name] = handler_name or component_name meta.component_handlers[component_name] = handler_name or component_name
components.append( components.append(
@@ -765,8 +765,7 @@ class PluginRunner:
target_plugin_ids: Set[str] = { target_plugin_ids: Set[str] = {
plugin_id for plugin_id in reload_root_ids if plugin_id not in loaded_plugin_ids plugin_id for plugin_id in reload_root_ids if plugin_id not in loaded_plugin_ids
} }
loaded_root_plugin_ids = reload_root_ids & loaded_plugin_ids if loaded_root_plugin_ids := reload_root_ids & loaded_plugin_ids:
if loaded_root_plugin_ids:
target_plugin_ids.update(self._collect_reverse_dependents_for_roots(loaded_root_plugin_ids)) target_plugin_ids.update(self._collect_reverse_dependents_for_roots(loaded_root_plugin_ids))
unload_order = self._build_unload_order(target_plugin_ids & loaded_plugin_ids) unload_order = self._build_unload_order(target_plugin_ids & loaded_plugin_ids)
@@ -823,11 +822,10 @@ class PluginRunner:
continue continue
_, manifest, _ = candidate _, manifest, _ = candidate
unsatisfied_dependencies = self._loader.manifest_validator.get_unsatisfied_plugin_dependencies( if unsatisfied_dependencies := self._loader.manifest_validator.get_unsatisfied_plugin_dependencies(
manifest, manifest,
available_plugin_versions=available_plugins, available_plugin_versions=available_plugins,
) ):
if unsatisfied_dependencies:
failed_plugins[load_plugin_id] = f"依赖未满足: {', '.join(unsatisfied_dependencies)}" failed_plugins[load_plugin_id] = f"依赖未满足: {', '.join(unsatisfied_dependencies)}"
continue continue
@@ -1240,10 +1238,12 @@ def _isolate_sys_path(plugin_dirs: List[str]) -> None:
同时阻止插件代码直接导入主程序内部 ``src.*`` 模块,并清理可直接从 同时阻止插件代码直接导入主程序内部 ``src.*`` 模块,并清理可直接从
``sys.modules`` 摸到的高权限叶子模块,避免绕过 SDK / capability 边界。 ``sys.modules`` 摸到的高权限叶子模块,避免绕过 SDK / capability 边界。
""" """
from importlib import util as importlib_util
from types import ModuleType
import builtins import builtins
import importlib import importlib
import sysconfig import sysconfig
from types import ModuleType
# 保留: 标准库路径 + site-packages含 SDK 和依赖) # 保留: 标准库路径 + site-packages含 SDK 和依赖)
stdlib_paths = set() stdlib_paths = set()
@@ -1389,26 +1389,28 @@ def _isolate_sys_path(plugin_dirs: List[str]) -> None:
sys.modules.pop(module_name, None) sys.modules.pop(module_name, None)
# ``import`` 语句与 ``importlib.import_module`` 走的是不同入口,因此两边都需要兜底。 # ``import`` 语句与 ``importlib.import_module`` 走的是不同入口,因此两边都需要兜底。
original_import = getattr(builtins, "__maibot_runner_original_import__", builtins.__import__) builtins_module = cast(Any, builtins)
builtins.__maibot_runner_original_import__ = original_import original_import = getattr(builtins_module, "__maibot_runner_original_import__", builtins.__import__)
builtins_module.__maibot_runner_original_import__ = original_import
def _guarded_import(name: str, globals: Any = None, locals: Any = None, fromlist: Any = (), level: int = 0) -> Any: def _guarded_import(name: str, globals: Any = None, locals: Any = None, fromlist: Any = (), level: int = 0) -> Any:
if level == 0: if level == 0:
_assert_plugin_import_allowed(name, import_globals=globals, fromlist=fromlist) _assert_plugin_import_allowed(name, import_globals=globals, fromlist=fromlist)
return original_import(name, globals, locals, fromlist, level) return original_import(name, globals, locals, fromlist, level)
_guarded_import.__maibot_runner_plugin_import_guard__ = True cast(Any, _guarded_import).__maibot_runner_plugin_import_guard__ = True
builtins.__import__ = _guarded_import builtins.__import__ = _guarded_import
original_import_module = getattr(importlib, "__maibot_runner_original_import_module__", importlib.import_module) importlib_module = cast(Any, importlib)
importlib.__maibot_runner_original_import_module__ = original_import_module original_import_module = getattr(importlib_module, "__maibot_runner_original_import_module__", importlib.import_module)
importlib_module.__maibot_runner_original_import_module__ = original_import_module
def _guarded_import_module(name: str, package: Optional[str] = None) -> Any: def _guarded_import_module(name: str, package: Optional[str] = None) -> Any:
resolved_name = importlib.util.resolve_name(name, package) if name.startswith(".") else name resolved_name = importlib_util.resolve_name(name, package) if name.startswith(".") else name
_assert_plugin_import_allowed(resolved_name) _assert_plugin_import_allowed(resolved_name)
return original_import_module(name, package) return original_import_module(name, package)
_guarded_import_module.__maibot_runner_plugin_import_guard__ = True cast(Any, _guarded_import_module).__maibot_runner_plugin_import_guard__ = True
importlib.import_module = _guarded_import_module importlib.import_module = _guarded_import_module