fix(gateway): resolve per-profile home channel in multiplex mode - #60743
fix(gateway): resolve per-profile home channel in multiplex mode#60743lexiismadd wants to merge 1 commit into
Conversation
teknium1
left a comment
There was a problem hiding this comment.
Thanks for tracing the stale process-environment reads; the underlying multiplexing defect is present on current main (gateway/config.py:768-773, gateway/run.py:11399-11402). The implementation needs changes before it can safely provide the claimed guarantee.
Problems
- The new onboarding
get_secret()call is not inside_profile_runtime_scope: direct/sethomedispatch occurs atgateway/run.py:9857, while the normal inbound scope is only entered by_run_agentatgateway/run.py:16846. In multiplex mode an unscoped read raises (agent/secret_scope.py:149-157), and the patch catches it and falls back to process-globalos.getenv(). - The new map uses
MATRIX_HOME_CHANNELandEMAIL_HOME_CHANNEL, but main usesMATRIX_HOME_ROOM(gateway/config.py:1679) andEMAIL_HOME_ADDRESS(gateway/config.py:1713). - Removing the in-memory
/sethomeupdate does not refresh an active secret-scope mapping;save_env_value()updatesos.environathermes_cli/config.py:7602, while a scope remains authoritative (agent/secret_scope.py:144-147). Existing same-process behavior is covered attests/gateway/test_restart_notification.py:182-243.
Suggested changes
- Scope direct command/onboarding paths by
source.profile, use canonical target keys, and add multiplex regressions for secondary-profile/sethomeplus Matrix/email targets.
Automated hermes-sweeper review.
| # get_secret so the notice honors the same per-profile resolution | ||
| # path as the rest of the gateway. | ||
| try: | ||
| from agent.secret_scope import get_secret as _get_secret |
There was a problem hiding this comment.
This lookup is still outside _profile_runtime_scope: that scope is entered later by _run_agent (gateway/run.py:16846), while this onboarding branch runs during _handle_message_with_agent. In multiplex mode get_secret() therefore raises, and this except falls back to the same cross-profile os.getenv() value the change is intended to eliminate. Scope this path by source.profile instead of falling back to process-global environment state.
When running multiplex_profiles: true, all profiles shared a single state.db for session storage. This adds per-profile state.db files so each profile's sessions, routing tables, and slash commands write to the correct profile's database. Changes: - gateway/run.py: _build_profile_session_dbs() creates per-profile AsyncSessionDBs; _session_db_for(source) routes to the correct DB; SessionStore wired with get_profile_db callback - gateway/session.py: SessionStore accepts get_profile_db callback; routing table persistence and session reset use per-profile DB - gateway/slash_commands.py: all slash commands route through _session_db_for(source) instead of self._session_db - gateway/config.py: get_home_channel() reads live via get_secret() when a profile secret scope is active (from PR NousResearch#60743) - hermes_state.py: ON CONFLICT preserves user_id and source via COALESCE to prevent null-overwrite on profile-scoped writes - plugins/platforms/matrix/adapter.py: per-sender/room profile routing via MATRIX_SENDER_PROFILE_MAP env var or config.extra maps Also addresses teknium1 review on PR NousResearch#60743: - /sethome notice check uses get_secret() instead of os.getenv() - /sethome handler drops racy in-memory home_channel write - Matrix routing config documented in adapter docstring
4c988ea to
fe65551
Compare
|
Closing after a hunk-by-hunk review against current main — the home-channel core is superseded and the rest needs a fresh start:
That session-DB isolation idea is genuinely valuable: if you re-propose it as a focused PR against the current SessionStore with tests, happy to prioritize the review. Thanks for the work here. |
Summary
When running multiple profiles in a single gateway process (
multiplex_profiles: true), each profile needs its ownTELEGRAM_HOME_CHANNEL(and equivalent per-platform home channels) so cron deliveries, restart notifications, and the per-chat home-channel notice are scoped to the correct chat.Previously:
get_home_channel()(gateway/config.py) returned aHomeChannelcached once at config-load time viaos.getenv(), which always read the default profile's environment./sethomenotice check in run.py usedos.getenv(env_key)directly, bypassing any per-profile resolution./sethomehandler in slash_commands.py wrote the in-memory cache viaplatform_config.home_channel = HomeChannel(...), which raced between profiles in multiplex mode (last-write-wins).The fix:
get_home_channel()now reads live viaagent.secret_scope.get_secret()when a profile secret scope is active, falling back toos.getenv()in single-profile mode, then to the cached attribute. This honors the active per-profile scope on every call, so cron deliveries, restart notifications, and the per-chat notice all see the correct value./sethomenotice check in run.py also usesget_secret()for the same reason./sethomehandler no longer mutates the in-memory cache; thesave_env_value()call already persists to the active profile's.env, and the next live read picks up the new value. The in-memory write was racy and is no longer needed.The existing
_HOME_CHANNEL_NAME_ENV_KEYSand thread-id maps remain limited to Telegram/Discord, matching the current scope ofname/thread_idresolution. Other platforms fall through to the cached attribute (same as before).Verified live: lexi DM bot no longer prompts for
/sethomeafter gateway restart despite the lexi.envhavingTELEGRAM_HOME_CHANNEL=5397107712(its user ID). The family group's home channel still routes to-1002369818110correctly.Files changed
gateway/config.py:get_home_channel()now does live resolution viaget_secret(); added_HOME_CHANNEL_ENV_KEYSmap.gateway/run.py:/sethomenotice check usesget_secret()instead ofos.getenv().gateway/slash_commands.py:/sethomehandler drops in-memoryplatform_config.home_channelwrite;save_env_value()handles persistence.Test plan
Three unit tests added (in PR description; reproducible via
venv/bin/python):get_home_channel()returns env value with correct name/thread_id.get_home_channel()returns scope value, overriding env.platform_config.home_channel.Manual verification on the user's deployment: lexi DM bot stopped prompting for
/sethomeafter gateway restart, and the family group home channel still routes correctly.Related
_is_telegram_topic_lane→self._session_db.is_telegram_topic_mode_enabled(), and appears to be a separate ContextVar propagation issue in the multiplex refactor that landed recently. Filing as a follow-up.