Skip to content

feat: 新增两个插件生命周期事件钩子 & 为插件metadata.yaml引入dependencies字段 #1925

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

Flartiny
Copy link
Contributor

@Flartiny Flartiny commented Jun 25, 2025

Motivation

为可能的插件联动做铺垫,方便监控插件生命周期

Modifications

  1. 新增on_star_activated和on_star_deactivated两个事件钩子,帮助了解其他插件的状态,使用上形如:
@filter.on_star_activated("astrbot_plugin_monitered")
async def on_star_activated(self, star: StarMetadata):
        logger.info(f"插件 {star.name} 已启用")
  1. 为使以上改动在初始化时按预期工作,尝试通过引入可选的dependencies字段控制插件的初始化顺序
    举例来说:有A插件,其功能一定程度上依赖B插件
name: astrbot_plugin_A
desc: This is plugin A
version: v1.0.0
author: AstrBot
repo: https://github.com/author/astrbot_plugin_A
dependencies:
    - astrbot_plugin_B

则A先于B初始化,待B初始化(启用)时,就能触发A中的on_star_activated钩子
此外,系统插件优先初始化

Check

目前仅进行了简单测试(一级依赖),复杂用例与可能导致错误的用例待测试

  • 😊 我的 Commit Message 符合良好的规范
  • 👀 我的更改经过良好的测试
  • 🤓 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到了 requirements.txtpyproject.toml 文件相应位置。
  • 😮 我的更改没有引入恶意代码

好的,这是将 pull request 总结翻译成中文的结果:

Sourcery 总结

引入了两个插件生命周期事件钩子用于激活和停用,并支持通过元数据中新的“dependencies”字段实现依赖驱动的插件初始化顺序。

新特性:

  • 添加 on_star_activated 事件钩子,用于在指定插件激活时发出通知
  • 添加 on_star_deactivated 事件钩子,用于在指定插件停用时发出通知
  • 支持插件元数据中的可选 dependencies 字段,用于指定加载依赖项

增强功能:

  • 实现拓扑排序,以根据声明的依赖关系确定插件加载顺序,并优先加载系统插件
  • 在插件激活和停用过程中触发新的生命周期事件
Original summary in English

Summary by Sourcery

Introduce two plugin lifecycle event hooks for activation and deactivation, and support dependency-driven plugin initialization order via a new 'dependencies' field in metadata.

New Features:

  • Add on_star_activated event hook to notify when a specified plugin is activated
  • Add on_star_deactivated event hook to notify when a specified plugin is deactivated
  • Support an optional dependencies field in plugin metadata for specifying load dependencies

Enhancements:

  • Implement topological sorting to determine plugin load order based on declared dependencies and prioritise system plugins
  • Trigger the new lifecycle events during plugin activation and deactivation processes

This comment was marked as outdated.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Flartiny - 我已经查看了你的更改 - 这里有一些反馈:

  • 避免在加载元数据时在 _get_load_order 中静默地吞下异常——至少记录堆栈跟踪,这样插件故障就不会被隐藏。
  • _get_load_order 中提取依赖关系图构建和拓扑排序到更小的辅助方法中,以提高可读性和可测试性。
  • 目前,缺少依赖项只会发出警告,但仍然会加载插件——考虑排除或快速失败未解决的依赖项,以避免不可预测的运行时错误。
AI 代理的提示
请解决此代码审查中的评论:
## 总体评论
- 避免在加载元数据时在 `_get_load_order` 中静默地吞下异常——至少记录堆栈跟踪,这样插件故障就不会被隐藏。
-`_get_load_order` 中提取依赖关系图构建和拓扑排序到更小的辅助方法中,以提高可读性和可测试性。
- 目前,缺少依赖项只会发出警告,但仍然会加载插件——考虑排除或快速失败未解决的依赖项,以避免不可预测的运行时错误。

Sourcery 对开源是免费的 - 如果你喜欢我们的评论,请考虑分享它们 ✨
帮助我更有用!请点击每个评论上的 👍 或 👎,我将使用反馈来改进你的评论。
Original comment in English

Hey @Flartiny - I've reviewed your changes - here's some feedback:

  • Avoid silently swallowing exceptions in _get_load_order when loading metadata—at minimum log the stack trace so plugin failures aren’t hidden.
  • Extract the dependency‐graph construction and topological sort from _get_load_order into smaller helper methods to improve readability and testability.
  • Right now missing dependencies only emit warnings but still load the plugin—consider excluding or failing fast on unresolved dependencies to avoid unpredictable runtime errors.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Avoid silently swallowing exceptions in `_get_load_order` when loading metadata—at minimum log the stack trace so plugin failures aren’t hidden.
- Extract the dependency‐graph construction and topological sort from `_get_load_order` into smaller helper methods to improve readability and testability.
- Right now missing dependencies only emit warnings but still load the plugin—consider excluding or failing fast on unresolved dependencies to avoid unpredictable runtime errors.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 887 to 889
# 检查这个 handler 是否监听了特定的插件名
target_star_name = handler.extras_configs.get("target_star_name")
if target_star_name:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Use named expression to simplify assignment and conditional (use-named-expression)

Suggested change
# 检查这个 handler 是否监听了特定的插件名
target_star_name = handler.extras_configs.get("target_star_name")
if target_star_name:
if target_star_name := handler.extras_configs.get("target_star_name"):
Original comment in English

suggestion (code-quality): Use named expression to simplify assignment and conditional (use-named-expression)

Suggested change
# 检查这个 handler 是否监听了特定的插件名
target_star_name = handler.extras_configs.get("target_star_name")
if target_star_name:
if target_star_name := handler.extras_configs.get("target_star_name"):

Comment on lines +941 to +942
metadata = self._load_plugin_metadata(plugin_dir_path)
if metadata:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Use named expression to simplify assignment and conditional (use-named-expression)

Suggested change
metadata = self._load_plugin_metadata(plugin_dir_path)
if metadata:
if metadata := self._load_plugin_metadata(plugin_dir_path):
Original comment in English

suggestion (code-quality): Use named expression to simplify assignment and conditional (use-named-expression)

Suggested change
metadata = self._load_plugin_metadata(plugin_dir_path)
if metadata:
if metadata := self._load_plugin_metadata(plugin_dir_path):

Copy link
Member

@Soulter Soulter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这两个钩子和 terminal() 与 initialize() 有区别嘛

@Soulter Soulter self-assigned this Jun 28, 2025
@Flartiny
Copy link
Contributor Author

这两个钩子和 terminal() 与 initialize() 有区别嘛

我认为有一定区别,terminal() 与 initialize()用于控制插件自身在生命周期首尾的活动,而on_star_activated和on_star_deactivated帮助插件在自身生命周期中期了解其他插件的启停情况并作出响应。

接前文,经测试,目前的改动一般情况下运行正常,但存在几处问题:

  1. 存在循环依赖时不加载任何插件,需手动处理造成循环的插件后重启
  2. 假设A依赖B,即A通过on_star_activated("B")监听B,A重载后需手动重载B以达到预期效果

正尝试基于图结构更好地管理插件间的关联,包括以子图为单位自动进行插件重载等

@Flartiny
Copy link
Contributor Author

引入networkx进行相关操作,这个依赖应该未来的记忆部分也会引入(?
图片
以上图为例:
重载A时,实际重载插件的顺序为[A,B,C,D]
重载B时,实际重载插件的顺序为[B,C,D]
重载C时,实际重载插件的顺序为[C,D]
重载D时,实际重载插件的顺序为[D]

关于此pr的说明:
metadata.yaml引入dependencies仅帮助控制加载顺序,它在逻辑上建立插件间的依赖关系
两个事件钩子的作用就如其字面含义,但多数情况下会需要经过控制加载顺序以正常工作


现在存在循环依赖时,仍加载全部插件,目的是不影响无关插件的工作。但导致循环依赖的部分插件可能不按预期工作,这点由用户或开发者自行处理。
现在涉及加载插件的操作(启用、重载、安装)均以子图为单位进行,如上图。


install_plugin_from_file未经测试(我的Astrbot之前“从压缩包安装”就用不了,可能和docker或者其他未知原因有关。但是从代码上看应该没问题)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants