feat(plugin_system): 引入组件局部状态管理并重构插件API

引入了基于 `stream_id` 的组件局部状态管理机制。这允许在不修改全局配置的情况下,为特定会话临时启用或禁用组件,提供了更高的灵活性。

全面重构了 `plugin_manage_api`,提供了更强大和稳定的插件管理功能:
- 新增 `reload_all_plugins` 和 `get_system_report` API,方便进行批量重载和系统状态诊断。
- 增强了组件卸载逻辑,确保在插件移除时能更彻底地清理资源,特别是对 `EventHandler` 的订阅。
- 重写了内置的 `/system plugin` 命令,以利用新的API,并为相关操作添加了权限控制。

组件注册中心(ComponentRegistry)中的多个 `get_enabled_*` 方法现在可以接受 `stream_id`,以正确反映局部状态。

BREAKING CHANGE: `plugin_manage_api` 中的多个函数已被移除或替换。例如 `list_loaded_plugins` 和 `remove_plugin` 已被移除,加载插件的逻辑已整合到 `register_plugin_from_file` 中。内置的 `/system plugin` 命令的子命令也已更改。
This commit is contained in:
minecraft1024a
2025-11-21 21:05:02 +08:00
parent ccfe17c986
commit a0618fb3c4
5 changed files with 390 additions and 143 deletions

View File

@@ -96,16 +96,13 @@ class SystemCommand(PlusCommand):
help_text = """🔌 插件管理命令帮助
📋 基本操作:
• `/system plugin help` - 显示插件管理帮助
• `/system plugin list` - 列出所有注册的插件
• `/system plugin list_enabled` - 列出所有加载(启用)的插件
• `/system plugin report` - 查看系统插件报告
• `/system plugin rescan` - 重新扫描所有插件目录
⚙️ 插件控制:
• `/system plugin load <插件名>` - 加载指定插件
• `/system plugin unload <插件名>` - 卸载指定插件
• `/system plugin reload <插件名>` - 重新加载指定插件
• `/system plugin force_reload <插件名>` - 强制重载指定插件
• `/system plugin add_dir <目录路径>` - 添加插件目录
• `/system plugin reload_all` - 重新加载所有插件
"""
elif target == "permission":
help_text = """📋 权限管理命令帮助
@@ -150,20 +147,16 @@ class SystemCommand(PlusCommand):
if action in ["help", "帮助"]:
await self._show_help("plugin")
elif action in ["list", "列表"]:
await self._list_registered_plugins()
elif action in ["list_enabled", "已启用"]:
await self._list_loaded_plugins()
elif action in ["report", "报告"]:
await self._show_system_report()
elif action in ["rescan", "重扫"]:
await self._rescan_plugin_dirs()
elif action in ["load", "加载"] and len(remaining_args) > 0:
await self._load_plugin(remaining_args[0])
elif action in ["unload", "卸载"] and len(remaining_args) > 0:
await self._unload_plugin(remaining_args[0])
elif action in ["reload", "重载"] and len(remaining_args) > 0:
await self._reload_plugin(remaining_args[0])
elif action in ["force_reload", "强制重载"] and len(remaining_args) > 0:
await self._force_reload_plugin(remaining_args[0])
elif action in ["reload_all", "重载全部"]:
await self._reload_all_plugins()
else:
await self.send_text("❌ 插件管理命令不合法\n使用 /system plugin help 查看帮助")
@@ -429,61 +422,70 @@ class SystemCommand(PlusCommand):
# Permission Management Section
# =================================================================
async def _list_loaded_plugins(self):
"""列出已加载的插件"""
plugins = plugin_manage_api.list_loaded_plugins()
await self.send_text(f"📦 已加载的插件: {', '.join(plugins) if plugins else ''}")
@require_permission("plugin.manage", deny_message="❌ 你没有权限查看插件报告")
async def _show_system_report(self):
"""显示系统插件报告"""
report = plugin_manage_api.get_system_report()
response_parts = [
"📊 **系统插件报告**",
f" - 已加载插件: {report['system_info']['loaded_plugins_count']}",
f" - 组件总数: {report['system_info']['total_components_count']}",
]
async def _list_registered_plugins(self):
"""列出已注册的插件"""
plugins = plugin_manage_api.list_registered_plugins()
await self.send_text(f"📋 已注册的插件: {', '.join(plugins) if plugins else ''}")
if report["plugins"]:
response_parts.append("\n✅ **已加载插件:**")
for name, info in report["plugins"].items():
response_parts.append(f" • **{info['display_name']} (`{name}`)** v{info['version']} by {info['author']}")
if report["failed_plugins"]:
response_parts.append("\n❌ **加载失败的插件:**")
for name, error in report["failed_plugins"].items():
response_parts.append(f" • **`{name}`**: {error}")
await self._send_long_message("\n".join(response_parts))
@require_permission("plugin.manage", deny_message="❌ 你没有权限扫描插件")
async def _rescan_plugin_dirs(self):
"""重新扫描插件目录"""
plugin_manage_api.rescan_plugin_directory()
await self.send_text("🔄 插件目录重新扫描已启动")
await self.send_text("🔄 正在重新扫描插件目录...")
success, fail = plugin_manage_api.rescan_and_register_plugins(load_after_register=True)
await self.send_text(f"✅ 扫描完成!\n新增成功: {success}个, 新增失败: {fail}个。")
@require_permission("plugin.manage", deny_message="❌ 你没有权限加载插件")
async def _load_plugin(self, plugin_name: str):
"""加载指定插件"""
success, count = plugin_manage_api.load_plugin(plugin_name)
success = plugin_manage_api.register_plugin_from_file(plugin_name, load_after_register=True)
if success:
await self.send_text(f"✅ 插件加载成功: `{plugin_name}`")
else:
if count == 0:
await self.send_text(f"⚠️ 插件 `{plugin_name}` 为禁用状态")
else:
await self.send_text(f"❌ 插件加载失败: `{plugin_name}`")
await self.send_text(f"❌ 插件加载失败: `{plugin_name}`。请检查日志获取详细信息。")
async def _unload_plugin(self, plugin_name: str):
"""卸载指定插件"""
success = await plugin_manage_api.remove_plugin(plugin_name)
if success:
await self.send_text(f"✅ 插件卸载成功: `{plugin_name}`")
else:
await self.send_text(f"❌ 插件卸载失败: `{plugin_name}`")
@require_permission("plugin.manage", deny_message="❌ 你没有权限重载插件")
async def _reload_plugin(self, plugin_name: str):
"""重新加载指定插件"""
success = await plugin_manage_api.reload_plugin(plugin_name)
if success:
await self.send_text(f"✅ 插件重新加载成功: `{plugin_name}`")
else:
await self.send_text(f"❌ 插件重新加载失败: `{plugin_name}`")
async def _force_reload_plugin(self, plugin_name: str):
"""强制重载指定插件(深度清理)"""
await self.send_text(f"🔄 开始强制重载插件: `{plugin_name}`... (注意: 实际执行reload)")
try:
success = await plugin_manage_api.reload_plugin(plugin_name)
if success:
await self.send_text(f"✅ 插件重载成功: `{plugin_name}`")
await self.send_text(f"✅ 插件重新加载成功: `{plugin_name}`")
else:
await self.send_text(f"❌ 插件重载失败: `{plugin_name}`")
except Exception as e:
await self.send_text(f"重载过程中发生错误: {e!s}")
await self.send_text(f"❌ 插件重新加载失败: `{plugin_name}`")
except ValueError as e:
await self.send_text(f"操作失败: {e}")
@require_permission("plugin.manage", deny_message="❌ 你没有权限重载所有插件")
async def _reload_all_plugins(self):
"""重新加载所有插件"""
await self.send_text("🔄 正在重新加载所有插件...")
success = await plugin_manage_api.reload_all_plugins()
if success:
await self.send_text("✅ 所有插件已成功重载。")
else:
await self.send_text("⚠️ 部分插件重载失败,请检查日志。")
# =================================================================
# Permission Management Section