From ef0de0d760e1418b8acae626cc0c334a0509f818 Mon Sep 17 00:00:00 2001 From: viettranx Date: Tue, 31 Mar 2026 19:33:01 +0700 Subject: [PATCH] fix(kg): merge recursive CTE branches and widen detail dialog Combine forward+reverse traversal into single recursive branch using CASE to fix SQLSTATE 42P19 (PostgreSQL parses triple UNION ALL as left-associative, putting recursive ref in non-recursive term). Also widen entity detail dialog from max-w-5xl to max-w-7xl. --- .../store/pg/knowledge_graph_traversal.go | 50 +++++-------------- .../pages/memory/kg-entity-detail-dialog.tsx | 2 +- 2 files changed, 13 insertions(+), 39 deletions(-) diff --git a/internal/store/pg/knowledge_graph_traversal.go b/internal/store/pg/knowledge_graph_traversal.go index 48e834f7..887bbe28 100644 --- a/internal/store/pg/knowledge_graph_traversal.go +++ b/internal/store/pg/knowledge_graph_traversal.go @@ -62,28 +62,15 @@ func (s *PGKnowledgeGraphStore) Traverse(ctx context.Context, agentID, userID, s e.created_at, e.updated_at, p.depth + 1, p.path || e.id::text, - r.relation_type + CASE WHEN r.source_entity_id = p.id + THEN r.relation_type + ELSE '~' || r.relation_type + END FROM paths p - JOIN kg_relations r ON p.id = r.source_entity_id AND r.agent_id = $2 - JOIN kg_entities e ON r.target_entity_id = e.id AND e.agent_id = $2 + JOIN kg_relations r ON (r.source_entity_id = p.id OR r.target_entity_id = p.id) AND r.agent_id = $2 + JOIN kg_entities e ON e.id = (CASE WHEN r.source_entity_id = p.id THEN r.target_entity_id ELSE r.source_entity_id END) AND e.agent_id = $2 WHERE p.depth < $%d AND NOT e.id::text = ANY(p.path) - - UNION ALL - - SELECT - e.id, e.agent_id, e.user_id, e.external_id, - e.name, e.entity_type, e.description, - e.properties, e.source_id, e.confidence, - e.created_at, e.updated_at, - p.depth + 1, - p.path || e.id::text, - '~' || r.relation_type - FROM paths p - JOIN kg_relations r ON p.id = r.target_entity_id AND r.agent_id = $2 - JOIN kg_entities e ON r.source_entity_id = e.id AND e.agent_id = $2 - WHERE p.depth < $%[2]d - AND NOT e.id::text = ANY(p.path) ) SELECT id, agent_id, user_id, external_id, @@ -123,28 +110,15 @@ func (s *PGKnowledgeGraphStore) Traverse(ctx context.Context, agentID, userID, s e.created_at, e.updated_at, p.depth + 1, p.path || e.id::text, - r.relation_type + CASE WHEN r.source_entity_id = p.id + THEN r.relation_type + ELSE '~' || r.relation_type + END FROM paths p - JOIN kg_relations r ON p.id = r.source_entity_id AND r.user_id = $3 - JOIN kg_entities e ON r.target_entity_id = e.id AND e.user_id = $3 + JOIN kg_relations r ON (r.source_entity_id = p.id OR r.target_entity_id = p.id) AND r.user_id = $3 + JOIN kg_entities e ON e.id = (CASE WHEN r.source_entity_id = p.id THEN r.target_entity_id ELSE r.source_entity_id END) AND e.user_id = $3 WHERE p.depth < $%d AND NOT e.id::text = ANY(p.path) - - UNION ALL - - SELECT - e.id, e.agent_id, e.user_id, e.external_id, - e.name, e.entity_type, e.description, - e.properties, e.source_id, e.confidence, - e.created_at, e.updated_at, - p.depth + 1, - p.path || e.id::text, - '~' || r.relation_type - FROM paths p - JOIN kg_relations r ON p.id = r.target_entity_id AND r.user_id = $3 - JOIN kg_entities e ON r.source_entity_id = e.id AND e.user_id = $3 - WHERE p.depth < $%[2]d - AND NOT e.id::text = ANY(p.path) ) SELECT id, agent_id, user_id, external_id, diff --git a/ui/web/src/pages/memory/kg-entity-detail-dialog.tsx b/ui/web/src/pages/memory/kg-entity-detail-dialog.tsx index 5bbaeecf..9881c1d5 100644 --- a/ui/web/src/pages/memory/kg-entity-detail-dialog.tsx +++ b/ui/web/src/pages/memory/kg-entity-detail-dialog.tsx @@ -84,7 +84,7 @@ export function KGEntityDetailDialog({ open, onOpenChange, agentId, entity, getE return ( !traversing && onOpenChange(v)}> - + {entity?.name}