mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-23 10:42:00 +00:00
fix(memory): apply /memory approve against a fresh store when no live agent
The CLI /memory slash handler (cli_commands_mixin._handle_memory_command) passed self.agent._memory_store straight through, which is None when the command runs without a live agent — e.g. /memory approve from the Desktop GUI. The shared write-approval handler then returns "memory store unavailable" and applies nothing, even with built-in memory enabled and pending writes present. Fall back to a freshly loaded on-disk MemoryStore when no live store is available, mirroring the gateway path (gateway/slash_commands.py). It persists to the same MEMORY/USER.md and creates MEMORY.md on the first approved write. Fixes #46783 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
100e7be20e
commit
3147cbb136
2 changed files with 40 additions and 0 deletions
|
|
@ -1361,6 +1361,16 @@ class CLICommandsMixin:
|
|||
parts = cmd.strip().split()
|
||||
args = parts[1:] if len(parts) > 1 else []
|
||||
store = getattr(self.agent, "_memory_store", None) if getattr(self, "agent", None) else None
|
||||
if store is None:
|
||||
# No live agent store (e.g. /memory approve invoked from the Desktop
|
||||
# GUI, or any context without an active agent). Apply against a freshly
|
||||
# loaded on-disk store, mirroring the gateway path
|
||||
# (gateway/slash_commands.py): it persists to the same MEMORY/USER.md
|
||||
# and creates MEMORY.md on the first approved write. Without this the
|
||||
# shared handler returns "memory store unavailable". See #46783.
|
||||
from tools.memory_tool import MemoryStore
|
||||
store = MemoryStore()
|
||||
store.load_from_disk()
|
||||
out = handle_pending_subcommand(
|
||||
wa.MEMORY, args,
|
||||
memory_store=store,
|
||||
|
|
|
|||
|
|
@ -107,6 +107,36 @@ def test_memory_gate_on_then_apply(hermes_home):
|
|||
assert "approved entry" in store.user_entries[0]
|
||||
|
||||
|
||||
def test_cli_memory_approve_without_live_agent_uses_fresh_store(hermes_home, capsys):
|
||||
"""#46783: ``/memory approve`` from a context with no live agent (e.g. the
|
||||
Desktop GUI) passed ``memory_store=None`` into the shared handler, which
|
||||
returned "memory store unavailable" and applied nothing. The CLI handler must
|
||||
fall back to a freshly loaded on-disk store, like the gateway path does."""
|
||||
import json
|
||||
from tools.memory_tool import memory_tool, MemoryStore
|
||||
from tools import write_approval as wa
|
||||
from hermes_cli.cli_commands_mixin import CLICommandsMixin
|
||||
|
||||
_set_approval("memory", True)
|
||||
staging = MemoryStore(); staging.load_from_disk()
|
||||
r = json.loads(memory_tool("add", "memory", "remember the launch date", store=staging))
|
||||
assert r.get("pending_id"), r
|
||||
assert wa.pending_count("memory") == 1
|
||||
|
||||
# Bare CLI handler with no live agent → store resolves to None pre-fix.
|
||||
handler = CLICommandsMixin.__new__(CLICommandsMixin)
|
||||
handler.agent = None
|
||||
handler._handle_memory_command("/memory approve all")
|
||||
|
||||
out = capsys.readouterr().out
|
||||
assert "memory store unavailable" not in out, out
|
||||
assert "Approved 1" in out, out
|
||||
assert wa.pending_count("memory") == 0
|
||||
# The approved write landed in a freshly loaded on-disk store (MEMORY.md).
|
||||
reloaded = MemoryStore(); reloaded.load_from_disk()
|
||||
assert any("remember the launch date" in e for e in reloaded.memory_entries)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Skill gate
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue