fix(qqbot): accept is_reconnect kwarg in QQAdapter.connect() - #59429
Closed
lemonwan wants to merge 1 commit into
Closed
fix(qqbot): accept is_reconnect kwarg in QQAdapter.connect()#59429lemonwan wants to merge 1 commit into
lemonwan wants to merge 1 commit into
Conversation
The gateway's reconnect loop forwards is_reconnect=True to every
adapter.connect() call (gateway/run.py:7724). QQAdapter.connect()
was the only adapter that didn't accept the kwarg, so every retry
after a websocket drop raised:
TypeError: QQAdapter.connect() got an unexpected keyword
argument 'is_reconnect'
...leaving qqbot permanently disconnected after the first 4009
'Session timed out' close. This aligns QQ with the BasePlatformAdapter
contract that all ~30 other adapters already implement.
Collaborator
Duplicate of #52966 — the earliest still-open canonical fix for the QQBot |
teknium1
pushed a commit
that referenced
this pull request
Jul 10, 2026
…onnect The gateway reconnect watcher forwards is_reconnect=True to every adapter.connect() call on every retry. Adapters whose signature omits the kwarg raise TypeError at every reconnect attempt and stay silently disconnected — the exact bug that shipped for QQAdapter and only surfaced after messages stopped flowing on the QQ channel for hours. This test statically parses every adapter.py under gateway/platforms/ and plugins/platforms/ (via AST, so third-party SDKs like slack_sdk, matrix-nio, aiohttp, telegram, etc. are NOT required in the test env) and asserts every *Adapter class with an async connect() accepts is_reconnect — either as a keyword-only argument or absorbed by **kwargs. Also fixes plugins/platforms/wecom/callback_adapter.py:WecomCallbackAdapter, which the new test caught as a second offender. Same class of bug: bare 'async def connect(self)' signature would die on the first reconnect. Companion to #59429 (which fixed the original QQAdapter offender).
santhreal
pushed a commit
to santhreal/hermes-agent
that referenced
this pull request
Jul 13, 2026
…onnect The gateway reconnect watcher forwards is_reconnect=True to every adapter.connect() call on every retry. Adapters whose signature omits the kwarg raise TypeError at every reconnect attempt and stay silently disconnected — the exact bug that shipped for QQAdapter and only surfaced after messages stopped flowing on the QQ channel for hours. This test statically parses every adapter.py under gateway/platforms/ and plugins/platforms/ (via AST, so third-party SDKs like slack_sdk, matrix-nio, aiohttp, telegram, etc. are NOT required in the test env) and asserts every *Adapter class with an async connect() accepts is_reconnect — either as a keyword-only argument or absorbed by **kwargs. Also fixes plugins/platforms/wecom/callback_adapter.py:WecomCallbackAdapter, which the new test caught as a second offender. Same class of bug: bare 'async def connect(self)' signature would die on the first reconnect. Companion to NousResearch#59429 (which fixed the original QQAdapter offender).
Contributor
|
Thanks for the focused QQBot reconnect fix. This is already implemented on current Automated hermes-sweeper review evidence:
The member comment correctly identified the duplicate cluster; this PR's requested guarantee is now covered on main. |
justemu
pushed a commit
to justemu/hermes-agent
that referenced
this pull request
Jul 18, 2026
…onnect The gateway reconnect watcher forwards is_reconnect=True to every adapter.connect() call on every retry. Adapters whose signature omits the kwarg raise TypeError at every reconnect attempt and stay silently disconnected — the exact bug that shipped for QQAdapter and only surfaced after messages stopped flowing on the QQ channel for hours. This test statically parses every adapter.py under gateway/platforms/ and plugins/platforms/ (via AST, so third-party SDKs like slack_sdk, matrix-nio, aiohttp, telegram, etc. are NOT required in the test env) and asserts every *Adapter class with an async connect() accepts is_reconnect — either as a keyword-only argument or absorbed by **kwargs. Also fixes plugins/platforms/wecom/callback_adapter.py:WecomCallbackAdapter, which the new test caught as a second offender. Same class of bug: bare 'async def connect(self)' signature would die on the first reconnect. Companion to NousResearch#59429 (which fixed the original QQAdapter offender).
Gravezzz
pushed a commit
to Gravezzz/hermes-agent
that referenced
this pull request
Jul 21, 2026
…onnect The gateway reconnect watcher forwards is_reconnect=True to every adapter.connect() call on every retry. Adapters whose signature omits the kwarg raise TypeError at every reconnect attempt and stay silently disconnected — the exact bug that shipped for QQAdapter and only surfaced after messages stopped flowing on the QQ channel for hours. This test statically parses every adapter.py under gateway/platforms/ and plugins/platforms/ (via AST, so third-party SDKs like slack_sdk, matrix-nio, aiohttp, telegram, etc. are NOT required in the test env) and asserts every *Adapter class with an async connect() accepts is_reconnect — either as a keyword-only argument or absorbed by **kwargs. Also fixes plugins/platforms/wecom/callback_adapter.py:WecomCallbackAdapter, which the new test caught as a second offender. Same class of bug: bare 'async def connect(self)' signature would die on the first reconnect. Companion to NousResearch#59429 (which fixed the original QQAdapter offender).
leewenjie
pushed a commit
to leewenjie/hermes-agent
that referenced
this pull request
Aug 7, 2026
…onnect The gateway reconnect watcher forwards is_reconnect=True to every adapter.connect() call on every retry. Adapters whose signature omits the kwarg raise TypeError at every reconnect attempt and stay silently disconnected — the exact bug that shipped for QQAdapter and only surfaced after messages stopped flowing on the QQ channel for hours. This test statically parses every adapter.py under gateway/platforms/ and plugins/platforms/ (via AST, so third-party SDKs like slack_sdk, matrix-nio, aiohttp, telegram, etc. are NOT required in the test env) and asserts every *Adapter class with an async connect() accepts is_reconnect — either as a keyword-only argument or absorbed by **kwargs. Also fixes plugins/platforms/wecom/callback_adapter.py:WecomCallbackAdapter, which the new test caught as a second offender. Same class of bug: bare 'async def connect(self)' signature would die on the first reconnect. Companion to NousResearch#59429 (which fixed the original QQAdapter offender).
randlee
pushed a commit
to randlee/hermes-agent
that referenced
this pull request
Aug 11, 2026
…onnect The gateway reconnect watcher forwards is_reconnect=True to every adapter.connect() call on every retry. Adapters whose signature omits the kwarg raise TypeError at every reconnect attempt and stay silently disconnected — the exact bug that shipped for QQAdapter and only surfaced after messages stopped flowing on the QQ channel for hours. This test statically parses every adapter.py under gateway/platforms/ and plugins/platforms/ (via AST, so third-party SDKs like slack_sdk, matrix-nio, aiohttp, telegram, etc. are NOT required in the test env) and asserts every *Adapter class with an async connect() accepts is_reconnect — either as a keyword-only argument or absorbed by **kwargs. Also fixes plugins/platforms/wecom/callback_adapter.py:WecomCallbackAdapter, which the new test caught as a second offender. Same class of bug: bare 'async def connect(self)' signature would die on the first reconnect. Companion to NousResearch#59429 (which fixed the original QQAdapter offender).
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.
Symptom
After the QQ WebSocket receives its first
code=4009 Session timed outclose (which happens routinely, ~every 30 min per QQ's own docs), the gateway reconnect loop dies with:…and never recovers. QQ silently stops delivering messages to the agent until the gateway is manually restarted (and even then, the next 4009 close kills it again). Nothing on the QQ side surfaces the failure — users just notice their agent has stopped responding on QQ.
Root cause
gateway/run.pyforwardsis_reconnect=Truetoadapter.connect()on every retry (line 7724 →_call_adapter_connectat 3383). All ~30 other adapters — Telegram, Discord, Slack, Feishu, WhatsApp, Signal, WeChat, Matrix, Teams, LINE, Email, IRC, SMS, DingTalk, WeCom, Homeassistant, Google Chat, Mattermost, Ntfy, Photon, Raft, Simplex, Yuanbao, API Server, BlueBubbles, Webhook, MSGraph Webhook, Relay — accept*, is_reconnect: bool = Falseper theBasePlatformAdapter.connect()contract (seegateway/platforms/base.py:2864).QQAdapter.connect()was the lone holdout with a bareasync def connect(self) -> bool:signature.Fix
Add the
*, is_reconnect: bool = Falsekwarg toQQAdapter.connect(). QQ's connection flow does not need to branch on cold-boot vs. reconnect today (unlike Telegram, which uses it to drivedrop_pending_updates), so the parameter is accepted-and-ignored with adel is_reconnectand a docstring pointer explaining why it must nonetheless be accepted.Verification
On the affected host, before this patch: qqbot cycled through 30-min timeout → TypeError → 60s → 120s retry backoff, permanently disconnected.
After this patch:
systemctl --user restart hermes-gateway→ qqbot connects → user confirmed message delivery restored end-to-end.Notes
connectacceptsis_reconnectto catch regressions of this exact class, but out of scope for this fix.