Files
Mofox-Core/docs/plugins/troubleshooting-guide.md
2025-12-17 09:44:51 +08:00

396 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🔧 插件开发故障排除指南
本指南帮助你快速解决 MoFox-Bot 插件开发中的常见问题。
---
## 📋 快速诊断清单
遇到问题时,首先按照以下步骤检查:
1. ✅ 检查日志文件 `logs/app_*.jsonl`
2. ✅ 确认插件已在 `_manifest.json` 中正确配置
3. ✅ 验证你使用的是 `PlusCommand` 而不是 `BaseCommand`
4. ✅ 检查 `execute()` 方法签名是否正确
5. ✅ 确认返回值格式正确
---
## 🔴 严重问题:插件无法加载
### 错误 #1: "未检测到插件"
**症状**
- 插件目录存在,但日志中没有加载信息
- `get_plugin_components()` 返回空列表
**可能原因与解决方案**
#### ❌ 缺少 `@register_plugin` 装饰器
```python
# 错误 - 缺少装饰器
class MyPlugin(BasePlugin): # 不会被检测到
pass
# 正确 - 添加装饰器
@register_plugin # 必须添加!
class MyPlugin(BasePlugin):
pass
```
#### ❌ `plugin.py` 文件不存在或位置错误
```
plugins/
└── my_plugin/
├── _manifest.json ✅
└── plugin.py ✅ 必须在这里
```
#### ❌ `_manifest.json` 格式错误
```json
{
"manifest_version": 1,
"name": "My Plugin",
"version": "1.0.0",
"description": "插件描述",
"author": {
"name": "Your Name"
}
}
```
---
### 错误 #2: "ActionInfo.__init__() missing required argument: 'component_type'"
**症状**
```
TypeError: ActionInfo.__init__() missing 1 required positional argument: 'component_type'
```
**原因**:手动创建 `ActionInfo` 时未指定 `component_type` 参数
**解决方案**
```python
from src.plugin_system import ActionInfo, ComponentType
# ❌ 错误 - 缺少 component_type
action_info = ActionInfo(
name="my_action",
description="我的动作"
)
# ✅ 正确方法 1 - 使用自动生成(推荐)
class MyAction(BaseAction):
action_name = "my_action"
action_description = "我的动作"
def get_plugin_components(self):
return [
(MyAction.get_action_info(), MyAction) # 自动生成,推荐!
]
# ✅ 正确方法 2 - 手动指定 component_type
action_info = ActionInfo(
name="my_action",
description="我的动作",
component_type=ComponentType.ACTION # 必须指定!
)
```
---
## 🟡 命令问题:命令无响应
### 错误 #3: 命令被识别但不执行
**症状**
- 输入 `/mycommand` 后没有任何反应
- 日志显示命令已匹配但未执行
**可能原因与解决方案**
#### ❌ 使用了 `BaseCommand` 而不是 `PlusCommand`
```python
# ❌ 错误 - 使用 BaseCommand
from src.plugin_system import BaseCommand
class MyCommand(BaseCommand): # 不推荐!
command_name = "mycommand"
command_pattern = r"^/mycommand$" # 需要手动写正则
async def execute(self): # 签名错误!
pass
# ✅ 正确 - 使用 PlusCommand
from src.plugin_system import PlusCommand, CommandArgs
class MyCommand(PlusCommand): # 推荐!
command_name = "mycommand"
# 不需要 command_pattern会自动生成
async def execute(self, args: CommandArgs): # 正确签名
await self.send_text("命令执行成功")
return True, "执行了mycommand", True
```
#### ❌ `execute()` 方法签名错误
```python
# ❌ 错误的签名(缺少 args 参数)
async def execute(self) -> Tuple[bool, Optional[str], bool]:
pass
# ❌ 错误的签名(参数类型错误)
async def execute(self, args: list[str]) -> Tuple[bool, Optional[str], bool]:
pass
# ✅ 正确的签名
async def execute(self, args: CommandArgs) -> Tuple[bool, Optional[str], bool]:
await self.send_text("响应用户")
return True, "日志描述", True
```
---
### 错误 #4: 命令发送了消息但用户没收到
**症状**
- 日志显示命令执行成功
- 但用户没有收到任何消息
**原因**:在返回值中返回消息,而不是使用 `self.send_text()`
**解决方案**
```python
# ❌ 错误 - 在返回值中返回消息
async def execute(self, args: CommandArgs):
message = "这是给用户的消息"
return True, message, True # 这不会发送给用户!
# ✅ 正确 - 使用 self.send_text()
async def execute(self, args: CommandArgs):
# 发送消息给用户
await self.send_text("这是给用户的消息")
# 返回日志描述(不是用户消息)
return True, "执行了某个操作", True
```
---
### 错误 #5: "notice处理失败" 或重复消息
**症状**
- 日志中出现 "notice处理失败"
- 用户收到重复的消息
**原因**:同时使用了 `send_api.send_text()` 和返回消息
**解决方案**
```python
# ❌ 错误 - 混用不同的发送方式
from src.plugin_system.apis.chat_api import send_api
async def execute(self, args: CommandArgs):
await send_api.send_text(self.stream_id, "消息1") # 不要这样做
return True, "消息2", True # 也不要返回消息
# ✅ 正确 - 只使用 self.send_text()
async def execute(self, args: CommandArgs):
await self.send_text("这是唯一的消息") # 推荐方式
return True, "日志:执行成功", True # 仅用于日志
```
---
## 🟢 配置问题
### 错误 #6: 配置警告 "配置中不存在字空间或键"
**症状**
```
获取全局配置 plugins.my_plugin 失败: "配置中不存在字空间或键 'plugins'"
```
**这是正常的吗?**
**是的,这是正常行为!** 不需要修复。
**说明**
- 系统首先尝试从全局配置加载:`config/plugins/my_plugin/config.toml`
- 如果不存在,会自动回退到插件本地配置:`plugins/my_plugin/config.toml`
- 这个警告可以安全忽略
**如果你想消除警告**
1.`config/plugins/` 目录创建你的插件配置目录
2. 或者直接忽略 - 使用本地配置完全正常
---
## 🔧 返回值问题
### 错误 #7: 返回值格式错误
**Action 返回值** (2个元素)
```python
async def execute(self) -> Tuple[bool, str]:
await self.send_text("消息")
return True, "日志描述" # 2个元素
```
**Command 返回值** (3个元素)
```python
async def execute(self, args: CommandArgs) -> Tuple[bool, Optional[str], bool]:
await self.send_text("消息")
return True, "日志描述", True # 3个元素增加了拦截标志
```
**对比表格**
| 组件类型 | 返回值 | 元素说明 |
|----------|--------|----------|
| **Action** | `(bool, str)` | (成功标志, 日志描述) |
| **Command** | `(bool, str, bool)` | (成功标志, 日志描述, 拦截标志) |
---
## 🎯 参数解析问题
### 错误 #8: 无法获取命令参数
**症状**
- `args` 为空或不包含预期的参数
**解决方案**
```python
async def execute(self, args: CommandArgs):
# 检查是否有参数
if args.is_empty():
await self.send_text("❌ 缺少参数\n用法: /command <参数>")
return True, "缺少参数", True
# 获取原始参数字符串
raw_input = args.get_raw()
# 获取解析后的参数列表
arg_list = args.get_args()
# 获取第一个参数
first_arg = args.get_first("默认值")
# 获取指定索引的参数
second_arg = args.get_arg(1, "默认值")
# 检查标志
if args.has_flag("--verbose"):
# 处理 --verbose 模式
pass
# 获取标志的值
output = args.get_flag_value("--output", "default.txt")
```
---
## 📝 类型注解问题
### 错误 #9: IDE 报类型错误
**解决方案**:确保使用正确的类型导入
```python
from typing import Tuple, Optional, List, Type
from src.plugin_system import (
BasePlugin,
PlusCommand,
BaseAction,
CommandArgs,
ComponentInfo,
CommandInfo,
ActionInfo,
ComponentType
)
# 正确的类型注解
def get_plugin_components(self) -> List[Tuple[ComponentInfo, Type]]:
return [
(MyCommand.get_command_info(), MyCommand),
(MyAction.get_action_info(), MyAction)
]
```
---
## 🚀 性能问题
### 错误 #10: 插件响应缓慢
**可能原因**
1. **阻塞操作**:在 `execute()` 中使用了同步 I/O
2. **大量数据处理**:在主线程处理大文件或复杂计算
3. **频繁的数据库查询**:每次都查询数据库
**解决方案**
```python
import asyncio
async def execute(self, args: CommandArgs):
# ✅ 使用异步操作
result = await some_async_function()
# ✅ 对于同步操作,使用 asyncio.to_thread
result = await asyncio.to_thread(blocking_function)
# ✅ 批量数据库操作
from src.common.database.optimization.batch_scheduler import get_batch_scheduler
scheduler = get_batch_scheduler()
await scheduler.schedule_batch_insert(Model, data_list)
return True, "执行成功", True
```
---
## 📞 获取帮助
如果以上方案都无法解决你的问题:
1. **查看日志**:检查 `logs/app_*.jsonl` 获取详细错误信息
2. **查阅文档**
- [快速开始指南](./quick-start.md)
- [增强命令指南](./PLUS_COMMAND_GUIDE.md)
- [Action组件指南](./action-components.md)
3. **在线文档**https://mofox-studio.github.io/MoFox-Bot-Docs/
4. **提交 Issue**:在 GitHub 仓库提交详细的问题报告
---
## 🎓 最佳实践速查
| 场景 | 推荐做法 | 避免 |
|------|----------|------|
| 创建命令 | 使用 `PlusCommand` | ❌ 使用 `BaseCommand` |
| 发送消息 | `await self.send_text()` | ❌ 在返回值中返回消息 |
| 注册组件 | 使用 `get_action_info()` | ❌ 手动创建不带 `component_type` 的 Info |
| 参数处理 | 使用 `CommandArgs` 方法 | ❌ 手动解析字符串 |
| 异步操作 | 使用 `async/await` | ❌ 使用同步阻塞操作 |
| 配置读取 | `self.get_config()` | ❌ 硬编码配置值 |
---
**最后更新**2024-12-17
**版本**v1.0.0
有问题欢迎反馈,帮助我们改进这份指南!