add:新增文档变更

This commit is contained in:
SengokuCola
2025-06-20 01:41:23 +08:00
parent bb9c914f80
commit 3fcebf6d4f
10 changed files with 590 additions and 673 deletions

View File

@@ -128,146 +128,21 @@ action_require = [
associated_types = ["text", "emoji", "image"] associated_types = ["text", "emoji", "image"]
``` ```
### 4. 新API导入必须项 ### 4. 执行方法必须项
使用新插件系统时必须导入所需的API模块
```python
# 导入新API模块
from src.plugin_system.apis import generator_api, send_api, emoji_api
# 如果需要使用其他API
from src.plugin_system.apis import llm_api, database_api, message_api
```
### 5. 动作记录必须项
每个 Action 在执行完成后,**必须**使用 `store_action_info` 记录动作信息:
```python ```python
async def execute(self) -> Tuple[bool, str]: async def execute(self) -> Tuple[bool, str]:
# ... 执行动作的代码 ... """
执行Action的主要逻辑
if success:
# 存储动作信息 - 使用新API格式
await self.store_action_info(
action_build_into_prompt=True, # 让麦麦知道这个动作
action_prompt_display=f"执行了xxx动作参数{param}", # 动作描述
action_done=True, # 动作是否完成
)
return True, "动作执行成功"
```
> ⚠️ **重要提示**新API格式中不再需要手动传递 `thinking_id` 等参数BaseAction会自动处理。
## 🚀 新API使用指南
### 📨 消息发送API
新的消息发送API更加简洁自动处理群聊/私聊逻辑:
```python
class MessageAction(BaseAction):
async def execute(self) -> Tuple[bool, str]:
# 发送文本消息 - 自动判断群聊/私聊
await self.send_text("Hello World!")
# 发送表情包
emoji_base64 = await emoji_api.get_by_description("开心")
if emoji_base64:
await self.send_emoji(emoji_base64)
# 发送图片
await self.send_image(image_base64)
# 发送自定义类型消息
await self.send_custom("video", video_data, typing=True)
return True, "消息发送完成"
```
### 🤖 智能生成API (replyer_1)
使用replyer_1生成个性化内容
```python
class SmartReplyAction(BaseAction):
async def execute(self) -> Tuple[bool, str]:
# 构建生成参数
reply_data = {
"text": "请生成一个友好的回复",
"style": "casual",
"topic": "日常聊天",
"replyer_name": "replyer_1" # 指定使用replyer_1
}
# 使用generator_api生成回复
success, reply_set = await generator_api.generate_reply(
chat_stream=self.chat_stream,
action_data=reply_data,
platform=self.platform,
chat_id=self.chat_id,
is_group=self.is_group
)
if success and reply_set:
# 提取并发送文本回复
for reply_type, reply_content in reply_set:
if reply_type == "text":
await self.send_text(reply_content)
elif reply_type == "emoji":
await self.send_emoji(reply_content)
# 记录动作 Returns:
await self.store_action_info( Tuple[bool, str]: (是否成功, 执行结果描述)
action_build_into_prompt=True, """
action_prompt_display=f"使用replyer_1生成了智能回复", # 执行动作的代码
action_done=True success = True
) message = "动作执行成功"
return True, "智能回复生成成功" return success, message
else:
return False, "回复生成失败"
```
### ⚙️ 配置访问API
使用便捷的配置访问方法:
```python
class ConfigurableAction(BaseAction):
async def execute(self) -> Tuple[bool, str]:
# 获取插件配置 - 支持嵌套键访问
enable_feature = self.get_config("features.enable_smart_mode", False)
max_length = self.get_config("limits.max_text_length", 200)
style = self.get_config("behavior.response_style", "friendly")
if enable_feature:
# 启用高级功能
pass
return True, "配置获取成功"
```
### 📊 数据库API
使用新的数据库API存储和查询数据
```python
class DataAction(BaseAction):
async def execute(self) -> Tuple[bool, str]:
# 使用database_api
from src.plugin_system.apis import database_api
# 存储数据
await database_api.store_action_info(
chat_stream=self.chat_stream,
action_name=self.action_name,
action_data=self.action_data,
# ... 其他参数
)
return True, "数据存储完成"
``` ```
## 🔧 激活类型详解 ## 🔧 激活类型详解
@@ -286,28 +161,8 @@ class GreetingAction(BaseAction):
keyword_case_sensitive = False # 不区分大小写 keyword_case_sensitive = False # 不区分大小写
async def execute(self) -> Tuple[bool, str]: async def execute(self) -> Tuple[bool, str]:
# 可选使用replyer_1生成个性化问候 # 执行问候逻辑
if self.get_config("greeting.use_smart_reply", False): return True, "发送了问候"
greeting_data = {
"text": "生成一个友好的问候语",
"replyer_name": "replyer_1"
}
success, reply_set = await generator_api.generate_reply(
chat_stream=self.chat_stream,
action_data=greeting_data
)
if success:
for reply_type, content in reply_set:
if reply_type == "text":
await self.send_text(content)
break
return True, "发送智能问候"
# 传统问候方式
await self.send_text("你好!很高兴见到你!")
return True, "发送问候"
``` ```
### LLM_JUDGE激活 ### LLM_JUDGE激活
@@ -330,26 +185,8 @@ class HelpAction(BaseAction):
""" """
async def execute(self) -> Tuple[bool, str]: async def execute(self) -> Tuple[bool, str]:
# 使用replyer_1生成帮助内容 # 执行帮助逻辑
help_data = { return True, "提供了帮助"
"text": "用户需要帮助,请提供适当的帮助信息",
"help_type": self.action_data.get("help_type", "general"),
"replyer_name": "replyer_1"
}
success, reply_set = await generator_api.generate_reply(
chat_stream=self.chat_stream,
action_data=help_data
)
if success:
for reply_type, content in reply_set:
if reply_type == "text":
await self.send_text(content)
return True, "提供了帮助"
else:
await self.send_text("我来帮助你!有什么问题吗?")
return True, "提供了默认帮助"
``` ```
### RANDOM激活 ### RANDOM激活
@@ -365,11 +202,181 @@ class SurpriseAction(BaseAction):
random_activation_probability = 0.1 # 10%概率激活 random_activation_probability = 0.1 # 10%概率激活
async def execute(self) -> Tuple[bool, str]: async def execute(self) -> Tuple[bool, str]:
import random # 执行惊喜动作
return True, "发送了惊喜内容"
surprises = ["🎉", "✨", "🌟", "💝", "🎈"]
selected = random.choice(surprises)
await self.send_emoji(selected)
return True, f"发送了惊喜表情: {selected}"
``` ```
### ALWAYS激活
永远激活,常用于核心功能:
```python
class CoreAction(BaseAction):
focus_activation_type = ActionActivationType.ALWAYS
normal_activation_type = ActionActivationType.ALWAYS
async def execute(self) -> Tuple[bool, str]:
# 执行核心功能
return True, "执行了核心功能"
```
### NEVER激活
从不激活,用于临时禁用:
```python
class DisabledAction(BaseAction):
focus_activation_type = ActionActivationType.NEVER
normal_activation_type = ActionActivationType.NEVER
async def execute(self) -> Tuple[bool, str]:
# 这个方法不会被调用
return False, "已禁用"
```
## 📚 BaseAction内置属性和方法
### 内置属性
```python
class MyAction(BaseAction):
def __init__(self):
# 消息相关属性
self.message # 当前消息对象
self.chat_stream # 聊天流对象
self.user_id # 用户ID
self.user_nickname # 用户昵称
self.platform # 平台类型 (qq, telegram等)
self.chat_id # 聊天ID
self.is_group # 是否群聊
# Action相关属性
self.action_data # Action执行时的数据
self.thinking_id # 思考ID
self.matched_groups # 匹配到的组(如果有正则匹配)
```
### 内置方法
```python
class MyAction(BaseAction):
# 配置相关
def get_config(self, key: str, default=None):
"""获取配置值"""
pass
# 消息发送相关
async def send_text(self, text: str):
"""发送文本消息"""
pass
async def send_emoji(self, emoji_base64: str):
"""发送表情包"""
pass
async def send_image(self, image_base64: str):
"""发送图片"""
pass
# 动作记录相关
async def store_action_info(self, **kwargs):
"""记录动作信息"""
pass
```
## 🎯 完整Action示例
```python
from src.plugin_system import BaseAction, ActionActivationType, ChatMode
from typing import Tuple
class ExampleAction(BaseAction):
"""示例Action - 展示完整的Action结构"""
# === 激活控制 ===
focus_activation_type = ActionActivationType.LLM_JUDGE
normal_activation_type = ActionActivationType.KEYWORD
mode_enable = ChatMode.ALL
parallel_action = False
# 关键词激活配置
activation_keywords = ["示例", "测试", "example"]
keyword_case_sensitive = False
# LLM判断提示词
llm_judge_prompt = "当用户需要示例或测试功能时激活"
# 随机激活概率如果使用RANDOM类型
random_activation_probability = 0.2
# === 基本信息 ===
action_name = "example_action"
action_description = "这是一个示例Action用于演示Action的完整结构"
# === 功能定义 ===
action_parameters = {
"content": "要处理的内容",
"type": "处理类型",
"options": "可选配置"
}
action_require = [
"用户需要示例功能时使用",
"适合用于测试和演示",
"不要在正式对话中频繁使用"
]
associated_types = ["text", "emoji"]
async def execute(self) -> Tuple[bool, str]:
"""执行示例Action"""
try:
# 获取Action参数
content = self.action_data.get("content", "默认内容")
action_type = self.action_data.get("type", "default")
# 获取配置
enable_feature = self.get_config("example.enable_advanced", False)
max_length = self.get_config("example.max_length", 100)
# 执行具体逻辑
if action_type == "greeting":
await self.send_text(f"你好!这是示例内容:{content}")
elif action_type == "info":
await self.send_text(f"信息:{content[:max_length]}")
else:
await self.send_text("执行了示例Action")
# 记录动作信息
await self.store_action_info(
action_build_into_prompt=True,
action_prompt_display=f"执行了示例动作:{action_type}",
action_done=True
)
return True, f"示例Action执行成功类型{action_type}"
except Exception as e:
return False, f"执行失败:{str(e)}"
```
## 🎯 最佳实践
### 1. Action设计原则
- **单一职责**每个Action只负责一个明确的功能
- **智能激活**:合理选择激活类型,避免过度激活
- **清晰描述**:提供准确的`action_require`帮助LLM决策
- **错误处理**:妥善处理执行过程中的异常情况
### 2. 性能优化
- **激活控制**使用合适的激活类型减少不必要的LLM调用
- **并行执行**:谨慎设置`parallel_action`,避免冲突
- **资源管理**:及时释放占用的资源
### 3. 调试技巧
- **日志记录**:在关键位置添加日志
- **参数验证**:检查`action_data`的有效性
- **配置测试**:测试不同配置下的行为

View File

@@ -1,398 +1,311 @@
# 📡 消息API # 消息API
## 📖 概述 > 消息API提供了强大的消息查询、计数和格式化功能让你轻松处理聊天消息数据。
消息API提供了发送各种类型消息的接口支持文本、表情、图片等多种消息类型。新版API格式更加简洁直观自动处理群聊/私聊判断。 ## 导入方式
## 🔄 基础消息发送
### 发送文本消息
```python ```python
# 新API格式 - 自动判断群聊/私聊 from src.plugin_system.apis import message_api
await self.send_text("这是一条文本消息")
# 发送多行文本
message = """
这是第一行
这是第二行
这是第三行
"""
await self.send_text(message.strip())
``` ```
### 发送表情消息 ## 功能概述
消息API主要提供三大类功能
- **消息查询** - 按时间、聊天、用户等条件查询消息
- **消息计数** - 统计新消息数量
- **消息格式化** - 将消息转换为可读格式
---
## 消息查询API
### 按时间查询消息
#### `get_messages_by_time(start_time, end_time, limit=0, limit_mode="latest")`
获取指定时间范围内的消息
**参数:**
- `start_time` (float): 开始时间戳
- `end_time` (float): 结束时间戳
- `limit` (int): 限制返回消息数量0为不限制
- `limit_mode` (str): 限制模式,`"earliest"`获取最早记录,`"latest"`获取最新记录
**返回:** `List[Dict[str, Any]]` - 消息列表
**示例:**
```python ```python
# 新API格式 - 发送表情 import time
await self.send_emoji("😊")
await self.send_emoji("🎉") # 获取最近24小时的消息
await self.send_emoji("👋") now = time.time()
yesterday = now - 24 * 3600
messages = message_api.get_messages_by_time(yesterday, now, limit=50)
``` ```
### 发送特定类型消息 ### 按聊天查询消息
#### `get_messages_by_time_in_chat(chat_id, start_time, end_time, limit=0, limit_mode="latest")`
获取指定聊天中指定时间范围内的消息
**参数:**
- `chat_id` (str): 聊天ID
- 其他参数同上
**示例:**
```python ```python
# 发送图片 # 获取某个群聊最近的100条消息
await self.send_type("image", "https://example.com/image.jpg") messages = message_api.get_messages_by_time_in_chat(
chat_id="123456789",
# 发送音频 start_time=yesterday,
await self.send_type("audio", "audio_file_path") end_time=now,
limit=100
# 发送视频
await self.send_type("video", "video_file_path")
# 发送文件
await self.send_type("file", "file_path")
```
## 🎯 跨目标消息发送
### 使用send_api模块发送消息
```python
# 导入send_api
from src.plugin_system.apis import send_api
# 向指定群聊发送文本消息
success = await send_api.text_to_group(
text="这是发送到群聊的消息",
group_id="123456789",
platform="qq"
)
# 向指定用户发送私聊消息
success = await send_api.text_to_user(
text="这是私聊消息",
user_id="987654321",
platform="qq"
)
# 向指定群聊发送表情
success = await send_api.emoji_to_group(
emoji="😊",
group_id="123456789",
platform="qq"
)
# 向指定用户发送表情
success = await send_api.emoji_to_user(
emoji="🎉",
user_id="987654321",
platform="qq"
) )
``` ```
### 通用目标消息发送 #### `get_messages_by_time_in_chat_inclusive(chat_id, start_time, end_time, limit=0, limit_mode="latest")`
获取指定聊天中指定时间范围内的消息(包含边界时间点)
`get_messages_by_time_in_chat` 类似,但包含边界时间戳的消息。
#### `get_recent_messages(chat_id, hours=24.0, limit=100, limit_mode="latest")`
获取指定聊天中最近一段时间的消息(便捷方法)
**参数:**
- `chat_id` (str): 聊天ID
- `hours` (float): 最近多少小时默认24小时
- `limit` (int): 限制返回消息数量默认100条
- `limit_mode` (str): 限制模式
**示例:**
```python ```python
# 向任意目标发送任意类型消息 # 获取最近6小时的消息
success = await send_api.message_to_target( recent_messages = message_api.get_recent_messages(
message_type="text", # 消息类型 chat_id="123456789",
content="消息内容", # 消息内容 hours=6.0,
platform="qq", # 平台 limit=50
target_id="123456789", # 目标ID
is_group=True, # 是否为群聊
display_message="显示消息" # 可选:显示消息
) )
``` ```
## 📨 消息类型支持 ### 按用户查询消息
### 支持的消息类型 #### `get_messages_by_time_in_chat_for_users(chat_id, start_time, end_time, person_ids, limit=0, limit_mode="latest")`
| 类型 | 说明 | 新API方法 | send_api方法 | 获取指定聊天中指定用户在指定时间范围内的消息
|-----|------|----------|-------------|
| `text` | 普通文本消息 | `await self.send_text()` | `await send_api.text_to_group()` |
| `emoji` | 表情消息 | `await self.send_emoji()` | `await send_api.emoji_to_group()` |
| `image` | 图片消息 | `await self.send_type("image", url)` | `await send_api.message_to_target()` |
| `audio` | 音频消息 | `await self.send_type("audio", path)` | `await send_api.message_to_target()` |
| `video` | 视频消息 | `await self.send_type("video", path)` | `await send_api.message_to_target()` |
| `file` | 文件消息 | `await self.send_type("file", path)` | `await send_api.message_to_target()` |
### 新API格式示例 **参数:**
- `chat_id` (str): 聊天ID
- `start_time` (float): 开始时间戳
- `end_time` (float): 结束时间戳
- `person_ids` (list): 用户ID列表
- `limit` (int): 限制返回消息数量
- `limit_mode` (str): 限制模式
**示例:**
```python ```python
class ExampleAction(BaseAction): # 获取特定用户的消息
async def execute(self) -> Tuple[bool, str]: user_messages = message_api.get_messages_by_time_in_chat_for_users(
# 文本消息 - 最常用 chat_id="123456789",
await self.send_text("普通文本消息") start_time=yesterday,
end_time=now,
# 表情消息 - 直接方法 person_ids=["user1", "user2"]
await self.send_emoji("🎉") )
# 图片消息
await self.send_type("image", "/path/to/image.jpg")
# 音频消息
await self.send_type("audio", "/path/to/audio.mp3")
# 文件消息
await self.send_type("file", "/path/to/document.pdf")
return True, "发送了多种类型的消息"
``` ```
## 🔍 消息信息获取 #### `get_messages_by_time_for_users(start_time, end_time, person_ids, limit=0, limit_mode="latest")`
### 获取当前消息信 获取指定用户在所有聊天中指定时间范围内的消
### 其他查询方法
#### `get_random_chat_messages(start_time, end_time, limit=0, limit_mode="latest")`
随机选择一个聊天,返回该聊天在指定时间范围内的消息
#### `get_messages_before_time(timestamp, limit=0)`
获取指定时间戳之前的消息
#### `get_messages_before_time_in_chat(chat_id, timestamp, limit=0)`
获取指定聊天中指定时间戳之前的消息
#### `get_messages_before_time_for_users(timestamp, person_ids, limit=0)`
获取指定用户在指定时间戳之前的消息
---
## 消息计数API
### `count_new_messages(chat_id, start_time=0.0, end_time=None)`
计算指定聊天中从开始时间到结束时间的新消息数量
**参数:**
- `chat_id` (str): 聊天ID
- `start_time` (float): 开始时间戳
- `end_time` (float): 结束时间戳如果为None则使用当前时间
**返回:** `int` - 新消息数量
**示例:**
```python ```python
# 新API格式 - 直接属性访问 # 计算最近1小时的新消息数
class ExampleCommand(BaseCommand): import time
async def execute(self) -> Tuple[bool, str]: now = time.time()
# 用户信息 hour_ago = now - 3600
user_id = self.user_id new_count = message_api.count_new_messages("123456789", hour_ago, now)
user_nickname = self.user_nickname print(f"最近1小时有{new_count}条新消息")
# 聊天信息
is_group_chat = self.is_group
chat_id = self.chat_id
platform = self.platform
# 消息内容
message_text = self.message.processed_plain_text
# 构建信息显示
info = f"""
👤 用户: {user_nickname}({user_id})
💬 类型: {'群聊' if is_group_chat else '私聊'}
📱 平台: {platform}
📝 内容: {message_text}
""".strip()
await self.send_text(info)
return True, "显示了消息信息"
``` ```
### 获取群聊信息(如果适用) ### `count_new_messages_for_users(chat_id, start_time, end_time, person_ids)`
计算指定聊天中指定用户从开始时间到结束时间的新消息数量
---
## 消息格式化API
### `build_readable_messages_to_str(messages, **options)`
将消息列表构建成可读的字符串
**参数:**
- `messages` (List[Dict[str, Any]]): 消息列表
- `replace_bot_name` (bool): 是否将机器人的名称替换为"你"默认True
- `merge_messages` (bool): 是否合并连续消息默认False
- `timestamp_mode` (str): 时间戳显示模式,`"relative"``"absolute"`,默认`"relative"`
- `read_mark` (float): 已读标记时间戳用于分割已读和未读消息默认0.0
- `truncate` (bool): 是否截断长消息默认False
- `show_actions` (bool): 是否显示动作记录默认False
**返回:** `str` - 格式化后的可读字符串
**示例:**
```python ```python
# 在Action或Command中检查群聊信息 # 获取消息并格式化为可读文本
if self.is_group: messages = message_api.get_recent_messages("123456789", hours=2)
group_info = self.message.message_info.group_info readable_text = message_api.build_readable_messages_to_str(
if group_info: messages,
group_id = group_info.group_id replace_bot_name=True,
group_name = getattr(group_info, 'group_name', '未知群聊') merge_messages=True,
timestamp_mode="relative"
await self.send_text(f"当前群聊: {group_name}({group_id})") )
else: print(readable_text)
await self.send_text("当前是私聊对话")
``` ```
## 🌐 平台支持 ### `build_readable_messages_with_details(messages, **options)` 异步
### 支持的平台 将消息列表构建成可读的字符串,并返回详细信息
| 平台 | 标识 | 说明 | **参数:**`build_readable_messages_to_str` 类似,但不包含 `read_mark``show_actions`
|-----|------|------|
| QQ | `qq` | QQ聊天平台 |
| 微信 | `wechat` | 微信聊天平台 |
| Discord | `discord` | Discord聊天平台 |
### 平台适配示例 **返回:** `Tuple[str, List[Tuple[float, str, str]]]` - 格式化字符串和详细信息元组列表(时间戳, 昵称, 内容)
**示例:**
```python ```python
class PlatformAdaptiveAction(BaseAction): # 异步获取详细格式化信息
async def execute(self) -> Tuple[bool, str]: readable_text, details = await message_api.build_readable_messages_with_details(
# 获取当前平台 messages,
current_platform = self.platform timestamp_mode="absolute"
)
# 根据平台调整消息格式
if current_platform == "qq": for timestamp, nickname, content in details:
await self.send_text("[QQ] 这是QQ平台的消息") print(f"{timestamp}: {nickname} 说: {content}")
await self.send_emoji("🐧") # QQ企鹅表情
elif current_platform == "wechat":
await self.send_text("【微信】这是微信平台的消息")
await self.send_emoji("💬") # 微信气泡表情
elif current_platform == "discord":
await self.send_text("**Discord** 这是Discord平台的消息")
await self.send_emoji("🎮") # Discord游戏表情
else:
await self.send_text(f"未知平台: {current_platform}")
return True, f"发送了{current_platform}平台适配消息"
``` ```
## 🎨 消息格式化和高级功能 ### `get_person_ids_from_messages(messages)` 异步
### 长消息分割 从消息列表中提取不重复的用户ID列表
**参数:**
- `messages` (List[Dict[str, Any]]): 消息列表
**返回:** `List[str]` - 用户ID列表
**示例:**
```python ```python
# 自动处理长消息分割 # 获取参与对话的所有用户ID
long_message = "这是一条很长的消息..." * 100 messages = message_api.get_recent_messages("123456789")
person_ids = await message_api.get_person_ids_from_messages(messages)
# 新API会自动处理长消息分割 print(f"参与对话的用户: {person_ids}")
await self.send_text(long_message)
``` ```
### 消息模板和格式化 ---
## 完整使用示例
### 场景1统计活跃度
```python ```python
class TemplateMessageAction(BaseAction): import time
async def execute(self) -> Tuple[bool, str]: from src.plugin_system.apis import message_api
# 使用配置中的消息模板
template = self.get_config("messages.greeting_template", "你好 {username}") async def analyze_chat_activity(chat_id: str):
"""分析聊天活跃度"""
# 格式化消息 now = time.time()
formatted_message = template.format( day_ago = now - 24 * 3600
username=self.user_nickname,
time=datetime.now().strftime("%H:%M"), # 获取最近24小时的消息
platform=self.platform messages = message_api.get_recent_messages(chat_id, hours=24)
)
# 统计消息数量
await self.send_text(formatted_message) total_count = len(messages)
# 根据配置决定是否发送表情 # 获取参与用户
if self.get_config("messages.include_emoji", True): person_ids = await message_api.get_person_ids_from_messages(messages)
await self.send_emoji("😊")
# 格式化消息内容
return True, "发送了模板化消息" readable_text = message_api.build_readable_messages_to_str(
messages[-10:], # 最后10条消息
merge_messages=True,
timestamp_mode="relative"
)
return {
"total_messages": total_count,
"active_users": len(person_ids),
"recent_chat": readable_text
}
``` ```
### 条件消息发送 ### 场景2查看特定用户的历史消息
```python ```python
class ConditionalMessageAction(BaseAction): def get_user_history(chat_id: str, user_id: str, days: int = 7):
async def execute(self) -> Tuple[bool, str]: """获取用户最近N天的消息历史"""
# 根据用户类型发送不同消息 now = time.time()
if self.is_group: start_time = now - days * 24 * 3600
await self.send_text(f"群聊消息 - 当前群成员: @{self.user_nickname}")
else: # 获取特定用户的消息
await self.send_text(f"私聊消息 - 你好 {self.user_nickname}") user_messages = message_api.get_messages_by_time_in_chat_for_users(
chat_id=chat_id,
# 根据时间发送不同表情 start_time=start_time,
from datetime import datetime end_time=now,
hour = datetime.now().hour person_ids=[user_id],
limit=100
if 6 <= hour < 12: )
await self.send_emoji("🌅") # 早上
elif 12 <= hour < 18: # 格式化为可读文本
await self.send_emoji("☀️") # 下午 readable_history = message_api.build_readable_messages_to_str(
else: user_messages,
await self.send_emoji("🌙") # 晚上 replace_bot_name=False,
timestamp_mode="absolute"
return True, "发送了条件化消息" )
return readable_history
``` ```
## 🛠️ 高级消息发送功能 ---
### 批量消息发送 ## 注意事项
```python 1. **时间戳格式**所有时间参数都使用Unix时间戳float类型
class BatchMessageAction(BaseAction): 2. **异步函数**`build_readable_messages_with_details``get_person_ids_from_messages` 是异步函数,需要使用 `await`
async def execute(self) -> Tuple[bool, str]: 3. **性能考虑**:查询大量消息时建议设置合理的 `limit` 参数
messages = [ 4. **消息格式**:返回的消息是字典格式,包含时间戳、发送者、内容等信息
("text", "第一条消息"), 5. **用户ID**`person_ids` 参数接受字符串列表,用于筛选特定用户的消息
("emoji", "🎉"),
("text", "第二条消息"),
("emoji", "✨")
]
for msg_type, content in messages:
if msg_type == "text":
await self.send_text(content)
elif msg_type == "emoji":
await self.send_emoji(content)
# 可选:添加延迟避免消息发送过快
import asyncio
await asyncio.sleep(0.5)
return True, "发送了批量消息"
```
### 错误处理和重试
```python
class ReliableMessageAction(BaseAction):
async def execute(self) -> Tuple[bool, str]:
max_retries = 3
retry_count = 0
while retry_count < max_retries:
try:
await self.send_text("重要消息")
return True, "消息发送成功"
except Exception as e:
retry_count += 1
logger.warning(f"消息发送失败 (尝试 {retry_count}/{max_retries}): {e}")
if retry_count < max_retries:
import asyncio
await asyncio.sleep(1) # 等待1秒后重试
return False, "消息发送失败,已达到最大重试次数"
```
## 📝 最佳实践
### 1. 消息发送最佳实践
```python
# ✅ 好的做法
class GoodMessageAction(BaseAction):
async def execute(self) -> Tuple[bool, str]:
# 1. 检查配置
if not self.get_config("features.enable_messages", True):
return True, "消息功能已禁用"
# 2. 简洁的消息发送
await self.send_text("简洁明了的消息")
# 3. 适当的表情使用
if self.get_config("features.enable_emoji", True):
await self.send_emoji("😊")
return True, "消息发送完成"
# ❌ 避免的做法
class BadMessageAction(BaseAction):
async def execute(self) -> Tuple[bool, str]:
# 避免:过长的消息
await self.send_text("这是一条非常非常长的消息" * 50)
# 避免:过多的表情
for emoji in ["😊", "🎉", "✨", "🌟", "💫"]:
await self.send_emoji(emoji)
return True, "发送了糟糕的消息"
```
### 2. 错误处理
```python
# ✅ 推荐的错误处理
class SafeMessageAction(BaseAction):
async def execute(self) -> Tuple[bool, str]:
try:
message = self.get_config("messages.default", "默认消息")
await self.send_text(message)
return True, "消息发送成功"
except Exception as e:
logger.error(f"消息发送失败: {e}")
# 可选:发送备用消息
await self.send_text("消息发送遇到问题,请稍后再试")
return False, f"发送失败: {str(e)}"
```
### 3. 性能优化
```python
# ✅ 性能友好的消息发送
class OptimizedMessageAction(BaseAction):
async def execute(self) -> Tuple[bool, str]:
# 合并多个短消息为一条长消息
parts = [
"第一部分信息",
"第二部分信息",
"第三部分信息"
]
combined_message = "\n".join(parts)
await self.send_text(combined_message)
return True, "发送了优化的消息"
```
通过新的API格式消息发送变得更加简洁高效

View File

@@ -14,13 +14,13 @@ Command是直接响应用户明确指令的组件与Action不同Command是
## 🆚 Action vs Command 核心区别 ## 🆚 Action vs Command 核心区别
| 特征 | Action | Command | | 特征 | Action | Command |
|-----|-------|---------| | ------------------ | --------------------- | ---------------- |
| **触发方式** | 麦麦主动决策使用 | 用户主动触发 | | **触发方式** | 麦麦主动决策使用 | 用户主动触发 |
| **决策机制** | 两层决策(激活+使用) | 直接匹配执行 | | **决策机制** | 两层决策(激活+使用) | 直接匹配执行 |
| **随机性** | 有随机性和智能性 | 确定性执行 | | **随机性** | 有随机性和智能性 | 确定性执行 |
| **用途** | 增强麦麦行为拟人化 | 提供具体功能服务 | | **用途** | 增强麦麦行为拟人化 | 提供具体功能服务 |
| **性能影响** | 需要LLM决策 | 正则匹配,性能好 | | **性能影响** | 需要LLM决策 | 正则匹配,性能好 |
## 🏗️ Command基本结构 ## 🏗️ Command基本结构
@@ -32,16 +32,16 @@ from src.plugin_system import BaseCommand
class MyCommand(BaseCommand): class MyCommand(BaseCommand):
# 正则表达式匹配模式 # 正则表达式匹配模式
command_pattern = r"^/help\s+(?P<topic>\w+)$" command_pattern = r"^/help\s+(?P<topic>\w+)$"
# 命令帮助说明 # 命令帮助说明
command_help = "显示指定主题的帮助信息" command_help = "显示指定主题的帮助信息"
# 使用示例 # 使用示例
command_examples = ["/help action", "/help command"] command_examples = ["/help action", "/help command"]
# 是否拦截后续处理 # 是否拦截后续处理
intercept_message = True intercept_message = True
async def execute(self) -> Tuple[bool, Optional[str]]: async def execute(self) -> Tuple[bool, Optional[str]]:
"""执行命令逻辑""" """执行命令逻辑"""
# 命令执行逻辑 # 命令执行逻辑
@@ -50,12 +50,12 @@ class MyCommand(BaseCommand):
### 属性说明 ### 属性说明
| 属性 | 类型 | 说明 | | 属性 | 类型 | 说明 |
|-----|------|------| | --------------------- | --------- | -------------------- |
| `command_pattern` | str | 正则表达式匹配模式 | | `command_pattern` | str | 正则表达式匹配模式 |
| `command_help` | str | 命令帮助说明 | | `command_help` | str | 命令帮助说明 |
| `command_examples` | List[str] | 使用示例列表 | | `command_examples` | List[str] | 使用示例列表 |
| `intercept_message` | bool | 是否拦截消息继续处理 | | `intercept_message` | bool | 是否拦截消息继续处理 |
## 🔍 正则表达式匹配 ## 🔍 正则表达式匹配
@@ -65,7 +65,7 @@ class MyCommand(BaseCommand):
class SimpleCommand(BaseCommand): class SimpleCommand(BaseCommand):
# 匹配 /ping # 匹配 /ping
command_pattern = r"^/ping$" command_pattern = r"^/ping$"
async def execute(self) -> Tuple[bool, Optional[str]]: async def execute(self) -> Tuple[bool, Optional[str]]:
await self.send_text("Pong!") await self.send_text("Pong!")
return True, "发送了Pong回复" return True, "发送了Pong回复"
@@ -79,19 +79,19 @@ class SimpleCommand(BaseCommand):
class UserCommand(BaseCommand): class UserCommand(BaseCommand):
# 匹配 /user add 张三 或 /user del 李四 # 匹配 /user add 张三 或 /user del 李四
command_pattern = r"^/user\s+(?P<action>add|del|info)\s+(?P<username>\w+)$" command_pattern = r"^/user\s+(?P<action>add|del|info)\s+(?P<username>\w+)$"
async def execute(self) -> Tuple[bool, Optional[str]]: async def execute(self) -> Tuple[bool, Optional[str]]:
# 通过 self.matched_groups 获取捕获的参数 # 通过 self.matched_groups 获取捕获的参数
action = self.matched_groups.get("action") action = self.matched_groups.get("action")
username = self.matched_groups.get("username") username = self.matched_groups.get("username")
if action == "add": if action == "add":
await self.send_text(f"添加用户:{username}") await self.send_text(f"添加用户:{username}")
elif action == "del": elif action == "del":
await self.send_text(f"删除用户:{username}") await self.send_text(f"删除用户:{username}")
elif action == "info": elif action == "info":
await self.send_text(f"用户信息:{username}") await self.send_text(f"用户信息:{username}")
return True, f"执行了{action}操作" return True, f"执行了{action}操作"
``` ```
@@ -101,15 +101,15 @@ class UserCommand(BaseCommand):
class HelpCommand(BaseCommand): class HelpCommand(BaseCommand):
# 匹配 /help 或 /help topic # 匹配 /help 或 /help topic
command_pattern = r"^/help(?:\s+(?P<topic>\w+))?$" command_pattern = r"^/help(?:\s+(?P<topic>\w+))?$"
async def execute(self) -> Tuple[bool, Optional[str]]: async def execute(self) -> Tuple[bool, Optional[str]]:
topic = self.matched_groups.get("topic") topic = self.matched_groups.get("topic")
if topic: if topic:
await self.send_text(f"显示{topic}的帮助") await self.send_text(f"显示{topic}的帮助")
else: else:
await self.send_text("显示总体帮助") await self.send_text("显示总体帮助")
return True, "显示了帮助信息" return True, "显示了帮助信息"
``` ```
@@ -122,7 +122,7 @@ class AdminCommand(BaseCommand):
command_pattern = r"^/admin\s+.+" command_pattern = r"^/admin\s+.+"
command_help = "管理员命令" command_help = "管理员命令"
intercept_message = True # 拦截,不继续处理 intercept_message = True # 拦截,不继续处理
async def execute(self) -> Tuple[bool, Optional[str]]: async def execute(self) -> Tuple[bool, Optional[str]]:
# 执行管理操作 # 执行管理操作
await self.send_text("执行管理命令") await self.send_text("执行管理命令")
@@ -137,7 +137,7 @@ class LogCommand(BaseCommand):
command_pattern = r"^/log\s+.+" command_pattern = r"^/log\s+.+"
command_help = "记录日志" command_help = "记录日志"
intercept_message = False # 不拦截,继续处理 intercept_message = False # 不拦截,继续处理
async def execute(self) -> Tuple[bool, Optional[str]]: async def execute(self) -> Tuple[bool, Optional[str]]:
# 记录日志但不阻止后续处理 # 记录日志但不阻止后续处理
await self.send_text("已记录到日志") await self.send_text("已记录到日志")
@@ -147,12 +147,12 @@ class LogCommand(BaseCommand):
### 拦截控制的用途 ### 拦截控制的用途
| 场景 | intercept_message | 说明 | | 场景 | intercept_message | 说明 |
|-----|------------------|------| | -------- | ----------------- | -------------------------- |
| 系统命令 | True | 防止命令被当作普通消息处理 | | 系统命令 | True | 防止命令被当作普通消息处理 |
| 查询命令 | True | 直接返回结果,无需后续处理 | | 查询命令 | True | 直接返回结果,无需后续处理 |
| 日志命令 | False | 记录但允许消息继续流转 | | 日志命令 | False | 记录但允许消息继续流转 |
| 监控命令 | False | 监控但不影响正常聊天 | | 监控命令 | False | 监控但不影响正常聊天 |
## 🎨 完整Command示例 ## 🎨 完整Command示例
@@ -261,7 +261,7 @@ class UserManagementCommand(BaseCommand):
🕒 注册时间: 2024-01-01 🕒 注册时间: 2024-01-01
🎯 角色: 普通用户 🎯 角色: 普通用户
""".strip() """.strip()
await self.send_text(user_info) await self.send_text(user_info)
return True, f"显示用户信息: {username}" return True, f"显示用户信息: {username}"
@@ -293,10 +293,10 @@ class SystemInfoCommand(BaseCommand):
try: try:
if info_type in ["system", "all"]: if info_type in ["system", "all"]:
await self._show_system_info() await self._show_system_info()
if info_type in ["memory", "all"]: if info_type in ["memory", "all"]:
await self._show_memory_info() await self._show_memory_info()
if info_type in ["plugins", "all"]: if info_type in ["plugins", "all"]:
await self._show_plugin_info() await self._show_plugin_info()
@@ -317,13 +317,13 @@ class SystemInfoCommand(BaseCommand):
🐍 Python: {platform.python_version()} 🐍 Python: {platform.python_version()}
⏰ 运行时间: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ⏰ 运行时间: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
""".strip() """.strip()
await self.send_text(system_info) await self.send_text(system_info)
async def _show_memory_info(self): async def _show_memory_info(self):
"""显示内存信息""" """显示内存信息"""
import psutil import psutil
memory = psutil.virtual_memory() memory = psutil.virtual_memory()
memory_info = f""" memory_info = f"""
💾 **内存信息** 💾 **内存信息**
@@ -331,20 +331,20 @@ class SystemInfoCommand(BaseCommand):
🟢 可用内存: {memory.available // (1024**3)} GB 🟢 可用内存: {memory.available // (1024**3)} GB
📈 使用率: {memory.percent}% 📈 使用率: {memory.percent}%
""".strip() """.strip()
await self.send_text(memory_info) await self.send_text(memory_info)
async def _show_plugin_info(self): async def _show_plugin_info(self):
"""显示插件信息""" """显示插件信息"""
# 通过配置获取插件信息 # 通过配置获取插件信息
plugins = await self._get_loaded_plugins() plugins = await self._get_loaded_plugins()
plugin_info = f""" plugin_info = f"""
🔌 **插件信息** 🔌 **插件信息**
📦 已加载插件: {len(plugins)} 📦 已加载插件: {len(plugins)}
🔧 活跃插件: {len([p for p in plugins if p.get('active', False)])} 🔧 活跃插件: {len([p for p in plugins if p.get('active', False)])}
""".strip() """.strip()
await self.send_text(plugin_info) await self.send_text(plugin_info)
async def _get_loaded_plugins(self) -> list: async def _get_loaded_plugins(self) -> list:
@@ -371,70 +371,21 @@ class CustomPrefixCommand(BaseCommand):
async def execute(self) -> Tuple[bool, Optional[str]]: async def execute(self) -> Tuple[bool, Optional[str]]:
"""执行骰子命令""" """执行骰子命令"""
import random import random
command = self.matched_groups.get("command") command = self.matched_groups.get("command")
count = int(self.matched_groups.get("count", "6")) count = int(self.matched_groups.get("count", "6"))
# 限制骰子面数 # 限制骰子面数
if count > 100: if count > 100:
await self.send_text("❌ 骰子面数不能超过100") await self.send_text("❌ 骰子面数不能超过100")
return False, "骰子面数超限" return False, "骰子面数超限"
result = random.randint(1, count) result = random.randint(1, count)
await self.send_text(f"🎲 投掷{count}面骰子,结果: {result}") await self.send_text(f"🎲 投掷{count}面骰子,结果: {result}")
return True, f"投掷了{count}面骰子,结果{result}" return True, f"投掷了{count}面骰子,结果{result}"
``` ```
## 🔧 新API格式使用指南
### 消息发送
```python
# 新API格式 ✅
await self.send_text("消息内容")
await self.send_emoji("😊")
# 旧API格式 ❌
await self.api.send_text_to_group("消息内容", group_id, "qq")
```
### 配置访问
```python
# 新API格式 ✅
config_value = self.get_config("section.key", "default_value")
# 旧API格式 ❌
config_value = self.api.get_config("section.key", "default_value")
```
### 用户信息获取
```python
# 新API格式 ✅
user_id = self.user_id
user_nickname = self.user_nickname
is_group_chat = self.is_group
# 旧API格式 ❌
user_id = self.message.message_info.user_info.user_id
```
### 动作记录
```python
# 新API格式 ✅ (在Action中)
await self.store_action_info(
action_build_into_prompt=True,
action_prompt_display="执行了某操作",
action_done=True
)
# 旧API格式 ❌
await self.api.store_action_info(...)
```
## 📊 性能优化建议 ## 📊 性能优化建议
### 1. 正则表达式优化 ### 1. 正则表达式优化
@@ -458,7 +409,7 @@ async def execute(self) -> Tuple[bool, Optional[str]]:
if not username: if not username:
await self.send_text("❌ 请提供用户名") await self.send_text("❌ 请提供用户名")
return False, "缺少参数" return False, "缺少参数"
# 继续处理... # 继续处理...
``` ```
@@ -479,8 +430,6 @@ async def execute(self) -> Tuple[bool, Optional[str]]:
return False, f"执行失败: {e}" return False, f"执行失败: {e}"
``` ```
通过新的API格式Command开发变得更加简洁和直观
## 🎯 最佳实践 ## 🎯 最佳实践
### 1. 命令设计原则 ### 1. 命令设计原则
@@ -514,12 +463,12 @@ class WellDocumentedCommand(BaseCommand):
```python ```python
async def execute(self) -> Tuple[bool, Optional[str]]: async def execute(self) -> Tuple[bool, Optional[str]]:
param = self.matched_groups.get("param") param = self.matched_groups.get("param")
# 参数验证 # 参数验证
if param not in ["test", "debug", "production"]: if param not in ["test", "debug", "production"]:
await self.send_text("❌ 无效的参数,支持: test, debug, production") await self.send_text("❌ 无效的参数,支持: test, debug, production")
return False, "无效参数" return False, "无效参数"
# 执行逻辑 # 执行逻辑
try: try:
result = await self._process_param(param) result = await self._process_param(param)
@@ -535,9 +484,9 @@ async def execute(self) -> Tuple[bool, Optional[str]]:
```python ```python
async def execute(self) -> Tuple[bool, Optional[str]]: async def execute(self) -> Tuple[bool, Optional[str]]:
# 从配置读取设置 # 从配置读取设置
max_items = self.api.get_config("command.max_items", 10) max_items = self.get_config("command.max_items", 10)
timeout = self.api.get_config("command.timeout", 30) timeout = self.get_config("command.timeout", 30)
# 使用配置进行处理 # 使用配置进行处理
... ...
``` ```
@@ -562,4 +511,4 @@ async def execute(self) -> Tuple[bool, Optional[str]]:
--- ---
🎉 **现在你已经掌握了Command组件开发的完整知识继续学习 [API参考](api/) 来了解所有可用的接口。** 🎉 **现在你已经掌握了Command组件开发的完整知识继续学习 [API参考](api/) 来了解所有可用的接口。**

View File

@@ -8,10 +8,28 @@
## 📖 目录 ## 📖 目录
1. [配置定义Schema驱动的配置系统](#配置定义schema驱动的配置系统) 1. [配置架构变更说明](#配置架构变更说明)
2. [配置访问在Action和Command中使用配置](#配置访问在action和command中使用配置) 2. [配置定义Schema驱动的配置系统](#配置定义schema驱动的配置系统)
3. [完整示例:从定义到使用](#完整示例从定义到使用) 3. [配置访问在Action和Command中使用配置](#配置访问在action和command中使用配置)
4. [最佳实践与注意事项](#最佳实践与注意事项) 4. [完整示例:从定义到使用](#完整示例从定义到使用)
5. [最佳实践与注意事项](#最佳实践与注意事项)
---
## 配置架构变更说明
- **`_manifest.json`** - 负责插件的**元数据信息**(静态)
- 插件名称、版本、描述
- 作者信息、许可证
- 仓库链接、关键词、分类
- 组件列表、兼容性信息
- **`config.toml`** - 负责插件的**运行时配置**(动态)
- `enabled` - 是否启用插件
- 功能参数配置
- 组件启用开关
- 用户可调整的行为参数
--- ---
@@ -101,7 +119,7 @@ class MutePlugin(BasePlugin):
# 步骤1: 定义配置节的描述 # 步骤1: 定义配置节的描述
config_section_descriptions = { config_section_descriptions = {
"plugin": "插件基本信息配置", "plugin": "插件启用配置",
"components": "组件启用控制", "components": "组件启用控制",
"mute": "核心禁言功能配置", "mute": "核心禁言功能配置",
"smart_mute": "智能禁言Action的专属配置", "smart_mute": "智能禁言Action的专属配置",
@@ -111,10 +129,7 @@ class MutePlugin(BasePlugin):
# 步骤2: 使用ConfigField定义详细的配置Schema # 步骤2: 使用ConfigField定义详细的配置Schema
config_schema = { config_schema = {
"plugin": { "plugin": {
"name": ConfigField(type=str, default="mute_plugin", description="插件名称", required=True), "enabled": ConfigField(type=bool, default=False, description="是否启用插件")
"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": { "components": {
"enable_smart_mute": ConfigField(type=bool, default=True, description="是否启用智能禁言Action"), "enable_smart_mute": ConfigField(type=bool, default=True, description="是否启用智能禁言Action"),
@@ -170,21 +185,12 @@ class MutePlugin(BasePlugin):
# mute_plugin - 自动生成的配置文件 # mute_plugin - 自动生成的配置文件
# 群聊禁言管理插件,提供智能禁言功能 # 群聊禁言管理插件,提供智能禁言功能
# 插件基本信息配置 # 插件启用配置
[plugin] [plugin]
# 插件名称 (必需)
name = "mute_plugin"
# 插件版本号
version = "2.0.0"
# 是否启用插件 # 是否启用插件
enabled = false enabled = false
# 插件描述 (必需)
description = "群聊禁言管理插件"
# 组件启用控制 # 组件启用控制
[components] [components]
@@ -378,7 +384,7 @@ class GreetingPlugin(BasePlugin):
# 配置节描述 # 配置节描述
config_section_descriptions = { config_section_descriptions = {
"plugin": "插件基本信息", "plugin": "插件启用配置",
"greeting": "问候功能配置", "greeting": "问候功能配置",
"features": "功能开关配置", "features": "功能开关配置",
"messages": "消息模板配置" "messages": "消息模板配置"
@@ -387,8 +393,7 @@ class GreetingPlugin(BasePlugin):
# 配置Schema定义 # 配置Schema定义
config_schema = { config_schema = {
"plugin": { "plugin": {
"enabled": ConfigField(type=bool, default=True, description="是否启用插件"), "enabled": ConfigField(type=bool, default=True, description="是否启用插件")
"version": ConfigField(type=str, default="1.0.0", description="插件版本")
}, },
"greeting": { "greeting": {
"template": ConfigField( "template": ConfigField(

View File

@@ -10,31 +10,43 @@
- [🧱 Action组件详解](action-components.md) - 掌握最核心的Action组件 - [🧱 Action组件详解](action-components.md) - 掌握最核心的Action组件
- [💻 Command组件详解](command-components.md) - 学习直接响应命令的组件 - [💻 Command组件详解](command-components.md) - 学习直接响应命令的组件
- [⚙️ 配置管理指南](configuration-guide.md) - 学会使用配置驱动开发 - [⚙️ 配置管理指南](configuration-guide.md) - 学会使用自动生成的插件配置文件
- [📄 Manifest系统指南](manifest-guide.md) - 了解插件元数据管理和配置架构
- [🔧 工具系统详解](tool-system.md) - 工具系统的使用和开发(非主要功能)
## API浏览 ## API浏览
### 🔗 核心通信API ### 消息发送与处理API
- [📡 消息API](api/message-api.md) - 消息接收和处理接口
- [📤 发送API](api/send-api.md) - 各种类型消息发送接口 - [📤 发送API](api/send-api.md) - 各种类型消息发送接口
- [💬 聊天API](api/chat-api.md) - 聊天流管理和查询接口 - [消息API](api/message-api.md) - 消息获取,消息构建,消息查询接口
- [聊天流API](api/chat-api.md) - 聊天流管理和查询接口
### 🤖 AI与生成API ### AI与生成API
- [🧠 LLM API](api/llm-api.md) - 大语言模型交互接口 - [LLM API](api/llm-api.md) - 大语言模型交互接口可以使用内置LLM生成内容
- [✨ 回复生成器API](api/generator-api.md) - 智能回复生成接口 - [✨ 回复生成器API](api/generator-api.md) - 智能回复生成接口,可以使用内置风格化生成器
### 表情包api
- [😊 表情包API](api/emoji-api.md) - 表情包选择和管理接口 - [😊 表情包API](api/emoji-api.md) - 表情包选择和管理接口
### 📊 数据与配置API ### 关系系统api
- [人物信息API](api/person-api.md) - 用户信息,处理麦麦认识的人和关系的接口
### 数据与配置API
- [🗄️ 数据库API](api/database-api.md) - 数据库操作接口 - [🗄️ 数据库API](api/database-api.md) - 数据库操作接口
- [⚙️ 配置API](api/config-api.md) - 配置读取和用户信息接口 - [⚙️ 配置API](api/config-api.md) - 配置读取和用户信息接口
- [👤 个人信息API](api/person-api.md) - 用户信息查询接口
### 🛠️ 工具API ### 工具API
- [🔧 工具API](api/utils-api.md) - 文件操作、时间处理等工具函数 - [工具API](api/utils-api.md) - 文件操作、时间处理等工具函数
## 实验性
这些功能将在未来重构或移除
- [🔧 工具系统详解](tool-system.md) - 工具系统的使用和开发
## 支持
> 如果你在文档中发现错误或需要补充,请: > 如果你在文档中发现错误或需要补充,请:
1. 检查最新的文档版本 1. 检查最新的文档版本

View File

@@ -4,6 +4,26 @@
MaiBot插件系统现在强制要求每个插件都必须包含一个 `_manifest.json` 文件。这个文件描述了插件的基本信息、依赖关系、组件等重要元数据。 MaiBot插件系统现在强制要求每个插件都必须包含一个 `_manifest.json` 文件。这个文件描述了插件的基本信息、依赖关系、组件等重要元数据。
### 🔄 配置架构Manifest与Config的职责分离
为了避免信息重复和提高维护性,我们采用了**双文件架构**
- **`_manifest.json`** - 插件的**静态元数据**
- 插件身份信息(名称、版本、描述)
- 开发者信息(作者、许可证、仓库)
- 系统信息(兼容性、组件列表、分类)
- **`config.toml`** - 插件的**运行时配置**
- 启用状态 (`enabled`)
- 功能参数配置
- 用户可调整的行为设置
这种分离确保了:
- ✅ 元数据信息统一管理
- ✅ 运行时配置灵活调整
- ✅ 避免重复维护
- ✅ 更清晰的职责划分
## 🔧 Manifest文件结构 ## 🔧 Manifest文件结构
### 必需字段 ### 必需字段

View File

@@ -217,6 +217,20 @@ class ActionPlanner(BasePlanner):
# 如果repair_json直接返回了字典对象直接使用 # 如果repair_json直接返回了字典对象直接使用
parsed_json = fixed_json_string parsed_json = fixed_json_string
# 处理repair_json可能返回列表的情况
if isinstance(parsed_json, list):
if parsed_json:
# 取列表中最后一个元素(通常是最完整的)
parsed_json = parsed_json[-1]
logger.warning(f"{self.log_prefix}LLM返回了多个JSON对象使用最后一个: {parsed_json}")
else:
parsed_json = {}
# 确保parsed_json是字典
if not isinstance(parsed_json, dict):
logger.error(f"{self.log_prefix}解析后的JSON不是字典类型: {type(parsed_json)}")
parsed_json = {}
# 提取决策,提供默认值 # 提取决策,提供默认值
extracted_action = parsed_json.get("action", "no_reply") extracted_action = parsed_json.get("action", "no_reply")
extracted_reasoning = "" extracted_reasoning = ""

View File

@@ -3,6 +3,7 @@ import os
import importlib import importlib
import importlib.util import importlib.util
from pathlib import Path from pathlib import Path
import traceback
if TYPE_CHECKING: if TYPE_CHECKING:
from src.plugin_system.base.base_plugin import BasePlugin from src.plugin_system.base.base_plugin import BasePlugin
@@ -151,6 +152,7 @@ class PluginManager:
except ValueError as e: except ValueError as e:
# manifest文件格式错误或验证失败 # manifest文件格式错误或验证失败
traceback.print_exc()
total_failed_registration += 1 total_failed_registration += 1
error_msg = f"manifest验证失败: {str(e)}" error_msg = f"manifest验证失败: {str(e)}"
self.failed_plugins[plugin_name] = error_msg self.failed_plugins[plugin_name] = error_msg

View File

@@ -351,7 +351,7 @@ class CoreActionsPlugin(BasePlugin):
# 配置节描述 # 配置节描述
config_section_descriptions = { config_section_descriptions = {
"plugin": "插件基本信息配置", "plugin": "插件启用配置",
"components": "核心组件启用配置", "components": "核心组件启用配置",
"no_reply": "不回复动作配置", "no_reply": "不回复动作配置",
"emoji": "表情动作配置", "emoji": "表情动作配置",
@@ -360,12 +360,7 @@ class CoreActionsPlugin(BasePlugin):
# 配置Schema定义 # 配置Schema定义
config_schema = { config_schema = {
"plugin": { "plugin": {
"name": ConfigField(type=str, default="core_actions", description="插件名称", required=True),
"version": ConfigField(type=str, default="1.0.0", description="插件版本号"),
"enabled": ConfigField(type=bool, default=True, description="是否启用插件"), "enabled": ConfigField(type=bool, default=True, description="是否启用插件"),
"description": ConfigField(
type=str, default="系统核心动作插件,提供基础聊天交互功能", description="插件描述", required=True
),
}, },
"components": { "components": {
"enable_reply": ConfigField(type=bool, default=True, description="是否启用'回复'动作"), "enable_reply": ConfigField(type=bool, default=True, description="是否启用'回复'动作"),

View File

@@ -1,5 +1,5 @@
[inner] [inner]
version = "2.23.0" version = "2.24.0"
#----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读---- #----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读----
#如果你想要修改配置文件请在修改后将version的值进行变更 #如果你想要修改配置文件请在修改后将version的值进行变更
@@ -43,7 +43,7 @@ identity_detail = [
expression_style = "描述麦麦说话的表达风格,表达习惯,例如:(回复尽量简短一些。可以参考贴吧,知乎和微博的回复风格,回复不要浮夸,不要用夸张修辞,平淡一些。不要有额外的符号,尽量简单简短)" expression_style = "描述麦麦说话的表达风格,表达习惯,例如:(回复尽量简短一些。可以参考贴吧,知乎和微博的回复风格,回复不要浮夸,不要用夸张修辞,平淡一些。不要有额外的符号,尽量简单简短)"
enable_expression_learning = false # 是否启用表达学习,麦麦会学习不同群里人类说话风格(群之间不互通) enable_expression_learning = false # 是否启用表达学习,麦麦会学习不同群里人类说话风格(群之间不互通)
learning_interval = 600 # 学习间隔 单位秒 learning_interval = 600 # 学习间隔 单位秒
selection_mode = "llm" # 专注模式下 表达方式选择模式:'llm' 使用LLM智能选择'random' 使用传统随机选择 selection_mode = "random" # 专注模式下 表达方式选择模式:'llm' 使用LLM智能选择'random' 使用传统随机选择
[relationship] [relationship]
enable_relationship = true # 是否启用关系系统 enable_relationship = true # 是否启用关系系统
@@ -320,12 +320,12 @@ temp = 0.2
[model.lpmm_qa] # 问答模型 [model.lpmm_qa] # 问答模型
name = "Pro/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B" name = "Qwen/Qwen3-30B-A3B"
provider = "SILICONFLOW" provider = "SILICONFLOW"
pri_in = 4.0 pri_in = 0.7
pri_out = 16.0 pri_out = 2.8
temp = 0.7 temp = 0.7
enable_thinking = false # 是否启用思考
[maim_message] [maim_message]
auth_token = [] # 认证令牌用于API验证为空则不启用验证 auth_token = [] # 认证令牌用于API验证为空则不启用验证