mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-27 19:25:15 +02:00
feat: add no-update sentinel handling to save_memory function and corresponding unit tests
This commit is contained in:
parent
132e7b3c44
commit
8c9be9796a
2 changed files with 64 additions and 0 deletions
|
|
@ -29,6 +29,15 @@ from app.services.memory.validation import (
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
_NO_UPDATE_SENTINELS = frozenset(
|
||||||
|
{
|
||||||
|
"NO_UPDATE",
|
||||||
|
"NO UPDATE",
|
||||||
|
"NO_CHANGE",
|
||||||
|
"NO CHANGE",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class MemoryScope(StrEnum):
|
class MemoryScope(StrEnum):
|
||||||
USER = "user"
|
USER = "user"
|
||||||
|
|
@ -149,6 +158,13 @@ async def save_memory(
|
||||||
notice: str | None = None
|
notice: str | None = None
|
||||||
warnings: list[str] = []
|
warnings: list[str] = []
|
||||||
|
|
||||||
|
if next_content.upper() in _NO_UPDATE_SENTINELS:
|
||||||
|
return SaveResult(
|
||||||
|
status="no_op",
|
||||||
|
message="No memory update requested.",
|
||||||
|
memory_md=old_memory,
|
||||||
|
)
|
||||||
|
|
||||||
if len(next_content) > MEMORY_HARD_LIMIT and llm is not None:
|
if len(next_content) > MEMORY_HARD_LIMIT and llm is not None:
|
||||||
rewritten = await forced_rewrite(next_content, llm)
|
rewritten = await forced_rewrite(next_content, llm)
|
||||||
if rewritten is not None and len(rewritten) < len(next_content):
|
if rewritten is not None and len(rewritten) < len(next_content):
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,54 @@ async def test_save_memory_rejects_long_no_heading_payload(monkeypatch) -> None:
|
||||||
assert target.memory_md.startswith("## Facts")
|
assert target.memory_md.startswith("## Facts")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_save_memory_no_update_sentinel_is_no_op(monkeypatch) -> None:
|
||||||
|
existing = "## Preferences\n- 2026-05-20: Existing preference\n"
|
||||||
|
target = SimpleNamespace(memory_md=existing)
|
||||||
|
session = _FakeSession()
|
||||||
|
|
||||||
|
async def fake_load_target(**_kwargs):
|
||||||
|
return target
|
||||||
|
|
||||||
|
monkeypatch.setattr("app.services.memory.service._load_target", fake_load_target)
|
||||||
|
|
||||||
|
result = await save_memory(
|
||||||
|
scope=MemoryScope.USER,
|
||||||
|
target_id="00000000-0000-0000-0000-000000000000",
|
||||||
|
content="NO_UPDATE",
|
||||||
|
session=session,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result.status == "no_op"
|
||||||
|
assert result.memory_md == existing
|
||||||
|
assert target.memory_md == existing
|
||||||
|
assert session.commit_calls == 0
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_save_memory_no_update_sentinel_is_case_insensitive(monkeypatch) -> None:
|
||||||
|
existing = "## Preferences\n- 2026-05-20: Existing preference\n"
|
||||||
|
target = SimpleNamespace(memory_md=existing)
|
||||||
|
session = _FakeSession()
|
||||||
|
|
||||||
|
async def fake_load_target(**_kwargs):
|
||||||
|
return target
|
||||||
|
|
||||||
|
monkeypatch.setattr("app.services.memory.service._load_target", fake_load_target)
|
||||||
|
|
||||||
|
result = await save_memory(
|
||||||
|
scope=MemoryScope.USER,
|
||||||
|
target_id="00000000-0000-0000-0000-000000000000",
|
||||||
|
content=" no update ",
|
||||||
|
session=session,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result.status == "no_op"
|
||||||
|
assert result.memory_md == existing
|
||||||
|
assert target.memory_md == existing
|
||||||
|
assert session.commit_calls == 0
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_save_memory_grandfathers_existing_team_personal_heading(
|
async def test_save_memory_grandfathers_existing_team_personal_heading(
|
||||||
monkeypatch,
|
monkeypatch,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue