refactor(plugins): add apply_yaml_config_fn registry hook for YAML→env config bridges#24849
Closed
kshitijk4poor wants to merge 1 commit into
Closed
refactor(plugins): add apply_yaml_config_fn registry hook for YAML→env config bridges#24849kshitijk4poor wants to merge 1 commit into
kshitijk4poor wants to merge 1 commit into
Conversation
Lets platform plugins own their YAML→env config bridge instead of forcing core gateway/config.py to know every platform's schema. The hook receives the full parsed config.yaml and the platform's own sub-dict, may mutate os.environ (env > YAML precedence preserved via the standard `not os.getenv(...)` guards), and may return a dict to merge into PlatformConfig.extra. It runs during load_gateway_config() after the existing generic shared-key loop and before _apply_env_overrides(), mirroring the env_enablement_fn dispatch pattern (NousResearch#21306, NousResearch#21331). Pure addition — no behavior change for existing platforms. Each of the eight platforms with hardcoded YAML→env blocks today (discord, telegram, whatsapp, slack, dingtalk, mattermost, matrix, feishu, ~252 LOC in gateway/config.py) can migrate in independent follow-up PRs; the hardcoded blocks remain functional in the meantime, and their `not os.getenv(...)` guards make them no-ops for any env var the hook already set. Test coverage: 10 new tests in tests/gateway/test_platform_registry.py covering field default, callable acceptance, env mutation, extras merge, both signature args, exception swallowing, missing/non-dict sections, and env > YAML precedence. Refs NousResearch#3823, NousResearch#24356. Closes NousResearch#24836.
e5658e7 to
12c83ec
Compare
Contributor
|
Salvaged onto current main via PR #25443 — cherry-pick was clean, your authorship is preserved in |
28 tasks
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
Adds
apply_yaml_config_fntoPlatformEntryso platform plugins can own their YAML→env config bridges instead of forcing coregateway/config.pyto know every platform's schema. Pure addition — no behavior change for existing platforms.Closes #24836. Refs #3823, #24356.
Why
gateway/config.pycurrently has hardcoded YAML→env bridges for 8 platforms (discord, telegram, whatsapp, slack, dingtalk, mattermost, matrix, feishu, ~252 LOC). When a platform migrates to the bundled plugin system (e.g. Discord in #24356), its bridge stays stuck in core. Third-party plugin platforms can't bridge YAML keys to env at all without monkey-patchingload_gateway_config. The existingenv_enablement_fnhook (#21306, #21331) handles env→extras seeding but not YAML→env, which is the symmetric case this hook covers.What changed
gateway/platform_registry.pyapply_yaml_config_fn: Optional[Callable[[dict, dict], Optional[dict]]] = Nonefield onPlatformEntry.gateway/config.pyload_gateway_config()immediately after the generic shared-key loop. Iterates registry entries, calls hook with(yaml_cfg, platform_cfg), swallows exceptions to debug log (matchesenv_enablement_fnprecedent), merges any returned dict into the platform'sextraviaplatforms_dataso it survivesfrom_dict.tests/gateway/test_platform_registry.pynot os.getenv(...)guards.gateway/platforms/ADDING_A_PLATFORM.mdenv_enablement_fn.website/docs/developer-guide/adding-platform-adapters.mdhermes_cli/plugins.py::register_platform()already forwards**entry_kwargstoPlatformEntry, so plugins can passapply_yaml_config_fn=immediately with no plugin-side core change.Order of operations
This order means each of the 8 hardcoded platforms can migrate independently in follow-up PRs without breaking anything, and migration is net-negative LOC per platform.
Example usage (for a future plugin migration PR)
Test plan
bash scripts/run_tests.sh tests/gateway/test_platform_registry.py→ 42 passed (32 existing + 10 new).bash scripts/run_tests.sh tests/gateway/test_discord_reply_mode.py tests/gateway/test_slack_mention.py tests/gateway/test_whatsapp_reply_prefix.py tests/gateway/test_whatsapp_group_gating.py→ 118 passed (every YAML-loading test in the gateway suite).tests/gateway/→ 5367 passed, 9 failures all pre-existing onorigin/main(Discord document-handling + Matrix E2EE — verified by stashing this PR and re-running on stock main).load_gateway_config(): registered a temporary plugin platform with a YAML→env hook in a tmpHERMES_HOME, wrote a config.yaml exercising both the new hook AND the existing Discord hardcoded block, and verified:discord.require_mentionanddiscord.allowed_channelsto env vars.PlatformConfig.extra.Out of scope (future PRs)
Platform.DISCORDenum, allowlist maps,_UPDATE_ALLOWED_PLATFORMS, voice-mode adapter access) — independent generic-registry concerns deserving their own scoping issues.