hermes-agent/tests
Teknium eb07c05646
fix(gateway): prune stale SessionStore entries to bound memory + disk (#11789)
SessionStore._entries grew unbounded.  Every unique
(platform, chat_id, thread_id, user_id) tuple ever seen was kept in
RAM and rewritten to sessions.json on every message.  A Discord bot
in 100 servers x 100 channels x ~100 rotating users accumulates on
the order of 10^5 entries after a few months; each sessions.json
write becomes an O(n) fsync.  Nothing trimmed this — there was no
TTL, no cap, no eviction path.

Changes
-------
* SessionStore.prune_old_entries(max_age_days) — drops entries whose
  updated_at is older than the cutoff.  Preserves:
    - suspended entries (user paused them via /stop for later resume)
    - entries with an active background process attached
  Pruning is functionally identical to a natural reset-policy expiry:
  SQLite transcript stays, session_key -> session_id mapping dropped,
  returning user gets a fresh session.

* GatewayConfig.session_store_max_age_days (default 90; 0 disables).
  Serialized in to_dict/from_dict, coerced from bad types / negatives
  to safe defaults.  No migration needed — missing field -> 90 days.

* _session_expiry_watcher calls prune_old_entries once per hour
  (first tick is immediate).  Uses the existing watcher loop so no
  new background task is created.

Why not more aggressive
-----------------------
90 days is long enough that legitimate long-idle users (seasonal,
vacation, etc.) aren't surprised — pruning just means they get a
fresh session on return, same outcome they'd get from any other
reset-policy trigger.  Admins can lower it via config; 0 disables.

Tests
-----
tests/gateway/test_session_store_prune.py — 17 cases covering:
  * entry age based on updated_at, not created_at
  * max_age_days=0 disables; negative coerces to 0
  * suspended + active-process entries are skipped
  * _save fires iff something was removed
  * disk JSON reflects post-prune state
  * thread safety against concurrent readers
  * config field roundtrips + graceful fallback on bad values
  * watcher gate logic (first tick prunes, subsequent within 1h don't)

119 broader session/gateway tests remain green.
2026-04-17 13:48:49 -07:00
..
acp fix(acp): improve zed integration 2026-04-17 13:29:26 -07:00
agent test: remove 169 change-detector tests across 21 files (#11472) 2026-04-17 01:05:09 -07:00
cli fix(surrogates): sanitize reasoning/reasoning_content/reasoning_details fields (#11628) 2026-04-17 13:30:47 -07:00
cron feat(cron+tests): extend origin fallback to email/dingtalk/qqbot + fix Weixin test mocks 2026-04-17 06:26:43 -07:00
e2e refactor: extract shared helpers to deduplicate repeated code patterns (#7917) 2026-04-11 13:59:52 -07:00
environments/benchmarks fix(security): consolidated security hardening — SSRF, timing attack, tar traversal, credential leakage (#5944) 2026-04-07 17:28:37 -07:00
fakes fix: streaming tool call parsing, error handling, and fake HA state mutation 2026-03-14 14:27:20 +03:00
gateway fix(gateway): prune stale SessionStore entries to bound memory + disk (#11789) 2026-04-17 13:48:49 -07:00
hermes_cli feat(providers): add native NVIDIA NIM provider 2026-04-17 13:47:46 -07:00
honcho_plugin fix(honcho): strip whitespace from conclusion and delete_id inputs 2026-04-16 09:50:10 -07:00
integration fix(discord): strip RTP padding before DAVE/Opus decode (#11267) 2026-04-16 16:50:15 -07:00
plugins test: remove 169 change-detector tests across 21 files (#11472) 2026-04-17 01:05:09 -07:00
run_agent fix(tests): make AIAgent constructor calls self-contained (#11755) 2026-04-17 12:32:03 -07:00
skills fix(google-workspace): normalize authorized user token writes 2026-04-16 04:22:16 -07:00
tools fix(providers): complete NVIDIA NIM parity with other providers 2026-04-17 13:47:46 -07:00
__init__.py A bit of restructuring for simplicity and organization 2025-10-01 23:29:25 +00:00
conftest.py test: make test env hermetic; enforce CI parity via scripts/run_tests.sh (#11577) 2026-04-17 06:09:09 -07:00
run_interrupt_test.py fix: thread safety for concurrent subagent delegation (#1672) 2026-03-17 02:53:33 -07:00
test_batch_runner_checkpoint.py fix: sanitize chat payloads and provider precedence 2026-03-13 23:59:12 -07:00
test_cli_file_drop.py fix(gateway): reject file paths in get_command() + file-drop tests (#7356) 2026-04-10 13:06:02 -07:00
test_cli_skin_integration.py fix: CLI/UX batch — ChatConsole errors, curses scroll, skin-aware banner, git state banner (#5974) 2026-04-07 17:59:42 -07:00
test_ctx_halving_fix.py fix(tests): fix 78 CI test failures and remove dead test (#9036) 2026-04-13 10:50:24 -07:00
test_empty_model_fallback.py fix: fall back to provider's default model when model config is empty (#8303) 2026-04-12 03:53:30 -07:00
test_evidence_store.py feat: add OSS Security Forensics skill (Skills Hub) (#1482) 2026-03-15 21:59:53 -07:00
test_hermes_constants.py fix(gateway): harden Docker/container gateway pathway 2026-04-12 16:36:11 -07:00
test_hermes_logging.py fix(tests): fix 78 CI test failures and remove dead test (#9036) 2026-04-13 10:50:24 -07:00
test_hermes_state.py fix(state): orphan children instead of cascade-deleting in prune/delete (#6513) 2026-04-09 02:41:56 -07:00
test_honcho_client_config.py feat(memory): pluggable memory provider interface with profile isolation, review fixes, and honcho CLI restoration (#4623) 2026-04-02 15:33:51 -07:00
test_ipv4_preference.py feat: add network.force_ipv4 config to fix IPv6 timeout issues (#8196) 2026-04-11 23:12:11 -07:00
test_mcp_serve.py feat: add MCP server mode — hermes mcp serve (#3795) 2026-03-29 15:47:19 -07:00
test_minisweagent_path.py chore: remove all remaining mini-swe-agent references 2026-03-24 08:19:23 -07:00
test_model_picker_scroll.py fix: CLI/UX batch — ChatConsole errors, curses scroll, skin-aware banner, git state banner (#5974) 2026-04-07 17:59:42 -07:00
test_model_tools.py feat(plugins): let pre_tool_call hooks block tool execution 2026-04-13 22:01:49 -07:00
test_model_tools_async_bridge.py fix: use per-thread persistent event loops in worker threads 2026-03-20 15:41:06 -04:00
test_ollama_num_ctx.py fix: provider/model resolution — salvage 4 PRs + MiniMax aux URL fix (#5983) 2026-04-07 22:23:28 -07:00
test_packaging_metadata.py chore: prepare Hermes for Homebrew packaging (#4099) 2026-03-30 17:34:43 -07:00
test_plugin_skills.py fix(tests): attach caplog to specific logger in 3 order-dependent tests (#11453) 2026-04-17 00:20:40 -07:00
test_project_metadata.py build(deps): add qrcode to dingtalk + feishu extras (parity with messaging) (#11627) 2026-04-17 13:31:53 -07:00
test_retry_utils.py feat(agent): add jittered retry backoff 2026-04-08 00:41:36 -07:00
test_sql_injection.py fix(security): eliminate SQL string formatting in execute() calls 2026-03-19 15:16:35 +01:00
test_subprocess_home_isolation.py fix: per-profile subprocess HOME isolation (#4426) (#7357) 2026-04-10 13:37:45 -07:00
test_timezone.py fix: remove 115 verified dead code symbols across 46 production files 2026-04-10 03:44:43 -07:00
test_toolset_distributions.py test: add unit tests for 8 modules (batch 2) 2026-02-26 13:54:20 +03:00
test_toolsets.py fix(mcp): make server aliases explicit 2026-04-14 17:19:20 -07:00
test_trajectory_compressor.py fix: load credentials from HERMES_HOME .env in trajectory_compressor 2026-04-14 10:24:19 -07:00
test_trajectory_compressor_async.py fix(tests): fix 78 CI test failures and remove dead test (#9036) 2026-04-13 10:50:24 -07:00
test_utils_truthy_values.py Gate tool-gateway behind an env var, so it's not in users' faces until we're ready. Even if users enable it, it'll be blocked server-side for now, until we unlock for non-admin users on tool-gateway. 2026-03-30 13:28:10 +09:00