diff --git a/docs/plugins/config-access-guide.md b/docs/plugins/config-access-guide.md index 1a619316d..119684886 100644 --- a/docs/plugins/config-access-guide.md +++ b/docs/plugins/config-access-guide.md @@ -1,5 +1,11 @@ # 🔧 插件配置访问指南 +> **💡 阅读须知** +> +> 本文主要介绍如何在插件的 **Action** 或 **Command** 组件中 **访问(读取)** 配置值。 +> +> 如果你还不了解如何为插件 **定义** 配置并让系统 **自动生成** 带注释的 `config.toml` 文件,请务必先阅读 ➡️ **[⚙️ 插件配置定义指南](configuration-guide.md)**。 + ## 问题描述 在插件开发中,你可能遇到这样的问题: diff --git a/docs/plugins/configuration-guide.md b/docs/plugins/configuration-guide.md new file mode 100644 index 000000000..5b1b3f4df --- /dev/null +++ b/docs/plugins/configuration-guide.md @@ -0,0 +1,202 @@ +# ⚙️ 插件配置定义指南 + +本文档将指导你如何为你的插件定义一个健壮、规范且自带文档的配置文件。 + +## 核心理念:Schema驱动的配置 + +在新版插件系统中,我们引入了一套 **配置Schema(模式)驱动** 的机制。你不再需要手动创建和维护 `config.toml` 文件,而是通过在插件代码中 **声明配置的结构**,系统将为你完成剩下的工作。 + +**核心优势:** + +- **自动化 (Automation)**: 如果配置文件不存在,系统会根据你的声明 **自动生成** 一份包含默认值和详细注释的 `config.toml` 文件。 +- **规范化 (Standardization)**: 所有插件的配置都遵循统一的结构,提升了可维护性。 +- **自带文档 (Self-documenting)**: 配置文件中的每一项都包含详细的注释、类型说明、可选值和示例,极大地降低了用户的使用门槛。 +- **健壮性 (Robustness)**: 在代码中直接定义配置的类型和默认值,减少了因配置错误导致的运行时问题。 +- **易于管理 (Easy Management)**: 生成的配置文件可以方便地加入 `.gitignore`,避免将个人配置(如API Key)提交到版本库。 + +--- + +## 如何定义配置 + +配置的定义在你的插件主类(继承自 `BasePlugin`)中完成,主要通过两个类属性: + +1. `config_section_descriptions`: 一个字典,用于描述配置文件的各个区段(`[section]`)。 +2. `config_schema`: 核心部分,一个嵌套字典,用于定义每个区段下的具体配置项。 + +### `ConfigField`:配置项的基石 + +每个配置项都通过一个 `ConfigField` 对象来定义。 + +```python +from src.plugin_system.base.config_types import ConfigField + +@dataclass +class ConfigField: + """配置字段定义""" + type: type # 字段类型 (例如 str, int, float, bool, list) + default: Any # 默认值 + description: str # 字段描述 (将作为注释生成到配置文件中) + example: Optional[str] = None # 示例值 (可选) + required: bool = False # 是否必需 (可选, 主要用于文档提示) + choices: Optional[List[Any]] = None # 可选值列表 (可选) +``` + +--- + +## 完整示例 + +让我们以一个功能丰富的 `MutePlugin` 为例,看看如何定义它的配置。 + +### 1. 插件代码 (`plugin.py`) + +```python +# src/plugins/built_in/mute_plugin/plugin.py + +# ... 其他导入 ... +from src.plugin_system import BasePlugin, register_plugin +from src.plugin_system.base.config_types import ConfigField +from typing import List, Tuple, Type + +@register_plugin +class MutePlugin(BasePlugin): + """禁言插件""" + + # 插件基本信息 + plugin_name = "mute_plugin" + plugin_description = "群聊禁言管理插件,提供智能禁言功能" + plugin_version = "2.0.0" + plugin_author = "MaiBot开发团队" + enable_plugin = True + config_file_name = "config.toml" + + # 步骤1: 定义配置节的描述 + config_section_descriptions = { + "plugin": "插件基本信息配置", + "components": "组件启用控制", + "mute": "核心禁言功能配置", + "smart_mute": "智能禁言Action的专属配置", + "logging": "日志记录相关配置" + } + + # 步骤2: 使用ConfigField定义详细的配置Schema + config_schema = { + "plugin": { + "name": ConfigField(type=str, default="mute_plugin", description="插件名称", required=True), + "version": ConfigField(type=str, default="2.0.0", description="插件版本号"), + "enabled": ConfigField(type=bool, default=False, description="是否启用插件"), + "description": ConfigField(type=str, default="群聊禁言管理插件", description="插件描述", required=True) + }, + "components": { + "enable_smart_mute": ConfigField(type=bool, default=True, description="是否启用智能禁言Action"), + "enable_mute_command": ConfigField(type=bool, default=False, description="是否启用禁言命令Command") + }, + "mute": { + "min_duration": ConfigField(type=int, default=60, description="最短禁言时长(秒)"), + "max_duration": ConfigField(type=int, default=2592000, description="最长禁言时长(秒),默认30天"), + "templates": ConfigField( + type=list, + default=["好的,禁言 {target} {duration},理由:{reason}", "收到,对 {target} 执行禁言 {duration}"], + description="成功禁言后发送的随机消息模板" + ) + }, + "smart_mute": { + "keyword_sensitivity": ConfigField( + type=str, + default="normal", + description="关键词激活的敏感度", + choices=["low", "normal", "high"] # 定义可选值 + ), + }, + "logging": { + "level": ConfigField( + type=str, + default="INFO", + description="日志记录级别", + choices=["DEBUG", "INFO", "WARNING", "ERROR"] + ), + "prefix": ConfigField(type=str, default="[MutePlugin]", description="日志记录前缀", example="[MyMutePlugin]") + } + } + + def get_plugin_components(self) -> List[Tuple[ComponentInfo, Type]]: + # ... 组件注册逻辑 ... + # 在这里可以通过 self.get_config() 来获取配置值 + pass + +``` + +### 2. 自动生成的配置文件 (`config.toml`) + +当 `mute_plugin` 首次加载且其目录中不存在 `config.toml` 时,系统会自动创建以下文件: + +```toml +# mute_plugin - 自动生成的配置文件 +# 群聊禁言管理插件,提供智能禁言功能 + +# 插件基本信息配置 +[plugin] + +# 插件名称 (必需) +name = "mute_plugin" + +# 插件版本号 +version = "2.0.0" + +# 是否启用插件 +enabled = false + +# 插件描述 (必需) +description = "群聊禁言管理插件" + + +# 组件启用控制 +[components] + +# 是否启用智能禁言Action +enable_smart_mute = true + +# 是否启用禁言命令Command +enable_mute_command = false + + +# 核心禁言功能配置 +[mute] + +# 最短禁言时长(秒) +min_duration = 60 + +# 最长禁言时长(秒),默认30天 +max_duration = 2592000 + +# 成功禁言后发送的随机消息模板 +templates = ["好的,禁言 {target} {duration},理由:{reason}", "收到,对 {target} 执行禁言 {duration}"] + + +# 智能禁言Action的专属配置 +[smart_mute] + +# 关键词激活的敏感度 +# 可选值: low, normal, high +keyword_sensitivity = "normal" + + +# 日志记录相关配置 +[logging] + +# 日志记录级别 +# 可选值: DEBUG, INFO, WARNING, ERROR +level = "INFO" + +# 日志记录前缀 +# 示例: [MyMutePlugin] +prefix = "[MutePlugin]" + +``` + +## 最佳实践 + +1. **定义优于创建**: 始终优先在 `plugin.py` 中定义 `config_schema`,而不是手动创建 `config.toml`。 +2. **描述清晰**: 为每个 `ConfigField` 和 `config_section_descriptions` 编写清晰、准确的描述。这会直接成为你的插件文档的一部分。 +3. **提供合理默认值**: 确保你的插件在默认配置下就能正常运行(或处于一个安全禁用的状态)。 +4. **gitignore**: 将 `plugins/*/config.toml` 或 `src/plugins/built_in/*/config.toml` 加入 `.gitignore`,以避免提交个人敏感信息。 +5. **访问配置**: 在插件的任何地方,统一使用 `self.api.get_config("section.key", "default_value")` 来安全地获取配置值。详细请参考 [**插件配置访问指南**](config-access-guide.md)。 \ No newline at end of file diff --git a/docs/plugins/quick-start.md b/docs/plugins/quick-start.md index 2b5f38779..79d596601 100644 --- a/docs/plugins/quick-start.md +++ b/docs/plugins/quick-start.md @@ -1,5 +1,13 @@ # 🚀 快速开始指南 +本指南将带你用5分钟时间,从零开始创建一个功能完整的MaiBot插件。 + +> **💡 配置先行** +> +> 在开始之前,强烈建议你先阅读 ➡️ **[⚙️ 插件配置定义指南](configuration-guide.md)**。 +> +> 了解如何通过 `config_schema` 定义插件配置,可以让系统为你自动生成带详细注释的 `config.toml` 文件,这是现代插件开发的最佳实践。 + ## 📖 概述 这个指南将带你在5分钟内创建你的第一个MaiBot插件。我们将创建一个简单的问候插件,展示插件系统的基本概念。 diff --git a/plugins/example_plugin/plugin.py b/plugins/example_plugin/plugin.py index 481e0b59a..bd46e3121 100644 --- a/plugins/example_plugin/plugin.py +++ b/plugins/example_plugin/plugin.py @@ -31,6 +31,7 @@ from src.plugin_system.base.base_plugin import register_plugin from src.plugin_system.base.base_action import BaseAction from src.plugin_system.base.base_command import BaseCommand from src.plugin_system.base.component_types import ComponentInfo, ActionActivationType, ChatMode +from src.plugin_system.base.config_types import ConfigField from src.common.logger import get_logger logger = get_logger("example_comprehensive") @@ -647,9 +648,85 @@ class ExampleComprehensivePlugin(BasePlugin): enable_plugin = True config_file_name = "config.toml" + # 配置节描述 + config_section_descriptions = { + "plugin": "插件基本信息配置", + "components": "组件启用控制", + "greeting": "智能问候配置", + "helpful": "智能帮助Action配置", + "help": "帮助系统Command配置", + "send": "消息发送命令配置", + "echo": "回声命令配置", + "dice": "骰子命令配置", + "info": "消息信息命令配置", + "logging": "日志记录配置", + } + + # 配置Schema定义 + config_schema = { + "plugin": { + "name": ConfigField(type=str, default="example_plugin", description="插件名称", required=True), + "version": ConfigField(type=str, default="2.0.0", description="插件版本号"), + "enabled": ConfigField(type=bool, default=True, description="是否启用插件"), + "description": ConfigField(type=str, default="综合示例插件,展示新插件系统的完整功能", description="插件描述", required=True) + }, + "components": { + "enable_greeting": ConfigField(type=bool, default=True, description="是否启用'智能问候'Action"), + "enable_helpful": ConfigField(type=bool, default=True, description="是否启用'智能帮助'Action"), + "enable_help": ConfigField(type=bool, default=True, description="是否启用'/help'命令"), + "enable_send": ConfigField(type=bool, default=True, description="是否启用'/send'命令"), + "enable_echo": ConfigField(type=bool, default=True, description="是否启用'/echo'命令"), + "enable_info": ConfigField(type=bool, default=True, description="是否启用'/info'命令"), + "enable_dice": ConfigField(type=bool, default=True, description="是否启用'!dice'命令") + }, + "greeting": { + "template": ConfigField(type=str, default="你好,{username}!欢迎使用MaiBot综合插件系统!", description="问候消息模板"), + "enable_emoji": ConfigField(type=bool, default=True, description="问候时是否附带表情"), + "enable_llm": ConfigField(type=bool, default=False, description="是否使用LLM生成个性化问候语") + }, + "helpful": { + "enable_llm": ConfigField(type=bool, default=False, description="是否使用LLM生成帮助内容"), + "enable_emoji": ConfigField(type=bool, default=True, description="提供帮助时是否附带表情"), + "random_activation_probability": ConfigField(type=float, default=0.15, description="Normal模式下随机触发帮助的概率") + }, + "help": { + "show_extended_help": ConfigField(type=bool, default=True, description="是否显示扩展帮助信息"), + "include_action_info": ConfigField(type=bool, default=True, description="帮助信息中是否包含Action的信息"), + "include_config_info": ConfigField(type=bool, default=True, description="帮助信息中是否包含配置相关信息"), + "enable_llm": ConfigField(type=bool, default=False, description="是否使用LLM生成帮助摘要"), + "enable_emoji": ConfigField(type=bool, default=True, description="帮助信息中是否使用表情符号") + }, + "send": { + "max_message_length": ConfigField(type=int, default=500, description="发送消息的最大长度限制"), + "enable_length_check": ConfigField(type=bool, default=True, description="是否启用消息长度检查"), + "default_platform": ConfigField(type=str, default="qq", description="默认发送平台") + }, + "echo": { + "max_length": ConfigField(type=int, default=200, description="回声消息的最大长度"), + "enable_formatting": ConfigField(type=bool, default=True, description="是否为回声消息添加'🔊 回声: '前缀") + }, + "dice": { + "enable_dice": ConfigField(type=bool, default=True, description="是否启用骰子功能"), + "max_dice_count": ConfigField(type=int, default=10, description="一次最多可以掷的骰子数量") + }, + "info": { + "show_detailed_info": ConfigField(type=bool, default=True, description="是否显示详细信息"), + "include_stream_info": ConfigField(type=bool, default=True, description="是否包含聊天流信息"), + "max_content_preview": ConfigField(type=int, default=100, description="消息内容预览的最大长度") + }, + "logging": { + "level": ConfigField(type=str, default="INFO", description="日志级别", choices=["DEBUG", "INFO", "WARNING", "ERROR"]), + "prefix": ConfigField(type=str, default="[ExampleComprehensive]", description="日志前缀") + } + } + def get_plugin_components(self) -> List[Tuple[ComponentInfo, Type]]: """返回插件包含的组件列表""" + # 从配置动态设置Action参数 + helpful_chance = self.get_config("helpful.random_activation_probability", 0.15) + HelpfulAction.random_activation_probability = helpful_chance + # 从配置获取组件启用状态 enable_greeting = self.get_config("components.enable_greeting", True) enable_helpful = self.get_config("components.enable_helpful", True) diff --git a/src/plugins/built_in/vtb_plugin/plugin.py b/src/plugins/built_in/vtb_plugin/plugin.py index db948750c..881958a14 100644 --- a/src/plugins/built_in/vtb_plugin/plugin.py +++ b/src/plugins/built_in/vtb_plugin/plugin.py @@ -2,6 +2,7 @@ from src.plugin_system.base.base_plugin import BasePlugin, register_plugin from src.plugin_system.base.component_types import ComponentInfo from src.common.logger import get_logger from src.plugin_system.base.base_action import BaseAction, ActionActivationType, ChatMode +from src.plugin_system.base.config_types import ConfigField from typing import Tuple, List, Type logger = get_logger("vtb") @@ -113,9 +114,48 @@ class VTBPlugin(BasePlugin): enable_plugin = True config_file_name = "config.toml" + # 配置节描述 + config_section_descriptions = { + "plugin": "插件基本信息配置", + "components": "组件启用配置", + "vtb_action": "VTB动作专属配置", + "logging": "日志记录配置", + } + + # 配置Schema定义 + config_schema = { + "plugin": { + "name": ConfigField(type=str, default="vtb_plugin", description="插件名称", required=True), + "version": ConfigField(type=str, default="0.1.0", description="插件版本号"), + "enabled": ConfigField(type=bool, default=True, description="是否启用插件"), + "description": ConfigField(type=str, default="虚拟主播情感表达插件", description="插件描述", required=True) + }, + "components": { + "enable_vtb": ConfigField(type=bool, default=True, description="是否启用VTB动作") + }, + "vtb_action": { + "random_activation_probability": ConfigField( + type=float, + default=0.08, + description="Normal模式下,随机触发VTB动作的概率(0.0到1.0)", + example=0.1 + ), + "max_text_length": ConfigField(type=int, default=100, description="用于VTB动作的情感描述文本的最大长度"), + "default_emotion": ConfigField(type=str, default="平静", description="当没有有效输入时,默认表达的情感") + }, + "logging": { + "level": ConfigField(type=str, default="INFO", description="日志级别", choices=["DEBUG", "INFO", "WARNING", "ERROR"]), + "prefix": ConfigField(type=str, default="[VTB]", description="日志记录前缀") + } + } + def get_plugin_components(self) -> List[Tuple[ComponentInfo, Type]]: """返回插件包含的组件列表""" + # 从配置动态设置Action参数 + random_chance = self.get_config("vtb_action.random_activation_probability", 0.08) + VTBAction.random_activation_probability = random_chance + # 从配置获取组件启用状态 enable_vtb = self.get_config("components.enable_vtb", True) components = []