add select relations to list_by_type tool

This commit is contained in:
phernandez
2024-12-30 15:05:35 -06:00
parent 8dd2de3e9a
commit 12a21d81b6
2 changed files with 100 additions and 6 deletions
@@ -24,17 +24,34 @@ class EntityRepository(Repository[Entity]):
return await self.find_one(query)
async def list_entities(
self,
entity_type: Optional[str] = None,
doc_id: Optional[int] = None,
sort_by: Optional[str] = "updated_at",
self,
entity_type: Optional[str] = None,
doc_id: Optional[int] = None,
sort_by: Optional[str] = "updated_at",
include_related: bool = False,
) -> Sequence[Entity]:
"""List all entities, optionally filtered by type and sorted."""
query = self.select().options(*self.get_load_options())
query = self.select()
# Always load base relations
query = query.options(*self.get_load_options())
# Apply filters
if entity_type:
query = query.where(Entity.entity_type == entity_type)
# When include_related is True, get both:
# 1. Entities of the requested type
# 2. Entities that have relations with entities of the requested type
if include_related:
query = query.where(
or_(
Entity.entity_type == entity_type,
Entity.from_relations.any(Relation.to_entity.has(entity_type=entity_type)),
Entity.to_relations.any(Relation.from_entity.has(entity_type=entity_type))
)
)
else:
query = query.where(Entity.entity_type == entity_type)
if doc_id:
query = query.where(Entity.doc_id == doc_id)
@@ -461,3 +461,80 @@ async def test_delete_by_path_ids_with_observations(
result = await session.execute(query)
remaining_observations = result.scalars().all()
assert len(remaining_observations) == 0
@pytest.mark.asyncio
async def test_list_entities_with_related(entity_repository: EntityRepository, session_maker):
"""Test listing entities with related entities included."""
# Create test entities
async with db.scoped_session(session_maker) as session:
# Core entities
core = Entity(
name="core_service",
entity_type="service",
path_id="service/core",
file_path="service/core.md",
description="Core service"
)
dbe = Entity(
name="db_service",
entity_type="service",
path_id="service/db",
file_path="service/db.md",
description="Database service"
)
# Related entity of different type
config = Entity(
name="service_config",
entity_type="configuration",
path_id="config/service",
file_path="config/service.md",
description="Service configuration"
)
session.add_all([core, dbe, config])
await session.flush()
# Create relations in both directions
relations = [
# core -> db (depends_on)
Relation(from_id=core.id, to_id=dbe.id, relation_type="depends_on"),
# config -> core (configures)
Relation(from_id=config.id, to_id=core.id, relation_type="configures")
]
session.add_all(relations)
# Test 1: List services without related entities
services = await entity_repository.list_entities(
entity_type="service",
include_related=False
)
assert len(services) == 2
service_names = {s.name for s in services}
assert service_names == {"core_service", "db_service"}
# Test 2: List services with related entities
services_and_related = await entity_repository.list_entities(
entity_type="service",
include_related=True
)
assert len(services_and_related) == 3
# Should include both services and the config
entity_names = {e.name for e in services_and_related}
assert entity_names == {"core_service", "db_service", "service_config"}
# Test 3: Verify relations are loaded
core_service = next(e for e in services_and_related if e.name == "core_service")
assert len(core_service.from_relations) > 0 # Has incoming relation from config
assert len(core_service.to_relations) > 0 # Has outgoing relation to db
# Test 4: List configurations with related
configs = await entity_repository.list_entities(
entity_type="configuration",
include_related=True,
sort_by="name"
)
config_names = {c.name for c in configs}
# Should include both config and the services it relates to
assert "service_config" in config_names
assert "core_service" in config_names # Related via configures relation