-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
改进 SessionWaiter 兜底流程并避免拦截后续事件 #3812
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 4 commits
98d1b46
9023363
b1ff47d
3b306ec
b797cbe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,6 @@ | ||||||||||||||||||||||||
| import abc | ||||||||||||||||||||||||
| import asyncio | ||||||||||||||||||||||||
| import copy | ||||||||||||||||||||||||
| import hashlib | ||||||||||||||||||||||||
| import re | ||||||||||||||||||||||||
| import uuid | ||||||||||||||||||||||||
|
|
@@ -278,6 +279,20 @@ def clear_result(self): | |||||||||||||||||||||||
| """清除消息事件的结果。""" | ||||||||||||||||||||||||
| self._result = None | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def clone_for_llm(self) -> "AstrMessageEvent": | ||||||||||||||||||||||||
| """浅拷贝并重置状态,以便重新走默认 LLM 流程。""" | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
| """浅拷贝并重置状态,以便重新走默认 LLM 流程。""" | |
| """ | |
| 浅拷贝并重置状态,以便重新走默认 LLM 流程。 | |
| - 清除事件结果(_result) | |
| - 重置发送操作标记(_has_send_oper)、LLM 调用标记(call_llm)、唤醒状态(is_wake)、命令唤醒标记(is_at_or_wake_command)、插件名(plugins_name)、会话等待绕过标记(_bypass_session_waiter) | |
| - 保留非瞬态的 extras 字段(_extras),移除瞬态字段(TRANSIENT_EXTRA_KEYS)以避免跨管线上下文丢失 | |
| Returns: | |
| AstrMessageEvent: 重置后的事件副本,可安全地重新进入 LLM 处理流程 | |
| """ |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shallow copy with copy.copy() may cause issues with mutable attributes. The message_obj.message list is shared between the original and cloned event. If the clone modifies the message chain (like inserting an At component at line 95-97 in packages/session_controller/main.py), it affects the original event.
Consider using copy.deepcopy() instead, or at least document this limitation:
new_event: AstrMessageEvent = copy.deepcopy(self)Or add a warning comment:
# Warning: Shallow copy means message_obj and its contents are shared
new_event: AstrMessageEvent = copy.copy(self)| """浅拷贝并重置状态,以便重新走默认 LLM 流程。""" | |
| new_event: AstrMessageEvent = copy.copy(self) | |
| """深拷贝并重置状态,以便重新走默认 LLM 流程。""" | |
| new_event: AstrMessageEvent = copy.deepcopy(self) |
sourcery-ai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |||||||||||
| from typing import Any | ||||||||||||
|
|
||||||||||||
| import astrbot.core.message.components as Comp | ||||||||||||
| from astrbot import logger | ||||||||||||
| from astrbot.core.platform import AstrMessageEvent | ||||||||||||
|
|
||||||||||||
| USER_SESSIONS: dict[str, "SessionWaiter"] = {} # 存储 SessionWaiter 实例 | ||||||||||||
|
|
@@ -29,6 +30,33 @@ def __init__(self): | |||||||||||
|
|
||||||||||||
| self.history_chains: list[list[Comp.BaseMessageComponent]] = [] | ||||||||||||
|
|
||||||||||||
| def fallback_to_llm( | ||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (complexity): 建议对 主要的复杂度来自 1. 拆分
|
||||||||||||
| self, | ||||||||||||
| event_queue: asyncio.Queue, | ||||||||||||
| event: AstrMessageEvent, | ||||||||||||
| *, | ||||||||||||
| stop_session: bool = True, | ||||||||||||
| ) -> AstrMessageEvent: | ||||||||||||
| """将当前事件重新入队,由默认 LLM 流程处理,适用于非预期输入的兜底。 | ||||||||||||
|
|
||||||||||||
| Args: | ||||||||||||
|
Comment on lines
+33
to
+42
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): 从命名和 docstring( Original comment in Englishissue (bug_risk): The Given the naming and docstring (
Comment on lines
+33
to
+42
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (bug_risk): 建议在使用事件队列的 put_nowait 时考虑处理潜在的队列背压问题。
建议实现: from typing import Any
import asyncio
import astrbot.core.message.components as Comp
from astrbot import logger
from astrbot.core.platform import AstrMessageEvent async def fallback_to_llm(
self,
event_queue: asyncio.Queue,
event: AstrMessageEvent,
*,
stop_session: bool = True,
) -> AstrMessageEvent: new_event = event.clone_for_llm()
new_event._bypass_session_waiter = not stop_session
await event_queue.put(new_event)
event.stop_event()由于 Original comment in Englishsuggestion (bug_risk): Consider handling potential queue backpressure instead of using put_nowait on the event queue.
Suggested implementation: from typing import Any
import asyncio
import astrbot.core.message.components as Comp
from astrbot import logger
from astrbot.core.platform import AstrMessageEvent async def fallback_to_llm(
self,
event_queue: asyncio.Queue,
event: AstrMessageEvent,
*,
stop_session: bool = True,
) -> AstrMessageEvent: new_event = event.clone_for_llm()
new_event._bypass_session_waiter = not stop_session
await event_queue.put(new_event)
event.stop_event()Because |
||||||||||||
| event_queue: 事件队列 | ||||||||||||
| event: 当前事件 | ||||||||||||
| stop_session: 是否结束当前 SessionWaiter。False 时仅兜底当前输入,继续等待后续输入。 | ||||||||||||
|
||||||||||||
| stop_session: 是否结束当前 SessionWaiter。False 时仅兜底当前输入,继续等待后续输入。 | |
| stop_session: 是否结束当前 SessionWaiter。False 时仅兜底当前输入,继续等待后续输入。 | |
| Returns: | |
| AstrMessageEvent: 重新入队的事件副本 |
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Race condition: When stop_session=True, there's a window between queueing the new event (line 54) and stopping the session (line 57) where the new event could be processed and intercepted by the still-active session again, defeating the fallback purpose.
The logic should be:
new_event._bypass_session_waiter = True # Always bypass for fallback eventsThis ensures the fallback event always reaches the LLM pipeline regardless of session state or timing.
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new fallback_to_llm method lacks test coverage. This is a critical feature that handles session fallback logic with multiple code paths (stop_session=True vs False) and interactions with event queuing, event stopping, and session cleanup.
Consider adding tests to verify:
- Event is correctly cloned and enqueued
_bypass_session_waiterflag is set appropriately- Original event is stopped
- Session is stopped when
stop_session=True - Session continues when
stop_session=False - Warning is logged when
stop_session=False
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,3 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import copy | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from sys import maxsize | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import astrbot.api.message_components as Comp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -7,7 +6,6 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from astrbot.api.star import Context, Star | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from astrbot.core.utils.session_waiter import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FILTERS, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| USER_SESSIONS, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SessionController, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SessionWaiter, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| session_waiter, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -23,10 +21,12 @@ def __init__(self, context: Context): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @filter.event_message_type(filter.EventMessageType.ALL, priority=maxsize) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def handle_session_control_agent(self, event: AstrMessageEvent): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """会话控制代理""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if getattr(event, "_bypass_session_waiter", False): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if getattr(event, "_bypass_session_waiter", False): | |
| if hasattr(event, "_bypass_session_waiter") and event._bypass_session_waiter: |
sourcery-ai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (code-quality): 合并嵌套的 if 条件(merge-nested-ifs)
| 0, | |
| Comp.At(qq=event.get_self_id(), name=event.get_self_id()), | |
| ) | |
| new_event = copy.copy(event) | |
| # 重新推入事件队列 | |
| self.context.get_event_queue().put_nowait(new_event) | |
| event.stop_event() | |
| controller.stop() | |
| controller.fallback_to_llm( | |
| self.context.get_event_queue(), | |
| event, | |
| ) | |
| try: | |
| await empty_mention_waiter(event) | |
| if len(messages) == 1 and (( | |
| isinstance(messages[0], Comp.At) | |
| and str(messages[0].qq) == str(event.get_self_id()) | |
| and p_settings.get("empty_mention_waiting", True) | |
| ) or ( | |
| isinstance(messages[0], Comp.Plain) | |
| and messages[0].text.strip() in wake_prefix | |
| )): | |
| if p_settings.get("empty_mention_waiting_need_reply", True): | |
| try: | |
| # 尝试使用 LLM 生成更生动的回复 | |
| func_tools_mgr = self.context.get_llm_tool_manager() | |
| # 获取用户当前的对话信息 | |
| curr_cid = await self.context.conversation_manager.get_curr_conversation_id( | |
| event.unified_msg_origin, | |
| ) | |
| conversation = None | |
| if curr_cid: | |
| conversation = await self.context.conversation_manager.get_conversation( | |
| event.unified_msg_origin, | |
| curr_cid, | |
| ) | |
| else: | |
| # 创建新对话 | |
| curr_cid = await self.context.conversation_manager.new_conversation( | |
| event.unified_msg_origin, | |
| platform_id=event.get_platform_id(), | |
| ) | |
| # 使用 LLM 生成回复 | |
| yield event.request_llm( | |
| prompt=( | |
| "注意,你正在社交媒体上中与用户进行聊天,用户只是通过@来唤醒你,但并未在这条消息中输入内容,他可能会在接下来一条发送他想发送的内容。" | |
| "你友好地询问用户想要聊些什么或者需要什么帮助,回复要符合人设,不要太过机械化。" | |
| "请注意,你仅需要输出要回复用户的内容,不要输出其他任何东西" | |
| ), | |
| func_tool_manager=func_tools_mgr, | |
| session_id=curr_cid, | |
| contexts=[], | |
| system_prompt="", | |
| conversation=conversation, | |
| ) | |
| except Exception as e: | |
| logger.error(f"LLM response failed: {e!s}") | |
| # LLM 回复失败,使用原始预设回复 | |
| yield event.plain_result("想要问什么呢?😄") | |
| @session_waiter(60) | |
| async def empty_mention_waiter( | |
| controller: SessionController, | |
| event: AstrMessageEvent, | |
| ): | |
| event.message_obj.message.insert( | |
| 0, | |
| Comp.At(qq=event.get_self_id(), name=event.get_self_id()), | |
| ) | |
| controller.fallback_to_llm( | |
| self.context.get_event_queue(), | |
| event, | |
| ) | |
| try: | |
| await empty_mention_waiter(event) | |
| except TimeoutError as _: | |
| pass | |
| except Exception as e: | |
| yield event.plain_result("发生错误,请联系管理员: " + str(e)) | |
| finally: | |
| event.stop_event() | |
说明
过多的嵌套会使代码难以理解,这在 Python 中尤为明显,因为没有花括号来帮助区分不同的嵌套层级。阅读嵌套很深的代码时会很混乱,因为你必须时刻记住各个条件对应的是哪一层。我们因此会尽量在可能的地方减少嵌套,而当两个 if 条件可以通过 and 合并时,就是一个很容易的优化点。
Original comment in English
suggestion (code-quality): Merge nested if conditions (merge-nested-ifs)
| 0, | |
| Comp.At(qq=event.get_self_id(), name=event.get_self_id()), | |
| ) | |
| new_event = copy.copy(event) | |
| # 重新推入事件队列 | |
| self.context.get_event_queue().put_nowait(new_event) | |
| event.stop_event() | |
| controller.stop() | |
| controller.fallback_to_llm( | |
| self.context.get_event_queue(), | |
| event, | |
| ) | |
| try: | |
| await empty_mention_waiter(event) | |
| if len(messages) == 1 and (( | |
| isinstance(messages[0], Comp.At) | |
| and str(messages[0].qq) == str(event.get_self_id()) | |
| and p_settings.get("empty_mention_waiting", True) | |
| ) or ( | |
| isinstance(messages[0], Comp.Plain) | |
| and messages[0].text.strip() in wake_prefix | |
| )): | |
| if p_settings.get("empty_mention_waiting_need_reply", True): | |
| try: | |
| # 尝试使用 LLM 生成更生动的回复 | |
| func_tools_mgr = self.context.get_llm_tool_manager() | |
| # 获取用户当前的对话信息 | |
| curr_cid = await self.context.conversation_manager.get_curr_conversation_id( | |
| event.unified_msg_origin, | |
| ) | |
| conversation = None | |
| if curr_cid: | |
| conversation = await self.context.conversation_manager.get_conversation( | |
| event.unified_msg_origin, | |
| curr_cid, | |
| ) | |
| else: | |
| # 创建新对话 | |
| curr_cid = await self.context.conversation_manager.new_conversation( | |
| event.unified_msg_origin, | |
| platform_id=event.get_platform_id(), | |
| ) | |
| # 使用 LLM 生成回复 | |
| yield event.request_llm( | |
| prompt=( | |
| "注意,你正在社交媒体上中与用户进行聊天,用户只是通过@来唤醒你,但并未在这条消息中输入内容,他可能会在接下来一条发送他想发送的内容。" | |
| "你友好地询问用户想要聊些什么或者需要什么帮助,回复要符合人设,不要太过机械化。" | |
| "请注意,你仅需要输出要回复用户的内容,不要输出其他任何东西" | |
| ), | |
| func_tool_manager=func_tools_mgr, | |
| session_id=curr_cid, | |
| contexts=[], | |
| system_prompt="", | |
| conversation=conversation, | |
| ) | |
| except Exception as e: | |
| logger.error(f"LLM response failed: {e!s}") | |
| # LLM 回复失败,使用原始预设回复 | |
| yield event.plain_result("想要问什么呢?😄") | |
| @session_waiter(60) | |
| async def empty_mention_waiter( | |
| controller: SessionController, | |
| event: AstrMessageEvent, | |
| ): | |
| event.message_obj.message.insert( | |
| 0, | |
| Comp.At(qq=event.get_self_id(), name=event.get_self_id()), | |
| ) | |
| controller.fallback_to_llm( | |
| self.context.get_event_queue(), | |
| event, | |
| ) | |
| try: | |
| await empty_mention_waiter(event) | |
| except TimeoutError as _: | |
| pass | |
| except Exception as e: | |
| yield event.plain_result("发生错误,请联系管理员: " + str(e)) | |
| finally: | |
| event.stop_event() | |
Explanation
Too much nesting can make code difficult to understand, and this is especiallytrue in Python, where there are no brackets to help out with the delineation of
different nesting levels.
Reading deeply nested code is confusing, since you have to keep track of which
conditions relate to which levels. We therefore strive to reduce nesting where
possible, and the situation where two if conditions can be combined using
and is an easy win.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (code-quality): 合并嵌套的 if 条件(merge-nested-ifs)
| 0, | |
| Comp.At(qq=event.get_self_id(), name=event.get_self_id()), | |
| ) | |
| new_event = copy.copy(event) | |
| # 重新推入事件队列 | |
| self.context.get_event_queue().put_nowait(new_event) | |
| event.stop_event() | |
| controller.stop() | |
| controller.fallback_to_llm( | |
| self.context.get_event_queue(), | |
| event, | |
| ) | |
| try: | |
| await empty_mention_waiter(event) | |
| if len(messages) == 1 and (( | |
| isinstance(messages[0], Comp.At) | |
| and str(messages[0].qq) == str(event.get_self_id()) | |
| and p_settings.get("empty_mention_waiting", True) | |
| ) or ( | |
| isinstance(messages[0], Comp.Plain) | |
| and messages[0].text.strip() in wake_prefix | |
| )): | |
| if p_settings.get("empty_mention_waiting_need_reply", True): | |
| try: | |
| # 尝试使用 LLM 生成更生动的回复 | |
| func_tools_mgr = self.context.get_llm_tool_manager() | |
| # 获取用户当前的对话信息 | |
| curr_cid = await self.context.conversation_manager.get_curr_conversation_id( | |
| event.unified_msg_origin, | |
| ) | |
| conversation = None | |
| if curr_cid: | |
| conversation = await self.context.conversation_manager.get_conversation( | |
| event.unified_msg_origin, | |
| curr_cid, | |
| ) | |
| else: | |
| # 创建新对话 | |
| curr_cid = await self.context.conversation_manager.new_conversation( | |
| event.unified_msg_origin, | |
| platform_id=event.get_platform_id(), | |
| ) | |
| # 使用 LLM 生成回复 | |
| yield event.request_llm( | |
| prompt=( | |
| "注意,你正在社交媒体上中与用户进行聊天,用户只是通过@来唤醒你,但并未在这条消息中输入内容,他可能会在接下来一条发送他想发送的内容。" | |
| "你友好地询问用户想要聊些什么或者需要什么帮助,回复要符合人设,不要太过机械化。" | |
| "请注意,你仅需要输出要回复用户的内容,不要输出其他任何东西" | |
| ), | |
| func_tool_manager=func_tools_mgr, | |
| session_id=curr_cid, | |
| contexts=[], | |
| system_prompt="", | |
| conversation=conversation, | |
| ) | |
| except Exception as e: | |
| logger.error(f"LLM response failed: {e!s}") | |
| # LLM 回复失败,使用原始预设回复 | |
| yield event.plain_result("想要问什么呢?😄") | |
| @session_waiter(60) | |
| async def empty_mention_waiter( | |
| controller: SessionController, | |
| event: AstrMessageEvent, | |
| ): | |
| event.message_obj.message.insert( | |
| 0, | |
| Comp.At(qq=event.get_self_id(), name=event.get_self_id()), | |
| ) | |
| controller.fallback_to_llm( | |
| self.context.get_event_queue(), | |
| event, | |
| ) | |
| try: | |
| await empty_mention_waiter(event) | |
| except TimeoutError as _: | |
| pass | |
| except Exception as e: | |
| yield event.plain_result("发生错误,请联系管理员: " + str(e)) | |
| finally: | |
| event.stop_event() | |
说明
过多的嵌套会让代码难以理解,特别是在没有花括号来标示不同嵌套层级的 Python 中,这一点尤为明显。阅读嵌套很深的代码时,你需要时刻记住每个条件属于哪一层逻辑,这会让理解变得很吃力。因此我们会尽量在可能的情况下减少嵌套,而把两个 if 条件用 and 合并起来,就是一个简单直接的改进点。
Original comment in English
suggestion (code-quality): Merge nested if conditions (merge-nested-ifs)
| 0, | |
| Comp.At(qq=event.get_self_id(), name=event.get_self_id()), | |
| ) | |
| new_event = copy.copy(event) | |
| # 重新推入事件队列 | |
| self.context.get_event_queue().put_nowait(new_event) | |
| event.stop_event() | |
| controller.stop() | |
| controller.fallback_to_llm( | |
| self.context.get_event_queue(), | |
| event, | |
| ) | |
| try: | |
| await empty_mention_waiter(event) | |
| if len(messages) == 1 and (( | |
| isinstance(messages[0], Comp.At) | |
| and str(messages[0].qq) == str(event.get_self_id()) | |
| and p_settings.get("empty_mention_waiting", True) | |
| ) or ( | |
| isinstance(messages[0], Comp.Plain) | |
| and messages[0].text.strip() in wake_prefix | |
| )): | |
| if p_settings.get("empty_mention_waiting_need_reply", True): | |
| try: | |
| # 尝试使用 LLM 生成更生动的回复 | |
| func_tools_mgr = self.context.get_llm_tool_manager() | |
| # 获取用户当前的对话信息 | |
| curr_cid = await self.context.conversation_manager.get_curr_conversation_id( | |
| event.unified_msg_origin, | |
| ) | |
| conversation = None | |
| if curr_cid: | |
| conversation = await self.context.conversation_manager.get_conversation( | |
| event.unified_msg_origin, | |
| curr_cid, | |
| ) | |
| else: | |
| # 创建新对话 | |
| curr_cid = await self.context.conversation_manager.new_conversation( | |
| event.unified_msg_origin, | |
| platform_id=event.get_platform_id(), | |
| ) | |
| # 使用 LLM 生成回复 | |
| yield event.request_llm( | |
| prompt=( | |
| "注意,你正在社交媒体上中与用户进行聊天,用户只是通过@来唤醒你,但并未在这条消息中输入内容,他可能会在接下来一条发送他想发送的内容。" | |
| "你友好地询问用户想要聊些什么或者需要什么帮助,回复要符合人设,不要太过机械化。" | |
| "请注意,你仅需要输出要回复用户的内容,不要输出其他任何东西" | |
| ), | |
| func_tool_manager=func_tools_mgr, | |
| session_id=curr_cid, | |
| contexts=[], | |
| system_prompt="", | |
| conversation=conversation, | |
| ) | |
| except Exception as e: | |
| logger.error(f"LLM response failed: {e!s}") | |
| # LLM 回复失败,使用原始预设回复 | |
| yield event.plain_result("想要问什么呢?😄") | |
| @session_waiter(60) | |
| async def empty_mention_waiter( | |
| controller: SessionController, | |
| event: AstrMessageEvent, | |
| ): | |
| event.message_obj.message.insert( | |
| 0, | |
| Comp.At(qq=event.get_self_id(), name=event.get_self_id()), | |
| ) | |
| controller.fallback_to_llm( | |
| self.context.get_event_queue(), | |
| event, | |
| ) | |
| try: | |
| await empty_mention_waiter(event) | |
| except TimeoutError as _: | |
| pass | |
| except Exception as e: | |
| yield event.plain_result("发生错误,请联系管理员: " + str(e)) | |
| finally: | |
| event.stop_event() | |
Explanation
Too much nesting can make code difficult to understand, and this is especiallytrue in Python, where there are no brackets to help out with the delineation of
different nesting levels.
Reading deeply nested code is confusing, since you have to keep track of which
conditions relate to which levels. We therefore strive to reduce nesting where
possible, and the situation where two if conditions can be combined using
and is an easy win.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): 建议通过把“extras 清理”和“LLM pipeline 状态重置”逻辑提取到独立的辅助方法中,来重构
clone_for_llm,使其职责更清晰、更聚焦。你可以保持当前新增行为不变,但通过拆分职责、显式化意图,减少
clone_for_llm目前略显“杂物箱”的感觉。1. 抽取对瞬时 extras 的处理
目前只有
clone_for_llm知道TRANSIENT_EXTRA_KEYS的存在。把这部分逻辑移到一个小 helper 中,可以让行为更清晰并方便复用:这样
clone_for_llm就不需要直接去操作_extras:2. 把状态重置逻辑集中到专用 helper
那段一次性重置多个标志位的代码可以提取成一个语义更明确的 helper,这样未来如果 LLM pipeline 状态有新增字段,只需要在这一处更新,而不用在
clone_for_llm内联维护:这样
clone_for_llm就可以写成:这样的拆分在保留当前行为的同时,让下面两类操作:
都变得更加显式且可以分别进行测试。如果你之后决定把
_bypass_session_waiter从核心事件中剥离出去,也会更容易做到这一点。Original comment in English
issue (complexity): Consider refactoring
clone_for_llmby extracting extras-cleanup and LLM-pipeline state-reset logic into dedicated helper methods to make its responsibilities clearer and more focused.You can keep the new behavior but reduce the “grab‑bag” feel of
clone_for_llmby splitting responsibilities and making the intent explicit.1. Factor out transient extras handling
Right now
clone_for_llmis the only place that knows aboutTRANSIENT_EXTRA_KEYS. Moving this into a small helper makes the behavior clearer and reusable:Then
clone_for_llmdoesn’t need to manually fiddle with_extras:2. Factor state resets into a dedicated helper
The block that resets multiple flags can be made intention‑revealing and centralized, so future state additions only need to be updated in one “LLM pipeline” helper instead of inline in
clone_for_llm:Then
clone_for_llmbecomes:This preserves all current behavior but makes the operations:
explicit and independently testable. It also makes it easier to later move
_bypass_session_waiterhandling out of the core event if you decide to decouple that concern.