refactor(gateway): migrate ALL remaining inline adapters (slack, dingtalk, whatsapp, matrix, feishu, telegram, wecom, email, sms) to plugins - #41284
Conversation
🔎 Lint report:
|
| Rule | Count |
|---|---|
unresolved-attribute |
88 |
unresolved-import |
67 |
invalid-method-override |
15 |
invalid-argument-type |
11 |
invalid-assignment |
7 |
unresolved-reference |
3 |
call-non-callable |
2 |
no-matching-overload |
1 |
not-subscriptable |
1 |
unused-type-ignore-comment |
1 |
invalid-return-type |
1 |
First entries
plugins/platforms/whatsapp/adapter.py:1100: [invalid-method-override] invalid-method-override: Invalid override of method `send_document`: Definition is incompatible with `BasePlatformAdapter.send_document`
plugins/platforms/dingtalk/adapter.py:1209: [unresolved-attribute] unresolved-attribute: Attribute `StreamingUpdateHeaders` is not defined on `None` in union `Unknown | None`
plugins/platforms/wecom/callback_adapter.py:134: [unresolved-attribute] unresolved-attribute: Attribute `AsyncClient` is not defined on `None` in union `Unknown | None`
plugins/platforms/telegram/adapter.py:1618: [unresolved-attribute] unresolved-attribute: Attribute `Document` is not defined on `None` in union `Unknown | None`
plugins/platforms/dingtalk/adapter.py:895: [invalid-assignment] invalid-assignment: Invalid subscript assignment with key of type `str | None` and value of type `str` on object of type `dict[str, str]`
plugins/platforms/dingtalk/adapter.py:1103: [unresolved-attribute] unresolved-attribute: Attribute `DeliverCardRequest` is not defined on `None` in union `Unknown | None`
plugins/platforms/dingtalk/adapter.py:1410: [unresolved-attribute] unresolved-attribute: Attribute `ChatbotHandler` is not defined on `None` in union `Unknown | None`
plugins/platforms/feishu/feishu_comment.py:41: [unresolved-import] unresolved-import: Cannot resolve imported module `lark_oapi.core.model.base_request`
plugins/platforms/matrix/adapter.py:714: [unresolved-import] unresolved-import: Cannot resolve imported module `mautrix.client.state_store`
plugins/platforms/email/adapter.py:374: [invalid-argument-type] invalid-argument-type: Argument to bound method `IMAP4.uid` is incorrect: Expected `str`, found `None`
plugins/platforms/wecom/adapter.py:284: [unresolved-attribute] unresolved-attribute: Attribute `ClientSession` is not defined on `None` in union `Unknown | None`
plugins/platforms/feishu/adapter.py:1368: [unresolved-import] unresolved-import: Cannot resolve imported module `lark_oapi.core`
plugins/platforms/feishu/adapter.py:3535: [unresolved-attribute] unresolved-attribute: Unresolved attribute `_last_chunk_len` on type `MessageEvent`
plugins/platforms/telegram/adapter.py:2076: [unresolved-attribute] unresolved-attribute: Attribute `message_id` is not defined on `None` in union `None | Unknown`
tests/tools/test_send_message_tool.py:873: [invalid-assignment] invalid-assignment: Object of type `AsyncMock` is not assignable to attribute `standalone_sender_fn` on type `PlatformEntry | None`
plugins/platforms/telegram/adapter.py:4317: [unresolved-attribute] unresolved-attribute: Attribute `CHANNEL` is not defined on `None` in union `Unknown | None`
plugins/platforms/matrix/adapter.py:1288: [invalid-method-override] invalid-method-override: Invalid override of method `send_document`: Definition is incompatible with `BasePlatformAdapter.send_document`
plugins/platforms/telegram/adapter.py:3406: [unresolved-attribute] unresolved-attribute: Attribute `PRIVATE` is not defined on `None` in union `Unknown | None`
plugins/platforms/telegram/adapter.py:2937: [invalid-assignment] invalid-assignment: Object of type `None` is not assignable to `def group_providers(slugs) -> Unknown`
plugins/platforms/whatsapp/adapter.py:1089: [invalid-method-override] invalid-method-override: Invalid override of method `send_voice`: Definition is incompatible with `BasePlatformAdapter.send_voice`
plugins/platforms/matrix/adapter.py:2952: [unresolved-attribute] unresolved-attribute: Attribute `group` is not defined on `None` in union `Match[str] | None`
plugins/platforms/telegram/adapter.py:5295: [unresolved-attribute] unresolved-attribute: Unresolved attribute `_last_chunk_len` on type `MessageEvent`
plugins/platforms/wecom/callback_adapter.py:25: [unresolved-import] unresolved-import: Cannot resolve imported module `defusedxml.ElementTree`
plugins/platforms/telegram/telegram_network.py:18: [unresolved-import] unresolved-import: Cannot resolve imported module `httpx`
plugins/platforms/dingtalk/adapter.py:1265: [unresolved-attribute] unresolved-attribute: Attribute `RobotRecallEmotionRequest` is not defined on `None` in union `Unknown | None`
... and 172 more
✅ Fixed issues (182):
| Rule | Count |
|---|---|
unresolved-attribute |
85 |
unresolved-import |
57 |
invalid-method-override |
15 |
invalid-argument-type |
10 |
invalid-assignment |
7 |
call-non-callable |
2 |
unresolved-reference |
2 |
no-matching-overload |
1 |
invalid-return-type |
1 |
not-subscriptable |
1 |
unused-type-ignore-comment |
1 |
First entries
gateway/platforms/feishu.py:2595: [no-matching-overload] no-matching-overload: No overload of bound method `dict.get` matches arguments
gateway/platforms/dingtalk.py:1071: [unresolved-attribute] unresolved-attribute: Attribute `create_card_with_options_async` is not defined on `None` in union `Any | None`
gateway/platforms/dingtalk.py:1446: [unresolved-attribute] unresolved-attribute: Attribute `from_dict` is not defined on `None` in union `Unknown | None`
gateway/platforms/matrix.py:810: [unresolved-import] unresolved-import: Cannot resolve imported module `mautrix.util.async_db`
gateway/platforms/feishu.py:4577: [call-non-callable] call-non-callable: Object of type `None` is not callable
gateway/platforms/dingtalk.py:1067: [unresolved-attribute] unresolved-attribute: Attribute `CreateCardHeaders` is not defined on `None` in union `Unknown | None`
gateway/platforms/whatsapp.py:1078: [invalid-method-override] invalid-method-override: Invalid override of method `send_video`: Definition is incompatible with `BasePlatformAdapter.send_video`
gateway/platforms/whatsapp.py:1067: [invalid-method-override] invalid-method-override: Invalid override of method `send_image_file`: Definition is incompatible with `BasePlatformAdapter.send_image_file`
gateway/platforms/email.py:80: [invalid-assignment] invalid-assignment: Object of type `Literal["0"]` is not assignable to `Literal["0.16.0"]`
gateway/platforms/telegram.py:1519: [unresolved-attribute] unresolved-attribute: Attribute `builder` is not defined on `<special-form 'typing.Any'>` in union `Unknown | <special-form 'typing.Any'>`
gateway/platforms/wecom.py:1464: [invalid-method-override] invalid-method-override: Invalid override of method `send_voice`: Definition is incompatible with `BasePlatformAdapter.send_voice`
gateway/platforms/matrix.py:345: [unresolved-import] unresolved-import: Cannot resolve imported module `mautrix.types`
gateway/platforms/matrix.py:2809: [unresolved-import] unresolved-import: Cannot resolve imported module `markdown`
gateway/platforms/telegram.py:137: [unresolved-import] unresolved-import: Cannot resolve imported module `telegram.ext`
gateway/platforms/matrix.py:808: [unresolved-import] unresolved-import: Cannot resolve imported module `mautrix.crypto`
gateway/platforms/dingtalk.py:1276: [unresolved-attribute] unresolved-attribute: Attribute `RobotReplyEmotionRequest` is not defined on `None` in union `Unknown | None`
gateway/platforms/wecom.py:179: [unresolved-attribute] unresolved-attribute: Attribute `ClientWebSocketResponse` is not defined on `None` in union `Unknown | None`
gateway/platforms/dingtalk.py:78: [unresolved-import] unresolved-import: Cannot resolve imported module `alibabacloud_tea_util`
gateway/platforms/telegram.py:1618: [unresolved-attribute] unresolved-attribute: Attribute `Document` is not defined on `None` in union `Unknown | None`
hermes_cli/gateway.py:5177: [invalid-assignment] invalid-assignment: Object of type `None` is not assignable to `def qr_register(*, initial_domain: str = "feishu", timeout_seconds: int = 600) -> dict[Unknown, Unknown] | None`
gateway/platforms/dingtalk.py:257: [unresolved-attribute] unresolved-attribute: Attribute `AsyncClient` is not defined on `None` in union `Unknown | None`
hermes_cli/gateway.py:5249: [invalid-argument-type] invalid-argument-type: Argument to function `save_env_value` is incorrect: Expected `str`, found `Unknown | str | None`
gateway/platforms/dingtalk.py:1441: [unresolved-attribute] unresolved-attribute: Attribute `data` is not defined on `None` in union `Unknown | None`
gateway/platforms/telegram.py:2076: [unresolved-attribute] unresolved-attribute: Attribute `message_id` is not defined on `None` in union `None | Unknown`
gateway/platforms/feishu.py:1368: [unresolved-import] unresolved-import: Cannot resolve imported module `lark_oapi.core`
... and 157 more
Unchanged: 5008 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
1ba0a94 to
908dc9b
Compare
…ugins WIP toward #41112 — full transition of all gateway channels to plugins. dingtalk and whatsapp adapters relocated to plugins/platforms/<name>/ with register() + standalone_sender_fn / apply_yaml_config_fn / setup_fn / is_connected hooks. Core touchpoints stripped: run.py factory elifs, config.py YAML bridges + _PLATFORM_CONNECTED_CHECKERS entries, gateway.py static _PLATFORMS dicts + setup-map entries + _setup_* fns, send_message_tool dispatch (now via _registry_standalone_send) + _send_* helpers. matrix, feishu, telegram still to come in this branch.
WIP toward #41112. Matrix adapter relocated to plugins/platforms/matrix/ with register() + standalone_sender_fn (REST text path) / apply_yaml_config_fn / setup_fn (full E2EE-aware wizard) hooks. Core touchpoints stripped: run.py elif, config.py matrix_cfg YAML bridge, gateway.py static dict + setup-map entry, setup.py _setup_matrix, send_message_tool _send_matrix + dispatch. _send_matrix_via_adapter (native media path) kept in send_message_tool with its import repointed to plugins.platforms.matrix.adapter. Matrix uses the generic token connected-check (no is_connected override needed). feishu + telegram still to come.
…lugin WIP toward #41112. Feishu adapter + its feishu_comment / feishu_comment_rules / feishu_meeting_invite satellites relocated to plugins/platforms/feishu/ with internal imports rewritten to the new package path. register() exposes the platform with standalone_sender_fn (adapter-based send incl native media: images/video/voice/documents), apply_yaml_config_fn (allow_bots bridge), setup_fn (full QR-register + manual + DM/group-policy wizard), is_connected (app_id). Core touchpoints stripped: run.py elif, config.py feishu YAML bridge + _PLATFORM_CONNECTED_CHECKERS entry, gateway.py static dict + _setup_feishu + setup-map entry, send_message_tool _send_feishu + text dispatch + native-media branch (now via registry standalone_sender_fn) + FeishuAdapter MAX_LENGTHS import (registry max_message_length=8000 covers it). telegram still to come (the last one).
…undled plugin WIP toward #41112 — the last and largest gateway channel. Telegram adapter + telegram_network satellite relocated to plugins/platforms/telegram/ with the network import rewritten to the new package path. register() exposes the platform with standalone_sender_fn (delegates to the retained _send_telegram REST sender), apply_yaml_config_fn (full telegram: YAML→env + extra bridge), setup_fn (delegates to the managed-bot QR wizard via lazy import), and a _build_adapter that applies the notification-mode resolution that used to live in gateway/run.py's factory branch. Core touchpoints stripped: run.py factory branch (was the leading if), config.py 90-line telegram_cfg bridge, gateway.py static dict + setup-map entry. send_message_tool keeps _send_telegram (the plugin delegates to it) with its TelegramAdapter imports repointed to the plugin path. Generic Platform.TELEGRAM references in core (auth maps, bridged config-loop special-cases, source-platform behavior checks) intentionally remain — same 'left generic in core' policy as the merged migrations.
… discovery, telegram extra precedence, prompt_choice import
- Sweep test imports gateway.platforms.{telegram,feishu,matrix,dingtalk,whatsapp}
(+ telegram_network / feishu satellites) -> plugins.platforms.<x>.adapter
across ~68 test files; both 'from X import' and 'from gateway.platforms import X'
forms.
- _is_platform_connected now forces discover_plugins() before the registry
lookup so get_connected_platforms() works on directly-constructed GatewayConfig
(fixes dingtalk-recognised tests after its checker moved to the plugin).
- telegram _apply_yaml_config no longer re-emits generic shared-config keys
(reply_prefix etc.) that _merge_platform_map already merges with top-level
precedence, while still passing through telegram-specific extras (base_url).
- prompt_choice lives in hermes_cli.setup, not cli_output — fixed the import in
feishu/dingtalk interactive_setup and the test patch target.
- test_setup_feishu rewritten to drive interactive_setup via the plugin.
…ndalone_sender_fn The _send_matrix / _send_whatsapp inline helpers moved into their plugins' _standalone_send (#41112). Updated the three affected tests to patch / call the plugin registry standalone_sender_fn instead of the removed module-level helpers; behavior assertions (lightweight text path, bridge routing, room-ID percent-encoding) preserved.
…hecker invariant + webhook-secret source path - Restore TELEGRAM_REQUIRE_MENTION env bridge for the top-level require_mention shorthand (#3979) in core config.py — keys off the top-level key, not a telegram: block, so the plugin hook (which needs a block) can't cover the no-telegram-block case. - test_all_builtins_have_checker_or_generic_token_path now also accepts registry-provided is_connected/validate_config (dingtalk/whatsapp/feishu checkers moved to their plugins). - test_telegram_webhook_secret reads the adapter source from the new plugins/platforms/telegram/adapter.py path.
…platforms; test path/import updates - hermes_logging COMPONENT_PREFIXES['gateway'] now includes plugins.platforms so migrated adapters' logs route to gateway.log + match 'hermes logs --component gateway'. - Generalize the _enabled_explicit marker (was slack-only) to every platform with an explicit enabled key, and make _enable_from_env read (not pop) it, so the registry-driven plugin-enable pass honors an explicit enabled:false for telegram/matrix/etc. instead of re-enabling on token/SDK presence. - Telegram gets an is_connected (token check) so the enable gate doesn't flip it on merely because python-telegram-bot is importable. - Test updates: windows-native npm-scan path -> plugins/platforms/whatsapp, webhook-secret source path -> plugin adapter, logging component tests use expanded gateway prefixes, connected-checker invariant accepts registry is_connected/validate_config.
… explicit is_connected; setup-flow test stubs - whatsapp/telegram/matrix _is_connected now read tokens via hermes_cli.gateway.get_env_value (not os.getenv) so setup-status callers that patch get_env_value — and the connected-platforms check — observe the same value (matches the discord/slack plugin pattern). whatsapp keys off WHATSAPP_ENABLED instead of returning unconditional True (was making it always show 'configured' in hermes setup). matrix/telegram gain explicit is_connected so _platform_status reflects real config, not mere SDK presence. - _all_platforms() hides matrix on Windows for registry-discovered plugins too (python-olm has no Windows wheel), not just the legacy _PLATFORMS list. - setup_gateway tests stub _configure_platform + keep checklist pre-selection so migrated plugins' interactive_setup wizards don't read real stdin.
Was an exact-tuple snapshot ('gateway','hermes_plugins'); now asserts the
required prefixes (incl. the new plugins.platforms from #41112) as an
invariant so future gateway-component prefixes don't break it.
… plugin Completes #41112 — the last unclaimed chat-platform channels. WeCom Smart Robot (wecom) and callback-mode self-built apps (wecom_callback), sharing the wecom_crypto satellite, relocated to plugins/platforms/wecom/ (adapter.py + callback_adapter.py + wecom_crypto.py, internal crypto import rewritten). register() exposes BOTH platforms via the registry with standalone_sender_fn (wecom WebSocket send), setup_fn (QR/manual wizard), is_connected (bot_id / corp_id). Core touchpoints stripped: run.py 2 factory elifs, config.py 2 _PLATFORM_CONNECTED_CHECKERS entries, gateway.py 2 static dicts + _setup_wecom + setup-map entry, send_message_tool _send_wecom (now registry dispatch). Env->PlatformConfig seeding stays in core. 191 wecom-related tests pass.
…_send + restore dingtalk token redaction CI (test shard 6) caught tests/tools/test_send_message_missing_platforms.py importing the removed _send_dingtalk/_send_matrix helpers. Added thin pre-migration-shaped shims around the plugins' _standalone_send (same pattern mattermost/HA used in this file). Also restored access_token redaction in the dingtalk plugin's _standalone_send error path (the legacy _send_dingtalk returned via _error() which redacts URL secrets; the bare plugin return leaked the webhook access_token in exception text) by reusing send_message_tool._error via lazy import.
908dc9b to
91da240
Compare
Migrates the remaining unclaimed, genuinely-messaging channels: email (IMAP
poll + SMTP reply) and sms (Twilio REST). Both relocated to
plugins/platforms/{email,sms}/ with register() + standalone_sender_fn +
is_connected. Core touchpoints stripped: run.py 2 factory elifs, config.py 2
_PLATFORM_CONNECTED_CHECKERS entries, gateway.py 2 static dicts,
send_message_tool _send_email/_send_sms (now registry dispatch). Both
standalone senders preserve credential redaction via send_message_tool._error;
sms preserves markdown stripping; both marked pii_safe. env->PlatformConfig
seeding stays in core.
Deliberately NOT migrated: webhook + api_server + msgraph_webhook (generic
HTTP/ingress surfaces the #41112 tracker flags as not platform-shaped); and
signal/qqbot/weixin/yuanbao/bluebubbles (open contributor PRs).
…ange (#f6f363662) Pre-existing main breakage, not migration fallout: f6f3636 made _component_check_auth fail closed when no allowlist is set but only updated test_discord_component_auth.py, leaving test_discord_model_picker's empty-allowlist case asserting events that the now-rejected click never produces. Give the picker view an allowlist containing the interacting user ({"123"}) so the authorized path — which is what this control-clearing test actually exercises — runs. Confirmed: fails on current main (a317e54 red), passes on the stale local clone that lacks f6f3636.
…-closed change (#f6f363662) Same pre-existing main breakage as the model-picker fix: f6f3636 made component-button auth fail closed but only updated test_discord_component_auth.py. test_discord_clarify_buttons' test_choice_falls_back_to_label_text_when_entry_missing and test_other_flips_entry_to_awaiting_text drove the authorized-proceed path with an empty allowlist, which now correctly rejects. Give the interacting user (id 42) an allowlist entry so the proceed path runs (the dedicated *_unauthorized_* tests still cover rejection). Verified green under the hermetic per-file runner.
…Error (cryptography version skew)
CI shard (test 1) deterministically failed importing the dingtalk plugin:
alibabacloud_dingtalk transitively imports cryptography and raises
AttributeError ('cryptography.utils' has no attribute 'DeprecatedIn46') when
CI's cryptography is older than the SDK expects. The adapter guarded that SDK
import with 'except ImportError', which does NOT catch AttributeError, so the
whole adapter (and thus plugin discovery via __init__'s 'from .adapter import
register') crashed instead of degrading. Broadened the alibabacloud_dingtalk
guard, the dingtalk_stream guard, and the check_dingtalk_requirements lazy
re-import to 'except Exception' so a broken optional SDK dependency chain
degrades gracefully (CARD_SDK_AVAILABLE/DINGTALK_STREAM_AVAILABLE=False), same
as a missing dep. This was invisible before migration because the inline
adapter was only imported when dingtalk was activated, not at plugin-discovery
time.
…ge (#f6f363662) Pre-existing main breakage inherited via rebase, not slack-migration fallout: f6f3636 made discord component-button auth fail closed when no allowlist is set but only updated test_discord_component_auth.py. test_discord_model_picker and two test_discord_clarify_buttons tests drove the authorized-proceed path with an empty allowlist, which now correctly rejects. Give the interacting user an allowlist entry so the proceed path runs (dedicated *_unauthorized_* tests still cover rejection). Same fix as #41284; both PRs un-break main's currently-red CI.
Move gateway/platforms/slack.py into plugins/platforms/slack/ following the Discord (#24356) and Home Assistant (#40709) migrations. Advances #41112 / hardcoded Platform.SLACK touchpoints in core. - Adapter file renamed via git mv (history preserved). - register() exposes the platform via ctx.register_platform() instead of the Platform.SLACK elif in gateway/run.py::_create_adapter(). - _standalone_send() replaces the legacy _send_slack() helper in tools/send_message_tool.py; out-of-process cron delivery (deliver=slack) now flows through the registry's standalone_sender_fn. mrkdwn formatting moved into the plugin (was applied in _send_to_platform before chunking). - _apply_yaml_config() owns the config.yaml slack: -> SLACK_* env bridge (require_mention, strict_mention, allow_bots, free_response_channels, reactions, allowed_channels), replacing the hardcoded block in gateway/config.py. - interactive_setup() replaces hermes_cli/setup.py::_setup_slack + _write_slack_manifest_and_instruct and the static _PLATFORMS["slack"] dict in hermes_cli/gateway.py; setup metadata is discovered dynamically. - is_connected() probes SLACK_BOT_TOKEN via hermes_cli.gateway.get_env_value. - max_message_length=39000 on the PlatformEntry; the registry fallback in send_message_tool covers it (dropped the _MAX_LENGTHS entry). The SLACK_BOT_TOKEN/SLACK_HOME_CHANNEL env->PlatformConfig seeding and the _is_user_authorized allowlist maps stay in core (same as Discord/HA/Mattermost). Bug fixed during migration: the registry-driven plugin-enable pass in _apply_env_overrides re-enabled any plugin platform whose is_connected() passed, ignoring an explicit enabled: false. Slack is the first plugin with an enabled-false-wins test, so it exposed this latent bug (Discord had no such test). Added an explicit-disable guard (_enabled_explicit + enabled=False -> skip) and changed the slack env-block to read the flag instead of popping it so the guard can see it; the flag is still cleared in the final per-platform cleanup. Restores test_explicit_{top_level,platforms}_slack_enabled_false_wins. Test imports rewritten across 11 files (gateway.platforms.slack -> plugins.platforms.slack.adapter). The _setup_slack home-channel tests moved to tests/gateway/test_slack_plugin_setup.py exercising interactive_setup. The test_send_message_tool slack-formatting tests now patch the registry standalone_sender_fn (via _patch_slack_standalone_sender) and assert the mrkdwn-formatted text reaches the wire. Validation: 706 targeted tests pass (slack/config/setup/registry/send/media suites); 18/18 live E2E checks pass (real plugin discovery + registry resolves SlackAdapter, env-only enable, standalone sender wired, YAML bridge, dynamic setup discovery).
|
Reviewed this end-to-end (fetched into a worktree, ran the migrated-platform + shared-surface test suites serially, plus targeted repros). Solid, behavior-preserving migration overall — telegram's full YAML bridge is intact (all keys + the bare- One blocker and a couple of smaller notes: 🔴 HIGH — explicit
|
…gram/wecom/email/sms adapters to bundled plugins Salvage of PR #41284 onto current main. Relocates the last 9 inline messaging adapters (+ satellites: telegram_network, feishu_comment/_rules/meeting_invite, wecom_crypto, wecom_callback) from gateway/platforms/ into self-contained bundled plugins under plugins/platforms/<x>/, discovered via the platform registry. Strips the per-platform core touchpoints from gateway/run.py, gateway/config.py, hermes_cli/gateway.py, hermes_cli/setup.py, and tools/send_message_tool.py. Carries forward the migration fixes (explicit enabled:false honored, get_connected_platforms forces discovery, plugin is_connected via gateway.get_env_value, logs --component gateway matches plugins.platforms.*, matrix hidden on Windows). Additionally ports config keys main added since the PR base: the matrix plugin's _apply_yaml_config now also covers allowed_users, ignore_user_patterns, process_notices, and session_scope (the inline gateway/config.py matrix block gained these in the 1340 commits the PR sat open; they would otherwise have been silently dropped on deletion).
…gram/wecom/email/sms adapters to bundled plugins Salvage of PR #41284 onto current main. Relocates the last 9 inline messaging adapters (+ satellites: telegram_network, feishu_comment/_rules/meeting_invite, wecom_crypto, wecom_callback) from gateway/platforms/ into self-contained bundled plugins under plugins/platforms/<x>/, discovered via the platform registry. Strips the per-platform core touchpoints from gateway/run.py, gateway/config.py, hermes_cli/gateway.py, hermes_cli/setup.py, and tools/send_message_tool.py. Carries forward the migration fixes (explicit enabled:false honored, get_connected_platforms forces discovery, plugin is_connected via gateway.get_env_value, logs --component gateway matches plugins.platforms.*, matrix hidden on Windows). Additionally ports config keys main added since the PR base: the matrix plugin's _apply_yaml_config now also covers allowed_users, ignore_user_patterns, process_notices, and session_scope (the inline gateway/config.py matrix block gained these in the 1340 commits the PR sat open; they would otherwise have been silently dropped on deletion).
|
Merged via #49408 onto current Your branch was ~1340 commits stale, so a plain cherry-pick would have reverted large swaths of unrelated work. The migration was re-applied surgically on current Two things that had drifted since this PR opened were also fixed in the salvage:
Verified end-to-end before merge: registry resolves all 10 platforms; |
…gram/wecom/email/sms adapters to bundled plugins Salvage of PR NousResearch#41284 onto current main. Relocates the last 9 inline messaging adapters (+ satellites: telegram_network, feishu_comment/_rules/meeting_invite, wecom_crypto, wecom_callback) from gateway/platforms/ into self-contained bundled plugins under plugins/platforms/<x>/, discovered via the platform registry. Strips the per-platform core touchpoints from gateway/run.py, gateway/config.py, hermes_cli/gateway.py, hermes_cli/setup.py, and tools/send_message_tool.py. Carries forward the migration fixes (explicit enabled:false honored, get_connected_platforms forces discovery, plugin is_connected via gateway.get_env_value, logs --component gateway matches plugins.platforms.*, matrix hidden on Windows). Additionally ports config keys main added since the PR base: the matrix plugin's _apply_yaml_config now also covers allowed_users, ignore_user_patterns, process_notices, and session_scope (the inline gateway/config.py matrix block gained these in the 1340 commits the PR sat open; they would otherwise have been silently dropped on deletion).
…gram/wecom/email/sms adapters to bundled plugins Salvage of PR NousResearch#41284 onto current main. Relocates the last 9 inline messaging adapters (+ satellites: telegram_network, feishu_comment/_rules/meeting_invite, wecom_crypto, wecom_callback) from gateway/platforms/ into self-contained bundled plugins under plugins/platforms/<x>/, discovered via the platform registry. Strips the per-platform core touchpoints from gateway/run.py, gateway/config.py, hermes_cli/gateway.py, hermes_cli/setup.py, and tools/send_message_tool.py. Carries forward the migration fixes (explicit enabled:false honored, get_connected_platforms forces discovery, plugin is_connected via gateway.get_env_value, logs --component gateway matches plugins.platforms.*, matrix hidden on Windows). Additionally ports config keys main added since the PR base: the matrix plugin's _apply_yaml_config now also covers allowed_users, ignore_user_patterns, process_notices, and session_scope (the inline gateway/config.py matrix block gained these in the 1340 commits the PR sat open; they would otherwise have been silently dropped on deletion).
…gram/wecom/email/sms adapters to bundled plugins Salvage of PR NousResearch#41284 onto current main. Relocates the last 9 inline messaging adapters (+ satellites: telegram_network, feishu_comment/_rules/meeting_invite, wecom_crypto, wecom_callback) from gateway/platforms/ into self-contained bundled plugins under plugins/platforms/<x>/, discovered via the platform registry. Strips the per-platform core touchpoints from gateway/run.py, gateway/config.py, hermes_cli/gateway.py, hermes_cli/setup.py, and tools/send_message_tool.py. Carries forward the migration fixes (explicit enabled:false honored, get_connected_platforms forces discovery, plugin is_connected via gateway.get_env_value, logs --component gateway matches plugins.platforms.*, matrix hidden on Windows). Additionally ports config keys main added since the PR base: the matrix plugin's _apply_yaml_config now also covers allowed_users, ignore_user_patterns, process_notices, and session_scope (the inline gateway/config.py matrix block gained these in the 1340 commits the PR sat open; they would otherwise have been silently dropped on deletion).
…gram/wecom/email/sms adapters to bundled plugins Salvage of PR NousResearch#41284 onto current main. Relocates the last 9 inline messaging adapters (+ satellites: telegram_network, feishu_comment/_rules/meeting_invite, wecom_crypto, wecom_callback) from gateway/platforms/ into self-contained bundled plugins under plugins/platforms/<x>/, discovered via the platform registry. Strips the per-platform core touchpoints from gateway/run.py, gateway/config.py, hermes_cli/gateway.py, hermes_cli/setup.py, and tools/send_message_tool.py. Carries forward the migration fixes (explicit enabled:false honored, get_connected_platforms forces discovery, plugin is_connected via gateway.get_env_value, logs --component gateway matches plugins.platforms.*, matrix hidden on Windows). Additionally ports config keys main added since the PR base: the matrix plugin's _apply_yaml_config now also covers allowed_users, ignore_user_patterns, process_notices, and session_scope (the inline gateway/config.py matrix block gained these in the 1340 commits the PR sat open; they would otherwise have been silently dropped on deletion).
…gram/wecom/email/sms adapters to bundled plugins Salvage of PR NousResearch#41284 onto current main. Relocates the last 9 inline messaging adapters (+ satellites: telegram_network, feishu_comment/_rules/meeting_invite, wecom_crypto, wecom_callback) from gateway/platforms/ into self-contained bundled plugins under plugins/platforms/<x>/, discovered via the platform registry. Strips the per-platform core touchpoints from gateway/run.py, gateway/config.py, hermes_cli/gateway.py, hermes_cli/setup.py, and tools/send_message_tool.py. Carries forward the migration fixes (explicit enabled:false honored, get_connected_platforms forces discovery, plugin is_connected via gateway.get_env_value, logs --component gateway matches plugins.platforms.*, matrix hidden on Windows). Additionally ports config keys main added since the PR base: the matrix plugin's _apply_yaml_config now also covers allowed_users, ignore_user_patterns, process_notices, and session_scope (the inline gateway/config.py matrix block gained these in the 1340 commits the PR sat open; they would otherwise have been silently dropped on deletion).
…gram/wecom/email/sms adapters to bundled plugins Salvage of PR NousResearch#41284 onto current main. Relocates the last 9 inline messaging adapters (+ satellites: telegram_network, feishu_comment/_rules/meeting_invite, wecom_crypto, wecom_callback) from gateway/platforms/ into self-contained bundled plugins under plugins/platforms/<x>/, discovered via the platform registry. Strips the per-platform core touchpoints from gateway/run.py, gateway/config.py, hermes_cli/gateway.py, hermes_cli/setup.py, and tools/send_message_tool.py. Carries forward the migration fixes (explicit enabled:false honored, get_connected_platforms forces discovery, plugin is_connected via gateway.get_env_value, logs --component gateway matches plugins.platforms.*, matrix hidden on Windows). Additionally ports config keys main added since the PR base: the matrix plugin's _apply_yaml_config now also covers allowed_users, ignore_user_patterns, process_notices, and session_scope (the inline gateway/config.py matrix block gained these in the 1340 commits the PR sat open; they would otherwise have been silently dropped on deletion).
…gram/wecom/email/sms adapters to bundled plugins Salvage of PR NousResearch#41284 onto current main. Relocates the last 9 inline messaging adapters (+ satellites: telegram_network, feishu_comment/_rules/meeting_invite, wecom_crypto, wecom_callback) from gateway/platforms/ into self-contained bundled plugins under plugins/platforms/<x>/, discovered via the platform registry. Strips the per-platform core touchpoints from gateway/run.py, gateway/config.py, hermes_cli/gateway.py, hermes_cli/setup.py, and tools/send_message_tool.py. Carries forward the migration fixes (explicit enabled:false honored, get_connected_platforms forces discovery, plugin is_connected via gateway.get_env_value, logs --component gateway matches plugins.platforms.*, matrix hidden on Windows). Additionally ports config keys main added since the PR base: the matrix plugin's _apply_yaml_config now also covers allowed_users, ignore_user_patterns, process_notices, and session_scope (the inline gateway/config.py matrix block gained these in the 1340 commits the PR sat open; they would otherwise have been silently dropped on deletion).
Summary
Migrates ALL remaining inline messaging-platform adapters — slack, dingtalk, whatsapp, matrix, feishu, telegram, wecom (+ wecom_callback), email, and sms — out of
gateway/platforms/into self-contained bundled plugins underplugins/platforms/<x>/, discovered via the platform registry instead of hardcodedPlatform.<X>touchpoints. Completes the gateway-channel → plugin transition tracked in #41112 (companion to the registry architecture in #3823). With Discord, Home Assistant, Mattermost, Slack (#41160) and the born-as-plugin set already done, this removes the last hardcoded adapter branches from core.Changes
Each platform follows the established Discord/HA migration shape:
git mv(history preserved):gateway/platforms/<x>.py→plugins/platforms/<x>/adapter.py, plus__init__.py/plugin.yaml. Satellites travel with their adapter:telegram_network.py→ telegram plugin; the threefeishu_comment*/feishu_meeting_invitemodules → feishu plugin;wecom_crypto.py+wecom_callback.py→ wecom plugin (internal imports rewritten).register(ctx)exposes each platform with the hook set:standalone_sender_fn(out-of-process cron delivery),apply_yaml_config_fn(config.yaml → env/extra bridge),setup_fn(interactive wizard),is_connected,check_fn, plusallowed_users_env/allow_all_env/cron_deliver_env_var/max_message_length/emoji.gateway/run.pyfactory branches (telegram's leadingif, the rest elifs);gateway/config.pyper-platform YAML→env blocks +_PLATFORM_CONNECTED_CHECKERSentries;hermes_cli/gateway.pystatic_PLATFORMSdicts + setup-map entries;hermes_cli/setup.py_setup_matrix;tools/send_message_tool.py_send_<x>dispatch (now a generic_registry_standalone_sendregistry hook). Telegram keeps_send_telegram(its plugin delegates to it); matrix keeps_send_matrix_via_adapter(native-media path) with its import repointed.Deliberately left generic in core (same policy as prior migrations): the
Platform.<X>enum literals, the_is_user_authorizedallowlist maps, the cron delivery maps, and the bridged-loop shared-key handling.Fixes uncovered during migration
enabled: falsehonored for plugin platforms. The registry-driven plugin-enable pass re-enabled any plugin whosecheck_fn/is_connectedpassed, ignoring an explicit disable. Generalized the_enabled_explicitmarker (was slack-only), made_enable_from_envread (not pop) it, and added an explicit-disable guard.get_connected_platforms()forces plugin discovery before the registry checker lookup so directly-constructedGatewayConfigresolves migrated checkers.is_connectedreads viagateway.get_env_value(telegram/whatsapp/matrix) so setup-status and connected checks observe the same value; telegram/matrix gain explicitis_connectedso they aren't enabled on mere SDK presence.hermes logs --component gatewaynow matchesplugins.platforms.*adapter logs (added toCOMPONENT_PREFIXES).Validation
ddgsinstalled locally, absent in CI — identical failures on cleanmain)Test imports swept across ~68 files (
gateway.platforms.<x>→plugins.platforms.<x>.adapter);_setup_matrix/_setup_feishutests retargeted to the plugins'interactive_setup; send-helper tests retargeted to the registrystandalone_sender_fn.Scope
Deliberately not migrated and left in core: webhook, api_server, msgraph_webhook (generic HTTP / change-notification ingress surfaces the #41112 tracker flags as not platform-shaped). signal, qqbot, weixin, yuanbao, bluebubbles are excluded because they have open contributor migration PRs (#41061, #41065, #41101, #40804, #31872) — preserving that work. Slack was folded in from #41160 (now closed) so this is the single PR for the whole transition.
Infographic