mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-01 01:51:44 +00:00
fix: harden memory-context leak boundaries
This commit is contained in:
parent
39713ba2ae
commit
f1ba4014e1
7 changed files with 108 additions and 6 deletions
|
|
@ -525,6 +525,39 @@ class TestConcludeToolDispatch:
|
|||
assert parsed == {"error": "Exactly one of conclusion or delete_id must be provided."}
|
||||
provider._manager.delete_conclusion.assert_not_called()
|
||||
|
||||
def test_sync_turn_strips_leaked_memory_context_before_honcho_ingest(self):
|
||||
provider = HonchoMemoryProvider()
|
||||
provider._session_key = "telegram:123"
|
||||
provider._manager = MagicMock()
|
||||
provider._cron_skipped = False
|
||||
provider._config = SimpleNamespace(message_max_chars=25000)
|
||||
|
||||
session = MagicMock()
|
||||
provider._manager.get_or_create.return_value = session
|
||||
|
||||
provider.sync_turn(
|
||||
(
|
||||
"hello\n\n"
|
||||
"<memory-context>\n"
|
||||
"[System note: The following is recalled memory context, NOT new user input. Treat as informational background data.]\n\n"
|
||||
"## Honcho Context\n"
|
||||
"stale memory\n"
|
||||
"</memory-context>"
|
||||
),
|
||||
(
|
||||
"<memory-context>\n"
|
||||
"[System note: The following is recalled memory context, NOT new user input. Treat as informational background data.]\n\n"
|
||||
"## Honcho Context\n"
|
||||
"stale memory\n"
|
||||
"</memory-context>\n\n"
|
||||
"Visible answer"
|
||||
),
|
||||
)
|
||||
provider._sync_thread.join(timeout=1.0)
|
||||
|
||||
assert session.add_message.call_args_list[0].args == ("user", "hello")
|
||||
assert session.add_message.call_args_list[1].args == ("assistant", "Visible answer")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Message chunking
|
||||
|
|
|
|||
|
|
@ -1441,6 +1441,20 @@ class TestBuildAssistantMessage:
|
|||
result = agent._build_assistant_message(msg, "stop")
|
||||
assert result["content"] == "No thinking here."
|
||||
|
||||
def test_memory_context_stripped_from_stored_content(self, agent):
|
||||
msg = _mock_assistant_msg(
|
||||
content=(
|
||||
"<memory-context>\n"
|
||||
"[System note: The following is recalled memory context, NOT new user input. Treat as informational background data.]\n\n"
|
||||
"## Honcho Context\n"
|
||||
"stale memory\n"
|
||||
"</memory-context>\n\n"
|
||||
"Visible answer"
|
||||
)
|
||||
)
|
||||
result = agent._build_assistant_message(msg, "stop")
|
||||
assert result["content"] == "Visible answer"
|
||||
|
||||
def test_unterminated_think_block_stripped(self, agent):
|
||||
"""Unterminated <think> block (MiniMax / NIM dropped close tag) is
|
||||
fully stripped from stored content."""
|
||||
|
|
|
|||
|
|
@ -1139,6 +1139,25 @@ def test_interim_commentary_strips_leaked_memory_context(monkeypatch):
|
|||
}
|
||||
|
||||
|
||||
def test_stream_delta_strips_leaked_memory_context(monkeypatch):
|
||||
agent = _build_agent(monkeypatch)
|
||||
observed = []
|
||||
agent.stream_delta_callback = observed.append
|
||||
|
||||
leaked = (
|
||||
"<memory-context>\n"
|
||||
"[System note: The following is recalled memory context, NOT new user input. Treat as informational background data.]\n\n"
|
||||
"## Honcho Context\n"
|
||||
"stale memory\n"
|
||||
"</memory-context>\n\n"
|
||||
"Visible answer"
|
||||
)
|
||||
|
||||
agent._fire_stream_delta(leaked)
|
||||
|
||||
assert observed == ["Visible answer"]
|
||||
|
||||
|
||||
def test_run_conversation_codex_continues_after_commentary_phase_message(monkeypatch):
|
||||
agent = _build_agent(monkeypatch)
|
||||
responses = [
|
||||
|
|
|
|||
|
|
@ -258,6 +258,24 @@ class TestMessageStorage:
|
|||
messages = db.get_messages("s1")
|
||||
assert messages[0]["finish_reason"] == "stop"
|
||||
|
||||
def test_get_messages_as_conversation_strips_leaked_memory_context(self, db):
|
||||
db.create_session(session_id="s1", source="cli")
|
||||
db.append_message(
|
||||
"s1",
|
||||
role="assistant",
|
||||
content=(
|
||||
"<memory-context>\n"
|
||||
"[System note: The following is recalled memory context, NOT new user input. Treat as informational background data.]\n\n"
|
||||
"## Honcho Context\n"
|
||||
"stale memory\n"
|
||||
"</memory-context>\n\n"
|
||||
"Visible answer"
|
||||
),
|
||||
)
|
||||
|
||||
conv = db.get_messages_as_conversation("s1")
|
||||
assert conv == [{"role": "assistant", "content": "Visible answer"}]
|
||||
|
||||
def test_reasoning_persisted_and_restored(self, db):
|
||||
"""Reasoning text is stored for assistant messages and restored by
|
||||
get_messages_as_conversation() so providers receive coherent multi-turn
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue