fix: isolate /new consolidation in API mode
This commit is contained in:
@@ -516,7 +516,7 @@ class TestNewCommandArchival:
|
||||
loop.sessions.save(session)
|
||||
before_count = len(session.messages)
|
||||
|
||||
async def _failing_consolidate(_messages) -> bool:
|
||||
async def _failing_consolidate(_messages, store=None) -> bool:
|
||||
return False
|
||||
|
||||
loop.memory_consolidator.consolidate_messages = _failing_consolidate # type: ignore[method-assign]
|
||||
@@ -542,7 +542,7 @@ class TestNewCommandArchival:
|
||||
|
||||
archived_count = -1
|
||||
|
||||
async def _fake_consolidate(messages) -> bool:
|
||||
async def _fake_consolidate(messages, store=None) -> bool:
|
||||
nonlocal archived_count
|
||||
archived_count = len(messages)
|
||||
return True
|
||||
@@ -567,7 +567,7 @@ class TestNewCommandArchival:
|
||||
session.add_message("assistant", f"resp{i}")
|
||||
loop.sessions.save(session)
|
||||
|
||||
async def _ok_consolidate(_messages) -> bool:
|
||||
async def _ok_consolidate(_messages, store=None) -> bool:
|
||||
return True
|
||||
|
||||
loop.memory_consolidator.consolidate_messages = _ok_consolidate # type: ignore[method-assign]
|
||||
@@ -578,3 +578,33 @@ class TestNewCommandArchival:
|
||||
assert response is not None
|
||||
assert "new session started" in response.content.lower()
|
||||
assert loop.sessions.get_or_create("cli:test").messages == []
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_new_archives_to_custom_store_when_provided(self, tmp_path: Path) -> None:
|
||||
"""When memory_store is passed, /new must archive through that store."""
|
||||
from nanobot.bus.events import InboundMessage
|
||||
from nanobot.agent.memory import MemoryStore
|
||||
|
||||
loop = self._make_loop(tmp_path)
|
||||
session = loop.sessions.get_or_create("cli:test")
|
||||
for i in range(5):
|
||||
session.add_message("user", f"msg{i}")
|
||||
session.add_message("assistant", f"resp{i}")
|
||||
loop.sessions.save(session)
|
||||
|
||||
used_store = None
|
||||
|
||||
async def _tracking_consolidate(messages, store=None) -> bool:
|
||||
nonlocal used_store
|
||||
used_store = store
|
||||
return True
|
||||
|
||||
loop.memory_consolidator.consolidate_messages = _tracking_consolidate # type: ignore[method-assign]
|
||||
|
||||
iso_store = MagicMock(spec=MemoryStore)
|
||||
new_msg = InboundMessage(channel="cli", sender_id="user", chat_id="test", content="/new")
|
||||
response = await loop._process_message(new_msg, memory_store=iso_store)
|
||||
|
||||
assert response is not None
|
||||
assert "new session started" in response.content.lower()
|
||||
assert used_store is iso_store, "archive_unconsolidated must use the provided store"
|
||||
|
||||
@@ -158,7 +158,7 @@ async def test_preflight_consolidation_before_llm_call(tmp_path, monkeypatch) ->
|
||||
|
||||
loop = _make_loop(tmp_path, estimated_tokens=0, context_window_tokens=200)
|
||||
|
||||
async def track_consolidate(messages):
|
||||
async def track_consolidate(messages, store=None):
|
||||
order.append("consolidate")
|
||||
return True
|
||||
loop.memory_consolidator.consolidate_messages = track_consolidate # type: ignore[method-assign]
|
||||
|
||||
@@ -622,6 +622,53 @@ class TestConsolidationIsolation:
|
||||
assert (global_mem_dir / "MEMORY.md").read_text() == ""
|
||||
assert (global_mem_dir / "HISTORY.md").read_text() == ""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_new_command_uses_isolated_store(self, tmp_path):
|
||||
"""process_direct(isolate_memory=True) + /new must archive to the isolated store."""
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
from nanobot.agent.loop import AgentLoop
|
||||
from nanobot.agent.memory import MemoryStore
|
||||
from nanobot.bus.queue import MessageBus
|
||||
from nanobot.providers.base import LLMResponse
|
||||
|
||||
bus = MessageBus()
|
||||
provider = MagicMock()
|
||||
provider.get_default_model.return_value = "test-model"
|
||||
provider.estimate_prompt_tokens.return_value = (10_000, "test")
|
||||
agent = AgentLoop(
|
||||
bus=bus, provider=provider, workspace=tmp_path,
|
||||
model="test-model", context_window_tokens=1,
|
||||
)
|
||||
agent._mcp_connected = True # skip MCP connect
|
||||
agent.tools.get_definitions = MagicMock(return_value=[])
|
||||
|
||||
# Pre-populate session so /new has something to archive
|
||||
session = agent.sessions.get_or_create("api:alice")
|
||||
for i in range(3):
|
||||
session.add_message("user", f"msg{i}")
|
||||
session.add_message("assistant", f"resp{i}")
|
||||
agent.sessions.save(session)
|
||||
|
||||
used_store = None
|
||||
|
||||
async def _tracking_consolidate(messages, store=None) -> bool:
|
||||
nonlocal used_store
|
||||
used_store = store
|
||||
return True
|
||||
|
||||
agent.memory_consolidator.consolidate_messages = _tracking_consolidate # type: ignore[method-assign]
|
||||
|
||||
result = await agent.process_direct(
|
||||
"/new", session_key="api:alice", isolate_memory=True,
|
||||
)
|
||||
|
||||
assert "new session started" in result.lower()
|
||||
assert used_store is not None, "consolidation must receive a store"
|
||||
assert isinstance(used_store, MemoryStore)
|
||||
assert "sessions" in str(used_store.memory_dir), (
|
||||
"store must point to per-session dir, not global workspace"
|
||||
)
|
||||
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user