fix(cron+weixin): Batch-4 salvage — origin fallback dict + Weixin session split + multi-target deliver - #11594
Merged
Merged
Conversation
… cron & send_message - gateway/platforms/weixin.py: - Split aiohttp.ClientSession into _poll_session and _send_session - Add _LIVE_ADAPTERS registry so send_weixin_direct() reuses the connected gateway adapter instead of creating a competing session - Fixes silent message loss when gateway is running (iLink token contention) - cron/scheduler.py: - Support comma-separated deliver values (e.g. 'feishu,weixin') for multi-target delivery - Delay pconfig/enabled check until standalone fallback so live adapters work even when platform is not in gateway config - tools/send_message_tool.py: - Synthesize PlatformConfig from WEIXIN_* env vars when gateway config lacks a weixin entry - Fall back to WEIXIN_HOME_CHANNEL env var for home channel resolution - tests/gateway/test_weixin.py: - Update mocks to include _send_session
…x Weixin test mocks Cron origin fallback extension (builds on #9193's _HOME_TARGET_ENV_VARS): adds the three remaining origin-fallback-eligible platforms that have home channel env vars configured in gateway/config.py but use non-generic env var names: - email → EMAIL_HOME_ADDRESS (non-standard suffix) - dingtalk → DINGTALK_HOME_CHANNEL - qqbot → QQ_HOME_CHANNEL (non-standard prefix: QQ_ not QQBOT_) Picks up the completeness intent of @Xowiek's PR #11317 using the architecturally-correct dict-based lookup from #9193, so platforms with non-standard env var names actually resolve instead of silently missing. Extended the parametrized regression test to cover the new three. Weixin test mock alignment (builds on #10091's _send_session split): Three test sites added in Batch 1 (TestWeixinSendImageFileParameterName) and Batch 3 (TestWeixinVoiceSending) mocked only adapter._session, but #10091 switched the send paths to check self._send_session. Added the companion setter so the tests stay green with the session split in place.
teknium1
force-pushed
the
hermes/hermes-7078c790
branch
from
April 17, 2026 12:43
ce02944 to
5a160d6
Compare
This was referenced Apr 17, 2026
This was referenced Apr 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Batch-4 salvage — cron origin-fallback correctness + Weixin session architecture fix + cron multi-target delivery. Three contributor PRs salvaged together in FULL (no feature dropping this time), with per-commit authorship preserved across all three contributors.
Included contributor work (ALL preserved, no scope trimming)
◆ #10091 @LLQWQ —
fix(gateway/weixin): split poll/send sessions, reuse live adapterCommit
02777741— the full PR, landed first to establish the architectural base:aiohttp.ClientSessioninto_poll_sessionand_send_session; add_LIVE_ADAPTERSregistry sosend_weixin_direct()reuses the connected gateway adapter instead of spawning a competing iLink session under the same bot token (fixes silent message loss when gateway is running, closes [Bug]: Weixin messages from cron/send_message are silently dropped when gateway is running #10089)_resolve_delivery_targetinto_resolve_single_delivery_target(job, deliver_value)+_resolve_delivery_targets(job) → List[dict], supporting comma-separated multi-target deliver values (e.g."feishu,weixin"); delayspconfig.enabledcheck so live adapters work without gateway config entriesPlatformConfigfromWEIXIN_*env vars when gateway config lacks a weixin entry; falls back toWEIXIN_HOME_CHANNELfor home-channel resolution_send_session◆ #9193 @briandevans —
fix(cron): restore origin fallback for feishu home channelsTwo clean commits (cherry-picked on top of #10091):
8635577e— narrow fix adding feishu/wecom/weixin to the origin-fallback tupleca85534a— architectural fix adds a module-level_HOME_TARGET_ENV_VARSdict mapping platform → its actual env var name, plus a_get_home_target_chat_id()helper. Replaces the buggyf"{platform.upper()}_HOME_CHANNEL"pattern that silently missed platforms with non-generic env var names likeMATRIX_HOME_ROOM_resolve_single_delivery_target()— the dict/helper are at module scope and work regardless of the function renameCloses #8848.
◆ #11317 @Xowiek —
fix(cron): broaden deliver=origin home-channel fallbackCompleteness intent picked up via my Teknium commit
3668766b— extends_HOME_TARGET_ENV_VARSto cover the 3 remaining origin-fallback-eligible platforms that have home-channel env vars ingateway/config.py:email→EMAIL_HOME_ADDRESS(non-standard suffix)dingtalk→DINGTALK_HOME_CHANNELqqbot→QQ_HOME_CHANNEL(non-standard prefix:QQ_notQQBOT_)Note:
whatsapp,homeassistant,webhook,wecom_callbackfrom #11317's proposed list don't have_HOME_CHANNELenv vars defined anywhere ingateway/config.py, so they can't meaningfully participate in origin fallback until those are added upstream.Conflict resolutions
Three resolution points (all mechanical, all verified):
_send_file()in weixin.py — Batch-3 fix: route Weixin voice replies to real file attachments #9425 addedforce_file_attachmentparam; fix(weixin): split poll/send sessions and reuse live adapter to prevent message loss #10091 renamed_session → _send_session. Kept both changes in one signature.send_voice()in weixin.py — lingeringself._sessioncheck (added in Batch-3 fix: route Weixin voice replies to real file attachments #9425 after fix(weixin): split poll/send sessions and reuse live adapter to prevent message loss #10091 was written) updated toself._send_sessionto stay consistent with the rename.cron/scheduler.py— fix(cron): include feishu/wecom/weixin in origin fallback #9193'sca85534aheader conflict with fix(weixin): split poll/send sessions and reuse live adapter to prevent message loss #10091's rename. Kept_resolve_single_delivery_target(job, deliver_value)signature from fix(weixin): split poll/send sessions and reuse live adapter to prevent message loss #10091; the_get_home_target_chat_id()helper from fix(cron): include feishu/wecom/weixin in origin fallback #9193 was added above it. All the actual fallback-iteration logic merged cleanly because it's inside the function body (same lines, just different function name).tests/gateway/test_weixin.py— three test sites added in Batch-1 (TestWeixinSendImageFileParameterName) and Batch-3 (TestWeixinVoiceSending) mocked onlyadapter._sessionbut fix(weixin): split poll/send sessions and reuse live adapter to prevent message loss #10091 made the send paths checkself._send_session. Addedadapter._send_session = adapter._sessioncompanion setter at each.Verification
◆ Full suite: 430 tests pass across
test_weixin,test_qqbot,test_unauthorized_dm_behavior,test_platform_base,test_send_image_file,test_send_retry,test_scheduler(cron),test_send_message_tool,test_url_safety. Cron subtree: 174 passed, 4 skipped.◆ Integration checks (runtime, real imports):
_HOME_TARGET_ENV_VARSdict complete: 14 platforms with correct env var names"feishu,weixin"resolves to 2 targets via_resolve_delivery_targets()_resolve_delivery_target()returns first target (existing callers unchanged)QQ_HOME_CHANNELresolves toqqbotplatform (non-standard prefix handled)MATRIX_HOME_ROOMresolves tomatrixplatform (non-standard suffix handled)EMAIL_HOME_ADDRESSresolves toemailplatform (non-standard suffix handled)_LIVE_ADAPTERSdict exists;_poll_session/_send_sessionattrs initialize to None; legacy_sessionattribute removedsend_weixin_direct()references_LIVE_ADAPTERS.get()withsend_session.closedguard◆ py_compile OK on all 5 touched files.
AUTHOR_MAP additions
brian@bde.io → briandevanshubin_ll@qq.com → LLQWQOn merge
Will rebase-merge to preserve per-commit authorship across 3 contributors (LLQWQ ×1, briandevans ×2, me ×2), then close #9193, #11317, #10091 with credit pointing here.