增加了组件的全局启用和禁用功能
This commit is contained in:
@@ -46,6 +46,9 @@
|
|||||||
11. 修正了`command`所编译的`Pattern`注册时的错误输出。
|
11. 修正了`command`所编译的`Pattern`注册时的错误输出。
|
||||||
12. `events_manager`有了task相关逻辑了。
|
12. `events_manager`有了task相关逻辑了。
|
||||||
13. 现在有了插件卸载和重载功能了,也就是热插拔。
|
13. 现在有了插件卸载和重载功能了,也就是热插拔。
|
||||||
|
14. 实现了组件的全局启用和禁用功能。
|
||||||
|
- 通过`enable_component`和`disable_component`方法来启用或禁用组件。
|
||||||
|
- 不过这个操作不会保存到配置文件~
|
||||||
|
|
||||||
### TODO
|
### TODO
|
||||||
把这个看起来就很别扭的config获取方式改一下
|
把这个看起来就很别扭的config获取方式改一下
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ from src.plugin_system.base.component_types import ActionInfo, ChatMode
|
|||||||
from src.plugin_system.apis import generator_api, send_api, message_api
|
from src.plugin_system.apis import generator_api, send_api, message_api
|
||||||
from src.chat.willing.willing_manager import get_willing_manager
|
from src.chat.willing.willing_manager import get_willing_manager
|
||||||
from src.chat.mai_thinking.mai_think import mai_thinking_manager
|
from src.chat.mai_thinking.mai_think import mai_thinking_manager
|
||||||
from maim_message.message_base import GroupInfo,UserInfo
|
from maim_message.message_base import GroupInfo
|
||||||
|
|
||||||
ENABLE_THINKING = False
|
ENABLE_THINKING = False
|
||||||
|
|
||||||
@@ -257,31 +257,29 @@ class HeartFChatting:
|
|||||||
)
|
)
|
||||||
person_name = await person_info_manager.get_value(person_id, "person_name")
|
person_name = await person_info_manager.get_value(person_id, "person_name")
|
||||||
return f"{person_name}:{message_data.get('processed_plain_text')}"
|
return f"{person_name}:{message_data.get('processed_plain_text')}"
|
||||||
|
|
||||||
async def send_typing(self):
|
async def send_typing(self):
|
||||||
group_info = GroupInfo(platform = "amaidesu_default",group_id = 114514,group_name = "内心")
|
group_info = GroupInfo(platform="amaidesu_default", group_id="114514", group_name="内心")
|
||||||
|
|
||||||
chat = await get_chat_manager().get_or_create_stream(
|
chat = await get_chat_manager().get_or_create_stream(
|
||||||
platform = "amaidesu_default",
|
platform="amaidesu_default",
|
||||||
user_info = None,
|
user_info=None, # type: ignore
|
||||||
group_info = group_info
|
group_info=group_info,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
await send_api.custom_to_stream(
|
await send_api.custom_to_stream(
|
||||||
message_type="state", content="typing", stream_id=chat.stream_id, storage_message=False
|
message_type="state", content="typing", stream_id=chat.stream_id, storage_message=False
|
||||||
)
|
)
|
||||||
|
|
||||||
async def stop_typing(self):
|
async def stop_typing(self):
|
||||||
group_info = GroupInfo(platform = "amaidesu_default",group_id = 114514,group_name = "内心")
|
group_info = GroupInfo(platform="amaidesu_default", group_id="114514", group_name="内心")
|
||||||
|
|
||||||
chat = await get_chat_manager().get_or_create_stream(
|
chat = await get_chat_manager().get_or_create_stream(
|
||||||
platform = "amaidesu_default",
|
platform="amaidesu_default",
|
||||||
user_info = None,
|
user_info=None, # type: ignore
|
||||||
group_info = group_info
|
group_info=group_info,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
await send_api.custom_to_stream(
|
await send_api.custom_to_stream(
|
||||||
message_type="state", content="stop_typing", stream_id=chat.stream_id, storage_message=False
|
message_type="state", content="stop_typing", stream_id=chat.stream_id, storage_message=False
|
||||||
)
|
)
|
||||||
@@ -295,7 +293,7 @@ class HeartFChatting:
|
|||||||
cycle_timers, thinking_id = self.start_cycle()
|
cycle_timers, thinking_id = self.start_cycle()
|
||||||
|
|
||||||
logger.info(f"{self.log_prefix} 开始第{self._cycle_counter}次思考[模式:{self.loop_mode}]")
|
logger.info(f"{self.log_prefix} 开始第{self._cycle_counter}次思考[模式:{self.loop_mode}]")
|
||||||
|
|
||||||
await self.send_typing()
|
await self.send_typing()
|
||||||
|
|
||||||
async with global_prompt_manager.async_message_scope(self.chat_stream.context.get_template_name()):
|
async with global_prompt_manager.async_message_scope(self.chat_stream.context.get_template_name()):
|
||||||
@@ -364,15 +362,12 @@ class HeartFChatting:
|
|||||||
logger.info(f"[{self.log_prefix}] {global_config.bot.nickname} 决定的回复内容: {content}")
|
logger.info(f"[{self.log_prefix}] {global_config.bot.nickname} 决定的回复内容: {content}")
|
||||||
|
|
||||||
# 发送回复 (不再需要传入 chat)
|
# 发送回复 (不再需要传入 chat)
|
||||||
reply_text = await self._send_response(response_set, reply_to_str, loop_start_time,message_data)
|
reply_text = await self._send_response(response_set, reply_to_str, loop_start_time, message_data)
|
||||||
|
|
||||||
await self.stop_typing()
|
await self.stop_typing()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ENABLE_THINKING:
|
if ENABLE_THINKING:
|
||||||
await mai_thinking_manager.get_mai_think(self.stream_id).do_think_after_response(reply_text)
|
await mai_thinking_manager.get_mai_think(self.stream_id).do_think_after_response(reply_text)
|
||||||
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -504,10 +499,9 @@ class HeartFChatting:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
interested_rate = (message_data.get("interest_value") or 0.0) * self.willing_amplifier
|
interested_rate = (message_data.get("interest_value") or 0.0) * self.willing_amplifier
|
||||||
|
|
||||||
self.willing_manager.setup(message_data, self.chat_stream)
|
self.willing_manager.setup(message_data, self.chat_stream)
|
||||||
|
|
||||||
|
|
||||||
reply_probability = await self.willing_manager.get_reply_probability(message_data.get("message_id", ""))
|
reply_probability = await self.willing_manager.get_reply_probability(message_data.get("message_id", ""))
|
||||||
|
|
||||||
talk_frequency = -1.00
|
talk_frequency = -1.00
|
||||||
@@ -517,7 +511,7 @@ class HeartFChatting:
|
|||||||
if additional_config and "maimcore_reply_probability_gain" in additional_config:
|
if additional_config and "maimcore_reply_probability_gain" in additional_config:
|
||||||
reply_probability += additional_config["maimcore_reply_probability_gain"]
|
reply_probability += additional_config["maimcore_reply_probability_gain"]
|
||||||
reply_probability = min(max(reply_probability, 0), 1) # 确保概率在 0-1 之间
|
reply_probability = min(max(reply_probability, 0), 1) # 确保概率在 0-1 之间
|
||||||
|
|
||||||
talk_frequency = global_config.chat.get_current_talk_frequency(self.stream_id)
|
talk_frequency = global_config.chat.get_current_talk_frequency(self.stream_id)
|
||||||
reply_probability = talk_frequency * reply_probability
|
reply_probability = talk_frequency * reply_probability
|
||||||
|
|
||||||
@@ -527,9 +521,9 @@ class HeartFChatting:
|
|||||||
|
|
||||||
# 打印消息信息
|
# 打印消息信息
|
||||||
mes_name = self.chat_stream.group_info.group_name if self.chat_stream.group_info else "私聊"
|
mes_name = self.chat_stream.group_info.group_name if self.chat_stream.group_info else "私聊"
|
||||||
|
|
||||||
# logger.info(f"[{mes_name}] 当前聊天频率: {talk_frequency:.2f},兴趣值: {interested_rate:.2f},回复概率: {reply_probability * 100:.1f}%")
|
# logger.info(f"[{mes_name}] 当前聊天频率: {talk_frequency:.2f},兴趣值: {interested_rate:.2f},回复概率: {reply_probability * 100:.1f}%")
|
||||||
|
|
||||||
if reply_probability > 0.05:
|
if reply_probability > 0.05:
|
||||||
logger.info(
|
logger.info(
|
||||||
f"[{mes_name}]"
|
f"[{mes_name}]"
|
||||||
@@ -545,7 +539,6 @@ class HeartFChatting:
|
|||||||
# 意愿管理器:注销当前message信息 (无论是否回复,只要处理过就删除)
|
# 意愿管理器:注销当前message信息 (无论是否回复,只要处理过就删除)
|
||||||
self.willing_manager.delete(message_data.get("message_id", ""))
|
self.willing_manager.delete(message_data.get("message_id", ""))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
async def _generate_response(
|
async def _generate_response(
|
||||||
self, message_data: dict, available_actions: Optional[Dict[str, ActionInfo]], reply_to: str
|
self, message_data: dict, available_actions: Optional[Dict[str, ActionInfo]], reply_to: str
|
||||||
@@ -570,7 +563,7 @@ class HeartFChatting:
|
|||||||
logger.error(f"[{self.log_prefix}] 回复生成出现错误:{str(e)} {traceback.format_exc()}")
|
logger.error(f"[{self.log_prefix}] 回复生成出现错误:{str(e)} {traceback.format_exc()}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def _send_response(self, reply_set, reply_to, thinking_start_time,message_data):
|
async def _send_response(self, reply_set, reply_to, thinking_start_time, message_data):
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
new_message_count = message_api.count_new_messages(
|
new_message_count = message_api.count_new_messages(
|
||||||
chat_id=self.chat_stream.stream_id, start_time=thinking_start_time, end_time=current_time
|
chat_id=self.chat_stream.stream_id, start_time=thinking_start_time, end_time=current_time
|
||||||
@@ -592,13 +585,27 @@ class HeartFChatting:
|
|||||||
if not first_replied:
|
if not first_replied:
|
||||||
if need_reply:
|
if need_reply:
|
||||||
await send_api.text_to_stream(
|
await send_api.text_to_stream(
|
||||||
text=data, stream_id=self.chat_stream.stream_id, reply_to=reply_to, reply_to_platform_id=reply_to_platform_id, typing=False
|
text=data,
|
||||||
|
stream_id=self.chat_stream.stream_id,
|
||||||
|
reply_to=reply_to,
|
||||||
|
reply_to_platform_id=reply_to_platform_id,
|
||||||
|
typing=False,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
await send_api.text_to_stream(text=data, stream_id=self.chat_stream.stream_id, reply_to_platform_id=reply_to_platform_id, typing=False)
|
await send_api.text_to_stream(
|
||||||
|
text=data,
|
||||||
|
stream_id=self.chat_stream.stream_id,
|
||||||
|
reply_to_platform_id=reply_to_platform_id,
|
||||||
|
typing=False,
|
||||||
|
)
|
||||||
first_replied = True
|
first_replied = True
|
||||||
else:
|
else:
|
||||||
await send_api.text_to_stream(text=data, stream_id=self.chat_stream.stream_id, reply_to_platform_id=reply_to_platform_id, typing=True)
|
await send_api.text_to_stream(
|
||||||
|
text=data,
|
||||||
|
stream_id=self.chat_stream.stream_id,
|
||||||
|
reply_to_platform_id=reply_to_platform_id,
|
||||||
|
typing=True,
|
||||||
|
)
|
||||||
reply_text += data
|
reply_text += data
|
||||||
|
|
||||||
return reply_text
|
return reply_text
|
||||||
|
|||||||
@@ -163,20 +163,25 @@ class ChatManager:
|
|||||||
"""注册消息到聊天流"""
|
"""注册消息到聊天流"""
|
||||||
stream_id = self._generate_stream_id(
|
stream_id = self._generate_stream_id(
|
||||||
message.message_info.platform, # type: ignore
|
message.message_info.platform, # type: ignore
|
||||||
message.message_info.user_info, # type: ignore
|
message.message_info.user_info,
|
||||||
message.message_info.group_info,
|
message.message_info.group_info,
|
||||||
)
|
)
|
||||||
self.last_messages[stream_id] = message
|
self.last_messages[stream_id] = message
|
||||||
# logger.debug(f"注册消息到聊天流: {stream_id}")
|
# logger.debug(f"注册消息到聊天流: {stream_id}")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _generate_stream_id(platform: str, user_info: UserInfo, group_info: Optional[GroupInfo] = None) -> str:
|
def _generate_stream_id(
|
||||||
|
platform: str, user_info: Optional[UserInfo], group_info: Optional[GroupInfo] = None
|
||||||
|
) -> str:
|
||||||
"""生成聊天流唯一ID"""
|
"""生成聊天流唯一ID"""
|
||||||
|
if not user_info and not group_info:
|
||||||
|
raise ValueError("用户信息或群组信息必须提供")
|
||||||
|
|
||||||
if group_info:
|
if group_info:
|
||||||
# 组合关键信息
|
# 组合关键信息
|
||||||
components = [platform, str(group_info.group_id)]
|
components = [platform, str(group_info.group_id)]
|
||||||
else:
|
else:
|
||||||
components = [platform, str(user_info.user_id), "private"]
|
components = [platform, str(user_info.user_id), "private"] # type: ignore
|
||||||
|
|
||||||
# 使用MD5生成唯一ID
|
# 使用MD5生成唯一ID
|
||||||
key = "_".join(components)
|
key = "_".join(components)
|
||||||
|
|||||||
@@ -110,11 +110,17 @@ class ComponentRegistry:
|
|||||||
# 根据组件类型进行特定注册(使用原始名称)
|
# 根据组件类型进行特定注册(使用原始名称)
|
||||||
match component_type:
|
match component_type:
|
||||||
case ComponentType.ACTION:
|
case ComponentType.ACTION:
|
||||||
ret = self._register_action_component(component_info, component_class) # type: ignore
|
assert isinstance(component_info, ActionInfo)
|
||||||
|
assert issubclass(component_class, BaseAction)
|
||||||
|
ret = self._register_action_component(component_info, component_class)
|
||||||
case ComponentType.COMMAND:
|
case ComponentType.COMMAND:
|
||||||
ret = self._register_command_component(component_info, component_class) # type: ignore
|
assert isinstance(component_info, CommandInfo)
|
||||||
|
assert issubclass(component_class, BaseCommand)
|
||||||
|
ret = self._register_command_component(component_info, component_class)
|
||||||
case ComponentType.EVENT_HANDLER:
|
case ComponentType.EVENT_HANDLER:
|
||||||
ret = self._register_event_handler_component(component_info, component_class) # type: ignore
|
assert isinstance(component_info, EventHandlerInfo)
|
||||||
|
assert issubclass(component_class, BaseEventHandler)
|
||||||
|
ret = self._register_event_handler_component(component_info, component_class)
|
||||||
case _:
|
case _:
|
||||||
logger.warning(f"未知组件类型: {component_type}")
|
logger.warning(f"未知组件类型: {component_type}")
|
||||||
|
|
||||||
@@ -218,6 +224,71 @@ class ComponentRegistry:
|
|||||||
self._components_classes.pop(component_name, None)
|
self._components_classes.pop(component_name, None)
|
||||||
logger.info(f"组件 {component_name} 已移除")
|
logger.info(f"组件 {component_name} 已移除")
|
||||||
|
|
||||||
|
# === 组件全局启用/禁用方法 ===
|
||||||
|
|
||||||
|
def enable_component(self, component_name: str, component_type: ComponentType) -> bool:
|
||||||
|
"""全局的启用某个组件
|
||||||
|
Parameters:
|
||||||
|
component_name: 组件名称
|
||||||
|
component_type: 组件类型
|
||||||
|
Returns:
|
||||||
|
bool: 启用成功返回True,失败返回False
|
||||||
|
"""
|
||||||
|
target_component_class = self.get_component_class(component_name, component_type)
|
||||||
|
target_component_info = self.get_component_info(component_name, component_type)
|
||||||
|
if not target_component_class or not target_component_info:
|
||||||
|
logger.warning(f"组件 {component_name} 未注册,无法启用")
|
||||||
|
return False
|
||||||
|
target_component_info.enabled = True
|
||||||
|
match component_type:
|
||||||
|
case ComponentType.ACTION:
|
||||||
|
assert isinstance(target_component_info, ActionInfo)
|
||||||
|
self._default_actions[component_name] = target_component_info
|
||||||
|
case ComponentType.COMMAND:
|
||||||
|
assert isinstance(target_component_info, CommandInfo)
|
||||||
|
pattern = target_component_info.command_pattern
|
||||||
|
self._command_patterns[re.compile(pattern)] = component_name
|
||||||
|
case ComponentType.EVENT_HANDLER:
|
||||||
|
assert isinstance(target_component_info, EventHandlerInfo)
|
||||||
|
assert issubclass(target_component_class, BaseEventHandler)
|
||||||
|
self._enabled_event_handlers[component_name] = target_component_class
|
||||||
|
from .events_manager import events_manager # 延迟导入防止循环导入问题
|
||||||
|
|
||||||
|
events_manager.register_event_subscriber(target_component_info, target_component_class)
|
||||||
|
self._components[component_name].enabled = True
|
||||||
|
self._components_by_type[component_type][component_name].enabled = True
|
||||||
|
logger.info(f"组件 {component_name} 已启用")
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def disable_component(self, component_name: str, component_type: ComponentType) -> bool:
|
||||||
|
"""全局的禁用某个组件
|
||||||
|
Parameters:
|
||||||
|
component_name: 组件名称
|
||||||
|
component_type: 组件类型
|
||||||
|
Returns:
|
||||||
|
bool: 禁用成功返回True,失败返回False
|
||||||
|
"""
|
||||||
|
target_component_class = self.get_component_class(component_name, component_type)
|
||||||
|
target_component_info = self.get_component_info(component_name, component_type)
|
||||||
|
if not target_component_class or not target_component_info:
|
||||||
|
logger.warning(f"组件 {component_name} 未注册,无法禁用")
|
||||||
|
return False
|
||||||
|
target_component_info.enabled = False
|
||||||
|
match component_type:
|
||||||
|
case ComponentType.ACTION:
|
||||||
|
self._default_actions.pop(component_name, None)
|
||||||
|
case ComponentType.COMMAND:
|
||||||
|
self._command_patterns = {k: v for k, v in self._command_patterns.items() if v != component_name}
|
||||||
|
case ComponentType.EVENT_HANDLER:
|
||||||
|
self._enabled_event_handlers.pop(component_name, None)
|
||||||
|
from .events_manager import events_manager # 延迟导入防止循环导入问题
|
||||||
|
|
||||||
|
await events_manager.unregister_event_subscriber(component_name)
|
||||||
|
self._components[component_name].enabled = False
|
||||||
|
self._components_by_type[component_type][component_name].enabled = False
|
||||||
|
logger.info(f"组件 {component_name} 已禁用")
|
||||||
|
return True
|
||||||
|
|
||||||
# === 组件查询方法 ===
|
# === 组件查询方法 ===
|
||||||
def get_component_info(
|
def get_component_info(
|
||||||
self, component_name: str, component_type: Optional[ComponentType] = None
|
self, component_name: str, component_type: Optional[ComponentType] = None
|
||||||
|
|||||||
Reference in New Issue
Block a user