mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
feat(gateway): add configurable Feishu websocket reconnect timing
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>
This commit is contained in:
parent
7cf4bd06bf
commit
7d0bf15121
2 changed files with 55 additions and 2 deletions
|
|
@ -270,6 +270,8 @@ class FeishuAdapterSettings:
|
|||
webhook_host: str
|
||||
webhook_port: int
|
||||
webhook_path: str
|
||||
ws_reconnect_nonce: int = 30
|
||||
ws_reconnect_interval: int = 120
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -358,6 +360,22 @@ def _strip_markdown_to_plain_text(text: str) -> str:
|
|||
return plain.strip()
|
||||
|
||||
|
||||
def _coerce_non_negative_int(value: Any, default: int) -> int:
|
||||
try:
|
||||
parsed = int(value)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
return parsed if parsed >= 0 else default
|
||||
|
||||
|
||||
def _coerce_positive_int(value: Any, default: int) -> int:
|
||||
try:
|
||||
parsed = int(value)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
return parsed if parsed >= 1 else default
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Post payload builders and parsers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
@ -1040,6 +1058,8 @@ class FeishuAdapter(BasePlatformAdapter):
|
|||
str(extra.get("webhook_path") or os.getenv("FEISHU_WEBHOOK_PATH", _DEFAULT_WEBHOOK_PATH)).strip()
|
||||
or _DEFAULT_WEBHOOK_PATH
|
||||
),
|
||||
ws_reconnect_nonce=_coerce_non_negative_int(extra.get("ws_reconnect_nonce"), 30),
|
||||
ws_reconnect_interval=_coerce_positive_int(extra.get("ws_reconnect_interval"), 120),
|
||||
)
|
||||
|
||||
def _apply_settings(self, settings: FeishuAdapterSettings) -> None:
|
||||
|
|
@ -1062,6 +1082,8 @@ class FeishuAdapter(BasePlatformAdapter):
|
|||
self._webhook_host = settings.webhook_host
|
||||
self._webhook_port = settings.webhook_port
|
||||
self._webhook_path = settings.webhook_path
|
||||
self._ws_reconnect_nonce = settings.ws_reconnect_nonce
|
||||
self._ws_reconnect_interval = settings.ws_reconnect_interval
|
||||
|
||||
def _build_event_handler(self) -> Any:
|
||||
if EventDispatcherHandler is None:
|
||||
|
|
@ -3032,6 +3054,11 @@ class FeishuAdapter(BasePlatformAdapter):
|
|||
event_handler=self._event_handler,
|
||||
domain=domain,
|
||||
)
|
||||
try:
|
||||
setattr(self._ws_client, "_reconnect_nonce", self._ws_reconnect_nonce)
|
||||
setattr(self._ws_client, "_reconnect_interval", self._ws_reconnect_interval)
|
||||
except Exception:
|
||||
logger.debug("[Feishu] Failed to override websocket reconnect settings", exc_info=True)
|
||||
self._ws_future = loop.run_in_executor(
|
||||
None,
|
||||
_run_official_feishu_ws_client,
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ class TestFeishuAdapterMessaging(unittest.TestCase):
|
|||
from gateway.platforms.feishu import FeishuAdapter
|
||||
|
||||
adapter = FeishuAdapter(PlatformConfig())
|
||||
ws_client = object()
|
||||
ws_client = SimpleNamespace()
|
||||
|
||||
with (
|
||||
patch("gateway.platforms.feishu.FEISHU_AVAILABLE", True),
|
||||
|
|
@ -367,7 +367,7 @@ class TestFeishuAdapterMessaging(unittest.TestCase):
|
|||
from gateway.platforms.feishu import FeishuAdapter
|
||||
|
||||
adapter = FeishuAdapter(PlatformConfig())
|
||||
ws_client = object()
|
||||
ws_client = SimpleNamespace()
|
||||
sleeps = []
|
||||
|
||||
with (
|
||||
|
|
@ -561,6 +561,32 @@ class TestAdapterModule(unittest.TestCase):
|
|||
self.assertIn("register_p2_im_message_reaction_deleted_v1", source)
|
||||
self.assertIn("register_p2_card_action_trigger", source)
|
||||
|
||||
def test_load_settings_uses_sdk_defaults_for_invalid_ws_reconnect_values(self):
|
||||
from gateway.platforms.feishu import FeishuAdapter
|
||||
|
||||
settings = FeishuAdapter._load_settings(
|
||||
{
|
||||
"ws_reconnect_nonce": -1,
|
||||
"ws_reconnect_interval": "bad",
|
||||
}
|
||||
)
|
||||
|
||||
self.assertEqual(settings.ws_reconnect_nonce, 30)
|
||||
self.assertEqual(settings.ws_reconnect_interval, 120)
|
||||
|
||||
def test_load_settings_accepts_custom_ws_reconnect_values(self):
|
||||
from gateway.platforms.feishu import FeishuAdapter
|
||||
|
||||
settings = FeishuAdapter._load_settings(
|
||||
{
|
||||
"ws_reconnect_nonce": 0,
|
||||
"ws_reconnect_interval": 3,
|
||||
}
|
||||
)
|
||||
|
||||
self.assertEqual(settings.ws_reconnect_nonce, 0)
|
||||
self.assertEqual(settings.ws_reconnect_interval, 3)
|
||||
|
||||
|
||||
class TestAdapterBehavior(unittest.TestCase):
|
||||
@patch.dict(os.environ, {}, clear=True)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue