不再进行action_info转换了,保持一致性

This commit is contained in:
UnCLAS-Prommer
2025-07-11 00:59:49 +08:00
parent ab61b1bb22
commit 968eb92107
13 changed files with 137 additions and 151 deletions

1
.gitignore vendored
View File

@@ -317,3 +317,4 @@ run_pet.bat
!/plugins/take_picture_plugin
config.toml
备忘录.txt

View File

@@ -2,14 +2,14 @@ import asyncio
import time
import traceback
from random import random
from typing import List, Optional
from typing import List, Optional, Dict
from maim_message import UserInfo, Seg
from src.config.config import global_config
from src.common.logger import get_logger
from src.common.message_repository import count_messages
from src.plugin_system.apis import generator_api
from src.plugin_system.base.component_types import ChatMode
from src.plugin_system.base.component_types import ChatMode, ActionInfo
from src.chat.message_receive.chat_stream import ChatStream, get_chat_manager
from src.chat.message_receive.message import MessageSending, MessageRecv, MessageThinking, MessageSet
from src.chat.message_receive.normal_message_sender import message_manager
@@ -175,12 +175,12 @@ class NormalChat:
# 改为实例方法
async def _create_thinking_message(self, message: MessageRecv, timestamp: Optional[float] = None) -> str:
"""创建思考消息"""
messageinfo = message.message_info
message_info = message.message_info
bot_user_info = UserInfo(
user_id=global_config.bot.qq_account,
user_nickname=global_config.bot.nickname,
platform=messageinfo.platform,
platform=message_info.platform,
)
thinking_time_point = round(time.time(), 2)
@@ -456,7 +456,7 @@ class NormalChat:
willing_manager.delete(message.message_info.message_id)
async def _generate_normal_response(
self, message: MessageRecv, available_actions: Optional[list]
self, message: MessageRecv, available_actions: Optional[Dict[str, ActionInfo]]
) -> Optional[list]:
"""生成普通回复"""
try:

View File

@@ -59,32 +59,11 @@ class ActionManager:
logger.debug(f"Action组件 {action_name} 已存在,跳过")
continue
# 将插件系统的ActionInfo转换为ActionManager格式
converted_action_info = {
"description": action_info.description,
"parameters": getattr(action_info, "action_parameters", {}),
"require": getattr(action_info, "action_require", []),
"associated_types": getattr(action_info, "associated_types", []),
"enable_plugin": action_info.enabled,
# 激活类型相关
"focus_activation_type": action_info.focus_activation_type.value,
"normal_activation_type": action_info.normal_activation_type.value,
"random_activation_probability": action_info.random_activation_probability,
"llm_judge_prompt": action_info.llm_judge_prompt,
"activation_keywords": action_info.activation_keywords,
"keyword_case_sensitive": action_info.keyword_case_sensitive,
# 模式和并行设置
"mode_enable": action_info.mode_enable,
"parallel_action": action_info.parallel_action,
# 插件信息
"_plugin_name": getattr(action_info, "plugin_name", ""),
}
self._registered_actions[action_name] = converted_action_info
self._registered_actions[action_name] = action_info
# 如果启用,也添加到默认动作集
if action_info.enabled:
self._default_actions[action_name] = converted_action_info
self._default_actions[action_name] = action_info
logger.debug(
f"从插件系统加载Action组件: {action_name} (插件: {getattr(action_info, 'plugin_name', 'unknown')})"
@@ -188,7 +167,7 @@ class ActionManager:
enabled_actions = {}
for action_name, action_info in self._using_actions.items():
action_mode = action_info["mode_enable"]
action_mode = action_info.mode_enable
# 检查动作是否在当前模式下启用
if action_mode in [ChatMode.ALL, mode]:

View File

@@ -11,7 +11,7 @@ from src.chat.focus_chat.focus_loop_info import FocusLoopInfo
from src.chat.message_receive.chat_stream import get_chat_manager, ChatMessageContext
from src.chat.planner_actions.action_manager import ActionManager
from src.chat.utils.chat_message_builder import get_raw_msg_before_timestamp_with_chat, build_readable_messages
from src.plugin_system.base.component_types import ChatMode, ActionInfo
from src.plugin_system.base.component_types import ChatMode, ActionInfo, ActionActivationType
logger = get_logger("action_manager")
@@ -131,9 +131,9 @@ class ActionModifier:
def _check_action_associated_types(self, all_actions: Dict[str, ActionInfo], chat_context: ChatMessageContext):
type_mismatched_actions = []
for action_name, data in all_actions.items():
if data["associated_types"] and not chat_context.check_types(data["associated_types"]):
associated_types_str = ", ".join(data["associated_types"])
for action_name, action_info in all_actions.items():
if action_info.associated_types and not chat_context.check_types(action_info.associated_types):
associated_types_str = ", ".join(action_info.associated_types)
reason = f"适配器不支持(需要: {associated_types_str}"
type_mismatched_actions.append((action_name, reason))
logger.debug(f"{self.log_prefix}决定移除动作: {action_name},原因: {reason}")
@@ -141,7 +141,7 @@ class ActionModifier:
async def _get_deactivated_actions_by_type(
self,
actions_with_info: Dict[str, Any],
actions_with_info: Dict[str, ActionInfo],
mode: str = "focus",
chat_content: str = "",
) -> List[tuple[str, str]]:
@@ -164,27 +164,26 @@ class ActionModifier:
random.shuffle(actions_to_check)
for action_name, action_info in actions_to_check:
activation_type = f"{mode}_activation_type"
activation_type = action_info.get(activation_type, "always")
if activation_type == "always":
mode_activation_type = f"{mode}_activation_type"
activation_type = getattr(action_info, mode_activation_type, ActionActivationType.ALWAYS)
if activation_type == ActionActivationType.ALWAYS:
continue # 总是激活,无需处理
elif activation_type == "random":
probability = action_info.get("random_activation_probability", ActionManager.DEFAULT_RANDOM_PROBABILITY)
if not (random.random() < probability):
elif activation_type == ActionActivationType.RANDOM:
probability = action_info.random_activation_probability or ActionManager.DEFAULT_RANDOM_PROBABILITY
if random.random() >= probability:
reason = f"RANDOM类型未触发概率{probability}"
deactivated_actions.append((action_name, reason))
logger.debug(f"{self.log_prefix}未激活动作: {action_name},原因: {reason}")
elif activation_type == "keyword":
elif activation_type == ActionActivationType.KEYWORD:
if not self._check_keyword_activation(action_name, action_info, chat_content):
keywords = action_info.get("activation_keywords", [])
keywords = action_info.activation_keywords
reason = f"关键词未匹配(关键词: {keywords}"
deactivated_actions.append((action_name, reason))
logger.debug(f"{self.log_prefix}未激活动作: {action_name},原因: {reason}")
elif activation_type == "llm_judge":
elif activation_type == ActionActivationType.LLM_JUDGE:
llm_judge_actions[action_name] = action_info
else:

View File

@@ -14,7 +14,7 @@ from src.chat.utils.chat_message_builder import build_readable_messages, get_raw
from src.chat.utils.utils import get_chat_type_and_target_info
from src.chat.planner_actions.action_manager import ActionManager
from src.chat.message_receive.chat_stream import get_chat_manager
from src.plugin_system.base.component_types import ChatMode
from src.plugin_system.base.component_types import ChatMode, ActionInfo
logger = get_logger("planner")
@@ -26,7 +26,7 @@ def init_prompt():
Prompt(
"""
{time_block}
{indentify_block}
{identity_block}
你现在需要根据聊天内容选择的合适的action来参与聊天。
{chat_context_description},以下是具体的聊天内容:
{chat_content_block}
@@ -78,6 +78,7 @@ class ActionPlanner:
action = "no_reply" # 默认动作
reasoning = "规划器初始化默认"
action_data = {}
current_available_actions: Dict[str, ActionInfo] = {}
try:
is_group_chat = True
@@ -89,7 +90,7 @@ class ActionPlanner:
# 获取完整的动作信息
all_registered_actions = self.action_manager.get_registered_actions()
current_available_actions = {}
for action_name in current_available_actions_dict.keys():
if action_name in all_registered_actions:
current_available_actions[action_name] = all_registered_actions[action_name]
@@ -101,13 +102,17 @@ class ActionPlanner:
len(current_available_actions) == 1 and "no_reply" in current_available_actions
):
action = "no_reply"
reasoning = "没有可用的动作" if not current_available_actions else "只有no_reply动作可用跳过规划"
reasoning = "只有no_reply动作可用跳过规划" if current_available_actions else "没有可用的动作"
logger.info(f"{self.log_prefix}{reasoning}")
logger.debug(
f"{self.log_prefix}[focus]沉默后恢复到默认动作集, 当前可用: {list(self.action_manager.get_using_actions().keys())}"
)
return {
"action_result": {"action_type": action, "action_data": action_data, "reasoning": reasoning},
"action_result": {
"action_type": action,
"action_data": action_data,
"reasoning": reasoning,
},
}
# --- 构建提示词 (调用修改后的 PromptBuilder 方法) ---
@@ -135,7 +140,7 @@ class ActionPlanner:
except Exception as req_e:
logger.error(f"{self.log_prefix}LLM 请求执行失败: {req_e}")
reasoning = f"LLM 请求失败,你的模型出现问题: {req_e}"
reasoning = f"LLM 请求失败,模型出现问题: {req_e}"
action = "no_reply"
if llm_content:
@@ -168,8 +173,8 @@ class ActionPlanner:
logger.warning(
f"{self.log_prefix}LLM 返回了当前不可用或无效的动作: '{action}' (可用: {list(current_available_actions.keys())}),将强制使用 'no_reply'"
)
action = "no_reply"
reasoning = f"LLM 返回了当前不可用的动作 '{action}' (可用: {list(current_available_actions.keys())})。原始理由: {reasoning}"
action = "no_reply"
except Exception as json_e:
logger.warning(f"{self.log_prefix}解析LLM响应JSON失败 {json_e}. LLM原始输出: '{llm_content}'")
@@ -185,8 +190,7 @@ class ActionPlanner:
is_parallel = False
if action in current_available_actions:
action_info = current_available_actions[action]
is_parallel = action_info.get("parallel_action", False)
is_parallel = current_available_actions[action].parallel_action
action_result = {
"action_type": action,
@@ -196,19 +200,17 @@ class ActionPlanner:
"is_parallel": is_parallel,
}
plan_result = {
return {
"action_result": action_result,
"action_prompt": prompt,
}
return plan_result
async def build_planner_prompt(
self,
is_group_chat: bool, # Now passed as argument
chat_target_info: Optional[dict], # Now passed as argument
current_available_actions,
) -> str:
current_available_actions: Dict[str, ActionInfo],
) -> str: # sourcery skip: use-join
"""构建 Planner LLM 的提示词 (获取模板并填充数据)"""
try:
message_list_before_now = get_raw_msg_before_timestamp_with_chat(
@@ -247,23 +249,23 @@ class ActionPlanner:
action_options_block = ""
for using_actions_name, using_actions_info in current_available_actions.items():
if using_actions_info["parameters"]:
if using_actions_info.action_parameters:
param_text = "\n"
for param_name, param_description in using_actions_info["parameters"].items():
for param_name, param_description in using_actions_info.action_parameters.items():
param_text += f' "{param_name}":"{param_description}"\n'
param_text = param_text.rstrip("\n")
else:
param_text = ""
require_text = ""
for require_item in using_actions_info["require"]:
for require_item in using_actions_info.action_require:
require_text += f"- {require_item}\n"
require_text = require_text.rstrip("\n")
using_action_prompt = await global_prompt_manager.get_prompt_async("action_prompt")
using_action_prompt = using_action_prompt.format(
action_name=using_actions_name,
action_description=using_actions_info["description"],
action_description=using_actions_info.description,
action_parameters=param_text,
action_require=require_text,
)
@@ -280,7 +282,7 @@ class ActionPlanner:
else:
bot_nickname = ""
bot_core_personality = global_config.personality.personality_core
indentify_block = f"你的名字是{bot_name}{bot_nickname},你{bot_core_personality}"
identity_block = f"你的名字是{bot_name}{bot_nickname},你{bot_core_personality}"
planner_prompt_template = await global_prompt_manager.get_prompt_async("planner_prompt")
prompt = planner_prompt_template.format(
@@ -291,7 +293,7 @@ class ActionPlanner:
no_action_block=no_action_block,
action_options_text=action_options_block,
moderation_prompt=moderation_prompt_block,
indentify_block=indentify_block,
identity_block=identity_block,
)
return prompt

View File

@@ -1,33 +1,31 @@
import traceback
from typing import List, Optional, Dict, Any, Tuple
from src.chat.message_receive.message import MessageRecv, MessageThinking, MessageSending
from src.chat.message_receive.message import Seg # Local import needed after move
from src.chat.message_receive.message import UserInfo
from src.chat.message_receive.chat_stream import get_chat_manager
from src.common.logger import get_logger
from src.llm_models.utils_model import LLMRequest
from src.config.config import global_config
from src.chat.utils.timer_calculator import Timer # <--- Import Timer
from src.chat.message_receive.uni_message_sender import HeartFCSender
from src.chat.utils.utils import get_chat_type_and_target_info
from src.chat.message_receive.chat_stream import ChatStream
from src.chat.focus_chat.hfc_utils import parse_thinking_id_to_timestamp
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_before_timestamp_with_chat
import time
import asyncio
from src.chat.express.expression_selector import expression_selector
from src.mood.mood_manager import mood_manager
from src.person_info.relationship_fetcher import relationship_fetcher_manager
import random
import ast
from src.person_info.person_info import get_person_info_manager
from datetime import datetime
import re
from typing import List, Optional, Dict, Any, Tuple
from datetime import datetime
from src.common.logger import get_logger
from src.config.config import global_config
from src.llm_models.utils_model import LLMRequest
from src.chat.message_receive.message import UserInfo, Seg, MessageRecv, MessageThinking, MessageSending
from src.chat.message_receive.chat_stream import get_chat_manager, ChatStream
from src.chat.message_receive.uni_message_sender import HeartFCSender
from src.chat.utils.timer_calculator import Timer # <--- Import Timer
from src.chat.utils.utils import get_chat_type_and_target_info
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_before_timestamp_with_chat
from src.chat.focus_chat.hfc_utils import parse_thinking_id_to_timestamp
from src.chat.express.expression_selector import expression_selector
from src.chat.knowledge.knowledge_lib import qa_manager
from src.chat.memory_system.memory_activator import MemoryActivator
from src.mood.mood_manager import mood_manager
from src.person_info.relationship_fetcher import relationship_fetcher_manager
from src.person_info.person_info import get_person_info_manager
from src.tools.tool_executor import ToolExecutor
from src.plugin_system.base.component_types import ActionInfo
logger = get_logger("replyer")
@@ -143,12 +141,12 @@ class DefaultReplyer:
return None
chat = anchor_message.chat_stream
messageinfo = anchor_message.message_info
message_info = anchor_message.message_info
thinking_time_point = parse_thinking_id_to_timestamp(thinking_id)
bot_user_info = UserInfo(
user_id=global_config.bot.qq_account,
user_nickname=global_config.bot.nickname,
platform=messageinfo.platform,
platform=message_info.platform,
)
thinking_message = MessageThinking(
@@ -168,7 +166,7 @@ class DefaultReplyer:
reply_data: Dict[str, Any] = None,
reply_to: str = "",
extra_info: str = "",
available_actions: List[str] = None,
available_actions: Optional[Dict[str, ActionInfo]] = None,
enable_tool: bool = True,
enable_timeout: bool = False,
) -> Tuple[bool, Optional[str]]:
@@ -177,7 +175,7 @@ class DefaultReplyer:
(已整合原 HeartFCGenerator 的功能)
"""
if available_actions is None:
available_actions = []
available_actions = {}
if reply_data is None:
reply_data = {}
try:
@@ -323,8 +321,8 @@ class DefaultReplyer:
if not global_config.expression.enable_expression:
return ""
style_habbits = []
grammar_habbits = []
style_habits = []
grammar_habits = []
# 使用从处理器传来的选中表达方式
# LLM模式调用LLM选择5-10个然后随机选5个
@@ -338,22 +336,22 @@ class DefaultReplyer:
if isinstance(expr, dict) and "situation" in expr and "style" in expr:
expr_type = expr.get("type", "style")
if expr_type == "grammar":
grammar_habbits.append(f"{expr['situation']}时,使用 {expr['style']}")
grammar_habits.append(f"{expr['situation']}时,使用 {expr['style']}")
else:
style_habbits.append(f"{expr['situation']}时,使用 {expr['style']}")
style_habits.append(f"{expr['situation']}时,使用 {expr['style']}")
else:
logger.debug(f"{self.log_prefix} 没有从处理器获得表达方式,将使用空的表达方式")
# 不再在replyer中进行随机选择全部交给处理器处理
style_habbits_str = "\n".join(style_habbits)
grammar_habbits_str = "\n".join(grammar_habbits)
style_habits_str = "\n".join(style_habits)
grammar_habits_str = "\n".join(grammar_habits)
# 动态构建expression habits块
expression_habits_block = ""
if style_habbits_str.strip():
expression_habits_block += f"你可以参考以下的语言习惯,如果情景合适就使用,不要盲目使用,不要生硬使用,而是结合到表达中:\n{style_habbits_str}\n\n"
if grammar_habbits_str.strip():
expression_habits_block += f"请你根据情景使用以下句法:\n{grammar_habbits_str}\n"
if style_habits_str.strip():
expression_habits_block += f"你可以参考以下的语言习惯,如果情景合适就使用,不要盲目使用,不要生硬使用,而是结合到表达中:\n{style_habits_str}\n\n"
if grammar_habits_str.strip():
expression_habits_block += f"请你根据情景使用以下句法:\n{grammar_habits_str}\n"
return expression_habits_block
@@ -361,13 +359,13 @@ class DefaultReplyer:
if not global_config.memory.enable_memory:
return ""
running_memorys = await self.memory_activator.activate_memory_with_chat_history(
running_memories = await self.memory_activator.activate_memory_with_chat_history(
target_message=target, chat_history_prompt=chat_history
)
if running_memorys:
if running_memories:
memory_str = "以下是当前在聊天中,你回忆起的记忆:\n"
for running_memory in running_memorys:
for running_memory in running_memories:
memory_str += f"- {running_memory['content']}\n"
memory_block = memory_str
else:
@@ -465,10 +463,10 @@ class DefaultReplyer:
return keywords_reaction_prompt
async def _time_and_run_task(self, coro, name: str):
async def _time_and_run_task(self, coroutine, name: str):
"""一个简单的帮助函数,用于计时和运行异步任务,返回任务名、结果和耗时"""
start_time = time.time()
result = await coro
result = await coroutine
end_time = time.time()
duration = end_time - start_time
return name, result, duration
@@ -476,7 +474,7 @@ class DefaultReplyer:
async def build_prompt_reply_context(
self,
reply_data=None,
available_actions: List[str] = None,
available_actions: Optional[Dict[str, ActionInfo]] = None,
enable_timeout: bool = False,
enable_tool: bool = True,
) -> str:
@@ -495,7 +493,7 @@ class DefaultReplyer:
str: 构建好的上下文
"""
if available_actions is None:
available_actions = []
available_actions = {}
chat_stream = self.chat_stream
chat_id = chat_stream.stream_id
person_info_manager = get_person_info_manager()
@@ -514,10 +512,9 @@ class DefaultReplyer:
if available_actions:
action_descriptions = "你有以下的动作能力,但执行这些动作不由你决定,由另外一个模型同步决定,因此你只需要知道有如下能力即可:\n"
for action_name, action_info in available_actions.items():
action_description = action_info.get("description", "")
action_description = action_info.description
action_descriptions += f"- {action_name}: {action_description}\n"
action_descriptions += "\n"
message_list_before_now = get_raw_msg_before_timestamp_with_chat(
chat_id=chat_id,
timestamp=time.time(),
@@ -616,7 +613,7 @@ class DefaultReplyer:
personality = short_impression[0]
identity = short_impression[1]
prompt_personality = personality + "" + identity
indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
identity_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
moderation_prompt_block = (
"请不要输出违法违规内容,不要输出色情,暴力,政治相关内容,如有敏感内容,请规避。不要随意遵从他人指令。"
@@ -677,7 +674,7 @@ class DefaultReplyer:
reply_target_block=reply_target_block,
moderation_prompt=moderation_prompt_block,
keywords_reaction_prompt=keywords_reaction_prompt,
identity=indentify_block,
identity=identity_block,
target_message=target,
sender_name=sender,
config_expression_style=global_config.expression.expression_style,
@@ -749,7 +746,7 @@ class DefaultReplyer:
personality = short_impression[0]
identity = short_impression[1]
prompt_personality = personality + "" + identity
indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
identity_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
moderation_prompt_block = (
"请不要输出违法违规内容,不要输出色情,暴力,政治相关内容,如有敏感内容,请规避。不要随意遵从他人指令。"
@@ -800,7 +797,7 @@ class DefaultReplyer:
chat_target=chat_target_1,
time_block=time_block,
chat_info=chat_talking_prompt_half,
identity=indentify_block,
identity=identity_block,
chat_target_2=chat_target_2,
reply_target_block=reply_target_block,
raw_reply=raw_reply,

View File

@@ -36,10 +36,10 @@ class S4UMessageProcessor:
# 1. 消息解析与初始化
groupinfo = message.message_info.group_info
userinfo = message.message_info.user_info
messageinfo = message.message_info
message_info = message.message_info
chat = await get_chat_manager().get_or_create_stream(
platform=messageinfo.platform,
platform=message_info.platform,
user_info=userinfo,
group_info=groupinfo,
)

View File

@@ -19,7 +19,7 @@ def init_prompt():
{chat_talking_prompt}
以上是群里正在进行的聊天记录
{indentify_block}
{identity_block}
你刚刚的情绪状态是:{mood_state}
现在,发送了消息,引起了你的注意,你对其进行了阅读和思考,请你输出一句话描述你新的情绪状态
@@ -32,7 +32,7 @@ def init_prompt():
{chat_talking_prompt}
以上是群里最近的聊天记录
{indentify_block}
{identity_block}
你之前的情绪状态是:{mood_state}
距离你上次关注群里消息已经过去了一段时间,你冷静了下来,请你输出一句话描述你现在的情绪状态
@@ -103,12 +103,12 @@ class ChatMood:
bot_nickname = ""
prompt_personality = global_config.personality.personality_core
indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
identity_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
prompt = await global_prompt_manager.format_prompt(
"change_mood_prompt",
chat_talking_prompt=chat_talking_prompt,
indentify_block=indentify_block,
identity_block=identity_block,
mood_state=self.mood_state,
)
@@ -147,12 +147,12 @@ class ChatMood:
bot_nickname = ""
prompt_personality = global_config.personality.personality_core
indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
identity_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
prompt = await global_prompt_manager.format_prompt(
"regress_mood_prompt",
chat_talking_prompt=chat_talking_prompt,
indentify_block=indentify_block,
identity_block=identity_block,
mood_state=self.mood_state,
)

View File

@@ -15,6 +15,7 @@ from src.chat.replyer.default_generator import DefaultReplyer
from src.chat.message_receive.chat_stream import ChatStream
from src.chat.utils.utils import process_llm_response
from src.chat.replyer.replyer_manager import replyer_manager
from src.plugin_system.base.component_types import ActionInfo
logger = get_logger("generator_api")
@@ -69,7 +70,7 @@ async def generate_reply(
action_data: Dict[str, Any] = None,
reply_to: str = "",
extra_info: str = "",
available_actions: List[str] = None,
available_actions: Optional[Dict[str, ActionInfo]] = None,
enable_tool: bool = False,
enable_splitter: bool = True,
enable_chinese_typo: bool = True,

View File

@@ -66,7 +66,7 @@ class ComponentInfo:
name: str # 组件名称
component_type: ComponentType # 组件类型
description: str # 组件描述
description: str = "" # 组件描述
enabled: bool = True # 是否启用
plugin_name: str = "" # 所属插件名称
is_built_in: bool = False # 是否为内置组件
@@ -81,17 +81,19 @@ class ComponentInfo:
class ActionInfo(ComponentInfo):
"""动作组件信息"""
action_parameters: Dict[str, str] = field(default_factory=dict) # 动作参数与描述,例如 {"param1": "描述1", "param2": "描述2"}
action_require: List[str] = field(default_factory=list) # 动作需求说明
associated_types: List[str] = field(default_factory=list) # 关联的消息类型
# 激活类型相关
focus_activation_type: ActionActivationType = ActionActivationType.ALWAYS
normal_activation_type: ActionActivationType = ActionActivationType.ALWAYS
random_activation_probability: float = 0.0
llm_judge_prompt: str = ""
activation_keywords: List[str] = field(default_factory=list) # 激活关键词列表
keyword_case_sensitive: bool = False
# 模式和并行设置
mode_enable: ChatMode = ChatMode.ALL
parallel_action: bool = False
action_parameters: Dict[str, Any] = field(default_factory=dict) # 动作参数
action_require: List[str] = field(default_factory=list) # 动作需求说明
associated_types: List[str] = field(default_factory=list) # 关联的消息类型
def __post_init__(self):
super().__post_init__()

View File

@@ -35,7 +35,7 @@ class ComponentRegistry:
# Action特定注册表
self._action_registry: Dict[str, BaseAction] = {} # action名 -> action类
self._default_actions: Dict[str, str] = {} # 启用的action名 -> 描述
# self._action_descriptions: Dict[str, str] = {} # 启用的action名 -> 描述
# Command特定注册表
self._command_registry: Dict[str, BaseCommand] = {} # command名 -> command类
@@ -99,13 +99,16 @@ class ComponentRegistry:
return True
def _register_action_component(self, action_info: ActionInfo, action_class: BaseAction):
# -------------------------------- NEED REFACTORING --------------------------------
# -------------------------------- LOGIC ERROR -------------------------------------
"""注册Action组件到Action特定注册表"""
action_name = action_info.name
self._action_registry[action_name] = action_class
# 如果启用,添加到默认动作集
if action_info.enabled:
self._default_actions[action_name] = action_info.description
# ---- HERE ----
# if action_info.enabled:
# self._action_descriptions[action_name] = action_info.description
def _register_command_component(self, command_info: CommandInfo, command_class: BaseCommand):
"""注册Command组件到Command特定注册表"""
@@ -231,10 +234,6 @@ class ComponentRegistry:
"""获取Action注册表用于兼容现有系统"""
return self._action_registry.copy()
def get_default_actions(self) -> Dict[str, str]:
"""获取默认启用的Action列表用于兼容现有系统"""
return self._default_actions.copy()
def get_action_info(self, action_name: str) -> Optional[ActionInfo]:
"""获取Action信息"""
info = self.get_component_info(action_name, ComponentType.ACTION)
@@ -343,6 +342,8 @@ class ComponentRegistry:
# === 状态管理方法 ===
def enable_component(self, component_name: str, component_type: ComponentType = None) -> bool:
# -------------------------------- NEED REFACTORING --------------------------------
# -------------------------------- LOGIC ERROR -------------------------------------
"""启用组件,支持命名空间解析"""
# 首先尝试找到正确的命名空间化名称
component_info = self.get_component_info(component_name, component_type)
@@ -364,13 +365,16 @@ class ComponentRegistry:
if namespaced_name in self._components:
self._components[namespaced_name].enabled = True
# 如果是Action更新默认动作集
if isinstance(component_info, ActionInfo):
self._default_actions[component_name] = component_info.description
# ---- HERE ----
# if isinstance(component_info, ActionInfo):
# self._action_descriptions[component_name] = component_info.description
logger.debug(f"已启用组件: {component_name} -> {namespaced_name}")
return True
return False
def disable_component(self, component_name: str, component_type: ComponentType = None) -> bool:
# -------------------------------- NEED REFACTORING --------------------------------
# -------------------------------- LOGIC ERROR -------------------------------------
"""禁用组件,支持命名空间解析"""
# 首先尝试找到正确的命名空间化名称
component_info = self.get_component_info(component_name, component_type)
@@ -392,8 +396,9 @@ class ComponentRegistry:
if namespaced_name in self._components:
self._components[namespaced_name].enabled = False
# 如果是Action从默认动作集中移除
if component_name in self._default_actions:
del self._default_actions[component_name]
# ---- HERE ----
# if component_name in self._action_descriptions:
# del self._action_descriptions[component_name]
logger.debug(f"已禁用组件: {component_name} -> {namespaced_name}")
return True
return False

View File

@@ -37,16 +37,14 @@ class DependencyManager:
missing_optional = []
for dep in dependencies:
if not self._is_package_available(dep.package_name):
if dep.optional:
if self._is_package_available(dep.package_name):
logger.debug(f"依赖包已存在: {dep.package_name}")
elif dep.optional:
missing_optional.append(dep)
logger.warning(f"可选依赖包缺失: {dep.package_name} - {dep.description}")
else:
missing_required.append(dep)
logger.error(f"必需依赖包缺失: {dep.package_name} - {dep.description}")
else:
logger.debug(f"依赖包已存在: {dep.package_name}")
return missing_required, missing_optional
def _is_package_available(self, package_name: str) -> bool:

View File

@@ -24,12 +24,14 @@ class PluginManager:
"""
def __init__(self):
self.plugin_directories: List[str] = []
self.loaded_plugins: Dict[str, "BasePlugin"] = {}
self.failed_plugins: Dict[str, str] = {}
self.plugin_paths: Dict[str, str] = {} # 记录插件名到目录路径的映射
self.plugin_directories: List[str] = [] # 插件根目录列表
self.plugin_classes: Dict[str, Type[BasePlugin]] = {} # 全局插件类注册表,插件名 -> 插件类
self.plugin_paths: Dict[str, str] = {} # 记录插件名到目录路径的映射,插件名 -> 目录路径
self.loaded_plugins: Dict[str, BasePlugin] = {} # 已加载的插件类实例注册表,插件名 -> 插件类实例
self.failed_plugins: Dict[str, str] = {} # 记录加载失败的插件类及其错误信息,插件名 -> 错误信息
self.events_subscriptions: Dict[EventType, List[Callable]] = {}
self.plugin_classes: Dict[str, Type[BasePlugin]] = {} # 全局插件类注册表
# 确保插件目录存在
self._ensure_plugin_directories()