From c14c37d46b902b407292838274111d3c5c2fda30 Mon Sep 17 00:00:00 2001 From: Kewe63 Date: Tue, 2 Jun 2026 10:34:44 +0300 Subject: [PATCH] =?UTF-8?q?fix(openviking):=20add=20missing=20/agent/{agen?= =?UTF-8?q?t}/=20segment=20to=20memory=20URI=20=E2=80=94=20fixes=20#36969?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _build_memory_uri produced URIs of the form: viking://user/{user}/memories/{subdir}/mem_{slug}.md The /agent/{agent}/ segment was missing, causing every agent under the same user to write into the same flat namespace. In multi-agent deployments agents silently overwrite each other's memories and vector retrieval cross-pollinates results. self._agent was already populated correctly (from OPENVIKING_AGENT env var, default 'hermes') and sent via X-OpenViking-Agent header — it was simply not interpolated into the URI. Fix: add the missing segment so URIs follow the documented shape: viking://user/{user}/agent/{agent}/memories/{subdir}/mem_{slug}.md Tests: 4 new regression tests in TestOpenVikingMemoryUriBuilder, 13/13 passed (9 existing + 4 new). --- plugins/memory/openviking/__init__.py | 4 +- tests/openviking_plugin/test_openviking.py | 50 ++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/plugins/memory/openviking/__init__.py b/plugins/memory/openviking/__init__.py index 42925fa74..810f2db43 100644 --- a/plugins/memory/openviking/__init__.py +++ b/plugins/memory/openviking/__init__.py @@ -627,9 +627,9 @@ class OpenVikingMemoryProvider(MemoryProvider): logger.warning("OpenViking session commit failed: %s", e) def _build_memory_uri(self, subdir: str) -> str: - """Build a viking:// memory URI under the configured user/subdir.""" + """Build a viking:// memory URI under the configured user/agent/subdir.""" slug = uuid.uuid4().hex[:12] - return f"viking://user/{self._user}/memories/{subdir}/mem_{slug}.md" + return f"viking://user/{self._user}/agent/{self._agent}/memories/{subdir}/mem_{slug}.md" def on_memory_write( self, diff --git a/tests/openviking_plugin/test_openviking.py b/tests/openviking_plugin/test_openviking.py index 6848afc47..505ac54eb 100644 --- a/tests/openviking_plugin/test_openviking.py +++ b/tests/openviking_plugin/test_openviking.py @@ -231,3 +231,53 @@ class TestOpenVikingBrowse: "/api/v1/fs/ls", {"uri": "viking://user/hermes"}, )] + + +class TestOpenVikingMemoryUriBuilder: + """Regression tests for _build_memory_uri — fixes #36969. + + Before the fix the URI omitted /agent/{agent}/, causing all agents + under the same user to share the same memory namespace. + """ + + def _make_provider(self, user="alice", agent="coder"): + p = OpenVikingMemoryProvider.__new__(OpenVikingMemoryProvider) + p._user = user + p._agent = agent + return p + + def test_uri_layout_includes_agent_segment(self): + """URI must contain /agent/{agent}/ between user and memories.""" + p = self._make_provider(user="alice", agent="coder") + uri = p._build_memory_uri("preferences") + assert uri.startswith("viking://user/alice/agent/coder/memories/preferences/mem_") + assert uri.endswith(".md") + + def test_uri_uses_configured_agent_not_default(self): + """_agent value must be interpolated — not hardcoded to 'hermes'.""" + p = self._make_provider(user="alice", agent="research-bot") + uri = p._build_memory_uri("entities") + assert "/agent/research-bot/" in uri + assert "/agent/hermes/" not in uri + + def test_uri_slug_is_twelve_hex_chars_and_unique(self): + """Slug must be 12 hex chars and differ between calls.""" + import re + p = self._make_provider() + uri1 = p._build_memory_uri("preferences") + uri2 = p._build_memory_uri("preferences") + slug1 = uri1.split("/mem_")[1].replace(".md", "") + slug2 = uri2.split("/mem_")[1].replace(".md", "") + assert re.fullmatch(r"[0-9a-f]{12}", slug1) + assert re.fullmatch(r"[0-9a-f]{12}", slug2) + assert slug1 != slug2 + + def test_uri_subdir_placed_correctly_for_all_categories(self): + """All five category subdirs must appear between memories/ and slug.""" + p = self._make_provider(user="u", agent="a") + subdirs = ["preferences", "entities", "events", "cases", "patterns"] + for subdir in subdirs: + uri = p._build_memory_uri(subdir) + assert f"/memories/{subdir}/mem_" in uri, ( + f"subdir '{subdir}' not placed correctly in URI: {uri}" + )