@grackle-ai/knowledge 0.59.1 → 0.60.0
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/dist/client.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/edge-store.d.ts +32 -0
- package/dist/edge-store.d.ts.map +1 -0
- package/dist/edge-store.js +145 -0
- package/dist/edge-store.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/node-store.d.ts +110 -0
- package/dist/node-store.d.ts.map +1 -0
- package/dist/node-store.js +266 -0
- package/dist/node-store.js.map +1 -0
- package/package.json +2 -2
package/dist/client.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { type Driver, type Session } from "neo4j-driver";
|
|
11
11
|
/** Configuration for the Neo4j connection. */
|
|
12
12
|
export interface Neo4jClientConfig {
|
|
13
|
-
/** Bolt URL (default: bolt://
|
|
13
|
+
/** Bolt URL (default: bolt://127.0.0.1:7687). */
|
|
14
14
|
url?: string;
|
|
15
15
|
/** Username (default: neo4j). */
|
|
16
16
|
username?: string;
|
package/dist/constants.js
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge CRUD operations for the knowledge graph.
|
|
3
|
+
*
|
|
4
|
+
* Provides create and remove operations for typed relationships between
|
|
5
|
+
* {@link KnowledgeNode} instances, backed by Neo4j.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { type EdgeType, type KnowledgeEdge } from "./types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Create a typed edge between two nodes.
|
|
12
|
+
*
|
|
13
|
+
* @param fromId - Source node ID.
|
|
14
|
+
* @param toId - Target node ID.
|
|
15
|
+
* @param type - Relationship type (must be a valid {@link EdgeType}).
|
|
16
|
+
* @param metadata - Optional metadata to attach to the edge.
|
|
17
|
+
* @returns The created edge.
|
|
18
|
+
* @throws If either node does not exist.
|
|
19
|
+
* @throws If the edge type is invalid.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createEdge(fromId: string, toId: string, type: EdgeType, metadata?: Record<string, unknown>): Promise<KnowledgeEdge>;
|
|
22
|
+
/**
|
|
23
|
+
* Remove an edge between two nodes.
|
|
24
|
+
*
|
|
25
|
+
* @param fromId - Source node ID.
|
|
26
|
+
* @param toId - Target node ID.
|
|
27
|
+
* @param type - Relationship type to remove.
|
|
28
|
+
* @returns `true` if an edge was removed, `false` if no matching edge existed.
|
|
29
|
+
* @throws If the edge type is invalid.
|
|
30
|
+
*/
|
|
31
|
+
export declare function removeEdge(fromId: string, toId: string, type: EdgeType): Promise<boolean>;
|
|
32
|
+
//# sourceMappingURL=edge-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edge-store.d.ts","sourceRoot":"","sources":["../src/edge-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,EAAa,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAwD1E;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,EACd,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,aAAa,CAAC,CAiDxB;AAED;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,OAAO,CAAC,CAsBlB"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge CRUD operations for the knowledge graph.
|
|
3
|
+
*
|
|
4
|
+
* Provides create and remove operations for typed relationships between
|
|
5
|
+
* {@link KnowledgeNode} instances, backed by Neo4j.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { getSession } from "./client.js";
|
|
10
|
+
import { logger } from "./logger.js";
|
|
11
|
+
import { NODE_LABEL } from "./constants.js";
|
|
12
|
+
import { EDGE_TYPE } from "./types.js";
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Validation
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
/** Known edge type values for runtime validation. */
|
|
17
|
+
const VALID_EDGE_TYPES = new Set(Object.values(EDGE_TYPE));
|
|
18
|
+
/**
|
|
19
|
+
* Assert that a string is a valid {@link EdgeType}.
|
|
20
|
+
*
|
|
21
|
+
* @throws If the value is not a known edge type.
|
|
22
|
+
*/
|
|
23
|
+
function assertValidEdgeType(type) {
|
|
24
|
+
if (!VALID_EDGE_TYPES.has(type)) {
|
|
25
|
+
throw new Error(`Invalid edge type: "${type}". Must be one of: ${[...VALID_EDGE_TYPES].join(", ")}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Cypher builders
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
/**
|
|
32
|
+
* Build the Cypher query for creating an edge of a given type.
|
|
33
|
+
*
|
|
34
|
+
* Relationship types cannot be parameterized in Cypher, so the type is
|
|
35
|
+
* interpolated directly. This is safe because {@link assertValidEdgeType}
|
|
36
|
+
* ensures the value comes from the closed {@link EdgeType} union.
|
|
37
|
+
*/
|
|
38
|
+
function buildCreateEdgeCypher(edgeType) {
|
|
39
|
+
return [
|
|
40
|
+
`MATCH (a:${NODE_LABEL} {id: $fromId}), (b:${NODE_LABEL} {id: $toId})`,
|
|
41
|
+
`CREATE (a)-[r:${edgeType} {metadata: $metadata, createdAt: $createdAt}]->(b)`,
|
|
42
|
+
`RETURN a.id AS fromId, b.id AS toId, type(r) AS type, r.metadata AS metadata, r.createdAt AS createdAt`,
|
|
43
|
+
].join("\n");
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Build the Cypher query for removing an edge of a given type.
|
|
47
|
+
*/
|
|
48
|
+
function buildRemoveEdgeCypher(edgeType) {
|
|
49
|
+
return [
|
|
50
|
+
`MATCH (a:${NODE_LABEL} {id: $fromId})-[r:${edgeType}]->(b:${NODE_LABEL} {id: $toId})`,
|
|
51
|
+
`DELETE r`,
|
|
52
|
+
`RETURN count(r) AS deleted`,
|
|
53
|
+
].join("\n");
|
|
54
|
+
}
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Public API
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
/**
|
|
59
|
+
* Create a typed edge between two nodes.
|
|
60
|
+
*
|
|
61
|
+
* @param fromId - Source node ID.
|
|
62
|
+
* @param toId - Target node ID.
|
|
63
|
+
* @param type - Relationship type (must be a valid {@link EdgeType}).
|
|
64
|
+
* @param metadata - Optional metadata to attach to the edge.
|
|
65
|
+
* @returns The created edge.
|
|
66
|
+
* @throws If either node does not exist.
|
|
67
|
+
* @throws If the edge type is invalid.
|
|
68
|
+
*/
|
|
69
|
+
export async function createEdge(fromId, toId, type, metadata) {
|
|
70
|
+
assertValidEdgeType(type);
|
|
71
|
+
const createdAt = new Date().toISOString();
|
|
72
|
+
const metadataStr = metadata !== undefined ? JSON.stringify(metadata) : null;
|
|
73
|
+
const session = getSession();
|
|
74
|
+
try {
|
|
75
|
+
const result = await session.run(buildCreateEdgeCypher(type), {
|
|
76
|
+
fromId,
|
|
77
|
+
toId,
|
|
78
|
+
metadata: metadataStr,
|
|
79
|
+
createdAt,
|
|
80
|
+
});
|
|
81
|
+
if (result.records.length === 0) {
|
|
82
|
+
throw new Error(`Cannot create edge: one or both nodes not found (fromId=${fromId}, toId=${toId})`);
|
|
83
|
+
}
|
|
84
|
+
const record = result.records[0];
|
|
85
|
+
let parsedMetadata;
|
|
86
|
+
const rawMetadata = record.get("metadata");
|
|
87
|
+
if (rawMetadata !== null) {
|
|
88
|
+
try {
|
|
89
|
+
parsedMetadata = JSON.parse(rawMetadata);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
parsedMetadata = undefined;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
logger.debug({ fromId, toId, type }, "Created edge");
|
|
96
|
+
return {
|
|
97
|
+
fromId: record.get("fromId"),
|
|
98
|
+
toId: record.get("toId"),
|
|
99
|
+
type: record.get("type"),
|
|
100
|
+
metadata: parsedMetadata,
|
|
101
|
+
createdAt: record.get("createdAt"),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
try {
|
|
106
|
+
await session.close();
|
|
107
|
+
}
|
|
108
|
+
catch (closeError) {
|
|
109
|
+
logger.warn({ err: closeError }, "Failed to close session after createEdge");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Remove an edge between two nodes.
|
|
115
|
+
*
|
|
116
|
+
* @param fromId - Source node ID.
|
|
117
|
+
* @param toId - Target node ID.
|
|
118
|
+
* @param type - Relationship type to remove.
|
|
119
|
+
* @returns `true` if an edge was removed, `false` if no matching edge existed.
|
|
120
|
+
* @throws If the edge type is invalid.
|
|
121
|
+
*/
|
|
122
|
+
export async function removeEdge(fromId, toId, type) {
|
|
123
|
+
assertValidEdgeType(type);
|
|
124
|
+
const session = getSession();
|
|
125
|
+
try {
|
|
126
|
+
const result = await session.run(buildRemoveEdgeCypher(type), {
|
|
127
|
+
fromId,
|
|
128
|
+
toId,
|
|
129
|
+
});
|
|
130
|
+
const deleted = result.records[0]?.get("deleted");
|
|
131
|
+
if (deleted > 0) {
|
|
132
|
+
logger.debug({ fromId, toId, type }, "Removed edge");
|
|
133
|
+
}
|
|
134
|
+
return deleted > 0;
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
try {
|
|
138
|
+
await session.close();
|
|
139
|
+
}
|
|
140
|
+
catch (closeError) {
|
|
141
|
+
logger.warn({ err: closeError }, "Failed to close session after removeEdge");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=edge-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edge-store.js","sourceRoot":"","sources":["../src/edge-store.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -20,4 +20,7 @@ export type { EmbeddedChunk } from "./ingest.js";
|
|
|
20
20
|
export { ingest } from "./ingest.js";
|
|
21
21
|
export type { TranscriptChunkerOptions } from "./transcript-chunker.js";
|
|
22
22
|
export { createTranscriptChunker } from "./transcript-chunker.js";
|
|
23
|
+
export { createReferenceNode, createNativeNode, getNode, deleteNode, updateNode, recordToNode, } from "./node-store.js";
|
|
24
|
+
export type { CreateReferenceNodeInput, CreateNativeNodeInput, UpdateReferenceNodeInput, UpdateNativeNodeInput, UpdateNodeInput, NodeWithEdges, } from "./node-store.js";
|
|
25
|
+
export { createEdge, removeEdge } from "./edge-store.js";
|
|
23
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxF,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC5D,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,oCAAoC,EACpC,UAAU,EACV,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxF,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC5D,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,oCAAoC,EACpC,UAAU,EACV,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,OAAO,EACP,UAAU,EACV,UAAU,EACV,YAAY,GACb,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,eAAe,EACf,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -15,4 +15,6 @@ export { createLocalEmbedder } from "./local-embedder.js";
|
|
|
15
15
|
export { createPassThroughChunker } from "./pass-through-chunker.js";
|
|
16
16
|
export { ingest } from "./ingest.js";
|
|
17
17
|
export { createTranscriptChunker } from "./transcript-chunker.js";
|
|
18
|
+
export { createReferenceNode, createNativeNode, getNode, deleteNode, updateNode, recordToNode, } from "./node-store.js";
|
|
19
|
+
export { createEdge, removeEdge } from "./edge-store.js";
|
|
18
20
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExF,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC5D,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,oCAAoC,EACpC,UAAU,EACV,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExF,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC5D,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,oCAAoC,EACpC,UAAU,EACV,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAErE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,OAAO,EACP,UAAU,EACV,UAAU,EACV,YAAY,GACb,MAAM,iBAAiB,CAAC;AASzB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node CRUD operations for the knowledge graph.
|
|
3
|
+
*
|
|
4
|
+
* Provides create, read, update, and delete operations for both
|
|
5
|
+
* {@link ReferenceNode} and {@link NativeNode} types, backed by Neo4j.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { type ReferenceSource, type NativeCategory, type KnowledgeNode, type KnowledgeEdge } from "./types.js";
|
|
10
|
+
/** Input for creating a reference node. Excludes auto-generated fields. */
|
|
11
|
+
export interface CreateReferenceNodeInput {
|
|
12
|
+
/** Which entity type this refers to. */
|
|
13
|
+
sourceType: ReferenceSource;
|
|
14
|
+
/** The ID of the entity in Grackle's relational DB. */
|
|
15
|
+
sourceId: string;
|
|
16
|
+
/** Human-readable label derived from the source. */
|
|
17
|
+
label: string;
|
|
18
|
+
/** Dense vector embedding for similarity search. */
|
|
19
|
+
embedding: number[];
|
|
20
|
+
/** Workspace scope (empty string = global). */
|
|
21
|
+
workspaceId: string;
|
|
22
|
+
}
|
|
23
|
+
/** Input for creating a native node. Excludes auto-generated fields. */
|
|
24
|
+
export interface CreateNativeNodeInput {
|
|
25
|
+
/** Subcategory of the native node. */
|
|
26
|
+
category: NativeCategory;
|
|
27
|
+
/** Title or summary. */
|
|
28
|
+
title: string;
|
|
29
|
+
/** Full content owned by this node. */
|
|
30
|
+
content: string;
|
|
31
|
+
/** Free-form tags for categorization. */
|
|
32
|
+
tags: string[];
|
|
33
|
+
/** Dense vector embedding for similarity search. */
|
|
34
|
+
embedding: number[];
|
|
35
|
+
/** Workspace scope (empty string = global). */
|
|
36
|
+
workspaceId: string;
|
|
37
|
+
}
|
|
38
|
+
/** Fields that can be updated on a reference node. */
|
|
39
|
+
export interface UpdateReferenceNodeInput {
|
|
40
|
+
/** Updated label. */
|
|
41
|
+
label?: string;
|
|
42
|
+
/** Updated source ID. */
|
|
43
|
+
sourceId?: string;
|
|
44
|
+
/** Updated embedding vector. */
|
|
45
|
+
embedding?: number[];
|
|
46
|
+
}
|
|
47
|
+
/** Fields that can be updated on a native node. */
|
|
48
|
+
export interface UpdateNativeNodeInput {
|
|
49
|
+
/** Updated title. */
|
|
50
|
+
title?: string;
|
|
51
|
+
/** Updated content. */
|
|
52
|
+
content?: string;
|
|
53
|
+
/** Updated tags. */
|
|
54
|
+
tags?: string[];
|
|
55
|
+
/** Updated embedding vector. */
|
|
56
|
+
embedding?: number[];
|
|
57
|
+
}
|
|
58
|
+
/** Union of update inputs for either node kind. */
|
|
59
|
+
export type UpdateNodeInput = UpdateReferenceNodeInput | UpdateNativeNodeInput;
|
|
60
|
+
/** A node together with all its edges. */
|
|
61
|
+
export interface NodeWithEdges {
|
|
62
|
+
/** The knowledge graph node. */
|
|
63
|
+
node: KnowledgeNode;
|
|
64
|
+
/** All edges connected to this node (both incoming and outgoing). */
|
|
65
|
+
edges: KnowledgeEdge[];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Convert Neo4j node properties to a typed {@link KnowledgeNode}.
|
|
69
|
+
*
|
|
70
|
+
* Handles the discriminated union based on the `kind` property.
|
|
71
|
+
*/
|
|
72
|
+
export declare function recordToNode(properties: Record<string, unknown>): KnowledgeNode;
|
|
73
|
+
/**
|
|
74
|
+
* Create a reference node in the knowledge graph.
|
|
75
|
+
*
|
|
76
|
+
* Generates a UUID and timestamps automatically.
|
|
77
|
+
*
|
|
78
|
+
* @returns The ID of the created node.
|
|
79
|
+
*/
|
|
80
|
+
export declare function createReferenceNode(input: CreateReferenceNodeInput): Promise<string>;
|
|
81
|
+
/**
|
|
82
|
+
* Create a native node in the knowledge graph.
|
|
83
|
+
*
|
|
84
|
+
* Generates a UUID and timestamps automatically.
|
|
85
|
+
*
|
|
86
|
+
* @returns The ID of the created node.
|
|
87
|
+
*/
|
|
88
|
+
export declare function createNativeNode(input: CreateNativeNodeInput): Promise<string>;
|
|
89
|
+
/**
|
|
90
|
+
* Get a node by ID, including all its edges.
|
|
91
|
+
*
|
|
92
|
+
* @returns The node and its edges, or `undefined` if the node was not found.
|
|
93
|
+
*/
|
|
94
|
+
export declare function getNode(id: string): Promise<NodeWithEdges | undefined>;
|
|
95
|
+
/**
|
|
96
|
+
* Delete a node and all its edges (`DETACH DELETE`).
|
|
97
|
+
*
|
|
98
|
+
* @returns `true` if a node was deleted, `false` if the node was not found.
|
|
99
|
+
*/
|
|
100
|
+
export declare function deleteNode(id: string): Promise<boolean>;
|
|
101
|
+
/**
|
|
102
|
+
* Update a node's mutable properties.
|
|
103
|
+
*
|
|
104
|
+
* Cannot change `kind`, `id`, `createdAt`, or `workspaceId`.
|
|
105
|
+
* Automatically updates the `updatedAt` timestamp.
|
|
106
|
+
*
|
|
107
|
+
* @returns The updated node, or `undefined` if the node was not found.
|
|
108
|
+
*/
|
|
109
|
+
export declare function updateNode(id: string, updates: UpdateNodeInput): Promise<KnowledgeNode | undefined>;
|
|
110
|
+
//# sourceMappingURL=node-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-store.d.ts","sourceRoot":"","sources":["../src/node-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAEnB,MAAM,YAAY,CAAC;AAMpB,2EAA2E;AAC3E,MAAM,WAAW,wBAAwB;IACvC,wCAAwC;IACxC,UAAU,EAAE,eAAe,CAAC;IAC5B,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wEAAwE;AACxE,MAAM,WAAW,qBAAqB;IACpC,sCAAsC;IACtC,QAAQ,EAAE,cAAc,CAAC;IACzB,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,oDAAoD;IACpD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,sDAAsD;AACtD,MAAM,WAAW,wBAAwB;IACvC,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,mDAAmD;AACnD,MAAM,WAAW,qBAAqB;IACpC,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,mDAAmD;AACnD,MAAM,MAAM,eAAe,GAAG,wBAAwB,GAAG,qBAAqB,CAAC;AAE/E,0CAA0C;AAC1C,MAAM,WAAW,aAAa;IAC5B,gCAAgC;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,qEAAqE;IACrE,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAsCD;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,aAAa,CA4Bf;AA4BD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,MAAM,CAAC,CA4BjB;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAwB5E;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgB7D;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAmCpC"}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node CRUD operations for the knowledge graph.
|
|
3
|
+
*
|
|
4
|
+
* Provides create, read, update, and delete operations for both
|
|
5
|
+
* {@link ReferenceNode} and {@link NativeNode} types, backed by Neo4j.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import { randomUUID } from "node:crypto";
|
|
10
|
+
import { getSession } from "./client.js";
|
|
11
|
+
import { logger } from "./logger.js";
|
|
12
|
+
import { NODE_LABEL } from "./constants.js";
|
|
13
|
+
import { NODE_KIND, } from "./types.js";
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Cypher queries
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
const GET_NODE_WITH_EDGES_CYPHER = `
|
|
18
|
+
MATCH (n:${NODE_LABEL} {id: $id})
|
|
19
|
+
OPTIONAL MATCH (n)-[r]-(m:${NODE_LABEL})
|
|
20
|
+
WITH n, r, m
|
|
21
|
+
WHERE r IS NOT NULL
|
|
22
|
+
RETURN n,
|
|
23
|
+
collect({
|
|
24
|
+
fromId: CASE WHEN startNode(r) = n THEN n.id ELSE m.id END,
|
|
25
|
+
toId: CASE WHEN endNode(r) = n THEN n.id ELSE m.id END,
|
|
26
|
+
type: type(r),
|
|
27
|
+
metadata: r.metadata,
|
|
28
|
+
createdAt: r.createdAt
|
|
29
|
+
}) AS edges
|
|
30
|
+
UNION ALL
|
|
31
|
+
MATCH (n:${NODE_LABEL} {id: $id})
|
|
32
|
+
WHERE NOT (n)-[]-()
|
|
33
|
+
RETURN n, [] AS edges`;
|
|
34
|
+
const DELETE_NODE_CYPHER = `
|
|
35
|
+
MATCH (n:${NODE_LABEL} {id: $id})
|
|
36
|
+
DETACH DELETE n
|
|
37
|
+
RETURN count(n) AS deleted`;
|
|
38
|
+
const UPDATE_NODE_CYPHER = `
|
|
39
|
+
MATCH (n:${NODE_LABEL} {id: $id})
|
|
40
|
+
SET n += $updates
|
|
41
|
+
RETURN n`;
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Helpers
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
/**
|
|
46
|
+
* Convert Neo4j node properties to a typed {@link KnowledgeNode}.
|
|
47
|
+
*
|
|
48
|
+
* Handles the discriminated union based on the `kind` property.
|
|
49
|
+
*/
|
|
50
|
+
export function recordToNode(properties) {
|
|
51
|
+
const base = {
|
|
52
|
+
id: properties.id,
|
|
53
|
+
kind: properties.kind,
|
|
54
|
+
embedding: properties.embedding ?? [],
|
|
55
|
+
createdAt: properties.createdAt,
|
|
56
|
+
updatedAt: properties.updatedAt,
|
|
57
|
+
workspaceId: properties.workspaceId ?? "",
|
|
58
|
+
};
|
|
59
|
+
if (base.kind === NODE_KIND.REFERENCE) {
|
|
60
|
+
return {
|
|
61
|
+
...base,
|
|
62
|
+
kind: NODE_KIND.REFERENCE,
|
|
63
|
+
sourceType: properties.sourceType,
|
|
64
|
+
sourceId: properties.sourceId,
|
|
65
|
+
label: properties.label ?? "",
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
...base,
|
|
70
|
+
kind: NODE_KIND.NATIVE,
|
|
71
|
+
category: properties.category,
|
|
72
|
+
title: properties.title ?? "",
|
|
73
|
+
content: properties.content ?? "",
|
|
74
|
+
tags: properties.tags ?? [],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Convert a raw edge object from Cypher `collect()` to a {@link KnowledgeEdge}.
|
|
79
|
+
*/
|
|
80
|
+
function recordToEdge(raw) {
|
|
81
|
+
let metadata;
|
|
82
|
+
if (raw.metadata !== undefined && raw.metadata !== null) {
|
|
83
|
+
try {
|
|
84
|
+
metadata = JSON.parse(raw.metadata);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
metadata = undefined;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
fromId: raw.fromId,
|
|
92
|
+
toId: raw.toId,
|
|
93
|
+
type: raw.type,
|
|
94
|
+
metadata,
|
|
95
|
+
createdAt: raw.createdAt,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// Public API
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
/**
|
|
102
|
+
* Create a reference node in the knowledge graph.
|
|
103
|
+
*
|
|
104
|
+
* Generates a UUID and timestamps automatically.
|
|
105
|
+
*
|
|
106
|
+
* @returns The ID of the created node.
|
|
107
|
+
*/
|
|
108
|
+
export async function createReferenceNode(input) {
|
|
109
|
+
const id = randomUUID();
|
|
110
|
+
const now = new Date().toISOString();
|
|
111
|
+
const props = {
|
|
112
|
+
id,
|
|
113
|
+
kind: NODE_KIND.REFERENCE,
|
|
114
|
+
sourceType: input.sourceType,
|
|
115
|
+
sourceId: input.sourceId,
|
|
116
|
+
label: input.label,
|
|
117
|
+
embedding: input.embedding,
|
|
118
|
+
workspaceId: input.workspaceId,
|
|
119
|
+
createdAt: now,
|
|
120
|
+
updatedAt: now,
|
|
121
|
+
};
|
|
122
|
+
const session = getSession();
|
|
123
|
+
try {
|
|
124
|
+
await session.run(`CREATE (n:${NODE_LABEL} $props) RETURN n`, { props });
|
|
125
|
+
logger.debug({ nodeId: id, kind: NODE_KIND.REFERENCE }, "Created reference node");
|
|
126
|
+
return id;
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
try {
|
|
130
|
+
await session.close();
|
|
131
|
+
}
|
|
132
|
+
catch (closeError) {
|
|
133
|
+
logger.warn({ err: closeError }, "Failed to close session after createReferenceNode");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Create a native node in the knowledge graph.
|
|
139
|
+
*
|
|
140
|
+
* Generates a UUID and timestamps automatically.
|
|
141
|
+
*
|
|
142
|
+
* @returns The ID of the created node.
|
|
143
|
+
*/
|
|
144
|
+
export async function createNativeNode(input) {
|
|
145
|
+
const id = randomUUID();
|
|
146
|
+
const now = new Date().toISOString();
|
|
147
|
+
const props = {
|
|
148
|
+
id,
|
|
149
|
+
kind: NODE_KIND.NATIVE,
|
|
150
|
+
category: input.category,
|
|
151
|
+
title: input.title,
|
|
152
|
+
content: input.content,
|
|
153
|
+
tags: input.tags,
|
|
154
|
+
embedding: input.embedding,
|
|
155
|
+
workspaceId: input.workspaceId,
|
|
156
|
+
createdAt: now,
|
|
157
|
+
updatedAt: now,
|
|
158
|
+
};
|
|
159
|
+
const session = getSession();
|
|
160
|
+
try {
|
|
161
|
+
await session.run(`CREATE (n:${NODE_LABEL} $props) RETURN n`, { props });
|
|
162
|
+
logger.debug({ nodeId: id, kind: NODE_KIND.NATIVE }, "Created native node");
|
|
163
|
+
return id;
|
|
164
|
+
}
|
|
165
|
+
finally {
|
|
166
|
+
try {
|
|
167
|
+
await session.close();
|
|
168
|
+
}
|
|
169
|
+
catch (closeError) {
|
|
170
|
+
logger.warn({ err: closeError }, "Failed to close session after createNativeNode");
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Get a node by ID, including all its edges.
|
|
176
|
+
*
|
|
177
|
+
* @returns The node and its edges, or `undefined` if the node was not found.
|
|
178
|
+
*/
|
|
179
|
+
export async function getNode(id) {
|
|
180
|
+
const session = getSession();
|
|
181
|
+
try {
|
|
182
|
+
const result = await session.run(GET_NODE_WITH_EDGES_CYPHER, { id });
|
|
183
|
+
if (result.records.length === 0) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
const record = result.records[0];
|
|
187
|
+
const neo4jNode = record.get("n");
|
|
188
|
+
const rawEdges = record.get("edges");
|
|
189
|
+
const node = recordToNode(neo4jNode.properties);
|
|
190
|
+
const edges = rawEdges.map(recordToEdge);
|
|
191
|
+
return { node, edges };
|
|
192
|
+
}
|
|
193
|
+
finally {
|
|
194
|
+
try {
|
|
195
|
+
await session.close();
|
|
196
|
+
}
|
|
197
|
+
catch (closeError) {
|
|
198
|
+
logger.warn({ err: closeError }, "Failed to close session after getNode");
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Delete a node and all its edges (`DETACH DELETE`).
|
|
204
|
+
*
|
|
205
|
+
* @returns `true` if a node was deleted, `false` if the node was not found.
|
|
206
|
+
*/
|
|
207
|
+
export async function deleteNode(id) {
|
|
208
|
+
const session = getSession();
|
|
209
|
+
try {
|
|
210
|
+
const result = await session.run(DELETE_NODE_CYPHER, { id });
|
|
211
|
+
const deleted = result.records[0]?.get("deleted");
|
|
212
|
+
if (deleted > 0) {
|
|
213
|
+
logger.debug({ nodeId: id }, "Deleted node");
|
|
214
|
+
}
|
|
215
|
+
return deleted > 0;
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
218
|
+
try {
|
|
219
|
+
await session.close();
|
|
220
|
+
}
|
|
221
|
+
catch (closeError) {
|
|
222
|
+
logger.warn({ err: closeError }, "Failed to close session after deleteNode");
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Update a node's mutable properties.
|
|
228
|
+
*
|
|
229
|
+
* Cannot change `kind`, `id`, `createdAt`, or `workspaceId`.
|
|
230
|
+
* Automatically updates the `updatedAt` timestamp.
|
|
231
|
+
*
|
|
232
|
+
* @returns The updated node, or `undefined` if the node was not found.
|
|
233
|
+
*/
|
|
234
|
+
export async function updateNode(id, updates) {
|
|
235
|
+
// Strip immutable fields defensively.
|
|
236
|
+
const { ...mutableUpdates } = updates;
|
|
237
|
+
const forbidden = ["kind", "id", "createdAt", "workspaceId"];
|
|
238
|
+
for (const key of forbidden) {
|
|
239
|
+
delete mutableUpdates[key];
|
|
240
|
+
}
|
|
241
|
+
const patchedUpdates = {
|
|
242
|
+
...mutableUpdates,
|
|
243
|
+
updatedAt: new Date().toISOString(),
|
|
244
|
+
};
|
|
245
|
+
const session = getSession();
|
|
246
|
+
try {
|
|
247
|
+
const result = await session.run(UPDATE_NODE_CYPHER, {
|
|
248
|
+
id,
|
|
249
|
+
updates: patchedUpdates,
|
|
250
|
+
});
|
|
251
|
+
if (result.records.length === 0) {
|
|
252
|
+
return undefined;
|
|
253
|
+
}
|
|
254
|
+
const neo4jNode = result.records[0].get("n");
|
|
255
|
+
return recordToNode(neo4jNode.properties);
|
|
256
|
+
}
|
|
257
|
+
finally {
|
|
258
|
+
try {
|
|
259
|
+
await session.close();
|
|
260
|
+
}
|
|
261
|
+
catch (closeError) {
|
|
262
|
+
logger.warn({ err: closeError }, "Failed to close session after updateNode");
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=node-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-store.js","sourceRoot":"","sources":["../src/node-store.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grackle-ai/knowledge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.60.0",
|
|
4
4
|
"description": "Knowledge graph subsystem for Grackle (Neo4j + vector search)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"@huggingface/transformers": "^3.4.0",
|
|
28
28
|
"neo4j-driver": "^6.0.1",
|
|
29
29
|
"pino": "^10.3.1",
|
|
30
|
-
"@grackle-ai/common": "0.
|
|
30
|
+
"@grackle-ai/common": "0.60.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@rushstack/heft": "1.2.4",
|