fix: batch gateway/platform fixes — matrix E2EE, CJK input, Windows browser, Feishu reconnect + ACL - #5665
Merged
Conversation
…EVICE_ID Two issues caused Matrix E2EE to silently not work in encrypted rooms: 1. When matrix-nio is installed without the [e2e] extra (no python-olm / libolm), nio.crypto.ENCRYPTION_ENABLED is False and client.olm is never initialized. The adapter logged warnings but returned True from connect(), so the bot appeared online but could never decrypt messages. Now: check_matrix_requirements() and connect() both hard-fail with a clear error message when MATRIX_ENCRYPTION=true but E2EE deps are missing. 2. Without a stable device_id, the bot gets a new device identity on each restart. Other clients see it as "unknown device" and refuse to share Megolm session keys. Now: MATRIX_DEVICE_ID env var lets users pin a stable device identity that persists across restarts and is passed to nio.AsyncClient constructor + restore_login(). Changes: - gateway/platforms/matrix.py: add _check_e2ee_deps(), hard-fail in connect() and check_matrix_requirements(), MATRIX_DEVICE_ID support in constructor + restore_login - gateway/config.py: plumb MATRIX_DEVICE_ID into platform extras - hermes_cli/config.py: add MATRIX_DEVICE_ID to OPTIONAL_ENV_VARS Closes #3521
This commit fixes two critical bugs in the Feishu adapter that affect message reliability and process lifecycle. **Bug Fix 1: Intermittent Message Drops** Root cause: Event handler was created once in __init__ and reused across reconnects, causing callbacks to capture stale loop references. When the adapter disconnected and reconnected, old callbacks continued firing with invalid loop references, resulting in dropped messages with warnings: "[Feishu] Dropping inbound message before adapter loop is ready" Fix: - Rebuild event handler on each connect (websocket/webhook) - Clear handler on disconnect - Ensure callbacks always capture current valid loop - Add defensive loop.is_closed() checks with getattr for test compatibility - Unify webhook dispatch path to use same loop checks as websocket mode **Bug Fix 2: Process Hangs on Ctrl+C / SIGTERM** Root cause: Feishu SDK's websocket client runs in a background thread with an infinite _select() loop that never exits naturally. The thread was never properly joined on disconnect, causing processes to hang indefinitely after Ctrl+C or gateway stop commands. Fix: - Store reference to thread-local event loop (_ws_thread_loop) - On disconnect, cancel all tasks in thread loop and stop it gracefully via call_soon_threadsafe() - Await thread future with 10s timeout - Clean up pending tasks in thread's finally block before closing loop - Add detailed debug logging for disconnect flow **Additional Improvements:** - Add regression tests for disconnect cleanup and webhook dispatch - Ensure all event callbacks check loop readiness before dispatching Tested on Linux with websocket mode. All Feishu tests pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Allow users to configure websocket reconnect behavior via platform extra
config to reduce reconnect latency in production environments.
The official Feishu SDK defaults to:
- First reconnect: random jitter 0-30 seconds
- Subsequent retries: 120 second intervals
This can cause 20-30 second delays before reconnection after network
interruptions. This commit makes these values configurable while keeping
the SDK defaults for backward compatibility.
Configuration via ~/.hermes/config.yaml:
```yaml
platforms:
feishu:
extra:
ws_reconnect_nonce: 0 # Disable first-reconnect jitter (default: 30)
ws_reconnect_interval: 3 # Retry every 3 seconds (default: 120)
```
Invalid values (negative numbers, non-integers) fall back to SDK defaults.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Allow Feishu websocket keepalive timing to be configured via platform extra config so disconnects can be detected faster in unstable networks. New optional extra settings: - ws_ping_interval - ws_ping_timeout These values are applied only when explicitly configured. Invalid values fall back to the websocket library defaults by leaving the options unset. This complements the reconnect timing settings added previously and helps reduce total recovery time after network interruptions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reapply local reconnect and ping settings after the Feishu SDK refreshes its client config so user-provided websocket tuning actually takes effect. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consolidate coercion functions, extract loop readiness check, and deduplicate test mock setup to improve maintainability without changing behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add fine-grained authorization policies per Feishu group chat via platforms.feishu.extra configuration. - Add global bot-level admins that bypass all group restrictions - Add per-group policies: open, allowlist, blacklist, admin_only, disabled - Add default_group_policy fallback for chats without explicit rules - Thread chat_id through group message gate for per-chat rule selection - Match both open_id and user_id for backward compatibility - Preserve existing FEISHU_ALLOWED_USERS / FEISHU_GROUP_POLICY behavior - Add focused regression tests for all policy modes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use os.path.join for Windows install path so test passes on Linux (os.path.join uses / on Linux, \ on Windows).
teknium1
force-pushed
the
hermes/hermes-03d7aa21
branch
from
April 6, 2026 23:53
ca724af to
3e26865
Compare
This was referenced Apr 6, 2026
1 task
This was referenced Jul 27, 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
Five gateway/platform fixes salvaged from contributor PRs (Tier 3 from batch triage).
1. Matrix E2EE hard-fail + stable device ID (PR #5517 by @kshitijk4poor)
2. CJK wide chars in TUI input height (PR #5539 by @qaqcvc)
len()counts CJK characters as 1 but they occupy 2 terminal columns_input_height(): usesget_cwidth()from prompt_toolkit3. Windows browser auto-launch (PR #5584 by @Ruzzgar)
_get_chrome_debug_candidates()os.path.joininstead of hardcoded backslash paths4. Feishu reconnect/shutdown (PR #5500 by @jtuki, 5 commits)
5. Feishu per-group access control (PR #5541 by @jtuki)
Dropped from this batch: PR #5572 (pairing file locks) — main-side commit e9b5864 already added atomic writes + threading.RLock to pairing.py, creating 5 conflict regions. #5572's unique addition (cross-process fcntl/msvcrt locks) can be a follow-up PR.
Test results
Closes #5517, closes #5539, closes #5584, closes #5500, closes #5541