fix(recovery): name the real state.db in the copy-pasteable recovery banners
The gateway broadcast and turn-failure explanation printed a literal ~/.hermes/state.db; now that the line is a command the operator is meant to run as-is, interpolate _default_db_path() so profile / HERMES_HOME installs are pointed at the store that actually failed. Also: split a comment that a merge fused onto the logger line in session_lost_and_found.py, and fix an inverted test docstring.
This commit is contained in:
+10
-3
@@ -27476,20 +27476,27 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
|
||||
if not error:
|
||||
return
|
||||
|
||||
from hermes_state import classify_persistence_error, format_session_db_unavailable
|
||||
from hermes_state import (
|
||||
_default_db_path,
|
||||
classify_persistence_error,
|
||||
format_session_db_unavailable,
|
||||
)
|
||||
|
||||
cause = classify_persistence_error(error)
|
||||
hint = format_session_db_unavailable()
|
||||
if cause == "corrupt":
|
||||
# Copy-pasteable, so name the real store (profiles / HERMES_HOME
|
||||
# do not live under ~/.hermes).
|
||||
db_path = _default_db_path()
|
||||
message = (
|
||||
"⚠️ Session database corruption detected. Messages may not be "
|
||||
"persisted. Recovery options:\n"
|
||||
"1. Run `hermes doctor --fix`\n"
|
||||
"2. Stop the gateway, then recover with:\n"
|
||||
" hermes sessions recover --source ~/.hermes/state.db "
|
||||
f" hermes sessions recover --source {db_path} "
|
||||
"--inspect-only\n"
|
||||
" (if it reports recoverable) hermes sessions recover "
|
||||
"--source ~/.hermes/state.db --output recovered-state.db\n"
|
||||
f"--source {db_path} --output recovered-state.db\n"
|
||||
" — recovery snapshots the damaged file first; do NOT run "
|
||||
"`sqlite3 ... \".recover\"` against the live state.db, a "
|
||||
"vulnerable sqlite3 CLI can corrupt it further\n"
|
||||
|
||||
@@ -32,7 +32,9 @@ import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
|
||||
logger = logging.getLogger(__name__)# Hermes session ids are timestamps: 20260812_135332_ab12cd. This is the
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Hermes session ids are timestamps: 20260812_135332_ab12cd. This is the
|
||||
# strongest sentinel available for classifying schema-less rows.
|
||||
SESSION_ID_PATTERN = re.compile(r"^\d{8}_\d{6}_")
|
||||
|
||||
|
||||
+7
-2
@@ -4423,6 +4423,11 @@ class AIAgent:
|
||||
"pending_messages/pending-*.json."
|
||||
)
|
||||
if cause == "corrupt":
|
||||
from hermes_state import _default_db_path
|
||||
|
||||
# Copy-pasteable, so name the real store (profiles /
|
||||
# HERMES_HOME do not live under ~/.hermes).
|
||||
db_path = _default_db_path()
|
||||
return (
|
||||
prefix
|
||||
+ "the turn was stopped because the state database "
|
||||
@@ -4431,10 +4436,10 @@ class AIAgent:
|
||||
"not help. Recovery options:\n"
|
||||
"1. Run `hermes doctor --fix`\n"
|
||||
"2. Stop the gateway, then recover with:\n"
|
||||
" hermes sessions recover --source ~/.hermes/state.db "
|
||||
f" hermes sessions recover --source {db_path} "
|
||||
"--inspect-only\n"
|
||||
" (if it reports recoverable) hermes sessions recover "
|
||||
"--source ~/.hermes/state.db --output recovered-state.db\n"
|
||||
f"--source {db_path} --output recovered-state.db\n"
|
||||
" — recovery snapshots the damaged file first; do NOT "
|
||||
"run `sqlite3 ... \".recover\"` against the live "
|
||||
"state.db, a vulnerable sqlite3 CLI can corrupt it "
|
||||
|
||||
@@ -307,9 +307,9 @@ class TestEmittedCommandsSatisfyCliContract:
|
||||
return argparse.Namespace(**fields)
|
||||
|
||||
def test_old_v1_shape_is_still_rejected(self, tmp_path):
|
||||
"""Guard the test's own premise: neither --inspect-only nor
|
||||
--output (the shape the v1 banner printed) is rejected with rc 2
|
||||
by the real dispatcher."""
|
||||
"""Guard the test's own premise: the bare `--source <db>` shape the
|
||||
v1 banner printed (neither --inspect-only nor --output) is rejected
|
||||
with rc 2 by the real dispatcher."""
|
||||
import hermes_cli.sessions_cmd as sc
|
||||
|
||||
rc = sc.cmd_sessions(self._namespace(tmp_path / "state.db"))
|
||||
|
||||
Reference in New Issue
Block a user