mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-05-20 08:32:25 +00:00
fix(memory): refresh session before empty guard
This commit is contained in:
parent
c58a360b25
commit
eb0ff3ad1d
@ -678,7 +678,7 @@ class Consolidator:
|
|||||||
The budget reserves space for completion tokens and a safety buffer
|
The budget reserves space for completion tokens and a safety buffer
|
||||||
so the LLM request never exceeds the context window.
|
so the LLM request never exceeds the context window.
|
||||||
"""
|
"""
|
||||||
if not session.messages or self.context_window_tokens <= 0:
|
if self.context_window_tokens <= 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
lock = self.get_lock(session.key)
|
lock = self.get_lock(session.key)
|
||||||
@ -687,6 +687,8 @@ class Consolidator:
|
|||||||
fresh = self.sessions.get_or_create(session.key)
|
fresh = self.sessions.get_or_create(session.key)
|
||||||
if fresh is not session:
|
if fresh is not session:
|
||||||
session = fresh
|
session = fresh
|
||||||
|
if not session.messages:
|
||||||
|
return
|
||||||
|
|
||||||
budget = self._input_token_budget
|
budget = self._input_token_budget
|
||||||
target = int(budget * self.consolidation_ratio)
|
target = int(budget * self.consolidation_ratio)
|
||||||
|
|||||||
@ -477,6 +477,47 @@ class TestCompactIdleSession:
|
|||||||
class TestConsolidatorSessionRefresh:
|
class TestConsolidatorSessionRefresh:
|
||||||
"""Background consolidation must detect stale session references."""
|
"""Background consolidation must detect stale session references."""
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_reloads_before_empty_session_guard(self, tmp_path):
|
||||||
|
"""A stale empty reference must not skip a non-empty cached session."""
|
||||||
|
from nanobot.agent.memory import Consolidator, MemoryStore
|
||||||
|
from nanobot.session.manager import Session, SessionManager
|
||||||
|
|
||||||
|
store = MemoryStore(tmp_path)
|
||||||
|
provider = MagicMock()
|
||||||
|
provider.chat_with_retry = AsyncMock(
|
||||||
|
return_value=MagicMock(content="summary", finish_reason="stop")
|
||||||
|
)
|
||||||
|
provider.generation.max_tokens = 4096
|
||||||
|
provider.estimate_prompt_tokens = MagicMock(return_value=(10, "test"))
|
||||||
|
sessions = SessionManager(tmp_path)
|
||||||
|
consolidator = Consolidator(
|
||||||
|
store=store,
|
||||||
|
provider=provider,
|
||||||
|
model="test-model",
|
||||||
|
sessions=sessions,
|
||||||
|
context_window_tokens=128_000,
|
||||||
|
build_messages=MagicMock(return_value=[]),
|
||||||
|
get_tool_definitions=MagicMock(return_value=[]),
|
||||||
|
)
|
||||||
|
|
||||||
|
fresh = sessions.get_or_create("cli:test")
|
||||||
|
fresh.add_message("user", "fresh message")
|
||||||
|
sessions.save(fresh)
|
||||||
|
stale_empty = Session(key="cli:test")
|
||||||
|
|
||||||
|
seen: dict[str, Session] = {}
|
||||||
|
|
||||||
|
def estimate(session: Session):
|
||||||
|
seen["session"] = session
|
||||||
|
return 10, "test"
|
||||||
|
|
||||||
|
consolidator.estimate_session_prompt_tokens = MagicMock(side_effect=estimate)
|
||||||
|
|
||||||
|
await consolidator.maybe_consolidate_by_tokens(stale_empty)
|
||||||
|
|
||||||
|
assert seen["session"] is fresh
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_reloads_stale_session_after_compact(self, tmp_path):
|
async def test_reloads_stale_session_after_compact(self, tmp_path):
|
||||||
"""After compact_idle_session replaces the session, a concurrent
|
"""After compact_idle_session replaces the session, a concurrent
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user