@monoes/memory 1.0.20 → 1.0.21
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/hnsw-distance.d.ts +31 -0
- package/dist/hnsw-distance.d.ts.map +1 -0
- package/dist/hnsw-distance.js +106 -0
- package/dist/hnsw-distance.js.map +1 -0
- package/dist/hnsw-graph-ops.d.ts +29 -0
- package/dist/hnsw-graph-ops.d.ts.map +1 -0
- package/dist/hnsw-graph-ops.js +96 -0
- package/dist/hnsw-graph-ops.js.map +1 -0
- package/dist/hnsw-heap.d.ts +45 -0
- package/dist/hnsw-heap.d.ts.map +1 -0
- package/dist/hnsw-heap.js +155 -0
- package/dist/hnsw-heap.js.map +1 -0
- package/dist/hnsw-index.d.ts +14 -41
- package/dist/hnsw-index.d.ts.map +1 -1
- package/dist/hnsw-index.js +17 -461
- package/dist/hnsw-index.js.map +1 -1
- package/dist/hnsw-quantizer.d.ts +28 -0
- package/dist/hnsw-quantizer.d.ts.map +1 -0
- package/dist/hnsw-quantizer.js +100 -0
- package/dist/hnsw-quantizer.js.map +1 -0
- package/dist/hnsw-serialize.d.ts +39 -0
- package/dist/hnsw-serialize.d.ts.map +1 -0
- package/dist/hnsw-serialize.js +54 -0
- package/dist/hnsw-serialize.js.map +1 -0
- package/dist/migration-loaders.d.ts +38 -0
- package/dist/migration-loaders.d.ts.map +1 -0
- package/dist/migration-loaders.js +269 -0
- package/dist/migration-loaders.js.map +1 -0
- package/dist/migration-transform.d.ts +21 -0
- package/dist/migration-transform.d.ts.map +1 -0
- package/dist/migration-transform.js +124 -0
- package/dist/migration-transform.js.map +1 -0
- package/dist/migration.d.ts +38 -22
- package/dist/migration.d.ts.map +1 -1
- package/dist/migration.js +35 -348
- package/dist/migration.js.map +1 -1
- package/dist/sql-backend-ann.d.ts +46 -0
- package/dist/sql-backend-ann.d.ts.map +1 -0
- package/dist/sql-backend-ann.js +120 -0
- package/dist/sql-backend-ann.js.map +1 -0
- package/dist/sql-backend-introspect.d.ts +17 -0
- package/dist/sql-backend-introspect.d.ts.map +1 -0
- package/dist/sql-backend-introspect.js +114 -0
- package/dist/sql-backend-introspect.js.map +1 -0
- package/dist/sql-backend-reads.d.ts +53 -0
- package/dist/sql-backend-reads.d.ts.map +1 -0
- package/dist/sql-backend-reads.js +295 -0
- package/dist/sql-backend-reads.js.map +1 -0
- package/dist/sql-backend-writes.d.ts +64 -0
- package/dist/sql-backend-writes.d.ts.map +1 -0
- package/dist/sql-backend-writes.js +270 -0
- package/dist/sql-backend-writes.js.map +1 -0
- package/dist/sql-backend.d.ts +39 -96
- package/dist/sql-backend.d.ts.map +1 -1
- package/dist/sql-backend.js +49 -706
- package/dist/sql-backend.js.map +1 -1
- package/dist/types-backend.d.ts +187 -0
- package/dist/types-backend.d.ts.map +1 -0
- package/dist/types-backend.js +8 -0
- package/dist/types-backend.js.map +1 -0
- package/dist/types-core.d.ts +180 -0
- package/dist/types-core.d.ts.map +1 -0
- package/dist/types-core.js +8 -0
- package/dist/types-core.js.map +1 -0
- package/dist/types-misc.d.ts +172 -0
- package/dist/types-misc.d.ts.map +1 -0
- package/dist/types-misc.js +56 -0
- package/dist/types-misc.js.map +1 -0
- package/dist/types.d.ts +8 -516
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +5 -49
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1 HNSW Vector Index — distance metrics
|
|
3
|
+
*
|
|
4
|
+
* Split out of hnsw-index.ts (file-size sweep). Pure move: the method bodies
|
|
5
|
+
* are unchanged; state previously reached via `this` (the configured metric,
|
|
6
|
+
* a node's normalized vector) is now passed in explicitly by the caller.
|
|
7
|
+
*
|
|
8
|
+
* @module v1/memory/hnsw-distance
|
|
9
|
+
*/
|
|
10
|
+
import type { HNSWNode } from './hnsw-index.js';
|
|
11
|
+
import type { DistanceMetric } from './types.js';
|
|
12
|
+
export declare function distance(metric: DistanceMetric, a: Float32Array, b: Float32Array): number;
|
|
13
|
+
export declare function cosineDistance(a: Float32Array, b: Float32Array): number;
|
|
14
|
+
/**
|
|
15
|
+
* OPTIMIZED: Cosine distance using pre-normalized vectors
|
|
16
|
+
* Only requires dot product (no sqrt operations)
|
|
17
|
+
* Performance: O(n) with ~2x speedup over standard cosine
|
|
18
|
+
*/
|
|
19
|
+
export declare function cosineDistanceNormalized(a: Float32Array, b: Float32Array): number;
|
|
20
|
+
/**
|
|
21
|
+
* Normalize a vector to unit length for O(1) cosine similarity
|
|
22
|
+
*/
|
|
23
|
+
export declare function normalizeVector(vector: Float32Array): Float32Array;
|
|
24
|
+
/**
|
|
25
|
+
* OPTIMIZED distance calculation that uses pre-normalized vectors when available
|
|
26
|
+
*/
|
|
27
|
+
export declare function distanceOptimized(metric: DistanceMetric, query: Float32Array, normalizedQuery: Float32Array | null, node: HNSWNode): number;
|
|
28
|
+
export declare function euclideanDistance(a: Float32Array, b: Float32Array): number;
|
|
29
|
+
export declare function dotProductDistance(a: Float32Array, b: Float32Array): number;
|
|
30
|
+
export declare function manhattanDistance(a: Float32Array, b: Float32Array): number;
|
|
31
|
+
//# sourceMappingURL=hnsw-distance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hnsw-distance.d.ts","sourceRoot":"","sources":["../src/hnsw-distance.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAazF;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAevE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAQjF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAiBlE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,YAAY,EACnB,eAAe,EAAE,YAAY,GAAG,IAAI,EACpC,IAAI,EAAE,QAAQ,GACb,MAAM,CAQR;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAO1E;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAO3E;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAM1E"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1 HNSW Vector Index — distance metrics
|
|
3
|
+
*
|
|
4
|
+
* Split out of hnsw-index.ts (file-size sweep). Pure move: the method bodies
|
|
5
|
+
* are unchanged; state previously reached via `this` (the configured metric,
|
|
6
|
+
* a node's normalized vector) is now passed in explicitly by the caller.
|
|
7
|
+
*
|
|
8
|
+
* @module v1/memory/hnsw-distance
|
|
9
|
+
*/
|
|
10
|
+
export function distance(metric, a, b) {
|
|
11
|
+
switch (metric) {
|
|
12
|
+
case 'cosine':
|
|
13
|
+
return cosineDistance(a, b);
|
|
14
|
+
case 'euclidean':
|
|
15
|
+
return euclideanDistance(a, b);
|
|
16
|
+
case 'dot':
|
|
17
|
+
return dotProductDistance(a, b);
|
|
18
|
+
case 'manhattan':
|
|
19
|
+
return manhattanDistance(a, b);
|
|
20
|
+
default:
|
|
21
|
+
return cosineDistance(a, b);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function cosineDistance(a, b) {
|
|
25
|
+
let dotProduct = 0;
|
|
26
|
+
let normA = 0;
|
|
27
|
+
let normB = 0;
|
|
28
|
+
for (let i = 0; i < a.length; i++) {
|
|
29
|
+
dotProduct += a[i] * b[i];
|
|
30
|
+
normA += a[i] * a[i];
|
|
31
|
+
normB += b[i] * b[i];
|
|
32
|
+
}
|
|
33
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
34
|
+
if (denom === 0)
|
|
35
|
+
return 1; // zero vector has maximum distance
|
|
36
|
+
const similarity = dotProduct / denom;
|
|
37
|
+
return 1 - similarity; // Convert to distance
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* OPTIMIZED: Cosine distance using pre-normalized vectors
|
|
41
|
+
* Only requires dot product (no sqrt operations)
|
|
42
|
+
* Performance: O(n) with ~2x speedup over standard cosine
|
|
43
|
+
*/
|
|
44
|
+
export function cosineDistanceNormalized(a, b) {
|
|
45
|
+
let dotProduct = 0;
|
|
46
|
+
for (let i = 0; i < a.length; i++) {
|
|
47
|
+
dotProduct += a[i] * b[i];
|
|
48
|
+
}
|
|
49
|
+
// For normalized vectors: cosine_similarity = dot_product
|
|
50
|
+
// Return distance (1 - similarity)
|
|
51
|
+
return 1 - dotProduct;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Normalize a vector to unit length for O(1) cosine similarity
|
|
55
|
+
*/
|
|
56
|
+
export function normalizeVector(vector) {
|
|
57
|
+
let norm = 0;
|
|
58
|
+
for (let i = 0; i < vector.length; i++) {
|
|
59
|
+
const v = Number.isFinite(vector[i]) ? vector[i] : 0;
|
|
60
|
+
norm += v * v;
|
|
61
|
+
}
|
|
62
|
+
norm = Math.sqrt(norm);
|
|
63
|
+
if (norm === 0 || !Number.isFinite(norm)) {
|
|
64
|
+
return new Float32Array(vector.length); // safe zero vector for non-finite input
|
|
65
|
+
}
|
|
66
|
+
const normalized = new Float32Array(vector.length);
|
|
67
|
+
for (let i = 0; i < vector.length; i++) {
|
|
68
|
+
normalized[i] = (Number.isFinite(vector[i]) ? vector[i] : 0) / norm;
|
|
69
|
+
}
|
|
70
|
+
return normalized;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* OPTIMIZED distance calculation that uses pre-normalized vectors when available
|
|
74
|
+
*/
|
|
75
|
+
export function distanceOptimized(metric, query, normalizedQuery, node) {
|
|
76
|
+
// Use optimized path for cosine with pre-normalized vectors
|
|
77
|
+
if (metric === 'cosine' && normalizedQuery !== null && node.normalizedVector !== null) {
|
|
78
|
+
return cosineDistanceNormalized(normalizedQuery, node.normalizedVector);
|
|
79
|
+
}
|
|
80
|
+
// Fall back to standard distance calculation
|
|
81
|
+
return distance(metric, query, node.vector);
|
|
82
|
+
}
|
|
83
|
+
export function euclideanDistance(a, b) {
|
|
84
|
+
let sum = 0;
|
|
85
|
+
for (let i = 0; i < a.length; i++) {
|
|
86
|
+
const diff = a[i] - b[i];
|
|
87
|
+
sum += diff * diff;
|
|
88
|
+
}
|
|
89
|
+
return Math.sqrt(sum);
|
|
90
|
+
}
|
|
91
|
+
export function dotProductDistance(a, b) {
|
|
92
|
+
let dotProduct = 0;
|
|
93
|
+
for (let i = 0; i < a.length; i++) {
|
|
94
|
+
dotProduct += a[i] * b[i];
|
|
95
|
+
}
|
|
96
|
+
// Negative because higher dot product = more similar
|
|
97
|
+
return -dotProduct;
|
|
98
|
+
}
|
|
99
|
+
export function manhattanDistance(a, b) {
|
|
100
|
+
let sum = 0;
|
|
101
|
+
for (let i = 0; i < a.length; i++) {
|
|
102
|
+
sum += Math.abs(a[i] - b[i]);
|
|
103
|
+
}
|
|
104
|
+
return sum;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=hnsw-distance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hnsw-distance.js","sourceRoot":"","sources":["../src/hnsw-distance.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,UAAU,QAAQ,CAAC,MAAsB,EAAE,CAAe,EAAE,CAAe;IAC/E,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ;YACX,OAAO,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9B,KAAK,WAAW;YACd,OAAO,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACjC,KAAK,KAAK;YACR,OAAO,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAClC,KAAK,WAAW;YACd,OAAO,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACjC;YACE,OAAO,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,CAAe,EAAE,CAAe;IAC7D,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1B,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrB,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC,mCAAmC;IAC9D,MAAM,UAAU,GAAG,UAAU,GAAG,KAAK,CAAC;IACtC,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC,sBAAsB;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,CAAe,EAAE,CAAe;IACvE,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,0DAA0D;IAC1D,mCAAmC;IACnC,OAAO,CAAC,GAAG,UAAU,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAoB;IAClD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IACD,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEvB,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,OAAO,IAAI,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,wCAAwC;IAClF,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACtE,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAsB,EACtB,KAAmB,EACnB,eAAoC,EACpC,IAAc;IAEd,4DAA4D;IAC5D,IAAI,MAAM,KAAK,QAAQ,IAAI,eAAe,KAAK,IAAI,IAAI,IAAI,CAAC,gBAAgB,KAAK,IAAI,EAAE,CAAC;QACtF,OAAO,wBAAwB,CAAC,eAAe,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC1E,CAAC;IAED,6CAA6C;IAC7C,OAAO,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,CAAe,EAAE,CAAe;IAChE,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,GAAG,IAAI,IAAI,GAAG,IAAI,CAAC;IACrB,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,CAAe,EAAE,CAAe;IACjE,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,qDAAqD;IACrD,OAAO,CAAC,UAAU,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,CAAe,EAAE,CAAe;IAChE,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1 HNSW Vector Index — graph search/maintenance operations
|
|
3
|
+
*
|
|
4
|
+
* Split out of hnsw-index.ts (file-size sweep). Pure move: the method bodies
|
|
5
|
+
* are unchanged; the node map and configured metric previously reached via
|
|
6
|
+
* `this` are now passed in explicitly by the caller.
|
|
7
|
+
*
|
|
8
|
+
* @module v1/memory/hnsw-graph-ops
|
|
9
|
+
*/
|
|
10
|
+
import type { HNSWNode } from './hnsw-index.js';
|
|
11
|
+
import type { DistanceMetric } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* OPTIMIZED searchLayer using heap-based priority queues
|
|
14
|
+
* Performance: O(log n) per operation vs O(n log n) for Array.sort()
|
|
15
|
+
* Expected speedup: 3-5x for large result sets
|
|
16
|
+
*/
|
|
17
|
+
export declare function searchLayerOptimized(nodes: Map<string, HNSWNode>, metric: DistanceMetric, query: Float32Array, normalizedQuery: Float32Array | null, entryPoint: string, ef: number, level: number): Array<{
|
|
18
|
+
id: string;
|
|
19
|
+
distance: number;
|
|
20
|
+
}>;
|
|
21
|
+
export declare function selectNeighbors(nodeId: string, _query: Float32Array, candidates: Array<{
|
|
22
|
+
id: string;
|
|
23
|
+
distance: number;
|
|
24
|
+
}>, M: number): Array<{
|
|
25
|
+
id: string;
|
|
26
|
+
distance: number;
|
|
27
|
+
}>;
|
|
28
|
+
export declare function pruneConnections(nodes: Map<string, HNSWNode>, metric: DistanceMetric, node: HNSWNode, level: number, maxConnections: number): void;
|
|
29
|
+
//# sourceMappingURL=hnsw-graph-ops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hnsw-graph-ops.d.ts","sourceRoot":"","sources":["../src/hnsw-graph-ops.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC5B,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE,YAAY,EACnB,eAAe,EAAE,YAAY,GAAG,IAAI,EACpC,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAwDzC;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,EACnD,CAAC,EAAE,MAAM,GACR,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAIzC;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC5B,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,GACrB,IAAI,CA2BN"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1 HNSW Vector Index — graph search/maintenance operations
|
|
3
|
+
*
|
|
4
|
+
* Split out of hnsw-index.ts (file-size sweep). Pure move: the method bodies
|
|
5
|
+
* are unchanged; the node map and configured metric previously reached via
|
|
6
|
+
* `this` are now passed in explicitly by the caller.
|
|
7
|
+
*
|
|
8
|
+
* @module v1/memory/hnsw-graph-ops
|
|
9
|
+
*/
|
|
10
|
+
import { distance, distanceOptimized } from './hnsw-distance.js';
|
|
11
|
+
import { BinaryMaxHeap, BinaryMinHeap } from './hnsw-heap.js';
|
|
12
|
+
/**
|
|
13
|
+
* OPTIMIZED searchLayer using heap-based priority queues
|
|
14
|
+
* Performance: O(log n) per operation vs O(n log n) for Array.sort()
|
|
15
|
+
* Expected speedup: 3-5x for large result sets
|
|
16
|
+
*/
|
|
17
|
+
export function searchLayerOptimized(nodes, metric, query, normalizedQuery, entryPoint, ef, level) {
|
|
18
|
+
const visited = new Set([entryPoint]);
|
|
19
|
+
// Min-heap for candidates (closest first for expansion)
|
|
20
|
+
const candidates = new BinaryMinHeap();
|
|
21
|
+
// Max-heap for results (bounded size, tracks worst distance efficiently)
|
|
22
|
+
const results = new BinaryMaxHeap(ef);
|
|
23
|
+
const entryNode = nodes.get(entryPoint);
|
|
24
|
+
const entryDist = distanceOptimized(metric, query, normalizedQuery, entryNode);
|
|
25
|
+
candidates.insert(entryPoint, entryDist);
|
|
26
|
+
results.insert(entryPoint, entryDist);
|
|
27
|
+
while (!candidates.isEmpty()) {
|
|
28
|
+
// Get closest candidate - O(log n)
|
|
29
|
+
const currentDist = candidates.peekPriority();
|
|
30
|
+
const currentId = candidates.extractMin();
|
|
31
|
+
// Check termination: if closest candidate is worse than worst result, stop
|
|
32
|
+
const worstResultDist = results.peekMaxPriority();
|
|
33
|
+
if (currentDist > worstResultDist && results.size >= ef) {
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
// Explore neighbors
|
|
37
|
+
const node = nodes.get(currentId);
|
|
38
|
+
if (!node)
|
|
39
|
+
continue;
|
|
40
|
+
const connections = node.connections.get(level);
|
|
41
|
+
if (!connections)
|
|
42
|
+
continue;
|
|
43
|
+
for (const neighborId of connections) {
|
|
44
|
+
if (visited.has(neighborId))
|
|
45
|
+
continue;
|
|
46
|
+
visited.add(neighborId);
|
|
47
|
+
const neighborNode = nodes.get(neighborId);
|
|
48
|
+
if (!neighborNode)
|
|
49
|
+
continue;
|
|
50
|
+
const dist = distanceOptimized(metric, query, normalizedQuery, neighborNode);
|
|
51
|
+
// Only add if within threshold or results not full
|
|
52
|
+
if (results.size < ef || dist < worstResultDist) {
|
|
53
|
+
candidates.insert(neighborId, dist);
|
|
54
|
+
// Max-heap handles size bounding automatically - O(log n)
|
|
55
|
+
results.insert(neighborId, dist);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Return sorted results
|
|
60
|
+
return results.toSortedArray().map(({ item, priority }) => ({
|
|
61
|
+
id: item,
|
|
62
|
+
distance: priority,
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
export function selectNeighbors(nodeId, _query, candidates, M) {
|
|
66
|
+
// candidates arrive distance-ascending from searchLayerOptimized/toSortedArray;
|
|
67
|
+
// filter preserves that order, so no additional sort is needed.
|
|
68
|
+
return candidates.filter((c) => c.id !== nodeId).slice(0, M);
|
|
69
|
+
}
|
|
70
|
+
export function pruneConnections(nodes, metric, node, level, maxConnections) {
|
|
71
|
+
const connections = node.connections.get(level);
|
|
72
|
+
if (!connections || connections.size <= maxConnections)
|
|
73
|
+
return;
|
|
74
|
+
// Calculate distances to all connections
|
|
75
|
+
const distances = [];
|
|
76
|
+
for (const connId of connections) {
|
|
77
|
+
const connNode = nodes.get(connId);
|
|
78
|
+
if (connNode) {
|
|
79
|
+
distances.push({
|
|
80
|
+
id: connId,
|
|
81
|
+
distance: distance(metric, node.vector, connNode.vector),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Keep only the closest ones
|
|
86
|
+
distances.sort((a, b) => a.distance - b.distance);
|
|
87
|
+
const toKeep = new Set(distances.slice(0, maxConnections).map((d) => d.id));
|
|
88
|
+
// Remove excess connections
|
|
89
|
+
for (const connId of connections) {
|
|
90
|
+
if (!toKeep.has(connId)) {
|
|
91
|
+
connections.delete(connId);
|
|
92
|
+
nodes.get(connId)?.connections.get(level)?.delete(node.id);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=hnsw-graph-ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hnsw-graph-ops.js","sourceRoot":"","sources":["../src/hnsw-graph-ops.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1 HNSW Vector Index — priority-queue heaps
|
|
3
|
+
*
|
|
4
|
+
* Split out of hnsw-index.ts (file-size sweep). Pure move: no behaviour change.
|
|
5
|
+
*
|
|
6
|
+
* @module v1/memory/hnsw-heap
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Binary Min Heap for O(log n) priority queue operations
|
|
10
|
+
* Used for candidate selection in HNSW search
|
|
11
|
+
*/
|
|
12
|
+
export declare class BinaryMinHeap<T> {
|
|
13
|
+
private heap;
|
|
14
|
+
get size(): number;
|
|
15
|
+
insert(item: T, priority: number): void;
|
|
16
|
+
extractMin(): T | undefined;
|
|
17
|
+
peek(): T | undefined;
|
|
18
|
+
peekPriority(): number | undefined;
|
|
19
|
+
isEmpty(): boolean;
|
|
20
|
+
toArray(): T[];
|
|
21
|
+
private bubbleUp;
|
|
22
|
+
private bubbleDown;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Binary Max Heap for bounded top-k tracking
|
|
26
|
+
* Keeps track of k smallest elements by evicting largest when full
|
|
27
|
+
*/
|
|
28
|
+
export declare class BinaryMaxHeap<T> {
|
|
29
|
+
private heap;
|
|
30
|
+
private maxSize;
|
|
31
|
+
constructor(maxSize?: number);
|
|
32
|
+
get size(): number;
|
|
33
|
+
insert(item: T, priority: number): boolean;
|
|
34
|
+
peekMax(): T | undefined;
|
|
35
|
+
peekMaxPriority(): number;
|
|
36
|
+
extractMax(): T | undefined;
|
|
37
|
+
isEmpty(): boolean;
|
|
38
|
+
toSortedArray(): Array<{
|
|
39
|
+
item: T;
|
|
40
|
+
priority: number;
|
|
41
|
+
}>;
|
|
42
|
+
private bubbleUp;
|
|
43
|
+
private bubbleDown;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=hnsw-heap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hnsw-heap.d.ts","sourceRoot":"","sources":["../src/hnsw-heap.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,qBAAa,aAAa,CAAC,CAAC;IAC1B,OAAO,CAAC,IAAI,CAA4C;IAExD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAGtC;IAED,UAAU,IAAI,CAAC,GAAG,SAAS,CAS1B;IAED,IAAI,IAAI,CAAC,GAAG,SAAS,CAEpB;IAED,YAAY,IAAI,MAAM,GAAG,SAAS,CAEjC;IAED,OAAO,IAAI,OAAO,CAEjB;IAED,OAAO,IAAI,CAAC,EAAE,CAKb;IAED,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,UAAU;CAiBnB;AAED;;;GAGG;AACH,qBAAa,aAAa,CAAC,CAAC;IAC1B,OAAO,CAAC,IAAI,CAA4C;IACxD,OAAO,CAAC,OAAO,CAAS;IAExB,YAAY,OAAO,GAAE,MAAiB,EAErC;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAezC;IAED,OAAO,IAAI,CAAC,GAAG,SAAS,CAEvB;IAED,eAAe,IAAI,MAAM,CAExB;IAED,UAAU,IAAI,CAAC,GAAG,SAAS,CAS1B;IAED,OAAO,IAAI,OAAO,CAEjB;IAED,aAAa,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAEpD;IAED,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,UAAU;CAiBnB"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V1 HNSW Vector Index — priority-queue heaps
|
|
3
|
+
*
|
|
4
|
+
* Split out of hnsw-index.ts (file-size sweep). Pure move: no behaviour change.
|
|
5
|
+
*
|
|
6
|
+
* @module v1/memory/hnsw-heap
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Binary Min Heap for O(log n) priority queue operations
|
|
10
|
+
* Used for candidate selection in HNSW search
|
|
11
|
+
*/
|
|
12
|
+
export class BinaryMinHeap {
|
|
13
|
+
heap = [];
|
|
14
|
+
get size() {
|
|
15
|
+
return this.heap.length;
|
|
16
|
+
}
|
|
17
|
+
insert(item, priority) {
|
|
18
|
+
this.heap.push({ item, priority });
|
|
19
|
+
this.bubbleUp(this.heap.length - 1);
|
|
20
|
+
}
|
|
21
|
+
extractMin() {
|
|
22
|
+
if (this.heap.length === 0)
|
|
23
|
+
return undefined;
|
|
24
|
+
const min = this.heap[0].item;
|
|
25
|
+
const last = this.heap.pop();
|
|
26
|
+
if (this.heap.length > 0) {
|
|
27
|
+
this.heap[0] = last;
|
|
28
|
+
this.bubbleDown(0);
|
|
29
|
+
}
|
|
30
|
+
return min;
|
|
31
|
+
}
|
|
32
|
+
peek() {
|
|
33
|
+
return this.heap[0]?.item;
|
|
34
|
+
}
|
|
35
|
+
peekPriority() {
|
|
36
|
+
return this.heap[0]?.priority;
|
|
37
|
+
}
|
|
38
|
+
isEmpty() {
|
|
39
|
+
return this.heap.length === 0;
|
|
40
|
+
}
|
|
41
|
+
toArray() {
|
|
42
|
+
return this.heap
|
|
43
|
+
.slice()
|
|
44
|
+
.sort((a, b) => a.priority - b.priority)
|
|
45
|
+
.map((entry) => entry.item);
|
|
46
|
+
}
|
|
47
|
+
bubbleUp(index) {
|
|
48
|
+
while (index > 0) {
|
|
49
|
+
const parent = Math.floor((index - 1) / 2);
|
|
50
|
+
if (this.heap[parent].priority <= this.heap[index].priority)
|
|
51
|
+
break;
|
|
52
|
+
[this.heap[parent], this.heap[index]] = [this.heap[index], this.heap[parent]];
|
|
53
|
+
index = parent;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
bubbleDown(index) {
|
|
57
|
+
const length = this.heap.length;
|
|
58
|
+
while (true) {
|
|
59
|
+
let smallest = index;
|
|
60
|
+
const left = 2 * index + 1;
|
|
61
|
+
const right = 2 * index + 2;
|
|
62
|
+
if (left < length && this.heap[left].priority < this.heap[smallest].priority) {
|
|
63
|
+
smallest = left;
|
|
64
|
+
}
|
|
65
|
+
if (right < length && this.heap[right].priority < this.heap[smallest].priority) {
|
|
66
|
+
smallest = right;
|
|
67
|
+
}
|
|
68
|
+
if (smallest === index)
|
|
69
|
+
break;
|
|
70
|
+
[this.heap[smallest], this.heap[index]] = [this.heap[index], this.heap[smallest]];
|
|
71
|
+
index = smallest;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Binary Max Heap for bounded top-k tracking
|
|
77
|
+
* Keeps track of k smallest elements by evicting largest when full
|
|
78
|
+
*/
|
|
79
|
+
export class BinaryMaxHeap {
|
|
80
|
+
heap = [];
|
|
81
|
+
maxSize;
|
|
82
|
+
constructor(maxSize = Infinity) {
|
|
83
|
+
this.maxSize = maxSize;
|
|
84
|
+
}
|
|
85
|
+
get size() {
|
|
86
|
+
return this.heap.length;
|
|
87
|
+
}
|
|
88
|
+
insert(item, priority) {
|
|
89
|
+
// If at capacity and new item is worse than worst, reject
|
|
90
|
+
if (this.heap.length >= this.maxSize && priority >= this.heap[0]?.priority) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
if (this.heap.length >= this.maxSize) {
|
|
94
|
+
// Replace max element
|
|
95
|
+
this.heap[0] = { item, priority };
|
|
96
|
+
this.bubbleDown(0);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
this.heap.push({ item, priority });
|
|
100
|
+
this.bubbleUp(this.heap.length - 1);
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
peekMax() {
|
|
105
|
+
return this.heap[0]?.item;
|
|
106
|
+
}
|
|
107
|
+
peekMaxPriority() {
|
|
108
|
+
return this.heap[0]?.priority ?? Infinity;
|
|
109
|
+
}
|
|
110
|
+
extractMax() {
|
|
111
|
+
if (this.heap.length === 0)
|
|
112
|
+
return undefined;
|
|
113
|
+
const max = this.heap[0].item;
|
|
114
|
+
const last = this.heap.pop();
|
|
115
|
+
if (this.heap.length > 0) {
|
|
116
|
+
this.heap[0] = last;
|
|
117
|
+
this.bubbleDown(0);
|
|
118
|
+
}
|
|
119
|
+
return max;
|
|
120
|
+
}
|
|
121
|
+
isEmpty() {
|
|
122
|
+
return this.heap.length === 0;
|
|
123
|
+
}
|
|
124
|
+
toSortedArray() {
|
|
125
|
+
return this.heap.slice().sort((a, b) => a.priority - b.priority);
|
|
126
|
+
}
|
|
127
|
+
bubbleUp(index) {
|
|
128
|
+
while (index > 0) {
|
|
129
|
+
const parent = Math.floor((index - 1) / 2);
|
|
130
|
+
if (this.heap[parent].priority >= this.heap[index].priority)
|
|
131
|
+
break;
|
|
132
|
+
[this.heap[parent], this.heap[index]] = [this.heap[index], this.heap[parent]];
|
|
133
|
+
index = parent;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
bubbleDown(index) {
|
|
137
|
+
const length = this.heap.length;
|
|
138
|
+
while (true) {
|
|
139
|
+
let largest = index;
|
|
140
|
+
const left = 2 * index + 1;
|
|
141
|
+
const right = 2 * index + 2;
|
|
142
|
+
if (left < length && this.heap[left].priority > this.heap[largest].priority) {
|
|
143
|
+
largest = left;
|
|
144
|
+
}
|
|
145
|
+
if (right < length && this.heap[right].priority > this.heap[largest].priority) {
|
|
146
|
+
largest = right;
|
|
147
|
+
}
|
|
148
|
+
if (largest === index)
|
|
149
|
+
break;
|
|
150
|
+
[this.heap[largest], this.heap[index]] = [this.heap[index], this.heap[largest]];
|
|
151
|
+
index = largest;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=hnsw-heap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hnsw-heap.js","sourceRoot":"","sources":["../src/hnsw-heap.ts"],"names":[],"mappings":"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"}
|
package/dist/hnsw-index.d.ts
CHANGED
|
@@ -14,23 +14,23 @@
|
|
|
14
14
|
* @module v1/memory/hnsw-index
|
|
15
15
|
*/
|
|
16
16
|
import { EventEmitter } from 'node:events';
|
|
17
|
+
import type { HNSWSerialized } from './hnsw-serialize.js';
|
|
17
18
|
import type { HNSWConfig, HNSWStats } from './types.js';
|
|
19
|
+
export type { HNSWSerialized } from './hnsw-serialize.js';
|
|
18
20
|
/**
|
|
19
|
-
*
|
|
20
|
-
* HNSWIndex.deserialize(). `version` guards against loading a shape from a
|
|
21
|
-
* future/incompatible format.
|
|
21
|
+
* Internal node structure for HNSW graph
|
|
22
22
|
*/
|
|
23
|
-
export interface
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
23
|
+
export interface HNSWNode {
|
|
24
|
+
/** Node ID (memory entry ID) */
|
|
25
|
+
id: string;
|
|
26
|
+
/** Vector embedding (original) */
|
|
27
|
+
vector: Float32Array;
|
|
28
|
+
/** Pre-normalized vector for O(1) cosine similarity */
|
|
29
|
+
normalizedVector: Float32Array | null;
|
|
30
|
+
/** Connections at each layer */
|
|
31
|
+
connections: Map<number, Set<string>>;
|
|
32
|
+
/** Node level (top layer this node appears in) */
|
|
33
|
+
level: number;
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* HNSW Index implementation for ultra-fast vector similarity search
|
|
@@ -111,33 +111,6 @@ export declare class HNSWIndex extends EventEmitter {
|
|
|
111
111
|
private mergeConfig;
|
|
112
112
|
private getRandomLevel;
|
|
113
113
|
private insertNode;
|
|
114
|
-
/**
|
|
115
|
-
* OPTIMIZED searchLayer using heap-based priority queues
|
|
116
|
-
* Performance: O(log n) per operation vs O(n log n) for Array.sort()
|
|
117
|
-
* Expected speedup: 3-5x for large result sets
|
|
118
|
-
*/
|
|
119
|
-
private searchLayerOptimized;
|
|
120
|
-
private selectNeighbors;
|
|
121
|
-
private pruneConnections;
|
|
122
|
-
private distance;
|
|
123
|
-
private cosineDistance;
|
|
124
|
-
/**
|
|
125
|
-
* OPTIMIZED: Cosine distance using pre-normalized vectors
|
|
126
|
-
* Only requires dot product (no sqrt operations)
|
|
127
|
-
* Performance: O(n) with ~2x speedup over standard cosine
|
|
128
|
-
*/
|
|
129
|
-
private cosineDistanceNormalized;
|
|
130
|
-
/**
|
|
131
|
-
* Normalize a vector to unit length for O(1) cosine similarity
|
|
132
|
-
*/
|
|
133
|
-
private normalizeVector;
|
|
134
|
-
/**
|
|
135
|
-
* OPTIMIZED distance calculation that uses pre-normalized vectors when available
|
|
136
|
-
*/
|
|
137
|
-
private distanceOptimized;
|
|
138
|
-
private euclideanDistance;
|
|
139
|
-
private dotProductDistance;
|
|
140
|
-
private manhattanDistance;
|
|
141
114
|
}
|
|
142
115
|
export default HNSWIndex;
|
|
143
116
|
//# sourceMappingURL=hnsw-index.d.ts.map
|
package/dist/hnsw-index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hnsw-index.d.ts","sourceRoot":"","sources":["../src/hnsw-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"hnsw-index.d.ts","sourceRoot":"","sources":["../src/hnsw-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAExD,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IAEX,kCAAkC;IAClC,MAAM,EAAE,YAAY,CAAC;IAErB,uDAAuD;IACvD,gBAAgB,EAAE,YAAY,GAAG,IAAI,CAAC;IAEtC,gCAAgC;IAChC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAEtC,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,qBAAa,SAAU,SAAQ,YAAY;IACzC,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,SAAS,CAAS;IAG1B,OAAO,CAAC,KAAK,CAYX;IAGF,OAAO,CAAC,SAAS,CAA0B;IAE3C,YAAY,MAAM,GAAE,OAAO,CAAC,UAAU,CAAM,EAQ3C;IAED;;OAEG;IACG,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAkD9D;IAED;;OAEG;IACG,MAAM,CACV,KAAK,EAAE,YAAY,EACnB,CAAC,EAAE,MAAM,EACT,EAAE,CAAC,EAAE,MAAM,GACV,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAqElD;IAED;;OAEG;IACG,iBAAiB,CACrB,KAAK,EAAE,YAAY,EACnB,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,EAC/B,EAAE,CAAC,EAAE,MAAM,GACV,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAMlD;IAED;;OAEG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA2C9C;IAED;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBjF;IAED;;;;;;;;;;OAUG;IACH,SAAS,IAAI,cAAc,CAK1B;IAED,+DAA+D;IAC/D,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,CASlD;IAED;;OAEG;IACH,QAAQ,IAAI,SAAS,CAiBpB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI,CAWZ;IAED;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEvB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAID,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,cAAc;YAMR,UAAU;CAwEzB;eAEc,SAAS"}
|