From 9f75c8b20b84084468ec1d3f1210458850e6cd81 Mon Sep 17 00:00:00 2001 From: Stuart McKay Date: Thu, 2 Jul 2026 22:11:54 +1200 Subject: [PATCH] fix(memory): reject relations with missing entities --- src/memory/__tests__/knowledge-graph.test.ts | 30 ++++++++++++++++++++ src/memory/index.ts | 11 +++++++ 2 files changed, 41 insertions(+) diff --git a/src/memory/__tests__/knowledge-graph.test.ts b/src/memory/__tests__/knowledge-graph.test.ts index 236242413a..7b2266391d 100644 --- a/src/memory/__tests__/knowledge-graph.test.ts +++ b/src/memory/__tests__/knowledge-graph.test.ts @@ -103,6 +103,36 @@ describe('KnowledgeGraphManager', () => { const newRelations = await manager.createRelations([]); expect(newRelations).toHaveLength(0); }); + + it('should reject relations with a missing from entity', async () => { + await manager.createEntities([ + { name: 'Alice', entityType: 'person', observations: [] }, + ]); + + await expect( + manager.createRelations([ + { from: 'Ghost', to: 'Alice', relationType: 'knows' }, + ]) + ).rejects.toThrow('Entity with name Ghost not found'); + + const graph = await manager.readGraph(); + expect(graph.relations).toHaveLength(0); + }); + + it('should reject relations with a missing to entity', async () => { + await manager.createEntities([ + { name: 'Alice', entityType: 'person', observations: [] }, + ]); + + await expect( + manager.createRelations([ + { from: 'Alice', to: 'Ghost', relationType: 'knows' }, + ]) + ).rejects.toThrow('Entity with name Ghost not found'); + + const graph = await manager.readGraph(); + expect(graph.relations).toHaveLength(0); + }); }); describe('addObservations', () => { diff --git a/src/memory/index.ts b/src/memory/index.ts index 9865c5318e..4f595d12c0 100644 --- a/src/memory/index.ts +++ b/src/memory/index.ts @@ -127,6 +127,17 @@ export class KnowledgeGraphManager { async createRelations(relations: Relation[]): Promise { const graph = await this.loadGraph(); + const entityNames = new Set(graph.entities.map(e => e.name)); + + for (const relation of relations) { + if (!entityNames.has(relation.from)) { + throw new Error(`Entity with name ${relation.from} not found`); + } + if (!entityNames.has(relation.to)) { + throw new Error(`Entity with name ${relation.to} not found`); + } + } + const newRelations = relations.filter(r => !graph.relations.some(existingRelation => existingRelation.from === r.from && existingRelation.to === r.to &&