Merge branch 'dev' of https://github.com/MoFox-Studio/MoFox_Bot into dev
This commit is contained in:
@@ -362,7 +362,7 @@ class ChatterPlanFilter:
|
||||
return "最近没有聊天内容。", "没有未读消息。", []
|
||||
|
||||
stream_context = chat_stream.context_manager
|
||||
|
||||
|
||||
# 获取真正的已读和未读消息
|
||||
read_messages = stream_context.context.history_messages # 已读消息存储在history_messages中
|
||||
if not read_messages:
|
||||
@@ -652,30 +652,30 @@ class ChatterPlanFilter:
|
||||
if not action_info:
|
||||
logger.debug(f"动作 {action_name} 不在可用动作列表中,保留所有参数")
|
||||
return action_data
|
||||
|
||||
|
||||
# 获取该动作定义的合法参数
|
||||
defined_params = set(action_info.action_parameters.keys())
|
||||
|
||||
|
||||
# 合法参数集合
|
||||
valid_params = defined_params
|
||||
|
||||
|
||||
# 过滤参数
|
||||
filtered_data = {}
|
||||
removed_params = []
|
||||
|
||||
|
||||
for key, value in action_data.items():
|
||||
if key in valid_params:
|
||||
filtered_data[key] = value
|
||||
else:
|
||||
removed_params.append(key)
|
||||
|
||||
|
||||
# 记录被移除的参数
|
||||
if removed_params:
|
||||
logger.info(
|
||||
f"🧹 [参数过滤] 动作 '{action_name}' 移除了多余参数: {removed_params}. "
|
||||
f"合法参数: {sorted(valid_params)}"
|
||||
)
|
||||
|
||||
|
||||
return filtered_data
|
||||
|
||||
def _filter_no_actions(self, action_list: list[ActionPlannerInfo]) -> list[ActionPlannerInfo]:
|
||||
|
||||
@@ -545,14 +545,14 @@ async def execute_proactive_thinking(stream_id: str):
|
||||
# 获取或创建该聊天流的执行锁
|
||||
if stream_id not in _execution_locks:
|
||||
_execution_locks[stream_id] = asyncio.Lock()
|
||||
|
||||
|
||||
lock = _execution_locks[stream_id]
|
||||
|
||||
|
||||
# 尝试获取锁,如果已被占用则跳过本次执行(防止重复)
|
||||
if lock.locked():
|
||||
logger.warning(f"⚠️ 主动思考跳过:聊天流 {stream_id} 已有正在执行的主动思考任务")
|
||||
return
|
||||
|
||||
|
||||
async with lock:
|
||||
logger.debug(f"🤔 开始主动思考 {stream_id}")
|
||||
|
||||
@@ -563,13 +563,13 @@ async def execute_proactive_thinking(stream_id: str):
|
||||
from src.chat.message_receive.chat_stream import get_chat_manager
|
||||
chat_manager = get_chat_manager()
|
||||
chat_stream = await chat_manager.get_stream(stream_id)
|
||||
|
||||
|
||||
if chat_stream and chat_stream.context_manager.context.is_chatter_processing:
|
||||
logger.warning(f"⚠️ 主动思考跳过:聊天流 {stream_id} 的 chatter 正在处理消息")
|
||||
return
|
||||
except Exception as e:
|
||||
logger.warning(f"检查 chatter 处理状态时出错: {e},继续执行")
|
||||
|
||||
|
||||
# 0.1 检查白名单/黑名单
|
||||
# 从 stream_id 获取 stream_config 字符串进行验证
|
||||
try:
|
||||
|
||||
@@ -31,4 +31,4 @@ __plugin_meta__ = PluginMetadata(
|
||||
# 导入插件主类
|
||||
from .plugin import AntiInjectionPlugin
|
||||
|
||||
__all__ = ["__plugin_meta__", "AntiInjectionPlugin"]
|
||||
__all__ = ["AntiInjectionPlugin", "__plugin_meta__"]
|
||||
|
||||
@@ -8,8 +8,8 @@ import time
|
||||
|
||||
from src.chat.security.interfaces import (
|
||||
SecurityAction,
|
||||
SecurityCheckResult,
|
||||
SecurityChecker,
|
||||
SecurityCheckResult,
|
||||
SecurityLevel,
|
||||
)
|
||||
from src.common.logger import get_logger
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
处理检测结果,执行相应的动作(允许/监控/加盾/阻止/反击)。
|
||||
"""
|
||||
|
||||
from src.chat.security.interfaces import SecurityAction, SecurityCheckResult
|
||||
from src.chat.security.interfaces import SecurityCheckResult
|
||||
from src.common.logger import get_logger
|
||||
|
||||
from .counter_attack import CounterAttackGenerator
|
||||
|
||||
@@ -64,15 +64,15 @@ class CoreActionsPlugin(BasePlugin):
|
||||
|
||||
# --- 根据配置注册组件 ---
|
||||
components: ClassVar = []
|
||||
|
||||
|
||||
# 注册 reply 动作
|
||||
if self.get_config("components.enable_reply", True):
|
||||
components.append((ReplyAction.get_action_info(), ReplyAction))
|
||||
|
||||
|
||||
# 注册 respond 动作
|
||||
if self.get_config("components.enable_respond", True):
|
||||
components.append((RespondAction.get_action_info(), RespondAction))
|
||||
|
||||
|
||||
# 注册 emoji 动作
|
||||
if self.get_config("components.enable_emoji", True):
|
||||
components.append((EmojiAction.get_action_info(), EmojiAction))
|
||||
|
||||
@@ -22,23 +22,23 @@ class ReplyAction(BaseAction):
|
||||
- 专注于理解和回应单条消息的具体内容
|
||||
- 适合 Focus 模式下的精准回复
|
||||
"""
|
||||
|
||||
|
||||
# 动作基本信息
|
||||
action_name = "reply"
|
||||
action_description = "针对特定消息进行精准回复。深度理解并回应单条消息的具体内容。需要指定目标消息ID。"
|
||||
|
||||
|
||||
# 激活设置
|
||||
activation_type = ActionActivationType.ALWAYS # 回复动作总是可用
|
||||
mode_enable = ChatMode.ALL # 在所有模式下都可用
|
||||
parallel_action = False # 回复动作不能与其他动作并行
|
||||
|
||||
|
||||
# 动作参数定义
|
||||
action_parameters: ClassVar = {
|
||||
"target_message_id": "要回复的目标消息ID(必需,来自未读消息的 <m...> 标签)",
|
||||
"content": "回复的具体内容(可选,由LLM生成)",
|
||||
"should_quote_reply": "是否引用原消息(可选,true/false,默认false。群聊中回复较早消息或需要明确指向时使用true)",
|
||||
}
|
||||
|
||||
|
||||
# 动作使用场景
|
||||
action_require: ClassVar = [
|
||||
"需要针对特定消息进行精准回复时使用",
|
||||
@@ -48,10 +48,10 @@ class ReplyAction(BaseAction):
|
||||
"群聊中需要明确回应某个特定用户或问题时使用",
|
||||
"关注单条消息的具体内容和上下文细节",
|
||||
]
|
||||
|
||||
|
||||
# 关联类型
|
||||
associated_types: ClassVar[list[str]] = ["text"]
|
||||
|
||||
|
||||
async def execute(self) -> tuple[bool, str]:
|
||||
"""执行reply动作
|
||||
|
||||
@@ -70,21 +70,21 @@ class RespondAction(BaseAction):
|
||||
- 适合对于群聊消息下的宏观回应
|
||||
- 避免与单一用户深度对话而忽略其他用户的消息
|
||||
"""
|
||||
|
||||
|
||||
# 动作基本信息
|
||||
action_name = "respond"
|
||||
action_description = "统一回应所有未读消息。理解整体对话动态和话题走向,生成连贯的回复。无需指定目标消息。"
|
||||
|
||||
|
||||
# 激活设置
|
||||
activation_type = ActionActivationType.ALWAYS # 回应动作总是可用
|
||||
mode_enable = ChatMode.ALL # 在所有模式下都可用
|
||||
parallel_action = False # 回应动作不能与其他动作并行
|
||||
|
||||
|
||||
# 动作参数定义
|
||||
action_parameters: ClassVar = {
|
||||
"content": "回复的具体内容(可选,由LLM生成)",
|
||||
}
|
||||
|
||||
|
||||
# 动作使用场景
|
||||
action_require: ClassVar = [
|
||||
"需要统一回应多条未读消息时使用(Normal 模式专用)",
|
||||
@@ -94,10 +94,10 @@ class RespondAction(BaseAction):
|
||||
"适合群聊中的自然对话流,无需精确指向特定消息",
|
||||
"可以同时回应多个话题或参与者",
|
||||
]
|
||||
|
||||
|
||||
# 关联类型
|
||||
associated_types: ClassVar[list[str]] = ["text"]
|
||||
|
||||
|
||||
async def execute(self) -> tuple[bool, str]:
|
||||
"""执行respond动作
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
import asyncio
|
||||
import base64
|
||||
import datetime
|
||||
import filetype
|
||||
from collections.abc import Callable
|
||||
|
||||
import aiohttp
|
||||
import filetype
|
||||
from maim_message import UserInfo
|
||||
|
||||
from src.chat.message_receive.chat_stream import get_chat_manager
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import re
|
||||
from typing import ClassVar
|
||||
|
||||
from src.chat.utils.prompt_component_manager import prompt_component_manager
|
||||
from src.plugin_system.apis import (
|
||||
plugin_manage_api,
|
||||
)
|
||||
@@ -74,6 +74,7 @@ class SystemCommand(PlusCommand):
|
||||
• `/system permission` - 权限管理
|
||||
• `/system plugin` - 插件管理
|
||||
• `/system schedule` - 定时任务管理
|
||||
• `/system prompt` - 提示词注入管理
|
||||
"""
|
||||
elif target == "schedule":
|
||||
help_text = """📅 定时任务管理帮助
|
||||
@@ -113,8 +114,17 @@ class SystemCommand(PlusCommand):
|
||||
• /system permission nodes [插件名] - 查看权限节点
|
||||
• /system permission allnodes - 查看所有权限节点详情
|
||||
"""
|
||||
await self.send_text(help_text)
|
||||
elif target == "prompt":
|
||||
help_text = """📝 提示词注入管理帮助
|
||||
|
||||
🔎 查询命令 (需要 `system.prompt.view` 权限):
|
||||
• `/system prompt help` - 显示此帮助
|
||||
• `/system prompt map` - 查看全局注入关系图
|
||||
• `/system prompt targets` - 列出所有可被注入的核心提示词
|
||||
• `/system prompt components` - 列出所有已注册的提示词组件
|
||||
• `/system prompt info <目标名>` - 查看特定核心提示词的注入详情
|
||||
"""
|
||||
await self.send_text(help_text)
|
||||
|
||||
# =================================================================
|
||||
# Plugin Management Section
|
||||
@@ -231,6 +241,101 @@ class SystemCommand(PlusCommand):
|
||||
else:
|
||||
await self.send_text(f"❌ 恢复任务失败: `{schedule_id}`")
|
||||
|
||||
# =================================================================
|
||||
# Prompt Management Section
|
||||
# =================================================================
|
||||
async def _handle_prompt_commands(self, args: list[str]):
|
||||
"""处理提示词管理相关命令"""
|
||||
if not args or args[0].lower() in ["help", "帮助"]:
|
||||
await self._show_help("prompt")
|
||||
return
|
||||
|
||||
action = args[0].lower()
|
||||
remaining_args = args[1:]
|
||||
|
||||
if action in ["map", "关系图"]:
|
||||
await self._show_injection_map()
|
||||
elif action in ["targets", "目标"]:
|
||||
await self._list_core_prompts()
|
||||
elif action in ["components", "组件"]:
|
||||
await self._list_prompt_components()
|
||||
elif action in ["info", "详情"] and remaining_args:
|
||||
await self._get_prompt_injection_info(remaining_args[0])
|
||||
else:
|
||||
await self.send_text("❌ 提示词管理命令不合法\n使用 /system prompt help 查看帮助")
|
||||
|
||||
@require_permission("prompt.view", deny_message="❌ 你没有查看提示词注入信息的权限")
|
||||
async def _show_injection_map(self):
|
||||
"""显示全局注入关系图"""
|
||||
injection_map = await prompt_component_manager.get_full_injection_map()
|
||||
if not injection_map:
|
||||
await self.send_text("📊 当前没有任何提示词注入关系")
|
||||
return
|
||||
|
||||
response_parts = ["📊 全局提示词注入关系图:\n"]
|
||||
for target, injections in injection_map.items():
|
||||
if injections:
|
||||
response_parts.append(f"🎯 **{target}** (注入源):")
|
||||
for inj in injections:
|
||||
source_tag = f"({inj['source']})" if inj['source'] != 'static_default' else ''
|
||||
response_parts.append(f" ⎿ `{inj['name']}` (优先级: {inj['priority']}) {source_tag}")
|
||||
else:
|
||||
response_parts.append(f"🎯 **{target}** (无注入)")
|
||||
|
||||
await self._send_long_message("\n".join(response_parts))
|
||||
|
||||
@require_permission("prompt.view", deny_message="❌ 你没有查看提示词注入信息的权限")
|
||||
async def _list_core_prompts(self):
|
||||
"""列出所有可注入的核心提示词"""
|
||||
targets = prompt_component_manager.get_core_prompts()
|
||||
if not targets:
|
||||
await self.send_text("🎯 当前没有可注入的核心提示词")
|
||||
return
|
||||
|
||||
response = "🎯 所有可注入的核心提示词:\n" + "\n".join([f"• `{name}`" for name in targets])
|
||||
await self.send_text(response)
|
||||
|
||||
@require_permission("prompt.view", deny_message="❌ 你没有查看提示词注入信息的权限")
|
||||
async def _list_prompt_components(self):
|
||||
"""列出所有已注册的提示词组件"""
|
||||
components = prompt_component_manager.get_registered_prompt_component_info()
|
||||
if not components:
|
||||
await self.send_text("🧩 当前没有已注册的提示词组件")
|
||||
return
|
||||
|
||||
response_parts = [f"🧩 已注册的提示词组件 (共 {len(components)} 个):"]
|
||||
for comp in components:
|
||||
response_parts.append(f"• `{comp.name}` (来自: `{comp.plugin_name}`)")
|
||||
|
||||
await self._send_long_message("\n".join(response_parts))
|
||||
|
||||
|
||||
@require_permission("prompt.view", deny_message="❌ 你没有查看提示词注入信息的权限")
|
||||
async def _get_prompt_injection_info(self, target_name: str):
|
||||
"""获取特定核心提示词的注入详情"""
|
||||
injections = await prompt_component_manager.get_injections_for_prompt(target_name)
|
||||
|
||||
core_prompts = prompt_component_manager.get_core_prompts()
|
||||
if target_name not in core_prompts:
|
||||
await self.send_text(f"❌ 找不到核心提示词: `{target_name}`")
|
||||
return
|
||||
|
||||
if not injections:
|
||||
await self.send_text(f"🎯 核心提示词 `{target_name}` 当前没有被任何组件注入。")
|
||||
return
|
||||
|
||||
response_parts = [f"🔎 核心提示词 `{target_name}` 的注入详情:"]
|
||||
for inj in injections:
|
||||
response_parts.append(
|
||||
f" • **`{inj['name']}`** (优先级: {inj['priority']})"
|
||||
)
|
||||
response_parts.append(f" - 来源: `{inj['source']}`")
|
||||
response_parts.append(f" - 类型: `{inj['injection_type']}`")
|
||||
if inj.get('target_content'):
|
||||
response_parts.append(f" - 操作目标: `{inj['target_content']}`")
|
||||
|
||||
await self.send_text("\n".join(response_parts))
|
||||
|
||||
# =================================================================
|
||||
# Permission Management Section
|
||||
# =================================================================
|
||||
|
||||
Reference in New Issue
Block a user