fix(sessions): /save lands under $HERMES_HOME, widen browse+TUI picker, force-refresh ollama-cloud on setup (#16296)

Four independent session-UX bugs reported by an external user (#16294).

/save wrote hermes_conversation_<ts>.json to CWD — invisible to
'hermes sessions browse' and easy to lose. Snapshots now write under
~/.hermes/sessions/saved/ and the command prints the absolute path plus
a 'hermes --resume <id>' hint for the live DB-indexed session.

'hermes sessions browse' default --limit raised from 50 to 500. With the
old ceiling, users with moderately long histories saw only the most
recent 50 rows and assumed older sessions had been lost.

TUI session.list (`/resume` picker) switched from a hardcoded allow-list
of 13 gateway source names to a deny-list of just { 'tool' }. Sessions
tagged acp / webhook / user-defined HERMES_SESSION_SOURCE values and
any newly-added platform now surface. Default limit 20 → 200.

ollama-cloud provider setup passes force_refresh=True to
fetch_ollama_cloud_models() so a user entering their API key sees the
fresh catalog (e.g. deepseek v4 flash, kimi k2.6) immediately instead
of waiting up to an hour for the disk cache TTL to expire.

Closes #16294.
This commit is contained in:
Teknium
2026-04-26 18:49:48 -07:00
committed by GitHub
parent 7e3c8a31f0
commit 5eb6cd82b2
8 changed files with 240 additions and 60 deletions

View File

@@ -401,14 +401,21 @@ class TestSessionBrowseArgparse:
from hermes_cli.main import _session_browse_picker
assert callable(_session_browse_picker)
def test_browse_default_limit_is_50(self):
"""The default --limit for browse should be 50."""
# This test verifies at the argparse level
# We test by running the parse on "sessions browse" args
# Since we can't easily extract the subparser, verify via the
# _session_browse_picker accepting large lists
sessions = _make_sessions(50)
assert len(sessions) == 50
def test_browse_default_limit_is_500(self):
"""The default --limit for browse should be 500."""
# Build the same argparse tree cmd_sessions uses and verify the default.
import argparse
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest="sessions_action")
browse = subparsers.add_parser("browse")
browse.add_argument("--source")
browse.add_argument("--limit", type=int, default=500)
args = parser.parse_args(["browse"])
assert args.limit == 500
args = parser.parse_args(["browse", "--limit", "42"])
assert args.limit == 42
# ─── Integration: cmd_sessions browse action ────────────────────────────────

View File

@@ -0,0 +1,30 @@
"""Regression: ``hermes setup`` for the ollama-cloud provider must force-refresh
the model cache after the user supplies a key, otherwise the picker keeps
serving a stale cache (models.dev only, no live API probe) for up to an hour.
"""
from __future__ import annotations
from unittest.mock import patch
def test_setup_ollama_cloud_passes_force_refresh(monkeypatch):
"""The provider-setup model-fetch for ollama-cloud must pass ``force_refresh=True``."""
import hermes_cli.main as main_mod
import inspect
src = inspect.getsource(main_mod)
# Locate the ollama-cloud branch in the provider setup flow.
marker = 'provider_id == "ollama-cloud"'
assert marker in src, "ollama-cloud branch missing from provider setup"
idx = src.index(marker)
# The call to fetch_ollama_cloud_models should be within the next ~2000 chars.
snippet = src[idx:idx + 2000]
assert "fetch_ollama_cloud_models(" in snippet, snippet[:500]
assert "force_refresh=True" in snippet, (
"ollama-cloud setup must pass force_refresh=True so newly released "
"models (e.g. deepseek v4 flash, kimi k2.6) appear the moment the "
"user enters their key, not an hour later when the cache TTL expires. "
f"Snippet: {snippet[:500]}"
)