Skip to content

fix(weixin_offacc): 修复 active_send_mode 下 buffer 缺失导致消息丢弃#8731

Open
denmouv wants to merge 1 commit into
AstrBotDevs:masterfrom
denmouv:fix/weixin-active-send-mode-buffer-bug
Open

fix(weixin_offacc): 修复 active_send_mode 下 buffer 缺失导致消息丢弃#8731
denmouv wants to merge 1 commit into
AstrBotDevs:masterfrom
denmouv:fix/weixin-active-send-mode-buffer-bug

Conversation

@denmouv

@denmouv denmouv commented Jun 11, 2026

Copy link
Copy Markdown

当 active_send_mode=True 时,handle_callback 在 L160 提前 return,跳过了 user_buffer 的创建(L256),但 handle_msg 无条件要求 buffer 存在,导致所有用户消息在适配器层被静默丢弃。

修复:在 handle_msg 中按 active_send_mode 分叉,主动模式下直接提交事件(message_out={} 在 send() 中不被访问,完全安全)。被动模式行为零变化。

Closes #6182
Closes #7566

Modifications / 改动点

仅修改 astrbot/core/platform/sources/weixin_official_account/weixin_offacc_adapter.pyhandle_msg 方法(+17 行,零删除)。

  • 主动模式:检测 active_send_mode=True 时直接提交事件,message_out={}send() 方法在主动模式下通过 client.message.send_text() 直接推送,不访问 message_out
  • 被动模式:保持原有 buffer 检查逻辑不变

模式切换安全性:用户通过 Dashboard 切换 active_send_mode 后,PlatformManager.reload() 完整销毁旧 adapter 并创建新实例,不存在缓存属性过期问题。

  • This is NOT a breaking change.

Screenshots or Test Results / 运行截图或测试结果

验证环境

  • AstrBot v4.25.5,Docker 部署
  • active_send_mode: True
  • 微信公众号适配器

验证步骤

  1. 备份原文件,应用 patch
  2. docker restart astrbot
  3. 检查启动日志 — 正常,无报错
  4. 受影响用户发送消息,检查日志

修复前(历史日志)

用户 o9N_E0jYIBH4NPLCvjQIgr5z1c6I(此前 4 次 CRITICAL)发送消息时的典型日志:

[17:07:49] [CRIT] [weixin_offacc_adapter:513]: 用户消息未找到缓冲状态,无法处理消息: user=o9N_E0jYIBH4NPLCvjQIgr5z1c6I message_id=25470519203843813

消息在适配器层被丢弃,无 event_bus、无 respond.stage。

修复后(同一用户 o9N_E0jYIBH4NPLCvjQIgr5z1c6I 测试)

[22:40:59.973] [INFO] [weixin_offacc_adapter:151]: 解析成功: TextMessage(...FromUserName: 'o9N_E0jYIBH4NPLCvjQIgr5z1c6I'...Content: '深圳大学最高的建筑是什么'...)
[22:40:59.973] [INFO] [weixin_offacc_adapter:507]: abm: {...active_send_mode: True...}
[22:40:59.974] [INFO] [core.event_bus:74]: [weixin_official_account] o9N_E0jYIBH4NPLCvjQIgr5z1c6I: 深圳大学最高的建筑是什么
[22:41:03.317] [INFO] [respond.stage:183]: Prepare to send - o9N_E0jYIBH4NPLCvjQIgr5z1c6I: 正在为您查询相关信息
image

验证结论

  • ✅ 消息成功进入 event_bus
  • ✅ 消息成功到达 respond.stage 并准备发送
  • ✅ 零 CRITICAL "未找到缓冲状态" 错误
  • ✅ 受影响用户恢复正常通信

Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
    / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。

  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    / 我的更改经过了良好的测试,并已在上方提供了"验证步骤"和"运行截图"

  • 🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txtpyproject.toml 文件相应位置。

  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。

Summary by Sourcery

Bug Fixes:

  • Prevent user messages from being dropped in Weixin Official Account active_send_mode by bypassing the missing buffer check while preserving passive mode behavior.

@dosubot dosubot Bot added size:S This PR changes 10-29 lines, ignoring generated files. area:platform The bug / feature is about IM platform adapter, such as QQ, Lark, Telegram, WebChat and so on. labels Jun 11, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an active send mode in the WeChat Official Account adapter's handle_msg method, enabling direct message delivery via the WeChat Customer Service API and bypassing the passive reply buffering mechanism. The reviewer suggested refactoring the code to unify the event creation and submission logic, which is currently duplicated between the active and passive sending modes.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines 511 to 528
# === 主动发送模式 ===
# 回复通过微信客服 API (client.message.send_text) 直接推送,
# 不依赖被动回复的缓冲机制。传入空字典作为 message_out 占位。
if self.active_send_mode:
message_event = WeixinOfficialAccountPlatformEvent(
message_str=message.message_str,
message_obj=message,
platform_meta=self.meta(),
session_id=message.session_id,
client=self.client,
message_out={},
)
self.commit_event(message_event)
return

# === 被动回复模式 ===
# 必须有缓冲状态来暂存 LLM 的异步回复,以应对微信 5 秒响应期限。
buffer = self.user_buffer.get(message.sender.user_id, None)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

handle_msg 方法中,主动发送模式和被动回复模式下创建 WeixinOfficialAccountPlatformEvent 并提交事件的逻辑存在重复。可以通过在 active_send_mode 下直接将 buffer 赋值为空字典 {},然后统一在方法末尾创建并提交事件,从而避免代码重复,提高代码的可维护性。

        if self.active_send_mode:
            buffer = {}
        else:
            # === 被动回复模式 ===
            # 必须有缓冲状态来暂存 LLM 的异步回复,以应对微信 5 秒响应期限。
            buffer = self.user_buffer.get(message.sender.user_id, None)
References
  1. 避免在不同模式下重复编写相同的事件创建和提交逻辑,应尽量复用主体代码以减少冗余。

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好哩,已采纳。buffer = {} 是局部临时变量,不会残留到 user_buffer,避免了假 buffer 方案的内存泄漏和持久化问题。事件构造逻辑已统一为一处喵。

当 active_send_mode=True 时,handle_callback 在 L160 提前 return,
跳过了 user_buffer 的创建(L256),但 handle_msg 无条件要求 buffer
存在,导致所有用户消息在适配器层被静默丢弃。

修复:在 handle_msg 中按 active_send_mode 分叉,主动模式下直接
提交事件(message_out={} 在 send() 中不被访问,完全安全)。

Closes AstrBotDevs#6182
Closes AstrBotDevs#7566
@denmouv denmouv force-pushed the fix/weixin-active-send-mode-buffer-bug branch from 05179c6 to 8b076a1 Compare June 11, 2026 14:55

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In the active_send_mode branch you currently set buffer = {}; if downstream logic ever assumes a specific buffer structure this could break silently, so consider encapsulating this as a well-typed sentinel (e.g., a small dataclass or a named constant) or adding a type hint/assert to make the expected shape explicit.
  • Given that active_send_mode bypasses the buffer check entirely, it may be worth adding a short inline comment near where buffer is later consumed (or an assertion in the active path) to guard against future refactors accidentally reintroducing buffer-dependent behavior for active mode.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the active_send_mode branch you currently set `buffer = {}`; if downstream logic ever assumes a specific buffer structure this could break silently, so consider encapsulating this as a well-typed sentinel (e.g., a small dataclass or a named constant) or adding a type hint/assert to make the expected shape explicit.
- Given that active_send_mode bypasses the buffer check entirely, it may be worth adding a short inline comment near where `buffer` is later consumed (or an assertion in the active path) to guard against future refactors accidentally reintroducing buffer-dependent behavior for active mode.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:platform The bug / feature is about IM platform adapter, such as QQ, Lark, Telegram, WebChat and so on. size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

1 participant