fix: skip plugin reload for deactivated plugins to preserve their tools#8740
fix: skip plugin reload for deactivated plugins to preserve their tools#8740tangtaizong666 wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a check in star_manager.py to skip reloading deactivated plugins, preventing their registered tools from being unbound and lost. It also adds comprehensive unit tests to verify that deactivated plugins skip the reload cycle while activated plugins undergo the full cycle. The review feedback suggests adding or [] when retrieving inactivated_plugins to handle cases where the key exists but is explicitly set to None, avoiding a potential TypeError during membership testing.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| break | ||
|
|
||
| if specified_module_path: | ||
| inactivated_plugins = await sp.global_get("inactivated_plugins", []) |
There was a problem hiding this comment.
To ensure defensive programming and robust handling of potential null/None values in the configuration, it is safer to append or [] when retrieving inactivated_plugins. If the key exists in the shared preferences but is explicitly set to null (or None), sp.global_get will return None, which would subsequently cause a TypeError when executing specified_module_path in inactivated_plugins.
| inactivated_plugins = await sp.global_get("inactivated_plugins", []) | |
| inactivated_plugins = await sp.global_get("inactivated_plugins", []) or [] |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- In the new
reloadguard, the log message usesspecified_plugin_name, which can beNonewhen reloading by module path or in bulk; consider deriving a name fromsmdor falling back tospecified_module_pathso the log line is always meaningful.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In the new `reload` guard, the log message uses `specified_plugin_name`, which can be `None` when reloading by module path or in bulk; consider deriving a name from `smd` or falling back to `specified_module_path` so the log line is always meaningful.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
Responding to the two bot review suggestions after checking them against the codebase:
|
Fixes #8582
Saving the config of a deactivated plugin in the WebUI calls
plugin_manager.reload(plugin_name)unconditionally (dashboard/routes/config.py). For a deactivated plugin,_terminate_pluginshort-circuits, but_unbind_pluginstill removes the plugin fromstar_map/star_registryand deletes all of its tools fromllm_tools.func_list, while the subsequentload()skips instantiation (the plugin path is ininactivated_plugins). Tools registered viacontext.add_llm_tools()in the plugin's__init__are therefore never re-added: they disappear fromfunc_listuntil the plugin is re-enabled, and staleinactivated_llm_toolsblacklist entries are left behind.Modifications / 改动点
astrbot/core/star/star_manager.py:reload()now returns early when the specified plugin is listed in the persistedinactivated_pluginspreference. A deactivated plugin has no instance to re-apply config to; the new config is picked up by the full reload thatturn_on_plugintriggers when the plugin is re-enabled.inactivated_pluginspreference instead ofmetadata.activated:turn_on_pluginremoves the entry from the preference before callingreload(), while the stale metadata still hasactivated=Falseat that moment, so checking the flag would break plugin re-enabling.reload()covers every caller (config save, WebUI reload button,update_plugin), not just the config-save route.tests/test_plugin_manager.py: regression tests for both paths — a deactivated plugin is left untouched (no terminate/unbind/load, stays instar_map/star_registry), and an activated plugin still goes through the full terminate → unbind → load cycle.This is NOT a breaking change. / 这不是一个破坏性变更。
Screenshots or Test Results / 运行截图或测试结果
(includes the two new regression tests;
test_reload_skips_deactivated_pluginfails on master and passes with this change)Checklist / 检查清单
😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
/ 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。
👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
/ 我的更改经过了良好的测试,并已在上方提供了"验证步骤"和"运行截图"。
🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in
requirements.txtandpyproject.toml./ 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到
requirements.txt和pyproject.toml文件相应位置。😮 My changes do not introduce malicious code.
/ 我的更改没有引入恶意代码。
Summary by Sourcery
Guard plugin reload against deactivated plugins so their tools remain registered and configuration is applied only when re-enabled.
Bug Fixes:
Tests: