插件实例与生命周期
每个 Nekro Agent 插件的核心都是一个 NekroPlugin
类的实例。这个实例不仅定义了插件的基本信息,还作为各种功能和事件回调的挂载点。理解插件实例的创建和其完整的生命周期对于开发稳定且功能完善的插件至关重要。
NekroPlugin
实例
在你的插件主文件 (例如 plugin.py
) 中,首先需要导入并创建一个 NekroPlugin
实例:
from nekro_agent.api.plugin import NekroPlugin
plugin = NekroPlugin(
name="我的酷炫插件",
module_name="my_cool_plugin",
description="这个插件能做很多酷炫的事情。",
version="1.0.0",
author="开发者名称",
url="https://github.com/developer/my_cool_plugin", # 可选
is_builtin=False, # 通常第三方插件为 False
is_package=False # 如果你的插件是一个复杂的包结构,可能需要调整
)
核心参数解析:
name
(str): 插件的显示名称,将出现在 Nekro Agent 的用户界面中。module_name
(str): 插件的模块名称,必须是 Python 模块的有效名称,并且在所有插件中保持唯一。通常与插件的目录名一致。它用于内部识别和管理插件。description
(str): 插件的简短描述,说明其主要功能。version
(str): 插件的版本号,建议遵循语义化版本规范 (如1.0.0
)。author
(str): 插件的作者或开发团队名称。url
(str, 可选): 指向插件项目仓库、文档或主页的 URL。is_builtin
(bool, 可选, 默认为False
): 标记插件是否为 Nekro Agent 内置插件。is_package
(bool, 可选, 默认为False
): 标记插件是否作为一个 Python 包进行管理。
NekroPlugin
实例 (plugin
) 将作为后续所有装饰器的调用对象,用于挂载沙盒方法、配置、生命周期回调等。
插件生命周期
插件的生命周期描述了从插件被系统发现、加载、运行到最终卸载的整个过程。Nekro Agent 提供了一系列装饰器,允许你在生命周期的特定阶段执行自定义逻辑。
1. 初始化 (@plugin.mount_init_method()
)
当 Nekro Agent 首次加载插件时(通常在 Agent 启动或插件被动态启用时),会执行通过 @plugin.mount_init_method()
装饰器注册的异步函数。这个阶段非常适合执行只需要进行一次的设置工作。
用途:
- 资源准备:创建或连接数据库、初始化文件系统(如创建插件所需的数据目录)。
- 状态初始化:设置插件的初始状态、加载默认配置或数据。
- 外部系统连接:如果插件需要与外部服务交互,可以在此建立连接。
- 环境验证:检查必要的依赖项或环境变量是否满足。
示例:
from nekro_agent.api import core
from qdrant_client import models as qdrant_models # 假设使用 qdrant
@plugin.mount_init_method()
async def initialize_plugin():
core.logger.info(f"插件 '{plugin.name}' 正在初始化...")
# 示例:初始化向量数据库集合
try:
client = await core.get_qdrant_client() # 获取 Qdrant 客户端
collection_name = plugin.get_vector_collection_name("my_data") # 为插件生成唯一的集合名
collections = await client.get_collections()
collection_names = [collection.name for collection in collections.collections]
if collection_name not in collection_names:
core.logger.info(f"正在创建向量数据库集合: {collection_name}")
await client.create_collection(
collection_name=collection_name,
vectors_config=qdrant_models.VectorParams(
size=768, # 示例维度,根据你的 embedding 模型调整
distance=qdrant_models.Distance.COSINE,
),
)
core.logger.success(f"集合 {collection_name} 创建成功")
else:
core.logger.info(f"集合 {collection_name} 已存在")
except Exception as e:
core.logger.error(f"插件 '{plugin.name}' 初始化向量数据库失败: {e}")
core.logger.success(f"插件 '{plugin.name}' 初始化完成。")
注意:初始化方法应该是异步的 (async def
)。如果初始化过程中发生错误,应妥善处理并记录日志,确保 Agent 能够继续运行。
2. 会话重置回调 (@plugin.mount_on_channel_reset()
)
当一个特定的聊天会话被重置时(例如用户清空了聊天历史或会话状态),通过 @plugin.mount_on_channel_reset()
装饰器注册的异步函数会被调用。这个回调会接收一个 AgentCtx
对象,其中包含了被重置会话的相关信息。
用途:
- 清理与特定会话相关的插件数据(如缓存、状态)。
- 重置该会话的插件特定设置。
示例:
from nekro_agent.api.schemas import AgentCtx
@plugin.mount_on_channel_reset()
async def handle_channel_reset(_ctx: AgentCtx):
core.logger.info(f"插件 '{plugin.name}' 收到会话 {_ctx.from_chat_key} 重置事件。")
# 示例:清除该会话的插件特定缓存
# await plugin.store.delete(chat_key=ctx.from_chat_key, store_key="session_cache")
core.logger.info(f"会话 {_ctx.from_chat_key} 的插件特定数据已清理。")
注意:滥用此回调可能会影响 Agent 的性能或正常对话流程。大多数插件功能应通过沙盒方法实现。
3. 清理 (@plugin.mount_cleanup_method()
)
当插件被卸载或 Nekro Agent 关闭时,会执行通过 @plugin.mount_cleanup_method()
装饰器注册的异步函数。这个阶段用于释放插件占用的所有资源,确保系统干净地关闭或重载插件。
用途:
- 释放资源:关闭数据库连接、释放文件句柄、停止后台任务等。
- 重置状态:清空全局变量或缓存,确保下次加载时是全新的状态。
- 外部系统断开连接:如果插件与外部服务保持长连接,应在此处断开。
示例:
@plugin.mount_cleanup_method()
async def cleanup_plugin():
core.logger.info(f"插件 '{plugin.name}' 正在清理...")
# 示例:关闭可能存在的数据库连接池或清除临时文件
# await close_database_connections()
# await clear_temporary_files()
core.logger.success(f"插件 '{plugin.name}' 清理完成。")
重要性: 正确的清理对于插件的稳定性和可维护性至关重要,尤其是在开发和调试阶段频繁重载插件时。如果未能正确清理资源,可能导致:
- 资源泄漏:如内存泄漏、文件句柄未释放。
- 状态冲突:重载后的插件可能继承了旧插件的残留状态。
- 行为异常:插件表现不符合预期。
确保你的初始化和清理方法成对出现,管理好插件的资源和状态。