fix:修复禁言插件和豆包画图插件
This commit is contained in:
@@ -1,169 +0,0 @@
|
||||
# MaiBot 插件系统 - 重构版
|
||||
|
||||
## 目录结构说明
|
||||
|
||||
经过重构,插件系统现在采用清晰的**系统核心**与**插件内容**分离的架构:
|
||||
|
||||
```
|
||||
src/
|
||||
├── plugin_system/ # 🔧 系统核心 - 插件框架本身
|
||||
│ ├── __init__.py # 统一导出接口
|
||||
│ ├── core/ # 核心管理
|
||||
│ │ ├── plugin_manager.py
|
||||
│ │ ├── component_registry.py
|
||||
│ │ └── __init__.py
|
||||
│ ├── apis/ # API接口
|
||||
│ │ ├── plugin_api.py # 统一API聚合
|
||||
│ │ ├── message_api.py
|
||||
│ │ ├── llm_api.py
|
||||
│ │ ├── database_api.py
|
||||
│ │ ├── config_api.py
|
||||
│ │ ├── utils_api.py
|
||||
│ │ ├── stream_api.py
|
||||
│ │ ├── hearflow_api.py
|
||||
│ │ └── __init__.py
|
||||
│ ├── base/ # 基础类
|
||||
│ │ ├── base_plugin.py
|
||||
│ │ ├── base_action.py
|
||||
│ │ ├── base_command.py
|
||||
│ │ ├── component_types.py
|
||||
│ │ └── __init__.py
|
||||
│ └── registry/ # 注册相关(预留)
|
||||
└── plugins/ # 🔌 插件内容 - 具体的插件实现
|
||||
├── built_in/ # 内置插件
|
||||
│ ├── system_actions/ # 系统内置Action
|
||||
│ └── system_commands/# 系统内置Command
|
||||
└── examples/ # 示例插件
|
||||
└── simple_plugin/
|
||||
├── plugin.py
|
||||
└── config.toml
|
||||
```
|
||||
|
||||
## 架构优势
|
||||
|
||||
### 1. 职责清晰
|
||||
- **`src/plugin_system/`** - 系统提供的框架、API和基础设施
|
||||
- **`src/plugins/`** - 用户开发或使用的具体插件
|
||||
|
||||
### 2. 导入简化
|
||||
```python
|
||||
# 统一导入接口
|
||||
from src.plugin_system import (
|
||||
BasePlugin, register_plugin, BaseAction, BaseCommand,
|
||||
ActionInfo, CommandInfo, PluginAPI
|
||||
)
|
||||
```
|
||||
|
||||
### 3. 模块化设计
|
||||
- 各个子模块都有清晰的职责和接口
|
||||
- 支持按需导入特定功能
|
||||
- 便于维护和扩展
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 创建简单插件
|
||||
|
||||
```python
|
||||
from src.plugin_system import BasePlugin, register_plugin, BaseAction, ActionInfo
|
||||
|
||||
class MyAction(BaseAction):
|
||||
async def execute(self):
|
||||
return True, "Hello from my plugin!"
|
||||
|
||||
@register_plugin
|
||||
class MyPlugin(BasePlugin):
|
||||
plugin_name = "my_plugin"
|
||||
plugin_description = "我的第一个插件"
|
||||
|
||||
def get_plugin_components(self):
|
||||
return [(
|
||||
ActionInfo(name="my_action", description="我的动作"),
|
||||
MyAction
|
||||
)]
|
||||
```
|
||||
|
||||
### 使用系统API
|
||||
|
||||
```python
|
||||
class MyAction(BaseAction):
|
||||
async def execute(self):
|
||||
# 发送消息
|
||||
await self.api.send_text_to_group(
|
||||
self.api.get_service("chat_stream"),
|
||||
"Hello World!"
|
||||
)
|
||||
|
||||
# 数据库操作
|
||||
data = await self.api.db_get("table", "key")
|
||||
|
||||
# LLM调用
|
||||
response = await self.api.llm_text_request("你好")
|
||||
|
||||
return True, response
|
||||
```
|
||||
|
||||
## 兼容性迁移
|
||||
|
||||
### 现有Action迁移
|
||||
```python
|
||||
# 旧方式
|
||||
from src.chat.actions.base_action import BaseAction, register_action
|
||||
|
||||
# 新方式
|
||||
from src.plugin_system import BaseAction, register_plugin
|
||||
from src.plugin_system.base.component_types import ActionInfo
|
||||
|
||||
# 将Action封装到Plugin中
|
||||
@register_plugin
|
||||
class MyActionPlugin(BasePlugin):
|
||||
plugin_name = "my_action_plugin"
|
||||
|
||||
def get_plugin_components(self):
|
||||
return [(ActionInfo(...), MyAction)]
|
||||
```
|
||||
|
||||
### 现有Command迁移
|
||||
```python
|
||||
# 旧方式
|
||||
from src.chat.command.command_handler import BaseCommand, register_command
|
||||
|
||||
# 新方式
|
||||
from src.plugin_system import BaseCommand, register_plugin
|
||||
from src.plugin_system.base.component_types import CommandInfo
|
||||
|
||||
# 将Command封装到Plugin中
|
||||
@register_plugin
|
||||
class MyCommandPlugin(BasePlugin):
|
||||
plugin_name = "my_command_plugin"
|
||||
|
||||
def get_plugin_components(self):
|
||||
return [(CommandInfo(...), MyCommand)]
|
||||
```
|
||||
|
||||
## 扩展指南
|
||||
|
||||
### 添加新的组件类型
|
||||
1. 在 `component_types.py` 中定义新的组件类型
|
||||
2. 在 `component_registry.py` 中添加对应的注册逻辑
|
||||
3. 创建对应的基类
|
||||
|
||||
### 添加新的API
|
||||
1. 在 `apis/` 目录下创建新的API模块
|
||||
2. 在 `plugin_api.py` 中集成新API
|
||||
3. 更新 `__init__.py` 导出接口
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **单一插件包含相关组件** - 一个插件可以包含多个相关的Action和Command
|
||||
2. **使用配置文件** - 通过TOML配置文件管理插件行为
|
||||
3. **合理的组件命名** - 使用描述性的组件名称
|
||||
4. **充分的错误处理** - 在组件中妥善处理异常
|
||||
5. **详细的文档** - 为插件和组件编写清晰的文档
|
||||
|
||||
## 内置插件规划
|
||||
|
||||
- **系统核心插件** - 将现有的内置Action/Command迁移为系统插件
|
||||
- **工具插件** - 常用的工具和实用功能
|
||||
- **示例插件** - 帮助开发者学习的示例代码
|
||||
|
||||
这个重构保持了向后兼容性,同时提供了更清晰、更易维护的架构。
|
||||
@@ -1,172 +0,0 @@
|
||||
# API使用指南
|
||||
|
||||
插件系统提供了多种API访问方式,根据使用场景选择合适的API类。
|
||||
|
||||
## 📊 API分类
|
||||
|
||||
### 🔗 ActionAPI - 需要Action依赖
|
||||
**适用场景**:在Action组件中使用,需要访问聊天上下文
|
||||
```python
|
||||
from src.plugin_system.apis import ActionAPI
|
||||
|
||||
class MyAction(BaseAction):
|
||||
async def execute(self):
|
||||
# Action已内置ActionAPI,可以直接使用
|
||||
await self.api.send_message("text", "Hello")
|
||||
await self.api.store_action_info(action_prompt_display="执行了动作")
|
||||
```
|
||||
|
||||
**包含功能**:
|
||||
- ✅ 发送消息(需要chat_stream、expressor等)
|
||||
- ✅ 数据库操作(需要thinking_id、action_data等)
|
||||
|
||||
### 🔧 IndependentAPI - 独立功能
|
||||
**适用场景**:在Command组件中使用,或需要独立工具功能
|
||||
```python
|
||||
from src.plugin_system.apis import IndependentAPI
|
||||
|
||||
class MyCommand(BaseCommand):
|
||||
async def execute(self):
|
||||
# 创建独立API实例
|
||||
api = IndependentAPI(log_prefix="[MyCommand]")
|
||||
|
||||
# 使用独立功能
|
||||
models = api.get_available_models()
|
||||
config = api.get_global_config("some_key")
|
||||
timestamp = api.get_timestamp()
|
||||
```
|
||||
|
||||
**包含功能**:
|
||||
- ✅ LLM模型调用
|
||||
- ✅ 配置读取
|
||||
- ✅ 工具函数(时间、文件、ID生成等)
|
||||
- ✅ 聊天流查询
|
||||
- ✅ 心流状态控制
|
||||
|
||||
### ⚡ StaticAPI - 静态访问
|
||||
**适用场景**:简单工具调用,不需要实例化
|
||||
```python
|
||||
from src.plugin_system.apis import StaticAPI
|
||||
|
||||
# 直接调用静态方法
|
||||
models = StaticAPI.get_available_models()
|
||||
config = StaticAPI.get_global_config("bot.nickname")
|
||||
timestamp = StaticAPI.get_timestamp()
|
||||
unique_id = StaticAPI.generate_unique_id()
|
||||
|
||||
# 异步方法
|
||||
result = await StaticAPI.generate_with_model(prompt, model_config)
|
||||
chat_stream = StaticAPI.get_chat_stream_by_group_id("123456")
|
||||
```
|
||||
|
||||
## 🎯 使用建议
|
||||
|
||||
### Action组件开发
|
||||
```python
|
||||
class MyAction(BaseAction):
|
||||
# 激活条件直接在类中定义
|
||||
focus_activation_type = ActionActivationType.KEYWORD
|
||||
activation_keywords = ["测试"]
|
||||
|
||||
async def execute(self):
|
||||
# 使用内置的ActionAPI
|
||||
success = await self.api.send_message("text", "处理中...")
|
||||
|
||||
# 存储执行记录
|
||||
await self.api.store_action_info(
|
||||
action_prompt_display="执行了测试动作"
|
||||
)
|
||||
|
||||
return True, "完成"
|
||||
```
|
||||
|
||||
### Command组件开发
|
||||
```python
|
||||
class MyCommand(BaseCommand):
|
||||
# 命令模式直接在类中定义
|
||||
command_pattern = r"^/test\s+(?P<param>\w+)$"
|
||||
command_help = "测试命令"
|
||||
|
||||
async def execute(self):
|
||||
# 使用独立API
|
||||
api = IndependentAPI(log_prefix="[TestCommand]")
|
||||
|
||||
# 获取配置
|
||||
max_length = api.get_global_config("test.max_length", 100)
|
||||
|
||||
# 生成内容(如果需要)
|
||||
if api.get_available_models():
|
||||
models = api.get_available_models()
|
||||
first_model = list(models.values())[0]
|
||||
|
||||
success, response, _, _ = await api.generate_with_model(
|
||||
"生成测试回复", first_model
|
||||
)
|
||||
|
||||
if success:
|
||||
await self.send_reply(response)
|
||||
```
|
||||
|
||||
### 独立工具使用
|
||||
```python
|
||||
# 不在插件环境中的独立使用
|
||||
from src.plugin_system.apis import StaticAPI
|
||||
|
||||
def some_utility_function():
|
||||
# 获取配置
|
||||
bot_name = StaticAPI.get_global_config("bot.nickname", "Bot")
|
||||
|
||||
# 生成ID
|
||||
request_id = StaticAPI.generate_unique_id()
|
||||
|
||||
# 格式化时间
|
||||
current_time = StaticAPI.format_time()
|
||||
|
||||
return f"{bot_name}_{request_id}_{current_time}"
|
||||
```
|
||||
|
||||
## 🔄 迁移指南
|
||||
|
||||
### 从原PluginAPI迁移
|
||||
|
||||
**原来的用法**:
|
||||
```python
|
||||
# 原来需要导入完整PluginAPI
|
||||
from src.plugin_system.apis import PluginAPI
|
||||
|
||||
api = PluginAPI(chat_stream=..., expressor=...)
|
||||
await api.send_message("text", "Hello")
|
||||
config = api.get_global_config("key")
|
||||
```
|
||||
|
||||
**新的用法**:
|
||||
```python
|
||||
# 方式1:继续使用原PluginAPI(不变)
|
||||
from src.plugin_system.apis import PluginAPI
|
||||
|
||||
# 方式2:使用分类API(推荐)
|
||||
from src.plugin_system.apis import ActionAPI, IndependentAPI
|
||||
|
||||
# Action相关功能
|
||||
action_api = ActionAPI(chat_stream=..., expressor=...)
|
||||
await action_api.send_message("text", "Hello")
|
||||
|
||||
# 独立功能
|
||||
config = IndependentAPI().get_global_config("key")
|
||||
# 或者
|
||||
config = StaticAPI.get_global_config("key")
|
||||
```
|
||||
|
||||
## 📋 API对照表
|
||||
|
||||
| 功能类别 | 原PluginAPI | ActionAPI | IndependentAPI | StaticAPI |
|
||||
|---------|-------------|-----------|----------------|-----------|
|
||||
| 发送消息 | ✅ | ✅ | ❌ | ❌ |
|
||||
| 数据库操作 | ✅ | ✅ | ❌ | ❌ |
|
||||
| LLM调用 | ✅ | ❌ | ✅ | ✅ |
|
||||
| 配置读取 | ✅ | ❌ | ✅ | ✅ |
|
||||
| 工具函数 | ✅ | ❌ | ✅ | ✅ |
|
||||
| 聊天流查询 | ✅ | ❌ | ✅ | ✅ |
|
||||
| 心流控制 | ✅ | ❌ | ✅ | ✅ |
|
||||
|
||||
这样的分类让插件开发者可以更明确地知道需要什么样的API,避免不必要的依赖注入。
|
||||
@@ -166,14 +166,13 @@ class BaseAction(ABC):
|
||||
if not chat_stream:
|
||||
logger.error(f"{self.log_prefix} 没有可用的聊天流发送命令")
|
||||
return False
|
||||
|
||||
command_content = str(command_data)
|
||||
|
||||
|
||||
if chat_stream.group_info:
|
||||
# 群聊
|
||||
success = await self.api.send_message_to_target(
|
||||
message_type="command",
|
||||
content=command_content,
|
||||
content=command_data,
|
||||
platform=chat_stream.platform,
|
||||
target_id=str(chat_stream.group_info.group_id),
|
||||
is_group=True,
|
||||
@@ -183,7 +182,7 @@ class BaseAction(ABC):
|
||||
# 私聊
|
||||
success = await self.api.send_message_to_target(
|
||||
message_type="command",
|
||||
content=command_content,
|
||||
content=command_data,
|
||||
platform=chat_stream.platform,
|
||||
target_id=str(chat_stream.user_info.user_id),
|
||||
is_group=False,
|
||||
@@ -213,7 +212,7 @@ class BaseAction(ABC):
|
||||
"""
|
||||
try:
|
||||
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
|
||||
from src.chat.message_receive.message import create_empty_anchor_message
|
||||
from src.chat.focus_chat.hfc_utils import create_empty_anchor_message
|
||||
|
||||
# 获取服务
|
||||
expressor = self.api.get_service("expressor")
|
||||
@@ -281,7 +280,7 @@ class BaseAction(ABC):
|
||||
"""
|
||||
try:
|
||||
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
|
||||
from src.chat.message_receive.message import create_empty_anchor_message
|
||||
from src.chat.focus_chat.hfc_utils import create_empty_anchor_message
|
||||
|
||||
# 获取服务
|
||||
replyer = self.api.get_service("replyer")
|
||||
|
||||
@@ -102,7 +102,7 @@ class BaseCommand(ABC):
|
||||
|
||||
# 使用send_message_to_target方法发送命令
|
||||
chat_stream = self.message.chat_stream
|
||||
command_content = str(command_data)
|
||||
command_content = command_data
|
||||
|
||||
if chat_stream.group_info:
|
||||
# 群聊
|
||||
|
||||
@@ -167,16 +167,26 @@ class BasePlugin(ABC):
|
||||
return True
|
||||
|
||||
def get_config(self, key: str, default: Any = None) -> Any:
|
||||
"""获取插件配置值
|
||||
"""获取插件配置值,支持嵌套键访问
|
||||
|
||||
Args:
|
||||
key: 配置键名
|
||||
key: 配置键名,支持嵌套访问如 "section.subsection.key"
|
||||
default: 默认值
|
||||
|
||||
Returns:
|
||||
Any: 配置值或默认值
|
||||
"""
|
||||
return self.config.get(key, default)
|
||||
# 支持嵌套键访问
|
||||
keys = key.split('.')
|
||||
current = self.config
|
||||
|
||||
for k in keys:
|
||||
if isinstance(current, dict) and k in current:
|
||||
current = current[k]
|
||||
else:
|
||||
return default
|
||||
|
||||
return current
|
||||
|
||||
|
||||
def register_plugin(cls):
|
||||
|
||||
Reference in New Issue
Block a user