feat: add persistent memory system + SQLite session store
Two-part implementation: Part A - Curated Bounded Memory: - New memory tool (tools/memory_tool.py) with MEMORY.md + USER.md stores - Character-limited (2200/1375 chars), § delimited entries - Frozen snapshot injected into system prompt at session start - Model manages pruning via replace/remove with substring matching - Usage indicator shown in system prompt header Part B - SQLite Session Store: - New hermes_state.py with SessionDB class, FTS5 full-text search - Gateway session.py rewritten to dual-write SQLite + legacy JSONL - Compression-triggered session splitting with parent_session_id chains - New session_search tool with Gemini Flash summarization of matched sessions - CLI session lifecycle (create on launch, close on exit) Also: - System prompt now cached per session, only rebuilt on compression (fixes prefix cache invalidation from date/time changes every turn) - Config version bumped to 3, hermes doctor checks for new artifacts - Disabled in batch_runner and RL environments
This commit is contained in:
parent
655303f2f1
commit
440c244cac
19 changed files with 2397 additions and 327 deletions
15
cli.py
15
cli.py
|
|
@ -723,6 +723,14 @@ class HermesCLI:
|
|||
if self.agent is not None:
|
||||
return True
|
||||
|
||||
# Initialize SQLite session store for CLI sessions
|
||||
self._session_db = None
|
||||
try:
|
||||
from hermes_state import SessionDB
|
||||
self._session_db = SessionDB()
|
||||
except Exception:
|
||||
pass # SQLite session store is optional
|
||||
|
||||
try:
|
||||
self.agent = AIAgent(
|
||||
model=self.model,
|
||||
|
|
@ -735,6 +743,7 @@ class HermesCLI:
|
|||
ephemeral_system_prompt=self.system_prompt if self.system_prompt else None,
|
||||
session_id=self.session_id, # Pass CLI's session ID to agent
|
||||
platform="cli", # CLI interface — agent uses terminal-friendly formatting
|
||||
session_db=self._session_db,
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
|
|
@ -1775,6 +1784,12 @@ class HermesCLI:
|
|||
pass
|
||||
finally:
|
||||
self._should_exit = True
|
||||
# Close session in SQLite
|
||||
if hasattr(self, '_session_db') and self._session_db and self.agent:
|
||||
try:
|
||||
self._session_db.end_session(self.agent.session_id, "cli_close")
|
||||
except Exception:
|
||||
pass
|
||||
_run_cleanup()
|
||||
print("\nGoodbye! ⚕")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue