@anvia/neo4j 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,23 +2,22 @@
2
2
 
3
3
  Schema-first local GraphRAG for Neo4j 2026.01 and newer.
4
4
 
5
+ Provider-neutral schemas from `@anvia/graph` are accepted alongside the compatibility
6
+ `defineNeo4jGraphSchema()` API. Registered graphs expose `graph.retrieve()`, and the shared
7
+ `createGraphSearchTool()` factory gives Neo4j and Memgraph the same Agent tool API.
8
+
5
9
  ## Installation
6
10
 
7
11
  ```sh
8
- pnpm add @anvia/neo4j @anvia/core
12
+ pnpm add @anvia/graph @anvia/neo4j @anvia/core
9
13
  ```
10
14
 
11
15
  ## Managed knowledge graph
12
16
 
13
17
  ```ts
14
18
  import { Agent } from "@anvia/core/agent";
15
- import { embedDocuments } from "@anvia/core/embeddings";
16
- import {
17
- Neo4jClient,
18
- createNeo4jGraphSearchTool,
19
- defineNeo4jGraphSchema,
20
- extractGraphFacts,
21
- } from "@anvia/neo4j";
19
+ import { createGraphSearchTool, ingestGraphText } from "@anvia/graph";
20
+ import { Neo4jClient, defineNeo4jGraphSchema } from "@anvia/neo4j";
22
21
  import { z } from "zod";
23
22
 
24
23
  const schema = defineNeo4jGraphSchema({
@@ -71,34 +70,23 @@ const graph = client.managedKnowledgeGraph({
71
70
 
72
71
  await graph.ensure({ indexTimeoutMs: 60_000 });
73
72
 
74
- const facts = await extractGraphFacts({ model: extractionModel, schema, chunks });
75
- const [embeddedChunks, embeddedEntities] = await Promise.all([
76
- embedDocuments({
77
- model: embeddingModel,
78
- documents: chunks,
79
- id: (chunk) => chunk.id,
80
- content: (chunk) => chunk.text,
81
- }),
82
- embedDocuments({
83
- model: embeddingModel,
84
- documents: [...facts.output.entities],
85
- id: (entity) => entity.key,
86
- content: (entity) => formatEntity(entity),
87
- }),
88
- ]);
89
-
90
- const write = await graph.replaceDocuments({
91
- documents,
92
- chunks: embeddedChunks.documents,
93
- entities: embeddedEntities.documents,
94
- relationships: facts.output.relationships,
95
- mentions: facts.output.mentions,
73
+ const ingestion = await ingestGraphText({
74
+ graph,
75
+ document: { id: "incident-42", text },
76
+ extractionModel,
77
+ embeddingModel,
78
+ chunking: {
79
+ strategy: "recursive",
80
+ maxSize: 1_000,
81
+ overlap: 100,
82
+ separators: ["\n\n", "\n", " "],
83
+ },
96
84
  conflict: "error",
97
85
  orphanEntities: "delete",
98
86
  });
99
- console.log(write);
87
+ console.log(ingestion.write);
100
88
 
101
- const searchGraph = createNeo4jGraphSearchTool({
89
+ const searchGraph = createGraphSearchTool({
102
90
  name: "search_support_graph",
103
91
  description: "Search connected support incidents and products.",
104
92
  graph,
@@ -123,9 +111,10 @@ const searchGraph = createNeo4jGraphSearchTool({
123
111
  const agent = new Agent({ id: "support", model: chatModel, tools: [searchGraph] });
124
112
  ```
125
113
 
126
- The application owns file discovery, reading, chunking, entity embedding text, model loading,
127
- retry policy, and Agent lifecycle. `extractGraphFacts()` performs model extraction but no writes.
128
- `replaceDocuments()` performs one deterministic transaction but no model calls.
114
+ The application owns file discovery, reading, model loading, retry policy, and Agent lifecycle.
115
+ `ingestGraphText()` and `ingestGraphDocuments()` provide the convenient end-to-end path. Advanced
116
+ callers can compose `prepareGraphDocuments()`, `extractGraphFacts()`, `embedDocuments()`, and
117
+ `replaceDocuments()` directly when they need custom orchestration.
129
118
 
130
119
  Graph property schemas must use `z.strictObject()` and must not coerce, default, transform,
131
120
  preprocess, catch, trim, or otherwise overwrite values. This keeps extraction, comparison, and
@@ -181,6 +170,23 @@ const graph = client.knowledgeGraph({
181
170
  await graph.validate();
182
171
  ```
183
172
 
173
+ ## Graph explorer
174
+
175
+ Managed and existing graph registrations implement the shared `GraphExplorer` contract:
176
+
177
+ ```ts
178
+ const overview = await graph.explore({ mode: "overview", maxNodes: 100 });
179
+ const neighborhood = await graph.explore({
180
+ mode: "expand",
181
+ nodeIds: [overview.nodes[0]!.id],
182
+ maxDepth: 1,
183
+ });
184
+ ```
185
+
186
+ The explorer returns Neo4j element IDs as opaque strings, limits every query, and omits embeddings
187
+ and other `__anvia_*` properties. Use stable graph identity properties for application logic; use the
188
+ opaque IDs only to expand the current view.
189
+
184
190
  Existing registrations are read-only and expose no provisioning or write methods. Use
185
191
  `client.nativeDriver()` for application-owned Cypher.
186
192
 
@@ -0,0 +1,176 @@
1
+ import {
2
+ Neo4jKnowledgeGraphBase,
3
+ parseNeo4jProperties
4
+ } from "./chunk-QNHOT7P2.js";
5
+
6
+ // src/explore.ts
7
+ import {
8
+ resolveGraphExploreOptions
9
+ } from "@anvia/graph";
10
+ import { int } from "neo4j-driver";
11
+ async function exploreGraph(graph, options) {
12
+ if (!(graph instanceof Neo4jKnowledgeGraphBase)) {
13
+ throw new TypeError("exploreGraph requires a Neo4j knowledge graph registration.");
14
+ }
15
+ const resolved = resolveGraphExploreOptions(graph.schema, options);
16
+ const records = resolved.mode === "overview" ? await overviewNodes(graph, resolved) : await expandedNodes(graph, resolved);
17
+ const nodes = uniqueNodes(records.map((record) => nodeFromRecord(record, graph.schema)));
18
+ const visibleNodes = nodes.slice(0, resolved.maxNodes);
19
+ const relationships = await relationshipsBetween(
20
+ graph,
21
+ visibleNodes.map((node) => node.id),
22
+ resolved.relationships,
23
+ resolved.maxRelationships,
24
+ resolved.abortSignal
25
+ );
26
+ return {
27
+ nodes: visibleNodes,
28
+ relationships: relationships.slice(0, resolved.maxRelationships),
29
+ truncated: {
30
+ nodes: records.length > resolved.maxNodes || nodes.length > resolved.maxNodes,
31
+ relationships: relationships.length > resolved.maxRelationships
32
+ }
33
+ };
34
+ }
35
+ async function overviewNodes(graph, options) {
36
+ const result = await graph.query(
37
+ `MATCH (node)
38
+ WHERE any(type IN labels(node) WHERE type IN $nodeTypes)
39
+ RETURN elementId(node) AS id, labels(node) AS labels, properties(node) AS properties
40
+ ORDER BY elementId(node)
41
+ LIMIT $nodeLimit`,
42
+ { nodeTypes: options.nodeTypes, nodeLimit: int(options.maxNodes + 1) },
43
+ options.abortSignal
44
+ );
45
+ return result.records;
46
+ }
47
+ async function expandedNodes(graph, options) {
48
+ const roots = await graph.query(
49
+ `MATCH (node)
50
+ WHERE elementId(node) IN $nodeIds
51
+ AND any(type IN labels(node) WHERE type IN $nodeTypes)
52
+ RETURN elementId(node) AS id, labels(node) AS labels, properties(node) AS properties`,
53
+ { nodeIds: options.nodeIds, nodeTypes: options.nodeTypes },
54
+ options.abortSignal
55
+ );
56
+ if (options.relationships.length === 0) return roots.records;
57
+ const remainingNodeLimit = options.maxNodes + 1 - roots.records.length;
58
+ if (remainingNodeLimit <= 0) return roots.records;
59
+ const pattern = traversalPattern(options.direction, options.maxDepth);
60
+ const neighbors = await graph.query(
61
+ `MATCH (root) WHERE elementId(root) IN $nodeIds
62
+ MATCH path = ${pattern}
63
+ WHERE all(rel IN relationships(path) WHERE type(rel) IN $relationshipTypes)
64
+ AND any(type IN labels(node) WHERE type IN $nodeTypes)
65
+ RETURN elementId(node) AS id, labels(node) AS labels, properties(node) AS properties
66
+ LIMIT $nodeLimit`,
67
+ {
68
+ nodeIds: options.nodeIds,
69
+ nodeTypes: options.nodeTypes,
70
+ relationshipTypes: options.relationships,
71
+ nodeLimit: int(remainingNodeLimit)
72
+ },
73
+ options.abortSignal
74
+ );
75
+ return [...roots.records, ...neighbors.records];
76
+ }
77
+ async function relationshipsBetween(graph, nodeIds, relationshipTypes, maxRelationships, abortSignal) {
78
+ if (nodeIds.length === 0 || relationshipTypes.length === 0) return [];
79
+ const result = await graph.query(
80
+ `MATCH (from)-[relationship]->(to)
81
+ WHERE elementId(from) IN $nodeIds
82
+ AND elementId(to) IN $nodeIds
83
+ AND type(relationship) IN $relationshipTypes
84
+ RETURN elementId(relationship) AS id,
85
+ type(relationship) AS type,
86
+ elementId(from) AS source,
87
+ elementId(to) AS target,
88
+ properties(relationship) AS properties
89
+ ORDER BY elementId(relationship)
90
+ LIMIT $relationshipLimit`,
91
+ {
92
+ nodeIds,
93
+ relationshipTypes,
94
+ relationshipLimit: int(maxRelationships + 1)
95
+ },
96
+ abortSignal
97
+ );
98
+ return result.records.map(relationshipFromRecord);
99
+ }
100
+ function nodeFromRecord(record, schema) {
101
+ const id = stringValue(record.get("id"), "Neo4j explorer node id");
102
+ const labels = stringArray(record.get("labels"), "Neo4j explorer node labels");
103
+ const raw = objectValue(record.get("properties"), "Neo4j explorer node properties");
104
+ const type = labels.find((label) => label in schema.nodes);
105
+ if (type === void 0) throw new TypeError("Neo4j explorer node has no registered type.");
106
+ const properties = applicationProperties(raw, "Neo4j explorer node properties");
107
+ const node = {
108
+ id,
109
+ type,
110
+ identity: identityProperties(schema, type, properties),
111
+ properties
112
+ };
113
+ const key = raw.__anvia_key;
114
+ if (typeof key === "string") node.key = key;
115
+ return node;
116
+ }
117
+ function relationshipFromRecord(record) {
118
+ const raw = objectValue(record.get("properties"), "Neo4j explorer relationship properties");
119
+ const relationship = {
120
+ id: stringValue(record.get("id"), "Neo4j explorer relationship id"),
121
+ type: stringValue(record.get("type"), "Neo4j explorer relationship type"),
122
+ from: stringValue(record.get("source"), "Neo4j explorer relationship source"),
123
+ to: stringValue(record.get("target"), "Neo4j explorer relationship target"),
124
+ properties: applicationProperties(raw, "Neo4j explorer relationship properties")
125
+ };
126
+ const key = raw.__anvia_key;
127
+ if (typeof key === "string") relationship.key = key;
128
+ return relationship;
129
+ }
130
+ function identityProperties(schema, type, properties) {
131
+ const identity = {};
132
+ const definition = schema.nodes[type];
133
+ if (definition === void 0) return identity;
134
+ for (const property of definition.identity) {
135
+ const value = properties[property];
136
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
137
+ identity[property] = value;
138
+ }
139
+ }
140
+ return identity;
141
+ }
142
+ function applicationProperties(value, label) {
143
+ return parseNeo4jProperties(
144
+ Object.fromEntries(Object.entries(value).filter(([key]) => !key.startsWith("__anvia_"))),
145
+ label
146
+ );
147
+ }
148
+ function uniqueNodes(nodes) {
149
+ return [...new Map(nodes.map((node) => [node.id, node])).values()];
150
+ }
151
+ function traversalPattern(direction, maxDepth) {
152
+ if (direction === "outgoing") return `(root)-[*1..${maxDepth}]->(node)`;
153
+ if (direction === "incoming") return `(root)<-[*1..${maxDepth}]-(node)`;
154
+ return `(root)-[*1..${maxDepth}]-(node)`;
155
+ }
156
+ function stringValue(value, label) {
157
+ if (typeof value !== "string") throw new TypeError(`${label} must be a string.`);
158
+ return value;
159
+ }
160
+ function stringArray(value, label) {
161
+ if (!Array.isArray(value) || !value.every((item) => typeof item === "string")) {
162
+ throw new TypeError(`${label} must be a string array.`);
163
+ }
164
+ return value;
165
+ }
166
+ function objectValue(value, label) {
167
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
168
+ throw new TypeError(`${label} must be an object.`);
169
+ }
170
+ return value;
171
+ }
172
+
173
+ export {
174
+ exploreGraph
175
+ };
176
+ //# sourceMappingURL=chunk-PWE3ETSF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/explore.ts"],"sourcesContent":["import {\n resolveGraphExploreOptions,\n type GraphExploreNode,\n type GraphExploreOptions,\n type GraphExploreRelationship,\n type GraphExploreResult,\n type ResolvedGraphExploreExpandOptions,\n} from \"@anvia/graph\";\nimport { int, type Record as Neo4jRecord } from \"neo4j-driver\";\nimport { Neo4jKnowledgeGraphBase } from \"./graph.js\";\nimport { parseNeo4jProperties } from \"./schema.js\";\nimport type { Neo4jGraphSchema, Neo4jNodeIdentity } from \"./types.js\";\n\nexport async function exploreGraph<Schema extends Neo4jGraphSchema>(\n graph: Neo4jKnowledgeGraphBase<Schema>,\n options: GraphExploreOptions<Schema>,\n): Promise<GraphExploreResult> {\n if (!(graph instanceof Neo4jKnowledgeGraphBase)) {\n throw new TypeError(\"exploreGraph requires a Neo4j knowledge graph registration.\");\n }\n const resolved = resolveGraphExploreOptions(graph.schema, options);\n const records =\n resolved.mode === \"overview\"\n ? await overviewNodes(graph, resolved)\n : await expandedNodes(graph, resolved);\n const nodes = uniqueNodes(records.map((record) => nodeFromRecord(record, graph.schema)));\n const visibleNodes = nodes.slice(0, resolved.maxNodes);\n const relationships = await relationshipsBetween(\n graph,\n visibleNodes.map((node) => node.id),\n resolved.relationships,\n resolved.maxRelationships,\n resolved.abortSignal,\n );\n return {\n nodes: visibleNodes,\n relationships: relationships.slice(0, resolved.maxRelationships),\n truncated: {\n nodes: records.length > resolved.maxNodes || nodes.length > resolved.maxNodes,\n relationships: relationships.length > resolved.maxRelationships,\n },\n };\n}\n\nasync function overviewNodes(\n graph: Neo4jKnowledgeGraphBase,\n options: ReturnType<typeof resolveGraphExploreOptions> & { mode: \"overview\" },\n): Promise<readonly Neo4jRecord[]> {\n const result = await graph.query(\n `MATCH (node)\nWHERE any(type IN labels(node) WHERE type IN $nodeTypes)\nRETURN elementId(node) AS id, labels(node) AS labels, properties(node) AS properties\nORDER BY elementId(node)\nLIMIT $nodeLimit`,\n { nodeTypes: options.nodeTypes, nodeLimit: int(options.maxNodes + 1) },\n options.abortSignal,\n );\n return result.records;\n}\n\nasync function expandedNodes(\n graph: Neo4jKnowledgeGraphBase,\n options: ResolvedGraphExploreExpandOptions,\n): Promise<readonly Neo4jRecord[]> {\n const roots = await graph.query(\n `MATCH (node)\nWHERE elementId(node) IN $nodeIds\n AND any(type IN labels(node) WHERE type IN $nodeTypes)\nRETURN elementId(node) AS id, labels(node) AS labels, properties(node) AS properties`,\n { nodeIds: options.nodeIds, nodeTypes: options.nodeTypes },\n options.abortSignal,\n );\n if (options.relationships.length === 0) return roots.records;\n const remainingNodeLimit = options.maxNodes + 1 - roots.records.length;\n if (remainingNodeLimit <= 0) return roots.records;\n const pattern = traversalPattern(options.direction, options.maxDepth);\n const neighbors = await graph.query(\n `MATCH (root) WHERE elementId(root) IN $nodeIds\nMATCH path = ${pattern}\nWHERE all(rel IN relationships(path) WHERE type(rel) IN $relationshipTypes)\n AND any(type IN labels(node) WHERE type IN $nodeTypes)\nRETURN elementId(node) AS id, labels(node) AS labels, properties(node) AS properties\nLIMIT $nodeLimit`,\n {\n nodeIds: options.nodeIds,\n nodeTypes: options.nodeTypes,\n relationshipTypes: options.relationships,\n nodeLimit: int(remainingNodeLimit),\n },\n options.abortSignal,\n );\n return [...roots.records, ...neighbors.records];\n}\n\nasync function relationshipsBetween(\n graph: Neo4jKnowledgeGraphBase,\n nodeIds: readonly string[],\n relationshipTypes: readonly string[],\n maxRelationships: number,\n abortSignal?: AbortSignal,\n): Promise<GraphExploreRelationship[]> {\n if (nodeIds.length === 0 || relationshipTypes.length === 0) return [];\n const result = await graph.query(\n `MATCH (from)-[relationship]->(to)\nWHERE elementId(from) IN $nodeIds\n AND elementId(to) IN $nodeIds\n AND type(relationship) IN $relationshipTypes\nRETURN elementId(relationship) AS id,\n type(relationship) AS type,\n elementId(from) AS source,\n elementId(to) AS target,\n properties(relationship) AS properties\nORDER BY elementId(relationship)\nLIMIT $relationshipLimit`,\n {\n nodeIds,\n relationshipTypes,\n relationshipLimit: int(maxRelationships + 1),\n },\n abortSignal,\n );\n return result.records.map(relationshipFromRecord);\n}\n\nfunction nodeFromRecord(record: Neo4jRecord, schema: Neo4jGraphSchema): GraphExploreNode {\n const id = stringValue(record.get(\"id\"), \"Neo4j explorer node id\");\n const labels = stringArray(record.get(\"labels\"), \"Neo4j explorer node labels\");\n const raw = objectValue(record.get(\"properties\"), \"Neo4j explorer node properties\");\n const type = labels.find((label) => label in schema.nodes);\n if (type === undefined) throw new TypeError(\"Neo4j explorer node has no registered type.\");\n const properties = applicationProperties(raw, \"Neo4j explorer node properties\");\n const node: {\n id: string;\n key?: string | undefined;\n type: string;\n identity: Neo4jNodeIdentity;\n properties: typeof properties;\n } = {\n id,\n type,\n identity: identityProperties(schema, type, properties),\n properties,\n };\n const key = raw.__anvia_key;\n if (typeof key === \"string\") node.key = key;\n return node;\n}\n\nfunction relationshipFromRecord(record: Neo4jRecord): GraphExploreRelationship {\n const raw = objectValue(record.get(\"properties\"), \"Neo4j explorer relationship properties\");\n const relationship: {\n id: string;\n key?: string | undefined;\n type: string;\n from: string;\n to: string;\n properties: ReturnType<typeof applicationProperties>;\n } = {\n id: stringValue(record.get(\"id\"), \"Neo4j explorer relationship id\"),\n type: stringValue(record.get(\"type\"), \"Neo4j explorer relationship type\"),\n from: stringValue(record.get(\"source\"), \"Neo4j explorer relationship source\"),\n to: stringValue(record.get(\"target\"), \"Neo4j explorer relationship target\"),\n properties: applicationProperties(raw, \"Neo4j explorer relationship properties\"),\n };\n const key = raw.__anvia_key;\n if (typeof key === \"string\") relationship.key = key;\n return relationship;\n}\n\nfunction identityProperties(\n schema: Neo4jGraphSchema,\n type: string,\n properties: ReturnType<typeof applicationProperties>,\n): Neo4jNodeIdentity {\n const identity: Record<string, string | number | boolean> = {};\n const definition = schema.nodes[type];\n if (definition === undefined) return identity;\n for (const property of definition.identity) {\n const value = properties[property];\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n identity[property] = value;\n }\n }\n return identity;\n}\n\nfunction applicationProperties(value: Record<string, unknown>, label: string) {\n return parseNeo4jProperties(\n Object.fromEntries(Object.entries(value).filter(([key]) => !key.startsWith(\"__anvia_\"))),\n label,\n );\n}\n\nfunction uniqueNodes(nodes: readonly GraphExploreNode[]): GraphExploreNode[] {\n return [...new Map(nodes.map((node) => [node.id, node])).values()];\n}\n\nfunction traversalPattern(direction: \"outgoing\" | \"incoming\" | \"both\", maxDepth: number): string {\n if (direction === \"outgoing\") return `(root)-[*1..${maxDepth}]->(node)`;\n if (direction === \"incoming\") return `(root)<-[*1..${maxDepth}]-(node)`;\n return `(root)-[*1..${maxDepth}]-(node)`;\n}\n\nfunction stringValue(value: unknown, label: string): string {\n if (typeof value !== \"string\") throw new TypeError(`${label} must be a string.`);\n return value;\n}\n\nfunction stringArray(value: unknown, label: string): string[] {\n if (!Array.isArray(value) || !value.every((item) => typeof item === \"string\")) {\n throw new TypeError(`${label} must be a string array.`);\n }\n return value;\n}\n\nfunction objectValue(value: unknown, label: string): Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new TypeError(`${label} must be an object.`);\n }\n return value as Record<string, unknown>;\n}\n"],"mappings":"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","names":[]}