sliftutils 1.4.81 → 1.4.82
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/index.d.ts +61 -13
- package/package.json +1 -1
- package/spec.txt +18 -0
- package/storage/dist/embeddingFormats.ts.cache +340 -0
- package/storage/dist/faceFramesData.ts.cache +55 -0
- package/storage/embeddingBench.d.ts +1 -0
- package/storage/embeddingBench.ts +152 -0
- package/storage/embeddingFormats.d.ts +4 -1
- package/storage/embeddingFormats.ts +173 -111
- package/storage/faceFramesData.d.ts +1 -0
- package/storage/faceFramesData.ts +49 -0
- package/storage/faceFramesServer.d.ts +1 -0
- package/storage/faceFramesServer.ts +56 -0
- package/storage/proxydatabase/dist/Database.ts.cache +13 -0
- package/storage/proxydatabase/dist/inMemoryDatabase.ts.cache +105 -0
- package/storage/proxydatabase/dist/ivfDbCheck.ts.cache +81 -0
- package/storage/proxydatabase/dist/ivfEmbeddingDatabase.ts.cache +334 -0
- package/storage/proxydatabase/dist/transactionSet.ts.cache +108 -0
- package/storage/proxydatabase/inMemoryDatabase.d.ts +13 -0
- package/storage/proxydatabase/inMemoryDatabase.ts +108 -0
- package/storage/proxydatabase/ivfDbCheck.d.ts +1 -0
- package/storage/proxydatabase/ivfDbCheck.ts +85 -0
- package/storage/proxydatabase/ivfEmbeddingDatabase.d.ts +11 -7
- package/storage/proxydatabase/ivfEmbeddingDatabase.ts +289 -144
- package/storage/proxydatabase/transactionSet.d.ts +9 -5
- package/storage/proxydatabase/transactionSet.ts +43 -22
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
3
|
+
//exports.InMemoryDatabase = void 0;
|
|
4
|
+
// Rough byte size of a value, for the read/written-bytes metrics.
|
|
5
|
+
function sizeOf(value) {
|
|
6
|
+
if (value === undefined || value === null) {
|
|
7
|
+
return 0;
|
|
8
|
+
}
|
|
9
|
+
if (value instanceof Uint8Array) {
|
|
10
|
+
return value.byteLength;
|
|
11
|
+
}
|
|
12
|
+
if (typeof value === "string") {
|
|
13
|
+
return value.length;
|
|
14
|
+
}
|
|
15
|
+
if (typeof value === "number") {
|
|
16
|
+
return 8;
|
|
17
|
+
}
|
|
18
|
+
if (typeof value === "boolean") {
|
|
19
|
+
return 1;
|
|
20
|
+
}
|
|
21
|
+
if (Array.isArray(value)) {
|
|
22
|
+
let total = 0;
|
|
23
|
+
for (const entry of value) {
|
|
24
|
+
total += sizeOf(entry);
|
|
25
|
+
}
|
|
26
|
+
return total;
|
|
27
|
+
}
|
|
28
|
+
if (typeof value === "object") {
|
|
29
|
+
let total = 0;
|
|
30
|
+
const record = value;
|
|
31
|
+
for (const key of Object.keys(record)) {
|
|
32
|
+
total += sizeOf(record[key]);
|
|
33
|
+
}
|
|
34
|
+
return total;
|
|
35
|
+
}
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
// Record the property path a dereference lambda walks, so a write/delete can be applied at it.
|
|
39
|
+
function capturePath(deref) {
|
|
40
|
+
const path = [];
|
|
41
|
+
const handler = {
|
|
42
|
+
get(_target, key) {
|
|
43
|
+
if (typeof key === "string") {
|
|
44
|
+
path.push(key);
|
|
45
|
+
}
|
|
46
|
+
return new Proxy({}, handler);
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
deref(new Proxy({}, handler));
|
|
50
|
+
return path;
|
|
51
|
+
}
|
|
52
|
+
function setPath(root, path, value) {
|
|
53
|
+
let node = root;
|
|
54
|
+
for (let index = 0; index < path.length - 1; index++) {
|
|
55
|
+
const key = path[index];
|
|
56
|
+
const next = node[key];
|
|
57
|
+
if (!next || typeof next !== "object") {
|
|
58
|
+
node[key] = {};
|
|
59
|
+
}
|
|
60
|
+
node = node[key];
|
|
61
|
+
}
|
|
62
|
+
node[path[path.length - 1]] = value;
|
|
63
|
+
}
|
|
64
|
+
function deletePath(root, path) {
|
|
65
|
+
let node = root;
|
|
66
|
+
for (let index = 0; index < path.length - 1; index++) {
|
|
67
|
+
const next = node[path[index]];
|
|
68
|
+
if (!next || typeof next !== "object") {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
node = next;
|
|
72
|
+
}
|
|
73
|
+
delete node[path[path.length - 1]];
|
|
74
|
+
}
|
|
75
|
+
// In-memory Database for tests/dev: holds the whole root as a plain object and counts every call plus the
|
|
76
|
+
// bytes flowing through. Synchronous and always "synced", so reads only return undefined for a genuinely
|
|
77
|
+
// missing scalar (a missing transaction set reads as empty inside the set helpers).
|
|
78
|
+
class InMemoryDatabase {
|
|
79
|
+
constructor(initial) {
|
|
80
|
+
this.readCalls = 0;
|
|
81
|
+
this.writeCalls = 0;
|
|
82
|
+
this.deleteCalls = 0;
|
|
83
|
+
this.bytesRead = 0;
|
|
84
|
+
this.bytesWritten = 0;
|
|
85
|
+
this.root = initial;
|
|
86
|
+
}
|
|
87
|
+
readData(deref) {
|
|
88
|
+
this.readCalls++;
|
|
89
|
+
const result = deref(this.root);
|
|
90
|
+
this.bytesRead += sizeOf(result);
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
writeData(deref, newValue) {
|
|
94
|
+
this.writeCalls++;
|
|
95
|
+
this.bytesWritten += sizeOf(newValue);
|
|
96
|
+
setPath(this.root, capturePath(deref), newValue);
|
|
97
|
+
}
|
|
98
|
+
deleteData(deref) {
|
|
99
|
+
this.deleteCalls++;
|
|
100
|
+
deletePath(this.root, capturePath(deref));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.InMemoryDatabase = InMemoryDatabase;
|
|
104
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5NZW1vcnlEYXRhYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImluTWVtb3J5RGF0YWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEsa0VBQWtFO0FBQ2xFLFNBQVMsTUFBTSxDQUFDLEtBQWM7SUFDMUIsSUFBSSxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUN4QyxPQUFPLENBQUMsQ0FBQztJQUNiLENBQUM7SUFDRCxJQUFJLEtBQUssWUFBWSxVQUFVLEVBQUUsQ0FBQztRQUM5QixPQUFPLEtBQUssQ0FBQyxVQUFVLENBQUM7SUFDNUIsQ0FBQztJQUNELElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDNUIsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDO0lBQ3hCLENBQUM7SUFDRCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzVCLE9BQU8sQ0FBQyxDQUFDO0lBQ2IsQ0FBQztJQUNELElBQUksT0FBTyxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDN0IsT0FBTyxDQUFDLENBQUM7SUFDYixDQUFDO0lBQ0QsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDdkIsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsS0FBSyxNQUFNLEtBQUssSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUN4QixLQUFLLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzNCLENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNqQixDQUFDO0lBQ0QsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUM1QixJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7UUFDZCxNQUFNLE1BQU0sR0FBRyxLQUFnQyxDQUFDO1FBQ2hELEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFN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Q0FBQyxDQUFDO1FBQ3hDLElBQUksQ0FBQyxTQUFTLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2pDLE9BQU8sTUFBTSxDQUFDO0lBQ2xCLENBQUM7SUFDRCxTQUFTLENBQVEsS0FBNEIsRUFBRSxRQUFlO1FBQzFELElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNsQixJQUFJLENBQUMsWUFBWSxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN0QyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsS0FBbUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ25GLENBQUM7SUFDRCxVQUFVLENBQUMsS0FBOEI7UUFDckMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ25CLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxLQUFtQyxDQUFDLENBQUMsQ0FBQztJQUM1RSxDQUFDO0NBQ0o7QUEzQkQsNENBMkJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGF0YWJhc2UgfSBmcm9tIFwiLi9EYXRhYmFzZVwiO1xuXG4vLyBSb3VnaCBieXRlIHNpemUgb2YgYSB2YWx1ZSwgZm9yIHRoZSByZWFkL3dyaXR0ZW4tYnl0ZXMgbWV0cmljcy5cbmZ1bmN0aW9uIHNpemVPZih2YWx1ZTogdW5rbm93bik6IG51bWJlciB7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlLmJ5dGVMZW5ndGg7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlLmxlbmd0aDtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICByZXR1cm4gODtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJib29sZWFuXCIpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICBsZXQgdG90YWwgPSAwO1xuICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIHZhbHVlKSB7XG4gICAgICAgICAgICB0b3RhbCArPSBzaXplT2YoZW50cnkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0b3RhbDtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICBsZXQgdG90YWwgPSAwO1xuICAgICAgICBjb25zdCByZWNvcmQgPSB2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMocmVjb3JkKSkge1xuICAgICAgICAgICAgdG90YWwgKz0gc2l6ZU9mKHJlY29yZFtrZXldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdG90YWw7XG4gICAgfVxuICAgIHJldHVybiAwO1xufVxuXG4vLyBSZWNvcmQgdGhlIHByb3BlcnR5IHBhdGggYSBkZXJlZmVyZW5jZSBsYW1iZGEgd2Fsa3MsIHNvIGEgd3JpdGUvZGVsZXRlIGNhbiBiZSBhcHBsaWVkIGF0IGl0LlxuZnVuY3Rpb24gY2FwdHVyZVBhdGgoZGVyZWY6IChyb290OiB1bmtub3duKSA9PiB1bmtub3duKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHBhdGg6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3QgaGFuZGxlcjogUHJveHlIYW5kbGVyPG9iamVjdD4gPSB7XG4gICAgICAgIGdldChfdGFyZ2V0LCBrZXkpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2Yga2V5ID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgcGF0aC5wdXNoKGtleSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb3h5KHt9LCBoYW5kbGVyKTtcbiAgICAgICAgfSxcbiAgICB9O1xuICAgIGRlcmVmKG5ldyBQcm94eSh7fSwgaGFuZGxlcikpO1xuICAgIHJldHVybiBwYXRoO1xufVxuXG5mdW5jdGlvbiBzZXRQYXRoKHJvb3Q6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBwYXRoOiBzdHJpbmdbXSwgdmFsdWU6IHVua25vd24pOiB2b2lkIHtcbiAgICBsZXQgbm9kZSA9IHJvb3Q7XG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHBhdGgubGVuZ3RoIC0gMTsgaW5kZXgrKykge1xuICAgICAgICBjb25zdCBrZXkgPSBwYXRoW2luZGV4XTtcbiAgICAgICAgY29uc3QgbmV4dCA9IG5vZGVba2V5XTtcbiAgICAgICAgaWYgKCFuZXh0IHx8IHR5cGVvZiBuZXh0ICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBub2RlW2tleV0gPSB7fTtcbiAgICAgICAgfVxuICAgICAgICBub2RlID0gbm9kZVtrZXldIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgIH1cbiAgICBub2RlW3BhdGhbcGF0aC5sZW5ndGggLSAxXV0gPSB2YWx1ZTtcbn1cblxuZnVuY3Rpb24gZGVsZXRlUGF0aChyb290OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgcGF0aDogc3RyaW5nW10pOiB2b2lkIHtcbiAgICBsZXQgbm9kZSA9IHJvb3Q7XG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHBhdGgubGVuZ3RoIC0gMTsgaW5kZXgrKykge1xuICAgICAgICBjb25zdCBuZXh0ID0gbm9kZVtwYXRoW2luZGV4XV07XG4gICAgICAgIGlmICghbmV4dCB8fCB0eXBlb2YgbmV4dCAhPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIG5vZGUgPSBuZXh0IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgIH1cbiAgICBkZWxldGUgbm9kZVtwYXRoW3BhdGgubGVuZ3RoIC0gMV1dO1xufVxuXG4vLyBJbi1tZW1vcnkgRGF0YWJhc2UgZm9yIHRlc3RzL2RldjogaG9sZHMgdGhlIHdob2xlIHJvb3QgYXMgYSBwbGFpbiBvYmplY3QgYW5kIGNvdW50cyBldmVyeSBjYWxsIHBsdXMgdGhlXG4vLyBieXRlcyBmbG93aW5nIHRocm91Z2guIFN5bmNocm9ub3VzIGFuZCBhbHdheXMgXCJzeW5jZWRcIiwgc28gcmVhZHMgb25seSByZXR1cm4gdW5kZWZpbmVkIGZvciBhIGdlbnVpbmVseVxuLy8gbWlzc2luZyBzY2FsYXIgKGEgbWlzc2luZyB0cmFuc2FjdGlvbiBzZXQgcmVhZHMgYXMgZW1wdHkgaW5zaWRlIHRoZSBzZXQgaGVscGVycykuXG5leHBvcnQgY2xhc3MgSW5NZW1vcnlEYXRhYmFzZTxSb290PiBpbXBsZW1lbnRzIERhdGFiYXNlPFJvb3Q+IHtcbiAgICBwdWJsaWMgcmVhZENhbGxzID0gMDtcbiAgICBwdWJsaWMgd3JpdGVDYWxscyA9IDA7XG4gICAgcHVibGljIGRlbGV0ZUNhbGxzID0gMDtcbiAgICBwdWJsaWMgYnl0ZXNSZWFkID0gMDtcbiAgICBwdWJsaWMgYnl0ZXNXcml0dGVuID0gMDtcbiAgICBwcml2YXRlIHJvb3Q6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4gICAgY29uc3RydWN0b3IoaW5pdGlhbDogUm9vdCkge1xuICAgICAgICB0aGlzLnJvb3QgPSBpbml0aWFsIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgIH1cblxuICAgIHJlYWREYXRhPFZhbHVlPihkZXJlZjogKHJvb3Q6IFJvb3QpID0+IFZhbHVlKTogVmFsdWUgfCB1bmRlZmluZWQge1xuICAgICAgICB0aGlzLnJlYWRDYWxscysrO1xuICAgICAgICBjb25zdCByZXN1bHQgPSBkZXJlZih0aGlzLnJvb3QgYXMgUm9vdCk7XG4gICAgICAgIHRoaXMuYnl0ZXNSZWFkICs9IHNpemVPZihyZXN1bHQpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICB3cml0ZURhdGE8VmFsdWU+KGRlcmVmOiAocm9vdDogUm9vdCkgPT4gVmFsdWUsIG5ld1ZhbHVlOiBWYWx1ZSk6IHZvaWQge1xuICAgICAgICB0aGlzLndyaXRlQ2FsbHMrKztcbiAgICAgICAgdGhpcy5ieXRlc1dyaXR0ZW4gKz0gc2l6ZU9mKG5ld1ZhbHVlKTtcbiAgICAgICAgc2V0UGF0aCh0aGlzLnJvb3QsIGNhcHR1cmVQYXRoKGRlcmVmIGFzIChyb290OiB1bmtub3duKSA9PiB1bmtub3duKSwgbmV3VmFsdWUpO1xuICAgIH1cbiAgICBkZWxldGVEYXRhKGRlcmVmOiAocm9vdDogUm9vdCkgPT4gdW5rbm93bik6IHZvaWQge1xuICAgICAgICB0aGlzLmRlbGV0ZUNhbGxzKys7XG4gICAgICAgIGRlbGV0ZVBhdGgodGhpcy5yb290LCBjYXB0dXJlUGF0aChkZXJlZiBhcyAocm9vdDogdW5rbm93bikgPT4gdW5rbm93bikpO1xuICAgIH1cbn1cbiJdfQ==
|
|
105
|
+
/* _JS_SOURCE_HASH = "aa6987f940c5d431dfd1c6d9989fec9aef7d35056bea35397ec8e94982f2c3ca"; */
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
6
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const inMemoryDatabase_1 = require("./inMemoryDatabase");
|
|
8
|
+
const ivfEmbeddingDatabase_1 = require("./ivfEmbeddingDatabase");
|
|
9
|
+
const embeddingFormats_1 = require("../embeddingFormats");
|
|
10
|
+
const faceFramesData_1 = require("../faceFramesData");
|
|
11
|
+
// Exercises the tiered IVF embedding database through the in-memory Database wrapper, which counts every
|
|
12
|
+
// read/write/delete call and the bytes through each, across dataset sizes and load patterns, with timing.
|
|
13
|
+
const DIM = 512;
|
|
14
|
+
const FILE_NAME = "faceFrames2_full.f32";
|
|
15
|
+
const MODEL = "buffalo_l";
|
|
16
|
+
const FORMAT = "q8g8_2048";
|
|
17
|
+
async function loadFloats(count) {
|
|
18
|
+
const byteLength = count * DIM * 4;
|
|
19
|
+
const filePath = await (0, faceFramesData_1.ensureFaceData)(FILE_NAME, byteLength);
|
|
20
|
+
const buffer = Buffer.alloc(byteLength);
|
|
21
|
+
const handle = fs_1.default.openSync(filePath, "r");
|
|
22
|
+
fs_1.default.readSync(handle, buffer, 0, byteLength, 0);
|
|
23
|
+
fs_1.default.closeSync(handle);
|
|
24
|
+
return new Float32Array(buffer.buffer, buffer.byteOffset, count * DIM);
|
|
25
|
+
}
|
|
26
|
+
async function buildInputs(count) {
|
|
27
|
+
const floats = await loadFloats(count);
|
|
28
|
+
const inputs = [];
|
|
29
|
+
for (let index = 0; index < count; index++) {
|
|
30
|
+
const slice = floats.subarray(index * DIM, (index + 1) * DIM);
|
|
31
|
+
inputs.push({ ref: "e" + index, embedding: (0, embeddingFormats_1.encodeEmbedding)({ input: slice, format: FORMAT, model: MODEL }) });
|
|
32
|
+
}
|
|
33
|
+
return inputs;
|
|
34
|
+
}
|
|
35
|
+
function freshDatabase(config) {
|
|
36
|
+
const root = { config, count: 0, flat: {}, steps: {}, centroids: {}, cells: {} };
|
|
37
|
+
return new inMemoryDatabase_1.InMemoryDatabase(root);
|
|
38
|
+
}
|
|
39
|
+
function pad(value, width) {
|
|
40
|
+
return String(value).padStart(width);
|
|
41
|
+
}
|
|
42
|
+
async function main() {
|
|
43
|
+
const config = { model: MODEL, format: FORMAT, cellTargetSize: 128 };
|
|
44
|
+
const runs = [
|
|
45
|
+
{ size: 10000, batch: 1 },
|
|
46
|
+
{ size: 10000, batch: 100 },
|
|
47
|
+
{ size: 100000, batch: 1000 },
|
|
48
|
+
];
|
|
49
|
+
let maxSize = 0;
|
|
50
|
+
for (const run of runs) {
|
|
51
|
+
if (run.size > maxSize) {
|
|
52
|
+
maxSize = run.size;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const loadStart = Date.now();
|
|
56
|
+
const allInputs = await buildInputs(maxSize);
|
|
57
|
+
console.log(`loaded + encoded ${maxSize} embeddings in ${((Date.now() - loadStart) / 1000).toFixed(1)}s\n`);
|
|
58
|
+
console.log(`${pad("added", 7)} ${pad("batch", 5)} | ${pad("secs", 7)} ${pad("reads", 8)} ${pad("writes", 8)} ${pad("deletes", 8)} ${pad("readMB", 9)} ${pad("writeMB", 8)} | recall`);
|
|
59
|
+
for (const run of runs) {
|
|
60
|
+
const database = freshDatabase(config);
|
|
61
|
+
const start = Date.now();
|
|
62
|
+
for (let offset = 0; offset < run.size; offset += run.batch) {
|
|
63
|
+
(0, ivfEmbeddingDatabase_1.insertEmbeddings)(database, allInputs.slice(offset, offset + run.batch));
|
|
64
|
+
}
|
|
65
|
+
const seconds = (Date.now() - start) / 1000;
|
|
66
|
+
let found = 0;
|
|
67
|
+
const sampleCount = 100;
|
|
68
|
+
for (let index = 0; index < sampleCount; index++) {
|
|
69
|
+
const query = allInputs[Math.floor(index * run.size / sampleCount)];
|
|
70
|
+
const hits = (0, ivfEmbeddingDatabase_1.searchEmbeddings)(database, query.embedding, { probeBudget: 512, resultCount: 1 });
|
|
71
|
+
if (hits && hits.length && hits[0].ref === query.ref) {
|
|
72
|
+
found++;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const recall = (found / sampleCount).toFixed(2);
|
|
76
|
+
console.log(`${pad(run.size, 7)} ${pad(run.batch, 5)} | ${pad(seconds.toFixed(1), 7)} ${pad(database.readCalls, 8)} ${pad(database.writeCalls, 8)} ${pad(database.deleteCalls, 8)} ${pad((database.bytesRead / 1e6).toFixed(0), 9)} ${pad((database.bytesWritten / 1e6).toFixed(0), 8)} | ${recall}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
main();
|
|
80
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXZmRGJDaGVjay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIml2ZkRiQ2hlY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw0Q0FBb0I7QUFDcEIseURBQXNEO0FBQ3RELGlFQUF5SDtBQUN6SCwwREFBdUU7QUFDdkUsc0RBQW1EO0FBRW5ELHlHQUF5RztBQUN6RywwR0FBMEc7QUFFMUcsTUFBTSxHQUFHLEdBQUcsR0FBRyxDQUFDO0FBQ2hCLE1BQU0sU0FBUyxHQUFHLHNCQUFzQixDQUFDO0FBQ3pDLE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FBQztBQUMxQixNQUFNLE1BQU0sR0FBb0IsV0FBVyxDQUFDO0FBRTVDLEtBQUssVUFBVSxVQUFVLENBQUMsS0FBYTtJQUNuQyxNQUFNLFVBQVUsR0FBRyxLQUFLLEdBQUcsR0FBRyxHQUFHLENBQUMsQ0FBQztJQUNuQyxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUEsK0JBQWMsRUFBQyxTQUFTLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDN0QsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN4QyxNQUFNLE1BQU0sR0FBRyxZQUFFLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUMxQyxZQUFFLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM5QyxZQUFFLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3JCLE9BQU8sSUFBSSxZQUFZLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQztBQUMzRSxDQUFDO0FBRUQsS0FBSyxVQUFVLFdBQVcsQ0FBQyxLQUFhO0lBQ3BDLE1BQU0sTUFBTSxHQUFHLE1BQU0sVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sTUFBTSxHQUFxQixFQUFFLENBQUM7SUFDcEMsS0FBSyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxHQUFHLEdBQUcsRUFBRSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQztRQUM5RCxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsR0FBRyxLQUFLLEVBQUUsU0FBUyxFQUFFLElBQUEsa0NBQWUsRUFBQyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEgsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2xCLENBQUM7QUFFRCxTQUFTLGFBQWEsQ0FBQyxNQUFpQjtJQUNwQyxNQUFNLElBQUksR0FBcUIsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDbkcsT0FBTyxJQUFJLG1DQUFnQixDQUFtQixJQUFJLENBQUMsQ0FBQztBQUN4RCxDQUFDO0FBRUQsU0FBUyxHQUFHLENBQUMsS0FBc0IsRUFBRSxLQUFhO0lBQzlDLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUN6QyxDQUFDO0FBRUQsS0FBSyxVQUFVLElBQUk7SUFDZixNQUFNLE1BQU0sR0FBYyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxjQUFjLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDaEYsTUFBTSxJQUFJLEdBQXNDO1FBQzVDLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFO1FBQ3pCLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFO1FBQzNCLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFO0tBQ2hDLENBQUM7SUFFRixJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFDaEIsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUNyQixJQUFJLEdBQUcsQ0FBQyxJQUFJLEdBQUcsT0FBTyxFQUFFLENBQUM7WUFDckIsT0FBTyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDdkIsQ0FBQztJQUNMLENBQUM7SUFDRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDN0IsTUFBTSxTQUFTLEdBQUcsTUFBTSxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDN0MsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsT0FBTyxrQkFBa0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRTVHLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3ZMLEtBQUssTUFBTSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDckIsTUFBTSxRQUFRLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUN6QixLQUFLLElBQUksTUFBTSxHQUFHLENBQUMsRUFBRSxNQUFNLEdBQUcsR0FBRyxDQUFDLElBQUksRUFBRSxNQUFNLElBQUksR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzFELElBQUEsdUNBQWdCLEVBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLE1BQU0sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUM1RSxDQUFDO1FBQ0QsTUFBTSxPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDO1FBRTVDLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztRQUNkLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQztRQUN4QixLQUFLLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRSxLQUFLLEdBQUcsV0FBVyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7WUFDL0MsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxJQUFJLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQztZQUNwRSxNQUFNLElBQUksR0FBRyxJQUFBLHVDQUFnQixFQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsU0FBUyxFQUFFLEVBQUUsV0FBVyxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUMvRixJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNuRCxLQUFLLEVBQUUsQ0FBQztZQUNaLENBQUM7UUFDTCxDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsQ0FBQyxLQUFLLEdBQUcsV0FBVyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2hELE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsU0FBUyxHQUFHLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsWUFBWSxHQUFHLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsTUFBTSxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQzFTLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgeyBJbk1lbW9yeURhdGFiYXNlIH0gZnJvbSBcIi4vaW5NZW1vcnlEYXRhYmFzZVwiO1xuaW1wb3J0IHsgSXZmRW1iZWRkaW5nUm9vdCwgSXZmQ29uZmlnLCBFbWJlZGRpbmdJbnB1dCwgaW5zZXJ0RW1iZWRkaW5ncywgc2VhcmNoRW1iZWRkaW5ncyB9IGZyb20gXCIuL2l2ZkVtYmVkZGluZ0RhdGFiYXNlXCI7XG5pbXBvcnQgeyBlbmNvZGVFbWJlZGRpbmcsIEVtYmVkZGluZ0Zvcm1hdCB9IGZyb20gXCIuLi9lbWJlZGRpbmdGb3JtYXRzXCI7XG5pbXBvcnQgeyBlbnN1cmVGYWNlRGF0YSB9IGZyb20gXCIuLi9mYWNlRnJhbWVzRGF0YVwiO1xuXG4vLyBFeGVyY2lzZXMgdGhlIHRpZXJlZCBJVkYgZW1iZWRkaW5nIGRhdGFiYXNlIHRocm91Z2ggdGhlIGluLW1lbW9yeSBEYXRhYmFzZSB3cmFwcGVyLCB3aGljaCBjb3VudHMgZXZlcnlcbi8vIHJlYWQvd3JpdGUvZGVsZXRlIGNhbGwgYW5kIHRoZSBieXRlcyB0aHJvdWdoIGVhY2gsIGFjcm9zcyBkYXRhc2V0IHNpemVzIGFuZCBsb2FkIHBhdHRlcm5zLCB3aXRoIHRpbWluZy5cblxuY29uc3QgRElNID0gNTEyO1xuY29uc3QgRklMRV9OQU1FID0gXCJmYWNlRnJhbWVzMl9mdWxsLmYzMlwiO1xuY29uc3QgTU9ERUwgPSBcImJ1ZmZhbG9fbFwiO1xuY29uc3QgRk9STUFUOiBFbWJlZGRpbmdGb3JtYXQgPSBcInE4ZzhfMjA0OFwiO1xuXG5hc3luYyBmdW5jdGlvbiBsb2FkRmxvYXRzKGNvdW50OiBudW1iZXIpOiBQcm9taXNlPEZsb2F0MzJBcnJheT4ge1xuICAgIGNvbnN0IGJ5dGVMZW5ndGggPSBjb3VudCAqIERJTSAqIDQ7XG4gICAgY29uc3QgZmlsZVBhdGggPSBhd2FpdCBlbnN1cmVGYWNlRGF0YShGSUxFX05BTUUsIGJ5dGVMZW5ndGgpO1xuICAgIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhieXRlTGVuZ3RoKTtcbiAgICBjb25zdCBoYW5kbGUgPSBmcy5vcGVuU3luYyhmaWxlUGF0aCwgXCJyXCIpO1xuICAgIGZzLnJlYWRTeW5jKGhhbmRsZSwgYnVmZmVyLCAwLCBieXRlTGVuZ3RoLCAwKTtcbiAgICBmcy5jbG9zZVN5bmMoaGFuZGxlKTtcbiAgICByZXR1cm4gbmV3IEZsb2F0MzJBcnJheShidWZmZXIuYnVmZmVyLCBidWZmZXIuYnl0ZU9mZnNldCwgY291bnQgKiBESU0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBidWlsZElucHV0cyhjb3VudDogbnVtYmVyKTogUHJvbWlzZTxFbWJlZGRpbmdJbnB1dFtdPiB7XG4gICAgY29uc3QgZmxvYXRzID0gYXdhaXQgbG9hZEZsb2F0cyhjb3VudCk7XG4gICAgY29uc3QgaW5wdXRzOiBFbWJlZGRpbmdJbnB1dFtdID0gW107XG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGNvdW50OyBpbmRleCsrKSB7XG4gICAgICAgIGNvbnN0IHNsaWNlID0gZmxvYXRzLnN1YmFycmF5KGluZGV4ICogRElNLCAoaW5kZXggKyAxKSAqIERJTSk7XG4gICAgICAgIGlucHV0cy5wdXNoKHsgcmVmOiBcImVcIiArIGluZGV4LCBlbWJlZGRpbmc6IGVuY29kZUVtYmVkZGluZyh7IGlucHV0OiBzbGljZSwgZm9ybWF0OiBGT1JNQVQsIG1vZGVsOiBNT0RFTCB9KSB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGlucHV0cztcbn1cblxuZnVuY3Rpb24gZnJlc2hEYXRhYmFzZShjb25maWc6IEl2ZkNvbmZpZyk6IEluTWVtb3J5RGF0YWJhc2U8SXZmRW1iZWRkaW5nUm9vdD4ge1xuICAgIGNvbnN0IHJvb3Q6IEl2ZkVtYmVkZGluZ1Jvb3QgPSB7IGNvbmZpZywgY291bnQ6IDAsIGZsYXQ6IHt9LCBzdGVwczoge30sIGNlbnRyb2lkczoge30sIGNlbGxzOiB7fSB9O1xuICAgIHJldHVybiBuZXcgSW5NZW1vcnlEYXRhYmFzZTxJdmZFbWJlZGRpbmdSb290Pihyb290KTtcbn1cblxuZnVuY3Rpb24gcGFkKHZhbHVlOiBzdHJpbmcgfCBudW1iZXIsIHdpZHRoOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIHJldHVybiBTdHJpbmcodmFsdWUpLnBhZFN0YXJ0KHdpZHRoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgICBjb25zdCBjb25maWc6IEl2ZkNvbmZpZyA9IHsgbW9kZWw6IE1PREVMLCBmb3JtYXQ6IEZPUk1BVCwgY2VsbFRhcmdldFNpemU6IDEyOCB9O1xuICAgIGNvbnN0IHJ1bnM6IHsgc2l6ZTogbnVtYmVyOyBiYXRjaDogbnVtYmVyIH1bXSA9IFtcbiAgICAgICAgeyBzaXplOiAxMDAwMCwgYmF0Y2g6IDEgfSxcbiAgICAgICAgeyBzaXplOiAxMDAwMCwgYmF0Y2g6IDEwMCB9LFxuICAgICAgICB7IHNpemU6IDEwMDAwMCwgYmF0Y2g6IDEwMDAgfSxcbiAgICBdO1xuXG4gICAgbGV0IG1heFNpemUgPSAwO1xuICAgIGZvciAoY29uc3QgcnVuIG9mIHJ1bnMpIHtcbiAgICAgICAgaWYgKHJ1bi5zaXplID4gbWF4U2l6ZSkge1xuICAgICAgICAgICAgbWF4U2l6ZSA9IHJ1bi5zaXplO1xuICAgICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGxvYWRTdGFydCA9IERhdGUubm93KCk7XG4gICAgY29uc3QgYWxsSW5wdXRzID0gYXdhaXQgYnVpbGRJbnB1dHMobWF4U2l6ZSk7XG4gICAgY29uc29sZS5sb2coYGxvYWRlZCArIGVuY29kZWQgJHttYXhTaXplfSBlbWJlZGRpbmdzIGluICR7KChEYXRlLm5vdygpIC0gbG9hZFN0YXJ0KSAvIDEwMDApLnRvRml4ZWQoMSl9c1xcbmApO1xuXG4gICAgY29uc29sZS5sb2coYCR7cGFkKFwiYWRkZWRcIiwgNyl9ICR7cGFkKFwiYmF0Y2hcIiwgNSl9IHwgJHtwYWQoXCJzZWNzXCIsIDcpfSAke3BhZChcInJlYWRzXCIsIDgpfSAke3BhZChcIndyaXRlc1wiLCA4KX0gJHtwYWQoXCJkZWxldGVzXCIsIDgpfSAke3BhZChcInJlYWRNQlwiLCA5KX0gJHtwYWQoXCJ3cml0ZU1CXCIsIDgpfSB8IHJlY2FsbGApO1xuICAgIGZvciAoY29uc3QgcnVuIG9mIHJ1bnMpIHtcbiAgICAgICAgY29uc3QgZGF0YWJhc2UgPSBmcmVzaERhdGFiYXNlKGNvbmZpZyk7XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgZm9yIChsZXQgb2Zmc2V0ID0gMDsgb2Zmc2V0IDwgcnVuLnNpemU7IG9mZnNldCArPSBydW4uYmF0Y2gpIHtcbiAgICAgICAgICAgIGluc2VydEVtYmVkZGluZ3MoZGF0YWJhc2UsIGFsbElucHV0cy5zbGljZShvZmZzZXQsIG9mZnNldCArIHJ1bi5iYXRjaCkpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNlY29uZHMgPSAoRGF0ZS5ub3coKSAtIHN0YXJ0KSAvIDEwMDA7XG5cbiAgICAgICAgbGV0IGZvdW5kID0gMDtcbiAgICAgICAgY29uc3Qgc2FtcGxlQ291bnQgPSAxMDA7XG4gICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBzYW1wbGVDb3VudDsgaW5kZXgrKykge1xuICAgICAgICAgICAgY29uc3QgcXVlcnkgPSBhbGxJbnB1dHNbTWF0aC5mbG9vcihpbmRleCAqIHJ1bi5zaXplIC8gc2FtcGxlQ291bnQpXTtcbiAgICAgICAgICAgIGNvbnN0IGhpdHMgPSBzZWFyY2hFbWJlZGRpbmdzKGRhdGFiYXNlLCBxdWVyeS5lbWJlZGRpbmcsIHsgcHJvYmVCdWRnZXQ6IDUxMiwgcmVzdWx0Q291bnQ6IDEgfSk7XG4gICAgICAgICAgICBpZiAoaGl0cyAmJiBoaXRzLmxlbmd0aCAmJiBoaXRzWzBdLnJlZiA9PT0gcXVlcnkucmVmKSB7XG4gICAgICAgICAgICAgICAgZm91bmQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZWNhbGwgPSAoZm91bmQgLyBzYW1wbGVDb3VudCkudG9GaXhlZCgyKTtcbiAgICAgICAgY29uc29sZS5sb2coYCR7cGFkKHJ1bi5zaXplLCA3KX0gJHtwYWQocnVuLmJhdGNoLCA1KX0gfCAke3BhZChzZWNvbmRzLnRvRml4ZWQoMSksIDcpfSAke3BhZChkYXRhYmFzZS5yZWFkQ2FsbHMsIDgpfSAke3BhZChkYXRhYmFzZS53cml0ZUNhbGxzLCA4KX0gJHtwYWQoZGF0YWJhc2UuZGVsZXRlQ2FsbHMsIDgpfSAke3BhZCgoZGF0YWJhc2UuYnl0ZXNSZWFkIC8gMWU2KS50b0ZpeGVkKDApLCA5KX0gJHtwYWQoKGRhdGFiYXNlLmJ5dGVzV3JpdHRlbiAvIDFlNikudG9GaXhlZCgwKSwgOCl9IHwgJHtyZWNhbGx9YCk7XG4gICAgfVxufVxuXG5tYWluKCk7XG4iXX0//=
|
|
81
|
+
/* _JS_SOURCE_HASH = "31db07ffef35ecca7578f435bb6db898fafcf77607d50d5ffd52abaf2d4a1490"; */
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
3
|
+
//exports.removeEmbeddings = exports.insertEmbeddings = exports.searchEmbeddings = exports.rebuildStructure = void 0;
|
|
4
|
+
const Database_1 = require("./Database");
|
|
5
|
+
const transactionSet_1 = require("./transactionSet");
|
|
6
|
+
const embeddingFormats_1 = require("../embeddingFormats");
|
|
7
|
+
// Below this many embeddings we skip the IVF entirely (flat store). 1024 = a clean power of two.
|
|
8
|
+
const FLAT_LIMIT = 1024;
|
|
9
|
+
// Force a from-scratch rebuild once at each of these (multiples of 4 above FLAT_LIMIT, up to ~16k), gated by a step flag so each runs at most once ever.
|
|
10
|
+
const REGENERATE_AT = [4096, 16384];
|
|
11
|
+
const STEP_IVF = "ivf";
|
|
12
|
+
// On delete, the member's exact cell plus this many nearby cells are checked, in case a rebuild left it non-optimal.
|
|
13
|
+
const DELETE_FALLBACK_CELLS = 10;
|
|
14
|
+
const REBALANCE_ITERATIONS = 4;
|
|
15
|
+
function flatStore(database) {
|
|
16
|
+
return (0, Database_1.namespaceDatabase)(database, root => root.flat);
|
|
17
|
+
}
|
|
18
|
+
function centroidStore(database) {
|
|
19
|
+
return (0, Database_1.namespaceDatabase)(database, root => root.centroids);
|
|
20
|
+
}
|
|
21
|
+
function cellStore(database, cellId) {
|
|
22
|
+
return (0, Database_1.namespaceDatabase)(database, root => root.cells[cellId]);
|
|
23
|
+
}
|
|
24
|
+
function readSteps(database) {
|
|
25
|
+
var _a;
|
|
26
|
+
return (_a = database.readData(root => root.steps)) !== null && _a !== void 0 ? _a : {};
|
|
27
|
+
}
|
|
28
|
+
function readCount(database) {
|
|
29
|
+
var _a;
|
|
30
|
+
return (_a = database.readData(root => root.count)) !== null && _a !== void 0 ? _a : 0;
|
|
31
|
+
}
|
|
32
|
+
function rankCellsByCloseness(embedding, centroids) {
|
|
33
|
+
const ranked = [];
|
|
34
|
+
for (const cellId of centroids.keys()) {
|
|
35
|
+
ranked.push({ cellId, closeness: (0, embeddingFormats_1.getCloseness)(embedding, centroids.get(cellId)) });
|
|
36
|
+
}
|
|
37
|
+
ranked.sort((left, right) => right.closeness - left.closeness);
|
|
38
|
+
return ranked.map(entry => entry.cellId);
|
|
39
|
+
}
|
|
40
|
+
// Per-write chance of a full rebuild. Zero at/under the target size, then rises (cubically) past it so cells
|
|
41
|
+
// stay roughly between target and ~2x target.
|
|
42
|
+
function rebalanceProbability(fillRatio) {
|
|
43
|
+
if (fillRatio <= 1) {
|
|
44
|
+
return 0;
|
|
45
|
+
}
|
|
46
|
+
const over = fillRatio - 1;
|
|
47
|
+
return Math.min(1, over * over * over * 0.25);
|
|
48
|
+
}
|
|
49
|
+
// k-means. Decodes every member to a pooled float32 buffer ONCE, then assigns with a plain internal float
|
|
50
|
+
// dot (no getCloseness call — comparing two float vectors is trivial) and keeps centroids as float means,
|
|
51
|
+
// encoding them to StoredEmbedding only at the end. Releases the borrowed buffers when done.
|
|
52
|
+
function clusterMembers(members, clusterCount, config) {
|
|
53
|
+
const memberFloats = [];
|
|
54
|
+
for (const member of members) {
|
|
55
|
+
memberFloats.push((0, embeddingFormats_1.embeddingToFloat32)(member.embedding, true));
|
|
56
|
+
}
|
|
57
|
+
const length = memberFloats.length ? memberFloats[0].length : 0;
|
|
58
|
+
let centroids = [];
|
|
59
|
+
const seedStep = members.length / clusterCount;
|
|
60
|
+
for (let clusterIndex = 0; clusterIndex < clusterCount; clusterIndex++) {
|
|
61
|
+
centroids.push(new Float32Array(memberFloats[Math.floor(clusterIndex * seedStep)]));
|
|
62
|
+
}
|
|
63
|
+
let groups = [];
|
|
64
|
+
for (let iteration = 0; iteration < REBALANCE_ITERATIONS; iteration++) {
|
|
65
|
+
groups = [];
|
|
66
|
+
for (let clusterIndex = 0; clusterIndex < centroids.length; clusterIndex++) {
|
|
67
|
+
groups.push([]);
|
|
68
|
+
}
|
|
69
|
+
for (let memberIndex = 0; memberIndex < memberFloats.length; memberIndex++) {
|
|
70
|
+
const memberFloat = memberFloats[memberIndex];
|
|
71
|
+
let bestIndex = 0;
|
|
72
|
+
let bestDot = -Infinity;
|
|
73
|
+
for (let centroidIndex = 0; centroidIndex < centroids.length; centroidIndex++) {
|
|
74
|
+
const centroidFloat = centroids[centroidIndex];
|
|
75
|
+
let dot = 0;
|
|
76
|
+
for (let dim = 0; dim < length; dim++) {
|
|
77
|
+
dot += memberFloat[dim] * centroidFloat[dim];
|
|
78
|
+
}
|
|
79
|
+
if (dot > bestDot) {
|
|
80
|
+
bestDot = dot;
|
|
81
|
+
bestIndex = centroidIndex;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
groups[bestIndex].push(memberIndex);
|
|
85
|
+
}
|
|
86
|
+
const nextCentroids = [];
|
|
87
|
+
const nextGroups = [];
|
|
88
|
+
for (const group of groups) {
|
|
89
|
+
if (!group.length) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const mean = new Float32Array(length);
|
|
93
|
+
for (const memberIndex of group) {
|
|
94
|
+
const memberFloat = memberFloats[memberIndex];
|
|
95
|
+
for (let dim = 0; dim < length; dim++) {
|
|
96
|
+
mean[dim] += memberFloat[dim];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
let norm = 0;
|
|
100
|
+
for (let dim = 0; dim < length; dim++) {
|
|
101
|
+
norm += mean[dim] * mean[dim];
|
|
102
|
+
}
|
|
103
|
+
const magnitude = Math.sqrt(norm) || 1;
|
|
104
|
+
for (let dim = 0; dim < length; dim++) {
|
|
105
|
+
mean[dim] /= magnitude;
|
|
106
|
+
}
|
|
107
|
+
nextCentroids.push(mean);
|
|
108
|
+
nextGroups.push(group);
|
|
109
|
+
}
|
|
110
|
+
centroids = nextCentroids;
|
|
111
|
+
groups = nextGroups;
|
|
112
|
+
}
|
|
113
|
+
const result = [];
|
|
114
|
+
for (let clusterIndex = 0; clusterIndex < centroids.length; clusterIndex++) {
|
|
115
|
+
const centroid = (0, embeddingFormats_1.encodeEmbedding)({ input: centroids[clusterIndex], format: config.format, model: config.model });
|
|
116
|
+
const cellMembers = [];
|
|
117
|
+
for (const memberIndex of groups[clusterIndex]) {
|
|
118
|
+
cellMembers.push(members[memberIndex]);
|
|
119
|
+
}
|
|
120
|
+
result.push({ centroid, members: cellMembers });
|
|
121
|
+
}
|
|
122
|
+
for (const memberFloat of memberFloats) {
|
|
123
|
+
(0, embeddingFormats_1.releaseFloat32)(memberFloat);
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
// Re-cluster EVERY embedding (flat tier + all cells) into a fresh IVF, clear the flat tier, and mark IVF
|
|
128
|
+
// mode. This is the rearranger: run probabilistically as the set grows, once at each regenerate threshold,
|
|
129
|
+
// and once to upgrade from flat. Reads everything it uses, so it bails (does nothing) if anything isn't
|
|
130
|
+
// synced and the caller's retry re-runs it; no caller cares about its result.
|
|
131
|
+
function rebuildStructure(database) {
|
|
132
|
+
const config = database.readData(root => root.config);
|
|
133
|
+
if (!config)
|
|
134
|
+
return;
|
|
135
|
+
const allMembers = [];
|
|
136
|
+
const flat = (0, transactionSet_1.transactionRead)(flatStore(database));
|
|
137
|
+
if (!flat)
|
|
138
|
+
return;
|
|
139
|
+
for (const ref of flat.keys()) {
|
|
140
|
+
allMembers.push({ ref, embedding: flat.get(ref) });
|
|
141
|
+
}
|
|
142
|
+
const centroids = (0, transactionSet_1.transactionRead)(centroidStore(database));
|
|
143
|
+
if (!centroids)
|
|
144
|
+
return;
|
|
145
|
+
const oldCellIds = Array.from(centroids.keys());
|
|
146
|
+
const cellStores = database.readData(root => oldCellIds.map(cellId => root.cells[cellId]));
|
|
147
|
+
if (!cellStores)
|
|
148
|
+
return;
|
|
149
|
+
for (const store of cellStores) {
|
|
150
|
+
const members = (0, transactionSet_1.replayTransactionStore)(store);
|
|
151
|
+
for (const ref of members.keys()) {
|
|
152
|
+
allMembers.push({ ref, embedding: members.get(ref) });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (!allMembers.length)
|
|
156
|
+
return;
|
|
157
|
+
const clusterCount = Math.max(1, Math.round(allMembers.length / config.cellTargetSize));
|
|
158
|
+
const clusters = clusterMembers(allMembers, clusterCount, config);
|
|
159
|
+
const newCellIds = new Set();
|
|
160
|
+
const centroidWrites = [];
|
|
161
|
+
for (const cluster of clusters) {
|
|
162
|
+
const cellId = (0, embeddingFormats_1.hashEmbedding)(cluster.centroid);
|
|
163
|
+
newCellIds.add(cellId);
|
|
164
|
+
centroidWrites.push({ key: cellId, value: cluster.centroid });
|
|
165
|
+
const memberWrites = cluster.members.map(member => ({ key: member.ref, value: member.embedding }));
|
|
166
|
+
(0, transactionSet_1.transactionMutate)(cellStore(database, cellId), memberWrites);
|
|
167
|
+
}
|
|
168
|
+
for (const oldCellId of oldCellIds) {
|
|
169
|
+
if (newCellIds.has(oldCellId)) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
centroidWrites.push({ key: oldCellId, value: undefined });
|
|
173
|
+
database.deleteData(root => root.cells[oldCellId]);
|
|
174
|
+
}
|
|
175
|
+
(0, transactionSet_1.transactionMutate)(centroidStore(database), centroidWrites);
|
|
176
|
+
database.deleteData(root => root.flat);
|
|
177
|
+
database.writeData(root => root.count, allMembers.length);
|
|
178
|
+
database.writeData(root => root.steps[STEP_IVF], true);
|
|
179
|
+
}
|
|
180
|
+
exports.rebuildStructure = rebuildStructure;
|
|
181
|
+
function searchEmbeddings(database, query, options) {
|
|
182
|
+
const config = database.readData(root => root.config);
|
|
183
|
+
if (!config)
|
|
184
|
+
return undefined;
|
|
185
|
+
const steps = readSteps(database);
|
|
186
|
+
const hits = [];
|
|
187
|
+
if (!steps[STEP_IVF]) {
|
|
188
|
+
const flat = (0, transactionSet_1.transactionRead)(flatStore(database));
|
|
189
|
+
if (!flat)
|
|
190
|
+
return undefined;
|
|
191
|
+
for (const ref of flat.keys()) {
|
|
192
|
+
hits.push({ ref, closeness: (0, embeddingFormats_1.getCloseness)(query, flat.get(ref)) });
|
|
193
|
+
}
|
|
194
|
+
hits.sort((left, right) => right.closeness - left.closeness);
|
|
195
|
+
return hits.slice(0, options.resultCount);
|
|
196
|
+
}
|
|
197
|
+
const centroids = (0, transactionSet_1.transactionRead)(centroidStore(database));
|
|
198
|
+
if (!centroids)
|
|
199
|
+
return undefined;
|
|
200
|
+
if (!centroids.size)
|
|
201
|
+
return [];
|
|
202
|
+
const probeCellCount = Math.max(1, Math.ceil(options.probeBudget / config.cellTargetSize));
|
|
203
|
+
const probeCellIds = rankCellsByCloseness(query, centroids).slice(0, probeCellCount);
|
|
204
|
+
const stores = database.readData(root => probeCellIds.map(cellId => root.cells[cellId]));
|
|
205
|
+
if (!stores)
|
|
206
|
+
return undefined;
|
|
207
|
+
for (const store of stores) {
|
|
208
|
+
const members = (0, transactionSet_1.replayTransactionStore)(store);
|
|
209
|
+
for (const ref of members.keys()) {
|
|
210
|
+
hits.push({ ref, closeness: (0, embeddingFormats_1.getCloseness)(query, members.get(ref)) });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
hits.sort((left, right) => right.closeness - left.closeness);
|
|
214
|
+
return hits.slice(0, options.resultCount);
|
|
215
|
+
}
|
|
216
|
+
exports.searchEmbeddings = searchEmbeddings;
|
|
217
|
+
function insertEmbeddings(database, items) {
|
|
218
|
+
if (!items.length)
|
|
219
|
+
return true;
|
|
220
|
+
const config = database.readData(root => root.config);
|
|
221
|
+
if (!config)
|
|
222
|
+
return undefined;
|
|
223
|
+
const steps = readSteps(database);
|
|
224
|
+
const newCount = readCount(database) + items.length;
|
|
225
|
+
if (!steps[STEP_IVF]) {
|
|
226
|
+
const flatWrites = items.map(item => ({ key: item.ref, value: item.embedding }));
|
|
227
|
+
(0, transactionSet_1.transactionMutate)(flatStore(database), flatWrites);
|
|
228
|
+
database.writeData(root => root.count, newCount);
|
|
229
|
+
if (newCount > FLAT_LIMIT) {
|
|
230
|
+
rebuildStructure(database);
|
|
231
|
+
}
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
const centroids = (0, transactionSet_1.transactionRead)(centroidStore(database));
|
|
235
|
+
if (!centroids)
|
|
236
|
+
return undefined;
|
|
237
|
+
const itemsByCell = new Map();
|
|
238
|
+
for (const item of items) {
|
|
239
|
+
const cellId = rankCellsByCloseness(item.embedding, centroids)[0];
|
|
240
|
+
let group = itemsByCell.get(cellId);
|
|
241
|
+
if (!group) {
|
|
242
|
+
group = [];
|
|
243
|
+
itemsByCell.set(cellId, group);
|
|
244
|
+
}
|
|
245
|
+
group.push(item);
|
|
246
|
+
}
|
|
247
|
+
for (const cellId of itemsByCell.keys()) {
|
|
248
|
+
const group = itemsByCell.get(cellId);
|
|
249
|
+
const memberWrites = group.map(item => ({ key: item.ref, value: item.embedding }));
|
|
250
|
+
(0, transactionSet_1.transactionMutate)(cellStore(database, cellId), memberWrites);
|
|
251
|
+
}
|
|
252
|
+
database.writeData(root => root.count, newCount);
|
|
253
|
+
let regenerated = false;
|
|
254
|
+
for (const threshold of REGENERATE_AT) {
|
|
255
|
+
const stepName = "regen" + threshold;
|
|
256
|
+
if (!steps[stepName] && newCount > threshold) {
|
|
257
|
+
rebuildStructure(database);
|
|
258
|
+
database.writeData(root => root.steps[stepName], true);
|
|
259
|
+
regenerated = true;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (!regenerated) {
|
|
263
|
+
const averageFill = newCount / Math.max(1, centroids.size) / config.cellTargetSize;
|
|
264
|
+
if (Math.random() < rebalanceProbability(averageFill)) {
|
|
265
|
+
rebuildStructure(database);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
exports.insertEmbeddings = insertEmbeddings;
|
|
271
|
+
function removeEmbeddings(database, items) {
|
|
272
|
+
if (!items.length)
|
|
273
|
+
return true;
|
|
274
|
+
const steps = readSteps(database);
|
|
275
|
+
const count = readCount(database);
|
|
276
|
+
if (!steps[STEP_IVF]) {
|
|
277
|
+
const flatDeletes = items.map(item => ({ key: item.ref, value: undefined }));
|
|
278
|
+
(0, transactionSet_1.transactionMutate)(flatStore(database), flatDeletes);
|
|
279
|
+
database.writeData(root => root.count, Math.max(0, count - items.length));
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
const centroids = (0, transactionSet_1.transactionRead)(centroidStore(database));
|
|
283
|
+
if (!centroids)
|
|
284
|
+
return undefined;
|
|
285
|
+
if (!centroids.size)
|
|
286
|
+
return true;
|
|
287
|
+
const candidatesByItem = [];
|
|
288
|
+
const candidateSet = new Set();
|
|
289
|
+
for (const item of items) {
|
|
290
|
+
const cellIds = rankCellsByCloseness(item.embedding, centroids).slice(0, 1 + DELETE_FALLBACK_CELLS);
|
|
291
|
+
candidatesByItem.push({ ref: item.ref, cellIds });
|
|
292
|
+
for (const cellId of cellIds) {
|
|
293
|
+
candidateSet.add(cellId);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const candidateCellIds = Array.from(candidateSet);
|
|
297
|
+
const stores = database.readData(root => candidateCellIds.map(cellId => root.cells[cellId]));
|
|
298
|
+
if (!stores)
|
|
299
|
+
return undefined;
|
|
300
|
+
const membersByCell = new Map();
|
|
301
|
+
for (let index = 0; index < candidateCellIds.length; index++) {
|
|
302
|
+
membersByCell.set(candidateCellIds[index], (0, transactionSet_1.replayTransactionStore)(stores[index]));
|
|
303
|
+
}
|
|
304
|
+
const deletesByCell = new Map();
|
|
305
|
+
for (const candidate of candidatesByItem) {
|
|
306
|
+
for (const cellId of candidate.cellIds) {
|
|
307
|
+
const members = membersByCell.get(cellId);
|
|
308
|
+
if (!members || !members.has(candidate.ref)) {
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
let refs = deletesByCell.get(cellId);
|
|
312
|
+
if (!refs) {
|
|
313
|
+
refs = [];
|
|
314
|
+
deletesByCell.set(cellId, refs);
|
|
315
|
+
}
|
|
316
|
+
refs.push(candidate.ref);
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
let deletedCount = 0;
|
|
321
|
+
for (const cellId of deletesByCell.keys()) {
|
|
322
|
+
const refs = deletesByCell.get(cellId);
|
|
323
|
+
deletedCount += refs.length;
|
|
324
|
+
const memberDeletes = refs.map(ref => ({ key: ref, value: undefined }));
|
|
325
|
+
(0, transactionSet_1.transactionMutate)(cellStore(database, cellId), memberDeletes);
|
|
326
|
+
}
|
|
327
|
+
if (deletedCount) {
|
|
328
|
+
database.writeData(root => root.count, Math.max(0, count - deletedCount));
|
|
329
|
+
}
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
exports.removeEmbeddings = removeEmbeddings;
|
|
333
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXZmRW1iZWRkaW5nRGF0YWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpdmZFbWJlZGRpbmdEYXRhYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5Q0FBeUQ7QUFDekQscURBQW1IO0FBQ25ILDBEQUF5SjtBQTBCekosaUdBQWlHO0FBQ2pHLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQztBQUN4Qix5SkFBeUo7QUFDekosTUFBTSxhQUFhLEdBQUcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDcEMsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDO0FBQ3ZCLHFIQUFxSDtBQUNySCxNQUFNLHFCQUFxQixHQUFHLEVBQUUsQ0FBQztBQUNqQyxNQUFNLG9CQUFvQixHQUFHLENBQUMsQ0FBQztBQUUvQixTQUFTLFNBQVMsQ0FBQyxRQUFvQztJQUNuRCxPQUFPLElBQUEsNEJBQWlCLEVBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzFELENBQUM7QUFDRCxTQUFTLGFBQWEsQ0FBQyxRQUFvQztJQUN2RCxPQUFPLElBQUEsNEJBQWlCLEVBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQy9ELENBQUM7QUFDRCxTQUFTLFNBQVMsQ0FBQyxRQUFvQyxFQUFFLE1BQWM7SUFDbkUsT0FBTyxJQUFBLDRCQUFpQixFQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUNuRSxDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsUUFBb0M7O0lBQ25ELE9BQU8sTUFBQSxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxtQ0FBSSxFQUFFLENBQUM7QUFDdkQsQ0FBQztB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QUFZLENBQUMsQ0FBQyxDQUFDO0lBQzlFLENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNoQixDQUFDO0FBakVELDRDQWlFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERhdGFiYXNlLCBuYW1lc3BhY2VEYXRhYmFzZSB9IGZyb20gXCIuL0RhdGFiYXNlXCI7XG5pbXBvcnQgeyBUcmFuc2FjdGlvblNldFN0b3JlLCB0cmFuc2FjdGlvblJlYWQsIHRyYW5zYWN0aW9uTXV0YXRlLCByZXBsYXlUcmFuc2FjdGlvblN0b3JlIH0gZnJvbSBcIi4vdHJhbnNhY3Rpb25TZXRcIjtcbmltcG9ydCB7IFN0b3JlZEVtYmVkZGluZywgRW1iZWRkaW5nRm9ybWF0LCBnZXRDbG9zZW5lc3MsIGVtYmVkZGluZ1RvRmxvYXQzMiwgcmVsZWFzZUZsb2F0MzIsIGVuY29kZUVtYmVkZGluZywgaGFzaEVtYmVkZGluZyB9IGZyb20gXCIuLi9lbWJlZGRpbmdGb3JtYXRzXCI7XG5cbmV4cG9ydCB0eXBlIEl2ZkNvbmZpZyA9IHtcbiAgICBtb2RlbDogc3RyaW5nO1xuICAgIGZvcm1hdDogRW1iZWRkaW5nRm9ybWF0O1xuICAgIC8vIFRhcmdldCBudW1iZXIgb2YgZW1iZWRkaW5ncyBwZXIgY2VsbC5cbiAgICBjZWxsVGFyZ2V0U2l6ZTogbnVtYmVyO1xufTtcblxuLy8gVGllcmVkIHN0b3JhZ2UuIEJlbG93IEZMQVRfTElNSVQgZW1iZWRkaW5ncyB0aGUgd2hvbGUgc2V0IGxpdmVzIGluIG9uZSBmbGF0IHRyYW5zYWN0aW9uIHNldCAobm8gSVZGKTtcbi8vIG9uY2UgaXQgZ3Jvd3MgcGFzdCB0aGF0IHdlIGJ1aWxkIHRoZSBJVkYgKGNlbnRyb2lkcyArIHBlci1jZWxsIHNldHMpIGFuZCBzdGF5IHRoZXJlIGZvcmV2ZXIuIGBjb3VudGAgaXNcbi8vIHRoZSBsaXZlIGVtYmVkZGluZyBjb3VudCAocmUtZGVyaXZlZCBleGFjdGx5IG9uIGEgcmVidWlsZCkuIGBzdGVwc2AgcmVjb3JkcyBvbmUtdGltZSB1cGdyYWRlcyB0aGF0IG11c3Rcbi8vIG5ldmVyIHJlLXJ1biBldmVuIGlmIHRoZSBzZXQgbGF0ZXIgc2hyaW5rcyBhbmQgcmVncm93cy5cbmV4cG9ydCB0eXBlIEl2ZkVtYmVkZGluZ1Jvb3QgPSB7XG4gICAgY29uZmlnOiBJdmZDb25maWc7XG4gICAgY291bnQ6IG51bWJlcjtcbiAgICBmbGF0OiBUcmFuc2FjdGlvblNldFN0b3JlPFN0b3JlZEVtYmVkZGluZz47XG4gICAgc3RlcHM6IHsgW3N0ZXA6IHN0cmluZ106IGJvb2xlYW4gfTtcbiAgICBjZW50cm9pZHM6IFRyYW5zYWN0aW9uU2V0U3RvcmU8U3RvcmVkRW1iZWRkaW5nPjtcbiAgICBjZWxsczogeyBbY2VsbElkOiBzdHJpbmddOiBUcmFuc2FjdGlvblNldFN0b3JlPFN0b3JlZEVtYmVkZGluZz4gfTtcbn07XG5cbmV4cG9ydCB0eXBlIEVtYmVkZGluZ0lucHV0ID0geyByZWY6IHN0cmluZzsgZW1iZWRkaW5nOiBTdG9yZWRFbWJlZGRpbmcgfTtcbmV4cG9ydCB0eXBlIFNlYXJjaEhpdCA9IHsgcmVmOiBzdHJpbmc7IGNsb3NlbmVzczogbnVtYmVyIH07XG50eXBlIENlbGxFbnRyeSA9IHsgcmVmOiBzdHJpbmc7IGVtYmVkZGluZzogU3RvcmVkRW1iZWRkaW5nIH07XG5cbi8vIEJlbG93IHRoaXMgbWFueSBlbWJlZGRpbmdzIHdlIHNraXAgdGhlIElWRiBlbnRpcmVseSAoZmxhdCBzdG9yZSkuIDEwMjQgPSBhIGNsZWFuIHBvd2VyIG9mIHR3by5cbmNvbnN0IEZMQVRfTElNSVQgPSAxMDI0O1xuLy8gRm9yY2UgYSBmcm9tLXNjcmF0Y2ggcmVidWlsZCBvbmNlIGF0IGVhY2ggb2YgdGhlc2UgKG11bHRpcGxlcyBvZiA0IGFib3ZlIEZMQVRfTElNSVQsIHVwIHRvIH4xNmspLCBnYXRlZCBieSBhIHN0ZXAgZmxhZyBzbyBlYWNoIHJ1bnMgYXQgbW9zdCBvbmNlIGV2ZXIuXG5jb25zdCBSRUdFTkVSQVRFX0FUID0gWzQwOTYsIDE2Mzg0XTtcbmNvbnN0IFNURVBfSVZGID0gXCJpdmZcIjtcbi8vIE9uIGRlbGV0ZSwgdGhlIG1lbWJlcidzIGV4YWN0IGNlbGwgcGx1cyB0aGlzIG1hbnkgbmVhcmJ5IGNlbGxzIGFyZSBjaGVja2VkLCBpbiBjYXNlIGEgcmVidWlsZCBsZWZ0IGl0IG5vbi1vcHRpbWFsLlxuY29uc3QgREVMRVRFX0ZBTExCQUNLX0NFTExTID0gMTA7XG5jb25zdCBSRUJBTEFOQ0VfSVRFUkFUSU9OUyA9IDQ7XG5cbmZ1bmN0aW9uIGZsYXRTdG9yZShkYXRhYmFzZTogRGF0YWJhc2U8SXZmRW1iZWRkaW5nUm9vdD4pOiBEYXRhYmFzZTxUcmFuc2FjdGlvblNldFN0b3JlPFN0b3JlZEVtYmVkZGluZz4+IHtcbiAgICByZXR1cm4gbmFtZXNwYWNlRGF0YWJhc2UoZGF0YWJhc2UsIHJvb3QgPT4gcm9vdC5mbGF0KTtcbn1cbmZ1bmN0aW9uIGNlbnRyb2lkU3RvcmUoZGF0YWJhc2U6IERhdGFiYXNlPEl2ZkVtYmVkZGluZ1Jvb3Q+KTogRGF0YWJhc2U8VHJhbnNhY3Rpb25TZXRTdG9yZTxTdG9yZWRFbWJlZGRpbmc+PiB7XG4gICAgcmV0dXJuIG5hbWVzcGFjZURhdGFiYXNlKGRhdGFiYXNlLCByb290ID0+IHJvb3QuY2VudHJvaWRzKTtcbn1cbmZ1bmN0aW9uIGNlbGxTdG9yZShkYXRhYmFzZTogRGF0YWJhc2U8SXZmRW1iZWRkaW5nUm9vdD4sIGNlbGxJZDogc3RyaW5nKTogRGF0YWJhc2U8VHJhbnNhY3Rpb25TZXRTdG9yZTxTdG9yZWRFbWJlZGRpbmc+PiB7XG4gICAgcmV0dXJuIG5hbWVzcGFjZURhdGFiYXNlKGRhdGFiYXNlLCByb290ID0+IHJvb3QuY2VsbHNbY2VsbElkXSk7XG59XG5cbmZ1bmN0aW9uIHJlYWRTdGVwcyhkYXRhYmFzZTogRGF0YWJhc2U8SXZmRW1iZWRkaW5nUm9vdD4pOiB7IFtzdGVwOiBzdHJpbmddOiBib29sZWFuIH0ge1xuICAgIHJldHVybiBkYXRhYmFzZS5yZWFkRGF0YShyb290ID0+IHJvb3Quc3RlcHMpID8/IHt9O1xufVxuZnVuY3Rpb24gcmVhZENvdW50KGRhdGFiYXNlOiBEYXRhYmFzZTxJdmZFbWJlZGRpbmdSb290Pik6IG51bWJlciB7XG4gICAgcmV0dXJuIGRhdGFiYXNlLnJlYWREYXRhKHJvb3QgPT4gcm9vdC5jb3VudCkgPz8gMDtcbn1cblxuZnVuY3Rpb24gcmFua0NlbGxzQnlDbG9zZW5lc3MoZW1iZWRkaW5nOiBTdG9yZWRFbWJlZGRpbmcsIGNlbnRyb2lkczogTWFwPHN0cmluZywgU3RvcmVkRW1iZWRkaW5nPik6IHN0cmluZ1tdIHtcbiAgICBjb25zdCByYW5rZWQ6IHsgY2VsbElkOiBzdHJpbmc7IGNsb3NlbmVzczogbnVtYmVyIH1bXSA9IFtdO1xuICAgIGZvciAoY29uc3QgY2VsbElkIG9mIGNlbnRyb2lkcy5rZXlzKCkpIHtcbiAgICAgICAgcmFua2VkLnB1c2goeyBjZWxsSWQsIGNsb3NlbmVzczogZ2V0Q2xvc2VuZXNzKGVtYmVkZGluZywgY2VudHJvaWRzLmdldChjZWxsSWQpISkgfSk7XG4gICAgfVxuICAgIHJhbmtlZC5zb3J0KChsZWZ0LCByaWdodCkgPT4gcmlnaHQuY2xvc2VuZXNzIC0gbGVmdC5jbG9zZW5lc3MpO1xuICAgIHJldHVybiByYW5rZWQubWFwKGVudHJ5ID0+IGVudHJ5LmNlbGxJZCk7XG59XG5cbi8vIFBlci13cml0ZSBjaGFuY2Ugb2YgYSBmdWxsIHJlYnVpbGQuIFplcm8gYXQvdW5kZXIgdGhlIHRhcmdldCBzaXplLCB0aGVuIHJpc2VzIChjdWJpY2FsbHkpIHBhc3QgaXQgc28gY2VsbHNcbi8vIHN0YXkgcm91Z2hseSBiZXR3ZWVuIHRhcmdldCBhbmQgfjJ4IHRhcmdldC5cbmZ1bmN0aW9uIHJlYmFsYW5jZVByb2JhYmlsaXR5KGZpbGxSYXRpbzogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAoZmlsbFJhdGlvIDw9IDEpIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGNvbnN0IG92ZXIgPSBmaWxsUmF0aW8gLSAxO1xuICAgIHJldHVybiBNYXRoLm1pbigxLCBvdmVyICogb3ZlciAqIG92ZXIgKiAwLjI1KTtcbn1cblxuLy8gay1tZWFucy4gRGVjb2RlcyBldmVyeSBtZW1iZXIgdG8gYSBwb29sZWQgZmxvYXQzMiBidWZmZXIgT05DRSwgdGhlbiBhc3NpZ25zIHdpdGggYSBwbGFpbiBpbnRlcm5hbCBmbG9hdFxuLy8gZG90IChubyBnZXRDbG9zZW5lc3MgY2FsbCDigJQgY29tcGFyaW5nIHR3byBmbG9hdCB2ZWN0b3JzIGlzIHRyaXZpYWwpIGFuZCBrZWVwcyBjZW50cm9pZHMgYXMgZmxvYXQgbWVhbnMsXG4vLyBlbmNvZGluZyB0aGVtIHRvIFN0b3JlZEVtYmVkZGluZyBvbmx5IGF0IHRoZSBlbmQuIFJlbGVhc2VzIHRoZSBib3Jyb3dlZCBidWZmZXJzIHdoZW4gZG9uZS5cbmZ1bmN0aW9uIGNsdXN0ZXJNZW1iZXJzKG1lbWJlcnM6IENlbGxFbnRyeVtdLCBjbHVzdGVyQ291bnQ6IG51bWJlciwgY29uZmlnOiBJdmZDb25maWcpOiB7IGNlbnRyb2lkOiBTdG9yZWRFbWJlZGRpbmc7IG1lbWJlcnM6IENlbGxFbnRyeVtdIH1bXSB7XG4gICAgY29uc3QgbWVtYmVyRmxvYXRzOiBGbG9hdDMyQXJyYXlbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgbWVtYmVyIG9mIG1lbWJlcnMpIHtcbiAgICAgICAgbWVtYmVyRmxvYXRzLnB1c2goZW1iZWRkaW5nVG9GbG9hdDMyKG1lbWJlci5lbWJlZGRpbmcsIHRydWUpKTtcbiAgICB9XG4gICAgY29uc3QgbGVuZ3RoID0gbWVtYmVyRmxvYXRzLmxlbmd0aCA/IG1lbWJlckZsb2F0c1swXS5sZW5ndGggOiAwO1xuICAgIGxldCBjZW50cm9pZHM6IEZsb2F0MzJBcnJheVtdID0gW107XG4gICAgY29uc3Qgc2VlZFN0ZXAgPSBtZW1iZXJzLmxlbmd0aCAvIGNsdXN0ZXJDb3VudDtcbiAgICBmb3IgKGxldCBjbHVzdGVySW5kZXggPSAwOyBjbHVzdGVySW5kZXggPCBjbHVzdGVyQ291bnQ7IGNsdXN0ZXJJbmRleCsrKSB7XG4gICAgICAgIGNlbnRyb2lkcy5wdXNoKG5ldyBGbG9hdDMyQXJyYXkobWVtYmVyRmxvYXRzW01hdGguZmxvb3IoY2x1c3RlckluZGV4ICogc2VlZFN0ZXApXSkpO1xuICAgIH1cbiAgICBsZXQgZ3JvdXBzOiBudW1iZXJbXVtdID0gW107XG4gICAgZm9yIChsZXQgaXRlcmF0aW9uID0gMDsgaXRlcmF0aW9uIDwgUkVCQUxBTkNFX0lURVJBVElPTlM7IGl0ZXJhdGlvbisrKSB7XG4gICAgICAgIGdyb3VwcyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBjbHVzdGVySW5kZXggPSAwOyBjbHVzdGVySW5kZXggPCBjZW50cm9pZHMubGVuZ3RoOyBjbHVzdGVySW5kZXgrKykge1xuICAgICAgICAgICAgZ3JvdXBzLnB1c2goW10pO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IG1lbWJlckluZGV4ID0gMDsgbWVtYmVySW5kZXggPCBtZW1iZXJGbG9hdHMubGVuZ3RoOyBtZW1iZXJJbmRleCsrKSB7XG4gICAgICAgICAgICBjb25zdCBtZW1iZXJGbG9hdCA9IG1lbWJlckZsb2F0c1ttZW1iZXJJbmRleF07XG4gICAgICAgICAgICBsZXQgYmVzdEluZGV4ID0gMDtcbiAgICAgICAgICAgIGxldCBiZXN0RG90ID0gLUluZmluaXR5O1xuICAgICAgICAgICAgZm9yIChsZXQgY2VudHJvaWRJbmRleCA9IDA7IGNlbnRyb2lkSW5kZXggPCBjZW50cm9pZHMubGVuZ3RoOyBjZW50cm9pZEluZGV4KyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjZW50cm9pZEZsb2F0ID0gY2VudHJvaWRzW2NlbnRyb2lkSW5kZXhdO1xuICAgICAgICAgICAgICAgIGxldCBkb3QgPSAwO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGxlbmd0aDsgZGltKyspIHtcbiAgICAgICAgICAgICAgICAgICAgZG90ICs9IG1lbWJlckZsb2F0W2RpbV0gKiBjZW50cm9pZEZsb2F0W2RpbV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChkb3QgPiBiZXN0RG90KSB7XG4gICAgICAgICAgICAgICAgICAgIGJlc3REb3QgPSBkb3Q7XG4gICAgICAgICAgICAgICAgICAgIGJlc3RJbmRleCA9IGNlbnRyb2lkSW5kZXg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZ3JvdXBzW2Jlc3RJbmRleF0ucHVzaChtZW1iZXJJbmRleCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbmV4dENlbnRyb2lkczogRmxvYXQzMkFycmF5W10gPSBbXTtcbiAgICAgICAgY29uc3QgbmV4dEdyb3VwczogbnVtYmVyW11bXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGdyb3VwIG9mIGdyb3Vwcykge1xuICAgICAgICAgICAgaWYgKCFncm91cC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG1lYW4gPSBuZXcgRmxvYXQzMkFycmF5KGxlbmd0aCk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG1lbWJlckluZGV4IG9mIGdyb3VwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbWVtYmVyRmxvYXQgPSBtZW1iZXJGbG9hdHNbbWVtYmVySW5kZXhdO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGxlbmd0aDsgZGltKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbWVhbltkaW1dICs9IG1lbWJlckZsb2F0W2RpbV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGV0IG5vcm0gPSAwO1xuICAgICAgICAgICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwgbGVuZ3RoOyBkaW0rKykge1xuICAgICAgICAgICAgICAgIG5vcm0gKz0gbWVhbltkaW1dICogbWVhbltkaW1dO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgbWFnbml0dWRlID0gTWF0aC5zcXJ0KG5vcm0pIHx8IDE7XG4gICAgICAgICAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBsZW5ndGg7IGRpbSsrKSB7XG4gICAgICAgICAgICAgICAgbWVhbltkaW1dIC89IG1hZ25pdHVkZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5leHRDZW50cm9pZHMucHVzaChtZWFuKTtcbiAgICAgICAgICAgIG5leHRHcm91cHMucHVzaChncm91cCk7XG4gICAgICAgIH1cbiAgICAgICAgY2VudHJvaWRzID0gbmV4dENlbnRyb2lkcztcbiAgICAgICAgZ3JvdXBzID0gbmV4dEdyb3VwcztcbiAgICB9XG4gICAgY29uc3QgcmVzdWx0OiB7IGNlbnRyb2lkOiBTdG9yZWRFbWJlZGRpbmc7IG1lbWJlcnM6IENlbGxFbnRyeVtdIH1bXSA9IFtdO1xuICAgIGZvciAobGV0IGNsdXN0ZXJJbmRleCA9IDA7IGNsdXN0ZXJJbmRleCA8IGNlbnRyb2lkcy5sZW5ndGg7IGNsdXN0ZXJJbmRleCsrKSB7XG4gICAgICAgIGNvbnN0IGNlbnRyb2lkID0gZW5jb2RlRW1iZWRkaW5nKHsgaW5wdXQ6IGNlbnRyb2lkc1tjbHVzdGVySW5kZXhdLCBmb3JtYXQ6IGNvbmZpZy5mb3JtYXQsIG1vZGVsOiBjb25maWcubW9kZWwgfSk7XG4gICAgICAgIGNvbnN0IGNlbGxNZW1iZXJzOiBDZWxsRW50cnlbXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IG1lbWJlckluZGV4IG9mIGdyb3Vwc1tjbHVzdGVySW5kZXhdKSB7XG4gICAgICAgICAgICBjZWxsTWVtYmVycy5wdXNoKG1lbWJlcnNbbWVtYmVySW5kZXhdKTtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQucHVzaCh7IGNlbnRyb2lkLCBtZW1iZXJzOiBjZWxsTWVtYmVycyB9KTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBtZW1iZXJGbG9hdCBvZiBtZW1iZXJGbG9hdHMpIHtcbiAgICAgICAgcmVsZWFzZUZsb2F0MzIobWVtYmVyRmxvYXQpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vLyBSZS1jbHVzdGVyIEVWRVJZIGVtYmVkZGluZyAoZmxhdCB0aWVyICsgYWxsIGNlbGxzKSBpbnRvIGEgZnJlc2ggSVZGLCBjbGVhciB0aGUgZmxhdCB0aWVyLCBhbmQgbWFyayBJVkZcbi8vIG1vZGUuIFRoaXMgaXMgdGhlIHJlYXJyYW5nZXI6IHJ1biBwcm9iYWJpbGlzdGljYWxseSBhcyB0aGUgc2V0IGdyb3dzLCBvbmNlIGF0IGVhY2ggcmVnZW5lcmF0ZSB0aHJlc2hvbGQsXG4vLyBhbmQgb25jZSB0byB1cGdyYWRlIGZyb20gZmxhdC4gUmVhZHMgZXZlcnl0aGluZyBpdCB1c2VzLCBzbyBpdCBiYWlscyAoZG9lcyBub3RoaW5nKSBpZiBhbnl0aGluZyBpc24ndFxuLy8gc3luY2VkIGFuZCB0aGUgY2FsbGVyJ3MgcmV0cnkgcmUtcnVucyBpdDsgbm8gY2FsbGVyIGNhcmVzIGFib3V0IGl0cyByZXN1bHQuXG5leHBvcnQgZnVuY3Rpb24gcmVidWlsZFN0cnVjdHVyZShkYXRhYmFzZTogRGF0YWJhc2U8SXZmRW1iZWRkaW5nUm9vdD4pOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWcgPSBkYXRhYmFzZS5yZWFkRGF0YShyb290ID0+IHJvb3QuY29uZmlnKTtcbiAgICBpZiAoIWNvbmZpZykgcmV0dXJuO1xuXG4gICAgY29uc3QgYWxsTWVtYmVyczogQ2VsbEVudHJ5W10gPSBbXTtcbiAgICBjb25zdCBmbGF0ID0gdHJhbnNhY3Rpb25SZWFkKGZsYXRTdG9yZShkYXRhYmFzZSkpO1xuICAgIGlmICghZmxhdCkgcmV0dXJuO1xuICAgIGZvciAoY29uc3QgcmVmIG9mIGZsYXQua2V5cygpKSB7XG4gICAgICAgIGFsbE1lbWJlcnMucHVzaCh7IHJlZiwgZW1iZWRkaW5nOiBmbGF0LmdldChyZWYpISB9KTtcbiAgICB9XG4gICAgY29uc3QgY2VudHJvaWRzID0gdHJhbnNhY3Rpb25SZWFkKGNlbnRyb2lkU3RvcmUoZGF0YWJhc2UpKTtcbiAgICBpZiAoIWNlbnRyb2lkcykgcmV0dXJuO1xuICAgIGNvbnN0IG9sZENlbGxJZHMgPSBBcnJheS5mcm9tKGNlbnRyb2lkcy5rZXlzKCkpO1xuICAgIGNvbnN0IGNlbGxTdG9yZXMgPSBkYXRhYmFzZS5yZWFkRGF0YShyb290ID0+IG9sZENlbGxJZHMubWFwKGNlbGxJZCA9PiByb290LmNlbGxzW2NlbGxJZF0pKTtcbiAgICBpZiAoIWNlbGxTdG9yZXMpIHJldHVybjtcbiAgICBmb3IgKGNvbnN0IHN0b3JlIG9mIGNlbGxTdG9yZXMpIHtcbiAgICAgICAgY29uc3QgbWVtYmVycyA9IHJlcGxheVRyYW5zYWN0aW9uU3RvcmU8U3RvcmVkRW1iZWRkaW5nPihzdG9yZSk7XG4gICAgICAgIGZvciAoY29uc3QgcmVmIG9mIG1lbWJlcnMua2V5cygpKSB7XG4gICAgICAgICAgICBhbGxNZW1iZXJzLnB1c2goeyByZWYsIGVtYmVkZGluZzogbWVtYmVycy5nZXQocmVmKSEgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFhbGxNZW1iZXJzLmxlbmd0aCkgcmV0dXJuO1xuXG4gICAgY29uc3QgY2x1c3RlckNvdW50ID0gTWF0aC5tYXgoMSwgTWF0aC5yb3VuZChhbGxNZW1iZXJzLmxlbmd0aCAvIGNvbmZpZy5jZWxsVGFyZ2V0U2l6ZSkpO1xuICAgIGNvbnN0IGNsdXN0ZXJzID0gY2x1c3Rlck1lbWJlcnMoYWxsTWVtYmVycywgY2x1c3RlckNvdW50LCBjb25maWcpO1xuXG4gICAgY29uc3QgbmV3Q2VsbElkcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIGNvbnN0IGNlbnRyb2lkV3JpdGVzOiB7IGtleTogc3RyaW5nOyB2YWx1ZTogU3RvcmVkRW1iZWRkaW5nIHwgdW5kZWZpbmVkIH1bXSA9IFtdO1xuICAgIGZvciAoY29uc3QgY2x1c3RlciBvZiBjbHVzdGVycykge1xuICAgICAgICBjb25zdCBjZWxsSWQgPSBoYXNoRW1iZWRkaW5nKGNsdXN0ZXIuY2VudHJvaWQpO1xuICAgICAgICBuZXdDZWxsSWRzLmFkZChjZWxsSWQpO1xuICAgICAgICBjZW50cm9pZFdyaXRlcy5wdXNoKHsga2V5OiBjZWxsSWQsIHZhbHVlOiBjbHVzdGVyLmNlbnRyb2lkIH0pO1xuICAgICAgICBjb25zdCBtZW1iZXJXcml0ZXMgPSBjbHVzdGVyLm1lbWJlcnMubWFwKG1lbWJlciA9PiAoeyBrZXk6IG1lbWJlci5yZWYsIHZhbHVlOiBtZW1iZXIuZW1iZWRkaW5nIH0pKTtcbiAgICAgICAgdHJhbnNhY3Rpb25NdXRhdGUoY2VsbFN0b3JlKGRhdGFiYXNlLCBjZWxsSWQpLCBtZW1iZXJXcml0ZXMpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IG9sZENlbGxJZCBvZiBvbGRDZWxsSWRzKSB7XG4gICAgICAgIGlmIChuZXdDZWxsSWRzLmhhcyhvbGRDZWxsSWQpKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjZW50cm9pZFdyaXRlcy5wdXNoKHsga2V5OiBvbGRDZWxsSWQsIHZhbHVlOiB1bmRlZmluZWQgfSk7XG4gICAgICAgIGRhdGFiYXNlLmRlbGV0ZURhdGEocm9vdCA9PiByb290LmNlbGxzW29sZENlbGxJZF0pO1xuICAgIH1cbiAgICB0cmFuc2FjdGlvbk11dGF0ZShjZW50cm9pZFN0b3JlKGRhdGFiYXNlKSwgY2VudHJvaWRXcml0ZXMpO1xuICAgIGRhdGFiYXNlLmRlbGV0ZURhdGEocm9vdCA9PiByb290LmZsYXQpO1xuICAgIGRhdGFiYXNlLndyaXRlRGF0YShyb290ID0+IHJvb3QuY291bnQsIGFsbE1lbWJlcnMubGVuZ3RoKTtcbiAgICBkYXRhYmFzZS53cml0ZURhdGEocm9vdCA9PiByb290LnN0ZXBzW1NURVBfSVZGXSwgdHJ1ZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2hFbWJlZGRpbmdzKFxuICAgIGRhdGFiYXNlOiBEYXRhYmFzZTxJdmZFbWJlZGRpbmdSb290PixcbiAgICBxdWVyeTogU3RvcmVkRW1iZWRkaW5nLFxuICAgIG9wdGlvbnM6IHsgcHJvYmVCdWRnZXQ6IG51bWJlcjsgcmVzdWx0Q291bnQ6IG51bWJlciB9LFxuKTogU2VhcmNoSGl0W10gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGNvbmZpZyA9IGRhdGFiYXNlLnJlYWREYXRhKHJvb3QgPT4gcm9vdC5jb25maWcpO1xuICAgIGlmICghY29uZmlnKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHN0ZXBzID0gcmVhZFN0ZXBzKGRhdGFiYXNlKTtcblxuICAgIGNvbnN0IGhpdHM6IFNlYXJjaEhpdFtdID0gW107XG4gICAgaWYgKCFzdGVwc1tTVEVQX0lWRl0pIHtcbiAgICAgICAgY29uc3QgZmxhdCA9IHRyYW5zYWN0aW9uUmVhZChmbGF0U3RvcmUoZGF0YWJhc2UpKTtcbiAgICAgICAgaWYgKCFmbGF0KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICBmb3IgKGNvbnN0IHJlZiBvZiBmbGF0LmtleXMoKSkge1xuICAgICAgICAgICAgaGl0cy5wdXNoKHsgcmVmLCBjbG9zZW5lc3M6IGdldENsb3NlbmVzcyhxdWVyeSwgZmxhdC5nZXQocmVmKSEpIH0pO1xuICAgICAgICB9XG4gICAgICAgIGhpdHMuc29ydCgobGVmdCwgcmlnaHQpID0+IHJpZ2h0LmNsb3NlbmVzcyAtIGxlZnQuY2xvc2VuZXNzKTtcbiAgICAgICAgcmV0dXJuIGhpdHMuc2xpY2UoMCwgb3B0aW9ucy5yZXN1bHRDb3VudCk7XG4gICAgfVxuXG4gICAgY29uc3QgY2VudHJvaWRzID0gdHJhbnNhY3Rpb25SZWFkKGNlbnRyb2lkU3RvcmUoZGF0YWJhc2UpKTtcbiAgICBpZiAoIWNlbnRyb2lkcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAoIWNlbnRyb2lkcy5zaXplKSByZXR1cm4gW107XG4gICAgY29uc3QgcHJvYmVDZWxsQ291bnQgPSBNYXRoLm1heCgxLCBNYXRoLmNlaWwob3B0aW9ucy5wcm9iZUJ1ZGdldCAvIGNvbmZpZy5jZWxsVGFyZ2V0U2l6ZSkpO1xuICAgIGNvbnN0IHByb2JlQ2VsbElkcyA9IHJhbmtDZWxsc0J5Q2xvc2VuZXNzKHF1ZXJ5LCBjZW50cm9pZHMpLnNsaWNlKDAsIHByb2JlQ2VsbENvdW50KTtcbiAgICBjb25zdCBzdG9yZXMgPSBkYXRhYmFzZS5yZWFkRGF0YShyb290ID0+IHByb2JlQ2VsbElkcy5tYXAoY2VsbElkID0+IHJvb3QuY2VsbHNbY2VsbElkXSkpO1xuICAgIGlmICghc3RvcmVzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGZvciAoY29uc3Qgc3RvcmUgb2Ygc3RvcmVzKSB7XG4gICAgICAgIGNvbnN0IG1lbWJlcnMgPSByZXBsYXlUcmFuc2FjdGlvblN0b3JlPFN0b3JlZEVtYmVkZGluZz4oc3RvcmUpO1xuICAgICAgICBmb3IgKGNvbnN0IHJlZiBvZiBtZW1iZXJzLmtleXMoKSkge1xuICAgICAgICAgICAgaGl0cy5wdXNoKHsgcmVmLCBjbG9zZW5lc3M6IGdldENsb3NlbmVzcyhxdWVyeSwgbWVtYmVycy5nZXQocmVmKSEpIH0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGhpdHMuc29ydCgobGVmdCwgcmlnaHQpID0+IHJpZ2h0LmNsb3NlbmVzcyAtIGxlZnQuY2xvc2VuZXNzKTtcbiAgICByZXR1cm4gaGl0cy5zbGljZSgwLCBvcHRpb25zLnJlc3VsdENvdW50KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGluc2VydEVtYmVkZGluZ3MoXG4gICAgZGF0YWJhc2U6IERhdGFiYXNlPEl2ZkVtYmVkZGluZ1Jvb3Q+LFxuICAgIGl0ZW1zOiBFbWJlZGRpbmdJbnB1dFtdLFxuKTogdHJ1ZSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFpdGVtcy5sZW5ndGgpIHJldHVybiB0cnVlO1xuICAgIGNvbnN0IGNvbmZpZyA9IGRhdGFiYXNlLnJlYWREYXRhKHJvb3QgPT4gcm9vdC5jb25maWcpO1xuICAgIGlmICghY29uZmlnKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IHN0ZXBzID0gcmVhZFN0ZXBzKGRhdGFiYXNlKTtcbiAgICBjb25zdCBuZXdDb3VudCA9IHJlYWRDb3VudChkYXRhYmFzZSkgKyBpdGVtcy5sZW5ndGg7XG5cbiAgICBpZiAoIXN0ZXBzW1NURVBfSVZGXSkge1xuICAgICAgICBjb25zdCBmbGF0V3JpdGVzID0gaXRlbXMubWFwKGl0ZW0gPT4gKHsga2V5OiBpdGVtLnJlZiwgdmFsdWU6IGl0ZW0uZW1iZWRkaW5nIH0pKTtcbiAgICAgICAgdHJhbnNhY3Rpb25NdXRhdGUoZmxhdFN0b3JlKGRhdGFiYXNlKSwgZmxhdFdyaXRlcyk7XG4gICAgICAgIGRhdGFiYXNlLndyaXRlRGF0YShyb290ID0+IHJvb3QuY291bnQsIG5ld0NvdW50KTtcbiAgICAgICAgaWYgKG5ld0NvdW50ID4gRkxBVF9MSU1JVCkge1xuICAgICAgICAgICAgcmVidWlsZFN0cnVjdHVyZShkYXRhYmFzZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgY29uc3QgY2VudHJvaWRzID0gdHJhbnNhY3Rpb25SZWFkKGNlbnRyb2lkU3RvcmUoZGF0YWJhc2UpKTtcbiAgICBpZiAoIWNlbnRyb2lkcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBjb25zdCBpdGVtc0J5Q2VsbCA9IG5ldyBNYXA8c3RyaW5nLCBFbWJlZGRpbmdJbnB1dFtdPigpO1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykge1xuICAgICAgICBjb25zdCBjZWxsSWQgPSByYW5rQ2VsbHNCeUNsb3NlbmVzcyhpdGVtLmVtYmVkZGluZywgY2VudHJvaWRzKVswXTtcbiAgICAgICAgbGV0IGdyb3VwID0gaXRlbXNCeUNlbGwuZ2V0KGNlbGxJZCk7XG4gICAgICAgIGlmICghZ3JvdXApIHtcbiAgICAgICAgICAgIGdyb3VwID0gW107XG4gICAgICAgICAgICBpdGVtc0J5Q2VsbC5zZXQoY2VsbElkLCBncm91cCk7XG4gICAgICAgIH1cbiAgICAgICAgZ3JvdXAucHVzaChpdGVtKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBjZWxsSWQgb2YgaXRlbXNCeUNlbGwua2V5cygpKSB7XG4gICAgICAgIGNvbnN0IGdyb3VwID0gaXRlbXNCeUNlbGwuZ2V0KGNlbGxJZCkhO1xuICAgICAgICBjb25zdCBtZW1iZXJXcml0ZXMgPSBncm91cC5tYXAoaXRlbSA9PiAoeyBrZXk6IGl0ZW0ucmVmLCB2YWx1ZTogaXRlbS5lbWJlZGRpbmcgfSkpO1xuICAgICAgICB0cmFuc2FjdGlvbk11dGF0ZShjZWxsU3RvcmUoZGF0YWJhc2UsIGNlbGxJZCksIG1lbWJlcldyaXRlcyk7XG4gICAgfVxuICAgIGRhdGFiYXNlLndyaXRlRGF0YShyb290ID0+IHJvb3QuY291bnQsIG5ld0NvdW50KTtcblxuICAgIGxldCByZWdlbmVyYXRlZCA9IGZhbHNlO1xuICAgIGZvciAoY29uc3QgdGhyZXNob2xkIG9mIFJFR0VORVJBVEVfQVQpIHtcbiAgICAgICAgY29uc3Qgc3RlcE5hbWUgPSBcInJlZ2VuXCIgKyB0aHJlc2hvbGQ7XG4gICAgICAgIGlmICghc3RlcHNbc3RlcE5hbWVdICYmIG5ld0NvdW50ID4gdGhyZXNob2xkKSB7XG4gICAgICAgICAgICByZWJ1aWxkU3RydWN0dXJlKGRhdGFiYXNlKTtcbiAgICAgICAgICAgIGRhdGFiYXNlLndyaXRlRGF0YShyb290ID0+IHJvb3Quc3RlcHNbc3RlcE5hbWVdLCB0cnVlKTtcbiAgICAgICAgICAgIHJlZ2VuZXJhdGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoIXJlZ2VuZXJhdGVkKSB7XG4gICAgICAgIGNvbnN0IGF2ZXJhZ2VGaWxsID0gbmV3Q291bnQgLyBNYXRoLm1heCgxLCBjZW50cm9pZHMuc2l6ZSkgLyBjb25maWcuY2VsbFRhcmdldFNpemU7XG4gICAgICAgIGlmIChNYXRoLnJhbmRvbSgpIDwgcmViYWxhbmNlUHJvYmFiaWxpdHkoYXZlcmFnZUZpbGwpKSB7XG4gICAgICAgICAgICByZWJ1aWxkU3RydWN0dXJlKGRhdGFiYXNlKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUVtYmVkZGluZ3MoXG4gICAgZGF0YWJhc2U6IERhdGFiYXNlPEl2ZkVtYmVkZGluZ1Jvb3Q+LFxuICAgIGl0ZW1zOiBFbWJlZGRpbmdJbnB1dFtdLFxuKTogdHJ1ZSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFpdGVtcy5sZW5ndGgpIHJldHVybiB0cnVlO1xuICAgIGNvbnN0IHN0ZXBzID0gcmVhZFN0ZXBzKGRhdGFiYXNlKTtcbiAgICBjb25zdCBjb3VudCA9IHJlYWRDb3VudChkYXRhYmFzZSk7XG5cbiAgICBpZiAoIXN0ZXBzW1NURVBfSVZGXSkge1xuICAgICAgICBjb25zdCBmbGF0RGVsZXRlcyA9IGl0ZW1zLm1hcChpdGVtID0+ICh7IGtleTogaXRlbS5yZWYsIHZhbHVlOiB1bmRlZmluZWQgfSkpO1xuICAgICAgICB0cmFuc2FjdGlvbk11dGF0ZShmbGF0U3RvcmUoZGF0YWJhc2UpLCBmbGF0RGVsZXRlcyk7XG4gICAgICAgIGRhdGFiYXNlLndyaXRlRGF0YShyb290ID0+IHJvb3QuY291bnQsIE1hdGgubWF4KDAsIGNvdW50IC0gaXRlbXMubGVuZ3RoKSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGNvbnN0IGNlbnRyb2lkcyA9IHRyYW5zYWN0aW9uUmVhZChjZW50cm9pZFN0b3JlKGRhdGFiYXNlKSk7XG4gICAgaWYgKCFjZW50cm9pZHMpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgaWYgKCFjZW50cm9pZHMuc2l6ZSkgcmV0dXJuIHRydWU7XG5cbiAgICBjb25zdCBjYW5kaWRhdGVzQnlJdGVtOiB7IHJlZjogc3RyaW5nOyBjZWxsSWRzOiBzdHJpbmdbXSB9W10gPSBbXTtcbiAgICBjb25zdCBjYW5kaWRhdGVTZXQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHtcbiAgICAgICAgY29uc3QgY2VsbElkcyA9IHJhbmtDZWxsc0J5Q2xvc2VuZXNzKGl0ZW0uZW1iZWRkaW5nLCBjZW50cm9pZHMpLnNsaWNlKDAsIDEgKyBERUxFVEVfRkFMTEJBQ0tfQ0VMTFMpO1xuICAgICAgICBjYW5kaWRhdGVzQnlJdGVtLnB1c2goeyByZWY6IGl0ZW0ucmVmLCBjZWxsSWRzIH0pO1xuICAgICAgICBmb3IgKGNvbnN0IGNlbGxJZCBvZiBjZWxsSWRzKSB7XG4gICAgICAgICAgICBjYW5kaWRhdGVTZXQuYWRkKGNlbGxJZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBjYW5kaWRhdGVDZWxsSWRzID0gQXJyYXkuZnJvbShjYW5kaWRhdGVTZXQpO1xuICAgIGNvbnN0IHN0b3JlcyA9IGRhdGFiYXNlLnJlYWREYXRhKHJvb3QgPT4gY2FuZGlkYXRlQ2VsbElkcy5tYXAoY2VsbElkID0+IHJvb3QuY2VsbHNbY2VsbElkXSkpO1xuICAgIGlmICghc3RvcmVzKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGNvbnN0IG1lbWJlcnNCeUNlbGwgPSBuZXcgTWFwPHN0cmluZywgTWFwPHN0cmluZywgU3RvcmVkRW1iZWRkaW5nPj4oKTtcbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgY2FuZGlkYXRlQ2VsbElkcy5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgbWVtYmVyc0J5Q2VsbC5zZXQoY2FuZGlkYXRlQ2VsbElkc1tpbmRleF0sIHJlcGxheVRyYW5zYWN0aW9uU3RvcmUoc3RvcmVzW2luZGV4XSkpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlbGV0ZXNCeUNlbGwgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nW10+KCk7XG4gICAgZm9yIChjb25zdCBjYW5kaWRhdGUgb2YgY2FuZGlkYXRlc0J5SXRlbSkge1xuICAgICAgICBmb3IgKGNvbnN0IGNlbGxJZCBvZiBjYW5kaWRhdGUuY2VsbElkcykge1xuICAgICAgICAgICAgY29uc3QgbWVtYmVycyA9IG1lbWJlcnNCeUNlbGwuZ2V0KGNlbGxJZCk7XG4gICAgICAgICAgICBpZiAoIW1lbWJlcnMgfHwgIW1lbWJlcnMuaGFzKGNhbmRpZGF0ZS5yZWYpKSB7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgcmVmcyA9IGRlbGV0ZXNCeUNlbGwuZ2V0KGNlbGxJZCk7XG4gICAgICAgICAgICBpZiAoIXJlZnMpIHtcbiAgICAgICAgICAgICAgICByZWZzID0gW107XG4gICAgICAgICAgICAgICAgZGVsZXRlc0J5Q2VsbC5zZXQoY2VsbElkLCByZWZzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlZnMucHVzaChjYW5kaWRhdGUucmVmKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbGV0IGRlbGV0ZWRDb3VudCA9IDA7XG4gICAgZm9yIChjb25zdCBjZWxsSWQgb2YgZGVsZXRlc0J5Q2VsbC5rZXlzKCkpIHtcbiAgICAgICAgY29uc3QgcmVmcyA9IGRlbGV0ZXNCeUNlbGwuZ2V0KGNlbGxJZCkhO1xuICAgICAgICBkZWxldGVkQ291bnQgKz0gcmVmcy5sZW5ndGg7XG4gICAgICAgIGNvbnN0IG1lbWJlckRlbGV0ZXMgPSByZWZzLm1hcChyZWYgPT4gKHsga2V5OiByZWYsIHZhbHVlOiB1bmRlZmluZWQgfSkpO1xuICAgICAgICB0cmFuc2FjdGlvbk11dGF0ZShjZWxsU3RvcmUoZGF0YWJhc2UsIGNlbGxJZCksIG1lbWJlckRlbGV0ZXMpO1xuICAgIH1cbiAgICBpZiAoZGVsZXRlZENvdW50KSB7XG4gICAgICAgIGRhdGFiYXNlLndyaXRlRGF0YShyb290ID0+IHJvb3QuY291bnQsIE1hdGgubWF4KDAsIGNvdW50IC0gZGVsZXRlZENvdW50KSk7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuIl19
|
|
334
|
+
/* _JS_SOURCE_HASH = "6bb25c321db29d41be7eec5ac48ec8aad9563a1f8c7710e6700a8deb6ed719c9"; */
|