fix:修复禁言插件和豆包画图插件

This commit is contained in:
SengokuCola
2025-06-11 00:18:48 +08:00
parent 6455dab5b8
commit 22aae4d1cd
17 changed files with 271 additions and 685 deletions

View File

@@ -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迁移为系统插件
- **工具插件** - 常用的工具和实用功能
- **示例插件** - 帮助开发者学习的示例代码
这个重构保持了向后兼容性,同时提供了更清晰、更易维护的架构。

View File

@@ -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避免不必要的依赖注入。

View File

@@ -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")

View File

@@ -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:
# 群聊

View File

@@ -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):