mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
finish build_context
This commit is contained in:
@@ -64,16 +64,6 @@ class MemoryUrl(BaseModel):
|
||||
|
||||
# Create base URL
|
||||
url = cls(scheme=scheme, host=host, path=path)
|
||||
|
||||
# Parse special patterns
|
||||
path_no_slash = path[1:] if path.startswith("/") else path
|
||||
|
||||
# Extract special prefixes
|
||||
segments = path_no_slash.split("/")
|
||||
if segments and segments[0] in {"related", "context"}:
|
||||
url.params["type"] = segments[0]
|
||||
url.params["target"] = "/".join(segments[1:])
|
||||
|
||||
return url
|
||||
|
||||
@property
|
||||
|
||||
@@ -58,18 +58,9 @@ class ContextService:
|
||||
|
||||
# Parse the URI
|
||||
memory_url = MemoryUrl.parse(uri)
|
||||
|
||||
# Find primary entities based on URL type
|
||||
if memory_url.params.get("type") == "related":
|
||||
# Special mode for finding related content
|
||||
target = memory_url.params["target"]
|
||||
logger.debug(f"Finding related content for '{target}'")
|
||||
|
||||
# start by looking at direct relations
|
||||
primary = await self.find_related_1(target)
|
||||
|
||||
# Pattern matching - use search
|
||||
elif '*' in memory_url.relative_path():
|
||||
if '*' in memory_url.relative_path():
|
||||
logger.debug(f"Pattern search for '{memory_url.relative_path()}'")
|
||||
primary = await self.search_repository.search(permalink_match=memory_url.relative_path())
|
||||
|
||||
@@ -104,20 +95,6 @@ class ContextService:
|
||||
},
|
||||
}
|
||||
|
||||
async def find_related_1(self, permalink: str):
|
||||
"""Find entities related to a given permalink."""
|
||||
# First find the target entity
|
||||
target = await self.search_repository.search(permalink=permalink)
|
||||
if not target:
|
||||
return []
|
||||
|
||||
# Use find_connected to get related items at depth=1
|
||||
type_id_pairs = [(r.type, r.id) for r in target]
|
||||
return await self.find_connected(
|
||||
type_id_pairs,
|
||||
max_depth=1, # Only immediate relations
|
||||
)
|
||||
|
||||
async def find_connected(
|
||||
self,
|
||||
type_id_pairs: List[Tuple[str, int]],
|
||||
|
||||
@@ -68,26 +68,12 @@ async def test_get_memory_context_timeframe(client, test_graph):
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_related_context(client, test_graph):
|
||||
"""Test getting related content."""
|
||||
async def test_get_related_context_filters(client, test_graph):
|
||||
"""Test filtering related content by relation type."""
|
||||
response = await client.get("/memory/related/test/root")
|
||||
assert response.status_code == 200
|
||||
|
||||
context = GraphContext(**response.json())
|
||||
assert len(context.primary_entities) > 0
|
||||
assert any("connected1" in e.permalink for e in context.related_entities)
|
||||
assert any("connected2" in e.permalink for e in context.related_entities)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_related_context_filters(client, test_graph):
|
||||
"""Test filtering related content by relation type."""
|
||||
response = await client.get("/memory/related/test/root?relation_types=connects_to")
|
||||
assert response.status_code == 200
|
||||
|
||||
context = GraphContext(**response.json())
|
||||
for relation in context.related_entities:
|
||||
if relation.type == "relation":
|
||||
assert relation.relation_type == "connects_to"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from basic_memory.schemas.memory import MemoryUrl
|
||||
|
||||
|
||||
@@ -11,7 +12,6 @@ def test_basic_permalink():
|
||||
assert url.scheme == "memory"
|
||||
assert url.host == "basic-memory"
|
||||
assert url.path == "/specs/search"
|
||||
assert url.pattern is None
|
||||
assert url.params == {}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ def test_glob_pattern():
|
||||
url = MemoryUrl.parse("memory://basic-memory/specs/search/*")
|
||||
assert url.host == "basic-memory"
|
||||
assert url.path == "/specs/search/*"
|
||||
assert url.pattern == "specs/search/*"
|
||||
|
||||
|
||||
def test_related_prefix():
|
||||
@@ -28,10 +27,6 @@ def test_related_prefix():
|
||||
url = MemoryUrl.parse("memory://basic-memory/related/specs/search")
|
||||
assert url.host == "basic-memory"
|
||||
assert url.path == "/related/specs/search"
|
||||
assert url.params == {
|
||||
"type": "related",
|
||||
"target": "specs/search"
|
||||
}
|
||||
|
||||
|
||||
def test_context_prefix():
|
||||
@@ -39,10 +34,6 @@ def test_context_prefix():
|
||||
url = MemoryUrl.parse("memory://basic-memory/context/current")
|
||||
assert url.host == "basic-memory"
|
||||
assert url.path == "/context/current"
|
||||
assert url.params == {
|
||||
"type": "context",
|
||||
"target": "current"
|
||||
}
|
||||
|
||||
|
||||
def test_invalid_scheme():
|
||||
@@ -62,7 +53,6 @@ def test_complex_pattern():
|
||||
url = MemoryUrl.parse("memory://basic-memory/specs/*/search/*")
|
||||
assert url.host == "basic-memory"
|
||||
assert url.path == "/specs/*/search/*"
|
||||
assert url.pattern == "specs/*/search/*"
|
||||
|
||||
|
||||
def test_url_reconstruction():
|
||||
@@ -81,4 +71,4 @@ def test_relative_path():
|
||||
def test_project_property():
|
||||
"""Test project name access."""
|
||||
url = MemoryUrl.parse("memory://basic-memory/specs/search")
|
||||
assert url.project == "basic-memory"
|
||||
assert url.project == "basic-memory"
|
||||
|
||||
@@ -19,19 +19,16 @@ def test_search_modes():
|
||||
query = SearchQuery(permalink="specs/search")
|
||||
assert query.permalink == "specs/search"
|
||||
assert query.text is None
|
||||
assert query.permalink_pattern is None
|
||||
|
||||
# Pattern match
|
||||
query = SearchQuery(permalink_pattern="specs/*")
|
||||
assert query.permalink_pattern == "specs/*"
|
||||
query = SearchQuery(permalink="specs/*")
|
||||
assert query.permalink == "specs/*"
|
||||
assert query.text is None
|
||||
assert query.permalink is None
|
||||
|
||||
# Text search
|
||||
query = SearchQuery(text="search implementation")
|
||||
assert query.text == "search implementation"
|
||||
assert query.permalink is None
|
||||
assert query.permalink_pattern is None
|
||||
|
||||
|
||||
def test_search_filters():
|
||||
|
||||
@@ -15,16 +15,6 @@ async def context_service(search_repository, entity_repository):
|
||||
"""Create context service for testing."""
|
||||
return ContextService(search_repository, entity_repository)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_related_1(context_service, test_graph):
|
||||
"""Test finding related content."""
|
||||
results = await context_service.find_related_1("test/root")
|
||||
# Should get immediate connections
|
||||
assert any("connected1" in r.permalink for r in results)
|
||||
assert any("connected2" in r.permalink for r in results)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_find_connected_basic(context_service, test_graph, search_service):
|
||||
"""Test basic connectivity traversal."""
|
||||
@@ -175,13 +165,6 @@ async def test_build_context_pattern(context_service, test_graph):
|
||||
total_entities = results["metadata"]["total_entities"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_context_related(context_service, test_graph):
|
||||
"""Test building context from related mode."""
|
||||
context = await context_service.build_context("memory://project/related/test/root")
|
||||
assert len(context["primary_entities"]) > 0
|
||||
assert len(context["related_entities"]) > 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_build_context_not_found(context_service):
|
||||
|
||||
Reference in New Issue
Block a user