Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -7947,7 +7947,9 @@ def _handle_model_switch(self, cmd_original: str):
# config-gated default, --global forces persist, otherwise defer to
# model.persist_switch_by_default (defaults to True so /model survives
# across sessions).
persist_global = resolve_persist_behavior(is_global_flag, is_session)
persist_global = resolve_persist_behavior(
is_global_flag, is_session, explicit_provider
)

# --refresh: wipe the on-disk picker cache before building the
# provider list. Forces a live re-fetch of every authed provider's
Expand Down
4 changes: 3 additions & 1 deletion gateway/slash_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -1399,7 +1399,9 @@ async def _handle_model_command(self, event: MessageEvent) -> Optional[str]:
force_refresh,
is_session,
) = parse_model_flags(raw_args)
persist_global = resolve_persist_behavior(is_global_flag, is_session)
persist_global = resolve_persist_behavior(
is_global_flag, is_session, explicit_provider
)

# --refresh: bust the disk cache so the picker shows live data.
if force_refresh:
Expand Down
14 changes: 12 additions & 2 deletions hermes_cli/model_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,14 +365,22 @@ def parse_model_flags(raw_args: str) -> tuple[str, str, bool, bool, bool]:
return (model_input, explicit_provider, is_global, force_refresh, is_session)


def resolve_persist_behavior(is_global: bool, is_session: bool) -> bool:
def resolve_persist_behavior(
is_global: bool,
is_session: bool,
explicit_provider: str = "",
) -> bool:
"""Decide whether a ``/model`` switch should persist to ``config.yaml``.

Resolution order:

1. ``--session`` explicitly opts out β†’ ``False`` (this session only).
2. ``--global`` explicitly opts in β†’ ``True``.
3. Otherwise defer to ``model.persist_switch_by_default`` in
3. ``--provider`` given without an explicit persist flag β†’ ``False``
(session only). Provider switches are typically exploratory β€” the
user is trying a different backend for this conversation, not
reconfiguring the default. ``--global`` can still force persist.
4. Otherwise defer to ``model.persist_switch_by_default`` in
``config.yaml`` (defaults to ``True``, so a plain ``/model <name>``
survives across sessions β€” the behavior users expect).

Expand All @@ -384,6 +392,8 @@ def resolve_persist_behavior(is_global: bool, is_session: bool) -> bool:
return False
if is_global:
return True
if explicit_provider:
return False
try:
from hermes_cli.config import load_config

Expand Down
20 changes: 20 additions & 0 deletions tests/hermes_cli/test_model_switch_persist_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,26 @@ def test_session_overrides_global_when_both_set(self):
with _config({"model": {"persist_switch_by_default": True}}):
assert resolve_persist_behavior(True, True) is False

def test_provider_flag_defaults_to_session_only(self):
# --provider without --global/--session β†’ session only.
with _config({"model": {"persist_switch_by_default": True}}):
assert resolve_persist_behavior(False, False, "anthropic") is False

def test_provider_with_global_still_persists(self):
# --provider + --global β†’ persists.
with _config({"model": {"persist_switch_by_default": False}}):
assert resolve_persist_behavior(True, False, "anthropic") is True

def test_provider_with_session_still_session_only(self):
# --provider + --session β†’ session only.
with _config({"model": {"persist_switch_by_default": True}}):
assert resolve_persist_behavior(False, True, "anthropic") is False

def test_no_provider_uses_config_default(self):
# No --provider β†’ respects config default (True).
with _config({"model": {"persist_switch_by_default": True}}):
assert resolve_persist_behavior(False, False, "") is True


# ---------------------------------------------------------------------------
# helper
Expand Down
4 changes: 3 additions & 1 deletion tui_gateway/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2628,7 +2628,9 @@ def _apply_model_switch(
_force_refresh,
is_session,
) = parsed_flags
persist_global = resolve_persist_behavior(is_global_flag, is_session)
persist_global = resolve_persist_behavior(
is_global_flag, is_session, explicit_provider
)
if not model_input:
raise ValueError("model value required")

Expand Down
Loading