"use client"; import { useCallback, useEffect, useState } from "react"; import { Button, Card } from "@/components/ui/Primitives"; import { queryEntity, getEntityTimeline, getKGContradictions, type PalaceKGTriple } from "@/lib/palace-client"; interface KnowledgeGraphViewProps { wingId?: string; } export function KnowledgeGraphView({ wingId }: KnowledgeGraphViewProps) { const [entity, setEntity] = useState(""); const [triples, setTriples] = useState([]); const [contradictions, setContradictions] = useState>([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const loadContradictions = useCallback(async () => { try { const result = await getKGContradictions(wingId); setContradictions(result); } catch { // Ignore — contradictions are supplementary } }, [wingId]); useEffect(() => { void loadContradictions(); }, [loadContradictions]); const handleQuery = async () => { if (!entity.trim()) return; try { setLoading(true); setError(null); const result = await queryEntity(entity); setTriples(result); } catch { setError("Query failed"); } finally { setLoading(false); } }; const handleTimeline = async () => { if (!entity.trim()) return; try { setLoading(true); setError(null); const result = await getEntityTimeline(entity); setTriples(result); } catch { setError("Timeline query failed"); } finally { setLoading(false); } }; return (
Knowledge Graph
setEntity(e.target.value)} onKeyDown={(e) => e.key === "Enter" && handleQuery()} placeholder="Query entity (e.g. React, Fastify)..." aria-label="Query knowledge graph entity" className="input" style={{ flex: 1 }} />
{error &&
{error}
} {loading &&
Loading...
} {!loading && triples.length === 0 && entity && (
No triples found for “{entity}”
)}
{triples.map((t) => (
{t.subject} {t.predicate} {t.object} {Math.round(t.confidence * 100)}% {t.validTo && " (invalidated)"}
))}
{contradictions.length > 0 && (
Contradictions ({contradictions.length})
{contradictions.map((c, i) => (
{c.a.subject} {c.a.predicate} → {c.a.object}
vs → {c.b.object}
))}
)}
); }