@sochdb/sochdb 0.4.0 → 0.4.2

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.
Files changed (80) hide show
  1. package/README.md +416 -34
  2. package/_bin/aarch64-apple-darwin/libsochdb_storage.dylib +0 -0
  3. package/_bin/aarch64-apple-darwin/sochdb-bulk +0 -0
  4. package/_bin/aarch64-apple-darwin/sochdb-grpc-server +0 -0
  5. package/_bin/aarch64-apple-darwin/sochdb-server +0 -0
  6. package/_bin/x86_64-pc-windows-msvc/sochdb-bulk.exe +0 -0
  7. package/_bin/x86_64-pc-windows-msvc/sochdb-grpc-server.exe +0 -0
  8. package/_bin/x86_64-pc-windows-msvc/sochdb_storage.dll +0 -0
  9. package/_bin/x86_64-unknown-linux-gnu/libsochdb_storage.so +0 -0
  10. package/_bin/x86_64-unknown-linux-gnu/sochdb-bulk +0 -0
  11. package/_bin/x86_64-unknown-linux-gnu/sochdb-grpc-server +0 -0
  12. package/_bin/x86_64-unknown-linux-gnu/sochdb-server +0 -0
  13. package/bin/sochdb-bulk.js +1 -1
  14. package/bin/sochdb-grpc-server.js +1 -1
  15. package/bin/sochdb-server.js +1 -1
  16. package/dist/cjs/context-builder.js +280 -0
  17. package/dist/cjs/database.js +2 -2
  18. package/dist/cjs/embedded/database.js +2 -2
  19. package/dist/cjs/embedded/ffi/hnsw-bindings.js +295 -0
  20. package/dist/cjs/embedded/ffi/library-finder.js +10 -3
  21. package/dist/cjs/embedded/index.js +5 -2
  22. package/dist/cjs/errors.js +99 -7
  23. package/dist/cjs/index.js +46 -6
  24. package/dist/cjs/ipc-client.js +2 -2
  25. package/dist/cjs/memory/consolidation.js +202 -0
  26. package/dist/cjs/memory/extraction.js +181 -0
  27. package/dist/cjs/memory/index.js +26 -0
  28. package/dist/cjs/memory/retrieval.js +232 -0
  29. package/dist/cjs/memory/types.js +69 -0
  30. package/dist/cjs/namespace.js +255 -0
  31. package/dist/cjs/queue.js +289 -0
  32. package/dist/cjs/semantic-cache.js +220 -0
  33. package/dist/esm/context-builder.js +280 -0
  34. package/dist/esm/database.js +2 -2
  35. package/dist/esm/embedded/database.js +2 -2
  36. package/dist/esm/embedded/ffi/hnsw-bindings.js +316 -0
  37. package/dist/esm/embedded/ffi/library-finder.js +10 -3
  38. package/dist/esm/embedded/index.js +5 -2
  39. package/dist/esm/errors.js +107 -7
  40. package/dist/esm/index.js +46 -6
  41. package/dist/esm/ipc-client.js +2 -2
  42. package/dist/esm/memory/consolidation.js +206 -0
  43. package/dist/esm/memory/extraction.js +185 -0
  44. package/dist/esm/memory/index.js +26 -0
  45. package/dist/esm/memory/retrieval.js +243 -0
  46. package/dist/esm/memory/types.js +72 -0
  47. package/dist/esm/namespace.js +262 -0
  48. package/dist/esm/queue.js +291 -0
  49. package/dist/esm/semantic-cache.js +223 -0
  50. package/dist/types/context-builder.d.ts +97 -0
  51. package/dist/types/context-builder.d.ts.map +1 -0
  52. package/dist/types/database.d.ts +1 -1
  53. package/dist/types/embedded/database.d.ts +1 -1
  54. package/dist/types/embedded/ffi/hnsw-bindings.d.ts +90 -0
  55. package/dist/types/embedded/ffi/hnsw-bindings.d.ts.map +1 -0
  56. package/dist/types/embedded/ffi/library-finder.d.ts.map +1 -1
  57. package/dist/types/embedded/index.d.ts +1 -0
  58. package/dist/types/embedded/index.d.ts.map +1 -1
  59. package/dist/types/errors.d.ts +57 -1
  60. package/dist/types/errors.d.ts.map +1 -1
  61. package/dist/types/index.d.ts +15 -3
  62. package/dist/types/index.d.ts.map +1 -1
  63. package/dist/types/ipc-client.d.ts +1 -1
  64. package/dist/types/memory/consolidation.d.ts +66 -0
  65. package/dist/types/memory/consolidation.d.ts.map +1 -0
  66. package/dist/types/memory/extraction.d.ts +82 -0
  67. package/dist/types/memory/extraction.d.ts.map +1 -0
  68. package/dist/types/memory/index.d.ts +10 -0
  69. package/dist/types/memory/index.d.ts.map +1 -0
  70. package/dist/types/memory/retrieval.d.ts +46 -0
  71. package/dist/types/memory/retrieval.d.ts.map +1 -0
  72. package/dist/types/memory/types.d.ts +147 -0
  73. package/dist/types/memory/types.d.ts.map +1 -0
  74. package/dist/types/namespace.d.ts +129 -0
  75. package/dist/types/namespace.d.ts.map +1 -0
  76. package/dist/types/queue.d.ts +120 -0
  77. package/dist/types/queue.d.ts.map +1 -0
  78. package/dist/types/semantic-cache.d.ts +84 -0
  79. package/dist/types/semantic-cache.d.ts.map +1 -0
  80. package/package.json +1 -1
@@ -0,0 +1,280 @@
1
+ "use strict";
2
+ /**
3
+ * Context Query Builder for LLM Context Assembly
4
+ *
5
+ * Token-aware context assembly with priority-based truncation.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.ContextQueryBuilder = exports.TruncationStrategy = exports.ContextOutputFormat = void 0;
9
+ exports.createContextBuilder = createContextBuilder;
10
+ var ContextOutputFormat;
11
+ (function (ContextOutputFormat) {
12
+ ContextOutputFormat["TOON"] = "toon";
13
+ ContextOutputFormat["JSON"] = "json";
14
+ ContextOutputFormat["MARKDOWN"] = "markdown";
15
+ })(ContextOutputFormat || (exports.ContextOutputFormat = ContextOutputFormat = {}));
16
+ var TruncationStrategy;
17
+ (function (TruncationStrategy) {
18
+ TruncationStrategy["TAIL_DROP"] = "tail_drop";
19
+ TruncationStrategy["HEAD_DROP"] = "head_drop";
20
+ TruncationStrategy["PROPORTIONAL"] = "proportional";
21
+ })(TruncationStrategy || (exports.TruncationStrategy = TruncationStrategy = {}));
22
+ /**
23
+ * Context Query Builder for assembling LLM context
24
+ */
25
+ class ContextQueryBuilder {
26
+ constructor() {
27
+ this.tokenBudget = 4096;
28
+ this.format = ContextOutputFormat.TOON;
29
+ this.truncation = TruncationStrategy.TAIL_DROP;
30
+ this.sections = [];
31
+ }
32
+ /**
33
+ * Set session ID for context
34
+ */
35
+ forSession(sessionId) {
36
+ this.sessionId = sessionId;
37
+ return this;
38
+ }
39
+ /**
40
+ * Set token budget
41
+ */
42
+ withBudget(tokens) {
43
+ this.tokenBudget = tokens;
44
+ return this;
45
+ }
46
+ /**
47
+ * Set output format
48
+ */
49
+ setFormat(format) {
50
+ this.format = format;
51
+ return this;
52
+ }
53
+ /**
54
+ * Set truncation strategy
55
+ */
56
+ setTruncation(strategy) {
57
+ this.truncation = strategy;
58
+ return this;
59
+ }
60
+ /**
61
+ * Add literal text section
62
+ */
63
+ literal(name, priority, text) {
64
+ const tokenCount = this.estimateTokens(text);
65
+ this.sections.push({
66
+ name,
67
+ priority,
68
+ content: text,
69
+ tokenCount,
70
+ });
71
+ return this;
72
+ }
73
+ /**
74
+ * Start a new section
75
+ */
76
+ section(name, priority) {
77
+ this.currentSection = {
78
+ name,
79
+ priority,
80
+ content: '',
81
+ tokenCount: 0,
82
+ };
83
+ return this;
84
+ }
85
+ /**
86
+ * Add content to current section
87
+ */
88
+ get(path) {
89
+ if (!this.currentSection) {
90
+ throw new Error('No active section. Call section() first.');
91
+ }
92
+ this.currentSection.content += `GET ${path}\n`;
93
+ return this;
94
+ }
95
+ /**
96
+ * Add last N records query
97
+ */
98
+ last(n, table) {
99
+ if (!this.currentSection) {
100
+ throw new Error('No active section. Call section() first.');
101
+ }
102
+ this.currentSection.content += `LAST ${n} FROM ${table}\n`;
103
+ return this;
104
+ }
105
+ /**
106
+ * Add where equals condition
107
+ */
108
+ whereEq(field, value) {
109
+ if (!this.currentSection) {
110
+ throw new Error('No active section. Call section() first.');
111
+ }
112
+ this.currentSection.content += `WHERE ${field} = ${JSON.stringify(value)}\n`;
113
+ return this;
114
+ }
115
+ /**
116
+ * Add vector search
117
+ */
118
+ search(collection, embedding, k) {
119
+ if (!this.currentSection) {
120
+ throw new Error('No active section. Call section() first.');
121
+ }
122
+ this.currentSection.content += `SEARCH ${collection} WITH ${embedding} LIMIT ${k}\n`;
123
+ return this;
124
+ }
125
+ /**
126
+ * Add SQL query
127
+ */
128
+ sql(query) {
129
+ if (!this.currentSection) {
130
+ throw new Error('No active section. Call section() first.');
131
+ }
132
+ this.currentSection.content += `SQL: ${query}\n`;
133
+ return this;
134
+ }
135
+ /**
136
+ * Finish current section
137
+ */
138
+ done() {
139
+ if (this.currentSection) {
140
+ this.currentSection.tokenCount = this.estimateTokens(this.currentSection.content);
141
+ this.sections.push(this.currentSection);
142
+ this.currentSection = undefined;
143
+ }
144
+ return this;
145
+ }
146
+ /**
147
+ * Execute and build context
148
+ */
149
+ execute() {
150
+ // Finish any pending section
151
+ if (this.currentSection) {
152
+ this.done();
153
+ }
154
+ // Sort sections by priority (lower = higher priority)
155
+ const sortedSections = [...this.sections].sort((a, b) => a.priority - b.priority);
156
+ // Calculate total tokens
157
+ let totalTokens = sortedSections.reduce((sum, s) => sum + s.tokenCount, 0);
158
+ // Truncate if needed
159
+ const truncatedSections = [];
160
+ const includedSections = [];
161
+ if (totalTokens <= this.tokenBudget) {
162
+ // No truncation needed
163
+ for (const section of sortedSections) {
164
+ includedSections.push(section);
165
+ truncatedSections.push({
166
+ name: section.name,
167
+ tokenCount: section.tokenCount,
168
+ truncated: false,
169
+ });
170
+ }
171
+ }
172
+ else {
173
+ // Apply truncation strategy
174
+ let remainingBudget = this.tokenBudget;
175
+ if (this.truncation === TruncationStrategy.TAIL_DROP) {
176
+ // Include sections in priority order until budget exhausted
177
+ for (const section of sortedSections) {
178
+ if (section.tokenCount <= remainingBudget) {
179
+ includedSections.push(section);
180
+ remainingBudget -= section.tokenCount;
181
+ truncatedSections.push({
182
+ name: section.name,
183
+ tokenCount: section.tokenCount,
184
+ truncated: false,
185
+ });
186
+ }
187
+ else {
188
+ truncatedSections.push({
189
+ name: section.name,
190
+ tokenCount: 0,
191
+ truncated: true,
192
+ });
193
+ }
194
+ }
195
+ }
196
+ else if (this.truncation === TruncationStrategy.PROPORTIONAL) {
197
+ // Proportionally reduce all sections
198
+ const ratio = this.tokenBudget / totalTokens;
199
+ for (const section of sortedSections) {
200
+ const allocatedTokens = Math.floor(section.tokenCount * ratio);
201
+ const truncatedContent = this.truncateText(section.content, allocatedTokens);
202
+ includedSections.push({
203
+ ...section,
204
+ content: truncatedContent,
205
+ tokenCount: allocatedTokens,
206
+ });
207
+ truncatedSections.push({
208
+ name: section.name,
209
+ tokenCount: allocatedTokens,
210
+ truncated: allocatedTokens < section.tokenCount,
211
+ });
212
+ }
213
+ }
214
+ }
215
+ // Build final context based on format
216
+ let text = '';
217
+ let actualTokens = 0;
218
+ if (this.format === ContextOutputFormat.TOON) {
219
+ text = this.buildToonFormat(includedSections);
220
+ }
221
+ else if (this.format === ContextOutputFormat.JSON) {
222
+ text = this.buildJsonFormat(includedSections);
223
+ }
224
+ else {
225
+ text = this.buildMarkdownFormat(includedSections);
226
+ }
227
+ actualTokens = this.estimateTokens(text);
228
+ return {
229
+ text,
230
+ tokenCount: actualTokens,
231
+ sections: truncatedSections,
232
+ };
233
+ }
234
+ // Helper methods
235
+ estimateTokens(text) {
236
+ // Rough estimate: ~4 characters per token for English
237
+ return Math.ceil(text.length / 4);
238
+ }
239
+ truncateText(text, maxTokens) {
240
+ const maxChars = maxTokens * 4;
241
+ if (text.length <= maxChars) {
242
+ return text;
243
+ }
244
+ return text.substring(0, maxChars) + '...';
245
+ }
246
+ buildToonFormat(sections) {
247
+ const lines = [];
248
+ for (const section of sections) {
249
+ lines.push(`[${section.name}]`);
250
+ lines.push(section.content);
251
+ lines.push('');
252
+ }
253
+ return lines.join('\n');
254
+ }
255
+ buildJsonFormat(sections) {
256
+ const obj = {};
257
+ for (const section of sections) {
258
+ obj[section.name] = section.content;
259
+ }
260
+ return JSON.stringify(obj, null, 2);
261
+ }
262
+ buildMarkdownFormat(sections) {
263
+ const lines = [];
264
+ for (const section of sections) {
265
+ lines.push(`## ${section.name}`);
266
+ lines.push('');
267
+ lines.push(section.content);
268
+ lines.push('');
269
+ }
270
+ return lines.join('\n');
271
+ }
272
+ }
273
+ exports.ContextQueryBuilder = ContextQueryBuilder;
274
+ /**
275
+ * Create a context query builder
276
+ */
277
+ function createContextBuilder() {
278
+ return new ContextQueryBuilder();
279
+ }
280
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC1idWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbnRleHQtYnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7R0FJRzs7O0FBc1RILG9EQUVDO0FBdFRELElBQVksbUJBSVg7QUFKRCxXQUFZLG1CQUFtQjtJQUM3QixvQ0FBYSxDQUFBO0lBQ2Isb0NBQWEsQ0FBQTtJQUNiLDRDQUFxQixDQUFBO0FBQ3ZCLENBQUMsRUFKVyxtQkFBbUIsbUNBQW5CLG1CQUFtQixRQUk5QjtBQUVELElBQVksa0JBSVg7QUFKRCxXQUFZLGtCQUFrQjtJQUM1Qiw2Q0FBdUIsQ0FBQTtJQUN2Qiw2Q0FBdUIsQ0FBQTtJQUN2QixtREFBNkIsQ0FBQTtBQUMvQixDQUFDLEVBSlcsa0JBQWtCLGtDQUFsQixrQkFBa0IsUUFJN0I7QUFlRDs7R0FFRztBQUNILE1BQWEsbUJBQW1CO0lBQWhDO1FBRVUsZ0JBQVcsR0FBVyxJQUFJLENBQUM7UUFDM0IsV0FBTSxHQUF3QixtQkFBbUIsQ0FBQyxJQUFJLENBQUM7UUFDdkQsZUFBVSxHQUF1QixrQkFBa0IsQ0FBQyxTQUFTLENBQUM7UUFDOUQsYUFBUSxHQUFjLEVBQUUsQ0FBQztJQThRbkMsQ0FBQztJQTNRQzs7T0FFRztJQUNILFVBQVUsQ0FBQyxTQUFpQjtRQUMxQixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUMzQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNILFVBQVUsQ0FBQyxNQUFjO1FBQ3ZCLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxDQUFDO1FBQzFCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyxDQUFDLE1BQTJCO1FBQ25DLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOztPQUVHO0lBQ0gsYUFB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YSxFQUFFLENBQUM7UUFFM0IsS0FBSyxNQUFNLE9BQU8sSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUMvQixLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7WUFDakMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNmLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzVCLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDakIsQ0FBQztRQUVELE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMxQixDQUFDO0NBQ0Y7QUFuUkQsa0RBbVJDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixvQkFBb0I7SUFDbEMsT0FBTyxJQUFJLG1CQUFtQixFQUFFLENBQUM7QUFDbkMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29udGV4dCBRdWVyeSBCdWlsZGVyIGZvciBMTE0gQ29udGV4dCBBc3NlbWJseVxuICogXG4gKiBUb2tlbi1hd2FyZSBjb250ZXh0IGFzc2VtYmx5IHdpdGggcHJpb3JpdHktYmFzZWQgdHJ1bmNhdGlvbi5cbiAqL1xuXG5leHBvcnQgZW51bSBDb250ZXh0T3V0cHV0Rm9ybWF0IHtcbiAgVE9PTiA9ICd0b29uJyxcbiAgSlNPTiA9ICdqc29uJyxcbiAgTUFSS0RPV04gPSAnbWFya2Rvd24nLFxufVxuXG5leHBvcnQgZW51bSBUcnVuY2F0aW9uU3RyYXRlZ3kge1xuICBUQUlMX0RST1AgPSAndGFpbF9kcm9wJywgICAgICAgLy8gRHJvcCBmcm9tIGVuZFxuICBIRUFEX0RST1AgPSAnaGVhZF9kcm9wJywgICAgICAgLy8gRHJvcCBmcm9tIGJlZ2lubmluZ1xuICBQUk9QT1JUSU9OQUwgPSAncHJvcG9ydGlvbmFsJywgLy8gUHJvcG9ydGlvbmFsIGFjcm9zcyBzZWN0aW9uc1xufVxuXG5pbnRlcmZhY2UgU2VjdGlvbiB7XG4gIG5hbWU6IHN0cmluZztcbiAgcHJpb3JpdHk6IG51bWJlcjtcbiAgY29udGVudDogc3RyaW5nO1xuICB0b2tlbkNvdW50OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udGV4dFJlc3VsdCB7XG4gIHRleHQ6IHN0cmluZztcbiAgdG9rZW5Db3VudDogbnVtYmVyO1xuICBzZWN0aW9uczogQXJyYXk8eyBuYW1lOiBzdHJpbmc7IHRva2VuQ291bnQ6IG51bWJlcjsgdHJ1bmNhdGVkOiBib29sZWFuIH0+O1xufVxuXG4vKipcbiAqIENvbnRleHQgUXVlcnkgQnVpbGRlciBmb3IgYXNzZW1ibGluZyBMTE0gY29udGV4dFxuICovXG5leHBvcnQgY2xhc3MgQ29udGV4dFF1ZXJ5QnVpbGRlciB7XG4gIHByaXZhdGUgc2Vzc2lvbklkPzogc3RyaW5nO1xuICBwcml2YXRlIHRva2VuQnVkZ2V0OiBudW1iZXIgPSA0MDk2O1xuICBwcml2YXRlIGZvcm1hdDogQ29udGV4dE91dHB1dEZvcm1hdCA9IENvbnRleHRPdXRwdXRGb3JtYXQuVE9PTjtcbiAgcHJpdmF0ZSB0cnVuY2F0aW9uOiBUcnVuY2F0aW9uU3RyYXRlZ3kgPSBUcnVuY2F0aW9uU3RyYXRlZ3kuVEFJTF9EUk9QO1xuICBwcml2YXRlIHNlY3Rpb25zOiBTZWN0aW9uW10gPSBbXTtcbiAgcHJpdmF0ZSBjdXJyZW50U2VjdGlvbj86IFNlY3Rpb247XG5cbiAgLyoqXG4gICAqIFNldCBzZXNzaW9uIElEIGZvciBjb250ZXh0XG4gICAqL1xuICBmb3JTZXNzaW9uKHNlc3Npb25JZDogc3RyaW5nKTogdGhpcyB7XG4gICAgdGhpcy5zZXNzaW9uSWQgPSBzZXNzaW9uSWQ7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRva2VuIGJ1ZGdldFxuICAgKi9cbiAgd2l0aEJ1ZGdldCh0b2tlbnM6IG51bWJlcik6IHRoaXMge1xuICAgIHRoaXMudG9rZW5CdWRnZXQgPSB0b2tlbnM7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0IG91dHB1dCBmb3JtYXRcbiAgICovXG4gIHNldEZvcm1hdChmb3JtYXQ6IENvbnRleHRPdXRwdXRGb3JtYXQpOiB0aGlzIHtcbiAgICB0aGlzLmZvcm1hdCA9IGZvcm1hdDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdHJ1bmNhdGlvbiBzdHJhdGVneVxuICAgKi9cbiAgc2V0VHJ1bmNhdGlvbihzdHJhdGVneTogVHJ1bmNhdGlvblN0cmF0ZWd5KTogdGhpcyB7XG4gICAgdGhpcy50cnVuY2F0aW9uID0gc3RyYXRlZ3k7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGxpdGVyYWwgdGV4dCBzZWN0aW9uXG4gICAqL1xuICBsaXRlcmFsKG5hbWU6IHN0cmluZywgcHJpb3JpdHk6IG51bWJlciwgdGV4dDogc3RyaW5nKTogdGhpcyB7XG4gICAgY29uc3QgdG9rZW5Db3VudCA9IHRoaXMuZXN0aW1hdGVUb2tlbnModGV4dCk7XG4gICAgdGhpcy5zZWN0aW9ucy5wdXNoKHtcbiAgICAgIG5hbWUsXG4gICAgICBwcmlvcml0eSxcbiAgICAgIGNvbnRlbnQ6IHRleHQsXG4gICAgICB0b2tlbkNvdW50LFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXJ0IGEgbmV3IHNlY3Rpb25cbiAgICovXG4gIHNlY3Rpb24obmFtZTogc3RyaW5nLCBwcmlvcml0eTogbnVtYmVyKTogdGhpcyB7XG4gICAgdGhpcy5jdXJyZW50U2VjdGlvbiA9IHtcbiAgICAgIG5hbWUsXG4gICAgICBwcmlvcml0eSxcbiAgICAgIGNvbnRlbnQ6ICcnLFxuICAgICAgdG9rZW5Db3VudDogMCxcbiAgICB9O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBjb250ZW50IHRvIGN1cnJlbnQgc2VjdGlvblxuICAgKi9cbiAgZ2V0KHBhdGg6IHN0cmluZyk6IHRoaXMge1xuICAgIGlmICghdGhpcy5jdXJyZW50U2VjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBhY3RpdmUgc2VjdGlvbi4gQ2FsbCBzZWN0aW9uKCkgZmlyc3QuJyk7XG4gICAgfVxuICAgIHRoaXMuY3VycmVudFNlY3Rpb24uY29udGVudCArPSBgR0VUICR7cGF0aH1cXG5gO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBsYXN0IE4gcmVjb3JkcyBxdWVyeVxuICAgKi9cbiAgbGFzdChuOiBudW1iZXIsIHRhYmxlOiBzdHJpbmcpOiB0aGlzIHtcbiAgICBpZiAoIXRoaXMuY3VycmVudFNlY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gYWN0aXZlIHNlY3Rpb24uIENhbGwgc2VjdGlvbigpIGZpcnN0LicpO1xuICAgIH1cbiAgICB0aGlzLmN1cnJlbnRTZWN0aW9uLmNvbnRlbnQgKz0gYExBU1QgJHtufSBGUk9NICR7dGFibGV9XFxuYDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgd2hlcmUgZXF1YWxzIGNvbmRpdGlvblxuICAgKi9cbiAgd2hlcmVFcShmaWVsZDogc3RyaW5nLCB2YWx1ZTogYW55KTogdGhpcyB7XG4gICAgaWYgKCF0aGlzLmN1cnJlbnRTZWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGFjdGl2ZSBzZWN0aW9uLiBDYWxsIHNlY3Rpb24oKSBmaXJzdC4nKTtcbiAgICB9XG4gICAgdGhpcy5jdXJyZW50U2VjdGlvbi5jb250ZW50ICs9IGBXSEVSRSAke2ZpZWxkfSA9ICR7SlNPTi5zdHJpbmdpZnkodmFsdWUpfVxcbmA7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkIHZlY3RvciBzZWFyY2hcbiAgICovXG4gIHNlYXJjaChjb2xsZWN0aW9uOiBzdHJpbmcsIGVtYmVkZGluZzogc3RyaW5nLCBrOiBudW1iZXIpOiB0aGlzIHtcbiAgICBpZiAoIXRoaXMuY3VycmVudFNlY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gYWN0aXZlIHNlY3Rpb24uIENhbGwgc2VjdGlvbigpIGZpcnN0LicpO1xuICAgIH1cbiAgICB0aGlzLmN1cnJlbnRTZWN0aW9uLmNvbnRlbnQgKz0gYFNFQVJDSCAke2NvbGxlY3Rpb259IFdJVEggJHtlbWJlZGRpbmd9IExJTUlUICR7a31cXG5gO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBTUUwgcXVlcnlcbiAgICovXG4gIHNxbChxdWVyeTogc3RyaW5nKTogdGhpcyB7XG4gICAgaWYgKCF0aGlzLmN1cnJlbnRTZWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGFjdGl2ZSBzZWN0aW9uLiBDYWxsIHNlY3Rpb24oKSBmaXJzdC4nKTtcbiAgICB9XG4gICAgdGhpcy5jdXJyZW50U2VjdGlvbi5jb250ZW50ICs9IGBTUUw6ICR7cXVlcnl9XFxuYDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5pc2ggY3VycmVudCBzZWN0aW9uXG4gICAqL1xuICBkb25lKCk6IHRoaXMge1xuICAgIGlmICh0aGlzLmN1cnJlbnRTZWN0aW9uKSB7XG4gICAgICB0aGlzLmN1cnJlbnRTZWN0aW9uLnRva2VuQ291bnQgPSB0aGlzLmVzdGltYXRlVG9rZW5zKHRoaXMuY3VycmVudFNlY3Rpb24uY29udGVudCk7XG4gICAgICB0aGlzLnNlY3Rpb25zLnB1c2godGhpcy5jdXJyZW50U2VjdGlvbik7XG4gICAgICB0aGlzLmN1cnJlbnRTZWN0aW9uID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlIGFuZCBidWlsZCBjb250ZXh0XG4gICAqL1xuICBleGVjdXRlKCk6IENvbnRleHRSZXN1bHQge1xuICAgIC8vIEZpbmlzaCBhbnkgcGVuZGluZyBzZWN0aW9uXG4gICAgaWYgKHRoaXMuY3VycmVudFNlY3Rpb24pIHtcbiAgICAgIHRoaXMuZG9uZSgpO1xuICAgIH1cblxuICAgIC8vIFNvcnQgc2VjdGlvbnMgYnkgcHJpb3JpdHkgKGxvd2VyID0gaGlnaGVyIHByaW9yaXR5KVxuICAgIGNvbnN0IHNvcnRlZFNlY3Rpb25zID0gWy4uLnRoaXMuc2VjdGlvbnNdLnNvcnQoKGEsIGIpID0+IGEucHJpb3JpdHkgLSBiLnByaW9yaXR5KTtcblxuICAgIC8vIENhbGN1bGF0ZSB0b3RhbCB0b2tlbnNcbiAgICBsZXQgdG90YWxUb2tlbnMgPSBzb3J0ZWRTZWN0aW9ucy5yZWR1Y2UoKHN1bSwgcykgPT4gc3VtICsgcy50b2tlbkNvdW50LCAwKTtcblxuICAgIC8vIFRydW5jYXRlIGlmIG5lZWRlZFxuICAgIGNvbnN0IHRydW5jYXRlZFNlY3Rpb25zOiBBcnJheTx7IG5hbWU6IHN0cmluZzsgdG9rZW5Db3VudDogbnVtYmVyOyB0cnVuY2F0ZWQ6IGJvb2xlYW4gfT4gPSBbXTtcbiAgICBjb25zdCBpbmNsdWRlZFNlY3Rpb25zOiBTZWN0aW9uW10gPSBbXTtcblxuICAgIGlmICh0b3RhbFRva2VucyA8PSB0aGlzLnRva2VuQnVkZ2V0KSB7XG4gICAgICAvLyBObyB0cnVuY2F0aW9uIG5lZWRlZFxuICAgICAgZm9yIChjb25zdCBzZWN0aW9uIG9mIHNvcnRlZFNlY3Rpb25zKSB7XG4gICAgICAgIGluY2x1ZGVkU2VjdGlvbnMucHVzaChzZWN0aW9uKTtcbiAgICAgICAgdHJ1bmNhdGVkU2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgbmFtZTogc2VjdGlvbi5uYW1lLFxuICAgICAgICAgIHRva2VuQ291bnQ6IHNlY3Rpb24udG9rZW5Db3VudCxcbiAgICAgICAgICB0cnVuY2F0ZWQ6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQXBwbHkgdHJ1bmNhdGlvbiBzdHJhdGVneVxuICAgICAgbGV0IHJlbWFpbmluZ0J1ZGdldCA9IHRoaXMudG9rZW5CdWRnZXQ7XG5cbiAgICAgIGlmICh0aGlzLnRydW5jYXRpb24gPT09IFRydW5jYXRpb25TdHJhdGVneS5UQUlMX0RST1ApIHtcbiAgICAgICAgLy8gSW5jbHVkZSBzZWN0aW9ucyBpbiBwcmlvcml0eSBvcmRlciB1bnRpbCBidWRnZXQgZXhoYXVzdGVkXG4gICAgICAgIGZvciAoY29uc3Qgc2VjdGlvbiBvZiBzb3J0ZWRTZWN0aW9ucykge1xuICAgICAgICAgIGlmIChzZWN0aW9uLnRva2VuQ291bnQgPD0gcmVtYWluaW5nQnVkZ2V0KSB7XG4gICAgICAgICAgICBpbmNsdWRlZFNlY3Rpb25zLnB1c2goc2VjdGlvbik7XG4gICAgICAgICAgICByZW1haW5pbmdCdWRnZXQgLT0gc2VjdGlvbi50b2tlbkNvdW50O1xuICAgICAgICAgICAgdHJ1bmNhdGVkU2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgICAgIG5hbWU6IHNlY3Rpb24ubmFtZSxcbiAgICAgICAgICAgICAgdG9rZW5Db3VudDogc2VjdGlvbi50b2tlbkNvdW50LFxuICAgICAgICAgICAgICB0cnVuY2F0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRydW5jYXRlZFNlY3Rpb25zLnB1c2goe1xuICAgICAgICAgICAgICBuYW1lOiBzZWN0aW9uLm5hbWUsXG4gICAgICAgICAgICAgIHRva2VuQ291bnQ6IDAsXG4gICAgICAgICAgICAgIHRydW5jYXRlZDogdHJ1ZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0aGlzLnRydW5jYXRpb24gPT09IFRydW5jYXRpb25TdHJhdGVneS5QUk9QT1JUSU9OQUwpIHtcbiAgICAgICAgLy8gUHJvcG9ydGlvbmFsbHkgcmVkdWNlIGFsbCBzZWN0aW9uc1xuICAgICAgICBjb25zdCByYXRpbyA9IHRoaXMudG9rZW5CdWRnZXQgLyB0b3RhbFRva2VucztcbiAgICAgICAgZm9yIChjb25zdCBzZWN0aW9uIG9mIHNvcnRlZFNlY3Rpb25zKSB7XG4gICAgICAgICAgY29uc3QgYWxsb2NhdGVkVG9rZW5zID0gTWF0aC5mbG9vcihzZWN0aW9uLnRva2VuQ291bnQgKiByYXRpbyk7XG4gICAgICAgICAgY29uc3QgdHJ1bmNhdGVkQ29udGVudCA9IHRoaXMudHJ1bmNhdGVUZXh0KHNlY3Rpb24uY29udGVudCwgYWxsb2NhdGVkVG9rZW5zKTtcbiAgICAgICAgICBpbmNsdWRlZFNlY3Rpb25zLnB1c2goe1xuICAgICAgICAgICAgLi4uc2VjdGlvbixcbiAgICAgICAgICAgIGNvbnRlbnQ6IHRydW5jYXRlZENvbnRlbnQsXG4gICAgICAgICAgICB0b2tlbkNvdW50OiBhbGxvY2F0ZWRUb2tlbnMsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdHJ1bmNhdGVkU2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgICBuYW1lOiBzZWN0aW9uLm5hbWUsXG4gICAgICAgICAgICB0b2tlbkNvdW50OiBhbGxvY2F0ZWRUb2tlbnMsXG4gICAgICAgICAgICB0cnVuY2F0ZWQ6IGFsbG9jYXRlZFRva2VucyA8IHNlY3Rpb24udG9rZW5Db3VudCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEJ1aWxkIGZpbmFsIGNvbnRleHQgYmFzZWQgb24gZm9ybWF0XG4gICAgbGV0IHRleHQgPSAnJztcbiAgICBsZXQgYWN0dWFsVG9rZW5zID0gMDtcblxuICAgIGlmICh0aGlzLmZvcm1hdCA9PT0gQ29udGV4dE91dHB1dEZvcm1hdC5UT09OKSB7XG4gICAgICB0ZXh0ID0gdGhpcy5idWlsZFRvb25Gb3JtYXQoaW5jbHVkZWRTZWN0aW9ucyk7XG4gICAgfSBlbHNlIGlmICh0aGlzLmZvcm1hdCA9PT0gQ29udGV4dE91dHB1dEZvcm1hdC5KU09OKSB7XG4gICAgICB0ZXh0ID0gdGhpcy5idWlsZEpzb25Gb3JtYXQoaW5jbHVkZWRTZWN0aW9ucyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRleHQgPSB0aGlzLmJ1aWxkTWFya2Rvd25Gb3JtYXQoaW5jbHVkZWRTZWN0aW9ucyk7XG4gICAgfVxuXG4gICAgYWN0dWFsVG9rZW5zID0gdGhpcy5lc3RpbWF0ZVRva2Vucyh0ZXh0KTtcblxuICAgIHJldHVybiB7XG4gICAgICB0ZXh0LFxuICAgICAgdG9rZW5Db3VudDogYWN0dWFsVG9rZW5zLFxuICAgICAgc2VjdGlvbnM6IHRydW5jYXRlZFNlY3Rpb25zLFxuICAgIH07XG4gIH1cblxuICAvLyBIZWxwZXIgbWV0aG9kc1xuICBwcml2YXRlIGVzdGltYXRlVG9rZW5zKHRleHQ6IHN0cmluZyk6IG51bWJlciB7XG4gICAgLy8gUm91Z2ggZXN0aW1hdGU6IH40IGNoYXJhY3RlcnMgcGVyIHRva2VuIGZvciBFbmdsaXNoXG4gICAgcmV0dXJuIE1hdGguY2VpbCh0ZXh0Lmxlbmd0aCAvIDQpO1xuICB9XG5cbiAgcHJpdmF0ZSB0cnVuY2F0ZVRleHQodGV4dDogc3RyaW5nLCBtYXhUb2tlbnM6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3QgbWF4Q2hhcnMgPSBtYXhUb2tlbnMgKiA0O1xuICAgIGlmICh0ZXh0Lmxlbmd0aCA8PSBtYXhDaGFycykge1xuICAgICAgcmV0dXJuIHRleHQ7XG4gICAgfVxuICAgIHJldHVybiB0ZXh0LnN1YnN0cmluZygwLCBtYXhDaGFycykgKyAnLi4uJztcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRUb29uRm9ybWF0KHNlY3Rpb25zOiBTZWN0aW9uW10pOiBzdHJpbmcge1xuICAgIGNvbnN0IGxpbmVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIFxuICAgIGZvciAoY29uc3Qgc2VjdGlvbiBvZiBzZWN0aW9ucykge1xuICAgICAgbGluZXMucHVzaChgWyR7c2VjdGlvbi5uYW1lfV1gKTtcbiAgICAgIGxpbmVzLnB1c2goc2VjdGlvbi5jb250ZW50KTtcbiAgICAgIGxpbmVzLnB1c2goJycpO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gbGluZXMuam9pbignXFxuJyk7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkSnNvbkZvcm1hdChzZWN0aW9uczogU2VjdGlvbltdKTogc3RyaW5nIHtcbiAgICBjb25zdCBvYmo6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICBcbiAgICBmb3IgKGNvbnN0IHNlY3Rpb24gb2Ygc2VjdGlvbnMpIHtcbiAgICAgIG9ialtzZWN0aW9uLm5hbWVdID0gc2VjdGlvbi5jb250ZW50O1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCAyKTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRNYXJrZG93bkZvcm1hdChzZWN0aW9uczogU2VjdGlvbltdKTogc3RyaW5nIHtcbiAgICBjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXTtcbiAgICBcbiAgICBmb3IgKGNvbnN0IHNlY3Rpb24gb2Ygc2VjdGlvbnMpIHtcbiAgICAgIGxpbmVzLnB1c2goYCMjICR7c2VjdGlvbi5uYW1lfWApO1xuICAgICAgbGluZXMucHVzaCgnJyk7XG4gICAgICBsaW5lcy5wdXNoKHNlY3Rpb24uY29udGVudCk7XG4gICAgICBsaW5lcy5wdXNoKCcnKTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIGxpbmVzLmpvaW4oJ1xcbicpO1xuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgY29udGV4dCBxdWVyeSBidWlsZGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDb250ZXh0QnVpbGRlcigpOiBDb250ZXh0UXVlcnlCdWlsZGVyIHtcbiAgcmV0dXJuIG5ldyBDb250ZXh0UXVlcnlCdWlsZGVyKCk7XG59XG4iXX0=