Skip to content
Merged
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
33 changes: 16 additions & 17 deletions cli-config.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -583,28 +583,27 @@ memory:
# Session Reset Policy (Messaging Platforms)
# =============================================================================
# Controls when messaging sessions (Telegram, Discord, WhatsApp, Slack) are
# automatically cleared. Without resets, conversation context grows indefinitely
# which increases API costs with every message.
# automatically cleared. Default is "none": sessions never auto-reset —
# conversation context lives until you /reset or /new manually, or context
# compression kicks in. Opt in to automatic resets if you prefer sessions to
# clear on a schedule (long-lived context increases API cost per message,
# though prompt caching and compression keep this manageable).
#
# When a reset triggers, the agent first saves important information to its
# persistent memory — but the conversation context is wiped. The agent starts
# fresh but retains learned facts via its memory system.
#
# Users can always manually reset with /reset or /new in chat.
# When an automatic reset triggers, the agent first saves important
# information to its persistent memory — but the conversation context is
# wiped. The agent starts fresh but retains learned facts via its memory
# system.
#
# Modes:
# "both" - Reset on EITHER inactivity timeout or daily boundary (recommended)
# "idle" - Reset only after N minutes of inactivity
# "daily" - Reset only at a fixed hour each day
# "none" - Never auto-reset; context lives until /reset or compression kicks in
#
# When a reset triggers, the agent gets one turn to save important memories and
# skills before the context is wiped. Persistent memory carries across sessions.
# "none" - Never auto-reset (default); context lives until /reset or compression
# "idle" - Reset after N minutes of inactivity
# "daily" - Reset at a fixed hour each day
# "both" - Reset on EITHER inactivity timeout or daily boundary
#
session_reset:
mode: both # "both", "idle", "daily", or "none"
idle_minutes: 1440 # Inactivity timeout in minutes (default: 1440 = 24 hours)
at_hour: 4 # Daily reset hour, 0-23 local time (default: 4 AM)
mode: none # "none", "idle", "daily", or "both"
idle_minutes: 1440 # Inactivity timeout in minutes (used by "idle"/"both")
at_hour: 4 # Daily reset hour, 0-23 local time (used by "daily"/"both")

# Maximum number of simultaneously active chat sessions across CLI, TUI,
# dashboard chat, and messaging gateway. Set to null, 0, or omit to allow
Expand Down
2 changes: 1 addition & 1 deletion docs/session-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ When a session expires:

```yaml
session_reset:
mode: both # none | idle | daily | both
mode: none # none (default) | idle | daily | both
at_hour: 4 # daily reset hour (local time)
idle_minutes: 1440 # idle timeout (24h)
notify: true # notify user on auto-reset
Expand Down
67 changes: 67 additions & 0 deletions tests/gateway/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import logging
import os
from pathlib import Path
from unittest.mock import patch

import pytest
Expand Down Expand Up @@ -486,6 +487,72 @@ def test_get_notice_delivery_honors_platform_override(self):


class TestLoadGatewayConfig:
def test_shipped_template_does_not_enable_auto_reset(self, tmp_path, monkeypatch):
"""A fresh install seeded from cli-config.yaml.example must not
auto-reset sessions.

Installers (scripts/install.sh, scripts/install.ps1,
docker/stage2-hook.sh, hermes doctor) copy the template verbatim to
~/.hermes/config.yaml, so whatever ``session_reset.mode`` the template
ships becomes an EXPLICIT user setting that overrides the code
default. After #60194 flipped the default to "none", the template
still said "both" — every new install kept 24h-idle resets on
(Luciano's report, July 2026). This pins the invariant: template
seed == no auto-reset.
"""
template = (
Path(__file__).resolve().parents[2] / "cli-config.yaml.example"
)
hermes_home = tmp_path / ".hermes"
hermes_home.mkdir()
(hermes_home / "config.yaml").write_text(
template.read_text(encoding="utf-8"), encoding="utf-8"
)
monkeypatch.setenv("HERMES_HOME", str(hermes_home))

config = load_gateway_config()

assert config.default_reset_policy.mode == "none"

def test_no_config_yaml_means_no_auto_reset(self, tmp_path, monkeypatch):
"""With no config.yaml at all, sessions must never auto-reset."""
hermes_home = tmp_path / ".hermes"
hermes_home.mkdir()
monkeypatch.setenv("HERMES_HOME", str(hermes_home))

config = load_gateway_config()

assert config.default_reset_policy.mode == "none"

def test_session_reset_without_mode_means_no_auto_reset(self, tmp_path, monkeypatch):
"""A session_reset block that tunes knobs but omits mode stays off."""
hermes_home = tmp_path / ".hermes"
hermes_home.mkdir()
(hermes_home / "config.yaml").write_text(
"session_reset:\n idle_minutes: 60\n", encoding="utf-8"
)
monkeypatch.setenv("HERMES_HOME", str(hermes_home))

config = load_gateway_config()

assert config.default_reset_policy.mode == "none"
assert config.default_reset_policy.idle_minutes == 60

def test_explicit_session_reset_opt_in_is_honored(self, tmp_path, monkeypatch):
"""Users who explicitly opt in to auto-reset keep their policy."""
hermes_home = tmp_path / ".hermes"
hermes_home.mkdir()
(hermes_home / "config.yaml").write_text(
"session_reset:\n mode: idle\n idle_minutes: 30\n",
encoding="utf-8",
)
monkeypatch.setenv("HERMES_HOME", str(hermes_home))

config = load_gateway_config()

assert config.default_reset_policy.mode == "idle"
assert config.default_reset_policy.idle_minutes == 30

def test_bridges_quick_commands_from_config_yaml(self, tmp_path, monkeypatch):
hermes_home = tmp_path / ".hermes"
hermes_home.mkdir()
Expand Down
Loading