@khoralabs/memories-react-graph
v0.7.6
Published
React 3D graph UI for exploring memories knowledge graphs.
Readme
@khoralabs/memories-react-graph
React components for exploring a memories knowledge graph in 3D: hybrid search, namespace selection, and memory preview.
Built on React 19, @react-three/fiber, and three.js. The package does not open a database by itself — mount MemoriesClientProvider with a ReactMemoriesClient (or createClient factory for database switching), then namespaces + namespace-memories providers for catalog/focus/CRUD.
Exports
| Export | Role |
|--------|------|
| @khoralabs/memories-react-graph | Browser UI: providers, graph chrome, hooks, ReactMemoriesClient type |
| @khoralabs/memories-react-graph/service | createServiceReactMemoriesClient (Node/server or hosts that intentionally pull memories-service) |
| MemoriesClientProvider / useMemoriesClient / useMemoriesDatabase | Client + database focus + resolved ontology |
| MemoriesNamespacesProvider / useMemoriesNamespaces | Namespace catalog, focus, CRUD/suppress, arms-driven search |
| MemoriesNamespaceMemoriesProvider / useMemoriesMemory | Scope-sensitive graph catalog, search, memory focus, create/update/remove (MemoriesMemoryProvider is a deprecated alias) |
| useGraphMemoriesSearch / useGraphNamespacesSearch | Thin chrome slices of provider search state (not useMemoriesGraphChrome) |
| ReactMemoriesClient | Host backend interface (implement over a BFF, or use /service) |
| DEFAULT_SEARCH_DEBOUNCE_MS | Shared default debounce for namespace + memory search |
| GraphScene | 3D graph canvas with nodes, edges, focus/hover |
| GraphProjectionProvider / useProjection / useMemoriesGraphChrome | Scene projection; chrome = load/refresh/Esc (search is via search hooks) |
| GraphSearch / GraphNamespaceSearch | Memory / namespace search (Input / Addon / Loading compounds; bare <GraphSearch /> keeps defaults) |
| GraphNamespaceTree | Hierarchical namespace browser; Hierarchy filters to ranked search hits |
| AddNamespaceButton / AddMemoryButton / RefreshGraphButton | Compound chrome buttons (.Tooltip + Button props) |
| GraphPreviewDock | Selected memory preview panel |
| GraphLoading, GraphFetchError | Loading and error states |
Peer dependencies: react, react-dom, three, @react-three/fiber, @react-three/drei, @react-three/postprocessing (used when fog.blur is enabled for screen-space edge softening). Optional peer: @khoralabs/memories-service (only for /service).
Host integration
- Implement
ReactMemoriesClient(browser BFF) or importcreateServiceReactMemoriesClientfrom@khoralabs/memories-react-graph/service(do not import/serviceinto a Vite/Bun HTML client bundle that only needs UI). - Mount
MemoriesClientProvider→MemoriesNamespacesProvider→MemoriesNamespaceMemoriesProvider→GraphProjectionProvider. - Namespace root is host-owned (no package default). Prefer
listNamespaces.namespaceRoot(catalog wins); else providernamespaceRootprop. WithcreateServiceReactMemoriesClient, passnamespaceRooton the client (stamped ontolistNamespaces) and/or on the provider — bare service catalog has no root field. Omitting focusnamespacelands on that root withsubtreeonce known. - Hosts own create forms; call
useMemoriesNamespaces().create/useMemoriesMemory().create. UseAddNamespaceButton/AddMemoryButtonas chrome triggers only (wireonClick). - The memory catalog follows namespaces
scope(exactvssubtree). Memory search UI usesuseGraphMemoriesSearch/GraphSearch(notuseMemoriesGraphChrome). Bare<GraphSearch />/<GraphNamespaceSearch />keep the default input + icon + status chrome; compose.Input/.Addon/.Loadingto add or reorder addons. - Namespace search (
GraphNamespaceSearch) is arms-driven; tune withuseGraphNamespacesSearch().setSearchArms(e.g.{ nodes: 0, lexical: 1 }for catalog-only). Pair withGraphNamespaceTree— Hierarchy shows the full catalog when the query is empty, and a score-ordered hit tree while searching.
import {
AddMemoryButton,
AddNamespaceButton,
GraphNamespaceSearch,
GraphNamespaceTree,
GraphProjectionProvider,
GraphScene,
GraphSearch,
MemoriesClientProvider,
MemoriesNamespaceMemoriesProvider,
MemoriesNamespacesProvider,
useMemoriesMemory,
useMemoriesNamespaces,
} from "@khoralabs/memories-react-graph";
import { createServiceReactMemoriesClient } from "@khoralabs/memories-react-graph/service";
const database = { kind: "account" as const, ownerKey: "user-1" };
const createClient = (db: typeof database) =>
createServiceReactMemoriesClient({
baseUrl: "https://memories.example",
database: db,
namespaceRoot: "global", // host convention
});
function CreateMemoryControl() {
const { create } = useMemoriesMemory();
return (
<AddMemoryButton
onClick={() => {
const key = window.prompt("Memory key");
if (!key) return;
void create({
kind: "node",
key,
content: [{ key: "body", text: "…" }],
});
}}
/>
);
}
function CreateNamespaceControl({ parent }: { parent?: string }) {
const { create, validateSegment } = useMemoriesNamespaces();
return (
<AddNamespaceButton
onClick={() => {
const name = window.prompt("Namespace name");
if (!name) return;
if (validateSegment(name)) return;
void create({ parent, name });
}}
/>
);
}
function MemoriesGraphPage() {
return (
<MemoriesClientProvider createClient={createClient} database={database}>
<MemoriesNamespacesProvider>
<MemoriesNamespaceMemoriesProvider>
<GraphProjectionProvider>
<CreateNamespaceControl />
<CreateMemoryControl />
<GraphNamespaceSearch />
<GraphNamespaceTree>
<GraphNamespaceTree.Label>
Namespaces
{/* Wrappers must use LabelActions (direct AddNamespaceButton also works) */}
<GraphNamespaceTree.LabelActions>
<CreateNamespaceControl />
</GraphNamespaceTree.LabelActions>
</GraphNamespaceTree.Label>
<GraphNamespaceTree.Hierarchy />
</GraphNamespaceTree>
<GraphSearch />
<GraphScene />
</GraphProjectionProvider>
</MemoriesNamespaceMemoriesProvider>
</MemoriesNamespacesProvider>
</MemoriesClientProvider>
);
}Hosts can still drive subgraph highlighting via useGraphMemoriesSearch().setGraphSearchOverride (e.g. after calling @khoralabs/memories-agents or a host investigate route).
Compose search chrome when you need extra addons (.Loading is the status spinner / summary):
<GraphSearch>
<GraphSearch.Input />
<GraphSearch.Addon>…</GraphSearch.Addon>
<GraphSearch.Addon align="inline-end">
<GraphSearch.Loading />
</GraphSearch.Addon>
</GraphSearch>Development
bun install
bun test packages/react/graph
bun run --filter @khoralabs/memories-react-graph typecheck