Skip to content

fix(gateway): make /model session-scoped by default on messaging platforms - #63095

Closed
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:liuhao/cron-bugfix-63083
Closed

fix(gateway): make /model session-scoped by default on messaging platforms#63095
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:liuhao/cron-bugfix-63083

Conversation

@liuhao1024

Copy link
Copy Markdown
Contributor

What does this PR do?

Changes /model behavior on messaging platforms (gateway) from persisting to global config.yaml by default to session-scoped by default.

Previously, /model on gateway would follow CLI behavior via the model.persist_switch_by_default config setting, which defaults to True. This meant switching models in one chat would write the change to the global config.yaml, affecting all other sessions — unintended cross-session pollution.

Messaging platform sessions are typically ephemeral and per-chat, so this PR changes the default to session-scoped: the switch applies to the current chat only, survives gateway restart via the session DB, but does not persist to disk unless --global is explicitly passed.

This aligns gateway /model behavior with user expectations for messaging platform UX, while CLI behavior (persistence by default) remains unchanged.

Related Issue

Fixes #63083

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • gateway/slash_commands.py: Changed persist_global logic to default to False on messaging platforms unless --global is explicitly passed or --session is explicitly passed. Added comment explaining the rationale and reference to /model writes to global config.yaml without --global flag on cross-provider switch attempts #63083.
  • tests/gateway/test_model_picker_persist.py: Updated test_picker_tap_persists_by_defaulttest_picker_tap_does_not_persist_by_default to reflect the new behavior (session-scoped by default). Added new test test_picker_tap_with_global_flag_persists to verify --global flag works correctly.
  • tests/gateway/test_model_command_flat_string_config.py: Updated test_model_no_flag_persists_by_defaulttest_model_no_flag_does_not_persist_by_default to reflect the new behavior.

How to Test

  1. Run gateway on a messaging platform (Telegram/Discord)
  2. Start a session with model A
  3. In a chat, run /model gpt-5.5 (no flags)
  4. Verify: the session switches to gpt-5.5 and shows "session only" hint
  5. Check ~/.hermes/config.yaml — should still have model A
  6. In the same chat, run /model claude-sonnet-4.6 --global
  7. Verify: the session switches to claude-sonnet-4.6 and shows "saved to global config" hint
  8. Check ~/.hermes/config.yaml — should now have claude-sonnet-4.6
  9. Run pytest tests/gateway/test_model_picker_persist.py tests/gateway/test_model_command_flat_string_config.py -q — all tests pass

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 26.4.1

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

…forms

Previously, /model on messaging platforms (gateway) would persist to
global config.yaml by default, matching CLI behavior via the
model.persist_switch_by_default config setting. This caused unintended
cross-session pollution when users switched models in one chat, as the
global config change affected all other sessions.

On messaging platforms, sessions are typically ephemeral and per-chat,
so /model now defaults to session-scoped behavior: the switch applies
to the current chat only and survives gateway restart via the session DB,
but does not write to config.yaml unless --global is explicitly passed.

This differs from CLI behavior (where /model still persists by default)
to align with user expectations for messaging platform UX.

Fixes NousResearch#63083
@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery area/config Config system, migrations, profiles sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades P2 Medium — degraded but workaround exists duplicate This issue or pull request already exists labels Jul 12, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Duplicate of #61488 (liuhao... earlier, still open) — diff-compared: both edit gateway/slash_commands.py at the same site in _handle_model_command (right after parse_model_flags) with the identical mechanism: default /model to session-scope on messaging (non-LOCAL) platforms unless --global is explicitly passed, to stop picker taps from writing the global config.yaml. Both also update the same test_model_no_flag_persists_by_default test. #61488 (2026-07-09) predates this PR (2026-07-12) and is the canonical fix; this one cites #63083 while #61488 cites #61458, but the code-site and mechanism are the same. Same gateway /model session-scope cluster as #62827 / #59493.

@liuhao1024

Copy link
Copy Markdown
Contributor Author

This PR is a duplicate of #$61488.

Both PRs fix the same issue (messaging platform /model command defaulting to global config) by modifying the same code path (_handle_model_command in gateway/slash_commands.py).

PR #$61488 (created 2026-07-09) is the earlier submission with a more explicit implementation (checking source.platform type).

Closing this PR in favor of the canonical earlier submission.

@liuhao1024 liuhao1024 closed this Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/gateway Gateway runner, session dispatch, delivery duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

/model writes to global config.yaml without --global flag on cross-provider switch attempts

2 participants