@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.
@@ -0,0 +1,473 @@
1
+ import {
2
+ ManagedNeo4jKnowledgeGraph,
3
+ Neo4jKnowledgeGraphBase,
4
+ finiteScore,
5
+ positiveInteger,
6
+ quoteIdentifier,
7
+ strictProperties,
8
+ throwIfAborted
9
+ } from "./chunk-QNHOT7P2.js";
10
+
11
+ // src/retrieve.ts
12
+ import { embedText } from "@anvia/core/embeddings";
13
+ import { int, isInt } from "neo4j-driver";
14
+ async function retrieveGraphContext(options) {
15
+ if (!(options.graph instanceof Neo4jKnowledgeGraphBase)) {
16
+ throw new TypeError("retrieveGraphContext requires a Neo4j knowledge graph registration.");
17
+ }
18
+ if (typeof options.query !== "string" || options.query.trim().length === 0) {
19
+ throw new TypeError("Graph retrieval query must be a non-empty string.");
20
+ }
21
+ validateSearch(options.search);
22
+ validateTraversal(options.graph.schema, options.traversal);
23
+ validateEvidence(options.graph.evidenceCapability, options.evidence);
24
+ throwIfAborted(options.abortSignal);
25
+ const graph = options.graph;
26
+ const selectedSeeds = options.search.seeds.map((name) => ({ name, seed: graph.seed(name) }));
27
+ const expectedDimensions = selectedSeeds[0]?.seed.vectorIndex.dimensions;
28
+ if (expectedDimensions === void 0 || selectedSeeds.some((item) => item.seed.vectorIndex.dimensions !== expectedDimensions)) {
29
+ throw new TypeError("Selected Neo4j graph seeds must use the same vector dimensions.");
30
+ }
31
+ if (options.model.dimensions !== void 0 && options.model.dimensions !== expectedDimensions) {
32
+ throw new TypeError(
33
+ `Embedding model dimensions ${options.model.dimensions} do not match Neo4j graph dimensions ${expectedDimensions}.`
34
+ );
35
+ }
36
+ if (options.search.type === "hybrid") {
37
+ for (const { name, seed } of selectedSeeds) {
38
+ if (seed.fulltextIndex === void 0) {
39
+ throw new TypeError(`Neo4j graph seed ${name} does not declare a full-text index.`);
40
+ }
41
+ }
42
+ }
43
+ const { embedding } = await embedText({
44
+ model: options.model,
45
+ text: options.query,
46
+ retries: options.retries,
47
+ abortSignal: options.abortSignal
48
+ });
49
+ if (embedding.vector.length !== expectedDimensions) {
50
+ throw new TypeError(
51
+ `Query embedding dimensions ${embedding.vector.length} do not match Neo4j graph dimensions ${expectedDimensions}.`
52
+ );
53
+ }
54
+ const resultLists = [];
55
+ for (const { seed } of selectedSeeds) {
56
+ const limit = options.search.type === "hybrid" ? options.search.candidatesPerSeed : options.search.topK;
57
+ resultLists.push(
58
+ await vectorSearch(
59
+ graph,
60
+ seed.labels,
61
+ seed.vectorIndex.name,
62
+ embedding.vector,
63
+ limit,
64
+ seed.entryRelationshipType,
65
+ options.abortSignal
66
+ )
67
+ );
68
+ if (options.search.type === "hybrid") {
69
+ const fulltextIndex = seed.fulltextIndex;
70
+ if (fulltextIndex === void 0) {
71
+ throw new TypeError("Hybrid Neo4j graph retrieval requires a full-text index.");
72
+ }
73
+ resultLists.push(
74
+ await fulltextSearch(
75
+ graph,
76
+ fulltextIndex.name,
77
+ options.query,
78
+ limit,
79
+ seed.entryRelationshipType,
80
+ options.abortSignal
81
+ )
82
+ );
83
+ }
84
+ }
85
+ const hits = options.search.type === "hybrid" ? fuseResults(resultLists, options.search.topK, options.search.rrfK) : vectorResults(resultLists[0] ?? [], options.search.topK, options.search.minScore);
86
+ throwIfAborted(options.abortSignal);
87
+ const seeds = hits.map((hit) => seedFromHit(hit, options.graph.schema));
88
+ const traversed = hits.length === 0 ? { nodes: [], relationships: [] } : await traverse(graph, hits, options.traversal, options.abortSignal);
89
+ const context = { seeds, ...traversed };
90
+ const evidence = await hydrateEvidence(graph, context, options.evidence, options.abortSignal);
91
+ return { ...context, evidence };
92
+ }
93
+ async function vectorSearch(graph, labels, indexName, vector, limit, entryRelationshipType, abortSignal) {
94
+ const labelExpression = labels.map(quoteIdentifier).join("|");
95
+ const result = await graph.query(
96
+ `CYPHER 25
97
+ MATCH (seed:${labelExpression})
98
+ SEARCH seed IN (VECTOR INDEX ${quoteIdentifier(indexName)} FOR $vector LIMIT $limit) SCORE AS score
99
+ RETURN elementId(seed) AS elementId, labels(seed) AS labels, properties(seed) AS properties, score`,
100
+ { vector, limit: int(limit) },
101
+ abortSignal
102
+ );
103
+ return result.records.map((record) => ({ ...parseSearchHit(record), entryRelationshipType }));
104
+ }
105
+ async function fulltextSearch(graph, indexName, query, limit, entryRelationshipType, abortSignal) {
106
+ const result = await graph.query(
107
+ `CALL db.index.fulltext.queryNodes($indexName, $query, {limit: $limit}) YIELD node AS seed, score
108
+ RETURN elementId(seed) AS elementId, labels(seed) AS labels, properties(seed) AS properties, score`,
109
+ { indexName, query: escapeLucene(query), limit: int(limit) },
110
+ abortSignal
111
+ );
112
+ return result.records.map((record) => ({ ...parseSearchHit(record), entryRelationshipType }));
113
+ }
114
+ function parseSearchHit(record) {
115
+ const elementId = record.get("elementId");
116
+ const labels = record.get("labels");
117
+ const properties = record.get("properties");
118
+ const score = record.get("score");
119
+ if (typeof elementId !== "string" || !Array.isArray(labels) || !labels.every((label) => typeof label === "string") || typeof properties !== "object" || properties === null || typeof score !== "number" || !Number.isFinite(score)) {
120
+ throw new TypeError("Neo4j search returned a malformed result.");
121
+ }
122
+ return { elementId, labels, properties, score };
123
+ }
124
+ function seedFromHit(hit, schema) {
125
+ const application = applicationProperties(hit.properties, "Neo4j search seed");
126
+ const key = stringProperty(hit.properties, "__anvia_key") ?? stringProperty(hit.properties, "__anvia_id") ?? hit.elementId;
127
+ const type = hit.labels.find((label) => label in schema.nodes) ?? hit.labels[0] ?? "Node";
128
+ return {
129
+ key,
130
+ type,
131
+ score: hit.score,
132
+ properties: application,
133
+ sourceChunkIds: hit.entryRelationshipType === "ANVIA_MENTIONS" ? [key] : stringArrayProperty(hit.properties, "__anvia_source_chunk_ids")
134
+ };
135
+ }
136
+ async function hydrateEvidence(graph, context, options, abortSignal) {
137
+ if (options.type === "none") return [];
138
+ if (!(graph instanceof ManagedNeo4jKnowledgeGraph)) {
139
+ throw new TypeError("Chunk evidence requires a managed Neo4j knowledge graph.");
140
+ }
141
+ const chunkIds = [];
142
+ const seen = /* @__PURE__ */ new Set();
143
+ for (const sourceChunkIds of [
144
+ ...context.seeds.map((seed) => seed.sourceChunkIds),
145
+ ...context.nodes.map((node) => node.sourceChunkIds),
146
+ ...context.relationships.map((relationship) => relationship.sourceChunkIds)
147
+ ]) {
148
+ for (const chunkId of sourceChunkIds) {
149
+ if (seen.has(chunkId)) continue;
150
+ seen.add(chunkId);
151
+ chunkIds.push(chunkId);
152
+ if (chunkIds.length === options.maxChunks) break;
153
+ }
154
+ if (chunkIds.length === options.maxChunks) break;
155
+ }
156
+ if (chunkIds.length === 0) return [];
157
+ throwIfAborted(abortSignal);
158
+ const result = await graph.query(
159
+ `MATCH (d:${quoteIdentifier(graph.resources.labels.document)})-[:${quoteIdentifier("ANVIA_HAS_CHUNK")}]->(c:${quoteIdentifier(graph.resources.labels.chunk)})
160
+ WHERE c.${quoteIdentifier("__anvia_id")} IN $chunkIds
161
+ RETURN c.${quoteIdentifier("__anvia_id")} AS chunkId,
162
+ d.${quoteIdentifier("__anvia_id")} AS documentId,
163
+ c.${quoteIdentifier("__anvia_index")} AS index,
164
+ c.${quoteIdentifier("__anvia_text")} AS text,
165
+ properties(c) AS properties`,
166
+ { chunkIds },
167
+ abortSignal
168
+ );
169
+ const byId = /* @__PURE__ */ new Map();
170
+ for (const record of result.records) {
171
+ const evidence = evidenceFromRecord(record);
172
+ if (byId.has(evidence.chunkId)) {
173
+ throw new TypeError(`Neo4j evidence returned duplicate chunk ${evidence.chunkId}.`);
174
+ }
175
+ byId.set(evidence.chunkId, evidence);
176
+ }
177
+ return chunkIds.map((chunkId) => {
178
+ const evidence = byId.get(chunkId);
179
+ if (evidence === void 0) {
180
+ throw new Error(`Neo4j graph evidence references missing chunk ${chunkId}.`);
181
+ }
182
+ return evidence;
183
+ });
184
+ }
185
+ function evidenceFromRecord(record) {
186
+ const chunkId = stringValue(record.get("chunkId"), "Neo4j evidence chunk id");
187
+ const documentId = stringValue(record.get("documentId"), "Neo4j evidence document id");
188
+ const index = safeIntegerValue(record.get("index"), "Neo4j evidence chunk index");
189
+ const text = stringValue(record.get("text"), "Neo4j evidence text");
190
+ const raw = record.get("properties");
191
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
192
+ throw new TypeError("Neo4j evidence properties must be an object.");
193
+ }
194
+ return {
195
+ chunkId,
196
+ documentId,
197
+ index,
198
+ text,
199
+ metadata: applicationProperties(raw, "Neo4j evidence metadata")
200
+ };
201
+ }
202
+ function safeIntegerValue(value, label) {
203
+ let number = value;
204
+ if (isInt(value)) {
205
+ number = void 0;
206
+ if (value.inSafeRange()) {
207
+ number = value.toNumber();
208
+ }
209
+ }
210
+ if (typeof number !== "number" || !Number.isSafeInteger(number)) {
211
+ throw new TypeError(`${label} must be a safe integer.`);
212
+ }
213
+ return number;
214
+ }
215
+ function vectorResults(results, topK, minScore) {
216
+ return results.filter((item) => minScore === void 0 || item.score >= minScore).slice(0, topK);
217
+ }
218
+ async function traverse(graph, seeds, options, abortSignal) {
219
+ const traversalSeedIds = new Set(
220
+ seeds.filter((seed) => seed.entryRelationshipType === void 0).map((seed) => seed.elementId)
221
+ );
222
+ const entryGroups = groupBy(
223
+ seeds.filter(
224
+ (seed) => seed.entryRelationshipType !== void 0
225
+ ),
226
+ (seed) => seed.entryRelationshipType
227
+ );
228
+ for (const [relationshipType, group] of entryGroups) {
229
+ const entries = await graph.query(
230
+ `MATCH (seed) WHERE elementId(seed) IN $seedIds
231
+ MATCH (seed)-[:${quoteIdentifier(relationshipType)}]->(entry)
232
+ RETURN DISTINCT elementId(entry) AS elementId`,
233
+ { seedIds: group.map((seed) => seed.elementId) },
234
+ abortSignal
235
+ );
236
+ for (const record of entries.records) {
237
+ traversalSeedIds.add(stringValue(record.get("elementId"), "Neo4j entry elementId"));
238
+ }
239
+ }
240
+ if (traversalSeedIds.size === 0) return { nodes: [], relationships: [] };
241
+ const limitedSeedIds = [...traversalSeedIds].slice(0, options.maxNodes);
242
+ const pattern = traversalPattern(options.direction, options.maxDepth);
243
+ const pathLimit = Math.max(options.maxNodes, options.maxRelationships);
244
+ const seedNodes = await graph.query(
245
+ `MATCH (node) WHERE elementId(node) IN $seedIds
246
+ RETURN {elementId: elementId(node), labels: labels(node), properties: properties(node)} AS node`,
247
+ { seedIds: limitedSeedIds },
248
+ abortSignal
249
+ );
250
+ const result = await graph.query(
251
+ `MATCH (seed) WHERE elementId(seed) IN $seedIds
252
+ MATCH path = ${pattern}
253
+ WHERE all(rel IN relationships(path) WHERE type(rel) IN $relationshipTypes)
254
+ RETURN [item IN nodes(path) | {elementId: elementId(item), labels: labels(item), properties: properties(item)}] AS nodes,
255
+ [item IN relationships(path) | {elementId: elementId(item), type: type(item), properties: properties(item), from: elementId(startNode(item)), to: elementId(endNode(item))}] AS relationships
256
+ LIMIT $pathLimit`,
257
+ {
258
+ seedIds: limitedSeedIds,
259
+ relationshipTypes: options.relationships,
260
+ pathLimit: int(pathLimit)
261
+ },
262
+ abortSignal
263
+ );
264
+ const nodes = /* @__PURE__ */ new Map();
265
+ const nodeKeysByElementId = /* @__PURE__ */ new Map();
266
+ const relationships = /* @__PURE__ */ new Map();
267
+ const seedNodesByElementId = /* @__PURE__ */ new Map();
268
+ for (const record of seedNodes.records) {
269
+ const value = record.get("node");
270
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
271
+ throw new TypeError("Neo4j traversal returned a malformed seed node.");
272
+ }
273
+ const map = value;
274
+ seedNodesByElementId.set(stringValue(map.elementId, "Neo4j seed node elementId"), map);
275
+ }
276
+ const addNode = (value) => {
277
+ const parsed = contextNode(value, graph.schema);
278
+ const existing = nodes.get(parsed.node.key);
279
+ if (existing === void 0 && nodes.size >= options.maxNodes) return;
280
+ if (existing === void 0) nodes.set(parsed.node.key, parsed.node);
281
+ nodeKeysByElementId.set(parsed.elementId, parsed.node.key);
282
+ };
283
+ for (const elementId of limitedSeedIds) {
284
+ const value = seedNodesByElementId.get(elementId);
285
+ if (value !== void 0) addNode(value);
286
+ }
287
+ for (const record of result.records) {
288
+ for (const value of listOfMaps(record.get("nodes"), "Neo4j traversal nodes")) {
289
+ addNode(value);
290
+ }
291
+ }
292
+ for (const record of result.records) {
293
+ for (const value of listOfMaps(record.get("relationships"), "Neo4j traversal relationships")) {
294
+ const relationship = contextRelationship(value, nodeKeysByElementId);
295
+ if (relationship !== void 0 && !relationships.has(relationship.key) && relationships.size < options.maxRelationships) {
296
+ relationships.set(relationship.key, relationship);
297
+ }
298
+ }
299
+ }
300
+ return { nodes: [...nodes.values()], relationships: [...relationships.values()] };
301
+ }
302
+ function traversalPattern(direction, maxDepth) {
303
+ if (direction === "outgoing") {
304
+ return `(seed)-[*1..${maxDepth}]->(node)`;
305
+ }
306
+ if (direction === "incoming") {
307
+ return `(seed)<-[*1..${maxDepth}]-(node)`;
308
+ }
309
+ return `(seed)-[*1..${maxDepth}]-(node)`;
310
+ }
311
+ function contextNode(value, schema) {
312
+ const labels = value.labels;
313
+ const raw = value.properties;
314
+ if (!Array.isArray(labels) || !labels.every((label) => typeof label === "string")) {
315
+ throw new TypeError("Neo4j traversal returned malformed node labels.");
316
+ }
317
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
318
+ throw new TypeError("Neo4j traversal returned malformed node properties.");
319
+ }
320
+ const properties = applicationProperties(raw, "Neo4j graph node");
321
+ const type = labels.find((label) => label in schema.nodes) ?? labels[0] ?? "Node";
322
+ const definition = schema.nodes[type];
323
+ const identity = {};
324
+ if (definition !== void 0) {
325
+ for (const property of definition.identity) {
326
+ const item = properties[property];
327
+ if (typeof item === "string" || typeof item === "number" || typeof item === "boolean") {
328
+ identity[property] = item;
329
+ }
330
+ }
331
+ }
332
+ const elementId = stringValue(value.elementId, "Neo4j node elementId");
333
+ return {
334
+ elementId,
335
+ node: {
336
+ key: stringProperty(raw, "__anvia_key") ?? elementId,
337
+ type,
338
+ identity,
339
+ properties,
340
+ sourceChunkIds: stringArrayProperty(
341
+ raw,
342
+ "__anvia_source_chunk_ids"
343
+ )
344
+ }
345
+ };
346
+ }
347
+ function contextRelationship(value, nodeKeysByElementId) {
348
+ const raw = value.properties;
349
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
350
+ throw new TypeError("Neo4j traversal returned malformed relationship properties.");
351
+ }
352
+ const elementId = stringValue(value.elementId, "Neo4j relationship elementId");
353
+ const fromElementId = stringValue(value.from, "Neo4j relationship source");
354
+ const toElementId = stringValue(value.to, "Neo4j relationship target");
355
+ const from = nodeKeysByElementId.get(fromElementId);
356
+ const to = nodeKeysByElementId.get(toElementId);
357
+ if (from === void 0 || to === void 0) return void 0;
358
+ return {
359
+ key: stringProperty(raw, "__anvia_key") ?? elementId,
360
+ type: stringValue(value.type, "Neo4j relationship type"),
361
+ from,
362
+ to,
363
+ properties: applicationProperties(raw, "Neo4j graph relationship"),
364
+ sourceChunkIds: stringArrayProperty(raw, "__anvia_source_chunk_ids")
365
+ };
366
+ }
367
+ function fuseResults(lists, topK, rrfK) {
368
+ const fused = /* @__PURE__ */ new Map();
369
+ for (const list of lists) {
370
+ list.forEach((item, index) => {
371
+ const score = 1 / (rrfK + index + 1);
372
+ const current = fused.get(item.elementId);
373
+ fused.set(item.elementId, { ...item, score: (current?.score ?? 0) + score });
374
+ });
375
+ }
376
+ return [...fused.values()].sort((left, right) => right.score - left.score).slice(0, topK);
377
+ }
378
+ function validateSearch(search) {
379
+ positiveInteger(search.topK, "Neo4j graph search topK");
380
+ if (search.seeds.length === 0 || new Set(search.seeds).size !== search.seeds.length) {
381
+ throw new TypeError("Neo4j graph search requires unique seed names.");
382
+ }
383
+ if (search.type === "vector") {
384
+ if (search.seeds.length !== 1)
385
+ throw new TypeError(
386
+ "Vector graph search accepts exactly one seed; use hybrid search to fuse multiple seeds."
387
+ );
388
+ finiteScore(search.minScore, "Neo4j graph search minScore");
389
+ } else {
390
+ positiveInteger(search.candidatesPerSeed, "Neo4j hybrid candidatesPerSeed");
391
+ positiveInteger(search.rrfK, "Neo4j hybrid rrfK");
392
+ }
393
+ }
394
+ function validateEvidence(capability, evidence) {
395
+ if (typeof evidence !== "object" || evidence === null) {
396
+ throw new TypeError("Neo4j graph retrieval requires an explicit evidence mode.");
397
+ }
398
+ if (evidence.type === "none") return;
399
+ if (evidence.type !== "chunks") {
400
+ throw new TypeError("Unknown Neo4j graph evidence mode.");
401
+ }
402
+ positiveInteger(evidence.maxChunks, "Neo4j graph evidence maxChunks");
403
+ if (capability !== "chunks") {
404
+ throw new TypeError("Chunk evidence requires a managed Neo4j knowledge graph.");
405
+ }
406
+ }
407
+ function validateTraversal(schema, traversal) {
408
+ if (traversal.direction !== "outgoing" && traversal.direction !== "incoming" && traversal.direction !== "both") {
409
+ throw new TypeError("Neo4j traversal direction must be outgoing, incoming, or both.");
410
+ }
411
+ positiveInteger(traversal.maxDepth, "Neo4j traversal maxDepth", 8);
412
+ positiveInteger(traversal.maxNodes, "Neo4j traversal maxNodes");
413
+ positiveInteger(traversal.maxRelationships, "Neo4j traversal maxRelationships");
414
+ if (traversal.relationships.length === 0 || new Set(traversal.relationships).size !== traversal.relationships.length) {
415
+ throw new TypeError("Neo4j traversal requires unique relationship types.");
416
+ }
417
+ for (const type of traversal.relationships) {
418
+ if (!(type in schema.relationships))
419
+ throw new TypeError(`Neo4j traversal references unknown relationship type ${type}.`);
420
+ }
421
+ }
422
+ function applicationProperties(value, label) {
423
+ return strictProperties(
424
+ Object.fromEntries(Object.entries(value).filter(([key]) => !key.startsWith("__anvia_"))),
425
+ label
426
+ );
427
+ }
428
+ function stringProperty(value, property) {
429
+ const item = value[property];
430
+ if (item === void 0) return void 0;
431
+ return stringValue(item, `Neo4j property ${property}`);
432
+ }
433
+ function stringArrayProperty(value, property) {
434
+ const item = value[property];
435
+ if (item === void 0) return [];
436
+ if (!Array.isArray(item) || !item.every((entry) => typeof entry === "string")) {
437
+ throw new TypeError(`Neo4j property ${property} must be a string array.`);
438
+ }
439
+ return [...item];
440
+ }
441
+ function stringValue(value, label) {
442
+ if (typeof value !== "string") throw new TypeError(`${label} must be a string.`);
443
+ return value;
444
+ }
445
+ function listOfMaps(value, label) {
446
+ if (!Array.isArray(value) || !value.every((item) => typeof item === "object" && item !== null && !Array.isArray(item))) {
447
+ throw new TypeError(`${label} must be an array of objects.`);
448
+ }
449
+ return value;
450
+ }
451
+ function escapeLucene(value) {
452
+ const specialCharacters = new Set('+-&|!(){}[]^"~*?:\\/');
453
+ let escaped = "";
454
+ for (const character of value) {
455
+ escaped += specialCharacters.has(character) ? `\\${character}` : character;
456
+ }
457
+ return escaped;
458
+ }
459
+ function groupBy(values, keyFor) {
460
+ const groups = /* @__PURE__ */ new Map();
461
+ for (const value of values) {
462
+ const key = keyFor(value);
463
+ const group = groups.get(key);
464
+ if (group === void 0) groups.set(key, [value]);
465
+ else group.push(value);
466
+ }
467
+ return groups;
468
+ }
469
+
470
+ export {
471
+ retrieveGraphContext
472
+ };
473
+ //# sourceMappingURL=chunk-YLW4LCKJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/retrieve.ts"],"sourcesContent":["import { embedText } from \"@anvia/core/embeddings\";\nimport { int, isInt, type Record as Neo4jRecord } from \"neo4j-driver\";\nimport { ManagedNeo4jKnowledgeGraph, Neo4jKnowledgeGraphBase } from \"./graph.js\";\nimport {\n finiteScore,\n positiveInteger,\n quoteIdentifier,\n strictProperties,\n throwIfAborted,\n} from \"./helpers.js\";\nimport type {\n Neo4jGraphContext,\n Neo4jGraphContextNode,\n Neo4jGraphContextRelationship,\n Neo4jGraphContextSeed,\n Neo4jGraphEvidence,\n Neo4jGraphEvidenceOptions,\n Neo4jGraphSchema,\n RetrieveGraphContextOptions,\n} from \"./types.js\";\n\ntype SearchHit = {\n elementId: string;\n labels: string[];\n properties: Record<string, unknown>;\n score: number;\n entryRelationshipType?: string | undefined;\n};\n\nexport async function retrieveGraphContext<Schema extends Neo4jGraphSchema>(\n options: RetrieveGraphContextOptions<Schema>,\n): Promise<Neo4jGraphContext> {\n if (!(options.graph instanceof Neo4jKnowledgeGraphBase)) {\n throw new TypeError(\"retrieveGraphContext requires a Neo4j knowledge graph registration.\");\n }\n if (typeof options.query !== \"string\" || options.query.trim().length === 0) {\n throw new TypeError(\"Graph retrieval query must be a non-empty string.\");\n }\n validateSearch(options.search);\n validateTraversal(options.graph.schema, options.traversal);\n validateEvidence(options.graph.evidenceCapability, options.evidence);\n throwIfAborted(options.abortSignal);\n const graph = options.graph as Neo4jKnowledgeGraphBase<Schema>;\n const selectedSeeds = options.search.seeds.map((name) => ({ name, seed: graph.seed(name) }));\n const expectedDimensions = selectedSeeds[0]?.seed.vectorIndex.dimensions;\n if (\n expectedDimensions === undefined ||\n selectedSeeds.some((item) => item.seed.vectorIndex.dimensions !== expectedDimensions)\n ) {\n throw new TypeError(\"Selected Neo4j graph seeds must use the same vector dimensions.\");\n }\n if (options.model.dimensions !== undefined && options.model.dimensions !== expectedDimensions) {\n throw new TypeError(\n `Embedding model dimensions ${options.model.dimensions} do not match Neo4j graph dimensions ${expectedDimensions}.`,\n );\n }\n if (options.search.type === \"hybrid\") {\n for (const { name, seed } of selectedSeeds) {\n if (seed.fulltextIndex === undefined) {\n throw new TypeError(`Neo4j graph seed ${name} does not declare a full-text index.`);\n }\n }\n }\n const { embedding } = await embedText({\n model: options.model,\n text: options.query,\n retries: options.retries,\n abortSignal: options.abortSignal,\n });\n if (embedding.vector.length !== expectedDimensions) {\n throw new TypeError(\n `Query embedding dimensions ${embedding.vector.length} do not match Neo4j graph dimensions ${expectedDimensions}.`,\n );\n }\n\n const resultLists: SearchHit[][] = [];\n for (const { seed } of selectedSeeds) {\n const limit =\n options.search.type === \"hybrid\" ? options.search.candidatesPerSeed : options.search.topK;\n resultLists.push(\n await vectorSearch(\n graph,\n seed.labels,\n seed.vectorIndex.name,\n embedding.vector,\n limit,\n seed.entryRelationshipType,\n options.abortSignal,\n ),\n );\n if (options.search.type === \"hybrid\") {\n const fulltextIndex = seed.fulltextIndex;\n if (fulltextIndex === undefined) {\n throw new TypeError(\"Hybrid Neo4j graph retrieval requires a full-text index.\");\n }\n resultLists.push(\n await fulltextSearch(\n graph,\n fulltextIndex.name,\n options.query,\n limit,\n seed.entryRelationshipType,\n options.abortSignal,\n ),\n );\n }\n }\n\n const hits =\n options.search.type === \"hybrid\"\n ? fuseResults(resultLists, options.search.topK, options.search.rrfK)\n : vectorResults(resultLists[0] ?? [], options.search.topK, options.search.minScore);\n throwIfAborted(options.abortSignal);\n const seeds = hits.map((hit) => seedFromHit(hit, options.graph.schema));\n const traversed =\n hits.length === 0\n ? { nodes: [], relationships: [] }\n : await traverse(graph, hits, options.traversal, options.abortSignal);\n const context = { seeds, ...traversed };\n const evidence = await hydrateEvidence(graph, context, options.evidence, options.abortSignal);\n return { ...context, evidence };\n}\n\nasync function vectorSearch(\n graph: Neo4jKnowledgeGraphBase,\n labels: readonly string[],\n indexName: string,\n vector: readonly number[],\n limit: number,\n entryRelationshipType?: string,\n abortSignal?: AbortSignal,\n): Promise<SearchHit[]> {\n const labelExpression = labels.map(quoteIdentifier).join(\"|\");\n const result = await graph.query(\n `CYPHER 25\nMATCH (seed:${labelExpression})\nSEARCH seed IN (VECTOR INDEX ${quoteIdentifier(indexName)} FOR $vector LIMIT $limit) SCORE AS score\nRETURN elementId(seed) AS elementId, labels(seed) AS labels, properties(seed) AS properties, score`,\n { vector, limit: int(limit) },\n abortSignal,\n );\n return result.records.map((record) => ({ ...parseSearchHit(record), entryRelationshipType }));\n}\n\nasync function fulltextSearch(\n graph: Neo4jKnowledgeGraphBase,\n indexName: string,\n query: string,\n limit: number,\n entryRelationshipType?: string,\n abortSignal?: AbortSignal,\n): Promise<SearchHit[]> {\n const result = await graph.query(\n `CALL db.index.fulltext.queryNodes($indexName, $query, {limit: $limit}) YIELD node AS seed, score\nRETURN elementId(seed) AS elementId, labels(seed) AS labels, properties(seed) AS properties, score`,\n { indexName, query: escapeLucene(query), limit: int(limit) },\n abortSignal,\n );\n return result.records.map((record) => ({ ...parseSearchHit(record), entryRelationshipType }));\n}\n\nfunction parseSearchHit(record: Neo4jRecord): SearchHit {\n const elementId = record.get(\"elementId\");\n const labels = record.get(\"labels\");\n const properties = record.get(\"properties\");\n const score = record.get(\"score\");\n if (\n typeof elementId !== \"string\" ||\n !Array.isArray(labels) ||\n !labels.every((label) => typeof label === \"string\") ||\n typeof properties !== \"object\" ||\n properties === null ||\n typeof score !== \"number\" ||\n !Number.isFinite(score)\n ) {\n throw new TypeError(\"Neo4j search returned a malformed result.\");\n }\n return { elementId, labels, properties: properties as Record<string, unknown>, score };\n}\n\nfunction seedFromHit(hit: SearchHit, schema: Neo4jGraphSchema): Neo4jGraphContextSeed {\n const application = applicationProperties(hit.properties, \"Neo4j search seed\");\n const key =\n stringProperty(hit.properties, \"__anvia_key\") ??\n stringProperty(hit.properties, \"__anvia_id\") ??\n hit.elementId;\n const type = hit.labels.find((label) => label in schema.nodes) ?? hit.labels[0] ?? \"Node\";\n return {\n key,\n type,\n score: hit.score,\n properties: application,\n sourceChunkIds:\n hit.entryRelationshipType === \"ANVIA_MENTIONS\"\n ? [key]\n : stringArrayProperty(hit.properties, \"__anvia_source_chunk_ids\"),\n };\n}\n\nasync function hydrateEvidence(\n graph: Neo4jKnowledgeGraphBase,\n context: Pick<Neo4jGraphContext, \"seeds\" | \"nodes\" | \"relationships\">,\n options: Neo4jGraphEvidenceOptions,\n abortSignal?: AbortSignal,\n): Promise<Neo4jGraphEvidence[]> {\n if (options.type === \"none\") return [];\n if (!(graph instanceof ManagedNeo4jKnowledgeGraph)) {\n throw new TypeError(\"Chunk evidence requires a managed Neo4j knowledge graph.\");\n }\n const chunkIds: string[] = [];\n const seen = new Set<string>();\n for (const sourceChunkIds of [\n ...context.seeds.map((seed) => seed.sourceChunkIds),\n ...context.nodes.map((node) => node.sourceChunkIds),\n ...context.relationships.map((relationship) => relationship.sourceChunkIds),\n ]) {\n for (const chunkId of sourceChunkIds) {\n if (seen.has(chunkId)) continue;\n seen.add(chunkId);\n chunkIds.push(chunkId);\n if (chunkIds.length === options.maxChunks) break;\n }\n if (chunkIds.length === options.maxChunks) break;\n }\n if (chunkIds.length === 0) return [];\n throwIfAborted(abortSignal);\n const result = await graph.query(\n `MATCH (d:${quoteIdentifier(graph.resources.labels.document)})-[:${quoteIdentifier(\"ANVIA_HAS_CHUNK\")}]->(c:${quoteIdentifier(graph.resources.labels.chunk)})\nWHERE c.${quoteIdentifier(\"__anvia_id\")} IN $chunkIds\nRETURN c.${quoteIdentifier(\"__anvia_id\")} AS chunkId,\n d.${quoteIdentifier(\"__anvia_id\")} AS documentId,\n c.${quoteIdentifier(\"__anvia_index\")} AS index,\n c.${quoteIdentifier(\"__anvia_text\")} AS text,\n properties(c) AS properties`,\n { chunkIds },\n abortSignal,\n );\n const byId = new Map<string, Neo4jGraphEvidence>();\n for (const record of result.records) {\n const evidence = evidenceFromRecord(record);\n if (byId.has(evidence.chunkId)) {\n throw new TypeError(`Neo4j evidence returned duplicate chunk ${evidence.chunkId}.`);\n }\n byId.set(evidence.chunkId, evidence);\n }\n return chunkIds.map((chunkId) => {\n const evidence = byId.get(chunkId);\n if (evidence === undefined) {\n throw new Error(`Neo4j graph evidence references missing chunk ${chunkId}.`);\n }\n return evidence;\n });\n}\n\nfunction evidenceFromRecord(record: Neo4jRecord): Neo4jGraphEvidence {\n const chunkId = stringValue(record.get(\"chunkId\"), \"Neo4j evidence chunk id\");\n const documentId = stringValue(record.get(\"documentId\"), \"Neo4j evidence document id\");\n const index = safeIntegerValue(record.get(\"index\"), \"Neo4j evidence chunk index\");\n const text = stringValue(record.get(\"text\"), \"Neo4j evidence text\");\n const raw = record.get(\"properties\");\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n throw new TypeError(\"Neo4j evidence properties must be an object.\");\n }\n return {\n chunkId,\n documentId,\n index,\n text,\n metadata: applicationProperties(raw as Record<string, unknown>, \"Neo4j evidence metadata\"),\n };\n}\n\nfunction safeIntegerValue(value: unknown, label: string): number {\n let number = value;\n if (isInt(value)) {\n number = undefined;\n if (value.inSafeRange()) {\n number = value.toNumber();\n }\n }\n if (typeof number !== \"number\" || !Number.isSafeInteger(number)) {\n throw new TypeError(`${label} must be a safe integer.`);\n }\n return number;\n}\n\nfunction vectorResults(\n results: SearchHit[],\n topK: number,\n minScore: number | undefined,\n): SearchHit[] {\n return results.filter((item) => minScore === undefined || item.score >= minScore).slice(0, topK);\n}\n\nasync function traverse<Schema extends Neo4jGraphSchema>(\n graph: Neo4jKnowledgeGraphBase<Schema>,\n seeds: readonly SearchHit[],\n options: RetrieveGraphContextOptions<Schema>[\"traversal\"],\n abortSignal?: AbortSignal,\n): Promise<{ nodes: Neo4jGraphContextNode[]; relationships: Neo4jGraphContextRelationship[] }> {\n const traversalSeedIds = new Set(\n seeds.filter((seed) => seed.entryRelationshipType === undefined).map((seed) => seed.elementId),\n );\n const entryGroups = groupBy(\n seeds.filter(\n (seed): seed is SearchHit & { entryRelationshipType: string } =>\n seed.entryRelationshipType !== undefined,\n ),\n (seed) => seed.entryRelationshipType,\n );\n for (const [relationshipType, group] of entryGroups) {\n const entries = await graph.query(\n `MATCH (seed) WHERE elementId(seed) IN $seedIds\nMATCH (seed)-[:${quoteIdentifier(relationshipType)}]->(entry)\nRETURN DISTINCT elementId(entry) AS elementId`,\n { seedIds: group.map((seed) => seed.elementId) },\n abortSignal,\n );\n for (const record of entries.records) {\n traversalSeedIds.add(stringValue(record.get(\"elementId\"), \"Neo4j entry elementId\"));\n }\n }\n if (traversalSeedIds.size === 0) return { nodes: [], relationships: [] };\n const limitedSeedIds = [...traversalSeedIds].slice(0, options.maxNodes);\n const pattern = traversalPattern(options.direction, options.maxDepth);\n const pathLimit = Math.max(options.maxNodes, options.maxRelationships);\n const seedNodes = await graph.query(\n `MATCH (node) WHERE elementId(node) IN $seedIds\nRETURN {elementId: elementId(node), labels: labels(node), properties: properties(node)} AS node`,\n { seedIds: limitedSeedIds },\n abortSignal,\n );\n const result = await graph.query(\n `MATCH (seed) WHERE elementId(seed) IN $seedIds\nMATCH path = ${pattern}\nWHERE all(rel IN relationships(path) WHERE type(rel) IN $relationshipTypes)\nRETURN [item IN nodes(path) | {elementId: elementId(item), labels: labels(item), properties: properties(item)}] AS nodes,\n [item IN relationships(path) | {elementId: elementId(item), type: type(item), properties: properties(item), from: elementId(startNode(item)), to: elementId(endNode(item))}] AS relationships\nLIMIT $pathLimit`,\n {\n seedIds: limitedSeedIds,\n relationshipTypes: options.relationships,\n pathLimit: int(pathLimit),\n },\n abortSignal,\n );\n const nodes = new Map<string, Neo4jGraphContextNode>();\n const nodeKeysByElementId = new Map<string, string>();\n const relationships = new Map<string, Neo4jGraphContextRelationship>();\n const seedNodesByElementId = new Map<string, Record<string, unknown>>();\n for (const record of seedNodes.records) {\n const value = record.get(\"node\");\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new TypeError(\"Neo4j traversal returned a malformed seed node.\");\n }\n const map = value as Record<string, unknown>;\n seedNodesByElementId.set(stringValue(map.elementId, \"Neo4j seed node elementId\"), map);\n }\n const addNode = (value: Record<string, unknown>) => {\n const parsed = contextNode(value, graph.schema);\n const existing = nodes.get(parsed.node.key);\n if (existing === undefined && nodes.size >= options.maxNodes) return;\n if (existing === undefined) nodes.set(parsed.node.key, parsed.node);\n nodeKeysByElementId.set(parsed.elementId, parsed.node.key);\n };\n for (const elementId of limitedSeedIds) {\n const value = seedNodesByElementId.get(elementId);\n if (value !== undefined) addNode(value);\n }\n for (const record of result.records) {\n for (const value of listOfMaps(record.get(\"nodes\"), \"Neo4j traversal nodes\")) {\n addNode(value);\n }\n }\n for (const record of result.records) {\n for (const value of listOfMaps(record.get(\"relationships\"), \"Neo4j traversal relationships\")) {\n const relationship = contextRelationship(value, nodeKeysByElementId);\n if (\n relationship !== undefined &&\n !relationships.has(relationship.key) &&\n relationships.size < options.maxRelationships\n ) {\n relationships.set(relationship.key, relationship);\n }\n }\n }\n return { nodes: [...nodes.values()], relationships: [...relationships.values()] };\n}\n\nfunction traversalPattern(direction: \"outgoing\" | \"incoming\" | \"both\", maxDepth: number): string {\n if (direction === \"outgoing\") {\n return `(seed)-[*1..${maxDepth}]->(node)`;\n }\n if (direction === \"incoming\") {\n return `(seed)<-[*1..${maxDepth}]-(node)`;\n }\n return `(seed)-[*1..${maxDepth}]-(node)`;\n}\n\nfunction contextNode(\n value: Record<string, unknown>,\n schema: Neo4jGraphSchema,\n): { elementId: string; node: Neo4jGraphContextNode } {\n const labels = value.labels;\n const raw = value.properties;\n if (!Array.isArray(labels) || !labels.every((label) => typeof label === \"string\")) {\n throw new TypeError(\"Neo4j traversal returned malformed node labels.\");\n }\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n throw new TypeError(\"Neo4j traversal returned malformed node properties.\");\n }\n const properties = applicationProperties(raw as Record<string, unknown>, \"Neo4j graph node\");\n const type = labels.find((label) => label in schema.nodes) ?? labels[0] ?? \"Node\";\n const definition = schema.nodes[type];\n const identity: Record<string, string | number | boolean> = {};\n if (definition !== undefined) {\n for (const property of definition.identity) {\n const item = properties[property];\n if (typeof item === \"string\" || typeof item === \"number\" || typeof item === \"boolean\") {\n identity[property] = item;\n }\n }\n }\n const elementId = stringValue(value.elementId, \"Neo4j node elementId\");\n return {\n elementId,\n node: {\n key: stringProperty(raw as Record<string, unknown>, \"__anvia_key\") ?? elementId,\n type,\n identity,\n properties,\n sourceChunkIds: stringArrayProperty(\n raw as Record<string, unknown>,\n \"__anvia_source_chunk_ids\",\n ),\n },\n };\n}\n\nfunction contextRelationship(\n value: Record<string, unknown>,\n nodeKeysByElementId: ReadonlyMap<string, string>,\n): Neo4jGraphContextRelationship | undefined {\n const raw = value.properties;\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) {\n throw new TypeError(\"Neo4j traversal returned malformed relationship properties.\");\n }\n const elementId = stringValue(value.elementId, \"Neo4j relationship elementId\");\n const fromElementId = stringValue(value.from, \"Neo4j relationship source\");\n const toElementId = stringValue(value.to, \"Neo4j relationship target\");\n const from = nodeKeysByElementId.get(fromElementId);\n const to = nodeKeysByElementId.get(toElementId);\n if (from === undefined || to === undefined) return undefined;\n return {\n key: stringProperty(raw as Record<string, unknown>, \"__anvia_key\") ?? elementId,\n type: stringValue(value.type, \"Neo4j relationship type\"),\n from,\n to,\n properties: applicationProperties(raw as Record<string, unknown>, \"Neo4j graph relationship\"),\n sourceChunkIds: stringArrayProperty(raw as Record<string, unknown>, \"__anvia_source_chunk_ids\"),\n };\n}\n\nfunction fuseResults(lists: readonly SearchHit[][], topK: number, rrfK: number): SearchHit[] {\n const fused = new Map<string, SearchHit>();\n for (const list of lists) {\n list.forEach((item, index) => {\n const score = 1 / (rrfK + index + 1);\n const current = fused.get(item.elementId);\n fused.set(item.elementId, { ...item, score: (current?.score ?? 0) + score });\n });\n }\n return [...fused.values()].sort((left, right) => right.score - left.score).slice(0, topK);\n}\n\nfunction validateSearch(search: RetrieveGraphContextOptions<Neo4jGraphSchema>[\"search\"]): void {\n positiveInteger(search.topK, \"Neo4j graph search topK\");\n if (search.seeds.length === 0 || new Set(search.seeds).size !== search.seeds.length) {\n throw new TypeError(\"Neo4j graph search requires unique seed names.\");\n }\n if (search.type === \"vector\") {\n if (search.seeds.length !== 1)\n throw new TypeError(\n \"Vector graph search accepts exactly one seed; use hybrid search to fuse multiple seeds.\",\n );\n finiteScore(search.minScore, \"Neo4j graph search minScore\");\n } else {\n positiveInteger(search.candidatesPerSeed, \"Neo4j hybrid candidatesPerSeed\");\n positiveInteger(search.rrfK, \"Neo4j hybrid rrfK\");\n }\n}\n\nfunction validateEvidence(\n capability: \"none\" | \"chunks\",\n evidence: Neo4jGraphEvidenceOptions,\n): void {\n if (typeof evidence !== \"object\" || evidence === null) {\n throw new TypeError(\"Neo4j graph retrieval requires an explicit evidence mode.\");\n }\n if (evidence.type === \"none\") return;\n if (evidence.type !== \"chunks\") {\n throw new TypeError(\"Unknown Neo4j graph evidence mode.\");\n }\n positiveInteger(evidence.maxChunks, \"Neo4j graph evidence maxChunks\");\n if (capability !== \"chunks\") {\n throw new TypeError(\"Chunk evidence requires a managed Neo4j knowledge graph.\");\n }\n}\n\nfunction validateTraversal(\n schema: Neo4jGraphSchema,\n traversal: RetrieveGraphContextOptions<Neo4jGraphSchema>[\"traversal\"],\n): void {\n if (\n traversal.direction !== \"outgoing\" &&\n traversal.direction !== \"incoming\" &&\n traversal.direction !== \"both\"\n ) {\n throw new TypeError(\"Neo4j traversal direction must be outgoing, incoming, or both.\");\n }\n positiveInteger(traversal.maxDepth, \"Neo4j traversal maxDepth\", 8);\n positiveInteger(traversal.maxNodes, \"Neo4j traversal maxNodes\");\n positiveInteger(traversal.maxRelationships, \"Neo4j traversal maxRelationships\");\n if (\n traversal.relationships.length === 0 ||\n new Set(traversal.relationships).size !== traversal.relationships.length\n ) {\n throw new TypeError(\"Neo4j traversal requires unique relationship types.\");\n }\n for (const type of traversal.relationships) {\n if (!(type in schema.relationships))\n throw new TypeError(`Neo4j traversal references unknown relationship type ${type}.`);\n }\n}\n\nfunction applicationProperties(value: Record<string, unknown>, label: string) {\n return strictProperties(\n Object.fromEntries(Object.entries(value).filter(([key]) => !key.startsWith(\"__anvia_\"))),\n label,\n );\n}\n\nfunction stringProperty(value: Record<string, unknown>, property: string): string | undefined {\n const item = value[property];\n if (item === undefined) return undefined;\n return stringValue(item, `Neo4j property ${property}`);\n}\n\nfunction stringArrayProperty(value: Record<string, unknown>, property: string): string[] {\n const item = value[property];\n if (item === undefined) return [];\n if (!Array.isArray(item) || !item.every((entry) => typeof entry === \"string\")) {\n throw new TypeError(`Neo4j property ${property} must be a string array.`);\n }\n return [...item];\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 listOfMaps(value: unknown, label: string): Record<string, unknown>[] {\n if (\n !Array.isArray(value) ||\n !value.every((item) => typeof item === \"object\" && item !== null && !Array.isArray(item))\n ) {\n throw new TypeError(`${label} must be an array of objects.`);\n }\n return value as Record<string, unknown>[];\n}\n\nfunction escapeLucene(value: string): string {\n const specialCharacters = new Set('+-&|!(){}[]^\"~*?:\\\\/');\n let escaped = \"\";\n for (const character of value) {\n escaped += specialCharacters.has(character) ? `\\\\${character}` : character;\n }\n return escaped;\n}\n\nfunction groupBy<Value, Key>(\n values: readonly Value[],\n keyFor: (value: Value) => Key,\n): Map<Key, Value[]> {\n const groups = new Map<Key, Value[]>();\n for (const value of values) {\n const key = keyFor(value);\n const group = groups.get(key);\n if (group === undefined) groups.set(key, [value]);\n else group.push(value);\n }\n return groups;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,8 @@
1
+ import {
2
+ exploreGraph
3
+ } from "./chunk-PWE3ETSF.js";
4
+ import "./chunk-QNHOT7P2.js";
5
+ export {
6
+ exploreGraph
7
+ };
8
+ //# sourceMappingURL=explore-RA53GFX2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { Driver, QueryResult, ManagedTransaction } from 'neo4j-driver';
2
+ import { GraphRetrieveOptions, GraphContext, GraphExploreOptions, GraphExploreResult } from '@anvia/graph';
3
+ export { GraphFactConflictError } from '@anvia/graph';
2
4
  import * as _anvia_core_embeddings from '@anvia/core/embeddings';
3
5
  import { EmbeddedDocument } from '@anvia/core/embeddings';
4
6
  import * as _anvia_core from '@anvia/core';
5
- import { RetrySetting, CompletionModel, Usage } from '@anvia/core';
6
- import { Tool } from '@anvia/core/tool';
7
+ import { CompletionModel, RetrySetting, Usage } from '@anvia/core';
7
8
  import { z } from 'zod';
8
9
 
9
10
  type Neo4jPropertyPrimitive = string | number | boolean;
@@ -27,7 +28,7 @@ type Neo4jGraphSchemaOptions = Readonly<{
27
28
  relationships: Readonly<Record<string, Neo4jRelationshipDefinition>>;
28
29
  }>;
29
30
  type Neo4jGraphSchema<Options extends Neo4jGraphSchemaOptions = Neo4jGraphSchemaOptions> = Readonly<Options & {
30
- kind: "neo4j-graph-schema";
31
+ kind: "neo4j-graph-schema" | "graph-schema";
31
32
  }>;
32
33
  type NodeDefinitions<Schema extends Neo4jGraphSchema> = Schema["nodes"];
33
34
  type RelationshipDefinitions<Schema extends Neo4jGraphSchema> = Schema["relationships"];
@@ -248,26 +249,6 @@ type RetrieveGraphContextOptions<Schema extends Neo4jGraphSchema> = (RetrieveGra
248
249
  maxChunks: number;
249
250
  }>;
250
251
  }>);
251
- type CreateNeo4jGraphSearchToolBase<Schema extends Neo4jGraphSchema> = Readonly<{
252
- name: string;
253
- description: string;
254
- model: _anvia_core_embeddings.EmbeddingModel;
255
- search: Neo4jGraphSearchOptions;
256
- traversal: Neo4jGraphTraversalOptions<Schema>;
257
- retries?: RetrySetting | undefined;
258
- }>;
259
- type CreateNeo4jGraphSearchToolOptions<Schema extends Neo4jGraphSchema> = (CreateNeo4jGraphSearchToolBase<Schema> & Readonly<{
260
- graph: AnyNeo4jKnowledgeGraph<Schema>;
261
- evidence: Readonly<{
262
- type: "none";
263
- }>;
264
- }>) | (CreateNeo4jGraphSearchToolBase<Schema> & Readonly<{
265
- graph: ManagedNeo4jKnowledgeGraph<Schema>;
266
- evidence: Readonly<{
267
- type: "chunks";
268
- maxChunks: number;
269
- }>;
270
- }>);
271
252
  type Neo4jGraphChangeCounts = Readonly<{
272
253
  created: number;
273
254
  updated: number;
@@ -281,9 +262,6 @@ type Neo4jGraphWriteResult = Readonly<{
281
262
  relationships: Neo4jGraphChangeCounts;
282
263
  mentions: Neo4jGraphChangeCounts;
283
264
  }>;
284
- type Neo4jGraphSearchTool = Tool<{
285
- query: string;
286
- }, Neo4jGraphContext>;
287
265
 
288
266
  type SeedRegistration = Readonly<{
289
267
  labels: readonly string[];
@@ -304,6 +282,8 @@ declare abstract class Neo4jKnowledgeGraphBase<Schema extends Neo4jGraphSchema =
304
282
  protected constructor(owner: Neo4jClient, schema: Schema);
305
283
  validate(options?: Neo4jGraphValidateOptions): Promise<void>;
306
284
  query(text: string, parameters: Record<string, unknown>, abortSignal?: AbortSignal, access?: "read" | "write"): Promise<QueryResult>;
285
+ retrieve(options: GraphRetrieveOptions<Schema, Evidence>): Promise<GraphContext>;
286
+ explore(options: GraphExploreOptions<Schema>): Promise<GraphExploreResult>;
307
287
  seed(name: string): SeedRegistration;
308
288
  protected transaction<T>(abortSignal: AbortSignal | undefined, run: (transaction: GraphTransaction) => Promise<T>): Promise<T>;
309
289
  private runTransaction;
@@ -341,17 +321,12 @@ declare class Neo4jClient {
341
321
  private assertOpen;
342
322
  }
343
323
 
324
+ declare function exploreGraph<Schema extends Neo4jGraphSchema>(graph: Neo4jKnowledgeGraphBase<Schema>, options: GraphExploreOptions<Schema>): Promise<GraphExploreResult>;
325
+
344
326
  declare function extractGraphFacts<Schema extends Neo4jGraphSchema, Model extends _anvia_core.CompletionModel>(options: ExtractGraphFactsOptions<Schema, Model>): Promise<ExtractGraphFactsResult<Schema>>;
345
- declare class GraphFactConflictError extends Error {
346
- readonly factKey: string;
347
- readonly sourceChunkIds: readonly string[];
348
- constructor(factKey: string, sourceChunkIds: readonly string[]);
349
- }
350
327
 
351
328
  declare function retrieveGraphContext<Schema extends Neo4jGraphSchema>(options: RetrieveGraphContextOptions<Schema>): Promise<Neo4jGraphContext>;
352
329
 
353
330
  declare function defineNeo4jGraphSchema<const Options extends Neo4jGraphSchemaOptions>(options: Options): Neo4jGraphSchema<Options>;
354
331
 
355
- declare function createNeo4jGraphSearchTool<Schema extends Neo4jGraphSchema>(options: CreateNeo4jGraphSearchToolOptions<Schema>): Neo4jGraphSearchTool;
356
-
357
- export { type CreateNeo4jGraphSearchToolOptions, type DeleteNeo4jDocumentsOptions, type ExistingNeo4jSeed, type ExtractGraphFactsOptions, type ExtractGraphFactsResult, GraphFactConflictError, ManagedNeo4jKnowledgeGraph, type ManagedNeo4jKnowledgeGraphOptions, Neo4jClient, type Neo4jClientOptions, type Neo4jFulltextIndex, type Neo4jGraphChangeCounts, type Neo4jGraphChunk, type Neo4jGraphConflict, type Neo4jGraphContext, type Neo4jGraphContextNode, type Neo4jGraphContextRelationship, type Neo4jGraphContextSeed, type Neo4jGraphDocument, type Neo4jGraphEnsureOptions, type Neo4jGraphEntity, type Neo4jGraphEvidence, type Neo4jGraphEvidenceCapability, type Neo4jGraphEvidenceOptions, type Neo4jGraphFacts, type Neo4jGraphMention, type Neo4jGraphRelationship, type Neo4jGraphSchema, type Neo4jGraphSchemaOptions, type Neo4jGraphSearchOptions, type Neo4jGraphSearchTool, type Neo4jGraphTraversalOptions, type Neo4jGraphValidateOptions, type Neo4jGraphWriteResult, type Neo4jHybridSearchOptions, Neo4jKnowledgeGraph, type Neo4jKnowledgeGraphOptions, type Neo4jNodeDefinition, type Neo4jNodeIdentity, type Neo4jOrphanEntityPolicy, type Neo4jProperties, type Neo4jPropertyPrimitive, type Neo4jPropertyValue, type Neo4jRelationshipDefinition, type Neo4jVectorIndex, type Neo4jVectorSearchOptions, type ReplaceNeo4jDocumentsOptions, type RetrieveGraphContextOptions, createNeo4jGraphSearchTool, defineNeo4jGraphSchema, extractGraphFacts, retrieveGraphContext };
332
+ export { type DeleteNeo4jDocumentsOptions, type ExistingNeo4jSeed, type ExtractGraphFactsOptions, type ExtractGraphFactsResult, ManagedNeo4jKnowledgeGraph, type ManagedNeo4jKnowledgeGraphOptions, Neo4jClient, type Neo4jClientOptions, type Neo4jFulltextIndex, type Neo4jGraphChangeCounts, type Neo4jGraphChunk, type Neo4jGraphConflict, type Neo4jGraphContext, type Neo4jGraphContextNode, type Neo4jGraphContextRelationship, type Neo4jGraphContextSeed, type Neo4jGraphDocument, type Neo4jGraphEnsureOptions, type Neo4jGraphEntity, type Neo4jGraphEvidence, type Neo4jGraphEvidenceCapability, type Neo4jGraphEvidenceOptions, type Neo4jGraphFacts, type Neo4jGraphMention, type Neo4jGraphRelationship, type Neo4jGraphSchema, type Neo4jGraphSchemaOptions, type Neo4jGraphSearchOptions, type Neo4jGraphTraversalOptions, type Neo4jGraphValidateOptions, type Neo4jGraphWriteResult, type Neo4jHybridSearchOptions, Neo4jKnowledgeGraph, type Neo4jKnowledgeGraphOptions, type Neo4jNodeDefinition, type Neo4jNodeIdentity, type Neo4jOrphanEntityPolicy, type Neo4jProperties, type Neo4jPropertyPrimitive, type Neo4jPropertyValue, type Neo4jRelationshipDefinition, type Neo4jVectorIndex, type Neo4jVectorSearchOptions, type ReplaceNeo4jDocumentsOptions, type RetrieveGraphContextOptions, defineNeo4jGraphSchema, exploreGraph, extractGraphFacts, retrieveGraphContext };