功能描述
当前 session_waiter 装饰的 handler 内部只能通过 await event.send(...) 发送消息,而 event.send 会绕过 ResultDecorateStage,导致"回复时 @ 发送者""回复时引用消息""分段回复""TTS""文本转图片"等用户配置的装饰功能在会话控制器场景下全部失效,破坏体验一致性。
文档示例也明确标注不能使用 yield,这是当前架构的限制。
根因
SessionWaiter.trigger 丢弃了 handler 的返回值(session_waiter.py#L169 原地 await 后无返回)。
|
@filter.event_message_type(filter.EventMessageType.ALL, priority=maxsize) |
|
async def handle_session_control_agent(self, event: AstrMessageEvent) -> None: |
|
"""会话控制代理""" |
|
for session_filter in FILTERS: |
|
session_id = session_filter.filter(event) |
|
if session_id in USER_SESSIONS: |
|
await SessionWaiter.trigger(session_id, event) |
|
event.stop_event() |
handle_session_control_agent 在 trigger 后立即 event.stop_event(),使后续 ResultDecorateStage / RespondStage 被跳过。
建议方案
...然而要解决这个问题却仅仅只要 10 行改动:
SessionWaiter.trigger 返回 handler 的返回值(None → Any)。
handle_session_control_agent 改为 Async Generator:当 trigger 返回 MessageEventResult 时 yield 它,借助 Scheduler 的洋葱模型自动执行 ResultDecorateStage 与 RespondStage;否则保持原 stop_event 行为。
且完全向后兼容:老插件在 waiter 内用 event.send 且不 return 的,handler 返回 None,走原 stop_event 路径,行为不变。新插件只需把 await event.send(event.plain_result(...)) 改写为 return event.plain_result(...) 即可享受完整装饰流程。
使用场景
任何使用 session_waiter 的多轮会话插件,典型如成语接龙、问答游戏、分步表单收集等。以成语接龙为例:
改前(装饰功能失效):
@session_waiter(timeout=60)
async def idiom_waiter(controller: SessionController, event: AstrMessageEvent):
# ...
await event.send(event.plain_result("先见之明")) # 不走 @回复 / 引用 / 分段
controller.keep(timeout=60, reset_timeout=True)
改后(装饰功能生效):
@session_waiter(timeout=60)
async def idiom_waiter(controller: SessionController, event: AstrMessageEvent):
# ...
controller.keep(timeout=60, reset_timeout=True)
return event.plain_result("先见之明") # 自动走 @回复 / 引用 / 分段 / TTS / 转图
检查清单
功能描述
当前
session_waiter装饰的 handler 内部只能通过await event.send(...)发送消息,而event.send会绕过ResultDecorateStage,导致"回复时 @ 发送者""回复时引用消息""分段回复""TTS""文本转图片"等用户配置的装饰功能在会话控制器场景下全部失效,破坏体验一致性。文档示例也明确标注不能使用 yield,这是当前架构的限制。
根因
SessionWaiter.trigger丢弃了 handler 的返回值(session_waiter.py#L169 原地await后无返回)。AstrBot/astrbot/builtin_stars/astrbot/main.py
Lines 44 to 51 in bb9b187
handle_session_control_agent在 trigger 后立即event.stop_event(),使后续ResultDecorateStage/RespondStage被跳过。建议方案
...然而要解决这个问题却仅仅只要 10 行改动:
SessionWaiter.trigger返回 handler 的返回值(None→Any)。handle_session_control_agent改为 Async Generator:当 trigger 返回MessageEventResult时yield它,借助 Scheduler 的洋葱模型自动执行ResultDecorateStage与RespondStage;否则保持原stop_event行为。且完全向后兼容:老插件在 waiter 内用
event.send且不 return 的,handler 返回None,走原stop_event路径,行为不变。新插件只需把await event.send(event.plain_result(...))改写为return event.plain_result(...)即可享受完整装饰流程。使用场景
任何使用
session_waiter的多轮会话插件,典型如成语接龙、问答游戏、分步表单收集等。以成语接龙为例:改前(装饰功能失效):
改后(装饰功能生效):
检查清单