Skip to content

[Bug] turn_on_plugin 不在 AstrBot 重启路径中,inactivated_llm_tools 幽灵条目随重启累积 #8584

@irmia2026

Description

@irmia2026

What happened / 发生了什么

turn_off_plugin 将工具名写入持久化黑名单 inactivated_llm_tools(SQLite preferences 表),但恢复路径仅有一条:在 WebUI 中手动点击「启用插件」按钮。AstrBot 正常重启(stop()load())、reload()restart() 均不经过 turn_on_plugin,导致黑名单条目随每次停用操作不断累积,重启后无差别将所有工具设为关闭状态。


根因:写入和恢复路径不对称

下面是 inactivated_llm_tools 的完整数据流:

┌──────────────────────────────────────────────────┐
│ 写入(唯一路径)                                   │
│ star_manager.py:1712-1716 — turn_off_plugin       │
│   sp.global_put("inactivated_llm_tools", [...])   │
│   → 持久化到 SQLite preferences 表                 │
├──────────────────────────────────────────────────┤
│ 读取 + 应用                                        │
│ star_manager.py:891 — load()                      │
│   inactivated_llm_tools = sp.global_get(...)      │
│ star_manager.py:1091 — load()                     │
│   if ft.name in inactivated_llm_tools:            │
│       ft.active = False                           │
│   (只应用黑名单,从不清理)                         │
├──────────────────────────────────────────────────┤
│ 恢复(唯一路径)                                    │
│ dashboard/routes/plugin.py:1902                   │
│   → turn_on_plugin                               │
│   → 遍历 func_list,清理匹配的条目                  │
│   → 仅 WebUI 手动「启用插件」触发                   │
└──────────────────────────────────────────────────┘

关键缺口在 load():它读取黑名单、应用黑名单,但从不清理那些"对应插件已启用"的条目。load() 在所有插件加载完成后应该检查:某个插件是启用的 → 它的工具不应该在黑名单里 → 清除对应条目。

此外,以下常见操作路径完全绕过了 turn_on_plugin

操作 是否调 turn_on_plugin
AstrBot 重启(stop()load()
reload()_unbind_plugin_terminate_pluginload()
restart()
WebUI「启用插件」按钮 ✅(唯一)

累积效应

每次停用-重新启用循环如果是通过 AstrBot 重启(而非 WebUI 按钮)完成的,就会在 DB 中留下 N 个幽灵条目。多次累积后,inactivated_llm_tools 列表持续增长,load() 在 L1091 无差别应用——即使用户手动逐个打开过所有工具,重启后它们又全被关闭。


涉及文件

文件 行号 说明
astrbot/core/star/star_manager.py 870-1249 load():读取并应用黑名单,但缺少末尾清理步骤
astrbot/core/star/star_manager.py 1679-1718 turn_off_plugin:唯一写入点
astrbot/core/star/star_manager.py 1767-1791 turn_on_plugin:唯一清理点(但不在重启路径中)
astrbot/dashboard/routes/plugin.py 1902 WebUI 触发 turn_on_plugin 的唯一入口

Expected behavior / 期望行为

load() 在所有插件加载完成后,遍历所有 activated=True 的插件已注册的工具,将匹配条目从 inactivated_llm_tools 中清除并恢复 active

# load() 末尾,所有 star 加载完成后(仅 full reload 时执行)
# 遍历 star_registry 而非 star_map,因为前者按注册顺序保留
for star_meta in star_registry:
    if not star_meta.activated or not star_meta.module_path:
        continue
    plugin_path = star_meta.module_path
    for func_tool in llm_tools.func_list:
        mp = func_tool.handler_module_path
        if not mp:
            continue
        if mp.startswith(plugin_path):
            if func_tool.name in inactivated_llm_tools:
                inactivated_llm_tools.remove(func_tool.name)
                func_tool.active = True
await sp.global_put("inactivated_llm_tools", inactivated_llm_tools)

注意:此修复仅针对"因插件整体停用而写入黑名单的工具"。由于 inactivated_llm_tools扁平列表,不区分"因插件停用而关闭"和"用户单独手动关闭",用户单独关闭的工具也会在重启后被恢复。这是 inactivated_llm_tools 架构层面的缺陷(turn_on_plugin 目前同样有此问题),彻底的修复需要将两套语义分开存储(例如新增 inactivated_plugins 作为独立判断依据),不在本 issue 范围内。


Reproduce / 如何复现?

  1. 部署一个注册了函数工具的插件
  2. WebUI 停用该插件 → turn_off_plugin 将 N 个工具名写入 DB
  3. WebUI 重新启用插件 → 工具恢复正常(这一步走了 turn_on_plugin,清理成功)
  4. 重启 AstrBot(不走 turn_on_plugin)→ load() 从 DB 读取黑名单 → 工具被设为 active=False
  5. 用户手动在「函数工具管理」中重新打开工具
  6. 再次重启 AstrBotload() 再次读取 → 工具再次被关闭

黑名单条目不会被任何重启路径清理,只能通过 WebUI 启用插件来清除。


AstrBot version, deployment method (e.g., Windows Docker Desktop deployment), provider used, and messaging platform used. / AstrBot 版本、部署方式(如 Windows Docker Desktop 部署)、使用的提供商、使用的消息平台适配器

AstrBot 版本 v4.24.2
Python 版本 3.12.12
操作系统 Windows 11

OS

Windows

Logs / 报错日志

无显式报错。

Are you willing to submit a PR? / 你愿意提交 PR 吗?

  • Yes!

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:coreThe bug / feature is about astrbot's core, backendbugSomething isn't workingfeature:pluginThe bug / feature is about AstrBot plugin system.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions