From 3fcebf6d4ffcc1d3c2bbf1f6fbb0c58e0fee09f0 Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Fri, 20 Jun 2025 01:41:23 +0800 Subject: [PATCH] =?UTF-8?q?add=EF=BC=9A=E6=96=B0=E5=A2=9E=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=8F=98=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/plugins/action-components.md | 375 +++++------ docs/plugins/api/message-api.md | 593 ++++++++---------- docs/plugins/command-components.md | 153 ++--- docs/plugins/configuration-guide.md | 49 +- docs/plugins/{README.md => index.md} | 38 +- docs/plugins/manifest-guide.md | 20 + .../focus_chat/planners/planner_simple.py | 14 + src/plugin_system/core/plugin_manager.py | 2 + src/plugins/built_in/core_actions/plugin.py | 7 +- template/bot_config_template.toml | 12 +- 10 files changed, 590 insertions(+), 673 deletions(-) rename docs/plugins/{README.md => index.md} (57%) diff --git a/docs/plugins/action-components.md b/docs/plugins/action-components.md index e8ae77f74..d68d87076 100644 --- a/docs/plugins/action-components.md +++ b/docs/plugins/action-components.md @@ -128,146 +128,21 @@ action_require = [ associated_types = ["text", "emoji", "image"] ``` -### 4. 新API导入必须项 - -使用新插件系统时,必须导入所需的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` 记录动作信息: +### 4. 执行方法必须项 ```python async def execute(self) -> Tuple[bool, str]: - # ... 执行动作的代码 ... - - 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) + """ + 执行Action的主要逻辑 - # 记录动作 - await self.store_action_info( - action_build_into_prompt=True, - action_prompt_display=f"使用replyer_1生成了智能回复", - action_done=True - ) + Returns: + Tuple[bool, str]: (是否成功, 执行结果描述) + """ + # 执行动作的代码 + success = True + message = "动作执行成功" - return True, "智能回复生成成功" - 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, "数据存储完成" + return success, message ``` ## 🔧 激活类型详解 @@ -286,28 +161,8 @@ class GreetingAction(BaseAction): keyword_case_sensitive = False # 不区分大小写 async def execute(self) -> Tuple[bool, str]: - # 可选:使用replyer_1生成个性化问候 - if self.get_config("greeting.use_smart_reply", False): - 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, "发送问候" + # 执行问候逻辑 + return True, "发送了问候" ``` ### LLM_JUDGE激活 @@ -330,26 +185,8 @@ class HelpAction(BaseAction): """ async def execute(self) -> Tuple[bool, str]: - # 使用replyer_1生成帮助内容 - help_data = { - "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, "提供了默认帮助" + # 执行帮助逻辑 + return True, "提供了帮助" ``` ### RANDOM激活 @@ -365,11 +202,181 @@ class SurpriseAction(BaseAction): random_activation_probability = 0.1 # 10%概率激活 async def execute(self) -> Tuple[bool, str]: - import random - - surprises = ["🎉", "✨", "🌟", "💝", "🎈"] - selected = random.choice(surprises) - - await self.send_emoji(selected) - return True, f"发送了惊喜表情: {selected}" + # 执行惊喜动作 + return True, "发送了惊喜内容" ``` + +### 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`的有效性 +- **配置测试**:测试不同配置下的行为 diff --git a/docs/plugins/api/message-api.md b/docs/plugins/api/message-api.md index c83473ad4..c95a9cc6f 100644 --- a/docs/plugins/api/message-api.md +++ b/docs/plugins/api/message-api.md @@ -1,398 +1,311 @@ -# 📡 消息API +# 消息API -## 📖 概述 +> 消息API提供了强大的消息查询、计数和格式化功能,让你轻松处理聊天消息数据。 -消息API提供了发送各种类型消息的接口,支持文本、表情、图片等多种消息类型。新版API格式更加简洁直观,自动处理群聊/私聊判断。 - -## 🔄 基础消息发送 - -### 发送文本消息 +## 导入方式 ```python -# 新API格式 - 自动判断群聊/私聊 -await self.send_text("这是一条文本消息") - -# 发送多行文本 -message = """ -这是第一行 -这是第二行 -这是第三行 -""" -await self.send_text(message.strip()) +from src.plugin_system.apis import message_api ``` -### 发送表情消息 +## 功能概述 +消息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 -# 新API格式 - 发送表情 -await self.send_emoji("😊") -await self.send_emoji("🎉") -await self.send_emoji("👋") +import time + +# 获取最近24小时的消息 +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 -# 发送图片 -await self.send_type("image", "https://example.com/image.jpg") - -# 发送音频 -await self.send_type("audio", "audio_file_path") - -# 发送视频 -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" +# 获取某个群聊最近的100条消息 +messages = message_api.get_messages_by_time_in_chat( + chat_id="123456789", + start_time=yesterday, + end_time=now, + limit=100 ) ``` -### 通用目标消息发送 +#### `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 -# 向任意目标发送任意类型消息 -success = await send_api.message_to_target( - message_type="text", # 消息类型 - content="消息内容", # 消息内容 - platform="qq", # 平台 - target_id="123456789", # 目标ID - is_group=True, # 是否为群聊 - display_message="显示消息" # 可选:显示消息 +# 获取最近6小时的消息 +recent_messages = message_api.get_recent_messages( + chat_id="123456789", + hours=6.0, + limit=50 ) ``` -## 📨 消息类型支持 +### 按用户查询消息 -### 支持的消息类型 +#### `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 -class ExampleAction(BaseAction): - async def execute(self) -> Tuple[bool, str]: - # 文本消息 - 最常用 - await self.send_text("普通文本消息") - - # 表情消息 - 直接方法 - 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, "发送了多种类型的消息" +# 获取特定用户的消息 +user_messages = message_api.get_messages_by_time_in_chat_for_users( + chat_id="123456789", + start_time=yesterday, + end_time=now, + person_ids=["user1", "user2"] +) ``` -## 🔍 消息信息获取 +#### `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 -# 新API格式 - 直接属性访问 -class ExampleCommand(BaseCommand): - async def execute(self) -> Tuple[bool, str]: - # 用户信息 - user_id = self.user_id - user_nickname = self.user_nickname - - # 聊天信息 - 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, "显示了消息信息" +# 计算最近1小时的新消息数 +import time +now = time.time() +hour_ago = now - 3600 +new_count = message_api.count_new_messages("123456789", hour_ago, now) +print(f"最近1小时有{new_count}条新消息") ``` -### 获取群聊信息(如果适用) +### `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 -# 在Action或Command中检查群聊信息 -if self.is_group: - group_info = self.message.message_info.group_info - if group_info: - group_id = group_info.group_id - group_name = getattr(group_info, 'group_name', '未知群聊') - - await self.send_text(f"当前群聊: {group_name}({group_id})") -else: - await self.send_text("当前是私聊对话") +# 获取消息并格式化为可读文本 +messages = message_api.get_recent_messages("123456789", hours=2) +readable_text = message_api.build_readable_messages_to_str( + messages, + replace_bot_name=True, + merge_messages=True, + timestamp_mode="relative" +) +print(readable_text) ``` -## 🌐 平台支持 +### `build_readable_messages_with_details(messages, **options)` 异步 -### 支持的平台 +将消息列表构建成可读的字符串,并返回详细信息 -| 平台 | 标识 | 说明 | -|-----|------|------| -| QQ | `qq` | QQ聊天平台 | -| 微信 | `wechat` | 微信聊天平台 | -| Discord | `discord` | Discord聊天平台 | +**参数:** 与 `build_readable_messages_to_str` 类似,但不包含 `read_mark` 和 `show_actions` -### 平台适配示例 +**返回:** `Tuple[str, List[Tuple[float, str, str]]]` - 格式化字符串和详细信息元组列表(时间戳, 昵称, 内容) +**示例:** ```python -class PlatformAdaptiveAction(BaseAction): - async def execute(self) -> Tuple[bool, str]: - # 获取当前平台 - current_platform = self.platform - - # 根据平台调整消息格式 - if current_platform == "qq": - await self.send_text("[QQ] 这是QQ平台的消息") - 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}平台适配消息" +# 异步获取详细格式化信息 +readable_text, details = await message_api.build_readable_messages_with_details( + messages, + timestamp_mode="absolute" +) + +for timestamp, nickname, content in details: + print(f"{timestamp}: {nickname} 说: {content}") ``` -## 🎨 消息格式化和高级功能 +### `get_person_ids_from_messages(messages)` 异步 -### 长消息分割 +从消息列表中提取不重复的用户ID列表 +**参数:** +- `messages` (List[Dict[str, Any]]): 消息列表 + +**返回:** `List[str]` - 用户ID列表 + +**示例:** ```python -# 自动处理长消息分割 -long_message = "这是一条很长的消息..." * 100 - -# 新API会自动处理长消息分割 -await self.send_text(long_message) +# 获取参与对话的所有用户ID +messages = message_api.get_recent_messages("123456789") +person_ids = await message_api.get_person_ids_from_messages(messages) +print(f"参与对话的用户: {person_ids}") ``` -### 消息模板和格式化 +--- + +## 完整使用示例 + +### 场景1:统计活跃度 ```python -class TemplateMessageAction(BaseAction): - async def execute(self) -> Tuple[bool, str]: - # 使用配置中的消息模板 - template = self.get_config("messages.greeting_template", "你好 {username}!") - - # 格式化消息 - formatted_message = template.format( - username=self.user_nickname, - time=datetime.now().strftime("%H:%M"), - platform=self.platform - ) - - await self.send_text(formatted_message) - - # 根据配置决定是否发送表情 - if self.get_config("messages.include_emoji", True): - await self.send_emoji("😊") - - return True, "发送了模板化消息" +import time +from src.plugin_system.apis import message_api + +async def analyze_chat_activity(chat_id: str): + """分析聊天活跃度""" + now = time.time() + day_ago = now - 24 * 3600 + + # 获取最近24小时的消息 + messages = message_api.get_recent_messages(chat_id, hours=24) + + # 统计消息数量 + total_count = len(messages) + + # 获取参与用户 + person_ids = await message_api.get_person_ids_from_messages(messages) + + # 格式化消息内容 + 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 -class ConditionalMessageAction(BaseAction): - async def execute(self) -> Tuple[bool, str]: - # 根据用户类型发送不同消息 - if self.is_group: - await self.send_text(f"群聊消息 - 当前群成员: @{self.user_nickname}") - else: - await self.send_text(f"私聊消息 - 你好 {self.user_nickname}!") - - # 根据时间发送不同表情 - from datetime import datetime - hour = datetime.now().hour - - if 6 <= hour < 12: - await self.send_emoji("🌅") # 早上 - elif 12 <= hour < 18: - await self.send_emoji("☀️") # 下午 - else: - await self.send_emoji("🌙") # 晚上 - - return True, "发送了条件化消息" +def get_user_history(chat_id: str, user_id: str, days: int = 7): + """获取用户最近N天的消息历史""" + now = time.time() + start_time = now - days * 24 * 3600 + + # 获取特定用户的消息 + user_messages = message_api.get_messages_by_time_in_chat_for_users( + chat_id=chat_id, + start_time=start_time, + end_time=now, + person_ids=[user_id], + limit=100 + ) + + # 格式化为可读文本 + readable_history = message_api.build_readable_messages_to_str( + user_messages, + replace_bot_name=False, + timestamp_mode="absolute" + ) + + return readable_history ``` -## 🛠️ 高级消息发送功能 +--- -### 批量消息发送 +## 注意事项 -```python -class BatchMessageAction(BaseAction): - async def execute(self) -> Tuple[bool, str]: - messages = [ - ("text", "第一条消息"), - ("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格式,消息发送变得更加简洁高效! \ No newline at end of file +1. **时间戳格式**:所有时间参数都使用Unix时间戳(float类型) +2. **异步函数**:`build_readable_messages_with_details` 和 `get_person_ids_from_messages` 是异步函数,需要使用 `await` +3. **性能考虑**:查询大量消息时建议设置合理的 `limit` 参数 +4. **消息格式**:返回的消息是字典格式,包含时间戳、发送者、内容等信息 +5. **用户ID**:`person_ids` 参数接受字符串列表,用于筛选特定用户的消息 \ No newline at end of file diff --git a/docs/plugins/command-components.md b/docs/plugins/command-components.md index ae2239671..76f32db66 100644 --- a/docs/plugins/command-components.md +++ b/docs/plugins/command-components.md @@ -14,13 +14,13 @@ Command是直接响应用户明确指令的组件,与Action不同,Command是 ## 🆚 Action vs Command 核心区别 -| 特征 | Action | Command | -|-----|-------|---------| -| **触发方式** | 麦麦主动决策使用 | 用户主动触发 | -| **决策机制** | 两层决策(激活+使用) | 直接匹配执行 | -| **随机性** | 有随机性和智能性 | 确定性执行 | -| **用途** | 增强麦麦行为拟人化 | 提供具体功能服务 | -| **性能影响** | 需要LLM决策 | 正则匹配,性能好 | +| 特征 | Action | Command | +| ------------------ | --------------------- | ---------------- | +| **触发方式** | 麦麦主动决策使用 | 用户主动触发 | +| **决策机制** | 两层决策(激活+使用) | 直接匹配执行 | +| **随机性** | 有随机性和智能性 | 确定性执行 | +| **用途** | 增强麦麦行为拟人化 | 提供具体功能服务 | +| **性能影响** | 需要LLM决策 | 正则匹配,性能好 | ## 🏗️ Command基本结构 @@ -32,16 +32,16 @@ from src.plugin_system import BaseCommand class MyCommand(BaseCommand): # 正则表达式匹配模式 command_pattern = r"^/help\s+(?P\w+)$" - + # 命令帮助说明 command_help = "显示指定主题的帮助信息" - + # 使用示例 command_examples = ["/help action", "/help command"] - + # 是否拦截后续处理 intercept_message = True - + async def execute(self) -> Tuple[bool, Optional[str]]: """执行命令逻辑""" # 命令执行逻辑 @@ -50,12 +50,12 @@ class MyCommand(BaseCommand): ### 属性说明 -| 属性 | 类型 | 说明 | -|-----|------|------| -| `command_pattern` | str | 正则表达式匹配模式 | -| `command_help` | str | 命令帮助说明 | -| `command_examples` | List[str] | 使用示例列表 | -| `intercept_message` | bool | 是否拦截消息继续处理 | +| 属性 | 类型 | 说明 | +| --------------------- | --------- | -------------------- | +| `command_pattern` | str | 正则表达式匹配模式 | +| `command_help` | str | 命令帮助说明 | +| `command_examples` | List[str] | 使用示例列表 | +| `intercept_message` | bool | 是否拦截消息继续处理 | ## 🔍 正则表达式匹配 @@ -65,7 +65,7 @@ class MyCommand(BaseCommand): class SimpleCommand(BaseCommand): # 匹配 /ping command_pattern = r"^/ping$" - + async def execute(self) -> Tuple[bool, Optional[str]]: await self.send_text("Pong!") return True, "发送了Pong回复" @@ -79,19 +79,19 @@ class SimpleCommand(BaseCommand): class UserCommand(BaseCommand): # 匹配 /user add 张三 或 /user del 李四 command_pattern = r"^/user\s+(?Padd|del|info)\s+(?P\w+)$" - + async def execute(self) -> Tuple[bool, Optional[str]]: # 通过 self.matched_groups 获取捕获的参数 action = self.matched_groups.get("action") username = self.matched_groups.get("username") - + if action == "add": await self.send_text(f"添加用户:{username}") elif action == "del": await self.send_text(f"删除用户:{username}") elif action == "info": await self.send_text(f"用户信息:{username}") - + return True, f"执行了{action}操作" ``` @@ -101,15 +101,15 @@ class UserCommand(BaseCommand): class HelpCommand(BaseCommand): # 匹配 /help 或 /help topic command_pattern = r"^/help(?:\s+(?P\w+))?$" - + async def execute(self) -> Tuple[bool, Optional[str]]: topic = self.matched_groups.get("topic") - + if topic: await self.send_text(f"显示{topic}的帮助") else: await self.send_text("显示总体帮助") - + return True, "显示了帮助信息" ``` @@ -122,7 +122,7 @@ class AdminCommand(BaseCommand): command_pattern = r"^/admin\s+.+" command_help = "管理员命令" intercept_message = True # 拦截,不继续处理 - + async def execute(self) -> Tuple[bool, Optional[str]]: # 执行管理操作 await self.send_text("执行管理命令") @@ -137,7 +137,7 @@ class LogCommand(BaseCommand): command_pattern = r"^/log\s+.+" command_help = "记录日志" intercept_message = False # 不拦截,继续处理 - + async def execute(self) -> Tuple[bool, Optional[str]]: # 记录日志但不阻止后续处理 await self.send_text("已记录到日志") @@ -147,12 +147,12 @@ class LogCommand(BaseCommand): ### 拦截控制的用途 -| 场景 | intercept_message | 说明 | -|-----|------------------|------| -| 系统命令 | True | 防止命令被当作普通消息处理 | -| 查询命令 | True | 直接返回结果,无需后续处理 | -| 日志命令 | False | 记录但允许消息继续流转 | -| 监控命令 | False | 监控但不影响正常聊天 | +| 场景 | intercept_message | 说明 | +| -------- | ----------------- | -------------------------- | +| 系统命令 | True | 防止命令被当作普通消息处理 | +| 查询命令 | True | 直接返回结果,无需后续处理 | +| 日志命令 | False | 记录但允许消息继续流转 | +| 监控命令 | False | 监控但不影响正常聊天 | ## 🎨 完整Command示例 @@ -261,7 +261,7 @@ class UserManagementCommand(BaseCommand): 🕒 注册时间: 2024-01-01 🎯 角色: 普通用户 """.strip() - + await self.send_text(user_info) return True, f"显示用户信息: {username}" @@ -293,10 +293,10 @@ class SystemInfoCommand(BaseCommand): try: if info_type in ["system", "all"]: await self._show_system_info() - + if info_type in ["memory", "all"]: await self._show_memory_info() - + if info_type in ["plugins", "all"]: await self._show_plugin_info() @@ -317,13 +317,13 @@ class SystemInfoCommand(BaseCommand): 🐍 Python: {platform.python_version()} ⏰ 运行时间: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} """.strip() - + await self.send_text(system_info) async def _show_memory_info(self): """显示内存信息""" import psutil - + memory = psutil.virtual_memory() memory_info = f""" 💾 **内存信息** @@ -331,20 +331,20 @@ class SystemInfoCommand(BaseCommand): 🟢 可用内存: {memory.available // (1024**3)} GB 📈 使用率: {memory.percent}% """.strip() - + await self.send_text(memory_info) async def _show_plugin_info(self): """显示插件信息""" # 通过配置获取插件信息 plugins = await self._get_loaded_plugins() - + plugin_info = f""" 🔌 **插件信息** 📦 已加载插件: {len(plugins)} 🔧 活跃插件: {len([p for p in plugins if p.get('active', False)])} """.strip() - + await self.send_text(plugin_info) async def _get_loaded_plugins(self) -> list: @@ -371,70 +371,21 @@ class CustomPrefixCommand(BaseCommand): async def execute(self) -> Tuple[bool, Optional[str]]: """执行骰子命令""" import random - + command = self.matched_groups.get("command") count = int(self.matched_groups.get("count", "6")) - + # 限制骰子面数 if count > 100: await self.send_text("❌ 骰子面数不能超过100") return False, "骰子面数超限" - + result = random.randint(1, count) await self.send_text(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. 正则表达式优化 @@ -458,7 +409,7 @@ async def execute(self) -> Tuple[bool, Optional[str]]: if not username: await self.send_text("❌ 请提供用户名") return False, "缺少参数" - + # 继续处理... ``` @@ -479,8 +430,6 @@ async def execute(self) -> Tuple[bool, Optional[str]]: return False, f"执行失败: {e}" ``` -通过新的API格式,Command开发变得更加简洁和直观! - ## 🎯 最佳实践 ### 1. 命令设计原则 @@ -514,12 +463,12 @@ class WellDocumentedCommand(BaseCommand): ```python async def execute(self) -> Tuple[bool, Optional[str]]: param = self.matched_groups.get("param") - + # 参数验证 if param not in ["test", "debug", "production"]: await self.send_text("❌ 无效的参数,支持: test, debug, production") return False, "无效参数" - + # 执行逻辑 try: result = await self._process_param(param) @@ -535,9 +484,9 @@ async def execute(self) -> Tuple[bool, Optional[str]]: ```python async def execute(self) -> Tuple[bool, Optional[str]]: # 从配置读取设置 - max_items = self.api.get_config("command.max_items", 10) - timeout = self.api.get_config("command.timeout", 30) - + max_items = self.get_config("command.max_items", 10) + timeout = self.get_config("command.timeout", 30) + # 使用配置进行处理 ... ``` @@ -562,4 +511,4 @@ async def execute(self) -> Tuple[bool, Optional[str]]: --- -🎉 **现在你已经掌握了Command组件开发的完整知识!继续学习 [API参考](api/) 来了解所有可用的接口。** \ No newline at end of file +🎉 **现在你已经掌握了Command组件开发的完整知识!继续学习 [API参考](api/) 来了解所有可用的接口。** diff --git a/docs/plugins/configuration-guide.md b/docs/plugins/configuration-guide.md index a681922d5..30407fa80 100644 --- a/docs/plugins/configuration-guide.md +++ b/docs/plugins/configuration-guide.md @@ -8,10 +8,28 @@ ## 📖 目录 -1. [配置定义:Schema驱动的配置系统](#配置定义schema驱动的配置系统) -2. [配置访问:在Action和Command中使用配置](#配置访问在action和command中使用配置) -3. [完整示例:从定义到使用](#完整示例从定义到使用) -4. [最佳实践与注意事项](#最佳实践与注意事项) +1. [配置架构变更说明](#配置架构变更说明) +2. [配置定义:Schema驱动的配置系统](#配置定义schema驱动的配置系统) +3. [配置访问:在Action和Command中使用配置](#配置访问在action和command中使用配置) +4. [完整示例:从定义到使用](#完整示例从定义到使用) +5. [最佳实践与注意事项](#最佳实践与注意事项) + +--- + +## 配置架构变更说明 + +- **`_manifest.json`** - 负责插件的**元数据信息**(静态) + - 插件名称、版本、描述 + - 作者信息、许可证 + - 仓库链接、关键词、分类 + - 组件列表、兼容性信息 + +- **`config.toml`** - 负责插件的**运行时配置**(动态) + - `enabled` - 是否启用插件 + - 功能参数配置 + - 组件启用开关 + - 用户可调整的行为参数 + --- @@ -101,7 +119,7 @@ class MutePlugin(BasePlugin): # 步骤1: 定义配置节的描述 config_section_descriptions = { - "plugin": "插件基本信息配置", + "plugin": "插件启用配置", "components": "组件启用控制", "mute": "核心禁言功能配置", "smart_mute": "智能禁言Action的专属配置", @@ -111,10 +129,7 @@ class MutePlugin(BasePlugin): # 步骤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) + "enabled": ConfigField(type=bool, default=False, description="是否启用插件") }, "components": { "enable_smart_mute": ConfigField(type=bool, default=True, description="是否启用智能禁言Action"), @@ -170,21 +185,12 @@ class MutePlugin(BasePlugin): # mute_plugin - 自动生成的配置文件 # 群聊禁言管理插件,提供智能禁言功能 -# 插件基本信息配置 +# 插件启用配置 [plugin] -# 插件名称 (必需) -name = "mute_plugin" - -# 插件版本号 -version = "2.0.0" - # 是否启用插件 enabled = false -# 插件描述 (必需) -description = "群聊禁言管理插件" - # 组件启用控制 [components] @@ -378,7 +384,7 @@ class GreetingPlugin(BasePlugin): # 配置节描述 config_section_descriptions = { - "plugin": "插件基本信息", + "plugin": "插件启用配置", "greeting": "问候功能配置", "features": "功能开关配置", "messages": "消息模板配置" @@ -387,8 +393,7 @@ class GreetingPlugin(BasePlugin): # 配置Schema定义 config_schema = { "plugin": { - "enabled": ConfigField(type=bool, default=True, description="是否启用插件"), - "version": ConfigField(type=str, default="1.0.0", description="插件版本") + "enabled": ConfigField(type=bool, default=True, description="是否启用插件") }, "greeting": { "template": ConfigField( diff --git a/docs/plugins/README.md b/docs/plugins/index.md similarity index 57% rename from docs/plugins/README.md rename to docs/plugins/index.md index f71aa1e79..2e025fd62 100644 --- a/docs/plugins/README.md +++ b/docs/plugins/index.md @@ -10,31 +10,43 @@ - [🧱 Action组件详解](action-components.md) - 掌握最核心的Action组件 - [💻 Command组件详解](command-components.md) - 学习直接响应命令的组件 -- [⚙️ 配置管理指南](configuration-guide.md) - 学会使用配置驱动开发 - -- [🔧 工具系统详解](tool-system.md) - 工具系统的使用和开发(非主要功能) +- [⚙️ 配置管理指南](configuration-guide.md) - 学会使用自动生成的插件配置文件 +- [📄 Manifest系统指南](manifest-guide.md) - 了解插件元数据管理和配置架构 ## API浏览 -### 🔗 核心通信API -- [📡 消息API](api/message-api.md) - 消息接收和处理接口 +### 消息发送与处理API - [📤 发送API](api/send-api.md) - 各种类型消息发送接口 -- [💬 聊天API](api/chat-api.md) - 聊天流管理和查询接口 +- [消息API](api/message-api.md) - 消息获取,消息构建,消息查询接口 +- [聊天流API](api/chat-api.md) - 聊天流管理和查询接口 -### 🤖 AI与生成API -- [🧠 LLM API](api/llm-api.md) - 大语言模型交互接口 -- [✨ 回复生成器API](api/generator-api.md) - 智能回复生成接口 +### AI与生成API +- [LLM API](api/llm-api.md) - 大语言模型交互接口,可以使用内置LLM生成内容 +- [✨ 回复生成器API](api/generator-api.md) - 智能回复生成接口,可以使用内置风格化生成器 + +### 表情包api - [😊 表情包API](api/emoji-api.md) - 表情包选择和管理接口 -### 📊 数据与配置API +### 关系系统api +- [人物信息API](api/person-api.md) - 用户信息,处理麦麦认识的人和关系的接口 + +### 数据与配置API - [🗄️ 数据库API](api/database-api.md) - 数据库操作接口 - [⚙️ 配置API](api/config-api.md) - 配置读取和用户信息接口 -- [👤 个人信息API](api/person-api.md) - 用户信息查询接口 -### 🛠️ 工具API -- [🔧 工具API](api/utils-api.md) - 文件操作、时间处理等工具函数 +### 工具API +- [工具API](api/utils-api.md) - 文件操作、时间处理等工具函数 +## 实验性 + +这些功能将在未来重构或移除 +- [🔧 工具系统详解](tool-system.md) - 工具系统的使用和开发 + + + +## 支持 + > 如果你在文档中发现错误或需要补充,请: 1. 检查最新的文档版本 diff --git a/docs/plugins/manifest-guide.md b/docs/plugins/manifest-guide.md index 8d2005b86..5c5d7e3fb 100644 --- a/docs/plugins/manifest-guide.md +++ b/docs/plugins/manifest-guide.md @@ -4,6 +4,26 @@ MaiBot插件系统现在强制要求每个插件都必须包含一个 `_manifest.json` 文件。这个文件描述了插件的基本信息、依赖关系、组件等重要元数据。 +### 🔄 配置架构:Manifest与Config的职责分离 + +为了避免信息重复和提高维护性,我们采用了**双文件架构**: + +- **`_manifest.json`** - 插件的**静态元数据** + - 插件身份信息(名称、版本、描述) + - 开发者信息(作者、许可证、仓库) + - 系统信息(兼容性、组件列表、分类) + +- **`config.toml`** - 插件的**运行时配置** + - 启用状态 (`enabled`) + - 功能参数配置 + - 用户可调整的行为设置 + +这种分离确保了: +- ✅ 元数据信息统一管理 +- ✅ 运行时配置灵活调整 +- ✅ 避免重复维护 +- ✅ 更清晰的职责划分 + ## 🔧 Manifest文件结构 ### 必需字段 diff --git a/src/chat/focus_chat/planners/planner_simple.py b/src/chat/focus_chat/planners/planner_simple.py index 3970a73ac..da728923e 100644 --- a/src/chat/focus_chat/planners/planner_simple.py +++ b/src/chat/focus_chat/planners/planner_simple.py @@ -217,6 +217,20 @@ class ActionPlanner(BasePlanner): # 如果repair_json直接返回了字典对象,直接使用 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_reasoning = "" diff --git a/src/plugin_system/core/plugin_manager.py b/src/plugin_system/core/plugin_manager.py index 47edec4af..3fc263a0d 100644 --- a/src/plugin_system/core/plugin_manager.py +++ b/src/plugin_system/core/plugin_manager.py @@ -3,6 +3,7 @@ import os import importlib import importlib.util from pathlib import Path +import traceback if TYPE_CHECKING: from src.plugin_system.base.base_plugin import BasePlugin @@ -151,6 +152,7 @@ class PluginManager: except ValueError as e: # manifest文件格式错误或验证失败 + traceback.print_exc() total_failed_registration += 1 error_msg = f"manifest验证失败: {str(e)}" self.failed_plugins[plugin_name] = error_msg diff --git a/src/plugins/built_in/core_actions/plugin.py b/src/plugins/built_in/core_actions/plugin.py index a51d20697..e175d4627 100644 --- a/src/plugins/built_in/core_actions/plugin.py +++ b/src/plugins/built_in/core_actions/plugin.py @@ -351,7 +351,7 @@ class CoreActionsPlugin(BasePlugin): # 配置节描述 config_section_descriptions = { - "plugin": "插件基本信息配置", + "plugin": "插件启用配置", "components": "核心组件启用配置", "no_reply": "不回复动作配置", "emoji": "表情动作配置", @@ -360,12 +360,7 @@ class CoreActionsPlugin(BasePlugin): # 配置Schema定义 config_schema = { "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="是否启用插件"), - "description": ConfigField( - type=str, default="系统核心动作插件,提供基础聊天交互功能", description="插件描述", required=True - ), }, "components": { "enable_reply": ConfigField(type=bool, default=True, description="是否启用'回复'动作"), diff --git a/template/bot_config_template.toml b/template/bot_config_template.toml index b8aa5936a..348ed1b1c 100644 --- a/template/bot_config_template.toml +++ b/template/bot_config_template.toml @@ -1,5 +1,5 @@ [inner] -version = "2.23.0" +version = "2.24.0" #----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读---- #如果你想要修改配置文件,请在修改后将version的值进行变更 @@ -43,7 +43,7 @@ identity_detail = [ expression_style = "描述麦麦说话的表达风格,表达习惯,例如:(回复尽量简短一些。可以参考贴吧,知乎和微博的回复风格,回复不要浮夸,不要用夸张修辞,平淡一些。不要有额外的符号,尽量简单简短)" enable_expression_learning = false # 是否启用表达学习,麦麦会学习不同群里人类说话风格(群之间不互通) learning_interval = 600 # 学习间隔 单位秒 -selection_mode = "llm" # 专注模式下 表达方式选择模式:'llm' 使用LLM智能选择,'random' 使用传统随机选择 +selection_mode = "random" # 专注模式下 表达方式选择模式:'llm' 使用LLM智能选择,'random' 使用传统随机选择 [relationship] enable_relationship = true # 是否启用关系系统 @@ -320,12 +320,12 @@ temp = 0.2 [model.lpmm_qa] # 问答模型 -name = "Pro/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B" +name = "Qwen/Qwen3-30B-A3B" provider = "SILICONFLOW" -pri_in = 4.0 -pri_out = 16.0 +pri_in = 0.7 +pri_out = 2.8 temp = 0.7 - +enable_thinking = false # 是否启用思考 [maim_message] auth_token = [] # 认证令牌,用于API验证,为空则不启用验证